RenderProxy.cpp revision 738ec3aace180018560998d1c2cdeb9ddde5fbfa
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#define LOG_TAG "RenderProxy" 18 19#include "RenderProxy.h" 20 21#include "CanvasContext.h" 22#include "RenderTask.h" 23#include "RenderThread.h" 24 25#include "../DeferredLayerUpdater.h" 26#include "../DisplayList.h" 27#include "../LayerRenderer.h" 28#include "../Rect.h" 29 30namespace android { 31namespace uirenderer { 32namespace renderthread { 33 34#define ARGS(method) method ## Args 35 36#define CREATE_BRIDGE0(name) CREATE_BRIDGE(name,,,,,,,,) 37#define CREATE_BRIDGE1(name, a1) CREATE_BRIDGE(name, a1,,,,,,,) 38#define CREATE_BRIDGE2(name, a1, a2) CREATE_BRIDGE(name, a1,a2,,,,,,) 39#define CREATE_BRIDGE3(name, a1, a2, a3) CREATE_BRIDGE(name, a1,a2,a3,,,,,) 40#define CREATE_BRIDGE4(name, a1, a2, a3, a4) CREATE_BRIDGE(name, a1,a2,a3,a4,,,,) 41#define CREATE_BRIDGE5(name, a1, a2, a3, a4, a5) CREATE_BRIDGE(name, a1,a2,a3,a4,a5,,,) 42#define CREATE_BRIDGE6(name, a1, a2, a3, a4, a5, a6) CREATE_BRIDGE(name, a1,a2,a3,a4,a5,a6,,) 43#define CREATE_BRIDGE7(name, a1, a2, a3, a4, a5, a6, a7) CREATE_BRIDGE(name, a1,a2,a3,a4,a5,a6,a7,) 44#define CREATE_BRIDGE(name, a1, a2, a3, a4, a5, a6, a7, a8) \ 45 typedef struct { \ 46 a1; a2; a3; a4; a5; a6; a7; a8; \ 47 } ARGS(name); \ 48 static void* Bridge_ ## name(ARGS(name)* args) 49 50#define SETUP_TASK(method) \ 51 LOG_ALWAYS_FATAL_IF( METHOD_INVOKE_PAYLOAD_SIZE < sizeof(ARGS(method)), \ 52 "METHOD_INVOKE_PAYLOAD_SIZE %zu is smaller than sizeof(" #method "Args) %zu", \ 53 METHOD_INVOKE_PAYLOAD_SIZE, sizeof(ARGS(method))); \ 54 MethodInvokeRenderTask* task = new MethodInvokeRenderTask((RunnableMethod) Bridge_ ## method); \ 55 ARGS(method) *args = (ARGS(method) *) task->payload() 56 57CREATE_BRIDGE3(createContext, RenderThread* thread, bool translucent, RenderNode* rootRenderNode) { 58 return new CanvasContext(*args->thread, args->translucent, args->rootRenderNode); 59} 60 61RenderProxy::RenderProxy(bool translucent, RenderNode* rootRenderNode) 62 : mRenderThread(RenderThread::getInstance()) 63 , mContext(0) { 64 SETUP_TASK(createContext); 65 args->translucent = translucent; 66 args->rootRenderNode = rootRenderNode; 67 args->thread = &mRenderThread; 68 mContext = (CanvasContext*) postAndWait(task); 69 mDrawFrameTask.setContext(&mRenderThread, mContext); 70} 71 72RenderProxy::~RenderProxy() { 73 destroyContext(); 74} 75 76CREATE_BRIDGE1(destroyContext, CanvasContext* context) { 77 delete args->context; 78 return NULL; 79} 80 81void RenderProxy::destroyContext() { 82 if (mContext) { 83 SETUP_TASK(destroyContext); 84 args->context = mContext; 85 mContext = 0; 86 mDrawFrameTask.setContext(NULL, NULL); 87 // This is also a fence as we need to be certain that there are no 88 // outstanding mDrawFrame tasks posted before it is destroyed 89 postAndWait(task); 90 } 91} 92 93CREATE_BRIDGE2(setFrameInterval, RenderThread* thread, nsecs_t frameIntervalNanos) { 94 args->thread->timeLord().setFrameInterval(args->frameIntervalNanos); 95 return NULL; 96} 97 98void RenderProxy::setFrameInterval(nsecs_t frameIntervalNanos) { 99 SETUP_TASK(setFrameInterval); 100 args->thread = &mRenderThread; 101 args->frameIntervalNanos = frameIntervalNanos; 102 post(task); 103} 104 105CREATE_BRIDGE1(loadSystemProperties, CanvasContext* context) { 106 bool needsRedraw = false; 107 if (Caches::hasInstance()) { 108 needsRedraw = Caches::getInstance().initProperties(); 109 } 110 if (args->context->profiler().loadSystemProperties()) { 111 needsRedraw = true; 112 } 113 return (void*) needsRedraw; 114} 115 116bool RenderProxy::loadSystemProperties() { 117 SETUP_TASK(loadSystemProperties); 118 args->context = mContext; 119 return (bool) postAndWait(task); 120} 121 122CREATE_BRIDGE2(initialize, CanvasContext* context, ANativeWindow* window) { 123 return (void*) args->context->initialize(args->window); 124} 125 126bool RenderProxy::initialize(const sp<ANativeWindow>& window) { 127 SETUP_TASK(initialize); 128 args->context = mContext; 129 args->window = window.get(); 130 return (bool) postAndWait(task); 131} 132 133CREATE_BRIDGE2(updateSurface, CanvasContext* context, ANativeWindow* window) { 134 args->context->updateSurface(args->window); 135 return NULL; 136} 137 138void RenderProxy::updateSurface(const sp<ANativeWindow>& window) { 139 SETUP_TASK(updateSurface); 140 args->context = mContext; 141 args->window = window.get(); 142 postAndWait(task); 143} 144 145CREATE_BRIDGE2(pauseSurface, CanvasContext* context, ANativeWindow* window) { 146 args->context->pauseSurface(args->window); 147 return NULL; 148} 149 150void RenderProxy::pauseSurface(const sp<ANativeWindow>& window) { 151 SETUP_TASK(pauseSurface); 152 args->context = mContext; 153 args->window = window.get(); 154 postAndWait(task); 155} 156 157CREATE_BRIDGE7(setup, CanvasContext* context, int width, int height, 158 Vector3 lightCenter, float lightRadius, 159 uint8_t ambientShadowAlpha, uint8_t spotShadowAlpha) { 160 args->context->setup(args->width, args->height, args->lightCenter, args->lightRadius, 161 args->ambientShadowAlpha, args->spotShadowAlpha); 162 return NULL; 163} 164 165void RenderProxy::setup(int width, int height, const Vector3& lightCenter, float lightRadius, 166 uint8_t ambientShadowAlpha, uint8_t spotShadowAlpha) { 167 SETUP_TASK(setup); 168 args->context = mContext; 169 args->width = width; 170 args->height = height; 171 args->lightCenter = lightCenter; 172 args->lightRadius = lightRadius; 173 args->ambientShadowAlpha = ambientShadowAlpha; 174 args->spotShadowAlpha = spotShadowAlpha; 175 post(task); 176} 177 178CREATE_BRIDGE2(setOpaque, CanvasContext* context, bool opaque) { 179 args->context->setOpaque(args->opaque); 180 return NULL; 181} 182 183void RenderProxy::setOpaque(bool opaque) { 184 SETUP_TASK(setOpaque); 185 args->context = mContext; 186 args->opaque = opaque; 187 post(task); 188} 189 190int RenderProxy::syncAndDrawFrame(nsecs_t frameTimeNanos, nsecs_t recordDurationNanos, 191 float density) { 192 mDrawFrameTask.setDensity(density); 193 return mDrawFrameTask.drawFrame(frameTimeNanos, recordDurationNanos); 194} 195 196CREATE_BRIDGE1(destroyCanvasAndSurface, CanvasContext* context) { 197 args->context->destroyCanvasAndSurface(); 198 return NULL; 199} 200 201void RenderProxy::destroyCanvasAndSurface() { 202 SETUP_TASK(destroyCanvasAndSurface); 203 args->context = mContext; 204 // destroyCanvasAndSurface() needs a fence as when it returns the 205 // underlying BufferQueue is going to be released from under 206 // the render thread. 207 postAndWait(task); 208} 209 210CREATE_BRIDGE2(invokeFunctor, RenderThread* thread, Functor* functor) { 211 CanvasContext::invokeFunctor(*args->thread, args->functor); 212 return NULL; 213} 214 215void RenderProxy::invokeFunctor(Functor* functor, bool waitForCompletion) { 216 ATRACE_CALL(); 217 RenderThread& thread = RenderThread::getInstance(); 218 SETUP_TASK(invokeFunctor); 219 args->thread = &thread; 220 args->functor = functor; 221 if (waitForCompletion) { 222 // waitForCompletion = true is expected to be fairly rare and only 223 // happen in destruction. Thus it should be fine to temporarily 224 // create a Mutex 225 Mutex mutex; 226 Condition condition; 227 SignalingRenderTask syncTask(task, &mutex, &condition); 228 AutoMutex _lock(mutex); 229 thread.queue(&syncTask); 230 condition.wait(mutex); 231 } else { 232 thread.queue(task); 233 } 234} 235 236CREATE_BRIDGE2(runWithGlContext, CanvasContext* context, RenderTask* task) { 237 args->context->runWithGlContext(args->task); 238 return NULL; 239} 240 241void RenderProxy::runWithGlContext(RenderTask* gltask) { 242 SETUP_TASK(runWithGlContext); 243 args->context = mContext; 244 args->task = gltask; 245 postAndWait(task); 246} 247 248CREATE_BRIDGE1(destroyLayer, Layer* layer) { 249 LayerRenderer::destroyLayer(args->layer); 250 return NULL; 251} 252 253void RenderProxy::enqueueDestroyLayer(Layer* layer) { 254 SETUP_TASK(destroyLayer); 255 args->layer = layer; 256 RenderThread::getInstance().queue(task); 257} 258 259CREATE_BRIDGE3(createDisplayListLayer, CanvasContext* context, int width, int height) { 260 Layer* layer = args->context->createRenderLayer(args->width, args->height); 261 if (!layer) return 0; 262 return new DeferredLayerUpdater(layer, RenderProxy::enqueueDestroyLayer); 263} 264 265DeferredLayerUpdater* RenderProxy::createDisplayListLayer(int width, int height) { 266 SETUP_TASK(createDisplayListLayer); 267 args->width = width; 268 args->height = height; 269 args->context = mContext; 270 void* retval = postAndWait(task); 271 DeferredLayerUpdater* layer = reinterpret_cast<DeferredLayerUpdater*>(retval); 272 return layer; 273} 274 275CREATE_BRIDGE1(createTextureLayer, CanvasContext* context) { 276 Layer* layer = args->context->createTextureLayer(); 277 if (!layer) return 0; 278 return new DeferredLayerUpdater(layer, RenderProxy::enqueueDestroyLayer); 279} 280 281DeferredLayerUpdater* RenderProxy::createTextureLayer() { 282 SETUP_TASK(createTextureLayer); 283 args->context = mContext; 284 void* retval = postAndWait(task); 285 DeferredLayerUpdater* layer = reinterpret_cast<DeferredLayerUpdater*>(retval); 286 return layer; 287} 288 289CREATE_BRIDGE3(copyLayerInto, CanvasContext* context, DeferredLayerUpdater* layer, 290 SkBitmap* bitmap) { 291 bool success = args->context->copyLayerInto(args->layer, args->bitmap); 292 return (void*) success; 293} 294 295bool RenderProxy::copyLayerInto(DeferredLayerUpdater* layer, SkBitmap* bitmap) { 296 SETUP_TASK(copyLayerInto); 297 args->context = mContext; 298 args->layer = layer; 299 args->bitmap = bitmap; 300 return (bool) postAndWait(task); 301} 302 303void RenderProxy::pushLayerUpdate(DeferredLayerUpdater* layer) { 304 mDrawFrameTask.pushLayerUpdate(layer); 305} 306 307void RenderProxy::cancelLayerUpdate(DeferredLayerUpdater* layer) { 308 mDrawFrameTask.removeLayerUpdate(layer); 309} 310 311CREATE_BRIDGE1(detachSurfaceTexture, DeferredLayerUpdater* layer) { 312 args->layer->detachSurfaceTexture(); 313 return NULL; 314} 315 316void RenderProxy::detachSurfaceTexture(DeferredLayerUpdater* layer) { 317 SETUP_TASK(detachSurfaceTexture); 318 args->layer = layer; 319 postAndWait(task); 320} 321 322CREATE_BRIDGE1(destroyHardwareResources, CanvasContext* context) { 323 args->context->destroyHardwareResources(); 324 return NULL; 325} 326 327void RenderProxy::destroyHardwareResources() { 328 SETUP_TASK(destroyHardwareResources); 329 args->context = mContext; 330 post(task); 331} 332 333CREATE_BRIDGE2(timMemory, RenderThread* thread, int level) { 334 CanvasContext::trimMemory(*args->thread, args->level); 335 return NULL; 336} 337 338void RenderProxy::trimMemory(int level) { 339 RenderThread& thread = RenderThread::getInstance(); 340 SETUP_TASK(timMemory); 341 args->thread = &thread; 342 args->level = level; 343 thread.queue(task); 344} 345 346CREATE_BRIDGE0(fence) { 347 // Intentionally empty 348 return NULL; 349} 350 351void RenderProxy::fence() { 352 SETUP_TASK(fence); 353 postAndWait(task); 354} 355 356CREATE_BRIDGE1(stopDrawing, CanvasContext* context) { 357 args->context->stopDrawing(); 358 return NULL; 359} 360 361void RenderProxy::stopDrawing() { 362 SETUP_TASK(stopDrawing); 363 args->context = mContext; 364 postAndWait(task); 365} 366 367CREATE_BRIDGE1(notifyFramePending, CanvasContext* context) { 368 args->context->notifyFramePending(); 369 return NULL; 370} 371 372void RenderProxy::notifyFramePending() { 373 SETUP_TASK(notifyFramePending); 374 args->context = mContext; 375 mRenderThread.queueAtFront(task); 376} 377 378CREATE_BRIDGE2(dumpProfileInfo, CanvasContext* context, int fd) { 379 args->context->profiler().dumpData(args->fd); 380 return NULL; 381} 382 383void RenderProxy::dumpProfileInfo(int fd) { 384 SETUP_TASK(dumpProfileInfo); 385 args->context = mContext; 386 args->fd = fd; 387 postAndWait(task); 388} 389 390CREATE_BRIDGE4(setTextureAtlas, RenderThread* thread, GraphicBuffer* buffer, int64_t* map, size_t size) { 391 CanvasContext::setTextureAtlas(*args->thread, args->buffer, args->map, args->size); 392 args->buffer->decStrong(0); 393 return NULL; 394} 395 396void RenderProxy::setTextureAtlas(const sp<GraphicBuffer>& buffer, int64_t* map, size_t size) { 397 SETUP_TASK(setTextureAtlas); 398 args->thread = &mRenderThread; 399 args->buffer = buffer.get(); 400 args->buffer->incStrong(0); 401 args->map = map; 402 args->size = size; 403 post(task); 404} 405 406void RenderProxy::post(RenderTask* task) { 407 mRenderThread.queue(task); 408} 409 410void* RenderProxy::postAndWait(MethodInvokeRenderTask* task) { 411 void* retval; 412 task->setReturnPtr(&retval); 413 SignalingRenderTask syncTask(task, &mSyncMutex, &mSyncCondition); 414 AutoMutex _lock(mSyncMutex); 415 mRenderThread.queue(&syncTask); 416 mSyncCondition.wait(mSyncMutex); 417 return retval; 418} 419 420} /* namespace renderthread */ 421} /* namespace uirenderer */ 422} /* namespace android */ 423