Skip to main content

surfman/
device.rs

1//! The abstract interface that all devices conform to.
2
3use super::connection::Connection as ConnectionInterface;
4use crate::{ContextAttributes, ContextID, Error, GLApi, SurfaceAccess, SurfaceInfo, SurfaceType};
5use euclid::default::Size2D;
6use glow::Texture;
7
8use std::os::raw::c_void;
9
10/// A thread-local handle to a device.
11///
12/// Devices contain most of the relevant surface management methods.
13pub trait Device: Sized
14where
15    Self::Connection: ConnectionInterface,
16{
17    /// The connection type associated with this device.
18    type Connection;
19    /// The context type associated with this device.
20    type Context;
21    /// The context descriptor type associated with this device.
22    type ContextDescriptor;
23    /// The native context type associated with this device.
24    type NativeContext;
25    /// The surface type associated with this device.
26    type Surface;
27    /// The surface texture type associated with this device.
28    type SurfaceTexture;
29
30    // device.rs
31
32    /// Returns the native device associated with this device.
33    fn native_device(&self) -> <Self::Connection as ConnectionInterface>::NativeDevice;
34
35    /// Returns the display server connection that this device was created with.
36    fn connection(&self) -> Self::Connection;
37
38    /// Returns the adapter that this device was created with.
39    fn adapter(&self) -> <Self::Connection as ConnectionInterface>::Adapter;
40
41    /// Returns the OpenGL API flavor that this device supports (OpenGL or OpenGL ES).
42    fn gl_api(&self) -> GLApi;
43
44    // context.rs
45
46    /// Creates a context descriptor with the given attributes.
47    ///
48    /// Context descriptors are local to this device.
49    fn create_context_descriptor(
50        &self,
51        attributes: &ContextAttributes,
52    ) -> Result<Self::ContextDescriptor, Error>;
53
54    /// Creates a new OpenGL context and makes it current.
55    ///
56    /// The context initially has no surface attached. Until a surface is bound to it, rendering
57    /// commands will fail or have no effect.
58    fn create_context(
59        &self,
60        descriptor: &Self::ContextDescriptor,
61        share_with: Option<&Self::Context>,
62    ) -> Result<Self::Context, Error>;
63
64    /// Wraps a native context object in an OpenGL context.
65    ///
66    /// Panics if context is not current.
67    unsafe fn create_context_from_native_context(
68        &self,
69        native_context: Self::NativeContext,
70    ) -> Result<Self::Context, Error>;
71
72    /// Destroys a context.
73    ///
74    /// The context must have been created on this device.
75    fn destroy_context(&self, context: &mut Self::Context) -> Result<(), Error>;
76
77    /// Returns the descriptor that this context was created with.
78    fn context_descriptor(&self, context: &Self::Context) -> Self::ContextDescriptor;
79
80    /// Makes the context the current OpenGL context for this thread.
81    ///
82    /// After calling this function, it is valid to use OpenGL rendering commands.
83    fn make_context_current(&self, context: &Self::Context) -> Result<(), Error>;
84
85    /// Removes the current OpenGL context from this thread.
86    ///
87    /// After calling this function, OpenGL rendering commands will fail until a new context is
88    /// made current.
89    fn make_no_context_current(&self) -> Result<(), Error>;
90
91    /// Returns the attributes that the context descriptor was created with.
92    fn context_descriptor_attributes(
93        &self,
94        context_descriptor: &Self::ContextDescriptor,
95    ) -> ContextAttributes;
96
97    /// Fetches the address of an OpenGL function associated with this context.
98    ///
99    /// OpenGL functions are local to a context. You should not use OpenGL functions on one context
100    /// with any other context.
101    ///
102    /// This method is typically used with a function like `gl::load_with()` from the `gl` crate to
103    /// load OpenGL function pointers.
104    fn get_proc_address(&self, context: &Self::Context, symbol_name: &str) -> *const c_void;
105
106    /// Attaches a surface to a context for rendering.
107    ///
108    /// This function takes ownership of the surface. The surface must have been created with this
109    /// context, or an `IncompatibleSurface` error is returned.
110    ///
111    /// If this function is called with a surface already bound, a `SurfaceAlreadyBound` error is
112    /// returned. To avoid this error, first unbind the existing surface with
113    /// `unbind_surface_from_context`.
114    ///
115    /// If an error is returned, the surface is returned alongside it.
116    fn bind_surface_to_context(
117        &self,
118        context: &mut Self::Context,
119        surface: Self::Surface,
120    ) -> Result<(), (Error, Self::Surface)>;
121
122    /// Removes and returns any attached surface from this context.
123    ///
124    /// Any pending OpenGL commands targeting this surface will be automatically flushed, so the
125    /// surface is safe to read from immediately when this function returns.
126    fn unbind_surface_from_context(
127        &self,
128        context: &mut Self::Context,
129    ) -> Result<Option<Self::Surface>, Error>;
130
131    /// Returns a unique ID representing a context.
132    ///
133    /// This ID is unique to all currently-allocated contexts. If you destroy a context and create
134    /// a new one, the new context might have the same ID as the destroyed one.
135    fn context_id(&self, context: &Self::Context) -> ContextID;
136
137    /// Returns various information about the surface attached to a context.
138    ///
139    /// This includes, most notably, the OpenGL framebuffer object needed to render to the surface.
140    fn context_surface_info(&self, context: &Self::Context) -> Result<Option<SurfaceInfo>, Error>;
141
142    /// Returns the native context associated with the given context.
143    fn native_context(&self, context: &Self::Context) -> Self::NativeContext;
144
145    // surface.rs
146
147    /// Creates either a generic or a widget surface, depending on the supplied surface type.
148    ///
149    /// Only the given context may ever render to the surface, but generic surfaces can be wrapped
150    /// up in a `SurfaceTexture` for reading by other contexts.
151    fn create_surface(
152        &self,
153        context: &Self::Context,
154        surface_access: SurfaceAccess,
155        surface_type: SurfaceType<<Self::Connection as ConnectionInterface>::NativeWidget>,
156    ) -> Result<Self::Surface, Error>;
157
158    /// Creates a surface texture from an existing generic surface for use with the given context.
159    ///
160    /// The surface texture is local to the supplied context and takes ownership of the surface.
161    /// Destroying the surface texture allows you to retrieve the surface again.
162    ///
163    /// *The supplied context does not have to be the same context that the surface is associated
164    /// with.* This allows you to render to a surface in one context and sample from that surface
165    /// in another context.
166    ///
167    /// Calling this method on a widget surface returns a `WidgetAttached` error.
168    fn create_surface_texture(
169        &self,
170        context: &mut Self::Context,
171        surface: Self::Surface,
172    ) -> Result<Self::SurfaceTexture, (Error, Self::Surface)>;
173
174    /// Destroys a surface.
175    ///
176    /// The supplied context must be the context the surface is associated with, or this returns
177    /// an `IncompatibleSurface` error.
178    ///
179    /// You must explicitly call this method to dispose of a surface. Otherwise, a panic occurs in
180    /// the `drop` method.
181    fn destroy_surface(
182        &self,
183        context: &mut Self::Context,
184        surface: &mut Self::Surface,
185    ) -> Result<(), Error>;
186
187    /// Destroys a surface texture and returns the underlying surface.
188    ///
189    /// The supplied context must be the same context the surface texture was created with, or an
190    /// `IncompatibleSurfaceTexture` error is returned.
191    ///
192    /// All surface textures must be explicitly destroyed with this function, or a panic will
193    /// occur.
194    fn destroy_surface_texture(
195        &self,
196        context: &mut Self::Context,
197        surface_texture: Self::SurfaceTexture,
198    ) -> Result<Self::Surface, (Error, Self::SurfaceTexture)>;
199
200    /// Returns the OpenGL texture target needed to read from this surface texture.
201    ///
202    /// This will be `GL_TEXTURE_2D` or `GL_TEXTURE_RECTANGLE`, depending on platform.
203    fn surface_gl_texture_target(&self) -> u32;
204
205    /// Displays the contents of the currently bound surface to the screen, if
206    /// it is a widget surface.
207    ///
208    /// Widget surfaces are internally double-buffered, so changes to them don't
209    /// show up in their associated widgets until this method is called.
210    fn present_bound_surface(&self, context: &mut Self::Context) -> Result<(), Error>;
211
212    /// Displays the contents of a widget surface on screen.
213    ///
214    /// Widget surfaces are internally double-buffered, so changes to them don't show up in their
215    /// associated widgets until this method is called.
216    ///
217    /// The supplied context must match the context the surface was created with, or an
218    /// `IncompatibleSurface` error is returned.
219    fn present_surface(
220        &self,
221        context: &Self::Context,
222        surface: &mut Self::Surface,
223    ) -> Result<(), Error>;
224
225    /// If the currently bound surface is a widget surface, resize it,
226    fn resize_bound_surface(
227        &self,
228        context: &mut Self::Context,
229        size: Size2D<i32>,
230    ) -> Result<(), Error>;
231
232    /// Resizes a widget surface.
233    fn resize_surface(
234        &self,
235        context: &Self::Context,
236        surface: &mut Self::Surface,
237        size: Size2D<i32>,
238    ) -> Result<(), Error>;
239
240    /// Returns various information about the surface, including the framebuffer object needed to
241    /// render to this surface.
242    ///
243    /// Before rendering to a surface attached to a context, you must call `glBindFramebuffer()`
244    /// on the framebuffer object returned by this function. This framebuffer object may or not be
245    /// 0, the default framebuffer, depending on platform.
246    fn surface_info(&self, surface: &Self::Surface) -> SurfaceInfo;
247
248    /// Returns the OpenGL texture object containing the contents of this surface.
249    ///
250    /// It is only legal to read from, not write to, this texture object.
251    fn surface_texture_object(&self, surface_texture: &Self::SurfaceTexture) -> Option<Texture>;
252}