Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
#include "servers/render_context/render_context.h"
#include "servers/window_server/sdl3/window_server_sdl3.h"
#include "servers/window_server/window_server.h"
#include "types/signal.h"
#include "types/types.h"

/*struct RenderContextSurface {
Expand All @@ -25,7 +26,8 @@
do { \
if (!SDL_IsMainThread()) { \
LOG_ERROR( \
"WindowServer(SDL3)::" #function " must be called only from main thread or " \
"RenderContext(OpenGL 1.3, SDL3)::" #function \
" must be called only from main thread or " \
"via call_deferred/call_deferred_async" \
) \
set_error(NOT_MAIN_THREAD_ERROR); \
Expand All @@ -37,6 +39,21 @@
const static u32 INIT_FLAGS = SDL_INIT_VIDEO | SDL_INIT_EVENTS;
static u8 g_isInit = 0;

struct ServerSignal {
Signal* signal;
c_str name;
c_str description;
};

// clang-format off
static Signal g_signalGlContextCreated;

#define SERVER_SIGNAL(_signal, _name, _description) (struct ServerSignal) {.signal = _signal, .name = _name, .description = _description}
static struct ServerSignal g_signals[] = {
SERVER_SIGNAL(&g_signalGlContextCreated, "gl_context_created", "")
};
// clang-format on

static boolean _init(void) {
if (!SDL_WasInit(INIT_FLAGS)) {
if (!SDL_Init(INIT_FLAGS)) {
Expand All @@ -46,17 +63,83 @@ static boolean _init(void) {
g_isInit = 1;
}

for (usize i = 0; i < (sizeof(g_signals) / sizeof(g_signals[0])); ++i) {
if (!signal_constructor(g_signals[i].signal)) {
LOG_ERROR("RenderContext::_init: Signal initializaito failed");
return false;
}
}

return true;
}

static boolean _quit(void) {
if (g_isInit) {
SDL_QuitSubSystem(INIT_FLAGS);
}

for (usize i = 0; i < (sizeof(g_signals) / sizeof(g_signals[0])); ++i) {
signal_destructor(g_signals[i].signal);
}
return true;
}


static SignalCallbackHandler impl_signal_connect(c_str name, SignalCallbackFunc func, void* ctx) {
ERROR_ARGS_CHECK_2(name, func, { return 0; });

for (usize i = 0; i < (sizeof(g_signals) / sizeof(g_signals[0])); ++i) {
if (strcmp(name, g_signals[i].name) == 0) {
return signal_connect(g_signals[i].signal, func, ctx);
}
}

LOG_WARN("RenderContext(OpenGL 1.3, SDL3)::signal_connect: Signal '%s' not found", name);
set_error(ERROR_NOT_FOUND);
return 0;
}

static boolean impl_signal_disconnect(c_str name, SignalCallbackHandler handler) {
ERROR_ARGS_CHECK_2(name, handler, { return false; });

for (usize i = 0; i < (sizeof(g_signals) / sizeof(g_signals[0])); ++i) {
if (strcmp(name, g_signals[i].name) == 0) {
return signal_disconnect(g_signals[i].signal, handler);
}
}

LOG_WARN("RenderContext.signal_disconnect: Signal '%s' not found", name);
set_error(ERROR_NOT_FOUND);
return false;
}

static i32 get_available_signals(c_str* names_buff, c_str* descriptions_buff) {
const usize signals_count = sizeof(g_signals) / sizeof(g_signals[0]);

if (names_buff) {
names_buff = tmalloc(sizeof(c_str) * signals_count);
ERROR_ALLOC_CHECK(names_buff, { return 0; });
}

if (descriptions_buff) {
descriptions_buff = tmalloc(sizeof(c_str) * signals_count);
ERROR_ALLOC_CHECK(descriptions_buff, {
tfree(names_buff);
return 0;
});
}

for (usize i = 0; i < (sizeof(g_signals) / sizeof(g_signals[0])); ++i) {
if (names_buff)
names_buff[i] = g_signals[i].name;
if (descriptions_buff)
descriptions_buff[i] = g_signals[i].description;
}

return signals_count;
}


static SDL_GLContext g_openglSharedContext = NULL;
static RenderContextSurface* create_surface(WindowServerWindow* window) {
ERROR_ARGS_CHECK_1(window, { return NULL; });
Expand All @@ -66,10 +149,16 @@ static RenderContextSurface* create_surface(WindowServerWindow* window) {
g_openglSharedContext = SDL_GL_CreateContext((SDL_Window*) window);

if (!g_openglSharedContext) {
LOG_FATAL("Failed to create shared OpenGL context. SDL Error: %s", SDL_GetError());
LOG_FATAL(
"RenderContext.create_surface: Failed to create shared OpenGL context. SDL Error: "
"%s",
SDL_GetError()
);
set_error(ANY_ERROR);
return NULL;
}

signal_emit(&g_signalGlContextCreated, NULL);
}

return (RenderContextSurface*) window;
Expand All @@ -92,7 +181,10 @@ static boolean surface_make_current(RenderContextSurface* surface) {
}

if (!SDL_GL_MakeCurrent((SDL_Window*) surface, g_openglSharedContext)) {
LOG_FATAL("Failed to change OpenGL context. SDL Error: %s", SDL_GetError());
LOG_FATAL(
"RenderContext.surface_make_current: Failed to change OpenGL context. SDL Error: %s",
SDL_GetError()
);
set_error(ANY_ERROR);
return false;
}
Expand All @@ -111,27 +203,35 @@ static boolean surface_present(RenderContextSurface* surface) {
return false;
}
if (!SDL_GL_SwapWindow((SDL_Window*) surface)) {
LOG_FATAL("Failed to swap window's buffers. SDL Error: %s", SDL_GetError());
LOG_FATAL(
"RenderContext.surface_present: Failed to swap window's buffers. SDL Error: %s",
SDL_GetError()
);
set_error(ANY_ERROR);
return false;
}
return true;
}


#define REGISTER(fn) render_context_backend_set_function(backend, #fn, (fptr) fn)
#define REGISTER_WITH_NAME(name, fn) render_context_backend_set_function(backend, name, (fptr) fn)
#define REGISTER(fn) REGISTER_WITH_NAME(#fn, fn)

void render_context_opengl_13_sdl3_backend_register(void) {
RenderContextBackend* backend = render_context_backend_new();

REGISTER(_init);
REGISTER(_quit);

REGISTER_WITH_NAME("signal_connect", impl_signal_connect);
REGISTER_WITH_NAME("signal_disconnect", impl_signal_disconnect);
REGISTER(get_available_signals);

REGISTER(create_surface);
REGISTER(destroy_surface);
REGISTER(surface_make_current);
REGISTER(surface_present);

render_context_backend_set_function(backend, "get_proc_addr", (fptr) SDL_GL_GetProcAddress);
REGISTER_WITH_NAME("get_proc_addr", SDL_GL_GetProcAddress);

render_context_register_backend("OpenGL 1.3", "SDL3", backend);
}
7 changes: 7 additions & 0 deletions src/servers/render_context/render_context.h
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

#include <error.h>
#include <types/types.h>
#include <types/signal.h>

#include <servers/window_server/window_server.h>

Expand All @@ -23,6 +24,12 @@ typedef struct {
boolean (*_init)(void);
boolean (*_quit)(void);

// TODO: change to StringSlice when fix/string PR is will be allowed
SignalCallbackHandler (*signal_connect)(c_str name, SignalCallbackFunc func, void* ctx);
boolean (*signal_disconnect)(c_str name, SignalCallbackHandler);
i32 (*get_available_signals)(c_str* names_buff, c_str* descriptions_buff);


RenderContextSurface* (*create_surface)(WindowServerWindow* window);
boolean (*destroy_surface)(RenderContextSurface* surface);

Expand Down