luminance/context.rs
1//! Graphics context.
2//!
3//! # Graphics context and backends
4//!
5//! A graphics context is an external type typically implemented by other crates and which provides
6//! support for backends. Its main scope is to unify all possible implementations of backends
7//! behind a single trait: [`GraphicsContext`]. A [`GraphicsContext`] really only requires two items
8//! to be implemented:
9//!
10//! - The type of the backend to use — [`GraphicsContext::Backend`]. That type will often be used
11//! to access the GPU, cache costly operations, etc.
12//! - A method to get a mutable access to the underlying backend — [`GraphicsContext::backend`].
13//!
14//! Most of the time, if you want to work with _any_ windowing implementation, you will want to
15//! use a type variable such as `C: GraphicsContext`. If you want to work with any context
16//! supporting a specific backend, use `C: GraphicsContext<Backend = YourBackendType`. Etc.
17//!
18//! This crate doesn’t provide you with creating such contexts. Instead, you must do it yourself
19//! or rely on crates doing it for you.
20//!
21//! # Default implementation of helper functions
22//!
23//! By default, graphics contexts automatically get several methods implemented on them. Those
24//! methods are helper functions available to write code in a more elegant and compact way than
25//! passing around mutable references on the context. Often, it will help you not having to
26//! use type ascription, too, since the [`GraphicsContext::Backend`] type is known when calling
27//! those functions.
28//!
29//! Instead of:
30//!
31//! ```ignore
32//! use luminance::context::GraphicsContext as _;
33//! use luminance::buffer::Buffer;
34//!
35//! let buffer: Buffer<SomeBackendType, u8> = Buffer::from_slice(&mut context, slice).unwrap();
36//! ```
37//!
38//! You can simply do:
39//!
40//! ```ignore
41//! use luminance::context::GraphicsContext as _;
42//!
43//! let buffer = context.new_buffer_from_slice(slice).unwrap();
44//! ```
45
46use crate::{
47 backend::{
48 color_slot::ColorSlot,
49 depth_stencil_slot::DepthStencilSlot,
50 framebuffer::Framebuffer as FramebufferBackend,
51 query::Query as QueryBackend,
52 shader::{Shader, ShaderData as ShaderDataBackend},
53 tess::Tess as TessBackend,
54 texture::Texture as TextureBackend,
55 },
56 texture::TexelUpload,
57};
58use crate::{
59 framebuffer::{Framebuffer, FramebufferError},
60 pipeline::PipelineGate,
61 pixel::Pixel,
62 query::Query,
63 shader::{ProgramBuilder, ShaderData, ShaderDataError, Stage, StageError, StageType},
64 tess::{Deinterleaved, Interleaved, TessBuilder, TessVertexData},
65 texture::{Dimensionable, Sampler, Texture, TextureError},
66 vertex::Semantics,
67};
68
69/// Class of graphics context.
70///
71/// Graphics context must implement this trait to be able to be used throughout the rest of the
72/// crate.
73pub unsafe trait GraphicsContext: Sized {
74 /// Internal type used by the backend to cache, optimize and store data. This roughly represents
75 /// the GPU data / context a backend implementation needs to work correctly.
76 type Backend;
77
78 /// Access the underlying backend.
79 fn backend(&mut self) -> &mut Self::Backend;
80
81 /// Access the query API.
82 fn query(&mut self) -> Query<Self::Backend>
83 where
84 Self::Backend: QueryBackend,
85 {
86 Query::new(self)
87 }
88
89 /// Create a new pipeline gate
90 fn new_pipeline_gate(&mut self) -> PipelineGate<Self::Backend> {
91 PipelineGate::new(self)
92 }
93
94 /// Create a new framebuffer.
95 ///
96 /// See the documentation of [`Framebuffer::new`] for further details.
97 fn new_framebuffer<D, CS, DS>(
98 &mut self,
99 size: D::Size,
100 mipmaps: usize,
101 sampler: Sampler,
102 ) -> Result<Framebuffer<Self::Backend, D, CS, DS>, FramebufferError>
103 where
104 Self::Backend: FramebufferBackend<D>,
105 D: Dimensionable,
106 CS: ColorSlot<Self::Backend, D>,
107 DS: DepthStencilSlot<Self::Backend, D>,
108 {
109 Framebuffer::new(self, size, mipmaps, sampler)
110 }
111
112 /// Create a new shader stage.
113 ///
114 /// See the documentation of [`Stage::new`] for further details.
115 fn new_shader_stage<R>(
116 &mut self,
117 ty: StageType,
118 src: R,
119 ) -> Result<Stage<Self::Backend>, StageError>
120 where
121 Self::Backend: Shader,
122 R: AsRef<str>,
123 {
124 Stage::new(self, ty, src)
125 }
126
127 /// Create a new shader program.
128 ///
129 /// See the documentation of [`ProgramBuilder::new`] for further details.
130 fn new_shader_program<Sem, Out, Uni>(&mut self) -> ProgramBuilder<Self, Sem, Out, Uni>
131 where
132 Self::Backend: Shader,
133 Sem: Semantics,
134 {
135 ProgramBuilder::new(self)
136 }
137
138 /// Create a new shader data.
139 ///
140 /// See the documentation of [`ShaderData::new`] for further details.
141 fn new_shader_data<T>(
142 &mut self,
143 values: impl IntoIterator<Item = T>,
144 ) -> Result<ShaderData<Self::Backend, T>, ShaderDataError>
145 where
146 Self::Backend: ShaderDataBackend<T>,
147 {
148 ShaderData::new(self, values)
149 }
150
151 /// Create a [`TessBuilder`].
152 ///
153 /// See the documentation of [`TessBuilder::new`] for further details.
154 fn new_tess(&mut self) -> TessBuilder<Self::Backend, (), (), (), Interleaved>
155 where
156 Self::Backend: TessBackend<(), (), (), Interleaved>,
157 {
158 TessBuilder::new(self)
159 }
160
161 /// Create a [`TessBuilder`] with deinterleaved memory.
162 ///
163 /// See the documentation of [`TessBuilder::new`] for further details.
164 fn new_deinterleaved_tess<V, W>(&mut self) -> TessBuilder<Self::Backend, V, (), W, Deinterleaved>
165 where
166 Self::Backend: TessBackend<V, (), W, Deinterleaved>,
167 V: TessVertexData<Deinterleaved>,
168 W: TessVertexData<Deinterleaved>,
169 {
170 TessBuilder::new(self)
171 }
172
173 /// Create a new texture from texels.
174 ///
175 /// Feel free to have a look at the documentation of [`Texture::new`] for further details.
176 fn new_texture<D, P>(
177 &mut self,
178 size: D::Size,
179 sampler: Sampler,
180 texels: TexelUpload<[P::Encoding]>,
181 ) -> Result<Texture<Self::Backend, D, P>, TextureError>
182 where
183 Self::Backend: TextureBackend<D, P>,
184 D: Dimensionable,
185 P: Pixel,
186 {
187 Texture::new(self, size, sampler, texels)
188 }
189
190 /// Create a new texture from raw texels.
191 ///
192 /// Feel free to have a look at the documentation of [`Texture::new_raw`] for further details.
193 fn new_texture_raw<D, P>(
194 &mut self,
195 size: D::Size,
196 sampler: Sampler,
197 texels: TexelUpload<[P::RawEncoding]>,
198 ) -> Result<Texture<Self::Backend, D, P>, TextureError>
199 where
200 Self::Backend: TextureBackend<D, P>,
201 D: Dimensionable,
202 P: Pixel,
203 {
204 Texture::new_raw(self, size, sampler, texels)
205 }
206}