VirtualBox

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

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

wddm/3d: more impl

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