diff --git a/core/java/android/view/Surface.java b/core/java/android/view/Surface.java index 17ad615164a17..17f07b5a2ad40 100644 --- a/core/java/android/view/Surface.java +++ b/core/java/android/view/Surface.java @@ -23,7 +23,6 @@ import android.content.res.CompatibilityInfo.Translator; import android.graphics.Canvas; import android.graphics.ColorSpace; import android.graphics.GraphicBuffer; -import android.graphics.HardwareRenderer; import android.graphics.Matrix; import android.graphics.RecordingCanvas; import android.graphics.Rect; @@ -926,7 +925,7 @@ public class Surface implements Parcelable { private final class HwuiContext { private final RenderNode mRenderNode; - private HardwareRenderer mHardwareRenderer; + private long mHwuiRenderer; private RecordingCanvas mCanvas; private final boolean mIsWideColorGamut; @@ -935,12 +934,8 @@ public class Surface implements Parcelable { mRenderNode.setClipToBounds(false); mRenderNode.setForceDarkAllowed(false); mIsWideColorGamut = isWideColorGamut; - mHardwareRenderer = new HardwareRenderer(); - mHardwareRenderer.setSurface(Surface.this, true); - mHardwareRenderer.loadSystemProperties(); - mHardwareRenderer.setWideGamut(isWideColorGamut); - mHardwareRenderer.setLightSourceAlpha(0.0f, 0.0f); - mHardwareRenderer.setLightSourceGeometry(0.0f, 0.0f, 0.0f, 0.0f); + mHwuiRenderer = nHwuiCreate(mRenderNode.mNativeRenderNode, mNativeObject, + isWideColorGamut); } Canvas lockCanvas(int width, int height) { @@ -958,20 +953,27 @@ public class Surface implements Parcelable { } mRenderNode.endRecording(); mCanvas = null; - mHardwareRenderer.drawRenderNode(mRenderNode); - // TODO unable to set FrameInfoFlags::SurfaceCanvas on the draw + nHwuiDraw(mHwuiRenderer); } void updateSurface() { - mHardwareRenderer.setSurface(Surface.this); + nHwuiSetSurface(mHwuiRenderer, mNativeObject); } void destroy() { - mHardwareRenderer.destroy(); + if (mHwuiRenderer != 0) { + nHwuiDestroy(mHwuiRenderer); + mHwuiRenderer = 0; + } } boolean isWideColorGamut() { return mIsWideColorGamut; } } + + private static native long nHwuiCreate(long rootNode, long surface, boolean isWideColorGamut); + 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 78fb2ab9b228c..058a4c8ee2f98 100644 --- a/core/jni/android_view_Surface.cpp +++ b/core/jni/android_view_Surface.cpp @@ -45,6 +45,11 @@ #include +#include +#include +#include +#include + // ---------------------------------------------------------------------------- namespace android { @@ -184,6 +189,21 @@ static jboolean nativeIsConsumerRunningBehind(JNIEnv* env, jclass clazz, jlong n return value; } +static inline SkColorType convertPixelFormat(PixelFormat format) { + /* note: if PIXEL_FORMAT_RGBX_8888 means that all alpha bytes are 0xFF, then + we can map to kN32_SkColorType, and optionally call + bitmap.setAlphaType(kOpaque_SkAlphaType) on the resulting SkBitmap + (as an accelerator) + */ + switch (format) { + case PIXEL_FORMAT_RGBX_8888: return kN32_SkColorType; + case PIXEL_FORMAT_RGBA_8888: return kN32_SkColorType; + case PIXEL_FORMAT_RGBA_FP16: return kRGBA_F16_SkColorType; + case PIXEL_FORMAT_RGB_565: return kRGB_565_SkColorType; + default: return kUnknown_SkColorType; + } +} + static jlong nativeLockCanvas(JNIEnv* env, jclass clazz, jlong nativeObject, jobject canvasObj, jobject dirtyRectObj) { sp surface(reinterpret_cast(nativeObject)); @@ -193,7 +213,7 @@ static jlong nativeLockCanvas(JNIEnv* env, jclass clazz, return 0; } - if (ACanvas_isSupportedPixelFormat(ANativeWindow_getFormat(surface.get()))) { + if (convertPixelFormat(ANativeWindow_getFormat(surface.get())) == kUnknown_SkColorType) { native_window_set_buffers_format(surface.get(), PIXEL_FORMAT_RGBA_8888); } @@ -413,8 +433,62 @@ static jint nativeSetAutoRefreshEnabled(JNIEnv* env, jclass clazz, jlong nativeO return anw->perform(surface, NATIVE_WINDOW_SET_AUTO_REFRESH, int(enabled)); } +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, + jboolean isWideColorGamut) { + RenderNode* rootNode = reinterpret_cast(rootNodePtr); + sp surface(reinterpret_cast(surfacePtr)); + ContextFactory factory; + RenderProxy* proxy = new RenderProxy(false, rootNode, &factory); + proxy->loadSystemProperties(); + if (isWideColorGamut) { + proxy->setWideGamut(true); + } + proxy->setSwapBehavior(SwapBehavior::kSwap_discardBuffer); + proxy->setSurface(surface); + // Shadows can't be used via this interface, so just set the light source + // to all 0s. + proxy->setLightAlpha(0, 0); + proxy->setLightGeometry((Vector3){0, 0, 0}, 0); + return (jlong) proxy; +} + +static void setSurface(JNIEnv* env, jclass clazz, jlong rendererPtr, jlong surfacePtr) { + RenderProxy* proxy = reinterpret_cast(rendererPtr); + sp surface(reinterpret_cast(surfacePtr)); + proxy->setSurface(surface); +} + +static void draw(JNIEnv* env, jclass clazz, jlong rendererPtr) { + RenderProxy* proxy = reinterpret_cast(rendererPtr); + nsecs_t vsync = systemTime(SYSTEM_TIME_MONOTONIC); + UiFrameInfoBuilder(proxy->frameInfo()) + .setVsync(vsync, vsync) + .addFlag(FrameInfoFlags::SurfaceCanvas); + proxy->syncAndDrawFrame(); +} + +static void destroy(JNIEnv* env, jclass clazz, jlong rendererPtr) { + RenderProxy* proxy = reinterpret_cast(rendererPtr); + delete proxy; +} + +} // uirenderer + // ---------------------------------------------------------------------------- +namespace hwui = android::uirenderer; + static const JNINativeMethod gSurfaceMethods[] = { {"nativeCreateFromSurfaceTexture", "(Landroid/graphics/SurfaceTexture;)J", (void*)nativeCreateFromSurfaceTexture }, @@ -447,6 +521,12 @@ static const JNINativeMethod gSurfaceMethods[] = { (void*)nativeAttachAndQueueBufferWithColorSpace}, {"nativeSetSharedBufferModeEnabled", "(JZ)I", (void*)nativeSetSharedBufferModeEnabled}, {"nativeSetAutoRefreshEnabled", "(JZ)I", (void*)nativeSetAutoRefreshEnabled}, + + // HWUI context + {"nHwuiCreate", "(JJZ)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) diff --git a/core/jni/android_view_ThreadedRenderer.cpp b/core/jni/android_view_ThreadedRenderer.cpp index 1552cebaff471..dd3a4d0c56999 100644 --- a/core/jni/android_view_ThreadedRenderer.cpp +++ b/core/jni/android_view_ThreadedRenderer.cpp @@ -174,15 +174,12 @@ static void android_view_ThreadedRenderer_setName(JNIEnv* env, jobject clazz, } static void android_view_ThreadedRenderer_setSurface(JNIEnv* env, jobject clazz, - jlong proxyPtr, jobject jsurface, jboolean discardBuffer) { + jlong proxyPtr, jobject jsurface) { RenderProxy* proxy = reinterpret_cast(proxyPtr); sp surface; if (jsurface) { surface = android_view_Surface_getSurface(env, jsurface); } - if (discardBuffer) { - proxy->setSwapBehavior(SwapBehavior::kSwap_discardBuffer); - } proxy->setSurface(surface); } @@ -635,7 +632,7 @@ static const JNINativeMethod gMethods[] = { { "nDeleteProxy", "(J)V", (void*) android_view_ThreadedRenderer_deleteProxy }, { "nLoadSystemProperties", "(J)Z", (void*) android_view_ThreadedRenderer_loadSystemProperties }, { "nSetName", "(JLjava/lang/String;)V", (void*) android_view_ThreadedRenderer_setName }, - { "nSetSurface", "(JLandroid/view/Surface;Z)V", (void*) android_view_ThreadedRenderer_setSurface }, + { "nSetSurface", "(JLandroid/view/Surface;)V", (void*) android_view_ThreadedRenderer_setSurface }, { "nPause", "(J)Z", (void*) android_view_ThreadedRenderer_pause }, { "nSetStopped", "(JZ)V", (void*) android_view_ThreadedRenderer_setStopped }, { "nSetLightAlpha", "(JFF)V", (void*) android_view_ThreadedRenderer_setLightAlpha }, diff --git a/graphics/java/android/graphics/HardwareRenderer.java b/graphics/java/android/graphics/HardwareRenderer.java index 3f3ad578e8d77..b6b2d4e1c46a7 100644 --- a/graphics/java/android/graphics/HardwareRenderer.java +++ b/graphics/java/android/graphics/HardwareRenderer.java @@ -286,24 +286,10 @@ public class HardwareRenderer { * non-null then {@link Surface#isValid()} must be true. */ public void setSurface(@Nullable Surface surface) { - setSurface(surface, false); - } - - /** - * See {@link #setSurface(Surface)} - * - * @hide - * @param discardBuffer determines whether the surface will attempt to preserve its contents - * between frames. If set to true the renderer will attempt to preserve - * the contents of the buffer between frames if the implementation allows - * it. If set to false no attempt will be made to preserve the buffer's - * contents between frames. - */ - public void setSurface(@Nullable Surface surface, boolean discardBuffer) { if (surface != null && !surface.isValid()) { throw new IllegalArgumentException("Surface is invalid. surface.isValid() == false."); } - nSetSurface(mNativeProxy, surface, discardBuffer); + nSetSurface(mNativeProxy, surface); } /** @@ -1098,7 +1084,7 @@ public class HardwareRenderer { private static native void nSetName(long nativeProxy, String name); - private static native void nSetSurface(long nativeProxy, Surface window, boolean discardBuffer); + private static native void nSetSurface(long nativeProxy, Surface window); private static native boolean nPause(long nativeProxy);