VirtualBox

source: vbox/trunk/src/VBox/Additions/WINNT/Graphics/Miniport/wddm/VBoxVideoWddm.cpp@ 33711

Last change on this file since 33711 was 33711, checked in by vboxsync, 14 years ago

Additions/WINNT/Graphics: more refactoring

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 220.1 KB
Line 
1/*
2 * Copyright (C) 2010 Oracle Corporation
3 *
4 * This file is part of VirtualBox Open Source Edition (OSE), as
5 * available from http://www.virtualbox.org. This file is free software;
6 * you can redistribute it and/or modify it under the terms of the GNU
7 * General Public License (GPL) as published by the Free Software
8 * Foundation, in version 2 as it comes in the "COPYING" file of the
9 * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
10 * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
11 */
12
13#include "../VBoxVideo.h"
14#include "../Helper.h"
15
16#include <iprt/asm.h>
17
18#include <VBox/VBoxGuestLib.h>
19#include <VBox/VBoxVideo.h>
20#include <wingdi.h> /* needed for RGNDATA definition */
21#include <VBoxDisplay.h> /* this is from Additions/WINNT/include/ to include escape codes */
22
23#define VBOXWDDM_MEMTAG 'MDBV'
24PVOID vboxWddmMemAlloc(IN SIZE_T cbSize)
25{
26 return ExAllocatePoolWithTag(NonPagedPool, cbSize, VBOXWDDM_MEMTAG);
27}
28
29PVOID vboxWddmMemAllocZero(IN SIZE_T cbSize)
30{
31 PVOID pvMem = vboxWddmMemAlloc(cbSize);
32 memset(pvMem, 0, cbSize);
33 return pvMem;
34}
35
36
37VOID vboxWddmMemFree(PVOID pvMem)
38{
39 ExFreePool(pvMem);
40}
41
42DECLINLINE(PVBOXWDDM_ALLOCATION) vboxWddmGetAllocationFromOpenData(PDEVICE_EXTENSION pDevExt, PVBOXWDDM_OPENALLOCATION pOa)
43{
44 DXGKARGCB_GETHANDLEDATA GhData;
45 GhData.hObject = pOa->hAllocation;
46 GhData.Type = DXGK_HANDLE_ALLOCATION;
47 GhData.Flags.Value = 0;
48 return (PVBOXWDDM_ALLOCATION)pDevExt->u.primary.DxgkInterface.DxgkCbGetHandleData(&GhData);
49}
50
51DECLINLINE(PVBOXWDDM_ALLOCATION) vboxWddmGetAllocationFromAllocList(PDEVICE_EXTENSION pDevExt, DXGK_ALLOCATIONLIST *pAllocList)
52{
53 return vboxWddmGetAllocationFromOpenData(pDevExt, (PVBOXWDDM_OPENALLOCATION)pAllocList->hDeviceSpecificAllocation);
54}
55
56static void vboxWddmPopulateDmaAllocInfo(PVBOXWDDM_DMA_ALLOCINFO pInfo, PVBOXWDDM_ALLOCATION pAlloc, DXGK_ALLOCATIONLIST *pDmaAlloc)
57{
58 pInfo->pAlloc = pAlloc;
59 if (pDmaAlloc->SegmentId)
60 {
61 pInfo->offAlloc = (VBOXVIDEOOFFSET)pDmaAlloc->PhysicalAddress.QuadPart;
62 pInfo->segmentIdAlloc = pDmaAlloc->SegmentId;
63 }
64 else
65 pInfo->segmentIdAlloc = 0;
66 pInfo->srcId = pAlloc->SurfDesc.VidPnSourceId;
67}
68
69static void vboxWddmPopulateDmaAllocInfoWithOffset(PVBOXWDDM_DMA_ALLOCINFO pInfo, PVBOXWDDM_ALLOCATION pAlloc, DXGK_ALLOCATIONLIST *pDmaAlloc, uint32_t offStart)
70{
71 pInfo->pAlloc = pAlloc;
72 if (pDmaAlloc->SegmentId)
73 {
74 pInfo->offAlloc = (VBOXVIDEOOFFSET)pDmaAlloc->PhysicalAddress.QuadPart + offStart;
75 pInfo->segmentIdAlloc = pDmaAlloc->SegmentId;
76 }
77 else
78 pInfo->segmentIdAlloc = 0;
79 pInfo->srcId = pAlloc->SurfDesc.VidPnSourceId;
80}
81
82//VBOXVIDEOOFFSET vboxWddmVRAMAddressToOffset(PDEVICE_EXTENSION pDevExt, PHYSICAL_ADDRESS phAddress)
83//{
84// Assert(phAddress.QuadPart >= VBE_DISPI_LFB_PHYSICAL_ADDRESS);
85// if (phAddress.QuadPart < VBE_DISPI_LFB_PHYSICAL_ADDRESS)
86// return VBOXVIDEOOFFSET_VOID;
87//
88// VBOXVIDEOOFFSET off = phAddress.QuadPart - VBE_DISPI_LFB_PHYSICAL_ADDRESS;
89// Assert(off < pDevExt->u.primary.cbVRAM);
90// if (off >= pDevExt->u.primary.cbVRAM)
91// return VBOXVIDEOOFFSET_VOID;
92//
93// return off;
94//}
95
96VBOXVIDEOOFFSET vboxWddmValidatePrimary(PVBOXWDDM_ALLOCATION pAllocation)
97{
98 Assert(pAllocation);
99 if (!pAllocation)
100 {
101 drprintf((__FUNCTION__": no allocation specified for Source\n"));
102 return VBOXVIDEOOFFSET_VOID;
103 }
104
105 Assert(pAllocation->SegmentId);
106 if (!pAllocation->SegmentId)
107 {
108 drprintf((__FUNCTION__": allocation is not paged in\n"));
109 return VBOXVIDEOOFFSET_VOID;
110 }
111
112 VBOXVIDEOOFFSET offVram = pAllocation->offVram;
113 Assert(offVram != VBOXVIDEOOFFSET_VOID);
114 if (offVram == VBOXVIDEOOFFSET_VOID)
115 drprintf((__FUNCTION__": VRAM pffset is not defined\n"));
116
117 return offVram;
118}
119
120NTSTATUS vboxWddmGhDisplayPostInfoScreenBySDesc (PDEVICE_EXTENSION pDevExt, PVBOXWDDM_SURFACE_DESC pDesc, POINT * pVScreenPos, uint16_t fFlags)
121{
122 void *p = vboxHGSMIBufferAlloc (commonFromDeviceExt(pDevExt),
123 sizeof (VBVAINFOSCREEN),
124 HGSMI_CH_VBVA,
125 VBVA_INFO_SCREEN);
126 Assert(p);
127 if (p)
128 {
129 VBVAINFOSCREEN *pScreen = (VBVAINFOSCREEN *)p;
130
131 pScreen->u32ViewIndex = pDesc->VidPnSourceId;
132 pScreen->i32OriginX = pVScreenPos->x;
133 pScreen->i32OriginY = pVScreenPos->y;
134 pScreen->u32StartOffset = 0; //(uint32_t)offVram; /* we pretend the view is located at the start of each framebuffer */
135 pScreen->u32LineSize = pDesc->pitch;
136 pScreen->u32Width = pDesc->width;
137 pScreen->u32Height = pDesc->height;
138 pScreen->u16BitsPerPixel = (uint16_t)pDesc->bpp;
139 pScreen->u16Flags = fFlags;
140
141 vboxHGSMIBufferSubmit (commonFromDeviceExt(pDevExt), p);
142
143 vboxHGSMIBufferFree (commonFromDeviceExt(pDevExt), p);
144 }
145
146 return STATUS_SUCCESS;
147
148}
149
150NTSTATUS vboxWddmGhDisplayPostInfoScreen (PDEVICE_EXTENSION pDevExt, PVBOXWDDM_ALLOCATION pAllocation, POINT * pVScreenPos)
151{
152 NTSTATUS Status = vboxWddmGhDisplayPostInfoScreenBySDesc(pDevExt, &pAllocation->SurfDesc, pVScreenPos, VBVA_SCREEN_F_ACTIVE);
153 Assert(Status == STATUS_SUCCESS);
154 return Status;
155}
156
157NTSTATUS vboxWddmGhDisplayPostInfoView(PDEVICE_EXTENSION pDevExt, PVBOXWDDM_ALLOCATION pAllocation)
158{
159 VBOXVIDEOOFFSET offVram = pAllocation->offVram;
160 Assert(offVram != VBOXVIDEOOFFSET_VOID);
161 if (offVram == VBOXVIDEOOFFSET_VOID)
162 return STATUS_INVALID_PARAMETER;
163
164 /* Issue the screen info command. */
165 void *p = vboxHGSMIBufferAlloc (commonFromDeviceExt(pDevExt),
166 sizeof (VBVAINFOVIEW),
167 HGSMI_CH_VBVA,
168 VBVA_INFO_VIEW);
169 Assert(p);
170 if (p)
171 {
172 VBVAINFOVIEW *pView = (VBVAINFOVIEW *)p;
173
174 pView->u32ViewIndex = pAllocation->SurfDesc.VidPnSourceId;
175 pView->u32ViewOffset = (uint32_t)offVram; /* we pretend the view is located at the start of each framebuffer */
176 pView->u32ViewSize = vboxWddmVramCpuVisibleSegmentSize(pDevExt)/commonFromDeviceExt(pDevExt)->cDisplays;
177
178 pView->u32MaxScreenSize = pView->u32ViewSize;
179
180 vboxHGSMIBufferSubmit (commonFromDeviceExt(pDevExt), p);
181
182 vboxHGSMIBufferFree (commonFromDeviceExt(pDevExt), p);
183 }
184
185 return STATUS_SUCCESS;
186}
187
188NTSTATUS vboxWddmGhDisplaySetMode(PDEVICE_EXTENSION pDevExt, PVBOXWDDM_ALLOCATION pAllocation)
189{
190// PVBOXWDDM_ALLOCATION_SHAREDPRIMARYSURFACE pPrimaryInfo = VBOXWDDM_ALLOCATION_BODY(pAllocation, VBOXWDDM_ALLOCATION_SHAREDPRIMARYSURFACE);
191 if (/*pPrimaryInfo->*/pAllocation->SurfDesc.VidPnSourceId)
192 return STATUS_SUCCESS;
193
194 if (VBoxVideoSetCurrentModePerform(pDevExt, pAllocation->SurfDesc.width,
195 pAllocation->SurfDesc.height, pAllocation->SurfDesc.bpp,
196 (ULONG)pAllocation->offVram))
197 return STATUS_SUCCESS;
198
199 AssertBreakpoint();
200 drprintf((__FUNCTION__": VBoxVideoSetCurrentModePerform failed\n"));
201 return STATUS_UNSUCCESSFUL;
202}
203
204NTSTATUS vboxWddmGhDisplayUpdateScreenPos(PDEVICE_EXTENSION pDevExt, PVBOXWDDM_SOURCE pSource, POINT *pVScreenPos)
205{
206 if (pSource->VScreenPos.x == pVScreenPos->x
207 && pSource->VScreenPos.y == pVScreenPos->y)
208 return STATUS_SUCCESS;
209
210 pSource->VScreenPos = *pVScreenPos;
211
212 PVBOXWDDM_ALLOCATION pAllocation = VBOXWDDM_FB_ALLOCATION(pSource);
213 NTSTATUS Status = vboxWddmGhDisplayPostInfoScreen(pDevExt, pAllocation, &pSource->VScreenPos);
214 Assert(Status == STATUS_SUCCESS);
215 return Status;
216}
217
218NTSTATUS vboxWddmGhDisplaySetInfo(PDEVICE_EXTENSION pDevExt, PVBOXWDDM_SOURCE pSource, D3DDDI_VIDEO_PRESENT_SOURCE_ID VidPnSourceId)
219{
220 PVBOXWDDM_ALLOCATION pAllocation = VBOXWDDM_FB_ALLOCATION(pSource);
221 VBOXVIDEOOFFSET offVram = vboxWddmValidatePrimary(pAllocation);
222 Assert(offVram != VBOXVIDEOOFFSET_VOID);
223 if (offVram == VBOXVIDEOOFFSET_VOID)
224 return STATUS_INVALID_PARAMETER;
225
226 /*
227 * Set the current mode into the hardware.
228 */
229// NTSTATUS Status= vboxWddmDisplaySettingsQueryPos(pDevExt, VidPnSourceId, &pSource->VScreenPos);
230// Assert(Status == STATUS_SUCCESS);
231 NTSTATUS Status = vboxWddmGhDisplaySetMode(pDevExt, pAllocation);
232 Assert(Status == STATUS_SUCCESS);
233 if (Status == STATUS_SUCCESS)
234 {
235 Status = vboxWddmGhDisplayPostInfoView(pDevExt, pAllocation);
236 Assert(Status == STATUS_SUCCESS);
237 if (Status == STATUS_SUCCESS)
238 {
239 Status = vboxWddmGhDisplayPostInfoScreen(pDevExt, pAllocation, &pSource->VScreenPos);
240 Assert(Status == STATUS_SUCCESS);
241 if (Status != STATUS_SUCCESS)
242 drprintf((__FUNCTION__": vboxWddmGhDisplayPostInfoScreen failed\n"));
243 }
244 else
245 drprintf((__FUNCTION__": vboxWddmGhDisplayPostInfoView failed\n"));
246 }
247 else
248 drprintf((__FUNCTION__": vboxWddmGhDisplaySetMode failed\n"));
249
250 return Status;
251}
252
253#ifdef VBOXWDDM_RENDER_FROM_SHADOW
254bool vboxWddmCheckUpdateShadowAddress(PDEVICE_EXTENSION pDevExt, PVBOXWDDM_SOURCE pSource,
255 D3DDDI_VIDEO_PRESENT_SOURCE_ID VidPnSourceId, UINT SegmentId, VBOXVIDEOOFFSET offVram)
256{
257 if (pSource->pPrimaryAllocation->enmType == VBOXWDDM_ALLOC_TYPE_UMD_RC_GENERIC)
258 {
259 Assert(pSource->offVram == VBOXVIDEOOFFSET_VOID);
260 return false;
261 }
262 if (pSource->offVram == offVram)
263 return false;
264 pSource->offVram = offVram;
265 pSource->pShadowAllocation->SegmentId = SegmentId;
266 pSource->pShadowAllocation->offVram = offVram;
267
268 NTSTATUS Status = vboxWddmGhDisplaySetInfo(pDevExt, pSource, VidPnSourceId);
269 Assert(Status == STATUS_SUCCESS);
270 if (Status != STATUS_SUCCESS)
271 drprintf((__FUNCTION__": vboxWddmGhDisplaySetInfo failed, Status (0x%x)\n", Status));
272
273 return true;
274}
275#endif
276
277HGSMIHEAP* vboxWddmHgsmiGetHeapFromCmdOffset(PDEVICE_EXTENSION pDevExt, HGSMIOFFSET offCmd)
278{
279#ifdef VBOX_WITH_VDMA
280 if(HGSMIAreaContainsOffset(&pDevExt->u.primary.Vdma.CmdHeap.area, offCmd))
281 return &pDevExt->u.primary.Vdma.CmdHeap;
282#endif
283 if (HGSMIAreaContainsOffset(&commonFromDeviceExt(pDevExt)->hgsmiAdapterHeap.area, offCmd))
284 return &commonFromDeviceExt(pDevExt)->hgsmiAdapterHeap;
285 return NULL;
286}
287
288typedef enum
289{
290 VBOXWDDM_HGSMICMD_TYPE_UNDEFINED = 0,
291 VBOXWDDM_HGSMICMD_TYPE_CTL = 1,
292#ifdef VBOX_WITH_VDMA
293 VBOXWDDM_HGSMICMD_TYPE_DMACMD = 2
294#endif
295} VBOXWDDM_HGSMICMD_TYPE;
296
297VBOXWDDM_HGSMICMD_TYPE vboxWddmHgsmiGetCmdTypeFromOffset(PDEVICE_EXTENSION pDevExt, HGSMIOFFSET offCmd)
298{
299#ifdef VBOX_WITH_VDMA
300 if(HGSMIAreaContainsOffset(&pDevExt->u.primary.Vdma.CmdHeap.area, offCmd))
301 return VBOXWDDM_HGSMICMD_TYPE_DMACMD;
302#endif
303 if (HGSMIAreaContainsOffset(&commonFromDeviceExt(pDevExt)->hgsmiAdapterHeap.area, offCmd))
304 return VBOXWDDM_HGSMICMD_TYPE_CTL;
305 return VBOXWDDM_HGSMICMD_TYPE_UNDEFINED;
306}
307
308
309VP_STATUS VBoxVideoCmnRegQueryDword(IN VBOXCMNREG Reg, PWSTR pName, uint32_t *pVal)
310{
311 if(!Reg)
312 return ERROR_INVALID_PARAMETER;
313 NTSTATUS Status = vboxWddmRegQueryValueDword(Reg, pName, (PDWORD)pVal);
314 return Status == STATUS_SUCCESS ? NO_ERROR : ERROR_INVALID_PARAMETER;
315}
316
317VP_STATUS VBoxVideoCmnRegSetDword(IN VBOXCMNREG Reg, PWSTR pName, uint32_t Val)
318{
319 if(!Reg)
320 return ERROR_INVALID_PARAMETER;
321 NTSTATUS Status = vboxWddmRegSetValueDword(Reg, pName, Val);
322 return Status == STATUS_SUCCESS ? NO_ERROR : ERROR_INVALID_PARAMETER;
323}
324
325VP_STATUS VBoxVideoCmnRegInit(IN PDEVICE_EXTENSION pDeviceExtension, OUT VBOXCMNREG *pReg)
326{
327 WCHAR Buf[512];
328 ULONG cbBuf = sizeof(Buf);
329 NTSTATUS Status = vboxWddmRegQueryDrvKeyName(pDeviceExtension, cbBuf, Buf, &cbBuf);
330 Assert(Status == STATUS_SUCCESS);
331 if (Status == STATUS_SUCCESS)
332 {
333 Status = vboxWddmRegOpenKey(pReg, Buf, GENERIC_READ | GENERIC_WRITE);
334 Assert(Status == STATUS_SUCCESS);
335 if(Status == STATUS_SUCCESS)
336 return NO_ERROR;
337 }
338
339 /* fall-back to make the subsequent VBoxVideoCmnRegXxx calls treat the fail accordingly
340 * basically needed to make as less modifications to the current XPDM code as possible */
341 *pReg = NULL;
342
343 return ERROR_INVALID_PARAMETER;
344}
345
346D3DDDIFORMAT vboxWddmCalcPixelFormat(VIDEO_MODE_INFORMATION *pInfo)
347{
348 switch (pInfo->BitsPerPlane)
349 {
350 case 32:
351 if(!(pInfo->AttributeFlags & VIDEO_MODE_PALETTE_DRIVEN) && !(pInfo->AttributeFlags & VIDEO_MODE_MANAGED_PALETTE))
352 {
353 if (pInfo->RedMask == 0xFF0000 && pInfo->GreenMask == 0xFF00 && pInfo->BlueMask == 0xFF)
354 return D3DDDIFMT_A8R8G8B8;
355 drprintf((__FUNCTION__": unsupported format: bpp(%d), rmask(%d), gmask(%d), bmask(%d)\n", pInfo->BitsPerPlane, pInfo->RedMask, pInfo->GreenMask, pInfo->BlueMask));
356 AssertBreakpoint();
357 }
358 else
359 {
360 drprintf((__FUNCTION__": unsupported AttributeFlags(0x%x)\n", pInfo->AttributeFlags));
361 AssertBreakpoint();
362 }
363 break;
364 case 24:
365 if(!(pInfo->AttributeFlags & VIDEO_MODE_PALETTE_DRIVEN) && !(pInfo->AttributeFlags & VIDEO_MODE_MANAGED_PALETTE))
366 {
367 if (pInfo->RedMask == 0xFF0000 && pInfo->GreenMask == 0xFF00 && pInfo->BlueMask == 0xFF)
368 return D3DDDIFMT_R8G8B8;
369 drprintf((__FUNCTION__": unsupported format: bpp(%d), rmask(%d), gmask(%d), bmask(%d)\n", pInfo->BitsPerPlane, pInfo->RedMask, pInfo->GreenMask, pInfo->BlueMask));
370 AssertBreakpoint();
371 }
372 else
373 {
374 drprintf((__FUNCTION__": unsupported AttributeFlags(0x%x)\n", pInfo->AttributeFlags));
375 AssertBreakpoint();
376 }
377 break;
378 case 16:
379 if(!(pInfo->AttributeFlags & VIDEO_MODE_PALETTE_DRIVEN) && !(pInfo->AttributeFlags & VIDEO_MODE_MANAGED_PALETTE))
380 {
381 if (pInfo->RedMask == 0xF800 && pInfo->GreenMask == 0x7E0 && pInfo->BlueMask == 0x1F)
382 return D3DDDIFMT_R5G6B5;
383 drprintf((__FUNCTION__": unsupported format: bpp(%d), rmask(%d), gmask(%d), bmask(%d)\n", pInfo->BitsPerPlane, pInfo->RedMask, pInfo->GreenMask, pInfo->BlueMask));
384 AssertBreakpoint();
385 }
386 else
387 {
388 drprintf((__FUNCTION__": unsupported AttributeFlags(0x%x)\n", pInfo->AttributeFlags));
389 AssertBreakpoint();
390 }
391 break;
392 case 8:
393 if((pInfo->AttributeFlags & VIDEO_MODE_PALETTE_DRIVEN) && (pInfo->AttributeFlags & VIDEO_MODE_MANAGED_PALETTE))
394 {
395 return D3DDDIFMT_P8;
396 }
397 else
398 {
399 drprintf((__FUNCTION__": unsupported AttributeFlags(0x%x)\n", pInfo->AttributeFlags));
400 AssertBreakpoint();
401 }
402 break;
403 default:
404 drprintf((__FUNCTION__": unsupported bpp(%d)\n", pInfo->BitsPerPlane));
405 AssertBreakpoint();
406 break;
407 }
408
409 return D3DDDIFMT_UNKNOWN;
410}
411
412NTSTATUS vboxWddmPickResources(PDEVICE_EXTENSION pContext, PDXGK_DEVICE_INFO pDeviceInfo, PULONG pAdapterMemorySize)
413{
414 NTSTATUS Status = STATUS_SUCCESS;
415 USHORT DispiId;
416 *pAdapterMemorySize = VBE_DISPI_TOTAL_VIDEO_MEMORY_BYTES;
417
418 VBoxVideoCmnPortWriteUshort((PUSHORT)VBE_DISPI_IOPORT_INDEX, VBE_DISPI_INDEX_ID);
419 VBoxVideoCmnPortWriteUshort((PUSHORT)VBE_DISPI_IOPORT_DATA, VBE_DISPI_ID2);
420 DispiId = VBoxVideoCmnPortReadUshort((PUSHORT)VBE_DISPI_IOPORT_DATA);
421 if (DispiId == VBE_DISPI_ID2)
422 {
423 dprintf(("VBoxVideoWddm: found the VBE card\n"));
424 /*
425 * Write some hardware information to registry, so that
426 * it's visible in Windows property dialog.
427 */
428
429 /*
430 * Query the adapter's memory size. It's a bit of a hack, we just read
431 * an ULONG from the data port without setting an index before.
432 */
433 *pAdapterMemorySize = VBoxVideoCmnPortReadUlong((PULONG)VBE_DISPI_IOPORT_DATA);
434 if (VBoxHGSMIIsSupported ())
435 {
436 PCM_RESOURCE_LIST pRcList = pDeviceInfo->TranslatedResourceList;
437 /* @todo: verify resources */
438 for (ULONG i = 0; i < pRcList->Count; ++i)
439 {
440 PCM_FULL_RESOURCE_DESCRIPTOR pFRc = &pRcList->List[i];
441 for (ULONG j = 0; j < pFRc->PartialResourceList.Count; ++j)
442 {
443 PCM_PARTIAL_RESOURCE_DESCRIPTOR pPRc = &pFRc->PartialResourceList.PartialDescriptors[j];
444 switch (pPRc->Type)
445 {
446 case CmResourceTypePort:
447 break;
448 case CmResourceTypeInterrupt:
449 break;
450 case CmResourceTypeMemory:
451 break;
452 case CmResourceTypeDma:
453 break;
454 case CmResourceTypeDeviceSpecific:
455 break;
456 case CmResourceTypeBusNumber:
457 break;
458 default:
459 break;
460 }
461 }
462 }
463 }
464 else
465 {
466 drprintf(("VBoxVideoWddm: HGSMI unsupported, returning err\n"));
467 /* @todo: report a better status */
468 Status = STATUS_UNSUCCESSFUL;
469 }
470 }
471 else
472 {
473 drprintf(("VBoxVideoWddm:: VBE card not found, returning err\n"));
474 Status = STATUS_UNSUCCESSFUL;
475 }
476
477
478 return Status;
479}
480
481static void vboxWddmDevExtZeroinit(PDEVICE_EXTENSION pDevExt, CONST PDEVICE_OBJECT pPDO)
482{
483 memset(pDevExt, 0, sizeof (DEVICE_EXTENSION));
484 pDevExt->pPDO = pPDO;
485 PWCHAR pName = (PWCHAR)(((uint8_t*)pDevExt) + VBOXWDDM_ROUNDBOUND(sizeof (DEVICE_EXTENSION), 8));
486 RtlInitUnicodeString(&pDevExt->RegKeyName, pName);
487#ifdef VBOXWDDM_RENDER_FROM_SHADOW
488 for (int i = 0; i < RT_ELEMENTS(pDevExt->aSources); ++i)
489 {
490 pDevExt->aSources[i].offVram = VBOXVIDEOOFFSET_VOID;
491 }
492#endif
493}
494
495static void vboxWddmSetupDisplays(PDEVICE_EXTENSION pDevExt)
496{
497 /* For WDDM, we simply store the number of monitors as we will deal with
498 * VidPN stuff later */
499 int rc = STATUS_SUCCESS;
500
501 if (commonFromDeviceExt(pDevExt)->bHGSMI)
502 {
503 ULONG ulAvailable = commonFromDeviceExt(pDevExt)->cbVRAM
504 - commonFromDeviceExt(pDevExt)->cbMiniportHeap
505 - VBVA_ADAPTER_INFORMATION_SIZE;
506
507 ULONG ulSize;
508 ULONG offset;
509#ifdef VBOX_WITH_VDMA
510 ulSize = ulAvailable / 2;
511 if (ulSize > VBOXWDDM_C_VDMA_BUFFER_SIZE)
512 ulSize = VBOXWDDM_C_VDMA_BUFFER_SIZE;
513
514 /* Align down to 4096 bytes. */
515 ulSize &= ~0xFFF;
516 offset = ulAvailable - ulSize;
517
518 Assert(!(offset & 0xFFF));
519#else
520 offset = ulAvailable;
521#endif
522 rc = vboxVdmaCreate (pDevExt, &pDevExt->u.primary.Vdma
523#ifdef VBOX_WITH_VDMA
524 , offset, ulSize
525#endif
526 );
527 AssertRC(rc);
528 if (RT_SUCCESS(rc))
529 {
530 /* can enable it right away since the host does not need any screen/FB info
531 * for basic DMA functionality */
532 rc = vboxVdmaEnable(pDevExt, &pDevExt->u.primary.Vdma);
533 AssertRC(rc);
534 if (RT_FAILURE(rc))
535 vboxVdmaDestroy(pDevExt, &pDevExt->u.primary.Vdma);
536 }
537
538 ulAvailable = offset;
539 ulSize = ulAvailable/2;
540 offset = ulAvailable - ulSize;
541
542 NTSTATUS Status = vboxVideoAMgrCreate(pDevExt, &pDevExt->AllocMgr, offset, ulSize);
543 Assert(Status == STATUS_SUCCESS);
544 if (Status != STATUS_SUCCESS)
545 {
546 offset = ulAvailable;
547 }
548
549#ifdef VBOXWDDM_RENDER_FROM_SHADOW
550 if (RT_SUCCESS(rc))
551 {
552 ulAvailable = offset;
553 ulSize = ulAvailable / 2;
554 ulSize /= commonFromDeviceExt(pDevExt)->cDisplays;
555 Assert(ulSize > VBVA_MIN_BUFFER_SIZE);
556 if (ulSize > VBVA_MIN_BUFFER_SIZE)
557 {
558 ULONG ulRatio = ulSize/VBVA_MIN_BUFFER_SIZE;
559 ulRatio >>= 4; /* /= 16; */
560 if (ulRatio)
561 ulSize = VBVA_MIN_BUFFER_SIZE * ulRatio;
562 else
563 ulSize = VBVA_MIN_BUFFER_SIZE;
564 }
565 else
566 {
567 /* todo: ?? */
568 }
569
570 ulSize &= ~0xFFF;
571 Assert(ulSize);
572
573 Assert(ulSize * commonFromDeviceExt(pDevExt)->cDisplays < ulAvailable);
574
575 for (int i = commonFromDeviceExt(pDevExt)->cDisplays-1; i >= 0; --i)
576 {
577 offset -= ulSize;
578 rc = vboxVbvaCreate(pDevExt, &pDevExt->aSources[i].Vbva, offset, ulSize, i);
579 AssertRC(rc);
580 if (RT_SUCCESS(rc))
581 {
582 rc = vboxVbvaEnable(pDevExt, &pDevExt->aSources[i].Vbva);
583 AssertRC(rc);
584 if (RT_FAILURE(rc))
585 {
586 /* @todo: de-initialize */
587 }
588 }
589 }
590 }
591#endif
592
593 rc = VBoxMapAdapterMemory(commonFromDeviceExt(pDevExt), (void**)&pDevExt->pvVisibleVram,
594 0,
595 vboxWddmVramCpuVisibleSize(pDevExt));
596 Assert(rc == VINF_SUCCESS);
597 if (rc != VINF_SUCCESS)
598 pDevExt->pvVisibleVram = NULL;
599
600 if (RT_FAILURE(rc))
601 commonFromDeviceExt(pDevExt)->bHGSMI = FALSE;
602 }
603}
604
605static int vboxWddmFreeDisplays(PDEVICE_EXTENSION pDevExt)
606{
607 int rc = VINF_SUCCESS;
608
609 Assert(pDevExt->pvVisibleVram);
610 if (pDevExt->pvVisibleVram)
611 VBoxUnmapAdapterMemory(commonFromDeviceExt(pDevExt), (void**)&pDevExt->pvVisibleVram);
612
613 for (int i = commonFromDeviceExt(pDevExt)->cDisplays-1; i >= 0; --i)
614 {
615 rc = vboxVbvaDisable(pDevExt, &pDevExt->aSources[i].Vbva);
616 AssertRC(rc);
617 if (RT_SUCCESS(rc))
618 {
619 rc = vboxVbvaDestroy(pDevExt, &pDevExt->aSources[i].Vbva);
620 AssertRC(rc);
621 if (RT_FAILURE(rc))
622 {
623 /* @todo: */
624 }
625 }
626 }
627
628 vboxVideoAMgrDestroy(pDevExt, &pDevExt->AllocMgr);
629
630 rc = vboxVdmaDisable(pDevExt, &pDevExt->u.primary.Vdma);
631 AssertRC(rc);
632 if (RT_SUCCESS(rc))
633 {
634 rc = vboxVdmaDestroy(pDevExt, &pDevExt->u.primary.Vdma);
635 AssertRC(rc);
636 }
637 return rc;
638}
639
640/* driver callbacks */
641NTSTATUS DxgkDdiAddDevice(
642 IN CONST PDEVICE_OBJECT PhysicalDeviceObject,
643 OUT PVOID *MiniportDeviceContext
644 )
645{
646 /* The DxgkDdiAddDevice function should be made pageable. */
647 PAGED_CODE();
648
649 dfprintf(("==> "__FUNCTION__ ", pdo(0x%x)\n", PhysicalDeviceObject));
650
651 vboxVDbgBreakFv();
652
653 NTSTATUS Status = STATUS_SUCCESS;
654 PDEVICE_EXTENSION pDevExt;
655
656 WCHAR RegKeyBuf[512];
657 ULONG cbRegKeyBuf = sizeof (RegKeyBuf);
658
659 Status = IoGetDeviceProperty (PhysicalDeviceObject,
660 DevicePropertyDriverKeyName,
661 cbRegKeyBuf,
662 RegKeyBuf,
663 &cbRegKeyBuf);
664 Assert(Status == STATUS_SUCCESS);
665 if (Status == STATUS_SUCCESS)
666 {
667 pDevExt = (PDEVICE_EXTENSION)vboxWddmMemAllocZero(VBOXWDDM_ROUNDBOUND(sizeof (DEVICE_EXTENSION), 8) + cbRegKeyBuf);
668 if (pDevExt)
669 {
670 PWCHAR pName = (PWCHAR)(((uint8_t*)pDevExt) + VBOXWDDM_ROUNDBOUND(sizeof (DEVICE_EXTENSION), 8));
671 memcpy(pName, RegKeyBuf, cbRegKeyBuf);
672 vboxWddmDevExtZeroinit(pDevExt, PhysicalDeviceObject);
673 *MiniportDeviceContext = pDevExt;
674 }
675 else
676 {
677 Status = STATUS_NO_MEMORY;
678 drprintf(("VBoxVideoWddm: ERROR, failed to create context\n"));
679 }
680 }
681
682 dfprintf(("<== "__FUNCTION__ ", Status(0x%x), pDevExt(0x%x)\n", Status, pDevExt));
683
684 return Status;
685}
686
687NTSTATUS DxgkDdiStartDevice(
688 IN CONST PVOID MiniportDeviceContext,
689 IN PDXGK_START_INFO DxgkStartInfo,
690 IN PDXGKRNL_INTERFACE DxgkInterface,
691 OUT PULONG NumberOfVideoPresentSources,
692 OUT PULONG NumberOfChildren
693 )
694{
695 /* The DxgkDdiStartDevice function should be made pageable. */
696 PAGED_CODE();
697
698 NTSTATUS Status;
699
700 dfprintf(("==> "__FUNCTION__ ", context(0x%x)\n", MiniportDeviceContext));
701
702 vboxVDbgBreakFv();
703
704 if ( ARGUMENT_PRESENT(MiniportDeviceContext) &&
705 ARGUMENT_PRESENT(DxgkInterface) &&
706 ARGUMENT_PRESENT(DxgkStartInfo) &&
707 ARGUMENT_PRESENT(NumberOfVideoPresentSources),
708 ARGUMENT_PRESENT(NumberOfChildren)
709 )
710 {
711 PDEVICE_EXTENSION pContext = (PDEVICE_EXTENSION)MiniportDeviceContext;
712
713 vboxWddmVGuidGet(pContext);
714
715 /* Save DeviceHandle and function pointers supplied by the DXGKRNL_INTERFACE structure passed to DxgkInterface. */
716 memcpy(&pContext->u.primary.DxgkInterface, DxgkInterface, sizeof (DXGKRNL_INTERFACE));
717
718 /* Allocate a DXGK_DEVICE_INFO structure, and call DxgkCbGetDeviceInformation to fill in the members of that structure, which include the registry path, the PDO, and a list of translated resources for the display adapter represented by MiniportDeviceContext. Save selected members (ones that the display miniport driver will need later)
719 * of the DXGK_DEVICE_INFO structure in the context block represented by MiniportDeviceContext. */
720 DXGK_DEVICE_INFO DeviceInfo;
721 Status = pContext->u.primary.DxgkInterface.DxgkCbGetDeviceInformation (pContext->u.primary.DxgkInterface.DeviceHandle, &DeviceInfo);
722 if (Status == STATUS_SUCCESS)
723 {
724 ULONG AdapterMemorySize;
725 Status = vboxWddmPickResources(pContext, &DeviceInfo, &AdapterMemorySize);
726 if (Status == STATUS_SUCCESS)
727 {
728 /* Initialize VBoxGuest library, which is used for requests which go through VMMDev. */
729 VbglInit ();
730
731 /* Guest supports only HGSMI, the old VBVA via VMMDev is not supported.
732 * The host will however support both old and new interface to keep compatibility
733 * with old guest additions.
734 */
735 VBoxSetupDisplaysHGSMI(pContext, AdapterMemorySize,
736 VBVACAPS_COMPLETEGCMD_BY_IOREAD | VBVACAPS_IRQ);
737 if (commonFromDeviceExt(pContext)->bHGSMI)
738 {
739 vboxWddmSetupDisplays(pContext);
740 if (!commonFromDeviceExt(pContext)->bHGSMI)
741 VBoxFreeDisplaysHGSMI(commonFromDeviceExt(pContext));
742 }
743 if (commonFromDeviceExt(pContext)->bHGSMI)
744 {
745 drprintf(("VBoxVideoWddm: using HGSMI\n"));
746 *NumberOfVideoPresentSources = commonFromDeviceExt(pContext)->cDisplays;
747 *NumberOfChildren = commonFromDeviceExt(pContext)->cDisplays;
748 dprintf(("VBoxVideoWddm: sources(%d), children(%d)\n", *NumberOfVideoPresentSources, *NumberOfChildren));
749
750 vboxVdmaDdiQueueInit(pContext, &pContext->DdiCmdQueue);
751 vboxVideoCmInit(&pContext->CmMgr);
752 InitializeListHead(&pContext->SwapchainList3D);
753 pContext->cContexts3D = 0;
754 ExInitializeFastMutex(&pContext->ContextMutex);
755 KeInitializeSpinLock(&pContext->SynchLock);
756
757#ifdef VBOX_WITH_VIDEOHWACCEL
758 vboxVhwaInit(pContext);
759#endif
760 }
761 else
762 {
763 drprintf(("VBoxVideoWddm: HGSMI failed to initialize, returning err\n"));
764
765 VbglTerminate();
766 /* @todo: report a better status */
767 Status = STATUS_UNSUCCESSFUL;
768 }
769 }
770 else
771 {
772 drprintf(("VBoxVideoWddm:: vboxWddmPickResources failed Status(0x%x), returning err\n", Status));
773 Status = STATUS_UNSUCCESSFUL;
774 }
775 }
776 else
777 {
778 drprintf(("VBoxVideoWddm: DxgkCbGetDeviceInformation failed Status(0x%x), returning err\n", Status));
779 }
780 }
781 else
782 {
783 drprintf(("VBoxVideoWddm: invalid parameter, returning err\n"));
784 Status = STATUS_INVALID_PARAMETER;
785 }
786
787 dfprintf(("<== "__FUNCTION__ ", status(0x%x)\n", Status));
788
789 return Status;
790}
791
792NTSTATUS DxgkDdiStopDevice(
793 IN CONST PVOID MiniportDeviceContext
794 )
795{
796 /* The DxgkDdiStopDevice function should be made pageable. */
797 PAGED_CODE();
798
799 dfprintf(("==> "__FUNCTION__ ", context(0x%p)\n", MiniportDeviceContext));
800
801 vboxVDbgBreakFv();
802
803 PDEVICE_EXTENSION pDevExt = (PDEVICE_EXTENSION)MiniportDeviceContext;
804 NTSTATUS Status = STATUS_SUCCESS;
805
806 vboxVideoCmTerm(&pDevExt->CmMgr);
807
808 /* do everything we did on DxgkDdiStartDevice in the reverse order */
809#ifdef VBOX_WITH_VIDEOHWACCEL
810 vboxVhwaFree(pDevExt);
811#endif
812
813 int rc = vboxWddmFreeDisplays(pDevExt);
814 if (RT_SUCCESS(rc))
815 VBoxFreeDisplaysHGSMI(commonFromDeviceExt(pDevExt));
816 AssertRC(rc);
817 if (RT_SUCCESS(rc))
818 {
819 VbglTerminate();
820
821 vboxWddmVGuidFree(pDevExt);
822
823 /* revert back to the state we were right after the DxgkDdiAddDevice */
824 vboxWddmDevExtZeroinit(pDevExt, pDevExt->pPDO);
825 }
826 else
827 Status = STATUS_UNSUCCESSFUL;
828
829 return Status;
830}
831
832NTSTATUS DxgkDdiRemoveDevice(
833 IN CONST PVOID MiniportDeviceContext
834 )
835{
836 /* DxgkDdiRemoveDevice should be made pageable. */
837 PAGED_CODE();
838
839 dfprintf(("==> "__FUNCTION__ ", context(0x%p)\n", MiniportDeviceContext));
840
841 vboxVDbgBreakFv();
842
843 vboxWddmMemFree(MiniportDeviceContext);
844
845 dfprintf(("<== "__FUNCTION__ ", context(0x%p)\n", MiniportDeviceContext));
846
847 return STATUS_SUCCESS;
848}
849
850NTSTATUS DxgkDdiDispatchIoRequest(
851 IN CONST PVOID MiniportDeviceContext,
852 IN ULONG VidPnSourceId,
853 IN PVIDEO_REQUEST_PACKET VideoRequestPacket
854 )
855{
856 dfprintf(("==> "__FUNCTION__ ", context(0x%p), ctl(0x%x)\n", MiniportDeviceContext, VideoRequestPacket->IoControlCode));
857
858 AssertBreakpoint();
859#if 0
860 PDEVICE_EXTENSION pDevExt = (PDEVICE_EXTENSION)MiniportDeviceContext;
861
862 switch (VideoRequestPacket->IoControlCode)
863 {
864 case IOCTL_VIDEO_QUERY_COLOR_CAPABILITIES:
865 {
866 if (VideoRequestPacket->OutputBufferLength < sizeof(VIDEO_COLOR_CAPABILITIES))
867 {
868 AssertBreakpoint();
869 VideoRequestPacket->StatusBlock->Status = ERROR_INSUFFICIENT_BUFFER;
870 return TRUE;
871 }
872 VIDEO_COLOR_CAPABILITIES *pCaps = (VIDEO_COLOR_CAPABILITIES*)VideoRequestPacket->OutputBuffer;
873
874 pCaps->Length = sizeof (VIDEO_COLOR_CAPABILITIES);
875 pCaps->AttributeFlags = VIDEO_DEVICE_COLOR;
876 pCaps->RedPhosphoreDecay = 0;
877 pCaps->GreenPhosphoreDecay = 0;
878 pCaps->BluePhosphoreDecay = 0;
879 pCaps->WhiteChromaticity_x = 3127;
880 pCaps->WhiteChromaticity_y = 3290;
881 pCaps->WhiteChromaticity_Y = 0;
882 pCaps->RedChromaticity_x = 6700;
883 pCaps->RedChromaticity_y = 3300;
884 pCaps->GreenChromaticity_x = 2100;
885 pCaps->GreenChromaticity_y = 7100;
886 pCaps->BlueChromaticity_x = 1400;
887 pCaps->BlueChromaticity_y = 800;
888 pCaps->WhiteGamma = 0;
889 pCaps->RedGamma = 20000;
890 pCaps->GreenGamma = 20000;
891 pCaps->BlueGamma = 20000;
892
893 VideoRequestPacket->StatusBlock->Status = NO_ERROR;
894 VideoRequestPacket->StatusBlock->Information = sizeof (VIDEO_COLOR_CAPABILITIES);
895 break;
896 }
897#if 0
898 case IOCTL_VIDEO_HANDLE_VIDEOPARAMETERS:
899 {
900 if (VideoRequestPacket->OutputBufferLength < sizeof(VIDEOPARAMETERS)
901 || VideoRequestPacket->InputBufferLength < sizeof(VIDEOPARAMETERS))
902 {
903 AssertBreakpoint();
904 VideoRequestPacket->StatusBlock->Status = ERROR_INSUFFICIENT_BUFFER;
905 return TRUE;
906 }
907
908 Result = VBoxVideoResetDevice((PDEVICE_EXTENSION)HwDeviceExtension,
909 RequestPacket->StatusBlock);
910 break;
911 }
912#endif
913 default:
914 AssertBreakpoint();
915 VideoRequestPacket->StatusBlock->Status = ERROR_INVALID_FUNCTION;
916 VideoRequestPacket->StatusBlock->Information = 0;
917 }
918#endif
919 dfprintf(("<== "__FUNCTION__ ", context(0x%p), ctl(0x%x)\n", MiniportDeviceContext, VideoRequestPacket->IoControlCode));
920
921 return STATUS_SUCCESS;
922}
923
924BOOLEAN DxgkDdiInterruptRoutine(
925 IN CONST PVOID MiniportDeviceContext,
926 IN ULONG MessageNumber
927 )
928{
929// dfprintf(("==> "__FUNCTION__ ", context(0x%p), msg(0x%x)\n", MiniportDeviceContext, MessageNumber));
930
931 vboxVDbgBreakFv();
932
933 PDEVICE_EXTENSION pDevExt = (PDEVICE_EXTENSION)MiniportDeviceContext;
934 BOOLEAN bOur = FALSE;
935 BOOLEAN bNeedDpc = FALSE;
936 if (commonFromDeviceExt(pDevExt)->pHostFlags) /* If HGSMI is enabled at all. */
937 {
938 VBOXSHGSMILIST CtlList;
939#ifdef VBOX_WITH_VDMA
940 VBOXSHGSMILIST DmaCmdList;
941#endif
942 vboxSHGSMIListInit(&CtlList);
943#ifdef VBOX_WITH_VDMA
944 vboxSHGSMIListInit(&DmaCmdList);
945#endif
946
947#ifdef VBOX_WITH_VIDEOHWACCEL
948 VBOXSHGSMILIST VhwaCmdList;
949 vboxSHGSMIListInit(&VhwaCmdList);
950#endif
951
952 uint32_t flags = commonFromDeviceExt(pDevExt)->pHostFlags->u32HostFlags;
953 bOur = (flags & HGSMIHOSTFLAGS_IRQ);
954 do
955 {
956 if (flags & HGSMIHOSTFLAGS_GCOMMAND_COMPLETED)
957 {
958 /* read the command offset */
959 HGSMIOFFSET offCmd = VBoxHGSMIGuestRead(commonFromDeviceExt(pDevExt));
960 Assert(offCmd != HGSMIOFFSET_VOID);
961 if (offCmd != HGSMIOFFSET_VOID)
962 {
963 VBOXWDDM_HGSMICMD_TYPE enmType = vboxWddmHgsmiGetCmdTypeFromOffset(pDevExt, offCmd);
964 PVBOXSHGSMILIST pList;
965 HGSMIHEAP * pHeap = NULL;
966 switch (enmType)
967 {
968#ifdef VBOX_WITH_VDMA
969 case VBOXWDDM_HGSMICMD_TYPE_DMACMD:
970 pList = &DmaCmdList;
971 pHeap = &pDevExt->u.primary.Vdma.CmdHeap;
972 break;
973#endif
974 case VBOXWDDM_HGSMICMD_TYPE_CTL:
975 pList = &CtlList;
976 pHeap = &commonFromDeviceExt(pDevExt)->hgsmiAdapterHeap;
977 break;
978 default:
979 AssertBreakpoint();
980 }
981
982 if (pHeap)
983 {
984 uint16_t chInfo;
985 uint8_t *pvCmd = HGSMIBufferDataAndChInfoFromOffset (&pHeap->area, offCmd, &chInfo);
986 Assert(pvCmd);
987 if (pvCmd)
988 {
989 switch (chInfo)
990 {
991#ifdef VBOX_WITH_VDMA
992 case VBVA_VDMA_CMD:
993 case VBVA_VDMA_CTL:
994 {
995 int rc = VBoxSHGSMICommandProcessCompletion (pHeap, (VBOXSHGSMIHEADER*)pvCmd, TRUE /*bool bIrq*/ , pList);
996 AssertRC(rc);
997 break;
998 }
999#endif
1000#ifdef VBOX_WITH_VIDEOHWACCEL
1001 case VBVA_VHWA_CMD:
1002 {
1003 vboxVhwaPutList(&VhwaCmdList, (VBOXVHWACMD*)pvCmd);
1004 break;
1005 }
1006#endif /* # ifdef VBOX_WITH_VIDEOHWACCEL */
1007 default:
1008 AssertBreakpoint();
1009 }
1010 }
1011 }
1012 }
1013 }
1014 else if (flags & HGSMIHOSTFLAGS_COMMANDS_PENDING)
1015 {
1016 AssertBreakpoint();
1017 /* @todo: FIXME: implement !!! */
1018 }
1019 else
1020 break;
1021
1022 flags = commonFromDeviceExt(pDevExt)->pHostFlags->u32HostFlags;
1023 } while (1);
1024
1025 if (!vboxSHGSMIListIsEmpty(&CtlList))
1026 {
1027 vboxSHGSMIListCat(&pDevExt->CtlList, &CtlList);
1028 bNeedDpc = TRUE;
1029 }
1030#ifdef VBOX_WITH_VDMA
1031 if (!vboxSHGSMIListIsEmpty(&DmaCmdList))
1032 {
1033 vboxSHGSMIListCat(&pDevExt->DmaCmdList, &DmaCmdList);
1034 bNeedDpc = TRUE;
1035 }
1036#endif
1037 if (!vboxSHGSMIListIsEmpty(&VhwaCmdList))
1038 {
1039 vboxSHGSMIListCat(&pDevExt->VhwaCmdList, &VhwaCmdList);
1040 bNeedDpc = TRUE;
1041 }
1042
1043 bNeedDpc |= !vboxVdmaDdiCmdIsCompletedListEmptyIsr(&pDevExt->DdiCmdQueue);
1044
1045 if (pDevExt->bNotifyDxDpc)
1046 {
1047// Assert(bNeedDpc == TRUE);
1048// pDevExt->bNotifyDxDpc = TRUE;
1049// pDevExt->bSetNotifyDxDpc = FALSE;
1050 bNeedDpc = TRUE;
1051 }
1052
1053 if (bOur)
1054 {
1055 HGSMIClearIrq (commonFromDeviceExt(pDevExt));
1056#ifdef DEBUG_misha
1057 /* this is not entirely correct since host may concurrently complete some commands and raise a new IRQ while we are here,
1058 * still this allows to check that the host flags are correctly cleared after the ISR */
1059 Assert(commonFromDeviceExt(pDevExt)->pHostFlags);
1060 uint32_t flags = commonFromDeviceExt(pDevExt)->pHostFlags->u32HostFlags;
1061 Assert(flags == 0);
1062#endif
1063 }
1064
1065 if (bNeedDpc)
1066 {
1067 BOOLEAN bDpcQueued = pDevExt->u.primary.DxgkInterface.DxgkCbQueueDpc(pDevExt->u.primary.DxgkInterface.DeviceHandle);
1068 }
1069 }
1070
1071// dfprintf(("<== "__FUNCTION__ ", context(0x%p), bOur(0x%x)\n", MiniportDeviceContext, (ULONG)bOur));
1072
1073 return bOur;
1074}
1075
1076
1077typedef struct VBOXWDDM_DPCDATA
1078{
1079 VBOXSHGSMILIST CtlList;
1080#ifdef VBOX_WITH_VDMA
1081 VBOXSHGSMILIST DmaCmdList;
1082#endif
1083#ifdef VBOX_WITH_VIDEOHWACCEL
1084 VBOXSHGSMILIST VhwaCmdList;
1085#endif
1086 LIST_ENTRY CompletedDdiCmdQueue;
1087 BOOL bNotifyDpc;
1088} VBOXWDDM_DPCDATA, *PVBOXWDDM_DPCDATA;
1089
1090typedef struct VBOXWDDM_GETDPCDATA_CONTEXT
1091{
1092 PDEVICE_EXTENSION pDevExt;
1093 VBOXWDDM_DPCDATA data;
1094} VBOXWDDM_GETDPCDATA_CONTEXT, *PVBOXWDDM_GETDPCDATA_CONTEXT;
1095
1096BOOLEAN vboxWddmGetDPCDataCallback(PVOID Context)
1097{
1098 PVBOXWDDM_GETDPCDATA_CONTEXT pdc = (PVBOXWDDM_GETDPCDATA_CONTEXT)Context;
1099
1100 vboxSHGSMIListDetach2List(&pdc->pDevExt->CtlList, &pdc->data.CtlList);
1101#ifdef VBOX_WITH_VDMA
1102 vboxSHGSMIListDetach2List(&pdc->pDevExt->DmaCmdList, &pdc->data.DmaCmdList);
1103#endif
1104#ifdef VBOX_WITH_VIDEOHWACCEL
1105 vboxSHGSMIListDetach2List(&pdc->pDevExt->VhwaCmdList, &pdc->data.VhwaCmdList);
1106#endif
1107 vboxVdmaDdiCmdGetCompletedListIsr(&pdc->pDevExt->DdiCmdQueue, &pdc->data.CompletedDdiCmdQueue);
1108
1109 pdc->data.bNotifyDpc = pdc->pDevExt->bNotifyDxDpc;
1110 pdc->pDevExt->bNotifyDxDpc = FALSE;
1111 return TRUE;
1112}
1113
1114VOID DxgkDdiDpcRoutine(
1115 IN CONST PVOID MiniportDeviceContext
1116 )
1117{
1118// dfprintf(("==> "__FUNCTION__ ", context(0x%p)\n", MiniportDeviceContext));
1119
1120 vboxVDbgBreakFv();
1121
1122 PDEVICE_EXTENSION pDevExt = (PDEVICE_EXTENSION)MiniportDeviceContext;
1123
1124 VBOXWDDM_GETDPCDATA_CONTEXT context = {0};
1125 BOOLEAN bRet;
1126
1127 context.pDevExt = pDevExt;
1128
1129 /* get DPC data at IRQL */
1130 NTSTATUS Status = pDevExt->u.primary.DxgkInterface.DxgkCbSynchronizeExecution(
1131 pDevExt->u.primary.DxgkInterface.DeviceHandle,
1132 vboxWddmGetDPCDataCallback,
1133 &context,
1134 0, /* IN ULONG MessageNumber */
1135 &bRet);
1136 Assert(Status == STATUS_SUCCESS);
1137
1138 if (context.data.bNotifyDpc)
1139 pDevExt->u.primary.DxgkInterface.DxgkCbNotifyDpc(pDevExt->u.primary.DxgkInterface.DeviceHandle);
1140
1141 if (!vboxSHGSMIListIsEmpty(&context.data.CtlList))
1142 {
1143 int rc = VBoxSHGSMICommandPostprocessCompletion (&commonFromDeviceExt(pDevExt)->hgsmiAdapterHeap, &context.data.CtlList);
1144 AssertRC(rc);
1145 }
1146#ifdef VBOX_WITH_VDMA
1147 if (!vboxSHGSMIListIsEmpty(&context.data.DmaCmdList))
1148 {
1149 int rc = VBoxSHGSMICommandPostprocessCompletion (&pDevExt->u.primary.Vdma.CmdHeap, &context.data.DmaCmdList);
1150 AssertRC(rc);
1151 }
1152#endif
1153#ifdef VBOX_WITH_VIDEOHWACCEL
1154 if (!vboxSHGSMIListIsEmpty(&context.data.VhwaCmdList))
1155 {
1156 vboxVhwaCompletionListProcess(pDevExt, &context.data.VhwaCmdList);
1157 }
1158#endif
1159
1160 vboxVdmaDdiCmdHandleCompletedList(pDevExt, &pDevExt->DdiCmdQueue, &context.data.CompletedDdiCmdQueue);
1161
1162// dfprintf(("<== "__FUNCTION__ ", context(0x%p)\n", MiniportDeviceContext));
1163}
1164
1165NTSTATUS DxgkDdiQueryChildRelations(
1166 IN CONST PVOID MiniportDeviceContext,
1167 IN OUT PDXGK_CHILD_DESCRIPTOR ChildRelations,
1168 IN ULONG ChildRelationsSize
1169 )
1170{
1171 /* The DxgkDdiQueryChildRelations function should be made pageable. */
1172 PAGED_CODE();
1173
1174 vboxVDbgBreakFv();
1175
1176 PDEVICE_EXTENSION pDevExt = (PDEVICE_EXTENSION)MiniportDeviceContext;
1177
1178 dfprintf(("==> "__FUNCTION__ ", context(0x%x)\n", MiniportDeviceContext));
1179 Assert(ChildRelationsSize == (commonFromDeviceExt(pDevExt)->cDisplays + 1)*sizeof(DXGK_CHILD_DESCRIPTOR));
1180 for (int i = 0; i < commonFromDeviceExt(pDevExt)->cDisplays; ++i)
1181 {
1182 ChildRelations[i].ChildDeviceType = TypeVideoOutput;
1183 ChildRelations[i].ChildCapabilities.Type.VideoOutput.InterfaceTechnology = D3DKMDT_VOT_HD15; /* VGA */
1184 ChildRelations[i].ChildCapabilities.Type.VideoOutput.MonitorOrientationAwareness = D3DKMDT_MOA_INTERRUPTIBLE; /* ?? D3DKMDT_MOA_NONE*/
1185 ChildRelations[i].ChildCapabilities.Type.VideoOutput.SupportsSdtvModes = FALSE;
1186 ChildRelations[i].ChildCapabilities.HpdAwareness = HpdAwarenessInterruptible; /* ?? HpdAwarenessAlwaysConnected; */
1187 ChildRelations[i].AcpiUid = i; /* */
1188 ChildRelations[i].ChildUid = i; /* should be == target id */
1189 }
1190 dfprintf(("<== "__FUNCTION__ ", context(0x%x)\n", MiniportDeviceContext));
1191 return STATUS_SUCCESS;
1192}
1193
1194NTSTATUS DxgkDdiQueryChildStatus(
1195 IN CONST PVOID MiniportDeviceContext,
1196 IN PDXGK_CHILD_STATUS ChildStatus,
1197 IN BOOLEAN NonDestructiveOnly
1198 )
1199{
1200 /* The DxgkDdiQueryChildStatus should be made pageable. */
1201 PAGED_CODE();
1202
1203 vboxVDbgBreakFv();
1204
1205 dfprintf(("==> "__FUNCTION__ ", context(0x%x)\n", MiniportDeviceContext));
1206
1207 NTSTATUS Status = STATUS_SUCCESS;
1208 switch (ChildStatus->Type)
1209 {
1210 case StatusConnection:
1211 ChildStatus->HotPlug.Connected = TRUE;
1212 dfprintf(("VBoxVideoWddm: StatusConnection\n"));
1213 break;
1214 case StatusRotation:
1215 ChildStatus->Rotation.Angle = 0;
1216 dfprintf(("VBoxVideoWddm: StatusRotation\n"));
1217 break;
1218 default:
1219 drprintf(("VBoxVideoWddm: ERROR: status type: %d\n", ChildStatus->Type));
1220 AssertBreakpoint();
1221 Status = STATUS_INVALID_PARAMETER;
1222 break;
1223 }
1224
1225 dfprintf(("<== "__FUNCTION__ ", context(0x%x)\n", MiniportDeviceContext));
1226
1227 return Status;
1228}
1229
1230NTSTATUS DxgkDdiQueryDeviceDescriptor(
1231 IN CONST PVOID MiniportDeviceContext,
1232 IN ULONG ChildUid,
1233 IN OUT PDXGK_DEVICE_DESCRIPTOR DeviceDescriptor
1234 )
1235{
1236 /* The DxgkDdiQueryDeviceDescriptor should be made pageable. */
1237 PAGED_CODE();
1238
1239 vboxVDbgBreakFv();
1240
1241 dfprintf(("==> "__FUNCTION__ ", context(0x%x)\n", MiniportDeviceContext));
1242
1243 dfprintf(("<== "__FUNCTION__ ", context(0x%x)\n", MiniportDeviceContext));
1244
1245 /* we do not support EDID */
1246 return STATUS_MONITOR_NO_DESCRIPTOR;
1247}
1248
1249NTSTATUS DxgkDdiSetPowerState(
1250 IN CONST PVOID MiniportDeviceContext,
1251 IN ULONG DeviceUid,
1252 IN DEVICE_POWER_STATE DevicePowerState,
1253 IN POWER_ACTION ActionType
1254 )
1255{
1256 /* The DxgkDdiSetPowerState function should be made pageable. */
1257 PAGED_CODE();
1258
1259 dfprintf(("==> "__FUNCTION__ ", context(0x%x)\n", MiniportDeviceContext));
1260
1261 /* @todo: */
1262// vboxVDbgBreakF();
1263
1264 dfprintf(("<== "__FUNCTION__ ", context(0x%x)\n", MiniportDeviceContext));
1265
1266 return STATUS_SUCCESS;
1267}
1268
1269NTSTATUS DxgkDdiNotifyAcpiEvent(
1270 IN CONST PVOID MiniportDeviceContext,
1271 IN DXGK_EVENT_TYPE EventType,
1272 IN ULONG Event,
1273 IN PVOID Argument,
1274 OUT PULONG AcpiFlags
1275 )
1276{
1277 dfprintf(("==> "__FUNCTION__ ", MiniportDeviceContext(0x%x)\n", MiniportDeviceContext));
1278
1279 vboxVDbgBreakF();
1280
1281 dfprintf(("<== "__FUNCTION__ ", MiniportDeviceContext(0x%x)\n", MiniportDeviceContext));
1282
1283 return STATUS_SUCCESS;
1284}
1285
1286VOID DxgkDdiResetDevice(
1287 IN CONST PVOID MiniportDeviceContext
1288 )
1289{
1290 /* DxgkDdiResetDevice can be called at any IRQL, so it must be in nonpageable memory. */
1291 vboxVDbgBreakF();
1292
1293
1294
1295 dfprintf(("==> "__FUNCTION__ ", context(0x%x)\n", MiniportDeviceContext));
1296 dfprintf(("<== "__FUNCTION__ ", context(0x%x)\n", MiniportDeviceContext));
1297}
1298
1299VOID DxgkDdiUnload(
1300 VOID
1301 )
1302{
1303 /* DxgkDdiUnload should be made pageable. */
1304 PAGED_CODE();
1305 dfprintf(("==> "__FUNCTION__ "\n"));
1306
1307 vboxVDbgBreakFv();
1308
1309 dfprintf(("<== "__FUNCTION__ "\n"));
1310}
1311
1312NTSTATUS DxgkDdiQueryInterface(
1313 IN CONST PVOID MiniportDeviceContext,
1314 IN PQUERY_INTERFACE QueryInterface
1315 )
1316{
1317 dfprintf(("==> "__FUNCTION__ ", MiniportDeviceContext(0x%x)\n", MiniportDeviceContext));
1318
1319 vboxVDbgBreakFv();
1320
1321 dfprintf(("<== "__FUNCTION__ ", MiniportDeviceContext(0x%x)\n", MiniportDeviceContext));
1322
1323 return STATUS_NOT_SUPPORTED;
1324}
1325
1326VOID DxgkDdiControlEtwLogging(
1327 IN BOOLEAN Enable,
1328 IN ULONG Flags,
1329 IN UCHAR Level
1330 )
1331{
1332 dfprintf(("==> "__FUNCTION__ "\n"));
1333
1334 vboxVDbgBreakF();
1335
1336 dfprintf(("<== "__FUNCTION__ "\n"));
1337}
1338
1339/**
1340 * DxgkDdiQueryAdapterInfo
1341 */
1342NTSTATUS APIENTRY DxgkDdiQueryAdapterInfo(
1343 CONST HANDLE hAdapter,
1344 CONST DXGKARG_QUERYADAPTERINFO* pQueryAdapterInfo)
1345{
1346 /* The DxgkDdiQueryAdapterInfo should be made pageable. */
1347 PAGED_CODE();
1348
1349 dfprintf(("==> "__FUNCTION__ ", context(0x%x), Query type (%d)\n", hAdapter, pQueryAdapterInfo->Type));
1350 NTSTATUS Status = STATUS_SUCCESS;
1351 PDEVICE_EXTENSION pContext = (PDEVICE_EXTENSION)hAdapter;
1352
1353 vboxVDbgBreakFv();
1354
1355 switch (pQueryAdapterInfo->Type)
1356 {
1357 case DXGKQAITYPE_DRIVERCAPS:
1358 {
1359 DXGK_DRIVERCAPS *pCaps = (DXGK_DRIVERCAPS*)pQueryAdapterInfo->pOutputData;
1360
1361 pCaps->HighestAcceptableAddress.HighPart = 0x0;
1362 pCaps->HighestAcceptableAddress.LowPart = 0xffffffffUL;
1363 pCaps->MaxAllocationListSlotId = 16;
1364 pCaps->ApertureSegmentCommitLimit = 0;
1365 pCaps->MaxPointerWidth = VBOXWDDM_C_POINTER_MAX_WIDTH;
1366 pCaps->MaxPointerHeight = VBOXWDDM_C_POINTER_MAX_HEIGHT;
1367 pCaps->PointerCaps.Value = 3; /* Monochrome , Color*/ /* MaskedColor == Value | 4, dosable for now */
1368 pCaps->InterruptMessageNumber = 0;
1369 pCaps->NumberOfSwizzlingRanges = 0;
1370 pCaps->MaxOverlays = 0;
1371#ifdef VBOX_WITH_VIDEOHWACCEL
1372 for (int i = 0; i < commonFromDeviceExt(pContext)->cDisplays; ++i)
1373 {
1374 if ( pContext->aSources[i].Vhwa.Settings.fFlags & VBOXVHWA_F_ENABLED)
1375 pCaps->MaxOverlays += pContext->aSources[i].Vhwa.Settings.cOverlaysSupported;
1376 }
1377#endif
1378 pCaps->GammaRampCaps.Value = 0;
1379 pCaps->PresentationCaps.Value = 0;
1380 pCaps->PresentationCaps.NoScreenToScreenBlt = 1;
1381 pCaps->PresentationCaps.NoOverlapScreenBlt = 1;
1382 pCaps->MaxQueuedFlipOnVSync = 0; /* do we need it? */
1383 pCaps->FlipCaps.Value = 0;
1384 /* ? pCaps->FlipCaps.FlipOnVSyncWithNoWait = 1; */
1385 pCaps->SchedulingCaps.Value = 0;
1386 /* we might need it for Aero.
1387 * Setting this flag means we support DeviceContext, i.e.
1388 * DxgkDdiCreateContext and DxgkDdiDestroyContext
1389 */
1390 pCaps->SchedulingCaps.MultiEngineAware = 1;
1391 pCaps->MemoryManagementCaps.Value = 0;
1392 /* @todo: this correlates with pCaps->SchedulingCaps.MultiEngineAware */
1393 pCaps->MemoryManagementCaps.PagingNode = 0;
1394 /* @todo: this correlates with pCaps->SchedulingCaps.MultiEngineAware */
1395 pCaps->GpuEngineTopology.NbAsymetricProcessingNodes = 1;
1396
1397 break;
1398 }
1399 case DXGKQAITYPE_QUERYSEGMENT:
1400 {
1401 /* no need for DXGK_QUERYSEGMENTIN as it contains AGP aperture info, which (AGP aperture) we do not support
1402 * DXGK_QUERYSEGMENTIN *pQsIn = (DXGK_QUERYSEGMENTIN*)pQueryAdapterInfo->pInputData; */
1403 DXGK_QUERYSEGMENTOUT *pQsOut = (DXGK_QUERYSEGMENTOUT*)pQueryAdapterInfo->pOutputData;
1404#ifdef VBOXWDDM_RENDER_FROM_SHADOW
1405# define VBOXWDDM_SEGMENTS_COUNT 2
1406#else
1407# define VBOXWDDM_SEGMENTS_COUNT 1
1408#endif
1409 if (!pQsOut->pSegmentDescriptor)
1410 {
1411 /* we are requested to provide the number of segments we support */
1412 pQsOut->NbSegment = VBOXWDDM_SEGMENTS_COUNT;
1413 }
1414 else if (pQsOut->NbSegment != VBOXWDDM_SEGMENTS_COUNT)
1415 {
1416 AssertBreakpoint();
1417 drprintf((__FUNCTION__ " NbSegment (%d) != 1\n", pQsOut->NbSegment));
1418 Status = STATUS_INVALID_PARAMETER;
1419 }
1420 else
1421 {
1422 DXGK_SEGMENTDESCRIPTOR* pDr = pQsOut->pSegmentDescriptor;
1423 /* we are requested to provide segment information */
1424 pDr->BaseAddress.QuadPart = 0; /* VBE_DISPI_LFB_PHYSICAL_ADDRESS; */
1425 pDr->CpuTranslatedAddress.QuadPart = VBE_DISPI_LFB_PHYSICAL_ADDRESS;
1426 /* make sure the size is page aligned */
1427 /* @todo: need to setup VBVA buffers and adjust the mem size here */
1428 pDr->Size = vboxWddmVramCpuVisibleSegmentSize(pContext);
1429 pDr->NbOfBanks = 0;
1430 pDr->pBankRangeTable = 0;
1431 pDr->CommitLimit = pDr->Size;
1432 pDr->Flags.Value = 0;
1433 pDr->Flags.CpuVisible = 1;
1434#ifdef VBOXWDDM_RENDER_FROM_SHADOW
1435 ++pDr;
1436 /* create cpu-invisible segment of the same size */
1437 pDr->BaseAddress.QuadPart = 0;
1438 pDr->CpuTranslatedAddress.QuadPart = 0;
1439 /* make sure the size is page aligned */
1440 /* @todo: need to setup VBVA buffers and adjust the mem size here */
1441 pDr->Size = vboxWddmVramCpuInvisibleSegmentSize(pContext);
1442 pDr->NbOfBanks = 0;
1443 pDr->pBankRangeTable = 0;
1444 pDr->CommitLimit = pDr->Size;
1445 pDr->Flags.Value = 0;
1446#endif
1447
1448 pQsOut->PagingBufferSegmentId = 0;
1449 pQsOut->PagingBufferSize = 1024;
1450 pQsOut->PagingBufferPrivateDataSize = 0; /* @todo: do we need a private buffer ? */
1451 }
1452 break;
1453 }
1454 case DXGKQAITYPE_UMDRIVERPRIVATE:
1455 Assert (pQueryAdapterInfo->OutputDataSize >= sizeof (VBOXWDDM_QI));
1456 if (pQueryAdapterInfo->OutputDataSize >= sizeof (VBOXWDDM_QI))
1457 {
1458 VBOXWDDM_QI * pQi = (VBOXWDDM_QI*)pQueryAdapterInfo->pOutputData;
1459 memset (pQi, 0, sizeof (VBOXWDDM_QI));
1460 pQi->u32Version = VBOXVIDEOIF_VERSION;
1461 pQi->cInfos = commonFromDeviceExt(pContext)->cDisplays;
1462#ifdef VBOX_WITH_VIDEOHWACCEL
1463 for (int i = 0; i < commonFromDeviceExt(pContext)->cDisplays; ++i)
1464 {
1465 pQi->aInfos[i] = pContext->aSources[i].Vhwa.Settings;
1466 }
1467#endif
1468 }
1469 else
1470 {
1471 drprintf((__FUNCTION__ ": buffer too small\n"));
1472 Status = STATUS_BUFFER_TOO_SMALL;
1473 }
1474 break;
1475 default:
1476 drprintf((__FUNCTION__ ": unsupported Type (%d)\n", pQueryAdapterInfo->Type));
1477 AssertBreakpoint();
1478 Status = STATUS_NOT_SUPPORTED;
1479 break;
1480 }
1481 dfprintf(("<== "__FUNCTION__ ", context(0x%x), Status(0x%x)\n", hAdapter, Status));
1482 return Status;
1483}
1484
1485/**
1486 * DxgkDdiCreateDevice
1487 */
1488NTSTATUS APIENTRY DxgkDdiCreateDevice(
1489 CONST HANDLE hAdapter,
1490 DXGKARG_CREATEDEVICE* pCreateDevice)
1491{
1492 /* DxgkDdiCreateDevice should be made pageable. */
1493 PAGED_CODE();
1494
1495 dfprintf(("==> "__FUNCTION__ ", context(0x%x)\n", hAdapter));
1496 NTSTATUS Status = STATUS_SUCCESS;
1497 PDEVICE_EXTENSION pContext = (PDEVICE_EXTENSION)hAdapter;
1498
1499 vboxVDbgBreakFv();
1500
1501 PVBOXWDDM_DEVICE pDevice = (PVBOXWDDM_DEVICE)vboxWddmMemAllocZero(sizeof (VBOXWDDM_DEVICE));
1502 pCreateDevice->hDevice = pDevice;
1503 if (pCreateDevice->Flags.SystemDevice)
1504 pDevice->enmType = VBOXWDDM_DEVICE_TYPE_SYSTEM;
1505// else
1506// {
1507// AssertBreakpoint(); /* we do not support custom contexts for now */
1508// drprintf((__FUNCTION__ ": we do not support custom devices for now, hAdapter (0x%x)\n", hAdapter));
1509// }
1510
1511 pDevice->pAdapter = pContext;
1512 pDevice->hDevice = pCreateDevice->hDevice;
1513
1514 pCreateDevice->hDevice = pDevice;
1515 pCreateDevice->pInfo = NULL;
1516
1517 dfprintf(("<== "__FUNCTION__ ", context(0x%x), Status(0x%x)\n", hAdapter, Status));
1518
1519 return Status;
1520}
1521
1522PVBOXWDDM_ALLOCATION vboxWddmAllocationCreateFromResource(PVBOXWDDM_RESOURCE pResource, uint32_t iIndex)
1523{
1524 PVBOXWDDM_ALLOCATION pAllocation = NULL;
1525 if (pResource)
1526 {
1527 Assert(iIndex < pResource->cAllocations);
1528 if (iIndex < pResource->cAllocations)
1529 {
1530 pAllocation = &pResource->aAllocations[iIndex];
1531 memset(pAllocation, 0, sizeof (VBOXWDDM_ALLOCATION));
1532 }
1533 }
1534 else
1535 pAllocation = (PVBOXWDDM_ALLOCATION)vboxWddmMemAllocZero(sizeof (VBOXWDDM_ALLOCATION));
1536
1537 if (pAllocation)
1538 {
1539 if (pResource)
1540 {
1541 pAllocation->pResource = pResource;
1542 pAllocation->iIndex = iIndex;
1543 }
1544 }
1545
1546 return pAllocation;
1547}
1548
1549void vboxWddmAllocationDeleteFromResource(PVBOXWDDM_RESOURCE pResource, PVBOXWDDM_ALLOCATION pAllocation)
1550{
1551 Assert(pAllocation->pResource == pResource);
1552 if (pResource)
1553 {
1554 Assert(&pResource->aAllocations[pAllocation->iIndex] == pAllocation);
1555 }
1556 else
1557 {
1558 vboxWddmMemFree(pAllocation);
1559 }
1560}
1561
1562NTSTATUS vboxWddmDestroyAllocation(PDEVICE_EXTENSION pDevExt, PVBOXWDDM_ALLOCATION pAllocation)
1563{
1564 PAGED_CODE();
1565
1566 switch (pAllocation->enmType)
1567 {
1568 case VBOXWDDM_ALLOC_TYPE_STD_SHAREDPRIMARYSURFACE:
1569 case VBOXWDDM_ALLOC_TYPE_UMD_RC_GENERIC:
1570 {
1571 if (pAllocation->bAssigned)
1572 {
1573 /* @todo: do we need to notify host? */
1574 vboxWddmAssignPrimary(pDevExt, &pDevExt->aSources[pAllocation->SurfDesc.VidPnSourceId], NULL, pAllocation->SurfDesc.VidPnSourceId);
1575 }
1576 break;
1577 }
1578#ifdef VBOXWDDM_RENDER_FROM_SHADOW
1579 case VBOXWDDM_ALLOC_TYPE_STD_SHADOWSURFACE:
1580 {
1581 if (pAllocation->bAssigned)
1582 {
1583 Assert(pAllocation->SurfDesc.VidPnSourceId != D3DDDI_ID_UNINITIALIZED);
1584 /* @todo: do we need to notify host? */
1585 vboxWddmAssignShadow(pDevExt, &pDevExt->aSources[pAllocation->SurfDesc.VidPnSourceId], NULL, pAllocation->SurfDesc.VidPnSourceId);
1586 }
1587 break;
1588 }
1589#endif
1590//#ifdef VBOX_WITH_VIDEOHWACCEL
1591// case VBOXWDDM_ALLOC_TYPE_UMD_RC_GENERIC:
1592// {
1593// if (pAllocation->fRcFlags.Overlay)
1594// {
1595// vboxVhwaHlpDestroyOverlay(pDevExt, pAllocation);
1596// }
1597// break;
1598// }
1599//#endif
1600 case VBOXWDDM_ALLOC_TYPE_UMD_HGSMI_BUFFER:
1601 {
1602 if (pAllocation->pSynchEvent)
1603 {
1604 ObDereferenceObject(pAllocation->pSynchEvent);
1605 }
1606 break;
1607 }
1608 default:
1609 break;
1610 }
1611
1612 PVBOXWDDM_SWAPCHAIN pSwapchain = vboxWddmSwapchainRetainByAlloc(pDevExt, pAllocation);
1613 if (pSwapchain)
1614 {
1615 vboxWddmSwapchainAllocRemove(pDevExt, pSwapchain, pAllocation);
1616 vboxWddmSwapchainRelease(pSwapchain);
1617 }
1618
1619 vboxWddmAllocationDeleteFromResource(pAllocation->pResource, pAllocation);
1620
1621 return STATUS_SUCCESS;
1622}
1623
1624NTSTATUS vboxWddmCreateAllocation(PDEVICE_EXTENSION pDevExt, PVBOXWDDM_RESOURCE pResource, uint32_t iIndex, DXGK_ALLOCATIONINFO* pAllocationInfo)
1625{
1626 PAGED_CODE();
1627
1628 NTSTATUS Status = STATUS_SUCCESS;
1629
1630 Assert(pAllocationInfo->PrivateDriverDataSize == sizeof (VBOXWDDM_ALLOCINFO));
1631 if (pAllocationInfo->PrivateDriverDataSize >= sizeof (VBOXWDDM_ALLOCINFO))
1632 {
1633 PVBOXWDDM_ALLOCINFO pAllocInfo = (PVBOXWDDM_ALLOCINFO)pAllocationInfo->pPrivateDriverData;
1634 PVBOXWDDM_ALLOCATION pAllocation = vboxWddmAllocationCreateFromResource(pResource, iIndex);
1635 Assert(pAllocation);
1636 if (pAllocation)
1637 {
1638 pAllocationInfo->pPrivateDriverData = NULL;
1639 pAllocationInfo->PrivateDriverDataSize = 0;
1640 pAllocationInfo->Alignment = 0;
1641 pAllocationInfo->PitchAlignedSize = 0;
1642 pAllocationInfo->HintedBank.Value = 0;
1643 pAllocationInfo->PreferredSegment.Value = 0;
1644 pAllocationInfo->SupportedReadSegmentSet = 1;
1645 pAllocationInfo->SupportedWriteSegmentSet = 1;
1646 pAllocationInfo->EvictionSegmentSet = 0;
1647 pAllocationInfo->MaximumRenamingListLength = 0;
1648 pAllocationInfo->hAllocation = pAllocation;
1649 pAllocationInfo->Flags.Value = 0;
1650 pAllocationInfo->pAllocationUsageHint = NULL;
1651 pAllocationInfo->AllocationPriority = D3DDDI_ALLOCATIONPRIORITY_NORMAL;
1652
1653 pAllocation->enmType = pAllocInfo->enmType;
1654 pAllocation->offVram = VBOXVIDEOOFFSET_VOID;
1655 pAllocation->bVisible = FALSE;
1656 pAllocation->bAssigned = FALSE;
1657
1658 switch (pAllocInfo->enmType)
1659 {
1660 case VBOXWDDM_ALLOC_TYPE_STD_SHAREDPRIMARYSURFACE:
1661 case VBOXWDDM_ALLOC_TYPE_UMD_RC_GENERIC:
1662 case VBOXWDDM_ALLOC_TYPE_STD_SHADOWSURFACE:
1663 case VBOXWDDM_ALLOC_TYPE_STD_STAGINGSURFACE:
1664 {
1665 pAllocation->fRcFlags = pAllocInfo->fFlags;
1666 pAllocation->SurfDesc = pAllocInfo->SurfDesc;
1667
1668 pAllocationInfo->Size = pAllocInfo->SurfDesc.cbSize;
1669
1670 switch (pAllocInfo->enmType)
1671 {
1672 case VBOXWDDM_ALLOC_TYPE_STD_SHAREDPRIMARYSURFACE:
1673#if 0 //defined(VBOXWDDM_RENDER_FROM_SHADOW)
1674 pAllocationInfo->SupportedReadSegmentSet = 2;
1675 pAllocationInfo->SupportedWriteSegmentSet = 2;
1676#endif
1677#ifndef VBOXWDDM_RENDER_FROM_SHADOW
1678 pAllocationInfo->Flags.CpuVisible = 1;
1679#endif
1680 break;
1681 case VBOXWDDM_ALLOC_TYPE_UMD_RC_GENERIC:
1682#ifdef VBOX_WITH_VIDEOHWACCEL
1683 if (pAllocInfo->fFlags.Overlay)
1684 {
1685 /* actually we can not "properly" issue create overlay commands to the host here
1686 * because we do not know source VidPn id here, i.e.
1687 * the primary which is supposed to be overlayed,
1688 * however we need to get some info like pitch & size from the host here */
1689 int rc = vboxVhwaHlpGetSurfInfo(pDevExt, pAllocation);
1690 AssertRC(rc);
1691 if (RT_SUCCESS(rc))
1692 {
1693 pAllocationInfo->Flags.Overlay = 1;
1694 pAllocationInfo->Flags.CpuVisible = 1;
1695 pAllocationInfo->Size = pAllocation->SurfDesc.cbSize;
1696
1697 pAllocationInfo->AllocationPriority = D3DDDI_ALLOCATIONPRIORITY_HIGH;
1698 }
1699 else
1700 Status = STATUS_UNSUCCESSFUL;
1701 }
1702 else
1703#endif
1704 {
1705 Assert(pAllocation->SurfDesc.bpp);
1706 Assert(pAllocation->SurfDesc.pitch);
1707 Assert(pAllocation->SurfDesc.cbSize);
1708 if (!pAllocInfo->fFlags.SharedResource)
1709 {
1710 pAllocationInfo->Flags.CpuVisible = 1;
1711 }
1712 }
1713 break;
1714 case VBOXWDDM_ALLOC_TYPE_STD_SHADOWSURFACE:
1715 case VBOXWDDM_ALLOC_TYPE_STD_STAGINGSURFACE:
1716 pAllocationInfo->Flags.CpuVisible = 1;
1717 break;
1718 }
1719
1720 if (Status == STATUS_SUCCESS)
1721 {
1722 pAllocation->UsageHint.Version = 0;
1723 pAllocation->UsageHint.v1.Flags.Value = 0;
1724 pAllocation->UsageHint.v1.Format = pAllocInfo->SurfDesc.format;
1725 pAllocation->UsageHint.v1.SwizzledFormat = 0;
1726 pAllocation->UsageHint.v1.ByteOffset = 0;
1727 pAllocation->UsageHint.v1.Width = pAllocation->SurfDesc.width;
1728 pAllocation->UsageHint.v1.Height = pAllocation->SurfDesc.height;
1729 pAllocation->UsageHint.v1.Pitch = pAllocation->SurfDesc.pitch;
1730 pAllocation->UsageHint.v1.Depth = 0;
1731 pAllocation->UsageHint.v1.SlicePitch = 0;
1732
1733 Assert(!pAllocationInfo->pAllocationUsageHint);
1734 pAllocationInfo->pAllocationUsageHint = &pAllocation->UsageHint;
1735 }
1736
1737 break;
1738 }
1739 case VBOXWDDM_ALLOC_TYPE_UMD_HGSMI_BUFFER:
1740 {
1741 pAllocationInfo->Size = pAllocInfo->cbBuffer;
1742 pAllocation->enmSynchType = pAllocInfo->enmSynchType;
1743 pAllocation->SurfDesc.cbSize = pAllocInfo->cbBuffer;
1744 pAllocationInfo->Flags.CpuVisible = 1;
1745// pAllocationInfo->Flags.SynchronousPaging = 1;
1746 pAllocationInfo->AllocationPriority = D3DDDI_ALLOCATIONPRIORITY_MAXIMUM;
1747 switch (pAllocInfo->enmSynchType)
1748 {
1749 case VBOXUHGSMI_SYNCHOBJECT_TYPE_EVENT:
1750 Status = ObReferenceObjectByHandle(pAllocInfo->hSynch, EVENT_MODIFY_STATE, *ExEventObjectType, UserMode,
1751 (PVOID*)&pAllocation->pSynchEvent,
1752 NULL);
1753 Assert(Status == STATUS_SUCCESS);
1754 break;
1755 case VBOXUHGSMI_SYNCHOBJECT_TYPE_SEMAPHORE:
1756 Status = ObReferenceObjectByHandle(pAllocInfo->hSynch, EVENT_MODIFY_STATE, *ExSemaphoreObjectType, UserMode,
1757 (PVOID*)&pAllocation->pSynchSemaphore,
1758 NULL);
1759 Assert(Status == STATUS_SUCCESS);
1760 break;
1761 case VBOXUHGSMI_SYNCHOBJECT_TYPE_NONE:
1762 pAllocation->pSynchEvent = NULL;
1763 Status = STATUS_SUCCESS;
1764 break;
1765 default:
1766 drprintf((__FUNCTION__ ": ERROR: invalid synch info type(%d)\n", pAllocInfo->enmSynchType));
1767 AssertBreakpoint();
1768 Status = STATUS_INVALID_PARAMETER;
1769 break;
1770 }
1771 break;
1772 }
1773
1774 default:
1775 drprintf((__FUNCTION__ ": ERROR: invalid alloc info type(%d)\n", pAllocInfo->enmType));
1776 AssertBreakpoint();
1777 Status = STATUS_INVALID_PARAMETER;
1778 break;
1779
1780 }
1781
1782 if (Status != STATUS_SUCCESS)
1783 vboxWddmAllocationDeleteFromResource(pResource, pAllocation);
1784 }
1785 else
1786 {
1787 drprintf((__FUNCTION__ ": ERROR: failed to create allocation description\n"));
1788 Status = STATUS_NO_MEMORY;
1789 }
1790
1791 }
1792 else
1793 {
1794 drprintf((__FUNCTION__ ": ERROR: PrivateDriverDataSize(%d) less than header size(%d)\n", pAllocationInfo->PrivateDriverDataSize, sizeof (VBOXWDDM_ALLOCINFO)));
1795 Status = STATUS_INVALID_PARAMETER;
1796 }
1797
1798 return Status;
1799}
1800
1801NTSTATUS APIENTRY DxgkDdiCreateAllocation(
1802 CONST HANDLE hAdapter,
1803 DXGKARG_CREATEALLOCATION* pCreateAllocation)
1804{
1805 /* DxgkDdiCreateAllocation should be made pageable. */
1806 PAGED_CODE();
1807
1808 dfprintf(("==> "__FUNCTION__ ", context(0x%x)\n", hAdapter));
1809
1810 vboxVDbgBreakFv();
1811
1812 PDEVICE_EXTENSION pDevExt = (PDEVICE_EXTENSION)hAdapter;
1813 NTSTATUS Status = STATUS_SUCCESS;
1814 PVBOXWDDM_RESOURCE pResource = NULL;
1815
1816 if (pCreateAllocation->PrivateDriverDataSize)
1817 {
1818 Assert(pCreateAllocation->PrivateDriverDataSize == sizeof (VBOXWDDM_RCINFO));
1819 Assert(pCreateAllocation->pPrivateDriverData);
1820 if (pCreateAllocation->PrivateDriverDataSize >= sizeof (VBOXWDDM_RCINFO))
1821 {
1822 PVBOXWDDM_RCINFO pRcInfo = (PVBOXWDDM_RCINFO)pCreateAllocation->pPrivateDriverData;
1823// Assert(pRcInfo->RcDesc.VidPnSourceId < commonFromDeviceExt(pDevExt)->cDisplays);
1824 Assert(pRcInfo->cAllocInfos == pCreateAllocation->NumAllocations);
1825 pResource = (PVBOXWDDM_RESOURCE)vboxWddmMemAllocZero(RT_OFFSETOF(VBOXWDDM_RESOURCE, aAllocations[pRcInfo->cAllocInfos]));
1826 Assert(pResource);
1827 if (pResource)
1828 {
1829 pResource->cAllocations = pRcInfo->cAllocInfos;
1830 pResource->fFlags = pRcInfo->fFlags;
1831 pResource->RcDesc = pRcInfo->RcDesc;
1832 }
1833 else
1834 Status = STATUS_NO_MEMORY;
1835 }
1836 else
1837 Status = STATUS_INVALID_PARAMETER;
1838 /* @todo: Implement Resource Data Handling */
1839 drprintf((__FUNCTION__ ": WARNING: Implement Resource Data Handling\n"));
1840 }
1841
1842 if (Status == STATUS_SUCCESS)
1843 {
1844 for (UINT i = 0; i < pCreateAllocation->NumAllocations; ++i)
1845 {
1846 Status = vboxWddmCreateAllocation(pDevExt, pResource, i, &pCreateAllocation->pAllocationInfo[i]);
1847 Assert(Status == STATUS_SUCCESS);
1848 if (Status != STATUS_SUCCESS)
1849 {
1850 drprintf((__FUNCTION__ ": ERROR: vboxWddmCreateAllocation error (0x%x)\n", Status));
1851 /* note: i-th allocation is expected to be cleared in a fail handling code above */
1852 for (UINT j = 0; j < i; ++j)
1853 {
1854 vboxWddmDestroyAllocation(pDevExt, (PVBOXWDDM_ALLOCATION)pCreateAllocation->pAllocationInfo[j].hAllocation);
1855 }
1856 }
1857 }
1858
1859 pCreateAllocation->hResource = pResource;
1860 if (pResource && Status != STATUS_SUCCESS)
1861 vboxWddmMemFree(pResource);
1862 }
1863 dfprintf(("<== "__FUNCTION__ ", status(0x%x), context(0x%x)\n", Status, hAdapter));
1864
1865 return Status;
1866}
1867
1868NTSTATUS
1869APIENTRY
1870DxgkDdiDestroyAllocation(
1871 CONST HANDLE hAdapter,
1872 CONST DXGKARG_DESTROYALLOCATION* pDestroyAllocation)
1873{
1874 /* DxgkDdiDestroyAllocation should be made pageable. */
1875 PAGED_CODE();
1876
1877 dfprintf(("==> "__FUNCTION__ ", context(0x%x)\n", hAdapter));
1878
1879 vboxVDbgBreakFv();
1880
1881 NTSTATUS Status = STATUS_SUCCESS;
1882
1883 PVBOXWDDM_RESOURCE pRc = (PVBOXWDDM_RESOURCE)pDestroyAllocation->hResource;
1884
1885 if (pRc)
1886 {
1887 Assert(pRc->cAllocations == pDestroyAllocation->NumAllocations);
1888 }
1889
1890 for (UINT i = 0; i < pDestroyAllocation->NumAllocations; ++i)
1891 {
1892 PVBOXWDDM_ALLOCATION pAlloc = (PVBOXWDDM_ALLOCATION)pDestroyAllocation->pAllocationList[i];
1893 Assert(pAlloc->pResource == pRc);
1894 vboxWddmDestroyAllocation((PDEVICE_EXTENSION)hAdapter, pAlloc);
1895 }
1896
1897 if (pRc)
1898 {
1899 vboxWddmMemFree(pRc);
1900 }
1901
1902 dfprintf(("<== "__FUNCTION__ ", status(0x%x), context(0x%x)\n", Status, hAdapter));
1903
1904 return Status;
1905}
1906
1907/**
1908 * DxgkDdiDescribeAllocation
1909 */
1910NTSTATUS
1911APIENTRY
1912DxgkDdiDescribeAllocation(
1913 CONST HANDLE hAdapter,
1914 DXGKARG_DESCRIBEALLOCATION* pDescribeAllocation)
1915{
1916// dfprintf(("==> "__FUNCTION__ ", hAdapter(0x%x)\n", hAdapter));
1917
1918 vboxVDbgBreakFv();
1919
1920 PVBOXWDDM_ALLOCATION pAllocation = (PVBOXWDDM_ALLOCATION)pDescribeAllocation->hAllocation;
1921 pDescribeAllocation->Width = pAllocation->SurfDesc.width;
1922 pDescribeAllocation->Height = pAllocation->SurfDesc.height;
1923 pDescribeAllocation->Format = pAllocation->SurfDesc.format;
1924 memset (&pDescribeAllocation->MultisampleMethod, 0, sizeof (pDescribeAllocation->MultisampleMethod));
1925 pDescribeAllocation->RefreshRate.Numerator = 60000;
1926 pDescribeAllocation->RefreshRate.Denominator = 1000;
1927 pDescribeAllocation->PrivateDriverFormatAttribute = 0;
1928
1929// dfprintf(("<== "__FUNCTION__ ", hAdapter(0x%x)\n", hAdapter));
1930
1931 return STATUS_SUCCESS;
1932}
1933
1934/**
1935 * DxgkDdiGetStandardAllocationDriverData
1936 */
1937NTSTATUS
1938APIENTRY
1939DxgkDdiGetStandardAllocationDriverData(
1940 CONST HANDLE hAdapter,
1941 DXGKARG_GETSTANDARDALLOCATIONDRIVERDATA* pGetStandardAllocationDriverData)
1942{
1943 /* DxgkDdiGetStandardAllocationDriverData should be made pageable. */
1944 PAGED_CODE();
1945
1946 dfprintf(("==> "__FUNCTION__ ", context(0x%x)\n", hAdapter));
1947
1948 vboxVDbgBreakFv();
1949
1950 NTSTATUS Status = STATUS_SUCCESS;
1951 PVBOXWDDM_ALLOCINFO pAllocInfo = NULL;
1952
1953 switch (pGetStandardAllocationDriverData->StandardAllocationType)
1954 {
1955 case D3DKMDT_STANDARDALLOCATION_SHAREDPRIMARYSURFACE:
1956 {
1957 dfprintf((__FUNCTION__ ": D3DKMDT_STANDARDALLOCATION_SHAREDPRIMARYSURFACE\n"));
1958 if(pGetStandardAllocationDriverData->pAllocationPrivateDriverData)
1959 {
1960 pAllocInfo = (PVBOXWDDM_ALLOCINFO)pGetStandardAllocationDriverData->pAllocationPrivateDriverData;
1961 memset (pAllocInfo, 0, sizeof (VBOXWDDM_ALLOCINFO));
1962 pAllocInfo->enmType = VBOXWDDM_ALLOC_TYPE_STD_SHAREDPRIMARYSURFACE;
1963 pAllocInfo->SurfDesc.width = pGetStandardAllocationDriverData->pCreateSharedPrimarySurfaceData->Width;
1964 pAllocInfo->SurfDesc.height = pGetStandardAllocationDriverData->pCreateSharedPrimarySurfaceData->Height;
1965 pAllocInfo->SurfDesc.format = pGetStandardAllocationDriverData->pCreateSharedPrimarySurfaceData->Format;
1966 pAllocInfo->SurfDesc.bpp = vboxWddmCalcBitsPerPixel(pAllocInfo->SurfDesc.format);
1967 pAllocInfo->SurfDesc.pitch = vboxWddmCalcPitch(pGetStandardAllocationDriverData->pCreateSharedPrimarySurfaceData->Width, pAllocInfo->SurfDesc.bpp);
1968 pAllocInfo->SurfDesc.cbSize = pAllocInfo->SurfDesc.pitch * pAllocInfo->SurfDesc.height;
1969 pAllocInfo->SurfDesc.depth = 0;
1970 pAllocInfo->SurfDesc.slicePitch = 0;
1971 pAllocInfo->SurfDesc.RefreshRate = pGetStandardAllocationDriverData->pCreateSharedPrimarySurfaceData->RefreshRate;
1972 pAllocInfo->SurfDesc.VidPnSourceId = pGetStandardAllocationDriverData->pCreateSharedPrimarySurfaceData->VidPnSourceId;
1973 }
1974 pGetStandardAllocationDriverData->AllocationPrivateDriverDataSize = sizeof (VBOXWDDM_ALLOCINFO);
1975
1976 pGetStandardAllocationDriverData->ResourcePrivateDriverDataSize = 0;
1977 break;
1978 }
1979 case D3DKMDT_STANDARDALLOCATION_SHADOWSURFACE:
1980 {
1981 dfprintf((__FUNCTION__ ": D3DKMDT_STANDARDALLOCATION_SHADOWSURFACE\n"));
1982 UINT bpp = vboxWddmCalcBitsPerPixel(pGetStandardAllocationDriverData->pCreateShadowSurfaceData->Format);
1983 Assert(bpp);
1984 if (bpp != 0)
1985 {
1986 UINT Pitch = vboxWddmCalcPitch(pGetStandardAllocationDriverData->pCreateShadowSurfaceData->Width, bpp);
1987 pGetStandardAllocationDriverData->pCreateShadowSurfaceData->Pitch = Pitch;
1988
1989 /* @todo: need [d/q]word align?? */
1990
1991 if (pGetStandardAllocationDriverData->pAllocationPrivateDriverData)
1992 {
1993 pAllocInfo = (PVBOXWDDM_ALLOCINFO)pGetStandardAllocationDriverData->pAllocationPrivateDriverData;
1994 pAllocInfo->enmType = VBOXWDDM_ALLOC_TYPE_STD_SHADOWSURFACE;
1995 pAllocInfo->SurfDesc.width = pGetStandardAllocationDriverData->pCreateShadowSurfaceData->Width;
1996 pAllocInfo->SurfDesc.height = pGetStandardAllocationDriverData->pCreateShadowSurfaceData->Height;
1997 pAllocInfo->SurfDesc.format = pGetStandardAllocationDriverData->pCreateShadowSurfaceData->Format;
1998 pAllocInfo->SurfDesc.bpp = vboxWddmCalcBitsPerPixel(pAllocInfo->SurfDesc.format);
1999 pAllocInfo->SurfDesc.pitch = vboxWddmCalcPitch(pGetStandardAllocationDriverData->pCreateShadowSurfaceData->Width, pAllocInfo->SurfDesc.bpp);
2000 pAllocInfo->SurfDesc.cbSize = pAllocInfo->SurfDesc.pitch * pAllocInfo->SurfDesc.height;
2001 pAllocInfo->SurfDesc.depth = 0;
2002 pAllocInfo->SurfDesc.slicePitch = 0;
2003 pAllocInfo->SurfDesc.RefreshRate.Numerator = 0;
2004 pAllocInfo->SurfDesc.RefreshRate.Denominator = 1000;
2005 pAllocInfo->SurfDesc.VidPnSourceId = D3DDDI_ID_UNINITIALIZED;
2006
2007 pGetStandardAllocationDriverData->pCreateShadowSurfaceData->Pitch = pAllocInfo->SurfDesc.pitch;
2008 }
2009 pGetStandardAllocationDriverData->AllocationPrivateDriverDataSize = sizeof (VBOXWDDM_ALLOCINFO);
2010
2011 pGetStandardAllocationDriverData->ResourcePrivateDriverDataSize = 0;
2012 }
2013 else
2014 {
2015 drprintf((__FUNCTION__ ": Invalid format (%d)\n", pGetStandardAllocationDriverData->pCreateShadowSurfaceData->Format));
2016 Status = STATUS_INVALID_PARAMETER;
2017 }
2018 break;
2019 }
2020 case D3DKMDT_STANDARDALLOCATION_STAGINGSURFACE:
2021 {
2022 dfprintf((__FUNCTION__ ": D3DKMDT_STANDARDALLOCATION_STAGINGSURFACE\n"));
2023 if(pGetStandardAllocationDriverData->pAllocationPrivateDriverData)
2024 {
2025 pAllocInfo = (PVBOXWDDM_ALLOCINFO)pGetStandardAllocationDriverData->pAllocationPrivateDriverData;
2026 pAllocInfo->enmType = VBOXWDDM_ALLOC_TYPE_STD_STAGINGSURFACE;
2027 pAllocInfo->SurfDesc.width = pGetStandardAllocationDriverData->pCreateStagingSurfaceData->Width;
2028 pAllocInfo->SurfDesc.height = pGetStandardAllocationDriverData->pCreateStagingSurfaceData->Height;
2029 pAllocInfo->SurfDesc.format = D3DDDIFMT_X8R8G8B8; /* staging has always always D3DDDIFMT_X8R8G8B8 */
2030 pAllocInfo->SurfDesc.bpp = vboxWddmCalcBitsPerPixel(pAllocInfo->SurfDesc.format);
2031 pAllocInfo->SurfDesc.pitch = vboxWddmCalcPitch(pGetStandardAllocationDriverData->pCreateStagingSurfaceData->Width, pAllocInfo->SurfDesc.bpp);
2032 pAllocInfo->SurfDesc.cbSize = pAllocInfo->SurfDesc.pitch * pAllocInfo->SurfDesc.height;
2033 pAllocInfo->SurfDesc.depth = 0;
2034 pAllocInfo->SurfDesc.slicePitch = 0;
2035 pAllocInfo->SurfDesc.RefreshRate.Numerator = 0;
2036 pAllocInfo->SurfDesc.RefreshRate.Denominator = 1000;
2037 pAllocInfo->SurfDesc.VidPnSourceId = D3DDDI_ID_UNINITIALIZED;
2038
2039 pGetStandardAllocationDriverData->pCreateStagingSurfaceData->Pitch = pAllocInfo->SurfDesc.pitch;
2040 }
2041 pGetStandardAllocationDriverData->AllocationPrivateDriverDataSize = sizeof (VBOXWDDM_ALLOCINFO);
2042
2043 pGetStandardAllocationDriverData->ResourcePrivateDriverDataSize = 0;
2044 break;
2045 }
2046//#if (DXGKDDI_INTERFACE_VERSION >= DXGKDDI_INTERFACE_VERSION_WIN7)
2047// case D3DKMDT_STANDARDALLOCATION_GDISURFACE:
2048//# error port to Win7 DDI
2049// break;
2050//#endif
2051 default:
2052 drprintf((__FUNCTION__ ": Invalid allocation type (%d)\n", pGetStandardAllocationDriverData->StandardAllocationType));
2053 Status = STATUS_INVALID_PARAMETER;
2054 break;
2055 }
2056
2057 dfprintf(("<== "__FUNCTION__ ", status(0x%x), context(0x%x)\n", Status, hAdapter));
2058
2059 return Status;
2060}
2061
2062NTSTATUS
2063APIENTRY
2064DxgkDdiAcquireSwizzlingRange(
2065 CONST HANDLE hAdapter,
2066 DXGKARG_ACQUIRESWIZZLINGRANGE* pAcquireSwizzlingRange)
2067{
2068 dfprintf(("==> "__FUNCTION__ ", hAdapter(0x%x)\n", hAdapter));
2069
2070 AssertBreakpoint();
2071
2072 dfprintf(("<== "__FUNCTION__ ", hAdapter(0x%x)\n", hAdapter));
2073
2074 return STATUS_SUCCESS;
2075}
2076
2077NTSTATUS
2078APIENTRY
2079DxgkDdiReleaseSwizzlingRange(
2080 CONST HANDLE hAdapter,
2081 CONST DXGKARG_RELEASESWIZZLINGRANGE* pReleaseSwizzlingRange)
2082{
2083 dfprintf(("==> "__FUNCTION__ ", hAdapter(0x%x)\n", hAdapter));
2084
2085 AssertBreakpoint();
2086
2087 dfprintf(("<== "__FUNCTION__ ", hAdapter(0x%x)\n", hAdapter));
2088
2089 return STATUS_SUCCESS;
2090}
2091
2092NTSTATUS
2093APIENTRY
2094DxgkDdiPatch(
2095 CONST HANDLE hAdapter,
2096 CONST DXGKARG_PATCH* pPatch)
2097{
2098 /* DxgkDdiPatch should be made pageable. */
2099 PAGED_CODE();
2100
2101 NTSTATUS Status = STATUS_SUCCESS;
2102
2103 dfprintf(("==> "__FUNCTION__ ", context(0x%x)\n", hAdapter));
2104
2105 vboxVDbgBreakFv();
2106
2107 /* Value == 2 is Present
2108 * Value == 4 is RedirectedPresent
2109 * we do not expect any other flags to be set here */
2110// Assert(pPatch->Flags.Value == 2 || pPatch->Flags.Value == 4);
2111 Assert(pPatch->DmaBufferPrivateDataSize >= sizeof (VBOXWDDM_DMA_PRIVATEDATA_BASEHDR));
2112 Assert(pPatch->DmaBufferPrivateDataSubmissionEndOffset - pPatch->DmaBufferPrivateDataSubmissionStartOffset >= sizeof (VBOXWDDM_DMA_PRIVATEDATA_BASEHDR));
2113 if (pPatch->DmaBufferPrivateDataSubmissionEndOffset - pPatch->DmaBufferPrivateDataSubmissionStartOffset >= sizeof (VBOXWDDM_DMA_PRIVATEDATA_BASEHDR))
2114 {
2115 VBOXWDDM_DMA_PRIVATEDATA_BASEHDR *pPrivateDataBase = (VBOXWDDM_DMA_PRIVATEDATA_BASEHDR*)((uint8_t*)pPatch->pDmaBufferPrivateData + pPatch->DmaBufferPrivateDataSubmissionStartOffset);
2116 switch (pPrivateDataBase->enmCmd)
2117 {
2118 case VBOXVDMACMD_TYPE_DMA_PRESENT_SHADOW2PRIMARY:
2119 {
2120 PVBOXWDDM_DMA_PRIVATEDATA_SHADOW2PRIMARY pS2P = (PVBOXWDDM_DMA_PRIVATEDATA_SHADOW2PRIMARY)pPrivateDataBase;
2121 Assert(pPatch->PatchLocationListSubmissionLength == 2);
2122 const D3DDDI_PATCHLOCATIONLIST* pPatchList = &pPatch->pPatchLocationList[pPatch->PatchLocationListSubmissionStart];
2123 Assert(pPatchList->AllocationIndex == DXGK_PRESENT_SOURCE_INDEX);
2124 Assert(pPatchList->PatchOffset == 0);
2125 const DXGK_ALLOCATIONLIST *pSrcAllocationList = &pPatch->pAllocationList[pPatchList->AllocationIndex];
2126 Assert(pSrcAllocationList->SegmentId);
2127 pS2P->Shadow2Primary.ShadowAlloc.segmentIdAlloc = pSrcAllocationList->SegmentId;
2128 pS2P->Shadow2Primary.ShadowAlloc.offAlloc = (VBOXVIDEOOFFSET)pSrcAllocationList->PhysicalAddress.QuadPart;
2129//
2130// pPatchList = &pPatch->pPatchLocationList[pPatch->PatchLocationListSubmissionStart + 1];
2131// Assert(pPatchList->AllocationIndex == DXGK_PRESENT_DESTINATION_INDEX);
2132// Assert(pPatchList->PatchOffset == 4);
2133// const DXGK_ALLOCATIONLIST *pDstAllocationList = &pPatch->pAllocationList[pPatchList->AllocationIndex];
2134// Assert(pDstAllocationList->SegmentId);
2135// pPrivateData->DstAllocInfo.segmentIdAlloc = pDstAllocationList->SegmentId;
2136// pPrivateData->DstAllocInfo.offAlloc = (VBOXVIDEOOFFSET)pDstAllocationList->PhysicalAddress.QuadPart;
2137 break;
2138 }
2139 case VBOXVDMACMD_TYPE_DMA_PRESENT_BLT:
2140 {
2141 PVBOXWDDM_DMA_PRIVATEDATA_BLT pBlt = (PVBOXWDDM_DMA_PRIVATEDATA_BLT)pPrivateDataBase;
2142 Assert(pPatch->PatchLocationListSubmissionLength == 2);
2143 const D3DDDI_PATCHLOCATIONLIST* pPatchList = &pPatch->pPatchLocationList[pPatch->PatchLocationListSubmissionStart];
2144 Assert(pPatchList->AllocationIndex == DXGK_PRESENT_SOURCE_INDEX);
2145 Assert(pPatchList->PatchOffset == 0);
2146 const DXGK_ALLOCATIONLIST *pSrcAllocationList = &pPatch->pAllocationList[pPatchList->AllocationIndex];
2147 Assert(pSrcAllocationList->SegmentId);
2148 pBlt->Blt.SrcAlloc.segmentIdAlloc = pSrcAllocationList->SegmentId;
2149 pBlt->Blt.SrcAlloc.offAlloc = (VBOXVIDEOOFFSET)pSrcAllocationList->PhysicalAddress.QuadPart;
2150
2151 pPatchList = &pPatch->pPatchLocationList[pPatch->PatchLocationListSubmissionStart + 1];
2152 Assert(pPatchList->AllocationIndex == DXGK_PRESENT_DESTINATION_INDEX);
2153 Assert(pPatchList->PatchOffset == 4);
2154 const DXGK_ALLOCATIONLIST *pDstAllocationList = &pPatch->pAllocationList[pPatchList->AllocationIndex];
2155 Assert(pDstAllocationList->SegmentId);
2156 pBlt->Blt.DstAlloc.segmentIdAlloc = pDstAllocationList->SegmentId;
2157 pBlt->Blt.DstAlloc.offAlloc = (VBOXVIDEOOFFSET)pDstAllocationList->PhysicalAddress.QuadPart;
2158 break;
2159 }
2160 case VBOXVDMACMD_TYPE_DMA_PRESENT_FLIP:
2161 {
2162 PVBOXWDDM_DMA_PRIVATEDATA_FLIP pFlip = (PVBOXWDDM_DMA_PRIVATEDATA_FLIP)pPrivateDataBase;
2163 Assert(pPatch->PatchLocationListSubmissionLength == 1);
2164 const D3DDDI_PATCHLOCATIONLIST* pPatchList = &pPatch->pPatchLocationList[pPatch->PatchLocationListSubmissionStart];
2165 Assert(pPatchList->AllocationIndex == DXGK_PRESENT_SOURCE_INDEX);
2166 Assert(pPatchList->PatchOffset == 0);
2167 const DXGK_ALLOCATIONLIST *pSrcAllocationList = &pPatch->pAllocationList[pPatchList->AllocationIndex];
2168 Assert(pSrcAllocationList->SegmentId);
2169 pFlip->Flip.Alloc.segmentIdAlloc = pSrcAllocationList->SegmentId;
2170 pFlip->Flip.Alloc.offAlloc = (VBOXVIDEOOFFSET)pSrcAllocationList->PhysicalAddress.QuadPart;
2171 break;
2172 }
2173 case VBOXVDMACMD_TYPE_DMA_PRESENT_CLRFILL:
2174 {
2175 PVBOXWDDM_DMA_PRIVATEDATA_CLRFILL pCF = (PVBOXWDDM_DMA_PRIVATEDATA_CLRFILL)pPrivateDataBase;
2176 Assert(pPatch->PatchLocationListSubmissionLength == 1);
2177 const D3DDDI_PATCHLOCATIONLIST* pPatchList = &pPatch->pPatchLocationList[pPatch->PatchLocationListSubmissionStart];
2178 Assert(pPatchList->AllocationIndex == DXGK_PRESENT_DESTINATION_INDEX);
2179 Assert(pPatchList->PatchOffset == 0);
2180 const DXGK_ALLOCATIONLIST *pDstAllocationList = &pPatch->pAllocationList[pPatchList->AllocationIndex];
2181 Assert(pDstAllocationList->SegmentId);
2182 pCF->ClrFill.Alloc.segmentIdAlloc = pDstAllocationList->SegmentId;
2183 pCF->ClrFill.Alloc.offAlloc = (VBOXVIDEOOFFSET)pDstAllocationList->PhysicalAddress.QuadPart;
2184 break;
2185 }
2186 case VBOXVDMACMD_TYPE_DMA_NOP:
2187 break;
2188 case VBOXVDMACMD_TYPE_CHROMIUM_CMD:
2189 {
2190 uint8_t * pPrivateBuf = (uint8_t*)pPrivateDataBase;
2191 for (UINT i = pPatch->PatchLocationListSubmissionStart; i < pPatch->PatchLocationListSubmissionLength; ++i)
2192 {
2193 const D3DDDI_PATCHLOCATIONLIST* pPatchList = &pPatch->pPatchLocationList[i];
2194 Assert(pPatchList->AllocationIndex < pPatch->AllocationListSize);
2195 const DXGK_ALLOCATIONLIST *pAllocationList = &pPatch->pAllocationList[pPatchList->AllocationIndex];
2196 Assert(pAllocationList->SegmentId);
2197 if (pAllocationList->SegmentId)
2198 {
2199 DXGK_ALLOCATIONLIST *pAllocation2Patch = (DXGK_ALLOCATIONLIST*)(pPrivateBuf + pPatchList->PatchOffset);
2200 pAllocation2Patch->SegmentId = pAllocationList->SegmentId;
2201 pAllocation2Patch->PhysicalAddress.QuadPart = pAllocationList->PhysicalAddress.QuadPart + pPatchList->AllocationOffset;
2202 Assert(!(pAllocationList->PhysicalAddress.QuadPart & 0xfffUL)); /* <- just a check to ensure allocation offset does not go here */
2203 }
2204 }
2205 break;
2206 }
2207 default:
2208 {
2209 AssertBreakpoint();
2210 uint8_t *pBuf = ((uint8_t *)pPatch->pDmaBuffer) + pPatch->DmaBufferSubmissionStartOffset;
2211 for (UINT i = pPatch->PatchLocationListSubmissionStart; i < pPatch->PatchLocationListSubmissionLength; ++i)
2212 {
2213 const D3DDDI_PATCHLOCATIONLIST* pPatchList = &pPatch->pPatchLocationList[i];
2214 Assert(pPatchList->AllocationIndex < pPatch->AllocationListSize);
2215 const DXGK_ALLOCATIONLIST *pAllocationList = &pPatch->pAllocationList[pPatchList->AllocationIndex];
2216 if (pAllocationList->SegmentId)
2217 {
2218 Assert(pPatchList->PatchOffset < (pPatch->DmaBufferSubmissionEndOffset - pPatch->DmaBufferSubmissionStartOffset));
2219 *((VBOXVIDEOOFFSET*)(pBuf+pPatchList->PatchOffset)) = (VBOXVIDEOOFFSET)pAllocationList->PhysicalAddress.QuadPart;
2220 }
2221 else
2222 {
2223 /* sanity */
2224 if (pPatch->Flags.Value == 2 || pPatch->Flags.Value == 4)
2225 Assert(i == 0);
2226 }
2227 }
2228 break;
2229 }
2230 }
2231 }
2232 else
2233 {
2234 drprintf((__FUNCTION__": DmaBufferPrivateDataSubmissionEndOffset (%d) - DmaBufferPrivateDataSubmissionStartOffset (%d) < sizeof (VBOXWDDM_DMA_PRIVATEDATA_BASEHDR) (%d)\n",
2235 pPatch->DmaBufferPrivateDataSubmissionEndOffset,
2236 pPatch->DmaBufferPrivateDataSubmissionStartOffset,
2237 sizeof (VBOXWDDM_DMA_PRIVATEDATA_BASEHDR)));
2238 return STATUS_INVALID_PARAMETER;
2239 }
2240
2241 dfprintf(("<== "__FUNCTION__ ", context(0x%x)\n", hAdapter));
2242
2243 return Status;
2244}
2245
2246typedef struct VBOXWDDM_CALL_ISR
2247{
2248 PDEVICE_EXTENSION pDevExt;
2249 ULONG MessageNumber;
2250} VBOXWDDM_CALL_ISR, *PVBOXWDDM_CALL_ISR;
2251
2252static BOOLEAN vboxWddmCallIsrCb(PVOID Context)
2253{
2254 PVBOXWDDM_CALL_ISR pdc = (PVBOXWDDM_CALL_ISR)Context;
2255 return DxgkDdiInterruptRoutine(pdc->pDevExt, pdc->MessageNumber);
2256}
2257
2258NTSTATUS vboxWddmCallIsr(PDEVICE_EXTENSION pDevExt)
2259{
2260 VBOXWDDM_CALL_ISR context;
2261 context.pDevExt = pDevExt;
2262 context.MessageNumber = 0;
2263 BOOLEAN bRet;
2264 NTSTATUS Status = pDevExt->u.primary.DxgkInterface.DxgkCbSynchronizeExecution(
2265 pDevExt->u.primary.DxgkInterface.DeviceHandle,
2266 vboxWddmCallIsrCb,
2267 &context,
2268 0, /* IN ULONG MessageNumber */
2269 &bRet);
2270 Assert(Status == STATUS_SUCCESS);
2271 return Status;
2272}
2273
2274static NTSTATUS vboxWddmSubmitCmd(PDEVICE_EXTENSION pDevExt, VBOXVDMAPIPE_CMD_DMACMD *pCmd)
2275{
2276 NTSTATUS Status = vboxVdmaDdiCmdSubmitted(pDevExt, &pDevExt->DdiCmdQueue, &pCmd->DdiCmd);
2277 Assert(Status == STATUS_SUCCESS);
2278 if (Status == STATUS_SUCCESS)
2279 {
2280 if (pCmd->fFlags.bDecVBVAUnlock)
2281 {
2282 uint32_t cNew = ASMAtomicIncU32(&pDevExt->cUnlockedVBVADisabled);
2283 Assert(cNew < UINT32_MAX/2);
2284 }
2285 NTSTATUS submStatus = vboxVdmaGgCmdSubmit(&pDevExt->u.primary.Vdma.DmaGg, &pCmd->Hdr);
2286 Assert(submStatus == STATUS_SUCCESS);
2287 if (submStatus != STATUS_SUCCESS)
2288 {
2289 if (pCmd->fFlags.bDecVBVAUnlock)
2290 {
2291 uint32_t cNew = ASMAtomicDecU32(&pDevExt->cUnlockedVBVADisabled);
2292 Assert(cNew < UINT32_MAX/2);
2293 }
2294 vboxVdmaDdiCmdCompleted(pDevExt, &pDevExt->DdiCmdQueue, &pCmd->DdiCmd, DXGK_INTERRUPT_DMA_FAULTED);
2295 }
2296 }
2297 else
2298 {
2299 vboxVdmaGgCmdDestroy(&pCmd->Hdr);
2300 }
2301 return Status;
2302}
2303
2304static NTSTATUS vboxWddmSubmitBltCmd(PDEVICE_EXTENSION pDevExt, VBOXWDDM_CONTEXT *pContext, UINT u32FenceId, PVBOXWDDM_DMA_PRIVATEDATA_BLT pBlt, VBOXVDMAPIPE_FLAGS_DMACMD fBltFlags)
2305{
2306 NTSTATUS Status = STATUS_SUCCESS;
2307
2308 PVBOXVDMAPIPE_CMD_DMACMD_BLT pBltCmd = (PVBOXVDMAPIPE_CMD_DMACMD_BLT)vboxVdmaGgCmdCreate(&pDevExt->u.primary.Vdma.DmaGg, VBOXVDMAPIPE_CMD_TYPE_DMACMD, RT_OFFSETOF(VBOXVDMAPIPE_CMD_DMACMD_BLT, Blt.DstRects.UpdateRects.aRects[pBlt->Blt.DstRects.UpdateRects.cRects]));
2309 Assert(pBltCmd);
2310 if (pBltCmd)
2311 {
2312 VBOXWDDM_SOURCE *pSource = &pDevExt->aSources[pBlt->Blt.DstAlloc.srcId];
2313 vboxVdmaDdiCmdInit(&pBltCmd->Hdr.DdiCmd, u32FenceId, pContext, vboxVdmaGgDdiCmdDestroy, pBltCmd);
2314 pBltCmd->Hdr.pDevExt = pDevExt;
2315 pBltCmd->Hdr.fFlags = fBltFlags;
2316 pBltCmd->Hdr.enmCmd = VBOXVDMACMD_TYPE_DMA_PRESENT_BLT;
2317 memcpy(&pBltCmd->Blt, &pBlt->Blt, RT_OFFSETOF(VBOXVDMA_BLT, DstRects.UpdateRects.aRects[pBlt->Blt.DstRects.UpdateRects.cRects]));
2318 vboxWddmSubmitCmd(pDevExt, &pBltCmd->Hdr);
2319 }
2320 else
2321 {
2322 Status = vboxVdmaDdiCmdFenceComplete(pDevExt, pContext, u32FenceId, DXGK_INTERRUPT_DMA_FAULTED);
2323 }
2324
2325 return Status;
2326}
2327
2328#ifdef VBOX_WITH_VDMA
2329DECLCALLBACK(VOID) vboxWddmDmaCompleteChromiumCmd(PDEVICE_EXTENSION pDevExt, PVBOXVDMADDI_CMD pCmd, PVOID pvContext)
2330{
2331 PVBOXVDMACBUF_DR pDr = (PVBOXVDMACBUF_DR)pvContext;
2332 PVBOXVDMACMD pHdr = VBOXVDMACBUF_DR_TAIL(pDr, VBOXVDMACMD);
2333 VBOXVDMACMD_CHROMIUM_CMD *pBody = VBOXVDMACMD_BODY(pHdr, VBOXVDMACMD_CHROMIUM_CMD);
2334 UINT cBufs = pBody->cBuffers;
2335 for (UINT i = 0; i < cBufs; ++i)
2336 {
2337 VBOXVDMACMD_CHROMIUM_BUFFER *pBufCmd = &pBody->aBuffers[i];
2338 if (!pBufCmd->u32GuesData)
2339 {
2340 /* signal completion */
2341 PVBOXWDDM_ALLOCATION pAlloc = (PVBOXWDDM_ALLOCATION)pBufCmd->u64GuesData;
2342 switch (pAlloc->enmSynchType)
2343 {
2344 case VBOXUHGSMI_SYNCHOBJECT_TYPE_EVENT:
2345 KeSetEvent(pAlloc->pSynchEvent, 3, FALSE);
2346 break;
2347 case VBOXUHGSMI_SYNCHOBJECT_TYPE_SEMAPHORE:
2348 KeReleaseSemaphore(pAlloc->pSynchSemaphore,
2349 3,
2350 1,
2351 FALSE);
2352 break;
2353 case VBOXUHGSMI_SYNCHOBJECT_TYPE_NONE:
2354 break;
2355 default:
2356 Assert(0);
2357 }
2358 }
2359 }
2360
2361 vboxVdmaCBufDrFree(&pDevExt->u.primary.Vdma, pDr);
2362}
2363#endif
2364
2365NTSTATUS
2366APIENTRY
2367DxgkDdiSubmitCommand(
2368 CONST HANDLE hAdapter,
2369 CONST DXGKARG_SUBMITCOMMAND* pSubmitCommand)
2370{
2371 /* DxgkDdiSubmitCommand runs at dispatch, should not be pageable. */
2372 NTSTATUS Status = STATUS_SUCCESS;
2373
2374// dfprintf(("==> "__FUNCTION__ ", context(0x%x)\n", hAdapter));
2375
2376 vboxVDbgBreakFv();
2377
2378 PDEVICE_EXTENSION pDevExt = (PDEVICE_EXTENSION)hAdapter;
2379 PVBOXWDDM_CONTEXT pContext = (PVBOXWDDM_CONTEXT)pSubmitCommand->hContext;
2380 Assert(pContext);
2381 Assert(pContext->pDevice);
2382 Assert(pContext->pDevice->pAdapter == pDevExt);
2383 Assert(!pSubmitCommand->DmaBufferSegmentId);
2384
2385 /* the DMA command buffer is located in system RAM, the host will need to pick it from there */
2386 //BufInfo.fFlags = 0; /* see VBOXVDMACBUF_FLAG_xx */
2387 Assert(pSubmitCommand->DmaBufferPrivateDataSubmissionEndOffset - pSubmitCommand->DmaBufferPrivateDataSubmissionStartOffset >= sizeof (VBOXWDDM_DMA_PRIVATEDATA_BASEHDR));
2388 if (pSubmitCommand->DmaBufferPrivateDataSubmissionEndOffset - pSubmitCommand->DmaBufferPrivateDataSubmissionStartOffset < sizeof (VBOXWDDM_DMA_PRIVATEDATA_BASEHDR))
2389 {
2390 drprintf((__FUNCTION__": DmaBufferPrivateDataSubmissionEndOffset (%d) - DmaBufferPrivateDataSubmissionStartOffset (%d) < sizeof (VBOXWDDM_DMA_PRIVATEDATA_BASEHDR) (%d)\n",
2391 pSubmitCommand->DmaBufferPrivateDataSubmissionEndOffset,
2392 pSubmitCommand->DmaBufferPrivateDataSubmissionStartOffset,
2393 sizeof (VBOXWDDM_DMA_PRIVATEDATA_BASEHDR)));
2394 return STATUS_INVALID_PARAMETER;
2395 }
2396
2397 PVBOXWDDM_DMA_PRIVATEDATA_BASEHDR pPrivateDataBase = (PVBOXWDDM_DMA_PRIVATEDATA_BASEHDR)((uint8_t*)pSubmitCommand->pDmaBufferPrivateData + pSubmitCommand->DmaBufferPrivateDataSubmissionStartOffset);
2398 Assert(pPrivateDataBase);
2399 switch (pPrivateDataBase->enmCmd)
2400 {
2401#ifdef VBOXWDDM_RENDER_FROM_SHADOW
2402 case VBOXVDMACMD_TYPE_DMA_PRESENT_SHADOW2PRIMARY:
2403 {
2404 PVBOXWDDM_DMA_PRIVATEDATA_SHADOW2PRIMARY pS2P = (PVBOXWDDM_DMA_PRIVATEDATA_SHADOW2PRIMARY)pPrivateDataBase;
2405 VBOXWDDM_SOURCE *pSource = &pDevExt->aSources[pS2P->Shadow2Primary.VidPnSourceId];
2406 PVBOXWDDM_ALLOCATION pSrcAlloc = pS2P->Shadow2Primary.ShadowAlloc.pAlloc;
2407 vboxWddmAssignShadow(pDevExt, pSource, pSrcAlloc, pS2P->Shadow2Primary.VidPnSourceId);
2408 vboxWddmCheckUpdateShadowAddress(pDevExt, pSource, pS2P->Shadow2Primary.VidPnSourceId,
2409 pS2P->Shadow2Primary.ShadowAlloc.segmentIdAlloc, pS2P->Shadow2Primary.ShadowAlloc.offAlloc);
2410 uint32_t cUnlockedVBVADisabled = ASMAtomicReadU32(&pDevExt->cUnlockedVBVADisabled);
2411 if (!cUnlockedVBVADisabled)
2412 VBOXVBVA_OP(ReportDirtyRect, pDevExt, pSource, &pS2P->Shadow2Primary.SrcRect);
2413 else
2414 {
2415 Assert(KeGetCurrentIrql() == DISPATCH_LEVEL);
2416 VBOXVBVA_OP_WITHLOCK_ATDPC(ReportDirtyRect, pDevExt, pSource, &pS2P->Shadow2Primary.SrcRect);
2417 }
2418 /* get DPC data at IRQL */
2419
2420 Status = vboxVdmaDdiCmdFenceComplete(pDevExt, pContext, pSubmitCommand->SubmissionFenceId, DXGK_INTERRUPT_DMA_COMPLETED);
2421 break;
2422 }
2423#endif
2424 case VBOXVDMACMD_TYPE_DMA_PRESENT_BLT:
2425 {
2426 VBOXWDDM_DMA_PRIVATEDATA_PRESENTHDR *pPrivateData = (VBOXWDDM_DMA_PRIVATEDATA_PRESENTHDR*)pPrivateDataBase;
2427 PVBOXWDDM_DMA_PRIVATEDATA_BLT pBlt = (PVBOXWDDM_DMA_PRIVATEDATA_BLT)pPrivateData;
2428 PVBOXWDDM_ALLOCATION pDstAlloc = pBlt->Blt.DstAlloc.pAlloc;
2429 PVBOXWDDM_ALLOCATION pSrcAlloc = pBlt->Blt.SrcAlloc.pAlloc;
2430 uint32_t cContexts3D = ASMAtomicReadU32(&pDevExt->cContexts3D);
2431 BOOLEAN bComplete = TRUE;
2432 switch (pDstAlloc->enmType)
2433 {
2434 case VBOXWDDM_ALLOC_TYPE_STD_SHAREDPRIMARYSURFACE:
2435 case VBOXWDDM_ALLOC_TYPE_UMD_RC_GENERIC:
2436 {
2437 if (pDstAlloc->bAssigned)
2438 {
2439 VBOXWDDM_SOURCE *pSource = &pDevExt->aSources[pDstAlloc->SurfDesc.VidPnSourceId];
2440 Assert(pSource->pPrimaryAllocation == pDstAlloc);
2441 switch (pSrcAlloc->enmType)
2442 {
2443 case VBOXWDDM_ALLOC_TYPE_STD_SHADOWSURFACE:
2444 {
2445 VBOXVDMAPIPE_FLAGS_DMACMD fBltFlags;
2446 fBltFlags.Value = 0;
2447 fBltFlags.b3DRelated = !!cContexts3D;
2448 Assert(pContext->enmType == VBOXWDDM_CONTEXT_TYPE_SYSTEM);
2449 vboxWddmAssignShadow(pDevExt, pSource, pSrcAlloc, pDstAlloc->SurfDesc.VidPnSourceId);
2450 vboxWddmCheckUpdateShadowAddress(pDevExt, pSource,
2451 pDstAlloc->SurfDesc.VidPnSourceId, pBlt->Blt.SrcAlloc.segmentIdAlloc, pBlt->Blt.SrcAlloc.offAlloc);
2452 if (vboxVhwaHlpOverlayListIsEmpty(pDevExt, pDstAlloc->SurfDesc.VidPnSourceId))
2453 {
2454 RECT rect;
2455 if (pBlt->Blt.DstRects.UpdateRects.cRects)
2456 {
2457 rect = pBlt->Blt.DstRects.UpdateRects.aRects[0];
2458 for (UINT i = 1; i < pBlt->Blt.DstRects.UpdateRects.cRects; ++i)
2459 {
2460 vboxWddmRectUnited(&rect, &rect, &pBlt->Blt.DstRects.UpdateRects.aRects[i]);
2461 }
2462 }
2463 else
2464 rect = pBlt->Blt.DstRects.ContextRect;
2465
2466 uint32_t cUnlockedVBVADisabled = ASMAtomicReadU32(&pDevExt->cUnlockedVBVADisabled);
2467 if (!cUnlockedVBVADisabled)
2468 VBOXVBVA_OP(ReportDirtyRect, pDevExt, pSource, &rect);
2469 else
2470 {
2471 Assert(KeGetCurrentIrql() == DISPATCH_LEVEL);
2472 VBOXVBVA_OP_WITHLOCK_ATDPC(ReportDirtyRect, pDevExt, pSource, &rect);
2473 }
2474 }
2475 else
2476 {
2477 fBltFlags.b2DRelated = 1;
2478 fBltFlags.bDecVBVAUnlock = 1;
2479 }
2480
2481 if (fBltFlags.Value)
2482 {
2483 Status = vboxWddmSubmitBltCmd(pDevExt, pContext, pSubmitCommand->SubmissionFenceId, pBlt, fBltFlags);
2484 bComplete = FALSE;
2485 }
2486 break;
2487 }
2488 case VBOXWDDM_ALLOC_TYPE_UMD_RC_GENERIC:
2489 {
2490 Assert(pContext->enmType == VBOXWDDM_CONTEXT_TYPE_CUSTOM_3D);
2491 Assert(pSrcAlloc->fRcFlags.RenderTarget);
2492 if (pSrcAlloc->fRcFlags.RenderTarget)
2493 {
2494 VBOXVDMAPIPE_FLAGS_DMACMD fBltFlags;
2495 fBltFlags.Value = 0;
2496 fBltFlags.b3DRelated = 1;
2497 Status = vboxWddmSubmitBltCmd(pDevExt, pContext, pSubmitCommand->SubmissionFenceId, pBlt, fBltFlags);
2498 bComplete = FALSE;
2499 }
2500 break;
2501 }
2502 default:
2503 AssertBreakpoint();
2504 break;
2505 }
2506 }
2507 break;
2508 }
2509 case VBOXWDDM_ALLOC_TYPE_STD_STAGINGSURFACE:
2510 {
2511 Assert(pContext->enmType == VBOXWDDM_CONTEXT_TYPE_CUSTOM_3D);
2512 Assert(pSrcAlloc->enmType == VBOXWDDM_ALLOC_TYPE_UMD_RC_GENERIC);
2513 Assert(pSrcAlloc->fRcFlags.RenderTarget);
2514 Assert(vboxWddmRectIsEqual(&pBlt->Blt.SrcRect, &pBlt->Blt.DstRects.ContextRect));
2515 Assert(pBlt->Blt.DstRects.UpdateRects.cRects == 1);
2516 Assert(vboxWddmRectIsEqual(&pBlt->Blt.SrcRect, pBlt->Blt.DstRects.UpdateRects.aRects));
2517 break;
2518 }
2519 case VBOXWDDM_ALLOC_TYPE_STD_SHADOWSURFACE:
2520 {
2521 Assert(pSrcAlloc->enmType == VBOXWDDM_ALLOC_TYPE_STD_SHAREDPRIMARYSURFACE);
2522 break;
2523 }
2524 default:
2525 AssertBreakpoint();
2526 break;
2527 }
2528
2529 if (bComplete)
2530 {
2531 Status = vboxVdmaDdiCmdFenceComplete(pDevExt, pContext, pSubmitCommand->SubmissionFenceId, DXGK_INTERRUPT_DMA_COMPLETED);
2532 }
2533 break;
2534 }
2535 case VBOXVDMACMD_TYPE_CHROMIUM_CMD:
2536 {
2537#ifdef VBOX_WITH_VDMA
2538 VBOXWDDM_DMA_PRIVATEDATA_CHROMIUM_CMD *pChromiumCmd = (VBOXWDDM_DMA_PRIVATEDATA_CHROMIUM_CMD*)pPrivateDataBase;
2539 UINT cbCmd = VBOXVDMACMD_SIZE_FROMBODYSIZE(RT_OFFSETOF(VBOXVDMACMD_CHROMIUM_CMD, aBuffers[pChromiumCmd->Base.u32CmdReserved]));
2540
2541 PVBOXVDMACBUF_DR pDr = vboxVdmaCBufDrCreate (&pDevExt->u.primary.Vdma, cbCmd);
2542 if (!pDr)
2543 {
2544 /* @todo: try flushing.. */
2545 drprintf((__FUNCTION__": vboxVdmaCBufDrCreate returned NULL\n"));
2546 return STATUS_INSUFFICIENT_RESOURCES;
2547 }
2548 // vboxVdmaCBufDrCreate zero initializes the pDr
2549 pDr->fFlags = VBOXVDMACBUF_FLAG_BUF_FOLLOWS_DR;
2550 pDr->cbBuf = cbCmd;
2551 pDr->rc = VERR_NOT_IMPLEMENTED;
2552
2553 PVBOXVDMACMD pHdr = VBOXVDMACBUF_DR_TAIL(pDr, VBOXVDMACMD);
2554 pHdr->enmType = VBOXVDMACMD_TYPE_CHROMIUM_CMD;
2555 pHdr->u32CmdSpecific = 0;
2556 VBOXVDMACMD_CHROMIUM_CMD *pBody = VBOXVDMACMD_BODY(pHdr, VBOXVDMACMD_CHROMIUM_CMD);
2557 pBody->cBuffers = pChromiumCmd->Base.u32CmdReserved;
2558 for (UINT i = 0; i < pChromiumCmd->Base.u32CmdReserved; ++i)
2559 {
2560 VBOXVDMACMD_CHROMIUM_BUFFER *pBufCmd = &pBody->aBuffers[i];
2561 VBOXWDDM_UHGSMI_BUFFER_SUBMIT_INFO *pBufInfo = &pChromiumCmd->aBufInfos[i];
2562
2563 pBufCmd->offBuffer = pBufInfo->Alloc.offAlloc;
2564 pBufCmd->cbBuffer = pBufInfo->cbData;
2565 pBufCmd->u32GuesData = pBufInfo->bDoNotSignalCompletion;
2566 pBufCmd->u64GuesData = (uint64_t)pBufInfo->Alloc.pAlloc;
2567 }
2568
2569 PVBOXVDMADDI_CMD pDdiCmd = VBOXVDMADDI_CMD_FROM_BUF_DR(pDr);
2570 vboxVdmaDdiCmdInit(pDdiCmd, pSubmitCommand->SubmissionFenceId, pContext, vboxWddmDmaCompleteChromiumCmd, pDr);
2571 NTSTATUS Status = vboxVdmaDdiCmdSubmitted(pDevExt, &pDevExt->DdiCmdQueue, pDdiCmd);
2572 Assert(Status == STATUS_SUCCESS);
2573 if (Status == STATUS_SUCCESS)
2574 {
2575 int rc = vboxVdmaCBufDrSubmit(pDevExt, &pDevExt->u.primary.Vdma, pDr);
2576 Assert(rc == VINF_SUCCESS);
2577 }
2578 else
2579 {
2580 vboxVdmaCBufDrFree(&pDevExt->u.primary.Vdma, pDr);
2581 }
2582#else
2583 Status = vboxVdmaDdiCmdFenceComplete(pDevExt, pContext, pSubmitCommand->SubmissionFenceId, DXGK_INTERRUPT_DMA_COMPLETED);
2584 Assert(Status == STATUS_SUCCESS);
2585#endif
2586 break;
2587 }
2588 case VBOXVDMACMD_TYPE_DMA_PRESENT_FLIP:
2589 {
2590 VBOXWDDM_DMA_PRIVATEDATA_FLIP *pFlip = (VBOXWDDM_DMA_PRIVATEDATA_FLIP*)pPrivateDataBase;
2591 PVBOXVDMAPIPE_CMD_DMACMD_FLIP pFlipCmd = (PVBOXVDMAPIPE_CMD_DMACMD_FLIP)vboxVdmaGgCmdCreate(
2592 &pDevExt->u.primary.Vdma.DmaGg, VBOXVDMAPIPE_CMD_TYPE_DMACMD, sizeof (VBOXVDMAPIPE_CMD_DMACMD_FLIP));
2593 Assert(pFlipCmd);
2594 if (pFlipCmd)
2595 {
2596 VBOXWDDM_SOURCE *pSource = &pDevExt->aSources[pFlip->Flip.Alloc.srcId];
2597 vboxVdmaDdiCmdInit(&pFlipCmd->Hdr.DdiCmd, pSubmitCommand->SubmissionFenceId, pContext, vboxVdmaGgDdiCmdDestroy, pFlipCmd);
2598 pFlipCmd->Hdr.pDevExt = pDevExt;
2599 pFlipCmd->Hdr.fFlags.Value = 0;
2600 pFlipCmd->Hdr.fFlags.b3DRelated = 1;
2601 pFlipCmd->Hdr.enmCmd = VBOXVDMACMD_TYPE_DMA_PRESENT_FLIP;
2602 memcpy(&pFlipCmd->Flip, &pFlip->Flip, sizeof (pFlipCmd->Flip));
2603 Status = vboxWddmSubmitCmd(pDevExt, &pFlipCmd->Hdr);
2604 Assert(Status == STATUS_SUCCESS);
2605 }
2606 else
2607 {
2608 Status = vboxVdmaDdiCmdFenceComplete(pDevExt, pContext, pSubmitCommand->SubmissionFenceId, DXGK_INTERRUPT_DMA_FAULTED);
2609 Assert(Status == STATUS_SUCCESS);
2610 }
2611 break;
2612 }
2613 case VBOXVDMACMD_TYPE_DMA_PRESENT_CLRFILL:
2614 {
2615 PVBOXWDDM_DMA_PRIVATEDATA_CLRFILL pCF = (PVBOXWDDM_DMA_PRIVATEDATA_CLRFILL)pPrivateDataBase;
2616 PVBOXVDMAPIPE_CMD_DMACMD_CLRFILL pCFCmd = (PVBOXVDMAPIPE_CMD_DMACMD_CLRFILL)vboxVdmaGgCmdCreate(
2617 &pDevExt->u.primary.Vdma.DmaGg, VBOXVDMAPIPE_CMD_TYPE_DMACMD,
2618 RT_OFFSETOF(VBOXVDMAPIPE_CMD_DMACMD_CLRFILL, ClrFill.Rects.aRects[pCF->ClrFill.Rects.cRects]));
2619 Assert(pCFCmd);
2620 if (pCFCmd)
2621 {
2622// VBOXWDDM_SOURCE *pSource = &pDevExt->aSources[pFlip->Flip.Alloc.srcId];
2623 vboxVdmaDdiCmdInit(&pCFCmd->Hdr.DdiCmd, pSubmitCommand->SubmissionFenceId, pContext, vboxVdmaGgDdiCmdDestroy, pCFCmd);
2624 pCFCmd->Hdr.pDevExt = pDevExt;
2625 pCFCmd->Hdr.pDevExt = pDevExt;
2626 pCFCmd->Hdr.fFlags.Value = 0;
2627 pCFCmd->Hdr.fFlags.b2DRelated = 1;
2628 pCFCmd->Hdr.fFlags.bDecVBVAUnlock = 1;
2629 pCFCmd->Hdr.enmCmd = VBOXVDMACMD_TYPE_DMA_PRESENT_CLRFILL;
2630 memcpy(&pCFCmd->ClrFill, &pCF->ClrFill, RT_OFFSETOF(VBOXVDMA_CLRFILL, Rects.aRects[pCF->ClrFill.Rects.cRects]));
2631 Status = vboxWddmSubmitCmd(pDevExt, &pCFCmd->Hdr);
2632 Assert(Status == STATUS_SUCCESS);
2633 }
2634 else
2635 {
2636 Status = vboxVdmaDdiCmdFenceComplete(pDevExt, pContext, pSubmitCommand->SubmissionFenceId, DXGK_INTERRUPT_DMA_FAULTED);
2637 Assert(Status == STATUS_SUCCESS);
2638 }
2639
2640 break;
2641 }
2642 case VBOXVDMACMD_TYPE_DMA_NOP:
2643 {
2644 Status = vboxVdmaDdiCmdFenceComplete(pDevExt, pContext, pSubmitCommand->SubmissionFenceId, DXGK_INTERRUPT_DMA_COMPLETED);
2645 Assert(Status == STATUS_SUCCESS);
2646 break;
2647 }
2648 default:
2649 {
2650 AssertBreakpoint();
2651#if 0 //def VBOX_WITH_VDMA
2652 VBOXWDDM_DMA_PRIVATEDATA_PRESENTHDR *pPrivateData = (VBOXWDDM_DMA_PRIVATEDATA_PRESENTHDR*)pPrivateDataBase;
2653 PVBOXVDMACBUF_DR pDr = vboxVdmaCBufDrCreate (&pDevExt->u.primary.Vdma, 0);
2654 if (!pDr)
2655 {
2656 /* @todo: try flushing.. */
2657 drprintf((__FUNCTION__": vboxVdmaCBufDrCreate returned NULL\n"));
2658 return STATUS_INSUFFICIENT_RESOURCES;
2659 }
2660 // vboxVdmaCBufDrCreate zero initializes the pDr
2661 //pDr->fFlags = 0;
2662 pDr->cbBuf = pSubmitCommand->DmaBufferSubmissionEndOffset - pSubmitCommand->DmaBufferSubmissionStartOffset;
2663 pDr->u32FenceId = pSubmitCommand->SubmissionFenceId;
2664 pDr->rc = VERR_NOT_IMPLEMENTED;
2665 if (pPrivateData)
2666 pDr->u64GuestContext = (uint64_t)pPrivateData->pContext;
2667 // else // vboxVdmaCBufDrCreate zero initializes the pDr
2668 // pDr->u64GuestContext = NULL;
2669 pDr->Location.phBuf = pSubmitCommand->DmaBufferPhysicalAddress.QuadPart + pSubmitCommand->DmaBufferSubmissionStartOffset;
2670
2671 vboxVdmaCBufDrSubmit(pDevExt, &pDevExt->u.primary.Vdma, pDr);
2672#endif
2673 break;
2674 }
2675 }
2676// dfprintf(("<== "__FUNCTION__ ", context(0x%x)\n", hAdapter));
2677
2678 return Status;
2679}
2680
2681NTSTATUS
2682APIENTRY
2683DxgkDdiPreemptCommand(
2684 CONST HANDLE hAdapter,
2685 CONST DXGKARG_PREEMPTCOMMAND* pPreemptCommand)
2686{
2687 dfprintf(("==> "__FUNCTION__ ", hAdapter(0x%x)\n", hAdapter));
2688
2689// AssertBreakpoint();
2690 /* @todo: fixme: implement */
2691
2692 dfprintf(("<== "__FUNCTION__ ", hAdapter(0x%x)\n", hAdapter));
2693
2694 return STATUS_SUCCESS;
2695}
2696
2697#if 0
2698static uint32_t vboxWddmSysMemElBuild(PVBOXVDMACMD_SYSMEMEL pEl, PMDL pMdl, uint32_t iPfn, uint32_t cPages, uint32_t cbBuffer, uint32_t *pcPagesRemaining)
2699{
2700 uint32_t cbInitialBuffer = cbBuffer;
2701 if (cbBuf >= sizeof (*pEl))
2702 {
2703 PFN_NUMBER cur = MmGetMdlPfnArray(pMdl)[iPfn];
2704 uint32_t cbEl = sizeof (*pEl);
2705 uint32_t cBufs = 1;
2706 pEl->phBuf[0] = (cur << 12);
2707 --cPages;
2708 cbBuffer -= sizeof (*pEl);
2709 bool bArrayMode = false;
2710 while (cPages)
2711 {
2712 PFN_NUMBER next = MmGetMdlPfnArray(pMdl)[iPfn+cBufs];
2713 if (!bArrayMode)
2714 {
2715 if (next == cur+1)
2716 {
2717 cur = next;
2718 ++cBufs;
2719 --cPages;
2720 }
2721 else if (cBufs > 1)
2722 {
2723 break;
2724 }
2725 else
2726 {
2727 bArrayMode = true;
2728 }
2729 }
2730
2731 /* array mode */
2732 if (cbBuffer < sizeof (pEl->phBuf[0]))
2733 {
2734 break;
2735 }
2736
2737 pEl->phBuf[cBufs] = (next << 12);
2738 cbBuffer -= sizeof (pEl->phBuf[0]);
2739 ++cBufs;
2740 --cPages;
2741 }
2742
2743 pEl->cPages = cPages;
2744 if (bArrayMode)
2745 pEl->fFlags = VBOXVDMACMD_SYSMEMEL_F_PAGELIST;
2746 else
2747 pEl->fFlags = 0;
2748 }
2749 else
2750 {
2751 Assert(0);
2752 }
2753
2754 *pcPagesRemaining = cPages;
2755 return cbInitialBuffer - cbBuffer;
2756}
2757
2758static uint32_t vboxWddmBpbTransferVRamSysBuildEls(PVBOXVDMACMD_DMA_BPB_TRANSFER_VRAMSYS pCmd, PMDL pMdl, uint32_t iPfn, uint32_t cPages, uint32_t cbBuffer, uint32_t *pcPagesRemaining)
2759{
2760 uint32_t cInitPages = cPages;
2761 uint32_t cbBufferUsed = vboxWddmSysMemElBuild(&pCmd->FirstEl, pMdl, iPfn, cPages, cbBuffer, &cPages);
2762 if (cbBufferUsed)
2763 {
2764 uint32_t cEls = 1;
2765 PVBOXVDMACMD_SYSMEMEL pEl = &pCmd->FirstEl;
2766 while (cPages)
2767 {
2768 PVBOXVDMACMD_SYSMEMEL pEl = VBOXVDMACMD_SYSMEMEL_NEXT(pEl);
2769 cbBufferUsed = vboxWddmSysMemElBuild(pEl, pMdl, iPfn + cInitPages - cPages, cPages, cbBuffer - cbBufferUsed, &cPages);
2770 if (cbBufferUsed)
2771 {
2772 ++cEls;
2773 }
2774 else
2775 break;
2776 }
2777 }
2778 else
2779 {
2780 Assert(0);
2781 }
2782
2783 pCmd->cTransferPages = (cInitPages - cPages);
2784 *pcPagesRemaining = cPages;
2785 return cbBufferUsed;
2786}
2787#endif
2788/*
2789 * DxgkDdiBuildPagingBuffer
2790 */
2791NTSTATUS
2792APIENTRY
2793DxgkDdiBuildPagingBuffer(
2794 CONST HANDLE hAdapter,
2795 DXGKARG_BUILDPAGINGBUFFER* pBuildPagingBuffer)
2796{
2797 /* DxgkDdiBuildPagingBuffer should be made pageable. */
2798 PAGED_CODE();
2799
2800 vboxVDbgBreakFv();
2801
2802 NTSTATUS Status = STATUS_SUCCESS;
2803 PDEVICE_EXTENSION pDevExt = (PDEVICE_EXTENSION)hAdapter;
2804
2805 dfprintf(("==> "__FUNCTION__ ", context(0x%x)\n", hAdapter));
2806
2807 /* @todo: */
2808 switch (pBuildPagingBuffer->Operation)
2809 {
2810 case DXGK_OPERATION_TRANSFER:
2811 {
2812#ifdef VBOX_WITH_VDMA
2813#if 0
2814 if ((!pBuildPagingBuffer->Transfer.Source.SegmentId) != (!pBuildPagingBuffer->Transfer.Destination.SegmentId))
2815 {
2816 PVBOXVDMACMD pCmd = (PVBOXVDMACMD)pBuildPagingBuffer->pDmaBuffer;
2817 pCmd->enmType = VBOXVDMACMD_TYPE_DMA_BPB_TRANSFER_VRAMSYS;
2818 pCmd->u32CmdSpecific = 0;
2819 PVBOXVDMACMD_DMA_BPB_TRANSFER_VRAMSYS pBody = VBOXVDMACMD_BODY(pCmd, VBOXVDMACMD_DMA_BPB_TRANSFER_VRAMSYS);
2820 PMDL pMdl;
2821 uint32_t cPages = (pBuildPagingBuffer->Transfer.TransferSize + 0xfff) >> 12;
2822 cPages -= pBuildPagingBuffer->MultipassOffset;
2823 uint32_t iFirstPage = pBuildPagingBuffer->Transfer.MdlOffset + pBuildPagingBuffer->MultipassOffset;
2824 uint32_t cPagesRemaining;
2825 if (pBuildPagingBuffer->Transfer.Source.SegmentId)
2826 {
2827 uint64_t off = pBuildPagingBuffer->Transfer.Source.SegmentAddress.QuadPart;
2828 off += pBuildPagingBuffer->Transfer.TransferOffset + (pBuildPagingBuffer->MultipassOffset << 12);
2829 pBody->offVramBuf = off;
2830 pMdl = pBuildPagingBuffer->Transfer.Source.pMdl;
2831 pBody->fFlags = 0;//VBOXVDMACMD_DMA_BPB_TRANSFER_VRAMSYS_SYS2VRAM
2832 }
2833 else
2834 {
2835 uint64_t off = pBuildPagingBuffer->Transfer.Destination.SegmentAddress.QuadPart;
2836 off += pBuildPagingBuffer->Transfer.TransferOffset + (pBuildPagingBuffer->MultipassOffset << 12);
2837 pBody->offVramBuf = off;
2838 pMdl = pBuildPagingBuffer->Transfer.Destination.pMdl;
2839 pBody->fFlags = VBOXVDMACMD_DMA_BPB_TRANSFER_VRAMSYS_SYS2VRAM;
2840 }
2841
2842 uint32_t sbBufferUsed = vboxWddmBpbTransferVRamSysBuildEls(pBody, pMdl, iFirstPage, cPages, pBuildPagingBuffer->DmaSize, &cPagesRemaining);
2843 Assert(sbBufferUsed);
2844 }
2845
2846#else
2847 UINT cbCmd = VBOXVDMACMD_SIZE(VBOXVDMACMD_DMA_BPB_TRANSFER);
2848 PVBOXVDMACBUF_DR pDr = vboxVdmaCBufDrCreate (&pDevExt->u.primary.Vdma, cbCmd);
2849 Assert(pDr);
2850 if (pDr)
2851 {
2852 SIZE_T cbTransfered = 0;
2853 SIZE_T cbTransferSize = pBuildPagingBuffer->Transfer.TransferSize;
2854 PVBOXVDMACMD pHdr = VBOXVDMACBUF_DR_TAIL(pDr, VBOXVDMACMD);
2855 do
2856 {
2857 // vboxVdmaCBufDrCreate zero initializes the pDr
2858 pDr->fFlags = VBOXVDMACBUF_FLAG_BUF_FOLLOWS_DR;
2859 pDr->cbBuf = cbCmd;
2860 pDr->rc = VERR_NOT_IMPLEMENTED;
2861
2862 pHdr->enmType = VBOXVDMACMD_TYPE_DMA_BPB_TRANSFER;
2863 pHdr->u32CmdSpecific = 0;
2864 VBOXVDMACMD_DMA_BPB_TRANSFER *pBody = VBOXVDMACMD_BODY(pHdr, VBOXVDMACMD_DMA_BPB_TRANSFER);
2865// pBody->cbTransferSize = (uint32_t)pBuildPagingBuffer->Transfer.TransferSize;
2866 pBody->fFlags = 0;
2867 SIZE_T cSrcPages = (cbTransferSize + 0xfff ) >> 12;
2868 SIZE_T cDstPages = cSrcPages;
2869
2870 if (pBuildPagingBuffer->Transfer.Source.SegmentId)
2871 {
2872 uint64_t off = pBuildPagingBuffer->Transfer.Source.SegmentAddress.QuadPart;
2873 off += pBuildPagingBuffer->Transfer.TransferOffset + cbTransfered;
2874 pBody->Src.offVramBuf = off;
2875 pBody->fFlags |= VBOXVDMACMD_DMA_BPB_TRANSFER_F_SRC_VRAMOFFSET;
2876 }
2877 else
2878 {
2879 UINT index = pBuildPagingBuffer->Transfer.MdlOffset + (cbTransfered>>12);
2880 pBody->Src.phBuf = MmGetMdlPfnArray(pBuildPagingBuffer->Transfer.Source.pMdl)[index] << 12;
2881 PFN_NUMBER num = MmGetMdlPfnArray(pBuildPagingBuffer->Transfer.Source.pMdl)[index];
2882 cSrcPages = 1;
2883 for (UINT i = 1; i < ((cbTransferSize - cbTransfered + 0xfff) >> 12); ++i)
2884 {
2885 PFN_NUMBER cur = MmGetMdlPfnArray(pBuildPagingBuffer->Transfer.Source.pMdl)[index+i];
2886 if(cur != ++num)
2887 {
2888 cSrcPages+= i-1;
2889 break;
2890 }
2891 }
2892 }
2893
2894 if (pBuildPagingBuffer->Transfer.Destination.SegmentId)
2895 {
2896 uint64_t off = pBuildPagingBuffer->Transfer.Destination.SegmentAddress.QuadPart;
2897 off += pBuildPagingBuffer->Transfer.TransferOffset;
2898 pBody->Dst.offVramBuf = off + cbTransfered;
2899 pBody->fFlags |= VBOXVDMACMD_DMA_BPB_TRANSFER_F_DST_VRAMOFFSET;
2900 }
2901 else
2902 {
2903 UINT index = pBuildPagingBuffer->Transfer.MdlOffset + (cbTransfered>>12);
2904 pBody->Dst.phBuf = MmGetMdlPfnArray(pBuildPagingBuffer->Transfer.Destination.pMdl)[index] << 12;
2905 PFN_NUMBER num = MmGetMdlPfnArray(pBuildPagingBuffer->Transfer.Destination.pMdl)[index];
2906 cDstPages = 1;
2907 for (UINT i = 1; i < ((cbTransferSize - cbTransfered + 0xfff) >> 12); ++i)
2908 {
2909 PFN_NUMBER cur = MmGetMdlPfnArray(pBuildPagingBuffer->Transfer.Destination.pMdl)[index+i];
2910 if(cur != ++num)
2911 {
2912 cDstPages+= i-1;
2913 break;
2914 }
2915 }
2916 }
2917
2918 SIZE_T cbCurTransfer;
2919 cbCurTransfer = RT_MIN(cbTransferSize - cbTransfered, cSrcPages << 12);
2920 cbCurTransfer = RT_MIN(cbCurTransfer, cDstPages << 12);
2921
2922 pBody->cbTransferSize = cbCurTransfer;
2923 Assert(!(cbCurTransfer & 0xfff));
2924
2925 int rc = vboxVdmaCBufDrSubmitSynch(pDevExt, &pDevExt->u.primary.Vdma, pDr);
2926 AssertRC(rc);
2927 if (RT_SUCCESS(rc))
2928 {
2929 Status = STATUS_SUCCESS;
2930 cbTransfered += cbCurTransfer;
2931 }
2932 else
2933 Status = STATUS_UNSUCCESSFUL;
2934 } while (cbTransfered < cbTransferSize);
2935 Assert(cbTransfered == cbTransferSize);
2936 vboxVdmaCBufDrFree(&pDevExt->u.primary.Vdma, pDr);
2937 }
2938 else
2939 {
2940 /* @todo: try flushing.. */
2941 drprintf((__FUNCTION__": vboxVdmaCBufDrCreate returned NULL\n"));
2942 Status = STATUS_INSUFFICIENT_RESOURCES;
2943 }
2944#endif
2945#endif /* #ifdef VBOX_WITH_VDMA */
2946 break;
2947 }
2948 case DXGK_OPERATION_FILL:
2949 {
2950// pBuildPagingBuffer->pDmaBuffer = (uint8_t*)pBuildPagingBuffer->pDmaBuffer + VBOXVDMACMD_SIZE(VBOXVDMACMD_DMA_BPB_FILL);
2951 break;
2952 }
2953 case DXGK_OPERATION_DISCARD_CONTENT:
2954 {
2955// AssertBreakpoint();
2956 break;
2957 }
2958 default:
2959 {
2960 drprintf((__FUNCTION__": unsupported op (%d)\n", pBuildPagingBuffer->Operation));
2961 AssertBreakpoint();
2962 break;
2963 }
2964 }
2965
2966 dfprintf(("<== "__FUNCTION__ ", context(0x%x)\n", hAdapter));
2967
2968 return Status;
2969
2970}
2971
2972NTSTATUS
2973APIENTRY
2974DxgkDdiSetPalette(
2975 CONST HANDLE hAdapter,
2976 CONST DXGKARG_SETPALETTE* pSetPalette
2977 )
2978{
2979 dfprintf(("==> "__FUNCTION__ ", hAdapter(0x%x)\n", hAdapter));
2980
2981 AssertBreakpoint();
2982 /* @todo: fixme: implement */
2983
2984 dfprintf(("<== "__FUNCTION__ ", hAdapter(0x%x)\n", hAdapter));
2985
2986 return STATUS_SUCCESS;
2987}
2988
2989BOOL vboxWddmPointerCopyColorData(CONST DXGKARG_SETPOINTERSHAPE* pSetPointerShape, PVIDEO_POINTER_ATTRIBUTES pPointerAttributes)
2990{
2991 /* Format of "hardware" pointer is:
2992 * 1 bpp AND mask with byte aligned scanlines,
2993 * B G R A bytes of XOR mask that starts on the next 4 byte aligned offset after AND mask.
2994 *
2995 * If fl & SPS_ALPHA then A bytes contain alpha channel information.
2996 * Otherwise A bytes are undefined (but will be 0).
2997 *
2998 */
2999 PBYTE pjSrcAnd = NULL;
3000 PBYTE pjSrcXor = NULL;
3001
3002 ULONG cy = 0;
3003
3004 PBYTE pjDstAnd = pPointerAttributes->Pixels;
3005 ULONG cjAnd = 0;
3006 PBYTE pjDstXor = pPointerAttributes->Pixels;
3007
3008 ULONG cxSrc = pSetPointerShape->Width;
3009 ULONG cySrc = pSetPointerShape->Width;
3010
3011 // Make sure the new pointer isn't too big to handle,
3012 // strip the size to 64x64 if necessary
3013 if (cxSrc > VBOXWDDM_C_POINTER_MAX_WIDTH)
3014 cxSrc = VBOXWDDM_C_POINTER_MAX_WIDTH;
3015
3016 if (cySrc > VBOXWDDM_C_POINTER_MAX_HEIGHT)
3017 cySrc = VBOXWDDM_C_POINTER_MAX_HEIGHT;
3018
3019 /* Size of AND mask in bytes */
3020 cjAnd = ((cxSrc + 7) / 8) * cySrc;
3021
3022 /* Pointer to XOR mask is 4-bytes aligned */
3023 pjDstXor += (cjAnd + 3) & ~3;
3024
3025 pPointerAttributes->Width = cxSrc;
3026 pPointerAttributes->Height = cySrc;
3027 pPointerAttributes->WidthInBytes = cxSrc * 4;
3028
3029 uint32_t cbData = ((cjAnd + 3) & ~3) + pPointerAttributes->Height*pPointerAttributes->WidthInBytes;
3030 uint32_t cbPointerAttributes = RT_OFFSETOF(VIDEO_POINTER_ATTRIBUTES, Pixels[cbData]);
3031 Assert(VBOXWDDM_POINTER_ATTRIBUTES_SIZE >= cbPointerAttributes);
3032 if (VBOXWDDM_POINTER_ATTRIBUTES_SIZE < cbPointerAttributes)
3033 {
3034 drprintf((__FUNCTION__": VBOXWDDM_POINTER_ATTRIBUTES_SIZE(%d) < cbPointerAttributes(%d)\n", VBOXWDDM_POINTER_ATTRIBUTES_SIZE, cbPointerAttributes));
3035 return FALSE;
3036 }
3037
3038 /* Init AND mask to 1 */
3039 RtlFillMemory (pjDstAnd, cjAnd, 0xFF);
3040
3041 PBYTE pjSrcAlpha = (PBYTE)pSetPointerShape->pPixels;
3042
3043 /*
3044 * Emulate AND mask to provide viewable mouse pointer for
3045 * hardware which does not support alpha channel.
3046 */
3047
3048 for (cy = 0; cy < cySrc; cy++)
3049 {
3050 ULONG cx;
3051
3052 UCHAR bitmask = 0x80;
3053
3054 for (cx = 0; cx < cxSrc; cx++, bitmask >>= 1)
3055 {
3056 if (bitmask == 0)
3057 {
3058 bitmask = 0x80;
3059 }
3060
3061 if (pjSrcAlpha[cx * 4 + 3] > 0x7f)
3062 {
3063 pjDstAnd[cx / 8] &= ~bitmask;
3064 }
3065 }
3066
3067 // Point to next source and dest scans
3068 pjSrcAlpha += pSetPointerShape->Pitch;
3069 pjDstAnd += (cxSrc + 7) / 8;
3070 }
3071
3072 /*
3073 * pso is 32 bit BGRX bitmap. Copy it to Pixels
3074 */
3075 pjSrcXor = (PBYTE)pSetPointerShape->pPixels;
3076 for (cy = 0; cy < cySrc; cy++)
3077 {
3078 /* 32 bit bitmap is being copied */
3079 RtlCopyMemory (pjDstXor, pjSrcXor, cxSrc * 4);
3080
3081 /* Point to next source and dest scans */
3082 pjSrcXor += pSetPointerShape->Pitch;
3083 pjDstXor += pPointerAttributes->WidthInBytes;
3084 }
3085
3086 return TRUE;
3087}
3088
3089BOOL vboxWddmPointerCopyMonoData(CONST DXGKARG_SETPOINTERSHAPE* pSetPointerShape, PVIDEO_POINTER_ATTRIBUTES pPointerAttributes)
3090{
3091 PBYTE pjSrc = NULL;
3092
3093 ULONG cy = 0;
3094
3095 PBYTE pjDstAnd = pPointerAttributes->Pixels;
3096 ULONG cjAnd = 0;
3097 PBYTE pjDstXor = pPointerAttributes->Pixels;
3098
3099 ULONG cxSrc = pSetPointerShape->Width;
3100 ULONG cySrc = pSetPointerShape->Height;
3101
3102 // Make sure the new pointer isn't too big to handle,
3103 // strip the size to 64x64 if necessary
3104 if (cxSrc > VBOXWDDM_C_POINTER_MAX_WIDTH)
3105 cxSrc = VBOXWDDM_C_POINTER_MAX_WIDTH;
3106
3107 if (cySrc > VBOXWDDM_C_POINTER_MAX_HEIGHT)
3108 cySrc = VBOXWDDM_C_POINTER_MAX_HEIGHT;
3109
3110 /* Size of AND mask in bytes */
3111 cjAnd = ((cxSrc + 7) / 8) * cySrc;
3112
3113 /* Pointer to XOR mask is 4-bytes aligned */
3114 pjDstXor += (cjAnd + 3) & ~3;
3115
3116 pPointerAttributes->Width = cxSrc;
3117 pPointerAttributes->Height = cySrc;
3118 pPointerAttributes->WidthInBytes = cxSrc * 4;
3119
3120 /* Init AND mask to 1 */
3121 RtlFillMemory (pjDstAnd, cjAnd, 0xFF);
3122
3123 /*
3124 * Copy AND mask.
3125 */
3126 pjSrc = (PBYTE)pSetPointerShape->pPixels;
3127
3128 for (cy = 0; cy < cySrc; cy++)
3129 {
3130 RtlCopyMemory (pjDstAnd, pjSrc, (cxSrc + 7) / 8);
3131
3132 // Point to next source and dest scans
3133 pjSrc += pSetPointerShape->Pitch;
3134 pjDstAnd += (cxSrc + 7) / 8;
3135 }
3136
3137 for (cy = 0; cy < cySrc; ++cy)
3138 {
3139 ULONG cx;
3140
3141 UCHAR bitmask = 0x80;
3142
3143 for (cx = 0; cx < cxSrc; cx++, bitmask >>= 1)
3144 {
3145 if (bitmask == 0)
3146 {
3147 bitmask = 0x80;
3148 }
3149
3150 if (pjSrc[cx / 8] & bitmask)
3151 {
3152 *(ULONG *)&pjDstXor[cx * 4] = 0x00FFFFFF;
3153 }
3154 else
3155 {
3156 *(ULONG *)&pjDstXor[cx * 4] = 0;
3157 }
3158 }
3159
3160 // Point to next source and dest scans
3161 pjSrc += pSetPointerShape->Pitch;
3162 pjDstXor += cxSrc * 4;
3163 }
3164
3165 return TRUE;
3166}
3167
3168static BOOLEAN vboxVddmPointerShapeToAttributes(CONST DXGKARG_SETPOINTERSHAPE* pSetPointerShape, PVBOXWDDM_POINTER_INFO pPointerInfo)
3169{
3170 PVIDEO_POINTER_ATTRIBUTES pPointerAttributes = &pPointerInfo->Attributes.data;
3171 /* pPointerAttributes maintains the visibility state, clear all except visibility */
3172 pPointerAttributes->Enable &= VBOX_MOUSE_POINTER_VISIBLE;
3173
3174 Assert(pSetPointerShape->Flags.Value == 1 || pSetPointerShape->Flags.Value == 2);
3175 if (pSetPointerShape->Flags.Color)
3176 {
3177 if (vboxWddmPointerCopyColorData(pSetPointerShape, pPointerAttributes))
3178 {
3179 pPointerAttributes->Flags = VIDEO_MODE_COLOR_POINTER;
3180 pPointerAttributes->Enable |= VBOX_MOUSE_POINTER_ALPHA;
3181 }
3182 else
3183 {
3184 drprintf((__FUNCTION__": vboxWddmPointerCopyColorData failed\n"));
3185 AssertBreakpoint();
3186 return FALSE;
3187 }
3188
3189 }
3190 else if (pSetPointerShape->Flags.Monochrome)
3191 {
3192 if (vboxWddmPointerCopyMonoData(pSetPointerShape, pPointerAttributes))
3193 {
3194 pPointerAttributes->Flags = VIDEO_MODE_MONO_POINTER;
3195 }
3196 else
3197 {
3198 drprintf((__FUNCTION__": vboxWddmPointerCopyMonoData failed\n"));
3199 AssertBreakpoint();
3200 return FALSE;
3201 }
3202 }
3203 else
3204 {
3205 drprintf((__FUNCTION__": unsupported pointer type Flags.Value(0x%x)\n", pSetPointerShape->Flags.Value));
3206 AssertBreakpoint();
3207 return FALSE;
3208 }
3209
3210 pPointerAttributes->Enable |= VBOX_MOUSE_POINTER_SHAPE;
3211
3212 /*
3213 * The hot spot coordinates and alpha flag will be encoded in the pPointerAttributes::Enable field.
3214 * High word will contain hot spot info and low word - flags.
3215 */
3216 pPointerAttributes->Enable |= (pSetPointerShape->YHot & 0xFF) << 24;
3217 pPointerAttributes->Enable |= (pSetPointerShape->XHot & 0xFF) << 16;
3218
3219 return TRUE;
3220}
3221
3222NTSTATUS
3223APIENTRY
3224DxgkDdiSetPointerPosition(
3225 CONST HANDLE hAdapter,
3226 CONST DXGKARG_SETPOINTERPOSITION* pSetPointerPosition)
3227{
3228// dfprintf(("==> "__FUNCTION__ ", hAdapter(0x%x)\n", hAdapter));
3229
3230 vboxVDbgBreakFv();
3231
3232 /* mouse integration is ON */
3233 PDEVICE_EXTENSION pDevExt = (PDEVICE_EXTENSION)hAdapter;
3234 PVBOXWDDM_POINTER_INFO pPointerInfo = &pDevExt->aSources[pSetPointerPosition->VidPnSourceId].PointerInfo;
3235 PVBOXWDDM_GLOBAL_POINTER_INFO pGlobalPointerInfo = &pDevExt->PointerInfo;
3236 PVIDEO_POINTER_ATTRIBUTES pPointerAttributes = &pPointerInfo->Attributes.data;
3237 BOOLEAN bNotifyVisibility;
3238 if (pSetPointerPosition->Flags.Visible)
3239 {
3240 bNotifyVisibility = (pGlobalPointerInfo->cVisible == 0);
3241 if (!(pPointerAttributes->Enable & VBOX_MOUSE_POINTER_VISIBLE))
3242 {
3243 ++pGlobalPointerInfo->cVisible;
3244 pPointerAttributes->Enable |= VBOX_MOUSE_POINTER_VISIBLE;
3245 }
3246 }
3247 else
3248 {
3249 if (!!(pPointerAttributes->Enable & VBOX_MOUSE_POINTER_VISIBLE))
3250 {
3251 --pGlobalPointerInfo->cVisible;
3252 Assert(pGlobalPointerInfo->cVisible < UINT32_MAX/2);
3253 pPointerAttributes->Enable &= ~VBOX_MOUSE_POINTER_VISIBLE;
3254 bNotifyVisibility = (pGlobalPointerInfo->cVisible == 0);
3255 }
3256 }
3257
3258 pPointerAttributes->Column = pSetPointerPosition->X;
3259 pPointerAttributes->Row = pSetPointerPosition->Y;
3260
3261 if (bNotifyVisibility && vboxQueryHostWantsAbsolute())
3262 {
3263 // tell the host to use the guest's pointer
3264 VIDEO_POINTER_ATTRIBUTES PointerAttributes;
3265
3266 /* Visible and No Shape means Show the pointer.
3267 * It is enough to init only this field.
3268 */
3269 PointerAttributes.Enable = pSetPointerPosition->Flags.Visible ? VBOX_MOUSE_POINTER_VISIBLE : 0;
3270
3271 BOOLEAN bResult = vboxUpdatePointerShape(pDevExt, &PointerAttributes, sizeof (PointerAttributes));
3272 Assert(bResult);
3273 }
3274
3275// dfprintf(("<== "__FUNCTION__ ", hAdapter(0x%x)\n", hAdapter));
3276
3277 return STATUS_SUCCESS;
3278}
3279
3280NTSTATUS
3281APIENTRY
3282DxgkDdiSetPointerShape(
3283 CONST HANDLE hAdapter,
3284 CONST DXGKARG_SETPOINTERSHAPE* pSetPointerShape)
3285{
3286// dfprintf(("==> "__FUNCTION__ ", hAdapter(0x%x)\n", hAdapter));
3287
3288 vboxVDbgBreakFv();
3289
3290 NTSTATUS Status = STATUS_NOT_SUPPORTED;
3291
3292 if (vboxQueryHostWantsAbsolute())
3293 {
3294 /* mouse integration is ON */
3295 PDEVICE_EXTENSION pDevExt = (PDEVICE_EXTENSION)hAdapter;
3296 PVBOXWDDM_POINTER_INFO pPointerInfo = &pDevExt->aSources[pSetPointerShape->VidPnSourceId].PointerInfo;
3297 /* @todo: to avoid extra data copy and extra heap allocation,
3298 * need to maintain the pre-allocated HGSMI buffer and convert the data directly to it */
3299 if (vboxVddmPointerShapeToAttributes(pSetPointerShape, pPointerInfo))
3300 {
3301 if (vboxUpdatePointerShape (pDevExt, &pPointerInfo->Attributes.data, VBOXWDDM_POINTER_ATTRIBUTES_SIZE))
3302 Status = STATUS_SUCCESS;
3303 else
3304 {
3305 AssertBreakpoint();
3306 drprintf((__FUNCTION__": vboxUpdatePointerShape failed\n"));
3307 }
3308 }
3309 }
3310
3311// dfprintf(("<== "__FUNCTION__ ", hAdapter(0x%x)\n", hAdapter));
3312
3313 return Status;
3314}
3315
3316NTSTATUS
3317APIENTRY CALLBACK
3318DxgkDdiResetFromTimeout(
3319 CONST HANDLE hAdapter)
3320{
3321 dfprintf(("==> "__FUNCTION__ ", hAdapter(0x%x)\n", hAdapter));
3322
3323 AssertBreakpoint();
3324 /* @todo: fixme: implement */
3325
3326 dfprintf(("<== "__FUNCTION__ ", hAdapter(0x%x)\n", hAdapter));
3327
3328 return STATUS_SUCCESS;
3329}
3330
3331
3332/* the lpRgnData->Buffer comes to us as RECT
3333 * to avoid extra memcpy we cast it to PRTRECT assuming
3334 * they are identical */
3335AssertCompile(sizeof(RECT) == sizeof(RTRECT));
3336AssertCompile(RT_OFFSETOF(RECT, left) == RT_OFFSETOF(RTRECT, xLeft));
3337AssertCompile(RT_OFFSETOF(RECT, bottom) == RT_OFFSETOF(RTRECT, yBottom));
3338AssertCompile(RT_OFFSETOF(RECT, right) == RT_OFFSETOF(RTRECT, xRight));
3339AssertCompile(RT_OFFSETOF(RECT, top) == RT_OFFSETOF(RTRECT, yTop));
3340
3341NTSTATUS
3342APIENTRY
3343DxgkDdiEscape(
3344 CONST HANDLE hAdapter,
3345 CONST DXGKARG_ESCAPE* pEscape)
3346{
3347 PAGED_CODE();
3348
3349// dfprintf(("==> "__FUNCTION__ ", hAdapter(0x%x)\n", hAdapter));
3350
3351 NTSTATUS Status = STATUS_NOT_SUPPORTED;
3352 PDEVICE_EXTENSION pDevExt = (PDEVICE_EXTENSION)hAdapter;
3353 Assert(pEscape->PrivateDriverDataSize >= sizeof (VBOXDISPIFESCAPE));
3354 if (pEscape->PrivateDriverDataSize >= sizeof (VBOXDISPIFESCAPE))
3355 {
3356 PVBOXDISPIFESCAPE pEscapeHdr = (PVBOXDISPIFESCAPE)pEscape->pPrivateDriverData;
3357 switch (pEscapeHdr->escapeCode)
3358 {
3359#ifdef VBOX_WITH_VDMA
3360 case VBOXESC_UHGSMI_SUBMIT:
3361 {
3362 PVBOXWDDM_CONTEXT pContext = (PVBOXWDDM_CONTEXT)pEscape->hContext;
3363 PVBOXDISPIFESCAPE_UHGSMI_SUBMIT pSubmit = (PVBOXDISPIFESCAPE_UHGSMI_SUBMIT)pEscapeHdr;
3364 Assert(pEscape->PrivateDriverDataSize >= sizeof (VBOXDISPIFESCAPE_UHGSMI_SUBMIT)
3365 && pEscape->PrivateDriverDataSize == RT_OFFSETOF(VBOXDISPIFESCAPE_UHGSMI_SUBMIT, aBuffers[pEscapeHdr->u32CmdSpecific]));
3366 if (pEscape->PrivateDriverDataSize >= sizeof (VBOXDISPIFESCAPE_GETVBOXVIDEOCMCMD)
3367 && pEscape->PrivateDriverDataSize == RT_OFFSETOF(VBOXDISPIFESCAPE_UHGSMI_SUBMIT, aBuffers[pEscapeHdr->u32CmdSpecific]))
3368 {
3369 Status = vboxVideoAMgrCtxAllocSubmit(pDevExt, &pContext->AllocContext, pEscapeHdr->u32CmdSpecific, pSubmit->aBuffers);
3370 Assert(Status == STATUS_SUCCESS);
3371 }
3372 else
3373 Status = STATUS_BUFFER_TOO_SMALL;
3374
3375 break;
3376 }
3377#endif
3378 case VBOXESC_UHGSMI_ALLOCATE:
3379 {
3380 PVBOXWDDM_CONTEXT pContext = (PVBOXWDDM_CONTEXT)pEscape->hContext;
3381 PVBOXDISPIFESCAPE_UHGSMI_ALLOCATE pAlocate = (PVBOXDISPIFESCAPE_UHGSMI_ALLOCATE)pEscapeHdr;
3382 Assert(pEscape->PrivateDriverDataSize == sizeof (VBOXDISPIFESCAPE_UHGSMI_ALLOCATE));
3383 if (pEscape->PrivateDriverDataSize == sizeof (VBOXDISPIFESCAPE_UHGSMI_ALLOCATE))
3384 {
3385 Status = vboxVideoAMgrCtxAllocCreate(&pContext->AllocContext, &pAlocate->Alloc);
3386 Assert(Status == STATUS_SUCCESS);
3387 }
3388 else
3389 Status = STATUS_BUFFER_TOO_SMALL;
3390
3391 break;
3392 }
3393 case VBOXESC_UHGSMI_DEALLOCATE:
3394 {
3395 PVBOXWDDM_CONTEXT pContext = (PVBOXWDDM_CONTEXT)pEscape->hContext;
3396 PVBOXDISPIFESCAPE_UHGSMI_DEALLOCATE pDealocate = (PVBOXDISPIFESCAPE_UHGSMI_DEALLOCATE)pEscapeHdr;
3397 Assert(pEscape->PrivateDriverDataSize == sizeof (VBOXDISPIFESCAPE_UHGSMI_DEALLOCATE));
3398 if (pEscape->PrivateDriverDataSize == sizeof (VBOXDISPIFESCAPE_UHGSMI_DEALLOCATE))
3399 {
3400 Status = vboxVideoAMgrCtxAllocDestroy(&pContext->AllocContext, pDealocate->hAlloc);
3401 Assert(Status == STATUS_SUCCESS);
3402 }
3403 else
3404 Status = STATUS_BUFFER_TOO_SMALL;
3405
3406 break;
3407 }
3408 case VBOXESC_GETVBOXVIDEOCMCMD:
3409 {
3410 PVBOXWDDM_CONTEXT pContext = (PVBOXWDDM_CONTEXT)pEscape->hContext;
3411 PVBOXDISPIFESCAPE_GETVBOXVIDEOCMCMD pRegions = (PVBOXDISPIFESCAPE_GETVBOXVIDEOCMCMD)pEscapeHdr;
3412 Assert(pEscape->PrivateDriverDataSize >= sizeof (VBOXDISPIFESCAPE_GETVBOXVIDEOCMCMD));
3413 if (pEscape->PrivateDriverDataSize >= sizeof (VBOXDISPIFESCAPE_GETVBOXVIDEOCMCMD))
3414 {
3415 Status = vboxVideoCmEscape(&pContext->CmContext, pRegions, pEscape->PrivateDriverDataSize);
3416 Assert(Status == STATUS_SUCCESS);
3417 }
3418 else
3419 Status = STATUS_BUFFER_TOO_SMALL;
3420
3421 break;
3422 }
3423 case VBOXESC_SETVISIBLEREGION:
3424 {
3425 LPRGNDATA lpRgnData = VBOXDISPIFESCAPE_DATA(pEscapeHdr, RGNDATA);
3426 uint32_t cbData = VBOXDISPIFESCAPE_DATA_SIZE(pEscape->PrivateDriverDataSize);
3427 uint32_t cbRects = cbData - RT_OFFSETOF(RGNDATA, Buffer);
3428 /* the lpRgnData->Buffer comes to us as RECT
3429 * to avoid extra memcpy we cast it to PRTRECT assuming
3430 * they are identical
3431 * see AssertCompile's above */
3432
3433 RTRECT *pRect = (RTRECT *)&lpRgnData->Buffer;
3434
3435 uint32_t cRects = cbRects/sizeof(RTRECT);
3436 int rc;
3437
3438 dprintf(("IOCTL_VIDEO_VBOX_SETVISIBLEREGION cRects=%d\n", cRects));
3439 Assert(cbRects >= sizeof(RTRECT)
3440 && cbRects == cRects*sizeof(RTRECT)
3441 && cRects == lpRgnData->rdh.nCount);
3442 if ( cbRects >= sizeof(RTRECT)
3443 && cbRects == cRects*sizeof(RTRECT)
3444 && cRects == lpRgnData->rdh.nCount)
3445 {
3446 /*
3447 * Inform the host about the visible region
3448 */
3449 VMMDevVideoSetVisibleRegion *req = NULL;
3450
3451 rc = VbglGRAlloc ((VMMDevRequestHeader **)&req,
3452 sizeof (VMMDevVideoSetVisibleRegion) + (cRects-1)*sizeof(RTRECT),
3453 VMMDevReq_VideoSetVisibleRegion);
3454 AssertRC(rc);
3455 if (RT_SUCCESS(rc))
3456 {
3457 req->cRect = cRects;
3458 memcpy(&req->Rect, pRect, cRects*sizeof(RTRECT));
3459
3460 rc = VbglGRPerform (&req->header);
3461 AssertRC(rc);
3462 if (!RT_SUCCESS(rc))
3463 {
3464 drprintf((__FUNCTION__": VbglGRPerform failed rc (%d)", rc));
3465 Status = STATUS_UNSUCCESSFUL;
3466 }
3467 }
3468 else
3469 {
3470 drprintf((__FUNCTION__": VbglGRAlloc failed rc (%d)", rc));
3471 Status = STATUS_UNSUCCESSFUL;
3472 }
3473 }
3474 else
3475 {
3476 drprintf((__FUNCTION__": VBOXESC_SETVISIBLEREGION: incorrect buffer size (%d), reported count (%d)\n", cbRects, lpRgnData->rdh.nCount));
3477 AssertBreakpoint();
3478 Status = STATUS_INVALID_PARAMETER;
3479 }
3480 break;
3481 }
3482 case VBOXESC_ISVRDPACTIVE:
3483 /* @todo: implement */
3484 Status = STATUS_SUCCESS;
3485 break;
3486 case VBOXESC_SCREENLAYOUT:
3487 {
3488 Assert(pEscape->PrivateDriverDataSize >= sizeof (VBOXDISPIFESCAPE_SCREENLAYOUT));
3489 if (pEscape->PrivateDriverDataSize >= sizeof (VBOXDISPIFESCAPE_SCREENLAYOUT))
3490 {
3491 PVBOXDISPIFESCAPE_SCREENLAYOUT pLo = (PVBOXDISPIFESCAPE_SCREENLAYOUT)pEscapeHdr;
3492 Assert(pLo->ScreenLayout.cScreens <= (UINT)commonFromDeviceExt(pDevExt)->cDisplays);
3493 for (UINT i = 0; i < pLo->ScreenLayout.cScreens; ++i)
3494 {
3495 PVBOXSCREENLAYOUT_ELEMENT pEl = &pLo->ScreenLayout.aScreens[i];
3496 Assert(pEl->VidPnSourceId < (UINT)commonFromDeviceExt(pDevExt)->cDisplays);
3497 if (pEl->VidPnSourceId < (UINT)commonFromDeviceExt(pDevExt)->cDisplays)
3498 {
3499 PVBOXWDDM_SOURCE pSource = &pDevExt->aSources[pEl->VidPnSourceId];
3500 NTSTATUS tmpStatus = vboxWddmGhDisplayUpdateScreenPos(pDevExt, pSource, &pEl->pos);
3501 Assert(tmpStatus == STATUS_SUCCESS);
3502 }
3503 }
3504 Status = STATUS_SUCCESS;
3505 break;
3506 }
3507 else
3508 {
3509 drprintf((__FUNCTION__": VBOXESC_SCREENLAYOUT: incorrect buffer size (%d) < sizeof (VBOXDISPIFESCAPE_SCREENLAYOUT) (%d)\n",
3510 pEscape->PrivateDriverDataSize, sizeof (VBOXDISPIFESCAPE_SCREENLAYOUT)));
3511 AssertBreakpoint();
3512 Status = STATUS_INVALID_PARAMETER;
3513 }
3514 }
3515 case VBOXESC_SWAPCHAININFO:
3516 {
3517 PVBOXWDDM_CONTEXT pContext = (PVBOXWDDM_CONTEXT)pEscape->hContext;
3518 Status = vboxWddmSwapchainCtxEscape(pDevExt, pContext, (PVBOXDISPIFESCAPE_SWAPCHAININFO)pEscapeHdr, pEscape->PrivateDriverDataSize);
3519 Assert(Status == STATUS_SUCCESS);
3520 break;
3521 }
3522 case VBOXESC_REINITVIDEOMODES:
3523 VBoxWddmInvalidateModesTable(pDevExt);
3524 Status = STATUS_SUCCESS;
3525 break;
3526 case VBOXESC_DBGPRINT:
3527 {
3528 /* use RT_OFFSETOF instead of sizeof since sizeof will give an aligned size that might
3529 * be bigger than the VBOXDISPIFESCAPE_DBGPRINT with a data containing just a few chars */
3530 Assert(pEscape->PrivateDriverDataSize >= RT_OFFSETOF(VBOXDISPIFESCAPE_DBGPRINT, aStringBuf[1]));
3531 /* only do DbgPrint when pEscape->PrivateDriverDataSize > RT_OFFSETOF(VBOXDISPIFESCAPE_DBGPRINT, aStringBuf[1])
3532 * since == RT_OFFSETOF(VBOXDISPIFESCAPE_DBGPRINT, aStringBuf[1]) means the buffer contains just \0,
3533 * i.e. no need to print it */
3534 if (pEscape->PrivateDriverDataSize > RT_OFFSETOF(VBOXDISPIFESCAPE_DBGPRINT, aStringBuf[1]))
3535 {
3536 PVBOXDISPIFESCAPE_DBGPRINT pDbgPrint = (PVBOXDISPIFESCAPE_DBGPRINT)pEscapeHdr;
3537 /* ensure the last char is \0*/
3538 *((uint8_t*)pDbgPrint + pEscape->PrivateDriverDataSize - 1) = '\0';
3539 DbgPrint(pDbgPrint->aStringBuf);
3540 }
3541 Status = STATUS_SUCCESS;
3542 break;
3543 }
3544 default:
3545 Assert(0);
3546 drprintf((__FUNCTION__": unsupported escape code (0x%x)\n", pEscapeHdr->escapeCode));
3547 break;
3548 }
3549 }
3550 else
3551 {
3552 drprintf((__FUNCTION__": pEscape->PrivateDriverDataSize(%d) < (%d)\n", pEscape->PrivateDriverDataSize, sizeof (VBOXDISPIFESCAPE)));
3553 AssertBreakpoint();
3554 Status = STATUS_BUFFER_TOO_SMALL;
3555 }
3556
3557// dfprintf(("<== "__FUNCTION__ ", hAdapter(0x%x)\n", hAdapter));
3558
3559 return Status;
3560}
3561
3562NTSTATUS
3563APIENTRY
3564DxgkDdiCollectDbgInfo(
3565 CONST HANDLE hAdapter,
3566 CONST DXGKARG_COLLECTDBGINFO* pCollectDbgInfo
3567 )
3568{
3569 dfprintf(("==> "__FUNCTION__ ", hAdapter(0x%x)\n", hAdapter));
3570
3571 AssertBreakpoint();
3572
3573 dfprintf(("<== "__FUNCTION__ ", hAdapter(0x%x)\n", hAdapter));
3574
3575 return STATUS_SUCCESS;
3576}
3577
3578typedef struct VBOXWDDM_QUERYCURFENCE_CB
3579{
3580 PDEVICE_EXTENSION pDevExt;
3581 ULONG MessageNumber;
3582 ULONG uLastCompletedCmdFenceId;
3583} VBOXWDDM_QUERYCURFENCE_CB, *PVBOXWDDM_QUERYCURFENCE_CB;
3584
3585static BOOLEAN vboxWddmQueryCurrentFenceCb(PVOID Context)
3586{
3587 PVBOXWDDM_QUERYCURFENCE_CB pdc = (PVBOXWDDM_QUERYCURFENCE_CB)Context;
3588 BOOL bRc = DxgkDdiInterruptRoutine(pdc->pDevExt, pdc->MessageNumber);
3589 pdc->uLastCompletedCmdFenceId = pdc->pDevExt->u.primary.Vdma.uLastCompletedPagingBufferCmdFenceId;
3590 return bRc;
3591}
3592
3593NTSTATUS
3594APIENTRY
3595DxgkDdiQueryCurrentFence(
3596 CONST HANDLE hAdapter,
3597 DXGKARG_QUERYCURRENTFENCE* pCurrentFence)
3598{
3599 dfprintf(("==> "__FUNCTION__ ", hAdapter(0x%x)\n", hAdapter));
3600
3601 vboxVDbgBreakF();
3602
3603 PDEVICE_EXTENSION pDevExt = (PDEVICE_EXTENSION)hAdapter;
3604 VBOXWDDM_QUERYCURFENCE_CB context = {0};
3605 context.pDevExt = pDevExt;
3606 BOOLEAN bRet;
3607 NTSTATUS Status = pDevExt->u.primary.DxgkInterface.DxgkCbSynchronizeExecution(
3608 pDevExt->u.primary.DxgkInterface.DeviceHandle,
3609 vboxWddmQueryCurrentFenceCb,
3610 &context,
3611 0, /* IN ULONG MessageNumber */
3612 &bRet);
3613 Assert(Status == STATUS_SUCCESS);
3614 if (Status == STATUS_SUCCESS)
3615 {
3616 pCurrentFence->CurrentFence = context.uLastCompletedCmdFenceId;
3617 }
3618
3619 dfprintf(("<== "__FUNCTION__ ", hAdapter(0x%x)\n", hAdapter));
3620
3621 return STATUS_SUCCESS;
3622}
3623
3624NTSTATUS
3625APIENTRY
3626DxgkDdiIsSupportedVidPn(
3627 CONST HANDLE hAdapter,
3628 OUT DXGKARG_ISSUPPORTEDVIDPN* pIsSupportedVidPnArg
3629 )
3630{
3631 /* The DxgkDdiIsSupportedVidPn should be made pageable. */
3632 PAGED_CODE();
3633
3634 dfprintf(("==> "__FUNCTION__ ", context(0x%x)\n", hAdapter));
3635
3636 vboxVDbgBreakFv();
3637
3638 PDEVICE_EXTENSION pContext = (PDEVICE_EXTENSION)hAdapter;
3639 BOOLEAN bSupported = TRUE;
3640 const DXGK_VIDPN_INTERFACE* pVidPnInterface = NULL;
3641 NTSTATUS Status = pContext->u.primary.DxgkInterface.DxgkCbQueryVidPnInterface(pIsSupportedVidPnArg->hDesiredVidPn, DXGK_VIDPN_INTERFACE_VERSION_V1, &pVidPnInterface);
3642 if (Status == STATUS_SUCCESS)
3643 {
3644 D3DKMDT_HVIDPNTOPOLOGY hVidPnTopology;
3645 const DXGK_VIDPNTOPOLOGY_INTERFACE* pVidPnTopologyInterface;
3646 Status = pVidPnInterface->pfnGetTopology(pIsSupportedVidPnArg->hDesiredVidPn, &hVidPnTopology, &pVidPnTopologyInterface);
3647 if (Status == STATUS_SUCCESS)
3648 {
3649 Status = vboxVidPnCheckTopology(pIsSupportedVidPnArg->hDesiredVidPn, hVidPnTopology, pVidPnTopologyInterface, &bSupported);
3650 if (Status == STATUS_SUCCESS && bSupported)
3651 {
3652 for (int id = 0; id < commonFromDeviceExt(pContext)->cDisplays; ++id)
3653 {
3654 D3DKMDT_HVIDPNSOURCEMODESET hNewVidPnSourceModeSet;
3655 const DXGK_VIDPNSOURCEMODESET_INTERFACE *pVidPnSourceModeSetInterface;
3656 Status = pVidPnInterface->pfnAcquireSourceModeSet(pIsSupportedVidPnArg->hDesiredVidPn,
3657 id,
3658 &hNewVidPnSourceModeSet,
3659 &pVidPnSourceModeSetInterface);
3660 if (Status == STATUS_SUCCESS)
3661 {
3662 Status = vboxVidPnCheckSourceModeSet(pIsSupportedVidPnArg->hDesiredVidPn, hNewVidPnSourceModeSet, pVidPnSourceModeSetInterface, &bSupported);
3663
3664 pVidPnInterface->pfnReleaseSourceModeSet(pIsSupportedVidPnArg->hDesiredVidPn, hNewVidPnSourceModeSet);
3665
3666 if (Status != STATUS_SUCCESS || !bSupported)
3667 break;
3668 }
3669 else if (Status == STATUS_GRAPHICS_INVALID_VIDEO_PRESENT_SOURCE)
3670 {
3671 drprintf(("VBoxVideoWddm: Warning: pfnAcquireSourceModeSet returned STATUS_GRAPHICS_INVALID_VIDEO_PRESENT_SOURCE, continuing\n"));
3672 Status = STATUS_SUCCESS;
3673 }
3674 else
3675 {
3676 drprintf(("VBoxVideoWddm: pfnAcquireSourceModeSet failed Status(0x%x)\n"));
3677 break;
3678 }
3679 }
3680
3681 if (Status == STATUS_SUCCESS && bSupported)
3682 {
3683 for (int id = 0; id < commonFromDeviceExt(pContext)->cDisplays; ++id)
3684 {
3685 D3DKMDT_HVIDPNTARGETMODESET hNewVidPnTargetModeSet;
3686 CONST DXGK_VIDPNTARGETMODESET_INTERFACE *pVidPnTargetModeSetInterface;
3687 Status = pVidPnInterface->pfnAcquireTargetModeSet(pIsSupportedVidPnArg->hDesiredVidPn,
3688 id, /*__in CONST D3DDDI_VIDEO_PRESENT_SOURCE_ID VidPnSourceId */
3689 &hNewVidPnTargetModeSet,
3690 &pVidPnTargetModeSetInterface);
3691 if (Status == STATUS_SUCCESS)
3692 {
3693 Status = vboxVidPnCheckTargetModeSet(pIsSupportedVidPnArg->hDesiredVidPn, hNewVidPnTargetModeSet, pVidPnTargetModeSetInterface, &bSupported);
3694
3695 pVidPnInterface->pfnReleaseTargetModeSet(pIsSupportedVidPnArg->hDesiredVidPn, hNewVidPnTargetModeSet);
3696
3697 if (Status != STATUS_SUCCESS || !bSupported)
3698 break;
3699 }
3700 else if (Status == STATUS_GRAPHICS_INVALID_VIDEO_PRESENT_SOURCE)
3701 {
3702 drprintf(("VBoxVideoWddm: Warning: pfnAcquireSourceModeSet returned STATUS_GRAPHICS_INVALID_VIDEO_PRESENT_SOURCE, continuing\n"));
3703 Status = STATUS_SUCCESS;
3704 }
3705 else
3706 {
3707 drprintf(("VBoxVideoWddm: pfnAcquireSourceModeSet failed Status(0x%x)\n"));
3708 break;
3709 }
3710 }
3711 }
3712 }
3713 }
3714 else
3715 {
3716 drprintf(("VBoxVideoWddm: pfnGetTopology failed Status(0x%x)\n"));
3717 }
3718 }
3719 else
3720 {
3721 drprintf(("VBoxVideoWddm: DxgkCbQueryVidPnInterface failed Status(0x%x)\n"));
3722 }
3723 pIsSupportedVidPnArg->IsVidPnSupported = bSupported;
3724
3725 dfprintf(("<== "__FUNCTION__ ", status(0x%x), context(0x%x)\n", Status, hAdapter));
3726
3727 return Status;
3728}
3729
3730NTSTATUS
3731APIENTRY
3732DxgkDdiRecommendFunctionalVidPn(
3733 CONST HANDLE hAdapter,
3734 CONST DXGKARG_RECOMMENDFUNCTIONALVIDPN* CONST pRecommendFunctionalVidPnArg
3735 )
3736{
3737 /* The DxgkDdiRecommendFunctionalVidPn should be made pageable. */
3738 PAGED_CODE();
3739
3740 dfprintf(("==> "__FUNCTION__ ", context(0x%x)\n", hAdapter));
3741
3742 vboxVDbgBreakF();
3743
3744 PDEVICE_EXTENSION pDevExt = (PDEVICE_EXTENSION)hAdapter;
3745 NTSTATUS Status;
3746 uint32_t cModes;
3747 int iPreferredMode;
3748 VIDEO_MODE_INFORMATION *pModes;
3749 uint32_t cResolutions;
3750 D3DKMDT_2DREGION *pResolutions;
3751 VIDEO_MODE_INFORMATION ModeInfos[4];
3752 VIDEO_MODE_INFORMATION *pModeInfos;
3753 D3DKMDT_2DREGION Resolution;
3754 uint32_t cModeInfos;
3755 int32_t iPreferredModeInfo;
3756 bool bFreeModes = false;
3757 VBoxWddmGetModesTable(pDevExt, /* PDEVICE_EXTENSION DeviceExtension */
3758 true, /* bool bRebuildTable*/
3759 &pModes, /* VIDEO_MODE_INFORMATION ** ppModes*/
3760 &cModes, /* uint32_t * pcModes */
3761 &iPreferredMode, /* uint32_t * pPreferrableMode*/
3762 &pResolutions, /* D3DKMDT_2DREGION **ppResolutions */
3763 &cResolutions /* uint32_t * pcResolutions */);
3764 Resolution.cx = pModes[iPreferredMode].VisScreenWidth;
3765 Resolution.cy = pModes[iPreferredMode].VisScreenHeight;
3766 Status = VBoxWddmGetModesForResolution(pDevExt, false,
3767 &Resolution,
3768 ModeInfos, RT_ELEMENTS(ModeInfos), &cModeInfos, &iPreferredModeInfo);
3769 Assert(Status == STATUS_SUCCESS || Status == STATUS_BUFFER_TOO_SMALL);
3770 if (Status == STATUS_SUCCESS)
3771 pModeInfos = ModeInfos;
3772 else if (Status == STATUS_BUFFER_TOO_SMALL)
3773 {
3774 uint32_t cModeInfos2;
3775 pModeInfos = (VIDEO_MODE_INFORMATION*)vboxWddmMemAlloc(sizeof (VIDEO_MODE_INFORMATION) * cModeInfos);
3776 if (pModeInfos)
3777 {
3778 bFreeModes = true;
3779 Status = VBoxWddmGetModesForResolution(pDevExt, false,
3780 &Resolution,
3781 pModeInfos, cModeInfos, &cModeInfos2, &iPreferredModeInfo);
3782 Assert(Status == STATUS_SUCCESS);
3783 Assert(iPreferredModeInfo >= 0); /* the array should contain the preferred info */
3784 if (Status != STATUS_SUCCESS)
3785 drprintf((__FUNCTION__": second call to VBoxWddmGetModesForResolution failed Status(0x%x), cModeInfos(%d), cModeInfos2(%d)\n", Status, cModeInfos, cModeInfos2));
3786 }
3787 }
3788 else
3789 drprintf((__FUNCTION__": VBoxWddmGetModesForResolution failed Status(0x%x)\n", Status));
3790
3791 if (Status == STATUS_SUCCESS)
3792 {
3793 for (int i = 0; i < commonFromDeviceExt(pDevExt)->cDisplays; ++i)
3794 {
3795 Status = vboxVidPnCheckAddMonitorModes(pDevExt, i, D3DKMDT_MCO_DRIVER, &Resolution, 1, 0);
3796 Assert(Status == STATUS_SUCCESS);
3797 if (Status != STATUS_SUCCESS)
3798 {
3799 drprintf((__FUNCTION__": vboxVidPnCheckAddMonitorModes failed Status(0x%x)\n", Status));
3800 break;
3801 }
3802 }
3803
3804 if (Status == STATUS_SUCCESS)
3805 {
3806 const DXGK_VIDPN_INTERFACE* pVidPnInterface = NULL;
3807 Status = pDevExt->u.primary.DxgkInterface.DxgkCbQueryVidPnInterface(pRecommendFunctionalVidPnArg->hRecommendedFunctionalVidPn, DXGK_VIDPN_INTERFACE_VERSION_V1, &pVidPnInterface);
3808 Assert(Status == STATUS_SUCCESS);
3809 if (Status == STATUS_SUCCESS)
3810 {
3811 Assert (iPreferredModeInfo >= 0);
3812 Status = vboxVidPnCreatePopulateVidPnFromLegacy(pDevExt, pRecommendFunctionalVidPnArg->hRecommendedFunctionalVidPn, pVidPnInterface,
3813 pModeInfos, cModeInfos, iPreferredModeInfo,
3814 &Resolution, 1);
3815 Assert(Status == STATUS_SUCCESS);
3816 if (Status != STATUS_SUCCESS)
3817 drprintf((__FUNCTION__": vboxVidPnCreatePopulateVidPnFromLegacy failed Status(0x%x)\n", Status));
3818 }
3819 else
3820 drprintf((__FUNCTION__": DxgkCbQueryVidPnInterface failed Status(0x%x)\n", Status));
3821 }
3822 }
3823
3824 if (bFreeModes)
3825 vboxWddmMemFree(pModeInfos);
3826
3827 dfprintf(("<== "__FUNCTION__ ", status(0x%x), context(0x%x)\n", Status, hAdapter));
3828
3829 return Status;
3830}
3831
3832NTSTATUS
3833APIENTRY
3834DxgkDdiEnumVidPnCofuncModality(
3835 CONST HANDLE hAdapter,
3836 CONST DXGKARG_ENUMVIDPNCOFUNCMODALITY* CONST pEnumCofuncModalityArg
3837 )
3838{
3839 /* The DxgkDdiEnumVidPnCofuncModality function should be made pageable. */
3840 PAGED_CODE();
3841
3842 dfprintf(("==> "__FUNCTION__ ", context(0x%x)\n", hAdapter));
3843
3844 vboxVDbgBreakFv();
3845
3846 PDEVICE_EXTENSION pContext = (PDEVICE_EXTENSION)hAdapter;
3847 const DXGK_VIDPN_INTERFACE* pVidPnInterface = NULL;
3848 NTSTATUS Status = pContext->u.primary.DxgkInterface.DxgkCbQueryVidPnInterface(pEnumCofuncModalityArg->hConstrainingVidPn, DXGK_VIDPN_INTERFACE_VERSION_V1, &pVidPnInterface);
3849 if (Status == STATUS_SUCCESS)
3850 {
3851 D3DKMDT_HVIDPNTOPOLOGY hVidPnTopology;
3852 const DXGK_VIDPNTOPOLOGY_INTERFACE* pVidPnTopologyInterface;
3853 NTSTATUS Status = pVidPnInterface->pfnGetTopology(pEnumCofuncModalityArg->hConstrainingVidPn, &hVidPnTopology, &pVidPnTopologyInterface);
3854 Assert(Status == STATUS_SUCCESS);
3855 if (Status == STATUS_SUCCESS)
3856 {
3857 VBOXVIDPNCOFUNCMODALITY CbContext = {0};
3858 CbContext.pEnumCofuncModalityArg = pEnumCofuncModalityArg;
3859 VBoxWddmGetModesTable(pContext, /* PDEVICE_EXTENSION DeviceExtension */
3860 false, /* bool bRebuildTable*/
3861 &CbContext.pModes, /* VIDEO_MODE_INFORMATION ** ppModes*/
3862 &CbContext.cModes, /* uint32_t * pcModes */
3863 &CbContext.iPreferredMode, /* uint32_t * pPreferrableMode*/
3864 &CbContext.pResolutions, /* D3DKMDT_2DREGION **ppResolutions */
3865 &CbContext.cResolutions /* uint32_t * pcResolutions */);
3866 Assert(CbContext.cModes);
3867 Assert(CbContext.cModes > (uint32_t)CbContext.iPreferredMode);
3868 CbContext.iPreferredMode = -1; /* <- we do not want the modes to be pinned */
3869 Status = vboxVidPnEnumPaths(pContext, pEnumCofuncModalityArg->hConstrainingVidPn, pVidPnInterface,
3870 hVidPnTopology, pVidPnTopologyInterface,
3871 vboxVidPnCofuncModalityPathEnum, &CbContext);
3872 Assert(Status == STATUS_SUCCESS);
3873 if (Status == STATUS_SUCCESS)
3874 {
3875 Status = CbContext.Status;
3876 Assert(Status == STATUS_SUCCESS);
3877 if (Status != STATUS_SUCCESS)
3878 drprintf((__FUNCTION__ ": vboxVidPnAdjustSourcesTargetsCallback failed Status(0x%x)\n", Status));
3879 }
3880 else
3881 drprintf((__FUNCTION__ ": vboxVidPnEnumPaths failed Status(0x%x)\n", Status));
3882 }
3883 else
3884 drprintf((__FUNCTION__ ": pfnGetTopology failed Status(0x%x)\n", Status));
3885 }
3886 else
3887 drprintf((__FUNCTION__ ": DxgkCbQueryVidPnInterface failed Status(0x%x)\n", Status));
3888
3889 dfprintf(("<== "__FUNCTION__ ", status(0x%x), context(0x%x)\n", Status, hAdapter));
3890
3891 return Status;
3892}
3893
3894NTSTATUS
3895APIENTRY
3896DxgkDdiSetVidPnSourceAddress(
3897 CONST HANDLE hAdapter,
3898 CONST DXGKARG_SETVIDPNSOURCEADDRESS* pSetVidPnSourceAddress
3899 )
3900{
3901 /* The DxgkDdiSetVidPnSourceAddress function should be made pageable. */
3902 PAGED_CODE();
3903
3904 vboxVDbgBreakFv();
3905
3906 dfprintf(("==> "__FUNCTION__ ", context(0x%x)\n", hAdapter));
3907
3908 NTSTATUS Status = STATUS_SUCCESS;
3909 PDEVICE_EXTENSION pDevExt = (PDEVICE_EXTENSION)hAdapter;
3910 Assert((UINT)commonFromDeviceExt(pDevExt)->cDisplays > pSetVidPnSourceAddress->VidPnSourceId);
3911
3912 PVBOXWDDM_SOURCE pSource = &pDevExt->aSources[pSetVidPnSourceAddress->VidPnSourceId];
3913 Status= vboxWddmDisplaySettingsQueryPos(pDevExt, pSetVidPnSourceAddress->VidPnSourceId, &pSource->VScreenPos);
3914 Assert(Status == STATUS_SUCCESS);
3915 Status = STATUS_SUCCESS;
3916
3917 if ((UINT)commonFromDeviceExt(pDevExt)->cDisplays > pSetVidPnSourceAddress->VidPnSourceId)
3918 {
3919 PVBOXWDDM_ALLOCATION pAllocation;
3920 Assert(pSetVidPnSourceAddress->hAllocation);
3921 Assert(pSetVidPnSourceAddress->hAllocation || pSource->pPrimaryAllocation);
3922 Assert (pSetVidPnSourceAddress->Flags.Value < 2); /* i.e. 0 or 1 (ModeChange) */
3923 if (pSetVidPnSourceAddress->hAllocation)
3924 {
3925 pAllocation = (PVBOXWDDM_ALLOCATION)pSetVidPnSourceAddress->hAllocation;
3926 vboxWddmAssignPrimary(pDevExt, pSource, pAllocation, pSetVidPnSourceAddress->VidPnSourceId);
3927 }
3928 else
3929 pAllocation = pSource->pPrimaryAllocation;
3930
3931 Assert(pAllocation);
3932 if (pAllocation)
3933 {
3934// Assert(pAllocation->enmType == VBOXWDDM_ALLOC_TYPE_STD_SHAREDPRIMARYSURFACE);
3935 pAllocation->offVram = (VBOXVIDEOOFFSET)pSetVidPnSourceAddress->PrimaryAddress.QuadPart;
3936 pAllocation->SegmentId = pSetVidPnSourceAddress->PrimarySegment;
3937 Assert (pAllocation->SegmentId);
3938 Assert (!pAllocation->bVisible);
3939 Assert(pAllocation->enmType == VBOXWDDM_ALLOC_TYPE_STD_SHAREDPRIMARYSURFACE
3940 || pAllocation->enmType == VBOXWDDM_ALLOC_TYPE_UMD_RC_GENERIC);
3941
3942 if (
3943#ifdef VBOXWDDM_RENDER_FROM_SHADOW
3944 /* this is the case of full-screen d3d, ensure we notify host */
3945 pAllocation->enmType == VBOXWDDM_ALLOC_TYPE_UMD_RC_GENERIC &&
3946#endif
3947 pAllocation->bVisible)
3948 {
3949#ifdef VBOXWDDM_RENDER_FROM_SHADOW
3950 /* to ensure the resize request gets issued in case we exit a full-screen D3D mode */
3951 pSource->offVram = VBOXVIDEOOFFSET_VOID;
3952#else
3953 /* should not generally happen, but still inform host*/
3954 Status = vboxWddmGhDisplaySetInfo(pDevExt, pSource, pSetVidPnSourceAddress->VidPnSourceId);
3955 Assert(Status == STATUS_SUCCESS);
3956 if (Status != STATUS_SUCCESS)
3957 drprintf((__FUNCTION__": vboxWddmGhDisplaySetInfo failed, Status (0x%x)\n", Status));
3958#endif
3959 }
3960 }
3961 else
3962 {
3963 drprintf((__FUNCTION__": no allocation data available!!\n"));
3964 Status = STATUS_INVALID_PARAMETER;
3965 }
3966 }
3967 else
3968 {
3969 drprintf((__FUNCTION__": invalid VidPnSourceId (%d), should be smaller than (%d)\n", pSetVidPnSourceAddress->VidPnSourceId, commonFromDeviceExt(pDevExt)->cDisplays));
3970 Status = STATUS_INVALID_PARAMETER;
3971 }
3972
3973 dfprintf(("<== "__FUNCTION__ ", status(0x%x), context(0x%x)\n", Status, hAdapter));
3974
3975 return Status;
3976}
3977
3978NTSTATUS
3979APIENTRY
3980DxgkDdiSetVidPnSourceVisibility(
3981 CONST HANDLE hAdapter,
3982 CONST DXGKARG_SETVIDPNSOURCEVISIBILITY* pSetVidPnSourceVisibility
3983 )
3984{
3985 /* DxgkDdiSetVidPnSourceVisibility should be made pageable. */
3986 PAGED_CODE();
3987
3988 vboxVDbgBreakFv();
3989
3990 dfprintf(("==> "__FUNCTION__ ", context(0x%x)\n", hAdapter));
3991
3992 NTSTATUS Status = STATUS_SUCCESS;
3993 PDEVICE_EXTENSION pDevExt = (PDEVICE_EXTENSION)hAdapter;
3994 Assert((UINT)commonFromDeviceExt(pDevExt)->cDisplays > pSetVidPnSourceVisibility->VidPnSourceId);
3995
3996 PVBOXWDDM_SOURCE pSource = &pDevExt->aSources[pSetVidPnSourceVisibility->VidPnSourceId];
3997 Status= vboxWddmDisplaySettingsQueryPos(pDevExt, pSetVidPnSourceVisibility->VidPnSourceId, &pSource->VScreenPos);
3998 Assert(Status == STATUS_SUCCESS);
3999 Status = STATUS_SUCCESS;
4000
4001 if ((UINT)commonFromDeviceExt(pDevExt)->cDisplays > pSetVidPnSourceVisibility->VidPnSourceId)
4002 {
4003 PVBOXWDDM_ALLOCATION pAllocation = pSource->pPrimaryAllocation;
4004 if (pAllocation)
4005 {
4006 Assert(pAllocation->enmType == VBOXWDDM_ALLOC_TYPE_STD_SHAREDPRIMARYSURFACE
4007 || pAllocation->enmType == VBOXWDDM_ALLOC_TYPE_UMD_RC_GENERIC);
4008
4009 Assert(pAllocation->bVisible != pSetVidPnSourceVisibility->Visible);
4010 if (pAllocation->bVisible != pSetVidPnSourceVisibility->Visible)
4011 {
4012 pAllocation->bVisible = pSetVidPnSourceVisibility->Visible;
4013 if (pAllocation->bVisible)
4014 {
4015#ifdef VBOXWDDM_RENDER_FROM_SHADOW
4016 if (/* this is the case of full-screen d3d, ensure we notify host */
4017 pAllocation->enmType == VBOXWDDM_ALLOC_TYPE_UMD_RC_GENERIC
4018 )
4019#endif
4020 {
4021#ifdef VBOXWDDM_RENDER_FROM_SHADOW
4022 /* to ensure the resize request gets issued in case we exit a full-screen D3D mode */
4023 pSource->offVram = VBOXVIDEOOFFSET_VOID;
4024#else
4025 Status = vboxWddmGhDisplaySetInfo(pDevExt, pSource, pSetVidPnSourceVisibility->VidPnSourceId);
4026 Assert(Status == STATUS_SUCCESS);
4027 if (Status != STATUS_SUCCESS)
4028 drprintf((__FUNCTION__": vboxWddmGhDisplaySetInfo failed, Status (0x%x)\n", Status));
4029#endif
4030 }
4031 }
4032#ifdef VBOX_WITH_VDMA
4033 else
4034 {
4035 vboxVdmaFlush (pDevExt, &pDevExt->u.primary.Vdma);
4036 }
4037#endif
4038 }
4039 }
4040 else
4041 {
4042 Assert(!pSetVidPnSourceVisibility->Visible);
4043 }
4044 }
4045 else
4046 {
4047 drprintf((__FUNCTION__": invalid VidPnSourceId (%d), should be smaller than (%d)\n", pSetVidPnSourceVisibility->VidPnSourceId, commonFromDeviceExt(pDevExt)->cDisplays));
4048 Status = STATUS_INVALID_PARAMETER;
4049 }
4050
4051 dfprintf(("<== "__FUNCTION__ ", status(0x%x), context(0x%x)\n", Status, hAdapter));
4052
4053 return Status;
4054}
4055
4056NTSTATUS
4057APIENTRY
4058DxgkDdiCommitVidPn(
4059 CONST HANDLE hAdapter,
4060 CONST DXGKARG_COMMITVIDPN* CONST pCommitVidPnArg
4061 )
4062{
4063 dfprintf(("==> "__FUNCTION__ ", context(0x%x)\n", hAdapter));
4064
4065 PDEVICE_EXTENSION pDevExt = (PDEVICE_EXTENSION)hAdapter;
4066
4067 vboxVDbgBreakFv();
4068
4069 const DXGK_VIDPN_INTERFACE* pVidPnInterface = NULL;
4070 NTSTATUS Status = pDevExt->u.primary.DxgkInterface.DxgkCbQueryVidPnInterface(pCommitVidPnArg->hFunctionalVidPn, DXGK_VIDPN_INTERFACE_VERSION_V1, &pVidPnInterface);
4071 if (Status == STATUS_SUCCESS)
4072 {
4073 if (pCommitVidPnArg->AffectedVidPnSourceId != D3DDDI_ID_ALL)
4074 {
4075 Status = vboxVidPnCommitSourceModeForSrcId(
4076 pDevExt,
4077 pCommitVidPnArg->hFunctionalVidPn, pVidPnInterface,
4078 pCommitVidPnArg->AffectedVidPnSourceId, (PVBOXWDDM_ALLOCATION)pCommitVidPnArg->hPrimaryAllocation);
4079 Assert(Status == STATUS_SUCCESS);
4080 if (Status != STATUS_SUCCESS)
4081 drprintf((__FUNCTION__ ": vboxVidPnCommitSourceModeForSrcId failed Status(0x%x)\n", Status));
4082 }
4083 else
4084 {
4085 /* clear all current primaries */
4086 for (int i = 0; i < commonFromDeviceExt(pDevExt)->cDisplays; ++i)
4087 {
4088 vboxWddmAssignPrimary(pDevExt, &pDevExt->aSources[i], NULL, i);
4089 }
4090
4091 D3DKMDT_HVIDPNTOPOLOGY hVidPnTopology;
4092 const DXGK_VIDPNTOPOLOGY_INTERFACE* pVidPnTopologyInterface;
4093 NTSTATUS Status = pVidPnInterface->pfnGetTopology(pCommitVidPnArg->hFunctionalVidPn, &hVidPnTopology, &pVidPnTopologyInterface);
4094 Assert(Status == STATUS_SUCCESS);
4095 if (Status == STATUS_SUCCESS)
4096 {
4097 VBOXVIDPNCOMMIT CbContext = {0};
4098 CbContext.pCommitVidPnArg = pCommitVidPnArg;
4099 Status = vboxVidPnEnumPaths(pDevExt, pCommitVidPnArg->hFunctionalVidPn, pVidPnInterface,
4100 hVidPnTopology, pVidPnTopologyInterface,
4101 vboxVidPnCommitPathEnum, &CbContext);
4102 Assert(Status == STATUS_SUCCESS);
4103 if (Status == STATUS_SUCCESS)
4104 {
4105 Status = CbContext.Status;
4106 Assert(Status == STATUS_SUCCESS);
4107 if (Status != STATUS_SUCCESS)
4108 drprintf((__FUNCTION__ ": vboxVidPnCommitPathEnum failed Status(0x%x)\n", Status));
4109 }
4110 else
4111 drprintf((__FUNCTION__ ": vboxVidPnEnumPaths failed Status(0x%x)\n", Status));
4112 }
4113 else
4114 drprintf((__FUNCTION__ ": pfnGetTopology failed Status(0x%x)\n", Status));
4115 }
4116
4117 if (Status == STATUS_SUCCESS)
4118 {
4119 pDevExt->u.primary.hCommittedVidPn = pCommitVidPnArg->hFunctionalVidPn;
4120 }
4121 }
4122 else
4123 drprintf((__FUNCTION__ ": DxgkCbQueryVidPnInterface failed Status(0x%x)\n", Status));
4124
4125 dfprintf(("<== "__FUNCTION__ ", status(0x%x), context(0x%x)\n", Status, hAdapter));
4126
4127 return Status;
4128}
4129
4130NTSTATUS
4131APIENTRY
4132DxgkDdiUpdateActiveVidPnPresentPath(
4133 CONST HANDLE hAdapter,
4134 CONST DXGKARG_UPDATEACTIVEVIDPNPRESENTPATH* CONST pUpdateActiveVidPnPresentPathArg
4135 )
4136{
4137 dfprintf(("==> "__FUNCTION__ ", hAdapter(0x%x)\n", hAdapter));
4138
4139 AssertBreakpoint();
4140
4141 dfprintf(("<== "__FUNCTION__ ", hAdapter(0x%x)\n", hAdapter));
4142
4143 return STATUS_SUCCESS;
4144}
4145
4146NTSTATUS
4147APIENTRY
4148DxgkDdiRecommendMonitorModes(
4149 CONST HANDLE hAdapter,
4150 CONST DXGKARG_RECOMMENDMONITORMODES* CONST pRecommendMonitorModesArg
4151 )
4152{
4153 dfprintf(("==> "__FUNCTION__ ", hAdapter(0x%x)\n", hAdapter));
4154
4155 vboxVDbgBreakFv();
4156
4157 PDEVICE_EXTENSION pDevExt = (PDEVICE_EXTENSION)hAdapter;
4158 NTSTATUS Status;
4159 uint32_t cModes;
4160 int32_t iPreferredMode;
4161 VIDEO_MODE_INFORMATION *pModes;
4162 uint32_t cResolutions;
4163 D3DKMDT_2DREGION *pResolutions;
4164 VBoxWddmGetModesTable(pDevExt, /* PDEVICE_EXTENSION DeviceExtension */
4165 false, /* bool bRebuildTable*/
4166 &pModes, /* VIDEO_MODE_INFORMATION ** ppModes*/
4167 &cModes, /* uint32_t * pcModes */
4168 &iPreferredMode, /* uint32_t * pPreferrableMode*/
4169 &pResolutions, /* D3DKMDT_2DREGION **ppResolutions */
4170 &cResolutions /* uint32_t * pcResolutions */);
4171
4172 for (uint32_t i = 0; i < cResolutions; i++)
4173 {
4174 D3DKMDT_MONITOR_SOURCE_MODE * pNewMonitorSourceModeInfo;
4175 Status = pRecommendMonitorModesArg->pMonitorSourceModeSetInterface->pfnCreateNewModeInfo(
4176 pRecommendMonitorModesArg->hMonitorSourceModeSet, &pNewMonitorSourceModeInfo);
4177 Assert(Status == STATUS_SUCCESS);
4178 if (Status == STATUS_SUCCESS)
4179 {
4180 Status = vboxVidPnPopulateMonitorSourceModeInfoFromLegacy(pDevExt,
4181 pNewMonitorSourceModeInfo,
4182 &pResolutions[i],
4183 D3DKMDT_MCO_DRIVER,
4184 FALSE);
4185 Assert(Status == STATUS_SUCCESS);
4186 if (Status == STATUS_SUCCESS)
4187 {
4188 Status = pRecommendMonitorModesArg->pMonitorSourceModeSetInterface->pfnAddMode(
4189 pRecommendMonitorModesArg->hMonitorSourceModeSet, pNewMonitorSourceModeInfo);
4190 Assert(Status == STATUS_SUCCESS);
4191 if (Status == STATUS_SUCCESS)
4192 continue;
4193 }
4194
4195 /* error has occurred, release & break */
4196 pRecommendMonitorModesArg->pMonitorSourceModeSetInterface->pfnReleaseModeInfo(
4197 pRecommendMonitorModesArg->hMonitorSourceModeSet, pNewMonitorSourceModeInfo);
4198 break;
4199 }
4200 }
4201
4202 dfprintf(("<== "__FUNCTION__ ", hAdapter(0x%x)\n", hAdapter));
4203
4204 return Status;
4205}
4206
4207NTSTATUS
4208APIENTRY
4209DxgkDdiRecommendVidPnTopology(
4210 CONST HANDLE hAdapter,
4211 CONST DXGKARG_RECOMMENDVIDPNTOPOLOGY* CONST pRecommendVidPnTopologyArg
4212 )
4213{
4214 dfprintf(("==> "__FUNCTION__ ", hAdapter(0x%x)\n", hAdapter));
4215
4216 vboxVDbgBreakFv();
4217
4218 dfprintf(("<== "__FUNCTION__ ", hAdapter(0x%x)\n", hAdapter));
4219
4220 return STATUS_GRAPHICS_NO_RECOMMENDED_VIDPN_TOPOLOGY;
4221}
4222
4223NTSTATUS
4224APIENTRY
4225DxgkDdiGetScanLine(
4226 CONST HANDLE hAdapter,
4227 DXGKARG_GETSCANLINE* pGetScanLine)
4228{
4229 dfprintf(("==> "__FUNCTION__ ", hAdapter(0x%x)\n", hAdapter));
4230
4231 PDEVICE_EXTENSION pDevExt = (PDEVICE_EXTENSION)hAdapter;
4232
4233 Assert((UINT)commonFromDeviceExt(pDevExt)->cDisplays > pGetScanLine->VidPnTargetId);
4234 VBOXWDDM_TARGET *pTarget = &pDevExt->aTargets[pGetScanLine->VidPnTargetId];
4235 Assert(pTarget->HeightTotal);
4236 Assert(pTarget->HeightVisible);
4237 Assert(pTarget->HeightTotal > pTarget->HeightVisible);
4238 Assert(pTarget->ScanLineState < pTarget->HeightTotal);
4239 if (pTarget->HeightTotal)
4240 {
4241 uint32_t curScanLine = pTarget->ScanLineState;
4242 ++pTarget->ScanLineState;
4243 if (pTarget->ScanLineState >= pTarget->HeightTotal)
4244 pTarget->ScanLineState = 0;
4245
4246
4247 BOOL bVBlank = (!curScanLine || curScanLine > pTarget->HeightVisible);
4248 pGetScanLine->ScanLine = curScanLine;
4249 pGetScanLine->InVerticalBlank = bVBlank;
4250 }
4251 else
4252 {
4253 pGetScanLine->InVerticalBlank = TRUE;
4254 pGetScanLine->ScanLine = 0;
4255 }
4256
4257 dfprintf(("<== "__FUNCTION__ ", hAdapter(0x%x)\n", hAdapter));
4258
4259 return STATUS_SUCCESS;
4260}
4261
4262NTSTATUS
4263APIENTRY
4264DxgkDdiStopCapture(
4265 CONST HANDLE hAdapter,
4266 CONST DXGKARG_STOPCAPTURE* pStopCapture)
4267{
4268 dfprintf(("==> "__FUNCTION__ ", hAdapter(0x%x)\n", hAdapter));
4269
4270 AssertBreakpoint();
4271
4272 dfprintf(("<== "__FUNCTION__ ", hAdapter(0x%x)\n", hAdapter));
4273
4274 return STATUS_SUCCESS;
4275}
4276
4277NTSTATUS
4278APIENTRY
4279DxgkDdiControlInterrupt(
4280 CONST HANDLE hAdapter,
4281 CONST DXGK_INTERRUPT_TYPE InterruptType,
4282 BOOLEAN Enable
4283 )
4284{
4285 dfprintf(("==> "__FUNCTION__ ", hAdapter(0x%x)\n", hAdapter));
4286
4287// AssertBreakpoint();
4288
4289 dfprintf(("<== "__FUNCTION__ ", hAdapter(0x%x)\n", hAdapter));
4290
4291 /* @todo: STATUS_NOT_IMPLEMENTED ?? */
4292 return STATUS_SUCCESS;
4293}
4294
4295NTSTATUS
4296APIENTRY
4297DxgkDdiCreateOverlay(
4298 CONST HANDLE hAdapter,
4299 DXGKARG_CREATEOVERLAY *pCreateOverlay)
4300{
4301 dfprintf(("==> "__FUNCTION__ ", hAdapter(0x%p)\n", hAdapter));
4302
4303 NTSTATUS Status = STATUS_SUCCESS;
4304 PDEVICE_EXTENSION pDevExt = (PDEVICE_EXTENSION)hAdapter;
4305 PVBOXWDDM_OVERLAY pOverlay = (PVBOXWDDM_OVERLAY)vboxWddmMemAllocZero(sizeof (VBOXWDDM_OVERLAY));
4306 Assert(pOverlay);
4307 if (pOverlay)
4308 {
4309 int rc = vboxVhwaHlpOverlayCreate(pDevExt, pCreateOverlay->VidPnSourceId, &pCreateOverlay->OverlayInfo, pOverlay);
4310 AssertRC(rc);
4311 if (RT_SUCCESS(rc))
4312 {
4313 vboxVhwaHlpOverlayListAdd(pDevExt, pOverlay);
4314#ifdef VBOXWDDM_RENDER_FROM_SHADOW
4315 RECT DstRect;
4316 vboxVhwaHlpOverlayDstRectGet(pDevExt, pOverlay, &DstRect);
4317 Status = vboxVdmaHlpUpdatePrimary(pDevExt, pCreateOverlay->VidPnSourceId, &DstRect);
4318 Assert(Status == STATUS_SUCCESS);
4319 /* ignore primary update failure */
4320 Status = STATUS_SUCCESS;
4321#endif
4322 pCreateOverlay->hOverlay = pOverlay;
4323 }
4324 else
4325 {
4326 vboxWddmMemFree(pOverlay);
4327 Status = STATUS_UNSUCCESSFUL;
4328 }
4329 }
4330 else
4331 Status = STATUS_NO_MEMORY;
4332
4333 dfprintf(("<== "__FUNCTION__ ", hAdapter(0x%p)\n", hAdapter));
4334
4335 return Status;
4336}
4337
4338NTSTATUS
4339APIENTRY
4340DxgkDdiDestroyDevice(
4341 CONST HANDLE hDevice)
4342{
4343 /* DxgkDdiDestroyDevice should be made pageable. */
4344 PAGED_CODE();
4345
4346 dfprintf(("==> "__FUNCTION__ ", hDevice(0x%x)\n", hDevice));
4347
4348 vboxVDbgBreakFv();
4349
4350 vboxWddmMemFree(hDevice);
4351
4352 dfprintf(("<== "__FUNCTION__ ", \n"));
4353
4354 return STATUS_SUCCESS;
4355}
4356
4357/*
4358 * DxgkDdiOpenAllocation
4359 */
4360NTSTATUS
4361APIENTRY
4362DxgkDdiOpenAllocation(
4363 CONST HANDLE hDevice,
4364 CONST DXGKARG_OPENALLOCATION *pOpenAllocation)
4365{
4366 /* DxgkDdiOpenAllocation should be made pageable. */
4367 PAGED_CODE();
4368
4369 dfprintf(("==> "__FUNCTION__ ", hDevice(0x%x)\n", hDevice));
4370
4371 vboxVDbgBreakFv();
4372
4373 NTSTATUS Status = STATUS_SUCCESS;
4374 PVBOXWDDM_DEVICE pDevice = (PVBOXWDDM_DEVICE)hDevice;
4375 PDEVICE_EXTENSION pDevExt = pDevice->pAdapter;
4376 PVBOXWDDM_RCINFO pRcInfo = NULL;
4377 if (pOpenAllocation->PrivateDriverSize)
4378 {
4379 Assert(pOpenAllocation->PrivateDriverSize == sizeof (VBOXWDDM_RCINFO));
4380 Assert(pOpenAllocation->pPrivateDriverData);
4381 if (pOpenAllocation->PrivateDriverSize >= sizeof (VBOXWDDM_RCINFO))
4382 {
4383 pRcInfo = (PVBOXWDDM_RCINFO)pOpenAllocation->pPrivateDriverData;
4384 Assert(pRcInfo->cAllocInfos == pOpenAllocation->NumAllocations);
4385 }
4386 else
4387 Status = STATUS_INVALID_PARAMETER;
4388 }
4389
4390 if (Status == STATUS_SUCCESS)
4391 {
4392 for (UINT i = 0; i < pOpenAllocation->NumAllocations; ++i)
4393 {
4394 DXGK_OPENALLOCATIONINFO* pInfo = &pOpenAllocation->pOpenAllocation[i];
4395 Assert(pInfo->PrivateDriverDataSize == sizeof (VBOXWDDM_ALLOCINFO));
4396 Assert(pInfo->pPrivateDriverData);
4397 PVBOXWDDM_OPENALLOCATION pOa = (PVBOXWDDM_OPENALLOCATION)vboxWddmMemAllocZero(sizeof (VBOXWDDM_OPENALLOCATION));
4398 pOa->hAllocation = pInfo->hAllocation;
4399 pInfo->hDeviceSpecificAllocation = pOa;
4400
4401 if (pRcInfo)
4402 {
4403#ifdef VBOX_WITH_VIDEOHWACCEL
4404 if (pRcInfo->RcDesc.fFlags.Overlay)
4405 {
4406 if (pInfo->PrivateDriverDataSize >= sizeof (VBOXWDDM_ALLOCINFO))
4407 {
4408 PVBOXWDDM_ALLOCINFO pAllocInfo = (PVBOXWDDM_ALLOCINFO)pInfo->pPrivateDriverData;
4409 PVBOXWDDM_ALLOCATION pAllocation = vboxWddmGetAllocationFromOpenData(pDevExt, pOa);
4410 Assert(pAllocation);
4411 if (pAllocation)
4412 {
4413 /* we have queried host for some surface info, like pitch & size,
4414 * need to return it back to the UMD (User Mode Drive) */
4415 pAllocInfo->SurfDesc = pAllocation->SurfDesc;
4416 /* success, just continue */
4417 continue;
4418 }
4419 else
4420 Status = STATUS_INVALID_PARAMETER;
4421 }
4422 else
4423 Status = STATUS_INVALID_PARAMETER;
4424
4425 /* we are here in case of error */
4426 AssertBreakpoint();
4427
4428 for (UINT j = 0; j < i; ++j)
4429 {
4430 DXGK_OPENALLOCATIONINFO* pInfo2Free = &pOpenAllocation->pOpenAllocation[j];
4431 PVBOXWDDM_OPENALLOCATION pOa2Free = (PVBOXWDDM_OPENALLOCATION)pInfo2Free->hDeviceSpecificAllocation;
4432 vboxWddmMemFree(pOa2Free);
4433 }
4434 }
4435#endif
4436 }
4437 }
4438 }
4439 dfprintf(("<== "__FUNCTION__ ", hDevice(0x%x)\n", hDevice));
4440
4441 return Status;
4442}
4443
4444NTSTATUS
4445APIENTRY
4446DxgkDdiCloseAllocation(
4447 CONST HANDLE hDevice,
4448 CONST DXGKARG_CLOSEALLOCATION* pCloseAllocation)
4449{
4450 /* DxgkDdiCloseAllocation should be made pageable. */
4451 PAGED_CODE();
4452
4453 dfprintf(("==> "__FUNCTION__ ", hDevice(0x%x)\n", hDevice));
4454
4455 vboxVDbgBreakFv();
4456
4457 for (UINT i = 0; i < pCloseAllocation->NumAllocations; ++i)
4458 {
4459 vboxWddmMemFree(pCloseAllocation->pOpenHandleList[i]);
4460 }
4461
4462 dfprintf(("<== "__FUNCTION__ ", hDevice(0x%x)\n", hDevice));
4463
4464 return STATUS_SUCCESS;
4465}
4466
4467NTSTATUS
4468APIENTRY
4469DxgkDdiRender(
4470 CONST HANDLE hContext,
4471 DXGKARG_RENDER *pRender)
4472{
4473// drprintf(("==> "__FUNCTION__ ", hContext(0x%x)\n", hContext));
4474
4475 Assert(pRender->DmaBufferPrivateDataSize >= sizeof (VBOXWDDM_DMA_PRIVATEDATA_BASEHDR));
4476 if (pRender->DmaBufferPrivateDataSize < sizeof (VBOXWDDM_DMA_PRIVATEDATA_BASEHDR))
4477 {
4478 drprintf((__FUNCTION__": Present->DmaBufferPrivateDataSize(%d) < sizeof VBOXWDDM_DMA_PRIVATEDATA_BASEHDR (%d)\n",
4479 pRender->DmaBufferPrivateDataSize , sizeof (VBOXWDDM_DMA_PRIVATEDATA_BASEHDR)));
4480 /* @todo: can this actually happen? what status to return? */
4481 return STATUS_INVALID_PARAMETER;
4482 }
4483 if (pRender->CommandLength < sizeof (VBOXWDDM_DMA_PRIVATEDATA_BASEHDR))
4484 {
4485 Assert(0);
4486 drprintf((__FUNCTION__": Present->DmaBufferPrivateDataSize(%d) < sizeof VBOXWDDM_DMA_PRIVATEDATA_BASEHDR (%d)\n",
4487 pRender->DmaBufferPrivateDataSize , sizeof (VBOXWDDM_DMA_PRIVATEDATA_BASEHDR)));
4488 /* @todo: can this actually happen? what status to return? */
4489 return STATUS_INVALID_PARAMETER;
4490 }
4491
4492 PVBOXWDDM_DMA_PRIVATEDATA_BASEHDR pInputHdr = (PVBOXWDDM_DMA_PRIVATEDATA_BASEHDR)pRender->pCommand;
4493 NTSTATUS Status = STATUS_SUCCESS;
4494 switch (pInputHdr->enmCmd)
4495 {
4496 case VBOXVDMACMD_TYPE_CHROMIUM_CMD:
4497 {
4498 if (pRender->CommandLength != RT_OFFSETOF(VBOXWDDM_DMA_PRIVATEDATA_UM_CHROMIUM_CMD, aBufInfos[pInputHdr->u32CmdReserved]))
4499 {
4500 Assert(0);
4501 return STATUS_INVALID_PARAMETER;
4502 }
4503 PVBOXWDDM_DMA_PRIVATEDATA_UM_CHROMIUM_CMD pUmCmd = (PVBOXWDDM_DMA_PRIVATEDATA_UM_CHROMIUM_CMD)pInputHdr;
4504 PVBOXWDDM_DMA_PRIVATEDATA_CHROMIUM_CMD pChromiumCmd = (PVBOXWDDM_DMA_PRIVATEDATA_CHROMIUM_CMD)pRender->pDmaBufferPrivateData;
4505 const uint32_t cbDma = RT_OFFSETOF(VBOXWDDM_DMA_PRIVATEDATA_CHROMIUM_CMD, aBufInfos[pInputHdr->u32CmdReserved]);
4506 if (pRender->DmaBufferPrivateDataSize < cbDma)
4507 {
4508 Assert(0);
4509 return STATUS_INVALID_PARAMETER;
4510 }
4511 if (pRender->DmaSize < cbDma)
4512 {
4513 Assert(0);
4514 return STATUS_INVALID_PARAMETER;
4515 }
4516
4517 if (pRender->PatchLocationListOutSize < pInputHdr->u32CmdReserved)
4518 {
4519 Assert(0);
4520 return STATUS_INVALID_PARAMETER;
4521 }
4522
4523 PVBOXWDDM_CONTEXT pContext = (PVBOXWDDM_CONTEXT)hContext;
4524 PVBOXWDDM_DEVICE pDevice = pContext->pDevice;
4525 PDEVICE_EXTENSION pDevExt = pDevice->pAdapter;
4526
4527 pChromiumCmd->Base.enmCmd = VBOXVDMACMD_TYPE_CHROMIUM_CMD;
4528 pChromiumCmd->Base.u32CmdReserved = pInputHdr->u32CmdReserved;
4529 pRender->pDmaBufferPrivateData = (uint8_t*)pRender->pDmaBufferPrivateData + cbDma;
4530 pRender->pDmaBuffer = ((uint8_t*)pRender->pDmaBuffer) + cbDma;
4531 D3DDDI_PATCHLOCATIONLIST* pPLL = pRender->pPatchLocationListOut;
4532 memset(pPLL, 0, sizeof (*pPLL) * pChromiumCmd->Base.u32CmdReserved);
4533 pRender->pPatchLocationListOut += pInputHdr->u32CmdReserved;
4534 PVBOXWDDM_UHGSMI_BUFFER_SUBMIT_INFO pSubmInfo = pChromiumCmd->aBufInfos;
4535 PVBOXWDDM_UHGSMI_BUFFER_UI_SUBMIT_INFO pSubmUmInfo = pUmCmd->aBufInfos;
4536 DXGK_ALLOCATIONLIST *pAllocationList = pRender->pAllocationList;
4537 for (UINT i = 0; i < pChromiumCmd->Base.u32CmdReserved; ++i)
4538 {
4539 PVBOXWDDM_ALLOCATION pAlloc = vboxWddmGetAllocationFromAllocList(pDevExt, pAllocationList);
4540 vboxWddmPopulateDmaAllocInfoWithOffset(&pSubmInfo->Alloc, pAlloc, pAllocationList, pSubmUmInfo->offData);
4541
4542 pSubmInfo->cbData = pSubmUmInfo->cbData;
4543 pSubmInfo->bDoNotSignalCompletion = pSubmUmInfo->fSubFlags.bDoNotSignalCompletion;
4544
4545 pPLL->AllocationIndex = i;
4546 pPLL->PatchOffset = RT_OFFSETOF(VBOXWDDM_DMA_PRIVATEDATA_CHROMIUM_CMD, aBufInfos[i].Alloc);
4547 pPLL->AllocationOffset = pSubmUmInfo->offData;
4548
4549 ++pPLL;
4550 ++pSubmInfo;
4551 ++pSubmUmInfo;
4552 ++pAllocationList;
4553 }
4554
4555 break;
4556 }
4557 case VBOXVDMACMD_TYPE_DMA_NOP:
4558 {
4559 PVBOXWDDM_DMA_PRIVATEDATA_BASEHDR pPrivateData = (PVBOXWDDM_DMA_PRIVATEDATA_BASEHDR)pRender->pDmaBufferPrivateData;
4560 pPrivateData->enmCmd = VBOXVDMACMD_TYPE_DMA_NOP;
4561
4562 pRender->pDmaBufferPrivateData = (uint8_t*)pRender->pDmaBufferPrivateData + sizeof (VBOXWDDM_DMA_PRIVATEDATA_BASEHDR);
4563 pRender->pDmaBuffer = ((uint8_t*)pRender->pDmaBuffer) + pRender->CommandLength;
4564 Assert(pRender->DmaSize >= pRender->CommandLength);
4565 Assert(pRender->PatchLocationListOutSize >= pRender->PatchLocationListInSize);
4566 UINT cbPLL = pRender->PatchLocationListInSize * sizeof (pRender->pPatchLocationListOut[0]);
4567 memcpy(pRender->pPatchLocationListOut, pRender->pPatchLocationListIn, cbPLL);
4568 pRender->pPatchLocationListOut += pRender->PatchLocationListInSize;
4569 break;
4570 }
4571 default:
4572 return STATUS_INVALID_PARAMETER;
4573 }
4574
4575// drprintf(("<== "__FUNCTION__ ", hContext(0x%x)\n", hContext));
4576
4577 return Status;
4578}
4579
4580#define VBOXVDMACMD_DMA_PRESENT_BLT_MINSIZE() (VBOXVDMACMD_SIZE(VBOXVDMACMD_DMA_PRESENT_BLT))
4581#define VBOXVDMACMD_DMA_PRESENT_BLT_SIZE(_c) (VBOXVDMACMD_BODY_FIELD_OFFSET(UINT, VBOXVDMACMD_DMA_PRESENT_BLT, aDstSubRects[_c]))
4582
4583#ifdef VBOX_WITH_VDMA
4584DECLINLINE(VOID) vboxWddmRectlFromRect(const RECT *pRect, PVBOXVDMA_RECTL pRectl)
4585{
4586 pRectl->left = (int16_t)pRect->left;
4587 pRectl->width = (uint16_t)(pRect->right - pRect->left);
4588 pRectl->top = (int16_t)pRect->top;
4589 pRectl->height = (uint16_t)(pRect->bottom - pRect->top);
4590}
4591
4592DECLINLINE(VBOXVDMA_PIXEL_FORMAT) vboxWddmFromPixFormat(D3DDDIFORMAT format)
4593{
4594 return (VBOXVDMA_PIXEL_FORMAT)format;
4595}
4596
4597DECLINLINE(VOID) vboxWddmSurfDescFromAllocation(PVBOXWDDM_ALLOCATION pAllocation, PVBOXVDMA_SURF_DESC pDesc)
4598{
4599 pDesc->width = pAllocation->SurfDesc.width;
4600 pDesc->height = pAllocation->SurfDesc.height;
4601 pDesc->format = vboxWddmFromPixFormat(pAllocation->SurfDesc.format);
4602 pDesc->bpp = pAllocation->SurfDesc.bpp;
4603 pDesc->pitch = pAllocation->SurfDesc.pitch;
4604 pDesc->fFlags = 0;
4605}
4606#endif
4607
4608DECLINLINE(BOOLEAN) vboxWddmPixFormatConversionSupported(D3DDDIFORMAT From, D3DDDIFORMAT To)
4609{
4610 Assert(From != D3DDDIFMT_UNKNOWN);
4611 Assert(To != D3DDDIFMT_UNKNOWN);
4612 Assert(From == To);
4613 return From == To;
4614}
4615
4616#if 0
4617DECLINLINE(bool) vboxWddmCheckForVisiblePrimary(PDEVICE_EXTENSION pDevExt, PVBOXWDDM_ALLOCATION pAllocation)
4618{
4619 !!!primary could be of pAllocation->enmType == VBOXWDDM_ALLOC_TYPE_UMD_RC_GENERIC!!!
4620 if (pAllocation->enmType != VBOXWDDM_ALLOC_TYPE_STD_SHAREDPRIMARYSURFACE)
4621 return false;
4622
4623 if (!pAllocation->bVisible)
4624 return false;
4625
4626 D3DDDI_VIDEO_PRESENT_SOURCE_ID id = pAllocation->SurfDesc.VidPnSourceId;
4627 if (id >= (D3DDDI_VIDEO_PRESENT_SOURCE_ID)commonFromDeviceExt(pDevExt)->cDisplays)
4628 return false;
4629
4630 PVBOXWDDM_SOURCE pSource = &pDevExt->aSources[id];
4631 if (pSource->pPrimaryAllocation != pAllocation)
4632 return false;
4633
4634 return true;
4635}
4636#endif
4637
4638/**
4639 * DxgkDdiPresent
4640 */
4641NTSTATUS
4642APIENTRY
4643DxgkDdiPresent(
4644 CONST HANDLE hContext,
4645 DXGKARG_PRESENT *pPresent)
4646{
4647 PAGED_CODE();
4648
4649// dfprintf(("==> "__FUNCTION__ ", hContext(0x%x)\n", hContext));
4650
4651 vboxVDbgBreakFv();
4652
4653 NTSTATUS Status = STATUS_SUCCESS;
4654 PVBOXWDDM_CONTEXT pContext = (PVBOXWDDM_CONTEXT)hContext;
4655 PVBOXWDDM_DEVICE pDevice = pContext->pDevice;
4656 PDEVICE_EXTENSION pDevExt = pDevice->pAdapter;
4657
4658 Assert(pPresent->DmaBufferPrivateDataSize >= sizeof (VBOXWDDM_DMA_PRIVATEDATA_PRESENTHDR));
4659 if (pPresent->DmaBufferPrivateDataSize < sizeof (VBOXWDDM_DMA_PRIVATEDATA_PRESENTHDR))
4660 {
4661 drprintf((__FUNCTION__": Present->DmaBufferPrivateDataSize(%d) < sizeof VBOXWDDM_DMA_PRIVATEDATA_PRESENTHDR (%d)\n", pPresent->DmaBufferPrivateDataSize , sizeof (VBOXWDDM_DMA_PRIVATEDATA_PRESENTHDR)));
4662 /* @todo: can this actually happen? what status tu return? */
4663 return STATUS_INVALID_PARAMETER;
4664 }
4665
4666 PVBOXWDDM_DMA_PRIVATEDATA_PRESENTHDR pPrivateData = (PVBOXWDDM_DMA_PRIVATEDATA_PRESENTHDR)pPresent->pDmaBufferPrivateData;
4667 pPrivateData->BaseHdr.fFlags.Value = 0;
4668 uint32_t cContexts3D = ASMAtomicReadU32(&pDevExt->cContexts3D);
4669#define VBOXWDDM_DUMMY_DMABUFFER_SIZE sizeof(RECT)
4670
4671 if (pPresent->Flags.Blt)
4672 {
4673 Assert(pPresent->Flags.Value == 1); /* only Blt is set, we do not support anything else for now */
4674 DXGK_ALLOCATIONLIST *pSrc = &pPresent->pAllocationList[DXGK_PRESENT_SOURCE_INDEX];
4675 DXGK_ALLOCATIONLIST *pDst = &pPresent->pAllocationList[DXGK_PRESENT_DESTINATION_INDEX];
4676 PVBOXWDDM_ALLOCATION pSrcAlloc = vboxWddmGetAllocationFromAllocList(pDevExt, pSrc);
4677 Assert(pSrcAlloc);
4678 if (pSrcAlloc)
4679 {
4680 PVBOXWDDM_ALLOCATION pDstAlloc = vboxWddmGetAllocationFromAllocList(pDevExt, pDst);
4681 Assert(pDstAlloc);
4682 if (pDstAlloc)
4683 {
4684 do
4685 {
4686#ifdef VBOXWDDM_RENDER_FROM_SHADOW
4687#if 0
4688 Assert (pSrcAlloc->enmType == VBOXWDDM_ALLOC_TYPE_STD_SHADOWSURFACE);
4689 Assert (pDstAlloc->enmType == VBOXWDDM_ALLOC_TYPE_STD_SHAREDPRIMARYSURFACE);
4690#else
4691 if (pContext->enmType == VBOXWDDM_CONTEXT_TYPE_SYSTEM)
4692 {
4693 Assert ((pSrcAlloc->enmType == VBOXWDDM_ALLOC_TYPE_STD_SHADOWSURFACE
4694 && pDstAlloc->enmType == VBOXWDDM_ALLOC_TYPE_STD_SHAREDPRIMARYSURFACE)
4695 || (pSrcAlloc->enmType == VBOXWDDM_ALLOC_TYPE_STD_SHAREDPRIMARYSURFACE
4696 && pDstAlloc->enmType == VBOXWDDM_ALLOC_TYPE_STD_SHADOWSURFACE));
4697 }
4698#endif
4699 /* issue VBOXWDDM_ALLOC_TYPE_STD_SHADOWSURFACE ONLY in case there are no 3D contexts currently
4700 * otherwise we would need info about all rects being updated on primary for visible rect reporting */
4701 if (!cContexts3D)
4702 {
4703 if (pDstAlloc->enmType == VBOXWDDM_ALLOC_TYPE_STD_SHAREDPRIMARYSURFACE
4704 && pSrcAlloc->enmType == VBOXWDDM_ALLOC_TYPE_STD_SHADOWSURFACE)
4705 {
4706 Assert(pContext->enmType == VBOXWDDM_CONTEXT_TYPE_SYSTEM);
4707 Assert(pDstAlloc->bAssigned);
4708 Assert(pDstAlloc->bVisible);
4709 if (pDstAlloc->bAssigned
4710 && pDstAlloc->bVisible)
4711 {
4712#ifdef VBOX_WITH_VIDEOHWACCEL
4713 if (vboxVhwaHlpOverlayListIsEmpty(pDevExt, pDstAlloc->SurfDesc.VidPnSourceId))
4714#endif
4715 {
4716 Assert(pPresent->DmaBufferPrivateDataSize >= sizeof (VBOXWDDM_DMA_PRIVATEDATA_SHADOW2PRIMARY));
4717 if (pPresent->DmaBufferPrivateDataSize >= sizeof (VBOXWDDM_DMA_PRIVATEDATA_SHADOW2PRIMARY))
4718 {
4719 VBOXWDDM_SOURCE *pSource = &pDevExt->aSources[pDstAlloc->SurfDesc.VidPnSourceId];
4720 vboxWddmAssignShadow(pDevExt, pSource, pSrcAlloc, pDstAlloc->SurfDesc.VidPnSourceId);
4721 Assert(pPresent->SrcRect.left == pPresent->DstRect.left);
4722 Assert(pPresent->SrcRect.right == pPresent->DstRect.right);
4723 Assert(pPresent->SrcRect.top == pPresent->DstRect.top);
4724 Assert(pPresent->SrcRect.bottom == pPresent->DstRect.bottom);
4725 RECT rect;
4726 if (pPresent->SubRectCnt)
4727 {
4728 rect = pPresent->pDstSubRects[0];
4729 for (UINT i = 1; i < pPresent->SubRectCnt; ++i)
4730 {
4731 vboxWddmRectUnited(&rect, &rect, &pPresent->pDstSubRects[i]);
4732 }
4733 }
4734 else
4735 rect = pPresent->SrcRect;
4736
4737
4738 pPresent->pDmaBufferPrivateData = (uint8_t*)pPresent->pDmaBufferPrivateData + sizeof (VBOXWDDM_DMA_PRIVATEDATA_SHADOW2PRIMARY);
4739 pPresent->pDmaBuffer = ((uint8_t*)pPresent->pDmaBuffer) + VBOXWDDM_DUMMY_DMABUFFER_SIZE;
4740 Assert(pPresent->DmaSize >= VBOXWDDM_DUMMY_DMABUFFER_SIZE);
4741 memset(pPresent->pPatchLocationListOut, 0, 2*sizeof (D3DDDI_PATCHLOCATIONLIST));
4742 pPresent->pPatchLocationListOut->PatchOffset = 0;
4743 pPresent->pPatchLocationListOut->AllocationIndex = DXGK_PRESENT_SOURCE_INDEX;
4744 ++pPresent->pPatchLocationListOut;
4745 pPresent->pPatchLocationListOut->PatchOffset = 4;
4746 pPresent->pPatchLocationListOut->AllocationIndex = DXGK_PRESENT_DESTINATION_INDEX;
4747 ++pPresent->pPatchLocationListOut;
4748
4749 pPrivateData->BaseHdr.enmCmd = VBOXVDMACMD_TYPE_DMA_PRESENT_SHADOW2PRIMARY;
4750 PVBOXWDDM_DMA_PRIVATEDATA_SHADOW2PRIMARY pS2P = (PVBOXWDDM_DMA_PRIVATEDATA_SHADOW2PRIMARY)pPrivateData;
4751 /* we do not know the shadow address yet, perform dummy DMA cycle */
4752 vboxWddmPopulateDmaAllocInfo(&pS2P->Shadow2Primary.ShadowAlloc, pSrcAlloc, pSrc);
4753// vboxWddmPopulateDmaAllocInfo(&pPrivateData->DstAllocInfo, pDstAlloc, pDst);
4754 pS2P->Shadow2Primary.SrcRect = rect;
4755 pS2P->Shadow2Primary.VidPnSourceId = pDstAlloc->SurfDesc.VidPnSourceId;
4756 break;
4757 }
4758 else
4759 {
4760 Status = STATUS_GRAPHICS_INSUFFICIENT_DMA_BUFFER;
4761 break;
4762 }
4763 }
4764 }
4765 }
4766 }
4767
4768 /* we're here because this is NOT a shadow->primary update
4769 * or because there are d3d contexts and we need to report visible rects
4770 * or because we have overlays active and we need a special handling for primary */
4771#endif
4772 UINT cbCmd = pPresent->DmaBufferPrivateDataSize;
4773 pPrivateData->BaseHdr.enmCmd = VBOXVDMACMD_TYPE_DMA_PRESENT_BLT;
4774
4775 PVBOXWDDM_DMA_PRIVATEDATA_BLT pBlt = (PVBOXWDDM_DMA_PRIVATEDATA_BLT)pPrivateData;
4776
4777 vboxWddmPopulateDmaAllocInfo(&pBlt->Blt.SrcAlloc, pSrcAlloc, pSrc);
4778 vboxWddmPopulateDmaAllocInfo(&pBlt->Blt.DstAlloc, pDstAlloc, pDst);
4779
4780 pBlt->Blt.SrcRect = pPresent->SrcRect;
4781 pBlt->Blt.DstRects.ContextRect = pPresent->DstRect;
4782 pBlt->Blt.DstRects.UpdateRects.cRects = 0;
4783 UINT cbHead = RT_OFFSETOF(VBOXWDDM_DMA_PRIVATEDATA_BLT, Blt.DstRects.UpdateRects.aRects[0]);
4784 Assert(pPresent->SubRectCnt > pPresent->MultipassOffset);
4785 UINT cbRects = (pPresent->SubRectCnt - pPresent->MultipassOffset) * sizeof (RECT);
4786 pPresent->pDmaBufferPrivateData = (uint8_t*)pPresent->pDmaBufferPrivateData + cbHead + cbRects;
4787 pPresent->pDmaBuffer = ((uint8_t*)pPresent->pDmaBuffer) + VBOXWDDM_DUMMY_DMABUFFER_SIZE;
4788 Assert(pPresent->DmaSize >= VBOXWDDM_DUMMY_DMABUFFER_SIZE);
4789 cbCmd -= cbHead;
4790 Assert(cbCmd < UINT32_MAX/2);
4791 Assert(cbCmd > sizeof (RECT));
4792 if (cbCmd >= cbRects)
4793 {
4794 cbCmd -= cbRects;
4795 memcpy(&pBlt->Blt.DstRects.UpdateRects.aRects[pPresent->MultipassOffset], pPresent->pDstSubRects, cbRects);
4796 pBlt->Blt.DstRects.UpdateRects.cRects += cbRects/sizeof (RECT);
4797 }
4798 else
4799 {
4800 UINT cbFitingRects = (cbCmd/sizeof (RECT)) * sizeof (RECT);
4801 Assert(cbFitingRects);
4802 memcpy(&pBlt->Blt.DstRects.UpdateRects.aRects[pPresent->MultipassOffset], pPresent->pDstSubRects, cbFitingRects);
4803 cbCmd -= cbFitingRects;
4804 pPresent->MultipassOffset += cbFitingRects/sizeof (RECT);
4805 pBlt->Blt.DstRects.UpdateRects.cRects += cbFitingRects/sizeof (RECT);
4806 Assert(pPresent->SubRectCnt > pPresent->MultipassOffset);
4807 Status = STATUS_GRAPHICS_INSUFFICIENT_DMA_BUFFER;
4808 }
4809
4810 memset(pPresent->pPatchLocationListOut, 0, 2*sizeof (D3DDDI_PATCHLOCATIONLIST));
4811 pPresent->pPatchLocationListOut->PatchOffset = 0;
4812 pPresent->pPatchLocationListOut->AllocationIndex = DXGK_PRESENT_SOURCE_INDEX;
4813 ++pPresent->pPatchLocationListOut;
4814 pPresent->pPatchLocationListOut->PatchOffset = 4;
4815 pPresent->pPatchLocationListOut->AllocationIndex = DXGK_PRESENT_DESTINATION_INDEX;
4816 ++pPresent->pPatchLocationListOut;
4817
4818 break;
4819#ifdef VBOX_WITH_VDMA
4820 cbCmd = pPresent->DmaSize;
4821
4822 Assert(pPresent->SubRectCnt);
4823 UINT cmdSize = VBOXVDMACMD_DMA_PRESENT_BLT_SIZE(pPresent->SubRectCnt - pPresent->MultipassOffset);
4824 PVBOXVDMACMD pCmd = (PVBOXVDMACMD)pPresent->pDmaBuffer;
4825 pPresent->pDmaBuffer = ((uint8_t*)pPresent->pDmaBuffer) + cmdSize;
4826 Assert(cbCmd >= VBOXVDMACMD_DMA_PRESENT_BLT_MINSIZE());
4827 if (cbCmd >= VBOXVDMACMD_DMA_PRESENT_BLT_MINSIZE())
4828 {
4829 if (vboxWddmPixFormatConversionSupported(pSrcAlloc->SurfDesc.format, pDstAlloc->SurfDesc.format))
4830 {
4831 memset(pPresent->pPatchLocationListOut, 0, 2*sizeof (D3DDDI_PATCHLOCATIONLIST));
4832 // pPresent->pPatchLocationListOut->PatchOffset = 0;
4833 // ++pPresent->pPatchLocationListOut;
4834 pPresent->pPatchLocationListOut->PatchOffset = VBOXVDMACMD_BODY_FIELD_OFFSET(UINT, VBOXVDMACMD_DMA_PRESENT_BLT, offSrc);
4835 pPresent->pPatchLocationListOut->AllocationIndex = DXGK_PRESENT_SOURCE_INDEX;
4836 ++pPresent->pPatchLocationListOut;
4837 pPresent->pPatchLocationListOut->PatchOffset = VBOXVDMACMD_BODY_FIELD_OFFSET(UINT, VBOXVDMACMD_DMA_PRESENT_BLT, offDst);
4838 pPresent->pPatchLocationListOut->AllocationIndex = DXGK_PRESENT_DESTINATION_INDEX;
4839 ++pPresent->pPatchLocationListOut;
4840
4841 pCmd->enmType = VBOXVDMACMD_TYPE_DMA_PRESENT_BLT;
4842 pCmd->u32CmdSpecific = 0;
4843 PVBOXVDMACMD_DMA_PRESENT_BLT pTransfer = VBOXVDMACMD_BODY(pCmd, VBOXVDMACMD_DMA_PRESENT_BLT);
4844 pTransfer->offSrc = (VBOXVIDEOOFFSET)pSrc->PhysicalAddress.QuadPart;
4845 pTransfer->offDst = (VBOXVIDEOOFFSET)pDst->PhysicalAddress.QuadPart;
4846 vboxWddmSurfDescFromAllocation(pSrcAlloc, &pTransfer->srcDesc);
4847 vboxWddmSurfDescFromAllocation(pDstAlloc, &pTransfer->dstDesc);
4848 vboxWddmRectlFromRect(&pPresent->SrcRect, &pTransfer->srcRectl);
4849 vboxWddmRectlFromRect(&pPresent->DstRect, &pTransfer->dstRectl);
4850 UINT i = 0;
4851 cbCmd -= VBOXVDMACMD_BODY_FIELD_OFFSET(UINT, VBOXVDMACMD_DMA_PRESENT_BLT, aDstSubRects);
4852 Assert(cbCmd >= sizeof (VBOXVDMA_RECTL));
4853 Assert(cbCmd < pPresent->DmaSize);
4854 for (; i < pPresent->SubRectCnt; ++i)
4855 {
4856 if (cbCmd < sizeof (VBOXVDMA_RECTL))
4857 {
4858 Assert(i);
4859 pPresent->MultipassOffset += i;
4860 Status = STATUS_GRAPHICS_INSUFFICIENT_DMA_BUFFER;
4861 break;
4862 }
4863 vboxWddmRectlFromRect(&pPresent->pDstSubRects[i + pPresent->MultipassOffset], &pTransfer->aDstSubRects[i]);
4864 cbCmd -= sizeof (VBOXVDMA_RECTL);
4865 }
4866 Assert(i);
4867 pPrivateData->BaseHdr.enmCmd = VBOXVDMACMD_TYPE_DMA_PRESENT_BLT;
4868 pTransfer->cDstSubRects = i;
4869 pPresent->pDmaBufferPrivateData = (uint8_t*)pPresent->pDmaBufferPrivateData + sizeof(VBOXWDDM_DMA_PRIVATEDATA_PRESENTHDR);
4870 }
4871 else
4872 {
4873 AssertBreakpoint();
4874 drprintf((__FUNCTION__": unsupported format conversion from(%d) to (%d)\n",pSrcAlloc->SurfDesc.format, pDstAlloc->SurfDesc.format));
4875 Status = STATUS_GRAPHICS_CANNOTCOLORCONVERT;
4876 }
4877 }
4878 else
4879 {
4880 /* this should not happen actually */
4881 drprintf((__FUNCTION__": cbCmd too small!! (%d)\n", cbCmd));
4882 Status = STATUS_GRAPHICS_INSUFFICIENT_DMA_BUFFER;
4883 }
4884#endif
4885 } while(0);
4886 }
4887 else
4888 {
4889 /* this should not happen actually */
4890 drprintf((__FUNCTION__": failed to get Dst Allocation info for hDeviceSpecificAllocation(0x%x)\n",pDst->hDeviceSpecificAllocation));
4891 Status = STATUS_INVALID_HANDLE;
4892 }
4893 }
4894 else
4895 {
4896 /* this should not happen actually */
4897 drprintf((__FUNCTION__": failed to get Src Allocation info for hDeviceSpecificAllocation(0x%x)\n",pSrc->hDeviceSpecificAllocation));
4898 Status = STATUS_INVALID_HANDLE;
4899 }
4900#if 0
4901 UINT cbCmd = pPresent->DmaSize;
4902
4903 Assert(pPresent->SubRectCnt);
4904 UINT cmdSize = VBOXVDMACMD_DMA_PRESENT_BLT_SIZE(pPresent->SubRectCnt - pPresent->MultipassOffset);
4905 PVBOXVDMACMD pCmd = (PVBOXVDMACMD)pPresent->pDmaBuffer;
4906 pPresent->pDmaBuffer = ((uint8_t*)pPresent->pDmaBuffer) + cmdSize;
4907 Assert(cbCmd >= VBOXVDMACMD_DMA_PRESENT_BLT_MINSIZE());
4908 if (cbCmd >= VBOXVDMACMD_DMA_PRESENT_BLT_MINSIZE())
4909 {
4910 DXGK_ALLOCATIONLIST *pSrc = &pPresent->pAllocationList[DXGK_PRESENT_SOURCE_INDEX];
4911 DXGK_ALLOCATIONLIST *pDst = &pPresent->pAllocationList[DXGK_PRESENT_DESTINATION_INDEX];
4912 PVBOXWDDM_ALLOCATION pSrcAlloc = vboxWddmGetAllocationFromAllocList(pDevExt, pSrc);
4913 Assert(pSrcAlloc);
4914 if (pSrcAlloc)
4915 {
4916 PVBOXWDDM_ALLOCATION pDstAlloc = vboxWddmGetAllocationFromAllocList(pDevExt, pDst);
4917 Assert(pDstAlloc);
4918 if (pDstAlloc)
4919 {
4920 if (vboxWddmPixFormatConversionSupported(pSrcAlloc->SurfDesc.format, pDstAlloc->SurfDesc.format))
4921 {
4922 memset(pPresent->pPatchLocationListOut, 0, 2*sizeof (D3DDDI_PATCHLOCATIONLIST));
4923// pPresent->pPatchLocationListOut->PatchOffset = 0;
4924// ++pPresent->pPatchLocationListOut;
4925 pPresent->pPatchLocationListOut->PatchOffset = VBOXVDMACMD_BODY_FIELD_OFFSET(UINT, VBOXVDMACMD_DMA_PRESENT_BLT, offSrc);
4926 pPresent->pPatchLocationListOut->AllocationIndex = DXGK_PRESENT_SOURCE_INDEX;
4927 ++pPresent->pPatchLocationListOut;
4928 pPresent->pPatchLocationListOut->PatchOffset = VBOXVDMACMD_BODY_FIELD_OFFSET(UINT, VBOXVDMACMD_DMA_PRESENT_BLT, offDst);
4929 pPresent->pPatchLocationListOut->AllocationIndex = DXGK_PRESENT_DESTINATION_INDEX;
4930 ++pPresent->pPatchLocationListOut;
4931
4932 pCmd->enmType = VBOXVDMACMD_TYPE_DMA_PRESENT_BLT;
4933 pCmd->u32CmdSpecific = 0;
4934 PVBOXVDMACMD_DMA_PRESENT_BLT pTransfer = VBOXVDMACMD_BODY(pCmd, VBOXVDMACMD_DMA_PRESENT_BLT);
4935 pTransfer->offSrc = (VBOXVIDEOOFFSET)pSrc->PhysicalAddress.QuadPart;
4936 pTransfer->offDst = (VBOXVIDEOOFFSET)pDst->PhysicalAddress.QuadPart;
4937 vboxWddmSurfDescFromAllocation(pSrcAlloc, &pTransfer->srcDesc);
4938 vboxWddmSurfDescFromAllocation(pDstAlloc, &pTransfer->dstDesc);
4939 vboxWddmRectlFromRect(&pPresent->SrcRect, &pTransfer->srcRectl);
4940 vboxWddmRectlFromRect(&pPresent->DstRect, &pTransfer->dstRectl);
4941 UINT i = 0;
4942 cbCmd -= VBOXVDMACMD_BODY_FIELD_OFFSET(UINT, VBOXVDMACMD_DMA_PRESENT_BLT, aDstSubRects);
4943 Assert(cbCmd >= sizeof (VBOXVDMA_RECTL));
4944 Assert(cbCmd < pPresent->DmaSize);
4945 for (; i < pPresent->SubRectCnt; ++i)
4946 {
4947 if (cbCmd < sizeof (VBOXVDMA_RECTL))
4948 {
4949 Assert(i);
4950 pPresent->MultipassOffset += i;
4951 Status = STATUS_GRAPHICS_INSUFFICIENT_DMA_BUFFER;
4952 break;
4953 }
4954 vboxWddmRectlFromRect(&pPresent->pDstSubRects[i + pPresent->MultipassOffset], &pTransfer->aDstSubRects[i]);
4955 cbCmd -= sizeof (VBOXVDMA_RECTL);
4956 }
4957 Assert(i);
4958 pTransfer->cDstSubRects = i;
4959 pPresent->pDmaBufferPrivateData = (uint8_t*)pPresent->pDmaBufferPrivateData + sizeof(VBOXWDDM_DMA_PRIVATEDATA_HDR);
4960 }
4961 else
4962 {
4963 AssertBreakpoint();
4964 drprintf((__FUNCTION__": unsupported format conversion from(%d) to (%d)\n",pSrcAlloc->SurfDesc.format, pDstAlloc->SurfDesc.format));
4965 Status = STATUS_GRAPHICS_CANNOTCOLORCONVERT;
4966 }
4967 }
4968 else
4969 {
4970 /* this should not happen actually */
4971 drprintf((__FUNCTION__": failed to get Dst Allocation info for hDeviceSpecificAllocation(0x%x)\n",pDst->hDeviceSpecificAllocation));
4972 Status = STATUS_INVALID_HANDLE;
4973 }
4974 }
4975 else
4976 {
4977 /* this should not happen actually */
4978 drprintf((__FUNCTION__": failed to get Src Allocation info for hDeviceSpecificAllocation(0x%x)\n",pSrc->hDeviceSpecificAllocation));
4979 Status = STATUS_INVALID_HANDLE;
4980 }
4981 }
4982 else
4983 {
4984 /* this should not happen actually */
4985 drprintf((__FUNCTION__": cbCmd too small!! (%d)\n", cbCmd));
4986 Status = STATUS_GRAPHICS_INSUFFICIENT_DMA_BUFFER;
4987 }
4988#endif
4989 }
4990 else if (pPresent->Flags.Flip)
4991 {
4992 Assert(pPresent->Flags.Value == 4); /* only Blt is set, we do not support anything else for now */
4993 Assert(pContext->enmType == VBOXWDDM_CONTEXT_TYPE_CUSTOM_3D);
4994 DXGK_ALLOCATIONLIST *pSrc = &pPresent->pAllocationList[DXGK_PRESENT_SOURCE_INDEX];
4995 PVBOXWDDM_ALLOCATION pSrcAlloc = vboxWddmGetAllocationFromAllocList(pDevExt, pSrc);
4996 Assert(pSrcAlloc);
4997 if (pSrcAlloc)
4998 {
4999 Assert(cContexts3D);
5000 pPrivateData->BaseHdr.enmCmd = VBOXVDMACMD_TYPE_DMA_PRESENT_FLIP;
5001 PVBOXWDDM_DMA_PRIVATEDATA_FLIP pFlip = (PVBOXWDDM_DMA_PRIVATEDATA_FLIP)pPrivateData;
5002
5003 vboxWddmPopulateDmaAllocInfo(&pFlip->Flip.Alloc, pSrcAlloc, pSrc);
5004
5005 UINT cbCmd = sizeof (VBOXWDDM_DMA_PRIVATEDATA_FLIP);
5006 pPresent->pDmaBufferPrivateData = (uint8_t*)pPresent->pDmaBufferPrivateData + cbCmd;
5007 pPresent->pDmaBuffer = ((uint8_t*)pPresent->pDmaBuffer) + VBOXWDDM_DUMMY_DMABUFFER_SIZE;
5008 Assert(pPresent->DmaSize >= VBOXWDDM_DUMMY_DMABUFFER_SIZE);
5009
5010 memset(pPresent->pPatchLocationListOut, 0, sizeof (D3DDDI_PATCHLOCATIONLIST));
5011 pPresent->pPatchLocationListOut->PatchOffset = 0;
5012 pPresent->pPatchLocationListOut->AllocationIndex = DXGK_PRESENT_SOURCE_INDEX;
5013 ++pPresent->pPatchLocationListOut;
5014 }
5015 else
5016 {
5017 /* this should not happen actually */
5018 drprintf((__FUNCTION__": failed to get pSrc Allocation info for hDeviceSpecificAllocation(0x%x)\n",pSrc->hDeviceSpecificAllocation));
5019 Status = STATUS_INVALID_HANDLE;
5020 }
5021 }
5022 else if (pPresent->Flags.ColorFill)
5023 {
5024 Assert(pContext->enmType == VBOXWDDM_CONTEXT_TYPE_CUSTOM_2D);
5025 Assert(pPresent->Flags.Value == 2); /* only ColorFill is set, we do not support anything else for now */
5026 DXGK_ALLOCATIONLIST *pDst = &pPresent->pAllocationList[DXGK_PRESENT_DESTINATION_INDEX];
5027 PVBOXWDDM_ALLOCATION pDstAlloc = vboxWddmGetAllocationFromAllocList(pDevExt, pDst);
5028 Assert(pDstAlloc);
5029 if (pDstAlloc)
5030 {
5031 UINT cbCmd = pPresent->DmaBufferPrivateDataSize;
5032 pPrivateData->BaseHdr.enmCmd = VBOXVDMACMD_TYPE_DMA_PRESENT_CLRFILL;
5033 PVBOXWDDM_DMA_PRIVATEDATA_CLRFILL pCF = (PVBOXWDDM_DMA_PRIVATEDATA_CLRFILL)pPrivateData;
5034
5035 vboxWddmPopulateDmaAllocInfo(&pCF->ClrFill.Alloc, pDstAlloc, pDst);
5036
5037 pCF->ClrFill.Color = pPresent->Color;
5038 pCF->ClrFill.Rects.cRects = 0;
5039 UINT cbHead = RT_OFFSETOF(VBOXWDDM_DMA_PRIVATEDATA_CLRFILL, ClrFill.Rects.aRects[0]);
5040 Assert(pPresent->SubRectCnt > pPresent->MultipassOffset);
5041 UINT cbRects = (pPresent->SubRectCnt - pPresent->MultipassOffset) * sizeof (RECT);
5042 pPresent->pDmaBufferPrivateData = (uint8_t*)pPresent->pDmaBufferPrivateData + cbHead + cbRects;
5043 pPresent->pDmaBuffer = ((uint8_t*)pPresent->pDmaBuffer) + VBOXWDDM_DUMMY_DMABUFFER_SIZE;
5044 Assert(pPresent->DmaSize >= VBOXWDDM_DUMMY_DMABUFFER_SIZE);
5045 cbCmd -= cbHead;
5046 Assert(cbCmd < UINT32_MAX/2);
5047 Assert(cbCmd > sizeof (RECT));
5048 if (cbCmd >= cbRects)
5049 {
5050 cbCmd -= cbRects;
5051 memcpy(&pCF->ClrFill.Rects.aRects[pPresent->MultipassOffset], pPresent->pDstSubRects, cbRects);
5052 pCF->ClrFill.Rects.cRects += cbRects/sizeof (RECT);
5053 }
5054 else
5055 {
5056 UINT cbFitingRects = (cbCmd/sizeof (RECT)) * sizeof (RECT);
5057 Assert(cbFitingRects);
5058 memcpy(&pCF->ClrFill.Rects.aRects[pPresent->MultipassOffset], pPresent->pDstSubRects, cbFitingRects);
5059 cbCmd -= cbFitingRects;
5060 pPresent->MultipassOffset += cbFitingRects/sizeof (RECT);
5061 pCF->ClrFill.Rects.cRects += cbFitingRects/sizeof (RECT);
5062 Assert(pPresent->SubRectCnt > pPresent->MultipassOffset);
5063 Status = STATUS_GRAPHICS_INSUFFICIENT_DMA_BUFFER;
5064 }
5065
5066 memset(pPresent->pPatchLocationListOut, 0, sizeof (D3DDDI_PATCHLOCATIONLIST));
5067 pPresent->pPatchLocationListOut->PatchOffset = 0;
5068 pPresent->pPatchLocationListOut->AllocationIndex = DXGK_PRESENT_DESTINATION_INDEX;
5069 ++pPresent->pPatchLocationListOut;
5070 }
5071 else
5072 {
5073 /* this should not happen actually */
5074 drprintf((__FUNCTION__": failed to get pDst Allocation info for hDeviceSpecificAllocation(0x%x)\n",pDst->hDeviceSpecificAllocation));
5075 Status = STATUS_INVALID_HANDLE;
5076 }
5077
5078 }
5079 else
5080 {
5081 drprintf((__FUNCTION__": cmd NOT IMPLEMENTED!! Flags(0x%x)\n", pPresent->Flags.Value));
5082 AssertBreakpoint();
5083 }
5084
5085// dfprintf(("<== "__FUNCTION__ ", hContext(0x%x), Status(0x%x)\n", hContext, Status));
5086
5087 return Status;
5088}
5089
5090NTSTATUS
5091APIENTRY
5092DxgkDdiUpdateOverlay(
5093 CONST HANDLE hOverlay,
5094 CONST DXGKARG_UPDATEOVERLAY *pUpdateOverlay)
5095{
5096 dfprintf(("==> "__FUNCTION__ ", hOverlay(0x%p)\n", hOverlay));
5097
5098 NTSTATUS Status = STATUS_SUCCESS;
5099 PVBOXWDDM_OVERLAY pOverlay = (PVBOXWDDM_OVERLAY)hOverlay;
5100 Assert(pOverlay);
5101 int rc = vboxVhwaHlpOverlayUpdate(pOverlay, &pUpdateOverlay->OverlayInfo);
5102 AssertRC(rc);
5103 if (RT_SUCCESS(rc))
5104 {
5105 RECT DstRect;
5106 vboxVhwaHlpOverlayDstRectGet(pOverlay->pDevExt, pOverlay, &DstRect);
5107 Status = vboxVdmaHlpUpdatePrimary(pOverlay->pDevExt, pOverlay->VidPnSourceId, &DstRect);
5108 Assert(Status == STATUS_SUCCESS);
5109 }
5110 else
5111 Status = STATUS_UNSUCCESSFUL;
5112
5113 dfprintf(("<== "__FUNCTION__ ", hOverlay(0x%p)\n", hOverlay));
5114
5115 return Status;
5116}
5117
5118NTSTATUS
5119APIENTRY
5120DxgkDdiFlipOverlay(
5121 CONST HANDLE hOverlay,
5122 CONST DXGKARG_FLIPOVERLAY *pFlipOverlay)
5123{
5124 dfprintf(("==> "__FUNCTION__ ", hOverlay(0x%p)\n", hOverlay));
5125
5126 NTSTATUS Status = STATUS_SUCCESS;
5127 PVBOXWDDM_OVERLAY pOverlay = (PVBOXWDDM_OVERLAY)hOverlay;
5128 Assert(pOverlay);
5129 int rc = vboxVhwaHlpOverlayFlip(pOverlay, pFlipOverlay);
5130 AssertRC(rc);
5131 if (RT_FAILURE(rc))
5132 Status = STATUS_UNSUCCESSFUL;
5133
5134 dfprintf(("<== "__FUNCTION__ ", hOverlay(0x%p)\n", hOverlay));
5135
5136 return Status;
5137}
5138
5139NTSTATUS
5140APIENTRY
5141DxgkDdiDestroyOverlay(
5142 CONST HANDLE hOverlay)
5143{
5144 dfprintf(("==> "__FUNCTION__ ", hOverlay(0x%p)\n", hOverlay));
5145
5146 NTSTATUS Status = STATUS_SUCCESS;
5147 PVBOXWDDM_OVERLAY pOverlay = (PVBOXWDDM_OVERLAY)hOverlay;
5148 Assert(pOverlay);
5149 vboxVhwaHlpOverlayListRemove(pOverlay->pDevExt, pOverlay);
5150 int rc = vboxVhwaHlpOverlayDestroy(pOverlay);
5151 AssertRC(rc);
5152 if (RT_SUCCESS(rc))
5153 vboxWddmMemFree(pOverlay);
5154 else
5155 Status = STATUS_UNSUCCESSFUL;
5156
5157 dfprintf(("<== "__FUNCTION__ ", hOverlay(0x%p)\n", hOverlay));
5158
5159 return Status;
5160}
5161
5162/**
5163 * DxgkDdiCreateContext
5164 */
5165NTSTATUS
5166APIENTRY
5167DxgkDdiCreateContext(
5168 CONST HANDLE hDevice,
5169 DXGKARG_CREATECONTEXT *pCreateContext)
5170{
5171 /* DxgkDdiCreateContext should be made pageable */
5172 PAGED_CODE();
5173
5174 dfprintf(("==> "__FUNCTION__ ", hDevice(0x%x)\n", hDevice));
5175
5176 vboxVDbgBreakFv();
5177
5178 NTSTATUS Status = STATUS_SUCCESS;
5179 PVBOXWDDM_DEVICE pDevice = (PVBOXWDDM_DEVICE)hDevice;
5180 PDEVICE_EXTENSION pDevExt = pDevice->pAdapter;
5181 PVBOXWDDM_CONTEXT pContext = (PVBOXWDDM_CONTEXT)vboxWddmMemAllocZero(sizeof (VBOXWDDM_CONTEXT));
5182 Assert(pContext);
5183 if (pContext)
5184 {
5185 pContext->pDevice = pDevice;
5186 pContext->hContext = pCreateContext->hContext;
5187 pContext->EngineAffinity = pCreateContext->EngineAffinity;
5188 pContext->NodeOrdinal = pCreateContext->NodeOrdinal;
5189 vboxVideoCmCtxInitEmpty(&pContext->CmContext);
5190 if (pCreateContext->Flags.SystemContext || pCreateContext->PrivateDriverDataSize == 0)
5191 {
5192 Assert(pCreateContext->PrivateDriverDataSize == 0);
5193 Assert(!pCreateContext->pPrivateDriverData);
5194 Assert(pCreateContext->Flags.Value <= 2); /* 2 is a GDI context in Win7 */
5195 pContext->enmType = VBOXWDDM_CONTEXT_TYPE_SYSTEM;
5196 for (int i = 0; i < commonFromDeviceExt(pDevExt)->cDisplays; ++i)
5197 {
5198 pDevExt->aSources[i].offVram = VBOXVIDEOOFFSET_VOID;
5199 NTSTATUS tmpStatus= vboxWddmDisplaySettingsQueryPos(pDevExt, i, &pDevExt->aSources[i].VScreenPos);
5200 Assert(tmpStatus == STATUS_SUCCESS);
5201 }
5202 }
5203 else
5204 {
5205 Assert(pCreateContext->Flags.Value == 0);
5206 Assert(pCreateContext->PrivateDriverDataSize == sizeof (VBOXWDDM_CREATECONTEXT_INFO));
5207 Assert(pCreateContext->pPrivateDriverData);
5208 if (pCreateContext->PrivateDriverDataSize == sizeof (VBOXWDDM_CREATECONTEXT_INFO))
5209 {
5210 PVBOXWDDM_CREATECONTEXT_INFO pInfo = (PVBOXWDDM_CREATECONTEXT_INFO)pCreateContext->pPrivateDriverData;
5211 switch (pInfo->enmType)
5212 {
5213 case VBOXWDDM_CONTEXT_TYPE_CUSTOM_3D:
5214 {
5215 Status = vboxVideoAMgrCtxCreate(&pDevExt->AllocMgr, &pContext->AllocContext);
5216 Assert(Status == STATUS_SUCCESS);
5217 if (Status == STATUS_SUCCESS)
5218 {
5219 ExInitializeFastMutex(&pContext->SwapchainMutex);
5220 Status = vboxWddmHTableCreate(&pContext->Swapchains, 4);
5221 Assert(Status == STATUS_SUCCESS);
5222 if (Status == STATUS_SUCCESS)
5223 {
5224 pContext->enmType = VBOXWDDM_CONTEXT_TYPE_CUSTOM_3D;
5225 Status = vboxVideoCmCtxAdd(&pDevice->pAdapter->CmMgr, &pContext->CmContext, (HANDLE)pInfo->hUmEvent, pInfo->u64UmInfo);
5226 Assert(Status == STATUS_SUCCESS);
5227 if (Status == STATUS_SUCCESS)
5228 {
5229 // Assert(KeGetCurrentIrql() < DISPATCH_LEVEL);
5230 // ExAcquireFastMutex(&pDevExt->ContextMutex);
5231 ASMAtomicIncU32(&pDevExt->cContexts3D);
5232 // ExReleaseFastMutex(&pDevExt->ContextMutex);
5233 break;
5234 }
5235 vboxWddmHTableDestroy(&pContext->Swapchains);
5236 }
5237 }
5238 break;
5239 }
5240 case VBOXWDDM_CONTEXT_TYPE_CUSTOM_UHGSMI_3D:
5241 case VBOXWDDM_CONTEXT_TYPE_CUSTOM_UHGSMI_GL:
5242 {
5243 Status = vboxVideoAMgrCtxCreate(&pDevExt->AllocMgr, &pContext->AllocContext);
5244 Assert(Status == STATUS_SUCCESS);
5245 if (Status != STATUS_SUCCESS)
5246 break;
5247 /* do not break to go to the _2D branch and do the rest stuff */
5248 }
5249 case VBOXWDDM_CONTEXT_TYPE_CUSTOM_2D:
5250 {
5251 pContext->enmType = pInfo->enmType;
5252 break;
5253 }
5254 default:
5255 {
5256 Assert(0);
5257 Status = STATUS_INVALID_PARAMETER;
5258 break;
5259 }
5260 }
5261 }
5262 }
5263
5264 if (Status == STATUS_SUCCESS)
5265 {
5266 pCreateContext->hContext = pContext;
5267 pCreateContext->ContextInfo.DmaBufferSize = VBOXWDDM_C_DMA_BUFFER_SIZE;
5268 pCreateContext->ContextInfo.DmaBufferSegmentSet = 0;
5269 pCreateContext->ContextInfo.DmaBufferPrivateDataSize = VBOXWDDM_C_DMA_PRIVATEDATA_SIZE;
5270 pCreateContext->ContextInfo.AllocationListSize = VBOXWDDM_C_ALLOC_LIST_SIZE;
5271 pCreateContext->ContextInfo.PatchLocationListSize = VBOXWDDM_C_PATH_LOCATION_LIST_SIZE;
5272 //#if (DXGKDDI_INTERFACE_VERSION >= DXGKDDI_INTERFACE_VERSION_WIN7)
5273 //# error port to Win7 DDI
5274 // //pCreateContext->ContextInfo.DmaBufferAllocationGroup = ???;
5275 //#endif // DXGKDDI_INTERFACE_VERSION
5276 }
5277 else
5278 vboxWddmMemFree(pContext);
5279 }
5280 else
5281 Status = STATUS_NO_MEMORY;
5282
5283 dfprintf(("<== "__FUNCTION__ ", hDevice(0x%x)\n", hDevice));
5284
5285 return Status;
5286}
5287
5288NTSTATUS
5289APIENTRY
5290DxgkDdiDestroyContext(
5291 CONST HANDLE hContext)
5292{
5293 dfprintf(("==> "__FUNCTION__ ", hContext(0x%x)\n", hContext));
5294 vboxVDbgBreakFv();
5295 PVBOXWDDM_CONTEXT pContext = (PVBOXWDDM_CONTEXT)hContext;
5296 PDEVICE_EXTENSION pDevExt = pContext->pDevice->pAdapter;
5297 if (pContext->enmType == VBOXWDDM_CONTEXT_TYPE_CUSTOM_3D)
5298 {
5299 Assert(KeGetCurrentIrql() < DISPATCH_LEVEL);
5300// ExAcquireFastMutex(&pDevExt->ContextMutex);
5301// RemoveEntryList(&pContext->ListEntry);
5302 uint32_t cContexts = ASMAtomicDecU32(&pDevExt->cContexts3D);
5303// ExReleaseFastMutex(&pDevExt->ContextMutex);
5304 Assert(cContexts < UINT32_MAX/2);
5305 }
5306
5307 NTSTATUS Status = vboxVideoAMgrCtxDestroy(&pContext->AllocContext);
5308 Assert(Status == STATUS_SUCCESS);
5309 if (Status == STATUS_SUCCESS)
5310 {
5311 Status = vboxVideoCmCtxRemove(&pContext->pDevice->pAdapter->CmMgr, &pContext->CmContext);
5312 Assert(Status == STATUS_SUCCESS);
5313 if (Status == STATUS_SUCCESS)
5314 {
5315 vboxWddmSwapchainCtxDestroyAll(pDevExt, pContext);
5316 vboxWddmMemFree(pContext);
5317 }
5318 }
5319
5320 dfprintf(("<== "__FUNCTION__ ", hContext(0x%x)\n", hContext));
5321
5322 return Status;
5323}
5324
5325NTSTATUS
5326APIENTRY
5327DxgkDdiLinkDevice(
5328 __in CONST PDEVICE_OBJECT PhysicalDeviceObject,
5329 __in CONST PVOID MiniportDeviceContext,
5330 __inout PLINKED_DEVICE LinkedDevice
5331 )
5332{
5333 drprintf(("==> "__FUNCTION__ ", MiniportDeviceContext(0x%x)\n", MiniportDeviceContext));
5334 vboxVDbgBreakFv();
5335 AssertBreakpoint();
5336 drprintf(("<== "__FUNCTION__ ", MiniportDeviceContext(0x%x)\n", MiniportDeviceContext));
5337 return STATUS_NOT_IMPLEMENTED;
5338}
5339
5340NTSTATUS
5341APIENTRY
5342DxgkDdiSetDisplayPrivateDriverFormat(
5343 CONST HANDLE hAdapter,
5344 /*CONST*/ DXGKARG_SETDISPLAYPRIVATEDRIVERFORMAT* pSetDisplayPrivateDriverFormat
5345 )
5346{
5347 dfprintf(("==> "__FUNCTION__ ", hAdapter(0x%x)\n", hAdapter));
5348 vboxVDbgBreakFv();
5349 AssertBreakpoint();
5350 dfprintf(("<== "__FUNCTION__ ", hAdapter(0x%x)\n", hAdapter));
5351 return STATUS_SUCCESS;
5352}
5353
5354NTSTATUS APIENTRY CALLBACK DxgkDdiRestartFromTimeout(IN_CONST_HANDLE hAdapter)
5355{
5356 dfprintf(("==> "__FUNCTION__ ", hAdapter(0x%x)\n", hAdapter));
5357 vboxVDbgBreakFv();
5358 AssertBreakpoint();
5359 dfprintf(("<== "__FUNCTION__ ", hAdapter(0x%x)\n", hAdapter));
5360 return STATUS_SUCCESS;
5361}
5362
5363NTSTATUS
5364DriverEntry(
5365 IN PDRIVER_OBJECT DriverObject,
5366 IN PUNICODE_STRING RegistryPath
5367 )
5368{
5369 PAGED_CODE();
5370
5371 vboxVDbgBreakFv();
5372
5373 drprintf(("VBoxVideoWddm::DriverEntry. Built %s %s\n", __DATE__, __TIME__));
5374
5375 DRIVER_INITIALIZATION_DATA DriverInitializationData = {'\0'};
5376
5377 if (! ARGUMENT_PRESENT(DriverObject) ||
5378 ! ARGUMENT_PRESENT(RegistryPath))
5379 {
5380 return STATUS_INVALID_PARAMETER;
5381 }
5382
5383 // Fill in the DriverInitializationData structure and call DxgkInitialize()
5384 DriverInitializationData.Version = DXGKDDI_INTERFACE_VERSION;
5385
5386 DriverInitializationData.DxgkDdiAddDevice = DxgkDdiAddDevice;
5387 DriverInitializationData.DxgkDdiStartDevice = DxgkDdiStartDevice;
5388 DriverInitializationData.DxgkDdiStopDevice = DxgkDdiStopDevice;
5389 DriverInitializationData.DxgkDdiRemoveDevice = DxgkDdiRemoveDevice;
5390 DriverInitializationData.DxgkDdiDispatchIoRequest = DxgkDdiDispatchIoRequest;
5391 DriverInitializationData.DxgkDdiInterruptRoutine = DxgkDdiInterruptRoutine;
5392 DriverInitializationData.DxgkDdiDpcRoutine = DxgkDdiDpcRoutine;
5393 DriverInitializationData.DxgkDdiQueryChildRelations = DxgkDdiQueryChildRelations;
5394 DriverInitializationData.DxgkDdiQueryChildStatus = DxgkDdiQueryChildStatus;
5395 DriverInitializationData.DxgkDdiQueryDeviceDescriptor = DxgkDdiQueryDeviceDescriptor;
5396 DriverInitializationData.DxgkDdiSetPowerState = DxgkDdiSetPowerState;
5397 DriverInitializationData.DxgkDdiNotifyAcpiEvent = DxgkDdiNotifyAcpiEvent;
5398 DriverInitializationData.DxgkDdiResetDevice = DxgkDdiResetDevice;
5399 DriverInitializationData.DxgkDdiUnload = DxgkDdiUnload;
5400 DriverInitializationData.DxgkDdiQueryInterface = DxgkDdiQueryInterface;
5401 DriverInitializationData.DxgkDdiControlEtwLogging = DxgkDdiControlEtwLogging;
5402
5403 DriverInitializationData.DxgkDdiQueryAdapterInfo = DxgkDdiQueryAdapterInfo;
5404 DriverInitializationData.DxgkDdiCreateDevice = DxgkDdiCreateDevice;
5405 DriverInitializationData.DxgkDdiCreateAllocation = DxgkDdiCreateAllocation;
5406 DriverInitializationData.DxgkDdiDestroyAllocation = DxgkDdiDestroyAllocation;
5407 DriverInitializationData.DxgkDdiDescribeAllocation = DxgkDdiDescribeAllocation;
5408 DriverInitializationData.DxgkDdiGetStandardAllocationDriverData = DxgkDdiGetStandardAllocationDriverData;
5409 DriverInitializationData.DxgkDdiAcquireSwizzlingRange = DxgkDdiAcquireSwizzlingRange;
5410 DriverInitializationData.DxgkDdiReleaseSwizzlingRange = DxgkDdiReleaseSwizzlingRange;
5411 DriverInitializationData.DxgkDdiPatch = DxgkDdiPatch;
5412 DriverInitializationData.DxgkDdiSubmitCommand = DxgkDdiSubmitCommand;
5413 DriverInitializationData.DxgkDdiPreemptCommand = DxgkDdiPreemptCommand;
5414 DriverInitializationData.DxgkDdiBuildPagingBuffer = DxgkDdiBuildPagingBuffer;
5415 DriverInitializationData.DxgkDdiSetPalette = DxgkDdiSetPalette;
5416 DriverInitializationData.DxgkDdiSetPointerPosition = DxgkDdiSetPointerPosition;
5417 DriverInitializationData.DxgkDdiSetPointerShape = DxgkDdiSetPointerShape;
5418 DriverInitializationData.DxgkDdiResetFromTimeout = DxgkDdiResetFromTimeout;
5419 DriverInitializationData.DxgkDdiRestartFromTimeout = DxgkDdiRestartFromTimeout;
5420 DriverInitializationData.DxgkDdiEscape = DxgkDdiEscape;
5421 DriverInitializationData.DxgkDdiCollectDbgInfo = DxgkDdiCollectDbgInfo;
5422 DriverInitializationData.DxgkDdiQueryCurrentFence = DxgkDdiQueryCurrentFence;
5423 DriverInitializationData.DxgkDdiIsSupportedVidPn = DxgkDdiIsSupportedVidPn;
5424 DriverInitializationData.DxgkDdiRecommendFunctionalVidPn = DxgkDdiRecommendFunctionalVidPn;
5425 DriverInitializationData.DxgkDdiEnumVidPnCofuncModality = DxgkDdiEnumVidPnCofuncModality;
5426 DriverInitializationData.DxgkDdiSetVidPnSourceAddress = DxgkDdiSetVidPnSourceAddress;
5427 DriverInitializationData.DxgkDdiSetVidPnSourceVisibility = DxgkDdiSetVidPnSourceVisibility;
5428 DriverInitializationData.DxgkDdiCommitVidPn = DxgkDdiCommitVidPn;
5429 DriverInitializationData.DxgkDdiUpdateActiveVidPnPresentPath = DxgkDdiUpdateActiveVidPnPresentPath;
5430 DriverInitializationData.DxgkDdiRecommendMonitorModes = DxgkDdiRecommendMonitorModes;
5431 DriverInitializationData.DxgkDdiRecommendVidPnTopology = DxgkDdiRecommendVidPnTopology;
5432 DriverInitializationData.DxgkDdiGetScanLine = DxgkDdiGetScanLine;
5433 DriverInitializationData.DxgkDdiStopCapture = DxgkDdiStopCapture;
5434 DriverInitializationData.DxgkDdiControlInterrupt = DxgkDdiControlInterrupt;
5435 DriverInitializationData.DxgkDdiCreateOverlay = DxgkDdiCreateOverlay;
5436
5437 DriverInitializationData.DxgkDdiDestroyDevice = DxgkDdiDestroyDevice;
5438 DriverInitializationData.DxgkDdiOpenAllocation = DxgkDdiOpenAllocation;
5439 DriverInitializationData.DxgkDdiCloseAllocation = DxgkDdiCloseAllocation;
5440 DriverInitializationData.DxgkDdiRender = DxgkDdiRender;
5441 DriverInitializationData.DxgkDdiPresent = DxgkDdiPresent;
5442
5443 DriverInitializationData.DxgkDdiUpdateOverlay = DxgkDdiUpdateOverlay;
5444 DriverInitializationData.DxgkDdiFlipOverlay = DxgkDdiFlipOverlay;
5445 DriverInitializationData.DxgkDdiDestroyOverlay = DxgkDdiDestroyOverlay;
5446
5447 DriverInitializationData.DxgkDdiCreateContext = DxgkDdiCreateContext;
5448 DriverInitializationData.DxgkDdiDestroyContext = DxgkDdiDestroyContext;
5449
5450 DriverInitializationData.DxgkDdiLinkDevice = NULL; //DxgkDdiLinkDevice;
5451 DriverInitializationData.DxgkDdiSetDisplayPrivateDriverFormat = DxgkDdiSetDisplayPrivateDriverFormat;
5452//#if (DXGKDDI_INTERFACE_VERSION >= DXGKDDI_INTERFACE_VERSION_WIN7)
5453//# error port to Win7 DDI
5454// DriverInitializationData.DxgkDdiRenderKm = DxgkDdiRenderKm;
5455// DriverInitializationData.DxgkDdiRestartFromTimeout = DxgkDdiRestartFromTimeout;
5456// DriverInitializationData.DxgkDdiSetVidPnSourceVisibility = DxgkDdiSetVidPnSourceVisibility;
5457// DriverInitializationData.DxgkDdiUpdateActiveVidPnPresentPath = DxgkDdiUpdateActiveVidPnPresentPath;
5458// DriverInitializationData.DxgkDdiQueryVidPnHWCapability = DxgkDdiQueryVidPnHWCapability;
5459//#endif
5460
5461 return DxgkInitialize(DriverObject,
5462 RegistryPath,
5463 &DriverInitializationData);
5464}
Note: See TracBrowser for help on using the repository browser.

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