1 // Copyright 2017 The Dawn Authors
2 //
3 // Licensed under the Apache License, Version 2.0 (the "License");
4 // you may not use this file except in compliance with the License.
5 // You may obtain a copy of the License at
6 //
7 //     http://www.apache.org/licenses/LICENSE-2.0
8 //
9 // Unless required by applicable law or agreed to in writing, software
10 // distributed under the License is distributed on an "AS IS" BASIS,
11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 // See the License for the specific language governing permissions and
13 // limitations under the License.
14 
15 #ifndef DAWNNATIVE_SWAPCHAIN_H_
16 #define DAWNNATIVE_SWAPCHAIN_H_
17 
18 #include "dawn_native/Error.h"
19 #include "dawn_native/Forward.h"
20 #include "dawn_native/ObjectBase.h"
21 
22 #include "dawn/dawn_wsi.h"
23 #include "dawn_native/dawn_platform.h"
24 
25 namespace dawn_native {
26 
27     MaybeError ValidateSwapChainDescriptor(const DeviceBase* device,
28                                            const Surface* surface,
29                                            const SwapChainDescriptor* descriptor);
30 
31     TextureDescriptor GetSwapChainBaseTextureDescriptor(NewSwapChainBase* swapChain);
32 
33     class SwapChainBase : public ObjectBase {
34       public:
35         SwapChainBase(DeviceBase* device);
36 
37         static SwapChainBase* MakeError(DeviceBase* device);
38 
39         // Dawn API
40         virtual void Configure(wgpu::TextureFormat format,
41                                wgpu::TextureUsage allowedUsage,
42                                uint32_t width,
43                                uint32_t height) = 0;
44         virtual TextureViewBase* GetCurrentTextureView() = 0;
45         virtual void Present() = 0;
46 
47       protected:
48         SwapChainBase(DeviceBase* device, ObjectBase::ErrorTag tag);
49         ~SwapChainBase() override;
50     };
51 
52     // The base class for implementation-based SwapChains that are deprecated.
53     class OldSwapChainBase : public SwapChainBase {
54       public:
55         OldSwapChainBase(DeviceBase* device, const SwapChainDescriptor* descriptor);
56 
57         static SwapChainBase* MakeError(DeviceBase* device);
58 
59         // Dawn API
60         void Configure(wgpu::TextureFormat format,
61                        wgpu::TextureUsage allowedUsage,
62                        uint32_t width,
63                        uint32_t height) override;
64         TextureViewBase* GetCurrentTextureView() override;
65         void Present() override;
66 
67       protected:
68         ~OldSwapChainBase() override;
69         const DawnSwapChainImplementation& GetImplementation();
70         virtual TextureBase* GetNextTextureImpl(const TextureDescriptor*) = 0;
71         virtual MaybeError OnBeforePresent(TextureViewBase* view) = 0;
72 
73       private:
74         MaybeError ValidateConfigure(wgpu::TextureFormat format,
75                                      wgpu::TextureUsage allowedUsage,
76                                      uint32_t width,
77                                      uint32_t height) const;
78         MaybeError ValidateGetCurrentTextureView() const;
79         MaybeError ValidatePresent() const;
80 
81         DawnSwapChainImplementation mImplementation = {};
82         wgpu::TextureFormat mFormat = {};
83         wgpu::TextureUsage mAllowedUsage;
84         uint32_t mWidth = 0;
85         uint32_t mHeight = 0;
86         Ref<TextureBase> mCurrentTexture;
87         Ref<TextureViewBase> mCurrentTextureView;
88     };
89 
90     // The base class for surface-based SwapChains that aren't ready yet.
91     class NewSwapChainBase : public SwapChainBase {
92       public:
93         NewSwapChainBase(DeviceBase* device,
94                          Surface* surface,
95                          const SwapChainDescriptor* descriptor);
96 
97         // This is called when the swapchain is detached when one of the following happens:
98         //
99         //  - The surface it is attached to is being destroyed.
100         //  - The swapchain is being replaced by another one on the surface.
101         //
102         // Note that the surface has a Ref on the last swapchain that was used on it so the
103         // SwapChain destructor will only be called after one of the things above happens.
104         //
105         // The call for the detaching previous swapchain should be called inside the backend
106         // implementation of SwapChains. This is to allow them to acquire any resources before
107         // calling detach to make a seamless transition from the previous swapchain.
108         //
109         // Likewise the call for the swapchain being destroyed must be done in the backend's
110         // swapchain's destructor since C++ says it is UB to call virtual methods in the base class
111         // destructor.
112         void DetachFromSurface();
113 
114         void SetIsAttached();
115 
116         // Dawn API
117         void Configure(wgpu::TextureFormat format,
118                        wgpu::TextureUsage allowedUsage,
119                        uint32_t width,
120                        uint32_t height) override;
121         TextureViewBase* GetCurrentTextureView() override;
122         void Present() override;
123 
124         uint32_t GetWidth() const;
125         uint32_t GetHeight() const;
126         wgpu::TextureFormat GetFormat() const;
127         wgpu::TextureUsage GetUsage() const;
128         wgpu::PresentMode GetPresentMode() const;
129         Surface* GetSurface() const;
130         bool IsAttached() const;
131         wgpu::BackendType GetBackendType() const;
132 
133       protected:
134         ~NewSwapChainBase() override;
135 
136       private:
137         bool mAttached;
138         uint32_t mWidth;
139         uint32_t mHeight;
140         wgpu::TextureFormat mFormat;
141         wgpu::TextureUsage mUsage;
142         wgpu::PresentMode mPresentMode;
143 
144         // This is a weak reference to the surface. If the surface is destroyed it will call
145         // DetachFromSurface and mSurface will be updated to nullptr.
146         Surface* mSurface = nullptr;
147         Ref<TextureViewBase> mCurrentTextureView;
148 
149         MaybeError ValidatePresent() const;
150         MaybeError ValidateGetCurrentTextureView() const;
151 
152         // GetCurrentTextureViewImpl and PresentImpl are guaranteed to be called in an interleaved
153         // manner, starting with GetCurrentTextureViewImpl.
154 
155         // The returned texture view must match the swapchain descriptor exactly.
156         virtual ResultOrError<TextureViewBase*> GetCurrentTextureViewImpl() = 0;
157         // The call to present must destroy the current view's texture so further access to it are
158         // invalid.
159         virtual MaybeError PresentImpl() = 0;
160 
161         // Guaranteed to be called exactly once during the lifetime of the SwapChain. After it is
162         // called no other virtual method can be called.
163         virtual void DetachFromSurfaceImpl() = 0;
164     };
165 
166 }  // namespace dawn_native
167 
168 #endif  // DAWNNATIVE_SWAPCHAIN_H_
169