RenderProxy.cpp revision 298a146754e35cbc650aa991ebff1a41eefdbe80
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 "RenderProxy.h" 18 19#include "DeferredLayerUpdater.h" 20#include "DisplayList.h" 21#include "LayerRenderer.h" 22#include "Readback.h" 23#include "Rect.h" 24#include "renderthread/CanvasContext.h" 25#include "renderthread/EglManager.h" 26#include "renderthread/RenderTask.h" 27#include "renderthread/RenderThread.h" 28#include "utils/Macros.h" 29#include "utils/TimeUtils.h" 30 31namespace android { 32namespace uirenderer { 33namespace renderthread { 34 35#define ARGS(method) method ## Args 36 37#define CREATE_BRIDGE0(name) CREATE_BRIDGE(name,,,,,,,,) 38#define CREATE_BRIDGE1(name, a1) CREATE_BRIDGE(name, a1,,,,,,,) 39#define CREATE_BRIDGE2(name, a1, a2) CREATE_BRIDGE(name, a1,a2,,,,,,) 40#define CREATE_BRIDGE3(name, a1, a2, a3) CREATE_BRIDGE(name, a1,a2,a3,,,,,) 41#define CREATE_BRIDGE4(name, a1, a2, a3, a4) CREATE_BRIDGE(name, a1,a2,a3,a4,,,,) 42#define CREATE_BRIDGE5(name, a1, a2, a3, a4, a5) CREATE_BRIDGE(name, a1,a2,a3,a4,a5,,,) 43#define CREATE_BRIDGE6(name, a1, a2, a3, a4, a5, a6) CREATE_BRIDGE(name, a1,a2,a3,a4,a5,a6,,) 44#define CREATE_BRIDGE7(name, a1, a2, a3, a4, a5, a6, a7) CREATE_BRIDGE(name, a1,a2,a3,a4,a5,a6,a7,) 45#define CREATE_BRIDGE(name, a1, a2, a3, a4, a5, a6, a7, a8) \ 46 typedef struct { \ 47 a1; a2; a3; a4; a5; a6; a7; a8; \ 48 } ARGS(name); \ 49 static_assert(std::is_trivially_destructible<ARGS(name)>::value, \ 50 "Error, ARGS must be trivially destructible!"); \ 51 static void* Bridge_ ## name(ARGS(name)* args) 52 53#define SETUP_TASK(method) \ 54 LOG_ALWAYS_FATAL_IF( METHOD_INVOKE_PAYLOAD_SIZE < sizeof(ARGS(method)), \ 55 "METHOD_INVOKE_PAYLOAD_SIZE %zu is smaller than sizeof(" #method "Args) %zu", \ 56 METHOD_INVOKE_PAYLOAD_SIZE, sizeof(ARGS(method))); \ 57 MethodInvokeRenderTask* task = new MethodInvokeRenderTask((RunnableMethod) Bridge_ ## method); \ 58 ARGS(method) *args = (ARGS(method) *) task->payload() 59 60CREATE_BRIDGE4(createContext, RenderThread* thread, bool translucent, 61 RenderNode* rootRenderNode, IContextFactory* contextFactory) { 62 return new CanvasContext(*args->thread, args->translucent, 63 args->rootRenderNode, args->contextFactory); 64} 65 66RenderProxy::RenderProxy(bool translucent, RenderNode* rootRenderNode, IContextFactory* contextFactory) 67 : mRenderThread(RenderThread::getInstance()) 68 , mContext(nullptr) { 69 SETUP_TASK(createContext); 70 args->translucent = translucent; 71 args->rootRenderNode = rootRenderNode; 72 args->thread = &mRenderThread; 73 args->contextFactory = contextFactory; 74 mContext = (CanvasContext*) postAndWait(task); 75 mDrawFrameTask.setContext(&mRenderThread, mContext, rootRenderNode); 76} 77 78RenderProxy::~RenderProxy() { 79 destroyContext(); 80} 81 82CREATE_BRIDGE1(destroyContext, CanvasContext* context) { 83 delete args->context; 84 return nullptr; 85} 86 87void RenderProxy::destroyContext() { 88 if (mContext) { 89 SETUP_TASK(destroyContext); 90 args->context = mContext; 91 mContext = nullptr; 92 mDrawFrameTask.setContext(nullptr, nullptr, nullptr); 93 // This is also a fence as we need to be certain that there are no 94 // outstanding mDrawFrame tasks posted before it is destroyed 95 postAndWait(task); 96 } 97} 98 99CREATE_BRIDGE2(setSwapBehavior, CanvasContext* context, SwapBehavior swapBehavior) { 100 args->context->setSwapBehavior(args->swapBehavior); 101 return nullptr; 102} 103 104void RenderProxy::setSwapBehavior(SwapBehavior swapBehavior) { 105 SETUP_TASK(setSwapBehavior); 106 args->context = mContext; 107 args->swapBehavior = swapBehavior; 108 post(task); 109} 110 111CREATE_BRIDGE1(loadSystemProperties, CanvasContext* context) { 112 bool needsRedraw = false; 113 if (Caches::hasInstance()) { 114 needsRedraw = Properties::load(); 115 } 116 if (args->context->profiler().consumeProperties()) { 117 needsRedraw = true; 118 } 119 return (void*) needsRedraw; 120} 121 122bool RenderProxy::loadSystemProperties() { 123 SETUP_TASK(loadSystemProperties); 124 args->context = mContext; 125 return (bool) postAndWait(task); 126} 127 128CREATE_BRIDGE2(setName, CanvasContext* context, const char* name) { 129 args->context->setName(std::string(args->name)); 130 return nullptr; 131} 132 133void RenderProxy::setName(const char* name) { 134 SETUP_TASK(setName); 135 args->context = mContext; 136 args->name = name; 137 postAndWait(task); // block since name/value pointers owned by caller 138} 139 140CREATE_BRIDGE2(initialize, CanvasContext* context, Surface* surface) { 141 args->context->initialize(args->surface); 142 return nullptr; 143} 144 145void RenderProxy::initialize(const sp<Surface>& surface) { 146 SETUP_TASK(initialize); 147 args->context = mContext; 148 args->surface = surface.get(); 149 post(task); 150} 151 152CREATE_BRIDGE2(updateSurface, CanvasContext* context, Surface* surface) { 153 args->context->updateSurface(args->surface); 154 return nullptr; 155} 156 157void RenderProxy::updateSurface(const sp<Surface>& surface) { 158 SETUP_TASK(updateSurface); 159 args->context = mContext; 160 args->surface = surface.get(); 161 post(task); 162} 163 164CREATE_BRIDGE2(pauseSurface, CanvasContext* context, Surface* surface) { 165 return (void*) args->context->pauseSurface(args->surface); 166} 167 168bool RenderProxy::pauseSurface(const sp<Surface>& surface) { 169 SETUP_TASK(pauseSurface); 170 args->context = mContext; 171 args->surface = surface.get(); 172 return (bool) postAndWait(task); 173} 174 175CREATE_BRIDGE2(setStopped, CanvasContext* context, bool stopped) { 176 args->context->setStopped(args->stopped); 177 return nullptr; 178} 179 180void RenderProxy::setStopped(bool stopped) { 181 SETUP_TASK(setStopped); 182 args->context = mContext; 183 args->stopped = stopped; 184 postAndWait(task); 185} 186 187CREATE_BRIDGE6(setup, CanvasContext* context, int width, int height, 188 float lightRadius, uint8_t ambientShadowAlpha, uint8_t spotShadowAlpha) { 189 args->context->setup(args->width, args->height, args->lightRadius, 190 args->ambientShadowAlpha, args->spotShadowAlpha); 191 return nullptr; 192} 193 194void RenderProxy::setup(int width, int height, float lightRadius, 195 uint8_t ambientShadowAlpha, uint8_t spotShadowAlpha) { 196 SETUP_TASK(setup); 197 args->context = mContext; 198 args->width = width; 199 args->height = height; 200 args->lightRadius = lightRadius; 201 args->ambientShadowAlpha = ambientShadowAlpha; 202 args->spotShadowAlpha = spotShadowAlpha; 203 post(task); 204} 205 206CREATE_BRIDGE2(setLightCenter, CanvasContext* context, Vector3 lightCenter) { 207 args->context->setLightCenter(args->lightCenter); 208 return nullptr; 209} 210 211void RenderProxy::setLightCenter(const Vector3& lightCenter) { 212 SETUP_TASK(setLightCenter); 213 args->context = mContext; 214 args->lightCenter = lightCenter; 215 post(task); 216} 217 218CREATE_BRIDGE2(setOpaque, CanvasContext* context, bool opaque) { 219 args->context->setOpaque(args->opaque); 220 return nullptr; 221} 222 223void RenderProxy::setOpaque(bool opaque) { 224 SETUP_TASK(setOpaque); 225 args->context = mContext; 226 args->opaque = opaque; 227 post(task); 228} 229 230int64_t* RenderProxy::frameInfo() { 231 return mDrawFrameTask.frameInfo(); 232} 233 234int RenderProxy::syncAndDrawFrame(TreeObserver* observer) { 235 return mDrawFrameTask.drawFrame(observer); 236} 237 238CREATE_BRIDGE2(destroy, CanvasContext* context, TreeObserver* observer) { 239 args->context->destroy(args->observer); 240 return nullptr; 241} 242 243void RenderProxy::destroy(TreeObserver* observer) { 244 SETUP_TASK(destroy); 245 args->context = mContext; 246 args->observer = observer; 247 // destroyCanvasAndSurface() needs a fence as when it returns the 248 // underlying BufferQueue is going to be released from under 249 // the render thread. 250 postAndWait(task); 251} 252 253CREATE_BRIDGE2(invokeFunctor, RenderThread* thread, Functor* functor) { 254 CanvasContext::invokeFunctor(*args->thread, args->functor); 255 return nullptr; 256} 257 258void RenderProxy::invokeFunctor(Functor* functor, bool waitForCompletion) { 259 ATRACE_CALL(); 260 RenderThread& thread = RenderThread::getInstance(); 261 SETUP_TASK(invokeFunctor); 262 args->thread = &thread; 263 args->functor = functor; 264 if (waitForCompletion) { 265 // waitForCompletion = true is expected to be fairly rare and only 266 // happen in destruction. Thus it should be fine to temporarily 267 // create a Mutex 268 staticPostAndWait(task); 269 } else { 270 thread.queue(task); 271 } 272} 273 274CREATE_BRIDGE2(runWithGlContext, CanvasContext* context, RenderTask* task) { 275 args->context->runWithGlContext(args->task); 276 return nullptr; 277} 278 279void RenderProxy::runWithGlContext(RenderTask* gltask) { 280 SETUP_TASK(runWithGlContext); 281 args->context = mContext; 282 args->task = gltask; 283 postAndWait(task); 284} 285 286CREATE_BRIDGE1(createTextureLayer, CanvasContext* context) { 287 Layer* layer = args->context->createTextureLayer(); 288 if (!layer) return nullptr; 289 return new DeferredLayerUpdater(layer); 290} 291 292DeferredLayerUpdater* RenderProxy::createTextureLayer() { 293 SETUP_TASK(createTextureLayer); 294 args->context = mContext; 295 void* retval = postAndWait(task); 296 DeferredLayerUpdater* layer = reinterpret_cast<DeferredLayerUpdater*>(retval); 297 return layer; 298} 299 300CREATE_BRIDGE3(buildLayer, CanvasContext* context, RenderNode* node, TreeObserver* observer) { 301 args->context->buildLayer(args->node, args->observer); 302 return nullptr; 303} 304 305void RenderProxy::buildLayer(RenderNode* node, TreeObserver* observer) { 306 SETUP_TASK(buildLayer); 307 args->context = mContext; 308 args->node = node; 309 args->observer = observer; 310 postAndWait(task); 311} 312 313CREATE_BRIDGE3(copyLayerInto, CanvasContext* context, DeferredLayerUpdater* layer, 314 SkBitmap* bitmap) { 315 bool success = args->context->copyLayerInto(args->layer, args->bitmap); 316 return (void*) success; 317} 318 319bool RenderProxy::copyLayerInto(DeferredLayerUpdater* layer, SkBitmap& bitmap) { 320 SETUP_TASK(copyLayerInto); 321 args->context = mContext; 322 args->layer = layer; 323 args->bitmap = &bitmap; 324 return (bool) postAndWait(task); 325} 326 327void RenderProxy::pushLayerUpdate(DeferredLayerUpdater* layer) { 328 mDrawFrameTask.pushLayerUpdate(layer); 329} 330 331void RenderProxy::cancelLayerUpdate(DeferredLayerUpdater* layer) { 332 mDrawFrameTask.removeLayerUpdate(layer); 333} 334 335CREATE_BRIDGE1(detachSurfaceTexture, DeferredLayerUpdater* layer) { 336 args->layer->detachSurfaceTexture(); 337 return nullptr; 338} 339 340void RenderProxy::detachSurfaceTexture(DeferredLayerUpdater* layer) { 341 SETUP_TASK(detachSurfaceTexture); 342 args->layer = layer; 343 postAndWait(task); 344} 345 346CREATE_BRIDGE2(destroyHardwareResources, CanvasContext* context, TreeObserver* observer) { 347 args->context->destroyHardwareResources(args->observer); 348 return nullptr; 349} 350 351void RenderProxy::destroyHardwareResources(TreeObserver* observer) { 352 SETUP_TASK(destroyHardwareResources); 353 args->context = mContext; 354 args->observer = observer; 355 postAndWait(task); 356} 357 358CREATE_BRIDGE2(trimMemory, RenderThread* thread, int level) { 359 CanvasContext::trimMemory(*args->thread, args->level); 360 return nullptr; 361} 362 363void RenderProxy::trimMemory(int level) { 364 // Avoid creating a RenderThread to do a trimMemory. 365 if (RenderThread::hasInstance()) { 366 RenderThread& thread = RenderThread::getInstance(); 367 SETUP_TASK(trimMemory); 368 args->thread = &thread; 369 args->level = level; 370 thread.queue(task); 371 } 372} 373 374CREATE_BRIDGE2(overrideProperty, const char* name, const char* value) { 375 Properties::overrideProperty(args->name, args->value); 376 return nullptr; 377} 378 379void RenderProxy::overrideProperty(const char* name, const char* value) { 380 SETUP_TASK(overrideProperty); 381 args->name = name; 382 args->value = value; 383 staticPostAndWait(task); // expensive, but block here since name/value pointers owned by caller 384} 385 386CREATE_BRIDGE0(fence) { 387 // Intentionally empty 388 return nullptr; 389} 390 391template <typename T> 392void UNUSED(T t) {} 393 394void RenderProxy::fence() { 395 SETUP_TASK(fence); 396 UNUSED(args); 397 postAndWait(task); 398} 399 400void RenderProxy::staticFence() { 401 SETUP_TASK(fence); 402 UNUSED(args); 403 staticPostAndWait(task); 404} 405 406CREATE_BRIDGE1(stopDrawing, CanvasContext* context) { 407 args->context->stopDrawing(); 408 return nullptr; 409} 410 411void RenderProxy::stopDrawing() { 412 SETUP_TASK(stopDrawing); 413 args->context = mContext; 414 postAndWait(task); 415} 416 417CREATE_BRIDGE1(notifyFramePending, CanvasContext* context) { 418 args->context->notifyFramePending(); 419 return nullptr; 420} 421 422void RenderProxy::notifyFramePending() { 423 SETUP_TASK(notifyFramePending); 424 args->context = mContext; 425 mRenderThread.queueAtFront(task); 426} 427 428CREATE_BRIDGE4(dumpProfileInfo, CanvasContext* context, RenderThread* thread, 429 int fd, int dumpFlags) { 430 args->context->profiler().dumpData(args->fd); 431 if (args->dumpFlags & DumpFlags::FrameStats) { 432 args->context->dumpFrames(args->fd); 433 } 434 if (args->dumpFlags & DumpFlags::Reset) { 435 args->context->resetFrameStats(); 436 } 437 if (args->dumpFlags & DumpFlags::JankStats) { 438 args->thread->jankTracker().dump(args->fd); 439 } 440 return nullptr; 441} 442 443void RenderProxy::dumpProfileInfo(int fd, int dumpFlags) { 444 SETUP_TASK(dumpProfileInfo); 445 args->context = mContext; 446 args->thread = &mRenderThread; 447 args->fd = fd; 448 args->dumpFlags = dumpFlags; 449 postAndWait(task); 450} 451 452CREATE_BRIDGE1(resetProfileInfo, CanvasContext* context) { 453 args->context->resetFrameStats(); 454 return nullptr; 455} 456 457void RenderProxy::resetProfileInfo() { 458 SETUP_TASK(resetProfileInfo); 459 args->context = mContext; 460 postAndWait(task); 461} 462 463CREATE_BRIDGE2(dumpGraphicsMemory, int fd, RenderThread* thread) { 464 args->thread->jankTracker().dump(args->fd); 465 466 FILE *file = fdopen(args->fd, "a"); 467 if (Caches::hasInstance()) { 468 String8 cachesLog; 469 Caches::getInstance().dumpMemoryUsage(cachesLog); 470 fprintf(file, "\nCaches:\n%s\n", cachesLog.string()); 471 } else { 472 fprintf(file, "\nNo caches instance.\n"); 473 } 474#if HWUI_NEW_OPS 475 fprintf(file, "\nPipeline=FrameBuilder\n"); 476#else 477 fprintf(file, "\nPipeline=OpenGLRenderer\n"); 478#endif 479 fflush(file); 480 return nullptr; 481} 482 483void RenderProxy::dumpGraphicsMemory(int fd) { 484 if (!RenderThread::hasInstance()) return; 485 SETUP_TASK(dumpGraphicsMemory); 486 args->fd = fd; 487 args->thread = &RenderThread::getInstance(); 488 staticPostAndWait(task); 489} 490 491CREATE_BRIDGE4(setTextureAtlas, RenderThread* thread, GraphicBuffer* buffer, int64_t* map, 492 size_t size) { 493 CanvasContext::setTextureAtlas(*args->thread, args->buffer, args->map, args->size); 494 args->buffer->decStrong(nullptr); 495 return nullptr; 496} 497 498void RenderProxy::setTextureAtlas(const sp<GraphicBuffer>& buffer, int64_t* map, size_t size) { 499 SETUP_TASK(setTextureAtlas); 500 args->thread = &mRenderThread; 501 args->buffer = buffer.get(); 502 args->buffer->incStrong(nullptr); 503 args->map = map; 504 args->size = size; 505 post(task); 506} 507 508CREATE_BRIDGE2(setProcessStatsBuffer, RenderThread* thread, int fd) { 509 args->thread->jankTracker().switchStorageToAshmem(args->fd); 510 close(args->fd); 511 return nullptr; 512} 513 514void RenderProxy::setProcessStatsBuffer(int fd) { 515 SETUP_TASK(setProcessStatsBuffer); 516 args->thread = &mRenderThread; 517 args->fd = dup(fd); 518 post(task); 519} 520 521int RenderProxy::getRenderThreadTid() { 522 return mRenderThread.getTid(); 523} 524 525CREATE_BRIDGE3(addRenderNode, CanvasContext* context, RenderNode* node, bool placeFront) { 526 args->context->addRenderNode(args->node, args->placeFront); 527 return nullptr; 528} 529 530void RenderProxy::addRenderNode(RenderNode* node, bool placeFront) { 531 SETUP_TASK(addRenderNode); 532 args->context = mContext; 533 args->node = node; 534 args->placeFront = placeFront; 535 post(task); 536} 537 538CREATE_BRIDGE2(removeRenderNode, CanvasContext* context, RenderNode* node) { 539 args->context->removeRenderNode(args->node); 540 return nullptr; 541} 542 543void RenderProxy::removeRenderNode(RenderNode* node) { 544 SETUP_TASK(removeRenderNode); 545 args->context = mContext; 546 args->node = node; 547 post(task); 548} 549 550CREATE_BRIDGE2(drawRenderNode, CanvasContext* context, RenderNode* node) { 551 args->context->prepareAndDraw(args->node); 552 return nullptr; 553} 554 555void RenderProxy::drawRenderNode(RenderNode* node) { 556 SETUP_TASK(drawRenderNode); 557 args->context = mContext; 558 args->node = node; 559 // Be pseudo-thread-safe and don't use any member variables 560 staticPostAndWait(task); 561} 562 563CREATE_BRIDGE5(setContentDrawBounds, CanvasContext* context, int left, int top, 564 int right, int bottom) { 565 args->context->setContentDrawBounds(args->left, args->top, args->right, args->bottom); 566 return nullptr; 567} 568 569void RenderProxy::setContentDrawBounds(int left, int top, int right, int bottom) { 570 SETUP_TASK(setContentDrawBounds); 571 args->context = mContext; 572 args->left = left; 573 args->top = top; 574 args->right = right; 575 args->bottom = bottom; 576 staticPostAndWait(task); 577} 578 579CREATE_BRIDGE1(serializeDisplayListTree, CanvasContext* context) { 580 args->context->serializeDisplayListTree(); 581 return nullptr; 582} 583 584void RenderProxy::serializeDisplayListTree() { 585 SETUP_TASK(serializeDisplayListTree); 586 args->context = mContext; 587 post(task); 588} 589 590CREATE_BRIDGE2(addFrameMetricsObserver, CanvasContext* context, 591 FrameMetricsObserver* frameStatsObserver) { 592 args->context->addFrameMetricsObserver(args->frameStatsObserver); 593 if (args->frameStatsObserver != nullptr) { 594 args->frameStatsObserver->decStrong(args->context); 595 } 596 return nullptr; 597} 598 599void RenderProxy::addFrameMetricsObserver(FrameMetricsObserver* observer) { 600 SETUP_TASK(addFrameMetricsObserver); 601 args->context = mContext; 602 args->frameStatsObserver = observer; 603 if (observer != nullptr) { 604 observer->incStrong(mContext); 605 } 606 post(task); 607} 608 609CREATE_BRIDGE2(removeFrameMetricsObserver, CanvasContext* context, 610 FrameMetricsObserver* frameStatsObserver) { 611 args->context->removeFrameMetricsObserver(args->frameStatsObserver); 612 if (args->frameStatsObserver != nullptr) { 613 args->frameStatsObserver->decStrong(args->context); 614 } 615 return nullptr; 616} 617 618void RenderProxy::removeFrameMetricsObserver(FrameMetricsObserver* observer) { 619 SETUP_TASK(removeFrameMetricsObserver); 620 args->context = mContext; 621 args->frameStatsObserver = observer; 622 if (observer != nullptr) { 623 observer->incStrong(mContext); 624 } 625 post(task); 626} 627 628CREATE_BRIDGE3(copySurfaceInto, RenderThread* thread, 629 Surface* surface, SkBitmap* bitmap) { 630 return (void*) Readback::copySurfaceInto(*args->thread, 631 *args->surface, args->bitmap); 632} 633 634int RenderProxy::copySurfaceInto(sp<Surface>& surface, SkBitmap* bitmap) { 635 SETUP_TASK(copySurfaceInto); 636 args->bitmap = bitmap; 637 args->surface = surface.get(); 638 args->thread = &RenderThread::getInstance(); 639 return static_cast<int>( 640 reinterpret_cast<intptr_t>( staticPostAndWait(task) )); 641} 642 643CREATE_BRIDGE2(prepareToDraw, RenderThread* thread, SkBitmap* bitmap) { 644 if (Caches::hasInstance() && args->thread->eglManager().hasEglContext()) { 645 ATRACE_NAME("Bitmap#prepareToDraw task"); 646 Caches::getInstance().textureCache.prefetch(args->bitmap); 647 } 648 delete args->bitmap; 649 args->bitmap = nullptr; 650 return nullptr; 651} 652 653void RenderProxy::prepareToDraw(const SkBitmap& bitmap) { 654 // If we haven't spun up a hardware accelerated window yet, there's no 655 // point in precaching these bitmaps as it can't impact jank. 656 // We also don't know if we even will spin up a hardware-accelerated 657 // window or not. 658 if (!RenderThread::hasInstance()) return; 659 RenderThread* renderThread = &RenderThread::getInstance(); 660 SETUP_TASK(prepareToDraw); 661 args->thread = renderThread; 662 args->bitmap = new SkBitmap(bitmap); 663 nsecs_t lastVsync = renderThread->timeLord().latestVsync(); 664 nsecs_t estimatedNextVsync = lastVsync + renderThread->timeLord().frameIntervalNanos(); 665 nsecs_t timeToNextVsync = estimatedNextVsync - systemTime(CLOCK_MONOTONIC); 666 // We expect the UI thread to take 4ms and for RT to be active from VSYNC+4ms to 667 // VSYNC+12ms or so, so aim for the gap during which RT is expected to 668 // be idle 669 // TODO: Make this concept a first-class supported thing? RT could use 670 // knowledge of pending draws to better schedule this task 671 if (timeToNextVsync > -6_ms && timeToNextVsync < 1_ms) { 672 renderThread->queueAt(task, estimatedNextVsync + 8_ms); 673 } else { 674 renderThread->queue(task); 675 } 676} 677 678void RenderProxy::post(RenderTask* task) { 679 mRenderThread.queue(task); 680} 681 682void* RenderProxy::postAndWait(MethodInvokeRenderTask* task) { 683 void* retval; 684 task->setReturnPtr(&retval); 685 SignalingRenderTask syncTask(task, &mSyncMutex, &mSyncCondition); 686 AutoMutex _lock(mSyncMutex); 687 mRenderThread.queue(&syncTask); 688 while (!syncTask.hasRun()) { 689 mSyncCondition.wait(mSyncMutex); 690 } 691 return retval; 692} 693 694void* RenderProxy::staticPostAndWait(MethodInvokeRenderTask* task) { 695 RenderThread& thread = RenderThread::getInstance(); 696 void* retval; 697 task->setReturnPtr(&retval); 698 thread.queueAndWait(task); 699 return retval; 700} 701 702} /* namespace renderthread */ 703} /* namespace uirenderer */ 704} /* namespace android */ 705