RenderProxy.cpp revision 7f2e5e3cea6af1f1dff35842aa13d46c47315b91
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 55enum class DumpFlags { 56 kFrameStats = 1 << 0, 57 kReset = 1 << 1, 58}; 59MAKE_FLAGS_ENUM(DumpFlags) 60 61CREATE_BRIDGE4(createContext, RenderThread* thread, bool translucent, 62 RenderNode* rootRenderNode, IContextFactory* contextFactory) { 63 return new CanvasContext(*args->thread, args->translucent, 64 args->rootRenderNode, args->contextFactory); 65} 66 67RenderProxy::RenderProxy(bool translucent, RenderNode* rootRenderNode, IContextFactory* contextFactory) 68 : mRenderThread(RenderThread::getInstance()) 69 , mContext(nullptr) { 70 SETUP_TASK(createContext); 71 args->translucent = translucent; 72 args->rootRenderNode = rootRenderNode; 73 args->thread = &mRenderThread; 74 args->contextFactory = contextFactory; 75 mContext = (CanvasContext*) postAndWait(task); 76 mDrawFrameTask.setContext(&mRenderThread, mContext); 77} 78 79RenderProxy::~RenderProxy() { 80 destroyContext(); 81} 82 83CREATE_BRIDGE1(destroyContext, CanvasContext* context) { 84 delete args->context; 85 return nullptr; 86} 87 88void RenderProxy::destroyContext() { 89 if (mContext) { 90 SETUP_TASK(destroyContext); 91 args->context = mContext; 92 mContext = nullptr; 93 mDrawFrameTask.setContext(nullptr, nullptr); 94 // This is also a fence as we need to be certain that there are no 95 // outstanding mDrawFrame tasks posted before it is destroyed 96 postAndWait(task); 97 } 98} 99 100CREATE_BRIDGE2(setSwapBehavior, CanvasContext* context, SwapBehavior swapBehavior) { 101 args->context->setSwapBehavior(args->swapBehavior); 102 return nullptr; 103} 104 105void RenderProxy::setSwapBehavior(SwapBehavior swapBehavior) { 106 SETUP_TASK(setSwapBehavior); 107 args->context = mContext; 108 args->swapBehavior = swapBehavior; 109 post(task); 110} 111 112CREATE_BRIDGE1(loadSystemProperties, CanvasContext* context) { 113 bool needsRedraw = false; 114 if (Caches::hasInstance()) { 115 needsRedraw = Caches::getInstance().initProperties(); 116 } 117 if (args->context->profiler().loadSystemProperties()) { 118 needsRedraw = true; 119 } 120 return (void*) needsRedraw; 121} 122 123bool RenderProxy::loadSystemProperties() { 124 SETUP_TASK(loadSystemProperties); 125 args->context = mContext; 126 return (bool) postAndWait(task); 127} 128 129CREATE_BRIDGE2(setName, CanvasContext* context, const char* name) { 130 args->context->setName(std::string(args->name)); 131 return nullptr; 132} 133 134void RenderProxy::setName(const char* name) { 135 SETUP_TASK(setName); 136 args->context = mContext; 137 args->name = name; 138 postAndWait(task); 139} 140 141CREATE_BRIDGE2(initialize, CanvasContext* context, ANativeWindow* window) { 142 return (void*) args->context->initialize(args->window); 143} 144 145bool RenderProxy::initialize(const sp<ANativeWindow>& window) { 146 SETUP_TASK(initialize); 147 args->context = mContext; 148 args->window = window.get(); 149 return (bool) postAndWait(task); 150} 151 152CREATE_BRIDGE2(updateSurface, CanvasContext* context, ANativeWindow* window) { 153 args->context->updateSurface(args->window); 154 return nullptr; 155} 156 157void RenderProxy::updateSurface(const sp<ANativeWindow>& window) { 158 SETUP_TASK(updateSurface); 159 args->context = mContext; 160 args->window = window.get(); 161 postAndWait(task); 162} 163 164CREATE_BRIDGE2(pauseSurface, CanvasContext* context, ANativeWindow* window) { 165 return (void*) args->context->pauseSurface(args->window); 166} 167 168bool RenderProxy::pauseSurface(const sp<ANativeWindow>& window) { 169 SETUP_TASK(pauseSurface); 170 args->context = mContext; 171 args->window = window.get(); 172 return (bool) postAndWait(task); 173} 174 175CREATE_BRIDGE7(setup, CanvasContext* context, int width, int height, 176 Vector3 lightCenter, float lightRadius, 177 uint8_t ambientShadowAlpha, uint8_t spotShadowAlpha) { 178 args->context->setup(args->width, args->height, args->lightCenter, args->lightRadius, 179 args->ambientShadowAlpha, args->spotShadowAlpha); 180 return nullptr; 181} 182 183void RenderProxy::setup(int width, int height, const Vector3& lightCenter, 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->lightCenter = lightCenter; 190 args->lightRadius = lightRadius; 191 args->ambientShadowAlpha = ambientShadowAlpha; 192 args->spotShadowAlpha = spotShadowAlpha; 193 post(task); 194} 195 196CREATE_BRIDGE2(setOpaque, CanvasContext* context, bool opaque) { 197 args->context->setOpaque(args->opaque); 198 return nullptr; 199} 200 201void RenderProxy::setOpaque(bool opaque) { 202 SETUP_TASK(setOpaque); 203 args->context = mContext; 204 args->opaque = opaque; 205 post(task); 206} 207 208int64_t* RenderProxy::frameInfo() { 209 return mDrawFrameTask.frameInfo(); 210} 211 212int RenderProxy::syncAndDrawFrame() { 213 return mDrawFrameTask.drawFrame(); 214} 215 216CREATE_BRIDGE1(destroy, CanvasContext* context) { 217 args->context->destroy(); 218 return nullptr; 219} 220 221void RenderProxy::destroy() { 222 SETUP_TASK(destroy); 223 args->context = mContext; 224 // destroyCanvasAndSurface() needs a fence as when it returns the 225 // underlying BufferQueue is going to be released from under 226 // the render thread. 227 postAndWait(task); 228} 229 230CREATE_BRIDGE2(invokeFunctor, RenderThread* thread, Functor* functor) { 231 CanvasContext::invokeFunctor(*args->thread, args->functor); 232 return nullptr; 233} 234 235void RenderProxy::invokeFunctor(Functor* functor, bool waitForCompletion) { 236 ATRACE_CALL(); 237 RenderThread& thread = RenderThread::getInstance(); 238 SETUP_TASK(invokeFunctor); 239 args->thread = &thread; 240 args->functor = functor; 241 if (waitForCompletion) { 242 // waitForCompletion = true is expected to be fairly rare and only 243 // happen in destruction. Thus it should be fine to temporarily 244 // create a Mutex 245 staticPostAndWait(task); 246 } else { 247 thread.queue(task); 248 } 249} 250 251CREATE_BRIDGE2(runWithGlContext, CanvasContext* context, RenderTask* task) { 252 args->context->runWithGlContext(args->task); 253 return nullptr; 254} 255 256void RenderProxy::runWithGlContext(RenderTask* gltask) { 257 SETUP_TASK(runWithGlContext); 258 args->context = mContext; 259 args->task = gltask; 260 postAndWait(task); 261} 262 263CREATE_BRIDGE2(createTextureLayer, RenderThread* thread, CanvasContext* context) { 264 Layer* layer = args->context->createTextureLayer(); 265 if (!layer) return nullptr; 266 return new DeferredLayerUpdater(*args->thread, layer); 267} 268 269DeferredLayerUpdater* RenderProxy::createTextureLayer() { 270 SETUP_TASK(createTextureLayer); 271 args->context = mContext; 272 args->thread = &mRenderThread; 273 void* retval = postAndWait(task); 274 DeferredLayerUpdater* layer = reinterpret_cast<DeferredLayerUpdater*>(retval); 275 return layer; 276} 277 278CREATE_BRIDGE2(buildLayer, CanvasContext* context, RenderNode* node) { 279 args->context->buildLayer(args->node); 280 return nullptr; 281} 282 283void RenderProxy::buildLayer(RenderNode* node) { 284 SETUP_TASK(buildLayer); 285 args->context = mContext; 286 args->node = node; 287 postAndWait(task); 288} 289 290CREATE_BRIDGE3(copyLayerInto, CanvasContext* context, DeferredLayerUpdater* layer, 291 SkBitmap* bitmap) { 292 bool success = args->context->copyLayerInto(args->layer, args->bitmap); 293 return (void*) success; 294} 295 296bool RenderProxy::copyLayerInto(DeferredLayerUpdater* layer, SkBitmap& bitmap) { 297 SETUP_TASK(copyLayerInto); 298 args->context = mContext; 299 args->layer = layer; 300 args->bitmap = &bitmap; 301 return (bool) postAndWait(task); 302} 303 304void RenderProxy::pushLayerUpdate(DeferredLayerUpdater* layer) { 305 mDrawFrameTask.pushLayerUpdate(layer); 306} 307 308void RenderProxy::cancelLayerUpdate(DeferredLayerUpdater* layer) { 309 mDrawFrameTask.removeLayerUpdate(layer); 310} 311 312CREATE_BRIDGE1(detachSurfaceTexture, DeferredLayerUpdater* layer) { 313 args->layer->detachSurfaceTexture(); 314 return nullptr; 315} 316 317void RenderProxy::detachSurfaceTexture(DeferredLayerUpdater* layer) { 318 SETUP_TASK(detachSurfaceTexture); 319 args->layer = layer; 320 postAndWait(task); 321} 322 323CREATE_BRIDGE1(destroyHardwareResources, CanvasContext* context) { 324 args->context->destroyHardwareResources(); 325 return nullptr; 326} 327 328void RenderProxy::destroyHardwareResources() { 329 SETUP_TASK(destroyHardwareResources); 330 args->context = mContext; 331 post(task); 332} 333 334CREATE_BRIDGE2(timMemory, RenderThread* thread, int level) { 335 CanvasContext::trimMemory(*args->thread, args->level); 336 return nullptr; 337} 338 339void RenderProxy::trimMemory(int level) { 340 // Avoid creating a RenderThread to do a trimMemory. 341 if (RenderThread::hasInstance()) { 342 RenderThread& thread = RenderThread::getInstance(); 343 SETUP_TASK(timMemory); 344 args->thread = &thread; 345 args->level = level; 346 thread.queue(task); 347 } 348} 349 350CREATE_BRIDGE0(fence) { 351 // Intentionally empty 352 return nullptr; 353} 354 355template <typename T> 356void UNUSED(T t) {} 357 358void RenderProxy::fence() { 359 SETUP_TASK(fence); 360 UNUSED(args); 361 postAndWait(task); 362} 363 364CREATE_BRIDGE1(stopDrawing, CanvasContext* context) { 365 args->context->stopDrawing(); 366 return nullptr; 367} 368 369void RenderProxy::stopDrawing() { 370 SETUP_TASK(stopDrawing); 371 args->context = mContext; 372 postAndWait(task); 373} 374 375CREATE_BRIDGE1(notifyFramePending, CanvasContext* context) { 376 args->context->notifyFramePending(); 377 return nullptr; 378} 379 380void RenderProxy::notifyFramePending() { 381 SETUP_TASK(notifyFramePending); 382 args->context = mContext; 383 mRenderThread.queueAtFront(task); 384} 385 386CREATE_BRIDGE4(dumpProfileInfo, CanvasContext* context, RenderThread* thread, 387 int fd, int dumpFlags) { 388 args->context->profiler().dumpData(args->fd); 389 args->thread->jankTracker().dump(args->fd); 390 if (args->dumpFlags & DumpFlags::kFrameStats) { 391 args->context->dumpFrames(args->fd); 392 } 393 if (args->dumpFlags & DumpFlags::kReset) { 394 args->context->resetFrameStats(); 395 } 396 return nullptr; 397} 398 399void RenderProxy::dumpProfileInfo(int fd, int dumpFlags) { 400 SETUP_TASK(dumpProfileInfo); 401 args->context = mContext; 402 args->thread = &mRenderThread; 403 args->fd = fd; 404 args->dumpFlags = dumpFlags; 405 postAndWait(task); 406} 407 408CREATE_BRIDGE1(resetProfileInfo, CanvasContext* context) { 409 args->context->resetFrameStats(); 410 return nullptr; 411} 412 413void RenderProxy::resetProfileInfo() { 414 SETUP_TASK(resetProfileInfo); 415 args->context = mContext; 416 postAndWait(task); 417} 418 419CREATE_BRIDGE2(dumpGraphicsMemory, int fd, RenderThread* thread) { 420 args->thread->jankTracker().dump(args->fd); 421 422 FILE *file = fdopen(args->fd, "a"); 423 if (Caches::hasInstance()) { 424 String8 cachesLog; 425 Caches::getInstance().dumpMemoryUsage(cachesLog); 426 fprintf(file, "\nCaches:\n%s\n", cachesLog.string()); 427 } else { 428 fprintf(file, "\nNo caches instance.\n"); 429 } 430 fflush(file); 431 return nullptr; 432} 433 434void RenderProxy::dumpGraphicsMemory(int fd) { 435 if (!RenderThread::hasInstance()) return; 436 SETUP_TASK(dumpGraphicsMemory); 437 args->fd = fd; 438 args->thread = &RenderThread::getInstance(); 439 staticPostAndWait(task); 440} 441 442CREATE_BRIDGE4(setTextureAtlas, RenderThread* thread, GraphicBuffer* buffer, int64_t* map, size_t size) { 443 CanvasContext::setTextureAtlas(*args->thread, args->buffer, args->map, args->size); 444 args->buffer->decStrong(nullptr); 445 return nullptr; 446} 447 448void RenderProxy::setTextureAtlas(const sp<GraphicBuffer>& buffer, int64_t* map, size_t size) { 449 SETUP_TASK(setTextureAtlas); 450 args->thread = &mRenderThread; 451 args->buffer = buffer.get(); 452 args->buffer->incStrong(nullptr); 453 args->map = map; 454 args->size = size; 455 post(task); 456} 457 458CREATE_BRIDGE2(setProcessStatsBuffer, RenderThread* thread, int fd) { 459 args->thread->jankTracker().switchStorageToAshmem(args->fd); 460 close(args->fd); 461 return nullptr; 462} 463 464void RenderProxy::setProcessStatsBuffer(int fd) { 465 SETUP_TASK(setProcessStatsBuffer); 466 args->thread = &mRenderThread; 467 args->fd = dup(fd); 468 post(task); 469} 470 471void RenderProxy::post(RenderTask* task) { 472 mRenderThread.queue(task); 473} 474 475void* RenderProxy::postAndWait(MethodInvokeRenderTask* task) { 476 void* retval; 477 task->setReturnPtr(&retval); 478 SignalingRenderTask syncTask(task, &mSyncMutex, &mSyncCondition); 479 AutoMutex _lock(mSyncMutex); 480 mRenderThread.queue(&syncTask); 481 mSyncCondition.wait(mSyncMutex); 482 return retval; 483} 484 485void* RenderProxy::staticPostAndWait(MethodInvokeRenderTask* task) { 486 RenderThread& thread = RenderThread::getInstance(); 487 void* retval; 488 task->setReturnPtr(&retval); 489 Mutex mutex; 490 Condition condition; 491 SignalingRenderTask syncTask(task, &mutex, &condition); 492 AutoMutex _lock(mutex); 493 thread.queue(&syncTask); 494 condition.wait(mutex); 495 return retval; 496} 497 498} /* namespace renderthread */ 499} /* namespace uirenderer */ 500} /* namespace android */ 501