VirtualBox

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

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