1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
/*!
Easy to use, light OpenGL 3+ wrapper

glin aims to be a mostly bindless, simple wrapper over opengl that simplifies and provides a safe
api for opengl without aiming to cover every possible case but instead making it easy to use unsafe
calls in combination with the safe api when one needs to use extensions or any opengl api that is
not covered (yet).

That means for example that in certain cases functions will take GLenums directly as parameters
when the particular parameter can change or have several options not originally on the standard
through extensions, while parameters that have clearly defined options in the standard will have
an enum representation.

# Usage

The first thing needed to use glin is a Context. A context needs an instance implementing GLWindow
to be able to load the Open GL or Open GL ES functions:

```no_run
#[cfg(feature = "glfw")]
use glfw::Context;

#[cfg(feature = "glfw")]
fn main(){
    let mut glfw_instance = glfw::init(glfw::FAIL_ON_ERRORS).unwrap();

    glfw_instance.window_hint(glfw::WindowHint::ContextVersion(4, 1));
    glfw_instance.window_hint(glfw::WindowHint::OpenGlProfile( glfw::OpenGlProfileHint::Core ));
    glfw_instance.window_hint(glfw::WindowHint::OpenGlForwardCompat(true));
    let (mut window, receiver) = glfw_instance
        .create_window(1280, 720, "triangle", glfw::WindowMode::Windowed).unwrap();
    window.set_key_polling(true);
    window.make_current();
    glfw_instance.set_swap_interval(glfw::SwapInterval::Sync(1));

    let gl = glin::Context::new(&mut window).unwrap();
}

#[cfg(feature = "egli")]
use egli::Display;

#[cfg(feature = "egli")]
fn main(){
    use std::ptr;

    let mut display = Display::from_default_display()
        .expect("failed to get EGL display");

    display.initialize()
        .expect("failed to initialize");

    let configs = display.config_filter()
                         .choose_configs()
                         .expect("failed to get configurations");

    let config = *configs.first().unwrap();
    let surface = display.create_window_surface(config, ptr::null_mut()).unwrap();

    let context = display
        .create_context_with_client_version(config, egli::ContextClientVersion::OpenGlEs2)
        .unwrap();

    display.make_current(&surface, &surface, &context).unwrap();

    let gl = glin::Context::new(&mut display).unwrap();
}


#[cfg(feature = "glutin")]
use glutin::GlContext;

#[cfg(feature = "glutin")]
fn main(){
    let mut events_loop = glutin::EventsLoop::new();
    let window = glutin::WindowBuilder::new()
        .with_title("Hello, world!")
        .with_dimensions(1024, 768);
    let context = glutin::ContextBuilder::new()
        .with_vsync(true);
    let mut gl_window = glutin::GlWindow::new(window, context, &events_loop).unwrap();

    unsafe {
        gl_window.make_current().unwrap();
    }

    let gl = glin::Context::new(&mut gl_window).unwrap();
}

#[cfg(not(any(feature="glfw", feature="egli", feature="glutin")))]
fn main() {}
```

Once we have a context we can start creating glin objects and issuing draw calls through it.

# Creating glin Objects

To create any glin object you need a context and the constructor calls are done through that context
which generally returns a builder that can be customized with more parameters to finally create
the desired object:

```no_run
# use std::mem;
use glin::gl;

struct Vertex{
    position: [f32;3],
}

fn main(){
    # let gl: glin::Context = unsafe{ mem::MaybeUninit::uninit().assume_init() };
    let buffer_object: glin::Buffer<Vertex> = gl.new_buffer().empty().unwrap();
    let program = gl.new_program().from_src(&[
            (gl::VERTEX_SHADER, "// vertex shader source"),
            (gl::FRAGMENT_SHADER, "// fragment shader source"),
        ]).unwrap();
    let _texture = gl.new_texture().from_format(glin::texture::Format{
        target: gl::TEXTURE_2D,
        internal_format: gl::RGBA,
        width: 640,
        height: 480,
        levels: 1,
        #[cfg(all(not(feature = "gles"), not(feature="webgl")))]
        samples: 0,
    });
}
```

# Drawing

Drawing geometry in glin is done through vaos. A VAO is just an OpenGL vertex array object but also
contains a memory reference to the buffers it uses internally.

Apart from the geometry in order to draw something in glin you'll need a glsl program, it's
uniforms and optionally some properties that customize the drawing.

To use a set of properties, just call with on an exisiting context to create a new context with
the original properties + the new properties passed as parameter:

```no_run
#[macro_use] extern crate glin;
use std::mem;
use glin::gl;

#[derive(VertexFormat)]
struct Vertex{
    position: [f32;3],
}

fn main(){
    let gl: glin::Context = unsafe{ mem::uninitialized() };
    let buffer_object: glin::Buffer<Vertex> = gl.new_buffer().empty().unwrap();
    let program = gl.new_program().from_src(&[
            (gl::VERTEX_SHADER, "// vertex shader source"),
            (gl::FRAGMENT_SHADER, "// fragment shader source"),
        ]).unwrap();
    let vao: glin::SimpleVao<Vertex> = gl.new_simple_vao()
        .empty_from_bindings(&program, gl::TRIANGLES)
        .unwrap();
    let gl = gl.with(&[glin::Property::DepthTest(true)]);
    gl.draw(&vao, &program, &[]).is_ok();
}
```
*/
// #![warn(clippy::all)]
#[macro_use] extern crate mopa;
extern crate regex;
#[macro_use] extern crate bitflags;
#[cfg(feature = "webgl")]
#[macro_use] extern crate stdweb;
#[cfg(feature = "webgl")]
#[macro_use] extern crate stdweb_derive;
#[cfg(feature = "webgl")]
extern crate serde;
#[cfg(feature = "webgl")]
#[macro_use] extern crate serde_derive;
#[cfg(feature = "webgl")]
extern crate densevec;
#[cfg(feature = "webgl")]
extern crate mem_cmp;
#[macro_use] extern crate log;
#[macro_use] extern crate lazy_static;
extern crate indexmap;
#[cfg(feature="glsl_optimizer")]
extern crate glsl_optimizer_sys;

#[doc(inline)]
pub use program::Program;
#[doc(inline)]
pub use attributes::{VertexFormat, Bindings};
#[doc(inline)]
pub use vao::{Vao, VaoRange, VaoDraw};
#[doc(inline)]
pub use vao::simple_vao::{self, SimpleVao};
#[doc(inline)]
pub use fbo::Fbo;
#[doc(inline)]
#[cfg(all(not(feature = "gles"), not(feature="webgl")))]
pub use buffer::{Buffer, SharedBuffer, BufferStorage, SharedBufferStorage,
    MapReadFlags, MapWriteFlags, MapReadWriteFlags, BufferRange, BufferRangeMut};
#[doc(inline)]
#[cfg(any(feature = "gles", feature="webgl"))]
pub use buffer::{Buffer, SharedBuffer, BufferRange, BufferRangeMut};
#[doc(inline)]
pub use texture::{Texture, TextureSampler};
#[doc(inline)]
pub use cubemap::CubeMap;
#[doc(inline)]
pub use state::{Property, Vendor};
#[cfg(all(not(feature = "gles"), not(feature="webgl")))]
#[doc(inline)]
pub use state::{DebugInfo, DebugSeverity, DebugSource, DebugType};
#[doc(inline)]
pub use context::{
    Context, CreationContext, CreationContextMut, CreationProxy,
    SurfaceCreationContext, Screen, RenderSurface
};
#[doc(inline)]
pub use state::State;
#[doc(inline)]
pub use utils::Rect;
#[doc(inline)]
pub use features::traits::{Image, CubemapImage};
#[cfg(not(feature="webgl"))]
#[doc(inline)]
pub use features::traits::GlWindow;
#[cfg(feature="webgl")]
#[doc(inline)]
pub use features::traits::WebGlWindow;
#[doc(inline)]
pub use error::{Error, ErrorKind};
#[doc(inline)]
pub use offscreen_buffer::{OffscreenBuffer, UntypedOffscreenBuffer};
#[doc(inline)]
pub use sampler::Sampler;
#[doc(inline)]
pub use utils::{gl_format_from_internal, gl_type_from_internal, Color};
#[doc(inline)]
pub use state::{Capabilities, Viewport};
#[doc(inline)]
#[cfg(all(not(feature = "gles"), not(feature="webgl")))]
pub use sync::Fence;
#[cfg(not(feature="webgl"))]
pub use debug_group::DebugGroup;
pub use indexmap::{IndexMap as HashMap, indexmap as hash_map};

#[cfg(feature = "gles")]
pub use gles as gl;

#[cfg(feature = "webgl")]
pub use webgl2 as gl;

use std::result;

#[macro_use] pub mod macros;
#[macro_use] mod utils;
pub mod program;
pub mod texture;
pub mod cubemap;
pub mod buffer;
pub mod fbo;
mod state;
mod context;
mod features;
pub mod attributes;
pub mod vao;
#[cfg(all(not(feature = "gles"), not(feature="webgl")))]
pub mod gl;
#[cfg(feature = "gles")]
pub mod gles;
#[cfg(feature = "webgl")]
pub mod webgl2;
mod error;
#[cfg(all(not(feature = "gles"), not(feature="webgl")))]
pub mod query;
mod offscreen_buffer;
mod sampler;
#[cfg(all(not(feature = "gles"), not(feature="webgl")))]
mod sync;
#[cfg(not(feature="webgl"))]
mod debug_group;

pub type IndexT = u32;
pub type Result<T> = result::Result<T,Error>;

#[cfg(feature = "derive")]
#[allow(unused_imports)]
#[macro_use]
extern crate glin_derive;

#[cfg(feature = "derive")]
#[doc(hidden)]
pub use glin_derive::*;



use std::os::raw::c_uint;

#[repr(C)]
pub struct DrawElementsIndirectCommand{
    pub count: c_uint,
    pub instance_count: c_uint,
    pub first_index: c_uint,
    pub base_vertex: c_uint,
    pub base_instance: c_uint,
}

#[repr(C)]
pub struct DrawArraysIndirectCommand{
    pub count: c_uint,
    pub instance_count: c_uint,
    pub first: c_uint,
    pub base_instance: c_uint,
}