Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 2ad8ec50 authored by Mathias Agopian's avatar Mathias Agopian
Browse files

fix [2071412] work around mdp 32-bits fade limitation

in the case where we fade a 32-bits surface (ie: GL_MODULATE w/ a,a,a,a + blending),
we first make a copy of the background into a RGB buffer, then we blend the 32-bits
surface as usual (without the alpha component), and finally blend the copy of
the background on top with 1-a. This uses a lot of bandwidth, but no CPU time.
parent d5493f3f
Loading
Loading
Loading
Loading
+68 −11
Original line number Diff line number Diff line
@@ -154,6 +154,8 @@ static bool copybit(GLint x, GLint y,
        int transform,
        ogles_context_t* c)
{
    status_t err = NO_ERROR;

    // We assume checkContext has already been called and has already
    // returned true.

@@ -200,6 +202,7 @@ static bool copybit(GLint x, GLint y,
    
    const uint32_t enables = c->rasterizer.state.enables;
    int planeAlpha = 255;
    bool alphaPlaneWorkaround = false;
    static const int tmu = 0;
    texture_t& tev(c->rasterizer.state.texture[tmu]);
    int32_t opFormat = textureObject->surface.format;
@@ -259,9 +262,10 @@ static bool copybit(GLint x, GLint y,
            if (c->currentColorClamped.r == c->currentColorClamped.a &&
                c->currentColorClamped.g == c->currentColorClamped.a &&
                c->currentColorClamped.b == c->currentColorClamped.a) {
                // TODO: Need to emulate: RGBA source, color={a,a,a,a} / premult
                // and RGBA source, color={1,1,1,a} / regular-blending
                // (both are equivalent)
                // TODO: RGBA source, color={1,1,1,a} / regular-blending
                // is equivalent
                alphaPlaneWorkaround = true;
                break;
            }
        }
        LOGD_IF(DEBUG_COPYBIT, "GGL_MODULATE");
@@ -331,13 +335,13 @@ static bool copybit(GLint x, GLint y,
                    tmp_w, tmp_h, src.format,
                    GraphicBuffer::USAGE_HW_2D);

        status_t err = tempBitmap->initCheck();
        err = tempBitmap->initCheck();
        if (err == NO_ERROR) {
            copybit_image_t tmp_dst;
            copybit_rect_t tmp_rect;
            tmp_dst.w = tmp_w;
            tmp_dst.h = tmp_h;
            tmp_dst.format = src.format;
            tmp_dst.format = tempBitmap->format;
            tmp_dst.handle = (native_handle_t*)tempBitmap->getNativeBuffer()->handle;
            tmp_rect.l = 0;
            tmp_rect.t = 0;
@@ -359,13 +363,66 @@ static bool copybit(GLint x, GLint y,
    textureToCopyBitImage(&cbSurface, cbSurface.format, target_hnd, &dst);
    copybit_rect_t drect = {x, y, x+w, y+h};


    /* and now the alpha-plane hack. This handles the "Fade" case of a
     * texture with an alpha channel.
     */
    if (alphaPlaneWorkaround) {
        sp<GraphicBuffer> tempCb = new GraphicBuffer(
                    w, h, COPYBIT_FORMAT_RGB_565,
                    GraphicBuffer::USAGE_HW_2D);

        err = tempCb->initCheck();

        copybit_image_t tmpCbImg;
        copybit_rect_t tmpCbRect;
        tmpCbImg.w = w;
        tmpCbImg.h = h;
        tmpCbImg.format = tempCb->format;
        tmpCbImg.handle = (native_handle_t*)tempCb->getNativeBuffer()->handle;
        tmpCbRect.l = 0;
        tmpCbRect.t = 0;
        tmpCbRect.r = w;
        tmpCbRect.b = h;

        if (!err) {
            // first make a copy of the destination buffer
            region_iterator tmp_it(Region(Rect(w, h)));
            copybit->set_parameter(copybit, COPYBIT_TRANSFORM, 0);
            copybit->set_parameter(copybit, COPYBIT_PLANE_ALPHA, 0xFF);
            copybit->set_parameter(copybit, COPYBIT_DITHER, COPYBIT_DISABLE);
            err = copybit->stretch(copybit,
                    &tmpCbImg, &dst, &tmpCbRect, &drect, &tmp_it);
        }
        if (!err) {
            // then proceed as usual, but without the alpha plane
            copybit->set_parameter(copybit, COPYBIT_TRANSFORM, transform);
            copybit->set_parameter(copybit, COPYBIT_PLANE_ALPHA, 0xFF);
            copybit->set_parameter(copybit, COPYBIT_DITHER,
                    (enables & GGL_ENABLE_DITHER) ?
                            COPYBIT_ENABLE : COPYBIT_DISABLE);
            clipRectRegion it(c);
            err = copybit->stretch(copybit, &dst, &src, &drect, &srect, &it);
        }
        if (!err) {
            // finally copy back the destination on top with 1-alphaplane
            int invPlaneAlpha = 0xFF - fixedToByte(c->currentColorClamped.a);
            clipRectRegion it(c);
            copybit->set_parameter(copybit, COPYBIT_TRANSFORM, 0);
            copybit->set_parameter(copybit, COPYBIT_PLANE_ALPHA, invPlaneAlpha);
            copybit->set_parameter(copybit, COPYBIT_DITHER, COPYBIT_ENABLE);
            err = copybit->stretch(copybit,
                    &dst, &tmpCbImg, &drect, &tmpCbRect, &it);
        }
    } else {
        copybit->set_parameter(copybit, COPYBIT_TRANSFORM, transform);
        copybit->set_parameter(copybit, COPYBIT_PLANE_ALPHA, planeAlpha);
        copybit->set_parameter(copybit, COPYBIT_DITHER,
            (enables & GGL_ENABLE_DITHER) ? COPYBIT_ENABLE : COPYBIT_DISABLE);

                (enables & GGL_ENABLE_DITHER) ?
                        COPYBIT_ENABLE : COPYBIT_DISABLE);
        clipRectRegion it(c);
    status_t err = copybit->stretch(copybit, &dst, &src, &drect, &srect, &it);
        err = copybit->stretch(copybit, &dst, &src, &drect, &srect, &it);
    }
    if (err != NO_ERROR) {
        c->textures.tmu[0].texture->try_copybit = false;
    }