diff options
Diffstat (limited to 'libs')
-rw-r--r-- | libs/hwui/Caches.cpp | 13 | ||||
-rw-r--r-- | libs/hwui/Caches.h | 1 | ||||
-rwxr-xr-x | libs/hwui/Dither.cpp | 4 | ||||
-rw-r--r-- | libs/hwui/FontRenderer.cpp | 17 | ||||
-rw-r--r-- | libs/hwui/Layer.cpp | 7 | ||||
-rw-r--r-- | libs/hwui/Layer.h | 3 | ||||
-rw-r--r-- | libs/hwui/OpenGLRenderer.cpp | 47 | ||||
-rw-r--r-- | libs/hwui/OpenGLRenderer.h | 3 | ||||
-rw-r--r-- | libs/hwui/ProgramCache.cpp | 53 | ||||
-rw-r--r-- | libs/hwui/Properties.h | 10 | ||||
-rw-r--r-- | libs/hwui/ResourceCache.cpp | 15 | ||||
-rw-r--r-- | libs/hwui/ResourceCache.h | 2 | ||||
-rw-r--r-- | libs/hwui/Stencil.cpp | 25 | ||||
-rw-r--r-- | libs/hwui/Stencil.h | 10 | ||||
-rw-r--r-- | libs/hwui/font/CacheTexture.cpp | 3 | ||||
-rw-r--r-- | libs/hwui/font/CacheTexture.h | 53 |
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 |