diff options
-rw-r--r-- | core/java/android/view/ViewRoot.java | 14 | ||||
-rw-r--r-- | libs/hwui/Caches.h | 2 | ||||
-rw-r--r-- | libs/hwui/Debug.h | 3 | ||||
-rw-r--r-- | libs/hwui/PathCache.cpp | 185 | ||||
-rw-r--r-- | libs/hwui/PathCache.h | 139 | ||||
-rw-r--r-- | libs/hwui/ShapeCache.cpp | 14 | ||||
-rw-r--r-- | libs/hwui/ShapeCache.h | 88 |
7 files changed, 98 insertions, 347 deletions
diff --git a/core/java/android/view/ViewRoot.java b/core/java/android/view/ViewRoot.java index 1f15628..97983ba 100644 --- a/core/java/android/view/ViewRoot.java +++ b/core/java/android/view/ViewRoot.java @@ -489,17 +489,17 @@ public final class ViewRoot extends Handler implements ViewParent, // Try to enable hardware acceleration if requested if (attrs != null && (attrs.flags & WindowManager.LayoutParams.FLAG_HARDWARE_ACCELERATED) != 0) { - // Don't enable hardware acceleration when we're not on the main thread - if (Looper.getMainLooper() != Looper.myLooper()) { - Log.w(HardwareRenderer.LOG_TAG, "Attempting to initialize hardware acceleration " - + "outside of the main thread, aborting"); - return; - } - // Only enable hardware acceleration if we are not in the system process // The window manager creates ViewRoots to display animated preview windows // of launching apps and we don't want those to be hardware accelerated if (!HardwareRenderer.sRendererDisabled) { + // Don't enable hardware acceleration when we're not on the main thread + if (Looper.getMainLooper() != Looper.myLooper()) { + Log.w(HardwareRenderer.LOG_TAG, "Attempting to initialize hardware " + + "acceleration outside of the main thread, aborting"); + return; + } + final boolean translucent = attrs.format != PixelFormat.OPAQUE; if (mAttachInfo.mHardwareRenderer != null) { mAttachInfo.mHardwareRenderer.destroy(true); diff --git a/libs/hwui/Caches.h b/libs/hwui/Caches.h index c03c347..aa0ceb7 100644 --- a/libs/hwui/Caches.h +++ b/libs/hwui/Caches.h @@ -31,8 +31,8 @@ #include "GradientCache.h" #include "PatchCache.h" #include "ProgramCache.h" -#include "PathCache.h" #include "ShapeCache.h" +#include "PathCache.h" #include "TextDropShadowCache.h" #include "FboCache.h" #include "ResourceCache.h" diff --git a/libs/hwui/Debug.h b/libs/hwui/Debug.h index 014519e..6236684 100644 --- a/libs/hwui/Debug.h +++ b/libs/hwui/Debug.h @@ -42,9 +42,6 @@ // This flag requires DEBUG_PATCHES to be turned on #define DEBUG_PATCHES_EMPTY_VERTICES 0 -// Turn on to display debug info about paths -#define DEBUG_PATHS 0 - // Turn on to display debug info about shapes #define DEBUG_SHAPES 0 diff --git a/libs/hwui/PathCache.cpp b/libs/hwui/PathCache.cpp index 3184598..28c302e 100644 --- a/libs/hwui/PathCache.cpp +++ b/libs/hwui/PathCache.cpp @@ -16,11 +16,6 @@ #define LOG_TAG "OpenGLRenderer" -#include <GLES2/gl2.h> - -#include <SkCanvas.h> -#include <SkRect.h> - #include <utils/threads.h> #include "PathCache.h" @@ -30,87 +25,11 @@ namespace android { namespace uirenderer { /////////////////////////////////////////////////////////////////////////////// -// Constructors/destructor -/////////////////////////////////////////////////////////////////////////////// - -PathCache::PathCache(): - mCache(GenerationCache<PathCacheEntry, PathTexture*>::kUnlimitedCapacity), - mSize(0), mMaxSize(MB(DEFAULT_PATH_CACHE_SIZE)) { - char property[PROPERTY_VALUE_MAX]; - if (property_get(PROPERTY_PATH_CACHE_SIZE, property, NULL) > 0) { - LOGD(" Setting path cache size to %sMB", property); - setMaxSize(MB(atof(property))); - } else { - LOGD(" Using default path cache size of %.2fMB", DEFAULT_PATH_CACHE_SIZE); - } - init(); -} - -PathCache::PathCache(uint32_t maxByteSize): - mCache(GenerationCache<PathCacheEntry, PathTexture*>::kUnlimitedCapacity), - mSize(0), mMaxSize(maxByteSize) { - init(); -} - -PathCache::~PathCache() { - mCache.clear(); -} - -void PathCache::init() { - mCache.setOnEntryRemovedListener(this); - - GLint maxTextureSize; - glGetIntegerv(GL_MAX_TEXTURE_SIZE, &maxTextureSize); - mMaxTextureSize = maxTextureSize; - - mDebugEnabled = readDebugLevel() & kDebugCaches; -} - -/////////////////////////////////////////////////////////////////////////////// -// Size management +// Path cache /////////////////////////////////////////////////////////////////////////////// -uint32_t PathCache::getSize() { - return mSize; -} - -uint32_t PathCache::getMaxSize() { - return mMaxSize; -} - -void PathCache::setMaxSize(uint32_t maxSize) { - mMaxSize = maxSize; - while (mSize > mMaxSize) { - mCache.removeOldest(); - } -} - -/////////////////////////////////////////////////////////////////////////////// -// Callbacks -/////////////////////////////////////////////////////////////////////////////// - -void PathCache::operator()(PathCacheEntry& path, PathTexture*& texture) { - removeTexture(texture); -} - -/////////////////////////////////////////////////////////////////////////////// -// Caching -/////////////////////////////////////////////////////////////////////////////// - -void PathCache::removeTexture(PathTexture* texture) { - if (texture) { - const uint32_t size = texture->width * texture->height; - mSize -= size; - - PATH_LOGD("PathCache::callback: delete path: name, size, mSize = %d, %d, %d", - texture->id, size, mSize); - if (mDebugEnabled) { - LOGD("Path deleted, size = %d", size); - } - - glDeleteTextures(1, &texture->id); - delete texture; - } +PathCache::PathCache(): ShapeCache<PathCacheEntry>("path", + PROPERTY_PATH_CACHE_SIZE, DEFAULT_PATH_CACHE_SIZE) { } void PathCache::remove(SkPath* path) { @@ -159,103 +78,5 @@ PathTexture* PathCache::get(SkPath* path, SkPaint* paint) { return texture; } -PathTexture* PathCache::addTexture(const PathCacheEntry& entry, - const SkPath *path, const SkPaint* paint) { - const SkRect& bounds = path->getBounds(); - - const float pathWidth = fmax(bounds.width(), 1.0f); - const float pathHeight = fmax(bounds.height(), 1.0f); - - if (pathWidth > mMaxTextureSize || pathHeight > mMaxTextureSize) { - LOGW("Path too large to be rendered into a texture"); - return NULL; - } - - const float offset = entry.strokeWidth * 1.5f; - const uint32_t width = uint32_t(pathWidth + offset * 2.0 + 0.5); - const uint32_t height = uint32_t(pathHeight + offset * 2.0 + 0.5); - - const uint32_t size = width * height; - // Don't even try to cache a bitmap that's bigger than the cache - if (size < mMaxSize) { - while (mSize + size > mMaxSize) { - mCache.removeOldest(); - } - } - - PathTexture* texture = new PathTexture; - texture->left = bounds.fLeft; - texture->top = bounds.fTop; - texture->offset = offset; - texture->width = width; - texture->height = height; - texture->generation = path->getGenerationID(); - - SkBitmap bitmap; - bitmap.setConfig(SkBitmap::kA8_Config, width, height); - bitmap.allocPixels(); - bitmap.eraseColor(0); - - SkPaint pathPaint(*paint); - - // Make sure the paint is opaque, color, alpha, filter, etc. - // will be applied later when compositing the alpha8 texture - pathPaint.setColor(0xff000000); - pathPaint.setAlpha(255); - pathPaint.setColorFilter(NULL); - pathPaint.setMaskFilter(NULL); - pathPaint.setShader(NULL); - SkXfermode* mode = SkXfermode::Create(SkXfermode::kSrc_Mode); - pathPaint.setXfermode(mode)->safeUnref(); - - SkCanvas canvas(bitmap); - canvas.translate(-bounds.fLeft + offset, -bounds.fTop + offset); - canvas.drawPath(*path, pathPaint); - - generateTexture(bitmap, texture); - - if (size < mMaxSize) { - mSize += size; - PATH_LOGD("PathCache::get: create path: name, size, mSize = %d, %d, %d", - texture->id, size, mSize); - if (mDebugEnabled) { - LOGD("Path created, size = %d", size); - } - mCache.put(entry, texture); - } else { - texture->cleanup = true; - } - - return texture; -} - -void PathCache::clear() { - mCache.clear(); -} - -void PathCache::generateTexture(SkBitmap& bitmap, Texture* texture) { - SkAutoLockPixels alp(bitmap); - if (!bitmap.readyToDraw()) { - LOGE("Cannot generate texture from bitmap"); - return; - } - - glGenTextures(1, &texture->id); - - glBindTexture(GL_TEXTURE_2D, texture->id); - // Textures are Alpha8 - glPixelStorei(GL_UNPACK_ALIGNMENT, 1); - - texture->blend = true; - 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); -} - }; // namespace uirenderer }; // namespace android diff --git a/libs/hwui/PathCache.h b/libs/hwui/PathCache.h index ae2e55d..dc67e16 100644 --- a/libs/hwui/PathCache.h +++ b/libs/hwui/PathCache.h @@ -17,123 +17,54 @@ #ifndef ANDROID_HWUI_PATH_CACHE_H #define ANDROID_HWUI_PATH_CACHE_H -#include <SkBitmap.h> -#include <SkPaint.h> -#include <SkPath.h> - #include <utils/Vector.h> #include "Debug.h" -#include "Texture.h" +#include "ShapeCache.h" + #include "utils/Compare.h" -#include "utils/GenerationCache.h" namespace android { namespace uirenderer { /////////////////////////////////////////////////////////////////////////////// -// Defines -/////////////////////////////////////////////////////////////////////////////// - -// Debug -#if DEBUG_PATHS - #define PATH_LOGD(...) LOGD(__VA_ARGS__) -#else - #define PATH_LOGD(...) -#endif - -/////////////////////////////////////////////////////////////////////////////// // Classes /////////////////////////////////////////////////////////////////////////////// -/** - * Describe a path in the path cache. - */ -struct PathCacheEntry { - PathCacheEntry() { - path = NULL; - join = SkPaint::kDefault_Join; - cap = SkPaint::kDefault_Cap; - style = SkPaint::kFill_Style; - miter = 4.0f; - strokeWidth = 1.0f; +struct PathCacheEntry: public ShapeCacheEntry { + PathCacheEntry(SkPath* path, SkPaint* paint): + ShapeCacheEntry(ShapeCacheEntry::kShapePath, paint) { + this->path = path; } - PathCacheEntry(const PathCacheEntry& entry): - path(entry.path), join(entry.join), cap(entry.cap), - style(entry.style), miter(entry.miter), - strokeWidth(entry.strokeWidth) { + PathCacheEntry(): ShapeCacheEntry() { + path = NULL; } - PathCacheEntry(SkPath* path, SkPaint* paint) { - this->path = path; - join = paint->getStrokeJoin(); - cap = paint->getStrokeCap(); - miter = paint->getStrokeMiter(); - strokeWidth = paint->getStrokeWidth(); - style = paint->getStyle(); + PathCacheEntry(const PathCacheEntry& entry): + ShapeCacheEntry(entry) { + path = entry.path; } - SkPath* path; - SkPaint::Join join; - SkPaint::Cap cap; - SkPaint::Style style; - float miter; - float strokeWidth; - - bool operator<(const PathCacheEntry& rhs) const { + bool lessThan(const ShapeCacheEntry& r) const { + const PathCacheEntry& rhs = (const PathCacheEntry&) r; LTE_INT(path) { - LTE_INT(join) { - LTE_INT(cap) { - LTE_INT(style) { - LTE_FLOAT(miter) { - LTE_FLOAT(strokeWidth) return false; - } - } - } - } + return false; } return false; } -}; // struct PathCacheEntry - -/** - * Alpha texture used to represent a path. - */ -struct PathTexture: public Texture { - PathTexture(): Texture() { - } - /** - * Left coordinate of the path bounds. - */ - float left; - /** - * Top coordinate of the path bounds. - */ - float top; - /** - * Offset to draw the path at the correct origin. - */ - float offset; -}; // struct PathTexture + SkPath* path; +}; // PathCacheEntry /** * A simple LRU path cache. The cache has a maximum size expressed in bytes. * Any texture added to the cache causing the cache to grow beyond the maximum * allowed size will also cause the oldest texture to be kicked out. */ -class PathCache: public OnEntryRemoved<PathCacheEntry, PathTexture*> { +class PathCache: public ShapeCache<PathCacheEntry> { public: PathCache(); - PathCache(uint32_t maxByteSize); - ~PathCache(); - - /** - * Used as a callback when an entry is removed from the cache. - * Do not invoke directly. - */ - void operator()(PathCacheEntry& path, PathTexture*& texture); /** * Returns the texture associated with the specified path. If the texture @@ -141,10 +72,6 @@ public: */ PathTexture* get(SkPath* path, SkPaint* paint); /** - * Clears the cache. This causes all textures to be deleted. - */ - void clear(); - /** * Removes an entry. */ void remove(SkPath* path); @@ -158,39 +85,7 @@ public: */ void clearGarbage(); - /** - * Sets the maximum size of the cache in bytes. - */ - void setMaxSize(uint32_t maxSize); - /** - * Returns the maximum size of the cache in bytes. - */ - uint32_t getMaxSize(); - /** - * Returns the current size of the cache in bytes. - */ - uint32_t getSize(); - private: - /** - * Generates the texture from a bitmap into the specified texture structure. - */ - void generateTexture(SkBitmap& bitmap, Texture* texture); - - void removeTexture(PathTexture* texture); - - PathTexture* addTexture(const PathCacheEntry& entry, const SkPath *path, const SkPaint* paint); - - void init(); - - GenerationCache<PathCacheEntry, PathTexture*> mCache; - - uint32_t mSize; - uint32_t mMaxSize; - GLuint mMaxTextureSize; - - bool mDebugEnabled; - Vector<SkPath*> mGarbage; mutable Mutex mLock; }; // class PathCache diff --git a/libs/hwui/ShapeCache.cpp b/libs/hwui/ShapeCache.cpp index ffa18e3..b78eecb 100644 --- a/libs/hwui/ShapeCache.cpp +++ b/libs/hwui/ShapeCache.cpp @@ -21,7 +21,12 @@ namespace android { namespace uirenderer { -RoundRectShapeCache::RoundRectShapeCache(): ShapeCache<RoundRectShapeCacheEntry>() { +/////////////////////////////////////////////////////////////////////////////// +// Rounded rects +/////////////////////////////////////////////////////////////////////////////// + +RoundRectShapeCache::RoundRectShapeCache(): ShapeCache<RoundRectShapeCacheEntry>( + "round rect", PROPERTY_SHAPE_CACHE_SIZE, DEFAULT_SHAPE_CACHE_SIZE) { } PathTexture* RoundRectShapeCache::getRoundRect(float width, float height, @@ -41,7 +46,12 @@ PathTexture* RoundRectShapeCache::getRoundRect(float width, float height, return texture; } -CircleShapeCache::CircleShapeCache(): ShapeCache<CircleShapeCacheEntry>() { +/////////////////////////////////////////////////////////////////////////////// +// Circles +/////////////////////////////////////////////////////////////////////////////// + +CircleShapeCache::CircleShapeCache(): ShapeCache<CircleShapeCacheEntry>( + "circle", PROPERTY_SHAPE_CACHE_SIZE, DEFAULT_SHAPE_CACHE_SIZE) { } PathTexture* CircleShapeCache::getCircle(float radius, SkPaint* paint) { diff --git a/libs/hwui/ShapeCache.h b/libs/hwui/ShapeCache.h index 910d01d..c8bcfc2 100644 --- a/libs/hwui/ShapeCache.h +++ b/libs/hwui/ShapeCache.h @@ -19,11 +19,17 @@ #include <GLES2/gl2.h> +#include <SkBitmap.h> #include <SkCanvas.h> +#include <SkPaint.h> +#include <SkPath.h> #include <SkRect.h> -#include "PathCache.h" +#include "Debug.h" #include "Properties.h" +#include "Texture.h" +#include "utils/Compare.h" +#include "utils/GenerationCache.h" namespace android { namespace uirenderer { @@ -44,6 +50,27 @@ namespace uirenderer { /////////////////////////////////////////////////////////////////////////////// /** + * Alpha texture used to represent a path. + */ +struct PathTexture: public Texture { + PathTexture(): Texture() { + } + + /** + * Left coordinate of the path bounds. + */ + float left; + /** + * Top coordinate of the path bounds. + */ + float top; + /** + * Offset to draw the path at the correct origin. + */ + float offset; +}; // struct PathTexture + +/** * Describe a shape in the shape cache. */ struct ShapeCacheEntry { @@ -52,7 +79,8 @@ struct ShapeCacheEntry { kShapeRoundRect, kShapeCircle, kShapeOval, - kShapeArc + kShapeArc, + kShapePath }; ShapeCacheEntry() { @@ -196,8 +224,7 @@ private: template<typename Entry> class ShapeCache: public OnEntryRemoved<Entry, PathTexture*> { public: - ShapeCache(); - ShapeCache(uint32_t maxByteSize); + ShapeCache(const char* name, const char* propertyName, float defaultSize); ~ShapeCache(); /** @@ -231,22 +258,23 @@ protected: return mCache.get(entry); } -private: - /** - * Generates the texture from a bitmap into the specified texture structure. - */ - void generateTexture(SkBitmap& bitmap, Texture* texture); - void removeTexture(PathTexture* texture); - void init(); - GenerationCache<Entry, PathTexture*> mCache; uint32_t mSize; uint32_t mMaxSize; GLuint mMaxTextureSize; + char* mName; bool mDebugEnabled; + +private: + /** + * Generates the texture from a bitmap into the specified texture structure. + */ + void generateTexture(SkBitmap& bitmap, Texture* texture); + + void init(); }; // class ShapeCache class RoundRectShapeCache: public ShapeCache<RoundRectShapeCacheEntry> { @@ -269,29 +297,29 @@ public: /////////////////////////////////////////////////////////////////////////////// template<class Entry> -ShapeCache<Entry>::ShapeCache(): +ShapeCache<Entry>::ShapeCache(const char* name, const char* propertyName, float defaultSize): mCache(GenerationCache<ShapeCacheEntry, PathTexture*>::kUnlimitedCapacity), - mSize(0), mMaxSize(MB(DEFAULT_SHAPE_CACHE_SIZE)) { + mSize(0), mMaxSize(MB(defaultSize)) { char property[PROPERTY_VALUE_MAX]; - if (property_get(PROPERTY_SHAPE_CACHE_SIZE, property, NULL) > 0) { - LOGD(" Setting shape cache size to %sMB", property); + if (property_get(propertyName, property, NULL) > 0) { + LOGD(" Setting %s cache size to %sMB", name, property); setMaxSize(MB(atof(property))); } else { - LOGD(" Using default shape cache size of %.2fMB", DEFAULT_SHAPE_CACHE_SIZE); + LOGD(" Using default %s cache size of %.2fMB", name, defaultSize); } - init(); -} -template<class Entry> -ShapeCache<Entry>::ShapeCache(uint32_t maxByteSize): - mCache(GenerationCache<ShapeCacheEntry, PathTexture*>::kUnlimitedCapacity), - mSize(0), mMaxSize(maxByteSize) { + size_t len = strlen(name); + mName = new char[len + 1]; + strcpy(mName, name); + mName[len] = '\0'; + init(); } template<class Entry> ShapeCache<Entry>::~ShapeCache() { mCache.clear(); + delete[] mName; } template<class Entry> @@ -346,10 +374,10 @@ void ShapeCache<Entry>::removeTexture(PathTexture* texture) { const uint32_t size = texture->width * texture->height; mSize -= size; - SHAPE_LOGD("ShapeCache::callback: delete path: name, size, mSize = %d, %d, %d", - texture->id, size, mSize); + SHAPE_LOGD("ShapeCache::callback: delete %s: name, size, mSize = %d, %d, %d", + mName, texture->id, size, mSize); if (mDebugEnabled) { - LOGD("Path deleted, size = %d", size); + LOGD("Shape %s deleted, size = %d", mName, size); } glDeleteTextures(1, &texture->id); @@ -366,7 +394,7 @@ PathTexture* ShapeCache<Entry>::addTexture(const Entry& entry, const SkPath *pat const float pathHeight = fmax(bounds.height(), 1.0f); if (pathWidth > mMaxTextureSize || pathHeight > mMaxTextureSize) { - LOGW("Shape too large to be rendered into a texture"); + LOGW("Shape %s too large to be rendered into a texture", mName); return NULL; } @@ -415,10 +443,10 @@ PathTexture* ShapeCache<Entry>::addTexture(const Entry& entry, const SkPath *pat if (size < mMaxSize) { mSize += size; - SHAPE_LOGD("ShapeCache::get: create path: name, size, mSize = %d, %d, %d", - texture->id, size, mSize); + SHAPE_LOGD("ShapeCache::get: create %s: name, size, mSize = %d, %d, %d", + mName, texture->id, size, mSize); if (mDebugEnabled) { - LOGD("Shape created, size = %d", size); + LOGD("Shape %s created, size = %d", mName, size); } mCache.put(entry, texture); } else { |