RenderProxy.cpp revision 69e5adffb19135d51bde8e458f4907d7265f3e23
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_BRIDGE3(createContext, RenderThread* thread, bool translucent, RenderNode* rootRenderNode) { 56 return new CanvasContext(*args->thread, args->translucent, args->rootRenderNode); 57} 58 59RenderProxy::RenderProxy(bool translucent, RenderNode* rootRenderNode) 60 : mRenderThread(RenderThread::getInstance()) 61 , mContext(0) { 62 SETUP_TASK(createContext); 63 args->translucent = translucent; 64 args->rootRenderNode = rootRenderNode; 65 args->thread = &mRenderThread; 66 mContext = (CanvasContext*) postAndWait(task); 67 mDrawFrameTask.setContext(&mRenderThread, mContext); 68} 69 70RenderProxy::~RenderProxy() { 71 destroyContext(); 72} 73 74CREATE_BRIDGE1(destroyContext, CanvasContext* context) { 75 delete args->context; 76 return NULL; 77} 78 79void RenderProxy::destroyContext() { 80 if (mContext) { 81 SETUP_TASK(destroyContext); 82 args->context = mContext; 83 mContext = 0; 84 mDrawFrameTask.setContext(NULL, NULL); 85 // This is also a fence as we need to be certain that there are no 86 // outstanding mDrawFrame tasks posted before it is destroyed 87 postAndWait(task); 88 } 89} 90 91CREATE_BRIDGE2(setFrameInterval, RenderThread* thread, nsecs_t frameIntervalNanos) { 92 args->thread->timeLord().setFrameInterval(args->frameIntervalNanos); 93 return NULL; 94} 95 96void RenderProxy::setFrameInterval(nsecs_t frameIntervalNanos) { 97 SETUP_TASK(setFrameInterval); 98 args->thread = &mRenderThread; 99 args->frameIntervalNanos = frameIntervalNanos; 100 post(task); 101} 102 103CREATE_BRIDGE1(loadSystemProperties, CanvasContext* context) { 104 bool needsRedraw = false; 105 if (Caches::hasInstance()) { 106 needsRedraw = Caches::getInstance().initProperties(); 107 } 108 if (args->context->profiler().loadSystemProperties()) { 109 needsRedraw = true; 110 } 111 return (void*) needsRedraw; 112} 113 114bool RenderProxy::loadSystemProperties() { 115 SETUP_TASK(loadSystemProperties); 116 args->context = mContext; 117 return (bool) postAndWait(task); 118} 119 120CREATE_BRIDGE2(initialize, CanvasContext* context, ANativeWindow* window) { 121 return (void*) args->context->initialize(args->window); 122} 123 124bool RenderProxy::initialize(const sp<ANativeWindow>& window) { 125 SETUP_TASK(initialize); 126 args->context = mContext; 127 args->window = window.get(); 128 return (bool) postAndWait(task); 129} 130 131CREATE_BRIDGE2(updateSurface, CanvasContext* context, ANativeWindow* window) { 132 args->context->updateSurface(args->window); 133 return NULL; 134} 135 136void RenderProxy::updateSurface(const sp<ANativeWindow>& window) { 137 SETUP_TASK(updateSurface); 138 args->context = mContext; 139 args->window = window.get(); 140 postAndWait(task); 141} 142 143CREATE_BRIDGE2(pauseSurface, CanvasContext* context, ANativeWindow* window) { 144 args->context->pauseSurface(args->window); 145 return NULL; 146} 147 148void RenderProxy::pauseSurface(const sp<ANativeWindow>& window) { 149 SETUP_TASK(pauseSurface); 150 args->context = mContext; 151 args->window = window.get(); 152 postAndWait(task); 153} 154 155CREATE_BRIDGE7(setup, CanvasContext* context, int width, int height, 156 Vector3 lightCenter, float lightRadius, 157 uint8_t ambientShadowAlpha, uint8_t spotShadowAlpha) { 158 args->context->setup(args->width, args->height, args->lightCenter, args->lightRadius, 159 args->ambientShadowAlpha, args->spotShadowAlpha); 160 return NULL; 161} 162 163void RenderProxy::setup(int width, int height, const Vector3& lightCenter, float lightRadius, 164 uint8_t ambientShadowAlpha, uint8_t spotShadowAlpha) { 165 SETUP_TASK(setup); 166 args->context = mContext; 167 args->width = width; 168 args->height = height; 169 args->lightCenter = lightCenter; 170 args->lightRadius = lightRadius; 171 args->ambientShadowAlpha = ambientShadowAlpha; 172 args->spotShadowAlpha = spotShadowAlpha; 173 post(task); 174} 175 176CREATE_BRIDGE2(setOpaque, CanvasContext* context, bool opaque) { 177 args->context->setOpaque(args->opaque); 178 return NULL; 179} 180 181void RenderProxy::setOpaque(bool opaque) { 182 SETUP_TASK(setOpaque); 183 args->context = mContext; 184 args->opaque = opaque; 185 post(task); 186} 187 188int RenderProxy::syncAndDrawFrame(nsecs_t frameTimeNanos, nsecs_t recordDurationNanos, 189 float density) { 190 mDrawFrameTask.setDensity(density); 191 return mDrawFrameTask.drawFrame(frameTimeNanos, recordDurationNanos); 192} 193 194CREATE_BRIDGE1(destroyCanvasAndSurface, CanvasContext* context) { 195 args->context->destroyCanvasAndSurface(); 196 return NULL; 197} 198 199void RenderProxy::destroyCanvasAndSurface() { 200 SETUP_TASK(destroyCanvasAndSurface); 201 args->context = mContext; 202 // destroyCanvasAndSurface() needs a fence as when it returns the 203 // underlying BufferQueue is going to be released from under 204 // the render thread. 205 postAndWait(task); 206} 207 208CREATE_BRIDGE2(invokeFunctor, RenderThread* thread, Functor* functor) { 209 CanvasContext::invokeFunctor(*args->thread, args->functor); 210 return NULL; 211} 212 213void RenderProxy::invokeFunctor(Functor* functor, bool waitForCompletion) { 214 ATRACE_CALL(); 215 RenderThread& thread = RenderThread::getInstance(); 216 SETUP_TASK(invokeFunctor); 217 args->thread = &thread; 218 args->functor = functor; 219 if (waitForCompletion) { 220 // waitForCompletion = true is expected to be fairly rare and only 221 // happen in destruction. Thus it should be fine to temporarily 222 // create a Mutex 223 Mutex mutex; 224 Condition condition; 225 SignalingRenderTask syncTask(task, &mutex, &condition); 226 AutoMutex _lock(mutex); 227 thread.queue(&syncTask); 228 condition.wait(mutex); 229 } else { 230 thread.queue(task); 231 } 232} 233 234CREATE_BRIDGE2(runWithGlContext, CanvasContext* context, RenderTask* task) { 235 args->context->runWithGlContext(args->task); 236 return NULL; 237} 238 239void RenderProxy::runWithGlContext(RenderTask* gltask) { 240 SETUP_TASK(runWithGlContext); 241 args->context = mContext; 242 args->task = gltask; 243 postAndWait(task); 244} 245 246CREATE_BRIDGE1(destroyLayer, Layer* layer) { 247 LayerRenderer::destroyLayer(args->layer); 248 return NULL; 249} 250 251void RenderProxy::enqueueDestroyLayer(Layer* layer) { 252 SETUP_TASK(destroyLayer); 253 args->layer = layer; 254 RenderThread::getInstance().queue(task); 255} 256 257CREATE_BRIDGE3(createDisplayListLayer, CanvasContext* context, int width, int height) { 258 Layer* layer = args->context->createRenderLayer(args->width, args->height); 259 if (!layer) return 0; 260 return new DeferredLayerUpdater(layer, RenderProxy::enqueueDestroyLayer); 261} 262 263DeferredLayerUpdater* RenderProxy::createDisplayListLayer(int width, int height) { 264 SETUP_TASK(createDisplayListLayer); 265 args->width = width; 266 args->height = height; 267 args->context = mContext; 268 void* retval = postAndWait(task); 269 DeferredLayerUpdater* layer = reinterpret_cast<DeferredLayerUpdater*>(retval); 270 return layer; 271} 272 273CREATE_BRIDGE1(createTextureLayer, CanvasContext* context) { 274 Layer* layer = args->context->createTextureLayer(); 275 if (!layer) return 0; 276 return new DeferredLayerUpdater(layer, RenderProxy::enqueueDestroyLayer); 277} 278 279DeferredLayerUpdater* RenderProxy::createTextureLayer() { 280 SETUP_TASK(createTextureLayer); 281 args->context = mContext; 282 void* retval = postAndWait(task); 283 DeferredLayerUpdater* layer = reinterpret_cast<DeferredLayerUpdater*>(retval); 284 return layer; 285} 286 287CREATE_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 293bool 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 301void RenderProxy::pushLayerUpdate(DeferredLayerUpdater* layer) { 302 mDrawFrameTask.pushLayerUpdate(layer); 303} 304 305void RenderProxy::cancelLayerUpdate(DeferredLayerUpdater* layer) { 306 mDrawFrameTask.removeLayerUpdate(layer); 307} 308 309CREATE_BRIDGE1(detachSurfaceTexture, DeferredLayerUpdater* layer) { 310 args->layer->detachSurfaceTexture(); 311 return NULL; 312} 313 314void RenderProxy::detachSurfaceTexture(DeferredLayerUpdater* layer) { 315 SETUP_TASK(detachSurfaceTexture); 316 args->layer = layer; 317 postAndWait(task); 318} 319 320CREATE_BRIDGE1(destroyHardwareResources, CanvasContext* context) { 321 args->context->destroyHardwareResources(); 322 return NULL; 323} 324 325void RenderProxy::destroyHardwareResources() { 326 SETUP_TASK(destroyHardwareResources); 327 args->context = mContext; 328 post(task); 329} 330 331CREATE_BRIDGE2(timMemory, RenderThread* thread, int level) { 332 CanvasContext::trimMemory(*args->thread, args->level); 333 return NULL; 334} 335 336void 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 347CREATE_BRIDGE0(fence) { 348 // Intentionally empty 349 return NULL; 350} 351 352void RenderProxy::fence() { 353 SETUP_TASK(fence); 354 postAndWait(task); 355} 356 357CREATE_BRIDGE1(stopDrawing, CanvasContext* context) { 358 args->context->stopDrawing(); 359 return NULL; 360} 361 362void RenderProxy::stopDrawing() { 363 SETUP_TASK(stopDrawing); 364 args->context = mContext; 365 postAndWait(task); 366} 367 368CREATE_BRIDGE1(notifyFramePending, CanvasContext* context) { 369 args->context->notifyFramePending(); 370 return NULL; 371} 372 373void RenderProxy::notifyFramePending() { 374 SETUP_TASK(notifyFramePending); 375 args->context = mContext; 376 mRenderThread.queueAtFront(task); 377} 378 379CREATE_BRIDGE2(dumpProfileInfo, CanvasContext* context, int fd) { 380 args->context->profiler().dumpData(args->fd); 381 return NULL; 382} 383 384void RenderProxy::dumpProfileInfo(int fd) { 385 SETUP_TASK(dumpProfileInfo); 386 args->context = mContext; 387 args->fd = fd; 388 postAndWait(task); 389} 390 391CREATE_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 397void 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 407void RenderProxy::post(RenderTask* task) { 408 mRenderThread.queue(task); 409} 410 411void* 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