Skip to main content

surfman/multi/
device.rs

1//! A device abstraction that allows the choice of backends dynamically.
2
3use super::connection::Connection;
4use super::context::{Context, ContextDescriptor, NativeContext};
5use super::surface::{NativeWidget, Surface, SurfaceTexture};
6use crate::connection::Connection as ConnectionInterface;
7use crate::context::ContextAttributes;
8use crate::device::Device as DeviceInterface;
9use crate::{ContextID, Error, GLApi, SurfaceAccess, SurfaceInfo, SurfaceType};
10use euclid::default::Size2D;
11use glow::Texture;
12
13use std::os::raw::c_void;
14
15/// Represents a hardware display adapter that can be used for rendering (including the CPU).
16///
17/// Adapters can be sent between threads. To render with an adapter, open a thread-local `Device`.
18pub enum Adapter<Def, Alt>
19where
20    Def: DeviceInterface,
21    Alt: DeviceInterface,
22{
23    /// The default adapter type.
24    Default(<Def::Connection as ConnectionInterface>::Adapter),
25    /// The alternate adapter type.
26    Alternate(<Alt::Connection as ConnectionInterface>::Adapter),
27}
28
29impl<Def, Alt> Clone for Adapter<Def, Alt>
30where
31    Def: DeviceInterface,
32    Alt: DeviceInterface,
33    <Def::Connection as ConnectionInterface>::Adapter: Clone,
34    <Alt::Connection as ConnectionInterface>::Adapter: Clone,
35{
36    fn clone(&self) -> Self {
37        match self {
38            Adapter::Default(ref adapter) => Adapter::Default(adapter.clone()),
39            Adapter::Alternate(ref adapter) => Adapter::Alternate(adapter.clone()),
40        }
41    }
42}
43
44/// A thread-local handle to a device.
45///
46/// Devices contain most of the relevant surface management methods.
47pub enum Device<Def, Alt>
48where
49    Def: DeviceInterface,
50    Alt: DeviceInterface,
51{
52    /// The default device type.
53    Default(Def),
54    /// The alternate device type.
55    Alternate(Alt),
56}
57
58/// Represents a native platform-specific device.
59pub enum NativeDevice<Def, Alt>
60where
61    Def: DeviceInterface,
62    Alt: DeviceInterface,
63{
64    /// The default native device type.
65    Default(<Def::Connection as ConnectionInterface>::NativeDevice),
66    /// The alternate native device type.
67    Alternate(<Alt::Connection as ConnectionInterface>::NativeDevice),
68}
69
70impl<Def, Alt> Device<Def, Alt>
71where
72    Def: DeviceInterface,
73    Alt: DeviceInterface,
74    Def::Connection: ConnectionInterface,
75    Alt::Connection: ConnectionInterface,
76{
77    /// Returns the native device underlying this device.
78    pub fn native_device(&self) -> NativeDevice<Def, Alt> {
79        match *self {
80            Device::Default(ref device) => NativeDevice::Default(device.native_device()),
81            Device::Alternate(ref device) => NativeDevice::Alternate(device.native_device()),
82        }
83    }
84
85    /// Returns the display server connection that this device was created with.
86    pub fn connection(&self) -> Connection<Def, Alt> {
87        match *self {
88            Device::Default(ref device) => Connection::Default(device.connection()),
89            Device::Alternate(ref device) => Connection::Alternate(device.connection()),
90        }
91    }
92
93    /// Returns the adapter that this device was created with.
94    pub fn adapter(&self) -> Adapter<Def, Alt> {
95        match *self {
96            Device::Default(ref device) => Adapter::Default(device.adapter()),
97            Device::Alternate(ref device) => Adapter::Alternate(device.adapter()),
98        }
99    }
100
101    /// Returns the OpenGL API flavor that this device supports (OpenGL or OpenGL ES).
102    pub fn gl_api(&self) -> GLApi {
103        match *self {
104            Device::Default(ref device) => device.gl_api(),
105            Device::Alternate(ref device) => device.gl_api(),
106        }
107    }
108}
109
110impl<Def, Alt> DeviceInterface for Device<Def, Alt>
111where
112    Def: DeviceInterface,
113    Alt: DeviceInterface,
114    Def::Connection: ConnectionInterface<Device = Def>,
115    Alt::Connection: ConnectionInterface<Device = Alt>,
116{
117    type Connection = Connection<Def, Alt>;
118    type Context = Context<Def, Alt>;
119    type ContextDescriptor = ContextDescriptor<Def, Alt>;
120    type NativeContext = NativeContext<Def, Alt>;
121    type Surface = Surface<Def, Alt>;
122    type SurfaceTexture = SurfaceTexture<Def, Alt>;
123
124    // device.rs
125
126    #[inline]
127    fn native_device(&self) -> NativeDevice<Def, Alt> {
128        Device::native_device(self)
129    }
130
131    #[inline]
132    fn connection(&self) -> Connection<Def, Alt> {
133        Device::connection(self)
134    }
135
136    #[inline]
137    fn adapter(&self) -> Adapter<Def, Alt> {
138        Device::adapter(self)
139    }
140
141    #[inline]
142    fn gl_api(&self) -> GLApi {
143        Device::gl_api(self)
144    }
145
146    // context.rs
147
148    #[inline]
149    fn create_context_descriptor(
150        &self,
151        attributes: &ContextAttributes,
152    ) -> Result<Self::ContextDescriptor, Error> {
153        Device::create_context_descriptor(self, attributes)
154    }
155
156    #[inline]
157    fn create_context(
158        &self,
159        descriptor: &ContextDescriptor<Def, Alt>,
160        share_with: Option<&Context<Def, Alt>>,
161    ) -> Result<Context<Def, Alt>, Error> {
162        Device::create_context(self, descriptor, share_with)
163    }
164
165    #[inline]
166    unsafe fn create_context_from_native_context(
167        &self,
168        native_context: Self::NativeContext,
169    ) -> Result<Context<Def, Alt>, Error> {
170        Device::create_context_from_native_context(self, native_context)
171    }
172
173    #[inline]
174    fn destroy_context(&self, context: &mut Context<Def, Alt>) -> Result<(), Error> {
175        Device::destroy_context(self, context)
176    }
177
178    #[inline]
179    fn native_context(&self, context: &Context<Def, Alt>) -> Self::NativeContext {
180        Device::native_context(self, context)
181    }
182
183    #[inline]
184    fn context_descriptor(&self, context: &Context<Def, Alt>) -> Self::ContextDescriptor {
185        Device::context_descriptor(self, context)
186    }
187
188    #[inline]
189    fn make_context_current(&self, context: &Context<Def, Alt>) -> Result<(), Error> {
190        Device::make_context_current(self, context)
191    }
192
193    #[inline]
194    fn make_no_context_current(&self) -> Result<(), Error> {
195        Device::make_no_context_current(self)
196    }
197
198    #[inline]
199    fn context_descriptor_attributes(
200        &self,
201        context_descriptor: &ContextDescriptor<Def, Alt>,
202    ) -> ContextAttributes {
203        Device::context_descriptor_attributes(self, context_descriptor)
204    }
205
206    #[inline]
207    fn get_proc_address(&self, context: &Context<Def, Alt>, symbol_name: &str) -> *const c_void {
208        Device::get_proc_address(self, context, symbol_name)
209    }
210
211    #[inline]
212    fn bind_surface_to_context(
213        &self,
214        context: &mut Context<Def, Alt>,
215        surface: Surface<Def, Alt>,
216    ) -> Result<(), (Error, Surface<Def, Alt>)> {
217        Device::bind_surface_to_context(self, context, surface)
218    }
219
220    #[inline]
221    fn unbind_surface_from_context(
222        &self,
223        context: &mut Context<Def, Alt>,
224    ) -> Result<Option<Surface<Def, Alt>>, Error> {
225        Device::unbind_surface_from_context(self, context)
226    }
227
228    #[inline]
229    fn context_id(&self, context: &Context<Def, Alt>) -> ContextID {
230        Device::context_id(self, context)
231    }
232
233    #[inline]
234    fn context_surface_info(
235        &self,
236        context: &Context<Def, Alt>,
237    ) -> Result<Option<SurfaceInfo>, Error> {
238        Device::context_surface_info(self, context)
239    }
240
241    // surface.rs
242
243    #[inline]
244    fn create_surface(
245        &self,
246        context: &Context<Def, Alt>,
247        surface_access: SurfaceAccess,
248        surface_type: SurfaceType<NativeWidget<Def, Alt>>,
249    ) -> Result<Surface<Def, Alt>, Error> {
250        Device::create_surface(self, context, surface_access, surface_type)
251    }
252
253    #[inline]
254    fn create_surface_texture(
255        &self,
256        context: &mut Context<Def, Alt>,
257        surface: Surface<Def, Alt>,
258    ) -> Result<SurfaceTexture<Def, Alt>, (Error, Surface<Def, Alt>)> {
259        Device::create_surface_texture(self, context, surface)
260    }
261
262    #[inline]
263    fn destroy_surface(
264        &self,
265        context: &mut Context<Def, Alt>,
266        surface: &mut Surface<Def, Alt>,
267    ) -> Result<(), Error> {
268        Device::destroy_surface(self, context, surface)
269    }
270
271    #[inline]
272    fn destroy_surface_texture(
273        &self,
274        context: &mut Context<Def, Alt>,
275        surface_texture: SurfaceTexture<Def, Alt>,
276    ) -> Result<Surface<Def, Alt>, (Error, SurfaceTexture<Def, Alt>)> {
277        Device::destroy_surface_texture(self, context, surface_texture)
278    }
279
280    #[inline]
281    fn surface_gl_texture_target(&self) -> u32 {
282        Device::surface_gl_texture_target(self)
283    }
284
285    #[inline]
286    fn present_bound_surface(&self, context: &mut Context<Def, Alt>) -> Result<(), Error> {
287        Device::present_bound_surface(self, context)
288    }
289
290    #[inline]
291    fn resize_bound_surface(
292        &self,
293        context: &mut Self::Context,
294        size: Size2D<i32>,
295    ) -> Result<(), Error> {
296        Device::resize_bound_surface(&self, context, size)
297    }
298
299    #[inline]
300    fn present_surface(
301        &self,
302        context: &Context<Def, Alt>,
303        surface: &mut Surface<Def, Alt>,
304    ) -> Result<(), Error> {
305        Device::present_surface(self, context, surface)
306    }
307
308    #[inline]
309    fn resize_surface(
310        &self,
311        context: &Context<Def, Alt>,
312        surface: &mut Surface<Def, Alt>,
313        size: Size2D<i32>,
314    ) -> Result<(), Error> {
315        Device::resize_surface(self, context, surface, size)
316    }
317
318    #[inline]
319    fn surface_info(&self, surface: &Surface<Def, Alt>) -> SurfaceInfo {
320        Device::surface_info(self, surface)
321    }
322
323    #[inline]
324    fn surface_texture_object(
325        &self,
326        surface_texture: &SurfaceTexture<Def, Alt>,
327    ) -> Option<Texture> {
328        Device::surface_texture_object(self, surface_texture)
329    }
330}