VirtualBox

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

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

wddm/3d: chromium over hgsmi transport fixing & perf measurement

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