VirtualBox

Ignore:
Timestamp:
Sep 4, 2013 4:23:11 PM (11 years ago)
Author:
vboxsync
Message:

crOpenGL: basics for no-alpha blits

File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/VBox/GuestHost/OpenGL/util/blitter.cpp

    r46885 r48275  
    2828#include <iprt/mem.h>
    2929
    30 
    3130/* @param pCtxBase      - contains the blitter context info. Its value is treated differently depending on the fCreateNewCtx value
    3231 * @param fCreateNewCtx - if true  - the pCtxBase must NOT be NULL. its visualBits is used as a visual bits info for the new context,
     
    4746 *                                   This is needed because BlitFramebufferEXT is known to be often buggy, and glDrawXxx-based blits appear to be more reliable
    4847 */
    49 int CrBltInit(PCR_BLITTER pBlitter, const CR_BLITTER_CONTEXT *pCtxBase, bool fCreateNewCtx, bool fForceDrawBlt, SPUDispatchTable *pDispatch)
     48VBOXBLITTERDECL(int) CrBltInit(PCR_BLITTER pBlitter, const CR_BLITTER_CONTEXT *pCtxBase, bool fCreateNewCtx, bool fForceDrawBlt, const CR_GLSL_CACHE *pShaders, SPUDispatchTable *pDispatch)
    5049{
    5150    if (pCtxBase && pCtxBase->Base.id < 0)
     
    8079        pBlitter->Flags.CtxCreated = 1;
    8180    }
     81
     82    if (pShaders)
     83    {
     84        pBlitter->pGlslCache = pShaders;
     85        pBlitter->Flags.ShadersGloal = 1;
     86    }
     87    else
     88    {
     89        CrGlslInit(&pBlitter->LocalGlslCache, pDispatch);
     90        pBlitter->pGlslCache = &pBlitter->LocalGlslCache;
     91    }
     92
     93    return VINF_SUCCESS;
     94}
     95
     96VBOXBLITTERDECL(int) CrBltCleanup(PCR_BLITTER pBlitter, const CR_BLITTER_CONTEXT *pRestoreCtxInfo, const CR_BLITTER_WINDOW *pRestoreMural)
     97{
     98    if (CrBltIsEntered(pBlitter))
     99    {
     100        crWarning("CrBltBlitTexTex: blitter is entered");
     101        return VERR_INVALID_STATE;
     102    }
     103
     104    if (pBlitter->Flags.ShadersGloal || !CrGlslNeedsCleanup(&pBlitter->LocalGlslCache))
     105        return VINF_SUCCESS;
     106
     107    int rc = CrBltEnter(pBlitter, pRestoreCtxInfo, pRestoreMural);
     108    if (!RT_SUCCESS(rc))
     109    {
     110        crWarning("CrBltEnter failed, rc %d");
     111        return rc;
     112    }
     113
     114    CrGlslCleanup(&pBlitter->LocalGlslCache);
     115
     116    CrBltLeave(pBlitter);
    82117
    83118    return VINF_SUCCESS;
     
    596631    crBltCheckSetupViewport(pBlitter, pDstSize, enmDstBuff == GL_DRAW_FRAMEBUFFER);
    597632
    598     pBlitter->pfnBlt(pBlitter, pSrc, paSrcRects, pDstSize, paDstRects, cRects, fFlags);
     633    if (!(fFlags & CRBLT_F_NOALPHA))
     634        pBlitter->pfnBlt(pBlitter, pSrc, paSrcRects, pDstSize, paDstRects, cRects, fFlags);
     635    else
     636    {
     637        int rc = pBlitter->Flags.ShadersGloal ?
     638                CrGlslProgUseNoAlpha(pBlitter->pGlslCache, pSrc->target)
     639                :
     640                CrGlslProgUseGenNoAlpha(&pBlitter->LocalGlslCache, pSrc->target);
     641
     642        if (!RT_SUCCESS(rc))
     643        {
     644            crWarning("Failed to use no-alpha program rc!, falling back to default blit", rc);
     645            pBlitter->pfnBlt(pBlitter, pSrc, paSrcRects, pDstSize, paDstRects, cRects, fFlags);
     646            return;
     647        }
     648
     649        /* since we use shaders, we need to use draw commands rather than framebuffer blits.
     650         * force using draw-based blitting */
     651        crBltBlitTexBufImplDraw2D(pBlitter, pSrc, paSrcRects, pDstSize, paDstRects, cRects, fFlags);
     652
     653        Assert(pBlitter->Flags.ShadersGloal || &pBlitter->LocalGlslCache == pBlitter->pGlslCache);
     654
     655        CrGlslProgClear(pBlitter->pGlslCache);
     656    }
    599657}
    600658
     
    760818}
    761819
     820
     821VBOXBLITTERDECL(bool) CrGlslIsSupported(CR_GLSL_CACHE *pCache)
     822{
     823    if (pCache->glVersion == 0.)
     824    {
     825        const char * pszStr = (const char*)pCache->pDispatch->GetString(GL_VERSION);
     826        pCache->glVersion = crStrToFloat(pszStr);
     827        if (pCache->glVersion == 0.)
     828        {
     829            crWarning("pCache->glVersion is null!");
     830        }
     831    }
     832
     833    if (pCache->glVersion >= 2.0)
     834        return true;
     835
     836    /* @todo: we could also check for GL_ARB_shader_objects and GL_ARB_fragment_shader,
     837     * but seems like chromium does not support properly gl*Object versions of shader functions used with those extensions */
     838    return false;
     839}
     840
     841#define CR_GLSL_STR_V_120 "#version 120\n"
     842#define CR_GLSL_STR_EXT_TR "#extension GL_ARB_texture_rectangle : enable\n"
     843#define CR_GLSL_STR_TEX2D "texture2D"
     844#define CR_GLSL_STR_TEX2DRECT "texture2DRect"
     845
     846#define CR_GLSL_PATTERN_FS_NOALPHA(_ver, _ext, _tex) \
     847        _ver \
     848        _ext \
     849        "void main()\n" \
     850        "{\n" \
     851            "vec2 srcCoord = vec2(gl_TexCoord[0]);\n" \
     852            "gl_FragData[0].xyz = (" _tex "(0, srcCoord).xyz);\n" \
     853            "gl_FragData[0].w = 1.0;\n" \
     854        "}\n"
     855
     856static const char* crGlslGetFsStringNoAlpha(CR_GLSL_CACHE *pCache, GLenum enmTexTarget)
     857{
     858    if (!CrGlslIsSupported(pCache))
     859    {
     860        crWarning("CrGlslIsSupported is false");
     861        return NULL;
     862    }
     863
     864    if (pCache->glVersion >= 2.1)
     865    {
     866        if (enmTexTarget == GL_TEXTURE_2D)
     867            return CR_GLSL_PATTERN_FS_NOALPHA(CR_GLSL_STR_V_120, "", CR_GLSL_STR_TEX2D);
     868        else if (enmTexTarget == GL_TEXTURE_RECTANGLE_ARB)
     869            return CR_GLSL_PATTERN_FS_NOALPHA(CR_GLSL_STR_V_120, CR_GLSL_STR_EXT_TR, CR_GLSL_STR_TEX2DRECT);
     870
     871        crWarning("invalid enmTexTarget %#x", enmTexTarget);
     872        return NULL;
     873    }
     874    else if (pCache->glVersion >= 2.0)
     875    {
     876        if (enmTexTarget == GL_TEXTURE_2D)
     877            return CR_GLSL_PATTERN_FS_NOALPHA("", "", CR_GLSL_STR_TEX2D);
     878        else if (enmTexTarget == GL_TEXTURE_RECTANGLE_ARB)
     879            return CR_GLSL_PATTERN_FS_NOALPHA("", CR_GLSL_STR_EXT_TR, CR_GLSL_STR_TEX2DRECT);
     880
     881        crWarning("invalid enmTexTarget %#x", enmTexTarget);
     882        return NULL;
     883    }
     884
     885    crError("crGlslGetFsStringNoAlpha: we should not be here!");
     886    return NULL;
     887}
     888
     889static int crGlslProgGenNoAlpha(CR_GLSL_CACHE *pCache, GLenum enmTexTarget, GLuint *puiProgram)
     890{
     891    *puiProgram = 0;
     892
     893    const char*pStrFsShader = crGlslGetFsStringNoAlpha(pCache, enmTexTarget);
     894    if (!pStrFsShader)
     895    {
     896        crWarning("crGlslGetFsStringNoAlpha failed");
     897        return VERR_NOT_SUPPORTED;
     898    }
     899
     900    int rc = VINF_SUCCESS;
     901    GLchar * pBuf = NULL;
     902    GLuint uiProgram = 0;
     903    GLuint uiShader = pCache->pDispatch->CreateShader(GL_FRAGMENT_SHADER);
     904    if (!uiShader)
     905    {
     906        crWarning("CreateShader failed");
     907        return VERR_NOT_SUPPORTED;
     908    }
     909
     910    pCache->pDispatch->ShaderSource(uiShader, 1, &pStrFsShader, NULL);
     911
     912    pCache->pDispatch->CompileShader(uiShader);
     913
     914    GLint compiled = 0;
     915    pCache->pDispatch->GetShaderiv(uiShader, GL_COMPILE_STATUS, &compiled);
     916
     917#ifdef DEBUG_misha
     918    if(!compiled)
     919#endif
     920    {
     921        if (!pBuf)
     922            pBuf = (GLchar *)RTMemAlloc(16300);
     923        pCache->pDispatch->GetShaderInfoLog(uiShader, 16300, NULL, pBuf);
     924#ifdef DEBUG_misha
     925        if (compiled)
     926            crDebug("compile success:\n-------------------\n%d\n--------\n", pBuf);
     927        else
     928#endif
     929        {
     930            crWarning("compile FAILURE:\n-------------------\n%d\n--------\n", pBuf);
     931            rc = VERR_NOT_SUPPORTED;
     932            goto end;
     933        }
     934    }
     935
     936    Assert(compiled);
     937
     938    uiProgram = pCache->pDispatch->CreateProgram();
     939    if (!uiProgram)
     940    {
     941        rc = VERR_NOT_SUPPORTED;
     942        goto end;
     943    }
     944
     945    pCache->pDispatch->AttachShader(uiProgram, uiShader);
     946
     947    pCache->pDispatch->LinkProgram(uiProgram);
     948
     949    GLint linked;
     950    pCache->pDispatch->GetProgramiv(uiProgram, GL_LINK_STATUS, &linked);
     951#ifdef DEBUG_misha
     952    if(!linked)
     953#endif
     954    {
     955        if (!pBuf)
     956            pBuf = (GLchar *)RTMemAlloc(16300);
     957        pCache->pDispatch->GetProgramInfoLog(uiProgram, 16300, NULL, pBuf);
     958#ifdef DEBUG_misha
     959        if (linked)
     960            crDebug("link success:\n-------------------\n%d\n--------\n", pBuf);
     961        else
     962#endif
     963        {
     964            crWarning("link FAILURE:\n-------------------\n%d\n--------\n", pBuf);
     965            rc = VERR_NOT_SUPPORTED;
     966            goto end;
     967        }
     968    }
     969
     970    Assert(linked);
     971
     972    *puiProgram = uiProgram;
     973
     974    /* avoid end finalizer from cleaning it */
     975    uiProgram = 0;
     976
     977    end:
     978    if (uiShader)
     979        pCache->pDispatch->DeleteShader(uiShader);
     980    if (uiProgram)
     981        pCache->pDispatch->DeleteProgram(uiProgram);
     982    if (pBuf)
     983        RTMemFree(pBuf);
     984    return rc;
     985}
     986
     987DECLINLINE(GLuint) crGlslProgGetNoAlpha(const CR_GLSL_CACHE *pCache, GLenum enmTexTarget)
     988{
     989    switch (enmTexTarget)
     990    {
     991        case GL_TEXTURE_2D:
     992            return  pCache->uNoAlpha2DProg;
     993        case GL_TEXTURE_RECTANGLE_ARB:
     994            return pCache->uNoAlpha2DRectProg;
     995        default:
     996            crWarning("invalid tex enmTexTarget %#x", enmTexTarget);
     997            return 0;
     998    }
     999}
     1000
     1001DECLINLINE(GLuint*) crGlslProgGetNoAlphaPtr(CR_GLSL_CACHE *pCache, GLenum enmTexTarget)
     1002{
     1003    switch (enmTexTarget)
     1004    {
     1005        case GL_TEXTURE_2D:
     1006            return  &pCache->uNoAlpha2DProg;
     1007        case GL_TEXTURE_RECTANGLE_ARB:
     1008            return &pCache->uNoAlpha2DRectProg;
     1009        default:
     1010            crWarning("invalid tex enmTexTarget %#x", enmTexTarget);
     1011            return NULL;
     1012    }
     1013}
     1014
     1015VBOXBLITTERDECL(int) CrGlslProgGenNoAlpha(CR_GLSL_CACHE *pCache, GLenum enmTexTarget)
     1016{
     1017    GLuint*puiProgram = crGlslProgGetNoAlphaPtr(pCache, enmTexTarget);
     1018    if (!puiProgram)
     1019        return VERR_INVALID_PARAMETER;
     1020
     1021    if (*puiProgram)
     1022        return VINF_SUCCESS;
     1023
     1024    return crGlslProgGenNoAlpha(pCache, enmTexTarget, puiProgram);
     1025}
     1026
     1027VBOXBLITTERDECL(int) CrGlslProgGenAllNoAlpha(CR_GLSL_CACHE *pCache)
     1028{
     1029    int rc = CrGlslProgGenNoAlpha(pCache, GL_TEXTURE_2D);
     1030    if (!RT_SUCCESS(rc))
     1031    {
     1032        crWarning("CrGlslProgGenNoAlpha GL_TEXTURE_2D failed rc %d", rc);
     1033        return rc;
     1034    }
     1035
     1036    rc = CrGlslProgGenNoAlpha(pCache, GL_TEXTURE_RECTANGLE_ARB);
     1037    if (!RT_SUCCESS(rc))
     1038    {
     1039        crWarning("CrGlslProgGenNoAlpha GL_TEXTURE_RECTANGLE failed rc %d", rc);
     1040        return rc;
     1041    }
     1042
     1043    return VINF_SUCCESS;
     1044}
     1045
     1046VBOXBLITTERDECL(void) CrGlslProgClear(const CR_GLSL_CACHE *pCache)
     1047{
     1048    pCache->pDispatch->UseProgram(0);
     1049}
     1050
     1051VBOXBLITTERDECL(int) CrGlslProgUseNoAlpha(const CR_GLSL_CACHE *pCache, GLenum enmTexTarget)
     1052{
     1053    GLuint uiProg = crGlslProgGetNoAlpha(pCache, enmTexTarget);
     1054    if (!uiProg)
     1055    {
     1056        crWarning("request to use inexistent program!");
     1057        return VERR_INVALID_STATE;
     1058    }
     1059
     1060    Assert(uiProg);
     1061
     1062    pCache->pDispatch->UseProgram(uiProg);
     1063
     1064    return VINF_SUCCESS;
     1065}
     1066
     1067VBOXBLITTERDECL(int) CrGlslProgUseGenNoAlpha(CR_GLSL_CACHE *pCache, GLenum enmTexTarget)
     1068{
     1069    GLuint uiProg = crGlslProgGetNoAlpha(pCache, enmTexTarget);
     1070    if (!uiProg)
     1071    {
     1072        int rc = CrGlslProgGenNoAlpha(pCache, enmTexTarget);
     1073        if (!RT_SUCCESS(rc))
     1074        {
     1075            crWarning("CrGlslProgGenNoAlpha failed, rc %d", rc);
     1076            return rc;
     1077        }
     1078
     1079        uiProg = crGlslProgGetNoAlpha(pCache, enmTexTarget);
     1080        CRASSERT(uiProg);
     1081    }
     1082
     1083    Assert(uiProg);
     1084
     1085    pCache->pDispatch->UseProgram(uiProg);
     1086
     1087    return VINF_SUCCESS;
     1088}
     1089
     1090VBOXBLITTERDECL(bool) CrGlslNeedsCleanup(CR_GLSL_CACHE *pCache)
     1091{
     1092    return pCache->uNoAlpha2DProg || pCache->uNoAlpha2DRectProg;
     1093}
     1094
     1095VBOXBLITTERDECL(void) CrGlslCleanup(CR_GLSL_CACHE *pCache)
     1096{
     1097    if (pCache->uNoAlpha2DProg)
     1098    {
     1099        pCache->pDispatch->DeleteProgram(pCache->uNoAlpha2DProg);
     1100        pCache->uNoAlpha2DProg = 0;
     1101    }
     1102
     1103    if (pCache->uNoAlpha2DRectProg)
     1104    {
     1105        pCache->pDispatch->DeleteProgram(pCache->uNoAlpha2DRectProg);
     1106        pCache->uNoAlpha2DRectProg = 0;
     1107    }
     1108}
     1109
     1110VBOXBLITTERDECL(void) CrGlslTerm(CR_GLSL_CACHE *pCache)
     1111{
     1112    CRASSERT(!CrGlslNeedsCleanup(pCache));
     1113
     1114    CrGlslCleanup(pCache);
     1115
     1116    /* sanity */
     1117    memset(pCache, 0, sizeof (*pCache));
     1118}
Note: See TracChangeset for help on using the changeset viewer.

© 2024 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette