VirtualBox

source: vbox/trunk/src/VBox/Additions/WINNT/Graphics/Video/mp/wddm/VBoxMPWddm.cpp@ 46662

Last change on this file since 46662 was 46662, checked in by vboxsync, 12 years ago

wddm/3d/wine: set host id impl

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 268.3 KB
Line 
1/* $Id: VBoxMPWddm.cpp 46662 2013-06-19 14:22:29Z vboxsync $ */
2/** @file
3 * VBox WDDM Miniport driver
4 */
5
6/*
7 * Copyright (C) 2011-2013 Oracle Corporation
8 *
9 * This file is part of VirtualBox Open Source Edition (OSE), as
10 * available from http://www.virtualbox.org. This file is free software;
11 * you can redistribute it and/or modify it under the terms of the GNU
12 * General Public License (GPL) as published by the Free Software
13 * Foundation, in version 2 as it comes in the "COPYING" file of the
14 * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
15 * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
16 */
17
18#include "VBoxMPWddm.h"
19#include "common/VBoxMPCommon.h"
20#include "common/VBoxMPHGSMI.h"
21#include "VBoxMPVhwa.h"
22#include "VBoxMPVidPn.h"
23
24#include <iprt/asm.h>
25//#include <iprt/initterm.h>
26
27#include <VBox/VBoxGuestLib.h>
28#include <VBox/VBoxVideo.h>
29#include <wingdi.h> /* needed for RGNDATA definition */
30#include <VBoxDisplay.h> /* this is from Additions/WINNT/include/ to include escape codes */
31#include <VBox/Hardware/VBoxVideoVBE.h>
32
33DWORD g_VBoxLogUm = 0;
34#ifdef VBOX_WDDM_WIN8
35DWORD g_VBoxDisplayOnly = 0;
36#endif
37
38#define VBOXWDDM_MEMTAG 'MDBV'
39PVOID vboxWddmMemAlloc(IN SIZE_T cbSize)
40{
41 return ExAllocatePoolWithTag(NonPagedPool, cbSize, VBOXWDDM_MEMTAG);
42}
43
44PVOID vboxWddmMemAllocZero(IN SIZE_T cbSize)
45{
46 PVOID pvMem = vboxWddmMemAlloc(cbSize);
47 memset(pvMem, 0, cbSize);
48 return pvMem;
49}
50
51
52VOID vboxWddmMemFree(PVOID pvMem)
53{
54 ExFreePool(pvMem);
55}
56
57DECLINLINE(void) VBoxWddmOaRelease(PVBOXWDDM_OPENALLOCATION pOa)
58{
59 PVBOXWDDM_ALLOCATION pAllocation = pOa->pAllocation;
60 KIRQL OldIrql;
61 KeAcquireSpinLock(&pAllocation->OpenLock, &OldIrql);
62 Assert(pAllocation->cOpens);
63 --pAllocation->cOpens;
64 uint32_t cOpens = --pOa->cOpens;
65 Assert(cOpens < UINT32_MAX/2);
66 if (!cOpens)
67 {
68 RemoveEntryList(&pOa->ListEntry);
69 KeReleaseSpinLock(&pAllocation->OpenLock, OldIrql);
70 vboxWddmMemFree(pOa);
71 }
72 else
73 KeReleaseSpinLock(&pAllocation->OpenLock, OldIrql);
74}
75
76DECLINLINE(PVBOXWDDM_OPENALLOCATION) VBoxWddmOaSearchLocked(PVBOXWDDM_DEVICE pDevice, PVBOXWDDM_ALLOCATION pAllocation)
77{
78 for (PLIST_ENTRY pCur = pAllocation->OpenList.Flink; pCur != &pAllocation->OpenList; pCur = pCur->Flink)
79 {
80 PVBOXWDDM_OPENALLOCATION pCurOa = CONTAINING_RECORD(pCur, VBOXWDDM_OPENALLOCATION, ListEntry);
81 if (pCurOa->pDevice == pDevice)
82 {
83 return pCurOa;
84 }
85 }
86 return NULL;
87}
88
89DECLINLINE(PVBOXWDDM_OPENALLOCATION) VBoxWddmOaSearch(PVBOXWDDM_DEVICE pDevice, PVBOXWDDM_ALLOCATION pAllocation)
90{
91 PVBOXWDDM_OPENALLOCATION pOa;
92 KIRQL OldIrql;
93 KeAcquireSpinLock(&pAllocation->OpenLock, &OldIrql);
94 pOa = VBoxWddmOaSearchLocked(pDevice, pAllocation);
95 KeReleaseSpinLock(&pAllocation->OpenLock, OldIrql);
96 return pOa;
97}
98
99DECLINLINE(PVBOXWDDM_ALLOCATION) vboxWddmGetAllocationFromHandle(PVBOXMP_DEVEXT pDevExt, D3DKMT_HANDLE hAllocation)
100{
101 DXGKARGCB_GETHANDLEDATA GhData;
102 GhData.hObject = hAllocation;
103 GhData.Type = DXGK_HANDLE_ALLOCATION;
104 GhData.Flags.Value = 0;
105 return (PVBOXWDDM_ALLOCATION)pDevExt->u.primary.DxgkInterface.DxgkCbGetHandleData(&GhData);
106}
107
108DECLINLINE(PVBOXWDDM_ALLOCATION) vboxWddmGetAllocationFromAllocList(PVBOXMP_DEVEXT pDevExt, DXGK_ALLOCATIONLIST *pAllocList)
109{
110 PVBOXWDDM_OPENALLOCATION pOa = (PVBOXWDDM_OPENALLOCATION)pAllocList->hDeviceSpecificAllocation;
111 return pOa->pAllocation;
112}
113
114static void vboxWddmPopulateDmaAllocInfo(PVBOXWDDM_DMA_ALLOCINFO pInfo, PVBOXWDDM_ALLOCATION pAlloc, DXGK_ALLOCATIONLIST *pDmaAlloc)
115{
116 pInfo->pAlloc = pAlloc;
117 if (pDmaAlloc->SegmentId)
118 {
119 pInfo->offAlloc = (VBOXVIDEOOFFSET)pDmaAlloc->PhysicalAddress.QuadPart;
120 pInfo->segmentIdAlloc = pDmaAlloc->SegmentId;
121 }
122 else
123 pInfo->segmentIdAlloc = 0;
124 pInfo->srcId = pAlloc->AllocData.SurfDesc.VidPnSourceId;
125}
126
127static void vboxWddmPopulateDmaAllocInfoWithOffset(PVBOXWDDM_DMA_ALLOCINFO pInfo, PVBOXWDDM_ALLOCATION pAlloc, DXGK_ALLOCATIONLIST *pDmaAlloc, uint32_t offStart)
128{
129 pInfo->pAlloc = pAlloc;
130 if (pDmaAlloc->SegmentId)
131 {
132 pInfo->offAlloc = (VBOXVIDEOOFFSET)pDmaAlloc->PhysicalAddress.QuadPart + offStart;
133 pInfo->segmentIdAlloc = pDmaAlloc->SegmentId;
134 }
135 else
136 pInfo->segmentIdAlloc = 0;
137 pInfo->srcId = pAlloc->AllocData.SurfDesc.VidPnSourceId;
138}
139
140NTSTATUS vboxWddmGhDisplayPostInfoScreenBySDesc (PVBOXMP_DEVEXT pDevExt, const VBOXWDDM_SURFACE_DESC *pDesc, const POINT * pVScreenPos, uint16_t fFlags)
141{
142 void *p = VBoxHGSMIBufferAlloc (&VBoxCommonFromDeviceExt(pDevExt)->guestCtx,
143 sizeof (VBVAINFOSCREEN),
144 HGSMI_CH_VBVA,
145 VBVA_INFO_SCREEN);
146 Assert(p);
147 if (p)
148 {
149 VBVAINFOSCREEN *pScreen = (VBVAINFOSCREEN *)p;
150
151 pScreen->u32ViewIndex = pDesc->VidPnSourceId;
152 pScreen->i32OriginX = pVScreenPos->x;
153 pScreen->i32OriginY = pVScreenPos->y;
154 pScreen->u32StartOffset = 0; //(uint32_t)offVram; /* we pretend the view is located at the start of each framebuffer */
155 pScreen->u32LineSize = pDesc->pitch;
156 pScreen->u32Width = pDesc->width;
157 pScreen->u32Height = pDesc->height;
158 pScreen->u16BitsPerPixel = (uint16_t)pDesc->bpp;
159 pScreen->u16Flags = fFlags;
160
161 VBoxHGSMIBufferSubmit (&VBoxCommonFromDeviceExt(pDevExt)->guestCtx, p);
162
163 VBoxHGSMIBufferFree (&VBoxCommonFromDeviceExt(pDevExt)->guestCtx, p);
164 }
165
166 return STATUS_SUCCESS;
167
168}
169
170NTSTATUS vboxWddmGhDisplayPostInfoScreen(PVBOXMP_DEVEXT pDevExt, const VBOXWDDM_ALLOC_DATA *pAllocData, const POINT * pVScreenPos)
171{
172 NTSTATUS Status = vboxWddmGhDisplayPostInfoScreenBySDesc(pDevExt, &pAllocData->SurfDesc, pVScreenPos, VBVA_SCREEN_F_ACTIVE);
173 if (!NT_SUCCESS(Status))
174 WARN(("vboxWddmGhDisplayPostInfoScreenBySDesc failed Status 0x%x", Status));
175 return Status;
176}
177
178NTSTATUS vboxWddmGhDisplayHideScreen(PVBOXMP_DEVEXT pDevExt, D3DDDI_VIDEO_PRESENT_TARGET_ID VidPnTargetId)
179{
180 VBOXWDDM_SURFACE_DESC SurfDesc = {0};
181 POINT VScreenPos = {0};
182 SurfDesc.VidPnSourceId = VidPnTargetId;
183 NTSTATUS Status = vboxWddmGhDisplayPostInfoScreenBySDesc(pDevExt, &SurfDesc, &VScreenPos, VBVA_SCREEN_F_ACTIVE | VBVA_SCREEN_F_DISABLED);
184 if (!NT_SUCCESS(Status))
185 WARN(("vboxWddmGhDisplayPostInfoScreenBySDesc failed Status 0x%x", Status));
186 return Status;
187}
188
189NTSTATUS vboxWddmGhDisplayPostInfoView(PVBOXMP_DEVEXT pDevExt, const VBOXWDDM_ALLOC_DATA *pAllocData)
190{
191 VBOXVIDEOOFFSET offVram = pAllocData->Addr.offVram;
192 if (offVram == VBOXVIDEOOFFSET_VOID)
193 {
194 WARN(("offVram == VBOXVIDEOOFFSET_VOID"));
195 return STATUS_INVALID_PARAMETER;
196 }
197
198 /* Issue the screen info command. */
199 void *p = VBoxHGSMIBufferAlloc (&VBoxCommonFromDeviceExt(pDevExt)->guestCtx,
200 sizeof (VBVAINFOVIEW),
201 HGSMI_CH_VBVA,
202 VBVA_INFO_VIEW);
203 Assert(p);
204 if (p)
205 {
206 VBVAINFOVIEW *pView = (VBVAINFOVIEW *)p;
207
208 pView->u32ViewIndex = pAllocData->SurfDesc.VidPnSourceId;
209 pView->u32ViewOffset = (uint32_t)offVram; /* we pretend the view is located at the start of each framebuffer */
210 pView->u32ViewSize = vboxWddmVramCpuVisibleSegmentSize(pDevExt)/VBoxCommonFromDeviceExt(pDevExt)->cDisplays;
211
212 pView->u32MaxScreenSize = pView->u32ViewSize;
213
214 VBoxHGSMIBufferSubmit (&VBoxCommonFromDeviceExt(pDevExt)->guestCtx, p);
215
216 VBoxHGSMIBufferFree (&VBoxCommonFromDeviceExt(pDevExt)->guestCtx, p);
217 }
218
219 return STATUS_SUCCESS;
220}
221
222NTSTATUS vboxWddmGhDisplaySetMode(PVBOXMP_DEVEXT pDevExt, const VBOXWDDM_ALLOC_DATA *pAllocData)
223{
224// PVBOXWDDM_ALLOCATION_SHAREDPRIMARYSURFACE pPrimaryInfo = VBOXWDDM_ALLOCATION_BODY(pAllocation, VBOXWDDM_ALLOCATION_SHAREDPRIMARYSURFACE);
225 if (/*pPrimaryInfo->*/pAllocData->SurfDesc.VidPnSourceId)
226 return STATUS_SUCCESS;
227
228 if (pAllocData->Addr.offVram == VBOXVIDEOOFFSET_VOID)
229 {
230 WARN(("pAllocData->Addr.offVram == VBOXVIDEOOFFSET_VOID"));
231 return STATUS_UNSUCCESSFUL;
232 }
233
234 USHORT width = pAllocData->SurfDesc.width;
235 USHORT height = pAllocData->SurfDesc.height;
236 USHORT bpp = pAllocData->SurfDesc.bpp;
237 ULONG cbLine = VBOXWDDM_ROUNDBOUND(((width * bpp) + 7) / 8, 4);
238 ULONG yOffset = (ULONG)pAllocData->Addr.offVram / cbLine;
239 ULONG xOffset = (ULONG)pAllocData->Addr.offVram % cbLine;
240
241 if (bpp == 4)
242 {
243 xOffset <<= 1;
244 }
245 else
246 {
247 Assert(!(xOffset%((bpp + 7) >> 3)));
248 xOffset /= ((bpp + 7) >> 3);
249 }
250 Assert(xOffset <= 0xffff);
251 Assert(yOffset <= 0xffff);
252
253 VBoxVideoSetModeRegisters(width, height, width, bpp, 0, (uint16_t)xOffset, (uint16_t)yOffset);
254 /*@todo read back from port to check if mode switch was successful */
255
256 return STATUS_SUCCESS;
257}
258
259NTSTATUS vboxWddmGhDisplayUpdateScreenPos(PVBOXMP_DEVEXT pDevExt, PVBOXWDDM_SOURCE pSource, const POINT *pVScreenPos)
260{
261 if (pSource->VScreenPos.x == pVScreenPos->x
262 && pSource->VScreenPos.y == pVScreenPos->y)
263 return STATUS_SUCCESS;
264
265 pSource->VScreenPos = *pVScreenPos;
266
267 NTSTATUS Status = vboxWddmGhDisplayPostInfoScreen(pDevExt, &pSource->AllocData, &pSource->VScreenPos);
268 Assert(Status == STATUS_SUCCESS);
269 return Status;
270}
271
272NTSTATUS vboxWddmGhDisplaySetInfo(PVBOXMP_DEVEXT pDevExt, const VBOXWDDM_ALLOC_DATA *pAllocData, const POINT * pVScreenPos)
273{
274 NTSTATUS Status = vboxWddmGhDisplaySetMode(pDevExt, pAllocData);
275 Assert(Status == STATUS_SUCCESS);
276 if (Status == STATUS_SUCCESS)
277 {
278 Status = vboxWddmGhDisplayPostInfoView(pDevExt, pAllocData);
279 Assert(Status == STATUS_SUCCESS);
280 if (Status == STATUS_SUCCESS)
281 {
282 Status = vboxWddmGhDisplayPostInfoScreen(pDevExt, pAllocData, pVScreenPos);
283 Assert(Status == STATUS_SUCCESS);
284 if (!NT_SUCCESS(Status))
285 WARN(("vboxWddmGhDisplayPostInfoScreen failed"));
286 }
287 else
288 WARN(("vboxWddmGhDisplayPostInfoView failed"));
289 }
290 else
291 WARN(("vboxWddmGhDisplaySetMode failed"));
292
293 return Status;
294}
295
296bool vboxWddmGhDisplayCheckSetInfoFromSource(PVBOXMP_DEVEXT pDevExt, PVBOXWDDM_SOURCE pSource)
297{
298// Assert(VBOXVIDEOOFFSET_VOID != pSource->AllocData.Addr.offVram);
299
300 if (pSource->fGhSynced)
301 return false;
302
303 char fGhSynced = 1;
304 PVBOXWDDM_ALLOCATION pFbAlloc = VBOXWDDM_FB_ALLOCATION(pDevExt, pSource);
305#ifdef VBOXWDDM_RENDER_FROM_SHADOW
306# ifdef VBOX_WDDM_WIN8
307 if (!g_VBoxDisplayOnly)
308# endif
309 {
310 if (!pFbAlloc)
311 {
312 pFbAlloc = VBOXWDDM_NONFB_ALLOCATION(pDevExt, pSource);
313 fGhSynced = -1;
314 }
315
316 if (!pFbAlloc || pFbAlloc->AllocData.Addr.offVram == VBOXVIDEOOFFSET_VOID)
317 {
318 return false;
319 }
320 }
321#endif
322
323#ifdef VBOX_WDDM_WIN8
324 Assert(!g_VBoxDisplayOnly == !!pFbAlloc);
325#else
326 Assert(pFbAlloc);
327#endif
328#ifndef VBOXWDDM_RENDER_FROM_SHADOW
329 Assert(!pFbAlloc || pFbAlloc->AllocData.Addr.offVram == pSource->AllocData.Addr.offVram);
330#endif
331 Assert(!pFbAlloc || pFbAlloc->AllocData.Addr.SegmentId == pSource->AllocData.Addr.SegmentId);
332
333 NTSTATUS Status = vboxWddmGhDisplaySetInfo(pDevExt, pFbAlloc ? &pFbAlloc->AllocData : &pSource->AllocData, &pSource->VScreenPos);
334 if (NT_SUCCESS(Status))
335 pSource->fGhSynced = fGhSynced;
336 else
337 WARN(("vboxWddmGhDisplaySetInfo failed, Status (0x%x)", Status));
338
339 return true;
340}
341
342static VOID vboxWddmModeRenderFromShadowDisableOnSubmitCommand(PVBOXMP_DEVEXT pDevExt, BOOLEAN fDisable)
343{
344 for (int i = 0; i < VBoxCommonFromDeviceExt(pDevExt)->cDisplays; ++i)
345 {
346 PVBOXWDDM_SOURCE pSource = &pDevExt->aSources[i];
347 PVBOXWDDM_ALLOCATION pFromAllocation;
348 PVBOXWDDM_ALLOCATION pToAllocation;
349 if (fDisable)
350 {
351 pFromAllocation = pSource->pShadowAllocation;
352 pToAllocation = pSource->pPrimaryAllocation;
353 }
354 else
355 {
356 pToAllocation = pSource->pShadowAllocation;
357 pFromAllocation = pSource->pPrimaryAllocation;
358 }
359
360 Assert(pToAllocation->AllocData.Addr.offVram != VBOXVIDEOOFFSET_VOID);
361 Assert(pFromAllocation->AllocData.Addr.offVram != VBOXVIDEOOFFSET_VOID);
362 if (pToAllocation->AllocData.Addr.offVram != VBOXVIDEOOFFSET_VOID
363 && pFromAllocation->AllocData.Addr.offVram != VBOXVIDEOOFFSET_VOID)
364 {
365 RECT Rect;
366 Rect.left = 0;
367 Rect.top = 0;
368 Rect.right = pToAllocation->AllocData.SurfDesc.width;
369 Rect.bottom = pToAllocation->AllocData.SurfDesc.height;
370 vboxVdmaGgDmaBltPerform(pDevExt, &pFromAllocation->AllocData, &Rect,
371 &pToAllocation->AllocData, &Rect);
372 }
373
374 /* ensure we issue resize command on next update */
375 pSource->fGhSynced = 0;
376 }
377}
378
379static BOOLEAN vboxWddmModeRenderFromShadowCheckOnSubmitCommand(PVBOXMP_DEVEXT pDevExt, BOOLEAN *pbSwitched)
380{
381 BOOLEAN fDisabled, fNeedSwitch;
382 uint32_t cCount = ASMAtomicUoReadU32(&pDevExt->cRenderFromShadowDisabledContexts);
383
384 fDisabled = !!cCount;
385 fNeedSwitch = (!fDisabled != !pDevExt->fRenderToShadowDisabled);
386
387 if (fNeedSwitch)
388 {
389 vboxWddmModeRenderFromShadowDisableOnSubmitCommand(pDevExt, fDisabled);
390 pDevExt->fRenderToShadowDisabled = fDisabled;
391 }
392
393 if (pbSwitched)
394 *pbSwitched = fNeedSwitch;
395
396 return fDisabled;
397}
398
399
400static VOID vboxWddmModeRenderFromShadowDisableRegister(PVBOXMP_DEVEXT pDevExt, VBOXWDDM_CONTEXT *pContext)
401{
402 if (pContext->fRenderFromShadowDisabled)
403 return;
404 ASMAtomicIncU32(&pDevExt->cRenderFromShadowDisabledContexts);
405 pContext->fRenderFromShadowDisabled = TRUE;
406}
407
408static VOID vboxWddmModeRenderFromShadowDisableUnregister(PVBOXMP_DEVEXT pDevExt, VBOXWDDM_CONTEXT *pContext)
409{
410 if (!pContext->fRenderFromShadowDisabled)
411 return;
412
413 uint32_t cCount = ASMAtomicDecU32(&pDevExt->cRenderFromShadowDisabledContexts);
414 Assert(cCount < UINT32_MAX);
415 pContext->fRenderFromShadowDisabled = FALSE;
416}
417
418#ifdef VBOXWDDM_RENDER_FROM_SHADOW
419bool vboxWddmCheckUpdateFramebufferAddress(PVBOXMP_DEVEXT pDevExt, PVBOXWDDM_SOURCE pSource)
420{
421 if (pSource->pPrimaryAllocation->enmType == VBOXWDDM_ALLOC_TYPE_UMD_RC_GENERIC)
422 {
423// Assert(pSource->fGhSynced == FALSE);
424 return false;
425 }
426
427 return vboxWddmGhDisplayCheckSetInfoFromSource(pDevExt, pSource);
428}
429#endif
430
431PVBOXSHGSMI vboxWddmHgsmiGetHeapFromCmdOffset(PVBOXMP_DEVEXT pDevExt, HGSMIOFFSET offCmd)
432{
433#ifdef VBOX_WITH_VDMA
434 if(HGSMIAreaContainsOffset(&pDevExt->u.primary.Vdma.CmdHeap.Heap.area, offCmd))
435 return &pDevExt->u.primary.Vdma.CmdHeap;
436#endif
437 if (HGSMIAreaContainsOffset(&VBoxCommonFromDeviceExt(pDevExt)->guestCtx.heapCtx.Heap.area, offCmd))
438 return &VBoxCommonFromDeviceExt(pDevExt)->guestCtx.heapCtx;
439 return NULL;
440}
441
442typedef enum
443{
444 VBOXWDDM_HGSMICMD_TYPE_UNDEFINED = 0,
445 VBOXWDDM_HGSMICMD_TYPE_CTL = 1,
446#ifdef VBOX_WITH_VDMA
447 VBOXWDDM_HGSMICMD_TYPE_DMACMD = 2
448#endif
449} VBOXWDDM_HGSMICMD_TYPE;
450
451VBOXWDDM_HGSMICMD_TYPE vboxWddmHgsmiGetCmdTypeFromOffset(PVBOXMP_DEVEXT pDevExt, HGSMIOFFSET offCmd)
452{
453#ifdef VBOX_WITH_VDMA
454 if(HGSMIAreaContainsOffset(&pDevExt->u.primary.Vdma.CmdHeap.Heap.area, offCmd))
455 return VBOXWDDM_HGSMICMD_TYPE_DMACMD;
456#endif
457 if (HGSMIAreaContainsOffset(&VBoxCommonFromDeviceExt(pDevExt)->guestCtx.heapCtx.Heap.area, offCmd))
458 return VBOXWDDM_HGSMICMD_TYPE_CTL;
459 return VBOXWDDM_HGSMICMD_TYPE_UNDEFINED;
460}
461
462static NTSTATUS vboxWddmChildStatusReportPerform(PVBOXMP_DEVEXT pDevExt, PVBOXVDMA_CHILD_STATUS pChildStatus, D3DDDI_VIDEO_PRESENT_TARGET_ID iChild)
463{
464 DXGK_CHILD_STATUS DdiChildStatus;
465 if (pChildStatus->fFlags & VBOXVDMA_CHILD_STATUS_F_DISCONNECTED)
466 {
467 /* report disconnected */
468 memset(&DdiChildStatus, 0, sizeof (DdiChildStatus));
469 DdiChildStatus.Type = StatusConnection;
470 if (iChild != D3DDDI_ID_UNINITIALIZED)
471 {
472 Assert(iChild < UINT32_MAX/2);
473 Assert(iChild < (UINT)VBoxCommonFromDeviceExt(pDevExt)->cDisplays);
474 DdiChildStatus.ChildUid = iChild;
475 }
476 else
477 {
478 Assert(pChildStatus->iChild < UINT32_MAX/2);
479 Assert(pChildStatus->iChild < (UINT)VBoxCommonFromDeviceExt(pDevExt)->cDisplays);
480 DdiChildStatus.ChildUid = pChildStatus->iChild;
481 }
482 LOG(("Reporting DISCONNECT to child %d", DdiChildStatus.ChildUid));
483 DdiChildStatus.HotPlug.Connected = FALSE;
484 NTSTATUS Status = pDevExt->u.primary.DxgkInterface.DxgkCbIndicateChildStatus(pDevExt->u.primary.DxgkInterface.DeviceHandle, &DdiChildStatus);
485 if (!NT_SUCCESS(Status))
486 {
487 WARN(("DxgkCbIndicateChildStatus failed with Status (0x%x)", Status));
488 return Status;
489 }
490 }
491
492 if (pChildStatus->fFlags & VBOXVDMA_CHILD_STATUS_F_CONNECTED)
493 {
494 /* report disconnected */
495 memset(&DdiChildStatus, 0, sizeof (DdiChildStatus));
496 DdiChildStatus.Type = StatusConnection;
497 if (iChild != D3DDDI_ID_UNINITIALIZED)
498 {
499 Assert(iChild < UINT32_MAX/2);
500 Assert(iChild < (UINT)VBoxCommonFromDeviceExt(pDevExt)->cDisplays);
501 DdiChildStatus.ChildUid = iChild;
502 }
503 else
504 {
505 Assert(pChildStatus->iChild < UINT32_MAX/2);
506 Assert(pChildStatus->iChild < (UINT)VBoxCommonFromDeviceExt(pDevExt)->cDisplays);
507 DdiChildStatus.ChildUid = pChildStatus->iChild;
508 }
509 LOG(("Reporting CONNECT to child %d", DdiChildStatus.ChildUid));
510 DdiChildStatus.HotPlug.Connected = TRUE;
511 NTSTATUS Status = pDevExt->u.primary.DxgkInterface.DxgkCbIndicateChildStatus(pDevExt->u.primary.DxgkInterface.DeviceHandle, &DdiChildStatus);
512 if (!NT_SUCCESS(Status))
513 {
514 WARN(("DxgkCbIndicateChildStatus failed with Status (0x%x)", Status));
515 return Status;
516 }
517 }
518
519 if (pChildStatus->fFlags & VBOXVDMA_CHILD_STATUS_F_ROTATED)
520 {
521 /* report disconnected */
522 memset(&DdiChildStatus, 0, sizeof (DdiChildStatus));
523 DdiChildStatus.Type = StatusRotation;
524 if (iChild != D3DDDI_ID_UNINITIALIZED)
525 {
526 Assert(iChild < UINT32_MAX/2);
527 Assert(iChild < (UINT)VBoxCommonFromDeviceExt(pDevExt)->cDisplays);
528 DdiChildStatus.ChildUid = iChild;
529 }
530 else
531 {
532 Assert(pChildStatus->iChild < UINT32_MAX/2);
533 Assert(pChildStatus->iChild < (UINT)VBoxCommonFromDeviceExt(pDevExt)->cDisplays);
534 DdiChildStatus.ChildUid = pChildStatus->iChild;
535 }
536 LOG(("Reporting ROTATED to child %d", DdiChildStatus.ChildUid));
537 DdiChildStatus.Rotation.Angle = pChildStatus->u8RotationAngle;
538 NTSTATUS Status = pDevExt->u.primary.DxgkInterface.DxgkCbIndicateChildStatus(pDevExt->u.primary.DxgkInterface.DeviceHandle, &DdiChildStatus);
539 if (!NT_SUCCESS(Status))
540 {
541 WARN(("DxgkCbIndicateChildStatus failed with Status (0x%x)", Status));
542 return Status;
543 }
544 }
545
546 return STATUS_SUCCESS;
547}
548
549static NTSTATUS vboxWddmChildStatusDoReportReconnected(PVBOXMP_DEVEXT pDevExt, VBOXVDMACMD_CHILD_STATUS_IRQ *pBody)
550{
551 NTSTATUS Status = STATUS_SUCCESS;
552
553 for (UINT i = 0; i < pBody->cInfos; ++i)
554 {
555 PVBOXVDMA_CHILD_STATUS pInfo = &pBody->aInfos[i];
556 if (pBody->fFlags & VBOXVDMACMD_CHILD_STATUS_IRQ_F_APPLY_TO_ALL)
557 {
558 for (D3DDDI_VIDEO_PRESENT_TARGET_ID iChild = 0; iChild < (UINT)VBoxCommonFromDeviceExt(pDevExt)->cDisplays; ++iChild)
559 {
560 Status = vboxWddmChildStatusReportPerform(pDevExt, pInfo, iChild);
561 if (!NT_SUCCESS(Status))
562 {
563 WARN(("vboxWddmChildStatusReportPerform failed with Status (0x%x)", Status));
564 break;
565 }
566 }
567 }
568 else
569 {
570 Status = vboxWddmChildStatusReportPerform(pDevExt, pInfo, D3DDDI_ID_UNINITIALIZED);
571 if (!NT_SUCCESS(Status))
572 {
573 WARN(("vboxWddmChildStatusReportPerform failed with Status (0x%x)", Status));
574 break;
575 }
576 }
577 }
578
579 return Status;
580}
581
582typedef struct VBOXWDDMCHILDSTATUSCB
583{
584 PVBOXVDMACBUF_DR pDr;
585 PKEVENT pEvent;
586} VBOXWDDMCHILDSTATUSCB, *PVBOXWDDMCHILDSTATUSCB;
587
588static DECLCALLBACK(VOID) vboxWddmChildStatusReportCompletion(PVBOXMP_DEVEXT pDevExt, PVBOXVDMADDI_CMD pCmd, PVOID pvContext)
589{
590 /* we should be called from our DPC routine */
591 Assert(KeGetCurrentIrql() == DISPATCH_LEVEL);
592
593 PVBOXWDDMCHILDSTATUSCB pCtx = (PVBOXWDDMCHILDSTATUSCB)pvContext;
594 PVBOXVDMACBUF_DR pDr = pCtx->pDr;
595 PVBOXVDMACMD pHdr = VBOXVDMACBUF_DR_TAIL(pDr, VBOXVDMACMD);
596 VBOXVDMACMD_CHILD_STATUS_IRQ *pBody = VBOXVDMACMD_BODY(pHdr, VBOXVDMACMD_CHILD_STATUS_IRQ);
597
598 vboxWddmChildStatusDoReportReconnected(pDevExt, pBody);
599
600 vboxVdmaCBufDrFree(&pDevExt->u.primary.Vdma, pDr);
601
602 if (pCtx->pEvent)
603 {
604 KeSetEvent(pCtx->pEvent, 0, FALSE);
605 }
606}
607
608static NTSTATUS vboxWddmChildStatusReportReconnected(PVBOXMP_DEVEXT pDevExt, D3DDDI_VIDEO_PRESENT_TARGET_ID idTarget)
609{
610#ifdef VBOX_WDDM_MONITOR_REPLUG_IRQ
611 NTSTATUS Status = STATUS_UNSUCCESSFUL;
612 UINT cbCmd = VBOXVDMACMD_SIZE_FROMBODYSIZE(sizeof (VBOXVDMACMD_CHILD_STATUS_IRQ));
613
614 PVBOXVDMACBUF_DR pDr = vboxVdmaCBufDrCreate(&pDevExt->u.primary.Vdma, cbCmd);
615 if (pDr)
616 {
617 // vboxVdmaCBufDrCreate zero initializes the pDr
618 /* the command data follows the descriptor */
619 pDr->fFlags = VBOXVDMACBUF_FLAG_BUF_FOLLOWS_DR;
620 pDr->cbBuf = cbCmd;
621 pDr->rc = VERR_NOT_IMPLEMENTED;
622
623 PVBOXVDMACMD pHdr = VBOXVDMACBUF_DR_TAIL(pDr, VBOXVDMACMD);
624 pHdr->enmType = VBOXVDMACMD_TYPE_CHILD_STATUS_IRQ;
625 pHdr->u32CmdSpecific = 0;
626 PVBOXVDMACMD_CHILD_STATUS_IRQ pBody = VBOXVDMACMD_BODY(pHdr, VBOXVDMACMD_CHILD_STATUS_IRQ);
627 pBody->cInfos = 1;
628 if (idTarget == D3DDDI_ID_ALL)
629 {
630 pBody->fFlags |= VBOXVDMACMD_CHILD_STATUS_IRQ_F_APPLY_TO_ALL;
631 }
632 pBody->aInfos[0].iChild = idTarget;
633 pBody->aInfos[0].fFlags = VBOXVDMA_CHILD_STATUS_F_DISCONNECTED | VBOXVDMA_CHILD_STATUS_F_CONNECTED;
634 /* we're going to KeWaitForSingleObject */
635 Assert(KeGetCurrentIrql() < DISPATCH_LEVEL);
636
637 PVBOXVDMADDI_CMD pDdiCmd = VBOXVDMADDI_CMD_FROM_BUF_DR(pDr);
638 VBOXWDDMCHILDSTATUSCB Ctx;
639 KEVENT Event;
640 KeInitializeEvent(&Event, NotificationEvent, FALSE);
641 Ctx.pDr = pDr;
642 Ctx.pEvent = &Event;
643 vboxVdmaDdiCmdInit(pDdiCmd, 0, 0, vboxWddmChildStatusReportCompletion, &Ctx);
644 /* mark command as submitted & invisible for the dx runtime since dx did not originate it */
645 vboxVdmaDdiCmdSubmittedNotDx(pDdiCmd);
646 int rc = vboxVdmaCBufDrSubmit(pDevExt, &pDevExt->u.primary.Vdma, pDr);
647 Assert(rc == VINF_SUCCESS);
648 if (RT_SUCCESS(rc))
649 {
650 Status = KeWaitForSingleObject(&Event, Executive, KernelMode, FALSE, NULL);
651 Assert(Status == STATUS_SUCCESS);
652 return STATUS_SUCCESS;
653 }
654
655 Status = STATUS_UNSUCCESSFUL;
656
657 vboxVdmaCBufDrFree(&pDevExt->u.primary.Vdma, pDr);
658 }
659 else
660 {
661 Assert(0);
662 /* @todo: try flushing.. */
663 LOGREL(("vboxVdmaCBufDrCreate returned NULL"));
664 Status = STATUS_INSUFFICIENT_RESOURCES;
665 }
666
667 return Status;
668#else
669 VBOXVDMACMD_CHILD_STATUS_IRQ Body = {0};
670 Body.cInfos = 1;
671 if (idTarget == D3DDDI_ID_ALL)
672 {
673 Body.fFlags |= VBOXVDMACMD_CHILD_STATUS_IRQ_F_APPLY_TO_ALL;
674 }
675 Body.aInfos[0].iChild = idTarget;
676 Body.aInfos[0].fFlags = VBOXVDMA_CHILD_STATUS_F_DISCONNECTED | VBOXVDMA_CHILD_STATUS_F_CONNECTED;
677 Assert(KeGetCurrentIrql() <= DISPATCH_LEVEL);
678 return vboxWddmChildStatusDoReportReconnected(pDevExt, &Body);
679#endif
680}
681
682static NTSTATUS vboxWddmChildStatusCheckByMask(PVBOXMP_DEVEXT pDevExt, PVBOXWDDM_VIDEOMODES_INFO paInfos, uint8_t *pMask)
683{
684 NTSTATUS Status = STATUS_SUCCESS;
685 bool bChanged[VBOX_VIDEO_MAX_SCREENS] = {0};
686 int i;
687
688 LOG(("checking child status.."));
689
690 for (i = 0; i < VBoxCommonFromDeviceExt(pDevExt)->cDisplays; ++i)
691 {
692 if (pMask && !ASMBitTest(pMask, i))
693 continue;
694
695 LOG(("requested to change child status for display %d", i));
696
697 /* @todo: check that we actually need the current source->target */
698 PVBOXWDDM_VIDEOMODES_INFO pInfo = &paInfos[i];
699 VIDEO_MODE_INFORMATION *pModeInfo = &pInfo->aModes[pInfo->iPreferredMode];
700 BOOLEAN fMatch = FALSE;
701 Status = vboxVidPnMatchMonitorModes(pDevExt, i, pInfo->aResolutions, pInfo->cResolutions, &fMatch);
702 if (!NT_SUCCESS(Status))
703 {
704 WARN(("vboxVidPnMatchMonitorModes failed Status(0x%x)", Status));
705 /* ignore the failures here, although we probably should not?? */
706 break;
707 }
708
709 bChanged[i] = !fMatch;
710 }
711
712 if (!NT_SUCCESS(Status))
713 {
714 WARN(("updating monitor modes failed, Status(0x%x)", Status));
715 return Status;
716 }
717
718 for (i = 0; i < VBoxCommonFromDeviceExt(pDevExt)->cDisplays; ++i)
719 {
720 if (bChanged[i])
721 {
722 LOG(("modes changed for display %d", i));
723
724 NTSTATUS tmpStatus = vboxWddmChildStatusReportReconnected(pDevExt, i);
725 if (!NT_SUCCESS(tmpStatus))
726 {
727 WARN(("vboxWddmChildStatusReportReconnected failed Status(0x%x)", Status));
728 /* ignore the failures here, although we probably should not?? */
729 break;
730 }
731 }
732 }
733
734 /* wait for the reconnected monitor data to be picked up */
735 CONST DXGK_MONITOR_INTERFACE *pMonitorInterface;
736 Status = pDevExt->u.primary.DxgkInterface.DxgkCbQueryMonitorInterface(pDevExt->u.primary.DxgkInterface.DeviceHandle, DXGK_MONITOR_INTERFACE_VERSION_V1, &pMonitorInterface);
737 if (!NT_SUCCESS(Status))
738 {
739 WARN(("DxgkCbQueryMonitorInterface failed, Status()0x%x", Status));
740 return Status;
741 }
742
743 for (i = 0; i < VBoxCommonFromDeviceExt(pDevExt)->cDisplays; ++i)
744 {
745 D3DKMDT_HMONITORSOURCEMODESET hMonitorSMS;
746 CONST DXGK_MONITORSOURCEMODESET_INTERFACE *pMonitorSMSIf;
747 if (!bChanged[i])
748 continue;
749
750 while (1)
751 {
752 Status = pMonitorInterface->pfnAcquireMonitorSourceModeSet(pDevExt->u.primary.DxgkInterface.DeviceHandle,
753 i,
754 &hMonitorSMS,
755 &pMonitorSMSIf);
756 if (NT_SUCCESS(Status))
757 {
758 NTSTATUS tmpStatus = pMonitorInterface->pfnReleaseMonitorSourceModeSet(pDevExt->u.primary.DxgkInterface.DeviceHandle, hMonitorSMS);
759 if (!NT_SUCCESS(tmpStatus))
760 {
761 WARN(("pfnReleaseMonitorSourceModeSet failed tmpStatus(0x%x)", tmpStatus));
762 }
763 break;
764 }
765
766 if (Status != STATUS_GRAPHICS_MONITOR_NOT_CONNECTED)
767 {
768 WARN(("DxgkCbQueryMonitorInterface failed, Status()0x%x", Status));
769 break;
770 }
771
772 Assert(KeGetCurrentIrql() < DISPATCH_LEVEL);
773
774 LARGE_INTEGER Interval;
775 Interval.QuadPart = -(int64_t) 2 /* ms */ * 10000;
776 NTSTATUS tmpStatus = KeDelayExecutionThread(KernelMode, FALSE, &Interval);
777 if (!NT_SUCCESS(tmpStatus))
778 {
779 WARN(("KeDelayExecutionThread failed tmpStatus(0x%x)", tmpStatus));
780 }
781 }
782 }
783
784 return STATUS_SUCCESS;
785}
786
787typedef struct VBOXWDDM_HWRESOURCES
788{
789 PHYSICAL_ADDRESS phVRAM;
790 ULONG cbVRAM;
791 ULONG ulApertureSize;
792} VBOXWDDM_HWRESOURCES, *PVBOXWDDM_HWRESOURCES;
793
794NTSTATUS vboxWddmPickResources(PVBOXMP_DEVEXT pDevExt, PDXGK_DEVICE_INFO pDeviceInfo, PVBOXWDDM_HWRESOURCES pHwResources)
795{
796 NTSTATUS Status = STATUS_SUCCESS;
797 USHORT DispiId;
798 memset(pHwResources, 0, sizeof (*pHwResources));
799 pHwResources->cbVRAM = VBE_DISPI_TOTAL_VIDEO_MEMORY_BYTES;
800
801 VBoxVideoCmnPortWriteUshort(VBE_DISPI_IOPORT_INDEX, VBE_DISPI_INDEX_ID);
802 VBoxVideoCmnPortWriteUshort(VBE_DISPI_IOPORT_DATA, VBE_DISPI_ID2);
803 DispiId = VBoxVideoCmnPortReadUshort(VBE_DISPI_IOPORT_DATA);
804 if (DispiId == VBE_DISPI_ID2)
805 {
806 LOGREL(("found the VBE card"));
807 /*
808 * Write some hardware information to registry, so that
809 * it's visible in Windows property dialog.
810 */
811
812 /*
813 * Query the adapter's memory size. It's a bit of a hack, we just read
814 * an ULONG from the data port without setting an index before.
815 */
816 pHwResources->cbVRAM = VBoxVideoCmnPortReadUlong(VBE_DISPI_IOPORT_DATA);
817 if (VBoxHGSMIIsSupported ())
818 {
819 PCM_RESOURCE_LIST pRcList = pDeviceInfo->TranslatedResourceList;
820 /* @todo: verify resources */
821 for (ULONG i = 0; i < pRcList->Count; ++i)
822 {
823 PCM_FULL_RESOURCE_DESCRIPTOR pFRc = &pRcList->List[i];
824 for (ULONG j = 0; j < pFRc->PartialResourceList.Count; ++j)
825 {
826 PCM_PARTIAL_RESOURCE_DESCRIPTOR pPRc = &pFRc->PartialResourceList.PartialDescriptors[j];
827 switch (pPRc->Type)
828 {
829 case CmResourceTypePort:
830 break;
831 case CmResourceTypeInterrupt:
832 break;
833 case CmResourceTypeMemory:
834 /* we assume there is one memory segment */
835 Assert(pHwResources->phVRAM.QuadPart == 0);
836 pHwResources->phVRAM = pPRc->u.Memory.Start;
837 Assert(pHwResources->phVRAM.QuadPart != 0);
838 pHwResources->ulApertureSize = pPRc->u.Memory.Length;
839 Assert(pHwResources->cbVRAM <= pHwResources->ulApertureSize);
840 break;
841 case CmResourceTypeDma:
842 break;
843 case CmResourceTypeDeviceSpecific:
844 break;
845 case CmResourceTypeBusNumber:
846 break;
847 default:
848 break;
849 }
850 }
851 }
852 }
853 else
854 {
855 LOGREL(("HGSMI unsupported, returning err"));
856 /* @todo: report a better status */
857 Status = STATUS_UNSUCCESSFUL;
858 }
859 }
860 else
861 {
862 LOGREL(("VBE card not found, returning err"));
863 Status = STATUS_UNSUCCESSFUL;
864 }
865
866
867 return Status;
868}
869
870static void vboxWddmDevExtZeroinit(PVBOXMP_DEVEXT pDevExt, CONST PDEVICE_OBJECT pPDO)
871{
872 memset(pDevExt, 0, sizeof (VBOXMP_DEVEXT));
873 pDevExt->pPDO = pPDO;
874 PWCHAR pName = (PWCHAR)(((uint8_t*)pDevExt) + VBOXWDDM_ROUNDBOUND(sizeof(VBOXMP_DEVEXT), 8));
875 RtlInitUnicodeString(&pDevExt->RegKeyName, pName);
876#ifdef VBOXWDDM_RENDER_FROM_SHADOW
877 for (int i = 0; i < RT_ELEMENTS(pDevExt->aSources); ++i)
878 {
879 PVBOXWDDM_SOURCE pSource = &pDevExt->aSources[i];
880 pSource->AllocData.SurfDesc.VidPnSourceId = i;
881 pSource->AllocData.Addr.offVram = VBOXVIDEOOFFSET_VOID;
882 }
883#endif
884}
885
886static void vboxWddmSetupDisplays(PVBOXMP_DEVEXT pDevExt)
887{
888 /* For WDDM, we simply store the number of monitors as we will deal with
889 * VidPN stuff later */
890 int rc = STATUS_SUCCESS;
891
892 if (VBoxCommonFromDeviceExt(pDevExt)->bHGSMI)
893 {
894 ULONG ulAvailable = VBoxCommonFromDeviceExt(pDevExt)->cbVRAM
895 - VBoxCommonFromDeviceExt(pDevExt)->cbMiniportHeap
896 - VBVA_ADAPTER_INFORMATION_SIZE;
897
898 ULONG ulSize;
899 ULONG offset;
900#ifdef VBOX_WITH_VDMA
901 ulSize = ulAvailable / 2;
902 if (ulSize > VBOXWDDM_C_VDMA_BUFFER_SIZE)
903 ulSize = VBOXWDDM_C_VDMA_BUFFER_SIZE;
904
905 /* Align down to 4096 bytes. */
906 ulSize &= ~0xFFF;
907 offset = ulAvailable - ulSize;
908
909 Assert(!(offset & 0xFFF));
910#else
911 offset = ulAvailable;
912#endif
913 rc = vboxVdmaCreate (pDevExt, &pDevExt->u.primary.Vdma
914#ifdef VBOX_WITH_VDMA
915 , offset, ulSize
916#endif
917 );
918 AssertRC(rc);
919 if (RT_SUCCESS(rc))
920 {
921#ifdef VBOX_VDMA_WITH_WATCHDOG
922 vboxWddmWdInit(pDevExt);
923#endif
924 /* can enable it right away since the host does not need any screen/FB info
925 * for basic DMA functionality */
926 rc = vboxVdmaEnable(pDevExt, &pDevExt->u.primary.Vdma);
927 AssertRC(rc);
928 if (RT_FAILURE(rc))
929 vboxVdmaDestroy(pDevExt, &pDevExt->u.primary.Vdma);
930 }
931
932 ulAvailable = offset;
933 ulSize = ulAvailable/2;
934 offset = ulAvailable - ulSize;
935
936 NTSTATUS Status = vboxVideoAMgrCreate(pDevExt, &pDevExt->AllocMgr, offset, ulSize);
937 Assert(Status == STATUS_SUCCESS);
938 if (Status != STATUS_SUCCESS)
939 {
940 offset = ulAvailable;
941 }
942
943#ifdef VBOXWDDM_RENDER_FROM_SHADOW
944 if (RT_SUCCESS(rc))
945 {
946 ulAvailable = offset;
947 ulSize = ulAvailable / 2;
948 ulSize /= VBoxCommonFromDeviceExt(pDevExt)->cDisplays;
949 Assert(ulSize > VBVA_MIN_BUFFER_SIZE);
950 if (ulSize > VBVA_MIN_BUFFER_SIZE)
951 {
952 ULONG ulRatio = ulSize/VBVA_MIN_BUFFER_SIZE;
953 ulRatio >>= 4; /* /= 16; */
954 if (ulRatio)
955 ulSize = VBVA_MIN_BUFFER_SIZE * ulRatio;
956 else
957 ulSize = VBVA_MIN_BUFFER_SIZE;
958 }
959 else
960 {
961 /* todo: ?? */
962 }
963
964 ulSize &= ~0xFFF;
965 Assert(ulSize);
966
967 Assert(ulSize * VBoxCommonFromDeviceExt(pDevExt)->cDisplays < ulAvailable);
968
969 for (int i = VBoxCommonFromDeviceExt(pDevExt)->cDisplays-1; i >= 0; --i)
970 {
971 offset -= ulSize;
972 rc = vboxVbvaCreate(pDevExt, &pDevExt->aSources[i].Vbva, offset, ulSize, i);
973 AssertRC(rc);
974 if (RT_SUCCESS(rc))
975 {
976 rc = vboxVbvaEnable(pDevExt, &pDevExt->aSources[i].Vbva);
977 AssertRC(rc);
978 if (RT_FAILURE(rc))
979 {
980 /* @todo: de-initialize */
981 }
982 }
983 }
984 }
985#endif
986
987 rc = VBoxMPCmnMapAdapterMemory(VBoxCommonFromDeviceExt(pDevExt), (void**)&pDevExt->pvVisibleVram,
988 0, vboxWddmVramCpuVisibleSize(pDevExt));
989 Assert(rc == VINF_SUCCESS);
990 if (rc != VINF_SUCCESS)
991 pDevExt->pvVisibleVram = NULL;
992
993 if (RT_FAILURE(rc))
994 VBoxCommonFromDeviceExt(pDevExt)->bHGSMI = FALSE;
995 }
996}
997
998static int vboxWddmFreeDisplays(PVBOXMP_DEVEXT pDevExt)
999{
1000 int rc = VINF_SUCCESS;
1001
1002 Assert(pDevExt->pvVisibleVram);
1003 if (pDevExt->pvVisibleVram)
1004 VBoxMPCmnUnmapAdapterMemory(VBoxCommonFromDeviceExt(pDevExt), (void**)&pDevExt->pvVisibleVram);
1005
1006 for (int i = VBoxCommonFromDeviceExt(pDevExt)->cDisplays-1; i >= 0; --i)
1007 {
1008 rc = vboxVbvaDisable(pDevExt, &pDevExt->aSources[i].Vbva);
1009 AssertRC(rc);
1010 if (RT_SUCCESS(rc))
1011 {
1012 rc = vboxVbvaDestroy(pDevExt, &pDevExt->aSources[i].Vbva);
1013 AssertRC(rc);
1014 if (RT_FAILURE(rc))
1015 {
1016 /* @todo: */
1017 }
1018 }
1019 }
1020
1021 vboxVideoAMgrDestroy(pDevExt, &pDevExt->AllocMgr);
1022
1023 rc = vboxVdmaDisable(pDevExt, &pDevExt->u.primary.Vdma);
1024 AssertRC(rc);
1025 if (RT_SUCCESS(rc))
1026 {
1027#ifdef VBOX_VDMA_WITH_WATCHDOG
1028 vboxWddmWdTerm(pDevExt);
1029#endif
1030 rc = vboxVdmaDestroy(pDevExt, &pDevExt->u.primary.Vdma);
1031 AssertRC(rc);
1032 }
1033 return rc;
1034}
1035
1036
1037/* driver callbacks */
1038NTSTATUS DxgkDdiAddDevice(
1039 IN CONST PDEVICE_OBJECT PhysicalDeviceObject,
1040 OUT PVOID *MiniportDeviceContext
1041 )
1042{
1043 /* The DxgkDdiAddDevice function should be made pageable. */
1044 PAGED_CODE();
1045
1046 LOGF(("ENTER, pdo(0x%x)", PhysicalDeviceObject));
1047
1048 vboxVDbgBreakFv();
1049
1050 NTSTATUS Status = STATUS_SUCCESS;
1051 PVBOXMP_DEVEXT pDevExt;
1052
1053 WCHAR RegKeyBuf[512];
1054 ULONG cbRegKeyBuf = sizeof (RegKeyBuf);
1055
1056 Status = IoGetDeviceProperty (PhysicalDeviceObject,
1057 DevicePropertyDriverKeyName,
1058 cbRegKeyBuf,
1059 RegKeyBuf,
1060 &cbRegKeyBuf);
1061 Assert(Status == STATUS_SUCCESS);
1062 if (Status == STATUS_SUCCESS)
1063 {
1064 pDevExt = (PVBOXMP_DEVEXT)vboxWddmMemAllocZero(VBOXWDDM_ROUNDBOUND(sizeof(VBOXMP_DEVEXT), 8) + cbRegKeyBuf);
1065 if (pDevExt)
1066 {
1067 PWCHAR pName = (PWCHAR)(((uint8_t*)pDevExt) + VBOXWDDM_ROUNDBOUND(sizeof(VBOXMP_DEVEXT), 8));
1068 memcpy(pName, RegKeyBuf, cbRegKeyBuf);
1069 vboxWddmDevExtZeroinit(pDevExt, PhysicalDeviceObject);
1070 *MiniportDeviceContext = pDevExt;
1071 }
1072 else
1073 {
1074 Status = STATUS_NO_MEMORY;
1075 LOGREL(("ERROR, failed to create context"));
1076 }
1077 }
1078
1079 LOGF(("LEAVE, Status(0x%x), pDevExt(0x%x)", Status, pDevExt));
1080
1081 return Status;
1082}
1083
1084NTSTATUS DxgkDdiStartDevice(
1085 IN CONST PVOID MiniportDeviceContext,
1086 IN PDXGK_START_INFO DxgkStartInfo,
1087 IN PDXGKRNL_INTERFACE DxgkInterface,
1088 OUT PULONG NumberOfVideoPresentSources,
1089 OUT PULONG NumberOfChildren
1090 )
1091{
1092 /* The DxgkDdiStartDevice function should be made pageable. */
1093 PAGED_CODE();
1094
1095 NTSTATUS Status;
1096
1097 LOGF(("ENTER, context(0x%x)", MiniportDeviceContext));
1098
1099 vboxVDbgBreakFv();
1100
1101 if ( ARGUMENT_PRESENT(MiniportDeviceContext) &&
1102 ARGUMENT_PRESENT(DxgkInterface) &&
1103 ARGUMENT_PRESENT(DxgkStartInfo) &&
1104 ARGUMENT_PRESENT(NumberOfVideoPresentSources),
1105 ARGUMENT_PRESENT(NumberOfChildren)
1106 )
1107 {
1108 PVBOXMP_DEVEXT pDevExt = (PVBOXMP_DEVEXT)MiniportDeviceContext;
1109
1110 vboxWddmVGuidGet(pDevExt);
1111
1112 /* Save DeviceHandle and function pointers supplied by the DXGKRNL_INTERFACE structure passed to DxgkInterface. */
1113 memcpy(&pDevExt->u.primary.DxgkInterface, DxgkInterface, sizeof (DXGKRNL_INTERFACE));
1114
1115 /* 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)
1116 * of the DXGK_DEVICE_INFO structure in the context block represented by MiniportDeviceContext. */
1117 DXGK_DEVICE_INFO DeviceInfo;
1118 Status = pDevExt->u.primary.DxgkInterface.DxgkCbGetDeviceInformation (pDevExt->u.primary.DxgkInterface.DeviceHandle, &DeviceInfo);
1119 if (Status == STATUS_SUCCESS)
1120 {
1121 VBOXWDDM_HWRESOURCES HwRc;
1122 Status = vboxWddmPickResources(pDevExt, &DeviceInfo, &HwRc);
1123 if (Status == STATUS_SUCCESS)
1124 {
1125 /* Guest supports only HGSMI, the old VBVA via VMMDev is not supported.
1126 * The host will however support both old and new interface to keep compatibility
1127 * with old guest additions.
1128 */
1129 VBoxSetupDisplaysHGSMI(VBoxCommonFromDeviceExt(pDevExt),
1130 HwRc.phVRAM, HwRc.ulApertureSize, HwRc.cbVRAM,
1131 VBVACAPS_COMPLETEGCMD_BY_IOREAD | VBVACAPS_IRQ);
1132 if (VBoxCommonFromDeviceExt(pDevExt)->bHGSMI)
1133 {
1134 vboxWddmSetupDisplays(pDevExt);
1135 if (!VBoxCommonFromDeviceExt(pDevExt)->bHGSMI)
1136 VBoxFreeDisplaysHGSMI(VBoxCommonFromDeviceExt(pDevExt));
1137 }
1138 if (VBoxCommonFromDeviceExt(pDevExt)->bHGSMI)
1139 {
1140 LOGREL(("using HGSMI"));
1141 *NumberOfVideoPresentSources = VBoxCommonFromDeviceExt(pDevExt)->cDisplays;
1142 *NumberOfChildren = VBoxCommonFromDeviceExt(pDevExt)->cDisplays;
1143 LOG(("sources(%d), children(%d)", *NumberOfVideoPresentSources, *NumberOfChildren));
1144
1145 vboxVdmaDdiNodesInit(pDevExt);
1146 vboxVideoCmInit(&pDevExt->CmMgr);
1147 InitializeListHead(&pDevExt->SwapchainList3D);
1148 pDevExt->cContexts3D = 0;
1149 pDevExt->cContexts2D = 0;
1150 pDevExt->cUnlockedVBVADisabled = 0;
1151 VBOXWDDM_CTXLOCK_INIT(pDevExt);
1152 KeInitializeSpinLock(&pDevExt->SynchLock);
1153
1154 VBoxMPCmnInitCustomVideoModes(pDevExt);
1155 VBoxWddmInvalidateAllVideoModesInfos(pDevExt);
1156
1157 VBoxCommonFromDeviceExt(pDevExt)->fAnyX = VBoxVideoAnyWidthAllowed();
1158#if 0
1159 vboxShRcTreeInit(pDevExt);
1160#endif
1161
1162#ifdef VBOX_WITH_VIDEOHWACCEL
1163 vboxVhwaInit(pDevExt);
1164#endif
1165 VBoxWddmSlInit(pDevExt);
1166
1167#ifdef VBOX_WDDM_MINIPORT_WITH_VISIBLE_RECTS
1168 VBoxMpCrShgsmiTransportCreate(&pDevExt->CrHgsmiTransport, pDevExt);
1169#endif
1170
1171 for (UINT i = 0; i < (UINT)VBoxCommonFromDeviceExt(pDevExt)->cDisplays; ++i)
1172 {
1173 PVBOXWDDM_SOURCE pSource = &pDevExt->aSources[i];
1174 KeInitializeSpinLock(&pSource->AllocationLock);
1175 }
1176
1177#ifdef VBOX_WDDM_WIN8
1178 DXGK_DISPLAY_INFORMATION DisplayInfo;
1179 Status = pDevExt->u.primary.DxgkInterface.DxgkCbAcquirePostDisplayOwnership(pDevExt->u.primary.DxgkInterface.DeviceHandle,
1180 &DisplayInfo);
1181 if (NT_SUCCESS(Status))
1182 {
1183 PVBOXWDDM_SOURCE pSource = &pDevExt->aSources[0];
1184 PHYSICAL_ADDRESS PhAddr;
1185 /* display info may sometimes not be valid, e.g. on from-full-graphics wddm driver update
1186 * ensure we have something meaningful here */
1187 if (!DisplayInfo.Width)
1188 {
1189 PhAddr = VBoxCommonFromDeviceExt(pDevExt)->phVRAM;
1190 vboxWddmDiInitDefault(&DisplayInfo, PhAddr, 0);
1191 }
1192 else
1193 {
1194 PhAddr = DisplayInfo.PhysicAddress;
1195 DisplayInfo.TargetId = 0;
1196 }
1197
1198 vboxWddmDiToAllocData(pDevExt, &DisplayInfo, &pSource->AllocData);
1199
1200 /* init the rest source infos with some default values */
1201 for (UINT i = 1; i < (UINT)VBoxCommonFromDeviceExt(pDevExt)->cDisplays; ++i)
1202 {
1203 PhAddr.QuadPart += pSource->AllocData.SurfDesc.cbSize;
1204 PhAddr.QuadPart = ROUND_TO_PAGES(PhAddr.QuadPart);
1205 vboxWddmDiInitDefault(&DisplayInfo, PhAddr, i);
1206 pSource = &pDevExt->aSources[i];
1207 vboxWddmDiToAllocData(pDevExt, &DisplayInfo, &pSource->AllocData);
1208 }
1209 }
1210 else
1211 {
1212 WARN(("DxgkCbAcquirePostDisplayOwnership failed, Status 0x%x", Status));
1213 }
1214#endif
1215 }
1216 else
1217 {
1218 LOGREL(("HGSMI failed to initialize, returning err"));
1219
1220 /* @todo: report a better status */
1221 Status = STATUS_UNSUCCESSFUL;
1222 }
1223 }
1224 else
1225 {
1226 LOGREL(("vboxWddmPickResources failed Status(0x%x), returning err", Status));
1227 Status = STATUS_UNSUCCESSFUL;
1228 }
1229 }
1230 else
1231 {
1232 LOGREL(("DxgkCbGetDeviceInformation failed Status(0x%x), returning err", Status));
1233 }
1234 }
1235 else
1236 {
1237 LOGREL(("invalid parameter, returning err"));
1238 Status = STATUS_INVALID_PARAMETER;
1239 }
1240
1241 LOGF(("LEAVE, status(0x%x)", Status));
1242
1243 return Status;
1244}
1245
1246NTSTATUS DxgkDdiStopDevice(
1247 IN CONST PVOID MiniportDeviceContext
1248 )
1249{
1250 /* The DxgkDdiStopDevice function should be made pageable. */
1251 PAGED_CODE();
1252
1253 LOGF(("ENTER, context(0x%p)", MiniportDeviceContext));
1254
1255 vboxVDbgBreakFv();
1256
1257 PVBOXMP_DEVEXT pDevExt = (PVBOXMP_DEVEXT)MiniportDeviceContext;
1258 NTSTATUS Status = STATUS_SUCCESS;
1259
1260#ifdef VBOX_WDDM_MINIPORT_WITH_VISIBLE_RECTS
1261 VBoxMpCrShgsmiTransportTerm(&pDevExt->CrHgsmiTransport);
1262#endif
1263
1264 VBoxWddmSlTerm(pDevExt);
1265
1266 vboxVideoCmTerm(&pDevExt->CmMgr);
1267
1268 /* do everything we did on DxgkDdiStartDevice in the reverse order */
1269#ifdef VBOX_WITH_VIDEOHWACCEL
1270 vboxVhwaFree(pDevExt);
1271#endif
1272#if 0
1273 vboxShRcTreeTerm(pDevExt);
1274#endif
1275
1276 int rc = vboxWddmFreeDisplays(pDevExt);
1277 if (RT_SUCCESS(rc))
1278 VBoxFreeDisplaysHGSMI(VBoxCommonFromDeviceExt(pDevExt));
1279 AssertRC(rc);
1280 if (RT_SUCCESS(rc))
1281 {
1282 vboxWddmVGuidFree(pDevExt);
1283
1284 /* revert back to the state we were right after the DxgkDdiAddDevice */
1285 vboxWddmDevExtZeroinit(pDevExt, pDevExt->pPDO);
1286 }
1287 else
1288 Status = STATUS_UNSUCCESSFUL;
1289
1290 return Status;
1291}
1292
1293NTSTATUS DxgkDdiRemoveDevice(
1294 IN CONST PVOID MiniportDeviceContext
1295 )
1296{
1297 /* DxgkDdiRemoveDevice should be made pageable. */
1298 PAGED_CODE();
1299
1300 LOGF(("ENTER, context(0x%p)", MiniportDeviceContext));
1301
1302 vboxVDbgBreakFv();
1303
1304 vboxWddmMemFree(MiniportDeviceContext);
1305
1306 LOGF(("LEAVE, context(0x%p)", MiniportDeviceContext));
1307
1308 return STATUS_SUCCESS;
1309}
1310
1311NTSTATUS DxgkDdiDispatchIoRequest(
1312 IN CONST PVOID MiniportDeviceContext,
1313 IN ULONG VidPnSourceId,
1314 IN PVIDEO_REQUEST_PACKET VideoRequestPacket
1315 )
1316{
1317 LOGF(("ENTER, context(0x%p), ctl(0x%x)", MiniportDeviceContext, VideoRequestPacket->IoControlCode));
1318
1319 AssertBreakpoint();
1320#if 0
1321 PVBOXMP_DEVEXT pDevExt = (PVBOXMP_DEVEXT)MiniportDeviceContext;
1322
1323 switch (VideoRequestPacket->IoControlCode)
1324 {
1325 case IOCTL_VIDEO_QUERY_COLOR_CAPABILITIES:
1326 {
1327 if (VideoRequestPacket->OutputBufferLength < sizeof(VIDEO_COLOR_CAPABILITIES))
1328 {
1329 AssertBreakpoint();
1330 VideoRequestPacket->StatusBlock->Status = ERROR_INSUFFICIENT_BUFFER;
1331 return TRUE;
1332 }
1333 VIDEO_COLOR_CAPABILITIES *pCaps = (VIDEO_COLOR_CAPABILITIES*)VideoRequestPacket->OutputBuffer;
1334
1335 pCaps->Length = sizeof (VIDEO_COLOR_CAPABILITIES);
1336 pCaps->AttributeFlags = VIDEO_DEVICE_COLOR;
1337 pCaps->RedPhosphoreDecay = 0;
1338 pCaps->GreenPhosphoreDecay = 0;
1339 pCaps->BluePhosphoreDecay = 0;
1340 pCaps->WhiteChromaticity_x = 3127;
1341 pCaps->WhiteChromaticity_y = 3290;
1342 pCaps->WhiteChromaticity_Y = 0;
1343 pCaps->RedChromaticity_x = 6700;
1344 pCaps->RedChromaticity_y = 3300;
1345 pCaps->GreenChromaticity_x = 2100;
1346 pCaps->GreenChromaticity_y = 7100;
1347 pCaps->BlueChromaticity_x = 1400;
1348 pCaps->BlueChromaticity_y = 800;
1349 pCaps->WhiteGamma = 0;
1350 pCaps->RedGamma = 20000;
1351 pCaps->GreenGamma = 20000;
1352 pCaps->BlueGamma = 20000;
1353
1354 VideoRequestPacket->StatusBlock->Status = NO_ERROR;
1355 VideoRequestPacket->StatusBlock->Information = sizeof (VIDEO_COLOR_CAPABILITIES);
1356 break;
1357 }
1358#if 0
1359 case IOCTL_VIDEO_HANDLE_VIDEOPARAMETERS:
1360 {
1361 if (VideoRequestPacket->OutputBufferLength < sizeof(VIDEOPARAMETERS)
1362 || VideoRequestPacket->InputBufferLength < sizeof(VIDEOPARAMETERS))
1363 {
1364 AssertBreakpoint();
1365 VideoRequestPacket->StatusBlock->Status = ERROR_INSUFFICIENT_BUFFER;
1366 return TRUE;
1367 }
1368
1369 Result = VBoxVideoResetDevice((PVBOXMP_DEVEXT)HwDeviceExtension,
1370 RequestPacket->StatusBlock);
1371 break;
1372 }
1373#endif
1374 default:
1375 AssertBreakpoint();
1376 VideoRequestPacket->StatusBlock->Status = ERROR_INVALID_FUNCTION;
1377 VideoRequestPacket->StatusBlock->Information = 0;
1378 }
1379#endif
1380 LOGF(("LEAVE, context(0x%p), ctl(0x%x)", MiniportDeviceContext, VideoRequestPacket->IoControlCode));
1381
1382 return STATUS_SUCCESS;
1383}
1384
1385BOOLEAN DxgkDdiInterruptRoutine(
1386 IN CONST PVOID MiniportDeviceContext,
1387 IN ULONG MessageNumber
1388 )
1389{
1390// LOGF(("ENTER, context(0x%p), msg(0x%x)", MiniportDeviceContext, MessageNumber));
1391
1392 vboxVDbgBreakFv();
1393
1394 PVBOXMP_DEVEXT pDevExt = (PVBOXMP_DEVEXT)MiniportDeviceContext;
1395 BOOLEAN bOur = FALSE;
1396 BOOLEAN bNeedDpc = FALSE;
1397 if (VBoxCommonFromDeviceExt(pDevExt)->hostCtx.pfHostFlags) /* If HGSMI is enabled at all. */
1398 {
1399 VBOXVTLIST CtlList;
1400#ifdef VBOX_WITH_VDMA
1401 VBOXVTLIST DmaCmdList;
1402#endif
1403 vboxVtListInit(&CtlList);
1404#ifdef VBOX_WITH_VDMA
1405 vboxVtListInit(&DmaCmdList);
1406#endif
1407
1408#ifdef VBOX_WITH_VIDEOHWACCEL
1409 VBOXVTLIST VhwaCmdList;
1410 vboxVtListInit(&VhwaCmdList);
1411#endif
1412
1413 uint32_t flags = VBoxCommonFromDeviceExt(pDevExt)->hostCtx.pfHostFlags->u32HostFlags;
1414 bOur = (flags & HGSMIHOSTFLAGS_IRQ);
1415 do
1416 {
1417 if (flags & HGSMIHOSTFLAGS_GCOMMAND_COMPLETED)
1418 {
1419 /* read the command offset */
1420 HGSMIOFFSET offCmd = VBoxVideoCmnPortReadUlong(VBoxCommonFromDeviceExt(pDevExt)->guestCtx.port);
1421 Assert(offCmd != HGSMIOFFSET_VOID);
1422 if (offCmd != HGSMIOFFSET_VOID)
1423 {
1424 VBOXWDDM_HGSMICMD_TYPE enmType = vboxWddmHgsmiGetCmdTypeFromOffset(pDevExt, offCmd);
1425 PVBOXVTLIST pList;
1426 PVBOXSHGSMI pHeap = NULL;
1427 switch (enmType)
1428 {
1429#ifdef VBOX_WITH_VDMA
1430 case VBOXWDDM_HGSMICMD_TYPE_DMACMD:
1431 pList = &DmaCmdList;
1432 pHeap = &pDevExt->u.primary.Vdma.CmdHeap;
1433 break;
1434#endif
1435 case VBOXWDDM_HGSMICMD_TYPE_CTL:
1436 pList = &CtlList;
1437 pHeap = &VBoxCommonFromDeviceExt(pDevExt)->guestCtx.heapCtx;
1438 break;
1439 default:
1440 AssertBreakpoint();
1441 }
1442
1443 if (pHeap)
1444 {
1445 uint16_t chInfo;
1446 uint8_t *pvCmd = HGSMIBufferDataAndChInfoFromOffset (&pHeap->Heap.area, offCmd, &chInfo);
1447 Assert(pvCmd);
1448 if (pvCmd)
1449 {
1450 switch (chInfo)
1451 {
1452#ifdef VBOX_WITH_VDMA
1453 case VBVA_VDMA_CMD:
1454 case VBVA_VDMA_CTL:
1455 {
1456 int rc = VBoxSHGSMICommandProcessCompletion (pHeap, (VBOXSHGSMIHEADER*)pvCmd, TRUE /*bool bIrq*/ , pList);
1457 AssertRC(rc);
1458 break;
1459 }
1460#endif
1461#ifdef VBOX_WITH_VIDEOHWACCEL
1462 case VBVA_VHWA_CMD:
1463 {
1464 vboxVhwaPutList(&VhwaCmdList, (VBOXVHWACMD*)pvCmd);
1465 break;
1466 }
1467#endif /* # ifdef VBOX_WITH_VIDEOHWACCEL */
1468 default:
1469 AssertBreakpoint();
1470 }
1471 }
1472 }
1473 }
1474 }
1475 else if (flags & HGSMIHOSTFLAGS_COMMANDS_PENDING)
1476 {
1477 AssertBreakpoint();
1478 /* @todo: FIXME: implement !!! */
1479 }
1480 else
1481 break;
1482
1483 flags = VBoxCommonFromDeviceExt(pDevExt)->hostCtx.pfHostFlags->u32HostFlags;
1484 } while (1);
1485
1486 if (!vboxVtListIsEmpty(&CtlList))
1487 {
1488 vboxVtListCat(&pDevExt->CtlList, &CtlList);
1489 bNeedDpc = TRUE;
1490 }
1491#ifdef VBOX_WITH_VDMA
1492 if (!vboxVtListIsEmpty(&DmaCmdList))
1493 {
1494 vboxVtListCat(&pDevExt->DmaCmdList, &DmaCmdList);
1495 bNeedDpc = TRUE;
1496 }
1497#endif
1498 if (!vboxVtListIsEmpty(&VhwaCmdList))
1499 {
1500 vboxVtListCat(&pDevExt->VhwaCmdList, &VhwaCmdList);
1501 bNeedDpc = TRUE;
1502 }
1503
1504 bNeedDpc |= !vboxVdmaDdiCmdIsCompletedListEmptyIsr(pDevExt);
1505
1506 if (pDevExt->bNotifyDxDpc)
1507 {
1508 bNeedDpc = TRUE;
1509 }
1510
1511 if (bOur)
1512 {
1513#ifdef VBOX_VDMA_WITH_WATCHDOG
1514 if (flags & HGSMIHOSTFLAGS_WATCHDOG)
1515 {
1516 Assert(0);
1517 }
1518#endif
1519 if (flags & HGSMIHOSTFLAGS_VSYNC)
1520 {
1521 Assert(0);
1522 DXGKARGCB_NOTIFY_INTERRUPT_DATA notify;
1523 for (UINT i = 0; i < (UINT)VBoxCommonFromDeviceExt(pDevExt)->cDisplays; ++i)
1524 {
1525 PVBOXWDDM_SOURCE pSource = &pDevExt->aSources[i];
1526 PVBOXWDDM_ALLOCATION pPrimary = pSource->pPrimaryAllocation;
1527 if (pPrimary && pPrimary->AllocData.Addr.offVram != VBOXVIDEOOFFSET_VOID)
1528 {
1529 memset(&notify, 0, sizeof(DXGKARGCB_NOTIFY_INTERRUPT_DATA));
1530 notify.InterruptType = DXGK_INTERRUPT_CRTC_VSYNC;
1531 /* @todo: !!!this is not correct in case we want source[i]->target[i!=j] mapping */
1532 notify.CrtcVsync.VidPnTargetId = i;
1533 notify.CrtcVsync.PhysicalAddress.QuadPart = pPrimary->AllocData.Addr.offVram;
1534 pDevExt->u.primary.DxgkInterface.DxgkCbNotifyInterrupt(pDevExt->u.primary.DxgkInterface.DeviceHandle, &notify);
1535
1536 pDevExt->bNotifyDxDpc = TRUE;
1537 }
1538 }
1539 }
1540
1541 if (pDevExt->bNotifyDxDpc)
1542 {
1543 bNeedDpc = TRUE;
1544 }
1545
1546 VBoxHGSMIClearIrq(&VBoxCommonFromDeviceExt(pDevExt)->hostCtx);
1547#if 0 //def DEBUG_misha
1548 /* this is not entirely correct since host may concurrently complete some commands and raise a new IRQ while we are here,
1549 * still this allows to check that the host flags are correctly cleared after the ISR */
1550 Assert(VBoxCommonFromDeviceExt(pDevExt)->hostCtx.pfHostFlags);
1551 uint32_t flags = VBoxCommonFromDeviceExt(pDevExt)->hostCtx.pfHostFlags->u32HostFlags;
1552 Assert(flags == 0);
1553#endif
1554 }
1555
1556 if (bNeedDpc)
1557 {
1558 pDevExt->u.primary.DxgkInterface.DxgkCbQueueDpc(pDevExt->u.primary.DxgkInterface.DeviceHandle);
1559 }
1560 }
1561
1562// LOGF(("LEAVE, context(0x%p), bOur(0x%x)", MiniportDeviceContext, (ULONG)bOur));
1563
1564 return bOur;
1565}
1566
1567
1568typedef struct VBOXWDDM_DPCDATA
1569{
1570 VBOXVTLIST CtlList;
1571#ifdef VBOX_WITH_VDMA
1572 VBOXVTLIST DmaCmdList;
1573#endif
1574#ifdef VBOX_WITH_VIDEOHWACCEL
1575 VBOXVTLIST VhwaCmdList;
1576#endif
1577 LIST_ENTRY CompletedDdiCmdQueue;
1578 BOOL bNotifyDpc;
1579} VBOXWDDM_DPCDATA, *PVBOXWDDM_DPCDATA;
1580
1581typedef struct VBOXWDDM_GETDPCDATA_CONTEXT
1582{
1583 PVBOXMP_DEVEXT pDevExt;
1584 VBOXWDDM_DPCDATA data;
1585} VBOXWDDM_GETDPCDATA_CONTEXT, *PVBOXWDDM_GETDPCDATA_CONTEXT;
1586
1587BOOLEAN vboxWddmGetDPCDataCallback(PVOID Context)
1588{
1589 PVBOXWDDM_GETDPCDATA_CONTEXT pdc = (PVBOXWDDM_GETDPCDATA_CONTEXT)Context;
1590
1591 vboxVtListDetach2List(&pdc->pDevExt->CtlList, &pdc->data.CtlList);
1592#ifdef VBOX_WITH_VDMA
1593 vboxVtListDetach2List(&pdc->pDevExt->DmaCmdList, &pdc->data.DmaCmdList);
1594#endif
1595#ifdef VBOX_WITH_VIDEOHWACCEL
1596 vboxVtListDetach2List(&pdc->pDevExt->VhwaCmdList, &pdc->data.VhwaCmdList);
1597#endif
1598 vboxVdmaDdiCmdGetCompletedListIsr(pdc->pDevExt, &pdc->data.CompletedDdiCmdQueue);
1599
1600 pdc->data.bNotifyDpc = pdc->pDevExt->bNotifyDxDpc;
1601 pdc->pDevExt->bNotifyDxDpc = FALSE;
1602 return TRUE;
1603}
1604
1605VOID DxgkDdiDpcRoutine(
1606 IN CONST PVOID MiniportDeviceContext
1607 )
1608{
1609// LOGF(("ENTER, context(0x%p)", MiniportDeviceContext));
1610
1611 vboxVDbgBreakFv();
1612
1613 PVBOXMP_DEVEXT pDevExt = (PVBOXMP_DEVEXT)MiniportDeviceContext;
1614
1615 VBOXWDDM_GETDPCDATA_CONTEXT context = {0};
1616 BOOLEAN bRet;
1617
1618 context.pDevExt = pDevExt;
1619
1620 /* get DPC data at IRQL */
1621 NTSTATUS Status = pDevExt->u.primary.DxgkInterface.DxgkCbSynchronizeExecution(
1622 pDevExt->u.primary.DxgkInterface.DeviceHandle,
1623 vboxWddmGetDPCDataCallback,
1624 &context,
1625 0, /* IN ULONG MessageNumber */
1626 &bRet);
1627 Assert(Status == STATUS_SUCCESS);
1628
1629// if (context.data.bNotifyDpc)
1630 pDevExt->u.primary.DxgkInterface.DxgkCbNotifyDpc(pDevExt->u.primary.DxgkInterface.DeviceHandle);
1631
1632 if (!vboxVtListIsEmpty(&context.data.CtlList))
1633 {
1634 int rc = VBoxSHGSMICommandPostprocessCompletion (&VBoxCommonFromDeviceExt(pDevExt)->guestCtx.heapCtx, &context.data.CtlList);
1635 AssertRC(rc);
1636 }
1637#ifdef VBOX_WITH_VDMA
1638 if (!vboxVtListIsEmpty(&context.data.DmaCmdList))
1639 {
1640 int rc = VBoxSHGSMICommandPostprocessCompletion (&pDevExt->u.primary.Vdma.CmdHeap, &context.data.DmaCmdList);
1641 AssertRC(rc);
1642 }
1643#endif
1644#ifdef VBOX_WITH_VIDEOHWACCEL
1645 if (!vboxVtListIsEmpty(&context.data.VhwaCmdList))
1646 {
1647 vboxVhwaCompletionListProcess(pDevExt, &context.data.VhwaCmdList);
1648 }
1649#endif
1650
1651 vboxVdmaDdiCmdHandleCompletedList(pDevExt, &context.data.CompletedDdiCmdQueue);
1652
1653// LOGF(("LEAVE, context(0x%p)", MiniportDeviceContext));
1654}
1655
1656NTSTATUS DxgkDdiQueryChildRelations(
1657 IN CONST PVOID MiniportDeviceContext,
1658 IN OUT PDXGK_CHILD_DESCRIPTOR ChildRelations,
1659 IN ULONG ChildRelationsSize
1660 )
1661{
1662 /* The DxgkDdiQueryChildRelations function should be made pageable. */
1663 PAGED_CODE();
1664
1665 vboxVDbgBreakFv();
1666
1667 PVBOXMP_DEVEXT pDevExt = (PVBOXMP_DEVEXT)MiniportDeviceContext;
1668
1669 LOGF(("ENTER, context(0x%x)", MiniportDeviceContext));
1670 Assert(ChildRelationsSize == (VBoxCommonFromDeviceExt(pDevExt)->cDisplays + 1)*sizeof(DXGK_CHILD_DESCRIPTOR));
1671 for (int i = 0; i < VBoxCommonFromDeviceExt(pDevExt)->cDisplays; ++i)
1672 {
1673 ChildRelations[i].ChildDeviceType = TypeVideoOutput;
1674 ChildRelations[i].ChildCapabilities.Type.VideoOutput.InterfaceTechnology = D3DKMDT_VOT_HD15; /* VGA */
1675 ChildRelations[i].ChildCapabilities.Type.VideoOutput.MonitorOrientationAwareness = D3DKMDT_MOA_INTERRUPTIBLE; /* ?? D3DKMDT_MOA_NONE*/
1676 ChildRelations[i].ChildCapabilities.Type.VideoOutput.SupportsSdtvModes = FALSE;
1677 ChildRelations[i].ChildCapabilities.HpdAwareness = HpdAwarenessInterruptible; /* ?? HpdAwarenessAlwaysConnected; */
1678 ChildRelations[i].AcpiUid = 0; /* */
1679 ChildRelations[i].ChildUid = i; /* should be == target id */
1680 }
1681 LOGF(("LEAVE, context(0x%x)", MiniportDeviceContext));
1682 return STATUS_SUCCESS;
1683}
1684
1685NTSTATUS DxgkDdiQueryChildStatus(
1686 IN CONST PVOID MiniportDeviceContext,
1687 IN PDXGK_CHILD_STATUS ChildStatus,
1688 IN BOOLEAN NonDestructiveOnly
1689 )
1690{
1691 /* The DxgkDdiQueryChildStatus should be made pageable. */
1692 PAGED_CODE();
1693
1694 vboxVDbgBreakFv();
1695
1696 LOGF(("ENTER, context(0x%x)", MiniportDeviceContext));
1697
1698 NTSTATUS Status = STATUS_SUCCESS;
1699 switch (ChildStatus->Type)
1700 {
1701 case StatusConnection:
1702 ChildStatus->HotPlug.Connected = TRUE;
1703 LOGF(("StatusConnection"));
1704 break;
1705 case StatusRotation:
1706 ChildStatus->Rotation.Angle = 0;
1707 LOGF(("StatusRotation"));
1708 break;
1709 default:
1710 LOGREL(("ERROR: status type: %d", ChildStatus->Type));
1711 AssertBreakpoint();
1712 Status = STATUS_INVALID_PARAMETER;
1713 break;
1714 }
1715
1716 LOGF(("LEAVE, context(0x%x)", MiniportDeviceContext));
1717
1718 return Status;
1719}
1720
1721NTSTATUS DxgkDdiQueryDeviceDescriptor(
1722 IN CONST PVOID MiniportDeviceContext,
1723 IN ULONG ChildUid,
1724 IN OUT PDXGK_DEVICE_DESCRIPTOR DeviceDescriptor
1725 )
1726{
1727 /* The DxgkDdiQueryDeviceDescriptor should be made pageable. */
1728 PAGED_CODE();
1729
1730 vboxVDbgBreakFv();
1731
1732 LOGF(("ENTER, context(0x%x)", MiniportDeviceContext));
1733
1734 LOGF(("LEAVE, context(0x%x)", MiniportDeviceContext));
1735
1736 /* we do not support EDID */
1737 return STATUS_MONITOR_NO_DESCRIPTOR;
1738}
1739
1740NTSTATUS DxgkDdiSetPowerState(
1741 IN CONST PVOID MiniportDeviceContext,
1742 IN ULONG DeviceUid,
1743 IN DEVICE_POWER_STATE DevicePowerState,
1744 IN POWER_ACTION ActionType
1745 )
1746{
1747 /* The DxgkDdiSetPowerState function should be made pageable. */
1748 PAGED_CODE();
1749
1750 LOGF(("ENTER, context(0x%x)", MiniportDeviceContext));
1751
1752 vboxVDbgBreakFv();
1753
1754 LOGF(("LEAVE, context(0x%x)", MiniportDeviceContext));
1755
1756 return STATUS_SUCCESS;
1757}
1758
1759NTSTATUS DxgkDdiNotifyAcpiEvent(
1760 IN CONST PVOID MiniportDeviceContext,
1761 IN DXGK_EVENT_TYPE EventType,
1762 IN ULONG Event,
1763 IN PVOID Argument,
1764 OUT PULONG AcpiFlags
1765 )
1766{
1767 LOGF(("ENTER, MiniportDeviceContext(0x%x)", MiniportDeviceContext));
1768
1769 vboxVDbgBreakF();
1770
1771 LOGF(("LEAVE, MiniportDeviceContext(0x%x)", MiniportDeviceContext));
1772
1773 return STATUS_SUCCESS;
1774}
1775
1776VOID DxgkDdiResetDevice(
1777 IN CONST PVOID MiniportDeviceContext
1778 )
1779{
1780 /* DxgkDdiResetDevice can be called at any IRQL, so it must be in nonpageable memory. */
1781 vboxVDbgBreakF();
1782
1783
1784
1785 LOGF(("ENTER, context(0x%x)", MiniportDeviceContext));
1786 LOGF(("LEAVE, context(0x%x)", MiniportDeviceContext));
1787}
1788
1789VOID DxgkDdiUnload(
1790 VOID
1791 )
1792{
1793 /* DxgkDdiUnload should be made pageable. */
1794 PAGED_CODE();
1795 LOGF((": unloading"));
1796
1797 vboxVDbgBreakFv();
1798
1799 VbglTerminate();
1800
1801 VBoxWddmVrTerm();
1802
1803 PRTLOGGER pLogger = RTLogRelSetDefaultInstance(NULL);
1804 if (pLogger)
1805 {
1806 RTLogDestroy(pLogger);
1807 }
1808 pLogger = RTLogSetDefaultInstance(NULL);
1809 if (pLogger)
1810 {
1811 RTLogDestroy(pLogger);
1812 }
1813}
1814
1815NTSTATUS DxgkDdiQueryInterface(
1816 IN CONST PVOID MiniportDeviceContext,
1817 IN PQUERY_INTERFACE QueryInterface
1818 )
1819{
1820 LOGF(("ENTER, MiniportDeviceContext(0x%x)", MiniportDeviceContext));
1821
1822 vboxVDbgBreakFv();
1823
1824 LOGF(("LEAVE, MiniportDeviceContext(0x%x)", MiniportDeviceContext));
1825
1826 return STATUS_NOT_SUPPORTED;
1827}
1828
1829VOID DxgkDdiControlEtwLogging(
1830 IN BOOLEAN Enable,
1831 IN ULONG Flags,
1832 IN UCHAR Level
1833 )
1834{
1835 LOGF(("ENTER"));
1836
1837 vboxVDbgBreakF();
1838
1839 LOGF(("LEAVE"));
1840}
1841
1842/**
1843 * DxgkDdiQueryAdapterInfo
1844 */
1845NTSTATUS APIENTRY DxgkDdiQueryAdapterInfo(
1846 CONST HANDLE hAdapter,
1847 CONST DXGKARG_QUERYADAPTERINFO* pQueryAdapterInfo)
1848{
1849 /* The DxgkDdiQueryAdapterInfo should be made pageable. */
1850 PAGED_CODE();
1851
1852 LOGF(("ENTER, context(0x%x), Query type (%d)", hAdapter, pQueryAdapterInfo->Type));
1853 NTSTATUS Status = STATUS_SUCCESS;
1854 PVBOXMP_DEVEXT pDevExt = (PVBOXMP_DEVEXT)hAdapter;
1855
1856 vboxVDbgBreakFv();
1857
1858 switch (pQueryAdapterInfo->Type)
1859 {
1860 case DXGKQAITYPE_DRIVERCAPS:
1861 {
1862 DXGK_DRIVERCAPS *pCaps = (DXGK_DRIVERCAPS*)pQueryAdapterInfo->pOutputData;
1863
1864#ifdef VBOX_WDDM_WIN8
1865 memset(pCaps, 0, sizeof (*pCaps));
1866#endif
1867
1868 pCaps->HighestAcceptableAddress.QuadPart = ~((uintptr_t)0);
1869 pCaps->MaxPointerWidth = VBOXWDDM_C_POINTER_MAX_WIDTH;
1870 pCaps->MaxPointerHeight = VBOXWDDM_C_POINTER_MAX_HEIGHT;
1871 pCaps->PointerCaps.Value = 3; /* Monochrome , Color*/ /* MaskedColor == Value | 4, disable for now */
1872#ifdef VBOX_WDDM_WIN8
1873 if (!g_VBoxDisplayOnly)
1874#endif
1875 {
1876 pCaps->MaxAllocationListSlotId = 16;
1877 pCaps->ApertureSegmentCommitLimit = 0;
1878 pCaps->InterruptMessageNumber = 0;
1879 pCaps->NumberOfSwizzlingRanges = 0;
1880 pCaps->MaxOverlays = 0;
1881#ifdef VBOX_WITH_VIDEOHWACCEL
1882 for (int i = 0; i < VBoxCommonFromDeviceExt(pDevExt)->cDisplays; ++i)
1883 {
1884 if ( pDevExt->aSources[i].Vhwa.Settings.fFlags & VBOXVHWA_F_ENABLED)
1885 pCaps->MaxOverlays += pDevExt->aSources[i].Vhwa.Settings.cOverlaysSupported;
1886 }
1887#endif
1888 pCaps->GammaRampCaps.Value = 0;
1889 pCaps->PresentationCaps.Value = 0;
1890 pCaps->PresentationCaps.NoScreenToScreenBlt = 1;
1891 pCaps->PresentationCaps.NoOverlapScreenBlt = 1;
1892 pCaps->MaxQueuedFlipOnVSync = 0; /* do we need it? */
1893 pCaps->FlipCaps.Value = 0;
1894 /* ? pCaps->FlipCaps.FlipOnVSyncWithNoWait = 1; */
1895 pCaps->SchedulingCaps.Value = 0;
1896 /* we might need it for Aero.
1897 * Setting this flag means we support DeviceContext, i.e.
1898 * DxgkDdiCreateContext and DxgkDdiDestroyContext
1899 */
1900 pCaps->SchedulingCaps.MultiEngineAware = 1;
1901 pCaps->MemoryManagementCaps.Value = 0;
1902 /* @todo: this correlates with pCaps->SchedulingCaps.MultiEngineAware */
1903 pCaps->MemoryManagementCaps.PagingNode = 0;
1904 /* @todo: this correlates with pCaps->SchedulingCaps.MultiEngineAware */
1905 pCaps->GpuEngineTopology.NbAsymetricProcessingNodes = VBOXWDDM_NUM_NODES;
1906#ifdef VBOX_WDDM_WIN8
1907 pCaps->WDDMVersion = DXGKDDI_WDDMv1;
1908#endif
1909 }
1910#ifdef VBOX_WDDM_WIN8
1911 else
1912 {
1913 pCaps->WDDMVersion = DXGKDDI_WDDMv1_2;
1914 }
1915#endif
1916 break;
1917 }
1918 case DXGKQAITYPE_QUERYSEGMENT:
1919 {
1920#ifdef VBOX_WDDM_WIN8
1921 if (!g_VBoxDisplayOnly)
1922#endif
1923 {
1924 /* no need for DXGK_QUERYSEGMENTIN as it contains AGP aperture info, which (AGP aperture) we do not support
1925 * DXGK_QUERYSEGMENTIN *pQsIn = (DXGK_QUERYSEGMENTIN*)pQueryAdapterInfo->pInputData; */
1926 DXGK_QUERYSEGMENTOUT *pQsOut = (DXGK_QUERYSEGMENTOUT*)pQueryAdapterInfo->pOutputData;
1927#ifdef VBOXWDDM_RENDER_FROM_SHADOW
1928# define VBOXWDDM_SEGMENTS_COUNT 2
1929#else
1930# define VBOXWDDM_SEGMENTS_COUNT 1
1931#endif
1932 if (!pQsOut->pSegmentDescriptor)
1933 {
1934 /* we are requested to provide the number of segments we support */
1935 pQsOut->NbSegment = VBOXWDDM_SEGMENTS_COUNT;
1936 }
1937 else if (pQsOut->NbSegment != VBOXWDDM_SEGMENTS_COUNT)
1938 {
1939 AssertBreakpoint();
1940 LOGREL(("NbSegment (%d) != 1", pQsOut->NbSegment));
1941 Status = STATUS_INVALID_PARAMETER;
1942 }
1943 else
1944 {
1945 DXGK_SEGMENTDESCRIPTOR* pDr = pQsOut->pSegmentDescriptor;
1946 /* we are requested to provide segment information */
1947 pDr->BaseAddress.QuadPart = 0;
1948 pDr->CpuTranslatedAddress = VBoxCommonFromDeviceExt(pDevExt)->phVRAM;
1949 /* make sure the size is page aligned */
1950 /* @todo: need to setup VBVA buffers and adjust the mem size here */
1951 pDr->Size = vboxWddmVramCpuVisibleSegmentSize(pDevExt);
1952 pDr->NbOfBanks = 0;
1953 pDr->pBankRangeTable = 0;
1954 pDr->CommitLimit = pDr->Size;
1955 pDr->Flags.Value = 0;
1956 pDr->Flags.CpuVisible = 1;
1957#ifdef VBOXWDDM_RENDER_FROM_SHADOW
1958 ++pDr;
1959 /* create cpu-invisible segment of the same size */
1960 pDr->BaseAddress.QuadPart = 0;
1961 pDr->CpuTranslatedAddress.QuadPart = 0;
1962 /* make sure the size is page aligned */
1963 /* @todo: need to setup VBVA buffers and adjust the mem size here */
1964 pDr->Size = vboxWddmVramCpuInvisibleSegmentSize(pDevExt);
1965 pDr->NbOfBanks = 0;
1966 pDr->pBankRangeTable = 0;
1967 pDr->CommitLimit = pDr->Size;
1968 pDr->Flags.Value = 0;
1969#endif
1970
1971 pQsOut->PagingBufferSegmentId = 0;
1972 pQsOut->PagingBufferSize = 1024;
1973 pQsOut->PagingBufferPrivateDataSize = 0; /* @todo: do we need a private buffer ? */
1974 }
1975 }
1976#ifdef VBOX_WDDM_WIN8
1977 else
1978 {
1979 WARN(("unsupported Type (%d)", pQueryAdapterInfo->Type));
1980 Status = STATUS_NOT_SUPPORTED;
1981 }
1982#endif
1983
1984 break;
1985 }
1986 case DXGKQAITYPE_UMDRIVERPRIVATE:
1987#ifdef VBOX_WDDM_WIN8
1988 if (!g_VBoxDisplayOnly)
1989#endif
1990 {
1991 Assert (pQueryAdapterInfo->OutputDataSize >= sizeof (VBOXWDDM_QI));
1992 if (pQueryAdapterInfo->OutputDataSize >= sizeof (VBOXWDDM_QI))
1993 {
1994 VBOXWDDM_QI * pQi = (VBOXWDDM_QI*)pQueryAdapterInfo->pOutputData;
1995 memset (pQi, 0, sizeof (VBOXWDDM_QI));
1996 pQi->u32Version = VBOXVIDEOIF_VERSION;
1997 pQi->cInfos = VBoxCommonFromDeviceExt(pDevExt)->cDisplays;
1998#ifdef VBOX_WITH_VIDEOHWACCEL
1999 for (int i = 0; i < VBoxCommonFromDeviceExt(pDevExt)->cDisplays; ++i)
2000 {
2001 pQi->aInfos[i] = pDevExt->aSources[i].Vhwa.Settings;
2002 }
2003#endif
2004 }
2005 else
2006 {
2007 LOGREL(("buffer too small"));
2008 Status = STATUS_BUFFER_TOO_SMALL;
2009 }
2010 }
2011#ifdef VBOX_WDDM_WIN8
2012 else
2013 {
2014 WARN(("unsupported Type (%d)", pQueryAdapterInfo->Type));
2015 Status = STATUS_NOT_SUPPORTED;
2016 }
2017#endif
2018 break;
2019#ifdef VBOX_WDDM_WIN8
2020 case DXGKQAITYPE_QUERYSEGMENT3:
2021 LOGREL(("DXGKQAITYPE_QUERYSEGMENT3 treating as unsupported!"));
2022 Status = STATUS_NOT_SUPPORTED;
2023 break;
2024#endif
2025 default:
2026 WARN(("unsupported Type (%d)", pQueryAdapterInfo->Type));
2027 Status = STATUS_NOT_SUPPORTED;
2028 break;
2029 }
2030 LOGF(("LEAVE, context(0x%x), Status(0x%x)", hAdapter, Status));
2031 return Status;
2032}
2033
2034/**
2035 * DxgkDdiCreateDevice
2036 */
2037NTSTATUS APIENTRY DxgkDdiCreateDevice(
2038 CONST HANDLE hAdapter,
2039 DXGKARG_CREATEDEVICE* pCreateDevice)
2040{
2041 /* DxgkDdiCreateDevice should be made pageable. */
2042 PAGED_CODE();
2043
2044 LOGF(("ENTER, context(0x%x)", hAdapter));
2045 NTSTATUS Status = STATUS_SUCCESS;
2046 PVBOXMP_DEVEXT pDevExt = (PVBOXMP_DEVEXT)hAdapter;
2047
2048 vboxVDbgBreakFv();
2049
2050 PVBOXWDDM_DEVICE pDevice = (PVBOXWDDM_DEVICE)vboxWddmMemAllocZero(sizeof (VBOXWDDM_DEVICE));
2051 pCreateDevice->hDevice = pDevice;
2052 if (pCreateDevice->Flags.SystemDevice)
2053 pDevice->enmType = VBOXWDDM_DEVICE_TYPE_SYSTEM;
2054
2055 pDevice->pAdapter = pDevExt;
2056 pDevice->hDevice = pCreateDevice->hDevice;
2057
2058 pCreateDevice->hDevice = pDevice;
2059 pCreateDevice->pInfo = NULL;
2060
2061 LOGF(("LEAVE, context(0x%x), Status(0x%x)", hAdapter, Status));
2062
2063 return Status;
2064}
2065
2066PVBOXWDDM_RESOURCE vboxWddmResourceCreate(PVBOXMP_DEVEXT pDevExt, PVBOXWDDM_RCINFO pRcInfo)
2067{
2068 PVBOXWDDM_RESOURCE pResource = (PVBOXWDDM_RESOURCE)vboxWddmMemAllocZero(RT_OFFSETOF(VBOXWDDM_RESOURCE, aAllocations[pRcInfo->cAllocInfos]));
2069 if (!pResource)
2070 {
2071 AssertFailed();
2072 return NULL;
2073 }
2074 pResource->cRefs = 1;
2075 pResource->cAllocations = pRcInfo->cAllocInfos;
2076 pResource->fFlags = pRcInfo->fFlags;
2077 pResource->RcDesc = pRcInfo->RcDesc;
2078 return pResource;
2079}
2080
2081VOID vboxWddmResourceRetain(PVBOXWDDM_RESOURCE pResource)
2082{
2083 ASMAtomicIncU32(&pResource->cRefs);
2084}
2085
2086static VOID vboxWddmResourceDestroy(PVBOXWDDM_RESOURCE pResource)
2087{
2088 vboxWddmMemFree(pResource);
2089}
2090
2091VOID vboxWddmResourceWaitDereference(PVBOXWDDM_RESOURCE pResource)
2092{
2093 vboxWddmCounterU32Wait(&pResource->cRefs, 1);
2094}
2095
2096VOID vboxWddmResourceRelease(PVBOXWDDM_RESOURCE pResource)
2097{
2098 uint32_t cRefs = ASMAtomicDecU32(&pResource->cRefs);
2099 Assert(cRefs < UINT32_MAX/2);
2100 if (!cRefs)
2101 {
2102 vboxWddmResourceDestroy(pResource);
2103 }
2104}
2105
2106void vboxWddmAllocationDeleteFromResource(PVBOXWDDM_RESOURCE pResource, PVBOXWDDM_ALLOCATION pAllocation)
2107{
2108 Assert(pAllocation->pResource == pResource);
2109 if (pResource)
2110 {
2111 Assert(&pResource->aAllocations[pAllocation->iIndex] == pAllocation);
2112 vboxWddmResourceRelease(pResource);
2113 }
2114 else
2115 {
2116 vboxWddmMemFree(pAllocation);
2117 }
2118}
2119
2120VOID vboxWddmAllocationCleanupAssignment(PVBOXMP_DEVEXT pDevExt, PVBOXWDDM_ALLOCATION pAllocation)
2121{
2122 switch (pAllocation->enmType)
2123 {
2124 case VBOXWDDM_ALLOC_TYPE_STD_SHAREDPRIMARYSURFACE:
2125 case VBOXWDDM_ALLOC_TYPE_UMD_RC_GENERIC:
2126 {
2127 if (pAllocation->bAssigned)
2128 {
2129 /* @todo: do we need to notify host? */
2130 vboxWddmAssignPrimary(pDevExt, &pDevExt->aSources[pAllocation->AllocData.SurfDesc.VidPnSourceId], NULL, pAllocation->AllocData.SurfDesc.VidPnSourceId);
2131 }
2132 break;
2133 }
2134#ifdef VBOXWDDM_RENDER_FROM_SHADOW
2135 case VBOXWDDM_ALLOC_TYPE_STD_SHADOWSURFACE:
2136 {
2137 if (pAllocation->bAssigned)
2138 {
2139 Assert(pAllocation->AllocData.SurfDesc.VidPnSourceId != D3DDDI_ID_UNINITIALIZED);
2140 /* @todo: do we need to notify host? */
2141 vboxWddmAssignShadow(pDevExt, &pDevExt->aSources[pAllocation->AllocData.SurfDesc.VidPnSourceId], NULL, pAllocation->AllocData.SurfDesc.VidPnSourceId);
2142 }
2143 break;
2144 }
2145#endif
2146 default:
2147 break;
2148 }
2149}
2150
2151VOID vboxWddmAllocationCleanup(PVBOXMP_DEVEXT pDevExt, PVBOXWDDM_ALLOCATION pAllocation)
2152{
2153 switch (pAllocation->enmType)
2154 {
2155 case VBOXWDDM_ALLOC_TYPE_STD_SHAREDPRIMARYSURFACE:
2156 case VBOXWDDM_ALLOC_TYPE_UMD_RC_GENERIC:
2157 {
2158#if 0
2159 if (pAllocation->enmType == VBOXWDDM_ALLOC_TYPE_UMD_RC_GENERIC)
2160 {
2161 if (pAllocation->hSharedHandle)
2162 {
2163 vboxShRcTreeRemove(pDevExt, pAllocation);
2164 }
2165 }
2166#endif
2167 break;
2168 }
2169 case VBOXWDDM_ALLOC_TYPE_UMD_HGSMI_BUFFER:
2170 {
2171 if (pAllocation->pSynchEvent)
2172 ObDereferenceObject(pAllocation->pSynchEvent);
2173 break;
2174 }
2175 default:
2176 break;
2177 }
2178
2179 PVBOXWDDM_SWAPCHAIN pSwapchain = vboxWddmSwapchainRetainByAlloc(pDevExt, pAllocation);
2180 if (pSwapchain)
2181 {
2182 vboxWddmSwapchainAllocRemove(pDevExt, pSwapchain, pAllocation);
2183 vboxWddmSwapchainRelease(pSwapchain);
2184 }
2185}
2186
2187VOID vboxWddmAllocationDestroy(PVBOXWDDM_ALLOCATION pAllocation)
2188{
2189 PAGED_CODE();
2190
2191 vboxWddmAllocationDeleteFromResource(pAllocation->pResource, pAllocation);
2192}
2193
2194PVBOXWDDM_ALLOCATION vboxWddmAllocationCreateFromResource(PVBOXWDDM_RESOURCE pResource, uint32_t iIndex)
2195{
2196 PVBOXWDDM_ALLOCATION pAllocation = NULL;
2197 if (pResource)
2198 {
2199 Assert(iIndex < pResource->cAllocations);
2200 if (iIndex < pResource->cAllocations)
2201 {
2202 pAllocation = &pResource->aAllocations[iIndex];
2203 memset(pAllocation, 0, sizeof (VBOXWDDM_ALLOCATION));
2204 }
2205 vboxWddmResourceRetain(pResource);
2206 }
2207 else
2208 pAllocation = (PVBOXWDDM_ALLOCATION)vboxWddmMemAllocZero(sizeof (VBOXWDDM_ALLOCATION));
2209
2210 if (pAllocation)
2211 {
2212 if (pResource)
2213 {
2214 pAllocation->pResource = pResource;
2215 pAllocation->iIndex = iIndex;
2216 }
2217 }
2218
2219 return pAllocation;
2220}
2221
2222VOID vboxWddmAllocationWaitDereference(PVBOXWDDM_ALLOCATION pAllocation)
2223{
2224 vboxWddmCounterU32Wait(&pAllocation->cRefs, 1);
2225}
2226
2227
2228NTSTATUS vboxWddmAllocationCreate(PVBOXMP_DEVEXT pDevExt, PVBOXWDDM_RESOURCE pResource, uint32_t iIndex, DXGK_ALLOCATIONINFO* pAllocationInfo)
2229{
2230 PAGED_CODE();
2231
2232 NTSTATUS Status = STATUS_SUCCESS;
2233
2234 Assert(pAllocationInfo->PrivateDriverDataSize == sizeof (VBOXWDDM_ALLOCINFO));
2235 if (pAllocationInfo->PrivateDriverDataSize >= sizeof (VBOXWDDM_ALLOCINFO))
2236 {
2237 PVBOXWDDM_ALLOCINFO pAllocInfo = (PVBOXWDDM_ALLOCINFO)pAllocationInfo->pPrivateDriverData;
2238 PVBOXWDDM_ALLOCATION pAllocation = vboxWddmAllocationCreateFromResource(pResource, iIndex);
2239 Assert(pAllocation);
2240 if (pAllocation)
2241 {
2242 pAllocationInfo->pPrivateDriverData = NULL;
2243 pAllocationInfo->PrivateDriverDataSize = 0;
2244 pAllocationInfo->Alignment = 0;
2245 pAllocationInfo->PitchAlignedSize = 0;
2246 pAllocationInfo->HintedBank.Value = 0;
2247 pAllocationInfo->PreferredSegment.Value = 0;
2248 pAllocationInfo->SupportedReadSegmentSet = 1;
2249 pAllocationInfo->SupportedWriteSegmentSet = 1;
2250 pAllocationInfo->EvictionSegmentSet = 0;
2251 pAllocationInfo->MaximumRenamingListLength = 0;
2252 pAllocationInfo->hAllocation = pAllocation;
2253 pAllocationInfo->Flags.Value = 0;
2254 pAllocationInfo->pAllocationUsageHint = NULL;
2255 pAllocationInfo->AllocationPriority = D3DDDI_ALLOCATIONPRIORITY_NORMAL;
2256
2257 pAllocation->enmType = pAllocInfo->enmType;
2258 pAllocation->AllocData.Addr.SegmentId = 0;
2259 pAllocation->AllocData.Addr.offVram = VBOXVIDEOOFFSET_VOID;
2260 pAllocation->cRefs = 1;
2261 pAllocation->bVisible = FALSE;
2262 pAllocation->bAssigned = FALSE;
2263 KeInitializeSpinLock(&pAllocation->OpenLock);
2264 InitializeListHead(&pAllocation->OpenList);
2265
2266 switch (pAllocInfo->enmType)
2267 {
2268 case VBOXWDDM_ALLOC_TYPE_STD_SHAREDPRIMARYSURFACE:
2269 case VBOXWDDM_ALLOC_TYPE_UMD_RC_GENERIC:
2270 case VBOXWDDM_ALLOC_TYPE_STD_SHADOWSURFACE:
2271 case VBOXWDDM_ALLOC_TYPE_STD_STAGINGSURFACE:
2272 {
2273 pAllocation->fRcFlags = pAllocInfo->fFlags;
2274 pAllocation->AllocData.SurfDesc = pAllocInfo->SurfDesc;
2275 pAllocation->hostID = pAllocInfo->hostID;
2276
2277 pAllocationInfo->Size = pAllocInfo->SurfDesc.cbSize;
2278
2279 switch (pAllocInfo->enmType)
2280 {
2281 case VBOXWDDM_ALLOC_TYPE_STD_SHAREDPRIMARYSURFACE:
2282#if 0 //defined(VBOXWDDM_RENDER_FROM_SHADOW)
2283 pAllocationInfo->SupportedReadSegmentSet = 2;
2284 pAllocationInfo->SupportedWriteSegmentSet = 2;
2285#endif
2286#ifndef VBOXWDDM_RENDER_FROM_SHADOW
2287 pAllocationInfo->Flags.CpuVisible = 1;
2288#endif
2289 break;
2290 case VBOXWDDM_ALLOC_TYPE_UMD_RC_GENERIC:
2291#ifdef VBOX_WITH_VIDEOHWACCEL
2292 if (pAllocInfo->fFlags.Overlay)
2293 {
2294 /* actually we can not "properly" issue create overlay commands to the host here
2295 * because we do not know source VidPn id here, i.e.
2296 * the primary which is supposed to be overlayed,
2297 * however we need to get some info like pitch & size from the host here */
2298 int rc = vboxVhwaHlpGetSurfInfo(pDevExt, pAllocation);
2299 AssertRC(rc);
2300 if (RT_SUCCESS(rc))
2301 {
2302 pAllocationInfo->Flags.Overlay = 1;
2303 pAllocationInfo->Flags.CpuVisible = 1;
2304 pAllocationInfo->Size = pAllocation->AllocData.SurfDesc.cbSize;
2305
2306 pAllocationInfo->AllocationPriority = D3DDDI_ALLOCATIONPRIORITY_HIGH;
2307 }
2308 else
2309 Status = STATUS_UNSUCCESSFUL;
2310 }
2311 else
2312#endif
2313 {
2314 Assert(pAllocation->AllocData.SurfDesc.bpp);
2315 Assert(pAllocation->AllocData.SurfDesc.pitch);
2316 Assert(pAllocation->AllocData.SurfDesc.cbSize);
2317 if (!pAllocInfo->fFlags.SharedResource)
2318 {
2319 pAllocationInfo->Flags.CpuVisible = 1;
2320 }
2321 else
2322 {
2323 pAllocation->hSharedHandle = (HANDLE)pAllocInfo->hSharedHandle;
2324#if 0
2325 if (pAllocation->hSharedHandle)
2326 {
2327 vboxShRcTreePut(pDevExt, pAllocation);
2328 }
2329#endif
2330 }
2331 }
2332 break;
2333 case VBOXWDDM_ALLOC_TYPE_STD_SHADOWSURFACE:
2334 case VBOXWDDM_ALLOC_TYPE_STD_STAGINGSURFACE:
2335 pAllocationInfo->Flags.CpuVisible = 1;
2336 break;
2337 }
2338
2339 if (Status == STATUS_SUCCESS)
2340 {
2341 pAllocation->UsageHint.Version = 0;
2342 pAllocation->UsageHint.v1.Flags.Value = 0;
2343 pAllocation->UsageHint.v1.Format = pAllocInfo->SurfDesc.format;
2344 pAllocation->UsageHint.v1.SwizzledFormat = 0;
2345 pAllocation->UsageHint.v1.ByteOffset = 0;
2346 pAllocation->UsageHint.v1.Width = pAllocation->AllocData.SurfDesc.width;
2347 pAllocation->UsageHint.v1.Height = pAllocation->AllocData.SurfDesc.height;
2348 pAllocation->UsageHint.v1.Pitch = pAllocation->AllocData.SurfDesc.pitch;
2349 pAllocation->UsageHint.v1.Depth = 0;
2350 pAllocation->UsageHint.v1.SlicePitch = 0;
2351
2352 Assert(!pAllocationInfo->pAllocationUsageHint);
2353 pAllocationInfo->pAllocationUsageHint = &pAllocation->UsageHint;
2354 }
2355
2356 break;
2357 }
2358 case VBOXWDDM_ALLOC_TYPE_UMD_HGSMI_BUFFER:
2359 {
2360 pAllocationInfo->Size = pAllocInfo->cbBuffer;
2361 pAllocation->fUhgsmiType = pAllocInfo->fUhgsmiType;
2362 pAllocation->AllocData.SurfDesc.cbSize = pAllocInfo->cbBuffer;
2363 pAllocationInfo->Flags.CpuVisible = 1;
2364// pAllocationInfo->Flags.SynchronousPaging = 1;
2365 pAllocationInfo->AllocationPriority = D3DDDI_ALLOCATIONPRIORITY_MAXIMUM;
2366 if (pAllocInfo->hSynch)
2367 {
2368 Status = ObReferenceObjectByHandle((HANDLE)pAllocInfo->hSynch, EVENT_MODIFY_STATE, *ExEventObjectType, UserMode,
2369 (PVOID*)&pAllocation->pSynchEvent,
2370 NULL);
2371 Assert(Status == STATUS_SUCCESS);
2372 }
2373 break;
2374 }
2375
2376 default:
2377 LOGREL(("ERROR: invalid alloc info type(%d)", pAllocInfo->enmType));
2378 AssertBreakpoint();
2379 Status = STATUS_INVALID_PARAMETER;
2380 break;
2381
2382 }
2383
2384 if (Status != STATUS_SUCCESS)
2385 vboxWddmAllocationDeleteFromResource(pResource, pAllocation);
2386 }
2387 else
2388 {
2389 LOGREL(("ERROR: failed to create allocation description"));
2390 Status = STATUS_NO_MEMORY;
2391 }
2392
2393 }
2394 else
2395 {
2396 LOGREL(("ERROR: PrivateDriverDataSize(%d) less than header size(%d)", pAllocationInfo->PrivateDriverDataSize, sizeof (VBOXWDDM_ALLOCINFO)));
2397 Status = STATUS_INVALID_PARAMETER;
2398 }
2399
2400 return Status;
2401}
2402
2403NTSTATUS APIENTRY DxgkDdiCreateAllocation(
2404 CONST HANDLE hAdapter,
2405 DXGKARG_CREATEALLOCATION* pCreateAllocation)
2406{
2407 /* DxgkDdiCreateAllocation should be made pageable. */
2408 PAGED_CODE();
2409
2410 LOGF(("ENTER, context(0x%x)", hAdapter));
2411
2412 vboxVDbgBreakFv();
2413
2414 PVBOXMP_DEVEXT pDevExt = (PVBOXMP_DEVEXT)hAdapter;
2415 NTSTATUS Status = STATUS_SUCCESS;
2416 PVBOXWDDM_RESOURCE pResource = NULL;
2417
2418 if (pCreateAllocation->PrivateDriverDataSize)
2419 {
2420 Assert(pCreateAllocation->PrivateDriverDataSize == sizeof (VBOXWDDM_RCINFO));
2421 Assert(pCreateAllocation->pPrivateDriverData);
2422 if (pCreateAllocation->PrivateDriverDataSize < sizeof (VBOXWDDM_RCINFO))
2423 {
2424 WARN(("invalid private data size (%d)", pCreateAllocation->PrivateDriverDataSize));
2425 return STATUS_INVALID_PARAMETER;
2426 }
2427
2428 PVBOXWDDM_RCINFO pRcInfo = (PVBOXWDDM_RCINFO)pCreateAllocation->pPrivateDriverData;
2429// Assert(pRcInfo->RcDesc.VidPnSourceId < VBoxCommonFromDeviceExt(pDevExt)->cDisplays);
2430 if (pRcInfo->cAllocInfos != pCreateAllocation->NumAllocations)
2431 {
2432 WARN(("invalid number of allocations passed in, (%d), expected (%d)", pRcInfo->cAllocInfos, pCreateAllocation->NumAllocations));
2433 return STATUS_INVALID_PARAMETER;
2434 }
2435
2436 /* a check to ensure we do not get the allocation size which is too big to overflow the 32bit value */
2437 if (VBOXWDDM_TRAILARRAY_MAXELEMENTSU32(VBOXWDDM_RESOURCE, aAllocations) < pRcInfo->cAllocInfos)
2438 {
2439 WARN(("number of allocations passed too big (%d), max is (%d)", pRcInfo->cAllocInfos, VBOXWDDM_TRAILARRAY_MAXELEMENTSU32(VBOXWDDM_RESOURCE, aAllocations)));
2440 return STATUS_INVALID_PARAMETER;
2441 }
2442
2443 pResource = (PVBOXWDDM_RESOURCE)vboxWddmMemAllocZero(RT_OFFSETOF(VBOXWDDM_RESOURCE, aAllocations[pRcInfo->cAllocInfos]));
2444 if (!pResource)
2445 {
2446 WARN(("vboxWddmMemAllocZero failed for (%d) allocations", pRcInfo->cAllocInfos));
2447 return STATUS_NO_MEMORY;
2448 }
2449
2450 pResource->cRefs = 1;
2451 pResource->cAllocations = pRcInfo->cAllocInfos;
2452 pResource->fFlags = pRcInfo->fFlags;
2453 pResource->RcDesc = pRcInfo->RcDesc;
2454 }
2455
2456
2457 for (UINT i = 0; i < pCreateAllocation->NumAllocations; ++i)
2458 {
2459 Status = vboxWddmAllocationCreate(pDevExt, pResource, i, &pCreateAllocation->pAllocationInfo[i]);
2460 if (Status != STATUS_SUCCESS)
2461 {
2462 WARN(("vboxWddmAllocationCreate(%d) failed, Status(0x%x)", i, Status));
2463 /* note: i-th allocation is expected to be cleared in a fail handling code above */
2464 for (UINT j = 0; j < i; ++j)
2465 {
2466 vboxWddmAllocationCleanup(pDevExt, (PVBOXWDDM_ALLOCATION)pCreateAllocation->pAllocationInfo[j].hAllocation);
2467 vboxWddmAllocationRelease((PVBOXWDDM_ALLOCATION)pCreateAllocation->pAllocationInfo[j].hAllocation);
2468 }
2469 }
2470 }
2471
2472 pCreateAllocation->hResource = pResource;
2473 if (pResource && Status != STATUS_SUCCESS)
2474 vboxWddmResourceRelease(pResource);
2475
2476 LOGF(("LEAVE, status(0x%x), context(0x%x)", Status, hAdapter));
2477
2478 return Status;
2479}
2480
2481NTSTATUS
2482APIENTRY
2483DxgkDdiDestroyAllocation(
2484 CONST HANDLE hAdapter,
2485 CONST DXGKARG_DESTROYALLOCATION* pDestroyAllocation)
2486{
2487 /* DxgkDdiDestroyAllocation should be made pageable. */
2488 PAGED_CODE();
2489
2490 LOGF(("ENTER, context(0x%x)", hAdapter));
2491
2492 vboxVDbgBreakFv();
2493
2494 NTSTATUS Status = STATUS_SUCCESS;
2495
2496 PVBOXWDDM_RESOURCE pRc = (PVBOXWDDM_RESOURCE)pDestroyAllocation->hResource;
2497 PVBOXMP_DEVEXT pDevExt = (PVBOXMP_DEVEXT)hAdapter;
2498
2499 if (pRc)
2500 {
2501 Assert(pRc->cAllocations == pDestroyAllocation->NumAllocations);
2502 }
2503
2504 for (UINT i = 0; i < pDestroyAllocation->NumAllocations; ++i)
2505 {
2506 PVBOXWDDM_ALLOCATION pAlloc = (PVBOXWDDM_ALLOCATION)pDestroyAllocation->pAllocationList[i];
2507 Assert(pAlloc->pResource == pRc);
2508 vboxWddmAllocationCleanupAssignment(pDevExt, pAlloc);
2509 /* wait for all current allocation-related ops are completed */
2510 vboxWddmAllocationWaitDereference(pAlloc);
2511 vboxWddmAllocationCleanup(pDevExt, pAlloc);
2512 vboxWddmAllocationRelease(pAlloc);
2513 }
2514
2515 if (pRc)
2516 {
2517 /* wait for all current resource-related ops are completed */
2518 vboxWddmResourceWaitDereference(pRc);
2519 vboxWddmResourceRelease(pRc);
2520 }
2521
2522 LOGF(("LEAVE, status(0x%x), context(0x%x)", Status, hAdapter));
2523
2524 return Status;
2525}
2526
2527/**
2528 * DxgkDdiDescribeAllocation
2529 */
2530NTSTATUS
2531APIENTRY
2532DxgkDdiDescribeAllocation(
2533 CONST HANDLE hAdapter,
2534 DXGKARG_DESCRIBEALLOCATION* pDescribeAllocation)
2535{
2536// LOGF(("ENTER, hAdapter(0x%x)", hAdapter));
2537
2538 vboxVDbgBreakFv();
2539
2540 PVBOXWDDM_ALLOCATION pAllocation = (PVBOXWDDM_ALLOCATION)pDescribeAllocation->hAllocation;
2541 pDescribeAllocation->Width = pAllocation->AllocData.SurfDesc.width;
2542 pDescribeAllocation->Height = pAllocation->AllocData.SurfDesc.height;
2543 pDescribeAllocation->Format = pAllocation->AllocData.SurfDesc.format;
2544 memset (&pDescribeAllocation->MultisampleMethod, 0, sizeof (pDescribeAllocation->MultisampleMethod));
2545 pDescribeAllocation->RefreshRate.Numerator = 60000;
2546 pDescribeAllocation->RefreshRate.Denominator = 1000;
2547 pDescribeAllocation->PrivateDriverFormatAttribute = 0;
2548
2549// LOGF(("LEAVE, hAdapter(0x%x)", hAdapter));
2550
2551 return STATUS_SUCCESS;
2552}
2553
2554/**
2555 * DxgkDdiGetStandardAllocationDriverData
2556 */
2557NTSTATUS
2558APIENTRY
2559DxgkDdiGetStandardAllocationDriverData(
2560 CONST HANDLE hAdapter,
2561 DXGKARG_GETSTANDARDALLOCATIONDRIVERDATA* pGetStandardAllocationDriverData)
2562{
2563 /* DxgkDdiGetStandardAllocationDriverData should be made pageable. */
2564 PAGED_CODE();
2565
2566 LOGF(("ENTER, context(0x%x)", hAdapter));
2567
2568 vboxVDbgBreakFv();
2569
2570 NTSTATUS Status = STATUS_SUCCESS;
2571 PVBOXWDDM_ALLOCINFO pAllocInfo = NULL;
2572
2573 switch (pGetStandardAllocationDriverData->StandardAllocationType)
2574 {
2575 case D3DKMDT_STANDARDALLOCATION_SHAREDPRIMARYSURFACE:
2576 {
2577 LOGF(("D3DKMDT_STANDARDALLOCATION_SHAREDPRIMARYSURFACE"));
2578 if(pGetStandardAllocationDriverData->pAllocationPrivateDriverData)
2579 {
2580 pAllocInfo = (PVBOXWDDM_ALLOCINFO)pGetStandardAllocationDriverData->pAllocationPrivateDriverData;
2581 memset (pAllocInfo, 0, sizeof (VBOXWDDM_ALLOCINFO));
2582 pAllocInfo->enmType = VBOXWDDM_ALLOC_TYPE_STD_SHAREDPRIMARYSURFACE;
2583 pAllocInfo->SurfDesc.width = pGetStandardAllocationDriverData->pCreateSharedPrimarySurfaceData->Width;
2584 pAllocInfo->SurfDesc.height = pGetStandardAllocationDriverData->pCreateSharedPrimarySurfaceData->Height;
2585 pAllocInfo->SurfDesc.format = pGetStandardAllocationDriverData->pCreateSharedPrimarySurfaceData->Format;
2586 pAllocInfo->SurfDesc.bpp = vboxWddmCalcBitsPerPixel(pAllocInfo->SurfDesc.format);
2587 pAllocInfo->SurfDesc.pitch = vboxWddmCalcPitch(pGetStandardAllocationDriverData->pCreateSharedPrimarySurfaceData->Width, pAllocInfo->SurfDesc.format);
2588 pAllocInfo->SurfDesc.cbSize = vboxWddmCalcSize(pAllocInfo->SurfDesc.pitch, pAllocInfo->SurfDesc.height, pAllocInfo->SurfDesc.format);
2589 pAllocInfo->SurfDesc.depth = 0;
2590 pAllocInfo->SurfDesc.slicePitch = 0;
2591 pAllocInfo->SurfDesc.RefreshRate = pGetStandardAllocationDriverData->pCreateSharedPrimarySurfaceData->RefreshRate;
2592 pAllocInfo->SurfDesc.VidPnSourceId = pGetStandardAllocationDriverData->pCreateSharedPrimarySurfaceData->VidPnSourceId;
2593 }
2594 pGetStandardAllocationDriverData->AllocationPrivateDriverDataSize = sizeof (VBOXWDDM_ALLOCINFO);
2595
2596 pGetStandardAllocationDriverData->ResourcePrivateDriverDataSize = 0;
2597 break;
2598 }
2599 case D3DKMDT_STANDARDALLOCATION_SHADOWSURFACE:
2600 {
2601 LOGF(("D3DKMDT_STANDARDALLOCATION_SHADOWSURFACE"));
2602 UINT bpp = vboxWddmCalcBitsPerPixel(pGetStandardAllocationDriverData->pCreateShadowSurfaceData->Format);
2603 Assert(bpp);
2604 if (bpp != 0)
2605 {
2606 UINT Pitch = vboxWddmCalcPitch(pGetStandardAllocationDriverData->pCreateShadowSurfaceData->Width, pGetStandardAllocationDriverData->pCreateShadowSurfaceData->Format);
2607 pGetStandardAllocationDriverData->pCreateShadowSurfaceData->Pitch = Pitch;
2608
2609 /* @todo: need [d/q]word align?? */
2610
2611 if (pGetStandardAllocationDriverData->pAllocationPrivateDriverData)
2612 {
2613 pAllocInfo = (PVBOXWDDM_ALLOCINFO)pGetStandardAllocationDriverData->pAllocationPrivateDriverData;
2614 pAllocInfo->enmType = VBOXWDDM_ALLOC_TYPE_STD_SHADOWSURFACE;
2615 pAllocInfo->SurfDesc.width = pGetStandardAllocationDriverData->pCreateShadowSurfaceData->Width;
2616 pAllocInfo->SurfDesc.height = pGetStandardAllocationDriverData->pCreateShadowSurfaceData->Height;
2617 pAllocInfo->SurfDesc.format = pGetStandardAllocationDriverData->pCreateShadowSurfaceData->Format;
2618 pAllocInfo->SurfDesc.bpp = vboxWddmCalcBitsPerPixel(pAllocInfo->SurfDesc.format);
2619 pAllocInfo->SurfDesc.pitch = vboxWddmCalcPitch(pGetStandardAllocationDriverData->pCreateShadowSurfaceData->Width, pAllocInfo->SurfDesc.format);
2620 pAllocInfo->SurfDesc.cbSize = vboxWddmCalcSize(pAllocInfo->SurfDesc.pitch, pAllocInfo->SurfDesc.height, pAllocInfo->SurfDesc.format);
2621 pAllocInfo->SurfDesc.depth = 0;
2622 pAllocInfo->SurfDesc.slicePitch = 0;
2623 pAllocInfo->SurfDesc.RefreshRate.Numerator = 0;
2624 pAllocInfo->SurfDesc.RefreshRate.Denominator = 1000;
2625 pAllocInfo->SurfDesc.VidPnSourceId = D3DDDI_ID_UNINITIALIZED;
2626
2627 pGetStandardAllocationDriverData->pCreateShadowSurfaceData->Pitch = pAllocInfo->SurfDesc.pitch;
2628 }
2629 pGetStandardAllocationDriverData->AllocationPrivateDriverDataSize = sizeof (VBOXWDDM_ALLOCINFO);
2630
2631 pGetStandardAllocationDriverData->ResourcePrivateDriverDataSize = 0;
2632 }
2633 else
2634 {
2635 LOGREL(("Invalid format (%d)", pGetStandardAllocationDriverData->pCreateShadowSurfaceData->Format));
2636 Status = STATUS_INVALID_PARAMETER;
2637 }
2638 break;
2639 }
2640 case D3DKMDT_STANDARDALLOCATION_STAGINGSURFACE:
2641 {
2642 LOGF(("D3DKMDT_STANDARDALLOCATION_STAGINGSURFACE"));
2643 if(pGetStandardAllocationDriverData->pAllocationPrivateDriverData)
2644 {
2645 pAllocInfo = (PVBOXWDDM_ALLOCINFO)pGetStandardAllocationDriverData->pAllocationPrivateDriverData;
2646 pAllocInfo->enmType = VBOXWDDM_ALLOC_TYPE_STD_STAGINGSURFACE;
2647 pAllocInfo->SurfDesc.width = pGetStandardAllocationDriverData->pCreateStagingSurfaceData->Width;
2648 pAllocInfo->SurfDesc.height = pGetStandardAllocationDriverData->pCreateStagingSurfaceData->Height;
2649 pAllocInfo->SurfDesc.format = D3DDDIFMT_X8R8G8B8; /* staging has always always D3DDDIFMT_X8R8G8B8 */
2650 pAllocInfo->SurfDesc.bpp = vboxWddmCalcBitsPerPixel(pAllocInfo->SurfDesc.format);
2651 pAllocInfo->SurfDesc.pitch = vboxWddmCalcPitch(pGetStandardAllocationDriverData->pCreateStagingSurfaceData->Width, pAllocInfo->SurfDesc.format);
2652 pAllocInfo->SurfDesc.cbSize = vboxWddmCalcSize(pAllocInfo->SurfDesc.pitch, pAllocInfo->SurfDesc.height, pAllocInfo->SurfDesc.format);
2653 pAllocInfo->SurfDesc.depth = 0;
2654 pAllocInfo->SurfDesc.slicePitch = 0;
2655 pAllocInfo->SurfDesc.RefreshRate.Numerator = 0;
2656 pAllocInfo->SurfDesc.RefreshRate.Denominator = 1000;
2657 pAllocInfo->SurfDesc.VidPnSourceId = D3DDDI_ID_UNINITIALIZED;
2658
2659 pGetStandardAllocationDriverData->pCreateStagingSurfaceData->Pitch = pAllocInfo->SurfDesc.pitch;
2660 }
2661 pGetStandardAllocationDriverData->AllocationPrivateDriverDataSize = sizeof (VBOXWDDM_ALLOCINFO);
2662
2663 pGetStandardAllocationDriverData->ResourcePrivateDriverDataSize = 0;
2664 break;
2665 }
2666//#if (DXGKDDI_INTERFACE_VERSION >= DXGKDDI_INTERFACE_VERSION_WIN7)
2667// case D3DKMDT_STANDARDALLOCATION_GDISURFACE:
2668//# error port to Win7 DDI
2669// break;
2670//#endif
2671 default:
2672 LOGREL(("Invalid allocation type (%d)", pGetStandardAllocationDriverData->StandardAllocationType));
2673 Status = STATUS_INVALID_PARAMETER;
2674 break;
2675 }
2676
2677 LOGF(("LEAVE, status(0x%x), context(0x%x)", Status, hAdapter));
2678
2679 return Status;
2680}
2681
2682NTSTATUS
2683APIENTRY
2684DxgkDdiAcquireSwizzlingRange(
2685 CONST HANDLE hAdapter,
2686 DXGKARG_ACQUIRESWIZZLINGRANGE* pAcquireSwizzlingRange)
2687{
2688 LOGF(("ENTER, hAdapter(0x%x)", hAdapter));
2689
2690 AssertBreakpoint();
2691
2692 LOGF(("LEAVE, hAdapter(0x%x)", hAdapter));
2693
2694 return STATUS_SUCCESS;
2695}
2696
2697NTSTATUS
2698APIENTRY
2699DxgkDdiReleaseSwizzlingRange(
2700 CONST HANDLE hAdapter,
2701 CONST DXGKARG_RELEASESWIZZLINGRANGE* pReleaseSwizzlingRange)
2702{
2703 LOGF(("ENTER, hAdapter(0x%x)", hAdapter));
2704
2705 AssertBreakpoint();
2706
2707 LOGF(("LEAVE, hAdapter(0x%x)", hAdapter));
2708
2709 return STATUS_SUCCESS;
2710}
2711
2712NTSTATUS
2713APIENTRY
2714DxgkDdiPatch(
2715 CONST HANDLE hAdapter,
2716 CONST DXGKARG_PATCH* pPatch)
2717{
2718 /* DxgkDdiPatch should be made pageable. */
2719 PAGED_CODE();
2720
2721 NTSTATUS Status = STATUS_SUCCESS;
2722
2723 LOGF(("ENTER, context(0x%x)", hAdapter));
2724
2725 vboxVDbgBreakFv();
2726
2727 /* Value == 2 is Present
2728 * Value == 4 is RedirectedPresent
2729 * we do not expect any other flags to be set here */
2730// Assert(pPatch->Flags.Value == 2 || pPatch->Flags.Value == 4);
2731 if (pPatch->DmaBufferPrivateDataSubmissionEndOffset - pPatch->DmaBufferPrivateDataSubmissionStartOffset >= sizeof (VBOXWDDM_DMA_PRIVATEDATA_BASEHDR))
2732 {
2733 Assert(pPatch->DmaBufferPrivateDataSize >= sizeof (VBOXWDDM_DMA_PRIVATEDATA_BASEHDR));
2734 VBOXWDDM_DMA_PRIVATEDATA_BASEHDR *pPrivateDataBase = (VBOXWDDM_DMA_PRIVATEDATA_BASEHDR*)((uint8_t*)pPatch->pDmaBufferPrivateData + pPatch->DmaBufferPrivateDataSubmissionStartOffset);
2735 switch (pPrivateDataBase->enmCmd)
2736 {
2737 case VBOXVDMACMD_TYPE_DMA_PRESENT_SHADOW2PRIMARY:
2738 {
2739 PVBOXWDDM_DMA_PRIVATEDATA_SHADOW2PRIMARY pS2P = (PVBOXWDDM_DMA_PRIVATEDATA_SHADOW2PRIMARY)pPrivateDataBase;
2740 Assert(pPatch->PatchLocationListSubmissionLength == 2);
2741 const D3DDDI_PATCHLOCATIONLIST* pPatchList = &pPatch->pPatchLocationList[pPatch->PatchLocationListSubmissionStart];
2742 Assert(pPatchList->AllocationIndex == DXGK_PRESENT_SOURCE_INDEX);
2743 Assert(pPatchList->PatchOffset == 0);
2744 const DXGK_ALLOCATIONLIST *pSrcAllocationList = &pPatch->pAllocationList[pPatchList->AllocationIndex];
2745 Assert(pSrcAllocationList->SegmentId);
2746 pS2P->Shadow2Primary.ShadowAlloc.segmentIdAlloc = pSrcAllocationList->SegmentId;
2747 pS2P->Shadow2Primary.ShadowAlloc.offAlloc = (VBOXVIDEOOFFSET)pSrcAllocationList->PhysicalAddress.QuadPart;
2748//
2749// pPatchList = &pPatch->pPatchLocationList[pPatch->PatchLocationListSubmissionStart + 1];
2750// Assert(pPatchList->AllocationIndex == DXGK_PRESENT_DESTINATION_INDEX);
2751// Assert(pPatchList->PatchOffset == 4);
2752// const DXGK_ALLOCATIONLIST *pDstAllocationList = &pPatch->pAllocationList[pPatchList->AllocationIndex];
2753// Assert(pDstAllocationList->SegmentId);
2754// pPrivateData->DstAllocInfo.segmentIdAlloc = pDstAllocationList->SegmentId;
2755// pPrivateData->DstAllocInfo.offAlloc = (VBOXVIDEOOFFSET)pDstAllocationList->PhysicalAddress.QuadPart;
2756 break;
2757 }
2758 case VBOXVDMACMD_TYPE_DMA_PRESENT_BLT:
2759 {
2760 PVBOXWDDM_DMA_PRIVATEDATA_BLT pBlt = (PVBOXWDDM_DMA_PRIVATEDATA_BLT)pPrivateDataBase;
2761 Assert(pPatch->PatchLocationListSubmissionLength == 2);
2762 const D3DDDI_PATCHLOCATIONLIST* pPatchList = &pPatch->pPatchLocationList[pPatch->PatchLocationListSubmissionStart];
2763 Assert(pPatchList->AllocationIndex == DXGK_PRESENT_SOURCE_INDEX);
2764 Assert(pPatchList->PatchOffset == 0);
2765 const DXGK_ALLOCATIONLIST *pSrcAllocationList = &pPatch->pAllocationList[pPatchList->AllocationIndex];
2766 Assert(pSrcAllocationList->SegmentId);
2767 pBlt->Blt.SrcAlloc.segmentIdAlloc = pSrcAllocationList->SegmentId;
2768 pBlt->Blt.SrcAlloc.offAlloc = (VBOXVIDEOOFFSET)pSrcAllocationList->PhysicalAddress.QuadPart;
2769
2770 pPatchList = &pPatch->pPatchLocationList[pPatch->PatchLocationListSubmissionStart + 1];
2771 Assert(pPatchList->AllocationIndex == DXGK_PRESENT_DESTINATION_INDEX);
2772 Assert(pPatchList->PatchOffset == 4);
2773 const DXGK_ALLOCATIONLIST *pDstAllocationList = &pPatch->pAllocationList[pPatchList->AllocationIndex];
2774 Assert(pDstAllocationList->SegmentId);
2775 pBlt->Blt.DstAlloc.segmentIdAlloc = pDstAllocationList->SegmentId;
2776 pBlt->Blt.DstAlloc.offAlloc = (VBOXVIDEOOFFSET)pDstAllocationList->PhysicalAddress.QuadPart;
2777 break;
2778 }
2779 case VBOXVDMACMD_TYPE_DMA_PRESENT_FLIP:
2780 {
2781 PVBOXWDDM_DMA_PRIVATEDATA_FLIP pFlip = (PVBOXWDDM_DMA_PRIVATEDATA_FLIP)pPrivateDataBase;
2782 Assert(pPatch->PatchLocationListSubmissionLength == 1);
2783 const D3DDDI_PATCHLOCATIONLIST* pPatchList = &pPatch->pPatchLocationList[pPatch->PatchLocationListSubmissionStart];
2784 Assert(pPatchList->AllocationIndex == DXGK_PRESENT_SOURCE_INDEX);
2785 Assert(pPatchList->PatchOffset == 0);
2786 const DXGK_ALLOCATIONLIST *pSrcAllocationList = &pPatch->pAllocationList[pPatchList->AllocationIndex];
2787 Assert(pSrcAllocationList->SegmentId);
2788 pFlip->Flip.Alloc.segmentIdAlloc = pSrcAllocationList->SegmentId;
2789 pFlip->Flip.Alloc.offAlloc = (VBOXVIDEOOFFSET)pSrcAllocationList->PhysicalAddress.QuadPart;
2790 break;
2791 }
2792 case VBOXVDMACMD_TYPE_DMA_PRESENT_CLRFILL:
2793 {
2794 PVBOXWDDM_DMA_PRIVATEDATA_CLRFILL pCF = (PVBOXWDDM_DMA_PRIVATEDATA_CLRFILL)pPrivateDataBase;
2795 Assert(pPatch->PatchLocationListSubmissionLength == 1);
2796 const D3DDDI_PATCHLOCATIONLIST* pPatchList = &pPatch->pPatchLocationList[pPatch->PatchLocationListSubmissionStart];
2797 Assert(pPatchList->AllocationIndex == DXGK_PRESENT_DESTINATION_INDEX);
2798 Assert(pPatchList->PatchOffset == 0);
2799 const DXGK_ALLOCATIONLIST *pDstAllocationList = &pPatch->pAllocationList[pPatchList->AllocationIndex];
2800 Assert(pDstAllocationList->SegmentId);
2801 pCF->ClrFill.Alloc.segmentIdAlloc = pDstAllocationList->SegmentId;
2802 pCF->ClrFill.Alloc.offAlloc = (VBOXVIDEOOFFSET)pDstAllocationList->PhysicalAddress.QuadPart;
2803 break;
2804 }
2805 case VBOXVDMACMD_TYPE_DMA_NOP:
2806 break;
2807 case VBOXVDMACMD_TYPE_CHROMIUM_CMD:
2808 {
2809 uint8_t * pPrivateBuf = (uint8_t*)pPrivateDataBase;
2810 for (UINT i = pPatch->PatchLocationListSubmissionStart; i < pPatch->PatchLocationListSubmissionLength; ++i)
2811 {
2812 const D3DDDI_PATCHLOCATIONLIST* pPatchList = &pPatch->pPatchLocationList[i];
2813 Assert(pPatchList->AllocationIndex < pPatch->AllocationListSize);
2814 const DXGK_ALLOCATIONLIST *pAllocationList = &pPatch->pAllocationList[pPatchList->AllocationIndex];
2815 Assert(pAllocationList->SegmentId);
2816 if (pAllocationList->SegmentId)
2817 {
2818 DXGK_ALLOCATIONLIST *pAllocation2Patch = (DXGK_ALLOCATIONLIST*)(pPrivateBuf + pPatchList->PatchOffset);
2819 pAllocation2Patch->SegmentId = pAllocationList->SegmentId;
2820 pAllocation2Patch->PhysicalAddress.QuadPart = pAllocationList->PhysicalAddress.QuadPart + pPatchList->AllocationOffset;
2821 Assert(!(pAllocationList->PhysicalAddress.QuadPart & 0xfffUL)); /* <- just a check to ensure allocation offset does not go here */
2822 }
2823 }
2824 break;
2825 }
2826 default:
2827 {
2828 AssertBreakpoint();
2829 uint8_t *pBuf = ((uint8_t *)pPatch->pDmaBuffer) + pPatch->DmaBufferSubmissionStartOffset;
2830 for (UINT i = pPatch->PatchLocationListSubmissionStart; i < pPatch->PatchLocationListSubmissionLength; ++i)
2831 {
2832 const D3DDDI_PATCHLOCATIONLIST* pPatchList = &pPatch->pPatchLocationList[i];
2833 Assert(pPatchList->AllocationIndex < pPatch->AllocationListSize);
2834 const DXGK_ALLOCATIONLIST *pAllocationList = &pPatch->pAllocationList[pPatchList->AllocationIndex];
2835 if (pAllocationList->SegmentId)
2836 {
2837 Assert(pPatchList->PatchOffset < (pPatch->DmaBufferSubmissionEndOffset - pPatch->DmaBufferSubmissionStartOffset));
2838 *((VBOXVIDEOOFFSET*)(pBuf+pPatchList->PatchOffset)) = (VBOXVIDEOOFFSET)pAllocationList->PhysicalAddress.QuadPart;
2839 }
2840 else
2841 {
2842 /* sanity */
2843 if (pPatch->Flags.Value == 2 || pPatch->Flags.Value == 4)
2844 Assert(i == 0);
2845 }
2846 }
2847 break;
2848 }
2849 }
2850 }
2851 else if (pPatch->DmaBufferPrivateDataSubmissionEndOffset == pPatch->DmaBufferPrivateDataSubmissionStartOffset)
2852 {
2853 /* this is a NOP, just return success */
2854 WARN(("null data size, treating as NOP"));
2855 return STATUS_SUCCESS;
2856 }
2857 else
2858 {
2859 WARN(("DmaBufferPrivateDataSubmissionEndOffset (%d) - DmaBufferPrivateDataSubmissionStartOffset (%d) < sizeof (VBOXWDDM_DMA_PRIVATEDATA_BASEHDR) (%d)",
2860 pPatch->DmaBufferPrivateDataSubmissionEndOffset,
2861 pPatch->DmaBufferPrivateDataSubmissionStartOffset,
2862 sizeof (VBOXWDDM_DMA_PRIVATEDATA_BASEHDR)));
2863 return STATUS_INVALID_PARAMETER;
2864 }
2865
2866 LOGF(("LEAVE, context(0x%x)", hAdapter));
2867
2868 return Status;
2869}
2870
2871typedef struct VBOXWDDM_CALL_ISR
2872{
2873 PVBOXMP_DEVEXT pDevExt;
2874 ULONG MessageNumber;
2875} VBOXWDDM_CALL_ISR, *PVBOXWDDM_CALL_ISR;
2876
2877static BOOLEAN vboxWddmCallIsrCb(PVOID Context)
2878{
2879 PVBOXWDDM_CALL_ISR pdc = (PVBOXWDDM_CALL_ISR)Context;
2880 return DxgkDdiInterruptRoutine(pdc->pDevExt, pdc->MessageNumber);
2881}
2882
2883NTSTATUS vboxWddmCallIsr(PVBOXMP_DEVEXT pDevExt)
2884{
2885 VBOXWDDM_CALL_ISR context;
2886 context.pDevExt = pDevExt;
2887 context.MessageNumber = 0;
2888 BOOLEAN bRet;
2889 NTSTATUS Status = pDevExt->u.primary.DxgkInterface.DxgkCbSynchronizeExecution(
2890 pDevExt->u.primary.DxgkInterface.DeviceHandle,
2891 vboxWddmCallIsrCb,
2892 &context,
2893 0, /* IN ULONG MessageNumber */
2894 &bRet);
2895 Assert(Status == STATUS_SUCCESS);
2896 return Status;
2897}
2898
2899static NTSTATUS vboxWddmSubmitCmd(PVBOXMP_DEVEXT pDevExt, VBOXVDMAPIPE_CMD_DMACMD *pCmd)
2900{
2901 NTSTATUS Status = vboxVdmaGgCmdDmaNotifySubmitted(pDevExt, pCmd);
2902 Assert(Status == STATUS_SUCCESS);
2903 if (Status == STATUS_SUCCESS)
2904 {
2905 NTSTATUS submStatus = vboxVdmaGgCmdSubmit(pDevExt, &pCmd->Hdr);
2906 Assert(submStatus == STATUS_SUCCESS);
2907 if (submStatus != STATUS_SUCCESS)
2908 {
2909 vboxVdmaGgCmdDmaNotifyCompleted(pDevExt, pCmd, DXGK_INTERRUPT_DMA_FAULTED);
2910 }
2911 }
2912 else
2913 {
2914 vboxVdmaGgCmdRelease(pDevExt, &pCmd->Hdr);
2915 }
2916 return Status;
2917}
2918
2919static NTSTATUS vboxWddmSubmitBltCmd(PVBOXMP_DEVEXT pDevExt, VBOXWDDM_CONTEXT *pContext, UINT u32FenceId, PVBOXWDDM_DMA_PRIVATEDATA_BLT pBlt, VBOXVDMAPIPE_FLAGS_DMACMD fBltFlags)
2920{
2921 NTSTATUS Status = STATUS_SUCCESS;
2922 PVBOXVDMAPIPE_CMD_DMACMD_BLT pBltCmd = (PVBOXVDMAPIPE_CMD_DMACMD_BLT)vboxVdmaGgCmdCreate(pDevExt, VBOXVDMAPIPE_CMD_TYPE_DMACMD, RT_OFFSETOF(VBOXVDMAPIPE_CMD_DMACMD_BLT, Blt.DstRects.UpdateRects.aRects[pBlt->Blt.DstRects.UpdateRects.cRects]));
2923 Assert(pBltCmd);
2924 if (pBltCmd)
2925 {
2926 VBOXWDDM_SOURCE *pSource = &pDevExt->aSources[pBlt->Blt.DstAlloc.srcId];
2927 vboxVdmaGgCmdDmaNotifyInit(&pBltCmd->Hdr, pContext->NodeOrdinal, u32FenceId, vboxVdmaGgDdiCmdRelease, pBltCmd);
2928 pBltCmd->Hdr.fFlags = fBltFlags;
2929 pBltCmd->Hdr.pContext = pContext;
2930 pBltCmd->Hdr.enmCmd = VBOXVDMACMD_TYPE_DMA_PRESENT_BLT;
2931 memcpy(&pBltCmd->Blt, &pBlt->Blt, RT_OFFSETOF(VBOXVDMA_BLT, DstRects.UpdateRects.aRects[pBlt->Blt.DstRects.UpdateRects.cRects]));
2932 Status = vboxWddmSubmitCmd(pDevExt, &pBltCmd->Hdr);
2933 if (Status != STATUS_SUCCESS)
2934 {
2935 WARN(("vboxWddmSubmitCmd failed, Status 0x%x", Status));
2936 Status = STATUS_SUCCESS;
2937 }
2938 vboxVdmaGgCmdRelease(pDevExt, &pBltCmd->Hdr.Hdr);
2939 }
2940 else
2941 {
2942 Status = vboxVdmaDdiCmdFenceComplete(pDevExt, pContext->NodeOrdinal, u32FenceId, DXGK_INTERRUPT_DMA_FAULTED);
2943 }
2944 return Status;
2945}
2946
2947#ifdef VBOX_WITH_CRHGSMI
2948DECLCALLBACK(VOID) vboxWddmDmaCompleteChromiumCmd(PVBOXMP_DEVEXT pDevExt, PVBOXVDMADDI_CMD pCmd, PVOID pvContext)
2949{
2950 PVBOXVDMACBUF_DR pDr = (PVBOXVDMACBUF_DR)pvContext;
2951 PVBOXVDMACMD pHdr = VBOXVDMACBUF_DR_TAIL(pDr, VBOXVDMACMD);
2952 VBOXVDMACMD_CHROMIUM_CMD *pBody = VBOXVDMACMD_BODY(pHdr, VBOXVDMACMD_CHROMIUM_CMD);
2953 UINT cBufs = pBody->cBuffers;
2954 for (UINT i = 0; i < cBufs; ++i)
2955 {
2956 VBOXVDMACMD_CHROMIUM_BUFFER *pBufCmd = &pBody->aBuffers[i];
2957 if (!pBufCmd->u32GuestData)
2958 {
2959 /* signal completion */
2960 PVBOXWDDM_ALLOCATION pAlloc = (PVBOXWDDM_ALLOCATION)pBufCmd->u64GuestData;
2961 if (pAlloc->pSynchEvent)
2962 KeSetEvent(pAlloc->pSynchEvent, 3, FALSE);
2963 }
2964 }
2965
2966 vboxVdmaCBufDrFree(&pDevExt->u.primary.Vdma, pDr);
2967}
2968#endif
2969
2970NTSTATUS
2971APIENTRY
2972DxgkDdiSubmitCommand(
2973 CONST HANDLE hAdapter,
2974 CONST DXGKARG_SUBMITCOMMAND* pSubmitCommand)
2975{
2976 /* DxgkDdiSubmitCommand runs at dispatch, should not be pageable. */
2977 NTSTATUS Status = STATUS_SUCCESS;
2978
2979// LOGF(("ENTER, context(0x%x)", hAdapter));
2980
2981 vboxVDbgBreakFv();
2982
2983 PVBOXMP_DEVEXT pDevExt = (PVBOXMP_DEVEXT)hAdapter;
2984 PVBOXWDDM_CONTEXT pContext = (PVBOXWDDM_CONTEXT)pSubmitCommand->hContext;
2985 PVBOXWDDM_DMA_PRIVATEDATA_BASEHDR pPrivateDataBase = NULL;
2986 VBOXVDMACMD_TYPE enmCmd = VBOXVDMACMD_TYPE_UNDEFINED;
2987 Assert(pContext);
2988 Assert(pContext->pDevice);
2989 Assert(pContext->pDevice->pAdapter == pDevExt);
2990 Assert(!pSubmitCommand->DmaBufferSegmentId);
2991
2992 /* the DMA command buffer is located in system RAM, the host will need to pick it from there */
2993 //BufInfo.fFlags = 0; /* see VBOXVDMACBUF_FLAG_xx */
2994 if (pSubmitCommand->DmaBufferPrivateDataSubmissionEndOffset - pSubmitCommand->DmaBufferPrivateDataSubmissionStartOffset >= sizeof (VBOXWDDM_DMA_PRIVATEDATA_BASEHDR))
2995 {
2996 pPrivateDataBase = (PVBOXWDDM_DMA_PRIVATEDATA_BASEHDR)((uint8_t*)pSubmitCommand->pDmaBufferPrivateData + pSubmitCommand->DmaBufferPrivateDataSubmissionStartOffset);
2997 Assert(pPrivateDataBase);
2998 enmCmd = pPrivateDataBase->enmCmd;
2999 }
3000 else if (pSubmitCommand->DmaBufferPrivateDataSubmissionEndOffset == pSubmitCommand->DmaBufferPrivateDataSubmissionStartOffset)
3001 {
3002 WARN(("null data size, treating as NOP"));
3003 enmCmd = VBOXVDMACMD_TYPE_DMA_NOP;
3004 }
3005 else
3006 {
3007 WARN(("DmaBufferPrivateDataSubmissionEndOffset (%d) - DmaBufferPrivateDataSubmissionStartOffset (%d) < sizeof (VBOXWDDM_DMA_PRIVATEDATA_BASEHDR) (%d)",
3008 pSubmitCommand->DmaBufferPrivateDataSubmissionEndOffset,
3009 pSubmitCommand->DmaBufferPrivateDataSubmissionStartOffset,
3010 sizeof (VBOXWDDM_DMA_PRIVATEDATA_BASEHDR)));
3011 return STATUS_INVALID_PARAMETER;
3012 }
3013
3014 if (pContext->enmType == VBOXWDDM_CONTEXT_TYPE_CUSTOM_2D)
3015 vboxWddmModeRenderFromShadowDisableRegister(pDevExt, pContext);
3016
3017 BOOLEAN fRenderFromSharedDisabled = pDevExt->fRenderToShadowDisabled;
3018
3019 switch (enmCmd)
3020 {
3021#ifdef VBOXWDDM_RENDER_FROM_SHADOW
3022 case VBOXVDMACMD_TYPE_DMA_PRESENT_SHADOW2PRIMARY:
3023 {
3024 PVBOXWDDM_DMA_PRIVATEDATA_SHADOW2PRIMARY pS2P = (PVBOXWDDM_DMA_PRIVATEDATA_SHADOW2PRIMARY)pPrivateDataBase;
3025 VBOXWDDM_SOURCE *pSource = &pDevExt->aSources[pS2P->Shadow2Primary.VidPnSourceId];
3026 PVBOXWDDM_ALLOCATION pSrcAlloc = pS2P->Shadow2Primary.ShadowAlloc.pAlloc;
3027 vboxWddmAddrSetVram(&pSrcAlloc->AllocData.Addr, pS2P->Shadow2Primary.ShadowAlloc.segmentIdAlloc, pS2P->Shadow2Primary.ShadowAlloc.offAlloc);
3028 vboxWddmAssignShadow(pDevExt, pSource, pSrcAlloc, pS2P->Shadow2Primary.VidPnSourceId);
3029 fRenderFromSharedDisabled = vboxWddmModeRenderFromShadowCheckOnSubmitCommand(pDevExt, NULL);
3030 vboxWddmCheckUpdateFramebufferAddress(pDevExt, pSource);
3031 if (pSrcAlloc->bVisible)
3032 {
3033 uint32_t cUnlockedVBVADisabled = ASMAtomicReadU32(&pDevExt->cUnlockedVBVADisabled);
3034 if (!cUnlockedVBVADisabled)
3035 VBOXVBVA_OP(ReportDirtyRect, pDevExt, pSource, &pS2P->Shadow2Primary.SrcRect);
3036 else
3037 {
3038 Assert(KeGetCurrentIrql() == DISPATCH_LEVEL);
3039 VBOXVBVA_OP_WITHLOCK_ATDPC(ReportDirtyRect, pDevExt, pSource, &pS2P->Shadow2Primary.SrcRect);
3040 }
3041 }
3042
3043 Status = vboxVdmaDdiCmdFenceComplete(pDevExt, pContext->NodeOrdinal, pSubmitCommand->SubmissionFenceId, DXGK_INTERRUPT_DMA_COMPLETED);
3044 break;
3045 }
3046#endif
3047 case VBOXVDMACMD_TYPE_DMA_PRESENT_BLT:
3048 {
3049 VBOXWDDM_DMA_PRIVATEDATA_PRESENTHDR *pPrivateData = (VBOXWDDM_DMA_PRIVATEDATA_PRESENTHDR*)pPrivateDataBase;
3050 PVBOXWDDM_DMA_PRIVATEDATA_BLT pBlt = (PVBOXWDDM_DMA_PRIVATEDATA_BLT)pPrivateData;
3051 PVBOXWDDM_ALLOCATION pDstAlloc = pBlt->Blt.DstAlloc.pAlloc;
3052 PVBOXWDDM_ALLOCATION pSrcAlloc = pBlt->Blt.SrcAlloc.pAlloc;
3053
3054 vboxWddmAddrSetVram(&pDstAlloc->AllocData.Addr, pBlt->Blt.DstAlloc.segmentIdAlloc, pBlt->Blt.DstAlloc.offAlloc);
3055 vboxWddmAddrSetVram(&pSrcAlloc->AllocData.Addr, pBlt->Blt.SrcAlloc.segmentIdAlloc, pBlt->Blt.SrcAlloc.offAlloc);
3056
3057 uint32_t cContexts3D = ASMAtomicReadU32(&pDevExt->cContexts3D);
3058
3059 VBOXVDMAPIPE_FLAGS_DMACMD fBltFlags;
3060 fBltFlags.Value = 0;
3061
3062 if (pDstAlloc->bAssigned &&
3063 (pDstAlloc->enmType == VBOXWDDM_ALLOC_TYPE_STD_SHAREDPRIMARYSURFACE
3064 || pDstAlloc->enmType == VBOXWDDM_ALLOC_TYPE_STD_SHAREDPRIMARYSURFACE)
3065 )
3066 {
3067 VBOXWDDM_SOURCE *pSource = &pDevExt->aSources[pDstAlloc->AllocData.SurfDesc.VidPnSourceId];
3068 Assert(pDstAlloc->AllocData.SurfDesc.VidPnSourceId < VBOX_VIDEO_MAX_SCREENS);
3069
3070 if (pSrcAlloc->enmType == VBOXWDDM_ALLOC_TYPE_STD_SHADOWSURFACE)
3071 vboxWddmAssignShadow(pDevExt, pSource, pSrcAlloc, pDstAlloc->AllocData.SurfDesc.VidPnSourceId);
3072 fRenderFromSharedDisabled = vboxWddmModeRenderFromShadowCheckOnSubmitCommand(pDevExt, NULL);
3073 if(pContext->enmType != VBOXWDDM_CONTEXT_TYPE_CUSTOM_3D
3074 || pDstAlloc->enmType !=VBOXWDDM_ALLOC_TYPE_UMD_RC_GENERIC)
3075 vboxWddmCheckUpdateFramebufferAddress(pDevExt, pSource);
3076 }
3077 else if (pSrcAlloc->bAssigned &&
3078 (pSrcAlloc->enmType == VBOXWDDM_ALLOC_TYPE_STD_SHAREDPRIMARYSURFACE
3079 || pSrcAlloc->enmType == VBOXWDDM_ALLOC_TYPE_STD_SHAREDPRIMARYSURFACE)
3080 )
3081 {
3082 VBOXWDDM_SOURCE *pSource = &pDevExt->aSources[pDstAlloc->AllocData.SurfDesc.VidPnSourceId];
3083 Assert(pDstAlloc->AllocData.SurfDesc.VidPnSourceId < VBOX_VIDEO_MAX_SCREENS);
3084
3085 if (pDstAlloc->enmType == VBOXWDDM_ALLOC_TYPE_STD_SHADOWSURFACE)
3086 vboxWddmAssignShadow(pDevExt, pSource, pDstAlloc, pSrcAlloc->AllocData.SurfDesc.VidPnSourceId);
3087 fRenderFromSharedDisabled = vboxWddmModeRenderFromShadowCheckOnSubmitCommand(pDevExt, NULL);
3088 if(pContext->enmType != VBOXWDDM_CONTEXT_TYPE_CUSTOM_3D
3089 || pSrcAlloc->enmType !=VBOXWDDM_ALLOC_TYPE_UMD_RC_GENERIC)
3090 vboxWddmCheckUpdateFramebufferAddress(pDevExt, pSource);
3091 }
3092
3093 if (pContext->enmType != VBOXWDDM_CONTEXT_TYPE_CUSTOM_3D && fRenderFromSharedDisabled)
3094 fBltFlags.fRealOp = 1;
3095
3096 switch (pDstAlloc->enmType)
3097 {
3098 case VBOXWDDM_ALLOC_TYPE_STD_SHAREDPRIMARYSURFACE:
3099 case VBOXWDDM_ALLOC_TYPE_UMD_RC_GENERIC:
3100 {
3101 if (pDstAlloc->bAssigned)
3102 {
3103// Assert(pSource->pPrimaryAllocation == pDstAlloc);
3104
3105 switch (pSrcAlloc->enmType)
3106 {
3107 case VBOXWDDM_ALLOC_TYPE_STD_SHADOWSURFACE:
3108 {
3109 fBltFlags.fVisibleRegions = !!cContexts3D;
3110 Assert(pContext->enmType == VBOXWDDM_CONTEXT_TYPE_SYSTEM);
3111 VBOXWDDM_SOURCE *pSource = &pDevExt->aSources[pDstAlloc->AllocData.SurfDesc.VidPnSourceId];
3112 Assert(pDstAlloc->AllocData.SurfDesc.VidPnSourceId < VBOX_VIDEO_MAX_SCREENS);
3113
3114 if (!fRenderFromSharedDisabled && pSource->bVisible)
3115 {
3116 RECT rect;
3117 if (pBlt->Blt.DstRects.UpdateRects.cRects)
3118 {
3119 rect = pBlt->Blt.DstRects.UpdateRects.aRects[0];
3120 for (UINT i = 1; i < pBlt->Blt.DstRects.UpdateRects.cRects; ++i)
3121 {
3122 vboxWddmRectUnited(&rect, &rect, &pBlt->Blt.DstRects.UpdateRects.aRects[i]);
3123 }
3124 }
3125 else
3126 rect = pBlt->Blt.DstRects.ContextRect;
3127
3128 uint32_t cUnlockedVBVADisabled = ASMAtomicReadU32(&pDevExt->cUnlockedVBVADisabled);
3129 if (!cUnlockedVBVADisabled)
3130 {
3131 VBOXVBVA_OP(ReportDirtyRect, pDevExt, pSource, &rect);
3132 }
3133 else
3134 {
3135 VBOXVBVA_OP_WITHLOCK_ATDPC(ReportDirtyRect, pDevExt, pSource, &rect);
3136 }
3137 }
3138
3139 break;
3140 }
3141 case VBOXWDDM_ALLOC_TYPE_UMD_RC_GENERIC:
3142 {
3143 if(pContext->enmType == VBOXWDDM_CONTEXT_TYPE_CUSTOM_3D)
3144 {
3145 Assert(pSrcAlloc->fRcFlags.RenderTarget);
3146 if (pSrcAlloc->fRcFlags.RenderTarget)
3147 fBltFlags.fVisibleRegions = 1;
3148 }
3149 break;
3150 }
3151 default:
3152 {
3153 AssertBreakpoint();
3154 break;
3155 }
3156 }
3157 }
3158
3159 break;
3160 }
3161 case VBOXWDDM_ALLOC_TYPE_STD_STAGINGSURFACE:
3162 {
3163// Assert(pContext->enmType == VBOXWDDM_CONTEXT_TYPE_CUSTOM_3D);
3164 Assert(pSrcAlloc->enmType == VBOXWDDM_ALLOC_TYPE_UMD_RC_GENERIC);
3165 Assert(pSrcAlloc->fRcFlags.RenderTarget);
3166 Assert(vboxWddmRectIsEqual(&pBlt->Blt.SrcRect, &pBlt->Blt.DstRects.ContextRect));
3167 Assert(pBlt->Blt.DstRects.UpdateRects.cRects == 1);
3168 Assert(vboxWddmRectIsEqual(&pBlt->Blt.SrcRect, pBlt->Blt.DstRects.UpdateRects.aRects));
3169 break;
3170 }
3171 case VBOXWDDM_ALLOC_TYPE_STD_SHADOWSURFACE:
3172 {
3173 Assert(pSrcAlloc->enmType == VBOXWDDM_ALLOC_TYPE_STD_SHAREDPRIMARYSURFACE);
3174 Assert(pContext->enmType == VBOXWDDM_CONTEXT_TYPE_SYSTEM);
3175 break;
3176 }
3177 default:
3178 AssertBreakpoint();
3179 break;
3180 }
3181
3182 if (fBltFlags.Value)
3183 {
3184 Status = vboxWddmSubmitBltCmd(pDevExt, pContext, pSubmitCommand->SubmissionFenceId, pBlt, fBltFlags);
3185 }
3186 else
3187 {
3188 Status = vboxVdmaDdiCmdFenceComplete(pDevExt, pContext->NodeOrdinal, pSubmitCommand->SubmissionFenceId, DXGK_INTERRUPT_DMA_COMPLETED);
3189 }
3190 break;
3191 }
3192 case VBOXVDMACMD_TYPE_CHROMIUM_CMD:
3193 {
3194#ifdef VBOX_WITH_CRHGSMI
3195 VBOXWDDM_DMA_PRIVATEDATA_CHROMIUM_CMD *pChromiumCmd = (VBOXWDDM_DMA_PRIVATEDATA_CHROMIUM_CMD*)pPrivateDataBase;
3196 UINT cbCmd = VBOXVDMACMD_SIZE_FROMBODYSIZE(RT_OFFSETOF(VBOXVDMACMD_CHROMIUM_CMD, aBuffers[pChromiumCmd->Base.u32CmdReserved]));
3197
3198 PVBOXVDMACBUF_DR pDr = vboxVdmaCBufDrCreate (&pDevExt->u.primary.Vdma, cbCmd);
3199 if (!pDr)
3200 {
3201 /* @todo: try flushing.. */
3202 LOGREL(("vboxVdmaCBufDrCreate returned NULL"));
3203 return STATUS_INSUFFICIENT_RESOURCES;
3204 }
3205 // vboxVdmaCBufDrCreate zero initializes the pDr
3206 pDr->fFlags = VBOXVDMACBUF_FLAG_BUF_FOLLOWS_DR;
3207 pDr->cbBuf = cbCmd;
3208 pDr->rc = VERR_NOT_IMPLEMENTED;
3209
3210 PVBOXVDMACMD pHdr = VBOXVDMACBUF_DR_TAIL(pDr, VBOXVDMACMD);
3211 pHdr->enmType = VBOXVDMACMD_TYPE_CHROMIUM_CMD;
3212 pHdr->u32CmdSpecific = 0;
3213 VBOXVDMACMD_CHROMIUM_CMD *pBody = VBOXVDMACMD_BODY(pHdr, VBOXVDMACMD_CHROMIUM_CMD);
3214 pBody->cBuffers = pChromiumCmd->Base.u32CmdReserved;
3215 for (UINT i = 0; i < pChromiumCmd->Base.u32CmdReserved; ++i)
3216 {
3217 VBOXVDMACMD_CHROMIUM_BUFFER *pBufCmd = &pBody->aBuffers[i];
3218 VBOXWDDM_UHGSMI_BUFFER_SUBMIT_INFO *pBufInfo = &pChromiumCmd->aBufInfos[i];
3219
3220 pBufCmd->offBuffer = pBufInfo->Alloc.offAlloc;
3221 pBufCmd->cbBuffer = pBufInfo->cbData;
3222 pBufCmd->u32GuestData = pBufInfo->bDoNotSignalCompletion;
3223 pBufCmd->u64GuestData = (uint64_t)pBufInfo->Alloc.pAlloc;
3224 }
3225
3226 PVBOXVDMADDI_CMD pDdiCmd = VBOXVDMADDI_CMD_FROM_BUF_DR(pDr);
3227 vboxVdmaDdiCmdInit(pDdiCmd, pContext->NodeOrdinal, pSubmitCommand->SubmissionFenceId, vboxWddmDmaCompleteChromiumCmd, pDr);
3228 NTSTATUS Status = vboxVdmaDdiCmdSubmitted(pDevExt, pDdiCmd);
3229 Assert(Status == STATUS_SUCCESS);
3230 if (Status == STATUS_SUCCESS)
3231 {
3232 int rc = vboxVdmaCBufDrSubmit(pDevExt, &pDevExt->u.primary.Vdma, pDr);
3233 Assert(rc == VINF_SUCCESS);
3234 }
3235 else
3236 {
3237 vboxVdmaCBufDrFree(&pDevExt->u.primary.Vdma, pDr);
3238 }
3239#else
3240 Status = vboxVdmaDdiCmdFenceComplete(pDevExt, pContext->NodeOrdinal, pSubmitCommand->SubmissionFenceId, DXGK_INTERRUPT_DMA_COMPLETED);
3241 Assert(Status == STATUS_SUCCESS);
3242#endif
3243 break;
3244 }
3245 case VBOXVDMACMD_TYPE_DMA_PRESENT_FLIP:
3246 {
3247 VBOXWDDM_DMA_PRIVATEDATA_FLIP *pFlip = (VBOXWDDM_DMA_PRIVATEDATA_FLIP*)pPrivateDataBase;
3248 vboxWddmAddrSetVram(&pFlip->Flip.Alloc.pAlloc->AllocData.Addr, pFlip->Flip.Alloc.segmentIdAlloc, pFlip->Flip.Alloc.offAlloc);
3249 PVBOXVDMAPIPE_CMD_DMACMD_FLIP pFlipCmd = (PVBOXVDMAPIPE_CMD_DMACMD_FLIP)vboxVdmaGgCmdCreate(pDevExt,
3250 VBOXVDMAPIPE_CMD_TYPE_DMACMD, sizeof (VBOXVDMAPIPE_CMD_DMACMD_FLIP));
3251 Assert(pFlipCmd);
3252 if (pFlipCmd)
3253 {
3254 VBOXWDDM_SOURCE *pSource = &pDevExt->aSources[pFlip->Flip.Alloc.srcId];
3255 vboxVdmaGgCmdDmaNotifyInit(&pFlipCmd->Hdr, pContext->NodeOrdinal, pSubmitCommand->SubmissionFenceId, vboxVdmaGgDdiCmdRelease, pFlipCmd);
3256 pFlipCmd->Hdr.fFlags.Value = 0;
3257 pFlipCmd->Hdr.fFlags.fVisibleRegions = 1;
3258 pFlipCmd->Hdr.pContext = pContext;
3259 pFlipCmd->Hdr.enmCmd = VBOXVDMACMD_TYPE_DMA_PRESENT_FLIP;
3260 memcpy(&pFlipCmd->Flip, &pFlip->Flip, sizeof (pFlipCmd->Flip));
3261 Status = vboxWddmSubmitCmd(pDevExt, &pFlipCmd->Hdr);
3262 if (Status != STATUS_SUCCESS)
3263 WARN(("vboxWddmSubmitCmd failed, Status 0x%x", Status));
3264 vboxVdmaGgCmdRelease(pDevExt, &pFlipCmd->Hdr.Hdr);
3265 }
3266 else
3267 {
3268 Status = vboxVdmaDdiCmdFenceComplete(pDevExt, pContext->NodeOrdinal, pSubmitCommand->SubmissionFenceId, DXGK_INTERRUPT_DMA_FAULTED);
3269 Assert(Status == STATUS_SUCCESS);
3270 }
3271 break;
3272 }
3273 case VBOXVDMACMD_TYPE_DMA_PRESENT_CLRFILL:
3274 {
3275 PVBOXWDDM_DMA_PRIVATEDATA_CLRFILL pCF = (PVBOXWDDM_DMA_PRIVATEDATA_CLRFILL)pPrivateDataBase;
3276 vboxWddmAddrSetVram(&pCF->ClrFill.Alloc.pAlloc->AllocData.Addr, pCF->ClrFill.Alloc.segmentIdAlloc, pCF->ClrFill.Alloc.offAlloc);
3277 PVBOXVDMAPIPE_CMD_DMACMD_CLRFILL pCFCmd = (PVBOXVDMAPIPE_CMD_DMACMD_CLRFILL)vboxVdmaGgCmdCreate(pDevExt,
3278 VBOXVDMAPIPE_CMD_TYPE_DMACMD, RT_OFFSETOF(VBOXVDMAPIPE_CMD_DMACMD_CLRFILL, ClrFill.Rects.aRects[pCF->ClrFill.Rects.cRects]));
3279 Assert(pCFCmd);
3280 if (pCFCmd)
3281 {
3282 vboxVdmaGgCmdDmaNotifyInit(&pCFCmd->Hdr, pContext->NodeOrdinal, pSubmitCommand->SubmissionFenceId, vboxVdmaGgDdiCmdRelease, pCFCmd);
3283 pCFCmd->Hdr.fFlags.Value = 0;
3284 pCFCmd->Hdr.fFlags.fRealOp = 1;
3285 pCFCmd->Hdr.pContext = pContext;
3286 pCFCmd->Hdr.enmCmd = VBOXVDMACMD_TYPE_DMA_PRESENT_CLRFILL;
3287 memcpy(&pCFCmd->ClrFill, &pCF->ClrFill, RT_OFFSETOF(VBOXVDMA_CLRFILL, Rects.aRects[pCF->ClrFill.Rects.cRects]));
3288 Status = vboxWddmSubmitCmd(pDevExt, &pCFCmd->Hdr);
3289 if (Status != STATUS_SUCCESS)
3290 WARN(("vboxWddmSubmitCmd failed, Status 0x%x", Status));
3291 vboxVdmaGgCmdRelease(pDevExt, &pCFCmd->Hdr.Hdr);
3292
3293 }
3294 else
3295 {
3296 Status = vboxVdmaDdiCmdFenceComplete(pDevExt, pContext->NodeOrdinal, pSubmitCommand->SubmissionFenceId, DXGK_INTERRUPT_DMA_FAULTED);
3297 Assert(Status == STATUS_SUCCESS);
3298 }
3299
3300 break;
3301 }
3302 case VBOXVDMACMD_TYPE_DMA_NOP:
3303 {
3304 Status = vboxVdmaDdiCmdFenceComplete(pDevExt, pContext->NodeOrdinal, pSubmitCommand->SubmissionFenceId, DXGK_INTERRUPT_DMA_COMPLETED);
3305 Assert(Status == STATUS_SUCCESS);
3306 break;
3307 }
3308 default:
3309 {
3310 WARN(("unexpected command %d", enmCmd));
3311#if 0 //def VBOX_WITH_VDMA
3312 VBOXWDDM_DMA_PRIVATEDATA_PRESENTHDR *pPrivateData = (VBOXWDDM_DMA_PRIVATEDATA_PRESENTHDR*)pPrivateDataBase;
3313 PVBOXVDMACBUF_DR pDr = vboxVdmaCBufDrCreate (&pDevExt->u.primary.Vdma, 0);
3314 if (!pDr)
3315 {
3316 /* @todo: try flushing.. */
3317 LOGREL(("vboxVdmaCBufDrCreate returned NULL"));
3318 return STATUS_INSUFFICIENT_RESOURCES;
3319 }
3320 // vboxVdmaCBufDrCreate zero initializes the pDr
3321 //pDr->fFlags = 0;
3322 pDr->cbBuf = pSubmitCommand->DmaBufferSubmissionEndOffset - pSubmitCommand->DmaBufferSubmissionStartOffset;
3323 pDr->u32FenceId = pSubmitCommand->SubmissionFenceId;
3324 pDr->rc = VERR_NOT_IMPLEMENTED;
3325 if (pPrivateData)
3326 pDr->u64GuestContext = (uint64_t)pPrivateData->pContext;
3327 // else // vboxVdmaCBufDrCreate zero initializes the pDr
3328 // pDr->u64GuestContext = NULL;
3329 pDr->Location.phBuf = pSubmitCommand->DmaBufferPhysicalAddress.QuadPart + pSubmitCommand->DmaBufferSubmissionStartOffset;
3330
3331 vboxVdmaCBufDrSubmit(pDevExt, &pDevExt->u.primary.Vdma, pDr);
3332#endif
3333 break;
3334 }
3335 }
3336// LOGF(("LEAVE, context(0x%x)", hAdapter));
3337
3338 return Status;
3339}
3340
3341NTSTATUS
3342APIENTRY
3343DxgkDdiPreemptCommand(
3344 CONST HANDLE hAdapter,
3345 CONST DXGKARG_PREEMPTCOMMAND* pPreemptCommand)
3346{
3347 LOGF(("ENTER, hAdapter(0x%x)", hAdapter));
3348
3349 AssertFailed();
3350 /* @todo: fixme: implement */
3351
3352 LOGF(("LEAVE, hAdapter(0x%x)", hAdapter));
3353
3354 return STATUS_SUCCESS;
3355}
3356
3357#if 0
3358static uint32_t vboxWddmSysMemElBuild(PVBOXVDMACMD_SYSMEMEL pEl, PMDL pMdl, uint32_t iPfn, uint32_t cPages, uint32_t cbBuffer, uint32_t *pcPagesRemaining)
3359{
3360 uint32_t cbInitialBuffer = cbBuffer;
3361 if (cbBuf >= sizeof (*pEl))
3362 {
3363 PFN_NUMBER cur = MmGetMdlPfnArray(pMdl)[iPfn];
3364 uint32_t cbEl = sizeof (*pEl);
3365 uint32_t cBufs = 1;
3366 pEl->phBuf[0] = (cur << 12);
3367 --cPages;
3368 cbBuffer -= sizeof (*pEl);
3369 bool bArrayMode = false;
3370 while (cPages)
3371 {
3372 PFN_NUMBER next = MmGetMdlPfnArray(pMdl)[iPfn+cBufs];
3373 if (!bArrayMode)
3374 {
3375 if (next == cur+1)
3376 {
3377 cur = next;
3378 ++cBufs;
3379 --cPages;
3380 }
3381 else if (cBufs > 1)
3382 {
3383 break;
3384 }
3385 else
3386 {
3387 bArrayMode = true;
3388 }
3389 }
3390
3391 /* array mode */
3392 if (cbBuffer < sizeof (pEl->phBuf[0]))
3393 {
3394 break;
3395 }
3396
3397 pEl->phBuf[cBufs] = (next << 12);
3398 cbBuffer -= sizeof (pEl->phBuf[0]);
3399 ++cBufs;
3400 --cPages;
3401 }
3402
3403 pEl->cPages = cPages;
3404 if (bArrayMode)
3405 pEl->fFlags = VBOXVDMACMD_SYSMEMEL_F_PAGELIST;
3406 else
3407 pEl->fFlags = 0;
3408 }
3409 else
3410 {
3411 Assert(0);
3412 }
3413
3414 *pcPagesRemaining = cPages;
3415 return cbInitialBuffer - cbBuffer;
3416}
3417
3418static uint32_t vboxWddmBpbTransferVRamSysBuildEls(PVBOXVDMACMD_DMA_BPB_TRANSFER_VRAMSYS pCmd, PMDL pMdl, uint32_t iPfn, uint32_t cPages, uint32_t cbBuffer, uint32_t *pcPagesRemaining)
3419{
3420 uint32_t cInitPages = cPages;
3421 uint32_t cbBufferUsed = vboxWddmSysMemElBuild(&pCmd->FirstEl, pMdl, iPfn, cPages, cbBuffer, &cPages);
3422 if (cbBufferUsed)
3423 {
3424 uint32_t cEls = 1;
3425 PVBOXVDMACMD_SYSMEMEL pEl = &pCmd->FirstEl;
3426 while (cPages)
3427 {
3428 PVBOXVDMACMD_SYSMEMEL pEl = VBOXVDMACMD_SYSMEMEL_NEXT(pEl);
3429 cbBufferUsed = vboxWddmSysMemElBuild(pEl, pMdl, iPfn + cInitPages - cPages, cPages, cbBuffer - cbBufferUsed, &cPages);
3430 if (cbBufferUsed)
3431 {
3432 ++cEls;
3433 }
3434 else
3435 break;
3436 }
3437 }
3438 else
3439 {
3440 Assert(0);
3441 }
3442
3443 pCmd->cTransferPages = (cInitPages - cPages);
3444 *pcPagesRemaining = cPages;
3445 return cbBufferUsed;
3446}
3447#endif
3448/*
3449 * DxgkDdiBuildPagingBuffer
3450 */
3451NTSTATUS
3452APIENTRY
3453DxgkDdiBuildPagingBuffer(
3454 CONST HANDLE hAdapter,
3455 DXGKARG_BUILDPAGINGBUFFER* pBuildPagingBuffer)
3456{
3457 /* DxgkDdiBuildPagingBuffer should be made pageable. */
3458 PAGED_CODE();
3459
3460 vboxVDbgBreakFv();
3461
3462 NTSTATUS Status = STATUS_SUCCESS;
3463 PVBOXMP_DEVEXT pDevExt = (PVBOXMP_DEVEXT)hAdapter;
3464
3465 LOGF(("ENTER, context(0x%x)", hAdapter));
3466
3467 /* @todo: */
3468 switch (pBuildPagingBuffer->Operation)
3469 {
3470 case DXGK_OPERATION_TRANSFER:
3471 {
3472#ifdef VBOX_WITH_VDMA
3473#if 0
3474 if ((!pBuildPagingBuffer->Transfer.Source.SegmentId) != (!pBuildPagingBuffer->Transfer.Destination.SegmentId))
3475 {
3476 PVBOXVDMACMD pCmd = (PVBOXVDMACMD)pBuildPagingBuffer->pDmaBuffer;
3477 pCmd->enmType = VBOXVDMACMD_TYPE_DMA_BPB_TRANSFER_VRAMSYS;
3478 pCmd->u32CmdSpecific = 0;
3479 PVBOXVDMACMD_DMA_BPB_TRANSFER_VRAMSYS pBody = VBOXVDMACMD_BODY(pCmd, VBOXVDMACMD_DMA_BPB_TRANSFER_VRAMSYS);
3480 PMDL pMdl;
3481 uint32_t cPages = (pBuildPagingBuffer->Transfer.TransferSize + 0xfff) >> 12;
3482 cPages -= pBuildPagingBuffer->MultipassOffset;
3483 uint32_t iFirstPage = pBuildPagingBuffer->Transfer.MdlOffset + pBuildPagingBuffer->MultipassOffset;
3484 uint32_t cPagesRemaining;
3485 if (pBuildPagingBuffer->Transfer.Source.SegmentId)
3486 {
3487 uint64_t off = pBuildPagingBuffer->Transfer.Source.SegmentAddress.QuadPart;
3488 off += pBuildPagingBuffer->Transfer.TransferOffset + (pBuildPagingBuffer->MultipassOffset << 12);
3489 pBody->offVramBuf = off;
3490 pMdl = pBuildPagingBuffer->Transfer.Source.pMdl;
3491 pBody->fFlags = 0;//VBOXVDMACMD_DMA_BPB_TRANSFER_VRAMSYS_SYS2VRAM
3492 }
3493 else
3494 {
3495 uint64_t off = pBuildPagingBuffer->Transfer.Destination.SegmentAddress.QuadPart;
3496 off += pBuildPagingBuffer->Transfer.TransferOffset + (pBuildPagingBuffer->MultipassOffset << 12);
3497 pBody->offVramBuf = off;
3498 pMdl = pBuildPagingBuffer->Transfer.Destination.pMdl;
3499 pBody->fFlags = VBOXVDMACMD_DMA_BPB_TRANSFER_VRAMSYS_SYS2VRAM;
3500 }
3501
3502 uint32_t sbBufferUsed = vboxWddmBpbTransferVRamSysBuildEls(pBody, pMdl, iFirstPage, cPages, pBuildPagingBuffer->DmaSize, &cPagesRemaining);
3503 Assert(sbBufferUsed);
3504 }
3505
3506#else
3507 PVBOXWDDM_ALLOCATION pAlloc = (PVBOXWDDM_ALLOCATION)pBuildPagingBuffer->Transfer.hAllocation;
3508 Assert(pAlloc);
3509 if (pAlloc
3510 && !pAlloc->fRcFlags.Overlay /* overlay surfaces actually contain a valid data */
3511 && pAlloc->enmType != VBOXWDDM_ALLOC_TYPE_STD_SHADOWSURFACE /* shadow primary - also */
3512 && pAlloc->enmType != VBOXWDDM_ALLOC_TYPE_UMD_HGSMI_BUFFER /* hgsmi buffer - also */
3513 )
3514 {
3515 /* we do not care about the others for now */
3516 Status = STATUS_SUCCESS;
3517 break;
3518 }
3519 UINT cbCmd = VBOXVDMACMD_SIZE(VBOXVDMACMD_DMA_BPB_TRANSFER);
3520 PVBOXVDMACBUF_DR pDr = vboxVdmaCBufDrCreate (&pDevExt->u.primary.Vdma, cbCmd);
3521 Assert(pDr);
3522 if (pDr)
3523 {
3524 SIZE_T cbTransfered = 0;
3525 SIZE_T cbTransferSize = pBuildPagingBuffer->Transfer.TransferSize;
3526 PVBOXVDMACMD pHdr = VBOXVDMACBUF_DR_TAIL(pDr, VBOXVDMACMD);
3527 do
3528 {
3529 // vboxVdmaCBufDrCreate zero initializes the pDr
3530 pDr->fFlags = VBOXVDMACBUF_FLAG_BUF_FOLLOWS_DR;
3531 pDr->cbBuf = cbCmd;
3532 pDr->rc = VERR_NOT_IMPLEMENTED;
3533
3534 pHdr->enmType = VBOXVDMACMD_TYPE_DMA_BPB_TRANSFER;
3535 pHdr->u32CmdSpecific = 0;
3536 VBOXVDMACMD_DMA_BPB_TRANSFER *pBody = VBOXVDMACMD_BODY(pHdr, VBOXVDMACMD_DMA_BPB_TRANSFER);
3537// pBody->cbTransferSize = (uint32_t)pBuildPagingBuffer->Transfer.TransferSize;
3538 pBody->fFlags = 0;
3539 SIZE_T cSrcPages = (cbTransferSize + 0xfff ) >> 12;
3540 SIZE_T cDstPages = cSrcPages;
3541
3542 if (pBuildPagingBuffer->Transfer.Source.SegmentId)
3543 {
3544 uint64_t off = pBuildPagingBuffer->Transfer.Source.SegmentAddress.QuadPart;
3545 off += pBuildPagingBuffer->Transfer.TransferOffset + cbTransfered;
3546 pBody->Src.offVramBuf = off;
3547 pBody->fFlags |= VBOXVDMACMD_DMA_BPB_TRANSFER_F_SRC_VRAMOFFSET;
3548 }
3549 else
3550 {
3551 UINT index = pBuildPagingBuffer->Transfer.MdlOffset + (UINT)(cbTransfered>>12);
3552 pBody->Src.phBuf = MmGetMdlPfnArray(pBuildPagingBuffer->Transfer.Source.pMdl)[index] << 12;
3553 PFN_NUMBER num = MmGetMdlPfnArray(pBuildPagingBuffer->Transfer.Source.pMdl)[index];
3554 cSrcPages = 1;
3555 for (UINT i = 1; i < ((cbTransferSize - cbTransfered + 0xfff) >> 12); ++i)
3556 {
3557 PFN_NUMBER cur = MmGetMdlPfnArray(pBuildPagingBuffer->Transfer.Source.pMdl)[index+i];
3558 if(cur != ++num)
3559 {
3560 cSrcPages+= i-1;
3561 break;
3562 }
3563 }
3564 }
3565
3566 if (pBuildPagingBuffer->Transfer.Destination.SegmentId)
3567 {
3568 uint64_t off = pBuildPagingBuffer->Transfer.Destination.SegmentAddress.QuadPart;
3569 off += pBuildPagingBuffer->Transfer.TransferOffset;
3570 pBody->Dst.offVramBuf = off + cbTransfered;
3571 pBody->fFlags |= VBOXVDMACMD_DMA_BPB_TRANSFER_F_DST_VRAMOFFSET;
3572 }
3573 else
3574 {
3575 UINT index = pBuildPagingBuffer->Transfer.MdlOffset + (UINT)(cbTransfered>>12);
3576 pBody->Dst.phBuf = MmGetMdlPfnArray(pBuildPagingBuffer->Transfer.Destination.pMdl)[index] << 12;
3577 PFN_NUMBER num = MmGetMdlPfnArray(pBuildPagingBuffer->Transfer.Destination.pMdl)[index];
3578 cDstPages = 1;
3579 for (UINT i = 1; i < ((cbTransferSize - cbTransfered + 0xfff) >> 12); ++i)
3580 {
3581 PFN_NUMBER cur = MmGetMdlPfnArray(pBuildPagingBuffer->Transfer.Destination.pMdl)[index+i];
3582 if(cur != ++num)
3583 {
3584 cDstPages+= i-1;
3585 break;
3586 }
3587 }
3588 }
3589
3590 SIZE_T cbCurTransfer;
3591 cbCurTransfer = RT_MIN(cbTransferSize - cbTransfered, cSrcPages << 12);
3592 cbCurTransfer = RT_MIN(cbCurTransfer, cDstPages << 12);
3593
3594 pBody->cbTransferSize = (UINT)cbCurTransfer;
3595 Assert(!(cbCurTransfer & 0xfff));
3596
3597 int rc = vboxVdmaCBufDrSubmitSynch(pDevExt, &pDevExt->u.primary.Vdma, pDr);
3598 AssertRC(rc);
3599 if (RT_SUCCESS(rc))
3600 {
3601 Status = STATUS_SUCCESS;
3602 cbTransfered += cbCurTransfer;
3603 }
3604 else
3605 Status = STATUS_UNSUCCESSFUL;
3606 } while (cbTransfered < cbTransferSize);
3607 Assert(cbTransfered == cbTransferSize);
3608 vboxVdmaCBufDrFree(&pDevExt->u.primary.Vdma, pDr);
3609 }
3610 else
3611 {
3612 /* @todo: try flushing.. */
3613 LOGREL(("vboxVdmaCBufDrCreate returned NULL"));
3614 Status = STATUS_INSUFFICIENT_RESOURCES;
3615 }
3616#endif
3617#endif /* #ifdef VBOX_WITH_VDMA */
3618 break;
3619 }
3620 case DXGK_OPERATION_FILL:
3621 {
3622 Assert(pBuildPagingBuffer->Fill.FillPattern == 0);
3623 PVBOXWDDM_ALLOCATION pAlloc = (PVBOXWDDM_ALLOCATION)pBuildPagingBuffer->Fill.hAllocation;
3624// pBuildPagingBuffer->pDmaBuffer = (uint8_t*)pBuildPagingBuffer->pDmaBuffer + VBOXVDMACMD_SIZE(VBOXVDMACMD_DMA_BPB_FILL);
3625 break;
3626 }
3627 case DXGK_OPERATION_DISCARD_CONTENT:
3628 {
3629// AssertBreakpoint();
3630 break;
3631 }
3632 default:
3633 {
3634 LOGREL(("unsupported op (%d)", pBuildPagingBuffer->Operation));
3635 AssertBreakpoint();
3636 break;
3637 }
3638 }
3639
3640 LOGF(("LEAVE, context(0x%x)", hAdapter));
3641
3642 return Status;
3643
3644}
3645
3646NTSTATUS
3647APIENTRY
3648DxgkDdiSetPalette(
3649 CONST HANDLE hAdapter,
3650 CONST DXGKARG_SETPALETTE* pSetPalette
3651 )
3652{
3653 LOGF(("ENTER, hAdapter(0x%x)", hAdapter));
3654
3655 AssertBreakpoint();
3656 /* @todo: fixme: implement */
3657
3658 LOGF(("LEAVE, hAdapter(0x%x)", hAdapter));
3659
3660 return STATUS_SUCCESS;
3661}
3662
3663BOOL vboxWddmPointerCopyColorData(CONST DXGKARG_SETPOINTERSHAPE* pSetPointerShape, PVIDEO_POINTER_ATTRIBUTES pPointerAttributes)
3664{
3665 ULONG srcMaskW, srcMaskH;
3666 ULONG dstBytesPerLine;
3667 ULONG x, y;
3668 BYTE *pSrc, *pDst, bit;
3669
3670 srcMaskW = pSetPointerShape->Width;
3671 srcMaskH = pSetPointerShape->Height;
3672
3673 /* truncate masks if we exceed supported size */
3674 pPointerAttributes->Width = min(srcMaskW, VBOXWDDM_C_POINTER_MAX_WIDTH);
3675 pPointerAttributes->Height = min(srcMaskH, VBOXWDDM_C_POINTER_MAX_HEIGHT);
3676 pPointerAttributes->WidthInBytes = pPointerAttributes->Width * 4;
3677
3678 /* cnstruct and mask from alpha color channel */
3679 pSrc = (PBYTE)pSetPointerShape->pPixels;
3680 pDst = pPointerAttributes->Pixels;
3681 dstBytesPerLine = (pPointerAttributes->Width+7)/8;
3682
3683 /* sanity check */
3684 uint32_t cbData = RT_ALIGN_T(dstBytesPerLine*pPointerAttributes->Height, 4, ULONG)+
3685 pPointerAttributes->Height*pPointerAttributes->WidthInBytes;
3686 uint32_t cbPointerAttributes = RT_OFFSETOF(VIDEO_POINTER_ATTRIBUTES, Pixels[cbData]);
3687 Assert(VBOXWDDM_POINTER_ATTRIBUTES_SIZE >= cbPointerAttributes);
3688 if (VBOXWDDM_POINTER_ATTRIBUTES_SIZE < cbPointerAttributes)
3689 {
3690 LOGREL(("VBOXWDDM_POINTER_ATTRIBUTES_SIZE(%d) < cbPointerAttributes(%d)", VBOXWDDM_POINTER_ATTRIBUTES_SIZE, cbPointerAttributes));
3691 return FALSE;
3692 }
3693
3694 memset(pDst, 0xFF, dstBytesPerLine*pPointerAttributes->Height);
3695 for (y=0; y<pPointerAttributes->Height; ++y)
3696 {
3697 for (x=0, bit=7; x<pPointerAttributes->Width; ++x, --bit)
3698 {
3699 if (0xFF==bit) bit=7;
3700
3701 if (pSrc[y*pSetPointerShape->Pitch + x*4 + 3] > 0x7F)
3702 {
3703 pDst[y*dstBytesPerLine + x/8] &= ~RT_BIT(bit);
3704 }
3705 }
3706 }
3707
3708 /* copy 32bpp to XOR DIB, it start in pPointerAttributes->Pixels should be 4bytes aligned */
3709 pSrc = (BYTE*)pSetPointerShape->pPixels;
3710 pDst = pPointerAttributes->Pixels + RT_ALIGN_T(dstBytesPerLine*pPointerAttributes->Height, 4, ULONG);
3711 dstBytesPerLine = pPointerAttributes->Width * 4;
3712
3713 for (y=0; y<pPointerAttributes->Height; ++y)
3714 {
3715 memcpy(pDst+y*dstBytesPerLine, pSrc+y*pSetPointerShape->Pitch, dstBytesPerLine);
3716 }
3717
3718 return TRUE;
3719}
3720
3721BOOL vboxWddmPointerCopyMonoData(CONST DXGKARG_SETPOINTERSHAPE* pSetPointerShape, PVIDEO_POINTER_ATTRIBUTES pPointerAttributes)
3722{
3723 ULONG srcMaskW, srcMaskH;
3724 ULONG dstBytesPerLine;
3725 ULONG x, y;
3726 BYTE *pSrc, *pDst, bit;
3727
3728 srcMaskW = pSetPointerShape->Width;
3729 srcMaskH = pSetPointerShape->Height;
3730
3731 /* truncate masks if we exceed supported size */
3732 pPointerAttributes->Width = min(srcMaskW, VBOXWDDM_C_POINTER_MAX_WIDTH);
3733 pPointerAttributes->Height = min(srcMaskH, VBOXWDDM_C_POINTER_MAX_HEIGHT);
3734 pPointerAttributes->WidthInBytes = pPointerAttributes->Width * 4;
3735
3736 /* copy AND mask */
3737 pSrc = (PBYTE)pSetPointerShape->pPixels;
3738 pDst = pPointerAttributes->Pixels;
3739 dstBytesPerLine = (pPointerAttributes->Width+7)/8;
3740
3741 for (y=0; y<pPointerAttributes->Height; ++y)
3742 {
3743 memcpy(pDst+y*dstBytesPerLine, pSrc+y*pSetPointerShape->Pitch, dstBytesPerLine);
3744 }
3745
3746 /* convert XOR mask to RGB0 DIB, it start in pPointerAttributes->Pixels should be 4bytes aligned */
3747 pSrc = (BYTE*)pSetPointerShape->pPixels + srcMaskH*pSetPointerShape->Pitch;
3748 pDst = pPointerAttributes->Pixels + RT_ALIGN_T(dstBytesPerLine*pPointerAttributes->Height, 4, ULONG);
3749 dstBytesPerLine = pPointerAttributes->Width * 4;
3750
3751 for (y=0; y<pPointerAttributes->Height; ++y)
3752 {
3753 for (x=0, bit=7; x<pPointerAttributes->Width; ++x, --bit)
3754 {
3755 if (0xFF==bit) bit=7;
3756
3757 *(ULONG*)&pDst[y*dstBytesPerLine+x*4] = (pSrc[y*pSetPointerShape->Pitch+x/8] & RT_BIT(bit)) ? 0x00FFFFFF : 0;
3758 }
3759 }
3760
3761 return TRUE;
3762}
3763
3764static BOOLEAN vboxVddmPointerShapeToAttributes(CONST DXGKARG_SETPOINTERSHAPE* pSetPointerShape, PVBOXWDDM_POINTER_INFO pPointerInfo)
3765{
3766 PVIDEO_POINTER_ATTRIBUTES pPointerAttributes = &pPointerInfo->Attributes.data;
3767 /* pPointerAttributes maintains the visibility state, clear all except visibility */
3768 pPointerAttributes->Enable &= VBOX_MOUSE_POINTER_VISIBLE;
3769
3770 Assert(pSetPointerShape->Flags.Value == 1 || pSetPointerShape->Flags.Value == 2);
3771 if (pSetPointerShape->Flags.Color)
3772 {
3773 if (vboxWddmPointerCopyColorData(pSetPointerShape, pPointerAttributes))
3774 {
3775 pPointerAttributes->Flags = VIDEO_MODE_COLOR_POINTER;
3776 pPointerAttributes->Enable |= VBOX_MOUSE_POINTER_ALPHA;
3777 }
3778 else
3779 {
3780 LOGREL(("vboxWddmPointerCopyColorData failed"));
3781 AssertBreakpoint();
3782 return FALSE;
3783 }
3784
3785 }
3786 else if (pSetPointerShape->Flags.Monochrome)
3787 {
3788 if (vboxWddmPointerCopyMonoData(pSetPointerShape, pPointerAttributes))
3789 {
3790 pPointerAttributes->Flags = VIDEO_MODE_MONO_POINTER;
3791 }
3792 else
3793 {
3794 LOGREL(("vboxWddmPointerCopyMonoData failed"));
3795 AssertBreakpoint();
3796 return FALSE;
3797 }
3798 }
3799 else
3800 {
3801 LOGREL(("unsupported pointer type Flags.Value(0x%x)", pSetPointerShape->Flags.Value));
3802 AssertBreakpoint();
3803 return FALSE;
3804 }
3805
3806 pPointerAttributes->Enable |= VBOX_MOUSE_POINTER_SHAPE;
3807
3808 /*
3809 * The hot spot coordinates and alpha flag will be encoded in the pPointerAttributes::Enable field.
3810 * High word will contain hot spot info and low word - flags.
3811 */
3812 pPointerAttributes->Enable |= (pSetPointerShape->YHot & 0xFF) << 24;
3813 pPointerAttributes->Enable |= (pSetPointerShape->XHot & 0xFF) << 16;
3814
3815 return TRUE;
3816}
3817
3818NTSTATUS
3819APIENTRY
3820DxgkDdiSetPointerPosition(
3821 CONST HANDLE hAdapter,
3822 CONST DXGKARG_SETPOINTERPOSITION* pSetPointerPosition)
3823{
3824// LOGF(("ENTER, hAdapter(0x%x)", hAdapter));
3825
3826 vboxVDbgBreakFv();
3827
3828 /* mouse integration is ON */
3829 PVBOXMP_DEVEXT pDevExt = (PVBOXMP_DEVEXT)hAdapter;
3830 PVBOXWDDM_POINTER_INFO pPointerInfo = &pDevExt->aSources[pSetPointerPosition->VidPnSourceId].PointerInfo;
3831 PVBOXWDDM_GLOBAL_POINTER_INFO pGlobalPointerInfo = &pDevExt->PointerInfo;
3832 PVIDEO_POINTER_ATTRIBUTES pPointerAttributes = &pPointerInfo->Attributes.data;
3833 BOOLEAN fScreenVisState = !!(pPointerAttributes->Enable & VBOX_MOUSE_POINTER_VISIBLE);
3834 BOOLEAN fVisStateChanged = FALSE;
3835 BOOLEAN fScreenChanged = pGlobalPointerInfo->iLastReportedScreen != pSetPointerPosition->VidPnSourceId;
3836
3837 if (pSetPointerPosition->Flags.Visible)
3838 {
3839 pPointerAttributes->Enable |= VBOX_MOUSE_POINTER_VISIBLE;
3840 if (!fScreenVisState)
3841 {
3842 fVisStateChanged = !!pGlobalPointerInfo->cVisible;
3843 ++pGlobalPointerInfo->cVisible;
3844 }
3845 }
3846 else
3847 {
3848 pPointerAttributes->Enable &= ~VBOX_MOUSE_POINTER_VISIBLE;
3849 if (fScreenVisState)
3850 {
3851 --pGlobalPointerInfo->cVisible;
3852 fVisStateChanged = !!pGlobalPointerInfo->cVisible;
3853 }
3854 }
3855
3856 pGlobalPointerInfo->iLastReportedScreen = pSetPointerPosition->VidPnSourceId;
3857
3858 if ((fVisStateChanged || fScreenChanged) && VBoxQueryHostWantsAbsolute())
3859 {
3860 if (fScreenChanged)
3861 {
3862 BOOLEAN bResult = VBoxMPCmnUpdatePointerShape(VBoxCommonFromDeviceExt(pDevExt), &pPointerInfo->Attributes.data, VBOXWDDM_POINTER_ATTRIBUTES_SIZE);
3863 Assert(bResult);
3864 }
3865 else
3866 {
3867 // tell the host to use the guest's pointer
3868 VIDEO_POINTER_ATTRIBUTES PointerAttributes;
3869
3870 /* Visible and No Shape means Show the pointer.
3871 * It is enough to init only this field.
3872 */
3873 PointerAttributes.Enable = pSetPointerPosition->Flags.Visible ? VBOX_MOUSE_POINTER_VISIBLE : 0;
3874
3875 BOOLEAN bResult = VBoxMPCmnUpdatePointerShape(VBoxCommonFromDeviceExt(pDevExt), &PointerAttributes, sizeof (PointerAttributes));
3876 Assert(bResult);
3877 }
3878 }
3879
3880// LOGF(("LEAVE, hAdapter(0x%x)", hAdapter));
3881
3882 return STATUS_SUCCESS;
3883}
3884
3885NTSTATUS
3886APIENTRY
3887DxgkDdiSetPointerShape(
3888 CONST HANDLE hAdapter,
3889 CONST DXGKARG_SETPOINTERSHAPE* pSetPointerShape)
3890{
3891// LOGF(("ENTER, hAdapter(0x%x)", hAdapter));
3892
3893 vboxVDbgBreakFv();
3894
3895 NTSTATUS Status = STATUS_NOT_SUPPORTED;
3896
3897 if (VBoxQueryHostWantsAbsolute())
3898 {
3899 /* mouse integration is ON */
3900 PVBOXMP_DEVEXT pDevExt = (PVBOXMP_DEVEXT)hAdapter;
3901 PVBOXWDDM_POINTER_INFO pPointerInfo = &pDevExt->aSources[pSetPointerShape->VidPnSourceId].PointerInfo;
3902 /* @todo: to avoid extra data copy and extra heap allocation,
3903 * need to maintain the pre-allocated HGSMI buffer and convert the data directly to it */
3904 if (vboxVddmPointerShapeToAttributes(pSetPointerShape, pPointerInfo))
3905 {
3906 pDevExt->PointerInfo.iLastReportedScreen = pSetPointerShape->VidPnSourceId;
3907 if (VBoxMPCmnUpdatePointerShape(VBoxCommonFromDeviceExt(pDevExt), &pPointerInfo->Attributes.data, VBOXWDDM_POINTER_ATTRIBUTES_SIZE))
3908 Status = STATUS_SUCCESS;
3909 else
3910 {
3911 AssertBreakpoint();
3912 LOGREL(("vboxUpdatePointerShape failed"));
3913 }
3914 }
3915 }
3916
3917// LOGF(("LEAVE, hAdapter(0x%x)", hAdapter));
3918
3919 return Status;
3920}
3921
3922NTSTATUS
3923APIENTRY CALLBACK
3924DxgkDdiResetFromTimeout(
3925 CONST HANDLE hAdapter)
3926{
3927 LOGF(("ENTER, hAdapter(0x%x)", hAdapter));
3928
3929 AssertBreakpoint();
3930 /* @todo: fixme: implement */
3931
3932 LOGF(("LEAVE, hAdapter(0x%x)", hAdapter));
3933
3934 return STATUS_SUCCESS;
3935}
3936
3937
3938/* the lpRgnData->Buffer comes to us as RECT
3939 * to avoid extra memcpy we cast it to PRTRECT assuming
3940 * they are identical */
3941AssertCompile(sizeof(RECT) == sizeof(RTRECT));
3942AssertCompile(RT_OFFSETOF(RECT, left) == RT_OFFSETOF(RTRECT, xLeft));
3943AssertCompile(RT_OFFSETOF(RECT, bottom) == RT_OFFSETOF(RTRECT, yBottom));
3944AssertCompile(RT_OFFSETOF(RECT, right) == RT_OFFSETOF(RTRECT, xRight));
3945AssertCompile(RT_OFFSETOF(RECT, top) == RT_OFFSETOF(RTRECT, yTop));
3946
3947NTSTATUS
3948APIENTRY
3949DxgkDdiEscape(
3950 CONST HANDLE hAdapter,
3951 CONST DXGKARG_ESCAPE* pEscape)
3952{
3953 PAGED_CODE();
3954
3955// LOGF(("ENTER, hAdapter(0x%x)", hAdapter));
3956
3957 NTSTATUS Status = STATUS_NOT_SUPPORTED;
3958 PVBOXMP_DEVEXT pDevExt = (PVBOXMP_DEVEXT)hAdapter;
3959 Assert(pEscape->PrivateDriverDataSize >= sizeof (VBOXDISPIFESCAPE));
3960 if (pEscape->PrivateDriverDataSize >= sizeof (VBOXDISPIFESCAPE))
3961 {
3962 PVBOXDISPIFESCAPE pEscapeHdr = (PVBOXDISPIFESCAPE)pEscape->pPrivateDriverData;
3963 switch (pEscapeHdr->escapeCode)
3964 {
3965#ifdef VBOX_WITH_CRHGSMI
3966 case VBOXESC_UHGSMI_SUBMIT:
3967 {
3968 /* submit VBOXUHGSMI command */
3969 PVBOXWDDM_CONTEXT pContext = (PVBOXWDDM_CONTEXT)pEscape->hContext;
3970 PVBOXDISPIFESCAPE_UHGSMI_SUBMIT pSubmit = (PVBOXDISPIFESCAPE_UHGSMI_SUBMIT)pEscapeHdr;
3971 Assert(pEscape->PrivateDriverDataSize >= sizeof (VBOXDISPIFESCAPE_UHGSMI_SUBMIT)
3972 && pEscape->PrivateDriverDataSize == RT_OFFSETOF(VBOXDISPIFESCAPE_UHGSMI_SUBMIT, aBuffers[pEscapeHdr->u32CmdSpecific]));
3973 if (pEscape->PrivateDriverDataSize >= sizeof (VBOXDISPIFESCAPE_GETVBOXVIDEOCMCMD)
3974 && pEscape->PrivateDriverDataSize == RT_OFFSETOF(VBOXDISPIFESCAPE_UHGSMI_SUBMIT, aBuffers[pEscapeHdr->u32CmdSpecific]))
3975 {
3976 Status = vboxVideoAMgrCtxAllocSubmit(pDevExt, &pContext->AllocContext, pEscapeHdr->u32CmdSpecific, pSubmit->aBuffers);
3977 Assert(Status == STATUS_SUCCESS);
3978 }
3979 else
3980 Status = STATUS_BUFFER_TOO_SMALL;
3981
3982 break;
3983 }
3984#endif
3985 case VBOXESC_UHGSMI_ALLOCATE:
3986 {
3987 /* allocate VBOXUHGSMI buffer */
3988 PVBOXWDDM_CONTEXT pContext = (PVBOXWDDM_CONTEXT)pEscape->hContext;
3989 PVBOXDISPIFESCAPE_UHGSMI_ALLOCATE pAlocate = (PVBOXDISPIFESCAPE_UHGSMI_ALLOCATE)pEscapeHdr;
3990 Assert(pEscape->PrivateDriverDataSize == sizeof (VBOXDISPIFESCAPE_UHGSMI_ALLOCATE));
3991 if (pEscape->PrivateDriverDataSize == sizeof (VBOXDISPIFESCAPE_UHGSMI_ALLOCATE))
3992 {
3993 Status = vboxVideoAMgrCtxAllocCreate(&pContext->AllocContext, &pAlocate->Alloc);
3994 Assert(Status == STATUS_SUCCESS);
3995 }
3996 else
3997 Status = STATUS_BUFFER_TOO_SMALL;
3998
3999 break;
4000 }
4001
4002 case VBOXESC_UHGSMI_DEALLOCATE:
4003 {
4004 /* deallocate VBOXUHGSMI buffer */
4005 PVBOXWDDM_CONTEXT pContext = (PVBOXWDDM_CONTEXT)pEscape->hContext;
4006 PVBOXDISPIFESCAPE_UHGSMI_DEALLOCATE pDealocate = (PVBOXDISPIFESCAPE_UHGSMI_DEALLOCATE)pEscapeHdr;
4007 Assert(pEscape->PrivateDriverDataSize == sizeof (VBOXDISPIFESCAPE_UHGSMI_DEALLOCATE));
4008 if (pEscape->PrivateDriverDataSize == sizeof (VBOXDISPIFESCAPE_UHGSMI_DEALLOCATE))
4009 {
4010 Status = vboxVideoAMgrCtxAllocDestroy(&pContext->AllocContext, pDealocate->hAlloc);
4011 Assert(Status == STATUS_SUCCESS);
4012 }
4013 else
4014 Status = STATUS_BUFFER_TOO_SMALL;
4015
4016 break;
4017 }
4018
4019 case VBOXESC_GETVBOXVIDEOCMCMD:
4020 {
4021 /* get the list of r0->r3 commands (d3d window visible regions reporting )*/
4022 PVBOXWDDM_CONTEXT pContext = (PVBOXWDDM_CONTEXT)pEscape->hContext;
4023 PVBOXDISPIFESCAPE_GETVBOXVIDEOCMCMD pRegions = (PVBOXDISPIFESCAPE_GETVBOXVIDEOCMCMD)pEscapeHdr;
4024 Assert(pEscape->PrivateDriverDataSize >= sizeof (VBOXDISPIFESCAPE_GETVBOXVIDEOCMCMD));
4025 if (pEscape->PrivateDriverDataSize >= sizeof (VBOXDISPIFESCAPE_GETVBOXVIDEOCMCMD))
4026 {
4027 if (pContext->enmType == VBOXWDDM_CONTEXT_TYPE_CUSTOM_3D)
4028 {
4029 Status = vboxVideoCmEscape(&pContext->CmContext, pRegions, pEscape->PrivateDriverDataSize);
4030 Assert(Status == STATUS_SUCCESS);
4031 }
4032 else
4033 {
4034 WARN(("VBOXESC_GETVBOXVIDEOCMCMD recieved invalid context type %d", pContext->enmType));
4035 Status = STATUS_INVALID_PARAMETER;
4036 }
4037 }
4038 else
4039 Status = STATUS_BUFFER_TOO_SMALL;
4040
4041 break;
4042 }
4043
4044 case VBOXESC_CRHGSMICTLCON_CALL:
4045 {
4046 PVBOXWDDM_CONTEXT pContext = (PVBOXWDDM_CONTEXT)pEscape->hContext;
4047 PVBOXDISPIFESCAPE_CRHGSMICTLCON_CALL pCall = (PVBOXDISPIFESCAPE_CRHGSMICTLCON_CALL)pEscapeHdr;
4048 if (pEscape->PrivateDriverDataSize >= sizeof (*pCall))
4049 {
4050 /* this is true due to the above condition */
4051 Assert(pEscape->PrivateDriverDataSize > RT_OFFSETOF(VBOXDISPIFESCAPE_CRHGSMICTLCON_CALL, CallInfo));
4052 int rc = VBoxMpCrCtlConCallUserData(&pDevExt->CrCtlCon, &pCall->CallInfo, pEscape->PrivateDriverDataSize - RT_OFFSETOF(VBOXDISPIFESCAPE_CRHGSMICTLCON_CALL, CallInfo));
4053 pEscapeHdr->u32CmdSpecific = (uint32_t)rc;
4054 Status = STATUS_SUCCESS; /* <- always return success here, otherwise the private data buffer modifications
4055 * i.e. rc status stored in u32CmdSpecific will not be copied to user mode */
4056 if (!RT_SUCCESS(rc))
4057 WARN(("VBoxMpCrUmCtlConCall failed, rc(%d)", rc));
4058 }
4059 else
4060 {
4061 WARN(("buffer too small!"));
4062 Status = STATUS_BUFFER_TOO_SMALL;
4063 }
4064
4065 break;
4066 }
4067
4068 case VBOXESC_CRHGSMICTLCON_GETCLIENTID:
4069 {
4070 PVBOXWDDM_CONTEXT pContext = (PVBOXWDDM_CONTEXT)pEscape->hContext;
4071 if (pEscape->PrivateDriverDataSize == sizeof (*pEscapeHdr))
4072 {
4073 pEscapeHdr->u32CmdSpecific = pContext->u32CrConClientID;
4074 Status = STATUS_SUCCESS;
4075 }
4076 else
4077 {
4078 WARN(("unexpected buffer size!"));
4079 Status = STATUS_INVALID_PARAMETER;
4080 }
4081
4082 break;
4083 }
4084
4085 case VBOXESC_SETVISIBLEREGION:
4086 {
4087 /* visible regions for seamless */
4088 LPRGNDATA lpRgnData = VBOXDISPIFESCAPE_DATA(pEscapeHdr, RGNDATA);
4089 uint32_t cbData = VBOXDISPIFESCAPE_DATA_SIZE(pEscape->PrivateDriverDataSize);
4090 uint32_t cbRects = cbData - RT_OFFSETOF(RGNDATA, Buffer);
4091 /* the lpRgnData->Buffer comes to us as RECT
4092 * to avoid extra memcpy we cast it to PRTRECT assuming
4093 * they are identical
4094 * see AssertCompile's above */
4095
4096 RTRECT *pRect = (RTRECT *)&lpRgnData->Buffer;
4097
4098 uint32_t cRects = cbRects/sizeof(RTRECT);
4099 int rc;
4100
4101 LOG(("IOCTL_VIDEO_VBOX_SETVISIBLEREGION cRects=%d", cRects));
4102 Assert(cbRects >= sizeof(RTRECT)
4103 && cbRects == cRects*sizeof(RTRECT)
4104 && cRects == lpRgnData->rdh.nCount);
4105 if ( cbRects >= sizeof(RTRECT)
4106 && cbRects == cRects*sizeof(RTRECT)
4107 && cRects == lpRgnData->rdh.nCount)
4108 {
4109 /*
4110 * Inform the host about the visible region
4111 */
4112 VMMDevVideoSetVisibleRegion *req = NULL;
4113
4114 rc = VbglGRAlloc ((VMMDevRequestHeader **)&req,
4115 sizeof (VMMDevVideoSetVisibleRegion) + (cRects-1)*sizeof(RTRECT),
4116 VMMDevReq_VideoSetVisibleRegion);
4117 AssertRC(rc);
4118 if (RT_SUCCESS(rc))
4119 {
4120 req->cRect = cRects;
4121 memcpy(&req->Rect, pRect, cRects*sizeof(RTRECT));
4122
4123 rc = VbglGRPerform (&req->header);
4124 AssertRC(rc);
4125 if (!RT_SUCCESS(rc))
4126 {
4127 LOGREL(("VbglGRPerform failed rc (%d)", rc));
4128 Status = STATUS_UNSUCCESSFUL;
4129 }
4130 }
4131 else
4132 {
4133 LOGREL(("VbglGRAlloc failed rc (%d)", rc));
4134 Status = STATUS_UNSUCCESSFUL;
4135 }
4136 }
4137 else
4138 {
4139 LOGREL(("VBOXESC_SETVISIBLEREGION: incorrect buffer size (%d), reported count (%d)", cbRects, lpRgnData->rdh.nCount));
4140 AssertBreakpoint();
4141 Status = STATUS_INVALID_PARAMETER;
4142 }
4143 break;
4144 }
4145 case VBOXESC_ISVRDPACTIVE:
4146 /* @todo: implement */
4147 Status = STATUS_SUCCESS;
4148 break;
4149 case VBOXESC_SCREENLAYOUT:
4150 {
4151 /* set screen layout (unused currently) */
4152 if (pEscape->PrivateDriverDataSize < sizeof (VBOXDISPIFESCAPE_SCREENLAYOUT))
4153 {
4154 WARN(("VBOXESC_SCREENLAYOUT: incorrect buffer size (%d) < sizeof (VBOXDISPIFESCAPE_SCREENLAYOUT) (%d)",
4155 pEscape->PrivateDriverDataSize, sizeof (VBOXDISPIFESCAPE_SCREENLAYOUT)));
4156 Status = STATUS_INVALID_PARAMETER;
4157 break;
4158 }
4159
4160 PVBOXDISPIFESCAPE_SCREENLAYOUT pLo = (PVBOXDISPIFESCAPE_SCREENLAYOUT)pEscapeHdr;
4161 if (pLo->ScreenLayout.cScreens > (UINT)VBoxCommonFromDeviceExt(pDevExt)->cDisplays)
4162 {
4163 WARN(("VBOXESC_SCREENLAYOUT: number of screens too big (%d), should be <= (%d)",
4164 pLo->ScreenLayout.cScreens, VBoxCommonFromDeviceExt(pDevExt)->cDisplays));
4165 Status = STATUS_INVALID_PARAMETER;
4166 break;
4167 }
4168
4169 for (UINT i = 0; i < pLo->ScreenLayout.cScreens; ++i)
4170 {
4171 PVBOXSCREENLAYOUT_ELEMENT pEl = &pLo->ScreenLayout.aScreens[i];
4172 Assert(pEl->VidPnSourceId < (UINT)VBoxCommonFromDeviceExt(pDevExt)->cDisplays);
4173 if (pEl->VidPnSourceId < (UINT)VBoxCommonFromDeviceExt(pDevExt)->cDisplays)
4174 {
4175 PVBOXWDDM_SOURCE pSource = &pDevExt->aSources[pEl->VidPnSourceId];
4176 NTSTATUS tmpStatus = vboxWddmGhDisplayUpdateScreenPos(pDevExt, pSource, &pEl->pos);
4177 Assert(tmpStatus == STATUS_SUCCESS);
4178 }
4179 }
4180
4181 Status = STATUS_SUCCESS;
4182 break;
4183 }
4184 case VBOXESC_SWAPCHAININFO:
4185 {
4186 /* set swapchain information */
4187 PVBOXWDDM_CONTEXT pContext = (PVBOXWDDM_CONTEXT)pEscape->hContext;
4188 Status = vboxWddmSwapchainCtxEscape(pDevExt, pContext, (PVBOXDISPIFESCAPE_SWAPCHAININFO)pEscapeHdr, pEscape->PrivateDriverDataSize);
4189 Assert(Status == STATUS_SUCCESS);
4190 break;
4191 }
4192 case VBOXESC_REINITVIDEOMODES:
4193 {
4194 if (pEscape->Flags.HardwareAccess)
4195 {
4196 WARN(("VBOXESC_REINITVIDEOMODES called with HardwareAccess flag set, failing"));
4197 Status = STATUS_INVALID_PARAMETER;
4198 break;
4199 }
4200 WARN(("VBOXESC_REINITVIDEOMODESBYMASK should be called instead"));
4201 PVBOXWDDM_VIDEOMODES_INFO pInfos = VBoxWddmUpdateAllVideoModesInfos(pDevExt);
4202 Status = vboxWddmChildStatusCheckByMask(pDevExt, pInfos, NULL);
4203 if (!NT_SUCCESS(Status))
4204 {
4205 WARN(("vboxWddmChildStatusCheckByMask failed, Status 0x%x", Status));
4206 }
4207 break;
4208 }
4209 case VBOXESC_REINITVIDEOMODESBYMASK:
4210 {
4211 BOOLEAN fCheckDisplayRecconect = (pEscapeHdr->u32CmdSpecific & VBOXWDDM_REINITVIDEOMODESBYMASK_F_RECONNECT_DISPLAYS_ON_CHANGE);
4212 if (fCheckDisplayRecconect && pEscape->Flags.HardwareAccess)
4213 {
4214 WARN(("VBOXESC_REINITVIDEOMODESBYMASK called with HardwareAccess flag set, failing"));
4215 Status = STATUS_INVALID_PARAMETER;
4216 break;
4217 }
4218 if (pEscape->PrivateDriverDataSize != sizeof (VBOXDISPIFESCAPE_REINITVIDEOMODESBYMASK))
4219 {
4220 WARN(("invalid private driver size %d", pEscape->PrivateDriverDataSize));
4221 Status = STATUS_INVALID_PARAMETER;
4222 break;
4223 }
4224 LOG(("=> VBOXESC_REINITVIDEOMODESBYMASK"));
4225 PVBOXDISPIFESCAPE_REINITVIDEOMODESBYMASK pData = (PVBOXDISPIFESCAPE_REINITVIDEOMODESBYMASK)pEscapeHdr;
4226 PVBOXWDDM_VIDEOMODES_INFO pInfos = VBoxWddmUpdateVideoModesInfoByMask(pDevExt, pData->ScreenMask);
4227 if (fCheckDisplayRecconect)
4228 {
4229 Status = vboxWddmChildStatusCheckByMask(pDevExt, pInfos, pData->ScreenMask);
4230 if (!NT_SUCCESS(Status))
4231 {
4232 WARN(("vboxWddmChildStatusCheckByMask failed, Status 0x%x", Status));
4233 }
4234 }
4235 LOG(("<= VBOXESC_REINITVIDEOMODESBYMASK"));
4236 break;
4237 }
4238 case VBOXESC_ADJUSTVIDEOMODES:
4239 {
4240 if (!pEscape->Flags.HardwareAccess)
4241 {
4242 WARN(("VBOXESC_ADJUSTVIDEOMODES called without HardwareAccess flag set, failing"));
4243 Status = STATUS_INVALID_PARAMETER;
4244 break;
4245 }
4246
4247 uint32_t cModes = pEscapeHdr->u32CmdSpecific;
4248 if (cModes > VBOXWDDM_TRAILARRAY_MAXELEMENTSU32(VBOXDISPIFESCAPE_ADJUSTVIDEOMODES, aScreenInfos)
4249 || pEscape->PrivateDriverDataSize != RT_OFFSETOF(VBOXDISPIFESCAPE_ADJUSTVIDEOMODES, aScreenInfos[cModes]))
4250 {
4251 WARN(("invalid modes count passed"));
4252 Status = STATUS_INVALID_PARAMETER;
4253 break;
4254 }
4255
4256 PVBOXDISPIFESCAPE_ADJUSTVIDEOMODES pPodesInfo = (PVBOXDISPIFESCAPE_ADJUSTVIDEOMODES)pEscapeHdr;
4257 VBoxWddmAdjustModes(pDevExt, cModes, pPodesInfo->aScreenInfos);
4258 Status = STATUS_SUCCESS;
4259 break;
4260 }
4261 case VBOXESC_SHRC_ADDREF:
4262 case VBOXESC_SHRC_RELEASE:
4263 {
4264 PVBOXWDDM_DEVICE pDevice = (PVBOXWDDM_DEVICE)pEscape->hDevice;
4265 /* query whether the allocation represanted by the given [wine-generated] shared resource handle still exists */
4266 if (pEscape->PrivateDriverDataSize != sizeof (VBOXDISPIFESCAPE_SHRC_REF))
4267 {
4268 WARN(("invalid buffer size for VBOXDISPIFESCAPE_SHRC_REF, was(%d), but expected (%d)",
4269 pEscape->PrivateDriverDataSize, sizeof (VBOXDISPIFESCAPE_SHRC_REF)));
4270 Status = STATUS_INVALID_PARAMETER;
4271 break;
4272 }
4273
4274 PVBOXDISPIFESCAPE_SHRC_REF pShRcRef = (PVBOXDISPIFESCAPE_SHRC_REF)pEscapeHdr;
4275 PVBOXWDDM_ALLOCATION pAlloc = vboxWddmGetAllocationFromHandle(pDevExt, (D3DKMT_HANDLE)pShRcRef->hAlloc);
4276 if (!pAlloc)
4277 {
4278 WARN(("failed to get allocation from handle"));
4279 Status = STATUS_INVALID_PARAMETER;
4280 break;
4281 }
4282
4283 PVBOXWDDM_OPENALLOCATION pOa = VBoxWddmOaSearch(pDevice, pAlloc);
4284 if (!pOa)
4285 {
4286 WARN(("failed to get open allocation from alloc"));
4287 Status = STATUS_INVALID_PARAMETER;
4288 break;
4289 }
4290
4291 Assert(pAlloc->cShRcRefs >= pOa->cShRcRefs);
4292
4293 if (pEscapeHdr->escapeCode == VBOXESC_SHRC_ADDREF)
4294 {
4295#ifdef DEBUG
4296 Assert(!pAlloc->fAssumedDeletion);
4297#endif
4298 ++pAlloc->cShRcRefs;
4299 ++pOa->cShRcRefs;
4300 }
4301 else
4302 {
4303 Assert(pAlloc->cShRcRefs);
4304 Assert(pOa->cShRcRefs);
4305 --pAlloc->cShRcRefs;
4306 --pOa->cShRcRefs;
4307#ifdef DEBUG
4308 Assert(!pAlloc->fAssumedDeletion);
4309 if (!pAlloc->cShRcRefs)
4310 {
4311 pAlloc->fAssumedDeletion = TRUE;
4312 }
4313#endif
4314 }
4315
4316 pShRcRef->EscapeHdr.u32CmdSpecific = pAlloc->cShRcRefs;
4317 Status = STATUS_SUCCESS;
4318 break;
4319 }
4320 case VBOXESC_ISANYX:
4321 {
4322 if (pEscape->PrivateDriverDataSize != sizeof (VBOXDISPIFESCAPE_ISANYX))
4323 {
4324 WARN(("invalid private driver size %d", pEscape->PrivateDriverDataSize));
4325 Status = STATUS_INVALID_PARAMETER;
4326 break;
4327 }
4328
4329 PVBOXDISPIFESCAPE_ISANYX pIsAnyX = (PVBOXDISPIFESCAPE_ISANYX)pEscapeHdr;
4330 pIsAnyX->u32IsAnyX = VBoxCommonFromDeviceExt(pDevExt)->fAnyX;
4331 Status = STATUS_SUCCESS;
4332 break;
4333 }
4334 case VBOXESC_DBGPRINT:
4335 {
4336 /* use RT_OFFSETOF instead of sizeof since sizeof will give an aligned size that might
4337 * be bigger than the VBOXDISPIFESCAPE_DBGPRINT with a data containing just a few chars */
4338 Assert(pEscape->PrivateDriverDataSize >= RT_OFFSETOF(VBOXDISPIFESCAPE_DBGPRINT, aStringBuf[1]));
4339 /* only do DbgPrint when pEscape->PrivateDriverDataSize > RT_OFFSETOF(VBOXDISPIFESCAPE_DBGPRINT, aStringBuf[1])
4340 * since == RT_OFFSETOF(VBOXDISPIFESCAPE_DBGPRINT, aStringBuf[1]) means the buffer contains just \0,
4341 * i.e. no need to print it */
4342 if (pEscape->PrivateDriverDataSize > RT_OFFSETOF(VBOXDISPIFESCAPE_DBGPRINT, aStringBuf[1]))
4343 {
4344 PVBOXDISPIFESCAPE_DBGPRINT pDbgPrint = (PVBOXDISPIFESCAPE_DBGPRINT)pEscapeHdr;
4345 /* ensure the last char is \0*/
4346 *((uint8_t*)pDbgPrint + pEscape->PrivateDriverDataSize - 1) = '\0';
4347 if (g_VBoxLogUm & VBOXWDDM_CFG_LOG_UM_DBGPRINT)
4348 DbgPrint("%s\n", pDbgPrint->aStringBuf);
4349 if (g_VBoxLogUm & VBOXWDDM_CFG_LOG_UM_BACKDOOR)
4350 LOGREL_EXACT(("%s\n", pDbgPrint->aStringBuf));
4351 }
4352 Status = STATUS_SUCCESS;
4353 break;
4354 }
4355 case VBOXESC_DBGDUMPBUF:
4356 {
4357 Status = vboxUmdDumpBuf((PVBOXDISPIFESCAPE_DBGDUMPBUF)pEscapeHdr, pEscape->PrivateDriverDataSize);
4358 break;
4359 }
4360 default:
4361 Assert(0);
4362 LOGREL(("unsupported escape code (0x%x)", pEscapeHdr->escapeCode));
4363 break;
4364 }
4365 }
4366 else
4367 {
4368 LOGREL(("pEscape->PrivateDriverDataSize(%d) < (%d)", pEscape->PrivateDriverDataSize, sizeof (VBOXDISPIFESCAPE)));
4369 AssertBreakpoint();
4370 Status = STATUS_BUFFER_TOO_SMALL;
4371 }
4372
4373// LOGF(("LEAVE, hAdapter(0x%x)", hAdapter));
4374
4375 return Status;
4376}
4377
4378NTSTATUS
4379APIENTRY
4380DxgkDdiCollectDbgInfo(
4381 CONST HANDLE hAdapter,
4382 CONST DXGKARG_COLLECTDBGINFO* pCollectDbgInfo
4383 )
4384{
4385 LOGF(("ENTER, hAdapter(0x%x)", hAdapter));
4386
4387 AssertBreakpoint();
4388
4389 LOGF(("LEAVE, hAdapter(0x%x)", hAdapter));
4390
4391 return STATUS_SUCCESS;
4392}
4393
4394typedef struct VBOXWDDM_QUERYCURFENCE_CB
4395{
4396 PVBOXMP_DEVEXT pDevExt;
4397 ULONG MessageNumber;
4398 ULONG uLastCompletedCmdFenceId;
4399} VBOXWDDM_QUERYCURFENCE_CB, *PVBOXWDDM_QUERYCURFENCE_CB;
4400
4401static BOOLEAN vboxWddmQueryCurrentFenceCb(PVOID Context)
4402{
4403 PVBOXWDDM_QUERYCURFENCE_CB pdc = (PVBOXWDDM_QUERYCURFENCE_CB)Context;
4404 BOOL bRc = DxgkDdiInterruptRoutine(pdc->pDevExt, pdc->MessageNumber);
4405 pdc->uLastCompletedCmdFenceId = pdc->pDevExt->u.primary.Vdma.uLastCompletedPagingBufferCmdFenceId;
4406 return bRc;
4407}
4408
4409NTSTATUS
4410APIENTRY
4411DxgkDdiQueryCurrentFence(
4412 CONST HANDLE hAdapter,
4413 DXGKARG_QUERYCURRENTFENCE* pCurrentFence)
4414{
4415 LOGF(("ENTER, hAdapter(0x%x)", hAdapter));
4416
4417 vboxVDbgBreakF();
4418
4419 PVBOXMP_DEVEXT pDevExt = (PVBOXMP_DEVEXT)hAdapter;
4420 VBOXWDDM_QUERYCURFENCE_CB context = {0};
4421 context.pDevExt = pDevExt;
4422 BOOLEAN bRet;
4423 NTSTATUS Status = pDevExt->u.primary.DxgkInterface.DxgkCbSynchronizeExecution(
4424 pDevExt->u.primary.DxgkInterface.DeviceHandle,
4425 vboxWddmQueryCurrentFenceCb,
4426 &context,
4427 0, /* IN ULONG MessageNumber */
4428 &bRet);
4429 Assert(Status == STATUS_SUCCESS);
4430 if (Status == STATUS_SUCCESS)
4431 {
4432 pCurrentFence->CurrentFence = context.uLastCompletedCmdFenceId;
4433 }
4434
4435 LOGF(("LEAVE, hAdapter(0x%x)", hAdapter));
4436
4437 return STATUS_SUCCESS;
4438}
4439
4440NTSTATUS
4441APIENTRY
4442DxgkDdiIsSupportedVidPn(
4443 CONST HANDLE hAdapter,
4444 OUT DXGKARG_ISSUPPORTEDVIDPN* pIsSupportedVidPnArg
4445 )
4446{
4447 /* The DxgkDdiIsSupportedVidPn should be made pageable. */
4448 PAGED_CODE();
4449
4450 LOGF(("ENTER, context(0x%x)", hAdapter));
4451
4452 vboxVDbgBreakFv();
4453
4454 NTSTATUS Status = STATUS_SUCCESS;
4455 BOOLEAN bSupported = TRUE;
4456
4457 PVBOXMP_DEVEXT pContext = (PVBOXMP_DEVEXT)hAdapter;
4458 const DXGK_VIDPN_INTERFACE* pVidPnInterface = NULL;
4459 Status = pContext->u.primary.DxgkInterface.DxgkCbQueryVidPnInterface(pIsSupportedVidPnArg->hDesiredVidPn, DXGK_VIDPN_INTERFACE_VERSION_V1, &pVidPnInterface);
4460 if (!NT_SUCCESS(Status))
4461 {
4462 WARN(("DxgkCbQueryVidPnInterface failed Status()0x%x\n", Status));
4463 return Status;
4464 }
4465
4466#ifdef VBOXWDDM_DEBUG_VIDPN
4467 vboxVidPnDumpVidPn("\n>>>>IS SUPPORTED VidPN : >>>>", pContext, pIsSupportedVidPnArg->hDesiredVidPn, pVidPnInterface, "<<<<<<<<<<<<<<<<<<<<");
4468#endif
4469
4470 D3DKMDT_HVIDPNTOPOLOGY hVidPnTopology;
4471 const DXGK_VIDPNTOPOLOGY_INTERFACE* pVidPnTopologyInterface;
4472 Status = pVidPnInterface->pfnGetTopology(pIsSupportedVidPnArg->hDesiredVidPn, &hVidPnTopology, &pVidPnTopologyInterface);
4473 if (!NT_SUCCESS(Status))
4474 {
4475 WARN(("pfnGetTopology failed Status()0x%x\n", Status));
4476 return Status;
4477 }
4478
4479 VBOXVIDPNPATHITEM aItems[VBOX_VIDEO_MAX_SCREENS];
4480 BOOLEAN fDisabledFound = FALSE;
4481 Status = vboxVidPnCheckTopology(hVidPnTopology, pVidPnTopologyInterface, TRUE /* fBreakOnDisabled */, RT_ELEMENTS(aItems), aItems, &fDisabledFound);
4482 Assert(Status == STATUS_SUCCESS);
4483 if (!NT_SUCCESS(Status))
4484 {
4485 WARN(("vboxVidPnCheckTopology failed Status()0x%x\n", Status));
4486 return Status;
4487 }
4488
4489 if (fDisabledFound)
4490 {
4491 LOG(("found unsupported path"));
4492 bSupported = FALSE;
4493 }
4494
4495 pIsSupportedVidPnArg->IsVidPnSupported = bSupported;
4496
4497#ifdef VBOXWDDM_DEBUG_VIDPN
4498 LOGREL(("The Given VidPn is %ssupported\n", pIsSupportedVidPnArg->IsVidPnSupported ? "" : "!!NOT!! "));
4499#endif
4500
4501 LOGF(("LEAVE, status(0x%x), context(0x%x)", Status, hAdapter));
4502
4503 return Status;
4504}
4505
4506NTSTATUS
4507APIENTRY
4508DxgkDdiRecommendFunctionalVidPn(
4509 CONST HANDLE hAdapter,
4510 CONST DXGKARG_RECOMMENDFUNCTIONALVIDPN* CONST pRecommendFunctionalVidPnArg
4511 )
4512{
4513 /* The DxgkDdiRecommendFunctionalVidPn should be made pageable. */
4514 PAGED_CODE();
4515
4516 LOGF(("ENTER, context(0x%x)", hAdapter));
4517
4518 vboxVDbgBreakFv();
4519
4520 PVBOXMP_DEVEXT pDevExt = (PVBOXMP_DEVEXT)hAdapter;
4521 NTSTATUS Status;
4522 PVBOXWDDM_RECOMMENDVIDPN pVidPnInfo = pRecommendFunctionalVidPnArg->PrivateDriverDataSize >= sizeof (VBOXWDDM_RECOMMENDVIDPN) ?
4523 (PVBOXWDDM_RECOMMENDVIDPN)pRecommendFunctionalVidPnArg->pPrivateDriverData : NULL;
4524 PVBOXWDDM_VIDEOMODES_INFO pInfos = VBoxWddmUpdateAllVideoModesInfos(pDevExt);
4525 int i;
4526
4527 for (i = 0; i < VBoxCommonFromDeviceExt(pDevExt)->cDisplays; ++i)
4528 {
4529 /* @todo: check that we actually need the current source->target */
4530 PVBOXWDDM_VIDEOMODES_INFO pInfo = &pInfos[i];
4531 VIDEO_MODE_INFORMATION *pModeInfo = &pInfo->aModes[pInfo->iPreferredMode];
4532#if 0
4533 D3DKMDT_2DREGION Resolution;
4534 Resolution.cx = pModeInfo->VisScreenWidth;
4535 Resolution.cy = pModeInfo->VisScreenHeight;
4536 Status = vboxVidPnCheckAddMonitorModes(pDevExt, i, D3DKMDT_MCO_DRIVER, &Resolution, 1, 0);
4537#else
4538 Status = vboxVidPnCheckAddMonitorModes(pDevExt, i, D3DKMDT_MCO_DRIVER, pInfo->aResolutions, pInfo->cResolutions, pInfo->iPreferredResolution);
4539#endif
4540 if (Status != STATUS_SUCCESS)
4541 {
4542 WARN(("vboxVidPnCheckAddMonitorModes failed Status(0x%x)", Status));
4543 break;
4544 }
4545 }
4546
4547 const DXGK_VIDPN_INTERFACE* pVidPnInterface = NULL;
4548 Status = pDevExt->u.primary.DxgkInterface.DxgkCbQueryVidPnInterface(pRecommendFunctionalVidPnArg->hRecommendedFunctionalVidPn, DXGK_VIDPN_INTERFACE_VERSION_V1, &pVidPnInterface);
4549 if (!NT_SUCCESS(Status))
4550 {
4551 WARN(("DxgkCbQueryVidPnInterface failed Status(0x%x)", Status));
4552 return Status;
4553 }
4554
4555 for (i = 0; i < VBoxCommonFromDeviceExt(pDevExt)->cDisplays; ++i)
4556 {
4557 Status = vboxVidPnPathAdd(pRecommendFunctionalVidPnArg->hRecommendedFunctionalVidPn, pVidPnInterface, i, i);
4558 if (!NT_SUCCESS(Status))
4559 {
4560 WARN(("vboxVidPnPathAdd failed Status(0x%x)", Status));
4561 return Status;
4562 }
4563 }
4564
4565 VIDEO_MODE_INFORMATION *pResModes = NULL;
4566 uint32_t cResModes = 0;
4567
4568 for (i = 0; i < VBoxCommonFromDeviceExt(pDevExt)->cDisplays; ++i)
4569 {
4570 D3DKMDT_2DREGION Resolution;
4571 PVBOXWDDM_VIDEOMODES_INFO pInfo = &pInfos[i];
4572 VIDEO_MODE_INFORMATION *pModeInfo = &pInfo->aModes[pInfo->iPreferredMode];
4573 Resolution.cx = pModeInfo->VisScreenWidth;
4574 Resolution.cy = pModeInfo->VisScreenHeight;
4575 int32_t iPreferableResMode;
4576 uint32_t cActualResModes;
4577
4578 Status = VBoxWddmGetModesForResolution(pInfo->aModes, pInfo->cModes, pInfo->iPreferredMode, &Resolution,
4579 pResModes, cResModes, &cActualResModes, &iPreferableResMode);
4580 Assert(Status == STATUS_SUCCESS || Status == STATUS_BUFFER_TOO_SMALL);
4581 if (Status == STATUS_BUFFER_TOO_SMALL)
4582 {
4583 Assert(cResModes < cActualResModes);
4584 if (pResModes)
4585 {
4586 vboxWddmMemFree(pResModes);
4587 }
4588 pResModes = (VIDEO_MODE_INFORMATION*)vboxWddmMemAllocZero(sizeof (*pResModes) * cActualResModes);
4589 Assert(pResModes);
4590 if (!pResModes)
4591 {
4592 Status = STATUS_NO_MEMORY;
4593 break;
4594 }
4595 cResModes = cActualResModes;
4596 Status = VBoxWddmGetModesForResolution(pInfo->aModes, pInfo->cModes, pInfo->iPreferredMode, &Resolution,
4597 pResModes, cResModes, &cActualResModes, &iPreferableResMode);
4598 Assert(Status == STATUS_SUCCESS);
4599 if (Status != STATUS_SUCCESS)
4600 break;
4601 }
4602 else if (Status != STATUS_SUCCESS)
4603 break;
4604
4605 Assert(iPreferableResMode >= 0);
4606 Assert(cActualResModes);
4607
4608 Status = vboxVidPnCreatePopulateVidPnPathFromLegacy(pDevExt, pRecommendFunctionalVidPnArg->hRecommendedFunctionalVidPn, pVidPnInterface,
4609 pResModes, cActualResModes, iPreferableResMode,
4610 &Resolution, 1 /* cResolutions */,
4611 i, i); /* srcId, tgtId */
4612 Assert(Status == STATUS_SUCCESS);
4613 if (Status != STATUS_SUCCESS)
4614 {
4615 LOGREL(("vboxVidPnCreatePopulateVidPnFromLegacy failed Status(0x%x)", Status));
4616 break;
4617 }
4618 }
4619
4620 if(pResModes)
4621 vboxWddmMemFree(pResModes);
4622
4623#ifdef VBOXWDDM_DEBUG_VIDPN
4624 vboxVidPnDumpVidPn("\n>>>>Recommended VidPN: >>>>", pDevExt, pRecommendFunctionalVidPnArg->hRecommendedFunctionalVidPn, pVidPnInterface, "<<<<<<<<<<<<<<<<<<<<\n");
4625#endif
4626
4627 LOGF(("LEAVE, status(0x%x), context(0x%x)", Status, hAdapter));
4628
4629 return Status;
4630}
4631
4632NTSTATUS
4633APIENTRY
4634DxgkDdiEnumVidPnCofuncModality(
4635 CONST HANDLE hAdapter,
4636 CONST DXGKARG_ENUMVIDPNCOFUNCMODALITY* CONST pEnumCofuncModalityArg
4637 )
4638{
4639 /* The DxgkDdiEnumVidPnCofuncModality function should be made pageable. */
4640 PAGED_CODE();
4641
4642 LOGF(("ENTER, context(0x%x)", hAdapter));
4643
4644 vboxVDbgBreakFv();
4645
4646 PVBOXMP_DEVEXT pDevExt = (PVBOXMP_DEVEXT)hAdapter;
4647 const DXGK_VIDPN_INTERFACE* pVidPnInterface = NULL;
4648 NTSTATUS Status = pDevExt->u.primary.DxgkInterface.DxgkCbQueryVidPnInterface(pEnumCofuncModalityArg->hConstrainingVidPn, DXGK_VIDPN_INTERFACE_VERSION_V1, &pVidPnInterface);
4649 if (!NT_SUCCESS(Status))
4650 {
4651 WARN(("DxgkCbQueryVidPnInterface failed Status()0x%x\n", Status));
4652 return Status;
4653 }
4654#ifdef VBOXWDDM_DEBUG_VIDPN
4655 vboxVidPnDumpCofuncModalityArg(">>>>MODALITY Args: ", pEnumCofuncModalityArg, "\n");
4656 vboxVidPnDumpVidPn(">>>>MODALITY VidPN (IN) : >>>>\n", pDevExt, pEnumCofuncModalityArg->hConstrainingVidPn, pVidPnInterface, "<<<<<<<<<<<<<<<<<<<<\n");
4657#endif
4658
4659 D3DKMDT_HVIDPNTOPOLOGY hVidPnTopology;
4660 const DXGK_VIDPNTOPOLOGY_INTERFACE* pVidPnTopologyInterface;
4661 Status = pVidPnInterface->pfnGetTopology(pEnumCofuncModalityArg->hConstrainingVidPn, &hVidPnTopology, &pVidPnTopologyInterface);
4662 Assert(Status == STATUS_SUCCESS);
4663 if (!NT_SUCCESS(Status))
4664 {
4665 WARN(("pfnGetTopology failed Status()0x%x\n", Status));
4666 return Status;
4667 }
4668
4669 VBOXVIDPNPATHITEM aItems[VBOX_VIDEO_MAX_SCREENS];
4670 Status = vboxVidPnCheckTopology(hVidPnTopology, pVidPnTopologyInterface, FALSE /* fBreakOnDisabled */, RT_ELEMENTS(aItems), aItems, NULL /* *pfDisabledFound */);
4671 Assert(Status == STATUS_SUCCESS);
4672 if (!NT_SUCCESS(Status))
4673 {
4674 WARN(("vboxVidPnCheckTopology failed Status()0x%x\n", Status));
4675 return Status;
4676 }
4677
4678 VBOXVIDPNCOFUNCMODALITY CbContext = {0};
4679 CbContext.pDevExt = pDevExt;
4680 CbContext.pVidPnInterface = pVidPnInterface;
4681 CbContext.pEnumCofuncModalityArg = pEnumCofuncModalityArg;
4682 CbContext.pInfos = VBoxWddmGetAllVideoModesInfos(pDevExt);
4683 CbContext.cPathInfos = RT_ELEMENTS(aItems);
4684 CbContext.apPathInfos = aItems;
4685
4686 Status = vboxVidPnEnumPaths(hVidPnTopology, pVidPnTopologyInterface,
4687 vboxVidPnCofuncModalityPathEnum, &CbContext);
4688 Assert(Status == STATUS_SUCCESS);
4689 if (!NT_SUCCESS(Status))
4690 {
4691 WARN(("vboxVidPnEnumPaths failed Status()0x%x\n", Status));
4692 return Status;
4693 }
4694
4695 Status = CbContext.Status;
4696 if (!NT_SUCCESS(Status))
4697 {
4698 WARN(("vboxVidPnCofuncModalityPathEnum failed Status()0x%x\n", Status));
4699 return Status;
4700 }
4701
4702#ifdef VBOXWDDM_DEBUG_VIDPN
4703 vboxVidPnDumpVidPn("\n>>>>MODALITY VidPN (OUT) : >>>>\n", pDevExt, pEnumCofuncModalityArg->hConstrainingVidPn, pVidPnInterface, "<<<<<<<<<<<<<<<<<<<<\n\n");
4704#endif
4705
4706 LOGF(("LEAVE, status(0x%x), context(0x%x)", Status, hAdapter));
4707
4708 return Status;
4709}
4710
4711NTSTATUS
4712APIENTRY
4713DxgkDdiSetVidPnSourceAddress(
4714 CONST HANDLE hAdapter,
4715 CONST DXGKARG_SETVIDPNSOURCEADDRESS* pSetVidPnSourceAddress
4716 )
4717{
4718 /* The DxgkDdiSetVidPnSourceAddress function should be made pageable. */
4719 PAGED_CODE();
4720
4721 vboxVDbgBreakFv();
4722
4723 LOGF(("ENTER, context(0x%x)", hAdapter));
4724
4725 NTSTATUS Status = STATUS_SUCCESS;
4726 PVBOXMP_DEVEXT pDevExt = (PVBOXMP_DEVEXT)hAdapter;
4727 Assert((UINT)VBoxCommonFromDeviceExt(pDevExt)->cDisplays > pSetVidPnSourceAddress->VidPnSourceId);
4728
4729 PVBOXWDDM_SOURCE pSource = &pDevExt->aSources[pSetVidPnSourceAddress->VidPnSourceId];
4730 Status= vboxWddmDisplaySettingsQueryPos(pDevExt, pSetVidPnSourceAddress->VidPnSourceId, &pSource->VScreenPos);
4731 Assert(Status == STATUS_SUCCESS);
4732 Status = STATUS_SUCCESS;
4733
4734 if ((UINT)VBoxCommonFromDeviceExt(pDevExt)->cDisplays <= pSetVidPnSourceAddress->VidPnSourceId)
4735 {
4736 WARN(("invalid VidPnSourceId (%d), for displays(%d)", pSetVidPnSourceAddress->VidPnSourceId, VBoxCommonFromDeviceExt(pDevExt)->cDisplays));
4737 return STATUS_INVALID_PARAMETER;
4738 }
4739
4740 PVBOXWDDM_ALLOCATION pAllocation;
4741 Assert(pSetVidPnSourceAddress->hAllocation);
4742 Assert(pSetVidPnSourceAddress->hAllocation || pSource->pPrimaryAllocation);
4743 Assert (pSetVidPnSourceAddress->Flags.Value < 2); /* i.e. 0 or 1 (ModeChange) */
4744
4745 if (pSetVidPnSourceAddress->hAllocation)
4746 {
4747 pAllocation = (PVBOXWDDM_ALLOCATION)pSetVidPnSourceAddress->hAllocation;
4748 vboxWddmAssignPrimary(pDevExt, pSource, pAllocation, pSetVidPnSourceAddress->VidPnSourceId);
4749 }
4750 else
4751 pAllocation = pSource->pPrimaryAllocation;
4752
4753 if (pAllocation)
4754 {
4755 vboxWddmAddrSetVram(&pAllocation->AllocData.Addr, pSetVidPnSourceAddress->PrimarySegment, (VBOXVIDEOOFFSET)pSetVidPnSourceAddress->PrimaryAddress.QuadPart);
4756 }
4757
4758#ifdef VBOX_WDDM_WIN8
4759 if (g_VBoxDisplayOnly && !pAllocation)
4760 {
4761 /* the VRAM here is an absolute address, nto an offset!
4762 * convert to offset since all internal VBox functionality is offset-based */
4763 vboxWddmAddrSetVram(&pSource->AllocData.Addr, pSetVidPnSourceAddress->PrimarySegment,
4764 vboxWddmVramAddrToOffset(pDevExt, pSetVidPnSourceAddress->PrimaryAddress));
4765 }
4766 else
4767#endif
4768 {
4769#ifdef VBOX_WDDM_WIN8
4770 Assert(!g_VBoxDisplayOnly);
4771#endif
4772 vboxWddmAddrSetVram(&pSource->AllocData.Addr, pSetVidPnSourceAddress->PrimarySegment,
4773 pSetVidPnSourceAddress->PrimaryAddress.QuadPart);
4774 }
4775
4776 pSource->fGhSynced = 0; /* force guest->host notification */
4777
4778 if (pSource->bVisible
4779//#if defined(VBOXWDDM_RENDER_FROM_SHADOW)
4780// && (
4781//# if defined(VBOX_WDDM_WIN8)
4782// g_VBoxDisplayOnly
4783// ||
4784//# endif
4785// pDevExt->fRenderToShadowDisabled
4786// /* only update for UMD_RC_GENERIC when resolution changes to inform host about it
4787// * otherwise keep host using the same VRAM, containing a valid data before the switch (i.e. SHADOW) */
4788// || (pAllocation
4789// && pAllocation->enmType == VBOXWDDM_ALLOC_TYPE_UMD_RC_GENERIC
4790// && (pAllocation->AllocData.SurfDesc.width != pSource->AllocData.SurfDesc.width
4791// || pAllocation->AllocData.SurfDesc.height != pSource->AllocData.SurfDesc.height)
4792// )
4793// )
4794//#endif
4795 )
4796 {
4797 vboxWddmGhDisplayCheckSetInfoFromSource(pDevExt, pSource);
4798 }
4799
4800 LOGF(("LEAVE, status(0x%x), context(0x%x)", Status, hAdapter));
4801
4802 return Status;
4803}
4804
4805NTSTATUS
4806APIENTRY
4807DxgkDdiSetVidPnSourceVisibility(
4808 CONST HANDLE hAdapter,
4809 CONST DXGKARG_SETVIDPNSOURCEVISIBILITY* pSetVidPnSourceVisibility
4810 )
4811{
4812 /* DxgkDdiSetVidPnSourceVisibility should be made pageable. */
4813 PAGED_CODE();
4814
4815 vboxVDbgBreakFv();
4816
4817 LOGF(("ENTER, context(0x%x)", hAdapter));
4818
4819 NTSTATUS Status = STATUS_SUCCESS;
4820 PVBOXMP_DEVEXT pDevExt = (PVBOXMP_DEVEXT)hAdapter;
4821 Assert((UINT)VBoxCommonFromDeviceExt(pDevExt)->cDisplays > pSetVidPnSourceVisibility->VidPnSourceId);
4822
4823 PVBOXWDDM_SOURCE pSource = &pDevExt->aSources[pSetVidPnSourceVisibility->VidPnSourceId];
4824 Status= vboxWddmDisplaySettingsQueryPos(pDevExt, pSetVidPnSourceVisibility->VidPnSourceId, &pSource->VScreenPos);
4825 Assert(Status == STATUS_SUCCESS);
4826 Status = STATUS_SUCCESS;
4827
4828 if ((UINT)VBoxCommonFromDeviceExt(pDevExt)->cDisplays <= pSetVidPnSourceVisibility->VidPnSourceId)
4829 {
4830 WARN(("invalid VidPnSourceId (%d), for displays(%d)", pSetVidPnSourceVisibility->VidPnSourceId, VBoxCommonFromDeviceExt(pDevExt)->cDisplays));
4831 return STATUS_INVALID_PARAMETER;
4832 }
4833
4834 PVBOXWDDM_ALLOCATION pAllocation = pSource->pPrimaryAllocation;
4835 if (pAllocation)
4836 pAllocation->bVisible = pSetVidPnSourceVisibility->Visible;
4837
4838 if (pSource->bVisible != pSetVidPnSourceVisibility->Visible)
4839 {
4840 pSource->bVisible = pSetVidPnSourceVisibility->Visible;
4841 if (pSource->bVisible
4842//#if defined(VBOXWDDM_RENDER_FROM_SHADOW)
4843// && (
4844//# if defined(VBOX_WDDM_WIN8)
4845// g_VBoxDisplayOnly
4846// ||
4847//# endif
4848// pDevExt->fRenderToShadowDisabled
4849// /* only update for UMD_RC_GENERIC when resolution changes to inform host about it
4850// * otherwise keep host using the same VRAM, containing a valid data before the switch (i.e. SHADOW) */
4851// || (pAllocation
4852// && pAllocation->enmType == VBOXWDDM_ALLOC_TYPE_UMD_RC_GENERIC
4853// && (pAllocation->AllocData.SurfDesc.width != pSource->AllocData.SurfDesc.width
4854// || pAllocation->AllocData.SurfDesc.height != pSource->AllocData.SurfDesc.height)
4855// )
4856// )
4857//#endif
4858 )
4859 {
4860 vboxWddmGhDisplayCheckSetInfoFromSource(pDevExt, pSource);
4861 }
4862 }
4863
4864 LOGF(("LEAVE, status(0x%x), context(0x%x)", Status, hAdapter));
4865
4866 return Status;
4867}
4868
4869static DECLCALLBACK(BOOLEAN) vboxWddmVidPnCleanupTargetsForSrcEnum(PVBOXMP_DEVEXT pDevExt, D3DKMDT_HVIDPNTOPOLOGY hVidPnTopology, const DXGK_VIDPNTOPOLOGY_INTERFACE* pVidPnTopologyInterface,
4870 CONST D3DDDI_VIDEO_PRESENT_SOURCE_ID VidPnSourceId, D3DDDI_VIDEO_PRESENT_TARGET_ID VidPnTargetId, SIZE_T cTgtPaths, PVOID pContext)
4871{
4872 AssertRelease(VidPnTargetId < RT_ELEMENTS(pDevExt->aTargets));
4873 PVBOXWDDM_TARGET pTarget = &pDevExt->aTargets[VidPnTargetId];
4874 /* see comments in DxgkDdiCommitVidPn */
4875 pTarget->HeightVisible = 0;
4876 return TRUE;
4877}
4878
4879
4880NTSTATUS
4881APIENTRY
4882DxgkDdiCommitVidPn(
4883 CONST HANDLE hAdapter,
4884 CONST DXGKARG_COMMITVIDPN* CONST pCommitVidPnArg
4885 )
4886{
4887 LOGF(("ENTER, context(0x%x)", hAdapter));
4888
4889 PVBOXMP_DEVEXT pDevExt = (PVBOXMP_DEVEXT)hAdapter;
4890 uint32_t au32OldHeightVisible[VBOX_VIDEO_MAX_SCREENS];
4891 NTSTATUS Status;
4892
4893 vboxVDbgBreakFv();
4894
4895 /* we first store the current visible height for each target (monitor)
4896 * and then we will zero up it for targets either for the given source
4897 * (in case pCommitVidPnArg->AffectedVidPnSourceId != D3DDDI_ID_ALL)
4898 * or all targets otherwize.
4899 * In the end we will match the old and new visible height for all targets to see if
4900 * some of them become inactivated and hide them accordingly,
4901 * or we will restore the old height values on failure */
4902 for (int i = 0; i < VBoxCommonFromDeviceExt(pDevExt)->cDisplays; ++i)
4903 {
4904 PVBOXWDDM_TARGET pTarget = &pDevExt->aTargets[i];
4905 au32OldHeightVisible[i] = pTarget->HeightVisible;
4906 }
4907
4908 do {
4909 const DXGK_VIDPN_INTERFACE* pVidPnInterface = NULL;
4910 Status = pDevExt->u.primary.DxgkInterface.DxgkCbQueryVidPnInterface(pCommitVidPnArg->hFunctionalVidPn, DXGK_VIDPN_INTERFACE_VERSION_V1, &pVidPnInterface);
4911 if (!NT_SUCCESS(Status))
4912 {
4913 WARN(("DxgkCbQueryVidPnInterface failed Status 0x%x", Status));
4914 break;
4915 }
4916
4917#ifdef VBOXWDDM_DEBUG_VIDPN
4918 vboxVidPnDumpVidPn("\n>>>>COMMIT VidPN: >>>>", pDevExt, pCommitVidPnArg->hFunctionalVidPn, pVidPnInterface, "<<<<<<<<<<<<<<<<<<<<\n");
4919#endif
4920
4921 if (pCommitVidPnArg->AffectedVidPnSourceId != D3DDDI_ID_ALL)
4922 {
4923 /* there is not VidPn on driver start, check that */
4924 if (pDevExt->u.primary.hCommittedVidPn)
4925 {
4926 D3DKMDT_HVIDPNTOPOLOGY hVidPnTopology;
4927 CONST DXGK_VIDPNTOPOLOGY_INTERFACE* pVidPnTopologyInterface;
4928 const DXGK_VIDPN_INTERFACE* pOldVidPnInterface = NULL;
4929 Status = pDevExt->u.primary.DxgkInterface.DxgkCbQueryVidPnInterface(pDevExt->u.primary.hCommittedVidPn, DXGK_VIDPN_INTERFACE_VERSION_V1, &pOldVidPnInterface);
4930 if (!NT_SUCCESS(Status))
4931 {
4932 WARN(("DxgkCbQueryVidPnInterface for current VidPn failed Status 0x%x", Status));
4933 break;
4934 }
4935
4936 Status = pOldVidPnInterface->pfnGetTopology(pDevExt->u.primary.hCommittedVidPn, &hVidPnTopology, &pVidPnTopologyInterface);
4937 if (!NT_SUCCESS(Status))
4938 {
4939 WARN(("pfnGetTopology for current VidPn failed Status 0x%x", Status));
4940 break;
4941 }
4942
4943 /* this will zero up visible height for all targets of the fiven source, see above comment */
4944 Status = vboxVidPnEnumTargetsForSource(pDevExt, hVidPnTopology, pVidPnTopologyInterface,
4945 pCommitVidPnArg->AffectedVidPnSourceId,
4946 vboxWddmVidPnCleanupTargetsForSrcEnum, NULL);
4947 if (Status == STATUS_GRAPHICS_SOURCE_NOT_IN_TOPOLOGY)
4948 Status = STATUS_SUCCESS;
4949
4950 if (!NT_SUCCESS(Status))
4951 {
4952 WARN(("vboxVidPnEnumTargetsForSource for current VidPn failed Status 0x%x", Status));
4953 break;
4954 }
4955 }
4956
4957 Status = vboxVidPnCommitSourceModeForSrcId(
4958 pDevExt,
4959 pCommitVidPnArg->hFunctionalVidPn, pVidPnInterface,
4960 pCommitVidPnArg->AffectedVidPnSourceId, (PVBOXWDDM_ALLOCATION)pCommitVidPnArg->hPrimaryAllocation);
4961 if (!NT_SUCCESS(Status))
4962 {
4963 WARN(("vboxVidPnCommitSourceModeForSrcId for current VidPn failed Status 0x%x", Status));
4964 break;
4965 }
4966 }
4967 else
4968 {
4969 for (int i = 0; i < VBoxCommonFromDeviceExt(pDevExt)->cDisplays; ++i)
4970 {
4971 PVBOXWDDM_TARGET pTarget = &pDevExt->aTargets[i];
4972 /* see above comment */
4973 pTarget->HeightVisible = 0;
4974 }
4975
4976 /* clear all current primaries */
4977 for (int i = 0; i < VBoxCommonFromDeviceExt(pDevExt)->cDisplays; ++i)
4978 {
4979 vboxWddmAssignPrimary(pDevExt, &pDevExt->aSources[i], NULL, i);
4980 }
4981
4982 D3DKMDT_HVIDPNTOPOLOGY hVidPnTopology;
4983 const DXGK_VIDPNTOPOLOGY_INTERFACE* pVidPnTopologyInterface;
4984 Status = pVidPnInterface->pfnGetTopology(pCommitVidPnArg->hFunctionalVidPn, &hVidPnTopology, &pVidPnTopologyInterface);
4985 if (!NT_SUCCESS(Status))
4986 {
4987 WARN(("pfnGetTopology failed Status 0x%x", Status));
4988 break;
4989 }
4990
4991 VBOXVIDPNCOMMIT CbContext = {0};
4992 CbContext.pDevExt = pDevExt;
4993 CbContext.pVidPnInterface = pVidPnInterface;
4994 CbContext.pCommitVidPnArg = pCommitVidPnArg;
4995 Status = vboxVidPnEnumPaths(hVidPnTopology, pVidPnTopologyInterface,
4996 vboxVidPnCommitPathEnum, &CbContext);
4997 if (!NT_SUCCESS(Status))
4998 {
4999 WARN(("vboxVidPnEnumPaths failed Status 0x%x", Status));
5000 break;
5001 }
5002
5003 Status = CbContext.Status;
5004 if (!NT_SUCCESS(Status))
5005 {
5006 WARN(("vboxVidPnCommitPathEnum failed Status 0x%x", Status));
5007 break;
5008 }
5009 }
5010
5011 Assert(NT_SUCCESS(Status));
5012 pDevExt->u.primary.hCommittedVidPn = pCommitVidPnArg->hFunctionalVidPn;
5013
5014 for (int i = 1; /* <- never try to hide a primary monitor */
5015 i < VBoxCommonFromDeviceExt(pDevExt)->cDisplays; ++i)
5016 {
5017 PVBOXWDDM_TARGET pTarget = &pDevExt->aTargets[i];
5018 if (!pTarget->HeightVisible && !!au32OldHeightVisible[i])
5019 {
5020 /* the target was previously visible */
5021 vboxWddmGhDisplayHideScreen(pDevExt, i);
5022 }
5023 }
5024
5025//#ifdef VBOX_WDDM_WIN8
5026// if (g_VBoxDisplayOnly)
5027 {
5028 for (int i = 0; /* <- never try to hide a primary monitor */
5029 i < VBoxCommonFromDeviceExt(pDevExt)->cDisplays; ++i)
5030 {
5031 PVBOXWDDM_SOURCE pSource = &pDevExt->aSources[i];
5032 if (pSource->bVisible)
5033 {
5034 vboxWddmGhDisplayCheckSetInfoFromSource(pDevExt, pSource);
5035 }
5036 }
5037 }
5038//#endif
5039 LOGF(("LEAVE, SUCCESS status(0x%x), context(0x%x)", Status, hAdapter));
5040
5041 return Status;
5042 } while (0);
5043
5044 AssertRelease(!NT_SUCCESS(Status));
5045 /* failure branch restore original visible height values, see comments above */
5046 for (int i = 0; i < VBoxCommonFromDeviceExt(pDevExt)->cDisplays; ++i)
5047 {
5048 PVBOXWDDM_TARGET pTarget = &pDevExt->aTargets[i];
5049 pTarget->HeightVisible = au32OldHeightVisible[i];
5050 }
5051
5052 LOGF(("LEAVE, !!FAILURE!! status(0x%x), context(0x%x)", Status, hAdapter));
5053 return Status;
5054}
5055
5056NTSTATUS
5057APIENTRY
5058DxgkDdiUpdateActiveVidPnPresentPath(
5059 CONST HANDLE hAdapter,
5060 CONST DXGKARG_UPDATEACTIVEVIDPNPRESENTPATH* CONST pUpdateActiveVidPnPresentPathArg
5061 )
5062{
5063 LOGF(("ENTER, hAdapter(0x%x)", hAdapter));
5064
5065 AssertBreakpoint();
5066
5067 LOGF(("LEAVE, hAdapter(0x%x)", hAdapter));
5068
5069 return STATUS_SUCCESS;
5070}
5071
5072NTSTATUS
5073APIENTRY
5074DxgkDdiRecommendMonitorModes(
5075 CONST HANDLE hAdapter,
5076 CONST DXGKARG_RECOMMENDMONITORMODES* CONST pRecommendMonitorModesArg
5077 )
5078{
5079 LOGF(("ENTER, hAdapter(0x%x)", hAdapter));
5080
5081 vboxVDbgBreakFv();
5082
5083 PVBOXMP_DEVEXT pDevExt = (PVBOXMP_DEVEXT)hAdapter;
5084 NTSTATUS Status;
5085 PVBOXWDDM_VIDEOMODES_INFO pInfo = VBoxWddmGetVideoModesInfo(pDevExt, pRecommendMonitorModesArg->VideoPresentTargetId);
5086 PVIDEO_MODE_INFORMATION pPreferredMode = &pInfo->aModes[pInfo->iPreferredMode];
5087
5088
5089 for (uint32_t i = 0; i < pInfo->cResolutions; i++)
5090 {
5091 D3DKMDT_MONITOR_SOURCE_MODE * pNewMonitorSourceModeInfo;
5092 Status = pRecommendMonitorModesArg->pMonitorSourceModeSetInterface->pfnCreateNewModeInfo(
5093 pRecommendMonitorModesArg->hMonitorSourceModeSet, &pNewMonitorSourceModeInfo);
5094 Assert(Status == STATUS_SUCCESS);
5095 if (Status == STATUS_SUCCESS)
5096 {
5097 Status = vboxVidPnPopulateMonitorSourceModeInfoFromLegacy(pDevExt,
5098 pNewMonitorSourceModeInfo,
5099 &pInfo->aResolutions[i],
5100 D3DKMDT_MCO_DRIVER,
5101 pPreferredMode->VisScreenWidth == pInfo->aResolutions[i].cx
5102 && pPreferredMode->VisScreenHeight == pInfo->aResolutions[i].cy);
5103 Assert(Status == STATUS_SUCCESS);
5104 if (Status == STATUS_SUCCESS)
5105 {
5106 Status = pRecommendMonitorModesArg->pMonitorSourceModeSetInterface->pfnAddMode(
5107 pRecommendMonitorModesArg->hMonitorSourceModeSet, pNewMonitorSourceModeInfo);
5108 Assert(Status == STATUS_SUCCESS);
5109 if (Status == STATUS_SUCCESS)
5110 continue;
5111 }
5112
5113 /* error has occurred, release & break */
5114 pRecommendMonitorModesArg->pMonitorSourceModeSetInterface->pfnReleaseModeInfo(
5115 pRecommendMonitorModesArg->hMonitorSourceModeSet, pNewMonitorSourceModeInfo);
5116 break;
5117 }
5118 }
5119
5120 LOGF(("LEAVE, hAdapter(0x%x)", hAdapter));
5121
5122 return Status;
5123}
5124
5125NTSTATUS
5126APIENTRY
5127DxgkDdiRecommendVidPnTopology(
5128 CONST HANDLE hAdapter,
5129 CONST DXGKARG_RECOMMENDVIDPNTOPOLOGY* CONST pRecommendVidPnTopologyArg
5130 )
5131{
5132 LOGF(("ENTER, hAdapter(0x%x)", hAdapter));
5133
5134 vboxVDbgBreakFv();
5135
5136 LOGF(("LEAVE, hAdapter(0x%x)", hAdapter));
5137
5138 return STATUS_GRAPHICS_NO_RECOMMENDED_VIDPN_TOPOLOGY;
5139}
5140
5141NTSTATUS
5142APIENTRY
5143DxgkDdiGetScanLine(
5144 CONST HANDLE hAdapter,
5145 DXGKARG_GETSCANLINE* pGetScanLine)
5146{
5147 LOGF(("ENTER, hAdapter(0x%x)", hAdapter));
5148
5149 PVBOXMP_DEVEXT pDevExt = (PVBOXMP_DEVEXT)hAdapter;
5150
5151#ifdef DEBUG_misha
5152 RT_BREAKPOINT();
5153#endif
5154
5155 NTSTATUS Status = VBoxWddmSlGetScanLine(pDevExt, pGetScanLine);
5156
5157 LOGF(("LEAVE, hAdapter(0x%x)", hAdapter));
5158
5159 return Status;
5160}
5161
5162NTSTATUS
5163APIENTRY
5164DxgkDdiStopCapture(
5165 CONST HANDLE hAdapter,
5166 CONST DXGKARG_STOPCAPTURE* pStopCapture)
5167{
5168 LOGF(("ENTER, hAdapter(0x%x)", hAdapter));
5169
5170 AssertBreakpoint();
5171
5172 LOGF(("LEAVE, hAdapter(0x%x)", hAdapter));
5173
5174 return STATUS_SUCCESS;
5175}
5176
5177NTSTATUS
5178APIENTRY
5179DxgkDdiControlInterrupt(
5180 CONST HANDLE hAdapter,
5181 CONST DXGK_INTERRUPT_TYPE InterruptType,
5182 BOOLEAN Enable
5183 )
5184{
5185 LOGF(("ENTER, hAdapter(0x%x)", hAdapter));
5186
5187 NTSTATUS Status = STATUS_NOT_IMPLEMENTED;
5188 PVBOXMP_DEVEXT pDevExt = (PVBOXMP_DEVEXT)hAdapter;
5189
5190 switch (InterruptType)
5191 {
5192 case DXGK_INTERRUPT_CRTC_VSYNC:
5193 {
5194 Status = VBoxWddmSlEnableVSyncNotification(pDevExt, Enable);
5195 if (NT_SUCCESS(Status))
5196 Status = STATUS_SUCCESS; /* <- sanity */
5197 else
5198 WARN(("VSYNC Interrupt control failed Enable(%d), Status(0x%x)", Enable, Status));
5199 break;
5200 }
5201 case DXGK_INTERRUPT_DMA_COMPLETED:
5202 case DXGK_INTERRUPT_DMA_PREEMPTED:
5203 case DXGK_INTERRUPT_DMA_FAULTED:
5204 WARN(("Unexpected interrupt type! %d", InterruptType));
5205 break;
5206 default:
5207 WARN(("UNSUPPORTED interrupt type! %d", InterruptType));
5208 break;
5209 }
5210
5211 LOGF(("LEAVE, hAdapter(0x%x)", hAdapter));
5212
5213 return Status;
5214}
5215
5216NTSTATUS
5217APIENTRY
5218DxgkDdiCreateOverlay(
5219 CONST HANDLE hAdapter,
5220 DXGKARG_CREATEOVERLAY *pCreateOverlay)
5221{
5222 LOGF(("ENTER, hAdapter(0x%p)", hAdapter));
5223
5224 NTSTATUS Status = STATUS_SUCCESS;
5225 PVBOXMP_DEVEXT pDevExt = (PVBOXMP_DEVEXT)hAdapter;
5226 PVBOXWDDM_OVERLAY pOverlay = (PVBOXWDDM_OVERLAY)vboxWddmMemAllocZero(sizeof (VBOXWDDM_OVERLAY));
5227 Assert(pOverlay);
5228 if (pOverlay)
5229 {
5230 int rc = vboxVhwaHlpOverlayCreate(pDevExt, pCreateOverlay->VidPnSourceId, &pCreateOverlay->OverlayInfo, pOverlay);
5231 AssertRC(rc);
5232 if (RT_SUCCESS(rc))
5233 {
5234 pCreateOverlay->hOverlay = pOverlay;
5235 }
5236 else
5237 {
5238 vboxWddmMemFree(pOverlay);
5239 Status = STATUS_UNSUCCESSFUL;
5240 }
5241 }
5242 else
5243 Status = STATUS_NO_MEMORY;
5244
5245 LOGF(("LEAVE, hAdapter(0x%p)", hAdapter));
5246
5247 return Status;
5248}
5249
5250NTSTATUS
5251APIENTRY
5252DxgkDdiDestroyDevice(
5253 CONST HANDLE hDevice)
5254{
5255 /* DxgkDdiDestroyDevice should be made pageable. */
5256 PAGED_CODE();
5257
5258 LOGF(("ENTER, hDevice(0x%x)", hDevice));
5259
5260 vboxVDbgBreakFv();
5261
5262 vboxWddmMemFree(hDevice);
5263
5264 LOGF(("LEAVE, "));
5265
5266 return STATUS_SUCCESS;
5267}
5268
5269
5270
5271/*
5272 * DxgkDdiOpenAllocation
5273 */
5274NTSTATUS
5275APIENTRY
5276DxgkDdiOpenAllocation(
5277 CONST HANDLE hDevice,
5278 CONST DXGKARG_OPENALLOCATION *pOpenAllocation)
5279{
5280 /* DxgkDdiOpenAllocation should be made pageable. */
5281 PAGED_CODE();
5282
5283 LOGF(("ENTER, hDevice(0x%x)", hDevice));
5284
5285 vboxVDbgBreakFv();
5286
5287 NTSTATUS Status = STATUS_SUCCESS;
5288 PVBOXWDDM_DEVICE pDevice = (PVBOXWDDM_DEVICE)hDevice;
5289 PVBOXMP_DEVEXT pDevExt = pDevice->pAdapter;
5290 PVBOXWDDM_RCINFO pRcInfo = NULL;
5291 if (pOpenAllocation->PrivateDriverSize)
5292 {
5293 Assert(pOpenAllocation->PrivateDriverSize == sizeof (VBOXWDDM_RCINFO));
5294 Assert(pOpenAllocation->pPrivateDriverData);
5295 if (pOpenAllocation->PrivateDriverSize >= sizeof (VBOXWDDM_RCINFO))
5296 {
5297 pRcInfo = (PVBOXWDDM_RCINFO)pOpenAllocation->pPrivateDriverData;
5298 Assert(pRcInfo->cAllocInfos == pOpenAllocation->NumAllocations);
5299 }
5300 else
5301 Status = STATUS_INVALID_PARAMETER;
5302 }
5303
5304 if (Status == STATUS_SUCCESS)
5305 {
5306 UINT i = 0;
5307 for (; i < pOpenAllocation->NumAllocations; ++i)
5308 {
5309 DXGK_OPENALLOCATIONINFO* pInfo = &pOpenAllocation->pOpenAllocation[i];
5310 Assert(pInfo->PrivateDriverDataSize == sizeof (VBOXWDDM_ALLOCINFO));
5311 Assert(pInfo->pPrivateDriverData);
5312 PVBOXWDDM_ALLOCATION pAllocation = vboxWddmGetAllocationFromHandle(pDevExt, pInfo->hAllocation);
5313 if (!pAllocation)
5314 {
5315 WARN(("invalid handle"));
5316 Status = STATUS_INVALID_PARAMETER;
5317 break;
5318 }
5319
5320#ifdef DEBUG
5321 Assert(!pAllocation->fAssumedDeletion);
5322#endif
5323 if (pRcInfo)
5324 {
5325 Assert(pAllocation->enmType == VBOXWDDM_ALLOC_TYPE_UMD_RC_GENERIC);
5326
5327 if (pInfo->PrivateDriverDataSize != sizeof (VBOXWDDM_ALLOCINFO)
5328 || !pInfo->pPrivateDriverData)
5329 {
5330 WARN(("invalid data size"));
5331 Status = STATUS_INVALID_PARAMETER;
5332 break;
5333 }
5334 PVBOXWDDM_ALLOCINFO pAllocInfo = (PVBOXWDDM_ALLOCINFO)pInfo->pPrivateDriverData;
5335
5336#ifdef VBOX_WITH_VIDEOHWACCEL
5337 if (pRcInfo->RcDesc.fFlags.Overlay)
5338 {
5339 /* we have queried host for some surface info, like pitch & size,
5340 * need to return it back to the UMD (User Mode Drive) */
5341 pAllocInfo->SurfDesc = pAllocation->AllocData.SurfDesc;
5342 /* success, just continue */
5343 }
5344#endif
5345 }
5346
5347 KIRQL OldIrql;
5348 PVBOXWDDM_OPENALLOCATION pOa;
5349 KeAcquireSpinLock(&pAllocation->OpenLock, &OldIrql);
5350 pOa = VBoxWddmOaSearchLocked(pDevice, pAllocation);
5351 if (pOa)
5352 {
5353 ++pOa->cOpens;
5354 ++pAllocation->cOpens;
5355 KeReleaseSpinLock(&pAllocation->OpenLock, OldIrql);
5356 }
5357 else
5358 {
5359 KeReleaseSpinLock(&pAllocation->OpenLock, OldIrql);
5360 pOa = (PVBOXWDDM_OPENALLOCATION)vboxWddmMemAllocZero(sizeof (VBOXWDDM_OPENALLOCATION));
5361 if (!pOa)
5362 {
5363 WARN(("failed to allocation alloc info"));
5364 Status = STATUS_INSUFFICIENT_RESOURCES;
5365 break;
5366 }
5367
5368 pOa->hAllocation = pInfo->hAllocation;
5369 pOa->pAllocation = pAllocation;
5370 pOa->pDevice = pDevice;
5371 pOa->cOpens = 1;
5372
5373 PVBOXWDDM_OPENALLOCATION pConcurrentOa;
5374 KeAcquireSpinLock(&pAllocation->OpenLock, &OldIrql);
5375 pConcurrentOa = VBoxWddmOaSearchLocked(pDevice, pAllocation);
5376 if (!pConcurrentOa)
5377 InsertHeadList(&pAllocation->OpenList, &pOa->ListEntry);
5378 else
5379 ++pConcurrentOa->cOpens;
5380 ++pAllocation->cOpens;
5381 KeReleaseSpinLock(&pAllocation->OpenLock, OldIrql);
5382 if (pConcurrentOa)
5383 {
5384 vboxWddmMemFree(pOa);
5385 pOa = pConcurrentOa;
5386 }
5387 }
5388
5389 pInfo->hDeviceSpecificAllocation = pOa;
5390 }
5391
5392 if (Status != STATUS_SUCCESS)
5393 {
5394 for (UINT j = 0; j < i; ++j)
5395 {
5396 DXGK_OPENALLOCATIONINFO* pInfo2Free = &pOpenAllocation->pOpenAllocation[j];
5397 PVBOXWDDM_OPENALLOCATION pOa2Free = (PVBOXWDDM_OPENALLOCATION)pInfo2Free->hDeviceSpecificAllocation;
5398 VBoxWddmOaRelease(pOa2Free);
5399 }
5400 }
5401 }
5402 LOGF(("LEAVE, hDevice(0x%x)", hDevice));
5403
5404 return Status;
5405}
5406
5407NTSTATUS
5408APIENTRY
5409DxgkDdiCloseAllocation(
5410 CONST HANDLE hDevice,
5411 CONST DXGKARG_CLOSEALLOCATION* pCloseAllocation)
5412{
5413 /* DxgkDdiCloseAllocation should be made pageable. */
5414 PAGED_CODE();
5415
5416 LOGF(("ENTER, hDevice(0x%x)", hDevice));
5417
5418 vboxVDbgBreakFv();
5419
5420 PVBOXWDDM_DEVICE pDevice = (PVBOXWDDM_DEVICE)hDevice;
5421 PVBOXMP_DEVEXT pDevExt = pDevice->pAdapter;
5422
5423 for (UINT i = 0; i < pCloseAllocation->NumAllocations; ++i)
5424 {
5425 PVBOXWDDM_OPENALLOCATION pOa2Free = (PVBOXWDDM_OPENALLOCATION)pCloseAllocation->pOpenHandleList[i];
5426 PVBOXWDDM_ALLOCATION pAllocation = pOa2Free->pAllocation;
5427 Assert(pAllocation->cShRcRefs >= pOa2Free->cShRcRefs);
5428 pAllocation->cShRcRefs -= pOa2Free->cShRcRefs;
5429 VBoxWddmOaRelease(pOa2Free);
5430 }
5431
5432 LOGF(("LEAVE, hDevice(0x%x)", hDevice));
5433
5434 return STATUS_SUCCESS;
5435}
5436
5437NTSTATUS
5438APIENTRY
5439DxgkDdiRender(
5440 CONST HANDLE hContext,
5441 DXGKARG_RENDER *pRender)
5442{
5443// LOGF(("ENTER, hContext(0x%x)", hContext));
5444
5445 Assert(pRender->DmaBufferPrivateDataSize >= sizeof (VBOXWDDM_DMA_PRIVATEDATA_BASEHDR));
5446 if (pRender->DmaBufferPrivateDataSize < sizeof (VBOXWDDM_DMA_PRIVATEDATA_BASEHDR))
5447 {
5448 LOGREL(("Present->DmaBufferPrivateDataSize(%d) < sizeof VBOXWDDM_DMA_PRIVATEDATA_BASEHDR (%d)",
5449 pRender->DmaBufferPrivateDataSize , sizeof (VBOXWDDM_DMA_PRIVATEDATA_BASEHDR)));
5450 /* @todo: can this actually happen? what status to return? */
5451 return STATUS_INVALID_PARAMETER;
5452 }
5453 if (pRender->CommandLength < sizeof (VBOXWDDM_DMA_PRIVATEDATA_BASEHDR))
5454 {
5455 Assert(0);
5456 LOGREL(("Present->DmaBufferPrivateDataSize(%d) < sizeof VBOXWDDM_DMA_PRIVATEDATA_BASEHDR (%d)",
5457 pRender->DmaBufferPrivateDataSize , sizeof (VBOXWDDM_DMA_PRIVATEDATA_BASEHDR)));
5458 /* @todo: can this actually happen? what status to return? */
5459 return STATUS_INVALID_PARAMETER;
5460 }
5461
5462 PVBOXWDDM_DMA_PRIVATEDATA_BASEHDR pInputHdr = (PVBOXWDDM_DMA_PRIVATEDATA_BASEHDR)pRender->pCommand;
5463 NTSTATUS Status = STATUS_SUCCESS;
5464 switch (pInputHdr->enmCmd)
5465 {
5466 case VBOXVDMACMD_TYPE_CHROMIUM_CMD:
5467 {
5468 if (pRender->CommandLength != RT_OFFSETOF(VBOXWDDM_DMA_PRIVATEDATA_UM_CHROMIUM_CMD, aBufInfos[pInputHdr->u32CmdReserved]))
5469 {
5470 Assert(0);
5471 return STATUS_INVALID_PARAMETER;
5472 }
5473 PVBOXWDDM_DMA_PRIVATEDATA_UM_CHROMIUM_CMD pUmCmd = (PVBOXWDDM_DMA_PRIVATEDATA_UM_CHROMIUM_CMD)pInputHdr;
5474 PVBOXWDDM_DMA_PRIVATEDATA_CHROMIUM_CMD pChromiumCmd = (PVBOXWDDM_DMA_PRIVATEDATA_CHROMIUM_CMD)pRender->pDmaBufferPrivateData;
5475 const uint32_t cbDma = RT_OFFSETOF(VBOXWDDM_DMA_PRIVATEDATA_CHROMIUM_CMD, aBufInfos[pInputHdr->u32CmdReserved]);
5476 if (pRender->DmaBufferPrivateDataSize < cbDma)
5477 {
5478 Assert(0);
5479 return STATUS_INVALID_PARAMETER;
5480 }
5481 if (pRender->DmaSize < cbDma)
5482 {
5483 Assert(0);
5484 return STATUS_INVALID_PARAMETER;
5485 }
5486
5487 if (pRender->PatchLocationListOutSize < pInputHdr->u32CmdReserved)
5488 {
5489 Assert(0);
5490 return STATUS_INVALID_PARAMETER;
5491 }
5492
5493 PVBOXWDDM_CONTEXT pContext = (PVBOXWDDM_CONTEXT)hContext;
5494 PVBOXWDDM_DEVICE pDevice = pContext->pDevice;
5495 PVBOXMP_DEVEXT pDevExt = pDevice->pAdapter;
5496
5497 pChromiumCmd->Base.enmCmd = VBOXVDMACMD_TYPE_CHROMIUM_CMD;
5498 pChromiumCmd->Base.u32CmdReserved = pInputHdr->u32CmdReserved;
5499 pRender->pDmaBufferPrivateData = (uint8_t*)pRender->pDmaBufferPrivateData + cbDma;
5500 pRender->pDmaBuffer = ((uint8_t*)pRender->pDmaBuffer) + cbDma;
5501 D3DDDI_PATCHLOCATIONLIST* pPLL = pRender->pPatchLocationListOut;
5502 memset(pPLL, 0, sizeof (*pPLL) * pChromiumCmd->Base.u32CmdReserved);
5503 pRender->pPatchLocationListOut += pInputHdr->u32CmdReserved;
5504 PVBOXWDDM_UHGSMI_BUFFER_SUBMIT_INFO pSubmInfo = pChromiumCmd->aBufInfos;
5505 PVBOXWDDM_UHGSMI_BUFFER_UI_SUBMIT_INFO pSubmUmInfo = pUmCmd->aBufInfos;
5506 DXGK_ALLOCATIONLIST *pAllocationList = pRender->pAllocationList;
5507 for (UINT i = 0; i < pChromiumCmd->Base.u32CmdReserved; ++i)
5508 {
5509 PVBOXWDDM_ALLOCATION pAlloc = vboxWddmGetAllocationFromAllocList(pDevExt, pAllocationList);
5510 vboxWddmPopulateDmaAllocInfoWithOffset(&pSubmInfo->Alloc, pAlloc, pAllocationList, pSubmUmInfo->offData);
5511
5512 pSubmInfo->cbData = pSubmUmInfo->cbData;
5513 pSubmInfo->bDoNotSignalCompletion = pSubmUmInfo->bDoNotSignalCompletion;
5514
5515 pPLL->AllocationIndex = i;
5516 pPLL->PatchOffset = RT_OFFSETOF(VBOXWDDM_DMA_PRIVATEDATA_CHROMIUM_CMD, aBufInfos[i].Alloc);
5517 pPLL->AllocationOffset = pSubmUmInfo->offData;
5518
5519 ++pPLL;
5520 ++pSubmInfo;
5521 ++pSubmUmInfo;
5522 ++pAllocationList;
5523 }
5524
5525 break;
5526 }
5527 case VBOXVDMACMD_TYPE_DMA_NOP:
5528 {
5529 PVBOXWDDM_DMA_PRIVATEDATA_BASEHDR pPrivateData = (PVBOXWDDM_DMA_PRIVATEDATA_BASEHDR)pRender->pDmaBufferPrivateData;
5530 pPrivateData->enmCmd = VBOXVDMACMD_TYPE_DMA_NOP;
5531
5532 pRender->pDmaBufferPrivateData = (uint8_t*)pRender->pDmaBufferPrivateData + sizeof (VBOXWDDM_DMA_PRIVATEDATA_BASEHDR);
5533 pRender->pDmaBuffer = ((uint8_t*)pRender->pDmaBuffer) + pRender->CommandLength;
5534 Assert(pRender->DmaSize >= pRender->CommandLength);
5535 Assert(pRender->PatchLocationListOutSize >= pRender->PatchLocationListInSize);
5536 UINT cbPLL = pRender->PatchLocationListInSize * sizeof (pRender->pPatchLocationListOut[0]);
5537 memcpy(pRender->pPatchLocationListOut, pRender->pPatchLocationListIn, cbPLL);
5538 pRender->pPatchLocationListOut += pRender->PatchLocationListInSize;
5539 break;
5540 }
5541 default:
5542 return STATUS_INVALID_PARAMETER;
5543 }
5544
5545// LOGF(("LEAVE, hContext(0x%x)", hContext));
5546
5547 return Status;
5548}
5549
5550#define VBOXVDMACMD_DMA_PRESENT_BLT_MINSIZE() (VBOXVDMACMD_SIZE(VBOXVDMACMD_DMA_PRESENT_BLT))
5551#define VBOXVDMACMD_DMA_PRESENT_BLT_SIZE(_c) (VBOXVDMACMD_BODY_FIELD_OFFSET(UINT, VBOXVDMACMD_DMA_PRESENT_BLT, aDstSubRects[_c]))
5552
5553#ifdef VBOX_WITH_VDMA
5554DECLINLINE(VOID) vboxWddmRectlFromRect(const RECT *pRect, PVBOXVDMA_RECTL pRectl)
5555{
5556 pRectl->left = (int16_t)pRect->left;
5557 pRectl->width = (uint16_t)(pRect->right - pRect->left);
5558 pRectl->top = (int16_t)pRect->top;
5559 pRectl->height = (uint16_t)(pRect->bottom - pRect->top);
5560}
5561
5562DECLINLINE(VBOXVDMA_PIXEL_FORMAT) vboxWddmFromPixFormat(D3DDDIFORMAT format)
5563{
5564 return (VBOXVDMA_PIXEL_FORMAT)format;
5565}
5566
5567DECLINLINE(VOID) vboxWddmSurfDescFromAllocation(PVBOXWDDM_ALLOCATION pAllocation, PVBOXVDMA_SURF_DESC pDesc)
5568{
5569 pDesc->width = pAllocation->AllocData.SurfDesc.width;
5570 pDesc->height = pAllocation->AllocData.SurfDesc.height;
5571 pDesc->format = vboxWddmFromPixFormat(pAllocation->AllocData.SurfDesc.format);
5572 pDesc->bpp = pAllocation->AllocData.SurfDesc.bpp;
5573 pDesc->pitch = pAllocation->AllocData.SurfDesc.pitch;
5574 pDesc->fFlags = 0;
5575}
5576#endif
5577
5578DECLINLINE(BOOLEAN) vboxWddmPixFormatConversionSupported(D3DDDIFORMAT From, D3DDDIFORMAT To)
5579{
5580 Assert(From != D3DDDIFMT_UNKNOWN);
5581 Assert(To != D3DDDIFMT_UNKNOWN);
5582 Assert(From == To);
5583 return From == To;
5584}
5585
5586/**
5587 * DxgkDdiPresent
5588 */
5589NTSTATUS
5590APIENTRY
5591DxgkDdiPresent(
5592 CONST HANDLE hContext,
5593 DXGKARG_PRESENT *pPresent)
5594{
5595 PAGED_CODE();
5596
5597// LOGF(("ENTER, hContext(0x%x)", hContext));
5598
5599 vboxVDbgBreakFv();
5600
5601 NTSTATUS Status = STATUS_SUCCESS;
5602 PVBOXWDDM_CONTEXT pContext = (PVBOXWDDM_CONTEXT)hContext;
5603 PVBOXWDDM_DEVICE pDevice = pContext->pDevice;
5604 PVBOXMP_DEVEXT pDevExt = pDevice->pAdapter;
5605
5606 Assert(pPresent->DmaBufferPrivateDataSize >= sizeof (VBOXWDDM_DMA_PRIVATEDATA_PRESENTHDR));
5607 if (pPresent->DmaBufferPrivateDataSize < sizeof (VBOXWDDM_DMA_PRIVATEDATA_PRESENTHDR))
5608 {
5609 LOGREL(("Present->DmaBufferPrivateDataSize(%d) < sizeof VBOXWDDM_DMA_PRIVATEDATA_PRESENTHDR (%d)", pPresent->DmaBufferPrivateDataSize , sizeof (VBOXWDDM_DMA_PRIVATEDATA_PRESENTHDR)));
5610 /* @todo: can this actually happen? what status tu return? */
5611 return STATUS_INVALID_PARAMETER;
5612 }
5613
5614 PVBOXWDDM_DMA_PRIVATEDATA_PRESENTHDR pPrivateData = (PVBOXWDDM_DMA_PRIVATEDATA_PRESENTHDR)pPresent->pDmaBufferPrivateData;
5615 pPrivateData->BaseHdr.fFlags.Value = 0;
5616 uint32_t cContexts3D = ASMAtomicReadU32(&pDevExt->cContexts3D);
5617 uint32_t cContexts2D = ASMAtomicReadU32(&pDevExt->cContexts2D);
5618#define VBOXWDDM_DUMMY_DMABUFFER_SIZE sizeof(RECT)
5619
5620 if (pPresent->Flags.Blt)
5621 {
5622 Assert(pPresent->Flags.Value == 1); /* only Blt is set, we do not support anything else for now */
5623 DXGK_ALLOCATIONLIST *pSrc = &pPresent->pAllocationList[DXGK_PRESENT_SOURCE_INDEX];
5624 DXGK_ALLOCATIONLIST *pDst = &pPresent->pAllocationList[DXGK_PRESENT_DESTINATION_INDEX];
5625 PVBOXWDDM_ALLOCATION pSrcAlloc = vboxWddmGetAllocationFromAllocList(pDevExt, pSrc);
5626 Assert(pSrcAlloc);
5627 if (pSrcAlloc)
5628 {
5629 PVBOXWDDM_ALLOCATION pDstAlloc = vboxWddmGetAllocationFromAllocList(pDevExt, pDst);
5630 Assert(pDstAlloc);
5631 if (pDstAlloc)
5632 {
5633 do
5634 {
5635#ifdef VBOXWDDM_RENDER_FROM_SHADOW
5636#if 0
5637 Assert (pSrcAlloc->enmType == VBOXWDDM_ALLOC_TYPE_STD_SHADOWSURFACE);
5638 Assert (pDstAlloc->enmType == VBOXWDDM_ALLOC_TYPE_STD_SHAREDPRIMARYSURFACE);
5639#else
5640 if (pContext->enmType == VBOXWDDM_CONTEXT_TYPE_SYSTEM)
5641 {
5642 Assert ((pSrcAlloc->enmType == VBOXWDDM_ALLOC_TYPE_STD_SHADOWSURFACE
5643 && pDstAlloc->enmType == VBOXWDDM_ALLOC_TYPE_STD_SHAREDPRIMARYSURFACE)
5644 || (pSrcAlloc->enmType == VBOXWDDM_ALLOC_TYPE_STD_SHAREDPRIMARYSURFACE
5645 && pDstAlloc->enmType == VBOXWDDM_ALLOC_TYPE_STD_SHADOWSURFACE));
5646 }
5647#endif
5648 /* issue VBOXWDDM_ALLOC_TYPE_STD_SHADOWSURFACE ONLY in case there are no 3D contexts currently
5649 * otherwise we would need info about all rects being updated on primary for visible rect reporting */
5650 if (!cContexts3D && !cContexts2D)
5651 {
5652 if (pDstAlloc->enmType == VBOXWDDM_ALLOC_TYPE_STD_SHAREDPRIMARYSURFACE
5653 && pSrcAlloc->enmType == VBOXWDDM_ALLOC_TYPE_STD_SHADOWSURFACE)
5654 {
5655 Assert(pContext->enmType == VBOXWDDM_CONTEXT_TYPE_SYSTEM);
5656 Assert(pDstAlloc->bAssigned);
5657 if (pDstAlloc->bAssigned)
5658 {
5659#ifdef VBOX_WITH_VIDEOHWACCEL
5660// if (vboxVhwaHlpOverlayListIsEmpty(pDevExt, pDstAlloc->AllocData.SurfDesc.VidPnSourceId))
5661#endif
5662 {
5663 Assert(pPresent->DmaBufferPrivateDataSize >= sizeof (VBOXWDDM_DMA_PRIVATEDATA_SHADOW2PRIMARY));
5664 if (pPresent->DmaBufferPrivateDataSize >= sizeof (VBOXWDDM_DMA_PRIVATEDATA_SHADOW2PRIMARY))
5665 {
5666 Assert(pPresent->SrcRect.left == pPresent->DstRect.left);
5667 Assert(pPresent->SrcRect.right == pPresent->DstRect.right);
5668 Assert(pPresent->SrcRect.top == pPresent->DstRect.top);
5669 Assert(pPresent->SrcRect.bottom == pPresent->DstRect.bottom);
5670 RECT rect;
5671 if (pPresent->SubRectCnt)
5672 {
5673 rect = pPresent->pDstSubRects[0];
5674 for (UINT i = 1; i < pPresent->SubRectCnt; ++i)
5675 {
5676 vboxWddmRectUnited(&rect, &rect, &pPresent->pDstSubRects[i]);
5677 }
5678 }
5679 else
5680 rect = pPresent->SrcRect;
5681
5682
5683 pPresent->pDmaBufferPrivateData = (uint8_t*)pPresent->pDmaBufferPrivateData + sizeof (VBOXWDDM_DMA_PRIVATEDATA_SHADOW2PRIMARY);
5684 pPresent->pDmaBuffer = ((uint8_t*)pPresent->pDmaBuffer) + VBOXWDDM_DUMMY_DMABUFFER_SIZE;
5685 Assert(pPresent->DmaSize >= VBOXWDDM_DUMMY_DMABUFFER_SIZE);
5686 memset(pPresent->pPatchLocationListOut, 0, 2*sizeof (D3DDDI_PATCHLOCATIONLIST));
5687 pPresent->pPatchLocationListOut->PatchOffset = 0;
5688 pPresent->pPatchLocationListOut->AllocationIndex = DXGK_PRESENT_SOURCE_INDEX;
5689 ++pPresent->pPatchLocationListOut;
5690 pPresent->pPatchLocationListOut->PatchOffset = 4;
5691 pPresent->pPatchLocationListOut->AllocationIndex = DXGK_PRESENT_DESTINATION_INDEX;
5692 ++pPresent->pPatchLocationListOut;
5693
5694 pPrivateData->BaseHdr.enmCmd = VBOXVDMACMD_TYPE_DMA_PRESENT_SHADOW2PRIMARY;
5695 PVBOXWDDM_DMA_PRIVATEDATA_SHADOW2PRIMARY pS2P = (PVBOXWDDM_DMA_PRIVATEDATA_SHADOW2PRIMARY)pPrivateData;
5696 /* we do not know the shadow address yet, perform dummy DMA cycle */
5697 vboxWddmPopulateDmaAllocInfo(&pS2P->Shadow2Primary.ShadowAlloc, pSrcAlloc, pSrc);
5698// vboxWddmPopulateDmaAllocInfo(&pPrivateData->DstAllocInfo, pDstAlloc, pDst);
5699 pS2P->Shadow2Primary.SrcRect = rect;
5700 pS2P->Shadow2Primary.VidPnSourceId = pDstAlloc->AllocData.SurfDesc.VidPnSourceId;
5701 break;
5702 }
5703 else
5704 {
5705 Status = STATUS_GRAPHICS_INSUFFICIENT_DMA_BUFFER;
5706 break;
5707 }
5708 }
5709 }
5710 }
5711 }
5712
5713 /* we're here because this is NOT a shadow->primary update
5714 * or because there are d3d contexts and we need to report visible rects
5715 * or because we have overlays active and we need a special handling for primary */
5716#endif
5717 UINT cbCmd = pPresent->DmaBufferPrivateDataSize;
5718 pPrivateData->BaseHdr.enmCmd = VBOXVDMACMD_TYPE_DMA_PRESENT_BLT;
5719
5720 PVBOXWDDM_DMA_PRIVATEDATA_BLT pBlt = (PVBOXWDDM_DMA_PRIVATEDATA_BLT)pPrivateData;
5721
5722 vboxWddmPopulateDmaAllocInfo(&pBlt->Blt.SrcAlloc, pSrcAlloc, pSrc);
5723 vboxWddmPopulateDmaAllocInfo(&pBlt->Blt.DstAlloc, pDstAlloc, pDst);
5724
5725 ASSERT_WARN(!pSrcAlloc->fRcFlags.SharedResource, ("Shared Allocatoin used in Present!"));
5726
5727 pBlt->Blt.SrcRect = pPresent->SrcRect;
5728 pBlt->Blt.DstRects.ContextRect = pPresent->DstRect;
5729 pBlt->Blt.DstRects.UpdateRects.cRects = 0;
5730 UINT cbHead = RT_OFFSETOF(VBOXWDDM_DMA_PRIVATEDATA_BLT, Blt.DstRects.UpdateRects.aRects[0]);
5731 Assert(pPresent->SubRectCnt > pPresent->MultipassOffset);
5732 UINT cbRects = (pPresent->SubRectCnt - pPresent->MultipassOffset) * sizeof (RECT);
5733 pPresent->pDmaBufferPrivateData = (uint8_t*)pPresent->pDmaBufferPrivateData + cbHead + cbRects;
5734 pPresent->pDmaBuffer = ((uint8_t*)pPresent->pDmaBuffer) + VBOXWDDM_DUMMY_DMABUFFER_SIZE;
5735 Assert(pPresent->DmaSize >= VBOXWDDM_DUMMY_DMABUFFER_SIZE);
5736 cbCmd -= cbHead;
5737 Assert(cbCmd < UINT32_MAX/2);
5738 Assert(cbCmd > sizeof (RECT));
5739 if (cbCmd >= cbRects)
5740 {
5741 cbCmd -= cbRects;
5742 memcpy(&pBlt->Blt.DstRects.UpdateRects.aRects[pPresent->MultipassOffset], pPresent->pDstSubRects, cbRects);
5743 pBlt->Blt.DstRects.UpdateRects.cRects += cbRects/sizeof (RECT);
5744 }
5745 else
5746 {
5747 UINT cbFitingRects = (cbCmd/sizeof (RECT)) * sizeof (RECT);
5748 Assert(cbFitingRects);
5749 memcpy(&pBlt->Blt.DstRects.UpdateRects.aRects[pPresent->MultipassOffset], pPresent->pDstSubRects, cbFitingRects);
5750 cbCmd -= cbFitingRects;
5751 pPresent->MultipassOffset += cbFitingRects/sizeof (RECT);
5752 pBlt->Blt.DstRects.UpdateRects.cRects += cbFitingRects/sizeof (RECT);
5753 Assert(pPresent->SubRectCnt > pPresent->MultipassOffset);
5754 Status = STATUS_GRAPHICS_INSUFFICIENT_DMA_BUFFER;
5755 }
5756
5757 memset(pPresent->pPatchLocationListOut, 0, 2*sizeof (D3DDDI_PATCHLOCATIONLIST));
5758 pPresent->pPatchLocationListOut->PatchOffset = 0;
5759 pPresent->pPatchLocationListOut->AllocationIndex = DXGK_PRESENT_SOURCE_INDEX;
5760 ++pPresent->pPatchLocationListOut;
5761 pPresent->pPatchLocationListOut->PatchOffset = 4;
5762 pPresent->pPatchLocationListOut->AllocationIndex = DXGK_PRESENT_DESTINATION_INDEX;
5763 ++pPresent->pPatchLocationListOut;
5764
5765 break;
5766#ifdef VBOX_WITH_VDMA
5767 cbCmd = pPresent->DmaSize;
5768
5769 Assert(pPresent->SubRectCnt);
5770 UINT cmdSize = VBOXVDMACMD_DMA_PRESENT_BLT_SIZE(pPresent->SubRectCnt - pPresent->MultipassOffset);
5771 PVBOXVDMACMD pCmd = (PVBOXVDMACMD)pPresent->pDmaBuffer;
5772 pPresent->pDmaBuffer = ((uint8_t*)pPresent->pDmaBuffer) + cmdSize;
5773 Assert(cbCmd >= VBOXVDMACMD_DMA_PRESENT_BLT_MINSIZE());
5774 if (cbCmd >= VBOXVDMACMD_DMA_PRESENT_BLT_MINSIZE())
5775 {
5776 if (vboxWddmPixFormatConversionSupported(pSrcAlloc->AllocData.SurfDesc.format, pDstAlloc->AllocData.SurfDesc.format))
5777 {
5778 memset(pPresent->pPatchLocationListOut, 0, 2*sizeof (D3DDDI_PATCHLOCATIONLIST));
5779 // pPresent->pPatchLocationListOut->PatchOffset = 0;
5780 // ++pPresent->pPatchLocationListOut;
5781 pPresent->pPatchLocationListOut->PatchOffset = VBOXVDMACMD_BODY_FIELD_OFFSET(UINT, VBOXVDMACMD_DMA_PRESENT_BLT, offSrc);
5782 pPresent->pPatchLocationListOut->AllocationIndex = DXGK_PRESENT_SOURCE_INDEX;
5783 ++pPresent->pPatchLocationListOut;
5784 pPresent->pPatchLocationListOut->PatchOffset = VBOXVDMACMD_BODY_FIELD_OFFSET(UINT, VBOXVDMACMD_DMA_PRESENT_BLT, offDst);
5785 pPresent->pPatchLocationListOut->AllocationIndex = DXGK_PRESENT_DESTINATION_INDEX;
5786 ++pPresent->pPatchLocationListOut;
5787
5788 pCmd->enmType = VBOXVDMACMD_TYPE_DMA_PRESENT_BLT;
5789 pCmd->u32CmdSpecific = 0;
5790 PVBOXVDMACMD_DMA_PRESENT_BLT pTransfer = VBOXVDMACMD_BODY(pCmd, VBOXVDMACMD_DMA_PRESENT_BLT);
5791 pTransfer->offSrc = (VBOXVIDEOOFFSET)pSrc->PhysicalAddress.QuadPart;
5792 pTransfer->offDst = (VBOXVIDEOOFFSET)pDst->PhysicalAddress.QuadPart;
5793 vboxWddmSurfDescFromAllocation(pSrcAlloc, &pTransfer->srcDesc);
5794 vboxWddmSurfDescFromAllocation(pDstAlloc, &pTransfer->dstDesc);
5795 vboxWddmRectlFromRect(&pPresent->SrcRect, &pTransfer->srcRectl);
5796 vboxWddmRectlFromRect(&pPresent->DstRect, &pTransfer->dstRectl);
5797 UINT i = 0;
5798 cbCmd -= VBOXVDMACMD_BODY_FIELD_OFFSET(UINT, VBOXVDMACMD_DMA_PRESENT_BLT, aDstSubRects);
5799 Assert(cbCmd >= sizeof (VBOXVDMA_RECTL));
5800 Assert(cbCmd < pPresent->DmaSize);
5801 for (; i < pPresent->SubRectCnt; ++i)
5802 {
5803 if (cbCmd < sizeof (VBOXVDMA_RECTL))
5804 {
5805 Assert(i);
5806 pPresent->MultipassOffset += i;
5807 Status = STATUS_GRAPHICS_INSUFFICIENT_DMA_BUFFER;
5808 break;
5809 }
5810 vboxWddmRectlFromRect(&pPresent->pDstSubRects[i + pPresent->MultipassOffset], &pTransfer->aDstSubRects[i]);
5811 cbCmd -= sizeof (VBOXVDMA_RECTL);
5812 }
5813 Assert(i);
5814 pPrivateData->BaseHdr.enmCmd = VBOXVDMACMD_TYPE_DMA_PRESENT_BLT;
5815 pTransfer->cDstSubRects = i;
5816 pPresent->pDmaBufferPrivateData = (uint8_t*)pPresent->pDmaBufferPrivateData + sizeof(VBOXWDDM_DMA_PRIVATEDATA_PRESENTHDR);
5817 }
5818 else
5819 {
5820 AssertBreakpoint();
5821 LOGREL(("unsupported format conversion from(%d) to (%d)",pSrcAlloc->AllocData.SurfDesc.format, pDstAlloc->AllocData.SurfDesc.format));
5822 Status = STATUS_GRAPHICS_CANNOTCOLORCONVERT;
5823 }
5824 }
5825 else
5826 {
5827 /* this should not happen actually */
5828 LOGREL(("cbCmd too small!! (%d)", cbCmd));
5829 Status = STATUS_GRAPHICS_INSUFFICIENT_DMA_BUFFER;
5830 }
5831#endif
5832 } while(0);
5833 }
5834 else
5835 {
5836 /* this should not happen actually */
5837 LOGREL(("failed to get Dst Allocation info for hDeviceSpecificAllocation(0x%x)",pDst->hDeviceSpecificAllocation));
5838 Status = STATUS_INVALID_HANDLE;
5839 }
5840 }
5841 else
5842 {
5843 /* this should not happen actually */
5844 LOGREL(("failed to get Src Allocation info for hDeviceSpecificAllocation(0x%x)",pSrc->hDeviceSpecificAllocation));
5845 Status = STATUS_INVALID_HANDLE;
5846 }
5847#if 0
5848 UINT cbCmd = pPresent->DmaSize;
5849
5850 Assert(pPresent->SubRectCnt);
5851 UINT cmdSize = VBOXVDMACMD_DMA_PRESENT_BLT_SIZE(pPresent->SubRectCnt - pPresent->MultipassOffset);
5852 PVBOXVDMACMD pCmd = (PVBOXVDMACMD)pPresent->pDmaBuffer;
5853 pPresent->pDmaBuffer = ((uint8_t*)pPresent->pDmaBuffer) + cmdSize;
5854 Assert(cbCmd >= VBOXVDMACMD_DMA_PRESENT_BLT_MINSIZE());
5855 if (cbCmd >= VBOXVDMACMD_DMA_PRESENT_BLT_MINSIZE())
5856 {
5857 DXGK_ALLOCATIONLIST *pSrc = &pPresent->pAllocationList[DXGK_PRESENT_SOURCE_INDEX];
5858 DXGK_ALLOCATIONLIST *pDst = &pPresent->pAllocationList[DXGK_PRESENT_DESTINATION_INDEX];
5859 PVBOXWDDM_ALLOCATION pSrcAlloc = vboxWddmGetAllocationFromAllocList(pDevExt, pSrc);
5860 Assert(pSrcAlloc);
5861 if (pSrcAlloc)
5862 {
5863 PVBOXWDDM_ALLOCATION pDstAlloc = vboxWddmGetAllocationFromAllocList(pDevExt, pDst);
5864 Assert(pDstAlloc);
5865 if (pDstAlloc)
5866 {
5867 if (vboxWddmPixFormatConversionSupported(pSrcAlloc->AllocData.SurfDesc.format, pDstAlloc->AllocData.SurfDesc.format))
5868 {
5869 memset(pPresent->pPatchLocationListOut, 0, 2*sizeof (D3DDDI_PATCHLOCATIONLIST));
5870// pPresent->pPatchLocationListOut->PatchOffset = 0;
5871// ++pPresent->pPatchLocationListOut;
5872 pPresent->pPatchLocationListOut->PatchOffset = VBOXVDMACMD_BODY_FIELD_OFFSET(UINT, VBOXVDMACMD_DMA_PRESENT_BLT, offSrc);
5873 pPresent->pPatchLocationListOut->AllocationIndex = DXGK_PRESENT_SOURCE_INDEX;
5874 ++pPresent->pPatchLocationListOut;
5875 pPresent->pPatchLocationListOut->PatchOffset = VBOXVDMACMD_BODY_FIELD_OFFSET(UINT, VBOXVDMACMD_DMA_PRESENT_BLT, offDst);
5876 pPresent->pPatchLocationListOut->AllocationIndex = DXGK_PRESENT_DESTINATION_INDEX;
5877 ++pPresent->pPatchLocationListOut;
5878
5879 pCmd->enmType = VBOXVDMACMD_TYPE_DMA_PRESENT_BLT;
5880 pCmd->u32CmdSpecific = 0;
5881 PVBOXVDMACMD_DMA_PRESENT_BLT pTransfer = VBOXVDMACMD_BODY(pCmd, VBOXVDMACMD_DMA_PRESENT_BLT);
5882 pTransfer->offSrc = (VBOXVIDEOOFFSET)pSrc->PhysicalAddress.QuadPart;
5883 pTransfer->offDst = (VBOXVIDEOOFFSET)pDst->PhysicalAddress.QuadPart;
5884 vboxWddmSurfDescFromAllocation(pSrcAlloc, &pTransfer->srcDesc);
5885 vboxWddmSurfDescFromAllocation(pDstAlloc, &pTransfer->dstDesc);
5886 vboxWddmRectlFromRect(&pPresent->SrcRect, &pTransfer->srcRectl);
5887 vboxWddmRectlFromRect(&pPresent->DstRect, &pTransfer->dstRectl);
5888 UINT i = 0;
5889 cbCmd -= VBOXVDMACMD_BODY_FIELD_OFFSET(UINT, VBOXVDMACMD_DMA_PRESENT_BLT, aDstSubRects);
5890 Assert(cbCmd >= sizeof (VBOXVDMA_RECTL));
5891 Assert(cbCmd < pPresent->DmaSize);
5892 for (; i < pPresent->SubRectCnt; ++i)
5893 {
5894 if (cbCmd < sizeof (VBOXVDMA_RECTL))
5895 {
5896 Assert(i);
5897 pPresent->MultipassOffset += i;
5898 Status = STATUS_GRAPHICS_INSUFFICIENT_DMA_BUFFER;
5899 break;
5900 }
5901 vboxWddmRectlFromRect(&pPresent->pDstSubRects[i + pPresent->MultipassOffset], &pTransfer->aDstSubRects[i]);
5902 cbCmd -= sizeof (VBOXVDMA_RECTL);
5903 }
5904 Assert(i);
5905 pTransfer->cDstSubRects = i;
5906 pPresent->pDmaBufferPrivateData = (uint8_t*)pPresent->pDmaBufferPrivateData + sizeof(VBOXWDDM_DMA_PRIVATEDATA_HDR);
5907 }
5908 else
5909 {
5910 AssertBreakpoint();
5911 LOGREL(("unsupported format conversion from(%d) to (%d)",pSrcAlloc->AllocData.SurfDesc.format, pDstAlloc->AllocData.SurfDesc.format));
5912 Status = STATUS_GRAPHICS_CANNOTCOLORCONVERT;
5913 }
5914 }
5915 else
5916 {
5917 /* this should not happen actually */
5918 LOGREL(("failed to get Dst Allocation info for hDeviceSpecificAllocation(0x%x)",pDst->hDeviceSpecificAllocation));
5919 Status = STATUS_INVALID_HANDLE;
5920 }
5921 }
5922 else
5923 {
5924 /* this should not happen actually */
5925 LOGREL(("failed to get Src Allocation info for hDeviceSpecificAllocation(0x%x)",pSrc->hDeviceSpecificAllocation));
5926 Status = STATUS_INVALID_HANDLE;
5927 }
5928 }
5929 else
5930 {
5931 /* this should not happen actually */
5932 LOGREL(("cbCmd too small!! (%d)", cbCmd));
5933 Status = STATUS_GRAPHICS_INSUFFICIENT_DMA_BUFFER;
5934 }
5935#endif
5936 }
5937 else if (pPresent->Flags.Flip)
5938 {
5939 Assert(pPresent->Flags.Value == 4); /* only Blt is set, we do not support anything else for now */
5940 Assert(pContext->enmType == VBOXWDDM_CONTEXT_TYPE_CUSTOM_3D);
5941 DXGK_ALLOCATIONLIST *pSrc = &pPresent->pAllocationList[DXGK_PRESENT_SOURCE_INDEX];
5942 PVBOXWDDM_ALLOCATION pSrcAlloc = vboxWddmGetAllocationFromAllocList(pDevExt, pSrc);
5943 Assert(pSrcAlloc);
5944 if (pSrcAlloc)
5945 {
5946 Assert(cContexts3D);
5947 pPrivateData->BaseHdr.enmCmd = VBOXVDMACMD_TYPE_DMA_PRESENT_FLIP;
5948 PVBOXWDDM_DMA_PRIVATEDATA_FLIP pFlip = (PVBOXWDDM_DMA_PRIVATEDATA_FLIP)pPrivateData;
5949
5950 vboxWddmPopulateDmaAllocInfo(&pFlip->Flip.Alloc, pSrcAlloc, pSrc);
5951
5952 UINT cbCmd = sizeof (VBOXWDDM_DMA_PRIVATEDATA_FLIP);
5953 pPresent->pDmaBufferPrivateData = (uint8_t*)pPresent->pDmaBufferPrivateData + cbCmd;
5954 pPresent->pDmaBuffer = ((uint8_t*)pPresent->pDmaBuffer) + VBOXWDDM_DUMMY_DMABUFFER_SIZE;
5955 Assert(pPresent->DmaSize >= VBOXWDDM_DUMMY_DMABUFFER_SIZE);
5956
5957 memset(pPresent->pPatchLocationListOut, 0, sizeof (D3DDDI_PATCHLOCATIONLIST));
5958 pPresent->pPatchLocationListOut->PatchOffset = 0;
5959 pPresent->pPatchLocationListOut->AllocationIndex = DXGK_PRESENT_SOURCE_INDEX;
5960 ++pPresent->pPatchLocationListOut;
5961 }
5962 else
5963 {
5964 /* this should not happen actually */
5965 LOGREL(("failed to get pSrc Allocation info for hDeviceSpecificAllocation(0x%x)",pSrc->hDeviceSpecificAllocation));
5966 Status = STATUS_INVALID_HANDLE;
5967 }
5968 }
5969 else if (pPresent->Flags.ColorFill)
5970 {
5971 Assert(pContext->enmType == VBOXWDDM_CONTEXT_TYPE_CUSTOM_2D);
5972 Assert(pPresent->Flags.Value == 2); /* only ColorFill is set, we do not support anything else for now */
5973 DXGK_ALLOCATIONLIST *pDst = &pPresent->pAllocationList[DXGK_PRESENT_DESTINATION_INDEX];
5974 PVBOXWDDM_ALLOCATION pDstAlloc = vboxWddmGetAllocationFromAllocList(pDevExt, pDst);
5975 Assert(pDstAlloc);
5976 if (pDstAlloc)
5977 {
5978 UINT cbCmd = pPresent->DmaBufferPrivateDataSize;
5979 pPrivateData->BaseHdr.enmCmd = VBOXVDMACMD_TYPE_DMA_PRESENT_CLRFILL;
5980 PVBOXWDDM_DMA_PRIVATEDATA_CLRFILL pCF = (PVBOXWDDM_DMA_PRIVATEDATA_CLRFILL)pPrivateData;
5981
5982 vboxWddmPopulateDmaAllocInfo(&pCF->ClrFill.Alloc, pDstAlloc, pDst);
5983
5984 pCF->ClrFill.Color = pPresent->Color;
5985 pCF->ClrFill.Rects.cRects = 0;
5986 UINT cbHead = RT_OFFSETOF(VBOXWDDM_DMA_PRIVATEDATA_CLRFILL, ClrFill.Rects.aRects[0]);
5987 Assert(pPresent->SubRectCnt > pPresent->MultipassOffset);
5988 UINT cbRects = (pPresent->SubRectCnt - pPresent->MultipassOffset) * sizeof (RECT);
5989 pPresent->pDmaBufferPrivateData = (uint8_t*)pPresent->pDmaBufferPrivateData + cbHead + cbRects;
5990 pPresent->pDmaBuffer = ((uint8_t*)pPresent->pDmaBuffer) + VBOXWDDM_DUMMY_DMABUFFER_SIZE;
5991 Assert(pPresent->DmaSize >= VBOXWDDM_DUMMY_DMABUFFER_SIZE);
5992 cbCmd -= cbHead;
5993 Assert(cbCmd < UINT32_MAX/2);
5994 Assert(cbCmd > sizeof (RECT));
5995 if (cbCmd >= cbRects)
5996 {
5997 cbCmd -= cbRects;
5998 memcpy(&pCF->ClrFill.Rects.aRects[pPresent->MultipassOffset], pPresent->pDstSubRects, cbRects);
5999 pCF->ClrFill.Rects.cRects += cbRects/sizeof (RECT);
6000 }
6001 else
6002 {
6003 UINT cbFitingRects = (cbCmd/sizeof (RECT)) * sizeof (RECT);
6004 Assert(cbFitingRects);
6005 memcpy(&pCF->ClrFill.Rects.aRects[pPresent->MultipassOffset], pPresent->pDstSubRects, cbFitingRects);
6006 cbCmd -= cbFitingRects;
6007 pPresent->MultipassOffset += cbFitingRects/sizeof (RECT);
6008 pCF->ClrFill.Rects.cRects += cbFitingRects/sizeof (RECT);
6009 Assert(pPresent->SubRectCnt > pPresent->MultipassOffset);
6010 Status = STATUS_GRAPHICS_INSUFFICIENT_DMA_BUFFER;
6011 }
6012
6013 memset(pPresent->pPatchLocationListOut, 0, sizeof (D3DDDI_PATCHLOCATIONLIST));
6014 pPresent->pPatchLocationListOut->PatchOffset = 0;
6015 pPresent->pPatchLocationListOut->AllocationIndex = DXGK_PRESENT_DESTINATION_INDEX;
6016 ++pPresent->pPatchLocationListOut;
6017 }
6018 else
6019 {
6020 /* this should not happen actually */
6021 LOGREL(("failed to get pDst Allocation info for hDeviceSpecificAllocation(0x%x)",pDst->hDeviceSpecificAllocation));
6022 Status = STATUS_INVALID_HANDLE;
6023 }
6024
6025 }
6026 else
6027 {
6028 LOGREL(("cmd NOT IMPLEMENTED!! Flags(0x%x)", pPresent->Flags.Value));
6029 AssertBreakpoint();
6030 }
6031
6032// LOGF(("LEAVE, hContext(0x%x), Status(0x%x)", hContext, Status));
6033
6034 return Status;
6035}
6036
6037NTSTATUS
6038APIENTRY
6039DxgkDdiUpdateOverlay(
6040 CONST HANDLE hOverlay,
6041 CONST DXGKARG_UPDATEOVERLAY *pUpdateOverlay)
6042{
6043 LOGF(("ENTER, hOverlay(0x%p)", hOverlay));
6044
6045 NTSTATUS Status = STATUS_SUCCESS;
6046 PVBOXWDDM_OVERLAY pOverlay = (PVBOXWDDM_OVERLAY)hOverlay;
6047 Assert(pOverlay);
6048 int rc = vboxVhwaHlpOverlayUpdate(pOverlay, &pUpdateOverlay->OverlayInfo);
6049 AssertRC(rc);
6050 if (RT_SUCCESS(rc))
6051 {
6052 RECT DstRect;
6053 vboxVhwaHlpOverlayDstRectGet(pOverlay->pDevExt, pOverlay, &DstRect);
6054 Status = vboxVdmaHlpUpdatePrimary(pOverlay->pDevExt, pOverlay->VidPnSourceId, &DstRect);
6055 Assert(Status == STATUS_SUCCESS);
6056 }
6057 else
6058 Status = STATUS_UNSUCCESSFUL;
6059
6060 LOGF(("LEAVE, hOverlay(0x%p)", hOverlay));
6061
6062 return Status;
6063}
6064
6065NTSTATUS
6066APIENTRY
6067DxgkDdiFlipOverlay(
6068 CONST HANDLE hOverlay,
6069 CONST DXGKARG_FLIPOVERLAY *pFlipOverlay)
6070{
6071 LOGF(("ENTER, hOverlay(0x%p)", hOverlay));
6072
6073 NTSTATUS Status = STATUS_SUCCESS;
6074 PVBOXWDDM_OVERLAY pOverlay = (PVBOXWDDM_OVERLAY)hOverlay;
6075 Assert(pOverlay);
6076 int rc = vboxVhwaHlpOverlayFlip(pOverlay, pFlipOverlay);
6077 AssertRC(rc);
6078 if (RT_FAILURE(rc))
6079 Status = STATUS_UNSUCCESSFUL;
6080
6081 LOGF(("LEAVE, hOverlay(0x%p)", hOverlay));
6082
6083 return Status;
6084}
6085
6086NTSTATUS
6087APIENTRY
6088DxgkDdiDestroyOverlay(
6089 CONST HANDLE hOverlay)
6090{
6091 LOGF(("ENTER, hOverlay(0x%p)", hOverlay));
6092
6093 NTSTATUS Status = STATUS_SUCCESS;
6094 PVBOXWDDM_OVERLAY pOverlay = (PVBOXWDDM_OVERLAY)hOverlay;
6095 Assert(pOverlay);
6096 int rc = vboxVhwaHlpOverlayDestroy(pOverlay);
6097 AssertRC(rc);
6098 if (RT_SUCCESS(rc))
6099 vboxWddmMemFree(pOverlay);
6100 else
6101 Status = STATUS_UNSUCCESSFUL;
6102
6103 LOGF(("LEAVE, hOverlay(0x%p)", hOverlay));
6104
6105 return Status;
6106}
6107
6108/**
6109 * DxgkDdiCreateContext
6110 */
6111NTSTATUS
6112APIENTRY
6113DxgkDdiCreateContext(
6114 CONST HANDLE hDevice,
6115 DXGKARG_CREATECONTEXT *pCreateContext)
6116{
6117 /* DxgkDdiCreateContext should be made pageable */
6118 PAGED_CODE();
6119
6120 LOGF(("ENTER, hDevice(0x%x)", hDevice));
6121
6122 vboxVDbgBreakFv();
6123
6124 if (pCreateContext->NodeOrdinal >= VBOXWDDM_NUM_NODES)
6125 {
6126 WARN(("Invalid NodeOrdinal (%d), expected to be less that (%d)\n", pCreateContext->NodeOrdinal, VBOXWDDM_NUM_NODES));
6127 return STATUS_INVALID_PARAMETER;
6128 }
6129
6130 NTSTATUS Status = STATUS_SUCCESS;
6131 PVBOXWDDM_DEVICE pDevice = (PVBOXWDDM_DEVICE)hDevice;
6132 PVBOXMP_DEVEXT pDevExt = pDevice->pAdapter;
6133 PVBOXWDDM_CONTEXT pContext = (PVBOXWDDM_CONTEXT)vboxWddmMemAllocZero(sizeof (VBOXWDDM_CONTEXT));
6134 Assert(pContext);
6135 if (pContext)
6136 {
6137 pContext->pDevice = pDevice;
6138 pContext->hContext = pCreateContext->hContext;
6139 pContext->EngineAffinity = pCreateContext->EngineAffinity;
6140 pContext->NodeOrdinal = pCreateContext->NodeOrdinal;
6141 vboxVideoCmCtxInitEmpty(&pContext->CmContext);
6142 if (pCreateContext->Flags.SystemContext || pCreateContext->PrivateDriverDataSize == 0)
6143 {
6144 Assert(pCreateContext->PrivateDriverDataSize == 0);
6145 Assert(!pCreateContext->pPrivateDriverData);
6146 Assert(pCreateContext->Flags.Value <= 2); /* 2 is a GDI context in Win7 */
6147 pContext->enmType = VBOXWDDM_CONTEXT_TYPE_SYSTEM;
6148 for (int i = 0; i < VBoxCommonFromDeviceExt(pDevExt)->cDisplays; ++i)
6149 {
6150 pDevExt->aSources[i].fGhSynced = 0;
6151 NTSTATUS tmpStatus= vboxWddmDisplaySettingsQueryPos(pDevExt, i, &pDevExt->aSources[i].VScreenPos);
6152 Assert(tmpStatus == STATUS_SUCCESS);
6153 }
6154 }
6155 else
6156 {
6157 Assert(pCreateContext->Flags.Value == 0);
6158 Assert(pCreateContext->PrivateDriverDataSize == sizeof (VBOXWDDM_CREATECONTEXT_INFO));
6159 Assert(pCreateContext->pPrivateDriverData);
6160 if (pCreateContext->PrivateDriverDataSize == sizeof (VBOXWDDM_CREATECONTEXT_INFO))
6161 {
6162 PVBOXWDDM_CREATECONTEXT_INFO pInfo = (PVBOXWDDM_CREATECONTEXT_INFO)pCreateContext->pPrivateDriverData;
6163 switch (pInfo->enmType)
6164 {
6165 case VBOXWDDM_CONTEXT_TYPE_CUSTOM_3D:
6166 {
6167 Status = vboxVideoAMgrCtxCreate(&pDevExt->AllocMgr, &pContext->AllocContext);
6168 Assert(Status == STATUS_SUCCESS);
6169 if (Status == STATUS_SUCCESS)
6170 {
6171 Status = vboxWddmSwapchainCtxInit(pDevExt, pContext);
6172 Assert(Status == STATUS_SUCCESS);
6173 if (Status == STATUS_SUCCESS)
6174 {
6175 pContext->enmType = VBOXWDDM_CONTEXT_TYPE_CUSTOM_3D;
6176 Status = vboxVideoCmCtxAdd(&pDevice->pAdapter->CmMgr, &pContext->CmContext, (HANDLE)pInfo->hUmEvent, pInfo->u64UmInfo);
6177 Assert(Status == STATUS_SUCCESS);
6178 if (Status == STATUS_SUCCESS)
6179 {
6180 int rc = VINF_SUCCESS;
6181 if (pInfo->crVersionMajor || pInfo->crVersionMinor)
6182 {
6183 rc = VBoxMpCrCtlConConnect(&pDevExt->CrCtlCon,
6184 pInfo->crVersionMajor, pInfo->crVersionMinor,
6185 &pContext->u32CrConClientID);
6186 if (RT_SUCCESS(rc))
6187 {
6188#ifdef VBOX_WDDM_MINIPORT_WITH_VISIBLE_RECTS
6189 VBoxMpCrPackerInit(&pContext->CrPacker);
6190#endif
6191 }
6192 else
6193 {
6194 WARN(("VBoxMpCrCtlConConnect failed rc (%d)", rc));
6195 Status = STATUS_UNSUCCESSFUL;
6196 }
6197 }
6198
6199 if (RT_SUCCESS(rc))
6200 {
6201 ASMAtomicIncU32(&pDevExt->cContexts3D);
6202 break;
6203 }
6204 }
6205
6206 vboxWddmSwapchainCtxTerm(pDevExt, pContext);
6207 }
6208 vboxVideoAMgrCtxDestroy(&pContext->AllocContext);
6209 }
6210 break;
6211 }
6212 case VBOXWDDM_CONTEXT_TYPE_CUSTOM_UHGSMI_3D:
6213 case VBOXWDDM_CONTEXT_TYPE_CUSTOM_UHGSMI_GL:
6214 {
6215 pContext->enmType = pInfo->enmType;
6216 Status = vboxVideoAMgrCtxCreate(&pDevExt->AllocMgr, &pContext->AllocContext);
6217 Assert(Status == STATUS_SUCCESS);
6218 if (Status == STATUS_SUCCESS)
6219 {
6220 int rc = VINF_SUCCESS;
6221 if (pInfo->crVersionMajor || pInfo->crVersionMinor)
6222 {
6223 rc = VBoxMpCrCtlConConnect(&pDevExt->CrCtlCon,
6224 pInfo->crVersionMajor, pInfo->crVersionMinor,
6225 &pContext->u32CrConClientID);
6226 if (!RT_SUCCESS(rc))
6227 {
6228 WARN(("VBoxMpCrCtlConConnect failed rc (%d)", rc));
6229 Status = STATUS_UNSUCCESSFUL;
6230 }
6231 }
6232
6233 if (RT_SUCCESS(rc))
6234 {
6235 ASMAtomicIncU32(&pDevExt->cContexts3D);
6236 break;
6237 }
6238 vboxVideoAMgrCtxDestroy(&pContext->AllocContext);
6239 }
6240 break;
6241 }
6242 case VBOXWDDM_CONTEXT_TYPE_CUSTOM_2D:
6243 {
6244 pContext->enmType = pInfo->enmType;
6245 ASMAtomicIncU32(&pDevExt->cContexts2D);
6246 break;
6247 }
6248 default:
6249 {
6250 Assert(0);
6251 Status = STATUS_INVALID_PARAMETER;
6252 break;
6253 }
6254 }
6255 }
6256 }
6257
6258 if (Status == STATUS_SUCCESS)
6259 {
6260 pCreateContext->hContext = pContext;
6261 pCreateContext->ContextInfo.DmaBufferSize = VBOXWDDM_C_DMA_BUFFER_SIZE;
6262 pCreateContext->ContextInfo.DmaBufferSegmentSet = 0;
6263 pCreateContext->ContextInfo.DmaBufferPrivateDataSize = VBOXWDDM_C_DMA_PRIVATEDATA_SIZE;
6264 pCreateContext->ContextInfo.AllocationListSize = VBOXWDDM_C_ALLOC_LIST_SIZE;
6265 pCreateContext->ContextInfo.PatchLocationListSize = VBOXWDDM_C_PATH_LOCATION_LIST_SIZE;
6266 //#if (DXGKDDI_INTERFACE_VERSION >= DXGKDDI_INTERFACE_VERSION_WIN7)
6267 //# error port to Win7 DDI
6268 // //pCreateContext->ContextInfo.DmaBufferAllocationGroup = ???;
6269 //#endif // DXGKDDI_INTERFACE_VERSION
6270 }
6271 else
6272 vboxWddmMemFree(pContext);
6273 }
6274 else
6275 Status = STATUS_NO_MEMORY;
6276
6277 LOGF(("LEAVE, hDevice(0x%x)", hDevice));
6278
6279 return Status;
6280}
6281
6282NTSTATUS
6283APIENTRY
6284DxgkDdiDestroyContext(
6285 CONST HANDLE hContext)
6286{
6287 LOGF(("ENTER, hContext(0x%x)", hContext));
6288 vboxVDbgBreakFv();
6289 PVBOXWDDM_CONTEXT pContext = (PVBOXWDDM_CONTEXT)hContext;
6290 PVBOXMP_DEVEXT pDevExt = pContext->pDevice->pAdapter;
6291 switch(pContext->enmType)
6292 {
6293 case VBOXWDDM_CONTEXT_TYPE_CUSTOM_3D:
6294 case VBOXWDDM_CONTEXT_TYPE_CUSTOM_UHGSMI_3D:
6295 case VBOXWDDM_CONTEXT_TYPE_CUSTOM_UHGSMI_GL:
6296 {
6297 uint32_t cContexts = ASMAtomicDecU32(&pDevExt->cContexts3D);
6298 Assert(cContexts < UINT32_MAX/2);
6299 if (pContext->u32CrConClientID)
6300 {
6301 VBoxMpCrCtlConDisconnect(&pDevExt->CrCtlCon, pContext->u32CrConClientID);
6302 }
6303 break;
6304 }
6305 case VBOXWDDM_CONTEXT_TYPE_CUSTOM_2D:
6306 {
6307 uint32_t cContexts = ASMAtomicDecU32(&pDevExt->cContexts2D);
6308 Assert(cContexts < UINT32_MAX/2);
6309 break;
6310 }
6311 default:
6312 break;
6313 }
6314
6315 vboxWddmModeRenderFromShadowDisableUnregister(pDevExt, pContext);
6316
6317 /* first terminate the swapchain, this will also ensure
6318 * all currently pending driver->user Cm commands
6319 * (i.e. visible regions commands) are completed */
6320 vboxWddmSwapchainCtxTerm(pDevExt, pContext);
6321
6322 NTSTATUS Status = vboxVideoAMgrCtxDestroy(&pContext->AllocContext);
6323 Assert(Status == STATUS_SUCCESS);
6324 if (Status == STATUS_SUCCESS)
6325 {
6326 Status = vboxVideoCmCtxRemove(&pContext->pDevice->pAdapter->CmMgr, &pContext->CmContext);
6327 Assert(Status == STATUS_SUCCESS);
6328 if (Status == STATUS_SUCCESS)
6329 {
6330 vboxWddmMemFree(pContext);
6331 }
6332 }
6333
6334 LOGF(("LEAVE, hContext(0x%x)", hContext));
6335
6336 return Status;
6337}
6338
6339NTSTATUS
6340APIENTRY
6341DxgkDdiLinkDevice(
6342 __in CONST PDEVICE_OBJECT PhysicalDeviceObject,
6343 __in CONST PVOID MiniportDeviceContext,
6344 __inout PLINKED_DEVICE LinkedDevice
6345 )
6346{
6347 LOGF(("ENTER, MiniportDeviceContext(0x%x)", MiniportDeviceContext));
6348 vboxVDbgBreakFv();
6349 AssertBreakpoint();
6350 LOGF(("LEAVE, MiniportDeviceContext(0x%x)", MiniportDeviceContext));
6351 return STATUS_NOT_IMPLEMENTED;
6352}
6353
6354NTSTATUS
6355APIENTRY
6356DxgkDdiSetDisplayPrivateDriverFormat(
6357 CONST HANDLE hAdapter,
6358 /*CONST*/ DXGKARG_SETDISPLAYPRIVATEDRIVERFORMAT* pSetDisplayPrivateDriverFormat
6359 )
6360{
6361 LOGF(("ENTER, hAdapter(0x%x)", hAdapter));
6362 vboxVDbgBreakFv();
6363 AssertBreakpoint();
6364 LOGF(("LEAVE, hAdapter(0x%x)", hAdapter));
6365 return STATUS_SUCCESS;
6366}
6367
6368NTSTATUS APIENTRY CALLBACK DxgkDdiRestartFromTimeout(IN_CONST_HANDLE hAdapter)
6369{
6370 LOGF(("ENTER, hAdapter(0x%x)", hAdapter));
6371 vboxVDbgBreakFv();
6372 AssertBreakpoint();
6373 LOGF(("LEAVE, hAdapter(0x%x)", hAdapter));
6374 return STATUS_SUCCESS;
6375}
6376
6377#ifdef VBOX_WDDM_WIN8
6378
6379static NTSTATUS APIENTRY DxgkDdiQueryVidPnHWCapability(
6380 __in const HANDLE hAdapter,
6381 __inout DXGKARG_QUERYVIDPNHWCAPABILITY *pVidPnHWCaps
6382 )
6383{
6384 LOGF(("ENTER, hAdapter(0x%x)", hAdapter));
6385 vboxVDbgBreakF();
6386 pVidPnHWCaps->VidPnHWCaps.DriverRotation = 0;
6387 pVidPnHWCaps->VidPnHWCaps.DriverScaling = 0;
6388 pVidPnHWCaps->VidPnHWCaps.DriverCloning = 0;
6389 pVidPnHWCaps->VidPnHWCaps.DriverColorConvert = 0;
6390 pVidPnHWCaps->VidPnHWCaps.DriverLinkedAdapaterOutput = 0;
6391 pVidPnHWCaps->VidPnHWCaps.DriverRemoteDisplay = 0;
6392 LOGF(("LEAVE, hAdapter(0x%x)", hAdapter));
6393 return STATUS_SUCCESS;
6394}
6395
6396static NTSTATUS APIENTRY DxgkDdiPresentDisplayOnly(
6397 _In_ const HANDLE hAdapter,
6398 _In_ const DXGKARG_PRESENT_DISPLAYONLY *pPresentDisplayOnly
6399 )
6400{
6401 LOGF(("ENTER, hAdapter(0x%x)", hAdapter));
6402 vboxVDbgBreakF();
6403
6404 PVBOXMP_DEVEXT pDevExt = (PVBOXMP_DEVEXT)hAdapter;
6405 PVBOXWDDM_SOURCE pSource = &pDevExt->aSources[pPresentDisplayOnly->VidPnSourceId];
6406 Assert(pSource->AllocData.Addr.SegmentId);
6407 VBOXWDDM_ALLOC_DATA SrcAllocData;
6408 SrcAllocData.SurfDesc.width = pPresentDisplayOnly->Pitch * pPresentDisplayOnly->BytesPerPixel;
6409 SrcAllocData.SurfDesc.height = ~0UL;
6410 switch (pPresentDisplayOnly->BytesPerPixel)
6411 {
6412 case 4:
6413 SrcAllocData.SurfDesc.format = D3DDDIFMT_A8R8G8B8;
6414 break;
6415 case 3:
6416 SrcAllocData.SurfDesc.format = D3DDDIFMT_R8G8B8;
6417 break;
6418 case 2:
6419 SrcAllocData.SurfDesc.format = D3DDDIFMT_R5G6B5;
6420 break;
6421 case 1:
6422 SrcAllocData.SurfDesc.format = D3DDDIFMT_P8;
6423 break;
6424 default:
6425 WARN(("Unknown format"));
6426 SrcAllocData.SurfDesc.format = D3DDDIFMT_UNKNOWN;
6427 break;
6428 }
6429 SrcAllocData.SurfDesc.bpp = pPresentDisplayOnly->BytesPerPixel >> 3;
6430 SrcAllocData.SurfDesc.pitch = pPresentDisplayOnly->Pitch;
6431 SrcAllocData.SurfDesc.depth = 1;
6432 SrcAllocData.SurfDesc.slicePitch = pPresentDisplayOnly->Pitch;
6433 SrcAllocData.SurfDesc.cbSize = ~0UL;
6434 SrcAllocData.Addr.SegmentId = 0;
6435 SrcAllocData.Addr.pvMem = pPresentDisplayOnly->pSource;
6436
6437 RECT UpdateRect;
6438 BOOLEAN bUpdateRectInited = FALSE;
6439
6440 for (UINT i = 0; i < pPresentDisplayOnly->NumMoves; ++i)
6441 {
6442 if (!bUpdateRectInited)
6443 {
6444 UpdateRect = pPresentDisplayOnly->pMoves[i].DestRect;
6445 bUpdateRectInited = TRUE;
6446 }
6447 else
6448 vboxWddmRectUnite(&UpdateRect, &pPresentDisplayOnly->pMoves[i].DestRect);
6449 vboxVdmaGgDmaBltPerform(pDevExt, &SrcAllocData, &pPresentDisplayOnly->pMoves[i].DestRect, &pSource->AllocData, &pPresentDisplayOnly->pMoves[i].DestRect);
6450 }
6451
6452 for (UINT i = 0; i < pPresentDisplayOnly->NumDirtyRects; ++i)
6453 {
6454 vboxVdmaGgDmaBltPerform(pDevExt, &SrcAllocData, &pPresentDisplayOnly->pDirtyRect[i], &pSource->AllocData, &pPresentDisplayOnly->pDirtyRect[i]);
6455 if (!bUpdateRectInited)
6456 {
6457 UpdateRect = pPresentDisplayOnly->pDirtyRect[i];
6458 bUpdateRectInited = TRUE;
6459 }
6460 else
6461 vboxWddmRectUnite(&UpdateRect, &pPresentDisplayOnly->pDirtyRect[i]);
6462 }
6463
6464 if (bUpdateRectInited && pSource->bVisible)
6465 {
6466 VBOXVBVA_OP_WITHLOCK(ReportDirtyRect, pDevExt, pSource, &UpdateRect);
6467 }
6468
6469 LOGF(("LEAVE, hAdapter(0x%x)", hAdapter));
6470 return STATUS_SUCCESS;
6471}
6472
6473static NTSTATUS DxgkDdiStopDeviceAndReleasePostDisplayOwnership(
6474 _In_ PVOID MiniportDeviceContext,
6475 _In_ D3DDDI_VIDEO_PRESENT_TARGET_ID TargetId,
6476 _Out_ PDXGK_DISPLAY_INFORMATION DisplayInfo
6477)
6478{
6479 LOGF(("ENTER, hAdapter(0x%x)", MiniportDeviceContext));
6480 vboxVDbgBreakFv();
6481 AssertBreakpoint();
6482 LOGF(("LEAVE, hAdapter(0x%x)", MiniportDeviceContext));
6483 return STATUS_NOT_SUPPORTED;
6484}
6485
6486static NTSTATUS DxgkDdiSystemDisplayEnable(
6487 _In_ PVOID MiniportDeviceContext,
6488 _In_ D3DDDI_VIDEO_PRESENT_TARGET_ID TargetId,
6489 _In_ PDXGKARG_SYSTEM_DISPLAY_ENABLE_FLAGS Flags,
6490 _Out_ UINT *Width,
6491 _Out_ UINT *Height,
6492 _Out_ D3DDDIFORMAT *ColorFormat
6493 )
6494{
6495 LOGF(("ENTER, hAdapter(0x%x)", MiniportDeviceContext));
6496 vboxVDbgBreakFv();
6497 AssertBreakpoint();
6498 LOGF(("LEAVE, hAdapter(0x%x)", MiniportDeviceContext));
6499 return STATUS_NOT_SUPPORTED;
6500}
6501
6502static VOID DxgkDdiSystemDisplayWrite(
6503 _In_ PVOID MiniportDeviceContext,
6504 _In_ PVOID Source,
6505 _In_ UINT SourceWidth,
6506 _In_ UINT SourceHeight,
6507 _In_ UINT SourceStride,
6508 _In_ UINT PositionX,
6509 _In_ UINT PositionY
6510)
6511{
6512 LOGF(("ENTER, hAdapter(0x%x)", MiniportDeviceContext));
6513 vboxVDbgBreakFv();
6514 AssertBreakpoint();
6515 LOGF(("LEAVE, hAdapter(0x%x)", MiniportDeviceContext));
6516}
6517
6518static NTSTATUS DxgkDdiGetChildContainerId(
6519 _In_ PVOID MiniportDeviceContext,
6520 _In_ ULONG ChildUid,
6521 _Inout_ PDXGK_CHILD_CONTAINER_ID ContainerId
6522)
6523{
6524 LOGF(("ENTER, hAdapter(0x%x)", MiniportDeviceContext));
6525 vboxVDbgBreakFv();
6526 AssertBreakpoint();
6527 LOGF(("LEAVE, hAdapter(0x%x)", MiniportDeviceContext));
6528 return STATUS_SUCCESS;
6529}
6530
6531static NTSTATUS APIENTRY DxgkDdiSetPowerComponentFState(
6532 _In_ const HANDLE DriverContext,
6533 UINT ComponentIndex,
6534 UINT FState
6535)
6536{
6537 LOGF(("ENTER, DriverContext(0x%x)", DriverContext));
6538 vboxVDbgBreakFv();
6539 AssertBreakpoint();
6540 LOGF(("LEAVE, DriverContext(0x%x)", DriverContext));
6541 return STATUS_SUCCESS;
6542}
6543
6544static NTSTATUS APIENTRY DxgkDdiPowerRuntimeControlRequest(
6545 _In_ const HANDLE DriverContext,
6546 _In_ LPCGUID PowerControlCode,
6547 _In_opt_ PVOID InBuffer,
6548 _In_ SIZE_T InBufferSize,
6549 _Out_opt_ PVOID OutBuffer,
6550 _In_ SIZE_T OutBufferSize,
6551 _Out_opt_ PSIZE_T BytesReturned
6552)
6553{
6554 LOGF(("ENTER, DriverContext(0x%x)", DriverContext));
6555 vboxVDbgBreakFv();
6556 AssertBreakpoint();
6557 LOGF(("LEAVE, DriverContext(0x%x)", DriverContext));
6558 return STATUS_SUCCESS;
6559}
6560
6561static NTSTATUS DxgkDdiNotifySurpriseRemoval(
6562 _In_ PVOID MiniportDeviceContext,
6563 _In_ DXGK_SURPRISE_REMOVAL_TYPE RemovalType
6564 )
6565{
6566 LOGF(("ENTER, hAdapter(0x%x)", MiniportDeviceContext));
6567 vboxVDbgBreakFv();
6568 AssertBreakpoint();
6569 LOGF(("LEAVE, hAdapter(0x%x)", MiniportDeviceContext));
6570 return STATUS_SUCCESS;
6571}
6572
6573static NTSTATUS vboxWddmInitDisplayOnlyDriver(IN PDRIVER_OBJECT pDriverObject, IN PUNICODE_STRING pRegistryPath)
6574{
6575 KMDDOD_INITIALIZATION_DATA DriverInitializationData = {'\0'};
6576
6577 DriverInitializationData.Version = DXGKDDI_INTERFACE_VERSION_WIN8;
6578
6579 DriverInitializationData.DxgkDdiAddDevice = DxgkDdiAddDevice;
6580 DriverInitializationData.DxgkDdiStartDevice = DxgkDdiStartDevice;
6581 DriverInitializationData.DxgkDdiStopDevice = DxgkDdiStopDevice;
6582 DriverInitializationData.DxgkDdiRemoveDevice = DxgkDdiRemoveDevice;
6583 DriverInitializationData.DxgkDdiDispatchIoRequest = DxgkDdiDispatchIoRequest;
6584 DriverInitializationData.DxgkDdiInterruptRoutine = DxgkDdiInterruptRoutine;
6585 DriverInitializationData.DxgkDdiDpcRoutine = DxgkDdiDpcRoutine;
6586 DriverInitializationData.DxgkDdiQueryChildRelations = DxgkDdiQueryChildRelations;
6587 DriverInitializationData.DxgkDdiQueryChildStatus = DxgkDdiQueryChildStatus;
6588 DriverInitializationData.DxgkDdiQueryDeviceDescriptor = DxgkDdiQueryDeviceDescriptor;
6589 DriverInitializationData.DxgkDdiSetPowerState = DxgkDdiSetPowerState;
6590 DriverInitializationData.DxgkDdiNotifyAcpiEvent = DxgkDdiNotifyAcpiEvent;
6591 DriverInitializationData.DxgkDdiResetDevice = DxgkDdiResetDevice;
6592 DriverInitializationData.DxgkDdiUnload = DxgkDdiUnload;
6593 DriverInitializationData.DxgkDdiQueryInterface = DxgkDdiQueryInterface;
6594 DriverInitializationData.DxgkDdiControlEtwLogging = DxgkDdiControlEtwLogging;
6595 DriverInitializationData.DxgkDdiQueryAdapterInfo = DxgkDdiQueryAdapterInfo;
6596 DriverInitializationData.DxgkDdiSetPalette = DxgkDdiSetPalette;
6597 DriverInitializationData.DxgkDdiSetPointerPosition = DxgkDdiSetPointerPosition;
6598 DriverInitializationData.DxgkDdiSetPointerShape = DxgkDdiSetPointerShape;
6599 DriverInitializationData.DxgkDdiEscape = DxgkDdiEscape;
6600 DriverInitializationData.DxgkDdiCollectDbgInfo = DxgkDdiCollectDbgInfo;
6601 DriverInitializationData.DxgkDdiIsSupportedVidPn = DxgkDdiIsSupportedVidPn;
6602 DriverInitializationData.DxgkDdiRecommendFunctionalVidPn = DxgkDdiRecommendFunctionalVidPn;
6603 DriverInitializationData.DxgkDdiEnumVidPnCofuncModality = DxgkDdiEnumVidPnCofuncModality;
6604 DriverInitializationData.DxgkDdiSetVidPnSourceVisibility = DxgkDdiSetVidPnSourceVisibility;
6605 DriverInitializationData.DxgkDdiCommitVidPn = DxgkDdiCommitVidPn;
6606 DriverInitializationData.DxgkDdiUpdateActiveVidPnPresentPath = DxgkDdiUpdateActiveVidPnPresentPath;
6607 DriverInitializationData.DxgkDdiRecommendMonitorModes = DxgkDdiRecommendMonitorModes;
6608 DriverInitializationData.DxgkDdiGetScanLine = DxgkDdiGetScanLine;
6609 DriverInitializationData.DxgkDdiQueryVidPnHWCapability = DxgkDdiQueryVidPnHWCapability;
6610 DriverInitializationData.DxgkDdiPresentDisplayOnly = DxgkDdiPresentDisplayOnly;
6611 DriverInitializationData.DxgkDdiStopDeviceAndReleasePostDisplayOwnership = DxgkDdiStopDeviceAndReleasePostDisplayOwnership;
6612 DriverInitializationData.DxgkDdiSystemDisplayEnable = DxgkDdiSystemDisplayEnable;
6613 DriverInitializationData.DxgkDdiSystemDisplayWrite = DxgkDdiSystemDisplayWrite;
6614// DriverInitializationData.DxgkDdiGetChildContainerId = DxgkDdiGetChildContainerId;
6615 DriverInitializationData.DxgkDdiControlInterrupt = DxgkDdiControlInterrupt;
6616// DriverInitializationData.DxgkDdiSetPowerComponentFState = DxgkDdiSetPowerComponentFState;
6617// DriverInitializationData.DxgkDdiPowerRuntimeControlRequest = DxgkDdiPowerRuntimeControlRequest;
6618// DriverInitializationData.DxgkDdiNotifySurpriseRemoval = DxgkDdiNotifySurpriseRemoval;
6619
6620 NTSTATUS Status = DxgkInitializeDisplayOnlyDriver(pDriverObject,
6621 pRegistryPath,
6622 &DriverInitializationData);
6623 if (!NT_SUCCESS(Status))
6624 {
6625 WARN(("DxgkInitializeDisplayOnlyDriver failed! Status 0x%x", Status));
6626 }
6627 return Status;
6628}
6629#endif
6630
6631static NTSTATUS vboxWddmInitFullGraphicsDriver(IN PDRIVER_OBJECT pDriverObject, IN PUNICODE_STRING pRegistryPath)
6632{
6633 DRIVER_INITIALIZATION_DATA DriverInitializationData = {'\0'};
6634
6635 // Fill in the DriverInitializationData structure and call DxgkInitialize()
6636 DriverInitializationData.Version = DXGKDDI_INTERFACE_VERSION;
6637
6638 DriverInitializationData.DxgkDdiAddDevice = DxgkDdiAddDevice;
6639 DriverInitializationData.DxgkDdiStartDevice = DxgkDdiStartDevice;
6640 DriverInitializationData.DxgkDdiStopDevice = DxgkDdiStopDevice;
6641 DriverInitializationData.DxgkDdiRemoveDevice = DxgkDdiRemoveDevice;
6642 DriverInitializationData.DxgkDdiDispatchIoRequest = DxgkDdiDispatchIoRequest;
6643 DriverInitializationData.DxgkDdiInterruptRoutine = DxgkDdiInterruptRoutine;
6644 DriverInitializationData.DxgkDdiDpcRoutine = DxgkDdiDpcRoutine;
6645 DriverInitializationData.DxgkDdiQueryChildRelations = DxgkDdiQueryChildRelations;
6646 DriverInitializationData.DxgkDdiQueryChildStatus = DxgkDdiQueryChildStatus;
6647 DriverInitializationData.DxgkDdiQueryDeviceDescriptor = DxgkDdiQueryDeviceDescriptor;
6648 DriverInitializationData.DxgkDdiSetPowerState = DxgkDdiSetPowerState;
6649 DriverInitializationData.DxgkDdiNotifyAcpiEvent = DxgkDdiNotifyAcpiEvent;
6650 DriverInitializationData.DxgkDdiResetDevice = DxgkDdiResetDevice;
6651 DriverInitializationData.DxgkDdiUnload = DxgkDdiUnload;
6652 DriverInitializationData.DxgkDdiQueryInterface = DxgkDdiQueryInterface;
6653 DriverInitializationData.DxgkDdiControlEtwLogging = DxgkDdiControlEtwLogging;
6654
6655 DriverInitializationData.DxgkDdiQueryAdapterInfo = DxgkDdiQueryAdapterInfo;
6656 DriverInitializationData.DxgkDdiCreateDevice = DxgkDdiCreateDevice;
6657 DriverInitializationData.DxgkDdiCreateAllocation = DxgkDdiCreateAllocation;
6658 DriverInitializationData.DxgkDdiDestroyAllocation = DxgkDdiDestroyAllocation;
6659 DriverInitializationData.DxgkDdiDescribeAllocation = DxgkDdiDescribeAllocation;
6660 DriverInitializationData.DxgkDdiGetStandardAllocationDriverData = DxgkDdiGetStandardAllocationDriverData;
6661 DriverInitializationData.DxgkDdiAcquireSwizzlingRange = DxgkDdiAcquireSwizzlingRange;
6662 DriverInitializationData.DxgkDdiReleaseSwizzlingRange = DxgkDdiReleaseSwizzlingRange;
6663 DriverInitializationData.DxgkDdiPatch = DxgkDdiPatch;
6664 DriverInitializationData.DxgkDdiSubmitCommand = DxgkDdiSubmitCommand;
6665 DriverInitializationData.DxgkDdiPreemptCommand = DxgkDdiPreemptCommand;
6666 DriverInitializationData.DxgkDdiBuildPagingBuffer = DxgkDdiBuildPagingBuffer;
6667 DriverInitializationData.DxgkDdiSetPalette = DxgkDdiSetPalette;
6668 DriverInitializationData.DxgkDdiSetPointerPosition = DxgkDdiSetPointerPosition;
6669 DriverInitializationData.DxgkDdiSetPointerShape = DxgkDdiSetPointerShape;
6670 DriverInitializationData.DxgkDdiResetFromTimeout = DxgkDdiResetFromTimeout;
6671 DriverInitializationData.DxgkDdiRestartFromTimeout = DxgkDdiRestartFromTimeout;
6672 DriverInitializationData.DxgkDdiEscape = DxgkDdiEscape;
6673 DriverInitializationData.DxgkDdiCollectDbgInfo = DxgkDdiCollectDbgInfo;
6674 DriverInitializationData.DxgkDdiQueryCurrentFence = DxgkDdiQueryCurrentFence;
6675 DriverInitializationData.DxgkDdiIsSupportedVidPn = DxgkDdiIsSupportedVidPn;
6676 DriverInitializationData.DxgkDdiRecommendFunctionalVidPn = DxgkDdiRecommendFunctionalVidPn;
6677 DriverInitializationData.DxgkDdiEnumVidPnCofuncModality = DxgkDdiEnumVidPnCofuncModality;
6678 DriverInitializationData.DxgkDdiSetVidPnSourceAddress = DxgkDdiSetVidPnSourceAddress;
6679 DriverInitializationData.DxgkDdiSetVidPnSourceVisibility = DxgkDdiSetVidPnSourceVisibility;
6680 DriverInitializationData.DxgkDdiCommitVidPn = DxgkDdiCommitVidPn;
6681 DriverInitializationData.DxgkDdiUpdateActiveVidPnPresentPath = DxgkDdiUpdateActiveVidPnPresentPath;
6682 DriverInitializationData.DxgkDdiRecommendMonitorModes = DxgkDdiRecommendMonitorModes;
6683 DriverInitializationData.DxgkDdiRecommendVidPnTopology = DxgkDdiRecommendVidPnTopology;
6684 DriverInitializationData.DxgkDdiGetScanLine = DxgkDdiGetScanLine;
6685 DriverInitializationData.DxgkDdiStopCapture = DxgkDdiStopCapture;
6686 DriverInitializationData.DxgkDdiControlInterrupt = DxgkDdiControlInterrupt;
6687 DriverInitializationData.DxgkDdiCreateOverlay = DxgkDdiCreateOverlay;
6688
6689 DriverInitializationData.DxgkDdiDestroyDevice = DxgkDdiDestroyDevice;
6690 DriverInitializationData.DxgkDdiOpenAllocation = DxgkDdiOpenAllocation;
6691 DriverInitializationData.DxgkDdiCloseAllocation = DxgkDdiCloseAllocation;
6692 DriverInitializationData.DxgkDdiRender = DxgkDdiRender;
6693 DriverInitializationData.DxgkDdiPresent = DxgkDdiPresent;
6694
6695 DriverInitializationData.DxgkDdiUpdateOverlay = DxgkDdiUpdateOverlay;
6696 DriverInitializationData.DxgkDdiFlipOverlay = DxgkDdiFlipOverlay;
6697 DriverInitializationData.DxgkDdiDestroyOverlay = DxgkDdiDestroyOverlay;
6698
6699 DriverInitializationData.DxgkDdiCreateContext = DxgkDdiCreateContext;
6700 DriverInitializationData.DxgkDdiDestroyContext = DxgkDdiDestroyContext;
6701
6702 DriverInitializationData.DxgkDdiLinkDevice = NULL; //DxgkDdiLinkDevice;
6703 DriverInitializationData.DxgkDdiSetDisplayPrivateDriverFormat = DxgkDdiSetDisplayPrivateDriverFormat;
6704//#if (DXGKDDI_INTERFACE_VERSION >= DXGKDDI_INTERFACE_VERSION_WIN7)
6705//# error port to Win7 DDI
6706// DriverInitializationData.DxgkDdiRenderKm = DxgkDdiRenderKm;
6707// DriverInitializationData.DxgkDdiRestartFromTimeout = DxgkDdiRestartFromTimeout;
6708// DriverInitializationData.DxgkDdiSetVidPnSourceVisibility = DxgkDdiSetVidPnSourceVisibility;
6709// DriverInitializationData.DxgkDdiUpdateActiveVidPnPresentPath = DxgkDdiUpdateActiveVidPnPresentPath;
6710// DriverInitializationData.DxgkDdiQueryVidPnHWCapability = DxgkDdiQueryVidPnHWCapability;
6711//#endif
6712
6713 NTSTATUS Status = DxgkInitialize(pDriverObject,
6714 pRegistryPath,
6715 &DriverInitializationData);
6716 if (!NT_SUCCESS(Status))
6717 {
6718 WARN(("DxgkInitialize failed! Status 0x%x", Status));
6719 }
6720 return Status;
6721}
6722
6723NTSTATUS
6724DriverEntry(
6725 IN PDRIVER_OBJECT DriverObject,
6726 IN PUNICODE_STRING RegistryPath
6727 )
6728{
6729 PAGED_CODE();
6730
6731 vboxVDbgBreakFv();
6732
6733#if 0//def DEBUG_misha
6734 RTLogGroupSettings(0, "+default.e.l.f.l2.l3");
6735#endif
6736
6737#ifdef VBOX_WDDM_WIN8
6738 LOGREL(("VBox WDDM Driver for Windows 8, %d bit; Built %s %s", (sizeof (void*) << 3), __DATE__, __TIME__));
6739#else
6740 LOGREL(("VBox WDDM Driver for Windows Vista and 7, %d bit; Built %s %s", (sizeof (void*) << 3), __DATE__, __TIME__));
6741#endif
6742
6743 if (! ARGUMENT_PRESENT(DriverObject) ||
6744 ! ARGUMENT_PRESENT(RegistryPath))
6745 {
6746 return STATUS_INVALID_PARAMETER;
6747 }
6748
6749 vboxWddmDrvCfgInit(RegistryPath);
6750
6751 ULONG major, minor, build;
6752 BOOLEAN checkedBuild = PsGetVersion(&major, &minor, &build, NULL);
6753 BOOLEAN f3DCheckRequired = FALSE;
6754
6755 LOGREL(("OsVersion( %d, %d, %d )", major, minor, build));
6756
6757 NTSTATUS Status = STATUS_SUCCESS;
6758 /* Initialize VBoxGuest library, which is used for requests which go through VMMDev. */
6759 int rc = VbglInit();
6760 if (RT_SUCCESS(rc))
6761 {
6762 if (major > 6)
6763 {
6764 WARN(("Unknow win version, newer major release, assuming 3D check is required"));
6765 f3DCheckRequired = TRUE;
6766 }
6767 else if (major == 6)
6768 {
6769 if (minor > 2)
6770 {
6771 WARN(("Unknow win version, newer minor release, assuming 3D check is required"));
6772 f3DCheckRequired = TRUE;
6773 }
6774 else if (minor == 2)
6775 {
6776 LOG(("3D check is required!"));
6777 f3DCheckRequired = TRUE;
6778 }
6779 else
6780 {
6781 LOG(("3D is NOT required!"));
6782 f3DCheckRequired = FALSE;
6783 }
6784 }
6785 else
6786 {
6787 WARN(("Unsupported OLDER win version, ignore and assume 3D is NOT required"));
6788 f3DCheckRequired = FALSE;
6789 }
6790
6791 Status = STATUS_SUCCESS;
6792
6793 if (f3DCheckRequired)
6794 {
6795 LOG(("3D check is required, doing the 3D check.."));
6796 if (!VBoxMpCrCtlConIs3DSupported())
6797 {
6798#ifdef VBOX_WDDM_WIN8
6799 LOGREL(("3D is NOT supported by the host, falling back to display-only mode.."));
6800 g_VBoxDisplayOnly = 1;
6801#else
6802 LOGREL(("3D is NOT supported by the host, but is required for the current guest version using this driver.."));
6803 Status = STATUS_UNSUCCESSFUL;
6804#endif
6805 }
6806 }
6807
6808#if 0 //defined(DEBUG_misha) && defined(VBOX_WDDM_WIN8)
6809 /* force g_VBoxDisplayOnly for debugging purposes */
6810 LOGREL(("Current win8 video driver only supports display-only mode no matter whether or not host 3D is enabled!"));
6811 g_VBoxDisplayOnly = 1;
6812#endif
6813
6814 if (NT_SUCCESS(Status))
6815 {
6816 Status = VBoxWddmVrInit();
6817 if (NT_SUCCESS(Status))
6818 {
6819#ifdef VBOX_WDDM_WIN8
6820 if (g_VBoxDisplayOnly)
6821 {
6822 Status = vboxWddmInitDisplayOnlyDriver(DriverObject, RegistryPath);
6823 }
6824 else
6825#endif
6826 {
6827 Status = vboxWddmInitFullGraphicsDriver(DriverObject, RegistryPath);
6828 }
6829
6830 if (NT_SUCCESS(Status))
6831 return Status;
6832
6833 VBoxWddmVrTerm();
6834 }
6835 else
6836 WARN(("VBoxWddmVrInit failed, Status(0x%x)", Status));
6837 }
6838 else
6839 LOGREL(("Aborting the video driver load due to 3D support missing"));
6840
6841 VbglTerminate();
6842 }
6843 else
6844 {
6845 WARN(("VbglInit failed, rc(%d)", rc));
6846 Status = STATUS_UNSUCCESSFUL;
6847 }
6848
6849 AssertRelease(!NT_SUCCESS(Status));
6850
6851 PRTLOGGER pLogger = RTLogRelSetDefaultInstance(NULL);
6852 if (pLogger)
6853 {
6854 RTLogDestroy(pLogger);
6855 }
6856 pLogger = RTLogSetDefaultInstance(NULL);
6857 if (pLogger)
6858 {
6859 RTLogDestroy(pLogger);
6860 }
6861
6862 return Status;
6863}
6864
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