1#![allow(non_snake_case, clippy::missing_safety_doc, clippy::too_many_arguments)]
16
17use std::ffi::{c_void, CStr};
18use std::sync::Mutex;
19
20use crate::sys;
21
22include!("gles_gen.rs");
23
24pub fn get_proc_address(name: &CStr) -> *const c_void {
26 lookup(name.to_bytes())
27}
28
29const GL_INVALID_ENUM: u32 = 0x0500;
30const GL_INVALID_VALUE: u32 = 0x0501;
31const GL_INVALID_OPERATION: u32 = 0x0502;
32const GL_COLOR: u32 = 0x1800;
33const GL_PIXEL_PACK_BUFFER: u32 = 0x88EB;
34const GL_PIXEL_UNPACK_BUFFER: u32 = 0x88EC;
35const GL_EXTENSIONS: u32 = 0x1F03;
36const GL_NUM_EXTENSIONS: u32 = 0x821D;
37const GL_MAP_READ_BIT: u32 = 0x0001;
38const GL_MAP_WRITE_BIT: u32 = 0x0002;
39const GL_MAP_INVALIDATE_RANGE_BIT: u32 = 0x0004;
40const GL_MAP_INVALIDATE_BUFFER_BIT: u32 = 0x0008;
41const GL_MAP_FLUSH_EXPLICIT_BIT: u32 = 0x0010;
42
43#[derive(Clone, Copy)]
44struct Store {
45 alignment: i32,
46 row_length: i32,
47 image_height: i32,
48 skip_pixels: i32,
49 skip_rows: i32,
50 skip_images: i32,
51}
52const STORE: Store = Store { alignment: 4, row_length: 0, image_height: 0, skip_pixels: 0, skip_rows: 0, skip_images: 0 };
53
54struct Mapping {
55 target: u32,
56 data: Vec<u8>,
57 offset: isize,
58 access: u32,
59}
60
61struct State {
62 error: u32,
64 unpack: Store,
65 pack: Store,
66 unpack_buffer: u32,
67 pack_buffer: u32,
68 strings: Vec<(u32, Box<[u8]>)>,
70 extensions: Option<Vec<Box<[u8]>>>,
71 maps: Vec<Mapping>,
72}
73
74static STATE: Mutex<State> = Mutex::new(State {
75 error: 0,
76 unpack: STORE,
77 pack: STORE,
78 unpack_buffer: 0,
79 pack_buffer: 0,
80 strings: Vec::new(),
81 extensions: None,
82 maps: Vec::new(),
83});
84
85fn state<R>(f: impl FnOnce(&mut State) -> R) -> R {
86 f(&mut STATE.lock().unwrap_or_else(|e| e.into_inner()))
87}
88
89fn set_error(e: u32) {
90 state(|s| s.error = e);
91}
92
93fn pixel_bytes(format: u32, ty: u32) -> u32 {
94 match ty {
95 0x8363 | 0x8033 | 0x8034 => return 2,
96 0x8368 | 0x8C3B | 0x8C3E | 0x84FA => return 4,
97 0x8DAD => return 8,
98 _ => {}
99 }
100 let size = match ty {
101 0x1400 | 0x1401 => 1,
102 0x1402 | 0x1403 | 0x140B => 2,
103 0x1404..=0x1406 => 4,
104 _ => 0,
105 };
106 let comps = match format {
107 0x1903 | 0x8D94 | 0x1906 | 0x1909 | 0x1902 => 1,
108 0x8227 | 0x8228 | 0x190A | 0x84F9 => 2,
109 0x1907 | 0x8D98 => 3,
110 0x1908 | 0x8D99 => 4,
111 _ => 0,
112 };
113 size * comps
114}
115
116fn image_bytes(s: &Store, w: i32, h: i32, d: i32, format: u32, ty: u32) -> u32 {
118 let bpp = pixel_bytes(format, ty) as u64;
119 if w <= 0 || h <= 0 || d <= 0 || bpp == 0 || s.alignment <= 0 {
120 return 0;
121 }
122 let (w, h, d) = (w as u64, h as u64, d as u64);
123 let row_len = if s.row_length > 0 { s.row_length as u64 } else { w };
124 let a = s.alignment as u64;
125 let row = (row_len * bpp).div_ceil(a) * a;
126 let img_h = if s.image_height > 0 { s.image_height as u64 } else { h };
127 let img = row * img_h;
128 (s.skip_images as u64 * img + (d - 1) * img + s.skip_rows as u64 * row + (h - 1) * row + s.skip_pixels as u64 * bpp + w * bpp) as u32
129}
130
131fn unpack(pixels: *const c_void, w: i32, h: i32, d: i32, format: u32, ty: u32) -> (*const u8, u32) {
133 state(|s| {
134 if s.unpack_buffer != 0 {
135 (std::ptr::null(), pixels as usize as u32)
136 } else if pixels.is_null() {
137 (std::ptr::null(), 0)
138 } else {
139 (pixels as *const u8, image_bytes(&s.unpack, w, h, d, format, ty))
140 }
141 })
142}
143
144unsafe fn cstr_len(p: *const c_void) -> u32 {
145 unsafe { CStr::from_ptr(p as *const std::ffi::c_char) }.to_bytes().len() as u32
146}
147
148unsafe fn truncated(get: impl Fn(*mut u8, u32) -> i32, size: i32, length: *mut c_void, out: *mut c_void) {
150 let n = get(std::ptr::null_mut(), 0);
151 let length = length as *mut i32;
152 if n < 0 || size <= 0 {
153 if !length.is_null() {
154 unsafe { *length = 0 };
155 }
156 return;
157 }
158 let mut tmp = vec![0u8; n as usize];
159 get(tmp.as_mut_ptr(), n as u32);
160 let k = n.min(size - 1) as usize;
161 unsafe {
162 std::ptr::copy_nonoverlapping(tmp.as_ptr(), out as *mut u8, k);
163 *(out as *mut u8).add(k) = 0;
164 if !length.is_null() {
165 *length = k as i32;
166 }
167 }
168}
169
170unsafe fn active_info(f: unsafe fn(u32, u32, *mut u8, u32, *mut u8) -> i32, program: u32, index: u32, size: i32, length: *mut c_void, out_size: *mut c_void, out_type: *mut c_void, name: *mut c_void) {
171 let mut info = [0i32; 2];
172 let n = unsafe { f(program, index, std::ptr::null_mut(), 0, info.as_mut_ptr() as *mut u8) };
173 let length = length as *mut i32;
174 if n < 0 {
175 if !length.is_null() {
176 unsafe { *length = 0 };
177 }
178 return;
179 }
180 let mut tmp = vec![0u8; n as usize];
181 unsafe { f(program, index, tmp.as_mut_ptr(), n as u32, info.as_mut_ptr() as *mut u8) };
182 let k = if size > 0 { n.min(size - 1) as usize } else { 0 };
183 unsafe {
184 if size > 0 {
185 std::ptr::copy_nonoverlapping(tmp.as_ptr(), name as *mut u8, k);
186 *(name as *mut u8).add(k) = 0;
187 }
188 if !length.is_null() {
189 *length = k as i32;
190 }
191 if !out_size.is_null() {
192 *(out_size as *mut i32) = info[0];
193 }
194 if !out_type.is_null() {
195 *(out_type as *mut u32) = info[1] as u32;
196 }
197 }
198}
199
200pub unsafe extern "C" fn glGetError() -> u32 {
203 let e = state(|s| std::mem::take(&mut s.error));
204 if e != 0 { e } else { unsafe { sys::gl_get_error() } }
205}
206
207fn string(name: u32) -> Option<Box<[u8]>> {
208 let n = unsafe { sys::gl_get_string(name, std::ptr::null_mut(), 0) };
209 if n < 0 {
210 return None;
211 }
212 let mut v = vec![0u8; n as usize + 1];
213 unsafe { sys::gl_get_string(name, v.as_mut_ptr(), n as u32) };
214 Some(v.into_boxed_slice())
215}
216
217pub unsafe extern "C" fn glGetString(name: u32) -> *const c_void {
218 if ![0x1F00, 0x1F01, 0x1F02, 0x8B8C, GL_EXTENSIONS].contains(&name) {
219 set_error(GL_INVALID_ENUM);
220 return std::ptr::null();
221 }
222 if let Some(p) = state(|s| s.strings.iter().find(|(n, _)| *n == name).map(|(_, b)| b.as_ptr())) {
223 return p as *const c_void;
224 }
225 let Some(b) = string(name) else { return std::ptr::null() };
226 state(|s| {
227 s.strings.push((name, b));
228 s.strings.last().map_or(std::ptr::null(), |(_, b)| b.as_ptr() as *const c_void)
229 })
230}
231
232fn extensions() -> usize {
233 if let Some(n) = state(|s| s.extensions.as_ref().map(Vec::len)) {
234 return n;
235 }
236 let all = string(GL_EXTENSIONS).unwrap_or_default();
237 let all = &all[..all.len().saturating_sub(1)];
238 let list: Vec<Box<[u8]>> = all
239 .split(|&b| b == b' ')
240 .filter(|e| !e.is_empty())
241 .map(|e| [e, &[0][..]].concat().into_boxed_slice())
242 .collect();
243 let n = list.len();
244 state(|s| s.extensions = Some(list));
245 n
246}
247
248pub unsafe extern "C" fn glGetStringi(name: u32, index: u32) -> *const c_void {
249 if name != GL_EXTENSIONS {
250 set_error(GL_INVALID_ENUM);
251 return std::ptr::null();
252 }
253 if index as usize >= extensions() {
254 set_error(GL_INVALID_VALUE);
255 return std::ptr::null();
256 }
257 state(|s| s.extensions.as_ref().map_or(std::ptr::null(), |l| l[index as usize].as_ptr() as *const c_void))
258}
259
260pub unsafe extern "C" fn glGetIntegerv(pname: u32, data: *mut c_void) {
263 if pname == GL_NUM_EXTENSIONS {
264 unsafe { *(data as *mut i32) = extensions() as i32 };
265 return;
266 }
267 unsafe { sys::gl_get_integerv(pname, data as *mut u8, 64) };
268}
269pub unsafe extern "C" fn glGetBooleanv(pname: u32, data: *mut c_void) {
270 let mut v = [0i32; 64];
271 let n = unsafe { sys::gl_get_integerv(pname, v.as_mut_ptr() as *mut u8, 64) };
272 for (i, x) in v.iter().take(n.clamp(0, 64) as usize).enumerate() {
273 unsafe { *(data as *mut u8).add(i) = (*x != 0) as u8 };
274 }
275}
276pub unsafe extern "C" fn glGetFloatv(pname: u32, data: *mut c_void) {
277 unsafe { sys::gl_get_floatv(pname, data as *mut u8, 64) };
278}
279pub unsafe extern "C" fn glGetInteger64v(pname: u32, data: *mut c_void) {
280 unsafe { sys::gl_get_integer64v(pname, data as *mut u8, 64) };
281}
282pub unsafe extern "C" fn glGetIntegeri_v(target: u32, index: u32, data: *mut c_void) {
283 unsafe { sys::gl_get_integeri_v(target, index, data as *mut u8, 16) };
284}
285pub unsafe extern "C" fn glGetInteger64i_v(target: u32, index: u32, data: *mut c_void) {
286 let mut v = [0i32; 16];
287 let n = unsafe { sys::gl_get_integeri_v(target, index, v.as_mut_ptr() as *mut u8, 16) };
288 for (i, x) in v.iter().take(n.clamp(0, 16) as usize).enumerate() {
289 unsafe { *(data as *mut i64).add(i) = *x as i64 };
290 }
291}
292pub unsafe extern "C" fn glGetInternalformativ(target: u32, internalformat: u32, pname: u32, count: i32, params: *mut c_void) {
293 unsafe { sys::gl_get_internalformativ(target, internalformat, pname, params as *mut u8, count.max(0) as u32) };
294}
295pub unsafe extern "C" fn glGetShaderPrecisionFormat(shadertype: u32, precisiontype: u32, range: *mut c_void, precision: *mut c_void) {
296 let mut v = [0i32; 3];
297 unsafe {
298 sys::gl_get_shader_precision_format(shadertype, precisiontype, v.as_mut_ptr() as *mut u8);
299 *(range as *mut i32) = v[0];
300 *(range as *mut i32).add(1) = v[1];
301 *(precision as *mut i32) = v[2];
302 }
303}
304
305macro_rules! single {
306 ($($name:ident($($p:ident: $t:ty),*) => $call:ident;)*) => {$(
307 pub unsafe extern "C" fn $name($($p: $t,)* params: *mut c_void) {
308 unsafe { *(params as *mut i32) = sys::$call($($p),*) as i32 };
309 }
310 )*};
311}
312single! {
313 glGetShaderiv(shader: u32, pname: u32) => gl_get_shaderiv;
314 glGetProgramiv(program: u32, pname: u32) => gl_get_programiv;
315 glGetBufferParameteriv(target: u32, pname: u32) => gl_get_buffer_parameteriv;
316 glGetRenderbufferParameteriv(target: u32, pname: u32) => gl_get_renderbuffer_parameteriv;
317 glGetFramebufferAttachmentParameteriv(target: u32, attachment: u32, pname: u32) => gl_get_framebuffer_attachment_parameteriv;
318 glGetTexParameteriv(target: u32, pname: u32) => gl_get_tex_parameteriv;
319 glGetSamplerParameteriv(sampler: u32, pname: u32) => gl_get_sampler_parameteriv;
320 glGetQueryiv(target: u32, pname: u32) => gl_get_queryiv;
321 glGetQueryObjectuiv(id: u32, pname: u32) => gl_get_query_objectuiv;
322 glGetVertexAttribiv(index: u32, pname: u32) => gl_get_vertex_attribiv;
323 glGetVertexAttribIiv(index: u32, pname: u32) => gl_get_vertex_attribiv;
324 glGetVertexAttribIuiv(index: u32, pname: u32) => gl_get_vertex_attribiv;
325}
326pub unsafe extern "C" fn glGetTexParameterfv(target: u32, pname: u32, params: *mut c_void) {
327 unsafe { *(params as *mut f32) = sys::gl_get_tex_parameterfv(target, pname) };
328}
329pub unsafe extern "C" fn glGetSamplerParameterfv(sampler: u32, pname: u32, params: *mut c_void) {
330 unsafe { *(params as *mut f32) = sys::gl_get_sampler_parameterfv(sampler, pname) };
331}
332pub unsafe extern "C" fn glGetBufferParameteri64v(target: u32, pname: u32, params: *mut c_void) {
333 unsafe { *(params as *mut i64) = sys::gl_get_buffer_parameteriv(target, pname) as i64 };
334}
335pub unsafe extern "C" fn glGetVertexAttribfv(index: u32, pname: u32, params: *mut c_void) {
336 unsafe { sys::gl_get_vertex_attribfv(index, pname, params as *mut u8, 4) };
337}
338pub unsafe extern "C" fn glGetVertexAttribPointerv(index: u32, pname: u32, pointer: *mut c_void) {
339 unsafe { *(pointer as *mut usize) = sys::gl_get_vertex_attrib_offset(index, pname) as usize };
340}
341pub unsafe extern "C" fn glGetUniformfv(program: u32, location: i32, params: *mut c_void) {
342 unsafe { sys::gl_get_uniformfv(program, location, params as *mut u8, 16) };
343}
344pub unsafe extern "C" fn glGetUniformiv(program: u32, location: i32, params: *mut c_void) {
345 unsafe { sys::gl_get_uniformiv(program, location, params as *mut u8, 16) };
346}
347pub unsafe extern "C" fn glGetUniformuiv(program: u32, location: i32, params: *mut c_void) {
348 unsafe { sys::gl_get_uniformuiv(program, location, params as *mut u8, 16) };
349}
350
351macro_rules! names {
354 ($($gen:ident, $del:ident => $create:ident, $delete:ident;)*) => {$(
355 pub unsafe extern "C" fn $gen(n: i32, out: *mut c_void) {
356 for i in 0..n.max(0) as usize {
357 unsafe { *(out as *mut u32).add(i) = sys::$create() };
358 }
359 }
360 pub unsafe extern "C" fn $del(n: i32, names: *const c_void) {
361 for i in 0..n.max(0) as usize {
362 unsafe { sys::$delete(*(names as *const u32).add(i)) };
363 }
364 }
365 )*};
366}
367names! {
368 glGenBuffers, glDeleteBuffers => gl_create_buffer, gl_delete_buffer;
369 glGenTextures, glDeleteTextures => gl_create_texture, gl_delete_texture;
370 glGenFramebuffers, glDeleteFramebuffers => gl_create_framebuffer, gl_delete_framebuffer;
371 glGenRenderbuffers, glDeleteRenderbuffers => gl_create_renderbuffer, gl_delete_renderbuffer;
372 glGenQueries, glDeleteQueries => gl_create_query, gl_delete_query;
373 glGenVertexArrays, glDeleteVertexArrays => gl_create_vertex_array, gl_delete_vertex_array;
374 glGenSamplers, glDeleteSamplers => gl_create_sampler, gl_delete_sampler;
375 glGenTransformFeedbacks, glDeleteTransformFeedbacks => gl_create_transform_feedback, gl_delete_transform_feedback;
376}
377
378pub unsafe extern "C" fn glBindBuffer(target: u32, buffer: u32) {
381 state(|s| match target {
382 GL_PIXEL_UNPACK_BUFFER => s.unpack_buffer = buffer,
383 GL_PIXEL_PACK_BUFFER => s.pack_buffer = buffer,
384 _ => {}
385 });
386 unsafe { sys::gl_bind_buffer(target, buffer) };
387}
388pub unsafe extern "C" fn glBufferData(target: u32, size: isize, data: *const c_void, usage: u32) {
389 unsafe { sys::gl_buffer_data(target, data as *const u8, size as u32, usage) };
390}
391pub unsafe extern "C" fn glBufferSubData(target: u32, offset: isize, size: isize, data: *const c_void) {
392 unsafe { sys::gl_buffer_sub_data(target, offset as u32, data as *const u8, size as u32) };
393}
394pub unsafe extern "C" fn glMapBufferRange(target: u32, offset: isize, length: isize, access: u32) -> *mut c_void {
395 if length <= 0 || offset < 0 || state(|s| s.maps.iter().any(|m| m.target == target)) {
396 set_error(GL_INVALID_OPERATION);
397 return std::ptr::null_mut();
398 }
399 let mut data = vec![0u8; length as usize];
400 if access & GL_MAP_READ_BIT != 0 || access & (GL_MAP_INVALIDATE_RANGE_BIT | GL_MAP_INVALIDATE_BUFFER_BIT) == 0 {
401 unsafe { sys::gl_get_buffer_sub_data(target, offset as u32, data.as_mut_ptr(), length as u32) }; }
403 let p = data.as_mut_ptr() as *mut c_void;
404 state(|s| s.maps.push(Mapping { target, data, offset, access }));
405 p
406}
407pub unsafe extern "C" fn glFlushMappedBufferRange(target: u32, offset: isize, length: isize) {
408 let ok = state(|s| match s.maps.iter().find(|m| m.target == target) {
409 Some(m) if offset >= 0 && length >= 0 && (offset + length) as usize <= m.data.len() => {
410 unsafe { sys::gl_buffer_sub_data(target, (m.offset + offset) as u32, m.data.as_ptr().add(offset as usize), length as u32) };
411 true
412 }
413 _ => false,
414 });
415 if !ok {
416 set_error(GL_INVALID_VALUE);
417 }
418}
419pub unsafe extern "C" fn glUnmapBuffer(target: u32) -> u8 {
420 let Some(m) = state(|s| s.maps.iter().position(|m| m.target == target).map(|i| s.maps.remove(i))) else {
421 set_error(GL_INVALID_OPERATION);
422 return 0;
423 };
424 if m.access & GL_MAP_WRITE_BIT != 0 && m.access & GL_MAP_FLUSH_EXPLICIT_BIT == 0 {
425 unsafe { sys::gl_buffer_sub_data(target, m.offset as u32, m.data.as_ptr(), m.data.len() as u32) };
426 }
427 1
428}
429pub unsafe extern "C" fn glGetBufferPointerv(target: u32, _pname: u32, params: *mut c_void) {
430 let p = state(|s| s.maps.iter().find(|m| m.target == target).map_or(std::ptr::null(), |m| m.data.as_ptr()));
431 unsafe { *(params as *mut *const u8) = p };
432}
433
434pub unsafe extern "C" fn glVertexAttribPointer(index: u32, size: i32, ty: u32, normalized: u8, stride: i32, pointer: *const c_void) {
437 unsafe { sys::gl_vertex_attrib_pointer(index, size, ty, normalized as u32, stride, pointer as usize as u32) };
438}
439pub unsafe extern "C" fn glVertexAttribIPointer(index: u32, size: i32, ty: u32, stride: i32, pointer: *const c_void) {
440 unsafe { sys::gl_vertex_attrib_ipointer(index, size, ty, stride, pointer as usize as u32) };
441}
442pub unsafe extern "C" fn glVertexAttrib1f(index: u32, x: f32) {
443 unsafe { sys::gl_vertex_attrib4f(index, x, 0.0, 0.0, 1.0) };
444}
445pub unsafe extern "C" fn glVertexAttrib2f(index: u32, x: f32, y: f32) {
446 unsafe { sys::gl_vertex_attrib4f(index, x, y, 0.0, 1.0) };
447}
448pub unsafe extern "C" fn glVertexAttrib3f(index: u32, x: f32, y: f32, z: f32) {
449 unsafe { sys::gl_vertex_attrib4f(index, x, y, z, 1.0) };
450}
451pub unsafe extern "C" fn glVertexAttrib1fv(index: u32, v: *const c_void) {
452 let v = v as *const f32;
453 unsafe { sys::gl_vertex_attrib4f(index, *v, 0.0, 0.0, 1.0) };
454}
455pub unsafe extern "C" fn glVertexAttrib2fv(index: u32, v: *const c_void) {
456 let v = v as *const f32;
457 unsafe { sys::gl_vertex_attrib4f(index, *v, *v.add(1), 0.0, 1.0) };
458}
459pub unsafe extern "C" fn glVertexAttrib3fv(index: u32, v: *const c_void) {
460 let v = v as *const f32;
461 unsafe { sys::gl_vertex_attrib4f(index, *v, *v.add(1), *v.add(2), 1.0) };
462}
463pub unsafe extern "C" fn glVertexAttrib4fv(index: u32, v: *const c_void) {
464 let v = v as *const f32;
465 unsafe { sys::gl_vertex_attrib4f(index, *v, *v.add(1), *v.add(2), *v.add(3)) };
466}
467pub unsafe extern "C" fn glVertexAttribI4iv(index: u32, v: *const c_void) {
468 let v = v as *const i32;
469 unsafe { sys::gl_vertex_attribi4i(index, *v, *v.add(1), *v.add(2), *v.add(3)) };
470}
471pub unsafe extern "C" fn glVertexAttribI4uiv(index: u32, v: *const c_void) {
472 let v = v as *const u32;
473 unsafe { sys::gl_vertex_attribi4ui(index, *v, *v.add(1), *v.add(2), *v.add(3)) };
474}
475pub unsafe extern "C" fn glDrawElements(mode: u32, count: i32, ty: u32, indices: *const c_void) {
476 unsafe { sys::gl_draw_elements(mode, count, ty, indices as usize as u32) };
477}
478pub unsafe extern "C" fn glDrawRangeElements(mode: u32, start: u32, end: u32, count: i32, ty: u32, indices: *const c_void) {
479 unsafe { sys::gl_draw_range_elements(mode, start, end, count, ty, indices as usize as u32) };
480}
481pub unsafe extern "C" fn glDrawElementsInstanced(mode: u32, count: i32, ty: u32, indices: *const c_void, instances: i32) {
482 unsafe { sys::gl_draw_elements_instanced(mode, count, ty, indices as usize as u32, instances) };
483}
484pub unsafe extern "C" fn glDrawBuffers(n: i32, bufs: *const c_void) {
485 unsafe { sys::gl_draw_buffers(bufs as *const u8, n.max(0) as u32) };
486}
487pub unsafe extern "C" fn glClearBufferiv(buffer: u32, drawbuffer: i32, value: *const c_void) {
488 unsafe { sys::gl_clear_bufferiv(buffer, drawbuffer, value as *const u8, if buffer == GL_COLOR { 4 } else { 1 }) };
489}
490pub unsafe extern "C" fn glClearBufferuiv(buffer: u32, drawbuffer: i32, value: *const c_void) {
491 unsafe { sys::gl_clear_bufferuiv(buffer, drawbuffer, value as *const u8, if buffer == GL_COLOR { 4 } else { 1 }) };
492}
493pub unsafe extern "C" fn glClearBufferfv(buffer: u32, drawbuffer: i32, value: *const c_void) {
494 unsafe { sys::gl_clear_bufferfv(buffer, drawbuffer, value as *const u8, if buffer == GL_COLOR { 4 } else { 1 }) };
495}
496
497pub unsafe extern "C" fn glPixelStorei(pname: u32, param: i32) {
500 state(|s| match pname {
501 0x0CF5 => s.unpack.alignment = param,
502 0x0CF2 => s.unpack.row_length = param,
503 0x806E => s.unpack.image_height = param,
504 0x0CF4 => s.unpack.skip_pixels = param,
505 0x0CF3 => s.unpack.skip_rows = param,
506 0x806D => s.unpack.skip_images = param,
507 0x0D05 => s.pack.alignment = param,
508 0x0D02 => s.pack.row_length = param,
509 0x0D04 => s.pack.skip_pixels = param,
510 0x0D03 => s.pack.skip_rows = param,
511 _ => {}
512 });
513 unsafe { sys::gl_pixel_storei(pname, param) };
514}
515pub unsafe extern "C" fn glTexImage2D(target: u32, level: i32, ifmt: i32, w: i32, h: i32, border: i32, format: u32, ty: u32, pixels: *const c_void) {
516 let (p, len) = unpack(pixels, w, h, 1, format, ty);
517 unsafe { sys::gl_tex_image_2d(target, level, ifmt, w, h, border, format, ty, p, len) };
518}
519pub unsafe extern "C" fn glTexImage3D(target: u32, level: i32, ifmt: i32, w: i32, h: i32, d: i32, border: i32, format: u32, ty: u32, pixels: *const c_void) {
520 let (p, len) = unpack(pixels, w, h, d, format, ty);
521 unsafe { sys::gl_tex_image_3d(target, level, ifmt, w, h, d, border, format, ty, p, len) };
522}
523pub unsafe extern "C" fn glTexSubImage2D(target: u32, level: i32, x: i32, y: i32, w: i32, h: i32, format: u32, ty: u32, pixels: *const c_void) {
524 let (p, len) = unpack(pixels, w, h, 1, format, ty);
525 unsafe { sys::gl_tex_sub_image_2d(target, level, x, y, w, h, format, ty, p, len) };
526}
527pub unsafe extern "C" fn glTexSubImage3D(target: u32, level: i32, x: i32, y: i32, z: i32, w: i32, h: i32, d: i32, format: u32, ty: u32, pixels: *const c_void) {
528 let (p, len) = unpack(pixels, w, h, d, format, ty);
529 unsafe { sys::gl_tex_sub_image_3d(target, level, x, y, z, w, h, d, format, ty, p, len) };
530}
531pub unsafe extern "C" fn glCompressedTexImage2D(target: u32, level: i32, ifmt: u32, w: i32, h: i32, border: i32, size: i32, data: *const c_void) {
532 unsafe { sys::gl_compressed_tex_image_2d(target, level, ifmt, w, h, border, data as *const u8, size as u32) };
533}
534pub unsafe extern "C" fn glCompressedTexImage3D(target: u32, level: i32, ifmt: u32, w: i32, h: i32, d: i32, border: i32, size: i32, data: *const c_void) {
535 unsafe { sys::gl_compressed_tex_image_3d(target, level, ifmt, w, h, d, border, data as *const u8, size as u32) };
536}
537pub unsafe extern "C" fn glCompressedTexSubImage2D(target: u32, level: i32, x: i32, y: i32, w: i32, h: i32, format: u32, size: i32, data: *const c_void) {
538 unsafe { sys::gl_compressed_tex_sub_image_2d(target, level, x, y, w, h, format, data as *const u8, size as u32) };
539}
540pub unsafe extern "C" fn glCompressedTexSubImage3D(
541 target: u32, level: i32, x: i32, y: i32, z: i32, w: i32, h: i32, d: i32, format: u32, size: i32, data: *const c_void,
542) {
543 unsafe { sys::gl_compressed_tex_sub_image_3d(target, level, x, y, z, w, h, d, format, data as *const u8, size as u32) };
544}
545pub unsafe extern "C" fn glTexParameteriv(target: u32, pname: u32, params: *const c_void) {
546 unsafe { sys::gl_tex_parameteri(target, pname, *(params as *const i32)) };
547}
548pub unsafe extern "C" fn glTexParameterfv(target: u32, pname: u32, params: *const c_void) {
549 unsafe { sys::gl_tex_parameterf(target, pname, *(params as *const f32)) };
550}
551pub unsafe extern "C" fn glSamplerParameteriv(sampler: u32, pname: u32, params: *const c_void) {
552 unsafe { sys::gl_sampler_parameteri(sampler, pname, *(params as *const i32)) };
553}
554pub unsafe extern "C" fn glSamplerParameterfv(sampler: u32, pname: u32, params: *const c_void) {
555 unsafe { sys::gl_sampler_parameterf(sampler, pname, *(params as *const f32)) };
556}
557pub unsafe extern "C" fn glReadPixels(x: i32, y: i32, w: i32, h: i32, format: u32, ty: u32, pixels: *mut c_void) {
558 let (pack_buffer, len) = state(|s| (s.pack_buffer, image_bytes(&s.pack, w, h, 1, format, ty)));
559 unsafe { sys::gl_read_pixels(x, y, w, h, format, ty, pixels as *mut u8, if pack_buffer != 0 { 0 } else { len }) };
560}
561pub unsafe extern "C" fn glInvalidateFramebuffer(target: u32, n: i32, attachments: *const c_void) {
562 unsafe { sys::gl_invalidate_framebuffer(target, attachments as *const u8, n.max(0) as u32) };
563}
564pub unsafe extern "C" fn glInvalidateSubFramebuffer(target: u32, n: i32, attachments: *const c_void, x: i32, y: i32, w: i32, h: i32) {
565 unsafe { sys::gl_invalidate_sub_framebuffer(target, attachments as *const u8, n.max(0) as u32, x, y, w, h) };
566}
567
568pub unsafe extern "C" fn glShaderSource(shader: u32, count: i32, strings: *const c_void, lengths: *const c_void) {
571 let strings = strings as *const *const c_void;
572 let lengths = lengths as *const i32;
573 let mut all = Vec::new();
574 for i in 0..count.max(0) as usize {
575 unsafe {
576 let p = *strings.add(i);
577 let n = if !lengths.is_null() && *lengths.add(i) >= 0 { *lengths.add(i) as u32 } else { cstr_len(p) };
578 all.extend_from_slice(std::slice::from_raw_parts(p as *const u8, n as usize));
579 }
580 }
581 unsafe { sys::gl_shader_source(shader, all.as_ptr(), all.len() as u32) };
582}
583pub unsafe extern "C" fn glGetShaderInfoLog(shader: u32, size: i32, length: *mut c_void, log: *mut c_void) {
584 unsafe { truncated(|p, n| sys::gl_get_shader_info_log(shader, p, n), size, length, log) };
585}
586pub unsafe extern "C" fn glGetProgramInfoLog(program: u32, size: i32, length: *mut c_void, log: *mut c_void) {
587 unsafe { truncated(|p, n| sys::gl_get_program_info_log(program, p, n), size, length, log) };
588}
589pub unsafe extern "C" fn glGetShaderSource(shader: u32, size: i32, length: *mut c_void, source: *mut c_void) {
590 unsafe { truncated(|p, n| sys::gl_get_shader_source(shader, p, n), size, length, source) };
591}
592pub unsafe extern "C" fn glGetActiveUniformBlockName(program: u32, index: u32, size: i32, length: *mut c_void, name: *mut c_void) {
593 unsafe { truncated(|p, n| sys::gl_get_active_uniform_block_name(program, index, p, n), size, length, name) };
594}
595pub unsafe extern "C" fn glGetActiveAttrib(program: u32, index: u32, size: i32, length: *mut c_void, out_size: *mut c_void, ty: *mut c_void, name: *mut c_void) {
596 unsafe { active_info(|p, i, d, c, info| sys::gl_get_active_attrib(p, i, d, c, info), program, index, size, length, out_size, ty, name) };
597}
598pub unsafe extern "C" fn glGetActiveUniform(program: u32, index: u32, size: i32, length: *mut c_void, out_size: *mut c_void, ty: *mut c_void, name: *mut c_void) {
599 unsafe { active_info(|p, i, d, c, info| sys::gl_get_active_uniform(p, i, d, c, info), program, index, size, length, out_size, ty, name) };
600}
601pub unsafe extern "C" fn glGetTransformFeedbackVarying(
602 program: u32, index: u32, size: i32, length: *mut c_void, out_size: *mut c_void, ty: *mut c_void, name: *mut c_void,
603) {
604 unsafe { active_info(|p, i, d, c, info| sys::gl_get_transform_feedback_varying(p, i, d, c, info), program, index, size, length, out_size, ty, name) };
605}
606pub unsafe extern "C" fn glGetAttachedShaders(program: u32, max: i32, count: *mut c_void, shaders: *mut c_void) {
607 let n = unsafe { sys::gl_get_attached_shaders(program, shaders as *mut u8, max.max(0) as u32) };
608 if !count.is_null() {
609 unsafe { *(count as *mut i32) = n.min(max) };
610 }
611}
612pub unsafe extern "C" fn glBindAttribLocation(program: u32, index: u32, name: *const c_void) {
613 unsafe { sys::gl_bind_attrib_location(program, index, name as *const u8, cstr_len(name)) };
614}
615pub unsafe extern "C" fn glGetAttribLocation(program: u32, name: *const c_void) -> i32 {
616 unsafe { sys::gl_get_attrib_location(program, name as *const u8, cstr_len(name)) }
617}
618pub unsafe extern "C" fn glGetFragDataLocation(program: u32, name: *const c_void) -> i32 {
619 unsafe { sys::gl_get_frag_data_location(program, name as *const u8, cstr_len(name)) }
620}
621pub unsafe extern "C" fn glGetUniformLocation(program: u32, name: *const c_void) -> i32 {
622 unsafe { sys::gl_get_uniform_location(program, name as *const u8, cstr_len(name)) }
623}
624pub unsafe extern "C" fn glGetUniformBlockIndex(program: u32, name: *const c_void) -> u32 {
625 unsafe { sys::gl_get_uniform_block_index(program, name as *const u8, cstr_len(name)) }
626}
627pub unsafe extern "C" fn glGetUniformIndices(program: u32, count: i32, names: *const c_void, indices: *mut c_void) {
628 let names = names as *const *const c_void;
629 for i in 0..count.max(0) as usize {
630 unsafe {
631 let n = *names.add(i);
632 *(indices as *mut u32).add(i) = sys::gl_get_uniform_index(program, n as *const u8, cstr_len(n));
633 }
634 }
635}
636pub unsafe extern "C" fn glGetActiveUniformsiv(program: u32, count: i32, indices: *const c_void, pname: u32, params: *mut c_void) {
637 unsafe { sys::gl_get_active_uniformsiv(program, indices as *const u8, count.max(0) as u32, pname, params as *mut u8) };
638}
639pub unsafe extern "C" fn glGetActiveUniformBlockiv(program: u32, index: u32, pname: u32, params: *mut c_void) {
640 unsafe { sys::gl_get_active_uniform_blockiv(program, index, pname, params as *mut u8, 64) };
641}
642pub unsafe extern "C" fn glTransformFeedbackVaryings(program: u32, count: i32, varyings: *const c_void, mode: u32) {
643 let varyings = varyings as *const *const c_void;
644 let mut all = Vec::new();
645 for i in 0..count.max(0) as usize {
646 unsafe {
647 let p = *varyings.add(i);
648 all.extend_from_slice(std::slice::from_raw_parts(p as *const u8, cstr_len(p) as usize + 1));
649 }
650 }
651 unsafe { sys::gl_transform_feedback_varyings(program, all.as_ptr(), all.len() as u32, count.max(0) as u32, mode) };
652}
653pub unsafe extern "C" fn glReleaseShaderCompiler() {}
654pub unsafe extern "C" fn glShaderBinary(_count: i32, _shaders: *const c_void, _format: u32, _binary: *const c_void, _length: i32) {
655 set_error(GL_INVALID_ENUM); }
657pub unsafe extern "C" fn glGetProgramBinary(_program: u32, _size: i32, length: *mut c_void, _format: *mut c_void, _binary: *mut c_void) {
658 if !length.is_null() {
659 unsafe { *(length as *mut i32) = 0 };
660 }
661 set_error(GL_INVALID_OPERATION);
662}
663pub unsafe extern "C" fn glProgramBinary(_program: u32, _format: u32, _binary: *const c_void, _length: i32) {
664 set_error(GL_INVALID_ENUM);
665}
666pub unsafe extern "C" fn glProgramParameteri(_program: u32, _pname: u32, _value: i32) {}
667
668pub unsafe extern "C" fn glFenceSync(condition: u32, flags: u32) -> *const c_void {
671 unsafe { sys::gl_fence_sync(condition, flags) as usize as *const c_void }
672}
673pub unsafe extern "C" fn glIsSync(sync: *const c_void) -> u8 {
674 unsafe { sys::gl_is_sync(sync as usize as u32) as u8 }
675}
676pub unsafe extern "C" fn glDeleteSync(sync: *const c_void) {
677 unsafe { sys::gl_delete_sync(sync as usize as u32) };
678}
679pub unsafe extern "C" fn glClientWaitSync(sync: *const c_void, flags: u32, timeout: u64) -> u32 {
680 unsafe { sys::gl_client_wait_sync(sync as usize as u32, flags, timeout) }
681}
682pub unsafe extern "C" fn glWaitSync(sync: *const c_void, flags: u32, timeout: u64) {
683 unsafe { sys::gl_wait_sync(sync as usize as u32, flags, timeout) };
684}
685pub unsafe extern "C" fn glGetSynciv(sync: *const c_void, pname: u32, count: i32, length: *mut c_void, values: *mut c_void) {
686 if count > 0 {
687 unsafe { *(values as *mut i32) = sys::gl_get_synciv(sync as usize as u32, pname) };
688 }
689 if !length.is_null() {
690 unsafe { *(length as *mut i32) = (count > 0) as i32 };
691 }
692}
693