VirtualBox

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

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

wddm/3d: visible regions reporting API & impl (not tested enough yet)

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 164.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 case VBOXVDMACMD_TYPE_DMA_PRESENT_BLT:
2079 {
2080 PVBOXWDDM_DMA_PRESENT_BLT pBlt = (PVBOXWDDM_DMA_PRESENT_BLT)pPrivateData;
2081 uint32_t cContexts3D = ASMAtomicReadU32(&pDevExt->cContexts3D);
2082 if (cContexts3D)
2083 {
2084 if (pPrivateData->fFlags.bShadow2PrimaryUpdate)
2085 {
2086 RECT rect;
2087 Assert(pBlt->DstRects.cRects);
2088 if (pBlt->DstRects.cRects > 1)
2089 {
2090 rect = pBlt->DstRects.aRects[1];
2091 for (UINT i = 2; i < pBlt->DstRects.cRects; ++i)
2092 {
2093 vboxWddmRectUnited(&rect, &rect, &pBlt->DstRects.aRects[i]);
2094 }
2095 }
2096 else
2097 rect = pBlt->DstRects.aRects[0];
2098
2099 VBOXWDDM_SOURCE *pSource = &pDevExt->aSources[pPrivateData->SrcAllocInfo.srcId];
2100 VBOXVBVA_OP(ReportDirtyRect, pDevExt, &pSource->Vbva, &rect);
2101 }
2102 }
2103 else
2104 Assert(!pPrivateData->fFlags.bShadow2PrimaryUpdate);
2105
2106 VBOXWDDM_SHADOW_UPDATE_COMPLETION context;
2107 context.pDevExt = pDevExt;
2108 context.pTransactionData = pPrivateData;
2109 context.SubmissionFenceId = pSubmitCommand->SubmissionFenceId;
2110 Status = pDevExt->u.primary.DxgkInterface.DxgkCbSynchronizeExecution(
2111 pDevExt->u.primary.DxgkInterface.DeviceHandle,
2112 vboxWddmNotifyShadowUpdateCompletion,
2113 &context,
2114 0, /* IN ULONG MessageNumber */
2115 &bRet);
2116 break;
2117 }
2118
2119#endif
2120 default:
2121 {
2122 PVBOXVDMACBUF_DR pDr = vboxVdmaCBufDrCreate (&pDevExt->u.primary.Vdma, 0);
2123 if (!pDr)
2124 {
2125 /* @todo: try flushing.. */
2126 drprintf((__FUNCTION__": vboxVdmaCBufDrCreate returned NULL\n"));
2127 return STATUS_INSUFFICIENT_RESOURCES;
2128 }
2129 // vboxVdmaCBufDrCreate zero initializes the pDr
2130 //pDr->fFlags = 0;
2131 pDr->cbBuf = pSubmitCommand->DmaBufferSubmissionEndOffset - pSubmitCommand->DmaBufferSubmissionStartOffset;
2132 pDr->u32FenceId = pSubmitCommand->SubmissionFenceId;
2133 pDr->rc = VERR_NOT_IMPLEMENTED;
2134 if (pPrivateData)
2135 pDr->u64GuestContext = (uint64_t)pPrivateData->pContext;
2136 // else // vboxVdmaCBufDrCreate zero initializes the pDr
2137 // pDr->u64GuestContext = NULL;
2138 pDr->Location.phBuf = pSubmitCommand->DmaBufferPhysicalAddress.QuadPart + pSubmitCommand->DmaBufferSubmissionStartOffset;
2139
2140 vboxVdmaCBufDrSubmit (pDevExt, &pDevExt->u.primary.Vdma, pDr);
2141 break;
2142 }
2143 }
2144// dfprintf(("<== "__FUNCTION__ ", context(0x%x)\n", hAdapter));
2145
2146 return Status;
2147}
2148
2149NTSTATUS
2150APIENTRY
2151DxgkDdiPreemptCommand(
2152 CONST HANDLE hAdapter,
2153 CONST DXGKARG_PREEMPTCOMMAND* pPreemptCommand)
2154{
2155 dfprintf(("==> "__FUNCTION__ ", hAdapter(0x%x)\n", hAdapter));
2156
2157 AssertBreakpoint();
2158 /* @todo: fixme: implement */
2159
2160 dfprintf(("<== "__FUNCTION__ ", hAdapter(0x%x)\n", hAdapter));
2161
2162 return STATUS_SUCCESS;
2163}
2164
2165/*
2166 * DxgkDdiBuildPagingBuffer
2167 */
2168NTSTATUS
2169APIENTRY
2170DxgkDdiBuildPagingBuffer(
2171 CONST HANDLE hAdapter,
2172 DXGKARG_BUILDPAGINGBUFFER* pBuildPagingBuffer)
2173{
2174 /* DxgkDdiBuildPagingBuffer should be made pageable. */
2175 PAGED_CODE();
2176
2177 vboxVDbgBreakFv();
2178
2179 NTSTATUS Status = STATUS_SUCCESS;
2180
2181 dfprintf(("==> "__FUNCTION__ ", context(0x%x)\n", hAdapter));
2182
2183 /* @todo: */
2184 switch (pBuildPagingBuffer->Operation)
2185 {
2186 case DXGK_OPERATION_TRANSFER:
2187 {
2188// pBuildPagingBuffer->pDmaBuffer = (uint8_t*)pBuildPagingBuffer->pDmaBuffer + VBOXVDMACMD_SIZE(VBOXVDMACMD_DMA_BPB_TRANSFER);
2189 break;
2190 }
2191 case DXGK_OPERATION_FILL:
2192 {
2193// pBuildPagingBuffer->pDmaBuffer = (uint8_t*)pBuildPagingBuffer->pDmaBuffer + VBOXVDMACMD_SIZE(VBOXVDMACMD_DMA_BPB_FILL);
2194 break;
2195 }
2196 case DXGK_OPERATION_DISCARD_CONTENT:
2197 {
2198// AssertBreakpoint();
2199 break;
2200 }
2201 default:
2202 {
2203 drprintf((__FUNCTION__": unsupported op (%d)\n", pBuildPagingBuffer->Operation));
2204 AssertBreakpoint();
2205 break;
2206 }
2207 }
2208
2209 dfprintf(("<== "__FUNCTION__ ", context(0x%x)\n", hAdapter));
2210
2211 return Status;
2212
2213}
2214
2215NTSTATUS
2216APIENTRY
2217DxgkDdiSetPalette(
2218 CONST HANDLE hAdapter,
2219 CONST DXGKARG_SETPALETTE* pSetPalette
2220 )
2221{
2222 dfprintf(("==> "__FUNCTION__ ", hAdapter(0x%x)\n", hAdapter));
2223
2224 AssertBreakpoint();
2225 /* @todo: fixme: implement */
2226
2227 dfprintf(("<== "__FUNCTION__ ", hAdapter(0x%x)\n", hAdapter));
2228
2229 return STATUS_SUCCESS;
2230}
2231
2232BOOL vboxWddmPointerCopyColorData(CONST DXGKARG_SETPOINTERSHAPE* pSetPointerShape, PVIDEO_POINTER_ATTRIBUTES pPointerAttributes)
2233{
2234 /* Format of "hardware" pointer is:
2235 * 1 bpp AND mask with byte aligned scanlines,
2236 * B G R A bytes of XOR mask that starts on the next 4 byte aligned offset after AND mask.
2237 *
2238 * If fl & SPS_ALPHA then A bytes contain alpha channel information.
2239 * Otherwise A bytes are undefined (but will be 0).
2240 *
2241 */
2242 PBYTE pjSrcAnd = NULL;
2243 PBYTE pjSrcXor = NULL;
2244
2245 ULONG cy = 0;
2246
2247 PBYTE pjDstAnd = pPointerAttributes->Pixels;
2248 ULONG cjAnd = 0;
2249 PBYTE pjDstXor = pPointerAttributes->Pixels;
2250
2251 ULONG cxSrc = pSetPointerShape->Width;
2252 ULONG cySrc = pSetPointerShape->Width;
2253
2254 // Make sure the new pointer isn't too big to handle,
2255 // strip the size to 64x64 if necessary
2256 if (cxSrc > VBOXWDDM_C_POINTER_MAX_WIDTH)
2257 cxSrc = VBOXWDDM_C_POINTER_MAX_WIDTH;
2258
2259 if (cySrc > VBOXWDDM_C_POINTER_MAX_HEIGHT)
2260 cySrc = VBOXWDDM_C_POINTER_MAX_HEIGHT;
2261
2262 /* Size of AND mask in bytes */
2263 cjAnd = ((cxSrc + 7) / 8) * cySrc;
2264
2265 /* Pointer to XOR mask is 4-bytes aligned */
2266 pjDstXor += (cjAnd + 3) & ~3;
2267
2268 pPointerAttributes->Width = cxSrc;
2269 pPointerAttributes->Height = cySrc;
2270 pPointerAttributes->WidthInBytes = cxSrc * 4;
2271
2272 uint32_t cbData = ((cjAnd + 3) & ~3) + pPointerAttributes->Height*pPointerAttributes->WidthInBytes;
2273 uint32_t cbPointerAttributes = RT_OFFSETOF(VIDEO_POINTER_ATTRIBUTES, Pixels[cbData]);
2274 Assert(VBOXWDDM_POINTER_ATTRIBUTES_SIZE >= cbPointerAttributes);
2275 if (VBOXWDDM_POINTER_ATTRIBUTES_SIZE < cbPointerAttributes)
2276 {
2277 drprintf((__FUNCTION__": VBOXWDDM_POINTER_ATTRIBUTES_SIZE(%d) < cbPointerAttributes(%d)\n", VBOXWDDM_POINTER_ATTRIBUTES_SIZE, cbPointerAttributes));
2278 return FALSE;
2279 }
2280
2281 /* Init AND mask to 1 */
2282 RtlFillMemory (pjDstAnd, cjAnd, 0xFF);
2283
2284 PBYTE pjSrcAlpha = (PBYTE)pSetPointerShape->pPixels;
2285
2286 /*
2287 * Emulate AND mask to provide viewable mouse pointer for
2288 * hardware which does not support alpha channel.
2289 */
2290
2291 for (cy = 0; cy < cySrc; cy++)
2292 {
2293 ULONG cx;
2294
2295 UCHAR bitmask = 0x80;
2296
2297 for (cx = 0; cx < cxSrc; cx++, bitmask >>= 1)
2298 {
2299 if (bitmask == 0)
2300 {
2301 bitmask = 0x80;
2302 }
2303
2304 if (pjSrcAlpha[cx * 4 + 3] > 0x7f)
2305 {
2306 pjDstAnd[cx / 8] &= ~bitmask;
2307 }
2308 }
2309
2310 // Point to next source and dest scans
2311 pjSrcAlpha += pSetPointerShape->Pitch;
2312 pjDstAnd += (cxSrc + 7) / 8;
2313 }
2314
2315 /*
2316 * pso is 32 bit BGRX bitmap. Copy it to Pixels
2317 */
2318 pjSrcXor = (PBYTE)pSetPointerShape->pPixels;
2319 for (cy = 0; cy < cySrc; cy++)
2320 {
2321 /* 32 bit bitmap is being copied */
2322 RtlCopyMemory (pjDstXor, pjSrcXor, cxSrc * 4);
2323
2324 /* Point to next source and dest scans */
2325 pjSrcXor += pSetPointerShape->Pitch;
2326 pjDstXor += pPointerAttributes->WidthInBytes;
2327 }
2328
2329 return TRUE;
2330}
2331
2332BOOL vboxWddmPointerCopyMonoData(CONST DXGKARG_SETPOINTERSHAPE* pSetPointerShape, PVIDEO_POINTER_ATTRIBUTES pPointerAttributes)
2333{
2334 PBYTE pjSrc = NULL;
2335
2336 ULONG cy = 0;
2337
2338 PBYTE pjDstAnd = pPointerAttributes->Pixels;
2339 ULONG cjAnd = 0;
2340 PBYTE pjDstXor = pPointerAttributes->Pixels;
2341
2342 ULONG cxSrc = pSetPointerShape->Width;
2343 ULONG cySrc = pSetPointerShape->Height;
2344
2345 // Make sure the new pointer isn't too big to handle,
2346 // strip the size to 64x64 if necessary
2347 if (cxSrc > VBOXWDDM_C_POINTER_MAX_WIDTH)
2348 cxSrc = VBOXWDDM_C_POINTER_MAX_WIDTH;
2349
2350 if (cySrc > VBOXWDDM_C_POINTER_MAX_HEIGHT)
2351 cySrc = VBOXWDDM_C_POINTER_MAX_HEIGHT;
2352
2353 /* Size of AND mask in bytes */
2354 cjAnd = ((cxSrc + 7) / 8) * cySrc;
2355
2356 /* Pointer to XOR mask is 4-bytes aligned */
2357 pjDstXor += (cjAnd + 3) & ~3;
2358
2359 pPointerAttributes->Width = cxSrc;
2360 pPointerAttributes->Height = cySrc;
2361 pPointerAttributes->WidthInBytes = cxSrc * 4;
2362
2363 /* Init AND mask to 1 */
2364 RtlFillMemory (pjDstAnd, cjAnd, 0xFF);
2365
2366 /*
2367 * Copy AND mask.
2368 */
2369 pjSrc = (PBYTE)pSetPointerShape->pPixels;
2370
2371 for (cy = 0; cy < cySrc; cy++)
2372 {
2373 RtlCopyMemory (pjDstAnd, pjSrc, (cxSrc + 7) / 8);
2374
2375 // Point to next source and dest scans
2376 pjSrc += pSetPointerShape->Pitch;
2377 pjDstAnd += (cxSrc + 7) / 8;
2378 }
2379
2380 for (cy = 0; cy < cySrc; ++cy)
2381 {
2382 ULONG cx;
2383
2384 UCHAR bitmask = 0x80;
2385
2386 for (cx = 0; cx < cxSrc; cx++, bitmask >>= 1)
2387 {
2388 if (bitmask == 0)
2389 {
2390 bitmask = 0x80;
2391 }
2392
2393 if (pjSrc[cx / 8] & bitmask)
2394 {
2395 *(ULONG *)&pjDstXor[cx * 4] = 0x00FFFFFF;
2396 }
2397 else
2398 {
2399 *(ULONG *)&pjDstXor[cx * 4] = 0;
2400 }
2401 }
2402
2403 // Point to next source and dest scans
2404 pjSrc += pSetPointerShape->Pitch;
2405 pjDstXor += cxSrc * 4;
2406 }
2407
2408 return TRUE;
2409}
2410
2411static BOOLEAN vboxVddmPointerShapeToAttributes(CONST DXGKARG_SETPOINTERSHAPE* pSetPointerShape, PVBOXWDDM_POINTER_INFO pPointerInfo)
2412{
2413 PVIDEO_POINTER_ATTRIBUTES pPointerAttributes = &pPointerInfo->Attributes.data;
2414 /* pPointerAttributes maintains the visibility state, clear all except visibility */
2415 pPointerAttributes->Enable &= VBOX_MOUSE_POINTER_VISIBLE;
2416
2417 Assert(pSetPointerShape->Flags.Value == 1 || pSetPointerShape->Flags.Value == 2);
2418 if (pSetPointerShape->Flags.Color)
2419 {
2420 if (vboxWddmPointerCopyColorData(pSetPointerShape, pPointerAttributes))
2421 {
2422 pPointerAttributes->Flags = VIDEO_MODE_COLOR_POINTER;
2423 pPointerAttributes->Enable |= VBOX_MOUSE_POINTER_ALPHA;
2424 }
2425 else
2426 {
2427 drprintf((__FUNCTION__": vboxWddmPointerCopyColorData failed\n"));
2428 AssertBreakpoint();
2429 return FALSE;
2430 }
2431
2432 }
2433 else if (pSetPointerShape->Flags.Monochrome)
2434 {
2435 if (vboxWddmPointerCopyMonoData(pSetPointerShape, pPointerAttributes))
2436 {
2437 pPointerAttributes->Flags = VIDEO_MODE_MONO_POINTER;
2438 }
2439 else
2440 {
2441 drprintf((__FUNCTION__": vboxWddmPointerCopyMonoData failed\n"));
2442 AssertBreakpoint();
2443 return FALSE;
2444 }
2445 }
2446 else
2447 {
2448 drprintf((__FUNCTION__": unsupported pointer type Flags.Value(0x%x)\n", pSetPointerShape->Flags.Value));
2449 AssertBreakpoint();
2450 return FALSE;
2451 }
2452
2453 pPointerAttributes->Enable |= VBOX_MOUSE_POINTER_SHAPE;
2454
2455 /*
2456 * The hot spot coordinates and alpha flag will be encoded in the pPointerAttributes::Enable field.
2457 * High word will contain hot spot info and low word - flags.
2458 */
2459 pPointerAttributes->Enable |= (pSetPointerShape->YHot & 0xFF) << 24;
2460 pPointerAttributes->Enable |= (pSetPointerShape->XHot & 0xFF) << 16;
2461
2462 return TRUE;
2463}
2464
2465NTSTATUS
2466APIENTRY
2467DxgkDdiSetPointerPosition(
2468 CONST HANDLE hAdapter,
2469 CONST DXGKARG_SETPOINTERPOSITION* pSetPointerPosition)
2470{
2471// dfprintf(("==> "__FUNCTION__ ", hAdapter(0x%x)\n", hAdapter));
2472
2473 vboxVDbgBreakFv();
2474
2475 /* mouse integration is ON */
2476 PDEVICE_EXTENSION pDevExt = (PDEVICE_EXTENSION)hAdapter;
2477 PVBOXWDDM_POINTER_INFO pPointerInfo = &pDevExt->aSources[pSetPointerPosition->VidPnSourceId].PointerInfo;
2478 PVIDEO_POINTER_ATTRIBUTES pPointerAttributes = &pPointerInfo->Attributes.data;
2479 BOOLEAN bNotifyVisibility;
2480 if (pSetPointerPosition->Flags.Visible)
2481 {
2482 bNotifyVisibility = !(pPointerAttributes->Enable & VBOX_MOUSE_POINTER_VISIBLE);
2483 pPointerAttributes->Enable |= VBOX_MOUSE_POINTER_VISIBLE;
2484 }
2485 else
2486 {
2487 bNotifyVisibility = !!(pPointerAttributes->Enable & VBOX_MOUSE_POINTER_VISIBLE);
2488 pPointerAttributes->Enable &= ~VBOX_MOUSE_POINTER_VISIBLE;
2489 }
2490
2491 pPointerAttributes->Column = pSetPointerPosition->X;
2492 pPointerAttributes->Row = pSetPointerPosition->Y;
2493
2494 if (bNotifyVisibility && vboxQueryHostWantsAbsolute())
2495 {
2496 // tell the host to use the guest's pointer
2497 VIDEO_POINTER_ATTRIBUTES PointerAttributes;
2498
2499 /* Visible and No Shape means Show the pointer.
2500 * It is enough to init only this field.
2501 */
2502 PointerAttributes.Enable = pSetPointerPosition->Flags.Visible ? VBOX_MOUSE_POINTER_VISIBLE : 0;
2503
2504 BOOLEAN bResult = vboxUpdatePointerShape(pDevExt, &PointerAttributes, sizeof (PointerAttributes));
2505 Assert(bResult);
2506 }
2507
2508// dfprintf(("<== "__FUNCTION__ ", hAdapter(0x%x)\n", hAdapter));
2509
2510 return STATUS_SUCCESS;
2511}
2512
2513NTSTATUS
2514APIENTRY
2515DxgkDdiSetPointerShape(
2516 CONST HANDLE hAdapter,
2517 CONST DXGKARG_SETPOINTERSHAPE* pSetPointerShape)
2518{
2519// dfprintf(("==> "__FUNCTION__ ", hAdapter(0x%x)\n", hAdapter));
2520
2521 vboxVDbgBreakFv();
2522
2523 NTSTATUS Status = STATUS_NOT_SUPPORTED;
2524
2525 if (vboxQueryHostWantsAbsolute())
2526 {
2527 /* mouse integration is ON */
2528 PDEVICE_EXTENSION pDevExt = (PDEVICE_EXTENSION)hAdapter;
2529 PVBOXWDDM_POINTER_INFO pPointerInfo = &pDevExt->aSources[pSetPointerShape->VidPnSourceId].PointerInfo;
2530 /* @todo: to avoid extra data copy and extra heap allocation,
2531 * need to maintain the pre-allocated HGSMI buffer and convert the data directly to it */
2532 if (vboxVddmPointerShapeToAttributes(pSetPointerShape, pPointerInfo))
2533 {
2534 if (vboxUpdatePointerShape (pDevExt, &pPointerInfo->Attributes.data, VBOXWDDM_POINTER_ATTRIBUTES_SIZE))
2535 Status = STATUS_SUCCESS;
2536 else
2537 {
2538 AssertBreakpoint();
2539 drprintf((__FUNCTION__": vboxUpdatePointerShape failed\n"));
2540 }
2541 }
2542 }
2543
2544// dfprintf(("<== "__FUNCTION__ ", hAdapter(0x%x)\n", hAdapter));
2545
2546 return Status;
2547}
2548
2549NTSTATUS
2550APIENTRY CALLBACK
2551DxgkDdiResetFromTimeout(
2552 CONST HANDLE hAdapter)
2553{
2554 dfprintf(("==> "__FUNCTION__ ", hAdapter(0x%x)\n", hAdapter));
2555
2556 AssertBreakpoint();
2557 /* @todo: fixme: implement */
2558
2559 dfprintf(("<== "__FUNCTION__ ", hAdapter(0x%x)\n", hAdapter));
2560
2561 return STATUS_SUCCESS;
2562}
2563
2564
2565/* the lpRgnData->Buffer comes to us as RECT
2566 * to avoid extra memcpy we cast it to PRTRECT assuming
2567 * they are identical */
2568AssertCompile(sizeof(RECT) == sizeof(RTRECT));
2569AssertCompile(RT_OFFSETOF(RECT, left) == RT_OFFSETOF(RTRECT, xLeft));
2570AssertCompile(RT_OFFSETOF(RECT, bottom) == RT_OFFSETOF(RTRECT, yBottom));
2571AssertCompile(RT_OFFSETOF(RECT, right) == RT_OFFSETOF(RTRECT, xRight));
2572AssertCompile(RT_OFFSETOF(RECT, top) == RT_OFFSETOF(RTRECT, yTop));
2573
2574NTSTATUS
2575APIENTRY
2576DxgkDdiEscape(
2577 CONST HANDLE hAdapter,
2578 CONST DXGKARG_ESCAPE* pEscape)
2579{
2580 PAGED_CODE();
2581
2582 dfprintf(("==> "__FUNCTION__ ", hAdapter(0x%x)\n", hAdapter));
2583
2584 NTSTATUS Status = STATUS_NOT_SUPPORTED;
2585 PDEVICE_EXTENSION pDevExt = (PDEVICE_EXTENSION)hAdapter;
2586 Assert(pEscape->PrivateDriverDataSize >= sizeof (VBOXDISPIFESCAPE));
2587 if (pEscape->PrivateDriverDataSize >= sizeof (VBOXDISPIFESCAPE))
2588 {
2589 PVBOXDISPIFESCAPE pEscapeHdr = (PVBOXDISPIFESCAPE)pEscape->pPrivateDriverData;
2590 switch (pEscapeHdr->escapeCode)
2591 {
2592 case VBOXESC_GETVBOXVIDEOCMCMD:
2593 {
2594 PVBOXWDDM_CONTEXT pContext = (PVBOXWDDM_CONTEXT)pEscape->hContext;
2595 PVBOXDISPIFESCAPE_GETVBOXVIDEOCMCMD pRegions = (PVBOXDISPIFESCAPE_GETVBOXVIDEOCMCMD)pEscapeHdr;
2596 Assert(pEscape->PrivateDriverDataSize >= sizeof (VBOXDISPIFESCAPE_GETVBOXVIDEOCMCMD));
2597 if (pEscape->PrivateDriverDataSize >= sizeof (VBOXDISPIFESCAPE_GETVBOXVIDEOCMCMD))
2598 {
2599 Status = vboxVideoCmEscape(&pContext->CmContext, pRegions, pEscape->PrivateDriverDataSize);
2600 Assert(Status == STATUS_SUCCESS);
2601 }
2602 else
2603 Status = STATUS_BUFFER_TOO_SMALL;
2604
2605 break;
2606 }
2607 case VBOXESC_SETVISIBLEREGION:
2608 {
2609 LPRGNDATA lpRgnData = VBOXDISPIFESCAPE_DATA(pEscapeHdr, RGNDATA);
2610 uint32_t cbData = VBOXDISPIFESCAPE_DATA_SIZE(pEscape->PrivateDriverDataSize);
2611 uint32_t cbRects = cbData - RT_OFFSETOF(RGNDATA, Buffer);
2612 /* the lpRgnData->Buffer comes to us as RECT
2613 * to avoid extra memcpy we cast it to PRTRECT assuming
2614 * they are identical
2615 * see AssertCompile's above */
2616
2617 RTRECT *pRect = (RTRECT *)&lpRgnData->Buffer;
2618
2619 uint32_t cRects = cbRects/sizeof(RTRECT);
2620 int rc;
2621
2622 dprintf(("IOCTL_VIDEO_VBOX_SETVISIBLEREGION cRects=%d\n", cRects));
2623 Assert(cbRects >= sizeof(RTRECT)
2624 && cbRects == cRects*sizeof(RTRECT)
2625 && cRects == lpRgnData->rdh.nCount);
2626 if ( cbRects >= sizeof(RTRECT)
2627 && cbRects == cRects*sizeof(RTRECT)
2628 && cRects == lpRgnData->rdh.nCount)
2629 {
2630 /*
2631 * Inform the host about the visible region
2632 */
2633 VMMDevVideoSetVisibleRegion *req = NULL;
2634
2635 rc = VbglGRAlloc ((VMMDevRequestHeader **)&req,
2636 sizeof (VMMDevVideoSetVisibleRegion) + (cRects-1)*sizeof(RTRECT),
2637 VMMDevReq_VideoSetVisibleRegion);
2638 AssertRC(rc);
2639 if (RT_SUCCESS(rc))
2640 {
2641 req->cRect = cRects;
2642 memcpy(&req->Rect, pRect, cRects*sizeof(RTRECT));
2643
2644 rc = VbglGRPerform (&req->header);
2645 AssertRC(rc);
2646 if (!RT_SUCCESS(rc))
2647 {
2648 drprintf((__FUNCTION__": VbglGRPerform failed rc (%d)", rc));
2649 Status = STATUS_UNSUCCESSFUL;
2650 }
2651 }
2652 else
2653 {
2654 drprintf((__FUNCTION__": VbglGRAlloc failed rc (%d)", rc));
2655 Status = STATUS_UNSUCCESSFUL;
2656 }
2657 }
2658 else
2659 {
2660 drprintf((__FUNCTION__": VBOXESC_SETVISIBLEREGION: incorrect buffer size (%d), reported count (%d)\n", cbRects, lpRgnData->rdh.nCount));
2661 AssertBreakpoint();
2662 Status = STATUS_INVALID_PARAMETER;
2663 }
2664 break;
2665 }
2666 case VBOXESC_ISVRDPACTIVE:
2667 /* @todo: implement */
2668 Status = STATUS_SUCCESS;
2669 break;
2670 case VBOXESC_REINITVIDEOMODES:
2671 VBoxWddmInvalidateModesTable(pDevExt);
2672 Status = STATUS_SUCCESS;
2673 break;
2674 default:
2675 drprintf((__FUNCTION__": unsupported escape code (0x%x)\n", pEscapeHdr->escapeCode));
2676 break;
2677 }
2678 }
2679 else
2680 {
2681 drprintf((__FUNCTION__": pEscape->PrivateDriverDataSize(%d) < (%d)\n", pEscape->PrivateDriverDataSize, sizeof (VBOXDISPIFESCAPE)));
2682 AssertBreakpoint();
2683 Status = STATUS_BUFFER_TOO_SMALL;
2684 }
2685
2686 dfprintf(("<== "__FUNCTION__ ", hAdapter(0x%x)\n", hAdapter));
2687
2688 return Status;
2689}
2690
2691NTSTATUS
2692APIENTRY
2693DxgkDdiCollectDbgInfo(
2694 CONST HANDLE hAdapter,
2695 CONST DXGKARG_COLLECTDBGINFO* pCollectDbgInfo
2696 )
2697{
2698 dfprintf(("==> "__FUNCTION__ ", hAdapter(0x%x)\n", hAdapter));
2699
2700 AssertBreakpoint();
2701
2702 dfprintf(("<== "__FUNCTION__ ", hAdapter(0x%x)\n", hAdapter));
2703
2704 return STATUS_SUCCESS;
2705}
2706
2707NTSTATUS
2708APIENTRY
2709DxgkDdiQueryCurrentFence(
2710 CONST HANDLE hAdapter,
2711 DXGKARG_QUERYCURRENTFENCE* pCurrentFence)
2712{
2713 dfprintf(("==> "__FUNCTION__ ", hAdapter(0x%x)\n", hAdapter));
2714
2715 AssertBreakpoint();
2716 /* @todo: fixme: implement */
2717
2718 dfprintf(("<== "__FUNCTION__ ", hAdapter(0x%x)\n", hAdapter));
2719
2720 return STATUS_SUCCESS;
2721}
2722
2723NTSTATUS
2724APIENTRY
2725DxgkDdiIsSupportedVidPn(
2726 CONST HANDLE hAdapter,
2727 OUT DXGKARG_ISSUPPORTEDVIDPN* pIsSupportedVidPnArg
2728 )
2729{
2730 /* The DxgkDdiIsSupportedVidPn should be made pageable. */
2731 PAGED_CODE();
2732
2733// dfprintf(("==> "__FUNCTION__ ", context(0x%x)\n", hAdapter));
2734
2735 vboxVDbgBreakFv();
2736
2737 PDEVICE_EXTENSION pContext = (PDEVICE_EXTENSION)hAdapter;
2738 BOOLEAN bSupported = TRUE;
2739 const DXGK_VIDPN_INTERFACE* pVidPnInterface = NULL;
2740 NTSTATUS Status = pContext->u.primary.DxgkInterface.DxgkCbQueryVidPnInterface(pIsSupportedVidPnArg->hDesiredVidPn, DXGK_VIDPN_INTERFACE_VERSION_V1, &pVidPnInterface);
2741 if (Status == STATUS_SUCCESS)
2742 {
2743 D3DKMDT_HVIDPNTOPOLOGY hVidPnTopology;
2744 const DXGK_VIDPNTOPOLOGY_INTERFACE* pVidPnTopologyInterface;
2745 Status = pVidPnInterface->pfnGetTopology(pIsSupportedVidPnArg->hDesiredVidPn, &hVidPnTopology, &pVidPnTopologyInterface);
2746 if (Status == STATUS_SUCCESS)
2747 {
2748 Status = vboxVidPnCheckTopology(pIsSupportedVidPnArg->hDesiredVidPn, hVidPnTopology, pVidPnTopologyInterface, &bSupported);
2749 if (Status == STATUS_SUCCESS && bSupported)
2750 {
2751 for (int id = 0; id < pContext->u.primary.cDisplays; ++id)
2752 {
2753 D3DKMDT_HVIDPNSOURCEMODESET hNewVidPnSourceModeSet;
2754 const DXGK_VIDPNSOURCEMODESET_INTERFACE *pVidPnSourceModeSetInterface;
2755 Status = pVidPnInterface->pfnAcquireSourceModeSet(pIsSupportedVidPnArg->hDesiredVidPn,
2756 id,
2757 &hNewVidPnSourceModeSet,
2758 &pVidPnSourceModeSetInterface);
2759 if (Status == STATUS_SUCCESS)
2760 {
2761 Status = vboxVidPnCheckSourceModeSet(pIsSupportedVidPnArg->hDesiredVidPn, hNewVidPnSourceModeSet, pVidPnSourceModeSetInterface, &bSupported);
2762
2763 pVidPnInterface->pfnReleaseSourceModeSet(pIsSupportedVidPnArg->hDesiredVidPn, hNewVidPnSourceModeSet);
2764
2765 if (Status != STATUS_SUCCESS || !bSupported)
2766 break;
2767 }
2768 else if (Status == STATUS_GRAPHICS_INVALID_VIDEO_PRESENT_SOURCE)
2769 {
2770 drprintf(("VBoxVideoWddm: Warning: pfnAcquireSourceModeSet returned STATUS_GRAPHICS_INVALID_VIDEO_PRESENT_SOURCE, continuing\n"));
2771 Status = STATUS_SUCCESS;
2772 }
2773 else
2774 {
2775 drprintf(("VBoxVideoWddm: pfnAcquireSourceModeSet failed Status(0x%x)\n"));
2776 break;
2777 }
2778 }
2779
2780 if (Status == STATUS_SUCCESS && bSupported)
2781 {
2782 for (int id = 0; id < pContext->u.primary.cDisplays; ++id)
2783 {
2784 D3DKMDT_HVIDPNTARGETMODESET hNewVidPnTargetModeSet;
2785 CONST DXGK_VIDPNTARGETMODESET_INTERFACE *pVidPnTargetModeSetInterface;
2786 Status = pVidPnInterface->pfnAcquireTargetModeSet(pIsSupportedVidPnArg->hDesiredVidPn,
2787 id, /*__in CONST D3DDDI_VIDEO_PRESENT_SOURCE_ID VidPnSourceId */
2788 &hNewVidPnTargetModeSet,
2789 &pVidPnTargetModeSetInterface);
2790 if (Status == STATUS_SUCCESS)
2791 {
2792 Status = vboxVidPnCheckTargetModeSet(pIsSupportedVidPnArg->hDesiredVidPn, hNewVidPnTargetModeSet, pVidPnTargetModeSetInterface, &bSupported);
2793
2794 pVidPnInterface->pfnReleaseTargetModeSet(pIsSupportedVidPnArg->hDesiredVidPn, hNewVidPnTargetModeSet);
2795
2796 if (Status != STATUS_SUCCESS || !bSupported)
2797 break;
2798 }
2799 else if (Status == STATUS_GRAPHICS_INVALID_VIDEO_PRESENT_SOURCE)
2800 {
2801 drprintf(("VBoxVideoWddm: Warning: pfnAcquireSourceModeSet returned STATUS_GRAPHICS_INVALID_VIDEO_PRESENT_SOURCE, continuing\n"));
2802 Status = STATUS_SUCCESS;
2803 }
2804 else
2805 {
2806 drprintf(("VBoxVideoWddm: pfnAcquireSourceModeSet failed Status(0x%x)\n"));
2807 break;
2808 }
2809 }
2810 }
2811 }
2812 }
2813 else
2814 {
2815 drprintf(("VBoxVideoWddm: pfnGetTopology failed Status(0x%x)\n"));
2816 }
2817 }
2818 else
2819 {
2820 drprintf(("VBoxVideoWddm: DxgkCbQueryVidPnInterface failed Status(0x%x)\n"));
2821 }
2822 pIsSupportedVidPnArg->IsVidPnSupported = bSupported;
2823
2824// dfprintf(("<== "__FUNCTION__ ", status(0x%x), context(0x%x)\n", Status, hAdapter));
2825
2826 return Status;
2827}
2828
2829NTSTATUS
2830APIENTRY
2831DxgkDdiRecommendFunctionalVidPn(
2832 CONST HANDLE hAdapter,
2833 CONST DXGKARG_RECOMMENDFUNCTIONALVIDPN* CONST pRecommendFunctionalVidPnArg
2834 )
2835{
2836 /* The DxgkDdiRecommendFunctionalVidPn should be made pageable. */
2837 PAGED_CODE();
2838
2839 dfprintf(("==> "__FUNCTION__ ", context(0x%x)\n", hAdapter));
2840
2841 vboxVDbgBreakF();
2842
2843 PDEVICE_EXTENSION pDevExt = (PDEVICE_EXTENSION)hAdapter;
2844 NTSTATUS Status;
2845 uint32_t cModes;
2846 int iPreferredMode;
2847 VIDEO_MODE_INFORMATION *pModes;
2848 uint32_t cResolutions;
2849 D3DKMDT_2DREGION *pResolutions;
2850 VIDEO_MODE_INFORMATION ModeInfos[4];
2851 VIDEO_MODE_INFORMATION *pModeInfos;
2852 D3DKMDT_2DREGION Resolution;
2853 uint32_t cModeInfos;
2854 int32_t iPreferredModeInfo;
2855 bool bFreeModes = false;
2856 VBoxWddmGetModesTable(pDevExt, /* PDEVICE_EXTENSION DeviceExtension */
2857 true, /* bool bRebuildTable*/
2858 &pModes, /* VIDEO_MODE_INFORMATION ** ppModes*/
2859 &cModes, /* uint32_t * pcModes */
2860 &iPreferredMode, /* uint32_t * pPreferrableMode*/
2861 &pResolutions, /* D3DKMDT_2DREGION **ppResolutions */
2862 &cResolutions /* uint32_t * pcResolutions */);
2863 Resolution.cx = pModes[iPreferredMode].VisScreenWidth;
2864 Resolution.cy = pModes[iPreferredMode].VisScreenHeight;
2865 Status = VBoxWddmGetModesForResolution(pDevExt, false,
2866 &Resolution,
2867 ModeInfos, RT_ELEMENTS(ModeInfos), &cModeInfos, &iPreferredModeInfo);
2868 Assert(Status == STATUS_SUCCESS || Status == STATUS_BUFFER_TOO_SMALL);
2869 if (Status == STATUS_SUCCESS)
2870 pModeInfos = ModeInfos;
2871 else if (Status == STATUS_BUFFER_TOO_SMALL)
2872 {
2873 uint32_t cModeInfos2;
2874 pModeInfos = (VIDEO_MODE_INFORMATION*)vboxWddmMemAlloc(sizeof (VIDEO_MODE_INFORMATION) * cModeInfos);
2875 if (pModeInfos)
2876 {
2877 bFreeModes = true;
2878 Status = VBoxWddmGetModesForResolution(pDevExt, false,
2879 &Resolution,
2880 pModeInfos, cModeInfos, &cModeInfos2, &iPreferredModeInfo);
2881 Assert(Status == STATUS_SUCCESS);
2882 Assert(iPreferredModeInfo >= 0); /* the array should contain the preffered info */
2883 if (Status != STATUS_SUCCESS)
2884 drprintf((__FUNCTION__": second call to VBoxWddmGetModesForResolution failed Status(0x%x), cModeInfos(%d), cModeInfos2(%d)\n", Status, cModeInfos, cModeInfos2));
2885 }
2886 }
2887 else
2888 drprintf((__FUNCTION__": VBoxWddmGetModesForResolution failed Status(0x%x)\n", Status));
2889
2890 if (Status == STATUS_SUCCESS)
2891 {
2892 for (int i = 0; i < pDevExt->u.primary.cDisplays; ++i)
2893 {
2894 Status = vboxVidPnCheckAddMonitorModes(pDevExt, i, D3DKMDT_MCO_DRIVER, &Resolution, 1, 0);
2895 Assert(Status == STATUS_SUCCESS);
2896 if (Status != STATUS_SUCCESS)
2897 {
2898 drprintf((__FUNCTION__": vboxVidPnCheckAddMonitorModes failed Status(0x%x)\n", Status));
2899 break;
2900 }
2901 }
2902
2903 if (Status == STATUS_SUCCESS)
2904 {
2905 const DXGK_VIDPN_INTERFACE* pVidPnInterface = NULL;
2906 Status = pDevExt->u.primary.DxgkInterface.DxgkCbQueryVidPnInterface(pRecommendFunctionalVidPnArg->hRecommendedFunctionalVidPn, DXGK_VIDPN_INTERFACE_VERSION_V1, &pVidPnInterface);
2907 Assert(Status == STATUS_SUCCESS);
2908 if (Status == STATUS_SUCCESS)
2909 {
2910 Assert (iPreferredModeInfo >= 0);
2911 Status = vboxVidPnCreatePopulateVidPnFromLegacy(pDevExt, pRecommendFunctionalVidPnArg->hRecommendedFunctionalVidPn, pVidPnInterface,
2912 pModeInfos, cModeInfos, iPreferredModeInfo,
2913 &Resolution, 1);
2914 Assert(Status == STATUS_SUCCESS);
2915 if (Status != STATUS_SUCCESS)
2916 drprintf((__FUNCTION__": vboxVidPnCreatePopulateVidPnFromLegacy failed Status(0x%x)\n", Status));
2917 }
2918 else
2919 drprintf((__FUNCTION__": DxgkCbQueryVidPnInterface failed Status(0x%x)\n", Status));
2920 }
2921 }
2922
2923 if (bFreeModes)
2924 vboxWddmMemFree(pModeInfos);
2925
2926 dfprintf(("<== "__FUNCTION__ ", status(0x%x), context(0x%x)\n", Status, hAdapter));
2927
2928 return Status;
2929}
2930
2931NTSTATUS
2932APIENTRY
2933DxgkDdiEnumVidPnCofuncModality(
2934 CONST HANDLE hAdapter,
2935 CONST DXGKARG_ENUMVIDPNCOFUNCMODALITY* CONST pEnumCofuncModalityArg
2936 )
2937{
2938 /* The DxgkDdiEnumVidPnCofuncModality function should be made pageable. */
2939 PAGED_CODE();
2940
2941// dfprintf(("==> "__FUNCTION__ ", context(0x%x)\n", hAdapter));
2942
2943 vboxVDbgBreakFv();
2944
2945 PDEVICE_EXTENSION pContext = (PDEVICE_EXTENSION)hAdapter;
2946 const DXGK_VIDPN_INTERFACE* pVidPnInterface = NULL;
2947 NTSTATUS Status = pContext->u.primary.DxgkInterface.DxgkCbQueryVidPnInterface(pEnumCofuncModalityArg->hConstrainingVidPn, DXGK_VIDPN_INTERFACE_VERSION_V1, &pVidPnInterface);
2948 if (Status == STATUS_SUCCESS)
2949 {
2950 D3DKMDT_HVIDPNTOPOLOGY hVidPnTopology;
2951 const DXGK_VIDPNTOPOLOGY_INTERFACE* pVidPnTopologyInterface;
2952 NTSTATUS Status = pVidPnInterface->pfnGetTopology(pEnumCofuncModalityArg->hConstrainingVidPn, &hVidPnTopology, &pVidPnTopologyInterface);
2953 Assert(Status == STATUS_SUCCESS);
2954 if (Status == STATUS_SUCCESS)
2955 {
2956 VBOXVIDPNCOFUNCMODALITY CbContext = {0};
2957 CbContext.pEnumCofuncModalityArg = pEnumCofuncModalityArg;
2958 VBoxWddmGetModesTable(pContext, /* PDEVICE_EXTENSION DeviceExtension */
2959 false, /* bool bRebuildTable*/
2960 &CbContext.pModes, /* VIDEO_MODE_INFORMATION ** ppModes*/
2961 &CbContext.cModes, /* uint32_t * pcModes */
2962 &CbContext.iPreferredMode, /* uint32_t * pPreferrableMode*/
2963 &CbContext.pResolutions, /* D3DKMDT_2DREGION **ppResolutions */
2964 &CbContext.cResolutions /* uint32_t * pcResolutions */);
2965 Assert(CbContext.cModes);
2966 Assert(CbContext.cModes > (uint32_t)CbContext.iPreferredMode);
2967 CbContext.iPreferredMode = -1; /* <- we do not want the modes to be pinned */
2968 Status = vboxVidPnEnumPaths(pContext, pEnumCofuncModalityArg->hConstrainingVidPn, pVidPnInterface,
2969 hVidPnTopology, pVidPnTopologyInterface,
2970 vboxVidPnCofuncModalityPathEnum, &CbContext);
2971 Assert(Status == STATUS_SUCCESS);
2972 if (Status == STATUS_SUCCESS)
2973 {
2974 Status = CbContext.Status;
2975 Assert(Status == STATUS_SUCCESS);
2976 if (Status != STATUS_SUCCESS)
2977 drprintf((__FUNCTION__ ": vboxVidPnAdjustSourcesTargetsCallback failed Status(0x%x)\n", Status));
2978 }
2979 else
2980 drprintf((__FUNCTION__ ": vboxVidPnEnumPaths failed Status(0x%x)\n", Status));
2981 }
2982 else
2983 drprintf((__FUNCTION__ ": pfnGetTopology failed Status(0x%x)\n", Status));
2984 }
2985 else
2986 drprintf((__FUNCTION__ ": DxgkCbQueryVidPnInterface failed Status(0x%x)\n", Status));
2987
2988// dfprintf(("<== "__FUNCTION__ ", status(0x%x), context(0x%x)\n", Status, hAdapter));
2989
2990 return Status;
2991}
2992
2993NTSTATUS
2994APIENTRY
2995DxgkDdiSetVidPnSourceAddress(
2996 CONST HANDLE hAdapter,
2997 CONST DXGKARG_SETVIDPNSOURCEADDRESS* pSetVidPnSourceAddress
2998 )
2999{
3000 /* The DxgkDdiSetVidPnSourceAddress function should be made pageable. */
3001 PAGED_CODE();
3002
3003 vboxVDbgBreakFv();
3004
3005 dfprintf(("==> "__FUNCTION__ ", context(0x%x)\n", hAdapter));
3006
3007 NTSTATUS Status = STATUS_SUCCESS;
3008 PDEVICE_EXTENSION pDevExt = (PDEVICE_EXTENSION)hAdapter;
3009 Assert((UINT)pDevExt->u.primary.cDisplays > pSetVidPnSourceAddress->VidPnSourceId);
3010 if ((UINT)pDevExt->u.primary.cDisplays > pSetVidPnSourceAddress->VidPnSourceId)
3011 {
3012 PVBOXWDDM_SOURCE pSource = &pDevExt->aSources[pSetVidPnSourceAddress->VidPnSourceId];
3013 PVBOXWDDM_ALLOCATION pAllocation;
3014 Assert(pSetVidPnSourceAddress->hAllocation);
3015 Assert(pSetVidPnSourceAddress->hAllocation || pSource->pPrimaryAllocation);
3016 Assert (pSetVidPnSourceAddress->Flags.Value < 2); /* i.e. 0 or 1 (ModeChange) */
3017 if (pSetVidPnSourceAddress->hAllocation)
3018 {
3019 pAllocation = (PVBOXWDDM_ALLOCATION)pSetVidPnSourceAddress->hAllocation;
3020 vboxWddmAssignPrimary(pDevExt, pSource, pAllocation, pSetVidPnSourceAddress->VidPnSourceId);
3021 }
3022 else
3023 pAllocation = pSource->pPrimaryAllocation;
3024
3025 Assert(pAllocation);
3026 if (pAllocation)
3027 {
3028 Assert(pAllocation->enmType == VBOXWDDM_ALLOC_TYPE_STD_SHAREDPRIMARYSURFACE);
3029 pAllocation->offVram = (VBOXVIDEOOFFSET)pSetVidPnSourceAddress->PrimaryAddress.QuadPart;
3030 pAllocation->SegmentId = pSetVidPnSourceAddress->PrimarySegment;
3031 Assert (pAllocation->SegmentId);
3032 Assert (!pAllocation->bVisible);
3033#ifndef VBOXWDDM_RENDER_FROM_SHADOW
3034 if (pAllocation->bVisible)
3035 {
3036 /* should not generally happen, but still inform host*/
3037 Status = vboxWddmGhDisplaySetInfo(pDevExt, pSource);
3038 Assert(Status == STATUS_SUCCESS);
3039 if (Status != STATUS_SUCCESS)
3040 drprintf((__FUNCTION__": vboxWddmGhDisplaySetInfo failed, Status (0x%x)\n", Status));
3041 }
3042#endif
3043 }
3044 else
3045 {
3046 drprintf((__FUNCTION__": no allocation data available!!\n"));
3047 Status = STATUS_INVALID_PARAMETER;
3048 }
3049 }
3050 else
3051 {
3052 drprintf((__FUNCTION__": invalid VidPnSourceId (%d), should be smaller than (%d)\n", pSetVidPnSourceAddress->VidPnSourceId, pDevExt->u.primary.cDisplays));
3053 Status = STATUS_INVALID_PARAMETER;
3054 }
3055
3056 dfprintf(("<== "__FUNCTION__ ", status(0x%x), context(0x%x)\n", Status, hAdapter));
3057
3058 return Status;
3059}
3060
3061NTSTATUS
3062APIENTRY
3063DxgkDdiSetVidPnSourceVisibility(
3064 CONST HANDLE hAdapter,
3065 CONST DXGKARG_SETVIDPNSOURCEVISIBILITY* pSetVidPnSourceVisibility
3066 )
3067{
3068 /* DxgkDdiSetVidPnSourceVisibility should be made pageable. */
3069 PAGED_CODE();
3070
3071 vboxVDbgBreakFv();
3072
3073 dfprintf(("==> "__FUNCTION__ ", context(0x%x)\n", hAdapter));
3074
3075 NTSTATUS Status = STATUS_SUCCESS;
3076 PDEVICE_EXTENSION pDevExt = (PDEVICE_EXTENSION)hAdapter;
3077 Assert((UINT)pDevExt->u.primary.cDisplays > pSetVidPnSourceVisibility->VidPnSourceId);
3078 if ((UINT)pDevExt->u.primary.cDisplays > pSetVidPnSourceVisibility->VidPnSourceId)
3079 {
3080 PVBOXWDDM_SOURCE pSource = &pDevExt->aSources[pSetVidPnSourceVisibility->VidPnSourceId];
3081 PVBOXWDDM_ALLOCATION pAllocation = pSource->pPrimaryAllocation;
3082
3083 Assert(pAllocation->bVisible != pSetVidPnSourceVisibility->Visible);
3084 if (pAllocation->bVisible != pSetVidPnSourceVisibility->Visible)
3085 {
3086 pAllocation->bVisible = pSetVidPnSourceVisibility->Visible;
3087#ifndef VBOXWDDM_RENDER_FROM_SHADOW
3088 if (pAllocation->bVisible)
3089 {
3090 Status = vboxWddmGhDisplaySetInfo(pDevExt, pSource);
3091 Assert(Status == STATUS_SUCCESS);
3092 if (Status != STATUS_SUCCESS)
3093 drprintf((__FUNCTION__": vboxWddmGhDisplaySetInfo failed, Status (0x%x)\n", Status));
3094 }
3095 else
3096 {
3097 vboxVdmaFlush (pDevExt, &pDevExt->u.primary.Vdma);
3098 }
3099#endif
3100 }
3101 }
3102 else
3103 {
3104 drprintf((__FUNCTION__": invalid VidPnSourceId (%d), should be smaller than (%d)\n", pSetVidPnSourceVisibility->VidPnSourceId, pDevExt->u.primary.cDisplays));
3105 Status = STATUS_INVALID_PARAMETER;
3106 }
3107
3108 dfprintf(("<== "__FUNCTION__ ", status(0x%x), context(0x%x)\n", Status, hAdapter));
3109
3110 return Status;
3111}
3112
3113NTSTATUS
3114APIENTRY
3115DxgkDdiCommitVidPn(
3116 CONST HANDLE hAdapter,
3117 CONST DXGKARG_COMMITVIDPN* CONST pCommitVidPnArg
3118 )
3119{
3120 dfprintf(("==> "__FUNCTION__ ", context(0x%x)\n", hAdapter));
3121
3122 PDEVICE_EXTENSION pDevExt = (PDEVICE_EXTENSION)hAdapter;
3123
3124 vboxVDbgBreakFv();
3125
3126 const DXGK_VIDPN_INTERFACE* pVidPnInterface = NULL;
3127 NTSTATUS Status = pDevExt->u.primary.DxgkInterface.DxgkCbQueryVidPnInterface(pCommitVidPnArg->hFunctionalVidPn, DXGK_VIDPN_INTERFACE_VERSION_V1, &pVidPnInterface);
3128 if (Status == STATUS_SUCCESS)
3129 {
3130 if (pCommitVidPnArg->AffectedVidPnSourceId != D3DDDI_ID_ALL)
3131 {
3132 Status = vboxVidPnCommitSourceModeForSrcId(
3133 pDevExt,
3134 pCommitVidPnArg->hFunctionalVidPn, pVidPnInterface,
3135 pCommitVidPnArg->AffectedVidPnSourceId, (PVBOXWDDM_ALLOCATION)pCommitVidPnArg->hPrimaryAllocation);
3136 Assert(Status == STATUS_SUCCESS);
3137 if (Status != STATUS_SUCCESS)
3138 drprintf((__FUNCTION__ ": vboxVidPnCommitSourceModeForSrcId failed Status(0x%x)\n", Status));
3139 }
3140 else
3141 {
3142 /* clear all current primaries */
3143 for (int i = 0; i < pDevExt->u.primary.cDisplays; ++i)
3144 {
3145 vboxWddmAssignPrimary(pDevExt, &pDevExt->aSources[i], NULL, i);
3146 }
3147
3148 D3DKMDT_HVIDPNTOPOLOGY hVidPnTopology;
3149 const DXGK_VIDPNTOPOLOGY_INTERFACE* pVidPnTopologyInterface;
3150 NTSTATUS Status = pVidPnInterface->pfnGetTopology(pCommitVidPnArg->hFunctionalVidPn, &hVidPnTopology, &pVidPnTopologyInterface);
3151 Assert(Status == STATUS_SUCCESS);
3152 if (Status == STATUS_SUCCESS)
3153 {
3154 VBOXVIDPNCOMMIT CbContext = {0};
3155 CbContext.pCommitVidPnArg = pCommitVidPnArg;
3156 Status = vboxVidPnEnumPaths(pDevExt, pCommitVidPnArg->hFunctionalVidPn, pVidPnInterface,
3157 hVidPnTopology, pVidPnTopologyInterface,
3158 vboxVidPnCommitPathEnum, &CbContext);
3159 Assert(Status == STATUS_SUCCESS);
3160 if (Status == STATUS_SUCCESS)
3161 {
3162 Status = CbContext.Status;
3163 Assert(Status == STATUS_SUCCESS);
3164 if (Status != STATUS_SUCCESS)
3165 drprintf((__FUNCTION__ ": vboxVidPnCommitPathEnum failed Status(0x%x)\n", Status));
3166 }
3167 else
3168 drprintf((__FUNCTION__ ": vboxVidPnEnumPaths failed Status(0x%x)\n", Status));
3169 }
3170 else
3171 drprintf((__FUNCTION__ ": pfnGetTopology failed Status(0x%x)\n", Status));
3172 }
3173
3174 if (Status == STATUS_SUCCESS)
3175 {
3176 pDevExt->u.primary.hCommittedVidPn = pCommitVidPnArg->hFunctionalVidPn;
3177 }
3178 }
3179 else
3180 drprintf((__FUNCTION__ ": DxgkCbQueryVidPnInterface failed Status(0x%x)\n", Status));
3181
3182 dfprintf(("<== "__FUNCTION__ ", status(0x%x), context(0x%x)\n", Status, hAdapter));
3183
3184 return Status;
3185}
3186
3187NTSTATUS
3188APIENTRY
3189DxgkDdiUpdateActiveVidPnPresentPath(
3190 CONST HANDLE hAdapter,
3191 CONST DXGKARG_UPDATEACTIVEVIDPNPRESENTPATH* CONST pUpdateActiveVidPnPresentPathArg
3192 )
3193{
3194 dfprintf(("==> "__FUNCTION__ ", hAdapter(0x%x)\n", hAdapter));
3195
3196 AssertBreakpoint();
3197
3198 dfprintf(("<== "__FUNCTION__ ", hAdapter(0x%x)\n", hAdapter));
3199
3200 return STATUS_SUCCESS;
3201}
3202
3203NTSTATUS
3204APIENTRY
3205DxgkDdiRecommendMonitorModes(
3206 CONST HANDLE hAdapter,
3207 CONST DXGKARG_RECOMMENDMONITORMODES* CONST pRecommendMonitorModesArg
3208 )
3209{
3210 dfprintf(("==> "__FUNCTION__ ", hAdapter(0x%x)\n", hAdapter));
3211
3212 vboxVDbgBreakFv();
3213
3214 PDEVICE_EXTENSION pDevExt = (PDEVICE_EXTENSION)hAdapter;
3215 NTSTATUS Status;
3216 uint32_t cModes;
3217 int32_t iPreferredMode;
3218 VIDEO_MODE_INFORMATION *pModes;
3219 uint32_t cResolutions;
3220 D3DKMDT_2DREGION *pResolutions;
3221 VBoxWddmGetModesTable(pDevExt, /* PDEVICE_EXTENSION DeviceExtension */
3222 false, /* bool bRebuildTable*/
3223 &pModes, /* VIDEO_MODE_INFORMATION ** ppModes*/
3224 &cModes, /* uint32_t * pcModes */
3225 &iPreferredMode, /* uint32_t * pPreferrableMode*/
3226 &pResolutions, /* D3DKMDT_2DREGION **ppResolutions */
3227 &cResolutions /* uint32_t * pcResolutions */);
3228
3229 for (uint32_t i = 0; i < cResolutions; i++)
3230 {
3231 D3DKMDT_MONITOR_SOURCE_MODE * pNewMonitorSourceModeInfo;
3232 Status = pRecommendMonitorModesArg->pMonitorSourceModeSetInterface->pfnCreateNewModeInfo(
3233 pRecommendMonitorModesArg->hMonitorSourceModeSet, &pNewMonitorSourceModeInfo);
3234 Assert(Status == STATUS_SUCCESS);
3235 if (Status == STATUS_SUCCESS)
3236 {
3237 Status = vboxVidPnPopulateMonitorSourceModeInfoFromLegacy(pDevExt,
3238 pNewMonitorSourceModeInfo,
3239 &pResolutions[i],
3240 D3DKMDT_MCO_DRIVER,
3241 FALSE);
3242 Assert(Status == STATUS_SUCCESS);
3243 if (Status == STATUS_SUCCESS)
3244 {
3245 Status = pRecommendMonitorModesArg->pMonitorSourceModeSetInterface->pfnAddMode(
3246 pRecommendMonitorModesArg->hMonitorSourceModeSet, pNewMonitorSourceModeInfo);
3247 Assert(Status == STATUS_SUCCESS);
3248 if (Status == STATUS_SUCCESS)
3249 continue;
3250 }
3251
3252 /* error has occured, release & break */
3253 pRecommendMonitorModesArg->pMonitorSourceModeSetInterface->pfnReleaseModeInfo(
3254 pRecommendMonitorModesArg->hMonitorSourceModeSet, pNewMonitorSourceModeInfo);
3255 break;
3256 }
3257 }
3258
3259 dfprintf(("<== "__FUNCTION__ ", hAdapter(0x%x)\n", hAdapter));
3260
3261 return Status;
3262}
3263
3264NTSTATUS
3265APIENTRY
3266DxgkDdiRecommendVidPnTopology(
3267 CONST HANDLE hAdapter,
3268 CONST DXGKARG_RECOMMENDVIDPNTOPOLOGY* CONST pRecommendVidPnTopologyArg
3269 )
3270{
3271 dfprintf(("==> "__FUNCTION__ ", hAdapter(0x%x)\n", hAdapter));
3272
3273 vboxVDbgBreakFv();
3274
3275 dfprintf(("<== "__FUNCTION__ ", hAdapter(0x%x)\n", hAdapter));
3276
3277 return STATUS_GRAPHICS_NO_RECOMMENDED_VIDPN_TOPOLOGY;
3278}
3279
3280NTSTATUS
3281APIENTRY
3282DxgkDdiGetScanLine(
3283 CONST HANDLE hAdapter,
3284 DXGKARG_GETSCANLINE* pGetScanLine)
3285{
3286 dfprintf(("==> "__FUNCTION__ ", hAdapter(0x%x)\n", hAdapter));
3287
3288 PDEVICE_EXTENSION pDevExt = (PDEVICE_EXTENSION)hAdapter;
3289
3290 Assert((UINT)pDevExt->u.primary.cDisplays > pGetScanLine->VidPnTargetId);
3291 VBOXWDDM_TARGET *pTarget = &pDevExt->aTargets[pGetScanLine->VidPnTargetId];
3292 Assert(pTarget->HeightTotal);
3293 Assert(pTarget->HeightVisible);
3294 Assert(pTarget->HeightTotal > pTarget->HeightVisible);
3295 Assert(pTarget->ScanLineState < pTarget->HeightTotal);
3296 if (pTarget->HeightTotal)
3297 {
3298 uint32_t curScanLine = pTarget->ScanLineState;
3299 ++pTarget->ScanLineState;
3300 if (pTarget->ScanLineState >= pTarget->HeightTotal)
3301 pTarget->ScanLineState = 0;
3302
3303
3304 BOOL bVBlank = (!curScanLine || curScanLine > pTarget->HeightVisible);
3305 pGetScanLine->ScanLine = curScanLine;
3306 pGetScanLine->InVerticalBlank = bVBlank;
3307 }
3308 else
3309 {
3310 pGetScanLine->InVerticalBlank = TRUE;
3311 pGetScanLine->ScanLine = 0;
3312 }
3313
3314 dfprintf(("<== "__FUNCTION__ ", hAdapter(0x%x)\n", hAdapter));
3315
3316 return STATUS_SUCCESS;
3317}
3318
3319NTSTATUS
3320APIENTRY
3321DxgkDdiStopCapture(
3322 CONST HANDLE hAdapter,
3323 CONST DXGKARG_STOPCAPTURE* pStopCapture)
3324{
3325 dfprintf(("==> "__FUNCTION__ ", hAdapter(0x%x)\n", hAdapter));
3326
3327 AssertBreakpoint();
3328
3329 dfprintf(("<== "__FUNCTION__ ", hAdapter(0x%x)\n", hAdapter));
3330
3331 return STATUS_SUCCESS;
3332}
3333
3334NTSTATUS
3335APIENTRY
3336DxgkDdiControlInterrupt(
3337 CONST HANDLE hAdapter,
3338 CONST DXGK_INTERRUPT_TYPE InterruptType,
3339 BOOLEAN Enable
3340 )
3341{
3342 dfprintf(("==> "__FUNCTION__ ", hAdapter(0x%x)\n", hAdapter));
3343
3344 AssertBreakpoint();
3345
3346 dfprintf(("<== "__FUNCTION__ ", hAdapter(0x%x)\n", hAdapter));
3347
3348 /* @todo: STATUS_NOT_IMPLEMENTED ?? */
3349 return STATUS_SUCCESS;
3350}
3351
3352NTSTATUS
3353APIENTRY
3354DxgkDdiCreateOverlay(
3355 CONST HANDLE hAdapter,
3356 DXGKARG_CREATEOVERLAY *pCreateOverlay)
3357{
3358 dfprintf(("==> "__FUNCTION__ ", hAdapter(0x%p)\n", hAdapter));
3359
3360 NTSTATUS Status = STATUS_SUCCESS;
3361 PDEVICE_EXTENSION pDevExt = (PDEVICE_EXTENSION)hAdapter;
3362 PVBOXWDDM_OVERLAY pOverlay = (PVBOXWDDM_OVERLAY)vboxWddmMemAllocZero(sizeof (VBOXWDDM_OVERLAY));
3363 Assert(pOverlay);
3364 if (pOverlay)
3365 {
3366 int rc = vboxVhwaHlpOverlayCreate(pDevExt, pCreateOverlay->VidPnSourceId, &pCreateOverlay->OverlayInfo, pOverlay);
3367 AssertRC(rc);
3368 if (RT_SUCCESS(rc))
3369 {
3370 pCreateOverlay->hOverlay = pOverlay;;
3371 }
3372 else
3373 {
3374 vboxWddmMemFree(pOverlay);
3375 Status = STATUS_UNSUCCESSFUL;
3376 }
3377 }
3378 else
3379 Status = STATUS_NO_MEMORY;
3380
3381 dfprintf(("<== "__FUNCTION__ ", hAdapter(0x%p)\n", hAdapter));
3382
3383 return Status;
3384}
3385
3386NTSTATUS
3387APIENTRY
3388DxgkDdiDestroyDevice(
3389 CONST HANDLE hDevice)
3390{
3391 /* DxgkDdiDestroyDevice should be made pageable. */
3392 PAGED_CODE();
3393
3394 dfprintf(("==> "__FUNCTION__ ", hDevice(0x%x)\n", hDevice));
3395
3396 vboxVDbgBreakFv();
3397
3398 vboxWddmMemFree(hDevice);
3399
3400 dfprintf(("<== "__FUNCTION__ ", \n"));
3401
3402 return STATUS_SUCCESS;
3403}
3404
3405/*
3406 * DxgkDdiOpenAllocation
3407 */
3408NTSTATUS
3409APIENTRY
3410DxgkDdiOpenAllocation(
3411 CONST HANDLE hDevice,
3412 CONST DXGKARG_OPENALLOCATION *pOpenAllocation)
3413{
3414 /* DxgkDdiOpenAllocation should be made pageable. */
3415 PAGED_CODE();
3416
3417 dfprintf(("==> "__FUNCTION__ ", hDevice(0x%x)\n", hDevice));
3418
3419 vboxVDbgBreakFv();
3420
3421 NTSTATUS Status = STATUS_SUCCESS;
3422 PVBOXWDDM_DEVICE pDevice = (PVBOXWDDM_DEVICE)hDevice;
3423 PDEVICE_EXTENSION pDevExt = pDevice->pAdapter;
3424 PVBOXWDDM_RCINFO pRcInfo = NULL;
3425 if (pOpenAllocation->PrivateDriverSize)
3426 {
3427 Assert(pOpenAllocation->PrivateDriverSize == sizeof (VBOXWDDM_RCINFO));
3428 Assert(pOpenAllocation->pPrivateDriverData);
3429 if (pOpenAllocation->PrivateDriverSize >= sizeof (VBOXWDDM_RCINFO))
3430 {
3431 pRcInfo = (PVBOXWDDM_RCINFO)pOpenAllocation->pPrivateDriverData;
3432 Assert(pRcInfo->cAllocInfos == pOpenAllocation->NumAllocations);
3433 }
3434 else
3435 Status = STATUS_INVALID_PARAMETER;
3436 }
3437
3438 if (Status == STATUS_SUCCESS)
3439 {
3440 for (UINT i = 0; i < pOpenAllocation->NumAllocations; ++i)
3441 {
3442 DXGK_OPENALLOCATIONINFO* pInfo = &pOpenAllocation->pOpenAllocation[i];
3443 Assert(pInfo->PrivateDriverDataSize == sizeof (VBOXWDDM_ALLOCINFO));
3444 Assert(pInfo->pPrivateDriverData);
3445 PVBOXWDDM_OPENALLOCATION pOa = (PVBOXWDDM_OPENALLOCATION)vboxWddmMemAllocZero(sizeof (VBOXWDDM_OPENALLOCATION));
3446 pOa->hAllocation = pInfo->hAllocation;
3447 pInfo->hDeviceSpecificAllocation = pOa;
3448
3449 if (pRcInfo)
3450 {
3451#ifdef VBOX_WITH_VIDEOHWACCEL
3452 if (pRcInfo->RcDesc.fFlags.Overlay)
3453 {
3454 if (pInfo->PrivateDriverDataSize >= sizeof (VBOXWDDM_ALLOCINFO))
3455 {
3456 PVBOXWDDM_ALLOCINFO pAllocInfo = (PVBOXWDDM_ALLOCINFO)pInfo->pPrivateDriverData;
3457 PVBOXWDDM_ALLOCATION pAllocation = vboxWddmGetAllocationFromOpenData(pDevExt, pOa);
3458 Assert(pAllocation);
3459 if (pAllocation)
3460 {
3461 /* we have queried host for some surface info, like pitch & size,
3462 * need to return it back to the UMD (User Mode Drive) */
3463 pAllocInfo->SurfDesc = pAllocation->SurfDesc;
3464 /* success, just contionue */
3465 continue;
3466 }
3467 else
3468 Status = STATUS_INVALID_PARAMETER;
3469 }
3470 else
3471 Status = STATUS_INVALID_PARAMETER;
3472
3473 /* we are here in case of error */
3474 AssertBreakpoint();
3475
3476 for (UINT j = 0; j < i; ++j)
3477 {
3478 DXGK_OPENALLOCATIONINFO* pInfo2Free = &pOpenAllocation->pOpenAllocation[j];
3479 PVBOXWDDM_OPENALLOCATION pOa2Free = (PVBOXWDDM_OPENALLOCATION)pInfo2Free->hDeviceSpecificAllocation;
3480 vboxWddmMemFree(pOa2Free);
3481 }
3482 }
3483#endif
3484 }
3485 }
3486 }
3487 dfprintf(("<== "__FUNCTION__ ", hDevice(0x%x)\n", hDevice));
3488
3489 return Status;
3490}
3491
3492NTSTATUS
3493APIENTRY
3494DxgkDdiCloseAllocation(
3495 CONST HANDLE hDevice,
3496 CONST DXGKARG_CLOSEALLOCATION* pCloseAllocation)
3497{
3498 /* DxgkDdiCloseAllocation should be made pageable. */
3499 PAGED_CODE();
3500
3501 dfprintf(("==> "__FUNCTION__ ", hDevice(0x%x)\n", hDevice));
3502
3503 vboxVDbgBreakFv();
3504
3505 for (UINT i = 0; i < pCloseAllocation->NumAllocations; ++i)
3506 {
3507 vboxWddmMemFree(pCloseAllocation->pOpenHandleList[i]);
3508 }
3509
3510 dfprintf(("<== "__FUNCTION__ ", hDevice(0x%x)\n", hDevice));
3511
3512 return STATUS_SUCCESS;
3513}
3514
3515NTSTATUS
3516APIENTRY
3517DxgkDdiRender(
3518 CONST HANDLE hContext,
3519 DXGKARG_RENDER *pRender)
3520{
3521 drprintf(("==> "__FUNCTION__ ", !!NOT_IMPLEMENTED!! hContext(0x%x)\n", hContext));
3522
3523 AssertBreakpoint();
3524
3525 drprintf(("<== "__FUNCTION__ ", !!NOT_IMPLEMENTED!! hContext(0x%x)\n", hContext));
3526
3527 return STATUS_NOT_IMPLEMENTED;
3528}
3529
3530#define VBOXVDMACMD_DMA_PRESENT_BLT_MINSIZE() (VBOXVDMACMD_SIZE(VBOXVDMACMD_DMA_PRESENT_BLT))
3531#define VBOXVDMACMD_DMA_PRESENT_BLT_SIZE(_c) (VBOXVDMACMD_BODY_FIELD_OFFSET(UINT, VBOXVDMACMD_DMA_PRESENT_BLT, aDstSubRects[_c]))
3532
3533DECLINLINE(PVBOXWDDM_ALLOCATION) vboxWddmGetAllocationFromAllocList(PDEVICE_EXTENSION pDevExt, DXGK_ALLOCATIONLIST *pAllocList)
3534{
3535 return vboxWddmGetAllocationFromOpenData(pDevExt, (PVBOXWDDM_OPENALLOCATION)pAllocList->hDeviceSpecificAllocation);
3536}
3537
3538DECLINLINE(VOID) vboxWddmRectlFromRect(const RECT *pRect, PVBOXVDMA_RECTL pRectl)
3539{
3540 pRectl->left = (int16_t)pRect->left;
3541 pRectl->width = (uint16_t)(pRect->right - pRect->left);
3542 pRectl->top = (int16_t)pRect->top;
3543 pRectl->height = (uint16_t)(pRect->bottom - pRect->top);
3544}
3545
3546DECLINLINE(VBOXVDMA_PIXEL_FORMAT) vboxWddmFromPixFormat(D3DDDIFORMAT format)
3547{
3548 return (VBOXVDMA_PIXEL_FORMAT)format;
3549}
3550
3551DECLINLINE(VOID) vboxWddmSurfDescFromAllocation(PVBOXWDDM_ALLOCATION pAllocation, PVBOXVDMA_SURF_DESC pDesc)
3552{
3553 pDesc->width = pAllocation->SurfDesc.width;
3554 pDesc->height = pAllocation->SurfDesc.height;
3555 pDesc->format = vboxWddmFromPixFormat(pAllocation->SurfDesc.format);
3556 pDesc->bpp = pAllocation->SurfDesc.bpp;
3557 pDesc->pitch = pAllocation->SurfDesc.pitch;
3558 pDesc->fFlags = 0;
3559}
3560
3561DECLINLINE(BOOLEAN) vboxWddmPixFormatConversionSupported(D3DDDIFORMAT From, D3DDDIFORMAT To)
3562{
3563 Assert(From != D3DDDIFMT_UNKNOWN);
3564 Assert(To != D3DDDIFMT_UNKNOWN);
3565 Assert(From == To);
3566 return From == To;
3567}
3568
3569DECLINLINE(bool) vboxWddmCheckForVisiblePrimary(PDEVICE_EXTENSION pDevExt, PVBOXWDDM_ALLOCATION pAllocation)
3570{
3571 if (pAllocation->enmType != VBOXWDDM_ALLOC_TYPE_STD_SHAREDPRIMARYSURFACE)
3572 return false;
3573
3574 if (!pAllocation->bVisible)
3575 return false;
3576
3577 D3DDDI_VIDEO_PRESENT_SOURCE_ID id = pAllocation->SurfDesc.VidPnSourceId;
3578 if (id >= (D3DDDI_VIDEO_PRESENT_SOURCE_ID)pDevExt->u.primary.cDisplays)
3579 return false;
3580
3581 PVBOXWDDM_SOURCE pSource = &pDevExt->aSources[id];
3582 if (pSource->pPrimaryAllocation != pAllocation)
3583 return false;
3584
3585 return true;
3586}
3587
3588static void vboxWddmPopulateDmaAllocInfo(PVBOXWDDM_DMA_ALLOCINFO pInfo, PVBOXWDDM_ALLOCATION pAlloc, DXGK_ALLOCATIONLIST *pDmaAlloc)
3589{
3590 pInfo->pAlloc = pAlloc;
3591 if (pDmaAlloc->SegmentId)
3592 {
3593 pInfo->offAlloc = (VBOXVIDEOOFFSET)pDmaAlloc->PhysicalAddress.QuadPart;
3594 pInfo->segmentIdAlloc = pDmaAlloc->SegmentId;
3595 }
3596 else
3597 pInfo->segmentIdAlloc = 0;
3598 pInfo->srcId = pAlloc->SurfDesc.VidPnSourceId;
3599}
3600/**
3601 * DxgkDdiPresent
3602 */
3603NTSTATUS
3604APIENTRY
3605DxgkDdiPresent(
3606 CONST HANDLE hContext,
3607 DXGKARG_PRESENT *pPresent)
3608{
3609 PAGED_CODE();
3610
3611// dfprintf(("==> "__FUNCTION__ ", hContext(0x%x)\n", hContext));
3612
3613 vboxVDbgBreakFv();
3614
3615 NTSTATUS Status = STATUS_SUCCESS;
3616 PVBOXWDDM_CONTEXT pContext = (PVBOXWDDM_CONTEXT)hContext;
3617 PVBOXWDDM_DEVICE pDevice = pContext->pDevice;
3618 PDEVICE_EXTENSION pDevExt = pDevice->pAdapter;
3619
3620 Assert(pPresent->DmaBufferPrivateDataSize >= sizeof (VBOXWDDM_DMA_PRIVATEDATA_HDR));
3621 if (pPresent->DmaBufferPrivateDataSize < sizeof (VBOXWDDM_DMA_PRIVATEDATA_HDR))
3622 {
3623 drprintf((__FUNCTION__": Present->DmaBufferPrivateDataSize(%d) < sizeof VBOXWDDM_DMA_PRIVATEDATA_HDR (%d)\n", pPresent->DmaBufferPrivateDataSize , sizeof (VBOXWDDM_DMA_PRIVATEDATA_HDR)));
3624 /* @todo: can this actually happen? what status tu return? */
3625 return STATUS_INVALID_PARAMETER;
3626 }
3627
3628 PVBOXWDDM_DMA_PRIVATEDATA_HDR pPrivateData = (PVBOXWDDM_DMA_PRIVATEDATA_HDR)pPresent->pDmaBufferPrivateData;
3629 pPrivateData->pContext = pContext;
3630 pPrivateData->fFlags.Value = 0;
3631 uint32_t cContexts3D = ASMAtomicReadU32(&pDevExt->cContexts3D);
3632#define VBOXWDDM_DUMMY_DMABUFFER_SIZE sizeof(RECT)
3633
3634 if (pPresent->Flags.Blt)
3635 {
3636 Assert(pPresent->Flags.Value == 1); /* only Blt is set, we do not support anything else for now */
3637 DXGK_ALLOCATIONLIST *pSrc = &pPresent->pAllocationList[DXGK_PRESENT_SOURCE_INDEX];
3638 DXGK_ALLOCATIONLIST *pDst = &pPresent->pAllocationList[DXGK_PRESENT_DESTINATION_INDEX];
3639 PVBOXWDDM_ALLOCATION pSrcAlloc = vboxWddmGetAllocationFromAllocList(pDevExt, pSrc);
3640 Assert(pSrcAlloc);
3641 if (pSrcAlloc)
3642 {
3643 PVBOXWDDM_ALLOCATION pDstAlloc = vboxWddmGetAllocationFromAllocList(pDevExt, pDst);
3644 Assert(pDstAlloc);
3645 if (pDstAlloc)
3646 {
3647 do
3648 {
3649#ifdef VBOXWDDM_RENDER_FROM_SHADOW
3650#if 0
3651 Assert (pSrcAlloc->enmType == VBOXWDDM_ALLOC_TYPE_STD_SHADOWSURFACE);
3652 Assert (pDstAlloc->enmType == VBOXWDDM_ALLOC_TYPE_STD_SHAREDPRIMARYSURFACE);
3653#else
3654 if (pContext->enmType == VBOXWDDM_CONTEXT_TYPE_SYSTEM)
3655 {
3656 Assert ((pSrcAlloc->enmType == VBOXWDDM_ALLOC_TYPE_STD_SHADOWSURFACE
3657 && pDstAlloc->enmType == VBOXWDDM_ALLOC_TYPE_STD_SHAREDPRIMARYSURFACE)
3658 || (pSrcAlloc->enmType == VBOXWDDM_ALLOC_TYPE_STD_SHAREDPRIMARYSURFACE
3659 && pDstAlloc->enmType == VBOXWDDM_ALLOC_TYPE_STD_SHADOWSURFACE));
3660 }
3661#endif
3662 /* issue VBOXWDDM_ALLOC_TYPE_STD_SHADOWSURFACE ONLY in case there are no 3D contexts currently
3663 * otherwise we would need info about all rects being updated on primary for visible rect reporting */
3664 if (!cContexts3D)
3665 {
3666 if (pDstAlloc->enmType == VBOXWDDM_ALLOC_TYPE_STD_SHAREDPRIMARYSURFACE
3667 && pSrcAlloc->enmType == VBOXWDDM_ALLOC_TYPE_STD_SHADOWSURFACE)
3668 {
3669 Assert(pContext->enmType == VBOXWDDM_CONTEXT_TYPE_SYSTEM);
3670 Assert(pDstAlloc->bAssigned);
3671 Assert(pDstAlloc->bVisible);
3672 if (pDstAlloc->bAssigned
3673 && pDstAlloc->bVisible)
3674 {
3675 Assert(pPresent->DmaBufferPrivateDataSize >= sizeof (VBOXWDDM_DMA_PRESENT_RENDER_FROM_SHADOW));
3676 if (pPresent->DmaBufferPrivateDataSize >= sizeof (VBOXWDDM_DMA_PRESENT_RENDER_FROM_SHADOW))
3677 {
3678 VBOXWDDM_SOURCE *pSource = &pDevExt->aSources[pDstAlloc->SurfDesc.VidPnSourceId];
3679 vboxWddmAssignShadow(pDevExt, pSource, pSrcAlloc, pDstAlloc->SurfDesc.VidPnSourceId);
3680 Assert(pPresent->SrcRect.left == pPresent->DstRect.left);
3681 Assert(pPresent->SrcRect.right == pPresent->DstRect.right);
3682 Assert(pPresent->SrcRect.top == pPresent->DstRect.top);
3683 Assert(pPresent->SrcRect.bottom == pPresent->DstRect.bottom);
3684 RECT rect;
3685 if (pPresent->SubRectCnt)
3686 {
3687 rect = pPresent->pDstSubRects[0];
3688 for (UINT i = 1; i < pPresent->SubRectCnt; ++i)
3689 {
3690 vboxWddmRectUnited(&rect, &rect, &pPresent->pDstSubRects[i]);
3691 }
3692 }
3693 else
3694 rect = pPresent->SrcRect;
3695
3696
3697 pPresent->pDmaBufferPrivateData = (uint8_t*)pPresent->pDmaBufferPrivateData + sizeof (VBOXWDDM_DMA_PRESENT_RENDER_FROM_SHADOW);
3698 pPresent->pDmaBuffer = ((uint8_t*)pPresent->pDmaBuffer) + VBOXWDDM_DUMMY_DMABUFFER_SIZE;
3699 Assert(pPresent->DmaSize >= VBOXWDDM_DUMMY_DMABUFFER_SIZE);
3700 memset(pPresent->pPatchLocationListOut, 0, 2*sizeof (D3DDDI_PATCHLOCATIONLIST));
3701 pPresent->pPatchLocationListOut->PatchOffset = 0;
3702 pPresent->pPatchLocationListOut->AllocationIndex = DXGK_PRESENT_SOURCE_INDEX;
3703 ++pPresent->pPatchLocationListOut;
3704 pPresent->pPatchLocationListOut->PatchOffset = 4;
3705 pPresent->pPatchLocationListOut->AllocationIndex = DXGK_PRESENT_DESTINATION_INDEX;
3706 ++pPresent->pPatchLocationListOut;
3707
3708
3709 /* we do not know the shadow address yet, perform dummy DMA cycle */
3710 pPrivateData->fFlags.bShadow2PrimaryUpdate = 1;
3711 pPrivateData->enmCmd = VBOXVDMACMD_TYPE_DMA_PRESENT_SHADOW2PRIMARY;
3712 vboxWddmPopulateDmaAllocInfo(&pPrivateData->SrcAllocInfo, pSrcAlloc, pSrc);
3713// no need to fill dst surf info here
3714// vboxWddmPopulateDmaAllocInfo(&pPrivateData->DstAllocInfo, pDstAlloc, pDst);
3715 PVBOXWDDM_DMA_PRESENT_RENDER_FROM_SHADOW pRFS = (PVBOXWDDM_DMA_PRESENT_RENDER_FROM_SHADOW)pPrivateData;
3716 pRFS->rect = rect;
3717 break;
3718 }
3719 else
3720 {
3721 Status = STATUS_GRAPHICS_INSUFFICIENT_DMA_BUFFER;
3722 break;
3723 }
3724 }
3725 }
3726 }
3727
3728 /* we're here because this is NOT a shadow->primary update
3729 * or because there are d3d contexts and we need to report visible rects */
3730#endif
3731 UINT cbCmd = pPresent->DmaBufferPrivateDataSize;
3732 pPrivateData->enmCmd = VBOXVDMACMD_TYPE_DMA_PRESENT_BLT;
3733
3734 if (pContext->enmType != VBOXWDDM_CONTEXT_TYPE_CUSTOM_3D)
3735 {
3736 vboxWddmPopulateDmaAllocInfo(&pPrivateData->SrcAllocInfo, pSrcAlloc, pSrc);
3737
3738 if (pDstAlloc->enmType == VBOXWDDM_ALLOC_TYPE_STD_SHAREDPRIMARYSURFACE
3739 && pSrcAlloc->enmType == VBOXWDDM_ALLOC_TYPE_STD_SHADOWSURFACE)
3740 {
3741#ifdef VBOXWDDM_RENDER_FROM_SHADOW
3742 Assert(cContexts3D);
3743#endif
3744 pPrivateData->fFlags.bShadow2PrimaryUpdate = 1;
3745 Assert(pContext->enmType == VBOXWDDM_CONTEXT_TYPE_SYSTEM);
3746 }
3747#ifdef VBOXWDDM_RENDER_FROM_SHADOW /* <- no need to fill dst surf info here */
3748 else
3749#endif
3750 {
3751 vboxWddmPopulateDmaAllocInfo(&pPrivateData->DstAllocInfo, pDstAlloc, pDst);
3752 }
3753 }
3754 /* else - no need to fill any surf info since we need this request for visible rects */
3755
3756 PVBOXWDDM_DMA_PRESENT_BLT pBlt = (PVBOXWDDM_DMA_PRESENT_BLT)pPrivateData;
3757 pBlt->SrcRect = pPresent->SrcRect;
3758 pBlt->DstRects.cRects = 1;
3759 pBlt->DstRects.aRects[0] = pPresent->DstRect;
3760 UINT cbHead = RT_OFFSETOF(VBOXWDDM_DMA_PRESENT_BLT, DstRects.aRects[1]);
3761 Assert(pPresent->SubRectCnt > pPresent->MultipassOffset);
3762 UINT cbRects = (pPresent->SubRectCnt - pPresent->MultipassOffset) * sizeof (RECT);
3763 pPresent->pDmaBuffer = ((uint8_t*)pPresent->pDmaBuffer) + cbHead + cbRects;
3764 cbCmd -= cbHead;
3765 Assert(cbCmd < UINT32_MAX/2);
3766 Assert(cbCmd > sizeof (RECT));
3767 if (cbCmd >= cbRects)
3768 {
3769 cbCmd -= cbRects;
3770 memcpy(&pBlt->DstRects.aRects[pPresent->MultipassOffset + 1], pPresent->pDstSubRects, cbRects);
3771 pBlt->DstRects.cRects += cbRects/sizeof (RECT);
3772 }
3773 else
3774 {
3775 UINT cbFitingRects = (cbCmd/sizeof (RECT)) * sizeof (RECT);
3776 Assert(cbFitingRects);
3777 memcpy(&pBlt->DstRects.aRects[pPresent->MultipassOffset + 1], pPresent->pDstSubRects, cbFitingRects);
3778 cbCmd -= cbFitingRects;
3779 pPresent->MultipassOffset += cbFitingRects/sizeof (RECT);
3780 pBlt->DstRects.cRects += cbFitingRects/sizeof (RECT);
3781 Assert(pPresent->SubRectCnt > pPresent->MultipassOffset);
3782 Status = STATUS_GRAPHICS_INSUFFICIENT_DMA_BUFFER;
3783 }
3784
3785 pPresent->pDmaBufferPrivateData = (uint8_t*)pPresent->pDmaBufferPrivateData + cbHead + cbRects;
3786 pPresent->pDmaBuffer = ((uint8_t*)pPresent->pDmaBuffer) + VBOXWDDM_DUMMY_DMABUFFER_SIZE;
3787 Assert(pPresent->DmaSize >= VBOXWDDM_DUMMY_DMABUFFER_SIZE);
3788 memset(pPresent->pPatchLocationListOut, 0, 2*sizeof (D3DDDI_PATCHLOCATIONLIST));
3789 pPresent->pPatchLocationListOut->PatchOffset = 0;
3790 pPresent->pPatchLocationListOut->AllocationIndex = DXGK_PRESENT_SOURCE_INDEX;
3791 ++pPresent->pPatchLocationListOut;
3792 pPresent->pPatchLocationListOut->PatchOffset = 4;
3793 pPresent->pPatchLocationListOut->AllocationIndex = DXGK_PRESENT_DESTINATION_INDEX;
3794 ++pPresent->pPatchLocationListOut;
3795
3796 break;
3797
3798 cbCmd = pPresent->DmaSize;
3799
3800 Assert(pPresent->SubRectCnt);
3801 UINT cmdSize = VBOXVDMACMD_DMA_PRESENT_BLT_SIZE(pPresent->SubRectCnt - pPresent->MultipassOffset);
3802 PVBOXVDMACMD pCmd = (PVBOXVDMACMD)pPresent->pDmaBuffer;
3803 pPresent->pDmaBuffer = ((uint8_t*)pPresent->pDmaBuffer) + cmdSize;
3804 Assert(cbCmd >= VBOXVDMACMD_DMA_PRESENT_BLT_MINSIZE());
3805 if (cbCmd >= VBOXVDMACMD_DMA_PRESENT_BLT_MINSIZE())
3806 {
3807 if (vboxWddmPixFormatConversionSupported(pSrcAlloc->SurfDesc.format, pDstAlloc->SurfDesc.format))
3808 {
3809 memset(pPresent->pPatchLocationListOut, 0, 2*sizeof (D3DDDI_PATCHLOCATIONLIST));
3810 // pPresent->pPatchLocationListOut->PatchOffset = 0;
3811 // ++pPresent->pPatchLocationListOut;
3812 pPresent->pPatchLocationListOut->PatchOffset = VBOXVDMACMD_BODY_FIELD_OFFSET(UINT, VBOXVDMACMD_DMA_PRESENT_BLT, offSrc);
3813 pPresent->pPatchLocationListOut->AllocationIndex = DXGK_PRESENT_SOURCE_INDEX;
3814 ++pPresent->pPatchLocationListOut;
3815 pPresent->pPatchLocationListOut->PatchOffset = VBOXVDMACMD_BODY_FIELD_OFFSET(UINT, VBOXVDMACMD_DMA_PRESENT_BLT, offDst);
3816 pPresent->pPatchLocationListOut->AllocationIndex = DXGK_PRESENT_DESTINATION_INDEX;
3817 ++pPresent->pPatchLocationListOut;
3818
3819 pCmd->enmType = VBOXVDMACMD_TYPE_DMA_PRESENT_BLT;
3820 pCmd->u32CmdSpecific = 0;
3821 PVBOXVDMACMD_DMA_PRESENT_BLT pTransfer = VBOXVDMACMD_BODY(pCmd, VBOXVDMACMD_DMA_PRESENT_BLT);
3822 pTransfer->offSrc = (VBOXVIDEOOFFSET)pSrc->PhysicalAddress.QuadPart;
3823 pTransfer->offDst = (VBOXVIDEOOFFSET)pDst->PhysicalAddress.QuadPart;
3824 vboxWddmSurfDescFromAllocation(pSrcAlloc, &pTransfer->srcDesc);
3825 vboxWddmSurfDescFromAllocation(pDstAlloc, &pTransfer->dstDesc);
3826 vboxWddmRectlFromRect(&pPresent->SrcRect, &pTransfer->srcRectl);
3827 vboxWddmRectlFromRect(&pPresent->DstRect, &pTransfer->dstRectl);
3828 UINT i = 0;
3829 cbCmd -= VBOXVDMACMD_BODY_FIELD_OFFSET(UINT, VBOXVDMACMD_DMA_PRESENT_BLT, aDstSubRects);
3830 Assert(cbCmd >= sizeof (VBOXVDMA_RECTL));
3831 Assert(cbCmd < pPresent->DmaSize);
3832 for (; i < pPresent->SubRectCnt; ++i)
3833 {
3834 if (cbCmd < sizeof (VBOXVDMA_RECTL))
3835 {
3836 Assert(i);
3837 pPresent->MultipassOffset += i;
3838 Status = STATUS_GRAPHICS_INSUFFICIENT_DMA_BUFFER;
3839 break;
3840 }
3841 vboxWddmRectlFromRect(&pPresent->pDstSubRects[i + pPresent->MultipassOffset], &pTransfer->aDstSubRects[i]);
3842 cbCmd -= sizeof (VBOXVDMA_RECTL);
3843 }
3844 Assert(i);
3845 pPrivateData->enmCmd = VBOXVDMACMD_TYPE_DMA_PRESENT_BLT;
3846 pTransfer->cDstSubRects = i;
3847 pPresent->pDmaBufferPrivateData = (uint8_t*)pPresent->pDmaBufferPrivateData + sizeof(VBOXWDDM_DMA_PRIVATEDATA_HDR);
3848 }
3849 else
3850 {
3851 AssertBreakpoint();
3852 drprintf((__FUNCTION__": unsupported format conversion from(%d) to (%d)\n",pSrcAlloc->SurfDesc.format, pDstAlloc->SurfDesc.format));
3853 Status = STATUS_GRAPHICS_CANNOTCOLORCONVERT;
3854 }
3855 }
3856 else
3857 {
3858 /* this should not happen actually */
3859 drprintf((__FUNCTION__": cbCmd too small!! (%d)\n", cbCmd));
3860 Status = STATUS_GRAPHICS_INSUFFICIENT_DMA_BUFFER;
3861 }
3862 } while(0);
3863 }
3864 else
3865 {
3866 /* this should not happen actually */
3867 drprintf((__FUNCTION__": failed to get Dst Allocation info for hDeviceSpecificAllocation(0x%x)\n",pDst->hDeviceSpecificAllocation));
3868 Status = STATUS_INVALID_HANDLE;
3869 }
3870 }
3871 else
3872 {
3873 /* this should not happen actually */
3874 drprintf((__FUNCTION__": failed to get Src Allocation info for hDeviceSpecificAllocation(0x%x)\n",pSrc->hDeviceSpecificAllocation));
3875 Status = STATUS_INVALID_HANDLE;
3876 }
3877#if 0
3878 UINT cbCmd = pPresent->DmaSize;
3879
3880 Assert(pPresent->SubRectCnt);
3881 UINT cmdSize = VBOXVDMACMD_DMA_PRESENT_BLT_SIZE(pPresent->SubRectCnt - pPresent->MultipassOffset);
3882 PVBOXVDMACMD pCmd = (PVBOXVDMACMD)pPresent->pDmaBuffer;
3883 pPresent->pDmaBuffer = ((uint8_t*)pPresent->pDmaBuffer) + cmdSize;
3884 Assert(cbCmd >= VBOXVDMACMD_DMA_PRESENT_BLT_MINSIZE());
3885 if (cbCmd >= VBOXVDMACMD_DMA_PRESENT_BLT_MINSIZE())
3886 {
3887 DXGK_ALLOCATIONLIST *pSrc = &pPresent->pAllocationList[DXGK_PRESENT_SOURCE_INDEX];
3888 DXGK_ALLOCATIONLIST *pDst = &pPresent->pAllocationList[DXGK_PRESENT_DESTINATION_INDEX];
3889 PVBOXWDDM_ALLOCATION pSrcAlloc = vboxWddmGetAllocationFromAllocList(pDevExt, pSrc);
3890 Assert(pSrcAlloc);
3891 if (pSrcAlloc)
3892 {
3893 PVBOXWDDM_ALLOCATION pDstAlloc = vboxWddmGetAllocationFromAllocList(pDevExt, pDst);
3894 Assert(pDstAlloc);
3895 if (pDstAlloc)
3896 {
3897 if (vboxWddmPixFormatConversionSupported(pSrcAlloc->SurfDesc.format, pDstAlloc->SurfDesc.format))
3898 {
3899 memset(pPresent->pPatchLocationListOut, 0, 2*sizeof (D3DDDI_PATCHLOCATIONLIST));
3900// pPresent->pPatchLocationListOut->PatchOffset = 0;
3901// ++pPresent->pPatchLocationListOut;
3902 pPresent->pPatchLocationListOut->PatchOffset = VBOXVDMACMD_BODY_FIELD_OFFSET(UINT, VBOXVDMACMD_DMA_PRESENT_BLT, offSrc);
3903 pPresent->pPatchLocationListOut->AllocationIndex = DXGK_PRESENT_SOURCE_INDEX;
3904 ++pPresent->pPatchLocationListOut;
3905 pPresent->pPatchLocationListOut->PatchOffset = VBOXVDMACMD_BODY_FIELD_OFFSET(UINT, VBOXVDMACMD_DMA_PRESENT_BLT, offDst);
3906 pPresent->pPatchLocationListOut->AllocationIndex = DXGK_PRESENT_DESTINATION_INDEX;
3907 ++pPresent->pPatchLocationListOut;
3908
3909 pCmd->enmType = VBOXVDMACMD_TYPE_DMA_PRESENT_BLT;
3910 pCmd->u32CmdSpecific = 0;
3911 PVBOXVDMACMD_DMA_PRESENT_BLT pTransfer = VBOXVDMACMD_BODY(pCmd, VBOXVDMACMD_DMA_PRESENT_BLT);
3912 pTransfer->offSrc = (VBOXVIDEOOFFSET)pSrc->PhysicalAddress.QuadPart;
3913 pTransfer->offDst = (VBOXVIDEOOFFSET)pDst->PhysicalAddress.QuadPart;
3914 vboxWddmSurfDescFromAllocation(pSrcAlloc, &pTransfer->srcDesc);
3915 vboxWddmSurfDescFromAllocation(pDstAlloc, &pTransfer->dstDesc);
3916 vboxWddmRectlFromRect(&pPresent->SrcRect, &pTransfer->srcRectl);
3917 vboxWddmRectlFromRect(&pPresent->DstRect, &pTransfer->dstRectl);
3918 UINT i = 0;
3919 cbCmd -= VBOXVDMACMD_BODY_FIELD_OFFSET(UINT, VBOXVDMACMD_DMA_PRESENT_BLT, aDstSubRects);
3920 Assert(cbCmd >= sizeof (VBOXVDMA_RECTL));
3921 Assert(cbCmd < pPresent->DmaSize);
3922 for (; i < pPresent->SubRectCnt; ++i)
3923 {
3924 if (cbCmd < sizeof (VBOXVDMA_RECTL))
3925 {
3926 Assert(i);
3927 pPresent->MultipassOffset += i;
3928 Status = STATUS_GRAPHICS_INSUFFICIENT_DMA_BUFFER;
3929 break;
3930 }
3931 vboxWddmRectlFromRect(&pPresent->pDstSubRects[i + pPresent->MultipassOffset], &pTransfer->aDstSubRects[i]);
3932 cbCmd -= sizeof (VBOXVDMA_RECTL);
3933 }
3934 Assert(i);
3935 pTransfer->cDstSubRects = i;
3936 pPresent->pDmaBufferPrivateData = (uint8_t*)pPresent->pDmaBufferPrivateData + sizeof(VBOXWDDM_DMA_PRIVATEDATA_HDR);
3937 }
3938 else
3939 {
3940 AssertBreakpoint();
3941 drprintf((__FUNCTION__": unsupported format conversion from(%d) to (%d)\n",pSrcAlloc->SurfDesc.format, pDstAlloc->SurfDesc.format));
3942 Status = STATUS_GRAPHICS_CANNOTCOLORCONVERT;
3943 }
3944 }
3945 else
3946 {
3947 /* this should not happen actually */
3948 drprintf((__FUNCTION__": failed to get Dst Allocation info for hDeviceSpecificAllocation(0x%x)\n",pDst->hDeviceSpecificAllocation));
3949 Status = STATUS_INVALID_HANDLE;
3950 }
3951 }
3952 else
3953 {
3954 /* this should not happen actually */
3955 drprintf((__FUNCTION__": failed to get Src Allocation info for hDeviceSpecificAllocation(0x%x)\n",pSrc->hDeviceSpecificAllocation));
3956 Status = STATUS_INVALID_HANDLE;
3957 }
3958 }
3959 else
3960 {
3961 /* this should not happen actually */
3962 drprintf((__FUNCTION__": cbCmd too small!! (%d)\n", cbCmd));
3963 Status = STATUS_GRAPHICS_INSUFFICIENT_DMA_BUFFER;
3964 }
3965#endif
3966 }
3967 else
3968 {
3969 drprintf((__FUNCTION__": cmd NOT IMPLEMENTED!! Flags(0x%x)\n", pPresent->Flags.Value));
3970 AssertBreakpoint();
3971 }
3972
3973// dfprintf(("<== "__FUNCTION__ ", hContext(0x%x), Status(0x%x)\n", hContext, Status));
3974
3975 return Status;
3976}
3977
3978NTSTATUS
3979APIENTRY
3980DxgkDdiUpdateOverlay(
3981 CONST HANDLE hOverlay,
3982 CONST DXGKARG_UPDATEOVERLAY *pUpdateOverlay)
3983{
3984 dfprintf(("==> "__FUNCTION__ ", hOverlay(0x%p)\n", hOverlay));
3985
3986 NTSTATUS Status = STATUS_SUCCESS;
3987 PVBOXWDDM_OVERLAY pOverlay = (PVBOXWDDM_OVERLAY)hOverlay;
3988 Assert(pOverlay);
3989 int rc = vboxVhwaHlpOverlayUpdate(pOverlay, &pUpdateOverlay->OverlayInfo);
3990 AssertRC(rc);
3991 if (RT_FAILURE(rc))
3992 Status = STATUS_UNSUCCESSFUL;
3993
3994 dfprintf(("<== "__FUNCTION__ ", hOverlay(0x%p)\n", hOverlay));
3995
3996 return Status;
3997}
3998
3999NTSTATUS
4000APIENTRY
4001DxgkDdiFlipOverlay(
4002 CONST HANDLE hOverlay,
4003 CONST DXGKARG_FLIPOVERLAY *pFlipOverlay)
4004{
4005 dfprintf(("==> "__FUNCTION__ ", hOverlay(0x%p)\n", hOverlay));
4006
4007 NTSTATUS Status = STATUS_SUCCESS;
4008 PVBOXWDDM_OVERLAY pOverlay = (PVBOXWDDM_OVERLAY)hOverlay;
4009 Assert(pOverlay);
4010 int rc = vboxVhwaHlpOverlayFlip(pOverlay, pFlipOverlay);
4011 AssertRC(rc);
4012 if (RT_FAILURE(rc))
4013 Status = STATUS_UNSUCCESSFUL;
4014
4015 dfprintf(("<== "__FUNCTION__ ", hOverlay(0x%p)\n", hOverlay));
4016
4017 return Status;
4018}
4019
4020NTSTATUS
4021APIENTRY
4022DxgkDdiDestroyOverlay(
4023 CONST HANDLE hOverlay)
4024{
4025 dfprintf(("==> "__FUNCTION__ ", hOverlay(0x%p)\n", hOverlay));
4026
4027 NTSTATUS Status = STATUS_SUCCESS;
4028 PVBOXWDDM_OVERLAY pOverlay = (PVBOXWDDM_OVERLAY)hOverlay;
4029 Assert(pOverlay);
4030 int rc = vboxVhwaHlpOverlayDestroy(pOverlay);
4031 AssertRC(rc);
4032 if (RT_SUCCESS(rc))
4033 vboxWddmMemFree(pOverlay);
4034 else
4035 Status = STATUS_UNSUCCESSFUL;
4036
4037 dfprintf(("<== "__FUNCTION__ ", hOverlay(0x%p)\n", hOverlay));
4038
4039 return Status;
4040}
4041
4042/**
4043 * DxgkDdiCreateContext
4044 */
4045NTSTATUS
4046APIENTRY
4047DxgkDdiCreateContext(
4048 CONST HANDLE hDevice,
4049 DXGKARG_CREATECONTEXT *pCreateContext)
4050{
4051 /* DxgkDdiCreateContext should be made pageable */
4052 PAGED_CODE();
4053
4054 dfprintf(("==> "__FUNCTION__ ", hDevice(0x%x)\n", hDevice));
4055
4056 vboxVDbgBreakFv();
4057
4058 NTSTATUS Status = STATUS_SUCCESS;
4059 PVBOXWDDM_DEVICE pDevice = (PVBOXWDDM_DEVICE)hDevice;
4060 PDEVICE_EXTENSION pDevExt = pDevice->pAdapter;
4061 PVBOXWDDM_CONTEXT pContext = (PVBOXWDDM_CONTEXT)vboxWddmMemAllocZero(sizeof (VBOXWDDM_CONTEXT));
4062 Assert(pContext);
4063 if (pContext)
4064 {
4065 InitializeListHead(&pContext->ListEntry);
4066 pContext->pDevice = pDevice;
4067 pContext->hContext = pCreateContext->hContext;
4068 pContext->EngineAffinity = pCreateContext->EngineAffinity;
4069 pContext->NodeOrdinal = pCreateContext->NodeOrdinal;
4070 vboxVideoCmCtxInitEmpty(&pContext->CmContext);
4071 if (pCreateContext->Flags.SystemContext || pCreateContext->PrivateDriverDataSize == 0)
4072 {
4073 Assert(pCreateContext->PrivateDriverDataSize == 0);
4074 Assert(!pCreateContext->pPrivateDriverData);
4075 Assert(pCreateContext->Flags.Value == 1 || pCreateContext->Flags.Value == 0);
4076 pContext->enmType = VBOXWDDM_CONTEXT_TYPE_SYSTEM;
4077 }
4078 else
4079 {
4080 Assert(pCreateContext->Flags.Value == 0);
4081 Assert(pCreateContext->PrivateDriverDataSize == sizeof (VBOXWDDM_CREATECONTEXT_INFO));
4082 Assert(pCreateContext->pPrivateDriverData);
4083 if (pCreateContext->PrivateDriverDataSize == sizeof (VBOXWDDM_CREATECONTEXT_INFO))
4084 {
4085 PVBOXWDDM_CREATECONTEXT_INFO pInfo = (PVBOXWDDM_CREATECONTEXT_INFO)pCreateContext->pPrivateDriverData;
4086 if (pInfo->u32IsD3D)
4087 {
4088 pContext->enmType = VBOXWDDM_CONTEXT_TYPE_CUSTOM_3D;
4089 Status = vboxVideoCmCtxAdd(&pDevice->pAdapter->CmMgr, &pContext->CmContext, (HANDLE)pInfo->hUmEvent, pInfo->u64UmInfo);
4090 Assert(Status == STATUS_SUCCESS);
4091 if (Status == STATUS_SUCCESS)
4092 {
4093 Assert(KeGetCurrentIrql() < DISPATCH_LEVEL);
4094 ExAcquireFastMutex(&pDevExt->ContextMutex);
4095 InsertHeadList(&pDevExt->ContextList3D, &pContext->ListEntry);
4096 ASMAtomicIncU32(&pDevExt->cContexts3D);
4097 ExReleaseFastMutex(&pDevExt->ContextMutex);
4098 }
4099 }
4100 else
4101 {
4102 pContext->enmType = VBOXWDDM_CONTEXT_TYPE_CUSTOM_2D;
4103 }
4104 }
4105 }
4106
4107 if (Status == STATUS_SUCCESS)
4108 {
4109 pCreateContext->hContext = pContext;
4110 pCreateContext->ContextInfo.DmaBufferSize = VBOXWDDM_C_DMA_BUFFER_SIZE;
4111 pCreateContext->ContextInfo.DmaBufferSegmentSet = 0;
4112 pCreateContext->ContextInfo.DmaBufferPrivateDataSize = VBOXWDDM_C_DMA_PRIVATEDATA_SIZE;
4113 pCreateContext->ContextInfo.AllocationListSize = VBOXWDDM_C_ALLOC_LIST_SIZE;
4114 pCreateContext->ContextInfo.PatchLocationListSize = VBOXWDDM_C_PATH_LOCATION_LIST_SIZE;
4115 //#if (DXGKDDI_INTERFACE_VERSION >= DXGKDDI_INTERFACE_VERSION_WIN7)
4116 //# error port to Win7 DDI
4117 // //pCreateContext->ContextInfo.DmaBufferAllocationGroup = ???;
4118 //#endif // DXGKDDI_INTERFACE_VERSION
4119 }
4120 else
4121 vboxWddmMemFree(pContext);
4122 }
4123 else
4124 Status = STATUS_NO_MEMORY;
4125
4126 dfprintf(("<== "__FUNCTION__ ", hDevice(0x%x)\n", hDevice));
4127
4128 return Status;
4129}
4130
4131NTSTATUS
4132APIENTRY
4133DxgkDdiDestroyContext(
4134 CONST HANDLE hContext)
4135{
4136 dfprintf(("==> "__FUNCTION__ ", hContext(0x%x)\n", hContext));
4137 vboxVDbgBreakFv();
4138 PVBOXWDDM_CONTEXT pContext = (PVBOXWDDM_CONTEXT)hContext;
4139 PDEVICE_EXTENSION pDevExt = pContext->pDevice->pAdapter;
4140 if (pContext->enmType == VBOXWDDM_CONTEXT_TYPE_CUSTOM_3D)
4141 {
4142 Assert(KeGetCurrentIrql() < DISPATCH_LEVEL);
4143 ExAcquireFastMutex(&pDevExt->ContextMutex);
4144 RemoveEntryList(&pContext->ListEntry);
4145 uint32_t cContexts = ASMAtomicDecU32(&pDevExt->cContexts3D);
4146 ExReleaseFastMutex(&pDevExt->ContextMutex);
4147 Assert(cContexts < UINT32_MAX/2);
4148 }
4149
4150 NTSTATUS Status = vboxVideoCmCtxRemove(&pContext->pDevice->pAdapter->CmMgr, &pContext->CmContext);
4151 Assert(Status == STATUS_SUCCESS);
4152 if (Status == STATUS_SUCCESS)
4153 vboxWddmMemFree(pContext);
4154
4155 dfprintf(("<== "__FUNCTION__ ", hContext(0x%x)\n", hContext));
4156
4157 return Status;
4158}
4159
4160NTSTATUS
4161APIENTRY
4162DxgkDdiLinkDevice(
4163 __in CONST PDEVICE_OBJECT PhysicalDeviceObject,
4164 __in CONST PVOID MiniportDeviceContext,
4165 __inout PLINKED_DEVICE LinkedDevice
4166 )
4167{
4168 drprintf(("==> "__FUNCTION__ ", MiniportDeviceContext(0x%x)\n", MiniportDeviceContext));
4169 vboxVDbgBreakFv();
4170 AssertBreakpoint();
4171 drprintf(("<== "__FUNCTION__ ", MiniportDeviceContext(0x%x)\n", MiniportDeviceContext));
4172 return STATUS_NOT_IMPLEMENTED;
4173}
4174
4175NTSTATUS
4176APIENTRY
4177DxgkDdiSetDisplayPrivateDriverFormat(
4178 CONST HANDLE hAdapter,
4179 /*CONST*/ DXGKARG_SETDISPLAYPRIVATEDRIVERFORMAT* pSetDisplayPrivateDriverFormat
4180 )
4181{
4182 dfprintf(("==> "__FUNCTION__ ", hAdapter(0x%x)\n", hAdapter));
4183 vboxVDbgBreakFv();
4184 AssertBreakpoint();
4185 dfprintf(("<== "__FUNCTION__ ", hAdapter(0x%x)\n", hAdapter));
4186 return STATUS_SUCCESS;
4187}
4188
4189NTSTATUS APIENTRY CALLBACK DxgkDdiRestartFromTimeout(IN_CONST_HANDLE hAdapter)
4190{
4191 dfprintf(("==> "__FUNCTION__ ", hAdapter(0x%x)\n", hAdapter));
4192 vboxVDbgBreakFv();
4193 AssertBreakpoint();
4194 dfprintf(("<== "__FUNCTION__ ", hAdapter(0x%x)\n", hAdapter));
4195 return STATUS_SUCCESS;
4196}
4197
4198NTSTATUS
4199DriverEntry(
4200 IN PDRIVER_OBJECT DriverObject,
4201 IN PUNICODE_STRING RegistryPath
4202 )
4203{
4204 PAGED_CODE();
4205
4206 vboxVDbgBreakFv();
4207
4208 drprintf(("VBoxVideoWddm::DriverEntry. Built %s %s\n", __DATE__, __TIME__));
4209
4210 DRIVER_INITIALIZATION_DATA DriverInitializationData = {'\0'};
4211
4212 if (! ARGUMENT_PRESENT(DriverObject) ||
4213 ! ARGUMENT_PRESENT(RegistryPath))
4214 {
4215 return STATUS_INVALID_PARAMETER;
4216 }
4217
4218 // Fill in the DriverInitializationData structure and call DxgkInitialize()
4219 DriverInitializationData.Version = DXGKDDI_INTERFACE_VERSION;
4220
4221 DriverInitializationData.DxgkDdiAddDevice = DxgkDdiAddDevice;
4222 DriverInitializationData.DxgkDdiStartDevice = DxgkDdiStartDevice;
4223 DriverInitializationData.DxgkDdiStopDevice = DxgkDdiStopDevice;
4224 DriverInitializationData.DxgkDdiRemoveDevice = DxgkDdiRemoveDevice;
4225 DriverInitializationData.DxgkDdiDispatchIoRequest = DxgkDdiDispatchIoRequest;
4226 DriverInitializationData.DxgkDdiInterruptRoutine = DxgkDdiInterruptRoutine;
4227 DriverInitializationData.DxgkDdiDpcRoutine = DxgkDdiDpcRoutine;
4228 DriverInitializationData.DxgkDdiQueryChildRelations = DxgkDdiQueryChildRelations;
4229 DriverInitializationData.DxgkDdiQueryChildStatus = DxgkDdiQueryChildStatus;
4230 DriverInitializationData.DxgkDdiQueryDeviceDescriptor = DxgkDdiQueryDeviceDescriptor;
4231 DriverInitializationData.DxgkDdiSetPowerState = DxgkDdiSetPowerState;
4232 DriverInitializationData.DxgkDdiNotifyAcpiEvent = DxgkDdiNotifyAcpiEvent;
4233 DriverInitializationData.DxgkDdiResetDevice = DxgkDdiResetDevice;
4234 DriverInitializationData.DxgkDdiUnload = DxgkDdiUnload;
4235 DriverInitializationData.DxgkDdiQueryInterface = DxgkDdiQueryInterface;
4236 DriverInitializationData.DxgkDdiControlEtwLogging = DxgkDdiControlEtwLogging;
4237
4238 DriverInitializationData.DxgkDdiQueryAdapterInfo = DxgkDdiQueryAdapterInfo;
4239 DriverInitializationData.DxgkDdiCreateDevice = DxgkDdiCreateDevice;
4240 DriverInitializationData.DxgkDdiCreateAllocation = DxgkDdiCreateAllocation;
4241 DriverInitializationData.DxgkDdiDestroyAllocation = DxgkDdiDestroyAllocation;
4242 DriverInitializationData.DxgkDdiDescribeAllocation = DxgkDdiDescribeAllocation;
4243 DriverInitializationData.DxgkDdiGetStandardAllocationDriverData = DxgkDdiGetStandardAllocationDriverData;
4244 DriverInitializationData.DxgkDdiAcquireSwizzlingRange = DxgkDdiAcquireSwizzlingRange;
4245 DriverInitializationData.DxgkDdiReleaseSwizzlingRange = DxgkDdiReleaseSwizzlingRange;
4246 DriverInitializationData.DxgkDdiPatch = DxgkDdiPatch;
4247 DriverInitializationData.DxgkDdiSubmitCommand = DxgkDdiSubmitCommand;
4248 DriverInitializationData.DxgkDdiPreemptCommand = DxgkDdiPreemptCommand;
4249 DriverInitializationData.DxgkDdiBuildPagingBuffer = DxgkDdiBuildPagingBuffer;
4250 DriverInitializationData.DxgkDdiSetPalette = DxgkDdiSetPalette;
4251 DriverInitializationData.DxgkDdiSetPointerPosition = DxgkDdiSetPointerPosition;
4252 DriverInitializationData.DxgkDdiSetPointerShape = DxgkDdiSetPointerShape;
4253 DriverInitializationData.DxgkDdiResetFromTimeout = DxgkDdiResetFromTimeout;
4254 DriverInitializationData.DxgkDdiRestartFromTimeout = DxgkDdiRestartFromTimeout;
4255 DriverInitializationData.DxgkDdiEscape = DxgkDdiEscape;
4256 DriverInitializationData.DxgkDdiCollectDbgInfo = DxgkDdiCollectDbgInfo;
4257 DriverInitializationData.DxgkDdiQueryCurrentFence = DxgkDdiQueryCurrentFence;
4258 DriverInitializationData.DxgkDdiIsSupportedVidPn = DxgkDdiIsSupportedVidPn;
4259 DriverInitializationData.DxgkDdiRecommendFunctionalVidPn = DxgkDdiRecommendFunctionalVidPn;
4260 DriverInitializationData.DxgkDdiEnumVidPnCofuncModality = DxgkDdiEnumVidPnCofuncModality;
4261 DriverInitializationData.DxgkDdiSetVidPnSourceAddress = DxgkDdiSetVidPnSourceAddress;
4262 DriverInitializationData.DxgkDdiSetVidPnSourceVisibility = DxgkDdiSetVidPnSourceVisibility;
4263 DriverInitializationData.DxgkDdiCommitVidPn = DxgkDdiCommitVidPn;
4264 DriverInitializationData.DxgkDdiUpdateActiveVidPnPresentPath = DxgkDdiUpdateActiveVidPnPresentPath;
4265 DriverInitializationData.DxgkDdiRecommendMonitorModes = DxgkDdiRecommendMonitorModes;
4266 DriverInitializationData.DxgkDdiRecommendVidPnTopology = DxgkDdiRecommendVidPnTopology;
4267 DriverInitializationData.DxgkDdiGetScanLine = DxgkDdiGetScanLine;
4268 DriverInitializationData.DxgkDdiStopCapture = DxgkDdiStopCapture;
4269 DriverInitializationData.DxgkDdiControlInterrupt = DxgkDdiControlInterrupt;
4270 DriverInitializationData.DxgkDdiCreateOverlay = DxgkDdiCreateOverlay;
4271
4272 DriverInitializationData.DxgkDdiDestroyDevice = DxgkDdiDestroyDevice;
4273 DriverInitializationData.DxgkDdiOpenAllocation = DxgkDdiOpenAllocation;
4274 DriverInitializationData.DxgkDdiCloseAllocation = DxgkDdiCloseAllocation;
4275 DriverInitializationData.DxgkDdiRender = DxgkDdiRender;
4276 DriverInitializationData.DxgkDdiPresent = DxgkDdiPresent;
4277
4278 DriverInitializationData.DxgkDdiUpdateOverlay = DxgkDdiUpdateOverlay;
4279 DriverInitializationData.DxgkDdiFlipOverlay = DxgkDdiFlipOverlay;
4280 DriverInitializationData.DxgkDdiDestroyOverlay = DxgkDdiDestroyOverlay;
4281
4282 DriverInitializationData.DxgkDdiCreateContext = DxgkDdiCreateContext;
4283 DriverInitializationData.DxgkDdiDestroyContext = DxgkDdiDestroyContext;
4284
4285 DriverInitializationData.DxgkDdiLinkDevice = NULL; //DxgkDdiLinkDevice;
4286 DriverInitializationData.DxgkDdiSetDisplayPrivateDriverFormat = DxgkDdiSetDisplayPrivateDriverFormat;
4287//#if (DXGKDDI_INTERFACE_VERSION >= DXGKDDI_INTERFACE_VERSION_WIN7)
4288//# error port to Win7 DDI
4289// DriverInitializationData.DxgkDdiRenderKm = DxgkDdiRenderKm;
4290// DriverInitializationData.DxgkDdiRestartFromTimeout = DxgkDdiRestartFromTimeout;
4291// DriverInitializationData.DxgkDdiSetVidPnSourceVisibility = DxgkDdiSetVidPnSourceVisibility;
4292// DriverInitializationData.DxgkDdiUpdateActiveVidPnPresentPath = DxgkDdiUpdateActiveVidPnPresentPath;
4293// DriverInitializationData.DxgkDdiQueryVidPnHWCapability = DxgkDdiQueryVidPnHWCapability;
4294//#endif
4295
4296 return DxgkInitialize(DriverObject,
4297 RegistryPath,
4298 &DriverInitializationData);
4299}
Note: See TracBrowser for help on using the repository browser.

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