RenderProxy.cpp revision 4f02bf4eef6af47f35c70c4dda5b7b9523d89ca0
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#define LOG_TAG "RenderProxy"
18
19#include "RenderProxy.h"
20
21#include "CanvasContext.h"
22#include "RenderTask.h"
23#include "RenderThread.h"
24
25#include "../DisplayList.h"
26#include "../Rect.h"
27
28namespace android {
29namespace uirenderer {
30namespace renderthread {
31
32#define ARGS(method) method ## Args
33
34#define CREATE_BRIDGE1(name, a1) CREATE_BRIDGE(name, a1,,,,,,,)
35#define CREATE_BRIDGE2(name, a1, a2) CREATE_BRIDGE(name, a1,a2,,,,,,)
36#define CREATE_BRIDGE3(name, a1, a2, a3) CREATE_BRIDGE(name, a1,a2,a3,,,,,)
37#define CREATE_BRIDGE4(name, a1, a2, a3, a4) CREATE_BRIDGE(name, a1,a2,a3,a4,,,,)
38#define CREATE_BRIDGE(name, a1, a2, a3, a4, a5, a6, a7, a8) \
39    typedef struct { \
40        a1; a2; a3; a4; a5; a6; a7; a8; \
41    } ARGS(name); \
42    static void* Bridge_ ## name(ARGS(name)* args)
43
44#define SETUP_TASK(method) \
45    LOG_ALWAYS_FATAL_IF( METHOD_INVOKE_PAYLOAD_SIZE < sizeof(ARGS(method)), \
46        "METHOD_INVOKE_PAYLOAD_SIZE %d is smaller than sizeof(" #method "Args) %d", \
47                METHOD_INVOKE_PAYLOAD_SIZE, sizeof(ARGS(method))); \
48    MethodInvokeRenderTask* task = createTask((RunnableMethod) Bridge_ ## method); \
49    ARGS(method) *args = (ARGS(method) *) task->payload()
50
51CREATE_BRIDGE1(createContext, bool translucent) {
52    return new CanvasContext(args->translucent);
53}
54
55RenderProxy::RenderProxy(bool translucent)
56        : mRenderThread(RenderThread::getInstance())
57        , mContext(0) {
58    SETUP_TASK(createContext);
59    args->translucent = translucent;
60    mContext = (CanvasContext*) postAndWait(task);
61}
62
63RenderProxy::~RenderProxy() {
64    destroyContext();
65}
66
67CREATE_BRIDGE1(destroyContext, CanvasContext* context) {
68    delete args->context;
69    return NULL;
70}
71
72void RenderProxy::destroyContext() {
73    if (mContext) {
74        SETUP_TASK(destroyContext);
75        args->context = mContext;
76        mContext = 0;
77        post(task);
78    }
79}
80
81CREATE_BRIDGE2(initialize, CanvasContext* context, EGLNativeWindowType window) {
82    return (void*) args->context->initialize(args->window);
83}
84
85bool RenderProxy::initialize(EGLNativeWindowType window) {
86    SETUP_TASK(initialize);
87    args->context = mContext;
88    args->window = window;
89    return (bool) postAndWait(task);
90}
91
92CREATE_BRIDGE2(updateSurface, CanvasContext* context, EGLNativeWindowType window) {
93    args->context->updateSurface(args->window);
94    return NULL;
95}
96
97void RenderProxy::updateSurface(EGLNativeWindowType window) {
98    SETUP_TASK(updateSurface);
99    args->context = mContext;
100    args->window = window;
101    post(task);
102}
103
104CREATE_BRIDGE3(setup, CanvasContext* context, int width, int height) {
105    args->context->setup(args->width, args->height);
106    return NULL;
107}
108
109void RenderProxy::setup(int width, int height) {
110    SETUP_TASK(setup);
111    args->context = mContext;
112    args->width = width;
113    args->height = height;
114    post(task);
115}
116
117CREATE_BRIDGE3(drawDisplayList, CanvasContext* context, DisplayList* displayList,
118        Rect dirty) {
119    Rect* dirty = &args->dirty;
120    if (dirty->bottom == -1 && dirty->left == -1 &&
121            dirty->top == -1 && dirty->right == -1) {
122        dirty = 0;
123    }
124    args->context->drawDisplayList(args->displayList, dirty);
125    return NULL;
126}
127
128void RenderProxy::drawDisplayList(DisplayList* displayList,
129        int dirtyLeft, int dirtyTop, int dirtyRight, int dirtyBottom) {
130    SETUP_TASK(drawDisplayList);
131    args->context = mContext;
132    args->displayList = displayList;
133    args->dirty.set(dirtyLeft, dirtyTop, dirtyRight, dirtyBottom);
134    // TODO: Switch to post() once some form of thread safety strategy is in place
135    postAndWait(task);
136}
137
138CREATE_BRIDGE1(destroyCanvas, CanvasContext* context) {
139    args->context->destroyCanvas();
140    return NULL;
141}
142
143void RenderProxy::destroyCanvas() {
144    SETUP_TASK(destroyCanvas);
145    args->context = mContext;
146    post(task);
147}
148
149CREATE_BRIDGE2(attachFunctor, CanvasContext* context, Functor* functor) {
150    args->context->attachFunctor(args->functor);
151    return NULL;
152}
153
154void RenderProxy::attachFunctor(Functor* functor) {
155    SETUP_TASK(attachFunctor);
156    args->context = mContext;
157    args->functor = functor;
158    post(task);
159}
160
161CREATE_BRIDGE2(detachFunctor, CanvasContext* context, Functor* functor) {
162    args->context->detachFunctor(args->functor);
163    return NULL;
164}
165
166void RenderProxy::detachFunctor(Functor* functor) {
167    SETUP_TASK(detachFunctor);
168    args->context = mContext;
169    args->functor = functor;
170    post(task);
171}
172
173MethodInvokeRenderTask* RenderProxy::createTask(RunnableMethod method) {
174    // TODO: Consider having a small pool of these to avoid alloc churn
175    return new MethodInvokeRenderTask(method);
176}
177
178void RenderProxy::post(RenderTask* task) {
179    mRenderThread.queue(task);
180}
181
182void* RenderProxy::postAndWait(MethodInvokeRenderTask* task) {
183    void* retval;
184    task->setReturnPtr(&retval);
185    SignalingRenderTask syncTask(task, &mSyncMutex, &mSyncCondition);
186    AutoMutex _lock(mSyncMutex);
187    mRenderThread.queue(&syncTask);
188    mSyncCondition.wait(mSyncMutex);
189    return retval;
190}
191
192} /* namespace renderthread */
193} /* namespace uirenderer */
194} /* namespace android */
195