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