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