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