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 "DeferredLayerUpdater.h"
     20 #include "DisplayList.h"
     21 #include "LayerRenderer.h"
     22 #include "Readback.h"
     23 #include "Rect.h"
     24 #include "renderthread/CanvasContext.h"
     25 #include "renderthread/RenderTask.h"
     26 #include "renderthread/RenderThread.h"
     27 #include "utils/Macros.h"
     28 
     29 namespace android {
     30 namespace uirenderer {
     31 namespace renderthread {
     32 
     33 #define ARGS(method) method ## Args
     34 
     35 #define CREATE_BRIDGE0(name) CREATE_BRIDGE(name,,,,,,,,)
     36 #define CREATE_BRIDGE1(name, a1) CREATE_BRIDGE(name, a1,,,,,,,)
     37 #define CREATE_BRIDGE2(name, a1, a2) CREATE_BRIDGE(name, a1,a2,,,,,,)
     38 #define CREATE_BRIDGE3(name, a1, a2, a3) CREATE_BRIDGE(name, a1,a2,a3,,,,,)
     39 #define CREATE_BRIDGE4(name, a1, a2, a3, a4) CREATE_BRIDGE(name, a1,a2,a3,a4,,,,)
     40 #define CREATE_BRIDGE5(name, a1, a2, a3, a4, a5) CREATE_BRIDGE(name, a1,a2,a3,a4,a5,,,)
     41 #define CREATE_BRIDGE6(name, a1, a2, a3, a4, a5, a6) CREATE_BRIDGE(name, a1,a2,a3,a4,a5,a6,,)
     42 #define CREATE_BRIDGE7(name, a1, a2, a3, a4, a5, a6, a7) CREATE_BRIDGE(name, a1,a2,a3,a4,a5,a6,a7,)
     43 #define CREATE_BRIDGE(name, a1, a2, a3, a4, a5, a6, a7, a8) \
     44     typedef struct { \
     45         a1; a2; a3; a4; a5; a6; a7; a8; \
     46     } ARGS(name); \
     47     static void* Bridge_ ## name(ARGS(name)* args)
     48 
     49 #define SETUP_TASK(method) \
     50     LOG_ALWAYS_FATAL_IF( METHOD_INVOKE_PAYLOAD_SIZE < sizeof(ARGS(method)), \
     51         "METHOD_INVOKE_PAYLOAD_SIZE %zu is smaller than sizeof(" #method "Args) %zu", \
     52                 METHOD_INVOKE_PAYLOAD_SIZE, sizeof(ARGS(method))); \
     53     MethodInvokeRenderTask* task = new MethodInvokeRenderTask((RunnableMethod) Bridge_ ## method); \
     54     ARGS(method) *args = (ARGS(method) *) task->payload()
     55 
     56 CREATE_BRIDGE4(createContext, RenderThread* thread, bool translucent,
     57         RenderNode* rootRenderNode, IContextFactory* contextFactory) {
     58     return new CanvasContext(*args->thread, args->translucent,
     59             args->rootRenderNode, args->contextFactory);
     60 }
     61 
     62 RenderProxy::RenderProxy(bool translucent, RenderNode* rootRenderNode, IContextFactory* contextFactory)
     63         : mRenderThread(RenderThread::getInstance())
     64         , mContext(nullptr) {
     65     SETUP_TASK(createContext);
     66     args->translucent = translucent;
     67     args->rootRenderNode = rootRenderNode;
     68     args->thread = &mRenderThread;
     69     args->contextFactory = contextFactory;
     70     mContext = (CanvasContext*) postAndWait(task);
     71     mDrawFrameTask.setContext(&mRenderThread, mContext, rootRenderNode);
     72 }
     73 
     74 RenderProxy::~RenderProxy() {
     75     destroyContext();
     76 }
     77 
     78 CREATE_BRIDGE1(destroyContext, CanvasContext* context) {
     79     delete args->context;
     80     return nullptr;
     81 }
     82 
     83 void RenderProxy::destroyContext() {
     84     if (mContext) {
     85         SETUP_TASK(destroyContext);
     86         args->context = mContext;
     87         mContext = nullptr;
     88         mDrawFrameTask.setContext(nullptr, nullptr, nullptr);
     89         // This is also a fence as we need to be certain that there are no
     90         // outstanding mDrawFrame tasks posted before it is destroyed
     91         postAndWait(task);
     92     }
     93 }
     94 
     95 CREATE_BRIDGE2(setSwapBehavior, CanvasContext* context, SwapBehavior swapBehavior) {
     96     args->context->setSwapBehavior(args->swapBehavior);
     97     return nullptr;
     98 }
     99 
    100 void RenderProxy::setSwapBehavior(SwapBehavior swapBehavior) {
    101     SETUP_TASK(setSwapBehavior);
    102     args->context = mContext;
    103     args->swapBehavior = swapBehavior;
    104     post(task);
    105 }
    106 
    107 CREATE_BRIDGE1(loadSystemProperties, CanvasContext* context) {
    108     bool needsRedraw = false;
    109     if (Caches::hasInstance()) {
    110         needsRedraw = Properties::load();
    111     }
    112     if (args->context->profiler().consumeProperties()) {
    113         needsRedraw = true;
    114     }
    115     return (void*) needsRedraw;
    116 }
    117 
    118 bool RenderProxy::loadSystemProperties() {
    119     SETUP_TASK(loadSystemProperties);
    120     args->context = mContext;
    121     return (bool) postAndWait(task);
    122 }
    123 
    124 CREATE_BRIDGE2(setName, CanvasContext* context, const char* name) {
    125     args->context->setName(std::string(args->name));
    126     return nullptr;
    127 }
    128 
    129 void RenderProxy::setName(const char* name) {
    130     SETUP_TASK(setName);
    131     args->context = mContext;
    132     args->name = name;
    133     postAndWait(task); // block since name/value pointers owned by caller
    134 }
    135 
    136 CREATE_BRIDGE2(initialize, CanvasContext* context, Surface* surface) {
    137     args->context->initialize(args->surface);
    138     return nullptr;
    139 }
    140 
    141 void RenderProxy::initialize(const sp<Surface>& surface) {
    142     SETUP_TASK(initialize);
    143     args->context = mContext;
    144     args->surface = surface.get();
    145     post(task);
    146 }
    147 
    148 CREATE_BRIDGE2(updateSurface, CanvasContext* context, Surface* surface) {
    149     args->context->updateSurface(args->surface);
    150     return nullptr;
    151 }
    152 
    153 void RenderProxy::updateSurface(const sp<Surface>& surface) {
    154     SETUP_TASK(updateSurface);
    155     args->context = mContext;
    156     args->surface = surface.get();
    157     postAndWait(task);
    158 }
    159 
    160 CREATE_BRIDGE2(pauseSurface, CanvasContext* context, Surface* surface) {
    161     return (void*) args->context->pauseSurface(args->surface);
    162 }
    163 
    164 bool RenderProxy::pauseSurface(const sp<Surface>& surface) {
    165     SETUP_TASK(pauseSurface);
    166     args->context = mContext;
    167     args->surface = surface.get();
    168     return (bool) postAndWait(task);
    169 }
    170 
    171 CREATE_BRIDGE2(setStopped, CanvasContext* context, bool stopped) {
    172     args->context->setStopped(args->stopped);
    173     return nullptr;
    174 }
    175 
    176 void RenderProxy::setStopped(bool stopped) {
    177     SETUP_TASK(setStopped);
    178     args->context = mContext;
    179     args->stopped = stopped;
    180     postAndWait(task);
    181 }
    182 
    183 CREATE_BRIDGE6(setup, CanvasContext* context, int width, int height,
    184         float lightRadius, uint8_t ambientShadowAlpha, uint8_t spotShadowAlpha) {
    185     args->context->setup(args->width, args->height, args->lightRadius,
    186             args->ambientShadowAlpha, args->spotShadowAlpha);
    187     return nullptr;
    188 }
    189 
    190 void RenderProxy::setup(int width, int height, float lightRadius,
    191         uint8_t ambientShadowAlpha, uint8_t spotShadowAlpha) {
    192     SETUP_TASK(setup);
    193     args->context = mContext;
    194     args->width = width;
    195     args->height = height;
    196     args->lightRadius = lightRadius;
    197     args->ambientShadowAlpha = ambientShadowAlpha;
    198     args->spotShadowAlpha = spotShadowAlpha;
    199     post(task);
    200 }
    201 
    202 CREATE_BRIDGE2(setLightCenter, CanvasContext* context, Vector3 lightCenter) {
    203     args->context->setLightCenter(args->lightCenter);
    204     return nullptr;
    205 }
    206 
    207 void RenderProxy::setLightCenter(const Vector3& lightCenter) {
    208     SETUP_TASK(setLightCenter);
    209     args->context = mContext;
    210     args->lightCenter = lightCenter;
    211     post(task);
    212 }
    213 
    214 CREATE_BRIDGE2(setOpaque, CanvasContext* context, bool opaque) {
    215     args->context->setOpaque(args->opaque);
    216     return nullptr;
    217 }
    218 
    219 void RenderProxy::setOpaque(bool opaque) {
    220     SETUP_TASK(setOpaque);
    221     args->context = mContext;
    222     args->opaque = opaque;
    223     post(task);
    224 }
    225 
    226 int64_t* RenderProxy::frameInfo() {
    227     return mDrawFrameTask.frameInfo();
    228 }
    229 
    230 int RenderProxy::syncAndDrawFrame(TreeObserver* observer) {
    231     return mDrawFrameTask.drawFrame(observer);
    232 }
    233 
    234 CREATE_BRIDGE2(destroy, CanvasContext* context, TreeObserver* observer) {
    235     args->context->destroy(args->observer);
    236     return nullptr;
    237 }
    238 
    239 void RenderProxy::destroy(TreeObserver* observer) {
    240     SETUP_TASK(destroy);
    241     args->context = mContext;
    242     args->observer = observer;
    243     // destroyCanvasAndSurface() needs a fence as when it returns the
    244     // underlying BufferQueue is going to be released from under
    245     // the render thread.
    246     postAndWait(task);
    247 }
    248 
    249 CREATE_BRIDGE2(invokeFunctor, RenderThread* thread, Functor* functor) {
    250     CanvasContext::invokeFunctor(*args->thread, args->functor);
    251     return nullptr;
    252 }
    253 
    254 void RenderProxy::invokeFunctor(Functor* functor, bool waitForCompletion) {
    255     ATRACE_CALL();
    256     RenderThread& thread = RenderThread::getInstance();
    257     SETUP_TASK(invokeFunctor);
    258     args->thread = &thread;
    259     args->functor = functor;
    260     if (waitForCompletion) {
    261         // waitForCompletion = true is expected to be fairly rare and only
    262         // happen in destruction. Thus it should be fine to temporarily
    263         // create a Mutex
    264         staticPostAndWait(task);
    265     } else {
    266         thread.queue(task);
    267     }
    268 }
    269 
    270 CREATE_BRIDGE2(runWithGlContext, CanvasContext* context, RenderTask* task) {
    271     args->context->runWithGlContext(args->task);
    272     return nullptr;
    273 }
    274 
    275 void RenderProxy::runWithGlContext(RenderTask* gltask) {
    276     SETUP_TASK(runWithGlContext);
    277     args->context = mContext;
    278     args->task = gltask;
    279     postAndWait(task);
    280 }
    281 
    282 CREATE_BRIDGE1(createTextureLayer, CanvasContext* context) {
    283     Layer* layer = args->context->createTextureLayer();
    284     if (!layer) return nullptr;
    285     return new DeferredLayerUpdater(layer);
    286 }
    287 
    288 DeferredLayerUpdater* RenderProxy::createTextureLayer() {
    289     SETUP_TASK(createTextureLayer);
    290     args->context = mContext;
    291     void* retval = postAndWait(task);
    292     DeferredLayerUpdater* layer = reinterpret_cast<DeferredLayerUpdater*>(retval);
    293     return layer;
    294 }
    295 
    296 CREATE_BRIDGE3(buildLayer, CanvasContext* context, RenderNode* node, TreeObserver* observer) {
    297     args->context->buildLayer(args->node, args->observer);
    298     return nullptr;
    299 }
    300 
    301 void RenderProxy::buildLayer(RenderNode* node, TreeObserver* observer) {
    302     SETUP_TASK(buildLayer);
    303     args->context = mContext;
    304     args->node = node;
    305     args->observer = observer;
    306     postAndWait(task);
    307 }
    308 
    309 CREATE_BRIDGE3(copyLayerInto, CanvasContext* context, DeferredLayerUpdater* layer,
    310         SkBitmap* bitmap) {
    311     bool success = args->context->copyLayerInto(args->layer, args->bitmap);
    312     return (void*) success;
    313 }
    314 
    315 bool RenderProxy::copyLayerInto(DeferredLayerUpdater* layer, SkBitmap& bitmap) {
    316     SETUP_TASK(copyLayerInto);
    317     args->context = mContext;
    318     args->layer = layer;
    319     args->bitmap = &bitmap;
    320     return (bool) postAndWait(task);
    321 }
    322 
    323 void RenderProxy::pushLayerUpdate(DeferredLayerUpdater* layer) {
    324     mDrawFrameTask.pushLayerUpdate(layer);
    325 }
    326 
    327 void RenderProxy::cancelLayerUpdate(DeferredLayerUpdater* layer) {
    328     mDrawFrameTask.removeLayerUpdate(layer);
    329 }
    330 
    331 CREATE_BRIDGE1(detachSurfaceTexture, DeferredLayerUpdater* layer) {
    332     args->layer->detachSurfaceTexture();
    333     return nullptr;
    334 }
    335 
    336 void RenderProxy::detachSurfaceTexture(DeferredLayerUpdater* layer) {
    337     SETUP_TASK(detachSurfaceTexture);
    338     args->layer = layer;
    339     postAndWait(task);
    340 }
    341 
    342 CREATE_BRIDGE2(destroyHardwareResources, CanvasContext* context, TreeObserver* observer) {
    343     args->context->destroyHardwareResources(args->observer);
    344     return nullptr;
    345 }
    346 
    347 void RenderProxy::destroyHardwareResources(TreeObserver* observer) {
    348     SETUP_TASK(destroyHardwareResources);
    349     args->context = mContext;
    350     args->observer = observer;
    351     postAndWait(task);
    352 }
    353 
    354 CREATE_BRIDGE2(trimMemory, RenderThread* thread, int level) {
    355     CanvasContext::trimMemory(*args->thread, args->level);
    356     return nullptr;
    357 }
    358 
    359 void RenderProxy::trimMemory(int level) {
    360     // Avoid creating a RenderThread to do a trimMemory.
    361     if (RenderThread::hasInstance()) {
    362         RenderThread& thread = RenderThread::getInstance();
    363         SETUP_TASK(trimMemory);
    364         args->thread = &thread;
    365         args->level = level;
    366         thread.queue(task);
    367     }
    368 }
    369 
    370 CREATE_BRIDGE2(overrideProperty, const char* name, const char* value) {
    371     Properties::overrideProperty(args->name, args->value);
    372     return nullptr;
    373 }
    374 
    375 void RenderProxy::overrideProperty(const char* name, const char* value) {
    376     SETUP_TASK(overrideProperty);
    377     args->name = name;
    378     args->value = value;
    379     staticPostAndWait(task); // expensive, but block here since name/value pointers owned by caller
    380 }
    381 
    382 CREATE_BRIDGE0(fence) {
    383     // Intentionally empty
    384     return nullptr;
    385 }
    386 
    387 template <typename T>
    388 void UNUSED(T t) {}
    389 
    390 void RenderProxy::fence() {
    391     SETUP_TASK(fence);
    392     UNUSED(args);
    393     postAndWait(task);
    394 }
    395 
    396 void RenderProxy::staticFence() {
    397     SETUP_TASK(fence);
    398     UNUSED(args);
    399     staticPostAndWait(task);
    400 }
    401 
    402 CREATE_BRIDGE1(stopDrawing, CanvasContext* context) {
    403     args->context->stopDrawing();
    404     return nullptr;
    405 }
    406 
    407 void RenderProxy::stopDrawing() {
    408     SETUP_TASK(stopDrawing);
    409     args->context = mContext;
    410     postAndWait(task);
    411 }
    412 
    413 CREATE_BRIDGE1(notifyFramePending, CanvasContext* context) {
    414     args->context->notifyFramePending();
    415     return nullptr;
    416 }
    417 
    418 void RenderProxy::notifyFramePending() {
    419     SETUP_TASK(notifyFramePending);
    420     args->context = mContext;
    421     mRenderThread.queueAtFront(task);
    422 }
    423 
    424 CREATE_BRIDGE4(dumpProfileInfo, CanvasContext* context, RenderThread* thread,
    425         int fd, int dumpFlags) {
    426     args->context->profiler().dumpData(args->fd);
    427     if (args->dumpFlags & DumpFlags::FrameStats) {
    428         args->context->dumpFrames(args->fd);
    429     }
    430     if (args->dumpFlags & DumpFlags::Reset) {
    431         args->context->resetFrameStats();
    432     }
    433     if (args->dumpFlags & DumpFlags::JankStats) {
    434         args->thread->jankTracker().dump(args->fd);
    435     }
    436     return nullptr;
    437 }
    438 
    439 void RenderProxy::dumpProfileInfo(int fd, int dumpFlags) {
    440     SETUP_TASK(dumpProfileInfo);
    441     args->context = mContext;
    442     args->thread = &mRenderThread;
    443     args->fd = fd;
    444     args->dumpFlags = dumpFlags;
    445     postAndWait(task);
    446 }
    447 
    448 CREATE_BRIDGE1(resetProfileInfo, CanvasContext* context) {
    449     args->context->resetFrameStats();
    450     return nullptr;
    451 }
    452 
    453 void RenderProxy::resetProfileInfo() {
    454     SETUP_TASK(resetProfileInfo);
    455     args->context = mContext;
    456     postAndWait(task);
    457 }
    458 
    459 CREATE_BRIDGE2(dumpGraphicsMemory, int fd, RenderThread* thread) {
    460     args->thread->jankTracker().dump(args->fd);
    461 
    462     FILE *file = fdopen(args->fd, "a");
    463     if (Caches::hasInstance()) {
    464         String8 cachesLog;
    465         Caches::getInstance().dumpMemoryUsage(cachesLog);
    466         fprintf(file, "\nCaches:\n%s\n", cachesLog.string());
    467     } else {
    468         fprintf(file, "\nNo caches instance.\n");
    469     }
    470 #if HWUI_NEW_OPS
    471     fprintf(file, "\nPipeline=FrameBuilder\n");
    472 #else
    473     fprintf(file, "\nPipeline=OpenGLRenderer\n");
    474 #endif
    475     fflush(file);
    476     return nullptr;
    477 }
    478 
    479 void RenderProxy::dumpGraphicsMemory(int fd) {
    480     if (!RenderThread::hasInstance()) return;
    481     SETUP_TASK(dumpGraphicsMemory);
    482     args->fd = fd;
    483     args->thread = &RenderThread::getInstance();
    484     staticPostAndWait(task);
    485 }
    486 
    487 CREATE_BRIDGE4(setTextureAtlas, RenderThread* thread, GraphicBuffer* buffer, int64_t* map,
    488                size_t size) {
    489     CanvasContext::setTextureAtlas(*args->thread, args->buffer, args->map, args->size);
    490     args->buffer->decStrong(nullptr);
    491     return nullptr;
    492 }
    493 
    494 void RenderProxy::setTextureAtlas(const sp<GraphicBuffer>& buffer, int64_t* map, size_t size) {
    495     SETUP_TASK(setTextureAtlas);
    496     args->thread = &mRenderThread;
    497     args->buffer = buffer.get();
    498     args->buffer->incStrong(nullptr);
    499     args->map = map;
    500     args->size = size;
    501     post(task);
    502 }
    503 
    504 CREATE_BRIDGE2(setProcessStatsBuffer, RenderThread* thread, int fd) {
    505     args->thread->jankTracker().switchStorageToAshmem(args->fd);
    506     close(args->fd);
    507     return nullptr;
    508 }
    509 
    510 void RenderProxy::setProcessStatsBuffer(int fd) {
    511     SETUP_TASK(setProcessStatsBuffer);
    512     args->thread = &mRenderThread;
    513     args->fd = dup(fd);
    514     post(task);
    515 }
    516 
    517 CREATE_BRIDGE3(addRenderNode, CanvasContext* context, RenderNode* node, bool placeFront) {
    518     args->context->addRenderNode(args->node, args->placeFront);
    519     return nullptr;
    520 }
    521 
    522 void RenderProxy::addRenderNode(RenderNode* node, bool placeFront) {
    523     SETUP_TASK(addRenderNode);
    524     args->context = mContext;
    525     args->node = node;
    526     args->placeFront = placeFront;
    527     post(task);
    528 }
    529 
    530 CREATE_BRIDGE2(removeRenderNode, CanvasContext* context, RenderNode* node) {
    531     args->context->removeRenderNode(args->node);
    532     return nullptr;
    533 }
    534 
    535 void RenderProxy::removeRenderNode(RenderNode* node) {
    536     SETUP_TASK(removeRenderNode);
    537     args->context = mContext;
    538     args->node = node;
    539     post(task);
    540 }
    541 
    542 CREATE_BRIDGE2(drawRenderNode, CanvasContext* context, RenderNode* node) {
    543     args->context->prepareAndDraw(args->node);
    544     return nullptr;
    545 }
    546 
    547 void RenderProxy::drawRenderNode(RenderNode* node) {
    548     SETUP_TASK(drawRenderNode);
    549     args->context = mContext;
    550     args->node = node;
    551     // Be pseudo-thread-safe and don't use any member variables
    552     staticPostAndWait(task);
    553 }
    554 
    555 CREATE_BRIDGE5(setContentDrawBounds, CanvasContext* context, int left, int top,
    556         int right, int bottom) {
    557     args->context->setContentDrawBounds(args->left, args->top, args->right, args->bottom);
    558     return nullptr;
    559 }
    560 
    561 void RenderProxy::setContentDrawBounds(int left, int top, int right, int bottom) {
    562     SETUP_TASK(setContentDrawBounds);
    563     args->context = mContext;
    564     args->left = left;
    565     args->top = top;
    566     args->right = right;
    567     args->bottom = bottom;
    568     staticPostAndWait(task);
    569 }
    570 
    571 CREATE_BRIDGE1(serializeDisplayListTree, CanvasContext* context) {
    572     args->context->serializeDisplayListTree();
    573     return nullptr;
    574 }
    575 
    576 void RenderProxy::serializeDisplayListTree() {
    577     SETUP_TASK(serializeDisplayListTree);
    578     args->context = mContext;
    579     post(task);
    580 }
    581 
    582 CREATE_BRIDGE2(addFrameMetricsObserver, CanvasContext* context,
    583         FrameMetricsObserver* frameStatsObserver) {
    584    args->context->addFrameMetricsObserver(args->frameStatsObserver);
    585    if (args->frameStatsObserver != nullptr) {
    586        args->frameStatsObserver->decStrong(args->context);
    587    }
    588    return nullptr;
    589 }
    590 
    591 void RenderProxy::addFrameMetricsObserver(FrameMetricsObserver* observer) {
    592     SETUP_TASK(addFrameMetricsObserver);
    593     args->context = mContext;
    594     args->frameStatsObserver = observer;
    595     if (observer != nullptr) {
    596         observer->incStrong(mContext);
    597     }
    598     post(task);
    599 }
    600 
    601 CREATE_BRIDGE2(removeFrameMetricsObserver, CanvasContext* context,
    602         FrameMetricsObserver* frameStatsObserver) {
    603    args->context->removeFrameMetricsObserver(args->frameStatsObserver);
    604    if (args->frameStatsObserver != nullptr) {
    605        args->frameStatsObserver->decStrong(args->context);
    606    }
    607    return nullptr;
    608 }
    609 
    610 void RenderProxy::removeFrameMetricsObserver(FrameMetricsObserver* observer) {
    611     SETUP_TASK(removeFrameMetricsObserver);
    612     args->context = mContext;
    613     args->frameStatsObserver = observer;
    614     if (observer != nullptr) {
    615         observer->incStrong(mContext);
    616     }
    617     post(task);
    618 }
    619 
    620 CREATE_BRIDGE3(copySurfaceInto, RenderThread* thread,
    621         Surface* surface, SkBitmap* bitmap) {
    622     return (void*) Readback::copySurfaceInto(*args->thread,
    623             *args->surface, args->bitmap);
    624 }
    625 
    626 int RenderProxy::copySurfaceInto(sp<Surface>& surface, SkBitmap* bitmap) {
    627     SETUP_TASK(copySurfaceInto);
    628     args->bitmap = bitmap;
    629     args->surface = surface.get();
    630     args->thread = &RenderThread::getInstance();
    631     return static_cast<int>(
    632             reinterpret_cast<intptr_t>( staticPostAndWait(task) ));
    633 }
    634 
    635 void RenderProxy::post(RenderTask* task) {
    636     mRenderThread.queue(task);
    637 }
    638 
    639 void* RenderProxy::postAndWait(MethodInvokeRenderTask* task) {
    640     void* retval;
    641     task->setReturnPtr(&retval);
    642     SignalingRenderTask syncTask(task, &mSyncMutex, &mSyncCondition);
    643     AutoMutex _lock(mSyncMutex);
    644     mRenderThread.queue(&syncTask);
    645     mSyncCondition.wait(mSyncMutex);
    646     return retval;
    647 }
    648 
    649 void* RenderProxy::staticPostAndWait(MethodInvokeRenderTask* task) {
    650     RenderThread& thread = RenderThread::getInstance();
    651     void* retval;
    652     task->setReturnPtr(&retval);
    653     thread.queueAndWait(task);
    654     return retval;
    655 }
    656 
    657 } /* namespace renderthread */
    658 } /* namespace uirenderer */
    659 } /* namespace android */
    660