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