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