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}