blob: 8e0546b529af648a8a3032ff4f88ff74c5c6699a [file] [log] [blame]
John Reckcec24ae2013-11-05 13:27:50 -08001/*
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
John Reckcec24ae2013-11-05 13:27:50 -080017#include "RenderThread.h"
18
John Reck4f02bf42014-01-03 18:09:17 -080019#include "CanvasContext.h"
John Reck3b202512014-06-23 13:13:08 -070020#include "EglManager.h"
Derek Sollenbergerc4fbada2016-11-07 16:05:41 -050021#include "OpenGLReadback.h"
John Reck4f02bf42014-01-03 18:09:17 -080022#include "RenderProxy.h"
Derek Sollenberger0e3cba32016-11-09 11:58:36 -050023#include "VulkanManager.h"
John Reck1bcacfd2017-11-03 10:12:19 -070024#include "hwui/Bitmap.h"
25#include "pipeline/skia/SkiaOpenGLPipeline.h"
26#include "pipeline/skia/SkiaOpenGLReadback.h"
Stan Ilieva31973fe2018-01-12 11:50:29 -050027#include "pipeline/skia/SkiaVulkanReadback.h"
John Reck1bcacfd2017-11-03 10:12:19 -070028#include "pipeline/skia/SkiaVulkanPipeline.h"
29#include "renderstate/RenderState.h"
30#include "renderthread/OpenGLPipeline.h"
John Reck12efa552016-11-15 10:22:01 -080031#include "utils/FatVector.h"
John Reckcec24ae2013-11-05 13:27:50 -080032
Chris Craik65fe5ee2015-01-26 18:06:29 -080033#include <gui/DisplayEventReceiver.h>
John Reckb36016c2015-03-11 08:50:53 -070034#include <gui/ISurfaceComposer.h>
35#include <gui/SurfaceComposerClient.h>
Chris Craik65fe5ee2015-01-26 18:06:29 -080036#include <sys/resource.h>
John Reckcba287b2015-11-10 12:52:44 -080037#include <utils/Condition.h>
Chris Craik65fe5ee2015-01-26 18:06:29 -080038#include <utils/Log.h>
John Reckcba287b2015-11-10 12:52:44 -080039#include <utils/Mutex.h>
Chris Craik65fe5ee2015-01-26 18:06:29 -080040
John Reckcec24ae2013-11-05 13:27:50 -080041namespace android {
John Reckcec24ae2013-11-05 13:27:50 -080042namespace uirenderer {
43namespace renderthread {
44
John Recke45b1fd2014-04-15 09:50:16 -070045// Number of events to read at a time from the DisplayEventReceiver pipe.
46// The value should be large enough that we can quickly drain the pipe
47// using just a few large reads.
48static const size_t EVENT_BUFFER_SIZE = 100;
49
50// Slight delay to give the UI time to push us a new frame before we replay
John Recka733f892014-12-19 11:37:21 -080051static const nsecs_t DISPATCH_FRAME_CALLBACKS_DELAY = milliseconds_to_nanoseconds(4);
John Recke45b1fd2014-04-15 09:50:16 -070052
John Reck6b507802015-11-03 10:09:59 -080053static bool gHasRenderThreadInstance = false;
54
John Reck259b25a2017-12-01 16:18:53 -080055static void (*gOnStartHook)() = nullptr;
56
John Reck6b507802015-11-03 10:09:59 -080057bool RenderThread::hasInstance() {
58 return gHasRenderThreadInstance;
59}
60
John Reck259b25a2017-12-01 16:18:53 -080061void RenderThread::setOnStartHook(void (*onStartHook)()) {
62 LOG_ALWAYS_FATAL_IF(hasInstance(), "can't set an onStartHook after we've started...");
63 gOnStartHook = onStartHook;
64}
65
John Reck6b507802015-11-03 10:09:59 -080066RenderThread& RenderThread::getInstance() {
67 // This is a pointer because otherwise __cxa_finalize
68 // will try to delete it like a Good Citizen but that causes us to crash
69 // because we don't want to delete the RenderThread normally.
70 static RenderThread* sInstance = new RenderThread();
71 gHasRenderThreadInstance = true;
72 return *sInstance;
73}
74
John Reck1bcacfd2017-11-03 10:12:19 -070075RenderThread::RenderThread()
76 : ThreadBase()
Chris Craikd41c4d82015-01-05 15:51:13 -080077 , mDisplayEventReceiver(nullptr)
John Recke45b1fd2014-04-15 09:50:16 -070078 , mVsyncRequested(false)
79 , mFrameCallbackTaskPending(false)
Chris Craikd41c4d82015-01-05 15:51:13 -080080 , mRenderState(nullptr)
Derek Sollenberger0e3cba32016-11-09 11:58:36 -050081 , mEglManager(nullptr)
82 , mVkManager(nullptr) {
Chris Craik2507c342015-05-04 14:36:49 -070083 Properties::load();
John Reckf8441e62017-10-23 13:10:41 -070084 start("RenderThread");
John Reckcec24ae2013-11-05 13:27:50 -080085}
86
87RenderThread::~RenderThread() {
John Reck3b202512014-06-23 13:13:08 -070088 LOG_ALWAYS_FATAL("Can't destroy the render thread");
John Reckcec24ae2013-11-05 13:27:50 -080089}
90
John Recke45b1fd2014-04-15 09:50:16 -070091void RenderThread::initializeDisplayEventReceiver() {
92 LOG_ALWAYS_FATAL_IF(mDisplayEventReceiver, "Initializing a second DisplayEventReceiver?");
93 mDisplayEventReceiver = new DisplayEventReceiver();
94 status_t status = mDisplayEventReceiver->initCheck();
John Reck1bcacfd2017-11-03 10:12:19 -070095 LOG_ALWAYS_FATAL_IF(status != NO_ERROR,
96 "Initialization of DisplayEventReceiver "
97 "failed with status: %d",
98 status);
John Recke45b1fd2014-04-15 09:50:16 -070099
100 // Register the FD
John Reck1bcacfd2017-11-03 10:12:19 -0700101 mLooper->addFd(mDisplayEventReceiver->getFd(), 0, Looper::EVENT_INPUT,
102 RenderThread::displayEventReceiverCallback, this);
John Recke45b1fd2014-04-15 09:50:16 -0700103}
104
John Reck3b202512014-06-23 13:13:08 -0700105void RenderThread::initThreadLocals() {
John Reck1bcacfd2017-11-03 10:12:19 -0700106 sp<IBinder> dtoken(SurfaceComposerClient::getBuiltInDisplay(ISurfaceComposer::eDisplayIdMain));
John Reckb36016c2015-03-11 08:50:53 -0700107 status_t status = SurfaceComposerClient::getDisplayInfo(dtoken, &mDisplayInfo);
108 LOG_ALWAYS_FATAL_IF(status, "Failed to get display info\n");
109 nsecs_t frameIntervalNanos = static_cast<nsecs_t>(1000000000 / mDisplayInfo.fps);
110 mTimeLord.setFrameInterval(frameIntervalNanos);
John Reck3b202512014-06-23 13:13:08 -0700111 initializeDisplayEventReceiver();
112 mEglManager = new EglManager(*this);
John Reck0e89e2b2014-10-31 14:49:06 -0700113 mRenderState = new RenderState(*this);
Derek Sollenberger0e3cba32016-11-09 11:58:36 -0500114 mVkManager = new VulkanManager(*this);
Derek Sollenbergerf9e45d12017-06-01 13:07:39 -0400115 mCacheManager = new CacheManager(mDisplayInfo);
116}
117
118void RenderThread::dumpGraphicsMemory(int fd) {
John Reck34781b22017-07-05 16:39:36 -0700119 globalProfileData()->dump(fd);
Derek Sollenbergerf9e45d12017-06-01 13:07:39 -0400120
121 String8 cachesOutput;
122 String8 pipeline;
123 auto renderType = Properties::getRenderPipelineType();
124 switch (renderType) {
125 case RenderPipelineType::OpenGL: {
126 if (Caches::hasInstance()) {
127 cachesOutput.appendFormat("Caches:\n");
128 Caches::getInstance().dumpMemoryUsage(cachesOutput);
129 } else {
130 cachesOutput.appendFormat("No caches instance.");
131 }
132 pipeline.appendFormat("FrameBuilder");
133 break;
134 }
135 case RenderPipelineType::SkiaGL: {
136 mCacheManager->dumpMemoryUsage(cachesOutput, mRenderState);
137 pipeline.appendFormat("Skia (OpenGL)");
138 break;
139 }
140 case RenderPipelineType::SkiaVulkan: {
141 mCacheManager->dumpMemoryUsage(cachesOutput, mRenderState);
142 pipeline.appendFormat("Skia (Vulkan)");
143 break;
144 }
145 default:
John Reck1bcacfd2017-11-03 10:12:19 -0700146 LOG_ALWAYS_FATAL("canvas context type %d not supported", (int32_t)renderType);
Derek Sollenbergerf9e45d12017-06-01 13:07:39 -0400147 break;
148 }
149
John Reck47f5c3a2017-11-13 11:32:39 -0800150 dprintf(fd, "\n%s\n", cachesOutput.string());
151 dprintf(fd, "\nPipeline=%s\n", pipeline.string());
John Reck3b202512014-06-23 13:13:08 -0700152}
153
Derek Sollenbergerc4fbada2016-11-07 16:05:41 -0500154Readback& RenderThread::readback() {
Derek Sollenbergerc4fbada2016-11-07 16:05:41 -0500155 if (!mReadback) {
156 auto renderType = Properties::getRenderPipelineType();
157 switch (renderType) {
158 case RenderPipelineType::OpenGL:
159 mReadback = new OpenGLReadbackImpl(*this);
160 break;
161 case RenderPipelineType::SkiaGL:
Derek Sollenbergerc4fbada2016-11-07 16:05:41 -0500162 mReadback = new skiapipeline::SkiaOpenGLReadback(*this);
163 break;
Stan Ilieva31973fe2018-01-12 11:50:29 -0500164 case RenderPipelineType::SkiaVulkan:
165 mReadback = new skiapipeline::SkiaVulkanReadback(*this);
166 break;
Derek Sollenbergerc4fbada2016-11-07 16:05:41 -0500167 default:
John Reck1bcacfd2017-11-03 10:12:19 -0700168 LOG_ALWAYS_FATAL("canvas context type %d not supported", (int32_t)renderType);
Derek Sollenbergerc4fbada2016-11-07 16:05:41 -0500169 break;
170 }
171 }
172
173 return *mReadback;
174}
175
Greg Daniel660d6ec2017-12-08 11:44:27 -0500176void RenderThread::setGrContext(sk_sp<GrContext> context) {
Derek Sollenbergerf9e45d12017-06-01 13:07:39 -0400177 mCacheManager->reset(context);
Greg Daniel660d6ec2017-12-08 11:44:27 -0500178 if (mGrContext) {
Derek Sollenbergerf9e45d12017-06-01 13:07:39 -0400179 mGrContext->releaseResourcesAndAbandonContext();
180 }
Greg Daniel660d6ec2017-12-08 11:44:27 -0500181 mGrContext = std::move(context);
Derek Sollenbergerf9e45d12017-06-01 13:07:39 -0400182}
183
John Recke45b1fd2014-04-15 09:50:16 -0700184int RenderThread::displayEventReceiverCallback(int fd, int events, void* data) {
185 if (events & (Looper::EVENT_ERROR | Looper::EVENT_HANGUP)) {
186 ALOGE("Display event receiver pipe was closed or an error occurred. "
John Reck1bcacfd2017-11-03 10:12:19 -0700187 "events=0x%x",
188 events);
189 return 0; // remove the callback
John Recke45b1fd2014-04-15 09:50:16 -0700190 }
191
192 if (!(events & Looper::EVENT_INPUT)) {
193 ALOGW("Received spurious callback for unhandled poll event. "
John Reck1bcacfd2017-11-03 10:12:19 -0700194 "events=0x%x",
195 events);
196 return 1; // keep the callback
John Recke45b1fd2014-04-15 09:50:16 -0700197 }
198
199 reinterpret_cast<RenderThread*>(data)->drainDisplayEventQueue();
200
John Reck1bcacfd2017-11-03 10:12:19 -0700201 return 1; // keep the callback
John Recke45b1fd2014-04-15 09:50:16 -0700202}
203
204static nsecs_t latestVsyncEvent(DisplayEventReceiver* receiver) {
205 DisplayEventReceiver::Event buf[EVENT_BUFFER_SIZE];
206 nsecs_t latest = 0;
207 ssize_t n;
208 while ((n = receiver->getEvents(buf, EVENT_BUFFER_SIZE)) > 0) {
209 for (ssize_t i = 0; i < n; i++) {
210 const DisplayEventReceiver::Event& ev = buf[i];
211 switch (ev.header.type) {
John Reck1bcacfd2017-11-03 10:12:19 -0700212 case DisplayEventReceiver::DISPLAY_EVENT_VSYNC:
213 latest = ev.header.timestamp;
214 break;
John Recke45b1fd2014-04-15 09:50:16 -0700215 }
216 }
217 }
218 if (n < 0) {
219 ALOGW("Failed to get events from display event receiver, status=%d", status_t(n));
220 }
221 return latest;
222}
223
John Recka733f892014-12-19 11:37:21 -0800224void RenderThread::drainDisplayEventQueue() {
John Recka5dda642014-05-22 15:43:54 -0700225 ATRACE_CALL();
John Recke45b1fd2014-04-15 09:50:16 -0700226 nsecs_t vsyncEvent = latestVsyncEvent(mDisplayEventReceiver);
227 if (vsyncEvent > 0) {
228 mVsyncRequested = false;
John Recka733f892014-12-19 11:37:21 -0800229 if (mTimeLord.vsyncReceived(vsyncEvent) && !mFrameCallbackTaskPending) {
John Recka5dda642014-05-22 15:43:54 -0700230 ATRACE_NAME("queue mFrameCallbackTask");
John Recke45b1fd2014-04-15 09:50:16 -0700231 mFrameCallbackTaskPending = true;
John Recka733f892014-12-19 11:37:21 -0800232 nsecs_t runAt = (vsyncEvent + DISPATCH_FRAME_CALLBACKS_DELAY);
John Reck1bcacfd2017-11-03 10:12:19 -0700233 queue().postAt(runAt, [this]() { dispatchFrameCallbacks(); });
John Recke45b1fd2014-04-15 09:50:16 -0700234 }
235 }
236}
237
238void RenderThread::dispatchFrameCallbacks() {
John Recka5dda642014-05-22 15:43:54 -0700239 ATRACE_CALL();
John Recke45b1fd2014-04-15 09:50:16 -0700240 mFrameCallbackTaskPending = false;
241
242 std::set<IFrameCallback*> callbacks;
243 mFrameCallbacks.swap(callbacks);
244
John Recka733f892014-12-19 11:37:21 -0800245 if (callbacks.size()) {
246 // Assume one of them will probably animate again so preemptively
247 // request the next vsync in case it occurs mid-frame
248 requestVsync();
John Reck1bcacfd2017-11-03 10:12:19 -0700249 for (std::set<IFrameCallback*>::iterator it = callbacks.begin(); it != callbacks.end();
250 it++) {
John Recka733f892014-12-19 11:37:21 -0800251 (*it)->doFrame();
252 }
John Recke45b1fd2014-04-15 09:50:16 -0700253 }
254}
255
John Recka5dda642014-05-22 15:43:54 -0700256void RenderThread::requestVsync() {
257 if (!mVsyncRequested) {
258 mVsyncRequested = true;
259 status_t status = mDisplayEventReceiver->requestNextVsync();
John Reck1bcacfd2017-11-03 10:12:19 -0700260 LOG_ALWAYS_FATAL_IF(status != NO_ERROR, "requestNextVsync failed with status: %d", status);
John Recka5dda642014-05-22 15:43:54 -0700261 }
262}
263
John Reckcec24ae2013-11-05 13:27:50 -0800264bool RenderThread::threadLoop() {
John Reck21be43e2014-08-14 10:25:16 -0700265 setpriority(PRIO_PROCESS, 0, PRIORITY_DISPLAY);
John Reck259b25a2017-12-01 16:18:53 -0800266 if (gOnStartHook) {
267 gOnStartHook();
268 }
John Reck3b202512014-06-23 13:13:08 -0700269 initThreadLocals();
John Recke45b1fd2014-04-15 09:50:16 -0700270
John Reckf8441e62017-10-23 13:10:41 -0700271 while (true) {
272 waitForWork();
273 processQueue();
John Recka5dda642014-05-22 15:43:54 -0700274
275 if (mPendingRegistrationFrameCallbacks.size() && !mFrameCallbackTaskPending) {
John Recka733f892014-12-19 11:37:21 -0800276 drainDisplayEventQueue();
John Reck1bcacfd2017-11-03 10:12:19 -0700277 mFrameCallbacks.insert(mPendingRegistrationFrameCallbacks.begin(),
278 mPendingRegistrationFrameCallbacks.end());
John Recka5dda642014-05-22 15:43:54 -0700279 mPendingRegistrationFrameCallbacks.clear();
280 requestVsync();
281 }
John Recka22c9b22015-01-14 10:40:15 -0800282
283 if (!mFrameCallbackTaskPending && !mVsyncRequested && mFrameCallbacks.size()) {
284 // TODO: Clean this up. This is working around an issue where a combination
285 // of bad timing and slow drawing can result in dropping a stale vsync
286 // on the floor (correct!) but fails to schedule to listen for the
287 // next vsync (oops), so none of the callbacks are run.
288 requestVsync();
289 }
John Reckcec24ae2013-11-05 13:27:50 -0800290 }
291
292 return false;
293}
294
John Recke45b1fd2014-04-15 09:50:16 -0700295void RenderThread::postFrameCallback(IFrameCallback* callback) {
John Recka5dda642014-05-22 15:43:54 -0700296 mPendingRegistrationFrameCallbacks.insert(callback);
John Recke45b1fd2014-04-15 09:50:16 -0700297}
298
John Reck01a5ea32014-12-03 13:01:07 -0800299bool RenderThread::removeFrameCallback(IFrameCallback* callback) {
300 size_t erased;
301 erased = mFrameCallbacks.erase(callback);
302 erased |= mPendingRegistrationFrameCallbacks.erase(callback);
303 return erased;
John Recka5dda642014-05-22 15:43:54 -0700304}
305
306void RenderThread::pushBackFrameCallback(IFrameCallback* callback) {
307 if (mFrameCallbacks.erase(callback)) {
308 mPendingRegistrationFrameCallbacks.insert(callback);
309 }
John Recke45b1fd2014-04-15 09:50:16 -0700310}
311
Stan Iliev7bc3bc62017-05-24 13:28:36 -0400312sk_sp<Bitmap> RenderThread::allocateHardwareBitmap(SkBitmap& skBitmap) {
313 auto renderType = Properties::getRenderPipelineType();
314 switch (renderType) {
315 case RenderPipelineType::OpenGL:
316 return OpenGLPipeline::allocateHardwareBitmap(*this, skBitmap);
317 case RenderPipelineType::SkiaGL:
318 return skiapipeline::SkiaOpenGLPipeline::allocateHardwareBitmap(*this, skBitmap);
319 case RenderPipelineType::SkiaVulkan:
320 return skiapipeline::SkiaVulkanPipeline::allocateHardwareBitmap(*this, skBitmap);
321 default:
John Reck1bcacfd2017-11-03 10:12:19 -0700322 LOG_ALWAYS_FATAL("canvas context type %d not supported", (int32_t)renderType);
Stan Iliev7bc3bc62017-05-24 13:28:36 -0400323 break;
324 }
325 return nullptr;
326}
327
Stan Iliev6b894d72017-08-23 12:41:41 -0400328bool RenderThread::isCurrent() {
329 return gettid() == getInstance().getTid();
330}
331
John Reckcec24ae2013-11-05 13:27:50 -0800332} /* namespace renderthread */
333} /* namespace uirenderer */
334} /* namespace android */