diff options
author | Romain Guy <romainguy@google.com> | 2011-07-25 16:36:01 -0700 |
---|---|---|
committer | Romain Guy <romainguy@google.com> | 2011-07-25 16:36:01 -0700 |
commit | e3c26851dc315b730ea0fe5ef35bb1db81f6d675 (patch) | |
tree | bc3fbae626f785fa38e40d4f5ab3737777d9a1ef | |
parent | 29d23ecfd8612ecd4a7b2140acd344934b73a558 (diff) | |
download | frameworks_base-e3c26851dc315b730ea0fe5ef35bb1db81f6d675.zip frameworks_base-e3c26851dc315b730ea0fe5ef35bb1db81f6d675.tar.gz frameworks_base-e3c26851dc315b730ea0fe5ef35bb1db81f6d675.tar.bz2 |
Improve rendering performance on some GPUs
This change sets textures filtering to GL_NEAREST by default. GL_LINEAR
filtering is only used when textures are transformed with a scale or
a rotation. This helps save a couple of fps on some GPUs.
Change-Id: I1efaa452c2c79905f00238e54d886a37203a2ac1
-rw-r--r-- | libs/hwui/GradientCache.cpp | 7 | ||||
-rw-r--r-- | libs/hwui/Layer.h | 24 | ||||
-rw-r--r-- | libs/hwui/LayerCache.cpp | 2 | ||||
-rw-r--r-- | libs/hwui/OpenGLRenderer.cpp | 40 | ||||
-rw-r--r-- | libs/hwui/OpenGLRenderer.h | 6 | ||||
-rw-r--r-- | libs/hwui/ShapeCache.h | 7 | ||||
-rw-r--r-- | libs/hwui/SkiaShader.cpp | 12 | ||||
-rw-r--r-- | libs/hwui/TextDropShadowCache.cpp | 7 | ||||
-rw-r--r-- | libs/hwui/Texture.h | 45 | ||||
-rw-r--r-- | libs/hwui/TextureCache.cpp | 7 |
10 files changed, 71 insertions, 86 deletions
diff --git a/libs/hwui/GradientCache.cpp b/libs/hwui/GradientCache.cpp index 4a40a63..996acd5 100644 --- a/libs/hwui/GradientCache.cpp +++ b/libs/hwui/GradientCache.cpp @@ -181,11 +181,8 @@ void GradientCache::generateTexture(SkBitmap* bitmap, Texture* texture) { glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, bitmap->rowBytesAsPixels(), texture->height, 0, GL_RGBA, GL_UNSIGNED_BYTE, bitmap->getPixels()); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); - - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); + texture->setFilter(GL_LINEAR, GL_LINEAR); + texture->setWrap(GL_CLAMP_TO_EDGE, GL_CLAMP_TO_EDGE); } }; // namespace uirenderer diff --git a/libs/hwui/Layer.h b/libs/hwui/Layer.h index 3c2d80d..0c536b0 100644 --- a/libs/hwui/Layer.h +++ b/libs/hwui/Layer.h @@ -51,8 +51,6 @@ struct Layer { texture.width = layerWidth; texture.height = layerHeight; colorFilter = NULL; - firstFilter = true; - firstWrap = true; } ~Layer() { @@ -150,27 +148,11 @@ struct Layer { } void setWrap(GLenum wrapS, GLenum wrapT, bool bindTexture = false, bool force = false) { - if (firstWrap || force || wrapS != texture.wrapS || wrapT != texture.wrapT) { - firstWrap = true; - texture.setWrap(wrapS, wrapT); - if (bindTexture) { - glBindTexture(renderTarget, texture.id); - } - glTexParameteri(renderTarget, GL_TEXTURE_WRAP_S, wrapS); - glTexParameteri(renderTarget, GL_TEXTURE_WRAP_T, wrapT); - } + texture.setWrap(wrapS, wrapT, bindTexture, force, renderTarget); } void setFilter(GLenum min, GLenum mag, bool bindTexture = false, bool force = false) { - if (firstFilter || force || min != texture.minFilter || mag != texture.magFilter) { - firstFilter = false; - texture.setFilter(min, mag); - if (bindTexture) { - glBindTexture(renderTarget, texture.id); - } - glTexParameteri(renderTarget, GL_TEXTURE_MIN_FILTER, min); - glTexParameteri(renderTarget, GL_TEXTURE_MAG_FILTER, mag); - } + texture.setFilter(min, mag,bindTexture, force, renderTarget); } inline bool isCacheable() { @@ -296,8 +278,6 @@ private: */ mat4 texTransform; - bool firstFilter; - bool firstWrap; }; // struct Layer }; // namespace uirenderer diff --git a/libs/hwui/LayerCache.cpp b/libs/hwui/LayerCache.cpp index 1a15e87..36083af 100644 --- a/libs/hwui/LayerCache.cpp +++ b/libs/hwui/LayerCache.cpp @@ -107,7 +107,7 @@ Layer* LayerCache::get(const uint32_t width, const uint32_t height) { layer->generateTexture(); layer->bindTexture(); layer->setFilter(GL_NEAREST, GL_NEAREST); - layer->setWrap(GL_CLAMP_TO_EDGE, GL_CLAMP_TO_EDGE); + layer->setWrap(GL_CLAMP_TO_EDGE, GL_CLAMP_TO_EDGE, false); glPixelStorei(GL_UNPACK_ALIGNMENT, 4); #if DEBUG_LAYERS diff --git a/libs/hwui/OpenGLRenderer.cpp b/libs/hwui/OpenGLRenderer.cpp index 85a9762..e67abbd 100644 --- a/libs/hwui/OpenGLRenderer.cpp +++ b/libs/hwui/OpenGLRenderer.cpp @@ -1293,16 +1293,16 @@ void OpenGLRenderer::drawAlphaBitmap(Texture* texture, float left, float top, Sk SkXfermode::Mode mode; getAlphaAndMode(paint, &alpha, &mode); - setTextureWrapModes(texture, GL_CLAMP_TO_EDGE, GL_CLAMP_TO_EDGE); - float x = left; float y = top; + GLenum filter = GL_LINEAR; bool ignoreTransform = false; if (mSnapshot->transform->isPureTranslate()) { x = (int) floorf(left + mSnapshot->transform->getTranslateX() + 0.5f); y = (int) floorf(top + mSnapshot->transform->getTranslateY() + 0.5f); ignoreTransform = true; + filter = GL_NEAREST; } setupDraw(); @@ -1315,7 +1315,11 @@ void OpenGLRenderer::drawAlphaBitmap(Texture* texture, float left, float top, Sk setupDrawBlending(true, mode); setupDrawProgram(); setupDrawModelView(x, y, x + texture->width, y + texture->height, ignoreTransform); + setupDrawTexture(texture->id); + texture->setWrap(GL_CLAMP_TO_EDGE, GL_CLAMP_TO_EDGE); + texture->setFilter(filter, filter); + setupDrawPureColorUniforms(); setupDrawColorFilterUniforms(); setupDrawShaderUniforms(); @@ -1379,7 +1383,9 @@ void OpenGLRenderer::drawBitmapMesh(SkBitmap* bitmap, int meshWidth, int meshHei Texture* texture = mCaches.textureCache.get(bitmap); if (!texture) return; const AutoTexture autoCleanup(texture); - setTextureWrapModes(texture, GL_CLAMP_TO_EDGE, GL_CLAMP_TO_EDGE); + + texture->setWrap(GL_CLAMP_TO_EDGE, GL_CLAMP_TO_EDGE, true); + texture->setFilter(GL_LINEAR, GL_LINEAR, true); int alpha; SkXfermode::Mode mode; @@ -1462,7 +1468,7 @@ void OpenGLRenderer::drawBitmap(SkBitmap* bitmap, Texture* texture = mCaches.textureCache.get(bitmap); if (!texture) return; const AutoTexture autoCleanup(texture); - setTextureWrapModes(texture, GL_CLAMP_TO_EDGE, GL_CLAMP_TO_EDGE); + texture->setWrap(GL_CLAMP_TO_EDGE, GL_CLAMP_TO_EDGE, true); const float width = texture->width; const float height = texture->height; @@ -1483,11 +1489,13 @@ void OpenGLRenderer::drawBitmap(SkBitmap* bitmap, const float x = (int) floorf(dstLeft + mSnapshot->transform->getTranslateX() + 0.5f); const float y = (int) floorf(dstTop + mSnapshot->transform->getTranslateY() + 0.5f); + texture->setFilter(GL_NEAREST, GL_NEAREST, true); drawTextureMesh(x, y, x + (dstRight - dstLeft), y + (dstBottom - dstTop), texture->id, alpha / 255.0f, mode, texture->blend, &mMeshVertices[0].position[0], &mMeshVertices[0].texture[0], GL_TRIANGLE_STRIP, gMeshCount, false, true); } else { + texture->setFilter(GL_LINEAR, GL_LINEAR, true); drawTextureMesh(dstLeft, dstTop, dstRight, dstBottom, texture->id, alpha / 255.0f, mode, texture->blend, &mMeshVertices[0].position[0], &mMeshVertices[0].texture[0], GL_TRIANGLE_STRIP, gMeshCount); @@ -1507,7 +1515,8 @@ void OpenGLRenderer::drawPatch(SkBitmap* bitmap, const int32_t* xDivs, const int Texture* texture = mCaches.textureCache.get(bitmap); if (!texture) return; const AutoTexture autoCleanup(texture); - setTextureWrapModes(texture, GL_CLAMP_TO_EDGE, GL_CLAMP_TO_EDGE); + texture->setWrap(GL_CLAMP_TO_EDGE, GL_CLAMP_TO_EDGE, true); + texture->setFilter(GL_LINEAR, GL_LINEAR, true); int alpha; SkXfermode::Mode mode; @@ -2411,16 +2420,18 @@ void OpenGLRenderer::drawTextureRect(float left, float top, float right, float b SkXfermode::Mode mode; getAlphaAndMode(paint, &alpha, &mode); - setTextureWrapModes(texture, GL_CLAMP_TO_EDGE, GL_CLAMP_TO_EDGE); + texture->setWrap(GL_CLAMP_TO_EDGE, GL_CLAMP_TO_EDGE, true); if (mSnapshot->transform->isPureTranslate()) { const float x = (int) floorf(left + mSnapshot->transform->getTranslateX() + 0.5f); const float y = (int) floorf(top + mSnapshot->transform->getTranslateY() + 0.5f); + texture->setFilter(GL_NEAREST, GL_NEAREST, true); drawTextureMesh(x, y, x + texture->width, y + texture->height, texture->id, alpha / 255.0f, mode, texture->blend, (GLvoid*) NULL, (GLvoid*) gMeshTextureOffset, GL_TRIANGLE_STRIP, gMeshCount, false, true); } else { + texture->setFilter(GL_LINEAR, GL_LINEAR, true); drawTextureMesh(left, top, right, bottom, texture->id, alpha / 255.0f, mode, texture->blend, (GLvoid*) NULL, (GLvoid*) gMeshTextureOffset, GL_TRIANGLE_STRIP, gMeshCount); @@ -2550,22 +2561,5 @@ SkXfermode::Mode OpenGLRenderer::getXfermode(SkXfermode* mode) { return resultMode; } -void OpenGLRenderer::setTextureWrapModes(Texture* texture, GLenum wrapS, GLenum wrapT) { - bool bound = false; - if (wrapS != texture->wrapS) { - glBindTexture(GL_TEXTURE_2D, texture->id); - bound = true; - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, wrapS); - texture->wrapS = wrapS; - } - if (wrapT != texture->wrapT) { - if (!bound) { - glBindTexture(GL_TEXTURE_2D, texture->id); - } - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, wrapT); - texture->wrapT = wrapT; - } -} - }; // namespace uirenderer }; // namespace android diff --git a/libs/hwui/OpenGLRenderer.h b/libs/hwui/OpenGLRenderer.h index 0a3d5090..fa893f0 100644 --- a/libs/hwui/OpenGLRenderer.h +++ b/libs/hwui/OpenGLRenderer.h @@ -464,12 +464,6 @@ private: } /** - * Sets the wrap modes for the specified texture. The wrap modes are modified - * only when needed. - */ - inline void setTextureWrapModes(Texture* texture, GLenum wrapS, GLenum wrapT); - - /** * Enable or disable blending as necessary. This function sets the appropriate * blend function based on the specified xfermode. */ diff --git a/libs/hwui/ShapeCache.h b/libs/hwui/ShapeCache.h index f4d9686..33953be 100644 --- a/libs/hwui/ShapeCache.h +++ b/libs/hwui/ShapeCache.h @@ -624,11 +624,8 @@ void ShapeCache<Entry>::generateTexture(SkBitmap& bitmap, Texture* texture) { glTexImage2D(GL_TEXTURE_2D, 0, GL_ALPHA, texture->width, texture->height, 0, GL_ALPHA, GL_UNSIGNED_BYTE, bitmap.getPixels()); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); - - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); + texture->setFilter(GL_LINEAR, GL_LINEAR); + texture->setWrap(GL_CLAMP_TO_EDGE, GL_CLAMP_TO_EDGE); } }; // namespace uirenderer diff --git a/libs/hwui/SkiaShader.cpp b/libs/hwui/SkiaShader.cpp index 8878c70..1a60dca 100644 --- a/libs/hwui/SkiaShader.cpp +++ b/libs/hwui/SkiaShader.cpp @@ -77,14 +77,7 @@ void SkiaShader::setupProgram(Program* program, const mat4& modelView, const Sna void SkiaShader::bindTexture(Texture* texture, GLenum wrapS, GLenum wrapT) { glBindTexture(GL_TEXTURE_2D, texture->id); - if (wrapS != texture->wrapS) { - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, wrapS); - texture->wrapS = wrapS; - } - if (wrapT != texture->wrapT) { - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, wrapT); - texture->wrapT = wrapT; - } + texture->setWrap(wrapS, wrapT); } void SkiaShader::computeScreenSpaceMatrix(mat4& screenSpace, const mat4& modelView) { @@ -151,6 +144,9 @@ void SkiaBitmapShader::setupProgram(Program* program, const mat4& modelView, // Uniforms bindTexture(texture, mWrapS, mWrapT); + GLenum filter = textureTransform.isPureTranslate() ? GL_NEAREST : GL_LINEAR; + texture->setFilter(filter, filter); + glUniform1i(program->getUniform("bitmapSampler"), textureSlot); glUniformMatrix4fv(program->getUniform("textureTransform"), 1, GL_FALSE, &textureTransform.data[0]); diff --git a/libs/hwui/TextDropShadowCache.cpp b/libs/hwui/TextDropShadowCache.cpp index 8f6f860..a3ee63b 100644 --- a/libs/hwui/TextDropShadowCache.cpp +++ b/libs/hwui/TextDropShadowCache.cpp @@ -137,11 +137,8 @@ ShadowTexture* TextDropShadowCache::get(SkPaint* paint, const char* text, uint32 glTexImage2D(GL_TEXTURE_2D, 0, GL_ALPHA, texture->width, texture->height, 0, GL_ALPHA, GL_UNSIGNED_BYTE, shadow.image); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); - - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); + texture->setFilter(GL_LINEAR, GL_LINEAR); + texture->setWrap(GL_CLAMP_TO_EDGE, GL_CLAMP_TO_EDGE); if (size < mMaxSize) { if (mDebugEnabled) { diff --git a/libs/hwui/Texture.h b/libs/hwui/Texture.h index c6ae326..48229b6 100644 --- a/libs/hwui/Texture.h +++ b/libs/hwui/Texture.h @@ -35,16 +35,45 @@ struct Texture { minFilter = GL_NEAREST; magFilter = GL_NEAREST; + + firstFilter = true; + firstWrap = true; } - void setWrap(GLenum wrapS, GLenum wrapT) { - this->wrapS = wrapS; - this->wrapT = wrapT; + void setWrap(GLenum wrapS, GLenum wrapT, bool bindTexture = false, bool force = false, + GLenum renderTarget = GL_TEXTURE_2D) { + + if (firstWrap || force || wrapS != this->wrapS || wrapT != this->wrapT) { + firstWrap = true; + + this->wrapS = wrapS; + this->wrapT = wrapT; + + if (bindTexture) { + glBindTexture(renderTarget, id); + } + + glTexParameteri(renderTarget, GL_TEXTURE_WRAP_S, wrapS); + glTexParameteri(renderTarget, GL_TEXTURE_WRAP_T, wrapT); + } } - void setFilter(GLenum min, GLenum mag) { - minFilter = min; - magFilter = mag; + void setFilter(GLenum min, GLenum mag, bool bindTexture = false, bool force = false, + GLenum renderTarget = GL_TEXTURE_2D) { + + if (firstFilter || force || min != minFilter || mag != magFilter) { + firstFilter = false; + + minFilter = min; + magFilter = mag; + + if (bindTexture) { + glBindTexture(renderTarget, id); + } + + glTexParameteri(renderTarget, GL_TEXTURE_MIN_FILTER, min); + glTexParameteri(renderTarget, GL_TEXTURE_MAG_FILTER, mag); + } } /** @@ -87,6 +116,10 @@ struct Texture { */ GLenum minFilter; GLenum magFilter; + +private: + bool firstFilter; + bool firstWrap; }; // struct Texture class AutoTexture { diff --git a/libs/hwui/TextureCache.cpp b/libs/hwui/TextureCache.cpp index 3752874..f926fdd 100644 --- a/libs/hwui/TextureCache.cpp +++ b/libs/hwui/TextureCache.cpp @@ -219,11 +219,8 @@ void TextureCache::generateTexture(SkBitmap* bitmap, Texture* texture, bool rege break; } - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); - - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); + texture->setFilter(GL_LINEAR, GL_LINEAR); + texture->setWrap(GL_CLAMP_TO_EDGE, GL_CLAMP_TO_EDGE); } void TextureCache::uploadLoFiTexture(bool resize, SkBitmap* bitmap, |