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