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