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