162 lines
4.0 KiB
C
162 lines
4.0 KiB
C
/**
|
|
* Copyright (c) 2025 Dominic Masters
|
|
*
|
|
* This software is released under the MIT License.
|
|
* https://opensource.org/licenses/MIT
|
|
*/
|
|
|
|
#include "framebuffer.h"
|
|
#include "display/display.h"
|
|
#include "assert/assert.h"
|
|
#include "util/memory.h"
|
|
|
|
framebuffer_t FRAMEBUFFER_BACKBUFFER = {0};
|
|
const framebuffer_t *FRAMEBUFFER_BOUND = &FRAMEBUFFER_BACKBUFFER;
|
|
|
|
void frameBufferInitBackbuffer() {
|
|
memoryZero(&FRAMEBUFFER_BACKBUFFER, sizeof(framebuffer_t));
|
|
|
|
FRAMEBUFFER_BACKBUFFER.id = -1;
|
|
FRAMEBUFFER_BOUND = &FRAMEBUFFER_BACKBUFFER;
|
|
}
|
|
|
|
#if DISPLAY_SIZE_DYNAMIC == 1
|
|
void frameBufferInit(
|
|
framebuffer_t *framebuffer,
|
|
const uint32_t width,
|
|
const uint32_t height
|
|
) {
|
|
#if DISPLAY_SDL2 == 1
|
|
assertNotNull(framebuffer, "Framebuffer cannot be NULL");
|
|
assertTrue(width > 0 && height > 0, "Width & height must be greater than 0");
|
|
|
|
memoryZero(framebuffer, sizeof(framebuffer_t));
|
|
textureInit(&framebuffer->texture, width, height, GL_RGBA, (texturedata_t){
|
|
.rgba = { .colors = NULL }
|
|
});
|
|
|
|
glGenFramebuffersEXT(1, &framebuffer->id);
|
|
glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, framebuffer->id);
|
|
|
|
glFramebufferTexture2DEXT(
|
|
GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT,
|
|
GL_TEXTURE_2D, framebuffer->texture.id, 0
|
|
);
|
|
|
|
if(
|
|
glCheckFramebufferStatusEXT(GL_FRAMEBUFFER_EXT) !=
|
|
GL_FRAMEBUFFER_COMPLETE_EXT
|
|
) {
|
|
assertUnreachable("Framebuffer is not complete");
|
|
}
|
|
|
|
glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0);
|
|
#endif
|
|
}
|
|
#endif
|
|
|
|
int32_t frameBufferGetWidth(const framebuffer_t *framebuffer) {
|
|
#if DISPLAY_SDL2
|
|
if(framebuffer == &FRAMEBUFFER_BACKBUFFER) {
|
|
#if DISPLAY_SIZE_DYNAMIC == 0
|
|
return DISPLAY_WIDTH;
|
|
#else
|
|
int32_t windowWidth, windowHeight;
|
|
SDL_GetWindowSize(DISPLAY.window, &windowWidth, &windowHeight);
|
|
return windowWidth;
|
|
#endif
|
|
}
|
|
|
|
return framebuffer->texture.width;
|
|
#endif
|
|
}
|
|
|
|
int32_t frameBufferGetHeight(const framebuffer_t *framebuffer) {
|
|
#if DISPLAY_SDL2
|
|
if(framebuffer == &FRAMEBUFFER_BACKBUFFER) {
|
|
#if DISPLAY_SIZE_DYNAMIC == 0
|
|
return DISPLAY_HEIGHT;
|
|
#else
|
|
int32_t windowWidth, windowHeight;
|
|
SDL_GetWindowSize(DISPLAY.window, &windowWidth, &windowHeight);
|
|
return windowHeight;
|
|
#endif
|
|
}
|
|
|
|
return framebuffer->texture.height;
|
|
#endif
|
|
}
|
|
|
|
void frameBufferBind(const framebuffer_t *framebuffer) {
|
|
if(framebuffer == NULL) {
|
|
#if DISPLAY_SDL2
|
|
frameBufferBind(&FRAMEBUFFER_BACKBUFFER);
|
|
#endif
|
|
|
|
FRAMEBUFFER_BOUND = &FRAMEBUFFER_BACKBUFFER;
|
|
return;
|
|
}
|
|
|
|
// Bind the framebuffer for rendering
|
|
#if DISPLAY_SDL2
|
|
if(framebuffer == &FRAMEBUFFER_BACKBUFFER) {
|
|
#if PSP
|
|
|
|
#else
|
|
glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0);
|
|
#endif
|
|
} else {
|
|
#if PSP
|
|
assertUnreachable("Framebuffers not supported on PSP");
|
|
#else
|
|
glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, framebuffer->id);
|
|
#endif
|
|
}
|
|
|
|
glViewport(
|
|
0, 0,
|
|
frameBufferGetWidth(framebuffer), frameBufferGetHeight(framebuffer)
|
|
);
|
|
#endif
|
|
|
|
FRAMEBUFFER_BOUND = framebuffer;
|
|
}
|
|
|
|
void frameBufferClear(uint8_t flags, color_t color) {
|
|
#if DISPLAY_SDL2
|
|
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);
|
|
#endif
|
|
}
|
|
|
|
void frameBufferDispose(framebuffer_t *framebuffer) {
|
|
assertNotNull(framebuffer, "Framebuffer cannot be NULL");
|
|
|
|
#if DISPLAY_SDL2
|
|
if(framebuffer == &FRAMEBUFFER_BACKBUFFER) {
|
|
assertUnreachable("Cannot dispose of backbuffer");
|
|
}
|
|
|
|
#if DISPLAY_SIZE_DYNAMIC == 0
|
|
assertUnreachable("Dynamic size framebuffers not supported");
|
|
#else
|
|
textureDispose(&framebuffer->texture);
|
|
glDeleteFramebuffersEXT(1, &framebuffer->id);
|
|
#endif
|
|
#endif
|
|
} |