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