Enable RenderNode and RecordingCanvas for layoutlib

Bug: 117921091
Test: all tests should pass
Change-Id: I574b12a5f7a6a54cbbcb17c35a3884368fd404e6
This commit is contained in:
Fedor Kudasov
2019-06-18 15:51:57 +01:00
parent c8d5387564
commit 86bd214059
11 changed files with 584 additions and 110 deletions

View File

@@ -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",

View File

@@ -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<std::string, RegJNIRec> 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<std::string, RegJNIRec> 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)},

View File

@@ -21,9 +21,9 @@
#include <nativehelper/JNIHelp.h>
#include <android_runtime/AndroidRuntime.h>
#ifdef __ANDROID__ // Layoutlib does not support Looper and device properties
#include <utils/Looper.h>
#include <cutils/properties.h>
#endif
#include <SkBitmap.h>
#include <SkRegion.h>
@@ -34,7 +34,9 @@
#include <hwui/Canvas.h>
#include <hwui/Paint.h>
#include <minikin/Layout.h>
#ifdef __ANDROID__ // Layoutlib does not support RenderThread
#include <renderthread/RenderProxy.h>
#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<Looper> mLooper;
sp<InvokeRunnableMessage> 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<Canvas*>(canvasPtr);
Functor* functor = reinterpret_cast<Functor*>(functorPtr);
sp<GlFunctorReleasedCallbackBridge> 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<RenderNode*>(renderNodePtr);
return reinterpret_cast<jlong>(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<Canvas*>(canvasPtr);
RenderNode* renderNode = reinterpret_cast<RenderNode*>(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<Canvas*>(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<Canvas*>(canvasPtr);
return reinterpret_cast<jlong>(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<Canvas*>(canvasPtr);
RenderNode* renderNode = reinterpret_cast<RenderNode*>(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<Canvas*>(canvasPtr);
DeferredLayerUpdater* layer = reinterpret_cast<DeferredLayerUpdater*>(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<Canvas*>(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<Canvas*>(canvasPtr);
CanvasPropertyPrimitive* xProp = reinterpret_cast<CanvasPropertyPrimitive*>(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<Canvas*>(canvasPtr);
canvas->drawWebViewFunctor(functor);
}

View File

@@ -16,9 +16,9 @@
#define LOG_TAG "OpenGLRenderer"
#define ATRACE_TAG ATRACE_TAG_VIEW
#ifdef __ANDROID__ // Layoutlib does not support EGL
#include <EGL/egl.h>
#endif
#include "jni.h"
#include "GraphicsJNI.h"
#include <nativehelper/JNIHelp.h>
@@ -28,7 +28,9 @@
#include <DamageAccumulator.h>
#include <Matrix.h>
#include <RenderNode.h>
#ifdef __ANDROID__ // Layoutlib does not support CanvasContext
#include <renderthread/CanvasContext.h>
#endif
#include <TreeInfo.h>
#include <hwui/Paint.h>
#include <utils/TraceUtils.h>
@@ -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<RenderNode*>(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<LayerType>(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<Paint*>(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<SkMatrix*>(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<SkMatrix*>(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<RenderNode*>(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<RenderNode*>(renderNodePtr);
SkPath* outlinePath = reinterpret_cast<SkPath*>(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<RenderNode*>(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<RenderNode*>(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<RenderNode*>(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<SkColor>(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<RenderNode*>(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<SkColor>(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<RenderNode*>(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<RenderNode*>(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<RenderNode*>(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<RenderNode*>(renderNodePtr);
renderNode->setUsageHint(static_cast<UsageHint>(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<RenderNode*>(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<RenderNode*>(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<RenderNode*>(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<RenderNode*>(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<RenderNode*>(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<RenderNode*>(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<RenderNode*>(renderNodePtr);
SkMatrix* outMatrix = reinterpret_cast<SkMatrix*>(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<RenderNode*>(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<RenderNode*>(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<RenderNode*>(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<RenderNode*>(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<RenderNode*>(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<RenderNode*>(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<RenderNode*>(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<RenderNode*>(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<RenderNode*>(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<RenderNode*>(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<RenderNode*>(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<RenderNode*>(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<RenderNode*>(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<RenderNode*>(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<RenderNode*>(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<RenderNode*>(renderNodePtr);
return static_cast<int>(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<RenderNode*>(renderNodePtr);
SkMatrix* outMatrix = reinterpret_cast<SkMatrix*>(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<SkMatrix*>(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<RenderNode*>(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<RenderNode*>(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<RenderNode*>(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<RenderNode*>(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<RenderNode*>(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<RenderNode*>(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);
}

View File

@@ -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",
],

View File

@@ -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
}
/**

View File

@@ -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 {

View File

@@ -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,

View File

@@ -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 <SkImagePriv.h>
#include <SkPathOps.h>
@@ -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<SkiaPipeline*>(info.canvasContext.getRenderPipeline())
->getVectorDrawables()
->push_back(vectorDrawable);
vectorDrawable->setPropertyChangeWillBeConsumed(true);
#endif
}
}
}

View File

@@ -18,14 +18,18 @@
#include <SkImagePriv.h>
#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<SkDrawable> 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<VkInteropFunctorDrawable>(
@@ -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<VkFunctorDrawable>(functor, asSkCanvas());
@@ -148,6 +159,7 @@ void SkiaRecordingCanvas::drawWebViewFunctor(int functor) {
}
mDisplayList->mChildFunctors.push_back(functorDrawable);
drawDrawable(functorDrawable);
#endif
}
void SkiaRecordingCanvas::drawVectorDrawable(VectorDrawableRoot* tree) {

View File

@@ -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 <ui/ColorSpace.h>
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<float2, 3> 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<float2, 3>& 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<float2, 3>& 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<float2, 3>& 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<float2, 3>& 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<float>, _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<float>, _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<float>, _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<float>, _1, -65504.0f, 65504.0f)
};
}
std::unique_ptr<float3[]> 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<float3[]> 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