VirtualBox

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

Last change on this file since 30346 was 30346, checked in by vboxsync, 15 years ago

wddm/3d: create render target resource & issue present request for getting d3d render visible regions, size and position

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