Home | History | Annotate | Download | only in renderthread
      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:
     59     DisplayEventReceiverWrapper(std::unique_ptr<DisplayEventReceiver>&& receiver)
     60             : mDisplayEventReceiver(std::move(receiver)) {}
     61 
     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 
     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:
     93     DummyVsyncSource(RenderThread* renderThread) : mRenderThread(renderThread) {}
     94 
     95     virtual void requestNextVsync() override {
     96         mRenderThread->queue().postDelayed(16_ms, [this]() {
     97             mRenderThread->drainDisplayEventQueue();
     98         });
     99     }
    100 
    101     virtual nsecs_t latestVsyncEvent() override {
    102         return systemTime(CLOCK_MONOTONIC);
    103     }
    104 
    105 private:
    106     RenderThread* mRenderThread;
    107 };
    108 
    109 bool RenderThread::hasInstance() {
    110     return gHasRenderThreadInstance;
    111 }
    112 
    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 
    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 
    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 
    139 RenderThread::~RenderThread() {
    140     LOG_ALWAYS_FATAL("Can't destroy the render thread");
    141 }
    142 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    292 void RenderThread::requestVsync() {
    293     if (!mVsyncRequested) {
    294         mVsyncRequested = true;
    295         mVsyncSource->requestNextVsync();
    296     }
    297 }
    298 
    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 
    330 void RenderThread::postFrameCallback(IFrameCallback* callback) {
    331     mPendingRegistrationFrameCallbacks.insert(callback);
    332 }
    333 
    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 
    341 void RenderThread::pushBackFrameCallback(IFrameCallback* callback) {
    342     if (mFrameCallbacks.erase(callback)) {
    343         mPendingRegistrationFrameCallbacks.insert(callback);
    344     }
    345 }
    346 
    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 
    363 bool RenderThread::isCurrent() {
    364     return gettid() == getInstance().getTid();
    365 }
    366 
    367 } /* namespace renderthread */
    368 } /* namespace uirenderer */
    369 } /* namespace android */
    370