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