VirtualBox

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

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

adds burn fix

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 205.5 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#ifdef VBOX_WITH_VDMA
2572 UINT cbCmd = VBOXVDMACMD_SIZE(VBOXVDMACMD_DMA_BPB_TRANSFER);
2573 PVBOXVDMACBUF_DR pDr = vboxVdmaCBufDrCreate (&pDevExt->u.primary.Vdma, cbCmd);
2574 Assert(pDr);
2575 if (pDr)
2576 {
2577 // vboxVdmaCBufDrCreate zero initializes the pDr
2578 pDr->fFlags = VBOXVDMACBUF_FLAG_BUF_FOLLOWS_DR;
2579 pDr->cbBuf = cbCmd;
2580 pDr->rc = VERR_NOT_IMPLEMENTED;
2581
2582 PVBOXVDMACMD pHdr = VBOXVDMACBUF_DR_TAIL(pDr, VBOXVDMACMD);
2583 pHdr->enmType = VBOXVDMACMD_TYPE_DMA_BPB_TRANSFER;
2584 pHdr->u32CmdSpecific = 0;
2585 VBOXVDMACMD_DMA_BPB_TRANSFER *pBody = VBOXVDMACMD_BODY(pHdr, VBOXVDMACMD_DMA_BPB_TRANSFER);
2586 pBody->cbTransferSize = (uint32_t)pBuildPagingBuffer->Transfer.TransferSize;
2587 pBody->fFlags = 0;
2588
2589 if (pBuildPagingBuffer->Transfer.Source.SegmentId)
2590 {
2591#ifdef DEBUG_misha
2592 Assert(pBuildPagingBuffer->Transfer.Source.SegmentAddress.QuadPart);
2593#endif
2594 uint64_t off = pBuildPagingBuffer->Transfer.Source.SegmentAddress.QuadPart;
2595 off += pBuildPagingBuffer->Transfer.TransferOffset;
2596 pBody->Src.offVramBuf = off;
2597 pBody->fFlags |= VBOXVDMACMD_DMA_BPB_TRANSFER_F_SRC_VRAMOFFSET;
2598 }
2599 else
2600 {
2601 pBody->Src.phBuf = MmGetMdlPfnArray(pBuildPagingBuffer->Transfer.Source.pMdl)[pBuildPagingBuffer->Transfer.MdlOffset] << 12;
2602#ifdef DEBUG
2603 {
2604 PFN_NUMBER num = MmGetMdlPfnArray(pBuildPagingBuffer->Transfer.Source.pMdl)[pBuildPagingBuffer->Transfer.MdlOffset];
2605 for (UINT i = 1; i < ((pBuildPagingBuffer->Transfer.TransferSize + 0xfff) >> 12); ++i)
2606 {
2607 PFN_NUMBER cur = MmGetMdlPfnArray(pBuildPagingBuffer->Transfer.Source.pMdl)[pBuildPagingBuffer->Transfer.MdlOffset+1];
2608 Assert(cur == ++num);
2609 }
2610 }
2611#endif
2612 }
2613
2614 if (pBuildPagingBuffer->Transfer.Destination.SegmentId)
2615 {
2616#ifdef DEBUG_misha
2617 Assert(pBuildPagingBuffer->Transfer.Destination.SegmentAddress.QuadPart);
2618#endif
2619 uint64_t off = pBuildPagingBuffer->Transfer.Destination.SegmentAddress.QuadPart;
2620 off += pBuildPagingBuffer->Transfer.TransferOffset;
2621 pBody->Dst.offVramBuf = off;
2622 pBody->fFlags |= VBOXVDMACMD_DMA_BPB_TRANSFER_F_DST_VRAMOFFSET;
2623 }
2624 else
2625 {
2626 pBody->Dst.phBuf = MmGetMdlPfnArray(pBuildPagingBuffer->Transfer.Destination.pMdl)[pBuildPagingBuffer->Transfer.MdlOffset] << 12;
2627#ifdef DEBUG
2628 {
2629 PFN_NUMBER num = MmGetMdlPfnArray(pBuildPagingBuffer->Transfer.Destination.pMdl)[pBuildPagingBuffer->Transfer.MdlOffset];
2630 for (UINT i = 1; i < ((pBuildPagingBuffer->Transfer.TransferSize + 0xfff) >> 12); ++i)
2631 {
2632 PFN_NUMBER cur = MmGetMdlPfnArray(pBuildPagingBuffer->Transfer.Destination.pMdl)[pBuildPagingBuffer->Transfer.MdlOffset+1];
2633 Assert(cur == ++num);
2634 }
2635 }
2636#endif
2637 }
2638
2639 int rc = vboxVdmaCBufDrSubmitSynch(pDevExt, &pDevExt->u.primary.Vdma, pDr);
2640 AssertRC(rc);
2641 if (RT_SUCCESS(rc))
2642 Status = STATUS_SUCCESS;
2643 else
2644 Status = STATUS_UNSUCCESSFUL;
2645
2646 vboxVdmaCBufDrFree(&pDevExt->u.primary.Vdma, pDr);
2647 }
2648 else
2649 {
2650 /* @todo: try flushing.. */
2651 drprintf((__FUNCTION__": vboxVdmaCBufDrCreate returned NULL\n"));
2652 Status = STATUS_INSUFFICIENT_RESOURCES;
2653 }
2654#endif /* #ifdef VBOX_WITH_VDMA */
2655 break;
2656 }
2657 case DXGK_OPERATION_FILL:
2658 {
2659// pBuildPagingBuffer->pDmaBuffer = (uint8_t*)pBuildPagingBuffer->pDmaBuffer + VBOXVDMACMD_SIZE(VBOXVDMACMD_DMA_BPB_FILL);
2660 break;
2661 }
2662 case DXGK_OPERATION_DISCARD_CONTENT:
2663 {
2664// AssertBreakpoint();
2665 break;
2666 }
2667 default:
2668 {
2669 drprintf((__FUNCTION__": unsupported op (%d)\n", pBuildPagingBuffer->Operation));
2670 AssertBreakpoint();
2671 break;
2672 }
2673 }
2674
2675 dfprintf(("<== "__FUNCTION__ ", context(0x%x)\n", hAdapter));
2676
2677 return Status;
2678
2679}
2680
2681NTSTATUS
2682APIENTRY
2683DxgkDdiSetPalette(
2684 CONST HANDLE hAdapter,
2685 CONST DXGKARG_SETPALETTE* pSetPalette
2686 )
2687{
2688 dfprintf(("==> "__FUNCTION__ ", hAdapter(0x%x)\n", hAdapter));
2689
2690 AssertBreakpoint();
2691 /* @todo: fixme: implement */
2692
2693 dfprintf(("<== "__FUNCTION__ ", hAdapter(0x%x)\n", hAdapter));
2694
2695 return STATUS_SUCCESS;
2696}
2697
2698BOOL vboxWddmPointerCopyColorData(CONST DXGKARG_SETPOINTERSHAPE* pSetPointerShape, PVIDEO_POINTER_ATTRIBUTES pPointerAttributes)
2699{
2700 /* Format of "hardware" pointer is:
2701 * 1 bpp AND mask with byte aligned scanlines,
2702 * B G R A bytes of XOR mask that starts on the next 4 byte aligned offset after AND mask.
2703 *
2704 * If fl & SPS_ALPHA then A bytes contain alpha channel information.
2705 * Otherwise A bytes are undefined (but will be 0).
2706 *
2707 */
2708 PBYTE pjSrcAnd = NULL;
2709 PBYTE pjSrcXor = NULL;
2710
2711 ULONG cy = 0;
2712
2713 PBYTE pjDstAnd = pPointerAttributes->Pixels;
2714 ULONG cjAnd = 0;
2715 PBYTE pjDstXor = pPointerAttributes->Pixels;
2716
2717 ULONG cxSrc = pSetPointerShape->Width;
2718 ULONG cySrc = pSetPointerShape->Width;
2719
2720 // Make sure the new pointer isn't too big to handle,
2721 // strip the size to 64x64 if necessary
2722 if (cxSrc > VBOXWDDM_C_POINTER_MAX_WIDTH)
2723 cxSrc = VBOXWDDM_C_POINTER_MAX_WIDTH;
2724
2725 if (cySrc > VBOXWDDM_C_POINTER_MAX_HEIGHT)
2726 cySrc = VBOXWDDM_C_POINTER_MAX_HEIGHT;
2727
2728 /* Size of AND mask in bytes */
2729 cjAnd = ((cxSrc + 7) / 8) * cySrc;
2730
2731 /* Pointer to XOR mask is 4-bytes aligned */
2732 pjDstXor += (cjAnd + 3) & ~3;
2733
2734 pPointerAttributes->Width = cxSrc;
2735 pPointerAttributes->Height = cySrc;
2736 pPointerAttributes->WidthInBytes = cxSrc * 4;
2737
2738 uint32_t cbData = ((cjAnd + 3) & ~3) + pPointerAttributes->Height*pPointerAttributes->WidthInBytes;
2739 uint32_t cbPointerAttributes = RT_OFFSETOF(VIDEO_POINTER_ATTRIBUTES, Pixels[cbData]);
2740 Assert(VBOXWDDM_POINTER_ATTRIBUTES_SIZE >= cbPointerAttributes);
2741 if (VBOXWDDM_POINTER_ATTRIBUTES_SIZE < cbPointerAttributes)
2742 {
2743 drprintf((__FUNCTION__": VBOXWDDM_POINTER_ATTRIBUTES_SIZE(%d) < cbPointerAttributes(%d)\n", VBOXWDDM_POINTER_ATTRIBUTES_SIZE, cbPointerAttributes));
2744 return FALSE;
2745 }
2746
2747 /* Init AND mask to 1 */
2748 RtlFillMemory (pjDstAnd, cjAnd, 0xFF);
2749
2750 PBYTE pjSrcAlpha = (PBYTE)pSetPointerShape->pPixels;
2751
2752 /*
2753 * Emulate AND mask to provide viewable mouse pointer for
2754 * hardware which does not support alpha channel.
2755 */
2756
2757 for (cy = 0; cy < cySrc; cy++)
2758 {
2759 ULONG cx;
2760
2761 UCHAR bitmask = 0x80;
2762
2763 for (cx = 0; cx < cxSrc; cx++, bitmask >>= 1)
2764 {
2765 if (bitmask == 0)
2766 {
2767 bitmask = 0x80;
2768 }
2769
2770 if (pjSrcAlpha[cx * 4 + 3] > 0x7f)
2771 {
2772 pjDstAnd[cx / 8] &= ~bitmask;
2773 }
2774 }
2775
2776 // Point to next source and dest scans
2777 pjSrcAlpha += pSetPointerShape->Pitch;
2778 pjDstAnd += (cxSrc + 7) / 8;
2779 }
2780
2781 /*
2782 * pso is 32 bit BGRX bitmap. Copy it to Pixels
2783 */
2784 pjSrcXor = (PBYTE)pSetPointerShape->pPixels;
2785 for (cy = 0; cy < cySrc; cy++)
2786 {
2787 /* 32 bit bitmap is being copied */
2788 RtlCopyMemory (pjDstXor, pjSrcXor, cxSrc * 4);
2789
2790 /* Point to next source and dest scans */
2791 pjSrcXor += pSetPointerShape->Pitch;
2792 pjDstXor += pPointerAttributes->WidthInBytes;
2793 }
2794
2795 return TRUE;
2796}
2797
2798BOOL vboxWddmPointerCopyMonoData(CONST DXGKARG_SETPOINTERSHAPE* pSetPointerShape, PVIDEO_POINTER_ATTRIBUTES pPointerAttributes)
2799{
2800 PBYTE pjSrc = NULL;
2801
2802 ULONG cy = 0;
2803
2804 PBYTE pjDstAnd = pPointerAttributes->Pixels;
2805 ULONG cjAnd = 0;
2806 PBYTE pjDstXor = pPointerAttributes->Pixels;
2807
2808 ULONG cxSrc = pSetPointerShape->Width;
2809 ULONG cySrc = pSetPointerShape->Height;
2810
2811 // Make sure the new pointer isn't too big to handle,
2812 // strip the size to 64x64 if necessary
2813 if (cxSrc > VBOXWDDM_C_POINTER_MAX_WIDTH)
2814 cxSrc = VBOXWDDM_C_POINTER_MAX_WIDTH;
2815
2816 if (cySrc > VBOXWDDM_C_POINTER_MAX_HEIGHT)
2817 cySrc = VBOXWDDM_C_POINTER_MAX_HEIGHT;
2818
2819 /* Size of AND mask in bytes */
2820 cjAnd = ((cxSrc + 7) / 8) * cySrc;
2821
2822 /* Pointer to XOR mask is 4-bytes aligned */
2823 pjDstXor += (cjAnd + 3) & ~3;
2824
2825 pPointerAttributes->Width = cxSrc;
2826 pPointerAttributes->Height = cySrc;
2827 pPointerAttributes->WidthInBytes = cxSrc * 4;
2828
2829 /* Init AND mask to 1 */
2830 RtlFillMemory (pjDstAnd, cjAnd, 0xFF);
2831
2832 /*
2833 * Copy AND mask.
2834 */
2835 pjSrc = (PBYTE)pSetPointerShape->pPixels;
2836
2837 for (cy = 0; cy < cySrc; cy++)
2838 {
2839 RtlCopyMemory (pjDstAnd, pjSrc, (cxSrc + 7) / 8);
2840
2841 // Point to next source and dest scans
2842 pjSrc += pSetPointerShape->Pitch;
2843 pjDstAnd += (cxSrc + 7) / 8;
2844 }
2845
2846 for (cy = 0; cy < cySrc; ++cy)
2847 {
2848 ULONG cx;
2849
2850 UCHAR bitmask = 0x80;
2851
2852 for (cx = 0; cx < cxSrc; cx++, bitmask >>= 1)
2853 {
2854 if (bitmask == 0)
2855 {
2856 bitmask = 0x80;
2857 }
2858
2859 if (pjSrc[cx / 8] & bitmask)
2860 {
2861 *(ULONG *)&pjDstXor[cx * 4] = 0x00FFFFFF;
2862 }
2863 else
2864 {
2865 *(ULONG *)&pjDstXor[cx * 4] = 0;
2866 }
2867 }
2868
2869 // Point to next source and dest scans
2870 pjSrc += pSetPointerShape->Pitch;
2871 pjDstXor += cxSrc * 4;
2872 }
2873
2874 return TRUE;
2875}
2876
2877static BOOLEAN vboxVddmPointerShapeToAttributes(CONST DXGKARG_SETPOINTERSHAPE* pSetPointerShape, PVBOXWDDM_POINTER_INFO pPointerInfo)
2878{
2879 PVIDEO_POINTER_ATTRIBUTES pPointerAttributes = &pPointerInfo->Attributes.data;
2880 /* pPointerAttributes maintains the visibility state, clear all except visibility */
2881 pPointerAttributes->Enable &= VBOX_MOUSE_POINTER_VISIBLE;
2882
2883 Assert(pSetPointerShape->Flags.Value == 1 || pSetPointerShape->Flags.Value == 2);
2884 if (pSetPointerShape->Flags.Color)
2885 {
2886 if (vboxWddmPointerCopyColorData(pSetPointerShape, pPointerAttributes))
2887 {
2888 pPointerAttributes->Flags = VIDEO_MODE_COLOR_POINTER;
2889 pPointerAttributes->Enable |= VBOX_MOUSE_POINTER_ALPHA;
2890 }
2891 else
2892 {
2893 drprintf((__FUNCTION__": vboxWddmPointerCopyColorData failed\n"));
2894 AssertBreakpoint();
2895 return FALSE;
2896 }
2897
2898 }
2899 else if (pSetPointerShape->Flags.Monochrome)
2900 {
2901 if (vboxWddmPointerCopyMonoData(pSetPointerShape, pPointerAttributes))
2902 {
2903 pPointerAttributes->Flags = VIDEO_MODE_MONO_POINTER;
2904 }
2905 else
2906 {
2907 drprintf((__FUNCTION__": vboxWddmPointerCopyMonoData failed\n"));
2908 AssertBreakpoint();
2909 return FALSE;
2910 }
2911 }
2912 else
2913 {
2914 drprintf((__FUNCTION__": unsupported pointer type Flags.Value(0x%x)\n", pSetPointerShape->Flags.Value));
2915 AssertBreakpoint();
2916 return FALSE;
2917 }
2918
2919 pPointerAttributes->Enable |= VBOX_MOUSE_POINTER_SHAPE;
2920
2921 /*
2922 * The hot spot coordinates and alpha flag will be encoded in the pPointerAttributes::Enable field.
2923 * High word will contain hot spot info and low word - flags.
2924 */
2925 pPointerAttributes->Enable |= (pSetPointerShape->YHot & 0xFF) << 24;
2926 pPointerAttributes->Enable |= (pSetPointerShape->XHot & 0xFF) << 16;
2927
2928 return TRUE;
2929}
2930
2931NTSTATUS
2932APIENTRY
2933DxgkDdiSetPointerPosition(
2934 CONST HANDLE hAdapter,
2935 CONST DXGKARG_SETPOINTERPOSITION* pSetPointerPosition)
2936{
2937// dfprintf(("==> "__FUNCTION__ ", hAdapter(0x%x)\n", hAdapter));
2938
2939 vboxVDbgBreakFv();
2940
2941 /* mouse integration is ON */
2942 PDEVICE_EXTENSION pDevExt = (PDEVICE_EXTENSION)hAdapter;
2943 PVBOXWDDM_POINTER_INFO pPointerInfo = &pDevExt->aSources[pSetPointerPosition->VidPnSourceId].PointerInfo;
2944 PVBOXWDDM_GLOBAL_POINTER_INFO pGlobalPointerInfo = &pDevExt->PointerInfo;
2945 PVIDEO_POINTER_ATTRIBUTES pPointerAttributes = &pPointerInfo->Attributes.data;
2946 BOOLEAN bNotifyVisibility;
2947 if (pSetPointerPosition->Flags.Visible)
2948 {
2949 bNotifyVisibility = (pGlobalPointerInfo->cVisible == 0);
2950 if (!(pPointerAttributes->Enable & VBOX_MOUSE_POINTER_VISIBLE))
2951 {
2952 ++pGlobalPointerInfo->cVisible;
2953 pPointerAttributes->Enable |= VBOX_MOUSE_POINTER_VISIBLE;
2954 }
2955 }
2956 else
2957 {
2958 if (!!(pPointerAttributes->Enable & VBOX_MOUSE_POINTER_VISIBLE))
2959 {
2960 --pGlobalPointerInfo->cVisible;
2961 Assert(pGlobalPointerInfo->cVisible < UINT32_MAX/2);
2962 pPointerAttributes->Enable &= ~VBOX_MOUSE_POINTER_VISIBLE;
2963 bNotifyVisibility = (pGlobalPointerInfo->cVisible == 0);
2964 }
2965 }
2966
2967 pPointerAttributes->Column = pSetPointerPosition->X;
2968 pPointerAttributes->Row = pSetPointerPosition->Y;
2969
2970 if (bNotifyVisibility && vboxQueryHostWantsAbsolute())
2971 {
2972 // tell the host to use the guest's pointer
2973 VIDEO_POINTER_ATTRIBUTES PointerAttributes;
2974
2975 /* Visible and No Shape means Show the pointer.
2976 * It is enough to init only this field.
2977 */
2978 PointerAttributes.Enable = pSetPointerPosition->Flags.Visible ? VBOX_MOUSE_POINTER_VISIBLE : 0;
2979
2980 BOOLEAN bResult = vboxUpdatePointerShape(pDevExt, &PointerAttributes, sizeof (PointerAttributes));
2981 Assert(bResult);
2982 }
2983
2984// dfprintf(("<== "__FUNCTION__ ", hAdapter(0x%x)\n", hAdapter));
2985
2986 return STATUS_SUCCESS;
2987}
2988
2989NTSTATUS
2990APIENTRY
2991DxgkDdiSetPointerShape(
2992 CONST HANDLE hAdapter,
2993 CONST DXGKARG_SETPOINTERSHAPE* pSetPointerShape)
2994{
2995// dfprintf(("==> "__FUNCTION__ ", hAdapter(0x%x)\n", hAdapter));
2996
2997 vboxVDbgBreakFv();
2998
2999 NTSTATUS Status = STATUS_NOT_SUPPORTED;
3000
3001 if (vboxQueryHostWantsAbsolute())
3002 {
3003 /* mouse integration is ON */
3004 PDEVICE_EXTENSION pDevExt = (PDEVICE_EXTENSION)hAdapter;
3005 PVBOXWDDM_POINTER_INFO pPointerInfo = &pDevExt->aSources[pSetPointerShape->VidPnSourceId].PointerInfo;
3006 /* @todo: to avoid extra data copy and extra heap allocation,
3007 * need to maintain the pre-allocated HGSMI buffer and convert the data directly to it */
3008 if (vboxVddmPointerShapeToAttributes(pSetPointerShape, pPointerInfo))
3009 {
3010 if (vboxUpdatePointerShape (pDevExt, &pPointerInfo->Attributes.data, VBOXWDDM_POINTER_ATTRIBUTES_SIZE))
3011 Status = STATUS_SUCCESS;
3012 else
3013 {
3014 AssertBreakpoint();
3015 drprintf((__FUNCTION__": vboxUpdatePointerShape failed\n"));
3016 }
3017 }
3018 }
3019
3020// dfprintf(("<== "__FUNCTION__ ", hAdapter(0x%x)\n", hAdapter));
3021
3022 return Status;
3023}
3024
3025NTSTATUS
3026APIENTRY CALLBACK
3027DxgkDdiResetFromTimeout(
3028 CONST HANDLE hAdapter)
3029{
3030 dfprintf(("==> "__FUNCTION__ ", hAdapter(0x%x)\n", hAdapter));
3031
3032 AssertBreakpoint();
3033 /* @todo: fixme: implement */
3034
3035 dfprintf(("<== "__FUNCTION__ ", hAdapter(0x%x)\n", hAdapter));
3036
3037 return STATUS_SUCCESS;
3038}
3039
3040
3041/* the lpRgnData->Buffer comes to us as RECT
3042 * to avoid extra memcpy we cast it to PRTRECT assuming
3043 * they are identical */
3044AssertCompile(sizeof(RECT) == sizeof(RTRECT));
3045AssertCompile(RT_OFFSETOF(RECT, left) == RT_OFFSETOF(RTRECT, xLeft));
3046AssertCompile(RT_OFFSETOF(RECT, bottom) == RT_OFFSETOF(RTRECT, yBottom));
3047AssertCompile(RT_OFFSETOF(RECT, right) == RT_OFFSETOF(RTRECT, xRight));
3048AssertCompile(RT_OFFSETOF(RECT, top) == RT_OFFSETOF(RTRECT, yTop));
3049
3050NTSTATUS
3051APIENTRY
3052DxgkDdiEscape(
3053 CONST HANDLE hAdapter,
3054 CONST DXGKARG_ESCAPE* pEscape)
3055{
3056 PAGED_CODE();
3057
3058// dfprintf(("==> "__FUNCTION__ ", hAdapter(0x%x)\n", hAdapter));
3059
3060 NTSTATUS Status = STATUS_NOT_SUPPORTED;
3061 PDEVICE_EXTENSION pDevExt = (PDEVICE_EXTENSION)hAdapter;
3062 Assert(pEscape->PrivateDriverDataSize >= sizeof (VBOXDISPIFESCAPE));
3063 if (pEscape->PrivateDriverDataSize >= sizeof (VBOXDISPIFESCAPE))
3064 {
3065 PVBOXDISPIFESCAPE pEscapeHdr = (PVBOXDISPIFESCAPE)pEscape->pPrivateDriverData;
3066 switch (pEscapeHdr->escapeCode)
3067 {
3068 case VBOXESC_GETVBOXVIDEOCMCMD:
3069 {
3070 PVBOXWDDM_CONTEXT pContext = (PVBOXWDDM_CONTEXT)pEscape->hContext;
3071 PVBOXDISPIFESCAPE_GETVBOXVIDEOCMCMD pRegions = (PVBOXDISPIFESCAPE_GETVBOXVIDEOCMCMD)pEscapeHdr;
3072 Assert(pEscape->PrivateDriverDataSize >= sizeof (VBOXDISPIFESCAPE_GETVBOXVIDEOCMCMD));
3073 if (pEscape->PrivateDriverDataSize >= sizeof (VBOXDISPIFESCAPE_GETVBOXVIDEOCMCMD))
3074 {
3075 Status = vboxVideoCmEscape(&pContext->CmContext, pRegions, pEscape->PrivateDriverDataSize);
3076 Assert(Status == STATUS_SUCCESS);
3077 }
3078 else
3079 Status = STATUS_BUFFER_TOO_SMALL;
3080
3081 break;
3082 }
3083 case VBOXESC_SETVISIBLEREGION:
3084 {
3085 LPRGNDATA lpRgnData = VBOXDISPIFESCAPE_DATA(pEscapeHdr, RGNDATA);
3086 uint32_t cbData = VBOXDISPIFESCAPE_DATA_SIZE(pEscape->PrivateDriverDataSize);
3087 uint32_t cbRects = cbData - RT_OFFSETOF(RGNDATA, Buffer);
3088 /* the lpRgnData->Buffer comes to us as RECT
3089 * to avoid extra memcpy we cast it to PRTRECT assuming
3090 * they are identical
3091 * see AssertCompile's above */
3092
3093 RTRECT *pRect = (RTRECT *)&lpRgnData->Buffer;
3094
3095 uint32_t cRects = cbRects/sizeof(RTRECT);
3096 int rc;
3097
3098 dprintf(("IOCTL_VIDEO_VBOX_SETVISIBLEREGION cRects=%d\n", cRects));
3099 Assert(cbRects >= sizeof(RTRECT)
3100 && cbRects == cRects*sizeof(RTRECT)
3101 && cRects == lpRgnData->rdh.nCount);
3102 if ( cbRects >= sizeof(RTRECT)
3103 && cbRects == cRects*sizeof(RTRECT)
3104 && cRects == lpRgnData->rdh.nCount)
3105 {
3106 /*
3107 * Inform the host about the visible region
3108 */
3109 VMMDevVideoSetVisibleRegion *req = NULL;
3110
3111 rc = VbglGRAlloc ((VMMDevRequestHeader **)&req,
3112 sizeof (VMMDevVideoSetVisibleRegion) + (cRects-1)*sizeof(RTRECT),
3113 VMMDevReq_VideoSetVisibleRegion);
3114 AssertRC(rc);
3115 if (RT_SUCCESS(rc))
3116 {
3117 req->cRect = cRects;
3118 memcpy(&req->Rect, pRect, cRects*sizeof(RTRECT));
3119
3120 rc = VbglGRPerform (&req->header);
3121 AssertRC(rc);
3122 if (!RT_SUCCESS(rc))
3123 {
3124 drprintf((__FUNCTION__": VbglGRPerform failed rc (%d)", rc));
3125 Status = STATUS_UNSUCCESSFUL;
3126 }
3127 }
3128 else
3129 {
3130 drprintf((__FUNCTION__": VbglGRAlloc failed rc (%d)", rc));
3131 Status = STATUS_UNSUCCESSFUL;
3132 }
3133 }
3134 else
3135 {
3136 drprintf((__FUNCTION__": VBOXESC_SETVISIBLEREGION: incorrect buffer size (%d), reported count (%d)\n", cbRects, lpRgnData->rdh.nCount));
3137 AssertBreakpoint();
3138 Status = STATUS_INVALID_PARAMETER;
3139 }
3140 break;
3141 }
3142 case VBOXESC_ISVRDPACTIVE:
3143 /* @todo: implement */
3144 Status = STATUS_SUCCESS;
3145 break;
3146 case VBOXESC_SCREENLAYOUT:
3147 {
3148 Assert(pEscape->PrivateDriverDataSize >= sizeof (VBOXDISPIFESCAPE_SCREENLAYOUT));
3149 if (pEscape->PrivateDriverDataSize >= sizeof (VBOXDISPIFESCAPE_SCREENLAYOUT))
3150 {
3151 PVBOXDISPIFESCAPE_SCREENLAYOUT pLo = (PVBOXDISPIFESCAPE_SCREENLAYOUT)pEscapeHdr;
3152 Assert(pLo->ScreenLayout.cScreens <= (UINT)pDevExt->u.primary.cDisplays);
3153 for (UINT i = 0; i < pLo->ScreenLayout.cScreens; ++i)
3154 {
3155 PVBOXSCREENLAYOUT_ELEMENT pEl = &pLo->ScreenLayout.aScreens[i];
3156 Assert(pEl->VidPnSourceId < (UINT)pDevExt->u.primary.cDisplays);
3157 if (pEl->VidPnSourceId < (UINT)pDevExt->u.primary.cDisplays)
3158 {
3159 PVBOXWDDM_SOURCE pSource = &pDevExt->aSources[pEl->VidPnSourceId];
3160 NTSTATUS tmpStatus = vboxWddmGhDisplayUpdateScreenPos(pDevExt, pSource, &pEl->pos);
3161 Assert(tmpStatus == STATUS_SUCCESS);
3162 }
3163 }
3164 Status = STATUS_SUCCESS;
3165 break;
3166 }
3167 else
3168 {
3169 drprintf((__FUNCTION__": VBOXESC_SCREENLAYOUT: incorrect buffer size (%d) < sizeof (VBOXDISPIFESCAPE_SCREENLAYOUT) (%d)\n",
3170 pEscape->PrivateDriverDataSize, sizeof (VBOXDISPIFESCAPE_SCREENLAYOUT)));
3171 AssertBreakpoint();
3172 Status = STATUS_INVALID_PARAMETER;
3173 }
3174 }
3175 case VBOXESC_SWAPCHAININFO:
3176 {
3177 PVBOXWDDM_CONTEXT pContext = (PVBOXWDDM_CONTEXT)pEscape->hContext;
3178 Status = vboxWddmSwapchainCtxEscape(pDevExt, pContext, (PVBOXDISPIFESCAPE_SWAPCHAININFO)pEscapeHdr, pEscape->PrivateDriverDataSize);
3179 Assert(Status == STATUS_SUCCESS);
3180 break;
3181 }
3182 case VBOXESC_REINITVIDEOMODES:
3183 VBoxWddmInvalidateModesTable(pDevExt);
3184 Status = STATUS_SUCCESS;
3185 break;
3186 case VBOXESC_DBGPRINT:
3187 {
3188 /* use RT_OFFSETOF instead of sizeof since sizeof will give an aligned size that might
3189 * be bigger than the VBOXDISPIFESCAPE_DBGPRINT with a data containing just a few chars */
3190 Assert(pEscape->PrivateDriverDataSize >= RT_OFFSETOF(VBOXDISPIFESCAPE_DBGPRINT, aStringBuf[1]));
3191 /* only do DbgPrint when pEscape->PrivateDriverDataSize > RT_OFFSETOF(VBOXDISPIFESCAPE_DBGPRINT, aStringBuf[1])
3192 * since == RT_OFFSETOF(VBOXDISPIFESCAPE_DBGPRINT, aStringBuf[1]) means the buffer contains just \0,
3193 * i.e. no need to print it */
3194 if (pEscape->PrivateDriverDataSize > RT_OFFSETOF(VBOXDISPIFESCAPE_DBGPRINT, aStringBuf[1]))
3195 {
3196 PVBOXDISPIFESCAPE_DBGPRINT pDbgPrint = (PVBOXDISPIFESCAPE_DBGPRINT)pEscapeHdr;
3197 /* ensure the last char is \0*/
3198 *((uint8_t*)pDbgPrint + pEscape->PrivateDriverDataSize - 1) = '\0';
3199 DbgPrint(pDbgPrint->aStringBuf);
3200 }
3201 Status = STATUS_SUCCESS;
3202 break;
3203 }
3204 default:
3205 Assert(0);
3206 drprintf((__FUNCTION__": unsupported escape code (0x%x)\n", pEscapeHdr->escapeCode));
3207 break;
3208 }
3209 }
3210 else
3211 {
3212 drprintf((__FUNCTION__": pEscape->PrivateDriverDataSize(%d) < (%d)\n", pEscape->PrivateDriverDataSize, sizeof (VBOXDISPIFESCAPE)));
3213 AssertBreakpoint();
3214 Status = STATUS_BUFFER_TOO_SMALL;
3215 }
3216
3217// dfprintf(("<== "__FUNCTION__ ", hAdapter(0x%x)\n", hAdapter));
3218
3219 return Status;
3220}
3221
3222NTSTATUS
3223APIENTRY
3224DxgkDdiCollectDbgInfo(
3225 CONST HANDLE hAdapter,
3226 CONST DXGKARG_COLLECTDBGINFO* pCollectDbgInfo
3227 )
3228{
3229 dfprintf(("==> "__FUNCTION__ ", hAdapter(0x%x)\n", hAdapter));
3230
3231 AssertBreakpoint();
3232
3233 dfprintf(("<== "__FUNCTION__ ", hAdapter(0x%x)\n", hAdapter));
3234
3235 return STATUS_SUCCESS;
3236}
3237
3238NTSTATUS
3239APIENTRY
3240DxgkDdiQueryCurrentFence(
3241 CONST HANDLE hAdapter,
3242 DXGKARG_QUERYCURRENTFENCE* pCurrentFence)
3243{
3244 dfprintf(("==> "__FUNCTION__ ", hAdapter(0x%x)\n", hAdapter));
3245
3246 AssertBreakpoint();
3247 /* @todo: fixme: implement */
3248
3249 dfprintf(("<== "__FUNCTION__ ", hAdapter(0x%x)\n", hAdapter));
3250
3251 return STATUS_SUCCESS;
3252}
3253
3254NTSTATUS
3255APIENTRY
3256DxgkDdiIsSupportedVidPn(
3257 CONST HANDLE hAdapter,
3258 OUT DXGKARG_ISSUPPORTEDVIDPN* pIsSupportedVidPnArg
3259 )
3260{
3261 /* The DxgkDdiIsSupportedVidPn should be made pageable. */
3262 PAGED_CODE();
3263
3264 dfprintf(("==> "__FUNCTION__ ", context(0x%x)\n", hAdapter));
3265
3266 vboxVDbgBreakFv();
3267
3268 PDEVICE_EXTENSION pContext = (PDEVICE_EXTENSION)hAdapter;
3269 BOOLEAN bSupported = TRUE;
3270 const DXGK_VIDPN_INTERFACE* pVidPnInterface = NULL;
3271 NTSTATUS Status = pContext->u.primary.DxgkInterface.DxgkCbQueryVidPnInterface(pIsSupportedVidPnArg->hDesiredVidPn, DXGK_VIDPN_INTERFACE_VERSION_V1, &pVidPnInterface);
3272 if (Status == STATUS_SUCCESS)
3273 {
3274 D3DKMDT_HVIDPNTOPOLOGY hVidPnTopology;
3275 const DXGK_VIDPNTOPOLOGY_INTERFACE* pVidPnTopologyInterface;
3276 Status = pVidPnInterface->pfnGetTopology(pIsSupportedVidPnArg->hDesiredVidPn, &hVidPnTopology, &pVidPnTopologyInterface);
3277 if (Status == STATUS_SUCCESS)
3278 {
3279 Status = vboxVidPnCheckTopology(pIsSupportedVidPnArg->hDesiredVidPn, hVidPnTopology, pVidPnTopologyInterface, &bSupported);
3280 if (Status == STATUS_SUCCESS && bSupported)
3281 {
3282 for (int id = 0; id < pContext->u.primary.cDisplays; ++id)
3283 {
3284 D3DKMDT_HVIDPNSOURCEMODESET hNewVidPnSourceModeSet;
3285 const DXGK_VIDPNSOURCEMODESET_INTERFACE *pVidPnSourceModeSetInterface;
3286 Status = pVidPnInterface->pfnAcquireSourceModeSet(pIsSupportedVidPnArg->hDesiredVidPn,
3287 id,
3288 &hNewVidPnSourceModeSet,
3289 &pVidPnSourceModeSetInterface);
3290 if (Status == STATUS_SUCCESS)
3291 {
3292 Status = vboxVidPnCheckSourceModeSet(pIsSupportedVidPnArg->hDesiredVidPn, hNewVidPnSourceModeSet, pVidPnSourceModeSetInterface, &bSupported);
3293
3294 pVidPnInterface->pfnReleaseSourceModeSet(pIsSupportedVidPnArg->hDesiredVidPn, hNewVidPnSourceModeSet);
3295
3296 if (Status != STATUS_SUCCESS || !bSupported)
3297 break;
3298 }
3299 else if (Status == STATUS_GRAPHICS_INVALID_VIDEO_PRESENT_SOURCE)
3300 {
3301 drprintf(("VBoxVideoWddm: Warning: pfnAcquireSourceModeSet returned STATUS_GRAPHICS_INVALID_VIDEO_PRESENT_SOURCE, continuing\n"));
3302 Status = STATUS_SUCCESS;
3303 }
3304 else
3305 {
3306 drprintf(("VBoxVideoWddm: pfnAcquireSourceModeSet failed Status(0x%x)\n"));
3307 break;
3308 }
3309 }
3310
3311 if (Status == STATUS_SUCCESS && bSupported)
3312 {
3313 for (int id = 0; id < pContext->u.primary.cDisplays; ++id)
3314 {
3315 D3DKMDT_HVIDPNTARGETMODESET hNewVidPnTargetModeSet;
3316 CONST DXGK_VIDPNTARGETMODESET_INTERFACE *pVidPnTargetModeSetInterface;
3317 Status = pVidPnInterface->pfnAcquireTargetModeSet(pIsSupportedVidPnArg->hDesiredVidPn,
3318 id, /*__in CONST D3DDDI_VIDEO_PRESENT_SOURCE_ID VidPnSourceId */
3319 &hNewVidPnTargetModeSet,
3320 &pVidPnTargetModeSetInterface);
3321 if (Status == STATUS_SUCCESS)
3322 {
3323 Status = vboxVidPnCheckTargetModeSet(pIsSupportedVidPnArg->hDesiredVidPn, hNewVidPnTargetModeSet, pVidPnTargetModeSetInterface, &bSupported);
3324
3325 pVidPnInterface->pfnReleaseTargetModeSet(pIsSupportedVidPnArg->hDesiredVidPn, hNewVidPnTargetModeSet);
3326
3327 if (Status != STATUS_SUCCESS || !bSupported)
3328 break;
3329 }
3330 else if (Status == STATUS_GRAPHICS_INVALID_VIDEO_PRESENT_SOURCE)
3331 {
3332 drprintf(("VBoxVideoWddm: Warning: pfnAcquireSourceModeSet returned STATUS_GRAPHICS_INVALID_VIDEO_PRESENT_SOURCE, continuing\n"));
3333 Status = STATUS_SUCCESS;
3334 }
3335 else
3336 {
3337 drprintf(("VBoxVideoWddm: pfnAcquireSourceModeSet failed Status(0x%x)\n"));
3338 break;
3339 }
3340 }
3341 }
3342 }
3343 }
3344 else
3345 {
3346 drprintf(("VBoxVideoWddm: pfnGetTopology failed Status(0x%x)\n"));
3347 }
3348 }
3349 else
3350 {
3351 drprintf(("VBoxVideoWddm: DxgkCbQueryVidPnInterface failed Status(0x%x)\n"));
3352 }
3353 pIsSupportedVidPnArg->IsVidPnSupported = bSupported;
3354
3355 dfprintf(("<== "__FUNCTION__ ", status(0x%x), context(0x%x)\n", Status, hAdapter));
3356
3357 return Status;
3358}
3359
3360NTSTATUS
3361APIENTRY
3362DxgkDdiRecommendFunctionalVidPn(
3363 CONST HANDLE hAdapter,
3364 CONST DXGKARG_RECOMMENDFUNCTIONALVIDPN* CONST pRecommendFunctionalVidPnArg
3365 )
3366{
3367 /* The DxgkDdiRecommendFunctionalVidPn should be made pageable. */
3368 PAGED_CODE();
3369
3370 dfprintf(("==> "__FUNCTION__ ", context(0x%x)\n", hAdapter));
3371
3372 vboxVDbgBreakF();
3373
3374 PDEVICE_EXTENSION pDevExt = (PDEVICE_EXTENSION)hAdapter;
3375 NTSTATUS Status;
3376 uint32_t cModes;
3377 int iPreferredMode;
3378 VIDEO_MODE_INFORMATION *pModes;
3379 uint32_t cResolutions;
3380 D3DKMDT_2DREGION *pResolutions;
3381 VIDEO_MODE_INFORMATION ModeInfos[4];
3382 VIDEO_MODE_INFORMATION *pModeInfos;
3383 D3DKMDT_2DREGION Resolution;
3384 uint32_t cModeInfos;
3385 int32_t iPreferredModeInfo;
3386 bool bFreeModes = false;
3387 VBoxWddmGetModesTable(pDevExt, /* PDEVICE_EXTENSION DeviceExtension */
3388 true, /* bool bRebuildTable*/
3389 &pModes, /* VIDEO_MODE_INFORMATION ** ppModes*/
3390 &cModes, /* uint32_t * pcModes */
3391 &iPreferredMode, /* uint32_t * pPreferrableMode*/
3392 &pResolutions, /* D3DKMDT_2DREGION **ppResolutions */
3393 &cResolutions /* uint32_t * pcResolutions */);
3394 Resolution.cx = pModes[iPreferredMode].VisScreenWidth;
3395 Resolution.cy = pModes[iPreferredMode].VisScreenHeight;
3396 Status = VBoxWddmGetModesForResolution(pDevExt, false,
3397 &Resolution,
3398 ModeInfos, RT_ELEMENTS(ModeInfos), &cModeInfos, &iPreferredModeInfo);
3399 Assert(Status == STATUS_SUCCESS || Status == STATUS_BUFFER_TOO_SMALL);
3400 if (Status == STATUS_SUCCESS)
3401 pModeInfos = ModeInfos;
3402 else if (Status == STATUS_BUFFER_TOO_SMALL)
3403 {
3404 uint32_t cModeInfos2;
3405 pModeInfos = (VIDEO_MODE_INFORMATION*)vboxWddmMemAlloc(sizeof (VIDEO_MODE_INFORMATION) * cModeInfos);
3406 if (pModeInfos)
3407 {
3408 bFreeModes = true;
3409 Status = VBoxWddmGetModesForResolution(pDevExt, false,
3410 &Resolution,
3411 pModeInfos, cModeInfos, &cModeInfos2, &iPreferredModeInfo);
3412 Assert(Status == STATUS_SUCCESS);
3413 Assert(iPreferredModeInfo >= 0); /* the array should contain the preffered info */
3414 if (Status != STATUS_SUCCESS)
3415 drprintf((__FUNCTION__": second call to VBoxWddmGetModesForResolution failed Status(0x%x), cModeInfos(%d), cModeInfos2(%d)\n", Status, cModeInfos, cModeInfos2));
3416 }
3417 }
3418 else
3419 drprintf((__FUNCTION__": VBoxWddmGetModesForResolution failed Status(0x%x)\n", Status));
3420
3421 if (Status == STATUS_SUCCESS)
3422 {
3423 for (int i = 0; i < pDevExt->u.primary.cDisplays; ++i)
3424 {
3425 Status = vboxVidPnCheckAddMonitorModes(pDevExt, i, D3DKMDT_MCO_DRIVER, &Resolution, 1, 0);
3426 Assert(Status == STATUS_SUCCESS);
3427 if (Status != STATUS_SUCCESS)
3428 {
3429 drprintf((__FUNCTION__": vboxVidPnCheckAddMonitorModes failed Status(0x%x)\n", Status));
3430 break;
3431 }
3432 }
3433
3434 if (Status == STATUS_SUCCESS)
3435 {
3436 const DXGK_VIDPN_INTERFACE* pVidPnInterface = NULL;
3437 Status = pDevExt->u.primary.DxgkInterface.DxgkCbQueryVidPnInterface(pRecommendFunctionalVidPnArg->hRecommendedFunctionalVidPn, DXGK_VIDPN_INTERFACE_VERSION_V1, &pVidPnInterface);
3438 Assert(Status == STATUS_SUCCESS);
3439 if (Status == STATUS_SUCCESS)
3440 {
3441 Assert (iPreferredModeInfo >= 0);
3442 Status = vboxVidPnCreatePopulateVidPnFromLegacy(pDevExt, pRecommendFunctionalVidPnArg->hRecommendedFunctionalVidPn, pVidPnInterface,
3443 pModeInfos, cModeInfos, iPreferredModeInfo,
3444 &Resolution, 1);
3445 Assert(Status == STATUS_SUCCESS);
3446 if (Status != STATUS_SUCCESS)
3447 drprintf((__FUNCTION__": vboxVidPnCreatePopulateVidPnFromLegacy failed Status(0x%x)\n", Status));
3448 }
3449 else
3450 drprintf((__FUNCTION__": DxgkCbQueryVidPnInterface failed Status(0x%x)\n", Status));
3451 }
3452 }
3453
3454 if (bFreeModes)
3455 vboxWddmMemFree(pModeInfos);
3456
3457 dfprintf(("<== "__FUNCTION__ ", status(0x%x), context(0x%x)\n", Status, hAdapter));
3458
3459 return Status;
3460}
3461
3462NTSTATUS
3463APIENTRY
3464DxgkDdiEnumVidPnCofuncModality(
3465 CONST HANDLE hAdapter,
3466 CONST DXGKARG_ENUMVIDPNCOFUNCMODALITY* CONST pEnumCofuncModalityArg
3467 )
3468{
3469 /* The DxgkDdiEnumVidPnCofuncModality function should be made pageable. */
3470 PAGED_CODE();
3471
3472 dfprintf(("==> "__FUNCTION__ ", context(0x%x)\n", hAdapter));
3473
3474 vboxVDbgBreakFv();
3475
3476 PDEVICE_EXTENSION pContext = (PDEVICE_EXTENSION)hAdapter;
3477 const DXGK_VIDPN_INTERFACE* pVidPnInterface = NULL;
3478 NTSTATUS Status = pContext->u.primary.DxgkInterface.DxgkCbQueryVidPnInterface(pEnumCofuncModalityArg->hConstrainingVidPn, DXGK_VIDPN_INTERFACE_VERSION_V1, &pVidPnInterface);
3479 if (Status == STATUS_SUCCESS)
3480 {
3481 D3DKMDT_HVIDPNTOPOLOGY hVidPnTopology;
3482 const DXGK_VIDPNTOPOLOGY_INTERFACE* pVidPnTopologyInterface;
3483 NTSTATUS Status = pVidPnInterface->pfnGetTopology(pEnumCofuncModalityArg->hConstrainingVidPn, &hVidPnTopology, &pVidPnTopologyInterface);
3484 Assert(Status == STATUS_SUCCESS);
3485 if (Status == STATUS_SUCCESS)
3486 {
3487 VBOXVIDPNCOFUNCMODALITY CbContext = {0};
3488 CbContext.pEnumCofuncModalityArg = pEnumCofuncModalityArg;
3489 VBoxWddmGetModesTable(pContext, /* PDEVICE_EXTENSION DeviceExtension */
3490 false, /* bool bRebuildTable*/
3491 &CbContext.pModes, /* VIDEO_MODE_INFORMATION ** ppModes*/
3492 &CbContext.cModes, /* uint32_t * pcModes */
3493 &CbContext.iPreferredMode, /* uint32_t * pPreferrableMode*/
3494 &CbContext.pResolutions, /* D3DKMDT_2DREGION **ppResolutions */
3495 &CbContext.cResolutions /* uint32_t * pcResolutions */);
3496 Assert(CbContext.cModes);
3497 Assert(CbContext.cModes > (uint32_t)CbContext.iPreferredMode);
3498 CbContext.iPreferredMode = -1; /* <- we do not want the modes to be pinned */
3499 Status = vboxVidPnEnumPaths(pContext, pEnumCofuncModalityArg->hConstrainingVidPn, pVidPnInterface,
3500 hVidPnTopology, pVidPnTopologyInterface,
3501 vboxVidPnCofuncModalityPathEnum, &CbContext);
3502 Assert(Status == STATUS_SUCCESS);
3503 if (Status == STATUS_SUCCESS)
3504 {
3505 Status = CbContext.Status;
3506 Assert(Status == STATUS_SUCCESS);
3507 if (Status != STATUS_SUCCESS)
3508 drprintf((__FUNCTION__ ": vboxVidPnAdjustSourcesTargetsCallback failed Status(0x%x)\n", Status));
3509 }
3510 else
3511 drprintf((__FUNCTION__ ": vboxVidPnEnumPaths failed Status(0x%x)\n", Status));
3512 }
3513 else
3514 drprintf((__FUNCTION__ ": pfnGetTopology failed Status(0x%x)\n", Status));
3515 }
3516 else
3517 drprintf((__FUNCTION__ ": DxgkCbQueryVidPnInterface failed Status(0x%x)\n", Status));
3518
3519 dfprintf(("<== "__FUNCTION__ ", status(0x%x), context(0x%x)\n", Status, hAdapter));
3520
3521 return Status;
3522}
3523
3524NTSTATUS
3525APIENTRY
3526DxgkDdiSetVidPnSourceAddress(
3527 CONST HANDLE hAdapter,
3528 CONST DXGKARG_SETVIDPNSOURCEADDRESS* pSetVidPnSourceAddress
3529 )
3530{
3531 /* The DxgkDdiSetVidPnSourceAddress function should be made pageable. */
3532 PAGED_CODE();
3533
3534 vboxVDbgBreakFv();
3535
3536 dfprintf(("==> "__FUNCTION__ ", context(0x%x)\n", hAdapter));
3537
3538 NTSTATUS Status = STATUS_SUCCESS;
3539 PDEVICE_EXTENSION pDevExt = (PDEVICE_EXTENSION)hAdapter;
3540 Assert((UINT)pDevExt->u.primary.cDisplays > pSetVidPnSourceAddress->VidPnSourceId);
3541
3542 PVBOXWDDM_SOURCE pSource = &pDevExt->aSources[pSetVidPnSourceAddress->VidPnSourceId];
3543 Status= vboxWddmDisplaySettingsQueryPos(pDevExt, pSetVidPnSourceAddress->VidPnSourceId, &pSource->VScreenPos);
3544 Assert(Status == STATUS_SUCCESS);
3545 Status = STATUS_SUCCESS;
3546
3547 if ((UINT)pDevExt->u.primary.cDisplays > pSetVidPnSourceAddress->VidPnSourceId)
3548 {
3549 PVBOXWDDM_ALLOCATION pAllocation;
3550 Assert(pSetVidPnSourceAddress->hAllocation);
3551 Assert(pSetVidPnSourceAddress->hAllocation || pSource->pPrimaryAllocation);
3552 Assert (pSetVidPnSourceAddress->Flags.Value < 2); /* i.e. 0 or 1 (ModeChange) */
3553 if (pSetVidPnSourceAddress->hAllocation)
3554 {
3555 pAllocation = (PVBOXWDDM_ALLOCATION)pSetVidPnSourceAddress->hAllocation;
3556 vboxWddmAssignPrimary(pDevExt, pSource, pAllocation, pSetVidPnSourceAddress->VidPnSourceId);
3557 }
3558 else
3559 pAllocation = pSource->pPrimaryAllocation;
3560
3561 Assert(pAllocation);
3562 if (pAllocation)
3563 {
3564// Assert(pAllocation->enmType == VBOXWDDM_ALLOC_TYPE_STD_SHAREDPRIMARYSURFACE);
3565 pAllocation->offVram = (VBOXVIDEOOFFSET)pSetVidPnSourceAddress->PrimaryAddress.QuadPart;
3566 pAllocation->SegmentId = pSetVidPnSourceAddress->PrimarySegment;
3567 Assert (pAllocation->SegmentId);
3568 Assert (!pAllocation->bVisible);
3569 Assert(pAllocation->enmType == VBOXWDDM_ALLOC_TYPE_STD_SHAREDPRIMARYSURFACE
3570 || pAllocation->enmType == VBOXWDDM_ALLOC_TYPE_UMD_RC_GENERIC);
3571
3572 if (
3573#ifdef VBOXWDDM_RENDER_FROM_SHADOW
3574 /* this is the case of full-screen d3d, ensure we notify host */
3575 pAllocation->enmType == VBOXWDDM_ALLOC_TYPE_UMD_RC_GENERIC &&
3576#endif
3577 pAllocation->bVisible)
3578 {
3579#ifdef VBOXWDDM_RENDER_FROM_SHADOW
3580 /* to ensure the resize request gets issued in case we exit a full-screen D3D mode */
3581 pSource->offVram = VBOXVIDEOOFFSET_VOID;
3582#else
3583 /* should not generally happen, but still inform host*/
3584 Status = vboxWddmGhDisplaySetInfo(pDevExt, pSource, pSetVidPnSourceAddress->VidPnSourceId);
3585 Assert(Status == STATUS_SUCCESS);
3586 if (Status != STATUS_SUCCESS)
3587 drprintf((__FUNCTION__": vboxWddmGhDisplaySetInfo failed, Status (0x%x)\n", Status));
3588#endif
3589 }
3590 }
3591 else
3592 {
3593 drprintf((__FUNCTION__": no allocation data available!!\n"));
3594 Status = STATUS_INVALID_PARAMETER;
3595 }
3596 }
3597 else
3598 {
3599 drprintf((__FUNCTION__": invalid VidPnSourceId (%d), should be smaller than (%d)\n", pSetVidPnSourceAddress->VidPnSourceId, pDevExt->u.primary.cDisplays));
3600 Status = STATUS_INVALID_PARAMETER;
3601 }
3602
3603 dfprintf(("<== "__FUNCTION__ ", status(0x%x), context(0x%x)\n", Status, hAdapter));
3604
3605 return Status;
3606}
3607
3608NTSTATUS
3609APIENTRY
3610DxgkDdiSetVidPnSourceVisibility(
3611 CONST HANDLE hAdapter,
3612 CONST DXGKARG_SETVIDPNSOURCEVISIBILITY* pSetVidPnSourceVisibility
3613 )
3614{
3615 /* DxgkDdiSetVidPnSourceVisibility should be made pageable. */
3616 PAGED_CODE();
3617
3618 vboxVDbgBreakFv();
3619
3620 dfprintf(("==> "__FUNCTION__ ", context(0x%x)\n", hAdapter));
3621
3622 NTSTATUS Status = STATUS_SUCCESS;
3623 PDEVICE_EXTENSION pDevExt = (PDEVICE_EXTENSION)hAdapter;
3624 Assert((UINT)pDevExt->u.primary.cDisplays > pSetVidPnSourceVisibility->VidPnSourceId);
3625
3626 PVBOXWDDM_SOURCE pSource = &pDevExt->aSources[pSetVidPnSourceVisibility->VidPnSourceId];
3627 Status= vboxWddmDisplaySettingsQueryPos(pDevExt, pSetVidPnSourceVisibility->VidPnSourceId, &pSource->VScreenPos);
3628 Assert(Status == STATUS_SUCCESS);
3629 Status = STATUS_SUCCESS;
3630
3631 if ((UINT)pDevExt->u.primary.cDisplays > pSetVidPnSourceVisibility->VidPnSourceId)
3632 {
3633 PVBOXWDDM_ALLOCATION pAllocation = pSource->pPrimaryAllocation;
3634 if (pAllocation)
3635 {
3636 Assert(pAllocation->enmType == VBOXWDDM_ALLOC_TYPE_STD_SHAREDPRIMARYSURFACE
3637 || pAllocation->enmType == VBOXWDDM_ALLOC_TYPE_UMD_RC_GENERIC);
3638
3639 Assert(pAllocation->bVisible != pSetVidPnSourceVisibility->Visible);
3640 if (pAllocation->bVisible != pSetVidPnSourceVisibility->Visible)
3641 {
3642 pAllocation->bVisible = pSetVidPnSourceVisibility->Visible;
3643 if (pAllocation->bVisible)
3644 {
3645#ifdef VBOXWDDM_RENDER_FROM_SHADOW
3646 if (/* this is the case of full-screen d3d, ensure we notify host */
3647 pAllocation->enmType == VBOXWDDM_ALLOC_TYPE_UMD_RC_GENERIC
3648 )
3649#endif
3650 {
3651#ifdef VBOXWDDM_RENDER_FROM_SHADOW
3652 /* to ensure the resize request gets issued in case we exit a full-screen D3D mode */
3653 pSource->offVram = VBOXVIDEOOFFSET_VOID;
3654#else
3655 Status = vboxWddmGhDisplaySetInfo(pDevExt, pSource, pSetVidPnSourceVisibility->VidPnSourceId);
3656 Assert(Status == STATUS_SUCCESS);
3657 if (Status != STATUS_SUCCESS)
3658 drprintf((__FUNCTION__": vboxWddmGhDisplaySetInfo failed, Status (0x%x)\n", Status));
3659#endif
3660 }
3661 }
3662#ifdef VBOX_WITH_VDMA
3663 else
3664 {
3665 vboxVdmaFlush (pDevExt, &pDevExt->u.primary.Vdma);
3666 }
3667#endif
3668 }
3669 }
3670 else
3671 {
3672 Assert(!pSetVidPnSourceVisibility->Visible);
3673 }
3674 }
3675 else
3676 {
3677 drprintf((__FUNCTION__": invalid VidPnSourceId (%d), should be smaller than (%d)\n", pSetVidPnSourceVisibility->VidPnSourceId, pDevExt->u.primary.cDisplays));
3678 Status = STATUS_INVALID_PARAMETER;
3679 }
3680
3681 dfprintf(("<== "__FUNCTION__ ", status(0x%x), context(0x%x)\n", Status, hAdapter));
3682
3683 return Status;
3684}
3685
3686NTSTATUS
3687APIENTRY
3688DxgkDdiCommitVidPn(
3689 CONST HANDLE hAdapter,
3690 CONST DXGKARG_COMMITVIDPN* CONST pCommitVidPnArg
3691 )
3692{
3693 dfprintf(("==> "__FUNCTION__ ", context(0x%x)\n", hAdapter));
3694
3695 PDEVICE_EXTENSION pDevExt = (PDEVICE_EXTENSION)hAdapter;
3696
3697 vboxVDbgBreakFv();
3698
3699 const DXGK_VIDPN_INTERFACE* pVidPnInterface = NULL;
3700 NTSTATUS Status = pDevExt->u.primary.DxgkInterface.DxgkCbQueryVidPnInterface(pCommitVidPnArg->hFunctionalVidPn, DXGK_VIDPN_INTERFACE_VERSION_V1, &pVidPnInterface);
3701 if (Status == STATUS_SUCCESS)
3702 {
3703 if (pCommitVidPnArg->AffectedVidPnSourceId != D3DDDI_ID_ALL)
3704 {
3705 Status = vboxVidPnCommitSourceModeForSrcId(
3706 pDevExt,
3707 pCommitVidPnArg->hFunctionalVidPn, pVidPnInterface,
3708 pCommitVidPnArg->AffectedVidPnSourceId, (PVBOXWDDM_ALLOCATION)pCommitVidPnArg->hPrimaryAllocation);
3709 Assert(Status == STATUS_SUCCESS);
3710 if (Status != STATUS_SUCCESS)
3711 drprintf((__FUNCTION__ ": vboxVidPnCommitSourceModeForSrcId failed Status(0x%x)\n", Status));
3712 }
3713 else
3714 {
3715 /* clear all current primaries */
3716 for (int i = 0; i < pDevExt->u.primary.cDisplays; ++i)
3717 {
3718 vboxWddmAssignPrimary(pDevExt, &pDevExt->aSources[i], NULL, i);
3719 }
3720
3721 D3DKMDT_HVIDPNTOPOLOGY hVidPnTopology;
3722 const DXGK_VIDPNTOPOLOGY_INTERFACE* pVidPnTopologyInterface;
3723 NTSTATUS Status = pVidPnInterface->pfnGetTopology(pCommitVidPnArg->hFunctionalVidPn, &hVidPnTopology, &pVidPnTopologyInterface);
3724 Assert(Status == STATUS_SUCCESS);
3725 if (Status == STATUS_SUCCESS)
3726 {
3727 VBOXVIDPNCOMMIT CbContext = {0};
3728 CbContext.pCommitVidPnArg = pCommitVidPnArg;
3729 Status = vboxVidPnEnumPaths(pDevExt, pCommitVidPnArg->hFunctionalVidPn, pVidPnInterface,
3730 hVidPnTopology, pVidPnTopologyInterface,
3731 vboxVidPnCommitPathEnum, &CbContext);
3732 Assert(Status == STATUS_SUCCESS);
3733 if (Status == STATUS_SUCCESS)
3734 {
3735 Status = CbContext.Status;
3736 Assert(Status == STATUS_SUCCESS);
3737 if (Status != STATUS_SUCCESS)
3738 drprintf((__FUNCTION__ ": vboxVidPnCommitPathEnum failed Status(0x%x)\n", Status));
3739 }
3740 else
3741 drprintf((__FUNCTION__ ": vboxVidPnEnumPaths failed Status(0x%x)\n", Status));
3742 }
3743 else
3744 drprintf((__FUNCTION__ ": pfnGetTopology failed Status(0x%x)\n", Status));
3745 }
3746
3747 if (Status == STATUS_SUCCESS)
3748 {
3749 pDevExt->u.primary.hCommittedVidPn = pCommitVidPnArg->hFunctionalVidPn;
3750 }
3751 }
3752 else
3753 drprintf((__FUNCTION__ ": DxgkCbQueryVidPnInterface failed Status(0x%x)\n", Status));
3754
3755 dfprintf(("<== "__FUNCTION__ ", status(0x%x), context(0x%x)\n", Status, hAdapter));
3756
3757 return Status;
3758}
3759
3760NTSTATUS
3761APIENTRY
3762DxgkDdiUpdateActiveVidPnPresentPath(
3763 CONST HANDLE hAdapter,
3764 CONST DXGKARG_UPDATEACTIVEVIDPNPRESENTPATH* CONST pUpdateActiveVidPnPresentPathArg
3765 )
3766{
3767 dfprintf(("==> "__FUNCTION__ ", hAdapter(0x%x)\n", hAdapter));
3768
3769 AssertBreakpoint();
3770
3771 dfprintf(("<== "__FUNCTION__ ", hAdapter(0x%x)\n", hAdapter));
3772
3773 return STATUS_SUCCESS;
3774}
3775
3776NTSTATUS
3777APIENTRY
3778DxgkDdiRecommendMonitorModes(
3779 CONST HANDLE hAdapter,
3780 CONST DXGKARG_RECOMMENDMONITORMODES* CONST pRecommendMonitorModesArg
3781 )
3782{
3783 dfprintf(("==> "__FUNCTION__ ", hAdapter(0x%x)\n", hAdapter));
3784
3785 vboxVDbgBreakFv();
3786
3787 PDEVICE_EXTENSION pDevExt = (PDEVICE_EXTENSION)hAdapter;
3788 NTSTATUS Status;
3789 uint32_t cModes;
3790 int32_t iPreferredMode;
3791 VIDEO_MODE_INFORMATION *pModes;
3792 uint32_t cResolutions;
3793 D3DKMDT_2DREGION *pResolutions;
3794 VBoxWddmGetModesTable(pDevExt, /* PDEVICE_EXTENSION DeviceExtension */
3795 false, /* bool bRebuildTable*/
3796 &pModes, /* VIDEO_MODE_INFORMATION ** ppModes*/
3797 &cModes, /* uint32_t * pcModes */
3798 &iPreferredMode, /* uint32_t * pPreferrableMode*/
3799 &pResolutions, /* D3DKMDT_2DREGION **ppResolutions */
3800 &cResolutions /* uint32_t * pcResolutions */);
3801
3802 for (uint32_t i = 0; i < cResolutions; i++)
3803 {
3804 D3DKMDT_MONITOR_SOURCE_MODE * pNewMonitorSourceModeInfo;
3805 Status = pRecommendMonitorModesArg->pMonitorSourceModeSetInterface->pfnCreateNewModeInfo(
3806 pRecommendMonitorModesArg->hMonitorSourceModeSet, &pNewMonitorSourceModeInfo);
3807 Assert(Status == STATUS_SUCCESS);
3808 if (Status == STATUS_SUCCESS)
3809 {
3810 Status = vboxVidPnPopulateMonitorSourceModeInfoFromLegacy(pDevExt,
3811 pNewMonitorSourceModeInfo,
3812 &pResolutions[i],
3813 D3DKMDT_MCO_DRIVER,
3814 FALSE);
3815 Assert(Status == STATUS_SUCCESS);
3816 if (Status == STATUS_SUCCESS)
3817 {
3818 Status = pRecommendMonitorModesArg->pMonitorSourceModeSetInterface->pfnAddMode(
3819 pRecommendMonitorModesArg->hMonitorSourceModeSet, pNewMonitorSourceModeInfo);
3820 Assert(Status == STATUS_SUCCESS);
3821 if (Status == STATUS_SUCCESS)
3822 continue;
3823 }
3824
3825 /* error has occured, release & break */
3826 pRecommendMonitorModesArg->pMonitorSourceModeSetInterface->pfnReleaseModeInfo(
3827 pRecommendMonitorModesArg->hMonitorSourceModeSet, pNewMonitorSourceModeInfo);
3828 break;
3829 }
3830 }
3831
3832 dfprintf(("<== "__FUNCTION__ ", hAdapter(0x%x)\n", hAdapter));
3833
3834 return Status;
3835}
3836
3837NTSTATUS
3838APIENTRY
3839DxgkDdiRecommendVidPnTopology(
3840 CONST HANDLE hAdapter,
3841 CONST DXGKARG_RECOMMENDVIDPNTOPOLOGY* CONST pRecommendVidPnTopologyArg
3842 )
3843{
3844 dfprintf(("==> "__FUNCTION__ ", hAdapter(0x%x)\n", hAdapter));
3845
3846 vboxVDbgBreakFv();
3847
3848 dfprintf(("<== "__FUNCTION__ ", hAdapter(0x%x)\n", hAdapter));
3849
3850 return STATUS_GRAPHICS_NO_RECOMMENDED_VIDPN_TOPOLOGY;
3851}
3852
3853NTSTATUS
3854APIENTRY
3855DxgkDdiGetScanLine(
3856 CONST HANDLE hAdapter,
3857 DXGKARG_GETSCANLINE* pGetScanLine)
3858{
3859 dfprintf(("==> "__FUNCTION__ ", hAdapter(0x%x)\n", hAdapter));
3860
3861 PDEVICE_EXTENSION pDevExt = (PDEVICE_EXTENSION)hAdapter;
3862
3863 Assert((UINT)pDevExt->u.primary.cDisplays > pGetScanLine->VidPnTargetId);
3864 VBOXWDDM_TARGET *pTarget = &pDevExt->aTargets[pGetScanLine->VidPnTargetId];
3865 Assert(pTarget->HeightTotal);
3866 Assert(pTarget->HeightVisible);
3867 Assert(pTarget->HeightTotal > pTarget->HeightVisible);
3868 Assert(pTarget->ScanLineState < pTarget->HeightTotal);
3869 if (pTarget->HeightTotal)
3870 {
3871 uint32_t curScanLine = pTarget->ScanLineState;
3872 ++pTarget->ScanLineState;
3873 if (pTarget->ScanLineState >= pTarget->HeightTotal)
3874 pTarget->ScanLineState = 0;
3875
3876
3877 BOOL bVBlank = (!curScanLine || curScanLine > pTarget->HeightVisible);
3878 pGetScanLine->ScanLine = curScanLine;
3879 pGetScanLine->InVerticalBlank = bVBlank;
3880 }
3881 else
3882 {
3883 pGetScanLine->InVerticalBlank = TRUE;
3884 pGetScanLine->ScanLine = 0;
3885 }
3886
3887 dfprintf(("<== "__FUNCTION__ ", hAdapter(0x%x)\n", hAdapter));
3888
3889 return STATUS_SUCCESS;
3890}
3891
3892NTSTATUS
3893APIENTRY
3894DxgkDdiStopCapture(
3895 CONST HANDLE hAdapter,
3896 CONST DXGKARG_STOPCAPTURE* pStopCapture)
3897{
3898 dfprintf(("==> "__FUNCTION__ ", hAdapter(0x%x)\n", hAdapter));
3899
3900 AssertBreakpoint();
3901
3902 dfprintf(("<== "__FUNCTION__ ", hAdapter(0x%x)\n", hAdapter));
3903
3904 return STATUS_SUCCESS;
3905}
3906
3907NTSTATUS
3908APIENTRY
3909DxgkDdiControlInterrupt(
3910 CONST HANDLE hAdapter,
3911 CONST DXGK_INTERRUPT_TYPE InterruptType,
3912 BOOLEAN Enable
3913 )
3914{
3915 dfprintf(("==> "__FUNCTION__ ", hAdapter(0x%x)\n", hAdapter));
3916
3917// AssertBreakpoint();
3918
3919 dfprintf(("<== "__FUNCTION__ ", hAdapter(0x%x)\n", hAdapter));
3920
3921 /* @todo: STATUS_NOT_IMPLEMENTED ?? */
3922 return STATUS_SUCCESS;
3923}
3924
3925NTSTATUS
3926APIENTRY
3927DxgkDdiCreateOverlay(
3928 CONST HANDLE hAdapter,
3929 DXGKARG_CREATEOVERLAY *pCreateOverlay)
3930{
3931 dfprintf(("==> "__FUNCTION__ ", hAdapter(0x%p)\n", hAdapter));
3932
3933 NTSTATUS Status = STATUS_SUCCESS;
3934 PDEVICE_EXTENSION pDevExt = (PDEVICE_EXTENSION)hAdapter;
3935 PVBOXWDDM_OVERLAY pOverlay = (PVBOXWDDM_OVERLAY)vboxWddmMemAllocZero(sizeof (VBOXWDDM_OVERLAY));
3936 Assert(pOverlay);
3937 if (pOverlay)
3938 {
3939 int rc = vboxVhwaHlpOverlayCreate(pDevExt, pCreateOverlay->VidPnSourceId, &pCreateOverlay->OverlayInfo, pOverlay);
3940 AssertRC(rc);
3941 if (RT_SUCCESS(rc))
3942 {
3943 vboxVhwaHlpOverlayListAdd(pDevExt, pOverlay);
3944#ifdef VBOXWDDM_RENDER_FROM_SHADOW
3945 RECT DstRect;
3946 vboxVhwaHlpOverlayDstRectGet(pDevExt, pOverlay, &DstRect);
3947 Status = vboxVdmaHlpUpdatePrimary(pDevExt, pCreateOverlay->VidPnSourceId, &DstRect);
3948 Assert(Status == STATUS_SUCCESS);
3949 /* ignore primary update failure */
3950 Status = STATUS_SUCCESS;
3951#endif
3952 pCreateOverlay->hOverlay = pOverlay;
3953 }
3954 else
3955 {
3956 vboxWddmMemFree(pOverlay);
3957 Status = STATUS_UNSUCCESSFUL;
3958 }
3959 }
3960 else
3961 Status = STATUS_NO_MEMORY;
3962
3963 dfprintf(("<== "__FUNCTION__ ", hAdapter(0x%p)\n", hAdapter));
3964
3965 return Status;
3966}
3967
3968NTSTATUS
3969APIENTRY
3970DxgkDdiDestroyDevice(
3971 CONST HANDLE hDevice)
3972{
3973 /* DxgkDdiDestroyDevice should be made pageable. */
3974 PAGED_CODE();
3975
3976 dfprintf(("==> "__FUNCTION__ ", hDevice(0x%x)\n", hDevice));
3977
3978 vboxVDbgBreakFv();
3979
3980 vboxWddmMemFree(hDevice);
3981
3982 dfprintf(("<== "__FUNCTION__ ", \n"));
3983
3984 return STATUS_SUCCESS;
3985}
3986
3987/*
3988 * DxgkDdiOpenAllocation
3989 */
3990NTSTATUS
3991APIENTRY
3992DxgkDdiOpenAllocation(
3993 CONST HANDLE hDevice,
3994 CONST DXGKARG_OPENALLOCATION *pOpenAllocation)
3995{
3996 /* DxgkDdiOpenAllocation should be made pageable. */
3997 PAGED_CODE();
3998
3999 dfprintf(("==> "__FUNCTION__ ", hDevice(0x%x)\n", hDevice));
4000
4001 vboxVDbgBreakFv();
4002
4003 NTSTATUS Status = STATUS_SUCCESS;
4004 PVBOXWDDM_DEVICE pDevice = (PVBOXWDDM_DEVICE)hDevice;
4005 PDEVICE_EXTENSION pDevExt = pDevice->pAdapter;
4006 PVBOXWDDM_RCINFO pRcInfo = NULL;
4007 if (pOpenAllocation->PrivateDriverSize)
4008 {
4009 Assert(pOpenAllocation->PrivateDriverSize == sizeof (VBOXWDDM_RCINFO));
4010 Assert(pOpenAllocation->pPrivateDriverData);
4011 if (pOpenAllocation->PrivateDriverSize >= sizeof (VBOXWDDM_RCINFO))
4012 {
4013 pRcInfo = (PVBOXWDDM_RCINFO)pOpenAllocation->pPrivateDriverData;
4014 Assert(pRcInfo->cAllocInfos == pOpenAllocation->NumAllocations);
4015 }
4016 else
4017 Status = STATUS_INVALID_PARAMETER;
4018 }
4019
4020 if (Status == STATUS_SUCCESS)
4021 {
4022 for (UINT i = 0; i < pOpenAllocation->NumAllocations; ++i)
4023 {
4024 DXGK_OPENALLOCATIONINFO* pInfo = &pOpenAllocation->pOpenAllocation[i];
4025 Assert(pInfo->PrivateDriverDataSize == sizeof (VBOXWDDM_ALLOCINFO));
4026 Assert(pInfo->pPrivateDriverData);
4027 PVBOXWDDM_OPENALLOCATION pOa = (PVBOXWDDM_OPENALLOCATION)vboxWddmMemAllocZero(sizeof (VBOXWDDM_OPENALLOCATION));
4028 pOa->hAllocation = pInfo->hAllocation;
4029 pInfo->hDeviceSpecificAllocation = pOa;
4030
4031 if (pRcInfo)
4032 {
4033#ifdef VBOX_WITH_VIDEOHWACCEL
4034 if (pRcInfo->RcDesc.fFlags.Overlay)
4035 {
4036 if (pInfo->PrivateDriverDataSize >= sizeof (VBOXWDDM_ALLOCINFO))
4037 {
4038 PVBOXWDDM_ALLOCINFO pAllocInfo = (PVBOXWDDM_ALLOCINFO)pInfo->pPrivateDriverData;
4039 PVBOXWDDM_ALLOCATION pAllocation = vboxWddmGetAllocationFromOpenData(pDevExt, pOa);
4040 Assert(pAllocation);
4041 if (pAllocation)
4042 {
4043 /* we have queried host for some surface info, like pitch & size,
4044 * need to return it back to the UMD (User Mode Drive) */
4045 pAllocInfo->SurfDesc = pAllocation->SurfDesc;
4046 /* success, just contionue */
4047 continue;
4048 }
4049 else
4050 Status = STATUS_INVALID_PARAMETER;
4051 }
4052 else
4053 Status = STATUS_INVALID_PARAMETER;
4054
4055 /* we are here in case of error */
4056 AssertBreakpoint();
4057
4058 for (UINT j = 0; j < i; ++j)
4059 {
4060 DXGK_OPENALLOCATIONINFO* pInfo2Free = &pOpenAllocation->pOpenAllocation[j];
4061 PVBOXWDDM_OPENALLOCATION pOa2Free = (PVBOXWDDM_OPENALLOCATION)pInfo2Free->hDeviceSpecificAllocation;
4062 vboxWddmMemFree(pOa2Free);
4063 }
4064 }
4065#endif
4066 }
4067 }
4068 }
4069 dfprintf(("<== "__FUNCTION__ ", hDevice(0x%x)\n", hDevice));
4070
4071 return Status;
4072}
4073
4074NTSTATUS
4075APIENTRY
4076DxgkDdiCloseAllocation(
4077 CONST HANDLE hDevice,
4078 CONST DXGKARG_CLOSEALLOCATION* pCloseAllocation)
4079{
4080 /* DxgkDdiCloseAllocation should be made pageable. */
4081 PAGED_CODE();
4082
4083 dfprintf(("==> "__FUNCTION__ ", hDevice(0x%x)\n", hDevice));
4084
4085 vboxVDbgBreakFv();
4086
4087 for (UINT i = 0; i < pCloseAllocation->NumAllocations; ++i)
4088 {
4089 vboxWddmMemFree(pCloseAllocation->pOpenHandleList[i]);
4090 }
4091
4092 dfprintf(("<== "__FUNCTION__ ", hDevice(0x%x)\n", hDevice));
4093
4094 return STATUS_SUCCESS;
4095}
4096
4097NTSTATUS
4098APIENTRY
4099DxgkDdiRender(
4100 CONST HANDLE hContext,
4101 DXGKARG_RENDER *pRender)
4102{
4103 drprintf(("==> "__FUNCTION__ ", hContext(0x%x)\n", hContext));
4104
4105 Assert(pRender->DmaBufferPrivateDataSize >= sizeof (VBOXWDDM_DMA_PRIVATEDATA_BASEHDR));
4106 if (pRender->DmaBufferPrivateDataSize < sizeof (VBOXWDDM_DMA_PRIVATEDATA_BASEHDR))
4107 {
4108 drprintf((__FUNCTION__": Present->DmaBufferPrivateDataSize(%d) < sizeof VBOXWDDM_DMA_PRIVATEDATA_BASEHDR (%d)\n",
4109 pRender->DmaBufferPrivateDataSize , sizeof (VBOXWDDM_DMA_PRIVATEDATA_BASEHDR)));
4110 /* @todo: can this actually happen? what status to return? */
4111 return STATUS_INVALID_PARAMETER;
4112 }
4113 if (pRender->CommandLength < sizeof (VBOXWDDM_DMA_PRIVATEDATA_BASEHDR))
4114 {
4115 Assert(0);
4116 drprintf((__FUNCTION__": Present->DmaBufferPrivateDataSize(%d) < sizeof VBOXWDDM_DMA_PRIVATEDATA_BASEHDR (%d)\n",
4117 pRender->DmaBufferPrivateDataSize , sizeof (VBOXWDDM_DMA_PRIVATEDATA_BASEHDR)));
4118 /* @todo: can this actually happen? what status to return? */
4119 return STATUS_INVALID_PARAMETER;
4120 }
4121
4122 PVBOXWDDM_DMA_PRIVATEDATA_BASEHDR pInputHdr = (PVBOXWDDM_DMA_PRIVATEDATA_BASEHDR)pRender->pCommand;
4123 NTSTATUS Status = STATUS_SUCCESS;
4124 switch (pInputHdr->enmCmd)
4125 {
4126 case VBOXVDMACMD_TYPE_CHROMIUM_CMD:
4127 {
4128 if (pRender->CommandLength != RT_OFFSETOF(VBOXWDDM_DMA_PRIVATEDATA_UM_CHROMIUM_CMD, aBufInfos[pInputHdr->u32CmdReserved]))
4129 {
4130 Assert(0);
4131 return STATUS_INVALID_PARAMETER;
4132 }
4133 PVBOXWDDM_DMA_PRIVATEDATA_UM_CHROMIUM_CMD pUmCmd = (PVBOXWDDM_DMA_PRIVATEDATA_UM_CHROMIUM_CMD)pInputHdr;
4134 PVBOXWDDM_DMA_PRIVATEDATA_CHROMIUM_CMD pChromiumCmd = (PVBOXWDDM_DMA_PRIVATEDATA_CHROMIUM_CMD)pRender->pDmaBufferPrivateData;
4135 const uint32_t cbDma = RT_OFFSETOF(VBOXWDDM_DMA_PRIVATEDATA_CHROMIUM_CMD, aBufInfos[pInputHdr->u32CmdReserved]);
4136 if (pRender->DmaBufferPrivateDataSize < cbDma)
4137 {
4138 Assert(0);
4139 return STATUS_INVALID_PARAMETER;
4140 }
4141 if (pRender->DmaSize < cbDma)
4142 {
4143 Assert(0);
4144 return STATUS_INVALID_PARAMETER;
4145 }
4146
4147 if (pRender->PatchLocationListOutSize < pInputHdr->u32CmdReserved)
4148 {
4149 Assert(0);
4150 return STATUS_INVALID_PARAMETER;
4151 }
4152
4153 PVBOXWDDM_CONTEXT pContext = (PVBOXWDDM_CONTEXT)hContext;
4154 PVBOXWDDM_DEVICE pDevice = pContext->pDevice;
4155 PDEVICE_EXTENSION pDevExt = pDevice->pAdapter;
4156
4157 pChromiumCmd->Base.enmCmd = VBOXVDMACMD_TYPE_CHROMIUM_CMD;
4158 pChromiumCmd->Base.u32CmdReserved = pInputHdr->u32CmdReserved;
4159 pRender->pDmaBufferPrivateData = (uint8_t*)pRender->pDmaBufferPrivateData + cbDma;
4160 pRender->pDmaBuffer = ((uint8_t*)pRender->pDmaBuffer) + cbDma;
4161 D3DDDI_PATCHLOCATIONLIST* pPLL = pRender->pPatchLocationListOut;
4162 memset(pPLL, 0, sizeof (*pPLL) * pChromiumCmd->Base.u32CmdReserved);
4163 pRender->pPatchLocationListOut += pInputHdr->u32CmdReserved;
4164 PVBOXWDDM_UHGSMI_BUFFER_SUBMIT_INFO pSubmInfo = pChromiumCmd->aBufInfos;
4165 PVBOXWDDM_UHGSMI_BUFFER_UI_SUBMIT_INFO pSubmUmInfo = pUmCmd->aBufInfos;
4166 DXGK_ALLOCATIONLIST *pAllocationList = pRender->pAllocationList;
4167 for (UINT i = 0; i < pChromiumCmd->Base.u32CmdReserved; ++i)
4168 {
4169 PVBOXWDDM_ALLOCATION pAlloc = vboxWddmGetAllocationFromAllocList(pDevExt, pAllocationList);
4170 vboxWddmPopulateDmaAllocInfoWithOffset(&pSubmInfo->Alloc, pAlloc, pAllocationList, pSubmUmInfo->offData);
4171
4172 pSubmInfo->cbData = pSubmUmInfo->cbData;
4173 pSubmInfo->bDoNotSignalCompletion = pSubmUmInfo->fSubFlags.bDoNotSignalCompletion;
4174
4175 pPLL->AllocationIndex = i;
4176 pPLL->PatchOffset = RT_OFFSETOF(VBOXWDDM_DMA_PRIVATEDATA_CHROMIUM_CMD, aBufInfos[i].Alloc);
4177 pPLL->AllocationOffset = pSubmUmInfo->offData;
4178
4179 ++pPLL;
4180 ++pSubmInfo;
4181 ++pSubmUmInfo;
4182 ++pAllocationList;
4183 }
4184
4185 break;
4186 }
4187 case VBOXVDMACMD_TYPE_DMA_NOP:
4188 {
4189 PVBOXWDDM_DMA_PRIVATEDATA_BASEHDR pPrivateData = (PVBOXWDDM_DMA_PRIVATEDATA_BASEHDR)pRender->pDmaBufferPrivateData;
4190 pPrivateData->enmCmd = VBOXVDMACMD_TYPE_DMA_NOP;
4191
4192 pRender->pDmaBufferPrivateData = (uint8_t*)pRender->pDmaBufferPrivateData + sizeof (VBOXWDDM_DMA_PRIVATEDATA_BASEHDR);
4193 pRender->pDmaBuffer = ((uint8_t*)pRender->pDmaBuffer) + pRender->CommandLength;
4194 Assert(pRender->DmaSize >= pRender->CommandLength);
4195 Assert(pRender->PatchLocationListOutSize >= pRender->PatchLocationListInSize);
4196 UINT cbPLL = pRender->PatchLocationListInSize * sizeof (pRender->pPatchLocationListOut[0]);
4197 memcpy(pRender->pPatchLocationListOut, pRender->pPatchLocationListIn, cbPLL);
4198 pRender->pPatchLocationListOut += pRender->PatchLocationListInSize;
4199 break;
4200 }
4201 default:
4202 return STATUS_INVALID_PARAMETER;
4203 }
4204
4205 drprintf(("<== "__FUNCTION__ ", hContext(0x%x)\n", hContext));
4206
4207 return Status;
4208}
4209
4210#define VBOXVDMACMD_DMA_PRESENT_BLT_MINSIZE() (VBOXVDMACMD_SIZE(VBOXVDMACMD_DMA_PRESENT_BLT))
4211#define VBOXVDMACMD_DMA_PRESENT_BLT_SIZE(_c) (VBOXVDMACMD_BODY_FIELD_OFFSET(UINT, VBOXVDMACMD_DMA_PRESENT_BLT, aDstSubRects[_c]))
4212
4213#ifdef VBOX_WITH_VDMA
4214DECLINLINE(VOID) vboxWddmRectlFromRect(const RECT *pRect, PVBOXVDMA_RECTL pRectl)
4215{
4216 pRectl->left = (int16_t)pRect->left;
4217 pRectl->width = (uint16_t)(pRect->right - pRect->left);
4218 pRectl->top = (int16_t)pRect->top;
4219 pRectl->height = (uint16_t)(pRect->bottom - pRect->top);
4220}
4221
4222DECLINLINE(VBOXVDMA_PIXEL_FORMAT) vboxWddmFromPixFormat(D3DDDIFORMAT format)
4223{
4224 return (VBOXVDMA_PIXEL_FORMAT)format;
4225}
4226
4227DECLINLINE(VOID) vboxWddmSurfDescFromAllocation(PVBOXWDDM_ALLOCATION pAllocation, PVBOXVDMA_SURF_DESC pDesc)
4228{
4229 pDesc->width = pAllocation->SurfDesc.width;
4230 pDesc->height = pAllocation->SurfDesc.height;
4231 pDesc->format = vboxWddmFromPixFormat(pAllocation->SurfDesc.format);
4232 pDesc->bpp = pAllocation->SurfDesc.bpp;
4233 pDesc->pitch = pAllocation->SurfDesc.pitch;
4234 pDesc->fFlags = 0;
4235}
4236#endif
4237
4238DECLINLINE(BOOLEAN) vboxWddmPixFormatConversionSupported(D3DDDIFORMAT From, D3DDDIFORMAT To)
4239{
4240 Assert(From != D3DDDIFMT_UNKNOWN);
4241 Assert(To != D3DDDIFMT_UNKNOWN);
4242 Assert(From == To);
4243 return From == To;
4244}
4245
4246#if 0
4247DECLINLINE(bool) vboxWddmCheckForVisiblePrimary(PDEVICE_EXTENSION pDevExt, PVBOXWDDM_ALLOCATION pAllocation)
4248{
4249 !!!primary could be of pAllocation->enmType == VBOXWDDM_ALLOC_TYPE_UMD_RC_GENERIC!!!
4250 if (pAllocation->enmType != VBOXWDDM_ALLOC_TYPE_STD_SHAREDPRIMARYSURFACE)
4251 return false;
4252
4253 if (!pAllocation->bVisible)
4254 return false;
4255
4256 D3DDDI_VIDEO_PRESENT_SOURCE_ID id = pAllocation->SurfDesc.VidPnSourceId;
4257 if (id >= (D3DDDI_VIDEO_PRESENT_SOURCE_ID)pDevExt->u.primary.cDisplays)
4258 return false;
4259
4260 PVBOXWDDM_SOURCE pSource = &pDevExt->aSources[id];
4261 if (pSource->pPrimaryAllocation != pAllocation)
4262 return false;
4263
4264 return true;
4265}
4266#endif
4267
4268/**
4269 * DxgkDdiPresent
4270 */
4271NTSTATUS
4272APIENTRY
4273DxgkDdiPresent(
4274 CONST HANDLE hContext,
4275 DXGKARG_PRESENT *pPresent)
4276{
4277 PAGED_CODE();
4278
4279// dfprintf(("==> "__FUNCTION__ ", hContext(0x%x)\n", hContext));
4280
4281 vboxVDbgBreakFv();
4282
4283 NTSTATUS Status = STATUS_SUCCESS;
4284 PVBOXWDDM_CONTEXT pContext = (PVBOXWDDM_CONTEXT)hContext;
4285 PVBOXWDDM_DEVICE pDevice = pContext->pDevice;
4286 PDEVICE_EXTENSION pDevExt = pDevice->pAdapter;
4287
4288 Assert(pPresent->DmaBufferPrivateDataSize >= sizeof (VBOXWDDM_DMA_PRIVATEDATA_PRESENTHDR));
4289 if (pPresent->DmaBufferPrivateDataSize < sizeof (VBOXWDDM_DMA_PRIVATEDATA_PRESENTHDR))
4290 {
4291 drprintf((__FUNCTION__": Present->DmaBufferPrivateDataSize(%d) < sizeof VBOXWDDM_DMA_PRIVATEDATA_PRESENTHDR (%d)\n", pPresent->DmaBufferPrivateDataSize , sizeof (VBOXWDDM_DMA_PRIVATEDATA_PRESENTHDR)));
4292 /* @todo: can this actually happen? what status tu return? */
4293 return STATUS_INVALID_PARAMETER;
4294 }
4295
4296 PVBOXWDDM_DMA_PRIVATEDATA_PRESENTHDR pPrivateData = (PVBOXWDDM_DMA_PRIVATEDATA_PRESENTHDR)pPresent->pDmaBufferPrivateData;
4297 pPrivateData->BaseHdr.fFlags.Value = 0;
4298 uint32_t cContexts3D = ASMAtomicReadU32(&pDevExt->cContexts3D);
4299#define VBOXWDDM_DUMMY_DMABUFFER_SIZE sizeof(RECT)
4300
4301 if (pPresent->Flags.Blt)
4302 {
4303 Assert(pPresent->Flags.Value == 1); /* only Blt is set, we do not support anything else for now */
4304 DXGK_ALLOCATIONLIST *pSrc = &pPresent->pAllocationList[DXGK_PRESENT_SOURCE_INDEX];
4305 DXGK_ALLOCATIONLIST *pDst = &pPresent->pAllocationList[DXGK_PRESENT_DESTINATION_INDEX];
4306 PVBOXWDDM_ALLOCATION pSrcAlloc = vboxWddmGetAllocationFromAllocList(pDevExt, pSrc);
4307 Assert(pSrcAlloc);
4308 if (pSrcAlloc)
4309 {
4310 PVBOXWDDM_ALLOCATION pDstAlloc = vboxWddmGetAllocationFromAllocList(pDevExt, pDst);
4311 Assert(pDstAlloc);
4312 if (pDstAlloc)
4313 {
4314 do
4315 {
4316#ifdef VBOXWDDM_RENDER_FROM_SHADOW
4317#if 0
4318 Assert (pSrcAlloc->enmType == VBOXWDDM_ALLOC_TYPE_STD_SHADOWSURFACE);
4319 Assert (pDstAlloc->enmType == VBOXWDDM_ALLOC_TYPE_STD_SHAREDPRIMARYSURFACE);
4320#else
4321 if (pContext->enmType == VBOXWDDM_CONTEXT_TYPE_SYSTEM)
4322 {
4323 Assert ((pSrcAlloc->enmType == VBOXWDDM_ALLOC_TYPE_STD_SHADOWSURFACE
4324 && pDstAlloc->enmType == VBOXWDDM_ALLOC_TYPE_STD_SHAREDPRIMARYSURFACE)
4325 || (pSrcAlloc->enmType == VBOXWDDM_ALLOC_TYPE_STD_SHAREDPRIMARYSURFACE
4326 && pDstAlloc->enmType == VBOXWDDM_ALLOC_TYPE_STD_SHADOWSURFACE));
4327 }
4328#endif
4329 /* issue VBOXWDDM_ALLOC_TYPE_STD_SHADOWSURFACE ONLY in case there are no 3D contexts currently
4330 * otherwise we would need info about all rects being updated on primary for visible rect reporting */
4331 if (!cContexts3D)
4332 {
4333 if (pDstAlloc->enmType == VBOXWDDM_ALLOC_TYPE_STD_SHAREDPRIMARYSURFACE
4334 && pSrcAlloc->enmType == VBOXWDDM_ALLOC_TYPE_STD_SHADOWSURFACE)
4335 {
4336 Assert(pContext->enmType == VBOXWDDM_CONTEXT_TYPE_SYSTEM);
4337 Assert(pDstAlloc->bAssigned);
4338 Assert(pDstAlloc->bVisible);
4339 if (pDstAlloc->bAssigned
4340 && pDstAlloc->bVisible)
4341 {
4342#ifdef VBOX_WITH_VIDEOHWACCEL
4343 if (vboxVhwaHlpOverlayListIsEmpty(pDevExt, pDstAlloc->SurfDesc.VidPnSourceId))
4344#endif
4345 {
4346 Assert(pPresent->DmaBufferPrivateDataSize >= sizeof (VBOXWDDM_DMA_PRIVATEDATA_SHADOW2PRIMARY));
4347 if (pPresent->DmaBufferPrivateDataSize >= sizeof (VBOXWDDM_DMA_PRIVATEDATA_SHADOW2PRIMARY))
4348 {
4349 VBOXWDDM_SOURCE *pSource = &pDevExt->aSources[pDstAlloc->SurfDesc.VidPnSourceId];
4350 vboxWddmAssignShadow(pDevExt, pSource, pSrcAlloc, pDstAlloc->SurfDesc.VidPnSourceId);
4351 Assert(pPresent->SrcRect.left == pPresent->DstRect.left);
4352 Assert(pPresent->SrcRect.right == pPresent->DstRect.right);
4353 Assert(pPresent->SrcRect.top == pPresent->DstRect.top);
4354 Assert(pPresent->SrcRect.bottom == pPresent->DstRect.bottom);
4355 RECT rect;
4356 if (pPresent->SubRectCnt)
4357 {
4358 rect = pPresent->pDstSubRects[0];
4359 for (UINT i = 1; i < pPresent->SubRectCnt; ++i)
4360 {
4361 vboxWddmRectUnited(&rect, &rect, &pPresent->pDstSubRects[i]);
4362 }
4363 }
4364 else
4365 rect = pPresent->SrcRect;
4366
4367
4368 pPresent->pDmaBufferPrivateData = (uint8_t*)pPresent->pDmaBufferPrivateData + sizeof (VBOXWDDM_DMA_PRIVATEDATA_SHADOW2PRIMARY);
4369 pPresent->pDmaBuffer = ((uint8_t*)pPresent->pDmaBuffer) + VBOXWDDM_DUMMY_DMABUFFER_SIZE;
4370 Assert(pPresent->DmaSize >= VBOXWDDM_DUMMY_DMABUFFER_SIZE);
4371 memset(pPresent->pPatchLocationListOut, 0, 2*sizeof (D3DDDI_PATCHLOCATIONLIST));
4372 pPresent->pPatchLocationListOut->PatchOffset = 0;
4373 pPresent->pPatchLocationListOut->AllocationIndex = DXGK_PRESENT_SOURCE_INDEX;
4374 ++pPresent->pPatchLocationListOut;
4375 pPresent->pPatchLocationListOut->PatchOffset = 4;
4376 pPresent->pPatchLocationListOut->AllocationIndex = DXGK_PRESENT_DESTINATION_INDEX;
4377 ++pPresent->pPatchLocationListOut;
4378
4379 pPrivateData->BaseHdr.enmCmd = VBOXVDMACMD_TYPE_DMA_PRESENT_SHADOW2PRIMARY;
4380 PVBOXWDDM_DMA_PRIVATEDATA_SHADOW2PRIMARY pS2P = (PVBOXWDDM_DMA_PRIVATEDATA_SHADOW2PRIMARY)pPrivateData;
4381 /* we do not know the shadow address yet, perform dummy DMA cycle */
4382 vboxWddmPopulateDmaAllocInfo(&pS2P->Shadow2Primary.ShadowAlloc, pSrcAlloc, pSrc);
4383// vboxWddmPopulateDmaAllocInfo(&pPrivateData->DstAllocInfo, pDstAlloc, pDst);
4384 pS2P->Shadow2Primary.SrcRect = rect;
4385 pS2P->Shadow2Primary.VidPnSourceId = pDstAlloc->SurfDesc.VidPnSourceId;
4386 break;
4387 }
4388 else
4389 {
4390 Status = STATUS_GRAPHICS_INSUFFICIENT_DMA_BUFFER;
4391 break;
4392 }
4393 }
4394 }
4395 }
4396 }
4397
4398 /* we're here because this is NOT a shadow->primary update
4399 * or because there are d3d contexts and we need to report visible rects
4400 * or because we have overlays active and we need a special handling for primary */
4401#endif
4402 UINT cbCmd = pPresent->DmaBufferPrivateDataSize;
4403 pPrivateData->BaseHdr.enmCmd = VBOXVDMACMD_TYPE_DMA_PRESENT_BLT;
4404
4405 PVBOXWDDM_DMA_PRIVATEDATA_BLT pBlt = (PVBOXWDDM_DMA_PRIVATEDATA_BLT)pPrivateData;
4406
4407 vboxWddmPopulateDmaAllocInfo(&pBlt->Blt.SrcAlloc, pSrcAlloc, pSrc);
4408 vboxWddmPopulateDmaAllocInfo(&pBlt->Blt.DstAlloc, pDstAlloc, pDst);
4409
4410 pBlt->Blt.SrcRect = pPresent->SrcRect;
4411 pBlt->Blt.DstRects.ContextRect = pPresent->DstRect;
4412 pBlt->Blt.DstRects.UpdateRects.cRects = 0;
4413 UINT cbHead = RT_OFFSETOF(VBOXWDDM_DMA_PRIVATEDATA_BLT, Blt.DstRects.UpdateRects.aRects[0]);
4414 Assert(pPresent->SubRectCnt > pPresent->MultipassOffset);
4415 UINT cbRects = (pPresent->SubRectCnt - pPresent->MultipassOffset) * sizeof (RECT);
4416 pPresent->pDmaBufferPrivateData = (uint8_t*)pPresent->pDmaBufferPrivateData + cbHead + cbRects;
4417 pPresent->pDmaBuffer = ((uint8_t*)pPresent->pDmaBuffer) + VBOXWDDM_DUMMY_DMABUFFER_SIZE;
4418 Assert(pPresent->DmaSize >= VBOXWDDM_DUMMY_DMABUFFER_SIZE);
4419 cbCmd -= cbHead;
4420 Assert(cbCmd < UINT32_MAX/2);
4421 Assert(cbCmd > sizeof (RECT));
4422 if (cbCmd >= cbRects)
4423 {
4424 cbCmd -= cbRects;
4425 memcpy(&pBlt->Blt.DstRects.UpdateRects.aRects[pPresent->MultipassOffset], pPresent->pDstSubRects, cbRects);
4426 pBlt->Blt.DstRects.UpdateRects.cRects += cbRects/sizeof (RECT);
4427 }
4428 else
4429 {
4430 UINT cbFitingRects = (cbCmd/sizeof (RECT)) * sizeof (RECT);
4431 Assert(cbFitingRects);
4432 memcpy(&pBlt->Blt.DstRects.UpdateRects.aRects[pPresent->MultipassOffset], pPresent->pDstSubRects, cbFitingRects);
4433 cbCmd -= cbFitingRects;
4434 pPresent->MultipassOffset += cbFitingRects/sizeof (RECT);
4435 pBlt->Blt.DstRects.UpdateRects.cRects += cbFitingRects/sizeof (RECT);
4436 Assert(pPresent->SubRectCnt > pPresent->MultipassOffset);
4437 Status = STATUS_GRAPHICS_INSUFFICIENT_DMA_BUFFER;
4438 }
4439
4440 memset(pPresent->pPatchLocationListOut, 0, 2*sizeof (D3DDDI_PATCHLOCATIONLIST));
4441 pPresent->pPatchLocationListOut->PatchOffset = 0;
4442 pPresent->pPatchLocationListOut->AllocationIndex = DXGK_PRESENT_SOURCE_INDEX;
4443 ++pPresent->pPatchLocationListOut;
4444 pPresent->pPatchLocationListOut->PatchOffset = 4;
4445 pPresent->pPatchLocationListOut->AllocationIndex = DXGK_PRESENT_DESTINATION_INDEX;
4446 ++pPresent->pPatchLocationListOut;
4447
4448 break;
4449#ifdef VBOX_WITH_VDMA
4450 cbCmd = pPresent->DmaSize;
4451
4452 Assert(pPresent->SubRectCnt);
4453 UINT cmdSize = VBOXVDMACMD_DMA_PRESENT_BLT_SIZE(pPresent->SubRectCnt - pPresent->MultipassOffset);
4454 PVBOXVDMACMD pCmd = (PVBOXVDMACMD)pPresent->pDmaBuffer;
4455 pPresent->pDmaBuffer = ((uint8_t*)pPresent->pDmaBuffer) + cmdSize;
4456 Assert(cbCmd >= VBOXVDMACMD_DMA_PRESENT_BLT_MINSIZE());
4457 if (cbCmd >= VBOXVDMACMD_DMA_PRESENT_BLT_MINSIZE())
4458 {
4459 if (vboxWddmPixFormatConversionSupported(pSrcAlloc->SurfDesc.format, pDstAlloc->SurfDesc.format))
4460 {
4461 memset(pPresent->pPatchLocationListOut, 0, 2*sizeof (D3DDDI_PATCHLOCATIONLIST));
4462 // pPresent->pPatchLocationListOut->PatchOffset = 0;
4463 // ++pPresent->pPatchLocationListOut;
4464 pPresent->pPatchLocationListOut->PatchOffset = VBOXVDMACMD_BODY_FIELD_OFFSET(UINT, VBOXVDMACMD_DMA_PRESENT_BLT, offSrc);
4465 pPresent->pPatchLocationListOut->AllocationIndex = DXGK_PRESENT_SOURCE_INDEX;
4466 ++pPresent->pPatchLocationListOut;
4467 pPresent->pPatchLocationListOut->PatchOffset = VBOXVDMACMD_BODY_FIELD_OFFSET(UINT, VBOXVDMACMD_DMA_PRESENT_BLT, offDst);
4468 pPresent->pPatchLocationListOut->AllocationIndex = DXGK_PRESENT_DESTINATION_INDEX;
4469 ++pPresent->pPatchLocationListOut;
4470
4471 pCmd->enmType = VBOXVDMACMD_TYPE_DMA_PRESENT_BLT;
4472 pCmd->u32CmdSpecific = 0;
4473 PVBOXVDMACMD_DMA_PRESENT_BLT pTransfer = VBOXVDMACMD_BODY(pCmd, VBOXVDMACMD_DMA_PRESENT_BLT);
4474 pTransfer->offSrc = (VBOXVIDEOOFFSET)pSrc->PhysicalAddress.QuadPart;
4475 pTransfer->offDst = (VBOXVIDEOOFFSET)pDst->PhysicalAddress.QuadPart;
4476 vboxWddmSurfDescFromAllocation(pSrcAlloc, &pTransfer->srcDesc);
4477 vboxWddmSurfDescFromAllocation(pDstAlloc, &pTransfer->dstDesc);
4478 vboxWddmRectlFromRect(&pPresent->SrcRect, &pTransfer->srcRectl);
4479 vboxWddmRectlFromRect(&pPresent->DstRect, &pTransfer->dstRectl);
4480 UINT i = 0;
4481 cbCmd -= VBOXVDMACMD_BODY_FIELD_OFFSET(UINT, VBOXVDMACMD_DMA_PRESENT_BLT, aDstSubRects);
4482 Assert(cbCmd >= sizeof (VBOXVDMA_RECTL));
4483 Assert(cbCmd < pPresent->DmaSize);
4484 for (; i < pPresent->SubRectCnt; ++i)
4485 {
4486 if (cbCmd < sizeof (VBOXVDMA_RECTL))
4487 {
4488 Assert(i);
4489 pPresent->MultipassOffset += i;
4490 Status = STATUS_GRAPHICS_INSUFFICIENT_DMA_BUFFER;
4491 break;
4492 }
4493 vboxWddmRectlFromRect(&pPresent->pDstSubRects[i + pPresent->MultipassOffset], &pTransfer->aDstSubRects[i]);
4494 cbCmd -= sizeof (VBOXVDMA_RECTL);
4495 }
4496 Assert(i);
4497 pPrivateData->BaseHdr.enmCmd = VBOXVDMACMD_TYPE_DMA_PRESENT_BLT;
4498 pTransfer->cDstSubRects = i;
4499 pPresent->pDmaBufferPrivateData = (uint8_t*)pPresent->pDmaBufferPrivateData + sizeof(VBOXWDDM_DMA_PRIVATEDATA_PRESENTHDR);
4500 }
4501 else
4502 {
4503 AssertBreakpoint();
4504 drprintf((__FUNCTION__": unsupported format conversion from(%d) to (%d)\n",pSrcAlloc->SurfDesc.format, pDstAlloc->SurfDesc.format));
4505 Status = STATUS_GRAPHICS_CANNOTCOLORCONVERT;
4506 }
4507 }
4508 else
4509 {
4510 /* this should not happen actually */
4511 drprintf((__FUNCTION__": cbCmd too small!! (%d)\n", cbCmd));
4512 Status = STATUS_GRAPHICS_INSUFFICIENT_DMA_BUFFER;
4513 }
4514#endif
4515 } while(0);
4516 }
4517 else
4518 {
4519 /* this should not happen actually */
4520 drprintf((__FUNCTION__": failed to get Dst Allocation info for hDeviceSpecificAllocation(0x%x)\n",pDst->hDeviceSpecificAllocation));
4521 Status = STATUS_INVALID_HANDLE;
4522 }
4523 }
4524 else
4525 {
4526 /* this should not happen actually */
4527 drprintf((__FUNCTION__": failed to get Src Allocation info for hDeviceSpecificAllocation(0x%x)\n",pSrc->hDeviceSpecificAllocation));
4528 Status = STATUS_INVALID_HANDLE;
4529 }
4530#if 0
4531 UINT cbCmd = pPresent->DmaSize;
4532
4533 Assert(pPresent->SubRectCnt);
4534 UINT cmdSize = VBOXVDMACMD_DMA_PRESENT_BLT_SIZE(pPresent->SubRectCnt - pPresent->MultipassOffset);
4535 PVBOXVDMACMD pCmd = (PVBOXVDMACMD)pPresent->pDmaBuffer;
4536 pPresent->pDmaBuffer = ((uint8_t*)pPresent->pDmaBuffer) + cmdSize;
4537 Assert(cbCmd >= VBOXVDMACMD_DMA_PRESENT_BLT_MINSIZE());
4538 if (cbCmd >= VBOXVDMACMD_DMA_PRESENT_BLT_MINSIZE())
4539 {
4540 DXGK_ALLOCATIONLIST *pSrc = &pPresent->pAllocationList[DXGK_PRESENT_SOURCE_INDEX];
4541 DXGK_ALLOCATIONLIST *pDst = &pPresent->pAllocationList[DXGK_PRESENT_DESTINATION_INDEX];
4542 PVBOXWDDM_ALLOCATION pSrcAlloc = vboxWddmGetAllocationFromAllocList(pDevExt, pSrc);
4543 Assert(pSrcAlloc);
4544 if (pSrcAlloc)
4545 {
4546 PVBOXWDDM_ALLOCATION pDstAlloc = vboxWddmGetAllocationFromAllocList(pDevExt, pDst);
4547 Assert(pDstAlloc);
4548 if (pDstAlloc)
4549 {
4550 if (vboxWddmPixFormatConversionSupported(pSrcAlloc->SurfDesc.format, pDstAlloc->SurfDesc.format))
4551 {
4552 memset(pPresent->pPatchLocationListOut, 0, 2*sizeof (D3DDDI_PATCHLOCATIONLIST));
4553// pPresent->pPatchLocationListOut->PatchOffset = 0;
4554// ++pPresent->pPatchLocationListOut;
4555 pPresent->pPatchLocationListOut->PatchOffset = VBOXVDMACMD_BODY_FIELD_OFFSET(UINT, VBOXVDMACMD_DMA_PRESENT_BLT, offSrc);
4556 pPresent->pPatchLocationListOut->AllocationIndex = DXGK_PRESENT_SOURCE_INDEX;
4557 ++pPresent->pPatchLocationListOut;
4558 pPresent->pPatchLocationListOut->PatchOffset = VBOXVDMACMD_BODY_FIELD_OFFSET(UINT, VBOXVDMACMD_DMA_PRESENT_BLT, offDst);
4559 pPresent->pPatchLocationListOut->AllocationIndex = DXGK_PRESENT_DESTINATION_INDEX;
4560 ++pPresent->pPatchLocationListOut;
4561
4562 pCmd->enmType = VBOXVDMACMD_TYPE_DMA_PRESENT_BLT;
4563 pCmd->u32CmdSpecific = 0;
4564 PVBOXVDMACMD_DMA_PRESENT_BLT pTransfer = VBOXVDMACMD_BODY(pCmd, VBOXVDMACMD_DMA_PRESENT_BLT);
4565 pTransfer->offSrc = (VBOXVIDEOOFFSET)pSrc->PhysicalAddress.QuadPart;
4566 pTransfer->offDst = (VBOXVIDEOOFFSET)pDst->PhysicalAddress.QuadPart;
4567 vboxWddmSurfDescFromAllocation(pSrcAlloc, &pTransfer->srcDesc);
4568 vboxWddmSurfDescFromAllocation(pDstAlloc, &pTransfer->dstDesc);
4569 vboxWddmRectlFromRect(&pPresent->SrcRect, &pTransfer->srcRectl);
4570 vboxWddmRectlFromRect(&pPresent->DstRect, &pTransfer->dstRectl);
4571 UINT i = 0;
4572 cbCmd -= VBOXVDMACMD_BODY_FIELD_OFFSET(UINT, VBOXVDMACMD_DMA_PRESENT_BLT, aDstSubRects);
4573 Assert(cbCmd >= sizeof (VBOXVDMA_RECTL));
4574 Assert(cbCmd < pPresent->DmaSize);
4575 for (; i < pPresent->SubRectCnt; ++i)
4576 {
4577 if (cbCmd < sizeof (VBOXVDMA_RECTL))
4578 {
4579 Assert(i);
4580 pPresent->MultipassOffset += i;
4581 Status = STATUS_GRAPHICS_INSUFFICIENT_DMA_BUFFER;
4582 break;
4583 }
4584 vboxWddmRectlFromRect(&pPresent->pDstSubRects[i + pPresent->MultipassOffset], &pTransfer->aDstSubRects[i]);
4585 cbCmd -= sizeof (VBOXVDMA_RECTL);
4586 }
4587 Assert(i);
4588 pTransfer->cDstSubRects = i;
4589 pPresent->pDmaBufferPrivateData = (uint8_t*)pPresent->pDmaBufferPrivateData + sizeof(VBOXWDDM_DMA_PRIVATEDATA_HDR);
4590 }
4591 else
4592 {
4593 AssertBreakpoint();
4594 drprintf((__FUNCTION__": unsupported format conversion from(%d) to (%d)\n",pSrcAlloc->SurfDesc.format, pDstAlloc->SurfDesc.format));
4595 Status = STATUS_GRAPHICS_CANNOTCOLORCONVERT;
4596 }
4597 }
4598 else
4599 {
4600 /* this should not happen actually */
4601 drprintf((__FUNCTION__": failed to get Dst Allocation info for hDeviceSpecificAllocation(0x%x)\n",pDst->hDeviceSpecificAllocation));
4602 Status = STATUS_INVALID_HANDLE;
4603 }
4604 }
4605 else
4606 {
4607 /* this should not happen actually */
4608 drprintf((__FUNCTION__": failed to get Src Allocation info for hDeviceSpecificAllocation(0x%x)\n",pSrc->hDeviceSpecificAllocation));
4609 Status = STATUS_INVALID_HANDLE;
4610 }
4611 }
4612 else
4613 {
4614 /* this should not happen actually */
4615 drprintf((__FUNCTION__": cbCmd too small!! (%d)\n", cbCmd));
4616 Status = STATUS_GRAPHICS_INSUFFICIENT_DMA_BUFFER;
4617 }
4618#endif
4619 }
4620 else if (pPresent->Flags.Flip)
4621 {
4622 Assert(pPresent->Flags.Value == 4); /* only Blt is set, we do not support anything else for now */
4623 Assert(pContext->enmType == VBOXWDDM_CONTEXT_TYPE_CUSTOM_3D);
4624 DXGK_ALLOCATIONLIST *pSrc = &pPresent->pAllocationList[DXGK_PRESENT_SOURCE_INDEX];
4625 PVBOXWDDM_ALLOCATION pSrcAlloc = vboxWddmGetAllocationFromAllocList(pDevExt, pSrc);
4626 Assert(pSrcAlloc);
4627 if (pSrcAlloc)
4628 {
4629 Assert(cContexts3D);
4630 pPrivateData->BaseHdr.enmCmd = VBOXVDMACMD_TYPE_DMA_PRESENT_FLIP;
4631 PVBOXWDDM_DMA_PRIVATEDATA_FLIP pFlip = (PVBOXWDDM_DMA_PRIVATEDATA_FLIP)pPrivateData;
4632
4633 vboxWddmPopulateDmaAllocInfo(&pFlip->Flip.Alloc, pSrcAlloc, pSrc);
4634
4635 UINT cbCmd = sizeof (VBOXWDDM_DMA_PRIVATEDATA_FLIP);
4636 pPresent->pDmaBufferPrivateData = (uint8_t*)pPresent->pDmaBufferPrivateData + cbCmd;
4637 pPresent->pDmaBuffer = ((uint8_t*)pPresent->pDmaBuffer) + VBOXWDDM_DUMMY_DMABUFFER_SIZE;
4638 Assert(pPresent->DmaSize >= VBOXWDDM_DUMMY_DMABUFFER_SIZE);
4639
4640 memset(pPresent->pPatchLocationListOut, 0, sizeof (D3DDDI_PATCHLOCATIONLIST));
4641 pPresent->pPatchLocationListOut->PatchOffset = 0;
4642 pPresent->pPatchLocationListOut->AllocationIndex = DXGK_PRESENT_SOURCE_INDEX;
4643 ++pPresent->pPatchLocationListOut;
4644 }
4645 else
4646 {
4647 /* this should not happen actually */
4648 drprintf((__FUNCTION__": failed to get pSrc Allocation info for hDeviceSpecificAllocation(0x%x)\n",pSrc->hDeviceSpecificAllocation));
4649 Status = STATUS_INVALID_HANDLE;
4650 }
4651 }
4652 else if (pPresent->Flags.ColorFill)
4653 {
4654 Assert(pContext->enmType == VBOXWDDM_CONTEXT_TYPE_CUSTOM_2D);
4655 Assert(pPresent->Flags.Value == 2); /* only ColorFill is set, we do not support anything else for now */
4656 DXGK_ALLOCATIONLIST *pDst = &pPresent->pAllocationList[DXGK_PRESENT_DESTINATION_INDEX];
4657 PVBOXWDDM_ALLOCATION pDstAlloc = vboxWddmGetAllocationFromAllocList(pDevExt, pDst);
4658 Assert(pDstAlloc);
4659 if (pDstAlloc)
4660 {
4661 UINT cbCmd = pPresent->DmaBufferPrivateDataSize;
4662 pPrivateData->BaseHdr.enmCmd = VBOXVDMACMD_TYPE_DMA_PRESENT_CLRFILL;
4663 PVBOXWDDM_DMA_PRIVATEDATA_CLRFILL pCF = (PVBOXWDDM_DMA_PRIVATEDATA_CLRFILL)pPrivateData;
4664
4665 vboxWddmPopulateDmaAllocInfo(&pCF->ClrFill.Alloc, pDstAlloc, pDst);
4666
4667 pCF->ClrFill.Color = pPresent->Color;
4668 pCF->ClrFill.Rects.cRects = 0;
4669 UINT cbHead = RT_OFFSETOF(VBOXWDDM_DMA_PRIVATEDATA_CLRFILL, ClrFill.Rects.aRects[0]);
4670 Assert(pPresent->SubRectCnt > pPresent->MultipassOffset);
4671 UINT cbRects = (pPresent->SubRectCnt - pPresent->MultipassOffset) * sizeof (RECT);
4672 pPresent->pDmaBufferPrivateData = (uint8_t*)pPresent->pDmaBufferPrivateData + cbHead + cbRects;
4673 pPresent->pDmaBuffer = ((uint8_t*)pPresent->pDmaBuffer) + VBOXWDDM_DUMMY_DMABUFFER_SIZE;
4674 Assert(pPresent->DmaSize >= VBOXWDDM_DUMMY_DMABUFFER_SIZE);
4675 cbCmd -= cbHead;
4676 Assert(cbCmd < UINT32_MAX/2);
4677 Assert(cbCmd > sizeof (RECT));
4678 if (cbCmd >= cbRects)
4679 {
4680 cbCmd -= cbRects;
4681 memcpy(&pCF->ClrFill.Rects.aRects[pPresent->MultipassOffset], pPresent->pDstSubRects, cbRects);
4682 pCF->ClrFill.Rects.cRects += cbRects/sizeof (RECT);
4683 }
4684 else
4685 {
4686 UINT cbFitingRects = (cbCmd/sizeof (RECT)) * sizeof (RECT);
4687 Assert(cbFitingRects);
4688 memcpy(&pCF->ClrFill.Rects.aRects[pPresent->MultipassOffset], pPresent->pDstSubRects, cbFitingRects);
4689 cbCmd -= cbFitingRects;
4690 pPresent->MultipassOffset += cbFitingRects/sizeof (RECT);
4691 pCF->ClrFill.Rects.cRects += cbFitingRects/sizeof (RECT);
4692 Assert(pPresent->SubRectCnt > pPresent->MultipassOffset);
4693 Status = STATUS_GRAPHICS_INSUFFICIENT_DMA_BUFFER;
4694 }
4695
4696 memset(pPresent->pPatchLocationListOut, 0, sizeof (D3DDDI_PATCHLOCATIONLIST));
4697 pPresent->pPatchLocationListOut->PatchOffset = 0;
4698 pPresent->pPatchLocationListOut->AllocationIndex = DXGK_PRESENT_DESTINATION_INDEX;
4699 ++pPresent->pPatchLocationListOut;
4700 }
4701 else
4702 {
4703 /* this should not happen actually */
4704 drprintf((__FUNCTION__": failed to get pDst Allocation info for hDeviceSpecificAllocation(0x%x)\n",pDst->hDeviceSpecificAllocation));
4705 Status = STATUS_INVALID_HANDLE;
4706 }
4707
4708 }
4709 else
4710 {
4711 drprintf((__FUNCTION__": cmd NOT IMPLEMENTED!! Flags(0x%x)\n", pPresent->Flags.Value));
4712 AssertBreakpoint();
4713 }
4714
4715// dfprintf(("<== "__FUNCTION__ ", hContext(0x%x), Status(0x%x)\n", hContext, Status));
4716
4717 return Status;
4718}
4719
4720NTSTATUS
4721APIENTRY
4722DxgkDdiUpdateOverlay(
4723 CONST HANDLE hOverlay,
4724 CONST DXGKARG_UPDATEOVERLAY *pUpdateOverlay)
4725{
4726 dfprintf(("==> "__FUNCTION__ ", hOverlay(0x%p)\n", hOverlay));
4727
4728 NTSTATUS Status = STATUS_SUCCESS;
4729 PVBOXWDDM_OVERLAY pOverlay = (PVBOXWDDM_OVERLAY)hOverlay;
4730 Assert(pOverlay);
4731 int rc = vboxVhwaHlpOverlayUpdate(pOverlay, &pUpdateOverlay->OverlayInfo);
4732 AssertRC(rc);
4733 if (RT_SUCCESS(rc))
4734 {
4735 RECT DstRect;
4736 vboxVhwaHlpOverlayDstRectGet(pOverlay->pDevExt, pOverlay, &DstRect);
4737 Status = vboxVdmaHlpUpdatePrimary(pOverlay->pDevExt, pOverlay->VidPnSourceId, &DstRect);
4738 Assert(Status == STATUS_SUCCESS);
4739 }
4740 else
4741 Status = STATUS_UNSUCCESSFUL;
4742
4743 dfprintf(("<== "__FUNCTION__ ", hOverlay(0x%p)\n", hOverlay));
4744
4745 return Status;
4746}
4747
4748NTSTATUS
4749APIENTRY
4750DxgkDdiFlipOverlay(
4751 CONST HANDLE hOverlay,
4752 CONST DXGKARG_FLIPOVERLAY *pFlipOverlay)
4753{
4754 dfprintf(("==> "__FUNCTION__ ", hOverlay(0x%p)\n", hOverlay));
4755
4756 NTSTATUS Status = STATUS_SUCCESS;
4757 PVBOXWDDM_OVERLAY pOverlay = (PVBOXWDDM_OVERLAY)hOverlay;
4758 Assert(pOverlay);
4759 int rc = vboxVhwaHlpOverlayFlip(pOverlay, pFlipOverlay);
4760 AssertRC(rc);
4761 if (RT_FAILURE(rc))
4762 Status = STATUS_UNSUCCESSFUL;
4763
4764 dfprintf(("<== "__FUNCTION__ ", hOverlay(0x%p)\n", hOverlay));
4765
4766 return Status;
4767}
4768
4769NTSTATUS
4770APIENTRY
4771DxgkDdiDestroyOverlay(
4772 CONST HANDLE hOverlay)
4773{
4774 dfprintf(("==> "__FUNCTION__ ", hOverlay(0x%p)\n", hOverlay));
4775
4776 NTSTATUS Status = STATUS_SUCCESS;
4777 PVBOXWDDM_OVERLAY pOverlay = (PVBOXWDDM_OVERLAY)hOverlay;
4778 Assert(pOverlay);
4779 vboxVhwaHlpOverlayListRemove(pOverlay->pDevExt, pOverlay);
4780 int rc = vboxVhwaHlpOverlayDestroy(pOverlay);
4781 AssertRC(rc);
4782 if (RT_SUCCESS(rc))
4783 vboxWddmMemFree(pOverlay);
4784 else
4785 Status = STATUS_UNSUCCESSFUL;
4786
4787 dfprintf(("<== "__FUNCTION__ ", hOverlay(0x%p)\n", hOverlay));
4788
4789 return Status;
4790}
4791
4792/**
4793 * DxgkDdiCreateContext
4794 */
4795NTSTATUS
4796APIENTRY
4797DxgkDdiCreateContext(
4798 CONST HANDLE hDevice,
4799 DXGKARG_CREATECONTEXT *pCreateContext)
4800{
4801 /* DxgkDdiCreateContext should be made pageable */
4802 PAGED_CODE();
4803
4804 dfprintf(("==> "__FUNCTION__ ", hDevice(0x%x)\n", hDevice));
4805
4806 vboxVDbgBreakFv();
4807
4808 NTSTATUS Status = STATUS_SUCCESS;
4809 PVBOXWDDM_DEVICE pDevice = (PVBOXWDDM_DEVICE)hDevice;
4810 PDEVICE_EXTENSION pDevExt = pDevice->pAdapter;
4811 PVBOXWDDM_CONTEXT pContext = (PVBOXWDDM_CONTEXT)vboxWddmMemAllocZero(sizeof (VBOXWDDM_CONTEXT));
4812 Assert(pContext);
4813 if (pContext)
4814 {
4815 pContext->pDevice = pDevice;
4816 pContext->hContext = pCreateContext->hContext;
4817 pContext->EngineAffinity = pCreateContext->EngineAffinity;
4818 pContext->NodeOrdinal = pCreateContext->NodeOrdinal;
4819 vboxVideoCmCtxInitEmpty(&pContext->CmContext);
4820 if (pCreateContext->Flags.SystemContext || pCreateContext->PrivateDriverDataSize == 0)
4821 {
4822 Assert(pCreateContext->PrivateDriverDataSize == 0);
4823 Assert(!pCreateContext->pPrivateDriverData);
4824 Assert(pCreateContext->Flags.Value <= 2); /* 2 is a GDI context in Win7 */
4825 pContext->enmType = VBOXWDDM_CONTEXT_TYPE_SYSTEM;
4826 for (int i = 0; i < pDevExt->u.primary.cDisplays; ++i)
4827 {
4828 pDevExt->aSources[i].offVram = VBOXVIDEOOFFSET_VOID;
4829 NTSTATUS tmpStatus= vboxWddmDisplaySettingsQueryPos(pDevExt, i, &pDevExt->aSources[i].VScreenPos);
4830 Assert(tmpStatus == STATUS_SUCCESS);
4831 }
4832 }
4833 else
4834 {
4835 Assert(pCreateContext->Flags.Value == 0);
4836 Assert(pCreateContext->PrivateDriverDataSize == sizeof (VBOXWDDM_CREATECONTEXT_INFO));
4837 Assert(pCreateContext->pPrivateDriverData);
4838 if (pCreateContext->PrivateDriverDataSize == sizeof (VBOXWDDM_CREATECONTEXT_INFO))
4839 {
4840 PVBOXWDDM_CREATECONTEXT_INFO pInfo = (PVBOXWDDM_CREATECONTEXT_INFO)pCreateContext->pPrivateDriverData;
4841 switch (pInfo->enmType)
4842 {
4843 case VBOXWDDM_CONTEXT_TYPE_CUSTOM_3D:
4844 {
4845 ExInitializeFastMutex(&pContext->SwapchainMutex);
4846 Status = vboxWddmHTableCreate(&pContext->Swapchains, 4);
4847 Assert(Status == STATUS_SUCCESS);
4848 if (Status == STATUS_SUCCESS)
4849 {
4850 pContext->enmType = VBOXWDDM_CONTEXT_TYPE_CUSTOM_3D;
4851 Status = vboxVideoCmCtxAdd(&pDevice->pAdapter->CmMgr, &pContext->CmContext, (HANDLE)pInfo->hUmEvent, pInfo->u64UmInfo);
4852 Assert(Status == STATUS_SUCCESS);
4853 if (Status == STATUS_SUCCESS)
4854 {
4855 // Assert(KeGetCurrentIrql() < DISPATCH_LEVEL);
4856 // ExAcquireFastMutex(&pDevExt->ContextMutex);
4857 ASMAtomicIncU32(&pDevExt->cContexts3D);
4858 // ExReleaseFastMutex(&pDevExt->ContextMutex);
4859 }
4860 else
4861 {
4862 vboxWddmHTableDestroy(&pContext->Swapchains);
4863 }
4864 }
4865 break;
4866 }
4867 case VBOXWDDM_CONTEXT_TYPE_CUSTOM_2D:
4868 case VBOXWDDM_CONTEXT_TYPE_CUSTOM_UHGSMI_3D:
4869 case VBOXWDDM_CONTEXT_TYPE_CUSTOM_UHGSMI_GL:
4870 {
4871 pContext->enmType = pInfo->enmType;
4872 break;
4873 }
4874 default:
4875 {
4876 Assert(0);
4877 Status = STATUS_INVALID_PARAMETER;
4878 break;
4879 }
4880 }
4881 }
4882 }
4883
4884 if (Status == STATUS_SUCCESS)
4885 {
4886 pCreateContext->hContext = pContext;
4887 pCreateContext->ContextInfo.DmaBufferSize = VBOXWDDM_C_DMA_BUFFER_SIZE;
4888 pCreateContext->ContextInfo.DmaBufferSegmentSet = 0;
4889 pCreateContext->ContextInfo.DmaBufferPrivateDataSize = VBOXWDDM_C_DMA_PRIVATEDATA_SIZE;
4890 pCreateContext->ContextInfo.AllocationListSize = VBOXWDDM_C_ALLOC_LIST_SIZE;
4891 pCreateContext->ContextInfo.PatchLocationListSize = VBOXWDDM_C_PATH_LOCATION_LIST_SIZE;
4892 //#if (DXGKDDI_INTERFACE_VERSION >= DXGKDDI_INTERFACE_VERSION_WIN7)
4893 //# error port to Win7 DDI
4894 // //pCreateContext->ContextInfo.DmaBufferAllocationGroup = ???;
4895 //#endif // DXGKDDI_INTERFACE_VERSION
4896 }
4897 else
4898 vboxWddmMemFree(pContext);
4899 }
4900 else
4901 Status = STATUS_NO_MEMORY;
4902
4903 dfprintf(("<== "__FUNCTION__ ", hDevice(0x%x)\n", hDevice));
4904
4905 return Status;
4906}
4907
4908NTSTATUS
4909APIENTRY
4910DxgkDdiDestroyContext(
4911 CONST HANDLE hContext)
4912{
4913 dfprintf(("==> "__FUNCTION__ ", hContext(0x%x)\n", hContext));
4914 vboxVDbgBreakFv();
4915 PVBOXWDDM_CONTEXT pContext = (PVBOXWDDM_CONTEXT)hContext;
4916 PDEVICE_EXTENSION pDevExt = pContext->pDevice->pAdapter;
4917 if (pContext->enmType == VBOXWDDM_CONTEXT_TYPE_CUSTOM_3D)
4918 {
4919 Assert(KeGetCurrentIrql() < DISPATCH_LEVEL);
4920// ExAcquireFastMutex(&pDevExt->ContextMutex);
4921// RemoveEntryList(&pContext->ListEntry);
4922 uint32_t cContexts = ASMAtomicDecU32(&pDevExt->cContexts3D);
4923// ExReleaseFastMutex(&pDevExt->ContextMutex);
4924 Assert(cContexts < UINT32_MAX/2);
4925 }
4926
4927 NTSTATUS Status = vboxVideoCmCtxRemove(&pContext->pDevice->pAdapter->CmMgr, &pContext->CmContext);
4928 Assert(Status == STATUS_SUCCESS);
4929 if (Status == STATUS_SUCCESS)
4930 {
4931 vboxWddmSwapchainCtxDestroyAll(pDevExt, pContext);
4932 vboxWddmMemFree(pContext);
4933 }
4934
4935 dfprintf(("<== "__FUNCTION__ ", hContext(0x%x)\n", hContext));
4936
4937 return Status;
4938}
4939
4940NTSTATUS
4941APIENTRY
4942DxgkDdiLinkDevice(
4943 __in CONST PDEVICE_OBJECT PhysicalDeviceObject,
4944 __in CONST PVOID MiniportDeviceContext,
4945 __inout PLINKED_DEVICE LinkedDevice
4946 )
4947{
4948 drprintf(("==> "__FUNCTION__ ", MiniportDeviceContext(0x%x)\n", MiniportDeviceContext));
4949 vboxVDbgBreakFv();
4950 AssertBreakpoint();
4951 drprintf(("<== "__FUNCTION__ ", MiniportDeviceContext(0x%x)\n", MiniportDeviceContext));
4952 return STATUS_NOT_IMPLEMENTED;
4953}
4954
4955NTSTATUS
4956APIENTRY
4957DxgkDdiSetDisplayPrivateDriverFormat(
4958 CONST HANDLE hAdapter,
4959 /*CONST*/ DXGKARG_SETDISPLAYPRIVATEDRIVERFORMAT* pSetDisplayPrivateDriverFormat
4960 )
4961{
4962 dfprintf(("==> "__FUNCTION__ ", hAdapter(0x%x)\n", hAdapter));
4963 vboxVDbgBreakFv();
4964 AssertBreakpoint();
4965 dfprintf(("<== "__FUNCTION__ ", hAdapter(0x%x)\n", hAdapter));
4966 return STATUS_SUCCESS;
4967}
4968
4969NTSTATUS APIENTRY CALLBACK DxgkDdiRestartFromTimeout(IN_CONST_HANDLE hAdapter)
4970{
4971 dfprintf(("==> "__FUNCTION__ ", hAdapter(0x%x)\n", hAdapter));
4972 vboxVDbgBreakFv();
4973 AssertBreakpoint();
4974 dfprintf(("<== "__FUNCTION__ ", hAdapter(0x%x)\n", hAdapter));
4975 return STATUS_SUCCESS;
4976}
4977
4978NTSTATUS
4979DriverEntry(
4980 IN PDRIVER_OBJECT DriverObject,
4981 IN PUNICODE_STRING RegistryPath
4982 )
4983{
4984 PAGED_CODE();
4985
4986 vboxVDbgBreakFv();
4987
4988 drprintf(("VBoxVideoWddm::DriverEntry. Built %s %s\n", __DATE__, __TIME__));
4989
4990 DRIVER_INITIALIZATION_DATA DriverInitializationData = {'\0'};
4991
4992 if (! ARGUMENT_PRESENT(DriverObject) ||
4993 ! ARGUMENT_PRESENT(RegistryPath))
4994 {
4995 return STATUS_INVALID_PARAMETER;
4996 }
4997
4998 // Fill in the DriverInitializationData structure and call DxgkInitialize()
4999 DriverInitializationData.Version = DXGKDDI_INTERFACE_VERSION;
5000
5001 DriverInitializationData.DxgkDdiAddDevice = DxgkDdiAddDevice;
5002 DriverInitializationData.DxgkDdiStartDevice = DxgkDdiStartDevice;
5003 DriverInitializationData.DxgkDdiStopDevice = DxgkDdiStopDevice;
5004 DriverInitializationData.DxgkDdiRemoveDevice = DxgkDdiRemoveDevice;
5005 DriverInitializationData.DxgkDdiDispatchIoRequest = DxgkDdiDispatchIoRequest;
5006 DriverInitializationData.DxgkDdiInterruptRoutine = DxgkDdiInterruptRoutine;
5007 DriverInitializationData.DxgkDdiDpcRoutine = DxgkDdiDpcRoutine;
5008 DriverInitializationData.DxgkDdiQueryChildRelations = DxgkDdiQueryChildRelations;
5009 DriverInitializationData.DxgkDdiQueryChildStatus = DxgkDdiQueryChildStatus;
5010 DriverInitializationData.DxgkDdiQueryDeviceDescriptor = DxgkDdiQueryDeviceDescriptor;
5011 DriverInitializationData.DxgkDdiSetPowerState = DxgkDdiSetPowerState;
5012 DriverInitializationData.DxgkDdiNotifyAcpiEvent = DxgkDdiNotifyAcpiEvent;
5013 DriverInitializationData.DxgkDdiResetDevice = DxgkDdiResetDevice;
5014 DriverInitializationData.DxgkDdiUnload = DxgkDdiUnload;
5015 DriverInitializationData.DxgkDdiQueryInterface = DxgkDdiQueryInterface;
5016 DriverInitializationData.DxgkDdiControlEtwLogging = DxgkDdiControlEtwLogging;
5017
5018 DriverInitializationData.DxgkDdiQueryAdapterInfo = DxgkDdiQueryAdapterInfo;
5019 DriverInitializationData.DxgkDdiCreateDevice = DxgkDdiCreateDevice;
5020 DriverInitializationData.DxgkDdiCreateAllocation = DxgkDdiCreateAllocation;
5021 DriverInitializationData.DxgkDdiDestroyAllocation = DxgkDdiDestroyAllocation;
5022 DriverInitializationData.DxgkDdiDescribeAllocation = DxgkDdiDescribeAllocation;
5023 DriverInitializationData.DxgkDdiGetStandardAllocationDriverData = DxgkDdiGetStandardAllocationDriverData;
5024 DriverInitializationData.DxgkDdiAcquireSwizzlingRange = DxgkDdiAcquireSwizzlingRange;
5025 DriverInitializationData.DxgkDdiReleaseSwizzlingRange = DxgkDdiReleaseSwizzlingRange;
5026 DriverInitializationData.DxgkDdiPatch = DxgkDdiPatch;
5027 DriverInitializationData.DxgkDdiSubmitCommand = DxgkDdiSubmitCommand;
5028 DriverInitializationData.DxgkDdiPreemptCommand = DxgkDdiPreemptCommand;
5029 DriverInitializationData.DxgkDdiBuildPagingBuffer = DxgkDdiBuildPagingBuffer;
5030 DriverInitializationData.DxgkDdiSetPalette = DxgkDdiSetPalette;
5031 DriverInitializationData.DxgkDdiSetPointerPosition = DxgkDdiSetPointerPosition;
5032 DriverInitializationData.DxgkDdiSetPointerShape = DxgkDdiSetPointerShape;
5033 DriverInitializationData.DxgkDdiResetFromTimeout = DxgkDdiResetFromTimeout;
5034 DriverInitializationData.DxgkDdiRestartFromTimeout = DxgkDdiRestartFromTimeout;
5035 DriverInitializationData.DxgkDdiEscape = DxgkDdiEscape;
5036 DriverInitializationData.DxgkDdiCollectDbgInfo = DxgkDdiCollectDbgInfo;
5037 DriverInitializationData.DxgkDdiQueryCurrentFence = DxgkDdiQueryCurrentFence;
5038 DriverInitializationData.DxgkDdiIsSupportedVidPn = DxgkDdiIsSupportedVidPn;
5039 DriverInitializationData.DxgkDdiRecommendFunctionalVidPn = DxgkDdiRecommendFunctionalVidPn;
5040 DriverInitializationData.DxgkDdiEnumVidPnCofuncModality = DxgkDdiEnumVidPnCofuncModality;
5041 DriverInitializationData.DxgkDdiSetVidPnSourceAddress = DxgkDdiSetVidPnSourceAddress;
5042 DriverInitializationData.DxgkDdiSetVidPnSourceVisibility = DxgkDdiSetVidPnSourceVisibility;
5043 DriverInitializationData.DxgkDdiCommitVidPn = DxgkDdiCommitVidPn;
5044 DriverInitializationData.DxgkDdiUpdateActiveVidPnPresentPath = DxgkDdiUpdateActiveVidPnPresentPath;
5045 DriverInitializationData.DxgkDdiRecommendMonitorModes = DxgkDdiRecommendMonitorModes;
5046 DriverInitializationData.DxgkDdiRecommendVidPnTopology = DxgkDdiRecommendVidPnTopology;
5047 DriverInitializationData.DxgkDdiGetScanLine = DxgkDdiGetScanLine;
5048 DriverInitializationData.DxgkDdiStopCapture = DxgkDdiStopCapture;
5049 DriverInitializationData.DxgkDdiControlInterrupt = DxgkDdiControlInterrupt;
5050 DriverInitializationData.DxgkDdiCreateOverlay = DxgkDdiCreateOverlay;
5051
5052 DriverInitializationData.DxgkDdiDestroyDevice = DxgkDdiDestroyDevice;
5053 DriverInitializationData.DxgkDdiOpenAllocation = DxgkDdiOpenAllocation;
5054 DriverInitializationData.DxgkDdiCloseAllocation = DxgkDdiCloseAllocation;
5055 DriverInitializationData.DxgkDdiRender = DxgkDdiRender;
5056 DriverInitializationData.DxgkDdiPresent = DxgkDdiPresent;
5057
5058 DriverInitializationData.DxgkDdiUpdateOverlay = DxgkDdiUpdateOverlay;
5059 DriverInitializationData.DxgkDdiFlipOverlay = DxgkDdiFlipOverlay;
5060 DriverInitializationData.DxgkDdiDestroyOverlay = DxgkDdiDestroyOverlay;
5061
5062 DriverInitializationData.DxgkDdiCreateContext = DxgkDdiCreateContext;
5063 DriverInitializationData.DxgkDdiDestroyContext = DxgkDdiDestroyContext;
5064
5065 DriverInitializationData.DxgkDdiLinkDevice = NULL; //DxgkDdiLinkDevice;
5066 DriverInitializationData.DxgkDdiSetDisplayPrivateDriverFormat = DxgkDdiSetDisplayPrivateDriverFormat;
5067//#if (DXGKDDI_INTERFACE_VERSION >= DXGKDDI_INTERFACE_VERSION_WIN7)
5068//# error port to Win7 DDI
5069// DriverInitializationData.DxgkDdiRenderKm = DxgkDdiRenderKm;
5070// DriverInitializationData.DxgkDdiRestartFromTimeout = DxgkDdiRestartFromTimeout;
5071// DriverInitializationData.DxgkDdiSetVidPnSourceVisibility = DxgkDdiSetVidPnSourceVisibility;
5072// DriverInitializationData.DxgkDdiUpdateActiveVidPnPresentPath = DxgkDdiUpdateActiveVidPnPresentPath;
5073// DriverInitializationData.DxgkDdiQueryVidPnHWCapability = DxgkDdiQueryVidPnHWCapability;
5074//#endif
5075
5076 return DxgkInitialize(DriverObject,
5077 RegistryPath,
5078 &DriverInitializationData);
5079}
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