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 "Properties.h"
22 #include "Readback.h"
23 #include "Rect.h"
24 #include "renderthread/CanvasContext.h"
25 #include "renderthread/EglManager.h"
26 #include "renderthread/RenderTask.h"
27 #include "renderthread/RenderThread.h"
28 #include "renderstate/RenderState.h"
29 #include "utils/Macros.h"
30 #include "utils/TimeUtils.h"
31 
32 #include <ui/GraphicBuffer.h>
33 
34 namespace android {
35 namespace uirenderer {
36 namespace renderthread {
37 
38 #define ARGS(method) method ## Args
39 
40 #define CREATE_BRIDGE0(name) CREATE_BRIDGE(name,,,,,,,,)
41 #define CREATE_BRIDGE1(name, a1) CREATE_BRIDGE(name, a1,,,,,,,)
42 #define CREATE_BRIDGE2(name, a1, a2) CREATE_BRIDGE(name, a1,a2,,,,,,)
43 #define CREATE_BRIDGE3(name, a1, a2, a3) CREATE_BRIDGE(name, a1,a2,a3,,,,,)
44 #define CREATE_BRIDGE4(name, a1, a2, a3, a4) CREATE_BRIDGE(name, a1,a2,a3,a4,,,,)
45 #define CREATE_BRIDGE5(name, a1, a2, a3, a4, a5) CREATE_BRIDGE(name, a1,a2,a3,a4,a5,,,)
46 #define CREATE_BRIDGE6(name, a1, a2, a3, a4, a5, a6) CREATE_BRIDGE(name, a1,a2,a3,a4,a5,a6,,)
47 #define CREATE_BRIDGE7(name, a1, a2, a3, a4, a5, a6, a7) CREATE_BRIDGE(name, a1,a2,a3,a4,a5,a6,a7,)
48 #define CREATE_BRIDGE(name, a1, a2, a3, a4, a5, a6, a7, a8) \
49     typedef struct { \
50         a1; a2; a3; a4; a5; a6; a7; a8; \
51     } ARGS(name); \
52     static_assert(std::is_trivially_destructible<ARGS(name)>::value, \
53             "Error, ARGS must be trivially destructible!"); \
54     static void* Bridge_ ## name(ARGS(name)* args)
55 
56 #define SETUP_TASK(method) \
57     LOG_ALWAYS_FATAL_IF( METHOD_INVOKE_PAYLOAD_SIZE < sizeof(ARGS(method)), \
58         "METHOD_INVOKE_PAYLOAD_SIZE %zu is smaller than sizeof(" #method "Args) %zu", \
59                 METHOD_INVOKE_PAYLOAD_SIZE, sizeof(ARGS(method))); \
60     MethodInvokeRenderTask* task = new MethodInvokeRenderTask((RunnableMethod) Bridge_ ## method); \
61     ARGS(method) *args = (ARGS(method) *) task->payload()
62 
CREATE_BRIDGE4(createContext,RenderThread * thread,bool translucent,RenderNode * rootRenderNode,IContextFactory * contextFactory)63 CREATE_BRIDGE4(createContext, RenderThread* thread, bool translucent,
64         RenderNode* rootRenderNode, IContextFactory* contextFactory) {
65     return CanvasContext::create(*args->thread, args->translucent,
66             args->rootRenderNode, args->contextFactory);
67 }
68 
RenderProxy(bool translucent,RenderNode * rootRenderNode,IContextFactory * contextFactory)69 RenderProxy::RenderProxy(bool translucent, RenderNode* rootRenderNode, IContextFactory* contextFactory)
70         : mRenderThread(RenderThread::getInstance())
71         , mContext(nullptr) {
72     SETUP_TASK(createContext);
73     args->translucent = translucent;
74     args->rootRenderNode = rootRenderNode;
75     args->thread = &mRenderThread;
76     args->contextFactory = contextFactory;
77     mContext = (CanvasContext*) postAndWait(task);
78     mDrawFrameTask.setContext(&mRenderThread, mContext, rootRenderNode);
79 }
80 
~RenderProxy()81 RenderProxy::~RenderProxy() {
82     destroyContext();
83 }
84 
CREATE_BRIDGE1(destroyContext,CanvasContext * context)85 CREATE_BRIDGE1(destroyContext, CanvasContext* context) {
86     delete args->context;
87     return nullptr;
88 }
89 
destroyContext()90 void RenderProxy::destroyContext() {
91     if (mContext) {
92         SETUP_TASK(destroyContext);
93         args->context = mContext;
94         mContext = nullptr;
95         mDrawFrameTask.setContext(nullptr, nullptr, nullptr);
96         // This is also a fence as we need to be certain that there are no
97         // outstanding mDrawFrame tasks posted before it is destroyed
98         postAndWait(task);
99     }
100 }
101 
CREATE_BRIDGE2(setSwapBehavior,CanvasContext * context,SwapBehavior swapBehavior)102 CREATE_BRIDGE2(setSwapBehavior, CanvasContext* context, SwapBehavior swapBehavior) {
103     args->context->setSwapBehavior(args->swapBehavior);
104     return nullptr;
105 }
106 
setSwapBehavior(SwapBehavior swapBehavior)107 void RenderProxy::setSwapBehavior(SwapBehavior swapBehavior) {
108     SETUP_TASK(setSwapBehavior);
109     args->context = mContext;
110     args->swapBehavior = swapBehavior;
111     post(task);
112 }
113 
CREATE_BRIDGE1(loadSystemProperties,CanvasContext * context)114 CREATE_BRIDGE1(loadSystemProperties, CanvasContext* context) {
115     bool needsRedraw = false;
116     if (Caches::hasInstance()) {
117         needsRedraw = Properties::load();
118     }
119     if (args->context->profiler().consumeProperties()) {
120         needsRedraw = true;
121     }
122     return (void*) needsRedraw;
123 }
124 
loadSystemProperties()125 bool RenderProxy::loadSystemProperties() {
126     SETUP_TASK(loadSystemProperties);
127     args->context = mContext;
128     return (bool) postAndWait(task);
129 }
130 
CREATE_BRIDGE2(setName,CanvasContext * context,const char * name)131 CREATE_BRIDGE2(setName, CanvasContext* context, const char* name) {
132     args->context->setName(std::string(args->name));
133     return nullptr;
134 }
135 
setName(const char * name)136 void RenderProxy::setName(const char* name) {
137     SETUP_TASK(setName);
138     args->context = mContext;
139     args->name = name;
140     postAndWait(task); // block since name/value pointers owned by caller
141 }
142 
CREATE_BRIDGE2(initialize,CanvasContext * context,Surface * surface)143 CREATE_BRIDGE2(initialize, CanvasContext* context, Surface* surface) {
144     args->context->initialize(args->surface);
145     return nullptr;
146 }
147 
initialize(const sp<Surface> & surface)148 void RenderProxy::initialize(const sp<Surface>& surface) {
149     SETUP_TASK(initialize);
150     args->context = mContext;
151     args->surface = surface.get();
152     post(task);
153 }
154 
CREATE_BRIDGE2(updateSurface,CanvasContext * context,Surface * surface)155 CREATE_BRIDGE2(updateSurface, CanvasContext* context, Surface* surface) {
156     args->context->updateSurface(args->surface);
157     return nullptr;
158 }
159 
updateSurface(const sp<Surface> & surface)160 void RenderProxy::updateSurface(const sp<Surface>& surface) {
161     SETUP_TASK(updateSurface);
162     args->context = mContext;
163     args->surface = surface.get();
164     post(task);
165 }
166 
CREATE_BRIDGE2(pauseSurface,CanvasContext * context,Surface * surface)167 CREATE_BRIDGE2(pauseSurface, CanvasContext* context, Surface* surface) {
168     return (void*) args->context->pauseSurface(args->surface);
169 }
170 
pauseSurface(const sp<Surface> & surface)171 bool RenderProxy::pauseSurface(const sp<Surface>& surface) {
172     SETUP_TASK(pauseSurface);
173     args->context = mContext;
174     args->surface = surface.get();
175     return (bool) postAndWait(task);
176 }
177 
CREATE_BRIDGE2(setStopped,CanvasContext * context,bool stopped)178 CREATE_BRIDGE2(setStopped, CanvasContext* context, bool stopped) {
179     args->context->setStopped(args->stopped);
180     return nullptr;
181 }
182 
setStopped(bool stopped)183 void RenderProxy::setStopped(bool stopped) {
184     SETUP_TASK(setStopped);
185     args->context = mContext;
186     args->stopped = stopped;
187     postAndWait(task);
188 }
189 
CREATE_BRIDGE4(setup,CanvasContext * context,float lightRadius,uint8_t ambientShadowAlpha,uint8_t spotShadowAlpha)190 CREATE_BRIDGE4(setup, CanvasContext* context,
191         float lightRadius, uint8_t ambientShadowAlpha, uint8_t spotShadowAlpha) {
192     args->context->setup(args->lightRadius,
193             args->ambientShadowAlpha, args->spotShadowAlpha);
194     return nullptr;
195 }
196 
setup(float lightRadius,uint8_t ambientShadowAlpha,uint8_t spotShadowAlpha)197 void RenderProxy::setup(float lightRadius,
198         uint8_t ambientShadowAlpha, uint8_t spotShadowAlpha) {
199     SETUP_TASK(setup);
200     args->context = mContext;
201     args->lightRadius = lightRadius;
202     args->ambientShadowAlpha = ambientShadowAlpha;
203     args->spotShadowAlpha = spotShadowAlpha;
204     post(task);
205 }
206 
CREATE_BRIDGE2(setLightCenter,CanvasContext * context,Vector3 lightCenter)207 CREATE_BRIDGE2(setLightCenter, CanvasContext* context, Vector3 lightCenter) {
208     args->context->setLightCenter(args->lightCenter);
209     return nullptr;
210 }
211 
setLightCenter(const Vector3 & lightCenter)212 void RenderProxy::setLightCenter(const Vector3& lightCenter) {
213     SETUP_TASK(setLightCenter);
214     args->context = mContext;
215     args->lightCenter = lightCenter;
216     post(task);
217 }
218 
CREATE_BRIDGE2(setOpaque,CanvasContext * context,bool opaque)219 CREATE_BRIDGE2(setOpaque, CanvasContext* context, bool opaque) {
220     args->context->setOpaque(args->opaque);
221     return nullptr;
222 }
223 
setOpaque(bool opaque)224 void RenderProxy::setOpaque(bool opaque) {
225     SETUP_TASK(setOpaque);
226     args->context = mContext;
227     args->opaque = opaque;
228     post(task);
229 }
230 
frameInfo()231 int64_t* RenderProxy::frameInfo() {
232     return mDrawFrameTask.frameInfo();
233 }
234 
syncAndDrawFrame()235 int RenderProxy::syncAndDrawFrame() {
236     return mDrawFrameTask.drawFrame();
237 }
238 
CREATE_BRIDGE1(destroy,CanvasContext * context)239 CREATE_BRIDGE1(destroy, CanvasContext* context) {
240     args->context->destroy();
241     return nullptr;
242 }
243 
destroy()244 void RenderProxy::destroy() {
245     SETUP_TASK(destroy);
246     args->context = mContext;
247     // destroyCanvasAndSurface() needs a fence as when it returns the
248     // underlying BufferQueue is going to be released from under
249     // the render thread.
250     postAndWait(task);
251 }
252 
CREATE_BRIDGE2(invokeFunctor,RenderThread * thread,Functor * functor)253 CREATE_BRIDGE2(invokeFunctor, RenderThread* thread, Functor* functor) {
254     CanvasContext::invokeFunctor(*args->thread, args->functor);
255     return nullptr;
256 }
257 
invokeFunctor(Functor * functor,bool waitForCompletion)258 void RenderProxy::invokeFunctor(Functor* functor, bool waitForCompletion) {
259     ATRACE_CALL();
260     RenderThread& thread = RenderThread::getInstance();
261     SETUP_TASK(invokeFunctor);
262     args->thread = &thread;
263     args->functor = functor;
264     if (waitForCompletion) {
265         // waitForCompletion = true is expected to be fairly rare and only
266         // happen in destruction. Thus it should be fine to temporarily
267         // create a Mutex
268         staticPostAndWait(task);
269     } else {
270         thread.queue(task);
271     }
272 }
273 
CREATE_BRIDGE1(createTextureLayer,CanvasContext * context)274 CREATE_BRIDGE1(createTextureLayer, CanvasContext* context) {
275     return args->context->createTextureLayer();
276 }
277 
createTextureLayer()278 DeferredLayerUpdater* RenderProxy::createTextureLayer() {
279     SETUP_TASK(createTextureLayer);
280     args->context = mContext;
281     void* retval = postAndWait(task);
282     DeferredLayerUpdater* layer = reinterpret_cast<DeferredLayerUpdater*>(retval);
283     return layer;
284 }
285 
CREATE_BRIDGE2(buildLayer,CanvasContext * context,RenderNode * node)286 CREATE_BRIDGE2(buildLayer, CanvasContext* context, RenderNode* node) {
287     args->context->buildLayer(args->node);
288     return nullptr;
289 }
290 
buildLayer(RenderNode * node)291 void RenderProxy::buildLayer(RenderNode* node) {
292     SETUP_TASK(buildLayer);
293     args->context = mContext;
294     args->node = node;
295     postAndWait(task);
296 }
297 
CREATE_BRIDGE3(copyLayerInto,CanvasContext * context,DeferredLayerUpdater * layer,SkBitmap * bitmap)298 CREATE_BRIDGE3(copyLayerInto, CanvasContext* context, DeferredLayerUpdater* layer,
299         SkBitmap* bitmap) {
300     bool success = args->context->copyLayerInto(args->layer, args->bitmap);
301     return (void*) success;
302 }
303 
copyLayerInto(DeferredLayerUpdater * layer,SkBitmap & bitmap)304 bool RenderProxy::copyLayerInto(DeferredLayerUpdater* layer, SkBitmap& bitmap) {
305     SETUP_TASK(copyLayerInto);
306     args->context = mContext;
307     args->layer = layer;
308     args->bitmap = &bitmap;
309     return (bool) postAndWait(task);
310 }
311 
pushLayerUpdate(DeferredLayerUpdater * layer)312 void RenderProxy::pushLayerUpdate(DeferredLayerUpdater* layer) {
313     mDrawFrameTask.pushLayerUpdate(layer);
314 }
315 
cancelLayerUpdate(DeferredLayerUpdater * layer)316 void RenderProxy::cancelLayerUpdate(DeferredLayerUpdater* layer) {
317     mDrawFrameTask.removeLayerUpdate(layer);
318 }
319 
CREATE_BRIDGE1(detachSurfaceTexture,DeferredLayerUpdater * layer)320 CREATE_BRIDGE1(detachSurfaceTexture, DeferredLayerUpdater* layer) {
321     args->layer->detachSurfaceTexture();
322     return nullptr;
323 }
324 
detachSurfaceTexture(DeferredLayerUpdater * layer)325 void RenderProxy::detachSurfaceTexture(DeferredLayerUpdater* layer) {
326     SETUP_TASK(detachSurfaceTexture);
327     args->layer = layer;
328     postAndWait(task);
329 }
330 
CREATE_BRIDGE1(destroyHardwareResources,CanvasContext * context)331 CREATE_BRIDGE1(destroyHardwareResources, CanvasContext* context) {
332     args->context->destroyHardwareResources();
333     return nullptr;
334 }
335 
destroyHardwareResources()336 void RenderProxy::destroyHardwareResources() {
337     SETUP_TASK(destroyHardwareResources);
338     args->context = mContext;
339     postAndWait(task);
340 }
341 
CREATE_BRIDGE2(trimMemory,RenderThread * thread,int level)342 CREATE_BRIDGE2(trimMemory, RenderThread* thread, int level) {
343     CanvasContext::trimMemory(*args->thread, args->level);
344     return nullptr;
345 }
346 
trimMemory(int level)347 void RenderProxy::trimMemory(int level) {
348     // Avoid creating a RenderThread to do a trimMemory.
349     if (RenderThread::hasInstance()) {
350         RenderThread& thread = RenderThread::getInstance();
351         SETUP_TASK(trimMemory);
352         args->thread = &thread;
353         args->level = level;
354         thread.queue(task);
355     }
356 }
357 
CREATE_BRIDGE2(overrideProperty,const char * name,const char * value)358 CREATE_BRIDGE2(overrideProperty, const char* name, const char* value) {
359     Properties::overrideProperty(args->name, args->value);
360     return nullptr;
361 }
362 
overrideProperty(const char * name,const char * value)363 void RenderProxy::overrideProperty(const char* name, const char* value) {
364     SETUP_TASK(overrideProperty);
365     args->name = name;
366     args->value = value;
367     staticPostAndWait(task); // expensive, but block here since name/value pointers owned by caller
368 }
369 
CREATE_BRIDGE0(fence)370 CREATE_BRIDGE0(fence) {
371     // Intentionally empty
372     return nullptr;
373 }
374 
375 template <typename T>
UNUSED(T t)376 void UNUSED(T t) {}
377 
fence()378 void RenderProxy::fence() {
379     SETUP_TASK(fence);
380     UNUSED(args);
381     postAndWait(task);
382 }
383 
staticFence()384 void RenderProxy::staticFence() {
385     SETUP_TASK(fence);
386     UNUSED(args);
387     staticPostAndWait(task);
388 }
389 
CREATE_BRIDGE1(stopDrawing,CanvasContext * context)390 CREATE_BRIDGE1(stopDrawing, CanvasContext* context) {
391     args->context->stopDrawing();
392     return nullptr;
393 }
394 
stopDrawing()395 void RenderProxy::stopDrawing() {
396     SETUP_TASK(stopDrawing);
397     args->context = mContext;
398     postAndWait(task);
399 }
400 
CREATE_BRIDGE1(notifyFramePending,CanvasContext * context)401 CREATE_BRIDGE1(notifyFramePending, CanvasContext* context) {
402     args->context->notifyFramePending();
403     return nullptr;
404 }
405 
notifyFramePending()406 void RenderProxy::notifyFramePending() {
407     SETUP_TASK(notifyFramePending);
408     args->context = mContext;
409     mRenderThread.queueAtFront(task);
410 }
411 
CREATE_BRIDGE4(dumpProfileInfo,CanvasContext * context,RenderThread * thread,int fd,int dumpFlags)412 CREATE_BRIDGE4(dumpProfileInfo, CanvasContext* context, RenderThread* thread,
413         int fd, int dumpFlags) {
414     args->context->profiler().dumpData(args->fd);
415     if (args->dumpFlags & DumpFlags::FrameStats) {
416         args->context->dumpFrames(args->fd);
417     }
418     if (args->dumpFlags & DumpFlags::Reset) {
419         args->context->resetFrameStats();
420     }
421     if (args->dumpFlags & DumpFlags::JankStats) {
422         args->thread->jankTracker().dump(args->fd);
423     }
424     return nullptr;
425 }
426 
dumpProfileInfo(int fd,int dumpFlags)427 void RenderProxy::dumpProfileInfo(int fd, int dumpFlags) {
428     SETUP_TASK(dumpProfileInfo);
429     args->context = mContext;
430     args->thread = &mRenderThread;
431     args->fd = fd;
432     args->dumpFlags = dumpFlags;
433     postAndWait(task);
434 }
435 
CREATE_BRIDGE1(resetProfileInfo,CanvasContext * context)436 CREATE_BRIDGE1(resetProfileInfo, CanvasContext* context) {
437     args->context->resetFrameStats();
438     return nullptr;
439 }
440 
resetProfileInfo()441 void RenderProxy::resetProfileInfo() {
442     SETUP_TASK(resetProfileInfo);
443     args->context = mContext;
444     postAndWait(task);
445 }
446 
CREATE_BRIDGE2(frameTimePercentile,RenderThread * thread,int percentile)447 CREATE_BRIDGE2(frameTimePercentile, RenderThread* thread, int percentile) {
448     return reinterpret_cast<void*>(static_cast<uintptr_t>(
449         args->thread->jankTracker().findPercentile(args->percentile)));
450 }
451 
frameTimePercentile(int p)452 uint32_t RenderProxy::frameTimePercentile(int p) {
453     SETUP_TASK(frameTimePercentile);
454     args->thread = &mRenderThread;
455     args->percentile = p;
456     return static_cast<uint32_t>(reinterpret_cast<uintptr_t>(
457         postAndWait(task)));
458 }
459 
CREATE_BRIDGE2(dumpGraphicsMemory,int fd,RenderThread * thread)460 CREATE_BRIDGE2(dumpGraphicsMemory, int fd, RenderThread* thread) {
461     args->thread->jankTracker().dump(args->fd);
462 
463     FILE *file = fdopen(args->fd, "a");
464     if (Caches::hasInstance()) {
465         String8 cachesLog;
466         Caches::getInstance().dumpMemoryUsage(cachesLog);
467         fprintf(file, "\nCaches:\n%s\n", cachesLog.string());
468     } else {
469         fprintf(file, "\nNo caches instance.\n");
470     }
471     fprintf(file, "\nPipeline=FrameBuilder\n");
472     fflush(file);
473     return nullptr;
474 }
475 
dumpGraphicsMemory(int fd)476 void RenderProxy::dumpGraphicsMemory(int fd) {
477     if (!RenderThread::hasInstance()) return;
478     SETUP_TASK(dumpGraphicsMemory);
479     args->fd = fd;
480     args->thread = &RenderThread::getInstance();
481     staticPostAndWait(task);
482 }
483 
CREATE_BRIDGE2(setProcessStatsBuffer,RenderThread * thread,int fd)484 CREATE_BRIDGE2(setProcessStatsBuffer, RenderThread* thread, int fd) {
485     args->thread->jankTracker().switchStorageToAshmem(args->fd);
486     close(args->fd);
487     return nullptr;
488 }
489 
setProcessStatsBuffer(int fd)490 void RenderProxy::setProcessStatsBuffer(int fd) {
491     SETUP_TASK(setProcessStatsBuffer);
492     auto& rt = RenderThread::getInstance();
493     args->thread = &rt;
494     args->fd = dup(fd);
495     rt.queue(task);
496 }
497 
CREATE_BRIDGE1(rotateProcessStatsBuffer,RenderThread * thread)498 CREATE_BRIDGE1(rotateProcessStatsBuffer, RenderThread* thread) {
499     args->thread->jankTracker().rotateStorage();
500     return nullptr;
501 }
502 
rotateProcessStatsBuffer()503 void RenderProxy::rotateProcessStatsBuffer() {
504     SETUP_TASK(rotateProcessStatsBuffer);
505     auto& rt = RenderThread::getInstance();
506     args->thread = &rt;
507     rt.queue(task);
508 }
509 
getRenderThreadTid()510 int RenderProxy::getRenderThreadTid() {
511     return mRenderThread.getTid();
512 }
513 
CREATE_BRIDGE3(addRenderNode,CanvasContext * context,RenderNode * node,bool placeFront)514 CREATE_BRIDGE3(addRenderNode, CanvasContext* context, RenderNode* node, bool placeFront) {
515     args->context->addRenderNode(args->node, args->placeFront);
516     return nullptr;
517 }
518 
addRenderNode(RenderNode * node,bool placeFront)519 void RenderProxy::addRenderNode(RenderNode* node, bool placeFront) {
520     SETUP_TASK(addRenderNode);
521     args->context = mContext;
522     args->node = node;
523     args->placeFront = placeFront;
524     post(task);
525 }
526 
CREATE_BRIDGE2(removeRenderNode,CanvasContext * context,RenderNode * node)527 CREATE_BRIDGE2(removeRenderNode, CanvasContext* context, RenderNode* node) {
528     args->context->removeRenderNode(args->node);
529     return nullptr;
530 }
531 
removeRenderNode(RenderNode * node)532 void RenderProxy::removeRenderNode(RenderNode* node) {
533     SETUP_TASK(removeRenderNode);
534     args->context = mContext;
535     args->node = node;
536     post(task);
537 }
538 
CREATE_BRIDGE2(drawRenderNode,CanvasContext * context,RenderNode * node)539 CREATE_BRIDGE2(drawRenderNode, CanvasContext* context, RenderNode* node) {
540     args->context->prepareAndDraw(args->node);
541     return nullptr;
542 }
543 
drawRenderNode(RenderNode * node)544 void RenderProxy::drawRenderNode(RenderNode* node) {
545     SETUP_TASK(drawRenderNode);
546     args->context = mContext;
547     args->node = node;
548     // Be pseudo-thread-safe and don't use any member variables
549     staticPostAndWait(task);
550 }
551 
CREATE_BRIDGE5(setContentDrawBounds,CanvasContext * context,int left,int top,int right,int bottom)552 CREATE_BRIDGE5(setContentDrawBounds, CanvasContext* context, int left, int top,
553         int right, int bottom) {
554     args->context->setContentDrawBounds(args->left, args->top, args->right, args->bottom);
555     return nullptr;
556 }
557 
setContentDrawBounds(int left,int top,int right,int bottom)558 void RenderProxy::setContentDrawBounds(int left, int top, int right, int bottom) {
559     SETUP_TASK(setContentDrawBounds);
560     args->context = mContext;
561     args->left = left;
562     args->top = top;
563     args->right = right;
564     args->bottom = bottom;
565     staticPostAndWait(task);
566 }
567 
CREATE_BRIDGE1(serializeDisplayListTree,CanvasContext * context)568 CREATE_BRIDGE1(serializeDisplayListTree, CanvasContext* context) {
569     args->context->serializeDisplayListTree();
570     return nullptr;
571 }
572 
serializeDisplayListTree()573 void RenderProxy::serializeDisplayListTree() {
574     SETUP_TASK(serializeDisplayListTree);
575     args->context = mContext;
576     post(task);
577 }
578 
CREATE_BRIDGE2(addFrameMetricsObserver,CanvasContext * context,FrameMetricsObserver * frameStatsObserver)579 CREATE_BRIDGE2(addFrameMetricsObserver, CanvasContext* context,
580         FrameMetricsObserver* frameStatsObserver) {
581    args->context->addFrameMetricsObserver(args->frameStatsObserver);
582    if (args->frameStatsObserver != nullptr) {
583        args->frameStatsObserver->decStrong(args->context);
584    }
585    return nullptr;
586 }
587 
addFrameMetricsObserver(FrameMetricsObserver * observer)588 void RenderProxy::addFrameMetricsObserver(FrameMetricsObserver* observer) {
589     SETUP_TASK(addFrameMetricsObserver);
590     args->context = mContext;
591     args->frameStatsObserver = observer;
592     if (observer != nullptr) {
593         observer->incStrong(mContext);
594     }
595     post(task);
596 }
597 
CREATE_BRIDGE2(removeFrameMetricsObserver,CanvasContext * context,FrameMetricsObserver * frameStatsObserver)598 CREATE_BRIDGE2(removeFrameMetricsObserver, CanvasContext* context,
599         FrameMetricsObserver* frameStatsObserver) {
600    args->context->removeFrameMetricsObserver(args->frameStatsObserver);
601    if (args->frameStatsObserver != nullptr) {
602        args->frameStatsObserver->decStrong(args->context);
603    }
604    return nullptr;
605 }
606 
removeFrameMetricsObserver(FrameMetricsObserver * observer)607 void RenderProxy::removeFrameMetricsObserver(FrameMetricsObserver* observer) {
608     SETUP_TASK(removeFrameMetricsObserver);
609     args->context = mContext;
610     args->frameStatsObserver = observer;
611     if (observer != nullptr) {
612         observer->incStrong(mContext);
613     }
614     post(task);
615 }
616 
CREATE_BRIDGE4(copySurfaceInto,RenderThread * thread,Surface * surface,Rect srcRect,SkBitmap * bitmap)617 CREATE_BRIDGE4(copySurfaceInto, RenderThread* thread,
618         Surface* surface, Rect srcRect, SkBitmap* bitmap) {
619     return (void*)args->thread->readback().copySurfaceInto(*args->surface,
620             args->srcRect, args->bitmap);
621 }
622 
copySurfaceInto(sp<Surface> & surface,int left,int top,int right,int bottom,SkBitmap * bitmap)623 int RenderProxy::copySurfaceInto(sp<Surface>& surface, int left, int top,
624         int right, int bottom,  SkBitmap* bitmap) {
625     SETUP_TASK(copySurfaceInto);
626     args->bitmap = bitmap;
627     args->surface = surface.get();
628     args->thread = &RenderThread::getInstance();
629     args->srcRect.set(left, top, right, bottom);
630     return static_cast<int>(
631             reinterpret_cast<intptr_t>( staticPostAndWait(task) ));
632 }
633 
CREATE_BRIDGE2(prepareToDraw,RenderThread * thread,Bitmap * bitmap)634 CREATE_BRIDGE2(prepareToDraw, RenderThread* thread, Bitmap* bitmap) {
635     CanvasContext::prepareToDraw(*args->thread, args->bitmap);
636     args->bitmap->unref();
637     args->bitmap = nullptr;
638     return nullptr;
639 }
640 
prepareToDraw(Bitmap & bitmap)641 void RenderProxy::prepareToDraw(Bitmap& bitmap) {
642     // If we haven't spun up a hardware accelerated window yet, there's no
643     // point in precaching these bitmaps as it can't impact jank.
644     // We also don't know if we even will spin up a hardware-accelerated
645     // window or not.
646     if (!RenderThread::hasInstance()) return;
647     RenderThread* renderThread = &RenderThread::getInstance();
648     SETUP_TASK(prepareToDraw);
649     args->thread = renderThread;
650     bitmap.ref();
651     args->bitmap = &bitmap;
652     nsecs_t lastVsync = renderThread->timeLord().latestVsync();
653     nsecs_t estimatedNextVsync = lastVsync + renderThread->timeLord().frameIntervalNanos();
654     nsecs_t timeToNextVsync = estimatedNextVsync - systemTime(CLOCK_MONOTONIC);
655     // We expect the UI thread to take 4ms and for RT to be active from VSYNC+4ms to
656     // VSYNC+12ms or so, so aim for the gap during which RT is expected to
657     // be idle
658     // TODO: Make this concept a first-class supported thing? RT could use
659     // knowledge of pending draws to better schedule this task
660     if (timeToNextVsync > -6_ms && timeToNextVsync < 1_ms) {
661         renderThread->queueAt(task, estimatedNextVsync + 8_ms);
662     } else {
663         renderThread->queue(task);
664     }
665 }
666 
CREATE_BRIDGE2(allocateHardwareBitmap,RenderThread * thread,SkBitmap * bitmap)667 CREATE_BRIDGE2(allocateHardwareBitmap, RenderThread* thread, SkBitmap* bitmap) {
668     sk_sp<Bitmap> hardwareBitmap = Bitmap::allocateHardwareBitmap(*args->thread, *args->bitmap);
669     return hardwareBitmap.release();
670 }
671 
allocateHardwareBitmap(SkBitmap & bitmap)672 sk_sp<Bitmap> RenderProxy::allocateHardwareBitmap(SkBitmap& bitmap) {
673     SETUP_TASK(allocateHardwareBitmap);
674     args->bitmap = &bitmap;
675     args->thread = &RenderThread::getInstance();
676     sk_sp<Bitmap> hardwareBitmap(reinterpret_cast<Bitmap*>(staticPostAndWait(task)));
677     return hardwareBitmap;
678 }
679 
CREATE_BRIDGE3(copyGraphicBufferInto,RenderThread * thread,GraphicBuffer * buffer,SkBitmap * bitmap)680 CREATE_BRIDGE3(copyGraphicBufferInto, RenderThread* thread, GraphicBuffer* buffer, SkBitmap* bitmap) {
681     return (void*) args->thread->readback().copyGraphicBufferInto(args->buffer, args->bitmap);
682 }
683 
copyGraphicBufferInto(GraphicBuffer * buffer,SkBitmap * bitmap)684 int RenderProxy::copyGraphicBufferInto(GraphicBuffer* buffer, SkBitmap* bitmap) {
685     RenderThread& thread = RenderThread::getInstance();
686     if (Properties::isSkiaEnabled() && gettid() == thread.getTid()) {
687         //TODO: fix everything that hits this. We should never be triggering a readback ourselves.
688         return (int) thread.readback().copyGraphicBufferInto(buffer, bitmap);
689     } else {
690         SETUP_TASK(copyGraphicBufferInto);
691         args->thread = &thread;
692         args->bitmap = bitmap;
693         args->buffer = buffer;
694         return static_cast<int>(reinterpret_cast<intptr_t>(staticPostAndWait(task)));
695     }
696 }
697 
CREATE_BRIDGE2(onBitmapDestroyed,RenderThread * thread,uint32_t pixelRefId)698 CREATE_BRIDGE2(onBitmapDestroyed, RenderThread* thread, uint32_t pixelRefId) {
699     args->thread->renderState().onBitmapDestroyed(args->pixelRefId);
700     return nullptr;
701 }
702 
onBitmapDestroyed(uint32_t pixelRefId)703 void RenderProxy::onBitmapDestroyed(uint32_t pixelRefId) {
704     if (!RenderThread::hasInstance()) return;
705     SETUP_TASK(onBitmapDestroyed);
706     RenderThread& thread = RenderThread::getInstance();
707     args->thread = &thread;
708     args->pixelRefId = pixelRefId;
709     thread.queue(task);
710 }
711 
disableVsync()712 void RenderProxy::disableVsync() {
713     Properties::disableVsync = true;
714 }
715 
post(RenderTask * task)716 void RenderProxy::post(RenderTask* task) {
717     mRenderThread.queue(task);
718 }
719 
postAndWait(MethodInvokeRenderTask * task)720 void* RenderProxy::postAndWait(MethodInvokeRenderTask* task) {
721     void* retval;
722     task->setReturnPtr(&retval);
723     SignalingRenderTask syncTask(task, &mSyncMutex, &mSyncCondition);
724     AutoMutex _lock(mSyncMutex);
725     mRenderThread.queue(&syncTask);
726     while (!syncTask.hasRun()) {
727         mSyncCondition.wait(mSyncMutex);
728     }
729     return retval;
730 }
731 
staticPostAndWait(MethodInvokeRenderTask * task)732 void* RenderProxy::staticPostAndWait(MethodInvokeRenderTask* task) {
733     RenderThread& thread = RenderThread::getInstance();
734     LOG_ALWAYS_FATAL_IF(gettid() == thread.getTid());
735     void* retval;
736     task->setReturnPtr(&retval);
737     thread.queueAndWait(task);
738     return retval;
739 }
740 
741 } /* namespace renderthread */
742 } /* namespace uirenderer */
743 } /* namespace android */
744