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