• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 "CanvasContext.h"
20 #include "RenderTask.h"
21 #include "RenderThread.h"
22 
23 #include "../DeferredLayerUpdater.h"
24 #include "../DisplayList.h"
25 #include "../LayerRenderer.h"
26 #include "../Rect.h"
27 
28 namespace android {
29 namespace uirenderer {
30 namespace renderthread {
31 
32 #define ARGS(method) method ## Args
33 
34 #define CREATE_BRIDGE0(name) CREATE_BRIDGE(name,,,,,,,,)
35 #define CREATE_BRIDGE1(name, a1) CREATE_BRIDGE(name, a1,,,,,,,)
36 #define CREATE_BRIDGE2(name, a1, a2) CREATE_BRIDGE(name, a1,a2,,,,,,)
37 #define CREATE_BRIDGE3(name, a1, a2, a3) CREATE_BRIDGE(name, a1,a2,a3,,,,,)
38 #define CREATE_BRIDGE4(name, a1, a2, a3, a4) CREATE_BRIDGE(name, a1,a2,a3,a4,,,,)
39 #define CREATE_BRIDGE5(name, a1, a2, a3, a4, a5) CREATE_BRIDGE(name, a1,a2,a3,a4,a5,,,)
40 #define CREATE_BRIDGE6(name, a1, a2, a3, a4, a5, a6) CREATE_BRIDGE(name, a1,a2,a3,a4,a5,a6,,)
41 #define CREATE_BRIDGE7(name, a1, a2, a3, a4, a5, a6, a7) CREATE_BRIDGE(name, a1,a2,a3,a4,a5,a6,a7,)
42 #define CREATE_BRIDGE(name, a1, a2, a3, a4, a5, a6, a7, a8) \
43     typedef struct { \
44         a1; a2; a3; a4; a5; a6; a7; a8; \
45     } ARGS(name); \
46     static void* Bridge_ ## name(ARGS(name)* args)
47 
48 #define SETUP_TASK(method) \
49     LOG_ALWAYS_FATAL_IF( METHOD_INVOKE_PAYLOAD_SIZE < sizeof(ARGS(method)), \
50         "METHOD_INVOKE_PAYLOAD_SIZE %zu is smaller than sizeof(" #method "Args) %zu", \
51                 METHOD_INVOKE_PAYLOAD_SIZE, sizeof(ARGS(method))); \
52     MethodInvokeRenderTask* task = new MethodInvokeRenderTask((RunnableMethod) Bridge_ ## method); \
53     ARGS(method) *args = (ARGS(method) *) task->payload()
54 
CREATE_BRIDGE4(createContext,RenderThread * thread,bool translucent,RenderNode * rootRenderNode,IContextFactory * contextFactory)55 CREATE_BRIDGE4(createContext, RenderThread* thread, bool translucent,
56         RenderNode* rootRenderNode, IContextFactory* contextFactory) {
57     return new CanvasContext(*args->thread, args->translucent,
58             args->rootRenderNode, args->contextFactory);
59 }
60 
RenderProxy(bool translucent,RenderNode * rootRenderNode,IContextFactory * contextFactory)61 RenderProxy::RenderProxy(bool translucent, RenderNode* rootRenderNode, IContextFactory* contextFactory)
62         : mRenderThread(RenderThread::getInstance())
63         , mContext(0) {
64     SETUP_TASK(createContext);
65     args->translucent = translucent;
66     args->rootRenderNode = rootRenderNode;
67     args->thread = &mRenderThread;
68     args->contextFactory = contextFactory;
69     mContext = (CanvasContext*) postAndWait(task);
70     mDrawFrameTask.setContext(&mRenderThread, mContext);
71 }
72 
~RenderProxy()73 RenderProxy::~RenderProxy() {
74     destroyContext();
75 }
76 
CREATE_BRIDGE1(destroyContext,CanvasContext * context)77 CREATE_BRIDGE1(destroyContext, CanvasContext* context) {
78     delete args->context;
79     return NULL;
80 }
81 
destroyContext()82 void RenderProxy::destroyContext() {
83     if (mContext) {
84         SETUP_TASK(destroyContext);
85         args->context = mContext;
86         mContext = 0;
87         mDrawFrameTask.setContext(NULL, NULL);
88         // This is also a fence as we need to be certain that there are no
89         // outstanding mDrawFrame tasks posted before it is destroyed
90         postAndWait(task);
91     }
92 }
93 
CREATE_BRIDGE2(setFrameInterval,RenderThread * thread,nsecs_t frameIntervalNanos)94 CREATE_BRIDGE2(setFrameInterval, RenderThread* thread, nsecs_t frameIntervalNanos) {
95     args->thread->timeLord().setFrameInterval(args->frameIntervalNanos);
96     return NULL;
97 }
98 
setFrameInterval(nsecs_t frameIntervalNanos)99 void RenderProxy::setFrameInterval(nsecs_t frameIntervalNanos) {
100     SETUP_TASK(setFrameInterval);
101     args->thread = &mRenderThread;
102     args->frameIntervalNanos = frameIntervalNanos;
103     post(task);
104 }
105 
CREATE_BRIDGE2(setSwapBehavior,CanvasContext * context,SwapBehavior swapBehavior)106 CREATE_BRIDGE2(setSwapBehavior, CanvasContext* context, SwapBehavior swapBehavior) {
107     args->context->setSwapBehavior(args->swapBehavior);
108     return NULL;
109 }
110 
setSwapBehavior(SwapBehavior swapBehavior)111 void RenderProxy::setSwapBehavior(SwapBehavior swapBehavior) {
112     SETUP_TASK(setSwapBehavior);
113     args->context = mContext;
114     args->swapBehavior = swapBehavior;
115     post(task);
116 }
117 
CREATE_BRIDGE1(loadSystemProperties,CanvasContext * context)118 CREATE_BRIDGE1(loadSystemProperties, CanvasContext* context) {
119     bool needsRedraw = false;
120     if (Caches::hasInstance()) {
121         needsRedraw = Caches::getInstance().initProperties();
122     }
123     if (args->context->profiler().loadSystemProperties()) {
124         needsRedraw = true;
125     }
126     return (void*) needsRedraw;
127 }
128 
loadSystemProperties()129 bool RenderProxy::loadSystemProperties() {
130     SETUP_TASK(loadSystemProperties);
131     args->context = mContext;
132     return (bool) postAndWait(task);
133 }
134 
CREATE_BRIDGE2(initialize,CanvasContext * context,ANativeWindow * window)135 CREATE_BRIDGE2(initialize, CanvasContext* context, ANativeWindow* window) {
136     return (void*) args->context->initialize(args->window);
137 }
138 
initialize(const sp<ANativeWindow> & window)139 bool RenderProxy::initialize(const sp<ANativeWindow>& window) {
140     SETUP_TASK(initialize);
141     args->context = mContext;
142     args->window = window.get();
143     return (bool) postAndWait(task);
144 }
145 
CREATE_BRIDGE2(updateSurface,CanvasContext * context,ANativeWindow * window)146 CREATE_BRIDGE2(updateSurface, CanvasContext* context, ANativeWindow* window) {
147     args->context->updateSurface(args->window);
148     return NULL;
149 }
150 
updateSurface(const sp<ANativeWindow> & window)151 void RenderProxy::updateSurface(const sp<ANativeWindow>& window) {
152     SETUP_TASK(updateSurface);
153     args->context = mContext;
154     args->window = window.get();
155     postAndWait(task);
156 }
157 
CREATE_BRIDGE2(pauseSurface,CanvasContext * context,ANativeWindow * window)158 CREATE_BRIDGE2(pauseSurface, CanvasContext* context, ANativeWindow* window) {
159     return (void*) args->context->pauseSurface(args->window);
160 }
161 
pauseSurface(const sp<ANativeWindow> & window)162 bool RenderProxy::pauseSurface(const sp<ANativeWindow>& window) {
163     SETUP_TASK(pauseSurface);
164     args->context = mContext;
165     args->window = window.get();
166     return (bool) postAndWait(task);
167 }
168 
CREATE_BRIDGE7(setup,CanvasContext * context,int width,int height,Vector3 lightCenter,float lightRadius,uint8_t ambientShadowAlpha,uint8_t spotShadowAlpha)169 CREATE_BRIDGE7(setup, CanvasContext* context, int width, int height,
170         Vector3 lightCenter, float lightRadius,
171         uint8_t ambientShadowAlpha, uint8_t spotShadowAlpha) {
172     args->context->setup(args->width, args->height, args->lightCenter, args->lightRadius,
173             args->ambientShadowAlpha, args->spotShadowAlpha);
174     return NULL;
175 }
176 
setup(int width,int height,const Vector3 & lightCenter,float lightRadius,uint8_t ambientShadowAlpha,uint8_t spotShadowAlpha)177 void RenderProxy::setup(int width, int height, const Vector3& lightCenter, float lightRadius,
178         uint8_t ambientShadowAlpha, uint8_t spotShadowAlpha) {
179     SETUP_TASK(setup);
180     args->context = mContext;
181     args->width = width;
182     args->height = height;
183     args->lightCenter = lightCenter;
184     args->lightRadius = lightRadius;
185     args->ambientShadowAlpha = ambientShadowAlpha;
186     args->spotShadowAlpha = spotShadowAlpha;
187     post(task);
188 }
189 
CREATE_BRIDGE2(setOpaque,CanvasContext * context,bool opaque)190 CREATE_BRIDGE2(setOpaque, CanvasContext* context, bool opaque) {
191     args->context->setOpaque(args->opaque);
192     return NULL;
193 }
194 
setOpaque(bool opaque)195 void RenderProxy::setOpaque(bool opaque) {
196     SETUP_TASK(setOpaque);
197     args->context = mContext;
198     args->opaque = opaque;
199     post(task);
200 }
201 
syncAndDrawFrame(nsecs_t frameTimeNanos,nsecs_t recordDurationNanos,float density)202 int RenderProxy::syncAndDrawFrame(nsecs_t frameTimeNanos, nsecs_t recordDurationNanos,
203         float density) {
204     mDrawFrameTask.setDensity(density);
205     return mDrawFrameTask.drawFrame(frameTimeNanos, recordDurationNanos);
206 }
207 
CREATE_BRIDGE1(destroy,CanvasContext * context)208 CREATE_BRIDGE1(destroy, CanvasContext* context) {
209     args->context->destroy();
210     return NULL;
211 }
212 
destroy()213 void RenderProxy::destroy() {
214     SETUP_TASK(destroy);
215     args->context = mContext;
216     // destroyCanvasAndSurface() needs a fence as when it returns the
217     // underlying BufferQueue is going to be released from under
218     // the render thread.
219     postAndWait(task);
220 }
221 
CREATE_BRIDGE2(invokeFunctor,RenderThread * thread,Functor * functor)222 CREATE_BRIDGE2(invokeFunctor, RenderThread* thread, Functor* functor) {
223     CanvasContext::invokeFunctor(*args->thread, args->functor);
224     return NULL;
225 }
226 
invokeFunctor(Functor * functor,bool waitForCompletion)227 void RenderProxy::invokeFunctor(Functor* functor, bool waitForCompletion) {
228     ATRACE_CALL();
229     RenderThread& thread = RenderThread::getInstance();
230     SETUP_TASK(invokeFunctor);
231     args->thread = &thread;
232     args->functor = functor;
233     if (waitForCompletion) {
234         // waitForCompletion = true is expected to be fairly rare and only
235         // happen in destruction. Thus it should be fine to temporarily
236         // create a Mutex
237         staticPostAndWait(task);
238     } else {
239         thread.queue(task);
240     }
241 }
242 
CREATE_BRIDGE2(runWithGlContext,CanvasContext * context,RenderTask * task)243 CREATE_BRIDGE2(runWithGlContext, CanvasContext* context, RenderTask* task) {
244     args->context->runWithGlContext(args->task);
245     return NULL;
246 }
247 
runWithGlContext(RenderTask * gltask)248 void RenderProxy::runWithGlContext(RenderTask* gltask) {
249     SETUP_TASK(runWithGlContext);
250     args->context = mContext;
251     args->task = gltask;
252     postAndWait(task);
253 }
254 
CREATE_BRIDGE2(createTextureLayer,RenderThread * thread,CanvasContext * context)255 CREATE_BRIDGE2(createTextureLayer, RenderThread* thread, CanvasContext* context) {
256     Layer* layer = args->context->createTextureLayer();
257     if (!layer) return 0;
258     return new DeferredLayerUpdater(*args->thread, layer);
259 }
260 
createTextureLayer()261 DeferredLayerUpdater* RenderProxy::createTextureLayer() {
262     SETUP_TASK(createTextureLayer);
263     args->context = mContext;
264     args->thread = &mRenderThread;
265     void* retval = postAndWait(task);
266     DeferredLayerUpdater* layer = reinterpret_cast<DeferredLayerUpdater*>(retval);
267     return layer;
268 }
269 
CREATE_BRIDGE2(buildLayer,CanvasContext * context,RenderNode * node)270 CREATE_BRIDGE2(buildLayer, CanvasContext* context, RenderNode* node) {
271     args->context->buildLayer(args->node);
272     return NULL;
273 }
274 
buildLayer(RenderNode * node)275 void RenderProxy::buildLayer(RenderNode* node) {
276     SETUP_TASK(buildLayer);
277     args->context = mContext;
278     args->node = node;
279     postAndWait(task);
280 }
281 
CREATE_BRIDGE3(copyLayerInto,CanvasContext * context,DeferredLayerUpdater * layer,SkBitmap * bitmap)282 CREATE_BRIDGE3(copyLayerInto, CanvasContext* context, DeferredLayerUpdater* layer,
283         SkBitmap* bitmap) {
284     bool success = args->context->copyLayerInto(args->layer, args->bitmap);
285     return (void*) success;
286 }
287 
copyLayerInto(DeferredLayerUpdater * layer,SkBitmap * bitmap)288 bool RenderProxy::copyLayerInto(DeferredLayerUpdater* layer, SkBitmap* bitmap) {
289     SETUP_TASK(copyLayerInto);
290     args->context = mContext;
291     args->layer = layer;
292     args->bitmap = bitmap;
293     return (bool) postAndWait(task);
294 }
295 
pushLayerUpdate(DeferredLayerUpdater * layer)296 void RenderProxy::pushLayerUpdate(DeferredLayerUpdater* layer) {
297     mDrawFrameTask.pushLayerUpdate(layer);
298 }
299 
cancelLayerUpdate(DeferredLayerUpdater * layer)300 void RenderProxy::cancelLayerUpdate(DeferredLayerUpdater* layer) {
301     mDrawFrameTask.removeLayerUpdate(layer);
302 }
303 
CREATE_BRIDGE1(detachSurfaceTexture,DeferredLayerUpdater * layer)304 CREATE_BRIDGE1(detachSurfaceTexture, DeferredLayerUpdater* layer) {
305     args->layer->detachSurfaceTexture();
306     return NULL;
307 }
308 
detachSurfaceTexture(DeferredLayerUpdater * layer)309 void RenderProxy::detachSurfaceTexture(DeferredLayerUpdater* layer) {
310     SETUP_TASK(detachSurfaceTexture);
311     args->layer = layer;
312     postAndWait(task);
313 }
314 
CREATE_BRIDGE1(destroyHardwareResources,CanvasContext * context)315 CREATE_BRIDGE1(destroyHardwareResources, CanvasContext* context) {
316     args->context->destroyHardwareResources();
317     return NULL;
318 }
319 
destroyHardwareResources()320 void RenderProxy::destroyHardwareResources() {
321     SETUP_TASK(destroyHardwareResources);
322     args->context = mContext;
323     post(task);
324 }
325 
CREATE_BRIDGE2(timMemory,RenderThread * thread,int level)326 CREATE_BRIDGE2(timMemory, RenderThread* thread, int level) {
327     CanvasContext::trimMemory(*args->thread, args->level);
328     return NULL;
329 }
330 
trimMemory(int level)331 void RenderProxy::trimMemory(int level) {
332     // Avoid creating a RenderThread to do a trimMemory.
333     if (RenderThread::hasInstance()) {
334         RenderThread& thread = RenderThread::getInstance();
335         SETUP_TASK(timMemory);
336         args->thread = &thread;
337         args->level = level;
338         thread.queue(task);
339     }
340 }
341 
CREATE_BRIDGE0(fence)342 CREATE_BRIDGE0(fence) {
343     // Intentionally empty
344     return NULL;
345 }
346 
fence()347 void RenderProxy::fence() {
348     SETUP_TASK(fence);
349     postAndWait(task);
350 }
351 
CREATE_BRIDGE1(stopDrawing,CanvasContext * context)352 CREATE_BRIDGE1(stopDrawing, CanvasContext* context) {
353     args->context->stopDrawing();
354     return NULL;
355 }
356 
stopDrawing()357 void RenderProxy::stopDrawing() {
358     SETUP_TASK(stopDrawing);
359     args->context = mContext;
360     postAndWait(task);
361 }
362 
CREATE_BRIDGE1(notifyFramePending,CanvasContext * context)363 CREATE_BRIDGE1(notifyFramePending, CanvasContext* context) {
364     args->context->notifyFramePending();
365     return NULL;
366 }
367 
notifyFramePending()368 void RenderProxy::notifyFramePending() {
369     SETUP_TASK(notifyFramePending);
370     args->context = mContext;
371     mRenderThread.queueAtFront(task);
372 }
373 
CREATE_BRIDGE2(dumpProfileInfo,CanvasContext * context,int fd)374 CREATE_BRIDGE2(dumpProfileInfo, CanvasContext* context, int fd) {
375     args->context->profiler().dumpData(args->fd);
376     return NULL;
377 }
378 
dumpProfileInfo(int fd)379 void RenderProxy::dumpProfileInfo(int fd) {
380     SETUP_TASK(dumpProfileInfo);
381     args->context = mContext;
382     args->fd = fd;
383     postAndWait(task);
384 }
385 
CREATE_BRIDGE1(outputLogBuffer,int fd)386 CREATE_BRIDGE1(outputLogBuffer, int fd) {
387     RenderNode::outputLogBuffer(args->fd);
388     return NULL;
389 }
390 
outputLogBuffer(int fd)391 void RenderProxy::outputLogBuffer(int fd) {
392     SETUP_TASK(outputLogBuffer);
393     args->fd = fd;
394     staticPostAndWait(task);
395 }
396 
CREATE_BRIDGE4(setTextureAtlas,RenderThread * thread,GraphicBuffer * buffer,int64_t * map,size_t size)397 CREATE_BRIDGE4(setTextureAtlas, RenderThread* thread, GraphicBuffer* buffer, int64_t* map, size_t size) {
398     CanvasContext::setTextureAtlas(*args->thread, args->buffer, args->map, args->size);
399     args->buffer->decStrong(0);
400     return NULL;
401 }
402 
setTextureAtlas(const sp<GraphicBuffer> & buffer,int64_t * map,size_t size)403 void RenderProxy::setTextureAtlas(const sp<GraphicBuffer>& buffer, int64_t* map, size_t size) {
404     SETUP_TASK(setTextureAtlas);
405     args->thread = &mRenderThread;
406     args->buffer = buffer.get();
407     args->buffer->incStrong(0);
408     args->map = map;
409     args->size = size;
410     post(task);
411 }
412 
post(RenderTask * task)413 void RenderProxy::post(RenderTask* task) {
414     mRenderThread.queue(task);
415 }
416 
postAndWait(MethodInvokeRenderTask * task)417 void* RenderProxy::postAndWait(MethodInvokeRenderTask* task) {
418     void* retval;
419     task->setReturnPtr(&retval);
420     SignalingRenderTask syncTask(task, &mSyncMutex, &mSyncCondition);
421     AutoMutex _lock(mSyncMutex);
422     mRenderThread.queue(&syncTask);
423     mSyncCondition.wait(mSyncMutex);
424     return retval;
425 }
426 
staticPostAndWait(MethodInvokeRenderTask * task)427 void* RenderProxy::staticPostAndWait(MethodInvokeRenderTask* task) {
428     RenderThread& thread = RenderThread::getInstance();
429     void* retval;
430     task->setReturnPtr(&retval);
431     Mutex mutex;
432     Condition condition;
433     SignalingRenderTask syncTask(task, &mutex, &condition);
434     AutoMutex _lock(mutex);
435     thread.queue(&syncTask);
436     condition.wait(mutex);
437     return retval;
438 }
439 
440 } /* namespace renderthread */
441 } /* namespace uirenderer */
442 } /* namespace android */
443