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