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