diff --git a/libc3/window/cairo/quartz/window_cairo_quartz_view.m b/libc3/window/cairo/quartz/window_cairo_quartz_view.m
index 7383305..a98df3c 100644
--- a/libc3/window/cairo/quartz/window_cairo_quartz_view.m
+++ b/libc3/window/cairo/quartz/window_cairo_quartz_view.m
@@ -42,7 +42,7 @@
self.bounds.size.width,
self.bounds.size.height);
cairo_t *cr = cairo_create(surface);
- if (! self.window_cairo->render(self.window_cairo, cr)) {
+ if (! self.window_cairo->render(self.window_cairo)) {
[self.window close];
[self.window release];
[[NSApplication sharedApplication] stop:nil];
diff --git a/libc3/window/sdl2/disabled/sdl2_sprite.c b/libc3/window/sdl2/disabled/sdl2_sprite.c
new file mode 100644
index 0000000..ba13ab0
--- /dev/null
+++ b/libc3/window/sdl2/disabled/sdl2_sprite.c
@@ -0,0 +1,369 @@
+/* c3
+ * Copyright 2022,2023 kmx.io <contact@kmx.io>
+ *
+ * Permission is hereby granted to use this software granted the above
+ * copyright notice and this permission paragraph are included in all
+ * copies and substantial portions of this software.
+ *
+ * THIS SOFTWARE IS PROVIDED "AS-IS" WITHOUT ANY GUARANTEE OF
+ * PURPOSE AND PERFORMANCE. IN NO EVENT WHATSOEVER SHALL THE
+ * AUTHOR BE CONSIDERED LIABLE FOR THE USE AND PERFORMANCE OF
+ * THIS SOFTWARE.
+ */
+#include <libc3/c3.h>
+#include "sdl2_sprite.h"
+
+void sdl2_sprite_bind (const s_sdl2_sprite *sprite, uw frame)
+{
+ assert(sprite);
+ assert(frame < sprite->frame_count);
+ frame %= sprite->frame_count;
+ assert(glGetError() == GL_NO_ERROR);
+ glBindTexture(GL_TEXTURE_2D, sprite->texture[frame]);
+ assert(glGetError() == GL_NO_ERROR);
+}
+
+void sdl2_sprite_clean (s_sdl2_sprite *sprite)
+{
+ assert(sprite);
+ str_clean(&sprite->path);
+ str_clean(&sprite->real_path);
+ glDeleteTextures(sprite->frame_count, sprite->texture);
+ free(sprite->texture);
+}
+
+static bool png_info_to_gl_info (s32 png_color_type,
+ s32 png_bit_depth,
+ GLenum *gl_format,
+ GLint *gl_internal_format,
+ GLenum *gl_type,
+ u8 *components)
+{
+ switch (png_bit_depth) {
+ case 8: *gl_type = GL_UNSIGNED_BYTE; break;
+ case 16: *gl_type = GL_UNSIGNED_SHORT; break;
+ default: *gl_type = 0; return false;
+ }
+ switch (png_color_type) {
+ case PNG_COLOR_TYPE_GRAY:
+ *components = 1;
+ *gl_format = GL_RED;
+ switch (png_bit_depth) {
+ case 8: *gl_internal_format = GL_RED; break;
+ case 16: *gl_internal_format = GL_RED; break;
+ default: *gl_internal_format = 0; return false;
+ }
+ break;
+ case PNG_COLOR_TYPE_GRAY_ALPHA:
+ *components = 2;
+ *gl_format = GL_RG;
+ switch (png_bit_depth) {
+ case 8: *gl_internal_format = GL_RG; break;
+ case 16: *gl_internal_format = GL_RG; break;
+ default: *gl_internal_format = 0; return false;
+ }
+ break;
+ case PNG_COLOR_TYPE_RGB:
+ *components = 3;
+ *gl_format = GL_RGB;
+ switch (png_bit_depth) {
+ case 8: *gl_internal_format = GL_RGB; break;
+ case 16: *gl_internal_format = GL_RGB; break;
+ default: *gl_internal_format = 0; return false;
+ }
+ break;
+ case PNG_COLOR_TYPE_RGBA:
+ *components = 4;
+ *gl_format = GL_RGBA;
+ switch (png_bit_depth) {
+ case 8: *gl_internal_format = GL_RGBA8; break;
+ case 16: *gl_internal_format = GL_RGBA16; break;
+ default: *gl_internal_format = 0; return false;
+ }
+ break;
+ default:
+ *components = 0;
+ *gl_format = 0;
+ *gl_internal_format = 0;
+ return false;
+ }
+ return true;
+}
+
+s_sdl2_sprite * sdl2_sprite_init (s_sdl2_sprite *sprite,
+ const s8 *path,
+ uw dim_x, uw dim_y,
+ uw frame_count)
+{
+ u8 *data;
+ FILE *fp;
+ GLenum gl_format;
+ GLint gl_internal_format;
+ GLenum gl_type;
+ uw i;
+ s32 png_bit_depth;
+ s32 png_color_type;
+ u8 png_components;
+ png_bytep png_data;
+ u32 png_h;
+ u8 png_header[8]; // maximum size is 8
+ png_infop png_info;
+ uw png_pixel_size;
+ png_structp png_read;
+ png_bytep *png_row;
+ u32 png_w;
+ u8 *sprite_data;
+ uw sprite_stride;
+ uw x;
+ uw y;
+ uw v;
+ assert(sprite);
+ assert(path);
+ assert(dim_x);
+ assert(dim_y);
+ assert(glGetError() == GL_NO_ERROR);
+ sprite->frame_count = (frame_count > 0) ? frame_count :
+ (dim_x * dim_y);
+ str_init_copy_1(&sprite->path, path);
+ if (! file_search(&sprite->path, sym_1("r"), &sprite->real_path)) {
+ err_write_1("sdl2_sprite_init: file not found: ");
+ err_puts(path);
+ str_clean(&sprite->path);
+ return NULL;
+ }
+ fp = fopen(sprite->real_path.ptr.ps8, "rb");
+ if (! fp) {
+ err_write_1("sdl2_sprite_init: fopen: ");
+ err_puts(sprite->real_path.ptr.ps8);
+ str_clean(&sprite->path);
+ str_clean(&sprite->real_path);
+ return NULL;
+ }
+ if (fread(png_header, 1, sizeof(png_header), fp) !=
+ sizeof(png_header)) {
+ err_write_1("sdl2_sprite_init: fread: ");
+ err_puts(sprite->real_path.ptr.ps8);
+ fclose(fp);
+ str_clean(&sprite->path);
+ str_clean(&sprite->real_path);
+ return NULL;
+ }
+ if (png_sig_cmp(png_header, 0, sizeof(png_header))) {
+ err_write_1("sdl2_sprite_init: not a png: ");
+ err_puts(sprite->real_path.ptr.ps8);
+ fclose(fp);
+ str_clean(&sprite->path);
+ str_clean(&sprite->real_path);
+ return NULL;
+ }
+ png_read = png_create_read_struct(PNG_LIBPNG_VER_STRING, NULL, NULL,
+ NULL);
+ if (! png_read) {
+ err_write_1("sdl2_sprite_init: png_create_read_struct: ");
+ err_puts(sprite->real_path.ptr.ps8);
+ fclose(fp);
+ str_clean(&sprite->path);
+ str_clean(&sprite->real_path);
+ return NULL;
+ }
+ png_info = png_create_info_struct(png_read);
+ if (! png_info) {
+ err_write_1("sdl2_sprite_init: png_create_info_struct: ");
+ err_puts(sprite->real_path.ptr.ps8);
+ png_destroy_read_struct(&png_read, NULL, NULL);
+ fclose(fp);
+ str_clean(&sprite->path);
+ str_clean(&sprite->real_path);
+ return NULL;
+ }
+ gl_internal_format = 0;
+ gl_format = 0;
+ gl_type = 0;
+ png_components = 0;
+ if (setjmp(png_jmpbuf(png_read))) {
+ png_destroy_read_struct(&png_read, &png_info, NULL);
+ fclose(fp);
+ str_clean(&sprite->path);
+ str_clean(&sprite->real_path);
+ return NULL;
+ }
+ png_set_sig_bytes(png_read, sizeof(png_header));
+ png_init_io(png_read, fp);
+ png_read_info(png_read, png_info);
+ png_get_IHDR(png_read, png_info, &png_w, &png_h,
+ &png_bit_depth, &png_color_type,
+ NULL, NULL, NULL);
+ if (png_color_type == PNG_COLOR_TYPE_PALETTE)
+ png_set_palette_to_rgb(png_read);
+ if (! png_info_to_gl_info(png_color_type, png_bit_depth, &gl_format,
+ &gl_internal_format, &gl_type,
+ &png_components)) {
+ if (! gl_format || ! png_components) {
+ err_write_1("sdl2_sprite_init: unknown PNG color type ");
+ err_inspect_s32(&png_color_type);
+ err_write_1(": ");
+ err_puts(sprite->real_path.ptr.ps8);
+ }
+ if (! gl_internal_format) {
+ err_write_1("sdl2_sprite_init: unknown OpenGL internal format: ");
+ err_puts(sprite->real_path.ptr.ps8);
+ }
+ if (! gl_type) {
+ err_write_1("sdl2_sprite_init: unknown OpenGL type: ");
+ err_puts(sprite->real_path.ptr.ps8);
+ }
+ png_destroy_read_struct(&png_read, &png_info, NULL);
+ fclose(fp);
+ str_clean(&sprite->path);
+ str_clean(&sprite->real_path);
+ return NULL;
+ }
+ png_pixel_size = (png_bit_depth / 8) * png_components;
+ if (! png_pixel_size)
+ png_error(png_read, "unknown png pixel size");
+ if (png_h > PNG_SIZE_MAX / (png_w * png_pixel_size))
+ png_error(png_read, "image_data buffer would be too large");
+ png_data = png_malloc(png_read, png_h * png_w * png_pixel_size);
+ png_row = png_malloc(png_read, png_h * sizeof(png_bytep));
+ i = 0;
+ while (i < png_h) {
+ png_row[i] = png_data + i * png_w * png_pixel_size;
+ i++;
+ }
+ if (png_bit_depth < 8)
+ png_set_packing(png_read);
+ png_read_image(png_read, png_row);
+ png_destroy_read_struct(&png_read, &png_info, NULL);
+ fclose(fp);
+ sprite->total_w = png_w;
+ sprite->total_h = png_h;
+ sprite->dim_x = dim_x;
+ sprite->dim_y = dim_y;
+ sprite->w = sprite->total_w / dim_x;
+ sprite->h = sprite->total_h / dim_y;
+ sprite->texture = calloc(sprite->frame_count, sizeof(GLuint));
+ if (! sprite->texture) {
+ err_puts("sdl2_sprite_init: sprite->texture:"
+ " failed to allocate memory");
+ str_clean(&sprite->path);
+ str_clean(&sprite->real_path);
+ return NULL;
+ }
+ glGenTextures(sprite->frame_count, sprite->texture);
+ GLenum gl_error = glGetError();
+ if (gl_error != GL_NO_ERROR) {
+ err_write_1("sdl2_sprite_init: ");
+ err_inspect_str(&sprite->real_path);
+ err_write_1(": glGenTextures: ");
+ err_puts((const s8 *) gluErrorString(gl_error));
+ free(sprite->texture);
+ str_clean(&sprite->path);
+ str_clean(&sprite->real_path);
+ return NULL;
+ }
+ sprite_stride = sprite->w * png_pixel_size;
+ data = malloc(sprite->h * sprite_stride);
+ if (! data) {
+ err_write_1("sdl2_sprite_init: failed to allocate memory: ");
+ err_puts(sprite->real_path.ptr.ps8);
+ free(sprite->texture);
+ str_clean(&sprite->path);
+ str_clean(&sprite->real_path);
+ return NULL;
+ }
+ i = 0;
+ y = 0;
+ while (i < sprite->frame_count && y < dim_y) {
+ x = 0;
+ while (i < sprite->frame_count && x < dim_x) {
+ sprite_data = data + sprite_stride * sprite->h;
+ v = 0;
+ while (v < sprite->h) {
+ sprite_data -= sprite_stride;
+ memcpy(sprite_data,
+ png_row[y * sprite->h + v] + x * sprite_stride,
+ sprite_stride);
+ v++;
+ }
+ glBindTexture(GL_TEXTURE_2D, sprite->texture[i]);
+ gl_error = glGetError();
+ if (gl_error != GL_NO_ERROR) {
+ err_write_1("sdl2_sprite_init: ");
+ err_inspect_str(&sprite->real_path);
+ err_write_1(": glBindTexture: ");
+ err_puts((const s8 *) gluErrorString(gl_error));
+ return NULL;
+ }
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S,
+ GL_CLAMP_TO_EDGE);
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T,
+ GL_CLAMP_TO_EDGE);
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER,
+ GL_LINEAR_MIPMAP_LINEAR);
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
+ gl_error = glGetError();
+ if (gl_error != GL_NO_ERROR) {
+ err_write_1("sdl2_sprite_init: ");
+ err_inspect_str(&sprite->real_path);
+ err_write_1(": glTexParameteri: ");
+ err_puts((const s8 *) gluErrorString(gl_error));
+ return NULL;
+ }
+ glTexImage2D(GL_TEXTURE_2D, 0, gl_format, sprite->w, sprite->h,
+ 0, gl_format, gl_type, data);
+ //glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, sprite->w, sprite->h,
+ // 0, GL_RGBA, GL_UNSIGNED_BYTE, data);
+ gl_error = glGetError();
+ if (gl_error != GL_NO_ERROR) {
+ err_write_1("sdl2_sprite_init: ");
+ err_inspect_str(&sprite->real_path);
+ err_write_1(": glTexImage2D: ");
+ err_puts((const s8 *) gluErrorString(gl_error));
+ return NULL;
+ }
+ glGenerateMipmap(GL_TEXTURE_2D);
+ assert(glGetError() == GL_NO_ERROR);
+ i++;
+ x++;
+ }
+ y++;
+ }
+ glBindTexture(GL_TEXTURE_2D, 0);
+ free(data);
+ free(png_data);
+ free(png_row);
+ return sprite;
+}
+
+void sdl2_sprite_render (const s_sdl2_sprite *sprite, uw frame)
+{
+ assert(sprite);
+ assert(frame < sprite->frame_count);
+ frame %= sprite->frame_count;
+ glColor4f(1, 1, 1, 1);
+ glEnable(GL_BLEND);
+ glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
+ glDisable(GL_CULL_FACE);
+ glEnable(GL_TEXTURE_2D);
+ glBindTexture(GL_TEXTURE_2D, sprite->texture[frame]);
+ glBegin(GL_QUADS); {
+ glTexCoord2f(0, 1);
+ glVertex2d(0, sprite->h);
+ glTexCoord2f(0, 0);
+ glVertex2i(0, 0);
+ glTexCoord2f(1, 0);
+ glVertex2i(sprite->w, 0);
+ glTexCoord2f(1, 1);
+ glVertex2d(sprite->w, sprite->h);
+ } glEnd();
+ glBindTexture(GL_TEXTURE_2D, 0);
+ glDisable(GL_TEXTURE_2D);
+ /*
+ glBegin(GL_LINE_LOOP); {
+ glVertex2d(0, sprite->h);
+ glVertex2i(0, 0);
+ glVertex2i(sprite->w, 0);
+ glVertex2d(sprite->w, sprite->h);
+ } glEnd();
+ */
+}
diff --git a/libc3/window/sdl2/disabled/sdl2_sprite.h b/libc3/window/sdl2/disabled/sdl2_sprite.h
new file mode 100644
index 0000000..675992d
--- /dev/null
+++ b/libc3/window/sdl2/disabled/sdl2_sprite.h
@@ -0,0 +1,29 @@
+/* c3
+ * Copyright 2022,2023 kmx.io <contact@kmx.io>
+ *
+ * Permission is hereby granted to use this software granted the above
+ * copyright notice and this permission paragraph are included in all
+ * copies and substantial portions of this software.
+ *
+ * THIS SOFTWARE IS PROVIDED "AS-IS" WITHOUT ANY GUARANTEE OF
+ * PURPOSE AND PERFORMANCE. IN NO EVENT WHATSOEVER SHALL THE
+ * AUTHOR BE CONSIDERED LIABLE FOR THE USE AND PERFORMANCE OF
+ * THIS SOFTWARE.
+ */
+#ifndef SDL2_SPRITE_H
+#define SDL2_SPRITE_H
+
+#include "types.h"
+
+/* stack allocation compatible functions */
+void sdl2_sprite_clean (s_sdl2_sprite *sprite);
+s_sdl2_sprite * sdl2_sprite_init (s_sdl2_sprite *sprite,
+ const s8 *path,
+ uw dim_x, uw dim_y,
+ uw frame_count);
+
+/* operations */
+void sdl2_sprite_bind (const s_sdl2_sprite *sprite, uw frame);
+void sdl2_sprite_render (const s_sdl2_sprite *sprite, uw frame);
+
+#endif /* CAIRO_SPRITE_H */
diff --git a/libc3/window/sdl2/gl_deprecated.c b/libc3/window/sdl2/gl_deprecated.c
new file mode 100644
index 0000000..dd77e39
--- /dev/null
+++ b/libc3/window/sdl2/gl_deprecated.c
@@ -0,0 +1,19 @@
+/* c3
+ * Copyright 2022,2023 kmx.io <contact@kmx.io>
+ *
+ * Permission is hereby granted to use this software granted the above
+ * copyright notice and this permission paragraph are included in all
+ * copies and substantial portions of this software.
+ *
+ * THIS SOFTWARE IS PROVIDED "AS-IS" WITHOUT ANY GUARANTEE OF
+ * PURPOSE AND PERFORMANCE. IN NO EVENT WHATSOEVER SHALL THE
+ * AUTHOR BE CONSIDERED LIABLE FOR THE USE AND PERFORMANCE OF
+ * THIS SOFTWARE.
+ */
+#define GL_SILENCE_DEPRECATION 1
+#include "gl_deprecated.h"
+
+const s8 * gl_error_string (GLenum error)
+{
+ return (const s8 *) gluErrorString(error);
+}
diff --git a/libc3/window/sdl2/gl_deprecated.h b/libc3/window/sdl2/gl_deprecated.h
new file mode 100644
index 0000000..0699465
--- /dev/null
+++ b/libc3/window/sdl2/gl_deprecated.h
@@ -0,0 +1,20 @@
+/* c3
+ * Copyright 2022,2023 kmx.io <contact@kmx.io>
+ *
+ * Permission is hereby granted to use this software granted the above
+ * copyright notice and this permission paragraph are included in all
+ * copies and substantial portions of this software.
+ *
+ * THIS SOFTWARE IS PROVIDED "AS-IS" WITHOUT ANY GUARANTEE OF
+ * PURPOSE AND PERFORMANCE. IN NO EVENT WHATSOEVER SHALL THE
+ * AUTHOR BE CONSIDERED LIABLE FOR THE USE AND PERFORMANCE OF
+ * THIS SOFTWARE.
+ */
+#ifndef GL_DEPRECATED_H
+#define GL_DEPRECATED_H
+
+#include "types.h"
+
+const s8 * gl_error_string (GLenum error);
+
+#endif /* GL_DEPRECATED_H */
diff --git a/libc3/window/sdl2/gl_lines.h b/libc3/window/sdl2/gl_lines.h
index e0fbcce..1c958b5 100644
--- a/libc3/window/sdl2/gl_lines.h
+++ b/libc3/window/sdl2/gl_lines.h
@@ -22,7 +22,7 @@ s_gl_lines * gl_lines_init (s_gl_lines *lines);
/* Heap-allocation functions, call gl_lines_delete after use. */
void gl_lines_delete (s_gl_lines *lines);
-s_gl_lines * gl_lines_new ();
+s_gl_lines * gl_lines_new (void);
/* Operators. */
s_gl_lines * gl_lines_allocate (s_gl_lines *lines, uw lines_count);
diff --git a/libc3/window/sdl2/gl_sprite.c b/libc3/window/sdl2/gl_sprite.c
index b87c764..fb1c54e 100644
--- a/libc3/window/sdl2/gl_sprite.c
+++ b/libc3/window/sdl2/gl_sprite.c
@@ -11,6 +11,7 @@
* THIS SOFTWARE.
*/
#include <libc3/c3.h>
+#include "gl_deprecated.h"
#include "gl_object.h"
#include "gl_point_2d.h"
#include "gl_point_3d.h"
@@ -262,7 +263,7 @@ s_gl_sprite * gl_sprite_init (s_gl_sprite *sprite, const s8 *path,
err_write_1("sdl2_sprite_init: ");
err_inspect_str(&tmp.real_path);
err_write_1(": glGenTextures: ");
- err_puts((const s8 *) gluErrorString(gl_error));
+ err_puts(gl_error_string(gl_error));
free(tmp.texture);
str_clean(&tmp.path);
str_clean(&tmp.real_path);
@@ -298,7 +299,7 @@ s_gl_sprite * gl_sprite_init (s_gl_sprite *sprite, const s8 *path,
err_write_1("sdl2_sprite_init: ");
err_inspect_str(&tmp.real_path);
err_write_1(": glBindTexture: ");
- err_puts((const s8 *) gluErrorString(gl_error));
+ err_puts(gl_error_string(gl_error));
return NULL;
}
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S,
@@ -313,7 +314,7 @@ s_gl_sprite * gl_sprite_init (s_gl_sprite *sprite, const s8 *path,
err_write_1("sdl2_sprite_init: ");
err_inspect_str(&tmp.real_path);
err_write_1(": glTexParameteri: ");
- err_puts((const s8 *) gluErrorString(gl_error));
+ err_puts(gl_error_string(gl_error));
return NULL;
}
glTexImage2D(GL_TEXTURE_2D, 0, gl_format, tmp.w, tmp.h,
@@ -325,7 +326,7 @@ s_gl_sprite * gl_sprite_init (s_gl_sprite *sprite, const s8 *path,
err_write_1("sdl2_sprite_init: ");
err_inspect_str(&tmp.real_path);
err_write_1(": glTexImage2D: ");
- err_puts((const s8 *) gluErrorString(gl_error));
+ err_puts(gl_error_string(gl_error));
return NULL;
}
glGenerateMipmap(GL_TEXTURE_2D);
diff --git a/libc3/window/sdl2/sdl2_sprite.c b/libc3/window/sdl2/sdl2_sprite.c
deleted file mode 100644
index ba13ab0..0000000
--- a/libc3/window/sdl2/sdl2_sprite.c
+++ /dev/null
@@ -1,369 +0,0 @@
-/* c3
- * Copyright 2022,2023 kmx.io <contact@kmx.io>
- *
- * Permission is hereby granted to use this software granted the above
- * copyright notice and this permission paragraph are included in all
- * copies and substantial portions of this software.
- *
- * THIS SOFTWARE IS PROVIDED "AS-IS" WITHOUT ANY GUARANTEE OF
- * PURPOSE AND PERFORMANCE. IN NO EVENT WHATSOEVER SHALL THE
- * AUTHOR BE CONSIDERED LIABLE FOR THE USE AND PERFORMANCE OF
- * THIS SOFTWARE.
- */
-#include <libc3/c3.h>
-#include "sdl2_sprite.h"
-
-void sdl2_sprite_bind (const s_sdl2_sprite *sprite, uw frame)
-{
- assert(sprite);
- assert(frame < sprite->frame_count);
- frame %= sprite->frame_count;
- assert(glGetError() == GL_NO_ERROR);
- glBindTexture(GL_TEXTURE_2D, sprite->texture[frame]);
- assert(glGetError() == GL_NO_ERROR);
-}
-
-void sdl2_sprite_clean (s_sdl2_sprite *sprite)
-{
- assert(sprite);
- str_clean(&sprite->path);
- str_clean(&sprite->real_path);
- glDeleteTextures(sprite->frame_count, sprite->texture);
- free(sprite->texture);
-}
-
-static bool png_info_to_gl_info (s32 png_color_type,
- s32 png_bit_depth,
- GLenum *gl_format,
- GLint *gl_internal_format,
- GLenum *gl_type,
- u8 *components)
-{
- switch (png_bit_depth) {
- case 8: *gl_type = GL_UNSIGNED_BYTE; break;
- case 16: *gl_type = GL_UNSIGNED_SHORT; break;
- default: *gl_type = 0; return false;
- }
- switch (png_color_type) {
- case PNG_COLOR_TYPE_GRAY:
- *components = 1;
- *gl_format = GL_RED;
- switch (png_bit_depth) {
- case 8: *gl_internal_format = GL_RED; break;
- case 16: *gl_internal_format = GL_RED; break;
- default: *gl_internal_format = 0; return false;
- }
- break;
- case PNG_COLOR_TYPE_GRAY_ALPHA:
- *components = 2;
- *gl_format = GL_RG;
- switch (png_bit_depth) {
- case 8: *gl_internal_format = GL_RG; break;
- case 16: *gl_internal_format = GL_RG; break;
- default: *gl_internal_format = 0; return false;
- }
- break;
- case PNG_COLOR_TYPE_RGB:
- *components = 3;
- *gl_format = GL_RGB;
- switch (png_bit_depth) {
- case 8: *gl_internal_format = GL_RGB; break;
- case 16: *gl_internal_format = GL_RGB; break;
- default: *gl_internal_format = 0; return false;
- }
- break;
- case PNG_COLOR_TYPE_RGBA:
- *components = 4;
- *gl_format = GL_RGBA;
- switch (png_bit_depth) {
- case 8: *gl_internal_format = GL_RGBA8; break;
- case 16: *gl_internal_format = GL_RGBA16; break;
- default: *gl_internal_format = 0; return false;
- }
- break;
- default:
- *components = 0;
- *gl_format = 0;
- *gl_internal_format = 0;
- return false;
- }
- return true;
-}
-
-s_sdl2_sprite * sdl2_sprite_init (s_sdl2_sprite *sprite,
- const s8 *path,
- uw dim_x, uw dim_y,
- uw frame_count)
-{
- u8 *data;
- FILE *fp;
- GLenum gl_format;
- GLint gl_internal_format;
- GLenum gl_type;
- uw i;
- s32 png_bit_depth;
- s32 png_color_type;
- u8 png_components;
- png_bytep png_data;
- u32 png_h;
- u8 png_header[8]; // maximum size is 8
- png_infop png_info;
- uw png_pixel_size;
- png_structp png_read;
- png_bytep *png_row;
- u32 png_w;
- u8 *sprite_data;
- uw sprite_stride;
- uw x;
- uw y;
- uw v;
- assert(sprite);
- assert(path);
- assert(dim_x);
- assert(dim_y);
- assert(glGetError() == GL_NO_ERROR);
- sprite->frame_count = (frame_count > 0) ? frame_count :
- (dim_x * dim_y);
- str_init_copy_1(&sprite->path, path);
- if (! file_search(&sprite->path, sym_1("r"), &sprite->real_path)) {
- err_write_1("sdl2_sprite_init: file not found: ");
- err_puts(path);
- str_clean(&sprite->path);
- return NULL;
- }
- fp = fopen(sprite->real_path.ptr.ps8, "rb");
- if (! fp) {
- err_write_1("sdl2_sprite_init: fopen: ");
- err_puts(sprite->real_path.ptr.ps8);
- str_clean(&sprite->path);
- str_clean(&sprite->real_path);
- return NULL;
- }
- if (fread(png_header, 1, sizeof(png_header), fp) !=
- sizeof(png_header)) {
- err_write_1("sdl2_sprite_init: fread: ");
- err_puts(sprite->real_path.ptr.ps8);
- fclose(fp);
- str_clean(&sprite->path);
- str_clean(&sprite->real_path);
- return NULL;
- }
- if (png_sig_cmp(png_header, 0, sizeof(png_header))) {
- err_write_1("sdl2_sprite_init: not a png: ");
- err_puts(sprite->real_path.ptr.ps8);
- fclose(fp);
- str_clean(&sprite->path);
- str_clean(&sprite->real_path);
- return NULL;
- }
- png_read = png_create_read_struct(PNG_LIBPNG_VER_STRING, NULL, NULL,
- NULL);
- if (! png_read) {
- err_write_1("sdl2_sprite_init: png_create_read_struct: ");
- err_puts(sprite->real_path.ptr.ps8);
- fclose(fp);
- str_clean(&sprite->path);
- str_clean(&sprite->real_path);
- return NULL;
- }
- png_info = png_create_info_struct(png_read);
- if (! png_info) {
- err_write_1("sdl2_sprite_init: png_create_info_struct: ");
- err_puts(sprite->real_path.ptr.ps8);
- png_destroy_read_struct(&png_read, NULL, NULL);
- fclose(fp);
- str_clean(&sprite->path);
- str_clean(&sprite->real_path);
- return NULL;
- }
- gl_internal_format = 0;
- gl_format = 0;
- gl_type = 0;
- png_components = 0;
- if (setjmp(png_jmpbuf(png_read))) {
- png_destroy_read_struct(&png_read, &png_info, NULL);
- fclose(fp);
- str_clean(&sprite->path);
- str_clean(&sprite->real_path);
- return NULL;
- }
- png_set_sig_bytes(png_read, sizeof(png_header));
- png_init_io(png_read, fp);
- png_read_info(png_read, png_info);
- png_get_IHDR(png_read, png_info, &png_w, &png_h,
- &png_bit_depth, &png_color_type,
- NULL, NULL, NULL);
- if (png_color_type == PNG_COLOR_TYPE_PALETTE)
- png_set_palette_to_rgb(png_read);
- if (! png_info_to_gl_info(png_color_type, png_bit_depth, &gl_format,
- &gl_internal_format, &gl_type,
- &png_components)) {
- if (! gl_format || ! png_components) {
- err_write_1("sdl2_sprite_init: unknown PNG color type ");
- err_inspect_s32(&png_color_type);
- err_write_1(": ");
- err_puts(sprite->real_path.ptr.ps8);
- }
- if (! gl_internal_format) {
- err_write_1("sdl2_sprite_init: unknown OpenGL internal format: ");
- err_puts(sprite->real_path.ptr.ps8);
- }
- if (! gl_type) {
- err_write_1("sdl2_sprite_init: unknown OpenGL type: ");
- err_puts(sprite->real_path.ptr.ps8);
- }
- png_destroy_read_struct(&png_read, &png_info, NULL);
- fclose(fp);
- str_clean(&sprite->path);
- str_clean(&sprite->real_path);
- return NULL;
- }
- png_pixel_size = (png_bit_depth / 8) * png_components;
- if (! png_pixel_size)
- png_error(png_read, "unknown png pixel size");
- if (png_h > PNG_SIZE_MAX / (png_w * png_pixel_size))
- png_error(png_read, "image_data buffer would be too large");
- png_data = png_malloc(png_read, png_h * png_w * png_pixel_size);
- png_row = png_malloc(png_read, png_h * sizeof(png_bytep));
- i = 0;
- while (i < png_h) {
- png_row[i] = png_data + i * png_w * png_pixel_size;
- i++;
- }
- if (png_bit_depth < 8)
- png_set_packing(png_read);
- png_read_image(png_read, png_row);
- png_destroy_read_struct(&png_read, &png_info, NULL);
- fclose(fp);
- sprite->total_w = png_w;
- sprite->total_h = png_h;
- sprite->dim_x = dim_x;
- sprite->dim_y = dim_y;
- sprite->w = sprite->total_w / dim_x;
- sprite->h = sprite->total_h / dim_y;
- sprite->texture = calloc(sprite->frame_count, sizeof(GLuint));
- if (! sprite->texture) {
- err_puts("sdl2_sprite_init: sprite->texture:"
- " failed to allocate memory");
- str_clean(&sprite->path);
- str_clean(&sprite->real_path);
- return NULL;
- }
- glGenTextures(sprite->frame_count, sprite->texture);
- GLenum gl_error = glGetError();
- if (gl_error != GL_NO_ERROR) {
- err_write_1("sdl2_sprite_init: ");
- err_inspect_str(&sprite->real_path);
- err_write_1(": glGenTextures: ");
- err_puts((const s8 *) gluErrorString(gl_error));
- free(sprite->texture);
- str_clean(&sprite->path);
- str_clean(&sprite->real_path);
- return NULL;
- }
- sprite_stride = sprite->w * png_pixel_size;
- data = malloc(sprite->h * sprite_stride);
- if (! data) {
- err_write_1("sdl2_sprite_init: failed to allocate memory: ");
- err_puts(sprite->real_path.ptr.ps8);
- free(sprite->texture);
- str_clean(&sprite->path);
- str_clean(&sprite->real_path);
- return NULL;
- }
- i = 0;
- y = 0;
- while (i < sprite->frame_count && y < dim_y) {
- x = 0;
- while (i < sprite->frame_count && x < dim_x) {
- sprite_data = data + sprite_stride * sprite->h;
- v = 0;
- while (v < sprite->h) {
- sprite_data -= sprite_stride;
- memcpy(sprite_data,
- png_row[y * sprite->h + v] + x * sprite_stride,
- sprite_stride);
- v++;
- }
- glBindTexture(GL_TEXTURE_2D, sprite->texture[i]);
- gl_error = glGetError();
- if (gl_error != GL_NO_ERROR) {
- err_write_1("sdl2_sprite_init: ");
- err_inspect_str(&sprite->real_path);
- err_write_1(": glBindTexture: ");
- err_puts((const s8 *) gluErrorString(gl_error));
- return NULL;
- }
- glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S,
- GL_CLAMP_TO_EDGE);
- glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T,
- GL_CLAMP_TO_EDGE);
- glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER,
- GL_LINEAR_MIPMAP_LINEAR);
- glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
- gl_error = glGetError();
- if (gl_error != GL_NO_ERROR) {
- err_write_1("sdl2_sprite_init: ");
- err_inspect_str(&sprite->real_path);
- err_write_1(": glTexParameteri: ");
- err_puts((const s8 *) gluErrorString(gl_error));
- return NULL;
- }
- glTexImage2D(GL_TEXTURE_2D, 0, gl_format, sprite->w, sprite->h,
- 0, gl_format, gl_type, data);
- //glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, sprite->w, sprite->h,
- // 0, GL_RGBA, GL_UNSIGNED_BYTE, data);
- gl_error = glGetError();
- if (gl_error != GL_NO_ERROR) {
- err_write_1("sdl2_sprite_init: ");
- err_inspect_str(&sprite->real_path);
- err_write_1(": glTexImage2D: ");
- err_puts((const s8 *) gluErrorString(gl_error));
- return NULL;
- }
- glGenerateMipmap(GL_TEXTURE_2D);
- assert(glGetError() == GL_NO_ERROR);
- i++;
- x++;
- }
- y++;
- }
- glBindTexture(GL_TEXTURE_2D, 0);
- free(data);
- free(png_data);
- free(png_row);
- return sprite;
-}
-
-void sdl2_sprite_render (const s_sdl2_sprite *sprite, uw frame)
-{
- assert(sprite);
- assert(frame < sprite->frame_count);
- frame %= sprite->frame_count;
- glColor4f(1, 1, 1, 1);
- glEnable(GL_BLEND);
- glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
- glDisable(GL_CULL_FACE);
- glEnable(GL_TEXTURE_2D);
- glBindTexture(GL_TEXTURE_2D, sprite->texture[frame]);
- glBegin(GL_QUADS); {
- glTexCoord2f(0, 1);
- glVertex2d(0, sprite->h);
- glTexCoord2f(0, 0);
- glVertex2i(0, 0);
- glTexCoord2f(1, 0);
- glVertex2i(sprite->w, 0);
- glTexCoord2f(1, 1);
- glVertex2d(sprite->w, sprite->h);
- } glEnd();
- glBindTexture(GL_TEXTURE_2D, 0);
- glDisable(GL_TEXTURE_2D);
- /*
- glBegin(GL_LINE_LOOP); {
- glVertex2d(0, sprite->h);
- glVertex2i(0, 0);
- glVertex2i(sprite->w, 0);
- glVertex2d(sprite->w, sprite->h);
- } glEnd();
- */
-}
diff --git a/libc3/window/sdl2/sdl2_sprite.h b/libc3/window/sdl2/sdl2_sprite.h
deleted file mode 100644
index 675992d..0000000
--- a/libc3/window/sdl2/sdl2_sprite.h
+++ /dev/null
@@ -1,29 +0,0 @@
-/* c3
- * Copyright 2022,2023 kmx.io <contact@kmx.io>
- *
- * Permission is hereby granted to use this software granted the above
- * copyright notice and this permission paragraph are included in all
- * copies and substantial portions of this software.
- *
- * THIS SOFTWARE IS PROVIDED "AS-IS" WITHOUT ANY GUARANTEE OF
- * PURPOSE AND PERFORMANCE. IN NO EVENT WHATSOEVER SHALL THE
- * AUTHOR BE CONSIDERED LIABLE FOR THE USE AND PERFORMANCE OF
- * THIS SOFTWARE.
- */
-#ifndef SDL2_SPRITE_H
-#define SDL2_SPRITE_H
-
-#include "types.h"
-
-/* stack allocation compatible functions */
-void sdl2_sprite_clean (s_sdl2_sprite *sprite);
-s_sdl2_sprite * sdl2_sprite_init (s_sdl2_sprite *sprite,
- const s8 *path,
- uw dim_x, uw dim_y,
- uw frame_count);
-
-/* operations */
-void sdl2_sprite_bind (const s_sdl2_sprite *sprite, uw frame);
-void sdl2_sprite_render (const s_sdl2_sprite *sprite, uw frame);
-
-#endif /* CAIRO_SPRITE_H */
diff --git a/libc3/window/sdl2/sources.mk b/libc3/window/sdl2/sources.mk
index 6589755..f4270ae 100644
--- a/libc3/window/sdl2/sources.mk
+++ b/libc3/window/sdl2/sources.mk
@@ -2,6 +2,7 @@
HEADERS = \
"gl_camera.h" \
"gl_cylinder.h" \
+ "gl_deprecated.h" \
"gl_font.h" \
"gl_ft2.h" \
"gl_lines.h" \
@@ -17,13 +18,13 @@ HEADERS = \
"gl_text.h" \
"gl_triangle.h" \
"gl_vertex.h" \
- "sdl2_sprite.h" \
"types.h" \
"window_sdl2.h" \
SOURCES = \
"gl_camera.c" \
"gl_cylinder.c" \
+ "gl_deprecated.c" \
"gl_font.c" \
"gl_lines.c" \
"gl_matrix_4d.c" \
@@ -37,6 +38,5 @@ SOURCES = \
"gl_text.c" \
"gl_triangle.c" \
"gl_vertex.c" \
- "sdl2_sprite.c" \
"window_sdl2.c" \
diff --git a/libc3/window/sdl2/sources.sh b/libc3/window/sdl2/sources.sh
index 490c35b..f4cb03a 100644
--- a/libc3/window/sdl2/sources.sh
+++ b/libc3/window/sdl2/sources.sh
@@ -1,3 +1,3 @@
# sources.sh generated by update_sources
-HEADERS='gl_camera.h gl_cylinder.h gl_font.h gl_ft2.h gl_lines.h gl_matrix_3d.h gl_matrix_4d.h gl_object.h gl_ortho.h gl_point_2d.h gl_point_3d.h gl_sphere.h gl_sprite.h gl_square.h gl_text.h gl_triangle.h gl_vertex.h sdl2_sprite.h types.h window_sdl2.h '
-SOURCES='gl_camera.c gl_cylinder.c gl_font.c gl_lines.c gl_matrix_4d.c gl_object.c gl_ortho.c gl_point_2d.c gl_point_3d.c gl_sphere.c gl_sprite.c gl_square.c gl_text.c gl_triangle.c gl_vertex.c sdl2_sprite.c window_sdl2.c '
+HEADERS='gl_camera.h gl_cylinder.h gl_deprecated.h gl_font.h gl_ft2.h gl_lines.h gl_matrix_3d.h gl_matrix_4d.h gl_object.h gl_ortho.h gl_point_2d.h gl_point_3d.h gl_sphere.h gl_sprite.h gl_square.h gl_text.h gl_triangle.h gl_vertex.h types.h window_sdl2.h '
+SOURCES='gl_camera.c gl_cylinder.c gl_deprecated.c gl_font.c gl_lines.c gl_matrix_4d.c gl_object.c gl_ortho.c gl_point_2d.c gl_point_3d.c gl_sphere.c gl_sprite.c gl_square.c gl_text.c gl_triangle.c gl_vertex.c window_sdl2.c '
diff --git a/libc3/window/sdl2/window_sdl2.c b/libc3/window/sdl2/window_sdl2.c
index 48fa5db..83b9a98 100644
--- a/libc3/window/sdl2/window_sdl2.c
+++ b/libc3/window/sdl2/window_sdl2.c
@@ -15,10 +15,25 @@
#include <xkbcommon/xkbcommon.h>
#include <libc3/c3.h>
#include "../window.h"
+#include "gl_deprecated.h"
#include "window_sdl2.h"
static bool g_window_sdl2_initialized = false;
+static void gl_debug (GLenum source, GLenum type, GLuint id,
+ GLenum severity, GLsizei length,
+ const GLchar* message, const void* user_param)
+{
+ (void) source;
+ (void) type;
+ (void) id;
+ (void) severity;
+ (void) length;
+ (void) user_param;
+ err_write_1("gl_debug_callback: ");
+ err_puts(message);
+}
+
void window_sdl2_clean (s_window_sdl2 *window)
{
window_clean((s_window *) window);
@@ -166,9 +181,11 @@ bool window_sdl2_run (s_window_sdl2 *window)
GLenum gl_error = glGetError();
if (gl_error != GL_NO_ERROR) {
warnx("OpenGL initialization error: %s\n",
- gluErrorString(gl_error));
+ gl_error_string(gl_error));
goto ko;
}
+ glEnable(GL_DEBUG_OUTPUT);
+ glDebugMessageCallback(gl_debug, NULL);
if (SDL_GL_MakeCurrent(sdl_window, context) < 0) {
warnx("window_sdl2_run: failed to make OpenGL context current: %s",
SDL_GetError());