RenderProxy.cpp revision eab3f2658aa41d37c3b05d49a2ce4e3f4ed85399
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 JankStats = 1 << 2, 60 }; 61}; 62 63CREATE_BRIDGE4(createContext, RenderThread* thread, bool translucent, 64 RenderNode* rootRenderNode, IContextFactory* contextFactory) { 65 return new CanvasContext(*args->thread, args->translucent, 66 args->rootRenderNode, args->contextFactory); 67} 68 69RenderProxy::RenderProxy(bool translucent, RenderNode* rootRenderNode, IContextFactory* contextFactory) 70 : mRenderThread(RenderThread::getInstance()) 71 , mContext(nullptr) { 72 SETUP_TASK(createContext); 73 args->translucent = translucent; 74 args->rootRenderNode = rootRenderNode; 75 args->thread = &mRenderThread; 76 args->contextFactory = contextFactory; 77 mContext = (CanvasContext*) postAndWait(task); 78 mDrawFrameTask.setContext(&mRenderThread, mContext, rootRenderNode); 79} 80 81RenderProxy::~RenderProxy() { 82 destroyContext(); 83} 84 85CREATE_BRIDGE1(destroyContext, CanvasContext* context) { 86 delete args->context; 87 return nullptr; 88} 89 90void RenderProxy::destroyContext() { 91 if (mContext) { 92 SETUP_TASK(destroyContext); 93 args->context = mContext; 94 mContext = nullptr; 95 mDrawFrameTask.setContext(nullptr, nullptr, nullptr); 96 // This is also a fence as we need to be certain that there are no 97 // outstanding mDrawFrame tasks posted before it is destroyed 98 postAndWait(task); 99 } 100} 101 102CREATE_BRIDGE2(setSwapBehavior, CanvasContext* context, SwapBehavior swapBehavior) { 103 args->context->setSwapBehavior(args->swapBehavior); 104 return nullptr; 105} 106 107void RenderProxy::setSwapBehavior(SwapBehavior swapBehavior) { 108 SETUP_TASK(setSwapBehavior); 109 args->context = mContext; 110 args->swapBehavior = swapBehavior; 111 post(task); 112} 113 114CREATE_BRIDGE1(loadSystemProperties, CanvasContext* context) { 115 bool needsRedraw = false; 116 if (Caches::hasInstance()) { 117 needsRedraw = Properties::load(); 118 } 119 if (args->context->profiler().consumeProperties()) { 120 needsRedraw = true; 121 } 122 return (void*) needsRedraw; 123} 124 125bool RenderProxy::loadSystemProperties() { 126 SETUP_TASK(loadSystemProperties); 127 args->context = mContext; 128 return (bool) postAndWait(task); 129} 130 131CREATE_BRIDGE2(setName, CanvasContext* context, const char* name) { 132 args->context->setName(std::string(args->name)); 133 return nullptr; 134} 135 136void RenderProxy::setName(const char* name) { 137 SETUP_TASK(setName); 138 args->context = mContext; 139 args->name = name; 140 postAndWait(task); // block since name/value pointers owned by caller 141} 142 143CREATE_BRIDGE2(initialize, CanvasContext* context, Surface* surface) { 144 args->context->initialize(args->surface); 145 return nullptr; 146} 147 148void RenderProxy::initialize(const sp<Surface>& surface) { 149 SETUP_TASK(initialize); 150 args->context = mContext; 151 args->surface = surface.get(); 152 post(task); 153} 154 155CREATE_BRIDGE2(updateSurface, CanvasContext* context, Surface* surface) { 156 args->context->updateSurface(args->surface); 157 return nullptr; 158} 159 160void RenderProxy::updateSurface(const sp<Surface>& surface) { 161 SETUP_TASK(updateSurface); 162 args->context = mContext; 163 args->surface = surface.get(); 164 postAndWait(task); 165} 166 167CREATE_BRIDGE2(pauseSurface, CanvasContext* context, Surface* surface) { 168 return (void*) args->context->pauseSurface(args->surface); 169} 170 171bool RenderProxy::pauseSurface(const sp<Surface>& surface) { 172 SETUP_TASK(pauseSurface); 173 args->context = mContext; 174 args->surface = surface.get(); 175 return (bool) postAndWait(task); 176} 177 178CREATE_BRIDGE6(setup, CanvasContext* context, int width, int height, 179 float lightRadius, uint8_t ambientShadowAlpha, uint8_t spotShadowAlpha) { 180 args->context->setup(args->width, args->height, args->lightRadius, 181 args->ambientShadowAlpha, args->spotShadowAlpha); 182 return nullptr; 183} 184 185void RenderProxy::setup(int width, int height, float lightRadius, 186 uint8_t ambientShadowAlpha, uint8_t spotShadowAlpha) { 187 SETUP_TASK(setup); 188 args->context = mContext; 189 args->width = width; 190 args->height = height; 191 args->lightRadius = lightRadius; 192 args->ambientShadowAlpha = ambientShadowAlpha; 193 args->spotShadowAlpha = spotShadowAlpha; 194 post(task); 195} 196 197CREATE_BRIDGE2(setLightCenter, CanvasContext* context, Vector3 lightCenter) { 198 args->context->setLightCenter(args->lightCenter); 199 return nullptr; 200} 201 202void RenderProxy::setLightCenter(const Vector3& lightCenter) { 203 SETUP_TASK(setLightCenter); 204 args->context = mContext; 205 args->lightCenter = lightCenter; 206 post(task); 207} 208 209CREATE_BRIDGE2(setOpaque, CanvasContext* context, bool opaque) { 210 args->context->setOpaque(args->opaque); 211 return nullptr; 212} 213 214void RenderProxy::setOpaque(bool opaque) { 215 SETUP_TASK(setOpaque); 216 args->context = mContext; 217 args->opaque = opaque; 218 post(task); 219} 220 221int64_t* RenderProxy::frameInfo() { 222 return mDrawFrameTask.frameInfo(); 223} 224 225int RenderProxy::syncAndDrawFrame() { 226 return mDrawFrameTask.drawFrame(); 227} 228 229CREATE_BRIDGE1(destroy, CanvasContext* context) { 230 args->context->destroy(); 231 return nullptr; 232} 233 234void RenderProxy::destroy() { 235 SETUP_TASK(destroy); 236 args->context = mContext; 237 // destroyCanvasAndSurface() needs a fence as when it returns the 238 // underlying BufferQueue is going to be released from under 239 // the render thread. 240 postAndWait(task); 241} 242 243CREATE_BRIDGE2(invokeFunctor, RenderThread* thread, Functor* functor) { 244 CanvasContext::invokeFunctor(*args->thread, args->functor); 245 return nullptr; 246} 247 248void RenderProxy::invokeFunctor(Functor* functor, bool waitForCompletion) { 249 ATRACE_CALL(); 250 RenderThread& thread = RenderThread::getInstance(); 251 SETUP_TASK(invokeFunctor); 252 args->thread = &thread; 253 args->functor = functor; 254 if (waitForCompletion) { 255 // waitForCompletion = true is expected to be fairly rare and only 256 // happen in destruction. Thus it should be fine to temporarily 257 // create a Mutex 258 staticPostAndWait(task); 259 } else { 260 thread.queue(task); 261 } 262} 263 264CREATE_BRIDGE2(runWithGlContext, CanvasContext* context, RenderTask* task) { 265 args->context->runWithGlContext(args->task); 266 return nullptr; 267} 268 269void RenderProxy::runWithGlContext(RenderTask* gltask) { 270 SETUP_TASK(runWithGlContext); 271 args->context = mContext; 272 args->task = gltask; 273 postAndWait(task); 274} 275 276CREATE_BRIDGE1(createTextureLayer, CanvasContext* context) { 277 Layer* layer = args->context->createTextureLayer(); 278 if (!layer) return nullptr; 279 return new DeferredLayerUpdater(layer); 280} 281 282DeferredLayerUpdater* RenderProxy::createTextureLayer() { 283 SETUP_TASK(createTextureLayer); 284 args->context = mContext; 285 void* retval = postAndWait(task); 286 DeferredLayerUpdater* layer = reinterpret_cast<DeferredLayerUpdater*>(retval); 287 return layer; 288} 289 290CREATE_BRIDGE2(buildLayer, CanvasContext* context, RenderNode* node) { 291 args->context->buildLayer(args->node); 292 return nullptr; 293} 294 295void RenderProxy::buildLayer(RenderNode* node) { 296 SETUP_TASK(buildLayer); 297 args->context = mContext; 298 args->node = node; 299 postAndWait(task); 300} 301 302CREATE_BRIDGE3(copyLayerInto, CanvasContext* context, DeferredLayerUpdater* layer, 303 SkBitmap* bitmap) { 304 bool success = args->context->copyLayerInto(args->layer, args->bitmap); 305 return (void*) success; 306} 307 308bool RenderProxy::copyLayerInto(DeferredLayerUpdater* layer, SkBitmap& bitmap) { 309 SETUP_TASK(copyLayerInto); 310 args->context = mContext; 311 args->layer = layer; 312 args->bitmap = &bitmap; 313 return (bool) postAndWait(task); 314} 315 316void RenderProxy::pushLayerUpdate(DeferredLayerUpdater* layer) { 317 mDrawFrameTask.pushLayerUpdate(layer); 318} 319 320void RenderProxy::cancelLayerUpdate(DeferredLayerUpdater* layer) { 321 mDrawFrameTask.removeLayerUpdate(layer); 322} 323 324CREATE_BRIDGE1(detachSurfaceTexture, DeferredLayerUpdater* layer) { 325 args->layer->detachSurfaceTexture(); 326 return nullptr; 327} 328 329void RenderProxy::detachSurfaceTexture(DeferredLayerUpdater* layer) { 330 SETUP_TASK(detachSurfaceTexture); 331 args->layer = layer; 332 postAndWait(task); 333} 334 335CREATE_BRIDGE1(destroyHardwareResources, CanvasContext* context) { 336 args->context->destroyHardwareResources(); 337 return nullptr; 338} 339 340void RenderProxy::destroyHardwareResources() { 341 SETUP_TASK(destroyHardwareResources); 342 args->context = mContext; 343 post(task); 344} 345 346CREATE_BRIDGE2(trimMemory, RenderThread* thread, int level) { 347 CanvasContext::trimMemory(*args->thread, args->level); 348 return nullptr; 349} 350 351void RenderProxy::trimMemory(int level) { 352 // Avoid creating a RenderThread to do a trimMemory. 353 if (RenderThread::hasInstance()) { 354 RenderThread& thread = RenderThread::getInstance(); 355 SETUP_TASK(trimMemory); 356 args->thread = &thread; 357 args->level = level; 358 thread.queue(task); 359 } 360} 361 362CREATE_BRIDGE2(overrideProperty, const char* name, const char* value) { 363 Properties::overrideProperty(args->name, args->value); 364 return nullptr; 365} 366 367void RenderProxy::overrideProperty(const char* name, const char* value) { 368 SETUP_TASK(overrideProperty); 369 args->name = name; 370 args->value = value; 371 staticPostAndWait(task); // expensive, but block here since name/value pointers owned by caller 372} 373 374CREATE_BRIDGE0(fence) { 375 // Intentionally empty 376 return nullptr; 377} 378 379template <typename T> 380void UNUSED(T t) {} 381 382void RenderProxy::fence() { 383 SETUP_TASK(fence); 384 UNUSED(args); 385 postAndWait(task); 386} 387 388void RenderProxy::staticFence() { 389 SETUP_TASK(fence); 390 UNUSED(args); 391 staticPostAndWait(task); 392} 393 394CREATE_BRIDGE1(stopDrawing, CanvasContext* context) { 395 args->context->stopDrawing(); 396 return nullptr; 397} 398 399void RenderProxy::stopDrawing() { 400 SETUP_TASK(stopDrawing); 401 args->context = mContext; 402 postAndWait(task); 403} 404 405CREATE_BRIDGE1(notifyFramePending, CanvasContext* context) { 406 args->context->notifyFramePending(); 407 return nullptr; 408} 409 410void RenderProxy::notifyFramePending() { 411 SETUP_TASK(notifyFramePending); 412 args->context = mContext; 413 mRenderThread.queueAtFront(task); 414} 415 416CREATE_BRIDGE4(dumpProfileInfo, CanvasContext* context, RenderThread* thread, 417 int fd, int dumpFlags) { 418 args->context->profiler().dumpData(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(addFrameMetricsObserver, CanvasContext* context, 572 FrameMetricsObserver* frameStatsObserver) { 573 args->context->addFrameMetricsObserver(args->frameStatsObserver); 574 if (args->frameStatsObserver != nullptr) { 575 args->frameStatsObserver->decStrong(args->context); 576 } 577 return nullptr; 578} 579 580void RenderProxy::addFrameMetricsObserver(FrameMetricsObserver* observer) { 581 SETUP_TASK(addFrameMetricsObserver); 582 args->context = mContext; 583 args->frameStatsObserver = observer; 584 if (observer != nullptr) { 585 observer->incStrong(mContext); 586 } 587 post(task); 588} 589 590CREATE_BRIDGE2(removeFrameMetricsObserver, CanvasContext* context, 591 FrameMetricsObserver* frameStatsObserver) { 592 args->context->removeFrameMetricsObserver(args->frameStatsObserver); 593 if (args->frameStatsObserver != nullptr) { 594 args->frameStatsObserver->decStrong(args->context); 595 } 596 return nullptr; 597} 598 599void RenderProxy::removeFrameMetricsObserver(FrameMetricsObserver* observer) { 600 SETUP_TASK(removeFrameMetricsObserver); 601 args->context = mContext; 602 args->frameStatsObserver = observer; 603 if (observer != nullptr) { 604 observer->incStrong(mContext); 605 } 606 post(task); 607} 608 609void RenderProxy::post(RenderTask* task) { 610 mRenderThread.queue(task); 611} 612 613void* RenderProxy::postAndWait(MethodInvokeRenderTask* task) { 614 void* retval; 615 task->setReturnPtr(&retval); 616 SignalingRenderTask syncTask(task, &mSyncMutex, &mSyncCondition); 617 AutoMutex _lock(mSyncMutex); 618 mRenderThread.queue(&syncTask); 619 mSyncCondition.wait(mSyncMutex); 620 return retval; 621} 622 623void* RenderProxy::staticPostAndWait(MethodInvokeRenderTask* task) { 624 RenderThread& thread = RenderThread::getInstance(); 625 void* retval; 626 task->setReturnPtr(&retval); 627 thread.queueAndWait(task); 628 return retval; 629} 630 631} /* namespace renderthread */ 632} /* namespace uirenderer */ 633} /* namespace android */ 634