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_setClipToOutline(jlong renderNodePtr,jboolean clipToOutline)177 static jboolean android_view_RenderNode_setClipToOutline(jlong renderNodePtr,
178 jboolean clipToOutline) {
179 RenderNode* renderNode = reinterpret_cast<RenderNode*>(renderNodePtr);
180 renderNode->mutateStagingProperties().mutableOutline().setShouldClip(clipToOutline);
181 renderNode->setPropertyFieldsDirty(RenderNode::GENERIC);
182 return true;
183 }
184
android_view_RenderNode_setRevealClip(jlong renderNodePtr,jboolean shouldClip,jfloat x,jfloat y,jfloat radius)185 static jboolean android_view_RenderNode_setRevealClip(jlong renderNodePtr, jboolean shouldClip,
186 jfloat x, jfloat y, jfloat radius) {
187 RenderNode* renderNode = reinterpret_cast<RenderNode*>(renderNodePtr);
188 renderNode->mutateStagingProperties().mutableRevealClip().set(
189 shouldClip, x, y, radius);
190 renderNode->setPropertyFieldsDirty(RenderNode::GENERIC);
191 return true;
192 }
193
android_view_RenderNode_setAlpha(jlong renderNodePtr,float alpha)194 static jboolean android_view_RenderNode_setAlpha(jlong renderNodePtr, float alpha) {
195 return SET_AND_DIRTY(setAlpha, alpha, RenderNode::ALPHA);
196 }
197
android_view_RenderNode_setHasOverlappingRendering(jlong renderNodePtr,bool hasOverlappingRendering)198 static jboolean android_view_RenderNode_setHasOverlappingRendering(jlong renderNodePtr,
199 bool hasOverlappingRendering) {
200 return SET_AND_DIRTY(setHasOverlappingRendering, hasOverlappingRendering,
201 RenderNode::GENERIC);
202 }
203
android_view_RenderNode_setElevation(jlong renderNodePtr,float elevation)204 static jboolean android_view_RenderNode_setElevation(jlong renderNodePtr, float elevation) {
205 return SET_AND_DIRTY(setElevation, elevation, RenderNode::Z);
206 }
207
android_view_RenderNode_setTranslationX(jlong renderNodePtr,float tx)208 static jboolean android_view_RenderNode_setTranslationX(jlong renderNodePtr, float tx) {
209 return SET_AND_DIRTY(setTranslationX, tx, RenderNode::TRANSLATION_X | RenderNode::X);
210 }
211
android_view_RenderNode_setTranslationY(jlong renderNodePtr,float ty)212 static jboolean android_view_RenderNode_setTranslationY(jlong renderNodePtr, float ty) {
213 return SET_AND_DIRTY(setTranslationY, ty, RenderNode::TRANSLATION_Y | RenderNode::Y);
214 }
215
android_view_RenderNode_setTranslationZ(jlong renderNodePtr,float tz)216 static jboolean android_view_RenderNode_setTranslationZ(jlong renderNodePtr, float tz) {
217 return SET_AND_DIRTY(setTranslationZ, tz, RenderNode::TRANSLATION_Z | RenderNode::Z);
218 }
219
android_view_RenderNode_setRotation(jlong renderNodePtr,float rotation)220 static jboolean android_view_RenderNode_setRotation(jlong renderNodePtr, float rotation) {
221 return SET_AND_DIRTY(setRotation, rotation, RenderNode::ROTATION);
222 }
223
android_view_RenderNode_setRotationX(jlong renderNodePtr,float rx)224 static jboolean android_view_RenderNode_setRotationX(jlong renderNodePtr, float rx) {
225 return SET_AND_DIRTY(setRotationX, rx, RenderNode::ROTATION_X);
226 }
227
android_view_RenderNode_setRotationY(jlong renderNodePtr,float ry)228 static jboolean android_view_RenderNode_setRotationY(jlong renderNodePtr, float ry) {
229 return SET_AND_DIRTY(setRotationY, ry, RenderNode::ROTATION_Y);
230 }
231
android_view_RenderNode_setScaleX(jlong renderNodePtr,float sx)232 static jboolean android_view_RenderNode_setScaleX(jlong renderNodePtr, float sx) {
233 return SET_AND_DIRTY(setScaleX, sx, RenderNode::SCALE_X);
234 }
235
android_view_RenderNode_setScaleY(jlong renderNodePtr,float sy)236 static jboolean android_view_RenderNode_setScaleY(jlong renderNodePtr, float sy) {
237 return SET_AND_DIRTY(setScaleY, sy, RenderNode::SCALE_Y);
238 }
239
android_view_RenderNode_setPivotX(jlong renderNodePtr,float px)240 static jboolean android_view_RenderNode_setPivotX(jlong renderNodePtr, float px) {
241 return SET_AND_DIRTY(setPivotX, px, RenderNode::GENERIC);
242 }
243
android_view_RenderNode_setPivotY(jlong renderNodePtr,float py)244 static jboolean android_view_RenderNode_setPivotY(jlong renderNodePtr, float py) {
245 return SET_AND_DIRTY(setPivotY, py, RenderNode::GENERIC);
246 }
247
android_view_RenderNode_setCameraDistance(jlong renderNodePtr,float distance)248 static jboolean android_view_RenderNode_setCameraDistance(jlong renderNodePtr, float distance) {
249 return SET_AND_DIRTY(setCameraDistance, distance, RenderNode::GENERIC);
250 }
251
android_view_RenderNode_setLeft(jlong renderNodePtr,int left)252 static jboolean android_view_RenderNode_setLeft(jlong renderNodePtr, int left) {
253 return SET_AND_DIRTY(setLeft, left, RenderNode::X);
254 }
255
android_view_RenderNode_setTop(jlong renderNodePtr,int top)256 static jboolean android_view_RenderNode_setTop(jlong renderNodePtr, int top) {
257 return SET_AND_DIRTY(setTop, top, RenderNode::Y);
258 }
259
android_view_RenderNode_setRight(jlong renderNodePtr,int right)260 static jboolean android_view_RenderNode_setRight(jlong renderNodePtr, int right) {
261 return SET_AND_DIRTY(setRight, right, RenderNode::X);
262 }
263
android_view_RenderNode_setBottom(jlong renderNodePtr,int bottom)264 static jboolean android_view_RenderNode_setBottom(jlong renderNodePtr, int bottom) {
265 return SET_AND_DIRTY(setBottom, bottom, RenderNode::Y);
266 }
267
android_view_RenderNode_setLeftTopRightBottom(jlong renderNodePtr,int left,int top,int right,int bottom)268 static jboolean android_view_RenderNode_setLeftTopRightBottom(jlong renderNodePtr,
269 int left, int top, int right, int bottom) {
270 RenderNode* renderNode = reinterpret_cast<RenderNode*>(renderNodePtr);
271 if (renderNode->mutateStagingProperties().setLeftTopRightBottom(left, top, right, bottom)) {
272 renderNode->setPropertyFieldsDirty(RenderNode::X | RenderNode::Y);
273 return true;
274 }
275 return false;
276 }
277
android_view_RenderNode_offsetLeftAndRight(jlong renderNodePtr,jint offset)278 static jboolean android_view_RenderNode_offsetLeftAndRight(jlong renderNodePtr, jint offset) {
279 return SET_AND_DIRTY(offsetLeftRight, offset, RenderNode::X);
280 }
281
android_view_RenderNode_offsetTopAndBottom(jlong renderNodePtr,jint offset)282 static jboolean android_view_RenderNode_offsetTopAndBottom(jlong renderNodePtr, jint offset) {
283 return SET_AND_DIRTY(offsetTopBottom, offset, RenderNode::Y);
284 }
285
286 // ----------------------------------------------------------------------------
287 // RenderProperties - getters
288 // ----------------------------------------------------------------------------
289
android_view_RenderNode_hasOverlappingRendering(jlong renderNodePtr)290 static jboolean android_view_RenderNode_hasOverlappingRendering(jlong renderNodePtr) {
291 RenderNode* renderNode = reinterpret_cast<RenderNode*>(renderNodePtr);
292 return renderNode->stagingProperties().hasOverlappingRendering();
293 }
294
android_view_RenderNode_getClipToOutline(jlong renderNodePtr)295 static jboolean android_view_RenderNode_getClipToOutline(jlong renderNodePtr) {
296 RenderNode* renderNode = reinterpret_cast<RenderNode*>(renderNodePtr);
297 return renderNode->stagingProperties().getOutline().getShouldClip();
298 }
299
android_view_RenderNode_getAlpha(jlong renderNodePtr)300 static jfloat android_view_RenderNode_getAlpha(jlong renderNodePtr) {
301 RenderNode* renderNode = reinterpret_cast<RenderNode*>(renderNodePtr);
302 return renderNode->stagingProperties().getAlpha();
303 }
304
android_view_RenderNode_getCameraDistance(jlong renderNodePtr)305 static jfloat android_view_RenderNode_getCameraDistance(jlong renderNodePtr) {
306 RenderNode* renderNode = reinterpret_cast<RenderNode*>(renderNodePtr);
307 return renderNode->stagingProperties().getCameraDistance();
308 }
309
android_view_RenderNode_getScaleX(jlong renderNodePtr)310 static jfloat android_view_RenderNode_getScaleX(jlong renderNodePtr) {
311 RenderNode* renderNode = reinterpret_cast<RenderNode*>(renderNodePtr);
312 return renderNode->stagingProperties().getScaleX();
313 }
314
android_view_RenderNode_getScaleY(jlong renderNodePtr)315 static jfloat android_view_RenderNode_getScaleY(jlong renderNodePtr) {
316 RenderNode* renderNode = reinterpret_cast<RenderNode*>(renderNodePtr);
317 return renderNode->stagingProperties().getScaleY();
318 }
319
android_view_RenderNode_getElevation(jlong renderNodePtr)320 static jfloat android_view_RenderNode_getElevation(jlong renderNodePtr) {
321 RenderNode* renderNode = reinterpret_cast<RenderNode*>(renderNodePtr);
322 return renderNode->stagingProperties().getElevation();
323 }
324
android_view_RenderNode_getTranslationX(jlong renderNodePtr)325 static jfloat android_view_RenderNode_getTranslationX(jlong renderNodePtr) {
326 RenderNode* renderNode = reinterpret_cast<RenderNode*>(renderNodePtr);
327 return renderNode->stagingProperties().getTranslationX();
328 }
329
android_view_RenderNode_getTranslationY(jlong renderNodePtr)330 static jfloat android_view_RenderNode_getTranslationY(jlong renderNodePtr) {
331 RenderNode* renderNode = reinterpret_cast<RenderNode*>(renderNodePtr);
332 return renderNode->stagingProperties().getTranslationY();
333 }
334
android_view_RenderNode_getTranslationZ(jlong renderNodePtr)335 static jfloat android_view_RenderNode_getTranslationZ(jlong renderNodePtr) {
336 RenderNode* renderNode = reinterpret_cast<RenderNode*>(renderNodePtr);
337 return renderNode->stagingProperties().getTranslationZ();
338 }
339
android_view_RenderNode_getRotation(jlong renderNodePtr)340 static jfloat android_view_RenderNode_getRotation(jlong renderNodePtr) {
341 RenderNode* renderNode = reinterpret_cast<RenderNode*>(renderNodePtr);
342 return renderNode->stagingProperties().getRotation();
343 }
344
android_view_RenderNode_getRotationX(jlong renderNodePtr)345 static jfloat android_view_RenderNode_getRotationX(jlong renderNodePtr) {
346 RenderNode* renderNode = reinterpret_cast<RenderNode*>(renderNodePtr);
347 return renderNode->stagingProperties().getRotationX();
348 }
349
android_view_RenderNode_getRotationY(jlong renderNodePtr)350 static jfloat android_view_RenderNode_getRotationY(jlong renderNodePtr) {
351 RenderNode* renderNode = reinterpret_cast<RenderNode*>(renderNodePtr);
352 return renderNode->stagingProperties().getRotationY();
353 }
354
android_view_RenderNode_isPivotExplicitlySet(jlong renderNodePtr)355 static jboolean android_view_RenderNode_isPivotExplicitlySet(jlong renderNodePtr) {
356 RenderNode* renderNode = reinterpret_cast<RenderNode*>(renderNodePtr);
357 return renderNode->stagingProperties().isPivotExplicitlySet();
358 }
359
android_view_RenderNode_hasIdentityMatrix(jlong renderNodePtr)360 static jboolean android_view_RenderNode_hasIdentityMatrix(jlong renderNodePtr) {
361 RenderNode* renderNode = reinterpret_cast<RenderNode*>(renderNodePtr);
362 renderNode->mutateStagingProperties().updateMatrix();
363 return !renderNode->stagingProperties().hasTransformMatrix();
364 }
365
366 // ----------------------------------------------------------------------------
367 // RenderProperties - computed getters
368 // ----------------------------------------------------------------------------
369
android_view_RenderNode_getTransformMatrix(jlong renderNodePtr,jlong outMatrixPtr)370 static void android_view_RenderNode_getTransformMatrix(jlong renderNodePtr, jlong outMatrixPtr) {
371 RenderNode* renderNode = reinterpret_cast<RenderNode*>(renderNodePtr);
372 SkMatrix* outMatrix = reinterpret_cast<SkMatrix*>(outMatrixPtr);
373
374 renderNode->mutateStagingProperties().updateMatrix();
375 const SkMatrix* transformMatrix = renderNode->stagingProperties().getTransformMatrix();
376
377 if (transformMatrix) {
378 *outMatrix = *transformMatrix;
379 } else {
380 outMatrix->setIdentity();
381 }
382 }
383
android_view_RenderNode_getInverseTransformMatrix(jlong renderNodePtr,jlong outMatrixPtr)384 static void android_view_RenderNode_getInverseTransformMatrix(jlong renderNodePtr,
385 jlong outMatrixPtr) {
386 // load transform matrix
387 android_view_RenderNode_getTransformMatrix(renderNodePtr, outMatrixPtr);
388 SkMatrix* outMatrix = reinterpret_cast<SkMatrix*>(outMatrixPtr);
389
390 // return it inverted
391 if (!outMatrix->invert(outMatrix)) {
392 // failed to load inverse, pass back identity
393 outMatrix->setIdentity();
394 }
395 }
396
android_view_RenderNode_getPivotX(jlong renderNodePtr)397 static jfloat android_view_RenderNode_getPivotX(jlong renderNodePtr) {
398 RenderNode* renderNode = reinterpret_cast<RenderNode*>(renderNodePtr);
399 renderNode->mutateStagingProperties().updateMatrix();
400 return renderNode->stagingProperties().getPivotX();
401 }
402
android_view_RenderNode_getPivotY(jlong renderNodePtr)403 static jfloat android_view_RenderNode_getPivotY(jlong renderNodePtr) {
404 RenderNode* renderNode = reinterpret_cast<RenderNode*>(renderNodePtr);
405 renderNode->mutateStagingProperties().updateMatrix();
406 return renderNode->stagingProperties().getPivotY();
407 }
408
409 // ----------------------------------------------------------------------------
410 // RenderProperties - Animations
411 // ----------------------------------------------------------------------------
412
android_view_RenderNode_addAnimator(JNIEnv * env,jobject clazz,jlong renderNodePtr,jlong animatorPtr)413 static void android_view_RenderNode_addAnimator(JNIEnv* env, jobject clazz, jlong renderNodePtr,
414 jlong animatorPtr) {
415 RenderNode* renderNode = reinterpret_cast<RenderNode*>(renderNodePtr);
416 RenderPropertyAnimator* animator = reinterpret_cast<RenderPropertyAnimator*>(animatorPtr);
417 renderNode->addAnimator(animator);
418 }
419
android_view_RenderNode_endAllAnimators(JNIEnv * env,jobject clazz,jlong renderNodePtr)420 static void android_view_RenderNode_endAllAnimators(JNIEnv* env, jobject clazz,
421 jlong renderNodePtr) {
422 RenderNode* renderNode = reinterpret_cast<RenderNode*>(renderNodePtr);
423 renderNode->animators().endAllStagingAnimators();
424 }
425
426 // ----------------------------------------------------------------------------
427 // SurfaceView position callback
428 // ----------------------------------------------------------------------------
429
430 jmethodID gSurfaceViewPositionUpdateMethod;
431 jmethodID gSurfaceViewPositionLostMethod;
432
android_view_RenderNode_requestPositionUpdates(JNIEnv * env,jobject,jlong renderNodePtr,jobject surfaceview)433 static void android_view_RenderNode_requestPositionUpdates(JNIEnv* env, jobject,
434 jlong renderNodePtr, jobject surfaceview) {
435 class SurfaceViewPositionUpdater : public RenderNode::PositionListener {
436 public:
437 SurfaceViewPositionUpdater(JNIEnv* env, jobject surfaceview) {
438 env->GetJavaVM(&mVm);
439 mWeakRef = env->NewWeakGlobalRef(surfaceview);
440 }
441
442 virtual ~SurfaceViewPositionUpdater() {
443 jnienv()->DeleteWeakGlobalRef(mWeakRef);
444 mWeakRef = nullptr;
445 }
446
447 virtual void onPositionUpdated(RenderNode& node, const TreeInfo& info) override {
448 if (CC_UNLIKELY(!mWeakRef || !info.updateWindowPositions)) return;
449
450 Matrix4 transform;
451 info.damageAccumulator->computeCurrentTransform(&transform);
452 const RenderProperties& props = node.properties();
453 uirenderer::Rect bounds(props.getWidth(), props.getHeight());
454 transform.mapRect(bounds);
455
456 if (CC_LIKELY(transform.isPureTranslate())) {
457 // snap/round the computed bounds, so they match the rounding behavior
458 // of the clear done in SurfaceView#draw().
459 bounds.snapToPixelBoundaries();
460 } else {
461 // Conservatively round out so the punched hole (in the ZOrderOnTop = true case)
462 // doesn't extend beyond the other window
463 bounds.roundOut();
464 }
465
466 incStrong(0);
467 auto functor = std::bind(
468 std::mem_fn(&SurfaceViewPositionUpdater::doUpdatePositionAsync), this,
469 (jlong) info.canvasContext.getFrameNumber(),
470 (jint) bounds.left, (jint) bounds.top,
471 (jint) bounds.right, (jint) bounds.bottom);
472
473 info.canvasContext.enqueueFrameWork(std::move(functor));
474 }
475
476 virtual void onPositionLost(RenderNode& node, const TreeInfo* info) override {
477 if (CC_UNLIKELY(!mWeakRef || (info && !info->updateWindowPositions))) return;
478
479 ATRACE_NAME("SurfaceView position lost");
480 JNIEnv* env = jnienv();
481 jobject localref = env->NewLocalRef(mWeakRef);
482 if (CC_UNLIKELY(!localref)) {
483 jnienv()->DeleteWeakGlobalRef(mWeakRef);
484 mWeakRef = nullptr;
485 return;
486 }
487
488 env->CallVoidMethod(localref, gSurfaceViewPositionLostMethod,
489 info ? info->canvasContext.getFrameNumber() : 0);
490 env->DeleteLocalRef(localref);
491 }
492
493 private:
494 JNIEnv* jnienv() {
495 JNIEnv* env;
496 if (mVm->GetEnv(reinterpret_cast<void**>(&env), JNI_VERSION_1_6) != JNI_OK) {
497 LOG_ALWAYS_FATAL("Failed to get JNIEnv for JavaVM: %p", mVm);
498 }
499 return env;
500 }
501
502 void doUpdatePositionAsync(jlong frameNumber, jint left, jint top,
503 jint right, jint bottom) {
504 ATRACE_NAME("Update SurfaceView position");
505
506 JNIEnv* env = jnienv();
507 jobject localref = env->NewLocalRef(mWeakRef);
508 if (CC_UNLIKELY(!localref)) {
509 env->DeleteWeakGlobalRef(mWeakRef);
510 mWeakRef = nullptr;
511 } else {
512 env->CallVoidMethod(localref, gSurfaceViewPositionUpdateMethod,
513 frameNumber, left, top, right, bottom);
514 env->DeleteLocalRef(localref);
515 }
516
517 // We need to release ourselves here
518 decStrong(0);
519 }
520
521 JavaVM* mVm;
522 jobject mWeakRef;
523 };
524
525 RenderNode* renderNode = reinterpret_cast<RenderNode*>(renderNodePtr);
526 renderNode->setPositionListener(new SurfaceViewPositionUpdater(env, surfaceview));
527 }
528
529 // ----------------------------------------------------------------------------
530 // JNI Glue
531 // ----------------------------------------------------------------------------
532
533 const char* const kClassPathName = "android/view/RenderNode";
534
535 static const JNINativeMethod gMethods[] = {
536 // ----------------------------------------------------------------------------
537 // Regular JNI
538 // ----------------------------------------------------------------------------
539 { "nCreate", "(Ljava/lang/String;)J", (void*) android_view_RenderNode_create },
540 { "nGetNativeFinalizer", "()J", (void*) android_view_RenderNode_getNativeFinalizer },
541 { "nOutput", "(J)V", (void*) android_view_RenderNode_output },
542 { "nGetDebugSize", "(J)I", (void*) android_view_RenderNode_getDebugSize },
543 { "nAddAnimator", "(JJ)V", (void*) android_view_RenderNode_addAnimator },
544 { "nEndAllAnimators", "(J)V", (void*) android_view_RenderNode_endAllAnimators },
545 { "nRequestPositionUpdates", "(JLandroid/view/SurfaceView;)V", (void*) android_view_RenderNode_requestPositionUpdates },
546 { "nSetDisplayList", "(JJ)V", (void*) android_view_RenderNode_setDisplayList },
547
548
549 // ----------------------------------------------------------------------------
550 // Fast JNI via @CriticalNative annotation in RenderNode.java
551 // ----------------------------------------------------------------------------
552 { "nSetDisplayList", "(JJ)V", (void*) android_view_RenderNode_setDisplayList },
553
554
555 // ----------------------------------------------------------------------------
556 // Critical JNI via @CriticalNative annotation in RenderNode.java
557 // ----------------------------------------------------------------------------
558 { "nIsValid", "(J)Z", (void*) android_view_RenderNode_isValid },
559 { "nSetLayerType", "(JI)Z", (void*) android_view_RenderNode_setLayerType },
560 { "nSetLayerPaint", "(JJ)Z", (void*) android_view_RenderNode_setLayerPaint },
561 { "nSetStaticMatrix", "(JJ)Z", (void*) android_view_RenderNode_setStaticMatrix },
562 { "nSetAnimationMatrix", "(JJ)Z", (void*) android_view_RenderNode_setAnimationMatrix },
563 { "nSetClipToBounds", "(JZ)Z", (void*) android_view_RenderNode_setClipToBounds },
564 { "nSetClipBounds", "(JIIII)Z", (void*) android_view_RenderNode_setClipBounds },
565 { "nSetClipBoundsEmpty", "(J)Z", (void*) android_view_RenderNode_setClipBoundsEmpty },
566 { "nSetProjectBackwards", "(JZ)Z", (void*) android_view_RenderNode_setProjectBackwards },
567 { "nSetProjectionReceiver","(JZ)Z", (void*) android_view_RenderNode_setProjectionReceiver },
568
569 { "nSetOutlineRoundRect", "(JIIIIFF)Z", (void*) android_view_RenderNode_setOutlineRoundRect },
570 { "nSetOutlineConvexPath", "(JJF)Z", (void*) android_view_RenderNode_setOutlineConvexPath },
571 { "nSetOutlineEmpty", "(J)Z", (void*) android_view_RenderNode_setOutlineEmpty },
572 { "nSetOutlineNone", "(J)Z", (void*) android_view_RenderNode_setOutlineNone },
573 { "nHasShadow", "(J)Z", (void*) android_view_RenderNode_hasShadow },
574 { "nSetClipToOutline", "(JZ)Z", (void*) android_view_RenderNode_setClipToOutline },
575 { "nSetRevealClip", "(JZFFF)Z", (void*) android_view_RenderNode_setRevealClip },
576
577 { "nSetAlpha", "(JF)Z", (void*) android_view_RenderNode_setAlpha },
578 { "nSetHasOverlappingRendering", "(JZ)Z",
579 (void*) android_view_RenderNode_setHasOverlappingRendering },
580 { "nSetElevation", "(JF)Z", (void*) android_view_RenderNode_setElevation },
581 { "nSetTranslationX", "(JF)Z", (void*) android_view_RenderNode_setTranslationX },
582 { "nSetTranslationY", "(JF)Z", (void*) android_view_RenderNode_setTranslationY },
583 { "nSetTranslationZ", "(JF)Z", (void*) android_view_RenderNode_setTranslationZ },
584 { "nSetRotation", "(JF)Z", (void*) android_view_RenderNode_setRotation },
585 { "nSetRotationX", "(JF)Z", (void*) android_view_RenderNode_setRotationX },
586 { "nSetRotationY", "(JF)Z", (void*) android_view_RenderNode_setRotationY },
587 { "nSetScaleX", "(JF)Z", (void*) android_view_RenderNode_setScaleX },
588 { "nSetScaleY", "(JF)Z", (void*) android_view_RenderNode_setScaleY },
589 { "nSetPivotX", "(JF)Z", (void*) android_view_RenderNode_setPivotX },
590 { "nSetPivotY", "(JF)Z", (void*) android_view_RenderNode_setPivotY },
591 { "nSetCameraDistance", "(JF)Z", (void*) android_view_RenderNode_setCameraDistance },
592 { "nSetLeft", "(JI)Z", (void*) android_view_RenderNode_setLeft },
593 { "nSetTop", "(JI)Z", (void*) android_view_RenderNode_setTop },
594 { "nSetRight", "(JI)Z", (void*) android_view_RenderNode_setRight },
595 { "nSetBottom", "(JI)Z", (void*) android_view_RenderNode_setBottom },
596 { "nSetLeftTopRightBottom","(JIIII)Z", (void*) android_view_RenderNode_setLeftTopRightBottom },
597 { "nOffsetLeftAndRight", "(JI)Z", (void*) android_view_RenderNode_offsetLeftAndRight },
598 { "nOffsetTopAndBottom", "(JI)Z", (void*) android_view_RenderNode_offsetTopAndBottom },
599
600 { "nHasOverlappingRendering", "(J)Z", (void*) android_view_RenderNode_hasOverlappingRendering },
601 { "nGetClipToOutline", "(J)Z", (void*) android_view_RenderNode_getClipToOutline },
602 { "nGetAlpha", "(J)F", (void*) android_view_RenderNode_getAlpha },
603 { "nGetCameraDistance", "(J)F", (void*) android_view_RenderNode_getCameraDistance },
604 { "nGetScaleX", "(J)F", (void*) android_view_RenderNode_getScaleX },
605 { "nGetScaleY", "(J)F", (void*) android_view_RenderNode_getScaleY },
606 { "nGetElevation", "(J)F", (void*) android_view_RenderNode_getElevation },
607 { "nGetTranslationX", "(J)F", (void*) android_view_RenderNode_getTranslationX },
608 { "nGetTranslationY", "(J)F", (void*) android_view_RenderNode_getTranslationY },
609 { "nGetTranslationZ", "(J)F", (void*) android_view_RenderNode_getTranslationZ },
610 { "nGetRotation", "(J)F", (void*) android_view_RenderNode_getRotation },
611 { "nGetRotationX", "(J)F", (void*) android_view_RenderNode_getRotationX },
612 { "nGetRotationY", "(J)F", (void*) android_view_RenderNode_getRotationY },
613 { "nIsPivotExplicitlySet", "(J)Z", (void*) android_view_RenderNode_isPivotExplicitlySet },
614 { "nHasIdentityMatrix", "(J)Z", (void*) android_view_RenderNode_hasIdentityMatrix },
615
616 { "nGetTransformMatrix", "(JJ)V", (void*) android_view_RenderNode_getTransformMatrix },
617 { "nGetInverseTransformMatrix","(JJ)V", (void*) android_view_RenderNode_getInverseTransformMatrix },
618
619 { "nGetPivotX", "(J)F", (void*) android_view_RenderNode_getPivotX },
620 { "nGetPivotY", "(J)F", (void*) android_view_RenderNode_getPivotY },
621 };
622
register_android_view_RenderNode(JNIEnv * env)623 int register_android_view_RenderNode(JNIEnv* env) {
624 jclass clazz = FindClassOrDie(env, "android/view/SurfaceView");
625 gSurfaceViewPositionUpdateMethod = GetMethodIDOrDie(env, clazz,
626 "updateSurfacePosition_renderWorker", "(JIIII)V");
627 gSurfaceViewPositionLostMethod = GetMethodIDOrDie(env, clazz,
628 "surfacePositionLost_uiRtSync", "(J)V");
629 return RegisterMethodsOrDie(env, kClassPathName, gMethods, NELEM(gMethods));
630 }
631
632 };
633
634