opengl
This commit is contained in:
parent
fc03951086
commit
e4428be844
8
Makefile
8
Makefile
@ -1,12 +1,12 @@
|
||||
CC=$(shell sh -c "which gcc-7 || which gcc")
|
||||
CFLAGS=-O3 -Wall -fPIC -fmessage-length=0 -D_GNU_SOURCE=1 -g3 -ggdb -Iinclude -isystemftgl -isystem/usr/local/include/freetype2 -isystem/usr/include/freetype2
|
||||
LDFLAGS=-shared
|
||||
LDLIBS=-lm -lX11 -lXext -lrt -lpthread -lXfixes -lGL -lfreetype
|
||||
LDLIBS=-lm -lX11 -lXext -lrt -lpthread -lXfixes -lGL -lfreetype -lGLEW
|
||||
SRC_DIR=src
|
||||
BIN32_DIR=bin32
|
||||
BIN64_DIR=bin64
|
||||
SOURCES=$(shell find $(SRC_DIR) -name "*.c" -print)
|
||||
SOURCES=$(shell find "ftgl" -name "*.c" -print)
|
||||
SOURCES+=$(shell find "ftgl" -name "*.c" -print)
|
||||
OBJECTS=$(SOURCES:.c=.o)
|
||||
|
||||
TARGET32=$(BIN32_DIR)/liboverlay.so.0
|
||||
@ -30,8 +30,8 @@ all:
|
||||
ifndef ARCH
|
||||
$(MAKE) clean
|
||||
$(MAKE) $(TARGET64) -e ARCH=64
|
||||
$(MAKE) clean
|
||||
$(MAKE) $(TARGET32) -e ARCH=32
|
||||
#$(MAKE) clean
|
||||
#$(MAKE) $(TARGET32) -e ARCH=32
|
||||
endif
|
||||
|
||||
install:
|
||||
|
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
BIN
ftgl/makefont.o
BIN
ftgl/makefont.o
Binary file not shown.
BIN
ftgl/mat4.o
Normal file
BIN
ftgl/mat4.o
Normal file
Binary file not shown.
BIN
ftgl/platform.o
BIN
ftgl/platform.o
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
BIN
ftgl/vector.o
BIN
ftgl/vector.o
Binary file not shown.
Binary file not shown.
Binary file not shown.
@ -10,7 +10,6 @@
|
||||
#include <GL/glew.h>
|
||||
#include <GL/glx.h>
|
||||
|
||||
struct xoverlay_library;
|
||||
struct xoverlay_glx_state
|
||||
{
|
||||
int version_major;
|
||||
@ -18,6 +17,8 @@ struct xoverlay_glx_state
|
||||
GLXContext context;
|
||||
};
|
||||
|
||||
int xoverlay_glx_init(struct xoverlay_library *library);
|
||||
int xoverlay_glx_create_window(struct xoverlay_library *library);
|
||||
int xoverlay_glx_destroy(struct xoverlay_library *library);
|
||||
struct xoverlay_glx_state glx_state;
|
||||
|
||||
int xoverlay_glx_init();
|
||||
int xoverlay_glx_create_window();
|
||||
int xoverlay_glx_destroy();
|
||||
|
@ -51,6 +51,7 @@ struct draw_instruction_stream_t
|
||||
size_t write_ptr;
|
||||
size_t read_ptr;
|
||||
size_t last_draw_instruction_offset;
|
||||
GLuint next_index;
|
||||
};
|
||||
|
||||
struct draw_instruction_stream_t dstream;
|
||||
@ -79,6 +80,9 @@ dis_push_instruction(struct draw_instruction_t instr);
|
||||
size_t
|
||||
dis_fetch_data(size_t bytes, void *data);
|
||||
|
||||
void*
|
||||
dis_read_data(size_t bytes);
|
||||
|
||||
void
|
||||
dis_switch_program(int program);
|
||||
|
||||
@ -100,32 +104,15 @@ dis_finish();
|
||||
struct draw_instruction_t*
|
||||
dis_fetch_instruction();
|
||||
|
||||
struct draw_cmd
|
||||
{
|
||||
vector_t *vertices;
|
||||
vector_t *indices;
|
||||
|
||||
int program;
|
||||
struct program_data_t data;
|
||||
};
|
||||
|
||||
struct draw_cmd*
|
||||
draw_cmd_new(int program);
|
||||
|
||||
void
|
||||
draw_cmd_delete(struct draw_cmd *cmd);
|
||||
|
||||
struct draw_state
|
||||
{
|
||||
mat4 model, view, projection;
|
||||
|
||||
int program;
|
||||
int dirty;
|
||||
|
||||
GLuint texture;
|
||||
GLuint shader;
|
||||
|
||||
struct vector_t *commands;
|
||||
struct size_t current_command;
|
||||
};
|
||||
|
||||
struct draw_state ds;
|
||||
@ -137,27 +124,41 @@ void
|
||||
ds_destroy();
|
||||
|
||||
void
|
||||
ds_alloc_next_command(int program);
|
||||
ds_mark_dirty();
|
||||
|
||||
void
|
||||
ds_next_frame();
|
||||
ds_prepare_program(int program);
|
||||
|
||||
void
|
||||
ds_render();
|
||||
ds_render_if_needed();
|
||||
|
||||
void
|
||||
ds_prepare_command(int program);
|
||||
ds_pre_render();
|
||||
|
||||
void
|
||||
ds_post_render();
|
||||
|
||||
void
|
||||
ds_render_next_frame();
|
||||
|
||||
/* To be called from programs */
|
||||
|
||||
void
|
||||
ds_bind_texture(GLuint texture);
|
||||
|
||||
void
|
||||
ds_use_shader(GLuint shader);
|
||||
|
||||
/* Primitive Internal Drawing API */
|
||||
|
||||
void
|
||||
draw_line(vec2 xy, vec2 delta, vec4 color);
|
||||
draw_line(vec2 xy, vec2 delta, vec4 color, float thickness);
|
||||
|
||||
void
|
||||
draw_rect(vec2 xy, vec2 hw, vec4 color);
|
||||
|
||||
void
|
||||
draw_rect_outline(vec2 xy, vec2 hw, vec4 color);
|
||||
draw_rect_outline(vec2 xy, vec2 hw, vec4 color, float thickness);
|
||||
|
||||
void
|
||||
draw_rect_textured(vec2 xy, vec2 hw, vec4 color, int texture, vec2 uv, vec2 st);
|
||||
|
@ -10,8 +10,6 @@
|
||||
#include <X11/Xlib.h>
|
||||
#include <X11/XKBlib.h>
|
||||
|
||||
#include "drawglx.h"
|
||||
|
||||
typedef void(*xoverlay_callback_keypress)(unsigned int keycode, int action);
|
||||
typedef void(*xoverlay_callback_click)(unsigned int buttoncode, int action);
|
||||
typedef void(*xoverlay_callback_scroll)(int value);
|
||||
@ -55,33 +53,60 @@ struct xoverlay_library
|
||||
char keymap[32];
|
||||
} keyboard;*/
|
||||
|
||||
struct xoverlay_glx_state glx;
|
||||
|
||||
char init;
|
||||
char drawing;
|
||||
};
|
||||
|
||||
int xoverlay_init(struct xoverlay_library *library);
|
||||
void xoverlay_destroy(struct xoverlay_library *library);
|
||||
struct xoverlay_library xoverlay_library;
|
||||
|
||||
void xoverlay_install_keyboard_callback(struct xoverlay_library *library, xoverlay_callback_keypress callback);
|
||||
void xoverlay_install_click_callback(struct xoverlay_library *library, xoverlay_callback_click callback);
|
||||
void xoverlay_install_scroll_callback(struct xoverlay_library *library, xoverlay_callback_scroll callback);
|
||||
void xoverlay_install_mouse_callback(struct xoverlay_library *library, xoverlay_callback_mousemove callback);
|
||||
/* void xoverlay_install_draw_callback(struct xoverlay_library *library, xoverlay_callback_draw callback); */
|
||||
typedef struct xoverlay_vec4_t
|
||||
{
|
||||
union
|
||||
{
|
||||
float data[4];
|
||||
struct
|
||||
{
|
||||
float r;
|
||||
float g;
|
||||
float b;
|
||||
float a;
|
||||
};
|
||||
struct
|
||||
{
|
||||
float x;
|
||||
float y;
|
||||
float z;
|
||||
float w;
|
||||
};
|
||||
};
|
||||
} xoverlay_vec4_t, xoverlay_rgba_t;
|
||||
|
||||
int xoverlay_is_button_down(struct xoverlay_library *library, KeyCode code);
|
||||
typedef struct xoverlay_vec2_t
|
||||
{
|
||||
float x;
|
||||
float y;
|
||||
} xoverlay_vec2_t;
|
||||
|
||||
unsigned xoverlay_rgb(int r, int g, int b);
|
||||
unsigned xoverlay_rgba(int r, int g, int b, int a);
|
||||
int xoverlay_init();
|
||||
void xoverlay_destroy();
|
||||
|
||||
void xoverlay_clear_rectangle(struct xoverlay_library *library, int x, int y, int w, int h);
|
||||
void xoverlay_clear_screen(struct xoverlay_library *library);
|
||||
void xoverlay_install_keyboard_callback(xoverlay_callback_keypress callback);
|
||||
void xoverlay_install_click_callback(xoverlay_callback_click callback);
|
||||
void xoverlay_install_scroll_callback(xoverlay_callback_scroll callback);
|
||||
void xoverlay_install_mouse_callback(xoverlay_callback_mousemove callback);
|
||||
|
||||
void xoverlay_draw_string(struct xoverlay_library *library, const char *string, int x, int y, unsigned fg, unsigned bg);
|
||||
void xoverlay_draw_line(struct xoverlay_library *library, int x, int y, int w, int h, unsigned fg);
|
||||
void xoverlay_draw_rectangle(struct xoverlay_library *library, int x, int y, int w, int h, unsigned fg);
|
||||
xoverlay_rgba_t xoverlay_rgba(int r, int g, int b, int a);
|
||||
|
||||
void xoverlay_poll_events(struct xoverlay_library *library);
|
||||
void xoverlay_draw_begin(struct xoverlay_library *library);
|
||||
void xoverlay_draw_end(struct xoverlay_library *library);
|
||||
void
|
||||
xoverlay_draw_line(xoverlay_vec2_t xy, xoverlay_vec2_t delta, xoverlay_rgba_t color, float thickness);
|
||||
|
||||
void
|
||||
xoverlay_draw_rect(xoverlay_vec2_t xy, xoverlay_vec2_t hw, xoverlay_rgba_t color);
|
||||
|
||||
void
|
||||
xoverlay_draw_rect_outline(xoverlay_vec2_t xy, xoverlay_vec2_t hw, xoverlay_rgba_t color, float thickness);
|
||||
|
||||
|
||||
void xoverlay_poll_events();
|
||||
void xoverlay_draw_begin();
|
||||
void xoverlay_draw_end();
|
||||
|
@ -8,6 +8,7 @@
|
||||
#pragma once
|
||||
|
||||
#include "freetype-gl.h"
|
||||
#include "vertex-buffer.h"
|
||||
|
||||
struct draw_cmd;
|
||||
|
||||
@ -16,22 +17,19 @@ struct draw_cmd;
|
||||
#define PROGRAM_RENDER(name) program_##name##_render
|
||||
#define PROGRAM_UNLOAD(name) program_##name##_unload
|
||||
#define PROGRAM_DESTROY(name) program_##name##_destroy
|
||||
#define PROGRAM_CHECK(name) program_##name##_check
|
||||
|
||||
#define DECL_PROGRAM_INIT(name) void program_##name##_init()
|
||||
#define DECL_PROGRAM_LOAD(name) void program_##name##_load()
|
||||
#define DECL_PROGRAM_RENDER(name) void program_##name##_render(struct draw_cmd *cmd)
|
||||
#define DECL_PROGRAM_RENDER(name) void program_##name##_render()
|
||||
#define DECL_PROGRAM_UNLOAD(name) void program_##name##_unload()
|
||||
#define DECL_PROGRAM_DESTROY(name) void program_##name##_destroy()
|
||||
#define DECL_PROGRAM_CHECK(name) int program_##name##_check(struct draw_cmd *cmd, void *data)
|
||||
|
||||
#define DECL_PROGRAM(name) \
|
||||
DECL_PROGRAM_INIT(name); \
|
||||
DECL_PROGRAM_LOAD(name); \
|
||||
DECL_PROGRAM_RENDER(name); \
|
||||
DECL_PROGRAM_UNLOAD(name); \
|
||||
DECL_PROGRAM_DESTROY(name); \
|
||||
DECL_PROGRAM_CHECK(name)
|
||||
DECL_PROGRAM_DESTROY(name)
|
||||
|
||||
enum
|
||||
{
|
||||
@ -41,47 +39,32 @@ enum
|
||||
PROGRAM_COUNT
|
||||
};
|
||||
|
||||
typedef void(*program_callback_fn)(struct draw_cmd *);
|
||||
typedef void(*program_callback_empty_fn)();
|
||||
typedef int(*program_callback_check_command_fn)(struct draw_cmd *cmd, void *data);
|
||||
|
||||
struct program_t
|
||||
{
|
||||
vertex_buffer_t *vertex;
|
||||
size_t vertex_size;
|
||||
GLuint shader;
|
||||
|
||||
program_callback_empty_fn init;
|
||||
program_callback_empty_fn load;
|
||||
program_callback_fn render;
|
||||
program_callback_empty_fn render;
|
||||
program_callback_empty_fn unload;
|
||||
program_callback_empty_fn destroy;
|
||||
program_callback_check_command_fn check;
|
||||
};
|
||||
|
||||
void
|
||||
program_init_inplace(struct program_t *program, const char *vertex_format, const char *shader_frag, const char *shader_vert, program_callback_empty_fn init, program_callback_empty_fn load, program_callback_fn render, program_callback_empty_fn unload, program_callback_empty_fn destroy, program_callback_check_command_fn check);
|
||||
program_init_inplace(struct program_t *program, const char *vertex_format, const char *shader_frag, const char *shader_vert, program_callback_empty_fn init, program_callback_empty_fn load, program_callback_empty_fn render, program_callback_empty_fn unload, program_callback_empty_fn destroy);
|
||||
|
||||
void
|
||||
program_init_everything();
|
||||
|
||||
struct program_t programs[PROGRAM_COUNT];
|
||||
|
||||
struct program_data_t
|
||||
{
|
||||
union
|
||||
{
|
||||
struct
|
||||
{
|
||||
int pad;
|
||||
} triangles_plain;
|
||||
struct
|
||||
{
|
||||
GLuint texture;
|
||||
} triangles_textured;
|
||||
struct
|
||||
{
|
||||
texture_font_t *font;
|
||||
} freetype;
|
||||
};
|
||||
};
|
||||
|
||||
DECL_PROGRAM(triangles_plain);
|
||||
DECL_PROGRAM(triangles_textured);
|
||||
DECL_PROGRAM(freetype);
|
||||
|
||||
void
|
||||
program_freetype_switch_font(texture_font_t *font);
|
||||
|
@ -10,28 +10,16 @@
|
||||
/* Used for drawing primitives */
|
||||
struct vertex_v2fc4f
|
||||
{
|
||||
float x;
|
||||
float y;
|
||||
|
||||
float r;
|
||||
float g;
|
||||
float b;
|
||||
float a;
|
||||
vec2 pos;
|
||||
vec4 color;
|
||||
};
|
||||
|
||||
/* Used for drawing textured primitives and freetype-gl fonts */
|
||||
struct vertex_v2ft2fc4f
|
||||
{
|
||||
float x;
|
||||
float y;
|
||||
|
||||
float s;
|
||||
float t;
|
||||
|
||||
float r;
|
||||
float g;
|
||||
float b;
|
||||
float a;
|
||||
vec2 pos;
|
||||
vec2 uv;
|
||||
vec4 color;
|
||||
};
|
||||
|
||||
|
||||
|
@ -7,8 +7,12 @@
|
||||
|
||||
#include "drawglx.h"
|
||||
#include "overlay.h"
|
||||
#include "programs.h"
|
||||
#include "drawglx_internal.h"
|
||||
|
||||
#include <GL/gl.h>
|
||||
#include <string.h>
|
||||
#include <stdio.h>
|
||||
|
||||
#define GLX_CONTEXT_MAJOR_VERSION_ARB 0x2091
|
||||
#define GLX_CONTEXT_MINOR_VERSION_ARB 0x2092
|
||||
@ -45,18 +49,14 @@ int glx_is_extension_supported(const char *list, const char *extension)
|
||||
return 0;
|
||||
}
|
||||
|
||||
int xoverlay_glx_init(struct xoverlay_library *library)
|
||||
int xoverlay_glx_init()
|
||||
{
|
||||
glXQueryVersion(library->display, &library->glx.version_major, &library->glx.version_minor);
|
||||
if (library->glx.version_major < 2)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
glXQueryVersion(xoverlay_library.display, &glx_state.version_major, &glx_state.version_minor);
|
||||
printf("GL Version: %s\n", glGetString(GL_VERSION));
|
||||
return 0;
|
||||
}
|
||||
|
||||
int xoverlay_glx_create_window(struct xoverlay_library *library)
|
||||
int xoverlay_glx_create_window()
|
||||
{
|
||||
GLint attribs[] = {
|
||||
GLX_X_RENDERABLE, GL_TRUE,
|
||||
@ -74,7 +74,7 @@ int xoverlay_glx_create_window(struct xoverlay_library *library)
|
||||
};
|
||||
|
||||
int fbc_count;
|
||||
GLXFBConfig *fbc = glXChooseFBConfig(library->display, library->screen, attribs, &fbc_count);
|
||||
GLXFBConfig *fbc = glXChooseFBConfig(xoverlay_library.display, xoverlay_library.screen, attribs, &fbc_count);
|
||||
if (fbc == NULL)
|
||||
{
|
||||
return -1;
|
||||
@ -83,11 +83,11 @@ int xoverlay_glx_create_window(struct xoverlay_library *library)
|
||||
int fbc_best_samples = -1;
|
||||
for (int i = 0; i < fbc_count; ++i)
|
||||
{
|
||||
XVisualInfo *info = glXGetVisualFromFBConfig(library->display, fbc[i]);
|
||||
XVisualInfo *info = glXGetVisualFromFBConfig(xoverlay_library.display, fbc[i]);
|
||||
if (info->depth != 32)
|
||||
continue;
|
||||
int samples;
|
||||
glXGetFBConfigAttrib(library->display, fbc[i], GLX_SAMPLES, &samples);
|
||||
glXGetFBConfigAttrib(xoverlay_library.display, fbc[i], GLX_SAMPLES, &samples);
|
||||
if (fbc_best < 0 || samples > fbc_best_samples)
|
||||
{
|
||||
fbc_best = i;
|
||||
@ -98,39 +98,41 @@ int xoverlay_glx_create_window(struct xoverlay_library *library)
|
||||
GLXFBConfig fbconfig = fbc[fbc_best];
|
||||
XFree(fbc);
|
||||
|
||||
XVisualInfo *info = glXGetVisualFromFBConfig(library->display, fbconfig);
|
||||
XVisualInfo *info = glXGetVisualFromFBConfig(xoverlay_library.display, fbconfig);
|
||||
if (info == NULL)
|
||||
{
|
||||
printf("GLX initialization error\n");
|
||||
return -1;
|
||||
}
|
||||
Window root = DefaultRootWindow(library->display);
|
||||
library->colormap = XCreateColormap(library->display, root, info->visual, AllocNone);
|
||||
Window root = DefaultRootWindow(xoverlay_library.display);
|
||||
xoverlay_library.colormap = XCreateColormap(xoverlay_library.display, root, info->visual, AllocNone);
|
||||
XSetWindowAttributes attr;
|
||||
attr.background_pixel = 0x0;
|
||||
attr.border_pixel = 0;
|
||||
attr.save_under = 1;
|
||||
attr.override_redirect = 1;
|
||||
attr.colormap = library->colormap;
|
||||
attr.colormap = xoverlay_library.colormap;
|
||||
|
||||
unsigned long mask = CWBackPixel | CWBorderPixel | CWSaveUnder | CWOverrideRedirect | CWColormap;
|
||||
printf("depth %d\n", info->depth);
|
||||
library->window = XCreateWindow(library->display, root, 0, 0, library->width, library->height, 0, info->depth, InputOutput, info->visual, mask, &attr);
|
||||
if (library->window == NULL)
|
||||
xoverlay_library.window = XCreateWindow(xoverlay_library.display, root, 0, 0, xoverlay_library.width, xoverlay_library.height, 0, info->depth, InputOutput, info->visual, mask, &attr);
|
||||
if (xoverlay_library.window == 0)
|
||||
{
|
||||
printf("X window initialization error\n");
|
||||
return -1;
|
||||
}
|
||||
XFree(info);
|
||||
XStoreName(library->display, library->window, "OverlayWindow");
|
||||
XMapWindow(library->display, library->window);
|
||||
XStoreName(xoverlay_library.display, xoverlay_library.window, "OverlayWindow");
|
||||
XMapWindow(xoverlay_library.display, xoverlay_library.window);
|
||||
|
||||
const char *extensions = glXQueryExtensionsString(library->display, library->screen);
|
||||
const char *extensions = glXQueryExtensionsString(xoverlay_library.display, xoverlay_library.screen);
|
||||
glXCreateContextAttribsARBfn glXCreateContextAttribsARB = (glXCreateContextAttribsARBfn)
|
||||
glXGetProcAddressARB((const GLubyte *) "glXCreateContextAttribsARB");
|
||||
|
||||
if (!glx_is_extension_supported(extensions, "GLX_ARB_create_context"))
|
||||
{
|
||||
printf("Falling back to glXCreateNewContext\n");
|
||||
library->glx.context = glXCreateNewContext(library->display, fbconfig, GLX_RGBA_TYPE, NULL, GL_TRUE);
|
||||
glx_state.context = glXCreateNewContext(xoverlay_library.display, fbconfig, GLX_RGBA_TYPE, NULL, GL_TRUE);
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -139,14 +141,15 @@ int xoverlay_glx_create_window(struct xoverlay_library *library)
|
||||
GLX_CONTEXT_MINOR_VERSION_ARB, 0,
|
||||
None
|
||||
};
|
||||
library->glx.context = glXCreateContextAttribsARB(library->display, fbconfig, NULL, GL_TRUE, ctx_attribs);
|
||||
XSync(library->display, GL_FALSE);
|
||||
glx_state.context = glXCreateContextAttribsARB(xoverlay_library.display, fbconfig, NULL, GL_TRUE, ctx_attribs);
|
||||
XSync(xoverlay_library.display, GL_FALSE);
|
||||
}
|
||||
if (library->glx.context == NULL)
|
||||
if (glx_state.context == NULL)
|
||||
{
|
||||
printf("OpenGL context initialization error\n");
|
||||
return -1;
|
||||
}
|
||||
if (!glXIsDirect(library->display, library->glx.context))
|
||||
if (!glXIsDirect(xoverlay_library.display, glx_state.context))
|
||||
{
|
||||
printf("Context is indirect\n");
|
||||
}
|
||||
@ -154,15 +157,25 @@ int xoverlay_glx_create_window(struct xoverlay_library *library)
|
||||
{
|
||||
printf("Context is direct\n");
|
||||
}
|
||||
glXMakeCurrent(library->display, library->window, library->glx.context);
|
||||
glClearColor(0.0f, 0.0f, 0.3f, 0.1f);
|
||||
glXMakeCurrent(xoverlay_library.display, xoverlay_library.window, glx_state.context);
|
||||
glewExperimental = GL_TRUE;
|
||||
if (glewInit() != GLEW_OK)
|
||||
{
|
||||
printf("GLEW initialization error: %s\n", glewGetErrorString(glGetError()));
|
||||
return -1;
|
||||
}
|
||||
glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
|
||||
glClear(GL_COLOR_BUFFER_BIT);
|
||||
glXSwapBuffers(library->display, library->window);
|
||||
glXSwapBuffers(xoverlay_library.display, xoverlay_library.window);
|
||||
|
||||
printf("Initializing DS\n");
|
||||
ds_init();
|
||||
program_init_everything();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int xoverlay_glx_destroy(struct xoverlay_library *library)
|
||||
int xoverlay_glx_destroy()
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
BIN
src/drawglx.o
Normal file
BIN
src/drawglx.o
Normal file
Binary file not shown.
@ -6,9 +6,12 @@
|
||||
*/
|
||||
|
||||
#include "drawglx_internal.h"
|
||||
#include "vertex_structs.h"
|
||||
#include "overlay.h"
|
||||
|
||||
#include <memory.h>
|
||||
#include <string.h>
|
||||
#include <math.h>
|
||||
|
||||
int
|
||||
drawglx_internal_init()
|
||||
@ -16,38 +19,46 @@ drawglx_internal_init()
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* STACK SAFE */
|
||||
void
|
||||
dis_init()
|
||||
{
|
||||
dstream.capacity = 128;
|
||||
dstream.memory = malloc(dstream.capacity);
|
||||
struct draw_instruction_t *instr = dstream.memory;
|
||||
instr->type = DI_INVALID_INSTRUCTION;
|
||||
dstream.read_ptr = 0;
|
||||
dstream.write_ptr = 0;
|
||||
dstream.next_index = 0;
|
||||
}
|
||||
|
||||
/* STACK SAFE */
|
||||
void
|
||||
dis_destroy()
|
||||
{
|
||||
free(dstream.memory);
|
||||
}
|
||||
|
||||
/* STACK SAFE */
|
||||
void
|
||||
dis_reset()
|
||||
{
|
||||
dstream.write_ptr = 0;
|
||||
dstream.read_ptr = 0;
|
||||
dstream.next_index = 0;
|
||||
}
|
||||
|
||||
/* STACK SAFE */
|
||||
void
|
||||
dis_reserve(size_t bytes)
|
||||
{
|
||||
while (dstream.write_ptr + bytes > dstream.capacity)
|
||||
{
|
||||
dstream.capacity *= 2;
|
||||
dstream.capacity += 4;
|
||||
dstream.memory = realloc(dstream.memory, dstream.capacity);
|
||||
}
|
||||
}
|
||||
|
||||
/* STACK SAFE */
|
||||
struct draw_instruction_t*
|
||||
dis_last_pushed_instruction()
|
||||
{
|
||||
@ -55,9 +66,14 @@ dis_last_pushed_instruction()
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
if (dstream.last_draw_instruction_offset + sizeof(struct draw_instruction_t) > dstream.capacity)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
return (struct draw_instruction_t *)(dstream.memory + dstream.last_draw_instruction_offset);
|
||||
}
|
||||
|
||||
/* STACK SAFE */
|
||||
void
|
||||
dis_push_data(size_t bytes, void *data)
|
||||
{
|
||||
@ -66,6 +82,7 @@ dis_push_data(size_t bytes, void *data)
|
||||
dstream.write_ptr += bytes;
|
||||
}
|
||||
|
||||
/* STACK SAFE */
|
||||
void
|
||||
dis_push_instruction(struct draw_instruction_t instr)
|
||||
{
|
||||
@ -84,6 +101,14 @@ dis_fetch_data(size_t bytes, void *data)
|
||||
return read_count;
|
||||
}
|
||||
|
||||
void*
|
||||
dis_read_data(size_t bytes)
|
||||
{
|
||||
void *result = dstream.memory + dstream.read_ptr;
|
||||
dstream.read_ptr += bytes;
|
||||
return result;
|
||||
}
|
||||
|
||||
void
|
||||
dis_switch_program(int program)
|
||||
{
|
||||
@ -91,7 +116,11 @@ dis_switch_program(int program)
|
||||
|
||||
if (last && last->type == DI_SWITCH_PROGRAM)
|
||||
{
|
||||
last->program = program;
|
||||
if (last->program != program)
|
||||
{
|
||||
last->program = program;
|
||||
dstream.next_index = 0;
|
||||
}
|
||||
return;
|
||||
}
|
||||
else
|
||||
@ -100,6 +129,7 @@ dis_switch_program(int program)
|
||||
|
||||
instr.type = DI_SWITCH_PROGRAM;
|
||||
instr.program = program;
|
||||
dstream.next_index = 0;
|
||||
dis_push_instruction(instr);
|
||||
}
|
||||
}
|
||||
@ -108,6 +138,7 @@ void
|
||||
dis_push_vertices(size_t count, size_t vertex_size, void *vertex_data)
|
||||
{
|
||||
struct draw_instruction_t *last = dis_last_pushed_instruction();
|
||||
dstream.next_index += count;
|
||||
|
||||
if (last && (last->type == DI_PUSH_VERTICES))
|
||||
{
|
||||
@ -207,164 +238,314 @@ dis_fetch_instruction()
|
||||
return result;
|
||||
}
|
||||
|
||||
struct draw_cmd*
|
||||
draw_cmd_new(int program)
|
||||
{
|
||||
struct draw_cmd *result = calloc(1, sizeof(struct draw_cmd));
|
||||
result->program = program;
|
||||
result->vertices = vector_new(programs[program]->vertex->vertices->item_size);
|
||||
result->indices = vector_new(programs[program]->vertex->indices->item_size);
|
||||
return result;
|
||||
}
|
||||
|
||||
void
|
||||
draw_cmd_delete(struct draw_cmd *cmd)
|
||||
{
|
||||
vector_delete(cmd->vertices);
|
||||
vector_delete(cmd->indices);
|
||||
free(cmd);
|
||||
}
|
||||
|
||||
void
|
||||
ds_init()
|
||||
{
|
||||
memset(&ds, 0, sizeof(struct draw_state));
|
||||
ds.commands = vector_new(sizeof(struct draw_cmd));
|
||||
vector_push_back(ds.commands, calloc(1, sizeof(struct draw_cmd)));
|
||||
ds.current_command = 0;
|
||||
dis_init();
|
||||
ds.program = -1;
|
||||
mat4_set_identity(&ds.projection);
|
||||
mat4_set_identity(&ds.view);
|
||||
mat4_set_identity(&ds.model);
|
||||
mat4_set_orthographic(&ds.projection, 0, xoverlay_library.width, 0, xoverlay_library.height, -1, 1);
|
||||
}
|
||||
|
||||
void
|
||||
ds_destroy()
|
||||
{
|
||||
for (int i = 0; i < ds.commands->size; ++i)
|
||||
dis_destroy();
|
||||
}
|
||||
|
||||
void
|
||||
ds_mark_dirty()
|
||||
{
|
||||
ds.dirty = 1;
|
||||
}
|
||||
|
||||
void
|
||||
ds_render_if_needed()
|
||||
{
|
||||
if (ds.dirty && ds.program >= 0)
|
||||
{
|
||||
struct draw_cmd *cmd = vector_get(ds.commands, i);
|
||||
draw_cmd_delete(cmd);
|
||||
printf("calling renderer...\n");
|
||||
programs[ds.program].render();
|
||||
}
|
||||
vector_delete(ds.commands);
|
||||
ds.dirty = 0;
|
||||
}
|
||||
|
||||
void
|
||||
ds_alloc_next_command(int program)
|
||||
ds_pre_render()
|
||||
{
|
||||
struct draw_cmd *result = calloc(1, sizeof(struct draw_cmd));
|
||||
result->program = program;
|
||||
vector_push_back(ds.commands, result);
|
||||
ds.current_command++;
|
||||
glPushAttrib(GL_CURRENT_BIT | GL_ENABLE_BIT | GL_LIGHTING_BIT | GL_TEXTURE_BIT | GL_COLOR_BUFFER_BIT);
|
||||
|
||||
glEnable(GL_BLEND);
|
||||
glEnable(GL_TEXTURE_2D);
|
||||
glDisable(GL_ALPHA_TEST);
|
||||
glDisable(GL_CULL_FACE);
|
||||
glDisable(GL_DEPTH_TEST);
|
||||
glDisable(GL_LIGHTING);
|
||||
glDisable(GL_STENCIL_TEST);
|
||||
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
|
||||
|
||||
glPushClientAttrib(GL_CLIENT_ALL_ATTRIB_BITS);
|
||||
|
||||
glDisableClientState(GL_COLOR_ARRAY);
|
||||
glDisableClientState(GL_EDGE_FLAG_ARRAY);
|
||||
glDisableClientState(GL_FOG_COORD_ARRAY);
|
||||
glDisableClientState(GL_SECONDARY_COLOR_ARRAY);
|
||||
glDisableClientState(GL_TEXTURE_COORD_ARRAY);
|
||||
glDisableClientState(GL_NORMAL_ARRAY);
|
||||
|
||||
glEnableClientState(GL_VERTEX_ARRAY);
|
||||
glEnableClientState(GL_INDEX_ARRAY);
|
||||
}
|
||||
|
||||
void
|
||||
ds_next_frame()
|
||||
ds_post_render()
|
||||
{
|
||||
for (int i = 0; i < ds.commands->size; ++i)
|
||||
glPopClientAttrib();
|
||||
glPopAttrib();
|
||||
}
|
||||
|
||||
void
|
||||
ds_render_next_frame()
|
||||
{
|
||||
glClear(GL_COLOR_BUFFER_BIT);
|
||||
dis_finish();
|
||||
ds.program = -1;
|
||||
struct draw_instruction_t *instr;
|
||||
|
||||
instr = dis_fetch_instruction();
|
||||
|
||||
while (instr)
|
||||
{
|
||||
struct draw_cmd *cmd = vector_get(ds.commands, i);
|
||||
draw_cmd_delete(cmd);
|
||||
}
|
||||
vector_resize(ds.commands, 1);
|
||||
memset(vector_get(ds.commands, 0), 0, sizeof(struct draw_cmd));
|
||||
ds.current_command = 0;
|
||||
}
|
||||
|
||||
void
|
||||
ds_render()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
void
|
||||
ds_render()
|
||||
{
|
||||
for (int i = 0; i < vector_size(state->commands); ++i)
|
||||
{
|
||||
struct draw_cmd *current = vector_get(state->commands, i);
|
||||
if (current->texture != state->texture)
|
||||
printf("instruction: %d data: %d\n", instr->type, instr->program);
|
||||
switch (instr->type)
|
||||
{
|
||||
glBindTexture(GL_TEXTURE_2D, current->texture);
|
||||
state->texture = current->texture;
|
||||
case DI_SWITCH_PROGRAM:
|
||||
if (ds.program != instr->program)
|
||||
{
|
||||
ds_render_if_needed();
|
||||
if (ds.program >= 0 && programs[ds.program].unload)
|
||||
programs[ds.program].unload();
|
||||
ds.program = instr->program;
|
||||
if (programs[ds.program].load)
|
||||
programs[ds.program].load();
|
||||
}
|
||||
break;
|
||||
case DI_PUSH_VERTICES:
|
||||
ds_mark_dirty();
|
||||
printf("program: %d\n", ds.program);
|
||||
vertex_buffer_push_back_vertices(programs[ds.program].vertex, dis_read_data(instr->count * programs[ds.program].vertex_size), instr->count);
|
||||
break;
|
||||
case DI_PUSH_INDICES:
|
||||
ds_mark_dirty();
|
||||
vertex_buffer_push_back_indices(programs[ds.program].vertex, dis_read_data(instr->count * sizeof(GLuint)), instr->count);
|
||||
break;
|
||||
case DI_PROGRAM_SWITCH_TEXTURE:
|
||||
ds_bind_texture(instr->texture);
|
||||
break;
|
||||
case DI_PROGRAM_SWITCH_FONT:
|
||||
program_freetype_switch_font(instr->font);
|
||||
break;
|
||||
case DI_INVALID_INSTRUCTION:
|
||||
case DI_TERMINATE:
|
||||
default:
|
||||
break;
|
||||
|
||||
}
|
||||
if (current->program != state->program)
|
||||
{
|
||||
if (state->program >= 0)
|
||||
{
|
||||
programs[state->program].unload();
|
||||
}
|
||||
if (programs[current->program].shader != state->shader)
|
||||
{
|
||||
glUseProgram(programs[current->program].shader);
|
||||
state->shader = programs[current->program].shader;
|
||||
}
|
||||
programs[current->program].load();
|
||||
}
|
||||
programs[current->program].render(current);
|
||||
instr = dis_fetch_instruction();
|
||||
}
|
||||
if (state->program >= 0)
|
||||
programs[state->program].unload();
|
||||
state->program = -1;
|
||||
}
|
||||
|
||||
void
|
||||
ds_prepare_command(int program)
|
||||
{
|
||||
int should_alloc_command = 0;
|
||||
struct draw_cmd *current = vector_get(ds.commands, ds.current_command);
|
||||
|
||||
if (current == NULL)
|
||||
should_alloc_command = 1;
|
||||
else if (program != current->program)
|
||||
should_alloc_command = 1;
|
||||
else if (programs[program].check && !programs[program].check(current))
|
||||
should_alloc_command = 1;
|
||||
|
||||
if (should_alloc_command)
|
||||
ds_render_if_needed();
|
||||
if (ds.program >= 0 && programs[ds.program].unload)
|
||||
{
|
||||
ds_alloc_next_command();
|
||||
programs[ds.program].unload();
|
||||
ds.program = -1;
|
||||
}
|
||||
dis_reset();
|
||||
glFlush();
|
||||
printf("SwapBuffers\n");
|
||||
glXSwapBuffers(xoverlay_library.display, xoverlay_library.window);
|
||||
}
|
||||
|
||||
void
|
||||
ds_bind_texture(GLuint texture)
|
||||
{
|
||||
if (ds.texture != texture)
|
||||
{
|
||||
ds.texture = texture;
|
||||
glBindTexture(GL_TEXTURE_2D, texture);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
draw_line(vec2 xy, vec2 delta, vec4 color)
|
||||
ds_use_shader(GLuint shader)
|
||||
{
|
||||
ds_prepare_command(PROGRAM_TRIANGLES_PLAIN);
|
||||
vertex_buffer_delete();
|
||||
if (ds.shader != shader)
|
||||
{
|
||||
ds.shader = shader;
|
||||
glUseProgram(shader);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
ds_prepare_program(int program)
|
||||
{
|
||||
printf("current program: %d, new: %d\n", ds.program, program);
|
||||
if (program != ds.program)
|
||||
{
|
||||
printf("switching to program %d from %d\n", program, ds.program);
|
||||
dis_switch_program(program);
|
||||
ds.program = program;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
draw_line(vec2 xy, vec2 delta, vec4 color, float thickness)
|
||||
{
|
||||
ds_prepare_program(PROGRAM_TRIANGLES_PLAIN);
|
||||
GLuint idx = dstream.next_index;
|
||||
|
||||
struct vertex_v2fc4f vertices[0];
|
||||
/* A C => ABC, CDB
|
||||
* B D
|
||||
*/
|
||||
GLuint indices[6] = { idx, idx + 1, idx + 2, idx + 2, idx + 3, idx + 1 };
|
||||
|
||||
vec2 normal = { .x = -delta.y, .y = delta.x };
|
||||
vec2 end = (vec2){ xy.x + delta.x, xy.y + delta.y };
|
||||
float length = sqrtf(normal.x * normal.x + normal.y * normal.y);
|
||||
if (length == 0)
|
||||
return;
|
||||
length /= thickness;
|
||||
normal.x /= length;
|
||||
normal.y /= length;
|
||||
|
||||
vertices[0].pos.x = xy.x - normal.x;
|
||||
vertices[0].pos.y = xy.y - normal.y;
|
||||
vertices[0].color = color;
|
||||
|
||||
vertices[1].pos.x = xy.x + normal.x;
|
||||
vertices[1].pos.y = xy.y + normal.y;
|
||||
vertices[1].color = color;
|
||||
|
||||
vertices[2].pos.x = end.x - normal.x;
|
||||
vertices[2].pos.y = end.y - normal.y;
|
||||
vertices[2].color = color;
|
||||
|
||||
vertices[3].pos.x = end.x + normal.x;
|
||||
vertices[3].pos.y = end.y + normal.y;
|
||||
vertices[3].color = color;
|
||||
|
||||
dis_push_vertices(4, sizeof(struct vertex_v2fc4f), vertices);
|
||||
dis_push_indices(6, indices);
|
||||
}
|
||||
|
||||
void
|
||||
draw_rect(vec2 xy, vec2 hw, vec4 color)
|
||||
{
|
||||
ds_prepare_command(PROGRAM_TRIANGLES_PLAIN);
|
||||
ds_prepare_program(PROGRAM_TRIANGLES_PLAIN);
|
||||
GLuint idx = dstream.next_index;
|
||||
|
||||
struct vertex_v2fc4f vertices[4];
|
||||
/* A C => ABC, CDB
|
||||
* B D
|
||||
*/
|
||||
GLuint indices[6] = { idx, idx + 1, idx + 2, idx + 2, idx + 3, idx + 1 };
|
||||
|
||||
vertices[0].pos.x = xy.x;
|
||||
vertices[0].pos.y = xy.y;
|
||||
vertices[0].color = color;
|
||||
|
||||
vertices[1].pos.x = xy.x;
|
||||
vertices[1].pos.y = xy.y + hw.y;
|
||||
vertices[1].color = color;
|
||||
|
||||
vertices[2].pos.x = xy.x + hw.x;
|
||||
vertices[2].pos.y = xy.y + hw.y;
|
||||
vertices[2].color = color;
|
||||
|
||||
vertices[3].pos.x = xy.x + hw.x;
|
||||
vertices[3].pos.y = xy.y;
|
||||
vertices[3].color = color;
|
||||
|
||||
dis_push_vertices(4, sizeof(struct vertex_v2fc4f), vertices);
|
||||
dis_push_indices(6, indices);
|
||||
}
|
||||
|
||||
void
|
||||
draw_rect_outline(vec2 xy, vec2 hw, vec4 color)
|
||||
draw_rect_outline(vec2 xy, vec2 hw, vec4 color, float thickness)
|
||||
{
|
||||
ds_prepare_command(PROGRAM_TRIANGLES_PLAIN);
|
||||
vec2 point = xy;
|
||||
vec2 delta = { hw.x, 0 };
|
||||
draw_line(point, delta, color, thickness);
|
||||
point.x += delta.x;
|
||||
delta.x = 0;
|
||||
delta.y = hw.y;
|
||||
draw_line(point, delta, color, thickness);
|
||||
point.y += delta.y;
|
||||
delta.x = -hw.x;
|
||||
delta.y = 0;
|
||||
draw_line(point, delta, color, thickness);
|
||||
point.x += delta.x;
|
||||
delta.x = 0;
|
||||
delta.y = -hw.y;
|
||||
draw_line(point, delta, color, thickness);
|
||||
}
|
||||
|
||||
void
|
||||
draw_rect_textured(vec2 xy, vec2 hw, vec4 color, int texture, vec2 uv, vec2 st)
|
||||
{
|
||||
ds_prepare_command(PROGRAM_TRIANGLES_TEXTURED);
|
||||
ds_prepare_program(PROGRAM_TRIANGLES_TEXTURED);
|
||||
GLuint idx = dstream.next_index;
|
||||
|
||||
struct vertex_v2ft2fc4f vertices[4];
|
||||
/* A C => ABC, CDB
|
||||
* B D
|
||||
*/
|
||||
GLuint indices[6] = { idx, idx + 1, idx + 2, idx + 2, idx + 3, idx + 1 };
|
||||
|
||||
vertices[0].pos.x = xy.x;
|
||||
vertices[0].pos.y = xy.y;
|
||||
vertices[0].uv = uv;
|
||||
vertices[0].color = color;
|
||||
|
||||
vertices[1].pos.x = xy.x;
|
||||
vertices[1].pos.y = xy.y + hw.y;
|
||||
vertices[1].uv = (vec2){ uv.x, uv.y + st.y };
|
||||
vertices[1].color = color;
|
||||
|
||||
vertices[2].pos.x = xy.x + hw.x;
|
||||
vertices[2].pos.y = xy.y + hw.y;
|
||||
vertices[1].uv = (vec2){ uv.x + st.x, uv.y + st.y };
|
||||
vertices[2].color = color;
|
||||
|
||||
vertices[3].pos.x = xy.x + hw.x;
|
||||
vertices[3].pos.y = xy.y;
|
||||
vertices[1].uv = (vec2){ uv.x + st.x, uv.y };
|
||||
vertices[3].color = color;
|
||||
|
||||
dis_push_vertices(4, sizeof(struct vertex_v2ft2fc4f), vertices);
|
||||
dis_push_indices(6, indices);
|
||||
}
|
||||
|
||||
void
|
||||
draw_string(vec2 xy, const char *string, texture_font_t *font, vec4 color)
|
||||
{
|
||||
ds_prepare_command(PROGRAM_FREETYPE);
|
||||
ds_prepare_program(PROGRAM_FREETYPE);
|
||||
}
|
||||
|
||||
void
|
||||
draw_string_outline(vec2 xy, const char *string, texture_font_t *font, vec4 color)
|
||||
{
|
||||
ds_prepare_command(PROGRAM_FREETYPE);
|
||||
ds_prepare_program(PROGRAM_FREETYPE);
|
||||
}
|
||||
|
||||
void
|
||||
draw_string_with_outline(vec2 xy, const char *string, texture_font_t *font, vec4 color, vec4 outline_color)
|
||||
{
|
||||
ds_prepare_command(PROGRAM_FREETYPE);
|
||||
ds_prepare_program(PROGRAM_FREETYPE);
|
||||
}
|
||||
|
||||
void
|
||||
|
BIN
src/drawglx_internal.o
Normal file
BIN
src/drawglx_internal.o
Normal file
Binary file not shown.
@ -25,7 +25,7 @@ int init_input()
|
||||
{
|
||||
DIR *dev_input;
|
||||
struct dirent *ent;
|
||||
char buffer[256];
|
||||
char buffer[400];
|
||||
dev_input = opendir("/dev/input/by-id");
|
||||
if (dev_input == NULL)
|
||||
{
|
||||
@ -36,7 +36,7 @@ int init_input()
|
||||
{
|
||||
if (fd_keyboard < 0 && strstr(ent->d_name, "-event-kbd"))
|
||||
{
|
||||
snprintf(buffer, 256, "/dev/input/by-id/%s", ent->d_name);
|
||||
snprintf(buffer, 400, "/dev/input/by-id/%s", ent->d_name);
|
||||
fd_keyboard = open(buffer, O_RDONLY);
|
||||
if (fd_keyboard < 0)
|
||||
{
|
||||
@ -46,7 +46,7 @@ int init_input()
|
||||
}
|
||||
if (fd_mouse < 0 && strstr(ent->d_name, "-event-mouse"))
|
||||
{
|
||||
snprintf(buffer, 256, "/dev/input/by-id/%s", ent->d_name);
|
||||
snprintf(buffer, 400, "/dev/input/by-id/%s", ent->d_name);
|
||||
fd_mouse = open(buffer, O_RDONLY);
|
||||
if (fd_mouse < 0)
|
||||
{
|
||||
|
BIN
src/input.o
Normal file
BIN
src/input.o
Normal file
Binary file not shown.
203
src/overlay.c
203
src/overlay.c
@ -7,6 +7,7 @@
|
||||
|
||||
#include "overlay.h"
|
||||
#include "input.h"
|
||||
#include "drawglx_internal.h"
|
||||
|
||||
#include <GL/glx.h>
|
||||
#include <X11/extensions/shape.h>
|
||||
@ -17,55 +18,52 @@
|
||||
int event_ShapeNotify;
|
||||
int event_ShapeError;
|
||||
|
||||
int xoverlay_init(struct xoverlay_library *library)
|
||||
int xoverlay_init()
|
||||
{
|
||||
memset(library, 0, sizeof(struct xoverlay_library));
|
||||
glewExperimental = GL_TRUE;
|
||||
if (glewInit() != GL_TRUE)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
memset(&xoverlay_library, 0, sizeof(struct xoverlay_library));
|
||||
if (init_input() < 0)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
library->display = XOpenDisplay(NULL);
|
||||
if (library->display == NULL)
|
||||
xoverlay_library.display = XOpenDisplay(NULL);
|
||||
if (xoverlay_library.display == NULL)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
library->screen = DefaultScreen(library->display);
|
||||
library->width = DisplayWidth(library->display, library->screen);
|
||||
library->height = DisplayHeight(library->display, library->screen);
|
||||
xoverlay_library.screen = DefaultScreen(xoverlay_library.display);
|
||||
xoverlay_library.width = DisplayWidth(xoverlay_library.display, xoverlay_library.screen);
|
||||
xoverlay_library.height = DisplayHeight(xoverlay_library.display, xoverlay_library.screen);
|
||||
|
||||
if (!XShapeQueryExtension(library->display, &event_ShapeNotify, &event_ShapeError))
|
||||
if (!XShapeQueryExtension(xoverlay_library.display, &event_ShapeNotify, &event_ShapeError))
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
xoverlay_glx_init(library);
|
||||
xoverlay_glx_create_window(library);
|
||||
if (xoverlay_glx_init() < 0)
|
||||
return -1;
|
||||
if (xoverlay_glx_create_window() < 0)
|
||||
return -1;
|
||||
|
||||
XShapeCombineMask(library->display, library->window, ShapeInput, 0, 0, None, ShapeSet);
|
||||
XShapeSelectInput(library->display, library->window, ShapeNotifyMask);
|
||||
XShapeCombineMask(xoverlay_library.display, xoverlay_library.window, ShapeInput, 0, 0, None, ShapeSet);
|
||||
XShapeSelectInput(xoverlay_library.display, xoverlay_library.window, ShapeNotifyMask);
|
||||
|
||||
XserverRegion region = XFixesCreateRegion(library->display, NULL, 0);
|
||||
XFixesSetWindowShapeRegion(library->display, library->window, ShapeInput, 0, 0, region);
|
||||
XFixesDestroyRegion(library->display, region);
|
||||
XserverRegion region = XFixesCreateRegion(xoverlay_library.display, NULL, 0);
|
||||
XFixesSetWindowShapeRegion(xoverlay_library.display, xoverlay_library.window, ShapeInput, 0, 0, region);
|
||||
XFixesDestroyRegion(xoverlay_library.display, region);
|
||||
|
||||
library->init = 1;
|
||||
xoverlay_library.init = 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
void xoverlay_destroy(struct xoverlay_library *library)
|
||||
void xoverlay_destroy()
|
||||
{
|
||||
XDestroyWindow(library->display, library->window);
|
||||
XCloseDisplay(library->display);
|
||||
library->init = 0;
|
||||
XDestroyWindow(xoverlay_library.display, xoverlay_library.window);
|
||||
XCloseDisplay(xoverlay_library.display);
|
||||
xoverlay_library.init = 0;
|
||||
}
|
||||
|
||||
unsigned xoverlay_rgb(int r, int g, int b)
|
||||
/*unsigned xoverlay_rgb(int r, int g, int b)
|
||||
{
|
||||
return xoverlay_rgba(r, g, b, 255);
|
||||
}
|
||||
@ -82,70 +80,64 @@ unsigned xoverlay_rgba(int r, int g, int b, int a)
|
||||
b = b * a / 255;
|
||||
result = (b & 0xFF) | (g & 0xFF) << 8 | (r & 0xFF) << 16 | (a & 0xFF) << 24;
|
||||
return result;
|
||||
}*/
|
||||
|
||||
xoverlay_rgba_t xoverlay_rgba(int r, int g, int b, int a)
|
||||
{
|
||||
xoverlay_rgba_t result;
|
||||
result.r = (float)r / 255.0f;
|
||||
result.g = (float)g / 255.0f;
|
||||
result.b = (float)b / 255.0f;
|
||||
result.a = (float)a / 255.0f;
|
||||
return result;
|
||||
}
|
||||
|
||||
void xoverlay_clear_rectangle(struct xoverlay_library *library, int x, int y, int w, int h)
|
||||
void
|
||||
xoverlay_draw_line(xoverlay_vec2_t xy, xoverlay_vec2_t delta, xoverlay_rgba_t color, float thickness)
|
||||
{
|
||||
if (!library->init) return;
|
||||
if (!library->drawing) return;
|
||||
draw_line(*(vec2*)&xy, *(vec2*)&delta, *(vec4*)&color, thickness);
|
||||
}
|
||||
|
||||
void xoverlay_clear_screen(struct xoverlay_library *library)
|
||||
void
|
||||
xoverlay_draw_rect(xoverlay_vec2_t xy, xoverlay_vec2_t hw, xoverlay_rgba_t color)
|
||||
{
|
||||
if (!library->init) return;
|
||||
if (!library->drawing) return;
|
||||
draw_rect(*(vec2*)&xy, *(vec2*)&hw, *(vec4*)&color);
|
||||
}
|
||||
|
||||
void xoverlay_draw_string(struct xoverlay_library *library, const char *string, int x, int y, unsigned fg, unsigned bg)
|
||||
void
|
||||
xoverlay_draw_rect_outline(xoverlay_vec2_t xy, xoverlay_vec2_t hw, xoverlay_rgba_t color, float thickness)
|
||||
{
|
||||
if (!library->init) return;
|
||||
if (!library->drawing) return;
|
||||
draw_rect_outline(*(vec2*)&xy, *(vec2*)&hw, *(vec4*)&color, thickness);
|
||||
}
|
||||
|
||||
void xoverlay_draw_line(struct xoverlay_library *library, int x, int y, int w, int h, unsigned fg)
|
||||
void xoverlay_install_keyboard_callback(xoverlay_callback_keypress callback)
|
||||
{
|
||||
if (!library->init) return;
|
||||
if (!library->drawing) return;
|
||||
XSetForeground(library->display, library->gc, fg);
|
||||
XDrawLine(library->display, library->window, library->gc, x, y, x + w, x + h);
|
||||
xoverlay_library.cb_keypress = callback;
|
||||
}
|
||||
|
||||
void xoverlay_draw_rectangle(struct xoverlay_library *library, int x, int y, int w, int h, unsigned fg)
|
||||
void xoverlay_install_click_callback(xoverlay_callback_click callback)
|
||||
{
|
||||
if (!library->init) return;
|
||||
if (!library->drawing) return;
|
||||
XSetForeground(library->display, library->gc, fg);
|
||||
XFillRectangle(library->display, library->window, library->gc, x, y, w, h);
|
||||
xoverlay_library.cb_click = callback;
|
||||
}
|
||||
|
||||
void xoverlay_install_keyboard_callback(struct xoverlay_library *library, xoverlay_callback_keypress callback)
|
||||
void xoverlay_install_scroll_callback(xoverlay_callback_scroll callback)
|
||||
{
|
||||
library->cb_keypress = callback;
|
||||
xoverlay_library.cb_scroll = callback;
|
||||
}
|
||||
|
||||
void xoverlay_install_click_callback(struct xoverlay_library *library, xoverlay_callback_click callback)
|
||||
void xoverlay_install_mouse_callback(xoverlay_callback_mousemove callback)
|
||||
{
|
||||
library->cb_click = callback;
|
||||
}
|
||||
|
||||
void xoverlay_install_scroll_callback(struct xoverlay_library *library, xoverlay_callback_scroll callback)
|
||||
{
|
||||
library->cb_scroll = callback;
|
||||
}
|
||||
|
||||
void xoverlay_install_mouse_callback(struct xoverlay_library *library, xoverlay_callback_mousemove callback)
|
||||
{
|
||||
library->cb_mousemove = callback;
|
||||
xoverlay_library.cb_mousemove = callback;
|
||||
}
|
||||
|
||||
/*void xoverlay_install_draw_callback(struct xoverlay_library *library, xoverlay_callback_draw callback)
|
||||
{
|
||||
library->cb_draw = callback;
|
||||
xoverlay_library.cb_draw = callback;
|
||||
}*/
|
||||
|
||||
void xoverlay_poll_events(struct xoverlay_library *library)
|
||||
void xoverlay_poll_events()
|
||||
{
|
||||
if (!library->init) return;
|
||||
if (!xoverlay_library.init) return;
|
||||
|
||||
struct input_event_parsed ev;
|
||||
|
||||
@ -157,8 +149,8 @@ void xoverlay_poll_events(struct xoverlay_library *library)
|
||||
switch (ev.type)
|
||||
{
|
||||
case INPUT_EVENT_KEY:
|
||||
if (library->cb_keypress)
|
||||
library->cb_keypress(ev.evt_key.key, ev.evt_key.state);
|
||||
if (xoverlay_library.cb_keypress)
|
||||
xoverlay_library.cb_keypress(ev.evt_key.key, ev.evt_key.state);
|
||||
break;
|
||||
}
|
||||
}
|
||||
@ -167,16 +159,16 @@ void xoverlay_poll_events(struct xoverlay_library *library)
|
||||
switch (ev.type)
|
||||
{
|
||||
case INPUT_EVENT_KEY:
|
||||
if (library->cb_click)
|
||||
library->cb_click(ev.evt_key.key, ev.evt_key.state);
|
||||
if (xoverlay_library.cb_click)
|
||||
xoverlay_library.cb_click(ev.evt_key.key, ev.evt_key.state);
|
||||
break;
|
||||
case INPUT_EVENT_MOVE:
|
||||
accum_x += ev.evt_move.x;
|
||||
accum_y += ev.evt_move.y;
|
||||
break;
|
||||
case INPUT_EVENT_SCROLL:
|
||||
if (library->cb_scroll)
|
||||
library->cb_scroll(ev.evt_scroll.value);
|
||||
if (xoverlay_library.cb_scroll)
|
||||
xoverlay_library.cb_scroll(ev.evt_scroll.value);
|
||||
break;
|
||||
}
|
||||
}
|
||||
@ -189,34 +181,34 @@ void xoverlay_poll_events(struct xoverlay_library *library)
|
||||
int c, d;
|
||||
unsigned e;
|
||||
|
||||
XQueryPointer(library->display, library->window, &a, &b, &mx, &my, &c, &d, &e);
|
||||
XQueryPointer(xoverlay_library.display, xoverlay_library.window, &a, &b, &mx, &my, &c, &d, &e);
|
||||
|
||||
if (mx != library->mouse.x || my != library->mouse.y)
|
||||
if (mx != xoverlay_library.mouse.x || my != xoverlay_library.mouse.y)
|
||||
{
|
||||
if (library->cb_mousemove)
|
||||
library->cb_mousemove(mx - library->mouse.x, my - library->mouse.y, mx, my);
|
||||
if (xoverlay_library.cb_mousemove)
|
||||
xoverlay_library.cb_mousemove(mx - xoverlay_library.mouse.x, my - xoverlay_library.mouse.y, mx, my);
|
||||
|
||||
library->mouse.x = mx;
|
||||
library->mouse.y = my;
|
||||
xoverlay_library.mouse.x = mx;
|
||||
xoverlay_library.mouse.y = my;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/*char keymap_new[32];
|
||||
XQueryKeymap(library->display, keymap_new);
|
||||
XQueryKeymap(xoverlay_library.display, keymap_new);
|
||||
for (int i = 0; i < 32; ++i)
|
||||
{
|
||||
if (keymap_new[i] != library->keyboard.keymap[i])
|
||||
if (keymap_new[i] != xoverlay_library.keyboard.keymap[i])
|
||||
{
|
||||
for (int j = 0; j < 8; ++j)
|
||||
{
|
||||
if ((keymap_new[i] & (1 << j)) != (library->keyboard.keymap[i] & (1 << j)))
|
||||
if ((keymap_new[i] & (1 << j)) != (xoverlay_library.keyboard.keymap[i] & (1 << j)))
|
||||
{
|
||||
if (library->cb_keypress)
|
||||
library->cb_keypress(i * 8 + j, !!(keymap_new[i] & (1 << j)));
|
||||
if (xoverlay_library.cb_keypress)
|
||||
xoverlay_library.cb_keypress(i * 8 + j, !!(keymap_new[i] & (1 << j)));
|
||||
}
|
||||
}
|
||||
library->keyboard.keymap[i] = keymap_new[i];
|
||||
xoverlay_library.keyboard.keymap[i] = keymap_new[i];
|
||||
}
|
||||
}
|
||||
|
||||
@ -226,57 +218,56 @@ void xoverlay_poll_events(struct xoverlay_library *library)
|
||||
int c, d;
|
||||
unsigned e;
|
||||
|
||||
XQueryPointer(library->display, library->window, &a, &b, &mx, &my, &c, &d, &e);
|
||||
if (library->cb_mousemove && (library->mouse.x != mx || library->mouse.y != my))
|
||||
XQueryPointer(xoverlay_library.display, xoverlay_library.window, &a, &b, &mx, &my, &c, &d, &e);
|
||||
if (xoverlay_library.cb_mousemove && (xoverlay_library.mouse.x != mx || xoverlay_library.mouse.y != my))
|
||||
{
|
||||
library->cb_mousemove(mx, my);
|
||||
xoverlay_library.cb_mousemove(mx, my);
|
||||
}
|
||||
|
||||
library->mouse.x = mx;
|
||||
library->mouse.y = my;*/
|
||||
xoverlay_library.mouse.x = mx;
|
||||
xoverlay_library.mouse.y = my;*/
|
||||
|
||||
/*XEvent xevt;
|
||||
if (XCheckWindowEvent(library->display, library->window, KeyPressMask | KeyReleaseMask | ButtonPressMask | ButtonReleaseMask | PointerMotionMask | ExposureMask, &xevt))
|
||||
if (XCheckWindowEvent(xoverlay_library.display, xoverlay_library.window, KeyPressMask | KeyReleaseMask | ButtonPressMask | ButtonReleaseMask | PointerMotionMask | ExposureMask, &xevt))
|
||||
{
|
||||
printf("event %d\n", xevt.type);
|
||||
switch (xevt.type)
|
||||
{
|
||||
case KeyPress:
|
||||
case KeyRelease:
|
||||
library->keyboard[xevt.xkey.keycode] = (xevt.xkey.type == KeyPress);
|
||||
if (library->cb_click)
|
||||
library->cb_click(xevt.xkey.keycode, xevt.xkey.type == KeyPress);
|
||||
xoverlay_library.keyboard[xevt.xkey.keycode] = (xevt.xkey.type == KeyPress);
|
||||
if (xoverlay_library.cb_click)
|
||||
xoverlay_library.cb_click(xevt.xkey.keycode, xevt.xkey.type == KeyPress);
|
||||
break;
|
||||
case ButtonPress:
|
||||
case ButtonRelease:
|
||||
library->mouse.buttons[xevt.xbutton.button - 1] = (xevt.xbutton.type == ButtonPress);
|
||||
if (library->cb_click)
|
||||
library->cb_click(xevt.xbutton.button - 1, xevt.xbutton.type == ButtonPress);
|
||||
xoverlay_library.mouse.buttons[xevt.xbutton.button - 1] = (xevt.xbutton.type == ButtonPress);
|
||||
if (xoverlay_library.cb_click)
|
||||
xoverlay_library.cb_click(xevt.xbutton.button - 1, xevt.xbutton.type == ButtonPress);
|
||||
break;
|
||||
case MotionNotify:
|
||||
library->mouse.x = xevt.xmotion.x;
|
||||
library->mouse.y = xevt.xmotion.y;
|
||||
if (library->cb_click)
|
||||
library->cb_click(xevt.xbutton.button - 1, xevt.xbutton.type == ButtonPress);
|
||||
xoverlay_library.mouse.x = xevt.xmotion.x;
|
||||
xoverlay_library.mouse.y = xevt.xmotion.y;
|
||||
if (xoverlay_library.cb_click)
|
||||
xoverlay_library.cb_click(xevt.xbutton.button - 1, xevt.xbutton.type == ButtonPress);
|
||||
break;
|
||||
case Expose:
|
||||
if (library->cb_draw)
|
||||
library->cb_draw();
|
||||
if (xoverlay_library.cb_draw)
|
||||
xoverlay_library.cb_draw();
|
||||
}
|
||||
}*/
|
||||
}
|
||||
|
||||
void xoverlay_draw_begin(struct xoverlay_library *library)
|
||||
void xoverlay_draw_begin()
|
||||
{
|
||||
if (!library->init) return;
|
||||
if (!xoverlay_library.init) return;
|
||||
|
||||
library->drawing = 1;
|
||||
xoverlay_library.drawing = 1;
|
||||
}
|
||||
|
||||
void xoverlay_draw_end(struct xoverlay_library *library)
|
||||
void xoverlay_draw_end()
|
||||
{
|
||||
if (!library->init) return;
|
||||
|
||||
XFlush(library->display);
|
||||
library->drawing = 0;
|
||||
if (!xoverlay_library.init) return;
|
||||
ds_render_next_frame();
|
||||
xoverlay_library.drawing = 0;
|
||||
}
|
||||
|
BIN
src/overlay.o
Normal file
BIN
src/overlay.o
Normal file
Binary file not shown.
@ -45,3 +45,9 @@ DECL_PROGRAM_DESTROY(freetype)
|
||||
texture_font_delete(font);
|
||||
}
|
||||
|
||||
void
|
||||
program_freetype_switch_font(texture_font_t *font)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
|
BIN
src/program_freetype.o
Normal file
BIN
src/program_freetype.o
Normal file
Binary file not shown.
@ -23,7 +23,8 @@ DECL_PROGRAM_RENDER(triangles_plain)
|
||||
{
|
||||
if (programs[PROGRAM_TRIANGLES_PLAIN].vertex->indices->size == 0)
|
||||
return;
|
||||
vertex_buffer_render(programs[PROGRAM_TRIANGLES_PLAIN], GL_TRIANGLES);
|
||||
printf("Rendering triangles_plain (%d indices)\n", programs[PROGRAM_TRIANGLES_PLAIN].vertex->indices->size);
|
||||
vertex_buffer_render(programs[PROGRAM_TRIANGLES_PLAIN].vertex, GL_TRIANGLES);
|
||||
}
|
||||
|
||||
DECL_PROGRAM_UNLOAD(triangles_plain)
|
||||
|
BIN
src/program_triangles_plain.o
Normal file
BIN
src/program_triangles_plain.o
Normal file
Binary file not shown.
@ -23,7 +23,7 @@ DECL_PROGRAM_RENDER(triangles_textured)
|
||||
{
|
||||
if (programs[PROGRAM_TRIANGLES_TEXTURED].vertex->indices->size == 0)
|
||||
return;
|
||||
vertex_buffer_render(programs[PROGRAM_TRIANGLES_TEXTURED], GL_TRIANGLES);
|
||||
vertex_buffer_render(programs[PROGRAM_TRIANGLES_TEXTURED].vertex, GL_TRIANGLES);
|
||||
}
|
||||
|
||||
DECL_PROGRAM_UNLOAD(triangles_textured)
|
||||
|
BIN
src/program_triangles_textured.o
Normal file
BIN
src/program_triangles_textured.o
Normal file
Binary file not shown.
115
src/programs.c
115
src/programs.c
@ -7,3 +7,118 @@
|
||||
|
||||
#include "drawglx_internal.h"
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
GLuint compile_shader(const char *source, GLenum type)
|
||||
{
|
||||
GLint status;
|
||||
GLuint shader = glCreateShader(type);
|
||||
glShaderSource(shader, 1, &source, 0);
|
||||
glCompileShader(shader);
|
||||
glGetShaderiv(shader, GL_COMPILE_STATUS, &status);
|
||||
if (status == GL_FALSE)
|
||||
{
|
||||
char error_log[256];
|
||||
glGetShaderInfoLog(shader, sizeof(error_log), NULL, error_log);
|
||||
printf("GL Shader compilation error:\n%s\n", error_log);
|
||||
exit(1);
|
||||
}
|
||||
return shader;
|
||||
}
|
||||
|
||||
void
|
||||
setup_matrices(GLuint shader, int textures)
|
||||
{
|
||||
glUseProgram(shader);
|
||||
glUniformMatrix4fv(glGetUniformLocation(shader, "model"), 1, 0, ds.model.data);
|
||||
glUniformMatrix4fv(glGetUniformLocation(shader, "view"), 1, 0, ds.view.data);
|
||||
glUniformMatrix4fv(glGetUniformLocation(shader, "projection"), 1, 0, ds.projection.data);
|
||||
if (textures)
|
||||
glUniform1i(glGetUniformLocation(shader, "texture"), 0);
|
||||
glUseProgram(0);
|
||||
}
|
||||
|
||||
void
|
||||
program_init_inplace(struct program_t *program, const char *vertex_format, const char *shader_frag, const char *shader_vert, program_callback_empty_fn init, program_callback_empty_fn load, program_callback_empty_fn render, program_callback_empty_fn unload, program_callback_empty_fn destroy)
|
||||
{
|
||||
program->init = init;
|
||||
program->load = load;
|
||||
program->render = render;
|
||||
program->unload = unload;
|
||||
program->destroy = destroy;
|
||||
program->vertex = vertex_buffer_new(vertex_format);
|
||||
printf("vertex: %p\n", program->vertex);
|
||||
|
||||
program->shader = glCreateProgram();
|
||||
GLint status;
|
||||
|
||||
GLuint sh_frag = compile_shader(shader_frag, GL_FRAGMENT_SHADER);
|
||||
glAttachShader(program->shader, sh_frag);
|
||||
glDeleteShader(sh_frag);
|
||||
|
||||
GLuint sh_vert = compile_shader(shader_vert, GL_VERTEX_SHADER);
|
||||
glAttachShader(program->shader, sh_vert);
|
||||
glDeleteShader(sh_vert);
|
||||
|
||||
glLinkProgram(program->shader);
|
||||
glGetProgramiv(program->shader, GL_LINK_STATUS, &status);
|
||||
if (status == GL_FALSE)
|
||||
{
|
||||
char error_log[256];
|
||||
glGetShaderInfoLog(program->shader, sizeof(error_log), NULL, error_log);
|
||||
printf("GL Shader linking error:\n%s\n", error_log);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
program->vertex_size = program->vertex->vertices->item_size;
|
||||
}
|
||||
|
||||
#define PROGRAM_INIT_INPLACE(location, format, fragment, vertex, name) \
|
||||
program_init_inplace(location, format, fragment, vertex, PROGRAM_INIT(name), PROGRAM_LOAD(name), PROGRAM_RENDER(name), PROGRAM_UNLOAD(name), PROGRAM_DESTROY(name))
|
||||
|
||||
const char *shader_v2fc4f_vert =
|
||||
"uniform mat4 model;\n"
|
||||
"uniform mat4 view;\n"
|
||||
"uniform mat4 projection;\n"
|
||||
"attribute vec2 vertex;\n"
|
||||
"attribute vec4 color;\n"
|
||||
"void main()\n"
|
||||
"{\n"
|
||||
" gl_FrontColor = color;\n"
|
||||
" gl_Position = projection*(view*(model*vec4(vertex,0.0,1.0)));\n"
|
||||
"}";
|
||||
const char *shader_v2fc4f_frag =
|
||||
"void main() {\n"
|
||||
" gl_FragColor = gl_Color;\n"
|
||||
"}";
|
||||
const char *shader_v2ft2fc4f_vert =
|
||||
"uniform mat4 model;\n"
|
||||
"uniform mat4 view;\n"
|
||||
"uniform mat4 projection;\n"
|
||||
"attribute vec2 vertex;\n"
|
||||
"attribute vec2 tex_coord;\n"
|
||||
"attribute vec4 color;\n"
|
||||
"void main()\n"
|
||||
"{\n"
|
||||
" gl_TexCoord[0].xy = tex_coord.xy;\n"
|
||||
" gl_FrontColor = color;\n"
|
||||
" gl_Position = projection*(view*(model*vec4(vertex,0.0,1.0)));\n"
|
||||
"}";
|
||||
const char *shader_v2ft2fc4f_frag =
|
||||
"uniform sampler2D texture;\n"
|
||||
"void main()\n"
|
||||
"{\n"
|
||||
" gl_FragColor = texture2D(texture, gl_TexCoord[0].xy) * gl_Color;\n"
|
||||
"}";
|
||||
|
||||
void
|
||||
program_init_everything()
|
||||
{
|
||||
printf("Initializing programs\n");
|
||||
PROGRAM_INIT_INPLACE(&programs[PROGRAM_TRIANGLES_PLAIN], "vertex:2f,color:4f", shader_v2fc4f_frag, shader_v2fc4f_vert, triangles_plain);
|
||||
setup_matrices(programs[PROGRAM_TRIANGLES_PLAIN].shader, 0);
|
||||
PROGRAM_INIT_INPLACE(&programs[PROGRAM_TRIANGLES_TEXTURED], "vertex:2f,tex_coord:2f,color:4f", shader_v2ft2fc4f_frag, shader_v2ft2fc4f_vert, triangles_textured);
|
||||
setup_matrices(programs[PROGRAM_TRIANGLES_TEXTURED].shader, 1);
|
||||
PROGRAM_INIT_INPLACE(&programs[PROGRAM_FREETYPE], "vertex:2f,tex_coord:2f,color:4f", shader_v2ft2fc4f_frag, shader_v2ft2fc4f_vert, freetype);
|
||||
setup_matrices(programs[PROGRAM_FREETYPE].shader, 1);
|
||||
}
|
||||
|
BIN
src/programs.o
Normal file
BIN
src/programs.o
Normal file
Binary file not shown.
Loading…
x
Reference in New Issue
Block a user