前一章Android渲染--重温硬件加速上我们主要介绍了硬件加速在View树更新的时候收集绘制OP,生成DisplayList,接下来就是要开始绘制。
绘制流程主要是在CanvasContext准备完后,绘制一帧的数据就准备好了。绘制会交给Pipeline做处理,最新版本(Android12)有2种类型的Pipeline,比如SkiaVulkanPipeline。
CanvasContext* CanvasContext::create(RenderThread& thread, bool translucent,
76 RenderNode* rootRenderNode, IContextFactory* contextFactory) {
77 auto renderType = Properties::getRenderPipelineType();
78
79 switch (renderType) {
80 case RenderPipelineType::SkiaGL:
81 return new CanvasContext(thread, translucent, rootRenderNode, contextFactory,
82 std::make_unique(thread));
83 case RenderPipelineType::SkiaVulkan:
84 return new CanvasContext(thread, translucent, rootRenderNode, contextFactory,
85 std::make_unique(thread));
86 default:
87 LOG_ALWAYS_FATAL("canvas context type %d not supported", (int32_t)renderType);
88 break;
89 }
90 return nullptr;
91 }
92
9.0之后google开始增强了Android的skia,将OpenGL的能力封装进Skia库里(Flutter的Skia图形库也是集成了OpenGl,Vulkan,Metal等)。SkiaVulkanPipeline 的会对 VulkanManager初始化,VulkanManager 是对 Vulkan 使用的封装。
void VulkanManager::initialize() {
343 std::lock_guard _lock{mInitializeLock};
344
345 if (mDevice != VK_NULL_HANDLE) {
346 return;
347 }
348
349 GET_PROC(EnumerateInstanceVersion);
350 uint32_t instanceVersion;
351 LOG_ALWAYS_FATAL_IF(mEnumerateInstanceVersion(&instanceVersion));
352 LOG_ALWAYS_FATAL_IF(instanceVersion < VK_MAKE_VERSION(1, 1, 0));
353
354 this->setupDevice(mExtensions, mPhysicalDeviceFeatures2);
355
356 mGetDeviceQueue(mDevice, mGraphicsQueueIndex, 0, &mGraphicsQueue);
357
358 if (Properties::enablePartialUpdates && Properties::useBufferAge) {
359 mSwapBehavior = SwapBehavior::BufferAge;
360 }
361 }
如果选用了Vulkan就终会执行到draw里,
bool SkiaVulkanPipeline::draw(const Frame& frame, const SkRect& screenDirty, const SkRect& dirty,
68 const LightGeometry& lightGeometry,
69 LayerUpdateQueue* layerUpdateQueue, const Rect& contentDrawBounds,
70 bool opaque, const LightInfo& lightInfo,
71 const std::vector>& renderNodes,
72 FrameInfoVisualizer* profiler) {
73 sk_sp backBuffer = mVkSurface->getCurrentSkSurface();
74 if (backBuffer.get() == nullptr) {
75 return false;
76 }
77 LightingInfo::updateLighting(lightGeometry, lightInfo);
78 renderFrame(*layerUpdateQueue, dirty, renderNodes, opaque, contentDrawBounds, backBuffer,
79 mVkSurface->getCurrentPreTransform());
80
81 // Draw visual debugging features
82 if (CC_UNLIKELY(Properties::showDirtyRegions ||
83 ProfileType::None != Properties::getProfileType())) {
84 SkCanvas* profileCanvas = backBuffer->getCanvas();
85 SkiaProfileRenderer profileRenderer(profileCanvas);
86 profiler->draw(profileRenderer);
87 }
88
89 {
90 ATRACE_NAME("flush commands");
91 vulkanManager().finishFrame(backBuffer.get());
92 }
93 layerUpdateQueue->clear();
94
95 // Log memory statistics
96 if (CC_UNLIKELY(Properties::debugLevel != kDebugDisabled)) {
97 dumpResourceCacheUsage();
98 }
99
100 return true;
101 }
Frame是描述一帧数据信息的,主要是宽,高,bufferAge,和Surface这几个属性。绘制开始时,由VulkanManager根据VulkanSurface的属性构建。
Frame SkiaVulkanPipeline::getFrame() {
63 LOG_ALWAYS_FATAL_IF(mVkSurface == nullptr, "getFrame() called on a context with no surface!");
64 return vulkanManager().dequeueNextBuffer(mVkSurface);
65 }
66
Frame VulkanManager::dequeueNextBuffer(VulkanSurface* surface) {
399 VulkanSurface::NativeBufferInfo* bufferInfo = surface->dequeueNativeBuffer();
400
401 if (bufferInfo == nullptr) {
402 ALOGE("VulkanSurface::dequeueNativeBuffer called with an invalid surface!");
403 return Frame(-1, -1, 0);
404 }
405
406 LOG_ALWAYS_FATAL_IF(!bufferInfo->dequeued);
407
408 if (bufferInfo->dequeue_fence != -1) {
409 struct sync_file_info* finfo = sync_file_info(bufferInfo->dequeue_fence);
410 bool isSignalPending = false;
411 if (finfo != NULL) {
412 isSignalPending = finfo->status != 1;
413 sync_file_info_free(finfo);
414 }
415 if (isSignalPending) {
416 int fence_clone = dup(bufferInfo->dequeue_fence);
417 if (fence_clone == -1) {
418 ALOGE("dup(fence) failed, stalling until signalled: %s (%d)", strerror(errno),
419 errno);
420 sync_wait(bufferInfo->dequeue_fence, -1 /* forever */);
421 } else {
422 VkSemaphoreCreateInfo semaphoreInfo;
423 semaphoreInfo.sType = VK_STRUCTURE_TYPE_SEMAPHORE_CREATE_INFO;
424 semaphoreInfo.pNext = nullptr;
425 semaphoreInfo.flags = 0;
426 VkSemaphore semaphore;
427 VkResult err = mCreateSemaphore(mDevice, &semaphoreInfo, nullptr, &semaphore);
428 if (err != VK_SUCCESS) {
429 ALOGE("Failed to create import semaphore, err: %d", err);
430 close(fence_clone);
431 sync_wait(bufferInfo->dequeue_fence, -1 /* forever */);
432 } else {
433 VkImportSemaphoreFdInfoKHR importInfo;
434 importInfo.sType = VK_STRUCTURE_TYPE_IMPORT_SEMAPHORE_FD_INFO_KHR;
435 importInfo.pNext = nullptr;
436 importInfo.semaphore = semaphore;
437 importInfo.flags = VK_SEMAPHORE_IMPORT_TEMPORARY_BIT;
438 importInfo.handleType = VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_SYNC_FD_BIT;
439 importInfo.fd = fence_clone;
440
441 err = mImportSemaphoreFdKHR(mDevice, &importInfo);
442 if (err != VK_SUCCESS) {
443 ALOGE("Failed to import semaphore, err: %d", err);
444 mDestroySemaphore(mDevice, semaphore, nullptr);
445 close(fence_clone);
446 sync_wait(bufferInfo->dequeue_fence, -1 /* forever */);
447 } else {
448 GrBackendSemaphore backendSemaphore;
449 backendSemaphore.initVulkan(semaphore);
450 // Skia will take ownership of the VkSemaphore and delete it once the wait
451 // has finished. The VkSemaphore also owns the imported fd, so it will
452 // close the fd when it is deleted.
453 bufferInfo->skSurface->wait(1, &backendSemaphore);
454 // The following flush blocks the GPU immediately instead of waiting for
455 // other drawing ops. It seems dequeue_fence is not respected otherwise.
456 // TODO: remove the flush after finding why backendSemaphore is not working.
457 bufferInfo->skSurface->flushAndSubmit();
458 }
459 }
460 }
461 }
462 }
463
464 int bufferAge = (mSwapBehavior == SwapBehavior::Discard) ? 0 : surface->getCurrentBuffersAge();
465 return Frame(surface->logicalWidth(), surface->logicalHeight(), bufferAge);
466 }
接上面的流程,会执行到SkiaPipeline的renderFrame函数。
void SkiaPipeline::renderFrame(const LayerUpdateQueue& layers, const SkRect& clip,
442 const std::vector>& nodes, bool opaque,
443 const Rect& contentDrawBounds, sk_sp surface,
444 const SkMatrix& preTransform) {
445 bool previousSkpEnabled = Properties::skpCaptureEnabled;
446 if (mPictureCapturedCallback) {
447 Properties::skpCaptureEnabled = true;
448 }
449
450 // Initialize the canvas for the current frame, that might be a recording canvas if SKP
451 // capture is enabled.
452 SkCanvas* canvas = tryCapture(surface.get(), nodes[0].get(), layers);
453
454 // draw all layers up front
455 renderLayersImpl(layers, opaque);
456
457 renderFrameImpl(clip, nodes, opaque, contentDrawBounds, canvas, preTransform);
458
459 endCapture(surface.get());
460
461 if (CC_UNLIKELY(Properties::debugOverdraw)) {
462 renderOverdraw(clip, nodes, contentDrawBounds, surface, preTransform);
463 }
464
465 Properties::skpCaptureEnabled = previousSkpEnabled;
466 }
这里主要对RenderNode做各个layer和内容的绘制,然后内容绘制完成后就执行swapbuffers,具体内部的渲染逻辑暂时先不展开了,有兴趣的读者可以自己研究下。
void VulkanManager::swapBuffers(VulkanSurface* surface, const SkRect& dirtyRect) {
561 if (CC_UNLIKELY(Properties::waitForGpuCompletion)) {
562 ATRACE_NAME("Finishing GPU work");
563 mDeviceWaitIdle(mDevice);
564 }
565
566 int fenceFd = -1;
567 if (mSwapSemaphore != VK_NULL_HANDLE) {
568 VkSemaphoreGetFdInfoKHR getFdInfo;
569 getFdInfo.sType = VK_STRUCTURE_TYPE_SEMAPHORE_GET_FD_INFO_KHR;
570 getFdInfo.pNext = nullptr;
571 getFdInfo.semaphore = mSwapSemaphore;
572 getFdInfo.handleType = VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_SYNC_FD_BIT;
573
574 VkResult err = mGetSemaphoreFdKHR(mDevice, &getFdInfo, &fenceFd);
575 ALOGE_IF(VK_SUCCESS != err, "VulkanManager::swapBuffers(): Failed to get semaphore Fd");
576 } else {
577 ALOGE("VulkanManager::swapBuffers(): Semaphore submission failed");
578
579 std::lock_guard lock(mGraphicsQueueMutex);
580 mQueueWaitIdle(mGraphicsQueue);
581 }
582 if (mDestroySemaphoreContext) {
583 destroy_semaphore(mDestroySemaphoreContext);
584 }
585
586 surface->presentCurrentBuffer(dirtyRect, fenceFd);
587 mSwapSemaphore = VK_NULL_HANDLE;
588 mDestroySemaphoreContext = nullptr;
589 }