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