VirtualBox

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

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

wddm: vidpn more logging + cosmetics

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