2021-12-05 19:51:05 +01:00
|
|
|
#include "gfx/context.h"
|
|
|
|
|
2022-05-14 11:41:30 +02:00
|
|
|
#include "config.h"
|
2021-12-05 19:51:05 +01:00
|
|
|
#include "game/shell.h"
|
|
|
|
#include "gfx/gl/gl_core_3_3.h"
|
2023-01-15 17:14:07 +01:00
|
|
|
#include "gfx/gl/utils.h"
|
2021-12-05 19:51:05 +01:00
|
|
|
#include "gfx/screenshot.h"
|
|
|
|
#include "log.h"
|
|
|
|
#include "memory.h"
|
|
|
|
|
2022-05-16 10:54:12 +02:00
|
|
|
#include <SDL2/SDL.h>
|
|
|
|
#include <SDL2/SDL_syswm.h>
|
2021-12-05 19:51:05 +01:00
|
|
|
#include <string.h>
|
|
|
|
|
|
|
|
typedef struct GFX_Context {
|
2023-01-15 17:14:07 +01:00
|
|
|
SDL_GLContext context;
|
|
|
|
SDL_Window *window_handle;
|
|
|
|
|
2021-12-05 19:51:05 +01:00
|
|
|
bool is_fullscreen; // fullscreen flag
|
|
|
|
bool is_rendered; // rendering flag
|
|
|
|
int32_t display_width;
|
|
|
|
int32_t display_height;
|
|
|
|
int32_t screen_width;
|
|
|
|
int32_t screen_height;
|
|
|
|
int32_t window_width;
|
|
|
|
int32_t window_height;
|
|
|
|
char *scheduled_screenshot_path;
|
2021-12-05 20:52:59 +01:00
|
|
|
GFX_2D_Renderer renderer_2d;
|
2021-12-06 16:24:20 +01:00
|
|
|
GFX_3D_Renderer renderer_3d;
|
2021-12-05 19:51:05 +01:00
|
|
|
} GFX_Context;
|
|
|
|
|
|
|
|
static GFX_Context m_Context = { 0 };
|
|
|
|
|
2023-01-15 17:14:07 +01:00
|
|
|
const char *get_extension_supported(const char *name)
|
|
|
|
{
|
|
|
|
int i, number_of_extensions;
|
|
|
|
|
|
|
|
glGetIntegerv(GL_NUM_EXTENSIONS, &number_of_extensions);
|
|
|
|
|
|
|
|
for (i = 0; i < number_of_extensions; i++) {
|
|
|
|
const char *gl_ext = (const char *)glGetStringi(GL_EXTENSIONS, i);
|
|
|
|
if (gl_ext && !strcmp(gl_ext, name)) {
|
|
|
|
return "yes";
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return "no";
|
|
|
|
}
|
|
|
|
|
2022-05-16 10:54:12 +02:00
|
|
|
void GFX_Context_Attach(void *window_handle)
|
2021-12-05 19:51:05 +01:00
|
|
|
{
|
2023-01-15 17:14:07 +01:00
|
|
|
const char *shading_ver;
|
|
|
|
|
2022-05-16 10:54:12 +02:00
|
|
|
if (m_Context.window_handle) {
|
2021-12-05 19:51:05 +01:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2022-05-16 10:54:12 +02:00
|
|
|
LOG_INFO("Attaching to window %p", window_handle);
|
2021-12-05 19:51:05 +01:00
|
|
|
|
2022-05-16 10:54:12 +02:00
|
|
|
m_Context.window_handle = window_handle;
|
2023-01-15 17:14:07 +01:00
|
|
|
m_Context.context = SDL_GL_CreateContext(m_Context.window_handle);
|
2021-12-05 19:51:05 +01:00
|
|
|
|
2023-01-15 17:14:07 +01:00
|
|
|
if (!m_Context.context) {
|
|
|
|
Shell_ExitSystem("Can't create OpenGL context");
|
2022-05-16 10:54:12 +02:00
|
|
|
}
|
|
|
|
|
2023-01-15 17:14:07 +01:00
|
|
|
if (SDL_GL_MakeCurrent(m_Context.window_handle, m_Context.context)) {
|
|
|
|
Shell_ExitSystem("Can't activate OpenGL context");
|
2021-12-05 19:51:05 +01:00
|
|
|
}
|
|
|
|
|
2023-01-15 17:14:07 +01:00
|
|
|
LOG_INFO("OpenGL vendor string: %s", glGetString(GL_VENDOR));
|
|
|
|
LOG_INFO("OpenGL renderer string: %s", glGetString(GL_RENDERER));
|
|
|
|
LOG_INFO("OpenGL version string: %s", glGetString(GL_VERSION));
|
2021-12-05 19:51:05 +01:00
|
|
|
|
2023-01-15 17:14:07 +01:00
|
|
|
shading_ver = (const char *)glGetString(GL_SHADING_LANGUAGE_VERSION);
|
|
|
|
if (shading_ver != NULL) {
|
|
|
|
LOG_INFO("Shading version string: %s", shading_ver);
|
|
|
|
} else {
|
|
|
|
GFX_GL_CheckError();
|
2021-12-05 19:51:05 +01:00
|
|
|
}
|
|
|
|
|
2023-01-15 17:14:07 +01:00
|
|
|
LOG_INFO(
|
|
|
|
"GL_ARB_explicit_attrib_location supported: %s",
|
|
|
|
get_extension_supported("GL_ARB_explicit_attrib_location"));
|
|
|
|
LOG_INFO(
|
|
|
|
"GL_EXT_gpu_shader4 supported: %s",
|
|
|
|
get_extension_supported("GL_EXT_gpu_shader4"));
|
|
|
|
|
|
|
|
// get screen dimensions
|
|
|
|
SDL_DisplayMode DM;
|
|
|
|
|
|
|
|
SDL_GetDesktopDisplayMode(0, &DM);
|
|
|
|
m_Context.screen_width = DM.w;
|
|
|
|
m_Context.screen_height = DM.h;
|
|
|
|
LOG_INFO("GetDesktopDisplayMode=%dx%d", DM.w, DM.h);
|
2021-12-05 19:51:05 +01:00
|
|
|
|
|
|
|
glClearColor(0, 0, 0, 0);
|
|
|
|
glClearDepth(1);
|
|
|
|
|
2022-01-31 09:16:23 -05:00
|
|
|
// VSync defaults to on unless user disabled it in runtime json
|
2023-01-15 17:14:07 +01:00
|
|
|
SDL_GL_SetSwapInterval(1);
|
2021-12-05 20:52:59 +01:00
|
|
|
|
|
|
|
GFX_2D_Renderer_Init(&m_Context.renderer_2d);
|
2021-12-06 16:24:20 +01:00
|
|
|
GFX_3D_Renderer_Init(&m_Context.renderer_3d);
|
2021-12-05 19:51:05 +01:00
|
|
|
}
|
|
|
|
|
2022-03-16 23:29:28 +01:00
|
|
|
void GFX_Context_Detach(void)
|
2021-12-05 19:51:05 +01:00
|
|
|
{
|
2022-05-16 10:54:12 +02:00
|
|
|
if (!m_Context.window_handle) {
|
2021-12-05 19:51:05 +01:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2021-12-05 20:52:59 +01:00
|
|
|
GFX_2D_Renderer_Close(&m_Context.renderer_2d);
|
2021-12-06 16:24:20 +01:00
|
|
|
GFX_3D_Renderer_Close(&m_Context.renderer_3d);
|
2021-12-05 20:52:59 +01:00
|
|
|
|
2023-01-15 17:14:07 +01:00
|
|
|
SDL_GL_MakeCurrent(NULL, NULL);
|
2021-12-05 19:51:05 +01:00
|
|
|
|
2023-01-15 17:14:07 +01:00
|
|
|
if (m_Context.context != NULL) {
|
|
|
|
SDL_GL_DeleteContext(m_Context.context);
|
|
|
|
m_Context.context = NULL;
|
|
|
|
}
|
2022-05-16 10:54:12 +02:00
|
|
|
m_Context.window_handle = NULL;
|
2021-12-05 19:51:05 +01:00
|
|
|
}
|
|
|
|
|
2022-01-31 09:16:23 -05:00
|
|
|
void GFX_Context_SetVSync(bool vsync)
|
|
|
|
{
|
2023-01-15 17:14:07 +01:00
|
|
|
SDL_GL_SetSwapInterval(vsync);
|
2022-01-31 09:16:23 -05:00
|
|
|
}
|
|
|
|
|
2022-03-16 23:29:28 +01:00
|
|
|
bool GFX_Context_IsFullscreen(void)
|
2021-12-05 19:51:05 +01:00
|
|
|
{
|
|
|
|
return m_Context.is_fullscreen;
|
|
|
|
}
|
|
|
|
|
|
|
|
void GFX_Context_SetFullscreen(bool fullscreen)
|
|
|
|
{
|
|
|
|
m_Context.is_fullscreen = fullscreen;
|
|
|
|
}
|
|
|
|
|
|
|
|
void GFX_Context_SetWindowSize(int32_t width, int32_t height)
|
|
|
|
{
|
|
|
|
LOG_INFO("Window size: %dx%d", width, height);
|
|
|
|
m_Context.window_width = width;
|
|
|
|
m_Context.window_height = height;
|
|
|
|
}
|
|
|
|
|
|
|
|
void GFX_Context_SetDisplaySize(int32_t width, int32_t height)
|
|
|
|
{
|
|
|
|
LOG_INFO("Display size: %dx%d", width, height);
|
|
|
|
m_Context.display_width = width;
|
|
|
|
m_Context.display_height = height;
|
|
|
|
}
|
|
|
|
|
2022-03-16 23:29:28 +01:00
|
|
|
int32_t GFX_Context_GetDisplayWidth(void)
|
2021-12-05 19:51:05 +01:00
|
|
|
{
|
|
|
|
return m_Context.display_width;
|
|
|
|
}
|
|
|
|
|
2022-03-16 23:29:28 +01:00
|
|
|
int32_t GFX_Context_GetDisplayHeight(void)
|
2021-12-05 19:51:05 +01:00
|
|
|
{
|
|
|
|
return m_Context.display_height;
|
|
|
|
}
|
|
|
|
|
2022-03-16 23:29:28 +01:00
|
|
|
int32_t GFX_Context_GetWindowWidth(void)
|
2021-12-05 19:51:05 +01:00
|
|
|
{
|
|
|
|
return m_Context.window_width ? m_Context.window_width
|
|
|
|
: m_Context.display_width;
|
|
|
|
}
|
|
|
|
|
2022-03-16 23:29:28 +01:00
|
|
|
int32_t GFX_Context_GetWindowHeight(void)
|
2021-12-05 19:51:05 +01:00
|
|
|
{
|
|
|
|
return m_Context.window_height ? m_Context.window_height
|
|
|
|
: m_Context.display_height;
|
|
|
|
}
|
|
|
|
|
2022-03-16 23:29:28 +01:00
|
|
|
int32_t GFX_Context_GetScreenWidth(void)
|
2021-12-05 19:51:05 +01:00
|
|
|
{
|
|
|
|
return m_Context.screen_width;
|
|
|
|
}
|
|
|
|
|
2022-03-16 23:29:28 +01:00
|
|
|
int32_t GFX_Context_GetScreenHeight(void)
|
2021-12-05 19:51:05 +01:00
|
|
|
{
|
|
|
|
return m_Context.screen_height;
|
|
|
|
}
|
|
|
|
|
2022-03-16 23:29:28 +01:00
|
|
|
void GFX_Context_SetupViewport(void)
|
2021-12-05 19:51:05 +01:00
|
|
|
{
|
|
|
|
int vp_width = m_Context.window_width;
|
|
|
|
int vp_height = m_Context.window_height;
|
|
|
|
|
|
|
|
// default to bottom left corner of the window
|
|
|
|
int vp_x = 0;
|
|
|
|
int vp_y = 0;
|
|
|
|
|
|
|
|
int hw = m_Context.display_height * vp_width;
|
|
|
|
int wh = m_Context.display_width * vp_height;
|
|
|
|
|
|
|
|
// create viewport offset if the window has a different
|
|
|
|
// aspect ratio than the current display mode
|
|
|
|
if (hw > wh) {
|
|
|
|
int max_w = wh / m_Context.display_height;
|
|
|
|
vp_x = (vp_width - max_w) / 2;
|
|
|
|
vp_width = max_w;
|
|
|
|
} else if (hw < wh) {
|
|
|
|
int max_h = hw / m_Context.display_width;
|
|
|
|
vp_y = (vp_height - max_h) / 2;
|
|
|
|
vp_height = max_h;
|
|
|
|
}
|
|
|
|
|
|
|
|
glViewport(vp_x, vp_y, vp_width, vp_height);
|
|
|
|
}
|
|
|
|
|
2022-03-16 23:29:28 +01:00
|
|
|
void GFX_Context_SwapBuffers(void)
|
2021-12-05 19:51:05 +01:00
|
|
|
{
|
|
|
|
glFinish();
|
|
|
|
|
|
|
|
if (m_Context.scheduled_screenshot_path) {
|
|
|
|
GFX_Screenshot_CaptureToFile(m_Context.scheduled_screenshot_path);
|
2022-01-07 03:14:07 +01:00
|
|
|
Memory_FreePointer(&m_Context.scheduled_screenshot_path);
|
2021-12-05 19:51:05 +01:00
|
|
|
}
|
|
|
|
|
2023-01-15 17:14:07 +01:00
|
|
|
SDL_GL_SwapWindow(m_Context.window_handle);
|
|
|
|
|
2021-12-05 19:51:05 +01:00
|
|
|
glDrawBuffer(GL_BACK);
|
|
|
|
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
|
|
|
|
|
|
|
|
m_Context.is_rendered = false;
|
|
|
|
}
|
|
|
|
|
2022-03-16 23:29:28 +01:00
|
|
|
void GFX_Context_SetRendered(void)
|
2021-12-05 19:51:05 +01:00
|
|
|
{
|
|
|
|
m_Context.is_rendered = true;
|
|
|
|
}
|
|
|
|
|
2022-03-16 23:29:28 +01:00
|
|
|
bool GFX_Context_IsRendered(void)
|
2021-12-05 19:51:05 +01:00
|
|
|
{
|
|
|
|
return m_Context.is_rendered;
|
|
|
|
}
|
|
|
|
|
|
|
|
void GFX_Context_ScheduleScreenshot(const char *path)
|
|
|
|
{
|
2022-03-03 00:25:21 +01:00
|
|
|
m_Context.scheduled_screenshot_path = Memory_DupStr(path);
|
2021-12-05 19:51:05 +01:00
|
|
|
}
|
2021-12-05 20:52:59 +01:00
|
|
|
|
2022-03-16 23:29:28 +01:00
|
|
|
GFX_2D_Renderer *GFX_Context_GetRenderer2D(void)
|
2021-12-05 20:52:59 +01:00
|
|
|
{
|
|
|
|
return &m_Context.renderer_2d;
|
|
|
|
}
|
2021-12-06 16:24:20 +01:00
|
|
|
|
2022-03-16 23:29:28 +01:00
|
|
|
GFX_3D_Renderer *GFX_Context_GetRenderer3D(void)
|
2021-12-06 16:24:20 +01:00
|
|
|
{
|
|
|
|
return &m_Context.renderer_3d;
|
|
|
|
}
|