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