فهرست منبع

Starting implementing the opengl backend

Vinicius Teshima 1 سال پیش
والد
کامیت
b9e5672499
11فایلهای تغییر یافته به همراه616 افزوده شده و 15 حذف شده
  1. 24 0
      Makefile
  2. 6 0
      shaders/font.frag
  3. 9 0
      shaders/font.vert
  4. 75 8
      src/app.h
  5. 271 0
      src/app_sdl.h
  6. 3 0
      src/buffer.h
  7. 0 1
      src/file.h
  8. 64 1
      src/main.c
  9. 151 0
      src/shader.h
  10. 8 0
      src/surface.h
  11. 5 5
      src/window.h

+ 24 - 0
Makefile

@@ -0,0 +1,24 @@
+PKGS=sdl2 glew
+CFLAGS=-std=c99 -m64 -Og -ggdb \
+-pedantic -Wall -Wextra -Wshadow \
+-Wcast-align -Wunused -Wconversion -Wmisleading-indentation \
+-Wduplicated-cond -Wduplicated-branches -Wlogical-op \
+-Wdouble-promotion -Wformat=2 -Wbad-function-cast \
+-Wmissing-declarations -Wmissing-parameter-type \
+-Wmissing-prototypes -Wnested-externs -Werror \
+$(shell pkg-config --cflags $(PKGS))
+
+LIBS=$(shell pkg-config --libs $(PKGS)) -lm -lc
+
+SRCS=$(wildcard src/*)
+
+.PHONY: run
+run: TAGS ged
+	./ged
+
+ged: $(SRCS)
+	$(CC) $(CFLAGS) -o ged src/main.c $(LIBS)
+
+
+TAGS: $(SRCS)
+	exuberant-ctags --kinds-all=* --totals=yes -e -R

+ 6 - 0
shaders/font.frag

@@ -0,0 +1,6 @@
+#version 330 core
+
+void main() {
+  vec2 uv = gl_FragCoord.xy / (vec2(800.0, 600.0) * 2);
+  gl_FragColor = vec4(uv.x, uv.y, 0.0, 1.0);
+}

+ 9 - 0
shaders/font.vert

@@ -0,0 +1,9 @@
+#version 330 core
+
+
+void main() {
+  float x = float(gl_VertexID & 1);
+  float y = float((gl_VertexID >> 1) & 1);
+
+  gl_Position = vec4(x - 0.5, y - 0.5, 0.0, 1.0);
+}

+ 75 - 8
src/app.h

@@ -1,11 +1,12 @@
 #ifndef APP_H
 #define APP_H
 
+#include <GL/glew.h>
+#include <SDL2/SDL.h>
+
 #include "da.h"
 #include "font.h"
 
-#include <SDL2/SDL.h>
-
 #include "vec2.h"
 #include "window.h"
 
@@ -14,6 +15,7 @@
 struct app {
 	struct window win;
 	SDL_Renderer *rdr;
+	SDL_GLContext glctx;
 	struct font font;
 	struct buffer buf;
 	bool running;
@@ -25,6 +27,7 @@ struct app {
 };
 
 struct app app_create(const char *win_title);
+void app_destroy(struct app app);
 
 void app_set_text_color(struct app app, uint32_t color);
 uint32_t app_get_text_color(struct app app);
@@ -41,6 +44,10 @@ void app_render_text(struct app app, const char *text, size_t text_size,
 
 struct vec2 app_calc_cur_pos(struct app app);
 
+void MessageCallback(GLenum source, GLenum type, GLuint id,
+		     GLenum severity, GLsizei length,
+		     const GLchar *msg, const void *up);
+
 #if defined(APP_IMP) || defined(IMP)
 
 #define UNHEX_COLOR(hex)			\
@@ -49,11 +56,15 @@ struct vec2 app_calc_cur_pos(struct app app);
 	(uint8_t) ((hex >> 8 ) & 0xFF),	\
 	(uint8_t) ((hex >> 0 ) & 0xFF)
 
+#include <GL/glew.h>
+
 #include "sc.h"
 
 struct app
 app_create(const char *win_title)
 {
+	SCE(SDL_Init(SDL_INIT_VIDEO));
+
 	struct app app = {
 		.win = window_create(win_title),
 		.rdr = NULL,
@@ -65,18 +76,61 @@ app_create(const char *win_title)
 		.target_fps = 120,
 	};
 
-	app.rdr = SDL_CreateRenderer(app.win.ptr, -1, SDL_RENDERER_ACCELERATED);
-	if ( app.rdr == NULL ) {
-		printf("Using software acceleration: %s\n", SDL_GetError());
-		app.rdr = SDL_CreateRenderer(app.win.ptr, -1,
-					     SDL_RENDERER_SOFTWARE);
+	{
+		SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, 3);
+		SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, 3);
+		SDL_GL_SetAttribute(SDL_GL_CONTEXT_PROFILE_MASK,
+				    SDL_GL_CONTEXT_PROFILE_CORE);
+
+		int32_t major = 0;
+		int32_t minor = 0;
+
+		SDL_GL_GetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, &major);
+		SDL_GL_GetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, &minor);
+		printf("GL Version: %d.%d\n", major, minor);
+	}
+
+	app.glctx = SDL_GL_CreateContext(app.win.ptr);
+	SCP(app.glctx);
+
+	if ( GLEW_OK != glewInit() ) {
+		fprintf(stderr, "Could Not Initilize GLEW!\n");
+		exit(EXIT_FAILURE);
+	}
+
+	glEnable(GL_BLEND);
+	glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
+
+	if ( GLEW_ARB_debug_output ) {
+		glEnable(GL_DEBUG_OUTPUT);
+		glDebugMessageCallback(MessageCallback, 0);
+	} else {
+		fprintf(stderr,
+			"WARNING! GLEW_ARB_debug_output is not availible");
 	}
-	SCP(app.rdr);
+
+	/* app.rdr = SDL_CreateRenderer(app.win.ptr, -1, SDL_RENDERER_ACCELERATED); */
+	/* if ( app.rdr == NULL ) { */
+	/* 	printf("Using software acceleration: %s\n", SDL_GetError()); */
+	/* 	app.rdr = SDL_CreateRenderer(app.win.ptr, -1, */
+	/* 				     SDL_RENDERER_SOFTWARE); */
+	/* } */
+	/* SCP(app.rdr); */
 
 
 	return app;
 }
 
+void
+app_destroy(struct app app)
+{
+	SDL_DestroyWindow(app.win.ptr);
+	SDL_GL_DeleteContext(app.glctx);
+	DA_DESTROY(app.buf.data);
+	SDL_Quit();
+}
+
+
 void
 app_render_char(struct app app, const char c, struct vec2 pos, double scale)
 {
@@ -264,6 +318,19 @@ app_calc_cur_pos(struct app app)
 }
 
 
+void
+MessageCallback(GLenum source, GLenum type, GLuint id,
+		GLenum severity, GLsizei length,
+		const GLchar *msg, const void *up)
+{
+	(void) source; (void) id; (void) length; (void) up;
+
+	fprintf(stderr,
+		"GL CALLBACK: %s type = 0x%x, severity = 0x%x, message = %s\n",
+		(type == GL_DEBUG_TYPE_ERROR ? "*** GL ERROR ***" : ""),
+		type, severity, msg);
+}
+
 #endif /* defined(APP_IMP) || defined(IMP) */
 
 #endif

+ 271 - 0
src/app_sdl.h

@@ -0,0 +1,271 @@
+#ifndef APP_H
+#define APP_H
+
+#include "da.h"
+#include "font.h"
+
+#include <SDL2/SDL.h>
+
+#include "vec2.h"
+#include "window.h"
+
+#include "buffer.h"
+
+struct app {
+	struct window win;
+	SDL_Renderer *rdr;
+	struct font font;
+	struct buffer buf;
+	bool running;
+	uint64_t target_fps;
+	struct {
+		uint8_t tab_size;
+	} cfg;
+	bool show_fps;
+};
+
+struct app app_create(const char *win_title);
+
+void app_set_text_color(struct app app, uint32_t color);
+uint32_t app_get_text_color(struct app app);
+
+void app_render_cursor_in_pos(struct app app, struct vec2 pos, uint32_t color);
+void app_render_cursor(struct app app, uint32_t color);
+void app_render_char(struct app app, const char c, struct vec2 pos,
+		     double scale);
+
+void app_render_buffer(struct app app, struct vec2 pos,
+		       uint32_t color, double scale);
+void app_render_text(struct app app, const char *text, size_t text_size,
+		     struct vec2 pos, uint32_t color, double scale);
+
+struct vec2 app_calc_cur_pos(struct app app);
+
+#if defined(APP_IMP) || defined(IMP)
+
+#define UNHEX_COLOR(hex)			\
+	(uint8_t) ((hex >> 24) & 0xFF),	\
+	(uint8_t) ((hex >> 16) & 0xFF),	\
+	(uint8_t) ((hex >> 8 ) & 0xFF),	\
+	(uint8_t) ((hex >> 0 ) & 0xFF)
+
+#include "sc.h"
+
+struct app
+app_create(const char *win_title)
+{
+	SCE(SDL_Init(SDL_INIT_VIDEO));
+
+	struct app app = {
+		.win = window_create(win_title),
+		.rdr = NULL,
+		.running = true,
+		.buf = buffer_create(),
+		.cfg = {
+			.tab_size = 8
+		},
+		.target_fps = 120,
+	};
+
+	app.rdr = SDL_CreateRenderer(app.win.ptr, -1, SDL_RENDERER_ACCELERATED);
+	if ( app.rdr == NULL ) {
+		printf("Using software acceleration: %s\n", SDL_GetError());
+		app.rdr = SDL_CreateRenderer(app.win.ptr, -1,
+					     SDL_RENDERER_SOFTWARE);
+	}
+	SCP(app.rdr);
+
+
+	return app;
+}
+
+void
+app_render_char(struct app app, const char c, struct vec2 pos, double scale)
+{
+	SDL_Rect dst = {
+		.x = (int32_t) pos.x,
+		.y = (int32_t) pos.y,
+		.w = (int32_t)(app.font.ch_w * scale),
+		.h = (int32_t)(app.font.ch_h * scale)
+	};
+
+	SCE(SDL_RenderCopy(app.rdr, app.font.tex,
+			   app.font.glyphs + (c - 32),
+			   &dst));
+}
+
+void
+app_set_text_color(struct app app, uint32_t color) {
+	uint8_t r = (uint8_t) ((color >> 24) & 0xFF);
+	uint8_t g = (uint8_t) ((color >> 16) & 0xFF);
+	uint8_t b = (uint8_t) ((color >> 8 ) & 0xFF);
+	uint8_t a = (uint8_t) ((color >> 0 ) & 0xFF);
+
+	SCE(SDL_SetTextureColorMod(app.font.tex, r, g, b));
+	SCE(SDL_SetTextureAlphaMod(app.font.tex, a));
+}
+
+uint32_t
+app_get_text_color(struct app app) {
+	uint8_t r = 0;
+	uint8_t g = 0;
+	uint8_t b = 0;
+	uint8_t a = 0;
+
+	SCE(SDL_GetTextureColorMod(app.font.tex, &r, &g, &b));
+	SCE(SDL_GetTextureAlphaMod(app.font.tex, &a));
+
+	return (r << 24) | (g << 16) | (b << 8) | (a << 0);
+}
+
+
+#define BRANCHLESS_IF(cond, when_true, when_false) \
+	(((cond)) * (when_true) + (!(cond)) * (when_false))
+
+void
+app_render_buffer(struct app app, struct vec2 pos,
+		  uint32_t color, double scale)
+{
+	app_set_text_color(app, color);
+
+	struct buffer buf = app.buf;
+	DA_DEF_STRUCT_ITEM(char, da);
+	DA_ASSIGN(da, buf.data);
+
+	struct vec2 pen = pos;
+	size_t i = buf.render_start;
+	char c;
+	for ( ; i < da.size; ++i ) {
+		c = da.items[i];
+		/* bool cond = (pen.x > app.win.w); */
+		/* pen.x = BRANCHLESS_IF(cond, pos.x, pen.x); */
+		/* pen.y += BRANCHLESS_IF(cond, */
+		/* 		       (double) (app.font.ch_h * scale), 0); */
+		switch ( c ) {
+		case '\n': {
+			if ( i == app.buf.cur ) {
+				app_render_cursor_in_pos(app, pen, 0xFF00FFFF);
+			}
+			pen.x = pos.x;
+			pen.y += (double) (app.font.ch_h * scale);
+			continue;
+		} break;
+		case '\t': {
+			if ( i == app.buf.cur ) {
+				app_render_cursor_in_pos(app, pen, 0xFF00FFFF);
+			}
+			pen.x += (double) ((app.font.ch_w * scale)
+					   * app.cfg.tab_size);
+			continue;
+		} break;
+		}
+		app_render_char(app, c, pen, scale);
+		if ( i == app.buf.cur ) {
+			app_render_cursor_in_pos(app, pen, 0xFF00FFFF);
+		}
+		pen.x += (double) (app.font.ch_w * scale);
+	}
+	if ( i == app.buf.cur ) {
+		app_render_cursor_in_pos(app, pen, 0xFF00FFFF);
+	}
+}
+
+void
+app_render_text(struct app app, const char *text, size_t text_size,
+		struct vec2 pos, uint32_t color, double scale)
+{
+	app_set_text_color(app, color);
+
+	struct vec2 pen = pos;
+	size_t i = 0;
+	char c;
+	for ( ; i < text_size; ++i ) {
+		c = text[i];
+		switch ( c ) {
+		case '\n': {
+			pen.x = pos.x;
+			pen.y += (double) (app.font.ch_h * scale);
+			continue;
+		} break;
+		case '\t': {
+			pen.x += (double) ((app.font.ch_w * scale)
+					   * app.cfg.tab_size);
+			continue;
+		} break;
+		}
+		app_render_char(app, c, pen, scale);
+		pen.x += (double) (app.font.ch_w * scale);
+	}
+}
+
+void
+app_render_cursor_in_pos(struct app app, struct vec2 pos, uint32_t color)
+{
+	SDL_Rect rect = {
+		.x = (int32_t) pos.x,
+		.y = (int32_t) pos.y,
+		.w = (int32_t) (app.font.ch_w * app.font.scale),
+		.h = (int32_t) (app.font.ch_h * app.font.scale)
+	};
+
+	SCE(SDL_SetRenderDrawColor(app.rdr, UNHEX_COLOR(color)));
+	SCE(SDL_RenderFillRect(app.rdr, &rect));
+
+	if ( app.buf.cur < app.buf.data.size ) {
+		char c = app.buf.data.items[app.buf.cur];
+		if ( c == '\n' ) return ;
+
+		uint32_t old_color = app_get_text_color(app);
+		app_set_text_color(app, ((~color) | 0xFF));
+		app_render_char(app, c, pos, app.font.scale);
+		app_set_text_color(app, old_color);
+	}
+}
+
+void
+app_render_cursor(struct app app, uint32_t color)
+{
+	struct vec2 pos = {
+		.x = ((double)(app.buf.cur) * (app.font.ch_w * app.font.scale)),
+		.y = ((double)(app.buf.cur) * (app.font.ch_h * app.font.scale))
+	};
+
+	app_render_cursor_in_pos(app, pos, color);
+}
+
+struct vec2
+app_calc_cur_pos(struct app app)
+{
+	size_t col = 0;
+	size_t row = buffer_calc_cur_row(app.buf);
+	enum buffer_err err;
+	/* RET_UNWRAP2(col, row, */
+	/* 	    struct ret_size_t_size_t, */
+	/* 	    buffer_calc_cur_pos(app.buf)); */
+	size_t start_line;
+	RET_UNWRAP2(start_line, err, struct ret_size_t_err,
+		    buffer_index_bw_char(app.buf, app.buf.cur, '\n'));
+	col = (app.buf.cur - start_line) - 1;
+	if ( err == BUFFER_ERR_NOT_FOUND ) {
+		col = app.buf.cur;
+	}
+
+	size_t tabs_n = 0;
+	RET_UNWRAP2(tabs_n, err,
+		    struct ret_size_t_err,
+		    buffer_count_char_between(app.buf, '\t',
+					      start_line, app.buf.cur));
+	col += ( tabs_n > 0 ) * ((tabs_n * app.cfg.tab_size) - tabs_n);
+
+	double row_px = (((double)row)
+			  * (app.font.ch_h * app.font.scale));
+	double col_px = (((double) col) *
+			 (app.font.ch_w * app.font.scale));
+
+	return vec2(col_px, row_px);
+}
+
+
+#endif /* defined(APP_IMP) || defined(IMP) */
+
+#endif

+ 3 - 0
src/buffer.h

@@ -84,6 +84,9 @@ struct ret_size_t_size_t buffer_calc_cur_pos(struct buffer buf);
 
 #if defined(BUFFER_IMP) || defined(IMP)
 
+#include <stdlib.h>
+#include <stdbool.h>
+#include <limits.h>
 #include <ctype.h>
 
 #include "vec2.h"

+ 0 - 1
src/file.h

@@ -52,7 +52,6 @@ file_read_all(const char *filepath)
 		goto err_close;
 	}
 	lseek(fd, 0, SEEK_SET);
-	printf("file->size = %ld\n", file_size);
 
 	if ( file_size == 0 ) {
 		err = FILE_ERR_EMPTY;

+ 64 - 1
src/main.c

@@ -5,6 +5,10 @@
 #include <time.h>
 
 #include <SDL2/SDL.h>
+#define GLEW_STATIC
+#include <GL/glew.h>
+#define GL_GLEXT_PROTOTYPES
+#include <SDL2/SDL_opengl.h>
 
 #pragma GCC diagnostic push
 #pragma GCC diagnostic ignored "-Wall"
@@ -25,12 +29,71 @@
 #include "file.h"
 #include "keybind.h"
 #include "config.h"
+#include "shader.h"
 
 struct app handle_events(struct app app);
 
-
 int32_t
 main(int32_t argc, char **argv)
+{
+	(void) argc; (void) argv;
+
+	struct app app = app_create("ged");
+	/* const char *font_path = "./charmap-oldschool_white.png"; */
+	/* app.font = font_create(app.rdr, font_path, 7, 18); */
+	/* app.font.scale = 2.0; */
+
+	enum shader_err err;
+
+	uint32_t vert_shader;
+	uint32_t frag_shader;
+
+	RET_UNWRAP2(vert_shader, err, struct ret_uint32_t_err,
+		    shader_compile_file("./shaders/font.vert",
+					GL_VERTEX_SHADER));
+	if ( err != SHADER_ERR_OK ) {
+		fprintf(stderr, "Failed to compile shader font.vert\n");
+		exit(EXIT_FAILURE);
+	}
+
+	RET_UNWRAP2(frag_shader, err, struct ret_uint32_t_err,
+		    shader_compile_file("./shaders/font.frag",
+					GL_FRAGMENT_SHADER));
+	if ( err != SHADER_ERR_OK ) {
+		fprintf(stderr, "Failed to compile shader font.frag\n");
+		exit(EXIT_FAILURE);
+	}
+
+	uint32_t prog;
+	RET_UNWRAP2(prog, err, struct ret_uint32_t_err,
+		    program_link(vert_shader, frag_shader));
+	if ( err != SHADER_ERR_OK ) {
+		fprintf(stderr, "Failed to link program\n");
+		exit(EXIT_FAILURE);
+	}
+
+	glUseProgram(prog);
+	uint32_t vao = 0;
+	glGenVertexArrays(1, &vao);
+	glBindVertexArray(vao);
+
+	while ( app.running ) {
+		app = handle_events(app);
+
+		glClearColor(0.0, 0.0, 0.0, 1.0);
+		glClear(GL_COLOR_BUFFER_BIT);
+		glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
+
+		SDL_GL_SwapWindow(app.win.ptr);
+	}
+
+	app_destroy(app);
+	exit(EXIT_SUCCESS);
+}
+
+int32_t main2(int32_t argc, char **argv);
+int32_t
+main2(int32_t argc, char **argv)
 {
 	srand((uint32_t) time(NULL));
 	if ( argc != 2 ) {

+ 151 - 0
src/shader.h

@@ -0,0 +1,151 @@
+#ifndef SHADER_H
+#define SHADER_H
+
+#include <GL/glew.h>
+
+enum shader_err {
+	SHADER_ERR_OK,
+	SHADER_ERR_FAIL_CREATE,
+	SHADER_ERR_FAIL_CREATE_PROG,
+	SHADER_ERR_FAIL_COMPILE,
+	SHADER_ERR_FAIL_READ_FILE,
+	SHADER_ERR_FAIL_LINK_PROG
+};
+
+struct ret_uint32_t_err {
+	uint32_t f1;
+	enum shader_err f2;
+};
+
+struct ret_uint32_t_err shader_compile_source(const char *src, GLenum type);
+struct ret_uint32_t_err shader_compile_file(const char *filepath, GLenum type);
+
+struct ret_uint32_t_err program_link(uint32_t vert_shader,
+				     uint32_t frag_shader);
+
+const char *shader_type_to_cstr(GLenum type);
+
+#if defined(SHADER_IMP) || defined(IMP)
+
+#include <stdio.h>
+
+#include "file.h"
+
+struct ret_uint32_t_err
+shader_compile_source(const char *src, GLenum type)
+{
+	enum shader_err err;
+	uint32_t shdr = glCreateShader(type);
+	if ( shdr == 0 ) {
+		err = SHADER_ERR_FAIL_CREATE;
+		goto err;
+	}
+	glShaderSource(shdr, 1, &src, NULL);
+	glCompileShader(shdr);
+
+	int32_t comp_status = GL_FALSE;
+	glGetShaderiv(shdr, GL_COMPILE_STATUS, &comp_status);
+
+	if ( comp_status == GL_FALSE ) {
+		err = SHADER_ERR_FAIL_COMPILE;
+		int32_t log_length = 1024;
+		glGetShaderiv(shdr, GL_INFO_LOG_LENGTH, &log_length);
+		log_length += 10;
+		char *log = calloc(sizeof(char), (size_t)log_length);
+		glGetShaderInfoLog(shdr, log_length, NULL, log);
+		fprintf(stderr, "FAILED COMPILE %s : %s\n",
+			shader_type_to_cstr(type), log);
+		goto err;
+	}
+
+	return (struct ret_uint32_t_err) {
+		.f1 = shdr,
+		.f2 = SHADER_ERR_OK
+	};
+
+err: ;
+	return (struct ret_uint32_t_err) {
+		.f1 = 0,
+		.f2 = err
+	};
+}
+
+struct ret_uint32_t_err
+shader_compile_file(const char *filepath, GLenum type)
+{
+	char *src;
+	size_t size;
+	enum file_err err;
+
+	RET_UNWRAP3(src, size, err,
+		    struct ret_void_p_err, file_read_all(filepath));
+	(void) size;
+	if ( err != FILE_ERR_OK ) {
+		return (struct ret_uint32_t_err) {
+			.f1 = 0,
+			.f2 = SHADER_ERR_FAIL_READ_FILE,
+		};
+	}
+
+	struct ret_uint32_t_err ret = shader_compile_source(src, type);
+	free(src);
+	return ret;
+}
+
+struct ret_uint32_t_err
+program_link(uint32_t vert_shader, uint32_t frag_shader)
+{
+	enum shader_err err;
+	uint32_t prog = glCreateProgram();
+	if ( prog == 0 ) {
+		err = SHADER_ERR_FAIL_CREATE_PROG;
+		goto err;
+	}
+
+	glAttachShader(prog, vert_shader);
+	glAttachShader(prog, frag_shader);
+
+	glLinkProgram(prog);
+
+	int32_t link_status = GL_FALSE;
+	glGetProgramiv(prog, GL_LINK_STATUS, &link_status);
+
+	if ( link_status != GL_TRUE ) {
+		err = SHADER_ERR_FAIL_LINK_PROG;
+		int32_t log_length = 1024;
+		glGetProgramiv(prog, GL_INFO_LOG_LENGTH, &log_length);
+		log_length += 10;
+		char *log = calloc(sizeof(char), (size_t)log_length);
+		glGetProgramInfoLog(prog, log_length, NULL, log);
+		fprintf(stderr, "FAILED LINK PROG: %s\n", log);
+		goto err;
+	}
+
+	glDeleteShader(vert_shader);
+	glDeleteShader(frag_shader);
+
+	return (struct ret_uint32_t_err) {
+		.f1 = prog,
+		.f2 = SHADER_ERR_OK,
+	};
+
+err: ;
+	return (struct ret_uint32_t_err) {
+		.f1 = 0,
+		.f2 = err,
+	};
+}
+
+const char *
+shader_type_to_cstr(GLenum type)
+{
+	switch ( type ) {
+	case GL_VERTEX_SHADER: return "GL_VERTEX_SHADER"; break;
+	case GL_FRAGMENT_SHADER: return "GL_FRAGMENT_SHADER"; break;
+	}
+	return "(Unknown Shader)";
+}
+
+#endif /* defined(SHADER_IMP) || defined(IMP) */
+
+#endif

+ 8 - 0
src/surface.h

@@ -5,6 +5,14 @@ SDL_Surface *surface_from_file(const char *filepath);
 
 #if defined(SURFACE_IMP) || defined(IMP)
 
+#ifdef STB_IMAGE_IMPLEMENTATION
+  #undef STB_IMAGE_IMPLEMENTATION
+  #include "stb_image.h"
+  #define STB_IMAGE_IMPLEMENTATION
+#else
+  #include "stb_image.h"
+#endif
+
 #include "sc.h"
 
 SDL_Surface *

+ 5 - 5
src/window.h

@@ -29,11 +29,11 @@ struct window
 window_create(const char *win_title)
 {
 	struct window win = {
-		.ptr = SDL_CreateWindow(win_title,
-					SDL_WINDOWPOS_UNDEFINED,
-					SDL_WINDOWPOS_UNDEFINED,
-					600, 800,
-					SDL_WINDOW_RESIZABLE),
+		.ptr = SDL_CreateWindow(
+			win_title,
+			SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED,
+			600, 800,
+			SDL_WINDOW_RESIZABLE | SDL_WINDOW_OPENGL),
 	};
 	SCP(win.ptr);