commit 62f0f04

shrub  ·  2026-07-30 21:20:38 +0000 UTC
parent 0970030
add renderer texture creation from memory
5 files changed,  +78, -25
+9, -0
 1@@ -11,6 +11,12 @@ typedef u32 MGMesh;
 2 typedef u32 MGTexture;
 3 #define MGTEXTURE_INVALID ((MGTexture)0)
 4 
 5+typedef struct {
 6+	const u8* pixels;
 7+	i32 width;
 8+	i32 height;
 9+} MGTextureDesc;
10+
11 typedef struct {
12 	float x;
13 	float y;
14@@ -54,6 +60,9 @@ void renderer_mesh_destroy(MGMesh id);
15 /* load texture from file */
16 MGTexture renderer_texture_load(const char* path);
17 
18+/* create an RGBA8 texture from pixels */
19+MGTexture renderer_texture_create(const MGTextureDesc* desc);
20+
21 /* destroy texture */
22 void renderer_texture_destroy(MGTexture id);
23 
+5, -0
 1@@ -41,6 +41,11 @@ MGTexture renderer_texture_load(const char* path)
 2 	return renderer_backend_texture_load(path);
 3 }
 4 
 5+MGTexture renderer_texture_create(const MGTextureDesc* desc)
 6+{
 7+	return renderer_backend_texture_create(desc);
 8+}
 9+
10 void renderer_texture_destroy(MGTexture texture)
11 {
12 	renderer_backend_texture_destroy(texture);
+1, -0
1@@ -13,6 +13,7 @@ void renderer_backend_mesh_draw(MGMesh mesh, MGTexture texture, const MGMat4* mv
2 void renderer_backend_mesh_destroy(MGMesh mesh);
3 
4 MGTexture renderer_backend_texture_load(const char* path);
5+MGTexture renderer_backend_texture_create(const MGTextureDesc* desc);
6 void renderer_backend_texture_destroy(MGTexture texture);
7 
8 #endif /* RENDERER_BACKEND_H */
+30, -7
 1@@ -450,14 +450,33 @@ void renderer_backend_mesh_destroy(MGMesh id)
 2 
 3 MGTexture renderer_backend_texture_load(const char* path)
 4 {
 5-	RendererTexture* texture;
 6+	stbi_uc* pixels;
 7 	int width;
 8 	int height;
 9 	int channels;
10-	u32 id;
11+	MGTextureDesc desc;
12+	MGTexture texture;
13 
14 	if (!path)
15 		return MGTEXTURE_INVALID;
16+	pixels = stbi_load(path, &width, &height, &channels, 4);
17+	if (!pixels) {
18+		mg_log(LOG_ERR, "Failed to load texture: %s", path);
19+		return MGTEXTURE_INVALID;
20+	}
21+	desc.pixels = pixels;
22+	desc.width = width;
23+	desc.height = height;
24+	texture = renderer_backend_texture_create(&desc);
25+	stbi_image_free(pixels);
26+	return texture;
27+}
28+
29+MGTexture renderer_backend_texture_create(const MGTextureDesc* desc)
30+{
31+	RendererTexture* texture;
32+	size_t size;
33+	u32 id;
34 
35 	/* find free texture slot */
36 	for (id = 1; id < MAX_TEXTURES; id++) {
37@@ -471,14 +490,18 @@ MGTexture renderer_backend_texture_load(const char* path)
38 	}
39 
40 	texture = &ren.textures[id];
41-	texture->pixels = stbi_load(path, &width, &height, &channels, 4);
42+	if (!desc || !desc->pixels || desc->width <= 0 || desc->height <= 0)
43+		return MGTEXTURE_INVALID;
44+	size = (size_t)desc->width * (size_t)desc->height * 4;
45+	texture->pixels = (u8*)malloc(size);
46 	if (!texture->pixels) {
47-		mg_log(LOG_ERR, "Failed to load texture: %s", path);
48+		mg_log(LOG_ERR, "Failed to create texture");
49 		return MGTEXTURE_INVALID;
50 	}
51 
52-	texture->width = width;
53-	texture->height = height;
54+	memcpy(texture->pixels, desc->pixels, size);
55+	texture->width = desc->width;
56+	texture->height = desc->height;
57 	texture->used = 1;
58 
59 	return id;
60@@ -495,6 +518,6 @@ void renderer_backend_texture_destroy(MGTexture id)
61 	if (!texture->used)
62 		return;
63 
64-	stbi_image_free(texture->pixels);
65+	free(texture->pixels);
66 	*texture = (RendererTexture){ 0 };
67 }
+33, -18
 1@@ -356,19 +356,40 @@ void renderer_backend_mesh_destroy(MGMesh id)
 2 
 3 MGTexture renderer_backend_texture_load(const char* path)
 4 {
 5-	sg_image_desc image_desc = { 0 };
 6-	sg_view_desc view_desc = { 0 };
 7-	RendererTexture* texture;
 8 	stbi_uc* pixels;
 9 	int width;
10 	int height;
11 	int channels;
12-	u32 id;
13+	MGTextureDesc desc;
14+	MGTexture texture;
15 
16 	if (!path)
17 		return MGTEXTURE_INVALID;
18 
19-	/* find free texture slot */
20+	pixels = stbi_load(path, &width, &height, &channels, 4);
21+	if (!pixels) {
22+		mg_log(LOG_ERR, "Failed to load texture: %s", path);
23+		return MGTEXTURE_INVALID;
24+	}
25+
26+	desc.pixels = pixels;
27+	desc.width = width;
28+	desc.height = height;
29+	texture = renderer_backend_texture_create(&desc);
30+	stbi_image_free(pixels);
31+	return texture;
32+}
33+
34+MGTexture renderer_backend_texture_create(const MGTextureDesc* desc)
35+{
36+	sg_image_desc image_desc = { 0 };
37+	sg_view_desc view_desc = { 0 };
38+	RendererTexture* texture;
39+	u32 id;
40+
41+	if (!desc || !desc->pixels || desc->width <= 0 || desc->height <= 0)
42+		return MGTEXTURE_INVALID;
43+
44 	for (id = 1; id < MAX_TEXTURES; id++) {
45 		if (!ren.textures[id].used)
46 			break;
47@@ -380,23 +401,17 @@ MGTexture renderer_backend_texture_load(const char* path)
48 	}
49 
50 	texture = &ren.textures[id];
51-	pixels = stbi_load(path, &width, &height, &channels, 4);
52-	if (!pixels) {
53-		mg_log(LOG_ERR, "Failed to load texture: %s", path);
54-		return MGTEXTURE_INVALID;
55-	}
56-
57-	image_desc.width = width;
58-	image_desc.height = height;
59+	image_desc.width = desc->width;
60+	image_desc.height = desc->height;
61 	image_desc.pixel_format = SG_PIXELFORMAT_RGBA8;
62-	image_desc.data.mip_levels[0].ptr = pixels;
63-	image_desc.data.mip_levels[0].size = width * height * 4;
64+	image_desc.data.mip_levels[0].ptr = desc->pixels;
65+	image_desc.data.mip_levels[0].size =
66+	    (size_t)desc->width * (size_t)desc->height * 4;
67 
68 	texture->image = sg_make_image(&image_desc);
69-	stbi_image_free(pixels);
70 	if (sg_query_image_state(texture->image) != SG_RESOURCESTATE_VALID) {
71 		*texture = (RendererTexture){ 0 };
72-		mg_log(LOG_ERR, "Failed to create texture: %s", path);
73+		mg_log(LOG_ERR, "Failed to create texture");
74 		return MGTEXTURE_INVALID;
75 	}
76 
77@@ -406,7 +421,7 @@ MGTexture renderer_backend_texture_load(const char* path)
78 	if (sg_query_view_state(texture->view) != SG_RESOURCESTATE_VALID) {
79 		sg_destroy_image(texture->image);
80 		*texture = (RendererTexture){ 0 };
81-		mg_log(LOG_ERR, "Failed to create texture view: %s", path);
82+		mg_log(LOG_ERR, "Failed to create texture view");
83 		return MGTEXTURE_INVALID;
84 	}
85