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 <android_runtime/android_view_Surface.h> 36 #include <system/window.h> 37 38 #include "android_view_GraphicBuffer.h" 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 <JankTracker.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 53 namespace android { 54 55 using namespace android::uirenderer; 56 using namespace android::uirenderer::renderthread; 57 58 struct { 59 jfieldID frameMetrics; 60 jfieldID timingDataBuffer; 61 jfieldID messageQueue; 62 jmethodID callback; 63 } gFrameMetricsObserverClassInfo; 64 65 static 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 73 // TODO: Clean this up, it's a bit odd to need to call over to 74 // rendernode's jni layer. Probably means RootRenderNode should be pulled 75 // into HWUI with appropriate callbacks for the various JNI hooks so 76 // that RenderNode's JNI layer can handle its own thing 77 void onRenderNodeRemoved(JNIEnv* env, RenderNode* node); 78 79 class ScopedRemovedRenderNodeObserver : public TreeObserver { 80 public: 81 ScopedRemovedRenderNodeObserver(JNIEnv* env) : mEnv(env) {} 82 ~ScopedRemovedRenderNodeObserver() { 83 for (auto& node : mMaybeRemovedNodes) { 84 if (node->hasParents()) continue; 85 onRenderNodeRemoved(mEnv, node.get()); 86 } 87 } 88 89 virtual void onMaybeRemovedFromTree(RenderNode* node) override { 90 mMaybeRemovedNodes.insert(sp<RenderNode>(node)); 91 } 92 93 private: 94 JNIEnv* mEnv; 95 std::set< sp<RenderNode> > mMaybeRemovedNodes; 96 }; 97 98 class OnFinishedEvent { 99 public: 100 OnFinishedEvent(BaseRenderNodeAnimator* animator, AnimationListener* listener) 101 : animator(animator), listener(listener) {} 102 sp<BaseRenderNodeAnimator> animator; 103 sp<AnimationListener> listener; 104 }; 105 106 class InvokeAnimationListeners : public MessageHandler { 107 public: 108 InvokeAnimationListeners(std::vector<OnFinishedEvent>& events) { 109 mOnFinishedEvents.swap(events); 110 } 111 112 static void callOnFinished(OnFinishedEvent& event) { 113 event.listener->onAnimationFinished(event.animator.get()); 114 } 115 116 virtual void handleMessage(const Message& message) { 117 std::for_each(mOnFinishedEvents.begin(), mOnFinishedEvents.end(), callOnFinished); 118 mOnFinishedEvents.clear(); 119 } 120 121 private: 122 std::vector<OnFinishedEvent> mOnFinishedEvents; 123 }; 124 125 class RenderingException : public MessageHandler { 126 public: 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 141 private: 142 JavaVM* mVm; 143 std::string mMessage; 144 }; 145 146 class RootRenderNode : public RenderNode, ErrorHandler { 147 public: 148 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 // TODO: This is hacky 164 info.windowInsetLeft = -stagingProperties().getLeft(); 165 info.windowInsetTop = -stagingProperties().getTop(); 166 info.updateWindowPositions = true; 167 RenderNode::prepareTree(info); 168 info.updateWindowPositions = false; 169 info.windowInsetLeft = 0; 170 info.windowInsetTop = 0; 171 info.errorHandler = nullptr; 172 } 173 174 void sendMessage(const sp<MessageHandler>& handler) { 175 mLooper->sendMessage(handler, 0); 176 } 177 178 void attachAnimatingNode(RenderNode* animatingNode) { 179 mPendingAnimatingRenderNodes.push_back(animatingNode); 180 } 181 182 void doAttachAnimatingNodes(AnimationContext* context) { 183 for (size_t i = 0; i < mPendingAnimatingRenderNodes.size(); i++) { 184 RenderNode* node = mPendingAnimatingRenderNodes[i].get(); 185 context->addAnimatingRenderNode(*node); 186 } 187 mPendingAnimatingRenderNodes.clear(); 188 } 189 190 void destroy() { 191 for (auto& renderNode : mPendingAnimatingRenderNodes) { 192 renderNode->animators().endAllStagingAnimators(); 193 } 194 mPendingAnimatingRenderNodes.clear(); 195 } 196 197 private: 198 sp<Looper> mLooper; 199 JavaVM* mVm; 200 std::vector< sp<RenderNode> > mPendingAnimatingRenderNodes; 201 }; 202 203 class AnimationContextBridge : public AnimationContext { 204 public: 205 AnimationContextBridge(renderthread::TimeLord& clock, RootRenderNode* rootNode) 206 : AnimationContext(clock), mRootNode(rootNode) { 207 } 208 209 virtual ~AnimationContextBridge() {} 210 211 // Marks the start of a frame, which will update the frame time and move all 212 // next frame animations into the current frame 213 virtual void startFrame(TreeInfo::TraversalMode mode) { 214 if (mode == TreeInfo::MODE_FULL) { 215 mRootNode->doAttachAnimatingNodes(this); 216 } 217 AnimationContext::startFrame(mode); 218 } 219 220 // Runs any animations still left in mCurrentFrameAnimations 221 virtual void runRemainingAnimations(TreeInfo& info) { 222 AnimationContext::runRemainingAnimations(info); 223 postOnFinishedEvents(); 224 } 225 226 virtual void callOnFinished(BaseRenderNodeAnimator* animator, AnimationListener* listener) { 227 OnFinishedEvent event(animator, listener); 228 mOnFinishedEvents.push_back(event); 229 } 230 231 virtual void destroy() { 232 AnimationContext::destroy(); 233 postOnFinishedEvents(); 234 } 235 236 private: 237 sp<RootRenderNode> mRootNode; 238 std::vector<OnFinishedEvent> mOnFinishedEvents; 239 240 void postOnFinishedEvents() { 241 if (mOnFinishedEvents.size()) { 242 sp<InvokeAnimationListeners> message 243 = new InvokeAnimationListeners(mOnFinishedEvents); 244 mRootNode->sendMessage(message); 245 } 246 } 247 }; 248 249 class ContextFactoryImpl : public IContextFactory { 250 public: 251 ContextFactoryImpl(RootRenderNode* rootNode) : mRootNode(rootNode) {} 252 253 virtual AnimationContext* createAnimationContext(renderthread::TimeLord& clock) { 254 return new AnimationContextBridge(clock, mRootNode); 255 } 256 257 private: 258 RootRenderNode* mRootNode; 259 }; 260 261 class ObserverProxy; 262 263 class NotifyHandler : public MessageHandler { 264 public: 265 NotifyHandler(JavaVM* vm, ObserverProxy* observer) : mVm(vm), mObserver(observer) {} 266 267 virtual void handleMessage(const Message& message); 268 269 private: 270 JavaVM* const mVm; 271 ObserverProxy* const mObserver; 272 }; 273 274 static jlongArray get_metrics_buffer(JNIEnv* env, jobject observer) { 275 jobject frameMetrics = env->GetObjectField( 276 observer, gFrameMetricsObserverClassInfo.frameMetrics); 277 LOG_ALWAYS_FATAL_IF(frameMetrics == nullptr, "unable to retrieve data sink object"); 278 jobject buffer = env->GetObjectField( 279 frameMetrics, gFrameMetricsObserverClassInfo.timingDataBuffer); 280 LOG_ALWAYS_FATAL_IF(buffer == nullptr, "unable to retrieve data sink buffer"); 281 return reinterpret_cast<jlongArray>(buffer); 282 } 283 284 /* 285 * Implements JNI layer for hwui frame metrics reporting. 286 */ 287 class ObserverProxy : public FrameMetricsObserver { 288 public: 289 ObserverProxy(JavaVM *vm, jobject observer) : mVm(vm) { 290 JNIEnv* env = getenv(mVm); 291 292 mObserverWeak = env->NewWeakGlobalRef(observer); 293 LOG_ALWAYS_FATAL_IF(mObserverWeak == nullptr, 294 "unable to create frame stats observer reference"); 295 296 jlongArray buffer = get_metrics_buffer(env, observer); 297 jsize bufferSize = env->GetArrayLength(reinterpret_cast<jarray>(buffer)); 298 LOG_ALWAYS_FATAL_IF(bufferSize != kBufferSize, 299 "Mismatched Java/Native FrameMetrics data format."); 300 301 jobject messageQueueLocal = env->GetObjectField( 302 observer, gFrameMetricsObserverClassInfo.messageQueue); 303 mMessageQueue = android_os_MessageQueue_getMessageQueue(env, messageQueueLocal); 304 LOG_ALWAYS_FATAL_IF(mMessageQueue == nullptr, "message queue not available"); 305 306 mMessageHandler = new NotifyHandler(mVm, this); 307 LOG_ALWAYS_FATAL_IF(mMessageHandler == nullptr, 308 "OOM: unable to allocate NotifyHandler"); 309 } 310 311 ~ObserverProxy() { 312 JNIEnv* env = getenv(mVm); 313 env->DeleteWeakGlobalRef(mObserverWeak); 314 } 315 316 jweak getObserverReference() { 317 return mObserverWeak; 318 } 319 320 bool getNextBuffer(JNIEnv* env, jlongArray sink, int* dropCount) { 321 FrameMetricsNotification& elem = mRingBuffer[mNextInQueue]; 322 323 if (elem.hasData.load()) { 324 env->SetLongArrayRegion(sink, 0, kBufferSize, elem.buffer); 325 *dropCount = elem.dropCount; 326 mNextInQueue = (mNextInQueue + 1) % kRingSize; 327 elem.hasData = false; 328 return true; 329 } 330 331 return false; 332 } 333 334 virtual void notify(const int64_t* stats) { 335 FrameMetricsNotification& elem = mRingBuffer[mNextFree]; 336 337 if (!elem.hasData.load()) { 338 memcpy(elem.buffer, stats, kBufferSize * sizeof(stats[0])); 339 340 elem.dropCount = mDroppedReports; 341 mDroppedReports = 0; 342 343 incStrong(nullptr); 344 mNextFree = (mNextFree + 1) % kRingSize; 345 elem.hasData = true; 346 347 mMessageQueue->getLooper()->sendMessage(mMessageHandler, mMessage); 348 } else { 349 mDroppedReports++; 350 } 351 } 352 353 private: 354 static const int kBufferSize = static_cast<int>(FrameInfoIndex::NumIndexes); 355 static constexpr int kRingSize = 3; 356 357 class FrameMetricsNotification { 358 public: 359 FrameMetricsNotification() : hasData(false) {} 360 361 std::atomic_bool hasData; 362 int64_t buffer[kBufferSize]; 363 int dropCount = 0; 364 }; 365 366 JavaVM* const mVm; 367 jweak mObserverWeak; 368 jobject mJavaBufferGlobal; 369 370 sp<MessageQueue> mMessageQueue; 371 sp<NotifyHandler> mMessageHandler; 372 Message mMessage; 373 374 int mNextFree = 0; 375 int mNextInQueue = 0; 376 FrameMetricsNotification mRingBuffer[kRingSize]; 377 378 int mDroppedReports = 0; 379 }; 380 381 void NotifyHandler::handleMessage(const Message& message) { 382 JNIEnv* env = getenv(mVm); 383 384 jobject target = env->NewLocalRef(mObserver->getObserverReference()); 385 386 if (target != nullptr) { 387 jlongArray javaBuffer = get_metrics_buffer(env, target); 388 int dropCount = 0; 389 while (mObserver->getNextBuffer(env, javaBuffer, &dropCount)) { 390 env->CallVoidMethod(target, gFrameMetricsObserverClassInfo.callback, dropCount); 391 } 392 env->DeleteLocalRef(target); 393 } 394 395 mObserver->decStrong(nullptr); 396 } 397 398 static void android_view_ThreadedRenderer_setAtlas(JNIEnv* env, jobject clazz, 399 jlong proxyPtr, jobject graphicBuffer, jlongArray atlasMapArray) { 400 sp<GraphicBuffer> buffer = graphicBufferForJavaObject(env, graphicBuffer); 401 jsize len = env->GetArrayLength(atlasMapArray); 402 if (len <= 0) { 403 ALOGW("Failed to initialize atlas, invalid map length: %d", len); 404 return; 405 } 406 int64_t* map = new int64_t[len]; 407 env->GetLongArrayRegion(atlasMapArray, 0, len, map); 408 409 RenderProxy* proxy = reinterpret_cast<RenderProxy*>(proxyPtr); 410 proxy->setTextureAtlas(buffer, map, len); 411 } 412 413 static void android_view_ThreadedRenderer_setProcessStatsBuffer(JNIEnv* env, jobject clazz, 414 jlong proxyPtr, jint fd) { 415 RenderProxy* proxy = reinterpret_cast<RenderProxy*>(proxyPtr); 416 proxy->setProcessStatsBuffer(fd); 417 } 418 419 static jlong android_view_ThreadedRenderer_createRootRenderNode(JNIEnv* env, jobject clazz) { 420 RootRenderNode* node = new RootRenderNode(env); 421 node->incStrong(0); 422 node->setName("RootRenderNode"); 423 return reinterpret_cast<jlong>(node); 424 } 425 426 static jlong android_view_ThreadedRenderer_createProxy(JNIEnv* env, jobject clazz, 427 jboolean translucent, jlong rootRenderNodePtr) { 428 RootRenderNode* rootRenderNode = reinterpret_cast<RootRenderNode*>(rootRenderNodePtr); 429 ContextFactoryImpl factory(rootRenderNode); 430 return (jlong) new RenderProxy(translucent, rootRenderNode, &factory); 431 } 432 433 static void android_view_ThreadedRenderer_deleteProxy(JNIEnv* env, jobject clazz, 434 jlong proxyPtr) { 435 RenderProxy* proxy = reinterpret_cast<RenderProxy*>(proxyPtr); 436 delete proxy; 437 } 438 439 static jboolean android_view_ThreadedRenderer_loadSystemProperties(JNIEnv* env, jobject clazz, 440 jlong proxyPtr) { 441 RenderProxy* proxy = reinterpret_cast<RenderProxy*>(proxyPtr); 442 return proxy->loadSystemProperties(); 443 } 444 445 static void android_view_ThreadedRenderer_setName(JNIEnv* env, jobject clazz, 446 jlong proxyPtr, jstring jname) { 447 RenderProxy* proxy = reinterpret_cast<RenderProxy*>(proxyPtr); 448 const char* name = env->GetStringUTFChars(jname, NULL); 449 proxy->setName(name); 450 env->ReleaseStringUTFChars(jname, name); 451 } 452 453 static void android_view_ThreadedRenderer_initialize(JNIEnv* env, jobject clazz, 454 jlong proxyPtr, jobject jsurface) { 455 RenderProxy* proxy = reinterpret_cast<RenderProxy*>(proxyPtr); 456 sp<Surface> surface = android_view_Surface_getSurface(env, jsurface); 457 proxy->initialize(surface); 458 } 459 460 static void android_view_ThreadedRenderer_updateSurface(JNIEnv* env, jobject clazz, 461 jlong proxyPtr, jobject jsurface) { 462 RenderProxy* proxy = reinterpret_cast<RenderProxy*>(proxyPtr); 463 sp<Surface> surface; 464 if (jsurface) { 465 surface = android_view_Surface_getSurface(env, jsurface); 466 } 467 proxy->updateSurface(surface); 468 } 469 470 static jboolean android_view_ThreadedRenderer_pauseSurface(JNIEnv* env, jobject clazz, 471 jlong proxyPtr, jobject jsurface) { 472 RenderProxy* proxy = reinterpret_cast<RenderProxy*>(proxyPtr); 473 sp<Surface> surface; 474 if (jsurface) { 475 surface = android_view_Surface_getSurface(env, jsurface); 476 } 477 return proxy->pauseSurface(surface); 478 } 479 480 static void android_view_ThreadedRenderer_setStopped(JNIEnv* env, jobject clazz, 481 jlong proxyPtr, jboolean stopped) { 482 RenderProxy* proxy = reinterpret_cast<RenderProxy*>(proxyPtr); 483 proxy->setStopped(stopped); 484 } 485 486 static void android_view_ThreadedRenderer_setup(JNIEnv* env, jobject clazz, jlong proxyPtr, 487 jint width, jint height, jfloat lightRadius, jint ambientShadowAlpha, jint spotShadowAlpha) { 488 RenderProxy* proxy = reinterpret_cast<RenderProxy*>(proxyPtr); 489 proxy->setup(width, height, lightRadius, ambientShadowAlpha, spotShadowAlpha); 490 } 491 492 static void android_view_ThreadedRenderer_setLightCenter(JNIEnv* env, jobject clazz, 493 jlong proxyPtr, jfloat lightX, jfloat lightY, jfloat lightZ) { 494 RenderProxy* proxy = reinterpret_cast<RenderProxy*>(proxyPtr); 495 proxy->setLightCenter((Vector3){lightX, lightY, lightZ}); 496 } 497 498 static void android_view_ThreadedRenderer_setOpaque(JNIEnv* env, jobject clazz, 499 jlong proxyPtr, jboolean opaque) { 500 RenderProxy* proxy = reinterpret_cast<RenderProxy*>(proxyPtr); 501 proxy->setOpaque(opaque); 502 } 503 504 static int android_view_ThreadedRenderer_syncAndDrawFrame(JNIEnv* env, jobject clazz, 505 jlong proxyPtr, jlongArray frameInfo, jint frameInfoSize) { 506 LOG_ALWAYS_FATAL_IF(frameInfoSize != UI_THREAD_FRAME_INFO_SIZE, 507 "Mismatched size expectations, given %d expected %d", 508 frameInfoSize, UI_THREAD_FRAME_INFO_SIZE); 509 RenderProxy* proxy = reinterpret_cast<RenderProxy*>(proxyPtr); 510 ScopedRemovedRenderNodeObserver observer(env); 511 env->GetLongArrayRegion(frameInfo, 0, frameInfoSize, proxy->frameInfo()); 512 return proxy->syncAndDrawFrame(&observer); 513 } 514 515 static void android_view_ThreadedRenderer_destroy(JNIEnv* env, jobject clazz, 516 jlong proxyPtr, jlong rootNodePtr) { 517 ScopedRemovedRenderNodeObserver observer(env); 518 RootRenderNode* rootRenderNode = reinterpret_cast<RootRenderNode*>(rootNodePtr); 519 rootRenderNode->destroy(); 520 RenderProxy* proxy = reinterpret_cast<RenderProxy*>(proxyPtr); 521 proxy->destroy(&observer); 522 } 523 524 static void android_view_ThreadedRenderer_registerAnimatingRenderNode(JNIEnv* env, jobject clazz, 525 jlong rootNodePtr, jlong animatingNodePtr) { 526 RootRenderNode* rootRenderNode = reinterpret_cast<RootRenderNode*>(rootNodePtr); 527 RenderNode* animatingNode = reinterpret_cast<RenderNode*>(animatingNodePtr); 528 rootRenderNode->attachAnimatingNode(animatingNode); 529 } 530 531 static void android_view_ThreadedRenderer_invokeFunctor(JNIEnv* env, jobject clazz, 532 jlong functorPtr, jboolean waitForCompletion) { 533 Functor* functor = reinterpret_cast<Functor*>(functorPtr); 534 RenderProxy::invokeFunctor(functor, waitForCompletion); 535 } 536 537 static jlong android_view_ThreadedRenderer_createTextureLayer(JNIEnv* env, jobject clazz, 538 jlong proxyPtr) { 539 RenderProxy* proxy = reinterpret_cast<RenderProxy*>(proxyPtr); 540 DeferredLayerUpdater* layer = proxy->createTextureLayer(); 541 return reinterpret_cast<jlong>(layer); 542 } 543 544 static void android_view_ThreadedRenderer_buildLayer(JNIEnv* env, jobject clazz, 545 jlong proxyPtr, jlong nodePtr) { 546 ScopedRemovedRenderNodeObserver observer(env); 547 RenderProxy* proxy = reinterpret_cast<RenderProxy*>(proxyPtr); 548 RenderNode* node = reinterpret_cast<RenderNode*>(nodePtr); 549 proxy->buildLayer(node, &observer); 550 } 551 552 static jboolean android_view_ThreadedRenderer_copyLayerInto(JNIEnv* env, jobject clazz, 553 jlong proxyPtr, jlong layerPtr, jobject jbitmap) { 554 RenderProxy* proxy = reinterpret_cast<RenderProxy*>(proxyPtr); 555 DeferredLayerUpdater* layer = reinterpret_cast<DeferredLayerUpdater*>(layerPtr); 556 SkBitmap bitmap; 557 GraphicsJNI::getSkBitmap(env, jbitmap, &bitmap); 558 return proxy->copyLayerInto(layer, bitmap); 559 } 560 561 static void android_view_ThreadedRenderer_pushLayerUpdate(JNIEnv* env, jobject clazz, 562 jlong proxyPtr, jlong layerPtr) { 563 RenderProxy* proxy = reinterpret_cast<RenderProxy*>(proxyPtr); 564 DeferredLayerUpdater* layer = reinterpret_cast<DeferredLayerUpdater*>(layerPtr); 565 proxy->pushLayerUpdate(layer); 566 } 567 568 static void android_view_ThreadedRenderer_cancelLayerUpdate(JNIEnv* env, jobject clazz, 569 jlong proxyPtr, jlong layerPtr) { 570 RenderProxy* proxy = reinterpret_cast<RenderProxy*>(proxyPtr); 571 DeferredLayerUpdater* layer = reinterpret_cast<DeferredLayerUpdater*>(layerPtr); 572 proxy->cancelLayerUpdate(layer); 573 } 574 575 static void android_view_ThreadedRenderer_detachSurfaceTexture(JNIEnv* env, jobject clazz, 576 jlong proxyPtr, jlong layerPtr) { 577 RenderProxy* proxy = reinterpret_cast<RenderProxy*>(proxyPtr); 578 DeferredLayerUpdater* layer = reinterpret_cast<DeferredLayerUpdater*>(layerPtr); 579 proxy->detachSurfaceTexture(layer); 580 } 581 582 static void android_view_ThreadedRenderer_destroyHardwareResources(JNIEnv* env, jobject clazz, 583 jlong proxyPtr) { 584 ScopedRemovedRenderNodeObserver observer(env); 585 RenderProxy* proxy = reinterpret_cast<RenderProxy*>(proxyPtr); 586 proxy->destroyHardwareResources(&observer); 587 } 588 589 static void android_view_ThreadedRenderer_trimMemory(JNIEnv* env, jobject clazz, 590 jint level) { 591 RenderProxy::trimMemory(level); 592 } 593 594 static void android_view_ThreadedRenderer_overrideProperty(JNIEnv* env, jobject clazz, 595 jstring name, jstring value) { 596 const char* nameCharArray = env->GetStringUTFChars(name, NULL); 597 const char* valueCharArray = env->GetStringUTFChars(value, NULL); 598 RenderProxy::overrideProperty(nameCharArray, valueCharArray); 599 env->ReleaseStringUTFChars(name, nameCharArray); 600 env->ReleaseStringUTFChars(name, valueCharArray); 601 } 602 603 static void android_view_ThreadedRenderer_fence(JNIEnv* env, jobject clazz, 604 jlong proxyPtr) { 605 RenderProxy* proxy = reinterpret_cast<RenderProxy*>(proxyPtr); 606 proxy->fence(); 607 } 608 609 static void android_view_ThreadedRenderer_stopDrawing(JNIEnv* env, jobject clazz, 610 jlong proxyPtr) { 611 RenderProxy* proxy = reinterpret_cast<RenderProxy*>(proxyPtr); 612 proxy->stopDrawing(); 613 } 614 615 static void android_view_ThreadedRenderer_notifyFramePending(JNIEnv* env, jobject clazz, 616 jlong proxyPtr) { 617 RenderProxy* proxy = reinterpret_cast<RenderProxy*>(proxyPtr); 618 proxy->notifyFramePending(); 619 } 620 621 static void android_view_ThreadedRenderer_serializeDisplayListTree(JNIEnv* env, jobject clazz, 622 jlong proxyPtr) { 623 RenderProxy* proxy = reinterpret_cast<RenderProxy*>(proxyPtr); 624 proxy->serializeDisplayListTree(); 625 } 626 627 static void android_view_ThreadedRenderer_dumpProfileInfo(JNIEnv* env, jobject clazz, 628 jlong proxyPtr, jobject javaFileDescriptor, jint dumpFlags) { 629 RenderProxy* proxy = reinterpret_cast<RenderProxy*>(proxyPtr); 630 int fd = jniGetFDFromFileDescriptor(env, javaFileDescriptor); 631 proxy->dumpProfileInfo(fd, dumpFlags); 632 } 633 634 static void android_view_ThreadedRenderer_dumpProfileData(JNIEnv* env, jobject clazz, 635 jbyteArray jdata, jobject javaFileDescriptor) { 636 int fd = jniGetFDFromFileDescriptor(env, javaFileDescriptor); 637 ScopedByteArrayRO buffer(env, jdata); 638 if (buffer.get()) { 639 JankTracker::dumpBuffer(buffer.get(), buffer.size(), fd); 640 } 641 } 642 643 static void android_view_ThreadedRenderer_addRenderNode(JNIEnv* env, jobject clazz, 644 jlong proxyPtr, jlong renderNodePtr, jboolean placeFront) { 645 RenderProxy* proxy = reinterpret_cast<RenderProxy*>(proxyPtr); 646 RenderNode* renderNode = reinterpret_cast<RenderNode*>(renderNodePtr); 647 proxy->addRenderNode(renderNode, placeFront); 648 } 649 650 static void android_view_ThreadedRenderer_removeRenderNode(JNIEnv* env, jobject clazz, 651 jlong proxyPtr, jlong renderNodePtr) { 652 RenderProxy* proxy = reinterpret_cast<RenderProxy*>(proxyPtr); 653 RenderNode* renderNode = reinterpret_cast<RenderNode*>(renderNodePtr); 654 proxy->removeRenderNode(renderNode); 655 } 656 657 static void android_view_ThreadedRendererd_drawRenderNode(JNIEnv* env, jobject clazz, 658 jlong proxyPtr, jlong renderNodePtr) { 659 RenderProxy* proxy = reinterpret_cast<RenderProxy*>(proxyPtr); 660 RenderNode* renderNode = reinterpret_cast<RenderNode*>(renderNodePtr); 661 proxy->drawRenderNode(renderNode); 662 } 663 664 static void android_view_ThreadedRenderer_setContentDrawBounds(JNIEnv* env, 665 jobject clazz, jlong proxyPtr, jint left, jint top, jint right, jint bottom) { 666 RenderProxy* proxy = reinterpret_cast<RenderProxy*>(proxyPtr); 667 proxy->setContentDrawBounds(left, top, right, bottom); 668 } 669 670 static jint android_view_ThreadedRenderer_copySurfaceInto(JNIEnv* env, 671 jobject clazz, jobject jsurface, jobject jbitmap) { 672 SkBitmap bitmap; 673 GraphicsJNI::getSkBitmap(env, jbitmap, &bitmap); 674 sp<Surface> surface = android_view_Surface_getSurface(env, jsurface); 675 return RenderProxy::copySurfaceInto(surface, &bitmap); 676 } 677 678 // ---------------------------------------------------------------------------- 679 // FrameMetricsObserver 680 // ---------------------------------------------------------------------------- 681 682 static jlong android_view_ThreadedRenderer_addFrameMetricsObserver(JNIEnv* env, 683 jclass clazz, jlong proxyPtr, jobject fso) { 684 JavaVM* vm = nullptr; 685 if (env->GetJavaVM(&vm) != JNI_OK) { 686 LOG_ALWAYS_FATAL("Unable to get Java VM"); 687 return 0; 688 } 689 690 renderthread::RenderProxy* renderProxy = 691 reinterpret_cast<renderthread::RenderProxy*>(proxyPtr); 692 693 FrameMetricsObserver* observer = new ObserverProxy(vm, fso); 694 renderProxy->addFrameMetricsObserver(observer); 695 return reinterpret_cast<jlong>(observer); 696 } 697 698 static void android_view_ThreadedRenderer_removeFrameMetricsObserver(JNIEnv* env, jclass clazz, 699 jlong proxyPtr, jlong observerPtr) { 700 FrameMetricsObserver* observer = reinterpret_cast<FrameMetricsObserver*>(observerPtr); 701 renderthread::RenderProxy* renderProxy = 702 reinterpret_cast<renderthread::RenderProxy*>(proxyPtr); 703 704 renderProxy->removeFrameMetricsObserver(observer); 705 } 706 707 // ---------------------------------------------------------------------------- 708 // Shaders 709 // ---------------------------------------------------------------------------- 710 711 static void android_view_ThreadedRenderer_setupShadersDiskCache(JNIEnv* env, jobject clazz, 712 jstring diskCachePath) { 713 const char* cacheArray = env->GetStringUTFChars(diskCachePath, NULL); 714 egl_cache_t::get()->setCacheFilename(cacheArray); 715 env->ReleaseStringUTFChars(diskCachePath, cacheArray); 716 } 717 718 // ---------------------------------------------------------------------------- 719 // JNI Glue 720 // ---------------------------------------------------------------------------- 721 722 const char* const kClassPathName = "android/view/ThreadedRenderer"; 723 724 static const JNINativeMethod gMethods[] = { 725 { "nSetAtlas", "(JLandroid/view/GraphicBuffer;[J)V", (void*) android_view_ThreadedRenderer_setAtlas }, 726 { "nSetProcessStatsBuffer", "(JI)V", (void*) android_view_ThreadedRenderer_setProcessStatsBuffer }, 727 { "nCreateRootRenderNode", "()J", (void*) android_view_ThreadedRenderer_createRootRenderNode }, 728 { "nCreateProxy", "(ZJ)J", (void*) android_view_ThreadedRenderer_createProxy }, 729 { "nDeleteProxy", "(J)V", (void*) android_view_ThreadedRenderer_deleteProxy }, 730 { "nLoadSystemProperties", "(J)Z", (void*) android_view_ThreadedRenderer_loadSystemProperties }, 731 { "nSetName", "(JLjava/lang/String;)V", (void*) android_view_ThreadedRenderer_setName }, 732 { "nInitialize", "(JLandroid/view/Surface;)V", (void*) android_view_ThreadedRenderer_initialize }, 733 { "nUpdateSurface", "(JLandroid/view/Surface;)V", (void*) android_view_ThreadedRenderer_updateSurface }, 734 { "nPauseSurface", "(JLandroid/view/Surface;)Z", (void*) android_view_ThreadedRenderer_pauseSurface }, 735 { "nSetStopped", "(JZ)V", (void*) android_view_ThreadedRenderer_setStopped }, 736 { "nSetup", "(JIIFII)V", (void*) android_view_ThreadedRenderer_setup }, 737 { "nSetLightCenter", "(JFFF)V", (void*) android_view_ThreadedRenderer_setLightCenter }, 738 { "nSetOpaque", "(JZ)V", (void*) android_view_ThreadedRenderer_setOpaque }, 739 { "nSyncAndDrawFrame", "(J[JI)I", (void*) android_view_ThreadedRenderer_syncAndDrawFrame }, 740 { "nDestroy", "(JJ)V", (void*) android_view_ThreadedRenderer_destroy }, 741 { "nRegisterAnimatingRenderNode", "(JJ)V", (void*) android_view_ThreadedRenderer_registerAnimatingRenderNode }, 742 { "nInvokeFunctor", "(JZ)V", (void*) android_view_ThreadedRenderer_invokeFunctor }, 743 { "nCreateTextureLayer", "(J)J", (void*) android_view_ThreadedRenderer_createTextureLayer }, 744 { "nBuildLayer", "(JJ)V", (void*) android_view_ThreadedRenderer_buildLayer }, 745 { "nCopyLayerInto", "(JJLandroid/graphics/Bitmap;)Z", (void*) android_view_ThreadedRenderer_copyLayerInto }, 746 { "nPushLayerUpdate", "(JJ)V", (void*) android_view_ThreadedRenderer_pushLayerUpdate }, 747 { "nCancelLayerUpdate", "(JJ)V", (void*) android_view_ThreadedRenderer_cancelLayerUpdate }, 748 { "nDetachSurfaceTexture", "(JJ)V", (void*) android_view_ThreadedRenderer_detachSurfaceTexture }, 749 { "nDestroyHardwareResources", "(J)V", (void*) android_view_ThreadedRenderer_destroyHardwareResources }, 750 { "nTrimMemory", "(I)V", (void*) android_view_ThreadedRenderer_trimMemory }, 751 { "nOverrideProperty", "(Ljava/lang/String;Ljava/lang/String;)V", (void*) android_view_ThreadedRenderer_overrideProperty }, 752 { "nFence", "(J)V", (void*) android_view_ThreadedRenderer_fence }, 753 { "nStopDrawing", "(J)V", (void*) android_view_ThreadedRenderer_stopDrawing }, 754 { "nNotifyFramePending", "(J)V", (void*) android_view_ThreadedRenderer_notifyFramePending }, 755 { "nSerializeDisplayListTree", "(J)V", (void*) android_view_ThreadedRenderer_serializeDisplayListTree }, 756 { "nDumpProfileInfo", "(JLjava/io/FileDescriptor;I)V", (void*) android_view_ThreadedRenderer_dumpProfileInfo }, 757 { "nDumpProfileData", "([BLjava/io/FileDescriptor;)V", (void*) android_view_ThreadedRenderer_dumpProfileData }, 758 { "setupShadersDiskCache", "(Ljava/lang/String;)V", 759 (void*) android_view_ThreadedRenderer_setupShadersDiskCache }, 760 { "nAddRenderNode", "(JJZ)V", (void*) android_view_ThreadedRenderer_addRenderNode}, 761 { "nRemoveRenderNode", "(JJ)V", (void*) android_view_ThreadedRenderer_removeRenderNode}, 762 { "nDrawRenderNode", "(JJ)V", (void*) android_view_ThreadedRendererd_drawRenderNode}, 763 { "nSetContentDrawBounds", "(JIIII)V", (void*)android_view_ThreadedRenderer_setContentDrawBounds}, 764 { "nAddFrameMetricsObserver", 765 "(JLandroid/view/FrameMetricsObserver;)J", 766 (void*)android_view_ThreadedRenderer_addFrameMetricsObserver }, 767 { "nRemoveFrameMetricsObserver", 768 "(JJ)V", 769 (void*)android_view_ThreadedRenderer_removeFrameMetricsObserver }, 770 { "nCopySurfaceInto", "(Landroid/view/Surface;Landroid/graphics/Bitmap;)I", 771 (void*)android_view_ThreadedRenderer_copySurfaceInto }, 772 }; 773 774 int register_android_view_ThreadedRenderer(JNIEnv* env) { 775 jclass observerClass = FindClassOrDie(env, "android/view/FrameMetricsObserver"); 776 gFrameMetricsObserverClassInfo.frameMetrics = GetFieldIDOrDie( 777 env, observerClass, "mFrameMetrics", "Landroid/view/FrameMetrics;"); 778 gFrameMetricsObserverClassInfo.messageQueue = GetFieldIDOrDie( 779 env, observerClass, "mMessageQueue", "Landroid/os/MessageQueue;"); 780 gFrameMetricsObserverClassInfo.callback = GetMethodIDOrDie( 781 env, observerClass, "notifyDataAvailable", "(I)V"); 782 783 jclass metricsClass = FindClassOrDie(env, "android/view/FrameMetrics"); 784 gFrameMetricsObserverClassInfo.timingDataBuffer = GetFieldIDOrDie( 785 env, metricsClass, "mTimingData", "[J"); 786 787 return RegisterMethodsOrDie(env, kClassPathName, gMethods, NELEM(gMethods)); 788 } 789 790 }; // namespace android 791