RenderProxy.cpp revision 05357641d398ef77d880da387a230820ab3203fe
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_BRIDGE1(createTextureLayer, CanvasContext* context) {
269    Layer* layer = args->context->createTextureLayer();
270    if (!layer) return nullptr;
271    return new DeferredLayerUpdater(layer);
272}
273
274DeferredLayerUpdater* RenderProxy::createTextureLayer() {
275    SETUP_TASK(createTextureLayer);
276    args->context = mContext;
277    void* retval = postAndWait(task);
278    DeferredLayerUpdater* layer = reinterpret_cast<DeferredLayerUpdater*>(retval);
279    return layer;
280}
281
282CREATE_BRIDGE3(buildLayer, CanvasContext* context, RenderNode* node, TreeObserver* observer) {
283    args->context->buildLayer(args->node, args->observer);
284    return nullptr;
285}
286
287void RenderProxy::buildLayer(RenderNode* node, TreeObserver* observer) {
288    SETUP_TASK(buildLayer);
289    args->context = mContext;
290    args->node = node;
291    args->observer = observer;
292    postAndWait(task);
293}
294
295CREATE_BRIDGE3(copyLayerInto, CanvasContext* context, DeferredLayerUpdater* layer,
296        SkBitmap* bitmap) {
297    bool success = args->context->copyLayerInto(args->layer, args->bitmap);
298    return (void*) success;
299}
300
301bool RenderProxy::copyLayerInto(DeferredLayerUpdater* layer, SkBitmap& bitmap) {
302    SETUP_TASK(copyLayerInto);
303    args->context = mContext;
304    args->layer = layer;
305    args->bitmap = &bitmap;
306    return (bool) postAndWait(task);
307}
308
309void RenderProxy::pushLayerUpdate(DeferredLayerUpdater* layer) {
310    mDrawFrameTask.pushLayerUpdate(layer);
311}
312
313void RenderProxy::cancelLayerUpdate(DeferredLayerUpdater* layer) {
314    mDrawFrameTask.removeLayerUpdate(layer);
315}
316
317CREATE_BRIDGE1(detachSurfaceTexture, DeferredLayerUpdater* layer) {
318    args->layer->detachSurfaceTexture();
319    return nullptr;
320}
321
322void RenderProxy::detachSurfaceTexture(DeferredLayerUpdater* layer) {
323    SETUP_TASK(detachSurfaceTexture);
324    args->layer = layer;
325    postAndWait(task);
326}
327
328CREATE_BRIDGE2(destroyHardwareResources, CanvasContext* context, TreeObserver* observer) {
329    args->context->destroyHardwareResources(args->observer);
330    return nullptr;
331}
332
333void RenderProxy::destroyHardwareResources(TreeObserver* observer) {
334    SETUP_TASK(destroyHardwareResources);
335    args->context = mContext;
336    args->observer = observer;
337    postAndWait(task);
338}
339
340CREATE_BRIDGE2(trimMemory, RenderThread* thread, int level) {
341    CanvasContext::trimMemory(*args->thread, args->level);
342    return nullptr;
343}
344
345void RenderProxy::trimMemory(int level) {
346    // Avoid creating a RenderThread to do a trimMemory.
347    if (RenderThread::hasInstance()) {
348        RenderThread& thread = RenderThread::getInstance();
349        SETUP_TASK(trimMemory);
350        args->thread = &thread;
351        args->level = level;
352        thread.queue(task);
353    }
354}
355
356CREATE_BRIDGE2(overrideProperty, const char* name, const char* value) {
357    Properties::overrideProperty(args->name, args->value);
358    return nullptr;
359}
360
361void RenderProxy::overrideProperty(const char* name, const char* value) {
362    SETUP_TASK(overrideProperty);
363    args->name = name;
364    args->value = value;
365    staticPostAndWait(task); // expensive, but block here since name/value pointers owned by caller
366}
367
368CREATE_BRIDGE0(fence) {
369    // Intentionally empty
370    return nullptr;
371}
372
373template <typename T>
374void UNUSED(T t) {}
375
376void RenderProxy::fence() {
377    SETUP_TASK(fence);
378    UNUSED(args);
379    postAndWait(task);
380}
381
382void RenderProxy::staticFence() {
383    SETUP_TASK(fence);
384    UNUSED(args);
385    staticPostAndWait(task);
386}
387
388CREATE_BRIDGE1(stopDrawing, CanvasContext* context) {
389    args->context->stopDrawing();
390    return nullptr;
391}
392
393void RenderProxy::stopDrawing() {
394    SETUP_TASK(stopDrawing);
395    args->context = mContext;
396    postAndWait(task);
397}
398
399CREATE_BRIDGE1(notifyFramePending, CanvasContext* context) {
400    args->context->notifyFramePending();
401    return nullptr;
402}
403
404void RenderProxy::notifyFramePending() {
405    SETUP_TASK(notifyFramePending);
406    args->context = mContext;
407    mRenderThread.queueAtFront(task);
408}
409
410CREATE_BRIDGE4(dumpProfileInfo, CanvasContext* context, RenderThread* thread,
411        int fd, int dumpFlags) {
412    args->context->profiler().dumpData(args->fd);
413    if (args->dumpFlags & DumpFlags::FrameStats) {
414        args->context->dumpFrames(args->fd);
415    }
416    if (args->dumpFlags & DumpFlags::Reset) {
417        args->context->resetFrameStats();
418    }
419    if (args->dumpFlags & DumpFlags::JankStats) {
420        args->thread->jankTracker().dump(args->fd);
421    }
422    return nullptr;
423}
424
425void RenderProxy::dumpProfileInfo(int fd, int dumpFlags) {
426    SETUP_TASK(dumpProfileInfo);
427    args->context = mContext;
428    args->thread = &mRenderThread;
429    args->fd = fd;
430    args->dumpFlags = dumpFlags;
431    postAndWait(task);
432}
433
434CREATE_BRIDGE1(resetProfileInfo, CanvasContext* context) {
435    args->context->resetFrameStats();
436    return nullptr;
437}
438
439void RenderProxy::resetProfileInfo() {
440    SETUP_TASK(resetProfileInfo);
441    args->context = mContext;
442    postAndWait(task);
443}
444
445CREATE_BRIDGE2(dumpGraphicsMemory, int fd, RenderThread* thread) {
446    args->thread->jankTracker().dump(args->fd);
447
448    FILE *file = fdopen(args->fd, "a");
449    if (Caches::hasInstance()) {
450        String8 cachesLog;
451        Caches::getInstance().dumpMemoryUsage(cachesLog);
452        fprintf(file, "\nCaches:\n%s\n", cachesLog.string());
453    } else {
454        fprintf(file, "\nNo caches instance.\n");
455    }
456#if HWUI_NEW_OPS
457    fprintf(file, "\nPipeline=FrameBuilder\n");
458#else
459    fprintf(file, "\nPipeline=OpenGLRenderer\n");
460#endif
461    fflush(file);
462    return nullptr;
463}
464
465void RenderProxy::dumpGraphicsMemory(int fd) {
466    if (!RenderThread::hasInstance()) return;
467    SETUP_TASK(dumpGraphicsMemory);
468    args->fd = fd;
469    args->thread = &RenderThread::getInstance();
470    staticPostAndWait(task);
471}
472
473CREATE_BRIDGE4(setTextureAtlas, RenderThread* thread, GraphicBuffer* buffer, int64_t* map,
474               size_t size) {
475    CanvasContext::setTextureAtlas(*args->thread, args->buffer, args->map, args->size);
476    args->buffer->decStrong(nullptr);
477    return nullptr;
478}
479
480void RenderProxy::setTextureAtlas(const sp<GraphicBuffer>& buffer, int64_t* map, size_t size) {
481    SETUP_TASK(setTextureAtlas);
482    args->thread = &mRenderThread;
483    args->buffer = buffer.get();
484    args->buffer->incStrong(nullptr);
485    args->map = map;
486    args->size = size;
487    post(task);
488}
489
490CREATE_BRIDGE2(setProcessStatsBuffer, RenderThread* thread, int fd) {
491    args->thread->jankTracker().switchStorageToAshmem(args->fd);
492    close(args->fd);
493    return nullptr;
494}
495
496void RenderProxy::setProcessStatsBuffer(int fd) {
497    SETUP_TASK(setProcessStatsBuffer);
498    args->thread = &mRenderThread;
499    args->fd = dup(fd);
500    post(task);
501}
502
503CREATE_BRIDGE3(addRenderNode, CanvasContext* context, RenderNode* node, bool placeFront) {
504    args->context->addRenderNode(args->node, args->placeFront);
505    return nullptr;
506}
507
508void RenderProxy::addRenderNode(RenderNode* node, bool placeFront) {
509    SETUP_TASK(addRenderNode);
510    args->context = mContext;
511    args->node = node;
512    args->placeFront = placeFront;
513    post(task);
514}
515
516CREATE_BRIDGE2(removeRenderNode, CanvasContext* context, RenderNode* node) {
517    args->context->removeRenderNode(args->node);
518    return nullptr;
519}
520
521void RenderProxy::removeRenderNode(RenderNode* node) {
522    SETUP_TASK(removeRenderNode);
523    args->context = mContext;
524    args->node = node;
525    post(task);
526}
527
528CREATE_BRIDGE2(drawRenderNode, CanvasContext* context, RenderNode* node) {
529    args->context->prepareAndDraw(args->node);
530    return nullptr;
531}
532
533void RenderProxy::drawRenderNode(RenderNode* node) {
534    SETUP_TASK(drawRenderNode);
535    args->context = mContext;
536    args->node = node;
537    // Be pseudo-thread-safe and don't use any member variables
538    staticPostAndWait(task);
539}
540
541CREATE_BRIDGE5(setContentDrawBounds, CanvasContext* context, int left, int top,
542        int right, int bottom) {
543    args->context->setContentDrawBounds(args->left, args->top, args->right, args->bottom);
544    return nullptr;
545}
546
547void RenderProxy::setContentDrawBounds(int left, int top, int right, int bottom) {
548    SETUP_TASK(setContentDrawBounds);
549    args->context = mContext;
550    args->left = left;
551    args->top = top;
552    args->right = right;
553    args->bottom = bottom;
554    staticPostAndWait(task);
555}
556
557CREATE_BRIDGE1(serializeDisplayListTree, CanvasContext* context) {
558    args->context->serializeDisplayListTree();
559    return nullptr;
560}
561
562void RenderProxy::serializeDisplayListTree() {
563    SETUP_TASK(serializeDisplayListTree);
564    args->context = mContext;
565    post(task);
566}
567
568CREATE_BRIDGE2(addFrameMetricsObserver, CanvasContext* context,
569        FrameMetricsObserver* frameStatsObserver) {
570   args->context->addFrameMetricsObserver(args->frameStatsObserver);
571   if (args->frameStatsObserver != nullptr) {
572       args->frameStatsObserver->decStrong(args->context);
573   }
574   return nullptr;
575}
576
577void RenderProxy::addFrameMetricsObserver(FrameMetricsObserver* observer) {
578    SETUP_TASK(addFrameMetricsObserver);
579    args->context = mContext;
580    args->frameStatsObserver = observer;
581    if (observer != nullptr) {
582        observer->incStrong(mContext);
583    }
584    post(task);
585}
586
587CREATE_BRIDGE2(removeFrameMetricsObserver, CanvasContext* context,
588        FrameMetricsObserver* frameStatsObserver) {
589   args->context->removeFrameMetricsObserver(args->frameStatsObserver);
590   if (args->frameStatsObserver != nullptr) {
591       args->frameStatsObserver->decStrong(args->context);
592   }
593   return nullptr;
594}
595
596void RenderProxy::removeFrameMetricsObserver(FrameMetricsObserver* observer) {
597    SETUP_TASK(removeFrameMetricsObserver);
598    args->context = mContext;
599    args->frameStatsObserver = observer;
600    if (observer != nullptr) {
601        observer->incStrong(mContext);
602    }
603    post(task);
604}
605
606CREATE_BRIDGE3(copySurfaceInto, RenderThread* thread,
607        Surface* surface, SkBitmap* bitmap) {
608    return (void*) Readback::copySurfaceInto(*args->thread,
609            *args->surface, args->bitmap);
610}
611
612int RenderProxy::copySurfaceInto(sp<Surface>& surface, SkBitmap* bitmap) {
613    SETUP_TASK(copySurfaceInto);
614    args->bitmap = bitmap;
615    args->surface = surface.get();
616    args->thread = &RenderThread::getInstance();
617    return static_cast<int>(
618            reinterpret_cast<intptr_t>( staticPostAndWait(task) ));
619}
620
621void RenderProxy::post(RenderTask* task) {
622    mRenderThread.queue(task);
623}
624
625void* RenderProxy::postAndWait(MethodInvokeRenderTask* task) {
626    void* retval;
627    task->setReturnPtr(&retval);
628    SignalingRenderTask syncTask(task, &mSyncMutex, &mSyncCondition);
629    AutoMutex _lock(mSyncMutex);
630    mRenderThread.queue(&syncTask);
631    mSyncCondition.wait(mSyncMutex);
632    return retval;
633}
634
635void* RenderProxy::staticPostAndWait(MethodInvokeRenderTask* task) {
636    RenderThread& thread = RenderThread::getInstance();
637    void* retval;
638    task->setReturnPtr(&retval);
639    thread.queueAndWait(task);
640    return retval;
641}
642
643} /* namespace renderthread */
644} /* namespace uirenderer */
645} /* namespace android */
646