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