VirtualBox

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

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

Build HGSMI memory allocator (unused)

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 68.4 KB
Line 
1/* $Id: VBoxMPVdma.cpp 50482 2014-02-17 15:23:05Z vboxsync $ */
2
3/** @file
4 * VBox WDDM Miniport driver
5 */
6
7/*
8 * Copyright (C) 2011-2012 Oracle Corporation
9 *
10 * This file is part of VirtualBox Open Source Edition (OSE), as
11 * available from http://www.virtualbox.org. This file is free software;
12 * you can redistribute it and/or modify it under the terms of the GNU
13 * General Public License (GPL) as published by the Free Software
14 * Foundation, in version 2 as it comes in the "COPYING" file of the
15 * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
16 * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
17 */
18
19#include "VBoxMPWddm.h"
20#include "common/VBoxMPCommon.h"
21#include "VBoxMPVdma.h"
22#include "VBoxMPVhwa.h"
23#include <iprt/asm.h>
24#include "VBoxMPCr.h"
25
26# include <packer.h>
27
28NTSTATUS vboxVdmaPipeConstruct(PVBOXVDMAPIPE pPipe)
29{
30 KeInitializeSpinLock(&pPipe->SinchLock);
31 KeInitializeEvent(&pPipe->Event, SynchronizationEvent, FALSE);
32 InitializeListHead(&pPipe->CmdListHead);
33 pPipe->enmState = VBOXVDMAPIPE_STATE_CREATED;
34 pPipe->bNeedNotify = true;
35 return STATUS_SUCCESS;
36}
37
38NTSTATUS vboxVdmaPipeSvrOpen(PVBOXVDMAPIPE pPipe)
39{
40 NTSTATUS Status = STATUS_SUCCESS;
41 KIRQL OldIrql;
42 KeAcquireSpinLock(&pPipe->SinchLock, &OldIrql);
43 Assert(pPipe->enmState == VBOXVDMAPIPE_STATE_CREATED);
44 switch (pPipe->enmState)
45 {
46 case VBOXVDMAPIPE_STATE_CREATED:
47 pPipe->enmState = VBOXVDMAPIPE_STATE_OPENNED;
48 pPipe->bNeedNotify = false;
49 break;
50 case VBOXVDMAPIPE_STATE_OPENNED:
51 pPipe->bNeedNotify = false;
52 break;
53 default:
54 AssertBreakpoint();
55 Status = STATUS_INVALID_PIPE_STATE;
56 break;
57 }
58
59 KeReleaseSpinLock(&pPipe->SinchLock, OldIrql);
60 return Status;
61}
62
63NTSTATUS vboxVdmaPipeSvrClose(PVBOXVDMAPIPE pPipe)
64{
65 NTSTATUS Status = STATUS_SUCCESS;
66 KIRQL OldIrql;
67 KeAcquireSpinLock(&pPipe->SinchLock, &OldIrql);
68 Assert(pPipe->enmState == VBOXVDMAPIPE_STATE_CLOSED
69 || pPipe->enmState == VBOXVDMAPIPE_STATE_CLOSING);
70 switch (pPipe->enmState)
71 {
72 case VBOXVDMAPIPE_STATE_CLOSING:
73 pPipe->enmState = VBOXVDMAPIPE_STATE_CLOSED;
74 break;
75 case VBOXVDMAPIPE_STATE_CLOSED:
76 break;
77 default:
78 AssertBreakpoint();
79 Status = STATUS_INVALID_PIPE_STATE;
80 break;
81 }
82
83 KeReleaseSpinLock(&pPipe->SinchLock, OldIrql);
84 return Status;
85}
86
87NTSTATUS vboxVdmaPipeCltClose(PVBOXVDMAPIPE pPipe)
88{
89 NTSTATUS Status = STATUS_SUCCESS;
90 KIRQL OldIrql;
91 KeAcquireSpinLock(&pPipe->SinchLock, &OldIrql);
92 bool bNeedNotify = false;
93 Assert(pPipe->enmState == VBOXVDMAPIPE_STATE_OPENNED
94 || pPipe->enmState == VBOXVDMAPIPE_STATE_CREATED
95 || pPipe->enmState == VBOXVDMAPIPE_STATE_CLOSED);
96 switch (pPipe->enmState)
97 {
98 case VBOXVDMAPIPE_STATE_OPENNED:
99 pPipe->enmState = VBOXVDMAPIPE_STATE_CLOSING;
100 bNeedNotify = pPipe->bNeedNotify;
101 pPipe->bNeedNotify = false;
102 break;
103 case VBOXVDMAPIPE_STATE_CREATED:
104 pPipe->enmState = VBOXVDMAPIPE_STATE_CLOSED;
105 pPipe->bNeedNotify = false;
106 break;
107 case VBOXVDMAPIPE_STATE_CLOSED:
108 break;
109 default:
110 AssertBreakpoint();
111 Status = STATUS_INVALID_PIPE_STATE;
112 break;
113 }
114
115 KeReleaseSpinLock(&pPipe->SinchLock, OldIrql);
116
117 if (bNeedNotify)
118 {
119 KeSetEvent(&pPipe->Event, 0, FALSE);
120 }
121 return Status;
122}
123
124NTSTATUS vboxVdmaPipeDestruct(PVBOXVDMAPIPE pPipe)
125{
126 Assert(pPipe->enmState == VBOXVDMAPIPE_STATE_CLOSED
127 || pPipe->enmState == VBOXVDMAPIPE_STATE_CREATED);
128 /* ensure the pipe is closed */
129 NTSTATUS Status = vboxVdmaPipeCltClose(pPipe);
130 Assert(Status == STATUS_SUCCESS);
131
132 Assert(pPipe->enmState == VBOXVDMAPIPE_STATE_CLOSED);
133
134 return Status;
135}
136
137NTSTATUS vboxVdmaPipeSvrCmdGetList(PVBOXVDMAPIPE pPipe, PLIST_ENTRY pDetachHead)
138{
139 PLIST_ENTRY pEntry = NULL;
140 KIRQL OldIrql;
141 NTSTATUS Status = STATUS_SUCCESS;
142 VBOXVDMAPIPE_STATE enmState = VBOXVDMAPIPE_STATE_CLOSED;
143 do
144 {
145 bool bListEmpty = true;
146 KeAcquireSpinLock(&pPipe->SinchLock, &OldIrql);
147 Assert(pPipe->enmState == VBOXVDMAPIPE_STATE_OPENNED
148 || pPipe->enmState == VBOXVDMAPIPE_STATE_CLOSING);
149 Assert(pPipe->enmState >= VBOXVDMAPIPE_STATE_OPENNED);
150 enmState = pPipe->enmState;
151 if (enmState >= VBOXVDMAPIPE_STATE_OPENNED)
152 {
153 vboxVideoLeDetach(&pPipe->CmdListHead, pDetachHead);
154 bListEmpty = !!(IsListEmpty(pDetachHead));
155 pPipe->bNeedNotify = bListEmpty;
156 }
157 else
158 {
159 KeReleaseSpinLock(&pPipe->SinchLock, OldIrql);
160 Status = STATUS_INVALID_PIPE_STATE;
161 break;
162 }
163
164 KeReleaseSpinLock(&pPipe->SinchLock, OldIrql);
165
166 if (!bListEmpty)
167 {
168 Assert(Status == STATUS_SUCCESS);
169 break;
170 }
171
172 if (enmState == VBOXVDMAPIPE_STATE_OPENNED)
173 {
174 Status = KeWaitForSingleObject(&pPipe->Event, Executive, KernelMode, FALSE, NULL /* PLARGE_INTEGER Timeout */);
175 Assert(Status == STATUS_SUCCESS);
176 if (Status != STATUS_SUCCESS)
177 break;
178 }
179 else
180 {
181 Assert(enmState == VBOXVDMAPIPE_STATE_CLOSING);
182 Status = STATUS_PIPE_CLOSING;
183 break;
184 }
185 } while (1);
186
187 return Status;
188}
189
190NTSTATUS vboxVdmaPipeCltCmdPut(PVBOXVDMAPIPE pPipe, PVBOXVDMAPIPE_CMD_HDR pCmd)
191{
192 NTSTATUS Status = STATUS_SUCCESS;
193 KIRQL OldIrql;
194 bool bNeedNotify = false;
195
196 KeAcquireSpinLock(&pPipe->SinchLock, &OldIrql);
197
198 Assert(pPipe->enmState == VBOXVDMAPIPE_STATE_OPENNED);
199 if (pPipe->enmState == VBOXVDMAPIPE_STATE_OPENNED)
200 {
201 bNeedNotify = pPipe->bNeedNotify;
202 InsertHeadList(&pPipe->CmdListHead, &pCmd->ListEntry);
203 pPipe->bNeedNotify = false;
204 }
205 else
206 Status = STATUS_INVALID_PIPE_STATE;
207
208 KeReleaseSpinLock(&pPipe->SinchLock, OldIrql);
209
210 if (bNeedNotify)
211 {
212 KeSetEvent(&pPipe->Event, 0, FALSE);
213 }
214
215 return Status;
216}
217
218DECLINLINE(void) vboxVdmaDirtyRectsCalcIntersection(const RECT *pArea, const VBOXWDDM_RECTS_INFO *pRects, PVBOXWDDM_RECTS_INFO pResult)
219{
220 uint32_t cRects = 0;
221 for (uint32_t i = 0; i < pRects->cRects; ++i)
222 {
223 if (vboxWddmRectIntersection(pArea, &pRects->aRects[i], &pResult->aRects[cRects]))
224 {
225 ++cRects;
226 }
227 }
228
229 pResult->cRects = cRects;
230}
231
232DECLINLINE(bool) vboxVdmaDirtyRectsHasIntersections(const RECT *paRects1, uint32_t cRects1, const RECT *paRects2, uint32_t cRects2)
233{
234 RECT tmpRect;
235 for (uint32_t i = 0; i < cRects1; ++i)
236 {
237 const RECT * pRect1 = &paRects1[i];
238 for (uint32_t j = 0; j < cRects2; ++j)
239 {
240 const RECT * pRect2 = &paRects2[j];
241 if (vboxWddmRectIntersection(pRect1, pRect2, &tmpRect))
242 return true;
243 }
244 }
245 return false;
246}
247
248DECLINLINE(bool) vboxVdmaDirtyRectsIsCover(const RECT *paRects, uint32_t cRects, const RECT *paRectsCovered, uint32_t cRectsCovered)
249{
250 for (uint32_t i = 0; i < cRectsCovered; ++i)
251 {
252 const RECT * pRectCovered = &paRectsCovered[i];
253 uint32_t j = 0;
254 for (; j < cRects; ++j)
255 {
256 const RECT * pRect = &paRects[j];
257 if (vboxWddmRectIsCoveres(pRect, pRectCovered))
258 break;
259 }
260 if (j == cRects)
261 return false;
262 }
263 return true;
264}
265
266NTSTATUS vboxVdmaPostHideSwapchain(PVBOXWDDM_SWAPCHAIN pSwapchain)
267{
268 Assert(KeGetCurrentIrql() < DISPATCH_LEVEL);
269 uint32_t cbCmdInternal = VBOXVIDEOCM_CMD_RECTS_INTERNAL_SIZE4CRECTS(0);
270 PVBOXVIDEOCM_CMD_RECTS_INTERNAL pCmdInternal =
271 (PVBOXVIDEOCM_CMD_RECTS_INTERNAL)vboxVideoCmCmdCreate(&pSwapchain->pContext->CmContext, cbCmdInternal);
272 Assert(pCmdInternal);
273 if (pCmdInternal)
274 {
275 pCmdInternal->hSwapchainUm = pSwapchain->hSwapchainUm;
276 pCmdInternal->Cmd.fFlags.Value = 0;
277 pCmdInternal->Cmd.fFlags.bAddHiddenRects = 1;
278 pCmdInternal->Cmd.fFlags.bHide = 1;
279 pCmdInternal->Cmd.RectsInfo.cRects = 0;
280 vboxVideoCmCmdSubmit(pCmdInternal, VBOXVIDEOCM_SUBMITSIZE_DEFAULT);
281 return STATUS_SUCCESS;
282 }
283 return STATUS_NO_MEMORY;
284}
285
286static VOID vboxWddmBltPipeRectsTranslate(VBOXVDMAPIPE_RECTS *pRects, int x, int y)
287{
288 vboxWddmRectTranslate(&pRects->ContextRect, x, y);
289
290 for (UINT i = 0; i < pRects->UpdateRects.cRects; ++i)
291 {
292 vboxWddmRectTranslate(&pRects->UpdateRects.aRects[i], x, y);
293 }
294}
295
296static VBOXVDMAPIPE_RECTS * vboxWddmBltPipeRectsDup(const VBOXVDMAPIPE_RECTS *pRects)
297{
298 const size_t cbDup = RT_OFFSETOF(VBOXVDMAPIPE_RECTS, UpdateRects.aRects[pRects->UpdateRects.cRects]);
299 VBOXVDMAPIPE_RECTS *pDup = (VBOXVDMAPIPE_RECTS*)vboxWddmMemAllocZero(cbDup);
300 if (!pDup)
301 {
302 WARN(("vboxWddmMemAllocZero failed"));
303 return NULL;
304 }
305 memcpy(pDup, pRects, cbDup);
306 return pDup;
307}
308
309typedef struct VBOXMP_VDMACR_WRITECOMPLETION
310{
311 void *pvBufferToFree;
312} VBOXMP_VDMACR_WRITECOMPLETION, *PVBOXMP_VDMACR_WRITECOMPLETION;
313
314static DECLCALLBACK(void) vboxVdmaCrWriteCompletion(PVBOXMP_CRSHGSMITRANSPORT pCon, int rc, void *pvCtx)
315{
316 PVBOXMP_VDMACR_WRITECOMPLETION pData = (PVBOXMP_VDMACR_WRITECOMPLETION)pvCtx;
317 void* pvBufferToFree = pData->pvBufferToFree;
318 if (pvBufferToFree)
319 VBoxMpCrShgsmiTransportBufFree(pCon, pvBufferToFree);
320
321 VBoxMpCrShgsmiTransportCmdTermWriteAsync(pCon, pvCtx);
322}
323
324typedef struct VBOXMP_VDMACR_WRITEREADCOMPLETION
325{
326 void *pvBufferToFree;
327 void *pvContext;
328} VBOXMP_VDMACR_WRITEREADCOMPLETION, *PVBOXMP_VDMACR_WRITEREADCOMPLETION;
329
330void vboxVdmaCrSubmitWriteReadAsyncGenericCompletion(PVBOXMP_CRSHGSMITRANSPORT pCon, void *pvCtx)
331{
332 PVBOXMP_VDMACR_WRITEREADCOMPLETION pData = (PVBOXMP_VDMACR_WRITEREADCOMPLETION)pvCtx;
333 void* pvBufferToFree = pData->pvBufferToFree;
334 if (pvBufferToFree)
335 VBoxMpCrShgsmiTransportBufFree(pCon, pvBufferToFree);
336
337 VBoxMpCrShgsmiTransportCmdTermWriteReadAsync(pCon, pvCtx);
338}
339
340NTSTATUS vboxVdmaCrSubmitWriteReadAsync(PVBOXMP_DEVEXT pDevExt, VBOXMP_CRPACKER *pCrPacker, uint32_t u32CrConClientID, PFNVBOXMP_CRSHGSMITRANSPORT_SENDWRITEREADASYNC_COMPLETION pfnCompletion, void *pvCompletion)
341{
342 Assert(u32CrConClientID);
343 NTSTATUS Status = STATUS_SUCCESS;
344 uint32_t cbBuffer;
345 void * pvPackBuffer;
346 void * pvBuffer = VBoxMpCrPackerTxBufferComplete(pCrPacker, &cbBuffer, &pvPackBuffer);
347 if (pvBuffer)
348 {
349 PVBOXMP_VDMACR_WRITEREADCOMPLETION pvCompletionData = (PVBOXMP_VDMACR_WRITEREADCOMPLETION)VBoxMpCrShgsmiTransportCmdCreateWriteReadAsync(&pDevExt->CrHgsmiTransport, u32CrConClientID, pvBuffer, cbBuffer,
350 pfnCompletion, sizeof (*pvCompletionData));
351 if (pvCompletionData)
352 {
353 pvCompletionData->pvBufferToFree = pvPackBuffer;
354 pvCompletionData->pvContext = pvCompletion;
355 int rc = VBoxMpCrShgsmiTransportCmdSubmitWriteReadAsync(&pDevExt->CrHgsmiTransport, pvCompletionData);
356 if (RT_SUCCESS(rc))
357 {
358 return STATUS_SUCCESS;
359 }
360 WARN(("VBoxMpCrShgsmiTransportCmdSubmitWriteAsync failed, rc %d", rc));
361 Status = STATUS_UNSUCCESSFUL;
362 VBoxMpCrShgsmiTransportCmdTermWriteReadAsync(&pDevExt->CrHgsmiTransport, pvCompletionData);
363 }
364 else
365 {
366 WARN(("VBoxMpCrShgsmiTransportCmdCreateWriteAsync failed"));
367 Status = STATUS_INSUFFICIENT_RESOURCES;
368 }
369 }
370
371 return Status;
372}
373
374NTSTATUS vboxVdmaCrSubmitWriteAsync(PVBOXMP_DEVEXT pDevExt, VBOXMP_CRPACKER *pCrPacker, uint32_t u32CrConClientID)
375{
376 Assert(u32CrConClientID);
377 NTSTATUS Status = STATUS_SUCCESS;
378 uint32_t cbBuffer;
379 void * pvPackBuffer;
380 void * pvBuffer = VBoxMpCrPackerTxBufferComplete(pCrPacker, &cbBuffer, &pvPackBuffer);
381 if (pvBuffer)
382 {
383 PVBOXMP_VDMACR_WRITECOMPLETION pvCompletionData = (PVBOXMP_VDMACR_WRITECOMPLETION)VBoxMpCrShgsmiTransportCmdCreateWriteAsync(&pDevExt->CrHgsmiTransport, u32CrConClientID, pvBuffer, cbBuffer,
384 vboxVdmaCrWriteCompletion, sizeof (*pvCompletionData));
385 if (pvCompletionData)
386 {
387 pvCompletionData->pvBufferToFree = pvPackBuffer;
388 int rc = VBoxMpCrShgsmiTransportCmdSubmitWriteAsync(&pDevExt->CrHgsmiTransport, pvCompletionData);
389 if (RT_SUCCESS(rc))
390 {
391 return STATUS_SUCCESS;
392 }
393 WARN(("VBoxMpCrShgsmiTransportCmdSubmitWriteAsync failed, rc %d", rc));
394 Status = STATUS_UNSUCCESSFUL;
395 VBoxMpCrShgsmiTransportCmdTermWriteAsync(&pDevExt->CrHgsmiTransport, pvCompletionData);
396 }
397 else
398 {
399 WARN(("VBoxMpCrShgsmiTransportCmdCreateWriteAsync failed"));
400 Status = STATUS_INSUFFICIENT_RESOURCES;
401 }
402 }
403
404 return Status;
405}
406
407static NTSTATUS vboxVdmaVRegGet(PVBOXWDDM_SWAPCHAIN pSwapchain, const RTRECT *pCtxRect, uint32_t *pcVRects, RTRECT **ppVRectsBuff, uint32_t *pcVRectsBuff)
408{
409 RTRECT *pVRectsBuff = *ppVRectsBuff;
410 uint32_t cVRectsBuff = *pcVRectsBuff;
411 uint32_t cVRects = VBoxVrListRectsCount(&pSwapchain->VisibleRegions);
412 if (cVRectsBuff < cVRects)
413 {
414 if (pVRectsBuff)
415 vboxWddmMemFree(pVRectsBuff);
416 pVRectsBuff = (RTRECT*)vboxWddmMemAlloc(cVRects * sizeof (pVRectsBuff[0]));
417 if (!pVRectsBuff)
418 {
419 WARN(("vboxWddmMemAlloc failed"));
420 *pcVRectsBuff = 0;
421 *ppVRectsBuff = NULL;
422 *pcVRects = NULL;
423 return STATUS_NO_MEMORY;
424 }
425
426 cVRectsBuff = cVRects;
427 *pcVRectsBuff = cVRectsBuff;
428 *ppVRectsBuff = pVRectsBuff;
429 }
430
431 int rc = VBoxVrListRectsGet(&pSwapchain->VisibleRegions, cVRects, pVRectsBuff);
432 AssertRC(rc);
433 if (pCtxRect->xLeft || pCtxRect->yTop)
434 {
435 for (UINT i = 0; i < cVRects; ++i)
436 {
437 VBoxRectTranslate(&pVRectsBuff[i], -pCtxRect->xLeft, -pCtxRect->yTop);
438 }
439 }
440
441 *pcVRects = cVRects;
442 return STATUS_SUCCESS;
443}
444
445
446/**
447 * @param pDevExt
448 */
449static NTSTATUS vboxVdmaProcessVRegCmdLegacy(PVBOXMP_DEVEXT pDevExt,
450 VBOXMP_CRPACKER *pCrPacker,
451 uint32_t u32CrConClientID,
452 PVBOXWDDM_SOURCE pSource,
453 PVBOXWDDM_SWAPCHAIN pSwapchain,
454 const RECT *pSrcRect,
455 const VBOXVDMAPIPE_RECTS *pContextRects)
456{
457 VBOXVDMAPIPE_RECTS *pRectsToFree = NULL;
458 POINT pos = pSource->VScreenPos;
459 if (pos.x || pos.y)
460 {
461 pRectsToFree = vboxWddmBltPipeRectsDup(pContextRects);
462 /* note: do NOT translate the src rect since it is used for screen pos calculation */
463 vboxWddmBltPipeRectsTranslate(pRectsToFree, pos.x, pos.y);
464 pContextRects = pRectsToFree;
465 }
466 const VBOXWDDM_RECTS_INFO *pRects = &pContextRects->UpdateRects;
467 NTSTATUS Status = STATUS_SUCCESS;
468 int rc;
469 bool fCurChanged = FALSE, fCurRectChanged = FALSE;
470 POINT CurPos;
471 RTRECT *pVRectsBuff = NULL;
472 uint32_t cVRectsBuff = 0;
473 VBOXWDDM_CTXLOCK_DATA
474
475 VBOXWDDM_CTXLOCK_LOCK(pDevExt);
476
477 if (pSwapchain)
478 {
479 CurPos.x = pContextRects->ContextRect.left - pSrcRect->left;
480 CurPos.y = pContextRects->ContextRect.top - pSrcRect->top;
481
482 if (CurPos.x != pSwapchain->Pos.x || CurPos.y != pSwapchain->Pos.y)
483 {
484#if 0
485 if (pSwapchain->Pos.x != VBOXWDDM_INVALID_COORD)
486 VBoxVrListTranslate(&pSwapchain->VisibleRegions, pSwapchain->Pos.x - CurPos.x, pSwapchain->Pos.y - CurPos.y);
487 else
488#endif
489 VBoxVrListClear(&pSwapchain->VisibleRegions);
490 fCurRectChanged = TRUE;
491 pSwapchain->Pos = CurPos;
492 }
493
494 rc = VBoxVrListRectsAdd(&pSwapchain->VisibleRegions, pRects->cRects, (const RTRECT*)pRects->aRects, &fCurChanged);
495 if (!RT_SUCCESS(rc))
496 {
497 WARN(("VBoxWddmVrListRectsAdd failed, rc %d!", rc));
498 Status = STATUS_UNSUCCESSFUL;
499 goto done;
500 }
501
502
503 /* visible rects of different windows do not intersect,
504 * so if the given window visible rects did not increase, others have not changed either */
505 if (!fCurChanged && !fCurRectChanged)
506 goto done;
507 }
508
509 /* before posting the add visible rects diff, we need to first hide rects for other windows */
510
511 for (PLIST_ENTRY pCur = pDevExt->SwapchainList3D.Flink; pCur != &pDevExt->SwapchainList3D; pCur = pCur->Flink)
512 {
513 if (pCur != &pSwapchain->DevExtListEntry)
514 {
515 PVBOXWDDM_SWAPCHAIN pCurSwapchain = VBOXWDDMENTRY_2_SWAPCHAIN(pCur);
516 PVBOXWDDM_CONTEXT pCurContext = pCurSwapchain->pContext;
517 PVBOXMP_CRPACKER pCurPacker = &pCurContext->CrPacker;
518 bool fChanged = FALSE;
519
520 rc = VBoxVrListRectsSubst(&pCurSwapchain->VisibleRegions, pRects->cRects, (const RTRECT*)pRects->aRects, &fChanged);
521 if (!RT_SUCCESS(rc))
522 {
523 WARN(("VBoxWddmVrListRectsAdd failed, rc %d!", rc));
524 Status = STATUS_UNSUCCESSFUL;
525 goto done;
526 }
527
528 if (!fChanged)
529 continue;
530
531 uint32_t cVRects;
532 RTRECT CurCtxRect;
533 CurCtxRect.xLeft = pCurSwapchain->Pos.x;
534 CurCtxRect.yTop = pCurSwapchain->Pos.y;
535 CurCtxRect.xRight = CurCtxRect.xLeft + pCurSwapchain->width;
536 CurCtxRect.yBottom = CurCtxRect.yTop + pCurSwapchain->height;
537 Status = vboxVdmaVRegGet(pCurSwapchain, &CurCtxRect, &cVRects, &pVRectsBuff, &cVRectsBuff);
538 if (!NT_SUCCESS(Status))
539 {
540 WARN(("vboxVdmaVRegGet Status 0x%x", Status));
541 goto done;
542 }
543
544 void *pvCommandBuffer = NULL;
545 uint32_t cbCommandBuffer = VBOXMP_CRCMD_HEADER_SIZE;
546 cbCommandBuffer += VBOXMP_CRCMD_SIZE_WINDOWVISIBLEREGIONS(cVRects);
547
548 pvCommandBuffer = VBoxMpCrShgsmiTransportBufAlloc(&pDevExt->CrHgsmiTransport, cbCommandBuffer);
549 if (!pvCommandBuffer)
550 {
551 WARN(("VBoxMpCrShgsmiTransportBufAlloc failed!"));
552 Status = VERR_OUT_OF_RESOURCES;
553 goto done;
554 }
555
556 VBoxMpCrPackerTxBufferInit(pCurPacker, pvCommandBuffer, cbCommandBuffer, 1);
557
558 Assert(pCurSwapchain->winHostID);
559 crPackWindowVisibleRegion(&pCurPacker->CrPacker, pCurSwapchain->winHostID, cVRects, (GLint*)pVRectsBuff);
560
561 Status = vboxVdmaCrSubmitWriteAsync(pDevExt, pCurPacker, pCurContext->u32CrConClientID);
562 if (!NT_SUCCESS(Status))
563 {
564 WARN(("vboxVdmaCrSubmitWriteAsync failed Status 0x%x", Status));
565 VBoxMpCrShgsmiTransportBufFree(&pDevExt->CrHgsmiTransport, pvCommandBuffer);
566 }
567 }
568 }
569
570 if (!pSwapchain)
571 goto done;
572
573 uint32_t cbCommandBuffer = VBOXMP_CRCMD_HEADER_SIZE, cCommands = 0;
574
575 uint32_t cVRects;
576 Status = vboxVdmaVRegGet(pSwapchain, (const RTRECT *)&pContextRects->ContextRect, &cVRects, &pVRectsBuff, &cVRectsBuff);
577 if (!NT_SUCCESS(Status))
578 {
579 WARN(("vboxVdmaVRegGet Status 0x%x", Status));
580 goto done;
581 }
582
583 ++cCommands;
584 cbCommandBuffer += VBOXMP_CRCMD_SIZE_WINDOWVISIBLEREGIONS(cVRects);
585
586 if (fCurRectChanged && fCurChanged)
587 {
588 ++cCommands;
589 cbCommandBuffer += VBOXMP_CRCMD_SIZE_WINDOWPOSITION;
590 }
591
592 if (!pSwapchain->fExposed)
593 {
594 ++cCommands;
595 cbCommandBuffer += VBOXMP_CRCMD_SIZE_WINDOWSHOW;
596 ++cCommands;
597 cbCommandBuffer += VBOXMP_CRCMD_SIZE_WINDOWSIZE;
598 }
599
600 void *pvCommandBuffer = VBoxMpCrShgsmiTransportBufAlloc(&pDevExt->CrHgsmiTransport, cbCommandBuffer);
601 if (!pvCommandBuffer)
602 {
603 WARN(("VBoxMpCrShgsmiTransportBufAlloc failed!"));
604 Status = STATUS_INSUFFICIENT_RESOURCES;
605 goto done;
606 }
607
608 VBoxMpCrPackerTxBufferInit(pCrPacker, pvCommandBuffer, cbCommandBuffer, cCommands);
609
610 Assert(pSwapchain->winHostID);
611
612 if (fCurRectChanged && fCurChanged)
613 crPackWindowPosition(&pCrPacker->CrPacker, pSwapchain->winHostID, CurPos.x, CurPos.y);
614
615 if (!pSwapchain->fExposed)
616 {
617 crPackWindowSize(&pCrPacker->CrPacker, pSwapchain->winHostID, pSwapchain->width, pSwapchain->height);
618 crPackWindowShow(&pCrPacker->CrPacker, pSwapchain->winHostID, TRUE);
619 pSwapchain->fExposed = TRUE;
620 }
621
622 crPackWindowVisibleRegion(&pCrPacker->CrPacker, pSwapchain->winHostID, cVRects, (GLint*)pVRectsBuff);
623
624 Status = vboxVdmaCrSubmitWriteAsync(pDevExt, pCrPacker, u32CrConClientID);
625 if (!NT_SUCCESS(Status))
626 {
627 WARN(("vboxVdmaCrSubmitWriteAsync failed Status 0x%x", Status));
628 VBoxMpCrShgsmiTransportBufFree(&pDevExt->CrHgsmiTransport, pvCommandBuffer);
629 }
630
631done:
632 VBOXWDDM_CTXLOCK_UNLOCK(pDevExt);
633
634 if (pRectsToFree)
635 vboxWddmMemFree(pRectsToFree);
636
637 if (pVRectsBuff)
638 vboxWddmMemFree(pVRectsBuff);
639
640 return Status;
641}
642
643static NTSTATUS vboxVdmaGgDmaColorFill(PVBOXMP_DEVEXT pDevExt, VBOXVDMA_CLRFILL *pCF)
644{
645 NTSTATUS Status = STATUS_UNSUCCESSFUL;
646 Assert (pDevExt->pvVisibleVram);
647 if (pDevExt->pvVisibleVram)
648 {
649 PVBOXWDDM_ALLOCATION pAlloc = pCF->Alloc.pAlloc;
650 Assert(pAlloc->AllocData.Addr.offVram != VBOXVIDEOOFFSET_VOID);
651 if (pAlloc->AllocData.Addr.offVram != VBOXVIDEOOFFSET_VOID)
652 {
653 RECT UnionRect = {0};
654 uint8_t *pvMem = pDevExt->pvVisibleVram + pAlloc->AllocData.Addr.offVram;
655 UINT bpp = pAlloc->AllocData.SurfDesc.bpp;
656 Assert(bpp);
657 Assert(((bpp * pAlloc->AllocData.SurfDesc.width) >> 3) == pAlloc->AllocData.SurfDesc.pitch);
658 switch (bpp)
659 {
660 case 32:
661 {
662 uint8_t bytestPP = bpp >> 3;
663 for (UINT i = 0; i < pCF->Rects.cRects; ++i)
664 {
665 RECT *pRect = &pCF->Rects.aRects[i];
666 for (LONG ir = pRect->top; ir < pRect->bottom; ++ir)
667 {
668 uint32_t * pvU32Mem = (uint32_t*)(pvMem + (ir * pAlloc->AllocData.SurfDesc.pitch) + (pRect->left * bytestPP));
669 uint32_t cRaw = pRect->right - pRect->left;
670 Assert(pRect->left >= 0);
671 Assert(pRect->right <= (LONG)pAlloc->AllocData.SurfDesc.width);
672 Assert(pRect->top >= 0);
673 Assert(pRect->bottom <= (LONG)pAlloc->AllocData.SurfDesc.height);
674 for (UINT j = 0; j < cRaw; ++j)
675 {
676 *pvU32Mem = pCF->Color;
677 ++pvU32Mem;
678 }
679 }
680 vboxWddmRectUnited(&UnionRect, &UnionRect, pRect);
681 }
682 Status = STATUS_SUCCESS;
683 break;
684 }
685 case 16:
686 case 8:
687 default:
688 AssertBreakpoint();
689 break;
690 }
691
692 if (Status == STATUS_SUCCESS)
693 {
694 if (pAlloc->AllocData.SurfDesc.VidPnSourceId != D3DDDI_ID_UNINITIALIZED
695 && VBOXWDDM_IS_FB_ALLOCATION(pDevExt, pAlloc)
696 && pAlloc->bVisible
697 )
698 {
699 if (!vboxWddmRectIsEmpty(&UnionRect))
700 {
701 PVBOXWDDM_SOURCE pSource = &pDevExt->aSources[pCF->Alloc.pAlloc->AllocData.SurfDesc.VidPnSourceId];
702 uint32_t cUnlockedVBVADisabled = ASMAtomicReadU32(&pDevExt->cUnlockedVBVADisabled);
703 if (!cUnlockedVBVADisabled)
704 {
705 VBOXVBVA_OP(ReportDirtyRect, pDevExt, pSource, &UnionRect);
706 }
707 else
708 {
709 VBOXVBVA_OP_WITHLOCK(ReportDirtyRect, pDevExt, pSource, &UnionRect);
710 }
711 }
712 }
713 else
714 {
715 AssertBreakpoint();
716 }
717 }
718 }
719 }
720
721 return Status;
722}
723
724NTSTATUS vboxVdmaGgDmaBltPerform(PVBOXMP_DEVEXT pDevExt, PVBOXWDDM_ALLOC_DATA pSrcAlloc, RECT* pSrcRect,
725 PVBOXWDDM_ALLOC_DATA pDstAlloc, RECT* pDstRect)
726{
727 uint8_t* pvVramBase = pDevExt->pvVisibleVram;
728 /* we do not support stretching */
729 uint32_t srcWidth = pSrcRect->right - pSrcRect->left;
730 uint32_t srcHeight = pSrcRect->bottom - pSrcRect->top;
731 uint32_t dstWidth = pDstRect->right - pDstRect->left;
732 uint32_t dstHeight = pDstRect->bottom - pDstRect->top;
733 Assert(srcHeight == dstHeight);
734 Assert(dstWidth == srcWidth);
735 Assert(pDstAlloc->Addr.offVram != VBOXVIDEOOFFSET_VOID);
736 Assert(pSrcAlloc->Addr.offVram != VBOXVIDEOOFFSET_VOID);
737 D3DDDIFORMAT enmSrcFormat, enmDstFormat;
738
739 enmSrcFormat = pSrcAlloc->SurfDesc.format;
740 enmDstFormat = pDstAlloc->SurfDesc.format;
741
742 if (enmSrcFormat != enmDstFormat)
743 {
744 /* just ignore the alpha component
745 * this is ok since our software-based stuff can not handle alpha channel in any way */
746 enmSrcFormat = vboxWddmFmtNoAlphaFormat(enmSrcFormat);
747 enmDstFormat = vboxWddmFmtNoAlphaFormat(enmDstFormat);
748 if (enmSrcFormat != enmDstFormat)
749 {
750 WARN(("color conversion src(%d), dst(%d) not supported!", pSrcAlloc->SurfDesc.format, pDstAlloc->SurfDesc.format));
751 return STATUS_INVALID_PARAMETER;
752 }
753 }
754 if (srcHeight != dstHeight)
755 return STATUS_INVALID_PARAMETER;
756 if (srcWidth != dstWidth)
757 return STATUS_INVALID_PARAMETER;
758 if (pDstAlloc->Addr.offVram == VBOXVIDEOOFFSET_VOID)
759 return STATUS_INVALID_PARAMETER;
760 if (pSrcAlloc->Addr.offVram == VBOXVIDEOOFFSET_VOID)
761 return STATUS_INVALID_PARAMETER;
762
763 uint8_t *pvDstSurf = pDstAlloc->Addr.SegmentId ? pvVramBase + pDstAlloc->Addr.offVram : (uint8_t*)pDstAlloc->Addr.pvMem;
764 uint8_t *pvSrcSurf = pSrcAlloc->Addr.SegmentId ? pvVramBase + pSrcAlloc->Addr.offVram : (uint8_t*)pSrcAlloc->Addr.pvMem;
765
766 if (pDstAlloc->SurfDesc.width == dstWidth
767 && pSrcAlloc->SurfDesc.width == srcWidth
768 && pSrcAlloc->SurfDesc.width == pDstAlloc->SurfDesc.width)
769 {
770 Assert(!pDstRect->left);
771 Assert(!pSrcRect->left);
772 uint32_t cbDstOff = vboxWddmCalcOffXYrd(0 /* x */, pDstRect->top, pDstAlloc->SurfDesc.pitch, pDstAlloc->SurfDesc.format);
773 uint32_t cbSrcOff = vboxWddmCalcOffXYrd(0 /* x */, pSrcRect->top, pSrcAlloc->SurfDesc.pitch, pSrcAlloc->SurfDesc.format);
774 uint32_t cbSize = vboxWddmCalcSize(pDstAlloc->SurfDesc.pitch, dstHeight, pDstAlloc->SurfDesc.format);
775 memcpy(pvDstSurf + cbDstOff, pvSrcSurf + cbSrcOff, cbSize);
776 }
777 else
778 {
779 uint32_t cbDstLine = vboxWddmCalcRowSize(pDstRect->left, pDstRect->right, pDstAlloc->SurfDesc.format);
780 uint32_t offDstStart = vboxWddmCalcOffXYrd(pDstRect->left, pDstRect->top, pDstAlloc->SurfDesc.pitch, pDstAlloc->SurfDesc.format);
781 Assert(cbDstLine <= pDstAlloc->SurfDesc.pitch);
782 uint32_t cbDstSkip = pDstAlloc->SurfDesc.pitch;
783 uint8_t * pvDstStart = pvDstSurf + offDstStart;
784
785 uint32_t cbSrcLine = vboxWddmCalcRowSize(pSrcRect->left, pSrcRect->right, pSrcAlloc->SurfDesc.format);
786 uint32_t offSrcStart = vboxWddmCalcOffXYrd(pSrcRect->left, pSrcRect->top, pSrcAlloc->SurfDesc.pitch, pSrcAlloc->SurfDesc.format);
787 Assert(cbSrcLine <= pSrcAlloc->SurfDesc.pitch);
788 uint32_t cbSrcSkip = pSrcAlloc->SurfDesc.pitch;
789 const uint8_t * pvSrcStart = pvSrcSurf + offSrcStart;
790
791 uint32_t cRows = vboxWddmCalcNumRows(pDstRect->top, pDstRect->bottom, pDstAlloc->SurfDesc.format);
792
793 Assert(cbDstLine == cbSrcLine);
794
795 for (uint32_t i = 0; i < cRows; ++i)
796 {
797 memcpy(pvDstStart, pvSrcStart, cbDstLine);
798 pvDstStart += cbDstSkip;
799 pvSrcStart += cbSrcSkip;
800 }
801 }
802 return STATUS_SUCCESS;
803}
804
805/*
806 * @return on success the number of bytes the command contained, otherwise - VERR_xxx error code
807 */
808static NTSTATUS vboxVdmaGgDmaBlt(PVBOXMP_DEVEXT pDevExt, PVBOXVDMA_BLT pBlt)
809{
810 /* we do not support stretching for now */
811 Assert(pBlt->SrcRect.right - pBlt->SrcRect.left == pBlt->DstRects.ContextRect.right - pBlt->DstRects.ContextRect.left);
812 Assert(pBlt->SrcRect.bottom - pBlt->SrcRect.top == pBlt->DstRects.ContextRect.bottom - pBlt->DstRects.ContextRect.top);
813 if (pBlt->SrcRect.right - pBlt->SrcRect.left != pBlt->DstRects.ContextRect.right - pBlt->DstRects.ContextRect.left)
814 return STATUS_INVALID_PARAMETER;
815 if (pBlt->SrcRect.bottom - pBlt->SrcRect.top != pBlt->DstRects.ContextRect.bottom - pBlt->DstRects.ContextRect.top)
816 return STATUS_INVALID_PARAMETER;
817 Assert(pBlt->DstRects.UpdateRects.cRects);
818
819 NTSTATUS Status = STATUS_SUCCESS;
820
821 if (pBlt->DstRects.UpdateRects.cRects)
822 {
823 for (uint32_t i = 0; i < pBlt->DstRects.UpdateRects.cRects; ++i)
824 {
825 RECT SrcRect;
826 vboxWddmRectTranslated(&SrcRect, &pBlt->DstRects.UpdateRects.aRects[i], -pBlt->DstRects.ContextRect.left, -pBlt->DstRects.ContextRect.top);
827
828 Status = vboxVdmaGgDmaBltPerform(pDevExt, &pBlt->SrcAlloc.pAlloc->AllocData, &SrcRect,
829 &pBlt->DstAlloc.pAlloc->AllocData, &pBlt->DstRects.UpdateRects.aRects[i]);
830 Assert(Status == STATUS_SUCCESS);
831 if (Status != STATUS_SUCCESS)
832 return Status;
833 }
834 }
835 else
836 {
837 Status = vboxVdmaGgDmaBltPerform(pDevExt, &pBlt->SrcAlloc.pAlloc->AllocData, &pBlt->SrcRect,
838 &pBlt->DstAlloc.pAlloc->AllocData, &pBlt->DstRects.ContextRect);
839 Assert(Status == STATUS_SUCCESS);
840 if (Status != STATUS_SUCCESS)
841 return Status;
842 }
843
844 return Status;
845}
846
847typedef struct VBOXVDMA_CRRXGENERICSYNC
848{
849 int rc;
850 KEVENT Event;
851} VBOXVDMA_CRRXGENERICSYNC, *PVBOXVDMA_CRRXGENERICSYNC;
852
853static DECLCALLBACK(void) vboxVdmaCrRxGenericSyncCompletion(PVBOXMP_CRSHGSMITRANSPORT pCon, int rc, void *pvRx, uint32_t cbRx, void *pvCtx)
854{
855 PVBOXMP_VDMACR_WRITEREADCOMPLETION pvCompletionData = (PVBOXMP_VDMACR_WRITEREADCOMPLETION)pvCtx;
856 PVBOXVDMA_CRRXGENERICSYNC pData = (PVBOXVDMA_CRRXGENERICSYNC)pvCompletionData->pvContext;
857 if (RT_SUCCESS(rc))
858 {
859 rc = VBoxMpCrCmdRxHandler((CRMessageHeader*)pvRx, cbRx);
860 if (!RT_SUCCESS(rc))
861 {
862 WARN(("VBoxMpCrCmdRxHandler failed %d", rc));
863 }
864 }
865 else
866 {
867 WARN(("rx failure %d", rc));
868 }
869
870 pData->rc = rc;
871
872 KeSetEvent(&pData->Event, 0, FALSE);
873
874 vboxVdmaCrSubmitWriteReadAsyncGenericCompletion(pCon, pvCtx);
875}
876
877NTSTATUS vboxVdmaCrRxGenericSync(PVBOXMP_DEVEXT pDevExt, VBOXMP_CRPACKER *pCrPacker, uint32_t u32CrConClientID)
878{
879 VBOXVDMA_CRRXGENERICSYNC Data;
880 Data.rc = VERR_NOT_SUPPORTED;
881 KeInitializeEvent(&Data.Event, SynchronizationEvent, FALSE);
882 NTSTATUS Status = vboxVdmaCrSubmitWriteReadAsync(pDevExt, pCrPacker, u32CrConClientID, vboxVdmaCrRxGenericSyncCompletion, &Data);
883 if (!NT_SUCCESS(Status))
884 {
885 WARN(("vboxVdmaCrSubmitWriteAsync failed Status 0x%x", Status));
886 return Status;
887 }
888
889 Status = KeWaitForSingleObject(&Data.Event, Executive, KernelMode, FALSE, NULL /* PLARGE_INTEGER Timeout */);
890 if (!NT_SUCCESS(Status))
891 {
892 WARN(("KeWaitForSingleObject failed Status 0x%x", Status));
893 return Status;
894 }
895
896 return STATUS_SUCCESS;
897}
898
899typedef struct VBOXMP_CRHGSMIMGR
900{
901 VBOXMP_CRPACKER CrPacker;
902 void *pvCommandBuffer;
903} VBOXMP_CRHGSMIMGR;
904
905DECLINLINE(CRPackContext*) vboxVdmaCrHmGetPackContext(VBOXMP_CRHGSMIMGR *pMgr)
906{
907 return &pMgr->CrPacker.CrPacker;
908}
909
910NTSTATUS vboxVdmaCrHmCreate(PVBOXMP_DEVEXT pDevExt, VBOXMP_CRHGSMIMGR *pMgr, uint32_t cbCommandBuffer, uint32_t cCommands)
911{
912 pMgr->pvCommandBuffer = VBoxMpCrShgsmiTransportBufAlloc(&pDevExt->CrHgsmiTransport, cbCommandBuffer);
913 if (!pMgr->pvCommandBuffer)
914 {
915 WARN(("VBoxMpCrShgsmiTransportBufAlloc failed!"));
916 return VERR_OUT_OF_RESOURCES;
917 }
918
919 VBoxMpCrPackerInit(&pMgr->CrPacker);
920
921 VBoxMpCrPackerTxBufferInit(&pMgr->CrPacker, pMgr->pvCommandBuffer, cbCommandBuffer, cCommands);
922
923 return STATUS_SUCCESS;
924}
925
926NTSTATUS vboxVdmaCrHmSubmitWrSync(PVBOXMP_DEVEXT pDevExt, VBOXMP_CRHGSMIMGR *pMgr, uint32_t u32CrConClientID)
927{
928 NTSTATUS Status = vboxVdmaCrRxGenericSync(pDevExt, &pMgr->CrPacker, u32CrConClientID);
929 if (!NT_SUCCESS(Status))
930 {
931 WARN(("vboxVdmaCrRxGenericSync failed Status 0x%x", Status));
932 VBoxMpCrShgsmiTransportBufFree(&pDevExt->CrHgsmiTransport, pMgr->pvCommandBuffer);
933 return Status;
934 }
935
936 return STATUS_SUCCESS;
937}
938#if 0
939NTSTATUS vboxVdmaCrCmdGetChromiumParametervCR(PVBOXMP_DEVEXT pDevExt, uint32_t u32CrConClientID, GLenum target, GLuint index, GLenum type, GLsizei count, GLvoid * values)
940{
941 uint32_t cbCommandBuffer = VBOXMP_CRCMD_HEADER_SIZE + VBOXMP_CRCMD_SIZE_GETCHROMIUMPARAMETERVCR;
942 uint32_t cCommands = 1;
943
944 VBOXMP_CRHGSMIMGR Mgr;
945 NTSTATUS Status = vboxVdmaCrHmCreate(pDevExt, &Mgr, cbCommandBuffer, cCommands);
946 if (!NT_SUCCESS(Status))
947 {
948 WARN(("vboxVdmaCrHmCreate failed Status 0x%x", Status));
949 return Status;
950 }
951
952 int dummy = 1;
953
954 crPackGetChromiumParametervCR(vboxVdmaCrHmGetPackContext(&Mgr), target, index, type, count, values, &dummy);
955
956 Status = vboxVdmaCrHmSubmitWrSync(pDevExt, &Mgr, u32CrConClientID);
957 if (!NT_SUCCESS(Status))
958 {
959 WARN(("vboxVdmaCrHmSubmitWrSync failed Status 0x%x", Status));
960 return Status;
961 }
962
963 return STATUS_SUCCESS;
964}
965
966static NTSTATUS vboxVdmaCrCmdCreateContext(PVBOXMP_DEVEXT pDevExt, int32_t visualBits, int32_t *pi32CtxID)
967{
968 uint32_t cbCommandBuffer = VBOXMP_CRCMD_HEADER_SIZE + VBOXMP_CRCMD_SIZE_CREATECONTEXT;
969 uint32_t cCommands = 1;
970
971 VBOXMP_CRHGSMIMGR Mgr;
972 NTSTATUS Status = vboxVdmaCrHmCreate(pDevExt, &Mgr, cbCommandBuffer, cCommands);
973 if (!NT_SUCCESS(Status))
974 {
975 WARN(("vboxVdmaCrHmCreate failed Status 0x%x", Status));
976 return Status;
977 }
978
979 int dummy = 1;
980
981 crPackCreateContext(&CrPacker.CrPacker, "", visualBits, 0, &pi32CtxID, &dummy);
982
983 Status = vboxVdmaCrHmSubmitWrSync(pDevExt, &Mgr, u32CrConClientID);
984 if (!NT_SUCCESS(Status))
985 {
986 WARN(("vboxVdmaCrHmSubmitWrSync failed Status 0x%x", Status));
987 return Status;
988 }
989
990 return STATUS_SUCCESS;
991}
992
993static NTSTATUS vboxVdmaCrCmdWindowCreate(PVBOXMP_DEVEXT pDevExt, int32_t visualBits, int32_t *pi32WinID)
994{
995 uint32_t cbCommandBuffer = VBOXMP_CRCMD_HEADER_SIZE + VBOXMP_CRCMD_SIZE_WINDOWCREATE;
996 uint32_t cCommands = 1;
997
998 VBOXMP_CRHGSMIMGR Mgr;
999 NTSTATUS Status = vboxVdmaCrHmCreate(pDevExt, &Mgr, cbCommandBuffer, cCommands);
1000 if (!NT_SUCCESS(Status))
1001 {
1002 WARN(("vboxVdmaCrHmCreate failed Status 0x%x", Status));
1003 return Status;
1004 }
1005
1006 int dummy = 1;
1007
1008 crPackWindowCreate(&CrPacker.CrPacker, "", visualBits, 0, &pi32CtxID, &dummy);
1009
1010 Status = vboxVdmaCrHmSubmitWrSync(pDevExt, &Mgr, u32CrConClientID);
1011 if (!NT_SUCCESS(Status))
1012 {
1013 WARN(("vboxVdmaCrHmSubmitWrSync failed Status 0x%x", Status));
1014 return Status;
1015 }
1016
1017 return STATUS_SUCCESS;
1018}
1019
1020static NTSTATUS vboxVdmaCrCtlGetDefaultCtxId(PVBOXMP_DEVEXT pDevExt, int32_t *pi32CtxID)
1021{
1022 if (!pDevExt->i32CrConDefaultCtxID)
1023 {
1024 if (!pDevExt->f3DEnabled)
1025 {
1026 WARN(("3D disabled, should not be here!"));
1027 return STATUS_UNSUCCESSFUL;
1028 }
1029
1030 uint32_t u32ClienID;
1031 NTSTATUS Status = vboxVdmaCrCtlGetDefaultClientId(pDevExt, &u32ClienID);
1032 if (!NT_SUCCESS(Status))
1033 {
1034 WARN(("vboxVdmaCrCtlGetDefaultClientId failed, Status %#x", Status));
1035 return Status;
1036 }
1037
1038 Status = vboxVdmaCrCmdWindowCreate(PVBOXMP_DEVEXT pDevExt, int32_t visualBits, int32_t *pi32WinID)
1039
1040 VBOXMP_CRPACKER CrPacker;
1041 VBoxMpCrPackerInit(&CrPacker);
1042
1043 int rc = VBoxMpCrCtlConConnect(&pDevExt->CrCtlCon, CR_PROTOCOL_VERSION_MAJOR, CR_PROTOCOL_VERSION_MINOR, &pDevExt->u32CrConDefaultClientID);
1044 if (!RT_SUCCESS(rc))
1045 {
1046 WARN(("VBoxMpCrCtlConConnect failed, rc %d", rc));
1047 return STATUS_UNSUCCESSFUL;
1048 }
1049 }
1050
1051 *pi32CtxID = pDevExt->i32CrConDefaultCtxID;
1052 return STATUS_SUCCESS;
1053}
1054#endif
1055
1056static NTSTATUS vboxVdmaTexPresentSubmit(PVBOXMP_DEVEXT pDevExt,
1057 VBOXMP_CRPACKER *pCrPacker,
1058 uint32_t u32CrConClientID,
1059 uint32_t hostID,
1060 uint32_t cfg,
1061 int32_t posX,
1062 int32_t posY,
1063 uint32_t cRects,
1064 const RTRECT*paRects)
1065{
1066 Assert(pDevExt->fTexPresentEnabled);
1067
1068 uint32_t cbCommandBuffer = VBOXMP_CRCMD_HEADER_SIZE + VBOXMP_CRCMD_SIZE_VBOXTEXPRESENT(cRects);
1069 uint32_t cCommands = 1;
1070 void *pvCommandBuffer = VBoxMpCrShgsmiTransportBufAlloc(&pDevExt->CrHgsmiTransport, cbCommandBuffer);
1071 if (!pvCommandBuffer)
1072 {
1073 WARN(("VBoxMpCrShgsmiTransportBufAlloc failed!"));
1074 return VERR_OUT_OF_RESOURCES;
1075 }
1076
1077 VBoxMpCrPackerTxBufferInit(pCrPacker, pvCommandBuffer, cbCommandBuffer, cCommands);
1078
1079 crPackVBoxTexPresent(&pCrPacker->CrPacker, hostID, cfg, posX, posY, cRects, (int32_t*)paRects);
1080
1081 NTSTATUS Status = vboxVdmaCrSubmitWriteAsync(pDevExt, pCrPacker, u32CrConClientID);
1082 if (!NT_SUCCESS(Status))
1083 {
1084 WARN(("vboxVdmaCrSubmitWriteAsync failed Status 0x%x", Status));
1085 VBoxMpCrShgsmiTransportBufFree(&pDevExt->CrHgsmiTransport, pvCommandBuffer);
1086 }
1087
1088 return Status;
1089}
1090
1091static NTSTATUS vboxVdmaCrCtlGetDefaultClientId(PVBOXMP_DEVEXT pDevExt, uint32_t *pu32ClienID)
1092{
1093 if (!pDevExt->u32CrConDefaultClientID)
1094 {
1095 if (!pDevExt->f3DEnabled)
1096 {
1097 WARN(("3D disabled, should not be here!"));
1098 return STATUS_UNSUCCESSFUL;
1099 }
1100
1101 int rc = VBoxMpCrCtlConConnect(&pDevExt->CrCtlCon, CR_PROTOCOL_VERSION_MAJOR, CR_PROTOCOL_VERSION_MINOR, &pDevExt->u32CrConDefaultClientID);
1102 if (!RT_SUCCESS(rc))
1103 {
1104 WARN(("VBoxMpCrCtlConConnect failed, rc %d", rc));
1105 return STATUS_UNSUCCESSFUL;
1106 }
1107 }
1108
1109 *pu32ClienID = pDevExt->u32CrConDefaultClientID;
1110 return STATUS_SUCCESS;
1111}
1112
1113static NTSTATUS vboxVdmaProcessVReg(PVBOXMP_DEVEXT pDevExt,
1114 VBOXMP_CRPACKER *pCrPacker,
1115 uint32_t u32CrConClientID,
1116 const VBOXWDDM_ALLOCATION *pSrcAlloc,
1117 const VBOXWDDM_ALLOCATION *pDstAlloc,
1118 const RECT *pSrcRect, const VBOXVDMAPIPE_RECTS *pDstRects)
1119{
1120 D3DDDI_VIDEO_PRESENT_SOURCE_ID srcId = pDstAlloc->AllocData.SurfDesc.VidPnSourceId;
1121 VBOXWDDM_SOURCE *pSource = &pDevExt->aSources[srcId];
1122 NTSTATUS Status = STATUS_SUCCESS;
1123
1124 if (pDevExt->fTexPresentEnabled)
1125 {
1126 /* we care only about screen regions */
1127 if (pDstAlloc != pSource->pPrimaryAllocation)
1128 {
1129 WARN(("non-primary allocation passed to vboxWddmSubmitBltCmd!"));
1130 return STATUS_NOT_SUPPORTED;
1131 }
1132
1133 uint32_t hostID = pSrcAlloc->AllocData.hostID;
1134 int rc;
1135 if (hostID)
1136 {
1137// Assert(pContext->enmType == VBOXWDDM_CONTEXT_TYPE_CUSTOM_3D);
1138 int32_t posX = pDstRects->ContextRect.left - pSrcRect->left;
1139 int32_t posY = pDstRects->ContextRect.top - pSrcRect->top;
1140
1141 Status = vboxVdmaTexPresentSubmit(pDevExt, pCrPacker, u32CrConClientID, hostID, srcId, posX, posY, pDstRects->UpdateRects.cRects, (const RTRECT*)pDstRects->UpdateRects.aRects);
1142 if (NT_SUCCESS(Status))
1143 {
1144 rc = VBoxVrListRectsSubst(&pSource->VrList, pDstRects->UpdateRects.cRects, (const RTRECT*)pDstRects->UpdateRects.aRects, NULL);
1145 if (RT_SUCCESS(rc))
1146 pSource->fHas3DVrs = TRUE;
1147 else
1148 WARN(("VBoxVrListRectsSubst failed rc %d, ignoring..", rc));
1149 }
1150 else
1151 WARN(("vboxVdmaTexPresentSubmit failed Status 0x%x", Status));
1152 }
1153 else if (pSource->pPrimaryAllocation == pDstAlloc)
1154 {
1155 bool fChanged = false;
1156 Assert(pSource->pPrimaryAllocation->bVisible);
1157 rc = VBoxVrListRectsAdd(&pSource->VrList, pDstRects->UpdateRects.cRects, (const RTRECT*)pDstRects->UpdateRects.aRects, &fChanged);
1158 if (RT_SUCCESS(rc))
1159 {
1160 if (fChanged)
1161 {
1162 Status = vboxVdmaTexPresentSubmit(pDevExt, pCrPacker, u32CrConClientID, hostID, srcId, 0, 0, pDstRects->UpdateRects.cRects, (const RTRECT*)pDstRects->UpdateRects.aRects);
1163 if (NT_SUCCESS(Status))
1164 {
1165 if (pSource->fHas3DVrs)
1166 {
1167 if (VBoxVrListRectsCount(&pSource->VrList) == 1)
1168 {
1169 RTRECT Rect;
1170 VBoxVrListRectsGet(&pSource->VrList, 1, &Rect);
1171 if (Rect.xLeft == 0
1172 && Rect.yTop == 0
1173 && Rect.xRight == pDstAlloc->AllocData.SurfDesc.width
1174 && Rect.yBottom == pDstAlloc->AllocData.SurfDesc.height)
1175 {
1176 pSource->fHas3DVrs = FALSE;
1177 }
1178 }
1179 }
1180 }
1181 else
1182 WARN(("vboxVdmaTexPresentSubmit failed Status 0x%x", Status));
1183 }
1184 }
1185 else
1186 WARN(("VBoxVrListRectsAdd failed rc %d, ignoring..", rc));
1187 }
1188 else
1189 {
1190 WARN(("unexpected"));
1191 Status = STATUS_INVALID_PARAMETER;
1192 }
1193 }
1194 else
1195 {
1196 PVBOXWDDM_SWAPCHAIN pSwapchain = vboxWddmSwapchainRetainByAlloc(pDevExt, pSrcAlloc);
1197
1198 if (pSwapchain)
1199 {
1200 Assert(pSrcAlloc->AllocData.SurfDesc.width == pSwapchain->width);
1201 Assert(pSrcAlloc->AllocData.SurfDesc.height == pSwapchain->height);
1202 }
1203
1204 Status = vboxVdmaProcessVRegCmdLegacy(pDevExt, pCrPacker, u32CrConClientID, pSource, pSwapchain, pSrcRect, pDstRects);
1205 if (!NT_SUCCESS(Status))
1206 WARN(("vboxVdmaProcessVRegCmdLegacy failed Status 0x%x", Status));
1207
1208 if (pSwapchain)
1209 vboxWddmSwapchainRelease(pSwapchain);
1210 }
1211
1212 return Status;
1213}
1214
1215NTSTATUS vboxVdmaTexPresentSetAlloc(PVBOXMP_DEVEXT pDevExt, PVBOXWDDM_ALLOCATION pRealFbAlloc)
1216{
1217 VBOXMP_CRPACKER CrPacker;
1218 VBoxMpCrPackerInit(&CrPacker);
1219 uint32_t u32CrConClientID;
1220
1221 NTSTATUS Status = vboxVdmaCrCtlGetDefaultClientId(pDevExt, &u32CrConClientID);
1222 if (!NT_SUCCESS(Status))
1223 {
1224 WARN(("vboxVdmaCrCtlGetDefaultClientId failed Status 0x%x", Status));
1225 return Status;
1226 }
1227
1228 RECT Rect;
1229 Rect.left = 0;
1230 Rect.top = 0;
1231 Rect.right = pRealFbAlloc->AllocData.SurfDesc.width;
1232 Rect.bottom = pRealFbAlloc->AllocData.SurfDesc.height;
1233
1234 VBOXVDMAPIPE_RECTS RectInfo;
1235 RectInfo.ContextRect = Rect;
1236 RectInfo.UpdateRects.cRects = 1;
1237 RectInfo.UpdateRects.aRects[0] = Rect;
1238
1239 return vboxVdmaProcessVReg(pDevExt, &CrPacker, u32CrConClientID,
1240 pRealFbAlloc, pRealFbAlloc,
1241 &Rect, &RectInfo);
1242}
1243
1244static NTSTATUS vboxVdmaProcessVRegCmd(PVBOXMP_DEVEXT pDevExt, VBOXWDDM_CONTEXT *pContext,
1245 const VBOXWDDM_DMA_ALLOCINFO *pSrcAllocInfo,
1246 const VBOXWDDM_DMA_ALLOCINFO *pDstAllocInfo,
1247 const RECT *pSrcRect, const VBOXVDMAPIPE_RECTS *pDstRects)
1248{
1249 return vboxVdmaProcessVReg(pDevExt, &pContext->CrPacker, pContext->u32CrConClientID,
1250 pSrcAllocInfo->pAlloc, pDstAllocInfo->pAlloc,
1251 pSrcRect, pDstRects);
1252}
1253
1254static void vboxVdmaBltDirtyRectsUpdate(PVBOXMP_DEVEXT pDevExt, VBOXWDDM_SOURCE *pSource, uint32_t cRects, const RECT *paRects)
1255{
1256 if (!cRects)
1257 {
1258 WARN(("vboxVdmaBltDirtyRectsUpdate: no rects specified"));
1259 return;
1260 }
1261
1262 RECT rect;
1263 rect = paRects[0];
1264 for (UINT i = 1; i < cRects; ++i)
1265 {
1266 vboxWddmRectUnited(&rect, &rect, &paRects[i]);
1267 }
1268
1269 uint32_t cUnlockedVBVADisabled = ASMAtomicReadU32(&pDevExt->cUnlockedVBVADisabled);
1270 if (!cUnlockedVBVADisabled)
1271 {
1272 VBOXVBVA_OP(ReportDirtyRect, pDevExt, pSource, &rect);
1273 }
1274 else
1275 {
1276 VBOXVBVA_OP_WITHLOCK_ATDPC(ReportDirtyRect, pDevExt, pSource, &rect);
1277 }
1278}
1279
1280NTSTATUS vboxVdmaProcessBltCmd(PVBOXMP_DEVEXT pDevExt, VBOXWDDM_CONTEXT *pContext, VBOXWDDM_DMA_PRIVATEDATA_BLT *pBlt)
1281{
1282 NTSTATUS Status = STATUS_SUCCESS;
1283 PVBOXWDDM_ALLOCATION pDstAlloc = pBlt->Blt.DstAlloc.pAlloc;
1284 PVBOXWDDM_ALLOCATION pSrcAlloc = pBlt->Blt.SrcAlloc.pAlloc;
1285 BOOLEAN fRenderFromSharedDisabled = pDevExt->fRenderToShadowDisabled;
1286 BOOLEAN fVRAMUpdated = FALSE;
1287
1288 if (!pDstAlloc->AllocData.hostID && !pSrcAlloc->AllocData.hostID)
1289 {
1290 /* the allocations contain a real data in VRAM, do blitting */
1291 vboxVdmaGgDmaBlt(pDevExt, &pBlt->Blt);
1292 fVRAMUpdated = TRUE;
1293 }
1294
1295 if (VBOXWDDM_IS_REAL_FB_ALLOCATION(pDevExt, pDstAlloc)
1296 && pDstAlloc->bVisible)
1297 {
1298 VBOXWDDM_SOURCE *pSource = &pDevExt->aSources[pDstAlloc->AllocData.SurfDesc.VidPnSourceId];
1299 Assert(pDstAlloc->AllocData.SurfDesc.VidPnSourceId < VBOX_VIDEO_MAX_SCREENS);
1300 Assert(pSource->pPrimaryAllocation == pDstAlloc);
1301
1302
1303 if (fVRAMUpdated)
1304 vboxVdmaBltDirtyRectsUpdate(pDevExt, pSource, pBlt->Blt.DstRects.UpdateRects.cRects, pBlt->Blt.DstRects.UpdateRects.aRects);
1305
1306 if (pSrcAlloc->AllocData.hostID || (pDevExt->fTexPresentEnabled ? pSource->fHas3DVrs : !!pDevExt->cContexts3D))
1307 {
1308 Status = vboxVdmaProcessVRegCmd(pDevExt, pContext, &pBlt->Blt.SrcAlloc, &pBlt->Blt.DstAlloc, &pBlt->Blt.SrcRect, &pBlt->Blt.DstRects);
1309 if (!NT_SUCCESS(Status))
1310 WARN(("vboxVdmaProcessVRegCmd failed Status 0x%x", Status));
1311 }
1312 }
1313
1314 return Status;
1315}
1316
1317NTSTATUS vboxVdmaProcessFlipCmd(PVBOXMP_DEVEXT pDevExt, VBOXWDDM_CONTEXT *pContext, VBOXWDDM_DMA_PRIVATEDATA_FLIP *pFlip)
1318{
1319 NTSTATUS Status = STATUS_SUCCESS;
1320 PVBOXWDDM_ALLOCATION pAlloc = pFlip->Flip.Alloc.pAlloc;
1321 VBOXWDDM_SOURCE *pSource = &pDevExt->aSources[pAlloc->AllocData.SurfDesc.VidPnSourceId];
1322 vboxWddmAssignPrimary(pDevExt, pSource, pAlloc, pAlloc->AllocData.SurfDesc.VidPnSourceId);
1323 if (pAlloc->AllocData.hostID)
1324 {
1325 RECT SrcRect;
1326 VBOXVDMAPIPE_RECTS Rects;
1327 SrcRect.left = 0;
1328 SrcRect.top = 0;
1329 SrcRect.right = pAlloc->AllocData.SurfDesc.width;
1330 SrcRect.bottom = pAlloc->AllocData.SurfDesc.height;
1331 Rects.ContextRect.left = 0;
1332 Rects.ContextRect.top = 0;
1333 Rects.ContextRect.right = pAlloc->AllocData.SurfDesc.width;
1334 Rects.ContextRect.bottom = pAlloc->AllocData.SurfDesc.height;
1335 Rects.UpdateRects.cRects = 1;
1336 Rects.UpdateRects.aRects[0] = Rects.ContextRect;
1337
1338 Status = vboxVdmaProcessVRegCmd(pDevExt, pContext, &pFlip->Flip.Alloc, &pFlip->Flip.Alloc, &SrcRect, &Rects);
1339 if (!NT_SUCCESS(Status))
1340 WARN(("vboxVdmaProcessVRegCmd failed Status 0x%x", Status));
1341 }
1342 else
1343 WARN(("unexpected flip request"));
1344
1345 return Status;
1346}
1347
1348NTSTATUS vboxVdmaProcessClrFillCmd(PVBOXMP_DEVEXT pDevExt, VBOXWDDM_CONTEXT *pContext, VBOXWDDM_DMA_PRIVATEDATA_CLRFILL *pCF)
1349{
1350 NTSTATUS Status = STATUS_SUCCESS;
1351 PVBOXWDDM_ALLOCATION pAlloc = pCF->ClrFill.Alloc.pAlloc;
1352
1353 if (!pAlloc->AllocData.hostID)
1354 {
1355 Status = vboxVdmaGgDmaColorFill(pDevExt, &pCF->ClrFill);
1356 if (!NT_SUCCESS(Status))
1357 WARN(("vboxVdmaGgDmaColorFill failed Status 0x%x", Status));
1358 }
1359 else
1360 WARN(("unexpected clrfill request"));
1361
1362 return Status;
1363}
1364
1365
1366#ifdef VBOX_WITH_VDMA
1367/*
1368 * This is currently used by VDMA. It is invisible for Vdma API clients since
1369 * Vdma transport may change if we choose to use another (e.g. more light-weight)
1370 * transport for DMA commands submission
1371 */
1372
1373#ifdef VBOXVDMA_WITH_VBVA
1374static int vboxWddmVdmaSubmitVbva(PVBOXMP_DEVEXT pDevExt, PVBOXVDMAINFO pInfo, HGSMIOFFSET offDr)
1375{
1376 int rc;
1377 if (vboxVbvaBufferBeginUpdate (pDevExt, &pDevExt->u.primary.Vbva))
1378 {
1379 rc = vboxVbvaReportCmdOffset(pDevExt, &pDevExt->u.primary.Vbva, offDr);
1380 vboxVbvaBufferEndUpdate (pDevExt, &pDevExt->u.primary.Vbva);
1381 }
1382 else
1383 {
1384 AssertBreakpoint();
1385 rc = VERR_INVALID_STATE;
1386 }
1387 return rc;
1388}
1389#define vboxWddmVdmaSubmit vboxWddmVdmaSubmitVbva
1390#else
1391static int vboxWddmVdmaSubmitHgsmi(PVBOXMP_DEVEXT pDevExt, PVBOXVDMAINFO pInfo, HGSMIOFFSET offDr)
1392{
1393 VBoxVideoCmnPortWriteUlong(VBoxCommonFromDeviceExt(pDevExt)->guestCtx.port, offDr);
1394 return VINF_SUCCESS;
1395}
1396#define vboxWddmVdmaSubmit vboxWddmVdmaSubmitHgsmi
1397#endif
1398
1399static int vboxVdmaInformHost(PVBOXMP_DEVEXT pDevExt, PVBOXVDMAINFO pInfo, VBOXVDMA_CTL_TYPE enmCtl)
1400{
1401 int rc = VINF_SUCCESS;
1402
1403 PVBOXVDMA_CTL pCmd = (PVBOXVDMA_CTL)VBoxSHGSMICommandAlloc(&VBoxCommonFromDeviceExt(pDevExt)->guestCtx.heapCtx, sizeof (VBOXVDMA_CTL), HGSMI_CH_VBVA, VBVA_VDMA_CTL);
1404 if (pCmd)
1405 {
1406 pCmd->enmCtl = enmCtl;
1407 pCmd->u32Offset = pInfo->CmdHeap.Heap.area.offBase;
1408 pCmd->i32Result = VERR_NOT_SUPPORTED;
1409
1410 const VBOXSHGSMIHEADER* pHdr = VBoxSHGSMICommandPrepSynch(&VBoxCommonFromDeviceExt(pDevExt)->guestCtx.heapCtx, pCmd);
1411 Assert(pHdr);
1412 if (pHdr)
1413 {
1414 do
1415 {
1416 HGSMIOFFSET offCmd = VBoxSHGSMICommandOffset(&VBoxCommonFromDeviceExt(pDevExt)->guestCtx.heapCtx, pHdr);
1417 Assert(offCmd != HGSMIOFFSET_VOID);
1418 if (offCmd != HGSMIOFFSET_VOID)
1419 {
1420 rc = vboxWddmVdmaSubmit(pDevExt, pInfo, offCmd);
1421 AssertRC(rc);
1422 if (RT_SUCCESS(rc))
1423 {
1424 rc = VBoxSHGSMICommandDoneSynch(&VBoxCommonFromDeviceExt(pDevExt)->guestCtx.heapCtx, pHdr);
1425 AssertRC(rc);
1426 if (RT_SUCCESS(rc))
1427 {
1428 rc = pCmd->i32Result;
1429 AssertRC(rc);
1430 }
1431 break;
1432 }
1433 }
1434 else
1435 rc = VERR_INVALID_PARAMETER;
1436 /* fail to submit, cancel it */
1437 VBoxSHGSMICommandCancelSynch(&VBoxCommonFromDeviceExt(pDevExt)->guestCtx.heapCtx, pHdr);
1438 } while (0);
1439 }
1440
1441 VBoxSHGSMICommandFree (&VBoxCommonFromDeviceExt(pDevExt)->guestCtx.heapCtx, pCmd);
1442 }
1443 else
1444 {
1445 LOGREL(("HGSMIHeapAlloc failed"));
1446 rc = VERR_OUT_OF_RESOURCES;
1447 }
1448
1449 return rc;
1450}
1451#endif
1452
1453static DECLCALLBACK(void *) hgsmiEnvAlloc(void *pvEnv, HGSMISIZE cb)
1454{
1455 NOREF(pvEnv);
1456 return RTMemAlloc(cb);
1457}
1458
1459static DECLCALLBACK(void) hgsmiEnvFree(void *pvEnv, void *pv)
1460{
1461 NOREF(pvEnv);
1462 RTMemFree(pv);
1463}
1464
1465static HGSMIENV g_hgsmiEnvVdma =
1466{
1467 NULL,
1468 hgsmiEnvAlloc,
1469 hgsmiEnvFree
1470};
1471
1472/* create a DMACommand buffer */
1473int vboxVdmaCreate(PVBOXMP_DEVEXT pDevExt, VBOXVDMAINFO *pInfo
1474#ifdef VBOX_WITH_VDMA
1475 , ULONG offBuffer, ULONG cbBuffer
1476#endif
1477 )
1478{
1479 int rc;
1480 pInfo->fEnabled = FALSE;
1481
1482#ifdef VBOX_WITH_VDMA
1483 Assert((offBuffer & 0xfff) == 0);
1484 Assert((cbBuffer & 0xfff) == 0);
1485 Assert(offBuffer);
1486 Assert(cbBuffer);
1487
1488 if((offBuffer & 0xfff)
1489 || (cbBuffer & 0xfff)
1490 || !offBuffer
1491 || !cbBuffer)
1492 {
1493 LOGREL(("invalid parameters: offBuffer(0x%x), cbBuffer(0x%x)", offBuffer, cbBuffer));
1494 return VERR_INVALID_PARAMETER;
1495 }
1496 PVOID pvBuffer;
1497
1498 rc = VBoxMPCmnMapAdapterMemory(VBoxCommonFromDeviceExt(pDevExt),
1499 &pvBuffer,
1500 offBuffer,
1501 cbBuffer);
1502 Assert(RT_SUCCESS(rc));
1503 if (RT_SUCCESS(rc))
1504 {
1505 /* Setup a HGSMI heap within the adapter information area. */
1506 rc = VBoxSHGSMIInit(&pInfo->CmdHeap,
1507 HGSMI_HEAP_TYPE_POINTER,
1508 pvBuffer,
1509 cbBuffer,
1510 offBuffer,
1511 &g_hgsmiEnvVdma);
1512 Assert(RT_SUCCESS(rc));
1513 if(RT_SUCCESS(rc))
1514#endif
1515 {
1516 return VINF_SUCCESS;
1517 }
1518#ifdef VBOX_WITH_VDMA
1519 else
1520 LOGREL(("HGSMIHeapSetup failed rc = 0x%x", rc));
1521
1522 VBoxMPCmnUnmapAdapterMemory(VBoxCommonFromDeviceExt(pDevExt), &pvBuffer);
1523 }
1524 else
1525 LOGREL(("VBoxMapAdapterMemory failed rc = 0x%x\n", rc));
1526#endif
1527 return rc;
1528}
1529
1530int vboxVdmaDisable (PVBOXMP_DEVEXT pDevExt, PVBOXVDMAINFO pInfo)
1531{
1532 Assert(pInfo->fEnabled);
1533 if (!pInfo->fEnabled)
1534 return VINF_ALREADY_INITIALIZED;
1535
1536 /* ensure nothing else is submitted */
1537 pInfo->fEnabled = FALSE;
1538#ifdef VBOX_WITH_VDMA
1539 int rc = vboxVdmaInformHost (pDevExt, pInfo, VBOXVDMA_CTL_TYPE_DISABLE);
1540 AssertRC(rc);
1541 return rc;
1542#else
1543 return VINF_SUCCESS;
1544#endif
1545}
1546
1547int vboxVdmaEnable (PVBOXMP_DEVEXT pDevExt, PVBOXVDMAINFO pInfo)
1548{
1549 Assert(!pInfo->fEnabled);
1550 if (pInfo->fEnabled)
1551 return VINF_ALREADY_INITIALIZED;
1552#ifdef VBOX_WITH_VDMA
1553 int rc = vboxVdmaInformHost (pDevExt, pInfo, VBOXVDMA_CTL_TYPE_ENABLE);
1554 Assert(RT_SUCCESS(rc));
1555 if (RT_SUCCESS(rc))
1556 pInfo->fEnabled = TRUE;
1557
1558 return rc;
1559#else
1560 return VINF_SUCCESS;
1561#endif
1562}
1563
1564#ifdef VBOX_WITH_VDMA
1565int vboxVdmaFlush (PVBOXMP_DEVEXT pDevExt, PVBOXVDMAINFO pInfo)
1566{
1567 Assert(pInfo->fEnabled);
1568 if (!pInfo->fEnabled)
1569 return VINF_ALREADY_INITIALIZED;
1570
1571 int rc = vboxVdmaInformHost (pDevExt, pInfo, VBOXVDMA_CTL_TYPE_FLUSH);
1572 Assert(RT_SUCCESS(rc));
1573
1574 return rc;
1575}
1576#endif
1577
1578int vboxVdmaDestroy (PVBOXMP_DEVEXT pDevExt, PVBOXVDMAINFO pInfo)
1579{
1580 int rc = VINF_SUCCESS;
1581 Assert(!pInfo->fEnabled);
1582 if (pInfo->fEnabled)
1583 rc = vboxVdmaDisable (pDevExt, pInfo);
1584#ifdef VBOX_WITH_VDMA
1585 VBoxSHGSMITerm(&pInfo->CmdHeap);
1586 VBoxMPCmnUnmapAdapterMemory(VBoxCommonFromDeviceExt(pDevExt), (void**)&pInfo->CmdHeap.Heap.area.pu8Base);
1587#endif
1588 return rc;
1589}
1590
1591#ifdef VBOX_WITH_VDMA
1592void vboxVdmaCBufDrFree (PVBOXVDMAINFO pInfo, PVBOXVDMACBUF_DR pDr)
1593{
1594 VBoxSHGSMICommandFree (&pInfo->CmdHeap, pDr);
1595}
1596
1597PVBOXVDMACBUF_DR vboxVdmaCBufDrCreate (PVBOXVDMAINFO pInfo, uint32_t cbTrailingData)
1598{
1599 uint32_t cbDr = VBOXVDMACBUF_DR_SIZE(cbTrailingData);
1600 PVBOXVDMACBUF_DR pDr = (PVBOXVDMACBUF_DR)VBoxSHGSMICommandAlloc (&pInfo->CmdHeap, cbDr, HGSMI_CH_VBVA, VBVA_VDMA_CMD);
1601 Assert(pDr);
1602 if (pDr)
1603 memset (pDr, 0, cbDr);
1604 else
1605 LOGREL(("VBoxSHGSMICommandAlloc returned NULL"));
1606
1607 return pDr;
1608}
1609
1610static DECLCALLBACK(void) vboxVdmaCBufDrCompletion(PVBOXSHGSMI pHeap, void *pvCmd, void *pvContext)
1611{
1612 PVBOXMP_DEVEXT pDevExt = (PVBOXMP_DEVEXT)pvContext;
1613 PVBOXVDMAINFO pInfo = &pDevExt->u.primary.Vdma;
1614
1615 vboxVdmaCBufDrFree (pInfo, (PVBOXVDMACBUF_DR)pvCmd);
1616}
1617
1618static DECLCALLBACK(void) vboxVdmaCBufDrCompletionIrq(PVBOXSHGSMI pHeap, void *pvCmd, void *pvContext,
1619 PFNVBOXSHGSMICMDCOMPLETION *ppfnCompletion, void **ppvCompletion)
1620{
1621 PVBOXMP_DEVEXT pDevExt = (PVBOXMP_DEVEXT)pvContext;
1622 PVBOXVDMAINFO pVdma = &pDevExt->u.primary.Vdma;
1623 PVBOXVDMACBUF_DR pDr = (PVBOXVDMACBUF_DR)pvCmd;
1624
1625 DXGK_INTERRUPT_TYPE enmComplType;
1626
1627 if (RT_SUCCESS(pDr->rc))
1628 {
1629 enmComplType = DXGK_INTERRUPT_DMA_COMPLETED;
1630 }
1631 else if (pDr->rc == VERR_INTERRUPTED)
1632 {
1633 Assert(0);
1634 enmComplType = DXGK_INTERRUPT_DMA_PREEMPTED;
1635 }
1636 else
1637 {
1638 Assert(0);
1639 enmComplType = DXGK_INTERRUPT_DMA_FAULTED;
1640 }
1641
1642 if (vboxVdmaDdiCmdCompletedIrq(pDevExt, VBOXVDMADDI_CMD_FROM_BUF_DR(pDr), enmComplType))
1643 {
1644 pDevExt->bNotifyDxDpc = TRUE;
1645 }
1646
1647 /* inform SHGSMI we DO NOT want to be called at DPC later */
1648 *ppfnCompletion = NULL;
1649// *ppvCompletion = pvContext;
1650}
1651
1652int vboxVdmaCBufDrSubmit(PVBOXMP_DEVEXT pDevExt, PVBOXVDMAINFO pInfo, PVBOXVDMACBUF_DR pDr)
1653{
1654 const VBOXSHGSMIHEADER* pHdr = VBoxSHGSMICommandPrepAsynchIrq (&pInfo->CmdHeap, pDr, vboxVdmaCBufDrCompletionIrq, pDevExt, VBOXSHGSMI_FLAG_GH_ASYNCH_FORCE);
1655 Assert(pHdr);
1656 int rc = VERR_GENERAL_FAILURE;
1657 if (pHdr)
1658 {
1659 do
1660 {
1661 HGSMIOFFSET offCmd = VBoxSHGSMICommandOffset(&pInfo->CmdHeap, pHdr);
1662 Assert(offCmd != HGSMIOFFSET_VOID);
1663 if (offCmd != HGSMIOFFSET_VOID)
1664 {
1665 rc = vboxWddmVdmaSubmit(pDevExt, pInfo, offCmd);
1666 AssertRC(rc);
1667 if (RT_SUCCESS(rc))
1668 {
1669 VBoxSHGSMICommandDoneAsynch(&pInfo->CmdHeap, pHdr);
1670 AssertRC(rc);
1671 break;
1672 }
1673 }
1674 else
1675 rc = VERR_INVALID_PARAMETER;
1676 /* fail to submit, cancel it */
1677 VBoxSHGSMICommandCancelAsynch(&pInfo->CmdHeap, pHdr);
1678 } while (0);
1679 }
1680 else
1681 rc = VERR_INVALID_PARAMETER;
1682 return rc;
1683}
1684
1685int vboxVdmaCBufDrSubmitSynch(PVBOXMP_DEVEXT pDevExt, PVBOXVDMAINFO pInfo, PVBOXVDMACBUF_DR pDr)
1686{
1687 const VBOXSHGSMIHEADER* pHdr = VBoxSHGSMICommandPrepAsynch (&pInfo->CmdHeap, pDr, NULL, NULL, VBOXSHGSMI_FLAG_GH_SYNCH);
1688 Assert(pHdr);
1689 int rc = VERR_GENERAL_FAILURE;
1690 if (pHdr)
1691 {
1692 do
1693 {
1694 HGSMIOFFSET offCmd = VBoxSHGSMICommandOffset(&pInfo->CmdHeap, pHdr);
1695 Assert(offCmd != HGSMIOFFSET_VOID);
1696 if (offCmd != HGSMIOFFSET_VOID)
1697 {
1698 rc = vboxWddmVdmaSubmit(pDevExt, pInfo, offCmd);
1699 AssertRC(rc);
1700 if (RT_SUCCESS(rc))
1701 {
1702 VBoxSHGSMICommandDoneAsynch(&pInfo->CmdHeap, pHdr);
1703 AssertRC(rc);
1704 break;
1705 }
1706 }
1707 else
1708 rc = VERR_INVALID_PARAMETER;
1709 /* fail to submit, cancel it */
1710 VBoxSHGSMICommandCancelAsynch(&pInfo->CmdHeap, pHdr);
1711 } while (0);
1712 }
1713 else
1714 rc = VERR_INVALID_PARAMETER;
1715 return rc;
1716}
1717#endif
1718
1719
1720/* ddi dma command queue */
1721
1722VOID vboxVdmaDdiCmdGetCompletedListIsr(PVBOXMP_DEVEXT pDevExt, LIST_ENTRY *pList)
1723{
1724 vboxVideoLeDetach(&pDevExt->DpcCmdQueue, pList);
1725}
1726
1727BOOLEAN vboxVdmaDdiCmdIsCompletedListEmptyIsr(PVBOXMP_DEVEXT pDevExt)
1728{
1729 return IsListEmpty(&pDevExt->DpcCmdQueue);
1730}
1731
1732DECLINLINE(BOOLEAN) vboxVdmaDdiCmdCanComplete(PVBOXMP_DEVEXT pDevExt, UINT u32NodeOrdinal)
1733{
1734 PVBOXVDMADDI_CMD_QUEUE pQueue = &pDevExt->aNodes[u32NodeOrdinal].CmdQueue;
1735 return ASMAtomicUoReadU32(&pQueue->cQueuedCmds) == 0;
1736}
1737
1738DECLCALLBACK(VOID) vboxVdmaDdiCmdCompletionCbFree(PVBOXMP_DEVEXT pDevExt, PVBOXVDMADDI_CMD pCmd, PVOID pvContext)
1739{
1740 vboxWddmMemFree(pCmd);
1741}
1742
1743static VOID vboxVdmaDdiCmdNotifyCompletedIrq(PVBOXMP_DEVEXT pDevExt, UINT u32NodeOrdinal, UINT u32FenceId, DXGK_INTERRUPT_TYPE enmComplType)
1744{
1745 PVBOXVDMADDI_NODE pNode = &pDevExt->aNodes[u32NodeOrdinal];
1746 DXGKARGCB_NOTIFY_INTERRUPT_DATA notify;
1747 memset(&notify, 0, sizeof(DXGKARGCB_NOTIFY_INTERRUPT_DATA));
1748 switch (enmComplType)
1749 {
1750 case DXGK_INTERRUPT_DMA_COMPLETED:
1751 notify.InterruptType = DXGK_INTERRUPT_DMA_COMPLETED;
1752 notify.DmaCompleted.SubmissionFenceId = u32FenceId;
1753 notify.DmaCompleted.NodeOrdinal = u32NodeOrdinal;
1754 pNode->uLastCompletedFenceId = u32FenceId;
1755 break;
1756
1757 case DXGK_INTERRUPT_DMA_PREEMPTED:
1758 Assert(0);
1759 notify.InterruptType = DXGK_INTERRUPT_DMA_PREEMPTED;
1760 notify.DmaPreempted.PreemptionFenceId = u32FenceId;
1761 notify.DmaPreempted.NodeOrdinal = u32NodeOrdinal;
1762 notify.DmaPreempted.LastCompletedFenceId = pNode->uLastCompletedFenceId;
1763 break;
1764
1765 case DXGK_INTERRUPT_DMA_FAULTED:
1766 Assert(0);
1767 notify.InterruptType = DXGK_INTERRUPT_DMA_FAULTED;
1768 notify.DmaFaulted.FaultedFenceId = u32FenceId;
1769 notify.DmaFaulted.Status = STATUS_UNSUCCESSFUL; /* @todo: better status ? */
1770 notify.DmaFaulted.NodeOrdinal = u32NodeOrdinal;
1771 break;
1772
1773 default:
1774 Assert(0);
1775 break;
1776 }
1777
1778 pDevExt->u.primary.DxgkInterface.DxgkCbNotifyInterrupt(pDevExt->u.primary.DxgkInterface.DeviceHandle, &notify);
1779}
1780
1781static VOID vboxVdmaDdiCmdProcessCompletedIrq(PVBOXMP_DEVEXT pDevExt, PVBOXVDMADDI_CMD pCmd, DXGK_INTERRUPT_TYPE enmComplType)
1782{
1783 vboxVdmaDdiCmdNotifyCompletedIrq(pDevExt, pCmd->u32NodeOrdinal, pCmd->u32FenceId, enmComplType);
1784 switch (enmComplType)
1785 {
1786 case DXGK_INTERRUPT_DMA_COMPLETED:
1787 InsertTailList(&pDevExt->DpcCmdQueue, &pCmd->QueueEntry);
1788 break;
1789 default:
1790 AssertFailed();
1791 break;
1792 }
1793}
1794
1795DECLINLINE(VOID) vboxVdmaDdiCmdDequeueIrq(PVBOXMP_DEVEXT pDevExt, PVBOXVDMADDI_CMD pCmd)
1796{
1797 PVBOXVDMADDI_CMD_QUEUE pQueue = &pDevExt->aNodes[pCmd->u32NodeOrdinal].CmdQueue;
1798 ASMAtomicDecU32(&pQueue->cQueuedCmds);
1799 RemoveEntryList(&pCmd->QueueEntry);
1800}
1801
1802DECLINLINE(VOID) vboxVdmaDdiCmdEnqueueIrq(PVBOXMP_DEVEXT pDevExt, PVBOXVDMADDI_CMD pCmd)
1803{
1804 PVBOXVDMADDI_CMD_QUEUE pQueue = &pDevExt->aNodes[pCmd->u32NodeOrdinal].CmdQueue;
1805 ASMAtomicIncU32(&pQueue->cQueuedCmds);
1806 InsertTailList(&pQueue->CmdQueue, &pCmd->QueueEntry);
1807}
1808
1809VOID vboxVdmaDdiNodesInit(PVBOXMP_DEVEXT pDevExt)
1810{
1811 for (UINT i = 0; i < RT_ELEMENTS(pDevExt->aNodes); ++i)
1812 {
1813 pDevExt->aNodes[i].uLastCompletedFenceId = 0;
1814 PVBOXVDMADDI_CMD_QUEUE pQueue = &pDevExt->aNodes[i].CmdQueue;
1815 pQueue->cQueuedCmds = 0;
1816 InitializeListHead(&pQueue->CmdQueue);
1817 }
1818 InitializeListHead(&pDevExt->DpcCmdQueue);
1819}
1820
1821BOOLEAN vboxVdmaDdiCmdCompletedIrq(PVBOXMP_DEVEXT pDevExt, PVBOXVDMADDI_CMD pCmd, DXGK_INTERRUPT_TYPE enmComplType)
1822{
1823 if (VBOXVDMADDI_STATE_NOT_DX_CMD == pCmd->enmState)
1824 {
1825 InsertTailList(&pDevExt->DpcCmdQueue, &pCmd->QueueEntry);
1826 return FALSE;
1827 }
1828
1829 PVBOXVDMADDI_CMD_QUEUE pQueue = &pDevExt->aNodes[pCmd->u32NodeOrdinal].CmdQueue;
1830 BOOLEAN bQueued = pCmd->enmState > VBOXVDMADDI_STATE_NOT_QUEUED;
1831 BOOLEAN bComplete = FALSE;
1832 Assert(!bQueued || pQueue->cQueuedCmds);
1833 Assert(!bQueued || !IsListEmpty(&pQueue->CmdQueue));
1834 pCmd->enmState = VBOXVDMADDI_STATE_COMPLETED;
1835 if (bQueued)
1836 {
1837 if (pQueue->CmdQueue.Flink == &pCmd->QueueEntry)
1838 {
1839 vboxVdmaDdiCmdDequeueIrq(pDevExt, pCmd);
1840 bComplete = TRUE;
1841 }
1842 }
1843 else if (IsListEmpty(&pQueue->CmdQueue))
1844 {
1845 bComplete = TRUE;
1846 }
1847 else
1848 {
1849 vboxVdmaDdiCmdEnqueueIrq(pDevExt, pCmd);
1850 }
1851
1852 if (bComplete)
1853 {
1854 vboxVdmaDdiCmdProcessCompletedIrq(pDevExt, pCmd, enmComplType);
1855
1856 while (!IsListEmpty(&pQueue->CmdQueue))
1857 {
1858 pCmd = VBOXVDMADDI_CMD_FROM_ENTRY(pQueue->CmdQueue.Flink);
1859 if (pCmd->enmState == VBOXVDMADDI_STATE_COMPLETED)
1860 {
1861 vboxVdmaDdiCmdDequeueIrq(pDevExt, pCmd);
1862 vboxVdmaDdiCmdProcessCompletedIrq(pDevExt, pCmd, pCmd->enmComplType);
1863 }
1864 else
1865 break;
1866 }
1867 }
1868 else
1869 {
1870 pCmd->enmState = VBOXVDMADDI_STATE_COMPLETED;
1871 pCmd->enmComplType = enmComplType;
1872 }
1873
1874 return bComplete;
1875}
1876
1877VOID vboxVdmaDdiCmdSubmittedIrq(PVBOXMP_DEVEXT pDevExt, PVBOXVDMADDI_CMD pCmd)
1878{
1879 BOOLEAN bQueued = pCmd->enmState >= VBOXVDMADDI_STATE_PENDING;
1880 Assert(pCmd->enmState < VBOXVDMADDI_STATE_SUBMITTED);
1881 pCmd->enmState = VBOXVDMADDI_STATE_SUBMITTED;
1882 if (!bQueued)
1883 vboxVdmaDdiCmdEnqueueIrq(pDevExt, pCmd);
1884}
1885
1886typedef struct VBOXVDMADDI_CMD_COMPLETED_CB
1887{
1888 PVBOXMP_DEVEXT pDevExt;
1889 PVBOXVDMADDI_CMD pCmd;
1890 DXGK_INTERRUPT_TYPE enmComplType;
1891} VBOXVDMADDI_CMD_COMPLETED_CB, *PVBOXVDMADDI_CMD_COMPLETED_CB;
1892
1893static BOOLEAN vboxVdmaDdiCmdCompletedCb(PVOID Context)
1894{
1895 PVBOXVDMADDI_CMD_COMPLETED_CB pdc = (PVBOXVDMADDI_CMD_COMPLETED_CB)Context;
1896 PVBOXMP_DEVEXT pDevExt = pdc->pDevExt;
1897 BOOLEAN bNeedDpc = vboxVdmaDdiCmdCompletedIrq(pDevExt, pdc->pCmd, pdc->enmComplType);
1898 pDevExt->bNotifyDxDpc |= bNeedDpc;
1899
1900 if (bNeedDpc)
1901 {
1902 pDevExt->u.primary.DxgkInterface.DxgkCbQueueDpc(pDevExt->u.primary.DxgkInterface.DeviceHandle);
1903 }
1904
1905 return bNeedDpc;
1906}
1907
1908NTSTATUS vboxVdmaDdiCmdCompleted(PVBOXMP_DEVEXT pDevExt, PVBOXVDMADDI_CMD pCmd, DXGK_INTERRUPT_TYPE enmComplType)
1909{
1910 VBOXVDMADDI_CMD_COMPLETED_CB context;
1911 context.pDevExt = pDevExt;
1912 context.pCmd = pCmd;
1913 context.enmComplType = enmComplType;
1914 BOOLEAN bNeedDps;
1915 NTSTATUS Status = pDevExt->u.primary.DxgkInterface.DxgkCbSynchronizeExecution(
1916 pDevExt->u.primary.DxgkInterface.DeviceHandle,
1917 vboxVdmaDdiCmdCompletedCb,
1918 &context,
1919 0, /* IN ULONG MessageNumber */
1920 &bNeedDps);
1921 Assert(Status == STATUS_SUCCESS);
1922 return Status;
1923}
1924
1925typedef struct VBOXVDMADDI_CMD_SUBMITTED_CB
1926{
1927 PVBOXMP_DEVEXT pDevExt;
1928 PVBOXVDMADDI_CMD pCmd;
1929} VBOXVDMADDI_CMD_SUBMITTED_CB, *PVBOXVDMADDI_CMD_SUBMITTED_CB;
1930
1931static BOOLEAN vboxVdmaDdiCmdSubmittedCb(PVOID Context)
1932{
1933 PVBOXVDMADDI_CMD_SUBMITTED_CB pdc = (PVBOXVDMADDI_CMD_SUBMITTED_CB)Context;
1934 vboxVdmaDdiCmdSubmittedIrq(pdc->pDevExt, pdc->pCmd);
1935
1936 return FALSE;
1937}
1938
1939NTSTATUS vboxVdmaDdiCmdSubmitted(PVBOXMP_DEVEXT pDevExt, PVBOXVDMADDI_CMD pCmd)
1940{
1941 VBOXVDMADDI_CMD_SUBMITTED_CB context;
1942 context.pDevExt = pDevExt;
1943 context.pCmd = pCmd;
1944 BOOLEAN bRc;
1945 NTSTATUS Status = pDevExt->u.primary.DxgkInterface.DxgkCbSynchronizeExecution(
1946 pDevExt->u.primary.DxgkInterface.DeviceHandle,
1947 vboxVdmaDdiCmdSubmittedCb,
1948 &context,
1949 0, /* IN ULONG MessageNumber */
1950 &bRc);
1951 Assert(Status == STATUS_SUCCESS);
1952 return Status;
1953}
1954
1955typedef struct VBOXVDMADDI_CMD_COMPLETE_CB
1956{
1957 PVBOXMP_DEVEXT pDevExt;
1958 UINT u32NodeOrdinal;
1959 uint32_t u32FenceId;
1960} VBOXVDMADDI_CMD_COMPLETE_CB, *PVBOXVDMADDI_CMD_COMPLETE_CB;
1961
1962static BOOLEAN vboxVdmaDdiCmdFenceCompleteCb(PVOID Context)
1963{
1964 PVBOXVDMADDI_CMD_COMPLETE_CB pdc = (PVBOXVDMADDI_CMD_COMPLETE_CB)Context;
1965 PVBOXMP_DEVEXT pDevExt = pdc->pDevExt;
1966
1967 vboxVdmaDdiCmdNotifyCompletedIrq(pDevExt, pdc->u32NodeOrdinal, pdc->u32FenceId, DXGK_INTERRUPT_DMA_COMPLETED);
1968
1969 pDevExt->bNotifyDxDpc = TRUE;
1970 pDevExt->u.primary.DxgkInterface.DxgkCbQueueDpc(pDevExt->u.primary.DxgkInterface.DeviceHandle);
1971
1972 return TRUE;
1973}
1974
1975static NTSTATUS vboxVdmaDdiCmdFenceNotifyComplete(PVBOXMP_DEVEXT pDevExt, uint32_t u32NodeOrdinal, uint32_t u32FenceId)
1976{
1977 VBOXVDMADDI_CMD_COMPLETE_CB context;
1978 context.pDevExt = pDevExt;
1979 context.u32NodeOrdinal = u32NodeOrdinal;
1980 context.u32FenceId = u32FenceId;
1981 BOOLEAN bRet;
1982 NTSTATUS Status = pDevExt->u.primary.DxgkInterface.DxgkCbSynchronizeExecution(
1983 pDevExt->u.primary.DxgkInterface.DeviceHandle,
1984 vboxVdmaDdiCmdFenceCompleteCb,
1985 &context,
1986 0, /* IN ULONG MessageNumber */
1987 &bRet);
1988 Assert(Status == STATUS_SUCCESS);
1989 return Status;
1990}
1991
1992NTSTATUS vboxVdmaDdiCmdFenceComplete(PVBOXMP_DEVEXT pDevExt, uint32_t u32NodeOrdinal, uint32_t u32FenceId, DXGK_INTERRUPT_TYPE enmComplType)
1993{
1994 if (vboxVdmaDdiCmdCanComplete(pDevExt, u32NodeOrdinal))
1995 return vboxVdmaDdiCmdFenceNotifyComplete(pDevExt, u32NodeOrdinal, u32FenceId);
1996
1997 PVBOXVDMADDI_CMD pCmd = (PVBOXVDMADDI_CMD)vboxWddmMemAlloc(sizeof (VBOXVDMADDI_CMD));
1998 Assert(pCmd);
1999 if (pCmd)
2000 {
2001 vboxVdmaDdiCmdInit(pCmd, u32NodeOrdinal, u32FenceId, vboxVdmaDdiCmdCompletionCbFree, NULL);
2002 NTSTATUS Status = vboxVdmaDdiCmdCompleted(pDevExt, pCmd, enmComplType);
2003 Assert(Status == STATUS_SUCCESS);
2004 if (Status == STATUS_SUCCESS)
2005 return STATUS_SUCCESS;
2006 vboxWddmMemFree(pCmd);
2007 return Status;
2008 }
2009 return STATUS_NO_MEMORY;
2010}
2011
2012#ifdef VBOXWDDM_RENDER_FROM_SHADOW
2013NTSTATUS vboxVdmaHlpUpdatePrimary(PVBOXMP_DEVEXT pDevExt, D3DDDI_VIDEO_PRESENT_SOURCE_ID VidPnSourceId, RECT* pRect)
2014{
2015 PVBOXWDDM_SOURCE pSource = &pDevExt->aSources[VidPnSourceId];
2016 Assert(pSource->pPrimaryAllocation);
2017 Assert(pSource->pShadowAllocation);
2018 if (!pSource->pPrimaryAllocation)
2019 return STATUS_INVALID_PARAMETER;
2020 if (!pSource->pShadowAllocation)
2021 return STATUS_INVALID_PARAMETER;
2022
2023 Assert(pSource->pPrimaryAllocation->AllocData.Addr.offVram != VBOXVIDEOOFFSET_VOID);
2024 Assert(pSource->pShadowAllocation->AllocData.Addr.offVram != VBOXVIDEOOFFSET_VOID);
2025 if (pSource->pPrimaryAllocation->AllocData.Addr.offVram == VBOXVIDEOOFFSET_VOID)
2026 return STATUS_INVALID_PARAMETER;
2027 if (pSource->pShadowAllocation->AllocData.Addr.offVram == VBOXVIDEOOFFSET_VOID)
2028 return STATUS_INVALID_PARAMETER;
2029
2030 NTSTATUS Status = vboxVdmaGgDmaBltPerform(pDevExt, &pSource->pShadowAllocation->AllocData, pRect, &pSource->pPrimaryAllocation->AllocData, pRect);
2031 Assert(Status == STATUS_SUCCESS);
2032 return Status;
2033}
2034#endif
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