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

Commit 257ae350 authored by Romain Guy's avatar Romain Guy
Browse files

Optimize text GL setup

Only performs the GL setup steps when at least one glyph is drawn.
This change also skips various draw operations when the specified
paint draws with alpha = 0.

Change-Id: I9eda148b0503acffc552ee19196f5d52e958a1a2
parent 10c4d99f
Loading
Loading
Loading
Loading
+8 −4
Original line number Diff line number Diff line
@@ -21,6 +21,7 @@

#include <cutils/properties.h>

#include <utils/Functor.h>
#include <utils/Log.h>

#include <RenderScript.h>
@@ -416,6 +417,8 @@ void FontRenderer::issueDrawCommand() {
        CacheTexture* texture = mCacheTextures[i];
        if (texture->canDraw()) {
            if (first) {
                if (mFunctor) (*mFunctor)(0, NULL);

                checkTextureUpdate();
                caches.bindIndicesBuffer(mIndexBufferID);

@@ -561,11 +564,12 @@ FontRenderer::DropShadow FontRenderer::renderDropShadow(SkPaint* paint, const ch
    return image;
}

void FontRenderer::initRender(const Rect* clip, Rect* bounds) {
void FontRenderer::initRender(const Rect* clip, Rect* bounds, Functor* functor) {
    checkInit();

    mDrawn = false;
    mBounds = bounds;
    mFunctor = functor;
    mClip = clip;
}

@@ -583,13 +587,13 @@ void FontRenderer::precache(SkPaint* paint, const char* text, int numGlyphs, con

bool FontRenderer::renderPosText(SkPaint* paint, const Rect* clip, const char *text,
        uint32_t startIndex, uint32_t len, int numGlyphs, int x, int y,
        const float* positions, Rect* bounds) {
        const float* positions, Rect* bounds, Functor* functor) {
    if (!mCurrentFont) {
        ALOGE("No font set");
        return false;
    }

    initRender(clip, bounds);
    initRender(clip, bounds, functor);
    mCurrentFont->render(paint, text, startIndex, len, numGlyphs, x, y, positions);
    finishRender();

@@ -604,7 +608,7 @@ bool FontRenderer::renderTextOnPath(SkPaint* paint, const Rect* clip, const char
        return false;
    }

    initRender(clip, bounds);
    initRender(clip, bounds, NULL);
    mCurrentFont->render(paint, text, startIndex, len, numGlyphs, path, hOffset, vOffset);
    finishRender();

+7 −8
Original line number Diff line number Diff line
@@ -38,6 +38,8 @@ namespace RSC {
    class ScriptIntrinsicBlur;
}

class Functor;

namespace android {
namespace uirenderer {

@@ -62,7 +64,8 @@ public:

    // bounds is an out parameter
    bool renderPosText(SkPaint* paint, const Rect* clip, const char *text, uint32_t startIndex,
            uint32_t len, int numGlyphs, int x, int y, const float* positions, Rect* bounds);
            uint32_t len, int numGlyphs, int x, int y, const float* positions, Rect* bounds,
            Functor* functor);
    // bounds is an out parameter
    bool renderTextOnPath(SkPaint* paint, const Rect* clip, const char *text, uint32_t startIndex,
            uint32_t len, int numGlyphs, SkPath* path, float hOffset, float vOffset, Rect* bounds);
@@ -88,13 +91,8 @@ public:
    DropShadow renderDropShadow(SkPaint* paint, const char *text, uint32_t startIndex,
            uint32_t len, int numGlyphs, uint32_t radius, const float* positions);

    GLuint getTexture(bool linearFiltering = false) {
        checkInit();

        mCurrentCacheTexture->setLinearFiltering(linearFiltering);
    void setTextureFiltering(bool linearFiltering) {
        mLinearFiltering = linearFiltering;

        return mCurrentCacheTexture->getTextureId();
    }

    uint32_t getCacheSize() const {
@@ -125,7 +123,7 @@ private:
    void initVertexArrayBuffers();

    void checkInit();
    void initRender(const Rect* clip, Rect* bounds);
    void initRender(const Rect* clip, Rect* bounds, Functor* functor);
    void finishRender();

    void issueDrawCommand();
@@ -167,6 +165,7 @@ private:
    uint32_t mMaxNumberOfQuads;
    uint32_t mIndexBufferID;

    Functor* mFunctor;
    const Rect* mClip;
    Rect* mBounds;
    bool mDrawn;
+66 −48
Original line number Diff line number Diff line
@@ -1726,7 +1726,7 @@ void OpenGLRenderer::setupDrawSimpleMesh() {
}

void OpenGLRenderer::setupDrawTexture(GLuint texture) {
    bindTexture(texture);
    if (texture) bindTexture(texture);
    mTextureUnit++;
    mCaches.enableTexCoordsVertexArray();
}
@@ -2385,7 +2385,8 @@ status_t OpenGLRenderer::drawShape(float left, float top, const PathTexture* tex

status_t OpenGLRenderer::drawRoundRect(float left, float top, float right, float bottom,
        float rx, float ry, SkPaint* p) {
    if (mSnapshot->isIgnored() || quickRejectPreStroke(left, top, right, bottom, p)) {
    if (mSnapshot->isIgnored() || quickRejectPreStroke(left, top, right, bottom, p) ||
            (p->getAlpha() == 0 && getXfermode(p->getXfermode()) != SkXfermode::kClear_Mode)) {
        return DrawGlInfo::kStatusDone;
    }

@@ -2410,7 +2411,8 @@ status_t OpenGLRenderer::drawRoundRect(float left, float top, float right, float

status_t OpenGLRenderer::drawCircle(float x, float y, float radius, SkPaint* p) {
    if (mSnapshot->isIgnored() || quickRejectPreStroke(x - radius, y - radius,
            x + radius, y + radius, p)) {
            x + radius, y + radius, p) ||
            (p->getAlpha() == 0 && getXfermode(p->getXfermode()) != SkXfermode::kClear_Mode)) {
        return DrawGlInfo::kStatusDone;
    }
    if (p->getPathEffect() != 0) {
@@ -2430,7 +2432,8 @@ status_t OpenGLRenderer::drawCircle(float x, float y, float radius, SkPaint* p)

status_t OpenGLRenderer::drawOval(float left, float top, float right, float bottom,
        SkPaint* p) {
    if (mSnapshot->isIgnored() || quickRejectPreStroke(left, top, right, bottom, p)) {
    if (mSnapshot->isIgnored() || quickRejectPreStroke(left, top, right, bottom, p) ||
            (p->getAlpha() == 0 && getXfermode(p->getXfermode()) != SkXfermode::kClear_Mode)) {
        return DrawGlInfo::kStatusDone;
    }

@@ -2451,7 +2454,8 @@ status_t OpenGLRenderer::drawOval(float left, float top, float right, float bott

status_t OpenGLRenderer::drawArc(float left, float top, float right, float bottom,
        float startAngle, float sweepAngle, bool useCenter, SkPaint* p) {
    if (mSnapshot->isIgnored() || quickRejectPreStroke(left, top, right, bottom, p)) {
    if (mSnapshot->isIgnored() || quickRejectPreStroke(left, top, right, bottom, p) ||
            (p->getAlpha() == 0 && getXfermode(p->getXfermode()) != SkXfermode::kClear_Mode)) {
        return DrawGlInfo::kStatusDone;
    }

@@ -2487,7 +2491,8 @@ status_t OpenGLRenderer::drawArc(float left, float top, float right, float botto
#define SkPaintDefaults_MiterLimit SkIntToScalar(4)

status_t OpenGLRenderer::drawRect(float left, float top, float right, float bottom, SkPaint* p) {
    if (mSnapshot->isIgnored() || quickRejectPreStroke(left, top, right, bottom, p)) {
    if (mSnapshot->isIgnored() || quickRejectPreStroke(left, top, right, bottom, p) ||
            (p->getAlpha() == 0 && getXfermode(p->getXfermode()) != SkXfermode::kClear_Mode)) {
        return DrawGlInfo::kStatusDone;
    }

@@ -2563,6 +2568,48 @@ bool OpenGLRenderer::canSkipText(const SkPaint* paint) const {
    return alpha == 0.0f && getXfermode(paint->getXfermode()) == SkXfermode::kSrcOver_Mode;
}

class TextSetupFunctor: public Functor {
public:
    TextSetupFunctor(OpenGLRenderer& renderer, float x, float y, bool pureTranslate,
            int alpha, SkXfermode::Mode mode, SkPaint* paint): Functor(),
            renderer(renderer), x(x), y(y), pureTranslate(pureTranslate),
            alpha(alpha), mode(mode), paint(paint) {
    }
    ~TextSetupFunctor() { }

    status_t operator ()(int what, void* data) {
        renderer.setupDraw();
        renderer.setupDrawTextGamma(paint);
        renderer.setupDrawDirtyRegionsDisabled();
        renderer.setupDrawWithTexture(true);
        renderer.setupDrawAlpha8Color(paint->getColor(), alpha);
        renderer.setupDrawColorFilter();
        renderer.setupDrawShader();
        renderer.setupDrawBlending(true, mode);
        renderer.setupDrawProgram();
        renderer.setupDrawModelView(x, y, x, y, pureTranslate, true);
        // Calling setupDrawTexture with the name 0 will enable the
        // uv attributes and increase the texture unit count
        // texture binding will be performed by the font renderer as
        // needed
        renderer.setupDrawTexture(0);
        renderer.setupDrawPureColorUniforms();
        renderer.setupDrawColorFilterUniforms();
        renderer.setupDrawShaderUniforms(pureTranslate);
        renderer.setupDrawTextGammaUniforms();

        return NO_ERROR;
    }

    OpenGLRenderer& renderer;
    float x;
    float y;
    bool pureTranslate;
    int alpha;
    SkXfermode::Mode mode;
    SkPaint* paint;
};

status_t OpenGLRenderer::drawPosText(const char* text, int bytesCount, int count,
        const float* positions, SkPaint* paint) {
    if (text == NULL || count == 0 || mSnapshot->isIgnored() || canSkipText(paint)) {
@@ -2599,31 +2646,16 @@ status_t OpenGLRenderer::drawPosText(const char* text, int bytesCount, int count
    if (pureTranslate && !linearFilter) {
        linearFilter = fabs(y - (int) y) > 0.0f || fabs(x - (int) x) > 0.0f;
    }

    mCaches.activeTexture(0);
    setupDraw();
    setupDrawTextGamma(paint);
    setupDrawDirtyRegionsDisabled();
    setupDrawWithTexture(true);
    setupDrawAlpha8Color(paint->getColor(), alpha);
    setupDrawColorFilter();
    setupDrawShader();
    setupDrawBlending(true, mode);
    setupDrawProgram();
    setupDrawModelView(x, y, x, y, pureTranslate, true);
    setupDrawTexture(fontRenderer.getTexture(linearFilter));
    setupDrawPureColorUniforms();
    setupDrawColorFilterUniforms();
    setupDrawShaderUniforms(pureTranslate);
    setupDrawTextGammaUniforms();
    fontRenderer.setTextureFiltering(linearFilter);

    const Rect* clip = pureTranslate ? mSnapshot->clipRect : &mSnapshot->getLocalClip();
    Rect bounds(FLT_MAX / 2.0f, FLT_MAX / 2.0f, FLT_MIN / 2.0f, FLT_MIN / 2.0f);

    const bool hasActiveLayer = hasLayer();

    TextSetupFunctor functor(*this, x, y, pureTranslate, alpha, mode, paint);
    if (fontRenderer.renderPosText(paint, clip, text, 0, bytesCount, count, x, y,
            positions, hasActiveLayer ? &bounds : NULL)) {
            positions, hasActiveLayer ? &bounds : NULL, &functor)) {
        if (hasActiveLayer) {
            if (!pureTranslate) {
                currentTransform().mapRect(bounds);
@@ -2716,40 +2748,22 @@ status_t OpenGLRenderer::drawText(const char* text, int bytesCount, int count,

    // Pick the appropriate texture filtering
    bool linearFilter = !pureTranslate || fabs(y - (int) y) > 0.0f || fabs(x - (int) x) > 0.0f;

    // The font renderer will always use texture unit 0
    mCaches.activeTexture(0);
    setupDraw();
    setupDrawTextGamma(paint);
    setupDrawDirtyRegionsDisabled();
    setupDrawWithTexture(true);
    setupDrawAlpha8Color(paint->getColor(), alpha);
    setupDrawColorFilter();
    setupDrawShader();
    setupDrawBlending(true, mode);
    setupDrawProgram();
    setupDrawModelView(x, y, x, y, pureTranslate, true);
    // See comment above; the font renderer must use texture unit 0
    // assert(mTextureUnit == 0)
    setupDrawTexture(fontRenderer.getTexture(linearFilter));
    setupDrawPureColorUniforms();
    setupDrawColorFilterUniforms();
    setupDrawShaderUniforms(pureTranslate);
    setupDrawTextGammaUniforms();
    fontRenderer.setTextureFiltering(linearFilter);

    // TODO: Implement better clipping for scaled/rotated text
    const Rect* clip = !pureTranslate ? NULL : mSnapshot->clipRect;
    Rect bounds(FLT_MAX / 2.0f, FLT_MAX / 2.0f, FLT_MIN / 2.0f, FLT_MIN / 2.0f);

    bool status;
    TextSetupFunctor functor(*this, x, y, pureTranslate, alpha, mode, paint);
    if (CC_UNLIKELY(paint->getTextAlign() != SkPaint::kLeft_Align)) {
        SkPaint paintCopy(*paint);
        paintCopy.setTextAlign(SkPaint::kLeft_Align);
        status = fontRenderer.renderPosText(&paintCopy, clip, text, 0, bytesCount, count, x, y,
                positions, hasActiveLayer ? &bounds : NULL);
                positions, hasActiveLayer ? &bounds : NULL, &functor);
    } else {
        status = fontRenderer.renderPosText(paint, clip, text, 0, bytesCount, count, x, y,
                positions, hasActiveLayer ? &bounds : NULL);
                positions, hasActiveLayer ? &bounds : NULL, &functor);
    }

    if (status && hasActiveLayer) {
@@ -2772,12 +2786,12 @@ status_t OpenGLRenderer::drawTextOnPath(const char* text, int bytesCount, int co

    FontRenderer& fontRenderer = mCaches.fontRenderer->getFontRenderer(paint);
    fontRenderer.setFont(paint, mat4::identity());
    fontRenderer.setTextureFiltering(true);

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

    mCaches.activeTexture(0);
    setupDraw();
    setupDrawTextGamma(paint);
    setupDrawDirtyRegionsDisabled();
@@ -2788,7 +2802,11 @@ status_t OpenGLRenderer::drawTextOnPath(const char* text, int bytesCount, int co
    setupDrawBlending(true, mode);
    setupDrawProgram();
    setupDrawModelView(0.0f, 0.0f, 0.0f, 0.0f, false, true);
    setupDrawTexture(fontRenderer.getTexture(true));
    // Calling setupDrawTexture with the name 0 will enable the
    // uv attributes and increase the texture unit count
    // texture binding will be performed by the font renderer as
    // needed
    setupDrawTexture(0);
    setupDrawPureColorUniforms();
    setupDrawColorFilterUniforms();
    setupDrawShaderUniforms(false);
+2 −0
Original line number Diff line number Diff line
@@ -85,6 +85,7 @@ struct DeferredDisplayState {
///////////////////////////////////////////////////////////////////////////////

class DisplayList;
class TextSetupFunctor;
class VertexBuffer;

/**
@@ -985,6 +986,7 @@ private:
    String8 mName;

    friend class DisplayListRenderer;
    friend class TextSetupFunctor;

}; // class OpenGLRenderer