From 86bd214059cd6150304888a285941bf74af5b687 Mon Sep 17 00:00:00 2001 From: Fedor Kudasov Date: Tue, 18 Jun 2019 15:51:57 +0100 Subject: [PATCH] Enable RenderNode and RecordingCanvas for layoutlib Bug: 117921091 Test: all tests should pass Change-Id: I574b12a5f7a6a54cbbcb17c35a3884368fd404e6 --- core/jni/Android.bp | 4 +- core/jni/LayoutlibLoader.cpp | 4 + core/jni/android_view_DisplayListCanvas.cpp | 34 +- core/jni/android_view_RenderNode.cpp | 167 +++---- libs/hwui/Android.bp | 31 +- libs/hwui/RenderNode.cpp | 7 + libs/hwui/RenderProperties.h | 4 + libs/hwui/hwui/Canvas.cpp | 4 - libs/hwui/pipeline/skia/SkiaDisplayList.cpp | 10 + .../pipeline/skia/SkiaRecordingCanvas.cpp | 12 + libs/hwui/utils/HostColorSpace.cpp | 417 ++++++++++++++++++ 11 files changed, 584 insertions(+), 110 deletions(-) create mode 100644 libs/hwui/utils/HostColorSpace.cpp diff --git a/core/jni/Android.bp b/core/jni/Android.bp index d6f5c23a63d24..640b8f9603bf2 100644 --- a/core/jni/Android.bp +++ b/core/jni/Android.bp @@ -40,6 +40,8 @@ cc_library_shared { "android_graphics_Picture.cpp", "android_nio_utils.cpp", "android_util_PathParser.cpp", + "android_view_DisplayListCanvas.cpp", + "android_view_RenderNode.cpp", "android/graphics/Bitmap.cpp", "android/graphics/BitmapFactory.cpp", "android/graphics/ByteBufferStreamAdaptor.cpp", @@ -136,7 +138,6 @@ cc_library_shared { "android_database_SQLiteDebug.cpp", "android_view_CompositionSamplingListener.cpp", "android_view_DisplayEventReceiver.cpp", - "android_view_DisplayListCanvas.cpp", "android_view_TextureLayer.cpp", "android_view_InputChannel.cpp", "android_view_InputDevice.cpp", @@ -147,7 +148,6 @@ cc_library_shared { "android_view_KeyEvent.cpp", "android_view_MotionEvent.cpp", "android_view_PointerIcon.cpp", - "android_view_RenderNode.cpp", "android_view_RenderNodeAnimator.cpp", "android_view_Surface.cpp", "android_view_SurfaceControl.cpp", diff --git a/core/jni/LayoutlibLoader.cpp b/core/jni/LayoutlibLoader.cpp index b17280908e81f..dd5113cb96add 100644 --- a/core/jni/LayoutlibLoader.cpp +++ b/core/jni/LayoutlibLoader.cpp @@ -67,6 +67,8 @@ extern int register_android_graphics_fonts_FontFamily(JNIEnv* env); extern int register_android_graphics_text_LineBreaker(JNIEnv* env); extern int register_android_graphics_text_MeasuredText(JNIEnv* env); extern int register_android_util_PathParser(JNIEnv* env); +extern int register_android_view_RenderNode(JNIEnv* env); +extern int register_android_view_DisplayListCanvas(JNIEnv* env); extern int register_com_android_internal_util_VirtualRefBasePtr(JNIEnv *env); extern int register_com_android_internal_view_animation_NativeInterpolatorFactoryHelper(JNIEnv *env); @@ -83,6 +85,7 @@ static const std::unordered_map gRegJNIMap = { {"android.graphics.BitmapFactory", REG_JNI(register_android_graphics_BitmapFactory)}, {"android.graphics.ByteBufferStreamAdaptor", REG_JNI(register_android_graphics_ByteBufferStreamAdaptor)}, {"android.graphics.Canvas", REG_JNI(register_android_graphics_Canvas)}, + {"android.graphics.RenderNode", REG_JNI(register_android_view_RenderNode)}, {"android.graphics.ColorFilter", REG_JNI(register_android_graphics_ColorFilter)}, {"android.graphics.ColorSpace", REG_JNI(register_android_graphics_ColorSpace)}, {"android.graphics.CreateJavaOutputStreamAdaptor", REG_JNI(register_android_graphics_CreateJavaOutputStreamAdaptor)}, @@ -98,6 +101,7 @@ static const std::unordered_map gRegJNIMap = { {"android.graphics.PathEffect", REG_JNI(register_android_graphics_PathEffect)}, {"android.graphics.PathMeasure", REG_JNI(register_android_graphics_PathMeasure)}, {"android.graphics.Picture", REG_JNI(register_android_graphics_Picture)}, + {"android.graphics.RecordingCanvas", REG_JNI(register_android_view_DisplayListCanvas)}, {"android.graphics.Region", REG_JNI(register_android_graphics_Region)}, {"android.graphics.Shader", REG_JNI(register_android_graphics_Shader)}, {"android.graphics.Typeface", REG_JNI(register_android_graphics_Typeface)}, diff --git a/core/jni/android_view_DisplayListCanvas.cpp b/core/jni/android_view_DisplayListCanvas.cpp index 40a133b9383b4..9907da5a2e68b 100644 --- a/core/jni/android_view_DisplayListCanvas.cpp +++ b/core/jni/android_view_DisplayListCanvas.cpp @@ -21,9 +21,9 @@ #include #include - +#ifdef __ANDROID__ // Layoutlib does not support Looper and device properties #include -#include +#endif #include #include @@ -34,7 +34,9 @@ #include #include #include +#ifdef __ANDROID__ // Layoutlib does not support RenderThread #include +#endif #include "core_jni_helpers.h" @@ -52,6 +54,7 @@ static JNIEnv* jnienv(JavaVM* vm) { return env; } +#ifdef __ANDROID__ // Layoutlib does not support GL, Looper class InvokeRunnableMessage : public MessageHandler { public: InvokeRunnableMessage(JNIEnv* env, jobject runnable) { @@ -87,11 +90,13 @@ private: sp mLooper; sp mMessage; }; +#endif // ---------------- @FastNative ----------------------------- static void android_view_DisplayListCanvas_callDrawGLFunction(JNIEnv* env, jobject clazz, jlong canvasPtr, jlong functorPtr, jobject releasedCallback) { +#ifdef __ANDROID__ // Layoutlib does not support GL Canvas* canvas = reinterpret_cast(canvasPtr); Functor* functor = reinterpret_cast(functorPtr); sp bridge; @@ -99,52 +104,57 @@ static void android_view_DisplayListCanvas_callDrawGLFunction(JNIEnv* env, jobje bridge = new GlFunctorReleasedCallbackBridge(env, releasedCallback); } canvas->callDrawGLFunction(functor, bridge.get()); +#endif } // ---------------- @CriticalNative ------------------------- -static jlong android_view_DisplayListCanvas_createDisplayListCanvas(jlong renderNodePtr, +static jlong android_view_DisplayListCanvas_createDisplayListCanvas(CRITICAL_JNI_PARAMS_COMMA jlong renderNodePtr, jint width, jint height) { RenderNode* renderNode = reinterpret_cast(renderNodePtr); return reinterpret_cast(Canvas::create_recording_canvas(width, height, renderNode)); } -static void android_view_DisplayListCanvas_resetDisplayListCanvas(jlong canvasPtr, +static void android_view_DisplayListCanvas_resetDisplayListCanvas(CRITICAL_JNI_PARAMS_COMMA jlong canvasPtr, jlong renderNodePtr, jint width, jint height) { Canvas* canvas = reinterpret_cast(canvasPtr); RenderNode* renderNode = reinterpret_cast(renderNodePtr); canvas->resetRecording(width, height, renderNode); } -static jint android_view_DisplayListCanvas_getMaxTextureSize() { +static jint android_view_DisplayListCanvas_getMaxTextureSize(CRITICAL_JNI_PARAMS) { +#ifdef __ANDROID__ // Layoutlib does not support RenderProxy (RenderThread) return android::uirenderer::renderthread::RenderProxy::maxTextureSize(); +#else + return 4096; +#endif } -static void android_view_DisplayListCanvas_insertReorderBarrier(jlong canvasPtr, +static void android_view_DisplayListCanvas_insertReorderBarrier(CRITICAL_JNI_PARAMS_COMMA jlong canvasPtr, jboolean reorderEnable) { Canvas* canvas = reinterpret_cast(canvasPtr); canvas->insertReorderBarrier(reorderEnable); } -static jlong android_view_DisplayListCanvas_finishRecording(jlong canvasPtr) { +static jlong android_view_DisplayListCanvas_finishRecording(CRITICAL_JNI_PARAMS_COMMA jlong canvasPtr) { Canvas* canvas = reinterpret_cast(canvasPtr); return reinterpret_cast(canvas->finishRecording()); } -static void android_view_DisplayListCanvas_drawRenderNode(jlong canvasPtr, jlong renderNodePtr) { +static void android_view_DisplayListCanvas_drawRenderNode(CRITICAL_JNI_PARAMS_COMMA jlong canvasPtr, jlong renderNodePtr) { Canvas* canvas = reinterpret_cast(canvasPtr); RenderNode* renderNode = reinterpret_cast(renderNodePtr); canvas->drawRenderNode(renderNode); } -static void android_view_DisplayListCanvas_drawTextureLayer(jlong canvasPtr, jlong layerPtr) { +static void android_view_DisplayListCanvas_drawTextureLayer(CRITICAL_JNI_PARAMS_COMMA jlong canvasPtr, jlong layerPtr) { Canvas* canvas = reinterpret_cast(canvasPtr); DeferredLayerUpdater* layer = reinterpret_cast(layerPtr); canvas->drawLayer(layer); } -static void android_view_DisplayListCanvas_drawRoundRectProps(jlong canvasPtr, +static void android_view_DisplayListCanvas_drawRoundRectProps(CRITICAL_JNI_PARAMS_COMMA jlong canvasPtr, jlong leftPropPtr, jlong topPropPtr, jlong rightPropPtr, jlong bottomPropPtr, jlong rxPropPtr, jlong ryPropPtr, jlong paintPropPtr) { Canvas* canvas = reinterpret_cast(canvasPtr); @@ -158,7 +168,7 @@ static void android_view_DisplayListCanvas_drawRoundRectProps(jlong canvasPtr, canvas->drawRoundRect(leftProp, topProp, rightProp, bottomProp, rxProp, ryProp, paintProp); } -static void android_view_DisplayListCanvas_drawCircleProps(jlong canvasPtr, +static void android_view_DisplayListCanvas_drawCircleProps(CRITICAL_JNI_PARAMS_COMMA jlong canvasPtr, jlong xPropPtr, jlong yPropPtr, jlong radiusPropPtr, jlong paintPropPtr) { Canvas* canvas = reinterpret_cast(canvasPtr); CanvasPropertyPrimitive* xProp = reinterpret_cast(xPropPtr); @@ -168,7 +178,7 @@ static void android_view_DisplayListCanvas_drawCircleProps(jlong canvasPtr, canvas->drawCircle(xProp, yProp, radiusProp, paintProp); } -static void android_view_DisplayListCanvas_drawWebViewFunctor(jlong canvasPtr, jint functor) { +static void android_view_DisplayListCanvas_drawWebViewFunctor(CRITICAL_JNI_PARAMS_COMMA jlong canvasPtr, jint functor) { Canvas* canvas = reinterpret_cast(canvasPtr); canvas->drawWebViewFunctor(functor); } diff --git a/core/jni/android_view_RenderNode.cpp b/core/jni/android_view_RenderNode.cpp index 43c0bbecd71cf..9450bc95ac946 100644 --- a/core/jni/android_view_RenderNode.cpp +++ b/core/jni/android_view_RenderNode.cpp @@ -16,9 +16,9 @@ #define LOG_TAG "OpenGLRenderer" #define ATRACE_TAG ATRACE_TAG_VIEW - +#ifdef __ANDROID__ // Layoutlib does not support EGL #include - +#endif #include "jni.h" #include "GraphicsJNI.h" #include @@ -28,7 +28,9 @@ #include #include #include +#ifdef __ANDROID__ // Layoutlib does not support CanvasContext #include +#endif #include #include #include @@ -85,7 +87,7 @@ static void android_view_RenderNode_setDisplayList(JNIEnv* env, renderNode->setStagingDisplayList(newData); } -static jboolean android_view_RenderNode_isValid(jlong renderNodePtr) { +static jboolean android_view_RenderNode_isValid(CRITICAL_JNI_PARAMS_COMMA jlong renderNodePtr) { return reinterpret_cast(renderNodePtr)->isValid(); } @@ -93,52 +95,52 @@ static jboolean android_view_RenderNode_isValid(jlong renderNodePtr) { // RenderProperties - setters // ---------------------------------------------------------------------------- -static jboolean android_view_RenderNode_setLayerType(jlong renderNodePtr, jint jlayerType) { +static jboolean android_view_RenderNode_setLayerType(CRITICAL_JNI_PARAMS_COMMA jlong renderNodePtr, jint jlayerType) { LayerType layerType = static_cast(jlayerType); return SET_AND_DIRTY(mutateLayerProperties().setType, layerType, RenderNode::GENERIC); } -static jboolean android_view_RenderNode_setLayerPaint(jlong renderNodePtr, jlong paintPtr) { +static jboolean android_view_RenderNode_setLayerPaint(CRITICAL_JNI_PARAMS_COMMA jlong renderNodePtr, jlong paintPtr) { Paint* paint = reinterpret_cast(paintPtr); return SET_AND_DIRTY(mutateLayerProperties().setFromPaint, paint, RenderNode::GENERIC); } -static jboolean android_view_RenderNode_setStaticMatrix(jlong renderNodePtr, jlong matrixPtr) { +static jboolean android_view_RenderNode_setStaticMatrix(CRITICAL_JNI_PARAMS_COMMA jlong renderNodePtr, jlong matrixPtr) { SkMatrix* matrix = reinterpret_cast(matrixPtr); return SET_AND_DIRTY(setStaticMatrix, matrix, RenderNode::GENERIC); } -static jboolean android_view_RenderNode_setAnimationMatrix(jlong renderNodePtr, jlong matrixPtr) { +static jboolean android_view_RenderNode_setAnimationMatrix(CRITICAL_JNI_PARAMS_COMMA jlong renderNodePtr, jlong matrixPtr) { SkMatrix* matrix = reinterpret_cast(matrixPtr); return SET_AND_DIRTY(setAnimationMatrix, matrix, RenderNode::GENERIC); } -static jboolean android_view_RenderNode_setClipToBounds(jlong renderNodePtr, +static jboolean android_view_RenderNode_setClipToBounds(CRITICAL_JNI_PARAMS_COMMA jlong renderNodePtr, jboolean clipToBounds) { return SET_AND_DIRTY(setClipToBounds, clipToBounds, RenderNode::GENERIC); } -static jboolean android_view_RenderNode_setClipBounds(jlong renderNodePtr, +static jboolean android_view_RenderNode_setClipBounds(CRITICAL_JNI_PARAMS_COMMA jlong renderNodePtr, jint left, jint top, jint right, jint bottom) { android::uirenderer::Rect clipBounds(left, top, right, bottom); return SET_AND_DIRTY(setClipBounds, clipBounds, RenderNode::GENERIC); } -static jboolean android_view_RenderNode_setClipBoundsEmpty(jlong renderNodePtr) { +static jboolean android_view_RenderNode_setClipBoundsEmpty(CRITICAL_JNI_PARAMS_COMMA jlong renderNodePtr) { return SET_AND_DIRTY(setClipBoundsEmpty,, RenderNode::GENERIC); } -static jboolean android_view_RenderNode_setProjectBackwards(jlong renderNodePtr, +static jboolean android_view_RenderNode_setProjectBackwards(CRITICAL_JNI_PARAMS_COMMA jlong renderNodePtr, jboolean shouldProject) { return SET_AND_DIRTY(setProjectBackwards, shouldProject, RenderNode::GENERIC); } -static jboolean android_view_RenderNode_setProjectionReceiver(jlong renderNodePtr, +static jboolean android_view_RenderNode_setProjectionReceiver(CRITICAL_JNI_PARAMS_COMMA jlong renderNodePtr, jboolean shouldRecieve) { return SET_AND_DIRTY(setProjectionReceiver, shouldRecieve, RenderNode::GENERIC); } -static jboolean android_view_RenderNode_setOutlineRoundRect(jlong renderNodePtr, +static jboolean android_view_RenderNode_setOutlineRoundRect(CRITICAL_JNI_PARAMS_COMMA jlong renderNodePtr, jint left, jint top, jint right, jint bottom, jfloat radius, jfloat alpha) { RenderNode* renderNode = reinterpret_cast(renderNodePtr); renderNode->mutateStagingProperties().mutableOutline().setRoundRect(left, top, right, bottom, @@ -147,7 +149,7 @@ static jboolean android_view_RenderNode_setOutlineRoundRect(jlong renderNodePtr, return true; } -static jboolean android_view_RenderNode_setOutlineConvexPath(jlong renderNodePtr, +static jboolean android_view_RenderNode_setOutlineConvexPath(CRITICAL_JNI_PARAMS_COMMA jlong renderNodePtr, jlong outlinePathPtr, jfloat alpha) { RenderNode* renderNode = reinterpret_cast(renderNodePtr); SkPath* outlinePath = reinterpret_cast(outlinePathPtr); @@ -156,47 +158,47 @@ static jboolean android_view_RenderNode_setOutlineConvexPath(jlong renderNodePtr return true; } -static jboolean android_view_RenderNode_setOutlineEmpty(jlong renderNodePtr) { +static jboolean android_view_RenderNode_setOutlineEmpty(CRITICAL_JNI_PARAMS_COMMA jlong renderNodePtr) { RenderNode* renderNode = reinterpret_cast(renderNodePtr); renderNode->mutateStagingProperties().mutableOutline().setEmpty(); renderNode->setPropertyFieldsDirty(RenderNode::GENERIC); return true; } -static jboolean android_view_RenderNode_setOutlineNone(jlong renderNodePtr) { +static jboolean android_view_RenderNode_setOutlineNone(CRITICAL_JNI_PARAMS_COMMA jlong renderNodePtr) { RenderNode* renderNode = reinterpret_cast(renderNodePtr); renderNode->mutateStagingProperties().mutableOutline().setNone(); renderNode->setPropertyFieldsDirty(RenderNode::GENERIC); return true; } -static jboolean android_view_RenderNode_hasShadow(jlong renderNodePtr) { +static jboolean android_view_RenderNode_hasShadow(CRITICAL_JNI_PARAMS_COMMA jlong renderNodePtr) { RenderNode* renderNode = reinterpret_cast(renderNodePtr); return renderNode->stagingProperties().hasShadow(); } -static jboolean android_view_RenderNode_setSpotShadowColor(jlong renderNodePtr, jint shadowColor) { +static jboolean android_view_RenderNode_setSpotShadowColor(CRITICAL_JNI_PARAMS_COMMA jlong renderNodePtr, jint shadowColor) { return SET_AND_DIRTY(setSpotShadowColor, static_cast(shadowColor), RenderNode::GENERIC); } -static jint android_view_RenderNode_getSpotShadowColor(jlong renderNodePtr) { +static jint android_view_RenderNode_getSpotShadowColor(CRITICAL_JNI_PARAMS_COMMA jlong renderNodePtr) { RenderNode* renderNode = reinterpret_cast(renderNodePtr); return renderNode->stagingProperties().getSpotShadowColor(); } -static jboolean android_view_RenderNode_setAmbientShadowColor(jlong renderNodePtr, +static jboolean android_view_RenderNode_setAmbientShadowColor(CRITICAL_JNI_PARAMS_COMMA jlong renderNodePtr, jint shadowColor) { return SET_AND_DIRTY(setAmbientShadowColor, static_cast(shadowColor), RenderNode::GENERIC); } -static jint android_view_RenderNode_getAmbientShadowColor(jlong renderNodePtr) { +static jint android_view_RenderNode_getAmbientShadowColor(CRITICAL_JNI_PARAMS_COMMA jlong renderNodePtr) { RenderNode* renderNode = reinterpret_cast(renderNodePtr); return renderNode->stagingProperties().getAmbientShadowColor(); } -static jboolean android_view_RenderNode_setClipToOutline(jlong renderNodePtr, +static jboolean android_view_RenderNode_setClipToOutline(CRITICAL_JNI_PARAMS_COMMA jlong renderNodePtr, jboolean clipToOutline) { RenderNode* renderNode = reinterpret_cast(renderNodePtr); renderNode->mutateStagingProperties().mutableOutline().setShouldClip(clipToOutline); @@ -204,7 +206,7 @@ static jboolean android_view_RenderNode_setClipToOutline(jlong renderNodePtr, return true; } -static jboolean android_view_RenderNode_setRevealClip(jlong renderNodePtr, jboolean shouldClip, +static jboolean android_view_RenderNode_setRevealClip(CRITICAL_JNI_PARAMS_COMMA jlong renderNodePtr, jboolean shouldClip, jfloat x, jfloat y, jfloat radius) { RenderNode* renderNode = reinterpret_cast(renderNodePtr); renderNode->mutateStagingProperties().mutableRevealClip().set( @@ -213,106 +215,106 @@ static jboolean android_view_RenderNode_setRevealClip(jlong renderNodePtr, jbool return true; } -static jboolean android_view_RenderNode_setAlpha(jlong renderNodePtr, float alpha) { +static jboolean android_view_RenderNode_setAlpha(CRITICAL_JNI_PARAMS_COMMA jlong renderNodePtr, float alpha) { return SET_AND_DIRTY(setAlpha, alpha, RenderNode::ALPHA); } -static jboolean android_view_RenderNode_setHasOverlappingRendering(jlong renderNodePtr, +static jboolean android_view_RenderNode_setHasOverlappingRendering(CRITICAL_JNI_PARAMS_COMMA jlong renderNodePtr, bool hasOverlappingRendering) { return SET_AND_DIRTY(setHasOverlappingRendering, hasOverlappingRendering, RenderNode::GENERIC); } -static void android_view_RenderNode_setUsageHint(jlong renderNodePtr, jint usageHint) { +static void android_view_RenderNode_setUsageHint(CRITICAL_JNI_PARAMS_COMMA jlong renderNodePtr, jint usageHint) { RenderNode* renderNode = reinterpret_cast(renderNodePtr); renderNode->setUsageHint(static_cast(usageHint)); } -static jboolean android_view_RenderNode_setElevation(jlong renderNodePtr, float elevation) { +static jboolean android_view_RenderNode_setElevation(CRITICAL_JNI_PARAMS_COMMA jlong renderNodePtr, float elevation) { return SET_AND_DIRTY(setElevation, elevation, RenderNode::Z); } -static jboolean android_view_RenderNode_setTranslationX(jlong renderNodePtr, float tx) { +static jboolean android_view_RenderNode_setTranslationX(CRITICAL_JNI_PARAMS_COMMA jlong renderNodePtr, float tx) { return SET_AND_DIRTY(setTranslationX, tx, RenderNode::TRANSLATION_X | RenderNode::X); } -static jboolean android_view_RenderNode_setTranslationY(jlong renderNodePtr, float ty) { +static jboolean android_view_RenderNode_setTranslationY(CRITICAL_JNI_PARAMS_COMMA jlong renderNodePtr, float ty) { return SET_AND_DIRTY(setTranslationY, ty, RenderNode::TRANSLATION_Y | RenderNode::Y); } -static jboolean android_view_RenderNode_setTranslationZ(jlong renderNodePtr, float tz) { +static jboolean android_view_RenderNode_setTranslationZ(CRITICAL_JNI_PARAMS_COMMA jlong renderNodePtr, float tz) { return SET_AND_DIRTY(setTranslationZ, tz, RenderNode::TRANSLATION_Z | RenderNode::Z); } -static jboolean android_view_RenderNode_setRotation(jlong renderNodePtr, float rotation) { +static jboolean android_view_RenderNode_setRotation(CRITICAL_JNI_PARAMS_COMMA jlong renderNodePtr, float rotation) { return SET_AND_DIRTY(setRotation, rotation, RenderNode::ROTATION); } -static jboolean android_view_RenderNode_setRotationX(jlong renderNodePtr, float rx) { +static jboolean android_view_RenderNode_setRotationX(CRITICAL_JNI_PARAMS_COMMA jlong renderNodePtr, float rx) { return SET_AND_DIRTY(setRotationX, rx, RenderNode::ROTATION_X); } -static jboolean android_view_RenderNode_setRotationY(jlong renderNodePtr, float ry) { +static jboolean android_view_RenderNode_setRotationY(CRITICAL_JNI_PARAMS_COMMA jlong renderNodePtr, float ry) { return SET_AND_DIRTY(setRotationY, ry, RenderNode::ROTATION_Y); } -static jboolean android_view_RenderNode_setScaleX(jlong renderNodePtr, float sx) { +static jboolean android_view_RenderNode_setScaleX(CRITICAL_JNI_PARAMS_COMMA jlong renderNodePtr, float sx) { return SET_AND_DIRTY(setScaleX, sx, RenderNode::SCALE_X); } -static jboolean android_view_RenderNode_setScaleY(jlong renderNodePtr, float sy) { +static jboolean android_view_RenderNode_setScaleY(CRITICAL_JNI_PARAMS_COMMA jlong renderNodePtr, float sy) { return SET_AND_DIRTY(setScaleY, sy, RenderNode::SCALE_Y); } -static jboolean android_view_RenderNode_setPivotX(jlong renderNodePtr, float px) { +static jboolean android_view_RenderNode_setPivotX(CRITICAL_JNI_PARAMS_COMMA jlong renderNodePtr, float px) { return SET_AND_DIRTY(setPivotX, px, RenderNode::GENERIC); } -static jboolean android_view_RenderNode_setPivotY(jlong renderNodePtr, float py) { +static jboolean android_view_RenderNode_setPivotY(CRITICAL_JNI_PARAMS_COMMA jlong renderNodePtr, float py) { return SET_AND_DIRTY(setPivotY, py, RenderNode::GENERIC); } -static jboolean android_view_RenderNode_resetPivot(jlong renderNodePtr) { +static jboolean android_view_RenderNode_resetPivot(CRITICAL_JNI_PARAMS_COMMA jlong renderNodePtr) { return SET_AND_DIRTY(resetPivot, /* void */, RenderNode::GENERIC); } -static jboolean android_view_RenderNode_setCameraDistance(jlong renderNodePtr, float distance) { +static jboolean android_view_RenderNode_setCameraDistance(CRITICAL_JNI_PARAMS_COMMA jlong renderNodePtr, float distance) { return SET_AND_DIRTY(setCameraDistance, distance, RenderNode::GENERIC); } -static jboolean android_view_RenderNode_setLeft(jlong renderNodePtr, int left) { +static jboolean android_view_RenderNode_setLeft(CRITICAL_JNI_PARAMS_COMMA jlong renderNodePtr, int left) { return SET_AND_DIRTY(setLeft, left, RenderNode::X); } -static jboolean android_view_RenderNode_setTop(jlong renderNodePtr, int top) { +static jboolean android_view_RenderNode_setTop(CRITICAL_JNI_PARAMS_COMMA jlong renderNodePtr, int top) { return SET_AND_DIRTY(setTop, top, RenderNode::Y); } -static jboolean android_view_RenderNode_setRight(jlong renderNodePtr, int right) { +static jboolean android_view_RenderNode_setRight(CRITICAL_JNI_PARAMS_COMMA jlong renderNodePtr, int right) { return SET_AND_DIRTY(setRight, right, RenderNode::X); } -static jboolean android_view_RenderNode_setBottom(jlong renderNodePtr, int bottom) { +static jboolean android_view_RenderNode_setBottom(CRITICAL_JNI_PARAMS_COMMA jlong renderNodePtr, int bottom) { return SET_AND_DIRTY(setBottom, bottom, RenderNode::Y); } -static jint android_view_RenderNode_getLeft(jlong renderNodePtr) { +static jint android_view_RenderNode_getLeft(CRITICAL_JNI_PARAMS_COMMA jlong renderNodePtr) { return reinterpret_cast(renderNodePtr)->stagingProperties().getLeft(); } -static jint android_view_RenderNode_getTop(jlong renderNodePtr) { +static jint android_view_RenderNode_getTop(CRITICAL_JNI_PARAMS_COMMA jlong renderNodePtr) { return reinterpret_cast(renderNodePtr)->stagingProperties().getTop(); } -static jint android_view_RenderNode_getRight(jlong renderNodePtr) { +static jint android_view_RenderNode_getRight(CRITICAL_JNI_PARAMS_COMMA jlong renderNodePtr) { return reinterpret_cast(renderNodePtr)->stagingProperties().getRight(); } -static jint android_view_RenderNode_getBottom(jlong renderNodePtr) { +static jint android_view_RenderNode_getBottom(CRITICAL_JNI_PARAMS_COMMA jlong renderNodePtr) { return reinterpret_cast(renderNodePtr)->stagingProperties().getBottom(); } -static jboolean android_view_RenderNode_setLeftTopRightBottom(jlong renderNodePtr, +static jboolean android_view_RenderNode_setLeftTopRightBottom(CRITICAL_JNI_PARAMS_COMMA jlong renderNodePtr, int left, int top, int right, int bottom) { RenderNode* renderNode = reinterpret_cast(renderNodePtr); if (renderNode->mutateStagingProperties().setLeftTopRightBottom(left, top, right, bottom)) { @@ -322,11 +324,11 @@ static jboolean android_view_RenderNode_setLeftTopRightBottom(jlong renderNodePt return false; } -static jboolean android_view_RenderNode_offsetLeftAndRight(jlong renderNodePtr, jint offset) { +static jboolean android_view_RenderNode_offsetLeftAndRight(CRITICAL_JNI_PARAMS_COMMA jlong renderNodePtr, jint offset) { return SET_AND_DIRTY(offsetLeftRight, offset, RenderNode::X); } -static jboolean android_view_RenderNode_offsetTopAndBottom(jlong renderNodePtr, jint offset) { +static jboolean android_view_RenderNode_offsetTopAndBottom(CRITICAL_JNI_PARAMS_COMMA jlong renderNodePtr, jint offset) { return SET_AND_DIRTY(offsetTopBottom, offset, RenderNode::Y); } @@ -334,12 +336,12 @@ static jboolean android_view_RenderNode_offsetTopAndBottom(jlong renderNodePtr, // RenderProperties - getters // ---------------------------------------------------------------------------- -static jboolean android_view_RenderNode_hasOverlappingRendering(jlong renderNodePtr) { +static jboolean android_view_RenderNode_hasOverlappingRendering(CRITICAL_JNI_PARAMS_COMMA jlong renderNodePtr) { RenderNode* renderNode = reinterpret_cast(renderNodePtr); return renderNode->stagingProperties().hasOverlappingRendering(); } -static jboolean android_view_RenderNode_getAnimationMatrix(jlong renderNodePtr, jlong outMatrixPtr) { +static jboolean android_view_RenderNode_getAnimationMatrix(CRITICAL_JNI_PARAMS_COMMA jlong renderNodePtr, jlong outMatrixPtr) { RenderNode* renderNode = reinterpret_cast(renderNodePtr); SkMatrix* outMatrix = reinterpret_cast(outMatrixPtr); @@ -352,83 +354,83 @@ static jboolean android_view_RenderNode_getAnimationMatrix(jlong renderNodePtr, return JNI_FALSE; } -static jboolean android_view_RenderNode_getClipToBounds(jlong renderNodePtr) { +static jboolean android_view_RenderNode_getClipToBounds(CRITICAL_JNI_PARAMS_COMMA jlong renderNodePtr) { RenderNode* renderNode = reinterpret_cast(renderNodePtr); return renderNode->stagingProperties().getClipToBounds(); } -static jboolean android_view_RenderNode_getClipToOutline(jlong renderNodePtr) { +static jboolean android_view_RenderNode_getClipToOutline(CRITICAL_JNI_PARAMS_COMMA jlong renderNodePtr) { RenderNode* renderNode = reinterpret_cast(renderNodePtr); return renderNode->stagingProperties().getOutline().getShouldClip(); } -static jfloat android_view_RenderNode_getAlpha(jlong renderNodePtr) { +static jfloat android_view_RenderNode_getAlpha(CRITICAL_JNI_PARAMS_COMMA jlong renderNodePtr) { RenderNode* renderNode = reinterpret_cast(renderNodePtr); return renderNode->stagingProperties().getAlpha(); } -static jfloat android_view_RenderNode_getCameraDistance(jlong renderNodePtr) { +static jfloat android_view_RenderNode_getCameraDistance(CRITICAL_JNI_PARAMS_COMMA jlong renderNodePtr) { RenderNode* renderNode = reinterpret_cast(renderNodePtr); return renderNode->stagingProperties().getCameraDistance(); } -static jfloat android_view_RenderNode_getScaleX(jlong renderNodePtr) { +static jfloat android_view_RenderNode_getScaleX(CRITICAL_JNI_PARAMS_COMMA jlong renderNodePtr) { RenderNode* renderNode = reinterpret_cast(renderNodePtr); return renderNode->stagingProperties().getScaleX(); } -static jfloat android_view_RenderNode_getScaleY(jlong renderNodePtr) { +static jfloat android_view_RenderNode_getScaleY(CRITICAL_JNI_PARAMS_COMMA jlong renderNodePtr) { RenderNode* renderNode = reinterpret_cast(renderNodePtr); return renderNode->stagingProperties().getScaleY(); } -static jfloat android_view_RenderNode_getElevation(jlong renderNodePtr) { +static jfloat android_view_RenderNode_getElevation(CRITICAL_JNI_PARAMS_COMMA jlong renderNodePtr) { RenderNode* renderNode = reinterpret_cast(renderNodePtr); return renderNode->stagingProperties().getElevation(); } -static jfloat android_view_RenderNode_getTranslationX(jlong renderNodePtr) { +static jfloat android_view_RenderNode_getTranslationX(CRITICAL_JNI_PARAMS_COMMA jlong renderNodePtr) { RenderNode* renderNode = reinterpret_cast(renderNodePtr); return renderNode->stagingProperties().getTranslationX(); } -static jfloat android_view_RenderNode_getTranslationY(jlong renderNodePtr) { +static jfloat android_view_RenderNode_getTranslationY(CRITICAL_JNI_PARAMS_COMMA jlong renderNodePtr) { RenderNode* renderNode = reinterpret_cast(renderNodePtr); return renderNode->stagingProperties().getTranslationY(); } -static jfloat android_view_RenderNode_getTranslationZ(jlong renderNodePtr) { +static jfloat android_view_RenderNode_getTranslationZ(CRITICAL_JNI_PARAMS_COMMA jlong renderNodePtr) { RenderNode* renderNode = reinterpret_cast(renderNodePtr); return renderNode->stagingProperties().getTranslationZ(); } -static jfloat android_view_RenderNode_getRotation(jlong renderNodePtr) { +static jfloat android_view_RenderNode_getRotation(CRITICAL_JNI_PARAMS_COMMA jlong renderNodePtr) { RenderNode* renderNode = reinterpret_cast(renderNodePtr); return renderNode->stagingProperties().getRotation(); } -static jfloat android_view_RenderNode_getRotationX(jlong renderNodePtr) { +static jfloat android_view_RenderNode_getRotationX(CRITICAL_JNI_PARAMS_COMMA jlong renderNodePtr) { RenderNode* renderNode = reinterpret_cast(renderNodePtr); return renderNode->stagingProperties().getRotationX(); } -static jfloat android_view_RenderNode_getRotationY(jlong renderNodePtr) { +static jfloat android_view_RenderNode_getRotationY(CRITICAL_JNI_PARAMS_COMMA jlong renderNodePtr) { RenderNode* renderNode = reinterpret_cast(renderNodePtr); return renderNode->stagingProperties().getRotationY(); } -static jboolean android_view_RenderNode_isPivotExplicitlySet(jlong renderNodePtr) { +static jboolean android_view_RenderNode_isPivotExplicitlySet(CRITICAL_JNI_PARAMS_COMMA jlong renderNodePtr) { RenderNode* renderNode = reinterpret_cast(renderNodePtr); return renderNode->stagingProperties().isPivotExplicitlySet(); } -static jboolean android_view_RenderNode_hasIdentityMatrix(jlong renderNodePtr) { +static jboolean android_view_RenderNode_hasIdentityMatrix(CRITICAL_JNI_PARAMS_COMMA jlong renderNodePtr) { RenderNode* renderNode = reinterpret_cast(renderNodePtr); renderNode->mutateStagingProperties().updateMatrix(); return !renderNode->stagingProperties().hasTransformMatrix(); } -static jint android_view_RenderNode_getLayerType(jlong renderNodePtr) { +static jint android_view_RenderNode_getLayerType(CRITICAL_JNI_PARAMS_COMMA jlong renderNodePtr) { RenderNode* renderNode = reinterpret_cast(renderNodePtr); return static_cast(renderNode->stagingProperties().layerProperties().type()); } @@ -437,7 +439,7 @@ static jint android_view_RenderNode_getLayerType(jlong renderNodePtr) { // RenderProperties - computed getters // ---------------------------------------------------------------------------- -static void android_view_RenderNode_getTransformMatrix(jlong renderNodePtr, jlong outMatrixPtr) { +static void getTransformMatrix(jlong renderNodePtr, jlong outMatrixPtr) { RenderNode* renderNode = reinterpret_cast(renderNodePtr); SkMatrix* outMatrix = reinterpret_cast(outMatrixPtr); @@ -451,10 +453,14 @@ static void android_view_RenderNode_getTransformMatrix(jlong renderNodePtr, jlon } } -static void android_view_RenderNode_getInverseTransformMatrix(jlong renderNodePtr, +static void android_view_RenderNode_getTransformMatrix(CRITICAL_JNI_PARAMS_COMMA jlong renderNodePtr, jlong outMatrixPtr) { + getTransformMatrix(renderNodePtr, outMatrixPtr); +} + +static void android_view_RenderNode_getInverseTransformMatrix(CRITICAL_JNI_PARAMS_COMMA jlong renderNodePtr, jlong outMatrixPtr) { // load transform matrix - android_view_RenderNode_getTransformMatrix(renderNodePtr, outMatrixPtr); + getTransformMatrix(renderNodePtr, outMatrixPtr); SkMatrix* outMatrix = reinterpret_cast(outMatrixPtr); // return it inverted @@ -464,35 +470,35 @@ static void android_view_RenderNode_getInverseTransformMatrix(jlong renderNodePt } } -static jfloat android_view_RenderNode_getPivotX(jlong renderNodePtr) { +static jfloat android_view_RenderNode_getPivotX(CRITICAL_JNI_PARAMS_COMMA jlong renderNodePtr) { RenderNode* renderNode = reinterpret_cast(renderNodePtr); renderNode->mutateStagingProperties().updateMatrix(); return renderNode->stagingProperties().getPivotX(); } -static jfloat android_view_RenderNode_getPivotY(jlong renderNodePtr) { +static jfloat android_view_RenderNode_getPivotY(CRITICAL_JNI_PARAMS_COMMA jlong renderNodePtr) { RenderNode* renderNode = reinterpret_cast(renderNodePtr); renderNode->mutateStagingProperties().updateMatrix(); return renderNode->stagingProperties().getPivotY(); } -static jint android_view_RenderNode_getWidth(jlong renderNodePtr) { +static jint android_view_RenderNode_getWidth(CRITICAL_JNI_PARAMS_COMMA jlong renderNodePtr) { return reinterpret_cast(renderNodePtr)->stagingProperties().getWidth(); } -static jint android_view_RenderNode_getHeight(jlong renderNodePtr) { +static jint android_view_RenderNode_getHeight(CRITICAL_JNI_PARAMS_COMMA jlong renderNodePtr) { return reinterpret_cast(renderNodePtr)->stagingProperties().getHeight(); } -static jboolean android_view_RenderNode_setAllowForceDark(jlong renderNodePtr, jboolean allow) { +static jboolean android_view_RenderNode_setAllowForceDark(CRITICAL_JNI_PARAMS_COMMA jlong renderNodePtr, jboolean allow) { return SET_AND_DIRTY(setAllowForceDark, allow, RenderNode::GENERIC); } -static jboolean android_view_RenderNode_getAllowForceDark(jlong renderNodePtr) { +static jboolean android_view_RenderNode_getAllowForceDark(CRITICAL_JNI_PARAMS_COMMA jlong renderNodePtr) { return reinterpret_cast(renderNodePtr)->stagingProperties().getAllowForceDark(); } -static jlong android_view_RenderNode_getUniqueId(jlong renderNodePtr) { +static jlong android_view_RenderNode_getUniqueId(CRITICAL_JNI_PARAMS_COMMA jlong renderNodePtr) { return reinterpret_cast(renderNodePtr)->uniqueId(); } @@ -558,6 +564,7 @@ static void android_view_RenderNode_requestPositionUpdates(JNIEnv* env, jobject, } mPreviousPosition = bounds; +#ifdef __ANDROID__ // Layoutlib does not support CanvasContext incStrong(0); auto functor = std::bind( std::mem_fn(&PositionListenerTrampoline::doUpdatePositionAsync), this, @@ -566,6 +573,7 @@ static void android_view_RenderNode_requestPositionUpdates(JNIEnv* env, jobject, (jint) bounds.right, (jint) bounds.bottom); info.canvasContext.enqueueFrameWork(std::move(functor)); +#endif } virtual void onPositionLost(RenderNode& node, const TreeInfo* info) override { @@ -584,10 +592,11 @@ static void android_view_RenderNode_requestPositionUpdates(JNIEnv* env, jobject, mWeakRef = nullptr; return; } - +#ifdef __ANDROID__ // Layoutlib does not support CanvasContext // TODO: Remember why this is synchronous and then make a comment env->CallVoidMethod(localref, gPositionListener_PositionLostMethod, info ? info->canvasContext.getFrameNumber() : 0); +#endif env->DeleteLocalRef(localref); } diff --git a/libs/hwui/Android.bp b/libs/hwui/Android.bp index 354a4b323f413..5814bb70475c8 100644 --- a/libs/hwui/Android.bp +++ b/libs/hwui/Android.bp @@ -56,6 +56,8 @@ cc_defaults { host: { include_dirs: [ "external/vulkan-headers/include", + "frameworks/native/libs/math/include", + "frameworks/native/libs/ui/include", ], cflags: [ "-Wno-unused-variable", @@ -159,6 +161,10 @@ cc_defaults { whole_static_libs: ["libskia"], srcs: [ + "pipeline/skia/SkiaDisplayList.cpp", + "pipeline/skia/SkiaRecordingCanvas.cpp", + "pipeline/skia/RenderNodeDrawable.cpp", + "pipeline/skia/ReorderBarrierDrawables.cpp", "hwui/AnimatedImageDrawable.cpp", "hwui/AnimatedImageThread.cpp", "hwui/Bitmap.cpp", @@ -168,15 +174,24 @@ cc_defaults { "hwui/PaintImpl.cpp", "hwui/Typeface.cpp", "utils/Blur.cpp", + "utils/Color.cpp", "utils/LinearAllocator.cpp", "utils/VectorDrawableUtils.cpp", + "AnimationContext.cpp", "Animator.cpp", + "AnimatorManager.cpp", + "CanvasTransform.cpp", + "DamageAccumulator.cpp", "Interpolator.cpp", + "LightingInfo.cpp", "Matrix.cpp", "PathParser.cpp", "Properties.cpp", "PropertyValuesAnimatorSet.cpp", "PropertyValuesHolder.cpp", + "RecordingCanvas.cpp", + "RenderNode.cpp", + "RenderProperties.cpp", "SkiaCanvas.cpp", "VectorDrawable.cpp", ], @@ -193,15 +208,11 @@ cc_defaults { srcs: [ "pipeline/skia/GLFunctorDrawable.cpp", "pipeline/skia/LayerDrawable.cpp", - "pipeline/skia/RenderNodeDrawable.cpp", - "pipeline/skia/ReorderBarrierDrawables.cpp", "pipeline/skia/ShaderCache.cpp", - "pipeline/skia/SkiaDisplayList.cpp", "pipeline/skia/SkiaMemoryTracer.cpp", "pipeline/skia/SkiaOpenGLPipeline.cpp", "pipeline/skia/SkiaPipeline.cpp", "pipeline/skia/SkiaProfileRenderer.cpp", - "pipeline/skia/SkiaRecordingCanvas.cpp", "pipeline/skia/SkiaVulkanPipeline.cpp", "pipeline/skia/VectorDrawableAtlas.cpp", "pipeline/skia/VkFunctorDrawable.cpp", @@ -224,13 +235,8 @@ cc_defaults { "surfacetexture/ImageConsumer.cpp", "surfacetexture/SurfaceTexture.cpp", "thread/CommonPool.cpp", - "utils/Color.cpp", "utils/GLUtils.cpp", "utils/StringUtils.cpp", - "AnimationContext.cpp", - "AnimatorManager.cpp", - "CanvasTransform.cpp", - "DamageAccumulator.cpp", "DeferredLayerUpdater.cpp", "DeviceInfo.cpp", "FrameInfo.cpp", @@ -241,13 +247,9 @@ cc_defaults { "JankTracker.cpp", "Layer.cpp", "LayerUpdateQueue.cpp", - "LightingInfo.cpp", "ProfileData.cpp", "ProfileDataContainer.cpp", "Readback.cpp", - "RecordingCanvas.cpp", - "RenderNode.cpp", - "RenderProperties.cpp", "TreeInfo.cpp", "WebViewFunctorManager.cpp", "protos/graphicsstats.proto", @@ -257,6 +259,9 @@ cc_defaults { cflags: ["-Wno-implicit-fallthrough"], }, host: { + srcs: [ + "utils/HostColorSpace.cpp", + ], export_static_lib_headers: [ "libarect", ], diff --git a/libs/hwui/RenderNode.cpp b/libs/hwui/RenderNode.cpp index a833f7ef98c95..8aee8f5b1848a 100644 --- a/libs/hwui/RenderNode.cpp +++ b/libs/hwui/RenderNode.cpp @@ -20,7 +20,12 @@ #include "Debug.h" #include "TreeInfo.h" #include "VectorDrawable.h" +#ifdef __ANDROID__ #include "renderthread/CanvasContext.h" +#else +#include "DamageAccumulator.h" +#include "pipeline/skia/SkiaDisplayList.h" +#endif #include "utils/FatVector.h" #include "utils/MathUtils.h" #include "utils/StringUtils.h" @@ -160,6 +165,7 @@ void RenderNode::prepareLayer(TreeInfo& info, uint32_t dirtyMask) { } void RenderNode::pushLayerUpdate(TreeInfo& info) { +#ifdef __ANDROID__ // Layoutlib does not support CanvasContext and Layers LayerType layerType = properties().effectiveLayerType(); // If we are not a layer OR we cannot be rendered (eg, view was detached) // we need to destroy any Layers we may have had previously @@ -188,6 +194,7 @@ void RenderNode::pushLayerUpdate(TreeInfo& info) { // That might be us, so tell CanvasContext that this layer is in the // tree and should not be destroyed. info.canvasContext.markLayerInUse(this); +#endif } /** diff --git a/libs/hwui/RenderProperties.h b/libs/hwui/RenderProperties.h index e6710cc8f950d..e9794489f171a 100644 --- a/libs/hwui/RenderProperties.h +++ b/libs/hwui/RenderProperties.h @@ -526,9 +526,13 @@ public: } bool fitsOnLayer() const { +#ifdef __ANDROID__ // Layoutlib does not support device info const DeviceInfo* deviceInfo = DeviceInfo::get(); return mPrimitiveFields.mWidth <= deviceInfo->maxTextureSize() && mPrimitiveFields.mHeight <= deviceInfo->maxTextureSize(); +#else + return mPrimitiveFields.mWidth <= 4096 && mPrimitiveFields.mHeight <= 4096; +#endif } bool promotedToLayer() const { diff --git a/libs/hwui/hwui/Canvas.cpp b/libs/hwui/hwui/Canvas.cpp index e2ddb91f15657..a48c86028262c 100644 --- a/libs/hwui/hwui/Canvas.cpp +++ b/libs/hwui/hwui/Canvas.cpp @@ -30,11 +30,7 @@ namespace android { Canvas* Canvas::create_recording_canvas(int width, int height, uirenderer::RenderNode* renderNode) { -#ifdef __ANDROID__ // Layoutlib does not support recording canvas return new uirenderer::skiapipeline::SkiaRecordingCanvas(renderNode, width, height); -#else - return NULL; -#endif } static inline void drawStroke(SkScalar left, SkScalar right, SkScalar top, SkScalar thickness, diff --git a/libs/hwui/pipeline/skia/SkiaDisplayList.cpp b/libs/hwui/pipeline/skia/SkiaDisplayList.cpp index 780ac20c65aad..c7d5f3193f45b 100644 --- a/libs/hwui/pipeline/skia/SkiaDisplayList.cpp +++ b/libs/hwui/pipeline/skia/SkiaDisplayList.cpp @@ -17,9 +17,15 @@ #include "SkiaDisplayList.h" #include "DumpOpsCanvas.h" +#ifdef __ANDROID__ // Layoutlib does not support SkiaPipeline #include "SkiaPipeline.h" +#else +#include "DamageAccumulator.h" +#endif #include "VectorDrawable.h" +#ifdef __ANDROID__ #include "renderthread/CanvasContext.h" +#endif #include #include @@ -81,6 +87,7 @@ bool SkiaDisplayList::prepareListAndChildren( // If the prepare tree is triggered by the UI thread and no previous call to // pinImages has failed then we must pin all mutable images in the GPU cache // until the next UI thread draw. +#ifdef __ANDROID__ // Layoutlib does not support CanvasContext if (info.prepareTextures && !info.canvasContext.pinImages(mMutableImages)) { // In the event that pinning failed we prevent future pinImage calls for the // remainder of this tree traversal and also unpin any currently pinned images @@ -88,6 +95,7 @@ bool SkiaDisplayList::prepareListAndChildren( info.prepareTextures = false; info.canvasContext.unpinImages(); } +#endif bool hasBackwardProjectedNodesHere = false; bool hasBackwardProjectedNodesSubtree = false; @@ -141,10 +149,12 @@ bool SkiaDisplayList::prepareListAndChildren( const SkRect& bounds = vectorDrawable->properties().getBounds(); if (intersects(info.screenSize, totalMatrix, bounds)) { isDirty = true; +#ifdef __ANDROID__ // Layoutlib does not support CanvasContext static_cast(info.canvasContext.getRenderPipeline()) ->getVectorDrawables() ->push_back(vectorDrawable); vectorDrawable->setPropertyChangeWillBeConsumed(true); +#endif } } } diff --git a/libs/hwui/pipeline/skia/SkiaRecordingCanvas.cpp b/libs/hwui/pipeline/skia/SkiaRecordingCanvas.cpp index 16c8b8923074f..38ef131bedefc 100644 --- a/libs/hwui/pipeline/skia/SkiaRecordingCanvas.cpp +++ b/libs/hwui/pipeline/skia/SkiaRecordingCanvas.cpp @@ -18,14 +18,18 @@ #include #include "CanvasTransform.h" +#ifdef __ANDROID__ // Layoutlib does not support Layers #include "Layer.h" #include "LayerDrawable.h" +#endif #include "NinePatchUtils.h" #include "RenderNode.h" #include "pipeline/skia/AnimatedDrawables.h" +#ifdef __ANDROID__ // Layoutlib does not support GL, Vulcan etc. #include "pipeline/skia/GLFunctorDrawable.h" #include "pipeline/skia/VkFunctorDrawable.h" #include "pipeline/skia/VkInteropFunctorDrawable.h" +#endif namespace android { namespace uirenderer { @@ -102,13 +106,16 @@ void SkiaRecordingCanvas::insertReorderBarrier(bool enableReorder) { } void SkiaRecordingCanvas::drawLayer(uirenderer::DeferredLayerUpdater* layerUpdater) { +#ifdef __ANDROID__ // Layoutlib does not support Layers if (layerUpdater != nullptr) { // Create a ref-counted drawable, which is kept alive by sk_sp in SkLiteDL. sk_sp drawable(new LayerDrawable(layerUpdater)); drawDrawable(drawable.get()); } +#endif } + void SkiaRecordingCanvas::drawRenderNode(uirenderer::RenderNode* renderNode) { // Record the child node. Drawable dtor will be invoked when mChildNodes deque is cleared. mDisplayList->mChildNodes.emplace_back(renderNode, asSkCanvas(), true, mCurrentBarrier); @@ -125,8 +132,10 @@ void SkiaRecordingCanvas::drawRenderNode(uirenderer::RenderNode* renderNode) { } } + void SkiaRecordingCanvas::callDrawGLFunction(Functor* functor, uirenderer::GlFunctorLifecycleListener* listener) { +#ifdef __ANDROID__ // Layoutlib does not support GL, Vulcan etc. FunctorDrawable* functorDrawable; if (Properties::getRenderPipelineType() == RenderPipelineType::SkiaVulkan) { functorDrawable = mDisplayList->allocateDrawable( @@ -137,9 +146,11 @@ void SkiaRecordingCanvas::callDrawGLFunction(Functor* functor, } mDisplayList->mChildFunctors.push_back(functorDrawable); drawDrawable(functorDrawable); +#endif } void SkiaRecordingCanvas::drawWebViewFunctor(int functor) { +#ifdef __ANDROID__ // Layoutlib does not support GL, Vulcan etc. FunctorDrawable* functorDrawable; if (Properties::getRenderPipelineType() == RenderPipelineType::SkiaVulkan) { functorDrawable = mDisplayList->allocateDrawable(functor, asSkCanvas()); @@ -148,6 +159,7 @@ void SkiaRecordingCanvas::drawWebViewFunctor(int functor) { } mDisplayList->mChildFunctors.push_back(functorDrawable); drawDrawable(functorDrawable); +#endif } void SkiaRecordingCanvas::drawVectorDrawable(VectorDrawableRoot* tree) { diff --git a/libs/hwui/utils/HostColorSpace.cpp b/libs/hwui/utils/HostColorSpace.cpp new file mode 100644 index 0000000000000..77a6820c69997 --- /dev/null +++ b/libs/hwui/utils/HostColorSpace.cpp @@ -0,0 +1,417 @@ +/* + * Copyright (C) 2019 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. + */ +// This is copied from framework/native/libs/ui in order not to include libui in host build + +#include + +using namespace std::placeholders; + +namespace android { + +static constexpr float linearResponse(float v) { + return v; +} + +static constexpr float rcpResponse(float x, const ColorSpace::TransferParameters& p) { + return x >= p.d * p.c ? (std::pow(x, 1.0f / p.g) - p.b) / p.a : x / p.c; +} + +static constexpr float response(float x, const ColorSpace::TransferParameters& p) { + return x >= p.d ? std::pow(p.a * x + p.b, p.g) : p.c * x; +} + +static constexpr float rcpFullResponse(float x, const ColorSpace::TransferParameters& p) { + return x >= p.d * p.c ? (std::pow(x - p.e, 1.0f / p.g) - p.b) / p.a : (x - p.f) / p.c; +} + +static constexpr float fullResponse(float x, const ColorSpace::TransferParameters& p) { + return x >= p.d ? std::pow(p.a * x + p.b, p.g) + p.e : p.c * x + p.f; +} + +static float absRcpResponse(float x, float g,float a, float b, float c, float d) { + float xx = std::abs(x); + return std::copysign(xx >= d * c ? (std::pow(xx, 1.0f / g) - b) / a : xx / c, x); +} + +static float absResponse(float x, float g, float a, float b, float c, float d) { + float xx = std::abs(x); + return std::copysign(xx >= d ? std::pow(a * xx + b, g) : c * xx, x); +} + +static float safePow(float x, float e) { + return powf(x < 0.0f ? 0.0f : x, e); +} + +static ColorSpace::transfer_function toOETF(const ColorSpace::TransferParameters& parameters) { + if (parameters.e == 0.0f && parameters.f == 0.0f) { + return std::bind(rcpResponse, _1, parameters); + } + return std::bind(rcpFullResponse, _1, parameters); +} + +static ColorSpace::transfer_function toEOTF( const ColorSpace::TransferParameters& parameters) { + if (parameters.e == 0.0f && parameters.f == 0.0f) { + return std::bind(response, _1, parameters); + } + return std::bind(fullResponse, _1, parameters); +} + +static ColorSpace::transfer_function toOETF(float gamma) { + if (gamma == 1.0f) { + return linearResponse; + } + return std::bind(safePow, _1, 1.0f / gamma); +} + +static ColorSpace::transfer_function toEOTF(float gamma) { + if (gamma == 1.0f) { + return linearResponse; + } + return std::bind(safePow, _1, gamma); +} + +static constexpr std::array computePrimaries(const mat3& rgbToXYZ) { + float3 r(rgbToXYZ * float3{1, 0, 0}); + float3 g(rgbToXYZ * float3{0, 1, 0}); + float3 b(rgbToXYZ * float3{0, 0, 1}); + + return {{r.xy / dot(r, float3{1}), + g.xy / dot(g, float3{1}), + b.xy / dot(b, float3{1})}}; +} + +static constexpr float2 computeWhitePoint(const mat3& rgbToXYZ) { + float3 w(rgbToXYZ * float3{1}); + return w.xy / dot(w, float3{1}); +} + +ColorSpace::ColorSpace( + const std::string& name, + const mat3& rgbToXYZ, + transfer_function OETF, + transfer_function EOTF, + clamping_function clamper) noexcept + : mName(name) + , mRGBtoXYZ(rgbToXYZ) + , mXYZtoRGB(inverse(rgbToXYZ)) + , mOETF(std::move(OETF)) + , mEOTF(std::move(EOTF)) + , mClamper(std::move(clamper)) + , mPrimaries(computePrimaries(rgbToXYZ)) + , mWhitePoint(computeWhitePoint(rgbToXYZ)) { +} + +ColorSpace::ColorSpace( + const std::string& name, + const mat3& rgbToXYZ, + const TransferParameters parameters, + clamping_function clamper) noexcept + : mName(name) + , mRGBtoXYZ(rgbToXYZ) + , mXYZtoRGB(inverse(rgbToXYZ)) + , mParameters(parameters) + , mOETF(toOETF(mParameters)) + , mEOTF(toEOTF(mParameters)) + , mClamper(std::move(clamper)) + , mPrimaries(computePrimaries(rgbToXYZ)) + , mWhitePoint(computeWhitePoint(rgbToXYZ)) { +} + +ColorSpace::ColorSpace( + const std::string& name, + const mat3& rgbToXYZ, + float gamma, + clamping_function clamper) noexcept + : mName(name) + , mRGBtoXYZ(rgbToXYZ) + , mXYZtoRGB(inverse(rgbToXYZ)) + , mParameters({gamma, 1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f}) + , mOETF(toOETF(gamma)) + , mEOTF(toEOTF(gamma)) + , mClamper(std::move(clamper)) + , mPrimaries(computePrimaries(rgbToXYZ)) + , mWhitePoint(computeWhitePoint(rgbToXYZ)) { +} + +ColorSpace::ColorSpace( + const std::string& name, + const std::array& primaries, + const float2& whitePoint, + transfer_function OETF, + transfer_function EOTF, + clamping_function clamper) noexcept + : mName(name) + , mRGBtoXYZ(computeXYZMatrix(primaries, whitePoint)) + , mXYZtoRGB(inverse(mRGBtoXYZ)) + , mOETF(std::move(OETF)) + , mEOTF(std::move(EOTF)) + , mClamper(std::move(clamper)) + , mPrimaries(primaries) + , mWhitePoint(whitePoint) { +} + +ColorSpace::ColorSpace( + const std::string& name, + const std::array& primaries, + const float2& whitePoint, + const TransferParameters parameters, + clamping_function clamper) noexcept + : mName(name) + , mRGBtoXYZ(computeXYZMatrix(primaries, whitePoint)) + , mXYZtoRGB(inverse(mRGBtoXYZ)) + , mParameters(parameters) + , mOETF(toOETF(mParameters)) + , mEOTF(toEOTF(mParameters)) + , mClamper(std::move(clamper)) + , mPrimaries(primaries) + , mWhitePoint(whitePoint) { +} + +ColorSpace::ColorSpace( + const std::string& name, + const std::array& primaries, + const float2& whitePoint, + float gamma, + clamping_function clamper) noexcept + : mName(name) + , mRGBtoXYZ(computeXYZMatrix(primaries, whitePoint)) + , mXYZtoRGB(inverse(mRGBtoXYZ)) + , mParameters({gamma, 1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f}) + , mOETF(toOETF(gamma)) + , mEOTF(toEOTF(gamma)) + , mClamper(std::move(clamper)) + , mPrimaries(primaries) + , mWhitePoint(whitePoint) { +} + +constexpr mat3 ColorSpace::computeXYZMatrix( + const std::array& primaries, const float2& whitePoint) { + const float2& R = primaries[0]; + const float2& G = primaries[1]; + const float2& B = primaries[2]; + const float2& W = whitePoint; + + float oneRxRy = (1 - R.x) / R.y; + float oneGxGy = (1 - G.x) / G.y; + float oneBxBy = (1 - B.x) / B.y; + float oneWxWy = (1 - W.x) / W.y; + + float RxRy = R.x / R.y; + float GxGy = G.x / G.y; + float BxBy = B.x / B.y; + float WxWy = W.x / W.y; + + float BY = + ((oneWxWy - oneRxRy) * (GxGy - RxRy) - (WxWy - RxRy) * (oneGxGy - oneRxRy)) / + ((oneBxBy - oneRxRy) * (GxGy - RxRy) - (BxBy - RxRy) * (oneGxGy - oneRxRy)); + float GY = (WxWy - RxRy - BY * (BxBy - RxRy)) / (GxGy - RxRy); + float RY = 1 - GY - BY; + + float RYRy = RY / R.y; + float GYGy = GY / G.y; + float BYBy = BY / B.y; + + return { + float3{RYRy * R.x, RY, RYRy * (1 - R.x - R.y)}, + float3{GYGy * G.x, GY, GYGy * (1 - G.x - G.y)}, + float3{BYBy * B.x, BY, BYBy * (1 - B.x - B.y)} + }; +} + +const ColorSpace ColorSpace::sRGB() { + return { + "sRGB IEC61966-2.1", + {{float2{0.640f, 0.330f}, {0.300f, 0.600f}, {0.150f, 0.060f}}}, + {0.3127f, 0.3290f}, + {2.4f, 1 / 1.055f, 0.055f / 1.055f, 1 / 12.92f, 0.04045f, 0.0f, 0.0f} + }; +} + +const ColorSpace ColorSpace::linearSRGB() { + return { + "sRGB IEC61966-2.1 (Linear)", + {{float2{0.640f, 0.330f}, {0.300f, 0.600f}, {0.150f, 0.060f}}}, + {0.3127f, 0.3290f} + }; +} + +const ColorSpace ColorSpace::extendedSRGB() { + return { + "scRGB-nl IEC 61966-2-2:2003", + {{float2{0.640f, 0.330f}, {0.300f, 0.600f}, {0.150f, 0.060f}}}, + {0.3127f, 0.3290f}, + std::bind(absRcpResponse, _1, 2.4f, 1 / 1.055f, 0.055f / 1.055f, 1 / 12.92f, 0.04045f), + std::bind(absResponse, _1, 2.4f, 1 / 1.055f, 0.055f / 1.055f, 1 / 12.92f, 0.04045f), + std::bind(clamp, _1, -0.799f, 2.399f) + }; +} + +const ColorSpace ColorSpace::linearExtendedSRGB() { + return { + "scRGB IEC 61966-2-2:2003", + {{float2{0.640f, 0.330f}, {0.300f, 0.600f}, {0.150f, 0.060f}}}, + {0.3127f, 0.3290f}, + 1.0f, + std::bind(clamp, _1, -0.5f, 7.499f) + }; +} + +const ColorSpace ColorSpace::NTSC() { + return { + "NTSC (1953)", + {{float2{0.67f, 0.33f}, {0.21f, 0.71f}, {0.14f, 0.08f}}}, + {0.310f, 0.316f}, + {1 / 0.45f, 1 / 1.099f, 0.099f / 1.099f, 1 / 4.5f, 0.081f, 0.0f, 0.0f} + }; +} + +const ColorSpace ColorSpace::BT709() { + return { + "Rec. ITU-R BT.709-5", + {{float2{0.640f, 0.330f}, {0.300f, 0.600f}, {0.150f, 0.060f}}}, + {0.3127f, 0.3290f}, + {1 / 0.45f, 1 / 1.099f, 0.099f / 1.099f, 1 / 4.5f, 0.081f, 0.0f, 0.0f} + }; +} + +const ColorSpace ColorSpace::BT2020() { + return { + "Rec. ITU-R BT.2020-1", + {{float2{0.708f, 0.292f}, {0.170f, 0.797f}, {0.131f, 0.046f}}}, + {0.3127f, 0.3290f}, + {1 / 0.45f, 1 / 1.099f, 0.099f / 1.099f, 1 / 4.5f, 0.081f, 0.0f, 0.0f} + }; +} + +const ColorSpace ColorSpace::AdobeRGB() { + return { + "Adobe RGB (1998)", + {{float2{0.64f, 0.33f}, {0.21f, 0.71f}, {0.15f, 0.06f}}}, + {0.3127f, 0.3290f}, + 2.2f + }; +} + +const ColorSpace ColorSpace::ProPhotoRGB() { + return { + "ROMM RGB ISO 22028-2:2013", + {{float2{0.7347f, 0.2653f}, {0.1596f, 0.8404f}, {0.0366f, 0.0001f}}}, + {0.34567f, 0.35850f}, + {1.8f, 1.0f, 0.0f, 1 / 16.0f, 0.031248f, 0.0f, 0.0f} + }; +} + +const ColorSpace ColorSpace::DisplayP3() { + return { + "Display P3", + {{float2{0.680f, 0.320f}, {0.265f, 0.690f}, {0.150f, 0.060f}}}, + {0.3127f, 0.3290f}, + {2.4f, 1 / 1.055f, 0.055f / 1.055f, 1 / 12.92f, 0.039f, 0.0f, 0.0f} + }; +} + +const ColorSpace ColorSpace::DCIP3() { + return { + "SMPTE RP 431-2-2007 DCI (P3)", + {{float2{0.680f, 0.320f}, {0.265f, 0.690f}, {0.150f, 0.060f}}}, + {0.314f, 0.351f}, + 2.6f + }; +} + +const ColorSpace ColorSpace::ACES() { + return { + "SMPTE ST 2065-1:2012 ACES", + {{float2{0.73470f, 0.26530f}, {0.0f, 1.0f}, {0.00010f, -0.0770f}}}, + {0.32168f, 0.33767f}, + 1.0f, + std::bind(clamp, _1, -65504.0f, 65504.0f) + }; +} + +const ColorSpace ColorSpace::ACEScg() { + return { + "Academy S-2014-004 ACEScg", + {{float2{0.713f, 0.293f}, {0.165f, 0.830f}, {0.128f, 0.044f}}}, + {0.32168f, 0.33767f}, + 1.0f, + std::bind(clamp, _1, -65504.0f, 65504.0f) + }; +} + +std::unique_ptr ColorSpace::createLUT(uint32_t size, const ColorSpace& src, + const ColorSpace& dst) { + size = clamp(size, 2u, 256u); + float m = 1.0f / float(size - 1); + + std::unique_ptr lut(new float3[size * size * size]); + float3* data = lut.get(); + + ColorSpaceConnector connector(src, dst); + + for (uint32_t z = 0; z < size; z++) { + for (int32_t y = int32_t(size - 1); y >= 0; y--) { + for (uint32_t x = 0; x < size; x++) { + *data++ = connector.transform({x * m, y * m, z * m}); + } + } + } + + return lut; +} + +static const float2 ILLUMINANT_D50_XY = {0.34567f, 0.35850f}; +static const float3 ILLUMINANT_D50_XYZ = {0.964212f, 1.0f, 0.825188f}; +static const mat3 BRADFORD = mat3{ + float3{ 0.8951f, -0.7502f, 0.0389f}, + float3{ 0.2664f, 1.7135f, -0.0685f}, + float3{-0.1614f, 0.0367f, 1.0296f} +}; + +static mat3 adaptation(const mat3& matrix, const float3& srcWhitePoint, const float3& dstWhitePoint) { + float3 srcLMS = matrix * srcWhitePoint; + float3 dstLMS = matrix * dstWhitePoint; + return inverse(matrix) * mat3{dstLMS / srcLMS} * matrix; +} + +ColorSpaceConnector::ColorSpaceConnector( + const ColorSpace& src, + const ColorSpace& dst) noexcept + : mSource(src) + , mDestination(dst) { + + if (all(lessThan(abs(src.getWhitePoint() - dst.getWhitePoint()), float2{1e-3f}))) { + mTransform = dst.getXYZtoRGB() * src.getRGBtoXYZ(); + } else { + mat3 rgbToXYZ(src.getRGBtoXYZ()); + mat3 xyzToRGB(dst.getXYZtoRGB()); + + float3 srcXYZ = ColorSpace::XYZ(float3{src.getWhitePoint(), 1}); + float3 dstXYZ = ColorSpace::XYZ(float3{dst.getWhitePoint(), 1}); + + if (any(greaterThan(abs(src.getWhitePoint() - ILLUMINANT_D50_XY), float2{1e-3f}))) { + rgbToXYZ = adaptation(BRADFORD, srcXYZ, ILLUMINANT_D50_XYZ) * src.getRGBtoXYZ(); + } + + if (any(greaterThan(abs(dst.getWhitePoint() - ILLUMINANT_D50_XY), float2{1e-3f}))) { + xyzToRGB = inverse(adaptation(BRADFORD, dstXYZ, ILLUMINANT_D50_XYZ) * dst.getRGBtoXYZ()); + } + + mTransform = xyzToRGB * rgbToXYZ; + } +} + +}; // namespace android