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