Add hooks for drawBitmap().
Change-Id: I58e962c3a8b2bc75c2605fe369ad3002579d86e0
Add texture cache.
Change-Id: I1c0e5581d228869e114438258a1014e33e024ad7
diff --git a/libs/hwui/Android.mk b/libs/hwui/Android.mk
index fd76811..95ebda1 100644
--- a/libs/hwui/Android.mk
+++ b/libs/hwui/Android.mk
@@ -4,7 +4,8 @@
LOCAL_SRC_FILES:= \
Matrix.cpp \
OpenGLRenderer.cpp \
- Program.cpp
+ Program.cpp \
+ TextureCache.cpp
LOCAL_C_INCLUDES += \
$(JNI_H_INCLUDE) \
diff --git a/libs/hwui/GenerationCache.h b/libs/hwui/GenerationCache.h
new file mode 100644
index 0000000..c4ff587
--- /dev/null
+++ b/libs/hwui/GenerationCache.h
@@ -0,0 +1,208 @@
+/*
+ * Copyright (C) 2010 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef ANDROID_UI_GENERATION_CACHE_H
+#define ANDROID_UI_GENERATION_CACHE_H
+
+#include <utils/KeyedVector.h>
+#include <utils/RefBase.h>
+
+namespace android {
+namespace uirenderer {
+
+template<typename EntryKey, typename EntryValue>
+class OnEntryRemoved {
+public:
+ virtual ~OnEntryRemoved() { };
+ virtual void operator()(EntryKey key, EntryValue value) = 0;
+}; // class OnEntryRemoved
+
+template<typename K, typename V>
+class GenerationCache {
+public:
+ GenerationCache(unsigned int maxCapacity): mMaxCapacity(maxCapacity), mListener(NULL) { };
+ ~GenerationCache() { clear(); };
+
+ void setOnEntryRemovedListener(OnEntryRemoved<K*, V*>* listener);
+
+ void clear();
+
+ bool contains(K* key) const;
+ const V* get(K* key);
+ void put(K* key, V* value);
+ const V* remove(K* key);
+
+ unsigned int size() const;
+
+private:
+ void removeOldest();
+
+ template<typename EntryKey, typename EntryValue>
+ struct Entry: public LightRefBase<Entry<EntryKey, EntryValue> > {
+ Entry() { }
+ Entry(const Entry<EntryKey, EntryValue>& e):
+ key(e.key), value(e.value), parent(e.parent), child(e.child) { }
+ Entry(sp<Entry<EntryKey, EntryValue> > e):
+ key(e->key), value(e->value), parent(e->parent), child(e->child) { }
+
+ EntryKey key;
+ EntryValue value;
+
+ sp<Entry<EntryKey, EntryValue> > parent;
+ sp<Entry<EntryKey, EntryValue> > child;
+ }; // struct Entry
+
+ void addToCache(sp<Entry<K*, V*> > entry, K* key, V* value);
+ void attachToCache(sp<Entry<K*, V*> > entry);
+ void detachFromCache(sp<Entry<K*, V*> > entry);
+
+ unsigned int mMaxCapacity;
+
+ OnEntryRemoved<K*, V*>* mListener;
+
+ KeyedVector<K*, sp<Entry<K*, V*> > > mCache;
+
+ sp<Entry<K*, V*> > mOldest;
+ sp<Entry<K*, V*> > mYougest;
+}; // class GenerationCache
+
+template<typename K, typename V>
+unsigned int GenerationCache<K, V>::size() const {
+ return mCache.size();
+}
+
+template<typename K, typename V>
+void GenerationCache<K, V>::setOnEntryRemovedListener(OnEntryRemoved<K*, V*>* listener) {
+ mListener = listener;
+}
+
+template<typename K, typename V>
+void GenerationCache<K, V>::clear() {
+ if (mListener) {
+ while (mCache.size() > 0) {
+ removeOldest();
+ }
+ } else {
+ mCache.clear();
+ }
+ mYougest.clear();
+ mOldest.clear();
+}
+
+template<typename K, typename V>
+bool GenerationCache<K, V>::contains(K* key) const {
+ return mCache.indexOfKey(key) >= 0;
+}
+
+template<typename K, typename V>
+const V* GenerationCache<K, V>::get(K* key) {
+ ssize_t index = mCache.indexOfKey(key);
+ if (index >= 0) {
+ sp<Entry<K*, V*> > entry = mCache.valueAt(index);
+ if (entry.get()) {
+ detachFromCache(entry);
+ attachToCache(entry);
+ return entry->value;
+ }
+ }
+
+ return NULL;
+}
+
+template<typename K, typename V>
+void GenerationCache<K, V>::put(K* key, V* value) {
+ if (mCache.size() >= mMaxCapacity) {
+ removeOldest();
+ }
+
+ ssize_t index = mCache.indexOfKey(key);
+ if (index >= 0) {
+ sp<Entry<K*, V*> > entry = mCache.valueAt(index);
+ detachFromCache(entry);
+ addToCache(entry, key, value);
+ } else {
+ sp<Entry<K*, V*> > entry = new Entry<K*, V*>;
+ addToCache(entry, key, value);
+ }
+}
+
+template<typename K, typename V>
+void GenerationCache<K, V>::addToCache(sp<Entry<K*, V*> > entry, K* key, V* value) {
+ entry->key = key;
+ entry->value = value;
+ mCache.add(key, entry);
+ attachToCache(entry);
+}
+
+template<typename K, typename V>
+const V* GenerationCache<K, V>::remove(K* key) {
+ ssize_t index = mCache.indexOfKey(key);
+ if (index >= 0) {
+ sp<Entry<K*, V*> > entry = mCache.valueAt(index);
+ if (mListener) {
+ (*mListener)(entry->key, entry->value);
+ }
+ mCache.removeItemsAt(index, 1);
+ detachFromCache(entry);
+ }
+
+ return NULL;
+}
+
+template<typename K, typename V>
+void GenerationCache<K, V>::removeOldest() {
+ if (mOldest.get()) {
+ remove(mOldest->key);
+ }
+}
+
+template<typename K, typename V>
+void GenerationCache<K, V>::attachToCache(sp<Entry<K*, V*> > entry) {
+ if (!mYougest.get()) {
+ mYougest = mOldest = entry;
+ } else {
+ entry->parent = mYougest;
+ mYougest->child = entry;
+ mYougest = entry;
+ }
+}
+
+template<typename K, typename V>
+void GenerationCache<K, V>::detachFromCache(sp<Entry<K*, V*> > entry) {
+ if (entry->parent.get()) {
+ entry->parent->child = entry->child;
+ }
+
+ if (entry->child.get()) {
+ entry->child->parent = entry->parent;
+ }
+
+ if (mOldest == entry) {
+ mOldest = entry->child;
+ }
+
+ if (mYougest == entry) {
+ mYougest = entry->parent;
+ }
+
+ entry->parent.clear();
+ entry->child.clear();
+}
+
+}; // namespace uirenderer
+}; // namespace android
+
+#endif // ANDROID_UI_GENERATION_CACHE_H
diff --git a/libs/hwui/OpenGLRenderer.cpp b/libs/hwui/OpenGLRenderer.cpp
index aa992c4..d8023859 100644
--- a/libs/hwui/OpenGLRenderer.cpp
+++ b/libs/hwui/OpenGLRenderer.cpp
@@ -33,6 +33,8 @@
// Defines
///////////////////////////////////////////////////////////////////////////////
+#define MAX_TEXTURE_COUNT 128
+
#define SV(x, y) { { x, y } }
#define FV(x, y, u, v) { { x, y }, { u, v } }
@@ -81,7 +83,7 @@
// Constructors/destructor
///////////////////////////////////////////////////////////////////////////////
-OpenGLRenderer::OpenGLRenderer() {
+OpenGLRenderer::OpenGLRenderer(): mTextureCache(MAX_TEXTURE_COUNT) {
LOGD("Create OpenGLRenderer");
mDrawColorShader = new DrawColorProgram;
@@ -92,6 +94,8 @@
OpenGLRenderer::~OpenGLRenderer() {
LOGD("Destroy OpenGLRenderer");
+
+ mTextureCache.clear();
}
///////////////////////////////////////////////////////////////////////////////
@@ -374,6 +378,10 @@
// Drawing
///////////////////////////////////////////////////////////////////////////////
+void OpenGLRenderer::drawBitmap(const SkBitmap* bitmap, float left, float top, const SkPaint* paint) {
+ LOGD("Drawing bitmap!");
+}
+
void OpenGLRenderer::drawColor(int color, SkXfermode::Mode mode) {
const Rect& clip = mSnapshot->clipRect;
drawColorRect(clip.left, clip.top, clip.right, clip.bottom, color, mode);
diff --git a/libs/hwui/OpenGLRenderer.h b/libs/hwui/OpenGLRenderer.h
index 1af73c1..e5cc98c 100644
--- a/libs/hwui/OpenGLRenderer.h
+++ b/libs/hwui/OpenGLRenderer.h
@@ -20,7 +20,9 @@
#include <GLES2/gl2.h>
#include <GLES2/gl2ext.h>
+#include <SkBitmap.h>
#include <SkMatrix.h>
+#include <SkPaint.h>
#include <SkXfermode.h>
#include <utils/RefBase.h>
@@ -29,6 +31,8 @@
#include "Program.h"
#include "Rect.h"
#include "Snapshot.h"
+#include "Texture.h"
+#include "TextureCache.h"
namespace android {
namespace uirenderer {
@@ -98,6 +102,7 @@
bool quickReject(float left, float top, float right, float bottom);
bool clipRect(float left, float top, float right, float bottom);
+ void drawBitmap(const SkBitmap* bitmap, float left, float top, const SkPaint* paint);
void drawColor(int color, SkXfermode::Mode mode);
void drawRect(float left, float top, float right, float bottom, const SkPaint* paint);
@@ -218,6 +223,9 @@
// Used to draw textured quads
TextureVertex mDrawTextureVertices[4];
+
+ // Used to cache all drawBitmap textures
+ TextureCache mTextureCache;
}; // class OpenGLRenderer
}; // namespace uirenderer
diff --git a/libs/hwui/Texture.h b/libs/hwui/Texture.h
new file mode 100644
index 0000000..b3b17ca
--- /dev/null
+++ b/libs/hwui/Texture.h
@@ -0,0 +1,50 @@
+/*
+ * Copyright (C) 2010 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef ANDROID_UI_TEXTURE_H
+#define ANDROID_UI_TEXTURE_H
+
+#include <GLES2/gl2.h>
+
+namespace android {
+namespace uirenderer {
+
+/**
+ * Represents an OpenGL texture.
+ */
+struct Texture {
+ /**
+ * Name of the texture.
+ */
+ GLuint id;
+ /**
+ * Indicates whether the texture requires blending.
+ */
+ bool blend;
+ /**
+ * Width of the backing bitmap.
+ */
+ unsigned int width;
+ /**
+ * Height of the backing bitmap.
+ */
+ unsigned int height;
+}; // struct Texture
+
+}; // namespace uirenderer
+}; // namespace android
+
+#endif // ANDROID_UI_TEXTURE_H
diff --git a/libs/hwui/TextureCache.cpp b/libs/hwui/TextureCache.cpp
new file mode 100644
index 0000000..b4a57ee
--- /dev/null
+++ b/libs/hwui/TextureCache.cpp
@@ -0,0 +1,86 @@
+/*
+ * Copyright (C) 2010 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <GLES2/gl2.h>
+
+#include "TextureCache.h"
+
+namespace android {
+namespace uirenderer {
+
+TextureCache::TextureCache(unsigned int maxEntries): mCache(maxEntries) {
+ mCache.setOnEntryRemovedListener(this);
+}
+
+TextureCache::~TextureCache() {
+ mCache.clear();
+}
+
+void TextureCache::operator()(SkBitmap* key, Texture* value) {
+ LOGD("Entry removed");
+ if (value) {
+ glDeleteTextures(1, &value->id);
+ delete value;
+ }
+}
+
+Texture* TextureCache::get(SkBitmap* bitmap) {
+ Texture* texture = mCache.get(bitmap);
+ if (!texture) {
+ texture = generateTexture(bitmap);
+ mCache.put(bitmap, texture);
+ }
+ return texture;
+}
+
+Texture* TextureCache::remove(SkBitmap* bitmap) {
+ return mCache.remove(bitmap);
+}
+
+void TextureCache::clear() {
+ mCache.clear();
+}
+
+Texture* TextureCache::generateTexture(SkBitmap* bitmap) {
+ Texture* texture = new Texture;
+
+ texture->width = bitmap->width();
+ texture->height = bitmap->height();
+
+ glGenTextures(1, &texture->id);
+ glBindTexture(GL_TEXTURE_2D, texture->id);
+
+ 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);
+
+ switch (bitmap->getConfig()) {
+ case SkBitmap::kRGB_565_Config:
+ glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB565, texture->width, texture->height,
+ 0, GL_RGB565, GL_UNSIGNED_SHORT_5_6_5, bitmap->getPixels());
+ break;
+ case SkBitmap::kARGB_8888_Config:
+ glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, texture->width, texture->height,
+ 0, GL_RGBA, GL_UNSIGNED_BYTE, bitmap->getPixels());
+ break;
+ }
+
+ return texture;
+}
+
+}; // namespace uirenderer
+}; // namespace android
diff --git a/libs/hwui/TextureCache.h b/libs/hwui/TextureCache.h
new file mode 100644
index 0000000..42328f4
--- /dev/null
+++ b/libs/hwui/TextureCache.h
@@ -0,0 +1,48 @@
+/*
+ * Copyright (C) 2010 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef ANDROID_UI_TEXTURE_CACHE_H
+#define ANDROID_UI_TEXTURE_CACHE_H
+
+#include <SkBitmap.h>
+
+#include "Texture.h"
+#include "GenerationCache.h"
+
+namespace android {
+namespace uirenderer {
+
+class TextureCache: public OnEntryRemoved<SkBitmap*, Texture*> {
+public:
+ TextureCache(unsigned int maxEntries);
+ ~TextureCache();
+
+ void operator()(SkBitmap* key, Texture* value);
+
+ Texture* get(SkBitmap* bitmap);
+ Texture* remove(SkBitmap* bitmap);
+ void clear();
+
+private:
+ Texture* generateTexture(SkBitmap* bitmap);
+
+ GenerationCache<SkBitmap, Texture> mCache;
+}; // class TextureCache
+
+}; // namespace uirenderer
+}; // namespace android
+
+#endif // ANDROID_UI_TEXTURE_CACHE_H