/* $Id$ */ /** @file * Blitter API */ /* * 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; * you can redistribute it and/or modify it under the terms of the GNU * 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. */ #ifndef ___cr_blitter_h__ #define ___cr_blitter_h__ #include #include #include "cr_spu.h" #include "cr_vreg.h" #ifndef IN_RING0 # define VBOXBLITTERDECL(_type) DECLEXPORT(_type) #else # define VBOXBLITTERDECL(_type) RTDECL(_type) #endif RT_C_DECLS_BEGIN typedef struct CR_BLITTER_IMG { void *pvData; GLuint cbData; GLenum enmFormat; GLuint width, height; GLuint bpp; GLuint pitch; } CR_BLITTER_IMG, *PCR_BLITTER_IMG; VBOXBLITTERDECL(void) CrMClrFillImgRect(CR_BLITTER_IMG *pDst, const RTRECT *pCopyRect, uint32_t u32Color); VBOXBLITTERDECL(void) CrMClrFillImg(CR_BLITTER_IMG *pImg, uint32_t cRects, const RTRECT *pRects, uint32_t u32Color); VBOXBLITTERDECL(void) CrMBltImgRect(const CR_BLITTER_IMG *pSrc, const RTPOINT *pSrcDataPoint, bool fSrcInvert, const RTRECT *pCopyRect, CR_BLITTER_IMG *pDst); VBOXBLITTERDECL(void) CrMBltImg(const CR_BLITTER_IMG *pSrc, const RTPOINT *pPos, uint32_t cRects, const RTRECT *pRects, CR_BLITTER_IMG *pDst); VBOXBLITTERDECL(void) CrMBltImgRectScaled(const CR_BLITTER_IMG *pSrc, const RTPOINT *pPos, bool fSrcInvert, const RTRECT *pCopyRect, float strX, float strY, CR_BLITTER_IMG *pDst); VBOXBLITTERDECL(void) CrMBltImgScaled(const CR_BLITTER_IMG *pSrc, const RTRECTSIZE *pSrcRectSize, const RTRECT *pDstRect, uint32_t cRects, const RTRECT *pRects, CR_BLITTER_IMG *pDst); /* GLSL Cache */ typedef struct CR_GLSL_CACHE { int iGlVersion; GLuint uNoAlpha2DProg; GLuint uNoAlpha2DRectProg; SPUDispatchTable *pDispatch; } CR_GLSL_CACHE; DECLINLINE(void) CrGlslInit(CR_GLSL_CACHE *pCache, SPUDispatchTable *pDispatch) { memset(pCache, 0, sizeof (*pCache)); pCache->pDispatch = pDispatch; } DECLINLINE(bool) CrGlslIsInited(const CR_GLSL_CACHE *pCache) { return !!pCache->pDispatch; } /* clients should set proper context before calling these funcs */ VBOXBLITTERDECL(bool) CrGlslIsSupported(CR_GLSL_CACHE *pCache); VBOXBLITTERDECL(int) CrGlslProgGenAllNoAlpha(CR_GLSL_CACHE *pCache); VBOXBLITTERDECL(int) CrGlslProgGenNoAlpha(CR_GLSL_CACHE *pCache, GLenum enmTexTarget); VBOXBLITTERDECL(int) CrGlslProgUseGenNoAlpha(CR_GLSL_CACHE *pCache, GLenum enmTexTarget); VBOXBLITTERDECL(int) CrGlslProgUseNoAlpha(const CR_GLSL_CACHE *pCache, GLenum enmTexTarget); VBOXBLITTERDECL(void) CrGlslProgClear(const CR_GLSL_CACHE *pCache); VBOXBLITTERDECL(bool) CrGlslNeedsCleanup(const CR_GLSL_CACHE *pCache); VBOXBLITTERDECL(void) CrGlslCleanup(CR_GLSL_CACHE *pCache); VBOXBLITTERDECL(void) CrGlslTerm(CR_GLSL_CACHE *pCache); /* BLITTER */ typedef struct CR_BLITTER_BUFFER { GLuint cbBuffer; GLvoid * pvBuffer; } CR_BLITTER_BUFFER, *PCR_BLITTER_BUFFER; typedef union CR_BLITTER_FLAGS { struct { uint32_t Initialized : 1; uint32_t CtxCreated : 1; uint32_t SupportsFBO : 1; uint32_t SupportsPBO : 1; uint32_t CurrentMuralChanged : 1; uint32_t LastWasFBODraw : 1; uint32_t ForceDrawBlit : 1; uint32_t ShadersGloal : 1; uint32_t Reserved : 24; }; uint32_t Value; } CR_BLITTER_FLAGS, *PCR_BLITTER_FLAGS; struct CR_BLITTER; typedef DECLCALLBACK(int) FNCRBLT_BLITTER(struct CR_BLITTER *pBlitter, const VBOXVR_TEXTURE *pSrc, const RTRECT *paSrcRect, const RTRECTSIZE *pDstSize, const RTRECT *paDstRect, uint32_t cRects, uint32_t fFlags); typedef FNCRBLT_BLITTER *PFNCRBLT_BLITTER; typedef struct CR_BLITTER_SPUITEM { int id; GLint visualBits; } CR_BLITTER_SPUITEM, *PCR_BLITTER_SPUITEM; typedef struct CR_BLITTER_CONTEXT { CR_BLITTER_SPUITEM Base; } CR_BLITTER_CONTEXT, *PCR_BLITTER_CONTEXT; typedef struct CR_BLITTER_WINDOW { CR_BLITTER_SPUITEM Base; GLuint width, height; } CR_BLITTER_WINDOW, *PCR_BLITTER_WINDOW; typedef struct CR_BLITTER { GLuint idFBO; CR_BLITTER_FLAGS Flags; uint32_t cEnters; PFNCRBLT_BLITTER pfnBlt; CR_BLITTER_BUFFER Verticies; CR_BLITTER_BUFFER Indicies; RTRECTSIZE CurrentSetSize; CR_BLITTER_WINDOW CurrentMural; CR_BLITTER_CONTEXT CtxInfo; int32_t i32MakeCurrentUserData; SPUDispatchTable *pDispatch; const CR_GLSL_CACHE *pGlslCache; CR_GLSL_CACHE LocalGlslCache; } CR_BLITTER, *PCR_BLITTER; DECLINLINE(GLboolean) CrBltIsInitialized(PCR_BLITTER pBlitter) { return !!pBlitter->pDispatch; } VBOXBLITTERDECL(int) CrBltInit(PCR_BLITTER pBlitter, const CR_BLITTER_CONTEXT *pCtxBase, bool fCreateNewCtx, bool fForceDrawBlt, const CR_GLSL_CACHE *pShaders, SPUDispatchTable *pDispatch); VBOXBLITTERDECL(void) CrBltTerm(PCR_BLITTER pBlitter); VBOXBLITTERDECL(int) CrBltCleanup(PCR_BLITTER pBlitter); DECLINLINE(GLboolean) CrBltSupportsTexTex(PCR_BLITTER pBlitter) { return pBlitter->Flags.SupportsFBO; } DECLINLINE(GLboolean) CrBltIsEntered(PCR_BLITTER pBlitter) { return !!pBlitter->cEnters; } DECLINLINE(GLint) CrBltGetVisBits(PCR_BLITTER pBlitter) { return pBlitter->CtxInfo.Base.visualBits; } DECLINLINE(GLboolean) CrBltIsEverEntered(PCR_BLITTER pBlitter) { return !!pBlitter->Flags.Initialized; } DECLINLINE(void) CrBltSetMakeCurrentUserData(PCR_BLITTER pBlitter, int32_t i32MakeCurrentUserData) { pBlitter->i32MakeCurrentUserData = i32MakeCurrentUserData; } VBOXBLITTERDECL(int) CrBltMuralSetCurrentInfo(PCR_BLITTER pBlitter, const CR_BLITTER_WINDOW *pMural); DECLINLINE(const CR_BLITTER_WINDOW *) CrBltMuralGetCurrentInfo(PCR_BLITTER pBlitter) { return &pBlitter->CurrentMural; } VBOXBLITTERDECL(void) CrBltCheckUpdateViewport(PCR_BLITTER pBlitter); VBOXBLITTERDECL(void) CrBltLeave(PCR_BLITTER pBlitter); VBOXBLITTERDECL(int) CrBltEnter(PCR_BLITTER pBlitter); VBOXBLITTERDECL(void) CrBltBlitTexMural(PCR_BLITTER pBlitter, bool fBb, const VBOXVR_TEXTURE *pSrc, const RTRECT *paSrcRects, const RTRECT *paDstRects, uint32_t cRects, uint32_t fFlags); VBOXBLITTERDECL(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); VBOXBLITTERDECL(int) CrBltImgGetTex(PCR_BLITTER pBlitter, const VBOXVR_TEXTURE *pSrc, GLenum enmFormat, CR_BLITTER_IMG *pDst); VBOXBLITTERDECL(int) CrBltImgGetMural(PCR_BLITTER pBlitter, bool fBb, CR_BLITTER_IMG *pDst); VBOXBLITTERDECL(void) CrBltImgFree(PCR_BLITTER pBlitter, CR_BLITTER_IMG *pDst); VBOXBLITTERDECL(void) CrBltPresent(PCR_BLITTER pBlitter); /* */ struct CR_TEXDATA; typedef DECLCALLBACK(void) FNCRTEXDATA_RELEASED(struct CR_TEXDATA *pTexture); typedef FNCRTEXDATA_RELEASED *PFNCRTEXDATA_RELEASED; typedef union CR_TEXDATA_FLAGS { struct { uint32_t DataValid : 1; uint32_t DataAcquired : 1; uint32_t DataInverted : 1; uint32_t Entered : 1; uint32_t Reserved : 28; }; uint32_t Value; } CR_TEXDATA_FLAGS, *PCR_TEXDATA_FLAGS; typedef struct CR_TEXDATA { VBOXVR_TEXTURE Tex; volatile uint32_t cRefs; /* fields specific to texture data download */ uint32_t idInvertTex; uint32_t idPBO; CR_TEXDATA_FLAGS Flags; PCR_BLITTER pBlitter; CR_BLITTER_IMG Img; /*dtor*/ PFNCRTEXDATA_RELEASED pfnTextureReleased; struct CR_TEXDATA *pScaledCache; } CR_TEXDATA, *PCR_TEXDATA; DECLINLINE(void) CrTdInit(PCR_TEXDATA pTex, const VBOXVR_TEXTURE *pVrTex, PCR_BLITTER pBlitter, PFNCRTEXDATA_RELEASED pfnTextureReleased) { memset(pTex, 0, sizeof (*pTex)); pTex->Tex = *pVrTex; pTex->cRefs = 1; pTex->pBlitter = pBlitter; pTex->pfnTextureReleased = pfnTextureReleased; } DECLINLINE(const VBOXVR_TEXTURE*) CrTdTexGet(const CR_TEXDATA *pTex) { return &pTex->Tex; } DECLINLINE(PCR_BLITTER) CrTdBlitterGet(CR_TEXDATA *pTex) { return pTex->pBlitter; } DECLINLINE(int) CrTdBltEnter(PCR_TEXDATA pTex) { int rc; if (pTex->Flags.Entered) return VERR_INVALID_STATE; rc = CrBltEnter(pTex->pBlitter); if (!RT_SUCCESS(rc)) { WARN(("CrBltEnter failed rc %d", rc)); return rc; } pTex->Flags.Entered = 1; return VINF_SUCCESS; } DECLINLINE(bool) CrTdBltIsEntered(PCR_TEXDATA pTex) { return pTex->Flags.Entered; } DECLINLINE(void) CrTdBltLeave(PCR_TEXDATA pTex) { if (!pTex->Flags.Entered) { WARN(("invalid Blt Leave")); return; } CrBltLeave(pTex->pBlitter); pTex->Flags.Entered = 0; } /* the CrTdBltXxx calls are done with the entered blitter */ /* acquire the texture data, returns the cached data in case it is cached. * the data remains cached in the CR_TEXDATA object until it is discarded with CrTdBltDataFree or CrTdBltDataCleanup. * */ VBOXBLITTERDECL(int) CrTdBltDataAcquire(PCR_TEXDATA pTex, GLenum enmFormat, bool fInverted, const CR_BLITTER_IMG**ppImg); VBOXBLITTERDECL(int) CrTdBltDataAcquireScaled(PCR_TEXDATA pTex, GLenum enmFormat, bool fInverted, uint32_t width, uint32_t height, const CR_BLITTER_IMG**ppImg); VBOXBLITTERDECL(int) CrTdBltDataReleaseScaled(PCR_TEXDATA pTex, const CR_BLITTER_IMG *pImg); VBOXBLITTERDECL(void) CrTdBltScaleCacheMoveTo(PCR_TEXDATA pTex, PCR_TEXDATA pDstTex); /* release the texture data, the data remains cached in the CR_TEXDATA object until it is discarded with CrTdBltDataFree or CrTdBltDataCleanup */ VBOXBLITTERDECL(int) CrTdBltDataRelease(PCR_TEXDATA pTex); /* discard the texture data cached with previous CrTdBltDataAcquire. * Must be called wit data released (CrTdBltDataRelease) */ VBOXBLITTERDECL(int) CrTdBltDataFree(PCR_TEXDATA pTex); VBOXBLITTERDECL(int) CrTdBltDataFreeNe(PCR_TEXDATA pTex); VBOXBLITTERDECL(void) CrTdBltDataInvalidateNe(PCR_TEXDATA pTex); /* does same as CrTdBltDataFree, and in addition cleans up. * this is kind of a texture destructor, which clients should call on texture object destruction, e.g. from the PFNCRTEXDATA_RELEASED callback */ VBOXBLITTERDECL(int) CrTdBltDataCleanup(PCR_TEXDATA pTex); VBOXBLITTERDECL(int) CrTdBltDataCleanupNe(PCR_TEXDATA pTex); DECLINLINE(uint32_t) CrTdAddRef(PCR_TEXDATA pTex) { return ASMAtomicIncU32(&pTex->cRefs); } DECLINLINE(uint32_t) CrTdRelease(PCR_TEXDATA pTex) { uint32_t cRefs = ASMAtomicDecU32(&pTex->cRefs); if (!cRefs) { if (pTex->pfnTextureReleased) pTex->pfnTextureReleased(pTex); else CrTdBltDataCleanupNe(pTex); } return cRefs; } RT_C_DECLS_END #endif /* #ifndef ___cr_blitter_h__ */