1#[macro_use]
7extern crate dl_api;
8#[cfg(windows)]
9extern crate winapi;
10
11macro_rules! gl {
12 ($o: expr, $a: stmt) => (
13 unsafe {
14 let a = { $a };
15 $o.error();
16 a
17 }
18 )
19}
20
21use std::os::raw::c_void;
22use std::rc::Rc;
23use std::cell::RefCell;
24
25mod loader;
26mod types;
27
28use types::*;
29
30mod texture;
31mod vertex_data;
32mod uniform_data;
33mod program;
34mod buffer;
35
36pub use vertex_data::VertexData;
37pub use uniform_data::UniformData;
38pub use program::Program;
39pub use buffer::Buffer;
40pub use texture::Texture;
41
42#[repr(u32)]
44pub enum Feature {
45 Dither = 0x0BD0,
46 CullFace = 0x0B44,
47 Blend = 0x0BE2,
48 DepthTest = 0x0B71,
49 StencilTest = 0x0B90,
50}
51
52#[repr(u32)]
54pub enum Topology {
55 Points = 0x0000,
56 Lines = 0x0001,
57 LineLoop = 0x0002,
58 LineStrip = 0x0003,
59 Triangles = 0x0004,
60 TriangleStrip = 0x0005,
61 TriangleFan = 0x0006,
62}
63
64#[derive(Clone)] pub struct OpenGL(Rc<RefCell<OpenGLContext>>);
66
67pub struct OpenGLBuilder {
69 lib: loader::Lib,
70 display: loader::Display,
71}
72
73impl OpenGLBuilder {
74 pub fn new() -> Option<(OpenGLBuilder, i32)> {
76 if let Ok(lib) = loader::Lib::new() {
77 let (mut display, visual_id) = lib.init();
78
79 Some((OpenGLBuilder {
80 lib,
81 display,
82 }, visual_id))
83 } else {
84 None
85 }
86 }
87
88 pub fn to_opengl(mut self, window: EGLNativeWindowType) -> OpenGL {
90 self.lib.init2(&mut self.display, window);
91
92 OpenGL(Rc::new(RefCell::new(OpenGLContext {
93 clear: self.lib.load(b"glClear\0"),
95 clear_color: self.lib.load(b"glClearColor\0"),
96 disable: self.lib.load(b"glDisable\0"),
97 enable: self.lib.load(b"glEnable\0"),
98 #[cfg(debug_assertions)]
99 get_error: self.lib.load(b"glGetError\0"),
100 blend_func_separate:
101 self.lib.load(b"glBlendFuncSeparate\0"),
102 create_shader: self.lib.load(b"glCreateShader\0"),
103 shader_source: self.lib.load(b"glShaderSource\0"),
104 compile_shader: self.lib.load(b"glCompileShader\0"),
105 create_program: self.lib.load(b"glCreateProgram\0"),
106 attach_shader: self.lib.load(b"glAttachShader\0"),
107 link_program: self.lib.load(b"glLinkProgram\0"),
108 uniform: self.lib.load(b"glGetUniformLocation\0"),
109 gen_buffers: self.lib.load(b"glGenBuffers\0"),
110 bind_buffer: self.lib.load(b"glBindBuffer\0"),
111 buffer_data: self.lib.load(b"glBufferData\0"),
112 vdata: self.lib.load(b"glGetAttribLocation\0"),
113 #[cfg(debug_assertions)]
114 get_shader: self.lib.load(b"glGetShaderiv\0"),
115 #[cfg(debug_assertions)]
116 info_log: self.lib.load(b"glGetShaderInfoLog\0"),
117 draw_arrays: self.lib.load(b"glDrawArrays\0"),
118 use_program: self.lib.load(b"glUseProgram\0"),
119 uniform_mat4: self.lib.load(b"glUniformMatrix4fv\0"),
120 uniform_int1: self.lib.load(b"glUniform1i\0"),
121 uniform_vec1: self.lib.load(b"glUniform1f\0"),
122 uniform_vec2: self.lib.load(b"glUniform2f\0"),
123 uniform_vec3: self.lib.load(b"glUniform3f\0"),
124 uniform_vec4: self.lib.load(b"glUniform4f\0"),
125 bind_texture: self.lib.load(b"glBindTexture\0"),
126 vertex_attrib: self.lib.load(b"glVertexAttribPointer\0"),
127 gen_textures: self.lib.load(b"glGenTextures\0"),
128 tex_params: self.lib.load(b"glTexParameteri\0"),
129 tex_image: self.lib.load(b"glTexImage2D\0"),
130 tex_subimage: self.lib.load(b"glTexSubImage2D\0"),
131 enable_vdata: self.lib.load(b"glEnableVertexAttribArray\0"),
132 viewport: self.lib.load(b"glViewport\0"),
133 gen_mipmap: self.lib.load(b"glGenerateMipmap\0"),
134 detach_shader: self.lib.load(b"glDetachShader\0"),
135 delete_program: self.lib.load(b"glDeleteProgram\0"),
136 delete_buffer: self.lib.load(b"glDeleteBuffers\0"),
137 delete_texture: self.lib.load(b"glDeleteTextures\0"),
138 stencil_op: self.lib.load(b"glStencilOp\0"),
139 stencil_func: self.lib.load(b"glStencilFunc\0"),
140 display: self.display,
142 lib: self.lib,
143 })))
144 }
145}
146
147struct OpenGLContext {
149 #[allow(unused)] lib: loader::Lib,
151 display: loader::Display,
152 clear: unsafe extern "system" fn(GLbitfield) -> (),
153 clear_color: unsafe extern "system" fn(GLfloat, GLfloat, GLfloat,
154 GLfloat) -> (),
155 disable: unsafe extern "system" fn(GLenum) -> (),
156 enable: unsafe extern "system" fn(GLenum) -> (),
157 #[cfg(debug_assertions)] get_error: unsafe extern "system" fn() -> GLenum,
158 blend_func_separate: unsafe extern "system" fn(GLenum, GLenum, GLenum,
159 GLenum) -> (),
160 create_shader: unsafe extern "system" fn(GLenum) -> GLuint,
161 shader_source: unsafe extern "system" fn(GLuint, GLsizei,
162 *const *const GLchar, *const GLint) -> (),
163 compile_shader: unsafe extern "system" fn(GLuint) -> (),
164 create_program: unsafe extern "system" fn() -> GLuint,
165 attach_shader: unsafe extern "system" fn(GLuint, GLuint) -> (),
166 link_program: unsafe extern "system" fn(GLuint) -> (),
167 uniform: unsafe extern "system" fn(GLuint, *const GLchar) -> GLint,
168 gen_buffers: unsafe extern "system" fn(GLsizei, *mut GLuint) -> (),
169 bind_buffer: unsafe extern "system" fn(GLenum, GLuint) -> (),
170 buffer_data: unsafe extern "system" fn(GLenum, GLsizeiptr,
171 *const c_void, GLenum) -> (),
172 vdata: unsafe extern "system" fn(GLuint, *const GLchar) -> GLint,
173 #[cfg(debug_assertions)]
174 get_shader: unsafe extern "system" fn(GLuint, GLenum, *mut GLint) -> (),
175 #[cfg(debug_assertions)]
176 info_log: unsafe extern "system" fn(GLuint, GLsizei, *mut GLsizei,
177 *mut GLchar) -> (),
178 draw_arrays: unsafe extern "system" fn(GLenum, GLint, GLsizei) -> (),
179 use_program: unsafe extern "system" fn(GLuint) -> (),
180 uniform_mat4: unsafe extern "system" fn(GLint, GLsizei, GLboolean,
181 *const GLfloat) -> (),
182 uniform_int1: unsafe extern "system" fn(GLint, GLint) -> (),
183 uniform_vec1: unsafe extern "system" fn(GLint, GLfloat) -> (),
184 uniform_vec2: unsafe extern "system" fn(GLint, GLfloat, GLfloat) -> (),
185 uniform_vec3: unsafe extern "system" fn(GLint, GLfloat, GLfloat, GLfloat)
186 -> (),
187 uniform_vec4: unsafe extern "system" fn(GLint, GLfloat, GLfloat, GLfloat,
188 GLfloat) -> (),
189 bind_texture: unsafe extern "system" fn(GLenum, GLuint) -> (),
190 vertex_attrib: unsafe extern "system" fn(GLuint, GLint, GLenum,
191 GLboolean, GLsizei, *const c_void) -> (),
192 gen_textures: unsafe extern "system" fn(GLsizei, *mut GLuint) -> (),
193 tex_params: unsafe extern "system" fn(GLenum, GLenum, GLint) -> (),
194 tex_image: unsafe extern "system" fn(GLenum, GLint, GLint, GLsizei,
195 GLsizei, GLint, GLenum, GLenum, *const c_void) -> (),
196 tex_subimage: unsafe extern "system" fn(GLenum, GLint, GLint, GLint, GLsizei,
197 GLsizei, GLenum, GLenum, *const c_void) -> (),
198 enable_vdata: unsafe extern "system" fn(GLuint) -> (),
199 viewport: unsafe extern "system" fn(GLint, GLint, GLsizei, GLsizei) -> (),
200 gen_mipmap: unsafe extern "system" fn(GLenum) -> (),
201 detach_shader: unsafe extern "system" fn(GLuint, GLuint) -> (),
202 delete_program: unsafe extern "system" fn(GLuint) -> (),
203 delete_buffer: unsafe extern "system" fn(GLsizei, *const GLuint) -> (),
204 delete_texture: unsafe extern "system" fn(GLsizei, *const GLuint) -> (),
205 stencil_op: unsafe extern "system" fn(GLenum, GLenum, GLenum) -> (),
206 stencil_func: unsafe extern "system" fn(GLenum, GLint, GLuint) -> (),
207}
208
209impl OpenGL {
210 pub fn color(&self, r: f32, g: f32, b: f32) {
212 gl!(self, (self.get().clear_color)(r, g, b, 1.0));
213 }
214
215 pub fn update(&self) {
217 self.get().display.swap(
219 #[cfg(not(target_os = "windows"))]
220 &self.get().lib
221 );
222 gl!(self, (self.get().clear)(0x00000100 | 0x00004000));
224 }
225
226 pub fn enable(&self, what: Feature) {
228 gl!(self, (self.get().enable)(what as u32))
229 }
230
231 pub fn disable(&self, what: Feature) {
233 gl!(self, (self.get().disable)(what as u32))
234 }
235
236 pub fn blend(&self) {
238 const GL_SRC_ALPHA: u32 = 0x0302;
239 const GL_ONE_MINUS_SRC_ALPHA: u32 = 0x0303;
240 const GL_DST_ALPHA: u32 = 0x0304;
241
242 gl!(self, (self.get().blend_func_separate)(
243 GL_SRC_ALPHA,
244 GL_ONE_MINUS_SRC_ALPHA,
245 GL_SRC_ALPHA,
246 GL_DST_ALPHA
247 ));
248 }
249
250 pub fn stencil(&self) {
252 gl!(self, (self.get().stencil_op)(
253 0x150A, 0x150A, 0x150A ));
255
256 gl!(self, (self.get().stencil_func)(
257 0x0205, 0, 0xffffffff ));
261 }
262
263 pub fn texture(&self) -> Texture {
265 Texture::new(self)
266 }
267
268 pub fn viewport(&self, w: u16, h: u16) {
270 gl!(self, (self.get().viewport)(0,0,w as GLsizei,h as GLsizei));
271 }
272
273 #[cfg(not(debug_assertions))]
274 unsafe fn error(&self) { }
275
276 #[cfg(debug_assertions)]
277 unsafe fn error(&self) {
278 match (self.get().get_error)() {
279 0 => return, 0x0500 => panic!("OpenGL Error: Invalid enum"),
281 0x0501 => panic!("OpenGL Error: Invalid value"),
282 0x0502 => panic!("OpenGL Error: Invalid operation"),
283 0x0503 => panic!("OpenGL Error: Stack overflow"),
284 0x0504 => panic!("OpenGL Error: Stack underflow"),
285 0x0505 => panic!("OpenGL Error: Out of memory"),
286 _ => panic!("OpenGL Error: Unknown"),
287 }
288 }
289
290 fn get(&self) -> std::cell::Ref<OpenGLContext> {
291 self.0.borrow()
292 }
293}