android_view_RenderNode.cpp revision dccca44ffda4836b56a21da95a046c9708ffd49c
1/*
2 * Copyright (C) 2012 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 *      http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17#define LOG_TAG "OpenGLRenderer"
18#define ATRACE_TAG ATRACE_TAG_VIEW
19
20#include <EGL/egl.h>
21
22#include "jni.h"
23#include "GraphicsJNI.h"
24#include <nativehelper/JNIHelp.h>
25#include <android_runtime/AndroidRuntime.h>
26
27#include <Animator.h>
28#include <DamageAccumulator.h>
29#include <Matrix.h>
30#include <RenderNode.h>
31#include <renderthread/CanvasContext.h>
32#include <TreeInfo.h>
33#include <hwui/Paint.h>
34
35#include "core_jni_helpers.h"
36
37namespace android {
38
39using namespace uirenderer;
40
41#define SET_AND_DIRTY(prop, val, dirtyFlag) \
42    (reinterpret_cast<RenderNode*>(renderNodePtr)->mutateStagingProperties().prop(val) \
43        ? (reinterpret_cast<RenderNode*>(renderNodePtr)->setPropertyFieldsDirty(dirtyFlag), true) \
44        : false)
45
46// ----------------------------------------------------------------------------
47// DisplayList view properties
48// ----------------------------------------------------------------------------
49
50static void android_view_RenderNode_output(JNIEnv* env,
51        jobject clazz, jlong renderNodePtr) {
52    RenderNode* renderNode = reinterpret_cast<RenderNode*>(renderNodePtr);
53    renderNode->output();
54}
55
56static jint android_view_RenderNode_getDebugSize(JNIEnv* env,
57        jobject clazz, jlong renderNodePtr) {
58    RenderNode* renderNode = reinterpret_cast<RenderNode*>(renderNodePtr);
59    return renderNode->getDebugSize();
60}
61
62static jlong android_view_RenderNode_create(JNIEnv* env, jobject clazz, jstring name) {
63    RenderNode* renderNode = new RenderNode();
64    renderNode->incStrong(0);
65    if (name != NULL) {
66        const char* textArray = env->GetStringUTFChars(name, NULL);
67        renderNode->setName(textArray);
68        env->ReleaseStringUTFChars(name, textArray);
69    }
70    return reinterpret_cast<jlong>(renderNode);
71}
72
73static void android_view_RenderNode_destroyRenderNode(JNIEnv* env,
74        jobject clazz, jlong renderNodePtr) {
75    RenderNode* renderNode = reinterpret_cast<RenderNode*>(renderNodePtr);
76    renderNode->decStrong(0);
77}
78
79static void android_view_RenderNode_setDisplayList(JNIEnv* env,
80        jobject clazz, jlong renderNodePtr, jlong displayListPtr) {
81    RenderNode* renderNode = reinterpret_cast<RenderNode*>(renderNodePtr);
82    DisplayList* newData = reinterpret_cast<DisplayList*>(displayListPtr);
83    renderNode->setStagingDisplayList(newData);
84}
85
86// ----------------------------------------------------------------------------
87// RenderProperties - setters
88// ----------------------------------------------------------------------------
89
90static jboolean android_view_RenderNode_setLayerType(JNIEnv* env,
91        jobject clazz, jlong renderNodePtr, jint jlayerType) {
92    LayerType layerType = static_cast<LayerType>(jlayerType);
93    return SET_AND_DIRTY(mutateLayerProperties().setType, layerType, RenderNode::GENERIC);
94}
95
96static jboolean android_view_RenderNode_setLayerPaint(JNIEnv* env,
97        jobject clazz, jlong renderNodePtr, jlong paintPtr) {
98    Paint* paint = reinterpret_cast<Paint*>(paintPtr);
99    return SET_AND_DIRTY(mutateLayerProperties().setFromPaint, paint, RenderNode::GENERIC);
100}
101
102static jboolean android_view_RenderNode_setStaticMatrix(JNIEnv* env,
103        jobject clazz, jlong renderNodePtr, jlong matrixPtr) {
104    SkMatrix* matrix = reinterpret_cast<SkMatrix*>(matrixPtr);
105    return SET_AND_DIRTY(setStaticMatrix, matrix, RenderNode::GENERIC);
106}
107
108static jboolean android_view_RenderNode_setAnimationMatrix(JNIEnv* env,
109        jobject clazz, jlong renderNodePtr, jlong matrixPtr) {
110    SkMatrix* matrix = reinterpret_cast<SkMatrix*>(matrixPtr);
111    return SET_AND_DIRTY(setAnimationMatrix, matrix, RenderNode::GENERIC);
112}
113
114static jboolean android_view_RenderNode_setClipToBounds(JNIEnv* env,
115        jobject clazz, jlong renderNodePtr, jboolean clipToBounds) {
116    return SET_AND_DIRTY(setClipToBounds, clipToBounds, RenderNode::GENERIC);
117}
118
119static jboolean android_view_RenderNode_setClipBounds(JNIEnv* env,
120        jobject clazz, jlong renderNodePtr, jint left, jint top, jint right, jint bottom) {
121    android::uirenderer::Rect clipBounds(left, top, right, bottom);
122    return SET_AND_DIRTY(setClipBounds, clipBounds, RenderNode::GENERIC);
123}
124
125static jboolean android_view_RenderNode_setClipBoundsEmpty(JNIEnv* env,
126        jobject clazz, jlong renderNodePtr) {
127    return SET_AND_DIRTY(setClipBoundsEmpty,, RenderNode::GENERIC);
128}
129
130static jboolean android_view_RenderNode_setProjectBackwards(JNIEnv* env,
131        jobject clazz, jlong renderNodePtr, jboolean shouldProject) {
132    return SET_AND_DIRTY(setProjectBackwards, shouldProject, RenderNode::GENERIC);
133}
134
135static jboolean android_view_RenderNode_setProjectionReceiver(JNIEnv* env,
136        jobject clazz, jlong renderNodePtr, jboolean shouldRecieve) {
137    return SET_AND_DIRTY(setProjectionReceiver, shouldRecieve, RenderNode::GENERIC);
138}
139
140static jboolean android_view_RenderNode_setOutlineRoundRect(JNIEnv* env,
141        jobject clazz, jlong renderNodePtr, jint left, jint top,
142        jint right, jint bottom, jfloat radius, jfloat alpha) {
143    RenderNode* renderNode = reinterpret_cast<RenderNode*>(renderNodePtr);
144    renderNode->mutateStagingProperties().mutableOutline().setRoundRect(left, top, right, bottom,
145            radius, alpha);
146    renderNode->setPropertyFieldsDirty(RenderNode::GENERIC);
147    return true;
148}
149
150static jboolean android_view_RenderNode_setOutlineConvexPath(JNIEnv* env,
151        jobject clazz, jlong renderNodePtr, jlong outlinePathPtr, jfloat alpha) {
152    RenderNode* renderNode = reinterpret_cast<RenderNode*>(renderNodePtr);
153    SkPath* outlinePath = reinterpret_cast<SkPath*>(outlinePathPtr);
154    renderNode->mutateStagingProperties().mutableOutline().setConvexPath(outlinePath, alpha);
155    renderNode->setPropertyFieldsDirty(RenderNode::GENERIC);
156    return true;
157}
158
159static jboolean android_view_RenderNode_setOutlineEmpty(JNIEnv* env,
160        jobject clazz, jlong renderNodePtr) {
161    RenderNode* renderNode = reinterpret_cast<RenderNode*>(renderNodePtr);
162    renderNode->mutateStagingProperties().mutableOutline().setEmpty();
163    renderNode->setPropertyFieldsDirty(RenderNode::GENERIC);
164    return true;
165}
166
167static jboolean android_view_RenderNode_setOutlineNone(JNIEnv* env,
168        jobject clazz, jlong renderNodePtr) {
169    RenderNode* renderNode = reinterpret_cast<RenderNode*>(renderNodePtr);
170    renderNode->mutateStagingProperties().mutableOutline().setNone();
171    renderNode->setPropertyFieldsDirty(RenderNode::GENERIC);
172    return true;
173}
174
175static jboolean android_view_RenderNode_hasShadow(JNIEnv* env,
176        jobject clazz, jlong renderNodePtr) {
177    RenderNode* renderNode = reinterpret_cast<RenderNode*>(renderNodePtr);
178    return renderNode->stagingProperties().hasShadow();
179}
180
181static jboolean android_view_RenderNode_setClipToOutline(JNIEnv* env,
182        jobject clazz, jlong renderNodePtr, jboolean clipToOutline) {
183    RenderNode* renderNode = reinterpret_cast<RenderNode*>(renderNodePtr);
184    renderNode->mutateStagingProperties().mutableOutline().setShouldClip(clipToOutline);
185    renderNode->setPropertyFieldsDirty(RenderNode::GENERIC);
186    return true;
187}
188
189static jboolean android_view_RenderNode_setRevealClip(JNIEnv* env,
190        jobject clazz, jlong renderNodePtr, jboolean shouldClip,
191        jfloat x, jfloat y, jfloat radius) {
192    RenderNode* renderNode = reinterpret_cast<RenderNode*>(renderNodePtr);
193    renderNode->mutateStagingProperties().mutableRevealClip().set(
194            shouldClip, x, y, radius);
195    renderNode->setPropertyFieldsDirty(RenderNode::GENERIC);
196    return true;
197}
198
199static jboolean android_view_RenderNode_setAlpha(JNIEnv* env,
200        jobject clazz, jlong renderNodePtr, float alpha) {
201    return SET_AND_DIRTY(setAlpha, alpha, RenderNode::ALPHA);
202}
203
204static jboolean android_view_RenderNode_setHasOverlappingRendering(JNIEnv* env,
205        jobject clazz, jlong renderNodePtr, bool hasOverlappingRendering) {
206    return SET_AND_DIRTY(setHasOverlappingRendering, hasOverlappingRendering,
207            RenderNode::GENERIC);
208}
209
210static jboolean android_view_RenderNode_setElevation(JNIEnv* env,
211        jobject clazz, jlong renderNodePtr, float elevation) {
212    return SET_AND_DIRTY(setElevation, elevation, RenderNode::Z);
213}
214
215static jboolean android_view_RenderNode_setTranslationX(JNIEnv* env,
216        jobject clazz, jlong renderNodePtr, float tx) {
217    return SET_AND_DIRTY(setTranslationX, tx, RenderNode::TRANSLATION_X | RenderNode::X);
218}
219
220static jboolean android_view_RenderNode_setTranslationY(JNIEnv* env,
221        jobject clazz, jlong renderNodePtr, float ty) {
222    return SET_AND_DIRTY(setTranslationY, ty, RenderNode::TRANSLATION_Y | RenderNode::Y);
223}
224
225static jboolean android_view_RenderNode_setTranslationZ(JNIEnv* env,
226        jobject clazz, jlong renderNodePtr, float tz) {
227    return SET_AND_DIRTY(setTranslationZ, tz, RenderNode::TRANSLATION_Z | RenderNode::Z);
228}
229
230static jboolean android_view_RenderNode_setRotation(JNIEnv* env,
231        jobject clazz, jlong renderNodePtr, float rotation) {
232    return SET_AND_DIRTY(setRotation, rotation, RenderNode::ROTATION);
233}
234
235static jboolean android_view_RenderNode_setRotationX(JNIEnv* env,
236        jobject clazz, jlong renderNodePtr, float rx) {
237    return SET_AND_DIRTY(setRotationX, rx, RenderNode::ROTATION_X);
238}
239
240static jboolean android_view_RenderNode_setRotationY(JNIEnv* env,
241        jobject clazz, jlong renderNodePtr, float ry) {
242    return SET_AND_DIRTY(setRotationY, ry, RenderNode::ROTATION_Y);
243}
244
245static jboolean android_view_RenderNode_setScaleX(JNIEnv* env,
246        jobject clazz, jlong renderNodePtr, float sx) {
247    return SET_AND_DIRTY(setScaleX, sx, RenderNode::SCALE_X);
248}
249
250static jboolean android_view_RenderNode_setScaleY(JNIEnv* env,
251        jobject clazz, jlong renderNodePtr, float sy) {
252    return SET_AND_DIRTY(setScaleY, sy, RenderNode::SCALE_Y);
253}
254
255static jboolean android_view_RenderNode_setPivotX(JNIEnv* env,
256        jobject clazz, jlong renderNodePtr, float px) {
257    return SET_AND_DIRTY(setPivotX, px, RenderNode::GENERIC);
258}
259
260static jboolean android_view_RenderNode_setPivotY(JNIEnv* env,
261        jobject clazz, jlong renderNodePtr, float py) {
262    return SET_AND_DIRTY(setPivotY, py, RenderNode::GENERIC);
263}
264
265static jboolean android_view_RenderNode_setCameraDistance(JNIEnv* env,
266        jobject clazz, jlong renderNodePtr, float distance) {
267    return SET_AND_DIRTY(setCameraDistance, distance, RenderNode::GENERIC);
268}
269
270static jboolean android_view_RenderNode_setLeft(JNIEnv* env,
271        jobject clazz, jlong renderNodePtr, int left) {
272    return SET_AND_DIRTY(setLeft, left, RenderNode::X);
273}
274
275static jboolean android_view_RenderNode_setTop(JNIEnv* env,
276        jobject clazz, jlong renderNodePtr, int top) {
277    return SET_AND_DIRTY(setTop, top, RenderNode::Y);
278}
279
280static jboolean android_view_RenderNode_setRight(JNIEnv* env,
281        jobject clazz, jlong renderNodePtr, int right) {
282    return SET_AND_DIRTY(setRight, right, RenderNode::X);
283}
284
285static jboolean android_view_RenderNode_setBottom(JNIEnv* env,
286        jobject clazz, jlong renderNodePtr, int bottom) {
287    return SET_AND_DIRTY(setBottom, bottom, RenderNode::Y);
288}
289
290static jboolean android_view_RenderNode_setLeftTopRightBottom(JNIEnv* env,
291        jobject clazz, jlong renderNodePtr, int left, int top,
292        int right, int bottom) {
293    RenderNode* renderNode = reinterpret_cast<RenderNode*>(renderNodePtr);
294    if (renderNode->mutateStagingProperties().setLeftTopRightBottom(left, top, right, bottom)) {
295        renderNode->setPropertyFieldsDirty(RenderNode::X | RenderNode::Y);
296        return true;
297    }
298    return false;
299}
300
301static jboolean android_view_RenderNode_offsetLeftAndRight(JNIEnv* env,
302        jobject clazz, jlong renderNodePtr, jint offset) {
303    return SET_AND_DIRTY(offsetLeftRight, offset, RenderNode::X);
304}
305
306static jboolean android_view_RenderNode_offsetTopAndBottom(JNIEnv* env,
307        jobject clazz, jlong renderNodePtr, jint offset) {
308    return SET_AND_DIRTY(offsetTopBottom, offset, RenderNode::Y);
309}
310
311// ----------------------------------------------------------------------------
312// RenderProperties - getters
313// ----------------------------------------------------------------------------
314
315static jboolean android_view_RenderNode_hasOverlappingRendering(JNIEnv* env,
316        jobject clazz, jlong renderNodePtr) {
317    RenderNode* renderNode = reinterpret_cast<RenderNode*>(renderNodePtr);
318    return renderNode->stagingProperties().hasOverlappingRendering();
319}
320
321static jboolean android_view_RenderNode_getClipToOutline(JNIEnv* env,
322        jobject clazz, jlong renderNodePtr) {
323    RenderNode* renderNode = reinterpret_cast<RenderNode*>(renderNodePtr);
324    return renderNode->stagingProperties().getOutline().getShouldClip();
325}
326
327static jfloat android_view_RenderNode_getAlpha(JNIEnv* env,
328        jobject clazz, jlong renderNodePtr) {
329    RenderNode* renderNode = reinterpret_cast<RenderNode*>(renderNodePtr);
330    return renderNode->stagingProperties().getAlpha();
331}
332
333static jfloat android_view_RenderNode_getCameraDistance(JNIEnv* env,
334        jobject clazz, jlong renderNodePtr) {
335    RenderNode* renderNode = reinterpret_cast<RenderNode*>(renderNodePtr);
336    return renderNode->stagingProperties().getCameraDistance();
337}
338
339static jfloat android_view_RenderNode_getScaleX(JNIEnv* env,
340        jobject clazz, jlong renderNodePtr) {
341    RenderNode* renderNode = reinterpret_cast<RenderNode*>(renderNodePtr);
342    return renderNode->stagingProperties().getScaleX();
343}
344
345static jfloat android_view_RenderNode_getScaleY(JNIEnv* env,
346        jobject clazz, jlong renderNodePtr) {
347    RenderNode* renderNode = reinterpret_cast<RenderNode*>(renderNodePtr);
348    return renderNode->stagingProperties().getScaleY();
349}
350
351static jfloat android_view_RenderNode_getElevation(JNIEnv* env,
352        jobject clazz, jlong renderNodePtr) {
353    RenderNode* renderNode = reinterpret_cast<RenderNode*>(renderNodePtr);
354    return renderNode->stagingProperties().getElevation();
355}
356
357static jfloat android_view_RenderNode_getTranslationX(JNIEnv* env,
358        jobject clazz, jlong renderNodePtr) {
359    RenderNode* renderNode = reinterpret_cast<RenderNode*>(renderNodePtr);
360    return renderNode->stagingProperties().getTranslationX();
361}
362
363static jfloat android_view_RenderNode_getTranslationY(JNIEnv* env,
364        jobject clazz, jlong renderNodePtr) {
365    RenderNode* renderNode = reinterpret_cast<RenderNode*>(renderNodePtr);
366    return renderNode->stagingProperties().getTranslationY();
367}
368
369static jfloat android_view_RenderNode_getTranslationZ(JNIEnv* env,
370        jobject clazz, jlong renderNodePtr) {
371    RenderNode* renderNode = reinterpret_cast<RenderNode*>(renderNodePtr);
372    return renderNode->stagingProperties().getTranslationZ();
373}
374
375static jfloat android_view_RenderNode_getRotation(JNIEnv* env,
376        jobject clazz, jlong renderNodePtr) {
377    RenderNode* renderNode = reinterpret_cast<RenderNode*>(renderNodePtr);
378    return renderNode->stagingProperties().getRotation();
379}
380
381static jfloat android_view_RenderNode_getRotationX(JNIEnv* env,
382        jobject clazz, jlong renderNodePtr) {
383    RenderNode* renderNode = reinterpret_cast<RenderNode*>(renderNodePtr);
384    return renderNode->stagingProperties().getRotationX();
385}
386
387static jfloat android_view_RenderNode_getRotationY(JNIEnv* env,
388        jobject clazz, jlong renderNodePtr) {
389    RenderNode* renderNode = reinterpret_cast<RenderNode*>(renderNodePtr);
390    return renderNode->stagingProperties().getRotationY();
391}
392
393static jboolean android_view_RenderNode_isPivotExplicitlySet(JNIEnv* env,
394        jobject clazz, jlong renderNodePtr) {
395    RenderNode* renderNode = reinterpret_cast<RenderNode*>(renderNodePtr);
396    return renderNode->stagingProperties().isPivotExplicitlySet();
397}
398
399static jboolean android_view_RenderNode_hasIdentityMatrix(JNIEnv* env,
400        jobject clazz, jlong renderNodePtr) {
401    RenderNode* renderNode = reinterpret_cast<RenderNode*>(renderNodePtr);
402    renderNode->mutateStagingProperties().updateMatrix();
403    return !renderNode->stagingProperties().hasTransformMatrix();
404}
405
406// ----------------------------------------------------------------------------
407// RenderProperties - computed getters
408// ----------------------------------------------------------------------------
409
410static void android_view_RenderNode_getTransformMatrix(JNIEnv* env,
411        jobject clazz, jlong renderNodePtr, jlong outMatrixPtr) {
412    RenderNode* renderNode = reinterpret_cast<RenderNode*>(renderNodePtr);
413    SkMatrix* outMatrix = reinterpret_cast<SkMatrix*>(outMatrixPtr);
414
415    renderNode->mutateStagingProperties().updateMatrix();
416    const SkMatrix* transformMatrix = renderNode->stagingProperties().getTransformMatrix();
417
418    if (transformMatrix) {
419        *outMatrix = *transformMatrix;
420    } else {
421        outMatrix->setIdentity();
422    }
423}
424
425static void android_view_RenderNode_getInverseTransformMatrix(JNIEnv* env,
426        jobject clazz, jlong renderNodePtr, jlong outMatrixPtr) {
427    // load transform matrix
428    android_view_RenderNode_getTransformMatrix(env, clazz, renderNodePtr, outMatrixPtr);
429    SkMatrix* outMatrix = reinterpret_cast<SkMatrix*>(outMatrixPtr);
430
431    // return it inverted
432    if (!outMatrix->invert(outMatrix)) {
433        // failed to load inverse, pass back identity
434        outMatrix->setIdentity();
435    }
436}
437
438static jfloat android_view_RenderNode_getPivotX(JNIEnv* env,
439        jobject clazz, jlong renderNodePtr) {
440    RenderNode* renderNode = reinterpret_cast<RenderNode*>(renderNodePtr);
441    renderNode->mutateStagingProperties().updateMatrix();
442    return renderNode->stagingProperties().getPivotX();
443}
444
445static jfloat android_view_RenderNode_getPivotY(JNIEnv* env,
446        jobject clazz, jlong renderNodePtr) {
447    RenderNode* renderNode = reinterpret_cast<RenderNode*>(renderNodePtr);
448    renderNode->mutateStagingProperties().updateMatrix();
449    return renderNode->stagingProperties().getPivotY();
450}
451
452// ----------------------------------------------------------------------------
453// RenderProperties - Animations
454// ----------------------------------------------------------------------------
455
456static void android_view_RenderNode_addAnimator(JNIEnv* env, jobject clazz,
457        jlong renderNodePtr, jlong animatorPtr) {
458    RenderNode* renderNode = reinterpret_cast<RenderNode*>(renderNodePtr);
459    RenderPropertyAnimator* animator = reinterpret_cast<RenderPropertyAnimator*>(animatorPtr);
460    renderNode->addAnimator(animator);
461}
462
463static void android_view_RenderNode_endAllAnimators(JNIEnv* env, jobject clazz,
464        jlong renderNodePtr) {
465    RenderNode* renderNode = reinterpret_cast<RenderNode*>(renderNodePtr);
466    renderNode->animators().endAllStagingAnimators();
467}
468
469// ----------------------------------------------------------------------------
470// SurfaceView position callback
471// ----------------------------------------------------------------------------
472
473jmethodID gSurfaceViewPositionUpdateMethod;
474
475static void android_view_RenderNode_requestPositionUpdates(JNIEnv* env, jobject,
476        jlong renderNodePtr, jobject surfaceview) {
477    class SurfaceViewPositionUpdater : public RenderNode::PositionListener {
478    public:
479        SurfaceViewPositionUpdater(JNIEnv* env, jobject surfaceview) {
480            env->GetJavaVM(&mVm);
481            mWeakRef = env->NewWeakGlobalRef(surfaceview);
482        }
483
484        virtual ~SurfaceViewPositionUpdater() {
485            jnienv()->DeleteWeakGlobalRef(mWeakRef);
486            mWeakRef = nullptr;
487        }
488
489        virtual void onPositionUpdated(RenderNode& node, const TreeInfo& info) override {
490            if (CC_UNLIKELY(!mWeakRef || !info.updateWindowPositions)) return;
491
492            Matrix4 transform;
493            info.damageAccumulator->computeCurrentTransform(&transform);
494            const RenderProperties& props = node.properties();
495            uirenderer::Rect bounds(props.getWidth(), props.getHeight());
496            transform.mapRect(bounds);
497            bounds.left -= info.windowInsetLeft;
498            bounds.right -= info.windowInsetLeft;
499            bounds.top -= info.windowInsetTop;
500            bounds.bottom -= info.windowInsetTop;
501
502            auto functor = std::bind(
503                std::mem_fn(&SurfaceViewPositionUpdater::doUpdatePosition), this,
504                (jlong) info.frameNumber, (jint) bounds.left, (jint) bounds.top,
505                (jint) bounds.right, (jint) bounds.bottom);
506
507            info.canvasContext.enqueueFrameWork(std::move(functor));
508        }
509
510    private:
511        JNIEnv* jnienv() {
512            JNIEnv* env;
513            if (mVm->GetEnv(reinterpret_cast<void**>(&env), JNI_VERSION_1_6) != JNI_OK) {
514                LOG_ALWAYS_FATAL("Failed to get JNIEnv for JavaVM: %p", mVm);
515            }
516            return env;
517        }
518
519        void doUpdatePosition(jlong frameNumber, jint left, jint top,
520                jint right, jint bottom) {
521            ATRACE_NAME("Update SurfaceView position");
522
523            JNIEnv* env = jnienv();
524            jobject localref = env->NewLocalRef(mWeakRef);
525            if (CC_UNLIKELY(!localref)) {
526                jnienv()->DeleteWeakGlobalRef(mWeakRef);
527                mWeakRef = nullptr;
528                return;
529            }
530
531            env->CallVoidMethod(localref, gSurfaceViewPositionUpdateMethod,
532                    frameNumber, left, top, right, bottom);
533            env->DeleteLocalRef(localref);
534        }
535
536        JavaVM* mVm;
537        jobject mWeakRef;
538    };
539
540    RenderNode* renderNode = reinterpret_cast<RenderNode*>(renderNodePtr);
541    renderNode->setPositionListener(new SurfaceViewPositionUpdater(env, surfaceview));
542}
543
544// ----------------------------------------------------------------------------
545// JNI Glue
546// ----------------------------------------------------------------------------
547
548const char* const kClassPathName = "android/view/RenderNode";
549
550static const JNINativeMethod gMethods[] = {
551    { "nCreate",               "(Ljava/lang/String;)J", (void*) android_view_RenderNode_create },
552    { "nDestroyRenderNode",    "(J)V",    (void*) android_view_RenderNode_destroyRenderNode },
553    { "nSetDisplayList",       "(JJ)V",   (void*) android_view_RenderNode_setDisplayList },
554    { "nOutput",               "(J)V",    (void*) android_view_RenderNode_output },
555    { "nGetDebugSize",         "(J)I",    (void*) android_view_RenderNode_getDebugSize },
556
557    { "nSetLayerType",         "!(JI)Z",  (void*) android_view_RenderNode_setLayerType },
558    { "nSetLayerPaint",        "!(JJ)Z",  (void*) android_view_RenderNode_setLayerPaint },
559    { "nSetStaticMatrix",      "!(JJ)Z",  (void*) android_view_RenderNode_setStaticMatrix },
560    { "nSetAnimationMatrix",   "!(JJ)Z",  (void*) android_view_RenderNode_setAnimationMatrix },
561    { "nSetClipToBounds",      "!(JZ)Z",  (void*) android_view_RenderNode_setClipToBounds },
562    { "nSetClipBounds",        "!(JIIII)Z", (void*) android_view_RenderNode_setClipBounds },
563    { "nSetClipBoundsEmpty",   "!(J)Z",   (void*) android_view_RenderNode_setClipBoundsEmpty },
564    { "nSetProjectBackwards",  "!(JZ)Z",  (void*) android_view_RenderNode_setProjectBackwards },
565    { "nSetProjectionReceiver","!(JZ)Z",  (void*) android_view_RenderNode_setProjectionReceiver },
566
567    { "nSetOutlineRoundRect",  "!(JIIIIFF)Z", (void*) android_view_RenderNode_setOutlineRoundRect },
568    { "nSetOutlineConvexPath", "!(JJF)Z", (void*) android_view_RenderNode_setOutlineConvexPath },
569    { "nSetOutlineEmpty",      "!(J)Z",   (void*) android_view_RenderNode_setOutlineEmpty },
570    { "nSetOutlineNone",       "!(J)Z",   (void*) android_view_RenderNode_setOutlineNone },
571    { "nHasShadow",            "!(J)Z",   (void*) android_view_RenderNode_hasShadow },
572    { "nSetClipToOutline",     "!(JZ)Z",  (void*) android_view_RenderNode_setClipToOutline },
573    { "nSetRevealClip",        "!(JZFFF)Z", (void*) android_view_RenderNode_setRevealClip },
574
575    { "nSetAlpha",             "!(JF)Z",  (void*) android_view_RenderNode_setAlpha },
576    { "nSetHasOverlappingRendering", "!(JZ)Z",
577            (void*) android_view_RenderNode_setHasOverlappingRendering },
578    { "nSetElevation",         "!(JF)Z",  (void*) android_view_RenderNode_setElevation },
579    { "nSetTranslationX",      "!(JF)Z",  (void*) android_view_RenderNode_setTranslationX },
580    { "nSetTranslationY",      "!(JF)Z",  (void*) android_view_RenderNode_setTranslationY },
581    { "nSetTranslationZ",      "!(JF)Z",  (void*) android_view_RenderNode_setTranslationZ },
582    { "nSetRotation",          "!(JF)Z",  (void*) android_view_RenderNode_setRotation },
583    { "nSetRotationX",         "!(JF)Z",  (void*) android_view_RenderNode_setRotationX },
584    { "nSetRotationY",         "!(JF)Z",  (void*) android_view_RenderNode_setRotationY },
585    { "nSetScaleX",            "!(JF)Z",  (void*) android_view_RenderNode_setScaleX },
586    { "nSetScaleY",            "!(JF)Z",  (void*) android_view_RenderNode_setScaleY },
587    { "nSetPivotX",            "!(JF)Z",  (void*) android_view_RenderNode_setPivotX },
588    { "nSetPivotY",            "!(JF)Z",  (void*) android_view_RenderNode_setPivotY },
589    { "nSetCameraDistance",    "!(JF)Z",  (void*) android_view_RenderNode_setCameraDistance },
590    { "nSetLeft",              "!(JI)Z",  (void*) android_view_RenderNode_setLeft },
591    { "nSetTop",               "!(JI)Z",  (void*) android_view_RenderNode_setTop },
592    { "nSetRight",             "!(JI)Z",  (void*) android_view_RenderNode_setRight },
593    { "nSetBottom",            "!(JI)Z",  (void*) android_view_RenderNode_setBottom },
594    { "nSetLeftTopRightBottom","!(JIIII)Z", (void*) android_view_RenderNode_setLeftTopRightBottom },
595    { "nOffsetLeftAndRight",   "!(JI)Z",  (void*) android_view_RenderNode_offsetLeftAndRight },
596    { "nOffsetTopAndBottom",   "!(JI)Z",  (void*) android_view_RenderNode_offsetTopAndBottom },
597
598    { "nHasOverlappingRendering", "!(J)Z",  (void*) android_view_RenderNode_hasOverlappingRendering },
599    { "nGetClipToOutline",        "!(J)Z",  (void*) android_view_RenderNode_getClipToOutline },
600    { "nGetAlpha",                "!(J)F",  (void*) android_view_RenderNode_getAlpha },
601    { "nGetCameraDistance",       "!(J)F",  (void*) android_view_RenderNode_getCameraDistance },
602    { "nGetScaleX",               "!(J)F",  (void*) android_view_RenderNode_getScaleX },
603    { "nGetScaleY",               "!(J)F",  (void*) android_view_RenderNode_getScaleY },
604    { "nGetElevation",            "!(J)F",  (void*) android_view_RenderNode_getElevation },
605    { "nGetTranslationX",         "!(J)F",  (void*) android_view_RenderNode_getTranslationX },
606    { "nGetTranslationY",         "!(J)F",  (void*) android_view_RenderNode_getTranslationY },
607    { "nGetTranslationZ",         "!(J)F",  (void*) android_view_RenderNode_getTranslationZ },
608    { "nGetRotation",             "!(J)F",  (void*) android_view_RenderNode_getRotation },
609    { "nGetRotationX",            "!(J)F",  (void*) android_view_RenderNode_getRotationX },
610    { "nGetRotationY",            "!(J)F",  (void*) android_view_RenderNode_getRotationY },
611    { "nIsPivotExplicitlySet",    "!(J)Z",  (void*) android_view_RenderNode_isPivotExplicitlySet },
612    { "nHasIdentityMatrix",       "!(J)Z",  (void*) android_view_RenderNode_hasIdentityMatrix },
613
614    { "nGetTransformMatrix",       "!(JJ)V", (void*) android_view_RenderNode_getTransformMatrix },
615    { "nGetInverseTransformMatrix","!(JJ)V", (void*) android_view_RenderNode_getInverseTransformMatrix },
616
617    { "nGetPivotX",                "!(J)F",  (void*) android_view_RenderNode_getPivotX },
618    { "nGetPivotY",                "!(J)F",  (void*) android_view_RenderNode_getPivotY },
619
620    { "nAddAnimator",              "(JJ)V", (void*) android_view_RenderNode_addAnimator },
621    { "nEndAllAnimators",          "(J)V", (void*) android_view_RenderNode_endAllAnimators },
622
623    { "nRequestPositionUpdates",   "(JLandroid/view/SurfaceView;)V", (void*) android_view_RenderNode_requestPositionUpdates },
624};
625
626int register_android_view_RenderNode(JNIEnv* env) {
627    jclass clazz = FindClassOrDie(env, "android/view/SurfaceView");
628    gSurfaceViewPositionUpdateMethod = GetMethodIDOrDie(env, clazz,
629            "updateWindowPositionRT", "(JIIII)V");
630    return RegisterMethodsOrDie(env, kClassPathName, gMethods, NELEM(gMethods));
631}
632
633};
634
635