A => .gitignore +3 -0
@@ 1,3 @@
+/target
+**/*.rs.bk
+Cargo.lock
A => Cargo.toml +16 -0
@@ 1,16 @@
+[package]
+name = "cypher-sys"
+version = "0.1.0"
+authors = ["chris <chris@indefini.org>"]
+edition = "2021"
+
+links = "cypher"
+build = "build.rs"
+
+[dependencies]
+libc = "0.2"
+
+[build-dependencies]
+pkg-config = "0.3"
+cc = "1.0"
+
A => LICENSE +21 -0
@@ 1,21 @@
+MIT License
+
+Copyright (c) 2024 Christophe Sadoine
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+SOFTWARE.
A => README +1 -0
@@ 1,1 @@
+OpenGL wrapper
A => build.rs +32 -0
@@ 1,32 @@
+use std::env;
+use std::path::PathBuf;
+
+fn main() {
+ let paths = Vec::new();
+ build_cypher(&paths);
+}
+
+fn build_cypher(include_paths: &[PathBuf]) {
+ let mut config = cc::Build::new();
+
+ for path in include_paths {
+ config.include(path);
+ }
+
+ config
+ .file("src/buffer.c")
+ .file("src/cypher.c")
+ .file("src/fbo.c")
+ .file("src/shader.c")
+ .file("src/texture.c");
+
+ config.compile("libcypher.a");
+
+ let out_dir = env::var("OUT_DIR").unwrap();
+
+ println!("cargo:rustc-link-search=native={}", out_dir);
+ println!(
+ "cargo:include={}/src",
+ env::current_dir().unwrap().display()
+ );
+}
A => src/buffer.c +75 -0
@@ 1,75 @@
+#include "buffer.h"
+#include "log.h"
+
+CglBuffer*
+cgl_buffer_init(const void* data, uint count)
+{
+ CglBuffer* b = calloc(1, sizeof *b);
+ b->target = GL_ARRAY_BUFFER;
+
+ glGenBuffers(1, &b->id);
+ glBindBuffer(b->target, b->id);
+ glBufferData(
+ b->target,
+ //b->size,
+ count * sizeof(GLfloat), //TODO size of f32
+ data,
+ GL_DYNAMIC_DRAW);
+
+ return b;
+}
+
+CglBuffer*
+cgl_buffer_index_init(const void* data, uint count)
+{
+ CglBuffer* b = calloc(1, sizeof *b);
+ b->target = GL_ELEMENT_ARRAY_BUFFER;
+
+ glGenBuffers(1, &b->id);
+ glBindBuffer(b->target, b->id);
+ glBufferData(
+ b->target,
+ //b->size,
+ count * sizeof(GLuint), //TODO
+ data,
+ GL_DYNAMIC_DRAW);
+
+ return b;
+}
+
+void
+cgl_buffer_update(
+ CglBuffer* b,
+ const void* data,
+ uint count)
+{
+ glBindBuffer(b->target, b->id);
+ glBufferSubData(
+ b->target,
+ 0,
+ //b->size,
+ count * sizeof(GLfloat), //TODO size of f32
+ data);
+}
+
+void
+cgl_buffer_index_update(
+ CglBuffer* b,
+ const void* data,
+ uint count)
+{
+ glBindBuffer(b->target, b->id);
+ glBufferSubData(
+ b->target,
+ 0,
+ //b->size,
+ count * sizeof(GLuint), //TODO
+ data);
+}
+
+void cgl_buffer_clean(CglBuffer* b)
+{
+ glDeleteBuffers(1, &b->id);
+ free(b);
+}
+
A => src/buffer.h +21 -0
@@ 1,21 @@
+#ifndef __buffer__
+#define __buffer__
+#include "gl.h"
+
+typedef struct _CglBuffer CglBuffer;
+
+struct _CglBuffer
+{
+ GLuint id;
+ GLenum target;
+};
+
+CglBuffer* cgl_buffer_init(const void* data, uint count);
+void cgl_buffer_update(CglBuffer* b, const void* data, uint count);
+
+CglBuffer* cgl_buffer_index_init(const void* data, uint count);
+void cgl_buffer_index_update(CglBuffer* b, const void* data, uint count);
+
+void cgl_buffer_clean(CglBuffer* buf);
+
+#endif
A => src/cypher.c +165 -0
@@ 1,165 @@
+#include "cypher.h"
+#include "gl.h"
+#include "stdio.h"
+#include "shader.h"
+#include "buffer.h"
+
+void cypher_init_simple()
+{
+ // uncomment to display version
+ //const GLubyte* ver_gl = glGetString(GL_VERSION);
+ //const GLubyte* ver_glsl = glGetString(GL_SHADING_LANGUAGE_VERSION);
+ //printf("cypher_init: GL %s, GLSL %s \n", ver_gl, ver_glsl);
+
+ glEnable(GL_DEPTH_TEST);
+ glEnable(GL_STENCIL_TEST);
+ glDepthFunc(GL_LEQUAL);
+ glClearDepthf(1.0f);
+ glClearStencil(0);
+}
+
+void cypher_init(rust_callback cb_init, void* data)
+{
+ cypher_init_simple();
+
+ if (cb_init && data) {
+ cb_init(data);
+ }
+}
+
+void cypher_draw_start(int w, int h)
+{
+ glViewport(0, 0, w, h);
+
+ //glClearColor(0.2, 0.4, 0.2, 1.0);
+ glClearColor(0.1, 0.1, 0.1, 1.0);
+ glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
+
+ glEnable(GL_BLEND);
+ glBlendFunc (GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
+}
+
+void cypher_viewport_set(int x, int y, int w, int h)
+{
+ glViewport(x, y, w, h);
+}
+
+void cypher_viewport_get(int* v)
+{
+ glGetIntegerv(GL_VIEWPORT, v);
+}
+
+
+//use for profiling
+void cypher_draw_end()
+{
+ glFinish();
+}
+
+void cypher_draw(rust_callback cb_draw, void* data, int w, int h)
+{
+ cypher_draw_start(w, h);
+
+ if (cb_draw && data) {
+ cb_draw(data);
+ }
+}
+
+void cypher_resize_simple(int w, int h)
+{
+ // GL Viewport stuff. you can avoid doing this if viewport is all the
+ // same as last frame if you want
+ glViewport(0, 0, w, h);
+}
+
+void cypher_resize(resize_callback cb_resize, void* data, int w, int h)
+{
+ cypher_resize_simple(w, h);
+
+ if (cb_resize && data) {
+ cb_resize(data, w, h);
+ }
+}
+
+void cgl_clear()
+{
+ glClear(GL_DEPTH_BUFFER_BIT);
+}
+
+static CglShaderAttribute* _position_attribute;
+static CglShader* shader;
+
+void demo_attribute_add(void* data, const char* name, CglShaderAttribute* att)
+{
+ printf("adding attribute %s, %p \n", name, data);
+ _position_attribute = att;
+}
+
+void cypher_demo_init()
+{
+ printf("init demo \n");
+ cypher_init_simple();
+ glViewport(0, 0, 1000, 1000);
+
+ const char * vert = "\
+ attribute vec3 position;\
+ void main(void)\
+ {\
+ gl_Position = vec4(position, 1.0);\
+ }\
+ ";
+
+ const char * frag = "\
+ void main(void)\
+ {\
+ gl_FragColor = vec4(1.0, 0.0, 0.0, 1.0);\
+ }";
+
+ shader = cgl_shader_init_string(vert, frag);
+ cgl_shader_attributes_init(shader, demo_attribute_add, NULL);
+
+ cgl_shader_use(shader);
+
+ int datalen = 3*3;
+ float data[] = {
+ /*
+ 0.0,0.0,-1.0,
+ 0.0,1.0,-1.0,
+ 1.0,0.0,-1.0
+ */
+ -1.0,-1.0,-1.0,
+ -1.0,1.0,-1.0,
+ 1.0,-1.0,-1.0,
+ };
+
+ CglBuffer* buffer = cgl_buffer_init(data, datalen);
+ cgl_shader_attribute_send(_position_attribute, buffer);
+}
+
+void cypher_demo_draw()
+{
+ glClearColor(0.2, 0.4, 0.2, 1.0);
+ glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
+
+ glEnable(GL_BLEND);
+ glBlendFunc (GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
+
+ cgl_shader_use(shader);
+ int vertex_count = 3;
+ cgl_draw( vertex_count);
+
+ printf("drawing demo \n");
+}
+
+void cypher_cull(int cull)
+{
+ if (cull == 0) {
+ //glDisable(GL_CULL_FACE);
+ glCullFace(GL_BACK);
+ }
+ else {
+ glEnable(GL_CULL_FACE);
+ glCullFace(GL_FRONT);
+ }
+}
+
A => src/cypher.h +19 -0
@@ 1,19 @@
+#ifndef __cypher__
+#define __cypher__
+
+typedef void (*rust_callback)(void* data);
+typedef void (*resize_callback)(void* data, int w, int h);
+
+void cypher_init_simple();
+void cypher_init(rust_callback cb_init, void* data);
+void cypher_draw(rust_callback cb_draw, void* data, int w, int h);
+void cypher_draw_start(int w, int h);
+void cypher_draw_end();
+void cypher_resize_simple(int w, int h);
+void cypher_resize(resize_callback cb_resize, void* data, int w, int h);
+
+void cgl_clear();
+
+void cypher_cull(int cull);
+
+#endif
A => src/fbo.c +292 -0
@@ 1,292 @@
+#include "fbo.h"
+#include "log.h"
+#include <stdio.h>
+
+CglFbo*
+cgl_create_fbo()
+{
+ CglFbo* f = calloc(1, sizeof *f);
+ f->has_color = 1;
+
+ glGenTextures(1, &f->texture_depth_stencil_id);
+ glBindTexture(GL_TEXTURE_2D, f->texture_depth_stencil_id);
+ glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
+ glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
+ glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
+ glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
+
+ //TODO texture resolution
+ int width = 1200;
+ int height = 400;
+ /*
+ glTexImage2D(
+ GL_TEXTURE_2D,
+ 0,
+ GL_DEPTH_COMPONENT,
+ width,
+ height,
+ 0,
+ GL_DEPTH_COMPONENT,
+ GL_FLOAT,
+ NULL);
+ */
+ glTexImage2D(
+ GL_TEXTURE_2D,
+ 0,
+ GL_DEPTH_STENCIL_OES,
+ width,
+ height,
+ 0,
+ GL_DEPTH_STENCIL_OES,
+ GL_UNSIGNED_INT_24_8_OES,
+ NULL);
+
+ glBindTexture(GL_TEXTURE_2D, 0);
+
+ glGenTextures(1, &f->texture_color);
+ glBindTexture(GL_TEXTURE_2D, f->texture_color);
+ glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
+ glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
+ glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
+ glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
+
+ glTexImage2D(
+ GL_TEXTURE_2D,
+ 0,
+ GL_RGB,
+ width,
+ height,
+ 0,
+ GL_RGB, //GL_DEPTH_STENCIL_OES,
+ GL_UNSIGNED_SHORT_5_6_5, //GL_UNSIGNED_INT_24_8_OES,
+ NULL);
+
+ glBindTexture(GL_TEXTURE_2D, 0);
+
+
+ /*
+ glGenRenderbuffers(1, &f->rb);
+ glBindRenderbuffer(GL_RENDERBUFFER, f->rb);
+ glRenderbufferStorage(GL_RENDERBUFFER, GL_RGBA, width, height);
+ //glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH24_STENCIL8_OES, width, height);
+ glBindRenderbuffer(GL_RENDERBUFFER, 0);
+ */
+
+ glGenFramebuffers(1, &f->fbo);
+ glBindFramebuffer(GL_FRAMEBUFFER, f->fbo);
+
+ glFramebufferTexture2D(
+ GL_FRAMEBUFFER,
+ GL_DEPTH_ATTACHMENT,
+ GL_TEXTURE_2D,
+ f->texture_depth_stencil_id,
+ 0);
+
+ glFramebufferTexture2D(
+ GL_FRAMEBUFFER,
+ GL_STENCIL_ATTACHMENT,
+ GL_TEXTURE_2D,
+ f->texture_depth_stencil_id,
+ 0);
+
+ glFramebufferTexture2D(
+ GL_FRAMEBUFFER,
+ GL_COLOR_ATTACHMENT0,
+ GL_TEXTURE_2D,
+ f->texture_color,
+ 0);
+
+ /*
+ glFramebufferRenderbuffer(
+ GL_FRAMEBUFFER,
+ GL_COLOR_ATTACHMENT0,
+ GL_RENDERBUFFER,
+ f->rb);
+ */
+
+
+ GLenum e = glCheckFramebufferStatus(GL_FRAMEBUFFER);
+
+ if (e != GL_FRAMEBUFFER_COMPLETE) {
+ printf("cypher::fbo, error : not complete\n");
+ }
+
+ glBindFramebuffer(GL_FRAMEBUFFER, 0);
+
+ return f;
+}
+
+void
+cgl_fbo_use(CglFbo* f)
+{
+ glBindTexture(GL_TEXTURE_2D, 0);
+ glBindFramebuffer(GL_FRAMEBUFFER, f->fbo);
+ glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT) ;
+ glEnable(GL_STENCIL_TEST);
+ glStencilFunc(GL_ALWAYS, 0x1, 0x1);
+ glStencilOp(GL_KEEP, GL_KEEP, GL_REPLACE);
+ //TODO clear
+}
+
+void
+cgl_fbo_use_end()
+{
+ glBindFramebuffer(GL_FRAMEBUFFER,0);
+}
+
+void
+cgl_fbo_resize(CglFbo* f, int w, int h)
+{
+ glBindTexture(GL_TEXTURE_2D, f->texture_depth_stencil_id);
+
+ glTexImage2D(
+ GL_TEXTURE_2D,
+ 0,
+ GL_DEPTH_STENCIL_OES,
+ w,
+ h,
+ 0,
+ GL_DEPTH_STENCIL_OES,
+ GL_UNSIGNED_INT_24_8_OES,
+ NULL);
+
+ glBindTexture(GL_TEXTURE_2D, 0);
+
+ if (f->has_color) {
+ glBindTexture(GL_TEXTURE_2D, f->texture_color);
+
+ glTexImage2D(
+ GL_TEXTURE_2D,
+ 0,
+ GL_RGB,
+ w,
+ h,
+ 0,
+ GL_RGB,
+ GL_UNSIGNED_SHORT_5_6_5,
+ NULL);
+
+ glBindTexture(GL_TEXTURE_2D, 0);
+ }
+
+ glBindRenderbuffer(GL_RENDERBUFFER, f->rb);
+ glRenderbufferStorage(GL_RENDERBUFFER, GL_RGBA, w, h);
+ //glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH24_STENCIL8_OES, w, h);
+ glBindRenderbuffer(GL_RENDERBUFFER, 0);
+}
+
+void
+cgl_fbo_destroy(CglFbo* s)
+{
+ //TODO
+ printf("TODO, destroy fbo : %p \n", s);
+}
+
+
+CglFbo*
+cgl_create_fbo_depth_only()
+{
+ CglFbo* f = calloc(1, sizeof *f);
+ f->has_color = 0;
+
+ glGenTextures(1, &f->texture_depth_stencil_id);
+ glBindTexture(GL_TEXTURE_2D, f->texture_depth_stencil_id);
+ glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
+ glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
+ glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
+ glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
+
+ //TODO texture resolution
+ int width = 1200;
+ int height = 400;
+ /*
+ glTexImage2D(
+ GL_TEXTURE_2D,
+ 0,
+ GL_DEPTH_COMPONENT,
+ width,
+ height,
+ 0,
+ GL_DEPTH_COMPONENT,
+ GL_FLOAT,
+ NULL);
+ */
+ glTexImage2D(
+ GL_TEXTURE_2D,
+ 0,
+ GL_DEPTH_STENCIL_OES,
+ width,
+ height,
+ 0,
+ GL_DEPTH_STENCIL_OES,
+ GL_UNSIGNED_INT_24_8_OES,
+ NULL);
+
+ glBindTexture(GL_TEXTURE_2D, 0);
+
+ glGenFramebuffers(1, &f->fbo);
+ glBindFramebuffer(GL_FRAMEBUFFER, f->fbo);
+
+ glFramebufferTexture2D(
+ GL_FRAMEBUFFER,
+ GL_DEPTH_ATTACHMENT,
+ GL_TEXTURE_2D,
+ f->texture_depth_stencil_id,
+ 0);
+
+ glFramebufferTexture2D(
+ GL_FRAMEBUFFER,
+ GL_STENCIL_ATTACHMENT,
+ GL_TEXTURE_2D,
+ f->texture_depth_stencil_id,
+ 0);
+
+ GLenum e = glCheckFramebufferStatus(GL_FRAMEBUFFER);
+
+ if (e == GL_FRAMEBUFFER_COMPLETE) {
+ printf("---->>>>>buffer complete\n");
+ }
+ else
+ printf("---->>>>>buffer NOOOOOOOOOOOOOOOT complete\n");
+
+ glBindFramebuffer(GL_FRAMEBUFFER, 0);
+
+ return f;
+}
+
+CglEglFbo* cgl_egl_fbo(void* egl_image)
+{
+ CglEglFbo* f = calloc(1, sizeof *f);
+
+ GLuint rbo = 0;
+ glGenRenderbuffers(1, &rbo);
+ glBindRenderbuffer(GL_RENDERBUFFER, rbo);
+ f->rbo = rbo;
+
+ //PFNGLEGLIMAGETARGETRENDERBUFFERSTORAGEOESPROC glEGLImageTargetRenderbufferStorageOES =
+ //(PFNGLEGLIMAGETARGETRENDERBUFFERSTORAGEOESPROC) eglGetProcAddress("glEGLImageTargetRenderbufferStorageOES");
+
+ glEGLImageTargetRenderbufferStorageOES(GL_RENDERBUFFER, egl_image);
+ glBindRenderbuffer(GL_RENDERBUFFER, 0);
+
+ GLuint fbo = 0;
+ glGenFramebuffers(1, &fbo);
+ glBindFramebuffer(GL_FRAMEBUFFER, fbo);
+ glFramebufferRenderbuffer(
+ GL_FRAMEBUFFER,
+ GL_COLOR_ATTACHMENT0,
+ GL_RENDERBUFFER,
+ rbo
+ );
+ //TODO do something with status or erase
+ //GLuint status = glCheckFramebufferStatus(GL_FRAMEBUFFER);
+ f->fbo = fbo;
+ glBindFramebuffer(GL_FRAMEBUFFER, 0);
+ return f;
+}
+
+void cgl_egl_fbo_use(const CglEglFbo* f)
+{
+ glBindFramebuffer(GL_FRAMEBUFFER, f->fbo);
+}
+
A => src/fbo.h +34 -0
@@ 1,34 @@
+#ifndef __fbo__
+#define __fbo__
+#include "gl.h"
+
+typedef struct _CglFbo CglFbo;
+
+struct _CglFbo {
+ GLuint texture_depth_stencil_id;
+ GLuint texture_color;
+ GLuint fbo;
+ GLuint rb;
+ //bool
+ int has_color;
+};
+
+CglFbo* cgl_create_fbo();
+CglFbo* cgl_create_fbo_depth_only();
+void cgl_fbo_use(CglFbo* fbo);
+void cgl_fbo_use_end();
+void cgl_fbo_resize(CglFbo* f, int w, int h);
+void cgl_fbo_destroy(CglFbo* s);
+
+
+typedef struct _CglEglFbo CglEglFbo;
+
+struct _CglEglFbo {
+ GLuint fbo;
+ GLuint rbo;
+};
+
+CglEglFbo* cgl_egl_fbo(void* egl_image);
+void cgl_egl_fbo_use(const CglEglFbo* fbo);
+
+#endif
A => src/gl.h +11 -0
@@ 1,11 @@
+#ifndef __gl__
+#define __gl__
+
+#include "stdlib.h"
+#define GL_GLEXT_PROTOTYPES 1
+#include "GLES2/gl2.h"
+#include "GLES2/gl2ext.h"
+typedef unsigned int uint;
+
+#endif
+
A => src/lib.rs +1 -0
@@ 1,1 @@
+//nothing here
A => src/log.h +9 -0
@@ 1,9 @@
+#ifndef __log__
+#define __log__
+#include <stdio.h>
+
+#define LOG(str,...) do {printf("LOG : "); printf(str, ## __VA_ARGS__); printf("\n");} while (0)
+#define ERR(str,...) do {printf("ERROR : "); printf(str, ## __VA_ARGS__); printf("\n");} while (0)
+
+
+#endif
A => src/shader.c +291 -0
@@ 1,291 @@
+#include "shader.h"
+#include "log.h"
+#include "stdio.h"
+#include "gl.h"
+
+CglShader*
+cgl_shader_init_string(const char* vert, const char* frag)
+{
+ CglShader* s = calloc(1, sizeof *s);
+ //TODO factorize this by creating a function that get the shader id
+ s->vert_shader = glCreateShader(GL_VERTEX_SHADER);
+ if (s->vert_shader == 0)
+ ERR("there was an error creating this vertex shader :\n%s\n", vert);
+
+ s->frag_shader = glCreateShader(GL_FRAGMENT_SHADER);
+ if (s->frag_shader == 0)
+ ERR("there was an error creating this fragment shader :\n%s\n", frag);
+
+ glShaderSource(s->vert_shader, 1, &vert, 0);
+ glCompileShader(s->vert_shader);
+
+ GLint status;
+ GLint info_length;
+ GLchar* message;
+
+ glGetShaderiv(s->vert_shader, GL_COMPILE_STATUS, &status);
+ if (status == GL_FALSE) {
+ ERR("There was an error compiling this vertex shader :\n%s\n", vert);
+ glGetShaderiv(s->vert_shader, GL_INFO_LOG_LENGTH, &info_length);
+ message = malloc(info_length);
+ glGetShaderInfoLog(s->vert_shader, info_length, 0, message);
+ ERR("Message was : '%s'",message);
+ free(message);
+ }
+
+ glShaderSource(s->frag_shader, 1, &frag, 0);
+ glCompileShader(s->frag_shader);
+
+ glGetShaderiv(s->frag_shader, GL_COMPILE_STATUS, &status);
+ if (status == GL_FALSE) {
+ ERR("There was an error compiling this fragment shader:\n%s\n", frag);
+ glGetShaderiv(s->frag_shader, GL_INFO_LOG_LENGTH, &info_length);
+ message = malloc(info_length);
+ glGetShaderInfoLog(s->frag_shader, info_length, 0, message);
+ ERR("Message was : '%s'",message);
+ free(message);
+ }
+
+ s->program = glCreateProgram();
+ glAttachShader(s->program, s->vert_shader);
+ glAttachShader(s->program, s->frag_shader);
+ glLinkProgram(s->program);
+
+ glGetProgramiv(s->program, GL_LINK_STATUS, &status);
+ if (status == GL_FALSE) {
+ ERR("There was an error in linking the program, frag : \n%s\n", frag );
+ glGetProgramiv(s->program, GL_INFO_LOG_LENGTH, &info_length);
+ message = malloc(info_length);
+ glGetProgramInfoLog(s->program, info_length, 0, message);
+ ERR("Message was : '%s'",message);
+ free(message);
+ }
+
+ return s;
+}
+
+static CglShaderAttribute*
+_cgl_shader_attribute_new(CglShader *s, const char* name, uint size)
+{
+ GLint att_tmp = glGetAttribLocation(s->program, name);
+ if (att_tmp == -1) {
+ ERR("Error in getting attribute '%s' at line %d", name, __LINE__);
+ return NULL;
+ }
+ else{
+ CglShaderAttribute* cgl_att = calloc(1, sizeof *cgl_att);
+ cgl_att->location = att_tmp;
+ //TODO printf("cypher: attributes check, name : %s, size: %i \n", name, size);
+ cgl_att->size = size;
+ cgl_att->type = GL_FLOAT;
+
+ return cgl_att;
+ }
+}
+
+//index is for sampler/texture, if none then -1
+CglShaderUniform*
+cgl_shader_uniform_new(CglShader *s, const char* name, int index)
+{
+ GLint uni_tmp = glGetUniformLocation(s->program, name);
+ if (uni_tmp == -1) {
+ ERR("Error in getting uniform '%s' at line %d", name, __LINE__);
+ return NULL;
+ }
+ else{
+ CglShaderUniform* cgl_uni = calloc(1, sizeof *cgl_uni);
+ cgl_uni->location = uni_tmp;
+ cgl_uni->sampler_index = index;
+ return cgl_uni;
+ }
+}
+
+void
+cgl_shader_use(CglShader* s)
+{
+ glUseProgram(s->program);
+}
+
+void
+cgl_shader_attribute_send(CglShaderAttribute* att, CglBuffer* buf)
+{
+ glBindBuffer(buf->target, buf->id);
+ glEnableVertexAttribArray(att->location);
+
+ glVertexAttribPointer(
+ att->location,
+ att->size,
+ att->type,
+ GL_FALSE,
+ 0,//buf->stride, //TODO
+ 0);
+
+}
+
+void
+cgl_draw(uint vertex_count)
+{
+ glDrawArrays(GL_TRIANGLES, 0, vertex_count );
+ glBindBuffer(GL_ARRAY_BUFFER, 0);
+}
+
+void
+cgl_draw_lines(uint vertex_count)
+{
+ glDrawArrays(GL_LINES, 0, vertex_count );
+ glBindBuffer(GL_ARRAY_BUFFER, 0);
+}
+
+
+void
+cgl_draw_faces(const CglBuffer* buffer, uint index_count)
+{
+ glBindBuffer(buffer->target, buffer->id);
+ glDrawElements(
+ GL_TRIANGLES,
+ index_count,
+ GL_UNSIGNED_INT,
+ 0);
+
+ glBindBuffer(buffer->target, 0);
+}
+
+void
+cgl_draw_end()
+{
+ glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
+ glBindBuffer(GL_ARRAY_BUFFER, 0);
+ //TODO glDisableVertexAttribArray?
+}
+
+void
+cgl_shader_uniform_int_set(CglShaderUniform* uni, int i)
+{
+ glUniform1i(uni->location, i);
+}
+
+void
+cgl_shader_uniform_float_set(CglShaderUniform* uni, float f)
+{
+ glUniform1f(uni->location, f);
+}
+
+void
+cgl_shader_uniform_vec2_set(CglShaderUniform* uni, float x, float y)
+{
+ glUniform2f(uni->location, x, y);
+}
+
+void
+cgl_shader_uniform_vec3_set(CglShaderUniform* uni, float x, float y, float z)
+{
+ glUniform3f(uni->location, x, y , z);
+}
+
+void
+cgl_shader_uniform_vec4_set(CglShaderUniform* uni, float x, float y, float z, float w)
+{
+ glUniform4f(uni->location, x, y , z, w);
+}
+
+void
+cgl_shader_uniform_mat4_set(CglShaderUniform* uni, const float* matrix)
+{
+ glUniformMatrix4fv(uni->location, 1, GL_FALSE, matrix);
+}
+
+void
+cgl_shader_uniform_mat3_set(CglShaderUniform* uni, const float* matrix)
+{
+ glUniformMatrix3fv(uni->location, 1, GL_FALSE, matrix);
+}
+
+void
+cgl_shader_uniform_texture_id_set(CglShaderUniform* uni, GLuint id, uint i)
+{
+ glUniform1i(uni->location, i);
+ glActiveTexture(GL_TEXTURE0 + i);
+ glBindTexture(GL_TEXTURE_2D, id);
+}
+
+
+void
+cgl_shader_uniform_texture_set(CglShaderUniform* uni, const CglTexture* texture, uint i)
+{
+ cgl_shader_uniform_texture_id_set(uni, texture->id, i);
+}
+
+
+void
+cgl_shader_uniform_fbo_depth_set(CglShaderUniform* uni, const CglFbo* fbo, uint i)
+{
+ glUniform1i(uni->location, i);
+ glActiveTexture(GL_TEXTURE0 + i);
+ glBindTexture(GL_TEXTURE_2D, fbo->texture_depth_stencil_id);
+ //printf("uniform fbo send id %d, index %d \n", fbo->texture_depth_stencil_id, i);
+}
+
+void
+cgl_shader_uniform_fbo_color_set(CglShaderUniform* uni, const CglFbo* fbo, uint i)
+{
+ glUniform1i(uni->location, i);
+ glActiveTexture(GL_TEXTURE0 + i);
+ glBindTexture(GL_TEXTURE_2D, fbo->texture_color);
+ //printf("uniform fbo send id %d, index %d \n", fbo->texture_depth_stencil_id, i);
+}
+
+void
+cgl_shader_uniforms_init(CglShader* s, uniform_set_cb cb, void* data)
+{
+ GLint num_uniforms;
+ glGetProgramiv(s->program, GL_ACTIVE_UNIFORMS, &num_uniforms);
+ GLchar uniform_name[256];
+ GLsizei length;
+ GLint size;
+ GLenum type;
+
+ int i = 0;
+ int sampler_index = 0;
+ for (i = 0; i < num_uniforms; i++){
+ glGetActiveUniform(s->program, i, sizeof(uniform_name), &length, &size, &type, uniform_name);
+
+ int index = -1;
+ if (type == GL_SAMPLER_2D) {
+ index = sampler_index;
+ sampler_index++;
+ }
+
+ CglShaderUniform* uni = cgl_shader_uniform_new(s, uniform_name, index);
+ cb(data, uniform_name, uni);
+ }
+}
+
+void
+cgl_shader_attributes_init(CglShader* s, attribute_set_cb cb, void* data)
+{
+ GLint num_attributes;
+ glGetProgramiv(s->program, GL_ACTIVE_ATTRIBUTES, &num_attributes);
+ GLchar attribute_name[256];
+ GLsizei length;
+ GLint size;
+ GLenum type;
+ int i = 0;
+ for (i = 0; i < num_attributes; i++) {
+ glGetActiveAttrib(s->program, i, sizeof(attribute_name), &length, &size, &type, attribute_name);
+
+ //TODO printf("cypher: attributes check, type : %i, size : %i \n", type, size);
+ if (type == GL_FLOAT_VEC2){
+ size *= 2;
+ }
+ else if (type == GL_FLOAT_VEC3){
+ size *= 3;
+ }
+ else if (type == GL_FLOAT_VEC4){
+ size *= 4;
+ }
+
+ CglShaderAttribute* att = _cgl_shader_attribute_new(s, attribute_name, size);
+ cb(data, attribute_name, att);
+ }
+}
+
A => src/shader.h +83 -0
@@ 1,83 @@
+#ifndef __shader__
+#define __shader__
+#include "gl.h"
+#include "buffer.h"
+#include "texture.h"
+#include "fbo.h"
+
+typedef struct _CglShaderAttribute CglShaderAttribute;
+
+struct _CglShaderAttribute
+{
+ GLint location;
+ GLint size;
+ GLenum type;
+};
+
+
+typedef struct _CglShaderUniform CglShaderUniform;
+struct _CglShaderUniform{
+ GLint location;
+ GLint sampler_index;
+ //UniformType type;
+};
+
+typedef enum _CglUniformType CglUniformType;
+enum _CglUniformType {
+ CGL_UNIFORM_UNKNOWN,
+ CGL_UNIFORM_TEXTURE,
+ CGL_UNIFORM_INT,
+ CGL_UNIFORM_FLOAT,
+ CGL_UNIFORM_VEC2,
+ CGL_UNIFORM_VEC3,
+ CGL_UNIFORM_VEC4,
+ CGL_UNIFORM_MAT3,
+ CGL_UNIFORM_MAT4
+};
+
+
+typedef struct _CglShader CglShader;
+
+struct _CglShader
+{
+ GLuint vert_shader;
+ GLuint frag_shader;
+ GLuint program;
+};
+
+
+typedef void (uniform_set_cb)(void* data, const char* name, CglShaderUniform* uni);
+typedef void (attribute_set_cb)(void* data, const char* name, CglShaderAttribute* uni);
+
+void cgl_shader_uniforms_init(CglShader* s, uniform_set_cb cb, void* data);
+void cgl_shader_attributes_init(CglShader* s, attribute_set_cb cb, void* data);
+
+CglShader* cgl_shader_init_string(const char* vert, const char* frag);
+
+void cgl_shader_use(CglShader* s);
+
+
+CglShaderAttribute* cgl_shader_attribute_new(CglShader *s, const char* name, uint size);
+CglShaderUniform* cgl_shader_uniform_new(CglShader *s, const char* name, int index);
+
+void cgl_shader_attribute_send(CglShaderAttribute* att, CglBuffer* buf);
+void cgl_draw(uint vertex_count);
+
+void cgl_shader_uniform_int_set(CglShaderUniform* uni, int i);
+void cgl_shader_uniform_float_set(CglShaderUniform* uni, float f);
+void cgl_shader_uniform_vec2_set(CglShaderUniform* uni, float x, float y);
+void cgl_shader_uniform_vec3_set(CglShaderUniform* uni, float x, float y, float z);
+void cgl_shader_uniform_vec4_set(CglShaderUniform* uni, float x, float y, float z, float w);
+void cgl_shader_uniform_mat4_set(CglShaderUniform* uni, const float* matrix);
+void cgl_shader_uniform_texture_set(CglShaderUniform* uni, const CglTexture* texture, uint i);
+void
+cgl_shader_uniform_texture_id_set(CglShaderUniform* uni, GLuint id, uint i);
+
+void cgl_shader_uniform_fbo_depth_set(CglShaderUniform* uni, const CglFbo* fbo, uint i);
+void cgl_shader_uniform_fbo_color_set(CglShaderUniform* uni, const CglFbo* fbo, uint i);
+
+void cgl_draw_faces(const CglBuffer* buffer, uint index_count);
+void cgl_draw_lines(uint vertex_count);
+void cgl_draw_end();
+
+#endif
A => src/texture.c +199 -0
@@ 1,199 @@
+#include "texture.h"
+#include "stdio.h"
+
+// This enum must be exactly the same as the rust one used in dormin.
+// at the time of writing it is at src/texture.rs
+enum InternalFormat {
+ Alpha,
+ Rgb,
+ Rgb8,
+ Rgba,
+ Rgba8
+};
+
+
+int get_gl_internal_format(int internal_format)
+{
+ int gl_internal_format = GL_RGBA;
+ if (internal_format == Alpha) {
+ gl_internal_format = GL_ALPHA;
+ }
+ else if (internal_format == Rgb) {
+ gl_internal_format = GL_RGB;
+ }
+ else if (internal_format == Rgb8) {
+ gl_internal_format = GL_RGB8_OES;
+ }
+ else if (internal_format == Rgba) {
+ gl_internal_format = GL_RGBA;
+ }
+ else if (internal_format == Rgba8) {
+ gl_internal_format = GL_RGBA8_OES;
+ }
+ else {
+ //TODO
+ printf("TODO: Texture internal format not implemented : %i \n", internal_format);
+ }
+
+ return gl_internal_format;
+}
+
+int get_gl_format_from_internal_format(int gl_internal_format)
+{
+ int gl_format = GL_RGBA;
+ if (gl_internal_format == GL_ALPHA) {
+ gl_format = GL_ALPHA;
+ }
+ else if (gl_internal_format == GL_RGB || gl_internal_format == GL_RGB8_OES) {
+ gl_format = GL_RGB;
+ }
+ else if (gl_internal_format == GL_RGBA || gl_internal_format == GL_RGBA8_OES) {
+ gl_format = GL_RGBA;
+ }
+ else {
+ //TODO
+ printf("TODO: Texture format not implemented : %i \n", gl_internal_format);
+ }
+
+ return gl_format;
+}
+
+
+CglTexture*
+cgl_texture_init(const void* data, int internal_format, int width, int height, int filtering)
+{
+ CglTexture* t = cgl_texture_new(internal_format, filtering);
+ int gl_internal_format = get_gl_internal_format(internal_format);
+ int gl_format = get_gl_format_from_internal_format(gl_internal_format);
+
+ glTexImage2D(
+ GL_TEXTURE_2D,
+ 0,
+ gl_internal_format,
+ width,
+ height,
+ 0,
+ gl_format, //GL_RGBA, //TODO tex->format,
+ GL_UNSIGNED_BYTE,
+ data);
+
+ return t;
+}
+
+void cgl_texture_update(
+ CglTexture* t,
+ int x,
+ int y,
+ int width,
+ int height,
+ int format,
+ void *data
+ )
+{
+ glBindTexture(GL_TEXTURE_2D, t->id);
+
+ int unpack = 4;
+ if (format == Alpha) {
+ glGetIntegerv(GL_UNPACK_ALIGNMENT, &unpack);
+ if (unpack != 1) {
+ glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
+ }
+ }
+
+ int gl_internal_format = get_gl_internal_format(format);
+ int gl_format = get_gl_format_from_internal_format(gl_internal_format);
+ glTexSubImage2D(
+ GL_TEXTURE_2D,
+ 0,
+ x,
+ y,
+ width,
+ height,
+ gl_format,
+ GL_UNSIGNED_BYTE,
+ data);
+
+ GLenum error = glGetError();
+
+ if (error) {
+ printf("there was an error with glTexSubImage2D\n");
+ }
+
+ if (format == Alpha && unpack != 1) {
+ glPixelStorei(GL_UNPACK_ALIGNMENT, unpack);
+ }
+}
+
+GLuint cgl_texture_id(const CglTexture* t)
+{
+ return t->id;
+}
+
+CglTexture* cgl_texture_from_id(const GLuint id)
+{
+ CglTexture* t = calloc(1, sizeof *t);
+ t->id = id;
+ return t;
+}
+
+CglTexture*
+cgl_texture_new(int internal_format, int filtering)
+{
+ //TODO free
+ CglTexture* t = calloc(1, sizeof *t);
+
+ glGenTextures(1, &t->id);
+ glBindTexture(GL_TEXTURE_2D, t->id);
+ if (filtering) {
+ glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
+ glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
+ }
+ else {
+ glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
+ glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
+ }
+
+ int gl_format = get_gl_internal_format(internal_format);
+
+ // default alignment is 4 so for rgb (3) we must set it to 1
+ if (gl_format == GL_RGB || gl_format == GL_RGB8_OES) {
+ glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
+ }
+
+ return t;
+}
+
+CglTexture*
+cgl_texture_from_egl_image(int is_external, void* image)
+{
+ CglTexture* t = calloc(1, sizeof *t);
+ glGenTextures(1, &t->id);
+
+ int target = GL_TEXTURE_2D;
+ if (is_external) target = GL_TEXTURE_EXTERNAL_OES;
+
+ glBindTexture(target, t->id);
+ glEGLImageTargetTexture2DOES(target, image);
+
+ //if you dont set the filters it does not work! (the texture is all black in the fragment shader...)
+ glTexParameterf(target, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
+ glTexParameterf(target, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
+
+ glBindTexture(target, 0);
+
+ return t;
+}
+
+void cgl_texture_write(CglTexture* t, void* data, int w, int h)
+{
+ GLuint fbo = 0;
+ glGenFramebuffers(1, &fbo);
+ glBindFramebuffer(GL_FRAMEBUFFER, fbo);
+
+ glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, t->id, 0);
+ glReadPixels(0, 0, w, h, GL_RGBA, GL_UNSIGNED_BYTE, data);
+
+ glBindFramebuffer(GL_FRAMEBUFFER, 0);
+ glDeleteFramebuffers(1, &fbo);
+}
+
A => src/texture.h +39 -0
@@ 1,39 @@
+#ifndef __texture__
+#define __texture__
+#include "gl.h"
+
+typedef struct _CglTexture CglTexture;
+
+struct _CglTexture
+{
+ GLuint id;
+};
+
+CglTexture* cgl_texture_new(
+ int internal_format,
+ int linear_filtering
+ );
+
+CglTexture* cgl_texture_init(
+ const void* data,
+ int internal_format,
+ int width,
+ int height,
+ int linear_filtering
+ );
+
+void cgl_texture_update(
+ CglTexture* t,
+ int x,
+ int y,
+ int width,
+ int height,
+ int format,
+ void *data
+ );
+
+GLuint cgl_texture_id(const CglTexture* t);
+
+CglTexture* cgl_texture_from_id(const GLuint id);
+
+#endif