/** * Copyright (c) 2026 Dominic Masters * * This software is released under the MIT License. * https://opensource.org/licenses/MIT */ #include "display/display.h" #include "display/framebuffer/framebuffer.h" #include "assert/assert.h" errorret_t frameBufferGLInitBackBuffer(void) { errorOk(); } uint32_t frameBufferGetWidth(const framebuffer_t *framebuffer) { if(framebuffer == NULL) { return 0; } if(framebuffer == &FRAMEBUFFER_BACKBUFFER) { #ifdef DUSK_DISPLAY_SIZE_DYNAMIC int32_t windowWidth, windowHeight; SDL_GetWindowSize(DISPLAY.window, &windowWidth, &windowHeight); return windowWidth; #else return DUSK_DISPLAY_WIDTH; #endif } return framebuffer->texture.width; } uint32_t frameBufferGLGetHeight(const framebuffer_t *framebuffer) { if(framebuffer == NULL) { return 0; } if(framebuffer == &FRAMEBUFFER_BACKBUFFER) { #ifdef DUSK_DISPLAY_SIZE_DYNAMIC int32_t windowWidth, windowHeight; SDL_GetWindowSize(DISPLAY.window, &windowWidth, &windowHeight); return windowHeight; #else return DUSK_DISPLAY_HEIGHT; #endif } return framebuffer->texture.height; } errorret_t frameBufferGLBind(framebuffer_t *framebuffer) { assertNotNull(framebuffer, "Framebuffer cannot be NULL"); #ifdef DUSK_DISPLAY_SIZE_DYNAMIC if(framebuffer == &FRAMEBUFFER_BACKBUFFER) { glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0); } else { glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, framebuffer->id); } glViewport( 0, 0, frameBufferGetWidth(framebuffer), frameBufferGetHeight(framebuffer) ); #else glViewport( 0, 0, DUSK_DISPLAY_WIDTH, DUSK_DISPLAY_HEIGHT ); #endif errorChain(errorGLCheck()); errorOk(); } void frameBufferClear(const uint8_t flags, const color_t color) { GLbitfield glFlags = 0; if(flags & FRAMEBUFFER_CLEAR_COLOR) { glFlags |= GL_COLOR_BUFFER_BIT; glClearColor( color.r / 255.0f, color.g / 255.0f, color.b / 255.0f, color.a / 255.0f ); } if(flags & FRAMEBUFFER_CLEAR_DEPTH) { glFlags |= GL_DEPTH_BUFFER_BIT; } glClear(glFlags); } #ifdef DUSK_DISPLAY_SIZE_DYNAMIC errorret_t frameBufferGLInit( framebuffer_t *fb, const uint32_t width, const uint32_t height ) { assertNotNull(fb, "Framebuffer cannot be NULL"); assertTrue(width > 0 && height > 0, "W/H must be greater than 0"); memoryZero(fb, sizeof(framebuffer_t)); textureInit(&fb->texture, width, height, TEXTURE_FORMAT_RGBA,(texturedata_t){ .rgbaColors = NULL }); errorChain(errorGLCheck()); glGenFramebuffersEXT(1, &fb->id); glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, fb->id); errorChain(errorGLCheck()); glFramebufferTexture2DEXT( GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT, GL_TEXTURE_2D, fb->texture.id, 0 ); errorChain(errorGLCheck()); if( glCheckFramebufferStatusEXT(GL_FRAMEBUFFER_EXT) != GL_FRAMEBUFFER_COMPLETE_EXT ) { assertUnreachable("Framebuffer is not complete"); } glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0); errorChain(errorGLCheck()); errorOk(); } errorret_t frameBufferGLDispose(framebuffer_t *framebuffer) { assertNotNull(framebuffer, "Framebuffer cannot be NULL"); if(framebuffer == &FRAMEBUFFER_BACKBUFFER) { assertUnreachable("Cannot dispose of backbuffer"); } errorChain(textureDispose(&framebuffer->texture)); glDeleteFramebuffersEXT(1, &framebuffer->id); errorChain(errorGLCheck()); errorOk(); } #endif