RenderProxy.cpp revision 2ab8298dc37851aab4623ba3f98d71055d653a73
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 "CanvasContext.h" 20#include "RenderTask.h" 21#include "RenderThread.h" 22 23#include "../DeferredLayerUpdater.h" 24#include "../DisplayList.h" 25#include "../LayerRenderer.h" 26#include "../Rect.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(0) { 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); 71} 72 73RenderProxy::~RenderProxy() { 74 destroyContext(); 75} 76 77CREATE_BRIDGE1(destroyContext, CanvasContext* context) { 78 delete args->context; 79 return NULL; 80} 81 82void RenderProxy::destroyContext() { 83 if (mContext) { 84 SETUP_TASK(destroyContext); 85 args->context = mContext; 86 mContext = 0; 87 mDrawFrameTask.setContext(NULL, NULL); 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(setFrameInterval, RenderThread* thread, nsecs_t frameIntervalNanos) { 95 args->thread->timeLord().setFrameInterval(args->frameIntervalNanos); 96 return NULL; 97} 98 99void RenderProxy::setFrameInterval(nsecs_t frameIntervalNanos) { 100 SETUP_TASK(setFrameInterval); 101 args->thread = &mRenderThread; 102 args->frameIntervalNanos = frameIntervalNanos; 103 post(task); 104} 105 106CREATE_BRIDGE2(setSwapBehavior, CanvasContext* context, SwapBehavior swapBehavior) { 107 args->context->setSwapBehavior(args->swapBehavior); 108 return NULL; 109} 110 111void RenderProxy::setSwapBehavior(SwapBehavior swapBehavior) { 112 SETUP_TASK(setSwapBehavior); 113 args->context = mContext; 114 args->swapBehavior = swapBehavior; 115 post(task); 116} 117 118CREATE_BRIDGE1(loadSystemProperties, CanvasContext* context) { 119 bool needsRedraw = false; 120 if (Caches::hasInstance()) { 121 needsRedraw = Caches::getInstance().initProperties(); 122 } 123 if (args->context->profiler().loadSystemProperties()) { 124 needsRedraw = true; 125 } 126 return (void*) needsRedraw; 127} 128 129bool RenderProxy::loadSystemProperties() { 130 SETUP_TASK(loadSystemProperties); 131 args->context = mContext; 132 return (bool) postAndWait(task); 133} 134 135CREATE_BRIDGE2(initialize, CanvasContext* context, ANativeWindow* window) { 136 return (void*) args->context->initialize(args->window); 137} 138 139bool RenderProxy::initialize(const sp<ANativeWindow>& window) { 140 SETUP_TASK(initialize); 141 args->context = mContext; 142 args->window = window.get(); 143 return (bool) postAndWait(task); 144} 145 146CREATE_BRIDGE2(updateSurface, CanvasContext* context, ANativeWindow* window) { 147 args->context->updateSurface(args->window); 148 return NULL; 149} 150 151void RenderProxy::updateSurface(const sp<ANativeWindow>& window) { 152 SETUP_TASK(updateSurface); 153 args->context = mContext; 154 args->window = window.get(); 155 postAndWait(task); 156} 157 158CREATE_BRIDGE2(pauseSurface, CanvasContext* context, ANativeWindow* window) { 159 args->context->pauseSurface(args->window); 160 return NULL; 161} 162 163void RenderProxy::pauseSurface(const sp<ANativeWindow>& window) { 164 SETUP_TASK(pauseSurface); 165 args->context = mContext; 166 args->window = window.get(); 167 postAndWait(task); 168} 169 170CREATE_BRIDGE7(setup, CanvasContext* context, int width, int height, 171 Vector3 lightCenter, float lightRadius, 172 uint8_t ambientShadowAlpha, uint8_t spotShadowAlpha) { 173 args->context->setup(args->width, args->height, args->lightCenter, args->lightRadius, 174 args->ambientShadowAlpha, args->spotShadowAlpha); 175 return NULL; 176} 177 178void RenderProxy::setup(int width, int height, const Vector3& lightCenter, float lightRadius, 179 uint8_t ambientShadowAlpha, uint8_t spotShadowAlpha) { 180 SETUP_TASK(setup); 181 args->context = mContext; 182 args->width = width; 183 args->height = height; 184 args->lightCenter = lightCenter; 185 args->lightRadius = lightRadius; 186 args->ambientShadowAlpha = ambientShadowAlpha; 187 args->spotShadowAlpha = spotShadowAlpha; 188 post(task); 189} 190 191CREATE_BRIDGE2(setOpaque, CanvasContext* context, bool opaque) { 192 args->context->setOpaque(args->opaque); 193 return NULL; 194} 195 196void RenderProxy::setOpaque(bool opaque) { 197 SETUP_TASK(setOpaque); 198 args->context = mContext; 199 args->opaque = opaque; 200 post(task); 201} 202 203int RenderProxy::syncAndDrawFrame(nsecs_t frameTimeNanos, nsecs_t recordDurationNanos, 204 float density) { 205 mDrawFrameTask.setDensity(density); 206 return mDrawFrameTask.drawFrame(frameTimeNanos, recordDurationNanos); 207} 208 209CREATE_BRIDGE1(destroy, CanvasContext* context) { 210 args->context->destroy(); 211 return NULL; 212} 213 214void RenderProxy::destroy() { 215 SETUP_TASK(destroy); 216 args->context = mContext; 217 // destroyCanvasAndSurface() needs a fence as when it returns the 218 // underlying BufferQueue is going to be released from under 219 // the render thread. 220 postAndWait(task); 221} 222 223CREATE_BRIDGE2(invokeFunctor, RenderThread* thread, Functor* functor) { 224 CanvasContext::invokeFunctor(*args->thread, args->functor); 225 return NULL; 226} 227 228void RenderProxy::invokeFunctor(Functor* functor, bool waitForCompletion) { 229 ATRACE_CALL(); 230 RenderThread& thread = RenderThread::getInstance(); 231 SETUP_TASK(invokeFunctor); 232 args->thread = &thread; 233 args->functor = functor; 234 if (waitForCompletion) { 235 // waitForCompletion = true is expected to be fairly rare and only 236 // happen in destruction. Thus it should be fine to temporarily 237 // create a Mutex 238 staticPostAndWait(task); 239 } else { 240 thread.queue(task); 241 } 242} 243 244CREATE_BRIDGE2(runWithGlContext, CanvasContext* context, RenderTask* task) { 245 args->context->runWithGlContext(args->task); 246 return NULL; 247} 248 249void RenderProxy::runWithGlContext(RenderTask* gltask) { 250 SETUP_TASK(runWithGlContext); 251 args->context = mContext; 252 args->task = gltask; 253 postAndWait(task); 254} 255 256CREATE_BRIDGE2(createTextureLayer, RenderThread* thread, CanvasContext* context) { 257 Layer* layer = args->context->createTextureLayer(); 258 if (!layer) return 0; 259 return new DeferredLayerUpdater(*args->thread, layer); 260} 261 262DeferredLayerUpdater* RenderProxy::createTextureLayer() { 263 SETUP_TASK(createTextureLayer); 264 args->context = mContext; 265 args->thread = &mRenderThread; 266 void* retval = postAndWait(task); 267 DeferredLayerUpdater* layer = reinterpret_cast<DeferredLayerUpdater*>(retval); 268 return layer; 269} 270 271CREATE_BRIDGE2(buildLayer, CanvasContext* context, RenderNode* node) { 272 args->context->buildLayer(args->node); 273 return NULL; 274} 275 276void RenderProxy::buildLayer(RenderNode* node) { 277 SETUP_TASK(buildLayer); 278 args->context = mContext; 279 args->node = node; 280 postAndWait(task); 281} 282 283CREATE_BRIDGE3(copyLayerInto, CanvasContext* context, DeferredLayerUpdater* layer, 284 SkBitmap* bitmap) { 285 bool success = args->context->copyLayerInto(args->layer, args->bitmap); 286 return (void*) success; 287} 288 289bool RenderProxy::copyLayerInto(DeferredLayerUpdater* layer, SkBitmap* bitmap) { 290 SETUP_TASK(copyLayerInto); 291 args->context = mContext; 292 args->layer = layer; 293 args->bitmap = bitmap; 294 return (bool) postAndWait(task); 295} 296 297void RenderProxy::pushLayerUpdate(DeferredLayerUpdater* layer) { 298 mDrawFrameTask.pushLayerUpdate(layer); 299} 300 301void RenderProxy::cancelLayerUpdate(DeferredLayerUpdater* layer) { 302 mDrawFrameTask.removeLayerUpdate(layer); 303} 304 305CREATE_BRIDGE1(detachSurfaceTexture, DeferredLayerUpdater* layer) { 306 args->layer->detachSurfaceTexture(); 307 return NULL; 308} 309 310void RenderProxy::detachSurfaceTexture(DeferredLayerUpdater* layer) { 311 SETUP_TASK(detachSurfaceTexture); 312 args->layer = layer; 313 postAndWait(task); 314} 315 316CREATE_BRIDGE1(destroyHardwareResources, CanvasContext* context) { 317 args->context->destroyHardwareResources(); 318 return NULL; 319} 320 321void RenderProxy::destroyHardwareResources() { 322 SETUP_TASK(destroyHardwareResources); 323 args->context = mContext; 324 post(task); 325} 326 327CREATE_BRIDGE2(timMemory, RenderThread* thread, int level) { 328 CanvasContext::trimMemory(*args->thread, args->level); 329 return NULL; 330} 331 332void RenderProxy::trimMemory(int level) { 333 // Avoid creating a RenderThread to do a trimMemory. 334 if (RenderThread::hasInstance()) { 335 RenderThread& thread = RenderThread::getInstance(); 336 SETUP_TASK(timMemory); 337 args->thread = &thread; 338 args->level = level; 339 thread.queue(task); 340 } 341} 342 343template <typename T> 344void UNUSED(T) {} 345 346 347CREATE_BRIDGE0(fence) { 348 // Intentionally empty 349 UNUSED(args); 350 return NULL; 351} 352 353void RenderProxy::fence() { 354 SETUP_TASK(fence); 355 UNUSED(args); 356 postAndWait(task); 357} 358 359CREATE_BRIDGE1(stopDrawing, CanvasContext* context) { 360 args->context->stopDrawing(); 361 return NULL; 362} 363 364void RenderProxy::stopDrawing() { 365 SETUP_TASK(stopDrawing); 366 args->context = mContext; 367 postAndWait(task); 368} 369 370CREATE_BRIDGE1(notifyFramePending, CanvasContext* context) { 371 args->context->notifyFramePending(); 372 return NULL; 373} 374 375void RenderProxy::notifyFramePending() { 376 SETUP_TASK(notifyFramePending); 377 args->context = mContext; 378 mRenderThread.queueAtFront(task); 379} 380 381CREATE_BRIDGE2(dumpProfileInfo, CanvasContext* context, int fd) { 382 args->context->profiler().dumpData(args->fd); 383 return NULL; 384} 385 386void RenderProxy::dumpProfileInfo(int fd) { 387 SETUP_TASK(dumpProfileInfo); 388 args->context = mContext; 389 args->fd = fd; 390 postAndWait(task); 391} 392 393CREATE_BRIDGE1(outputLogBuffer, int fd) { 394 RenderNode::outputLogBuffer(args->fd); 395 return NULL; 396} 397 398void RenderProxy::outputLogBuffer(int fd) { 399 SETUP_TASK(outputLogBuffer); 400 args->fd = fd; 401 staticPostAndWait(task); 402} 403 404CREATE_BRIDGE4(setTextureAtlas, RenderThread* thread, GraphicBuffer* buffer, int64_t* map, size_t size) { 405 CanvasContext::setTextureAtlas(*args->thread, args->buffer, args->map, args->size); 406 args->buffer->decStrong(0); 407 return NULL; 408} 409 410void RenderProxy::setTextureAtlas(const sp<GraphicBuffer>& buffer, int64_t* map, size_t size) { 411 SETUP_TASK(setTextureAtlas); 412 args->thread = &mRenderThread; 413 args->buffer = buffer.get(); 414 args->buffer->incStrong(0); 415 args->map = map; 416 args->size = size; 417 post(task); 418} 419 420void RenderProxy::post(RenderTask* task) { 421 mRenderThread.queue(task); 422} 423 424void* RenderProxy::postAndWait(MethodInvokeRenderTask* task) { 425 void* retval; 426 task->setReturnPtr(&retval); 427 SignalingRenderTask syncTask(task, &mSyncMutex, &mSyncCondition); 428 AutoMutex _lock(mSyncMutex); 429 mRenderThread.queue(&syncTask); 430 mSyncCondition.wait(mSyncMutex); 431 return retval; 432} 433 434void* RenderProxy::staticPostAndWait(MethodInvokeRenderTask* task) { 435 RenderThread& thread = RenderThread::getInstance(); 436 void* retval; 437 task->setReturnPtr(&retval); 438 Mutex mutex; 439 Condition condition; 440 SignalingRenderTask syncTask(task, &mutex, &condition); 441 AutoMutex _lock(mutex); 442 thread.queue(&syncTask); 443 condition.wait(mutex); 444 return retval; 445} 446 447} /* namespace renderthread */ 448} /* namespace uirenderer */ 449} /* namespace android */ 450