/* * Copyright (C) 2018 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #include "VkFunctorDrawable.h" #include <private/hwui/DrawVkInfo.h> #include <GrBackendDrawableInfo.h> #include <SkAndroidFrameworkUtils.h> #include <SkImage.h> #include <utils/Color.h> #include <utils/Trace.h> #include <utils/TraceUtils.h> #include <vk/GrVkTypes.h> #include <thread> #include "renderthread/RenderThread.h" #include "renderthread/VulkanManager.h" #include "thread/ThreadBase.h" #include "utils/TimeUtils.h" namespace android { namespace uirenderer { namespace skiapipeline { VkFunctorDrawHandler::VkFunctorDrawHandler(sp<WebViewFunctor::Handle> functor_handle, const SkMatrix& matrix, const SkIRect& clip, const SkImageInfo& image_info) : INHERITED() , mFunctorHandle(functor_handle) , mMatrix(matrix) , mClip(clip) , mImageInfo(image_info) {} VkFunctorDrawHandler::~VkFunctorDrawHandler() { if (mDrawn) { mFunctorHandle->postDrawVk(); } } void VkFunctorDrawHandler::draw(const GrBackendDrawableInfo& info) { ATRACE_CALL(); if (!renderthread::RenderThread::isCurrent()) LOG_ALWAYS_FATAL("VkFunctorDrawHandler::draw not called on render thread"); GrVkDrawableInfo vulkan_info; if (!info.getVkDrawableInfo(&vulkan_info)) { return; } renderthread::VulkanManager& vk_manager = renderthread::RenderThread::getInstance().vulkanManager(); mFunctorHandle->initVk(vk_manager.getVkFunctorInitParams()); SkMatrix44 mat4(mMatrix); VkFunctorDrawParams params{ .width = mImageInfo.width(), .height = mImageInfo.height(), .color_space_ptr = mImageInfo.colorSpace(), .clip_left = mClip.fLeft, .clip_top = mClip.fTop, .clip_right = mClip.fRight, .clip_bottom = mClip.fBottom, }; mat4.asColMajorf(¶ms.transform[0]); params.secondary_command_buffer = vulkan_info.fSecondaryCommandBuffer; params.color_attachment_index = vulkan_info.fColorAttachmentIndex; params.compatible_render_pass = vulkan_info.fCompatibleRenderPass; params.format = vulkan_info.fFormat; mFunctorHandle->drawVk(params); mDrawn = true; vulkan_info.fDrawBounds->offset.x = mClip.fLeft; vulkan_info.fDrawBounds->offset.y = mClip.fTop; vulkan_info.fDrawBounds->extent.width = mClip.fRight - mClip.fLeft; vulkan_info.fDrawBounds->extent.height = mClip.fBottom - mClip.fTop; } VkFunctorDrawable::~VkFunctorDrawable() {} void VkFunctorDrawable::onDraw(SkCanvas* canvas) { // "canvas" is either SkNWayCanvas created by SkiaPipeline::tryCapture (SKP capture use case) or // AlphaFilterCanvas (used by RenderNodeDrawable to apply alpha in certain cases). // "VkFunctorDrawable::onDraw" is not invoked for the most common case, when drawing in a GPU // canvas. if (canvas->getGrContext() == nullptr) { // We're dumping a picture, render a light-blue rectangle instead SkPaint paint; paint.setColor(0xFF81D4FA); canvas->drawRect(mBounds, paint); } else { // Handle the case when "canvas" is AlphaFilterCanvas. Find the wrapped GPU canvas. SkCanvas* gpuCanvas = SkAndroidFrameworkUtils::getBaseWrappedCanvas(canvas); // Enforce "canvas" must be an AlphaFilterCanvas. For GPU canvas, the call should come from // onSnapGpuDrawHandler. LOG_ALWAYS_FATAL_IF(gpuCanvas == canvas, "VkFunctorDrawable::onDraw() should not be called with a GPU canvas!"); // This will invoke onSnapGpuDrawHandler and regular draw flow. gpuCanvas->drawDrawable(this); } } std::unique_ptr<FunctorDrawable::GpuDrawHandler> VkFunctorDrawable::onSnapGpuDrawHandler( GrBackendApi backendApi, const SkMatrix& matrix, const SkIRect& clip, const SkImageInfo& image_info) { if (backendApi != GrBackendApi::kVulkan) { return nullptr; } std::unique_ptr<VkFunctorDrawHandler> draw; if (mAnyFunctor.index() == 0) { return std::make_unique<VkFunctorDrawHandler>(std::get<0>(mAnyFunctor).handle, matrix, clip, image_info); } else { LOG_ALWAYS_FATAL("Not implemented"); } } } // namespace skiapipeline } // namespace uirenderer } // namespace android