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