summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Makefile6
-rw-r--r--buffer.c7
-rw-r--r--gl.c128
-rw-r--r--main.c116
-rw-r--r--text.c1
5 files changed, 243 insertions, 15 deletions
diff --git a/Makefile b/Makefile
index e3823f3..23fddd6 100644
--- a/Makefile
+++ b/Makefile
@@ -7,14 +7,12 @@ PROFILE_CFLAGS=$(ALL_CFLAGS) -O3 -DPROFILE=1
GLOBAL_DATA_DIR=/usr/share/ted
LOCAL_DATA_DIR=/home/`logname`/.local/share/ted
INSTALL_BIN_DIR=/usr/bin
-ted: *.[ch] text.o
- $(CC) main.c text.o -o ted $(DEBUG_CFLAGS) $(LIBS)
+ted: *.[ch]
+ $(CC) main.c -o ted $(DEBUG_CFLAGS) $(LIBS)
release: *.[ch]
$(CC) main.c -o ted $(RELEASE_CFLAGS) $(LIBS)
profile: *.[ch]
$(CC) main.c -o ted $(PROFILE_CFLAGS) $(LIBS)
-text.o: text.c text.h base.h lib/stb_truetype.h
- $(CC) text.c -c -o $@ $(DEBUG_CFLAGS)
clean:
rm -f ted *.o
install: release
diff --git a/buffer.c b/buffer.c
index ec2b748..1402718 100644
--- a/buffer.c
+++ b/buffer.c
@@ -1788,9 +1788,10 @@ Status buffer_load_file(TextBuffer *buffer, char const *filename) {
void buffer_reload(TextBuffer *buffer) {
if (buffer->filename && !buffer_is_untitled(buffer)) {
BufferPos cursor_pos = buffer->cursor_pos;
- buffer_load_file(buffer, buffer->filename);
- buffer->cursor_pos = cursor_pos;
- buffer_validate_cursor(buffer);
+ if (buffer_load_file(buffer, buffer->filename)) {
+ buffer->cursor_pos = cursor_pos;
+ buffer_validate_cursor(buffer);
+ }
}
}
diff --git a/gl.c b/gl.c
new file mode 100644
index 0000000..6e61742
--- /dev/null
+++ b/gl.c
@@ -0,0 +1,128 @@
+#include "lib/glcorearb.h"
+
+// macro trickery to avoid having to write everything twice
+#define gl_for_each_proc(do)\
+ do(CREATESHADER, CreateShader)\
+ do(DELETESHADER, DeleteShader)\
+ do(CREATEPROGRAM, CreateProgram)\
+ do(SHADERSOURCE, ShaderSource)\
+ do(GETSHADERIV, GetShaderiv)\
+ do(GETSHADERINFOLOG, GetShaderInfoLog)\
+ do(COMPILESHADER, CompileShader)\
+ do(CREATEPROGRAM, CreateProgram)\
+ do(DELETEPROGRAM, DeleteProgram)\
+ do(ATTACHSHADER, AttachShader)\
+ do(LINKPROGRAM, LinkProgram)\
+ do(GETPROGRAMIV, GetProgramiv)\
+ do(GETPROGRAMINFOLOG, GetProgramInfoLog)\
+ do(USEPROGRAM, UseProgram)\
+ do(GETATTRIBLOCATION, GetAttribLocation)\
+ do(GETUNIFORMLOCATION, GetUniformLocation)\
+ do(GENBUFFERS, GenBuffers)\
+ do(DELETEBUFFERS, DeleteBuffers)\
+ do(BINDBUFFER, BindBuffer)\
+ do(BUFFERDATA, BufferData)\
+ do(VERTEXATTRIBPOINTER, VertexAttribPointer)\
+ do(ENABLEVERTEXATTRIBARRAY, EnableVertexAttribArray)\
+ do(DISABLEVERTEXATTRIBARRAY, DisableVertexAttribArray)\
+ do(GENVERTEXARRAYS, GenVertexArrays)\
+ do(BINDVERTEXARRAY, BindVertexArray)\
+ do(UNIFORM1F, Uniform1f)\
+ do(UNIFORM2F, Uniform2f)\
+ do(UNIFORM3F, Uniform3f)\
+ do(UNIFORM4F, Uniform4f)\
+ do(UNIFORM1I, Uniform1i)\
+ do(UNIFORM2I, Uniform2i)\
+ do(UNIFORM3I, Uniform3i)\
+ do(UNIFORM4I, Uniform4i)\
+ do(UNIFORMMATRIX4FV, UniformMatrix4fv)\
+ do(DEBUGMESSAGECALLBACK, DebugMessageCallback)\
+ do(DEBUGMESSAGECONTROL, DebugMessageControl)\
+
+#define gl_declare_proc(upper, lower) static PFNGL##upper##PROC gl##lower;
+gl_for_each_proc(gl_declare_proc)
+#undef gl_declare_proc
+
+// set by main()
+static int gl_version_major;
+static int gl_version_minor;
+
+static void gl_get_procs(void) {
+ #define gl_get_proc(upper, lower) gl##lower = (PFNGL##upper##PROC)SDL_GL_GetProcAddress("gl" #lower);
+ gl_for_each_proc(gl_get_proc)
+ #undef gl_get_proc
+}
+
+// compile a GLSL shader
+static GLuint gl_compile_shader(char const *code, GLenum shader_type) {
+ GLuint shader = glCreateShader(shader_type);
+ glShaderSource(shader, 1, &code, NULL);
+ glCompileShader(shader);
+ GLint status = 0;
+ glGetShaderiv(shader, GL_COMPILE_STATUS, &status);
+ if (status == GL_FALSE) {
+ char log[1024] = {0};
+ glGetShaderInfoLog(shader, sizeof log - 1, NULL, log);
+ debug_println("Error compiling shader: %s", log);
+ return 0;
+ }
+ return shader;
+}
+
+// link together GL shaders
+static GLuint gl_link_program(GLuint *shaders, size_t count) {
+ GLuint program = glCreateProgram();
+ if (program) {
+ for (size_t i = 0; i < count; ++i) {
+ if (!shaders[i]) {
+ glDeleteProgram(program);
+ return 0;
+ }
+ glAttachShader(program, shaders[i]);
+ }
+ glLinkProgram(program);
+ GLint status = 0;
+ glGetProgramiv(program, GL_LINK_STATUS, &status);
+ if (status == GL_FALSE) {
+ char log[1024] = {0};
+ glGetProgramInfoLog(program, sizeof log - 1, NULL, log);
+ debug_println("Error linking shaders: %s", log);
+ glDeleteProgram(program);
+ return 0;
+ }
+ }
+ return program;
+}
+
+static GLuint gl_compile_and_link_shaders(char const *vshader_code, char const *fshader_code) {
+ GLuint shaders[2];
+ shaders[0] = gl_compile_shader(vshader_code, GL_VERTEX_SHADER);
+ shaders[1] = gl_compile_shader(fshader_code, GL_FRAGMENT_SHADER);
+ GLuint program = gl_link_program(shaders, 2);
+ if (shaders[0]) glDeleteShader(shaders[0]);
+ if (shaders[1]) glDeleteShader(shaders[1]);
+ if (program) {
+ debug_print("Successfully linked program %u.\n", program);
+ }
+ return program;
+}
+
+static GLuint gl_attrib_loc(GLuint program, char const *attrib) {
+ GLint loc = glGetAttribLocation(program, attrib);
+ if (loc == -1) {
+ debug_print("Couldn't find vertex attribute %s.\n", attrib);
+ return 0;
+ }
+ return (GLuint)loc;
+}
+
+static GLint gl_uniform_loc(GLuint program, char const *uniform) {
+ GLint loc = glGetUniformLocation(program, uniform);
+ if (loc == -1) {
+ debug_print("Couldn't find uniform: %s.\n", uniform);
+ return -1;
+ }
+ return loc;
+}
+
+
diff --git a/main.c b/main.c
index e4445b8..57b3d4e 100644
--- a/main.c
+++ b/main.c
@@ -19,13 +19,10 @@ no_warn_end
#if _WIN32
#include <shellapi.h>
#endif
+#include "gl.c"
#include "unicode.h"
-#if DEBUG
-#include "text.h"
-#else
#include "text.c"
-#endif
#include "util.c"
#define MATH_GL
#include "math.c"
@@ -37,6 +34,7 @@ no_warn_end
#error "Unrecognized operating system."
#endif
+
#include "command.h"
#include "colors.h"
#include "time.c"
@@ -84,6 +82,15 @@ static Rect error_box_rect(Ted *ted) {
V2(menu_get_width(ted), 3 * char_height + 2 * padding));
}
+#if DEBUG
+static void APIENTRY gl_message_callback(GLenum source, GLenum type, unsigned int id, GLenum severity,
+ GLsizei length, const char *message, const void *userParam) {
+ (void)source; (void)type; (void)id; (void)length; (void)userParam;
+ if (severity == GL_DEBUG_SEVERITY_NOTIFICATION) return;
+ debug_println("Message from OpenGL: %s.", message);
+}
+#endif
+
#if _WIN32
INT WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,
PSTR lpCmdLine, INT nCmdShow) {
@@ -237,15 +244,103 @@ int main(int argc, char **argv) {
} // if we can't find the icon file, it's no big deal
}
- SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, 2);
- SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, 0);
+ gl_version_major = 4;
+ gl_version_minor = 3;
+ SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, gl_version_major);
+ SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, gl_version_minor);
+#if DEBUG
+ SDL_GL_SetAttribute(SDL_GL_CONTEXT_FLAGS, SDL_GL_CONTEXT_DEBUG_FLAG);
+#endif
SDL_GLContext *glctx = SDL_GL_CreateContext(window);
if (!glctx) {
- die("%s", SDL_GetError());
+ debug_println("Couldn't get GL 4.3 context. Falling back to 2.0.");
+ gl_version_major = 2;
+ gl_version_minor = 0;
+ SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, gl_version_major);
+ SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, gl_version_minor);
+ SDL_GL_SetAttribute(SDL_GL_CONTEXT_FLAGS, 0);
+ glctx = SDL_GL_CreateContext(window);
+ if (!glctx)
+ die("%s", SDL_GetError());
+ }
+ gl_get_procs();
+
+#if DEBUG
+ if (gl_version_major * 100 + gl_version_minor >= 403) {
+ GLint flags = 0;
+ glGetIntegerv(GL_CONTEXT_FLAGS, &flags);
+ glEnable(GL_DEBUG_OUTPUT);
+ glEnable(GL_DEBUG_OUTPUT_SYNCHRONOUS);
+ if (flags & GL_CONTEXT_FLAG_DEBUG_BIT) {
+ // set up debug message callback
+ glDebugMessageCallback(gl_message_callback, NULL);
+ glDebugMessageControl(GL_DONT_CARE, GL_DONT_CARE, GL_DONT_CARE, 0, NULL, GL_TRUE);
+ }
}
+#endif
SDL_GL_SetSwapInterval(1); // vsync
+ char const *vshader_code = "#version 110\n\
+attribute vec2 v_pos;\n\
+uniform vec2 window_size;\n\
+void main() {\n\
+ float x = v_pos.x / window_size.x * 2.0 - 1.0;\n\
+ float y = 1.0 - v_pos.y / window_size.y * 2.0;\n\
+ gl_Position = vec4(x, y, 0.0, 1.0);\n\
+}\n\
+";
+ char const *fshader_code = "#version 110\n\
+uniform vec4 color;\n\
+void main() {\n\
+ gl_FragColor = color;\n\
+}\n\
+";
+ float vertices[][2] = {
+ {0, 0},
+ {50, 0},
+ {0, 50},
+ };
+ GLuint program = gl_compile_and_link_shaders(vshader_code, fshader_code);
+ GLuint v_pos = gl_attrib_loc(program, "v_pos");
+ GLint u_window_size = gl_uniform_loc(program, "window_size");
+ GLint u_color = gl_uniform_loc(program, "color");
+
+ GLuint vbo = 0, vao = 0;
+ glGenBuffers(1, &vbo);
+ glGenVertexArrays(1, &vao);
+
+ glBindVertexArray(vao);
+ glBindBuffer(GL_ARRAY_BUFFER, vbo);
+ glBufferData(GL_ARRAY_BUFFER, sizeof vertices, vertices, GL_STATIC_DRAW);
+ glVertexAttribPointer(v_pos, 2, GL_FLOAT, 0, 2 * sizeof(float), (void *)0);
+ glEnableVertexAttribArray(v_pos);
+ glBindVertexArray(0);
+
+ while (1) {
+ int w, h;
+ SDL_GetWindowSize(window, &w, &h);
+
+ SDL_Event event;
+ while (SDL_PollEvent(&event)) if (event.type == SDL_QUIT) return 0;
+
+ glViewport(0, 0, w, h);
+ glClearColor(0,0,0,1);
+ glClear(GL_COLOR_BUFFER_BIT);
+
+
+ glUseProgram(program);
+ glUniform4f(u_color, 1, 1, 0, 1);
+ glUniform2f(u_window_size, (float)w, (float)h);
+ glBindVertexArray(vao);
+
+ glDrawArrays(GL_TRIANGLES, 0, 3);
+ SDL_GL_SwapWindow(window);
+ }
+
+ return 0;
+
+
ted_load_fonts(ted);
if (ted_haserr(ted))
die("Error loading font: %s", ted_geterr(ted));
@@ -339,6 +434,9 @@ int main(int argc, char **argv) {
case SDL_QUIT:
command_execute(ted, CMD_QUIT, 1);
break;
+ int w, h;
+ SDL_GetWindowSize(window, &w, &h);
+
case SDL_MOUSEWHEEL: {
// scroll with mouse wheel
Sint32 dx = event.wheel.x, dy = -event.wheel.y;
@@ -398,6 +496,7 @@ int main(int argc, char **argv) {
}
}
ted->drag_buffer = buffer;
+
}
}
} break;
@@ -549,6 +648,9 @@ int main(int argc, char **argv) {
}
for (u16 i = 0; i < TED_MAX_BUFFERS; ++i) {
TextBuffer *buffer = &ted->buffers[i];
+ int w, h;
+ SDL_GetWindowSize(window, &w, &h);
+
if (buffer_haserr(buffer)) {
ted_seterr_to_buferr(ted, buffer);
buffer_clearerr(buffer);
diff --git a/text.c b/text.c
index 7bafd14..c2554e8 100644
--- a/text.c
+++ b/text.c
@@ -7,7 +7,6 @@ no_warn_start
#include "lib/stb_truetype.h"
no_warn_end
#include <stdlib.h>
-#include <GL/gl.h>
// We split up code points into a bunch of pages, so we don't have to load all of the font at
// once into one texture.