Skip to content

Commit

Permalink
Implement struct loader generator.
Browse files Browse the repository at this point in the history
  • Loading branch information
brendanzab committed Jul 30, 2014
1 parent fa00b63 commit 052895c
Show file tree
Hide file tree
Showing 12 changed files with 585 additions and 70 deletions.
79 changes: 47 additions & 32 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -18,9 +18,9 @@ RUSTDOC = rustdoc

SRC_DIR = src
TEST_DIR = test
LIB_FILE = $(SRC_DIR)/gl.rs
GL_LIB_FILE = $(SRC_DIR)/gl.rs
GEN_FILE = $(SRC_DIR)/gl_generator/src/main.rs
EXAMPLE_FILES = $(SRC_DIR)/examples/*.rs
GEN_MACRO_FILE = $(SRC_DIR)/gl_generator/src/gl_generator.rs

BIN_DIR = bin
DEPS_DIR = deps
Expand All @@ -35,6 +35,7 @@ GL_API ?= gl
GL_PROFILE ?= core
GL_VERSION ?= 4.3
GL_EXTENSIONS ?=
GL_GENERATOR ?=
GL_FULL ?=
GL_XML ?= $(DEPS_DIR)/khronos-api/$(GL_API).xml

Expand All @@ -44,75 +45,89 @@ GEN_FLAGS ?= \
--profile $(GL_PROFILE) \
--version $(GL_VERSION) --xml $(GL_XML) \
$(foreach EXTENSION, $(GL_EXTENSIONS), --extension $(EXTENSION)) \
$(if $(GL_GENERATOR), --generator $(GL_GENERATOR)) \
$(if $(GL_FULL), --full)

MAKE=make
ifeq ($(OS),Windows_NT)
MAKE=mingw32-make
endif

all: lib examples doc
all: gl-lib gen-macro examples doc

submodule-update:
@git submodule init
@git submodule update

gen-deps: $(DEPS_DIR)/sax-rs/README.md
$(MAKE) lib -C $(DEPS_DIR)/sax-rs

$(DEPS_DIR)/sax-rs/README.md: submodule-update

gen: gen-deps
@mkdir -p $(BIN_DIR)
$(RUSTC) -L $(DEPS_DIR)/sax-rs/lib $(GEN_FILE) -o $(GLRSGEN)

gen-lib: gen
@mkdir -p $(LIB_DIR)
$(GLRSGEN) $(GEN_FLAGS) > $(GL_LIB_FILE)

gl-lib: gen-lib
$(RUSTC) $(GL_LIB_FILE) -O --out-dir=$(LIB_DIR)

gen-macro: gen-deps
@mkdir -p $(LIB_DIR)
$(RUSTC) -L $(DEPS_DIR)/sax-rs/lib $(GEN_MACRO_FILE) -O --out-dir=$(LIB_DIR)

check:
@mkdir -p $(TEST_DIR)
$(RUSTC) --out-dir=$(TEST_DIR) --test $(LIB_FILE)
$(RUSTC) --out-dir=$(TEST_DIR) --test $(GL_LIB_FILE)
$(TEST_DIR)/gl

doc:
@mkdir -p $(DOC_DIR)
$(RUSTDOC) -o $(DOC_DIR) $(LIB_FILE)
$(RUSTDOC) -o $(DOC_DIR) $(GL_LIB_FILE)

examples-dir:
mkdir -p $(EXAMPLES_DIR)

examples-deps:
examples-deps: examples-dir
$(MAKE) lib -C $(DEPS_DIR)/glfw-rs

$(EXAMPLE_FILES): lib examples-dir examples-deps
$(RUSTC) -L $(DEPS_DIR)/glfw-rs/lib -L $(LIB_DIR) --out-dir=$(EXAMPLES_DIR) $@
example-static-basic: gl-lib examples-dir examples-deps
$(RUSTC) -L $(DEPS_DIR)/glfw-rs/lib -L $(LIB_DIR) --out-dir=$(EXAMPLES_DIR) $(SRC_DIR)/examples/static_basic.rs

examples: $(EXAMPLE_FILES)
example-static-triangle:
$(RUSTC) -L $(DEPS_DIR)/glfw-rs/lib -L $(LIB_DIR) --out-dir=$(EXAMPLES_DIR) $(SRC_DIR)/examples/static_triangle.rs

gen-deps: $(DEPS_DIR)/sax-rs/README.md
$(MAKE) lib -C $(DEPS_DIR)/sax-rs
example-struct-triangle: gen-macro examples-dir examples-deps
$(RUSTC) -L $(DEPS_DIR)/glfw-rs/lib -L $(LIB_DIR) --out-dir=$(EXAMPLES_DIR) $(SRC_DIR)/examples/struct_triangle.rs

$(DEPS_DIR)/sax-rs/README.md: submodule-update

gen: gen-deps
@mkdir -p $(BIN_DIR)
$(RUSTC) -L $(DEPS_DIR)/sax-rs/lib $(GEN_FILE) -o $(GLRSGEN)

gen-lib: gen
@mkdir -p $(LIB_DIR)
$(GLRSGEN) $(GEN_FLAGS) > $(LIB_FILE)

lib: gen-lib
$(RUSTC) $(LIB_FILE) -O --out-dir=$(LIB_DIR)
examples: example-static-basic example-static-triangle example-struct-triangle

clean:
rm -f $(LIB_FILE)
rm -rf $(LIB_DIR)
rm -rf $(BIN_DIR)
rm -rf $(TEST_DIR)
rm -rf $(DOC_DIR)
rm -rf $(EXAMPLES_DIR)
$(MAKE) clean -C $(DEPS_DIR)/glfw-rs
$(MAKE) clean -C $(DEPS_DIR)/sax-rs

.PHONY: \
all \
submodule-update \
lib \
check \
doc \
examples \
examples-deps\
examples-dir \
gen \
gen-deps \
gen-lib \
$(EXAMPLE_FILES) \
gen-macro \
gl-lib \
check \
doc \
examples-dir \
examples-deps\
example-static-basic \
example-static-triangle \
example-struct-triangle \
examples \
clean

1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ GL_API ?= gl
GL_PROFILE ?= core
GL_VERSION ?= 4.3
GL_EXTENSIONS ?=
GL_GENERATOR ?=
GL_FULL ?=
GL_XML ?= ./deps/khronos-api/$(GL_API).xml
~~~
Expand Down
File renamed without changes.
File renamed without changes.
186 changes: 186 additions & 0 deletions src/examples/struct_triangle.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,186 @@
// Copyright 2013 The gl-rs developers. For a full listing of the authors,
// refer to the AUTHORS file at the top-level directory of this distribution.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

#![feature(globs)]
#![feature(phase)]

#[phase(plugin)]
extern crate gl_generator;
extern crate glfw;
extern crate native;
extern crate libc;

use glfw::Context;
use std::mem;
use std::ptr;
use std::str;

use self::gl::Gl;
use self::gl::types::*;

#[allow(non_camel_case_types)]
#[allow(non_snake_case_functions)]
pub mod gl {
use super::libc;
use std::mem;
use self::types::*;
generate_gl_bindings!("gl", "gl", "core", "3.2", "struct")
}

// Vertex data
static VERTEX_DATA: [GLfloat, ..6] = [
0.0, 0.5,
0.5, -0.5,
-0.5, -0.5
];

// Shader sources
static VS_SRC: &'static str =
"#version 150\n\
in vec2 position;\n\
void main() {\n\
gl_Position = vec4(position, 0.0, 1.0);\n\
}";

static FS_SRC: &'static str =
"#version 150\n\
out vec4 out_color;\n\
void main() {\n\
out_color = vec4(1.0, 1.0, 1.0, 1.0);\n\
}";

#[start]
fn start(argc: int, argv: *const *const u8) -> int {
native::start(argc, argv, main)
}

fn compile_shader(gl: &Gl, src: &str, ty: GLenum) -> GLuint {
let shader = gl.CreateShader(ty);
unsafe {
// Attempt to compile the shader
src.with_c_str(|ptr| gl.ShaderSource(shader, 1, &ptr, ptr::null()));
gl.CompileShader(shader);

// Get the compile status
let mut status = gl::FALSE as GLint;
gl.GetShaderiv(shader, gl::COMPILE_STATUS, &mut status);

// Fail on error
if status != (gl::TRUE as GLint) {
let mut len = 0;
gl.GetShaderiv(shader, gl::INFO_LOG_LENGTH, &mut len);
let mut buf = Vec::from_elem(len as uint - 1, 0u8); // subtract 1 to skip the trailing null character
gl.GetShaderInfoLog(shader, len, ptr::mut_null(), buf.as_mut_ptr() as *mut GLchar);
fail!("{}", str::from_utf8(buf.as_slice()).expect("ShaderInfoLog not valid utf8"));
}
}
shader
}

fn link_program(gl: &Gl, vs: GLuint, fs: GLuint) -> GLuint {
let program = gl.CreateProgram();
gl.AttachShader(program, vs);
gl.AttachShader(program, fs);
gl.LinkProgram(program);
unsafe {
// Get the link status
let mut status = gl::FALSE as GLint;
gl.GetProgramiv(program, gl::LINK_STATUS, &mut status);

// Fail on error
if status != (gl::TRUE as GLint) {
let mut len: GLint = 0;
gl.GetProgramiv(program, gl::INFO_LOG_LENGTH, &mut len);
let mut buf = Vec::from_elem(len as uint - 1, 0u8); // subtract 1 to skip the trailing null character
gl.GetProgramInfoLog(program, len, ptr::mut_null(), buf.as_mut_ptr() as *mut GLchar);
fail!("{}", str::from_utf8(buf.as_slice()).expect("ProgramInfoLog not valid utf8"));
}
}
program
}

fn main() {
let glfw = glfw::init(glfw::FAIL_ON_ERRORS).unwrap();

// Choose a GL profile that is compatible with OS X 10.7+
glfw.window_hint(glfw::ContextVersion(3, 2));
glfw.window_hint(glfw::OpenglForwardCompat(true));
glfw.window_hint(glfw::OpenglProfile(glfw::OpenGlCoreProfile));

let (window, _) = glfw.create_window(800, 600, "OpenGL", glfw::Windowed)
.expect("Failed to create GLFW window.");

// It is essential to make the context current before calling `gl::load_with`.
window.make_current();

// Load the OpenGL function pointers
let gl = Gl::load_with(|s| glfw.get_proc_address(s));

// Create GLSL shaders
let vs = compile_shader(&gl, VS_SRC, gl::VERTEX_SHADER);
let fs = compile_shader(&gl, FS_SRC, gl::FRAGMENT_SHADER);
let program = link_program(&gl, vs, fs);

let mut vao = 0;
let mut vbo = 0;

unsafe {
// Create Vertex Array Object
gl.GenVertexArrays(1, &mut vao);
gl.BindVertexArray(vao);

// Create a Vertex Buffer Object and copy the vertex data to it
gl.GenBuffers(1, &mut vbo);
gl.BindBuffer(gl::ARRAY_BUFFER, vbo);
gl.BufferData(gl::ARRAY_BUFFER,
(VERTEX_DATA.len() * mem::size_of::<GLfloat>()) as GLsizeiptr,
mem::transmute(&VERTEX_DATA[0]),
gl::STATIC_DRAW);

// Use shader program
gl::UseProgram(program);
"out_color".with_c_str(|ptr| gl.BindFragDataLocation(program, 0, ptr));

// Specify the layout of the vertex data
let pos_attr = "position".with_c_str(|ptr| gl.GetAttribLocation(program, ptr));
gl.EnableVertexAttribArray(pos_attr as GLuint);
gl.VertexAttribPointer(pos_attr as GLuint, 2, gl::FLOAT,
gl::FALSE as GLboolean, 0, ptr::null());
}

while !window.should_close() {
// Poll events
glfw.poll_events();

// Clear the screen to black
gl.ClearColor(0.3, 0.3, 0.3, 1.0);
gl.Clear(gl::COLOR_BUFFER_BIT);

// Draw a triangle from the 3 vertices
gl.DrawArrays(gl::TRIANGLES, 0, 3);

// Swap buffers
window.swap_buffers();
}

// Cleanup
gl.DeleteProgram(program);
gl.DeleteShader(fs);
gl.DeleteShader(vs);
unsafe {
gl.DeleteBuffers(1, &vbo);
gl.DeleteVertexArrays(1, &vao);
}
}
5 changes: 4 additions & 1 deletion src/gl_generator/src/gl_generator.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
#![crate_name = "gl_generator"]
#![comment = "OpenGL function loader generator."]
#![license = "ASL2"]
#![crate_type = "dylib"]

#![feature(phase)]
#![feature(globs)]
Expand All @@ -39,9 +40,11 @@ use syntax::codemap::Span;

use registry::*;
use static_gen::StaticGenerator;
use struct_gen::StructGenerator;

mod common;
pub mod static_gen;
pub mod struct_gen;
pub mod registry;
pub mod ty;

Expand Down Expand Up @@ -125,7 +128,7 @@ fn macro_handler(ecx: &mut ExtCtxt, span: Span, token_tree: &[TokenTree]) -> Box
let mut buffer = ::std::io::MemWriter::new();
match generator.as_slice() {
"static" => StaticGenerator::write(&mut buffer, &reg, ns, false),
"struct" => unimplemented!(),
"struct" => StructGenerator::write(&mut buffer, &reg, ns, false),
generator => {
ecx.span_err(span, format!("unknown generator type: {}", generator).as_slice());
return DummyResult::any(span)
Expand Down
4 changes: 3 additions & 1 deletion src/gl_generator/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -35,10 +35,12 @@ use std::io::{File, Reader};

use registry::*;
use static_gen::StaticGenerator;
use struct_gen::StructGenerator;

mod common;
pub mod registry;
pub mod static_gen;
pub mod struct_gen;
pub mod ty;

fn main() {
Expand Down Expand Up @@ -96,7 +98,7 @@ fn main() {

match args.opt_str("generator").unwrap_or("static".to_string()).as_slice() {
"static" => StaticGenerator::write(&mut io::stdout(), &reg, ns, true),
"struct" => unimplemented!(),
"struct" => StructGenerator::write(&mut io::stdout(), &reg, ns, true),
generator => fail!("Unexpected generator type '{}'", generator)
};
}
Loading

0 comments on commit 052895c

Please sign in to comment.