android_view_ThreadedRenderer.cpp revision 8c31e1db2a2cea4278503d6b9b27bca87946ef36
1/* 2 * Copyright (C) 2010 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 "ThreadedRenderer" 18 19#include <algorithm> 20#include <atomic> 21 22#include "jni.h" 23#include <nativehelper/JNIHelp.h> 24#include "core_jni_helpers.h" 25#include <GraphicsJNI.h> 26#include <ScopedPrimitiveArray.h> 27 28#include <EGL/egl.h> 29#include <EGL/eglext.h> 30#include <EGL/egl_cache.h> 31 32#include <utils/Looper.h> 33#include <utils/RefBase.h> 34#include <utils/StrongPointer.h> 35#include <utils/Timers.h> 36#include <android_runtime/android_view_Surface.h> 37#include <system/window.h> 38 39#include "android_os_MessageQueue.h" 40 41#include <Animator.h> 42#include <AnimationContext.h> 43#include <FrameInfo.h> 44#include <FrameMetricsObserver.h> 45#include <IContextFactory.h> 46#include <PropertyValuesAnimatorSet.h> 47#include <RenderNode.h> 48#include <renderthread/CanvasContext.h> 49#include <renderthread/RenderProxy.h> 50#include <renderthread/RenderTask.h> 51#include <renderthread/RenderThread.h> 52 53namespace android { 54 55using namespace android::uirenderer; 56using namespace android::uirenderer::renderthread; 57 58struct { 59 jfieldID frameMetrics; 60 jfieldID timingDataBuffer; 61 jfieldID messageQueue; 62 jmethodID callback; 63} gFrameMetricsObserverClassInfo; 64 65static JNIEnv* getenv(JavaVM* vm) { 66 JNIEnv* env; 67 if (vm->GetEnv(reinterpret_cast<void**>(&env), JNI_VERSION_1_6) != JNI_OK) { 68 LOG_ALWAYS_FATAL("Failed to get JNIEnv for JavaVM: %p", vm); 69 } 70 return env; 71} 72 73class OnFinishedEvent { 74public: 75 OnFinishedEvent(BaseRenderNodeAnimator* animator, AnimationListener* listener) 76 : animator(animator), listener(listener) {} 77 sp<BaseRenderNodeAnimator> animator; 78 sp<AnimationListener> listener; 79}; 80 81class InvokeAnimationListeners : public MessageHandler { 82public: 83 explicit InvokeAnimationListeners(std::vector<OnFinishedEvent>& events) { 84 mOnFinishedEvents.swap(events); 85 } 86 87 static void callOnFinished(OnFinishedEvent& event) { 88 event.listener->onAnimationFinished(event.animator.get()); 89 } 90 91 virtual void handleMessage(const Message& message) { 92 std::for_each(mOnFinishedEvents.begin(), mOnFinishedEvents.end(), callOnFinished); 93 mOnFinishedEvents.clear(); 94 } 95 96private: 97 std::vector<OnFinishedEvent> mOnFinishedEvents; 98}; 99 100class FinishAndInvokeListener : public MessageHandler { 101public: 102 explicit FinishAndInvokeListener(PropertyValuesAnimatorSet* anim) 103 : mAnimator(anim) { 104 mListener = anim->getOneShotListener(); 105 mRequestId = anim->getRequestId(); 106 } 107 108 virtual void handleMessage(const Message& message) { 109 if (mAnimator->getRequestId() == mRequestId) { 110 // Request Id has not changed, meaning there's no animation lifecyle change since the 111 // message is posted, so go ahead and call finish to make sure the PlayState is properly 112 // updated. This is needed because before the next frame comes in from UI thread to 113 // trigger an animation update, there could be reverse/cancel etc. So we need to update 114 // the playstate in time to ensure all the subsequent events get chained properly. 115 mAnimator->end(); 116 } 117 mListener->onAnimationFinished(nullptr); 118 } 119private: 120 sp<PropertyValuesAnimatorSet> mAnimator; 121 sp<AnimationListener> mListener; 122 uint32_t mRequestId; 123}; 124 125class RenderingException : public MessageHandler { 126public: 127 RenderingException(JavaVM* vm, const std::string& message) 128 : mVm(vm) 129 , mMessage(message) { 130 } 131 132 virtual void handleMessage(const Message&) { 133 throwException(mVm, mMessage); 134 } 135 136 static void throwException(JavaVM* vm, const std::string& message) { 137 JNIEnv* env = getenv(vm); 138 jniThrowException(env, "java/lang/IllegalStateException", message.c_str()); 139 } 140 141private: 142 JavaVM* mVm; 143 std::string mMessage; 144}; 145 146class RootRenderNode : public RenderNode, ErrorHandler { 147public: 148 explicit RootRenderNode(JNIEnv* env) : RenderNode() { 149 mLooper = Looper::getForThread(); 150 LOG_ALWAYS_FATAL_IF(!mLooper.get(), 151 "Must create RootRenderNode on a thread with a looper!"); 152 env->GetJavaVM(&mVm); 153 } 154 155 virtual ~RootRenderNode() {} 156 157 virtual void onError(const std::string& message) override { 158 mLooper->sendMessage(new RenderingException(mVm, message), 0); 159 } 160 161 virtual void prepareTree(TreeInfo& info) override { 162 info.errorHandler = this; 163 164 for (auto& anim : mRunningVDAnimators) { 165 // Assume that the property change in VD from the animators will not be consumed. Mark 166 // otherwise if the VDs are found in the display list tree. For VDs that are not in 167 // the display list tree, we stop providing animation pulses by 1) removing them from 168 // the animation list, 2) post a delayed message to end them at end time so their 169 // listeners can receive the corresponding callbacks. 170 anim->getVectorDrawable()->setPropertyChangeWillBeConsumed(false); 171 // Mark the VD dirty so it will damage itself during prepareTree. 172 anim->getVectorDrawable()->markDirty(); 173 } 174 if (info.mode == TreeInfo::MODE_FULL) { 175 for (auto &anim : mPausedVDAnimators) { 176 anim->getVectorDrawable()->setPropertyChangeWillBeConsumed(false); 177 anim->getVectorDrawable()->markDirty(); 178 } 179 } 180 // TODO: This is hacky 181 info.updateWindowPositions = true; 182 RenderNode::prepareTree(info); 183 info.updateWindowPositions = false; 184 info.errorHandler = nullptr; 185 } 186 187 void sendMessage(const sp<MessageHandler>& handler) { 188 mLooper->sendMessage(handler, 0); 189 } 190 191 void sendMessageDelayed(const sp<MessageHandler>& handler, nsecs_t delayInMs) { 192 mLooper->sendMessageDelayed(ms2ns(delayInMs), handler, 0); 193 } 194 195 void attachAnimatingNode(RenderNode* animatingNode) { 196 mPendingAnimatingRenderNodes.push_back(animatingNode); 197 } 198 199 void attachPendingVectorDrawableAnimators() { 200 mRunningVDAnimators.insert(mPendingVectorDrawableAnimators.begin(), 201 mPendingVectorDrawableAnimators.end()); 202 mPendingVectorDrawableAnimators.clear(); 203 } 204 205 void detachAnimators() { 206 // Remove animators from the list and post a delayed message in future to end the animator 207 for (auto& anim : mRunningVDAnimators) { 208 detachVectorDrawableAnimator(anim.get()); 209 } 210 mRunningVDAnimators.clear(); 211 mPausedVDAnimators.clear(); 212 } 213 214 // Move all the animators to the paused list, and send a delayed message to notify the finished 215 // listener. 216 void pauseAnimators() { 217 mPausedVDAnimators.insert(mRunningVDAnimators.begin(), mRunningVDAnimators.end()); 218 for (auto& anim : mRunningVDAnimators) { 219 detachVectorDrawableAnimator(anim.get()); 220 } 221 mRunningVDAnimators.clear(); 222 } 223 224 void doAttachAnimatingNodes(AnimationContext* context) { 225 for (size_t i = 0; i < mPendingAnimatingRenderNodes.size(); i++) { 226 RenderNode* node = mPendingAnimatingRenderNodes[i].get(); 227 context->addAnimatingRenderNode(*node); 228 } 229 mPendingAnimatingRenderNodes.clear(); 230 } 231 232 // Run VectorDrawable animators after prepareTree. 233 void runVectorDrawableAnimators(AnimationContext* context, TreeInfo& info) { 234 // Push staging. 235 if (info.mode == TreeInfo::MODE_FULL) { 236 pushStagingVectorDrawableAnimators(context); 237 } 238 239 // Run the animators in the running list. 240 for (auto it = mRunningVDAnimators.begin(); it != mRunningVDAnimators.end();) { 241 if ((*it)->animate(*context)) { 242 it = mRunningVDAnimators.erase(it); 243 } else { 244 it++; 245 } 246 } 247 248 // Run the animators in paused list during full sync. 249 if (info.mode == TreeInfo::MODE_FULL) { 250 // During full sync we also need to pulse paused animators, in case their targets 251 // have been added back to the display list. All the animators that passed the 252 // scheduled finish time will be removed from the paused list. 253 for (auto it = mPausedVDAnimators.begin(); it != mPausedVDAnimators.end();) { 254 if ((*it)->animate(*context)) { 255 // Animator has finished, remove from the list. 256 it = mPausedVDAnimators.erase(it); 257 } else { 258 it++; 259 } 260 } 261 } 262 263 // Move the animators with a target not in DisplayList to paused list. 264 for (auto it = mRunningVDAnimators.begin(); it != mRunningVDAnimators.end();) { 265 if (!(*it)->getVectorDrawable()->getPropertyChangeWillBeConsumed()) { 266 // Vector Drawable is not in the display list, we should remove this animator from 267 // the list, put it in the paused list, and post a delayed message to end the 268 // animator. 269 detachVectorDrawableAnimator(it->get()); 270 mPausedVDAnimators.insert(*it); 271 it = mRunningVDAnimators.erase(it); 272 } else { 273 it++; 274 } 275 } 276 277 // Move the animators with a target in DisplayList from paused list to running list, and 278 // trim paused list. 279 if (info.mode == TreeInfo::MODE_FULL) { 280 // Check whether any paused animator's target is back in Display List. If so, put the 281 // animator back in the running list. 282 for (auto it = mPausedVDAnimators.begin(); it != mPausedVDAnimators.end();) { 283 if ((*it)->getVectorDrawable()->getPropertyChangeWillBeConsumed()) { 284 mRunningVDAnimators.insert(*it); 285 it = mPausedVDAnimators.erase(it); 286 } else { 287 it++; 288 } 289 } 290 // Trim paused VD animators at full sync, so that when Java loses reference to an 291 // animator, we know we won't be requested to animate it any more, then we remove such 292 // animators from the paused list so they can be properly freed. We also remove the 293 // animators from paused list when the time elapsed since start has exceeded duration. 294 trimPausedVDAnimators(context); 295 } 296 297 info.out.hasAnimations |= !mRunningVDAnimators.empty(); 298 } 299 300 void trimPausedVDAnimators(AnimationContext* context) { 301 // Trim paused vector drawable animator list. 302 for (auto it = mPausedVDAnimators.begin(); it != mPausedVDAnimators.end();) { 303 // Remove paused VD animator if no one else is referencing it. Note that animators that 304 // have passed scheduled finish time are removed from list when they are being pulsed 305 // before prepare tree. 306 // TODO: this is a bit hacky, need to figure out a better way to track when the paused 307 // animators should be freed. 308 if ((*it)->getStrongCount() == 1) { 309 it = mPausedVDAnimators.erase(it); 310 } else { 311 it++; 312 } 313 } 314 } 315 316 void pushStagingVectorDrawableAnimators(AnimationContext* context) { 317 for (auto& anim : mRunningVDAnimators) { 318 anim->pushStaging(*context); 319 } 320 } 321 322 void destroy() { 323 for (auto& renderNode : mPendingAnimatingRenderNodes) { 324 renderNode->animators().endAllStagingAnimators(); 325 } 326 mPendingAnimatingRenderNodes.clear(); 327 mPendingVectorDrawableAnimators.clear(); 328 } 329 330 void addVectorDrawableAnimator(PropertyValuesAnimatorSet* anim) { 331 mPendingVectorDrawableAnimators.insert(anim); 332 } 333 334private: 335 sp<Looper> mLooper; 336 JavaVM* mVm; 337 std::vector< sp<RenderNode> > mPendingAnimatingRenderNodes; 338 std::set< sp<PropertyValuesAnimatorSet> > mPendingVectorDrawableAnimators; 339 std::set< sp<PropertyValuesAnimatorSet> > mRunningVDAnimators; 340 // mPausedVDAnimators stores a list of animators that have not yet passed the finish time, but 341 // their VectorDrawable targets are no longer in the DisplayList. We skip these animators when 342 // render thread runs animators independent of UI thread (i.e. RT_ONLY mode). These animators 343 // need to be re-activated once their VD target is added back into DisplayList. Since that could 344 // only happen when we do a full sync, we need to make sure to pulse these paused animators at 345 // full sync. If any animator's VD target is found in DisplayList during a full sync, we move 346 // the animator back to the running list. 347 std::set< sp<PropertyValuesAnimatorSet> > mPausedVDAnimators; 348 void detachVectorDrawableAnimator(PropertyValuesAnimatorSet* anim) { 349 if (anim->isInfinite() || !anim->isRunning()) { 350 // Do not need to post anything if the animation is infinite (i.e. no meaningful 351 // end listener action), or if the animation has already ended. 352 return; 353 } 354 nsecs_t remainingTimeInMs = anim->getRemainingPlayTime(); 355 // Post a delayed onFinished event that is scheduled to be handled when the animator ends. 356 if (anim->getOneShotListener()) { 357 // VectorDrawable's oneshot listener is updated when there are user triggered animation 358 // lifecycle changes, such as start(), end(), etc. By using checking and clearing 359 // one shot listener, we ensure the same end listener event gets posted only once. 360 // Therefore no duplicates. Another benefit of using one shot listener is that no 361 // removal is necessary: the end time of animation will not change unless triggered by 362 // user events, in which case the already posted listener's id will become stale, and 363 // the onFinished callback will then be ignored. 364 sp<FinishAndInvokeListener> message 365 = new FinishAndInvokeListener(anim); 366 sendMessageDelayed(message, remainingTimeInMs); 367 anim->clearOneShotListener(); 368 } 369 } 370}; 371 372class AnimationContextBridge : public AnimationContext { 373public: 374 AnimationContextBridge(renderthread::TimeLord& clock, RootRenderNode* rootNode) 375 : AnimationContext(clock), mRootNode(rootNode) { 376 } 377 378 virtual ~AnimationContextBridge() {} 379 380 // Marks the start of a frame, which will update the frame time and move all 381 // next frame animations into the current frame 382 virtual void startFrame(TreeInfo::TraversalMode mode) { 383 if (mode == TreeInfo::MODE_FULL) { 384 mRootNode->doAttachAnimatingNodes(this); 385 mRootNode->attachPendingVectorDrawableAnimators(); 386 } 387 AnimationContext::startFrame(mode); 388 } 389 390 // Runs any animations still left in mCurrentFrameAnimations 391 virtual void runRemainingAnimations(TreeInfo& info) { 392 AnimationContext::runRemainingAnimations(info); 393 mRootNode->runVectorDrawableAnimators(this, info); 394 postOnFinishedEvents(); 395 } 396 397 virtual void pauseAnimators() override { 398 mRootNode->pauseAnimators(); 399 } 400 401 virtual void callOnFinished(BaseRenderNodeAnimator* animator, AnimationListener* listener) { 402 OnFinishedEvent event(animator, listener); 403 mOnFinishedEvents.push_back(event); 404 } 405 406 virtual void destroy() { 407 AnimationContext::destroy(); 408 mRootNode->detachAnimators(); 409 postOnFinishedEvents(); 410 } 411 412private: 413 sp<RootRenderNode> mRootNode; 414 std::vector<OnFinishedEvent> mOnFinishedEvents; 415 416 void postOnFinishedEvents() { 417 if (mOnFinishedEvents.size()) { 418 sp<InvokeAnimationListeners> message 419 = new InvokeAnimationListeners(mOnFinishedEvents); 420 mRootNode->sendMessage(message); 421 } 422 } 423}; 424 425class ContextFactoryImpl : public IContextFactory { 426public: 427 explicit ContextFactoryImpl(RootRenderNode* rootNode) : mRootNode(rootNode) {} 428 429 virtual AnimationContext* createAnimationContext(renderthread::TimeLord& clock) { 430 return new AnimationContextBridge(clock, mRootNode); 431 } 432 433private: 434 RootRenderNode* mRootNode; 435}; 436 437class ObserverProxy; 438 439class NotifyHandler : public MessageHandler { 440public: 441 NotifyHandler(JavaVM* vm, ObserverProxy* observer) : mVm(vm), mObserver(observer) {} 442 443 virtual void handleMessage(const Message& message); 444 445private: 446 JavaVM* const mVm; 447 ObserverProxy* const mObserver; 448}; 449 450static jlongArray get_metrics_buffer(JNIEnv* env, jobject observer) { 451 jobject frameMetrics = env->GetObjectField( 452 observer, gFrameMetricsObserverClassInfo.frameMetrics); 453 LOG_ALWAYS_FATAL_IF(frameMetrics == nullptr, "unable to retrieve data sink object"); 454 jobject buffer = env->GetObjectField( 455 frameMetrics, gFrameMetricsObserverClassInfo.timingDataBuffer); 456 LOG_ALWAYS_FATAL_IF(buffer == nullptr, "unable to retrieve data sink buffer"); 457 return reinterpret_cast<jlongArray>(buffer); 458} 459 460/* 461 * Implements JNI layer for hwui frame metrics reporting. 462 */ 463class ObserverProxy : public FrameMetricsObserver { 464public: 465 ObserverProxy(JavaVM *vm, jobject observer) : mVm(vm) { 466 JNIEnv* env = getenv(mVm); 467 468 mObserverWeak = env->NewWeakGlobalRef(observer); 469 LOG_ALWAYS_FATAL_IF(mObserverWeak == nullptr, 470 "unable to create frame stats observer reference"); 471 472 jlongArray buffer = get_metrics_buffer(env, observer); 473 jsize bufferSize = env->GetArrayLength(reinterpret_cast<jarray>(buffer)); 474 LOG_ALWAYS_FATAL_IF(bufferSize != kBufferSize, 475 "Mismatched Java/Native FrameMetrics data format."); 476 477 jobject messageQueueLocal = env->GetObjectField( 478 observer, gFrameMetricsObserverClassInfo.messageQueue); 479 mMessageQueue = android_os_MessageQueue_getMessageQueue(env, messageQueueLocal); 480 LOG_ALWAYS_FATAL_IF(mMessageQueue == nullptr, "message queue not available"); 481 482 mMessageHandler = new NotifyHandler(mVm, this); 483 LOG_ALWAYS_FATAL_IF(mMessageHandler == nullptr, 484 "OOM: unable to allocate NotifyHandler"); 485 } 486 487 ~ObserverProxy() { 488 JNIEnv* env = getenv(mVm); 489 env->DeleteWeakGlobalRef(mObserverWeak); 490 } 491 492 jweak getObserverReference() { 493 return mObserverWeak; 494 } 495 496 bool getNextBuffer(JNIEnv* env, jlongArray sink, int* dropCount) { 497 FrameMetricsNotification& elem = mRingBuffer[mNextInQueue]; 498 499 if (elem.hasData.load()) { 500 env->SetLongArrayRegion(sink, 0, kBufferSize, elem.buffer); 501 *dropCount = elem.dropCount; 502 mNextInQueue = (mNextInQueue + 1) % kRingSize; 503 elem.hasData = false; 504 return true; 505 } 506 507 return false; 508 } 509 510 virtual void notify(const int64_t* stats) { 511 FrameMetricsNotification& elem = mRingBuffer[mNextFree]; 512 513 if (!elem.hasData.load()) { 514 memcpy(elem.buffer, stats, kBufferSize * sizeof(stats[0])); 515 516 elem.dropCount = mDroppedReports; 517 mDroppedReports = 0; 518 519 incStrong(nullptr); 520 mNextFree = (mNextFree + 1) % kRingSize; 521 elem.hasData = true; 522 523 mMessageQueue->getLooper()->sendMessage(mMessageHandler, mMessage); 524 } else { 525 mDroppedReports++; 526 } 527 } 528 529private: 530 static const int kBufferSize = static_cast<int>(FrameInfoIndex::NumIndexes); 531 static constexpr int kRingSize = 3; 532 533 class FrameMetricsNotification { 534 public: 535 FrameMetricsNotification() : hasData(false) {} 536 537 std::atomic_bool hasData; 538 int64_t buffer[kBufferSize]; 539 int dropCount = 0; 540 }; 541 542 JavaVM* const mVm; 543 jweak mObserverWeak; 544 545 sp<MessageQueue> mMessageQueue; 546 sp<NotifyHandler> mMessageHandler; 547 Message mMessage; 548 549 int mNextFree = 0; 550 int mNextInQueue = 0; 551 FrameMetricsNotification mRingBuffer[kRingSize]; 552 553 int mDroppedReports = 0; 554}; 555 556void NotifyHandler::handleMessage(const Message& message) { 557 JNIEnv* env = getenv(mVm); 558 559 jobject target = env->NewLocalRef(mObserver->getObserverReference()); 560 561 if (target != nullptr) { 562 jlongArray javaBuffer = get_metrics_buffer(env, target); 563 int dropCount = 0; 564 while (mObserver->getNextBuffer(env, javaBuffer, &dropCount)) { 565 env->CallVoidMethod(target, gFrameMetricsObserverClassInfo.callback, dropCount); 566 } 567 env->DeleteLocalRef(target); 568 } 569 570 mObserver->decStrong(nullptr); 571} 572 573static jboolean android_view_ThreadedRenderer_supportsOpenGL(JNIEnv* env, jobject clazz) { 574 char prop[PROPERTY_VALUE_MAX]; 575 if (property_get("ro.kernel.qemu", prop, NULL) == 0) { 576 // not in the emulator 577 return JNI_TRUE; 578 } 579 // In the emulator this property will be set > 0 when OpenGL ES 2.0 is 580 // enabled, 0 otherwise. On old emulator versions it will be undefined. 581 property_get("qemu.gles", prop, "0"); 582 return atoi(prop) > 0 ? JNI_TRUE : JNI_FALSE; 583} 584 585static void android_view_ThreadedRenderer_rotateProcessStatsBuffer(JNIEnv* env, jobject clazz) { 586 RenderProxy::rotateProcessStatsBuffer(); 587} 588 589static void android_view_ThreadedRenderer_setProcessStatsBuffer(JNIEnv* env, jobject clazz, 590 jint fd) { 591 RenderProxy::setProcessStatsBuffer(fd); 592} 593 594static jint android_view_ThreadedRenderer_getRenderThreadTid(JNIEnv* env, jobject clazz, 595 jlong proxyPtr) { 596 RenderProxy* proxy = reinterpret_cast<RenderProxy*>(proxyPtr); 597 return proxy->getRenderThreadTid(); 598} 599 600static jlong android_view_ThreadedRenderer_createRootRenderNode(JNIEnv* env, jobject clazz) { 601 RootRenderNode* node = new RootRenderNode(env); 602 node->incStrong(0); 603 node->setName("RootRenderNode"); 604 return reinterpret_cast<jlong>(node); 605} 606 607static jlong android_view_ThreadedRenderer_createProxy(JNIEnv* env, jobject clazz, 608 jboolean translucent, jlong rootRenderNodePtr) { 609 RootRenderNode* rootRenderNode = reinterpret_cast<RootRenderNode*>(rootRenderNodePtr); 610 ContextFactoryImpl factory(rootRenderNode); 611 return (jlong) new RenderProxy(translucent, rootRenderNode, &factory); 612} 613 614static void android_view_ThreadedRenderer_deleteProxy(JNIEnv* env, jobject clazz, 615 jlong proxyPtr) { 616 RenderProxy* proxy = reinterpret_cast<RenderProxy*>(proxyPtr); 617 delete proxy; 618} 619 620static jboolean android_view_ThreadedRenderer_loadSystemProperties(JNIEnv* env, jobject clazz, 621 jlong proxyPtr) { 622 RenderProxy* proxy = reinterpret_cast<RenderProxy*>(proxyPtr); 623 return proxy->loadSystemProperties(); 624} 625 626static void android_view_ThreadedRenderer_setName(JNIEnv* env, jobject clazz, 627 jlong proxyPtr, jstring jname) { 628 RenderProxy* proxy = reinterpret_cast<RenderProxy*>(proxyPtr); 629 const char* name = env->GetStringUTFChars(jname, NULL); 630 proxy->setName(name); 631 env->ReleaseStringUTFChars(jname, name); 632} 633 634static void android_view_ThreadedRenderer_initialize(JNIEnv* env, jobject clazz, 635 jlong proxyPtr, jobject jsurface) { 636 RenderProxy* proxy = reinterpret_cast<RenderProxy*>(proxyPtr); 637 sp<Surface> surface = android_view_Surface_getSurface(env, jsurface); 638 proxy->initialize(surface); 639} 640 641static void android_view_ThreadedRenderer_updateSurface(JNIEnv* env, jobject clazz, 642 jlong proxyPtr, jobject jsurface) { 643 RenderProxy* proxy = reinterpret_cast<RenderProxy*>(proxyPtr); 644 sp<Surface> surface; 645 if (jsurface) { 646 surface = android_view_Surface_getSurface(env, jsurface); 647 } 648 proxy->updateSurface(surface); 649} 650 651static jboolean android_view_ThreadedRenderer_pauseSurface(JNIEnv* env, jobject clazz, 652 jlong proxyPtr, jobject jsurface) { 653 RenderProxy* proxy = reinterpret_cast<RenderProxy*>(proxyPtr); 654 sp<Surface> surface; 655 if (jsurface) { 656 surface = android_view_Surface_getSurface(env, jsurface); 657 } 658 return proxy->pauseSurface(surface); 659} 660 661static void android_view_ThreadedRenderer_setStopped(JNIEnv* env, jobject clazz, 662 jlong proxyPtr, jboolean stopped) { 663 RenderProxy* proxy = reinterpret_cast<RenderProxy*>(proxyPtr); 664 proxy->setStopped(stopped); 665} 666 667static void android_view_ThreadedRenderer_setup(JNIEnv* env, jobject clazz, jlong proxyPtr, 668 jfloat lightRadius, jint ambientShadowAlpha, jint spotShadowAlpha) { 669 RenderProxy* proxy = reinterpret_cast<RenderProxy*>(proxyPtr); 670 proxy->setup(lightRadius, ambientShadowAlpha, spotShadowAlpha); 671} 672 673static void android_view_ThreadedRenderer_setLightCenter(JNIEnv* env, jobject clazz, 674 jlong proxyPtr, jfloat lightX, jfloat lightY, jfloat lightZ) { 675 RenderProxy* proxy = reinterpret_cast<RenderProxy*>(proxyPtr); 676 proxy->setLightCenter((Vector3){lightX, lightY, lightZ}); 677} 678 679static void android_view_ThreadedRenderer_setOpaque(JNIEnv* env, jobject clazz, 680 jlong proxyPtr, jboolean opaque) { 681 RenderProxy* proxy = reinterpret_cast<RenderProxy*>(proxyPtr); 682 proxy->setOpaque(opaque); 683} 684 685static int android_view_ThreadedRenderer_syncAndDrawFrame(JNIEnv* env, jobject clazz, 686 jlong proxyPtr, jlongArray frameInfo, jint frameInfoSize) { 687 LOG_ALWAYS_FATAL_IF(frameInfoSize != UI_THREAD_FRAME_INFO_SIZE, 688 "Mismatched size expectations, given %d expected %d", 689 frameInfoSize, UI_THREAD_FRAME_INFO_SIZE); 690 RenderProxy* proxy = reinterpret_cast<RenderProxy*>(proxyPtr); 691 env->GetLongArrayRegion(frameInfo, 0, frameInfoSize, proxy->frameInfo()); 692 return proxy->syncAndDrawFrame(); 693} 694 695static void android_view_ThreadedRenderer_destroy(JNIEnv* env, jobject clazz, 696 jlong proxyPtr, jlong rootNodePtr) { 697 RootRenderNode* rootRenderNode = reinterpret_cast<RootRenderNode*>(rootNodePtr); 698 rootRenderNode->destroy(); 699 RenderProxy* proxy = reinterpret_cast<RenderProxy*>(proxyPtr); 700 proxy->destroy(); 701} 702 703static void android_view_ThreadedRenderer_registerAnimatingRenderNode(JNIEnv* env, jobject clazz, 704 jlong rootNodePtr, jlong animatingNodePtr) { 705 RootRenderNode* rootRenderNode = reinterpret_cast<RootRenderNode*>(rootNodePtr); 706 RenderNode* animatingNode = reinterpret_cast<RenderNode*>(animatingNodePtr); 707 rootRenderNode->attachAnimatingNode(animatingNode); 708} 709 710static void android_view_ThreadedRenderer_registerVectorDrawableAnimator(JNIEnv* env, jobject clazz, 711 jlong rootNodePtr, jlong animatorPtr) { 712 RootRenderNode* rootRenderNode = reinterpret_cast<RootRenderNode*>(rootNodePtr); 713 PropertyValuesAnimatorSet* animator = reinterpret_cast<PropertyValuesAnimatorSet*>(animatorPtr); 714 rootRenderNode->addVectorDrawableAnimator(animator); 715} 716 717static void android_view_ThreadedRenderer_invokeFunctor(JNIEnv* env, jobject clazz, 718 jlong functorPtr, jboolean waitForCompletion) { 719 Functor* functor = reinterpret_cast<Functor*>(functorPtr); 720 RenderProxy::invokeFunctor(functor, waitForCompletion); 721} 722 723static jlong android_view_ThreadedRenderer_createTextureLayer(JNIEnv* env, jobject clazz, 724 jlong proxyPtr) { 725 RenderProxy* proxy = reinterpret_cast<RenderProxy*>(proxyPtr); 726 DeferredLayerUpdater* layer = proxy->createTextureLayer(); 727 return reinterpret_cast<jlong>(layer); 728} 729 730static void android_view_ThreadedRenderer_buildLayer(JNIEnv* env, jobject clazz, 731 jlong proxyPtr, jlong nodePtr) { 732 RenderProxy* proxy = reinterpret_cast<RenderProxy*>(proxyPtr); 733 RenderNode* node = reinterpret_cast<RenderNode*>(nodePtr); 734 proxy->buildLayer(node); 735} 736 737static jboolean android_view_ThreadedRenderer_copyLayerInto(JNIEnv* env, jobject clazz, 738 jlong proxyPtr, jlong layerPtr, jobject jbitmap) { 739 RenderProxy* proxy = reinterpret_cast<RenderProxy*>(proxyPtr); 740 DeferredLayerUpdater* layer = reinterpret_cast<DeferredLayerUpdater*>(layerPtr); 741 SkBitmap bitmap; 742 GraphicsJNI::getSkBitmap(env, jbitmap, &bitmap); 743 return proxy->copyLayerInto(layer, bitmap); 744} 745 746static void android_view_ThreadedRenderer_pushLayerUpdate(JNIEnv* env, jobject clazz, 747 jlong proxyPtr, jlong layerPtr) { 748 RenderProxy* proxy = reinterpret_cast<RenderProxy*>(proxyPtr); 749 DeferredLayerUpdater* layer = reinterpret_cast<DeferredLayerUpdater*>(layerPtr); 750 proxy->pushLayerUpdate(layer); 751} 752 753static void android_view_ThreadedRenderer_cancelLayerUpdate(JNIEnv* env, jobject clazz, 754 jlong proxyPtr, jlong layerPtr) { 755 RenderProxy* proxy = reinterpret_cast<RenderProxy*>(proxyPtr); 756 DeferredLayerUpdater* layer = reinterpret_cast<DeferredLayerUpdater*>(layerPtr); 757 proxy->cancelLayerUpdate(layer); 758} 759 760static void android_view_ThreadedRenderer_detachSurfaceTexture(JNIEnv* env, jobject clazz, 761 jlong proxyPtr, jlong layerPtr) { 762 RenderProxy* proxy = reinterpret_cast<RenderProxy*>(proxyPtr); 763 DeferredLayerUpdater* layer = reinterpret_cast<DeferredLayerUpdater*>(layerPtr); 764 proxy->detachSurfaceTexture(layer); 765} 766 767static void android_view_ThreadedRenderer_destroyHardwareResources(JNIEnv* env, jobject clazz, 768 jlong proxyPtr) { 769 RenderProxy* proxy = reinterpret_cast<RenderProxy*>(proxyPtr); 770 proxy->destroyHardwareResources(); 771} 772 773static void android_view_ThreadedRenderer_trimMemory(JNIEnv* env, jobject clazz, 774 jint level) { 775 RenderProxy::trimMemory(level); 776} 777 778static void android_view_ThreadedRenderer_overrideProperty(JNIEnv* env, jobject clazz, 779 jstring name, jstring value) { 780 const char* nameCharArray = env->GetStringUTFChars(name, NULL); 781 const char* valueCharArray = env->GetStringUTFChars(value, NULL); 782 RenderProxy::overrideProperty(nameCharArray, valueCharArray); 783 env->ReleaseStringUTFChars(name, nameCharArray); 784 env->ReleaseStringUTFChars(name, valueCharArray); 785} 786 787static void android_view_ThreadedRenderer_fence(JNIEnv* env, jobject clazz, 788 jlong proxyPtr) { 789 RenderProxy* proxy = reinterpret_cast<RenderProxy*>(proxyPtr); 790 proxy->fence(); 791} 792 793static void android_view_ThreadedRenderer_stopDrawing(JNIEnv* env, jobject clazz, 794 jlong proxyPtr) { 795 RenderProxy* proxy = reinterpret_cast<RenderProxy*>(proxyPtr); 796 proxy->stopDrawing(); 797} 798 799static void android_view_ThreadedRenderer_notifyFramePending(JNIEnv* env, jobject clazz, 800 jlong proxyPtr) { 801 RenderProxy* proxy = reinterpret_cast<RenderProxy*>(proxyPtr); 802 proxy->notifyFramePending(); 803} 804 805static void android_view_ThreadedRenderer_serializeDisplayListTree(JNIEnv* env, jobject clazz, 806 jlong proxyPtr) { 807 RenderProxy* proxy = reinterpret_cast<RenderProxy*>(proxyPtr); 808 proxy->serializeDisplayListTree(); 809} 810 811static void android_view_ThreadedRenderer_dumpProfileInfo(JNIEnv* env, jobject clazz, 812 jlong proxyPtr, jobject javaFileDescriptor, jint dumpFlags) { 813 RenderProxy* proxy = reinterpret_cast<RenderProxy*>(proxyPtr); 814 int fd = jniGetFDFromFileDescriptor(env, javaFileDescriptor); 815 proxy->dumpProfileInfo(fd, dumpFlags); 816} 817 818static void android_view_ThreadedRenderer_addRenderNode(JNIEnv* env, jobject clazz, 819 jlong proxyPtr, jlong renderNodePtr, jboolean placeFront) { 820 RenderProxy* proxy = reinterpret_cast<RenderProxy*>(proxyPtr); 821 RenderNode* renderNode = reinterpret_cast<RenderNode*>(renderNodePtr); 822 proxy->addRenderNode(renderNode, placeFront); 823} 824 825static void android_view_ThreadedRenderer_removeRenderNode(JNIEnv* env, jobject clazz, 826 jlong proxyPtr, jlong renderNodePtr) { 827 RenderProxy* proxy = reinterpret_cast<RenderProxy*>(proxyPtr); 828 RenderNode* renderNode = reinterpret_cast<RenderNode*>(renderNodePtr); 829 proxy->removeRenderNode(renderNode); 830} 831 832static void android_view_ThreadedRendererd_drawRenderNode(JNIEnv* env, jobject clazz, 833 jlong proxyPtr, jlong renderNodePtr) { 834 RenderProxy* proxy = reinterpret_cast<RenderProxy*>(proxyPtr); 835 RenderNode* renderNode = reinterpret_cast<RenderNode*>(renderNodePtr); 836 proxy->drawRenderNode(renderNode); 837} 838 839static void android_view_ThreadedRenderer_setContentDrawBounds(JNIEnv* env, 840 jobject clazz, jlong proxyPtr, jint left, jint top, jint right, jint bottom) { 841 RenderProxy* proxy = reinterpret_cast<RenderProxy*>(proxyPtr); 842 proxy->setContentDrawBounds(left, top, right, bottom); 843} 844 845static jint android_view_ThreadedRenderer_copySurfaceInto(JNIEnv* env, 846 jobject clazz, jobject jsurface, jint left, jint top, 847 jint right, jint bottom, jobject jbitmap) { 848 SkBitmap bitmap; 849 GraphicsJNI::getSkBitmap(env, jbitmap, &bitmap); 850 sp<Surface> surface = android_view_Surface_getSurface(env, jsurface); 851 return RenderProxy::copySurfaceInto(surface, left, top, right, bottom, &bitmap); 852} 853 854// ---------------------------------------------------------------------------- 855// FrameMetricsObserver 856// ---------------------------------------------------------------------------- 857 858static jlong android_view_ThreadedRenderer_addFrameMetricsObserver(JNIEnv* env, 859 jclass clazz, jlong proxyPtr, jobject fso) { 860 JavaVM* vm = nullptr; 861 if (env->GetJavaVM(&vm) != JNI_OK) { 862 LOG_ALWAYS_FATAL("Unable to get Java VM"); 863 return 0; 864 } 865 866 renderthread::RenderProxy* renderProxy = 867 reinterpret_cast<renderthread::RenderProxy*>(proxyPtr); 868 869 FrameMetricsObserver* observer = new ObserverProxy(vm, fso); 870 renderProxy->addFrameMetricsObserver(observer); 871 return reinterpret_cast<jlong>(observer); 872} 873 874static void android_view_ThreadedRenderer_removeFrameMetricsObserver(JNIEnv* env, jclass clazz, 875 jlong proxyPtr, jlong observerPtr) { 876 FrameMetricsObserver* observer = reinterpret_cast<FrameMetricsObserver*>(observerPtr); 877 renderthread::RenderProxy* renderProxy = 878 reinterpret_cast<renderthread::RenderProxy*>(proxyPtr); 879 880 renderProxy->removeFrameMetricsObserver(observer); 881} 882 883// ---------------------------------------------------------------------------- 884// Shaders 885// ---------------------------------------------------------------------------- 886 887static void android_view_ThreadedRenderer_setupShadersDiskCache(JNIEnv* env, jobject clazz, 888 jstring diskCachePath) { 889 const char* cacheArray = env->GetStringUTFChars(diskCachePath, NULL); 890 egl_cache_t::get()->setCacheFilename(cacheArray); 891 env->ReleaseStringUTFChars(diskCachePath, cacheArray); 892} 893 894// ---------------------------------------------------------------------------- 895// JNI Glue 896// ---------------------------------------------------------------------------- 897 898const char* const kClassPathName = "android/view/ThreadedRenderer"; 899 900static const JNINativeMethod gMethods[] = { 901 { "nSupportsOpenGL", "()Z", (void*) android_view_ThreadedRenderer_supportsOpenGL }, 902 { "nRotateProcessStatsBuffer", "()V", (void*) android_view_ThreadedRenderer_rotateProcessStatsBuffer }, 903 { "nSetProcessStatsBuffer", "(I)V", (void*) android_view_ThreadedRenderer_setProcessStatsBuffer }, 904 { "nGetRenderThreadTid", "(J)I", (void*) android_view_ThreadedRenderer_getRenderThreadTid }, 905 { "nCreateRootRenderNode", "()J", (void*) android_view_ThreadedRenderer_createRootRenderNode }, 906 { "nCreateProxy", "(ZJ)J", (void*) android_view_ThreadedRenderer_createProxy }, 907 { "nDeleteProxy", "(J)V", (void*) android_view_ThreadedRenderer_deleteProxy }, 908 { "nLoadSystemProperties", "(J)Z", (void*) android_view_ThreadedRenderer_loadSystemProperties }, 909 { "nSetName", "(JLjava/lang/String;)V", (void*) android_view_ThreadedRenderer_setName }, 910 { "nInitialize", "(JLandroid/view/Surface;)V", (void*) android_view_ThreadedRenderer_initialize }, 911 { "nUpdateSurface", "(JLandroid/view/Surface;)V", (void*) android_view_ThreadedRenderer_updateSurface }, 912 { "nPauseSurface", "(JLandroid/view/Surface;)Z", (void*) android_view_ThreadedRenderer_pauseSurface }, 913 { "nSetStopped", "(JZ)V", (void*) android_view_ThreadedRenderer_setStopped }, 914 { "nSetup", "(JFII)V", (void*) android_view_ThreadedRenderer_setup }, 915 { "nSetLightCenter", "(JFFF)V", (void*) android_view_ThreadedRenderer_setLightCenter }, 916 { "nSetOpaque", "(JZ)V", (void*) android_view_ThreadedRenderer_setOpaque }, 917 { "nSyncAndDrawFrame", "(J[JI)I", (void*) android_view_ThreadedRenderer_syncAndDrawFrame }, 918 { "nDestroy", "(JJ)V", (void*) android_view_ThreadedRenderer_destroy }, 919 { "nRegisterAnimatingRenderNode", "(JJ)V", (void*) android_view_ThreadedRenderer_registerAnimatingRenderNode }, 920 { "nRegisterVectorDrawableAnimator", "(JJ)V", (void*) android_view_ThreadedRenderer_registerVectorDrawableAnimator }, 921 { "nInvokeFunctor", "(JZ)V", (void*) android_view_ThreadedRenderer_invokeFunctor }, 922 { "nCreateTextureLayer", "(J)J", (void*) android_view_ThreadedRenderer_createTextureLayer }, 923 { "nBuildLayer", "(JJ)V", (void*) android_view_ThreadedRenderer_buildLayer }, 924 { "nCopyLayerInto", "(JJLandroid/graphics/Bitmap;)Z", (void*) android_view_ThreadedRenderer_copyLayerInto }, 925 { "nPushLayerUpdate", "(JJ)V", (void*) android_view_ThreadedRenderer_pushLayerUpdate }, 926 { "nCancelLayerUpdate", "(JJ)V", (void*) android_view_ThreadedRenderer_cancelLayerUpdate }, 927 { "nDetachSurfaceTexture", "(JJ)V", (void*) android_view_ThreadedRenderer_detachSurfaceTexture }, 928 { "nDestroyHardwareResources", "(J)V", (void*) android_view_ThreadedRenderer_destroyHardwareResources }, 929 { "nTrimMemory", "(I)V", (void*) android_view_ThreadedRenderer_trimMemory }, 930 { "nOverrideProperty", "(Ljava/lang/String;Ljava/lang/String;)V", (void*) android_view_ThreadedRenderer_overrideProperty }, 931 { "nFence", "(J)V", (void*) android_view_ThreadedRenderer_fence }, 932 { "nStopDrawing", "(J)V", (void*) android_view_ThreadedRenderer_stopDrawing }, 933 { "nNotifyFramePending", "(J)V", (void*) android_view_ThreadedRenderer_notifyFramePending }, 934 { "nSerializeDisplayListTree", "(J)V", (void*) android_view_ThreadedRenderer_serializeDisplayListTree }, 935 { "nDumpProfileInfo", "(JLjava/io/FileDescriptor;I)V", (void*) android_view_ThreadedRenderer_dumpProfileInfo }, 936 { "setupShadersDiskCache", "(Ljava/lang/String;)V", 937 (void*) android_view_ThreadedRenderer_setupShadersDiskCache }, 938 { "nAddRenderNode", "(JJZ)V", (void*) android_view_ThreadedRenderer_addRenderNode}, 939 { "nRemoveRenderNode", "(JJ)V", (void*) android_view_ThreadedRenderer_removeRenderNode}, 940 { "nDrawRenderNode", "(JJ)V", (void*) android_view_ThreadedRendererd_drawRenderNode}, 941 { "nSetContentDrawBounds", "(JIIII)V", (void*)android_view_ThreadedRenderer_setContentDrawBounds}, 942 { "nAddFrameMetricsObserver", 943 "(JLandroid/view/FrameMetricsObserver;)J", 944 (void*)android_view_ThreadedRenderer_addFrameMetricsObserver }, 945 { "nRemoveFrameMetricsObserver", 946 "(JJ)V", 947 (void*)android_view_ThreadedRenderer_removeFrameMetricsObserver }, 948 { "nCopySurfaceInto", "(Landroid/view/Surface;IIIILandroid/graphics/Bitmap;)I", 949 (void*)android_view_ThreadedRenderer_copySurfaceInto }, 950}; 951 952int register_android_view_ThreadedRenderer(JNIEnv* env) { 953 jclass observerClass = FindClassOrDie(env, "android/view/FrameMetricsObserver"); 954 gFrameMetricsObserverClassInfo.frameMetrics = GetFieldIDOrDie( 955 env, observerClass, "mFrameMetrics", "Landroid/view/FrameMetrics;"); 956 gFrameMetricsObserverClassInfo.messageQueue = GetFieldIDOrDie( 957 env, observerClass, "mMessageQueue", "Landroid/os/MessageQueue;"); 958 gFrameMetricsObserverClassInfo.callback = GetMethodIDOrDie( 959 env, observerClass, "notifyDataAvailable", "(I)V"); 960 961 jclass metricsClass = FindClassOrDie(env, "android/view/FrameMetrics"); 962 gFrameMetricsObserverClassInfo.timingDataBuffer = GetFieldIDOrDie( 963 env, metricsClass, "mTimingData", "[J"); 964 965 return RegisterMethodsOrDie(env, kClassPathName, gMethods, NELEM(gMethods)); 966} 967 968}; // namespace android 969