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