Add hooks for drawBitmap().
Change-Id: I58e962c3a8b2bc75c2605fe369ad3002579d86e0
Add texture cache.
Change-Id: I1c0e5581d228869e114438258a1014e33e024ad7
diff --git a/core/java/android/view/GLES20Canvas.java b/core/java/android/view/GLES20Canvas.java
index aafd3ff..5a2e99d 100644
--- a/core/java/android/view/GLES20Canvas.java
+++ b/core/java/android/view/GLES20Canvas.java
@@ -42,6 +42,9 @@
private int mWidth;
private int mHeight;
+
+ private final float[] mPoint = new float[2];
+ private final float[] mLine = new float[4];
///////////////////////////////////////////////////////////////////////////
// Constructors
@@ -64,7 +67,7 @@
nDestroyRenderer(mRenderer);
}
}
-
+
private native void nDestroyRenderer(int renderer);
///////////////////////////////////////////////////////////////////////////
@@ -358,24 +361,45 @@
@Override
public void drawBitmap(Bitmap bitmap, float left, float top, Paint paint) {
- // TODO: Implement
+ final int nativePaint = paint == null ? 0 : paint.mNativePaint;
+ nDrawBitmap(mRenderer, bitmap.mNativeBitmap, left, top, nativePaint,
+ bitmap.getDensity(), mDensity, mScreenDensity);
}
@Override
public void drawBitmap(Bitmap bitmap, Matrix matrix, Paint paint) {
- // TODO: Implement
+ final float width = bitmap.getWidth();
+ final float height = bitmap.getHeight();
+ final int nativePaint = paint == null ? 0 : paint.mNativePaint;
+ nDrawBitmap(mRenderer, bitmap.mNativeBitmap, 0.0f, 0.0f, width, height,
+ 0.0f, 0.0f, width, height, matrix.native_instance, nativePaint,
+ bitmap.getDensity(), mDensity, mScreenDensity);
}
@Override
public void drawBitmap(Bitmap bitmap, Rect src, Rect dst, Paint paint) {
- // TODO: Implement
+ final int nativePaint = paint == null ? 0 : paint.mNativePaint;
+ nDrawBitmap(mRenderer, bitmap.mNativeBitmap, src.left, src.top, src.right, src.bottom,
+ dst.left, dst.top, dst.right, dst.bottom, 0, nativePaint,
+ bitmap.getDensity(), mDensity, mScreenDensity);
}
@Override
public void drawBitmap(Bitmap bitmap, Rect src, RectF dst, Paint paint) {
- // TODO: Implement
+ final int nativePaint = paint == null ? 0 : paint.mNativePaint;
+ nDrawBitmap(mRenderer, bitmap.mNativeBitmap, src.left, src.top, src.right, src.bottom,
+ dst.left, dst.top, dst.right, dst.bottom, 0, nativePaint,
+ bitmap.getDensity(), mDensity, mScreenDensity);
}
+ private native void nDrawBitmap(int renderer, int bitmap, float left, float top, int paint,
+ int bitmapDensity, int canvasDensity, int screenDensity);
+
+ private native void nDrawBitmap(int renderer, int bitmap,
+ float srcLeft, float srcTop, float srcRight, float srcBottom,
+ float left, float top, float right, float bottom, int matrix, int paint,
+ int bitmapDensity, int canvasDensity, int screenDensity);
+
@Override
public void drawBitmap(int[] colors, int offset, int stride, float x, float y,
int width, int height, boolean hasAlpha, Paint paint) {
@@ -386,14 +410,12 @@
@Override
public void drawBitmap(int[] colors, int offset, int stride, int x, int y,
int width, int height, boolean hasAlpha, Paint paint) {
-
- // TODO: Implement
+ drawBitmap(colors, offset, stride, (float) x, (float) y, width, height, hasAlpha, paint);
}
@Override
public void drawBitmapMesh(Bitmap bitmap, int meshWidth, int meshHeight, float[] verts,
int vertOffset, int[] colors, int colorOffset, Paint paint) {
-
throw new UnsupportedOperationException();
}
@@ -416,7 +438,11 @@
@Override
public void drawLine(float startX, float startY, float stopX, float stopY, Paint paint) {
- // TODO: Implement
+ mLine[0] = startX;
+ mLine[1] = startY;
+ mLine[2] = stopX;
+ mLine[3] = stopY;
+ drawLines(mLine, 0, 1, paint);
}
@Override
@@ -426,7 +452,7 @@
@Override
public void drawLines(float[] pts, Paint paint) {
- // TODO: Implement
+ drawLines(pts, 0, pts.length / 4, paint);
}
@Override
@@ -461,7 +487,9 @@
@Override
public void drawPoint(float x, float y, Paint paint) {
- // TODO: Implement
+ mPoint[0] = x;
+ mPoint[1] = y;
+ drawPoints(mPoint, 0, 1, paint);
}
@Override
@@ -471,7 +499,7 @@
@Override
public void drawPoints(float[] pts, Paint paint) {
- // TODO: Implement
+ drawPoints(pts, 0, pts.length / 2, paint);
}
@Override
@@ -529,13 +557,12 @@
@Override
public void drawText(String text, float x, float y, Paint paint) {
- // TODO: Implement
+ drawText(text, 0, text.length(), x, y, paint);
}
@Override
public void drawTextOnPath(char[] text, int index, int count, Path path, float hOffset,
float vOffset, Paint paint) {
-
throw new UnsupportedOperationException();
}
@@ -547,14 +574,12 @@
@Override
public void drawTextRun(char[] text, int index, int count, int contextIndex, int contextCount,
float x, float y, int dir, Paint paint) {
-
throw new UnsupportedOperationException();
}
@Override
public void drawTextRun(CharSequence text, int start, int end, int contextStart, int contextEnd,
float x, float y, int dir, Paint paint) {
-
throw new UnsupportedOperationException();
}
@@ -562,7 +587,6 @@
public void drawVertices(VertexMode mode, int vertexCount, float[] verts, int vertOffset,
float[] texs, int texOffset, int[] colors, int colorOffset, short[] indices,
int indexOffset, int indexCount, Paint paint) {
-
throw new UnsupportedOperationException();
}
}
diff --git a/core/java/android/view/HardwareRenderer.java b/core/java/android/view/HardwareRenderer.java
index c7fe31b..a1ee3d3 100644
--- a/core/java/android/view/HardwareRenderer.java
+++ b/core/java/android/view/HardwareRenderer.java
@@ -76,10 +76,12 @@
* @param attachInfo AttachInfo tied to the specified view.
* @param translator Translator used to draw applications in compatibility mode.
* @param yoff The vertical offset for the drawing.
+ * @param density The density of the application
* @param scalingRequired Whether drawing should be scaled.
*/
abstract void draw(View view, View.AttachInfo attachInfo,
- CompatibilityInfo.Translator translator, int yoff, boolean scalingRequired);
+ CompatibilityInfo.Translator translator, int yoff, int density,
+ boolean scalingRequired);
/**
* Initializes the hardware renderer for the specified surface and setup the
@@ -370,7 +372,7 @@
@Override
void draw(View view, View.AttachInfo attachInfo, CompatibilityInfo.Translator translator,
- int yoff, boolean scalingRequired) {
+ int yoff, int density, boolean scalingRequired) {
if (canDraw()) {
attachInfo.mDrawingTime = SystemClock.uptimeMillis();
@@ -386,6 +388,7 @@
if (translator != null) {
translator.translateCanvas(canvas);
}
+ canvas.setDensity(density);
canvas.setScreenDensity(scalingRequired ? DisplayMetrics.DENSITY_DEVICE : 0);
view.draw(canvas);
diff --git a/core/java/android/view/ViewRoot.java b/core/java/android/view/ViewRoot.java
index 09c1793..e63ecef 100644
--- a/core/java/android/view/ViewRoot.java
+++ b/core/java/android/view/ViewRoot.java
@@ -1264,7 +1264,7 @@
if (mHwRenderer != null && mHwRenderer.isEnabled()) {
if (!dirty.isEmpty()) {
- mHwRenderer.draw(mView, mAttachInfo, mTranslator, yoff, scalingRequired);
+ mHwRenderer.draw(mView, mAttachInfo, mTranslator, yoff, mDensity, scalingRequired);
}
if (scrolling) {
diff --git a/core/jni/android_view_GLES20Canvas.cpp b/core/jni/android_view_GLES20Canvas.cpp
index fd9ce44..bd3b18d 100644
--- a/core/jni/android_view_GLES20Canvas.cpp
+++ b/core/jni/android_view_GLES20Canvas.cpp
@@ -18,6 +18,7 @@
#include <nativehelper/JNIHelp.h>
#include <android_runtime/AndroidRuntime.h>
+#include <SkBitmap.h>
#include <SkCanvas.h>
#include <SkMatrix.h>
#include <SkPaint.h>
@@ -44,11 +45,11 @@
// Constructors
// ----------------------------------------------------------------------------
-static OpenGLRenderer* android_view_GLES20Renderer_createRenderer(JNIEnv* env, jobject canvas) {
+static OpenGLRenderer* android_view_GLES20Canvas_createRenderer(JNIEnv* env, jobject canvas) {
return new OpenGLRenderer;
}
-static void android_view_GLES20Renderer_destroyRenderer(JNIEnv* env, jobject canvas,
+static void android_view_GLES20Canvas_destroyRenderer(JNIEnv* env, jobject canvas,
OpenGLRenderer* renderer) {
delete renderer;
}
@@ -57,12 +58,12 @@
// Setup
// ----------------------------------------------------------------------------
-static void android_view_GLES20Renderer_setViewport(JNIEnv* env, jobject canvas,
+static void android_view_GLES20Canvas_setViewport(JNIEnv* env, jobject canvas,
OpenGLRenderer* renderer, jint width, jint height) {
renderer->setViewport(width, height);
}
-static void android_view_GLES20Renderer_prepare(JNIEnv* env, jobject canvas,
+static void android_view_GLES20Canvas_prepare(JNIEnv* env, jobject canvas,
OpenGLRenderer* renderer) {
renderer->prepare();
}
@@ -71,22 +72,22 @@
// State
// ----------------------------------------------------------------------------
-static jint android_view_GLES20Renderer_save(JNIEnv* env, jobject canvas, OpenGLRenderer* renderer,
+static jint android_view_GLES20Canvas_save(JNIEnv* env, jobject canvas, OpenGLRenderer* renderer,
jint flags) {
return renderer->save(flags);
}
-static jint android_view_GLES20Renderer_getSaveCount(JNIEnv* env, jobject canvas,
+static jint android_view_GLES20Canvas_getSaveCount(JNIEnv* env, jobject canvas,
OpenGLRenderer* renderer) {
return renderer->getSaveCount();
}
-static void android_view_GLES20Renderer_restore(JNIEnv* env, jobject canvas,
+static void android_view_GLES20Canvas_restore(JNIEnv* env, jobject canvas,
OpenGLRenderer* renderer) {
renderer->restore();
}
-static void android_view_GLES20Renderer_restoreToCount(JNIEnv* env, jobject canvas,
+static void android_view_GLES20Canvas_restoreToCount(JNIEnv* env, jobject canvas,
OpenGLRenderer* renderer, jint saveCount) {
renderer->restoreToCount(saveCount);
}
@@ -95,13 +96,13 @@
// Layers
// ----------------------------------------------------------------------------
-static jint android_view_GLES20Renderer_saveLayer(JNIEnv* env, jobject canvas,
+static jint android_view_GLES20Canvas_saveLayer(JNIEnv* env, jobject canvas,
OpenGLRenderer* renderer, jfloat left, jfloat top, jfloat right, jfloat bottom,
SkPaint* paint, jint saveFlags) {
return renderer->saveLayer(left, top, right, bottom, paint, saveFlags);
}
-static jint android_view_GLES20Renderer_saveLayerAlpha(JNIEnv* env, jobject canvas,
+static jint android_view_GLES20Canvas_saveLayerAlpha(JNIEnv* env, jobject canvas,
OpenGLRenderer* renderer, jfloat left, jfloat top, jfloat right, jfloat bottom,
jint alpha, jint saveFlags) {
return renderer->saveLayerAlpha(left, top, right, bottom, alpha, saveFlags);
@@ -111,25 +112,24 @@
// Clipping
// ----------------------------------------------------------------------------
-static bool android_view_GLES20Renderer_quickReject(JNIEnv* env, jobject canvas,
+static bool android_view_GLES20Canvas_quickReject(JNIEnv* env, jobject canvas,
OpenGLRenderer* renderer, jfloat left, jfloat top, jfloat right, jfloat bottom,
SkCanvas::EdgeType edge) {
return renderer->quickReject(left, top, right, bottom);
}
-static bool android_view_GLES20Renderer_clipRectF(JNIEnv* env, jobject canvas,
+static bool android_view_GLES20Canvas_clipRectF(JNIEnv* env, jobject canvas,
OpenGLRenderer* renderer, jfloat left, jfloat top, jfloat right, jfloat bottom) {
return renderer->clipRect(left, top, right, bottom);
}
-static bool android_view_GLES20Renderer_clipRect(JNIEnv* env, jobject canvas,
+static bool android_view_GLES20Canvas_clipRect(JNIEnv* env, jobject canvas,
OpenGLRenderer* renderer, jint left, jint top, jint right, jint bottom) {
return renderer->clipRect(float(left), float(top), float(right), float(bottom));
}
-static bool android_view_GLES20Renderer_getClipBounds(JNIEnv* env, jobject canvas,
+static bool android_view_GLES20Canvas_getClipBounds(JNIEnv* env, jobject canvas,
OpenGLRenderer* renderer, jobject rect) {
-
const android::uirenderer::Rect& bounds(renderer->getClipBounds());
env->CallVoidMethod(rect, gRectClassInfo.set,
@@ -142,32 +142,32 @@
// Transforms
// ----------------------------------------------------------------------------
-static void android_view_GLES20Renderer_translate(JNIEnv* env, jobject canvas,
+static void android_view_GLES20Canvas_translate(JNIEnv* env, jobject canvas,
OpenGLRenderer* renderer, jfloat dx, jfloat dy) {
renderer->translate(dx, dy);
}
-static void android_view_GLES20Renderer_rotate(JNIEnv* env, jobject canvas,
+static void android_view_GLES20Canvas_rotate(JNIEnv* env, jobject canvas,
OpenGLRenderer* renderer, jfloat degrees) {
renderer->rotate(degrees);
}
-static void android_view_GLES20Renderer_scale(JNIEnv* env, jobject canvas,
+static void android_view_GLES20Canvas_scale(JNIEnv* env, jobject canvas,
OpenGLRenderer* renderer, jfloat sx, jfloat sy) {
renderer->scale(sx, sy);
}
-static void android_view_GLES20Renderer_setMatrix(JNIEnv* env, jobject canvas,
+static void android_view_GLES20Canvas_setMatrix(JNIEnv* env, jobject canvas,
OpenGLRenderer* renderer, SkMatrix* matrix) {
renderer->setMatrix(matrix);
}
-static void android_view_GLES20Renderer_getMatrix(JNIEnv* env, jobject canvas,
+static void android_view_GLES20Canvas_getMatrix(JNIEnv* env, jobject canvas,
OpenGLRenderer* renderer, SkMatrix* matrix) {
renderer->getMatrix(matrix);
}
-static void android_view_GLES20Renderer_concatMatrix(JNIEnv* env, jobject canvas,
+static void android_view_GLES20Canvas_concatMatrix(JNIEnv* env, jobject canvas,
OpenGLRenderer* renderer, SkMatrix* matrix) {
renderer->concatMatrix(matrix);
}
@@ -176,12 +176,37 @@
// Drawing
// ----------------------------------------------------------------------------
-static void android_view_GLES20Renderer_drawColor(JNIEnv* env, jobject canvas,
- OpenGLRenderer* renderer, jint color, jint mode) {
- renderer->drawColor(color, (SkXfermode::Mode) mode);
+static void android_view_GLES20Canvas_drawBitmap(JNIEnv* env, jobject canvas,
+ OpenGLRenderer* renderer, SkBitmap* bitmap, float left, float top,
+ SkPaint* paint, jint bitmapDensity, jint canvasDensity,jint screenDensity) {
+ if (canvasDensity == bitmapDensity || canvasDensity == 0 || bitmapDensity == 0) {
+ renderer->drawBitmap(bitmap, left, top, paint);
+ } else {
+ renderer->save(0);
+ const float scale = canvasDensity / float(bitmapDensity);
+ renderer->translate(left, top);
+ renderer->scale(scale, scale);
+ renderer->drawBitmap(bitmap, left, top, paint);
+ renderer->restore();
+ }
}
-static void android_view_GLES20Renderer_drawRect(JNIEnv* env, jobject canvas,
+static void android_view_GLES20Canvas_drawBitmapRect(JNIEnv* env, jobject canvas,
+ OpenGLRenderer* renderer, SkBitmap* bitmap,
+ float srcLeft, float srcTop, float srcRight, float srcBottom,
+ float dstLeft, float dstTop, float dstRight, float dstBottom,
+ SkMatrix* matrix, SkPaint* paint,
+ jint bitmapDenstiy, jint canvasDensity, jint screenDensity) {
+ // TODO: Implement!
+ LOGE("Not implemented: drawBitmap(IIFFFFFFFFIIIII)V");
+}
+
+static void android_view_GLES20Canvas_drawColor(JNIEnv* env, jobject canvas,
+ OpenGLRenderer* renderer, jint color, SkXfermode::Mode mode) {
+ renderer->drawColor(color, mode);
+}
+
+static void android_view_GLES20Canvas_drawRect(JNIEnv* env, jobject canvas,
OpenGLRenderer* renderer, jfloat left, jfloat top, jfloat right, jfloat bottom,
SkPaint* paint) {
renderer->drawRect(left, top, right, bottom, paint);
@@ -194,36 +219,38 @@
const char* const kClassPathName = "android/view/GLES20Canvas";
static JNINativeMethod gMethods[] = {
- { "nCreateRenderer", "()I", (void*) android_view_GLES20Renderer_createRenderer },
- { "nDestroyRenderer", "(I)V", (void*) android_view_GLES20Renderer_destroyRenderer },
- { "nSetViewport", "(III)V", (void*) android_view_GLES20Renderer_setViewport },
- { "nPrepare", "(I)V", (void*) android_view_GLES20Renderer_prepare },
+ { "nCreateRenderer", "()I", (void*) android_view_GLES20Canvas_createRenderer },
+ { "nDestroyRenderer", "(I)V", (void*) android_view_GLES20Canvas_destroyRenderer },
+ { "nSetViewport", "(III)V", (void*) android_view_GLES20Canvas_setViewport },
+ { "nPrepare", "(I)V", (void*) android_view_GLES20Canvas_prepare },
- { "nSave", "(II)I", (void*) android_view_GLES20Renderer_save },
- { "nRestore", "(I)V", (void*) android_view_GLES20Renderer_restore },
- { "nRestoreToCount", "(II)V", (void*) android_view_GLES20Renderer_restoreToCount },
- { "nGetSaveCount", "(I)I", (void*) android_view_GLES20Renderer_getSaveCount },
+ { "nSave", "(II)I", (void*) android_view_GLES20Canvas_save },
+ { "nRestore", "(I)V", (void*) android_view_GLES20Canvas_restore },
+ { "nRestoreToCount", "(II)V", (void*) android_view_GLES20Canvas_restoreToCount },
+ { "nGetSaveCount", "(I)I", (void*) android_view_GLES20Canvas_getSaveCount },
- { "nSaveLayer", "(IFFFFII)I", (void*) android_view_GLES20Renderer_saveLayer },
- { "nSaveLayerAlpha", "(IFFFFII)I", (void*) android_view_GLES20Renderer_saveLayerAlpha },
+ { "nSaveLayer", "(IFFFFII)I", (void*) android_view_GLES20Canvas_saveLayer },
+ { "nSaveLayerAlpha", "(IFFFFII)I", (void*) android_view_GLES20Canvas_saveLayerAlpha },
- { "nQuickReject", "(IFFFFI)Z", (void*) android_view_GLES20Renderer_quickReject },
- { "nClipRect", "(IFFFF)Z", (void*) android_view_GLES20Renderer_clipRectF },
- { "nClipRect", "(IIIII)Z", (void*) android_view_GLES20Renderer_clipRect },
+ { "nQuickReject", "(IFFFFI)Z", (void*) android_view_GLES20Canvas_quickReject },
+ { "nClipRect", "(IFFFF)Z", (void*) android_view_GLES20Canvas_clipRectF },
+ { "nClipRect", "(IIIII)Z", (void*) android_view_GLES20Canvas_clipRect },
- { "nTranslate", "(IFF)V", (void*) android_view_GLES20Renderer_translate },
- { "nRotate", "(IF)V", (void*) android_view_GLES20Renderer_rotate },
- { "nScale", "(IFF)V", (void*) android_view_GLES20Renderer_scale },
+ { "nTranslate", "(IFF)V", (void*) android_view_GLES20Canvas_translate },
+ { "nRotate", "(IF)V", (void*) android_view_GLES20Canvas_rotate },
+ { "nScale", "(IFF)V", (void*) android_view_GLES20Canvas_scale },
- { "nSetMatrix", "(II)V", (void*) android_view_GLES20Renderer_setMatrix },
- { "nGetMatrix", "(II)V", (void*) android_view_GLES20Renderer_getMatrix },
- { "nConcatMatrix", "(II)V", (void*) android_view_GLES20Renderer_concatMatrix },
+ { "nSetMatrix", "(II)V", (void*) android_view_GLES20Canvas_setMatrix },
+ { "nGetMatrix", "(II)V", (void*) android_view_GLES20Canvas_getMatrix },
+ { "nConcatMatrix", "(II)V", (void*) android_view_GLES20Canvas_concatMatrix },
- { "nDrawColor", "(III)V", (void*) android_view_GLES20Renderer_drawColor },
- { "nDrawRect", "(IFFFFI)V", (void*) android_view_GLES20Renderer_drawRect },
+ { "nDrawBitmap", "(IIFFIIII)V", (void*) android_view_GLES20Canvas_drawBitmap },
+ { "nDrawBitmap", "(IIFFFFFFFFIIIII)V", (void*) android_view_GLES20Canvas_drawBitmapRect },
+ { "nDrawColor", "(III)V", (void*) android_view_GLES20Canvas_drawColor },
+ { "nDrawRect", "(IFFFFI)V", (void*) android_view_GLES20Canvas_drawRect },
{ "nGetClipBounds", "(ILandroid/graphics/Rect;)Z",
- (void*) android_view_GLES20Renderer_getClipBounds },
+ (void*) android_view_GLES20Canvas_getClipBounds },
};
#define FIND_CLASS(var, className) \
diff --git a/graphics/java/android/graphics/Bitmap.java b/graphics/java/android/graphics/Bitmap.java
index e261cfa..537dd3a 100644
--- a/graphics/java/android/graphics/Bitmap.java
+++ b/graphics/java/android/graphics/Bitmap.java
@@ -35,9 +35,13 @@
*/
public static final int DENSITY_NONE = 0;
- // Note: mNativeBitmap is used by FaceDetector_jni.cpp
- // Don't change/rename without updating FaceDetector_jni.cpp
- private final int mNativeBitmap;
+ /**
+ * Note: mNativeBitmap is used by FaceDetector_jni.cpp
+ * Don't change/rename without updating FaceDetector_jni.cpp
+ *
+ * @hide
+ */
+ public final int mNativeBitmap;
private final boolean mIsMutable;
private byte[] mNinePatchChunk; // may be null
diff --git a/graphics/java/android/graphics/Canvas.java b/graphics/java/android/graphics/Canvas.java
index 3a0c18c..3b2210b 100644
--- a/graphics/java/android/graphics/Canvas.java
+++ b/graphics/java/android/graphics/Canvas.java
@@ -45,13 +45,19 @@
private GL mGL; // if not null, mBitmap must be null
// optional field set by the caller
- private DrawFilter mDrawFilter;
+ private DrawFilter mDrawFilter;
- // Package-scoped for quick access.
- /*package*/ int mDensity = Bitmap.DENSITY_NONE;
+ /**
+ * @hide
+ */
+ protected int mDensity = Bitmap.DENSITY_NONE;
- // Used to determine when compatibility scaling is in effect.
- private int mScreenDensity = Bitmap.DENSITY_NONE;
+ /**
+ * Used to determine when compatibility scaling is in effect.
+ *
+ * @hide
+ */
+ protected int mScreenDensity = Bitmap.DENSITY_NONE;
// Used by native code
@SuppressWarnings({"UnusedDeclaration"})
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
diff --git a/tests/HwAccelerationTest/AndroidManifest.xml b/tests/HwAccelerationTest/AndroidManifest.xml
index 30ac8d6..f9b2823 100644
--- a/tests/HwAccelerationTest/AndroidManifest.xml
+++ b/tests/HwAccelerationTest/AndroidManifest.xml
@@ -50,5 +50,15 @@
</intent-filter>
</activity>
+ <activity
+ android:name="BitmapsActivity"
+ android:label="_Bitmaps"
+ android:theme="@android:style/Theme.Translucent">
+ <intent-filter>
+ <action android:name="android.intent.action.MAIN" />
+ <category android:name="android.intent.category.LAUNCHER" />
+ </intent-filter>
+ </activity>
+
</application>
</manifest>
diff --git a/tests/HwAccelerationTest/res/drawable-hdpi/sunset1.jpg b/tests/HwAccelerationTest/res/drawable-hdpi/sunset1.jpg
new file mode 100644
index 0000000..92851f3
--- /dev/null
+++ b/tests/HwAccelerationTest/res/drawable-hdpi/sunset1.jpg
Binary files differ
diff --git a/tests/HwAccelerationTest/res/drawable-hdpi/sunset2.png b/tests/HwAccelerationTest/res/drawable-hdpi/sunset2.png
new file mode 100644
index 0000000..3258ee7
--- /dev/null
+++ b/tests/HwAccelerationTest/res/drawable-hdpi/sunset2.png
Binary files differ
diff --git a/tests/HwAccelerationTest/src/com/google/android/test/hwui/BitmapsActivity.java b/tests/HwAccelerationTest/src/com/google/android/test/hwui/BitmapsActivity.java
new file mode 100644
index 0000000..85e7bf0
--- /dev/null
+++ b/tests/HwAccelerationTest/src/com/google/android/test/hwui/BitmapsActivity.java
@@ -0,0 +1,79 @@
+/*
+ * 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.
+ */
+
+package com.google.android.test.hwui;
+
+import android.app.Activity;
+import android.content.Context;
+import android.graphics.Bitmap;
+import android.graphics.BitmapFactory;
+import android.graphics.Canvas;
+import android.graphics.Paint;
+import android.graphics.PorterDuff;
+import android.graphics.PorterDuffXfermode;
+import android.os.Bundle;
+import android.view.View;
+
+@SuppressWarnings({"UnusedDeclaration"})
+public class BitmapsActivity extends Activity {
+ @Override
+ protected void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ setContentView(new BitmapsView(this));
+ }
+
+ static class BitmapsView extends View {
+ private Paint mBitmapPaint;
+ private final Bitmap mBitmap1;
+ private final Bitmap mBitmap2;
+
+ BitmapsView(Context c) {
+ super(c);
+
+ mBitmap1 = BitmapFactory.decodeResource(c.getResources(), R.drawable.sunset1);
+ mBitmap2 = BitmapFactory.decodeResource(c.getResources(), R.drawable.sunset2);
+
+ mBitmapPaint = new Paint();
+ }
+
+ @Override
+ protected void onDraw(Canvas canvas) {
+ super.onDraw(canvas);
+
+ canvas.translate(120.0f, 50.0f);
+ canvas.drawBitmap(mBitmap1, 0.0f, 0.0f, mBitmapPaint);
+
+ canvas.translate(0.0f, mBitmap1.getHeight());
+ canvas.translate(0.0f, 25.0f);
+ canvas.drawBitmap(mBitmap2, 0.0f, 0.0f, null);
+
+ mBitmapPaint.setAlpha(127);
+ canvas.translate(0.0f, mBitmap2.getHeight());
+ canvas.translate(0.0f, 25.0f);
+ canvas.drawBitmap(mBitmap1, 0.0f, 0.0f, mBitmapPaint);
+
+ mBitmapPaint.setAlpha(255);
+ canvas.translate(0.0f, mBitmap1.getHeight());
+ canvas.translate(0.0f, 25.0f);
+ mBitmapPaint.setColor(0xffff0000);
+ canvas.drawRect(0.0f, 0.0f, mBitmap2.getWidth(), mBitmap2.getHeight(), mBitmapPaint);
+ mBitmapPaint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.DST_IN));
+ canvas.drawBitmap(mBitmap2, 0.0f, 0.0f, mBitmapPaint);
+
+ mBitmapPaint = new Paint();
+ }
+ }
+}