Loading libs/hwui/Android.mk +1 −0 Original line number Diff line number Diff line Loading @@ -5,6 +5,7 @@ include $(CLEAR_VARS) # defined in the current device/board configuration ifeq ($(USE_OPENGL_RENDERER),true) LOCAL_SRC_FILES:= \ utils/SortedListImpl.cpp \ DisplayListRenderer.cpp \ FboCache.cpp \ FontRenderer.cpp \ Loading libs/hwui/GenerationCache.h +5 −2 Original line number Diff line number Diff line Loading @@ -62,7 +62,7 @@ public: bool contains(K key) const; V get(K key); K getKeyAt(uint32_t index) const; void put(K key, V value); bool put(K key, V value); V remove(K key); V removeOldest(); V getValueAt(uint32_t index) const; Loading Loading @@ -149,7 +149,7 @@ V GenerationCache<K, V>::get(K key) { } template<typename K, typename V> void GenerationCache<K, V>::put(K key, V value) { bool GenerationCache<K, V>::put(K key, V value) { if (mMaxCapacity != kUnlimitedCapacity && mCache.size() >= mMaxCapacity) { removeOldest(); } Loading @@ -158,7 +158,10 @@ void GenerationCache<K, V>::put(K key, V value) { if (index < 0) { sp<Entry<K, V> > entry = new Entry<K, V>; addToCache(entry, key, value); return true; } return false; } template<typename K, typename V> Loading libs/hwui/Layer.h +26 −25 Original line number Diff line number Diff line Loading @@ -28,46 +28,33 @@ namespace android { namespace uirenderer { /** * Dimensions of a layer. */ struct LayerSize { LayerSize(): width(0), height(0) { } LayerSize(const uint32_t width, const uint32_t height): width(width), height(height) { } LayerSize(const LayerSize& size): width(size.width), height(size.height) { } uint32_t width; uint32_t height; bool operator<(const LayerSize& rhs) const { if (width == rhs.width) { return height < rhs.height; } return width < rhs.width; } bool operator==(const LayerSize& rhs) const { return width == rhs.width && height == rhs.height; } }; // struct LayerSize /////////////////////////////////////////////////////////////////////////////// // Layers /////////////////////////////////////////////////////////////////////////////// /** * A layer has dimensions and is backed by an OpenGL texture or FBO. */ struct Layer { Layer(const uint32_t layerWidth, const uint32_t layerHeight): width(layerWidth), height(layerHeight) { } /** * Coordinates of the layer. * Bounds of the layer. */ Rect layer; /** * Name of the texture used to render the layer. * Texture coordinates of the layer. */ GLuint texture; Rect texCoords; /** * Name of the FBO used to render the layer. If the name is 0 * this layer is not backed by an FBO, but a simple texture. */ GLuint fbo; /** * Opacity of the layer. */ Loading @@ -80,10 +67,24 @@ struct Layer { * Indicates whether this layer should be blended. */ bool blend; /** * Indicates whether this layer has been used already. */ bool empty; /** * Name of the texture used to render the layer. */ GLuint texture; /** * Width of the layer texture. */ uint32_t width; /** * Height of the layer texture. */ uint32_t height; }; // struct Layer }; // namespace uirenderer Loading libs/hwui/LayerCache.cpp +38 −41 Original line number Diff line number Diff line Loading @@ -30,9 +30,7 @@ namespace uirenderer { // Constructors/destructor /////////////////////////////////////////////////////////////////////////////// LayerCache::LayerCache(): mCache(GenerationCache<LayerSize, Layer*>::kUnlimitedCapacity), mSize(0), mMaxSize(MB(DEFAULT_LAYER_CACHE_SIZE)) { LayerCache::LayerCache(): mSize(0), mMaxSize(MB(DEFAULT_LAYER_CACHE_SIZE)) { char property[PROPERTY_VALUE_MAX]; if (property_get(PROPERTY_LAYER_CACHE_SIZE, property, NULL) > 0) { LOGD(" Setting layer cache size to %sMB", property); Loading @@ -42,11 +40,6 @@ LayerCache::LayerCache(): } } LayerCache::LayerCache(uint32_t maxByteSize): mCache(GenerationCache<LayerSize, Layer*>::kUnlimitedCapacity), mSize(0), mMaxSize(maxByteSize) { } LayerCache::~LayerCache() { clear(); } Loading @@ -64,19 +57,8 @@ uint32_t LayerCache::getMaxSize() { } void LayerCache::setMaxSize(uint32_t maxSize) { clear(); mMaxSize = maxSize; while (mSize > mMaxSize) { Layer* oldest = mCache.removeOldest(); deleteLayer(oldest); } } /////////////////////////////////////////////////////////////////////////////// // Callbacks /////////////////////////////////////////////////////////////////////////////// void LayerCache::operator()(LayerSize& size, Layer*& layer) { deleteLayer(layer); } /////////////////////////////////////////////////////////////////////////////// Loading @@ -85,7 +67,7 @@ void LayerCache::operator()(LayerSize& size, Layer*& layer) { void LayerCache::deleteLayer(Layer* layer) { if (layer) { mSize -= layer->layer.getWidth() * layer->layer.getHeight() * 4; mSize -= layer->width * layer->height * 4; glDeleteTextures(1, &layer->texture); delete layer; Loading @@ -93,21 +75,31 @@ void LayerCache::deleteLayer(Layer* layer) { } void LayerCache::clear() { mCache.setOnEntryRemovedListener(this); size_t count = mCache.size(); for (size_t i = 0; i < count; i++) { deleteLayer(mCache.itemAt(i).mLayer); } mCache.clear(); mCache.setOnEntryRemovedListener(NULL); } Layer* LayerCache::get(LayerSize& size) { Layer* layer = mCache.remove(size); if (layer) { LAYER_LOGD("Reusing layer"); Layer* LayerCache::get(const uint32_t width, const uint32_t height) { Layer* layer = NULL; LayerEntry entry(width, height); ssize_t index = mCache.indexOf(entry); mSize -= layer->layer.getWidth() * layer->layer.getHeight() * 4; if (index >= 0) { entry = mCache.itemAt(index); mCache.removeAt(index); layer = entry.mLayer; mSize -= layer->width * layer->height * 4; LAYER_LOGD("Reusing layer %dx%d", layer->width, layer->height); } else { LAYER_LOGD("Creating new layer"); LAYER_LOGD("Creating new layer %dx%d", entry.mWidth, entry.mHeight); layer = new Layer; layer = new Layer(entry.mWidth, entry.mHeight); layer->blend = true; layer->empty = true; layer->fbo = 0; Loading @@ -124,10 +116,10 @@ Layer* LayerCache::get(LayerSize& size) { glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); #if DEBUG_LAYERS uint32_t size = mCache.size(); for (uint32_t i = 0; i < size; i++) { LayerSize ls = mCache.getKeyAt(i); LAYER_LOGD(" Layer size %dx%d", ls.width, ls.height); size_t size = mCache.size(); for (size_t i = 0; i < size; i++) { const LayerEntry& entry = mCache.itemAt(i); LAYER_LOGD(" Layer size %dx%d", entry.mWidth, entry.mHeight); } #endif } Loading @@ -135,18 +127,23 @@ Layer* LayerCache::get(LayerSize& size) { return layer; } bool LayerCache::put(LayerSize& layerSize, Layer* layer) { const uint32_t size = layerSize.width * layerSize.height * 4; bool LayerCache::put(Layer* layer) { const uint32_t size = layer->width * layer->height * 4; // Don't even try to cache a layer that's bigger than the cache if (size < mMaxSize) { // TODO: Use an LRU while (mSize + size > mMaxSize) { Layer* oldest = mCache.removeOldest(); deleteLayer(oldest); LAYER_LOGD(" Deleting layer %.2fx%.2f", oldest->layer.getWidth(), oldest->layer.getHeight()); Layer* biggest = mCache.top().mLayer; deleteLayer(biggest); mCache.removeAt(mCache.size() - 1); LAYER_LOGD(" Deleting layer %.2fx%.2f", biggest->layer.getWidth(), biggest->layer.getHeight()); } mCache.put(layerSize, layer); LayerEntry entry(layer); mCache.add(entry); mSize += size; return true; Loading libs/hwui/LayerCache.h +48 −17 Original line number Diff line number Diff line Loading @@ -18,7 +18,7 @@ #define ANDROID_UI_LAYER_CACHE_H #include "Layer.h" #include "GenerationCache.h" #include "utils/SortedList.h" namespace android { namespace uirenderer { Loading @@ -30,6 +30,9 @@ namespace uirenderer { // Debug #define DEBUG_LAYERS 0 // Textures used by layers must have dimensions multiples of this number #define LAYER_SIZE 64 // Debug #if DEBUG_LAYERS #define LAYER_LOGD(...) LOGD(__VA_ARGS__) Loading @@ -41,40 +44,34 @@ namespace uirenderer { // Cache /////////////////////////////////////////////////////////////////////////////// class LayerCache: public OnEntryRemoved<LayerSize, Layer*> { class LayerCache { public: LayerCache(); LayerCache(uint32_t maxByteSize); ~LayerCache(); /** * Used as a callback when an entry is removed from the cache. * Do not invoke directly. */ void operator()(LayerSize& size, Layer*& layer); /** * Returns the layer of specified dimensions. If not suitable layer * can be found, a new one is created and returned. If creating a new * Returns a layer large enough for the specified dimensions. If no suitable * layer can be found, a new one is created and returned. If creating a new * layer fails, NULL is returned. * * When a layer is obtained from the cache, it is removed and the total * size of the cache goes down. * * @param size The dimensions of the desired layer * @param width The desired width of the layer * @param width The desired height of the layer */ Layer* get(LayerSize& size); Layer* get(const uint32_t width, const uint32_t height); /** * Adds the layer to the cache. The layer will not be added if there is * not enough space available. * not enough space available. Adding a layer can cause other layers to * be removed from the cache. * * @param size The dimensions of the layer * @param layer The layer to add to the cache * * @return True if the layer was added, false otherwise. */ bool put(LayerSize& size, Layer* layer); bool put(Layer* layer); /** * Clears the cache. This causes all layers to be deleted. */ Loading @@ -96,7 +93,41 @@ public: private: void deleteLayer(Layer* layer); GenerationCache<LayerSize, Layer*> mCache; struct LayerEntry { LayerEntry(): mLayer(NULL), mWidth(0), mHeight(0) { } LayerEntry(const uint32_t layerWidth, const uint32_t layerHeight): mLayer(NULL) { mWidth = uint32_t(ceilf(layerWidth / float(LAYER_SIZE)) * LAYER_SIZE); mHeight = uint32_t(ceilf(layerHeight / float(LAYER_SIZE)) * LAYER_SIZE); } LayerEntry(const LayerEntry& entry): mLayer(entry.mLayer), mWidth(entry.mWidth), mHeight(entry.mHeight) { } LayerEntry(Layer* layer): mLayer(layer), mWidth(layer->width), mHeight(layer->height) { } bool operator<(const LayerEntry& rhs) const { if (mWidth == rhs.mWidth) { return mHeight < rhs.mHeight; } return mWidth < rhs.mWidth; } bool operator==(const LayerEntry& rhs) const { return mWidth == rhs.mWidth && mHeight == rhs.mHeight; } Layer* mLayer; uint32_t mWidth; uint32_t mHeight; }; // struct LayerEntry SortedList<LayerEntry> mCache; uint32_t mSize; uint32_t mMaxSize; Loading Loading
libs/hwui/Android.mk +1 −0 Original line number Diff line number Diff line Loading @@ -5,6 +5,7 @@ include $(CLEAR_VARS) # defined in the current device/board configuration ifeq ($(USE_OPENGL_RENDERER),true) LOCAL_SRC_FILES:= \ utils/SortedListImpl.cpp \ DisplayListRenderer.cpp \ FboCache.cpp \ FontRenderer.cpp \ Loading
libs/hwui/GenerationCache.h +5 −2 Original line number Diff line number Diff line Loading @@ -62,7 +62,7 @@ public: bool contains(K key) const; V get(K key); K getKeyAt(uint32_t index) const; void put(K key, V value); bool put(K key, V value); V remove(K key); V removeOldest(); V getValueAt(uint32_t index) const; Loading Loading @@ -149,7 +149,7 @@ V GenerationCache<K, V>::get(K key) { } template<typename K, typename V> void GenerationCache<K, V>::put(K key, V value) { bool GenerationCache<K, V>::put(K key, V value) { if (mMaxCapacity != kUnlimitedCapacity && mCache.size() >= mMaxCapacity) { removeOldest(); } Loading @@ -158,7 +158,10 @@ void GenerationCache<K, V>::put(K key, V value) { if (index < 0) { sp<Entry<K, V> > entry = new Entry<K, V>; addToCache(entry, key, value); return true; } return false; } template<typename K, typename V> Loading
libs/hwui/Layer.h +26 −25 Original line number Diff line number Diff line Loading @@ -28,46 +28,33 @@ namespace android { namespace uirenderer { /** * Dimensions of a layer. */ struct LayerSize { LayerSize(): width(0), height(0) { } LayerSize(const uint32_t width, const uint32_t height): width(width), height(height) { } LayerSize(const LayerSize& size): width(size.width), height(size.height) { } uint32_t width; uint32_t height; bool operator<(const LayerSize& rhs) const { if (width == rhs.width) { return height < rhs.height; } return width < rhs.width; } bool operator==(const LayerSize& rhs) const { return width == rhs.width && height == rhs.height; } }; // struct LayerSize /////////////////////////////////////////////////////////////////////////////// // Layers /////////////////////////////////////////////////////////////////////////////// /** * A layer has dimensions and is backed by an OpenGL texture or FBO. */ struct Layer { Layer(const uint32_t layerWidth, const uint32_t layerHeight): width(layerWidth), height(layerHeight) { } /** * Coordinates of the layer. * Bounds of the layer. */ Rect layer; /** * Name of the texture used to render the layer. * Texture coordinates of the layer. */ GLuint texture; Rect texCoords; /** * Name of the FBO used to render the layer. If the name is 0 * this layer is not backed by an FBO, but a simple texture. */ GLuint fbo; /** * Opacity of the layer. */ Loading @@ -80,10 +67,24 @@ struct Layer { * Indicates whether this layer should be blended. */ bool blend; /** * Indicates whether this layer has been used already. */ bool empty; /** * Name of the texture used to render the layer. */ GLuint texture; /** * Width of the layer texture. */ uint32_t width; /** * Height of the layer texture. */ uint32_t height; }; // struct Layer }; // namespace uirenderer Loading
libs/hwui/LayerCache.cpp +38 −41 Original line number Diff line number Diff line Loading @@ -30,9 +30,7 @@ namespace uirenderer { // Constructors/destructor /////////////////////////////////////////////////////////////////////////////// LayerCache::LayerCache(): mCache(GenerationCache<LayerSize, Layer*>::kUnlimitedCapacity), mSize(0), mMaxSize(MB(DEFAULT_LAYER_CACHE_SIZE)) { LayerCache::LayerCache(): mSize(0), mMaxSize(MB(DEFAULT_LAYER_CACHE_SIZE)) { char property[PROPERTY_VALUE_MAX]; if (property_get(PROPERTY_LAYER_CACHE_SIZE, property, NULL) > 0) { LOGD(" Setting layer cache size to %sMB", property); Loading @@ -42,11 +40,6 @@ LayerCache::LayerCache(): } } LayerCache::LayerCache(uint32_t maxByteSize): mCache(GenerationCache<LayerSize, Layer*>::kUnlimitedCapacity), mSize(0), mMaxSize(maxByteSize) { } LayerCache::~LayerCache() { clear(); } Loading @@ -64,19 +57,8 @@ uint32_t LayerCache::getMaxSize() { } void LayerCache::setMaxSize(uint32_t maxSize) { clear(); mMaxSize = maxSize; while (mSize > mMaxSize) { Layer* oldest = mCache.removeOldest(); deleteLayer(oldest); } } /////////////////////////////////////////////////////////////////////////////// // Callbacks /////////////////////////////////////////////////////////////////////////////// void LayerCache::operator()(LayerSize& size, Layer*& layer) { deleteLayer(layer); } /////////////////////////////////////////////////////////////////////////////// Loading @@ -85,7 +67,7 @@ void LayerCache::operator()(LayerSize& size, Layer*& layer) { void LayerCache::deleteLayer(Layer* layer) { if (layer) { mSize -= layer->layer.getWidth() * layer->layer.getHeight() * 4; mSize -= layer->width * layer->height * 4; glDeleteTextures(1, &layer->texture); delete layer; Loading @@ -93,21 +75,31 @@ void LayerCache::deleteLayer(Layer* layer) { } void LayerCache::clear() { mCache.setOnEntryRemovedListener(this); size_t count = mCache.size(); for (size_t i = 0; i < count; i++) { deleteLayer(mCache.itemAt(i).mLayer); } mCache.clear(); mCache.setOnEntryRemovedListener(NULL); } Layer* LayerCache::get(LayerSize& size) { Layer* layer = mCache.remove(size); if (layer) { LAYER_LOGD("Reusing layer"); Layer* LayerCache::get(const uint32_t width, const uint32_t height) { Layer* layer = NULL; LayerEntry entry(width, height); ssize_t index = mCache.indexOf(entry); mSize -= layer->layer.getWidth() * layer->layer.getHeight() * 4; if (index >= 0) { entry = mCache.itemAt(index); mCache.removeAt(index); layer = entry.mLayer; mSize -= layer->width * layer->height * 4; LAYER_LOGD("Reusing layer %dx%d", layer->width, layer->height); } else { LAYER_LOGD("Creating new layer"); LAYER_LOGD("Creating new layer %dx%d", entry.mWidth, entry.mHeight); layer = new Layer; layer = new Layer(entry.mWidth, entry.mHeight); layer->blend = true; layer->empty = true; layer->fbo = 0; Loading @@ -124,10 +116,10 @@ Layer* LayerCache::get(LayerSize& size) { glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); #if DEBUG_LAYERS uint32_t size = mCache.size(); for (uint32_t i = 0; i < size; i++) { LayerSize ls = mCache.getKeyAt(i); LAYER_LOGD(" Layer size %dx%d", ls.width, ls.height); size_t size = mCache.size(); for (size_t i = 0; i < size; i++) { const LayerEntry& entry = mCache.itemAt(i); LAYER_LOGD(" Layer size %dx%d", entry.mWidth, entry.mHeight); } #endif } Loading @@ -135,18 +127,23 @@ Layer* LayerCache::get(LayerSize& size) { return layer; } bool LayerCache::put(LayerSize& layerSize, Layer* layer) { const uint32_t size = layerSize.width * layerSize.height * 4; bool LayerCache::put(Layer* layer) { const uint32_t size = layer->width * layer->height * 4; // Don't even try to cache a layer that's bigger than the cache if (size < mMaxSize) { // TODO: Use an LRU while (mSize + size > mMaxSize) { Layer* oldest = mCache.removeOldest(); deleteLayer(oldest); LAYER_LOGD(" Deleting layer %.2fx%.2f", oldest->layer.getWidth(), oldest->layer.getHeight()); Layer* biggest = mCache.top().mLayer; deleteLayer(biggest); mCache.removeAt(mCache.size() - 1); LAYER_LOGD(" Deleting layer %.2fx%.2f", biggest->layer.getWidth(), biggest->layer.getHeight()); } mCache.put(layerSize, layer); LayerEntry entry(layer); mCache.add(entry); mSize += size; return true; Loading
libs/hwui/LayerCache.h +48 −17 Original line number Diff line number Diff line Loading @@ -18,7 +18,7 @@ #define ANDROID_UI_LAYER_CACHE_H #include "Layer.h" #include "GenerationCache.h" #include "utils/SortedList.h" namespace android { namespace uirenderer { Loading @@ -30,6 +30,9 @@ namespace uirenderer { // Debug #define DEBUG_LAYERS 0 // Textures used by layers must have dimensions multiples of this number #define LAYER_SIZE 64 // Debug #if DEBUG_LAYERS #define LAYER_LOGD(...) LOGD(__VA_ARGS__) Loading @@ -41,40 +44,34 @@ namespace uirenderer { // Cache /////////////////////////////////////////////////////////////////////////////// class LayerCache: public OnEntryRemoved<LayerSize, Layer*> { class LayerCache { public: LayerCache(); LayerCache(uint32_t maxByteSize); ~LayerCache(); /** * Used as a callback when an entry is removed from the cache. * Do not invoke directly. */ void operator()(LayerSize& size, Layer*& layer); /** * Returns the layer of specified dimensions. If not suitable layer * can be found, a new one is created and returned. If creating a new * Returns a layer large enough for the specified dimensions. If no suitable * layer can be found, a new one is created and returned. If creating a new * layer fails, NULL is returned. * * When a layer is obtained from the cache, it is removed and the total * size of the cache goes down. * * @param size The dimensions of the desired layer * @param width The desired width of the layer * @param width The desired height of the layer */ Layer* get(LayerSize& size); Layer* get(const uint32_t width, const uint32_t height); /** * Adds the layer to the cache. The layer will not be added if there is * not enough space available. * not enough space available. Adding a layer can cause other layers to * be removed from the cache. * * @param size The dimensions of the layer * @param layer The layer to add to the cache * * @return True if the layer was added, false otherwise. */ bool put(LayerSize& size, Layer* layer); bool put(Layer* layer); /** * Clears the cache. This causes all layers to be deleted. */ Loading @@ -96,7 +93,41 @@ public: private: void deleteLayer(Layer* layer); GenerationCache<LayerSize, Layer*> mCache; struct LayerEntry { LayerEntry(): mLayer(NULL), mWidth(0), mHeight(0) { } LayerEntry(const uint32_t layerWidth, const uint32_t layerHeight): mLayer(NULL) { mWidth = uint32_t(ceilf(layerWidth / float(LAYER_SIZE)) * LAYER_SIZE); mHeight = uint32_t(ceilf(layerHeight / float(LAYER_SIZE)) * LAYER_SIZE); } LayerEntry(const LayerEntry& entry): mLayer(entry.mLayer), mWidth(entry.mWidth), mHeight(entry.mHeight) { } LayerEntry(Layer* layer): mLayer(layer), mWidth(layer->width), mHeight(layer->height) { } bool operator<(const LayerEntry& rhs) const { if (mWidth == rhs.mWidth) { return mHeight < rhs.mHeight; } return mWidth < rhs.mWidth; } bool operator==(const LayerEntry& rhs) const { return mWidth == rhs.mWidth && mHeight == rhs.mHeight; } Layer* mLayer; uint32_t mWidth; uint32_t mHeight; }; // struct LayerEntry SortedList<LayerEntry> mCache; uint32_t mSize; uint32_t mMaxSize; Loading