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