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