VirtualBox

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

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

wddm/2d: kernel(miniport) part impl

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

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