RenderProxy.cpp revision 06f5bc70a667a02b14e31d3f53f91d3661e30666
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 "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 55namespace DumpFlags { 56 enum { 57 FrameStats = 1 << 0, 58 Reset = 1 << 1, 59 }; 60}; 61 62CREATE_BRIDGE4(createContext, RenderThread* thread, bool translucent, 63 RenderNode* rootRenderNode, IContextFactory* contextFactory) { 64 return new CanvasContext(*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, ANativeWindow* window) { 143 args->context->initialize(args->window); 144 return nullptr; 145} 146 147void RenderProxy::initialize(const sp<ANativeWindow>& window) { 148 SETUP_TASK(initialize); 149 args->context = mContext; 150 args->window = window.get(); 151 post(task); 152} 153 154CREATE_BRIDGE2(updateSurface, CanvasContext* context, ANativeWindow* window) { 155 args->context->updateSurface(args->window); 156 return nullptr; 157} 158 159void RenderProxy::updateSurface(const sp<ANativeWindow>& window) { 160 SETUP_TASK(updateSurface); 161 args->context = mContext; 162 args->window = window.get(); 163 postAndWait(task); 164} 165 166CREATE_BRIDGE2(pauseSurface, CanvasContext* context, ANativeWindow* window) { 167 return (void*) args->context->pauseSurface(args->window); 168} 169 170bool RenderProxy::pauseSurface(const sp<ANativeWindow>& window) { 171 SETUP_TASK(pauseSurface); 172 args->context = mContext; 173 args->window = window.get(); 174 return (bool) postAndWait(task); 175} 176 177CREATE_BRIDGE6(setup, CanvasContext* context, int width, int height, 178 float lightRadius, uint8_t ambientShadowAlpha, uint8_t spotShadowAlpha) { 179 args->context->setup(args->width, args->height, args->lightRadius, 180 args->ambientShadowAlpha, args->spotShadowAlpha); 181 return nullptr; 182} 183 184void RenderProxy::setup(int width, int height, float lightRadius, 185 uint8_t ambientShadowAlpha, uint8_t spotShadowAlpha) { 186 SETUP_TASK(setup); 187 args->context = mContext; 188 args->width = width; 189 args->height = height; 190 args->lightRadius = lightRadius; 191 args->ambientShadowAlpha = ambientShadowAlpha; 192 args->spotShadowAlpha = spotShadowAlpha; 193 post(task); 194} 195 196CREATE_BRIDGE2(setLightCenter, CanvasContext* context, Vector3 lightCenter) { 197 args->context->setLightCenter(args->lightCenter); 198 return nullptr; 199} 200 201void RenderProxy::setLightCenter(const Vector3& lightCenter) { 202 SETUP_TASK(setLightCenter); 203 args->context = mContext; 204 args->lightCenter = lightCenter; 205 post(task); 206} 207 208CREATE_BRIDGE2(setOpaque, CanvasContext* context, bool opaque) { 209 args->context->setOpaque(args->opaque); 210 return nullptr; 211} 212 213void RenderProxy::setOpaque(bool opaque) { 214 SETUP_TASK(setOpaque); 215 args->context = mContext; 216 args->opaque = opaque; 217 post(task); 218} 219 220int64_t* RenderProxy::frameInfo() { 221 return mDrawFrameTask.frameInfo(); 222} 223 224int RenderProxy::syncAndDrawFrame() { 225 return mDrawFrameTask.drawFrame(); 226} 227 228CREATE_BRIDGE1(destroy, CanvasContext* context) { 229 args->context->destroy(); 230 return nullptr; 231} 232 233void RenderProxy::destroy() { 234 SETUP_TASK(destroy); 235 args->context = mContext; 236 // destroyCanvasAndSurface() needs a fence as when it returns the 237 // underlying BufferQueue is going to be released from under 238 // the render thread. 239 postAndWait(task); 240} 241 242CREATE_BRIDGE2(invokeFunctor, RenderThread* thread, Functor* functor) { 243 CanvasContext::invokeFunctor(*args->thread, args->functor); 244 return nullptr; 245} 246 247void RenderProxy::invokeFunctor(Functor* functor, bool waitForCompletion) { 248 ATRACE_CALL(); 249 RenderThread& thread = RenderThread::getInstance(); 250 SETUP_TASK(invokeFunctor); 251 args->thread = &thread; 252 args->functor = functor; 253 if (waitForCompletion) { 254 // waitForCompletion = true is expected to be fairly rare and only 255 // happen in destruction. Thus it should be fine to temporarily 256 // create a Mutex 257 staticPostAndWait(task); 258 } else { 259 thread.queue(task); 260 } 261} 262 263CREATE_BRIDGE2(runWithGlContext, CanvasContext* context, RenderTask* task) { 264 args->context->runWithGlContext(args->task); 265 return nullptr; 266} 267 268void RenderProxy::runWithGlContext(RenderTask* gltask) { 269 SETUP_TASK(runWithGlContext); 270 args->context = mContext; 271 args->task = gltask; 272 postAndWait(task); 273} 274 275CREATE_BRIDGE1(createTextureLayer, CanvasContext* context) { 276 Layer* layer = args->context->createTextureLayer(); 277 if (!layer) return nullptr; 278 return new DeferredLayerUpdater(layer); 279} 280 281DeferredLayerUpdater* RenderProxy::createTextureLayer() { 282 SETUP_TASK(createTextureLayer); 283 args->context = mContext; 284 void* retval = postAndWait(task); 285 DeferredLayerUpdater* layer = reinterpret_cast<DeferredLayerUpdater*>(retval); 286 return layer; 287} 288 289CREATE_BRIDGE2(buildLayer, CanvasContext* context, RenderNode* node) { 290 args->context->buildLayer(args->node); 291 return nullptr; 292} 293 294void RenderProxy::buildLayer(RenderNode* node) { 295 SETUP_TASK(buildLayer); 296 args->context = mContext; 297 args->node = node; 298 postAndWait(task); 299} 300 301CREATE_BRIDGE3(copyLayerInto, CanvasContext* context, DeferredLayerUpdater* layer, 302 SkBitmap* bitmap) { 303 bool success = args->context->copyLayerInto(args->layer, args->bitmap); 304 return (void*) success; 305} 306 307bool RenderProxy::copyLayerInto(DeferredLayerUpdater* layer, SkBitmap& bitmap) { 308 SETUP_TASK(copyLayerInto); 309 args->context = mContext; 310 args->layer = layer; 311 args->bitmap = &bitmap; 312 return (bool) postAndWait(task); 313} 314 315void RenderProxy::pushLayerUpdate(DeferredLayerUpdater* layer) { 316 mDrawFrameTask.pushLayerUpdate(layer); 317} 318 319void RenderProxy::cancelLayerUpdate(DeferredLayerUpdater* layer) { 320 mDrawFrameTask.removeLayerUpdate(layer); 321} 322 323CREATE_BRIDGE1(detachSurfaceTexture, DeferredLayerUpdater* layer) { 324 args->layer->detachSurfaceTexture(); 325 return nullptr; 326} 327 328void RenderProxy::detachSurfaceTexture(DeferredLayerUpdater* layer) { 329 SETUP_TASK(detachSurfaceTexture); 330 args->layer = layer; 331 postAndWait(task); 332} 333 334CREATE_BRIDGE1(destroyHardwareResources, CanvasContext* context) { 335 args->context->destroyHardwareResources(); 336 return nullptr; 337} 338 339void RenderProxy::destroyHardwareResources() { 340 SETUP_TASK(destroyHardwareResources); 341 args->context = mContext; 342 post(task); 343} 344 345CREATE_BRIDGE2(trimMemory, RenderThread* thread, int level) { 346 CanvasContext::trimMemory(*args->thread, args->level); 347 return nullptr; 348} 349 350void RenderProxy::trimMemory(int level) { 351 // Avoid creating a RenderThread to do a trimMemory. 352 if (RenderThread::hasInstance()) { 353 RenderThread& thread = RenderThread::getInstance(); 354 SETUP_TASK(trimMemory); 355 args->thread = &thread; 356 args->level = level; 357 thread.queue(task); 358 } 359} 360 361CREATE_BRIDGE2(overrideProperty, const char* name, const char* value) { 362 Properties::overrideProperty(args->name, args->value); 363 return nullptr; 364} 365 366void RenderProxy::overrideProperty(const char* name, const char* value) { 367 SETUP_TASK(overrideProperty); 368 args->name = name; 369 args->value = value; 370 staticPostAndWait(task); // expensive, but block here since name/value pointers owned by caller 371} 372 373CREATE_BRIDGE0(fence) { 374 // Intentionally empty 375 return nullptr; 376} 377 378template <typename T> 379void UNUSED(T t) {} 380 381void RenderProxy::fence() { 382 SETUP_TASK(fence); 383 UNUSED(args); 384 postAndWait(task); 385} 386 387void RenderProxy::staticFence() { 388 SETUP_TASK(fence); 389 UNUSED(args); 390 staticPostAndWait(task); 391} 392 393CREATE_BRIDGE1(stopDrawing, CanvasContext* context) { 394 args->context->stopDrawing(); 395 return nullptr; 396} 397 398void RenderProxy::stopDrawing() { 399 SETUP_TASK(stopDrawing); 400 args->context = mContext; 401 postAndWait(task); 402} 403 404CREATE_BRIDGE1(notifyFramePending, CanvasContext* context) { 405 args->context->notifyFramePending(); 406 return nullptr; 407} 408 409void RenderProxy::notifyFramePending() { 410 SETUP_TASK(notifyFramePending); 411 args->context = mContext; 412 mRenderThread.queueAtFront(task); 413} 414 415CREATE_BRIDGE4(dumpProfileInfo, CanvasContext* context, RenderThread* thread, 416 int fd, int dumpFlags) { 417 args->context->profiler().dumpData(args->fd); 418 args->thread->jankTracker().dump(args->fd); 419 if (args->dumpFlags & DumpFlags::FrameStats) { 420 args->context->dumpFrames(args->fd); 421 } 422 if (args->dumpFlags & DumpFlags::Reset) { 423 args->context->resetFrameStats(); 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(dumpGraphicsMemory, int fd, RenderThread* thread) { 449 args->thread->jankTracker().dump(args->fd); 450 451 FILE *file = fdopen(args->fd, "a"); 452 if (Caches::hasInstance()) { 453 String8 cachesLog; 454 Caches::getInstance().dumpMemoryUsage(cachesLog); 455 fprintf(file, "\nCaches:\n%s\n", cachesLog.string()); 456 } else { 457 fprintf(file, "\nNo caches instance.\n"); 458 } 459#if HWUI_NEW_OPS 460 fprintf(file, "\nPipeline=FrameBuilder\n"); 461#else 462 fprintf(file, "\nPipeline=OpenGLRenderer\n"); 463#endif 464 fflush(file); 465 return nullptr; 466} 467 468void RenderProxy::dumpGraphicsMemory(int fd) { 469 if (!RenderThread::hasInstance()) return; 470 SETUP_TASK(dumpGraphicsMemory); 471 args->fd = fd; 472 args->thread = &RenderThread::getInstance(); 473 staticPostAndWait(task); 474} 475 476CREATE_BRIDGE4(setTextureAtlas, RenderThread* thread, GraphicBuffer* buffer, int64_t* map, 477 size_t size) { 478 CanvasContext::setTextureAtlas(*args->thread, args->buffer, args->map, args->size); 479 args->buffer->decStrong(nullptr); 480 return nullptr; 481} 482 483void RenderProxy::setTextureAtlas(const sp<GraphicBuffer>& buffer, int64_t* map, size_t size) { 484 SETUP_TASK(setTextureAtlas); 485 args->thread = &mRenderThread; 486 args->buffer = buffer.get(); 487 args->buffer->incStrong(nullptr); 488 args->map = map; 489 args->size = size; 490 post(task); 491} 492 493CREATE_BRIDGE2(setProcessStatsBuffer, RenderThread* thread, int fd) { 494 args->thread->jankTracker().switchStorageToAshmem(args->fd); 495 close(args->fd); 496 return nullptr; 497} 498 499void RenderProxy::setProcessStatsBuffer(int fd) { 500 SETUP_TASK(setProcessStatsBuffer); 501 args->thread = &mRenderThread; 502 args->fd = dup(fd); 503 post(task); 504} 505 506CREATE_BRIDGE3(addRenderNode, CanvasContext* context, RenderNode* node, bool placeFront) { 507 args->context->addRenderNode(args->node, args->placeFront); 508 return nullptr; 509} 510 511void RenderProxy::addRenderNode(RenderNode* node, bool placeFront) { 512 SETUP_TASK(addRenderNode); 513 args->context = mContext; 514 args->node = node; 515 args->placeFront = placeFront; 516 post(task); 517} 518 519CREATE_BRIDGE2(removeRenderNode, CanvasContext* context, RenderNode* node) { 520 args->context->removeRenderNode(args->node); 521 return nullptr; 522} 523 524void RenderProxy::removeRenderNode(RenderNode* node) { 525 SETUP_TASK(removeRenderNode); 526 args->context = mContext; 527 args->node = node; 528 post(task); 529} 530 531CREATE_BRIDGE2(drawRenderNode, CanvasContext* context, RenderNode* node) { 532 args->context->prepareAndDraw(args->node); 533 return nullptr; 534} 535 536void RenderProxy::drawRenderNode(RenderNode* node) { 537 SETUP_TASK(drawRenderNode); 538 args->context = mContext; 539 args->node = node; 540 // Be pseudo-thread-safe and don't use any member variables 541 staticPostAndWait(task); 542} 543 544CREATE_BRIDGE5(setContentDrawBounds, CanvasContext* context, int left, int top, 545 int right, int bottom) { 546 args->context->setContentDrawBounds(args->left, args->top, args->right, args->bottom); 547 return nullptr; 548} 549 550void RenderProxy::setContentDrawBounds(int left, int top, int right, int bottom) { 551 SETUP_TASK(setContentDrawBounds); 552 args->context = mContext; 553 args->left = left; 554 args->top = top; 555 args->right = right; 556 args->bottom = bottom; 557 staticPostAndWait(task); 558} 559 560CREATE_BRIDGE1(serializeDisplayListTree, CanvasContext* context) { 561 args->context->serializeDisplayListTree(); 562 return nullptr; 563} 564 565void RenderProxy::serializeDisplayListTree() { 566 SETUP_TASK(serializeDisplayListTree); 567 args->context = mContext; 568 post(task); 569} 570 571CREATE_BRIDGE2(addFrameStatsObserver, CanvasContext* context, 572 FrameStatsObserver* frameStatsObserver) { 573 args->context->addFrameStatsObserver(args->frameStatsObserver); 574 if (args->frameStatsObserver != nullptr) { 575 args->frameStatsObserver->decStrong(args->context); 576 } 577 return nullptr; 578} 579 580void RenderProxy::addFrameStatsObserver(FrameStatsObserver* observer) { 581 SETUP_TASK(addFrameStatsObserver); 582 args->context = mContext; 583 args->frameStatsObserver = observer; 584 if (observer != nullptr) { 585 observer->incStrong(mContext); 586 } 587 post(task); 588} 589 590CREATE_BRIDGE2(removeFrameStatsObserver, CanvasContext* context, 591 FrameStatsObserver* frameStatsObserver) { 592 args->context->removeFrameStatsObserver(args->frameStatsObserver); 593 if (args->frameStatsObserver != nullptr) { 594 args->frameStatsObserver->decStrong(args->context); 595 } 596 return nullptr; 597} 598 599void RenderProxy::removeFrameStatsObserver(FrameStatsObserver* observer) { 600 SETUP_TASK(removeFrameStatsObserver); 601 args->context = mContext; 602 args->frameStatsObserver = observer; 603 if (observer != nullptr) { 604 observer->incStrong(mContext); 605 } 606 post(task); 607} 608 609CREATE_BRIDGE1(getDroppedFrameReportCount, CanvasContext* context) { 610 return (void*) args->context->getDroppedFrameReportCount(); 611} 612 613long RenderProxy::getDroppedFrameReportCount() { 614 SETUP_TASK(getDroppedFrameReportCount); 615 args->context = mContext; 616 return (long) postAndWait(task); 617} 618 619void RenderProxy::post(RenderTask* task) { 620 mRenderThread.queue(task); 621} 622 623void* RenderProxy::postAndWait(MethodInvokeRenderTask* task) { 624 void* retval; 625 task->setReturnPtr(&retval); 626 SignalingRenderTask syncTask(task, &mSyncMutex, &mSyncCondition); 627 AutoMutex _lock(mSyncMutex); 628 mRenderThread.queue(&syncTask); 629 mSyncCondition.wait(mSyncMutex); 630 return retval; 631} 632 633void* RenderProxy::staticPostAndWait(MethodInvokeRenderTask* task) { 634 RenderThread& thread = RenderThread::getInstance(); 635 void* retval; 636 task->setReturnPtr(&retval); 637 thread.queueAndWait(task); 638 return retval; 639} 640 641} /* namespace renderthread */ 642} /* namespace uirenderer */ 643} /* namespace android */ 644