VirtualBox

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

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

wddm/3d: more debugging

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

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