RenderProxy.cpp revision 56ad6ec42f814e9e61030ff819cac4e5d31def8b
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/RenderTask.h" 25#include "renderthread/RenderThread.h" 26#include "utils/Macros.h" 27 28namespace android { 29namespace uirenderer { 30namespace renderthread { 31 32#define ARGS(method) method ## Args 33 34#define CREATE_BRIDGE0(name) CREATE_BRIDGE(name,,,,,,,,) 35#define CREATE_BRIDGE1(name, a1) CREATE_BRIDGE(name, a1,,,,,,,) 36#define CREATE_BRIDGE2(name, a1, a2) CREATE_BRIDGE(name, a1,a2,,,,,,) 37#define CREATE_BRIDGE3(name, a1, a2, a3) CREATE_BRIDGE(name, a1,a2,a3,,,,,) 38#define CREATE_BRIDGE4(name, a1, a2, a3, a4) CREATE_BRIDGE(name, a1,a2,a3,a4,,,,) 39#define CREATE_BRIDGE5(name, a1, a2, a3, a4, a5) CREATE_BRIDGE(name, a1,a2,a3,a4,a5,,,) 40#define CREATE_BRIDGE6(name, a1, a2, a3, a4, a5, a6) CREATE_BRIDGE(name, a1,a2,a3,a4,a5,a6,,) 41#define CREATE_BRIDGE7(name, a1, a2, a3, a4, a5, a6, a7) CREATE_BRIDGE(name, a1,a2,a3,a4,a5,a6,a7,) 42#define CREATE_BRIDGE(name, a1, a2, a3, a4, a5, a6, a7, a8) \ 43 typedef struct { \ 44 a1; a2; a3; a4; a5; a6; a7; a8; \ 45 } ARGS(name); \ 46 static void* Bridge_ ## name(ARGS(name)* args) 47 48#define SETUP_TASK(method) \ 49 LOG_ALWAYS_FATAL_IF( METHOD_INVOKE_PAYLOAD_SIZE < sizeof(ARGS(method)), \ 50 "METHOD_INVOKE_PAYLOAD_SIZE %zu is smaller than sizeof(" #method "Args) %zu", \ 51 METHOD_INVOKE_PAYLOAD_SIZE, sizeof(ARGS(method))); \ 52 MethodInvokeRenderTask* task = new MethodInvokeRenderTask((RunnableMethod) Bridge_ ## method); \ 53 ARGS(method) *args = (ARGS(method) *) task->payload() 54 55CREATE_BRIDGE4(createContext, RenderThread* thread, bool translucent, 56 RenderNode* rootRenderNode, IContextFactory* contextFactory) { 57 return CanvasContext::create(*args->thread, args->translucent, 58 args->rootRenderNode, args->contextFactory); 59} 60 61RenderProxy::RenderProxy(bool translucent, RenderNode* rootRenderNode, IContextFactory* contextFactory) 62 : mRenderThread(RenderThread::getInstance()) 63 , mContext(nullptr) { 64 SETUP_TASK(createContext); 65 args->translucent = translucent; 66 args->rootRenderNode = rootRenderNode; 67 args->thread = &mRenderThread; 68 args->contextFactory = contextFactory; 69 mContext = (CanvasContext*) postAndWait(task); 70 mDrawFrameTask.setContext(&mRenderThread, mContext, rootRenderNode); 71} 72 73RenderProxy::~RenderProxy() { 74 destroyContext(); 75} 76 77CREATE_BRIDGE1(destroyContext, CanvasContext* context) { 78 delete args->context; 79 return nullptr; 80} 81 82void RenderProxy::destroyContext() { 83 if (mContext) { 84 SETUP_TASK(destroyContext); 85 args->context = mContext; 86 mContext = nullptr; 87 mDrawFrameTask.setContext(nullptr, nullptr, nullptr); 88 // This is also a fence as we need to be certain that there are no 89 // outstanding mDrawFrame tasks posted before it is destroyed 90 postAndWait(task); 91 } 92} 93 94CREATE_BRIDGE2(setSwapBehavior, CanvasContext* context, SwapBehavior swapBehavior) { 95 args->context->setSwapBehavior(args->swapBehavior); 96 return nullptr; 97} 98 99void RenderProxy::setSwapBehavior(SwapBehavior swapBehavior) { 100 SETUP_TASK(setSwapBehavior); 101 args->context = mContext; 102 args->swapBehavior = swapBehavior; 103 post(task); 104} 105 106CREATE_BRIDGE1(loadSystemProperties, CanvasContext* context) { 107 bool needsRedraw = false; 108 if (Caches::hasInstance()) { 109 needsRedraw = Properties::load(); 110 } 111 if (args->context->profiler().consumeProperties()) { 112 needsRedraw = true; 113 } 114 return (void*) needsRedraw; 115} 116 117bool RenderProxy::loadSystemProperties() { 118 SETUP_TASK(loadSystemProperties); 119 args->context = mContext; 120 return (bool) postAndWait(task); 121} 122 123CREATE_BRIDGE2(setName, CanvasContext* context, const char* name) { 124 args->context->setName(std::string(args->name)); 125 return nullptr; 126} 127 128void RenderProxy::setName(const char* name) { 129 SETUP_TASK(setName); 130 args->context = mContext; 131 args->name = name; 132 postAndWait(task); // block since name/value pointers owned by caller 133} 134 135CREATE_BRIDGE2(initialize, CanvasContext* context, Surface* surface) { 136 args->context->initialize(args->surface); 137 return nullptr; 138} 139 140void RenderProxy::initialize(const sp<Surface>& surface) { 141 SETUP_TASK(initialize); 142 args->context = mContext; 143 args->surface = surface.get(); 144 post(task); 145} 146 147CREATE_BRIDGE2(updateSurface, CanvasContext* context, Surface* surface) { 148 args->context->updateSurface(args->surface); 149 return nullptr; 150} 151 152void RenderProxy::updateSurface(const sp<Surface>& surface) { 153 SETUP_TASK(updateSurface); 154 args->context = mContext; 155 args->surface = surface.get(); 156 postAndWait(task); 157} 158 159CREATE_BRIDGE2(pauseSurface, CanvasContext* context, Surface* surface) { 160 return (void*) args->context->pauseSurface(args->surface); 161} 162 163bool RenderProxy::pauseSurface(const sp<Surface>& surface) { 164 SETUP_TASK(pauseSurface); 165 args->context = mContext; 166 args->surface = surface.get(); 167 return (bool) postAndWait(task); 168} 169 170CREATE_BRIDGE2(setStopped, CanvasContext* context, bool stopped) { 171 args->context->setStopped(args->stopped); 172 return nullptr; 173} 174 175void RenderProxy::setStopped(bool stopped) { 176 SETUP_TASK(setStopped); 177 args->context = mContext; 178 args->stopped = stopped; 179 postAndWait(task); 180} 181 182CREATE_BRIDGE4(setup, CanvasContext* context, 183 float lightRadius, uint8_t ambientShadowAlpha, uint8_t spotShadowAlpha) { 184 args->context->setup(args->lightRadius, 185 args->ambientShadowAlpha, args->spotShadowAlpha); 186 return nullptr; 187} 188 189void RenderProxy::setup(float lightRadius, 190 uint8_t ambientShadowAlpha, uint8_t spotShadowAlpha) { 191 SETUP_TASK(setup); 192 args->context = mContext; 193 args->lightRadius = lightRadius; 194 args->ambientShadowAlpha = ambientShadowAlpha; 195 args->spotShadowAlpha = spotShadowAlpha; 196 post(task); 197} 198 199CREATE_BRIDGE2(setLightCenter, CanvasContext* context, Vector3 lightCenter) { 200 args->context->setLightCenter(args->lightCenter); 201 return nullptr; 202} 203 204void RenderProxy::setLightCenter(const Vector3& lightCenter) { 205 SETUP_TASK(setLightCenter); 206 args->context = mContext; 207 args->lightCenter = lightCenter; 208 post(task); 209} 210 211CREATE_BRIDGE2(setOpaque, CanvasContext* context, bool opaque) { 212 args->context->setOpaque(args->opaque); 213 return nullptr; 214} 215 216void RenderProxy::setOpaque(bool opaque) { 217 SETUP_TASK(setOpaque); 218 args->context = mContext; 219 args->opaque = opaque; 220 post(task); 221} 222 223int64_t* RenderProxy::frameInfo() { 224 return mDrawFrameTask.frameInfo(); 225} 226 227int RenderProxy::syncAndDrawFrame(TreeObserver* observer) { 228 return mDrawFrameTask.drawFrame(observer); 229} 230 231CREATE_BRIDGE2(destroy, CanvasContext* context, TreeObserver* observer) { 232 args->context->destroy(args->observer); 233 return nullptr; 234} 235 236void RenderProxy::destroy(TreeObserver* observer) { 237 SETUP_TASK(destroy); 238 args->context = mContext; 239 args->observer = observer; 240 // destroyCanvasAndSurface() needs a fence as when it returns the 241 // underlying BufferQueue is going to be released from under 242 // the render thread. 243 postAndWait(task); 244} 245 246CREATE_BRIDGE2(invokeFunctor, RenderThread* thread, Functor* functor) { 247 CanvasContext::invokeFunctor(*args->thread, args->functor); 248 return nullptr; 249} 250 251void RenderProxy::invokeFunctor(Functor* functor, bool waitForCompletion) { 252 ATRACE_CALL(); 253 RenderThread& thread = RenderThread::getInstance(); 254 SETUP_TASK(invokeFunctor); 255 args->thread = &thread; 256 args->functor = functor; 257 if (waitForCompletion) { 258 // waitForCompletion = true is expected to be fairly rare and only 259 // happen in destruction. Thus it should be fine to temporarily 260 // create a Mutex 261 staticPostAndWait(task); 262 } else { 263 thread.queue(task); 264 } 265} 266 267CREATE_BRIDGE1(createTextureLayer, CanvasContext* context) { 268 return args->context->createTextureLayer(); 269} 270 271DeferredLayerUpdater* RenderProxy::createTextureLayer() { 272 SETUP_TASK(createTextureLayer); 273 args->context = mContext; 274 void* retval = postAndWait(task); 275 DeferredLayerUpdater* layer = reinterpret_cast<DeferredLayerUpdater*>(retval); 276 return layer; 277} 278 279CREATE_BRIDGE3(buildLayer, CanvasContext* context, RenderNode* node, TreeObserver* observer) { 280 args->context->buildLayer(args->node, args->observer); 281 return nullptr; 282} 283 284void RenderProxy::buildLayer(RenderNode* node, TreeObserver* observer) { 285 SETUP_TASK(buildLayer); 286 args->context = mContext; 287 args->node = node; 288 args->observer = observer; 289 postAndWait(task); 290} 291 292CREATE_BRIDGE3(copyLayerInto, CanvasContext* context, DeferredLayerUpdater* layer, 293 SkBitmap* bitmap) { 294 bool success = args->context->copyLayerInto(args->layer, args->bitmap); 295 return (void*) success; 296} 297 298bool RenderProxy::copyLayerInto(DeferredLayerUpdater* layer, SkBitmap& bitmap) { 299 SETUP_TASK(copyLayerInto); 300 args->context = mContext; 301 args->layer = layer; 302 args->bitmap = &bitmap; 303 return (bool) postAndWait(task); 304} 305 306void RenderProxy::pushLayerUpdate(DeferredLayerUpdater* layer) { 307 mDrawFrameTask.pushLayerUpdate(layer); 308} 309 310void RenderProxy::cancelLayerUpdate(DeferredLayerUpdater* layer) { 311 mDrawFrameTask.removeLayerUpdate(layer); 312} 313 314CREATE_BRIDGE1(detachSurfaceTexture, DeferredLayerUpdater* layer) { 315 args->layer->detachSurfaceTexture(); 316 return nullptr; 317} 318 319void RenderProxy::detachSurfaceTexture(DeferredLayerUpdater* layer) { 320 SETUP_TASK(detachSurfaceTexture); 321 args->layer = layer; 322 postAndWait(task); 323} 324 325CREATE_BRIDGE2(destroyHardwareResources, CanvasContext* context, TreeObserver* observer) { 326 args->context->destroyHardwareResources(args->observer); 327 return nullptr; 328} 329 330void RenderProxy::destroyHardwareResources(TreeObserver* observer) { 331 SETUP_TASK(destroyHardwareResources); 332 args->context = mContext; 333 args->observer = observer; 334 postAndWait(task); 335} 336 337CREATE_BRIDGE2(trimMemory, RenderThread* thread, int level) { 338 CanvasContext::trimMemory(*args->thread, args->level); 339 return nullptr; 340} 341 342void RenderProxy::trimMemory(int level) { 343 // Avoid creating a RenderThread to do a trimMemory. 344 if (RenderThread::hasInstance()) { 345 RenderThread& thread = RenderThread::getInstance(); 346 SETUP_TASK(trimMemory); 347 args->thread = &thread; 348 args->level = level; 349 thread.queue(task); 350 } 351} 352 353CREATE_BRIDGE2(overrideProperty, const char* name, const char* value) { 354 Properties::overrideProperty(args->name, args->value); 355 return nullptr; 356} 357 358void RenderProxy::overrideProperty(const char* name, const char* value) { 359 SETUP_TASK(overrideProperty); 360 args->name = name; 361 args->value = value; 362 staticPostAndWait(task); // expensive, but block here since name/value pointers owned by caller 363} 364 365CREATE_BRIDGE0(fence) { 366 // Intentionally empty 367 return nullptr; 368} 369 370template <typename T> 371void UNUSED(T t) {} 372 373void RenderProxy::fence() { 374 SETUP_TASK(fence); 375 UNUSED(args); 376 postAndWait(task); 377} 378 379void RenderProxy::staticFence() { 380 SETUP_TASK(fence); 381 UNUSED(args); 382 staticPostAndWait(task); 383} 384 385CREATE_BRIDGE1(stopDrawing, CanvasContext* context) { 386 args->context->stopDrawing(); 387 return nullptr; 388} 389 390void RenderProxy::stopDrawing() { 391 SETUP_TASK(stopDrawing); 392 args->context = mContext; 393 postAndWait(task); 394} 395 396CREATE_BRIDGE1(notifyFramePending, CanvasContext* context) { 397 args->context->notifyFramePending(); 398 return nullptr; 399} 400 401void RenderProxy::notifyFramePending() { 402 SETUP_TASK(notifyFramePending); 403 args->context = mContext; 404 mRenderThread.queueAtFront(task); 405} 406 407CREATE_BRIDGE4(dumpProfileInfo, CanvasContext* context, RenderThread* thread, 408 int fd, int dumpFlags) { 409 args->context->profiler().dumpData(args->fd); 410 if (args->dumpFlags & DumpFlags::FrameStats) { 411 args->context->dumpFrames(args->fd); 412 } 413 if (args->dumpFlags & DumpFlags::Reset) { 414 args->context->resetFrameStats(); 415 } 416 if (args->dumpFlags & DumpFlags::JankStats) { 417 args->thread->jankTracker().dump(args->fd); 418 } 419 return nullptr; 420} 421 422void RenderProxy::dumpProfileInfo(int fd, int dumpFlags) { 423 SETUP_TASK(dumpProfileInfo); 424 args->context = mContext; 425 args->thread = &mRenderThread; 426 args->fd = fd; 427 args->dumpFlags = dumpFlags; 428 postAndWait(task); 429} 430 431CREATE_BRIDGE1(resetProfileInfo, CanvasContext* context) { 432 args->context->resetFrameStats(); 433 return nullptr; 434} 435 436void RenderProxy::resetProfileInfo() { 437 SETUP_TASK(resetProfileInfo); 438 args->context = mContext; 439 postAndWait(task); 440} 441 442CREATE_BRIDGE2(frameTimePercentile, RenderThread* thread, int percentile) { 443 return reinterpret_cast<void*>(static_cast<uintptr_t>( 444 args->thread->jankTracker().findPercentile(args->percentile))); 445} 446 447uint32_t RenderProxy::frameTimePercentile(int p) { 448 SETUP_TASK(frameTimePercentile); 449 args->thread = &mRenderThread; 450 args->percentile = p; 451 return static_cast<uint32_t>(reinterpret_cast<uintptr_t>( 452 postAndWait(task))); 453} 454 455CREATE_BRIDGE2(dumpGraphicsMemory, int fd, RenderThread* thread) { 456 args->thread->jankTracker().dump(args->fd); 457 458 FILE *file = fdopen(args->fd, "a"); 459 if (Caches::hasInstance()) { 460 String8 cachesLog; 461 Caches::getInstance().dumpMemoryUsage(cachesLog); 462 fprintf(file, "\nCaches:\n%s\n", cachesLog.string()); 463 } else { 464 fprintf(file, "\nNo caches instance.\n"); 465 } 466 fprintf(file, "\nPipeline=FrameBuilder\n"); 467 fflush(file); 468 return nullptr; 469} 470 471void RenderProxy::dumpGraphicsMemory(int fd) { 472 if (!RenderThread::hasInstance()) return; 473 SETUP_TASK(dumpGraphicsMemory); 474 args->fd = fd; 475 args->thread = &RenderThread::getInstance(); 476 staticPostAndWait(task); 477} 478 479CREATE_BRIDGE4(setTextureAtlas, RenderThread* thread, GraphicBuffer* buffer, int64_t* map, 480 size_t size) { 481 CanvasContext::setTextureAtlas(*args->thread, args->buffer, args->map, args->size); 482 args->buffer->decStrong(nullptr); 483 return nullptr; 484} 485 486void RenderProxy::setTextureAtlas(const sp<GraphicBuffer>& buffer, int64_t* map, size_t size) { 487 SETUP_TASK(setTextureAtlas); 488 args->thread = &mRenderThread; 489 args->buffer = buffer.get(); 490 args->buffer->incStrong(nullptr); 491 args->map = map; 492 args->size = size; 493 post(task); 494} 495 496CREATE_BRIDGE2(setProcessStatsBuffer, RenderThread* thread, int fd) { 497 args->thread->jankTracker().switchStorageToAshmem(args->fd); 498 close(args->fd); 499 return nullptr; 500} 501 502void RenderProxy::setProcessStatsBuffer(int fd) { 503 SETUP_TASK(setProcessStatsBuffer); 504 args->thread = &mRenderThread; 505 args->fd = dup(fd); 506 post(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_BRIDGE3(copySurfaceInto, RenderThread* thread, 617 Surface* surface, SkBitmap* bitmap) { 618 return (void*) Readback::copySurfaceInto(*args->thread, 619 *args->surface, args->bitmap); 620} 621 622int RenderProxy::copySurfaceInto(sp<Surface>& surface, SkBitmap* bitmap) { 623 SETUP_TASK(copySurfaceInto); 624 args->bitmap = bitmap; 625 args->surface = surface.get(); 626 args->thread = &RenderThread::getInstance(); 627 return static_cast<int>( 628 reinterpret_cast<intptr_t>( staticPostAndWait(task) )); 629} 630 631void RenderProxy::post(RenderTask* task) { 632 mRenderThread.queue(task); 633} 634 635void* RenderProxy::postAndWait(MethodInvokeRenderTask* task) { 636 void* retval; 637 task->setReturnPtr(&retval); 638 SignalingRenderTask syncTask(task, &mSyncMutex, &mSyncCondition); 639 AutoMutex _lock(mSyncMutex); 640 mRenderThread.queue(&syncTask); 641 mSyncCondition.wait(mSyncMutex); 642 return retval; 643} 644 645void* RenderProxy::staticPostAndWait(MethodInvokeRenderTask* task) { 646 RenderThread& thread = RenderThread::getInstance(); 647 void* retval; 648 task->setReturnPtr(&retval); 649 thread.queueAndWait(task); 650 return retval; 651} 652 653} /* namespace renderthread */ 654} /* namespace uirenderer */ 655} /* namespace android */ 656