summaryrefslogtreecommitdiffstats
path: root/core
diff options
context:
space:
mode:
Diffstat (limited to 'core')
-rw-r--r--core/java/android/view/Surface.java123
-rw-r--r--core/jni/android_view_Surface.cpp56
2 files changed, 166 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);
}
diff --git a/core/jni/android_view_Surface.cpp b/core/jni/android_view_Surface.cpp
index 9bb8195..b3d9890 100644
--- a/core/jni/android_view_Surface.cpp
+++ b/core/jni/android_view_Surface.cpp
@@ -47,6 +47,11 @@
#include <ScopedUtfChars.h>
+#include <AnimationContext.h>
+#include <DisplayListRenderer.h>
+#include <RenderNode.h>
+#include <renderthread/RenderProxy.h>
+
// ----------------------------------------------------------------------------
namespace android {
@@ -352,8 +357,53 @@ static void nativeWriteToParcel(JNIEnv* env, jclass clazz,
parcel->writeStrongBinder( self != 0 ? self->getIGraphicBufferProducer()->asBinder() : NULL);
}
+namespace uirenderer {
+
+using namespace android::uirenderer::renderthread;
+
+class ContextFactory : public IContextFactory {
+public:
+ virtual AnimationContext* createAnimationContext(renderthread::TimeLord& clock) {
+ return new AnimationContext(clock);
+ }
+};
+
+static jlong create(JNIEnv* env, jclass clazz, jlong rootNodePtr, jlong surfacePtr) {
+ RenderNode* rootNode = reinterpret_cast<RenderNode*>(rootNodePtr);
+ sp<Surface> surface(reinterpret_cast<Surface*>(surfacePtr));
+ ContextFactory factory;
+ RenderProxy* proxy = new RenderProxy(false, rootNode, &factory);
+ proxy->loadSystemProperties();
+ proxy->initialize(surface);
+ // Shadows can't be used via this interface, so just set the light source
+ // to all 0s. (and width & height are unused, TODO remove them)
+ proxy->setup(0, 0, (Vector3){0, 0, 0}, 0, 0, 0);
+ return (jlong) proxy;
+}
+
+static void setSurface(JNIEnv* env, jclass clazz, jlong rendererPtr, jlong surfacePtr) {
+ RenderProxy* proxy = reinterpret_cast<RenderProxy*>(rendererPtr);
+ sp<Surface> surface(reinterpret_cast<Surface*>(surfacePtr));
+ proxy->updateSurface(surface);
+}
+
+static void draw(JNIEnv* env, jclass clazz, jlong rendererPtr) {
+ RenderProxy* proxy = reinterpret_cast<RenderProxy*>(rendererPtr);
+ nsecs_t frameTimeNs = systemTime(CLOCK_MONOTONIC);
+ proxy->syncAndDrawFrame(frameTimeNs, 0, 1.0f);
+}
+
+static void destroy(JNIEnv* env, jclass clazz, jlong rendererPtr) {
+ RenderProxy* proxy = reinterpret_cast<RenderProxy*>(rendererPtr);
+ delete proxy;
+}
+
+} // uirenderer
+
// ----------------------------------------------------------------------------
+namespace hwui = android::uirenderer;
+
static JNINativeMethod gSurfaceMethods[] = {
{"nativeCreateFromSurfaceTexture", "(Landroid/graphics/SurfaceTexture;)J",
(void*)nativeCreateFromSurfaceTexture },
@@ -375,6 +425,12 @@ static JNINativeMethod gSurfaceMethods[] = {
(void*)nativeReadFromParcel },
{"nativeWriteToParcel", "(JLandroid/os/Parcel;)V",
(void*)nativeWriteToParcel },
+
+ // HWUI context
+ {"nHwuiCreate", "(JJ)J", (void*) hwui::create },
+ {"nHwuiSetSurface", "(JJ)V", (void*) hwui::setSurface },
+ {"nHwuiDraw", "(J)V", (void*) hwui::draw },
+ {"nHwuiDestroy", "(J)V", (void*) hwui::destroy },
};
int register_android_view_Surface(JNIEnv* env)