commit 061e549

uint  ·  2026-07-21 19:39:14 +0000 UTC
parent 1286cb0
sokol opengl renderer

this is still a big todo; still gotta do the vulkan one and probably
create renderer_hard.c and renderer_soft.c
7 files changed,  +153, -8
+5, -2
 1@@ -16,8 +16,7 @@ typedef uint64_t u64;
 2 
 3 typedef SDL_Window MGWindow;
 4 
 5-/* video backend !only OpenGL for now */
 6-typedef struct {
 7+typedef struct { /* video backend !only OpenGL for now */
 8 	SDL_GLContext gl;
 9 } MGVidBE;
10 
11@@ -31,6 +30,10 @@ typedef struct {
12 	i32         height;
13 } MGContext;
14 
15+/* get drawable screen size. usually different due to hi-dpi options
16+   > probably can stub out on software renderer */
17+void platform_get_drawable_size(MGContext* ctx, i32* width, i32* height);
18+
19 /* initialise resources */
20 void platform_init(MGContext* ctx);
21 
+26, -0
 1@@ -0,0 +1,26 @@
 2+#ifndef RENDERER_H
 3+#define RENDERER_H
 4+
 5+#include <platform/platform.h>
 6+
 7+typedef struct {
 8+	MGContext* ctx;
 9+	i8         pass; /* basically a bool; in
10+			    render pass or not */
11+} MGRenderer;
12+
13+/* create renderer with chosen context
14+   (just GL for now) */
15+void renderer_create(MGContext* ctx, MGRenderer* ren);
16+
17+/* start drawing to screen */
18+void renderer_begin(MGRenderer* ren);
19+
20+/* finish drawing to screen */
21+void renderer_end(MGRenderer* ren);
22+
23+/* destroy renderer resources */
24+void renderer_destroy(MGRenderer* ren);
25+
26+#endif /* RENDERER_H */
27+
+3, -1
 1@@ -3,12 +3,14 @@
 2 
 3 #include <stdio.h>
 4 
 5-typedef enum {
 6+typedef enum { /* TODO: rename to MG_EC_... */
 7 	MG_ERR_EXIT_SUCCESS,
 8 	MG_ERR_EXIT_FAILURE,
 9 
10 	MG_ERR_GL_CTX_CREATE,
11 
12+	MG_ERR_REN_CREATE,
13+
14 	MG_ERR_LAST
15 } MGErrorCodes;
16 
+28, -5
 1@@ -9,33 +9,56 @@ project(
 2 
 3 sources = [
 4 	'source/main.c',
 5-	'source/platform/platform.c',
 6 	'source/util.c',
 7+	'source/platform/platform.c',
 8+]
 9+
10+include_dirs = [
11+	include_directories('include'),
12 ]
13 
14 vendor_inc = [
15 	include_directories('vendor'),
16 ]
17+
18+opengl_dep = dependency('opengl', required: false)
19+if not opengl_dep.found() # fallback (at least for alpine)
20+	opengl_dep = dependency('gl')
21+endif
22+
23 sokol_gfx_lib = static_library(
24 	'sokol_gfx',
25 	'vendor/sokol_gfx.c',
26 	include_directories: vendor_inc,
27+	dependencies: opengl_dep,
28 	override_options: [ 'c_std=c99' ],
29 )
30 
31 sokol_gfx_dep = declare_dependency(
32 	include_directories: vendor_inc,
33 	link_with: sokol_gfx_lib,
34+	dependencies: opengl_dep,
35+)
36+
37+renderer_lib = static_library(
38+	'renderer',
39+	'source/renderer/renderer.c',
40+	include_directories: include_dirs,
41+	dependencies: sokol_gfx_dep,
42+	override_options: [ 'c_std=c99' ],
43+)
44+
45+renderer_dep = declare_dependency(
46+	include_directories: include_dirs,
47+	link_with: renderer_lib,
48+	dependencies: sokol_gfx_dep,
49 )
50 
51 deps = [
52 	dependency('sdl2'),
53-	sokol_gfx_dep,
54+	renderer_dep,
55 ]
56 
57-include_dirs = [
58-	include_directories('include'),
59-]
60 executable(
61 	'magnolia',
62 	sources,
+9, -0
 1@@ -2,6 +2,7 @@
 2 
 3 #include "util.h"
 4 #include "platform/platform.h"
 5+#include "renderer/renderer.h"
 6 
 7 int main(void)
 8 {
 9@@ -12,6 +13,7 @@ int main(void)
10 		0, 0,       /* x, y */
11 		1024, 768,  /* w, h */
12 	};
13+	MGRenderer ren;
14 
15 	mg_log(LOG_INF, "test log info");
16 	mg_log(LOG_ERR, "test log error");
17@@ -19,12 +21,19 @@ int main(void)
18 
19 	platform_init(&ctx);
20 	platform_window_create(&ctx);
21+	renderer_create(&ctx, &ren);
22 
23 	while (platform_poll(&ctx)) {
24+		renderer_begin(&ren);
25+
26+		/* ... */
27+
28+		renderer_end(&ren);
29 		platform_present(&ctx);
30 		SDL_Delay(1); /* TODO: replace with target fps */
31 	}
32 
33+	renderer_destroy(&ren);
34 	platform_shutdown(&ctx);
35 	return MG_ERR_EXIT_SUCCESS;
36 }
+5, -0
 1@@ -3,6 +3,11 @@
 2 #include "util.h"
 3 #include "platform/platform.h"
 4 
 5+void platform_get_drawable_size(MGContext* ctx, i32* width, i32* height)
 6+{
 7+	SDL_GL_GetDrawableSize(ctx->win, width, height);
 8+}
 9+
10 void platform_init(MGContext* ctx)
11 {
12 	(void) ctx;
+77, -0
 1@@ -0,0 +1,77 @@
 2+#include <sokol_gfx.h>
 3+
 4+#include "util.h"
 5+#include "platform/platform.h"
 6+#include "renderer/renderer.h"
 7+
 8+void renderer_create(MGContext* ctx, MGRenderer* ren)
 9+{
10+	sg_desc desc = {0};
11+
12+	ren->ctx = ctx;
13+	ren->pass = 0;
14+
15+	desc.environment.defaults.color_format = SG_PIXELFORMAT_RGBA8;
16+	desc.environment.defaults.depth_format = SG_PIXELFORMAT_DEPTH;
17+	desc.environment.defaults.sample_count = 1;
18+
19+	sg_setup(&desc);
20+
21+	if (!sg_isvalid())
22+		mg_die(MG_ERR_REN_CREATE, "Failed to initialise renderer");
23+}
24+
25+void renderer_begin(MGRenderer* ren)
26+{
27+	sg_pass pass = {0};
28+	i32 width;
29+	i32 height;
30+
31+	ren->pass = 0;
32+
33+	platform_get_drawable_size(ren->ctx, &width, &height);
34+	/* (minimized window?) no need to draw */
35+	if (width <= 0 || height <= 0)
36+		return;
37+
38+	pass.action.colors[0].load_action = SG_LOADACTION_CLEAR;
39+	pass.action.colors[0].clear_value.r = 0.90f;
40+	pass.action.colors[0].clear_value.g = 0.80f;
41+	pass.action.colors[0].clear_value.b = 0.70f;
42+	pass.action.colors[0].clear_value.a = 1.00f;
43+
44+	pass.action.depth.load_action = SG_LOADACTION_CLEAR;
45+	pass.action.depth.clear_value = 1.0f;
46+
47+	/* swapchain descriptor */
48+	pass.swapchain.width = width;
49+	pass.swapchain.height = height;
50+	pass.swapchain.sample_count = 1;
51+	pass.swapchain.color_format = SG_PIXELFORMAT_RGBA8;
52+	pass.swapchain.depth_format = SG_PIXELFORMAT_DEPTH;
53+
54+	pass.swapchain.gl.framebuffer = 0;
55+
56+	sg_begin_pass(&pass);
57+	ren->pass = 1;
58+}
59+
60+void renderer_end(MGRenderer* ren)
61+{
62+	if (!ren->pass)
63+		return;
64+
65+	sg_end_pass();
66+	sg_commit();
67+
68+	ren->pass = 0;
69+}
70+
71+void renderer_destroy(MGRenderer* ren)
72+{
73+	if (sg_isvalid())
74+		sg_shutdown();
75+	ren->ctx = NULL;
76+	ren->pass = 0;
77+}
78+