1use super::context::Context;
4use super::device::Device;
5use crate::connection::Connection as ConnectionInterface;
6use crate::device::Device as DeviceInterface;
7use crate::{Error, SurfaceAccess, SurfaceInfo, SurfaceType};
8use euclid::default::Size2D;
9use glow::Texture;
10
11use std::fmt::{self, Debug, Formatter};
12
13pub enum Surface<Def, Alt>
30where
31 Def: DeviceInterface,
32 Alt: DeviceInterface,
33{
34 Default(Def::Surface),
36 Alternate(Alt::Surface),
38}
39
40pub enum SurfaceTexture<Def, Alt>
50where
51 Def: DeviceInterface,
52 Alt: DeviceInterface,
53{
54 Default(Def::SurfaceTexture),
56 Alternate(Alt::SurfaceTexture),
58}
59
60pub enum NativeWidget<Def, Alt>
62where
63 Def: DeviceInterface,
64 Alt: DeviceInterface,
65{
66 Default(<Def::Connection as ConnectionInterface>::NativeWidget),
68 Alternate(<Alt::Connection as ConnectionInterface>::NativeWidget),
70}
71
72impl<Def, Alt> Debug for Surface<Def, Alt>
73where
74 Def: DeviceInterface,
75 Alt: DeviceInterface,
76{
77 fn fmt(&self, f: &mut Formatter) -> Result<(), fmt::Error> {
78 write!(f, "Surface")
79 }
80}
81
82impl<Def, Alt> Debug for SurfaceTexture<Def, Alt>
83where
84 Def: DeviceInterface,
85 Alt: DeviceInterface,
86{
87 fn fmt(&self, f: &mut Formatter) -> Result<(), fmt::Error> {
88 write!(f, "SurfaceTexture")
89 }
90}
91
92impl<Def, Alt> Device<Def, Alt>
93where
94 Def: DeviceInterface,
95 Alt: DeviceInterface,
96{
97 pub fn create_surface(
102 &self,
103 context: &Context<Def, Alt>,
104 surface_access: SurfaceAccess,
105 surface_type: SurfaceType<NativeWidget<Def, Alt>>,
106 ) -> Result<Surface<Def, Alt>, Error> {
107 match (self, context) {
108 (&Device::Default(ref device), Context::Default(context)) => {
109 let surface_type = match surface_type {
110 SurfaceType::Generic { size } => SurfaceType::Generic { size },
111 SurfaceType::Widget {
112 native_widget: NativeWidget::Default(native_widget),
113 } => SurfaceType::Widget { native_widget },
114 SurfaceType::Widget { native_widget: _ } => {
115 return Err(Error::IncompatibleNativeWidget)
116 }
117 };
118 device
119 .create_surface(context, surface_access, surface_type)
120 .map(Surface::Default)
121 }
122 (&Device::Alternate(ref device), Context::Alternate(context)) => {
123 let surface_type = match surface_type {
124 SurfaceType::Generic { size } => SurfaceType::Generic { size },
125 SurfaceType::Widget {
126 native_widget: NativeWidget::Alternate(native_widget),
127 } => SurfaceType::Widget { native_widget },
128 SurfaceType::Widget { native_widget: _ } => {
129 return Err(Error::IncompatibleNativeWidget)
130 }
131 };
132 device
133 .create_surface(context, surface_access, surface_type)
134 .map(Surface::Alternate)
135 }
136 _ => Err(Error::IncompatibleContext),
137 }
138 }
139
140 pub fn create_surface_texture(
151 &self,
152 context: &mut Context<Def, Alt>,
153 surface: Surface<Def, Alt>,
154 ) -> Result<SurfaceTexture<Def, Alt>, (Error, Surface<Def, Alt>)> {
155 match (self, &mut *context) {
156 (Device::Default(device), &mut Context::Default(ref mut context)) => match surface {
157 Surface::Default(surface) => {
158 match device.create_surface_texture(context, surface) {
159 Ok(surface_texture) => Ok(SurfaceTexture::Default(surface_texture)),
160 Err((err, surface)) => Err((err, Surface::Default(surface))),
161 }
162 }
163 _ => Err((Error::IncompatibleSurface, surface)),
164 },
165 (Device::Alternate(device), &mut Context::Alternate(ref mut context)) => {
166 match surface {
167 Surface::Alternate(surface) => {
168 match device.create_surface_texture(context, surface) {
169 Ok(surface_texture) => Ok(SurfaceTexture::Alternate(surface_texture)),
170 Err((err, surface)) => Err((err, Surface::Alternate(surface))),
171 }
172 }
173 _ => Err((Error::IncompatibleSurface, surface)),
174 }
175 }
176 _ => Err((Error::IncompatibleContext, surface)),
177 }
178 }
179
180 pub fn destroy_surface(
188 &self,
189 context: &mut Context<Def, Alt>,
190 surface: &mut Surface<Def, Alt>,
191 ) -> Result<(), Error> {
192 match (self, &mut *context) {
193 (Device::Default(device), &mut Context::Default(ref mut context)) => match *surface {
194 Surface::Default(ref mut surface) => device.destroy_surface(context, surface),
195 _ => Err(Error::IncompatibleSurface),
196 },
197 (Device::Alternate(device), &mut Context::Alternate(ref mut context)) => match *surface
198 {
199 Surface::Alternate(ref mut surface) => device.destroy_surface(context, surface),
200 _ => Err(Error::IncompatibleSurface),
201 },
202 _ => Err(Error::IncompatibleContext),
203 }
204 }
205
206 pub fn destroy_surface_texture(
214 &self,
215 context: &mut Context<Def, Alt>,
216 surface_texture: SurfaceTexture<Def, Alt>,
217 ) -> Result<Surface<Def, Alt>, (Error, SurfaceTexture<Def, Alt>)> {
218 match (self, &mut *context) {
219 (Device::Default(device), &mut Context::Default(ref mut context)) => {
220 match surface_texture {
221 SurfaceTexture::Default(surface_texture) => {
222 match device.destroy_surface_texture(context, surface_texture) {
223 Ok(surface) => Ok(Surface::Default(surface)),
224 Err((err, surface_texture)) => {
225 Err((err, SurfaceTexture::Default(surface_texture)))
226 }
227 }
228 }
229 _ => Err((Error::IncompatibleSurfaceTexture, surface_texture)),
230 }
231 }
232 (Device::Alternate(device), &mut Context::Alternate(ref mut context)) => {
233 match surface_texture {
234 SurfaceTexture::Alternate(surface_texture) => {
235 match device.destroy_surface_texture(context, surface_texture) {
236 Ok(surface) => Ok(Surface::Alternate(surface)),
237 Err((err, surface_texture)) => {
238 Err((err, SurfaceTexture::Alternate(surface_texture)))
239 }
240 }
241 }
242 _ => Err((Error::IncompatibleSurfaceTexture, surface_texture)),
243 }
244 }
245 _ => Err((Error::IncompatibleContext, surface_texture)),
246 }
247 }
248
249 pub fn present_surface(
257 &self,
258 context: &Context<Def, Alt>,
259 surface: &mut Surface<Def, Alt>,
260 ) -> Result<(), Error> {
261 match (self, context) {
262 (Device::Default(device), Context::Default(context)) => match *surface {
263 Surface::Default(ref mut surface) => device.present_surface(context, surface),
264 _ => Err(Error::IncompatibleSurface),
265 },
266 (Device::Alternate(device), Context::Alternate(context)) => match *surface {
267 Surface::Alternate(ref mut surface) => device.present_surface(context, surface),
268 _ => Err(Error::IncompatibleSurface),
269 },
270 _ => Err(Error::IncompatibleContext),
271 }
272 }
273
274 pub fn resize_surface(
276 &self,
277 context: &Context<Def, Alt>,
278 surface: &mut Surface<Def, Alt>,
279 size: Size2D<i32>,
280 ) -> Result<(), Error> {
281 match (self, context) {
282 (Device::Default(device), Context::Default(context)) => match *surface {
283 Surface::Default(ref mut surface) => device.resize_surface(context, surface, size),
284 _ => Err(Error::IncompatibleSurface),
285 },
286 (Device::Alternate(device), Context::Alternate(context)) => match *surface {
287 Surface::Alternate(ref mut surface) => {
288 device.resize_surface(context, surface, size)
289 }
290 _ => Err(Error::IncompatibleSurface),
291 },
292 _ => Err(Error::IncompatibleContext),
293 }
294 }
295
296 #[inline]
300 pub fn surface_gl_texture_target(&self) -> u32 {
301 match *self {
302 Device::Default(ref device) => device.surface_gl_texture_target(),
303 Device::Alternate(ref device) => device.surface_gl_texture_target(),
304 }
305 }
306
307 pub fn surface_info(&self, surface: &Surface<Def, Alt>) -> SurfaceInfo {
314 match (self, surface) {
315 (Device::Default(device), Surface::Default(ref surface)) => {
316 device.surface_info(surface)
317 }
318 (Device::Alternate(device), Surface::Alternate(ref surface)) => {
319 device.surface_info(surface)
320 }
321 _ => panic!("Incompatible context!"),
322 }
323 }
324
325 pub fn surface_texture_object(
329 &self,
330 surface_texture: &SurfaceTexture<Def, Alt>,
331 ) -> Option<Texture> {
332 match (self, surface_texture) {
333 (Device::Default(device), SurfaceTexture::Default(ref surface_texture)) => {
334 device.surface_texture_object(surface_texture)
335 }
336 (Device::Alternate(device), SurfaceTexture::Alternate(ref surface_texture)) => {
337 device.surface_texture_object(surface_texture)
338 }
339 _ => panic!("Incompatible context!"),
340 }
341 }
342}