1 /*
2 * Copyright (C) 2016 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 "SkiaVulkanPipeline.h"
18
19 #include <GrDirectContext.h>
20 #include <GrTypes.h>
21 #include <SkSurface.h>
22 #include <SkTypes.h>
23 #include <cutils/properties.h>
24 #include <gui/TraceUtils.h>
25 #include <strings.h>
26 #include <vk/GrVkTypes.h>
27
28 #include "DeferredLayerUpdater.h"
29 #include "LightingInfo.h"
30 #include "Readback.h"
31 #include "ShaderCache.h"
32 #include "SkiaPipeline.h"
33 #include "SkiaProfileRenderer.h"
34 #include "VkInteropFunctorDrawable.h"
35 #include "renderstate/RenderState.h"
36 #include "renderthread/Frame.h"
37 #include "renderthread/IRenderPipeline.h"
38
39 using namespace android::uirenderer::renderthread;
40
41 namespace android {
42 namespace uirenderer {
43 namespace skiapipeline {
44
SkiaVulkanPipeline(renderthread::RenderThread & thread)45 SkiaVulkanPipeline::SkiaVulkanPipeline(renderthread::RenderThread& thread) : SkiaPipeline(thread) {
46 thread.renderState().registerContextCallback(this);
47 }
48
~SkiaVulkanPipeline()49 SkiaVulkanPipeline::~SkiaVulkanPipeline() {
50 mRenderThread.renderState().removeContextCallback(this);
51 }
52
vulkanManager()53 VulkanManager& SkiaVulkanPipeline::vulkanManager() {
54 return mRenderThread.vulkanManager();
55 }
56
makeCurrent()57 MakeCurrentResult SkiaVulkanPipeline::makeCurrent() {
58 // In case the surface was destroyed (e.g. a previous trimMemory call) we
59 // need to recreate it here.
60 if (mHardwareBuffer) {
61 mRenderThread.requireVkContext();
62 } else if (!isSurfaceReady() && mNativeWindow) {
63 setSurface(mNativeWindow.get(), SwapBehavior::kSwap_default);
64 }
65 return isContextReady() ? MakeCurrentResult::AlreadyCurrent : MakeCurrentResult::Failed;
66 }
67
getFrame()68 Frame SkiaVulkanPipeline::getFrame() {
69 LOG_ALWAYS_FATAL_IF(mVkSurface == nullptr, "getFrame() called on a context with no surface!");
70 return vulkanManager().dequeueNextBuffer(mVkSurface);
71 }
72
draw(const Frame & frame,const SkRect & screenDirty,const SkRect & dirty,const LightGeometry & lightGeometry,LayerUpdateQueue * layerUpdateQueue,const Rect & contentDrawBounds,bool opaque,const LightInfo & lightInfo,const std::vector<sp<RenderNode>> & renderNodes,FrameInfoVisualizer * profiler,const HardwareBufferRenderParams & bufferParams)73 IRenderPipeline::DrawResult SkiaVulkanPipeline::draw(
74 const Frame& frame, const SkRect& screenDirty, const SkRect& dirty,
75 const LightGeometry& lightGeometry, LayerUpdateQueue* layerUpdateQueue,
76 const Rect& contentDrawBounds, bool opaque, const LightInfo& lightInfo,
77 const std::vector<sp<RenderNode>>& renderNodes, FrameInfoVisualizer* profiler,
78 const HardwareBufferRenderParams& bufferParams) {
79 sk_sp<SkSurface> backBuffer;
80 SkMatrix preTransform;
81 if (mHardwareBuffer) {
82 backBuffer = getBufferSkSurface(bufferParams);
83 preTransform = bufferParams.getTransform();
84 } else {
85 backBuffer = mVkSurface->getCurrentSkSurface();
86 preTransform = mVkSurface->getCurrentPreTransform();
87 }
88
89 if (backBuffer.get() == nullptr) {
90 return {false, -1};
91 }
92
93 // update the coordinates of the global light position based on surface rotation
94 SkPoint lightCenter = preTransform.mapXY(lightGeometry.center.x, lightGeometry.center.y);
95 LightGeometry localGeometry = lightGeometry;
96 localGeometry.center.x = lightCenter.fX;
97 localGeometry.center.y = lightCenter.fY;
98
99 LightingInfo::updateLighting(localGeometry, lightInfo);
100 renderFrame(*layerUpdateQueue, dirty, renderNodes, opaque, contentDrawBounds, backBuffer,
101 preTransform);
102
103 // Draw visual debugging features
104 if (CC_UNLIKELY(Properties::showDirtyRegions ||
105 ProfileType::None != Properties::getProfileType())) {
106 SkCanvas* profileCanvas = backBuffer->getCanvas();
107 SkAutoCanvasRestore saver(profileCanvas, true);
108 profileCanvas->concat(mVkSurface->getCurrentPreTransform());
109 SkiaProfileRenderer profileRenderer(profileCanvas, frame.width(), frame.height());
110 profiler->draw(profileRenderer);
111 }
112
113 nsecs_t submissionTime = IRenderPipeline::DrawResult::kUnknownTime;
114 {
115 ATRACE_NAME("flush commands");
116 submissionTime = vulkanManager().finishFrame(backBuffer.get());
117 }
118 layerUpdateQueue->clear();
119
120 // Log memory statistics
121 if (CC_UNLIKELY(Properties::debugLevel != kDebugDisabled)) {
122 dumpResourceCacheUsage();
123 }
124
125 return {true, submissionTime};
126 }
127
swapBuffers(const Frame & frame,bool drew,const SkRect & screenDirty,FrameInfo * currentFrameInfo,bool * requireSwap)128 bool SkiaVulkanPipeline::swapBuffers(const Frame& frame, bool drew, const SkRect& screenDirty,
129 FrameInfo* currentFrameInfo, bool* requireSwap) {
130 // Even if we decided to cancel the frame, from the perspective of jank
131 // metrics the frame was swapped at this point
132 currentFrameInfo->markSwapBuffers();
133
134 if (mHardwareBuffer) {
135 return false;
136 }
137
138 *requireSwap = drew;
139
140 if (*requireSwap) {
141 vulkanManager().swapBuffers(mVkSurface, screenDirty);
142 }
143
144 return *requireSwap;
145 }
146
createTextureLayer()147 DeferredLayerUpdater* SkiaVulkanPipeline::createTextureLayer() {
148 mRenderThread.requireVkContext();
149
150 return new DeferredLayerUpdater(mRenderThread.renderState());
151 }
152
onStop()153 void SkiaVulkanPipeline::onStop() {}
154
flush()155 [[nodiscard]] android::base::unique_fd SkiaVulkanPipeline::flush() {
156 int fence = -1;
157 vulkanManager().createReleaseFence(&fence, mRenderThread.getGrContext());
158 return android::base::unique_fd(fence);
159 }
160
161 // We can safely ignore the swap behavior because VkManager will always operate
162 // in a mode equivalent to EGLManager::SwapBehavior::kBufferAge
setSurface(ANativeWindow * surface,SwapBehavior)163 bool SkiaVulkanPipeline::setSurface(ANativeWindow* surface, SwapBehavior /*swapBehavior*/) {
164 mNativeWindow = surface;
165
166 if (mVkSurface) {
167 vulkanManager().destroySurface(mVkSurface);
168 mVkSurface = nullptr;
169 }
170
171 if (surface) {
172 mRenderThread.requireVkContext();
173 mVkSurface =
174 vulkanManager().createSurface(surface, mColorMode, mSurfaceColorSpace,
175 mSurfaceColorType, mRenderThread.getGrContext(), 0);
176 }
177
178 return mVkSurface != nullptr;
179 }
180
setTargetSdrHdrRatio(float ratio)181 void SkiaVulkanPipeline::setTargetSdrHdrRatio(float ratio) {
182 SkiaPipeline::setTargetSdrHdrRatio(ratio);
183 if (mVkSurface) {
184 mVkSurface->setColorSpace(mSurfaceColorSpace);
185 }
186 }
187
isSurfaceReady()188 bool SkiaVulkanPipeline::isSurfaceReady() {
189 return CC_UNLIKELY(mVkSurface != nullptr);
190 }
191
isContextReady()192 bool SkiaVulkanPipeline::isContextReady() {
193 return CC_LIKELY(vulkanManager().hasVkContext());
194 }
195
invokeFunctor(const RenderThread & thread,Functor * functor)196 void SkiaVulkanPipeline::invokeFunctor(const RenderThread& thread, Functor* functor) {
197 VkInteropFunctorDrawable::vkInvokeFunctor(functor);
198 }
199
allocateHardwareBitmap(renderthread::RenderThread & renderThread,SkBitmap & skBitmap)200 sk_sp<Bitmap> SkiaVulkanPipeline::allocateHardwareBitmap(renderthread::RenderThread& renderThread,
201 SkBitmap& skBitmap) {
202 LOG_ALWAYS_FATAL("Unimplemented");
203 return nullptr;
204 }
205
onContextDestroyed()206 void SkiaVulkanPipeline::onContextDestroyed() {
207 if (mVkSurface) {
208 vulkanManager().destroySurface(mVkSurface);
209 mVkSurface = nullptr;
210 }
211 }
212
getPixelSnapMatrix() const213 const SkM44& SkiaVulkanPipeline::getPixelSnapMatrix() const {
214 return mVkSurface->getPixelSnapMatrix();
215 }
216
217 } /* namespace skiapipeline */
218 } /* namespace uirenderer */
219 } /* namespace android */
220