summaryrefslogtreecommitdiffstats
path: root/libs
diff options
context:
space:
mode:
Diffstat (limited to 'libs')
-rw-r--r--libs/hwui/Caches.cpp13
-rw-r--r--libs/hwui/Caches.h1
-rwxr-xr-xlibs/hwui/Dither.cpp4
-rw-r--r--libs/hwui/FontRenderer.cpp17
-rw-r--r--libs/hwui/Layer.cpp7
-rw-r--r--libs/hwui/Layer.h3
-rw-r--r--libs/hwui/OpenGLRenderer.cpp47
-rw-r--r--libs/hwui/OpenGLRenderer.h3
-rw-r--r--libs/hwui/ProgramCache.cpp53
-rw-r--r--libs/hwui/Properties.h10
-rw-r--r--libs/hwui/ResourceCache.cpp15
-rw-r--r--libs/hwui/ResourceCache.h2
-rw-r--r--libs/hwui/Stencil.cpp25
-rw-r--r--libs/hwui/Stencil.h10
-rw-r--r--libs/hwui/font/CacheTexture.cpp3
-rw-r--r--libs/hwui/font/CacheTexture.h53
16 files changed, 199 insertions, 67 deletions
diff --git a/libs/hwui/Caches.cpp b/libs/hwui/Caches.cpp
index 068eb9e..898962a 100644
--- a/libs/hwui/Caches.cpp
+++ b/libs/hwui/Caches.cpp
@@ -131,6 +131,13 @@ void Caches::initProperties() {
} else {
debugLayersUpdates = false;
}
+
+ if (property_get(PROPERTY_DEBUG_OVERDRAW, property, NULL) > 0) {
+ INIT_LOGD(" Overdraw debug enabled: %s", property);
+ debugOverdraw = !strcmp(property, "true");
+ } else {
+ debugOverdraw = false;
+ }
}
void Caches::terminate() {
@@ -428,13 +435,13 @@ void Caches::resetScissor() {
///////////////////////////////////////////////////////////////////////////////
void Caches::startTiling(GLuint x, GLuint y, GLuint width, GLuint height, bool opaque) {
- if (extensions.hasTiledRendering()) {
- glStartTilingQCOM(x, y, width, height, opaque ? GL_NONE : GL_COLOR_BUFFER_BIT0_QCOM);
+ if (extensions.hasTiledRendering() && !debugOverdraw) {
+ glStartTilingQCOM(x, y, width, height, (opaque ? GL_NONE : GL_COLOR_BUFFER_BIT0_QCOM));
}
}
void Caches::endTiling() {
- if (extensions.hasTiledRendering()) {
+ if (extensions.hasTiledRendering() && !debugOverdraw) {
glEndTilingQCOM(GL_COLOR_BUFFER_BIT0_QCOM);
}
}
diff --git a/libs/hwui/Caches.h b/libs/hwui/Caches.h
index 50e9e75..48efd10 100644
--- a/libs/hwui/Caches.h
+++ b/libs/hwui/Caches.h
@@ -242,6 +242,7 @@ public:
// Misc
GLint maxTextureSize;
bool debugLayersUpdates;
+ bool debugOverdraw;
TextureCache textureCache;
LayerCache layerCache;
diff --git a/libs/hwui/Dither.cpp b/libs/hwui/Dither.cpp
index 5817977..e80b325 100755
--- a/libs/hwui/Dither.cpp
+++ b/libs/hwui/Dither.cpp
@@ -76,8 +76,10 @@ void Dither::setupProgram(Program* program, GLuint* textureUnit) {
bindDitherTexture();
+ float ditherSize = 1.0f / DITHER_KERNEL_SIZE;
glUniform1i(program->getUniform("ditherSampler"), textureSlot);
- glUniform1f(program->getUniform("ditherSize"), 1.0f / DITHER_KERNEL_SIZE);
+ glUniform1f(program->getUniform("ditherSize"), ditherSize);
+ glUniform1f(program->getUniform("ditherSizeSquared"), ditherSize * ditherSize);
}
}; // namespace uirenderer
diff --git a/libs/hwui/FontRenderer.cpp b/libs/hwui/FontRenderer.cpp
index 86667ee..cab68f0 100644
--- a/libs/hwui/FontRenderer.cpp
+++ b/libs/hwui/FontRenderer.cpp
@@ -331,10 +331,14 @@ void FontRenderer::checkTextureUpdate() {
for (uint32_t i = 0; i < mCacheTextures.size(); i++) {
CacheTexture* cacheTexture = mCacheTextures[i];
if (cacheTexture->isDirty() && cacheTexture->getTexture()) {
- uint32_t xOffset = 0;
+ // Can't copy inner rect; glTexSubimage expects pointer to deal with entire buffer
+ // of data. So expand the dirty rect to the encompassing horizontal stripe.
+ const Rect* dirtyRect = cacheTexture->getDirtyRect();
+ uint32_t x = 0;
+ uint32_t y = dirtyRect->top;
uint32_t width = cacheTexture->getWidth();
- uint32_t height = cacheTexture->getHeight();
- void* textureData = cacheTexture->getTexture();
+ uint32_t height = dirtyRect->getHeight();
+ void* textureData = cacheTexture->getTexture() + y * width;
if (cacheTexture->getTextureId() != lastTextureId) {
lastTextureId = cacheTexture->getTextureId();
@@ -342,12 +346,11 @@ void FontRenderer::checkTextureUpdate() {
glBindTexture(GL_TEXTURE_2D, lastTextureId);
}
#if DEBUG_FONT_RENDERER
- ALOGD("glTextSubimage for cacheTexture %d: xOff, width height = %d, %d, %d",
- i, xOffset, width, height);
+ ALOGD("glTexSubimage for cacheTexture %d: x, y, width height = %d, %d, %d, %d",
+ i, x, y, width, height);
#endif
- glTexSubImage2D(GL_TEXTURE_2D, 0, xOffset, 0, width, height,
+ glTexSubImage2D(GL_TEXTURE_2D, 0, x, y, width, height,
GL_ALPHA, GL_UNSIGNED_BYTE, textureData);
-
cacheTexture->setDirty(false);
}
}
diff --git a/libs/hwui/Layer.cpp b/libs/hwui/Layer.cpp
index 76b274b..fb525ee 100644
--- a/libs/hwui/Layer.cpp
+++ b/libs/hwui/Layer.cpp
@@ -50,6 +50,13 @@ Layer::~Layer() {
deleteTexture();
}
+void Layer::freeResourcesLocked() {
+ if (colorFilter) {
+ Caches::getInstance().resourceCache.decrementRefcountLocked(colorFilter);
+ colorFilter = NULL;
+ }
+}
+
void Layer::setPaint(SkPaint* paint) {
OpenGLRenderer::getAlphaAndModeDirect(paint, &alpha, &mode);
}
diff --git a/libs/hwui/Layer.h b/libs/hwui/Layer.h
index 420073a..d2cd440 100644
--- a/libs/hwui/Layer.h
+++ b/libs/hwui/Layer.h
@@ -45,10 +45,11 @@ class DisplayList;
* A layer has dimensions and is backed by an OpenGL texture or FBO.
*/
struct Layer {
-
Layer(const uint32_t layerWidth, const uint32_t layerHeight);
~Layer();
+ void freeResourcesLocked();
+
/**
* Sets this layer's region to a rectangle. Computes the appropriate
* texture coordinates.
diff --git a/libs/hwui/OpenGLRenderer.cpp b/libs/hwui/OpenGLRenderer.cpp
index bdf1229..a4403c8 100644
--- a/libs/hwui/OpenGLRenderer.cpp
+++ b/libs/hwui/OpenGLRenderer.cpp
@@ -194,6 +194,8 @@ int OpenGLRenderer::prepareDirty(float left, float top, float right, float botto
mTilingSnapshot = mSnapshot;
startTiling(mTilingSnapshot, true);
+ debugOverdraw(true, true);
+
if (!opaque) {
mCaches.enableScissor();
mCaches.setScissor(left, mSnapshot->height - bottom, right - left, bottom - top);
@@ -231,6 +233,7 @@ void OpenGLRenderer::endTiling() {
}
void OpenGLRenderer::finish() {
+ renderOverdraw();
endTiling();
if (!suppressErrorChecks()) {
@@ -265,6 +268,40 @@ void OpenGLRenderer::finish() {
}
}
+void OpenGLRenderer::debugOverdraw(bool enable, bool clear) {
+ if (mCaches.debugOverdraw && getTargetFbo() == 0) {
+ if (clear) {
+ mCaches.disableScissor();
+ mCaches.stencil.clear();
+ }
+ if (enable) {
+ mCaches.stencil.enableDebugWrite();
+ } else {
+ mCaches.stencil.disable();
+ }
+ }
+}
+
+void OpenGLRenderer::renderOverdraw() {
+ if (mCaches.debugOverdraw && getTargetFbo() == 0) {
+ const Rect* clip = mTilingSnapshot->clipRect;
+
+ mCaches.enableScissor();
+ mCaches.setScissor(clip->left, mTilingSnapshot->height - clip->bottom,
+ clip->right - clip->left, clip->bottom - clip->top);
+
+ mCaches.stencil.enableDebugTest(2);
+ drawColor(0x2f0000ff, SkXfermode::kSrcOver_Mode);
+ mCaches.stencil.enableDebugTest(3);
+ drawColor(0x2f00ff00, SkXfermode::kSrcOver_Mode);
+ mCaches.stencil.enableDebugTest(4);
+ drawColor(0x3fff0000, SkXfermode::kSrcOver_Mode);
+ mCaches.stencil.enableDebugTest(4, true);
+ drawColor(0x7fff0000, SkXfermode::kSrcOver_Mode);
+ mCaches.stencil.disable();
+ }
+}
+
void OpenGLRenderer::interrupt() {
if (mCaches.currentProgram) {
if (mCaches.currentProgram->isInUse()) {
@@ -276,12 +313,14 @@ void OpenGLRenderer::interrupt() {
mCaches.unbindIndicesBuffer();
mCaches.resetVertexPointers();
mCaches.disbaleTexCoordsVertexArray();
+ debugOverdraw(false, false);
}
void OpenGLRenderer::resume() {
sp<Snapshot> snapshot = (mSnapshot != NULL) ? mSnapshot : mFirstSnapshot;
glViewport(0, 0, snapshot->viewport.getWidth(), snapshot->viewport.getHeight());
glBindFramebuffer(GL_FRAMEBUFFER, snapshot->fbo);
+ debugOverdraw(true, false);
glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
@@ -302,6 +341,7 @@ void OpenGLRenderer::resumeAfterLayer() {
sp<Snapshot> snapshot = (mSnapshot != NULL) ? mSnapshot : mFirstSnapshot;
glViewport(0, 0, snapshot->viewport.getWidth(), snapshot->viewport.getHeight());
glBindFramebuffer(GL_FRAMEBUFFER, snapshot->fbo);
+ debugOverdraw(true, false);
mCaches.resetScissor();
dirtyClip();
@@ -407,7 +447,10 @@ bool OpenGLRenderer::updateLayer(Layer* layer, bool inFrame) {
OpenGLRenderer* renderer = layer->renderer;
Rect& dirty = layer->dirtyRect;
- if (inFrame) endTiling();
+ if (inFrame) {
+ endTiling();
+ debugOverdraw(false, false);
+ }
renderer->setViewport(layer->layer.getWidth(), layer->layer.getHeight());
renderer->prepareDirty(dirty.left, dirty.top, dirty.right, dirty.bottom, !layer->isBlend());
@@ -724,6 +767,7 @@ bool OpenGLRenderer::createFboLayer(Layer* layer, Rect& bounds, Rect& clip, GLui
mSnapshot->orthoMatrix.load(mOrthoMatrix);
endTiling();
+ debugOverdraw(false, false);
// Bind texture to FBO
glBindFramebuffer(GL_FRAMEBUFFER, layer->getFbo());
layer->bindTexture();
@@ -772,6 +816,7 @@ void OpenGLRenderer::composeLayer(sp<Snapshot> current, sp<Snapshot> previous) {
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, 0, 0);
// Unbind current FBO and restore previous one
glBindFramebuffer(GL_FRAMEBUFFER, previous->fbo);
+ debugOverdraw(true, false);
startTiling(previous);
}
diff --git a/libs/hwui/OpenGLRenderer.h b/libs/hwui/OpenGLRenderer.h
index 7d5da68..46e66cb 100644
--- a/libs/hwui/OpenGLRenderer.h
+++ b/libs/hwui/OpenGLRenderer.h
@@ -723,6 +723,9 @@ private:
*/
void drawRegionRects(const Region& region);
+ void debugOverdraw(bool enable, bool clear);
+ void renderOverdraw();
+
/**
* Should be invoked every time the glScissor is modified.
*/
diff --git a/libs/hwui/ProgramCache.cpp b/libs/hwui/ProgramCache.cpp
index de7afed..c81319e 100644
--- a/libs/hwui/ProgramCache.cpp
+++ b/libs/hwui/ProgramCache.cpp
@@ -53,11 +53,14 @@ const char* gVS_Header_Uniforms_IsPoint =
"uniform mediump float pointSize;\n";
const char* gVS_Header_Uniforms_HasGradient[3] = {
// Linear
- "uniform mat4 screenSpace;\n",
+ "uniform mat4 screenSpace;\n"
+ "uniform float ditherSize;\n",
// Circular
- "uniform mat4 screenSpace;\n",
+ "uniform mat4 screenSpace;\n"
+ "uniform float ditherSize;\n",
// Sweep
"uniform mat4 screenSpace;\n"
+ "uniform float ditherSize;\n"
};
const char* gVS_Header_Uniforms_HasBitmap =
"uniform mat4 textureTransform;\n"
@@ -75,16 +78,22 @@ const char* gVS_Header_Varyings_PointHasBitmap =
"varying highp vec2 outPointBitmapTexCoords;\n";
const char* gVS_Header_Varyings_HasGradient[6] = {
// Linear
- "varying highp vec2 linear;\n",
- "varying float linear;\n",
+ "varying highp vec2 linear;\n"
+ "varying vec2 ditherTexCoords;\n",
+ "varying float linear;\n"
+ "varying vec2 ditherTexCoords;\n",
// Circular
- "varying highp vec2 circular;\n",
- "varying highp vec2 circular;\n",
+ "varying highp vec2 circular;\n"
+ "varying vec2 ditherTexCoords;\n",
+ "varying highp vec2 circular;\n"
+ "varying vec2 ditherTexCoords;\n",
// Sweep
- "varying highp vec2 sweep;\n",
- "varying highp vec2 sweep;\n",
+ "varying highp vec2 sweep;\n"
+ "varying vec2 ditherTexCoords;\n",
+ "varying highp vec2 sweep;\n"
+ "varying vec2 ditherTexCoords;\n",
};
const char* gVS_Main =
"\nvoid main(void) {\n";
@@ -94,16 +103,22 @@ const char* gVS_Main_OutTransformedTexCoords =
" outTexCoords = (mainTextureTransform * vec4(texCoords, 0.0, 1.0)).xy;\n";
const char* gVS_Main_OutGradient[6] = {
// Linear
- " linear = vec2((screenSpace * position).x, 0.5);\n",
- " linear = (screenSpace * position).x;\n",
+ " linear = vec2((screenSpace * position).x, 0.5);\n"
+ " ditherTexCoords = (gl_Position * ditherSize).xy;\n",
+ " linear = (screenSpace * position).x;\n"
+ " ditherTexCoords = (gl_Position * ditherSize).xy;\n",
// Circular
- " circular = (screenSpace * position).xy;\n",
- " circular = (screenSpace * position).xy;\n",
+ " circular = (screenSpace * position).xy;\n"
+ " ditherTexCoords = (gl_Position * ditherSize).xy;\n",
+ " circular = (screenSpace * position).xy;\n"
+ " ditherTexCoords = (gl_Position * ditherSize).xy;\n",
// Sweep
- " sweep = (screenSpace * position).xy;\n",
- " sweep = (screenSpace * position).xy;\n",
+ " sweep = (screenSpace * position).xy;\n"
+ " ditherTexCoords = (gl_Position * ditherSize).xy;\n",
+ " sweep = (screenSpace * position).xy;\n"
+ " ditherTexCoords = (gl_Position * ditherSize).xy;\n",
};
const char* gVS_Main_OutBitmapTexCoords =
" outBitmapTexCoords = (textureTransform * position).xy * textureDimension;\n";
@@ -144,7 +159,7 @@ const char* gFS_Uniforms_TextureSampler =
const char* gFS_Uniforms_ExternalTextureSampler =
"uniform samplerExternalOES baseSampler;\n";
#define FS_UNIFORMS_DITHER \
- "uniform float ditherSize;\n" \
+ "uniform float ditherSizeSquared;\n" \
"uniform sampler2D ditherSampler;\n"
#define FS_UNIFORMS_GRADIENT \
"uniform vec4 startColor;\n" \
@@ -188,7 +203,7 @@ const char* gFS_Main_PointBitmapTexCoords =
"((gl_PointCoord - vec2(0.5, 0.5)) * textureDimension * vec2(pointSize, pointSize));\n";
#define FS_MAIN_DITHER \
- "texture2D(ditherSampler, gl_FragCoord.xy * ditherSize).a * ditherSize * ditherSize"
+ "texture2D(ditherSampler, ditherTexCoords).a * ditherSizeSquared"
const char* gFS_Main_AddDitherToGradient =
" gradientColor += " FS_MAIN_DITHER ";\n";
@@ -511,9 +526,6 @@ String8 ProgramCache::generateVertexShader(const ProgramDescription& description
shader.append(gVS_Main_AALine);
}
}
- if (description.hasGradient) {
- shader.append(gVS_Main_OutGradient[gradientIndex(description)]);
- }
if (description.hasBitmap) {
shader.append(description.isPoint ?
gVS_Main_OutPointBitmapTexCoords :
@@ -524,6 +536,9 @@ String8 ProgramCache::generateVertexShader(const ProgramDescription& description
}
// Output transformed position
shader.append(gVS_Main_Position);
+ if (description.hasGradient) {
+ shader.append(gVS_Main_OutGradient[gradientIndex(description)]);
+ }
}
// End the shader
shader.append(gVS_Footer);
diff --git a/libs/hwui/Properties.h b/libs/hwui/Properties.h
index 0e3268e..31e60e4 100644
--- a/libs/hwui/Properties.h
+++ b/libs/hwui/Properties.h
@@ -37,7 +37,7 @@
// Defines the size in bits of the stencil buffer
// Note: Only 1 bit is required for clipping but more bits are required
// to properly implement the winding fill rule when rasterizing paths
-#define STENCIL_BUFFER_SIZE 0
+#define STENCIL_BUFFER_SIZE 8
/**
* Debug level for app developers. The value is a numeric value defined
@@ -56,11 +56,17 @@ enum DebugLevel {
};
/**
- * Used to enable/disbale layers update debugging. The accepted values are
+ * Used to enable/disable layers update debugging. The accepted values are
* "true" and "false". The default value is "false".
*/
#define PROPERTY_DEBUG_LAYERS_UPDATES "debug.hwui.show_layers_updates"
+/**
+ * Used to enable/disable overdraw debugging. The accepted values are
+ * "true" and "false". The default value is "false".
+ */
+#define PROPERTY_DEBUG_OVERDRAW "debug.hwui.show_overdraw"
+
// These properties are defined in mega-bytes
#define PROPERTY_TEXTURE_CACHE_SIZE "ro.hwui.texture_cache_size"
#define PROPERTY_LAYER_CACHE_SIZE "ro.hwui.layer_cache_size"
diff --git a/libs/hwui/ResourceCache.cpp b/libs/hwui/ResourceCache.cpp
index 1c83ea4..18d8324 100644
--- a/libs/hwui/ResourceCache.cpp
+++ b/libs/hwui/ResourceCache.cpp
@@ -155,7 +155,7 @@ void ResourceCache::decrementRefcountLocked(void* resource) {
}
ref->refCount--;
if (ref->refCount == 0) {
- deleteResourceReference(resource, ref);
+ deleteResourceReferenceLocked(resource, ref);
}
}
@@ -201,7 +201,7 @@ void ResourceCache::destructorLocked(SkPath* resource) {
}
ref->destroyed = true;
if (ref->refCount == 0) {
- deleteResourceReference(resource, ref);
+ deleteResourceReferenceLocked(resource, ref);
}
}
@@ -223,7 +223,7 @@ void ResourceCache::destructorLocked(SkBitmap* resource) {
}
ref->destroyed = true;
if (ref->refCount == 0) {
- deleteResourceReference(resource, ref);
+ deleteResourceReferenceLocked(resource, ref);
}
}
@@ -242,7 +242,7 @@ void ResourceCache::destructorLocked(SkiaShader* resource) {
}
ref->destroyed = true;
if (ref->refCount == 0) {
- deleteResourceReference(resource, ref);
+ deleteResourceReferenceLocked(resource, ref);
}
}
@@ -261,7 +261,7 @@ void ResourceCache::destructorLocked(SkiaColorFilter* resource) {
}
ref->destroyed = true;
if (ref->refCount == 0) {
- deleteResourceReference(resource, ref);
+ deleteResourceReferenceLocked(resource, ref);
}
}
@@ -284,7 +284,7 @@ void ResourceCache::recycleLocked(SkBitmap* resource) {
}
ref->recycled = true;
if (ref->refCount == 0) {
- deleteResourceReference(resource, ref);
+ deleteResourceReferenceLocked(resource, ref);
}
}
@@ -292,7 +292,7 @@ void ResourceCache::recycleLocked(SkBitmap* resource) {
* This method should only be called while the mLock mutex is held (that mutex is grabbed
* by the various destructor() and recycle() methods which call this method).
*/
-void ResourceCache::deleteResourceReference(void* resource, ResourceReference* ref) {
+void ResourceCache::deleteResourceReferenceLocked(void* resource, ResourceReference* ref) {
if (ref->recycled && ref->resourceType == kBitmap) {
((SkBitmap*) resource)->setPixels(NULL, NULL);
}
@@ -326,6 +326,7 @@ void ResourceCache::deleteResourceReference(void* resource, ResourceReference* r
break;
case kLayer: {
Layer* layer = (Layer*) resource;
+ layer->freeResourcesLocked();
delete layer;
}
break;
diff --git a/libs/hwui/ResourceCache.h b/libs/hwui/ResourceCache.h
index 2053d96..a80670c 100644
--- a/libs/hwui/ResourceCache.h
+++ b/libs/hwui/ResourceCache.h
@@ -103,7 +103,7 @@ public:
void recycleLocked(SkBitmap* resource);
private:
- void deleteResourceReference(void* resource, ResourceReference* ref);
+ void deleteResourceReferenceLocked(void* resource, ResourceReference* ref);
void incrementRefcount(void* resource, ResourceType resourceType);
void incrementRefcountLocked(void* resource, ResourceType resourceType);
diff --git a/libs/hwui/Stencil.cpp b/libs/hwui/Stencil.cpp
index 9d2c86f..84df82b 100644
--- a/libs/hwui/Stencil.cpp
+++ b/libs/hwui/Stencil.cpp
@@ -37,9 +37,10 @@ void Stencil::clear() {
void Stencil::enableTest() {
if (mState != kTest) {
enable();
- glStencilFunc(GL_LESS, 0x0, 0x1);
+ glStencilFunc(GL_EQUAL, 0x1, 0x1);
// We only want to test, let's keep everything
glStencilOp(GL_KEEP, GL_KEEP, GL_KEEP);
+ glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
mState = kTest;
}
}
@@ -50,12 +51,32 @@ void Stencil::enableWrite() {
glStencilFunc(GL_ALWAYS, 0x1, 0x1);
// The test always passes so the first two values are meaningless
glStencilOp(GL_KEEP, GL_KEEP, GL_REPLACE);
+ glColorMask(GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE);
+ mState = kWrite;
+ }
+}
+
+void Stencil::enableDebugTest(GLint value, bool greater) {
+ enable();
+ glStencilFunc(greater ? GL_LESS : GL_EQUAL, value, 0xffffffff);
+ // We only want to test, let's keep everything
+ glStencilOp(GL_KEEP, GL_KEEP, GL_KEEP);
+ mState = kTest;
+}
+
+void Stencil::enableDebugWrite() {
+ if (mState != kWrite) {
+ enable();
+ glStencilFunc(GL_ALWAYS, 0x1, 0xffffffff);
+ // The test always passes so the first two values are meaningless
+ glStencilOp(GL_KEEP, GL_KEEP, GL_INCR);
+ glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
mState = kWrite;
}
}
void Stencil::enable() {
- if (!mState == kDisabled) {
+ if (mState == kDisabled) {
glEnable(GL_STENCIL_TEST);
}
}
diff --git a/libs/hwui/Stencil.h b/libs/hwui/Stencil.h
index 67ccc78..2f8a66a 100644
--- a/libs/hwui/Stencil.h
+++ b/libs/hwui/Stencil.h
@@ -59,6 +59,16 @@ public:
void enableWrite();
/**
+ * The test passes only when equal to the specified value.
+ */
+ void enableDebugTest(GLint value, bool greater = false);
+
+ /**
+ * Used for debugging. The stencil test always passes and increments.
+ */
+ void enableDebugWrite();
+
+ /**
* Disables stencil test and write.
*/
void disable();
diff --git a/libs/hwui/font/CacheTexture.cpp b/libs/hwui/font/CacheTexture.cpp
index 4a3af12..f653592 100644
--- a/libs/hwui/font/CacheTexture.cpp
+++ b/libs/hwui/font/CacheTexture.cpp
@@ -171,6 +171,9 @@ bool CacheTexture::fitBitmap(const SkGlyph& glyph, uint32_t* retOriginX, uint32_
}
mDirty = true;
+ const Rect r(*retOriginX - TEXTURE_BORDER_SIZE, *retOriginY - TEXTURE_BORDER_SIZE,
+ *retOriginX + glyphW, *retOriginY + glyphH);
+ mDirtyRect.unionWith(r);
mNumGlyphs++;
#if DEBUG_FONT_RENDERER
diff --git a/libs/hwui/font/CacheTexture.h b/libs/hwui/font/CacheTexture.h
index bf1f4a9..fdd1623 100644
--- a/libs/hwui/font/CacheTexture.h
+++ b/libs/hwui/font/CacheTexture.h
@@ -24,6 +24,7 @@
#include <utils/Log.h>
#include "FontUtil.h"
+#include "Rect.h"
namespace android {
namespace uirenderer {
@@ -77,12 +78,7 @@ public:
}
~CacheTexture() {
- if (mTexture) {
- delete[] mTexture;
- }
- if (mTextureId) {
- glDeleteTextures(1, &mTextureId);
- }
+ releaseTexture();
reset();
}
@@ -105,38 +101,40 @@ public:
void releaseTexture() {
if (mTexture) {
- glDeleteTextures(1, &mTextureId);
delete[] mTexture;
mTexture = NULL;
+ }
+ if (mTextureId) {
+ glDeleteTextures(1, &mTextureId);
mTextureId = 0;
}
+ mDirty = false;
}
/**
* This method assumes that the proper texture unit is active.
*/
void allocateTexture() {
- int width = mWidth;
- int height = mHeight;
-
- mTexture = new uint8_t[width * height];
+ if (!mTexture) {
+ mTexture = new uint8_t[mWidth * mHeight];
+ }
if (!mTextureId) {
glGenTextures(1, &mTextureId);
- }
- glBindTexture(GL_TEXTURE_2D, mTextureId);
- glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
- // Initialize texture dimensions
- glTexImage2D(GL_TEXTURE_2D, 0, GL_ALPHA, width, height, 0,
- GL_ALPHA, GL_UNSIGNED_BYTE, 0);
+ glBindTexture(GL_TEXTURE_2D, mTextureId);
+ glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
+ // Initialize texture dimensions
+ glTexImage2D(GL_TEXTURE_2D, 0, GL_ALPHA, mWidth, mHeight, 0,
+ GL_ALPHA, GL_UNSIGNED_BYTE, 0);
- const GLenum filtering = getLinearFiltering() ? GL_LINEAR : GL_NEAREST;
- glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, filtering);
- glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, filtering);
+ const GLenum filtering = getLinearFiltering() ? GL_LINEAR : GL_NEAREST;
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, filtering);
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, filtering);
- glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
- glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
+ }
}
bool fitBitmap(const SkGlyph& glyph, uint32_t* retOriginX, uint32_t* retOriginY);
@@ -149,11 +147,16 @@ public:
return mHeight;
}
+ inline const Rect* getDirtyRect() const {
+ return &mDirtyRect;
+ }
+
inline uint8_t* getTexture() const {
return mTexture;
}
- inline GLuint getTextureId() const {
+ GLuint getTextureId() {
+ allocateTexture();
return mTextureId;
}
@@ -163,6 +166,9 @@ public:
inline void setDirty(bool dirty) {
mDirty = dirty;
+ if (!dirty) {
+ mDirtyRect.setEmpty();
+ }
}
inline bool getLinearFiltering() const {
@@ -196,6 +202,7 @@ private:
bool mDirty;
uint16_t mNumGlyphs;
CacheBlock* mCacheBlocks;
+ Rect mDirtyRect;
};
}; // namespace uirenderer