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 "CanvasContext.h"
20 #include "DeviceInfo.h"
21 #include "EglManager.h"
22 #include "OpenGLReadback.h"
23 #include "RenderProxy.h"
24 #include "VulkanManager.h"
25 #include "hwui/Bitmap.h"
26 #include "pipeline/skia/SkiaOpenGLPipeline.h"
27 #include "pipeline/skia/SkiaOpenGLReadback.h"
28 #include "pipeline/skia/SkiaVulkanReadback.h"
29 #include "pipeline/skia/SkiaVulkanPipeline.h"
30 #include "renderstate/RenderState.h"
31 #include "renderthread/OpenGLPipeline.h"
32 #include "utils/FatVector.h"
33 #include "utils/TimeUtils.h"
34 
35 #include <gui/DisplayEventReceiver.h>
36 #include <sys/resource.h>
37 #include <utils/Condition.h>
38 #include <utils/Log.h>
39 #include <utils/Mutex.h>
40 
41 namespace android {
42 namespace uirenderer {
43 namespace renderthread {
44 
45 // 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.
48 static 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
51 static const nsecs_t DISPATCH_FRAME_CALLBACKS_DELAY = milliseconds_to_nanoseconds(4);
52 
53 static bool gHasRenderThreadInstance = false;
54 
55 static void (*gOnStartHook)() = nullptr;
56 
57 class DisplayEventReceiverWrapper : public VsyncSource {
58 public:
DisplayEventReceiverWrapper(std::unique_ptr<DisplayEventReceiver> && receiver)59     DisplayEventReceiverWrapper(std::unique_ptr<DisplayEventReceiver>&& receiver)
60             : mDisplayEventReceiver(std::move(receiver)) {}
61 
requestNextVsync()62     virtual void requestNextVsync() override {
63         status_t status = mDisplayEventReceiver->requestNextVsync();
64         LOG_ALWAYS_FATAL_IF(status != NO_ERROR, "requestNextVsync failed with status: %d", status);
65     }
66 
latestVsyncEvent()67     virtual nsecs_t latestVsyncEvent() override {
68         DisplayEventReceiver::Event buf[EVENT_BUFFER_SIZE];
69         nsecs_t latest = 0;
70         ssize_t n;
71         while ((n = mDisplayEventReceiver->getEvents(buf, EVENT_BUFFER_SIZE)) > 0) {
72             for (ssize_t i = 0; i < n; i++) {
73                 const DisplayEventReceiver::Event& ev = buf[i];
74                 switch (ev.header.type) {
75                     case DisplayEventReceiver::DISPLAY_EVENT_VSYNC:
76                         latest = ev.header.timestamp;
77                         break;
78                 }
79             }
80         }
81         if (n < 0) {
82             ALOGW("Failed to get events from display event receiver, status=%d", status_t(n));
83         }
84         return latest;
85     }
86 
87 private:
88     std::unique_ptr<DisplayEventReceiver> mDisplayEventReceiver;
89 };
90 
91 class DummyVsyncSource : public VsyncSource {
92 public:
DummyVsyncSource(RenderThread * renderThread)93     DummyVsyncSource(RenderThread* renderThread) : mRenderThread(renderThread) {}
94 
requestNextVsync()95     virtual void requestNextVsync() override {
96         mRenderThread->queue().postDelayed(16_ms, [this]() {
97             mRenderThread->drainDisplayEventQueue();
98         });
99     }
100 
latestVsyncEvent()101     virtual nsecs_t latestVsyncEvent() override {
102         return systemTime(CLOCK_MONOTONIC);
103     }
104 
105 private:
106     RenderThread* mRenderThread;
107 };
108 
hasInstance()109 bool RenderThread::hasInstance() {
110     return gHasRenderThreadInstance;
111 }
112 
setOnStartHook(void (* onStartHook)())113 void RenderThread::setOnStartHook(void (*onStartHook)()) {
114     LOG_ALWAYS_FATAL_IF(hasInstance(), "can't set an onStartHook after we've started...");
115     gOnStartHook = onStartHook;
116 }
117 
getInstance()118 RenderThread& RenderThread::getInstance() {
119     // This is a pointer because otherwise __cxa_finalize
120     // will try to delete it like a Good Citizen but that causes us to crash
121     // because we don't want to delete the RenderThread normally.
122     static RenderThread* sInstance = new RenderThread();
123     gHasRenderThreadInstance = true;
124     return *sInstance;
125 }
126 
RenderThread()127 RenderThread::RenderThread()
128         : ThreadBase()
129         , mVsyncSource(nullptr)
130         , mVsyncRequested(false)
131         , mFrameCallbackTaskPending(false)
132         , mRenderState(nullptr)
133         , mEglManager(nullptr)
134         , mVkManager(nullptr) {
135     Properties::load();
136     start("RenderThread");
137 }
138 
~RenderThread()139 RenderThread::~RenderThread() {
140     LOG_ALWAYS_FATAL("Can't destroy the render thread");
141 }
142 
initializeDisplayEventReceiver()143 void RenderThread::initializeDisplayEventReceiver() {
144     LOG_ALWAYS_FATAL_IF(mVsyncSource, "Initializing a second DisplayEventReceiver?");
145 
146     if (!Properties::isolatedProcess) {
147         auto receiver = std::make_unique<DisplayEventReceiver>();
148         status_t status = receiver->initCheck();
149         LOG_ALWAYS_FATAL_IF(status != NO_ERROR,
150                 "Initialization of DisplayEventReceiver "
151                         "failed with status: %d",
152                 status);
153 
154         // Register the FD
155         mLooper->addFd(receiver->getFd(), 0, Looper::EVENT_INPUT,
156                 RenderThread::displayEventReceiverCallback, this);
157         mVsyncSource = new DisplayEventReceiverWrapper(std::move(receiver));
158     } else {
159         mVsyncSource = new DummyVsyncSource(this);
160     }
161 }
162 
initThreadLocals()163 void RenderThread::initThreadLocals() {
164     mDisplayInfo = DeviceInfo::queryDisplayInfo();
165     nsecs_t frameIntervalNanos = static_cast<nsecs_t>(1000000000 / mDisplayInfo.fps);
166     mTimeLord.setFrameInterval(frameIntervalNanos);
167     initializeDisplayEventReceiver();
168     mEglManager = new EglManager(*this);
169     mRenderState = new RenderState(*this);
170     mVkManager = new VulkanManager(*this);
171     mCacheManager = new CacheManager(mDisplayInfo);
172 }
173 
dumpGraphicsMemory(int fd)174 void RenderThread::dumpGraphicsMemory(int fd) {
175     globalProfileData()->dump(fd);
176 
177     String8 cachesOutput;
178     String8 pipeline;
179     auto renderType = Properties::getRenderPipelineType();
180     switch (renderType) {
181         case RenderPipelineType::OpenGL: {
182             if (Caches::hasInstance()) {
183                 cachesOutput.appendFormat("Caches:\n");
184                 Caches::getInstance().dumpMemoryUsage(cachesOutput);
185             } else {
186                 cachesOutput.appendFormat("No caches instance.");
187             }
188             pipeline.appendFormat("FrameBuilder");
189             break;
190         }
191         case RenderPipelineType::SkiaGL: {
192             mCacheManager->dumpMemoryUsage(cachesOutput, mRenderState);
193             pipeline.appendFormat("Skia (OpenGL)");
194             break;
195         }
196         case RenderPipelineType::SkiaVulkan: {
197             mCacheManager->dumpMemoryUsage(cachesOutput, mRenderState);
198             pipeline.appendFormat("Skia (Vulkan)");
199             break;
200         }
201         default:
202             LOG_ALWAYS_FATAL("canvas context type %d not supported", (int32_t)renderType);
203             break;
204     }
205 
206     dprintf(fd, "\n%s\n", cachesOutput.string());
207     dprintf(fd, "\nPipeline=%s\n", pipeline.string());
208 }
209 
readback()210 Readback& RenderThread::readback() {
211     if (!mReadback) {
212         auto renderType = Properties::getRenderPipelineType();
213         switch (renderType) {
214             case RenderPipelineType::OpenGL:
215                 mReadback = new OpenGLReadbackImpl(*this);
216                 break;
217             case RenderPipelineType::SkiaGL:
218                 mReadback = new skiapipeline::SkiaOpenGLReadback(*this);
219                 break;
220             case RenderPipelineType::SkiaVulkan:
221                 mReadback = new skiapipeline::SkiaVulkanReadback(*this);
222                 break;
223             default:
224                 LOG_ALWAYS_FATAL("canvas context type %d not supported", (int32_t)renderType);
225                 break;
226         }
227     }
228 
229     return *mReadback;
230 }
231 
setGrContext(sk_sp<GrContext> context)232 void RenderThread::setGrContext(sk_sp<GrContext> context) {
233     mCacheManager->reset(context);
234     if (mGrContext) {
235         mGrContext->releaseResourcesAndAbandonContext();
236     }
237     mGrContext = std::move(context);
238 }
239 
displayEventReceiverCallback(int fd,int events,void * data)240 int RenderThread::displayEventReceiverCallback(int fd, int events, void* data) {
241     if (events & (Looper::EVENT_ERROR | Looper::EVENT_HANGUP)) {
242         ALOGE("Display event receiver pipe was closed or an error occurred.  "
243               "events=0x%x",
244               events);
245         return 0;  // remove the callback
246     }
247 
248     if (!(events & Looper::EVENT_INPUT)) {
249         ALOGW("Received spurious callback for unhandled poll event.  "
250               "events=0x%x",
251               events);
252         return 1;  // keep the callback
253     }
254 
255     reinterpret_cast<RenderThread*>(data)->drainDisplayEventQueue();
256 
257     return 1;  // keep the callback
258 }
259 
drainDisplayEventQueue()260 void RenderThread::drainDisplayEventQueue() {
261     ATRACE_CALL();
262     nsecs_t vsyncEvent = mVsyncSource->latestVsyncEvent();
263     if (vsyncEvent > 0) {
264         mVsyncRequested = false;
265         if (mTimeLord.vsyncReceived(vsyncEvent) && !mFrameCallbackTaskPending) {
266             ATRACE_NAME("queue mFrameCallbackTask");
267             mFrameCallbackTaskPending = true;
268             nsecs_t runAt = (vsyncEvent + DISPATCH_FRAME_CALLBACKS_DELAY);
269             queue().postAt(runAt, [this]() { dispatchFrameCallbacks(); });
270         }
271     }
272 }
273 
dispatchFrameCallbacks()274 void RenderThread::dispatchFrameCallbacks() {
275     ATRACE_CALL();
276     mFrameCallbackTaskPending = false;
277 
278     std::set<IFrameCallback*> callbacks;
279     mFrameCallbacks.swap(callbacks);
280 
281     if (callbacks.size()) {
282         // Assume one of them will probably animate again so preemptively
283         // request the next vsync in case it occurs mid-frame
284         requestVsync();
285         for (std::set<IFrameCallback*>::iterator it = callbacks.begin(); it != callbacks.end();
286              it++) {
287             (*it)->doFrame();
288         }
289     }
290 }
291 
requestVsync()292 void RenderThread::requestVsync() {
293     if (!mVsyncRequested) {
294         mVsyncRequested = true;
295         mVsyncSource->requestNextVsync();
296     }
297 }
298 
threadLoop()299 bool RenderThread::threadLoop() {
300     setpriority(PRIO_PROCESS, 0, PRIORITY_DISPLAY);
301     if (gOnStartHook) {
302         gOnStartHook();
303     }
304     initThreadLocals();
305 
306     while (true) {
307         waitForWork();
308         processQueue();
309 
310         if (mPendingRegistrationFrameCallbacks.size() && !mFrameCallbackTaskPending) {
311             drainDisplayEventQueue();
312             mFrameCallbacks.insert(mPendingRegistrationFrameCallbacks.begin(),
313                                    mPendingRegistrationFrameCallbacks.end());
314             mPendingRegistrationFrameCallbacks.clear();
315             requestVsync();
316         }
317 
318         if (!mFrameCallbackTaskPending && !mVsyncRequested && mFrameCallbacks.size()) {
319             // TODO: Clean this up. This is working around an issue where a combination
320             // of bad timing and slow drawing can result in dropping a stale vsync
321             // on the floor (correct!) but fails to schedule to listen for the
322             // next vsync (oops), so none of the callbacks are run.
323             requestVsync();
324         }
325     }
326 
327     return false;
328 }
329 
postFrameCallback(IFrameCallback * callback)330 void RenderThread::postFrameCallback(IFrameCallback* callback) {
331     mPendingRegistrationFrameCallbacks.insert(callback);
332 }
333 
removeFrameCallback(IFrameCallback * callback)334 bool RenderThread::removeFrameCallback(IFrameCallback* callback) {
335     size_t erased;
336     erased = mFrameCallbacks.erase(callback);
337     erased |= mPendingRegistrationFrameCallbacks.erase(callback);
338     return erased;
339 }
340 
pushBackFrameCallback(IFrameCallback * callback)341 void RenderThread::pushBackFrameCallback(IFrameCallback* callback) {
342     if (mFrameCallbacks.erase(callback)) {
343         mPendingRegistrationFrameCallbacks.insert(callback);
344     }
345 }
346 
allocateHardwareBitmap(SkBitmap & skBitmap)347 sk_sp<Bitmap> RenderThread::allocateHardwareBitmap(SkBitmap& skBitmap) {
348     auto renderType = Properties::getRenderPipelineType();
349     switch (renderType) {
350         case RenderPipelineType::OpenGL:
351             return OpenGLPipeline::allocateHardwareBitmap(*this, skBitmap);
352         case RenderPipelineType::SkiaGL:
353             return skiapipeline::SkiaOpenGLPipeline::allocateHardwareBitmap(*this, skBitmap);
354         case RenderPipelineType::SkiaVulkan:
355             return skiapipeline::SkiaVulkanPipeline::allocateHardwareBitmap(*this, skBitmap);
356         default:
357             LOG_ALWAYS_FATAL("canvas context type %d not supported", (int32_t)renderType);
358             break;
359     }
360     return nullptr;
361 }
362 
isCurrent()363 bool RenderThread::isCurrent() {
364     return gettid() == getInstance().getTid();
365 }
366 
367 } /* namespace renderthread */
368 } /* namespace uirenderer */
369 } /* namespace android */
370