VirtualBox

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

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

wddm/3d: chromium hgsmi fixes

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

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