1 /*
2  * Copyright (C) 2013 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 #include "RenderThread.h"
18 
19 #include <GrContextOptions.h>
20 #include <android-base/properties.h>
21 #include <dlfcn.h>
22 #include <gl/GrGLInterface.h>
23 #include <gui/TraceUtils.h>
24 #include <include/gpu/ganesh/gl/GrGLDirectContext.h>
25 #include <private/android/choreographer.h>
26 #include <sys/resource.h>
27 #include <ui/FatVector.h>
28 #include <utils/Condition.h>
29 #include <utils/Log.h>
30 #include <utils/Mutex.h>
31 
32 #include <thread>
33 
34 #include "../HardwareBitmapUploader.h"
35 #include "CacheManager.h"
36 #include "CanvasContext.h"
37 #include "DeviceInfo.h"
38 #include "EglManager.h"
39 #include "Properties.h"
40 #include "Readback.h"
41 #include "RenderProxy.h"
42 #include "VulkanManager.h"
43 #include "hwui/Bitmap.h"
44 #include "pipeline/skia/SkiaOpenGLPipeline.h"
45 #include "pipeline/skia/SkiaVulkanPipeline.h"
46 #include "renderstate/RenderState.h"
47 #include "utils/TimeUtils.h"
48 
49 namespace android {
50 namespace uirenderer {
51 namespace renderthread {
52 
53 static bool gHasRenderThreadInstance = false;
54 
55 static JVMAttachHook gOnStartHook = nullptr;
56 
ASurfaceControlFunctions()57 ASurfaceControlFunctions::ASurfaceControlFunctions() {
58     void* handle_ = dlopen("libandroid.so", RTLD_NOW | RTLD_NODELETE);
59     createFunc = (ASC_create)dlsym(handle_, "ASurfaceControl_create");
60     LOG_ALWAYS_FATAL_IF(createFunc == nullptr,
61                         "Failed to find required symbol ASurfaceControl_create!");
62 
63     acquireFunc = (ASC_acquire) dlsym(handle_, "ASurfaceControl_acquire");
64     LOG_ALWAYS_FATAL_IF(acquireFunc == nullptr,
65             "Failed to find required symbol ASurfaceControl_acquire!");
66 
67     releaseFunc = (ASC_release) dlsym(handle_, "ASurfaceControl_release");
68     LOG_ALWAYS_FATAL_IF(releaseFunc == nullptr,
69             "Failed to find required symbol ASurfaceControl_release!");
70 
71     registerListenerFunc = (ASC_registerSurfaceStatsListener) dlsym(handle_,
72             "ASurfaceControl_registerSurfaceStatsListener");
73     LOG_ALWAYS_FATAL_IF(registerListenerFunc == nullptr,
74             "Failed to find required symbol ASurfaceControl_registerSurfaceStatsListener!");
75 
76     unregisterListenerFunc = (ASC_unregisterSurfaceStatsListener) dlsym(handle_,
77             "ASurfaceControl_unregisterSurfaceStatsListener");
78     LOG_ALWAYS_FATAL_IF(unregisterListenerFunc == nullptr,
79             "Failed to find required symbol ASurfaceControl_unregisterSurfaceStatsListener!");
80 
81     getAcquireTimeFunc = (ASCStats_getAcquireTime) dlsym(handle_,
82             "ASurfaceControlStats_getAcquireTime");
83     LOG_ALWAYS_FATAL_IF(getAcquireTimeFunc == nullptr,
84             "Failed to find required symbol ASurfaceControlStats_getAcquireTime!");
85 
86     getFrameNumberFunc = (ASCStats_getFrameNumber) dlsym(handle_,
87             "ASurfaceControlStats_getFrameNumber");
88     LOG_ALWAYS_FATAL_IF(getFrameNumberFunc == nullptr,
89             "Failed to find required symbol ASurfaceControlStats_getFrameNumber!");
90 
91     transactionCreateFunc = (AST_create)dlsym(handle_, "ASurfaceTransaction_create");
92     LOG_ALWAYS_FATAL_IF(transactionCreateFunc == nullptr,
93                         "Failed to find required symbol ASurfaceTransaction_create!");
94 
95     transactionDeleteFunc = (AST_delete)dlsym(handle_, "ASurfaceTransaction_delete");
96     LOG_ALWAYS_FATAL_IF(transactionDeleteFunc == nullptr,
97                         "Failed to find required symbol ASurfaceTransaction_delete!");
98 
99     transactionApplyFunc = (AST_apply)dlsym(handle_, "ASurfaceTransaction_apply");
100     LOG_ALWAYS_FATAL_IF(transactionApplyFunc == nullptr,
101                         "Failed to find required symbol ASurfaceTransaction_apply!");
102 
103     transactionReparentFunc = (AST_reparent)dlsym(handle_, "ASurfaceTransaction_reparent");
104     LOG_ALWAYS_FATAL_IF(transactionReparentFunc == nullptr,
105                         "Failed to find required symbol transactionReparentFunc!");
106 
107     transactionSetVisibilityFunc =
108             (AST_setVisibility)dlsym(handle_, "ASurfaceTransaction_setVisibility");
109     LOG_ALWAYS_FATAL_IF(transactionSetVisibilityFunc == nullptr,
110                         "Failed to find required symbol ASurfaceTransaction_setVisibility!");
111 
112     transactionSetZOrderFunc = (AST_setZOrder)dlsym(handle_, "ASurfaceTransaction_setZOrder");
113     LOG_ALWAYS_FATAL_IF(transactionSetZOrderFunc == nullptr,
114                         "Failed to find required symbol ASurfaceTransaction_setZOrder!");
115 }
116 
extendedFrameCallback(const AChoreographerFrameCallbackData * cbData,void * data)117 void RenderThread::extendedFrameCallback(const AChoreographerFrameCallbackData* cbData,
118                                          void* data) {
119     RenderThread* rt = reinterpret_cast<RenderThread*>(data);
120     size_t preferredFrameTimelineIndex =
121             AChoreographerFrameCallbackData_getPreferredFrameTimelineIndex(cbData);
122     AVsyncId vsyncId = AChoreographerFrameCallbackData_getFrameTimelineVsyncId(
123             cbData, preferredFrameTimelineIndex);
124     int64_t frameDeadline = AChoreographerFrameCallbackData_getFrameTimelineDeadlineNanos(
125             cbData, preferredFrameTimelineIndex);
126     int64_t frameTimeNanos = AChoreographerFrameCallbackData_getFrameTimeNanos(cbData);
127     // TODO(b/193273294): Remove when shared memory in use w/ expected present time always current.
128     int64_t frameInterval = AChoreographer_getFrameInterval(rt->mChoreographer);
129     rt->frameCallback(vsyncId, frameDeadline, frameTimeNanos, frameInterval);
130 }
131 
frameCallback(int64_t vsyncId,int64_t frameDeadline,int64_t frameTimeNanos,int64_t frameInterval)132 void RenderThread::frameCallback(int64_t vsyncId, int64_t frameDeadline, int64_t frameTimeNanos,
133                                  int64_t frameInterval) {
134     mVsyncRequested = false;
135     if (timeLord().vsyncReceived(frameTimeNanos, frameTimeNanos, vsyncId, frameDeadline,
136                                  frameInterval) &&
137         !mFrameCallbackTaskPending) {
138         mFrameCallbackTaskPending = true;
139 
140         using SteadyClock = std::chrono::steady_clock;
141         using Nanos = std::chrono::nanoseconds;
142         using toNsecs_t = std::chrono::duration<nsecs_t, std::nano>;
143         using toFloatMillis = std::chrono::duration<float, std::milli>;
144 
145         const auto frameTimeTimePoint = SteadyClock::time_point(Nanos(frameTimeNanos));
146         const auto deadlineTimePoint = SteadyClock::time_point(Nanos(frameDeadline));
147 
148         const auto timeUntilDeadline = deadlineTimePoint - frameTimeTimePoint;
149         const auto runAt = (frameTimeTimePoint + (timeUntilDeadline / 4));
150 
151         ATRACE_FORMAT("queue mFrameCallbackTask to run after %.2fms",
152                       toFloatMillis(runAt - SteadyClock::now()).count());
153         queue().postAt(toNsecs_t(runAt.time_since_epoch()).count(),
154                        [this]() { dispatchFrameCallbacks(); });
155     }
156 }
157 
refreshRateCallback(int64_t vsyncPeriod,void * data)158 void RenderThread::refreshRateCallback(int64_t vsyncPeriod, void* data) {
159     ATRACE_NAME("refreshRateCallback");
160     RenderThread* rt = reinterpret_cast<RenderThread*>(data);
161     DeviceInfo::get()->onRefreshRateChanged(vsyncPeriod);
162     rt->setupFrameInterval();
163 }
164 
165 class ChoreographerSource : public VsyncSource {
166 public:
ChoreographerSource(RenderThread * renderThread)167     ChoreographerSource(RenderThread* renderThread) : mRenderThread(renderThread) {}
168 
requestNextVsync()169     virtual void requestNextVsync() override {
170         AChoreographer_postVsyncCallback(mRenderThread->mChoreographer,
171                                          RenderThread::extendedFrameCallback, mRenderThread);
172     }
173 
drainPendingEvents()174     virtual void drainPendingEvents() override {
175         AChoreographer_handlePendingEvents(mRenderThread->mChoreographer, mRenderThread);
176     }
177 
178 private:
179     RenderThread* mRenderThread;
180 };
181 
182 class DummyVsyncSource : public VsyncSource {
183 public:
DummyVsyncSource(RenderThread * renderThread)184     DummyVsyncSource(RenderThread* renderThread) : mRenderThread(renderThread) {}
185 
requestNextVsync()186     virtual void requestNextVsync() override {
187         mRenderThread->queue().postDelayed(16_ms, [this]() {
188             mRenderThread->frameCallback(UiFrameInfoBuilder::INVALID_VSYNC_ID,
189                                          std::numeric_limits<int64_t>::max(),
190                                          systemTime(SYSTEM_TIME_MONOTONIC), 16_ms);
191         });
192     }
193 
drainPendingEvents()194     virtual void drainPendingEvents() override {
195         mRenderThread->frameCallback(UiFrameInfoBuilder::INVALID_VSYNC_ID,
196                                      std::numeric_limits<int64_t>::max(),
197                                      systemTime(SYSTEM_TIME_MONOTONIC), 16_ms);
198     }
199 
200 private:
201     RenderThread* mRenderThread;
202 };
203 
hasInstance()204 bool RenderThread::hasInstance() {
205     return gHasRenderThreadInstance;
206 }
207 
setOnStartHook(JVMAttachHook onStartHook)208 void RenderThread::setOnStartHook(JVMAttachHook onStartHook) {
209     LOG_ALWAYS_FATAL_IF(hasInstance(), "can't set an onStartHook after we've started...");
210     gOnStartHook = onStartHook;
211 }
212 
getOnStartHook()213 JVMAttachHook RenderThread::getOnStartHook() {
214     return gOnStartHook;
215 }
216 
getInstance()217 RenderThread& RenderThread::getInstance() {
218     [[clang::no_destroy]] static sp<RenderThread> sInstance = []() {
219         sp<RenderThread> thread = sp<RenderThread>::make();
220         thread->start("RenderThread");
221         return thread;
222     }();
223     gHasRenderThreadInstance = true;
224     return *sInstance;
225 }
226 
RenderThread()227 RenderThread::RenderThread()
228         : ThreadBase()
229         , mVsyncSource(nullptr)
230         , mVsyncRequested(false)
231         , mFrameCallbackTaskPending(false)
232         , mRenderState(nullptr)
233         , mEglManager(nullptr)
234         , mFunctorManager(WebViewFunctorManager::instance())
235         , mGlobalProfileData(mJankDataMutex) {
236     Properties::load();
237 }
238 
~RenderThread()239 RenderThread::~RenderThread() {
240     // Note that if this fatal assertion is removed then member variables must
241     // be properly destroyed.
242     LOG_ALWAYS_FATAL("Can't destroy the render thread");
243 }
244 
initializeChoreographer()245 void RenderThread::initializeChoreographer() {
246     LOG_ALWAYS_FATAL_IF(mVsyncSource, "Initializing a second Choreographer?");
247 
248     if (!Properties::isolatedProcess) {
249         mChoreographer = AChoreographer_create();
250         LOG_ALWAYS_FATAL_IF(mChoreographer == nullptr, "Initialization of Choreographer failed");
251         AChoreographer_registerRefreshRateCallback(mChoreographer,
252                                                    RenderThread::refreshRateCallback, this);
253 
254         // Register the FD
255         mLooper->addFd(AChoreographer_getFd(mChoreographer), 0, Looper::EVENT_INPUT,
256                        RenderThread::choreographerCallback, this);
257         mVsyncSource = new ChoreographerSource(this);
258     } else {
259         mVsyncSource = new DummyVsyncSource(this);
260     }
261 }
262 
initThreadLocals()263 void RenderThread::initThreadLocals() {
264     setupFrameInterval();
265     initializeChoreographer();
266     mEglManager = new EglManager();
267     mRenderState = new RenderState(*this);
268     mVkManager = VulkanManager::getInstance();
269     mCacheManager = new CacheManager(*this);
270 }
271 
setupFrameInterval()272 void RenderThread::setupFrameInterval() {
273     nsecs_t frameIntervalNanos = DeviceInfo::getVsyncPeriod();
274     mTimeLord.setFrameInterval(frameIntervalNanos);
275 }
276 
requireGlContext()277 void RenderThread::requireGlContext() {
278     if (mEglManager->hasEglContext()) {
279         return;
280     }
281     mEglManager->initialize();
282 
283     sk_sp<const GrGLInterface> glInterface = GrGLMakeNativeInterface();
284     LOG_ALWAYS_FATAL_IF(!glInterface.get());
285 
286     GrContextOptions options;
287     initGrContextOptions(options);
288     auto glesVersion = reinterpret_cast<const char*>(glGetString(GL_VERSION));
289     auto size = glesVersion ? strlen(glesVersion) : -1;
290     cacheManager().configureContext(&options, glesVersion, size);
291     sk_sp<GrDirectContext> grContext(GrDirectContexts::MakeGL(std::move(glInterface), options));
292     LOG_ALWAYS_FATAL_IF(!grContext.get());
293     setGrContext(grContext);
294 }
295 
requireVkContext()296 void RenderThread::requireVkContext() {
297     // the getter creates the context in the event it had been destroyed by destroyRenderingContext
298     // Also check if we have a GrContext before returning fast. VulkanManager may be shared with
299     // the HardwareBitmapUploader which initializes the Vk context without persisting the GrContext
300     // in the rendering thread.
301     if (vulkanManager().hasVkContext() && mGrContext) {
302         return;
303     }
304     mVkManager->initialize();
305     GrContextOptions options;
306     initGrContextOptions(options);
307     auto vkDriverVersion = mVkManager->getDriverVersion();
308     cacheManager().configureContext(&options, &vkDriverVersion, sizeof(vkDriverVersion));
309     sk_sp<GrDirectContext> grContext = mVkManager->createContext(options);
310     LOG_ALWAYS_FATAL_IF(!grContext.get());
311     setGrContext(grContext);
312 }
313 
initGrContextOptions(GrContextOptions & options)314 void RenderThread::initGrContextOptions(GrContextOptions& options) {
315     options.fPreferExternalImagesOverES3 = true;
316     options.fDisableDistanceFieldPaths = true;
317     if (android::base::GetBoolProperty(PROPERTY_REDUCE_OPS_TASK_SPLITTING, true)) {
318         options.fReduceOpsTaskSplitting = GrContextOptions::Enable::kYes;
319     } else {
320         options.fReduceOpsTaskSplitting = GrContextOptions::Enable::kNo;
321     }
322 }
323 
destroyRenderingContext()324 void RenderThread::destroyRenderingContext() {
325     mFunctorManager.onContextDestroyed();
326     if (Properties::getRenderPipelineType() == RenderPipelineType::SkiaGL) {
327         if (mEglManager->hasEglContext()) {
328             setGrContext(nullptr);
329             mEglManager->destroy();
330         }
331     } else {
332         setGrContext(nullptr);
333         mVkManager.clear();
334     }
335 }
336 
vulkanManager()337 VulkanManager& RenderThread::vulkanManager() {
338     if (!mVkManager.get()) {
339         mVkManager = VulkanManager::getInstance();
340     }
341     return *mVkManager.get();
342 }
343 
pipelineToString()344 static const char* pipelineToString() {
345     switch (auto renderType = Properties::getRenderPipelineType()) {
346         case RenderPipelineType::SkiaGL:
347             return "Skia (OpenGL)";
348         case RenderPipelineType::SkiaVulkan:
349             return "Skia (Vulkan)";
350         default:
351             LOG_ALWAYS_FATAL("canvas context type %d not supported", (int32_t)renderType);
352     }
353 }
354 
dumpGraphicsMemory(int fd,bool includeProfileData)355 void RenderThread::dumpGraphicsMemory(int fd, bool includeProfileData) {
356     if (includeProfileData) {
357         globalProfileData()->dump(fd);
358     }
359 
360     String8 cachesOutput;
361     mCacheManager->dumpMemoryUsage(cachesOutput, mRenderState);
362     dprintf(fd, "\nPipeline=%s\n%s", pipelineToString(), cachesOutput.c_str());
363     for (auto&& context : mCacheManager->mCanvasContexts) {
364         context->visitAllRenderNodes([&](const RenderNode& node) {
365             if (node.isTextureView()) {
366                 dprintf(fd, "TextureView: %dx%d\n", node.getWidth(), node.getHeight());
367             }
368         });
369     }
370     dprintf(fd, "\n");
371 }
372 
getMemoryUsage(size_t * cpuUsage,size_t * gpuUsage)373 void RenderThread::getMemoryUsage(size_t* cpuUsage, size_t* gpuUsage) {
374     mCacheManager->getMemoryUsage(cpuUsage, gpuUsage);
375 }
376 
readback()377 Readback& RenderThread::readback() {
378     if (!mReadback) {
379         mReadback = new Readback(*this);
380     }
381 
382     return *mReadback;
383 }
384 
setGrContext(sk_sp<GrDirectContext> context)385 void RenderThread::setGrContext(sk_sp<GrDirectContext> context) {
386     mCacheManager->reset(context);
387     if (mGrContext) {
388         mRenderState->onContextDestroyed();
389         mGrContext->releaseResourcesAndAbandonContext();
390     }
391     mGrContext = std::move(context);
392     if (mGrContext) {
393         DeviceInfo::setMaxTextureSize(mGrContext->maxRenderTargetSize());
394     }
395 }
396 
requireGrContext()397 sk_sp<GrDirectContext> RenderThread::requireGrContext() {
398     if (Properties::getRenderPipelineType() == RenderPipelineType::SkiaGL) {
399         requireGlContext();
400     } else {
401         requireVkContext();
402     }
403     return mGrContext;
404 }
405 
choreographerCallback(int fd,int events,void * data)406 int RenderThread::choreographerCallback(int fd, int events, void* data) {
407     if (events & (Looper::EVENT_ERROR | Looper::EVENT_HANGUP)) {
408         ALOGE("Display event receiver pipe was closed or an error occurred.  "
409               "events=0x%x",
410               events);
411         return 0;  // remove the callback
412     }
413 
414     if (!(events & Looper::EVENT_INPUT)) {
415         ALOGW("Received spurious callback for unhandled poll event.  "
416               "events=0x%x",
417               events);
418         return 1;  // keep the callback
419     }
420     RenderThread* rt = reinterpret_cast<RenderThread*>(data);
421     AChoreographer_handlePendingEvents(rt->mChoreographer, data);
422 
423     return 1;
424 }
425 
dispatchFrameCallbacks()426 void RenderThread::dispatchFrameCallbacks() {
427     ATRACE_CALL();
428     mFrameCallbackTaskPending = false;
429 
430     std::set<IFrameCallback*> callbacks;
431     mFrameCallbacks.swap(callbacks);
432 
433     if (callbacks.size()) {
434         // Assume one of them will probably animate again so preemptively
435         // request the next vsync in case it occurs mid-frame
436         requestVsync();
437         for (std::set<IFrameCallback*>::iterator it = callbacks.begin(); it != callbacks.end();
438              it++) {
439             (*it)->doFrame();
440         }
441     }
442 }
443 
requestVsync()444 void RenderThread::requestVsync() {
445     if (!mVsyncRequested) {
446         mVsyncRequested = true;
447         mVsyncSource->requestNextVsync();
448     }
449 }
450 
threadLoop()451 bool RenderThread::threadLoop() {
452     setpriority(PRIO_PROCESS, 0, PRIORITY_DISPLAY);
453     Looper::setForThread(mLooper);
454     if (gOnStartHook) {
455         gOnStartHook("RenderThread");
456     }
457     initThreadLocals();
458 
459     while (true) {
460         waitForWork();
461         processQueue();
462 
463         if (mPendingRegistrationFrameCallbacks.size() && !mFrameCallbackTaskPending) {
464             mVsyncSource->drainPendingEvents();
465             mFrameCallbacks.insert(mPendingRegistrationFrameCallbacks.begin(),
466                                    mPendingRegistrationFrameCallbacks.end());
467             mPendingRegistrationFrameCallbacks.clear();
468             requestVsync();
469         }
470 
471         if (!mFrameCallbackTaskPending && !mVsyncRequested && mFrameCallbacks.size()) {
472             // TODO: Clean this up. This is working around an issue where a combination
473             // of bad timing and slow drawing can result in dropping a stale vsync
474             // on the floor (correct!) but fails to schedule to listen for the
475             // next vsync (oops), so none of the callbacks are run.
476             requestVsync();
477         }
478 
479         mCacheManager->onThreadIdle();
480     }
481 
482     return false;
483 }
484 
postFrameCallback(IFrameCallback * callback)485 void RenderThread::postFrameCallback(IFrameCallback* callback) {
486     mPendingRegistrationFrameCallbacks.insert(callback);
487 }
488 
removeFrameCallback(IFrameCallback * callback)489 bool RenderThread::removeFrameCallback(IFrameCallback* callback) {
490     size_t erased;
491     erased = mFrameCallbacks.erase(callback);
492     erased |= mPendingRegistrationFrameCallbacks.erase(callback);
493     return erased;
494 }
495 
pushBackFrameCallback(IFrameCallback * callback)496 void RenderThread::pushBackFrameCallback(IFrameCallback* callback) {
497     if (mFrameCallbacks.erase(callback)) {
498         mPendingRegistrationFrameCallbacks.insert(callback);
499     }
500 }
501 
allocateHardwareBitmap(SkBitmap & skBitmap)502 sk_sp<Bitmap> RenderThread::allocateHardwareBitmap(SkBitmap& skBitmap) {
503     auto renderType = Properties::getRenderPipelineType();
504     switch (renderType) {
505         case RenderPipelineType::SkiaVulkan:
506             return skiapipeline::SkiaVulkanPipeline::allocateHardwareBitmap(*this, skBitmap);
507         default:
508             LOG_ALWAYS_FATAL("canvas context type %d not supported", (int32_t)renderType);
509             break;
510     }
511     return nullptr;
512 }
513 
isCurrent()514 bool RenderThread::isCurrent() {
515     return gettid() == getInstance().getTid();
516 }
517 
preload()518 void RenderThread::preload() {
519     // EGL driver is always preloaded only if HWUI renders with GL.
520     if (Properties::getRenderPipelineType() == RenderPipelineType::SkiaGL) {
521         std::thread eglInitThread([]() { eglGetDisplay(EGL_DEFAULT_DISPLAY); });
522         eglInitThread.detach();
523     } else {
524         requireVkContext();
525     }
526     HardwareBitmapUploader::initialize();
527 }
528 
trimMemory(TrimLevel level)529 void RenderThread::trimMemory(TrimLevel level) {
530     ATRACE_CALL();
531     cacheManager().trimMemory(level);
532 }
533 
trimCaches(CacheTrimLevel level)534 void RenderThread::trimCaches(CacheTrimLevel level) {
535     ATRACE_CALL();
536     cacheManager().trimCaches(level);
537 }
538 
539 } /* namespace renderthread */
540 } /* namespace uirenderer */
541 } /* namespace android */
542