VirtualBox

source: vbox/trunk/src/VBox/Devices/Graphics/DevVGA_VDMA.cpp@ 33187

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

wddm/3d: chromium hgsmi fixes

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 34.2 KB
Line 
1/** @file
2 * Video DMA (VDMA) support.
3 */
4
5/*
6 * Copyright (C) 2006-2009 Oracle Corporation
7 *
8 * This file is part of VirtualBox Open Source Edition (OSE), as
9 * available from http://www.virtualbox.org. This file is free software;
10 * you can redistribute it and/or modify it under the terms of the GNU
11 * General Public License (GPL) as published by the Free Software
12 * Foundation, in version 2 as it comes in the "COPYING" file of the
13 * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
14 * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
15 */
16//#include <VBox/VMMDev.h>
17#include <VBox/pdmdev.h>
18#include <VBox/VBoxVideo.h>
19#include <iprt/semaphore.h>
20#include <iprt/thread.h>
21#include <iprt/mem.h>
22#include <iprt/asm.h>
23
24#include "DevVGA.h"
25#include "HGSMI/SHGSMIHost.h"
26#include "HGSMI/HGSMIHostHlp.h"
27
28typedef enum
29{
30 VBOXVDMAPIPE_STATE_CLOSED = 0,
31 VBOXVDMAPIPE_STATE_CREATED = 1,
32 VBOXVDMAPIPE_STATE_OPENNED = 2,
33 VBOXVDMAPIPE_STATE_CLOSING = 3
34} VBOXVDMAPIPE_STATE;
35
36typedef struct VBOXVDMAPIPE
37{
38 RTSEMEVENT hEvent;
39 /* critical section for accessing pipe properties */
40 RTCRITSECT hCritSect;
41 VBOXVDMAPIPE_STATE enmState;
42 /* true iff the other end needs Event notification */
43 bool bNeedNotify;
44} VBOXVDMAPIPE, *PVBOXVDMAPIPE;
45
46typedef enum
47{
48 VBOXVDMAPIPE_CMD_TYPE_UNDEFINED = 0,
49 VBOXVDMAPIPE_CMD_TYPE_DMACMD = 1,
50 VBOXVDMAPIPE_CMD_TYPE_DMACTL = 2
51} VBOXVDMAPIPE_CMD_TYPE;
52
53typedef struct VBOXVDMAPIPE_CMD_BODY
54{
55 VBOXVDMAPIPE_CMD_TYPE enmType;
56 union
57 {
58 PVBOXVDMACBUF_DR pDr;
59 PVBOXVDMA_CTL pCtl;
60 void *pvCmd;
61 } u;
62}VBOXVDMAPIPE_CMD_BODY, *PVBOXVDMAPIPE_CMD_BODY;
63
64typedef struct VBOXVDMAPIPE_CMD
65{
66 HGSMILISTENTRY Entry;
67 VBOXVDMAPIPE_CMD_BODY Cmd;
68} VBOXVDMAPIPE_CMD, *PVBOXVDMAPIPE_CMD;
69
70#define VBOXVDMAPIPE_CMD_FROM_ENTRY(_pE) ( (PVBOXVDMAPIPE_CMD)((uint8_t *)(_pE) - RT_OFFSETOF(VBOXVDMAPIPE_CMD, Entry)) )
71
72typedef struct VBOXVDMAPIPE_CMD_POOL
73{
74 HGSMILIST List;
75 uint32_t cCmds;
76 VBOXVDMAPIPE_CMD aCmds[1];
77} VBOXVDMAPIPE_CMD_POOL, *PVBOXVDMAPIPE_CMD_POOL;
78
79typedef struct VBOXVDMAHOST
80{
81 VBOXVDMAPIPE Pipe;
82 HGSMILIST PendingList;
83 RTTHREAD hWorkerThread;
84 PHGSMIINSTANCE pHgsmi;
85 PVGASTATE pVGAState;
86 bool bEnabled;
87 VBOXVDMAPIPE_CMD_POOL CmdPool;
88} VBOXVDMAHOST, *PVBOXVDMAHOST;
89
90
91#ifdef VBOX_WITH_CRHGSMI
92
93typedef DECLCALLBACK(void) FNVBOXVDMACRCTL_CALLBACK(PVGASTATE pVGAState, PVBOXVDMACMD_CHROMIUM_CTL pCmd, void* pvContext);
94typedef FNVBOXVDMACRCTL_CALLBACK *PFNVBOXVDMACRCTL_CALLBACK;
95
96typedef struct VBOXVDMACMD_CHROMIUM_CTL_PRIVATE
97{
98 uint32_t cRefs;
99 uint32_t rc;
100 PFNVBOXVDMACRCTL_CALLBACK pfnCompletion;
101 void *pvCompletion;
102 VBOXVDMACMD_CHROMIUM_CTL Cmd;
103} VBOXVDMACMD_CHROMIUM_CTL_PRIVATE, *PVBOXVDMACMD_CHROMIUM_CTL_PRIVATE;
104
105#define VBOXVDMACMD_CHROMIUM_CTL_PRIVATE_FROM_CTL(_p) ((PVBOXVDMACMD_CHROMIUM_CTL_PRIVATE)(((uint8_t*)(_p)) - RT_OFFSETOF(VBOXVDMACMD_CHROMIUM_CTL_PRIVATE, Cmd)))
106
107static PVBOXVDMACMD_CHROMIUM_CTL vboxVDMACrCtlCreate(VBOXVDMACMD_CHROMIUM_CTL_TYPE enmCmd, uint32_t cbCmd)
108{
109 PVBOXVDMACMD_CHROMIUM_CTL_PRIVATE pHdr = (PVBOXVDMACMD_CHROMIUM_CTL_PRIVATE)RTMemAllocZ(cbCmd + RT_OFFSETOF(VBOXVDMACMD_CHROMIUM_CTL_PRIVATE, Cmd));
110 Assert(pHdr);
111 if (pHdr)
112 {
113 pHdr->cRefs = 1;
114 pHdr->rc = VERR_NOT_IMPLEMENTED;
115 pHdr->Cmd.enmType = enmCmd;
116 pHdr->Cmd.cbCmd = cbCmd;
117 return &pHdr->Cmd;
118 }
119
120 return NULL;
121}
122
123DECLINLINE(void) vboxVDMACrCtlRelease (PVBOXVDMACMD_CHROMIUM_CTL pCmd)
124{
125 PVBOXVDMACMD_CHROMIUM_CTL_PRIVATE pHdr = VBOXVDMACMD_CHROMIUM_CTL_PRIVATE_FROM_CTL(pCmd);
126 uint32_t cRefs = ASMAtomicDecU32(&pHdr->cRefs);
127 if(!cRefs)
128 {
129 RTMemFree(pHdr);
130 }
131}
132
133DECLINLINE(void) vboxVDMACrCtlRetain (PVBOXVDMACMD_CHROMIUM_CTL pCmd)
134{
135 PVBOXVDMACMD_CHROMIUM_CTL_PRIVATE pHdr = VBOXVDMACMD_CHROMIUM_CTL_PRIVATE_FROM_CTL(pCmd);
136 ASMAtomicIncU32(&pHdr->cRefs);
137}
138
139DECLINLINE(int) vboxVDMACrCtlGetRc (PVBOXVDMACMD_CHROMIUM_CTL pCmd)
140{
141 PVBOXVDMACMD_CHROMIUM_CTL_PRIVATE pHdr = VBOXVDMACMD_CHROMIUM_CTL_PRIVATE_FROM_CTL(pCmd);
142 return pHdr->rc;
143}
144
145static DECLCALLBACK(void) vboxVDMACrCtlCbSetEvent(PVGASTATE pVGAState, PVBOXVDMACMD_CHROMIUM_CTL pCmd, void* pvContext)
146{
147 RTSemEventSignal((RTSEMEVENT)pvContext);
148}
149
150static DECLCALLBACK(void) vboxVDMACrCtlCbReleaseCmd(PVGASTATE pVGAState, PVBOXVDMACMD_CHROMIUM_CTL pCmd, void* pvContext)
151{
152 vboxVDMACrCtlRelease(pCmd);
153}
154
155
156static int vboxVDMACrCtlPostAsync (PVGASTATE pVGAState, PVBOXVDMACMD_CHROMIUM_CTL pCmd, PFNVBOXVDMACRCTL_CALLBACK pfnCompletion, void *pvCompletion)
157{
158 if (pVGAState->pDrv->pfnCrHgsmiControlProcess)
159 {
160 PVBOXVDMACMD_CHROMIUM_CTL_PRIVATE pHdr = VBOXVDMACMD_CHROMIUM_CTL_PRIVATE_FROM_CTL(pCmd);
161 pHdr->pfnCompletion = pfnCompletion;
162 pHdr->pvCompletion = pvCompletion;
163 pVGAState->pDrv->pfnCrHgsmiControlProcess(pVGAState->pDrv, pCmd);
164 return VINF_SUCCESS;
165 }
166#ifdef DEBUG_misha
167 Assert(0);
168#endif
169 return VERR_NOT_SUPPORTED;
170}
171
172static int vboxVDMACrCtlPost(PVGASTATE pVGAState, PVBOXVDMACMD_CHROMIUM_CTL pCmd)
173{
174 RTSEMEVENT hComplEvent;
175 int rc = RTSemEventCreate(&hComplEvent);
176 AssertRC(rc);
177 if(RT_SUCCESS(rc))
178 {
179 rc = vboxVDMACrCtlPostAsync (pVGAState, pCmd, vboxVDMACrCtlCbSetEvent, (void*)hComplEvent);
180#ifdef DEBUG_misha
181 AssertRC(rc);
182#endif
183 if (RT_SUCCESS(rc))
184 {
185 rc = RTSemEventWaitNoResume(hComplEvent, RT_INDEFINITE_WAIT);
186 AssertRC(rc);
187 if(RT_SUCCESS(rc))
188 {
189 RTSemEventDestroy(hComplEvent);
190 }
191 }
192 else
193 {
194 /* the command is completed */
195 RTSemEventDestroy(hComplEvent);
196 }
197 }
198 return rc;
199}
200
201static int vboxVDMACrCtlHgsmiSetupAsync(struct VBOXVDMAHOST *pVdma)
202{
203 PVBOXVDMACMD_CHROMIUM_CTL_CRHGSMI_SETUP pCmd = (PVBOXVDMACMD_CHROMIUM_CTL_CRHGSMI_SETUP)vboxVDMACrCtlCreate(
204 VBOXVDMACMD_CHROMIUM_CTL_TYPE_CRHGSMI_SETUP, sizeof (*pCmd));
205 if (pCmd)
206 {
207 PVGASTATE pVGAState = pVdma->pVGAState;
208 pCmd->pvRamBase = pVGAState->vram_ptrR3;
209 int rc = vboxVDMACrCtlPostAsync(pVGAState, &pCmd->Hdr, vboxVDMACrCtlCbReleaseCmd, NULL);
210#ifdef DEBUG_misha
211 AssertRC(rc);
212#endif
213#if 0
214 if (RT_SUCCESS(rc))
215 {
216 rc = vboxVDMACrCtlGetRc(&pCmd->Hdr);
217 }
218 vboxVDMACrCtlRelease(&pCmd->Hdr);
219#endif
220 return rc;
221 }
222 return VERR_NO_MEMORY;
223}
224
225/* check if this is external cmd to be passed to chromium backend */
226static bool vboxVDMACmdCheckCrCmd(struct VBOXVDMAHOST *pVdma, PVBOXVDMACBUF_DR pCmd)
227{
228 PVBOXVDMACMD pDmaCmd;
229 uint8_t * pvRam = pVdma->pVGAState->vram_ptrR3;
230
231 if (pCmd->fFlags & VBOXVDMACBUF_FLAG_BUF_FOLLOWS_DR)
232 pDmaCmd = VBOXVDMACBUF_DR_TAIL(pCmd, VBOXVDMACMD);
233 else
234 pDmaCmd = NULL;
235
236 if (pDmaCmd)
237 {
238 uint32_t cbCmd = pCmd->cbBuf;
239 Assert(cbCmd >= VBOXVDMACMD_HEADER_SIZE());
240
241 if (cbCmd >= VBOXVDMACMD_HEADER_SIZE())
242 {
243 if (pDmaCmd->enmType == VBOXVDMACMD_TYPE_CHROMIUM_CMD)
244 {
245 PVBOXVDMACMD_CHROMIUM_CMD pCrCmd = VBOXVDMACMD_BODY(pDmaCmd, VBOXVDMACMD_CHROMIUM_CMD);
246 PVGASTATE pVGAState = pVdma->pVGAState;
247 if (pVGAState->pDrv->pfnCrHgsmiCommandProcess)
248 {
249 VBoxSHGSMICommandMarkAsynchCompletion(pCmd);
250 pVGAState->pDrv->pfnCrHgsmiCommandProcess(pVGAState->pDrv, pCrCmd);
251 return true;
252 }
253 else
254 {
255 Assert(0);
256 }
257
258 int tmpRc = VBoxSHGSMICommandComplete (pVdma->pHgsmi, pCmd);
259 AssertRC(tmpRc);
260// uint32_t cBufs = pCrCmd->cBuffers;
261// for (uint32_t i = 0; i < cBufs; ++i)
262// {
263// PVBOXVDMACMD_CHROMIUM_BUFFER pBuf = &pCrCmd->aBuffers[i];
264// void *pvBuffer = pvRam + pBuf->offBuffer;
265// uint32_t cbBuffer = pBuf->cbBuffer;
266// }
267 }
268 }
269 }
270 return false;
271}
272
273int vboxVDMACrHgsmiCommandCompleteAsync(PPDMIDISPLAYVBVACALLBACKS pInterface, PVBOXVDMACMD_CHROMIUM_CMD pCmd, int rc)
274{
275 PVGASTATE pVGAState = PPDMIDISPLAYVBVACALLBACKS_2_PVGASTATE(pInterface);
276 PHGSMIINSTANCE pIns = pVGAState->pHGSMI;
277 VBOXVDMACMD *pDmaHdr = VBOXVDMACMD_FROM_BODY(pCmd);
278 VBOXVDMACBUF_DR *pDr = VBOXVDMACBUF_DR_FROM_TAIL(pDmaHdr);
279 AssertRC(rc);
280 pDr->rc = rc;
281
282 Assert(pVGAState->fGuestCaps & VBVACAPS_COMPLETEGCMD_BY_IOREAD);
283 rc = VBoxSHGSMICommandComplete(pIns, pDr);
284 AssertRC(rc);
285 return rc;
286}
287
288int vboxVDMACrHgsmiControlCompleteAsync(PPDMIDISPLAYVBVACALLBACKS pInterface, PVBOXVDMACMD_CHROMIUM_CTL pCmd, int rc)
289{
290 PVGASTATE pVGAState = PPDMIDISPLAYVBVACALLBACKS_2_PVGASTATE(pInterface);
291 PVBOXVDMACMD_CHROMIUM_CTL_PRIVATE pCmdPrivate = VBOXVDMACMD_CHROMIUM_CTL_PRIVATE_FROM_CTL(pCmd);
292 pCmdPrivate->rc = rc;
293 AssertRC(rc);
294 if (pCmdPrivate->pfnCompletion)
295 {
296 pCmdPrivate->pfnCompletion(pVGAState, pCmd, pCmdPrivate->pvCompletion);
297 }
298 return VINF_SUCCESS;
299}
300
301#endif
302
303
304/* to simplify things and to avoid extra backend if modifications we assume the VBOXVDMA_RECTL is the same as VBVACMDHDR */
305AssertCompile(sizeof(VBOXVDMA_RECTL) == sizeof(VBVACMDHDR));
306AssertCompile(RT_SIZEOFMEMB(VBOXVDMA_RECTL, left) == RT_SIZEOFMEMB(VBVACMDHDR, x));
307AssertCompile(RT_SIZEOFMEMB(VBOXVDMA_RECTL, top) == RT_SIZEOFMEMB(VBVACMDHDR, y));
308AssertCompile(RT_SIZEOFMEMB(VBOXVDMA_RECTL, width) == RT_SIZEOFMEMB(VBVACMDHDR, w));
309AssertCompile(RT_SIZEOFMEMB(VBOXVDMA_RECTL, height) == RT_SIZEOFMEMB(VBVACMDHDR, h));
310AssertCompile(RT_OFFSETOF(VBOXVDMA_RECTL, left) == RT_OFFSETOF(VBVACMDHDR, x));
311AssertCompile(RT_OFFSETOF(VBOXVDMA_RECTL, top) == RT_OFFSETOF(VBVACMDHDR, y));
312AssertCompile(RT_OFFSETOF(VBOXVDMA_RECTL, width) == RT_OFFSETOF(VBVACMDHDR, w));
313AssertCompile(RT_OFFSETOF(VBOXVDMA_RECTL, height) == RT_OFFSETOF(VBVACMDHDR, h));
314
315static int vboxVDMANotifyPrimaryUpdate (PVGASTATE pVGAState, unsigned uScreenId, const VBOXVDMA_RECTL * pRectl)
316{
317 pVGAState->pDrv->pfnVBVAUpdateBegin (pVGAState->pDrv, uScreenId);
318
319 /* Updates the rectangle and sends the command to the VRDP server. */
320 pVGAState->pDrv->pfnVBVAUpdateProcess (pVGAState->pDrv, uScreenId,
321 (const PVBVACMDHDR)pRectl /* <- see above AssertCompile's and comments */,
322 sizeof (VBOXVDMA_RECTL));
323
324 pVGAState->pDrv->pfnVBVAUpdateEnd (pVGAState->pDrv, uScreenId, pRectl->left, pRectl->top,
325 pRectl->width, pRectl->height);
326
327 return VINF_SUCCESS;
328}
329
330static int vboxVDMACmdExecBltPerform(PVBOXVDMAHOST pVdma,
331 uint8_t *pvDstSurf, const uint8_t *pvSrcSurf,
332 const PVBOXVDMA_SURF_DESC pDstDesc, const PVBOXVDMA_SURF_DESC pSrcDesc,
333 const VBOXVDMA_RECTL * pDstRectl, const VBOXVDMA_RECTL * pSrcRectl)
334{
335 /* we do not support color conversion */
336 Assert(pDstDesc->format == pSrcDesc->format);
337 /* we do not support stretching */
338 Assert(pDstRectl->height == pSrcRectl->height);
339 Assert(pDstRectl->width == pSrcRectl->width);
340 if (pDstDesc->format != pSrcDesc->format)
341 return VERR_INVALID_FUNCTION;
342 if (pDstDesc->width == pDstRectl->width
343 && pSrcDesc->width == pSrcRectl->width
344 && pSrcDesc->width == pDstDesc->width)
345 {
346 Assert(!pDstRectl->left);
347 Assert(!pSrcRectl->left);
348 uint32_t cbOff = pDstDesc->pitch * pDstRectl->top;
349 uint32_t cbSize = pDstDesc->pitch * pDstRectl->height;
350 memcpy(pvDstSurf + cbOff, pvSrcSurf + cbOff, cbSize);
351 }
352 else
353 {
354 uint32_t offDstLineStart = pDstRectl->left * pDstDesc->bpp >> 3;
355 uint32_t offDstLineEnd = ((pDstRectl->left * pDstDesc->bpp + 7) >> 3) + ((pDstDesc->bpp * pDstRectl->width + 7) >> 3);
356 uint32_t cbDstLine = offDstLineEnd - offDstLineStart;
357 uint32_t offDstStart = pDstDesc->pitch * pDstRectl->top + offDstLineStart;
358 Assert(cbDstLine <= pDstDesc->pitch);
359 uint32_t cbDstSkip = pDstDesc->pitch;
360 uint8_t * pvDstStart = pvDstSurf + offDstStart;
361
362 uint32_t offSrcLineStart = pSrcRectl->left * pSrcDesc->bpp >> 3;
363 uint32_t offSrcLineEnd = ((pSrcRectl->left * pSrcDesc->bpp + 7) >> 3) + ((pSrcDesc->bpp * pSrcRectl->width + 7) >> 3);
364 uint32_t cbSrcLine = offSrcLineEnd - offSrcLineStart;
365 uint32_t offSrcStart = pSrcDesc->pitch * pSrcRectl->top + offSrcLineStart;
366 Assert(cbSrcLine <= pSrcDesc->pitch);
367 uint32_t cbSrcSkip = pSrcDesc->pitch;
368 const uint8_t * pvSrcStart = pvSrcSurf + offSrcStart;
369
370 Assert(cbDstLine == cbSrcLine);
371
372 for (uint32_t i = 0; ; ++i)
373 {
374 memcpy (pvDstStart, pvSrcStart, cbDstLine);
375 if (i == pDstRectl->height)
376 break;
377 pvDstStart += cbDstSkip;
378 pvSrcStart += cbSrcSkip;
379 }
380 }
381 return VINF_SUCCESS;
382}
383
384static void vboxVDMARectlUnite(VBOXVDMA_RECTL * pRectl1, const VBOXVDMA_RECTL * pRectl2)
385{
386 if (!pRectl1->width)
387 *pRectl1 = *pRectl2;
388 else
389 {
390 int16_t x21 = pRectl1->left + pRectl1->width;
391 int16_t x22 = pRectl2->left + pRectl2->width;
392 if (pRectl1->left > pRectl2->left)
393 {
394 pRectl1->left = pRectl2->left;
395 pRectl1->width = x21 < x22 ? x22 - pRectl1->left : x21 - pRectl1->left;
396 }
397 else if (x21 < x22)
398 pRectl1->width = x22 - pRectl1->left;
399
400 x21 = pRectl1->top + pRectl1->height;
401 x22 = pRectl2->top + pRectl2->height;
402 if (pRectl1->top > pRectl2->top)
403 {
404 pRectl1->top = pRectl2->top;
405 pRectl1->height = x21 < x22 ? x22 - pRectl1->top : x21 - pRectl1->top;
406 }
407 else if (x21 < x22)
408 pRectl1->height = x22 - pRectl1->top;
409 }
410}
411
412/*
413 * @return on success the number of bytes the command contained, otherwise - VERR_xxx error code
414 */
415static int vboxVDMACmdExecBlt(PVBOXVDMAHOST pVdma, const PVBOXVDMACMD_DMA_PRESENT_BLT pBlt, uint32_t cbBuffer)
416{
417 const uint32_t cbBlt = VBOXVDMACMD_BODY_FIELD_OFFSET(uint32_t, VBOXVDMACMD_DMA_PRESENT_BLT, aDstSubRects[pBlt->cDstSubRects]);
418 Assert(cbBlt <= cbBuffer);
419 if (cbBuffer < cbBlt)
420 return VERR_INVALID_FUNCTION;
421
422 /* we do not support stretching for now */
423 Assert(pBlt->srcRectl.width == pBlt->dstRectl.width);
424 Assert(pBlt->srcRectl.height == pBlt->dstRectl.height);
425 if (pBlt->srcRectl.width != pBlt->dstRectl.width)
426 return VERR_INVALID_FUNCTION;
427 if (pBlt->srcRectl.height != pBlt->dstRectl.height)
428 return VERR_INVALID_FUNCTION;
429 Assert(pBlt->cDstSubRects);
430
431 uint8_t * pvRam = pVdma->pVGAState->vram_ptrR3;
432 VBOXVDMA_RECTL updateRectl = {0};
433
434 if (pBlt->cDstSubRects)
435 {
436 VBOXVDMA_RECTL dstRectl, srcRectl;
437 const VBOXVDMA_RECTL *pDstRectl, *pSrcRectl;
438 for (uint32_t i = 0; i < pBlt->cDstSubRects; ++i)
439 {
440 pDstRectl = &pBlt->aDstSubRects[i];
441 if (pBlt->dstRectl.left || pBlt->dstRectl.top)
442 {
443 dstRectl.left = pDstRectl->left + pBlt->dstRectl.left;
444 dstRectl.top = pDstRectl->top + pBlt->dstRectl.top;
445 dstRectl.width = pDstRectl->width;
446 dstRectl.height = pDstRectl->height;
447 pDstRectl = &dstRectl;
448 }
449
450 pSrcRectl = &pBlt->aDstSubRects[i];
451 if (pBlt->srcRectl.left || pBlt->srcRectl.top)
452 {
453 srcRectl.left = pSrcRectl->left + pBlt->srcRectl.left;
454 srcRectl.top = pSrcRectl->top + pBlt->srcRectl.top;
455 srcRectl.width = pSrcRectl->width;
456 srcRectl.height = pSrcRectl->height;
457 pSrcRectl = &srcRectl;
458 }
459
460 int rc = vboxVDMACmdExecBltPerform(pVdma, pvRam + pBlt->offDst, pvRam + pBlt->offSrc,
461 &pBlt->dstDesc, &pBlt->srcDesc,
462 pDstRectl,
463 pSrcRectl);
464 AssertRC(rc);
465 if (!RT_SUCCESS(rc))
466 return rc;
467
468 vboxVDMARectlUnite(&updateRectl, pDstRectl);
469 }
470 }
471 else
472 {
473 int rc = vboxVDMACmdExecBltPerform(pVdma, pvRam + pBlt->offDst, pvRam + pBlt->offSrc,
474 &pBlt->dstDesc, &pBlt->srcDesc,
475 &pBlt->dstRectl,
476 &pBlt->srcRectl);
477 AssertRC(rc);
478 if (!RT_SUCCESS(rc))
479 return rc;
480
481 vboxVDMARectlUnite(&updateRectl, &pBlt->dstRectl);
482 }
483
484 int iView = 0;
485 /* @todo: fixme: check if update is needed and get iView */
486 vboxVDMANotifyPrimaryUpdate (pVdma->pVGAState, iView, &updateRectl);
487
488 return cbBlt;
489}
490
491static int vboxVDMACmdExec(PVBOXVDMAHOST pVdma, const uint8_t *pvBuffer, uint32_t cbBuffer)
492{
493 do
494 {
495 Assert(pvBuffer);
496 Assert(cbBuffer >= VBOXVDMACMD_HEADER_SIZE());
497
498 if (!pvBuffer)
499 return VERR_INVALID_PARAMETER;
500 if (cbBuffer < VBOXVDMACMD_HEADER_SIZE())
501 return VERR_INVALID_PARAMETER;
502
503 PVBOXVDMACMD pCmd = (PVBOXVDMACMD)pvBuffer;
504 uint32_t cbCmd = 0;
505 switch (pCmd->enmType)
506 {
507 case VBOXVDMACMD_TYPE_CHROMIUM_CMD:
508 {
509#ifdef VBOXWDDM_TEST_UHGSMI
510 static int count = 0;
511 static uint64_t start, end;
512 if (count==0)
513 {
514 start = RTTimeNanoTS();
515 }
516 ++count;
517 if (count==100000)
518 {
519 end = RTTimeNanoTS();
520 float ems = (end-start)/1000000.f;
521 LogRel(("100000 calls took %i ms, %i cps\n", (int)ems, (int)(100000.f*1000.f/ems) ));
522 }
523#endif
524 /* todo: post the buffer to chromium */
525 return VINF_SUCCESS;
526 }
527 case VBOXVDMACMD_TYPE_DMA_PRESENT_BLT:
528 {
529 const PVBOXVDMACMD_DMA_PRESENT_BLT pBlt = VBOXVDMACMD_BODY(pCmd, VBOXVDMACMD_DMA_PRESENT_BLT);
530 int cbBlt = vboxVDMACmdExecBlt(pVdma, pBlt, cbBuffer);
531 Assert(cbBlt >= 0);
532 Assert((uint32_t)cbBlt <= cbBuffer);
533 if (cbBlt >= 0)
534 {
535 if (cbBlt == cbBuffer)
536 return VINF_SUCCESS;
537 else
538 {
539 cbBuffer -= (uint32_t)cbBlt;
540 pvBuffer -= cbBlt;
541 }
542 }
543 else
544 return cbBlt; /* error */
545 break;
546 }
547 default:
548 AssertBreakpoint();
549 return VERR_INVALID_FUNCTION;
550 }
551 } while (1);
552
553 /* we should not be here */
554 AssertBreakpoint();
555 return VERR_INVALID_STATE;
556}
557
558int vboxVDMAPipeConstruct(PVBOXVDMAPIPE pPipe)
559{
560 int rc = RTSemEventCreate(&pPipe->hEvent);
561 AssertRC(rc);
562 if (RT_SUCCESS(rc))
563 {
564 rc = RTCritSectInit(&pPipe->hCritSect);
565 AssertRC(rc);
566 if (RT_SUCCESS(rc))
567 {
568 pPipe->enmState = VBOXVDMAPIPE_STATE_CREATED;
569 pPipe->bNeedNotify = true;
570 return VINF_SUCCESS;
571// RTCritSectDelete(pPipe->hCritSect);
572 }
573 RTSemEventDestroy(pPipe->hEvent);
574 }
575 return rc;
576}
577
578int vboxVDMAPipeOpenServer(PVBOXVDMAPIPE pPipe)
579{
580 int rc = RTCritSectEnter(&pPipe->hCritSect);
581 AssertRC(rc);
582 if (RT_SUCCESS(rc))
583 {
584 Assert(pPipe->enmState == VBOXVDMAPIPE_STATE_CREATED);
585 switch (pPipe->enmState)
586 {
587 case VBOXVDMAPIPE_STATE_CREATED:
588 pPipe->enmState = VBOXVDMAPIPE_STATE_OPENNED;
589 pPipe->bNeedNotify = false;
590 rc = VINF_SUCCESS;
591 break;
592 case VBOXVDMAPIPE_STATE_OPENNED:
593 pPipe->bNeedNotify = false;
594 rc = VINF_ALREADY_INITIALIZED;
595 break;
596 default:
597 AssertBreakpoint();
598 rc = VERR_INVALID_STATE;
599 break;
600 }
601
602 RTCritSectLeave(&pPipe->hCritSect);
603 }
604 return rc;
605}
606
607int vboxVDMAPipeCloseServer(PVBOXVDMAPIPE pPipe)
608{
609 int rc = RTCritSectEnter(&pPipe->hCritSect);
610 AssertRC(rc);
611 if (RT_SUCCESS(rc))
612 {
613 Assert(pPipe->enmState == VBOXVDMAPIPE_STATE_CLOSED
614 || pPipe->enmState == VBOXVDMAPIPE_STATE_CLOSING);
615 switch (pPipe->enmState)
616 {
617 case VBOXVDMAPIPE_STATE_CLOSING:
618 pPipe->enmState = VBOXVDMAPIPE_STATE_CLOSED;
619 rc = VINF_SUCCESS;
620 break;
621 case VBOXVDMAPIPE_STATE_CLOSED:
622 rc = VINF_ALREADY_INITIALIZED;
623 break;
624 default:
625 AssertBreakpoint();
626 rc = VERR_INVALID_STATE;
627 break;
628 }
629
630 RTCritSectLeave(&pPipe->hCritSect);
631 }
632 return rc;
633}
634
635int vboxVDMAPipeCloseClient(PVBOXVDMAPIPE pPipe)
636{
637 int rc = RTCritSectEnter(&pPipe->hCritSect);
638 AssertRC(rc);
639 if (RT_SUCCESS(rc))
640 {
641 bool bNeedNotify = false;
642 Assert(pPipe->enmState == VBOXVDMAPIPE_STATE_OPENNED
643 || pPipe->enmState == VBOXVDMAPIPE_STATE_CREATED
644 || pPipe->enmState == VBOXVDMAPIPE_STATE_CLOSED);
645 switch (pPipe->enmState)
646 {
647 case VBOXVDMAPIPE_STATE_OPENNED:
648 pPipe->enmState = VBOXVDMAPIPE_STATE_CLOSING;
649 bNeedNotify = pPipe->bNeedNotify;
650 pPipe->bNeedNotify = false;
651 break;
652 case VBOXVDMAPIPE_STATE_CREATED:
653 pPipe->enmState = VBOXVDMAPIPE_STATE_CLOSED;
654 pPipe->bNeedNotify = false;
655 break;
656 case VBOXVDMAPIPE_STATE_CLOSED:
657 rc = VINF_ALREADY_INITIALIZED;
658 break;
659 default:
660 AssertBreakpoint();
661 rc = VERR_INVALID_STATE;
662 break;
663 }
664
665 RTCritSectLeave(&pPipe->hCritSect);
666
667 if (bNeedNotify)
668 {
669 rc = RTSemEventSignal(pPipe->hEvent);
670 AssertRC(rc);
671 }
672 }
673 return rc;
674}
675
676
677typedef DECLCALLBACK(bool) FNHVBOXVDMARWCB(PVBOXVDMAPIPE pPipe, void *pvCallback);
678typedef FNHVBOXVDMARWCB *PFNHVBOXVDMARWCB;
679
680int vboxVDMAPipeModifyServer(PVBOXVDMAPIPE pPipe, PFNHVBOXVDMARWCB pfnCallback, void * pvCallback)
681{
682 int rc = RTCritSectEnter(&pPipe->hCritSect);
683 AssertRC(rc);
684 if (RT_SUCCESS(rc))
685 {
686 do
687 {
688 Assert(pPipe->enmState == VBOXVDMAPIPE_STATE_OPENNED
689 || pPipe->enmState == VBOXVDMAPIPE_STATE_CLOSING);
690
691 if (pPipe->enmState >= VBOXVDMAPIPE_STATE_OPENNED)
692 {
693 bool bProcessing = pfnCallback(pPipe, pvCallback);
694 pPipe->bNeedNotify = !bProcessing;
695 if (bProcessing)
696 {
697 RTCritSectLeave(&pPipe->hCritSect);
698 rc = VINF_SUCCESS;
699 break;
700 }
701 else if (pPipe->enmState == VBOXVDMAPIPE_STATE_CLOSING)
702 {
703 pPipe->enmState = VBOXVDMAPIPE_STATE_CLOSED;
704 RTCritSectLeave(&pPipe->hCritSect);
705 rc = VINF_EOF;
706 break;
707 }
708 }
709 else
710 {
711 AssertBreakpoint();
712 rc = VERR_INVALID_STATE;
713 RTCritSectLeave(&pPipe->hCritSect);
714 break;
715 }
716
717 RTCritSectLeave(&pPipe->hCritSect);
718
719 rc = RTSemEventWait(pPipe->hEvent, RT_INDEFINITE_WAIT);
720 AssertRC(rc);
721 if (!RT_SUCCESS(rc))
722 break;
723
724 rc = RTCritSectEnter(&pPipe->hCritSect);
725 AssertRC(rc);
726 if (!RT_SUCCESS(rc))
727 break;
728 } while (1);
729 }
730
731 return rc;
732}
733
734int vboxVDMAPipeModifyClient(PVBOXVDMAPIPE pPipe, PFNHVBOXVDMARWCB pfnCallback, void * pvCallback)
735{
736 int rc = RTCritSectEnter(&pPipe->hCritSect);
737 AssertRC(rc);
738 if (RT_SUCCESS(rc))
739 {
740 bool bNeedNotify = false;
741 Assert(pPipe->enmState == VBOXVDMAPIPE_STATE_OPENNED);
742 if (pPipe->enmState == VBOXVDMAPIPE_STATE_OPENNED)
743 {
744 bool bModified = pfnCallback(pPipe, pvCallback);
745 if (bModified)
746 {
747 bNeedNotify = pPipe->bNeedNotify;
748 pPipe->bNeedNotify = false;
749 }
750 }
751 else
752 rc = VERR_INVALID_STATE;
753
754 RTCritSectLeave(&pPipe->hCritSect);
755
756 if (bNeedNotify)
757 {
758 rc = RTSemEventSignal(pPipe->hEvent);
759 AssertRC(rc);
760 }
761 }
762 return rc;
763}
764
765int vboxVDMAPipeDestruct(PVBOXVDMAPIPE pPipe)
766{
767 Assert(pPipe->enmState == VBOXVDMAPIPE_STATE_CLOSED
768 || pPipe->enmState == VBOXVDMAPIPE_STATE_CREATED);
769 /* ensure the pipe is closed */
770 vboxVDMAPipeCloseClient(pPipe);
771
772 Assert(pPipe->enmState == VBOXVDMAPIPE_STATE_CLOSED);
773
774 if (pPipe->enmState != VBOXVDMAPIPE_STATE_CLOSED)
775 return VERR_INVALID_STATE;
776
777 int rc = RTCritSectDelete(&pPipe->hCritSect);
778 AssertRC(rc);
779
780 rc = RTSemEventDestroy(pPipe->hEvent);
781 AssertRC(rc);
782
783 return VINF_SUCCESS;
784}
785
786static void vboxVDMACommandProcess(PVBOXVDMAHOST pVdma, PVBOXVDMACBUF_DR pCmd)
787{
788 PHGSMIINSTANCE pHgsmi = pVdma->pHgsmi;
789 const uint8_t * pvBuf;
790 PGMPAGEMAPLOCK Lock;
791 int rc;
792 bool bReleaseLocked = false;
793
794 do
795 {
796 PPDMDEVINS pDevIns = pVdma->pVGAState->pDevInsR3;
797
798 if (pCmd->fFlags & VBOXVDMACBUF_FLAG_BUF_FOLLOWS_DR)
799 pvBuf = VBOXVDMACBUF_DR_TAIL(pCmd, const uint8_t);
800 else if (pCmd->fFlags & VBOXVDMACBUF_FLAG_BUF_VRAM_OFFSET)
801 {
802 uint8_t * pvRam = pVdma->pVGAState->vram_ptrR3;
803 pvBuf = pvRam + pCmd->Location.offVramBuf;
804 }
805 else
806 {
807 RTGCPHYS phPage = pCmd->Location.phBuf & ~0xfffULL;
808 uint32_t offset = pCmd->Location.phBuf & 0xfff;
809 Assert(offset + pCmd->cbBuf <= 0x1000);
810 if (offset + pCmd->cbBuf > 0x1000)
811 {
812 /* @todo: more advanced mechanism of command buffer proc is actually needed */
813 rc = VERR_INVALID_PARAMETER;
814 break;
815 }
816
817 const void * pvPageBuf;
818 rc = PDMDevHlpPhysGCPhys2CCPtrReadOnly(pDevIns, phPage, 0, &pvPageBuf, &Lock);
819 AssertRC(rc);
820 if (!RT_SUCCESS(rc))
821 {
822 /* @todo: if (rc == VERR_PGM_PHYS_PAGE_RESERVED) -> fall back on using PGMPhysRead ?? */
823 break;
824 }
825
826 pvBuf = (const uint8_t *)pvPageBuf;
827 pvBuf += offset;
828
829 bReleaseLocked = true;
830 }
831
832 rc = vboxVDMACmdExec(pVdma, pvBuf, pCmd->cbBuf);
833 AssertRC(rc);
834
835 if (bReleaseLocked)
836 PDMDevHlpPhysReleasePageMappingLock(pDevIns, &Lock);
837 } while (0);
838
839 pCmd->rc = rc;
840
841 rc = VBoxSHGSMICommandComplete (pHgsmi, pCmd);
842 AssertRC(rc);
843}
844
845static void vboxVDMAControlProcess(PVBOXVDMAHOST pVdma, PVBOXVDMA_CTL pCmd)
846{
847 PHGSMIINSTANCE pHgsmi = pVdma->pHgsmi;
848 pCmd->i32Result = VINF_SUCCESS;
849 int rc = VBoxSHGSMICommandComplete (pHgsmi, pCmd);
850 AssertRC(rc);
851}
852
853typedef struct
854{
855 struct VBOXVDMAHOST *pVdma;
856 VBOXVDMAPIPE_CMD_BODY Cmd;
857 bool bHasCmd;
858} VBOXVDMACMD_PROCESS_CONTEXT, *PVBOXVDMACMD_PROCESS_CONTEXT;
859
860static DECLCALLBACK(bool) vboxVDMACommandProcessCb(PVBOXVDMAPIPE pPipe, void *pvCallback)
861{
862 PVBOXVDMACMD_PROCESS_CONTEXT pContext = (PVBOXVDMACMD_PROCESS_CONTEXT)pvCallback;
863 struct VBOXVDMAHOST *pVdma = pContext->pVdma;
864 HGSMILISTENTRY *pEntry = hgsmiListRemoveHead(&pVdma->PendingList);
865 if (pEntry)
866 {
867 PVBOXVDMAPIPE_CMD pPipeCmd = VBOXVDMAPIPE_CMD_FROM_ENTRY(pEntry);
868 Assert(pPipeCmd);
869 pContext->Cmd = pPipeCmd->Cmd;
870 hgsmiListPrepend(&pVdma->CmdPool.List, pEntry);
871 pContext->bHasCmd = true;
872 return true;
873 }
874
875 pContext->bHasCmd = false;
876 return false;
877}
878
879static DECLCALLBACK(int) vboxVDMAWorkerThread(RTTHREAD ThreadSelf, void *pvUser)
880{
881 PVBOXVDMAHOST pVdma = (PVBOXVDMAHOST)pvUser;
882 PHGSMIINSTANCE pHgsmi = pVdma->pHgsmi;
883 VBOXVDMACMD_PROCESS_CONTEXT Context;
884 Context.pVdma = pVdma;
885
886 int rc = vboxVDMAPipeOpenServer(&pVdma->Pipe);
887 AssertRC(rc);
888 if (RT_SUCCESS(rc))
889 {
890 do
891 {
892 rc = vboxVDMAPipeModifyServer(&pVdma->Pipe, vboxVDMACommandProcessCb, &Context);
893 AssertRC(rc);
894 if (RT_SUCCESS(rc))
895 {
896 switch (Context.Cmd.enmType)
897 {
898 case VBOXVDMAPIPE_CMD_TYPE_DMACMD:
899 {
900 PVBOXVDMACBUF_DR pDr = Context.Cmd.u.pDr;
901 vboxVDMACommandProcess(pVdma, pDr);
902 break;
903 }
904 case VBOXVDMAPIPE_CMD_TYPE_DMACTL:
905 {
906 PVBOXVDMA_CTL pCtl = Context.Cmd.u.pCtl;
907 vboxVDMAControlProcess(pVdma, pCtl);
908 break;
909 }
910 default:
911 AssertBreakpoint();
912 break;
913 }
914
915 if (rc == VINF_EOF)
916 {
917 rc = VINF_SUCCESS;
918 break;
919 }
920 }
921 else
922 break;
923 } while (1);
924 }
925
926 /* always try to close the pipe to make sure the client side is notified */
927 int tmpRc = vboxVDMAPipeCloseServer(&pVdma->Pipe);
928 AssertRC(tmpRc);
929 return rc;
930}
931
932int vboxVDMAConstruct(PVGASTATE pVGAState, struct VBOXVDMAHOST **ppVdma, uint32_t cPipeElements)
933{
934 int rc;
935 PVBOXVDMAHOST pVdma = (PVBOXVDMAHOST)RTMemAllocZ (RT_OFFSETOF(VBOXVDMAHOST, CmdPool.aCmds[cPipeElements]));
936 Assert(pVdma);
937 if (pVdma)
938 {
939 hgsmiListInit(&pVdma->PendingList);
940 pVdma->pHgsmi = pVGAState->pHGSMI;
941 pVdma->pVGAState = pVGAState;
942 rc = vboxVDMAPipeConstruct(&pVdma->Pipe);
943 AssertRC(rc);
944 if (RT_SUCCESS(rc))
945 {
946 rc = RTThreadCreate(&pVdma->hWorkerThread, vboxVDMAWorkerThread, pVdma, 0, RTTHREADTYPE_IO, RTTHREADFLAGS_WAITABLE, "VDMA");
947 AssertRC(rc);
948 if (RT_SUCCESS(rc))
949 {
950 hgsmiListInit(&pVdma->CmdPool.List);
951 pVdma->CmdPool.cCmds = cPipeElements;
952 for (uint32_t i = 0; i < cPipeElements; ++i)
953 {
954 hgsmiListAppend(&pVdma->CmdPool.List, &pVdma->CmdPool.aCmds[i].Entry);
955 }
956#if 0 //def VBOX_WITH_CRHGSMI
957 int tmpRc = vboxVDMACrCtlHgsmiSetup(pVdma);
958# ifdef DEBUG_misha
959 AssertRC(tmpRc);
960# endif
961#endif
962 *ppVdma = pVdma;
963 return VINF_SUCCESS;
964 }
965
966 int tmpRc = vboxVDMAPipeDestruct(&pVdma->Pipe);
967 AssertRC(tmpRc);
968 }
969
970 RTMemFree(pVdma);
971 }
972 else
973 rc = VERR_OUT_OF_RESOURCES;
974
975 return rc;
976}
977
978int vboxVDMADestruct(struct VBOXVDMAHOST **pVdma)
979{
980 AssertBreakpoint();
981 return VINF_SUCCESS;
982}
983
984typedef struct
985{
986 struct VBOXVDMAHOST *pVdma;
987 VBOXVDMAPIPE_CMD_BODY Cmd;
988 bool bQueued;
989} VBOXVDMACMD_SUBMIT_CONTEXT, *PVBOXVDMACMD_SUBMIT_CONTEXT;
990
991DECLCALLBACK(bool) vboxVDMACommandSubmitCb(PVBOXVDMAPIPE pPipe, void *pvCallback)
992{
993 PVBOXVDMACMD_SUBMIT_CONTEXT pContext = (PVBOXVDMACMD_SUBMIT_CONTEXT)pvCallback;
994 struct VBOXVDMAHOST *pVdma = pContext->pVdma;
995 HGSMILISTENTRY *pEntry = hgsmiListRemoveHead(&pVdma->CmdPool.List);
996 Assert(pEntry);
997 if (pEntry)
998 {
999 PVBOXVDMAPIPE_CMD pPipeCmd = VBOXVDMAPIPE_CMD_FROM_ENTRY(pEntry);
1000 pPipeCmd->Cmd = pContext->Cmd;
1001 VBoxSHGSMICommandMarkAsynchCompletion(pContext->Cmd.u.pvCmd);
1002 pContext->bQueued = true;
1003 hgsmiListAppend(&pVdma->PendingList, pEntry);
1004 return true;
1005 }
1006
1007 /* @todo: should we try to flush some commands here? */
1008 pContext->bQueued = false;
1009 return false;
1010}
1011
1012void vboxVDMAControl(struct VBOXVDMAHOST *pVdma, PVBOXVDMA_CTL pCmd)
1013{
1014#if 1
1015 PHGSMIINSTANCE pIns = pVdma->pHgsmi;
1016
1017 switch (pCmd->enmCtl)
1018 {
1019 case VBOXVDMA_CTL_TYPE_ENABLE:
1020 {
1021 pVdma->bEnabled = true;
1022 pCmd->i32Result = VINF_SUCCESS;
1023#ifdef VBOX_WITH_CRHGSMI
1024 /* @todo: use async completion to ensure we notify a status to guest */
1025 int tmpRc = vboxVDMACrCtlHgsmiSetupAsync(pVdma);
1026 AssertRC(tmpRc);
1027#endif
1028 }
1029 break;
1030 case VBOXVDMA_CTL_TYPE_DISABLE:
1031 pVdma->bEnabled = false;
1032 pCmd->i32Result = VINF_SUCCESS;
1033 break;
1034 case VBOXVDMA_CTL_TYPE_FLUSH:
1035 pCmd->i32Result = VINF_SUCCESS;
1036 break;
1037 default:
1038 AssertBreakpoint();
1039 pCmd->i32Result = VERR_NOT_SUPPORTED;
1040 }
1041
1042 int rc = VBoxSHGSMICommandComplete (pIns, pCmd);
1043 AssertRC(rc);
1044#else
1045 /* test asinch completion */
1046 VBOXVDMACMD_SUBMIT_CONTEXT Context;
1047 Context.pVdma = pVdma;
1048 Context.Cmd.enmType = VBOXVDMAPIPE_CMD_TYPE_DMACTL;
1049 Context.Cmd.u.pCtl = pCmd;
1050
1051 int rc = vboxVDMAPipeModifyClient(&pVdma->Pipe, vboxVDMACommandSubmitCb, &Context);
1052 AssertRC(rc);
1053 if (RT_SUCCESS(rc))
1054 {
1055 Assert(Context.bQueued);
1056 if (Context.bQueued)
1057 {
1058 /* success */
1059 return;
1060 }
1061 rc = VERR_OUT_OF_RESOURCES;
1062 }
1063
1064 /* failure */
1065 Assert(RT_FAILURE(rc));
1066 PHGSMIINSTANCE pIns = pVdma->pHgsmi;
1067 pCmd->i32Result = rc;
1068 int tmpRc = VBoxSHGSMICommandComplete (pIns, pCmd);
1069 AssertRC(tmpRc);
1070
1071#endif
1072}
1073
1074void vboxVDMACommand(struct VBOXVDMAHOST *pVdma, PVBOXVDMACBUF_DR pCmd)
1075{
1076#ifdef VBOX_WITH_CRHGSMI
1077 if (vboxVDMACmdCheckCrCmd(pVdma, pCmd))
1078 return;
1079#endif
1080
1081#ifdef DEBUG_misha
1082 Assert(0);
1083#endif
1084
1085 VBOXVDMACMD_SUBMIT_CONTEXT Context;
1086 Context.pVdma = pVdma;
1087 Context.Cmd.enmType = VBOXVDMAPIPE_CMD_TYPE_DMACMD;
1088 Context.Cmd.u.pDr = pCmd;
1089
1090 int rc = vboxVDMAPipeModifyClient(&pVdma->Pipe, vboxVDMACommandSubmitCb, &Context);
1091 AssertRC(rc);
1092 if (RT_SUCCESS(rc))
1093 {
1094 Assert(Context.bQueued);
1095 if (Context.bQueued)
1096 {
1097 /* success */
1098 return;
1099 }
1100 rc = VERR_OUT_OF_RESOURCES;
1101 }
1102
1103 /* failure */
1104 Assert(RT_FAILURE(rc));
1105 PHGSMIINSTANCE pIns = pVdma->pHgsmi;
1106 pCmd->rc = rc;
1107 int tmpRc = VBoxSHGSMICommandComplete (pIns, pCmd);
1108 AssertRC(tmpRc);
1109}
1110
1111bool vboxVDMAIsEnabled(PVBOXVDMAHOST pVdma)
1112{
1113 return pVdma->bEnabled;
1114}
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