1use crate::context::CommandContext;
2use crate::version::Version;
3use crate::version::Api;
4use crate::gl;
5
6use std::fmt;
7use std::error::Error;
8
9use crate::texture::any::TextureAny;
10use crate::TextureExt;
11use crate::GlObject;
12
13#[derive(Copy, Clone, Debug)]
15pub enum GetFormatError {
16 NotSupported,
18}
19
20impl fmt::Display for GetFormatError {
21 fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
22 use self::GetFormatError::*;
23 let desc = match self {
24 NotSupported => "The backend doesn't support retrieving the internal format",
25 };
26 fmt.write_str(desc)
27 }
28}
29
30impl Error for GetFormatError {}
31
32#[derive(Copy, Clone, Debug, PartialEq, Eq)]
38pub enum InternalFormat {
39 OneComponent {
41 ty1: InternalFormatType,
43 bits1: usize,
45 },
46
47 TwoComponents {
49 ty1: InternalFormatType,
51 bits1: usize,
53 ty2: InternalFormatType,
55 bits2: usize,
57 },
58
59 ThreeComponents {
61 ty1: InternalFormatType,
63 bits1: usize,
65 ty2: InternalFormatType,
67 bits2: usize,
69 ty3: InternalFormatType,
71 bits3: usize,
73 },
74
75 FourComponents {
77 ty1: InternalFormatType,
79 bits1: usize,
81 ty2: InternalFormatType,
83 bits2: usize,
85 ty3: InternalFormatType,
87 bits3: usize,
89 ty4: InternalFormatType,
91 bits4: usize,
93 },
94}
95
96impl InternalFormat {
97 #[inline]
99 pub fn get_total_bits(&self) -> usize {
100 match *self {
101 InternalFormat::OneComponent { bits1, .. } => bits1,
102 InternalFormat::TwoComponents { bits1, bits2, .. } => bits1 + bits2,
103 InternalFormat::ThreeComponents { bits1, bits2, bits3, .. } => bits1 + bits2 + bits3,
104 InternalFormat::FourComponents { bits1, bits2, bits3, bits4, .. } =>
105 bits1 + bits2 + bits3 + bits4,
106 }
107 }
108}
109
110#[derive(Copy, Clone, Debug, PartialEq, Eq)]
112pub enum InternalFormatType {
113 SignedNormalized,
115 UnsignedNormalized,
117 Float,
119 Int,
121 UnsignedInt,
123}
124
125impl InternalFormatType {
126 #[inline]
128 fn from_glenum(val: gl::types::GLenum) -> InternalFormatType {
129 match val {
130 gl::SIGNED_NORMALIZED => InternalFormatType::SignedNormalized,
131 gl::UNSIGNED_NORMALIZED => InternalFormatType::UnsignedNormalized,
132 gl::FLOAT => InternalFormatType::Float,
133 gl::INT => InternalFormatType::Int,
134 gl::UNSIGNED_INT => InternalFormatType::UnsignedInt,
135 gl::NONE => unreachable!(), _ => unreachable!(),
137 }
138 }
139}
140
141pub fn get_format(ctxt: &mut CommandContext<'_>, texture: &TextureAny)
145 -> Result<InternalFormat, GetFormatError>
146{
147 if ctxt.version >= &Version(Api::Gl, 3, 0) || ctxt.version >= &Version(Api::GlEs, 3, 0) {
148 let (red_sz, red_ty, green_sz, green_ty, blue_sz, blue_ty,
149 alpha_sz, alpha_ty, depth_sz, depth_ty) = unsafe
150 {
151 let mut red_sz = 0;
152 let mut red_ty = 0;
153 let mut green_sz = 0;
154 let mut green_ty = 0;
155 let mut blue_sz = 0;
156 let mut blue_ty = 0;
157 let mut alpha_sz = 0;
158 let mut alpha_ty = 0;
159 let mut depth_sz = 0;
160 let mut depth_ty = 0;
161
162 if ctxt.version >= &Version(Api::Gl, 4, 5) ||
163 ctxt.extensions.gl_arb_direct_state_access
164 {
165 let id = texture.get_id();
166 ctxt.gl.GetTextureLevelParameteriv(id, 0, gl::TEXTURE_RED_SIZE, &mut red_sz);
167 ctxt.gl.GetTextureLevelParameteriv(id, 0, gl::TEXTURE_RED_TYPE, &mut red_ty);
168 ctxt.gl.GetTextureLevelParameteriv(id, 0, gl::TEXTURE_GREEN_SIZE, &mut green_sz);
169 ctxt.gl.GetTextureLevelParameteriv(id, 0, gl::TEXTURE_GREEN_TYPE, &mut green_ty);
170 ctxt.gl.GetTextureLevelParameteriv(id, 0, gl::TEXTURE_BLUE_SIZE, &mut blue_sz);
171 ctxt.gl.GetTextureLevelParameteriv(id, 0, gl::TEXTURE_BLUE_TYPE, &mut blue_ty);
172 ctxt.gl.GetTextureLevelParameteriv(id, 0, gl::TEXTURE_ALPHA_SIZE, &mut alpha_sz);
173 ctxt.gl.GetTextureLevelParameteriv(id, 0, gl::TEXTURE_ALPHA_TYPE, &mut alpha_ty);
174 ctxt.gl.GetTextureLevelParameteriv(id, 0, gl::TEXTURE_DEPTH_SIZE, &mut depth_sz);
175 ctxt.gl.GetTextureLevelParameteriv(id, 0, gl::TEXTURE_DEPTH_TYPE, &mut depth_ty);
176
177 } else if ctxt.extensions.gl_ext_direct_state_access {
178 let id = texture.get_id();
179 let bind_point = texture.get_bind_point();
180
181 ctxt.gl.GetTextureLevelParameterivEXT(id, bind_point, 0, gl::TEXTURE_RED_SIZE,
182 &mut red_sz);
183 ctxt.gl.GetTextureLevelParameterivEXT(id, bind_point, 0, gl::TEXTURE_RED_TYPE,
184 &mut red_ty);
185 ctxt.gl.GetTextureLevelParameterivEXT(id, bind_point, 0, gl::TEXTURE_GREEN_SIZE,
186 &mut green_sz);
187 ctxt.gl.GetTextureLevelParameterivEXT(id, bind_point, 0, gl::TEXTURE_GREEN_TYPE,
188 &mut green_ty);
189 ctxt.gl.GetTextureLevelParameterivEXT(id, bind_point, 0, gl::TEXTURE_BLUE_SIZE,
190 &mut blue_sz);
191 ctxt.gl.GetTextureLevelParameterivEXT(id, bind_point, 0, gl::TEXTURE_BLUE_TYPE,
192 &mut blue_ty);
193 ctxt.gl.GetTextureLevelParameterivEXT(id, bind_point, 0, gl::TEXTURE_ALPHA_SIZE,
194 &mut alpha_sz);
195 ctxt.gl.GetTextureLevelParameterivEXT(id, bind_point, 0, gl::TEXTURE_ALPHA_TYPE,
196 &mut alpha_ty);
197 ctxt.gl.GetTextureLevelParameterivEXT(id, bind_point, 0, gl::TEXTURE_DEPTH_SIZE,
198 &mut depth_sz);
199 ctxt.gl.GetTextureLevelParameterivEXT(id, bind_point, 0, gl::TEXTURE_DEPTH_TYPE,
200 &mut depth_ty);
201
202 } else {
203 let bind_point = texture.bind_to_current(ctxt);
204 ctxt.gl.GetTexLevelParameteriv(bind_point, 0, gl::TEXTURE_RED_SIZE, &mut red_sz);
205 ctxt.gl.GetTexLevelParameteriv(bind_point, 0, gl::TEXTURE_RED_TYPE, &mut red_ty);
206 ctxt.gl.GetTexLevelParameteriv(bind_point, 0, gl::TEXTURE_GREEN_SIZE,
207 &mut green_sz);
208 ctxt.gl.GetTexLevelParameteriv(bind_point, 0, gl::TEXTURE_GREEN_TYPE,
209 &mut green_ty);
210 ctxt.gl.GetTexLevelParameteriv(bind_point, 0, gl::TEXTURE_BLUE_SIZE, &mut blue_sz);
211 ctxt.gl.GetTexLevelParameteriv(bind_point, 0, gl::TEXTURE_BLUE_TYPE, &mut blue_ty);
212 ctxt.gl.GetTexLevelParameteriv(bind_point, 0, gl::TEXTURE_ALPHA_SIZE,
213 &mut alpha_sz);
214 ctxt.gl.GetTexLevelParameteriv(bind_point, 0, gl::TEXTURE_ALPHA_TYPE,
215 &mut alpha_ty);
216 ctxt.gl.GetTexLevelParameteriv(bind_point, 0, gl::TEXTURE_DEPTH_SIZE,
217 &mut depth_sz);
218 ctxt.gl.GetTexLevelParameteriv(bind_point, 0, gl::TEXTURE_DEPTH_TYPE,
219 &mut depth_ty);
220 }
221
222 (red_sz as gl::types::GLenum, red_ty as gl::types::GLenum,
223 green_sz as gl::types::GLenum, green_ty as gl::types::GLenum,
224 blue_sz as gl::types::GLenum, blue_ty as gl::types::GLenum,
225 alpha_sz as gl::types::GLenum, alpha_ty as gl::types::GLenum,
226 depth_sz as gl::types::GLenum, depth_ty as gl::types::GLenum)
227 };
228
229 Ok(match (red_sz, red_ty, green_sz, green_ty, blue_sz, blue_ty,
230 alpha_sz, alpha_ty, depth_sz, depth_ty)
231 {
232 (_, gl::NONE, _, _, _, _, _, _, _, gl::NONE) => return Err(GetFormatError::NotSupported),
233 (_, gl::NONE, _, _, _, _, _, _, sz1, ty1) => InternalFormat::OneComponent {
234 ty1: InternalFormatType::from_glenum(ty1),
235 bits1: sz1 as usize,
236 },
237 (sz1, ty1, _, gl::NONE, _, _, _, _, _, _) => InternalFormat::OneComponent {
238 ty1: InternalFormatType::from_glenum(ty1),
239 bits1: sz1 as usize,
240 },
241 (sz1, ty1, sz2, ty2, _, gl::NONE, _, _, _, _) => InternalFormat::TwoComponents {
242 ty1: InternalFormatType::from_glenum(ty1),
243 bits1: sz1 as usize,
244 ty2: InternalFormatType::from_glenum(ty2),
245 bits2: sz2 as usize,
246 },
247 (sz1, ty1, sz2, ty2, sz3, ty3, _, gl::NONE, _, _) => InternalFormat::ThreeComponents {
248 ty1: InternalFormatType::from_glenum(ty1),
249 bits1: sz1 as usize,
250 ty2: InternalFormatType::from_glenum(ty2),
251 bits2: sz2 as usize,
252 ty3: InternalFormatType::from_glenum(ty3),
253 bits3: sz3 as usize,
254 },
255 (sz1, ty1, sz2, ty2, sz3, ty3, sz4, ty4, _, gl::NONE) => InternalFormat::FourComponents {
256 ty1: InternalFormatType::from_glenum(ty1),
257 bits1: sz1 as usize,
258 ty2: InternalFormatType::from_glenum(ty2),
259 bits2: sz2 as usize,
260 ty3: InternalFormatType::from_glenum(ty3),
261 bits3: sz3 as usize,
262 ty4: InternalFormatType::from_glenum(ty4),
263 bits4: sz4 as usize,
264 },
265 _ => unreachable!()
266 })
267
268 } else {
269 Err(GetFormatError::NotSupported)
271 }
272}