diff options
Diffstat (limited to 'core/java/android/view/Surface.java')
-rw-r--r-- | core/java/android/view/Surface.java | 123 |
1 files changed, 110 insertions, 13 deletions
diff --git a/core/java/android/view/Surface.java b/core/java/android/view/Surface.java index 3770b8a..132e25c 100644 --- a/core/java/android/view/Surface.java +++ b/core/java/android/view/Surface.java @@ -87,6 +87,8 @@ public class Surface implements Parcelable { // non compatibility mode. private Matrix mCompatibleMatrix; + private HwuiContext mHwuiContext; + /** @hide */ @IntDef({ROTATION_0, ROTATION_90, ROTATION_180, ROTATION_270}) @Retention(RetentionPolicy.SOURCE) @@ -171,6 +173,10 @@ public class Surface implements Parcelable { nativeRelease(mNativeObject); setNativeObjectLocked(0); } + if (mHwuiContext != null) { + mHwuiContext.destroy(); + mHwuiContext = null; + } } } @@ -264,27 +270,60 @@ public class Surface implements Parcelable { * @param canvas The canvas previously obtained from {@link #lockCanvas}. */ public void unlockCanvasAndPost(Canvas canvas) { + synchronized (mLock) { + checkNotReleasedLocked(); + + if (mHwuiContext != null) { + mHwuiContext.unlockAndPost(canvas); + } else { + unlockSwCanvasAndPost(canvas); + } + } + } + + private void unlockSwCanvasAndPost(Canvas canvas) { if (canvas != mCanvas) { throw new IllegalArgumentException("canvas object must be the same instance that " + "was previously returned by lockCanvas"); } + if (mNativeObject != mLockedObject) { + Log.w(TAG, "WARNING: Surface's mNativeObject (0x" + + Long.toHexString(mNativeObject) + ") != mLockedObject (0x" + + Long.toHexString(mLockedObject) +")"); + } + if (mLockedObject == 0) { + throw new IllegalStateException("Surface was not locked"); + } + try { + nativeUnlockCanvasAndPost(mLockedObject, canvas); + } finally { + nativeRelease(mLockedObject); + mLockedObject = 0; + } + } + /** + * Gets a {@link Canvas} for drawing into this surface. + * + * After drawing into the provided {@link Canvas}, the caller must + * invoke {@link #unlockCanvasAndPost} to post the new contents to the surface. + * + * Unlike {@link #lockCanvas(Rect)} this will return a hardware-accelerated + * canvas. See the <a href="{@docRoot}guide/topics/graphics/hardware-accel.html#unsupported"> + * unsupported drawing operations</a> for a list of what is and isn't + * supported in a hardware-accelerated canvas. + * + * @return A canvas for drawing into the surface. + * + * @throws IllegalStateException If the canvas cannot be locked. + */ + public Canvas lockHardwareCanvas() { synchronized (mLock) { checkNotReleasedLocked(); - if (mNativeObject != mLockedObject) { - Log.w(TAG, "WARNING: Surface's mNativeObject (0x" + - Long.toHexString(mNativeObject) + ") != mLockedObject (0x" + - Long.toHexString(mLockedObject) +")"); - } - if (mLockedObject == 0) { - throw new IllegalStateException("Surface was not locked"); - } - try { - nativeUnlockCanvasAndPost(mLockedObject, canvas); - } finally { - nativeRelease(mLockedObject); - mLockedObject = 0; + if (mHwuiContext == null) { + mHwuiContext = new HwuiContext(); } + return mHwuiContext.lockCanvas(); } } @@ -415,6 +454,9 @@ public class Surface implements Parcelable { } mNativeObject = ptr; mGenerationId += 1; + if (mHwuiContext != null) { + mHwuiContext.updateSurface(); + } } } @@ -518,4 +560,59 @@ public class Surface implements Parcelable { mOrigMatrix.set(m); } } + + private final class HwuiContext { + private final RenderNode mRenderNode; + private long mHwuiRenderer; + private HardwareCanvas mCanvas; + + HwuiContext() { + mRenderNode = RenderNode.create("HwuiCanvas", null); + mRenderNode.setClipToBounds(false); + mHwuiRenderer = nHwuiCreate(mRenderNode.mNativeRenderNode, mNativeObject); + } + + Canvas lockCanvas() { + if (mCanvas != null) { + throw new IllegalStateException("Surface was already locked!"); + } + mCanvas = mRenderNode.start(0, 0); + return mCanvas; + } + + void unlockAndPost(Canvas canvas) { + if (canvas != mCanvas) { + throw new IllegalArgumentException("canvas object must be the same instance that " + + "was previously returned by lockCanvas"); + } + mRenderNode.end(mCanvas); + mCanvas = null; + nHwuiDraw(mHwuiRenderer); + } + + void updateSurface() { + nHwuiSetSurface(mHwuiRenderer, mNativeObject); + } + + void destroy() { + if (mHwuiRenderer != 0) { + nHwuiDestroy(mHwuiRenderer); + mHwuiRenderer = 0; + } + } + + @Override + protected void finalize() throws Throwable { + try { + destroy(); + } finally { + super.finalize(); + } + } + } + + private static native long nHwuiCreate(long rootNode, long surface); + private static native void nHwuiSetSurface(long renderer, long surface); + private static native void nHwuiDraw(long renderer); + private static native void nHwuiDestroy(long renderer); } |