Permalink
Browse files

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
  • Loading branch information...
1 parent 29d23ec commit e3c26851dc315b730ea0fe5ef35bb1db81f6d675 Romain Guy committed Jul 25, 2011
@@ -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
View
@@ -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 @@ struct Layer {
*/
mat4 texTransform;
- bool firstFilter;
- bool firstWrap;
}; // struct Layer
}; // namespace uirenderer
View
@@ -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
@@ -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
@@ -464,12 +464,6 @@ class OpenGLRenderer {
}
/**
- * 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.
*/
View
@@ -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
View
@@ -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]);
@@ -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) {
View
@@ -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 {
@@ -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,

0 comments on commit e3c2685

Please sign in to comment.