VirtualBox

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

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

wddm: 1. guest installler integration (uninstall needs additional fixing), 2. dev/vga saved state fixes, 3. better split video dma and wddm 4. separate wddm wine libs, 5. etc.

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