VirtualBox

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

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

Additions/WINNT/Graphics: more refactoring and some re-ordering

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

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