cogl/texture: Use macros for generating subclassing boilerplate

We can't unfortunately use the macros for the sub-types as the whole GL
variant of the texture wants access to the struct fields even when using
a macro like COGL_DECLARE_INTERNAL_TYPE. So we would have to re-do the
whole driver integration first.

Part-of: <https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/4100>
This commit is contained in:
Bilal Elmoussaoui 2024-10-20 11:14:15 +02:00 committed by Marge Bot
parent 34f4b8064f
commit 2a3e6a2df5
3 changed files with 131 additions and 79 deletions

View File

@ -109,26 +109,6 @@ typedef struct _CoglTextureLoader
} src; } src;
} CoglTextureLoader; } CoglTextureLoader;
struct _CoglTexture
{
GObject parent_instance;
CoglContext *context;
gboolean is_primitive;
CoglTextureLoader *loader;
GList *framebuffers;
int max_level_set;
int max_level_requested;
int width;
int height;
gboolean allocated;
/*
* Internal format
*/
CoglTextureComponents components;
unsigned int premultiplied : 1;
};
struct _CoglTextureClass struct _CoglTextureClass
{ {

View File

@ -59,7 +59,26 @@
#include <stdlib.h> #include <stdlib.h>
#include <math.h> #include <math.h>
G_DEFINE_ABSTRACT_TYPE (CoglTexture, cogl_texture, G_TYPE_OBJECT) typedef struct _CoglTexturePrivate
{
CoglContext *context;
gboolean is_primitive;
CoglTextureLoader *loader;
GList *framebuffers;
int max_level_set;
int max_level_requested;
int width;
int height;
gboolean allocated;
/*
* Internal format
*/
CoglTextureComponents components;
unsigned int premultiplied : 1;
} CoglTexturePrivate;
G_DEFINE_ABSTRACT_TYPE_WITH_PRIVATE (CoglTexture, cogl_texture, G_TYPE_OBJECT)
enum enum
{ {
@ -80,9 +99,12 @@ static GParamSpec *obj_props[PROP_LAST];
static void static void
_cogl_texture_free_loader (CoglTexture *texture) _cogl_texture_free_loader (CoglTexture *texture)
{ {
if (texture->loader) CoglTexturePrivate *priv =
cogl_texture_get_instance_private (texture);
if (priv->loader)
{ {
CoglTextureLoader *loader = texture->loader; CoglTextureLoader *loader = priv->loader;
switch (loader->src_type) switch (loader->src_type)
{ {
case COGL_TEXTURE_SOURCE_TYPE_SIZE: case COGL_TEXTURE_SOURCE_TYPE_SIZE:
@ -94,7 +116,7 @@ _cogl_texture_free_loader (CoglTexture *texture)
break; break;
} }
g_free (loader); g_free (loader);
texture->loader = NULL; priv->loader = NULL;
} }
} }
@ -115,23 +137,25 @@ cogl_texture_set_property (GObject *gobject,
GParamSpec *pspec) GParamSpec *pspec)
{ {
CoglTexture *texture = COGL_TEXTURE (gobject); CoglTexture *texture = COGL_TEXTURE (gobject);
CoglTexturePrivate *priv =
cogl_texture_get_instance_private (texture);
switch (prop_id) switch (prop_id)
{ {
case PROP_CONTEXT: case PROP_CONTEXT:
texture->context = g_value_get_object (value); priv->context = g_value_get_object (value);
break; break;
case PROP_WIDTH: case PROP_WIDTH:
texture->width = g_value_get_int (value); priv->width = g_value_get_int (value);
break; break;
case PROP_HEIGHT: case PROP_HEIGHT:
texture->height = g_value_get_int (value); priv->height = g_value_get_int (value);
break; break;
case PROP_LOADER: case PROP_LOADER:
texture->loader = g_value_get_pointer (value); priv->loader = g_value_get_pointer (value);
break; break;
case PROP_FORMAT: case PROP_FORMAT:
@ -149,11 +173,11 @@ cogl_texture_set_property (GObject *gobject,
* have to worry about updating the ->components state in * have to worry about updating the ->components state in
* _set_premultiplied(). * _set_premultiplied().
*/ */
texture->premultiplied = TRUE; priv->premultiplied = TRUE;
break; break;
case PROP_IS_PRIMITIVE: case PROP_IS_PRIMITIVE:
texture->is_primitive = g_value_get_boolean (value); priv->is_primitive = g_value_get_boolean (value);
break; break;
default: default:
@ -210,10 +234,13 @@ cogl_texture_class_init (CoglTextureClass *klass)
static void static void
cogl_texture_init (CoglTexture *texture) cogl_texture_init (CoglTexture *texture)
{ {
texture->max_level_set = 0; CoglTexturePrivate *priv =
texture->max_level_requested = 1000; /* OpenGL default GL_TEXTURE_MAX_LEVEL */ cogl_texture_get_instance_private (texture);
texture->allocated = FALSE;
texture->framebuffers = NULL; priv->max_level_set = 0;
priv->max_level_requested = 1000; /* OpenGL default GL_TEXTURE_MAX_LEVEL */
priv->allocated = FALSE;
priv->framebuffers = NULL;
} }
uint32_t uint32_t
@ -251,17 +278,23 @@ cogl_texture_is_get_data_supported (CoglTexture *texture)
unsigned int unsigned int
cogl_texture_get_width (CoglTexture *texture) cogl_texture_get_width (CoglTexture *texture)
{ {
CoglTexturePrivate *priv;
g_return_val_if_fail (COGL_IS_TEXTURE (texture), 0); g_return_val_if_fail (COGL_IS_TEXTURE (texture), 0);
return texture->width; priv = cogl_texture_get_instance_private (texture);
return priv->width;
} }
unsigned int unsigned int
cogl_texture_get_height (CoglTexture *texture) cogl_texture_get_height (CoglTexture *texture)
{ {
CoglTexturePrivate *priv;
g_return_val_if_fail (COGL_IS_TEXTURE (texture), 0); g_return_val_if_fail (COGL_IS_TEXTURE (texture), 0);
return texture->height; priv = cogl_texture_get_instance_private (texture);
return priv->height;
} }
CoglPixelFormat CoglPixelFormat
@ -282,19 +315,25 @@ _cogl_util_fls (unsigned int n)
int int
_cogl_texture_get_n_levels (CoglTexture *texture) _cogl_texture_get_n_levels (CoglTexture *texture)
{ {
CoglTexturePrivate *priv =
cogl_texture_get_instance_private (texture);
int width = cogl_texture_get_width (texture); int width = cogl_texture_get_width (texture);
int height = cogl_texture_get_height (texture); int height = cogl_texture_get_height (texture);
int max_dimension = MAX (width, height); int max_dimension = MAX (width, height);
int n_levels = _cogl_util_fls (max_dimension); int n_levels = _cogl_util_fls (max_dimension);
return MIN (n_levels, texture->max_level_requested + 1); return MIN (n_levels, priv->max_level_requested + 1);
} }
void void
cogl_texture_set_max_level (CoglTexture *texture, cogl_texture_set_max_level (CoglTexture *texture,
int max_level) int max_level)
{ {
texture->max_level_requested = max_level; CoglTexturePrivate *priv =
cogl_texture_get_instance_private (texture);
priv->max_level_requested = max_level;
} }
void void
@ -946,16 +985,20 @@ static void
on_framebuffer_destroy (CoglFramebuffer *framebuffer, on_framebuffer_destroy (CoglFramebuffer *framebuffer,
CoglTexture *texture) CoglTexture *texture)
{ {
texture->framebuffers = g_list_remove (texture->framebuffers, framebuffer); CoglTexturePrivate *priv =
cogl_texture_get_instance_private (texture);
priv->framebuffers = g_list_remove (priv->framebuffers, framebuffer);
} }
void void
_cogl_texture_associate_framebuffer (CoglTexture *texture, _cogl_texture_associate_framebuffer (CoglTexture *texture,
CoglFramebuffer *framebuffer) CoglFramebuffer *framebuffer)
{ {
CoglTexturePrivate *priv =
cogl_texture_get_instance_private (texture);
/* Note: we don't take a reference on the framebuffer here because /* Note: we don't take a reference on the framebuffer here because
* that would introduce a circular reference. */ * that would introduce a circular reference. */
texture->framebuffers = g_list_prepend (texture->framebuffers, framebuffer); priv->framebuffers = g_list_prepend (priv->framebuffers, framebuffer);
g_signal_connect (framebuffer, "destroy", g_signal_connect (framebuffer, "destroy",
G_CALLBACK (on_framebuffer_destroy), G_CALLBACK (on_framebuffer_destroy),
@ -965,7 +1008,9 @@ _cogl_texture_associate_framebuffer (CoglTexture *texture,
const GList * const GList *
_cogl_texture_get_associated_framebuffers (CoglTexture *texture) _cogl_texture_get_associated_framebuffers (CoglTexture *texture)
{ {
return texture->framebuffers; CoglTexturePrivate *priv =
cogl_texture_get_instance_private (texture);
return priv->framebuffers;
} }
void void
@ -1100,11 +1145,13 @@ _cogl_texture_set_allocated (CoglTexture *texture,
int width, int width,
int height) int height)
{ {
CoglTexturePrivate *priv =
cogl_texture_get_instance_private (texture);
_cogl_texture_set_internal_format (texture, internal_format); _cogl_texture_set_internal_format (texture, internal_format);
texture->width = width; priv->width = width;
texture->height = height; priv->height = height;
texture->allocated = TRUE; priv->allocated = TRUE;
_cogl_texture_free_loader (texture); _cogl_texture_free_loader (texture);
} }
@ -1112,64 +1159,72 @@ _cogl_texture_set_allocated (CoglTexture *texture,
gboolean gboolean
cogl_texture_is_allocated (CoglTexture *texture) cogl_texture_is_allocated (CoglTexture *texture)
{ {
return texture->allocated; CoglTexturePrivate *priv =
cogl_texture_get_instance_private (texture);
return priv->allocated;
} }
gboolean gboolean
cogl_texture_allocate (CoglTexture *texture, cogl_texture_allocate (CoglTexture *texture,
GError **error) GError **error)
{ {
CoglTexturePrivate *priv;
g_return_val_if_fail (COGL_IS_TEXTURE (texture), FALSE); g_return_val_if_fail (COGL_IS_TEXTURE (texture), FALSE);
priv = cogl_texture_get_instance_private (texture);
if (cogl_texture_is_allocated (texture)) if (cogl_texture_is_allocated (texture))
return TRUE; return TRUE;
if (texture->components == COGL_TEXTURE_COMPONENTS_RG && if (priv->components == COGL_TEXTURE_COMPONENTS_RG &&
!cogl_context_has_feature (texture->context, COGL_FEATURE_ID_TEXTURE_RG)) !cogl_context_has_feature (priv->context, COGL_FEATURE_ID_TEXTURE_RG))
g_set_error (error, g_set_error (error,
COGL_TEXTURE_ERROR, COGL_TEXTURE_ERROR,
COGL_TEXTURE_ERROR_FORMAT, COGL_TEXTURE_ERROR_FORMAT,
"A red-green texture was requested but the driver " "A red-green texture was requested but the driver "
"does not support them"); "does not support them");
texture->allocated = COGL_TEXTURE_GET_CLASS (texture)->allocate (texture, error); priv->allocated = COGL_TEXTURE_GET_CLASS (texture)->allocate (texture, error);
return texture->allocated; return priv->allocated;
} }
void void
_cogl_texture_set_internal_format (CoglTexture *texture, _cogl_texture_set_internal_format (CoglTexture *texture,
CoglPixelFormat internal_format) CoglPixelFormat internal_format)
{ {
texture->premultiplied = FALSE; CoglTexturePrivate *priv =
cogl_texture_get_instance_private (texture);
priv->premultiplied = FALSE;
if (internal_format == COGL_PIXEL_FORMAT_ANY) if (internal_format == COGL_PIXEL_FORMAT_ANY)
internal_format = COGL_PIXEL_FORMAT_RGBA_8888_PRE; internal_format = COGL_PIXEL_FORMAT_RGBA_8888_PRE;
if (internal_format == COGL_PIXEL_FORMAT_A_8) if (internal_format == COGL_PIXEL_FORMAT_A_8)
{ {
texture->components = COGL_TEXTURE_COMPONENTS_A; priv->components = COGL_TEXTURE_COMPONENTS_A;
return; return;
} }
else if (internal_format == COGL_PIXEL_FORMAT_RG_88) else if (internal_format == COGL_PIXEL_FORMAT_RG_88)
{ {
texture->components = COGL_TEXTURE_COMPONENTS_RG; priv->components = COGL_TEXTURE_COMPONENTS_RG;
return; return;
} }
else if (internal_format & COGL_DEPTH_BIT) else if (internal_format & COGL_DEPTH_BIT)
{ {
texture->components = COGL_TEXTURE_COMPONENTS_DEPTH; priv->components = COGL_TEXTURE_COMPONENTS_DEPTH;
return; return;
} }
else if (internal_format & COGL_A_BIT) else if (internal_format & COGL_A_BIT)
{ {
texture->components = COGL_TEXTURE_COMPONENTS_RGBA; priv->components = COGL_TEXTURE_COMPONENTS_RGBA;
if (internal_format & COGL_PREMULT_BIT) if (internal_format & COGL_PREMULT_BIT)
texture->premultiplied = TRUE; priv->premultiplied = TRUE;
return; return;
} }
else else
texture->components = COGL_TEXTURE_COMPONENTS_RGB; priv->components = COGL_TEXTURE_COMPONENTS_RGB;
} }
CoglPixelFormat CoglPixelFormat
@ -1234,44 +1289,56 @@ void
cogl_texture_set_components (CoglTexture *texture, cogl_texture_set_components (CoglTexture *texture,
CoglTextureComponents components) CoglTextureComponents components)
{ {
CoglTexturePrivate *priv;
g_return_if_fail (COGL_IS_TEXTURE (texture)); g_return_if_fail (COGL_IS_TEXTURE (texture));
g_return_if_fail (!cogl_texture_is_allocated (texture)); g_return_if_fail (!cogl_texture_is_allocated (texture));
if (texture->components == components) priv = cogl_texture_get_instance_private (texture);
if (priv->components == components)
return; return;
texture->components = components; priv->components = components;
} }
CoglTextureComponents CoglTextureComponents
cogl_texture_get_components (CoglTexture *texture) cogl_texture_get_components (CoglTexture *texture)
{ {
CoglTexturePrivate *priv;
g_return_val_if_fail (COGL_IS_TEXTURE (texture), 0); g_return_val_if_fail (COGL_IS_TEXTURE (texture), 0);
return texture->components; priv = cogl_texture_get_instance_private (texture);
return priv->components;
} }
void void
cogl_texture_set_premultiplied (CoglTexture *texture, cogl_texture_set_premultiplied (CoglTexture *texture,
gboolean premultiplied) gboolean premultiplied)
{ {
CoglTexturePrivate *priv;
g_return_if_fail (COGL_IS_TEXTURE (texture)); g_return_if_fail (COGL_IS_TEXTURE (texture));
g_return_if_fail (!cogl_texture_is_allocated (texture)); g_return_if_fail (!cogl_texture_is_allocated (texture));
premultiplied = !!premultiplied; premultiplied = !!premultiplied;
if (texture->premultiplied == premultiplied) priv = cogl_texture_get_instance_private (texture);
if (priv->premultiplied == premultiplied)
return; return;
texture->premultiplied = premultiplied; priv->premultiplied = premultiplied;
} }
gboolean gboolean
cogl_texture_get_premultiplied (CoglTexture *texture) cogl_texture_get_premultiplied (CoglTexture *texture)
{ {
CoglTexturePrivate *priv;
g_return_val_if_fail (COGL_IS_TEXTURE (texture), FALSE); g_return_val_if_fail (COGL_IS_TEXTURE (texture), FALSE);
return texture->premultiplied; priv = cogl_texture_get_instance_private (texture);
return priv->premultiplied;
} }
void void
@ -1285,34 +1352,44 @@ _cogl_texture_copy_internal_format (CoglTexture *src,
CoglContext * CoglContext *
cogl_texture_get_context (CoglTexture *texture) cogl_texture_get_context (CoglTexture *texture)
{ {
return texture->context; CoglTexturePrivate *priv =
cogl_texture_get_instance_private (texture);
return priv->context;
} }
CoglTextureLoader * CoglTextureLoader *
cogl_texture_get_loader (CoglTexture *texture) cogl_texture_get_loader (CoglTexture *texture)
{ {
return texture->loader; CoglTexturePrivate *priv =
cogl_texture_get_instance_private (texture);
return priv->loader;
} }
int int
cogl_texture_get_max_level_set (CoglTexture *texture) cogl_texture_get_max_level_set (CoglTexture *texture)
{ {
return texture->max_level_set; CoglTexturePrivate *priv =
cogl_texture_get_instance_private (texture);
return priv->max_level_set;
} }
void void
cogl_texture_set_max_level_set (CoglTexture *texture, cogl_texture_set_max_level_set (CoglTexture *texture,
int max_level_set) int max_level_set)
{ {
texture->max_level_set = max_level_set; CoglTexturePrivate *priv =
cogl_texture_get_instance_private (texture);
priv->max_level_set = max_level_set;
} }
void void
cogl_texture_set_auto_mipmap (CoglTexture *texture, cogl_texture_set_auto_mipmap (CoglTexture *texture,
gboolean value) gboolean value)
{ {
g_return_if_fail (COGL_IS_TEXTURE (texture) && CoglTexturePrivate *priv;
texture->is_primitive); g_return_if_fail (COGL_IS_TEXTURE (texture));
priv = cogl_texture_get_instance_private (texture);
g_return_if_fail (priv->is_primitive);
g_assert (COGL_TEXTURE_GET_CLASS (texture)->set_auto_mipmap != NULL); g_assert (COGL_TEXTURE_GET_CLASS (texture)->set_auto_mipmap != NULL);

View File

@ -52,22 +52,17 @@ G_BEGIN_DECLS
* API that tries to hide all the various complexities of creating, * API that tries to hide all the various complexities of creating,
* loading and manipulating textures. * loading and manipulating textures.
*/ */
COGL_EXPORT
G_DECLARE_DERIVABLE_TYPE (CoglTexture,
cogl_texture,
COGL,
TEXTURE,
GObject)
#define COGL_TYPE_TEXTURE (cogl_texture_get_type ()) #define COGL_TYPE_TEXTURE (cogl_texture_get_type ())
#define COGL_TEXTURE(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), COGL_TYPE_TEXTURE, CoglTexture))
#define COGL_TEXTURE_CONST(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), COGL_TYPE_TEXTURE, CoglTexture const))
#define COGL_TEXTURE_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), COGL_TYPE_TEXTURE, CoglTextureClass))
#define COGL_IS_TEXTURE(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), COGL_TYPE_TEXTURE))
#define COGL_IS_TEXTURE_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), COGL_TYPE_TEXTURE))
#define COGL_TEXTURE_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), COGL_TYPE_TEXTURE, CoglTextureClass))
typedef struct _CoglTextureClass CoglTextureClass; typedef struct _CoglTextureClass CoglTextureClass;
G_DEFINE_AUTOPTR_CLEANUP_FUNC (CoglTexture, g_object_unref)
COGL_EXPORT
GType cogl_texture_get_type (void) G_GNUC_CONST;
#define COGL_TEXTURE_MAX_WASTE 127 #define COGL_TEXTURE_MAX_WASTE 127
/** /**