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