VirtualBox

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

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

wddm: more multi-monitor fixes

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