diff options
Diffstat (limited to 'libs/hwui')
-rw-r--r-- | libs/hwui/Android.mk | 1 | ||||
-rw-r--r-- | libs/hwui/Caches.cpp | 47 | ||||
-rw-r--r-- | libs/hwui/Caches.h | 17 | ||||
-rw-r--r-- | libs/hwui/DisplayListLogBuffer.h | 1 | ||||
-rw-r--r-- | libs/hwui/DisplayListRenderer.cpp | 13 | ||||
-rw-r--r-- | libs/hwui/DisplayListRenderer.h | 99 | ||||
-rw-r--r-- | libs/hwui/FontRenderer.cpp | 12 | ||||
-rw-r--r-- | libs/hwui/GammaFontRenderer.cpp | 63 | ||||
-rw-r--r-- | libs/hwui/GammaFontRenderer.h | 39 | ||||
-rw-r--r-- | libs/hwui/LayerRenderer.cpp | 24 | ||||
-rw-r--r-- | libs/hwui/LayerRenderer.h | 33 | ||||
-rw-r--r-- | libs/hwui/Matrix.h | 4 | ||||
-rw-r--r-- | libs/hwui/OpenGLRenderer.cpp | 6 | ||||
-rw-r--r-- | libs/hwui/OpenGLRenderer.h | 14 | ||||
-rw-r--r-- | libs/hwui/Patch.cpp | 33 | ||||
-rw-r--r-- | libs/hwui/Properties.h | 5 | ||||
-rw-r--r-- | libs/hwui/ResourceCache.h | 4 | ||||
-rw-r--r-- | libs/hwui/SkiaColorFilter.h | 10 | ||||
-rw-r--r-- | libs/hwui/SkiaShader.h | 24 | ||||
-rw-r--r-- | libs/hwui/Snapshot.h | 3 | ||||
-rw-r--r-- | libs/hwui/TextureCache.cpp | 31 | ||||
-rw-r--r-- | libs/hwui/TextureCache.h | 13 |
22 files changed, 344 insertions, 152 deletions
diff --git a/libs/hwui/Android.mk b/libs/hwui/Android.mk index a98e4cd..9bfc94c 100644 --- a/libs/hwui/Android.mk +++ b/libs/hwui/Android.mk @@ -39,6 +39,7 @@ ifeq ($(USE_OPENGL_RENDERER),true) external/skia/include/utils LOCAL_CFLAGS += -DUSE_OPENGL_RENDERER + LOCAL_CFLAGS += -fvisibility=hidden LOCAL_MODULE_CLASS := SHARED_LIBRARIES LOCAL_SHARED_LIBRARIES := libcutils libutils libGLESv2 libskia libui LOCAL_MODULE := libhwui diff --git a/libs/hwui/Caches.cpp b/libs/hwui/Caches.cpp index 24ec4e8..f293cba 100644 --- a/libs/hwui/Caches.cpp +++ b/libs/hwui/Caches.cpp @@ -46,22 +46,16 @@ namespace uirenderer { // Constructors/destructor /////////////////////////////////////////////////////////////////////////////// -Caches::Caches(): Singleton<Caches>(), blend(false), lastSrcMode(GL_ZERO), - lastDstMode(GL_ZERO), currentProgram(NULL) { +Caches::Caches(): Singleton<Caches>(), mInitialized(false) { GLint maxTextureUnits; glGetIntegerv(GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS, &maxTextureUnits); if (maxTextureUnits < REQUIRED_TEXTURE_UNITS_COUNT) { LOGW("At least %d texture units are required!", REQUIRED_TEXTURE_UNITS_COUNT); } - glGenBuffers(1, &meshBuffer); - glBindBuffer(GL_ARRAY_BUFFER, meshBuffer); - glBufferData(GL_ARRAY_BUFFER, sizeof(gMeshVertices), gMeshVertices, GL_STATIC_DRAW); - glGetIntegerv(GL_MAX_TEXTURE_SIZE, &maxTextureSize); - mCurrentBuffer = meshBuffer; - mRegionMesh = NULL; + init(); mDebugLevel = readDebugLevel(); LOGD("Enabling debug mode %d", mDebugLevel); @@ -71,8 +65,40 @@ Caches::Caches(): Singleton<Caches>(), blend(false), lastSrcMode(GL_ZERO), #endif } -Caches::~Caches() { +void Caches::init() { + if (mInitialized) return; + + glGenBuffers(1, &meshBuffer); + glBindBuffer(GL_ARRAY_BUFFER, meshBuffer); + glBufferData(GL_ARRAY_BUFFER, sizeof(gMeshVertices), gMeshVertices, GL_STATIC_DRAW); + + mCurrentBuffer = meshBuffer; + mRegionMesh = NULL; + + blend = false; + lastSrcMode = GL_ZERO; + lastDstMode = GL_ZERO; + currentProgram = NULL; + + mInitialized = true; +} + +void Caches::terminate() { + if (!mInitialized) return; + + glDeleteBuffers(1, &meshBuffer); + mCurrentBuffer = 0; + + glDeleteBuffers(1, &mRegionMeshIndices); delete[] mRegionMesh; + mRegionMesh = NULL; + + fboCache.clear(); + + programCache.clear(); + currentProgram = NULL; + + mInitialized = false; } /////////////////////////////////////////////////////////////////////////////// @@ -170,8 +196,11 @@ void Caches::flush(FlushMode mode) { patchCache.clear(); dropShadowCache.clear(); gradientCache.clear(); + fontRenderer.clear(); // fall through case kFlushMode_Moderate: + fontRenderer.flush(); + textureCache.flush(); pathCache.clear(); roundRectShapeCache.clear(); circleShapeCache.clear(); diff --git a/libs/hwui/Caches.h b/libs/hwui/Caches.h index cdcbf21..5e58a9e 100644 --- a/libs/hwui/Caches.h +++ b/libs/hwui/Caches.h @@ -23,6 +23,8 @@ #include <utils/Singleton.h> +#include <cutils/compiler.h> + #include "Extensions.h" #include "FontRenderer.h" #include "GammaFontRenderer.h" @@ -82,9 +84,8 @@ struct CacheLogger { // Caches /////////////////////////////////////////////////////////////////////////////// -class Caches: public Singleton<Caches> { +class ANDROID_API Caches: public Singleton<Caches> { Caches(); - ~Caches(); friend class Singleton<Caches>; @@ -107,6 +108,11 @@ public: }; /** + * Initializes the cache. + */ + void init(); + + /** * Flush the cache. * * @param mode Indicates how much of the cache should be flushed @@ -114,6 +120,12 @@ public: void flush(FlushMode mode); /** + * Destroys all resources associated with this cache. This should + * be called after a flush(kFlushMode_Full). + */ + void terminate(); + + /** * Indicates whether the renderer is in debug mode. * This debug mode provides limited information to app developers. */ @@ -192,6 +204,7 @@ public: private: DebugLevel mDebugLevel; + bool mInitialized; }; // class Caches }; // namespace uirenderer diff --git a/libs/hwui/DisplayListLogBuffer.h b/libs/hwui/DisplayListLogBuffer.h index bf16f29..5d689bb 100644 --- a/libs/hwui/DisplayListLogBuffer.h +++ b/libs/hwui/DisplayListLogBuffer.h @@ -18,6 +18,7 @@ #define ANDROID_HWUI_DISPLAY_LIST_LOG_BUFFER_H #include <utils/Singleton.h> + #include <stdio.h> namespace android { diff --git a/libs/hwui/DisplayListRenderer.cpp b/libs/hwui/DisplayListRenderer.cpp index cedf456..3372d1c 100644 --- a/libs/hwui/DisplayListRenderer.cpp +++ b/libs/hwui/DisplayListRenderer.cpp @@ -382,12 +382,13 @@ void DisplayList::output(OpenGLRenderer& renderer, uint32_t level) { xDivs = getInts(xDivsCount); yDivs = getInts(yDivsCount); colors = getUInts(numColors); - DISPLAY_LIST_LOGD("%s%s", (char*) indent, OP_NAMES[op]); - getFloat(); - getFloat(); - getFloat(); - getFloat(); - getPaint(); + float left = getFloat(); + float top = getFloat(); + float right = getFloat(); + float bottom = getFloat(); + SkPaint* paint = getPaint(); + LOGD("%s%s %.2f, %.2f, %.2f, %.2f", (char*) indent, OP_NAMES[op], + left, top, right, bottom); } break; case DrawColor: { diff --git a/libs/hwui/DisplayListRenderer.h b/libs/hwui/DisplayListRenderer.h index 8cd7fea..ab475bf 100644 --- a/libs/hwui/DisplayListRenderer.h +++ b/libs/hwui/DisplayListRenderer.h @@ -26,6 +26,8 @@ #include <SkTDArray.h> #include <SkTSearch.h> +#include <cutils/compiler.h> + #include "DisplayListLogBuffer.h" #include "OpenGLRenderer.h" #include "utils/Functor.h" @@ -58,7 +60,7 @@ class DisplayListRenderer; class DisplayList { public: DisplayList(const DisplayListRenderer& recorder); - ~DisplayList(); + ANDROID_API ~DisplayList(); // IMPORTANT: Update the intialization of OP_NAMES in the .cpp file // when modifying this file @@ -107,13 +109,13 @@ public: void initFromDisplayListRenderer(const DisplayListRenderer& recorder, bool reusing = false); - size_t getSize(); + ANDROID_API size_t getSize(); bool replay(OpenGLRenderer& renderer, Rect& dirty, uint32_t level = 0); void output(OpenGLRenderer& renderer, uint32_t level = 0); - static void outputLogBuffer(int fd); + ANDROID_API static void outputLogBuffer(int fd); void setRenderable(bool renderable) { mIsRenderable = renderable; @@ -230,75 +232,76 @@ private: */ class DisplayListRenderer: public OpenGLRenderer { public: - DisplayListRenderer(); - ~DisplayListRenderer(); + ANDROID_API DisplayListRenderer(); + virtual ~DisplayListRenderer(); - DisplayList* getDisplayList(DisplayList* displayList); + ANDROID_API DisplayList* getDisplayList(DisplayList* displayList); - void setViewport(int width, int height); - void prepareDirty(float left, float top, float right, float bottom, bool opaque); - void finish(); + virtual void setViewport(int width, int height); + virtual void prepareDirty(float left, float top, float right, float bottom, bool opaque); + virtual void finish(); - bool callDrawGLFunction(Functor *functor, Rect& dirty); + virtual bool callDrawGLFunction(Functor *functor, Rect& dirty); - void interrupt(); - void resume(); + virtual void interrupt(); + virtual void resume(); - int save(int flags); - void restore(); - void restoreToCount(int saveCount); + virtual int save(int flags); + virtual void restore(); + virtual void restoreToCount(int saveCount); - int saveLayer(float left, float top, float right, float bottom, + virtual int saveLayer(float left, float top, float right, float bottom, SkPaint* p, int flags); - int saveLayerAlpha(float left, float top, float right, float bottom, + virtual int saveLayerAlpha(float left, float top, float right, float bottom, int alpha, int flags); - void translate(float dx, float dy); - void rotate(float degrees); - void scale(float sx, float sy); - void skew(float sx, float sy); + virtual void translate(float dx, float dy); + virtual void rotate(float degrees); + virtual void scale(float sx, float sy); + virtual void skew(float sx, float sy); - void setMatrix(SkMatrix* matrix); - void concatMatrix(SkMatrix* matrix); + virtual void setMatrix(SkMatrix* matrix); + virtual void concatMatrix(SkMatrix* matrix); - bool clipRect(float left, float top, float right, float bottom, SkRegion::Op op); + virtual bool clipRect(float left, float top, float right, float bottom, SkRegion::Op op); - bool drawDisplayList(DisplayList* displayList, uint32_t width, uint32_t height, + virtual bool drawDisplayList(DisplayList* displayList, uint32_t width, uint32_t height, Rect& dirty, uint32_t level = 0); - void drawLayer(Layer* layer, float x, float y, SkPaint* paint); - void drawBitmap(SkBitmap* bitmap, float left, float top, SkPaint* paint); - void drawBitmap(SkBitmap* bitmap, SkMatrix* matrix, SkPaint* paint); - void drawBitmap(SkBitmap* bitmap, float srcLeft, float srcTop, + virtual void drawLayer(Layer* layer, float x, float y, SkPaint* paint); + virtual void drawBitmap(SkBitmap* bitmap, float left, float top, SkPaint* paint); + virtual void drawBitmap(SkBitmap* bitmap, SkMatrix* matrix, SkPaint* paint); + virtual void drawBitmap(SkBitmap* bitmap, float srcLeft, float srcTop, float srcRight, float srcBottom, float dstLeft, float dstTop, float dstRight, float dstBottom, SkPaint* paint); - void drawBitmapMesh(SkBitmap* bitmap, int meshWidth, int meshHeight, + virtual void drawBitmapMesh(SkBitmap* bitmap, int meshWidth, int meshHeight, float* vertices, int* colors, SkPaint* paint); - void drawPatch(SkBitmap* bitmap, const int32_t* xDivs, const int32_t* yDivs, + virtual void drawPatch(SkBitmap* bitmap, const int32_t* xDivs, const int32_t* yDivs, const uint32_t* colors, uint32_t width, uint32_t height, int8_t numColors, float left, float top, float right, float bottom, SkPaint* paint); - void drawColor(int color, SkXfermode::Mode mode); - void drawRect(float left, float top, float right, float bottom, SkPaint* paint); - void drawRoundRect(float left, float top, float right, float bottom, + virtual void drawColor(int color, SkXfermode::Mode mode); + virtual void drawRect(float left, float top, float right, float bottom, SkPaint* paint); + virtual void drawRoundRect(float left, float top, float right, float bottom, float rx, float ry, SkPaint* paint); - void drawCircle(float x, float y, float radius, SkPaint* paint); - void drawOval(float left, float top, float right, float bottom, SkPaint* paint); - void drawArc(float left, float top, float right, float bottom, + virtual void drawCircle(float x, float y, float radius, SkPaint* paint); + virtual void drawOval(float left, float top, float right, float bottom, SkPaint* paint); + virtual void drawArc(float left, float top, float right, float bottom, float startAngle, float sweepAngle, bool useCenter, SkPaint* paint); - void drawPath(SkPath* path, SkPaint* paint); - void drawLines(float* points, int count, SkPaint* paint); - void drawPoints(float* points, int count, SkPaint* paint); - void drawText(const char* text, int bytesCount, int count, float x, float y, SkPaint* paint); + virtual void drawPath(SkPath* path, SkPaint* paint); + virtual void drawLines(float* points, int count, SkPaint* paint); + virtual void drawPoints(float* points, int count, SkPaint* paint); + virtual void drawText(const char* text, int bytesCount, int count, float x, float y, + SkPaint* paint); - void resetShader(); - void setupShader(SkiaShader* shader); + virtual void resetShader(); + virtual void setupShader(SkiaShader* shader); - void resetColorFilter(); - void setupColorFilter(SkiaColorFilter* filter); + virtual void resetColorFilter(); + virtual void setupColorFilter(SkiaColorFilter* filter); - void resetShadow(); - void setupShadow(float radius, float dx, float dy, int color); + virtual void resetShadow(); + virtual void setupShadow(float radius, float dx, float dy, int color); - void reset(); + ANDROID_API void reset(); const SkWriter32& writeStream() const { return mWriter; diff --git a/libs/hwui/FontRenderer.cpp b/libs/hwui/FontRenderer.cpp index a077cbc..158f785 100644 --- a/libs/hwui/FontRenderer.cpp +++ b/libs/hwui/FontRenderer.cpp @@ -163,7 +163,6 @@ void Font::render(SkPaint* paint, const char* text, uint32_t start, uint32_t len render(paint, text, start, len, numGlyphs, x, y, FRAMEBUFFER, NULL, 0, 0, NULL); } - } void Font::measure(SkPaint* paint, const char* text, uint32_t start, uint32_t len, @@ -615,7 +614,8 @@ void FontRenderer::issueDrawCommand() { void FontRenderer::appendMeshQuad(float x1, float y1, float z1, float u1, float v1, float x2, float y2, float z2, float u2, float v2, float x3, float y3, float z3, float u3, float v3, float x4, float y4, float z4, float u4, float v4) { - if (x1 > mClip->right || y1 < mClip->top || x2 < mClip->left || y4 > mClip->bottom) { + if (mClip && + (x1 > mClip->right || y1 < mClip->top || x2 < mClip->left || y4 > mClip->bottom)) { return; } @@ -723,11 +723,16 @@ FontRenderer::DropShadow FontRenderer::renderDropShadow(SkPaint* paint, const ch return image; } + mClip = NULL; + mBounds = NULL; + Rect bounds; mCurrentFont->measure(paint, text, startIndex, len, numGlyphs, &bounds); + uint32_t paddedWidth = (uint32_t) (bounds.right - bounds.left) + 2 * radius; uint32_t paddedHeight = (uint32_t) (bounds.top - bounds.bottom) + 2 * radius; uint8_t* dataBuffer = new uint8_t[paddedWidth * paddedHeight]; + for (uint32_t i = 0; i < paddedWidth * paddedHeight; i++) { dataBuffer[i] = 0; } @@ -765,8 +770,11 @@ bool FontRenderer::renderText(SkPaint* paint, const Rect* clip, const char *text mDrawn = false; mBounds = bounds; mClip = clip; + mCurrentFont->render(paint, text, startIndex, len, numGlyphs, x, y); + mBounds = NULL; + mClip = NULL; if (mCurrentQuadIndex != 0) { issueDrawCommand(); diff --git a/libs/hwui/GammaFontRenderer.cpp b/libs/hwui/GammaFontRenderer.cpp index e8362dc..eb863e9 100644 --- a/libs/hwui/GammaFontRenderer.cpp +++ b/libs/hwui/GammaFontRenderer.cpp @@ -67,20 +67,63 @@ GammaFontRenderer::GammaFontRenderer() { const float whiteGamma = 1.0f / gamma; for (uint32_t i = 0; i <= 255; i++) { - mDefault[i] = i; + mGammaTable[i] = i; const float v = i / 255.0f; const float black = pow(v, blackGamma); const float white = pow(v, whiteGamma); - mBlackGamma[i] = uint8_t((float)::floor(black * 255.0f + 0.5f)); - mWhiteGamma[i] = uint8_t((float)::floor(white * 255.0f + 0.5f)); + mGammaTable[256 + i] = uint8_t((float)::floor(black * 255.0f + 0.5f)); + mGammaTable[512 + i] = uint8_t((float)::floor(white * 255.0f + 0.5f)); } - // Configure the font renderers - mDefaultRenderer.setGammaTable(&mDefault[0]); - mBlackGammaRenderer.setGammaTable(&mBlackGamma[0]); - mWhiteGammaRenderer.setGammaTable(&mWhiteGamma[0]); + memset(mRenderers, 0, sizeof(FontRenderer*) * kGammaCount); + memset(mRenderersUsageCount, 0, sizeof(uint32_t) * kGammaCount); +} + +GammaFontRenderer::~GammaFontRenderer() { + for (int i = 0; i < kGammaCount; i++) { + delete mRenderers[i]; + } +} + +void GammaFontRenderer::clear() { + for (int i = 0; i < kGammaCount; i++) { + delete mRenderers[i]; + mRenderers[i] = NULL; + } +} + +void GammaFontRenderer::flush() { + int count = 0; + int min = -1; + uint32_t minCount = UINT_MAX; + + for (int i = 0; i < kGammaCount; i++) { + if (mRenderers[i]) { + count++; + if (mRenderersUsageCount[i] < minCount) { + minCount = mRenderersUsageCount[i]; + min = i; + } + } + } + + if (count <= 1 || min < 0) return; + + delete mRenderers[min]; + mRenderers[min] = NULL; +} + +FontRenderer* GammaFontRenderer::getRenderer(Gamma gamma) { + FontRenderer* renderer = mRenderers[gamma]; + if (!renderer) { + renderer = new FontRenderer(); + mRenderers[gamma] = renderer; + renderer->setGammaTable(&mGammaTable[gamma * 256]); + } + mRenderersUsageCount[gamma]++; + return renderer; } FontRenderer& GammaFontRenderer::getFontRenderer(const SkPaint* paint) { @@ -92,12 +135,12 @@ FontRenderer& GammaFontRenderer::getFontRenderer(const SkPaint* paint) { const int luminance = (r * 2 + g * 5 + b) >> 3; if (luminance <= mBlackThreshold) { - return mBlackGammaRenderer; + return *getRenderer(kGammaBlack); } else if (luminance >= mWhiteThreshold) { - return mWhiteGammaRenderer; + return *getRenderer(kGammaWhite); } } - return mDefaultRenderer; + return *getRenderer(kGammaDefault); } }; // namespace uirenderer diff --git a/libs/hwui/GammaFontRenderer.h b/libs/hwui/GammaFontRenderer.h index 96d960c..54c208e 100644 --- a/libs/hwui/GammaFontRenderer.h +++ b/libs/hwui/GammaFontRenderer.h @@ -26,36 +26,43 @@ namespace uirenderer { struct GammaFontRenderer { GammaFontRenderer(); + ~GammaFontRenderer(); + + enum Gamma { + kGammaDefault = 0, + kGammaBlack = 1, + kGammaWhite = 2, + kGammaCount = 3 + }; + + void clear(); + void flush(); FontRenderer& getFontRenderer(const SkPaint* paint); uint32_t getFontRendererCount() const { - return 3; + return kGammaCount; } uint32_t getFontRendererSize(uint32_t fontRenderer) const { - switch (fontRenderer) { - case 0: - return mDefaultRenderer.getCacheHeight() * mDefaultRenderer.getCacheWidth(); - case 1: - return mBlackGammaRenderer.getCacheHeight() * mBlackGammaRenderer.getCacheWidth(); - case 2: - return mWhiteGammaRenderer.getCacheHeight() * mWhiteGammaRenderer.getCacheWidth(); - } - return 0; + if (fontRenderer >= kGammaCount) return 0; + + FontRenderer* renderer = mRenderers[fontRenderer]; + if (!renderer) return 0; + + return renderer->getCacheHeight() * renderer->getCacheWidth(); } private: - FontRenderer mDefaultRenderer; - FontRenderer mBlackGammaRenderer; - FontRenderer mWhiteGammaRenderer; + FontRenderer* getRenderer(Gamma gamma); + + uint32_t mRenderersUsageCount[kGammaCount]; + FontRenderer* mRenderers[kGammaCount]; int mBlackThreshold; int mWhiteThreshold; - uint8_t mDefault[256]; - uint8_t mBlackGamma[256]; - uint8_t mWhiteGamma[256]; + uint8_t mGammaTable[256 * kGammaCount]; }; }; // namespace uirenderer diff --git a/libs/hwui/LayerRenderer.cpp b/libs/hwui/LayerRenderer.cpp index 349b9e3..e38b479 100644 --- a/libs/hwui/LayerRenderer.cpp +++ b/libs/hwui/LayerRenderer.cpp @@ -31,6 +31,12 @@ namespace uirenderer { // Rendering /////////////////////////////////////////////////////////////////////////////// +LayerRenderer::LayerRenderer(Layer* layer): mLayer(layer) { +} + +LayerRenderer::~LayerRenderer() { +} + void LayerRenderer::prepareDirty(float left, float top, float right, float bottom, bool opaque) { LAYER_RENDERER_LOGD("Rendering into layer, fbo = %d", mLayer->getFbo()); @@ -210,7 +216,8 @@ Layer* LayerRenderer::createLayer(uint32_t width, uint32_t height, bool isOpaque layer->allocateTexture(GL_RGBA, GL_UNSIGNED_BYTE); if (glGetError() != GL_NO_ERROR) { - LOGD("Could not allocate texture"); + LOGD("Could not allocate texture for layer (fbo=%d %dx%d)", + fbo, width, height); glBindFramebuffer(GL_FRAMEBUFFER, previousFbo); Caches::getInstance().fboCache.put(fbo); @@ -264,7 +271,7 @@ Layer* LayerRenderer::createTextureLayer(bool isOpaque) { layer->setFbo(0); layer->setAlpha(255, SkXfermode::kSrcOver_Mode); layer->layer.set(0.0f, 0.0f, 0.0f, 0.0f); - layer->texCoords.set(0.0f, 1.0f, 0.0f, 1.0f); + layer->texCoords.set(0.0f, 1.0f, 1.0f, 0.0f); layer->region.clear(); layer->setRenderTarget(GL_NONE); // see ::updateTextureLayer() @@ -400,6 +407,18 @@ bool LayerRenderer::copyLayer(Layer* layer, SkBitmap* bitmap) { renderer.setViewport(bitmap->width(), bitmap->height()); renderer.OpenGLRenderer::prepareDirty(0.0f, 0.0f, bitmap->width(), bitmap->height(), !layer->isBlend()); + + glDisable(GL_SCISSOR_TEST); + renderer.translate(0.0f, bitmap->height()); + renderer.scale(1.0f, -1.0f); + + mat4 texTransform(layer->getTexTransform()); + + mat4 invert; + invert.translate(0.0f, 1.0f, 0.0f); + invert.scale(1.0f, -1.0f, 1.0f); + layer->getTexTransform().multiply(invert); + if ((error = glGetError()) != GL_NO_ERROR) goto error; { @@ -413,6 +432,7 @@ bool LayerRenderer::copyLayer(Layer* layer, SkBitmap* bitmap) { if ((error = glGetError()) != GL_NO_ERROR) goto error; } + layer->getTexTransform().load(texTransform); status = true; } diff --git a/libs/hwui/LayerRenderer.h b/libs/hwui/LayerRenderer.h index 2246573..6104301 100644 --- a/libs/hwui/LayerRenderer.h +++ b/libs/hwui/LayerRenderer.h @@ -17,6 +17,8 @@ #ifndef ANDROID_HWUI_LAYER_RENDERER_H #define ANDROID_HWUI_LAYER_RENDERER_H +#include <cutils/compiler.h> + #include "OpenGLRenderer.h" #include "Layer.h" @@ -42,27 +44,24 @@ namespace uirenderer { class LayerRenderer: public OpenGLRenderer { public: - LayerRenderer(Layer* layer): mLayer(layer) { - } - - ~LayerRenderer() { - } + ANDROID_API LayerRenderer(Layer* layer); + virtual ~LayerRenderer(); - void prepareDirty(float left, float top, float right, float bottom, bool opaque); - void finish(); + virtual void prepareDirty(float left, float top, float right, float bottom, bool opaque); + virtual void finish(); - bool hasLayer(); - Region* getRegion(); - GLint getTargetFbo(); + virtual bool hasLayer(); + virtual Region* getRegion(); + virtual GLint getTargetFbo(); - static Layer* createTextureLayer(bool isOpaque); - static Layer* createLayer(uint32_t width, uint32_t height, bool isOpaque = false); - static bool resizeLayer(Layer* layer, uint32_t width, uint32_t height); - static void updateTextureLayer(Layer* layer, uint32_t width, uint32_t height, + ANDROID_API static Layer* createTextureLayer(bool isOpaque); + ANDROID_API static Layer* createLayer(uint32_t width, uint32_t height, bool isOpaque = false); + ANDROID_API static bool resizeLayer(Layer* layer, uint32_t width, uint32_t height); + ANDROID_API static void updateTextureLayer(Layer* layer, uint32_t width, uint32_t height, bool isOpaque, GLenum renderTarget, float* transform); - static void destroyLayer(Layer* layer); - static void destroyLayerDeferred(Layer* layer); - static bool copyLayer(Layer* layer, SkBitmap* bitmap); + ANDROID_API static void destroyLayer(Layer* layer); + ANDROID_API static void destroyLayerDeferred(Layer* layer); + ANDROID_API static bool copyLayer(Layer* layer, SkBitmap* bitmap); private: void generateMesh(); diff --git a/libs/hwui/Matrix.h b/libs/hwui/Matrix.h index 56fd37d..22220a9 100644 --- a/libs/hwui/Matrix.h +++ b/libs/hwui/Matrix.h @@ -19,6 +19,8 @@ #include <SkMatrix.h> +#include <cutils/compiler.h> + #include "Rect.h" namespace android { @@ -28,7 +30,7 @@ namespace uirenderer { // Classes /////////////////////////////////////////////////////////////////////////////// -class Matrix4 { +class ANDROID_API Matrix4 { public: float data[16]; diff --git a/libs/hwui/OpenGLRenderer.cpp b/libs/hwui/OpenGLRenderer.cpp index 32595e4..4d22646 100644 --- a/libs/hwui/OpenGLRenderer.cpp +++ b/libs/hwui/OpenGLRenderer.cpp @@ -201,14 +201,16 @@ void OpenGLRenderer::interrupt() { } void OpenGLRenderer::resume() { - glViewport(0, 0, mSnapshot->viewport.getWidth(), mSnapshot->viewport.getHeight()); + sp<Snapshot> snapshot = (mSnapshot != NULL) ? mSnapshot : mFirstSnapshot; + + glViewport(0, 0, snapshot->viewport.getWidth(), snapshot->viewport.getHeight()); glEnable(GL_SCISSOR_TEST); dirtyClip(); glDisable(GL_DITHER); - glBindFramebuffer(GL_FRAMEBUFFER, getTargetFbo()); + glBindFramebuffer(GL_FRAMEBUFFER, snapshot->fbo); glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0); mCaches.blend = true; diff --git a/libs/hwui/OpenGLRenderer.h b/libs/hwui/OpenGLRenderer.h index 14b22b3..2fc88e1 100644 --- a/libs/hwui/OpenGLRenderer.h +++ b/libs/hwui/OpenGLRenderer.h @@ -31,6 +31,8 @@ #include <utils/RefBase.h> #include <utils/Vector.h> +#include <cutils/compiler.h> + #include "Debug.h" #include "Extensions.h" #include "Matrix.h" @@ -57,12 +59,12 @@ class DisplayList; */ class OpenGLRenderer { public: - OpenGLRenderer(); + ANDROID_API OpenGLRenderer(); virtual ~OpenGLRenderer(); virtual void setViewport(int width, int height); - void prepare(bool opaque); + ANDROID_API void prepare(bool opaque); virtual void prepareDirty(float left, float top, float right, float bottom, bool opaque); virtual void finish(); @@ -72,7 +74,7 @@ public: virtual bool callDrawGLFunction(Functor *functor, Rect& dirty); - int getSaveCount() const; + ANDROID_API int getSaveCount() const; virtual int save(int flags); virtual void restore(); virtual void restoreToCount(int saveCount); @@ -87,12 +89,12 @@ public: virtual void scale(float sx, float sy); virtual void skew(float sx, float sy); - void getMatrix(SkMatrix* matrix); + ANDROID_API void getMatrix(SkMatrix* matrix); virtual void setMatrix(SkMatrix* matrix); virtual void concatMatrix(SkMatrix* matrix); - const Rect& getClipBounds(); - bool quickReject(float left, float top, float right, float bottom); + ANDROID_API const Rect& getClipBounds(); + ANDROID_API bool quickReject(float left, float top, float right, float bottom); virtual bool clipRect(float left, float top, float right, float bottom, SkRegion::Op op); virtual bool drawDisplayList(DisplayList* displayList, uint32_t width, uint32_t height, diff --git a/libs/hwui/Patch.cpp b/libs/hwui/Patch.cpp index f7dacae..47a2c99 100644 --- a/libs/hwui/Patch.cpp +++ b/libs/hwui/Patch.cpp @@ -157,14 +157,17 @@ void Patch::updateVertices(const float bitmapWidth, const float bitmapHeight, for (uint32_t i = 0; i < mYCount; i++) { float stepY = mYDivs[i]; + const float segment = stepY - previousStepY; if (i & 1) { - const float segment = stepY - previousStepY; y2 = y1 + floorf(segment * stretchY + 0.5f); } else { - y2 = y1 + stepY - previousStepY; + y2 = y1 + segment; } - float v2 = fmax(0.0f, stepY - 0.5f) / bitmapHeight; + + float vOffset = y1 == y2 ? 0.0f : 0.5 - (0.5 * segment / (y2 - y1)); + float v2 = fmax(0.0f, stepY - vOffset) / bitmapHeight; + v1 += vOffset / bitmapHeight; if (stepY > 0.0f) { #if DEBUG_EXPLODE_PATCHES @@ -179,7 +182,7 @@ void Patch::updateVertices(const float bitmapWidth, const float bitmapHeight, } y1 = y2; - v1 = (stepY + 0.5f) / bitmapHeight; + v1 = stepY / bitmapHeight; previousStepY = stepY; } @@ -190,8 +193,7 @@ void Patch::updateVertices(const float bitmapWidth, const float bitmapHeight, y1 += mYCount * EXPLODE_GAP; y2 += mYCount * EXPLODE_GAP; #endif - generateRow(vertex, y1, y2, v1, 1.0f, stretchX, right - left, - bitmapWidth, quadCount); + generateRow(vertex, y1, y2, v1, 1.0f, stretchX, right - left, bitmapWidth, quadCount); } if (verticesCount > 0) { @@ -220,14 +222,17 @@ void Patch::generateRow(TextureVertex*& vertex, float y1, float y2, float v1, fl // Generate the row quad by quad for (uint32_t i = 0; i < mXCount; i++) { float stepX = mXDivs[i]; + const float segment = stepX - previousStepX; if (i & 1) { - const float segment = stepX - previousStepX; x2 = x1 + floorf(segment * stretchX + 0.5f); } else { - x2 = x1 + stepX - previousStepX; + x2 = x1 + segment; } - float u2 = fmax(0.0f, stepX - 0.5f) / bitmapWidth; + + float uOffset = x1 == x2 ? 0.0f : 0.5 - (0.5 * segment / (x2 - x1)); + float u2 = fmax(0.0f, stepX - uOffset) / bitmapWidth; + u1 += uOffset / bitmapWidth; if (stepX > 0.0f) { #if DEBUG_EXPLODE_PATCHES @@ -241,7 +246,7 @@ void Patch::generateRow(TextureVertex*& vertex, float y1, float y2, float v1, fl } x1 = x2; - u1 = (stepX + 0.5f) / bitmapWidth; + u1 = stepX / bitmapWidth; previousStepX = stepX; } @@ -265,8 +270,8 @@ void Patch::generateQuad(TextureVertex*& vertex, float x1, float y1, float x2, f if ((mColorKey >> oldQuadCount) & 0x1) { #if DEBUG_PATCHES_EMPTY_VERTICES PATCH_LOGD(" quad %d (empty)", oldQuadCount); - PATCH_LOGD(" left, top = %.2f, %.2f\t\tu1, v1 = %.2f, %.2f", x1, y1, u1, v1); - PATCH_LOGD(" right, bottom = %.2f, %.2f\t\tu2, v2 = %.2f, %.2f", x2, y2, u2, v2); + PATCH_LOGD(" left, top = %.2f, %.2f\t\tu1, v1 = %.4f, %.4f", x1, y1, u1, v1); + PATCH_LOGD(" right, bottom = %.2f, %.2f\t\tu2, v2 = %.4f, %.4f", x2, y2, u2, v2); #endif return; } @@ -294,8 +299,8 @@ void Patch::generateQuad(TextureVertex*& vertex, float x1, float y1, float x2, f #if DEBUG_PATCHES_VERTICES PATCH_LOGD(" quad %d", oldQuadCount); - PATCH_LOGD(" left, top = %.2f, %.2f\t\tu1, v1 = %.2f, %.2f", x1, y1, u1, v1); - PATCH_LOGD(" right, bottom = %.2f, %.2f\t\tu2, v2 = %.2f, %.2f", x2, y2, u2, v2); + PATCH_LOGD(" left, top = %.2f, %.2f\t\tu1, v1 = %.4f, %.4f", x1, y1, u1, v1); + PATCH_LOGD(" right, bottom = %.2f, %.2f\t\tu2, v2 = %.4f, %.4f", x2, y2, u2, v2); #endif } diff --git a/libs/hwui/Properties.h b/libs/hwui/Properties.h index 5bd0d4f..8c01e3a 100644 --- a/libs/hwui/Properties.h +++ b/libs/hwui/Properties.h @@ -61,6 +61,9 @@ enum DebugLevel { #define PROPERTY_DROP_SHADOW_CACHE_SIZE "ro.hwui.drop_shadow_cache_size" #define PROPERTY_FBO_CACHE_SIZE "ro.hwui.fbo_cache_size" +// These properties are defined in percentage (range 0..1) +#define PROPERTY_TEXTURE_CACHE_FLUSH_RATE "ro.hwui.texture_cache_flush_rate" + // These properties are defined in pixels #define PROPERTY_TEXT_CACHE_WIDTH "ro.hwui.text_cache_width" #define PROPERTY_TEXT_CACHE_HEIGHT "ro.hwui.text_cache_height" @@ -82,6 +85,8 @@ enum DebugLevel { #define DEFAULT_DROP_SHADOW_CACHE_SIZE 2.0f #define DEFAULT_FBO_CACHE_SIZE 16 +#define DEFAULT_TEXTURE_CACHE_FLUSH_RATE 0.6f + #define DEFAULT_TEXT_GAMMA 1.4f #define DEFAULT_TEXT_BLACK_GAMMA_THRESHOLD 64 #define DEFAULT_TEXT_WHITE_GAMMA_THRESHOLD 192 diff --git a/libs/hwui/ResourceCache.h b/libs/hwui/ResourceCache.h index 2a38910..8cf466b 100644 --- a/libs/hwui/ResourceCache.h +++ b/libs/hwui/ResourceCache.h @@ -17,6 +17,8 @@ #ifndef ANDROID_HWUI_RESOURCE_CACHE_H #define ANDROID_HWUI_RESOURCE_CACHE_H +#include <cutils/compiler.h> + #include <SkBitmap.h> #include <SkiaColorFilter.h> #include <SkiaShader.h> @@ -49,7 +51,7 @@ public: ResourceType resourceType; }; -class ResourceCache { +class ANDROID_API ResourceCache { KeyedVector<void *, ResourceReference *>* mCache; public: ResourceCache(); diff --git a/libs/hwui/SkiaColorFilter.h b/libs/hwui/SkiaColorFilter.h index 1bf475c..2feb834 100644 --- a/libs/hwui/SkiaColorFilter.h +++ b/libs/hwui/SkiaColorFilter.h @@ -20,6 +20,8 @@ #include <GLES2/gl2.h> #include <SkColorFilter.h> +#include <cutils/compiler.h> + #include "ProgramCache.h" #include "Extensions.h" @@ -45,7 +47,7 @@ struct SkiaColorFilter { kBlend, }; - SkiaColorFilter(SkColorFilter *skFilter, Type type, bool blend); + ANDROID_API SkiaColorFilter(SkColorFilter *skFilter, Type type, bool blend); virtual ~SkiaColorFilter(); virtual void describe(ProgramDescription& description, const Extensions& extensions) = 0; @@ -79,7 +81,7 @@ private: * A color filter that multiplies the source color with a matrix and adds a vector. */ struct SkiaColorMatrixFilter: public SkiaColorFilter { - SkiaColorMatrixFilter(SkColorFilter *skFilter, float* matrix, float* vector); + ANDROID_API SkiaColorMatrixFilter(SkColorFilter *skFilter, float* matrix, float* vector); ~SkiaColorMatrixFilter(); void describe(ProgramDescription& description, const Extensions& extensions); @@ -95,7 +97,7 @@ private: * another fixed value. Ignores the alpha channel of both arguments. */ struct SkiaLightingFilter: public SkiaColorFilter { - SkiaLightingFilter(SkColorFilter *skFilter, int multiply, int add); + ANDROID_API SkiaLightingFilter(SkColorFilter *skFilter, int multiply, int add); void describe(ProgramDescription& description, const Extensions& extensions); void setupProgram(Program* program); @@ -110,7 +112,7 @@ private: * and PorterDuff blending mode. */ struct SkiaBlendFilter: public SkiaColorFilter { - SkiaBlendFilter(SkColorFilter *skFilter, int color, SkXfermode::Mode mode); + ANDROID_API SkiaBlendFilter(SkColorFilter *skFilter, int color, SkXfermode::Mode mode); void describe(ProgramDescription& description, const Extensions& extensions); void setupProgram(Program* program); diff --git a/libs/hwui/SkiaShader.h b/libs/hwui/SkiaShader.h index 89dd131..2de9a93 100644 --- a/libs/hwui/SkiaShader.h +++ b/libs/hwui/SkiaShader.h @@ -22,6 +22,8 @@ #include <GLES2/gl2.h> +#include <cutils/compiler.h> + #include "Extensions.h" #include "ProgramCache.h" #include "TextureCache.h" @@ -52,8 +54,8 @@ struct SkiaShader { kCompose }; - SkiaShader(Type type, SkShader* key, SkShader::TileMode tileX, SkShader::TileMode tileY, - SkMatrix* matrix, bool blend); + ANDROID_API SkiaShader(Type type, SkShader* key, SkShader::TileMode tileX, + SkShader::TileMode tileY, SkMatrix* matrix, bool blend); virtual ~SkiaShader(); virtual SkiaShader* copy() = 0; @@ -139,7 +141,7 @@ private: * A shader that draws a bitmap. */ struct SkiaBitmapShader: public SkiaShader { - SkiaBitmapShader(SkBitmap* bitmap, SkShader* key, SkShader::TileMode tileX, + ANDROID_API SkiaBitmapShader(SkBitmap* bitmap, SkShader* key, SkShader::TileMode tileX, SkShader::TileMode tileY, SkMatrix* matrix, bool blend); SkiaShader* copy(); @@ -169,8 +171,8 @@ private: * A shader that draws a linear gradient. */ struct SkiaLinearGradientShader: public SkiaShader { - SkiaLinearGradientShader(float* bounds, uint32_t* colors, float* positions, int count, - SkShader* key, SkShader::TileMode tileMode, SkMatrix* matrix, bool blend); + ANDROID_API SkiaLinearGradientShader(float* bounds, uint32_t* colors, float* positions, + int count, SkShader* key, SkShader::TileMode tileMode, SkMatrix* matrix, bool blend); ~SkiaLinearGradientShader(); SkiaShader* copy(); @@ -193,8 +195,8 @@ private: * A shader that draws a sweep gradient. */ struct SkiaSweepGradientShader: public SkiaShader { - SkiaSweepGradientShader(float x, float y, uint32_t* colors, float* positions, int count, - SkShader* key, SkMatrix* matrix, bool blend); + ANDROID_API SkiaSweepGradientShader(float x, float y, uint32_t* colors, float* positions, + int count, SkShader* key, SkMatrix* matrix, bool blend); ~SkiaSweepGradientShader(); SkiaShader* copy(); @@ -218,8 +220,9 @@ protected: * A shader that draws a circular gradient. */ struct SkiaCircularGradientShader: public SkiaSweepGradientShader { - SkiaCircularGradientShader(float x, float y, float radius, uint32_t* colors, float* positions, - int count, SkShader* key,SkShader::TileMode tileMode, SkMatrix* matrix, bool blend); + ANDROID_API SkiaCircularGradientShader(float x, float y, float radius, uint32_t* colors, + float* positions, int count, SkShader* key,SkShader::TileMode tileMode, + SkMatrix* matrix, bool blend); SkiaShader* copy(); void describe(ProgramDescription& description, const Extensions& extensions); @@ -233,7 +236,8 @@ private: * A shader that draws two shaders, composited with an xfermode. */ struct SkiaComposeShader: public SkiaShader { - SkiaComposeShader(SkiaShader* first, SkiaShader* second, SkXfermode::Mode mode, SkShader* key); + ANDROID_API SkiaComposeShader(SkiaShader* first, SkiaShader* second, SkXfermode::Mode mode, + SkShader* key); ~SkiaComposeShader(); SkiaShader* copy(); diff --git a/libs/hwui/Snapshot.h b/libs/hwui/Snapshot.h index d51154d..aff7b93 100644 --- a/libs/hwui/Snapshot.h +++ b/libs/hwui/Snapshot.h @@ -213,7 +213,8 @@ public: Layer* layer; /** - * Only set when the flag kFlagIsFboLayer is set. + * Target FBO used for rendering. Set to 0 when rendering directly + * into the framebuffer. */ GLuint fbo; diff --git a/libs/hwui/TextureCache.cpp b/libs/hwui/TextureCache.cpp index fbdbf92..018ce3e 100644 --- a/libs/hwui/TextureCache.cpp +++ b/libs/hwui/TextureCache.cpp @@ -34,7 +34,8 @@ namespace uirenderer { TextureCache::TextureCache(): mCache(GenerationCache<SkBitmap*, Texture*>::kUnlimitedCapacity), - mSize(0), mMaxSize(MB(DEFAULT_TEXTURE_CACHE_SIZE)) { + mSize(0), mMaxSize(MB(DEFAULT_TEXTURE_CACHE_SIZE)), + mFlushRate(DEFAULT_TEXTURE_CACHE_FLUSH_RATE) { char property[PROPERTY_VALUE_MAX]; if (property_get(PROPERTY_TEXTURE_CACHE_SIZE, property, NULL) > 0) { INIT_LOGD(" Setting texture cache size to %sMB", property); @@ -43,6 +44,15 @@ TextureCache::TextureCache(): INIT_LOGD(" Using default texture cache size of %.2fMB", DEFAULT_TEXTURE_CACHE_SIZE); } + if (property_get(PROPERTY_TEXTURE_CACHE_FLUSH_RATE, property, NULL) > 0) { + float flushRate = atof(property); + INIT_LOGD(" Setting texture cache flush rate to %.2f%%", flushRate * 100.0f); + setFlushRate(flushRate); + } else { + INIT_LOGD(" Using default texture cache flush rate of %.2f%%", + DEFAULT_TEXTURE_CACHE_FLUSH_RATE * 100.0f); + } + init(); } @@ -84,6 +94,10 @@ void TextureCache::setMaxSize(uint32_t maxSize) { } } +void TextureCache::setFlushRate(float flushRate) { + mFlushRate = fmaxf(0.0f, fminf(1.0f, flushRate)); +} + /////////////////////////////////////////////////////////////////////////////// // Callbacks /////////////////////////////////////////////////////////////////////////////// @@ -168,6 +182,21 @@ void TextureCache::clear() { TEXTURE_LOGD("TextureCache:clear(), mSize = %d", mSize); } +void TextureCache::flush() { + if (mFlushRate >= 1.0f || mCache.size() == 0) return; + if (mFlushRate <= 0.0f) { + clear(); + return; + } + + uint32_t targetSize = uint32_t(mSize * mFlushRate); + TEXTURE_LOGD("TextureCache::flush: target size: %d", targetSize); + + while (mSize > targetSize) { + mCache.removeOldest(); + } +} + void TextureCache::generateTexture(SkBitmap* bitmap, Texture* texture, bool regenerate) { SkAutoLockPixels alp(*bitmap); diff --git a/libs/hwui/TextureCache.h b/libs/hwui/TextureCache.h index f7707f7..ce924b4 100644 --- a/libs/hwui/TextureCache.h +++ b/libs/hwui/TextureCache.h @@ -98,6 +98,17 @@ public: */ uint32_t getSize(); + /** + * Partially flushes the cache. The amount of memory freed by a flush + * is defined by the flush rate. + */ + void flush(); + /** + * Indicates the percentage of the cache to retain when a + * memory trim is requested (see Caches::flush). + */ + void setFlushRate(float flushRate); + private: /** * Generates the texture from a bitmap into the specified texture structure. @@ -119,6 +130,8 @@ private: uint32_t mMaxSize; GLint mMaxTextureSize; + float mFlushRate; + bool mDebugEnabled; Vector<SkBitmap*> mGarbage; |