blitter.cpp revision 24e27201b1438d88569467f104a0e3cb1df190ed
c1350cf5bc50458ba79cc93ff9e0e5fe3f1aeeb0jeff.schenk * Blitter API implementation
c1350cf5bc50458ba79cc93ff9e0e5fe3f1aeeb0jeff.schenk * Copyright (C) 2013 Oracle Corporation
c1350cf5bc50458ba79cc93ff9e0e5fe3f1aeeb0jeff.schenk * This file is part of VirtualBox Open Source Edition (OSE), as
c1350cf5bc50458ba79cc93ff9e0e5fe3f1aeeb0jeff.schenk * available from http://www.virtualbox.org. This file is free software;
c1350cf5bc50458ba79cc93ff9e0e5fe3f1aeeb0jeff.schenk * you can redistribute it and/or modify it under the terms of the GNU
c1350cf5bc50458ba79cc93ff9e0e5fe3f1aeeb0jeff.schenk * General Public License (GPL) as published by the Free Software
c1350cf5bc50458ba79cc93ff9e0e5fe3f1aeeb0jeff.schenk * Foundation, in version 2 as it comes in the "COPYING" file of the
c1350cf5bc50458ba79cc93ff9e0e5fe3f1aeeb0jeff.schenk * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
c1350cf5bc50458ba79cc93ff9e0e5fe3f1aeeb0jeff.schenk * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
c1350cf5bc50458ba79cc93ff9e0e5fe3f1aeeb0jeff.schenk/* @param pCtxBase - contains the blitter context info. Its value is treated differently depending on the fCreateNewCtx value
c1350cf5bc50458ba79cc93ff9e0e5fe3f1aeeb0jeff.schenk * @param fCreateNewCtx - if true - the pCtxBase must NOT be NULL. its visualBits is used as a visual bits info for the new context,
c1350cf5bc50458ba79cc93ff9e0e5fe3f1aeeb0jeff.schenk * its id field is used to specified the shared context id to be used for blitter context.
c1350cf5bc50458ba79cc93ff9e0e5fe3f1aeeb0jeff.schenk * The id can be null to specify no shared context is needed
c1350cf5bc50458ba79cc93ff9e0e5fe3f1aeeb0jeff.schenk * if false - if pCtxBase is NOT null AND its id field is NOT null -
c1350cf5bc50458ba79cc93ff9e0e5fe3f1aeeb0jeff.schenk * specified the blitter context to be used
c1350cf5bc50458ba79cc93ff9e0e5fe3f1aeeb0jeff.schenk * blitter treats it as if it has default ogl state.
c1350cf5bc50458ba79cc93ff9e0e5fe3f1aeeb0jeff.schenk * otherwise -
c1350cf5bc50458ba79cc93ff9e0e5fe3f1aeeb0jeff.schenk * the blitter works in a "no-context" mode, i.e. a caller is responsible
c1350cf5bc50458ba79cc93ff9e0e5fe3f1aeeb0jeff.schenk * to making a proper context current before calling the blitter.
c1350cf5bc50458ba79cc93ff9e0e5fe3f1aeeb0jeff.schenk * Note that BltEnter/Leave MUST still be called, but the proper context
c1350cf5bc50458ba79cc93ff9e0e5fe3f1aeeb0jeff.schenk * must be set before doing BltEnter, and ResoreContext info is ignored in that case.
c1350cf5bc50458ba79cc93ff9e0e5fe3f1aeeb0jeff.schenk * Also note that blitter caches the current window info, and assumes the current context's values are preserved
c1350cf5bc50458ba79cc93ff9e0e5fe3f1aeeb0jeff.schenk * wrt that window before the calls, so if one uses different contexts for one blitter,
c1350cf5bc50458ba79cc93ff9e0e5fe3f1aeeb0jeff.schenk * the blitter current window values must be explicitly reset by doing CrBltMuralSetCurrentInfo(pBlitter, NULL)
c1350cf5bc50458ba79cc93ff9e0e5fe3f1aeeb0jeff.schenk * @param fForceDrawBlt - if true - forces the blitter to always use glDrawXxx-based blits even if GL_EXT_framebuffer_blit.
c1350cf5bc50458ba79cc93ff9e0e5fe3f1aeeb0jeff.schenk * This is needed because BlitFramebufferEXT is known to be often buggy, and glDrawXxx-based blits appear to be more reliable
c1350cf5bc50458ba79cc93ff9e0e5fe3f1aeeb0jeff.schenkVBOXBLITTERDECL(int) CrBltInit(PCR_BLITTER pBlitter, const CR_BLITTER_CONTEXT *pCtxBase, bool fCreateNewCtx, bool fForceDrawBlt, const CR_GLSL_CACHE *pShaders, SPUDispatchTable *pDispatch)
c1350cf5bc50458ba79cc93ff9e0e5fe3f1aeeb0jeff.schenk crWarning("Default share context not initialized!");
c1350cf5bc50458ba79cc93ff9e0e5fe3f1aeeb0jeff.schenk crWarning("pCtxBase is zero while fCreateNewCtx is set!");
c1350cf5bc50458ba79cc93ff9e0e5fe3f1aeeb0jeff.schenk pBlitter->CtxInfo.Base.id = pDispatch->CreateContext("", pCtxBase->Base.visualBits, pCtxBase->Base.id);
c1350cf5bc50458ba79cc93ff9e0e5fe3f1aeeb0jeff.schenk CrGlslInit(&pBlitter->LocalGlslCache, pDispatch);
c1350cf5bc50458ba79cc93ff9e0e5fe3f1aeeb0jeff.schenk pBlitter->pGlslCache = &pBlitter->LocalGlslCache;
c1350cf5bc50458ba79cc93ff9e0e5fe3f1aeeb0jeff.schenkVBOXBLITTERDECL(int) CrBltCleanup(PCR_BLITTER pBlitter)
c1350cf5bc50458ba79cc93ff9e0e5fe3f1aeeb0jeff.schenk crWarning("CrBltBlitTexTex: blitter is entered");
c1350cf5bc50458ba79cc93ff9e0e5fe3f1aeeb0jeff.schenk if (pBlitter->Flags.ShadersGloal || !CrGlslNeedsCleanup(&pBlitter->LocalGlslCache))
c1350cf5bc50458ba79cc93ff9e0e5fe3f1aeeb0jeff.schenk pBlitter->pDispatch->DestroyContext(pBlitter->CtxInfo.Base.id);
c1350cf5bc50458ba79cc93ff9e0e5fe3f1aeeb0jeff.schenkint CrBltMuralSetCurrentInfo(PCR_BLITTER pBlitter, const CR_BLITTER_WINDOW *pMural)
c1350cf5bc50458ba79cc93ff9e0e5fe3f1aeeb0jeff.schenk if (!memcmp(&pBlitter->CurrentMural, pMural, sizeof (pBlitter->CurrentMural)))
c1350cf5bc50458ba79cc93ff9e0e5fe3f1aeeb0jeff.schenk memcpy(&pBlitter->CurrentMural, pMural, sizeof (pBlitter->CurrentMural));
c1350cf5bc50458ba79cc93ff9e0e5fe3f1aeeb0jeff.schenk crWarning("can not set null mural for entered bleater");
c1350cf5bc50458ba79cc93ff9e0e5fe3f1aeeb0jeff.schenk crWarning("setting current mural for entered no-context blitter");
c1350cf5bc50458ba79cc93ff9e0e5fe3f1aeeb0jeff.schenk crWarning("changing mural for entered blitter, is is somewhat expected?");
c1350cf5bc50458ba79cc93ff9e0e5fe3f1aeeb0jeff.schenk pBlitter->pDispatch->MakeCurrent(pMural->Base.id, pBlitter->i32MakeCurrentUserData, pBlitter->CtxInfo.Base.id);
c1350cf5bc50458ba79cc93ff9e0e5fe3f1aeeb0jeff.schenkstatic DECLCALLBACK(int) crBltBlitTexBufImplFbo(PCR_BLITTER pBlitter, const VBOXVR_TEXTURE *pSrc, const RTRECT *paSrcRect, const RTRECTSIZE *pDstSize, const RTRECT *paDstRect, uint32_t cRects, uint32_t fFlags)
c1350cf5bc50458ba79cc93ff9e0e5fe3f1aeeb0jeff.schenk GLenum filter = CRBLT_FILTER_FROM_FLAGS(fFlags);
c1350cf5bc50458ba79cc93ff9e0e5fe3f1aeeb0jeff.schenk pBlitter->pDispatch->BindFramebufferEXT(GL_READ_FRAMEBUFFER, pBlitter->idFBO);
c1350cf5bc50458ba79cc93ff9e0e5fe3f1aeeb0jeff.schenk pBlitter->pDispatch->FramebufferTexture2DEXT(GL_READ_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, pSrc->target, pSrc->hwid, 0);
c1350cf5bc50458ba79cc93ff9e0e5fe3f1aeeb0jeff.schenk pBlitter->pDispatch->ReadBuffer(GL_COLOR_ATTACHMENT0);
c1350cf5bc50458ba79cc93ff9e0e5fe3f1aeeb0jeff.schenk /* use srcY1 < srcY2 && dstY1 < dstY2 whenever possible to avoid GPU driver bugs */
c1350cf5bc50458ba79cc93ff9e0e5fe3f1aeeb0jeff.schenk /* use srcX1 < srcX2 && dstX1 < dstX2 whenever possible to avoid GPU driver bugs */
c1350cf5bc50458ba79cc93ff9e0e5fe3f1aeeb0jeff.schenk pBlitter->pDispatch->BlitFramebufferEXT(srcX1, srcY1, srcX2, srcY2,
c1350cf5bc50458ba79cc93ff9e0e5fe3f1aeeb0jeff.schenk/* GL_TRIANGLE_FAN */
c1350cf5bc50458ba79cc93ff9e0e5fe3f1aeeb0jeff.schenkDECLINLINE(GLfloat*) crBltVtRectTFNormalized(const RTRECT *pRect, uint32_t normalX, uint32_t normalY, GLfloat* pBuff, uint32_t height)
c1350cf5bc50458ba79cc93ff9e0e5fe3f1aeeb0jeff.schenk /* going ccw:
c1350cf5bc50458ba79cc93ff9e0e5fe3f1aeeb0jeff.schenk * 1. (left;top) 4. (right;top)
c1350cf5bc50458ba79cc93ff9e0e5fe3f1aeeb0jeff.schenk * 2. (left;bottom) -> 3. (right;bottom) */
c1350cf5bc50458ba79cc93ff9e0e5fe3f1aeeb0jeff.schenk /* xLeft yTop */
c1350cf5bc50458ba79cc93ff9e0e5fe3f1aeeb0jeff.schenk pBuff[0] = ((float)pRect->xLeft)/((float)normalX);
c1350cf5bc50458ba79cc93ff9e0e5fe3f1aeeb0jeff.schenk pBuff[1] = ((float)(height ? height - pRect->yTop : pRect->yTop))/((float)normalY);
c1350cf5bc50458ba79cc93ff9e0e5fe3f1aeeb0jeff.schenk /* xLeft yBottom */
c1350cf5bc50458ba79cc93ff9e0e5fe3f1aeeb0jeff.schenk pBuff[3] = ((float)(height ? height - pRect->yBottom : pRect->yBottom))/((float)normalY);
c1350cf5bc50458ba79cc93ff9e0e5fe3f1aeeb0jeff.schenk /* xRight yBottom */
c1350cf5bc50458ba79cc93ff9e0e5fe3f1aeeb0jeff.schenk pBuff[4] = ((float)pRect->xRight)/((float)normalX);
c1350cf5bc50458ba79cc93ff9e0e5fe3f1aeeb0jeff.schenk /* xRight yTop */
c1350cf5bc50458ba79cc93ff9e0e5fe3f1aeeb0jeff.schenkDECLINLINE(GLfloat*) crBltVtRectsTFNormalized(const RTRECT *paRects, uint32_t cRects, uint32_t normalX, uint32_t normalY, GLfloat* pBuff, uint32_t height)
c1350cf5bc50458ba79cc93ff9e0e5fe3f1aeeb0jeff.schenk pBuff = crBltVtRectTFNormalized(&paRects[i], normalX, normalY, pBuff, height);
c1350cf5bc50458ba79cc93ff9e0e5fe3f1aeeb0jeff.schenkDECLINLINE(GLint*) crBltVtRectTF(const RTRECT *pRect, uint32_t normalX, uint32_t normalY, GLint* pBuff, uint32_t height)
c1350cf5bc50458ba79cc93ff9e0e5fe3f1aeeb0jeff.schenk /* xLeft yTop */
c1350cf5bc50458ba79cc93ff9e0e5fe3f1aeeb0jeff.schenk pBuff[1] = height ? height - pRect->yTop : pRect->yTop;
c1350cf5bc50458ba79cc93ff9e0e5fe3f1aeeb0jeff.schenk /* xLeft yBottom */
c1350cf5bc50458ba79cc93ff9e0e5fe3f1aeeb0jeff.schenk pBuff[3] = height ? height - pRect->yBottom : pRect->yBottom;
c1350cf5bc50458ba79cc93ff9e0e5fe3f1aeeb0jeff.schenk /* xRight yBottom */
c1350cf5bc50458ba79cc93ff9e0e5fe3f1aeeb0jeff.schenk /* xRight yTop */
c1350cf5bc50458ba79cc93ff9e0e5fe3f1aeeb0jeff.schenkDECLINLINE(GLubyte*) crBltVtFillRectIndicies(GLubyte *pIndex, GLubyte *piBase)
c1350cf5bc50458ba79cc93ff9e0e5fe3f1aeeb0jeff.schenk /* triangle 1 */
c1350cf5bc50458ba79cc93ff9e0e5fe3f1aeeb0jeff.schenk /* triangle 2 */
c1350cf5bc50458ba79cc93ff9e0e5fe3f1aeeb0jeff.schenk/* Indexed GL_TRIANGLES */
c1350cf5bc50458ba79cc93ff9e0e5fe3f1aeeb0jeff.schenkDECLINLINE(GLfloat*) crBltVtRectITNormalized(const RTRECT *pRect, uint32_t normalX, uint32_t normalY, GLfloat* pBuff, uint32_t height)
c1350cf5bc50458ba79cc93ff9e0e5fe3f1aeeb0jeff.schenk GLfloat* ret = crBltVtRectTFNormalized(pRect, normalX, normalY, pBuff, height);
c1350cf5bc50458ba79cc93ff9e0e5fe3f1aeeb0jeff.schenkDECLINLINE(GLint*) crBltVtRectIT(RTRECT *pRect, uint32_t normalX, uint32_t normalY, GLint* pBuff, GLubyte **ppIndex, GLubyte *piBase, uint32_t height)
c1350cf5bc50458ba79cc93ff9e0e5fe3f1aeeb0jeff.schenk GLint* ret = crBltVtRectTF(pRect, normalX, normalY, pBuff, height);
c1350cf5bc50458ba79cc93ff9e0e5fe3f1aeeb0jeff.schenk *ppIndex = crBltVtFillRectIndicies(*ppIndex, piBase);
c1350cf5bc50458ba79cc93ff9e0e5fe3f1aeeb0jeff.schenkDECLINLINE(GLuint) crBltVtGetNumVerticiesTF(GLuint cRects)
c1350cf5bc50458ba79cc93ff9e0e5fe3f1aeeb0jeff.schenk#define crBltVtGetNumVerticiesIT crBltVtGetNumVerticiesTF
c1350cf5bc50458ba79cc93ff9e0e5fe3f1aeeb0jeff.schenkDECLINLINE(GLuint) crBltVtGetNumIndiciesIT(GLuint cRects)
c1350cf5bc50458ba79cc93ff9e0e5fe3f1aeeb0jeff.schenkstatic GLfloat* crBltVtRectsITNormalized(const RTRECT *paRects, uint32_t cRects, uint32_t normalX, uint32_t normalY, GLfloat* pBuff, GLubyte **ppIndex, GLubyte *piBase, uint32_t height)
c1350cf5bc50458ba79cc93ff9e0e5fe3f1aeeb0jeff.schenk for (i = 0; i < cRects; ++i)
c1350cf5bc50458ba79cc93ff9e0e5fe3f1aeeb0jeff.schenk pBuff = crBltVtRectITNormalized(&paRects[i], normalX, normalY, pBuff, height);
c1350cf5bc50458ba79cc93ff9e0e5fe3f1aeeb0jeff.schenk for (i = 0; i < cRects; ++i)
c1350cf5bc50458ba79cc93ff9e0e5fe3f1aeeb0jeff.schenk pIndex = crBltVtFillRectIndicies(pIndex, piBase);
c1350cf5bc50458ba79cc93ff9e0e5fe3f1aeeb0jeff.schenkstatic void* crBltBufGet(PCR_BLITTER_BUFFER pBuffer, GLuint cbBuffer)
c1350cf5bc50458ba79cc93ff9e0e5fe3f1aeeb0jeff.schenk /* debugging: ensure we calculate proper buffer size */
c1350cf5bc50458ba79cc93ff9e0e5fe3f1aeeb0jeff.schenk crWarning("failed to allocate buffer of size %d", cbBuffer);
c1350cf5bc50458ba79cc93ff9e0e5fe3f1aeeb0jeff.schenkstatic void crBltCheckSetupViewport(PCR_BLITTER pBlitter, const RTRECTSIZE *pDstSize, bool fFBODraw)
c1350cf5bc50458ba79cc93ff9e0e5fe3f1aeeb0jeff.schenk bool fUpdateViewport = pBlitter->Flags.CurrentMuralChanged;
c1350cf5bc50458ba79cc93ff9e0e5fe3f1aeeb0jeff.schenk pBlitter->pDispatch->Ortho(0, pDstSize->cx, 0, pDstSize->cy, -1, 1);
c1350cf5bc50458ba79cc93ff9e0e5fe3f1aeeb0jeff.schenk pBlitter->pDispatch->Viewport(0, 0, pBlitter->CurrentSetSize.cx, pBlitter->CurrentSetSize.cy);
c1350cf5bc50458ba79cc93ff9e0e5fe3f1aeeb0jeff.schenkstatic DECLCALLBACK(int) crBltBlitTexBufImplDraw2D(PCR_BLITTER pBlitter, const VBOXVR_TEXTURE *pSrc, const RTRECT *paSrcRect, const RTRECTSIZE *pDstSize, const RTRECT *paDstRect, uint32_t cRects, uint32_t fFlags)
c1350cf5bc50458ba79cc93ff9e0e5fe3f1aeeb0jeff.schenk uint32_t srcHeight = (fFlags & CRBLT_F_INVERT_SRC_YCOORDS) ? pSrc->height : 0;
c1350cf5bc50458ba79cc93ff9e0e5fe3f1aeeb0jeff.schenk uint32_t dstHeight = (fFlags & CRBLT_F_INVERT_DST_YCOORDS) ? pDstSize->cy : 0;
c1350cf5bc50458ba79cc93ff9e0e5fe3f1aeeb0jeff.schenk crWarning("Unsupported texture target 0x%x", pSrc->target);
pVerticies = (GLfloat*)crBltBufGet(&pBlitter->Verticies, cElements * 2 * 2 * sizeof (*pVerticies) + cIndicies * sizeof (*pIndicies));
pTexCoords = crBltVtRectsITNormalized(paDstRect, cRects, 1, 1, pVerticies, &pIndicies, &iIdxBase, dstHeight);
return VINF_SUCCESS;
// crWarning("GL_EXT_framebuffer_blit not supported, will use Draw functions for blitting, which might be less efficient");
return VINF_SUCCESS;
return VERR_INVALID_STATE;
return VERR_INVALID_STATE;
if (pBlitter->CurrentMural.Base.id) /* <- pBlitter->CurrentMural.Base.id can be null if the blitter is in a "no-context" mode (see comments to BltInit for detail)*/
pBlitter->pDispatch->MakeCurrent(pBlitter->CurrentMural.Base.id, pBlitter->i32MakeCurrentUserData, pBlitter->CtxInfo.Base.id);
return VINF_SUCCESS;
return VINF_SUCCESS;
return rc;
static void crBltBlitTexBuf(PCR_BLITTER pBlitter, const VBOXVR_TEXTURE *pSrc, const RTRECT *paSrcRects, GLenum enmDstBuff, const RTRECTSIZE *pDstSize, const RTRECT *paDstRects, uint32_t cRects, uint32_t fFlags)
void CrBltBlitTexMural(PCR_BLITTER pBlitter, bool fBb, const VBOXVR_TEXTURE *pSrc, const RTRECT *paSrcRects, const RTRECT *paDstRects, uint32_t cRects, uint32_t fFlags)
crBltBlitTexBuf(pBlitter, pSrc, paSrcRects, fBb ? GL_BACK : GL_FRONT, &DstSize, paDstRects, cRects, fFlags);
void CrBltBlitTexTex(PCR_BLITTER pBlitter, const VBOXVR_TEXTURE *pSrc, const RTRECT *pSrcRect, const VBOXVR_TEXTURE *pDst, const RTRECT *pDstRect, uint32_t cRects, uint32_t fFlags)
pBlitter->pDispatch->FramebufferTexture2DEXT(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, pDst->target, pDst->hwid, 0);
// pBlitter->pDispatch->FramebufferTexture2DEXT(GL_DRAW_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_TEXTURE_2D, 0, 0);
// pBlitter->pDispatch->FramebufferTexture2DEXT(GL_DRAW_FRAMEBUFFER, GL_STENCIL_ATTACHMENT, GL_TEXTURE_2D, 0, 0);
pBlitter->pDispatch->FramebufferTexture2DEXT(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, pDst->target, 0, 0);
static int crBltImgInitBaseForTex(const VBOXVR_TEXTURE *pSrc, CR_BLITTER_IMG *pDst, GLenum enmFormat)
return VERR_NOT_IMPLEMENTED;
return VINF_SUCCESS;
return rc;
return VERR_NO_MEMORY;
#ifdef DEBUG_misha
return VINF_SUCCESS;
VBOXBLITTERDECL(int) CrBltImgGetTex(PCR_BLITTER pBlitter, const VBOXVR_TEXTURE *pSrc, GLenum enmFormat, CR_BLITTER_IMG *pDst)
return VERR_INVALID_STATE;
return rc;
#ifdef DEBUG_misha
return VINF_SUCCESS;
return VERR_INVALID_STATE;
return VERR_NOT_IMPLEMENTED;
* but seems like chromium does not support properly gl*Object versions of shader functions used with those extensions */
_ver \
_ext \
return NULL;
return NULL;
return NULL;
return NULL;
*puiProgram = 0;
if (!pStrFsShader)
return VERR_NOT_SUPPORTED;
if (!uiShader)
return VERR_NOT_SUPPORTED;
#ifndef DEBUG_misha
if(!compiled)
if (!pBuf)
#ifdef DEBUG_misha
if (compiled)
goto end;
if (!uiProgram)
goto end;
#ifndef DEBUG_misha
if(!linked)
if (!pBuf)
#ifdef DEBUG_misha
if (linked)
goto end;
uiProgram = 0;
end:
if (uiShader)
if (uiProgram)
if (pBuf)
return rc;
switch (enmTexTarget)
case GL_TEXTURE_2D:
case GL_TEXTURE_RECTANGLE_ARB:
switch (enmTexTarget)
case GL_TEXTURE_2D:
case GL_TEXTURE_RECTANGLE_ARB:
return NULL;
if (!puiProgram)
return VERR_INVALID_PARAMETER;
if (*puiProgram)
return VINF_SUCCESS;
return rc;
return rc;
return VINF_SUCCESS;
if (!uiProg)
return VERR_INVALID_STATE;
return VINF_SUCCESS;
if (!uiProg)
return rc;
return VINF_SUCCESS;
0, GL_STREAM_READ_ARB);
if (!tex)
return tex;
return VINF_SUCCESS;
return VERR_GENERAL_FAILURE;
return VINF_SUCCESS;
return rc;
if (!pvData)
return VERR_NO_MEMORY;
if (!pvData)
return VERR_GENERAL_FAILURE;
return VINF_SUCCESS;
/* release the texture data, the data remains cached in the CR_TEXDATA object until it is discarded with CrTdBltDataDiscard or CrTdBltDataCleanup */
return VERR_INVALID_STATE;
return VINF_SUCCESS;
return VERR_INVALID_STATE;
return VINF_SUCCESS;
return VINF_SUCCESS;
bool fEntered = false;
return rc;
fEntered = true;
if (fEntered)
return VINF_SUCCESS;
return VERR_INVALID_STATE;
return VINF_SUCCESS;
bool fEntered = false;
return rc;
fEntered = true;
if (fEntered)
return VINF_SUCCESS;
* the data remains cached in the CR_TEXDATA object until it is discarded with CrTdBltDataDiscard or CrTdBltDataCleanup.
VBOXBLITTERDECL(int) CrTdBltDataAcquire(PCR_TEXDATA pTex, GLenum enmFormat, bool fInverted, const CR_BLITTER_IMG**ppImg)
return VERR_INVALID_STATE;
if (pTex->Img.pvData && pTex->Img.enmFormat == enmFormat && !pTex->Flags.DataInverted == !fInverted)
return VINF_SUCCESS;
int rc;
if (fInverted)
return rc;
return rc;
return VINF_SUCCESS;