1 /*
2  * Copyright (C) 2019 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 #pragma once
17 
18 #include <android-base/unique_fd.h>
19 #include <system/graphics.h>
20 #include <system/window.h>
21 #include <vulkan/vulkan.h>
22 
23 #include <SkColorSpace.h>
24 #include <SkRefCnt.h>
25 #include <SkSize.h>
26 
27 #include "IRenderPipeline.h"
28 
29 class SkSurface;
30 
31 namespace android {
32 namespace uirenderer {
33 namespace renderthread {
34 
35 class VulkanManager;
36 
37 class VulkanSurface {
38 public:
39     static VulkanSurface* Create(ANativeWindow* window, ColorMode colorMode, SkColorType colorType,
40                                  sk_sp<SkColorSpace> colorSpace, GrDirectContext* grContext,
41                                  const VulkanManager& vkManager, uint32_t extraBuffers);
42     ~VulkanSurface();
43 
getCurrentSkSurface()44     sk_sp<SkSurface> getCurrentSkSurface() {
45         return mCurrentBufferInfo ? mCurrentBufferInfo->skSurface : nullptr;
46     }
getCurrentPreTransform()47     const SkMatrix& getCurrentPreTransform() { return mWindowInfo.preTransform; }
48 
49     void setColorSpace(sk_sp<SkColorSpace> colorSpace);
getPixelSnapMatrix()50     const SkM44& getPixelSnapMatrix() const { return mWindowInfo.pixelSnapMatrix; }
51 
52 private:
53     /*
54      * All structs/methods in this private section are specifically for use by the VulkanManager
55      *
56      */
57     friend VulkanManager;
58     struct NativeBufferInfo {
59         sk_sp<SkSurface> skSurface;
60         sp<ANativeWindowBuffer> buffer;
61         // The fence is only valid when the buffer is dequeued, and should be
62         // -1 any other time. When valid, we own the fd, and must ensure it is
63         // closed: either by closing it explicitly when queueing the buffer,
64         // or by passing ownership e.g. to ANativeWindow::cancelBuffer().
65         base::unique_fd dequeue_fence;
66         bool dequeued = false;
67         uint32_t lastPresentedCount = 0;
68         bool hasValidContents = false;
69     };
70 
71     NativeBufferInfo* dequeueNativeBuffer();
getCurrentBufferInfo()72     NativeBufferInfo* getCurrentBufferInfo() { return mCurrentBufferInfo; }
73     bool presentCurrentBuffer(const SkRect& dirtyRect, int semaphoreFd);
74 
75     // The width and height are are the logical width and height for when submitting draws to the
76     // surface. In reality if the window is rotated the underlying window may have the width and
77     // height swapped.
logicalWidth()78     int logicalWidth() const { return mWindowInfo.size.width(); }
logicalHeight()79     int logicalHeight() const { return mWindowInfo.size.height(); }
80     int getCurrentBuffersAge();
81 
82 private:
83     /*
84      * All code below this line while logically available to VulkanManager should not be treated
85      * as private to this class.
86      *
87      */
88 
89     // How many buffers we want to be able to use ourselves. We want 1 in active rendering with
90     // 1 more queued, so 2. This will be added to NATIVE_WINDOW_MIN_UNDEQUEUED_BUFFERS, which is
91     // how many buffers the consumer needs (eg, 1 for SurfaceFlinger), getting to a typically
92     // triple-buffered queue as a result.
93     static constexpr uint32_t sTargetBufferCount = 2;
94 
95     struct WindowInfo {
96         SkISize size;
97         uint32_t bufferFormat;
98         android_dataspace dataspace;
99         sk_sp<SkColorSpace> colorspace;
100         ColorMode colorMode;
101         int transform;
102         size_t bufferCount;
103         uint64_t windowUsageFlags;
104 
105         // size of the ANativeWindow if the inverse of transform requires us to swap width/height
106         SkISize actualSize;
107         // transform to be applied to the SkSurface to map the coordinates to the provided transform
108         SkMatrix preTransform;
109         SkM44 pixelSnapMatrix;
110     };
111 
112     VulkanSurface(ANativeWindow* window, const WindowInfo& windowInfo, GrDirectContext* grContext);
113     static bool InitializeWindowInfoStruct(ANativeWindow* window, ColorMode colorMode,
114                                            SkColorType colorType, sk_sp<SkColorSpace> colorSpace,
115                                            const VulkanManager& vkManager, uint32_t extraBuffers,
116                                            WindowInfo* outWindowInfo);
117     static bool UpdateWindow(ANativeWindow* window, const WindowInfo& windowInfo);
118     void releaseBuffers();
119     void invalidateBuffers();
120 
121     // TODO: This number comes from ui/BufferQueueDefs. We're not pulling the
122     // header in so that we don't need to depend on libui, but we should share
123     // this constant somewhere. But right now it's okay to keep here because we
124     // can't safely change the slot count anyways.
125     static constexpr size_t kNumBufferSlots = 64;
126     // TODO: Just use a vector?
127     NativeBufferInfo mNativeBuffers[kNumBufferSlots];
128 
129     sp<ANativeWindow> mNativeWindow;
130     WindowInfo mWindowInfo;
131     GrDirectContext* mGrContext;
132 
133     uint32_t mPresentCount = 0;
134     NativeBufferInfo* mCurrentBufferInfo = nullptr;
135 };
136 
137 } /* namespace renderthread */
138 } /* namespace uirenderer */
139 } /* namespace android */
140