• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
35 #include "core_jni_helpers.h"
36 
37 namespace android {
38 
39 using namespace uirenderer;
40 
41 #define SET_AND_DIRTY(prop, val, dirtyFlag) \
42     (reinterpret_cast<RenderNode*>(renderNodePtr)->mutateStagingProperties().prop(val) \
43         ? (reinterpret_cast<RenderNode*>(renderNodePtr)->setPropertyFieldsDirty(dirtyFlag), true) \
44         : false)
45 
46 // ----------------------------------------------------------------------------
47 // DisplayList view properties
48 // ----------------------------------------------------------------------------
49 
android_view_RenderNode_output(JNIEnv * env,jobject clazz,jlong renderNodePtr)50 static void android_view_RenderNode_output(JNIEnv* env, jobject clazz, jlong renderNodePtr) {
51     RenderNode* renderNode = reinterpret_cast<RenderNode*>(renderNodePtr);
52     renderNode->output();
53 }
54 
android_view_RenderNode_getDebugSize(JNIEnv * env,jobject clazz,jlong renderNodePtr)55 static jint android_view_RenderNode_getDebugSize(JNIEnv* env, jobject clazz, jlong renderNodePtr) {
56     RenderNode* renderNode = reinterpret_cast<RenderNode*>(renderNodePtr);
57     return renderNode->getDebugSize();
58 }
59 
android_view_RenderNode_create(JNIEnv * env,jobject,jstring name)60 static jlong android_view_RenderNode_create(JNIEnv* env, jobject, jstring name) {
61     RenderNode* renderNode = new RenderNode();
62     renderNode->incStrong(0);
63     if (name != NULL) {
64         const char* textArray = env->GetStringUTFChars(name, NULL);
65         renderNode->setName(textArray);
66         env->ReleaseStringUTFChars(name, textArray);
67     }
68     return reinterpret_cast<jlong>(renderNode);
69 }
70 
releaseRenderNode(RenderNode * renderNode)71 static void releaseRenderNode(RenderNode* renderNode) {
72     renderNode->decStrong(0);
73 }
74 
android_view_RenderNode_getNativeFinalizer(JNIEnv * env,jobject clazz)75 static jlong android_view_RenderNode_getNativeFinalizer(JNIEnv* env,
76         jobject clazz) {
77     return static_cast<jlong>(reinterpret_cast<uintptr_t>(&releaseRenderNode));
78 }
79 
android_view_RenderNode_setDisplayList(JNIEnv * env,jobject clazz,jlong renderNodePtr,jlong displayListPtr)80 static void android_view_RenderNode_setDisplayList(JNIEnv* env,
81         jobject clazz, jlong renderNodePtr, jlong displayListPtr) {
82     RenderNode* renderNode = reinterpret_cast<RenderNode*>(renderNodePtr);
83     DisplayList* newData = reinterpret_cast<DisplayList*>(displayListPtr);
84     renderNode->setStagingDisplayList(newData);
85 }
86 
android_view_RenderNode_isValid(jlong renderNodePtr)87 static jboolean android_view_RenderNode_isValid(jlong renderNodePtr) {
88     return reinterpret_cast<RenderNode*>(renderNodePtr)->isValid();
89 }
90 
91 // ----------------------------------------------------------------------------
92 // RenderProperties - setters
93 // ----------------------------------------------------------------------------
94 
android_view_RenderNode_setLayerType(jlong renderNodePtr,jint jlayerType)95 static jboolean android_view_RenderNode_setLayerType(jlong renderNodePtr, jint jlayerType) {
96     LayerType layerType = static_cast<LayerType>(jlayerType);
97     return SET_AND_DIRTY(mutateLayerProperties().setType, layerType, RenderNode::GENERIC);
98 }
99 
android_view_RenderNode_setLayerPaint(jlong renderNodePtr,jlong paintPtr)100 static jboolean android_view_RenderNode_setLayerPaint(jlong renderNodePtr, jlong paintPtr) {
101     Paint* paint = reinterpret_cast<Paint*>(paintPtr);
102     return SET_AND_DIRTY(mutateLayerProperties().setFromPaint, paint, RenderNode::GENERIC);
103 }
104 
android_view_RenderNode_setStaticMatrix(jlong renderNodePtr,jlong matrixPtr)105 static jboolean android_view_RenderNode_setStaticMatrix(jlong renderNodePtr, jlong matrixPtr) {
106     SkMatrix* matrix = reinterpret_cast<SkMatrix*>(matrixPtr);
107     return SET_AND_DIRTY(setStaticMatrix, matrix, RenderNode::GENERIC);
108 }
109 
android_view_RenderNode_setAnimationMatrix(jlong renderNodePtr,jlong matrixPtr)110 static jboolean android_view_RenderNode_setAnimationMatrix(jlong renderNodePtr, jlong matrixPtr) {
111     SkMatrix* matrix = reinterpret_cast<SkMatrix*>(matrixPtr);
112     return SET_AND_DIRTY(setAnimationMatrix, matrix, RenderNode::GENERIC);
113 }
114 
android_view_RenderNode_setClipToBounds(jlong renderNodePtr,jboolean clipToBounds)115 static jboolean android_view_RenderNode_setClipToBounds(jlong renderNodePtr,
116         jboolean clipToBounds) {
117     return SET_AND_DIRTY(setClipToBounds, clipToBounds, RenderNode::GENERIC);
118 }
119 
android_view_RenderNode_setClipBounds(jlong renderNodePtr,jint left,jint top,jint right,jint bottom)120 static jboolean android_view_RenderNode_setClipBounds(jlong renderNodePtr,
121         jint left, jint top, jint right, jint bottom) {
122     android::uirenderer::Rect clipBounds(left, top, right, bottom);
123     return SET_AND_DIRTY(setClipBounds, clipBounds, RenderNode::GENERIC);
124 }
125 
android_view_RenderNode_setClipBoundsEmpty(jlong renderNodePtr)126 static jboolean android_view_RenderNode_setClipBoundsEmpty(jlong renderNodePtr) {
127     return SET_AND_DIRTY(setClipBoundsEmpty,, RenderNode::GENERIC);
128 }
129 
android_view_RenderNode_setProjectBackwards(jlong renderNodePtr,jboolean shouldProject)130 static jboolean android_view_RenderNode_setProjectBackwards(jlong renderNodePtr,
131         jboolean shouldProject) {
132     return SET_AND_DIRTY(setProjectBackwards, shouldProject, RenderNode::GENERIC);
133 }
134 
android_view_RenderNode_setProjectionReceiver(jlong renderNodePtr,jboolean shouldRecieve)135 static jboolean android_view_RenderNode_setProjectionReceiver(jlong renderNodePtr,
136         jboolean shouldRecieve) {
137     return SET_AND_DIRTY(setProjectionReceiver, shouldRecieve, RenderNode::GENERIC);
138 }
139 
android_view_RenderNode_setOutlineRoundRect(jlong renderNodePtr,jint left,jint top,jint right,jint bottom,jfloat radius,jfloat alpha)140 static jboolean android_view_RenderNode_setOutlineRoundRect(jlong renderNodePtr,
141         jint left, jint top, jint right, jint bottom, jfloat radius, jfloat alpha) {
142     RenderNode* renderNode = reinterpret_cast<RenderNode*>(renderNodePtr);
143     renderNode->mutateStagingProperties().mutableOutline().setRoundRect(left, top, right, bottom,
144             radius, alpha);
145     renderNode->setPropertyFieldsDirty(RenderNode::GENERIC);
146     return true;
147 }
148 
android_view_RenderNode_setOutlineConvexPath(jlong renderNodePtr,jlong outlinePathPtr,jfloat alpha)149 static jboolean android_view_RenderNode_setOutlineConvexPath(jlong renderNodePtr,
150         jlong outlinePathPtr, jfloat alpha) {
151     RenderNode* renderNode = reinterpret_cast<RenderNode*>(renderNodePtr);
152     SkPath* outlinePath = reinterpret_cast<SkPath*>(outlinePathPtr);
153     renderNode->mutateStagingProperties().mutableOutline().setConvexPath(outlinePath, alpha);
154     renderNode->setPropertyFieldsDirty(RenderNode::GENERIC);
155     return true;
156 }
157 
android_view_RenderNode_setOutlineEmpty(jlong renderNodePtr)158 static jboolean android_view_RenderNode_setOutlineEmpty(jlong renderNodePtr) {
159     RenderNode* renderNode = reinterpret_cast<RenderNode*>(renderNodePtr);
160     renderNode->mutateStagingProperties().mutableOutline().setEmpty();
161     renderNode->setPropertyFieldsDirty(RenderNode::GENERIC);
162     return true;
163 }
164 
android_view_RenderNode_setOutlineNone(jlong renderNodePtr)165 static jboolean android_view_RenderNode_setOutlineNone(jlong renderNodePtr) {
166     RenderNode* renderNode = reinterpret_cast<RenderNode*>(renderNodePtr);
167     renderNode->mutateStagingProperties().mutableOutline().setNone();
168     renderNode->setPropertyFieldsDirty(RenderNode::GENERIC);
169     return true;
170 }
171 
android_view_RenderNode_hasShadow(jlong renderNodePtr)172 static jboolean android_view_RenderNode_hasShadow(jlong renderNodePtr) {
173     RenderNode* renderNode = reinterpret_cast<RenderNode*>(renderNodePtr);
174     return renderNode->stagingProperties().hasShadow();
175 }
176 
android_view_RenderNode_setSpotShadowColor(jlong renderNodePtr,jint shadowColor)177 static jboolean android_view_RenderNode_setSpotShadowColor(jlong renderNodePtr, jint shadowColor) {
178     return SET_AND_DIRTY(setSpotShadowColor,
179             static_cast<SkColor>(shadowColor), RenderNode::GENERIC);
180 }
181 
android_view_RenderNode_getSpotShadowColor(jlong renderNodePtr)182 static jint android_view_RenderNode_getSpotShadowColor(jlong renderNodePtr) {
183     RenderNode* renderNode = reinterpret_cast<RenderNode*>(renderNodePtr);
184     return renderNode->stagingProperties().getSpotShadowColor();
185 }
186 
android_view_RenderNode_setAmbientShadowColor(jlong renderNodePtr,jint shadowColor)187 static jboolean android_view_RenderNode_setAmbientShadowColor(jlong renderNodePtr,
188         jint shadowColor) {
189     return SET_AND_DIRTY(setAmbientShadowColor,
190             static_cast<SkColor>(shadowColor), RenderNode::GENERIC);
191 }
192 
android_view_RenderNode_getAmbientShadowColor(jlong renderNodePtr)193 static jint android_view_RenderNode_getAmbientShadowColor(jlong renderNodePtr) {
194     RenderNode* renderNode = reinterpret_cast<RenderNode*>(renderNodePtr);
195     return renderNode->stagingProperties().getAmbientShadowColor();
196 }
197 
android_view_RenderNode_setClipToOutline(jlong renderNodePtr,jboolean clipToOutline)198 static jboolean android_view_RenderNode_setClipToOutline(jlong renderNodePtr,
199         jboolean clipToOutline) {
200     RenderNode* renderNode = reinterpret_cast<RenderNode*>(renderNodePtr);
201     renderNode->mutateStagingProperties().mutableOutline().setShouldClip(clipToOutline);
202     renderNode->setPropertyFieldsDirty(RenderNode::GENERIC);
203     return true;
204 }
205 
android_view_RenderNode_setRevealClip(jlong renderNodePtr,jboolean shouldClip,jfloat x,jfloat y,jfloat radius)206 static jboolean android_view_RenderNode_setRevealClip(jlong renderNodePtr, jboolean shouldClip,
207         jfloat x, jfloat y, jfloat radius) {
208     RenderNode* renderNode = reinterpret_cast<RenderNode*>(renderNodePtr);
209     renderNode->mutateStagingProperties().mutableRevealClip().set(
210             shouldClip, x, y, radius);
211     renderNode->setPropertyFieldsDirty(RenderNode::GENERIC);
212     return true;
213 }
214 
android_view_RenderNode_setAlpha(jlong renderNodePtr,float alpha)215 static jboolean android_view_RenderNode_setAlpha(jlong renderNodePtr, float alpha) {
216     return SET_AND_DIRTY(setAlpha, alpha, RenderNode::ALPHA);
217 }
218 
android_view_RenderNode_setHasOverlappingRendering(jlong renderNodePtr,bool hasOverlappingRendering)219 static jboolean android_view_RenderNode_setHasOverlappingRendering(jlong renderNodePtr,
220         bool hasOverlappingRendering) {
221     return SET_AND_DIRTY(setHasOverlappingRendering, hasOverlappingRendering,
222             RenderNode::GENERIC);
223 }
224 
android_view_RenderNode_setElevation(jlong renderNodePtr,float elevation)225 static jboolean android_view_RenderNode_setElevation(jlong renderNodePtr, float elevation) {
226     return SET_AND_DIRTY(setElevation, elevation, RenderNode::Z);
227 }
228 
android_view_RenderNode_setTranslationX(jlong renderNodePtr,float tx)229 static jboolean android_view_RenderNode_setTranslationX(jlong renderNodePtr, float tx) {
230     return SET_AND_DIRTY(setTranslationX, tx, RenderNode::TRANSLATION_X | RenderNode::X);
231 }
232 
android_view_RenderNode_setTranslationY(jlong renderNodePtr,float ty)233 static jboolean android_view_RenderNode_setTranslationY(jlong renderNodePtr, float ty) {
234     return SET_AND_DIRTY(setTranslationY, ty, RenderNode::TRANSLATION_Y | RenderNode::Y);
235 }
236 
android_view_RenderNode_setTranslationZ(jlong renderNodePtr,float tz)237 static jboolean android_view_RenderNode_setTranslationZ(jlong renderNodePtr, float tz) {
238     return SET_AND_DIRTY(setTranslationZ, tz, RenderNode::TRANSLATION_Z | RenderNode::Z);
239 }
240 
android_view_RenderNode_setRotation(jlong renderNodePtr,float rotation)241 static jboolean android_view_RenderNode_setRotation(jlong renderNodePtr, float rotation) {
242     return SET_AND_DIRTY(setRotation, rotation, RenderNode::ROTATION);
243 }
244 
android_view_RenderNode_setRotationX(jlong renderNodePtr,float rx)245 static jboolean android_view_RenderNode_setRotationX(jlong renderNodePtr, float rx) {
246     return SET_AND_DIRTY(setRotationX, rx, RenderNode::ROTATION_X);
247 }
248 
android_view_RenderNode_setRotationY(jlong renderNodePtr,float ry)249 static jboolean android_view_RenderNode_setRotationY(jlong renderNodePtr, float ry) {
250     return SET_AND_DIRTY(setRotationY, ry, RenderNode::ROTATION_Y);
251 }
252 
android_view_RenderNode_setScaleX(jlong renderNodePtr,float sx)253 static jboolean android_view_RenderNode_setScaleX(jlong renderNodePtr, float sx) {
254     return SET_AND_DIRTY(setScaleX, sx, RenderNode::SCALE_X);
255 }
256 
android_view_RenderNode_setScaleY(jlong renderNodePtr,float sy)257 static jboolean android_view_RenderNode_setScaleY(jlong renderNodePtr, float sy) {
258     return SET_AND_DIRTY(setScaleY, sy, RenderNode::SCALE_Y);
259 }
260 
android_view_RenderNode_setPivotX(jlong renderNodePtr,float px)261 static jboolean android_view_RenderNode_setPivotX(jlong renderNodePtr, float px) {
262     return SET_AND_DIRTY(setPivotX, px, RenderNode::GENERIC);
263 }
264 
android_view_RenderNode_setPivotY(jlong renderNodePtr,float py)265 static jboolean android_view_RenderNode_setPivotY(jlong renderNodePtr, float py) {
266     return SET_AND_DIRTY(setPivotY, py, RenderNode::GENERIC);
267 }
268 
android_view_RenderNode_resetPivot(jlong renderNodePtr)269 static jboolean android_view_RenderNode_resetPivot(jlong renderNodePtr) {
270     return SET_AND_DIRTY(resetPivot, /* void */, RenderNode::GENERIC);
271 }
272 
android_view_RenderNode_setCameraDistance(jlong renderNodePtr,float distance)273 static jboolean android_view_RenderNode_setCameraDistance(jlong renderNodePtr, float distance) {
274     return SET_AND_DIRTY(setCameraDistance, distance, RenderNode::GENERIC);
275 }
276 
android_view_RenderNode_setLeft(jlong renderNodePtr,int left)277 static jboolean android_view_RenderNode_setLeft(jlong renderNodePtr, int left) {
278     return SET_AND_DIRTY(setLeft, left, RenderNode::X);
279 }
280 
android_view_RenderNode_setTop(jlong renderNodePtr,int top)281 static jboolean android_view_RenderNode_setTop(jlong renderNodePtr, int top) {
282     return SET_AND_DIRTY(setTop, top, RenderNode::Y);
283 }
284 
android_view_RenderNode_setRight(jlong renderNodePtr,int right)285 static jboolean android_view_RenderNode_setRight(jlong renderNodePtr, int right) {
286     return SET_AND_DIRTY(setRight, right, RenderNode::X);
287 }
288 
android_view_RenderNode_setBottom(jlong renderNodePtr,int bottom)289 static jboolean android_view_RenderNode_setBottom(jlong renderNodePtr, int bottom) {
290     return SET_AND_DIRTY(setBottom, bottom, RenderNode::Y);
291 }
292 
android_view_RenderNode_setLeftTopRightBottom(jlong renderNodePtr,int left,int top,int right,int bottom)293 static jboolean android_view_RenderNode_setLeftTopRightBottom(jlong renderNodePtr,
294         int left, int top, int right, int bottom) {
295     RenderNode* renderNode = reinterpret_cast<RenderNode*>(renderNodePtr);
296     if (renderNode->mutateStagingProperties().setLeftTopRightBottom(left, top, right, bottom)) {
297         renderNode->setPropertyFieldsDirty(RenderNode::X | RenderNode::Y);
298         return true;
299     }
300     return false;
301 }
302 
android_view_RenderNode_offsetLeftAndRight(jlong renderNodePtr,jint offset)303 static jboolean android_view_RenderNode_offsetLeftAndRight(jlong renderNodePtr, jint offset) {
304     return SET_AND_DIRTY(offsetLeftRight, offset, RenderNode::X);
305 }
306 
android_view_RenderNode_offsetTopAndBottom(jlong renderNodePtr,jint offset)307 static jboolean android_view_RenderNode_offsetTopAndBottom(jlong renderNodePtr, jint offset) {
308     return SET_AND_DIRTY(offsetTopBottom, offset, RenderNode::Y);
309 }
310 
311 // ----------------------------------------------------------------------------
312 // RenderProperties - getters
313 // ----------------------------------------------------------------------------
314 
android_view_RenderNode_hasOverlappingRendering(jlong renderNodePtr)315 static jboolean android_view_RenderNode_hasOverlappingRendering(jlong renderNodePtr) {
316     RenderNode* renderNode = reinterpret_cast<RenderNode*>(renderNodePtr);
317     return renderNode->stagingProperties().hasOverlappingRendering();
318 }
319 
android_view_RenderNode_getClipToOutline(jlong renderNodePtr)320 static jboolean android_view_RenderNode_getClipToOutline(jlong renderNodePtr) {
321     RenderNode* renderNode = reinterpret_cast<RenderNode*>(renderNodePtr);
322     return renderNode->stagingProperties().getOutline().getShouldClip();
323 }
324 
android_view_RenderNode_getAlpha(jlong renderNodePtr)325 static jfloat android_view_RenderNode_getAlpha(jlong renderNodePtr) {
326     RenderNode* renderNode = reinterpret_cast<RenderNode*>(renderNodePtr);
327     return renderNode->stagingProperties().getAlpha();
328 }
329 
android_view_RenderNode_getCameraDistance(jlong renderNodePtr)330 static jfloat android_view_RenderNode_getCameraDistance(jlong renderNodePtr) {
331     RenderNode* renderNode = reinterpret_cast<RenderNode*>(renderNodePtr);
332     return renderNode->stagingProperties().getCameraDistance();
333 }
334 
android_view_RenderNode_getScaleX(jlong renderNodePtr)335 static jfloat android_view_RenderNode_getScaleX(jlong renderNodePtr) {
336     RenderNode* renderNode = reinterpret_cast<RenderNode*>(renderNodePtr);
337     return renderNode->stagingProperties().getScaleX();
338 }
339 
android_view_RenderNode_getScaleY(jlong renderNodePtr)340 static jfloat android_view_RenderNode_getScaleY(jlong renderNodePtr) {
341     RenderNode* renderNode = reinterpret_cast<RenderNode*>(renderNodePtr);
342     return renderNode->stagingProperties().getScaleY();
343 }
344 
android_view_RenderNode_getElevation(jlong renderNodePtr)345 static jfloat android_view_RenderNode_getElevation(jlong renderNodePtr) {
346     RenderNode* renderNode = reinterpret_cast<RenderNode*>(renderNodePtr);
347     return renderNode->stagingProperties().getElevation();
348 }
349 
android_view_RenderNode_getTranslationX(jlong renderNodePtr)350 static jfloat android_view_RenderNode_getTranslationX(jlong renderNodePtr) {
351     RenderNode* renderNode = reinterpret_cast<RenderNode*>(renderNodePtr);
352     return renderNode->stagingProperties().getTranslationX();
353 }
354 
android_view_RenderNode_getTranslationY(jlong renderNodePtr)355 static jfloat android_view_RenderNode_getTranslationY(jlong renderNodePtr) {
356     RenderNode* renderNode = reinterpret_cast<RenderNode*>(renderNodePtr);
357     return renderNode->stagingProperties().getTranslationY();
358 }
359 
android_view_RenderNode_getTranslationZ(jlong renderNodePtr)360 static jfloat android_view_RenderNode_getTranslationZ(jlong renderNodePtr) {
361     RenderNode* renderNode = reinterpret_cast<RenderNode*>(renderNodePtr);
362     return renderNode->stagingProperties().getTranslationZ();
363 }
364 
android_view_RenderNode_getRotation(jlong renderNodePtr)365 static jfloat android_view_RenderNode_getRotation(jlong renderNodePtr) {
366     RenderNode* renderNode = reinterpret_cast<RenderNode*>(renderNodePtr);
367     return renderNode->stagingProperties().getRotation();
368 }
369 
android_view_RenderNode_getRotationX(jlong renderNodePtr)370 static jfloat android_view_RenderNode_getRotationX(jlong renderNodePtr) {
371     RenderNode* renderNode = reinterpret_cast<RenderNode*>(renderNodePtr);
372     return renderNode->stagingProperties().getRotationX();
373 }
374 
android_view_RenderNode_getRotationY(jlong renderNodePtr)375 static jfloat android_view_RenderNode_getRotationY(jlong renderNodePtr) {
376     RenderNode* renderNode = reinterpret_cast<RenderNode*>(renderNodePtr);
377     return renderNode->stagingProperties().getRotationY();
378 }
379 
android_view_RenderNode_isPivotExplicitlySet(jlong renderNodePtr)380 static jboolean android_view_RenderNode_isPivotExplicitlySet(jlong renderNodePtr) {
381     RenderNode* renderNode = reinterpret_cast<RenderNode*>(renderNodePtr);
382     return renderNode->stagingProperties().isPivotExplicitlySet();
383 }
384 
android_view_RenderNode_hasIdentityMatrix(jlong renderNodePtr)385 static jboolean android_view_RenderNode_hasIdentityMatrix(jlong renderNodePtr) {
386     RenderNode* renderNode = reinterpret_cast<RenderNode*>(renderNodePtr);
387     renderNode->mutateStagingProperties().updateMatrix();
388     return !renderNode->stagingProperties().hasTransformMatrix();
389 }
390 
391 // ----------------------------------------------------------------------------
392 // RenderProperties - computed getters
393 // ----------------------------------------------------------------------------
394 
android_view_RenderNode_getTransformMatrix(jlong renderNodePtr,jlong outMatrixPtr)395 static void android_view_RenderNode_getTransformMatrix(jlong renderNodePtr, jlong outMatrixPtr) {
396     RenderNode* renderNode = reinterpret_cast<RenderNode*>(renderNodePtr);
397     SkMatrix* outMatrix = reinterpret_cast<SkMatrix*>(outMatrixPtr);
398 
399     renderNode->mutateStagingProperties().updateMatrix();
400     const SkMatrix* transformMatrix = renderNode->stagingProperties().getTransformMatrix();
401 
402     if (transformMatrix) {
403         *outMatrix = *transformMatrix;
404     } else {
405         outMatrix->setIdentity();
406     }
407 }
408 
android_view_RenderNode_getInverseTransformMatrix(jlong renderNodePtr,jlong outMatrixPtr)409 static void android_view_RenderNode_getInverseTransformMatrix(jlong renderNodePtr,
410         jlong outMatrixPtr) {
411     // load transform matrix
412     android_view_RenderNode_getTransformMatrix(renderNodePtr, outMatrixPtr);
413     SkMatrix* outMatrix = reinterpret_cast<SkMatrix*>(outMatrixPtr);
414 
415     // return it inverted
416     if (!outMatrix->invert(outMatrix)) {
417         // failed to load inverse, pass back identity
418         outMatrix->setIdentity();
419     }
420 }
421 
android_view_RenderNode_getPivotX(jlong renderNodePtr)422 static jfloat android_view_RenderNode_getPivotX(jlong renderNodePtr) {
423     RenderNode* renderNode = reinterpret_cast<RenderNode*>(renderNodePtr);
424     renderNode->mutateStagingProperties().updateMatrix();
425     return renderNode->stagingProperties().getPivotX();
426 }
427 
android_view_RenderNode_getPivotY(jlong renderNodePtr)428 static jfloat android_view_RenderNode_getPivotY(jlong renderNodePtr) {
429     RenderNode* renderNode = reinterpret_cast<RenderNode*>(renderNodePtr);
430     renderNode->mutateStagingProperties().updateMatrix();
431     return renderNode->stagingProperties().getPivotY();
432 }
433 
434 // ----------------------------------------------------------------------------
435 // RenderProperties - Animations
436 // ----------------------------------------------------------------------------
437 
android_view_RenderNode_addAnimator(JNIEnv * env,jobject clazz,jlong renderNodePtr,jlong animatorPtr)438 static void android_view_RenderNode_addAnimator(JNIEnv* env, jobject clazz, jlong renderNodePtr,
439         jlong animatorPtr) {
440     RenderNode* renderNode = reinterpret_cast<RenderNode*>(renderNodePtr);
441     RenderPropertyAnimator* animator = reinterpret_cast<RenderPropertyAnimator*>(animatorPtr);
442     renderNode->addAnimator(animator);
443 }
444 
android_view_RenderNode_endAllAnimators(JNIEnv * env,jobject clazz,jlong renderNodePtr)445 static void android_view_RenderNode_endAllAnimators(JNIEnv* env, jobject clazz,
446         jlong renderNodePtr) {
447     RenderNode* renderNode = reinterpret_cast<RenderNode*>(renderNodePtr);
448     renderNode->animators().endAllStagingAnimators();
449 }
450 
451 // ----------------------------------------------------------------------------
452 // SurfaceView position callback
453 // ----------------------------------------------------------------------------
454 
455 jmethodID gSurfaceViewPositionUpdateMethod;
456 jmethodID gSurfaceViewPositionLostMethod;
457 
android_view_RenderNode_requestPositionUpdates(JNIEnv * env,jobject,jlong renderNodePtr,jobject surfaceview)458 static void android_view_RenderNode_requestPositionUpdates(JNIEnv* env, jobject,
459         jlong renderNodePtr, jobject surfaceview) {
460     class SurfaceViewPositionUpdater : public RenderNode::PositionListener {
461     public:
462         SurfaceViewPositionUpdater(JNIEnv* env, jobject surfaceview) {
463             env->GetJavaVM(&mVm);
464             mWeakRef = env->NewWeakGlobalRef(surfaceview);
465         }
466 
467         virtual ~SurfaceViewPositionUpdater() {
468             jnienv()->DeleteWeakGlobalRef(mWeakRef);
469             mWeakRef = nullptr;
470         }
471 
472         virtual void onPositionUpdated(RenderNode& node, const TreeInfo& info) override {
473             if (CC_UNLIKELY(!mWeakRef || !info.updateWindowPositions)) return;
474 
475             Matrix4 transform;
476             info.damageAccumulator->computeCurrentTransform(&transform);
477             const RenderProperties& props = node.properties();
478             uirenderer::Rect bounds(props.getWidth(), props.getHeight());
479             transform.mapRect(bounds);
480 
481             if (CC_LIKELY(transform.isPureTranslate())) {
482                 // snap/round the computed bounds, so they match the rounding behavior
483                 // of the clear done in SurfaceView#draw().
484                 bounds.snapToPixelBoundaries();
485             } else {
486                 // Conservatively round out so the punched hole (in the ZOrderOnTop = true case)
487                 // doesn't extend beyond the other window
488                 bounds.roundOut();
489             }
490 
491             incStrong(0);
492             auto functor = std::bind(
493                 std::mem_fn(&SurfaceViewPositionUpdater::doUpdatePositionAsync), this,
494                 (jlong) info.canvasContext.getFrameNumber(),
495                 (jint) bounds.left, (jint) bounds.top,
496                 (jint) bounds.right, (jint) bounds.bottom);
497 
498             info.canvasContext.enqueueFrameWork(std::move(functor));
499         }
500 
501         virtual void onPositionLost(RenderNode& node, const TreeInfo* info) override {
502             if (CC_UNLIKELY(!mWeakRef || (info && !info->updateWindowPositions))) return;
503 
504             ATRACE_NAME("SurfaceView position lost");
505             JNIEnv* env = jnienv();
506             jobject localref = env->NewLocalRef(mWeakRef);
507             if (CC_UNLIKELY(!localref)) {
508                 jnienv()->DeleteWeakGlobalRef(mWeakRef);
509                 mWeakRef = nullptr;
510                 return;
511             }
512 
513             env->CallVoidMethod(localref, gSurfaceViewPositionLostMethod,
514                     info ? info->canvasContext.getFrameNumber() : 0);
515             env->DeleteLocalRef(localref);
516         }
517 
518     private:
519         JNIEnv* jnienv() {
520             JNIEnv* env;
521             if (mVm->GetEnv(reinterpret_cast<void**>(&env), JNI_VERSION_1_6) != JNI_OK) {
522                 LOG_ALWAYS_FATAL("Failed to get JNIEnv for JavaVM: %p", mVm);
523             }
524             return env;
525         }
526 
527         void doUpdatePositionAsync(jlong frameNumber, jint left, jint top,
528                 jint right, jint bottom) {
529             ATRACE_NAME("Update SurfaceView position");
530 
531             JNIEnv* env = jnienv();
532             jobject localref = env->NewLocalRef(mWeakRef);
533             if (CC_UNLIKELY(!localref)) {
534                 env->DeleteWeakGlobalRef(mWeakRef);
535                 mWeakRef = nullptr;
536             } else {
537                 env->CallVoidMethod(localref, gSurfaceViewPositionUpdateMethod,
538                         frameNumber, left, top, right, bottom);
539                 env->DeleteLocalRef(localref);
540             }
541 
542             // We need to release ourselves here
543             decStrong(0);
544         }
545 
546         JavaVM* mVm;
547         jobject mWeakRef;
548     };
549 
550     RenderNode* renderNode = reinterpret_cast<RenderNode*>(renderNodePtr);
551     renderNode->setPositionListener(new SurfaceViewPositionUpdater(env, surfaceview));
552 }
553 
554 // ----------------------------------------------------------------------------
555 // JNI Glue
556 // ----------------------------------------------------------------------------
557 
558 const char* const kClassPathName = "android/view/RenderNode";
559 
560 static const JNINativeMethod gMethods[] = {
561 // ----------------------------------------------------------------------------
562 // Regular JNI
563 // ----------------------------------------------------------------------------
564     { "nCreate",               "(Ljava/lang/String;)J", (void*) android_view_RenderNode_create },
565     { "nGetNativeFinalizer",   "()J",    (void*) android_view_RenderNode_getNativeFinalizer },
566     { "nOutput",               "(J)V",    (void*) android_view_RenderNode_output },
567     { "nGetDebugSize",         "(J)I",    (void*) android_view_RenderNode_getDebugSize },
568     { "nAddAnimator",              "(JJ)V", (void*) android_view_RenderNode_addAnimator },
569     { "nEndAllAnimators",          "(J)V", (void*) android_view_RenderNode_endAllAnimators },
570     { "nRequestPositionUpdates",   "(JLandroid/view/SurfaceView;)V", (void*) android_view_RenderNode_requestPositionUpdates },
571     { "nSetDisplayList",       "(JJ)V",   (void*) android_view_RenderNode_setDisplayList },
572 
573 
574 // ----------------------------------------------------------------------------
575 // Fast JNI via @CriticalNative annotation in RenderNode.java
576 // ----------------------------------------------------------------------------
577     { "nSetDisplayList",       "(JJ)V",   (void*) android_view_RenderNode_setDisplayList },
578 
579 
580 // ----------------------------------------------------------------------------
581 // Critical JNI via @CriticalNative annotation in RenderNode.java
582 // ----------------------------------------------------------------------------
583     { "nIsValid",              "(J)Z",   (void*) android_view_RenderNode_isValid },
584     { "nSetLayerType",         "(JI)Z",  (void*) android_view_RenderNode_setLayerType },
585     { "nSetLayerPaint",        "(JJ)Z",  (void*) android_view_RenderNode_setLayerPaint },
586     { "nSetStaticMatrix",      "(JJ)Z",  (void*) android_view_RenderNode_setStaticMatrix },
587     { "nSetAnimationMatrix",   "(JJ)Z",  (void*) android_view_RenderNode_setAnimationMatrix },
588     { "nSetClipToBounds",      "(JZ)Z",  (void*) android_view_RenderNode_setClipToBounds },
589     { "nSetClipBounds",        "(JIIII)Z", (void*) android_view_RenderNode_setClipBounds },
590     { "nSetClipBoundsEmpty",   "(J)Z",   (void*) android_view_RenderNode_setClipBoundsEmpty },
591     { "nSetProjectBackwards",  "(JZ)Z",  (void*) android_view_RenderNode_setProjectBackwards },
592     { "nSetProjectionReceiver","(JZ)Z",  (void*) android_view_RenderNode_setProjectionReceiver },
593 
594     { "nSetOutlineRoundRect",  "(JIIIIFF)Z", (void*) android_view_RenderNode_setOutlineRoundRect },
595     { "nSetOutlineConvexPath", "(JJF)Z", (void*) android_view_RenderNode_setOutlineConvexPath },
596     { "nSetOutlineEmpty",      "(J)Z",   (void*) android_view_RenderNode_setOutlineEmpty },
597     { "nSetOutlineNone",       "(J)Z",   (void*) android_view_RenderNode_setOutlineNone },
598     { "nHasShadow",            "(J)Z",   (void*) android_view_RenderNode_hasShadow },
599     { "nSetSpotShadowColor",   "(JI)Z",  (void*) android_view_RenderNode_setSpotShadowColor },
600     { "nGetSpotShadowColor",   "(J)I",   (void*) android_view_RenderNode_getSpotShadowColor },
601     { "nSetAmbientShadowColor","(JI)Z",  (void*) android_view_RenderNode_setAmbientShadowColor },
602     { "nGetAmbientShadowColor","(J)I",   (void*) android_view_RenderNode_getAmbientShadowColor },
603     { "nSetClipToOutline",     "(JZ)Z",  (void*) android_view_RenderNode_setClipToOutline },
604     { "nSetRevealClip",        "(JZFFF)Z", (void*) android_view_RenderNode_setRevealClip },
605 
606     { "nSetAlpha",             "(JF)Z",  (void*) android_view_RenderNode_setAlpha },
607     { "nSetHasOverlappingRendering", "(JZ)Z",
608             (void*) android_view_RenderNode_setHasOverlappingRendering },
609     { "nSetElevation",         "(JF)Z",  (void*) android_view_RenderNode_setElevation },
610     { "nSetTranslationX",      "(JF)Z",  (void*) android_view_RenderNode_setTranslationX },
611     { "nSetTranslationY",      "(JF)Z",  (void*) android_view_RenderNode_setTranslationY },
612     { "nSetTranslationZ",      "(JF)Z",  (void*) android_view_RenderNode_setTranslationZ },
613     { "nSetRotation",          "(JF)Z",  (void*) android_view_RenderNode_setRotation },
614     { "nSetRotationX",         "(JF)Z",  (void*) android_view_RenderNode_setRotationX },
615     { "nSetRotationY",         "(JF)Z",  (void*) android_view_RenderNode_setRotationY },
616     { "nSetScaleX",            "(JF)Z",  (void*) android_view_RenderNode_setScaleX },
617     { "nSetScaleY",            "(JF)Z",  (void*) android_view_RenderNode_setScaleY },
618     { "nSetPivotX",            "(JF)Z",  (void*) android_view_RenderNode_setPivotX },
619     { "nSetPivotY",            "(JF)Z",  (void*) android_view_RenderNode_setPivotY },
620     { "nResetPivot",           "(J)Z",   (void*) android_view_RenderNode_resetPivot },
621     { "nSetCameraDistance",    "(JF)Z",  (void*) android_view_RenderNode_setCameraDistance },
622     { "nSetLeft",              "(JI)Z",  (void*) android_view_RenderNode_setLeft },
623     { "nSetTop",               "(JI)Z",  (void*) android_view_RenderNode_setTop },
624     { "nSetRight",             "(JI)Z",  (void*) android_view_RenderNode_setRight },
625     { "nSetBottom",            "(JI)Z",  (void*) android_view_RenderNode_setBottom },
626     { "nSetLeftTopRightBottom","(JIIII)Z", (void*) android_view_RenderNode_setLeftTopRightBottom },
627     { "nOffsetLeftAndRight",   "(JI)Z",  (void*) android_view_RenderNode_offsetLeftAndRight },
628     { "nOffsetTopAndBottom",   "(JI)Z",  (void*) android_view_RenderNode_offsetTopAndBottom },
629 
630     { "nHasOverlappingRendering", "(J)Z",  (void*) android_view_RenderNode_hasOverlappingRendering },
631     { "nGetClipToOutline",        "(J)Z",  (void*) android_view_RenderNode_getClipToOutline },
632     { "nGetAlpha",                "(J)F",  (void*) android_view_RenderNode_getAlpha },
633     { "nGetCameraDistance",       "(J)F",  (void*) android_view_RenderNode_getCameraDistance },
634     { "nGetScaleX",               "(J)F",  (void*) android_view_RenderNode_getScaleX },
635     { "nGetScaleY",               "(J)F",  (void*) android_view_RenderNode_getScaleY },
636     { "nGetElevation",            "(J)F",  (void*) android_view_RenderNode_getElevation },
637     { "nGetTranslationX",         "(J)F",  (void*) android_view_RenderNode_getTranslationX },
638     { "nGetTranslationY",         "(J)F",  (void*) android_view_RenderNode_getTranslationY },
639     { "nGetTranslationZ",         "(J)F",  (void*) android_view_RenderNode_getTranslationZ },
640     { "nGetRotation",             "(J)F",  (void*) android_view_RenderNode_getRotation },
641     { "nGetRotationX",            "(J)F",  (void*) android_view_RenderNode_getRotationX },
642     { "nGetRotationY",            "(J)F",  (void*) android_view_RenderNode_getRotationY },
643     { "nIsPivotExplicitlySet",    "(J)Z",  (void*) android_view_RenderNode_isPivotExplicitlySet },
644     { "nHasIdentityMatrix",       "(J)Z",  (void*) android_view_RenderNode_hasIdentityMatrix },
645 
646     { "nGetTransformMatrix",       "(JJ)V", (void*) android_view_RenderNode_getTransformMatrix },
647     { "nGetInverseTransformMatrix","(JJ)V", (void*) android_view_RenderNode_getInverseTransformMatrix },
648 
649     { "nGetPivotX",                "(J)F",  (void*) android_view_RenderNode_getPivotX },
650     { "nGetPivotY",                "(J)F",  (void*) android_view_RenderNode_getPivotY },
651 };
652 
register_android_view_RenderNode(JNIEnv * env)653 int register_android_view_RenderNode(JNIEnv* env) {
654     jclass clazz = FindClassOrDie(env, "android/view/SurfaceView");
655     gSurfaceViewPositionUpdateMethod = GetMethodIDOrDie(env, clazz,
656             "updateSurfacePosition_renderWorker", "(JIIII)V");
657     gSurfaceViewPositionLostMethod = GetMethodIDOrDie(env, clazz,
658             "surfacePositionLost_uiRtSync", "(J)V");
659     return RegisterMethodsOrDie(env, kClassPathName, gMethods, NELEM(gMethods));
660 }
661 
662 };
663 
664