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};
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
58impl<Def, Alt> Device<Def, Alt>
59where
60    Def: DeviceInterface,
61    Alt: DeviceInterface,
62    Def::Connection: ConnectionInterface,
63    Alt::Connection: ConnectionInterface,
64{
65    /// Returns the display server connection that this device was created with.
66    pub fn connection(&self) -> Connection<Def, Alt> {
67        match *self {
68            Device::Default(ref device) => Connection::Default(device.connection()),
69            Device::Alternate(ref device) => Connection::Alternate(device.connection()),
70        }
71    }
72
73    /// Returns the adapter that this device was created with.
74    pub fn adapter(&self) -> Adapter<Def, Alt> {
75        match *self {
76            Device::Default(ref device) => Adapter::Default(device.adapter()),
77            Device::Alternate(ref device) => Adapter::Alternate(device.adapter()),
78        }
79    }
80
81    /// Returns the OpenGL API flavor that this device supports (OpenGL or OpenGL ES).
82    pub fn gl_api(&self) -> GLApi {
83        match *self {
84            Device::Default(ref device) => device.gl_api(),
85            Device::Alternate(ref device) => device.gl_api(),
86        }
87    }
88}
89
90impl<Def, Alt> DeviceInterface for Device<Def, Alt>
91where
92    Def: DeviceInterface,
93    Alt: DeviceInterface,
94    Def::Connection: ConnectionInterface<Device = Def>,
95    Alt::Connection: ConnectionInterface<Device = Alt>,
96{
97    type Connection = Connection<Def, Alt>;
98    type Context = Context<Def, Alt>;
99    type ContextDescriptor = ContextDescriptor<Def, Alt>;
100    type Surface = Surface<Def, Alt>;
101    type SurfaceTexture = SurfaceTexture<Def, Alt>;
102
103    // device.rs
104
105    #[inline]
106    fn connection(&self) -> Connection<Def, Alt> {
107        Device::connection(self)
108    }
109
110    #[inline]
111    fn adapter(&self) -> Adapter<Def, Alt> {
112        Device::adapter(self)
113    }
114
115    #[inline]
116    fn gl_api(&self) -> GLApi {
117        Device::gl_api(self)
118    }
119
120    // context.rs
121
122    #[inline]
123    fn create_context_descriptor(
124        &self,
125        attributes: &ContextAttributes,
126    ) -> Result<Self::ContextDescriptor, Error> {
127        Device::create_context_descriptor(self, attributes)
128    }
129
130    #[inline]
131    fn create_context(
132        &self,
133        descriptor: &ContextDescriptor<Def, Alt>,
134        share_with: Option<&Context<Def, Alt>>,
135    ) -> Result<Context<Def, Alt>, Error> {
136        Device::create_context(self, descriptor, share_with)
137    }
138
139    #[inline]
140    fn destroy_context(&self, context: &mut Context<Def, Alt>) -> Result<(), Error> {
141        Device::destroy_context(self, context)
142    }
143
144    #[inline]
145    fn context_descriptor(&self, context: &Context<Def, Alt>) -> Self::ContextDescriptor {
146        Device::context_descriptor(self, context)
147    }
148
149    #[inline]
150    fn make_context_current(&self, context: &Context<Def, Alt>) -> Result<(), Error> {
151        Device::make_context_current(self, context)
152    }
153
154    #[inline]
155    fn make_no_context_current(&self) -> Result<(), Error> {
156        Device::make_no_context_current(self)
157    }
158
159    #[inline]
160    fn context_descriptor_attributes(
161        &self,
162        context_descriptor: &ContextDescriptor<Def, Alt>,
163    ) -> ContextAttributes {
164        Device::context_descriptor_attributes(self, context_descriptor)
165    }
166
167    #[inline]
168    fn get_proc_address(&self, context: &Context<Def, Alt>, symbol_name: &str) -> *const c_void {
169        Device::get_proc_address(self, context, symbol_name)
170    }
171
172    #[inline]
173    fn bind_surface_to_context(
174        &self,
175        context: &mut Context<Def, Alt>,
176        surface: Surface<Def, Alt>,
177    ) -> Result<(), (Error, Surface<Def, Alt>)> {
178        Device::bind_surface_to_context(self, context, surface)
179    }
180
181    #[inline]
182    fn unbind_surface_from_context(
183        &self,
184        context: &mut Context<Def, Alt>,
185    ) -> Result<Option<Surface<Def, Alt>>, Error> {
186        Device::unbind_surface_from_context(self, context)
187    }
188
189    #[inline]
190    fn context_id(&self, context: &Context<Def, Alt>) -> ContextID {
191        Device::context_id(self, context)
192    }
193
194    #[inline]
195    fn context_surface_info(
196        &self,
197        context: &Context<Def, Alt>,
198    ) -> Result<Option<SurfaceInfo>, Error> {
199        Device::context_surface_info(self, context)
200    }
201
202    // surface.rs
203
204    #[inline]
205    fn create_surface(
206        &self,
207        context: &Context<Def, Alt>,
208        surface_access: SurfaceAccess,
209        surface_type: SurfaceType<NativeWidget<Def, Alt>>,
210    ) -> Result<Surface<Def, Alt>, Error> {
211        Device::create_surface(self, context, surface_access, surface_type)
212    }
213
214    #[inline]
215    fn create_surface_texture(
216        &self,
217        context: &mut Context<Def, Alt>,
218        surface: Surface<Def, Alt>,
219    ) -> Result<SurfaceTexture<Def, Alt>, (Error, Surface<Def, Alt>)> {
220        Device::create_surface_texture(self, context, surface)
221    }
222
223    #[inline]
224    fn destroy_surface(
225        &self,
226        context: &mut Context<Def, Alt>,
227        surface: &mut Surface<Def, Alt>,
228    ) -> Result<(), Error> {
229        Device::destroy_surface(self, context, surface)
230    }
231
232    #[inline]
233    fn destroy_surface_texture(
234        &self,
235        context: &mut Context<Def, Alt>,
236        surface_texture: SurfaceTexture<Def, Alt>,
237    ) -> Result<Surface<Def, Alt>, (Error, SurfaceTexture<Def, Alt>)> {
238        Device::destroy_surface_texture(self, context, surface_texture)
239    }
240
241    #[inline]
242    fn surface_gl_texture_target(&self) -> u32 {
243        Device::surface_gl_texture_target(self)
244    }
245
246    #[inline]
247    fn present_bound_surface(&self, context: &mut Context<Def, Alt>) -> Result<(), Error> {
248        Device::present_bound_surface(self, context)
249    }
250
251    #[inline]
252    fn resize_bound_surface(
253        &self,
254        context: &mut Self::Context,
255        size: Size2D<i32>,
256    ) -> Result<(), Error> {
257        Device::resize_bound_surface(self, context, size)
258    }
259
260    #[inline]
261    fn present_surface(
262        &self,
263        context: &Context<Def, Alt>,
264        surface: &mut Surface<Def, Alt>,
265    ) -> Result<(), Error> {
266        Device::present_surface(self, context, surface)
267    }
268
269    #[inline]
270    fn resize_surface(
271        &self,
272        context: &Context<Def, Alt>,
273        surface: &mut Surface<Def, Alt>,
274        size: Size2D<i32>,
275    ) -> Result<(), Error> {
276        Device::resize_surface(self, context, surface, size)
277    }
278
279    #[inline]
280    fn surface_info(&self, surface: &Surface<Def, Alt>) -> SurfaceInfo {
281        Device::surface_info(self, surface)
282    }
283
284    #[inline]
285    fn surface_texture_object(
286        &self,
287        surface_texture: &SurfaceTexture<Def, Alt>,
288    ) -> Option<Texture> {
289        Device::surface_texture_object(self, surface_texture)
290    }
291}