VirtualBox

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

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

wddm: disable for guest installer

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

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