blitter.cpp revision 3cff6708e3c84eab9e98af93caa8c94bfbb37317
/* $Id$ */
/** @file
* Blitter API implementation
*/
/*
* Copyright (C) 2013 Oracle Corporation
*
* This file is part of VirtualBox Open Source Edition (OSE), as
* available from http://www.virtualbox.org. This file is free software;
* General Public License (GPL) as published by the Free Software
* Foundation, in version 2 as it comes in the "COPYING" file of the
* VirtualBox OSE distribution. VirtualBox OSE is distributed in the
* hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
*/
#include "cr_blitter.h"
#include "cr_spu.h"
#include "chromium.h"
#include "cr_error.h"
#include "cr_net.h"
#include "cr_rand.h"
#include "cr_mem.h"
#include "cr_string.h"
/* @param pCtxBase - contains the blitter context info. Its value is treated differently depending on the fCreateNewCtx value
* @param fCreateNewCtx - if true - the pCtxBase must NOT be NULL. its visualBits is used as a visual bits info for the new context,
* its id field is used to specified the shared context id to be used for blitter context.
* The id can be null to specify no shared context is needed
* if false - if pCtxBase is NOT null AND its id field is NOT null -
* specified the blitter context to be used
* blitter treats it as if it has default ogl state.
* otherwise -
* the blitter works in a "no-context" mode, i.e. a caller is responsible
* to making a proper context current before calling the blitter.
* must be set before doing BltEnter, and ResoreContext info is ignored in that case.
* Also note that blitter caches the current window info, and assumes the current context's values are preserved
* wrt that window before the calls, so if one uses different contexts for one blitter,
* the blitter current window values must be explicitly reset by doing CrBltMuralSetCurrent(pBlitter, NULL)
* @param fForceDrawBlt - if true - forces the blitter to always use glDrawXxx-based blits even if GL_EXT_framebuffer_blit.
* This is needed because BlitFramebufferEXT is known to be often buggy, and glDrawXxx-based blits appear to be more reliable
*/
int CrBltInit(PCR_BLITTER pBlitter, const CR_BLITTER_CONTEXT *pCtxBase, bool fCreateNewCtx, bool fForceDrawBlt, SPUDispatchTable *pDispatch)
{
{
crWarning("Default share context not initialized!");
return VERR_INVALID_PARAMETER;
}
if (!pCtxBase && fCreateNewCtx)
{
crWarning("pCtxBase is zero while fCreateNewCtx is set!");
return VERR_INVALID_PARAMETER;
}
if (pCtxBase)
if (fCreateNewCtx)
{
pBlitter->CtxInfo.Base.id = pDispatch->CreateContext("", pCtxBase->Base.visualBits, pCtxBase->Base.id);
{
crWarning("CreateContext failed!");
return VERR_GENERAL_FAILURE;
}
}
return VINF_SUCCESS;
}
{
}
{
if (pMural)
{
return VINF_SUCCESS;
}
else
{
return VINF_SUCCESS;
}
if (!CrBltIsEntered(pBlitter))
return VINF_SUCCESS;
{
crWarning("setting current mural for entered no-context blitter");
return VERR_INVALID_STATE;
}
if (pMural)
pBlitter->pDispatch->MakeCurrent(pMural->Base.id, pBlitter->i32MakeCurrentUserData, pBlitter->CtxInfo.Base.id);
else
return VINF_SUCCESS;
}
static 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)
{
pBlitter->pDispatch->FramebufferTexture2DEXT(GL_READ_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, pSrc->target, pSrc->hwid, 0);
{
if (CRBLT_F_INVERT_SRC_YCOORDS & fFlags)
{
}
else
{
}
if (CRBLT_F_INVERT_DST_YCOORDS & fFlags)
{
}
else
{
}
{
{
/* use srcY1 < srcY2 && dstY1 < dstY2 whenever possible to avoid GPU driver bugs */
}
}
{
{
/* use srcX1 < srcX2 && dstX1 < dstX2 whenever possible to avoid GPU driver bugs */
}
}
}
return VINF_SUCCESS;
}
/* GL_TRIANGLE_FAN */
DECLINLINE(GLfloat*) crBltVtRectTFNormalized(const RTRECT *pRect, uint32_t normalX, uint32_t normalY, GLfloat* pBuff, uint32_t height)
{
/* going ccw:
* 1. (left;top) 4. (right;top)
* | ^
* > |
* 2. (left;bottom) -> 3. (right;bottom) */
/* xLeft yTop */
/* xLeft yBottom */
/* xRight yBottom */
/* xRight yTop */
return &pBuff[8];
}
DECLINLINE(GLint*) crBltVtRectTF(const RTRECT *pRect, uint32_t normalX, uint32_t normalY, GLint* pBuff, uint32_t height)
{
/* xLeft yTop */
/* xLeft yBottom */
/* xRight yBottom */
/* xRight yTop */
return &pBuff[8];
}
{
/* triangle 1 */
/* triangle 2 */
return pIndex + 6;
}
/* Indexed GL_TRIANGLES */
DECLINLINE(GLfloat*) crBltVtRectITNormalized(const RTRECT *pRect, uint32_t normalX, uint32_t normalY, GLfloat* pBuff, uint32_t height)
{
return ret;
}
DECLINLINE(GLint*) crBltVtRectIT(RTRECT *pRect, uint32_t normalX, uint32_t normalY, GLint* pBuff, GLubyte **ppIndex, GLubyte *piBase, uint32_t height)
{
if (ppIndex)
return ret;
}
{
return cRects * 4;
}
{
return 6 * cRects;
}
static GLfloat* crBltVtRectsITNormalized(const RTRECT *paRects, uint32_t cRects, uint32_t normalX, uint32_t normalY, GLfloat* pBuff, GLubyte **ppIndex, GLubyte *piBase, uint32_t height)
{
uint32_t i;
for (i = 0; i < cRects; ++i)
{
}
if (ppIndex)
{
for (i = 0; i < cRects; ++i)
{
}
}
return pBuff;
}
{
{
{
}
#ifndef DEBUG_misha
/* debugging: ensure we calculate proper buffer size */
cbBuffer += 16;
#endif
else
{
}
}
}
static void crBltCheckSetupViewport(PCR_BLITTER pBlitter, const RTRECTSIZE *pDstSize, bool fFBODraw)
{
{
fUpdateViewport = true;
}
if (fUpdateViewport)
{
}
}
static 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)
{
{
case GL_TEXTURE_2D:
{
break;
}
case GL_TEXTURE_RECTANGLE_ARB:
{
normalX = 1;
normalY = 1;
break;
}
default:
{
return VERR_INVALID_PARAMETER;
}
}
if (cRects == 1)
{
/* just optimizatino to draw a single rect with GL_TRIANGLE_FAN */
bool bUseSameVerticies = paSrcRect == paDstRect && normalX == 1 && normalY == 1 && srcHeight == dstHeight;
if (bUseSameVerticies)
{
}
else
{
}
}
else
{
bool bUseSameVerticies = paSrcRect == paDstRect && normalX == 1 && normalY == 1 && srcHeight == dstHeight;
if (bUseSameVerticies)
{
pVerticies = (GLfloat*)crBltBufGet(&pBlitter->Verticies, cElements * 2 * sizeof (*pVerticies) + cIndicies * sizeof (*pIndicies));
crBltVtRectsITNormalized(paDstRect, cRects, normalX, normalY, pVerticies, &pIndicies, &iIdxBase, dstHeight);
}
else
{
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;
}
{
{
}
else
crWarning("GL_EXT_framebuffer_object not supported, blitter can only blit to window");
/* BlitFramebuffer seems to be buggy on Intel,
* try always glDrawXxx for now */
{
}
else
{
// crWarning("GL_EXT_framebuffer_blit not supported, will use Draw functions for blitting, which might be less efficient");
}
/* defaults. but just in case */
return VINF_SUCCESS;
}
{
{
}
{
{
pBlitter->pDispatch->MakeCurrent(pBlitter->pRestoreMural->Base.id, 0, pBlitter->pRestoreCtxInfo->Base.id);
}
else
{
}
}
}
int CrBltEnter(PCR_BLITTER pBlitter, const CR_BLITTER_CONTEXT *pRestoreCtxInfo, const CR_BLITTER_WINDOW *pRestoreMural)
{
{
crWarning("current mural not initialized!");
return VERR_INVALID_STATE;
}
if (CrBltIsEntered(pBlitter))
{
crWarning("blitter is entered already!");
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);
}
else
{
if (pRestoreCtxInfo)
{
crWarning("pRestoreCtxInfo is not NULL for \"no-context\" blitter");
}
}
if (pRestoreCtxInfo)
{
}
else
{
}
return VINF_SUCCESS;
if (RT_SUCCESS(rc))
{
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, const VBOXVR_TEXTURE *pSrc, const RTRECT *paSrcRects, const RTRECT *paDstRects, uint32_t cRects, uint32_t 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);
}
{
else
}