2 * Copyright (C) 2013 The Android Open Source Project
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
8 * http://www.apache.org/licenses/LICENSE-2.0
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.
17 #include "RenderProxy.h"
19 #include "DeferredLayerUpdater.h"
20 #include "DisplayList.h"
21 #include "LayerRenderer.h"
23 #include "renderthread/CanvasContext.h"
24 #include "renderthread/RenderTask.h"
25 #include "renderthread/RenderThread.h"
26 #include "utils/Macros.h"
29 namespace uirenderer {
30 namespace renderthread {
32 #define ARGS(method) method ## Args
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) \
44 a1; a2; a3; a4; a5; a6; a7; a8; \
46 static void* Bridge_ ## name(ARGS(name)* args)
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()
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);
68 RenderProxy::RenderProxy(bool translucent, RenderNode* rootRenderNode, IContextFactory* contextFactory)
69 : mRenderThread(RenderThread::getInstance())
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);
80 RenderProxy::~RenderProxy() {
84 CREATE_BRIDGE1(destroyContext, CanvasContext* context) {
89 void RenderProxy::destroyContext() {
91 SETUP_TASK(destroyContext);
92 args->context = mContext;
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
101 CREATE_BRIDGE2(setSwapBehavior, CanvasContext* context, SwapBehavior swapBehavior) {
102 args->context->setSwapBehavior(args->swapBehavior);
106 void RenderProxy::setSwapBehavior(SwapBehavior swapBehavior) {
107 SETUP_TASK(setSwapBehavior);
108 args->context = mContext;
109 args->swapBehavior = swapBehavior;
113 CREATE_BRIDGE1(loadSystemProperties, CanvasContext* context) {
114 bool needsRedraw = false;
115 if (Caches::hasInstance()) {
116 needsRedraw = Properties::load();
118 if (args->context->profiler().consumeProperties()) {
121 return (void*) needsRedraw;
124 bool RenderProxy::loadSystemProperties() {
125 SETUP_TASK(loadSystemProperties);
126 args->context = mContext;
127 return (bool) postAndWait(task);
130 CREATE_BRIDGE2(setName, CanvasContext* context, const char* name) {
131 args->context->setName(std::string(args->name));
135 void RenderProxy::setName(const char* name) {
137 args->context = mContext;
139 postAndWait(task); // block since name/value pointers owned by caller
142 CREATE_BRIDGE2(initialize, CanvasContext* context, ANativeWindow* window) {
143 args->context->initialize(args->window);
147 void RenderProxy::initialize(const sp<ANativeWindow>& window) {
148 SETUP_TASK(initialize);
149 args->context = mContext;
150 args->window = window.get();
154 CREATE_BRIDGE2(updateSurface, CanvasContext* context, ANativeWindow* window) {
155 args->context->updateSurface(args->window);
159 void RenderProxy::updateSurface(const sp<ANativeWindow>& window) {
160 SETUP_TASK(updateSurface);
161 args->context = mContext;
162 args->window = window.get();
166 CREATE_BRIDGE2(pauseSurface, CanvasContext* context, ANativeWindow* window) {
167 return (void*) args->context->pauseSurface(args->window);
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);
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);
184 void RenderProxy::setup(int width, int height, float lightRadius,
185 uint8_t ambientShadowAlpha, uint8_t spotShadowAlpha) {
187 args->context = mContext;
189 args->height = height;
190 args->lightRadius = lightRadius;
191 args->ambientShadowAlpha = ambientShadowAlpha;
192 args->spotShadowAlpha = spotShadowAlpha;
196 CREATE_BRIDGE2(setLightCenter, CanvasContext* context, Vector3 lightCenter) {
197 args->context->setLightCenter(args->lightCenter);
201 void RenderProxy::setLightCenter(const Vector3& lightCenter) {
202 SETUP_TASK(setLightCenter);
203 args->context = mContext;
204 args->lightCenter = lightCenter;
208 CREATE_BRIDGE2(setOpaque, CanvasContext* context, bool opaque) {
209 args->context->setOpaque(args->opaque);
213 void RenderProxy::setOpaque(bool opaque) {
214 SETUP_TASK(setOpaque);
215 args->context = mContext;
216 args->opaque = opaque;
220 int64_t* RenderProxy::frameInfo() {
221 return mDrawFrameTask.frameInfo();
224 int RenderProxy::syncAndDrawFrame() {
225 return mDrawFrameTask.drawFrame();
228 CREATE_BRIDGE1(destroy, CanvasContext* context) {
229 args->context->destroy();
233 void RenderProxy::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.
242 CREATE_BRIDGE2(invokeFunctor, RenderThread* thread, Functor* functor) {
243 CanvasContext::invokeFunctor(*args->thread, args->functor);
247 void RenderProxy::invokeFunctor(Functor* functor, bool waitForCompletion) {
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
257 staticPostAndWait(task);
263 CREATE_BRIDGE2(runWithGlContext, CanvasContext* context, RenderTask* task) {
264 args->context->runWithGlContext(args->task);
268 void RenderProxy::runWithGlContext(RenderTask* gltask) {
269 SETUP_TASK(runWithGlContext);
270 args->context = mContext;
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);
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);
290 CREATE_BRIDGE2(buildLayer, CanvasContext* context, RenderNode* node) {
291 args->context->buildLayer(args->node);
295 void RenderProxy::buildLayer(RenderNode* node) {
296 SETUP_TASK(buildLayer);
297 args->context = mContext;
302 CREATE_BRIDGE3(copyLayerInto, CanvasContext* context, DeferredLayerUpdater* layer,
304 bool success = args->context->copyLayerInto(args->layer, args->bitmap);
305 return (void*) success;
308 bool RenderProxy::copyLayerInto(DeferredLayerUpdater* layer, SkBitmap& bitmap) {
309 SETUP_TASK(copyLayerInto);
310 args->context = mContext;
312 args->bitmap = &bitmap;
313 return (bool) postAndWait(task);
316 void RenderProxy::pushLayerUpdate(DeferredLayerUpdater* layer) {
317 mDrawFrameTask.pushLayerUpdate(layer);
320 void RenderProxy::cancelLayerUpdate(DeferredLayerUpdater* layer) {
321 mDrawFrameTask.removeLayerUpdate(layer);
324 CREATE_BRIDGE1(detachSurfaceTexture, DeferredLayerUpdater* layer) {
325 args->layer->detachSurfaceTexture();
329 void RenderProxy::detachSurfaceTexture(DeferredLayerUpdater* layer) {
330 SETUP_TASK(detachSurfaceTexture);
335 CREATE_BRIDGE1(destroyHardwareResources, CanvasContext* context) {
336 args->context->destroyHardwareResources();
340 void RenderProxy::destroyHardwareResources() {
341 SETUP_TASK(destroyHardwareResources);
342 args->context = mContext;
346 CREATE_BRIDGE2(trimMemory, RenderThread* thread, int level) {
347 CanvasContext::trimMemory(*args->thread, args->level);
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;
362 CREATE_BRIDGE2(overrideProperty, const char* name, const char* value) {
363 Properties::overrideProperty(args->name, args->value);
367 void RenderProxy::overrideProperty(const char* name, const char* value) {
368 SETUP_TASK(overrideProperty);
371 staticPostAndWait(task); // expensive, but block here since name/value pointers owned by caller
374 CREATE_BRIDGE0(fence) {
375 // Intentionally empty
379 template <typename T>
382 void RenderProxy::fence() {
388 void RenderProxy::staticFence() {
391 staticPostAndWait(task);
394 CREATE_BRIDGE1(stopDrawing, CanvasContext* context) {
395 args->context->stopDrawing();
399 void RenderProxy::stopDrawing() {
400 SETUP_TASK(stopDrawing);
401 args->context = mContext;
405 CREATE_BRIDGE1(notifyFramePending, CanvasContext* context) {
406 args->context->notifyFramePending();
410 void RenderProxy::notifyFramePending() {
411 SETUP_TASK(notifyFramePending);
412 args->context = mContext;
413 mRenderThread.queueAtFront(task);
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);
423 if (args->dumpFlags & DumpFlags::Reset) {
424 args->context->resetFrameStats();
429 void RenderProxy::dumpProfileInfo(int fd, int dumpFlags) {
430 SETUP_TASK(dumpProfileInfo);
431 args->context = mContext;
432 args->thread = &mRenderThread;
434 args->dumpFlags = dumpFlags;
438 CREATE_BRIDGE1(resetProfileInfo, CanvasContext* context) {
439 args->context->resetFrameStats();
443 void RenderProxy::resetProfileInfo() {
444 SETUP_TASK(resetProfileInfo);
445 args->context = mContext;
449 CREATE_BRIDGE2(dumpGraphicsMemory, int fd, RenderThread* thread) {
450 args->thread->jankTracker().dump(args->fd);
452 FILE *file = fdopen(args->fd, "a");
453 if (Caches::hasInstance()) {
455 Caches::getInstance().dumpMemoryUsage(cachesLog);
456 fprintf(file, "\nCaches:\n%s\n", cachesLog.string());
458 fprintf(file, "\nNo caches instance.\n");
464 void RenderProxy::dumpGraphicsMemory(int fd) {
465 if (!RenderThread::hasInstance()) return;
466 SETUP_TASK(dumpGraphicsMemory);
468 args->thread = &RenderThread::getInstance();
469 staticPostAndWait(task);
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);
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);
488 CREATE_BRIDGE2(setProcessStatsBuffer, RenderThread* thread, int fd) {
489 args->thread->jankTracker().switchStorageToAshmem(args->fd);
494 void RenderProxy::setProcessStatsBuffer(int fd) {
495 SETUP_TASK(setProcessStatsBuffer);
496 args->thread = &mRenderThread;
501 void RenderProxy::post(RenderTask* task) {
502 mRenderThread.queue(task);
505 void* RenderProxy::postAndWait(MethodInvokeRenderTask* task) {
507 task->setReturnPtr(&retval);
508 SignalingRenderTask syncTask(task, &mSyncMutex, &mSyncCondition);
509 AutoMutex _lock(mSyncMutex);
510 mRenderThread.queue(&syncTask);
511 mSyncCondition.wait(mSyncMutex);
515 void* RenderProxy::staticPostAndWait(MethodInvokeRenderTask* task) {
516 RenderThread& thread = RenderThread::getInstance();
518 task->setReturnPtr(&retval);
521 SignalingRenderTask syncTask(task, &mutex, &condition);
522 AutoMutex _lock(mutex);
523 thread.queue(&syncTask);
524 condition.wait(mutex);
528 } /* namespace renderthread */
529 } /* namespace uirenderer */
530 } /* namespace android */