RenderProxy.cpp revision 51f2d606dcbfba3cc5b03dfea37c1304b91c232f
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(TreeObserver* observer) { 226 return mDrawFrameTask.drawFrame(observer); 227} 228 229CREATE_BRIDGE2(destroy, CanvasContext* context, TreeObserver* observer) { 230 args->context->destroy(args->observer); 231 return nullptr; 232} 233 234void RenderProxy::destroy(TreeObserver* observer) { 235 SETUP_TASK(destroy); 236 args->context = mContext; 237 args->observer = observer; 238 // destroyCanvasAndSurface() needs a fence as when it returns the 239 // underlying BufferQueue is going to be released from under 240 // the render thread. 241 postAndWait(task); 242} 243 244CREATE_BRIDGE2(invokeFunctor, RenderThread* thread, Functor* functor) { 245 CanvasContext::invokeFunctor(*args->thread, args->functor); 246 return nullptr; 247} 248 249void RenderProxy::invokeFunctor(Functor* functor, bool waitForCompletion) { 250 ATRACE_CALL(); 251 RenderThread& thread = RenderThread::getInstance(); 252 SETUP_TASK(invokeFunctor); 253 args->thread = &thread; 254 args->functor = functor; 255 if (waitForCompletion) { 256 // waitForCompletion = true is expected to be fairly rare and only 257 // happen in destruction. Thus it should be fine to temporarily 258 // create a Mutex 259 staticPostAndWait(task); 260 } else { 261 thread.queue(task); 262 } 263} 264 265CREATE_BRIDGE2(runWithGlContext, CanvasContext* context, RenderTask* task) { 266 args->context->runWithGlContext(args->task); 267 return nullptr; 268} 269 270void RenderProxy::runWithGlContext(RenderTask* gltask) { 271 SETUP_TASK(runWithGlContext); 272 args->context = mContext; 273 args->task = gltask; 274 postAndWait(task); 275} 276 277CREATE_BRIDGE1(createTextureLayer, CanvasContext* context) { 278 Layer* layer = args->context->createTextureLayer(); 279 if (!layer) return nullptr; 280 return new DeferredLayerUpdater(layer); 281} 282 283DeferredLayerUpdater* RenderProxy::createTextureLayer() { 284 SETUP_TASK(createTextureLayer); 285 args->context = mContext; 286 void* retval = postAndWait(task); 287 DeferredLayerUpdater* layer = reinterpret_cast<DeferredLayerUpdater*>(retval); 288 return layer; 289} 290 291CREATE_BRIDGE3(buildLayer, CanvasContext* context, RenderNode* node, TreeObserver* observer) { 292 args->context->buildLayer(args->node, args->observer); 293 return nullptr; 294} 295 296void RenderProxy::buildLayer(RenderNode* node, TreeObserver* observer) { 297 SETUP_TASK(buildLayer); 298 args->context = mContext; 299 args->node = node; 300 args->observer = observer; 301 postAndWait(task); 302} 303 304CREATE_BRIDGE3(copyLayerInto, CanvasContext* context, DeferredLayerUpdater* layer, 305 SkBitmap* bitmap) { 306 bool success = args->context->copyLayerInto(args->layer, args->bitmap); 307 return (void*) success; 308} 309 310bool RenderProxy::copyLayerInto(DeferredLayerUpdater* layer, SkBitmap& bitmap) { 311 SETUP_TASK(copyLayerInto); 312 args->context = mContext; 313 args->layer = layer; 314 args->bitmap = &bitmap; 315 return (bool) postAndWait(task); 316} 317 318void RenderProxy::pushLayerUpdate(DeferredLayerUpdater* layer) { 319 mDrawFrameTask.pushLayerUpdate(layer); 320} 321 322void RenderProxy::cancelLayerUpdate(DeferredLayerUpdater* layer) { 323 mDrawFrameTask.removeLayerUpdate(layer); 324} 325 326CREATE_BRIDGE1(detachSurfaceTexture, DeferredLayerUpdater* layer) { 327 args->layer->detachSurfaceTexture(); 328 return nullptr; 329} 330 331void RenderProxy::detachSurfaceTexture(DeferredLayerUpdater* layer) { 332 SETUP_TASK(detachSurfaceTexture); 333 args->layer = layer; 334 postAndWait(task); 335} 336 337CREATE_BRIDGE2(destroyHardwareResources, CanvasContext* context, TreeObserver* observer) { 338 args->context->destroyHardwareResources(args->observer); 339 return nullptr; 340} 341 342void RenderProxy::destroyHardwareResources(TreeObserver* observer) { 343 SETUP_TASK(destroyHardwareResources); 344 args->context = mContext; 345 args->observer = observer; 346 postAndWait(task); 347} 348 349CREATE_BRIDGE2(trimMemory, RenderThread* thread, int level) { 350 CanvasContext::trimMemory(*args->thread, args->level); 351 return nullptr; 352} 353 354void RenderProxy::trimMemory(int level) { 355 // Avoid creating a RenderThread to do a trimMemory. 356 if (RenderThread::hasInstance()) { 357 RenderThread& thread = RenderThread::getInstance(); 358 SETUP_TASK(trimMemory); 359 args->thread = &thread; 360 args->level = level; 361 thread.queue(task); 362 } 363} 364 365CREATE_BRIDGE2(overrideProperty, const char* name, const char* value) { 366 Properties::overrideProperty(args->name, args->value); 367 return nullptr; 368} 369 370void RenderProxy::overrideProperty(const char* name, const char* value) { 371 SETUP_TASK(overrideProperty); 372 args->name = name; 373 args->value = value; 374 staticPostAndWait(task); // expensive, but block here since name/value pointers owned by caller 375} 376 377CREATE_BRIDGE0(fence) { 378 // Intentionally empty 379 return nullptr; 380} 381 382template <typename T> 383void UNUSED(T t) {} 384 385void RenderProxy::fence() { 386 SETUP_TASK(fence); 387 UNUSED(args); 388 postAndWait(task); 389} 390 391void RenderProxy::staticFence() { 392 SETUP_TASK(fence); 393 UNUSED(args); 394 staticPostAndWait(task); 395} 396 397CREATE_BRIDGE1(stopDrawing, CanvasContext* context) { 398 args->context->stopDrawing(); 399 return nullptr; 400} 401 402void RenderProxy::stopDrawing() { 403 SETUP_TASK(stopDrawing); 404 args->context = mContext; 405 postAndWait(task); 406} 407 408CREATE_BRIDGE1(notifyFramePending, CanvasContext* context) { 409 args->context->notifyFramePending(); 410 return nullptr; 411} 412 413void RenderProxy::notifyFramePending() { 414 SETUP_TASK(notifyFramePending); 415 args->context = mContext; 416 mRenderThread.queueAtFront(task); 417} 418 419CREATE_BRIDGE4(dumpProfileInfo, CanvasContext* context, RenderThread* thread, 420 int fd, int dumpFlags) { 421 args->context->profiler().dumpData(args->fd); 422 if (args->dumpFlags & DumpFlags::FrameStats) { 423 args->context->dumpFrames(args->fd); 424 } 425 if (args->dumpFlags & DumpFlags::Reset) { 426 args->context->resetFrameStats(); 427 } 428 return nullptr; 429} 430 431void RenderProxy::dumpProfileInfo(int fd, int dumpFlags) { 432 SETUP_TASK(dumpProfileInfo); 433 args->context = mContext; 434 args->thread = &mRenderThread; 435 args->fd = fd; 436 args->dumpFlags = dumpFlags; 437 postAndWait(task); 438} 439 440CREATE_BRIDGE1(resetProfileInfo, CanvasContext* context) { 441 args->context->resetFrameStats(); 442 return nullptr; 443} 444 445void RenderProxy::resetProfileInfo() { 446 SETUP_TASK(resetProfileInfo); 447 args->context = mContext; 448 postAndWait(task); 449} 450 451CREATE_BRIDGE2(dumpGraphicsMemory, int fd, RenderThread* thread) { 452 args->thread->jankTracker().dump(args->fd); 453 454 FILE *file = fdopen(args->fd, "a"); 455 if (Caches::hasInstance()) { 456 String8 cachesLog; 457 Caches::getInstance().dumpMemoryUsage(cachesLog); 458 fprintf(file, "\nCaches:\n%s\n", cachesLog.string()); 459 } else { 460 fprintf(file, "\nNo caches instance.\n"); 461 } 462#if HWUI_NEW_OPS 463 fprintf(file, "\nPipeline=FrameBuilder\n"); 464#else 465 fprintf(file, "\nPipeline=OpenGLRenderer\n"); 466#endif 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 509CREATE_BRIDGE3(addRenderNode, CanvasContext* context, RenderNode* node, bool placeFront) { 510 args->context->addRenderNode(args->node, args->placeFront); 511 return nullptr; 512} 513 514void RenderProxy::addRenderNode(RenderNode* node, bool placeFront) { 515 SETUP_TASK(addRenderNode); 516 args->context = mContext; 517 args->node = node; 518 args->placeFront = placeFront; 519 post(task); 520} 521 522CREATE_BRIDGE2(removeRenderNode, CanvasContext* context, RenderNode* node) { 523 args->context->removeRenderNode(args->node); 524 return nullptr; 525} 526 527void RenderProxy::removeRenderNode(RenderNode* node) { 528 SETUP_TASK(removeRenderNode); 529 args->context = mContext; 530 args->node = node; 531 post(task); 532} 533 534CREATE_BRIDGE2(drawRenderNode, CanvasContext* context, RenderNode* node) { 535 args->context->prepareAndDraw(args->node); 536 return nullptr; 537} 538 539void RenderProxy::drawRenderNode(RenderNode* node) { 540 SETUP_TASK(drawRenderNode); 541 args->context = mContext; 542 args->node = node; 543 // Be pseudo-thread-safe and don't use any member variables 544 staticPostAndWait(task); 545} 546 547CREATE_BRIDGE5(setContentDrawBounds, CanvasContext* context, int left, int top, 548 int right, int bottom) { 549 args->context->setContentDrawBounds(args->left, args->top, args->right, args->bottom); 550 return nullptr; 551} 552 553void RenderProxy::setContentDrawBounds(int left, int top, int right, int bottom) { 554 SETUP_TASK(setContentDrawBounds); 555 args->context = mContext; 556 args->left = left; 557 args->top = top; 558 args->right = right; 559 args->bottom = bottom; 560 staticPostAndWait(task); 561} 562 563CREATE_BRIDGE1(serializeDisplayListTree, CanvasContext* context) { 564 args->context->serializeDisplayListTree(); 565 return nullptr; 566} 567 568void RenderProxy::serializeDisplayListTree() { 569 SETUP_TASK(serializeDisplayListTree); 570 args->context = mContext; 571 post(task); 572} 573 574CREATE_BRIDGE2(addFrameMetricsObserver, CanvasContext* context, 575 FrameMetricsObserver* frameStatsObserver) { 576 args->context->addFrameMetricsObserver(args->frameStatsObserver); 577 if (args->frameStatsObserver != nullptr) { 578 args->frameStatsObserver->decStrong(args->context); 579 } 580 return nullptr; 581} 582 583void RenderProxy::addFrameMetricsObserver(FrameMetricsObserver* observer) { 584 SETUP_TASK(addFrameMetricsObserver); 585 args->context = mContext; 586 args->frameStatsObserver = observer; 587 if (observer != nullptr) { 588 observer->incStrong(mContext); 589 } 590 post(task); 591} 592 593CREATE_BRIDGE2(removeFrameMetricsObserver, CanvasContext* context, 594 FrameMetricsObserver* frameStatsObserver) { 595 args->context->removeFrameMetricsObserver(args->frameStatsObserver); 596 if (args->frameStatsObserver != nullptr) { 597 args->frameStatsObserver->decStrong(args->context); 598 } 599 return nullptr; 600} 601 602void RenderProxy::removeFrameMetricsObserver(FrameMetricsObserver* observer) { 603 SETUP_TASK(removeFrameMetricsObserver); 604 args->context = mContext; 605 args->frameStatsObserver = observer; 606 if (observer != nullptr) { 607 observer->incStrong(mContext); 608 } 609 post(task); 610} 611 612void RenderProxy::post(RenderTask* task) { 613 mRenderThread.queue(task); 614} 615 616void* RenderProxy::postAndWait(MethodInvokeRenderTask* task) { 617 void* retval; 618 task->setReturnPtr(&retval); 619 SignalingRenderTask syncTask(task, &mSyncMutex, &mSyncCondition); 620 AutoMutex _lock(mSyncMutex); 621 mRenderThread.queue(&syncTask); 622 mSyncCondition.wait(mSyncMutex); 623 return retval; 624} 625 626void* RenderProxy::staticPostAndWait(MethodInvokeRenderTask* task) { 627 RenderThread& thread = RenderThread::getInstance(); 628 void* retval; 629 task->setReturnPtr(&retval); 630 thread.queueAndWait(task); 631 return retval; 632} 633 634} /* namespace renderthread */ 635} /* namespace uirenderer */ 636} /* namespace android */ 637