Wed, 01 Nov 2023 20:09:49 +0100
move window related stuff to its own unit
src/Makefile | file | annotate | diff | comparison | revisions | |
src/ascension/core.h | file | annotate | diff | comparison | revisions | |
src/ascension/datatypes.h | file | annotate | diff | comparison | revisions | |
src/ascension/utils.h | file | annotate | diff | comparison | revisions | |
src/ascension/window.h | file | annotate | diff | comparison | revisions | |
src/core.c | file | annotate | diff | comparison | revisions | |
src/window.c | file | annotate | diff | comparison | revisions | |
test/Makefile | file | annotate | diff | comparison | revisions | |
test/sandbox.c | file | annotate | diff | comparison | revisions |
1.1 --- a/src/Makefile Mon Oct 30 18:54:16 2023 +0100 1.2 +++ b/src/Makefile Wed Nov 01 20:09:49 2023 +0100 1.3 @@ -27,21 +27,25 @@ 1.4 1.5 BUILD_DIR=../build/lib 1.6 1.7 -SRC = core.c 1.8 +SRC = core.c window.c 1.9 1.10 OBJ = $(SRC:%.c=$(BUILD_DIR)/%.o) 1.11 1.12 all: $(BUILD_DIR)/libascension.a FORCE 1.13 - echo "You have successfully ascended." 1.14 + @echo "You have successfully ascended." 1.15 1.16 $(BUILD_DIR)/libascension.a: $(OBJ) 1.17 - echo "Creating library..." 1.18 + @echo "Creating library..." 1.19 $(AR) $(ARFLAGS) $@ $^ 1.20 1.21 FORCE: 1.22 1.23 -$(BUILD_DIR)/core.o: core.c ascension/core.h ascension/datatypes.h \ 1.24 - ascension/utils.h 1.25 - echo "Compiling $<" 1.26 +$(BUILD_DIR)/core.o: core.c ascension/core.h ascension/datatypes.h 1.27 + @echo "Compiling $<" 1.28 $(CC) -o $@ $(CFLAGS) -c $< 1.29 1.30 +$(BUILD_DIR)/window.o: window.c ascension/window.h ascension/core.h \ 1.31 + ascension/datatypes.h 1.32 + @echo "Compiling $<" 1.33 + $(CC) -o $@ $(CFLAGS) -c $< 1.34 +
2.1 --- a/src/ascension/core.h Mon Oct 30 18:54:16 2023 +0100 2.2 +++ b/src/ascension/core.h Wed Nov 01 20:09:49 2023 +0100 2.3 @@ -28,10 +28,6 @@ 2.4 #ifndef ASCENSION_CORE_H 2.5 #define ASCENSION_CORE_H 2.6 2.7 -#include <SDL2/SDL.h> 2.8 -#include <SDL2/SDL_ttf.h> 2.9 -#include <GL/glew.h> 2.10 - 2.11 #include <cx/string.h> 2.12 #include <cx/buffer.h> 2.13 #include <cx/list.h> 2.14 @@ -60,23 +56,6 @@ 2.15 /** Global ascension context. */ 2.16 extern AscContext asc_context; 2.17 2.18 -typedef struct AscWindowSettings { 2.19 - int depth_size; 2.20 - int vsync; 2.21 - asc_vec2i dimensions; 2.22 - int fullscreen; 2.23 - int gl_major_version; 2.24 - int gl_minor_version; 2.25 - char const* title; 2.26 -} AscWindowSettings; 2.27 - 2.28 -typedef struct AscWindow { 2.29 - SDL_Window* window; 2.30 - SDL_GLContext glctx; 2.31 - Uint32 id; 2.32 - asc_vec2i dimensions; 2.33 -} AscWindow; 2.34 - 2.35 void asc_context_initialize(void); 2.36 void asc_context_destroy(void); 2.37 2.38 @@ -107,47 +86,11 @@ 2.39 char const* asc_get_error(void); 2.40 void asc_clear_error(void); 2.41 2.42 -/** 2.43 - * Dispatches events and synchronizes all initialized windows. 2.44 - * 2.45 - * @return false, if one of the events is a QUIT event, true otherwise 2.46 - */ 2.47 -bool asc_loop_next(void); 2.48 - 2.49 -/** 2.50 - * Initializes the settings structure with default values. 2.51 - * 2.52 - * @param settings an uninitialized settings object 2.53 - */ 2.54 -void asc_window_settings_init_defaults(AscWindowSettings* settings); 2.55 - 2.56 -/** 2.57 - * Creates and initializes a new window and a corresponding OpenGL context. 2.58 - * 2.59 - * @param window the window structure 2.60 - * @param settings the settings to be used for initialization 2.61 - */ 2.62 -void asc_window_initialize(AscWindow* window, AscWindowSettings const* settings); 2.63 - 2.64 -/** 2.65 - * Destroys the window and its OpenGL context. 2.66 - * 2.67 - * Still alive windows will also be destroyed by asc_context_destroy() 2.68 - * automatically. 2.69 - * 2.70 - * @param window the window 2.71 - */ 2.72 -void asc_window_destroy(AscWindow* window); 2.73 - 2.74 -/** 2.75 - * Swaps buffers and adjusts the viewport to the current window size. 2.76 - * 2.77 - * This function is automatically invoked for all initialized windows 2.78 - * by asc_loop_next(). You usually do not need to call this function manually. 2.79 - * 2.80 - * @param window the window 2.81 - */ 2.82 -void asc_window_sync(AscWindow const *window); 2.83 +#ifdef NDEBUG 2.84 +#define asc_dprintf(...) 2.85 +#else 2.86 +#define asc_dprintf(...) printf(__VA_ARGS__); putchar('\n') 2.87 +#endif 2.88 2.89 #ifdef __cplusplus 2.90 } // extern "C"
3.1 --- a/src/ascension/datatypes.h Mon Oct 30 18:54:16 2023 +0100 3.2 +++ b/src/ascension/datatypes.h Wed Nov 01 20:09:49 2023 +0100 3.3 @@ -28,6 +28,7 @@ 3.4 #ifndef ASCENSION_DATATYPES_H 3.5 #define ASCENSION_DATATYPES_H 3.6 3.7 +#include <stdbool.h> 3.8 #include <SDL2/SDL_endian.h> 3.9 3.10 #ifdef __cplusplus
4.1 --- a/src/ascension/utils.h Mon Oct 30 18:54:16 2023 +0100 4.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 4.3 @@ -1,48 +0,0 @@ 4.4 -/* 4.5 - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER. 4.6 - * Copyright 2023 Mike Becker. All rights reserved. 4.7 - * 4.8 - * Redistribution and use in source and binary forms, with or without 4.9 - * modification, are permitted provided that the following conditions are met: 4.10 - * 4.11 - * 1. Redistributions of source code must retain the above copyright 4.12 - * notice, this list of conditions and the following disclaimer. 4.13 - * 4.14 - * 2. Redistributions in binary form must reproduce the above copyright 4.15 - * notice, this list of conditions and the following disclaimer in the 4.16 - * documentation and/or other materials provided with the distribution. 4.17 - * 4.18 - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 4.19 - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 4.20 - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 4.21 - * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE 4.22 - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 4.23 - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 4.24 - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 4.25 - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 4.26 - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 4.27 - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 4.28 - * POSSIBILITY OF SUCH DAMAGE. 4.29 - */ 4.30 - 4.31 -#ifndef ASCENSION_UTILS_H 4.32 -#define ASCENSION_UTILS_H 4.33 - 4.34 -#include <stdbool.h> 4.35 -#include <stdio.h> 4.36 - 4.37 -#ifdef __cplusplus 4.38 -extern "C" { 4.39 -#endif 4.40 - 4.41 -#ifdef NDEBUG 4.42 -#define asc_dprintf(...) 4.43 -#else 4.44 -#define asc_dprintf(...) printf(__VA_ARGS__); putchar('\n') 4.45 -#endif 4.46 - 4.47 -#ifdef __cplusplus 4.48 -} // extern "C" 4.49 -#endif 4.50 - 4.51 -#endif // ASCENSION_UTILS_H 4.52 \ No newline at end of file
5.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 5.2 +++ b/src/ascension/window.h Wed Nov 01 20:09:49 2023 +0100 5.3 @@ -0,0 +1,104 @@ 5.4 +/* 5.5 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER. 5.6 + * Copyright 2023 Mike Becker. All rights reserved. 5.7 + * 5.8 + * Redistribution and use in source and binary forms, with or without 5.9 + * modification, are permitted provided that the following conditions are met: 5.10 + * 5.11 + * 1. Redistributions of source code must retain the above copyright 5.12 + * notice, this list of conditions and the following disclaimer. 5.13 + * 5.14 + * 2. Redistributions in binary form must reproduce the above copyright 5.15 + * notice, this list of conditions and the following disclaimer in the 5.16 + * documentation and/or other materials provided with the distribution. 5.17 + * 5.18 + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 5.19 + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 5.20 + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 5.21 + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE 5.22 + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 5.23 + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 5.24 + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 5.25 + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 5.26 + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 5.27 + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 5.28 + * POSSIBILITY OF SUCH DAMAGE. 5.29 + */ 5.30 + 5.31 +#ifndef ASCENSION_WINDOW_H 5.32 +#define ASCENSION_WINDOW_H 5.33 + 5.34 +#include <SDL2/SDL.h> 5.35 + 5.36 +#include "core.h" 5.37 + 5.38 +#ifdef __cplusplus 5.39 +extern "C" { 5.40 +#endif 5.41 + 5.42 +typedef struct AscWindowSettings { 5.43 + int depth_size; 5.44 + int vsync; 5.45 + asc_vec2i dimensions; 5.46 + int fullscreen; 5.47 + int gl_major_version; 5.48 + int gl_minor_version; 5.49 + char const* title; 5.50 +} AscWindowSettings; 5.51 + 5.52 +typedef struct AscWindow { 5.53 + SDL_Window* window; 5.54 + SDL_GLContext glctx; 5.55 + Uint32 id; 5.56 + asc_vec2i dimensions; 5.57 +} AscWindow; 5.58 + 5.59 + 5.60 +/** 5.61 + * Dispatches events and synchronizes all initialized windows. 5.62 + * 5.63 + * @return false, if one of the events is a QUIT event, true otherwise 5.64 + */ 5.65 +bool asc_loop_next(void); 5.66 + 5.67 +/** 5.68 + * Initializes the settings structure with default values. 5.69 + * 5.70 + * @param settings an uninitialized settings object 5.71 + */ 5.72 +void asc_window_settings_init_defaults(AscWindowSettings* settings); 5.73 + 5.74 +/** 5.75 + * Creates and initializes a new window and a corresponding OpenGL context. 5.76 + * 5.77 + * @param window the window structure 5.78 + * @param settings the settings to be used for initialization 5.79 + */ 5.80 +void asc_window_initialize(AscWindow* window, AscWindowSettings const* settings); 5.81 + 5.82 +/** 5.83 + * Destroys the window and its OpenGL context. 5.84 + * 5.85 + * Still alive windows will also be destroyed by asc_context_destroy() 5.86 + * automatically. 5.87 + * 5.88 + * @param window the window 5.89 + */ 5.90 +void asc_window_destroy(AscWindow* window); 5.91 + 5.92 +/** 5.93 + * Swaps buffers and adjusts the viewport to the current window size. 5.94 + * 5.95 + * This function is automatically invoked for all initialized windows 5.96 + * by asc_loop_next(). You usually do not need to call this function manually. 5.97 + * 5.98 + * @param window the window 5.99 + */ 5.100 +void asc_window_sync(AscWindow const *window); 5.101 + 5.102 +#ifdef __cplusplus 5.103 +} // extern "C" 5.104 +#endif 5.105 + 5.106 +#endif /* ASCENSION_WINDOW_H */ 5.107 +
6.1 --- a/src/core.c Mon Oct 30 18:54:16 2023 +0100 6.2 +++ b/src/core.c Wed Nov 01 20:09:49 2023 +0100 6.3 @@ -26,31 +26,17 @@ 6.4 */ 6.5 6.6 #include "ascension/core.h" 6.7 -#include "ascension/utils.h" 6.8 6.9 #include <cx/linked_list.h> 6.10 #include <cx/printf.h> 6.11 6.12 -static void asc_gl_debug_callback( 6.13 - GLenum source, GLenum type, GLuint id, GLenum severity, 6.14 - GLsizei length, const GLchar* message, 6.15 - const void* userParam 6.16 -) { 6.17 - cxmutstr buf = cx_asprintf( 6.18 - "source = %d, id = %u, type = %d, severity= %d, message = %.*s", 6.19 - source, id, type, severity, length, message); 6.20 - if (type == GL_DEBUG_TYPE_ERROR) { 6.21 - asc_error(buf.ptr); 6.22 - } else { 6.23 - asc_dprintf("GL debug: %*.s", (int)buf.length, buf.ptr); 6.24 - } 6.25 - cx_strfree(&buf); 6.26 -} 6.27 +#include <SDL2/SDL.h> 6.28 +#include <SDL2/SDL_ttf.h> 6.29 6.30 AscContext asc_context; 6.31 6.32 -// forward declarations 6.33 -static void asc_window_destroy_impl(AscWindow* window); 6.34 +// forward declare the destructor functions that reside in other units 6.35 +void asc_window_destroy_impl(void* obj); 6.36 6.37 void asc_context_initialize(void) { 6.38 if (asc_test_flag(asc_context.flags, ASC_FLAG_INITILIZED)) 6.39 @@ -137,153 +123,3 @@ 6.40 cxBufferClear(&asc_context.error_buffer); 6.41 asc_clear_flag(&asc_context.flags, ASC_FLAG_HAS_ERROR); 6.42 } 6.43 - 6.44 -static void asc_event_window_resized(Uint32 id, Sint32 width, Sint32 height) { 6.45 - CxIterator iter = cxListIterator(asc_context.windows); 6.46 - cx_foreach(AscWindow*, w, iter) { 6.47 - if (w->id == id) { 6.48 - w->dimensions.width = width; 6.49 - w->dimensions.height = height; 6.50 - return; 6.51 - } 6.52 - } 6.53 -} 6.54 - 6.55 -bool asc_loop_next(void) { 6.56 - // dispatch SDL events 6.57 - SDL_Event event; 6.58 - while (SDL_PollEvent(&event)) { 6.59 - switch (event.type) { 6.60 - case SDL_QUIT:return false; 6.61 - case SDL_WINDOWEVENT: { 6.62 - if (event.window.type == SDL_WINDOWEVENT_RESIZED) 6.63 - asc_event_window_resized( 6.64 - event.window.windowID, 6.65 - event.window.data1, 6.66 - event.window.data2 6.67 - ); 6.68 - break; 6.69 - } 6.70 - case SDL_KEYDOWN: 6.71 - // TODO: remove this code and implement key press map instead 6.72 - if (event.key.keysym.sym == SDLK_ESCAPE) 6.73 - return false; 6.74 - break; 6.75 - case SDL_KEYUP: 6.76 - // TODO: implement key press map 6.77 - break; 6.78 - } 6.79 - } 6.80 - 6.81 - // sync the windows 6.82 - CxMutIterator windows = cxListMutIterator(asc_context.windows); 6.83 - cx_foreach(AscWindow*, w, windows) { 6.84 - asc_window_sync(w); 6.85 - } 6.86 - return true; 6.87 -} 6.88 - 6.89 -void asc_window_settings_init_defaults(AscWindowSettings* settings) { 6.90 - settings->depth_size = 24; 6.91 - settings->vsync = 1; 6.92 - settings->dimensions.width = 800; 6.93 - settings->dimensions.height = 600; 6.94 - settings->fullscreen = 0; 6.95 - settings->gl_major_version = 3; 6.96 - settings->gl_minor_version = 3; 6.97 - settings->title = "Ascended Window"; 6.98 -} 6.99 - 6.100 -void asc_window_initialize(AscWindow* window, AscWindowSettings const* settings) { 6.101 - Uint32 flags = SDL_WINDOW_OPENGL | SDL_WINDOW_SHOWN; 6.102 - flags |= settings->fullscreen ? SDL_WINDOW_FULLSCREEN_DESKTOP : SDL_WINDOW_RESIZABLE; 6.103 - 6.104 - window->window = SDL_CreateWindow( 6.105 - settings->title, 6.106 - SDL_WINDOWPOS_CENTERED, 6.107 - SDL_WINDOWPOS_CENTERED, 6.108 - settings->dimensions.width, 6.109 - settings->dimensions.height, 6.110 - flags 6.111 - ); 6.112 - if (window->window == NULL) { 6.113 - asc_error(SDL_GetError()); 6.114 - return; 6.115 - } 6.116 - 6.117 - window->id = SDL_GetWindowID(window->window); 6.118 - SDL_GetWindowSize(window->window, 6.119 - &window->dimensions.width, 6.120 - &window->dimensions.height 6.121 - ); 6.122 - 6.123 - SDL_GL_SetAttribute(SDL_GL_CONTEXT_PROFILE_MASK, SDL_GL_CONTEXT_PROFILE_CORE); 6.124 - SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, settings->gl_major_version); 6.125 - SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, settings->gl_minor_version); 6.126 - SDL_GL_SetAttribute(SDL_GL_DEPTH_SIZE, settings->depth_size); 6.127 - SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER, 1); 6.128 - window->glctx = SDL_GL_CreateContext(window->window); 6.129 - if (window->glctx == NULL) { 6.130 - asc_dprintf("Creating GL context failed for window %u", window->id); 6.131 - } else { 6.132 - glewExperimental = GL_TRUE; 6.133 - GLenum err = glewInit(); 6.134 - if (err == GLEW_OK) { 6.135 - SDL_GL_SetSwapInterval(settings->vsync); 6.136 - glEnable(GL_DEPTH_TEST); 6.137 - glEnable(GL_BLEND); 6.138 - glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); 6.139 - glEnable(GL_DEBUG_OUTPUT); 6.140 - glDebugMessageCallback(asc_gl_debug_callback, NULL); 6.141 - asc_dprintf("Window %u initialized", window->id); 6.142 - cxListAdd(asc_context.windows, window); 6.143 - return; 6.144 - } else { 6.145 - asc_error(glewGetErrorString(err)); 6.146 - } 6.147 - } 6.148 - 6.149 - // cleanup on error 6.150 - if (window->glctx != NULL) { 6.151 - SDL_GL_DeleteContext(window->glctx); 6.152 - } 6.153 - window->glctx = NULL; 6.154 - SDL_DestroyWindow(window->window); 6.155 - window->window = NULL; 6.156 - window->id = 0; 6.157 -} 6.158 - 6.159 -void asc_window_destroy_impl(AscWindow* window) { 6.160 - // destory the GL context and the window 6.161 - if (window->glctx != NULL) { 6.162 - SDL_GL_DeleteContext(window->glctx); 6.163 - } 6.164 - if (window->window != NULL) { 6.165 - SDL_DestroyWindow(window->window); 6.166 - } 6.167 - 6.168 - // clean the data 6.169 - asc_dprintf("Window %u and its OpenGL context destroyed.", window->id); 6.170 - memset(window, 0, sizeof(AscWindow)); 6.171 -} 6.172 - 6.173 -void asc_window_destroy(AscWindow* window) { 6.174 - // find the window in the context and remove it 6.175 - bool found = false; 6.176 - CxMutIterator iter = cxListMutIterator(asc_context.windows); 6.177 - cx_foreach(AscWindow*, w, iter) { 6.178 - if (w == window) { 6.179 - found = true; 6.180 - cxIteratorFlagRemoval(iter); 6.181 - } 6.182 - } 6.183 - if (!found) asc_window_destroy_impl(window); 6.184 -} 6.185 - 6.186 -void asc_window_sync(AscWindow const* window) { 6.187 - SDL_GL_MakeCurrent(window->window, window->glctx); 6.188 - SDL_GL_SwapWindow(window->window); 6.189 - glViewport(0, 0, window->dimensions.width, window->dimensions.height); 6.190 - glClearColor(0.0f, 0.0f, 0.0f, 1.0f); 6.191 - glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); 6.192 -}
7.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 7.2 +++ b/src/window.c Wed Nov 01 20:09:49 2023 +0100 7.3 @@ -0,0 +1,200 @@ 7.4 +/* 7.5 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER. 7.6 + * Copyright 2023 Mike Becker. All rights reserved. 7.7 + * 7.8 + * Redistribution and use in source and binary forms, with or without 7.9 + * modification, are permitted provided that the following conditions are met: 7.10 + * 7.11 + * 1. Redistributions of source code must retain the above copyright 7.12 + * notice, this list of conditions and the following disclaimer. 7.13 + * 7.14 + * 2. Redistributions in binary form must reproduce the above copyright 7.15 + * notice, this list of conditions and the following disclaimer in the 7.16 + * documentation and/or other materials provided with the distribution. 7.17 + * 7.18 + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 7.19 + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 7.20 + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 7.21 + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE 7.22 + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 7.23 + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 7.24 + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 7.25 + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 7.26 + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 7.27 + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 7.28 + * POSSIBILITY OF SUCH DAMAGE. 7.29 + */ 7.30 + 7.31 +#include "ascension/window.h" 7.32 + 7.33 +#include <cx/linked_list.h> 7.34 +#include <cx/printf.h> 7.35 + 7.36 +#include <GL/glew.h> 7.37 + 7.38 +static void asc_gl_debug_callback( 7.39 + GLenum source, GLenum type, GLuint id, GLenum severity, 7.40 + GLsizei length, const GLchar* message, 7.41 + const void* userParam 7.42 +) { 7.43 + cxmutstr buf = cx_asprintf( 7.44 + "source = %d, id = %u, type = %d, severity= %d, message = %.*s", 7.45 + source, id, type, severity, length, message); 7.46 + if (type == GL_DEBUG_TYPE_ERROR) { 7.47 + asc_error(buf.ptr); 7.48 + } else { 7.49 + asc_dprintf("GL debug: %*.s", (int)buf.length, buf.ptr); 7.50 + } 7.51 + cx_strfree(&buf); 7.52 +} 7.53 + 7.54 + 7.55 +static void asc_event_window_resized(Uint32 id, Sint32 width, Sint32 height) { 7.56 + CxIterator iter = cxListIterator(asc_context.windows); 7.57 + cx_foreach(AscWindow*, w, iter) { 7.58 + if (w->id == id) { 7.59 + w->dimensions.width = width; 7.60 + w->dimensions.height = height; 7.61 + return; 7.62 + } 7.63 + } 7.64 +} 7.65 + 7.66 +bool asc_loop_next(void) { 7.67 + // dispatch SDL events 7.68 + SDL_Event event; 7.69 + while (SDL_PollEvent(&event)) { 7.70 + switch (event.type) { 7.71 + case SDL_QUIT:return false; 7.72 + case SDL_WINDOWEVENT: { 7.73 + if (event.window.type == SDL_WINDOWEVENT_RESIZED) 7.74 + asc_event_window_resized( 7.75 + event.window.windowID, 7.76 + event.window.data1, 7.77 + event.window.data2 7.78 + ); 7.79 + break; 7.80 + } 7.81 + case SDL_KEYDOWN: 7.82 + // TODO: remove this code and implement key press map instead 7.83 + if (event.key.keysym.sym == SDLK_ESCAPE) 7.84 + return false; 7.85 + break; 7.86 + case SDL_KEYUP: 7.87 + // TODO: implement key press map 7.88 + break; 7.89 + } 7.90 + } 7.91 + 7.92 + // sync the windows 7.93 + CxMutIterator windows = cxListMutIterator(asc_context.windows); 7.94 + cx_foreach(AscWindow*, w, windows) { 7.95 + asc_window_sync(w); 7.96 + } 7.97 + return true; 7.98 +} 7.99 + 7.100 +void asc_window_settings_init_defaults(AscWindowSettings* settings) { 7.101 + settings->depth_size = 24; 7.102 + settings->vsync = 1; 7.103 + settings->dimensions.width = 800; 7.104 + settings->dimensions.height = 600; 7.105 + settings->fullscreen = 0; 7.106 + settings->gl_major_version = 3; 7.107 + settings->gl_minor_version = 3; 7.108 + settings->title = "Ascended Window"; 7.109 +} 7.110 + 7.111 +void asc_window_initialize(AscWindow* window, AscWindowSettings const* settings) { 7.112 + Uint32 flags = SDL_WINDOW_OPENGL | SDL_WINDOW_SHOWN; 7.113 + flags |= settings->fullscreen ? SDL_WINDOW_FULLSCREEN_DESKTOP : SDL_WINDOW_RESIZABLE; 7.114 + 7.115 + window->window = SDL_CreateWindow( 7.116 + settings->title, 7.117 + SDL_WINDOWPOS_CENTERED, 7.118 + SDL_WINDOWPOS_CENTERED, 7.119 + settings->dimensions.width, 7.120 + settings->dimensions.height, 7.121 + flags 7.122 + ); 7.123 + if (window->window == NULL) { 7.124 + asc_error(SDL_GetError()); 7.125 + return; 7.126 + } 7.127 + 7.128 + window->id = SDL_GetWindowID(window->window); 7.129 + SDL_GetWindowSize(window->window, 7.130 + &window->dimensions.width, 7.131 + &window->dimensions.height 7.132 + ); 7.133 + 7.134 + SDL_GL_SetAttribute(SDL_GL_CONTEXT_PROFILE_MASK, SDL_GL_CONTEXT_PROFILE_CORE); 7.135 + SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, settings->gl_major_version); 7.136 + SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, settings->gl_minor_version); 7.137 + SDL_GL_SetAttribute(SDL_GL_DEPTH_SIZE, settings->depth_size); 7.138 + SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER, 1); 7.139 + window->glctx = SDL_GL_CreateContext(window->window); 7.140 + if (window->glctx == NULL) { 7.141 + asc_dprintf("Creating GL context failed for window %u", window->id); 7.142 + } else { 7.143 + glewExperimental = GL_TRUE; 7.144 + GLenum err = glewInit(); 7.145 + if (err == GLEW_OK) { 7.146 + SDL_GL_SetSwapInterval(settings->vsync); 7.147 + glEnable(GL_DEPTH_TEST); 7.148 + glEnable(GL_BLEND); 7.149 + glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); 7.150 + glEnable(GL_DEBUG_OUTPUT); 7.151 + glDebugMessageCallback(asc_gl_debug_callback, NULL); 7.152 + asc_dprintf("Window %u initialized", window->id); 7.153 + cxListAdd(asc_context.windows, window); 7.154 + return; 7.155 + } else { 7.156 + asc_error(glewGetErrorString(err)); 7.157 + } 7.158 + } 7.159 + 7.160 + // cleanup on error 7.161 + if (window->glctx != NULL) { 7.162 + SDL_GL_DeleteContext(window->glctx); 7.163 + } 7.164 + window->glctx = NULL; 7.165 + SDL_DestroyWindow(window->window); 7.166 + window->window = NULL; 7.167 + window->id = 0; 7.168 +} 7.169 + 7.170 +void asc_window_destroy_impl(AscWindow* window) { 7.171 + // destory the GL context and the window 7.172 + if (window->glctx != NULL) { 7.173 + SDL_GL_DeleteContext(window->glctx); 7.174 + } 7.175 + if (window->window != NULL) { 7.176 + SDL_DestroyWindow(window->window); 7.177 + } 7.178 + 7.179 + // clean the data 7.180 + asc_dprintf("Window %u and its OpenGL context destroyed.", window->id); 7.181 + memset(window, 0, sizeof(AscWindow)); 7.182 +} 7.183 + 7.184 +void asc_window_destroy(AscWindow* window) { 7.185 + // find the window in the context and remove it 7.186 + bool found = false; 7.187 + CxMutIterator iter = cxListMutIterator(asc_context.windows); 7.188 + cx_foreach(AscWindow*, w, iter) { 7.189 + if (w == window) { 7.190 + found = true; 7.191 + cxIteratorFlagRemoval(iter); 7.192 + } 7.193 + } 7.194 + if (!found) asc_window_destroy_impl(window); 7.195 +} 7.196 + 7.197 +void asc_window_sync(AscWindow const* window) { 7.198 + SDL_GL_MakeCurrent(window->window, window->glctx); 7.199 + SDL_GL_SwapWindow(window->window); 7.200 + glViewport(0, 0, window->dimensions.width, window->dimensions.height); 7.201 + glClearColor(0.0f, 0.0f, 0.0f, 1.0f); 7.202 + glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); 7.203 +}
8.1 --- a/test/Makefile Mon Oct 30 18:54:16 2023 +0100 8.2 +++ b/test/Makefile Wed Nov 01 20:09:49 2023 +0100 8.3 @@ -33,11 +33,13 @@ 8.4 @echo "Sandbox demo successfully built." 8.5 8.6 $(BUILD_DIR)/sandbox: $(BUILD_DIR)/sandbox.o $(LIB_ASCENSION) 8.7 - echo "Linking executable..." 8.8 + @echo "Linking executable..." 8.9 $(CC) $(LDFLAGS) -o $@ $^ 8.10 8.11 -$(BUILD_DIR)/sandbox.o: sandbox.c ../src/ascension/core.h 8.12 - echo "Compiling $<" 8.13 +FORCE: 8.14 + 8.15 +$(BUILD_DIR)/sandbox.o: sandbox.c ../src/ascension/window.h \ 8.16 + ../src/ascension/core.h ../src/ascension/datatypes.h 8.17 + @echo "Compiling $<" 8.18 $(CC) -o $@ $(CFLAGS) -c $< 8.19 8.20 -FORCE:
9.1 --- a/test/sandbox.c Mon Oct 30 18:54:16 2023 +0100 9.2 +++ b/test/sandbox.c Wed Nov 01 20:09:49 2023 +0100 9.3 @@ -25,7 +25,7 @@ 9.4 * POSSIBILITY OF SUCH DAMAGE. 9.5 */ 9.6 9.7 -#include "ascension/core.h" 9.8 +#include "ascension/window.h" 9.9 9.10 static bool show_message_box_on_error(SDL_Window* window) { 9.11 if (asc_has_error()) {