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 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 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 82 RenderProxy::~RenderProxy() { 83 destroyContext(); 84 } 85 86 CREATE_BRIDGE1(destroyContext, CanvasContext* context) { 87 delete args->context; 88 return nullptr; 89 } 90 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 103 CREATE_BRIDGE2(setSwapBehavior, CanvasContext* context, SwapBehavior swapBehavior) { 104 args->context->setSwapBehavior(args->swapBehavior); 105 return nullptr; 106 } 107 108 void RenderProxy::setSwapBehavior(SwapBehavior swapBehavior) { 109 SETUP_TASK(setSwapBehavior); 110 args->context = mContext; 111 args->swapBehavior = swapBehavior; 112 post(task); 113 } 114 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 126 bool RenderProxy::loadSystemProperties() { 127 SETUP_TASK(loadSystemProperties); 128 args->context = mContext; 129 return (bool) postAndWait(task); 130 } 131 132 CREATE_BRIDGE2(setName, CanvasContext* context, const char* name) { 133 args->context->setName(std::string(args->name)); 134 return nullptr; 135 } 136 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 144 CREATE_BRIDGE2(initialize, CanvasContext* context, Surface* surface) { 145 args->context->initialize(args->surface); 146 return nullptr; 147 } 148 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 156 CREATE_BRIDGE2(updateSurface, CanvasContext* context, Surface* surface) { 157 args->context->updateSurface(args->surface); 158 return nullptr; 159 } 160 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 168 CREATE_BRIDGE2(pauseSurface, CanvasContext* context, Surface* surface) { 169 return (void*) args->context->pauseSurface(args->surface); 170 } 171 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 179 CREATE_BRIDGE2(setStopped, CanvasContext* context, bool stopped) { 180 args->context->setStopped(args->stopped); 181 return nullptr; 182 } 183 184 void RenderProxy::setStopped(bool stopped) { 185 SETUP_TASK(setStopped); 186 args->context = mContext; 187 args->stopped = stopped; 188 postAndWait(task); 189 } 190 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 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 208 CREATE_BRIDGE2(setLightCenter, CanvasContext* context, Vector3 lightCenter) { 209 args->context->setLightCenter(args->lightCenter); 210 return nullptr; 211 } 212 213 void RenderProxy::setLightCenter(const Vector3& lightCenter) { 214 SETUP_TASK(setLightCenter); 215 args->context = mContext; 216 args->lightCenter = lightCenter; 217 post(task); 218 } 219 220 CREATE_BRIDGE2(setOpaque, CanvasContext* context, bool opaque) { 221 args->context->setOpaque(args->opaque); 222 return nullptr; 223 } 224 225 void RenderProxy::setOpaque(bool opaque) { 226 SETUP_TASK(setOpaque); 227 args->context = mContext; 228 args->opaque = opaque; 229 post(task); 230 } 231 232 CREATE_BRIDGE2(setWideGamut, CanvasContext* context, bool wideGamut) { 233 args->context->setWideGamut(args->wideGamut); 234 return nullptr; 235 } 236 237 void RenderProxy::setWideGamut(bool wideGamut) { 238 SETUP_TASK(setWideGamut); 239 args->context = mContext; 240 args->wideGamut = wideGamut; 241 post(task); 242 } 243 244 int64_t* RenderProxy::frameInfo() { 245 return mDrawFrameTask.frameInfo(); 246 } 247 248 int RenderProxy::syncAndDrawFrame() { 249 return mDrawFrameTask.drawFrame(); 250 } 251 252 CREATE_BRIDGE1(destroy, CanvasContext* context) { 253 args->context->destroy(); 254 return nullptr; 255 } 256 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 266 CREATE_BRIDGE2(invokeFunctor, RenderThread* thread, Functor* functor) { 267 CanvasContext::invokeFunctor(*args->thread, args->functor); 268 return nullptr; 269 } 270 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 287 CREATE_BRIDGE1(createTextureLayer, CanvasContext* context) { 288 return args->context->createTextureLayer(); 289 } 290 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 299 CREATE_BRIDGE2(buildLayer, CanvasContext* context, RenderNode* node) { 300 args->context->buildLayer(args->node); 301 return nullptr; 302 } 303 304 void RenderProxy::buildLayer(RenderNode* node) { 305 SETUP_TASK(buildLayer); 306 args->context = mContext; 307 args->node = node; 308 postAndWait(task); 309 } 310 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 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 325 void RenderProxy::pushLayerUpdate(DeferredLayerUpdater* layer) { 326 mDrawFrameTask.pushLayerUpdate(layer); 327 } 328 329 void RenderProxy::cancelLayerUpdate(DeferredLayerUpdater* layer) { 330 mDrawFrameTask.removeLayerUpdate(layer); 331 } 332 333 CREATE_BRIDGE1(detachSurfaceTexture, DeferredLayerUpdater* layer) { 334 args->layer->detachSurfaceTexture(); 335 return nullptr; 336 } 337 338 void RenderProxy::detachSurfaceTexture(DeferredLayerUpdater* layer) { 339 SETUP_TASK(detachSurfaceTexture); 340 args->layer = layer; 341 postAndWait(task); 342 } 343 344 CREATE_BRIDGE1(destroyHardwareResources, CanvasContext* context) { 345 args->context->destroyHardwareResources(); 346 return nullptr; 347 } 348 349 void RenderProxy::destroyHardwareResources() { 350 SETUP_TASK(destroyHardwareResources); 351 args->context = mContext; 352 postAndWait(task); 353 } 354 355 CREATE_BRIDGE2(trimMemory, RenderThread* thread, int level) { 356 CanvasContext::trimMemory(*args->thread, args->level); 357 return nullptr; 358 } 359 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 371 CREATE_BRIDGE2(overrideProperty, const char* name, const char* value) { 372 Properties::overrideProperty(args->name, args->value); 373 return nullptr; 374 } 375 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 383 CREATE_BRIDGE0(fence) { 384 // Intentionally empty 385 return nullptr; 386 } 387 388 template <typename T> 389 void UNUSED(T t) {} 390 391 void RenderProxy::fence() { 392 SETUP_TASK(fence); 393 UNUSED(args); 394 postAndWait(task); 395 } 396 397 void RenderProxy::staticFence() { 398 SETUP_TASK(fence); 399 UNUSED(args); 400 staticPostAndWait(task); 401 } 402 403 CREATE_BRIDGE1(stopDrawing, CanvasContext* context) { 404 args->context->stopDrawing(); 405 return nullptr; 406 } 407 408 void RenderProxy::stopDrawing() { 409 SETUP_TASK(stopDrawing); 410 args->context = mContext; 411 postAndWait(task); 412 } 413 414 CREATE_BRIDGE1(notifyFramePending, CanvasContext* context) { 415 args->context->notifyFramePending(); 416 return nullptr; 417 } 418 419 void RenderProxy::notifyFramePending() { 420 SETUP_TASK(notifyFramePending); 421 args->context = mContext; 422 mRenderThread.queueAtFront(task); 423 } 424 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 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 449 CREATE_BRIDGE1(resetProfileInfo, CanvasContext* context) { 450 args->context->resetFrameStats(); 451 return nullptr; 452 } 453 454 void RenderProxy::resetProfileInfo() { 455 SETUP_TASK(resetProfileInfo); 456 args->context = mContext; 457 postAndWait(task); 458 } 459 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 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 473 CREATE_BRIDGE2(dumpGraphicsMemory, int fd, RenderThread* thread) { 474 args->thread->dumpGraphicsMemory(args->fd); 475 return nullptr; 476 } 477 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 486 CREATE_BRIDGE2(setProcessStatsBuffer, RenderThread* thread, int fd) { 487 args->thread->globalProfileData().switchStorageToAshmem(args->fd); 488 close(args->fd); 489 return nullptr; 490 } 491 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 500 CREATE_BRIDGE1(rotateProcessStatsBuffer, RenderThread* thread) { 501 args->thread->globalProfileData().rotateStorage(); 502 return nullptr; 503 } 504 505 void RenderProxy::rotateProcessStatsBuffer() { 506 SETUP_TASK(rotateProcessStatsBuffer); 507 auto& rt = RenderThread::getInstance(); 508 args->thread = &rt; 509 rt.queue(task); 510 } 511 512 int RenderProxy::getRenderThreadTid() { 513 return mRenderThread.getTid(); 514 } 515 516 CREATE_BRIDGE3(addRenderNode, CanvasContext* context, RenderNode* node, bool placeFront) { 517 args->context->addRenderNode(args->node, args->placeFront); 518 return nullptr; 519 } 520 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 529 CREATE_BRIDGE2(removeRenderNode, CanvasContext* context, RenderNode* node) { 530 args->context->removeRenderNode(args->node); 531 return nullptr; 532 } 533 534 void RenderProxy::removeRenderNode(RenderNode* node) { 535 SETUP_TASK(removeRenderNode); 536 args->context = mContext; 537 args->node = node; 538 post(task); 539 } 540 541 CREATE_BRIDGE2(drawRenderNode, CanvasContext* context, RenderNode* node) { 542 args->context->prepareAndDraw(args->node); 543 return nullptr; 544 } 545 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 554 void RenderProxy::setContentDrawBounds(int left, int top, int right, int bottom) { 555 mDrawFrameTask.setContentDrawBounds(left, top, right, bottom); 556 } 557 558 CREATE_BRIDGE1(serializeDisplayListTree, CanvasContext* context) { 559 args->context->serializeDisplayListTree(); 560 return nullptr; 561 } 562 563 void RenderProxy::serializeDisplayListTree() { 564 SETUP_TASK(serializeDisplayListTree); 565 args->context = mContext; 566 post(task); 567 } 568 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 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 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 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 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 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 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 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 657 CREATE_BRIDGE2(allocateHardwareBitmap, RenderThread* thread, SkBitmap* bitmap) { 658 sk_sp<Bitmap> hardwareBitmap = args->thread->allocateHardwareBitmap(*args->bitmap); 659 return hardwareBitmap.release(); 660 } 661 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 670 CREATE_BRIDGE3(copyGraphicBufferInto, RenderThread* thread, GraphicBuffer* buffer, SkBitmap* bitmap) { 671 return (void*) args->thread->readback().copyGraphicBufferInto(args->buffer, args->bitmap); 672 } 673 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 688 CREATE_BRIDGE2(onBitmapDestroyed, RenderThread* thread, uint32_t pixelRefId) { 689 args->thread->renderState().onBitmapDestroyed(args->pixelRefId); 690 return nullptr; 691 } 692 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 702 void RenderProxy::disableVsync() { 703 Properties::disableVsync = true; 704 } 705 706 void RenderProxy::post(RenderTask* task) { 707 mRenderThread.queue(task); 708 } 709 710 CREATE_BRIDGE1(repackVectorDrawableAtlas, RenderThread* thread) { 711 args->thread->cacheManager().acquireVectorDrawableAtlas()->repackIfNeeded( 712 args->thread->getGrContext()); 713 return nullptr; 714 } 715 716 void RenderProxy::repackVectorDrawableAtlas() { 717 RenderThread& thread = RenderThread::getInstance(); 718 SETUP_TASK(repackVectorDrawableAtlas); 719 args->thread = &thread; 720 thread.queue(task); 721 } 722 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 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