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