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