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