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