diff options
| author | 2010-06-30 15:50:05 -0700 | |
|---|---|---|
| committer | 2010-06-30 15:50:05 -0700 | |
| commit | 68e9a49aeb0b07d0d99c0a05771348bcd460a703 (patch) | |
| tree | 6c3b225d66e159df7355cd36ebcf1e6ba0e032a9 | |
| parent | 5840b7c1193e0deb28dd4e2f622eaa62cb0483a2 (diff) | |
| parent | ce0537b80087a6225273040a987414b1dd081aa0 (diff) | |
Merge "Add hooks for drawBitmap()."
| -rw-r--r-- | core/java/android/view/GLES20Canvas.java | 58 | ||||
| -rw-r--r-- | core/java/android/view/HardwareRenderer.java | 7 | ||||
| -rw-r--r-- | core/java/android/view/ViewRoot.java | 2 | ||||
| -rw-r--r-- | core/jni/android_view_GLES20Canvas.cpp | 121 | ||||
| -rw-r--r-- | graphics/java/android/graphics/Bitmap.java | 10 | ||||
| -rw-r--r-- | graphics/java/android/graphics/Canvas.java | 16 | ||||
| -rw-r--r-- | libs/hwui/Android.mk | 3 | ||||
| -rw-r--r-- | libs/hwui/GenerationCache.h | 208 | ||||
| -rw-r--r-- | libs/hwui/OpenGLRenderer.cpp | 10 | ||||
| -rw-r--r-- | libs/hwui/OpenGLRenderer.h | 8 | ||||
| -rw-r--r-- | libs/hwui/Texture.h | 50 | ||||
| -rw-r--r-- | libs/hwui/TextureCache.cpp | 86 | ||||
| -rw-r--r-- | libs/hwui/TextureCache.h | 48 | ||||
| -rw-r--r-- | tests/HwAccelerationTest/AndroidManifest.xml | 10 | ||||
| -rw-r--r-- | tests/HwAccelerationTest/res/drawable-hdpi/sunset1.jpg | bin | 0 -> 25019 bytes | |||
| -rw-r--r-- | tests/HwAccelerationTest/res/drawable-hdpi/sunset2.png | bin | 0 -> 55763 bytes | |||
| -rw-r--r-- | tests/HwAccelerationTest/src/com/google/android/test/hwui/BitmapsActivity.java | 79 |
17 files changed, 639 insertions, 77 deletions
diff --git a/core/java/android/view/GLES20Canvas.java b/core/java/android/view/GLES20Canvas.java index aafd3ffeb585..5a2e99df13f2 100644 --- a/core/java/android/view/GLES20Canvas.java +++ b/core/java/android/view/GLES20Canvas.java @@ -42,6 +42,9 @@ class GLES20Canvas extends Canvas { 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 @@ class GLES20Canvas extends Canvas { nDestroyRenderer(mRenderer); } } - + private native void nDestroyRenderer(int renderer); /////////////////////////////////////////////////////////////////////////// @@ -358,24 +361,45 @@ class GLES20Canvas extends Canvas { @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 @@ class GLES20Canvas extends Canvas { @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 @@ class GLES20Canvas extends Canvas { @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 @@ class GLES20Canvas extends Canvas { @Override public void drawLines(float[] pts, Paint paint) { - // TODO: Implement + drawLines(pts, 0, pts.length / 4, paint); } @Override @@ -461,7 +487,9 @@ class GLES20Canvas extends Canvas { @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 @@ class GLES20Canvas extends Canvas { @Override public void drawPoints(float[] pts, Paint paint) { - // TODO: Implement + drawPoints(pts, 0, pts.length / 2, paint); } @Override @@ -529,13 +557,12 @@ class GLES20Canvas extends Canvas { @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 @@ class GLES20Canvas extends Canvas { @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 @@ class GLES20Canvas extends Canvas { 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 c7fe31b43ba3..a1ee3d3dfba8 100644 --- a/core/java/android/view/HardwareRenderer.java +++ b/core/java/android/view/HardwareRenderer.java @@ -76,10 +76,12 @@ abstract class HardwareRenderer { * @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 @@ abstract class HardwareRenderer { @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 @@ abstract class HardwareRenderer { 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 09c1793b6cbd..e63ecef63b96 100644 --- a/core/java/android/view/ViewRoot.java +++ b/core/java/android/view/ViewRoot.java @@ -1264,7 +1264,7 @@ public final class ViewRoot extends Handler implements ViewParent, View.AttachIn 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 fd9ce445f5e4..bd3b18d4e2ec 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 @@ static struct { // 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 @@ static void android_view_GLES20Renderer_destroyRenderer(JNIEnv* env, jobject can // 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 @@ static void android_view_GLES20Renderer_prepare(JNIEnv* env, jobject canvas, // 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 @@ static void android_view_GLES20Renderer_restoreToCount(JNIEnv* env, jobject canv // 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 @@ static jint android_view_GLES20Renderer_saveLayerAlpha(JNIEnv* env, jobject canv // 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 @@ static bool android_view_GLES20Renderer_getClipBounds(JNIEnv* env, jobject canva // 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 @@ static void android_view_GLES20Renderer_concatMatrix(JNIEnv* env, jobject canvas // 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_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_GLES20Renderer_drawRect(JNIEnv* env, jobject canvas, +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 @@ static void android_view_GLES20Renderer_drawRect(JNIEnv* env, jobject canvas, 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 e261cfaa7a9a..537dd3aeb730 100644 --- a/graphics/java/android/graphics/Bitmap.java +++ b/graphics/java/android/graphics/Bitmap.java @@ -35,9 +35,13 @@ public final class Bitmap implements Parcelable { */ 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 3a0c18c6770a..3b2210bcf0d2 100644 --- a/graphics/java/android/graphics/Canvas.java +++ b/graphics/java/android/graphics/Canvas.java @@ -45,13 +45,19 @@ public class Canvas { 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 fd7681134e34..95ebda1938ab 100644 --- a/libs/hwui/Android.mk +++ b/libs/hwui/Android.mk @@ -4,7 +4,8 @@ include $(CLEAR_VARS) 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 000000000000..c4ff5879eec1 --- /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 aa992c4b044c..d80238599648 100644 --- a/libs/hwui/OpenGLRenderer.cpp +++ b/libs/hwui/OpenGLRenderer.cpp @@ -33,6 +33,8 @@ namespace uirenderer { // 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 @@ static const Blender gBlends[] = { // Constructors/destructor /////////////////////////////////////////////////////////////////////////////// -OpenGLRenderer::OpenGLRenderer() { +OpenGLRenderer::OpenGLRenderer(): mTextureCache(MAX_TEXTURE_COUNT) { LOGD("Create OpenGLRenderer"); mDrawColorShader = new DrawColorProgram; @@ -92,6 +94,8 @@ OpenGLRenderer::OpenGLRenderer() { OpenGLRenderer::~OpenGLRenderer() { LOGD("Destroy OpenGLRenderer"); + + mTextureCache.clear(); } /////////////////////////////////////////////////////////////////////////////// @@ -374,6 +378,10 @@ bool OpenGLRenderer::clipRect(float left, float top, float right, float bottom) // 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 1af73c1014db..e5cc98cfefb2 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 @@ public: 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 @@ private: // 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 000000000000..b3b17cae45e2 --- /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 000000000000..b4a57eef2caf --- /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 000000000000..42328f425500 --- /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 30ac8d6e0b37..f9b2823ba32b 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 Binary files differnew file mode 100644 index 000000000000..92851f3df924 --- /dev/null +++ b/tests/HwAccelerationTest/res/drawable-hdpi/sunset1.jpg diff --git a/tests/HwAccelerationTest/res/drawable-hdpi/sunset2.png b/tests/HwAccelerationTest/res/drawable-hdpi/sunset2.png Binary files differnew file mode 100644 index 000000000000..3258ee745389 --- /dev/null +++ b/tests/HwAccelerationTest/res/drawable-hdpi/sunset2.png 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 000000000000..85e7bf07bc88 --- /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(); + } + } +} |