From 257ae3502cfad43df681b1783528d645bdabc63f Mon Sep 17 00:00:00 2001 From: Romain Guy Date: Wed, 20 Mar 2013 16:31:12 -0700 Subject: 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 --- libs/hwui/OpenGLRenderer.cpp | 114 +++++++++++++++++++++++++------------------ 1 file changed, 66 insertions(+), 48 deletions(-) (limited to 'libs/hwui/OpenGLRenderer.cpp') diff --git a/libs/hwui/OpenGLRenderer.cpp b/libs/hwui/OpenGLRenderer.cpp index 8030d6672851..e7dfa666e2ab 100644 --- a/libs/hwui/OpenGLRenderer.cpp +++ b/libs/hwui/OpenGLRenderer.cpp @@ -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); -- cgit v1.2.3-59-g8ed1b