RenderProxy.cpp revision 10dd0585c11dcedb5a271d54e645594f1d215d5c
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_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
190void 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
202CREATE_BRIDGE2(setLightCenter, CanvasContext* context, Vector3 lightCenter) {
203    args->context->setLightCenter(args->lightCenter);
204    return nullptr;
205}
206
207void RenderProxy::setLightCenter(const Vector3& lightCenter) {
208    SETUP_TASK(setLightCenter);
209    args->context = mContext;
210    args->lightCenter = lightCenter;
211    post(task);
212}
213
214CREATE_BRIDGE2(setOpaque, CanvasContext* context, bool opaque) {
215    args->context->setOpaque(args->opaque);
216    return nullptr;
217}
218
219void RenderProxy::setOpaque(bool opaque) {
220    SETUP_TASK(setOpaque);
221    args->context = mContext;
222    args->opaque = opaque;
223    post(task);
224}
225
226int64_t* RenderProxy::frameInfo() {
227    return mDrawFrameTask.frameInfo();
228}
229
230int RenderProxy::syncAndDrawFrame(TreeObserver* observer) {
231    return mDrawFrameTask.drawFrame(observer);
232}
233
234CREATE_BRIDGE2(destroy, CanvasContext* context, TreeObserver* observer) {
235    args->context->destroy(args->observer);
236    return nullptr;
237}
238
239void 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
249CREATE_BRIDGE2(invokeFunctor, RenderThread* thread, Functor* functor) {
250    CanvasContext::invokeFunctor(*args->thread, args->functor);
251    return nullptr;
252}
253
254void 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
270CREATE_BRIDGE2(runWithGlContext, CanvasContext* context, RenderTask* task) {
271    args->context->runWithGlContext(args->task);
272    return nullptr;
273}
274
275void RenderProxy::runWithGlContext(RenderTask* gltask) {
276    SETUP_TASK(runWithGlContext);
277    args->context = mContext;
278    args->task = gltask;
279    postAndWait(task);
280}
281
282CREATE_BRIDGE1(createTextureLayer, CanvasContext* context) {
283    Layer* layer = args->context->createTextureLayer();
284    if (!layer) return nullptr;
285    return new DeferredLayerUpdater(layer);
286}
287
288DeferredLayerUpdater* 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
296CREATE_BRIDGE3(buildLayer, CanvasContext* context, RenderNode* node, TreeObserver* observer) {
297    args->context->buildLayer(args->node, args->observer);
298    return nullptr;
299}
300
301void 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
309CREATE_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
315bool 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
323void RenderProxy::pushLayerUpdate(DeferredLayerUpdater* layer) {
324    mDrawFrameTask.pushLayerUpdate(layer);
325}
326
327void RenderProxy::cancelLayerUpdate(DeferredLayerUpdater* layer) {
328    mDrawFrameTask.removeLayerUpdate(layer);
329}
330
331CREATE_BRIDGE1(detachSurfaceTexture, DeferredLayerUpdater* layer) {
332    args->layer->detachSurfaceTexture();
333    return nullptr;
334}
335
336void RenderProxy::detachSurfaceTexture(DeferredLayerUpdater* layer) {
337    SETUP_TASK(detachSurfaceTexture);
338    args->layer = layer;
339    postAndWait(task);
340}
341
342CREATE_BRIDGE2(destroyHardwareResources, CanvasContext* context, TreeObserver* observer) {
343    args->context->destroyHardwareResources(args->observer);
344    return nullptr;
345}
346
347void RenderProxy::destroyHardwareResources(TreeObserver* observer) {
348    SETUP_TASK(destroyHardwareResources);
349    args->context = mContext;
350    args->observer = observer;
351    postAndWait(task);
352}
353
354CREATE_BRIDGE2(trimMemory, RenderThread* thread, int level) {
355    CanvasContext::trimMemory(*args->thread, args->level);
356    return nullptr;
357}
358
359void 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
370CREATE_BRIDGE2(overrideProperty, const char* name, const char* value) {
371    Properties::overrideProperty(args->name, args->value);
372    return nullptr;
373}
374
375void 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
382CREATE_BRIDGE0(fence) {
383    // Intentionally empty
384    return nullptr;
385}
386
387template <typename T>
388void UNUSED(T t) {}
389
390void RenderProxy::fence() {
391    SETUP_TASK(fence);
392    UNUSED(args);
393    postAndWait(task);
394}
395
396void RenderProxy::staticFence() {
397    SETUP_TASK(fence);
398    UNUSED(args);
399    staticPostAndWait(task);
400}
401
402CREATE_BRIDGE1(stopDrawing, CanvasContext* context) {
403    args->context->stopDrawing();
404    return nullptr;
405}
406
407void RenderProxy::stopDrawing() {
408    SETUP_TASK(stopDrawing);
409    args->context = mContext;
410    postAndWait(task);
411}
412
413CREATE_BRIDGE1(notifyFramePending, CanvasContext* context) {
414    args->context->notifyFramePending();
415    return nullptr;
416}
417
418void RenderProxy::notifyFramePending() {
419    SETUP_TASK(notifyFramePending);
420    args->context = mContext;
421    mRenderThread.queueAtFront(task);
422}
423
424CREATE_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
439void 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
448CREATE_BRIDGE1(resetProfileInfo, CanvasContext* context) {
449    args->context->resetFrameStats();
450    return nullptr;
451}
452
453void RenderProxy::resetProfileInfo() {
454    SETUP_TASK(resetProfileInfo);
455    args->context = mContext;
456    postAndWait(task);
457}
458
459CREATE_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
479void 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
487CREATE_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
494void 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
504CREATE_BRIDGE2(setProcessStatsBuffer, RenderThread* thread, int fd) {
505    args->thread->jankTracker().switchStorageToAshmem(args->fd);
506    close(args->fd);
507    return nullptr;
508}
509
510void RenderProxy::setProcessStatsBuffer(int fd) {
511    SETUP_TASK(setProcessStatsBuffer);
512    args->thread = &mRenderThread;
513    args->fd = dup(fd);
514    post(task);
515}
516
517CREATE_BRIDGE3(addRenderNode, CanvasContext* context, RenderNode* node, bool placeFront) {
518    args->context->addRenderNode(args->node, args->placeFront);
519    return nullptr;
520}
521
522void 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
530CREATE_BRIDGE2(removeRenderNode, CanvasContext* context, RenderNode* node) {
531    args->context->removeRenderNode(args->node);
532    return nullptr;
533}
534
535void RenderProxy::removeRenderNode(RenderNode* node) {
536    SETUP_TASK(removeRenderNode);
537    args->context = mContext;
538    args->node = node;
539    post(task);
540}
541
542CREATE_BRIDGE2(drawRenderNode, CanvasContext* context, RenderNode* node) {
543    args->context->prepareAndDraw(args->node);
544    return nullptr;
545}
546
547void 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
555CREATE_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
561void 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
571CREATE_BRIDGE1(serializeDisplayListTree, CanvasContext* context) {
572    args->context->serializeDisplayListTree();
573    return nullptr;
574}
575
576void RenderProxy::serializeDisplayListTree() {
577    SETUP_TASK(serializeDisplayListTree);
578    args->context = mContext;
579    post(task);
580}
581
582CREATE_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
591void 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
601CREATE_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
610void 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
620CREATE_BRIDGE3(copySurfaceInto, RenderThread* thread,
621        Surface* surface, SkBitmap* bitmap) {
622    return (void*) Readback::copySurfaceInto(*args->thread,
623            *args->surface, args->bitmap);
624}
625
626bool 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 (bool) staticPostAndWait(task);
632}
633
634void RenderProxy::post(RenderTask* task) {
635    mRenderThread.queue(task);
636}
637
638void* RenderProxy::postAndWait(MethodInvokeRenderTask* task) {
639    void* retval;
640    task->setReturnPtr(&retval);
641    SignalingRenderTask syncTask(task, &mSyncMutex, &mSyncCondition);
642    AutoMutex _lock(mSyncMutex);
643    mRenderThread.queue(&syncTask);
644    mSyncCondition.wait(mSyncMutex);
645    return retval;
646}
647
648void* RenderProxy::staticPostAndWait(MethodInvokeRenderTask* task) {
649    RenderThread& thread = RenderThread::getInstance();
650    void* retval;
651    task->setReturnPtr(&retval);
652    thread.queueAndWait(task);
653    return retval;
654}
655
656} /* namespace renderthread */
657} /* namespace uirenderer */
658} /* namespace android */
659