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