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

Commit bbefa236 authored by Romain Guy's avatar Romain Guy Committed by Android (Google) Code Review
Browse files

Merge "Optimize blending state changes."

parents 90787e05 82ba814c
Loading
Loading
Loading
Loading
+48 −48
Original line number Diff line number Diff line
@@ -95,6 +95,7 @@ static const Blender gBlends[] = {
///////////////////////////////////////////////////////////////////////////////

OpenGLRenderer::OpenGLRenderer():
        mBlend(false), mLastSrcMode(GL_ZERO), mLastDstMode(GL_ZERO),
        mTextureCache(MB(DEFAULT_TEXTURE_CACHE_SIZE)),
        mLayerCache(MB(DEFAULT_LAYER_CACHE_SIZE)),
        mPatchCache(DEFAULT_PATCH_CACHE_SIZE) {
@@ -242,7 +243,7 @@ void OpenGLRenderer::composeLayer(sp<Snapshot> current, sp<Snapshot> previous) {
    const Rect& rect = layer->layer;

    drawTextureRect(rect.left, rect.top, rect.right, rect.bottom,
            layer->texture, layer->alpha, layer->mode, layer->blend, true);
            layer->texture, layer->alpha, layer->mode, layer->blend);

    LayerSize size(rect.getWidth(), rect.getHeight());
    // Failing to add the layer to the cache should happen only if the
@@ -421,13 +422,7 @@ bool OpenGLRenderer::clipRect(float left, float top, float right, float bottom)

void OpenGLRenderer::drawBitmap(SkBitmap* bitmap, float left, float top, const SkPaint* paint) {
    const Texture* texture = mTextureCache.get(bitmap);

    int alpha;
    SkXfermode::Mode mode;
    getAlphaAndMode(paint, &alpha, &mode);

    drawTextureRect(left, top, left + texture->width, top + texture->height, texture->id,
            alpha / 255.0f, mode, texture->blend, true);
    drawTextureRect(left, top, left + texture->width, top + texture->height, texture, paint);
}

void OpenGLRenderer::drawBitmap(SkBitmap* bitmap, const SkMatrix* matrix, const SkPaint* paint) {
@@ -436,13 +431,7 @@ void OpenGLRenderer::drawBitmap(SkBitmap* bitmap, const SkMatrix* matrix, const
    transform.mapRect(r);

    const Texture* texture = mTextureCache.get(bitmap);

    int alpha;
    SkXfermode::Mode mode;
    getAlphaAndMode(paint, &alpha, &mode);

    drawTextureRect(r.left, r.top, r.right, r.bottom, texture->id,
            alpha / 255.0f, mode, texture->blend, true);
    drawTextureRect(r.left, r.top, r.right, r.bottom, texture, paint);
}

void OpenGLRenderer::drawBitmap(SkBitmap* bitmap,
@@ -451,10 +440,6 @@ void OpenGLRenderer::drawBitmap(SkBitmap* bitmap,
         const SkPaint* paint) {
    const Texture* texture = mTextureCache.get(bitmap);

    int alpha;
    SkXfermode::Mode mode;
    getAlphaAndMode(paint, &alpha, &mode);

    const float width = texture->width;
    const float height = texture->height;

@@ -465,8 +450,7 @@ void OpenGLRenderer::drawBitmap(SkBitmap* bitmap,

    resetDrawTextureTexCoords(u1, v1, u2, v2);

    drawTextureRect(dstLeft, dstTop, dstRight, dstBottom, texture->id,
            alpha / 255.0f, mode, texture->blend, true);
    drawTextureRect(dstLeft, dstTop, dstRight, dstBottom, texture, paint);

    resetDrawTextureTexCoords(0.0f, 0.0f, 1.0f, 1.0f);
}
@@ -606,17 +590,12 @@ void OpenGLRenderer::drawRect(float left, float top, float right, float bottom,
void OpenGLRenderer::drawColorRect(float left, float top, float right, float bottom,
        int color, SkXfermode::Mode mode) {
    const int alpha = (color >> 24) & 0xFF;
    const bool blend = alpha < 255 || mode != SkXfermode::kSrcOver_Mode;

    const GLfloat a = alpha                  / 255.0f;
    const GLfloat r = ((color >> 16) & 0xFF) / 255.0f;
    const GLfloat g = ((color >>  8) & 0xFF) / 255.0f;
    const GLfloat b = ((color      ) & 0xFF) / 255.0f;

    if (blend) {
        glEnable(GL_BLEND);
        glBlendFunc(gBlends[mode].src, gBlends[mode].dst);
    }
    chooseBlending(alpha < 255, mode, true);

    mModelView.loadTranslate(left, top, 0.0f);
    mModelView.scale(right - left, bottom - top, 1.0f);
@@ -633,10 +612,17 @@ void OpenGLRenderer::drawColorRect(float left, float top, float right, float bot
    glDrawArrays(GL_TRIANGLE_STRIP, 0, gDrawColorVertexCount);

    glDisableVertexAttribArray(mDrawColorShader->position);

    if (blend) {
        glDisable(GL_BLEND);
}

void OpenGLRenderer::drawTextureRect(float left, float top, float right, float bottom,
        const Texture* texture, const SkPaint* paint, bool isPremultiplied) {
    int alpha;
    SkXfermode::Mode mode;
    getAlphaAndMode(paint, &alpha, &mode);

    drawTextureMesh(left, top, right, bottom, texture->id, alpha / 255.0f, mode, texture->blend,
            isPremultiplied, &mDrawTextureVertices[0].position[0],
            &mDrawTextureVertices[0].texture[0], NULL);
}

void OpenGLRenderer::drawTextureRect(float left, float top, float right, float bottom,
@@ -653,15 +639,7 @@ void OpenGLRenderer::drawTextureMesh(float left, float top, float right, float b

    mDrawTextureShader->use(&mOrthoMatrix[0], &mModelView.data[0], &mSnapshot->transform.data[0]);

    if (blend || alpha < 1.0f || mode != SkXfermode::kSrcOver_Mode) {
        GLenum sourceMode = gBlends[mode].src;
        if (!isPremultiplied && sourceMode == GL_ONE) {
            sourceMode = GL_SRC_ALPHA;
        }

        glEnable(GL_BLEND);
        glBlendFunc(sourceMode, gBlends[mode].dst);
    }
    chooseBlending(blend || alpha < 1.0f, mode, isPremultiplied);

    glBindTexture(GL_TEXTURE_2D, texture);

@@ -690,18 +668,40 @@ void OpenGLRenderer::drawTextureMesh(float left, float top, float right, float b
    glDisableVertexAttribArray(mDrawTextureShader->texCoords);

    glBindTexture(GL_TEXTURE_2D, 0);
}

void OpenGLRenderer::chooseBlending(bool blend, SkXfermode::Mode mode, bool isPremultiplied) {
    // In theory we should not blend if the mode is Src, but it's rare enough
    // that it's not worth it
    blend = blend || mode != SkXfermode::kSrcOver_Mode;
    if (blend) {
        if (!mBlend) {
            glEnable(GL_BLEND);
        }

        GLenum sourceMode = gBlends[mode].src;
        GLenum destMode = gBlends[mode].dst;
        if (!isPremultiplied && sourceMode == GL_ONE) {
            sourceMode = GL_SRC_ALPHA;
        }

        if (sourceMode != mLastSrcMode || destMode != mLastDstMode) {
            glBlendFunc(sourceMode, destMode);
            mLastSrcMode = sourceMode;
            mLastDstMode = destMode;
        }
    } else if (mBlend) {
        glDisable(GL_BLEND);
    }
    mBlend = blend;
}

void OpenGLRenderer::resetDrawTextureTexCoords(float u1, float v1, float u2, float v2) {
    mDrawTextureVertices[0].texture[0] = u1;
    mDrawTextureVertices[0].texture[1] = v1;
    mDrawTextureVertices[1].texture[0] = u2;
    mDrawTextureVertices[1].texture[1] = v1;
    mDrawTextureVertices[2].texture[0] = u1;
    mDrawTextureVertices[2].texture[1] = v2;
    mDrawTextureVertices[3].texture[0] = u2;
    mDrawTextureVertices[3].texture[1] = v2;
    TextureVertex* v = &mDrawTextureVertices[0];
    TextureVertex::setUV(v++, u1, v1);
    TextureVertex::setUV(v++, u2, v1);
    TextureVertex::setUV(v++, u1, v2);
    TextureVertex::setUV(v++, u2, v2);
}

void OpenGLRenderer::getAlphaAndMode(const SkPaint* paint, int* alpha, SkXfermode::Mode* mode) {
+44 −2
Original line number Diff line number Diff line
@@ -179,10 +179,40 @@ private:
     * @param isPremultiplied Indicates whether the texture has premultiplied alpha
     */
    void drawTextureRect(float left, float top, float right, float bottom, GLuint texture,
            float alpha, SkXfermode::Mode mode, bool blend, bool isPremultiplied = false);
            float alpha, SkXfermode::Mode mode, bool blend, bool isPremultiplied = true);

    /**
     * TODO: documentation
     * Draws a textured rectangle with the specified texture. The specified coordinates
     * are transformed by the current snapshot's transform matrix.
     *
     * @param left The left coordinate of the rectangle
     * @param top The top coordinate of the rectangle
     * @param right The right coordinate of the rectangle
     * @param bottom The bottom coordinate of the rectangle
     * @param texture The texture to use
     * @param paint The paint containing the alpha, blending mode, etc.
     * @param isPremultiplied Indicates whether the texture has premultiplied alpha
     */
    void drawTextureRect(float left, float top, float right, float bottom, const Texture* texture,
            const SkPaint* paint, bool isPremultiplied = true);

    /**
     * Draws a textured mesh with the specified texture. If the indices are omitted, the
     * mesh is drawn as a simple quad.
     *
     * @param left The left coordinate of the rectangle
     * @param top The top coordinate of the rectangle
     * @param right The right coordinate of the rectangle
     * @param bottom The bottom coordinate of the rectangle
     * @param texture The texture name to map onto the rectangle
     * @param alpha An additional translucency parameter, between 0.0f and 1.0f
     * @param mode The blending mode
     * @param blend True if the texture contains an alpha channel
     * @param isPremultiplied Indicates whether the texture has premultiplied alpha
     * @param vertices The vertices that define the mesh
     * @param texCoords The texture coordinates of each vertex
     * @param indices The indices of the vertices, can be NULL
     * @param elementsCount The number of elements in the mesh, required by indices
     */
    void drawTextureMesh(float left, float top, float right, float bottom, GLuint texture,
            float alpha, SkXfermode::Mode mode, bool blend, bool isPremultiplied,
@@ -217,6 +247,12 @@ private:
    inline void generateVertices(TextureVertex* vertex, float y, float v, const int32_t xDivs[],
            uint32_t xCount, float xStretch, float xStretchTex, float width, float widthTex);

    /**
     * Enable or disable blending as necessary. This function sets the appropriate
     * blend function based on the specified xfermode.
     */
    inline void chooseBlending(bool blend, SkXfermode::Mode mode, bool isPremultiplied);

    // Dimensions of the drawing surface
    int mWidth, mHeight;

@@ -240,6 +276,12 @@ private:
    // Used to draw textured quads
    TextureVertex mDrawTextureVertices[4];

    // Last known blend state
    bool mBlend;
    GLenum mLastSrcMode;
    GLenum mLastDstMode;

    // Various caches
    TextureCache mTextureCache;
    LayerCache mLayerCache;
    PatchCache mPatchCache;
+5 −0
Original line number Diff line number Diff line
@@ -41,6 +41,11 @@ struct TextureVertex {
        vertex[0].texture[0] = u;
        vertex[0].texture[1] = v;
    }

    static inline void setUV(TextureVertex* vertex, float u, float v) {
        vertex[0].texture[0] = u;
        vertex[0].texture[1] = v;
    }
}; // struct TextureVertex

}; // namespace uirenderer