diff options
author | Niels De Graef <niels.degraef@barco.com> | 2018-11-14 12:22:02 +0100 |
---|---|---|
committer | Niels De Graef <niels.degraef@barco.com> | 2019-06-24 15:14:01 +0200 |
commit | f8747a2fe248ff44355177ef27f90f2b55ef0514 (patch) | |
tree | 9663706e294e708b3097f396c7ec2ac3fe4c242a | |
parent | 89111517bd8d2c6a9ead17988cf74abe2ed674b8 (diff) | |
download | mutter-f8747a2fe248ff44355177ef27f90f2b55ef0514.tar.gz |
cogl: Add CoglMultiPlaneTexture for complex formats
Mutter always assumed that any texture it got was
representable by a `CoglTexture`, which does not have this kind of
concept. This also has the useful feature that each `CoglTexture`
corresponds to a single layer in a `CoglPipeline`.
To deal with this, we introduce a new object: a `CoglMultiPlaneTexture`
consists of multiple `CoglTexture`s, each representing a plane in the
texture we got. It also provides knows when to use a
CoglPixelFormatConversion.
-rw-r--r-- | cogl/cogl/cogl-multi-plane-texture.c | 157 | ||||
-rw-r--r-- | cogl/cogl/cogl-multi-plane-texture.h | 187 | ||||
-rw-r--r-- | cogl/cogl/cogl-texture-2d.c | 4 | ||||
-rw-r--r-- | cogl/cogl/cogl-texture-2d.h | 1 | ||||
-rw-r--r-- | cogl/cogl/cogl.h | 2 | ||||
-rw-r--r-- | cogl/cogl/meson.build | 2 | ||||
-rw-r--r-- | cogl/cogl/winsys/cogl-winsys-egl-x11.c | 1 |
7 files changed, 354 insertions, 0 deletions
diff --git a/cogl/cogl/cogl-multi-plane-texture.c b/cogl/cogl/cogl-multi-plane-texture.c new file mode 100644 index 000000000..db12e3471 --- /dev/null +++ b/cogl/cogl/cogl-multi-plane-texture.c @@ -0,0 +1,157 @@ +/* + * Authored By Niels De Graef <niels.degraef@barco.com> + * + * Copyright (C) 2018 Barco NV + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, see <http://www.gnu.org/licenses/>. + */ + +#include "cogl-config.h" + +#include "cogl-object-private.h" +#include "cogl-multi-plane-texture.h" +#include "cogl-gtype-private.h" +#include "cogl-texture-private.h" +#include "cogl-texture-2d-sliced.h" + +struct _CoglMultiPlaneTexture +{ + CoglObject _parent; + + CoglPixelFormat format; + + uint8_t n_planes; + CoglTexture **planes; +}; + +static void +_cogl_multi_plane_texture_free (CoglMultiPlaneTexture *self); + +COGL_OBJECT_DEFINE (MultiPlaneTexture, multi_plane_texture); +COGL_GTYPE_DEFINE_CLASS (MultiPlaneTexture, multi_plane_texture); + + +CoglPixelFormat +cogl_multi_plane_texture_get_format (CoglMultiPlaneTexture *self) +{ + return self->format; +} + +uint8_t +cogl_multi_plane_texture_get_n_planes (CoglMultiPlaneTexture *self) +{ + return self->n_planes; +} + +CoglTexture * +cogl_multi_plane_texture_get_plane (CoglMultiPlaneTexture *self, guint index) +{ + g_return_val_if_fail (self->n_planes > 0, NULL); + g_return_val_if_fail (index < self->n_planes, NULL); + + return self->planes[index]; +} + +CoglTexture ** +cogl_multi_plane_texture_get_planes (CoglMultiPlaneTexture *self) +{ + return self->planes; +} + +guint +cogl_multi_plane_texture_get_width (CoglMultiPlaneTexture *self) +{ + g_return_val_if_fail (self->n_planes > 0, 0); + + return cogl_texture_get_width (self->planes[0]); +} + +guint +cogl_multi_plane_texture_get_height (CoglMultiPlaneTexture *self) +{ + g_return_val_if_fail (self->n_planes > 0, 0); + + return cogl_texture_get_height (self->planes[0]); +} + +static void +_cogl_multi_plane_texture_free (CoglMultiPlaneTexture *self) +{ + uint8_t i = 0; + + for (i = 0; i < self->n_planes; i++) + cogl_object_unref (self->planes[i]); + + g_free (self->planes); +} + +CoglMultiPlaneTexture * +cogl_multi_plane_texture_new (CoglPixelFormat format, + CoglTexture **planes, uint8_t n_planes) +{ + CoglMultiPlaneTexture *self = g_slice_new0 (CoglMultiPlaneTexture); + + _cogl_multi_plane_texture_object_new (self); + + self->format = format; + self->n_planes = n_planes; + self->planes = planes; + + return self; +} + +CoglMultiPlaneTexture * +cogl_multi_plane_texture_new_single_plane (CoglPixelFormat format, + CoglTexture *plane) +{ + CoglMultiPlaneTexture *self = g_slice_new0 (CoglMultiPlaneTexture); + + _cogl_multi_plane_texture_object_new (self); + + self->format = format; + self->n_planes = 1; + self->planes = g_malloc (sizeof (CoglTexture *)); + self->planes[0] = plane; + + return self; +} + +char * +cogl_multi_plane_texture_to_string (CoglMultiPlaneTexture *self) +{ + g_autoptr(GString) str = NULL; + g_autofree char *ret = NULL; + uint8_t i; + + str = g_string_new (""); + g_string_append_printf (str, "CoglMultiPlaneTexture (%p) {\n", self); + g_string_append_printf (str, " .format = %s;\n", cogl_pixel_format_to_string (self->format)); + g_string_append_printf (str, " .n_planes = %u;\n", self->n_planes); + g_string_append (str, " .planes = {\n"); + + for (i = 0; i < self->n_planes; i++) + { + CoglTexture *plane = self->planes[i]; + + g_string_append_printf (str, " (%p) { .format = %s },\n", + plane, + cogl_pixel_format_to_string (_cogl_texture_get_format (plane))); + } + + g_string_append (str, " }\n"); + g_string_append (str, "}"); + + ret = g_string_free (g_steal_pointer (&str), FALSE); + return g_steal_pointer (&ret); +} diff --git a/cogl/cogl/cogl-multi-plane-texture.h b/cogl/cogl/cogl-multi-plane-texture.h new file mode 100644 index 000000000..f69ff23bd --- /dev/null +++ b/cogl/cogl/cogl-multi-plane-texture.h @@ -0,0 +1,187 @@ +/* + * Authored By Niels De Graef <niels.degraef@barco.com> + * + * Copyright (C) 2018 Barco NV + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA + * 02111-1307, USA. + */ + +#ifndef __COGL_MULTI_PLANE_TEXTURE_H__ +#define __COGL_MULTI_PLANE_TEXTURE_H__ + +#include "cogl/cogl-texture.h" + +G_BEGIN_DECLS + +/** + * SECTION:cogl-multi-plane-texture + * @title: CoglMultiPlaneTexture + * @short_description: A non-primitive texture that can have multiple planes. + * + * #CoglMultiPlaneTexture allows one to deal with non-trivial formats that + * have multiple planes, requires subsampling and/or aren't in RGB. A common + * example of this are decoded video frames, which often use something in the + * YUV colorspace, combined with subsampling. + * + * The basic idea of a #CoglMultiPlaneTexture is the following: + * - Each plane is represented by a separate #CoglTexture. That means that you + * should add each of these planes as a layer to your CoglPipeline. + * - When dealing with a color space that is not RGB, you can ask the + * #CoglMultiPlaneTexture to create a shader for you that does the conversion + * in the GPU. + * - In case you need to deal with memory access in a format with subsampling, + * you can use cogl_multi_plane_texture_get_width() and its analogous version + * for the height to get the correct size of the texture. + */ + +typedef struct _CoglMultiPlaneTexture CoglMultiPlaneTexture; +#define COGL_MULTI_PLANE_TEXTURE(tex) ((CoglMultiPlaneTexture *) tex) + + +/** + * cogl_multi_plane_texture_get_gtype: + * + * Returns: a #GType that can be used with the GLib type system. + */ +GType cogl_multi_plane_texture_get_gtype (void); + +/** + * cogl_is_multi_plane_texture: + * @object: A #CoglObject pointer + * + * Gets whether the given @object references an existing CoglMultiPlaneTexture. + * + * Return value: %TRUE if the @object references a #CoglMultiPlaneTexture, + * %FALSE otherwise + */ +gboolean +cogl_is_multi_plane_texture (void *object); + +/** + * cogl_multi_plane_texture_new: + * @format: The format of the #CoglMultiPlaneTexture + * @planes: (transfer full): The actual planes of the texture + * @n_planes: The number of planes + * + * Creates a #CoglMultiPlaneTexture with the given @format. Each of the + * #CoglTexture<!-- -->s represents a plane. + * + * Returns: (transfer full): A new #CoglMultiPlaneTexture. Use + * cogl_object_unref() when you're done with it. + */ +CoglMultiPlaneTexture * cogl_multi_plane_texture_new (CoglPixelFormat format, + CoglTexture **planes, + uint8_t n_planes); + +/** + * cogl_multi_plane_texture_new_single_plane: + * @format: The format of the #CoglMultiPlaneTexture + * @plane: (transfer full): The actual planes of the texture + * + * Creates a #CoglMultiPlaneTexture for a "simple" texture, i.e. with only one + * plane. + * + * Returns: (transfer full): A new #CoglMultiPlaneTexture. Use + * cogl_object_unref() when you're done with it. + */ +CoglMultiPlaneTexture * cogl_multi_plane_texture_new_single_plane (CoglPixelFormat format, + CoglTexture *plane); + +/** + * cogl_multi_plane_texture_get_format: + * @self: a #CoglMultiPlaneTexture + * + * Returns the pixel format that is used by this texture. + * + * Returns: The pixel format that is used by this #CoglMultiPlaneTexture. + */ +CoglPixelFormat cogl_multi_plane_texture_get_format (CoglMultiPlaneTexture *self); + +/** + * cogl_multi_plane_texture_get_n_planes: + * @self: a #CoglMultiPlaneTexture + * + * Returns the number of planes for this texture. Note that this is entirely + * dependent on the #CoglPixelFormat that is used. For example, simple RGB + * textures will have a single plane, while some more convoluted formats like + * NV12 and YUV 4:4:4 can have 2 and 3 planes respectively. + * + * Returns: The number of planes in this #CoglMultiPlaneTexture. + */ +uint8_t cogl_multi_plane_texture_get_n_planes (CoglMultiPlaneTexture *self); + +/** + * cogl_multi_plane_texture_get_plane: + * @self: a #CoglMultiPlaneTexture + * @index: the index of the plane + * + * Returns the n'th plane of the #CoglMultiPlaneTexture. Note that it is a + * programming error to use with an index larger than + * cogl_multi_plane_texture_get_n_planes(). + * + * Returns: (transfer none): The plane at the given @index. + */ +CoglTexture * cogl_multi_plane_texture_get_plane (CoglMultiPlaneTexture *self, + guint index); + +/** + * cogl_multi_plane_texture_get_planes: + * @self: a #CoglMultiPlaneTexture + * + * Returns all planes of the #CoglMultiPlaneTexture. + * + * Returns: (transfer none): The planes of this texture. + */ +CoglTexture ** cogl_multi_plane_texture_get_planes (CoglMultiPlaneTexture *self); + +/** + * cogl_multi_plane_texture_get_width: + * @self: a #CoglMultiPlaneTexture + * + * Returns the width of the #CoglMultiPlaneTexture. Prefer this over calling + * cogl_texture_get_width() on one of the textures, as that might give a + * different size when dealing with subsampling. + * + * Returns: The width of the texture. + */ +guint cogl_multi_plane_texture_get_width (CoglMultiPlaneTexture *self); + +/** + * cogl_multi_plane_texture_get_height: + * @self: a #CoglMultiPlaneTexture + * + * Returns the height of the #CoglMultiPlaneTexture. Prefer this over calling + * cogl_texture_get_height() on one of the textures, as that might give a + * different size when dealing with subsampling. + * + * Returns: The height of the texture. + */ +guint cogl_multi_plane_texture_get_height (CoglMultiPlaneTexture *self); + +/** + * cogl_multi_plane_texture_to_string: + * @self: a #CoglMultiPlaneTexture + * + * Returns a string representation of @self, useful for debugging purposes. + * + * Returns: (transfer full): A string representation of @self. Use g_free() when + * done with it. + */ +char * cogl_multi_plane_texture_to_string (CoglMultiPlaneTexture *self); + +G_END_DECLS + +#endif diff --git a/cogl/cogl/cogl-texture-2d.c b/cogl/cogl/cogl-texture-2d.c index d56538557..cd8fce68a 100644 --- a/cogl/cogl/cogl-texture-2d.c +++ b/cogl/cogl/cogl-texture-2d.c @@ -239,6 +239,7 @@ cogl_egl_texture_2d_new_from_image (CoglContext *ctx, int width, int height, CoglPixelFormat format, + CoglTextureComponents components, EGLImageKHR image, GError **error) { @@ -263,6 +264,9 @@ cogl_egl_texture_2d_new_from_image (CoglContext *ctx, tex = _cogl_texture_2d_create_base (ctx, width, height, format, loader); + /* Make sure we've set the right components before allocating */ + cogl_texture_set_components (COGL_TEXTURE (tex), components); + if (!cogl_texture_allocate (COGL_TEXTURE (tex), error)) { cogl_object_unref (tex); diff --git a/cogl/cogl/cogl-texture-2d.h b/cogl/cogl/cogl-texture-2d.h index 5fc97179e..e5b91172d 100644 --- a/cogl/cogl/cogl-texture-2d.h +++ b/cogl/cogl/cogl-texture-2d.h @@ -218,6 +218,7 @@ cogl_egl_texture_2d_new_from_image (CoglContext *ctx, int width, int height, CoglPixelFormat format, + CoglTextureComponents components, EGLImageKHR image, GError **error); diff --git a/cogl/cogl/cogl.h b/cogl/cogl/cogl.h index 1c251cc88..654adfd26 100644 --- a/cogl/cogl/cogl.h +++ b/cogl/cogl/cogl.h @@ -59,6 +59,7 @@ #include <cogl/cogl1-context.h> #include <cogl/cogl-bitmap.h> #include <cogl/cogl-color.h> +#include <cogl/cogl-pixel-format-conversion.h> #include <cogl/cogl-matrix.h> #include <cogl/cogl-matrix-stack.h> #include <cogl/cogl-offscreen.h> @@ -108,6 +109,7 @@ #include <cogl/cogl-sub-texture.h> #include <cogl/cogl-atlas-texture.h> #include <cogl/cogl-meta-texture.h> +#include <cogl/cogl-multi-plane-texture.h> #include <cogl/cogl-primitive-texture.h> #include <cogl/cogl-index-buffer.h> #include <cogl/cogl-attribute-buffer.h> diff --git a/cogl/cogl/meson.build b/cogl/cogl/meson.build index 513fa9c77..23532fb3f 100644 --- a/cogl/cogl/meson.build +++ b/cogl/cogl/meson.build @@ -82,6 +82,7 @@ cogl_headers = [ 'cogl-color.h', 'cogl-framebuffer.h', 'cogl-matrix.h', + 'cogl-multi-plane-texture.h', 'cogl-object.h', 'cogl-offscreen.h', 'cogl-onscreen.h', @@ -322,6 +323,7 @@ cogl_sources = [ 'cogl-atlas-texture-private.h', 'cogl-atlas-texture.c', 'cogl-meta-texture.c', + 'cogl-multi-plane-texture.c', 'cogl-primitive-texture.c', 'cogl-blit.h', 'cogl-blit.c', diff --git a/cogl/cogl/winsys/cogl-winsys-egl-x11.c b/cogl/cogl/winsys/cogl-winsys-egl-x11.c index 9735c7605..220f3b141 100644 --- a/cogl/cogl/winsys/cogl-winsys-egl-x11.c +++ b/cogl/cogl/winsys/cogl-winsys-egl-x11.c @@ -800,6 +800,7 @@ _cogl_winsys_texture_pixmap_x11_create (CoglTexturePixmapX11 *tex_pixmap) tex->width, tex->height, texture_format, + COGL_TEXTURE_COMPONENTS_RGBA, egl_tex_pixmap->image, NULL)); |