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