Home | History | Annotate | Download | only in renderthread
      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