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