1 /*
2  * Copyright (C) 2012 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 #define LOG_TAG "OpenGLRenderer"
18 #define ATRACE_TAG ATRACE_TAG_VIEW
19 
20 #include <EGL/egl.h>
21 
22 #include "jni.h"
23 #include "GraphicsJNI.h"
24 #include <nativehelper/JNIHelp.h>
25 #include <android_runtime/AndroidRuntime.h>
26 
27 #include <Animator.h>
28 #include <DamageAccumulator.h>
29 #include <Matrix.h>
30 #include <RenderNode.h>
31 #include <renderthread/CanvasContext.h>
32 #include <TreeInfo.h>
33 #include <hwui/Paint.h>
34 #include <utils/TraceUtils.h>
35 
36 #include "core_jni_helpers.h"
37 
38 namespace android {
39 
40 using namespace uirenderer;
41 
42 #define SET_AND_DIRTY(prop, val, dirtyFlag) \
43     (reinterpret_cast<RenderNode*>(renderNodePtr)->mutateStagingProperties().prop(val) \
44         ? (reinterpret_cast<RenderNode*>(renderNodePtr)->setPropertyFieldsDirty(dirtyFlag), true) \
45         : false)
46 
47 // ----------------------------------------------------------------------------
48 // DisplayList view properties
49 // ----------------------------------------------------------------------------
50 
android_view_RenderNode_output(JNIEnv * env,jobject clazz,jlong renderNodePtr)51 static void android_view_RenderNode_output(JNIEnv* env, jobject clazz, jlong renderNodePtr) {
52     RenderNode* renderNode = reinterpret_cast<RenderNode*>(renderNodePtr);
53     renderNode->output();
54 }
55 
android_view_RenderNode_getDebugSize(JNIEnv * env,jobject clazz,jlong renderNodePtr)56 static jint android_view_RenderNode_getDebugSize(JNIEnv* env, jobject clazz, jlong renderNodePtr) {
57     RenderNode* renderNode = reinterpret_cast<RenderNode*>(renderNodePtr);
58     return renderNode->getDebugSize();
59 }
60 
android_view_RenderNode_create(JNIEnv * env,jobject,jstring name)61 static jlong android_view_RenderNode_create(JNIEnv* env, jobject, jstring name) {
62     RenderNode* renderNode = new RenderNode();
63     renderNode->incStrong(0);
64     if (name != NULL) {
65         const char* textArray = env->GetStringUTFChars(name, NULL);
66         renderNode->setName(textArray);
67         env->ReleaseStringUTFChars(name, textArray);
68     }
69     return reinterpret_cast<jlong>(renderNode);
70 }
71 
releaseRenderNode(RenderNode * renderNode)72 static void releaseRenderNode(RenderNode* renderNode) {
73     renderNode->decStrong(0);
74 }
75 
android_view_RenderNode_getNativeFinalizer(JNIEnv * env,jobject clazz)76 static jlong android_view_RenderNode_getNativeFinalizer(JNIEnv* env,
77         jobject clazz) {
78     return static_cast<jlong>(reinterpret_cast<uintptr_t>(&releaseRenderNode));
79 }
80 
android_view_RenderNode_setDisplayList(JNIEnv * env,jobject clazz,jlong renderNodePtr,jlong displayListPtr)81 static void android_view_RenderNode_setDisplayList(JNIEnv* env,
82         jobject clazz, jlong renderNodePtr, jlong displayListPtr) {
83     RenderNode* renderNode = reinterpret_cast<RenderNode*>(renderNodePtr);
84     DisplayList* newData = reinterpret_cast<DisplayList*>(displayListPtr);
85     renderNode->setStagingDisplayList(newData);
86 }
87 
android_view_RenderNode_isValid(jlong renderNodePtr)88 static jboolean android_view_RenderNode_isValid(jlong renderNodePtr) {
89     return reinterpret_cast<RenderNode*>(renderNodePtr)->isValid();
90 }
91 
92 // ----------------------------------------------------------------------------
93 // RenderProperties - setters
94 // ----------------------------------------------------------------------------
95 
android_view_RenderNode_setLayerType(jlong renderNodePtr,jint jlayerType)96 static jboolean android_view_RenderNode_setLayerType(jlong renderNodePtr, jint jlayerType) {
97     LayerType layerType = static_cast<LayerType>(jlayerType);
98     return SET_AND_DIRTY(mutateLayerProperties().setType, layerType, RenderNode::GENERIC);
99 }
100 
android_view_RenderNode_setLayerPaint(jlong renderNodePtr,jlong paintPtr)101 static jboolean android_view_RenderNode_setLayerPaint(jlong renderNodePtr, jlong paintPtr) {
102     Paint* paint = reinterpret_cast<Paint*>(paintPtr);
103     return SET_AND_DIRTY(mutateLayerProperties().setFromPaint, paint, RenderNode::GENERIC);
104 }
105 
android_view_RenderNode_setStaticMatrix(jlong renderNodePtr,jlong matrixPtr)106 static jboolean android_view_RenderNode_setStaticMatrix(jlong renderNodePtr, jlong matrixPtr) {
107     SkMatrix* matrix = reinterpret_cast<SkMatrix*>(matrixPtr);
108     return SET_AND_DIRTY(setStaticMatrix, matrix, RenderNode::GENERIC);
109 }
110 
android_view_RenderNode_setAnimationMatrix(jlong renderNodePtr,jlong matrixPtr)111 static jboolean android_view_RenderNode_setAnimationMatrix(jlong renderNodePtr, jlong matrixPtr) {
112     SkMatrix* matrix = reinterpret_cast<SkMatrix*>(matrixPtr);
113     return SET_AND_DIRTY(setAnimationMatrix, matrix, RenderNode::GENERIC);
114 }
115 
android_view_RenderNode_setClipToBounds(jlong renderNodePtr,jboolean clipToBounds)116 static jboolean android_view_RenderNode_setClipToBounds(jlong renderNodePtr,
117         jboolean clipToBounds) {
118     return SET_AND_DIRTY(setClipToBounds, clipToBounds, RenderNode::GENERIC);
119 }
120 
android_view_RenderNode_setClipBounds(jlong renderNodePtr,jint left,jint top,jint right,jint bottom)121 static jboolean android_view_RenderNode_setClipBounds(jlong renderNodePtr,
122         jint left, jint top, jint right, jint bottom) {
123     android::uirenderer::Rect clipBounds(left, top, right, bottom);
124     return SET_AND_DIRTY(setClipBounds, clipBounds, RenderNode::GENERIC);
125 }
126 
android_view_RenderNode_setClipBoundsEmpty(jlong renderNodePtr)127 static jboolean android_view_RenderNode_setClipBoundsEmpty(jlong renderNodePtr) {
128     return SET_AND_DIRTY(setClipBoundsEmpty,, RenderNode::GENERIC);
129 }
130 
android_view_RenderNode_setProjectBackwards(jlong renderNodePtr,jboolean shouldProject)131 static jboolean android_view_RenderNode_setProjectBackwards(jlong renderNodePtr,
132         jboolean shouldProject) {
133     return SET_AND_DIRTY(setProjectBackwards, shouldProject, RenderNode::GENERIC);
134 }
135 
android_view_RenderNode_setProjectionReceiver(jlong renderNodePtr,jboolean shouldRecieve)136 static jboolean android_view_RenderNode_setProjectionReceiver(jlong renderNodePtr,
137         jboolean shouldRecieve) {
138     return SET_AND_DIRTY(setProjectionReceiver, shouldRecieve, RenderNode::GENERIC);
139 }
140 
android_view_RenderNode_setOutlineRoundRect(jlong renderNodePtr,jint left,jint top,jint right,jint bottom,jfloat radius,jfloat alpha)141 static jboolean android_view_RenderNode_setOutlineRoundRect(jlong renderNodePtr,
142         jint left, jint top, jint right, jint bottom, jfloat radius, jfloat alpha) {
143     RenderNode* renderNode = reinterpret_cast<RenderNode*>(renderNodePtr);
144     renderNode->mutateStagingProperties().mutableOutline().setRoundRect(left, top, right, bottom,
145             radius, alpha);
146     renderNode->setPropertyFieldsDirty(RenderNode::GENERIC);
147     return true;
148 }
149 
android_view_RenderNode_setOutlineConvexPath(jlong renderNodePtr,jlong outlinePathPtr,jfloat alpha)150 static jboolean android_view_RenderNode_setOutlineConvexPath(jlong renderNodePtr,
151         jlong outlinePathPtr, jfloat alpha) {
152     RenderNode* renderNode = reinterpret_cast<RenderNode*>(renderNodePtr);
153     SkPath* outlinePath = reinterpret_cast<SkPath*>(outlinePathPtr);
154     renderNode->mutateStagingProperties().mutableOutline().setConvexPath(outlinePath, alpha);
155     renderNode->setPropertyFieldsDirty(RenderNode::GENERIC);
156     return true;
157 }
158 
android_view_RenderNode_setOutlineEmpty(jlong renderNodePtr)159 static jboolean android_view_RenderNode_setOutlineEmpty(jlong renderNodePtr) {
160     RenderNode* renderNode = reinterpret_cast<RenderNode*>(renderNodePtr);
161     renderNode->mutateStagingProperties().mutableOutline().setEmpty();
162     renderNode->setPropertyFieldsDirty(RenderNode::GENERIC);
163     return true;
164 }
165 
android_view_RenderNode_setOutlineNone(jlong renderNodePtr)166 static jboolean android_view_RenderNode_setOutlineNone(jlong renderNodePtr) {
167     RenderNode* renderNode = reinterpret_cast<RenderNode*>(renderNodePtr);
168     renderNode->mutateStagingProperties().mutableOutline().setNone();
169     renderNode->setPropertyFieldsDirty(RenderNode::GENERIC);
170     return true;
171 }
172 
android_view_RenderNode_hasShadow(jlong renderNodePtr)173 static jboolean android_view_RenderNode_hasShadow(jlong renderNodePtr) {
174     RenderNode* renderNode = reinterpret_cast<RenderNode*>(renderNodePtr);
175     return renderNode->stagingProperties().hasShadow();
176 }
177 
android_view_RenderNode_setSpotShadowColor(jlong renderNodePtr,jint shadowColor)178 static jboolean android_view_RenderNode_setSpotShadowColor(jlong renderNodePtr, jint shadowColor) {
179     return SET_AND_DIRTY(setSpotShadowColor,
180             static_cast<SkColor>(shadowColor), RenderNode::GENERIC);
181 }
182 
android_view_RenderNode_getSpotShadowColor(jlong renderNodePtr)183 static jint android_view_RenderNode_getSpotShadowColor(jlong renderNodePtr) {
184     RenderNode* renderNode = reinterpret_cast<RenderNode*>(renderNodePtr);
185     return renderNode->stagingProperties().getSpotShadowColor();
186 }
187 
android_view_RenderNode_setAmbientShadowColor(jlong renderNodePtr,jint shadowColor)188 static jboolean android_view_RenderNode_setAmbientShadowColor(jlong renderNodePtr,
189         jint shadowColor) {
190     return SET_AND_DIRTY(setAmbientShadowColor,
191             static_cast<SkColor>(shadowColor), RenderNode::GENERIC);
192 }
193 
android_view_RenderNode_getAmbientShadowColor(jlong renderNodePtr)194 static jint android_view_RenderNode_getAmbientShadowColor(jlong renderNodePtr) {
195     RenderNode* renderNode = reinterpret_cast<RenderNode*>(renderNodePtr);
196     return renderNode->stagingProperties().getAmbientShadowColor();
197 }
198 
android_view_RenderNode_setClipToOutline(jlong renderNodePtr,jboolean clipToOutline)199 static jboolean android_view_RenderNode_setClipToOutline(jlong renderNodePtr,
200         jboolean clipToOutline) {
201     RenderNode* renderNode = reinterpret_cast<RenderNode*>(renderNodePtr);
202     renderNode->mutateStagingProperties().mutableOutline().setShouldClip(clipToOutline);
203     renderNode->setPropertyFieldsDirty(RenderNode::GENERIC);
204     return true;
205 }
206 
android_view_RenderNode_setRevealClip(jlong renderNodePtr,jboolean shouldClip,jfloat x,jfloat y,jfloat radius)207 static jboolean android_view_RenderNode_setRevealClip(jlong renderNodePtr, jboolean shouldClip,
208         jfloat x, jfloat y, jfloat radius) {
209     RenderNode* renderNode = reinterpret_cast<RenderNode*>(renderNodePtr);
210     renderNode->mutateStagingProperties().mutableRevealClip().set(
211             shouldClip, x, y, radius);
212     renderNode->setPropertyFieldsDirty(RenderNode::GENERIC);
213     return true;
214 }
215 
android_view_RenderNode_setAlpha(jlong renderNodePtr,float alpha)216 static jboolean android_view_RenderNode_setAlpha(jlong renderNodePtr, float alpha) {
217     return SET_AND_DIRTY(setAlpha, alpha, RenderNode::ALPHA);
218 }
219 
android_view_RenderNode_setHasOverlappingRendering(jlong renderNodePtr,bool hasOverlappingRendering)220 static jboolean android_view_RenderNode_setHasOverlappingRendering(jlong renderNodePtr,
221         bool hasOverlappingRendering) {
222     return SET_AND_DIRTY(setHasOverlappingRendering, hasOverlappingRendering,
223             RenderNode::GENERIC);
224 }
225 
android_view_RenderNode_setUsageHint(jlong renderNodePtr,jint usageHint)226 static void android_view_RenderNode_setUsageHint(jlong renderNodePtr, jint usageHint) {
227     RenderNode* renderNode = reinterpret_cast<RenderNode*>(renderNodePtr);
228     renderNode->setUsageHint(static_cast<UsageHint>(usageHint));
229 }
230 
android_view_RenderNode_setElevation(jlong renderNodePtr,float elevation)231 static jboolean android_view_RenderNode_setElevation(jlong renderNodePtr, float elevation) {
232     return SET_AND_DIRTY(setElevation, elevation, RenderNode::Z);
233 }
234 
android_view_RenderNode_setTranslationX(jlong renderNodePtr,float tx)235 static jboolean android_view_RenderNode_setTranslationX(jlong renderNodePtr, float tx) {
236     return SET_AND_DIRTY(setTranslationX, tx, RenderNode::TRANSLATION_X | RenderNode::X);
237 }
238 
android_view_RenderNode_setTranslationY(jlong renderNodePtr,float ty)239 static jboolean android_view_RenderNode_setTranslationY(jlong renderNodePtr, float ty) {
240     return SET_AND_DIRTY(setTranslationY, ty, RenderNode::TRANSLATION_Y | RenderNode::Y);
241 }
242 
android_view_RenderNode_setTranslationZ(jlong renderNodePtr,float tz)243 static jboolean android_view_RenderNode_setTranslationZ(jlong renderNodePtr, float tz) {
244     return SET_AND_DIRTY(setTranslationZ, tz, RenderNode::TRANSLATION_Z | RenderNode::Z);
245 }
246 
android_view_RenderNode_setRotation(jlong renderNodePtr,float rotation)247 static jboolean android_view_RenderNode_setRotation(jlong renderNodePtr, float rotation) {
248     return SET_AND_DIRTY(setRotation, rotation, RenderNode::ROTATION);
249 }
250 
android_view_RenderNode_setRotationX(jlong renderNodePtr,float rx)251 static jboolean android_view_RenderNode_setRotationX(jlong renderNodePtr, float rx) {
252     return SET_AND_DIRTY(setRotationX, rx, RenderNode::ROTATION_X);
253 }
254 
android_view_RenderNode_setRotationY(jlong renderNodePtr,float ry)255 static jboolean android_view_RenderNode_setRotationY(jlong renderNodePtr, float ry) {
256     return SET_AND_DIRTY(setRotationY, ry, RenderNode::ROTATION_Y);
257 }
258 
android_view_RenderNode_setScaleX(jlong renderNodePtr,float sx)259 static jboolean android_view_RenderNode_setScaleX(jlong renderNodePtr, float sx) {
260     return SET_AND_DIRTY(setScaleX, sx, RenderNode::SCALE_X);
261 }
262 
android_view_RenderNode_setScaleY(jlong renderNodePtr,float sy)263 static jboolean android_view_RenderNode_setScaleY(jlong renderNodePtr, float sy) {
264     return SET_AND_DIRTY(setScaleY, sy, RenderNode::SCALE_Y);
265 }
266 
android_view_RenderNode_setPivotX(jlong renderNodePtr,float px)267 static jboolean android_view_RenderNode_setPivotX(jlong renderNodePtr, float px) {
268     return SET_AND_DIRTY(setPivotX, px, RenderNode::GENERIC);
269 }
270 
android_view_RenderNode_setPivotY(jlong renderNodePtr,float py)271 static jboolean android_view_RenderNode_setPivotY(jlong renderNodePtr, float py) {
272     return SET_AND_DIRTY(setPivotY, py, RenderNode::GENERIC);
273 }
274 
android_view_RenderNode_resetPivot(jlong renderNodePtr)275 static jboolean android_view_RenderNode_resetPivot(jlong renderNodePtr) {
276     return SET_AND_DIRTY(resetPivot, /* void */, RenderNode::GENERIC);
277 }
278 
android_view_RenderNode_setCameraDistance(jlong renderNodePtr,float distance)279 static jboolean android_view_RenderNode_setCameraDistance(jlong renderNodePtr, float distance) {
280     return SET_AND_DIRTY(setCameraDistance, distance, RenderNode::GENERIC);
281 }
282 
android_view_RenderNode_setLeft(jlong renderNodePtr,int left)283 static jboolean android_view_RenderNode_setLeft(jlong renderNodePtr, int left) {
284     return SET_AND_DIRTY(setLeft, left, RenderNode::X);
285 }
286 
android_view_RenderNode_setTop(jlong renderNodePtr,int top)287 static jboolean android_view_RenderNode_setTop(jlong renderNodePtr, int top) {
288     return SET_AND_DIRTY(setTop, top, RenderNode::Y);
289 }
290 
android_view_RenderNode_setRight(jlong renderNodePtr,int right)291 static jboolean android_view_RenderNode_setRight(jlong renderNodePtr, int right) {
292     return SET_AND_DIRTY(setRight, right, RenderNode::X);
293 }
294 
android_view_RenderNode_setBottom(jlong renderNodePtr,int bottom)295 static jboolean android_view_RenderNode_setBottom(jlong renderNodePtr, int bottom) {
296     return SET_AND_DIRTY(setBottom, bottom, RenderNode::Y);
297 }
298 
android_view_RenderNode_getLeft(jlong renderNodePtr)299 static jint android_view_RenderNode_getLeft(jlong renderNodePtr) {
300     return reinterpret_cast<RenderNode*>(renderNodePtr)->stagingProperties().getLeft();
301 }
302 
android_view_RenderNode_getTop(jlong renderNodePtr)303 static jint android_view_RenderNode_getTop(jlong renderNodePtr) {
304     return reinterpret_cast<RenderNode*>(renderNodePtr)->stagingProperties().getTop();
305 }
306 
android_view_RenderNode_getRight(jlong renderNodePtr)307 static jint android_view_RenderNode_getRight(jlong renderNodePtr) {
308     return reinterpret_cast<RenderNode*>(renderNodePtr)->stagingProperties().getRight();
309 }
310 
android_view_RenderNode_getBottom(jlong renderNodePtr)311 static jint android_view_RenderNode_getBottom(jlong renderNodePtr) {
312     return reinterpret_cast<RenderNode*>(renderNodePtr)->stagingProperties().getBottom();
313 }
314 
android_view_RenderNode_setLeftTopRightBottom(jlong renderNodePtr,int left,int top,int right,int bottom)315 static jboolean android_view_RenderNode_setLeftTopRightBottom(jlong renderNodePtr,
316         int left, int top, int right, int bottom) {
317     RenderNode* renderNode = reinterpret_cast<RenderNode*>(renderNodePtr);
318     if (renderNode->mutateStagingProperties().setLeftTopRightBottom(left, top, right, bottom)) {
319         renderNode->setPropertyFieldsDirty(RenderNode::X | RenderNode::Y);
320         return true;
321     }
322     return false;
323 }
324 
android_view_RenderNode_offsetLeftAndRight(jlong renderNodePtr,jint offset)325 static jboolean android_view_RenderNode_offsetLeftAndRight(jlong renderNodePtr, jint offset) {
326     return SET_AND_DIRTY(offsetLeftRight, offset, RenderNode::X);
327 }
328 
android_view_RenderNode_offsetTopAndBottom(jlong renderNodePtr,jint offset)329 static jboolean android_view_RenderNode_offsetTopAndBottom(jlong renderNodePtr, jint offset) {
330     return SET_AND_DIRTY(offsetTopBottom, offset, RenderNode::Y);
331 }
332 
333 // ----------------------------------------------------------------------------
334 // RenderProperties - getters
335 // ----------------------------------------------------------------------------
336 
android_view_RenderNode_hasOverlappingRendering(jlong renderNodePtr)337 static jboolean android_view_RenderNode_hasOverlappingRendering(jlong renderNodePtr) {
338     RenderNode* renderNode = reinterpret_cast<RenderNode*>(renderNodePtr);
339     return renderNode->stagingProperties().hasOverlappingRendering();
340 }
341 
android_view_RenderNode_getAnimationMatrix(jlong renderNodePtr,jlong outMatrixPtr)342 static jboolean android_view_RenderNode_getAnimationMatrix(jlong renderNodePtr, jlong outMatrixPtr) {
343     RenderNode* renderNode = reinterpret_cast<RenderNode*>(renderNodePtr);
344     SkMatrix* outMatrix = reinterpret_cast<SkMatrix*>(outMatrixPtr);
345 
346     const SkMatrix* animationMatrix = renderNode->stagingProperties().getAnimationMatrix();
347 
348     if (animationMatrix) {
349         *outMatrix = *animationMatrix;
350         return JNI_TRUE;
351     }
352     return JNI_FALSE;
353 }
354 
android_view_RenderNode_getClipToBounds(jlong renderNodePtr)355 static jboolean android_view_RenderNode_getClipToBounds(jlong renderNodePtr) {
356     RenderNode* renderNode = reinterpret_cast<RenderNode*>(renderNodePtr);
357     return renderNode->stagingProperties().getClipToBounds();
358 }
359 
android_view_RenderNode_getClipToOutline(jlong renderNodePtr)360 static jboolean android_view_RenderNode_getClipToOutline(jlong renderNodePtr) {
361     RenderNode* renderNode = reinterpret_cast<RenderNode*>(renderNodePtr);
362     return renderNode->stagingProperties().getOutline().getShouldClip();
363 }
364 
android_view_RenderNode_getAlpha(jlong renderNodePtr)365 static jfloat android_view_RenderNode_getAlpha(jlong renderNodePtr) {
366     RenderNode* renderNode = reinterpret_cast<RenderNode*>(renderNodePtr);
367     return renderNode->stagingProperties().getAlpha();
368 }
369 
android_view_RenderNode_getCameraDistance(jlong renderNodePtr)370 static jfloat android_view_RenderNode_getCameraDistance(jlong renderNodePtr) {
371     RenderNode* renderNode = reinterpret_cast<RenderNode*>(renderNodePtr);
372     return renderNode->stagingProperties().getCameraDistance();
373 }
374 
android_view_RenderNode_getScaleX(jlong renderNodePtr)375 static jfloat android_view_RenderNode_getScaleX(jlong renderNodePtr) {
376     RenderNode* renderNode = reinterpret_cast<RenderNode*>(renderNodePtr);
377     return renderNode->stagingProperties().getScaleX();
378 }
379 
android_view_RenderNode_getScaleY(jlong renderNodePtr)380 static jfloat android_view_RenderNode_getScaleY(jlong renderNodePtr) {
381     RenderNode* renderNode = reinterpret_cast<RenderNode*>(renderNodePtr);
382     return renderNode->stagingProperties().getScaleY();
383 }
384 
android_view_RenderNode_getElevation(jlong renderNodePtr)385 static jfloat android_view_RenderNode_getElevation(jlong renderNodePtr) {
386     RenderNode* renderNode = reinterpret_cast<RenderNode*>(renderNodePtr);
387     return renderNode->stagingProperties().getElevation();
388 }
389 
android_view_RenderNode_getTranslationX(jlong renderNodePtr)390 static jfloat android_view_RenderNode_getTranslationX(jlong renderNodePtr) {
391     RenderNode* renderNode = reinterpret_cast<RenderNode*>(renderNodePtr);
392     return renderNode->stagingProperties().getTranslationX();
393 }
394 
android_view_RenderNode_getTranslationY(jlong renderNodePtr)395 static jfloat android_view_RenderNode_getTranslationY(jlong renderNodePtr) {
396     RenderNode* renderNode = reinterpret_cast<RenderNode*>(renderNodePtr);
397     return renderNode->stagingProperties().getTranslationY();
398 }
399 
android_view_RenderNode_getTranslationZ(jlong renderNodePtr)400 static jfloat android_view_RenderNode_getTranslationZ(jlong renderNodePtr) {
401     RenderNode* renderNode = reinterpret_cast<RenderNode*>(renderNodePtr);
402     return renderNode->stagingProperties().getTranslationZ();
403 }
404 
android_view_RenderNode_getRotation(jlong renderNodePtr)405 static jfloat android_view_RenderNode_getRotation(jlong renderNodePtr) {
406     RenderNode* renderNode = reinterpret_cast<RenderNode*>(renderNodePtr);
407     return renderNode->stagingProperties().getRotation();
408 }
409 
android_view_RenderNode_getRotationX(jlong renderNodePtr)410 static jfloat android_view_RenderNode_getRotationX(jlong renderNodePtr) {
411     RenderNode* renderNode = reinterpret_cast<RenderNode*>(renderNodePtr);
412     return renderNode->stagingProperties().getRotationX();
413 }
414 
android_view_RenderNode_getRotationY(jlong renderNodePtr)415 static jfloat android_view_RenderNode_getRotationY(jlong renderNodePtr) {
416     RenderNode* renderNode = reinterpret_cast<RenderNode*>(renderNodePtr);
417     return renderNode->stagingProperties().getRotationY();
418 }
419 
android_view_RenderNode_isPivotExplicitlySet(jlong renderNodePtr)420 static jboolean android_view_RenderNode_isPivotExplicitlySet(jlong renderNodePtr) {
421     RenderNode* renderNode = reinterpret_cast<RenderNode*>(renderNodePtr);
422     return renderNode->stagingProperties().isPivotExplicitlySet();
423 }
424 
android_view_RenderNode_hasIdentityMatrix(jlong renderNodePtr)425 static jboolean android_view_RenderNode_hasIdentityMatrix(jlong renderNodePtr) {
426     RenderNode* renderNode = reinterpret_cast<RenderNode*>(renderNodePtr);
427     renderNode->mutateStagingProperties().updateMatrix();
428     return !renderNode->stagingProperties().hasTransformMatrix();
429 }
430 
android_view_RenderNode_getLayerType(jlong renderNodePtr)431 static jint android_view_RenderNode_getLayerType(jlong renderNodePtr) {
432     RenderNode* renderNode = reinterpret_cast<RenderNode*>(renderNodePtr);
433     return static_cast<int>(renderNode->stagingProperties().layerProperties().type());
434 }
435 
436 // ----------------------------------------------------------------------------
437 // RenderProperties - computed getters
438 // ----------------------------------------------------------------------------
439 
android_view_RenderNode_getTransformMatrix(jlong renderNodePtr,jlong outMatrixPtr)440 static void android_view_RenderNode_getTransformMatrix(jlong renderNodePtr, jlong outMatrixPtr) {
441     RenderNode* renderNode = reinterpret_cast<RenderNode*>(renderNodePtr);
442     SkMatrix* outMatrix = reinterpret_cast<SkMatrix*>(outMatrixPtr);
443 
444     renderNode->mutateStagingProperties().updateMatrix();
445     const SkMatrix* transformMatrix = renderNode->stagingProperties().getTransformMatrix();
446 
447     if (transformMatrix) {
448         *outMatrix = *transformMatrix;
449     } else {
450         outMatrix->setIdentity();
451     }
452 }
453 
android_view_RenderNode_getInverseTransformMatrix(jlong renderNodePtr,jlong outMatrixPtr)454 static void android_view_RenderNode_getInverseTransformMatrix(jlong renderNodePtr,
455         jlong outMatrixPtr) {
456     // load transform matrix
457     android_view_RenderNode_getTransformMatrix(renderNodePtr, outMatrixPtr);
458     SkMatrix* outMatrix = reinterpret_cast<SkMatrix*>(outMatrixPtr);
459 
460     // return it inverted
461     if (!outMatrix->invert(outMatrix)) {
462         // failed to load inverse, pass back identity
463         outMatrix->setIdentity();
464     }
465 }
466 
android_view_RenderNode_getPivotX(jlong renderNodePtr)467 static jfloat android_view_RenderNode_getPivotX(jlong renderNodePtr) {
468     RenderNode* renderNode = reinterpret_cast<RenderNode*>(renderNodePtr);
469     renderNode->mutateStagingProperties().updateMatrix();
470     return renderNode->stagingProperties().getPivotX();
471 }
472 
android_view_RenderNode_getPivotY(jlong renderNodePtr)473 static jfloat android_view_RenderNode_getPivotY(jlong renderNodePtr) {
474     RenderNode* renderNode = reinterpret_cast<RenderNode*>(renderNodePtr);
475     renderNode->mutateStagingProperties().updateMatrix();
476     return renderNode->stagingProperties().getPivotY();
477 }
478 
android_view_RenderNode_getWidth(jlong renderNodePtr)479 static jint android_view_RenderNode_getWidth(jlong renderNodePtr) {
480     return reinterpret_cast<RenderNode*>(renderNodePtr)->stagingProperties().getWidth();
481 }
482 
android_view_RenderNode_getHeight(jlong renderNodePtr)483 static jint android_view_RenderNode_getHeight(jlong renderNodePtr) {
484     return reinterpret_cast<RenderNode*>(renderNodePtr)->stagingProperties().getHeight();
485 }
486 
android_view_RenderNode_setAllowForceDark(jlong renderNodePtr,jboolean allow)487 static jboolean android_view_RenderNode_setAllowForceDark(jlong renderNodePtr, jboolean allow) {
488     return SET_AND_DIRTY(setAllowForceDark, allow, RenderNode::GENERIC);
489 }
490 
android_view_RenderNode_getAllowForceDark(jlong renderNodePtr)491 static jboolean android_view_RenderNode_getAllowForceDark(jlong renderNodePtr) {
492     return reinterpret_cast<RenderNode*>(renderNodePtr)->stagingProperties().getAllowForceDark();
493 }
494 
android_view_RenderNode_getUniqueId(jlong renderNodePtr)495 static jlong android_view_RenderNode_getUniqueId(jlong renderNodePtr) {
496     return reinterpret_cast<RenderNode*>(renderNodePtr)->uniqueId();
497 }
498 
499 // ----------------------------------------------------------------------------
500 // RenderProperties - Animations
501 // ----------------------------------------------------------------------------
502 
android_view_RenderNode_addAnimator(JNIEnv * env,jobject clazz,jlong renderNodePtr,jlong animatorPtr)503 static void android_view_RenderNode_addAnimator(JNIEnv* env, jobject clazz, jlong renderNodePtr,
504         jlong animatorPtr) {
505     RenderNode* renderNode = reinterpret_cast<RenderNode*>(renderNodePtr);
506     RenderPropertyAnimator* animator = reinterpret_cast<RenderPropertyAnimator*>(animatorPtr);
507     renderNode->addAnimator(animator);
508 }
509 
android_view_RenderNode_endAllAnimators(JNIEnv * env,jobject clazz,jlong renderNodePtr)510 static void android_view_RenderNode_endAllAnimators(JNIEnv* env, jobject clazz,
511         jlong renderNodePtr) {
512     RenderNode* renderNode = reinterpret_cast<RenderNode*>(renderNodePtr);
513     renderNode->animators().endAllStagingAnimators();
514 }
515 
516 // ----------------------------------------------------------------------------
517 // SurfaceView position callback
518 // ----------------------------------------------------------------------------
519 
520 jmethodID gPositionListener_PositionChangedMethod;
521 jmethodID gPositionListener_PositionLostMethod;
522 
android_view_RenderNode_requestPositionUpdates(JNIEnv * env,jobject,jlong renderNodePtr,jobject listener)523 static void android_view_RenderNode_requestPositionUpdates(JNIEnv* env, jobject,
524         jlong renderNodePtr, jobject listener) {
525     class PositionListenerTrampoline : public RenderNode::PositionListener {
526     public:
527         PositionListenerTrampoline(JNIEnv* env, jobject listener) {
528             env->GetJavaVM(&mVm);
529             mWeakRef = env->NewWeakGlobalRef(listener);
530         }
531 
532         virtual ~PositionListenerTrampoline() {
533             jnienv()->DeleteWeakGlobalRef(mWeakRef);
534             mWeakRef = nullptr;
535         }
536 
537         virtual void onPositionUpdated(RenderNode& node, const TreeInfo& info) override {
538             if (CC_UNLIKELY(!mWeakRef || !info.updateWindowPositions)) return;
539 
540             Matrix4 transform;
541             info.damageAccumulator->computeCurrentTransform(&transform);
542             const RenderProperties& props = node.properties();
543             uirenderer::Rect bounds(props.getWidth(), props.getHeight());
544             transform.mapRect(bounds);
545 
546             if (CC_LIKELY(transform.isPureTranslate())) {
547                 // snap/round the computed bounds, so they match the rounding behavior
548                 // of the clear done in SurfaceView#draw().
549                 bounds.snapGeometryToPixelBoundaries(false);
550             } else {
551                 // Conservatively round out so the punched hole (in the ZOrderOnTop = true case)
552                 // doesn't extend beyond the other window
553                 bounds.roundOut();
554             }
555 
556             if (mPreviousPosition == bounds) {
557                 return;
558             }
559             mPreviousPosition = bounds;
560 
561             incStrong(0);
562             auto functor = std::bind(
563                 std::mem_fn(&PositionListenerTrampoline::doUpdatePositionAsync), this,
564                 (jlong) info.canvasContext.getFrameNumber(),
565                 (jint) bounds.left, (jint) bounds.top,
566                 (jint) bounds.right, (jint) bounds.bottom);
567 
568             info.canvasContext.enqueueFrameWork(std::move(functor));
569         }
570 
571         virtual void onPositionLost(RenderNode& node, const TreeInfo* info) override {
572             if (CC_UNLIKELY(!mWeakRef || (info && !info->updateWindowPositions))) return;
573 
574             if (mPreviousPosition.isEmpty()) {
575                 return;
576             }
577             mPreviousPosition.setEmpty();
578 
579             ATRACE_NAME("SurfaceView position lost");
580             JNIEnv* env = jnienv();
581             jobject localref = env->NewLocalRef(mWeakRef);
582             if (CC_UNLIKELY(!localref)) {
583                 jnienv()->DeleteWeakGlobalRef(mWeakRef);
584                 mWeakRef = nullptr;
585                 return;
586             }
587 
588             // TODO: Remember why this is synchronous and then make a comment
589             env->CallVoidMethod(localref, gPositionListener_PositionLostMethod,
590                     info ? info->canvasContext.getFrameNumber() : 0);
591             env->DeleteLocalRef(localref);
592         }
593 
594     private:
595         JNIEnv* jnienv() {
596             JNIEnv* env;
597             if (mVm->GetEnv(reinterpret_cast<void**>(&env), JNI_VERSION_1_6) != JNI_OK) {
598                 LOG_ALWAYS_FATAL("Failed to get JNIEnv for JavaVM: %p", mVm);
599             }
600             return env;
601         }
602 
603         void doUpdatePositionAsync(jlong frameNumber, jint left, jint top,
604                 jint right, jint bottom) {
605             ATRACE_NAME("Update SurfaceView position");
606 
607             JNIEnv* env = jnienv();
608             jobject localref = env->NewLocalRef(mWeakRef);
609             if (CC_UNLIKELY(!localref)) {
610                 env->DeleteWeakGlobalRef(mWeakRef);
611                 mWeakRef = nullptr;
612             } else {
613                 env->CallVoidMethod(localref, gPositionListener_PositionChangedMethod,
614                         frameNumber, left, top, right, bottom);
615                 env->DeleteLocalRef(localref);
616             }
617 
618             // We need to release ourselves here
619             decStrong(0);
620         }
621 
622         JavaVM* mVm;
623         jobject mWeakRef;
624         uirenderer::Rect mPreviousPosition;
625     };
626 
627     RenderNode* renderNode = reinterpret_cast<RenderNode*>(renderNodePtr);
628     renderNode->setPositionListener(new PositionListenerTrampoline(env, listener));
629 }
630 
631 // ----------------------------------------------------------------------------
632 // JNI Glue
633 // ----------------------------------------------------------------------------
634 
635 const char* const kClassPathName = "android/graphics/RenderNode";
636 
637 static const JNINativeMethod gMethods[] = {
638 // ----------------------------------------------------------------------------
639 // Regular JNI
640 // ----------------------------------------------------------------------------
641     { "nCreate",               "(Ljava/lang/String;)J", (void*) android_view_RenderNode_create },
642     { "nGetNativeFinalizer",   "()J",    (void*) android_view_RenderNode_getNativeFinalizer },
643     { "nOutput",               "(J)V",    (void*) android_view_RenderNode_output },
644     { "nGetDebugSize",         "(J)I",    (void*) android_view_RenderNode_getDebugSize },
645     { "nAddAnimator",              "(JJ)V", (void*) android_view_RenderNode_addAnimator },
646     { "nEndAllAnimators",          "(J)V", (void*) android_view_RenderNode_endAllAnimators },
647     { "nRequestPositionUpdates",   "(JLandroid/graphics/RenderNode$PositionUpdateListener;)V", (void*) android_view_RenderNode_requestPositionUpdates },
648     { "nSetDisplayList",       "(JJ)V",   (void*) android_view_RenderNode_setDisplayList },
649 
650 
651 // ----------------------------------------------------------------------------
652 // Fast JNI via @CriticalNative annotation in RenderNode.java
653 // ----------------------------------------------------------------------------
654     { "nSetDisplayList",       "(JJ)V",   (void*) android_view_RenderNode_setDisplayList },
655 
656 
657 // ----------------------------------------------------------------------------
658 // Critical JNI via @CriticalNative annotation in RenderNode.java
659 // ----------------------------------------------------------------------------
660     { "nIsValid",              "(J)Z",   (void*) android_view_RenderNode_isValid },
661     { "nSetLayerType",         "(JI)Z",  (void*) android_view_RenderNode_setLayerType },
662     { "nGetLayerType",         "(J)I",   (void*) android_view_RenderNode_getLayerType },
663     { "nSetLayerPaint",        "(JJ)Z",  (void*) android_view_RenderNode_setLayerPaint },
664     { "nSetStaticMatrix",      "(JJ)Z",  (void*) android_view_RenderNode_setStaticMatrix },
665     { "nSetAnimationMatrix",   "(JJ)Z",  (void*) android_view_RenderNode_setAnimationMatrix },
666     { "nGetAnimationMatrix",   "(JJ)Z",  (void*) android_view_RenderNode_getAnimationMatrix },
667     { "nSetClipToBounds",      "(JZ)Z",  (void*) android_view_RenderNode_setClipToBounds },
668     { "nGetClipToBounds",      "(J)Z",   (void*) android_view_RenderNode_getClipToBounds },
669     { "nSetClipBounds",        "(JIIII)Z", (void*) android_view_RenderNode_setClipBounds },
670     { "nSetClipBoundsEmpty",   "(J)Z",   (void*) android_view_RenderNode_setClipBoundsEmpty },
671     { "nSetProjectBackwards",  "(JZ)Z",  (void*) android_view_RenderNode_setProjectBackwards },
672     { "nSetProjectionReceiver","(JZ)Z",  (void*) android_view_RenderNode_setProjectionReceiver },
673 
674     { "nSetOutlineRoundRect",  "(JIIIIFF)Z", (void*) android_view_RenderNode_setOutlineRoundRect },
675     { "nSetOutlineConvexPath", "(JJF)Z", (void*) android_view_RenderNode_setOutlineConvexPath },
676     { "nSetOutlineEmpty",      "(J)Z",   (void*) android_view_RenderNode_setOutlineEmpty },
677     { "nSetOutlineNone",       "(J)Z",   (void*) android_view_RenderNode_setOutlineNone },
678     { "nHasShadow",            "(J)Z",   (void*) android_view_RenderNode_hasShadow },
679     { "nSetSpotShadowColor",   "(JI)Z",  (void*) android_view_RenderNode_setSpotShadowColor },
680     { "nGetSpotShadowColor",   "(J)I",   (void*) android_view_RenderNode_getSpotShadowColor },
681     { "nSetAmbientShadowColor","(JI)Z",  (void*) android_view_RenderNode_setAmbientShadowColor },
682     { "nGetAmbientShadowColor","(J)I",   (void*) android_view_RenderNode_getAmbientShadowColor },
683     { "nSetClipToOutline",     "(JZ)Z",  (void*) android_view_RenderNode_setClipToOutline },
684     { "nSetRevealClip",        "(JZFFF)Z", (void*) android_view_RenderNode_setRevealClip },
685 
686     { "nSetAlpha",             "(JF)Z",  (void*) android_view_RenderNode_setAlpha },
687     { "nSetHasOverlappingRendering", "(JZ)Z",
688             (void*) android_view_RenderNode_setHasOverlappingRendering },
689     { "nSetUsageHint",    "(JI)V", (void*) android_view_RenderNode_setUsageHint },
690     { "nSetElevation",         "(JF)Z",  (void*) android_view_RenderNode_setElevation },
691     { "nSetTranslationX",      "(JF)Z",  (void*) android_view_RenderNode_setTranslationX },
692     { "nSetTranslationY",      "(JF)Z",  (void*) android_view_RenderNode_setTranslationY },
693     { "nSetTranslationZ",      "(JF)Z",  (void*) android_view_RenderNode_setTranslationZ },
694     { "nSetRotation",          "(JF)Z",  (void*) android_view_RenderNode_setRotation },
695     { "nSetRotationX",         "(JF)Z",  (void*) android_view_RenderNode_setRotationX },
696     { "nSetRotationY",         "(JF)Z",  (void*) android_view_RenderNode_setRotationY },
697     { "nSetScaleX",            "(JF)Z",  (void*) android_view_RenderNode_setScaleX },
698     { "nSetScaleY",            "(JF)Z",  (void*) android_view_RenderNode_setScaleY },
699     { "nSetPivotX",            "(JF)Z",  (void*) android_view_RenderNode_setPivotX },
700     { "nSetPivotY",            "(JF)Z",  (void*) android_view_RenderNode_setPivotY },
701     { "nResetPivot",           "(J)Z",   (void*) android_view_RenderNode_resetPivot },
702     { "nSetCameraDistance",    "(JF)Z",  (void*) android_view_RenderNode_setCameraDistance },
703     { "nSetLeft",              "(JI)Z",  (void*) android_view_RenderNode_setLeft },
704     { "nSetTop",               "(JI)Z",  (void*) android_view_RenderNode_setTop },
705     { "nSetRight",             "(JI)Z",  (void*) android_view_RenderNode_setRight },
706     { "nSetBottom",            "(JI)Z",  (void*) android_view_RenderNode_setBottom },
707     { "nGetLeft",              "(J)I",  (void*) android_view_RenderNode_getLeft },
708     { "nGetTop",               "(J)I",  (void*) android_view_RenderNode_getTop },
709     { "nGetRight",             "(J)I",  (void*) android_view_RenderNode_getRight },
710     { "nGetBottom",            "(J)I",  (void*) android_view_RenderNode_getBottom },
711     { "nSetLeftTopRightBottom","(JIIII)Z", (void*) android_view_RenderNode_setLeftTopRightBottom },
712     { "nOffsetLeftAndRight",   "(JI)Z",  (void*) android_view_RenderNode_offsetLeftAndRight },
713     { "nOffsetTopAndBottom",   "(JI)Z",  (void*) android_view_RenderNode_offsetTopAndBottom },
714 
715     { "nHasOverlappingRendering", "(J)Z",  (void*) android_view_RenderNode_hasOverlappingRendering },
716     { "nGetClipToOutline",        "(J)Z",  (void*) android_view_RenderNode_getClipToOutline },
717     { "nGetAlpha",                "(J)F",  (void*) android_view_RenderNode_getAlpha },
718     { "nGetCameraDistance",       "(J)F",  (void*) android_view_RenderNode_getCameraDistance },
719     { "nGetScaleX",               "(J)F",  (void*) android_view_RenderNode_getScaleX },
720     { "nGetScaleY",               "(J)F",  (void*) android_view_RenderNode_getScaleY },
721     { "nGetElevation",            "(J)F",  (void*) android_view_RenderNode_getElevation },
722     { "nGetTranslationX",         "(J)F",  (void*) android_view_RenderNode_getTranslationX },
723     { "nGetTranslationY",         "(J)F",  (void*) android_view_RenderNode_getTranslationY },
724     { "nGetTranslationZ",         "(J)F",  (void*) android_view_RenderNode_getTranslationZ },
725     { "nGetRotation",             "(J)F",  (void*) android_view_RenderNode_getRotation },
726     { "nGetRotationX",            "(J)F",  (void*) android_view_RenderNode_getRotationX },
727     { "nGetRotationY",            "(J)F",  (void*) android_view_RenderNode_getRotationY },
728     { "nIsPivotExplicitlySet",    "(J)Z",  (void*) android_view_RenderNode_isPivotExplicitlySet },
729     { "nHasIdentityMatrix",       "(J)Z",  (void*) android_view_RenderNode_hasIdentityMatrix },
730 
731     { "nGetTransformMatrix",       "(JJ)V", (void*) android_view_RenderNode_getTransformMatrix },
732     { "nGetInverseTransformMatrix","(JJ)V", (void*) android_view_RenderNode_getInverseTransformMatrix },
733 
734     { "nGetPivotX",                "(J)F",  (void*) android_view_RenderNode_getPivotX },
735     { "nGetPivotY",                "(J)F",  (void*) android_view_RenderNode_getPivotY },
736     { "nGetWidth",                 "(J)I",  (void*) android_view_RenderNode_getWidth },
737     { "nGetHeight",                "(J)I",  (void*) android_view_RenderNode_getHeight },
738     { "nSetAllowForceDark",        "(JZ)Z", (void*) android_view_RenderNode_setAllowForceDark },
739     { "nGetAllowForceDark",        "(J)Z",  (void*) android_view_RenderNode_getAllowForceDark },
740     { "nGetUniqueId",              "(J)J",  (void*) android_view_RenderNode_getUniqueId },
741 };
742 
register_android_view_RenderNode(JNIEnv * env)743 int register_android_view_RenderNode(JNIEnv* env) {
744     jclass clazz = FindClassOrDie(env, "android/graphics/RenderNode$PositionUpdateListener");
745     gPositionListener_PositionChangedMethod = GetMethodIDOrDie(env, clazz,
746             "positionChanged", "(JIIII)V");
747     gPositionListener_PositionLostMethod = GetMethodIDOrDie(env, clazz,
748             "positionLost", "(J)V");
749     return RegisterMethodsOrDie(env, kClassPathName, gMethods, NELEM(gMethods));
750 }
751 
752 };
753 
754