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