VirtualBox

source: vbox/trunk/src/VBox/Additions/WINNT/Graphics/Video/disp/wddm/VBoxDispD3D.cpp@ 62522

Last change on this file since 62522 was 62522, checked in by vboxsync, 9 years ago

(C) 2016

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 249.9 KB
Line 
1/* $Id: VBoxDispD3D.cpp 62522 2016-07-22 19:17:25Z vboxsync $ */
2
3/** @file
4 * VBoxVideo Display D3D User mode dll
5 */
6
7/*
8 * Copyright (C) 2011-2016 Oracle Corporation
9 *
10 * This file is part of VirtualBox Open Source Edition (OSE), as
11 * available from http://www.virtualbox.org. This file is free software;
12 * you can redistribute it and/or modify it under the terms of the GNU
13 * General Public License (GPL) as published by the Free Software
14 * Foundation, in version 2 as it comes in the "COPYING" file of the
15 * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
16 * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
17 */
18
19#define INITGUID
20
21#include <iprt/initterm.h>
22#include <iprt/log.h>
23#include <iprt/mem.h>
24
25#include <VBox/Log.h>
26
27#include <VBox/VBoxGuestLib.h>
28
29#include "VBoxDispD3DCmn.h"
30#include "VBoxDispD3D.h"
31#include <VBox/VBoxCrHgsmi.h>
32
33#include <Psapi.h>
34
35#ifdef VBOX_WDDMDISP_WITH_PROFILE
36
37volatile uint32_t g_u32VBoxDispProfileFunctionLoggerIndex = 0;
38
39/* the number of frames to collect data before doing dump/reset */
40#define VBOXDISPPROFILE_DDI_DUMP_FRAME_COUNT 0x20
41
42struct VBOXDISPPROFILE_GLOBAL {
43 VBoxDispProfileFpsCounter ProfileDdiFps;
44 VBoxDispProfileSet ProfileDdiFunc;
45} g_VBoxDispProfile;
46
47/* uncomment to enable particular logging */
48/* allows dumping fps + how much time is spent in ddi functions in comparison with the rest time */
49//# define VBOXDISPPROFILE_DDI_STATISTIC_LOGGER_ENABLE
50/* allows dumping time spent in each function and the number of calls made for any given function */
51# define VBOXDISPPROFILE_DDI_FUNCTION_LOGGER_ENABLE
52
53# ifdef VBOXDISPPROFILE_DDI_FUNCTION_LOGGER_ENABLE
54
55class VBoxDispProfileDevicePostProcess
56{
57public:
58 VBoxDispProfileDevicePostProcess(PVBOXWDDMDISP_DEVICE pDevice) :
59 m_pDevice(pDevice)
60 {}
61
62 void postProcess()
63 {
64 if (m_pDevice->pDevice9If)
65 m_pDevice->pAdapter->D3D.D3D.pfnVBoxWineExD3DDev9Finish((IDirect3DDevice9Ex *)m_pDevice->pDevice9If);
66 }
67private:
68 PVBOXWDDMDISP_DEVICE m_pDevice;
69};
70
71//static VBoxDispProfileSet g_VBoxDispProfileDDI("D3D_DDI");
72# define VBOXDISPPROFILE_DDI_FUNCTION_LOGGER_PROLOGUE_DEV(_pObj) VBOXDISPPROFILE_FUNCTION_LOGGER_DEFINE((_pObj)->ProfileDdiFunc, VBoxDispProfileDevicePostProcess, VBoxDispProfileDevicePostProcess(_pObj))
73# define VBOXDISPPROFILE_DDI_FUNCTION_LOGGER_PROLOGUE_BASE(_pObj) VBOXDISPPROFILE_FUNCTION_LOGGER_DEFINE((_pObj)->ProfileDdiFunc, VBoxDispProfileDummyPostProcess, VBoxDispProfileDummyPostProcess())
74# define VBOXDISPPROFILE_DDI_FUNCTION_LOGGER_DUMP(_pObj) do {\
75 (_pObj)->ProfileDdiFunc.dump(_pObj); \
76 } while (0)
77# define VBOXDISPPROFILE_DDI_FUNCTION_LOGGER_RESET(_pObj) do {\
78 (_pObj)->ProfileDdiFunc.resetEntries();\
79 } while (0)
80# define VBOXDISPPROFILE_DDI_FUNCTION_LOGGER_DISABLE_CURRENT() do {\
81 VBOXDISPPROFILE_FUNCTION_LOGGER_DISABLE_CURRENT();\
82 } while (0)
83
84# define VBOXDISPPROFILE_DDI_FUNCTION_LOGGER_LOG_AND_DISABLE_CURRENT() VBOXDISPPROFILE_FUNCTION_LOGGER_LOG_AND_DISABLE_CURRENT()
85
86# define VBOXDISPPROFILE_DDI_FUNCTION_LOGGER_REPORT_FRAME(_pObj) do { \
87 if (!((_pObj)->ProfileDdiFunc.reportIteration() % VBOXDISPPROFILE_DDI_DUMP_FRAME_COUNT) /*&& !VBOXVDBG_IS_DWM()*/) {\
88 VBOXDISPPROFILE_DDI_FUNCTION_LOGGER_DUMP(_pObj); \
89 VBOXDISPPROFILE_DDI_FUNCTION_LOGGER_RESET(_pObj); \
90 } \
91 } while (0)
92
93# else
94# define VBOXDISPPROFILE_DDI_FUNCTION_LOGGER_PROLOGUE_DEV(_pObj) do {} while(0)
95# define VBOXDISPPROFILE_DDI_FUNCTION_LOGGER_PROLOGUE_BASE(_pObj) do {} while(0)
96# define VBOXDISPPROFILE_DDI_FUNCTION_LOGGER_DUMP(_pObj) do {} while(0)
97# define VBOXDISPPROFILE_DDI_FUNCTION_LOGGER_RESET(_pObj) do {} while(0)
98# define VBOXDISPPROFILE_DDI_FUNCTION_LOGGER_DISABLE_CURRENT() do {} while (0)
99# define VBOXDISPPROFILE_DDI_FUNCTION_LOGGER_LOG_AND_DISABLE_CURRENT() do {} while (0)
100# define VBOXDISPPROFILE_DDI_FUNCTION_LOGGER_REPORT_FRAME(_pDev) do {} while (0)
101# endif
102
103# ifdef VBOXDISPPROFILE_DDI_STATISTIC_LOGGER_ENABLE
104//static VBoxDispProfileFpsCounter g_VBoxDispFpsDDI(64);
105# define VBOXDISPPROFILE_DDI_STATISTIC_LOGGER_PROLOGUE(_pObj) VBOXDISPPROFILE_STATISTIC_LOGGER_DEFINE(&(_pObj)->ProfileDdiFps, VBoxDispProfileDummyPostProcess, VBoxDispProfileDummyPostProcess())
106# define VBOXDISPPROFILE_DDI_STATISTIC_LOGGER_DISABLE_CURRENT() do {\
107 VBOXDISPPROFILE_STATISTIC_LOGGER_DISABLE_CURRENT();\
108 } while (0)
109
110# define VBOXDISPPROFILE_DDI_STATISTIC_LOGGER_DUMP(_pObj) do { \
111 double fps = (_pObj)->ProfileDdiFps.GetFps(); \
112 double cps = (_pObj)->ProfileDdiFps.GetCps(); \
113 double tup = (_pObj)->ProfileDdiFps.GetTimeProcPercent(); \
114 VBOXDISPPROFILE_DUMP(("[0x%p]: fps: %f, cps: %.1f, host %.1f%%", (_pObj), fps, cps, tup)); \
115 } while (0)
116
117# define VBOXDISPPROFILE_DDI_STATISTIC_LOGGER_REPORT_FRAME(_pObj) do { \
118 (_pObj)->ProfileDdiFps.ReportFrame(); \
119 if(!((_pObj)->ProfileDdiFps.GetNumFrames() % VBOXDISPPROFILE_DDI_DUMP_FRAME_COUNT)) \
120 { \
121 VBOXDISPPROFILE_DDI_STATISTIC_LOGGER_DUMP(_pObj); \
122 } \
123 } while (0)
124
125# define VBOXDISPPROFILE_DDI_STATISTIC_LOGGER_LOG_AND_DISABLE_CURRENT() VBOXDISPPROFILE_STATISTIC_LOGGER_LOG_AND_DISABLE_CURRENT()
126# else
127# define VBOXDISPPROFILE_DDI_STATISTIC_LOGGER_PROLOGUE(_pObj) do {} while(0)
128# define VBOXDISPPROFILE_DDI_STATISTIC_LOGGER_DISABLE_CURRENT() do {} while (0)
129# define VBOXDISPPROFILE_DDI_STATISTIC_LOGGER_LOG_AND_DISABLE_CURRENT() do {} while (0)
130# define VBOXDISPPROFILE_DDI_STATISTIC_LOGGER_REPORT_FRAME(_pDev) do {} while (0)
131# define VBOXDISPPROFILE_DDI_STATISTIC_LOGGER_DUMP(_pObj) do {} while (0)
132# endif
133
134# define VBOXDISPPROFILE_FUNCTION_DDI_PROLOGUE_DEV(_pObj) \
135 VBOXDISPPROFILE_DDI_FUNCTION_LOGGER_PROLOGUE_DEV(_pObj); \
136 VBOXDISPPROFILE_DDI_STATISTIC_LOGGER_PROLOGUE(_pObj);
137
138# define VBOXDISPPROFILE_FUNCTION_DDI_PROLOGUE_BASE(_pObj) \
139 VBOXDISPPROFILE_DDI_FUNCTION_LOGGER_PROLOGUE_BASE(_pObj); \
140 VBOXDISPPROFILE_DDI_STATISTIC_LOGGER_PROLOGUE(_pObj);
141
142# define VBOXDISPPROFILE_DDI_LOG_AND_DISABLE_CURRENT() \
143 VBOXDISPPROFILE_DDI_STATISTIC_LOGGER_LOG_AND_DISABLE_CURRENT(); \
144 VBOXDISPPROFILE_DDI_FUNCTION_LOGGER_LOG_AND_DISABLE_CURRENT();
145
146# define VBOXDISPPROFILE_DDI_REPORT_FRAME(_pDev) do {\
147 VBOXDISPPROFILE_DDI_LOG_AND_DISABLE_CURRENT(); \
148 VBOXDISPPROFILE_DDI_STATISTIC_LOGGER_REPORT_FRAME(_pDev); \
149 VBOXDISPPROFILE_DDI_FUNCTION_LOGGER_REPORT_FRAME(_pDev); \
150 } while (0)
151
152#if 0
153# define VBOXDISPPROFILE_DDI_REPORT_FLUSH(_pDev) do {\
154 VBOXDISPPROFILE_DDI_LOG_AND_DISABLE_CURRENT(); \
155 VBOXDISPPROFILE_DDI_STATISTIC_LOGGER_REPORT_FRAME(_pDev); \
156 VBOXDISPPROFILE_DDI_FUNCTION_LOGGER_REPORT_FRAME(_pDev); \
157 } while (0)
158#else
159# define VBOXDISPPROFILE_DDI_REPORT_FLUSH(_pDev) do {} while (0)
160#endif
161
162# define VBOXDISPPROFILE_DDI_INIT_CMN(_pObj, _name, _cEntries) do { \
163 (_pObj)->ProfileDdiFps = VBoxDispProfileFpsCounter(); \
164 (_pObj)->ProfileDdiFps.init(_cEntries); \
165 (_pObj)->ProfileDdiFunc = VBoxDispProfileSet(_name); \
166 } while (0)
167
168# define VBOXDISPPROFILE_DDI_TERM_CMN(_pObj) do { \
169 (_pObj)->ProfileDdiFps.term(); \
170 } while (0)
171
172# define VBOXDISPPROFILE_DDI_TERM(_pObj) do {\
173 VBOXDISPPROFILE_DDI_LOG_AND_DISABLE_CURRENT(); \
174 VBOXDISPPROFILE_DDI_FUNCTION_LOGGER_DUMP(_pObj); \
175 VBOXDISPPROFILE_DDI_FUNCTION_LOGGER_RESET(_pObj); \
176 VBOXDISPPROFILE_DDI_TERM_CMN(_pObj); \
177 } while (0)
178
179# define VBOXDISPPROFILE_DDI_PRINT(_m) VBOXDISPPROFILE_DUMP(_m)
180
181# define VBOXDISPPROFILE_DDI_INIT_GLBL() VBOXDISPPROFILE_DDI_INIT_CMN(&g_VBoxDispProfile, "DDI_Adp", 64)
182# define VBOXDISPPROFILE_DDI_INIT_ADP(_pAdp) VBOXDISPPROFILE_DDI_INIT_CMN(_pAdp, "DDI_Adp", 64)
183# define VBOXDISPPROFILE_DDI_INIT_DEV(_pDev) VBOXDISPPROFILE_DDI_INIT_CMN(_pDev, "DDI_Dev", 64)
184#else
185# define VBOXDISPPROFILE_FUNCTION_DDI_PROLOGUE_DEV(_pObj) do {} while (0)
186# define VBOXDISPPROFILE_FUNCTION_DDI_PROLOGUE_BASE(_pObj) do {} while (0)
187# define VBOXDISPPROFILE_DDI_REPORT_FRAME(_pDev) do {} while (0)
188# define VBOXDISPPROFILE_DDI_REPORT_FLUSH(_pDev) do {} while (0)
189# define VBOXDISPPROFILE_DDI_INIT_GLBL() do {} while (0)
190# define VBOXDISPPROFILE_DDI_INIT_ADP(_pAdp) do {} while (0)
191# define VBOXDISPPROFILE_DDI_INIT_DEV(_pDev) do {} while (0)
192# define VBOXDISPPROFILE_DDI_TERM(_pObj) do {} while (0)
193# define VBOXDISPPROFILE_DDI_PRINT(_m) do {} while (0)
194#endif
195
196/* debugging/profiling stuff could go here.
197 * NOP in release */
198#define VBOXDISP_DDI_PROLOGUE_CMN() \
199 VBOXVDBG_BREAK_DDI(); \
200 VBOXVDBG_CREATE_CHECK_SWAPCHAIN();
201
202#define VBOXDISP_DDI_PROLOGUE_DEV(_hDevice) \
203 VBOXDISP_DDI_PROLOGUE_CMN(); \
204 VBOXDISPPROFILE_FUNCTION_DDI_PROLOGUE_DEV((PVBOXWDDMDISP_DEVICE)(_hDevice));
205
206#define VBOXDISP_DDI_PROLOGUE_ADP(_hAdapter) \
207 VBOXDISP_DDI_PROLOGUE_CMN(); \
208 VBOXDISPPROFILE_FUNCTION_DDI_PROLOGUE_BASE((PVBOXWDDMDISP_ADAPTER)(_hAdapter));
209
210#define VBOXDISP_DDI_PROLOGUE_GLBL() \
211 VBOXDISP_DDI_PROLOGUE_CMN(); \
212 VBOXDISPPROFILE_FUNCTION_DDI_PROLOGUE_BASE(&g_VBoxDispProfile);
213
214#ifdef VBOXDISPMP_TEST
215HRESULT vboxDispMpTstStart();
216HRESULT vboxDispMpTstStop();
217#endif
218
219#define VBOXDISP_WITH_WINE_BB_WORKAROUND
220
221//#define VBOXWDDMOVERLAY_TEST
222
223static D3DDDIQUERYTYPE gVBoxQueryTypes[] = {
224 D3DDDIQUERYTYPE_EVENT,
225 D3DDDIQUERYTYPE_OCCLUSION
226};
227
228#define VBOX_QUERYTYPE_COUNT() RT_ELEMENTS(gVBoxQueryTypes)
229
230static CRITICAL_SECTION g_VBoxCritSect;
231
232void vboxDispLock()
233{
234 EnterCriticalSection(&g_VBoxCritSect);
235}
236
237void vboxDispUnlock()
238{
239 LeaveCriticalSection(&g_VBoxCritSect);
240}
241
242void vboxDispLockInit()
243{
244 InitializeCriticalSection(&g_VBoxCritSect);
245}
246
247
248#define VBOXDISPCRHGSMI_SCOPE_SET_DEV(_pDev) do {} while(0)
249#define VBOXDISPCRHGSMI_SCOPE_SET_GLOBAL() do {} while(0)
250
251
252typedef struct VBOXWDDMDISP_NSCADD
253{
254 VOID* pvCommandBuffer;
255 UINT cbCommandBuffer;
256 D3DDDI_ALLOCATIONLIST* pAllocationList;
257 UINT cAllocationList;
258 D3DDDI_PATCHLOCATIONLIST* pPatchLocationList;
259 UINT cPatchLocationList;
260 UINT cAllocations;
261}VBOXWDDMDISP_NSCADD, *PVBOXWDDMDISP_NSCADD;
262
263static HRESULT vboxWddmNSCAddAlloc(PVBOXWDDMDISP_NSCADD pData, PVBOXWDDMDISP_ALLOCATION pAlloc)
264{
265 HRESULT hr = S_OK;
266 Assert(pAlloc->fEverWritten || pAlloc->pRc->RcDesc.fFlags.SharedResource);
267 if (pData->cAllocationList && pData->cPatchLocationList && pData->cbCommandBuffer >= 4)
268 {
269 memset(pData->pAllocationList, 0, sizeof (D3DDDI_ALLOCATIONLIST));
270 pData->pAllocationList[0].hAllocation = pAlloc->hAllocation;
271 if (pAlloc->fDirtyWrite)
272 pData->pAllocationList[0].WriteOperation = 1;
273
274 memset(pData->pPatchLocationList, 0, sizeof (D3DDDI_PATCHLOCATIONLIST));
275 pData->pPatchLocationList[0].PatchOffset = pData->cAllocations*4;
276 pData->pPatchLocationList[0].AllocationIndex = pData->cAllocations;
277
278 pData->cbCommandBuffer -= 4;
279 --pData->cAllocationList;
280 --pData->cPatchLocationList;
281 ++pData->cAllocations;
282
283 ++pData->pAllocationList;
284 ++pData->pPatchLocationList;
285 pData->pvCommandBuffer = (VOID*)(((uint8_t*)pData->pvCommandBuffer) + 4);
286
287 }
288 else
289 hr = S_FALSE;
290
291 return hr;
292}
293
294static VOID vboxWddmDalRemove(PVBOXWDDMDISP_ALLOCATION pAlloc)
295{
296 RTListNodeRemove(&pAlloc->DirtyAllocListEntry);
297 pAlloc->fDirtyWrite = FALSE;
298}
299
300#ifdef DEBUG_misha
301typedef struct VBOXWDDM_DBG_ALLOC
302{
303 BOOLEAN fWrite;
304 PVBOXWDDMDISP_ALLOCATION pAlloc;
305} VBOXWDDM_DBG_ALLOC;
306#endif
307
308static HRESULT vboxWddmDalNotifyChange(PVBOXWDDMDISP_DEVICE pDevice)
309{
310 VBOXWDDMDISP_NSCADD NscAdd;
311 BOOL bReinitRenderData = TRUE;
312#ifdef DEBUG_misha
313 uint32_t cDbgAllocs = 0;
314 VBOXWDDM_DBG_ALLOC aDbgAllocs[128];
315#endif
316
317 do
318 {
319 if (bReinitRenderData)
320 {
321 NscAdd.pvCommandBuffer = pDevice->DefaultContext.ContextInfo.pCommandBuffer;
322 NscAdd.cbCommandBuffer = pDevice->DefaultContext.ContextInfo.CommandBufferSize;
323 NscAdd.pAllocationList = pDevice->DefaultContext.ContextInfo.pAllocationList;
324 NscAdd.cAllocationList = pDevice->DefaultContext.ContextInfo.AllocationListSize;
325 NscAdd.pPatchLocationList = pDevice->DefaultContext.ContextInfo.pPatchLocationList;
326 NscAdd.cPatchLocationList = pDevice->DefaultContext.ContextInfo.PatchLocationListSize;
327 NscAdd.cAllocations = 0;
328 Assert(NscAdd.cbCommandBuffer >= sizeof (VBOXWDDM_DMA_PRIVATEDATA_BASEHDR));
329 if (NscAdd.cbCommandBuffer < sizeof (VBOXWDDM_DMA_PRIVATEDATA_BASEHDR))
330 return E_FAIL;
331
332 PVBOXWDDM_DMA_PRIVATEDATA_BASEHDR pHdr = (PVBOXWDDM_DMA_PRIVATEDATA_BASEHDR)NscAdd.pvCommandBuffer;
333 pHdr->enmCmd = VBOXVDMACMD_TYPE_DMA_NOP;
334 NscAdd.pvCommandBuffer = (VOID*)(((uint8_t*)NscAdd.pvCommandBuffer) + sizeof (*pHdr));
335 NscAdd.cbCommandBuffer -= sizeof (*pHdr);
336 bReinitRenderData = FALSE;
337
338#ifdef DEBUG_misha
339 {
340 memset(aDbgAllocs, 0, sizeof (aDbgAllocs));
341 PVBOXWDDMDISP_ALLOCATION pAlloc;
342 uint32_t cAllocs = 0;
343 RTListForEach(&pDevice->DirtyAllocList, pAlloc, VBOXWDDMDISP_ALLOCATION, DirtyAllocListEntry)
344 {
345 Assert(pAlloc->fEverWritten || pAlloc->pRc->RcDesc.fFlags.SharedResource);
346 if (cAllocs < RT_ELEMENTS(aDbgAllocs))
347 {
348 aDbgAllocs[cAllocs].pAlloc = pAlloc;
349 aDbgAllocs[cAllocs].fWrite = pAlloc->fDirtyWrite;
350 ++cDbgAllocs;
351 }
352 ++cAllocs;
353 }
354 }
355#endif
356 }
357
358 PVBOXWDDMDISP_ALLOCATION pAlloc = RTListGetFirst(&pDevice->DirtyAllocList, VBOXWDDMDISP_ALLOCATION, DirtyAllocListEntry);
359 if (pAlloc)
360 {
361 HRESULT tmpHr = vboxWddmNSCAddAlloc(&NscAdd, pAlloc);
362#ifdef DEBUG_misha
363 Assert(tmpHr == S_OK);
364#endif
365 Assert(tmpHr == S_OK || tmpHr == S_FALSE);
366 if (tmpHr == S_OK)
367 {
368 vboxWddmDalRemove(pAlloc);
369 continue;
370 }
371 }
372 else
373 {
374 if (!NscAdd.cAllocations)
375 break;
376 }
377
378 D3DDDICB_RENDER RenderData = {0};
379 RenderData.CommandLength = pDevice->DefaultContext.ContextInfo.CommandBufferSize - NscAdd.cbCommandBuffer;
380 Assert(RenderData.CommandLength);
381 Assert(RenderData.CommandLength < UINT32_MAX/2);
382 RenderData.CommandOffset = 0;
383 RenderData.NumAllocations = pDevice->DefaultContext.ContextInfo.AllocationListSize - NscAdd.cAllocationList;
384 Assert(RenderData.NumAllocations == NscAdd.cAllocations);
385 RenderData.NumPatchLocations = pDevice->DefaultContext.ContextInfo.PatchLocationListSize - NscAdd.cPatchLocationList;
386 Assert(RenderData.NumPatchLocations == NscAdd.cAllocations);
387// RenderData.NewCommandBufferSize = sizeof (VBOXVDMACMD) + 4 * (100);
388// RenderData.NewAllocationListSize = 100;
389// RenderData.NewPatchLocationListSize = 100;
390 RenderData.hContext = pDevice->DefaultContext.ContextInfo.hContext;
391
392 HRESULT hr = pDevice->RtCallbacks.pfnRenderCb(pDevice->hDevice, &RenderData);
393 Assert(hr == S_OK);
394 if (hr == S_OK)
395 {
396 pDevice->DefaultContext.ContextInfo.CommandBufferSize = RenderData.NewCommandBufferSize;
397 pDevice->DefaultContext.ContextInfo.pCommandBuffer = RenderData.pNewCommandBuffer;
398 pDevice->DefaultContext.ContextInfo.AllocationListSize = RenderData.NewAllocationListSize;
399 pDevice->DefaultContext.ContextInfo.pAllocationList = RenderData.pNewAllocationList;
400 pDevice->DefaultContext.ContextInfo.PatchLocationListSize = RenderData.NewPatchLocationListSize;
401 pDevice->DefaultContext.ContextInfo.pPatchLocationList = RenderData.pNewPatchLocationList;
402 bReinitRenderData = TRUE;
403 }
404 else
405 break;
406 } while (1);
407
408 return S_OK;
409}
410
411#ifdef VBOXWDDMDISP_DAL_CHECK_LOCK
412static HRESULT vboxWddmDalCheckUnlock(PVBOXWDDMDISP_DEVICE pDevice, PVBOXWDDMDISP_ALLOCATION pAlloc)
413{
414 if (!pAlloc->fAllocLocked || pAlloc->LockInfo.cLocks)
415 return S_OK;
416
417 Assert(pAlloc->hAllocation);
418
419 D3DDDICB_UNLOCK Unlock;
420
421 Unlock.NumAllocations = 1;
422 Unlock.phAllocations = &pAlloc->hAllocation;
423
424 HRESULT hr = pDevice->RtCallbacks.pfnUnlockCb(pDevice->hDevice, &Unlock);
425 if(hr != S_OK)
426 {
427 WARN(("pfnUnlockCb failed, hr %#x", hr));
428 }
429
430 return hr;
431}
432
433static HRESULT vboxWddmDalCheckLock(PVBOXWDDMDISP_DEVICE pDevice, PVBOXWDDMDISP_ALLOCATION pAlloc, D3DDDI_LOCKFLAGS Flags)
434{
435 if (!pAlloc->hAllocation || pAlloc->fAllocLocked)
436 return S_OK;
437
438 HRESULT hr;
439
440 if (pAlloc->fDirtyWrite)
441 {
442 Assert(pAlloc->DirtyAllocListEntry.pNext);
443 hr = vboxWddmDalNotifyChange(pDevice);
444 if (hr == S_OK)
445 {
446 Assert(!pAlloc->DirtyAllocListEntry.pNext);
447 }
448 else
449 {
450 WARN(("vboxWddmDalNotifyChange failed %#x, ignoring", hr));
451 }
452 }
453
454 D3DDDICB_LOCK LockData;
455 LockData.hAllocation = pAlloc->hAllocation;
456 LockData.PrivateDriverData = 0;
457 LockData.NumPages = 0;
458 LockData.pPages = NULL;
459 LockData.pData = NULL; /* out */
460 LockData.Flags.Value = 0;
461 LockData.Flags.Discard = Flags.Discard;
462 LockData.Flags.DonotWait = Flags.DoNotWait;
463
464 hr = pDevice->RtCallbacks.pfnLockCb(pDevice->hDevice, &LockData);
465 if (hr == S_OK)
466 {
467 if (!Flags.ReadOnly)
468 pAlloc->fEverWritten = TRUE;
469 pAlloc->fAllocLocked = TRUE;
470 return S_OK;
471 }
472
473 WARN(("pfnLockCb failed %#x, Flags %#x", hr, Flags.Value));
474
475 return hr;
476}
477#endif
478
479static BOOLEAN vboxWddmDalCheckNotifyRemove(PVBOXWDDMDISP_DEVICE pDevice, PVBOXWDDMDISP_ALLOCATION pAlloc)
480{
481 if (pAlloc->DirtyAllocListEntry.pNext)
482 {
483 HRESULT hr = vboxWddmDalNotifyChange(pDevice);
484 if (hr == S_OK)
485 {
486 Assert(!pAlloc->DirtyAllocListEntry.pNext);
487 }
488 else
489 {
490 WARN(("vboxWddmDalNotifyChange failed %#x", hr));
491 if (pAlloc->DirtyAllocListEntry.pNext)
492 vboxWddmDalRemove(pAlloc);
493 }
494
495 return TRUE;
496 }
497
498 return FALSE;
499}
500
501static BOOLEAN vboxWddmDalCheckAdd(PVBOXWDDMDISP_DEVICE pDevice, PVBOXWDDMDISP_ALLOCATION pAlloc, BOOLEAN fWrite)
502{
503 if (!pAlloc->hAllocation /* only shared resources matter */
504 || (/*!fWrite &&*/ !pAlloc->hSharedHandle)
505 )
506 {
507 Assert(!pAlloc->DirtyAllocListEntry.pNext || pAlloc->hSharedHandle /*|| pAlloc->fDirtyWrite*/);
508
509 Assert(!pAlloc->hSharedHandle);
510
511 return FALSE;
512 }
513
514 Assert(fWrite || pAlloc->fEverWritten || pAlloc->pRc->RcDesc.fFlags.SharedResource);
515
516 if (!pAlloc->DirtyAllocListEntry.pNext)
517 {
518 Assert(!pAlloc->fDirtyWrite);
519 RTListAppend(&pDevice->DirtyAllocList, &pAlloc->DirtyAllocListEntry);
520 }
521 else
522 {
523 Assert(pAlloc->fDirtyWrite == fWrite || pAlloc->pRc->RcDesc.fFlags.SharedResource);
524 }
525 pAlloc->fDirtyWrite |= fWrite;
526 pAlloc->fEverWritten |= fWrite;
527
528 return TRUE;
529}
530
531DECLINLINE(BOOLEAN) vboxWddmDalCheckAddRc(PVBOXWDDMDISP_DEVICE pDevice, PVBOXWDDMDISP_RESOURCE pRc, BOOLEAN fWrite)
532{
533 BOOLEAN fChanged = FALSE;
534 for (UINT i = 0; i < pRc->cAllocations; ++i)
535 {
536 PVBOXWDDMDISP_ALLOCATION pDAlloc = &pRc->aAllocations[i];
537 fChanged |= vboxWddmDalCheckAdd(pDevice, pDAlloc, fWrite);
538 }
539 return fChanged;
540}
541
542static VOID vboxWddmDalCheckAddDepthStencil(PVBOXWDDMDISP_DEVICE pDevice)
543{
544 if (pDevice->pDepthStencilRc)
545 vboxWddmDalCheckAddRc(pDevice, pDevice->pDepthStencilRc, TRUE);
546}
547
548static VOID vboxWddmDalCheckAddRTs(PVBOXWDDMDISP_DEVICE pDevice)
549{
550 for (UINT i = 0; i < pDevice->cRTs; ++i)
551 {
552 if (pDevice->apRTs[i])
553 {
554 vboxWddmDalCheckAdd(pDevice, pDevice->apRTs[i], TRUE);
555 }
556 }
557}
558
559static VOID vboxWddmDalCheckAddSamplers(PVBOXWDDMDISP_DEVICE pDevice)
560{
561 for (UINT i = 0, iSampler = 0; iSampler < pDevice->cSamplerTextures; ++i)
562 {
563 Assert(i < RT_ELEMENTS(pDevice->aSamplerTextures));
564 if (!pDevice->aSamplerTextures[i]) continue;
565 vboxWddmDalCheckAddRc(pDevice, pDevice->aSamplerTextures[i], FALSE);
566 ++iSampler;
567 }
568}
569
570static VOID vboxWddmDalCheckAddOnDraw(PVBOXWDDMDISP_DEVICE pDevice)
571{
572 vboxWddmDalCheckAddRTs(pDevice);
573
574 vboxWddmDalCheckAddDepthStencil(pDevice);
575
576 vboxWddmDalCheckAddSamplers(pDevice);
577}
578
579static BOOLEAN vboxWddmDalIsEmpty(PVBOXWDDMDISP_DEVICE pDevice)
580{
581 return RTListIsEmpty(&pDevice->DirtyAllocList);
582}
583
584#ifdef VBOX_WITH_VIDEOHWACCEL
585
586static bool vboxVhwaIsEnabled(PVBOXWDDMDISP_ADAPTER pAdapter)
587{
588 for (uint32_t i = 0; i < pAdapter->cHeads; ++i)
589 {
590 if (pAdapter->aHeads[i].Vhwa.Settings.fFlags & VBOXVHWA_F_ENABLED)
591 return true;
592 }
593 return false;
594}
595
596static bool vboxVhwaHasCKeying(PVBOXWDDMDISP_ADAPTER pAdapter)
597{
598 for (uint32_t i = 0; i < pAdapter->cHeads; ++i)
599 {
600 VBOXVHWA_INFO* pSettings = &pAdapter->aHeads[i].Vhwa.Settings;
601 if ((pSettings->fFlags & VBOXVHWA_F_ENABLED)
602 && ((pSettings->fFlags & VBOXVHWA_F_CKEY_DST)
603 || (pSettings->fFlags & VBOXVHWA_F_CKEY_SRC))
604 )
605 return true;
606 }
607 return false;
608}
609
610#endif
611
612static void vboxResourceFree(PVBOXWDDMDISP_RESOURCE pRc)
613{
614 RTMemFree(pRc);
615}
616
617void vboxWddmResourceInit(PVBOXWDDMDISP_RESOURCE pRc, UINT cAllocs)
618{
619 memset(pRc, 0, RT_OFFSETOF(VBOXWDDMDISP_RESOURCE, aAllocations[cAllocs]));
620 pRc->cAllocations = cAllocs;
621 for (UINT i = 0; i < cAllocs; ++i)
622 {
623 pRc->aAllocations[i].iAlloc = i;
624 pRc->aAllocations[i].pRc = pRc;
625 }
626}
627
628static PVBOXWDDMDISP_RESOURCE vboxResourceAlloc(UINT cAllocs)
629{
630 PVBOXWDDMDISP_RESOURCE pRc = (PVBOXWDDMDISP_RESOURCE)RTMemAlloc(RT_OFFSETOF(VBOXWDDMDISP_RESOURCE, aAllocations[cAllocs]));
631 Assert(pRc);
632 if (pRc)
633 {
634 vboxWddmResourceInit(pRc, cAllocs);
635 return pRc;
636 }
637 return NULL;
638}
639
640#ifdef VBOXWDDMDISP_DEBUG
641static void vboxWddmDbgSynchMemCheck(PVBOXWDDMDISP_ALLOCATION pAlloc, D3DLOCKED_RECT *pLockInfo)
642{
643 Assert(pAlloc->SurfDesc.pitch);
644 Assert(pAlloc->pvMem);
645 int iRc = 0;
646
647 if (pAlloc->SurfDesc.pitch == pLockInfo->Pitch)
648 {
649 Assert(pAlloc->SurfDesc.cbSize);
650 iRc = memcmp(pLockInfo->pBits, pAlloc->pvMem, pAlloc->SurfDesc.cbSize);
651 Assert(!iRc);
652 }
653 else
654 {
655 uint8_t *pvSrc, *pvDst;
656 uint32_t srcPitch, dstPitch;
657 if (1)
658 {
659 pvSrc = (uint8_t *)pAlloc->pvMem;
660 pvDst = (uint8_t *)pLockInfo->pBits;
661 srcPitch = pAlloc->SurfDesc.pitch;
662 dstPitch = pLockInfo->Pitch;
663 }
664 else
665 {
666 pvDst = (uint8_t *)pAlloc->pvMem;
667 pvSrc = (uint8_t *)pLockInfo->pBits;
668 dstPitch = pAlloc->SurfDesc.pitch;
669 srcPitch = (uint32_t)pLockInfo->Pitch;
670 }
671
672 Assert(pAlloc->SurfDesc.pitch <= (UINT)pLockInfo->Pitch);
673 uint32_t pitch = RT_MIN(srcPitch, dstPitch);
674 Assert(pitch);
675 uint32_t cRows = vboxWddmCalcNumRows(0, pAlloc->SurfDesc.height, pAlloc->SurfDesc.format);
676 for (UINT j = 0; j < cRows; ++j)
677 {
678 iRc = memcmp(pvDst, pvSrc, pitch);
679 Assert(!iRc);
680 pvSrc += srcPitch;
681 pvDst += dstPitch;
682 }
683 }
684}
685
686static VOID vboxWddmDbgRcSynchMemCheck(PVBOXWDDMDISP_RESOURCE pRc)
687{
688 if (!pRc)
689 {
690 return;
691 }
692
693 if (pRc->RcDesc.enmPool != D3DDDIPOOL_SYSTEMMEM)
694 {
695 return;
696 }
697
698 for (UINT i = 0; i < pRc->cAllocations; ++i)
699 {
700 D3DLOCKED_RECT Rect;
701 HRESULT hr = VBoxD3DIfLockRect(pRc, i, &Rect, NULL, D3DLOCK_READONLY);
702 if (FAILED(hr))
703 {
704 WARN(("VBoxD3DIfLockRect failed, hr(0x%x)", hr));
705 return;
706 }
707
708 PVBOXWDDMDISP_ALLOCATION pAlloc = &pRc->aAllocations[i];
709 Assert(pAlloc->pvMem);
710
711 vboxWddmDbgSynchMemCheck(pAlloc, &Rect);
712
713 hr = VBoxD3DIfUnlockRect(pRc, i);
714 Assert(SUCCEEDED(hr));
715 }
716}
717#endif
718
719
720/******/
721static HRESULT vboxWddmRenderTargetSet(PVBOXWDDMDISP_DEVICE pDevice, UINT iRt, PVBOXWDDMDISP_ALLOCATION pAlloc, BOOL bOnSwapchainSynch);
722
723DECLINLINE(VOID) vboxWddmSwapchainInit(PVBOXWDDMDISP_SWAPCHAIN pSwapchain)
724{
725 RTLISTNODE ListEntry = pSwapchain->ListEntry;
726 memset(pSwapchain, 0, sizeof (VBOXWDDMDISP_SWAPCHAIN));
727 pSwapchain->ListEntry = ListEntry;
728 pSwapchain->iBB = VBOXWDDMDISP_INDEX_UNDEFINED;
729}
730
731static HRESULT vboxWddmSwapchainKmSynch(PVBOXWDDMDISP_DEVICE pDevice, PVBOXWDDMDISP_SWAPCHAIN pSwapchain)
732{
733 struct
734 {
735 VBOXDISPIFESCAPE_SWAPCHAININFO SwapchainInfo;
736 D3DKMT_HANDLE ahAllocs[VBOXWDDMDISP_MAX_SWAPCHAIN_SIZE];
737 } Buf;
738
739 memset(&Buf.SwapchainInfo, 0, sizeof (Buf.SwapchainInfo));
740 Buf.SwapchainInfo.EscapeHdr.escapeCode = VBOXESC_SWAPCHAININFO;
741 Buf.SwapchainInfo.SwapchainInfo.hSwapchainKm = pSwapchain->hSwapchainKm;
742 Buf.SwapchainInfo.SwapchainInfo.hSwapchainUm = (VBOXDISP_UMHANDLE)pSwapchain;
743 HRESULT hr = pDevice->pAdapter->D3D.D3D.pfnVBoxWineExD3DSwapchain9GetHostWinID(pSwapchain->pSwapChainIf, &Buf.SwapchainInfo.SwapchainInfo.winHostID);
744 if (FAILED(hr))
745 {
746 WARN(("pfnVBoxWineExD3DSwapchain9GetHostWinID failed, hr 0x%x", hr));
747 return hr;
748 }
749 Assert(Buf.SwapchainInfo.SwapchainInfo.winHostID);
750// Buf.SwapchainInfo.SwapchainInfo.Rect;
751// Buf.SwapchainInfo.SwapchainInfo.u32Reserved;
752 Buf.SwapchainInfo.SwapchainInfo.cAllocs = pSwapchain->cRTs;
753 UINT cAllocsKm = 0;
754 for (UINT i = 0; i < Buf.SwapchainInfo.SwapchainInfo.cAllocs; ++i)
755 {
756// Assert(pSwapchain->aRTs[i].pAlloc->hAllocation);
757 Buf.SwapchainInfo.SwapchainInfo.ahAllocs[i] = pSwapchain->aRTs[i].pAlloc->hAllocation;
758 if (Buf.SwapchainInfo.SwapchainInfo.ahAllocs[i])
759 ++cAllocsKm;
760 }
761
762 Assert(cAllocsKm == Buf.SwapchainInfo.SwapchainInfo.cAllocs || !cAllocsKm);
763 if (cAllocsKm == Buf.SwapchainInfo.SwapchainInfo.cAllocs)
764 {
765 D3DDDICB_ESCAPE DdiEscape = {0};
766 DdiEscape.hContext = pDevice->DefaultContext.ContextInfo.hContext;
767 DdiEscape.hDevice = pDevice->hDevice;
768 // DdiEscape.Flags.Value = 0;
769 DdiEscape.pPrivateDriverData = &Buf.SwapchainInfo;
770 DdiEscape.PrivateDriverDataSize = RT_OFFSETOF(VBOXDISPIFESCAPE_SWAPCHAININFO, SwapchainInfo.ahAllocs[Buf.SwapchainInfo.SwapchainInfo.cAllocs]);
771 hr = pDevice->RtCallbacks.pfnEscapeCb(pDevice->pAdapter->hAdapter, &DdiEscape);
772#ifdef DEBUG_misha
773 Assert(hr == S_OK);
774#endif
775 if (hr == S_OK)
776 {
777 pSwapchain->hSwapchainKm = Buf.SwapchainInfo.SwapchainInfo.hSwapchainKm;
778 }
779 }
780
781 return S_OK;
782}
783
784static HRESULT vboxWddmSwapchainKmDestroy(PVBOXWDDMDISP_DEVICE pDevice, PVBOXWDDMDISP_SWAPCHAIN pSwapchain)
785{
786 HRESULT hr = S_OK;
787 if (pSwapchain->hSwapchainKm)
788 {
789 /* submit empty swapchain to destroy the KM one */
790 UINT cOldRTc = pSwapchain->cRTs;
791 pSwapchain->cRTs = 0;
792 hr = vboxWddmSwapchainKmSynch(pDevice, pSwapchain);
793 Assert(hr == S_OK);
794 Assert(!pSwapchain->hSwapchainKm);
795 pSwapchain->cRTs = cOldRTc;
796 }
797 return hr;
798}
799static HRESULT vboxWddmSwapchainDestroyIf(PVBOXWDDMDISP_DEVICE pDevice, PVBOXWDDMDISP_SWAPCHAIN pSwapchain)
800{
801 if (pSwapchain->pSwapChainIf)
802 {
803#ifndef VBOXWDDM_WITH_VISIBLE_FB
804 if (pSwapchain->pRenderTargetFbCopy)
805 {
806 pSwapchain->pRenderTargetFbCopy->Release();
807 pSwapchain->pRenderTargetFbCopy = NULL;
808 pSwapchain->bRTFbCopyUpToDate = FALSE;
809 }
810#endif
811 pSwapchain->pSwapChainIf->Release();
812 Assert(pSwapchain->hWnd);
813 pSwapchain->pSwapChainIf = NULL;
814 pSwapchain->hWnd = NULL;
815 return S_OK;
816 }
817
818 Assert(!pSwapchain->hWnd);
819 return S_OK;
820}
821
822DECLINLINE(VOID) vboxWddmSwapchainClear(PVBOXWDDMDISP_DEVICE pDevice, PVBOXWDDMDISP_SWAPCHAIN pSwapchain)
823{
824 for (UINT i = 0; i < pSwapchain->cRTs; ++i)
825 {
826 pSwapchain->aRTs[i].pAlloc->pSwapchain = NULL;
827 }
828
829 /* first do a Km destroy to ensure all km->um region submissions are completed */
830 vboxWddmSwapchainKmDestroy(pDevice, pSwapchain);
831 vboxWddmSwapchainDestroyIf(pDevice, pSwapchain);
832 vboxWddmSwapchainInit(pSwapchain);
833}
834
835VOID vboxWddmSwapchainDestroy(PVBOXWDDMDISP_DEVICE pDevice, PVBOXWDDMDISP_SWAPCHAIN pSwapchain)
836{
837 vboxWddmSwapchainClear(pDevice, pSwapchain);
838 RTListNodeRemove(&pSwapchain->ListEntry);
839 RTMemFree(pSwapchain);
840}
841
842static VOID vboxWddmSwapchainDestroyAll(PVBOXWDDMDISP_DEVICE pDevice)
843{
844 PVBOXWDDMDISP_SWAPCHAIN pCur = RTListGetFirst(&pDevice->SwapchainList, VBOXWDDMDISP_SWAPCHAIN, ListEntry);
845 while (pCur)
846 {
847 PVBOXWDDMDISP_SWAPCHAIN pNext = NULL;
848 if (!RTListNodeIsLast(&pDevice->SwapchainList, &pCur->ListEntry))
849 {
850 pNext = RTListNodeGetNext(&pCur->ListEntry, VBOXWDDMDISP_SWAPCHAIN, ListEntry);
851 }
852
853 vboxWddmSwapchainDestroy(pDevice, pCur);
854
855 pCur = pNext;
856 }
857}
858
859static PVBOXWDDMDISP_SWAPCHAIN vboxWddmSwapchainAlloc(PVBOXWDDMDISP_DEVICE pDevice)
860{
861 PVBOXWDDMDISP_SWAPCHAIN pSwapchain = (PVBOXWDDMDISP_SWAPCHAIN)RTMemAllocZ(sizeof (VBOXWDDMDISP_SWAPCHAIN));
862 Assert(pSwapchain);
863 if (pSwapchain)
864 {
865 RTListAppend(&pDevice->SwapchainList, &pSwapchain->ListEntry);
866 vboxWddmSwapchainInit(pSwapchain);
867 return pSwapchain;
868 }
869 return NULL;
870}
871
872DECLINLINE(VOID) vboxWddmSwapchainRtInit(PVBOXWDDMDISP_SWAPCHAIN pSwapchain, PVBOXWDDMDISP_RENDERTGT pRt, PVBOXWDDMDISP_ALLOCATION pAlloc)
873{
874 pSwapchain->fFlags.bChanged = 1;
875 pRt->pAlloc = pAlloc;
876 pRt->cNumFlips = 0;
877 pRt->fFlags.Value = 0;
878 pRt->fFlags.bAdded = 1;
879}
880
881DECLINLINE(VOID) vboxWddmSwapchainBbAddTail(PVBOXWDDMDISP_SWAPCHAIN pSwapchain, PVBOXWDDMDISP_ALLOCATION pAlloc, BOOL bAssignAsBb)
882{
883 pAlloc->pSwapchain = pSwapchain;
884 VBOXWDDMDISP_SWAPCHAIN_FLAGS fOldFlags = pSwapchain->fFlags;
885 PVBOXWDDMDISP_RENDERTGT pRt = &pSwapchain->aRTs[pSwapchain->cRTs];
886 ++pSwapchain->cRTs;
887 vboxWddmSwapchainRtInit(pSwapchain, pRt, pAlloc);
888 if (pSwapchain->cRTs == 1)
889 {
890 Assert(pSwapchain->iBB == VBOXWDDMDISP_INDEX_UNDEFINED);
891 pSwapchain->iBB = 0;
892 }
893 else if (bAssignAsBb)
894 {
895 pSwapchain->iBB = pSwapchain->cRTs - 1;
896 }
897 else if (pSwapchain->cRTs == 2) /* the first one is a frontbuffer */
898 {
899 pSwapchain->iBB = 1;
900 }
901}
902
903DECLINLINE(VOID) vboxWddmSwapchainFlip(PVBOXWDDMDISP_SWAPCHAIN pSwapchain)
904{
905 pSwapchain->iBB = (pSwapchain->iBB + 1) % pSwapchain->cRTs;
906}
907
908DECLINLINE(UINT) vboxWddmSwapchainNumRTs(PVBOXWDDMDISP_SWAPCHAIN pSwapchain)
909{
910 return pSwapchain->cRTs;
911}
912
913
914DECLINLINE(PVBOXWDDMDISP_RENDERTGT) vboxWddmSwapchainRtForAlloc(PVBOXWDDMDISP_SWAPCHAIN pSwapchain, PVBOXWDDMDISP_ALLOCATION pAlloc)
915{
916 if (pAlloc->pSwapchain != pSwapchain)
917 return NULL;
918
919 for (UINT i = 0; i < pSwapchain->cRTs; ++i)
920 {
921 Assert(pSwapchain->aRTs[i].pAlloc->pSwapchain = pSwapchain);
922 if (pSwapchain->aRTs[i].pAlloc == pAlloc)
923 return &pSwapchain->aRTs[i];
924 }
925
926 /* should never happen */
927 Assert(0);
928 return NULL;
929}
930
931DECLINLINE(UINT) vboxWddmSwapchainRtIndex(PVBOXWDDMDISP_SWAPCHAIN pSwapchain, PVBOXWDDMDISP_RENDERTGT pRT)
932{
933 UINT offFirst = RT_OFFSETOF(VBOXWDDMDISP_SWAPCHAIN, aRTs);
934 UINT offRT = UINT((uintptr_t)pRT - (uintptr_t)pSwapchain);
935 Assert(offRT < sizeof (VBOXWDDMDISP_SWAPCHAIN));
936 Assert(offRT >= offFirst);
937 Assert(!((offRT - offFirst) % sizeof (VBOXWDDMDISP_RENDERTGT)));
938 UINT iRt = (offRT - offFirst) / sizeof (VBOXWDDMDISP_RENDERTGT);
939 Assert(iRt < pSwapchain->cRTs);
940 return iRt;
941}
942
943DECLINLINE(VOID) vboxWddmSwapchainRtRemove(PVBOXWDDMDISP_SWAPCHAIN pSwapchain, PVBOXWDDMDISP_RENDERTGT pRT)
944{
945 UINT iRt = vboxWddmSwapchainRtIndex(pSwapchain, pRT);
946 Assert(iRt < pSwapchain->cRTs);
947 pRT->pAlloc->pSwapchain = NULL;
948 for (UINT i = iRt; i < pSwapchain->cRTs - 1; ++i)
949 {
950 pSwapchain->aRTs[i] = pSwapchain->aRTs[i + 1];
951 }
952
953 --pSwapchain->cRTs;
954 if (pSwapchain->cRTs)
955 {
956 if (pSwapchain->iBB > iRt)
957 {
958 --pSwapchain->iBB;
959 }
960 else if (pSwapchain->iBB == iRt)
961 {
962 pSwapchain->iBB = 0;
963 }
964 }
965 else
966 {
967 pSwapchain->iBB = VBOXWDDMDISP_INDEX_UNDEFINED;
968 }
969 pSwapchain->fFlags.bChanged = TRUE;
970 pSwapchain->fFlags.bSwitchReportingPresent = TRUE;
971}
972
973DECLINLINE(VOID) vboxWddmSwapchainSetBb(PVBOXWDDMDISP_SWAPCHAIN pSwapchain, PVBOXWDDMDISP_RENDERTGT pRT)
974{
975 UINT iRt = vboxWddmSwapchainRtIndex(pSwapchain, pRT);
976 Assert(iRt < pSwapchain->cRTs);
977 pSwapchain->iBB = iRt;
978 pSwapchain->fFlags.bChanged = TRUE;
979}
980
981PVBOXWDDMDISP_SWAPCHAIN vboxWddmSwapchainFindCreate(PVBOXWDDMDISP_DEVICE pDevice, PVBOXWDDMDISP_ALLOCATION pBbAlloc, BOOL *pbNeedPresent)
982{
983 PVBOXWDDMDISP_SWAPCHAIN pSwapchain = pBbAlloc->pSwapchain;
984 if (pSwapchain)
985 {
986 /* check if this is what we expect */
987 PVBOXWDDMDISP_RENDERTGT pRt = vboxWddmSwapchainGetBb(pSwapchain);
988 if (pRt->pAlloc != pBbAlloc)
989 {
990 if (pBbAlloc == vboxWddmSwapchainGetFb(pSwapchain)->pAlloc)
991 {
992 /* the current front-buffer present is requested, don't do anything */
993 *pbNeedPresent = FALSE;
994 return pSwapchain;
995 }
996 /* bad, @todo: correct the swapchain by either removing the Rt and adding it to another swapchain
997 * or by removing the pBbAlloc out of it */
998//@todo: Assert(0);
999
1000 PVBOXWDDMDISP_RENDERTGT pRt = vboxWddmSwapchainRtForAlloc(pSwapchain, pBbAlloc);
1001 Assert(pRt);
1002 vboxWddmSwapchainSetBb(pSwapchain, pRt);
1003 pSwapchain->fFlags.bSwitchReportingPresent = TRUE;
1004 }
1005 }
1006
1007 *pbNeedPresent = TRUE;
1008
1009 if (!pSwapchain)
1010 {
1011 /* first search for the swapchain the alloc might be added to */
1012 PVBOXWDDMDISP_SWAPCHAIN pCur = RTListGetFirst(&pDevice->SwapchainList, VBOXWDDMDISP_SWAPCHAIN, ListEntry);
1013 while (pCur)
1014 {
1015 PVBOXWDDMDISP_RENDERTGT pRt = vboxWddmSwapchainGetBb(pCur);
1016 Assert(pRt);
1017 if (pRt->cNumFlips < 2
1018 && vboxWddmSwapchainRtIndex(pCur, pRt) == 0) /* <- in case we add a rt to the swapchain on present this would mean
1019 * that the last RT in the swapchain array is now a frontbuffer and
1020 * thus the aRTs[0] is a backbuffer */
1021 {
1022 if (pBbAlloc->SurfDesc.width == pRt->pAlloc->SurfDesc.width
1023 && pBbAlloc->SurfDesc.height == pRt->pAlloc->SurfDesc.height
1024 && vboxWddmFmtNoAlphaFormat(pBbAlloc->SurfDesc.format) == vboxWddmFmtNoAlphaFormat(pRt->pAlloc->SurfDesc.format)
1025 && pBbAlloc->SurfDesc.VidPnSourceId == pRt->pAlloc->SurfDesc.VidPnSourceId
1026 )
1027 {
1028 vboxWddmSwapchainBbAddTail(pCur, pBbAlloc, TRUE);
1029 pSwapchain = pCur;
1030 break;
1031 }
1032 }
1033 if (RTListNodeIsLast(&pDevice->SwapchainList, &pCur->ListEntry))
1034 break;
1035 pCur = RTListNodeGetNext(&pCur->ListEntry, VBOXWDDMDISP_SWAPCHAIN, ListEntry);
1036 }
1037
1038// if (!pSwapchain) need to create a new one (see below)
1039 }
1040
1041 if (!pSwapchain)
1042 {
1043 pSwapchain = vboxWddmSwapchainAlloc(pDevice);
1044 Assert(pSwapchain);
1045 if (pSwapchain)
1046 {
1047 vboxWddmSwapchainBbAddTail(pSwapchain, pBbAlloc, FALSE);
1048 }
1049 }
1050
1051 return pSwapchain;
1052}
1053
1054static PVBOXWDDMDISP_SWAPCHAIN vboxWddmSwapchainCreateForRc(PVBOXWDDMDISP_DEVICE pDevice, PVBOXWDDMDISP_RESOURCE pRc)
1055{
1056 PVBOXWDDMDISP_SWAPCHAIN pSwapchain = vboxWddmSwapchainAlloc(pDevice);
1057 Assert(pSwapchain);
1058 if (pSwapchain)
1059 {
1060 for (UINT i = 0; i < pRc->cAllocations; ++i)
1061 {
1062 vboxWddmSwapchainBbAddTail(pSwapchain, &pRc->aAllocations[i], FALSE);
1063 }
1064 return pSwapchain;
1065 }
1066 return NULL;
1067}
1068
1069DECLINLINE(UINT) vboxWddmSwapchainIdxBb2Rt(PVBOXWDDMDISP_SWAPCHAIN pSwapchain, uint32_t iBb)
1070{
1071 return iBb != (~0) ? (iBb + pSwapchain->iBB) % pSwapchain->cRTs : vboxWddmSwapchainIdxFb(pSwapchain);
1072}
1073
1074static HRESULT vboxWddmSwapchainRtSynch(PVBOXWDDMDISP_DEVICE pDevice, PVBOXWDDMDISP_SWAPCHAIN pSwapchain, uint32_t iBb)
1075{
1076 if (pSwapchain->fFlags.bRtReportingPresent)
1077 return S_OK;
1078
1079 IDirect3DSurface9 *pD3D9Surf;
1080#ifdef VBOXDISP_WITH_WINE_BB_WORKAROUND
1081 if (pSwapchain->cRTs == 1)
1082 {
1083 iBb = 0;
1084 }
1085#endif
1086 UINT iRt = vboxWddmSwapchainIdxBb2Rt(pSwapchain, iBb);
1087 Assert(iRt < pSwapchain->cRTs);
1088 PVBOXWDDMDISP_RENDERTGT pRt = &pSwapchain->aRTs[iRt];
1089 HRESULT hr = pSwapchain->pSwapChainIf->GetBackBuffer(iBb, D3DBACKBUFFER_TYPE_MONO, &pD3D9Surf);
1090 if (FAILED(hr))
1091 {
1092 WARN(("GetBackBuffer failed, hr (0x%x)",hr));
1093 return hr;
1094 }
1095
1096 PVBOXWDDMDISP_ALLOCATION pAlloc = pRt->pAlloc;
1097 Assert(pD3D9Surf);
1098 Assert(pAlloc->enmD3DIfType == VBOXDISP_D3DIFTYPE_SURFACE);
1099 if (pAlloc->pD3DIf)
1100 {
1101 if (pSwapchain->fFlags.bChanged)
1102 {
1103 IDirect3DSurface9 *pD3D9OldSurf = NULL;
1104 if (pAlloc->pD3DIf)
1105 {
1106 /* since this can be texture, need to do the VBoxD3DIfSurfGet magic */
1107 hr = VBoxD3DIfSurfGet(pAlloc->pRc, pAlloc->iAlloc, &pD3D9OldSurf);
1108 if (FAILED(hr))
1109 {
1110 WARN(("VBoxD3DIfSurfGet failed, hr (0x%x)",hr));
1111 pD3D9Surf->Release();
1112 return hr;
1113 }
1114 }
1115
1116 if (pD3D9OldSurf && pD3D9OldSurf != pD3D9Surf)
1117 {
1118 VOID *pvSwapchain = NULL;
1119 /* get the old surface's swapchain */
1120 HRESULT tmpHr = pD3D9OldSurf->GetContainer(IID_IDirect3DSwapChain9, &pvSwapchain);
1121 if (tmpHr == S_OK)
1122 {
1123 Assert(pvSwapchain);
1124 ((IDirect3DSwapChain9 *)pvSwapchain)->Release();
1125 }
1126 else
1127 {
1128 Assert(!pvSwapchain);
1129 }
1130
1131 if (pvSwapchain != pSwapchain->pSwapChainIf)
1132 {
1133 /* the swapchain has changed, copy data to the new surface */
1134#ifdef DEBUG_misha
1135 /* @todo: we can not generally update the render target directly, implement */
1136 Assert(iBb != (~0));
1137#endif
1138 VBOXVDBG_CHECK_SWAPCHAIN_SYNC(hr = pDevice->pDevice9If->StretchRect(pD3D9OldSurf, NULL, pD3D9Surf, NULL, D3DTEXF_NONE); Assert(hr == S_OK),
1139 pAlloc, pD3D9OldSurf, NULL, pAlloc, pD3D9Surf, NULL);
1140 }
1141 }
1142
1143 if (pD3D9OldSurf)
1144 {
1145 pD3D9OldSurf->Release();
1146 }
1147 }
1148 else
1149 {
1150 Assert(pAlloc->enmD3DIfType == VBOXDISP_D3DIFTYPE_SURFACE);
1151 }
1152 pAlloc->pD3DIf->Release();
1153 }
1154
1155 pAlloc->enmD3DIfType = VBOXDISP_D3DIFTYPE_SURFACE;
1156 pAlloc->pD3DIf = pD3D9Surf;
1157 pRt->fFlags.Value = 0;
1158
1159 if (pSwapchain->fFlags.bChanged)
1160 {
1161 for (UINT i = 0; i < pDevice->cRTs; ++i)
1162 {
1163 if (pDevice->apRTs[i] == pAlloc)
1164 {
1165 hr = vboxWddmRenderTargetSet(pDevice, i, pAlloc, TRUE);
1166 Assert(hr == S_OK);
1167 }
1168 }
1169 }
1170
1171#ifdef VBOXDISP_WITH_WINE_BB_WORKAROUND
1172 if (pSwapchain->cRTs == 1)
1173 {
1174 IDirect3DSurface9 *pD3D9Bb;
1175 /* only use direct bb if wine is able to handle quick blits bewteen surfaces in one swapchain,
1176 * this is FALSE by now :( */
1177# ifdef VBOX_WINE_WITH_FAST_INTERSWAPCHAIN_BLT
1178 /* here we sync the front-buffer with a backbuffer data*/
1179 pD3D9Bb = (IDirect3DSurface9*)vboxWddmSwapchainGetBb(pSwapchain)->pAlloc->pD3DIf;
1180 Assert(pD3D9Bb);
1181 pD3D9Bb->AddRef();
1182 /* we use backbuffer as a rt frontbuffer copy, so release the old one and assign the current bb */
1183 if (pSwapchain->pRenderTargetFbCopy)
1184 {
1185 pSwapchain->pRenderTargetFbCopy->Release();
1186 }
1187 pSwapchain->pRenderTargetFbCopy = pD3D9Bb;
1188# else
1189 pD3D9Bb = pSwapchain->pRenderTargetFbCopy;
1190# endif
1191 HRESULT tmpHr = pSwapchain->pSwapChainIf->GetFrontBufferData(pD3D9Bb);
1192 if (SUCCEEDED(tmpHr))
1193 {
1194 VBOXVDBG_DUMP_SYNC_RT(pD3D9Bb);
1195 pSwapchain->bRTFbCopyUpToDate = TRUE;
1196# ifndef VBOX_WINE_WITH_FAST_INTERSWAPCHAIN_BLT
1197 VBOXVDBG_CHECK_SWAPCHAIN_SYNC(tmpHr = pDevice->pDevice9If->StretchRect(pD3D9Bb, NULL, (IDirect3DSurface9*)vboxWddmSwapchainGetBb(pSwapchain)->pAlloc->pD3DIf, NULL, D3DTEXF_NONE); Assert(tmpHr == S_OK),
1198 pAlloc, pD3D9Bb, NULL, pAlloc, (IDirect3DSurface9*)vboxWddmSwapchainGetBb(pSwapchain)->pAlloc->pD3DIf, NULL);
1199
1200 if (FAILED(tmpHr))
1201 {
1202 WARN(("StretchRect failed, hr (0x%x)", tmpHr));
1203 }
1204# endif
1205 }
1206 else
1207 {
1208 WARN(("GetFrontBufferData failed, hr (0x%x)", tmpHr));
1209 }
1210 }
1211#endif
1212 return hr;
1213}
1214
1215static HRESULT vboxWddmSwapchainSynch(PVBOXWDDMDISP_DEVICE pDevice, PVBOXWDDMDISP_SWAPCHAIN pSwapchain)
1216{
1217 HRESULT hr = S_OK;
1218 for (int iBb = -1; iBb < int(pSwapchain->cRTs - 1); ++iBb)
1219 {
1220 hr = vboxWddmSwapchainRtSynch(pDevice, pSwapchain, (UINT)iBb);
1221 Assert(hr == S_OK);
1222 }
1223 if (pSwapchain->fFlags.bChanged)
1224 {
1225 hr = vboxWddmSwapchainKmSynch(pDevice, pSwapchain);
1226 if (hr == S_OK)
1227 {
1228 pSwapchain->fFlags.bChanged = 0;
1229 }
1230 }
1231 return hr;
1232}
1233
1234static VOID vboxWddmSwapchainFillPresentParams(PVBOXWDDMDISP_SWAPCHAIN pSwapchain, D3DPRESENT_PARAMETERS *pParams)
1235{
1236 Assert(pSwapchain->cRTs);
1237#ifdef DEBUG_misha
1238 /* not supported by wine properly, need to use offscreen render targets and blit their data to swapchain RTs*/
1239 Assert(pSwapchain->cRTs <= 2);
1240#endif
1241 PVBOXWDDMDISP_RENDERTGT pRt = vboxWddmSwapchainGetBb(pSwapchain);
1242 PVBOXWDDMDISP_RESOURCE pRc = pRt->pAlloc->pRc;
1243 VBoxD3DIfFillPresentParams(pParams, pRc, pSwapchain->cRTs);
1244}
1245
1246/* copy current rt data to offscreen render targets */
1247static HRESULT vboxWddmSwapchainSwtichOffscreenRt(PVBOXWDDMDISP_DEVICE pDevice, PVBOXWDDMDISP_SWAPCHAIN pSwapchain, BOOL fForceCreate)
1248{
1249 D3DPRESENT_PARAMETERS Params;
1250 vboxWddmSwapchainFillPresentParams(pSwapchain, &Params);
1251 IDirect3DSurface9* pD3D9OldFb = NULL;
1252 IDirect3DSwapChain9 * pOldIf = pSwapchain->pSwapChainIf;
1253 HRESULT hr = S_OK;
1254 if (pOldIf)
1255 {
1256 hr = pOldIf->GetBackBuffer(~0, D3DBACKBUFFER_TYPE_MONO, &pD3D9OldFb);
1257 if (FAILED(hr))
1258 {
1259 WARN(("GetBackBuffer ~0 failed, hr (%d)", hr));
1260 return hr;
1261 }
1262 /* just need a pointer to match */
1263 pD3D9OldFb->Release();
1264 }
1265
1266 for (UINT i = 0; i < pSwapchain->cRTs; ++i)
1267 {
1268 PVBOXWDDMDISP_RENDERTGT pRT = &pSwapchain->aRTs[i];
1269 if (pRT->pAlloc->enmD3DIfType != VBOXDISP_D3DIFTYPE_SURFACE)
1270 continue;
1271 BOOL fHasSurf = pRT->pAlloc->enmD3DIfType == VBOXDISP_D3DIFTYPE_SURFACE ?
1272 !!pRT->pAlloc->pD3DIf
1273 :
1274 !!pRT->pAlloc->pRc->aAllocations[0].pD3DIf;
1275 if (!fForceCreate && !fHasSurf)
1276 continue;
1277
1278 IDirect3DSurface9* pD3D9OldSurf = NULL;
1279 if (fHasSurf)
1280 {
1281 VOID *pvSwapchain = NULL;
1282 /* since this can be texture, need to do the VBoxD3DIfSurfGet magic */
1283 hr = VBoxD3DIfSurfGet(pRT->pAlloc->pRc, pRT->pAlloc->iAlloc, &pD3D9OldSurf);
1284 Assert(hr == S_OK);
1285 hr = pD3D9OldSurf->GetContainer(IID_IDirect3DSwapChain9, &pvSwapchain);
1286 if (hr == S_OK)
1287 {
1288 Assert(pvSwapchain);
1289 ((IDirect3DSwapChain9 *)pvSwapchain)->Release();
1290 }
1291 else
1292 {
1293 hr = S_OK;
1294 Assert(!pvSwapchain);
1295 }
1296
1297 if (!pvSwapchain) /* no swapchain, it is already offscreen */
1298 {
1299 pD3D9OldSurf->Release();
1300 continue;
1301 }
1302 Assert (pvSwapchain == pOldIf);
1303 }
1304
1305 IDirect3DSurface9* pD3D9NewSurf;
1306 IDirect3DDevice9 *pDevice9If = pDevice->pDevice9If;
1307 hr = pDevice9If->CreateRenderTarget(
1308 Params.BackBufferWidth, Params.BackBufferHeight,
1309 Params.BackBufferFormat,
1310 Params.MultiSampleType,
1311 Params.MultiSampleQuality,
1312 TRUE, /*bLockable*/
1313 &pD3D9NewSurf,
1314 pRT->pAlloc->hSharedHandle ? &pRT->pAlloc->hSharedHandle : NULL
1315 );
1316 Assert(hr == S_OK);
1317 if (FAILED(hr))
1318 {
1319 if (pD3D9OldSurf)
1320 pD3D9OldSurf->Release();
1321 break;
1322 }
1323
1324 if (pD3D9OldSurf)
1325 {
1326 if (pD3D9OldSurf != pD3D9OldFb)
1327 {
1328 VBOXVDBG_CHECK_SWAPCHAIN_SYNC(hr = pDevice9If->StretchRect(pD3D9OldSurf, NULL, pD3D9NewSurf, NULL, D3DTEXF_NONE); Assert(hr == S_OK),
1329 pRT->pAlloc, pD3D9OldSurf, NULL, pRT->pAlloc, pD3D9NewSurf, NULL);
1330 }
1331 else
1332 {
1333 hr = pOldIf->GetFrontBufferData(pD3D9NewSurf);
1334 Assert(hr == S_OK);
1335 }
1336 }
1337 if (FAILED(hr))
1338 {
1339 if (pD3D9OldSurf)
1340 pD3D9OldSurf->Release();
1341 break;
1342 }
1343
1344 Assert(pRT->pAlloc->enmD3DIfType == VBOXDISP_D3DIFTYPE_SURFACE);
1345
1346 if (pRT->pAlloc->pD3DIf)
1347 pRT->pAlloc->pD3DIf->Release();
1348 pRT->pAlloc->pD3DIf = pD3D9NewSurf;
1349 if (pD3D9OldSurf)
1350 pD3D9OldSurf->Release();
1351 }
1352
1353 return hr;
1354}
1355
1356
1357/**
1358 * @return old RtReportingPresent state
1359 */
1360static HRESULT vboxWddmSwapchainSwtichRtPresent(PVBOXWDDMDISP_DEVICE pDevice, PVBOXWDDMDISP_SWAPCHAIN pSwapchain)
1361{
1362 if (pSwapchain->fFlags.bRtReportingPresent)
1363 return S_OK;
1364
1365 HRESULT hr;
1366 pSwapchain->bRTFbCopyUpToDate = FALSE;
1367 if (pSwapchain->pRenderTargetFbCopy)
1368 {
1369 pSwapchain->pRenderTargetFbCopy->Release();
1370 pSwapchain->pRenderTargetFbCopy = NULL;
1371 }
1372
1373 hr = vboxWddmSwapchainSwtichOffscreenRt(pDevice, pSwapchain,
1374 TRUE /* force offscreen surface creation right away. This way we ensure the swapchain data
1375 * is always uptodate which allows making the vboxWddmSwapchainRtSynch behave as a nop */
1376 );
1377 Assert(hr == S_OK);
1378 if (FAILED(hr))
1379 return hr;
1380
1381 /* ensure we update device RTs to offscreen ones we just created */
1382 for (UINT i = 0; i < pDevice->cRTs; ++i)
1383 {
1384 PVBOXWDDMDISP_ALLOCATION pRtAlloc = pDevice->apRTs[i];
1385 if (!pRtAlloc) continue;
1386 for (UINT j = 0; j < pSwapchain->cRTs; ++j)
1387 {
1388 PVBOXWDDMDISP_ALLOCATION pAlloc = pSwapchain->aRTs[j].pAlloc;
1389 if (pRtAlloc == pAlloc)
1390 {
1391 hr = vboxWddmRenderTargetSet(pDevice, i, pAlloc, TRUE);
1392 Assert(hr == S_OK);
1393 }
1394 }
1395 }
1396
1397 pSwapchain->fFlags.bRtReportingPresent = TRUE;
1398 return hr;
1399}
1400
1401HRESULT vboxWddmSwapchainChkCreateIf(PVBOXWDDMDISP_DEVICE pDevice, PVBOXWDDMDISP_SWAPCHAIN pSwapchain)
1402{
1403 if (!pSwapchain->fFlags.bChanged && pSwapchain->pSwapChainIf)
1404 return S_OK;
1405 /* preserve the old one */
1406 IDirect3DSwapChain9 * pOldIf = pSwapchain->pSwapChainIf;
1407 HRESULT hr = S_OK;
1408 BOOL bReuseSwapchain = FALSE;
1409 BOOL fNeedRtPresentSwitch = FALSE;
1410
1411 if (pSwapchain->fFlags.bSwitchReportingPresent || pSwapchain->cRTs > VBOXWDDMDISP_MAX_DIRECT_RTS)
1412 {
1413 pSwapchain->fFlags.bSwitchReportingPresent = FALSE;
1414 /* indicae switch to Render Target Reporting Present mode is needed */
1415 fNeedRtPresentSwitch = TRUE;
1416// vboxWddmSwapchainSwtichRtPresent(pDevice, pSwapchain);
1417 }
1418 else
1419 {
1420 for (UINT i = 0; i < pSwapchain->cRTs; ++i)
1421 {
1422 if (pSwapchain->aRTs[i].pAlloc->enmD3DIfType != VBOXDISP_D3DIFTYPE_SURFACE
1423 && (pSwapchain->aRTs[i].pAlloc->enmD3DIfType != VBOXDISP_D3DIFTYPE_UNDEFINED
1424 || pSwapchain->aRTs[i].pAlloc->enmType != VBOXWDDM_ALLOC_TYPE_STD_SHAREDPRIMARYSURFACE
1425 ))
1426 {
1427 fNeedRtPresentSwitch = TRUE;
1428 break;
1429 }
1430 }
1431 }
1432
1433 /* check if we need to re-create the swapchain */
1434 if (pOldIf)
1435 {
1436 if (fNeedRtPresentSwitch)
1437 {
1438 /* the number of swapchain backbuffers does not matter */
1439 bReuseSwapchain = TRUE;
1440 }
1441 else
1442 {
1443 D3DPRESENT_PARAMETERS OldParams;
1444 hr = pOldIf->GetPresentParameters(&OldParams);
1445 Assert(hr == S_OK);
1446 if (hr == S_OK)
1447 {
1448 if (OldParams.BackBufferCount == pSwapchain->cRTs-1)
1449 {
1450 bReuseSwapchain = TRUE;
1451 }
1452 }
1453 }
1454 }
1455
1456 /* first create the new one */
1457 IDirect3DSwapChain9 * pNewIf;
1458 ///
1459 PVBOXWDDMDISP_ADAPTER pAdapter = pDevice->pAdapter;
1460 UINT cSurfs = pSwapchain->cRTs;
1461 IDirect3DDevice9 *pDevice9If = NULL;
1462 HWND hOldWnd = pSwapchain->hWnd;
1463 if (!bReuseSwapchain)
1464 {
1465 VBOXWINEEX_D3DPRESENT_PARAMETERS Params;
1466 vboxWddmSwapchainFillPresentParams(pSwapchain, &Params.Base);
1467 Params.pHgsmi = NULL;
1468
1469 if (hr == S_OK)
1470 {
1471 DWORD fFlags = D3DCREATE_HARDWARE_VERTEXPROCESSING;
1472
1473 Params.Base.hDeviceWindow = NULL;
1474 /* @todo: it seems there should be a way to detect this correctly since
1475 * our vboxWddmDDevSetDisplayMode will be called in case we are using full-screen */
1476 Params.Base.Windowed = TRUE;
1477 // params.EnableAutoDepthStencil = FALSE;
1478 // params.AutoDepthStencilFormat = D3DFMT_UNKNOWN;
1479 // params.Flags;
1480 // params.FullScreen_RefreshRateInHz;
1481 // params.FullScreen_PresentationInterval;
1482 if (!pDevice->pDevice9If)
1483 {
1484#ifdef VBOX_WITH_CRHGSMI
1485 Params.pHgsmi = &pDevice->Uhgsmi.BasePrivate.Base;
1486#else
1487 Params.pHgsmi = NULL;
1488#endif
1489 hr = pAdapter->D3D.pD3D9If->CreateDevice(D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, NULL, fFlags, &Params.Base, &pDevice9If);
1490 Assert(hr == S_OK);
1491 if (hr == S_OK)
1492 {
1493 Assert(Params.Base.hDeviceWindow);
1494 pSwapchain->hWnd = Params.Base.hDeviceWindow;
1495 pDevice->pDevice9If = pDevice9If;
1496 hr = pDevice9If->GetSwapChain(0, &pNewIf);
1497 Assert(hr == S_OK);
1498 if (hr == S_OK)
1499 {
1500 Assert(pNewIf);
1501 }
1502 else
1503 {
1504 pDevice9If->Release();
1505 }
1506 }
1507 }
1508 else
1509 {
1510 pDevice9If = pDevice->pDevice9If;
1511
1512 if (pOldIf)
1513 {
1514 /* need to copy data to offscreen rt to ensure the data is preserved
1515 * since the swapchain data may become invalid once we create a new swapchain
1516 * and pass the current swapchain's window to it
1517 * thus vboxWddmSwapchainSynch will not be able to do synchronization */
1518 hr = vboxWddmSwapchainSwtichOffscreenRt(pDevice, pSwapchain, FALSE);
1519 Assert(hr == S_OK);
1520 }
1521
1522 /* re-use swapchain window
1523 * this will invalidate the previusly used swapchain */
1524 Params.Base.hDeviceWindow = pSwapchain->hWnd;
1525
1526 hr = pDevice->pDevice9If->CreateAdditionalSwapChain(&Params.Base, &pNewIf);
1527 Assert(hr == S_OK);
1528 if (hr == S_OK)
1529 {
1530 Assert(Params.Base.hDeviceWindow);
1531 pSwapchain->hWnd = Params.Base.hDeviceWindow;
1532 Assert(pNewIf);
1533 }
1534 }
1535 }
1536 }
1537 else
1538 {
1539 Assert(pOldIf);
1540 Assert(hOldWnd);
1541 pNewIf = pOldIf;
1542 /* to ensure the swapchain is not deleted once we release the pOldIf */
1543 pNewIf->AddRef();
1544 }
1545
1546 if (FAILED(hr))
1547 return hr;
1548
1549 Assert(pNewIf);
1550 pSwapchain->pSwapChainIf = pNewIf;
1551
1552 if (fNeedRtPresentSwitch)
1553 {
1554 hr = vboxWddmSwapchainSwtichRtPresent(pDevice, pSwapchain);
1555 }
1556 else
1557 {
1558#ifndef VBOXWDDM_WITH_VISIBLE_FB
1559 if (!pSwapchain->fFlags.bRtReportingPresent)
1560 {
1561 pSwapchain->bRTFbCopyUpToDate = FALSE;
1562# if defined(VBOXDISP_WITH_WINE_BB_WORKAROUND) && defined(VBOX_WINE_WITH_FAST_INTERSWAPCHAIN_BLT)
1563 /* if wine is able to do fast fb->bb blits, we will use backbuffer directly,
1564 * this is NOT possible currently */
1565 if (pSwapchain->cRTs == 1)
1566 {
1567 /* we will assign it to wine backbuffer on a swapchain synch */
1568 if (pSwapchain->pRenderTargetFbCopy)
1569 {
1570 pSwapchain->pRenderTargetFbCopy->Release();
1571 pSwapchain->pRenderTargetFbCopy = NULL;
1572 }
1573 }
1574 else
1575# endif
1576 if (!pSwapchain->pRenderTargetFbCopy)
1577 {
1578 D3DPRESENT_PARAMETERS Params;
1579 vboxWddmSwapchainFillPresentParams(pSwapchain, &Params);
1580 IDirect3DSurface9* pD3D9Surf;
1581 hr = pDevice9If->CreateRenderTarget(
1582 Params.BackBufferWidth, Params.BackBufferHeight,
1583 Params.BackBufferFormat,
1584 Params.MultiSampleType,
1585 Params.MultiSampleQuality,
1586 TRUE, /*bLockable*/
1587 &pD3D9Surf,
1588 NULL /* HANDLE* pSharedHandle */
1589 );
1590 Assert(hr == S_OK);
1591 if (hr == S_OK)
1592 {
1593 Assert(pD3D9Surf);
1594 pSwapchain->pRenderTargetFbCopy = pD3D9Surf;
1595 }
1596 }
1597 }
1598#endif
1599 }
1600
1601 /* ignore any subsequen failures */
1602 Assert(hr == S_OK);
1603
1604
1605#ifdef DEBUG
1606 for (UINT i = 0; i < cSurfs; ++i)
1607 {
1608 PVBOXWDDMDISP_RENDERTGT pRt = &pSwapchain->aRTs[i];
1609 Assert(pRt->pAlloc->enmD3DIfType == VBOXDISP_D3DIFTYPE_SURFACE
1610 || pRt->pAlloc->enmD3DIfType == VBOXDISP_D3DIFTYPE_TEXTURE);
1611 Assert(pRt->pAlloc->pRc->RcDesc.enmPool != D3DDDIPOOL_SYSTEMMEM);
1612 }
1613#endif
1614
1615 hr = vboxWddmSwapchainSynch(pDevice, pSwapchain);
1616 Assert(hr == S_OK);
1617
1618 Assert(!pSwapchain->fFlags.bChanged);
1619 Assert(!pSwapchain->fFlags.bSwitchReportingPresent);
1620 if (pOldIf)
1621 {
1622 Assert(hOldWnd);
1623 pOldIf->Release();
1624 }
1625 else
1626 {
1627 Assert(!hOldWnd);
1628 }
1629 return S_OK;
1630}
1631
1632static HRESULT vboxWddmSwapchainCreateIfForRc(PVBOXWDDMDISP_DEVICE pDevice, PVBOXWDDMDISP_RESOURCE pRc, PVBOXWDDMDISP_SWAPCHAIN *ppSwapchain)
1633{
1634 PVBOXWDDMDISP_SWAPCHAIN pSwapchain = vboxWddmSwapchainCreateForRc(pDevice, pRc);
1635 Assert(pSwapchain);
1636 *ppSwapchain = NULL;
1637 if (pSwapchain)
1638 {
1639 HRESULT hr = vboxWddmSwapchainChkCreateIf(pDevice, pSwapchain);
1640 Assert(hr == S_OK);
1641 if (hr == S_OK)
1642 {
1643 *ppSwapchain = pSwapchain;
1644 }
1645 return hr;
1646 }
1647 return E_OUTOFMEMORY;
1648}
1649
1650static HRESULT vboxWddmSwapchainPresentPerform(PVBOXWDDMDISP_DEVICE pDevice, PVBOXWDDMDISP_SWAPCHAIN pSwapchain);
1651
1652static HRESULT vboxWddmSwapchainBbUpdate(PVBOXWDDMDISP_DEVICE pDevice, PVBOXWDDMDISP_SWAPCHAIN pSwapchain, PVBOXWDDMDISP_ALLOCATION pBbAlloc)
1653{
1654 Assert(!pSwapchain->fFlags.bRtReportingPresent);
1655 for (UINT i = 0; i < pSwapchain->cRTs; ++i)
1656 {
1657 PVBOXWDDMDISP_ALLOCATION pCurBb = vboxWddmSwapchainGetBb(pSwapchain)->pAlloc;
1658 if (pCurBb == pBbAlloc)
1659 return S_OK;
1660
1661 HRESULT hr = vboxWddmSwapchainPresentPerform(pDevice, pSwapchain);
1662 if (FAILED(hr))
1663 {
1664 WARN(("vboxWddmSwapchainPresentPerform failed, hr (0x%x)", hr));
1665 return hr;
1666 }
1667 }
1668
1669 AssertMsgFailed(("the given allocation not par of the swapchain\n"));
1670 return E_FAIL;
1671}
1672
1673/* get the surface for the specified allocation in the swapchain */
1674static HRESULT vboxWddmSwapchainSurfGet(PVBOXWDDMDISP_DEVICE pDevice, PVBOXWDDMDISP_SWAPCHAIN pSwapchain, PVBOXWDDMDISP_ALLOCATION pAlloc, IDirect3DSurface9 **ppSurf)
1675{
1676 Assert(pAlloc->pSwapchain == pSwapchain);
1677
1678#ifndef VBOXWDDM_WITH_VISIBLE_FB
1679 if (!pSwapchain->fFlags.bRtReportingPresent
1680 && vboxWddmSwapchainGetFb(pSwapchain)->pAlloc == pAlloc
1681# ifdef VBOXDISP_WITH_WINE_BB_WORKAROUND
1682
1683 && vboxWddmSwapchainNumRTs(pSwapchain) != 1 /* for swapchains w/o a backbuffer the alloc will contain the back-buffer actually */
1684 )
1685 {
1686 /* this is a front-buffer */
1687 Assert(vboxWddmSwapchainNumRTs(pSwapchain) > 1);
1688 IDirect3DSurface9 *pSurf = pSwapchain->pRenderTargetFbCopy;
1689 Assert(pSurf);
1690 pSurf->AddRef();
1691 if (!pSwapchain->bRTFbCopyUpToDate)
1692 {
1693 HRESULT hr = pSwapchain->pSwapChainIf->GetFrontBufferData(pSurf);
1694 if (FAILED(hr))
1695 {
1696 WARN(("GetFrontBufferData failed, hr (0x%x)", hr));
1697 pSurf->Release();
1698 return hr;
1699 }
1700 pSwapchain->bRTFbCopyUpToDate = TRUE;
1701 }
1702
1703 *ppSurf = pSurf;
1704 return S_OK;
1705 }
1706# endif
1707#endif
1708
1709 /* if this is not a front-buffer - just return the surface associated with the allocation */
1710 return VBoxD3DIfSurfGet(pAlloc->pRc, pAlloc->iAlloc, ppSurf);
1711}
1712
1713static HRESULT vboxWddmSwapchainRtSurfGet(PVBOXWDDMDISP_DEVICE pDevice, PVBOXWDDMDISP_SWAPCHAIN pSwapchain, UINT iRt, PVBOXWDDMDISP_ALLOCATION pAlloc, BOOL bOnSwapchainSynch, IDirect3DSurface9 **ppSurf)
1714{
1715 Assert(pAlloc->pSwapchain == pSwapchain);
1716 HRESULT hr = S_OK;
1717
1718 /* do the necessary swapchain synchronization first,
1719 * not needed on swapchain synch since it is done already and we're called here just to set RTs */
1720 if (!bOnSwapchainSynch)
1721 {
1722
1723 if (!pSwapchain->fFlags.bRtReportingPresent)
1724 {
1725 /* iRt != 0 is untested here !! */
1726 Assert(iRt == 0);
1727 if (iRt == 0)
1728 {
1729 hr = vboxWddmSwapchainBbUpdate(pDevice, pSwapchain, pAlloc);
1730 if (FAILED(hr))
1731 {
1732 WARN(("vboxWddmSwapchainBbUpdate failed, hr(0x%x)",hr));
1733 return hr;
1734 }
1735 }
1736 }
1737
1738//@todo: Assert(!pSwapchain->fFlags.bChanged);
1739 Assert(pSwapchain->pSwapChainIf);
1740 hr = vboxWddmSwapchainChkCreateIf(pDevice, pSwapchain);
1741 if (FAILED(hr))
1742 {
1743 WARN(("vboxWddmSwapchainChkCreateIf failed, hr(0x%x)",hr));
1744 return hr;
1745 }
1746 }
1747
1748//@todo: Assert(vboxWddmSwapchainGetBb(pSwapchain)->pAlloc == pAlloc || iRt != 0);
1749 IDirect3DSurface9 *pSurf;
1750 hr = vboxWddmSwapchainSurfGet(pDevice, pSwapchain, pAlloc, &pSurf);
1751 if (FAILED(hr))
1752 {
1753 WARN(("vboxWddmSwapchainSurfGet failed, hr(0x%x)", hr));
1754 return hr;
1755 }
1756
1757 *ppSurf = pSurf;
1758 return S_OK;
1759
1760}
1761
1762static HRESULT vboxWddmSwapchainPresentPerform(PVBOXWDDMDISP_DEVICE pDevice, PVBOXWDDMDISP_SWAPCHAIN pSwapchain)
1763{
1764 HRESULT hr;
1765
1766 VBOXVDBG_DUMP_PRESENT_ENTER(pDevice, pSwapchain);
1767
1768 if (!pSwapchain->fFlags.bRtReportingPresent)
1769 {
1770 hr = pSwapchain->pSwapChainIf->Present(NULL, NULL, NULL, NULL, 0);
1771 Assert(hr == S_OK);
1772 if (FAILED(hr))
1773 return hr;
1774 }
1775 else
1776 {
1777 PVBOXWDDMDISP_ALLOCATION pCurBb = vboxWddmSwapchainGetBb(pSwapchain)->pAlloc;
1778 IDirect3DSurface9 *pSurf;
1779 hr = vboxWddmSwapchainSurfGet(pDevice, pSwapchain, pCurBb, &pSurf);
1780 Assert(hr == S_OK);
1781 if (FAILED(hr))
1782 return hr;
1783 hr = pDevice->pAdapter->D3D.D3D.pfnVBoxWineExD3DSwapchain9Present(pSwapchain->pSwapChainIf, pSurf);
1784 Assert(hr == S_OK);
1785 pSurf->Release();
1786 if (FAILED(hr))
1787 return hr;
1788 }
1789
1790 VBOXVDBG_DUMP_PRESENT_LEAVE(pDevice, pSwapchain);
1791
1792 pSwapchain->bRTFbCopyUpToDate = FALSE;
1793 vboxWddmSwapchainFlip(pSwapchain);
1794 Assert(!pSwapchain->fFlags.bChanged);
1795 Assert(!pSwapchain->fFlags.bSwitchReportingPresent);
1796 hr = vboxWddmSwapchainSynch(pDevice, pSwapchain);
1797 Assert(hr == S_OK);
1798 return hr;
1799}
1800
1801static HRESULT vboxWddmSwapchainPresent(PVBOXWDDMDISP_DEVICE pDevice, PVBOXWDDMDISP_ALLOCATION pBbAlloc)
1802{
1803 /* we currently *assume* that presenting shared resource is only possible when 3d app is rendering with composited desktop on,
1804 * no need to do anything else since dwm will present everything for us */
1805 if (pBbAlloc->hSharedHandle)
1806 {
1807 VBOXVDBG_ASSERT_IS_DWM(FALSE);
1808
1809 HRESULT hr = pDevice->pAdapter->D3D.D3D.pfnVBoxWineExD3DDev9Flush((IDirect3DDevice9Ex*)pDevice->pDevice9If);
1810 Assert(hr == S_OK);
1811
1812 vboxWddmDalNotifyChange(pDevice);
1813
1814 return S_OK;
1815 }
1816
1817 VBOXVDBG_ASSERT_IS_DWM(TRUE);
1818
1819 BOOL bNeedPresent;
1820 PVBOXWDDMDISP_SWAPCHAIN pSwapchain = vboxWddmSwapchainFindCreate(pDevice, pBbAlloc, &bNeedPresent);
1821 Assert(pSwapchain);
1822 if (!bNeedPresent)
1823 return S_OK;
1824 if (pSwapchain)
1825 {
1826 HRESULT hr = vboxWddmSwapchainChkCreateIf(pDevice, pSwapchain);
1827 Assert(hr == S_OK);
1828 if (hr == S_OK)
1829 {
1830 hr = vboxWddmSwapchainPresentPerform(pDevice, pSwapchain);
1831 Assert(hr == S_OK);
1832 }
1833 return hr;
1834 }
1835 return E_OUTOFMEMORY;
1836}
1837
1838#if 0 //def DEBUG
1839static void vboxWddmDbgRenderTargetUpdateCheckSurface(PVBOXWDDMDISP_DEVICE pDevice, PVBOXWDDMDISP_ALLOCATION pAlloc, uint32_t iBBuf)
1840{
1841 IDirect3DSurface9 *pD3D9Surf;
1842 Assert(pAlloc->enmD3DIfType == VBOXDISP_D3DIFTYPE_SURFACE);
1843 IDirect3DDevice9 * pDevice9If = pDevice->aScreens[pDevice->iPrimaryScreen].pDevice9If;
1844 HRESULT hr = pDevice9If->GetBackBuffer(0 /*UINT iSwapChain*/,
1845 iBBuf, D3DBACKBUFFER_TYPE_MONO, &pD3D9Surf);
1846 Assert(hr == S_OK);
1847 if (hr == S_OK)
1848 {
1849 Assert(pD3D9Surf);
1850 Assert(pD3D9Surf == pAlloc->pD3DIf);
1851 pD3D9Surf->Release();
1852 }
1853}
1854
1855static void vboxWddmDbgRenderTargetCheck(PVBOXWDDMDISP_DEVICE pDevice, PVBOXWDDMDISP_RESOURCE pRc, uint32_t iNewRTFB)
1856{
1857 PVBOXWDDMDISP_ALLOCATION pAlloc;
1858 UINT iBBuf = 0;
1859 Assert(iNewRTFB < pRc->cAllocations);
1860
1861 for (UINT i = 1; i < pRc->cAllocations; ++i, ++iBBuf)
1862 {
1863 UINT iAlloc = (iNewRTFB + i) % pRc->cAllocations;
1864 Assert(iAlloc != iNewRTFB);
1865 pAlloc = &pRc->aAllocations[iAlloc];
1866 vboxWddmDbgRenderTargetUpdateCheckSurface(pDevice, pAlloc, iBBuf);
1867 }
1868
1869 pAlloc = &pRc->aAllocations[iNewRTFB];
1870#ifdef VBOXWDDM_WITH_VISIBLE_FB
1871 vboxWddmDbgRenderTargetUpdateCheckSurface(pDevice, pAlloc, ~0UL /* <- for the frontbuffer */);
1872#else
1873 Assert((!pAlloc->pD3DIf) == (pRc->cAllocations > 1));
1874#endif
1875
1876 for (UINT i = 0; i < pRc->cAllocations; ++i)
1877 {
1878 pAlloc = &pRc->aAllocations[i];
1879 if (iNewRTFB == i)
1880 {
1881 Assert((!pAlloc->pD3DIf) == (pRc->cAllocations > 1));
1882 }
1883
1884 for (UINT j = i+1; j < pRc->cAllocations; ++j)
1885 {
1886 PVBOXWDDMDISP_ALLOCATION pAllocJ = &pRc->aAllocations[j];
1887 Assert(pAlloc->pD3DIf != pAllocJ->pD3DIf);
1888 }
1889 }
1890}
1891
1892# define VBOXVDBG_RTGT_STATECHECK(_pDev) (vboxWddmDbgRenderTargetCheck((_pDev), (_pDev)->aScreens[(_pDev)->iPrimaryScreen].pRenderTargetRc, (_pDev)->aScreens[(_pDev)->iPrimaryScreen].iRenderTargetFrontBuf))
1893#else
1894# define VBOXVDBG_RTGT_STATECHECK(_pDev) do{}while(0)
1895#endif
1896
1897/******/
1898
1899static HRESULT vboxWddmRenderTargetSet(PVBOXWDDMDISP_DEVICE pDevice, UINT iRt, PVBOXWDDMDISP_ALLOCATION pAlloc, BOOL bOnSwapchainSynch)
1900{
1901 IDirect3DDevice9 * pDevice9If = VBOXDISP_D3DEV(pDevice);
1902 HRESULT hr = S_OK;
1903 IDirect3DSurface9 *pD3D9Surf = NULL;
1904 if (pAlloc)
1905 {
1906 PVBOXWDDMDISP_SWAPCHAIN pSwapchain = vboxWddmSwapchainForAlloc(pAlloc);
1907 if (pSwapchain)
1908 {
1909 hr = vboxWddmSwapchainRtSurfGet(pDevice, pSwapchain, iRt, pAlloc, bOnSwapchainSynch, &pD3D9Surf);
1910 if (FAILED(hr))
1911 {
1912 WARN(("vboxWddmSwapchainRtSurfGet failed, hr(0x%x)",hr));
1913 return hr;
1914 }
1915 }
1916 else
1917 {
1918 hr = VBoxD3DIfSurfGet(pAlloc->pRc, pAlloc->iAlloc, &pD3D9Surf);
1919 if (FAILED(hr))
1920 {
1921 WARN(("VBoxD3DIfSurfGet failed, hr(0x%x)",hr));
1922 return hr;
1923 }
1924 }
1925
1926 Assert(pD3D9Surf);
1927 }
1928
1929 hr = pDevice9If->SetRenderTarget(iRt, pD3D9Surf);
1930 if (hr == S_OK)
1931 {
1932 Assert(iRt < pDevice->cRTs);
1933 pDevice->apRTs[iRt] = pAlloc;
1934 }
1935 else
1936 {
1937 /* @todo This is workaround for wine 1 render target. */
1938 if (!pAlloc)
1939 {
1940 pDevice->apRTs[iRt] = NULL;
1941 hr = S_OK;
1942 }
1943 else
1944 {
1945 AssertFailed();
1946 }
1947 }
1948
1949 if (pD3D9Surf)
1950 {
1951 pD3D9Surf->Release();
1952 }
1953
1954 return hr;
1955}
1956
1957/**
1958 * DLL entry point.
1959 */
1960BOOL WINAPI DllMain(HINSTANCE hInstance,
1961 DWORD dwReason,
1962 LPVOID lpReserved)
1963{
1964 switch (dwReason)
1965 {
1966 case DLL_PROCESS_ATTACH:
1967 {
1968 vboxDispLockInit();
1969
1970 vboxVDbgPrint(("VBoxDispD3D: DLL loaded.\n"));
1971#ifdef VBOXWDDMDISP_DEBUG_VEHANDLER
1972 vboxVDbgVEHandlerRegister();
1973#endif
1974 int rc = RTR3InitDll(RTR3INIT_FLAGS_UNOBTRUSIVE);
1975 AssertRC(rc);
1976 if (RT_SUCCESS(rc))
1977 {
1978// rc = VbglR3Init();
1979// AssertRC(rc);
1980// if (RT_SUCCESS(rc))
1981 {
1982 HRESULT hr = vboxDispCmInit();
1983 Assert(hr == S_OK);
1984 if (hr == S_OK)
1985 {
1986 VBoxDispD3DGlobalInit();
1987 vboxVDbgPrint(("VBoxDispD3D: DLL loaded OK\n"));
1988 return TRUE;
1989 }
1990// VbglR3Term();
1991 }
1992 }
1993
1994#ifdef VBOXWDDMDISP_DEBUG_VEHANDLER
1995 vboxVDbgVEHandlerUnregister();
1996#endif
1997 break;
1998 }
1999
2000 case DLL_PROCESS_DETACH:
2001 {
2002#ifdef VBOXWDDMDISP_DEBUG_VEHANDLER
2003 vboxVDbgVEHandlerUnregister();
2004#endif
2005 HRESULT hr = vboxDispCmTerm();
2006 Assert(hr == S_OK);
2007 if (hr == S_OK)
2008 {
2009// VbglR3Term();
2010 /// @todo RTR3Term();
2011 VBoxDispD3DGlobalTerm();
2012 return TRUE;
2013 }
2014
2015 break;
2016 }
2017
2018 default:
2019 return TRUE;
2020 }
2021 return FALSE;
2022}
2023
2024static HRESULT APIENTRY vboxWddmDispGetCaps (HANDLE hAdapter, CONST D3DDDIARG_GETCAPS* pData)
2025{
2026 VBOXDISP_DDI_PROLOGUE_ADP(hAdapter);
2027
2028 vboxVDbgPrint(("==> "__FUNCTION__", hAdapter(0x%p), caps type(%d)\n", hAdapter, pData->Type));
2029
2030 VBOXDISPCRHGSMI_SCOPE_SET_GLOBAL();
2031
2032 HRESULT hr = S_OK;
2033 PVBOXWDDMDISP_ADAPTER pAdapter = (PVBOXWDDMDISP_ADAPTER)hAdapter;
2034
2035 switch (pData->Type)
2036 {
2037 case D3DDDICAPS_DDRAW:
2038 {
2039 Assert(!VBOXDISPMODE_IS_3D(pAdapter));
2040 Assert(pData->DataSize == sizeof (DDRAW_CAPS));
2041 if (pData->DataSize >= sizeof (DDRAW_CAPS))
2042 {
2043 memset(pData->pData, 0, sizeof (DDRAW_CAPS));
2044#ifdef VBOX_WITH_VIDEOHWACCEL
2045 if (!VBOXDISPMODE_IS_3D(pAdapter))
2046 {
2047 if (vboxVhwaHasCKeying(pAdapter))
2048 {
2049 DDRAW_CAPS *pCaps = (DDRAW_CAPS*)pData->pData;
2050 pCaps->Caps |= DDRAW_CAPS_COLORKEY;
2051 // pCaps->Caps2 |= DDRAW_CAPS2_FLIPNOVSYNC;
2052 }
2053 }
2054 else
2055 {
2056 WARN(("D3DDDICAPS_DDRAW query for D3D mode!"));
2057 }
2058#endif
2059 }
2060 else
2061 hr = E_INVALIDARG;
2062 break;
2063 }
2064 case D3DDDICAPS_DDRAW_MODE_SPECIFIC:
2065 {
2066 Assert(!VBOXDISPMODE_IS_3D(pAdapter));
2067 Assert(pData->DataSize == sizeof (DDRAW_MODE_SPECIFIC_CAPS));
2068 if (pData->DataSize >= sizeof (DDRAW_MODE_SPECIFIC_CAPS))
2069 {
2070 DDRAW_MODE_SPECIFIC_CAPS * pCaps = (DDRAW_MODE_SPECIFIC_CAPS*)pData->pData;
2071 memset(&pCaps->Caps /* do not cleanup the first "Head" field,
2072 zero starting with the one following "Head", i.e. Caps */,
2073 0, sizeof (DDRAW_MODE_SPECIFIC_CAPS) - RT_OFFSETOF(DDRAW_MODE_SPECIFIC_CAPS, Caps));
2074#ifdef VBOX_WITH_VIDEOHWACCEL
2075 if (!VBOXDISPMODE_IS_3D(pAdapter))
2076 {
2077 VBOXVHWA_INFO *pSettings = &pAdapter->aHeads[pCaps->Head].Vhwa.Settings;
2078 if (pSettings->fFlags & VBOXVHWA_F_ENABLED)
2079 {
2080 pCaps->Caps |= MODE_CAPS_OVERLAY | MODE_CAPS_OVERLAYSTRETCH;
2081
2082 if (pSettings->fFlags & VBOXVHWA_F_CKEY_DST)
2083 {
2084 pCaps->CKeyCaps |= MODE_CKEYCAPS_DESTOVERLAY
2085 | MODE_CKEYCAPS_DESTOVERLAYYUV /* ?? */
2086 ;
2087 }
2088
2089 if (pSettings->fFlags & VBOXVHWA_F_CKEY_SRC)
2090 {
2091 pCaps->CKeyCaps |= MODE_CKEYCAPS_SRCOVERLAY
2092 | MODE_CKEYCAPS_SRCOVERLAYCLRSPACE /* ?? */
2093 | MODE_CKEYCAPS_SRCOVERLAYCLRSPACEYUV /* ?? */
2094 | MODE_CKEYCAPS_SRCOVERLAYYUV /* ?? */
2095 ;
2096 }
2097
2098 pCaps->FxCaps = MODE_FXCAPS_OVERLAYSHRINKX
2099 | MODE_FXCAPS_OVERLAYSHRINKY
2100 | MODE_FXCAPS_OVERLAYSTRETCHX
2101 | MODE_FXCAPS_OVERLAYSTRETCHY;
2102
2103
2104 pCaps->MaxVisibleOverlays = pSettings->cOverlaysSupported;
2105 pCaps->MinOverlayStretch = 1;
2106 pCaps->MaxOverlayStretch = 32000;
2107 }
2108 }
2109 else
2110 {
2111 WARN(("D3DDDICAPS_DDRAW_MODE_SPECIFIC query for D3D mode!"));
2112 }
2113#endif
2114 }
2115 else
2116 hr = E_INVALIDARG;
2117 break;
2118 }
2119 case D3DDDICAPS_GETFORMATCOUNT:
2120 *((uint32_t*)pData->pData) = pAdapter->Formats.cFormstOps;
2121 break;
2122 case D3DDDICAPS_GETFORMATDATA:
2123 Assert(pData->DataSize == pAdapter->Formats.cFormstOps * sizeof (FORMATOP));
2124 memcpy(pData->pData, pAdapter->Formats.paFormstOps, pAdapter->Formats.cFormstOps * sizeof (FORMATOP));
2125 break;
2126 case D3DDDICAPS_GETD3DQUERYCOUNT:
2127#if 1
2128 *((uint32_t*)pData->pData) = VBOX_QUERYTYPE_COUNT();
2129#else
2130 *((uint32_t*)pData->pData) = 0;
2131#endif
2132 break;
2133 case D3DDDICAPS_GETD3DQUERYDATA:
2134#if 1
2135 Assert(pData->DataSize == VBOX_QUERYTYPE_COUNT() * sizeof (D3DDDIQUERYTYPE));
2136 memcpy(pData->pData, gVBoxQueryTypes, VBOX_QUERYTYPE_COUNT() * sizeof (D3DDDIQUERYTYPE));
2137#else
2138 Assert(0);
2139 memset(pData->pData, 0, pData->DataSize);
2140#endif
2141 break;
2142 case D3DDDICAPS_GETD3D3CAPS:
2143 Assert(!VBOXDISPMODE_IS_3D(pAdapter));
2144 Assert(pData->DataSize == sizeof (D3DHAL_GLOBALDRIVERDATA));
2145 if (pData->DataSize >= sizeof (D3DHAL_GLOBALDRIVERDATA))
2146 {
2147 D3DHAL_GLOBALDRIVERDATA *pCaps = (D3DHAL_GLOBALDRIVERDATA *)pData->pData;
2148 memset (pCaps, 0, sizeof (D3DHAL_GLOBALDRIVERDATA));
2149 pCaps->dwSize = sizeof (D3DHAL_GLOBALDRIVERDATA);
2150 pCaps->hwCaps.dwSize = sizeof (D3DDEVICEDESC_V1);
2151 pCaps->hwCaps.dwFlags = D3DDD_COLORMODEL
2152 | D3DDD_DEVCAPS
2153 | D3DDD_DEVICERENDERBITDEPTH;
2154
2155 pCaps->hwCaps.dcmColorModel = D3DCOLOR_RGB;
2156 pCaps->hwCaps.dwDevCaps = D3DDEVCAPS_CANRENDERAFTERFLIP
2157// | D3DDEVCAPS_DRAWPRIMTLVERTEX
2158 | D3DDEVCAPS_EXECUTESYSTEMMEMORY
2159 | D3DDEVCAPS_EXECUTEVIDEOMEMORY
2160// | D3DDEVCAPS_FLOATTLVERTEX
2161 | D3DDEVCAPS_HWRASTERIZATION
2162// | D3DDEVCAPS_HWTRANSFORMANDLIGHT
2163// | D3DDEVCAPS_TLVERTEXSYSTEMMEMORY
2164// | D3DDEVCAPS_TEXTUREVIDEOMEMORY
2165 ;
2166 pCaps->hwCaps.dtcTransformCaps.dwSize = sizeof (D3DTRANSFORMCAPS);
2167 pCaps->hwCaps.dtcTransformCaps.dwCaps = 0;
2168 pCaps->hwCaps.bClipping = FALSE;
2169 pCaps->hwCaps.dlcLightingCaps.dwSize = sizeof (D3DLIGHTINGCAPS);
2170 pCaps->hwCaps.dlcLightingCaps.dwCaps = 0;
2171 pCaps->hwCaps.dlcLightingCaps.dwLightingModel = 0;
2172 pCaps->hwCaps.dlcLightingCaps.dwNumLights = 0;
2173 pCaps->hwCaps.dpcLineCaps.dwSize = sizeof (D3DPRIMCAPS);
2174 pCaps->hwCaps.dpcLineCaps.dwMiscCaps = 0;
2175 pCaps->hwCaps.dpcLineCaps.dwRasterCaps = 0;
2176 pCaps->hwCaps.dpcLineCaps.dwZCmpCaps = 0;
2177 pCaps->hwCaps.dpcLineCaps.dwSrcBlendCaps = 0;
2178 pCaps->hwCaps.dpcLineCaps.dwDestBlendCaps = 0;
2179 pCaps->hwCaps.dpcLineCaps.dwAlphaCmpCaps = 0;
2180 pCaps->hwCaps.dpcLineCaps.dwShadeCaps = 0;
2181 pCaps->hwCaps.dpcLineCaps.dwTextureCaps = 0;
2182 pCaps->hwCaps.dpcLineCaps.dwTextureFilterCaps = 0;
2183 pCaps->hwCaps.dpcLineCaps.dwTextureBlendCaps = 0;
2184 pCaps->hwCaps.dpcLineCaps.dwTextureAddressCaps = 0;
2185 pCaps->hwCaps.dpcLineCaps.dwStippleWidth = 0;
2186 pCaps->hwCaps.dpcLineCaps.dwStippleHeight = 0;
2187
2188 pCaps->hwCaps.dpcTriCaps.dwSize = sizeof (D3DPRIMCAPS);
2189 pCaps->hwCaps.dpcTriCaps.dwMiscCaps = 0;
2190 pCaps->hwCaps.dpcTriCaps.dwRasterCaps = 0;
2191 pCaps->hwCaps.dpcTriCaps.dwZCmpCaps = 0;
2192 pCaps->hwCaps.dpcTriCaps.dwSrcBlendCaps = 0;
2193 pCaps->hwCaps.dpcTriCaps.dwDestBlendCaps = 0;
2194 pCaps->hwCaps.dpcTriCaps.dwAlphaCmpCaps = 0;
2195 pCaps->hwCaps.dpcTriCaps.dwShadeCaps = 0;
2196 pCaps->hwCaps.dpcTriCaps.dwTextureCaps = 0;
2197 pCaps->hwCaps.dpcTriCaps.dwTextureFilterCaps = 0;
2198 pCaps->hwCaps.dpcTriCaps.dwTextureBlendCaps = 0;
2199 pCaps->hwCaps.dpcTriCaps.dwTextureAddressCaps = 0;
2200 pCaps->hwCaps.dpcTriCaps.dwStippleWidth = 0;
2201 pCaps->hwCaps.dpcTriCaps.dwStippleHeight = 0;
2202 pCaps->hwCaps.dwDeviceRenderBitDepth = DDBD_8 | DDBD_16 | DDBD_24 | DDBD_32;
2203 pCaps->hwCaps.dwDeviceZBufferBitDepth = 0;
2204 pCaps->hwCaps.dwMaxBufferSize = 0;
2205 pCaps->hwCaps.dwMaxVertexCount = 0;
2206
2207
2208 pCaps->dwNumVertices = 0;
2209 pCaps->dwNumClipVertices = 0;
2210 pCaps->dwNumTextureFormats = 0;//pAdapter->cSurfDescs;
2211 pCaps->lpTextureFormats = NULL;//pAdapter->paSurfDescs;
2212 }
2213 else
2214 hr = E_INVALIDARG;
2215 break;
2216 case D3DDDICAPS_GETD3D7CAPS:
2217 Assert(!VBOXDISPMODE_IS_3D(pAdapter));
2218 Assert(pData->DataSize == sizeof (D3DHAL_D3DEXTENDEDCAPS));
2219 if (pData->DataSize >= sizeof (D3DHAL_D3DEXTENDEDCAPS))
2220 {
2221 memset(pData->pData, 0, sizeof (D3DHAL_D3DEXTENDEDCAPS));
2222 D3DHAL_D3DEXTENDEDCAPS *pCaps = (D3DHAL_D3DEXTENDEDCAPS*)pData->pData;
2223 pCaps->dwSize = sizeof (D3DHAL_D3DEXTENDEDCAPS);
2224 }
2225 else
2226 hr = E_INVALIDARG;
2227 break;
2228 case D3DDDICAPS_GETD3D9CAPS:
2229 {
2230 Assert(pData->DataSize == sizeof (D3DCAPS9));
2231 if (pData->DataSize >= sizeof (D3DCAPS9))
2232 {
2233 Assert(VBOXDISPMODE_IS_3D(pAdapter));
2234 if (VBOXDISPMODE_IS_3D(pAdapter))
2235 {
2236 memcpy(pData->pData, &pAdapter->D3D.Caps, sizeof (D3DCAPS9));
2237 hr = S_OK;
2238 break;
2239 }
2240
2241 memset(pData->pData, 0, sizeof (D3DCAPS9));
2242 }
2243 else
2244 hr = E_INVALIDARG;
2245 break;
2246 }
2247 case D3DDDICAPS_GETD3D8CAPS:
2248 {
2249 Assert(pData->DataSize == RT_OFFSETOF(D3DCAPS9, DevCaps2));
2250 if (pData->DataSize == RT_OFFSETOF(D3DCAPS9, DevCaps2))
2251 {
2252 Assert(VBOXDISPMODE_IS_3D(pAdapter));
2253 if (VBOXDISPMODE_IS_3D(pAdapter))
2254 {
2255 memcpy(pData->pData, &pAdapter->D3D.Caps, RT_OFFSETOF(D3DCAPS9, DevCaps2));
2256 hr = S_OK;
2257 break;
2258 }
2259 }
2260 else
2261 hr = E_INVALIDARG;
2262 break;
2263 }
2264 case D3DDDICAPS_GETGAMMARAMPCAPS:
2265 *((uint32_t*)pData->pData) = 0;
2266 break;
2267 case D3DDDICAPS_GETVIDEOPROCESSORCAPS:
2268 case D3DDDICAPS_GETEXTENSIONGUIDCOUNT:
2269 case D3DDDICAPS_GETDECODEGUIDCOUNT:
2270 case D3DDDICAPS_GETVIDEOPROCESSORDEVICEGUIDCOUNT:
2271 case D3DDDICAPS_GETVIDEOPROCESSORRTFORMATCOUNT:
2272 if (pData->pData && pData->DataSize)
2273 memset(pData->pData, 0, pData->DataSize);
2274 break;
2275 case D3DDDICAPS_GETMULTISAMPLEQUALITYLEVELS:
2276 case D3DDDICAPS_GETD3D5CAPS:
2277 case D3DDDICAPS_GETD3D6CAPS:
2278 case D3DDDICAPS_GETDECODEGUIDS:
2279 case D3DDDICAPS_GETDECODERTFORMATCOUNT:
2280 case D3DDDICAPS_GETDECODERTFORMATS:
2281 case D3DDDICAPS_GETDECODECOMPRESSEDBUFFERINFOCOUNT:
2282 case D3DDDICAPS_GETDECODECOMPRESSEDBUFFERINFO:
2283 case D3DDDICAPS_GETDECODECONFIGURATIONCOUNT:
2284 case D3DDDICAPS_GETDECODECONFIGURATIONS:
2285 case D3DDDICAPS_GETVIDEOPROCESSORDEVICEGUIDS:
2286 case D3DDDICAPS_GETVIDEOPROCESSORRTFORMATS:
2287 case D3DDDICAPS_GETVIDEOPROCESSORRTSUBSTREAMFORMATCOUNT:
2288 case D3DDDICAPS_GETVIDEOPROCESSORRTSUBSTREAMFORMATS:
2289 case D3DDDICAPS_GETPROCAMPRANGE:
2290 case D3DDDICAPS_FILTERPROPERTYRANGE:
2291 case D3DDDICAPS_GETEXTENSIONGUIDS:
2292 case D3DDDICAPS_GETEXTENSIONCAPS:
2293 vboxVDbgPrint((__FUNCTION__": unimplemented caps type(%d)\n", pData->Type));
2294 Assert(0);
2295 if (pData->pData && pData->DataSize)
2296 memset(pData->pData, 0, pData->DataSize);
2297 break;
2298 default:
2299 vboxVDbgPrint((__FUNCTION__": unknown caps type(%d)\n", pData->Type));
2300 Assert(0);
2301 }
2302
2303 vboxVDbgPrint(("<== "__FUNCTION__", hAdapter(0x%p), caps type(%d)\n", hAdapter, pData->Type));
2304
2305 return S_OK;
2306}
2307
2308static HRESULT APIENTRY vboxWddmDDevSetRenderState(HANDLE hDevice, CONST D3DDDIARG_RENDERSTATE* pData)
2309{
2310 VBOXDISP_DDI_PROLOGUE_DEV(hDevice);
2311 vboxVDbgPrintF(("==> "__FUNCTION__", hDevice(0x%p)\n", hDevice));
2312 PVBOXWDDMDISP_DEVICE pDevice = (PVBOXWDDMDISP_DEVICE)hDevice;
2313 VBOXDISPCRHGSMI_SCOPE_SET_DEV(pDevice);
2314 Assert(pDevice);
2315 IDirect3DDevice9 * pDevice9If = VBOXDISP_D3DEV(pDevice);
2316 HRESULT hr = pDevice9If->SetRenderState(vboxDDI2D3DRenderStateType(pData->State), pData->Value);
2317 Assert(hr == S_OK);
2318 vboxVDbgPrintF(("<== "__FUNCTION__", hDevice(0x%p), hr(0x%x)\n", hDevice, hr));
2319 return hr;
2320}
2321
2322static HRESULT APIENTRY vboxWddmDDevUpdateWInfo(HANDLE hDevice, CONST D3DDDIARG_WINFO* pData)
2323{
2324 VBOXDISP_DDI_PROLOGUE_DEV(hDevice);
2325// PVBOXWDDMDISP_DEVICE pDevice = (PVBOXWDDMDISP_DEVICE)hDevice;
2326// VBOXDISPCRHGSMI_SCOPE_SET_DEV(pDevice);
2327 vboxVDbgPrintF(("==> "__FUNCTION__", hDevice(0x%p)\n", hDevice));
2328 vboxVDbgPrintF(("<== "__FUNCTION__", hDevice(0x%p)\n", hDevice));
2329 return S_OK;
2330}
2331
2332static HRESULT APIENTRY vboxWddmDDevValidateDevice(HANDLE hDevice, D3DDDIARG_VALIDATETEXTURESTAGESTATE* pData)
2333{
2334 VBOXDISP_DDI_PROLOGUE_DEV(hDevice);
2335// PVBOXWDDMDISP_DEVICE pDevice = (PVBOXWDDMDISP_DEVICE)hDevice;
2336// VBOXDISPCRHGSMI_SCOPE_SET_DEV(pDevice);
2337 vboxVDbgPrintF(("<== "__FUNCTION__", hDevice(0x%p)\n", hDevice));
2338#ifdef DEBUG_misha
2339 /* @todo: check if it's ok to always return success */
2340 vboxVDbgPrint((__FUNCTION__": @todo: check if it's ok to always return success\n"));
2341 Assert(0);
2342#endif
2343 vboxVDbgPrintF(("==> "__FUNCTION__", hDevice(0x%p)\n", hDevice));
2344 return S_OK;
2345}
2346
2347static HRESULT APIENTRY vboxWddmDDevSetTextureStageState(HANDLE hDevice, CONST D3DDDIARG_TEXTURESTAGESTATE* pData)
2348{
2349 VBOXDISP_DDI_PROLOGUE_DEV(hDevice);
2350 vboxVDbgPrintF(("==> "__FUNCTION__", hDevice(0x%p)\n", hDevice));
2351 PVBOXWDDMDISP_DEVICE pDevice = (PVBOXWDDMDISP_DEVICE)hDevice;
2352 Assert(pDevice);
2353 VBOXDISPCRHGSMI_SCOPE_SET_DEV(pDevice);
2354 IDirect3DDevice9 * pDevice9If = VBOXDISP_D3DEV(pDevice);
2355
2356 VBOXWDDMDISP_TSS_LOOKUP lookup = vboxDDI2D3DTestureStageStateType(pData->State);
2357 HRESULT hr;
2358
2359 if (!lookup.bSamplerState)
2360 {
2361 hr = pDevice9If->SetTextureStageState(pData->Stage, D3DTEXTURESTAGESTATETYPE(lookup.dType), pData->Value);
2362 }
2363 else
2364 {
2365 hr = pDevice9If->SetSamplerState(pData->Stage, D3DSAMPLERSTATETYPE(lookup.dType), pData->Value);
2366 }
2367
2368 Assert(hr == S_OK);
2369 vboxVDbgPrintF(("<== "__FUNCTION__", hDevice(0x%p), hr(0x%x)\n", hDevice, hr));
2370 return hr;
2371}
2372
2373static HRESULT APIENTRY vboxWddmDDevSetTexture(HANDLE hDevice, UINT Stage, HANDLE hTexture)
2374{
2375 VBOXDISP_DDI_PROLOGUE_DEV(hDevice);
2376 vboxVDbgPrintF(("==> "__FUNCTION__", hDevice(0x%p)\n", hDevice));
2377 PVBOXWDDMDISP_DEVICE pDevice = (PVBOXWDDMDISP_DEVICE)hDevice;
2378 Assert(pDevice);
2379 VBOXDISPCRHGSMI_SCOPE_SET_DEV(pDevice);
2380 IDirect3DDevice9 * pDevice9If = VBOXDISP_D3DEV(pDevice);
2381 PVBOXWDDMDISP_RESOURCE pRc = (PVBOXWDDMDISP_RESOURCE)hTexture;
2382// Assert(pRc);
2383 IDirect3DBaseTexture9 *pD3DIfTex;
2384 if (pRc)
2385 {
2386 VBOXVDBG_CHECK_SMSYNC(pRc);
2387 if (pRc->aAllocations[0].enmD3DIfType == VBOXDISP_D3DIFTYPE_TEXTURE)
2388 {
2389 pD3DIfTex = (IDirect3DTexture9*)pRc->aAllocations[0].pD3DIf;
2390
2391 VBOXVDBG_BREAK_SHARED(pRc);
2392 VBOXVDBG_DUMP_SETTEXTURE(pRc);
2393 }
2394 else if (pRc->aAllocations[0].enmD3DIfType == VBOXDISP_D3DIFTYPE_CUBE_TEXTURE)
2395 {
2396 pD3DIfTex = (IDirect3DCubeTexture9*)pRc->aAllocations[0].pD3DIf;
2397
2398 VBOXVDBG_BREAK_SHARED(pRc);
2399 VBOXVDBG_DUMP_SETTEXTURE(pRc);
2400 }
2401 else if (pRc->aAllocations[0].enmD3DIfType == VBOXDISP_D3DIFTYPE_VOLUME_TEXTURE)
2402 {
2403 pD3DIfTex = (IDirect3DVolumeTexture9*)pRc->aAllocations[0].pD3DIf;
2404
2405 VBOXVDBG_BREAK_SHARED(pRc);
2406 VBOXVDBG_DUMP_SETTEXTURE(pRc);
2407 }
2408 else
2409 {
2410 Assert(0);
2411 }
2412
2413 Assert(pDevice->cSamplerTextures < RT_ELEMENTS(pDevice->aSamplerTextures));
2414 int idx = VBOXWDDMDISP_SAMPLER_IDX(Stage);
2415 if (idx >= 0)
2416 {
2417 Assert(idx < RT_ELEMENTS(pDevice->aSamplerTextures));
2418#ifdef DEBUG_misha
2419 if (VBOXWDDMDISP_SAMPLER_IDX_IS_SPECIAL(Stage))
2420 {
2421 WARN(("non-zero special sampler index not tested!\n"));
2422 }
2423#endif
2424 if (!pDevice->aSamplerTextures[idx])
2425 {
2426 ++pDevice->cSamplerTextures;
2427 }
2428 Assert(pDevice->cSamplerTextures < RT_ELEMENTS(pDevice->aSamplerTextures));
2429 pDevice->aSamplerTextures[idx] = pRc;
2430 }
2431 else
2432 {
2433 WARN(("incorrect dampler index1! (%d)\n", Stage));
2434 }
2435 }
2436 else
2437 {
2438 pD3DIfTex = NULL;
2439 Assert(pDevice->cSamplerTextures < RT_ELEMENTS(pDevice->aSamplerTextures));
2440 int idx = VBOXWDDMDISP_SAMPLER_IDX(Stage);
2441 if (idx >= 0)
2442 {
2443 Assert(idx < RT_ELEMENTS(pDevice->aSamplerTextures));
2444 if (pDevice->aSamplerTextures[idx])
2445 {
2446 Assert(pDevice->cSamplerTextures);
2447 --pDevice->cSamplerTextures;
2448 }
2449 Assert(pDevice->cSamplerTextures < RT_ELEMENTS(pDevice->aSamplerTextures));
2450 pDevice->aSamplerTextures[idx] = NULL;
2451 }
2452 else
2453 {
2454 WARN(("incorrect dampler index2! (%d)\n", Stage));
2455 }
2456 }
2457
2458 HRESULT hr = pDevice9If->SetTexture(Stage, pD3DIfTex);
2459 Assert(hr == S_OK);
2460 vboxVDbgPrintF(("<== "__FUNCTION__", hDevice(0x%p), hr(0x%x)\n", hDevice, hr));
2461 return hr;
2462}
2463
2464static HRESULT APIENTRY vboxWddmDDevSetPixelShader(HANDLE hDevice, HANDLE hShaderHandle)
2465{
2466 VBOXDISP_DDI_PROLOGUE_DEV(hDevice);
2467 vboxVDbgPrintF(("==> "__FUNCTION__", hDevice(0x%p)\n", hDevice));
2468 PVBOXWDDMDISP_DEVICE pDevice = (PVBOXWDDMDISP_DEVICE)hDevice;
2469 Assert(pDevice);
2470 VBOXDISPCRHGSMI_SCOPE_SET_DEV(pDevice);
2471 IDirect3DDevice9 * pDevice9If = VBOXDISP_D3DEV(pDevice);
2472 IDirect3DPixelShader9 *pShader = (IDirect3DPixelShader9*)hShaderHandle;
2473 HRESULT hr = pDevice9If->SetPixelShader(pShader);
2474 Assert(hr == S_OK);
2475 vboxVDbgPrintF(("<== "__FUNCTION__", hDevice(0x%p), hr(0x%x)\n", hDevice, hr));
2476 return hr;
2477}
2478
2479static HRESULT APIENTRY vboxWddmDDevSetPixelShaderConst(HANDLE hDevice, CONST D3DDDIARG_SETPIXELSHADERCONST* pData, CONST FLOAT* pRegisters)
2480{
2481 VBOXDISP_DDI_PROLOGUE_DEV(hDevice);
2482 vboxVDbgPrintF(("==> "__FUNCTION__", hDevice(0x%p)\n", hDevice));
2483 PVBOXWDDMDISP_DEVICE pDevice = (PVBOXWDDMDISP_DEVICE)hDevice;
2484 Assert(pDevice);
2485 VBOXDISPCRHGSMI_SCOPE_SET_DEV(pDevice);
2486 IDirect3DDevice9 * pDevice9If = VBOXDISP_D3DEV(pDevice);
2487 HRESULT hr = pDevice9If->SetPixelShaderConstantF(pData->Register, pRegisters, pData->Count);
2488 Assert(hr == S_OK);
2489 vboxVDbgPrintF(("<== "__FUNCTION__", hDevice(0x%p), hr(0x%x)\n", hDevice, hr));
2490 return hr;
2491}
2492
2493static HRESULT APIENTRY vboxWddmDDevSetStreamSourceUm(HANDLE hDevice, CONST D3DDDIARG_SETSTREAMSOURCEUM* pData, CONST VOID* pUMBuffer )
2494{
2495 VBOXDISP_DDI_PROLOGUE_DEV(hDevice);
2496 vboxVDbgPrintF(("==> "__FUNCTION__", hDevice(0x%p)\n", hDevice));
2497 PVBOXWDDMDISP_DEVICE pDevice = (PVBOXWDDMDISP_DEVICE)hDevice;
2498 Assert(pDevice);
2499 VBOXDISPCRHGSMI_SCOPE_SET_DEV(pDevice);
2500 HRESULT hr = S_OK;
2501
2502 Assert(pData->Stream < RT_ELEMENTS(pDevice->aStreamSourceUm));
2503 PVBOXWDDMDISP_STREAMSOURCEUM pStrSrcUm = &pDevice->aStreamSourceUm[pData->Stream];
2504 if (pStrSrcUm->pvBuffer && !pUMBuffer)
2505 {
2506 --pDevice->cStreamSourcesUm;
2507 Assert(pDevice->cStreamSourcesUm < UINT32_MAX/2);
2508 }
2509 else if (!pStrSrcUm->pvBuffer && pUMBuffer)
2510 {
2511 ++pDevice->cStreamSourcesUm;
2512 Assert(pDevice->cStreamSourcesUm <= RT_ELEMENTS(pDevice->aStreamSourceUm));
2513 }
2514
2515 pStrSrcUm->pvBuffer = pUMBuffer;
2516 pStrSrcUm->cbStride = pData->Stride;
2517
2518 if (pDevice->aStreamSource[pData->Stream])
2519 {
2520 hr = pDevice->pDevice9If->SetStreamSource(pData->Stream, NULL, 0, 0);
2521 --pDevice->cStreamSources;
2522 Assert(pDevice->cStreamSources < UINT32_MAX/2);
2523 pDevice->aStreamSource[pData->Stream] = NULL;
2524 }
2525
2526 vboxVDbgPrintF(("<== "__FUNCTION__", hDevice(0x%p), hr(0x%x)\n", hDevice, hr));
2527 return hr;
2528}
2529
2530static HRESULT APIENTRY vboxWddmDDevSetIndices(HANDLE hDevice, CONST D3DDDIARG_SETINDICES* pData)
2531{
2532 VBOXDISP_DDI_PROLOGUE_DEV(hDevice);
2533 vboxVDbgPrintF(("==> "__FUNCTION__", hDevice(0x%p)\n", hDevice));
2534 PVBOXWDDMDISP_DEVICE pDevice = (PVBOXWDDMDISP_DEVICE)hDevice;
2535 Assert(pDevice);
2536 VBOXDISPCRHGSMI_SCOPE_SET_DEV(pDevice);
2537
2538 IDirect3DDevice9 * pDevice9If = VBOXDISP_D3DEV(pDevice);
2539 PVBOXWDDMDISP_RESOURCE pRc = (PVBOXWDDMDISP_RESOURCE)pData->hIndexBuffer;
2540 PVBOXWDDMDISP_ALLOCATION pAlloc = NULL;
2541 IDirect3DIndexBuffer9 *pIndexBuffer = NULL;
2542 if (pRc)
2543 {
2544 VBOXVDBG_CHECK_SMSYNC(pRc);
2545 Assert(pRc->cAllocations == 1);
2546 pAlloc = &pRc->aAllocations[0];
2547 Assert(pAlloc->pD3DIf);
2548 pIndexBuffer = (IDirect3DIndexBuffer9*)pAlloc->pD3DIf;
2549 }
2550 HRESULT hr = pDevice9If->SetIndices(pIndexBuffer);
2551 Assert(hr == S_OK);
2552 if (hr == S_OK)
2553 {
2554 pDevice->IndiciesInfo.pIndicesAlloc = pAlloc;
2555 pDevice->IndiciesInfo.uiStride = pData->Stride;
2556 pDevice->IndiciesInfo.pvIndicesUm = NULL;
2557 }
2558 vboxVDbgPrintF(("<== "__FUNCTION__", hDevice(0x%p), hr(0x%x)\n", hDevice, hr));
2559 return hr;
2560}
2561
2562static HRESULT APIENTRY vboxWddmDDevSetIndicesUm(HANDLE hDevice, UINT IndexSize, CONST VOID* pUMBuffer)
2563{
2564 VBOXDISP_DDI_PROLOGUE_DEV(hDevice);
2565 vboxVDbgPrintF(("==> "__FUNCTION__", hDevice(0x%p)\n", hDevice));
2566 PVBOXWDDMDISP_DEVICE pDevice = (PVBOXWDDMDISP_DEVICE)hDevice;
2567 Assert(pDevice);
2568 VBOXDISPCRHGSMI_SCOPE_SET_DEV(pDevice);
2569
2570 IDirect3DDevice9 * pDevice9If = VBOXDISP_D3DEV(pDevice);
2571
2572 HRESULT hr = S_OK;
2573 if (pDevice->IndiciesInfo.pIndicesAlloc)
2574 {
2575 hr = pDevice9If->SetIndices(NULL);
2576 }
2577
2578 if (SUCCEEDED(hr))
2579 {
2580 pDevice->IndiciesInfo.pvIndicesUm = pUMBuffer;
2581 pDevice->IndiciesInfo.uiStride = IndexSize;
2582 pDevice->IndiciesInfo.pIndicesAlloc = NULL;
2583 hr = S_OK;
2584 }
2585 else
2586 {
2587 WARN(("SetIndices failed hr 0x%x", hr));
2588 }
2589
2590 vboxVDbgPrintF(("<== "__FUNCTION__", hDevice(0x%p), hr(0x%x)\n", hDevice, hr));
2591 return hr;
2592}
2593
2594static HRESULT APIENTRY vboxWddmDDevDrawPrimitive(HANDLE hDevice, CONST D3DDDIARG_DRAWPRIMITIVE* pData, CONST UINT* pFlagBuffer)
2595{
2596 VBOXDISP_DDI_PROLOGUE_DEV(hDevice);
2597 vboxVDbgPrintF(("==> "__FUNCTION__", hDevice(0x%p)\n", hDevice));
2598 PVBOXWDDMDISP_DEVICE pDevice = (PVBOXWDDMDISP_DEVICE)hDevice;
2599 Assert(pDevice);
2600 VBOXDISPCRHGSMI_SCOPE_SET_DEV(pDevice);
2601
2602 IDirect3DDevice9 * pDevice9If = VBOXDISP_D3DEV(pDevice);
2603 Assert(!pFlagBuffer);
2604 HRESULT hr = S_OK;
2605
2606 VBOXVDBG_BREAK_SHARED_DEV(pDevice);
2607
2608 VBOXVDBG_DUMP_DRAWPRIM_ENTER(pDevice);
2609
2610 if (pDevice->cStreamSourcesUm)
2611 {
2612#ifdef DEBUG
2613 uint32_t cStreams = 0;
2614 for (UINT i = 0; i < RT_ELEMENTS(pDevice->aStreamSourceUm); ++i)
2615 {
2616 if(pDevice->aStreamSourceUm[i].pvBuffer)
2617 {
2618 ++cStreams;
2619 }
2620 }
2621
2622 Assert(cStreams);
2623 Assert(cStreams == pDevice->cStreamSourcesUm);
2624#endif
2625 if (pDevice->cStreamSourcesUm == 1)
2626 {
2627 for (UINT i = 0; i < RT_ELEMENTS(pDevice->aStreamSourceUm); ++i)
2628 {
2629 if(pDevice->aStreamSourceUm[i].pvBuffer)
2630 {
2631 hr = pDevice9If->DrawPrimitiveUP(pData->PrimitiveType,
2632 pData->PrimitiveCount,
2633 ((uint8_t*)pDevice->aStreamSourceUm[i].pvBuffer) + pData->VStart * pDevice->aStreamSourceUm[i].cbStride,
2634 pDevice->aStreamSourceUm[i].cbStride);
2635 Assert(hr == S_OK);
2636 break;
2637 }
2638 }
2639 }
2640 else
2641 {
2642 /* todo: impl */
2643 WARN(("multiple user stream sources (%d) not implemented!!", pDevice->cStreamSourcesUm));
2644 }
2645 }
2646 else
2647 {
2648
2649#ifdef DEBUG
2650 Assert(!pDevice->cStreamSourcesUm);
2651 for (UINT i = 0; i < RT_ELEMENTS(pDevice->aStreamSourceUm); ++i)
2652 {
2653 Assert(!pDevice->aStreamSourceUm[i].pvBuffer);
2654 }
2655
2656 uint32_t cStreams = 0;
2657 for (UINT i = 0; i < RT_ELEMENTS(pDevice->aStreamSource); ++i)
2658 {
2659 if (pDevice->aStreamSource[i])
2660 {
2661 ++cStreams;
2662 Assert(!pDevice->aStreamSource[i]->LockInfo.cLocks);
2663 }
2664 }
2665
2666 Assert(cStreams);
2667 Assert(cStreams == pDevice->cStreamSources);
2668#endif
2669 hr = pDevice9If->DrawPrimitive(pData->PrimitiveType,
2670 pData->VStart,
2671 pData->PrimitiveCount);
2672 Assert(hr == S_OK);
2673
2674// vboxVDbgMpPrintF((pDevice, __FUNCTION__": DrawPrimitive\n"));
2675 }
2676
2677 vboxWddmDalCheckAddOnDraw(pDevice);
2678
2679 VBOXVDBG_DUMP_DRAWPRIM_LEAVE(pDevice);
2680
2681 vboxVDbgPrintF(("<== "__FUNCTION__", hDevice(0x%p), hr(0x%x)\n", hDevice, hr));
2682 return hr;
2683}
2684
2685static HRESULT APIENTRY vboxWddmDDevDrawIndexedPrimitive(HANDLE hDevice, CONST D3DDDIARG_DRAWINDEXEDPRIMITIVE* pData)
2686{
2687 VBOXDISP_DDI_PROLOGUE_DEV(hDevice);
2688 vboxVDbgPrintF(("==> "__FUNCTION__", hDevice(0x%p)\n", hDevice));
2689 PVBOXWDDMDISP_DEVICE pDevice = (PVBOXWDDMDISP_DEVICE)hDevice;
2690 Assert(pDevice);
2691 VBOXDISPCRHGSMI_SCOPE_SET_DEV(pDevice);
2692
2693 IDirect3DDevice9 * pDevice9If = VBOXDISP_D3DEV(pDevice);
2694
2695 VBOXVDBG_BREAK_SHARED_DEV(pDevice);
2696
2697 VBOXVDBG_DUMP_DRAWPRIM_ENTER(pDevice);
2698
2699
2700#ifdef DEBUG
2701 uint32_t cStreams = 0;
2702 for (UINT i = 0; i < RT_ELEMENTS(pDevice->aStreamSourceUm); ++i)
2703 {
2704 if(pDevice->aStreamSourceUm[i].pvBuffer)
2705 ++cStreams;
2706 }
2707
2708 Assert(cStreams == pDevice->cStreamSourcesUm);
2709
2710 cStreams = 0;
2711
2712 for (UINT i = 0; i < RT_ELEMENTS(pDevice->aStreamSource); ++i)
2713 {
2714 if (pDevice->aStreamSource[i])
2715 {
2716 ++cStreams;
2717 Assert(!pDevice->aStreamSource[i]->LockInfo.cLocks);
2718 }
2719 }
2720
2721 Assert(cStreams == pDevice->cStreamSources);
2722#endif
2723
2724 HRESULT hr;
2725
2726 if (pDevice->cStreamSources)
2727 {
2728 Assert(pDevice->IndiciesInfo.pIndicesAlloc);
2729 Assert(!pDevice->IndiciesInfo.pvIndicesUm);
2730 Assert(!pDevice->IndiciesInfo.pIndicesAlloc->LockInfo.cLocks);
2731 Assert(!pDevice->cStreamSourcesUm);
2732
2733 hr = pDevice9If->DrawIndexedPrimitive(
2734 pData->PrimitiveType,
2735 pData->BaseVertexIndex,
2736 pData->MinIndex,
2737 pData->NumVertices,
2738 pData->StartIndex,
2739 pData->PrimitiveCount);
2740
2741 if(SUCCEEDED(hr))
2742 hr = S_OK;
2743 else
2744 WARN(("DrawIndexedPrimitive failed hr = 0x%x", hr));
2745 }
2746 else
2747 {
2748 Assert(pDevice->cStreamSourcesUm == 1);
2749 Assert(pDevice->IndiciesInfo.uiStride == 2 || pDevice->IndiciesInfo.uiStride == 4);
2750 const uint8_t * pvIndexBuffer;
2751 hr = S_OK;
2752
2753 if (pDevice->IndiciesInfo.pIndicesAlloc)
2754 {
2755 Assert(!pDevice->IndiciesInfo.pvIndicesUm);
2756 if (pDevice->IndiciesInfo.pIndicesAlloc->pvMem)
2757 pvIndexBuffer = (const uint8_t*)pDevice->IndiciesInfo.pIndicesAlloc->pvMem;
2758 else
2759 {
2760 WARN(("not expected!"));
2761 hr = E_FAIL;
2762 pvIndexBuffer = NULL;
2763 }
2764 }
2765 else
2766 {
2767 pvIndexBuffer = (const uint8_t*)pDevice->IndiciesInfo.pvIndicesUm;
2768 if (!pvIndexBuffer)
2769 {
2770 WARN(("not expected!"));
2771 hr = E_FAIL;
2772 }
2773 }
2774
2775 if (SUCCEEDED(hr))
2776 {
2777 for (UINT i = 0; i < RT_ELEMENTS(pDevice->aStreamSourceUm); ++i)
2778 {
2779 if(pDevice->aStreamSourceUm[i].pvBuffer)
2780 {
2781 hr = pDevice9If->DrawIndexedPrimitiveUP(pData->PrimitiveType,
2782 pData->MinIndex,
2783 pData->NumVertices,
2784 pData->PrimitiveCount,
2785 pvIndexBuffer + pDevice->IndiciesInfo.uiStride * pData->StartIndex,
2786 pDevice->IndiciesInfo.uiStride == 2 ? D3DFMT_INDEX16 : D3DFMT_INDEX32,
2787 pDevice->aStreamSourceUm[i].pvBuffer,
2788 pDevice->aStreamSourceUm[i].cbStride);
2789 if(SUCCEEDED(hr))
2790 {
2791 if (pDevice->IndiciesInfo.pIndicesAlloc)
2792 {
2793 HRESULT tmpHr = pDevice9If->SetIndices((IDirect3DIndexBuffer9*)pDevice->IndiciesInfo.pIndicesAlloc->pD3DIf);
2794 if(!SUCCEEDED(tmpHr))
2795 WARN(("SetIndices failed hr = 0x%x", tmpHr));
2796 }
2797
2798 hr = S_OK;
2799 }
2800 else
2801 WARN(("DrawIndexedPrimitiveUP failed hr = 0x%x", hr));
2802 break;
2803 }
2804 }
2805 }
2806 }
2807
2808 vboxWddmDalCheckAddOnDraw(pDevice);
2809
2810 VBOXVDBG_DUMP_DRAWPRIM_LEAVE(pDevice);
2811
2812 vboxVDbgPrintF(("<== "__FUNCTION__", hDevice(0x%p), hr(0x%x)\n", hDevice, hr));
2813 return hr;
2814}
2815
2816static HRESULT APIENTRY vboxWddmDDevDrawRectPatch(HANDLE hDevice, CONST D3DDDIARG_DRAWRECTPATCH* pData, CONST D3DDDIRECTPATCH_INFO* pInfo, CONST FLOAT* pPatch)
2817{
2818 VBOXDISP_DDI_PROLOGUE_DEV(hDevice);
2819 vboxVDbgPrintF(("<== "__FUNCTION__", hDevice(0x%p)\n", hDevice));
2820 PVBOXWDDMDISP_DEVICE pDevice = (PVBOXWDDMDISP_DEVICE)hDevice;
2821 Assert(pDevice);
2822 VBOXDISPCRHGSMI_SCOPE_SET_DEV(pDevice);
2823 Assert(0);
2824 vboxWddmDalCheckAddOnDraw(pDevice);
2825 vboxVDbgPrintF(("==> "__FUNCTION__", hDevice(0x%p)\n", hDevice));
2826 return E_FAIL;
2827}
2828
2829static HRESULT APIENTRY vboxWddmDDevDrawTriPatch(HANDLE hDevice, CONST D3DDDIARG_DRAWTRIPATCH* pData, CONST D3DDDITRIPATCH_INFO* pInfo, CONST FLOAT* pPatch)
2830{
2831 VBOXDISP_DDI_PROLOGUE_DEV(hDevice);
2832 vboxVDbgPrintF(("<== "__FUNCTION__", hDevice(0x%p)\n", hDevice));
2833 PVBOXWDDMDISP_DEVICE pDevice = (PVBOXWDDMDISP_DEVICE)hDevice;
2834 Assert(pDevice);
2835 VBOXDISPCRHGSMI_SCOPE_SET_DEV(pDevice);
2836 Assert(0);
2837 vboxWddmDalCheckAddOnDraw(pDevice);
2838 vboxVDbgPrintF(("==> "__FUNCTION__", hDevice(0x%p)\n", hDevice));
2839 return E_FAIL;
2840}
2841
2842static HRESULT APIENTRY vboxWddmDDevDrawPrimitive2(HANDLE hDevice, CONST D3DDDIARG_DRAWPRIMITIVE2* pData)
2843{
2844 VBOXDISP_DDI_PROLOGUE_DEV(hDevice);
2845 vboxVDbgPrintF(("==> "__FUNCTION__", hDevice(0x%p)\n", hDevice));
2846 PVBOXWDDMDISP_DEVICE pDevice = (PVBOXWDDMDISP_DEVICE)hDevice;
2847 Assert(pDevice);
2848 VBOXDISPCRHGSMI_SCOPE_SET_DEV(pDevice);
2849
2850 IDirect3DDevice9 * pDevice9If = VBOXDISP_D3DEV(pDevice);
2851 HRESULT hr;
2852
2853#if 0
2854 int stream;
2855 for (stream=0; stream<VBOXWDDMDISP_MAX_VERTEX_STREAMS; ++stream)
2856 {
2857 if (pDevice->aStreamSource[stream] && pDevice->aStreamSource[stream]->LockInfo.cLocks)
2858 {
2859 VBOXWDDMDISP_LOCKINFO *pLock = &pDevice->aStreamSource[stream]->LockInfo;
2860 if (pLock->fFlags.MightDrawFromLocked && (pLock->fFlags.Discard || pLock->fFlags.NoOverwrite))
2861 {
2862 IDirect3DVertexBuffer9 *pD3D9VBuf = (IDirect3DVertexBuffer9*)pDevice->aStreamSource[stream]->pD3DIf;
2863 Assert(pLock->fFlags.RangeValid);
2864 pD3D9VBuf->Lock(pLock->Range.Offset, pLock->Range.Size,
2865 &pLock->LockedRect.pBits,
2866 vboxDDI2D3DLockFlags(pLock->fFlags));
2867 RECT r;
2868 r.top = 0;
2869 r.left = pLock->Range.Offset;
2870 r.bottom = 1;
2871 r.right = pLock->Range.Offset + pLock->Range.Size;
2872
2873 VBoxD3DIfLockUnlockMemSynch(pDevice->aStreamSource[stream], &pLock->LockedRect, &r, true /*bool bToLockInfo*/);
2874
2875 pD3D9VBuf->Unlock();
2876 }
2877 }
2878 }
2879
2880 hr = pDevice9If->DrawPrimitive(pData->PrimitiveType, pData->FirstVertexOffset, pData->PrimitiveCount);
2881#else
2882 VBOXVDBG_BREAK_SHARED_DEV(pDevice);
2883
2884 VBOXVDBG_DUMP_DRAWPRIM_ENTER(pDevice);
2885
2886#ifdef DEBUG
2887 uint32_t cStreams = 0;
2888#endif
2889
2890 int stream;
2891 for (stream=0; stream<VBOXWDDMDISP_MAX_VERTEX_STREAMS; ++stream)
2892 {
2893 if (pDevice->aStreamSource[stream])
2894 {
2895#ifdef DEBUG
2896 ++cStreams;
2897#endif
2898 Assert(stream==0); /*only stream 0 should be accessed here*/
2899 Assert(pDevice->StreamSourceInfo[stream].uiStride!=0);
2900 VBOXWDDMDISP_LOCKINFO *pLock = &pDevice->aStreamSource[stream]->LockInfo;
2901
2902 if (pLock->cLocks)
2903 {
2904// vboxVDbgMpPrintF((pDevice, __FUNCTION__": DrawPrimitiveUP\n"));
2905
2906 Assert(pLock->fFlags.MightDrawFromLocked && (pLock->fFlags.Discard || pLock->fFlags.NoOverwrite));
2907 hr = pDevice9If->DrawPrimitiveUP(pData->PrimitiveType, pData->PrimitiveCount,
2908 (void*)((uintptr_t)pDevice->aStreamSource[stream]->pvMem+pDevice->StreamSourceInfo[stream].uiOffset+pData->FirstVertexOffset),
2909 pDevice->StreamSourceInfo[stream].uiStride);
2910 Assert(hr == S_OK);
2911 hr = pDevice9If->SetStreamSource(stream, (IDirect3DVertexBuffer9*)pDevice->aStreamSource[stream]->pD3DIf, pDevice->StreamSourceInfo[stream].uiOffset, pDevice->StreamSourceInfo[stream].uiStride);
2912 Assert(hr == S_OK);
2913 }
2914 else
2915 {
2916// vboxVDbgMpPrintF((pDevice, __FUNCTION__": DrawPrimitive\n"));
2917
2918 hr = pDevice9If->DrawPrimitive(pData->PrimitiveType, pData->FirstVertexOffset/pDevice->StreamSourceInfo[stream].uiStride, pData->PrimitiveCount);
2919 Assert(hr == S_OK);
2920 }
2921 }
2922 }
2923
2924#ifdef DEBUG
2925 Assert(cStreams);
2926 Assert(cStreams == pDevice->cStreamSources);
2927#endif
2928#endif
2929
2930 vboxWddmDalCheckAddOnDraw(pDevice);
2931
2932 VBOXVDBG_DUMP_DRAWPRIM_LEAVE(pDevice);
2933
2934 Assert(hr == S_OK);
2935 vboxVDbgPrintF(("<== "__FUNCTION__", hDevice(0x%p), hr(0x%x)\n", hDevice, hr));
2936 return hr;
2937}
2938
2939static UINT vboxWddmVertexCountFromPrimitive(D3DPRIMITIVETYPE PrimitiveType, UINT PrimitiveCount)
2940{
2941 Assert(PrimitiveCount > 0); /* Callers ensure this. */
2942
2943 UINT cVertices;
2944 switch (PrimitiveType)
2945 {
2946 case D3DPT_POINTLIST:
2947 cVertices = PrimitiveCount; /* Vertex per point. */
2948 break;
2949
2950 case D3DPT_LINELIST:
2951 cVertices = PrimitiveCount * 2; /* Two vertices for each line. */
2952 break;
2953
2954 case D3DPT_LINESTRIP:
2955 cVertices = PrimitiveCount + 1; /* Two vertices for the first line and one vertex for each subsequent. */
2956 break;
2957
2958 case D3DPT_TRIANGLELIST:
2959 cVertices = PrimitiveCount * 3; /* Three vertices for each triangle. */
2960 break;
2961
2962 case D3DPT_TRIANGLESTRIP:
2963 case D3DPT_TRIANGLEFAN:
2964 cVertices = PrimitiveCount + 2; /* Three vertices for the first triangle and one vertex for each subsequent. */
2965 break;
2966
2967 default:
2968 cVertices = 0; /* No such primitive in d3d9types.h. */
2969 break;
2970 }
2971
2972 return cVertices;
2973}
2974
2975static HRESULT APIENTRY vboxWddmDDevDrawIndexedPrimitive2(HANDLE hDevice, CONST D3DDDIARG_DRAWINDEXEDPRIMITIVE2* pData, UINT dwIndicesSize, CONST VOID* pIndexBuffer, CONST UINT* pFlagBuffer)
2976{
2977 VBOXDISP_DDI_PROLOGUE_DEV(hDevice);
2978 vboxVDbgPrintF(("==> "__FUNCTION__", hDevice(0x%p)\n", hDevice));
2979 PVBOXWDDMDISP_DEVICE pDevice = (PVBOXWDDMDISP_DEVICE)hDevice;
2980 Assert(pDevice);
2981 IDirect3DDevice9 * pDevice9If = VBOXDISP_D3DEV(pDevice);
2982 HRESULT hr = S_OK;
2983 VBOXDISPCRHGSMI_SCOPE_SET_DEV(pDevice);
2984 const uint8_t *pvVertexBuffer = NULL;
2985 DWORD cbVertexStride = 0;
2986
2987 LOGF(("\n PrimitiveType %d, BaseVertexOffset %d, MinIndex %d, NumVertices %d, StartIndexOffset %d, PrimitiveCount %d,\n"
2988 " dwIndicesSize %d, pIndexBuffer %p, pFlagBuffer %p\n",
2989 pData->PrimitiveType,
2990 pData->BaseVertexOffset,
2991 pData->MinIndex,
2992 pData->NumVertices,
2993 pData->StartIndexOffset,
2994 pData->PrimitiveCount,
2995 dwIndicesSize,
2996 pIndexBuffer,
2997 pFlagBuffer));
2998
2999 if (dwIndicesSize != 2 && dwIndicesSize != 4)
3000 {
3001 WARN(("unsupported dwIndicesSize %d", dwIndicesSize));
3002 return E_INVALIDARG;
3003 }
3004
3005 if (pData->PrimitiveCount == 0)
3006 {
3007 /* Nothing to draw. */
3008 return S_OK;
3009 }
3010
3011 /* Fetch the appropriate stream source:
3012 * "Stream zero contains transform indices and is the only stream that should be accessed."
3013 */
3014 if (pDevice->aStreamSourceUm[0].pvBuffer)
3015 {
3016 Assert(pDevice->aStreamSourceUm[0].cbStride);
3017
3018 pvVertexBuffer = (const uint8_t *)pDevice->aStreamSourceUm[0].pvBuffer;
3019 cbVertexStride = pDevice->aStreamSourceUm[0].cbStride;
3020 LOGF(("aStreamSourceUm %p, stride %d\n",
3021 pvVertexBuffer, cbVertexStride));
3022 }
3023 else if (pDevice->aStreamSource[0])
3024 {
3025 PVBOXWDDMDISP_ALLOCATION pAlloc = pDevice->aStreamSource[0];
3026 if (pAlloc->pvMem)
3027 {
3028 Assert(pDevice->StreamSourceInfo[0].uiStride);
3029 pvVertexBuffer = ((const uint8_t *)pAlloc->pvMem) + pDevice->StreamSourceInfo[0].uiOffset;
3030 cbVertexStride = pDevice->StreamSourceInfo[0].uiStride;
3031 LOGF(("aStreamSource %p, cbSize %d, stride %d, uiOffset %d (elements %d)\n",
3032 pvVertexBuffer, pAlloc->SurfDesc.cbSize, cbVertexStride, pDevice->StreamSourceInfo[0].uiOffset,
3033 cbVertexStride? pAlloc->SurfDesc.cbSize / cbVertexStride: 0));
3034 }
3035 else
3036 {
3037 WARN(("unsupported!!"));
3038 hr = E_FAIL;
3039 }
3040 }
3041 else
3042 {
3043 WARN(("not expected!"));
3044 hr = E_FAIL;
3045 }
3046
3047 if (SUCCEEDED(hr))
3048 {
3049 /* Convert input data to appropriate DrawIndexedPrimitiveUP parameters.
3050 * In particular prepare zero based vertex array becuase wine does not
3051 * handle MinVertexIndex correctly.
3052 */
3053
3054 /* Take the offset, which corresponds to the index == 0, into account. */
3055 const uint8_t *pu8VertexStart = pvVertexBuffer + pData->BaseVertexOffset;
3056
3057 /* Where the pData->MinIndex starts. */
3058 pu8VertexStart += pData->MinIndex * cbVertexStride;
3059
3060 /* Convert indexes to zero based relative to pData->MinIndex. */
3061 const uint8_t *pu8IndicesStartSrc = (uint8_t *)pIndexBuffer + pData->StartIndexOffset;
3062 UINT cIndices = vboxWddmVertexCountFromPrimitive(pData->PrimitiveType, pData->PrimitiveCount);
3063
3064 /* Allocate memory for converted indices. */
3065 uint8_t *pu8IndicesStartConv = (uint8_t *)RTMemAlloc(cIndices * dwIndicesSize);
3066 if (pu8IndicesStartConv != NULL)
3067 {
3068 UINT i;
3069 if (dwIndicesSize == 2)
3070 {
3071 uint16_t *pu16Src = (uint16_t *)pu8IndicesStartSrc;
3072 uint16_t *pu16Dst = (uint16_t *)pu8IndicesStartConv;
3073 for (i = 0; i < cIndices; ++i, ++pu16Dst, ++pu16Src)
3074 {
3075 *pu16Dst = *pu16Src - pData->MinIndex;
3076 }
3077 }
3078 else
3079 {
3080 uint32_t *pu32Src = (uint32_t *)pu8IndicesStartSrc;
3081 uint32_t *pu32Dst = (uint32_t *)pu8IndicesStartConv;
3082 for (i = 0; i < cIndices; ++i, ++pu32Dst, ++pu32Src)
3083 {
3084 *pu32Dst = *pu32Src - pData->MinIndex;
3085 }
3086 }
3087
3088 hr = pDevice9If->DrawIndexedPrimitiveUP(pData->PrimitiveType,
3089 0,
3090 pData->NumVertices,
3091 pData->PrimitiveCount,
3092 pu8IndicesStartConv,
3093 dwIndicesSize == 2 ? D3DFMT_INDEX16 : D3DFMT_INDEX32,
3094 pu8VertexStart,
3095 cbVertexStride);
3096
3097 if (SUCCEEDED(hr))
3098 hr = S_OK;
3099 else
3100 WARN(("DrawIndexedPrimitiveUP failed hr = 0x%x", hr));
3101
3102 RTMemFree(pu8IndicesStartConv);
3103
3104 /* Following any IDirect3DDevice9::DrawIndexedPrimitiveUP call, the stream 0 settings,
3105 * referenced by IDirect3DDevice9::GetStreamSource, are set to NULL. Also, the index
3106 * buffer setting for IDirect3DDevice9::SetIndices is set to NULL.
3107 */
3108 if (pDevice->aStreamSource[0])
3109 {
3110 HRESULT tmpHr = pDevice9If->SetStreamSource(0, (IDirect3DVertexBuffer9*)pDevice->aStreamSource[0]->pD3DIf, pDevice->StreamSourceInfo[0].uiOffset, pDevice->StreamSourceInfo[0].uiStride);
3111 if(!SUCCEEDED(tmpHr))
3112 WARN(("SetStreamSource failed hr = 0x%x", tmpHr));
3113 }
3114
3115 if (pDevice->IndiciesInfo.pIndicesAlloc)
3116 {
3117 HRESULT tmpHr = pDevice9If->SetIndices((IDirect3DIndexBuffer9*)pDevice->IndiciesInfo.pIndicesAlloc->pD3DIf);
3118 if(!SUCCEEDED(tmpHr))
3119 WARN(("SetIndices failed hr = 0x%x", tmpHr));
3120 }
3121 }
3122 else
3123 {
3124 hr = E_OUTOFMEMORY;
3125 }
3126 }
3127
3128 vboxWddmDalCheckAddOnDraw(pDevice);
3129 vboxVDbgPrintF(("<== "__FUNCTION__", hDevice(0x%p)\n", hDevice));
3130 return hr;
3131}
3132
3133AssertCompile(sizeof (D3DDDIBOX) == sizeof (VBOXBOX3D));
3134AssertCompile(RT_SIZEOFMEMB(D3DDDIBOX, Left) == RT_SIZEOFMEMB(VBOXBOX3D, Left));
3135AssertCompile(RT_SIZEOFMEMB(D3DDDIBOX, Top) == RT_SIZEOFMEMB(VBOXBOX3D, Top));
3136AssertCompile(RT_SIZEOFMEMB(D3DDDIBOX, Right) == RT_SIZEOFMEMB(VBOXBOX3D, Right));
3137AssertCompile(RT_SIZEOFMEMB(D3DDDIBOX, Bottom) == RT_SIZEOFMEMB(VBOXBOX3D, Bottom));
3138AssertCompile(RT_SIZEOFMEMB(D3DDDIBOX, Front) == RT_SIZEOFMEMB(VBOXBOX3D, Front));
3139AssertCompile(RT_SIZEOFMEMB(D3DDDIBOX, Back) == RT_SIZEOFMEMB(VBOXBOX3D, Back));
3140
3141AssertCompile(RT_OFFSETOF(D3DDDIBOX, Left) == RT_OFFSETOF(VBOXBOX3D, Left));
3142AssertCompile(RT_OFFSETOF(D3DDDIBOX, Top) == RT_OFFSETOF(VBOXBOX3D, Top));
3143AssertCompile(RT_OFFSETOF(D3DDDIBOX, Right) == RT_OFFSETOF(VBOXBOX3D, Right));
3144AssertCompile(RT_OFFSETOF(D3DDDIBOX, Bottom) == RT_OFFSETOF(VBOXBOX3D, Bottom));
3145AssertCompile(RT_OFFSETOF(D3DDDIBOX, Front) == RT_OFFSETOF(VBOXBOX3D, Front));
3146AssertCompile(RT_OFFSETOF(D3DDDIBOX, Back) == RT_OFFSETOF(VBOXBOX3D, Back));
3147
3148static HRESULT APIENTRY vboxWddmDDevVolBlt(HANDLE hDevice, CONST D3DDDIARG_VOLUMEBLT* pData)
3149{
3150 VBOXDISP_DDI_PROLOGUE_DEV(hDevice);
3151 vboxVDbgPrintF(("==> "__FUNCTION__", hDevice(0x%p)\n", hDevice));
3152 PVBOXWDDMDISP_DEVICE pDevice = (PVBOXWDDMDISP_DEVICE)hDevice;
3153 Assert(pDevice);
3154 VBOXDISPCRHGSMI_SCOPE_SET_DEV(pDevice);
3155 IDirect3DDevice9 * pDevice9If = VBOXDISP_D3DEV(pDevice);
3156 PVBOXWDDMDISP_RESOURCE pDstRc = (PVBOXWDDMDISP_RESOURCE)pData->hDstResource;
3157 PVBOXWDDMDISP_RESOURCE pSrcRc = (PVBOXWDDMDISP_RESOURCE)pData->hSrcResource;
3158 /* requirements for D3DDevice9::UpdateTexture */
3159 Assert(pDstRc->aAllocations[0].enmD3DIfType == VBOXDISP_D3DIFTYPE_VOLUME_TEXTURE);
3160 Assert(pSrcRc->aAllocations[0].enmD3DIfType == VBOXDISP_D3DIFTYPE_VOLUME_TEXTURE);
3161 IDirect3DVolumeTexture9 * pSrcTex = (IDirect3DVolumeTexture9*)pSrcRc->aAllocations[0].pD3DIf;
3162 IDirect3DVolumeTexture9 * pDstTex = (IDirect3DVolumeTexture9*)pDstRc->aAllocations[0].pD3DIf;
3163 VBOXPOINT3D Point;
3164 Point.x = pData->DstX;
3165 Point.y = pData->DstY;
3166 Point.z = pData->DstZ;
3167
3168 HRESULT hr = pDevice->pAdapter->D3D.D3D.pfnVBoxWineExD3DDev9VolTexBlt((IDirect3DDevice9Ex*)pDevice9If, pSrcTex, pDstTex,
3169 (VBOXBOX3D*)&pData->SrcBox, &Point);
3170 if (FAILED(hr))
3171 WARN(("pfnVBoxWineExD3DDev9VolTexBlt failed hr 0x%x", hr));
3172 else
3173 hr = S_OK;
3174 vboxVDbgPrintF(("<== "__FUNCTION__", hDevice(0x%p)\n", hDevice));
3175 return hr;;
3176}
3177
3178static HRESULT APIENTRY vboxWddmDDevBufBlt(HANDLE hDevice, CONST D3DDDIARG_BUFFERBLT* pData)
3179{
3180 VBOXDISP_DDI_PROLOGUE_DEV(hDevice);
3181 vboxVDbgPrintF(("<== "__FUNCTION__", hDevice(0x%p)\n", hDevice));
3182 PVBOXWDDMDISP_DEVICE pDevice = (PVBOXWDDMDISP_DEVICE)hDevice;
3183 Assert(pDevice);
3184 VBOXDISPCRHGSMI_SCOPE_SET_DEV(pDevice);
3185 Assert(0);
3186// @todo: vboxWddmDalCheckAdd(pDevice);
3187 vboxVDbgPrintF(("==> "__FUNCTION__", hDevice(0x%p)\n", hDevice));
3188 return E_FAIL;
3189}
3190
3191static HRESULT APIENTRY vboxWddmDDevTexBlt(HANDLE hDevice, CONST D3DDDIARG_TEXBLT* pData)
3192{
3193 VBOXDISP_DDI_PROLOGUE_DEV(hDevice);
3194 vboxVDbgPrintF(("==> "__FUNCTION__", hDevice(0x%p)\n", hDevice));
3195 PVBOXWDDMDISP_DEVICE pDevice = (PVBOXWDDMDISP_DEVICE)hDevice;
3196 Assert(pDevice);
3197 VBOXDISPCRHGSMI_SCOPE_SET_DEV(pDevice);
3198 IDirect3DDevice9 * pDevice9If = VBOXDISP_D3DEV(pDevice);
3199 PVBOXWDDMDISP_RESOURCE pDstRc = (PVBOXWDDMDISP_RESOURCE)pData->hDstResource;
3200 PVBOXWDDMDISP_RESOURCE pSrcRc = (PVBOXWDDMDISP_RESOURCE)pData->hSrcResource;
3201 /* requirements for D3DDevice9::UpdateTexture */
3202 Assert(pDstRc->aAllocations[0].enmD3DIfType == VBOXDISP_D3DIFTYPE_TEXTURE
3203 || pDstRc->aAllocations[0].enmD3DIfType == VBOXDISP_D3DIFTYPE_CUBE_TEXTURE
3204 || pDstRc->aAllocations[0].enmD3DIfType == VBOXDISP_D3DIFTYPE_VOLUME_TEXTURE);
3205 Assert(pSrcRc->aAllocations[0].enmD3DIfType == VBOXDISP_D3DIFTYPE_TEXTURE
3206 || pSrcRc->aAllocations[0].enmD3DIfType == VBOXDISP_D3DIFTYPE_CUBE_TEXTURE
3207 || pDstRc->aAllocations[0].enmD3DIfType == VBOXDISP_D3DIFTYPE_VOLUME_TEXTURE);
3208 Assert(pSrcRc->aAllocations[0].enmD3DIfType == pDstRc->aAllocations[0].enmD3DIfType);
3209 Assert(pSrcRc->RcDesc.enmPool == D3DDDIPOOL_SYSTEMMEM);
3210 Assert(pDstRc->RcDesc.enmPool != D3DDDIPOOL_SYSTEMMEM);
3211 HRESULT hr = S_OK;
3212 VBOXVDBG_CHECK_SMSYNC(pDstRc);
3213 VBOXVDBG_CHECK_SMSYNC(pSrcRc);
3214
3215 if (pSrcRc->aAllocations[0].SurfDesc.d3dWidth == pDstRc->aAllocations[0].SurfDesc.d3dWidth
3216 && pSrcRc->aAllocations[0].SurfDesc.height == pDstRc->aAllocations[0].SurfDesc.height
3217 && pSrcRc->RcDesc.enmFormat == pDstRc->RcDesc.enmFormat
3218 &&pData->DstPoint.x == 0 && pData->DstPoint.y == 0
3219 && pData->SrcRect.left == 0 && pData->SrcRect.top == 0
3220 && pData->SrcRect.right - pData->SrcRect.left == pSrcRc->aAllocations[0].SurfDesc.width
3221 && pData->SrcRect.bottom - pData->SrcRect.top == pSrcRc->aAllocations[0].SurfDesc.height)
3222 {
3223 IDirect3DBaseTexture9 *pD3DIfSrcTex = (IDirect3DBaseTexture9*)pSrcRc->aAllocations[0].pD3DIf;
3224 IDirect3DBaseTexture9 *pD3DIfDstTex = (IDirect3DBaseTexture9*)pDstRc->aAllocations[0].pD3DIf;
3225 Assert(pD3DIfSrcTex);
3226 Assert(pD3DIfDstTex);
3227 VBOXVDBG_CHECK_TEXBLT(
3228 hr = pDevice9If->UpdateTexture(pD3DIfSrcTex, pD3DIfDstTex); Assert(hr == S_OK),
3229 pSrcRc,
3230 &pData->SrcRect,
3231 pDstRc,
3232 &pData->DstPoint);
3233 }
3234 else
3235 {
3236 Assert(pDstRc->aAllocations[0].enmD3DIfType != VBOXDISP_D3DIFTYPE_VOLUME_TEXTURE);
3237 Assert(pSrcRc->aAllocations[0].enmD3DIfType != VBOXDISP_D3DIFTYPE_VOLUME_TEXTURE);
3238
3239 IDirect3DSurface9 *pSrcSurfIf = NULL;
3240 IDirect3DSurface9 *pDstSurfIf = NULL;
3241 hr = VBoxD3DIfSurfGet(pDstRc, 0, &pDstSurfIf);
3242 Assert(hr == S_OK);
3243 if (hr == S_OK)
3244 {
3245 hr = VBoxD3DIfSurfGet(pSrcRc, 0, &pSrcSurfIf);
3246 Assert(hr == S_OK);
3247 if (hr == S_OK)
3248 {
3249 RECT DstRect;
3250 vboxWddmRectMoved(&DstRect, &pData->SrcRect, pData->DstPoint.x, pData->DstPoint.y);
3251#ifdef DEBUG
3252 RECT tstRect = {0,0, pDstRc->aAllocations[0].SurfDesc.width, pDstRc->aAllocations[0].SurfDesc.height};
3253 Assert(vboxWddmRectIsCoveres(&tstRect, &DstRect));
3254#endif
3255 VBOXVDBG_CHECK_TEXBLT(
3256 hr = pDevice9If->StretchRect(pSrcSurfIf, &pData->SrcRect, pDstSurfIf, &DstRect, D3DTEXF_NONE); Assert(hr == S_OK),
3257 pSrcRc,
3258 &pData->SrcRect,
3259 pDstRc,
3260 &pData->DstPoint);
3261 pSrcSurfIf->Release();
3262 }
3263 pDstSurfIf->Release();
3264 }
3265 }
3266
3267 vboxWddmDalCheckAddRc(pDevice, pDstRc, TRUE);
3268 vboxWddmDalCheckAddRc(pDevice, pSrcRc, FALSE);
3269
3270 vboxVDbgPrintF(("<== "__FUNCTION__", hDevice(0x%p), hr(0x%x)\n", hDevice, hr));
3271 return hr;
3272}
3273
3274static HRESULT APIENTRY vboxWddmDDevStateSet(HANDLE hDevice, D3DDDIARG_STATESET* pData)
3275{
3276 VBOXDISP_DDI_PROLOGUE_DEV(hDevice);
3277 vboxVDbgPrintF(("<== "__FUNCTION__", hDevice(0x%p)\n", hDevice));
3278 PVBOXWDDMDISP_DEVICE pDevice = (PVBOXWDDMDISP_DEVICE)hDevice;
3279 Assert(pDevice);
3280 VBOXDISPCRHGSMI_SCOPE_SET_DEV(pDevice);
3281 Assert(0);
3282 vboxVDbgPrintF(("==> "__FUNCTION__", hDevice(0x%p)\n", hDevice));
3283 return E_FAIL;
3284}
3285static HRESULT APIENTRY vboxWddmDDevSetPriority(HANDLE hDevice, CONST D3DDDIARG_SETPRIORITY* pData)
3286{
3287 VBOXDISP_DDI_PROLOGUE_DEV(hDevice);
3288// PVBOXWDDMDISP_DEVICE pDevice = (PVBOXWDDMDISP_DEVICE)hDevice;
3289// Assert(pDevice);
3290// VBOXDISPCRHGSMI_SCOPE_SET_DEV(pDevice);
3291 vboxVDbgPrintF(("<== "__FUNCTION__", hDevice(0x%p)\n", hDevice));
3292 vboxVDbgPrintF(("==> "__FUNCTION__", hDevice(0x%p)\n", hDevice));
3293 return S_OK;
3294}
3295AssertCompile(sizeof (RECT) == sizeof (D3DRECT));
3296AssertCompile(RT_SIZEOFMEMB(RECT, left) == RT_SIZEOFMEMB(D3DRECT, x1));
3297AssertCompile(RT_SIZEOFMEMB(RECT, right) == RT_SIZEOFMEMB(D3DRECT, x2));
3298AssertCompile(RT_SIZEOFMEMB(RECT, top) == RT_SIZEOFMEMB(D3DRECT, y1));
3299AssertCompile(RT_SIZEOFMEMB(RECT, bottom) == RT_SIZEOFMEMB(D3DRECT, y2));
3300AssertCompile(RT_OFFSETOF(RECT, left) == RT_OFFSETOF(D3DRECT, x1));
3301AssertCompile(RT_OFFSETOF(RECT, right) == RT_OFFSETOF(D3DRECT, x2));
3302AssertCompile(RT_OFFSETOF(RECT, top) == RT_OFFSETOF(D3DRECT, y1));
3303AssertCompile(RT_OFFSETOF(RECT, bottom) == RT_OFFSETOF(D3DRECT, y2));
3304
3305static HRESULT APIENTRY vboxWddmDDevClear(HANDLE hDevice, CONST D3DDDIARG_CLEAR* pData, UINT NumRect, CONST RECT* pRect)
3306{
3307 VBOXDISP_DDI_PROLOGUE_DEV(hDevice);
3308 vboxVDbgPrintF(("==> "__FUNCTION__", hDevice(0x%p)\n", hDevice));
3309 PVBOXWDDMDISP_DEVICE pDevice = (PVBOXWDDMDISP_DEVICE)hDevice;
3310 Assert(pDevice);
3311 VBOXDISPCRHGSMI_SCOPE_SET_DEV(pDevice);
3312 IDirect3DDevice9 * pDevice9If = VBOXDISP_D3DEV(pDevice);
3313 HRESULT hr = pDevice9If->Clear(NumRect, (D3DRECT*)pRect /* see AssertCompile above */,
3314 pData->Flags,
3315 pData->FillColor,
3316 pData->FillDepth,
3317 pData->FillStencil);
3318 if (SUCCEEDED(hr))
3319 {
3320 if (pData->Flags & D3DCLEAR_TARGET)
3321 vboxWddmDalCheckAddRTs(pDevice);
3322 if ((pData->Flags & D3DCLEAR_STENCIL)
3323 || (pData->Flags & D3DCLEAR_ZBUFFER))
3324 vboxWddmDalCheckAddDepthStencil(pDevice);
3325 }
3326 else
3327 WARN(("Clear failed %#x", hr));
3328
3329 vboxVDbgPrintF(("<== "__FUNCTION__", hDevice(0x%p), hr(0x%x)\n", hDevice, hr));
3330 return hr;
3331}
3332static HRESULT APIENTRY vboxWddmDDevUpdatePalette(HANDLE hDevice, CONST D3DDDIARG_UPDATEPALETTE* pData, CONST PALETTEENTRY* pPaletteData)
3333{
3334 VBOXDISP_DDI_PROLOGUE_DEV(hDevice);
3335 vboxVDbgPrintF(("<== "__FUNCTION__", hDevice(0x%p)\n", hDevice));
3336 PVBOXWDDMDISP_DEVICE pDevice = (PVBOXWDDMDISP_DEVICE)hDevice;
3337 Assert(pDevice);
3338 VBOXDISPCRHGSMI_SCOPE_SET_DEV(pDevice);
3339 Assert(0);
3340 vboxVDbgPrintF(("==> "__FUNCTION__", hDevice(0x%p)\n", hDevice));
3341 return E_FAIL;
3342}
3343
3344static HRESULT APIENTRY vboxWddmDDevSetPalette(HANDLE hDevice, CONST D3DDDIARG_SETPALETTE* pData)
3345{
3346 VBOXDISP_DDI_PROLOGUE_DEV(hDevice);
3347 vboxVDbgPrintF(("<== "__FUNCTION__", hDevice(0x%p)\n", hDevice));
3348 PVBOXWDDMDISP_DEVICE pDevice = (PVBOXWDDMDISP_DEVICE)hDevice;
3349 Assert(pDevice);
3350 VBOXDISPCRHGSMI_SCOPE_SET_DEV(pDevice);
3351 Assert(0);
3352 vboxVDbgPrintF(("==> "__FUNCTION__", hDevice(0x%p)\n", hDevice));
3353 return E_FAIL;
3354}
3355
3356static HRESULT APIENTRY vboxWddmDDevSetVertexShaderConst(HANDLE hDevice, CONST D3DDDIARG_SETVERTEXSHADERCONST* pData , CONST VOID* pRegisters)
3357{
3358 VBOXDISP_DDI_PROLOGUE_DEV(hDevice);
3359 vboxVDbgPrintF(("==> "__FUNCTION__", hDevice(0x%p)\n", hDevice));
3360 PVBOXWDDMDISP_DEVICE pDevice = (PVBOXWDDMDISP_DEVICE)hDevice;
3361 Assert(pDevice);
3362 VBOXDISPCRHGSMI_SCOPE_SET_DEV(pDevice);
3363 IDirect3DDevice9 * pDevice9If = VBOXDISP_D3DEV(pDevice);
3364 HRESULT hr = pDevice9If->SetVertexShaderConstantF(
3365 pData->Register,
3366 (CONST float*)pRegisters,
3367 pData->Count);
3368 Assert(hr == S_OK);
3369 vboxVDbgPrintF(("<== "__FUNCTION__", hDevice(0x%p), hr(0x%x)\n", hDevice, hr));
3370 return hr;
3371}
3372static HRESULT APIENTRY vboxWddmDDevMultiplyTransform(HANDLE hDevice, CONST D3DDDIARG_MULTIPLYTRANSFORM* pData)
3373{
3374 VBOXDISP_DDI_PROLOGUE_DEV(hDevice);
3375 vboxVDbgPrintF(("<== "__FUNCTION__", hDevice(0x%p)\n", hDevice));
3376 PVBOXWDDMDISP_DEVICE pDevice = (PVBOXWDDMDISP_DEVICE)hDevice;
3377 Assert(pDevice);
3378 VBOXDISPCRHGSMI_SCOPE_SET_DEV(pDevice);
3379 Assert(0);
3380 vboxVDbgPrintF(("==> "__FUNCTION__", hDevice(0x%p)\n", hDevice));
3381 return E_FAIL;
3382}
3383static HRESULT APIENTRY vboxWddmDDevSetTransform(HANDLE hDevice, CONST D3DDDIARG_SETTRANSFORM* pData)
3384{
3385 VBOXDISP_DDI_PROLOGUE_DEV(hDevice);
3386 vboxVDbgPrintF(("<== "__FUNCTION__", hDevice(0x%p)\n", hDevice));
3387 PVBOXWDDMDISP_DEVICE pDevice = (PVBOXWDDMDISP_DEVICE)hDevice;
3388 Assert(pDevice);
3389 VBOXDISPCRHGSMI_SCOPE_SET_DEV(pDevice);
3390 Assert(0);
3391 vboxVDbgPrintF(("==> "__FUNCTION__", hDevice(0x%p)\n", hDevice));
3392 return E_FAIL;
3393}
3394static HRESULT APIENTRY vboxWddmDDevSetViewport(HANDLE hDevice, CONST D3DDDIARG_VIEWPORTINFO* pData)
3395{
3396 VBOXDISP_DDI_PROLOGUE_DEV(hDevice);
3397 vboxVDbgPrintF(("==> "__FUNCTION__", hDevice(0x%p)\n", hDevice));
3398 PVBOXWDDMDISP_DEVICE pDevice = (PVBOXWDDMDISP_DEVICE)hDevice;
3399 Assert(pDevice);
3400 VBOXDISPCRHGSMI_SCOPE_SET_DEV(pDevice);
3401
3402 IDirect3DDevice9 * pDevice9If = VBOXDISP_D3DEV(pDevice);
3403 pDevice->ViewPort.X = pData->X;
3404 pDevice->ViewPort.Y = pData->Y;
3405 pDevice->ViewPort.Width = pData->Width;
3406 pDevice->ViewPort.Height = pData->Height;
3407 HRESULT hr = pDevice9If->SetViewport(&pDevice->ViewPort);
3408 Assert(hr == S_OK);
3409 vboxVDbgPrintF(("<== "__FUNCTION__", hDevice(0x%p), hr(0x%x)\n", hDevice, hr));
3410 return hr;
3411}
3412static HRESULT APIENTRY vboxWddmDDevSetZRange(HANDLE hDevice, CONST D3DDDIARG_ZRANGE* pData)
3413{
3414 VBOXDISP_DDI_PROLOGUE_DEV(hDevice);
3415 vboxVDbgPrintF(("==> "__FUNCTION__", hDevice(0x%p)\n", hDevice));
3416 PVBOXWDDMDISP_DEVICE pDevice = (PVBOXWDDMDISP_DEVICE)hDevice;
3417 Assert(pDevice);
3418 VBOXDISPCRHGSMI_SCOPE_SET_DEV(pDevice);
3419
3420 IDirect3DDevice9 * pDevice9If = VBOXDISP_D3DEV(pDevice);
3421 pDevice->ViewPort.MinZ = pData->MinZ;
3422 pDevice->ViewPort.MaxZ = pData->MaxZ;
3423 HRESULT hr = pDevice9If->SetViewport(&pDevice->ViewPort);
3424 Assert(hr == S_OK);
3425 vboxVDbgPrintF(("<== "__FUNCTION__", hDevice(0x%p), hr(0x%x)\n", hDevice, hr));
3426 return hr;
3427}
3428static HRESULT APIENTRY vboxWddmDDevSetMaterial(HANDLE hDevice, CONST D3DDDIARG_SETMATERIAL* pData)
3429{
3430 VBOXDISP_DDI_PROLOGUE_DEV(hDevice);
3431 vboxVDbgPrintF(("<== "__FUNCTION__", hDevice(0x%p)\n", hDevice));
3432 PVBOXWDDMDISP_DEVICE pDevice = (PVBOXWDDMDISP_DEVICE)hDevice;
3433 Assert(pDevice);
3434 VBOXDISPCRHGSMI_SCOPE_SET_DEV(pDevice);
3435 Assert(0);
3436 vboxVDbgPrintF(("==> "__FUNCTION__", hDevice(0x%p)\n", hDevice));
3437 return E_FAIL;
3438}
3439static HRESULT APIENTRY vboxWddmDDevSetLight(HANDLE hDevice, CONST D3DDDIARG_SETLIGHT* pData, CONST D3DDDI_LIGHT* pLightProperties)
3440{
3441 VBOXDISP_DDI_PROLOGUE_DEV(hDevice);
3442 vboxVDbgPrintF(("<== "__FUNCTION__", hDevice(0x%p)\n", hDevice));
3443 PVBOXWDDMDISP_DEVICE pDevice = (PVBOXWDDMDISP_DEVICE)hDevice;
3444 Assert(pDevice);
3445 VBOXDISPCRHGSMI_SCOPE_SET_DEV(pDevice);
3446 Assert(0);
3447 vboxVDbgPrintF(("==> "__FUNCTION__", hDevice(0x%p)\n", hDevice));
3448 return E_FAIL;
3449}
3450static HRESULT APIENTRY vboxWddmDDevCreateLight(HANDLE hDevice, CONST D3DDDIARG_CREATELIGHT* pData)
3451{
3452 VBOXDISP_DDI_PROLOGUE_DEV(hDevice);
3453 vboxVDbgPrintF(("<== "__FUNCTION__", hDevice(0x%p)\n", hDevice));
3454 PVBOXWDDMDISP_DEVICE pDevice = (PVBOXWDDMDISP_DEVICE)hDevice;
3455 Assert(pDevice);
3456 VBOXDISPCRHGSMI_SCOPE_SET_DEV(pDevice);
3457 Assert(0);
3458 vboxVDbgPrintF(("==> "__FUNCTION__", hDevice(0x%p)\n", hDevice));
3459 return E_FAIL;
3460}
3461static HRESULT APIENTRY vboxWddmDDevDestroyLight(HANDLE hDevice, CONST D3DDDIARG_DESTROYLIGHT* pData)
3462{
3463 VBOXDISP_DDI_PROLOGUE_DEV(hDevice);
3464 vboxVDbgPrintF(("<== "__FUNCTION__", hDevice(0x%p)\n", hDevice));
3465 PVBOXWDDMDISP_DEVICE pDevice = (PVBOXWDDMDISP_DEVICE)hDevice;
3466 Assert(pDevice);
3467 VBOXDISPCRHGSMI_SCOPE_SET_DEV(pDevice);
3468 Assert(0);
3469 vboxVDbgPrintF(("==> "__FUNCTION__", hDevice(0x%p)\n", hDevice));
3470 return E_FAIL;
3471}
3472static HRESULT APIENTRY vboxWddmDDevSetClipPlane(HANDLE hDevice, CONST D3DDDIARG_SETCLIPPLANE* pData)
3473{
3474 VBOXDISP_DDI_PROLOGUE_DEV(hDevice);
3475 vboxVDbgPrintF(("==> "__FUNCTION__", hDevice(0x%p)\n", hDevice));
3476 PVBOXWDDMDISP_DEVICE pDevice = (PVBOXWDDMDISP_DEVICE)hDevice;
3477 Assert(pDevice);
3478 VBOXDISPCRHGSMI_SCOPE_SET_DEV(pDevice);
3479
3480 IDirect3DDevice9 * pDevice9If = VBOXDISP_D3DEV(pDevice);
3481 HRESULT hr = pDevice9If->SetClipPlane(pData->Index, pData->Plane);
3482 Assert(hr == S_OK);
3483 vboxVDbgPrintF(("<== "__FUNCTION__", hDevice(0x%p), hr(0x%x)\n", hDevice, hr));
3484 return hr;
3485}
3486
3487static HRESULT APIENTRY vboxWddmDDevGetInfo(HANDLE hDevice, UINT DevInfoID, VOID* pDevInfoStruct, UINT DevInfoSize)
3488{
3489 VBOXDISP_DDI_PROLOGUE_DEV(hDevice);
3490 vboxVDbgPrintF(("==> "__FUNCTION__", hDevice(0x%p)\n", hDevice));
3491// PVBOXWDDMDISP_DEVICE pDevice = (PVBOXWDDMDISP_DEVICE)hDevice;
3492// Assert(pDevice);
3493// VBOXDISPCRHGSMI_SCOPE_SET_DEV(pDevice);
3494 HRESULT hr = S_OK;
3495 switch (DevInfoID)
3496 {
3497 case D3DDDIDEVINFOID_VCACHE:
3498 {
3499 Assert(DevInfoSize == sizeof (D3DDDIDEVINFO_VCACHE));
3500 if (DevInfoSize == sizeof (D3DDDIDEVINFO_VCACHE))
3501 {
3502 D3DDDIDEVINFO_VCACHE *pVCache = (D3DDDIDEVINFO_VCACHE*)pDevInfoStruct;
3503 pVCache->Pattern = MAKEFOURCC('C', 'A', 'C', 'H');
3504 pVCache->OptMethod = 0 /* D3DXMESHOPT_STRIPREORDER */;
3505 pVCache->CacheSize = 0;
3506 pVCache->MagicNumber = 0;
3507 }
3508 else
3509 hr = E_INVALIDARG;
3510 break;
3511 }
3512 default:
3513 Assert(0);
3514 hr = E_NOTIMPL;
3515 }
3516 vboxVDbgPrintF(("<== "__FUNCTION__", hDevice(0x%p), hr(0x%x)\n", hDevice, hr));
3517 return hr;
3518}
3519
3520AssertCompile(sizeof (D3DDDIBOX) == sizeof (D3DBOX));
3521AssertCompile(RT_SIZEOFMEMB(D3DDDIBOX, Left) == RT_SIZEOFMEMB(D3DBOX, Left));
3522AssertCompile(RT_SIZEOFMEMB(D3DDDIBOX, Top) == RT_SIZEOFMEMB(D3DBOX, Top));
3523AssertCompile(RT_SIZEOFMEMB(D3DDDIBOX, Right) == RT_SIZEOFMEMB(D3DBOX, Right));
3524AssertCompile(RT_SIZEOFMEMB(D3DDDIBOX, Bottom) == RT_SIZEOFMEMB(D3DBOX, Bottom));
3525AssertCompile(RT_SIZEOFMEMB(D3DDDIBOX, Front) == RT_SIZEOFMEMB(D3DBOX, Front));
3526AssertCompile(RT_SIZEOFMEMB(D3DDDIBOX, Back) == RT_SIZEOFMEMB(D3DBOX, Back));
3527
3528AssertCompile(RT_OFFSETOF(D3DDDIBOX, Left) == RT_OFFSETOF(D3DBOX, Left));
3529AssertCompile(RT_OFFSETOF(D3DDDIBOX, Top) == RT_OFFSETOF(D3DBOX, Top));
3530AssertCompile(RT_OFFSETOF(D3DDDIBOX, Right) == RT_OFFSETOF(D3DBOX, Right));
3531AssertCompile(RT_OFFSETOF(D3DDDIBOX, Bottom) == RT_OFFSETOF(D3DBOX, Bottom));
3532AssertCompile(RT_OFFSETOF(D3DDDIBOX, Front) == RT_OFFSETOF(D3DBOX, Front));
3533AssertCompile(RT_OFFSETOF(D3DDDIBOX, Back) == RT_OFFSETOF(D3DBOX, Back));
3534
3535static HRESULT APIENTRY vboxWddmDDevLock(HANDLE hDevice, D3DDDIARG_LOCK* pData)
3536{
3537 VBOXDISP_DDI_PROLOGUE_DEV(hDevice);
3538 vboxVDbgPrintF(("==> "__FUNCTION__", hDevice(0x%p)\n", hDevice));
3539 PVBOXWDDMDISP_DEVICE pDevice = (PVBOXWDDMDISP_DEVICE)hDevice;
3540 Assert(pDevice);
3541 VBOXDISPCRHGSMI_SCOPE_SET_DEV(pDevice);
3542 PVBOXWDDMDISP_RESOURCE pRc = (PVBOXWDDMDISP_RESOURCE)pData->hResource;
3543 if (pData->SubResourceIndex >= pRc->cAllocations)
3544 return E_INVALIDARG;
3545 PVBOXWDDMDISP_ALLOCATION pAlloc = &pRc->aAllocations[pData->SubResourceIndex];
3546 Assert(pData->SubResourceIndex < pRc->cAllocations);
3547
3548 HRESULT hr = S_OK;
3549
3550 if (VBOXDISPMODE_IS_3D(pDevice->pAdapter))
3551 {
3552// Assert(pRc != pScreen->pRenderTargetRc || pScreen->iRenderTargetFrontBuf != pData->SubResourceIndex);
3553#ifdef VBOXWDDMDISP_DAL_CHECK_LOCK
3554 hr = vboxWddmDalCheckLock(pDevice, pAlloc, pData->Flags);
3555 if (!SUCCEEDED(hr))
3556 {
3557 WARN(("vboxWddmDalCheckLock failed %#x", hr));
3558 return hr;
3559 }
3560#endif
3561
3562 if (pRc->aAllocations[0].enmD3DIfType == VBOXDISP_D3DIFTYPE_TEXTURE
3563 || pRc->aAllocations[0].enmD3DIfType == VBOXDISP_D3DIFTYPE_CUBE_TEXTURE
3564 || pRc->aAllocations[0].enmD3DIfType == VBOXDISP_D3DIFTYPE_SURFACE)
3565 {
3566 PVBOXWDDMDISP_ALLOCATION pTexAlloc = &pRc->aAllocations[0];
3567 Assert(pData->SubResourceIndex < pRc->cAllocations);
3568 IDirect3DTexture9 *pD3DIfTex = (IDirect3DTexture9*)pTexAlloc->pD3DIf;
3569 IDirect3DCubeTexture9 *pD3DIfCubeTex = (IDirect3DCubeTexture9*)pTexAlloc->pD3DIf;
3570 IDirect3DSurface9 *pD3DIfSurface = (IDirect3DSurface9*)pTexAlloc->pD3DIf;
3571 Assert(pTexAlloc->pD3DIf);
3572 RECT *pRect = NULL;
3573 BOOL fNeedLock = TRUE;
3574 Assert(!pData->Flags.RangeValid);
3575 Assert(!pData->Flags.BoxValid);
3576 if (pData->Flags.AreaValid)
3577 {
3578 pRect = &pData->Area;
3579 }
3580
3581 /* else - we lock the entire texture, pRect == NULL */
3582
3583 if (pAlloc->LockInfo.cLocks)
3584 {
3585 Assert(pAlloc->LockInfo.fFlags.AreaValid == pData->Flags.AreaValid);
3586 if (pAlloc->LockInfo.fFlags.AreaValid && pData->Flags.AreaValid)
3587 {
3588 Assert(pAlloc->LockInfo.Area.left == pData->Area.left);
3589 Assert(pAlloc->LockInfo.Area.top == pData->Area.top);
3590 Assert(pAlloc->LockInfo.Area.right == pData->Area.right);
3591 Assert(pAlloc->LockInfo.Area.bottom == pData->Area.bottom);
3592 }
3593 Assert(pAlloc->LockInfo.LockedRect.pBits);
3594 Assert((pAlloc->LockInfo.fFlags.Value & ~1) == (pData->Flags.Value & ~1)); /* <- 1 is "ReadOnly" flag */
3595
3596 if (pAlloc->LockInfo.fFlags.ReadOnly && !pData->Flags.ReadOnly)
3597 {
3598 switch (pTexAlloc->enmD3DIfType)
3599 {
3600 case VBOXDISP_D3DIFTYPE_TEXTURE:
3601 hr = pD3DIfTex->UnlockRect(pData->SubResourceIndex);
3602 break;
3603 case VBOXDISP_D3DIFTYPE_CUBE_TEXTURE:
3604 hr = pD3DIfCubeTex->UnlockRect(VBOXDISP_CUBEMAP_INDEX_TO_FACE(pRc, pData->SubResourceIndex),
3605 VBOXDISP_CUBEMAP_INDEX_TO_LEVEL(pRc, pData->SubResourceIndex));
3606 break;
3607 case VBOXDISP_D3DIFTYPE_SURFACE:
3608 hr = pD3DIfSurface->UnlockRect();
3609 break;
3610 default:
3611 Assert(0);
3612 break;
3613 }
3614 Assert(hr == S_OK);
3615 }
3616 else
3617 {
3618 fNeedLock = FALSE;
3619 }
3620 }
3621
3622 if (fNeedLock && SUCCEEDED(hr))
3623 {
3624 VBOXVDBG_CHECK_SMSYNC(pRc);
3625
3626 pAlloc->LockInfo.fFlags = pData->Flags;
3627 if (pRect)
3628 {
3629 pAlloc->LockInfo.Area = *pRect;
3630 Assert(pAlloc->LockInfo.fFlags.AreaValid == 1);
3631 }
3632 else
3633 {
3634 Assert(pAlloc->LockInfo.fFlags.AreaValid == 0);
3635 }
3636
3637 switch (pTexAlloc->enmD3DIfType)
3638 {
3639 case VBOXDISP_D3DIFTYPE_TEXTURE:
3640 hr = pD3DIfTex->LockRect(pData->SubResourceIndex,
3641 &pAlloc->LockInfo.LockedRect,
3642 pRect,
3643 vboxDDI2D3DLockFlags(pData->Flags));
3644 break;
3645 case VBOXDISP_D3DIFTYPE_CUBE_TEXTURE:
3646 hr = pD3DIfCubeTex->LockRect(VBOXDISP_CUBEMAP_INDEX_TO_FACE(pRc, pData->SubResourceIndex),
3647 VBOXDISP_CUBEMAP_INDEX_TO_LEVEL(pRc, pData->SubResourceIndex),
3648 &pAlloc->LockInfo.LockedRect,
3649 pRect,
3650 vboxDDI2D3DLockFlags(pData->Flags));
3651 break;
3652 case VBOXDISP_D3DIFTYPE_SURFACE:
3653 hr = pD3DIfSurface->LockRect(&pAlloc->LockInfo.LockedRect,
3654 pRect,
3655 vboxDDI2D3DLockFlags(pData->Flags));
3656 break;
3657 default:
3658 Assert(0);
3659 break;
3660 }
3661
3662 if (FAILED(hr))
3663 {
3664 WARN(("LockRect failed, hr", hr));
3665 }
3666 }
3667
3668 if (SUCCEEDED(hr))
3669 {
3670 ++pAlloc->LockInfo.cLocks;
3671
3672 if (!pData->Flags.NotifyOnly)
3673 {
3674 pData->pSurfData = pAlloc->LockInfo.LockedRect.pBits;
3675 pData->Pitch = pAlloc->LockInfo.LockedRect.Pitch;
3676 pData->SlicePitch = 0;
3677 Assert(pAlloc->SurfDesc.slicePitch == 0);
3678 Assert(!pAlloc->pvMem);
3679 }
3680 else
3681 {
3682 Assert(pAlloc->pvMem);
3683 Assert(pRc->RcDesc.enmPool == D3DDDIPOOL_SYSTEMMEM);
3684 }
3685
3686 VBOXVDBG_DUMP_LOCK_ST(pData);
3687
3688 hr = S_OK;
3689 }
3690 }
3691 else if (pRc->aAllocations[0].enmD3DIfType == VBOXDISP_D3DIFTYPE_VOLUME_TEXTURE)
3692 {
3693 PVBOXWDDMDISP_ALLOCATION pTexAlloc = &pRc->aAllocations[0];
3694 Assert(pData->SubResourceIndex < pRc->cAllocations);
3695 IDirect3DVolumeTexture9 *pD3DIfTex = (IDirect3DVolumeTexture9*)pTexAlloc->pD3DIf;
3696 Assert(pTexAlloc->pD3DIf);
3697 D3DDDIBOX *pBox = NULL;
3698 BOOL fNeedLock = TRUE;
3699 Assert(!pData->Flags.AreaValid);
3700 Assert(!pData->Flags.BoxValid);
3701 if (pData->Flags.BoxValid)
3702 {
3703 pBox = &pData->Box;
3704 }
3705
3706 /* else - we lock the entire texture, pBox == NULL */
3707
3708 if (pAlloc->LockInfo.cLocks)
3709 {
3710 Assert(pAlloc->LockInfo.fFlags.BoxValid == pData->Flags.BoxValid);
3711 if (pAlloc->LockInfo.fFlags.BoxValid && pData->Flags.BoxValid)
3712 {
3713 Assert(pAlloc->LockInfo.Box.Left == pData->Box.Left);
3714 Assert(pAlloc->LockInfo.Box.Top == pData->Box.Top);
3715 Assert(pAlloc->LockInfo.Box.Right == pData->Box.Right);
3716 Assert(pAlloc->LockInfo.Box.Bottom == pData->Box.Bottom);
3717 Assert(pAlloc->LockInfo.Box.Front == pData->Box.Front);
3718 Assert(pAlloc->LockInfo.Box.Back == pData->Box.Back);
3719 }
3720 Assert(pAlloc->LockInfo.LockedBox.pBits);
3721 Assert((pAlloc->LockInfo.fFlags.Value & ~1) == (pData->Flags.Value & ~1)); /* <- 1 is "ReadOnly" flag */
3722
3723 if (pAlloc->LockInfo.fFlags.ReadOnly && !pData->Flags.ReadOnly)
3724 {
3725 hr = pD3DIfTex->UnlockBox(pData->SubResourceIndex);
3726 Assert(hr == S_OK);
3727 }
3728 else
3729 {
3730 fNeedLock = FALSE;
3731 }
3732 }
3733
3734 if (fNeedLock && SUCCEEDED(hr))
3735 {
3736 VBOXVDBG_CHECK_SMSYNC(pRc);
3737
3738 pAlloc->LockInfo.fFlags = pData->Flags;
3739 if (pBox)
3740 {
3741 pAlloc->LockInfo.Box = *pBox;
3742 Assert(pAlloc->LockInfo.fFlags.BoxValid == 1);
3743 }
3744 else
3745 {
3746 Assert(pAlloc->LockInfo.fFlags.BoxValid == 0);
3747 }
3748
3749 hr = pD3DIfTex->LockBox(pData->SubResourceIndex,
3750 &pAlloc->LockInfo.LockedBox,
3751 (D3DBOX*)pBox,
3752 vboxDDI2D3DLockFlags(pData->Flags));
3753 if (FAILED(hr))
3754 {
3755 WARN(("LockRect failed, hr", hr));
3756 }
3757 }
3758
3759 if (SUCCEEDED(hr))
3760 {
3761 ++pAlloc->LockInfo.cLocks;
3762
3763 if (!pData->Flags.NotifyOnly)
3764 {
3765 pData->pSurfData = pAlloc->LockInfo.LockedBox.pBits;
3766 pData->Pitch = pAlloc->LockInfo.LockedBox.RowPitch;
3767 pData->SlicePitch = pAlloc->LockInfo.LockedBox.SlicePitch;
3768 Assert(!pAlloc->pvMem);
3769 }
3770 else
3771 {
3772 Assert(pAlloc->pvMem);
3773 Assert(pRc->RcDesc.enmPool == D3DDDIPOOL_SYSTEMMEM);
3774 }
3775
3776 VBOXVDBG_DUMP_LOCK_ST(pData);
3777
3778 hr = S_OK;
3779 }
3780 }
3781 else if (pRc->aAllocations[0].enmD3DIfType == VBOXDISP_D3DIFTYPE_VERTEXBUFFER)
3782 {
3783 Assert(pData->SubResourceIndex < pRc->cAllocations);
3784 IDirect3DVertexBuffer9 *pD3D9VBuf = (IDirect3DVertexBuffer9*)pAlloc->pD3DIf;
3785 BOOL bLocked = false;
3786 Assert(pD3D9VBuf);
3787 Assert(!pData->Flags.AreaValid);
3788 Assert(!pData->Flags.BoxValid);
3789 D3DDDIRANGE *pRange = NULL;
3790 if (pData->Flags.RangeValid)
3791 {
3792 pRange = &pData->Range;
3793 }
3794
3795 /* else - we lock the entire vertex buffer, pRect == NULL */
3796
3797 if (!pAlloc->LockInfo.cLocks)
3798 {
3799 VBOXVDBG_CHECK_SMSYNC(pRc);
3800 if (!pData->Flags.MightDrawFromLocked || (!pData->Flags.Discard && !pData->Flags.NoOverwrite))
3801 {
3802 hr = pD3D9VBuf->Lock(pRange ? pRange->Offset : 0,
3803 pRange ? pRange->Size : 0,
3804 &pAlloc->LockInfo.LockedRect.pBits,
3805 vboxDDI2D3DLockFlags(pData->Flags));
3806 bLocked = true;
3807 }
3808
3809 Assert(hr == S_OK);
3810 if (hr == S_OK)
3811 {
3812 Assert(pAlloc->SurfDesc.pitch == pAlloc->SurfDesc.width);
3813 pAlloc->LockInfo.LockedRect.Pitch = pAlloc->SurfDesc.pitch;
3814// Assert(pAlloc->LockInfo.fFlags.Value == 0);
3815 pAlloc->LockInfo.fFlags = pData->Flags;
3816 if (pRange)
3817 {
3818 pAlloc->LockInfo.Range = *pRange;
3819 Assert(pAlloc->LockInfo.fFlags.RangeValid == 1);
3820// pAlloc->LockInfo.fFlags.RangeValid = 1;
3821 }
3822 else
3823 {
3824 Assert(pAlloc->LockInfo.fFlags.RangeValid == 0);
3825// pAlloc->LockInfo.fFlags.RangeValid = 0;
3826 }
3827 }
3828 }
3829 else
3830 {
3831 Assert(pAlloc->LockInfo.fFlags.RangeValid == pData->Flags.RangeValid);
3832 if (pAlloc->LockInfo.fFlags.RangeValid && pData->Flags.RangeValid)
3833 {
3834 Assert(pAlloc->LockInfo.Range.Offset == pData->Range.Offset);
3835 Assert(pAlloc->LockInfo.Range.Size == pData->Range.Size);
3836 }
3837 Assert(pAlloc->LockInfo.LockedRect.pBits);
3838 }
3839
3840 if (hr == S_OK)
3841 {
3842 ++pAlloc->LockInfo.cLocks;
3843
3844 if (!pData->Flags.NotifyOnly)
3845 {
3846 pData->pSurfData = pAlloc->LockInfo.LockedRect.pBits;
3847 pData->Pitch = pAlloc->LockInfo.LockedRect.Pitch;
3848 pData->SlicePitch = 0;
3849 Assert(pAlloc->SurfDesc.slicePitch == 0);
3850 Assert(!pAlloc->pvMem);
3851 }
3852 else
3853 {
3854 Assert(pAlloc->pvMem);
3855 Assert(pRc->RcDesc.enmPool == D3DDDIPOOL_SYSTEMMEM);
3856 if (bLocked && !pData->Flags.Discard)
3857 {
3858 RECT r, *pr;
3859 if (pRange)
3860 {
3861 r.top = 0;
3862 r.left = pRange->Offset;
3863 r.bottom = 1;
3864 r.right = pRange->Offset + pRange->Size;
3865 pr = &r;
3866 }
3867 else
3868 pr = NULL;
3869 VBoxD3DIfLockUnlockMemSynch(pAlloc, &pAlloc->LockInfo.LockedRect, pr, false /*bool bToLockInfo*/);
3870 }
3871 }
3872 }
3873 }
3874 else if (pRc->aAllocations[0].enmD3DIfType == VBOXDISP_D3DIFTYPE_INDEXBUFFER)
3875 {
3876 Assert(pData->SubResourceIndex < pRc->cAllocations);
3877 IDirect3DIndexBuffer9 *pD3D9IBuf = (IDirect3DIndexBuffer9*)pAlloc->pD3DIf;
3878 BOOL bLocked = false;
3879 Assert(pD3D9IBuf);
3880 Assert(!pData->Flags.AreaValid);
3881 Assert(!pData->Flags.BoxValid);
3882 D3DDDIRANGE *pRange = NULL;
3883 if (pData->Flags.RangeValid)
3884 {
3885 pRange = &pData->Range;
3886 }
3887
3888 /* else - we lock the entire vertex buffer, pRect == NULL */
3889
3890 if (!pAlloc->LockInfo.cLocks)
3891 {
3892 VBOXVDBG_CHECK_SMSYNC(pRc);
3893 if (!pData->Flags.MightDrawFromLocked || (!pData->Flags.Discard && !pData->Flags.NoOverwrite))
3894 {
3895 hr = pD3D9IBuf->Lock(pRange ? pRange->Offset : 0,
3896 pRange ? pRange->Size : 0,
3897 &pAlloc->LockInfo.LockedRect.pBits,
3898 vboxDDI2D3DLockFlags(pData->Flags));
3899 bLocked = true;
3900 }
3901
3902 Assert(hr == S_OK);
3903 if (hr == S_OK)
3904 {
3905 Assert(pAlloc->SurfDesc.pitch == pAlloc->SurfDesc.width);
3906 pAlloc->LockInfo.LockedRect.Pitch = pAlloc->SurfDesc.pitch;
3907// Assert(pAlloc->LockInfo.fFlags.Value == 0);
3908 pAlloc->LockInfo.fFlags = pData->Flags;
3909 if (pRange)
3910 {
3911 pAlloc->LockInfo.Range = *pRange;
3912 Assert(pAlloc->LockInfo.fFlags.RangeValid == 1);
3913// pAlloc->LockInfo.fFlags.RangeValid = 1;
3914 }
3915 else
3916 {
3917 Assert(pAlloc->LockInfo.fFlags.RangeValid == 0);
3918// pAlloc->LockInfo.fFlags.RangeValid = 0;
3919 }
3920 }
3921 }
3922 else
3923 {
3924 Assert(pAlloc->LockInfo.fFlags.RangeValid == pData->Flags.RangeValid);
3925 if (pAlloc->LockInfo.fFlags.RangeValid && pData->Flags.RangeValid)
3926 {
3927 Assert(pAlloc->LockInfo.Range.Offset == pData->Range.Offset);
3928 Assert(pAlloc->LockInfo.Range.Size == pData->Range.Size);
3929 }
3930 Assert(pAlloc->LockInfo.LockedRect.pBits);
3931 }
3932
3933 if (hr == S_OK)
3934 {
3935 ++pAlloc->LockInfo.cLocks;
3936
3937 if (!pData->Flags.NotifyOnly)
3938 {
3939 pData->pSurfData = pAlloc->LockInfo.LockedRect.pBits;
3940 pData->Pitch = pAlloc->LockInfo.LockedRect.Pitch;
3941 pData->SlicePitch = 0;
3942 Assert(pAlloc->SurfDesc.slicePitch == 0);
3943 Assert(!pAlloc->pvMem);
3944 }
3945 else
3946 {
3947 Assert(pAlloc->pvMem);
3948 Assert(pRc->RcDesc.enmPool == D3DDDIPOOL_SYSTEMMEM);
3949 if (bLocked && !pData->Flags.Discard)
3950 {
3951 RECT r, *pr;
3952 if (pRange)
3953 {
3954 r.top = 0;
3955 r.left = pRange->Offset;
3956 r.bottom = 1;
3957 r.right = pRange->Offset + pRange->Size;
3958 pr = &r;
3959 }
3960 else
3961 pr = NULL;
3962 VBoxD3DIfLockUnlockMemSynch(pAlloc, &pAlloc->LockInfo.LockedRect, pr, false /*bool bToLockInfo*/);
3963 }
3964 }
3965 }
3966 }
3967 else
3968 {
3969 WARN(("not implemented %d", pRc->aAllocations[0].enmD3DIfType));
3970 }
3971
3972#ifdef VBOXWDDMDISP_DAL_CHECK_LOCK
3973 if (!SUCCEEDED(hr))
3974 {
3975 WARN(("lock failed %#x", hr));
3976 vboxWddmDalCheckUnlock(pDevice, pAlloc);
3977 }
3978#endif
3979 }
3980 else /* if !VBOXDISPMODE_IS_3D(pDevice->pAdapter) */
3981 {
3982 if (pAlloc->hAllocation)
3983 {
3984 if (pRc->RcDesc.enmPool != D3DDDIPOOL_SYSTEMMEM)
3985 {
3986 D3DDDICB_LOCK LockData;
3987 LockData.hAllocation = pAlloc->hAllocation;
3988 LockData.PrivateDriverData = 0;
3989 LockData.NumPages = 0;
3990 LockData.pPages = NULL;
3991 LockData.pData = NULL; /* out */
3992 LockData.Flags.Value = 0;
3993 LockData.Flags.Discard = pData->Flags.Discard;
3994 LockData.Flags.DonotWait = pData->Flags.DoNotWait;
3995
3996 uintptr_t offset;
3997 if (pData->Flags.AreaValid)
3998 {
3999 offset = vboxWddmCalcOffXYrd(pData->Area.left, pData->Area.top, pAlloc->SurfDesc.pitch, pAlloc->SurfDesc.format);
4000 }
4001 else if (pData->Flags.RangeValid)
4002 {
4003 offset = pData->Range.Offset;
4004 }
4005 else if (pData->Flags.BoxValid)
4006 {
4007 vboxVDbgPrintF((__FUNCTION__": Implement Box area"));
4008 Assert(0);
4009 }
4010 else
4011 {
4012 offset = 0;
4013 }
4014
4015 hr = pDevice->RtCallbacks.pfnLockCb(pDevice->hDevice, &LockData);
4016 Assert(hr == S_OK || (hr == D3DERR_WASSTILLDRAWING && pData->Flags.DoNotWait));
4017 if (hr == S_OK)
4018 {
4019 pData->pSurfData = ((uint8_t*)LockData.pData) + offset;
4020 pData->Pitch = pAlloc->SurfDesc.pitch;
4021 pData->SlicePitch = pAlloc->SurfDesc.slicePitch;
4022
4023 if (pData->Flags.Discard)
4024 {
4025 /* check if the surface was renamed */
4026 if (LockData.hAllocation)
4027 pAlloc->hAllocation = LockData.hAllocation;
4028 }
4029 }
4030 }
4031 /* else - d3d may create sysmem render targets and call our Present callbacks for those
4032 * to make it work properly we need to create a VRAM surface corresponding to sysmem one
4033 * and copy stuff to VRAM on lock/unlock
4034 *
4035 * so we don't do any locking here, but still track the lock info here
4036 * and do lock-memcopy-unlock to VRAM surface on sysmem surface unlock
4037 * */
4038
4039 if (hr == S_OK)
4040 {
4041 Assert(!pAlloc->LockInfo.cLocks);
4042
4043 if (!pData->Flags.ReadOnly)
4044 {
4045 if (pData->Flags.AreaValid)
4046 vboxWddmDirtyRegionAddRect(&pAlloc->DirtyRegion, &pData->Area);
4047 else
4048 {
4049 Assert(!pData->Flags.RangeValid);
4050 Assert(!pData->Flags.BoxValid);
4051 vboxWddmDirtyRegionAddRect(&pAlloc->DirtyRegion, NULL); /* <- NULL means the entire surface */
4052 }
4053 }
4054
4055 ++pAlloc->LockInfo.cLocks;
4056 }
4057 }
4058 }
4059
4060 vboxVDbgPrintF(("<== "__FUNCTION__", hDevice(0x%p), hr(%d)\n", hDevice, hr));
4061 return hr;
4062}
4063
4064static HRESULT APIENTRY vboxWddmDDevUnlock(HANDLE hDevice, CONST D3DDDIARG_UNLOCK* pData)
4065{
4066 VBOXDISP_DDI_PROLOGUE_DEV(hDevice);
4067 vboxVDbgPrintF(("==> "__FUNCTION__", hDevice(0x%p)\n", hDevice));
4068 PVBOXWDDMDISP_DEVICE pDevice = (PVBOXWDDMDISP_DEVICE)hDevice;
4069 Assert(pDevice);
4070 VBOXDISPCRHGSMI_SCOPE_SET_DEV(pDevice);
4071 PVBOXWDDMDISP_RESOURCE pRc = (PVBOXWDDMDISP_RESOURCE)pData->hResource;
4072 HRESULT hr = S_OK;
4073
4074 Assert(pData->SubResourceIndex < pRc->cAllocations);
4075 if (pData->SubResourceIndex >= pRc->cAllocations)
4076 return E_INVALIDARG;
4077
4078 PVBOXWDDMDISP_ALLOCATION pAlloc = &pRc->aAllocations[pData->SubResourceIndex];
4079
4080 if (VBOXDISPMODE_IS_3D(pDevice->pAdapter))
4081 {
4082 if (pRc->aAllocations[0].enmD3DIfType == VBOXDISP_D3DIFTYPE_TEXTURE
4083 || pRc->aAllocations[0].enmD3DIfType == VBOXDISP_D3DIFTYPE_CUBE_TEXTURE
4084 || pRc->aAllocations[0].enmD3DIfType == VBOXDISP_D3DIFTYPE_SURFACE)
4085 {
4086 Assert(pData->SubResourceIndex < pRc->cAllocations);
4087
4088 VBOXVDBG_DUMP_UNLOCK_ST(pData);
4089
4090 --pAlloc->LockInfo.cLocks;
4091 Assert(pAlloc->LockInfo.cLocks < UINT32_MAX);
4092 if (!pAlloc->LockInfo.cLocks)
4093 {
4094 PVBOXWDDMDISP_ALLOCATION pTexAlloc = &pRc->aAllocations[0];
4095 Assert(pTexAlloc->pD3DIf);
4096 switch (pRc->aAllocations[0].enmD3DIfType)
4097 {
4098 case VBOXDISP_D3DIFTYPE_TEXTURE:
4099 {
4100 IDirect3DTexture9 *pD3DIfTex = (IDirect3DTexture9*)pTexAlloc->pD3DIf;
4101 hr = pD3DIfTex->UnlockRect(pData->SubResourceIndex);
4102 break;
4103 }
4104 case VBOXDISP_D3DIFTYPE_CUBE_TEXTURE:
4105 {
4106 IDirect3DCubeTexture9 *pD3DIfCubeTex = (IDirect3DCubeTexture9*)pTexAlloc->pD3DIf;
4107 hr = pD3DIfCubeTex->UnlockRect(VBOXDISP_CUBEMAP_INDEX_TO_FACE(pRc, pData->SubResourceIndex),
4108 VBOXDISP_CUBEMAP_INDEX_TO_LEVEL(pRc, pData->SubResourceIndex));
4109 break;
4110 }
4111 case VBOXDISP_D3DIFTYPE_SURFACE:
4112 {
4113 IDirect3DSurface9 *pD3DIfSurf = (IDirect3DSurface9*)pTexAlloc->pD3DIf;
4114 hr = pD3DIfSurf->UnlockRect();
4115 break;
4116 }
4117 default:
4118 Assert(0);
4119 break;
4120 }
4121 if (FAILED(hr))
4122 WARN(("UnlockRect failed, hr 0x%x", hr));
4123 VBOXVDBG_CHECK_SMSYNC(pRc);
4124 }
4125 }
4126 else if (pRc->aAllocations[0].enmD3DIfType == VBOXDISP_D3DIFTYPE_VOLUME_TEXTURE)
4127 {
4128 Assert(pData->SubResourceIndex < pRc->cAllocations);
4129
4130 VBOXVDBG_DUMP_UNLOCK_ST(pData);
4131
4132 --pAlloc->LockInfo.cLocks;
4133 Assert(pAlloc->LockInfo.cLocks < UINT32_MAX);
4134 if (!pAlloc->LockInfo.cLocks)
4135 {
4136 PVBOXWDDMDISP_ALLOCATION pTexAlloc = &pRc->aAllocations[0];
4137 Assert(pTexAlloc->pD3DIf);
4138 IDirect3DVolumeTexture9 *pD3DIfTex = (IDirect3DVolumeTexture9*)pTexAlloc->pD3DIf;
4139 hr = pD3DIfTex->UnlockBox(pData->SubResourceIndex);
4140 if (FAILED(hr))
4141 WARN(("UnlockBox failed, hr 0x%x", hr));
4142 VBOXVDBG_CHECK_SMSYNC(pRc);
4143 }
4144 }
4145 else if (pRc->aAllocations[0].enmD3DIfType == VBOXDISP_D3DIFTYPE_VERTEXBUFFER)
4146 {
4147 Assert(pData->SubResourceIndex < pRc->cAllocations);
4148
4149 --pAlloc->LockInfo.cLocks;
4150 Assert(pAlloc->LockInfo.cLocks < UINT32_MAX);
4151 if (!pAlloc->LockInfo.cLocks
4152 && (!pAlloc->LockInfo.fFlags.MightDrawFromLocked
4153 || (!pAlloc->LockInfo.fFlags.Discard && !pAlloc->LockInfo.fFlags.NoOverwrite)))
4154 {
4155// Assert(!pAlloc->LockInfo.cLocks);
4156 IDirect3DVertexBuffer9 *pD3D9VBuf = (IDirect3DVertexBuffer9*)pAlloc->pD3DIf;
4157 Assert(pD3D9VBuf);
4158 /* this is a sysmem texture, update */
4159 if (pAlloc->pvMem && !pAlloc->LockInfo.fFlags.ReadOnly)
4160 {
4161 RECT r, *pr;
4162 if (pAlloc->LockInfo.fFlags.RangeValid)
4163 {
4164 r.top = 0;
4165 r.left = pAlloc->LockInfo.Range.Offset;
4166 r.bottom = 1;
4167 r.right = pAlloc->LockInfo.Range.Offset + pAlloc->LockInfo.Range.Size;
4168 pr = &r;
4169 }
4170 else
4171 pr = NULL;
4172 VBoxD3DIfLockUnlockMemSynch(pAlloc, &pAlloc->LockInfo.LockedRect,
4173 pr,
4174 true /*bool bToLockInfo*/);
4175 }
4176 hr = pD3D9VBuf->Unlock();
4177 Assert(hr == S_OK);
4178 VBOXVDBG_CHECK_SMSYNC(pRc);
4179 }
4180 else
4181 {
4182 Assert(pAlloc->LockInfo.cLocks < UINT32_MAX);
4183 }
4184 }
4185 else if (pRc->aAllocations[0].enmD3DIfType == VBOXDISP_D3DIFTYPE_INDEXBUFFER)
4186 {
4187 Assert(pData->SubResourceIndex < pRc->cAllocations);
4188
4189 --pAlloc->LockInfo.cLocks;
4190 Assert(pAlloc->LockInfo.cLocks < UINT32_MAX);
4191 if (!pAlloc->LockInfo.cLocks
4192 && (!pAlloc->LockInfo.fFlags.MightDrawFromLocked
4193 || (!pAlloc->LockInfo.fFlags.Discard && !pAlloc->LockInfo.fFlags.NoOverwrite)))
4194 {
4195// Assert(!pAlloc->LockInfo.cLocks);
4196 IDirect3DIndexBuffer9 *pD3D9IBuf = (IDirect3DIndexBuffer9*)pAlloc->pD3DIf;
4197 Assert(pD3D9IBuf);
4198 /* this is a sysmem texture, update */
4199 if (pAlloc->pvMem && !pAlloc->LockInfo.fFlags.ReadOnly)
4200 {
4201 RECT r, *pr;
4202 if (pAlloc->LockInfo.fFlags.RangeValid)
4203 {
4204 r.top = 0;
4205 r.left = pAlloc->LockInfo.Range.Offset;
4206 r.bottom = 1;
4207 r.right = pAlloc->LockInfo.Range.Offset + pAlloc->LockInfo.Range.Size;
4208 pr = &r;
4209 }
4210 else
4211 pr = NULL;
4212 VBoxD3DIfLockUnlockMemSynch(pAlloc, &pAlloc->LockInfo.LockedRect,
4213 pr,
4214 true /*bool bToLockInfo*/);
4215 }
4216 hr = pD3D9IBuf->Unlock();
4217 Assert(hr == S_OK);
4218 VBOXVDBG_CHECK_SMSYNC(pRc);
4219 }
4220 else
4221 {
4222 Assert(pAlloc->LockInfo.cLocks < UINT32_MAX);
4223 }
4224 }
4225 else
4226 {
4227 WARN(("Unlock unsupported %d", pRc->aAllocations[0].enmD3DIfType));
4228 }
4229
4230#ifdef VBOXWDDMDISP_DAL_CHECK_LOCK
4231 if (SUCCEEDED(hr))
4232 {
4233 hr = vboxWddmDalCheckUnlock(pDevice, pAlloc);
4234 if (!SUCCEEDED(hr))
4235 WARN(("vboxWddmDalCheckUnlock failed %#x", hr));
4236 }
4237 else
4238 WARN(("unlock failed %#x", hr));
4239#endif
4240 }
4241 else
4242 {
4243 if (pAlloc->hAllocation)
4244 {
4245 BOOL fDoUnlock = FALSE;
4246
4247 Assert(pAlloc->LockInfo.cLocks);
4248 --pAlloc->LockInfo.cLocks;
4249 Assert(pAlloc->LockInfo.cLocks < UINT32_MAX);
4250
4251 if (pRc->RcDesc.enmPool != D3DDDIPOOL_SYSTEMMEM)
4252 {
4253 fDoUnlock = TRUE;
4254 }
4255 else
4256 {
4257 if (!pAlloc->LockInfo.cLocks)
4258 {
4259 D3DDDICB_LOCK LockData;
4260 LockData.hAllocation = pAlloc->hAllocation;
4261 LockData.PrivateDriverData = 0;
4262 LockData.NumPages = 0;
4263 LockData.pPages = NULL;
4264 LockData.pData = NULL; /* out */
4265 LockData.Flags.Value = 0;
4266
4267 hr = pDevice->RtCallbacks.pfnLockCb(pDevice->hDevice, &LockData);
4268 if (hr == S_OK)
4269 {
4270 D3DLOCKED_RECT LRect;
4271 LRect.pBits = LockData.pData;
4272 LRect.Pitch = pAlloc->SurfDesc.pitch;
4273 Assert(pAlloc->DirtyRegion.fFlags & VBOXWDDM_DIRTYREGION_F_VALID);
4274 VBoxD3DIfLockUnlockMemSynch(pAlloc, &LRect, &pAlloc->DirtyRegion.Rect, TRUE /* bool bToLockInfo*/);
4275 vboxWddmDirtyRegionClear(&pAlloc->DirtyRegion);
4276 fDoUnlock = TRUE;
4277 }
4278 else
4279 {
4280 WARN(("pfnLockCb failed, hr 0x%x", hr));
4281 }
4282 }
4283 }
4284
4285 if (fDoUnlock)
4286 {
4287 D3DDDICB_UNLOCK Unlock;
4288
4289 Unlock.NumAllocations = 1;
4290 Unlock.phAllocations = &pAlloc->hAllocation;
4291
4292 hr = pDevice->RtCallbacks.pfnUnlockCb(pDevice->hDevice, &Unlock);
4293 if(hr != S_OK)
4294 {
4295 WARN(("pfnUnlockCb failed, hr 0x%x", hr));
4296 }
4297 }
4298
4299 if (!SUCCEEDED(hr))
4300 {
4301 WARN(("unlock failure!"));
4302 ++pAlloc->LockInfo.cLocks;
4303 }
4304 }
4305 }
4306
4307 vboxVDbgPrintF(("<== "__FUNCTION__", hDevice(0x%p)\n", hDevice));
4308 return hr;
4309}
4310static HRESULT APIENTRY vboxWddmDDevLockAsync(HANDLE hDevice, D3DDDIARG_LOCKASYNC* pData)
4311{
4312 VBOXDISP_DDI_PROLOGUE_DEV(hDevice);
4313 vboxVDbgPrintF(("<== "__FUNCTION__", hDevice(0x%p)\n", hDevice));
4314 PVBOXWDDMDISP_DEVICE pDevice = (PVBOXWDDMDISP_DEVICE)hDevice;
4315 Assert(pDevice);
4316 VBOXDISPCRHGSMI_SCOPE_SET_DEV(pDevice);
4317 Assert(0);
4318 vboxVDbgPrintF(("==> "__FUNCTION__", hDevice(0x%p)\n", hDevice));
4319 return E_FAIL;
4320}
4321static HRESULT APIENTRY vboxWddmDDevUnlockAsync(HANDLE hDevice, CONST D3DDDIARG_UNLOCKASYNC* pData)
4322{
4323 VBOXDISP_DDI_PROLOGUE_DEV(hDevice);
4324 vboxVDbgPrintF(("<== "__FUNCTION__", hDevice(0x%p)\n", hDevice));
4325 PVBOXWDDMDISP_DEVICE pDevice = (PVBOXWDDMDISP_DEVICE)hDevice;
4326 Assert(pDevice);
4327 VBOXDISPCRHGSMI_SCOPE_SET_DEV(pDevice);
4328 Assert(0);
4329 vboxVDbgPrintF(("==> "__FUNCTION__", hDevice(0x%p)\n", hDevice));
4330 return E_FAIL;
4331}
4332static HRESULT APIENTRY vboxWddmDDevRename(HANDLE hDevice, CONST D3DDDIARG_RENAME* pData)
4333{
4334 VBOXDISP_DDI_PROLOGUE_DEV(hDevice);
4335 vboxVDbgPrintF(("<== "__FUNCTION__", hDevice(0x%p)\n", hDevice));
4336 PVBOXWDDMDISP_DEVICE pDevice = (PVBOXWDDMDISP_DEVICE)hDevice;
4337 Assert(pDevice);
4338 VBOXDISPCRHGSMI_SCOPE_SET_DEV(pDevice);
4339 Assert(0);
4340 vboxVDbgPrintF(("==> "__FUNCTION__", hDevice(0x%p)\n", hDevice));
4341 return E_FAIL;
4342}
4343
4344static void vboxWddmRequestAllocFree(D3DDDICB_ALLOCATE* pAlloc)
4345{
4346 RTMemFree(pAlloc);
4347}
4348
4349static D3DDDICB_ALLOCATE* vboxWddmRequestAllocAlloc(D3DDDIARG_CREATERESOURCE* pResource)
4350{
4351 /* allocate buffer for D3DDDICB_ALLOCATE + D3DDDI_ALLOCATIONINFO * numAllocs + PVBOXWDDM_RCINFO with aAllocInfos[numAllocs] */
4352 uint32_t cbBuf = sizeof (D3DDDICB_ALLOCATE);
4353 uint32_t offDdiAllocInfos = (cbBuf + 7) & ~3;
4354 uint32_t cbDdiAllocInfos = sizeof (D3DDDI_ALLOCATIONINFO) * pResource->SurfCount;
4355 cbBuf = offDdiAllocInfos + cbDdiAllocInfos;
4356 uint32_t offRcInfo = (cbBuf + 7) & ~3;
4357 uint32_t cbRcInfo = sizeof (VBOXWDDM_RCINFO);
4358 cbBuf = offRcInfo + cbRcInfo;
4359 uint32_t offAllocInfos = (cbBuf + 7) & ~3;
4360 uint32_t cbAllocInfos = sizeof (VBOXWDDM_ALLOCINFO) * pResource->SurfCount;
4361 cbBuf = offAllocInfos + cbAllocInfos;
4362 uint8_t *pvBuf = (uint8_t*)RTMemAllocZ(cbBuf);
4363 Assert(pvBuf);
4364 if (pvBuf)
4365 {
4366 D3DDDICB_ALLOCATE* pAlloc = (D3DDDICB_ALLOCATE*)pvBuf;
4367 pAlloc->NumAllocations = pResource->SurfCount;
4368 pAlloc->pAllocationInfo = (D3DDDI_ALLOCATIONINFO*)(pvBuf + offDdiAllocInfos);
4369 PVBOXWDDM_RCINFO pRcInfo = (PVBOXWDDM_RCINFO)(pvBuf + offRcInfo);
4370 pAlloc->PrivateDriverDataSize = cbRcInfo;
4371 pAlloc->pPrivateDriverData = pRcInfo;
4372 pAlloc->hResource = pResource->hResource;
4373 PVBOXWDDM_ALLOCINFO pAllocInfos = (PVBOXWDDM_ALLOCINFO)(pvBuf + offAllocInfos);
4374 for (UINT i = 0; i < pResource->SurfCount; ++i)
4375 {
4376 D3DDDI_ALLOCATIONINFO* pDdiAllocInfo = &pAlloc->pAllocationInfo[i];
4377 PVBOXWDDM_ALLOCINFO pAllocInfo = &pAllocInfos[i];
4378 pDdiAllocInfo->pPrivateDriverData = pAllocInfo;
4379 pDdiAllocInfo->PrivateDriverDataSize = sizeof (VBOXWDDM_ALLOCINFO);
4380 }
4381 return pAlloc;
4382 }
4383 return NULL;
4384}
4385
4386static HRESULT APIENTRY vboxWddmDDevCreateResource(HANDLE hDevice, D3DDDIARG_CREATERESOURCE* pResource)
4387{
4388 VBOXDISP_DDI_PROLOGUE_DEV(hDevice);
4389 vboxVDbgPrintF(("==> "__FUNCTION__", hDevice(0x%p)\n", hDevice));
4390 HRESULT hr = S_OK;
4391 PVBOXWDDMDISP_DEVICE pDevice = (PVBOXWDDMDISP_DEVICE)hDevice;
4392 Assert(pDevice);
4393 VBOXDISPCRHGSMI_SCOPE_SET_DEV(pDevice);
4394 Assert(pResource);
4395 PVBOXWDDMDISP_ADAPTER pAdapter = pDevice->pAdapter;
4396
4397 PVBOXWDDMDISP_RESOURCE pRc = vboxResourceAlloc(pResource->SurfCount);
4398 if (!pRc)
4399 {
4400 WARN(("vboxResourceAlloc failed"));
4401 return E_OUTOFMEMORY;
4402 }
4403 bool bIssueCreateResource = false;
4404 bool bCreateKMResource = false;
4405 bool bSetHostID = false;
4406
4407 pRc->hResource = pResource->hResource;
4408 pRc->hKMResource = NULL;
4409 pRc->pDevice = pDevice;
4410 pRc->fFlags.Value = 0;
4411 pRc->fFlags.Generic = 1;
4412 pRc->RcDesc.fFlags = pResource->Flags;
4413 pRc->RcDesc.enmFormat = pResource->Format;
4414 pRc->RcDesc.enmPool = pResource->Pool;
4415 pRc->RcDesc.enmMultisampleType = pResource->MultisampleType;
4416 pRc->RcDesc.MultisampleQuality = pResource->MultisampleQuality;
4417 pRc->RcDesc.MipLevels = pResource->MipLevels;
4418 pRc->RcDesc.Fvf = pResource->Fvf;
4419 pRc->RcDesc.VidPnSourceId = pResource->VidPnSourceId;
4420 pRc->RcDesc.RefreshRate = pResource->RefreshRate;
4421 pRc->RcDesc.enmRotation = pResource->Rotation;
4422 pRc->cAllocations = pResource->SurfCount;
4423 for (UINT i = 0; i < pResource->SurfCount; ++i)
4424 {
4425 PVBOXWDDMDISP_ALLOCATION pAllocation = &pRc->aAllocations[i];
4426 CONST D3DDDI_SURFACEINFO* pSurf = &pResource->pSurfList[i];
4427 pAllocation->hAllocation = NULL;
4428 pAllocation->enmType = VBOXWDDM_ALLOC_TYPE_UMD_RC_GENERIC;
4429 pAllocation->iAlloc = i;
4430 pAllocation->pRc = pRc;
4431 pAllocation->SurfDesc.d3dWidth = pSurf->Width;
4432 pAllocation->pvMem = (void*)pSurf->pSysMem;
4433 pAllocation->SurfDesc.slicePitch = pSurf->SysMemSlicePitch;
4434 pAllocation->SurfDesc.depth = pSurf->Depth;
4435 pAllocation->SurfDesc.width = pSurf->Width;
4436 pAllocation->SurfDesc.height = pSurf->Height;
4437 pAllocation->SurfDesc.format = pResource->Format;
4438 if (!vboxWddmFormatToFourcc(pResource->Format))
4439 pAllocation->SurfDesc.bpp = vboxWddmCalcBitsPerPixel(pResource->Format);
4440 else
4441 pAllocation->SurfDesc.bpp = 0;
4442
4443 if (pSurf->SysMemPitch)
4444 pAllocation->SurfDesc.pitch = pSurf->SysMemPitch;
4445 else
4446 pAllocation->SurfDesc.pitch = vboxWddmCalcPitch(pSurf->Width, pResource->Format);
4447
4448 pAllocation->SurfDesc.cbSize = vboxWddmCalcSize(pAllocation->SurfDesc.pitch, pAllocation->SurfDesc.height, pAllocation->SurfDesc.format);
4449
4450 pAllocation->SurfDesc.VidPnSourceId = pResource->VidPnSourceId;
4451
4452 if (pRc->RcDesc.enmPool == D3DDDIPOOL_SYSTEMMEM)
4453 {
4454 Assert(pAllocation->pvMem);
4455 Assert(pAllocation->SurfDesc.pitch);
4456 UINT minPitch = vboxWddmCalcPitch(pAllocation->SurfDesc.width, pAllocation->SurfDesc.format);
4457 Assert(minPitch);
4458 if (minPitch)
4459 {
4460 if (pAllocation->SurfDesc.pitch != minPitch)
4461 {
4462 Assert(pAllocation->SurfDesc.pitch > minPitch);
4463 pAllocation->SurfDesc.d3dWidth = vboxWddmCalcWidthForPitch(pAllocation->SurfDesc.pitch, pAllocation->SurfDesc.format);
4464 Assert(VBOXWDDMDISP_IS_TEXTURE(pRc->RcDesc.fFlags) && !pRc->RcDesc.fFlags.CubeMap); /* <- tested for textures only! */
4465 }
4466 Assert(pAllocation->SurfDesc.d3dWidth >= pAllocation->SurfDesc.width);
4467 }
4468 else
4469 {
4470 Assert(pAllocation->SurfDesc.d3dWidth == pAllocation->SurfDesc.width);
4471 }
4472 }
4473
4474 }
4475
4476 if (VBOXDISPMODE_IS_3D(pAdapter))
4477 {
4478 if (pRc->RcDesc.fFlags.SharedResource)
4479 {
4480 bIssueCreateResource = true;
4481 bCreateKMResource = true;
4482 }
4483
4484 if (pRc->RcDesc.fFlags.RenderTarget || pRc->RcDesc.fFlags.Primary)
4485 {
4486 bIssueCreateResource = true;
4487 bSetHostID = true;
4488 }
4489
4490 hr = VBoxD3DIfCreateForRc(pRc);
4491 if (!SUCCEEDED(hr))
4492 {
4493 WARN(("VBoxD3DIfCreateForRc failed, hr 0x%x", hr));
4494 }
4495 }
4496 else
4497 {
4498 bIssueCreateResource = (pResource->Pool != D3DDDIPOOL_SYSTEMMEM) || pResource->Flags.RenderTarget;
4499 bCreateKMResource = bIssueCreateResource;
4500 }
4501
4502 if (SUCCEEDED(hr) && bIssueCreateResource)
4503 {
4504 pRc->fFlags.KmResource = bCreateKMResource;
4505 D3DDDICB_ALLOCATE *pDdiAllocate = vboxWddmRequestAllocAlloc(pResource);
4506 Assert(pDdiAllocate);
4507 if (pDdiAllocate)
4508 {
4509 Assert(pDdiAllocate->pPrivateDriverData);
4510 Assert(pDdiAllocate->PrivateDriverDataSize == sizeof (VBOXWDDM_RCINFO));
4511 PVBOXWDDM_RCINFO pRcInfo = (PVBOXWDDM_RCINFO)pDdiAllocate->pPrivateDriverData;
4512 pRcInfo->fFlags = pRc->fFlags;
4513 pRcInfo->RcDesc = pRc->RcDesc;
4514 pRcInfo->cAllocInfos = pResource->SurfCount;
4515
4516 for (UINT i = 0; i < pResource->SurfCount; ++i)
4517 {
4518 D3DDDI_ALLOCATIONINFO *pDdiAllocI = &pDdiAllocate->pAllocationInfo[i];
4519 PVBOXWDDMDISP_ALLOCATION pAllocation = &pRc->aAllocations[i];
4520 Assert(pDdiAllocI->pPrivateDriverData);
4521 Assert(pDdiAllocI->PrivateDriverDataSize == sizeof (VBOXWDDM_ALLOCINFO));
4522 PVBOXWDDM_ALLOCINFO pAllocInfo = (PVBOXWDDM_ALLOCINFO)pDdiAllocI->pPrivateDriverData;
4523 CONST D3DDDI_SURFACEINFO* pSurf = &pResource->pSurfList[i];
4524 pDdiAllocI->hAllocation = NULL;
4525 pDdiAllocI->pSystemMem = pSurf->pSysMem;
4526 Assert((!!(pSurf->pSysMem)) == (pResource->Pool == D3DDDIPOOL_SYSTEMMEM));
4527 pDdiAllocI->VidPnSourceId = pResource->VidPnSourceId;
4528 pDdiAllocI->Flags.Value = 0;
4529 if (pResource->Flags.Primary)
4530 {
4531 Assert(pResource->Flags.RenderTarget);
4532 pDdiAllocI->Flags.Primary = 1;
4533 }
4534
4535 pAllocInfo->enmType = VBOXWDDM_ALLOC_TYPE_UMD_RC_GENERIC;
4536 pAllocInfo->fFlags = pResource->Flags;
4537 pAllocInfo->hSharedHandle = (uint64_t)pAllocation->hSharedHandle;
4538 pAllocInfo->SurfDesc = pAllocation->SurfDesc;
4539 if (bSetHostID)
4540 {
4541 IDirect3DSurface9 *pSurfIf = NULL;
4542 hr = VBoxD3DIfSurfGet(pRc, i, &pSurfIf);
4543 if (SUCCEEDED(hr))
4544 {
4545 hr = pAdapter->D3D.D3D.pfnVBoxWineExD3DSurf9GetHostId(pSurfIf, &pAllocInfo->hostID);
4546 if (SUCCEEDED(hr))
4547 {
4548 Assert(pAllocInfo->hostID);
4549 }
4550 else
4551 {
4552 WARN(("pfnVBoxWineExD3DSurf9GetHostId failed, hr 0x%x", hr));
4553 break;
4554 }
4555 pSurfIf->Release();
4556 }
4557 else
4558 {
4559 WARN(("VBoxD3DIfSurfGet failed, hr 0x%x", hr));
4560 break;
4561 }
4562 }
4563 else
4564 pAllocInfo->hostID = 0;
4565 }
4566
4567 Assert(!pRc->fFlags.Opened);
4568// Assert(!pRc->fFlags.KmResource);
4569 Assert(pRc->fFlags.Generic);
4570
4571 if (SUCCEEDED(hr))
4572 {
4573 if (bCreateKMResource)
4574 {
4575 Assert(pRc->fFlags.KmResource);
4576
4577 hr = pDevice->RtCallbacks.pfnAllocateCb(pDevice->hDevice, pDdiAllocate);
4578 Assert(hr == S_OK);
4579 Assert(pDdiAllocate->hKMResource
4580 || pResource->Flags.SharedResource /* for some reason shared resources
4581 * are created with zero km resource handle on Win7+ */
4582 );
4583 }
4584 else
4585 {
4586 Assert(!pRc->fFlags.KmResource);
4587
4588 pDdiAllocate->hResource = NULL;
4589 pDdiAllocate->NumAllocations = 1;
4590 pDdiAllocate->PrivateDriverDataSize = 0;
4591 pDdiAllocate->pPrivateDriverData = NULL;
4592 D3DDDI_ALLOCATIONINFO *pDdiAllocIBase = pDdiAllocate->pAllocationInfo;
4593
4594 for (UINT i = 0; i < pResource->SurfCount; ++i)
4595 {
4596 pDdiAllocate->pAllocationInfo = &pDdiAllocIBase[i];
4597 hr = pDevice->RtCallbacks.pfnAllocateCb(pDevice->hDevice, pDdiAllocate);
4598 Assert(hr == S_OK);
4599 Assert(!pDdiAllocate->hKMResource);
4600 if (SUCCEEDED(hr))
4601 {
4602 Assert(pDdiAllocate->pAllocationInfo->hAllocation);
4603 }
4604 else
4605 {
4606 for (UINT j = 0; j < i; ++j)
4607 {
4608 D3DDDI_ALLOCATIONINFO * pCur = &pDdiAllocIBase[i];
4609 D3DDDICB_DEALLOCATE Dealloc;
4610 Dealloc.hResource = 0;
4611 Dealloc.NumAllocations = 1;
4612 Dealloc.HandleList = &pCur->hAllocation;
4613 HRESULT tmpHr = pDevice->RtCallbacks.pfnDeallocateCb(pDevice->hDevice, &Dealloc);
4614 Assert(tmpHr == S_OK);
4615 }
4616 break;
4617 }
4618 }
4619
4620 pDdiAllocate->pAllocationInfo = pDdiAllocIBase;
4621 }
4622
4623 if (SUCCEEDED(hr))
4624 {
4625 pRc->hKMResource = pDdiAllocate->hKMResource;
4626
4627 for (UINT i = 0; i < pResource->SurfCount; ++i)
4628 {
4629 PVBOXWDDMDISP_ALLOCATION pAllocation = &pRc->aAllocations[i];
4630 D3DDDI_ALLOCATIONINFO *pDdiAllocI = &pDdiAllocate->pAllocationInfo[i];
4631 PVBOXWDDM_ALLOCINFO pAllocInfo = (PVBOXWDDM_ALLOCINFO)pDdiAllocI->pPrivateDriverData;
4632 CONST D3DDDI_SURFACEINFO* pSurf = &pResource->pSurfList[i];
4633 pAllocation->hAllocation = pDdiAllocI->hAllocation;
4634 pAllocation->enmType = VBOXWDDM_ALLOC_TYPE_UMD_RC_GENERIC;
4635 pAllocation->pvMem = (void*)pSurf->pSysMem;
4636 pAllocation->SurfDesc = pAllocInfo->SurfDesc;
4637
4638 if (pResource->Flags.SharedResource)
4639 {
4640#ifdef VBOXWDDMDISP_DEBUG_PRINT_SHARED_CREATE
4641 Assert(VBOXWDDMDISP_IS_TEXTURE(pResource->Flags));
4642 vboxVDbgPrint(("\n\n********\n(0x%x:0n%d)Shared CREATED pAlloc(0x%p), hRc(0x%p), hAl(0x%p), "
4643 "Handle(0x%x), (0n%d) \n***********\n\n",
4644 GetCurrentProcessId(), GetCurrentProcessId(),
4645 pAllocation, pRc->hKMResource, pAllocation->hAllocation,
4646 pAllocation->hSharedHandle, pAllocation->hSharedHandle
4647 ));
4648#endif
4649 }
4650 }
4651
4652 VBOXVDBG_CREATE_CHECK_SWAPCHAIN();
4653 }
4654 }
4655
4656 vboxWddmRequestAllocFree(pDdiAllocate);
4657 }
4658 else
4659 {
4660 hr = E_OUTOFMEMORY;
4661 }
4662 }
4663
4664 VBOXVDBG_BREAK_SHARED(pRc);
4665
4666 if (SUCCEEDED(hr))
4667 {
4668 pResource->hResource = pRc;
4669 hr = S_OK;
4670 }
4671 else
4672 vboxResourceFree(pRc);
4673
4674 vboxVDbgPrintF(("<== "__FUNCTION__", hDevice(0x%p)\n", hDevice));
4675 return hr;
4676}
4677
4678static HRESULT APIENTRY vboxWddmDDevDestroyResource(HANDLE hDevice, HANDLE hResource)
4679{
4680 VBOXDISP_DDI_PROLOGUE_DEV(hDevice);
4681 vboxVDbgPrintF(("==> "__FUNCTION__", hDevice(0x%p)\n", hDevice));
4682 PVBOXWDDMDISP_DEVICE pDevice = (PVBOXWDDMDISP_DEVICE)hDevice;
4683 Assert(pDevice);
4684 VBOXDISPCRHGSMI_SCOPE_SET_DEV(pDevice);
4685 PVBOXWDDMDISP_ADAPTER pAdapter = pDevice->pAdapter;
4686 PVBOXWDDMDISP_RESOURCE pRc = (PVBOXWDDMDISP_RESOURCE)hResource;
4687
4688 HRESULT hr = S_OK;
4689
4690 Assert(pDevice);
4691 Assert(hResource);
4692
4693 if (VBOXDISPMODE_IS_3D(pAdapter))
4694 {
4695 for (UINT i = 0; i < pRc->cAllocations; ++i)
4696 {
4697 PVBOXWDDMDISP_ALLOCATION pAlloc = &pRc->aAllocations[i];
4698 if (pAlloc->hSharedHandle)
4699 {
4700#ifdef VBOXWDDMDISP_DEBUG_PRINT_SHARED_CREATE
4701 vboxVDbgPrint(("\n\n********\n(0x%x:0n%d)Shared DESTROYED pAlloc(0x%p), hRc(0x%p), hAl(0x%p), "
4702 "Handle(0x%x), (0n%d) \n***********\n\n",
4703 GetCurrentProcessId(), GetCurrentProcessId(),
4704 pAlloc, pRc->hKMResource, pAlloc->hAllocation,
4705 pAlloc->hSharedHandle, pAlloc->hSharedHandle
4706 ));
4707#endif
4708 }
4709
4710 if (pAlloc->pD3DIf)
4711 pAlloc->pD3DIf->Release();
4712
4713 PVBOXWDDMDISP_SWAPCHAIN pSwapchain = vboxWddmSwapchainForAlloc(pAlloc);
4714 if (pSwapchain)
4715 {
4716 PVBOXWDDMDISP_RENDERTGT pRt = vboxWddmSwapchainRtForAlloc(pSwapchain, pAlloc);
4717 vboxWddmSwapchainRtRemove(pSwapchain, pRt);
4718 Assert(!vboxWddmSwapchainForAlloc(pAlloc));
4719 if (!vboxWddmSwapchainNumRTs(pSwapchain))
4720 vboxWddmSwapchainDestroy(pDevice, pSwapchain);
4721 }
4722
4723 vboxWddmDalCheckNotifyRemove(pDevice, pAlloc);
4724 }
4725 }
4726
4727 if (pRc->fFlags.KmResource)
4728 {
4729 D3DDDICB_DEALLOCATE Dealloc;
4730 Assert(pRc->hResource);
4731 Dealloc.hResource = pRc->hResource;
4732 /* according to the docs the below two are ignored in case we set the hResource */
4733 Dealloc.NumAllocations = 0;
4734 Dealloc.HandleList = NULL;
4735 hr = pDevice->RtCallbacks.pfnDeallocateCb(pDevice->hDevice, &Dealloc);
4736 Assert(hr == S_OK);
4737 }
4738 else
4739 {
4740 Assert(!(pRc->fFlags.Opened));
4741 for (UINT j = 0; j < pRc->cAllocations; ++j)
4742 {
4743 if (pRc->aAllocations[j].hAllocation)
4744 {
4745 D3DDDICB_DEALLOCATE Dealloc;
4746 Dealloc.hResource = NULL;
4747 Dealloc.NumAllocations = 1;
4748 Dealloc.HandleList = &pRc->aAllocations[j].hAllocation;
4749 HRESULT tmpHr = pDevice->RtCallbacks.pfnDeallocateCb(pDevice->hDevice, &Dealloc);
4750 Assert(tmpHr == S_OK);
4751 }
4752 }
4753 }
4754
4755 vboxResourceFree(pRc);
4756 vboxVDbgPrintF(("<== "__FUNCTION__", hDevice(0x%p)\n", hDevice));
4757 return hr;
4758}
4759static HRESULT APIENTRY vboxWddmDDevSetDisplayMode(HANDLE hDevice, CONST D3DDDIARG_SETDISPLAYMODE* pData)
4760{
4761 VBOXDISP_DDI_PROLOGUE_DEV(hDevice);
4762 vboxVDbgPrintF(("==> "__FUNCTION__", hDevice(0x%p)\n", hDevice));
4763 HRESULT hr = S_OK;
4764 PVBOXWDDMDISP_DEVICE pDevice = (PVBOXWDDMDISP_DEVICE)hDevice;
4765 Assert(pDevice);
4766 VBOXDISPCRHGSMI_SCOPE_SET_DEV(pDevice);
4767 Assert(VBOXDISPMODE_IS_3D(pDevice->pAdapter));
4768 PVBOXWDDMDISP_RESOURCE pRc = (PVBOXWDDMDISP_RESOURCE)pData->hResource;
4769 Assert(pRc);
4770 Assert(pRc->cAllocations > pData->SubResourceIndex);
4771 PVBOXWDDMDISP_ALLOCATION pAlloc = &pRc->aAllocations[pData->SubResourceIndex];
4772 Assert(pRc->RcDesc.fFlags.RenderTarget);
4773 Assert(pRc->RcDesc.fFlags.Primary);
4774 Assert(pAlloc->hAllocation);
4775 D3DDDICB_SETDISPLAYMODE DdiDm = {0};
4776 DdiDm.hPrimaryAllocation = pAlloc->hAllocation;
4777
4778 {
4779 hr = pDevice->RtCallbacks.pfnSetDisplayModeCb(pDevice->hDevice, &DdiDm);
4780 Assert(hr == S_OK);
4781 }
4782
4783 vboxVDbgPrintF(("<== "__FUNCTION__", hDevice(0x%p)\n", hDevice));
4784 return hr;
4785}
4786
4787#ifdef VBOXWDDM_TEST_UHGSMI
4788int vboxUhgsmiTst(PVBOXUHGSMI pUhgsmi, uint32_t cbBuf, uint32_t cNumCals, uint64_t * pTimeMs);
4789#endif
4790
4791static HRESULT APIENTRY vboxWddmDDevPresent(HANDLE hDevice, CONST D3DDDIARG_PRESENT* pData)
4792{
4793 VBOXDISP_DDI_PROLOGUE_DEV(hDevice);
4794 vboxVDbgPrintF(("==> "__FUNCTION__", hDevice(0x%p)\n", hDevice));
4795 PVBOXWDDMDISP_DEVICE pDevice = (PVBOXWDDMDISP_DEVICE)hDevice;
4796// VBOXDISPPROFILE_DDI_CHKDUMPRESET(pDevice);
4797 Assert(pDevice);
4798 VBOXDISPCRHGSMI_SCOPE_SET_DEV(pDevice);
4799 HRESULT hr = S_OK;
4800 PVBOXWDDMDISP_ADAPTER pAdapter = pDevice->pAdapter;
4801 PVBOXWDDMDISP_RESOURCE pSrcRc = NULL, pDstRc = NULL;
4802 PVBOXWDDMDISP_ALLOCATION pSrcAlloc = NULL, pDstAlloc = NULL;
4803
4804 Assert(vboxWddmDalIsEmpty(pDevice));
4805
4806 if (pData->hSrcResource)
4807 {
4808 pSrcRc = (PVBOXWDDMDISP_RESOURCE)pData->hSrcResource;
4809 Assert(pSrcRc->cAllocations > pData->SrcSubResourceIndex);
4810 pSrcAlloc = &pSrcRc->aAllocations[pData->SrcSubResourceIndex];
4811 Assert(pSrcAlloc->hAllocation);
4812 }
4813
4814 if (pData->hDstResource)
4815 {
4816 pDstRc = (PVBOXWDDMDISP_RESOURCE)pData->hDstResource;
4817 Assert(pDstRc->cAllocations > pData->DstSubResourceIndex);
4818 pDstAlloc = &pDstRc->aAllocations[pData->DstSubResourceIndex];
4819 Assert(pDstAlloc->hAllocation);
4820 }
4821
4822 if (VBOXDISPMODE_IS_3D(pAdapter))
4823 {
4824#ifdef VBOXWDDM_TEST_UHGSMI
4825 {
4826 static uint32_t cCals = 100000;
4827 static uint32_t cbData = 8 * 1024 * 1024;
4828 uint64_t TimeMs;
4829 int rc = vboxUhgsmiTst(&pDevice->Uhgsmi.Base, cbData, cCals, &TimeMs);
4830 uint32_t cCPS = (((uint64_t)cCals) * 1000ULL)/TimeMs;
4831 }
4832#endif
4833#ifdef VBOX_WITH_CROGL
4834 if (pAdapter->u32VBox3DCaps & CR_VBOX_CAP_TEX_PRESENT)
4835 {
4836 IDirect3DSurface9 *pSrcSurfIf = NULL;
4837 hr = VBoxD3DIfSurfGet(pSrcRc, pData->SrcSubResourceIndex, &pSrcSurfIf);
4838 if (SUCCEEDED(hr))
4839 {
4840 pAdapter->D3D.D3D.pfnVBoxWineExD3DSurf9SyncToHost(pSrcSurfIf);
4841 pSrcSurfIf->Release();
4842 }
4843 else
4844 {
4845 WARN(("VBoxD3DIfSurfGet failed, hr = 0x%x", hr));
4846 return hr;
4847 }
4848
4849 pAdapter->D3D.D3D.pfnVBoxWineExD3DDev9FlushToHost((IDirect3DDevice9Ex*)pDevice->pDevice9If);
4850 }
4851 else
4852#endif
4853 {
4854 pAdapter->D3D.D3D.pfnVBoxWineExD3DDev9FlushToHost((IDirect3DDevice9Ex*)pDevice->pDevice9If);
4855 PVBOXWDDMDISP_RESOURCE pRc = (PVBOXWDDMDISP_RESOURCE)pData->hSrcResource;
4856 Assert(pRc);
4857 Assert(pRc->cAllocations > pData->SrcSubResourceIndex);
4858 PVBOXWDDMDISP_ALLOCATION pAlloc = &pRc->aAllocations[pData->SrcSubResourceIndex];
4859 hr = vboxWddmSwapchainPresent(pDevice, pAlloc);
4860 Assert(hr == S_OK);
4861 }
4862 }
4863
4864 D3DDDICB_PRESENT DdiPresent = {0};
4865 if (pSrcAlloc)
4866 DdiPresent.hSrcAllocation = pSrcAlloc->hAllocation;
4867
4868 if (pDstAlloc)
4869 DdiPresent.hDstAllocation = pDstAlloc->hAllocation;
4870
4871 DdiPresent.hContext = pDevice->DefaultContext.ContextInfo.hContext;
4872
4873#if 0 //def VBOX_WDDMDISP_WITH_PROFILE
4874 VBoxDispProfileScopeLogger<VBoxDispProfileEntry> profilePresentCbLogger(pDevice->ProfileDdiPresentCb.alloc("pfnPresentCb"));
4875#endif
4876
4877#ifdef VBOXWDDMDISP_DEBUG_TIMER
4878 HANDLE hTimer = NULL;
4879 vboxVDbgTimerStart(pDevice->hTimerQueue, &hTimer, 1000);
4880#endif
4881 hr = pDevice->RtCallbacks.pfnPresentCb(pDevice->hDevice, &DdiPresent);
4882#ifdef VBOXWDDMDISP_DEBUG_TIMER
4883 vboxVDbgTimerStop(pDevice->hTimerQueue, hTimer);
4884#endif
4885#if 0 //def VBOX_WDDMDISP_WITH_PROFILE
4886 profilePresentCbLogger.logAndDisable();
4887 if (pDevice->ProfileDdiPresentCb.getNumEntries() == 64)
4888 {
4889 pDevice->ProfileDdiPresentCb.dump(pDevice);
4890 pDevice->ProfileDdiPresentCb.reset();
4891 }
4892#endif
4893 Assert(hr == S_OK);
4894
4895 vboxVDbgPrintF(("<== "__FUNCTION__", hDevice(0x%p), hr(0x%x)\n", hDevice, hr));
4896
4897 VBOXDISPPROFILE_DDI_REPORT_FRAME(pDevice);
4898
4899 return hr;
4900}
4901
4902static HRESULT APIENTRY vboxWddmDDevFlush(HANDLE hDevice)
4903{
4904 VBOXDISP_DDI_PROLOGUE_DEV(hDevice);
4905 vboxVDbgPrintF(("==> "__FUNCTION__", hDevice(0x%p)\n", hDevice));
4906 PVBOXWDDMDISP_DEVICE pDevice = (PVBOXWDDMDISP_DEVICE)hDevice;
4907 Assert(pDevice);
4908 VBOXDISPCRHGSMI_SCOPE_SET_DEV(pDevice);
4909 HRESULT hr = S_OK;
4910 if ( VBOXDISPMODE_IS_3D(pDevice->pAdapter)
4911 && pDevice->pDevice9If) /* Windows 10 can call the Flush when pDevice9If is not yet initialized. */
4912 {
4913
4914 hr = pDevice->pAdapter->D3D.D3D.pfnVBoxWineExD3DDev9Flush((IDirect3DDevice9Ex*)pDevice->pDevice9If);
4915 Assert(hr == S_OK);
4916
4917 vboxWddmDalNotifyChange(pDevice);
4918
4919 VBOXVDBG_DUMP_FLUSH(pDevice);
4920 }
4921 vboxVDbgPrintF(("<== "__FUNCTION__", hDevice(0x%p), hr(0x%x)\n", hDevice, hr));
4922
4923 VBOXDISPPROFILE_DDI_REPORT_FLUSH(pDevice);
4924
4925 return hr;
4926}
4927
4928AssertCompile(sizeof (D3DDDIVERTEXELEMENT) == sizeof (D3DVERTEXELEMENT9));
4929AssertCompile(RT_SIZEOFMEMB(D3DDDIVERTEXELEMENT, Stream) == RT_SIZEOFMEMB(D3DVERTEXELEMENT9, Stream));
4930AssertCompile(RT_SIZEOFMEMB(D3DDDIVERTEXELEMENT, Offset) == RT_SIZEOFMEMB(D3DVERTEXELEMENT9, Offset));
4931AssertCompile(RT_SIZEOFMEMB(D3DDDIVERTEXELEMENT, Type) == RT_SIZEOFMEMB(D3DVERTEXELEMENT9, Type));
4932AssertCompile(RT_SIZEOFMEMB(D3DDDIVERTEXELEMENT, Method) == RT_SIZEOFMEMB(D3DVERTEXELEMENT9, Method));
4933AssertCompile(RT_SIZEOFMEMB(D3DDDIVERTEXELEMENT, Usage) == RT_SIZEOFMEMB(D3DVERTEXELEMENT9, Usage));
4934AssertCompile(RT_SIZEOFMEMB(D3DDDIVERTEXELEMENT, UsageIndex) == RT_SIZEOFMEMB(D3DVERTEXELEMENT9, UsageIndex));
4935
4936AssertCompile(RT_OFFSETOF(D3DDDIVERTEXELEMENT, Stream) == RT_OFFSETOF(D3DVERTEXELEMENT9, Stream));
4937AssertCompile(RT_OFFSETOF(D3DDDIVERTEXELEMENT, Offset) == RT_OFFSETOF(D3DVERTEXELEMENT9, Offset));
4938AssertCompile(RT_OFFSETOF(D3DDDIVERTEXELEMENT, Type) == RT_OFFSETOF(D3DVERTEXELEMENT9, Type));
4939AssertCompile(RT_OFFSETOF(D3DDDIVERTEXELEMENT, Method) == RT_OFFSETOF(D3DVERTEXELEMENT9, Method));
4940AssertCompile(RT_OFFSETOF(D3DDDIVERTEXELEMENT, Usage) == RT_OFFSETOF(D3DVERTEXELEMENT9, Usage));
4941AssertCompile(RT_OFFSETOF(D3DDDIVERTEXELEMENT, UsageIndex) == RT_OFFSETOF(D3DVERTEXELEMENT9, UsageIndex));
4942
4943static HRESULT APIENTRY vboxWddmDDevCreateVertexShaderDecl(HANDLE hDevice, D3DDDIARG_CREATEVERTEXSHADERDECL* pData, CONST D3DDDIVERTEXELEMENT* pVertexElements)
4944{
4945 VBOXDISP_DDI_PROLOGUE_DEV(hDevice);
4946 vboxVDbgPrintF(("==> "__FUNCTION__", hDevice(0x%p)\n", hDevice));
4947 PVBOXWDDMDISP_DEVICE pDevice = (PVBOXWDDMDISP_DEVICE)hDevice;
4948 Assert(pDevice);
4949 VBOXDISPCRHGSMI_SCOPE_SET_DEV(pDevice);
4950 IDirect3DDevice9 * pDevice9If = VBOXDISP_D3DEV(pDevice);
4951 IDirect3DVertexDeclaration9 *pDecl;
4952 static D3DVERTEXELEMENT9 DeclEnd = D3DDECL_END();
4953 D3DVERTEXELEMENT9* pVe;
4954 HRESULT hr = S_OK;
4955 bool bFreeVe = false;
4956 if(memcmp(&DeclEnd, &pVertexElements[pData->NumVertexElements], sizeof (DeclEnd)))
4957 {
4958 pVe = (D3DVERTEXELEMENT9*)RTMemAlloc(sizeof (D3DVERTEXELEMENT9) * (pData->NumVertexElements + 1));
4959 if (pVe)
4960 {
4961 memcpy(pVe, pVertexElements, sizeof (D3DVERTEXELEMENT9) * pData->NumVertexElements);
4962 pVe[pData->NumVertexElements] = DeclEnd;
4963 bFreeVe = true;
4964 }
4965 else
4966 hr = E_OUTOFMEMORY;
4967 }
4968 else
4969 pVe = (D3DVERTEXELEMENT9*)pVertexElements;
4970
4971 if (hr == S_OK)
4972 {
4973 hr = pDevice9If->CreateVertexDeclaration(
4974 pVe,
4975 &pDecl
4976 );
4977 Assert(hr == S_OK);
4978 if (hr == S_OK)
4979 {
4980 Assert(pDecl);
4981 pData->ShaderHandle = pDecl;
4982 }
4983 }
4984
4985 if (bFreeVe)
4986 RTMemFree((void*)pVe);
4987
4988 vboxVDbgPrintF(("<== "__FUNCTION__", hDevice(0x%p), hr(0x%x)\n", hDevice, hr));
4989 return hr;
4990}
4991static HRESULT APIENTRY vboxWddmDDevSetVertexShaderDecl(HANDLE hDevice, HANDLE hShaderHandle)
4992{
4993 VBOXDISP_DDI_PROLOGUE_DEV(hDevice);
4994 vboxVDbgPrintF(("==> "__FUNCTION__", hDevice(0x%p)\n", hDevice));
4995 PVBOXWDDMDISP_DEVICE pDevice = (PVBOXWDDMDISP_DEVICE)hDevice;
4996 Assert(pDevice);
4997 VBOXDISPCRHGSMI_SCOPE_SET_DEV(pDevice);
4998 IDirect3DDevice9 * pDevice9If = VBOXDISP_D3DEV(pDevice);
4999 IDirect3DVertexDeclaration9 *pDecl = (IDirect3DVertexDeclaration9*)hShaderHandle;
5000 Assert(pDecl);
5001 HRESULT hr = pDevice9If->SetVertexDeclaration(pDecl);
5002 Assert(hr == S_OK);
5003 vboxVDbgPrintF(("<== "__FUNCTION__", hDevice(0x%p), hr(0x%x)\n", hDevice, hr));
5004 return hr;
5005}
5006static HRESULT APIENTRY vboxWddmDDevDeleteVertexShaderDecl(HANDLE hDevice, HANDLE hShaderHandle)
5007{
5008 VBOXDISP_DDI_PROLOGUE_DEV(hDevice);
5009 vboxVDbgPrintF(("==> "__FUNCTION__", hDevice(0x%p)\n", hDevice));
5010 PVBOXWDDMDISP_DEVICE pDevice = (PVBOXWDDMDISP_DEVICE)hDevice;
5011 Assert(pDevice);
5012 VBOXDISPCRHGSMI_SCOPE_SET_DEV(pDevice);
5013 IDirect3DVertexDeclaration9 *pDecl = (IDirect3DVertexDeclaration9*)hShaderHandle;
5014 HRESULT hr = S_OK;
5015 pDecl->Release();
5016 vboxVDbgPrintF(("<== "__FUNCTION__", hDevice(0x%p), hr(0x%x)\n", hDevice, hr));
5017 return hr;
5018}
5019static HRESULT APIENTRY vboxWddmDDevCreateVertexShaderFunc(HANDLE hDevice, D3DDDIARG_CREATEVERTEXSHADERFUNC* pData, CONST UINT* pCode)
5020{
5021 VBOXDISP_DDI_PROLOGUE_DEV(hDevice);
5022 vboxVDbgPrintF(("==> "__FUNCTION__", hDevice(0x%p)\n", hDevice));
5023 PVBOXWDDMDISP_DEVICE pDevice = (PVBOXWDDMDISP_DEVICE)hDevice;
5024 Assert(pDevice);
5025 VBOXDISPCRHGSMI_SCOPE_SET_DEV(pDevice);
5026 IDirect3DDevice9 * pDevice9If = VBOXDISP_D3DEV(pDevice);
5027 IDirect3DVertexShader9 *pShader;
5028 Assert(*((UINT*)((uint8_t*)pCode + pData->Size-4)) == 0x0000FFFF /* end token */);
5029 HRESULT hr = pDevice9If->CreateVertexShader((const DWORD *)pCode, &pShader);
5030 Assert(hr == S_OK);
5031 if (hr == S_OK)
5032 {
5033 Assert(pShader);
5034 pData->ShaderHandle = pShader;
5035 }
5036 vboxVDbgPrintF(("<== "__FUNCTION__", hDevice(0x%p), hr(0x%x)\n", hDevice, hr));
5037 return hr;
5038}
5039static HRESULT APIENTRY vboxWddmDDevSetVertexShaderFunc(HANDLE hDevice, HANDLE hShaderHandle)
5040{
5041 VBOXDISP_DDI_PROLOGUE_DEV(hDevice);
5042 vboxVDbgPrintF(("==> "__FUNCTION__", hDevice(0x%p)\n", hDevice));
5043 PVBOXWDDMDISP_DEVICE pDevice = (PVBOXWDDMDISP_DEVICE)hDevice;
5044 Assert(pDevice);
5045 VBOXDISPCRHGSMI_SCOPE_SET_DEV(pDevice);
5046 IDirect3DDevice9 * pDevice9If = VBOXDISP_D3DEV(pDevice);
5047 IDirect3DVertexShader9 *pShader = (IDirect3DVertexShader9*)hShaderHandle;
5048 HRESULT hr = pDevice9If->SetVertexShader(pShader);
5049 Assert(hr == S_OK);
5050 vboxVDbgPrintF(("<== "__FUNCTION__", hDevice(0x%p), hr(0x%x)\n", hDevice, hr));
5051 return hr;
5052}
5053static HRESULT APIENTRY vboxWddmDDevDeleteVertexShaderFunc(HANDLE hDevice, HANDLE hShaderHandle)
5054{
5055 VBOXDISP_DDI_PROLOGUE_DEV(hDevice);
5056 vboxVDbgPrintF(("==> "__FUNCTION__", hDevice(0x%p)\n", hDevice));
5057 PVBOXWDDMDISP_DEVICE pDevice = (PVBOXWDDMDISP_DEVICE)hDevice;
5058 Assert(pDevice);
5059 VBOXDISPCRHGSMI_SCOPE_SET_DEV(pDevice);
5060 IDirect3DVertexShader9 *pShader = (IDirect3DVertexShader9*)hShaderHandle;
5061 HRESULT hr = S_OK;
5062 pShader->Release();
5063 vboxVDbgPrintF(("<== "__FUNCTION__", hDevice(0x%p), hr(0x%x)\n", hDevice, hr));
5064 return hr;
5065}
5066static HRESULT APIENTRY vboxWddmDDevSetVertexShaderConstI(HANDLE hDevice, CONST D3DDDIARG_SETVERTEXSHADERCONSTI* pData, CONST INT* pRegisters)
5067{
5068 VBOXDISP_DDI_PROLOGUE_DEV(hDevice);
5069 vboxVDbgPrintF(("==> "__FUNCTION__", hDevice(0x%p)\n", hDevice));
5070 PVBOXWDDMDISP_DEVICE pDevice = (PVBOXWDDMDISP_DEVICE)hDevice;
5071 Assert(pDevice);
5072 VBOXDISPCRHGSMI_SCOPE_SET_DEV(pDevice);
5073 IDirect3DDevice9 * pDevice9If = VBOXDISP_D3DEV(pDevice);
5074 HRESULT hr = pDevice9If->SetVertexShaderConstantI(pData->Register, pRegisters, pData->Count);
5075 Assert(hr == S_OK);
5076 vboxVDbgPrintF(("<== "__FUNCTION__", hDevice(0x%p), hr(0x%x)\n", hDevice, hr));
5077 return hr;
5078}
5079static HRESULT APIENTRY vboxWddmDDevSetVertexShaderConstB(HANDLE hDevice, CONST D3DDDIARG_SETVERTEXSHADERCONSTB* pData, CONST BOOL* pRegisters)
5080{
5081 VBOXDISP_DDI_PROLOGUE_DEV(hDevice);
5082 vboxVDbgPrintF(("==> "__FUNCTION__", hDevice(0x%p)\n", hDevice));
5083 PVBOXWDDMDISP_DEVICE pDevice = (PVBOXWDDMDISP_DEVICE)hDevice;
5084 Assert(pDevice);
5085 VBOXDISPCRHGSMI_SCOPE_SET_DEV(pDevice);
5086 IDirect3DDevice9 * pDevice9If = VBOXDISP_D3DEV(pDevice);
5087 HRESULT hr = pDevice9If->SetVertexShaderConstantB(pData->Register, pRegisters, pData->Count);
5088 Assert(hr == S_OK);
5089 vboxVDbgPrintF(("<== "__FUNCTION__", hDevice(0x%p), hr(0x%x)\n", hDevice, hr));
5090 return hr;
5091}
5092static HRESULT APIENTRY vboxWddmDDevSetScissorRect(HANDLE hDevice, CONST RECT* pRect)
5093{
5094 VBOXDISP_DDI_PROLOGUE_DEV(hDevice);
5095 vboxVDbgPrintF(("==> "__FUNCTION__", hDevice(0x%p)\n", hDevice));
5096 PVBOXWDDMDISP_DEVICE pDevice = (PVBOXWDDMDISP_DEVICE)hDevice;
5097 Assert(pDevice);
5098 VBOXDISPCRHGSMI_SCOPE_SET_DEV(pDevice);
5099 IDirect3DDevice9 * pDevice9If = VBOXDISP_D3DEV(pDevice);
5100 HRESULT hr = pDevice9If->SetScissorRect(pRect);
5101 Assert(hr == S_OK);
5102 vboxVDbgPrintF(("<== "__FUNCTION__", hDevice(0x%p), hr(0x%x)\n", hDevice, hr));
5103 return hr;
5104}
5105static HRESULT APIENTRY vboxWddmDDevSetStreamSource(HANDLE hDevice, CONST D3DDDIARG_SETSTREAMSOURCE* pData)
5106{
5107 VBOXDISP_DDI_PROLOGUE_DEV(hDevice);
5108 vboxVDbgPrintF(("==> "__FUNCTION__", hDevice(0x%p)\n", hDevice));
5109 PVBOXWDDMDISP_DEVICE pDevice = (PVBOXWDDMDISP_DEVICE)hDevice;
5110 Assert(pDevice);
5111 VBOXDISPCRHGSMI_SCOPE_SET_DEV(pDevice);
5112 IDirect3DDevice9 * pDevice9If = VBOXDISP_D3DEV(pDevice);
5113 PVBOXWDDMDISP_RESOURCE pRc = (PVBOXWDDMDISP_RESOURCE)pData->hVertexBuffer;
5114 PVBOXWDDMDISP_ALLOCATION pAlloc = NULL;
5115 IDirect3DVertexBuffer9 *pStreamData = NULL;
5116 if (pRc)
5117 {
5118 VBOXVDBG_CHECK_SMSYNC(pRc);
5119 Assert(pRc->cAllocations == 1);
5120 pAlloc = &pRc->aAllocations[0];
5121 Assert(pAlloc->pD3DIf);
5122 pStreamData = (IDirect3DVertexBuffer9*)pAlloc->pD3DIf;
5123 }
5124 HRESULT hr = pDevice9If->SetStreamSource(pData->Stream, pStreamData, pData->Offset, pData->Stride);
5125 Assert(hr == S_OK);
5126 Assert(pData->Stream<VBOXWDDMDISP_MAX_VERTEX_STREAMS);
5127 if (hr == S_OK)
5128 {
5129 if (pDevice->aStreamSource[pData->Stream] && !pAlloc)
5130 {
5131 --pDevice->cStreamSources;
5132 Assert(pDevice->cStreamSources < UINT32_MAX/2);
5133 }
5134 else if (!pDevice->aStreamSource[pData->Stream] && pAlloc)
5135 {
5136 ++pDevice->cStreamSources;
5137 Assert(pDevice->cStreamSources <= RT_ELEMENTS(pDevice->aStreamSource));
5138 }
5139 pDevice->aStreamSource[pData->Stream] = pAlloc;
5140 pDevice->StreamSourceInfo[pData->Stream].uiOffset = pData->Offset;
5141 pDevice->StreamSourceInfo[pData->Stream].uiStride = pData->Stride;
5142
5143 PVBOXWDDMDISP_STREAMSOURCEUM pStrSrcUm = &pDevice->aStreamSourceUm[pData->Stream];
5144 if (pStrSrcUm->pvBuffer)
5145 {
5146 --pDevice->cStreamSourcesUm;
5147 Assert(pDevice->cStreamSourcesUm < UINT32_MAX/2);
5148 pStrSrcUm->pvBuffer = NULL;
5149 pStrSrcUm->cbStride = 0;
5150 }
5151 }
5152 vboxVDbgPrintF(("<== "__FUNCTION__", hDevice(0x%p), hr(0x%x)\n", hDevice, hr));
5153 return hr;
5154}
5155static HRESULT APIENTRY vboxWddmDDevSetStreamSourceFreq(HANDLE hDevice, CONST D3DDDIARG_SETSTREAMSOURCEFREQ* pData)
5156{
5157 VBOXDISP_DDI_PROLOGUE_DEV(hDevice);
5158 vboxVDbgPrintF(("==> "__FUNCTION__", hDevice(0x%p)\n", hDevice));
5159 PVBOXWDDMDISP_DEVICE pDevice = (PVBOXWDDMDISP_DEVICE)hDevice;
5160 Assert(pDevice);
5161 VBOXDISPCRHGSMI_SCOPE_SET_DEV(pDevice);
5162 IDirect3DDevice9 * pDevice9If = VBOXDISP_D3DEV(pDevice);
5163 HRESULT hr = pDevice9If->SetStreamSourceFreq(pData->Stream, pData->Divider);
5164 if (SUCCEEDED(hr))
5165 hr = S_OK;
5166 else
5167 WARN(("SetStreamSourceFreq failed hr 0x%x", hr));
5168
5169#ifdef DEBUG_misha
5170 /* test it more */
5171 Assert(0);
5172#endif
5173 vboxVDbgPrintF(("<== "__FUNCTION__", hDevice(0x%p)\n", hDevice));
5174 return hr;
5175}
5176static HRESULT APIENTRY vboxWddmDDevSetConvolutionKernelMono(HANDLE hDevice, CONST D3DDDIARG_SETCONVOLUTIONKERNELMONO* pData)
5177{
5178 VBOXDISP_DDI_PROLOGUE_DEV(hDevice);
5179 vboxVDbgPrintF(("<== "__FUNCTION__", hDevice(0x%p)\n", hDevice));
5180 PVBOXWDDMDISP_DEVICE pDevice = (PVBOXWDDMDISP_DEVICE)hDevice;
5181 Assert(pDevice);
5182 VBOXDISPCRHGSMI_SCOPE_SET_DEV(pDevice);
5183 Assert(0);
5184 vboxVDbgPrintF(("==> "__FUNCTION__", hDevice(0x%p)\n", hDevice));
5185 return E_FAIL;
5186}
5187static HRESULT APIENTRY vboxWddmDDevComposeRects(HANDLE hDevice, CONST D3DDDIARG_COMPOSERECTS* pData)
5188{
5189 VBOXDISP_DDI_PROLOGUE_DEV(hDevice);
5190 vboxVDbgPrintF(("<== "__FUNCTION__", hDevice(0x%p)\n", hDevice));
5191 PVBOXWDDMDISP_DEVICE pDevice = (PVBOXWDDMDISP_DEVICE)hDevice;
5192 Assert(pDevice);
5193 VBOXDISPCRHGSMI_SCOPE_SET_DEV(pDevice);
5194 Assert(0);
5195 vboxVDbgPrintF(("==> "__FUNCTION__", hDevice(0x%p)\n", hDevice));
5196 return E_FAIL;
5197}
5198
5199static HRESULT APIENTRY vboxWddmDDevBlt(HANDLE hDevice, CONST D3DDDIARG_BLT* pData)
5200{
5201 VBOXDISP_DDI_PROLOGUE_DEV(hDevice);
5202 vboxVDbgPrintF(("==> "__FUNCTION__", hDevice(0x%p)\n", hDevice));
5203 PVBOXWDDMDISP_DEVICE pDevice = (PVBOXWDDMDISP_DEVICE)hDevice;
5204 Assert(pDevice);
5205 VBOXDISPCRHGSMI_SCOPE_SET_DEV(pDevice);
5206// PVBOXWDDMDISP_SCREEN pScreen = &pDevice->aScreens[pDevice->iPrimaryScreen];
5207 IDirect3DDevice9 * pDevice9If = VBOXDISP_D3DEV(pDevice);
5208 PVBOXWDDMDISP_RESOURCE pDstRc = (PVBOXWDDMDISP_RESOURCE)pData->hDstResource;
5209 PVBOXWDDMDISP_RESOURCE pSrcRc = (PVBOXWDDMDISP_RESOURCE)pData->hSrcResource;
5210 VBOXVDBG_CHECK_SMSYNC(pDstRc);
5211 VBOXVDBG_CHECK_SMSYNC(pSrcRc);
5212 Assert(pDstRc->cAllocations > pData->DstSubResourceIndex);
5213 Assert(pSrcRc->cAllocations > pData->SrcSubResourceIndex);
5214 HRESULT hr = S_OK;
5215 PVBOXWDDMDISP_ALLOCATION pSrcAlloc = &pSrcRc->aAllocations[pData->SrcSubResourceIndex];
5216 PVBOXWDDMDISP_ALLOCATION pDstAlloc = &pDstRc->aAllocations[pData->DstSubResourceIndex];
5217 PVBOXWDDMDISP_SWAPCHAIN pSrcSwapchain = vboxWddmSwapchainForAlloc(pSrcAlloc);
5218 PVBOXWDDMDISP_SWAPCHAIN pDstSwapchain = vboxWddmSwapchainForAlloc(pDstAlloc);
5219 /* try StretchRect */
5220 IDirect3DSurface9 *pSrcSurfIf = NULL;
5221 IDirect3DSurface9 *pDstSurfIf = NULL;
5222 Assert(!pDstSwapchain || vboxWddmSwapchainGetFb(pDstSwapchain)->pAlloc != pDstAlloc || vboxWddmSwapchainNumRTs(pDstSwapchain) == 1);
5223
5224 VBOXVDBG_BREAK_SHARED(pSrcRc);
5225 VBOXVDBG_BREAK_SHARED(pDstRc);
5226
5227 hr = VBoxD3DIfSurfGet(pDstRc, pData->DstSubResourceIndex, &pDstSurfIf);
5228 Assert(hr == S_OK);
5229 if (hr == S_OK)
5230 {
5231 Assert(pDstSurfIf);
5232 do
5233 {
5234 if (pSrcSwapchain)
5235 {
5236 hr = vboxWddmSwapchainSurfGet(pDevice, pSrcSwapchain, pSrcAlloc, &pSrcSurfIf);
5237 Assert(hr == S_OK);
5238 }
5239 else
5240 {
5241 hr = VBoxD3DIfSurfGet(pSrcRc, pData->SrcSubResourceIndex, &pSrcSurfIf);
5242 Assert(hr == S_OK);
5243 }
5244
5245 if (hr == S_OK)
5246 {
5247 Assert(pSrcSurfIf);
5248
5249 VBOXVDBG_BREAK_SHARED(pSrcRc);
5250 VBOXVDBG_BREAK_SHARED(pDstRc);
5251
5252 /* we support only Point & Linear, we ignore [Begin|Continue|End]PresentToDwm */
5253 Assert((pData->Flags.Value & (~(0x00000100 | 0x00000200 | 0x00000400 | 0x00000001 | 0x00000002))) == 0);
5254 VBOXVDBG_CHECK_BLT(hr = pDevice9If->StretchRect(pSrcSurfIf, &pData->SrcRect, pDstSurfIf, &pData->DstRect, vboxDDI2D3DBltFlags(pData->Flags)); Assert(hr == S_OK),
5255 pSrcAlloc, pSrcSurfIf, &pData->SrcRect, pDstAlloc, pDstSurfIf, &pData->DstRect);
5256
5257 pSrcSurfIf->Release();
5258 }
5259 } while (0);
5260
5261 pDstSurfIf->Release();
5262 }
5263
5264 if (hr != S_OK)
5265 {
5266 /* todo: fallback to memcpy or whatever ? */
5267 Assert(0);
5268 }
5269
5270 PVBOXWDDMDISP_ALLOCATION pDAlloc = &pDstRc->aAllocations[pData->DstSubResourceIndex];
5271 vboxWddmDalCheckAdd(pDevice, pDAlloc, TRUE);
5272 pDAlloc = &pSrcRc->aAllocations[pData->SrcSubResourceIndex];
5273 vboxWddmDalCheckAdd(pDevice, pDAlloc, FALSE);
5274
5275 vboxVDbgPrintF(("<== "__FUNCTION__", hDevice(0x%p), hr(0x%x)\n", hDevice, hr));
5276 return hr;
5277}
5278static HRESULT APIENTRY vboxWddmDDevColorFill(HANDLE hDevice, CONST D3DDDIARG_COLORFILL* pData)
5279{
5280 VBOXDISP_DDI_PROLOGUE_DEV(hDevice);
5281 vboxVDbgPrintF(("==> "__FUNCTION__", hDevice(0x%p)\n", hDevice));
5282 PVBOXWDDMDISP_DEVICE pDevice = (PVBOXWDDMDISP_DEVICE)hDevice;
5283 Assert(pDevice);
5284 VBOXDISPCRHGSMI_SCOPE_SET_DEV(pDevice);
5285 IDirect3DDevice9 * pDevice9If = VBOXDISP_D3DEV(pDevice);
5286 PVBOXWDDMDISP_RESOURCE pRc = (PVBOXWDDMDISP_RESOURCE)pData->hResource;
5287 Assert(pRc);
5288 IDirect3DSurface9 *pSurfIf = NULL;
5289 HRESULT hr = VBoxD3DIfSurfGet(pRc, pData->SubResourceIndex, &pSurfIf);
5290 Assert(hr == S_OK);
5291 if (hr == S_OK)
5292 {
5293 VBOXVDBG_CHECK_SMSYNC(pRc);
5294 Assert(pSurfIf);
5295 hr = pDevice9If->ColorFill(pSurfIf, &pData->DstRect, pData->Color);
5296 Assert(hr == S_OK);
5297 /* @todo: check what need to do when PresentToDwm flag is set */
5298 Assert(pData->Flags.Value == 0);
5299
5300 pSurfIf->Release();
5301
5302 PVBOXWDDMDISP_ALLOCATION pDAlloc = &pRc->aAllocations[pData->SubResourceIndex];
5303 vboxWddmDalCheckAdd(pDevice, pDAlloc, TRUE);
5304 }
5305 vboxVDbgPrintF(("<== "__FUNCTION__", hDevice(0x%p), hr(0x%x)\n", hDevice, hr));
5306 return hr;
5307}
5308static HRESULT APIENTRY vboxWddmDDevDepthFill(HANDLE hDevice, CONST D3DDDIARG_DEPTHFILL* pData)
5309{
5310 VBOXDISP_DDI_PROLOGUE_DEV(hDevice);
5311 vboxVDbgPrintF(("<== "__FUNCTION__", hDevice(0x%p)\n", hDevice));
5312 PVBOXWDDMDISP_DEVICE pDevice = (PVBOXWDDMDISP_DEVICE)hDevice;
5313 Assert(pDevice);
5314 VBOXDISPCRHGSMI_SCOPE_SET_DEV(pDevice);
5315 Assert(0);
5316//@todo: vboxWddmDalCheckAdd(pDevice, pDAlloc, TRUE);
5317 vboxVDbgPrintF(("==> "__FUNCTION__", hDevice(0x%p)\n", hDevice));
5318 return E_FAIL;
5319}
5320static HRESULT APIENTRY vboxWddmDDevCreateQuery(HANDLE hDevice, D3DDDIARG_CREATEQUERY* pData)
5321{
5322 VBOXDISP_DDI_PROLOGUE_DEV(hDevice);
5323 vboxVDbgPrintF(("==> "__FUNCTION__", hDevice(0x%p)\n", hDevice));
5324 PVBOXWDDMDISP_DEVICE pDevice = (PVBOXWDDMDISP_DEVICE)hDevice;
5325 Assert(pDevice);
5326 VBOXDISPCRHGSMI_SCOPE_SET_DEV(pDevice);
5327
5328 IDirect3DDevice9 * pDevice9If = VBOXDISP_D3DEV(pDevice);
5329 HRESULT hr = S_OK;
5330 PVBOXWDDMDISP_QUERY pQuery = (PVBOXWDDMDISP_QUERY)RTMemAllocZ(sizeof (VBOXWDDMDISP_QUERY));
5331 if (!pQuery)
5332 {
5333 WARN(("RTMemAllocZ failed"));
5334 return E_OUTOFMEMORY;
5335 }
5336
5337 hr = pDevice9If->CreateQuery(vboxDDI2D3DQueryType(pData->QueryType), &pQuery->pQueryIf);
5338 if (FAILED(hr))
5339 {
5340 WARN(("CreateQuery failed, hr 0x%x", hr));
5341 RTMemFree(pQuery);
5342 return hr;
5343 }
5344
5345 Assert(hr == S_OK);
5346
5347 pQuery->enmType = pData->QueryType;
5348 pData->hQuery = pQuery;
5349
5350 vboxVDbgPrintF(("<== "__FUNCTION__", hDevice(0x%p)\n", hDevice));
5351 return hr;
5352}
5353static HRESULT APIENTRY vboxWddmDDevDestroyQuery(HANDLE hDevice, HANDLE hQuery)
5354{
5355 VBOXDISP_DDI_PROLOGUE_DEV(hDevice);
5356 vboxVDbgPrintF(("==> "__FUNCTION__", hDevice(0x%p)\n", hDevice));
5357 HRESULT hr = S_OK;
5358 PVBOXWDDMDISP_DEVICE pDevice = (PVBOXWDDMDISP_DEVICE)hDevice;
5359 Assert(pDevice);
5360 VBOXDISPCRHGSMI_SCOPE_SET_DEV(pDevice);
5361
5362 PVBOXWDDMDISP_QUERY pQuery = (PVBOXWDDMDISP_QUERY)hQuery;
5363 Assert(pQuery);
5364 pQuery->pQueryIf->Release();
5365 RTMemFree(pQuery);
5366 vboxVDbgPrintF(("<== "__FUNCTION__", hDevice(0x%p)\n", hDevice));
5367 return hr;
5368}
5369static HRESULT APIENTRY vboxWddmDDevIssueQuery(HANDLE hDevice, CONST D3DDDIARG_ISSUEQUERY* pData)
5370{
5371 VBOXDISP_DDI_PROLOGUE_DEV(hDevice);
5372 vboxVDbgPrintF(("==> "__FUNCTION__", hDevice(0x%p)\n", hDevice));
5373 HRESULT hr = S_OK;
5374 PVBOXWDDMDISP_DEVICE pDevice = (PVBOXWDDMDISP_DEVICE)hDevice;
5375 Assert(pDevice);
5376 VBOXDISPCRHGSMI_SCOPE_SET_DEV(pDevice);
5377
5378 PVBOXWDDMDISP_QUERY pQuery = (PVBOXWDDMDISP_QUERY)pData->hQuery;
5379 Assert(pQuery);
5380 pQuery->fQueryState.Value |= pData->Flags.Value;
5381 hr = pQuery->pQueryIf->Issue(vboxDDI2D3DIssueQueryFlags(pData->Flags));
5382 if (hr != S_OK)
5383 WARN(("Issue failed, hr = 0x%x", hr));
5384
5385 vboxVDbgPrintF(("<== "__FUNCTION__", hDevice(0x%p)\n", hDevice));
5386 return hr;
5387}
5388static HRESULT APIENTRY vboxWddmDDevGetQueryData(HANDLE hDevice, CONST D3DDDIARG_GETQUERYDATA* pData)
5389{
5390 VBOXDISP_DDI_PROLOGUE_DEV(hDevice);
5391 vboxVDbgPrintF(("==> "__FUNCTION__", hDevice(0x%p)\n", hDevice));
5392 HRESULT hr = S_OK;
5393 PVBOXWDDMDISP_DEVICE pDevice = (PVBOXWDDMDISP_DEVICE)hDevice;
5394 Assert(pDevice);
5395 VBOXDISPCRHGSMI_SCOPE_SET_DEV(pDevice);
5396
5397 PVBOXWDDMDISP_QUERY pQuery = (PVBOXWDDMDISP_QUERY)pData->hQuery;
5398 Assert(pQuery);
5399 DWORD cbData = pQuery->pQueryIf->GetDataSize();
5400#ifdef DEBUG
5401 switch (pQuery->enmType)
5402 {
5403 case D3DDDIQUERYTYPE_EVENT:
5404 Assert(cbData == sizeof (BOOL));
5405 break;
5406 case D3DDDIQUERYTYPE_OCCLUSION:
5407 Assert(cbData == sizeof (UINT));
5408 break;
5409 default:
5410 Assert(0);
5411 break;
5412 }
5413#endif
5414 hr = pQuery->pQueryIf->GetData(pData->pData, cbData, 0);
5415 if (hr != S_OK)
5416 WARN(("GetData failed, hr = 0x%x", hr));
5417
5418 vboxVDbgPrintF(("<== "__FUNCTION__", hDevice(0x%p)\n", hDevice));
5419 return hr;
5420}
5421static HRESULT APIENTRY vboxWddmDDevSetRenderTarget(HANDLE hDevice, CONST D3DDDIARG_SETRENDERTARGET* pData)
5422{
5423 VBOXDISP_DDI_PROLOGUE_DEV(hDevice);
5424 vboxVDbgPrintF(("==> "__FUNCTION__", hDevice(0x%p)\n", hDevice));
5425 PVBOXWDDMDISP_DEVICE pDevice = (PVBOXWDDMDISP_DEVICE)hDevice;
5426 Assert(pDevice);
5427 VBOXDISPCRHGSMI_SCOPE_SET_DEV(pDevice);
5428
5429 IDirect3DDevice9 * pDevice9If = VBOXDISP_D3DEV(pDevice);
5430 PVBOXWDDMDISP_RESOURCE pRc = (PVBOXWDDMDISP_RESOURCE)pData->hRenderTarget;
5431 PVBOXWDDMDISP_ALLOCATION pAlloc = NULL;
5432 if (pRc)
5433 {
5434 VBOXVDBG_CHECK_SMSYNC(pRc);
5435 Assert(pRc);
5436 Assert(pData->SubResourceIndex < pRc->cAllocations);
5437 pAlloc = &pRc->aAllocations[pData->SubResourceIndex];
5438 }
5439 HRESULT hr = vboxWddmRenderTargetSet(pDevice, pData->RenderTargetIndex, pAlloc, FALSE);
5440 Assert(hr == S_OK);
5441 vboxVDbgPrintF(("<== "__FUNCTION__", hDevice(0x%p), hr(0x%x)\n", hDevice, hr));
5442 return hr;
5443}
5444static HRESULT APIENTRY vboxWddmDDevSetDepthStencil(HANDLE hDevice, CONST D3DDDIARG_SETDEPTHSTENCIL* pData)
5445{
5446 VBOXDISP_DDI_PROLOGUE_DEV(hDevice);
5447 vboxVDbgPrintF(("==> "__FUNCTION__", hDevice(0x%p)\n", hDevice));
5448 PVBOXWDDMDISP_DEVICE pDevice = (PVBOXWDDMDISP_DEVICE)hDevice;
5449 Assert(pDevice);
5450 VBOXDISPCRHGSMI_SCOPE_SET_DEV(pDevice);
5451
5452 IDirect3DDevice9 * pDevice9If = VBOXDISP_D3DEV(pDevice);
5453 PVBOXWDDMDISP_RESOURCE pRc = (PVBOXWDDMDISP_RESOURCE)pData->hZBuffer;
5454 IDirect3DSurface9 *pD3D9Surf = NULL;
5455 HRESULT hr = S_OK;
5456 if (pRc)
5457 {
5458 VBOXVDBG_CHECK_SMSYNC(pRc);
5459 Assert(pRc->cAllocations == 1);
5460 hr = VBoxD3DIfSurfGet(pRc, 0, &pD3D9Surf);
5461 if (FAILED(hr))
5462 WARN(("VBoxD3DIfSurfGet failed, hr (0x%x)",hr));
5463 else
5464 Assert(pD3D9Surf);
5465 }
5466
5467 if (SUCCEEDED(hr))
5468 {
5469 hr = pDevice9If->SetDepthStencilSurface(pD3D9Surf);
5470 if (SUCCEEDED(hr))
5471 {
5472 pDevice->pDepthStencilRc = pRc;
5473 hr = S_OK;
5474 }
5475 else
5476 WARN(("VBoxD3DIfSurfGet failed, hr (0x%x)",hr));
5477
5478 if (pD3D9Surf)
5479 pD3D9Surf->Release();
5480 }
5481
5482 vboxVDbgPrintF(("<== "__FUNCTION__", hDevice(0x%p), hr(0x%x)\n", hDevice, hr));
5483 return hr;
5484}
5485static HRESULT APIENTRY vboxWddmDDevGenerateMipSubLevels(HANDLE hDevice, CONST D3DDDIARG_GENERATEMIPSUBLEVELS* pData)
5486{
5487 VBOXDISP_DDI_PROLOGUE_DEV(hDevice);
5488 vboxVDbgPrintF(("<== "__FUNCTION__", hDevice(0x%p)\n", hDevice));
5489 PVBOXWDDMDISP_DEVICE pDevice = (PVBOXWDDMDISP_DEVICE)hDevice;
5490 Assert(pDevice);
5491 VBOXDISPCRHGSMI_SCOPE_SET_DEV(pDevice);
5492
5493 Assert(0);
5494 vboxVDbgPrintF(("==> "__FUNCTION__", hDevice(0x%p)\n", hDevice));
5495 return E_FAIL;
5496}
5497static HRESULT APIENTRY vboxWddmDDevSetPixelShaderConstI(HANDLE hDevice, CONST D3DDDIARG_SETPIXELSHADERCONSTI* pData, CONST INT* pRegisters)
5498{
5499 VBOXDISP_DDI_PROLOGUE_DEV(hDevice);
5500 vboxVDbgPrintF(("==> "__FUNCTION__", hDevice(0x%p)\n", hDevice));
5501 PVBOXWDDMDISP_DEVICE pDevice = (PVBOXWDDMDISP_DEVICE)hDevice;
5502 Assert(pDevice);
5503 VBOXDISPCRHGSMI_SCOPE_SET_DEV(pDevice);
5504
5505 IDirect3DDevice9 * pDevice9If = VBOXDISP_D3DEV(pDevice);
5506 HRESULT hr = pDevice9If->SetPixelShaderConstantI(pData->Register, pRegisters, pData->Count);
5507 Assert(hr == S_OK);
5508 vboxVDbgPrintF(("<== "__FUNCTION__", hDevice(0x%p), hr(0x%x)\n", hDevice, hr));
5509 return hr;
5510}
5511static HRESULT APIENTRY vboxWddmDDevSetPixelShaderConstB(HANDLE hDevice, CONST D3DDDIARG_SETPIXELSHADERCONSTB* pData, CONST BOOL* pRegisters)
5512{
5513 VBOXDISP_DDI_PROLOGUE_DEV(hDevice);
5514 vboxVDbgPrintF(("==> "__FUNCTION__", hDevice(0x%p)\n", hDevice));
5515 PVBOXWDDMDISP_DEVICE pDevice = (PVBOXWDDMDISP_DEVICE)hDevice;
5516 Assert(pDevice);
5517 VBOXDISPCRHGSMI_SCOPE_SET_DEV(pDevice);
5518
5519 IDirect3DDevice9 * pDevice9If = VBOXDISP_D3DEV(pDevice);
5520 HRESULT hr = pDevice9If->SetPixelShaderConstantB(pData->Register, pRegisters, pData->Count);
5521 Assert(hr == S_OK);
5522 vboxVDbgPrintF(("<== "__FUNCTION__", hDevice(0x%p), hr(0x%x)\n", hDevice, hr));
5523 return hr;
5524}
5525static HRESULT APIENTRY vboxWddmDDevCreatePixelShader(HANDLE hDevice, D3DDDIARG_CREATEPIXELSHADER* pData, CONST UINT* pCode)
5526{
5527 VBOXDISP_DDI_PROLOGUE_DEV(hDevice);
5528 vboxVDbgPrintF(("==> "__FUNCTION__", hDevice(0x%p)\n", hDevice));
5529 PVBOXWDDMDISP_DEVICE pDevice = (PVBOXWDDMDISP_DEVICE)hDevice;
5530 Assert(pDevice);
5531 VBOXDISPCRHGSMI_SCOPE_SET_DEV(pDevice);
5532
5533 IDirect3DDevice9 * pDevice9If = VBOXDISP_D3DEV(pDevice);
5534 IDirect3DPixelShader9 *pShader;
5535 Assert(*((UINT*)((uint8_t*)pCode + pData->CodeSize-4)) == 0x0000FFFF /* end token */);
5536 HRESULT hr = pDevice9If->CreatePixelShader((const DWORD *)pCode, &pShader);
5537 Assert(hr == S_OK);
5538 if (hr == S_OK)
5539 {
5540 Assert(pShader);
5541 pData->ShaderHandle = pShader;
5542 }
5543 vboxVDbgPrintF(("<== "__FUNCTION__", hDevice(0x%p), hr(0x%x)\n", hDevice, hr));
5544 return hr;
5545}
5546static HRESULT APIENTRY vboxWddmDDevDeletePixelShader(HANDLE hDevice, HANDLE hShaderHandle)
5547{
5548 VBOXDISP_DDI_PROLOGUE_DEV(hDevice);
5549 vboxVDbgPrintF(("==> "__FUNCTION__", hDevice(0x%p)\n", hDevice));
5550 PVBOXWDDMDISP_DEVICE pDevice = (PVBOXWDDMDISP_DEVICE)hDevice;
5551 Assert(pDevice);
5552 VBOXDISPCRHGSMI_SCOPE_SET_DEV(pDevice);
5553
5554 IDirect3DPixelShader9 *pShader = (IDirect3DPixelShader9*)hShaderHandle;
5555 HRESULT hr = S_OK;
5556 pShader->Release();
5557 vboxVDbgPrintF(("<== "__FUNCTION__", hDevice(0x%p), hr(0x%x)\n", hDevice, hr));
5558 return hr;
5559}
5560static HRESULT APIENTRY vboxWddmDDevCreateDecodeDevice(HANDLE hDevice, D3DDDIARG_CREATEDECODEDEVICE* pData)
5561{
5562 VBOXDISP_DDI_PROLOGUE_DEV(hDevice);
5563 vboxVDbgPrintF(("<== "__FUNCTION__", hDevice(0x%p)\n", hDevice));
5564 PVBOXWDDMDISP_DEVICE pDevice = (PVBOXWDDMDISP_DEVICE)hDevice;
5565 Assert(pDevice);
5566 VBOXDISPCRHGSMI_SCOPE_SET_DEV(pDevice);
5567
5568 Assert(0);
5569 vboxVDbgPrintF(("==> "__FUNCTION__", hDevice(0x%p)\n", hDevice));
5570 return E_FAIL;
5571}
5572static HRESULT APIENTRY vboxWddmDDevDestroyDecodeDevice(HANDLE hDevice, HANDLE hDecodeDevice)
5573{
5574 VBOXDISP_DDI_PROLOGUE_DEV(hDevice);
5575 vboxVDbgPrintF(("<== "__FUNCTION__", hDevice(0x%p)\n", hDevice));
5576 PVBOXWDDMDISP_DEVICE pDevice = (PVBOXWDDMDISP_DEVICE)hDevice;
5577 Assert(pDevice);
5578 VBOXDISPCRHGSMI_SCOPE_SET_DEV(pDevice);
5579
5580 Assert(0);
5581 vboxVDbgPrintF(("==> "__FUNCTION__", hDevice(0x%p)\n", hDevice));
5582 return E_FAIL;
5583}
5584static HRESULT APIENTRY vboxWddmDDevSetDecodeRenderTarget(HANDLE hDevice, CONST D3DDDIARG_SETDECODERENDERTARGET* pData)
5585{
5586 VBOXDISP_DDI_PROLOGUE_DEV(hDevice);
5587 vboxVDbgPrintF(("<== "__FUNCTION__", hDevice(0x%p)\n", hDevice));
5588 PVBOXWDDMDISP_DEVICE pDevice = (PVBOXWDDMDISP_DEVICE)hDevice;
5589 Assert(pDevice);
5590 VBOXDISPCRHGSMI_SCOPE_SET_DEV(pDevice);
5591
5592 Assert(0);
5593 vboxVDbgPrintF(("==> "__FUNCTION__", hDevice(0x%p)\n", hDevice));
5594 return E_FAIL;
5595}
5596static HRESULT APIENTRY vboxWddmDDevDecodeBeginFrame(HANDLE hDevice, D3DDDIARG_DECODEBEGINFRAME* pData)
5597{
5598 VBOXDISP_DDI_PROLOGUE_DEV(hDevice);
5599 vboxVDbgPrintF(("<== "__FUNCTION__", hDevice(0x%p)\n", hDevice));
5600 PVBOXWDDMDISP_DEVICE pDevice = (PVBOXWDDMDISP_DEVICE)hDevice;
5601 Assert(pDevice);
5602 VBOXDISPCRHGSMI_SCOPE_SET_DEV(pDevice);
5603
5604 Assert(0);
5605 vboxVDbgPrintF(("==> "__FUNCTION__", hDevice(0x%p)\n", hDevice));
5606 return E_FAIL;
5607}
5608static HRESULT APIENTRY vboxWddmDDevDecodeEndFrame(HANDLE hDevice, D3DDDIARG_DECODEENDFRAME* pData)
5609{
5610 VBOXDISP_DDI_PROLOGUE_DEV(hDevice);
5611 vboxVDbgPrintF(("<== "__FUNCTION__", hDevice(0x%p)\n", hDevice));
5612 PVBOXWDDMDISP_DEVICE pDevice = (PVBOXWDDMDISP_DEVICE)hDevice;
5613 Assert(pDevice);
5614 VBOXDISPCRHGSMI_SCOPE_SET_DEV(pDevice);
5615
5616 Assert(0);
5617 vboxVDbgPrintF(("==> "__FUNCTION__", hDevice(0x%p)\n", hDevice));
5618 return E_FAIL;
5619}
5620static HRESULT APIENTRY vboxWddmDDevDecodeExecute(HANDLE hDevice, CONST D3DDDIARG_DECODEEXECUTE* pData)
5621{
5622 VBOXDISP_DDI_PROLOGUE_DEV(hDevice);
5623 vboxVDbgPrintF(("<== "__FUNCTION__", hDevice(0x%p)\n", hDevice));
5624 PVBOXWDDMDISP_DEVICE pDevice = (PVBOXWDDMDISP_DEVICE)hDevice;
5625 Assert(pDevice);
5626 VBOXDISPCRHGSMI_SCOPE_SET_DEV(pDevice);
5627
5628 Assert(0);
5629 vboxVDbgPrintF(("==> "__FUNCTION__", hDevice(0x%p)\n", hDevice));
5630 return E_FAIL;
5631}
5632static HRESULT APIENTRY vboxWddmDDevDecodeExtensionExecute(HANDLE hDevice, CONST D3DDDIARG_DECODEEXTENSIONEXECUTE* pData)
5633{
5634 VBOXDISP_DDI_PROLOGUE_DEV(hDevice);
5635 vboxVDbgPrintF(("<== "__FUNCTION__", hDevice(0x%p)\n", hDevice));
5636 PVBOXWDDMDISP_DEVICE pDevice = (PVBOXWDDMDISP_DEVICE)hDevice;
5637 Assert(pDevice);
5638 VBOXDISPCRHGSMI_SCOPE_SET_DEV(pDevice);
5639
5640 Assert(0);
5641 vboxVDbgPrintF(("==> "__FUNCTION__", hDevice(0x%p)\n", hDevice));
5642 return E_FAIL;
5643}
5644static HRESULT APIENTRY vboxWddmDDevCreateVideoProcessDevice(HANDLE hDevice, D3DDDIARG_CREATEVIDEOPROCESSDEVICE* pData)
5645{
5646 VBOXDISP_DDI_PROLOGUE_DEV(hDevice);
5647 vboxVDbgPrintF(("<== "__FUNCTION__", hDevice(0x%p)\n", hDevice));
5648 PVBOXWDDMDISP_DEVICE pDevice = (PVBOXWDDMDISP_DEVICE)hDevice;
5649 Assert(pDevice);
5650 VBOXDISPCRHGSMI_SCOPE_SET_DEV(pDevice);
5651
5652 Assert(0);
5653 vboxVDbgPrintF(("==> "__FUNCTION__", hDevice(0x%p)\n", hDevice));
5654 return E_FAIL;
5655}
5656static HRESULT APIENTRY vboxWddmDDevDestroyVideoProcessDevice(HANDLE hDevice, HANDLE hVideoProcessor)
5657{
5658 VBOXDISP_DDI_PROLOGUE_DEV(hDevice);
5659 vboxVDbgPrintF(("<== "__FUNCTION__", hDevice(0x%p)\n", hDevice));
5660 PVBOXWDDMDISP_DEVICE pDevice = (PVBOXWDDMDISP_DEVICE)hDevice;
5661 Assert(pDevice);
5662 VBOXDISPCRHGSMI_SCOPE_SET_DEV(pDevice);
5663
5664 Assert(0);
5665 vboxVDbgPrintF(("==> "__FUNCTION__", hDevice(0x%p)\n", hDevice));
5666 return E_FAIL;
5667}
5668static HRESULT APIENTRY vboxWddmDDevVideoProcessBeginFrame(HANDLE hDevice, HANDLE hVideoProcess)
5669{
5670 VBOXDISP_DDI_PROLOGUE_DEV(hDevice);
5671 vboxVDbgPrintF(("<== "__FUNCTION__", hDevice(0x%p)\n", hDevice));
5672 PVBOXWDDMDISP_DEVICE pDevice = (PVBOXWDDMDISP_DEVICE)hDevice;
5673 Assert(pDevice);
5674 VBOXDISPCRHGSMI_SCOPE_SET_DEV(pDevice);
5675
5676 Assert(0);
5677 vboxVDbgPrintF(("==> "__FUNCTION__", hDevice(0x%p)\n", hDevice));
5678 return E_FAIL;
5679}
5680static HRESULT APIENTRY vboxWddmDDevVideoProcessEndFrame(HANDLE hDevice, D3DDDIARG_VIDEOPROCESSENDFRAME* pData)
5681{
5682 VBOXDISP_DDI_PROLOGUE_DEV(hDevice);
5683 vboxVDbgPrintF(("<== "__FUNCTION__", hDevice(0x%p)\n", hDevice));
5684 PVBOXWDDMDISP_DEVICE pDevice = (PVBOXWDDMDISP_DEVICE)hDevice;
5685 Assert(pDevice);
5686 VBOXDISPCRHGSMI_SCOPE_SET_DEV(pDevice);
5687
5688 Assert(0);
5689 vboxVDbgPrintF(("==> "__FUNCTION__", hDevice(0x%p)\n", hDevice));
5690 return E_FAIL;
5691}
5692static HRESULT APIENTRY vboxWddmDDevSetVideoProcessRenderTarget(HANDLE hDevice, CONST D3DDDIARG_SETVIDEOPROCESSRENDERTARGET* pData)
5693{
5694 VBOXDISP_DDI_PROLOGUE_DEV(hDevice);
5695 vboxVDbgPrintF(("<== "__FUNCTION__", hDevice(0x%p)\n", hDevice));
5696 PVBOXWDDMDISP_DEVICE pDevice = (PVBOXWDDMDISP_DEVICE)hDevice;
5697 Assert(pDevice);
5698 VBOXDISPCRHGSMI_SCOPE_SET_DEV(pDevice);
5699
5700 Assert(0);
5701 vboxVDbgPrintF(("==> "__FUNCTION__", hDevice(0x%p)\n", hDevice));
5702 return E_FAIL;
5703}
5704static HRESULT APIENTRY vboxWddmDDevVideoProcessBlt(HANDLE hDevice, CONST D3DDDIARG_VIDEOPROCESSBLT* pData)
5705{
5706 VBOXDISP_DDI_PROLOGUE_DEV(hDevice);
5707 vboxVDbgPrintF(("<== "__FUNCTION__", hDevice(0x%p)\n", hDevice));
5708 PVBOXWDDMDISP_DEVICE pDevice = (PVBOXWDDMDISP_DEVICE)hDevice;
5709 Assert(pDevice);
5710 VBOXDISPCRHGSMI_SCOPE_SET_DEV(pDevice);
5711
5712 Assert(0);
5713 vboxVDbgPrintF(("==> "__FUNCTION__", hDevice(0x%p)\n", hDevice));
5714 return E_FAIL;
5715}
5716static HRESULT APIENTRY vboxWddmDDevCreateExtensionDevice(HANDLE hDevice, D3DDDIARG_CREATEEXTENSIONDEVICE* pData)
5717{
5718 VBOXDISP_DDI_PROLOGUE_DEV(hDevice);
5719 vboxVDbgPrintF(("<== "__FUNCTION__", hDevice(0x%p)\n", hDevice));
5720 PVBOXWDDMDISP_DEVICE pDevice = (PVBOXWDDMDISP_DEVICE)hDevice;
5721 Assert(pDevice);
5722 VBOXDISPCRHGSMI_SCOPE_SET_DEV(pDevice);
5723
5724 Assert(0);
5725 vboxVDbgPrintF(("==> "__FUNCTION__", hDevice(0x%p)\n", hDevice));
5726 return E_FAIL;
5727}
5728static HRESULT APIENTRY vboxWddmDDevDestroyExtensionDevice(HANDLE hDevice, HANDLE hExtension)
5729{
5730 VBOXDISP_DDI_PROLOGUE_DEV(hDevice);
5731 vboxVDbgPrintF(("<== "__FUNCTION__", hDevice(0x%p)\n", hDevice));
5732 PVBOXWDDMDISP_DEVICE pDevice = (PVBOXWDDMDISP_DEVICE)hDevice;
5733 Assert(pDevice);
5734 VBOXDISPCRHGSMI_SCOPE_SET_DEV(pDevice);
5735
5736 Assert(0);
5737 vboxVDbgPrintF(("==> "__FUNCTION__", hDevice(0x%p)\n", hDevice));
5738 return E_FAIL;
5739}
5740static HRESULT APIENTRY vboxWddmDDevExtensionExecute(HANDLE hDevice, CONST D3DDDIARG_EXTENSIONEXECUTE* pData)
5741{
5742 VBOXDISP_DDI_PROLOGUE_DEV(hDevice);
5743 vboxVDbgPrintF(("<== "__FUNCTION__", hDevice(0x%p)\n", hDevice));
5744 PVBOXWDDMDISP_DEVICE pDevice = (PVBOXWDDMDISP_DEVICE)hDevice;
5745 Assert(pDevice);
5746 VBOXDISPCRHGSMI_SCOPE_SET_DEV(pDevice);
5747
5748 Assert(0);
5749 vboxVDbgPrintF(("==> "__FUNCTION__", hDevice(0x%p)\n", hDevice));
5750 return E_FAIL;
5751}
5752static HRESULT APIENTRY vboxWddmDDevDestroyDevice(IN HANDLE hDevice)
5753{
5754 VBOXDISP_DDI_PROLOGUE_DEV(hDevice);
5755 vboxVDbgPrintF(("==> "__FUNCTION__", hDevice(0x%p)\n", hDevice));
5756
5757 PVBOXWDDMDISP_DEVICE pDevice = (PVBOXWDDMDISP_DEVICE)hDevice;
5758 Assert(pDevice);
5759 VBOXDISPCRHGSMI_SCOPE_SET_DEV(pDevice);
5760
5761 VBOXDISPPROFILE_DDI_PRINT(("Dumping on DestroyDevice: 0x%p", pDevice));
5762 VBOXDISPPROFILE_DDI_TERM(pDevice);
5763
5764#ifdef VBOXWDDMDISP_DEBUG_TIMER
5765 DeleteTimerQueueEx(pDevice->hTimerQueue, INVALID_HANDLE_VALUE /* see term */);
5766 pDevice->hTimerQueue = NULL;
5767#endif
5768
5769 PVBOXWDDMDISP_ADAPTER pAdapter = pDevice->pAdapter;
5770 if (VBOXDISPMODE_IS_3D(pAdapter))
5771 {
5772 vboxWddmSwapchainDestroyAll(pDevice);
5773 /* ensure the device is destroyed in any way.
5774 * Release may not work in case of some leaking, which will leave the crOgl context refering the destroyed VBOXUHGSMI */
5775 if (pDevice->pDevice9If)
5776 pDevice->pAdapter->D3D.D3D.pfnVBoxWineExD3DDev9Term((IDirect3DDevice9Ex *)pDevice->pDevice9If);
5777 }
5778
5779 HRESULT hr = vboxDispCmCtxDestroy(pDevice, &pDevice->DefaultContext);
5780 Assert(hr == S_OK);
5781 if (hr == S_OK)
5782 {
5783 if (pDevice->hHgsmiTransportModule)
5784 FreeLibrary(pDevice->hHgsmiTransportModule);
5785 RTMemFree(pDevice);
5786 }
5787 vboxVDbgPrintF(("<== "__FUNCTION__", hDevice(0x%p)\n", hDevice));
5788 return hr;
5789}
5790
5791AssertCompile(sizeof (RECT) == sizeof (D3DDDIRECT));
5792AssertCompile(RT_SIZEOFMEMB(RECT, left) == RT_SIZEOFMEMB(D3DDDIRECT, left));
5793AssertCompile(RT_SIZEOFMEMB(RECT, right) == RT_SIZEOFMEMB(D3DDDIRECT, right));
5794AssertCompile(RT_SIZEOFMEMB(RECT, top) == RT_SIZEOFMEMB(D3DDDIRECT, top));
5795AssertCompile(RT_SIZEOFMEMB(RECT, bottom) == RT_SIZEOFMEMB(D3DDDIRECT, bottom));
5796AssertCompile(RT_OFFSETOF(RECT, left) == RT_OFFSETOF(D3DDDIRECT, left));
5797AssertCompile(RT_OFFSETOF(RECT, right) == RT_OFFSETOF(D3DDDIRECT, right));
5798AssertCompile(RT_OFFSETOF(RECT, top) == RT_OFFSETOF(D3DDDIRECT, top));
5799AssertCompile(RT_OFFSETOF(RECT, bottom) == RT_OFFSETOF(D3DDDIRECT, bottom));
5800
5801static HRESULT APIENTRY vboxWddmDDevCreateOverlay(HANDLE hDevice, D3DDDIARG_CREATEOVERLAY* pData)
5802{
5803 VBOXDISP_DDI_PROLOGUE_DEV(hDevice);
5804 vboxVDbgPrintF(("==> "__FUNCTION__", hDevice(0x%p)\n", hDevice));
5805 PVBOXWDDMDISP_DEVICE pDevice = (PVBOXWDDMDISP_DEVICE)hDevice;
5806 PVBOXWDDMDISP_RESOURCE pRc = (PVBOXWDDMDISP_RESOURCE)pData->OverlayInfo.hResource;
5807 Assert(pRc);
5808 Assert(pRc->cAllocations > pData->OverlayInfo.SubResourceIndex);
5809 PVBOXWDDMDISP_ALLOCATION pAlloc = &pRc->aAllocations[pData->OverlayInfo.SubResourceIndex];
5810 HRESULT hr = S_OK;
5811 PVBOXWDDMDISP_OVERLAY pOverlay = (PVBOXWDDMDISP_OVERLAY)RTMemAllocZ(sizeof (VBOXWDDMDISP_OVERLAY));
5812 Assert(pOverlay);
5813 if (pOverlay)
5814 {
5815 VBOXWDDM_OVERLAY_INFO OurInfo;
5816 OurInfo.OverlayDesc.DstColorKeyLow = pData->OverlayInfo.DstColorKeyLow;
5817 OurInfo.OverlayDesc.DstColorKeyHigh = pData->OverlayInfo.DstColorKeyHigh;
5818 OurInfo.OverlayDesc.SrcColorKeyLow = pData->OverlayInfo.SrcColorKeyLow;
5819 OurInfo.OverlayDesc.SrcColorKeyHigh = pData->OverlayInfo.SrcColorKeyHigh;
5820 OurInfo.OverlayDesc.fFlags = pData->OverlayInfo.Flags.Value;
5821 vboxWddmDirtyRegionClear(&OurInfo.DirtyRegion);
5822 Assert(!pAlloc->LockInfo.cLocks);
5823 vboxWddmDirtyRegionUnite(&OurInfo.DirtyRegion, &pAlloc->DirtyRegion);
5824 D3DDDICB_CREATEOVERLAY OverInfo;
5825 OverInfo.VidPnSourceId = pData->VidPnSourceId;
5826 OverInfo.OverlayInfo.hAllocation = pAlloc->hAllocation;
5827 Assert(pAlloc->hAllocation);
5828 OverInfo.OverlayInfo.DstRect = *(D3DDDIRECT*)((void*)&pData->OverlayInfo.DstRect);
5829 OverInfo.OverlayInfo.SrcRect = *(D3DDDIRECT*)((void*)&pData->OverlayInfo.SrcRect);
5830 OverInfo.OverlayInfo.pPrivateDriverData = &OurInfo;
5831 OverInfo.OverlayInfo.PrivateDriverDataSize = sizeof (OurInfo);
5832 OverInfo.hKernelOverlay = NULL; /* <-- out */
5833#ifndef VBOXWDDMOVERLAY_TEST
5834 hr = pDevice->RtCallbacks.pfnCreateOverlayCb(pDevice->hDevice, &OverInfo);
5835 Assert(hr == S_OK);
5836 if (hr == S_OK)
5837 {
5838 Assert(OverInfo.hKernelOverlay);
5839 pOverlay->hOverlay = OverInfo.hKernelOverlay;
5840 pOverlay->VidPnSourceId = pData->VidPnSourceId;
5841
5842 Assert(!pAlloc->LockInfo.cLocks);
5843 if (!pAlloc->LockInfo.cLocks)
5844 {
5845 /* we have reported the dirty rect, may clear it if no locks are pending currently */
5846 vboxWddmDirtyRegionClear(&pAlloc->DirtyRegion);
5847 }
5848
5849 pData->hOverlay = pOverlay;
5850 }
5851 else
5852 {
5853 RTMemFree(pOverlay);
5854 }
5855#else
5856 pData->hOverlay = pOverlay;
5857#endif
5858 }
5859 else
5860 hr = E_OUTOFMEMORY;
5861
5862 vboxVDbgPrintF(("<== "__FUNCTION__", hDevice(0x%p)\n", hDevice));
5863 return hr;
5864}
5865static HRESULT APIENTRY vboxWddmDDevUpdateOverlay(HANDLE hDevice, CONST D3DDDIARG_UPDATEOVERLAY* pData)
5866{
5867 VBOXDISP_DDI_PROLOGUE_DEV(hDevice);
5868 vboxVDbgPrintF(("==> "__FUNCTION__", hDevice(0x%p)\n", hDevice));
5869 PVBOXWDDMDISP_DEVICE pDevice = (PVBOXWDDMDISP_DEVICE)hDevice;
5870 PVBOXWDDMDISP_RESOURCE pRc = (PVBOXWDDMDISP_RESOURCE)pData->OverlayInfo.hResource;
5871 Assert(pRc);
5872 Assert(pRc->cAllocations > pData->OverlayInfo.SubResourceIndex);
5873 PVBOXWDDMDISP_ALLOCATION pAlloc = &pRc->aAllocations[pData->OverlayInfo.SubResourceIndex];
5874 HRESULT hr = S_OK;
5875 PVBOXWDDMDISP_OVERLAY pOverlay = (PVBOXWDDMDISP_OVERLAY)pData->hOverlay;
5876 VBOXWDDM_OVERLAY_INFO OurInfo;
5877 OurInfo.OverlayDesc.DstColorKeyLow = pData->OverlayInfo.DstColorKeyLow;
5878 OurInfo.OverlayDesc.DstColorKeyHigh = pData->OverlayInfo.DstColorKeyHigh;
5879 OurInfo.OverlayDesc.SrcColorKeyLow = pData->OverlayInfo.SrcColorKeyLow;
5880 OurInfo.OverlayDesc.SrcColorKeyHigh = pData->OverlayInfo.SrcColorKeyHigh;
5881 OurInfo.OverlayDesc.fFlags = pData->OverlayInfo.Flags.Value;
5882 vboxWddmDirtyRegionClear(&OurInfo.DirtyRegion);
5883 Assert(!pAlloc->LockInfo.cLocks);
5884 vboxWddmDirtyRegionUnite(&OurInfo.DirtyRegion, &pAlloc->DirtyRegion);
5885 D3DDDICB_UPDATEOVERLAY OverInfo;
5886 OverInfo.hKernelOverlay = pOverlay->hOverlay;
5887 OverInfo.OverlayInfo.hAllocation = pAlloc->hAllocation;
5888 OverInfo.OverlayInfo.DstRect = *(D3DDDIRECT*)((void*)&pData->OverlayInfo.DstRect);
5889 OverInfo.OverlayInfo.SrcRect = *(D3DDDIRECT*)((void*)&pData->OverlayInfo.SrcRect);
5890 OverInfo.OverlayInfo.pPrivateDriverData = &OurInfo;
5891 OverInfo.OverlayInfo.PrivateDriverDataSize = sizeof (OurInfo);
5892#ifndef VBOXWDDMOVERLAY_TEST
5893 hr = pDevice->RtCallbacks.pfnUpdateOverlayCb(pDevice->hDevice, &OverInfo);
5894 Assert(hr == S_OK);
5895 if (hr == S_OK)
5896#endif
5897 {
5898 Assert(!pAlloc->LockInfo.cLocks);
5899 if (!pAlloc->LockInfo.cLocks)
5900 {
5901 /* we have reported the dirty rect, may clear it if no locks are pending currently */
5902 vboxWddmDirtyRegionClear(&pAlloc->DirtyRegion);
5903 }
5904 }
5905
5906 vboxVDbgPrintF(("<== "__FUNCTION__", hDevice(0x%p)\n", hDevice));
5907 return hr;
5908}
5909static HRESULT APIENTRY vboxWddmDDevFlipOverlay(HANDLE hDevice, CONST D3DDDIARG_FLIPOVERLAY* pData)
5910{
5911 VBOXDISP_DDI_PROLOGUE_DEV(hDevice);
5912 vboxVDbgPrintF(("==> "__FUNCTION__", hDevice(0x%p)\n", hDevice));
5913 PVBOXWDDMDISP_DEVICE pDevice = (PVBOXWDDMDISP_DEVICE)hDevice;
5914 PVBOXWDDMDISP_RESOURCE pRc = (PVBOXWDDMDISP_RESOURCE)pData->hSource;
5915 Assert(pRc);
5916 Assert(pRc->cAllocations > pData->SourceIndex);
5917 PVBOXWDDMDISP_ALLOCATION pAlloc = &pRc->aAllocations[pData->SourceIndex];
5918 HRESULT hr = S_OK;
5919 PVBOXWDDMDISP_OVERLAY pOverlay = (PVBOXWDDMDISP_OVERLAY)pData->hOverlay;
5920 VBOXWDDM_OVERLAYFLIP_INFO OurInfo;
5921 vboxWddmDirtyRegionClear(&OurInfo.DirtyRegion);
5922 Assert(!pAlloc->LockInfo.cLocks);
5923 vboxWddmDirtyRegionUnite(&OurInfo.DirtyRegion, &pAlloc->DirtyRegion);
5924 D3DDDICB_FLIPOVERLAY OverInfo;
5925 OverInfo.hKernelOverlay = pOverlay->hOverlay;
5926 OverInfo.hSource = pAlloc->hAllocation;
5927 OverInfo.pPrivateDriverData = &OurInfo;
5928 OverInfo.PrivateDriverDataSize = sizeof (OurInfo);
5929#ifndef VBOXWDDMOVERLAY_TEST
5930 hr = pDevice->RtCallbacks.pfnFlipOverlayCb(pDevice->hDevice, &OverInfo);
5931 Assert(hr == S_OK);
5932 if (hr == S_OK)
5933#endif
5934 {
5935 Assert(!pAlloc->LockInfo.cLocks);
5936 if (!pAlloc->LockInfo.cLocks)
5937 {
5938 /* we have reported the dirty rect, may clear it if no locks are pending currently */
5939 vboxWddmDirtyRegionClear(&pAlloc->DirtyRegion);
5940 }
5941 }
5942
5943 vboxVDbgPrintF(("<== "__FUNCTION__", hDevice(0x%p)\n", hDevice));
5944 return hr;
5945}
5946static HRESULT APIENTRY vboxWddmDDevGetOverlayColorControls(HANDLE hDevice, D3DDDIARG_GETOVERLAYCOLORCONTROLS* pData)
5947{
5948 VBOXDISP_DDI_PROLOGUE_DEV(hDevice);
5949 vboxVDbgPrintF(("<== "__FUNCTION__", hDevice(0x%p)\n", hDevice));
5950 Assert(0);
5951 vboxVDbgPrintF(("==> "__FUNCTION__", hDevice(0x%p)\n", hDevice));
5952 return E_FAIL;
5953}
5954static HRESULT APIENTRY vboxWddmDDevSetOverlayColorControls(HANDLE hDevice, CONST D3DDDIARG_SETOVERLAYCOLORCONTROLS* pData)
5955{
5956 VBOXDISP_DDI_PROLOGUE_DEV(hDevice);
5957 vboxVDbgPrintF(("<== "__FUNCTION__", hDevice(0x%p)\n", hDevice));
5958 Assert(0);
5959 vboxVDbgPrintF(("==> "__FUNCTION__", hDevice(0x%p)\n", hDevice));
5960 return E_FAIL;
5961}
5962static HRESULT APIENTRY vboxWddmDDevDestroyOverlay(HANDLE hDevice, CONST D3DDDIARG_DESTROYOVERLAY* pData)
5963{
5964 VBOXDISP_DDI_PROLOGUE_DEV(hDevice);
5965 vboxVDbgPrintF(("==> "__FUNCTION__", hDevice(0x%p)\n", hDevice));
5966 PVBOXWDDMDISP_DEVICE pDevice = (PVBOXWDDMDISP_DEVICE)hDevice;
5967 PVBOXWDDMDISP_OVERLAY pOverlay = (PVBOXWDDMDISP_OVERLAY)pData->hOverlay;
5968 D3DDDICB_DESTROYOVERLAY OverInfo;
5969 OverInfo.hKernelOverlay = pOverlay->hOverlay;
5970#ifndef VBOXWDDMOVERLAY_TEST
5971 HRESULT hr = pDevice->RtCallbacks.pfnDestroyOverlayCb(pDevice->hDevice, &OverInfo);
5972 Assert(hr == S_OK);
5973 if (hr == S_OK)
5974#else
5975 HRESULT hr = S_OK;
5976#endif
5977 {
5978 RTMemFree(pOverlay);
5979 }
5980
5981 vboxVDbgPrintF(("<== "__FUNCTION__", hDevice(0x%p)\n", hDevice));
5982 return hr;
5983}
5984static HRESULT APIENTRY vboxWddmDDevQueryResourceResidency(HANDLE hDevice, CONST D3DDDIARG_QUERYRESOURCERESIDENCY* pData)
5985{
5986 VBOXDISP_DDI_PROLOGUE_DEV(hDevice);
5987 vboxVDbgPrintF(("==> "__FUNCTION__", hDevice(0x%p)\n", hDevice));
5988 PVBOXWDDMDISP_DEVICE pDevice = (PVBOXWDDMDISP_DEVICE)hDevice;
5989
5990 HRESULT hr = S_OK;
5991 /* @todo check residency for the "real" allocations */
5992#if 0
5993 for (UINT i = 0; i < pData->NumResources; ++i)
5994 {
5995 PVBOXWDDMDISP_RESOURCE pRc = (PVBOXWDDMDISP_RESOURCE)pData->pHandleList[i];
5996 Assert(pRc->pDevice == pDevice);
5997 if (pRc->hKMResource)
5998 {
5999
6000 }
6001 }
6002#endif
6003 vboxVDbgPrintF(("<== "__FUNCTION__", hDevice(0x%p)\n", hDevice));
6004 return hr;
6005}
6006
6007static HRESULT APIENTRY vboxWddmDDevOpenResource(HANDLE hDevice, D3DDDIARG_OPENRESOURCE* pData)
6008{
6009 VBOXDISP_DDI_PROLOGUE_DEV(hDevice);
6010 vboxVDbgPrintF(("==> "__FUNCTION__", hDevice(0x%p)\n", hDevice));
6011 PVBOXWDDMDISP_DEVICE pDevice = (PVBOXWDDMDISP_DEVICE)hDevice;
6012 Assert(pDevice);
6013 VBOXDISPCRHGSMI_SCOPE_SET_DEV(pDevice);
6014
6015 HRESULT hr = S_OK;
6016
6017 Assert(pData->hKMResource);
6018
6019 Assert(pData->NumAllocations);
6020 PVBOXWDDMDISP_RESOURCE pRc = vboxResourceAlloc(pData->NumAllocations);
6021 Assert(pRc);
6022 if (pRc)
6023 {
6024 pRc->hResource = pData->hResource;
6025 pRc->hKMResource = pData->hKMResource;
6026 pRc->pDevice = pDevice;
6027 pRc->RcDesc.enmRotation = pData->Rotation;
6028 pRc->fFlags.Value = 0;
6029 pRc->fFlags.Opened = 1;
6030 pRc->fFlags.KmResource = 1;
6031
6032 for (UINT i = 0; i < pData->NumAllocations; ++i)
6033 {
6034 PVBOXWDDMDISP_ALLOCATION pAllocation = &pRc->aAllocations[i];
6035 D3DDDI_OPENALLOCATIONINFO* pOAI = pData->pOpenAllocationInfo;
6036 Assert(pOAI->PrivateDriverDataSize == sizeof (VBOXWDDM_ALLOCINFO));
6037 if (pOAI->PrivateDriverDataSize != sizeof (VBOXWDDM_ALLOCINFO))
6038 {
6039 hr = E_INVALIDARG;
6040 break;
6041 }
6042 Assert(pOAI->pPrivateDriverData);
6043 PVBOXWDDM_ALLOCINFO pAllocInfo = (PVBOXWDDM_ALLOCINFO)pOAI->pPrivateDriverData;
6044 pAllocation->hAllocation = pOAI->hAllocation;
6045 pAllocation->enmType = pAllocInfo->enmType;
6046 pAllocation->hSharedHandle = (HANDLE)pAllocInfo->hSharedHandle;
6047 pAllocation->SurfDesc = pAllocInfo->SurfDesc;
6048 pAllocation->pvMem = NULL;
6049#ifndef VBOXWDDMDISP_DEBUG_NOSHARED
6050 Assert(!pAllocation->hSharedHandle == (pAllocation->enmType == VBOXWDDM_ALLOC_TYPE_STD_SHAREDPRIMARYSURFACE));
6051#endif
6052#ifdef VBOXWDDMDISP_DEBUG_PRINT_SHARED_CREATE
6053 vboxVDbgPrint(("\n\n********\n(0x%x:0n%d)Shared OPENNED pAlloc(0x%p), hRc(0x%p), hAl(0x%p), "
6054 "Handle(0x%x), (0n%d) \n***********\n\n",
6055 GetCurrentProcessId(), GetCurrentProcessId(),
6056 pAllocation, pRc->hKMResource, pAllocation->hAllocation,
6057 pAllocation->hSharedHandle, pAllocation->hSharedHandle
6058 ));
6059#endif
6060 }
6061 if (!pData->pPrivateDriverData || !pData->PrivateDriverDataSize)
6062 {
6063 /* this is a "standard" allocation resource */
6064
6065 /* both should be actually zero */
6066 Assert(!pData->pPrivateDriverData && !pData->PrivateDriverDataSize);
6067 pRc->RcDesc.enmPool = D3DDDIPOOL_LOCALVIDMEM;
6068 pRc->RcDesc.enmMultisampleType = D3DDDIMULTISAMPLE_NONE;
6069 pRc->RcDesc.MultisampleQuality = 0;
6070 pRc->RcDesc.MipLevels = 0;
6071 /*pRc->RcDesc.Fvf;*/
6072 pRc->RcDesc.fFlags.SharedResource = 1;
6073
6074 if (pData->NumAllocations != 1)
6075 {
6076 WARN(("NumAllocations is expected to be 1, but was %d", pData->NumAllocations));
6077 }
6078
6079 for (UINT i = 0; i < pData->NumAllocations; ++i)
6080 {
6081 PVBOXWDDMDISP_ALLOCATION pAlloc = &pRc->aAllocations[i];
6082 pAlloc->enmD3DIfType = VBOXDISP_D3DIFTYPE_SURFACE;
6083 pAlloc->pD3DIf = NULL;
6084 }
6085
6086 D3DDDI_OPENALLOCATIONINFO* pDdiAllocInfo = &pData->pOpenAllocationInfo[0];
6087 Assert(pDdiAllocInfo->pPrivateDriverData);
6088 Assert(pDdiAllocInfo->PrivateDriverDataSize >= sizeof (VBOXWDDM_ALLOCINFO));
6089 if (pDdiAllocInfo->pPrivateDriverData && pDdiAllocInfo->PrivateDriverDataSize >= sizeof (VBOXWDDM_ALLOCINFO))
6090 {
6091 PVBOXWDDM_ALLOCINFO pAllocInfo = (PVBOXWDDM_ALLOCINFO)pDdiAllocInfo->pPrivateDriverData;
6092 switch(pAllocInfo->enmType)
6093 {
6094 case VBOXWDDM_ALLOC_TYPE_STD_SHAREDPRIMARYSURFACE:
6095 pRc->RcDesc.fFlags.Primary = 1;
6096 case VBOXWDDM_ALLOC_TYPE_STD_SHADOWSURFACE:
6097 case VBOXWDDM_ALLOC_TYPE_STD_STAGINGSURFACE:
6098 pRc->RcDesc.enmFormat = pAllocInfo->SurfDesc.format;
6099 pRc->RcDesc.VidPnSourceId = pAllocInfo->SurfDesc.VidPnSourceId;
6100 pRc->RcDesc.RefreshRate = pAllocInfo->SurfDesc.RefreshRate;
6101 break;
6102 default:
6103 Assert(0);
6104 hr = E_INVALIDARG;
6105 }
6106 }
6107 else
6108 hr = E_INVALIDARG;
6109 }
6110 else
6111 {
6112 /* this is a "generic" resource whose creation is initiated by the UMD */
6113 Assert(pData->PrivateDriverDataSize == sizeof (VBOXWDDM_RCINFO));
6114 if (pData->PrivateDriverDataSize == sizeof (VBOXWDDM_RCINFO))
6115 {
6116 VBOXWDDM_RCINFO *pRcInfo = (VBOXWDDM_RCINFO*)pData->pPrivateDriverData;
6117 Assert(pRcInfo->fFlags.Generic);
6118 Assert(!pRcInfo->fFlags.Opened);
6119 Assert(pRcInfo->cAllocInfos == pData->NumAllocations);
6120 pRc->fFlags.Value |= pRcInfo->fFlags.Value;
6121 pRc->fFlags.Generic = 1;
6122 pRc->RcDesc = pRcInfo->RcDesc;
6123 pRc->cAllocations = pData->NumAllocations;
6124 Assert(pRc->RcDesc.fFlags.SharedResource);
6125
6126 hr = VBoxD3DIfCreateForRc(pRc);
6127 if (!SUCCEEDED(hr))
6128 {
6129 WARN(("VBoxD3DIfCreateForRc failed, hr %d", hr));
6130 }
6131 }
6132 else
6133 hr = E_INVALIDARG;
6134 }
6135
6136 if (hr == S_OK)
6137 pData->hResource = pRc;
6138 else
6139 vboxResourceFree(pRc);
6140 }
6141 else
6142 {
6143 vboxVDbgPrintR((__FUNCTION__": vboxResourceAlloc failed for hDevice(0x%p), NumAllocations(%d)\n", hDevice, pData->NumAllocations));
6144 hr = E_OUTOFMEMORY;
6145 }
6146
6147 vboxVDbgPrintF(("<== "__FUNCTION__", hDevice(0x%p)\n", hDevice));
6148 return hr;
6149}
6150static HRESULT APIENTRY vboxWddmDDevGetCaptureAllocationHandle(HANDLE hDevice, D3DDDIARG_GETCAPTUREALLOCATIONHANDLE* pData)
6151{
6152 VBOXDISP_DDI_PROLOGUE_DEV(hDevice);
6153 vboxVDbgPrintF(("<== "__FUNCTION__", hDevice(0x%p)\n", hDevice));
6154 PVBOXWDDMDISP_DEVICE pDevice = (PVBOXWDDMDISP_DEVICE)hDevice;
6155 Assert(pDevice);
6156 VBOXDISPCRHGSMI_SCOPE_SET_DEV(pDevice);
6157
6158 Assert(0);
6159 vboxVDbgPrintF(("==> "__FUNCTION__", hDevice(0x%p)\n", hDevice));
6160 return E_FAIL;
6161}
6162
6163static HRESULT APIENTRY vboxWddmDDevCaptureToSysMem(HANDLE hDevice, CONST D3DDDIARG_CAPTURETOSYSMEM* pData)
6164{
6165 VBOXDISP_DDI_PROLOGUE_DEV(hDevice);
6166 vboxVDbgPrintF(("<== "__FUNCTION__", hDevice(0x%p)\n", hDevice));
6167 PVBOXWDDMDISP_DEVICE pDevice = (PVBOXWDDMDISP_DEVICE)hDevice;
6168 Assert(pDevice);
6169 VBOXDISPCRHGSMI_SCOPE_SET_DEV(pDevice);
6170
6171 Assert(0);
6172 vboxVDbgPrintF(("==> "__FUNCTION__", hDevice(0x%p)\n", hDevice));
6173 return E_FAIL;
6174}
6175
6176static HRESULT APIENTRY vboxWddmDispCreateDevice (IN HANDLE hAdapter, IN D3DDDIARG_CREATEDEVICE* pCreateData)
6177{
6178 VBOXDISP_DDI_PROLOGUE_ADP(hAdapter);
6179 HRESULT hr = S_OK;
6180 vboxVDbgPrint(("==> "__FUNCTION__", hAdapter(0x%p), Interface(%d), Version(%d)\n", hAdapter, pCreateData->Interface, pCreateData->Version));
6181
6182// Assert(0);
6183 PVBOXWDDMDISP_ADAPTER pAdapter = (PVBOXWDDMDISP_ADAPTER)hAdapter;
6184
6185 PVBOXWDDMDISP_DEVICE pDevice = (PVBOXWDDMDISP_DEVICE)RTMemAllocZ(RT_OFFSETOF(VBOXWDDMDISP_DEVICE, apRTs[pAdapter->D3D.cMaxSimRTs]));
6186 if (pDevice)
6187 {
6188 pDevice->cRTs = pAdapter->D3D.cMaxSimRTs;
6189 pDevice->hDevice = pCreateData->hDevice;
6190 pDevice->pAdapter = pAdapter;
6191 pDevice->u32IfVersion = pCreateData->Interface;
6192 pDevice->uRtVersion = pCreateData->Version;
6193 pDevice->RtCallbacks = *pCreateData->pCallbacks;
6194 pDevice->pvCmdBuffer = pCreateData->pCommandBuffer;
6195 pDevice->cbCmdBuffer = pCreateData->CommandBufferSize;
6196 pDevice->fFlags = pCreateData->Flags;
6197 /* Set Viewport to some default values */
6198 pDevice->ViewPort.X = 0;
6199 pDevice->ViewPort.Y = 0;
6200 pDevice->ViewPort.Width = 1;
6201 pDevice->ViewPort.Height = 1;
6202 pDevice->ViewPort.MinZ = 0.;
6203 pDevice->ViewPort.MaxZ = 1.;
6204
6205 RTListInit(&pDevice->DirtyAllocList);
6206
6207 Assert(!pCreateData->AllocationListSize);
6208 Assert(!pCreateData->PatchLocationListSize);
6209
6210 pCreateData->hDevice = pDevice;
6211
6212 pCreateData->pDeviceFuncs->pfnSetRenderState = vboxWddmDDevSetRenderState;
6213 pCreateData->pDeviceFuncs->pfnUpdateWInfo = vboxWddmDDevUpdateWInfo;
6214 pCreateData->pDeviceFuncs->pfnValidateDevice = vboxWddmDDevValidateDevice;
6215 pCreateData->pDeviceFuncs->pfnSetTextureStageState = vboxWddmDDevSetTextureStageState;
6216 pCreateData->pDeviceFuncs->pfnSetTexture = vboxWddmDDevSetTexture;
6217 pCreateData->pDeviceFuncs->pfnSetPixelShader = vboxWddmDDevSetPixelShader;
6218 pCreateData->pDeviceFuncs->pfnSetPixelShaderConst = vboxWddmDDevSetPixelShaderConst;
6219 pCreateData->pDeviceFuncs->pfnSetStreamSourceUm = vboxWddmDDevSetStreamSourceUm;
6220 pCreateData->pDeviceFuncs->pfnSetIndices = vboxWddmDDevSetIndices;
6221 pCreateData->pDeviceFuncs->pfnSetIndicesUm = vboxWddmDDevSetIndicesUm;
6222 pCreateData->pDeviceFuncs->pfnDrawPrimitive = vboxWddmDDevDrawPrimitive;
6223 pCreateData->pDeviceFuncs->pfnDrawIndexedPrimitive = vboxWddmDDevDrawIndexedPrimitive;
6224 pCreateData->pDeviceFuncs->pfnDrawRectPatch = vboxWddmDDevDrawRectPatch;
6225 pCreateData->pDeviceFuncs->pfnDrawTriPatch = vboxWddmDDevDrawTriPatch;
6226 pCreateData->pDeviceFuncs->pfnDrawPrimitive2 = vboxWddmDDevDrawPrimitive2;
6227 pCreateData->pDeviceFuncs->pfnDrawIndexedPrimitive2 = vboxWddmDDevDrawIndexedPrimitive2;
6228 pCreateData->pDeviceFuncs->pfnVolBlt = vboxWddmDDevVolBlt;
6229 pCreateData->pDeviceFuncs->pfnBufBlt = vboxWddmDDevBufBlt;
6230 pCreateData->pDeviceFuncs->pfnTexBlt = vboxWddmDDevTexBlt;
6231 pCreateData->pDeviceFuncs->pfnStateSet = vboxWddmDDevStateSet;
6232 pCreateData->pDeviceFuncs->pfnSetPriority = vboxWddmDDevSetPriority;
6233 pCreateData->pDeviceFuncs->pfnClear = vboxWddmDDevClear;
6234 pCreateData->pDeviceFuncs->pfnUpdatePalette = vboxWddmDDevUpdatePalette;
6235 pCreateData->pDeviceFuncs->pfnSetPalette = vboxWddmDDevSetPalette;
6236 pCreateData->pDeviceFuncs->pfnSetVertexShaderConst = vboxWddmDDevSetVertexShaderConst;
6237 pCreateData->pDeviceFuncs->pfnMultiplyTransform = vboxWddmDDevMultiplyTransform;
6238 pCreateData->pDeviceFuncs->pfnSetTransform = vboxWddmDDevSetTransform;
6239 pCreateData->pDeviceFuncs->pfnSetViewport = vboxWddmDDevSetViewport;
6240 pCreateData->pDeviceFuncs->pfnSetZRange = vboxWddmDDevSetZRange;
6241 pCreateData->pDeviceFuncs->pfnSetMaterial = vboxWddmDDevSetMaterial;
6242 pCreateData->pDeviceFuncs->pfnSetLight = vboxWddmDDevSetLight;
6243 pCreateData->pDeviceFuncs->pfnCreateLight = vboxWddmDDevCreateLight;
6244 pCreateData->pDeviceFuncs->pfnDestroyLight = vboxWddmDDevDestroyLight;
6245 pCreateData->pDeviceFuncs->pfnSetClipPlane = vboxWddmDDevSetClipPlane;
6246 pCreateData->pDeviceFuncs->pfnGetInfo = vboxWddmDDevGetInfo;
6247 pCreateData->pDeviceFuncs->pfnLock = vboxWddmDDevLock;
6248 pCreateData->pDeviceFuncs->pfnUnlock = vboxWddmDDevUnlock;
6249 pCreateData->pDeviceFuncs->pfnCreateResource = vboxWddmDDevCreateResource;
6250 pCreateData->pDeviceFuncs->pfnDestroyResource = vboxWddmDDevDestroyResource;
6251 pCreateData->pDeviceFuncs->pfnSetDisplayMode = vboxWddmDDevSetDisplayMode;
6252 pCreateData->pDeviceFuncs->pfnPresent = vboxWddmDDevPresent;
6253 pCreateData->pDeviceFuncs->pfnFlush = vboxWddmDDevFlush;
6254 pCreateData->pDeviceFuncs->pfnCreateVertexShaderFunc = vboxWddmDDevCreateVertexShaderFunc;
6255 pCreateData->pDeviceFuncs->pfnDeleteVertexShaderFunc = vboxWddmDDevDeleteVertexShaderFunc;
6256 pCreateData->pDeviceFuncs->pfnSetVertexShaderFunc = vboxWddmDDevSetVertexShaderFunc;
6257 pCreateData->pDeviceFuncs->pfnCreateVertexShaderDecl = vboxWddmDDevCreateVertexShaderDecl;
6258 pCreateData->pDeviceFuncs->pfnDeleteVertexShaderDecl = vboxWddmDDevDeleteVertexShaderDecl;
6259 pCreateData->pDeviceFuncs->pfnSetVertexShaderDecl = vboxWddmDDevSetVertexShaderDecl;
6260 pCreateData->pDeviceFuncs->pfnSetVertexShaderConstI = vboxWddmDDevSetVertexShaderConstI;
6261 pCreateData->pDeviceFuncs->pfnSetVertexShaderConstB = vboxWddmDDevSetVertexShaderConstB;
6262 pCreateData->pDeviceFuncs->pfnSetScissorRect = vboxWddmDDevSetScissorRect;
6263 pCreateData->pDeviceFuncs->pfnSetStreamSource = vboxWddmDDevSetStreamSource;
6264 pCreateData->pDeviceFuncs->pfnSetStreamSourceFreq = vboxWddmDDevSetStreamSourceFreq;
6265 pCreateData->pDeviceFuncs->pfnSetConvolutionKernelMono = vboxWddmDDevSetConvolutionKernelMono;
6266 pCreateData->pDeviceFuncs->pfnComposeRects = vboxWddmDDevComposeRects;
6267 pCreateData->pDeviceFuncs->pfnBlt = vboxWddmDDevBlt;
6268 pCreateData->pDeviceFuncs->pfnColorFill = vboxWddmDDevColorFill;
6269 pCreateData->pDeviceFuncs->pfnDepthFill = vboxWddmDDevDepthFill;
6270 pCreateData->pDeviceFuncs->pfnCreateQuery = vboxWddmDDevCreateQuery;
6271 pCreateData->pDeviceFuncs->pfnDestroyQuery = vboxWddmDDevDestroyQuery;
6272 pCreateData->pDeviceFuncs->pfnIssueQuery = vboxWddmDDevIssueQuery;
6273 pCreateData->pDeviceFuncs->pfnGetQueryData = vboxWddmDDevGetQueryData;
6274 pCreateData->pDeviceFuncs->pfnSetRenderTarget = vboxWddmDDevSetRenderTarget;
6275 pCreateData->pDeviceFuncs->pfnSetDepthStencil = vboxWddmDDevSetDepthStencil;
6276 pCreateData->pDeviceFuncs->pfnGenerateMipSubLevels = vboxWddmDDevGenerateMipSubLevels;
6277 pCreateData->pDeviceFuncs->pfnSetPixelShaderConstI = vboxWddmDDevSetPixelShaderConstI;
6278 pCreateData->pDeviceFuncs->pfnSetPixelShaderConstB = vboxWddmDDevSetPixelShaderConstB;
6279 pCreateData->pDeviceFuncs->pfnCreatePixelShader = vboxWddmDDevCreatePixelShader;
6280 pCreateData->pDeviceFuncs->pfnDeletePixelShader = vboxWddmDDevDeletePixelShader;
6281 pCreateData->pDeviceFuncs->pfnCreateDecodeDevice = vboxWddmDDevCreateDecodeDevice;
6282 pCreateData->pDeviceFuncs->pfnDestroyDecodeDevice = vboxWddmDDevDestroyDecodeDevice;
6283 pCreateData->pDeviceFuncs->pfnSetDecodeRenderTarget = vboxWddmDDevSetDecodeRenderTarget;
6284 pCreateData->pDeviceFuncs->pfnDecodeBeginFrame = vboxWddmDDevDecodeBeginFrame;
6285 pCreateData->pDeviceFuncs->pfnDecodeEndFrame = vboxWddmDDevDecodeEndFrame;
6286 pCreateData->pDeviceFuncs->pfnDecodeExecute = vboxWddmDDevDecodeExecute;
6287 pCreateData->pDeviceFuncs->pfnDecodeExtensionExecute = vboxWddmDDevDecodeExtensionExecute;
6288 pCreateData->pDeviceFuncs->pfnCreateVideoProcessDevice = vboxWddmDDevCreateVideoProcessDevice;
6289 pCreateData->pDeviceFuncs->pfnDestroyVideoProcessDevice = vboxWddmDDevDestroyVideoProcessDevice;
6290 pCreateData->pDeviceFuncs->pfnVideoProcessBeginFrame = vboxWddmDDevVideoProcessBeginFrame;
6291 pCreateData->pDeviceFuncs->pfnVideoProcessEndFrame = vboxWddmDDevVideoProcessEndFrame;
6292 pCreateData->pDeviceFuncs->pfnSetVideoProcessRenderTarget = vboxWddmDDevSetVideoProcessRenderTarget;
6293 pCreateData->pDeviceFuncs->pfnVideoProcessBlt = vboxWddmDDevVideoProcessBlt;
6294 pCreateData->pDeviceFuncs->pfnCreateExtensionDevice = vboxWddmDDevCreateExtensionDevice;
6295 pCreateData->pDeviceFuncs->pfnDestroyExtensionDevice = vboxWddmDDevDestroyExtensionDevice;
6296 pCreateData->pDeviceFuncs->pfnExtensionExecute = vboxWddmDDevExtensionExecute;
6297 pCreateData->pDeviceFuncs->pfnCreateOverlay = vboxWddmDDevCreateOverlay;
6298 pCreateData->pDeviceFuncs->pfnUpdateOverlay = vboxWddmDDevUpdateOverlay;
6299 pCreateData->pDeviceFuncs->pfnFlipOverlay = vboxWddmDDevFlipOverlay;
6300 pCreateData->pDeviceFuncs->pfnGetOverlayColorControls = vboxWddmDDevGetOverlayColorControls;
6301 pCreateData->pDeviceFuncs->pfnSetOverlayColorControls = vboxWddmDDevSetOverlayColorControls;
6302 pCreateData->pDeviceFuncs->pfnDestroyOverlay = vboxWddmDDevDestroyOverlay;
6303 pCreateData->pDeviceFuncs->pfnDestroyDevice = vboxWddmDDevDestroyDevice;
6304 pCreateData->pDeviceFuncs->pfnQueryResourceResidency = vboxWddmDDevQueryResourceResidency;
6305 pCreateData->pDeviceFuncs->pfnOpenResource = vboxWddmDDevOpenResource;
6306 pCreateData->pDeviceFuncs->pfnGetCaptureAllocationHandle = vboxWddmDDevGetCaptureAllocationHandle;
6307 pCreateData->pDeviceFuncs->pfnCaptureToSysMem = vboxWddmDDevCaptureToSysMem;
6308 pCreateData->pDeviceFuncs->pfnLockAsync = NULL; //vboxWddmDDevLockAsync;
6309 pCreateData->pDeviceFuncs->pfnUnlockAsync = NULL; //vboxWddmDDevUnlockAsync;
6310 pCreateData->pDeviceFuncs->pfnRename = NULL; //vboxWddmDDevRename;
6311
6312 VBOXDISPPROFILE_DDI_INIT_DEV(pDevice);
6313#ifdef VBOX_WDDMDISP_WITH_PROFILE
6314 pDevice->ProfileDdiPresentCb = VBoxDispProfileSet("pfnPresentCb");
6315#endif
6316
6317#ifdef VBOXWDDMDISP_DEBUG_TIMER
6318 pDevice->hTimerQueue = CreateTimerQueue();
6319 Assert(pDevice->hTimerQueue);
6320#endif
6321
6322 do
6323 {
6324 RTListInit(&pDevice->SwapchainList);
6325 Assert(!pCreateData->AllocationListSize
6326 && !pCreateData->PatchLocationListSize);
6327 if (!pCreateData->AllocationListSize
6328 && !pCreateData->PatchLocationListSize)
6329 {
6330 {
6331 VBOXDISPCRHGSMI_SCOPE_SET_DEV(pDevice);
6332
6333 hr = vboxDispCmCtxCreate(pDevice, &pDevice->DefaultContext);
6334 Assert(hr == S_OK);
6335 if (hr == S_OK)
6336 {
6337#ifdef VBOXDISP_EARLYCREATEDEVICE
6338 PVBOXWDDMDISP_RESOURCE pRc = vboxResourceAlloc(2);
6339 Assert(pRc);
6340 if (pRc)
6341 {
6342 D3DPRESENT_PARAMETERS params;
6343 memset(&params, 0, sizeof (params));
6344 // params.BackBufferWidth = 640;
6345 // params.BackBufferHeight = 480;
6346 params.BackBufferWidth = 0x400;
6347 params.BackBufferHeight = 0x300;
6348 params.BackBufferFormat = D3DFMT_A8R8G8B8;
6349 // params.BackBufferCount = 0;
6350 params.BackBufferCount = 1;
6351 params.MultiSampleType = D3DMULTISAMPLE_NONE;
6352 params.SwapEffect = D3DSWAPEFFECT_DISCARD;
6353 // params.hDeviceWindow = hWnd;
6354 /* @todo: it seems there should be a way to detect this correctly since
6355 * our vboxWddmDDevSetDisplayMode will be called in case we are using full-screen */
6356 params.Windowed = TRUE;
6357 // params.EnableAutoDepthStencil = FALSE;
6358 // params.AutoDepthStencilFormat = D3DFMT_UNKNOWN;
6359 // params.Flags;
6360 // params.FullScreen_RefreshRateInHz;
6361 // params.FullScreen_PresentationInterval;
6362
6363 hr = vboxWddmD3DDeviceCreate(pDevice, 0, pRc, &params, TRUE /*BOOL bLockable*/);
6364 Assert(hr == S_OK);
6365 if (hr == S_OK)
6366 break;
6367 vboxResourceFree(pRc);
6368 }
6369 else
6370 {
6371 hr = E_OUTOFMEMORY;
6372 }
6373#else
6374//# define VBOXDISP_TEST_SWAPCHAIN
6375# ifdef VBOXDISP_TEST_SWAPCHAIN
6376 VBOXDISP_D3DEV(pDevice);
6377# endif
6378 break;
6379#endif
6380
6381 HRESULT tmpHr = vboxDispCmCtxDestroy(pDevice, &pDevice->DefaultContext);
6382 Assert(tmpHr == S_OK);
6383 }
6384 }
6385 }
6386 else
6387 {
6388 vboxVDbgPrintR((__FUNCTION__": Not implemented: PatchLocationListSize(%d), AllocationListSize(%d)\n",
6389 pCreateData->PatchLocationListSize, pCreateData->AllocationListSize));
6390 //pCreateData->pAllocationList = ??
6391 hr = E_FAIL;
6392 }
6393
6394 RTMemFree(pDevice);
6395 } while (0);
6396 }
6397 else
6398 {
6399 vboxVDbgPrintR((__FUNCTION__": RTMemAllocZ returned NULL\n"));
6400 hr = E_OUTOFMEMORY;
6401 }
6402
6403 if (SUCCEEDED(hr))
6404 {
6405 /* Get system D3D DLL handle and prevent its unloading until entire process termination (GET_MODULE_HANDLE_EX_FLAG_PIN).
6406 * This is important because even after guest App issued CloseAdatper() call, we still use pointers provided by DLL. */
6407 if (GetModuleHandleEx(GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS | GET_MODULE_HANDLE_EX_FLAG_PIN,
6408 (LPCWSTR)pDevice->RtCallbacks.pfnAllocateCb,
6409 &pDevice->hHgsmiTransportModule))
6410 {
6411 Assert(pDevice->hHgsmiTransportModule);
6412 vboxVDbgPrintR((__FUNCTION__": system D3D DLL referenced with GET_MODULE_HANDLE_EX_FLAG_PIN flag\n"));
6413 }
6414 else
6415 {
6416 DWORD winEr = GetLastError();
6417 WARN(("GetModuleHandleEx failed winEr %d, ignoring", winEr));
6418 pDevice->hHgsmiTransportModule = 0;
6419 }
6420 }
6421
6422 vboxVDbgPrint(("<== "__FUNCTION__", hAdapter(0x%p)\n", hAdapter));
6423
6424 return hr;
6425}
6426
6427static HRESULT APIENTRY vboxWddmDispCloseAdapter (IN HANDLE hAdapter)
6428{
6429 VBOXDISP_DDI_PROLOGUE_ADP(hAdapter);
6430 vboxVDbgPrint(("==> "__FUNCTION__", hAdapter(0x%p)\n", hAdapter));
6431
6432 PVBOXWDDMDISP_ADAPTER pAdapter = (PVBOXWDDMDISP_ADAPTER)hAdapter;
6433 if (VBOXDISPMODE_IS_3D(pAdapter))
6434 {
6435 VBOXDISPCRHGSMI_SCOPE_SET_GLOBAL();
6436 VBoxDispD3DGlobalClose(&pAdapter->D3D, &pAdapter->Formats);
6437 }
6438#ifdef VBOX_WITH_VIDEOHWACCEL
6439 else
6440 {
6441 VBoxDispD3DGlobal2DFormatsTerm(pAdapter);
6442 }
6443#endif
6444
6445 VBOXDISPPROFILE_DDI_TERM(pAdapter);
6446
6447 RTMemFree(pAdapter);
6448
6449 vboxVDbgPrint(("<== "__FUNCTION__", hAdapter(0x%p)\n", hAdapter));
6450
6451#ifdef DEBUG
6452 VbglR3Term();
6453#endif
6454 return S_OK;
6455}
6456
6457#define VBOXDISP_IS_MODULE_FUNC(_pvModule, _cbModule, _pfn) ( \
6458 (((uintptr_t)(_pfn)) >= ((uintptr_t)(_pvModule))) \
6459 && (((uintptr_t)(_pfn)) < (((uintptr_t)(_pvModule)) + ((DWORD)(_cbModule)))) \
6460 )
6461
6462static BOOL vboxDispIsDDraw(__inout D3DDDIARG_OPENADAPTER* pOpenData)
6463{
6464 /*if we are loaded by ddraw module, the Interface version should be 7
6465 * and pAdapterCallbacks should be ddraw-supplied, i.e. reside in ddraw module */
6466 if (pOpenData->Interface != 7)
6467 return FALSE;
6468
6469 HMODULE hDDraw = GetModuleHandleA("ddraw.dll");
6470 if (!hDDraw)
6471 return FALSE;
6472
6473 HANDLE hProcess = GetCurrentProcess();
6474 MODULEINFO ModuleInfo = {0};
6475
6476 if (!GetModuleInformation(hProcess, hDDraw, &ModuleInfo, sizeof (ModuleInfo)))
6477 {
6478 DWORD winEr = GetLastError();
6479 WARN(("GetModuleInformation failed, %d", winEr));
6480 return FALSE;
6481 }
6482
6483 if (VBOXDISP_IS_MODULE_FUNC(ModuleInfo.lpBaseOfDll, ModuleInfo.SizeOfImage, pOpenData->pAdapterCallbacks->pfnQueryAdapterInfoCb))
6484 return TRUE;
6485 if (VBOXDISP_IS_MODULE_FUNC(ModuleInfo.lpBaseOfDll, ModuleInfo.SizeOfImage, pOpenData->pAdapterCallbacks->pfnGetMultisampleMethodListCb))
6486 return TRUE;
6487
6488 return FALSE;
6489}
6490
6491HRESULT APIENTRY OpenAdapter(__inout D3DDDIARG_OPENADAPTER* pOpenData)
6492{
6493#ifdef DEBUG
6494 VbglR3Init();
6495#endif
6496
6497 VBOXDISP_DDI_PROLOGUE_GLBL();
6498
6499 vboxVDbgPrint(("==> "__FUNCTION__"\n"));
6500
6501#if 0 //def DEBUG_misha
6502 DWORD dwVersion = 0;
6503 DWORD dwMajorVersion = 0;
6504 DWORD dwMinorVersion = 0;
6505 dwVersion = GetVersion();
6506 dwMajorVersion = (DWORD)(LOBYTE(LOWORD(dwVersion)));
6507 dwMinorVersion = (DWORD)(HIBYTE(LOWORD(dwVersion)));
6508
6509 if (dwMajorVersion == 6 && dwMinorVersion <= 1 && VBOXVDBG_IS_DWM())
6510 {
6511 exit(0);
6512 return E_FAIL;
6513 }
6514#endif
6515
6516// vboxDispLock();
6517
6518 HRESULT hr = E_FAIL;
6519
6520 do
6521 {
6522
6523 LOGREL(("Built %s %s", __DATE__, __TIME__));
6524
6525 VBOXWDDM_QI Query;
6526 D3DDDICB_QUERYADAPTERINFO DdiQuery;
6527 DdiQuery.PrivateDriverDataSize = sizeof(Query);
6528 DdiQuery.pPrivateDriverData = &Query;
6529 hr = pOpenData->pAdapterCallbacks->pfnQueryAdapterInfoCb(pOpenData->hAdapter, &DdiQuery);
6530 Assert(hr == S_OK);
6531 if (hr != S_OK)
6532 {
6533 vboxVDbgPrintR((__FUNCTION__": pfnQueryAdapterInfoCb failed, hr (%d)\n", hr));
6534 hr = E_FAIL;
6535 break;
6536 }
6537
6538 /* check the miniport version match display version */
6539 if (Query.u32Version != VBOXVIDEOIF_VERSION)
6540 {
6541 vboxVDbgPrintR((__FUNCTION__": miniport version mismatch, expected (%d), but was (%d)\n",
6542 VBOXVIDEOIF_VERSION,
6543 Query.u32Version));
6544 hr = E_FAIL;
6545 break;
6546 }
6547
6548#ifdef VBOX_WITH_VIDEOHWACCEL
6549 Assert(Query.cInfos >= 1);
6550 PVBOXWDDMDISP_ADAPTER pAdapter = (PVBOXWDDMDISP_ADAPTER)RTMemAllocZ(RT_OFFSETOF(VBOXWDDMDISP_ADAPTER, aHeads[Query.cInfos]));
6551#else
6552 PVBOXWDDMDISP_ADAPTER pAdapter = (PVBOXWDDMDISP_ADAPTER)RTMemAllocZ(sizeof (VBOXWDDMDISP_ADAPTER));
6553#endif
6554 Assert(pAdapter);
6555 if (pAdapter)
6556 {
6557 pAdapter->hAdapter = pOpenData->hAdapter;
6558 pAdapter->uIfVersion = pOpenData->Interface;
6559 pAdapter->uRtVersion= pOpenData->Version;
6560 pAdapter->RtCallbacks = *pOpenData->pAdapterCallbacks;
6561
6562 pAdapter->u32VBox3DCaps = Query.u32VBox3DCaps;
6563
6564 pAdapter->cHeads = Query.cInfos;
6565
6566 pOpenData->hAdapter = pAdapter;
6567 pOpenData->pAdapterFuncs->pfnGetCaps = vboxWddmDispGetCaps;
6568 pOpenData->pAdapterFuncs->pfnCreateDevice = vboxWddmDispCreateDevice;
6569 pOpenData->pAdapterFuncs->pfnCloseAdapter = vboxWddmDispCloseAdapter;
6570 pOpenData->DriverVersion = D3D_UMD_INTERFACE_VERSION;
6571 if (!vboxDispIsDDraw(pOpenData))
6572 {
6573 do
6574 {
6575 {
6576 VBOXDISPCRHGSMI_SCOPE_SET_GLOBAL();
6577 /* try enable the 3D */
6578 hr = VBoxDispD3DGlobalOpen(&pAdapter->D3D, &pAdapter->Formats);
6579 if (hr == S_OK)
6580 {
6581 LOG(("SUCCESS 3D Enabled, pAdapter (0x%p)", pAdapter));
6582 break;
6583 }
6584 else
6585 WARN(("VBoxDispD3DOpen failed, hr (%d)", hr));
6586
6587 }
6588 } while (0);
6589 }
6590#ifdef VBOX_WITH_VIDEOHWACCEL
6591 if (!VBOXDISPMODE_IS_3D(pAdapter))
6592 {
6593 for (uint32_t i = 0; i < pAdapter->cHeads; ++i)
6594 {
6595 pAdapter->aHeads[i].Vhwa.Settings = Query.aInfos[i];
6596 }
6597 hr = VBoxDispD3DGlobal2DFormatsInit(pAdapter);
6598 if (!SUCCEEDED(hr))
6599 {
6600 WARN(("VBoxDispD3DGlobal2DFormatsInit failed hr 0x%x", hr));
6601 }
6602 }
6603#endif
6604
6605 if (SUCCEEDED(hr))
6606 {
6607 VBOXDISPPROFILE_DDI_INIT_ADP(pAdapter);
6608 hr = S_OK;
6609 break;
6610 }
6611 else
6612 {
6613 WARN(("OpenAdapter failed hr 0x%x", hr));
6614 }
6615
6616 RTMemFree(pAdapter);
6617 }
6618 else
6619 {
6620 vboxVDbgPrintR((__FUNCTION__": RTMemAllocZ returned NULL\n"));
6621 hr = E_OUTOFMEMORY;
6622 }
6623
6624 } while (0);
6625
6626// vboxDispUnlock();
6627
6628 vboxVDbgPrint(("<== "__FUNCTION__", hr (%d)\n", hr));
6629
6630 return hr;
6631}
Note: See TracBrowser for help on using the repository browser.

© 2025 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette