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 ATRACE_TAG ATRACE_TAG_VIEW
18 #include <Animator.h>
19 #include <DamageAccumulator.h>
20 #include <Matrix.h>
21 #include <RenderNode.h>
22 #include <TreeInfo.h>
23 #include <effects/StretchEffect.h>
24 #include <gui/TraceUtils.h>
25 #include <hwui/Paint.h>
26 #include <renderthread/CanvasContext.h>
27
28 #include "GraphicsJNI.h"
29
30 namespace android {
31
32 using namespace uirenderer;
33
34 #define SET_AND_DIRTY(prop, val, dirtyFlag) \
35 (reinterpret_cast<RenderNode*>(renderNodePtr)->mutateStagingProperties().prop(val) \
36 ? (reinterpret_cast<RenderNode*>(renderNodePtr)->setPropertyFieldsDirty(dirtyFlag), true) \
37 : false)
38
39 // ----------------------------------------------------------------------------
40 // DisplayList view properties
41 // ----------------------------------------------------------------------------
42
android_view_RenderNode_output(JNIEnv * env,jobject clazz,jlong renderNodePtr)43 static void android_view_RenderNode_output(JNIEnv* env, jobject clazz, jlong renderNodePtr) {
44 RenderNode* renderNode = reinterpret_cast<RenderNode*>(renderNodePtr);
45 renderNode->output();
46 }
47
android_view_RenderNode_getUsageSize(JNIEnv * env,jobject clazz,jlong renderNodePtr)48 static jint android_view_RenderNode_getUsageSize(JNIEnv* env, jobject clazz, jlong renderNodePtr) {
49 RenderNode* renderNode = reinterpret_cast<RenderNode*>(renderNodePtr);
50 return renderNode->getUsageSize();
51 }
52
android_view_RenderNode_getAllocatedSize(JNIEnv * env,jobject clazz,jlong renderNodePtr)53 static jint android_view_RenderNode_getAllocatedSize(JNIEnv* env, jobject clazz, jlong renderNodePtr) {
54 RenderNode* renderNode = reinterpret_cast<RenderNode*>(renderNodePtr);
55 return renderNode->getAllocatedSize();
56 }
57
android_view_RenderNode_create(JNIEnv * env,jobject,jstring name)58 static jlong android_view_RenderNode_create(JNIEnv* env, jobject, jstring name) {
59 RenderNode* renderNode = new RenderNode();
60 renderNode->incStrong(0);
61 if (name != NULL) {
62 const char* textArray = env->GetStringUTFChars(name, NULL);
63 renderNode->setName(textArray);
64 env->ReleaseStringUTFChars(name, textArray);
65 }
66 return reinterpret_cast<jlong>(renderNode);
67 }
68
releaseRenderNode(RenderNode * renderNode)69 static void releaseRenderNode(RenderNode* renderNode) {
70 renderNode->decStrong(0);
71 }
72
android_view_RenderNode_getNativeFinalizer(JNIEnv * env,jobject clazz)73 static jlong android_view_RenderNode_getNativeFinalizer(JNIEnv* env,
74 jobject clazz) {
75 return static_cast<jlong>(reinterpret_cast<uintptr_t>(&releaseRenderNode));
76 }
77
android_view_RenderNode_discardDisplayList(CRITICAL_JNI_PARAMS_COMMA jlong renderNodePtr)78 static void android_view_RenderNode_discardDisplayList(CRITICAL_JNI_PARAMS_COMMA jlong renderNodePtr) {
79 RenderNode* renderNode = reinterpret_cast<RenderNode*>(renderNodePtr);
80 renderNode->discardStagingDisplayList();
81 }
82
android_view_RenderNode_isValid(CRITICAL_JNI_PARAMS_COMMA jlong renderNodePtr)83 static jboolean android_view_RenderNode_isValid(CRITICAL_JNI_PARAMS_COMMA jlong renderNodePtr) {
84 return reinterpret_cast<RenderNode*>(renderNodePtr)->isValid();
85 }
86
87 // ----------------------------------------------------------------------------
88 // RenderProperties - setters
89 // ----------------------------------------------------------------------------
90
android_view_RenderNode_setLayerType(CRITICAL_JNI_PARAMS_COMMA jlong renderNodePtr,jint jlayerType)91 static jboolean android_view_RenderNode_setLayerType(CRITICAL_JNI_PARAMS_COMMA jlong renderNodePtr, jint jlayerType) {
92 LayerType layerType = static_cast<LayerType>(jlayerType);
93 return SET_AND_DIRTY(mutateLayerProperties().setType, layerType, RenderNode::GENERIC);
94 }
95
android_view_RenderNode_setLayerPaint(CRITICAL_JNI_PARAMS_COMMA jlong renderNodePtr,jlong paintPtr)96 static jboolean android_view_RenderNode_setLayerPaint(CRITICAL_JNI_PARAMS_COMMA jlong renderNodePtr, jlong paintPtr) {
97 Paint* paint = reinterpret_cast<Paint*>(paintPtr);
98 return SET_AND_DIRTY(mutateLayerProperties().setFromPaint, paint, RenderNode::GENERIC);
99 }
100
android_view_RenderNode_setStaticMatrix(CRITICAL_JNI_PARAMS_COMMA jlong renderNodePtr,jlong matrixPtr)101 static jboolean android_view_RenderNode_setStaticMatrix(CRITICAL_JNI_PARAMS_COMMA jlong renderNodePtr, jlong matrixPtr) {
102 SkMatrix* matrix = reinterpret_cast<SkMatrix*>(matrixPtr);
103 return SET_AND_DIRTY(setStaticMatrix, matrix, RenderNode::GENERIC);
104 }
105
android_view_RenderNode_setAnimationMatrix(CRITICAL_JNI_PARAMS_COMMA jlong renderNodePtr,jlong matrixPtr)106 static jboolean android_view_RenderNode_setAnimationMatrix(CRITICAL_JNI_PARAMS_COMMA jlong renderNodePtr, jlong matrixPtr) {
107 SkMatrix* matrix = reinterpret_cast<SkMatrix*>(matrixPtr);
108 return SET_AND_DIRTY(setAnimationMatrix, matrix, RenderNode::GENERIC);
109 }
110
android_view_RenderNode_setClipToBounds(CRITICAL_JNI_PARAMS_COMMA jlong renderNodePtr,jboolean clipToBounds)111 static jboolean android_view_RenderNode_setClipToBounds(CRITICAL_JNI_PARAMS_COMMA jlong renderNodePtr,
112 jboolean clipToBounds) {
113 return SET_AND_DIRTY(setClipToBounds, clipToBounds, RenderNode::GENERIC);
114 }
115
android_view_RenderNode_setClipBounds(CRITICAL_JNI_PARAMS_COMMA jlong renderNodePtr,jint left,jint top,jint right,jint bottom)116 static jboolean android_view_RenderNode_setClipBounds(CRITICAL_JNI_PARAMS_COMMA jlong renderNodePtr,
117 jint left, jint top, jint right, jint bottom) {
118 android::uirenderer::Rect clipBounds(left, top, right, bottom);
119 return SET_AND_DIRTY(setClipBounds, clipBounds, RenderNode::GENERIC);
120 }
121
android_view_RenderNode_setClipBoundsEmpty(CRITICAL_JNI_PARAMS_COMMA jlong renderNodePtr)122 static jboolean android_view_RenderNode_setClipBoundsEmpty(CRITICAL_JNI_PARAMS_COMMA jlong renderNodePtr) {
123 return SET_AND_DIRTY(setClipBoundsEmpty,, RenderNode::GENERIC);
124 }
125
android_view_RenderNode_setProjectBackwards(CRITICAL_JNI_PARAMS_COMMA jlong renderNodePtr,jboolean shouldProject)126 static jboolean android_view_RenderNode_setProjectBackwards(CRITICAL_JNI_PARAMS_COMMA jlong renderNodePtr,
127 jboolean shouldProject) {
128 return SET_AND_DIRTY(setProjectBackwards, shouldProject, RenderNode::GENERIC);
129 }
130
android_view_RenderNode_setProjectionReceiver(CRITICAL_JNI_PARAMS_COMMA jlong renderNodePtr,jboolean shouldRecieve)131 static jboolean android_view_RenderNode_setProjectionReceiver(CRITICAL_JNI_PARAMS_COMMA jlong renderNodePtr,
132 jboolean shouldRecieve) {
133 return SET_AND_DIRTY(setProjectionReceiver, shouldRecieve, RenderNode::GENERIC);
134 }
135
android_view_RenderNode_setOutlineRoundRect(CRITICAL_JNI_PARAMS_COMMA jlong renderNodePtr,jint left,jint top,jint right,jint bottom,jfloat radius,jfloat alpha)136 static jboolean android_view_RenderNode_setOutlineRoundRect(CRITICAL_JNI_PARAMS_COMMA jlong renderNodePtr,
137 jint left, jint top, jint right, jint bottom, jfloat radius, jfloat alpha) {
138 RenderNode* renderNode = reinterpret_cast<RenderNode*>(renderNodePtr);
139 renderNode->mutateStagingProperties().mutableOutline().setRoundRect(left, top, right, bottom,
140 radius, alpha);
141 renderNode->setPropertyFieldsDirty(RenderNode::GENERIC);
142 return true;
143 }
144
android_view_RenderNode_setOutlinePath(CRITICAL_JNI_PARAMS_COMMA jlong renderNodePtr,jlong outlinePathPtr,jfloat alpha)145 static jboolean android_view_RenderNode_setOutlinePath(CRITICAL_JNI_PARAMS_COMMA jlong renderNodePtr,
146 jlong outlinePathPtr, jfloat alpha) {
147 RenderNode* renderNode = reinterpret_cast<RenderNode*>(renderNodePtr);
148 SkPath* outlinePath = reinterpret_cast<SkPath*>(outlinePathPtr);
149 renderNode->mutateStagingProperties().mutableOutline().setPath(outlinePath, alpha);
150 renderNode->setPropertyFieldsDirty(RenderNode::GENERIC);
151 return true;
152 }
153
android_view_RenderNode_setOutlineEmpty(CRITICAL_JNI_PARAMS_COMMA jlong renderNodePtr)154 static jboolean android_view_RenderNode_setOutlineEmpty(CRITICAL_JNI_PARAMS_COMMA jlong renderNodePtr) {
155 RenderNode* renderNode = reinterpret_cast<RenderNode*>(renderNodePtr);
156 renderNode->mutateStagingProperties().mutableOutline().setEmpty();
157 renderNode->setPropertyFieldsDirty(RenderNode::GENERIC);
158 return true;
159 }
160
android_view_RenderNode_setOutlineNone(CRITICAL_JNI_PARAMS_COMMA jlong renderNodePtr)161 static jboolean android_view_RenderNode_setOutlineNone(CRITICAL_JNI_PARAMS_COMMA jlong renderNodePtr) {
162 RenderNode* renderNode = reinterpret_cast<RenderNode*>(renderNodePtr);
163 renderNode->mutateStagingProperties().mutableOutline().setNone();
164 renderNode->setPropertyFieldsDirty(RenderNode::GENERIC);
165 return true;
166 }
167
android_view_RenderNode_clearStretch(CRITICAL_JNI_PARAMS_COMMA jlong renderNodePtr)168 static jboolean android_view_RenderNode_clearStretch(CRITICAL_JNI_PARAMS_COMMA jlong renderNodePtr) {
169 RenderNode* renderNode = reinterpret_cast<RenderNode*>(renderNodePtr);
170 auto& stretch = renderNode->mutateStagingProperties()
171 .mutateLayerProperties().mutableStretchEffect();
172 if (stretch.isEmpty()) {
173 return false;
174 }
175 stretch.setEmpty();
176 renderNode->setPropertyFieldsDirty(RenderNode::GENERIC);
177 return true;
178 }
179
android_view_RenderNode_stretch(CRITICAL_JNI_PARAMS_COMMA jlong renderNodePtr,jfloat vX,jfloat vY,jfloat maxX,jfloat maxY)180 static jboolean android_view_RenderNode_stretch(CRITICAL_JNI_PARAMS_COMMA jlong renderNodePtr,
181 jfloat vX, jfloat vY, jfloat maxX,
182 jfloat maxY) {
183 auto* renderNode = reinterpret_cast<RenderNode*>(renderNodePtr);
184 StretchEffect effect = StretchEffect({.fX = vX, .fY = vY}, maxX, maxY);
185 renderNode->mutateStagingProperties().mutateLayerProperties().mutableStretchEffect().mergeWith(
186 effect);
187 renderNode->setPropertyFieldsDirty(RenderNode::GENERIC);
188 return true;
189 }
190
android_view_RenderNode_hasShadow(CRITICAL_JNI_PARAMS_COMMA jlong renderNodePtr)191 static jboolean android_view_RenderNode_hasShadow(CRITICAL_JNI_PARAMS_COMMA jlong renderNodePtr) {
192 RenderNode* renderNode = reinterpret_cast<RenderNode*>(renderNodePtr);
193 return renderNode->stagingProperties().hasShadow();
194 }
195
android_view_RenderNode_setSpotShadowColor(CRITICAL_JNI_PARAMS_COMMA jlong renderNodePtr,jint shadowColor)196 static jboolean android_view_RenderNode_setSpotShadowColor(CRITICAL_JNI_PARAMS_COMMA jlong renderNodePtr, jint shadowColor) {
197 return SET_AND_DIRTY(setSpotShadowColor,
198 static_cast<SkColor>(shadowColor), RenderNode::GENERIC);
199 }
200
android_view_RenderNode_getSpotShadowColor(CRITICAL_JNI_PARAMS_COMMA jlong renderNodePtr)201 static jint android_view_RenderNode_getSpotShadowColor(CRITICAL_JNI_PARAMS_COMMA jlong renderNodePtr) {
202 RenderNode* renderNode = reinterpret_cast<RenderNode*>(renderNodePtr);
203 return renderNode->stagingProperties().getSpotShadowColor();
204 }
205
android_view_RenderNode_setAmbientShadowColor(CRITICAL_JNI_PARAMS_COMMA jlong renderNodePtr,jint shadowColor)206 static jboolean android_view_RenderNode_setAmbientShadowColor(CRITICAL_JNI_PARAMS_COMMA jlong renderNodePtr,
207 jint shadowColor) {
208 return SET_AND_DIRTY(setAmbientShadowColor,
209 static_cast<SkColor>(shadowColor), RenderNode::GENERIC);
210 }
211
android_view_RenderNode_getAmbientShadowColor(CRITICAL_JNI_PARAMS_COMMA jlong renderNodePtr)212 static jint android_view_RenderNode_getAmbientShadowColor(CRITICAL_JNI_PARAMS_COMMA jlong renderNodePtr) {
213 RenderNode* renderNode = reinterpret_cast<RenderNode*>(renderNodePtr);
214 return renderNode->stagingProperties().getAmbientShadowColor();
215 }
216
android_view_RenderNode_setClipToOutline(CRITICAL_JNI_PARAMS_COMMA jlong renderNodePtr,jboolean clipToOutline)217 static jboolean android_view_RenderNode_setClipToOutline(CRITICAL_JNI_PARAMS_COMMA jlong renderNodePtr,
218 jboolean clipToOutline) {
219 RenderNode* renderNode = reinterpret_cast<RenderNode*>(renderNodePtr);
220 renderNode->mutateStagingProperties().mutableOutline().setShouldClip(clipToOutline);
221 renderNode->setPropertyFieldsDirty(RenderNode::GENERIC);
222 return true;
223 }
224
android_view_RenderNode_setRevealClip(CRITICAL_JNI_PARAMS_COMMA jlong renderNodePtr,jboolean shouldClip,jfloat x,jfloat y,jfloat radius)225 static jboolean android_view_RenderNode_setRevealClip(CRITICAL_JNI_PARAMS_COMMA jlong renderNodePtr, jboolean shouldClip,
226 jfloat x, jfloat y, jfloat radius) {
227 RenderNode* renderNode = reinterpret_cast<RenderNode*>(renderNodePtr);
228 renderNode->mutateStagingProperties().mutableRevealClip().set(
229 shouldClip, x, y, radius);
230 renderNode->setPropertyFieldsDirty(RenderNode::GENERIC);
231 return true;
232 }
233
android_view_RenderNode_setAlpha(CRITICAL_JNI_PARAMS_COMMA jlong renderNodePtr,float alpha)234 static jboolean android_view_RenderNode_setAlpha(CRITICAL_JNI_PARAMS_COMMA jlong renderNodePtr, float alpha) {
235 return SET_AND_DIRTY(setAlpha, alpha, RenderNode::ALPHA);
236 }
237
android_view_RenderNode_setRenderEffect(CRITICAL_JNI_PARAMS_COMMA jlong renderNodePtr,jlong renderEffectPtr)238 static jboolean android_view_RenderNode_setRenderEffect(CRITICAL_JNI_PARAMS_COMMA jlong renderNodePtr,
239 jlong renderEffectPtr) {
240 SkImageFilter* imageFilter = reinterpret_cast<SkImageFilter*>(renderEffectPtr);
241 return SET_AND_DIRTY(mutateLayerProperties().setImageFilter, imageFilter, RenderNode::GENERIC);
242 }
243
android_view_RenderNode_setBackdropRenderEffect(CRITICAL_JNI_PARAMS_COMMA jlong renderNodePtr,jlong renderEffectPtr)244 static jboolean android_view_RenderNode_setBackdropRenderEffect(
245 CRITICAL_JNI_PARAMS_COMMA jlong renderNodePtr, jlong renderEffectPtr) {
246 SkImageFilter* imageFilter = reinterpret_cast<SkImageFilter*>(renderEffectPtr);
247 return SET_AND_DIRTY(mutateLayerProperties().setBackdropImageFilter, imageFilter,
248 RenderNode::GENERIC);
249 }
250
android_view_RenderNode_setHasOverlappingRendering(CRITICAL_JNI_PARAMS_COMMA jlong renderNodePtr,bool hasOverlappingRendering)251 static jboolean android_view_RenderNode_setHasOverlappingRendering(CRITICAL_JNI_PARAMS_COMMA jlong renderNodePtr,
252 bool hasOverlappingRendering) {
253 return SET_AND_DIRTY(setHasOverlappingRendering, hasOverlappingRendering,
254 RenderNode::GENERIC);
255 }
256
android_view_RenderNode_setUsageHint(CRITICAL_JNI_PARAMS_COMMA jlong renderNodePtr,jint usageHint)257 static void android_view_RenderNode_setUsageHint(CRITICAL_JNI_PARAMS_COMMA jlong renderNodePtr, jint usageHint) {
258 RenderNode* renderNode = reinterpret_cast<RenderNode*>(renderNodePtr);
259 renderNode->setUsageHint(static_cast<UsageHint>(usageHint));
260 }
261
android_view_RenderNode_setElevation(CRITICAL_JNI_PARAMS_COMMA jlong renderNodePtr,float elevation)262 static jboolean android_view_RenderNode_setElevation(CRITICAL_JNI_PARAMS_COMMA jlong renderNodePtr, float elevation) {
263 return SET_AND_DIRTY(setElevation, elevation, RenderNode::Z);
264 }
265
android_view_RenderNode_setTranslationX(CRITICAL_JNI_PARAMS_COMMA jlong renderNodePtr,float tx)266 static jboolean android_view_RenderNode_setTranslationX(CRITICAL_JNI_PARAMS_COMMA jlong renderNodePtr, float tx) {
267 return SET_AND_DIRTY(setTranslationX, tx, RenderNode::TRANSLATION_X | RenderNode::X);
268 }
269
android_view_RenderNode_setTranslationY(CRITICAL_JNI_PARAMS_COMMA jlong renderNodePtr,float ty)270 static jboolean android_view_RenderNode_setTranslationY(CRITICAL_JNI_PARAMS_COMMA jlong renderNodePtr, float ty) {
271 return SET_AND_DIRTY(setTranslationY, ty, RenderNode::TRANSLATION_Y | RenderNode::Y);
272 }
273
android_view_RenderNode_setTranslationZ(CRITICAL_JNI_PARAMS_COMMA jlong renderNodePtr,float tz)274 static jboolean android_view_RenderNode_setTranslationZ(CRITICAL_JNI_PARAMS_COMMA jlong renderNodePtr, float tz) {
275 return SET_AND_DIRTY(setTranslationZ, tz, RenderNode::TRANSLATION_Z | RenderNode::Z);
276 }
277
android_view_RenderNode_setRotation(CRITICAL_JNI_PARAMS_COMMA jlong renderNodePtr,float rotation)278 static jboolean android_view_RenderNode_setRotation(CRITICAL_JNI_PARAMS_COMMA jlong renderNodePtr, float rotation) {
279 return SET_AND_DIRTY(setRotation, rotation, RenderNode::ROTATION);
280 }
281
android_view_RenderNode_setRotationX(CRITICAL_JNI_PARAMS_COMMA jlong renderNodePtr,float rx)282 static jboolean android_view_RenderNode_setRotationX(CRITICAL_JNI_PARAMS_COMMA jlong renderNodePtr, float rx) {
283 return SET_AND_DIRTY(setRotationX, rx, RenderNode::ROTATION_X);
284 }
285
android_view_RenderNode_setRotationY(CRITICAL_JNI_PARAMS_COMMA jlong renderNodePtr,float ry)286 static jboolean android_view_RenderNode_setRotationY(CRITICAL_JNI_PARAMS_COMMA jlong renderNodePtr, float ry) {
287 return SET_AND_DIRTY(setRotationY, ry, RenderNode::ROTATION_Y);
288 }
289
android_view_RenderNode_setScaleX(CRITICAL_JNI_PARAMS_COMMA jlong renderNodePtr,float sx)290 static jboolean android_view_RenderNode_setScaleX(CRITICAL_JNI_PARAMS_COMMA jlong renderNodePtr, float sx) {
291 return SET_AND_DIRTY(setScaleX, sx, RenderNode::SCALE_X);
292 }
293
android_view_RenderNode_setScaleY(CRITICAL_JNI_PARAMS_COMMA jlong renderNodePtr,float sy)294 static jboolean android_view_RenderNode_setScaleY(CRITICAL_JNI_PARAMS_COMMA jlong renderNodePtr, float sy) {
295 return SET_AND_DIRTY(setScaleY, sy, RenderNode::SCALE_Y);
296 }
297
android_view_RenderNode_setPivotX(CRITICAL_JNI_PARAMS_COMMA jlong renderNodePtr,float px)298 static jboolean android_view_RenderNode_setPivotX(CRITICAL_JNI_PARAMS_COMMA jlong renderNodePtr, float px) {
299 return SET_AND_DIRTY(setPivotX, px, RenderNode::GENERIC);
300 }
301
android_view_RenderNode_setPivotY(CRITICAL_JNI_PARAMS_COMMA jlong renderNodePtr,float py)302 static jboolean android_view_RenderNode_setPivotY(CRITICAL_JNI_PARAMS_COMMA jlong renderNodePtr, float py) {
303 return SET_AND_DIRTY(setPivotY, py, RenderNode::GENERIC);
304 }
305
android_view_RenderNode_resetPivot(CRITICAL_JNI_PARAMS_COMMA jlong renderNodePtr)306 static jboolean android_view_RenderNode_resetPivot(CRITICAL_JNI_PARAMS_COMMA jlong renderNodePtr) {
307 return SET_AND_DIRTY(resetPivot, /* void */, RenderNode::GENERIC);
308 }
309
android_view_RenderNode_setCameraDistance(CRITICAL_JNI_PARAMS_COMMA jlong renderNodePtr,float distance)310 static jboolean android_view_RenderNode_setCameraDistance(CRITICAL_JNI_PARAMS_COMMA jlong renderNodePtr, float distance) {
311 return SET_AND_DIRTY(setCameraDistance, distance, RenderNode::GENERIC);
312 }
313
android_view_RenderNode_setLeft(CRITICAL_JNI_PARAMS_COMMA jlong renderNodePtr,int left)314 static jboolean android_view_RenderNode_setLeft(CRITICAL_JNI_PARAMS_COMMA jlong renderNodePtr, int left) {
315 return SET_AND_DIRTY(setLeft, left, RenderNode::X);
316 }
317
android_view_RenderNode_setTop(CRITICAL_JNI_PARAMS_COMMA jlong renderNodePtr,int top)318 static jboolean android_view_RenderNode_setTop(CRITICAL_JNI_PARAMS_COMMA jlong renderNodePtr, int top) {
319 return SET_AND_DIRTY(setTop, top, RenderNode::Y);
320 }
321
android_view_RenderNode_setRight(CRITICAL_JNI_PARAMS_COMMA jlong renderNodePtr,int right)322 static jboolean android_view_RenderNode_setRight(CRITICAL_JNI_PARAMS_COMMA jlong renderNodePtr, int right) {
323 return SET_AND_DIRTY(setRight, right, RenderNode::X);
324 }
325
android_view_RenderNode_setBottom(CRITICAL_JNI_PARAMS_COMMA jlong renderNodePtr,int bottom)326 static jboolean android_view_RenderNode_setBottom(CRITICAL_JNI_PARAMS_COMMA jlong renderNodePtr, int bottom) {
327 return SET_AND_DIRTY(setBottom, bottom, RenderNode::Y);
328 }
329
android_view_RenderNode_getLeft(CRITICAL_JNI_PARAMS_COMMA jlong renderNodePtr)330 static jint android_view_RenderNode_getLeft(CRITICAL_JNI_PARAMS_COMMA jlong renderNodePtr) {
331 return reinterpret_cast<RenderNode*>(renderNodePtr)->stagingProperties().getLeft();
332 }
333
android_view_RenderNode_getTop(CRITICAL_JNI_PARAMS_COMMA jlong renderNodePtr)334 static jint android_view_RenderNode_getTop(CRITICAL_JNI_PARAMS_COMMA jlong renderNodePtr) {
335 return reinterpret_cast<RenderNode*>(renderNodePtr)->stagingProperties().getTop();
336 }
337
android_view_RenderNode_getRight(CRITICAL_JNI_PARAMS_COMMA jlong renderNodePtr)338 static jint android_view_RenderNode_getRight(CRITICAL_JNI_PARAMS_COMMA jlong renderNodePtr) {
339 return reinterpret_cast<RenderNode*>(renderNodePtr)->stagingProperties().getRight();
340 }
341
android_view_RenderNode_getBottom(CRITICAL_JNI_PARAMS_COMMA jlong renderNodePtr)342 static jint android_view_RenderNode_getBottom(CRITICAL_JNI_PARAMS_COMMA jlong renderNodePtr) {
343 return reinterpret_cast<RenderNode*>(renderNodePtr)->stagingProperties().getBottom();
344 }
345
android_view_RenderNode_setLeftTopRightBottom(CRITICAL_JNI_PARAMS_COMMA jlong renderNodePtr,int left,int top,int right,int bottom)346 static jboolean android_view_RenderNode_setLeftTopRightBottom(CRITICAL_JNI_PARAMS_COMMA jlong renderNodePtr,
347 int left, int top, int right, int bottom) {
348 RenderNode* renderNode = reinterpret_cast<RenderNode*>(renderNodePtr);
349 if (renderNode->mutateStagingProperties().setLeftTopRightBottom(left, top, right, bottom)) {
350 renderNode->setPropertyFieldsDirty(RenderNode::X | RenderNode::Y);
351 return true;
352 }
353 return false;
354 }
355
android_view_RenderNode_offsetLeftAndRight(CRITICAL_JNI_PARAMS_COMMA jlong renderNodePtr,jint offset)356 static jboolean android_view_RenderNode_offsetLeftAndRight(CRITICAL_JNI_PARAMS_COMMA jlong renderNodePtr, jint offset) {
357 return SET_AND_DIRTY(offsetLeftRight, offset, RenderNode::X);
358 }
359
android_view_RenderNode_offsetTopAndBottom(CRITICAL_JNI_PARAMS_COMMA jlong renderNodePtr,jint offset)360 static jboolean android_view_RenderNode_offsetTopAndBottom(CRITICAL_JNI_PARAMS_COMMA jlong renderNodePtr, jint offset) {
361 return SET_AND_DIRTY(offsetTopBottom, offset, RenderNode::Y);
362 }
363
364 // ----------------------------------------------------------------------------
365 // RenderProperties - getters
366 // ----------------------------------------------------------------------------
367
android_view_RenderNode_hasOverlappingRendering(CRITICAL_JNI_PARAMS_COMMA jlong renderNodePtr)368 static jboolean android_view_RenderNode_hasOverlappingRendering(CRITICAL_JNI_PARAMS_COMMA jlong renderNodePtr) {
369 RenderNode* renderNode = reinterpret_cast<RenderNode*>(renderNodePtr);
370 return renderNode->stagingProperties().hasOverlappingRendering();
371 }
372
android_view_RenderNode_getAnimationMatrix(CRITICAL_JNI_PARAMS_COMMA jlong renderNodePtr,jlong outMatrixPtr)373 static jboolean android_view_RenderNode_getAnimationMatrix(CRITICAL_JNI_PARAMS_COMMA jlong renderNodePtr, jlong outMatrixPtr) {
374 RenderNode* renderNode = reinterpret_cast<RenderNode*>(renderNodePtr);
375 SkMatrix* outMatrix = reinterpret_cast<SkMatrix*>(outMatrixPtr);
376
377 const SkMatrix* animationMatrix = renderNode->stagingProperties().getAnimationMatrix();
378
379 if (animationMatrix) {
380 *outMatrix = *animationMatrix;
381 return JNI_TRUE;
382 }
383 return JNI_FALSE;
384 }
385
android_view_RenderNode_getClipToBounds(CRITICAL_JNI_PARAMS_COMMA jlong renderNodePtr)386 static jboolean android_view_RenderNode_getClipToBounds(CRITICAL_JNI_PARAMS_COMMA jlong renderNodePtr) {
387 RenderNode* renderNode = reinterpret_cast<RenderNode*>(renderNodePtr);
388 return renderNode->stagingProperties().getClipToBounds();
389 }
390
android_view_RenderNode_getClipToOutline(CRITICAL_JNI_PARAMS_COMMA jlong renderNodePtr)391 static jboolean android_view_RenderNode_getClipToOutline(CRITICAL_JNI_PARAMS_COMMA jlong renderNodePtr) {
392 RenderNode* renderNode = reinterpret_cast<RenderNode*>(renderNodePtr);
393 return renderNode->stagingProperties().getOutline().getShouldClip();
394 }
395
android_view_RenderNode_getAlpha(CRITICAL_JNI_PARAMS_COMMA jlong renderNodePtr)396 static jfloat android_view_RenderNode_getAlpha(CRITICAL_JNI_PARAMS_COMMA jlong renderNodePtr) {
397 RenderNode* renderNode = reinterpret_cast<RenderNode*>(renderNodePtr);
398 return renderNode->stagingProperties().getAlpha();
399 }
400
android_view_RenderNode_getCameraDistance(CRITICAL_JNI_PARAMS_COMMA jlong renderNodePtr)401 static jfloat android_view_RenderNode_getCameraDistance(CRITICAL_JNI_PARAMS_COMMA jlong renderNodePtr) {
402 RenderNode* renderNode = reinterpret_cast<RenderNode*>(renderNodePtr);
403 return renderNode->stagingProperties().getCameraDistance();
404 }
405
android_view_RenderNode_getScaleX(CRITICAL_JNI_PARAMS_COMMA jlong renderNodePtr)406 static jfloat android_view_RenderNode_getScaleX(CRITICAL_JNI_PARAMS_COMMA jlong renderNodePtr) {
407 RenderNode* renderNode = reinterpret_cast<RenderNode*>(renderNodePtr);
408 return renderNode->stagingProperties().getScaleX();
409 }
410
android_view_RenderNode_getScaleY(CRITICAL_JNI_PARAMS_COMMA jlong renderNodePtr)411 static jfloat android_view_RenderNode_getScaleY(CRITICAL_JNI_PARAMS_COMMA jlong renderNodePtr) {
412 RenderNode* renderNode = reinterpret_cast<RenderNode*>(renderNodePtr);
413 return renderNode->stagingProperties().getScaleY();
414 }
415
android_view_RenderNode_getElevation(CRITICAL_JNI_PARAMS_COMMA jlong renderNodePtr)416 static jfloat android_view_RenderNode_getElevation(CRITICAL_JNI_PARAMS_COMMA jlong renderNodePtr) {
417 RenderNode* renderNode = reinterpret_cast<RenderNode*>(renderNodePtr);
418 return renderNode->stagingProperties().getElevation();
419 }
420
android_view_RenderNode_getTranslationX(CRITICAL_JNI_PARAMS_COMMA jlong renderNodePtr)421 static jfloat android_view_RenderNode_getTranslationX(CRITICAL_JNI_PARAMS_COMMA jlong renderNodePtr) {
422 RenderNode* renderNode = reinterpret_cast<RenderNode*>(renderNodePtr);
423 return renderNode->stagingProperties().getTranslationX();
424 }
425
android_view_RenderNode_getTranslationY(CRITICAL_JNI_PARAMS_COMMA jlong renderNodePtr)426 static jfloat android_view_RenderNode_getTranslationY(CRITICAL_JNI_PARAMS_COMMA jlong renderNodePtr) {
427 RenderNode* renderNode = reinterpret_cast<RenderNode*>(renderNodePtr);
428 return renderNode->stagingProperties().getTranslationY();
429 }
430
android_view_RenderNode_getTranslationZ(CRITICAL_JNI_PARAMS_COMMA jlong renderNodePtr)431 static jfloat android_view_RenderNode_getTranslationZ(CRITICAL_JNI_PARAMS_COMMA jlong renderNodePtr) {
432 RenderNode* renderNode = reinterpret_cast<RenderNode*>(renderNodePtr);
433 return renderNode->stagingProperties().getTranslationZ();
434 }
435
android_view_RenderNode_getRotation(CRITICAL_JNI_PARAMS_COMMA jlong renderNodePtr)436 static jfloat android_view_RenderNode_getRotation(CRITICAL_JNI_PARAMS_COMMA jlong renderNodePtr) {
437 RenderNode* renderNode = reinterpret_cast<RenderNode*>(renderNodePtr);
438 return renderNode->stagingProperties().getRotation();
439 }
440
android_view_RenderNode_getRotationX(CRITICAL_JNI_PARAMS_COMMA jlong renderNodePtr)441 static jfloat android_view_RenderNode_getRotationX(CRITICAL_JNI_PARAMS_COMMA jlong renderNodePtr) {
442 RenderNode* renderNode = reinterpret_cast<RenderNode*>(renderNodePtr);
443 return renderNode->stagingProperties().getRotationX();
444 }
445
android_view_RenderNode_getRotationY(CRITICAL_JNI_PARAMS_COMMA jlong renderNodePtr)446 static jfloat android_view_RenderNode_getRotationY(CRITICAL_JNI_PARAMS_COMMA jlong renderNodePtr) {
447 RenderNode* renderNode = reinterpret_cast<RenderNode*>(renderNodePtr);
448 return renderNode->stagingProperties().getRotationY();
449 }
450
android_view_RenderNode_isPivotExplicitlySet(CRITICAL_JNI_PARAMS_COMMA jlong renderNodePtr)451 static jboolean android_view_RenderNode_isPivotExplicitlySet(CRITICAL_JNI_PARAMS_COMMA jlong renderNodePtr) {
452 RenderNode* renderNode = reinterpret_cast<RenderNode*>(renderNodePtr);
453 return renderNode->stagingProperties().isPivotExplicitlySet();
454 }
455
android_view_RenderNode_hasIdentityMatrix(CRITICAL_JNI_PARAMS_COMMA jlong renderNodePtr)456 static jboolean android_view_RenderNode_hasIdentityMatrix(CRITICAL_JNI_PARAMS_COMMA jlong renderNodePtr) {
457 RenderNode* renderNode = reinterpret_cast<RenderNode*>(renderNodePtr);
458 renderNode->mutateStagingProperties().updateMatrix();
459 return !renderNode->stagingProperties().hasTransformMatrix();
460 }
461
android_view_RenderNode_getLayerType(CRITICAL_JNI_PARAMS_COMMA jlong renderNodePtr)462 static jint android_view_RenderNode_getLayerType(CRITICAL_JNI_PARAMS_COMMA jlong renderNodePtr) {
463 RenderNode* renderNode = reinterpret_cast<RenderNode*>(renderNodePtr);
464 return static_cast<int>(renderNode->stagingProperties().layerProperties().type());
465 }
466
467 // ----------------------------------------------------------------------------
468 // RenderProperties - computed getters
469 // ----------------------------------------------------------------------------
470
getTransformMatrix(jlong renderNodePtr,jlong outMatrixPtr)471 static void getTransformMatrix(jlong renderNodePtr, jlong outMatrixPtr) {
472 RenderNode* renderNode = reinterpret_cast<RenderNode*>(renderNodePtr);
473 SkMatrix* outMatrix = reinterpret_cast<SkMatrix*>(outMatrixPtr);
474
475 renderNode->mutateStagingProperties().updateMatrix();
476 const SkMatrix* transformMatrix = renderNode->stagingProperties().getTransformMatrix();
477
478 if (transformMatrix) {
479 *outMatrix = *transformMatrix;
480 } else {
481 outMatrix->setIdentity();
482 }
483 }
484
android_view_RenderNode_getTransformMatrix(CRITICAL_JNI_PARAMS_COMMA jlong renderNodePtr,jlong outMatrixPtr)485 static void android_view_RenderNode_getTransformMatrix(CRITICAL_JNI_PARAMS_COMMA jlong renderNodePtr, jlong outMatrixPtr) {
486 getTransformMatrix(renderNodePtr, outMatrixPtr);
487 }
488
android_view_RenderNode_getInverseTransformMatrix(CRITICAL_JNI_PARAMS_COMMA jlong renderNodePtr,jlong outMatrixPtr)489 static void android_view_RenderNode_getInverseTransformMatrix(CRITICAL_JNI_PARAMS_COMMA jlong renderNodePtr,
490 jlong outMatrixPtr) {
491 // load transform matrix
492 getTransformMatrix(renderNodePtr, outMatrixPtr);
493 SkMatrix* outMatrix = reinterpret_cast<SkMatrix*>(outMatrixPtr);
494
495 // return it inverted
496 if (!outMatrix->invert(outMatrix)) {
497 // failed to load inverse, pass back identity
498 outMatrix->setIdentity();
499 }
500 }
501
android_view_RenderNode_getPivotX(CRITICAL_JNI_PARAMS_COMMA jlong renderNodePtr)502 static jfloat android_view_RenderNode_getPivotX(CRITICAL_JNI_PARAMS_COMMA jlong renderNodePtr) {
503 RenderNode* renderNode = reinterpret_cast<RenderNode*>(renderNodePtr);
504 renderNode->mutateStagingProperties().updateMatrix();
505 return renderNode->stagingProperties().getPivotX();
506 }
507
android_view_RenderNode_getPivotY(CRITICAL_JNI_PARAMS_COMMA jlong renderNodePtr)508 static jfloat android_view_RenderNode_getPivotY(CRITICAL_JNI_PARAMS_COMMA jlong renderNodePtr) {
509 RenderNode* renderNode = reinterpret_cast<RenderNode*>(renderNodePtr);
510 renderNode->mutateStagingProperties().updateMatrix();
511 return renderNode->stagingProperties().getPivotY();
512 }
513
android_view_RenderNode_getWidth(CRITICAL_JNI_PARAMS_COMMA jlong renderNodePtr)514 static jint android_view_RenderNode_getWidth(CRITICAL_JNI_PARAMS_COMMA jlong renderNodePtr) {
515 return reinterpret_cast<RenderNode*>(renderNodePtr)->stagingProperties().getWidth();
516 }
517
android_view_RenderNode_getHeight(CRITICAL_JNI_PARAMS_COMMA jlong renderNodePtr)518 static jint android_view_RenderNode_getHeight(CRITICAL_JNI_PARAMS_COMMA jlong renderNodePtr) {
519 return reinterpret_cast<RenderNode*>(renderNodePtr)->stagingProperties().getHeight();
520 }
521
android_view_RenderNode_setAllowForceDark(CRITICAL_JNI_PARAMS_COMMA jlong renderNodePtr,jboolean allow)522 static jboolean android_view_RenderNode_setAllowForceDark(CRITICAL_JNI_PARAMS_COMMA jlong renderNodePtr, jboolean allow) {
523 return SET_AND_DIRTY(setAllowForceDark, allow, RenderNode::GENERIC);
524 }
525
android_view_RenderNode_getAllowForceDark(CRITICAL_JNI_PARAMS_COMMA jlong renderNodePtr)526 static jboolean android_view_RenderNode_getAllowForceDark(CRITICAL_JNI_PARAMS_COMMA jlong renderNodePtr) {
527 return reinterpret_cast<RenderNode*>(renderNodePtr)->stagingProperties().getAllowForceDark();
528 }
529
android_view_RenderNode_getUniqueId(CRITICAL_JNI_PARAMS_COMMA jlong renderNodePtr)530 static jlong android_view_RenderNode_getUniqueId(CRITICAL_JNI_PARAMS_COMMA jlong renderNodePtr) {
531 return reinterpret_cast<RenderNode*>(renderNodePtr)->uniqueId();
532 }
533
android_view_RenderNode_setIsTextureView(CRITICAL_JNI_PARAMS_COMMA jlong renderNodePtr)534 static void android_view_RenderNode_setIsTextureView(
535 CRITICAL_JNI_PARAMS_COMMA jlong renderNodePtr) {
536 reinterpret_cast<RenderNode*>(renderNodePtr)->setIsTextureView();
537 }
538
539 // ----------------------------------------------------------------------------
540 // RenderProperties - Animations
541 // ----------------------------------------------------------------------------
542
android_view_RenderNode_addAnimator(JNIEnv * env,jobject clazz,jlong renderNodePtr,jlong animatorPtr)543 static void android_view_RenderNode_addAnimator(JNIEnv* env, jobject clazz, jlong renderNodePtr,
544 jlong animatorPtr) {
545 RenderNode* renderNode = reinterpret_cast<RenderNode*>(renderNodePtr);
546 RenderPropertyAnimator* animator = reinterpret_cast<RenderPropertyAnimator*>(animatorPtr);
547 renderNode->addAnimator(animator);
548 }
549
android_view_RenderNode_endAllAnimators(JNIEnv * env,jobject clazz,jlong renderNodePtr)550 static void android_view_RenderNode_endAllAnimators(JNIEnv* env, jobject clazz,
551 jlong renderNodePtr) {
552 RenderNode* renderNode = reinterpret_cast<RenderNode*>(renderNodePtr);
553 renderNode->animators().endAllStagingAnimators();
554 }
555
android_view_RenderNode_forceEndAnimators(JNIEnv * env,jobject clazz,jlong renderNodePtr)556 static void android_view_RenderNode_forceEndAnimators(JNIEnv* env, jobject clazz,
557 jlong renderNodePtr) {
558 RenderNode* renderNode = reinterpret_cast<RenderNode*>(renderNodePtr);
559 renderNode->animators().forceEndAnimators();
560 }
561
562 // ----------------------------------------------------------------------------
563 // SurfaceView position callback
564 // ----------------------------------------------------------------------------
565
566 struct {
567 jclass clazz;
568 jmethodID callPositionChanged;
569 jmethodID callPositionChanged2;
570 jmethodID callApplyStretch;
571 jmethodID callPositionLost;
572 } gPositionListener;
573
android_view_RenderNode_requestPositionUpdates(JNIEnv * env,jobject,jlong renderNodePtr,jobject listener)574 static void android_view_RenderNode_requestPositionUpdates(JNIEnv* env, jobject,
575 jlong renderNodePtr, jobject listener) {
576 class PositionListenerTrampoline : public RenderNode::PositionListener {
577 public:
578 PositionListenerTrampoline(JNIEnv* env, jobject listener) {
579 env->GetJavaVM(&mVm);
580 mListener = env->NewGlobalRef(listener);
581 }
582
583 virtual ~PositionListenerTrampoline() {
584 jnienv()->DeleteGlobalRef(mListener);
585 mListener = nullptr;
586 }
587
588 virtual void onPositionUpdated(RenderNode& node, const TreeInfo& info) override {
589 if (CC_UNLIKELY(!mListener || !info.updateWindowPositions)) return;
590
591 const RenderProperties& props = node.properties();
592 const bool enableClip = Properties::clipSurfaceViews;
593
594 Matrix4 transform;
595 SkIRect clipBounds;
596 if (enableClip) {
597 uirenderer::Rect initialClipBounds;
598 const auto clipFlags = props.getClippingFlags();
599 if (clipFlags) {
600 props.getClippingRectForFlags(clipFlags, &initialClipBounds);
601 } else {
602 // Works for RenderNode::damageSelf()
603 initialClipBounds.set(DIRTY_MIN, DIRTY_MIN, DIRTY_MAX, DIRTY_MAX);
604 }
605 clipBounds =
606 info.damageAccumulator
607 ->computeClipAndTransform(initialClipBounds.toSkRect(), &transform)
608 .roundOut();
609 } else {
610 info.damageAccumulator->computeCurrentTransform(&transform);
611 }
612 bool useStretchShader =
613 Properties::getStretchEffectBehavior() != StretchEffectBehavior::UniformScale;
614 // Compute the transform bounds first before calculating the stretch
615 uirenderer::Rect bounds(props.getWidth(), props.getHeight());
616 transform.mapRect(bounds);
617
618 bool hasStretch = useStretchShader && info.stretchEffectCount;
619 if (hasStretch) {
620 handleStretchEffect(info, bounds);
621 }
622
623 if (CC_LIKELY(transform.isPureTranslate()) && !hasStretch) {
624 // snap/round the computed bounds, so they match the rounding behavior
625 // of the clear done in SurfaceView#draw().
626 bounds.snapGeometryToPixelBoundaries(false);
627 } else {
628 // Conservatively round out so the punched hole (in the ZOrderOnTop = true case)
629 // doesn't extend beyond the other window
630 bounds.roundOut();
631 }
632
633 if (mPreviousPosition == bounds && mPreviousClip == clipBounds) {
634 return;
635 }
636 mPreviousPosition = bounds;
637 mPreviousClip = clipBounds;
638
639 ATRACE_NAME("Update SurfaceView position");
640
641 JNIEnv* env = jnienv();
642 // Update the new position synchronously. We cannot defer this to
643 // a worker pool to process asynchronously because the UI thread
644 // may be unblocked by the time a worker thread can process this,
645 // In particular if the app removes a view from the view tree before
646 // this callback is dispatched, then we lose the position
647 // information for this frame.
648 jboolean keepListening;
649 if (!enableClip) {
650 keepListening = env->CallStaticBooleanMethod(
651 gPositionListener.clazz, gPositionListener.callPositionChanged, mListener,
652 static_cast<jlong>(info.canvasContext.getFrameNumber()),
653 static_cast<jint>(bounds.left), static_cast<jint>(bounds.top),
654 static_cast<jint>(bounds.right), static_cast<jint>(bounds.bottom));
655 } else {
656 keepListening = env->CallStaticBooleanMethod(
657 gPositionListener.clazz, gPositionListener.callPositionChanged2, mListener,
658 static_cast<jlong>(info.canvasContext.getFrameNumber()),
659 static_cast<jint>(bounds.left), static_cast<jint>(bounds.top),
660 static_cast<jint>(bounds.right), static_cast<jint>(bounds.bottom),
661 static_cast<jint>(clipBounds.fLeft), static_cast<jint>(clipBounds.fTop),
662 static_cast<jint>(clipBounds.fRight),
663 static_cast<jint>(clipBounds.fBottom));
664 }
665 if (!keepListening) {
666 env->DeleteGlobalRef(mListener);
667 mListener = nullptr;
668 }
669 }
670
671 virtual void onPositionLost(RenderNode& node, const TreeInfo* info) override {
672 if (CC_UNLIKELY(!mListener || (info && !info->updateWindowPositions))) return;
673
674 if (mPreviousPosition.isEmpty()) {
675 return;
676 }
677 mPreviousPosition.setEmpty();
678
679 ATRACE_NAME("SurfaceView position lost");
680 JNIEnv* env = jnienv();
681 // Update the lost position synchronously. We cannot defer this to
682 // a worker pool to process asynchronously because the UI thread
683 // may be unblocked by the time a worker thread can process this,
684 // In particular if a view's rendernode is readded to the scene
685 // before this callback is dispatched, then we report that we lost
686 // position information on the wrong frame, which can be problematic
687 // for views like SurfaceView which rely on RenderNode callbacks
688 // for driving visibility.
689 jboolean keepListening = env->CallStaticBooleanMethod(
690 gPositionListener.clazz, gPositionListener.callPositionLost, mListener,
691 info ? info->canvasContext.getFrameNumber() : 0);
692 if (!keepListening) {
693 env->DeleteGlobalRef(mListener);
694 mListener = nullptr;
695 }
696 }
697
698 private:
699 JNIEnv* jnienv() {
700 JNIEnv* env;
701 if (mVm->GetEnv(reinterpret_cast<void**>(&env), JNI_VERSION_1_6) != JNI_OK) {
702 LOG_ALWAYS_FATAL("Failed to get JNIEnv for JavaVM: %p", mVm);
703 }
704 return env;
705 }
706
707 void handleStretchEffect(const TreeInfo& info, uirenderer::Rect& targetBounds) {
708 // Search up to find the nearest stretcheffect parent
709 const DamageAccumulator::StretchResult result =
710 info.damageAccumulator->findNearestStretchEffect();
711 const StretchEffect* effect = result.stretchEffect;
712 if (effect) {
713 // Compute the number of pixels that the stretching container
714 // scales by.
715 // Then compute the scale factor that the child would need
716 // to scale in order to occupy the same pixel bounds.
717 auto& parentBounds = result.parentBounds;
718 auto parentWidth = parentBounds.width();
719 auto parentHeight = parentBounds.height();
720 auto& stretchDirection = effect->getStretchDirection();
721 auto stretchX = stretchDirection.x();
722 auto stretchY = stretchDirection.y();
723 auto stretchXPixels = parentWidth * std::abs(stretchX);
724 auto stretchYPixels = parentHeight * std::abs(stretchY);
725 SkMatrix stretchMatrix;
726
727 auto childScaleX = 1 + (stretchXPixels / targetBounds.getWidth());
728 auto childScaleY = 1 + (stretchYPixels / targetBounds.getHeight());
729 auto pivotX = stretchX > 0 ? targetBounds.left : targetBounds.right;
730 auto pivotY = stretchY > 0 ? targetBounds.top : targetBounds.bottom;
731 stretchMatrix.setScale(childScaleX, childScaleY, pivotX, pivotY);
732 SkRect rect = SkRect::MakeLTRB(targetBounds.left, targetBounds.top,
733 targetBounds.right, targetBounds.bottom);
734 SkRect dst = stretchMatrix.mapRect(rect);
735 targetBounds.left = dst.left();
736 targetBounds.top = dst.top();
737 targetBounds.right = dst.right();
738 targetBounds.bottom = dst.bottom();
739 } else {
740 return;
741 }
742
743 if (Properties::getStretchEffectBehavior() ==
744 StretchEffectBehavior::Shader) {
745 JNIEnv* env = jnienv();
746
747 SkVector stretchDirection = effect->getStretchDirection();
748 jboolean keepListening = env->CallStaticBooleanMethod(
749 gPositionListener.clazz, gPositionListener.callApplyStretch, mListener,
750 info.canvasContext.getFrameNumber(), result.width, result.height,
751 stretchDirection.fX, stretchDirection.fY, effect->maxStretchAmountX,
752 effect->maxStretchAmountY, targetBounds.left, targetBounds.top,
753 targetBounds.right, targetBounds.bottom);
754 if (!keepListening) {
755 env->DeleteGlobalRef(mListener);
756 mListener = nullptr;
757 }
758 }
759 }
760
761 JavaVM* mVm;
762 jobject mListener;
763 uirenderer::Rect mPreviousPosition;
764 uirenderer::Rect mPreviousClip;
765 };
766
767 RenderNode* renderNode = reinterpret_cast<RenderNode*>(renderNodePtr);
768 renderNode->setPositionListener(new PositionListenerTrampoline(env, listener));
769 }
770
771 // ----------------------------------------------------------------------------
772 // JNI Glue
773 // ----------------------------------------------------------------------------
774
775 const char* const kClassPathName = "android/graphics/RenderNode";
776
777 static const JNINativeMethod gMethods[] = {
778 // ----------------------------------------------------------------------------
779 // Regular JNI
780 // ----------------------------------------------------------------------------
781 {"nCreate", "(Ljava/lang/String;)J", (void*)android_view_RenderNode_create},
782 {"nGetNativeFinalizer", "()J", (void*)android_view_RenderNode_getNativeFinalizer},
783 {"nOutput", "(J)V", (void*)android_view_RenderNode_output},
784 {"nGetUsageSize", "(J)I", (void*)android_view_RenderNode_getUsageSize},
785 {"nGetAllocatedSize", "(J)I", (void*)android_view_RenderNode_getAllocatedSize},
786 {"nAddAnimator", "(JJ)V", (void*)android_view_RenderNode_addAnimator},
787 {"nEndAllAnimators", "(J)V", (void*)android_view_RenderNode_endAllAnimators},
788 {"nForceEndAnimators", "(J)V", (void*)android_view_RenderNode_forceEndAnimators},
789 {"nRequestPositionUpdates", "(JLjava/lang/ref/WeakReference;)V",
790 (void*)android_view_RenderNode_requestPositionUpdates},
791
792 // ----------------------------------------------------------------------------
793 // Critical JNI via @CriticalNative annotation in RenderNode.java
794 // ----------------------------------------------------------------------------
795 {"nDiscardDisplayList", "(J)V", (void*)android_view_RenderNode_discardDisplayList},
796 {"nIsValid", "(J)Z", (void*)android_view_RenderNode_isValid},
797 {"nSetLayerType", "(JI)Z", (void*)android_view_RenderNode_setLayerType},
798 {"nGetLayerType", "(J)I", (void*)android_view_RenderNode_getLayerType},
799 {"nSetLayerPaint", "(JJ)Z", (void*)android_view_RenderNode_setLayerPaint},
800 {"nSetStaticMatrix", "(JJ)Z", (void*)android_view_RenderNode_setStaticMatrix},
801 {"nSetAnimationMatrix", "(JJ)Z", (void*)android_view_RenderNode_setAnimationMatrix},
802 {"nGetAnimationMatrix", "(JJ)Z", (void*)android_view_RenderNode_getAnimationMatrix},
803 {"nSetClipToBounds", "(JZ)Z", (void*)android_view_RenderNode_setClipToBounds},
804 {"nGetClipToBounds", "(J)Z", (void*)android_view_RenderNode_getClipToBounds},
805 {"nSetClipBounds", "(JIIII)Z", (void*)android_view_RenderNode_setClipBounds},
806 {"nSetClipBoundsEmpty", "(J)Z", (void*)android_view_RenderNode_setClipBoundsEmpty},
807 {"nSetProjectBackwards", "(JZ)Z", (void*)android_view_RenderNode_setProjectBackwards},
808 {"nSetProjectionReceiver", "(JZ)Z", (void*)android_view_RenderNode_setProjectionReceiver},
809
810 {"nSetOutlineRoundRect", "(JIIIIFF)Z", (void*)android_view_RenderNode_setOutlineRoundRect},
811 {"nSetOutlinePath", "(JJF)Z", (void*)android_view_RenderNode_setOutlinePath},
812 {"nSetOutlineEmpty", "(J)Z", (void*)android_view_RenderNode_setOutlineEmpty},
813 {"nSetOutlineNone", "(J)Z", (void*)android_view_RenderNode_setOutlineNone},
814 {"nClearStretch", "(J)Z", (void*)android_view_RenderNode_clearStretch},
815 {"nStretch", "(JFFFF)Z", (void*)android_view_RenderNode_stretch},
816 {"nHasShadow", "(J)Z", (void*)android_view_RenderNode_hasShadow},
817 {"nSetSpotShadowColor", "(JI)Z", (void*)android_view_RenderNode_setSpotShadowColor},
818 {"nGetSpotShadowColor", "(J)I", (void*)android_view_RenderNode_getSpotShadowColor},
819 {"nSetAmbientShadowColor", "(JI)Z", (void*)android_view_RenderNode_setAmbientShadowColor},
820 {"nGetAmbientShadowColor", "(J)I", (void*)android_view_RenderNode_getAmbientShadowColor},
821 {"nSetClipToOutline", "(JZ)Z", (void*)android_view_RenderNode_setClipToOutline},
822 {"nSetRevealClip", "(JZFFF)Z", (void*)android_view_RenderNode_setRevealClip},
823
824 {"nSetAlpha", "(JF)Z", (void*)android_view_RenderNode_setAlpha},
825 {"nSetRenderEffect", "(JJ)Z", (void*)android_view_RenderNode_setRenderEffect},
826 {"nSetBackdropRenderEffect", "(JJ)Z",
827 (void*)android_view_RenderNode_setBackdropRenderEffect},
828 {"nSetHasOverlappingRendering", "(JZ)Z",
829 (void*)android_view_RenderNode_setHasOverlappingRendering},
830 {"nSetUsageHint", "(JI)V", (void*)android_view_RenderNode_setUsageHint},
831 {"nSetElevation", "(JF)Z", (void*)android_view_RenderNode_setElevation},
832 {"nSetTranslationX", "(JF)Z", (void*)android_view_RenderNode_setTranslationX},
833 {"nSetTranslationY", "(JF)Z", (void*)android_view_RenderNode_setTranslationY},
834 {"nSetTranslationZ", "(JF)Z", (void*)android_view_RenderNode_setTranslationZ},
835 {"nSetRotation", "(JF)Z", (void*)android_view_RenderNode_setRotation},
836 {"nSetRotationX", "(JF)Z", (void*)android_view_RenderNode_setRotationX},
837 {"nSetRotationY", "(JF)Z", (void*)android_view_RenderNode_setRotationY},
838 {"nSetScaleX", "(JF)Z", (void*)android_view_RenderNode_setScaleX},
839 {"nSetScaleY", "(JF)Z", (void*)android_view_RenderNode_setScaleY},
840 {"nSetPivotX", "(JF)Z", (void*)android_view_RenderNode_setPivotX},
841 {"nSetPivotY", "(JF)Z", (void*)android_view_RenderNode_setPivotY},
842 {"nResetPivot", "(J)Z", (void*)android_view_RenderNode_resetPivot},
843 {"nSetCameraDistance", "(JF)Z", (void*)android_view_RenderNode_setCameraDistance},
844 {"nSetLeft", "(JI)Z", (void*)android_view_RenderNode_setLeft},
845 {"nSetTop", "(JI)Z", (void*)android_view_RenderNode_setTop},
846 {"nSetRight", "(JI)Z", (void*)android_view_RenderNode_setRight},
847 {"nSetBottom", "(JI)Z", (void*)android_view_RenderNode_setBottom},
848 {"nGetLeft", "(J)I", (void*)android_view_RenderNode_getLeft},
849 {"nGetTop", "(J)I", (void*)android_view_RenderNode_getTop},
850 {"nGetRight", "(J)I", (void*)android_view_RenderNode_getRight},
851 {"nGetBottom", "(J)I", (void*)android_view_RenderNode_getBottom},
852 {"nSetLeftTopRightBottom", "(JIIII)Z",
853 (void*)android_view_RenderNode_setLeftTopRightBottom},
854 {"nOffsetLeftAndRight", "(JI)Z", (void*)android_view_RenderNode_offsetLeftAndRight},
855 {"nOffsetTopAndBottom", "(JI)Z", (void*)android_view_RenderNode_offsetTopAndBottom},
856
857 {"nHasOverlappingRendering", "(J)Z",
858 (void*)android_view_RenderNode_hasOverlappingRendering},
859 {"nGetClipToOutline", "(J)Z", (void*)android_view_RenderNode_getClipToOutline},
860 {"nGetAlpha", "(J)F", (void*)android_view_RenderNode_getAlpha},
861 {"nGetCameraDistance", "(J)F", (void*)android_view_RenderNode_getCameraDistance},
862 {"nGetScaleX", "(J)F", (void*)android_view_RenderNode_getScaleX},
863 {"nGetScaleY", "(J)F", (void*)android_view_RenderNode_getScaleY},
864 {"nGetElevation", "(J)F", (void*)android_view_RenderNode_getElevation},
865 {"nGetTranslationX", "(J)F", (void*)android_view_RenderNode_getTranslationX},
866 {"nGetTranslationY", "(J)F", (void*)android_view_RenderNode_getTranslationY},
867 {"nGetTranslationZ", "(J)F", (void*)android_view_RenderNode_getTranslationZ},
868 {"nGetRotation", "(J)F", (void*)android_view_RenderNode_getRotation},
869 {"nGetRotationX", "(J)F", (void*)android_view_RenderNode_getRotationX},
870 {"nGetRotationY", "(J)F", (void*)android_view_RenderNode_getRotationY},
871 {"nIsPivotExplicitlySet", "(J)Z", (void*)android_view_RenderNode_isPivotExplicitlySet},
872 {"nHasIdentityMatrix", "(J)Z", (void*)android_view_RenderNode_hasIdentityMatrix},
873
874 {"nGetTransformMatrix", "(JJ)V", (void*)android_view_RenderNode_getTransformMatrix},
875 {"nGetInverseTransformMatrix", "(JJ)V",
876 (void*)android_view_RenderNode_getInverseTransformMatrix},
877
878 {"nGetPivotX", "(J)F", (void*)android_view_RenderNode_getPivotX},
879 {"nGetPivotY", "(J)F", (void*)android_view_RenderNode_getPivotY},
880 {"nGetWidth", "(J)I", (void*)android_view_RenderNode_getWidth},
881 {"nGetHeight", "(J)I", (void*)android_view_RenderNode_getHeight},
882 {"nSetAllowForceDark", "(JZ)Z", (void*)android_view_RenderNode_setAllowForceDark},
883 {"nGetAllowForceDark", "(J)Z", (void*)android_view_RenderNode_getAllowForceDark},
884 {"nGetUniqueId", "(J)J", (void*)android_view_RenderNode_getUniqueId},
885 {"nSetIsTextureView", "(J)V", (void*)android_view_RenderNode_setIsTextureView},
886 };
887
register_android_view_RenderNode(JNIEnv * env)888 int register_android_view_RenderNode(JNIEnv* env) {
889 jclass clazz = FindClassOrDie(env, "android/graphics/RenderNode$PositionUpdateListener");
890 gPositionListener.clazz = MakeGlobalRefOrDie(env, clazz);
891 gPositionListener.callPositionChanged = GetStaticMethodIDOrDie(
892 env, clazz, "callPositionChanged", "(Ljava/lang/ref/WeakReference;JIIII)Z");
893 gPositionListener.callPositionChanged2 = GetStaticMethodIDOrDie(
894 env, clazz, "callPositionChanged2", "(Ljava/lang/ref/WeakReference;JIIIIIIII)Z");
895 gPositionListener.callApplyStretch = GetStaticMethodIDOrDie(
896 env, clazz, "callApplyStretch", "(Ljava/lang/ref/WeakReference;JFFFFFFFFFF)Z");
897 gPositionListener.callPositionLost = GetStaticMethodIDOrDie(
898 env, clazz, "callPositionLost", "(Ljava/lang/ref/WeakReference;J)Z");
899 return RegisterMethodsOrDie(env, kClassPathName, gMethods, NELEM(gMethods));
900 }
901
902 };
903
904