summaryrefslogtreecommitdiff
path: root/libs/hwui/renderthread/VulkanSurface.h
blob: b8ccf7810b5d27ff87c1c90594473943ac35c8d9 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
/*
 * Copyright (C) 2019 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
#pragma once

#include <android-base/unique_fd.h>
#include <system/graphics.h>
#include <system/window.h>
#include <vulkan/vulkan.h>

#include <SkRefCnt.h>
#include <SkSize.h>

#include "IRenderPipeline.h"

class SkSurface;

namespace android {
namespace uirenderer {
namespace renderthread {

class VulkanManager;

class VulkanSurface {
public:
    static VulkanSurface* Create(ANativeWindow* window, ColorMode colorMode, SkColorType colorType,
                                 sk_sp<SkColorSpace> colorSpace, GrDirectContext* grContext,
                                 const VulkanManager& vkManager, uint32_t extraBuffers);
    ~VulkanSurface();

    sk_sp<SkSurface> getCurrentSkSurface() {
        return mCurrentBufferInfo ? mCurrentBufferInfo->skSurface : nullptr;
    }
    const SkMatrix& getCurrentPreTransform() { return mWindowInfo.preTransform; }

    const SkM44& getPixelSnapMatrix() const { return mWindowInfo.pixelSnapMatrix; }

private:
    /*
     * All structs/methods in this private section are specifically for use by the VulkanManager
     *
     */
    friend VulkanManager;
    struct NativeBufferInfo {
        sk_sp<SkSurface> skSurface;
        sp<ANativeWindowBuffer> buffer;
        // The fence is only valid when the buffer is dequeued, and should be
        // -1 any other time. When valid, we own the fd, and must ensure it is
        // closed: either by closing it explicitly when queueing the buffer,
        // or by passing ownership e.g. to ANativeWindow::cancelBuffer().
        base::unique_fd dequeue_fence;
        bool dequeued = false;
        uint32_t lastPresentedCount = 0;
        bool hasValidContents = false;
    };

    NativeBufferInfo* dequeueNativeBuffer();
    NativeBufferInfo* getCurrentBufferInfo() { return mCurrentBufferInfo; }
    bool presentCurrentBuffer(const SkRect& dirtyRect, int semaphoreFd);

    // The width and height are are the logical width and height for when submitting draws to the
    // surface. In reality if the window is rotated the underlying window may have the width and
    // height swapped.
    int logicalWidth() const { return mWindowInfo.size.width(); }
    int logicalHeight() const { return mWindowInfo.size.height(); }
    int getCurrentBuffersAge();

private:
    /*
     * All code below this line while logically available to VulkanManager should not be treated
     * as private to this class.
     *
     */

    // How many buffers we want to be able to use ourselves. We want 1 in active rendering with
    // 1 more queued, so 2. This will be added to NATIVE_WINDOW_MIN_UNDEQUEUED_BUFFERS, which is
    // how many buffers the consumer needs (eg, 1 for SurfaceFlinger), getting to a typically
    // triple-buffered queue as a result.
    static constexpr uint32_t sTargetBufferCount = 2;

    struct WindowInfo {
        SkISize size;
        uint32_t bufferFormat;
        android_dataspace dataspace;
        sk_sp<SkColorSpace> colorspace;
        int transform;
        size_t bufferCount;
        uint64_t windowUsageFlags;

        // size of the ANativeWindow if the inverse of transform requires us to swap width/height
        SkISize actualSize;
        // transform to be applied to the SkSurface to map the coordinates to the provided transform
        SkMatrix preTransform;
        SkM44 pixelSnapMatrix;
    };

    VulkanSurface(ANativeWindow* window, const WindowInfo& windowInfo, GrDirectContext* grContext);
    static bool InitializeWindowInfoStruct(ANativeWindow* window, ColorMode colorMode,
                                           SkColorType colorType, sk_sp<SkColorSpace> colorSpace,
                                           const VulkanManager& vkManager, uint32_t extraBuffers,
                                           WindowInfo* outWindowInfo);
    static bool UpdateWindow(ANativeWindow* window, const WindowInfo& windowInfo);
    void releaseBuffers();

    // TODO: This number comes from ui/BufferQueueDefs. We're not pulling the
    // header in so that we don't need to depend on libui, but we should share
    // this constant somewhere. But right now it's okay to keep here because we
    // can't safely change the slot count anyways.
    static constexpr size_t kNumBufferSlots = 64;
    // TODO: Just use a vector?
    NativeBufferInfo mNativeBuffers[kNumBufferSlots];

    sp<ANativeWindow> mNativeWindow;
    WindowInfo mWindowInfo;
    GrDirectContext* mGrContext;

    uint32_t mPresentCount = 0;
    NativeBufferInfo* mCurrentBufferInfo = nullptr;
};

} /* namespace renderthread */
} /* namespace uirenderer */
} /* namespace android */