VirtualBox

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

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

wddm/3d: visible regions bugfixes fixes

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