2 * Copyright (C) 2010 The Android Open Source Project
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
8 * http://www.apache.org/licenses/LICENSE-2.0
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.
17 #define LOG_TAG "ThreadedRenderer"
18 #define ATRACE_TAG ATRACE_TAG_VIEW
25 #include <nativehelper/JNIHelp.h>
26 #include "core_jni_helpers.h"
27 #include <GraphicsJNI.h>
28 #include <nativehelper/ScopedPrimitiveArray.h>
30 #include <gui/BufferItemConsumer.h>
31 #include <gui/BufferQueue.h>
32 #include <gui/Surface.h>
35 #include <EGL/eglext.h>
36 #include <private/EGL/cache.h>
38 #include <utils/Looper.h>
39 #include <utils/RefBase.h>
40 #include <utils/StrongPointer.h>
41 #include <utils/Timers.h>
42 #include <utils/TraceUtils.h>
43 #include <android_runtime/android_view_Surface.h>
44 #include <system/window.h>
46 #include "android_os_MessageQueue.h"
49 #include <AnimationContext.h>
50 #include <FrameInfo.h>
51 #include <FrameMetricsObserver.h>
52 #include <IContextFactory.h>
53 #include <Properties.h>
54 #include <PropertyValuesAnimatorSet.h>
55 #include <RenderNode.h>
56 #include <renderthread/CanvasContext.h>
57 #include <renderthread/RenderProxy.h>
58 #include <renderthread/RenderTask.h>
59 #include <renderthread/RenderThread.h>
60 #include <pipeline/skia/ShaderCache.h>
64 using namespace android::uirenderer;
65 using namespace android::uirenderer::renderthread;
68 jfieldID frameMetrics;
69 jfieldID timingDataBuffer;
70 jfieldID messageQueue;
72 } gFrameMetricsObserverClassInfo;
75 jmethodID onFrameDraw;
76 } gFrameDrawingCallback;
79 jmethodID onFrameComplete;
80 } gFrameCompleteCallback;
82 static JNIEnv* getenv(JavaVM* vm) {
84 if (vm->GetEnv(reinterpret_cast<void**>(&env), JNI_VERSION_1_6) != JNI_OK) {
85 LOG_ALWAYS_FATAL("Failed to get JNIEnv for JavaVM: %p", vm);
90 class OnFinishedEvent {
92 OnFinishedEvent(BaseRenderNodeAnimator* animator, AnimationListener* listener)
93 : animator(animator), listener(listener) {}
94 sp<BaseRenderNodeAnimator> animator;
95 sp<AnimationListener> listener;
98 class InvokeAnimationListeners : public MessageHandler {
100 explicit InvokeAnimationListeners(std::vector<OnFinishedEvent>& events) {
101 mOnFinishedEvents.swap(events);
104 static void callOnFinished(OnFinishedEvent& event) {
105 event.listener->onAnimationFinished(event.animator.get());
108 virtual void handleMessage(const Message& message) {
109 std::for_each(mOnFinishedEvents.begin(), mOnFinishedEvents.end(), callOnFinished);
110 mOnFinishedEvents.clear();
114 std::vector<OnFinishedEvent> mOnFinishedEvents;
117 class FinishAndInvokeListener : public MessageHandler {
119 explicit FinishAndInvokeListener(PropertyValuesAnimatorSet* anim)
121 mListener = anim->getOneShotListener();
122 mRequestId = anim->getRequestId();
125 virtual void handleMessage(const Message& message) {
126 if (mAnimator->getRequestId() == mRequestId) {
127 // Request Id has not changed, meaning there's no animation lifecyle change since the
128 // message is posted, so go ahead and call finish to make sure the PlayState is properly
129 // updated. This is needed because before the next frame comes in from UI thread to
130 // trigger an animation update, there could be reverse/cancel etc. So we need to update
131 // the playstate in time to ensure all the subsequent events get chained properly.
134 mListener->onAnimationFinished(nullptr);
137 sp<PropertyValuesAnimatorSet> mAnimator;
138 sp<AnimationListener> mListener;
142 class RenderingException : public MessageHandler {
144 RenderingException(JavaVM* vm, const std::string& message)
146 , mMessage(message) {
149 virtual void handleMessage(const Message&) {
150 throwException(mVm, mMessage);
153 static void throwException(JavaVM* vm, const std::string& message) {
154 JNIEnv* env = getenv(vm);
155 jniThrowException(env, "java/lang/IllegalStateException", message.c_str());
160 std::string mMessage;
163 class FrameCompleteWrapper : public MessageHandler {
165 FrameCompleteWrapper(JNIEnv* env, jobject jobject) {
166 mLooper = Looper::getForThread();
167 LOG_ALWAYS_FATAL_IF(!mLooper.get(), "Must create runnable on a Looper thread!");
168 env->GetJavaVM(&mVm);
169 mObject = env->NewGlobalRef(jobject);
170 LOG_ALWAYS_FATAL_IF(!mObject, "Failed to make global ref");
173 virtual ~FrameCompleteWrapper() {
177 void postFrameComplete(int64_t frameNr) {
180 mLooper->sendMessage(this, 0);
184 virtual void handleMessage(const Message&) {
186 ATRACE_FORMAT("frameComplete %" PRId64, mFrameNr);
187 getenv(mVm)->CallVoidMethod(mObject, gFrameCompleteCallback.onFrameComplete, mFrameNr);
196 int64_t mFrameNr = -1;
198 void releaseObject() {
200 getenv(mVm)->DeleteGlobalRef(mObject);
206 class RootRenderNode : public RenderNode, ErrorHandler {
208 explicit RootRenderNode(JNIEnv* env) : RenderNode() {
209 mLooper = Looper::getForThread();
210 LOG_ALWAYS_FATAL_IF(!mLooper.get(),
211 "Must create RootRenderNode on a thread with a looper!");
212 env->GetJavaVM(&mVm);
215 virtual ~RootRenderNode() {}
217 virtual void onError(const std::string& message) override {
218 mLooper->sendMessage(new RenderingException(mVm, message), 0);
221 virtual void prepareTree(TreeInfo& info) override {
222 info.errorHandler = this;
224 for (auto& anim : mRunningVDAnimators) {
225 // Assume that the property change in VD from the animators will not be consumed. Mark
226 // otherwise if the VDs are found in the display list tree. For VDs that are not in
227 // the display list tree, we stop providing animation pulses by 1) removing them from
228 // the animation list, 2) post a delayed message to end them at end time so their
229 // listeners can receive the corresponding callbacks.
230 anim->getVectorDrawable()->setPropertyChangeWillBeConsumed(false);
231 // Mark the VD dirty so it will damage itself during prepareTree.
232 anim->getVectorDrawable()->markDirty();
234 if (info.mode == TreeInfo::MODE_FULL) {
235 for (auto &anim : mPausedVDAnimators) {
236 anim->getVectorDrawable()->setPropertyChangeWillBeConsumed(false);
237 anim->getVectorDrawable()->markDirty();
240 // TODO: This is hacky
241 info.updateWindowPositions = true;
242 RenderNode::prepareTree(info);
243 info.updateWindowPositions = false;
244 info.errorHandler = nullptr;
247 void sendMessage(const sp<MessageHandler>& handler) {
248 mLooper->sendMessage(handler, 0);
251 void sendMessageDelayed(const sp<MessageHandler>& handler, nsecs_t delayInMs) {
252 mLooper->sendMessageDelayed(ms2ns(delayInMs), handler, 0);
255 void attachAnimatingNode(RenderNode* animatingNode) {
256 mPendingAnimatingRenderNodes.push_back(animatingNode);
259 void attachPendingVectorDrawableAnimators() {
260 mRunningVDAnimators.insert(mPendingVectorDrawableAnimators.begin(),
261 mPendingVectorDrawableAnimators.end());
262 mPendingVectorDrawableAnimators.clear();
265 void detachAnimators() {
266 // Remove animators from the list and post a delayed message in future to end the animator
267 // For infinite animators, remove the listener so we no longer hold a global ref to the AVD
268 // java object, and therefore the AVD objects in both native and Java can be properly
270 for (auto& anim : mRunningVDAnimators) {
271 detachVectorDrawableAnimator(anim.get());
272 anim->clearOneShotListener();
274 for (auto& anim : mPausedVDAnimators) {
275 anim->clearOneShotListener();
277 mRunningVDAnimators.clear();
278 mPausedVDAnimators.clear();
281 // Move all the animators to the paused list, and send a delayed message to notify the finished
283 void pauseAnimators() {
284 mPausedVDAnimators.insert(mRunningVDAnimators.begin(), mRunningVDAnimators.end());
285 for (auto& anim : mRunningVDAnimators) {
286 detachVectorDrawableAnimator(anim.get());
288 mRunningVDAnimators.clear();
291 void doAttachAnimatingNodes(AnimationContext* context) {
292 for (size_t i = 0; i < mPendingAnimatingRenderNodes.size(); i++) {
293 RenderNode* node = mPendingAnimatingRenderNodes[i].get();
294 context->addAnimatingRenderNode(*node);
296 mPendingAnimatingRenderNodes.clear();
299 // Run VectorDrawable animators after prepareTree.
300 void runVectorDrawableAnimators(AnimationContext* context, TreeInfo& info) {
302 if (info.mode == TreeInfo::MODE_FULL) {
303 pushStagingVectorDrawableAnimators(context);
306 // Run the animators in the running list.
307 for (auto it = mRunningVDAnimators.begin(); it != mRunningVDAnimators.end();) {
308 if ((*it)->animate(*context)) {
309 it = mRunningVDAnimators.erase(it);
315 // Run the animators in paused list during full sync.
316 if (info.mode == TreeInfo::MODE_FULL) {
317 // During full sync we also need to pulse paused animators, in case their targets
318 // have been added back to the display list. All the animators that passed the
319 // scheduled finish time will be removed from the paused list.
320 for (auto it = mPausedVDAnimators.begin(); it != mPausedVDAnimators.end();) {
321 if ((*it)->animate(*context)) {
322 // Animator has finished, remove from the list.
323 it = mPausedVDAnimators.erase(it);
330 // Move the animators with a target not in DisplayList to paused list.
331 for (auto it = mRunningVDAnimators.begin(); it != mRunningVDAnimators.end();) {
332 if (!(*it)->getVectorDrawable()->getPropertyChangeWillBeConsumed()) {
333 // Vector Drawable is not in the display list, we should remove this animator from
334 // the list, put it in the paused list, and post a delayed message to end the
336 detachVectorDrawableAnimator(it->get());
337 mPausedVDAnimators.insert(*it);
338 it = mRunningVDAnimators.erase(it);
344 // Move the animators with a target in DisplayList from paused list to running list, and
346 if (info.mode == TreeInfo::MODE_FULL) {
347 // Check whether any paused animator's target is back in Display List. If so, put the
348 // animator back in the running list.
349 for (auto it = mPausedVDAnimators.begin(); it != mPausedVDAnimators.end();) {
350 if ((*it)->getVectorDrawable()->getPropertyChangeWillBeConsumed()) {
351 mRunningVDAnimators.insert(*it);
352 it = mPausedVDAnimators.erase(it);
357 // Trim paused VD animators at full sync, so that when Java loses reference to an
358 // animator, we know we won't be requested to animate it any more, then we remove such
359 // animators from the paused list so they can be properly freed. We also remove the
360 // animators from paused list when the time elapsed since start has exceeded duration.
361 trimPausedVDAnimators(context);
364 info.out.hasAnimations |= !mRunningVDAnimators.empty();
367 void trimPausedVDAnimators(AnimationContext* context) {
368 // Trim paused vector drawable animator list.
369 for (auto it = mPausedVDAnimators.begin(); it != mPausedVDAnimators.end();) {
370 // Remove paused VD animator if no one else is referencing it. Note that animators that
371 // have passed scheduled finish time are removed from list when they are being pulsed
372 // before prepare tree.
373 // TODO: this is a bit hacky, need to figure out a better way to track when the paused
374 // animators should be freed.
375 if ((*it)->getStrongCount() == 1) {
376 it = mPausedVDAnimators.erase(it);
383 void pushStagingVectorDrawableAnimators(AnimationContext* context) {
384 for (auto& anim : mRunningVDAnimators) {
385 anim->pushStaging(*context);
390 for (auto& renderNode : mPendingAnimatingRenderNodes) {
391 renderNode->animators().endAllStagingAnimators();
393 mPendingAnimatingRenderNodes.clear();
394 mPendingVectorDrawableAnimators.clear();
397 void addVectorDrawableAnimator(PropertyValuesAnimatorSet* anim) {
398 mPendingVectorDrawableAnimators.insert(anim);
404 std::vector< sp<RenderNode> > mPendingAnimatingRenderNodes;
405 std::set< sp<PropertyValuesAnimatorSet> > mPendingVectorDrawableAnimators;
406 std::set< sp<PropertyValuesAnimatorSet> > mRunningVDAnimators;
407 // mPausedVDAnimators stores a list of animators that have not yet passed the finish time, but
408 // their VectorDrawable targets are no longer in the DisplayList. We skip these animators when
409 // render thread runs animators independent of UI thread (i.e. RT_ONLY mode). These animators
410 // need to be re-activated once their VD target is added back into DisplayList. Since that could
411 // only happen when we do a full sync, we need to make sure to pulse these paused animators at
412 // full sync. If any animator's VD target is found in DisplayList during a full sync, we move
413 // the animator back to the running list.
414 std::set< sp<PropertyValuesAnimatorSet> > mPausedVDAnimators;
415 void detachVectorDrawableAnimator(PropertyValuesAnimatorSet* anim) {
416 if (anim->isInfinite() || !anim->isRunning()) {
417 // Do not need to post anything if the animation is infinite (i.e. no meaningful
418 // end listener action), or if the animation has already ended.
421 nsecs_t remainingTimeInMs = anim->getRemainingPlayTime();
422 // Post a delayed onFinished event that is scheduled to be handled when the animator ends.
423 if (anim->getOneShotListener()) {
424 // VectorDrawable's oneshot listener is updated when there are user triggered animation
425 // lifecycle changes, such as start(), end(), etc. By using checking and clearing
426 // one shot listener, we ensure the same end listener event gets posted only once.
427 // Therefore no duplicates. Another benefit of using one shot listener is that no
428 // removal is necessary: the end time of animation will not change unless triggered by
429 // user events, in which case the already posted listener's id will become stale, and
430 // the onFinished callback will then be ignored.
431 sp<FinishAndInvokeListener> message
432 = new FinishAndInvokeListener(anim);
433 sendMessageDelayed(message, remainingTimeInMs);
434 anim->clearOneShotListener();
439 class AnimationContextBridge : public AnimationContext {
441 AnimationContextBridge(renderthread::TimeLord& clock, RootRenderNode* rootNode)
442 : AnimationContext(clock), mRootNode(rootNode) {
445 virtual ~AnimationContextBridge() {}
447 // Marks the start of a frame, which will update the frame time and move all
448 // next frame animations into the current frame
449 virtual void startFrame(TreeInfo::TraversalMode mode) {
450 if (mode == TreeInfo::MODE_FULL) {
451 mRootNode->doAttachAnimatingNodes(this);
452 mRootNode->attachPendingVectorDrawableAnimators();
454 AnimationContext::startFrame(mode);
457 // Runs any animations still left in mCurrentFrameAnimations
458 virtual void runRemainingAnimations(TreeInfo& info) {
459 AnimationContext::runRemainingAnimations(info);
460 mRootNode->runVectorDrawableAnimators(this, info);
461 postOnFinishedEvents();
464 virtual void pauseAnimators() override {
465 mRootNode->pauseAnimators();
468 virtual void callOnFinished(BaseRenderNodeAnimator* animator, AnimationListener* listener) {
469 OnFinishedEvent event(animator, listener);
470 mOnFinishedEvents.push_back(event);
473 virtual void destroy() {
474 AnimationContext::destroy();
475 mRootNode->detachAnimators();
476 postOnFinishedEvents();
480 sp<RootRenderNode> mRootNode;
481 std::vector<OnFinishedEvent> mOnFinishedEvents;
483 void postOnFinishedEvents() {
484 if (mOnFinishedEvents.size()) {
485 sp<InvokeAnimationListeners> message
486 = new InvokeAnimationListeners(mOnFinishedEvents);
487 mRootNode->sendMessage(message);
492 class ContextFactoryImpl : public IContextFactory {
494 explicit ContextFactoryImpl(RootRenderNode* rootNode) : mRootNode(rootNode) {}
496 virtual AnimationContext* createAnimationContext(renderthread::TimeLord& clock) {
497 return new AnimationContextBridge(clock, mRootNode);
501 RootRenderNode* mRootNode;
506 class NotifyHandler : public MessageHandler {
508 NotifyHandler(JavaVM* vm, ObserverProxy* observer) : mVm(vm), mObserver(observer) {}
510 virtual void handleMessage(const Message& message);
514 ObserverProxy* const mObserver;
517 static jlongArray get_metrics_buffer(JNIEnv* env, jobject observer) {
518 jobject frameMetrics = env->GetObjectField(
519 observer, gFrameMetricsObserverClassInfo.frameMetrics);
520 LOG_ALWAYS_FATAL_IF(frameMetrics == nullptr, "unable to retrieve data sink object");
521 jobject buffer = env->GetObjectField(
522 frameMetrics, gFrameMetricsObserverClassInfo.timingDataBuffer);
523 LOG_ALWAYS_FATAL_IF(buffer == nullptr, "unable to retrieve data sink buffer");
524 return reinterpret_cast<jlongArray>(buffer);
528 * Implements JNI layer for hwui frame metrics reporting.
530 class ObserverProxy : public FrameMetricsObserver {
532 ObserverProxy(JavaVM *vm, jobject observer) : mVm(vm) {
533 JNIEnv* env = getenv(mVm);
535 mObserverWeak = env->NewWeakGlobalRef(observer);
536 LOG_ALWAYS_FATAL_IF(mObserverWeak == nullptr,
537 "unable to create frame stats observer reference");
539 jlongArray buffer = get_metrics_buffer(env, observer);
540 jsize bufferSize = env->GetArrayLength(reinterpret_cast<jarray>(buffer));
541 LOG_ALWAYS_FATAL_IF(bufferSize != kBufferSize,
542 "Mismatched Java/Native FrameMetrics data format.");
544 jobject messageQueueLocal = env->GetObjectField(
545 observer, gFrameMetricsObserverClassInfo.messageQueue);
546 mMessageQueue = android_os_MessageQueue_getMessageQueue(env, messageQueueLocal);
547 LOG_ALWAYS_FATAL_IF(mMessageQueue == nullptr, "message queue not available");
549 mMessageHandler = new NotifyHandler(mVm, this);
550 LOG_ALWAYS_FATAL_IF(mMessageHandler == nullptr,
551 "OOM: unable to allocate NotifyHandler");
555 JNIEnv* env = getenv(mVm);
556 env->DeleteWeakGlobalRef(mObserverWeak);
559 jweak getObserverReference() {
560 return mObserverWeak;
563 bool getNextBuffer(JNIEnv* env, jlongArray sink, int* dropCount) {
564 FrameMetricsNotification& elem = mRingBuffer[mNextInQueue];
566 if (elem.hasData.load()) {
567 env->SetLongArrayRegion(sink, 0, kBufferSize, elem.buffer);
568 *dropCount = elem.dropCount;
569 mNextInQueue = (mNextInQueue + 1) % kRingSize;
570 elem.hasData = false;
577 virtual void notify(const int64_t* stats) {
578 FrameMetricsNotification& elem = mRingBuffer[mNextFree];
580 if (!elem.hasData.load()) {
581 memcpy(elem.buffer, stats, kBufferSize * sizeof(stats[0]));
583 elem.dropCount = mDroppedReports;
587 mNextFree = (mNextFree + 1) % kRingSize;
590 mMessageQueue->getLooper()->sendMessage(mMessageHandler, mMessage);
597 static const int kBufferSize = static_cast<int>(FrameInfoIndex::NumIndexes);
598 static constexpr int kRingSize = 3;
600 class FrameMetricsNotification {
602 FrameMetricsNotification() : hasData(false) {}
604 std::atomic_bool hasData;
605 int64_t buffer[kBufferSize];
612 sp<MessageQueue> mMessageQueue;
613 sp<NotifyHandler> mMessageHandler;
617 int mNextInQueue = 0;
618 FrameMetricsNotification mRingBuffer[kRingSize];
620 int mDroppedReports = 0;
623 void NotifyHandler::handleMessage(const Message& message) {
624 JNIEnv* env = getenv(mVm);
626 jobject target = env->NewLocalRef(mObserver->getObserverReference());
628 if (target != nullptr) {
629 jlongArray javaBuffer = get_metrics_buffer(env, target);
631 while (mObserver->getNextBuffer(env, javaBuffer, &dropCount)) {
632 env->CallVoidMethod(target, gFrameMetricsObserverClassInfo.callback, dropCount);
634 env->DeleteLocalRef(target);
637 mObserver->decStrong(nullptr);
640 static void android_view_ThreadedRenderer_rotateProcessStatsBuffer(JNIEnv* env, jobject clazz) {
641 RenderProxy::rotateProcessStatsBuffer();
644 static void android_view_ThreadedRenderer_setProcessStatsBuffer(JNIEnv* env, jobject clazz,
646 RenderProxy::setProcessStatsBuffer(fd);
649 static jint android_view_ThreadedRenderer_getRenderThreadTid(JNIEnv* env, jobject clazz,
651 RenderProxy* proxy = reinterpret_cast<RenderProxy*>(proxyPtr);
652 return proxy->getRenderThreadTid();
655 static jlong android_view_ThreadedRenderer_createRootRenderNode(JNIEnv* env, jobject clazz) {
656 RootRenderNode* node = new RootRenderNode(env);
658 node->setName("RootRenderNode");
659 return reinterpret_cast<jlong>(node);
662 static jlong android_view_ThreadedRenderer_createProxy(JNIEnv* env, jobject clazz,
663 jboolean translucent, jlong rootRenderNodePtr) {
664 RootRenderNode* rootRenderNode = reinterpret_cast<RootRenderNode*>(rootRenderNodePtr);
665 ContextFactoryImpl factory(rootRenderNode);
666 return (jlong) new RenderProxy(translucent, rootRenderNode, &factory);
669 static void android_view_ThreadedRenderer_deleteProxy(JNIEnv* env, jobject clazz,
671 RenderProxy* proxy = reinterpret_cast<RenderProxy*>(proxyPtr);
675 static jboolean android_view_ThreadedRenderer_loadSystemProperties(JNIEnv* env, jobject clazz,
677 RenderProxy* proxy = reinterpret_cast<RenderProxy*>(proxyPtr);
678 return proxy->loadSystemProperties();
681 static void android_view_ThreadedRenderer_setName(JNIEnv* env, jobject clazz,
682 jlong proxyPtr, jstring jname) {
683 RenderProxy* proxy = reinterpret_cast<RenderProxy*>(proxyPtr);
684 const char* name = env->GetStringUTFChars(jname, NULL);
685 proxy->setName(name);
686 env->ReleaseStringUTFChars(jname, name);
689 static void android_view_ThreadedRenderer_initialize(JNIEnv* env, jobject clazz,
690 jlong proxyPtr, jobject jsurface) {
691 RenderProxy* proxy = reinterpret_cast<RenderProxy*>(proxyPtr);
692 sp<Surface> surface = android_view_Surface_getSurface(env, jsurface);
693 proxy->initialize(surface);
696 static void android_view_ThreadedRenderer_updateSurface(JNIEnv* env, jobject clazz,
697 jlong proxyPtr, jobject jsurface) {
698 RenderProxy* proxy = reinterpret_cast<RenderProxy*>(proxyPtr);
701 surface = android_view_Surface_getSurface(env, jsurface);
703 proxy->updateSurface(surface);
706 static jboolean android_view_ThreadedRenderer_pauseSurface(JNIEnv* env, jobject clazz,
707 jlong proxyPtr, jobject jsurface) {
708 RenderProxy* proxy = reinterpret_cast<RenderProxy*>(proxyPtr);
711 surface = android_view_Surface_getSurface(env, jsurface);
713 return proxy->pauseSurface(surface);
716 static void android_view_ThreadedRenderer_setStopped(JNIEnv* env, jobject clazz,
717 jlong proxyPtr, jboolean stopped) {
718 RenderProxy* proxy = reinterpret_cast<RenderProxy*>(proxyPtr);
719 proxy->setStopped(stopped);
722 static void android_view_ThreadedRenderer_setup(JNIEnv* env, jobject clazz, jlong proxyPtr,
723 jfloat lightRadius, jint ambientShadowAlpha, jint spotShadowAlpha) {
724 RenderProxy* proxy = reinterpret_cast<RenderProxy*>(proxyPtr);
725 proxy->setup(lightRadius, ambientShadowAlpha, spotShadowAlpha);
728 static void android_view_ThreadedRenderer_setLightCenter(JNIEnv* env, jobject clazz,
729 jlong proxyPtr, jfloat lightX, jfloat lightY, jfloat lightZ) {
730 RenderProxy* proxy = reinterpret_cast<RenderProxy*>(proxyPtr);
731 proxy->setLightCenter((Vector3){lightX, lightY, lightZ});
734 static void android_view_ThreadedRenderer_setOpaque(JNIEnv* env, jobject clazz,
735 jlong proxyPtr, jboolean opaque) {
736 RenderProxy* proxy = reinterpret_cast<RenderProxy*>(proxyPtr);
737 proxy->setOpaque(opaque);
740 static void android_view_ThreadedRenderer_setWideGamut(JNIEnv* env, jobject clazz,
741 jlong proxyPtr, jboolean wideGamut) {
742 RenderProxy* proxy = reinterpret_cast<RenderProxy*>(proxyPtr);
743 proxy->setWideGamut(wideGamut);
746 static int android_view_ThreadedRenderer_syncAndDrawFrame(JNIEnv* env, jobject clazz,
747 jlong proxyPtr, jlongArray frameInfo, jint frameInfoSize) {
748 LOG_ALWAYS_FATAL_IF(frameInfoSize != UI_THREAD_FRAME_INFO_SIZE,
749 "Mismatched size expectations, given %d expected %d",
750 frameInfoSize, UI_THREAD_FRAME_INFO_SIZE);
751 RenderProxy* proxy = reinterpret_cast<RenderProxy*>(proxyPtr);
752 env->GetLongArrayRegion(frameInfo, 0, frameInfoSize, proxy->frameInfo());
753 return proxy->syncAndDrawFrame();
756 static void android_view_ThreadedRenderer_destroy(JNIEnv* env, jobject clazz,
757 jlong proxyPtr, jlong rootNodePtr) {
758 RootRenderNode* rootRenderNode = reinterpret_cast<RootRenderNode*>(rootNodePtr);
759 rootRenderNode->destroy();
760 RenderProxy* proxy = reinterpret_cast<RenderProxy*>(proxyPtr);
764 static void android_view_ThreadedRenderer_registerAnimatingRenderNode(JNIEnv* env, jobject clazz,
765 jlong rootNodePtr, jlong animatingNodePtr) {
766 RootRenderNode* rootRenderNode = reinterpret_cast<RootRenderNode*>(rootNodePtr);
767 RenderNode* animatingNode = reinterpret_cast<RenderNode*>(animatingNodePtr);
768 rootRenderNode->attachAnimatingNode(animatingNode);
771 static void android_view_ThreadedRenderer_registerVectorDrawableAnimator(JNIEnv* env, jobject clazz,
772 jlong rootNodePtr, jlong animatorPtr) {
773 RootRenderNode* rootRenderNode = reinterpret_cast<RootRenderNode*>(rootNodePtr);
774 PropertyValuesAnimatorSet* animator = reinterpret_cast<PropertyValuesAnimatorSet*>(animatorPtr);
775 rootRenderNode->addVectorDrawableAnimator(animator);
778 static void android_view_ThreadedRenderer_invokeFunctor(JNIEnv* env, jobject clazz,
779 jlong functorPtr, jboolean waitForCompletion) {
780 Functor* functor = reinterpret_cast<Functor*>(functorPtr);
781 RenderProxy::invokeFunctor(functor, waitForCompletion);
784 static jlong android_view_ThreadedRenderer_createTextureLayer(JNIEnv* env, jobject clazz,
786 RenderProxy* proxy = reinterpret_cast<RenderProxy*>(proxyPtr);
787 DeferredLayerUpdater* layer = proxy->createTextureLayer();
788 return reinterpret_cast<jlong>(layer);
791 static void android_view_ThreadedRenderer_buildLayer(JNIEnv* env, jobject clazz,
792 jlong proxyPtr, jlong nodePtr) {
793 RenderProxy* proxy = reinterpret_cast<RenderProxy*>(proxyPtr);
794 RenderNode* node = reinterpret_cast<RenderNode*>(nodePtr);
795 proxy->buildLayer(node);
798 static jboolean android_view_ThreadedRenderer_copyLayerInto(JNIEnv* env, jobject clazz,
799 jlong proxyPtr, jlong layerPtr, jobject jbitmap) {
800 RenderProxy* proxy = reinterpret_cast<RenderProxy*>(proxyPtr);
801 DeferredLayerUpdater* layer = reinterpret_cast<DeferredLayerUpdater*>(layerPtr);
803 GraphicsJNI::getSkBitmap(env, jbitmap, &bitmap);
804 return proxy->copyLayerInto(layer, bitmap);
807 static void android_view_ThreadedRenderer_pushLayerUpdate(JNIEnv* env, jobject clazz,
808 jlong proxyPtr, jlong layerPtr) {
809 RenderProxy* proxy = reinterpret_cast<RenderProxy*>(proxyPtr);
810 DeferredLayerUpdater* layer = reinterpret_cast<DeferredLayerUpdater*>(layerPtr);
811 proxy->pushLayerUpdate(layer);
814 static void android_view_ThreadedRenderer_cancelLayerUpdate(JNIEnv* env, jobject clazz,
815 jlong proxyPtr, jlong layerPtr) {
816 RenderProxy* proxy = reinterpret_cast<RenderProxy*>(proxyPtr);
817 DeferredLayerUpdater* layer = reinterpret_cast<DeferredLayerUpdater*>(layerPtr);
818 proxy->cancelLayerUpdate(layer);
821 static void android_view_ThreadedRenderer_detachSurfaceTexture(JNIEnv* env, jobject clazz,
822 jlong proxyPtr, jlong layerPtr) {
823 RenderProxy* proxy = reinterpret_cast<RenderProxy*>(proxyPtr);
824 DeferredLayerUpdater* layer = reinterpret_cast<DeferredLayerUpdater*>(layerPtr);
825 proxy->detachSurfaceTexture(layer);
828 static void android_view_ThreadedRenderer_destroyHardwareResources(JNIEnv* env, jobject clazz,
830 RenderProxy* proxy = reinterpret_cast<RenderProxy*>(proxyPtr);
831 proxy->destroyHardwareResources();
834 static void android_view_ThreadedRenderer_trimMemory(JNIEnv* env, jobject clazz,
836 RenderProxy::trimMemory(level);
839 static void android_view_ThreadedRenderer_overrideProperty(JNIEnv* env, jobject clazz,
840 jstring name, jstring value) {
841 const char* nameCharArray = env->GetStringUTFChars(name, NULL);
842 const char* valueCharArray = env->GetStringUTFChars(value, NULL);
843 RenderProxy::overrideProperty(nameCharArray, valueCharArray);
844 env->ReleaseStringUTFChars(name, nameCharArray);
845 env->ReleaseStringUTFChars(name, valueCharArray);
848 static void android_view_ThreadedRenderer_fence(JNIEnv* env, jobject clazz,
850 RenderProxy* proxy = reinterpret_cast<RenderProxy*>(proxyPtr);
854 static void android_view_ThreadedRenderer_stopDrawing(JNIEnv* env, jobject clazz,
856 RenderProxy* proxy = reinterpret_cast<RenderProxy*>(proxyPtr);
857 proxy->stopDrawing();
860 static void android_view_ThreadedRenderer_notifyFramePending(JNIEnv* env, jobject clazz,
862 RenderProxy* proxy = reinterpret_cast<RenderProxy*>(proxyPtr);
863 proxy->notifyFramePending();
866 static void android_view_ThreadedRenderer_serializeDisplayListTree(JNIEnv* env, jobject clazz,
868 RenderProxy* proxy = reinterpret_cast<RenderProxy*>(proxyPtr);
869 proxy->serializeDisplayListTree();
872 static void android_view_ThreadedRenderer_dumpProfileInfo(JNIEnv* env, jobject clazz,
873 jlong proxyPtr, jobject javaFileDescriptor, jint dumpFlags) {
874 RenderProxy* proxy = reinterpret_cast<RenderProxy*>(proxyPtr);
875 int fd = jniGetFDFromFileDescriptor(env, javaFileDescriptor);
876 proxy->dumpProfileInfo(fd, dumpFlags);
879 static void android_view_ThreadedRenderer_addRenderNode(JNIEnv* env, jobject clazz,
880 jlong proxyPtr, jlong renderNodePtr, jboolean placeFront) {
881 RenderProxy* proxy = reinterpret_cast<RenderProxy*>(proxyPtr);
882 RenderNode* renderNode = reinterpret_cast<RenderNode*>(renderNodePtr);
883 proxy->addRenderNode(renderNode, placeFront);
886 static void android_view_ThreadedRenderer_removeRenderNode(JNIEnv* env, jobject clazz,
887 jlong proxyPtr, jlong renderNodePtr) {
888 RenderProxy* proxy = reinterpret_cast<RenderProxy*>(proxyPtr);
889 RenderNode* renderNode = reinterpret_cast<RenderNode*>(renderNodePtr);
890 proxy->removeRenderNode(renderNode);
893 static void android_view_ThreadedRendererd_drawRenderNode(JNIEnv* env, jobject clazz,
894 jlong proxyPtr, jlong renderNodePtr) {
895 RenderProxy* proxy = reinterpret_cast<RenderProxy*>(proxyPtr);
896 RenderNode* renderNode = reinterpret_cast<RenderNode*>(renderNodePtr);
897 proxy->drawRenderNode(renderNode);
900 static void android_view_ThreadedRenderer_setContentDrawBounds(JNIEnv* env,
901 jobject clazz, jlong proxyPtr, jint left, jint top, jint right, jint bottom) {
902 RenderProxy* proxy = reinterpret_cast<RenderProxy*>(proxyPtr);
903 proxy->setContentDrawBounds(left, top, right, bottom);
906 class JGlobalRefHolder {
908 JGlobalRefHolder(JavaVM* vm, jobject object) : mVm(vm), mObject(object) {}
910 virtual ~JGlobalRefHolder() {
911 getenv(mVm)->DeleteGlobalRef(mObject);
915 jobject object() { return mObject; }
916 JavaVM* vm() { return mVm; }
919 JGlobalRefHolder(const JGlobalRefHolder&) = delete;
920 void operator=(const JGlobalRefHolder&) = delete;
926 static void android_view_ThreadedRenderer_setFrameCallback(JNIEnv* env,
927 jobject clazz, jlong proxyPtr, jobject frameCallback) {
928 RenderProxy* proxy = reinterpret_cast<RenderProxy*>(proxyPtr);
929 if (!frameCallback) {
930 proxy->setFrameCallback(nullptr);
932 JavaVM* vm = nullptr;
933 LOG_ALWAYS_FATAL_IF(env->GetJavaVM(&vm) != JNI_OK, "Unable to get Java VM");
934 auto globalCallbackRef = std::make_shared<JGlobalRefHolder>(vm,
935 env->NewGlobalRef(frameCallback));
936 proxy->setFrameCallback([globalCallbackRef](int64_t frameNr) {
937 JNIEnv* env = getenv(globalCallbackRef->vm());
938 env->CallVoidMethod(globalCallbackRef->object(), gFrameDrawingCallback.onFrameDraw,
939 static_cast<jlong>(frameNr));
944 static void android_view_ThreadedRenderer_setFrameCompleteCallback(JNIEnv* env,
945 jobject clazz, jlong proxyPtr, jobject callback) {
946 RenderProxy* proxy = reinterpret_cast<RenderProxy*>(proxyPtr);
948 proxy->setFrameCompleteCallback(nullptr);
950 sp<FrameCompleteWrapper> wrapper = new FrameCompleteWrapper{env, callback};
951 proxy->setFrameCompleteCallback([wrapper](int64_t frameNr) {
952 wrapper->postFrameComplete(frameNr);
957 static jint android_view_ThreadedRenderer_copySurfaceInto(JNIEnv* env,
958 jobject clazz, jobject jsurface, jint left, jint top,
959 jint right, jint bottom, jobject jbitmap) {
961 GraphicsJNI::getSkBitmap(env, jbitmap, &bitmap);
962 sp<Surface> surface = android_view_Surface_getSurface(env, jsurface);
963 return RenderProxy::copySurfaceInto(surface, left, top, right, bottom, &bitmap);
966 class ContextFactory : public IContextFactory {
968 virtual AnimationContext* createAnimationContext(renderthread::TimeLord& clock) {
969 return new AnimationContext(clock);
973 static jobject android_view_ThreadedRenderer_createHardwareBitmapFromRenderNode(JNIEnv* env,
974 jobject clazz, jlong renderNodePtr, jint jwidth, jint jheight) {
975 RenderNode* renderNode = reinterpret_cast<RenderNode*>(renderNodePtr);
976 if (jwidth <= 0 || jheight <= 0) {
977 ALOGW("Invalid width %d or height %d", jwidth, jheight);
981 uint32_t width = jwidth;
982 uint32_t height = jheight;
984 // Create a Surface wired up to a BufferItemConsumer
985 sp<IGraphicBufferProducer> producer;
986 sp<IGraphicBufferConsumer> rawConsumer;
987 BufferQueue::createBufferQueue(&producer, &rawConsumer);
988 // We only need 1 buffer but some drivers have bugs so workaround it by setting max count to 2
989 rawConsumer->setMaxBufferCount(2);
990 sp<BufferItemConsumer> consumer = new BufferItemConsumer(rawConsumer,
991 GRALLOC_USAGE_HW_TEXTURE | GRALLOC_USAGE_SW_READ_NEVER | GRALLOC_USAGE_SW_WRITE_NEVER);
992 consumer->setDefaultBufferSize(width, height);
993 sp<Surface> surface = new Surface(producer);
995 // Render into the surface
997 ContextFactory factory;
998 RenderProxy proxy{true, renderNode, &factory};
999 proxy.loadSystemProperties();
1000 proxy.setSwapBehavior(SwapBehavior::kSwap_discardBuffer);
1001 proxy.initialize(surface);
1002 // Shadows can't be used via this interface, so just set the light source
1004 proxy.setup(0, 0, 0);
1005 proxy.setLightCenter((Vector3){0, 0, 0});
1006 nsecs_t vsync = systemTime(CLOCK_MONOTONIC);
1007 UiFrameInfoBuilder(proxy.frameInfo())
1008 .setVsync(vsync, vsync)
1009 .addFlag(FrameInfoFlags::SurfaceCanvas);
1010 proxy.syncAndDrawFrame();
1013 // Yank out the GraphicBuffer
1014 BufferItem bufferItem;
1016 if ((err = consumer->acquireBuffer(&bufferItem, 0, true)) != OK) {
1017 ALOGW("Failed to acquireBuffer, error %d (%s)", err, strerror(-err));
1020 sp<GraphicBuffer> buffer = bufferItem.mGraphicBuffer;
1021 // We don't really care if this fails or not since we're just going to destroy this anyway
1022 consumer->releaseBuffer(bufferItem);
1023 if (!buffer.get()) {
1024 ALOGW("GraphicBuffer is null?");
1027 if (buffer->getWidth() != width || buffer->getHeight() != height) {
1028 ALOGW("GraphicBuffer size mismatch, got %dx%d expected %dx%d",
1029 buffer->getWidth(), buffer->getHeight(), width, height);
1030 // Continue I guess?
1032 sk_sp<Bitmap> bitmap = Bitmap::createFrom(buffer);
1033 if (!bitmap.get()) {
1034 ALOGW("Failed to create hardware bitmap from graphic buffer");
1037 return bitmap::createBitmap(env, bitmap.release(),
1038 android::bitmap::kBitmapCreateFlag_Premultiplied);
1041 static void android_view_ThreadedRenderer_disableVsync(JNIEnv*, jclass) {
1042 RenderProxy::disableVsync();
1045 static void android_view_ThreadedRenderer_setHighContrastText(JNIEnv*, jclass, jboolean enable) {
1046 Properties::enableHighContrastText = enable;
1049 static void android_view_ThreadedRenderer_hackySetRTAnimationsEnabled(JNIEnv*, jclass,
1051 Properties::enableRTAnimations = enable;
1054 static void android_view_ThreadedRenderer_setDebuggingEnabled(JNIEnv*, jclass, jboolean enable) {
1055 Properties::debuggingEnabled = enable;
1058 static void android_view_ThreadedRenderer_setIsolatedProcess(JNIEnv*, jclass, jboolean isolated) {
1059 Properties::isolatedProcess = isolated;
1062 static void android_view_ThreadedRenderer_setContextPriority(JNIEnv*, jclass,
1063 jint contextPriority) {
1064 Properties::contextPriority = contextPriority;
1067 // ----------------------------------------------------------------------------
1068 // FrameMetricsObserver
1069 // ----------------------------------------------------------------------------
1071 static jlong android_view_ThreadedRenderer_addFrameMetricsObserver(JNIEnv* env,
1072 jclass clazz, jlong proxyPtr, jobject fso) {
1073 JavaVM* vm = nullptr;
1074 if (env->GetJavaVM(&vm) != JNI_OK) {
1075 LOG_ALWAYS_FATAL("Unable to get Java VM");
1079 renderthread::RenderProxy* renderProxy =
1080 reinterpret_cast<renderthread::RenderProxy*>(proxyPtr);
1082 FrameMetricsObserver* observer = new ObserverProxy(vm, fso);
1083 renderProxy->addFrameMetricsObserver(observer);
1084 return reinterpret_cast<jlong>(observer);
1087 static void android_view_ThreadedRenderer_removeFrameMetricsObserver(JNIEnv* env, jclass clazz,
1088 jlong proxyPtr, jlong observerPtr) {
1089 FrameMetricsObserver* observer = reinterpret_cast<FrameMetricsObserver*>(observerPtr);
1090 renderthread::RenderProxy* renderProxy =
1091 reinterpret_cast<renderthread::RenderProxy*>(proxyPtr);
1093 renderProxy->removeFrameMetricsObserver(observer);
1096 // ----------------------------------------------------------------------------
1098 // ----------------------------------------------------------------------------
1100 static void android_view_ThreadedRenderer_setupShadersDiskCache(JNIEnv* env, jobject clazz,
1101 jstring diskCachePath, jstring skiaDiskCachePath) {
1102 const char* cacheArray = env->GetStringUTFChars(diskCachePath, NULL);
1103 android::egl_set_cache_filename(cacheArray);
1104 env->ReleaseStringUTFChars(diskCachePath, cacheArray);
1106 const char* skiaCacheArray = env->GetStringUTFChars(skiaDiskCachePath, NULL);
1107 uirenderer::skiapipeline::ShaderCache::get().setFilename(skiaCacheArray);
1108 env->ReleaseStringUTFChars(skiaDiskCachePath, skiaCacheArray);
1111 // ----------------------------------------------------------------------------
1113 // ----------------------------------------------------------------------------
1115 const char* const kClassPathName = "android/view/ThreadedRenderer";
1117 static const JNINativeMethod gMethods[] = {
1118 { "nRotateProcessStatsBuffer", "()V", (void*) android_view_ThreadedRenderer_rotateProcessStatsBuffer },
1119 { "nSetProcessStatsBuffer", "(I)V", (void*) android_view_ThreadedRenderer_setProcessStatsBuffer },
1120 { "nGetRenderThreadTid", "(J)I", (void*) android_view_ThreadedRenderer_getRenderThreadTid },
1121 { "nCreateRootRenderNode", "()J", (void*) android_view_ThreadedRenderer_createRootRenderNode },
1122 { "nCreateProxy", "(ZJ)J", (void*) android_view_ThreadedRenderer_createProxy },
1123 { "nDeleteProxy", "(J)V", (void*) android_view_ThreadedRenderer_deleteProxy },
1124 { "nLoadSystemProperties", "(J)Z", (void*) android_view_ThreadedRenderer_loadSystemProperties },
1125 { "nSetName", "(JLjava/lang/String;)V", (void*) android_view_ThreadedRenderer_setName },
1126 { "nInitialize", "(JLandroid/view/Surface;)V", (void*) android_view_ThreadedRenderer_initialize },
1127 { "nUpdateSurface", "(JLandroid/view/Surface;)V", (void*) android_view_ThreadedRenderer_updateSurface },
1128 { "nPauseSurface", "(JLandroid/view/Surface;)Z", (void*) android_view_ThreadedRenderer_pauseSurface },
1129 { "nSetStopped", "(JZ)V", (void*) android_view_ThreadedRenderer_setStopped },
1130 { "nSetup", "(JFII)V", (void*) android_view_ThreadedRenderer_setup },
1131 { "nSetLightCenter", "(JFFF)V", (void*) android_view_ThreadedRenderer_setLightCenter },
1132 { "nSetOpaque", "(JZ)V", (void*) android_view_ThreadedRenderer_setOpaque },
1133 { "nSetWideGamut", "(JZ)V", (void*) android_view_ThreadedRenderer_setWideGamut },
1134 { "nSyncAndDrawFrame", "(J[JI)I", (void*) android_view_ThreadedRenderer_syncAndDrawFrame },
1135 { "nDestroy", "(JJ)V", (void*) android_view_ThreadedRenderer_destroy },
1136 { "nRegisterAnimatingRenderNode", "(JJ)V", (void*) android_view_ThreadedRenderer_registerAnimatingRenderNode },
1137 { "nRegisterVectorDrawableAnimator", "(JJ)V", (void*) android_view_ThreadedRenderer_registerVectorDrawableAnimator },
1138 { "nInvokeFunctor", "(JZ)V", (void*) android_view_ThreadedRenderer_invokeFunctor },
1139 { "nCreateTextureLayer", "(J)J", (void*) android_view_ThreadedRenderer_createTextureLayer },
1140 { "nBuildLayer", "(JJ)V", (void*) android_view_ThreadedRenderer_buildLayer },
1141 { "nCopyLayerInto", "(JJLandroid/graphics/Bitmap;)Z", (void*) android_view_ThreadedRenderer_copyLayerInto },
1142 { "nPushLayerUpdate", "(JJ)V", (void*) android_view_ThreadedRenderer_pushLayerUpdate },
1143 { "nCancelLayerUpdate", "(JJ)V", (void*) android_view_ThreadedRenderer_cancelLayerUpdate },
1144 { "nDetachSurfaceTexture", "(JJ)V", (void*) android_view_ThreadedRenderer_detachSurfaceTexture },
1145 { "nDestroyHardwareResources", "(J)V", (void*) android_view_ThreadedRenderer_destroyHardwareResources },
1146 { "nTrimMemory", "(I)V", (void*) android_view_ThreadedRenderer_trimMemory },
1147 { "nOverrideProperty", "(Ljava/lang/String;Ljava/lang/String;)V", (void*) android_view_ThreadedRenderer_overrideProperty },
1148 { "nFence", "(J)V", (void*) android_view_ThreadedRenderer_fence },
1149 { "nStopDrawing", "(J)V", (void*) android_view_ThreadedRenderer_stopDrawing },
1150 { "nNotifyFramePending", "(J)V", (void*) android_view_ThreadedRenderer_notifyFramePending },
1151 { "nSerializeDisplayListTree", "(J)V", (void*) android_view_ThreadedRenderer_serializeDisplayListTree },
1152 { "nDumpProfileInfo", "(JLjava/io/FileDescriptor;I)V", (void*) android_view_ThreadedRenderer_dumpProfileInfo },
1153 { "setupShadersDiskCache", "(Ljava/lang/String;Ljava/lang/String;)V",
1154 (void*) android_view_ThreadedRenderer_setupShadersDiskCache },
1155 { "nAddRenderNode", "(JJZ)V", (void*) android_view_ThreadedRenderer_addRenderNode},
1156 { "nRemoveRenderNode", "(JJ)V", (void*) android_view_ThreadedRenderer_removeRenderNode},
1157 { "nDrawRenderNode", "(JJ)V", (void*) android_view_ThreadedRendererd_drawRenderNode},
1158 { "nSetContentDrawBounds", "(JIIII)V", (void*)android_view_ThreadedRenderer_setContentDrawBounds},
1159 { "nSetFrameCallback", "(JLandroid/view/ThreadedRenderer$FrameDrawingCallback;)V",
1160 (void*)android_view_ThreadedRenderer_setFrameCallback},
1161 { "nSetFrameCompleteCallback", "(JLandroid/view/ThreadedRenderer$FrameCompleteCallback;)V",
1162 (void*)android_view_ThreadedRenderer_setFrameCompleteCallback },
1163 { "nAddFrameMetricsObserver",
1164 "(JLandroid/view/FrameMetricsObserver;)J",
1165 (void*)android_view_ThreadedRenderer_addFrameMetricsObserver },
1166 { "nRemoveFrameMetricsObserver",
1168 (void*)android_view_ThreadedRenderer_removeFrameMetricsObserver },
1169 { "nCopySurfaceInto", "(Landroid/view/Surface;IIIILandroid/graphics/Bitmap;)I",
1170 (void*)android_view_ThreadedRenderer_copySurfaceInto },
1171 { "nCreateHardwareBitmap", "(JII)Landroid/graphics/Bitmap;",
1172 (void*)android_view_ThreadedRenderer_createHardwareBitmapFromRenderNode },
1173 { "disableVsync", "()V", (void*)android_view_ThreadedRenderer_disableVsync },
1174 { "nSetHighContrastText", "(Z)V", (void*)android_view_ThreadedRenderer_setHighContrastText },
1175 { "nHackySetRTAnimationsEnabled", "(Z)V",
1176 (void*)android_view_ThreadedRenderer_hackySetRTAnimationsEnabled },
1177 { "nSetDebuggingEnabled", "(Z)V", (void*)android_view_ThreadedRenderer_setDebuggingEnabled },
1178 { "nSetIsolatedProcess", "(Z)V", (void*)android_view_ThreadedRenderer_setIsolatedProcess },
1179 { "nSetContextPriority", "(I)V", (void*)android_view_ThreadedRenderer_setContextPriority },
1182 static JavaVM* mJvm = nullptr;
1184 static void attachRenderThreadToJvm() {
1185 LOG_ALWAYS_FATAL_IF(!mJvm, "No jvm but we set the hook??");
1187 JavaVMAttachArgs args;
1188 args.version = JNI_VERSION_1_4;
1189 args.name = (char*) "RenderThread";
1192 mJvm->AttachCurrentThreadAsDaemon(&env, (void*) &args);
1195 int register_android_view_ThreadedRenderer(JNIEnv* env) {
1196 env->GetJavaVM(&mJvm);
1197 RenderThread::setOnStartHook(&attachRenderThreadToJvm);
1198 jclass observerClass = FindClassOrDie(env, "android/view/FrameMetricsObserver");
1199 gFrameMetricsObserverClassInfo.frameMetrics = GetFieldIDOrDie(
1200 env, observerClass, "mFrameMetrics", "Landroid/view/FrameMetrics;");
1201 gFrameMetricsObserverClassInfo.messageQueue = GetFieldIDOrDie(
1202 env, observerClass, "mMessageQueue", "Landroid/os/MessageQueue;");
1203 gFrameMetricsObserverClassInfo.callback = GetMethodIDOrDie(
1204 env, observerClass, "notifyDataAvailable", "(I)V");
1206 jclass metricsClass = FindClassOrDie(env, "android/view/FrameMetrics");
1207 gFrameMetricsObserverClassInfo.timingDataBuffer = GetFieldIDOrDie(
1208 env, metricsClass, "mTimingData", "[J");
1210 jclass frameCallbackClass = FindClassOrDie(env,
1211 "android/view/ThreadedRenderer$FrameDrawingCallback");
1212 gFrameDrawingCallback.onFrameDraw = GetMethodIDOrDie(env, frameCallbackClass,
1213 "onFrameDraw", "(J)V");
1215 jclass frameCompleteClass = FindClassOrDie(env,
1216 "android/view/ThreadedRenderer$FrameCompleteCallback");
1217 gFrameCompleteCallback.onFrameComplete = GetMethodIDOrDie(env, frameCompleteClass,
1218 "onFrameComplete", "(J)V");
1220 return RegisterMethodsOrDie(env, kClassPathName, gMethods, NELEM(gMethods));
1223 }; // namespace android