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