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