VirtualBox

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

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

wddm/3d: disable verbose logging

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

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