From c4291dcc20d927e6f0250ebae9cdc600dd4f2fca Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mario=20H=C3=BCttel?= Date: Fri, 10 Jul 2020 21:36:02 +0200 Subject: [PATCH] Implement 2d texture --- include/shimatta-opengl-texture.h | 34 ++-- src/shimatta-opengl-texture.c | 297 +++++++++++++++++++++++++----- 2 files changed, 271 insertions(+), 60 deletions(-) diff --git a/include/shimatta-opengl-texture.h b/include/shimatta-opengl-texture.h index 15549cc..edc9b17 100644 --- a/include/shimatta-opengl-texture.h +++ b/include/shimatta-opengl-texture.h @@ -23,22 +23,30 @@ int shimatta_opengl_texture_use_in_slot(ShimattaOpenglTexture *texture, unsigned ShimattaOpenglTexture *shimatta_opengl_texture_new(void); -void shimatta_opengl_texture_set_filter(ShimattaOpenglTexture *texture, int filter_s, int filter_t); - -void shimatta_opengl_texture_set_wrap(ShimattaOpenglTexture *texture, int wrap_s, int wrap_t); - -void shimatta_opengl_texture_set_gen_mipmap(ShimattaOpenglTexture *texture, gboolean gen_mipmap); - -int shimatta_opengl_texture_get_filter(ShimattaOpenglTexture *texture, int *filter_s, int *filter_t); - -int shimatta_opengl_texture_get_wrap(ShimattaOpenglTexture *texture, int *wrap_s, int *wrap_t); - -gboolean shimatta_opengl_texture_get_gen_mipmap(ShimattaOpenglTexture *texture); - int shimatta_opengl_texture_set_data(ShimattaOpenglTexture *texture, unsigned int width, unsigned int height, GLenum format, void *buffer); -int shimatta_opengl_texture_set_from_image(ShimattaOpenglTexture *texture, const char *path); +int shimatta_opengl_texture_set_data_from_image(ShimattaOpenglTexture *texture, const char *path); + +void shimatta_opengl_texture_set_wrap_s(ShimattaOpenglTexture *self, int wrap_s); + +void shimatta_opengl_texture_set_wrap_t(ShimattaOpenglTexture *self, int wrap_t); + +void shimatta_opengl_texture_set_min_filter(ShimattaOpenglTexture *self, int min_filter); + +void shimatta_opengl_texture_set_mag_filter(ShimattaOpenglTexture *self, int mag_filter); + +void shimatta_opengl_texture_set_gen_mipmap(ShimattaOpenglTexture *self, gboolean gen_mipmap); + +int shimatta_opengl_texture_get_wrap_s(ShimattaOpenglTexture *self); + +int shimatta_opengl_texture_get_wrap_t(ShimattaOpenglTexture *self); + +int shimatta_opengl_texture_get_mag_filter(ShimattaOpenglTexture *self); + +int shimatta_opengl_texture_get_min_filter(ShimattaOpenglTexture *self); + +gboolean shimatta_opengl_texture_get_gen_mipmap(ShimattaOpenglTexture *self); G_END_DECLS diff --git a/src/shimatta-opengl-texture.c b/src/shimatta-opengl-texture.c index 1bcabdd..8511780 100644 --- a/src/shimatta-opengl-texture.c +++ b/src/shimatta-opengl-texture.c @@ -1,15 +1,21 @@ #include +#include #include typedef struct { - GLint texture_wrap_s; - GLint texture_wrap_t; - GLint texture_min_filter; - GLint texture_max_filter; gboolean generate_mipmap; GLuint texture_id; } ShimattaOpenglTexturePrivate; +enum shimatta_opengl_texture_properties { + PROP_TEXTURE_WRAP_S = 1, + PROP_TEXTURE_WRAP_T, + PROP_TEXTURE_MIN_FILTER, + PROP_TEXTURE_MAG_FILTER, + PROP_TEXTURE_GEN_MIPMAP, + N_PROPS_TEXTURE +}; + G_DEFINE_TYPE_WITH_PRIVATE(ShimattaOpenglTexture, shimatta_opengl_texture, G_TYPE_OBJECT); static int shimatta_opengl_texure_use_default_impl(ShimattaOpenglTexture *texture, unsigned int slot, gboolean use_slot) @@ -42,9 +48,108 @@ static void use_default(ShimattaOpenglTexture *texture) (void)shimatta_opengl_texure_use_default_impl(texture, 0U, FALSE); } +static void shimatta_opengl_texture_dispose(ShimattaOpenglTexture *self) +{ + ShimattaOpenglTexturePrivate *priv; + + priv = shimatta_opengl_texture_get_instance_private(self); + + if (priv->texture_id) { + glDeleteTextures(1, &priv->texture_id); + priv->texture_id = 0; + } + + G_OBJECT_CLASS(shimatta_opengl_texture_parent_class)->dispose(G_OBJECT(self)); +} + +static void shimatta_opengl_texture_get_property(GObject *obj, guint id, GValue *val, GParamSpec *spec) +{ + ShimattaOpenglTexture *self; + + self = SHIMATTA_OPENGL_TEXTURE(obj); + + switch (id) { + case PROP_TEXTURE_WRAP_S: + g_value_set_int(val, shimatta_opengl_texture_get_wrap_s(self)); + break; + case PROP_TEXTURE_WRAP_T: + g_value_set_int(val, shimatta_opengl_texture_get_wrap_t(self)); + break; + case PROP_TEXTURE_GEN_MIPMAP: + g_value_set_boolean(val, shimatta_opengl_texture_get_gen_mipmap(self)); + break; + case PROP_TEXTURE_MAG_FILTER: + g_value_set_int(val, shimatta_opengl_texture_get_mag_filter(self)); + break; + case PROP_TEXTURE_MIN_FILTER: + g_value_set_int(val, shimatta_opengl_texture_get_min_filter(self)); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID(obj, id, spec); + break; + } +} + +static void shimatta_opengl_texture_set_property(GObject *obj, guint id, const GValue *value, GParamSpec *spec) +{ + ShimattaOpenglTexture *self; + + self = SHIMATTA_OPENGL_TEXTURE(obj); + + switch (id) { + case PROP_TEXTURE_WRAP_S: + shimatta_opengl_texture_set_wrap_s(self, g_value_get_int(value)); + break; + case PROP_TEXTURE_WRAP_T: + shimatta_opengl_texture_set_wrap_t(self, g_value_get_int(value)); + break; + case PROP_TEXTURE_GEN_MIPMAP: + shimatta_opengl_texture_set_gen_mipmap(self, g_value_get_boolean(value)); + break; + case PROP_TEXTURE_MAG_FILTER: + shimatta_opengl_texture_set_mag_filter(self, g_value_get_int(value)); + break; + case PROP_TEXTURE_MIN_FILTER: + shimatta_opengl_texture_set_min_filter(self, g_value_get_int(value)); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID(obj, id, spec); + break; + } +} + +static GParamSpec *shimatta_opengl_texture_props[N_PROPS_TEXTURE] = {NULL, }; + static void shimatta_opengl_texture_class_init(ShimattaOpenglTextureClass *klass) { + GObjectClass *gclass; + gclass = G_OBJECT_CLASS(klass); + + klass->use = use_default; + klass->use_in_slot = use_in_slot_default; + + gclass->dispose = (void (*)(GObject *))shimatta_opengl_texture_dispose; + gclass->set_property = shimatta_opengl_texture_set_property; + gclass->get_property = shimatta_opengl_texture_get_property; + + shimatta_opengl_texture_props[PROP_TEXTURE_WRAP_S] = + g_param_spec_int("wrap-s", "WRAP_S", "Wrapping in S", + 0, INT_MAX, GL_REPEAT, G_PARAM_READWRITE); + shimatta_opengl_texture_props[PROP_TEXTURE_WRAP_T] = + g_param_spec_int("wrap-t", "WRAP_T", "Wrapping in T", + 0, INT_MAX, GL_REPEAT, G_PARAM_READWRITE); + shimatta_opengl_texture_props[PROP_TEXTURE_MIN_FILTER] = + g_param_spec_int("min-filter", "MIN_FILTER", "Min filtering", + 0, INT_MAX, GL_LINEAR, G_PARAM_READWRITE); + shimatta_opengl_texture_props[PROP_TEXTURE_MAG_FILTER] = + g_param_spec_int("max-filter", "MAG_FILTER", "Mag filtering", + 0, INT_MAX, GL_LINEAR, G_PARAM_READWRITE); + shimatta_opengl_texture_props[PROP_TEXTURE_GEN_MIPMAP] = + g_param_spec_boolean("generate-mipmap", "gen-mipmap", "Generate Mipmap for texture", + TRUE, G_PARAM_READWRITE); + + g_object_class_install_properties(gclass, N_PROPS_TEXTURE, shimatta_opengl_texture_props); } static void shimatta_opengl_texture_init(ShimattaOpenglTexture *self) @@ -53,16 +158,9 @@ static void shimatta_opengl_texture_init(ShimattaOpenglTexture *self) priv = shimatta_opengl_texture_get_instance_private(self); priv->texture_id = 0; - priv->texture_wrap_s = GL_REPEAT; - priv->texture_wrap_s = GL_REPEAT; - priv->texture_min_filter = GL_LINEAR; - priv->texture_max_filter = GL_LINEAR; - priv->generate_mipmap = TRUE; glGenTextures(1, &priv->texture_id); glBindTexture(GL_TEXTURE_2D, priv->texture_id); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); @@ -90,41 +188,10 @@ int shimatta_opengl_texture_use_in_slot(ShimattaOpenglTexture *texture, unsigned ShimattaOpenglTexture *shimatta_opengl_texture_new() { - + return g_object_new(SHIMATTA_TYPE_OPENGL_TEXTURE, NULL); } -void shimatta_opengl_texture_set_filter(ShimattaOpenglTexture *texture, int filter_s, int filter_t) -{ - ShimattaOpenglTexturePrivate *priv; - g_return_if_fail(SHIMATTA_IS_OPENGL_TEXTURE(texture)); - priv = shimatta_opengl_texture_get_instance_private(texture); -} - -void shimatta_opengl_texture_set_wrap(ShimattaOpenglTexture *texture, int wrap_s, int wrap_t) -{ - -} - -void shimatta_opengl_texture_set_gen_mipmap(ShimattaOpenglTexture *texture, gboolean gen_mipmap) -{ - -} - -int shimatta_opengl_texture_get_filter(ShimattaOpenglTexture *texture, int *filter_s, int *filter_t) -{ - -} - -int shimatta_opengl_texture_get_wrap(ShimattaOpenglTexture *texture, int *filter_s, int *filter_t) -{ - -} - -gboolean shimatta_opengl_texture_get_gen_mipmap(ShimattaOpenglTexture *texture) -{ - -} int shimatta_opengl_texture_set_data(ShimattaOpenglTexture *texture, unsigned int width, unsigned int height, GLenum format, void *buffer) @@ -132,17 +199,153 @@ int shimatta_opengl_texture_set_data(ShimattaOpenglTexture *texture, unsigned in ShimattaOpenglTexturePrivate *priv; g_return_val_if_fail(SHIMATTA_IS_OPENGL_TEXTURE(texture), -1001); + g_return_val_if_fail(!!buffer, -1005); + priv = shimatta_opengl_texture_get_instance_private(texture); + shimatta_opengl_texture_use(texture); + + glTexImage2D(GL_TEXTURE_2D, 0, format, width, height, 0, format, GL_UNSIGNED_BYTE, buffer); + if (priv->generate_mipmap) + glGenerateMipmap(GL_TEXTURE_2D); return 0; } -int shimatta_opengl_texture_set_from_image(ShimattaOpenglTexture *texture, const char *path) +int shimatta_opengl_texture_set_data_from_image(ShimattaOpenglTexture *texture, const char *path) +{ + int ret = -1; + unsigned char *data; + int width, height; + int nr_channels; + GLenum format; + + data = stbi_load(path, &width, &height, &nr_channels, 0); + if (!data) + goto go_out; + + switch (nr_channels) { + case 1: + format = GL_RED; + break; + case 3: + format = GL_RGB; + break; + case 4: + format = GL_RGBA; + break; + } + shimatta_opengl_texture_set_data(texture, width, height, format, data); + ret = 0; + stbi_image_free(data); + +go_out: + return ret; +} + +void shimatta_opengl_texture_set_wrap_s(ShimattaOpenglTexture *self, int wrap_s) +{ + g_return_if_fail(SHIMATTA_IS_OPENGL_TEXTURE(self)); + + shimatta_opengl_texture_use(self); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, wrap_s); + + g_object_notify_by_pspec(G_OBJECT(self), shimatta_opengl_texture_props[PROP_TEXTURE_WRAP_S]); +} + +void shimatta_opengl_texture_set_wrap_t(ShimattaOpenglTexture *self, int wrap_t) +{ + g_return_if_fail(SHIMATTA_IS_OPENGL_TEXTURE(self)); + + shimatta_opengl_texture_use(self); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, wrap_t); + + g_object_notify_by_pspec(G_OBJECT(self), shimatta_opengl_texture_props[PROP_TEXTURE_WRAP_T]); +} + +void shimatta_opengl_texture_set_min_filter(ShimattaOpenglTexture *self, int min_filter) +{ + g_return_if_fail(SHIMATTA_IS_OPENGL_TEXTURE(self)); + + shimatta_opengl_texture_use(self); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, min_filter); + + g_object_notify_by_pspec(G_OBJECT(self), shimatta_opengl_texture_props[PROP_TEXTURE_MIN_FILTER]); +} + +void shimatta_opengl_texture_set_mag_filter(ShimattaOpenglTexture *self, int mag_filter) +{ + g_return_if_fail(SHIMATTA_IS_OPENGL_TEXTURE(self)); + + shimatta_opengl_texture_use(self); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, mag_filter); + + g_object_notify_by_pspec(G_OBJECT(self), shimatta_opengl_texture_props[PROP_TEXTURE_MAG_FILTER]); +} + +void shimatta_opengl_texture_set_gen_mipmap(ShimattaOpenglTexture *self, gboolean gen_mipmap) { ShimattaOpenglTexturePrivate *priv; - g_return_val_if_fail(SHIMATTA_IS_OPENGL_TEXTURE(texture), -1001); - priv = shimatta_opengl_texture_get_instance_private(texture); + priv = shimatta_opengl_texture_get_instance_private(self); + g_return_if_fail(!!priv); - return 0; + priv->generate_mipmap = gen_mipmap; +} + +int shimatta_opengl_texture_get_wrap_s(ShimattaOpenglTexture *self) +{ + GLint val; + + g_return_val_if_fail(SHIMATTA_IS_OPENGL_TEXTURE(self), -1); + + shimatta_opengl_texture_use(self); + glGetTexParameteriv(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, &val); + + return val; +} + +int shimatta_opengl_texture_get_wrap_t(ShimattaOpenglTexture *self) +{ + GLint val; + + g_return_val_if_fail(SHIMATTA_IS_OPENGL_TEXTURE(self), -1); + + shimatta_opengl_texture_use(self); + glGetTexParameteriv(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, &val); + + return val; +} + +int shimatta_opengl_texture_get_mag_filter(ShimattaOpenglTexture *self) +{ + GLint val; + + g_return_val_if_fail(SHIMATTA_IS_OPENGL_TEXTURE(self), -1); + + shimatta_opengl_texture_use(self); + glGetTexParameteriv(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, &val); + + return val; +} + +int shimatta_opengl_texture_get_min_filter(ShimattaOpenglTexture *self) +{ + GLint val; + + g_return_val_if_fail(SHIMATTA_IS_OPENGL_TEXTURE(self), -1); + + shimatta_opengl_texture_use(self); + glGetTexParameteriv(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, &val); + + return val; +} + +gboolean shimatta_opengl_texture_get_gen_mipmap(ShimattaOpenglTexture *self) +{ + ShimattaOpenglTexturePrivate *priv; + + g_return_val_if_fail(SHIMATTA_IS_OPENGL_TEXTURE(self), -1); + priv = shimatta_opengl_texture_get_instance_private(self); + + return priv->generate_mipmap; }