OSDN Git Service

fix race condition between HWUI cache and renderThread
[android-x86/frameworks-base.git] / libs / hwui / renderthread / RenderProxy.cpp
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 "Rect.h"
23 #include "renderthread/CanvasContext.h"
24 #include "renderthread/RenderTask.h"
25 #include "renderthread/RenderThread.h"
26 #include "utils/Macros.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
55 namespace DumpFlags {
56     enum {
57         FrameStats = 1 << 0,
58         Reset      = 1 << 1,
59     };
60 };
61
62 CREATE_BRIDGE4(createContext, RenderThread* thread, bool translucent,
63         RenderNode* rootRenderNode, IContextFactory* contextFactory) {
64     return new CanvasContext(*args->thread, args->translucent,
65             args->rootRenderNode, args->contextFactory);
66 }
67
68 RenderProxy::RenderProxy(bool translucent, RenderNode* rootRenderNode, IContextFactory* contextFactory)
69         : mRenderThread(RenderThread::getInstance())
70         , mContext(nullptr) {
71     SETUP_TASK(createContext);
72     args->translucent = translucent;
73     args->rootRenderNode = rootRenderNode;
74     args->thread = &mRenderThread;
75     args->contextFactory = contextFactory;
76     mContext = (CanvasContext*) postAndWait(task);
77     mDrawFrameTask.setContext(&mRenderThread, mContext);
78 }
79
80 RenderProxy::~RenderProxy() {
81     destroyContext();
82 }
83
84 CREATE_BRIDGE1(destroyContext, CanvasContext* context) {
85     delete args->context;
86     return nullptr;
87 }
88
89 void RenderProxy::destroyContext() {
90     if (mContext) {
91         SETUP_TASK(destroyContext);
92         args->context = mContext;
93         mContext = nullptr;
94         mDrawFrameTask.setContext(nullptr, nullptr);
95         // This is also a fence as we need to be certain that there are no
96         // outstanding mDrawFrame tasks posted before it is destroyed
97         postAndWait(task);
98     }
99 }
100
101 CREATE_BRIDGE2(setSwapBehavior, CanvasContext* context, SwapBehavior swapBehavior) {
102     args->context->setSwapBehavior(args->swapBehavior);
103     return nullptr;
104 }
105
106 void RenderProxy::setSwapBehavior(SwapBehavior swapBehavior) {
107     SETUP_TASK(setSwapBehavior);
108     args->context = mContext;
109     args->swapBehavior = swapBehavior;
110     post(task);
111 }
112
113 CREATE_BRIDGE1(loadSystemProperties, CanvasContext* context) {
114     bool needsRedraw = false;
115     if (Caches::hasInstance()) {
116         needsRedraw = Properties::load();
117     }
118     if (args->context->profiler().consumeProperties()) {
119         needsRedraw = true;
120     }
121     return (void*) needsRedraw;
122 }
123
124 bool RenderProxy::loadSystemProperties() {
125     SETUP_TASK(loadSystemProperties);
126     args->context = mContext;
127     return (bool) postAndWait(task);
128 }
129
130 CREATE_BRIDGE2(setName, CanvasContext* context, const char* name) {
131     args->context->setName(std::string(args->name));
132     return nullptr;
133 }
134
135 void RenderProxy::setName(const char* name) {
136     SETUP_TASK(setName);
137     args->context = mContext;
138     args->name = name;
139     postAndWait(task); // block since name/value pointers owned by caller
140 }
141
142 CREATE_BRIDGE2(initialize, CanvasContext* context, ANativeWindow* window) {
143     args->context->initialize(args->window);
144     return nullptr;
145 }
146
147 void RenderProxy::initialize(const sp<ANativeWindow>& window) {
148     SETUP_TASK(initialize);
149     args->context = mContext;
150     args->window = window.get();
151     post(task);
152 }
153
154 CREATE_BRIDGE2(updateSurface, CanvasContext* context, ANativeWindow* window) {
155     args->context->updateSurface(args->window);
156     return nullptr;
157 }
158
159 void RenderProxy::updateSurface(const sp<ANativeWindow>& window) {
160     SETUP_TASK(updateSurface);
161     args->context = mContext;
162     args->window = window.get();
163     postAndWait(task);
164 }
165
166 CREATE_BRIDGE2(pauseSurface, CanvasContext* context, ANativeWindow* window) {
167     return (void*) args->context->pauseSurface(args->window);
168 }
169
170 bool RenderProxy::pauseSurface(const sp<ANativeWindow>& window) {
171     SETUP_TASK(pauseSurface);
172     args->context = mContext;
173     args->window = window.get();
174     return (bool) postAndWait(task);
175 }
176
177 CREATE_BRIDGE6(setup, CanvasContext* context, int width, int height,
178         float lightRadius, uint8_t ambientShadowAlpha, uint8_t spotShadowAlpha) {
179     args->context->setup(args->width, args->height, args->lightRadius,
180             args->ambientShadowAlpha, args->spotShadowAlpha);
181     return nullptr;
182 }
183
184 void RenderProxy::setup(int width, int height, float lightRadius,
185         uint8_t ambientShadowAlpha, uint8_t spotShadowAlpha) {
186     SETUP_TASK(setup);
187     args->context = mContext;
188     args->width = width;
189     args->height = height;
190     args->lightRadius = lightRadius;
191     args->ambientShadowAlpha = ambientShadowAlpha;
192     args->spotShadowAlpha = spotShadowAlpha;
193     post(task);
194 }
195
196 CREATE_BRIDGE2(setLightCenter, CanvasContext* context, Vector3 lightCenter) {
197     args->context->setLightCenter(args->lightCenter);
198     return nullptr;
199 }
200
201 void RenderProxy::setLightCenter(const Vector3& lightCenter) {
202     SETUP_TASK(setLightCenter);
203     args->context = mContext;
204     args->lightCenter = lightCenter;
205     post(task);
206 }
207
208 CREATE_BRIDGE2(setOpaque, CanvasContext* context, bool opaque) {
209     args->context->setOpaque(args->opaque);
210     return nullptr;
211 }
212
213 void RenderProxy::setOpaque(bool opaque) {
214     SETUP_TASK(setOpaque);
215     args->context = mContext;
216     args->opaque = opaque;
217     post(task);
218 }
219
220 int64_t* RenderProxy::frameInfo() {
221     return mDrawFrameTask.frameInfo();
222 }
223
224 int RenderProxy::syncAndDrawFrame() {
225     return mDrawFrameTask.drawFrame();
226 }
227
228 CREATE_BRIDGE1(destroy, CanvasContext* context) {
229     args->context->destroy();
230     return nullptr;
231 }
232
233 void RenderProxy::destroy() {
234     SETUP_TASK(destroy);
235     args->context = mContext;
236     // destroyCanvasAndSurface() needs a fence as when it returns the
237     // underlying BufferQueue is going to be released from under
238     // the render thread.
239     postAndWait(task);
240 }
241
242 CREATE_BRIDGE2(invokeFunctor, RenderThread* thread, Functor* functor) {
243     CanvasContext::invokeFunctor(*args->thread, args->functor);
244     return nullptr;
245 }
246
247 void RenderProxy::invokeFunctor(Functor* functor, bool waitForCompletion) {
248     ATRACE_CALL();
249     RenderThread& thread = RenderThread::getInstance();
250     SETUP_TASK(invokeFunctor);
251     args->thread = &thread;
252     args->functor = functor;
253     if (waitForCompletion) {
254         // waitForCompletion = true is expected to be fairly rare and only
255         // happen in destruction. Thus it should be fine to temporarily
256         // create a Mutex
257         staticPostAndWait(task);
258     } else {
259         thread.queue(task);
260     }
261 }
262
263 CREATE_BRIDGE2(runWithGlContext, CanvasContext* context, RenderTask* task) {
264     args->context->runWithGlContext(args->task);
265     return nullptr;
266 }
267
268 void RenderProxy::runWithGlContext(RenderTask* gltask) {
269     SETUP_TASK(runWithGlContext);
270     args->context = mContext;
271     args->task = gltask;
272     postAndWait(task);
273 }
274
275 CREATE_BRIDGE2(createTextureLayer, RenderThread* thread, CanvasContext* context) {
276     Layer* layer = args->context->createTextureLayer();
277     if (!layer) return nullptr;
278     return new DeferredLayerUpdater(*args->thread, layer);
279 }
280
281 DeferredLayerUpdater* RenderProxy::createTextureLayer() {
282     SETUP_TASK(createTextureLayer);
283     args->context = mContext;
284     args->thread = &mRenderThread;
285     void* retval = postAndWait(task);
286     DeferredLayerUpdater* layer = reinterpret_cast<DeferredLayerUpdater*>(retval);
287     return layer;
288 }
289
290 CREATE_BRIDGE2(buildLayer, CanvasContext* context, RenderNode* node) {
291     args->context->buildLayer(args->node);
292     return nullptr;
293 }
294
295 void RenderProxy::buildLayer(RenderNode* node) {
296     SETUP_TASK(buildLayer);
297     args->context = mContext;
298     args->node = node;
299     postAndWait(task);
300 }
301
302 CREATE_BRIDGE3(copyLayerInto, CanvasContext* context, DeferredLayerUpdater* layer,
303         SkBitmap* bitmap) {
304     bool success = args->context->copyLayerInto(args->layer, args->bitmap);
305     return (void*) success;
306 }
307
308 bool RenderProxy::copyLayerInto(DeferredLayerUpdater* layer, SkBitmap& bitmap) {
309     SETUP_TASK(copyLayerInto);
310     args->context = mContext;
311     args->layer = layer;
312     args->bitmap = &bitmap;
313     return (bool) postAndWait(task);
314 }
315
316 void RenderProxy::pushLayerUpdate(DeferredLayerUpdater* layer) {
317     mDrawFrameTask.pushLayerUpdate(layer);
318 }
319
320 void RenderProxy::cancelLayerUpdate(DeferredLayerUpdater* layer) {
321     mDrawFrameTask.removeLayerUpdate(layer);
322 }
323
324 CREATE_BRIDGE1(detachSurfaceTexture, DeferredLayerUpdater* layer) {
325     args->layer->detachSurfaceTexture();
326     return nullptr;
327 }
328
329 void RenderProxy::detachSurfaceTexture(DeferredLayerUpdater* layer) {
330     SETUP_TASK(detachSurfaceTexture);
331     args->layer = layer;
332     postAndWait(task);
333 }
334
335 CREATE_BRIDGE1(destroyHardwareResources, CanvasContext* context) {
336     args->context->destroyHardwareResources();
337     return nullptr;
338 }
339
340 void RenderProxy::destroyHardwareResources() {
341     SETUP_TASK(destroyHardwareResources);
342     args->context = mContext;
343     post(task);
344 }
345
346 CREATE_BRIDGE2(trimMemory, RenderThread* thread, int level) {
347     CanvasContext::trimMemory(*args->thread, args->level);
348     return nullptr;
349 }
350
351 void RenderProxy::trimMemory(int level) {
352     // Avoid creating a RenderThread to do a trimMemory.
353     if (RenderThread::hasInstance()) {
354         RenderThread& thread = RenderThread::getInstance();
355         SETUP_TASK(trimMemory);
356         args->thread = &thread;
357         args->level = level;
358         thread.queue(task);
359     }
360 }
361
362 CREATE_BRIDGE2(overrideProperty, const char* name, const char* value) {
363     Properties::overrideProperty(args->name, args->value);
364     return nullptr;
365 }
366
367 void RenderProxy::overrideProperty(const char* name, const char* value) {
368     SETUP_TASK(overrideProperty);
369     args->name = name;
370     args->value = value;
371     staticPostAndWait(task); // expensive, but block here since name/value pointers owned by caller
372 }
373
374 CREATE_BRIDGE0(fence) {
375     // Intentionally empty
376     return nullptr;
377 }
378
379 template <typename T>
380 void UNUSED(T t) {}
381
382 void RenderProxy::fence() {
383     SETUP_TASK(fence);
384     UNUSED(args);
385     postAndWait(task);
386 }
387
388 void RenderProxy::staticFence() {
389     SETUP_TASK(fence);
390     UNUSED(args);
391     staticPostAndWait(task);
392 }
393
394 CREATE_BRIDGE1(stopDrawing, CanvasContext* context) {
395     args->context->stopDrawing();
396     return nullptr;
397 }
398
399 void RenderProxy::stopDrawing() {
400     SETUP_TASK(stopDrawing);
401     args->context = mContext;
402     postAndWait(task);
403 }
404
405 CREATE_BRIDGE1(notifyFramePending, CanvasContext* context) {
406     args->context->notifyFramePending();
407     return nullptr;
408 }
409
410 void RenderProxy::notifyFramePending() {
411     SETUP_TASK(notifyFramePending);
412     args->context = mContext;
413     mRenderThread.queueAtFront(task);
414 }
415
416 CREATE_BRIDGE4(dumpProfileInfo, CanvasContext* context, RenderThread* thread,
417         int fd, int dumpFlags) {
418     args->context->profiler().dumpData(args->fd);
419     args->thread->jankTracker().dump(args->fd);
420     if (args->dumpFlags & DumpFlags::FrameStats) {
421         args->context->dumpFrames(args->fd);
422     }
423     if (args->dumpFlags & DumpFlags::Reset) {
424         args->context->resetFrameStats();
425     }
426     return nullptr;
427 }
428
429 void RenderProxy::dumpProfileInfo(int fd, int dumpFlags) {
430     SETUP_TASK(dumpProfileInfo);
431     args->context = mContext;
432     args->thread = &mRenderThread;
433     args->fd = fd;
434     args->dumpFlags = dumpFlags;
435     postAndWait(task);
436 }
437
438 CREATE_BRIDGE1(resetProfileInfo, CanvasContext* context) {
439     args->context->resetFrameStats();
440     return nullptr;
441 }
442
443 void RenderProxy::resetProfileInfo() {
444     SETUP_TASK(resetProfileInfo);
445     args->context = mContext;
446     postAndWait(task);
447 }
448
449 CREATE_BRIDGE2(dumpGraphicsMemory, int fd, RenderThread* thread) {
450     args->thread->jankTracker().dump(args->fd);
451
452     FILE *file = fdopen(args->fd, "a");
453     if (Caches::hasInstance()) {
454         String8 cachesLog;
455         Caches::getInstance().dumpMemoryUsage(cachesLog);
456         fprintf(file, "\nCaches:\n%s\n", cachesLog.string());
457     } else {
458         fprintf(file, "\nNo caches instance.\n");
459     }
460     fflush(file);
461     return nullptr;
462 }
463
464 void RenderProxy::dumpGraphicsMemory(int fd) {
465     if (!RenderThread::hasInstance()) return;
466     SETUP_TASK(dumpGraphicsMemory);
467     args->fd = fd;
468     args->thread = &RenderThread::getInstance();
469     staticPostAndWait(task);
470 }
471
472 CREATE_BRIDGE4(setTextureAtlas, RenderThread* thread, GraphicBuffer* buffer, int64_t* map, size_t size) {
473     CanvasContext::setTextureAtlas(*args->thread, args->buffer, args->map, args->size);
474     args->buffer->decStrong(nullptr);
475     return nullptr;
476 }
477
478 void RenderProxy::setTextureAtlas(const sp<GraphicBuffer>& buffer, int64_t* map, size_t size) {
479     SETUP_TASK(setTextureAtlas);
480     args->thread = &mRenderThread;
481     args->buffer = buffer.get();
482     args->buffer->incStrong(nullptr);
483     args->map = map;
484     args->size = size;
485     post(task);
486 }
487
488 CREATE_BRIDGE2(setProcessStatsBuffer, RenderThread* thread, int fd) {
489     args->thread->jankTracker().switchStorageToAshmem(args->fd);
490     close(args->fd);
491     return nullptr;
492 }
493
494 void RenderProxy::setProcessStatsBuffer(int fd) {
495     SETUP_TASK(setProcessStatsBuffer);
496     args->thread = &mRenderThread;
497     args->fd = dup(fd);
498     post(task);
499 }
500
501 void RenderProxy::post(RenderTask* task) {
502     mRenderThread.queue(task);
503 }
504
505 void* RenderProxy::postAndWait(MethodInvokeRenderTask* task) {
506     void* retval;
507     task->setReturnPtr(&retval);
508     SignalingRenderTask syncTask(task, &mSyncMutex, &mSyncCondition);
509     AutoMutex _lock(mSyncMutex);
510     mRenderThread.queue(&syncTask);
511     mSyncCondition.wait(mSyncMutex);
512     return retval;
513 }
514
515 void* RenderProxy::staticPostAndWait(MethodInvokeRenderTask* task) {
516     RenderThread& thread = RenderThread::getInstance();
517     void* retval;
518     task->setReturnPtr(&retval);
519     Mutex mutex;
520     Condition condition;
521     SignalingRenderTask syncTask(task, &mutex, &condition);
522     AutoMutex _lock(mutex);
523     thread.queue(&syncTask);
524     condition.wait(mutex);
525     return retval;
526 }
527
528 } /* namespace renderthread */
529 } /* namespace uirenderer */
530 } /* namespace android */