VirtualBox

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

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

wddm/3d: basics for chromium over hgsmi

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