VirtualBox

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

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

wddm/crOpenGL: more TexPresent impl

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