Remove calls to SkCanvas::setBitmapDevice()
Change-Id: Ib0aa2f65b77802b105c0e8a9d7cdde2e863d3673
diff --git a/core/java/android/view/Surface.java b/core/java/android/view/Surface.java
index a972b75..c10f287 100644
--- a/core/java/android/view/Surface.java
+++ b/core/java/android/view/Surface.java
@@ -215,7 +215,6 @@
private int mNativeSurfaceControl; // SurfaceControl*
private int mGenerationId; // incremented each time mNativeSurface changes
private final Canvas mCanvas = new CompatibleCanvas();
- private int mCanvasSaveCount; // Canvas save count at time of lockCanvas()
// The Translator for density compatibility mode. This is used for scaling
// the canvas to perform the appropriate density transformation.
diff --git a/core/jni/android/graphics/Canvas.cpp b/core/jni/android/graphics/Canvas.cpp
index ef9b96e..7208c57 100644
--- a/core/jni/android/graphics/Canvas.cpp
+++ b/core/jni/android/graphics/Canvas.cpp
@@ -93,14 +93,6 @@
return canvas->getDevice()->accessBitmap(false).height();
}
- static void setBitmap(JNIEnv* env, jobject, SkCanvas* canvas, SkBitmap* bitmap) {
- if (bitmap) {
- canvas->setBitmapDevice(*bitmap);
- } else {
- canvas->setDevice(NULL);
- }
- }
-
static int saveAll(JNIEnv* env, jobject jcanvas) {
NPE_CHECK_RETURN_ZERO(env, jcanvas);
return GraphicsJNI::getNativeCanvas(env, jcanvas)->save();
@@ -967,7 +959,6 @@
{"isOpaque","()Z", (void*) SkCanvasGlue::isOpaque},
{"getWidth","()I", (void*) SkCanvasGlue::getWidth},
{"getHeight","()I", (void*) SkCanvasGlue::getHeight},
- {"native_setBitmap","(II)V", (void*) SkCanvasGlue::setBitmap},
{"save","()I", (void*) SkCanvasGlue::saveAll},
{"save","(I)I", (void*) SkCanvasGlue::save},
{"native_saveLayer","(ILandroid/graphics/RectF;II)I",
diff --git a/core/jni/android_view_Surface.cpp b/core/jni/android_view_Surface.cpp
index bef751b..ed92e43 100644
--- a/core/jni/android_view_Surface.cpp
+++ b/core/jni/android_view_Surface.cpp
@@ -66,7 +66,6 @@
jfieldID mNativeSurfaceControl;
jfieldID mGenerationId;
jfieldID mCanvas;
- jfieldID mCanvasSaveCount;
jmethodID ctor;
} gSurfaceClassInfo;
@@ -78,11 +77,16 @@
} gRectClassInfo;
static struct {
+ jfieldID mFinalizer;
jfieldID mNativeCanvas;
jfieldID mSurfaceFormat;
} gCanvasClassInfo;
static struct {
+ jfieldID mNativeCanvas;
+} gCanvasFinalizerClassInfo;
+
+static struct {
jfieldID width;
jfieldID height;
jfieldID refreshRate;
@@ -374,6 +378,15 @@
}
}
+static inline void swapCanvasPtr(JNIEnv* env, jobject canvasObj, SkCanvas* newCanvas) {
+ jobject canvasFinalizerObj = env->GetObjectField(canvasObj, gCanvasClassInfo.mFinalizer);
+ SkCanvas* previousCanvas = reinterpret_cast<SkCanvas*>(
+ env->GetIntField(canvasObj, gCanvasClassInfo.mNativeCanvas));
+ env->SetIntField(canvasObj, gCanvasClassInfo.mNativeCanvas, (int)newCanvas);
+ env->SetIntField(canvasFinalizerObj, gCanvasFinalizerClassInfo.mNativeCanvas, (int)newCanvas);
+ SkSafeUnref(previousCanvas);
+}
+
static jobject nativeLockCanvas(JNIEnv* env, jobject surfaceObj, jobject dirtyRectObj) {
sp<Surface> surface(getSurface(env, surfaceObj));
if (!Surface::isValid(surface)) {
@@ -410,8 +423,6 @@
jobject canvasObj = env->GetObjectField(surfaceObj, gSurfaceClassInfo.mCanvas);
env->SetIntField(canvasObj, gCanvasClassInfo.mSurfaceFormat, info.format);
- SkCanvas* nativeCanvas = reinterpret_cast<SkCanvas*>(
- env->GetIntField(canvasObj, gCanvasClassInfo.mNativeCanvas));
SkBitmap bitmap;
ssize_t bpr = info.s * bytesPerPixel(info.format);
bitmap.setConfig(convertPixelFormat(info.format), info.w, info.h, bpr);
@@ -424,7 +435,9 @@
// be safe with an empty bitmap.
bitmap.setPixels(NULL);
}
- nativeCanvas->setBitmapDevice(bitmap);
+
+ SkCanvas* nativeCanvas = SkNEW_ARGS(SkCanvas, (bitmap));
+ swapCanvasPtr(env, canvasObj, nativeCanvas);
SkRegion clipReg;
if (dirtyRegion.isRect()) { // very common case
@@ -441,9 +454,6 @@
nativeCanvas->clipRegion(clipReg);
- int saveCount = nativeCanvas->save();
- env->SetIntField(surfaceObj, gSurfaceClassInfo.mCanvasSaveCount, saveCount);
-
if (dirtyRectObj) {
const Rect& bounds(dirtyRegion.getBounds());
env->SetIntField(dirtyRectObj, gRectClassInfo.left, bounds.left);
@@ -468,12 +478,8 @@
}
// detach the canvas from the surface
- SkCanvas* nativeCanvas = reinterpret_cast<SkCanvas*>(
- env->GetIntField(canvasObj, gCanvasClassInfo.mNativeCanvas));
- int saveCount = env->GetIntField(surfaceObj, gSurfaceClassInfo.mCanvasSaveCount);
- nativeCanvas->restoreToCount(saveCount);
- nativeCanvas->setBitmapDevice(SkBitmap());
- env->SetIntField(surfaceObj, gSurfaceClassInfo.mCanvasSaveCount, 0);
+ SkCanvas* nativeCanvas = SkNEW(SkCanvas);
+ swapCanvasPtr(env, canvasObj, nativeCanvas);
// unlock surface
status_t err = surface->unlockAndPost();
@@ -889,14 +895,16 @@
env->GetFieldID(gSurfaceClassInfo.clazz, "mGenerationId", "I");
gSurfaceClassInfo.mCanvas =
env->GetFieldID(gSurfaceClassInfo.clazz, "mCanvas", "Landroid/graphics/Canvas;");
- gSurfaceClassInfo.mCanvasSaveCount =
- env->GetFieldID(gSurfaceClassInfo.clazz, "mCanvasSaveCount", "I");
gSurfaceClassInfo.ctor = env->GetMethodID(gSurfaceClassInfo.clazz, "<init>", "()V");
clazz = env->FindClass("android/graphics/Canvas");
+ gCanvasClassInfo.mFinalizer = env->GetFieldID(clazz, "mFinalizer", "Landroid/graphics/Canvas$CanvasFinalizer;");
gCanvasClassInfo.mNativeCanvas = env->GetFieldID(clazz, "mNativeCanvas", "I");
gCanvasClassInfo.mSurfaceFormat = env->GetFieldID(clazz, "mSurfaceFormat", "I");
+ clazz = env->FindClass("android/graphics/Canvas$CanvasFinalizer");
+ gCanvasFinalizerClassInfo.mNativeCanvas = env->GetFieldID(clazz, "mNativeCanvas", "I");
+
clazz = env->FindClass("android/graphics/Rect");
gRectClassInfo.left = env->GetFieldID(clazz, "left", "I");
gRectClassInfo.top = env->GetFieldID(clazz, "top", "I");
diff --git a/core/jni/android_view_TextureView.cpp b/core/jni/android_view_TextureView.cpp
index 87b312f..64cbda3 100644
--- a/core/jni/android_view_TextureView.cpp
+++ b/core/jni/android_view_TextureView.cpp
@@ -43,11 +43,16 @@
} gRectClassInfo;
static struct {
- jfieldID nativeCanvas;
- jfieldID surfaceFormat;
+ jfieldID mFinalizer;
+ jfieldID mNativeCanvas;
+ jfieldID mSurfaceFormat;
} gCanvasClassInfo;
static struct {
+ jfieldID mNativeCanvas;
+} gCanvasFinalizerClassInfo;
+
+static struct {
jfieldID nativeWindow;
} gTextureViewClassInfo;
@@ -120,6 +125,15 @@
}
}
+static inline void swapCanvasPtr(JNIEnv* env, jobject canvasObj, SkCanvas* newCanvas) {
+ jobject canvasFinalizerObj = env->GetObjectField(canvasObj, gCanvasClassInfo.mFinalizer);
+ SkCanvas* previousCanvas = reinterpret_cast<SkCanvas*>(
+ env->GetIntField(canvasObj, gCanvasClassInfo.mNativeCanvas));
+ env->SetIntField(canvasObj, gCanvasClassInfo.mNativeCanvas, (int)newCanvas);
+ env->SetIntField(canvasFinalizerObj, gCanvasFinalizerClassInfo.mNativeCanvas, (int)newCanvas);
+ SkSafeUnref(previousCanvas);
+}
+
static void android_view_TextureView_lockCanvas(JNIEnv* env, jobject,
jint nativeWindow, jobject canvas, jobject dirtyRect) {
@@ -157,9 +171,10 @@
bitmap.setPixels(NULL);
}
- SET_INT(canvas, gCanvasClassInfo.surfaceFormat, buffer.format);
- SkCanvas* nativeCanvas = (SkCanvas*) GET_INT(canvas, gCanvasClassInfo.nativeCanvas);
- nativeCanvas->setBitmapDevice(bitmap);
+ SET_INT(canvas, gCanvasClassInfo.mSurfaceFormat, buffer.format);
+
+ SkCanvas* nativeCanvas = SkNEW_ARGS(SkCanvas, (bitmap));
+ swapCanvasPtr(env, canvas, nativeCanvas);
SkRect clipRect;
clipRect.set(rect.left, rect.top, rect.right, rect.bottom);
@@ -174,8 +189,8 @@
static void android_view_TextureView_unlockCanvasAndPost(JNIEnv* env, jobject,
jint nativeWindow, jobject canvas) {
- SkCanvas* nativeCanvas = (SkCanvas*) GET_INT(canvas, gCanvasClassInfo.nativeCanvas);
- nativeCanvas->setBitmapDevice(SkBitmap());
+ SkCanvas* nativeCanvas = SkNEW(SkCanvas);
+ swapCanvasPtr(env, canvas, nativeCanvas);
if (nativeWindow) {
sp<ANativeWindow> window((ANativeWindow*) nativeWindow);
@@ -226,8 +241,12 @@
GET_FIELD_ID(gRectClassInfo.bottom, clazz, "bottom", "I");
FIND_CLASS(clazz, "android/graphics/Canvas");
- GET_FIELD_ID(gCanvasClassInfo.nativeCanvas, clazz, "mNativeCanvas", "I");
- GET_FIELD_ID(gCanvasClassInfo.surfaceFormat, clazz, "mSurfaceFormat", "I");
+ GET_FIELD_ID(gCanvasClassInfo.mFinalizer, clazz, "mFinalizer", "Landroid/graphics/Canvas$CanvasFinalizer;");
+ GET_FIELD_ID(gCanvasClassInfo.mNativeCanvas, clazz, "mNativeCanvas", "I");
+ GET_FIELD_ID(gCanvasClassInfo.mSurfaceFormat, clazz, "mSurfaceFormat", "I");
+
+ FIND_CLASS(clazz, "android/graphics/Canvas$CanvasFinalizer");
+ GET_FIELD_ID(gCanvasFinalizerClassInfo.mNativeCanvas, clazz, "mNativeCanvas", "I");
FIND_CLASS(clazz, "android/view/TextureView");
GET_FIELD_ID(gTextureViewClassInfo.nativeWindow, clazz, "mNativeWindow", "I");
diff --git a/graphics/java/android/graphics/Canvas.java b/graphics/java/android/graphics/Canvas.java
index d8cac41..483d11a 100644
--- a/graphics/java/android/graphics/Canvas.java
+++ b/graphics/java/android/graphics/Canvas.java
@@ -37,8 +37,8 @@
* Canvas and Drawables</a> developer guide.</p></div>
*/
public class Canvas {
- // assigned in constructors, freed in finalizer
- final int mNativeCanvas;
+ // assigned in constructors or setBitmap, freed in finalizer
+ int mNativeCanvas;
// may be null
private Bitmap mBitmap;
@@ -83,7 +83,7 @@
private final CanvasFinalizer mFinalizer;
private static class CanvasFinalizer {
- private final int mNativeCanvas;
+ private int mNativeCanvas;
public CanvasFinalizer(int nativeCanvas) {
mNativeCanvas = nativeCanvas;
@@ -143,6 +143,17 @@
}
/**
+ * Replace existing canvas while ensuring that the swap has occurred before
+ * the previous native canvas is unreferenced.
+ */
+ private void safeCanvasSwap(int nativeCanvas) {
+ final int oldCanvas = mNativeCanvas;
+ mNativeCanvas = nativeCanvas;
+ mFinalizer.mNativeCanvas = nativeCanvas;
+ finalizer(oldCanvas);
+ }
+
+ /**
* Returns null.
*
* @deprecated This method is not supported and should not be invoked.
@@ -168,11 +179,11 @@
}
/**
- * Specify a bitmap for the canvas to draw into. As a side-effect, also
- * updates the canvas's target density to match that of the bitmap.
+ * Specify a bitmap for the canvas to draw into. As a side-effect, the
+ * canvas' target density is updated to match that of the bitmap while all
+ * other state such as the layers, filters, matrix, and clip are reset.
*
* @param bitmap Specifies a mutable bitmap for the canvas to draw into.
- *
* @see #setDensity(int)
* @see #getDensity()
*/
@@ -181,17 +192,19 @@
throw new RuntimeException("Can't set a bitmap device on a GL canvas");
}
- int pointer = 0;
- if (bitmap != null) {
+ if (bitmap == null) {
+ safeCanvasSwap(initRaster(0));
+ mDensity = Bitmap.DENSITY_NONE;
+ } else {
if (!bitmap.isMutable()) {
throw new IllegalStateException();
}
throwIfRecycled(bitmap);
+
+ safeCanvasSwap(initRaster(bitmap.ni()));
mDensity = bitmap.mDensity;
- pointer = bitmap.ni();
}
- native_setBitmap(mNativeCanvas, pointer);
mBitmap = bitmap;
}
@@ -1625,7 +1638,6 @@
public static native void freeTextLayoutCaches();
private static native int initRaster(int nativeBitmapOrZero);
- private static native void native_setBitmap(int nativeCanvas, int bitmap);
private static native int native_saveLayer(int nativeCanvas, RectF bounds,
int paint, int layerFlags);
private static native int native_saveLayer(int nativeCanvas, float l,
diff --git a/services/input/SpriteController.cpp b/services/input/SpriteController.cpp
index 1f3d2cf..8163ea0 100644
--- a/services/input/SpriteController.cpp
+++ b/services/input/SpriteController.cpp
@@ -208,8 +208,7 @@
surfaceInfo.w, surfaceInfo.h, bpr);
surfaceBitmap.setPixels(surfaceInfo.bits);
- SkCanvas surfaceCanvas;
- surfaceCanvas.setBitmapDevice(surfaceBitmap);
+ SkCanvas surfaceCanvas(surfaceBitmap);
SkPaint paint;
paint.setXfermodeMode(SkXfermode::kSrc_Mode);