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
This commit is contained in:
@@ -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,
|
||||
|
||||
Reference in New Issue
Block a user