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