• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 #include "dawn_native/SwapChain.h"
16 
17 #include "dawn_native/Device.h"
18 #include "dawn_native/Texture.h"
19 #include "dawn_native/ValidationUtils_autogen.h"
20 
21 namespace dawn_native {
22 
23     namespace {
24 
25         class ErrorSwapChain : public SwapChainBase {
26           public:
ErrorSwapChain(DeviceBase * device)27             ErrorSwapChain(DeviceBase* device) : SwapChainBase(device, ObjectBase::kError) {
28             }
29 
30           private:
GetNextTextureImpl(const TextureDescriptor *)31             TextureBase* GetNextTextureImpl(const TextureDescriptor*) override {
32                 UNREACHABLE();
33             }
34 
OnBeforePresent(TextureBase * texture)35             void OnBeforePresent(TextureBase* texture) override {
36                 UNREACHABLE();
37             }
38         };
39 
40     }  // anonymous namespace
41 
ValidateSwapChainDescriptor(const DeviceBase * device,const SwapChainDescriptor * descriptor)42     MaybeError ValidateSwapChainDescriptor(const DeviceBase* device,
43                                            const SwapChainDescriptor* descriptor) {
44         if (descriptor->implementation == 0) {
45             return DAWN_VALIDATION_ERROR("Null implementation for the swapchain");
46         }
47 
48         DawnSwapChainImplementation* impl =
49             reinterpret_cast<DawnSwapChainImplementation*>(descriptor->implementation);
50 
51         if (!impl->Init || !impl->Destroy || !impl->Configure || !impl->GetNextTexture ||
52             !impl->Present) {
53             return DAWN_VALIDATION_ERROR("Implementation is incomplete");
54         }
55 
56         return {};
57     }
58 
59     // SwapChain
60 
SwapChainBase(DeviceBase * device,const SwapChainDescriptor * descriptor)61     SwapChainBase::SwapChainBase(DeviceBase* device, const SwapChainDescriptor* descriptor)
62         : ObjectBase(device),
63           mImplementation(
64               *reinterpret_cast<DawnSwapChainImplementation*>(descriptor->implementation)) {
65     }
66 
SwapChainBase(DeviceBase * device,ObjectBase::ErrorTag tag)67     SwapChainBase::SwapChainBase(DeviceBase* device, ObjectBase::ErrorTag tag)
68         : ObjectBase(device, tag) {
69     }
70 
~SwapChainBase()71     SwapChainBase::~SwapChainBase() {
72         if (!IsError()) {
73             const auto& im = GetImplementation();
74             im.Destroy(im.userData);
75         }
76     }
77 
78     // static
MakeError(DeviceBase * device)79     SwapChainBase* SwapChainBase::MakeError(DeviceBase* device) {
80         return new ErrorSwapChain(device);
81     }
82 
Configure(dawn::TextureFormat format,dawn::TextureUsageBit allowedUsage,uint32_t width,uint32_t height)83     void SwapChainBase::Configure(dawn::TextureFormat format,
84                                   dawn::TextureUsageBit allowedUsage,
85                                   uint32_t width,
86                                   uint32_t height) {
87         if (GetDevice()->ConsumedError(ValidateConfigure(format, allowedUsage, width, height))) {
88             return;
89         }
90         ASSERT(!IsError());
91 
92         allowedUsage |= dawn::TextureUsageBit::Present;
93 
94         mFormat = format;
95         mAllowedUsage = allowedUsage;
96         mWidth = width;
97         mHeight = height;
98         mImplementation.Configure(mImplementation.userData, static_cast<DawnTextureFormat>(format),
99                                   static_cast<DawnTextureUsageBit>(allowedUsage), width, height);
100     }
101 
GetNextTexture()102     TextureBase* SwapChainBase::GetNextTexture() {
103         if (GetDevice()->ConsumedError(ValidateGetNextTexture())) {
104             return TextureBase::MakeError(GetDevice());
105         }
106         ASSERT(!IsError());
107 
108         TextureDescriptor descriptor;
109         descriptor.dimension = dawn::TextureDimension::e2D;
110         descriptor.size.width = mWidth;
111         descriptor.size.height = mHeight;
112         descriptor.size.depth = 1;
113         descriptor.arrayLayerCount = 1;
114         descriptor.sampleCount = 1;
115         descriptor.format = mFormat;
116         descriptor.mipLevelCount = 1;
117         descriptor.usage = mAllowedUsage;
118 
119         auto* texture = GetNextTextureImpl(&descriptor);
120         mLastNextTexture = texture;
121         return texture;
122     }
123 
Present(TextureBase * texture)124     void SwapChainBase::Present(TextureBase* texture) {
125         if (GetDevice()->ConsumedError(ValidatePresent(texture))) {
126             return;
127         }
128         ASSERT(!IsError());
129 
130         OnBeforePresent(texture);
131 
132         mImplementation.Present(mImplementation.userData);
133     }
134 
GetImplementation()135     const DawnSwapChainImplementation& SwapChainBase::GetImplementation() {
136         ASSERT(!IsError());
137         return mImplementation;
138     }
139 
ValidateConfigure(dawn::TextureFormat format,dawn::TextureUsageBit allowedUsage,uint32_t width,uint32_t height) const140     MaybeError SwapChainBase::ValidateConfigure(dawn::TextureFormat format,
141                                                 dawn::TextureUsageBit allowedUsage,
142                                                 uint32_t width,
143                                                 uint32_t height) const {
144         DAWN_TRY(GetDevice()->ValidateObject(this));
145 
146         DAWN_TRY(ValidateTextureUsageBit(allowedUsage));
147         DAWN_TRY(ValidateTextureFormat(format));
148 
149         if (width == 0 || height == 0) {
150             return DAWN_VALIDATION_ERROR("Swap chain cannot be configured to zero size");
151         }
152 
153         return {};
154     }
155 
ValidateGetNextTexture() const156     MaybeError SwapChainBase::ValidateGetNextTexture() const {
157         DAWN_TRY(GetDevice()->ValidateObject(this));
158 
159         if (mWidth == 0) {
160             // If width is 0, it implies swap chain has never been configured
161             return DAWN_VALIDATION_ERROR("Swap chain needs to be configured before GetNextTexture");
162         }
163 
164         return {};
165     }
166 
ValidatePresent(TextureBase * texture) const167     MaybeError SwapChainBase::ValidatePresent(TextureBase* texture) const {
168         DAWN_TRY(GetDevice()->ValidateObject(this));
169         DAWN_TRY(GetDevice()->ValidateObject(texture));
170 
171         // This also checks that the texture is valid since mLastNextTexture is always valid.
172         if (texture != mLastNextTexture) {
173             return DAWN_VALIDATION_ERROR(
174                 "Tried to present something other than the last NextTexture");
175         }
176 
177         return {};
178     }
179 
180 }  // namespace dawn_native
181