VirtualBox

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

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

wddm/3d: issue render cmd on flush for shared resources to notify d3d runtime about surf contents change (not completed)

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

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