Commit e3c26851 authored by Romain Guy's avatar Romain Guy
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
parent 29d23ecf
......@@ -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
......
......@@ -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
......
......@@ -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
......@@ -463,12 +463,6 @@ private:
glBindTexture(GL_TEXTURE_EXTERNAL_OES, texture);
}
/**
* 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.
......
......@@ -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
......
......@@ -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) {
......
......@@ -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,
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment