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 "DeferredLayerUpdater.h"
20 #include "Readback.h"
21 #include "ShaderCache.h"
22 #include "LightingInfo.h"
23 #include "SkiaPipeline.h"
24 #include "SkiaProfileRenderer.h"
25 #include "VkInteropFunctorDrawable.h"
26 #include "renderstate/RenderState.h"
27 #include "renderthread/Frame.h"
28 
29 #include <SkSurface.h>
30 #include <SkTypes.h>
31 
32 #include <GrContext.h>
33 #include <GrTypes.h>
34 #include <vk/GrVkTypes.h>
35 
36 #include <cutils/properties.h>
37 #include <strings.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)
46         : SkiaPipeline(thread), mVkManager(thread.vulkanManager()) {
47     thread.renderState().registerContextCallback(this);
48 }
49 
~SkiaVulkanPipeline()50 SkiaVulkanPipeline::~SkiaVulkanPipeline() {
51     mRenderThread.renderState().removeContextCallback(this);
52 }
53 
makeCurrent()54 MakeCurrentResult SkiaVulkanPipeline::makeCurrent() {
55     return MakeCurrentResult::AlreadyCurrent;
56 }
57 
getFrame()58 Frame SkiaVulkanPipeline::getFrame() {
59     LOG_ALWAYS_FATAL_IF(mVkSurface == nullptr, "getFrame() called on a context with no surface!");
60     return mVkManager.dequeueNextBuffer(mVkSurface);
61 }
62 
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)63 bool SkiaVulkanPipeline::draw(const Frame& frame, const SkRect& screenDirty, const SkRect& dirty,
64                               const LightGeometry& lightGeometry,
65                               LayerUpdateQueue* layerUpdateQueue, const Rect& contentDrawBounds,
66                               bool opaque, const LightInfo& lightInfo,
67                               const std::vector<sp<RenderNode>>& renderNodes,
68                               FrameInfoVisualizer* profiler) {
69     sk_sp<SkSurface> backBuffer = mVkSurface->getCurrentSkSurface();
70     if (backBuffer.get() == nullptr) {
71         return false;
72     }
73     LightingInfo::updateLighting(lightGeometry, lightInfo);
74     renderFrame(*layerUpdateQueue, dirty, renderNodes, opaque, contentDrawBounds, backBuffer,
75                 mVkSurface->getCurrentPreTransform());
76     ShaderCache::get().onVkFrameFlushed(mRenderThread.getGrContext());
77     layerUpdateQueue->clear();
78 
79     // Draw visual debugging features
80     if (CC_UNLIKELY(Properties::showDirtyRegions ||
81                     ProfileType::None != Properties::getProfileType())) {
82         SkCanvas* profileCanvas = backBuffer->getCanvas();
83         SkiaProfileRenderer profileRenderer(profileCanvas);
84         profiler->draw(profileRenderer);
85         profileCanvas->flush();
86     }
87 
88     // Log memory statistics
89     if (CC_UNLIKELY(Properties::debugLevel != kDebugDisabled)) {
90         dumpResourceCacheUsage();
91     }
92 
93     return true;
94 }
95 
swapBuffers(const Frame & frame,bool drew,const SkRect & screenDirty,FrameInfo * currentFrameInfo,bool * requireSwap)96 bool SkiaVulkanPipeline::swapBuffers(const Frame& frame, bool drew, const SkRect& screenDirty,
97                                      FrameInfo* currentFrameInfo, bool* requireSwap) {
98     *requireSwap = drew;
99 
100     // Even if we decided to cancel the frame, from the perspective of jank
101     // metrics the frame was swapped at this point
102     currentFrameInfo->markSwapBuffers();
103 
104     if (*requireSwap) {
105         mVkManager.swapBuffers(mVkSurface, screenDirty);
106     }
107 
108     return *requireSwap;
109 }
110 
createTextureLayer()111 DeferredLayerUpdater* SkiaVulkanPipeline::createTextureLayer() {
112     mRenderThread.requireVkContext();
113 
114     return new DeferredLayerUpdater(mRenderThread.renderState());
115 }
116 
onStop()117 void SkiaVulkanPipeline::onStop() {}
118 
setSurface(ANativeWindow * surface,SwapBehavior swapBehavior)119 bool SkiaVulkanPipeline::setSurface(ANativeWindow* surface, SwapBehavior swapBehavior) {
120     if (mVkSurface) {
121         mVkManager.destroySurface(mVkSurface);
122         mVkSurface = nullptr;
123     }
124 
125     if (surface) {
126         mRenderThread.requireVkContext();
127         mVkSurface =
128                 mVkManager.createSurface(surface, mColorMode, mSurfaceColorSpace, mSurfaceColorType,
129                                          mRenderThread.getGrContext(), 0);
130     }
131 
132     return mVkSurface != nullptr;
133 }
134 
isSurfaceReady()135 bool SkiaVulkanPipeline::isSurfaceReady() {
136     return CC_UNLIKELY(mVkSurface != nullptr);
137 }
138 
isContextReady()139 bool SkiaVulkanPipeline::isContextReady() {
140     return CC_LIKELY(mVkManager.hasVkContext());
141 }
142 
invokeFunctor(const RenderThread & thread,Functor * functor)143 void SkiaVulkanPipeline::invokeFunctor(const RenderThread& thread, Functor* functor) {
144     VkInteropFunctorDrawable::vkInvokeFunctor(functor);
145 }
146 
allocateHardwareBitmap(renderthread::RenderThread & renderThread,SkBitmap & skBitmap)147 sk_sp<Bitmap> SkiaVulkanPipeline::allocateHardwareBitmap(renderthread::RenderThread& renderThread,
148                                                          SkBitmap& skBitmap) {
149     LOG_ALWAYS_FATAL("Unimplemented");
150     return nullptr;
151 }
152 
onContextDestroyed()153 void SkiaVulkanPipeline::onContextDestroyed() {
154     if (mVkSurface) {
155         mVkManager.destroySurface(mVkSurface);
156         mVkSurface = nullptr;
157     }
158 }
159 
160 } /* namespace skiapipeline */
161 } /* namespace uirenderer */
162 } /* namespace android */
163