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}