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