VirtualBox

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

Last change on this file since 46876 was 46852, checked in by vboxsync, 11 years ago

wddm: fix win version support warning

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