From 12d80d643f77a0eab18cb1278793aee006bcf289 Mon Sep 17 00:00:00 2001 From: Leo Tenenbaum Date: Thu, 4 Feb 2021 16:56:28 -0500 Subject: started modern opengl --- Makefile | 6 +-- buffer.c | 7 ++-- gl.c | 128 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ main.c | 116 +++++++++++++++++++++++++++++++++++++++++++++++++++++---- text.c | 1 - 5 files changed, 243 insertions(+), 15 deletions(-) create mode 100644 gl.c 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 #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 -#include // 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. -- cgit v1.2.3