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