diff -r 5a8c31904e44 -r b3da4096c607 src/glcontext.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/glcontext.c Tue Mar 26 20:37:21 2024 +0100 @@ -0,0 +1,111 @@ +/* + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER. + * Copyright 2023 Mike Becker. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#include "ascension/glcontext.h" +#include "ascension/error.h" + +#include + +#include + +static void asc_gl_debug_callback( + GLenum source, GLenum type, GLuint id, GLenum severity, + GLsizei length, const GLchar* message, + const void* userParam +) { + cxmutstr buf = cx_asprintf( + "source = %d, id = %u, type = %d, severity= %d, message = %.*s", + source, id, type, severity, length, message); + if (type == GL_DEBUG_TYPE_ERROR) { + asc_error(buf.ptr); + } else { + asc_dprintf("GL debug: %.*s", (int)buf.length, buf.ptr); + } + cx_strfree(&buf); +} + +static void asc_shader_initialize_predefined(AscGLContext *ctx) { + AscShaderSprite *sprite = &ctx->shader.sprite; + sprite->base = asc_shader_easy_compile_and_link("shader/sprite_vtx.glsl", "shader/sprite_frag.glsl"); + sprite->surface = glGetUniformLocation(sprite->base.id, "surface"); + sprite->depth = glGetUniformLocation(sprite->base.id, "depth"); +} + +static void asc_shader_destroy_predefined(AscGLContext *ctx) { + asc_shader_program_destroy(ctx->shader.sprite.base); +} + +bool asc_gl_context_initialize( + AscGLContext *ctx, + SDL_Window *window, + AscGLContextSettings const *settings +) { + SDL_GL_SetAttribute(SDL_GL_CONTEXT_PROFILE_MASK, SDL_GL_CONTEXT_PROFILE_CORE); + SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, settings->gl_major_version); + SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, settings->gl_minor_version); + SDL_GL_SetAttribute(SDL_GL_DEPTH_SIZE, settings->depth_size); + SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER, 1); + ctx->glctx = SDL_GL_CreateContext(window); + if (ctx->glctx == NULL) return false; + ctx->window = window; + + glewExperimental = GL_TRUE; + GLenum err = glewInit(); + if (err == GLEW_OK) { + SDL_GL_SetSwapInterval(settings->vsync); + + glClearColor(0.0f, 0.0f, 0.0f, 1.0f); + glEnable(GL_DEBUG_OUTPUT); + glDebugMessageCallback(asc_gl_debug_callback, NULL); + + if (!asc_primitives_init(&ctx->primitives)) { + asc_error("Creating primitive meshes failed"); + SDL_GL_DeleteContext(ctx->glctx); + return false; + } + + asc_shader_initialize_predefined(ctx); + + return true; + } else { + asc_error(glewGetErrorString(err)); + SDL_GL_DeleteContext(ctx->glctx); + return false; + } +} + +void asc_gl_context_destroy(AscGLContext *ctx) { + if (ctx->glctx == NULL) return; + SDL_GL_MakeCurrent(ctx->window, ctx->glctx); + + asc_shader_destroy_predefined(ctx); + asc_primitives_destroy(&ctx->primitives); + + // destroy the GL context and the window + SDL_GL_DeleteContext(ctx->glctx); + ctx->glctx = NULL; +}