RenderProxy.cpp revision 9a814875c4e3a98fea99dae623f22268a9afa38a
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 "renderstate/RenderState.h" 28#include "utils/Macros.h" 29#include "utils/TimeUtils.h" 30 31#include <ui/GraphicBuffer.h> 32 33namespace android { 34namespace uirenderer { 35namespace renderthread { 36 37#define ARGS(method) method ## Args 38 39#define CREATE_BRIDGE0(name) CREATE_BRIDGE(name,,,,,,,,) 40#define CREATE_BRIDGE1(name, a1) CREATE_BRIDGE(name, a1,,,,,,,) 41#define CREATE_BRIDGE2(name, a1, a2) CREATE_BRIDGE(name, a1,a2,,,,,,) 42#define CREATE_BRIDGE3(name, a1, a2, a3) CREATE_BRIDGE(name, a1,a2,a3,,,,,) 43#define CREATE_BRIDGE4(name, a1, a2, a3, a4) CREATE_BRIDGE(name, a1,a2,a3,a4,,,,) 44#define CREATE_BRIDGE5(name, a1, a2, a3, a4, a5) CREATE_BRIDGE(name, a1,a2,a3,a4,a5,,,) 45#define CREATE_BRIDGE6(name, a1, a2, a3, a4, a5, a6) CREATE_BRIDGE(name, a1,a2,a3,a4,a5,a6,,) 46#define CREATE_BRIDGE7(name, a1, a2, a3, a4, a5, a6, a7) CREATE_BRIDGE(name, a1,a2,a3,a4,a5,a6,a7,) 47#define CREATE_BRIDGE(name, a1, a2, a3, a4, a5, a6, a7, a8) \ 48 typedef struct { \ 49 a1; a2; a3; a4; a5; a6; a7; a8; \ 50 } ARGS(name); \ 51 static_assert(std::is_trivially_destructible<ARGS(name)>::value, \ 52 "Error, ARGS must be trivially destructible!"); \ 53 static void* Bridge_ ## name(ARGS(name)* args) 54 55#define SETUP_TASK(method) \ 56 LOG_ALWAYS_FATAL_IF( METHOD_INVOKE_PAYLOAD_SIZE < sizeof(ARGS(method)), \ 57 "METHOD_INVOKE_PAYLOAD_SIZE %zu is smaller than sizeof(" #method "Args) %zu", \ 58 METHOD_INVOKE_PAYLOAD_SIZE, sizeof(ARGS(method))); \ 59 MethodInvokeRenderTask* task = new MethodInvokeRenderTask((RunnableMethod) Bridge_ ## method); \ 60 ARGS(method) *args = (ARGS(method) *) task->payload() 61 62CREATE_BRIDGE4(createContext, RenderThread* thread, bool translucent, 63 RenderNode* rootRenderNode, IContextFactory* contextFactory) { 64 return CanvasContext::create(*args->thread, args->translucent, 65 args->rootRenderNode, args->contextFactory); 66} 67 68RenderProxy::RenderProxy(bool translucent, RenderNode* rootRenderNode, IContextFactory* contextFactory) 69 : mRenderThread(RenderThread::getInstance()) 70 , mContext(nullptr) { 71 SETUP_TASK(createContext); 72 args->translucent = translucent; 73 args->rootRenderNode = rootRenderNode; 74 args->thread = &mRenderThread; 75 args->contextFactory = contextFactory; 76 mContext = (CanvasContext*) postAndWait(task); 77 mDrawFrameTask.setContext(&mRenderThread, mContext, rootRenderNode); 78} 79 80RenderProxy::~RenderProxy() { 81 destroyContext(); 82} 83 84CREATE_BRIDGE1(destroyContext, CanvasContext* context) { 85 delete args->context; 86 return nullptr; 87} 88 89void RenderProxy::destroyContext() { 90 if (mContext) { 91 SETUP_TASK(destroyContext); 92 args->context = mContext; 93 mContext = nullptr; 94 mDrawFrameTask.setContext(nullptr, nullptr, nullptr); 95 // This is also a fence as we need to be certain that there are no 96 // outstanding mDrawFrame tasks posted before it is destroyed 97 postAndWait(task); 98 } 99} 100 101CREATE_BRIDGE2(setSwapBehavior, CanvasContext* context, SwapBehavior swapBehavior) { 102 args->context->setSwapBehavior(args->swapBehavior); 103 return nullptr; 104} 105 106void RenderProxy::setSwapBehavior(SwapBehavior swapBehavior) { 107 SETUP_TASK(setSwapBehavior); 108 args->context = mContext; 109 args->swapBehavior = swapBehavior; 110 post(task); 111} 112 113CREATE_BRIDGE1(loadSystemProperties, CanvasContext* context) { 114 bool needsRedraw = false; 115 if (Caches::hasInstance()) { 116 needsRedraw = Properties::load(); 117 } 118 if (args->context->profiler().consumeProperties()) { 119 needsRedraw = true; 120 } 121 return (void*) needsRedraw; 122} 123 124bool RenderProxy::loadSystemProperties() { 125 SETUP_TASK(loadSystemProperties); 126 args->context = mContext; 127 return (bool) postAndWait(task); 128} 129 130CREATE_BRIDGE2(setName, CanvasContext* context, const char* name) { 131 args->context->setName(std::string(args->name)); 132 return nullptr; 133} 134 135void RenderProxy::setName(const char* name) { 136 SETUP_TASK(setName); 137 args->context = mContext; 138 args->name = name; 139 postAndWait(task); // block since name/value pointers owned by caller 140} 141 142CREATE_BRIDGE2(initialize, CanvasContext* context, Surface* surface) { 143 args->context->initialize(args->surface); 144 return nullptr; 145} 146 147void RenderProxy::initialize(const sp<Surface>& surface) { 148 SETUP_TASK(initialize); 149 args->context = mContext; 150 args->surface = surface.get(); 151 post(task); 152} 153 154CREATE_BRIDGE2(updateSurface, CanvasContext* context, Surface* surface) { 155 args->context->updateSurface(args->surface); 156 return nullptr; 157} 158 159void RenderProxy::updateSurface(const sp<Surface>& surface) { 160 SETUP_TASK(updateSurface); 161 args->context = mContext; 162 args->surface = surface.get(); 163 post(task); 164} 165 166CREATE_BRIDGE2(pauseSurface, CanvasContext* context, Surface* surface) { 167 return (void*) args->context->pauseSurface(args->surface); 168} 169 170bool RenderProxy::pauseSurface(const sp<Surface>& surface) { 171 SETUP_TASK(pauseSurface); 172 args->context = mContext; 173 args->surface = surface.get(); 174 return (bool) postAndWait(task); 175} 176 177CREATE_BRIDGE2(setStopped, CanvasContext* context, bool stopped) { 178 args->context->setStopped(args->stopped); 179 return nullptr; 180} 181 182void RenderProxy::setStopped(bool stopped) { 183 SETUP_TASK(setStopped); 184 args->context = mContext; 185 args->stopped = stopped; 186 postAndWait(task); 187} 188 189CREATE_BRIDGE4(setup, CanvasContext* context, 190 float lightRadius, uint8_t ambientShadowAlpha, uint8_t spotShadowAlpha) { 191 args->context->setup(args->lightRadius, 192 args->ambientShadowAlpha, args->spotShadowAlpha); 193 return nullptr; 194} 195 196void RenderProxy::setup(float lightRadius, 197 uint8_t ambientShadowAlpha, uint8_t spotShadowAlpha) { 198 SETUP_TASK(setup); 199 args->context = mContext; 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() { 235 return mDrawFrameTask.drawFrame(); 236} 237 238CREATE_BRIDGE1(destroy, CanvasContext* context) { 239 args->context->destroy(); 240 return nullptr; 241} 242 243void RenderProxy::destroy() { 244 SETUP_TASK(destroy); 245 args->context = mContext; 246 // destroyCanvasAndSurface() needs a fence as when it returns the 247 // underlying BufferQueue is going to be released from under 248 // the render thread. 249 postAndWait(task); 250} 251 252CREATE_BRIDGE2(invokeFunctor, RenderThread* thread, Functor* functor) { 253 CanvasContext::invokeFunctor(*args->thread, args->functor); 254 return nullptr; 255} 256 257void RenderProxy::invokeFunctor(Functor* functor, bool waitForCompletion) { 258 ATRACE_CALL(); 259 RenderThread& thread = RenderThread::getInstance(); 260 SETUP_TASK(invokeFunctor); 261 args->thread = &thread; 262 args->functor = functor; 263 if (waitForCompletion) { 264 // waitForCompletion = true is expected to be fairly rare and only 265 // happen in destruction. Thus it should be fine to temporarily 266 // create a Mutex 267 staticPostAndWait(task); 268 } else { 269 thread.queue(task); 270 } 271} 272 273CREATE_BRIDGE1(createTextureLayer, CanvasContext* context) { 274 return args->context->createTextureLayer(); 275} 276 277DeferredLayerUpdater* RenderProxy::createTextureLayer() { 278 SETUP_TASK(createTextureLayer); 279 args->context = mContext; 280 void* retval = postAndWait(task); 281 DeferredLayerUpdater* layer = reinterpret_cast<DeferredLayerUpdater*>(retval); 282 return layer; 283} 284 285CREATE_BRIDGE2(buildLayer, CanvasContext* context, RenderNode* node) { 286 args->context->buildLayer(args->node); 287 return nullptr; 288} 289 290void RenderProxy::buildLayer(RenderNode* node) { 291 SETUP_TASK(buildLayer); 292 args->context = mContext; 293 args->node = node; 294 postAndWait(task); 295} 296 297CREATE_BRIDGE3(copyLayerInto, CanvasContext* context, DeferredLayerUpdater* layer, 298 SkBitmap* bitmap) { 299 bool success = args->context->copyLayerInto(args->layer, args->bitmap); 300 return (void*) success; 301} 302 303bool RenderProxy::copyLayerInto(DeferredLayerUpdater* layer, SkBitmap& bitmap) { 304 SETUP_TASK(copyLayerInto); 305 args->context = mContext; 306 args->layer = layer; 307 args->bitmap = &bitmap; 308 return (bool) postAndWait(task); 309} 310 311void RenderProxy::pushLayerUpdate(DeferredLayerUpdater* layer) { 312 mDrawFrameTask.pushLayerUpdate(layer); 313} 314 315void RenderProxy::cancelLayerUpdate(DeferredLayerUpdater* layer) { 316 mDrawFrameTask.removeLayerUpdate(layer); 317} 318 319CREATE_BRIDGE1(detachSurfaceTexture, DeferredLayerUpdater* layer) { 320 args->layer->detachSurfaceTexture(); 321 return nullptr; 322} 323 324void RenderProxy::detachSurfaceTexture(DeferredLayerUpdater* layer) { 325 SETUP_TASK(detachSurfaceTexture); 326 args->layer = layer; 327 postAndWait(task); 328} 329 330CREATE_BRIDGE1(destroyHardwareResources, CanvasContext* context) { 331 args->context->destroyHardwareResources(); 332 return nullptr; 333} 334 335void RenderProxy::destroyHardwareResources() { 336 SETUP_TASK(destroyHardwareResources); 337 args->context = mContext; 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_BRIDGE2(setProcessStatsBuffer, RenderThread* thread, int fd) { 484 args->thread->jankTracker().switchStorageToAshmem(args->fd); 485 close(args->fd); 486 return nullptr; 487} 488 489void RenderProxy::setProcessStatsBuffer(int fd) { 490 SETUP_TASK(setProcessStatsBuffer); 491 auto& rt = RenderThread::getInstance(); 492 args->thread = &rt; 493 args->fd = dup(fd); 494 rt.queue(task); 495} 496 497CREATE_BRIDGE1(rotateProcessStatsBuffer, RenderThread* thread) { 498 args->thread->jankTracker().rotateStorage(); 499 return nullptr; 500} 501 502void RenderProxy::rotateProcessStatsBuffer() { 503 SETUP_TASK(rotateProcessStatsBuffer); 504 auto& rt = RenderThread::getInstance(); 505 args->thread = &rt; 506 rt.queue(task); 507} 508 509int RenderProxy::getRenderThreadTid() { 510 return mRenderThread.getTid(); 511} 512 513CREATE_BRIDGE3(addRenderNode, CanvasContext* context, RenderNode* node, bool placeFront) { 514 args->context->addRenderNode(args->node, args->placeFront); 515 return nullptr; 516} 517 518void RenderProxy::addRenderNode(RenderNode* node, bool placeFront) { 519 SETUP_TASK(addRenderNode); 520 args->context = mContext; 521 args->node = node; 522 args->placeFront = placeFront; 523 post(task); 524} 525 526CREATE_BRIDGE2(removeRenderNode, CanvasContext* context, RenderNode* node) { 527 args->context->removeRenderNode(args->node); 528 return nullptr; 529} 530 531void RenderProxy::removeRenderNode(RenderNode* node) { 532 SETUP_TASK(removeRenderNode); 533 args->context = mContext; 534 args->node = node; 535 post(task); 536} 537 538CREATE_BRIDGE2(drawRenderNode, CanvasContext* context, RenderNode* node) { 539 args->context->prepareAndDraw(args->node); 540 return nullptr; 541} 542 543void RenderProxy::drawRenderNode(RenderNode* node) { 544 SETUP_TASK(drawRenderNode); 545 args->context = mContext; 546 args->node = node; 547 // Be pseudo-thread-safe and don't use any member variables 548 staticPostAndWait(task); 549} 550 551CREATE_BRIDGE5(setContentDrawBounds, CanvasContext* context, int left, int top, 552 int right, int bottom) { 553 args->context->setContentDrawBounds(args->left, args->top, args->right, args->bottom); 554 return nullptr; 555} 556 557void RenderProxy::setContentDrawBounds(int left, int top, int right, int bottom) { 558 SETUP_TASK(setContentDrawBounds); 559 args->context = mContext; 560 args->left = left; 561 args->top = top; 562 args->right = right; 563 args->bottom = bottom; 564 staticPostAndWait(task); 565} 566 567CREATE_BRIDGE1(serializeDisplayListTree, CanvasContext* context) { 568 args->context->serializeDisplayListTree(); 569 return nullptr; 570} 571 572void RenderProxy::serializeDisplayListTree() { 573 SETUP_TASK(serializeDisplayListTree); 574 args->context = mContext; 575 post(task); 576} 577 578CREATE_BRIDGE2(addFrameMetricsObserver, CanvasContext* context, 579 FrameMetricsObserver* frameStatsObserver) { 580 args->context->addFrameMetricsObserver(args->frameStatsObserver); 581 if (args->frameStatsObserver != nullptr) { 582 args->frameStatsObserver->decStrong(args->context); 583 } 584 return nullptr; 585} 586 587void RenderProxy::addFrameMetricsObserver(FrameMetricsObserver* observer) { 588 SETUP_TASK(addFrameMetricsObserver); 589 args->context = mContext; 590 args->frameStatsObserver = observer; 591 if (observer != nullptr) { 592 observer->incStrong(mContext); 593 } 594 post(task); 595} 596 597CREATE_BRIDGE2(removeFrameMetricsObserver, CanvasContext* context, 598 FrameMetricsObserver* frameStatsObserver) { 599 args->context->removeFrameMetricsObserver(args->frameStatsObserver); 600 if (args->frameStatsObserver != nullptr) { 601 args->frameStatsObserver->decStrong(args->context); 602 } 603 return nullptr; 604} 605 606void RenderProxy::removeFrameMetricsObserver(FrameMetricsObserver* observer) { 607 SETUP_TASK(removeFrameMetricsObserver); 608 args->context = mContext; 609 args->frameStatsObserver = observer; 610 if (observer != nullptr) { 611 observer->incStrong(mContext); 612 } 613 post(task); 614} 615 616CREATE_BRIDGE4(copySurfaceInto, RenderThread* thread, 617 Surface* surface, Rect srcRect, SkBitmap* bitmap) { 618 return (void*)args->thread->readback().copySurfaceInto(*args->surface, 619 args->srcRect, args->bitmap); 620} 621 622int RenderProxy::copySurfaceInto(sp<Surface>& surface, int left, int top, 623 int right, int bottom, SkBitmap* bitmap) { 624 SETUP_TASK(copySurfaceInto); 625 args->bitmap = bitmap; 626 args->surface = surface.get(); 627 args->thread = &RenderThread::getInstance(); 628 args->srcRect.set(left, top, right, bottom); 629 return static_cast<int>( 630 reinterpret_cast<intptr_t>( staticPostAndWait(task) )); 631} 632 633CREATE_BRIDGE2(prepareToDraw, RenderThread* thread, Bitmap* bitmap) { 634 CanvasContext::prepareToDraw(*args->thread, args->bitmap); 635 args->bitmap->unref(); 636 args->bitmap = nullptr; 637 return nullptr; 638} 639 640void RenderProxy::prepareToDraw(Bitmap& bitmap) { 641 // If we haven't spun up a hardware accelerated window yet, there's no 642 // point in precaching these bitmaps as it can't impact jank. 643 // We also don't know if we even will spin up a hardware-accelerated 644 // window or not. 645 if (!RenderThread::hasInstance()) return; 646 RenderThread* renderThread = &RenderThread::getInstance(); 647 SETUP_TASK(prepareToDraw); 648 args->thread = renderThread; 649 bitmap.ref(); 650 args->bitmap = &bitmap; 651 nsecs_t lastVsync = renderThread->timeLord().latestVsync(); 652 nsecs_t estimatedNextVsync = lastVsync + renderThread->timeLord().frameIntervalNanos(); 653 nsecs_t timeToNextVsync = estimatedNextVsync - systemTime(CLOCK_MONOTONIC); 654 // We expect the UI thread to take 4ms and for RT to be active from VSYNC+4ms to 655 // VSYNC+12ms or so, so aim for the gap during which RT is expected to 656 // be idle 657 // TODO: Make this concept a first-class supported thing? RT could use 658 // knowledge of pending draws to better schedule this task 659 if (timeToNextVsync > -6_ms && timeToNextVsync < 1_ms) { 660 renderThread->queueAt(task, estimatedNextVsync + 8_ms); 661 } else { 662 renderThread->queue(task); 663 } 664} 665 666CREATE_BRIDGE2(allocateHardwareBitmap, RenderThread* thread, SkBitmap* bitmap) { 667 sk_sp<Bitmap> hardwareBitmap = Bitmap::allocateHardwareBitmap(*args->thread, *args->bitmap); 668 return hardwareBitmap.release(); 669} 670 671sk_sp<Bitmap> RenderProxy::allocateHardwareBitmap(SkBitmap& bitmap) { 672 SETUP_TASK(allocateHardwareBitmap); 673 args->bitmap = &bitmap; 674 args->thread = &RenderThread::getInstance(); 675 sk_sp<Bitmap> hardwareBitmap(reinterpret_cast<Bitmap*>(staticPostAndWait(task))); 676 return hardwareBitmap; 677} 678 679CREATE_BRIDGE3(copyGraphicBufferInto, RenderThread* thread, GraphicBuffer* buffer, SkBitmap* bitmap) { 680 return (void*) args->thread->readback().copyGraphicBufferInto(args->buffer, args->bitmap); 681} 682 683int RenderProxy::copyGraphicBufferInto(GraphicBuffer* buffer, SkBitmap* bitmap) { 684 RenderThread& thread = RenderThread::getInstance(); 685 if (Properties::isSkiaEnabled() && gettid() == thread.getTid()) { 686 //TODO: fix everything that hits this. We should never be triggering a readback ourselves. 687 return (int) thread.readback().copyGraphicBufferInto(buffer, bitmap); 688 } else { 689 SETUP_TASK(copyGraphicBufferInto); 690 args->thread = &thread; 691 args->bitmap = bitmap; 692 args->buffer = buffer; 693 return static_cast<int>(reinterpret_cast<intptr_t>(staticPostAndWait(task))); 694 } 695} 696 697CREATE_BRIDGE2(onBitmapDestroyed, RenderThread* thread, uint32_t pixelRefId) { 698 args->thread->renderState().onBitmapDestroyed(args->pixelRefId); 699 return nullptr; 700} 701 702void RenderProxy::onBitmapDestroyed(uint32_t pixelRefId) { 703 if (!RenderThread::hasInstance()) return; 704 SETUP_TASK(onBitmapDestroyed); 705 RenderThread& thread = RenderThread::getInstance(); 706 args->thread = &thread; 707 args->pixelRefId = pixelRefId; 708 thread.queue(task); 709} 710 711void RenderProxy::post(RenderTask* task) { 712 mRenderThread.queue(task); 713} 714 715void* RenderProxy::postAndWait(MethodInvokeRenderTask* task) { 716 void* retval; 717 task->setReturnPtr(&retval); 718 SignalingRenderTask syncTask(task, &mSyncMutex, &mSyncCondition); 719 AutoMutex _lock(mSyncMutex); 720 mRenderThread.queue(&syncTask); 721 while (!syncTask.hasRun()) { 722 mSyncCondition.wait(mSyncMutex); 723 } 724 return retval; 725} 726 727void* RenderProxy::staticPostAndWait(MethodInvokeRenderTask* task) { 728 RenderThread& thread = RenderThread::getInstance(); 729 LOG_ALWAYS_FATAL_IF(gettid() == thread.getTid()); 730 void* retval; 731 task->setReturnPtr(&retval); 732 thread.queueAndWait(task); 733 return retval; 734} 735 736} /* namespace renderthread */ 737} /* namespace uirenderer */ 738} /* namespace android */ 739