OSDN Git Service

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