From 0771399895c28ae7245eb6356a5f01ae72678d12 Mon Sep 17 00:00:00 2001
From: torgo7 <khenstot@gmail.com>
Date: Mon, 26 Sep 2022 21:42:42 -0300
Subject: [PATCH] Added GLFW, refactored main.c, update viewport and resolution
 only on actual window change (#19).

---
 build.sh   |   2 +-
 src/main.c | 471 ++++++++++++++++++++++++++++-------------------------
 2 files changed, 250 insertions(+), 223 deletions(-)

diff --git a/build.sh b/build.sh
index f7ea77df..ce724b01 100755
--- a/build.sh
+++ b/build.sh
@@ -3,7 +3,7 @@
 set -xe
 
 CC="${CXX:-cc}"
-PKGS="sdl2 glew freetype2"
+PKGS="sdl2 glew freetype2 glfw3"
 CFLAGS="-Wall -Wextra -std=c11 -pedantic -ggdb"
 LIBS=-lm
 SRC="src/main.c src/la.c src/editor.c src/sdl_extra.c src/file.c src/gl_extra.c src/free_glyph.c src/cursor_renderer.c src/uniforms.c"
diff --git a/src/main.c b/src/main.c
index 8aa0b574..c197194d 100644
--- a/src/main.c
+++ b/src/main.c
@@ -7,6 +7,7 @@
 #include <GL/glew.h>
 #define GL_GLEXT_PROTOTYPES
 #include <SDL2/SDL_opengl.h>
+#include <GLFW/glfw3.h>
 
 #include <ft2build.h>
 #include FT_FREETYPE_H
@@ -51,127 +52,100 @@ void usage(FILE *stream)
 
 // TODO: Jump forward/backward by a word
 // TODO: Delete a word
-// TODO: Blinking cursor
 // TODO: Delete line
 // TODO: Split the line on Enter
 
-void MessageCallback(GLenum source,
-                     GLenum type,
-                     GLuint id,
-                     GLenum severity,
-                     GLsizei length,
-                     const GLchar* message,
-                     const void* userParam)
-{
-    (void) source;
-    (void) id;
-    (void) length;
-    (void) userParam;
-    fprintf(stderr, "GL CALLBACK: %s type = 0x%x, severity = 0x%x, message = %s\n",
-            (type == GL_DEBUG_TYPE_ERROR ? "** GL ERROR **" : ""),
-            type, severity, message);
-}
-
-static Free_Glyph_Buffer fgb = {0};
-static Cursor_Renderer cr = {0};
-
 #define FREE_GLYPH_FONT_SIZE 64
 #define ZOOM_OUT_GLYPH_THRESHOLD 30
 
-void render_editor_into_fgb(SDL_Window *window, Free_Glyph_Buffer *fgb, Cursor_Renderer *cr, Editor *editor)
-{
-    int w, h;
-    SDL_GetWindowSize(window, &w, &h);
-
-    float max_line_len = 0.0f;
-
-    free_glyph_buffer_use(fgb);
-    {
-        glUniform2f(fgb->uniforms[UNIFORM_SLOT_RESOLUTION], (float) w, (float) h);
-        glUniform1f(fgb->uniforms[UNIFORM_SLOT_TIME], (float) SDL_GetTicks() / 1000.0f);
-        glUniform2f(fgb->uniforms[UNIFORM_SLOT_CAMERA_POS], camera_pos.x, camera_pos.y);
-        glUniform1f(fgb->uniforms[UNIFORM_SLOT_CAMERA_SCALE], camera_scale);
+void input(SDL_Event event, Editor * editor,const Cursor_Renderer *cr, const char *file_path);
+FT_Library initializeFreeType();
+FT_Face initializeFace(FT_Library library, const char *const font_file_path);
+void setPixelSize(FT_Face face);
+void render_editor_into_fgb(GLFWwindow *window,Free_Glyph_Buffer *fgb, const Cursor_Renderer *cr, const Editor *editor);
+void reset_cursor_blink_timer(const Cursor_Renderer *cr);
+GLFWwindow * initializeSDL();
+void initializeGLEW();
+void resizeWindow(int windowWidth, int windowHeight);
+void messageCallback(GLenum source,GLenum type,GLuint id,GLenum severity,GLsizei length,const GLchar* message,const void* userParam);
+void windowSizeCallback(GLFWwindow* window, int width, int height);
+void keyboardCharacterCallback(GLFWwindow* window, unsigned int codepoint);
+void cursorPositionCallback(GLFWwindow* window, double xpos, double ypos);
+void keyCallback(GLFWwindow* window, int key, int scancode, int action, int mods);
 
-        free_glyph_buffer_clear(fgb);
+static Cursor_Renderer cr = {0};
+const char *file_path = NULL;
 
-        {
-            for (size_t row = 0; row < editor->size; ++row) {
-                const Line *line = editor->lines + row;
+int main(int argc, char **argv){
+    static Free_Glyph_Buffer fgb = {0};
+    FT_Library library = initializeFreeType();
+    const char *const font_file_path = "./VictorMono-Regular.ttf";
+    FT_Face face = initializeFace(library,font_file_path);
+    setPixelSize(face);
 
-                const Vec2f begin = vec2f(0, -(float)row * FREE_GLYPH_FONT_SIZE);
-                Vec2f end = begin;
-                free_glyph_buffer_render_line_sized(
-                    fgb, line->chars, line->size,
-                    &end,
-                    vec4fs(1.0f), vec4fs(0.0f));
-                // TODO: the max_line_len should be calculated based on what's visible on the screen right now
-                float line_len = fabsf(end.x - begin.x);
-                if (line_len > max_line_len) {
-                    max_line_len = line_len;
-                }
-            }
+    if (argc > 1) {
+        file_path = argv[1];
+    }
+    if (file_path) {
+        FILE *file = fopen(file_path, "r");
+        if (file != NULL) {
+            editor_load_from_file(&editor, file);
+            fclose(file);
         }
-
-        free_glyph_buffer_sync(fgb);
-        free_glyph_buffer_draw(fgb);
     }
 
-    Vec2f cursor_pos = vec2fs(0.0f);
-    {
-        cursor_pos.y = -(float) editor->cursor_row * FREE_GLYPH_FONT_SIZE;
+    GLFWwindow *window = initializeSDL();
+    initializeGLEW();
 
-        if (editor->cursor_row < editor->size) {
-            Line *line = &editor->lines[editor->cursor_row];
-            cursor_pos.x = free_glyph_buffer_cursor_pos(fgb, line->chars, line->size, vec2f(0.0, cursor_pos.y), editor->cursor_col);
-        }
-    }
+    free_glyph_buffer_init(&fgb,
+                           face,
+                           "./shaders/free_glyph.vert",
+                           "./shaders/free_glyph.frag");
+    cursor_renderer_init(&cr,
+                         "./shaders/cursor.vert",
+                         "./shaders/cursor.frag");
 
-    cursor_renderer_use(cr);
-    {
-        glUniform2f(cr->uniforms[UNIFORM_SLOT_RESOLUTION], (float) w, (float) h);
-        glUniform1f(cr->uniforms[UNIFORM_SLOT_TIME], (float) SDL_GetTicks() / 1000.0f);
-        glUniform2f(cr->uniforms[UNIFORM_SLOT_CAMERA_POS], camera_pos.x, camera_pos.y);
-        glUniform1f(cr->uniforms[UNIFORM_SLOT_CAMERA_SCALE], camera_scale);
-        glUniform1f(cr->uniforms[UNIFORM_SLOT_CURSOR_HEIGHT], FREE_GLYPH_FONT_SIZE);
 
-        cursor_renderer_move_to(cr, cursor_pos);
-        cursor_renderer_draw();
-    }
+    glfwSetInputMode(window, GLFW_LOCK_KEY_MODS, GLFW_TRUE);
+    glfwSetWindowSizeCallback(window, windowSizeCallback);
+    glfwSetKeyCallback(window, keyCallback);
+    glfwSetCharCallback(window, keyboardCharacterCallback);
+    glfwSetCursorPosCallback(window, cursorPositionCallback);
+    
+    while (!glfwWindowShouldClose(window)) {
+        const Uint32 start = SDL_GetTicks();
 
-    {
-        float target_scale = 3.0f;
-        if (max_line_len > 0.0f) {
-            target_scale = SCREEN_WIDTH / max_line_len;
-        }
+        glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
+        glClear(GL_COLOR_BUFFER_BIT);
 
-        if (target_scale > 3.0f) {
-            target_scale = 3.0f;
-        }
+        render_editor_into_fgb(window,&fgb, &cr, &editor);
 
-        camera_vel = vec2f_mul(
-                         vec2f_sub(cursor_pos, camera_pos),
-                         vec2fs(2.0f));
-        camera_scale_vel = (target_scale - camera_scale) * 2.0f;
+        glfwSwapBuffers(window);
+        glfwPollEvents();
 
-        camera_pos = vec2f_add(camera_pos, vec2f_mul(camera_vel, vec2fs(DELTA_TIME)));
-        camera_scale = camera_scale + camera_scale_vel * DELTA_TIME;
+        const Uint32 duration = SDL_GetTicks() - start;
+        const Uint32 delta_time_ms = 1000 / FPS;
+        if (duration < delta_time_ms) {
+            SDL_Delay(delta_time_ms - duration);
+        }
     }
+    glfwTerminate();
+    return 0;
 }
 
-int main(int argc, char **argv)
-{
+FT_Library initializeFreeType(){
     FT_Library library = {0};
-
     FT_Error error = FT_Init_FreeType(&library);
     if (error) {
-        fprintf(stderr, "ERROR: could initialize FreeType2 library\n");
+        fprintf(stderr, "ERROR: could not initialize FreeType2 library\n");
         exit(1);
     }
+    return library;
+}
 
-    const char *const font_file_path = "./VictorMono-Regular.ttf";
-
+FT_Face initializeFace(FT_Library library, const char *const font_file_path){
     FT_Face face;
-    error = FT_New_Face(library, font_file_path, 0, &face);
+    FT_Error error = FT_New_Face(library, font_file_path, 0, &face);
     if (error == FT_Err_Unknown_File_Format) {
         fprintf(stderr, "ERROR: `%s` has an unknown format\n", font_file_path);
         exit(1);
@@ -179,52 +153,50 @@ int main(int argc, char **argv)
         fprintf(stderr, "ERROR: could not load file `%s`\n", font_file_path);
         exit(1);
     }
+    return face;
+}
 
+void setPixelSize(FT_Face face){
     FT_UInt pixel_size = FREE_GLYPH_FONT_SIZE;
     // TODO: FT_Set_Pixel_Sizes does not produce good looking results
     // We need to use something like FT_Set_Char_Size and properly set the device resolution
-    error = FT_Set_Pixel_Sizes(face, 0, pixel_size);
+    FT_Error error = FT_Set_Pixel_Sizes(face, 0, pixel_size);
     if (error) {
         fprintf(stderr, "ERROR: could not set pixel size to %u\n", pixel_size);
         exit(1);
     }
+}
 
-    const char *file_path = NULL;
-
-    if (argc > 1) {
-        file_path = argv[1];
-    }
-
-    if (file_path) {
-        FILE *file = fopen(file_path, "r");
-        if (file != NULL) {
-            editor_load_from_file(&editor, file);
-            fclose(file);
-        }
+GLFWwindow * initializeSDL(){
+    if (!glfwInit()){
+        fprintf(stderr, "ERROR: not could initialize GLFW3\n");
+        exit(1);
     }
-
-    scc(SDL_Init(SDL_INIT_VIDEO));
-
-    SDL_Window *window =
-        scp(SDL_CreateWindow("Text Editor",
-                             0, 0,
-                             SCREEN_WIDTH, SCREEN_HEIGHT,
-                             SDL_WINDOW_RESIZABLE | SDL_WINDOW_OPENGL));
-
+    GLFWwindow* window = glfwCreateWindow(SCREEN_WIDTH, SCREEN_HEIGHT, "Text Editor", NULL, NULL);;
+    if (!window)
     {
-        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);
-
-        int major;
-        int minor;
-        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);
+        fprintf(stderr, "ERROR: not could initialize GLFW3 Window\n");
+        glfwTerminate();
+        exit(1);
     }
 
-    scp(SDL_GL_CreateContext(window));
+    scc(SDL_Init(SDL_INIT_VIDEO));
+    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);
+
+    int major;
+    int minor;
+    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);
+    glEnable(GL_BLEND);
+    glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
+    glfwMakeContextCurrent(window);
+    return window;
+}
 
+void initializeGLEW(){
     if (GLEW_OK != glewInit()) {
         fprintf(stderr, "Could not initialize GLEW!");
         exit(1);
@@ -239,132 +211,187 @@ int main(int argc, char **argv)
         fprintf(stderr, "ARB_instanced_arrays is not supported; game may not work properly!!\n");
         exit(1);
     }
-
-    glEnable(GL_BLEND);
-    glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
-
     if (GLEW_ARB_debug_output) {
         glEnable(GL_DEBUG_OUTPUT);
-        glDebugMessageCallback(MessageCallback, 0);
+        glDebugMessageCallback(messageCallback, 0);
     } else {
         fprintf(stderr, "WARNING! GLEW_ARB_debug_output is not available");
     }
+}
 
+void keyboardCharacterCallback(GLFWwindow* window, unsigned int unicodeCodepoint){
+    (void) window;
+    // TODO: UTF-8/UTF-16 support
+    const char text = (unsigned char) unicodeCodepoint;
+    editor_insert_text_before_cursor(&editor,&text);
+    cursor_renderer_use(&cr);
+    reset_cursor_blink_timer(&cr);
+}
+void cursorPositionCallback(GLFWwindow* window, double xpos, double ypos){
+    (void) window;
+    (void) xpos;
+    (void) ypos;
+    // TODO: cursor moving with mouse?
+}
 
-    free_glyph_buffer_init(&fgb,
-                           face,
-                           "./shaders/free_glyph.vert",
-                           "./shaders/free_glyph.frag");
-    cursor_renderer_init(&cr,
-                         "./shaders/cursor.vert",
-                         "./shaders/cursor.frag");
-
-    bool quit = false;
-    while (!quit) {
-        const Uint32 start = SDL_GetTicks();
-        SDL_Event event = {0};
-        while (SDL_PollEvent(&event)) {
-            switch (event.type) {
-            case SDL_QUIT: {
-                quit = true;
-            }
+void keyCallback(GLFWwindow* window, int key, int scancode, int action, int mods){
+    (void) window;
+    (void) scancode;
+    (void) mods;
+    if(action == GLFW_PRESS || action == GLFW_REPEAT){
+        switch(key){
+            default:
             break;
-
-            case SDL_KEYDOWN: {
-                switch (event.key.keysym.sym) {
-                case SDLK_BACKSPACE: {
-                    editor_backspace(&editor);
+            case GLFW_KEY_UP:
+                if (editor.cursor_row > 0) {
+                    editor.cursor_row -= 1;
+                }
+                cursor_renderer_use(&cr);
+                reset_cursor_blink_timer(&cr);
+            break;
+            case GLFW_KEY_DOWN:
+                editor.cursor_row += 1;
+                cursor_renderer_use(&cr);
+                reset_cursor_blink_timer(&cr);
+            break;
+            case GLFW_KEY_LEFT:
+                if (editor.cursor_col > 0) {
+                    editor.cursor_col -= 1;
                     cursor_renderer_use(&cr);
-                    glUniform1f(cr.uniforms[UNIFORM_SLOT_LAST_STROKE], (float) SDL_GetTicks() / 1000.0f);
+                    reset_cursor_blink_timer(&cr);
                 }
-                break;
+            break;
+            case GLFW_KEY_RIGHT:
+                editor.cursor_col += 1;
+                cursor_renderer_use(&cr);
+                reset_cursor_blink_timer(&cr);
+            break;
 
-                case SDLK_F2: {
-                    if (file_path) {
-                        editor_save_to_file(&editor, file_path);
-                    }
+            case GLFW_KEY_BACKSPACE:
+                editor_backspace(&editor);
+                cursor_renderer_use(&cr);
+                reset_cursor_blink_timer(&cr);
+            break;
+            case GLFW_KEY_ENTER:
+                editor_insert_new_line(&editor);
+                cursor_renderer_use(&cr);
+                reset_cursor_blink_timer(&cr);
+            break;
+            case GLFW_KEY_F2:
+                if (file_path != NULL && *file_path) {
+                    editor_save_to_file(&editor, file_path);
                 }
-                break;
+            break;
+            case GLFW_KEY_DELETE:
+                editor_delete(&editor);
+                cursor_renderer_use(&cr);
+                reset_cursor_blink_timer(&cr);
+            break;
+        }
+    }
+}
 
-                case SDLK_RETURN: {
-                    editor_insert_new_line(&editor);
-                    cursor_renderer_use(&cr);
-                    glUniform1f(cr.uniforms[UNIFORM_SLOT_LAST_STROKE], (float) SDL_GetTicks() / 1000.0f);
-                }
-                break;
+void reset_cursor_blink_timer(const Cursor_Renderer *cr){
+    glUniform1f(cr->uniforms[UNIFORM_SLOT_LAST_STROKE], (float) SDL_GetTicks() / 1000.0f);
+}
 
-                case SDLK_DELETE: {
-                    editor_delete(&editor);
-                    cursor_renderer_use(&cr);
-                    glUniform1f(cr.uniforms[UNIFORM_SLOT_LAST_STROKE], (float) SDL_GetTicks() / 1000.0f);
-                }
-                break;
+void render_editor_into_fgb(GLFWwindow *window,Free_Glyph_Buffer *fgb, const Cursor_Renderer *cr, const Editor *editor)
+{
+    int windowWidth, windowHeight;
+    glfwGetWindowSize(window, &windowWidth, &windowHeight);        
+    float max_line_len = 0.0f;
 
-                case SDLK_UP: {
-                    if (editor.cursor_row > 0) {
-                        editor.cursor_row -= 1;
-                    }
-                    cursor_renderer_use(&cr);
-                    glUniform1f(cr.uniforms[UNIFORM_SLOT_LAST_STROKE], (float) SDL_GetTicks() / 1000.0f);
-                }
-                break;
+    free_glyph_buffer_use(fgb);
+    {
+        glUniform2f(fgb->uniforms[UNIFORM_SLOT_RESOLUTION], (float) windowWidth, (float) windowHeight);
+        glUniform1f(fgb->uniforms[UNIFORM_SLOT_TIME], (float) SDL_GetTicks() / 1000.0f);
+        glUniform2f(fgb->uniforms[UNIFORM_SLOT_CAMERA_POS], camera_pos.x, camera_pos.y);
+        glUniform1f(fgb->uniforms[UNIFORM_SLOT_CAMERA_SCALE], camera_scale);
 
-                case SDLK_DOWN: {
-                    editor.cursor_row += 1;
-                    cursor_renderer_use(&cr);
-                    glUniform1f(cr.uniforms[UNIFORM_SLOT_LAST_STROKE], (float) SDL_GetTicks() / 1000.0f);
-                }
-                break;
-
-                case SDLK_LEFT: {
-                    if (editor.cursor_col > 0) {
-                        editor.cursor_col -= 1;
-                        cursor_renderer_use(&cr);
-                        glUniform1f(cr.uniforms[UNIFORM_SLOT_LAST_STROKE], (float) SDL_GetTicks() / 1000.0f);
-                    }
-                }
-                break;
+        free_glyph_buffer_clear(fgb);
 
-                case SDLK_RIGHT: {
-                    editor.cursor_col += 1;
-                    cursor_renderer_use(&cr);
-                    glUniform1f(cr.uniforms[UNIFORM_SLOT_LAST_STROKE], (float) SDL_GetTicks() / 1000.0f);
+        {
+            for (size_t row = 0; row < editor->size; ++row) {
+                const Line *line = editor->lines + row;
 
+                const Vec2f begin = vec2f(0, -(float)row * FREE_GLYPH_FONT_SIZE);
+                Vec2f end = begin;
+                free_glyph_buffer_render_line_sized(
+                    fgb, line->chars, line->size,
+                    &end,
+                    vec4fs(1.0f), vec4fs(0.0f));
+                // TODO: the max_line_len should be calculated based on what's visible on the screen right now
+                float line_len = fabsf(end.x - begin.x);
+                if (line_len > max_line_len) {
+                    max_line_len = line_len;
                 }
-                break;
-                }
-            }
-            break;
-
-            case SDL_TEXTINPUT: {
-                editor_insert_text_before_cursor(&editor, event.text.text);
-                cursor_renderer_use(&cr);
-                glUniform1f(cr.uniforms[UNIFORM_SLOT_LAST_STROKE], (float) SDL_GetTicks() / 1000.0f);
-            }
-            break;
             }
         }
 
-        {
-            int w, h;
-            SDL_GetWindowSize(window, &w, &h);
-            // TODO(#19): update the viewport and the resolution only on actual window change
-            glViewport(0, 0, w, h);
+        free_glyph_buffer_sync(fgb);
+        free_glyph_buffer_draw(fgb);
+    }
+
+    Vec2f cursor_pos = vec2fs(0.0f);
+    {
+        cursor_pos.y = -(float) editor->cursor_row * FREE_GLYPH_FONT_SIZE;
+
+        if (editor->cursor_row < editor->size) {
+            const Line *line = &editor->lines[editor->cursor_row];
+            cursor_pos.x = free_glyph_buffer_cursor_pos(fgb, line->chars, line->size, vec2f(0.0, cursor_pos.y), editor->cursor_col);
         }
+    }
 
-        glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
-        glClear(GL_COLOR_BUFFER_BIT);
+    cursor_renderer_use(cr);
+    {
+        glUniform2f(cr->uniforms[UNIFORM_SLOT_RESOLUTION], (float) windowWidth, (float) windowHeight);
+        glUniform1f(cr->uniforms[UNIFORM_SLOT_TIME], (float) SDL_GetTicks() / 1000.0f);
+        glUniform2f(cr->uniforms[UNIFORM_SLOT_CAMERA_POS], camera_pos.x, camera_pos.y);
+        glUniform1f(cr->uniforms[UNIFORM_SLOT_CAMERA_SCALE], camera_scale);
+        glUniform1f(cr->uniforms[UNIFORM_SLOT_CURSOR_HEIGHT], FREE_GLYPH_FONT_SIZE);
 
-        render_editor_into_fgb(window, &fgb, &cr, &editor);
+        cursor_renderer_move_to(cr, cursor_pos);
+        cursor_renderer_draw();
+    }
 
-        SDL_GL_SwapWindow(window);
+    {
+        float target_scale = 3.0f;
+        if (max_line_len > 0.0f) {
+            target_scale = SCREEN_WIDTH / max_line_len;
+        }
 
-        const Uint32 duration = SDL_GetTicks() - start;
-        const Uint32 delta_time_ms = 1000 / FPS;
-        if (duration < delta_time_ms) {
-            SDL_Delay(delta_time_ms - duration);
+        if (target_scale > 3.0f) {
+            target_scale = 3.0f;
         }
+
+        camera_vel = vec2f_mul(
+                         vec2f_sub(cursor_pos, camera_pos),
+                         vec2fs(2.0f));
+        camera_scale_vel = (target_scale - camera_scale) * 2.0f;
+
+        camera_pos = vec2f_add(camera_pos, vec2f_mul(camera_vel, vec2fs(DELTA_TIME)));
+        camera_scale = camera_scale + camera_scale_vel * DELTA_TIME;
     }
+}
 
-    return 0;
+void messageCallback(GLenum source,
+                     GLenum type,
+                     GLuint id,
+                     GLenum severity,
+                     GLsizei length,
+                     const GLchar* message,
+                     const void* userParam)
+{
+    (void) source;
+    (void) id;
+    (void) length;
+    (void) userParam;
+    fprintf(stderr, "GL CALLBACK: %s type = 0x%x, severity = 0x%x, message = %s\n",
+            (type == GL_DEBUG_TYPE_ERROR ? "** GL ERROR **" : ""),
+            type, severity, message);
 }
+
+void windowSizeCallback(GLFWwindow* window, int windowWidth, int windowHeight){
+    (void) window;
+    glViewport(0, 0, windowWidth, windowHeight);
+}
\ No newline at end of file