VirtualBox

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

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

wddm/3d: 1st 3d app working under Aero! shared textures working

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