1 /*
2 * Copyright (C) 2018 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 "VkFunctorDrawable.h"
18 #include <private/hwui/DrawVkInfo.h>
19
20 #include <GrBackendDrawableInfo.h>
21 #include <SkAndroidFrameworkUtils.h>
22 #include <SkImage.h>
23 #include <SkM44.h>
24 #include <gui/TraceUtils.h>
25 #include <utils/Color.h>
26 #include <utils/Trace.h>
27 #include <vk/GrVkTypes.h>
28 #include <thread>
29 #include "renderthread/RenderThread.h"
30 #include "renderthread/VulkanManager.h"
31 #include "thread/ThreadBase.h"
32 #include "utils/TimeUtils.h"
33
34 namespace android {
35 namespace uirenderer {
36 namespace skiapipeline {
37
VkFunctorDrawHandler(sp<WebViewFunctor::Handle> functor_handle,const SkMatrix & matrix,const SkIRect & clip,const SkImageInfo & image_info)38 VkFunctorDrawHandler::VkFunctorDrawHandler(sp<WebViewFunctor::Handle> functor_handle,
39 const SkMatrix& matrix, const SkIRect& clip,
40 const SkImageInfo& image_info)
41 : INHERITED()
42 , mFunctorHandle(functor_handle)
43 , mMatrix(matrix)
44 , mClip(clip)
45 , mImageInfo(image_info) {}
46
~VkFunctorDrawHandler()47 VkFunctorDrawHandler::~VkFunctorDrawHandler() {
48 if (mDrawn) {
49 mFunctorHandle->postDrawVk();
50 }
51 }
52
draw(const GrBackendDrawableInfo & info)53 void VkFunctorDrawHandler::draw(const GrBackendDrawableInfo& info) {
54 ATRACE_CALL();
55 if (!renderthread::RenderThread::isCurrent())
56 LOG_ALWAYS_FATAL("VkFunctorDrawHandler::draw not called on render thread");
57
58 GrVkDrawableInfo vulkan_info;
59 if (!info.getVkDrawableInfo(&vulkan_info)) {
60 return;
61 }
62 renderthread::VulkanManager& vk_manager =
63 renderthread::RenderThread::getInstance().vulkanManager();
64 mFunctorHandle->initVk(vk_manager.getVkFunctorInitParams());
65
66 SkM44 mat4(mMatrix);
67 VkFunctorDrawParams params{
68 .width = mImageInfo.width(),
69 .height = mImageInfo.height(),
70 .color_space_ptr = mImageInfo.colorSpace(),
71 .clip_left = mClip.fLeft,
72 .clip_top = mClip.fTop,
73 .clip_right = mClip.fRight,
74 .clip_bottom = mClip.fBottom,
75 .is_layer = !vulkan_info.fFromSwapchainOrAndroidWindow,
76 };
77 mat4.getColMajor(¶ms.transform[0]);
78 params.secondary_command_buffer = vulkan_info.fSecondaryCommandBuffer;
79 params.color_attachment_index = vulkan_info.fColorAttachmentIndex;
80 params.compatible_render_pass = vulkan_info.fCompatibleRenderPass;
81 params.format = vulkan_info.fFormat;
82
83 mFunctorHandle->drawVk(params);
84 mDrawn = true;
85
86 vulkan_info.fDrawBounds->offset.x = mClip.fLeft;
87 vulkan_info.fDrawBounds->offset.y = mClip.fTop;
88 vulkan_info.fDrawBounds->extent.width = mClip.fRight - mClip.fLeft;
89 vulkan_info.fDrawBounds->extent.height = mClip.fBottom - mClip.fTop;
90 }
91
~VkFunctorDrawable()92 VkFunctorDrawable::~VkFunctorDrawable() {}
93
onDraw(SkCanvas * canvas)94 void VkFunctorDrawable::onDraw(SkCanvas* canvas) {
95 // "canvas" is either SkNWayCanvas created by SkiaPipeline::tryCapture (SKP capture use case) or
96 // AlphaFilterCanvas (used by RenderNodeDrawable to apply alpha in certain cases).
97 // "VkFunctorDrawable::onDraw" is not invoked for the most common case, when drawing in a GPU
98 // canvas.
99
100 if (canvas->recordingContext() == nullptr) {
101 // We're dumping a picture, render a light-blue rectangle instead
102 SkPaint paint;
103 paint.setColor(0xFF81D4FA);
104 canvas->drawRect(mBounds, paint);
105 } else {
106 // Handle the case when "canvas" is AlphaFilterCanvas. Find the wrapped GPU canvas.
107 SkCanvas* gpuCanvas = SkAndroidFrameworkUtils::getBaseWrappedCanvas(canvas);
108 // Enforce "canvas" must be an AlphaFilterCanvas. For GPU canvas, the call should come from
109 // onSnapGpuDrawHandler.
110 LOG_ALWAYS_FATAL_IF(gpuCanvas == canvas,
111 "VkFunctorDrawable::onDraw() should not be called with a GPU canvas!");
112
113 // This will invoke onSnapGpuDrawHandler and regular draw flow.
114 gpuCanvas->drawDrawable(this);
115 }
116 }
117
onSnapGpuDrawHandler(GrBackendApi backendApi,const SkMatrix & matrix,const SkIRect & clip,const SkImageInfo & image_info)118 std::unique_ptr<FunctorDrawable::GpuDrawHandler> VkFunctorDrawable::onSnapGpuDrawHandler(
119 GrBackendApi backendApi, const SkMatrix& matrix, const SkIRect& clip,
120 const SkImageInfo& image_info) {
121 if (backendApi != GrBackendApi::kVulkan) {
122 return nullptr;
123 }
124 std::unique_ptr<VkFunctorDrawHandler> draw;
125 return std::make_unique<VkFunctorDrawHandler>(mWebViewHandle, matrix, clip, image_info);
126 }
127
128 } // namespace skiapipeline
129 } // namespace uirenderer
130 } // namespace android
131