compositor: Add MetaMultiTexture class

In future commits, we want to be able to handle more complex textures,
such as video frames which are encoded in a YUV-pixel format and have
multiple planes (which each map to a separate texture).

To accomplish this, we introduce a new object `MetaMultiTexture`: this
object can deal with more complex formats by handling multiple
`CoglTexture`s.

It supports shaders for pixel format conversion from YUV to RGBA, as
well as blending. While custom bleding is currently only required for
YUV formats, we also implement it for RGB ones. This allows us to
simplify code in other places and will be needed in the future once
we want to support blending between different color spaces.

Co-Authored-By: Robert Mader <robert.mader@collabora.com>
Co-Authored-By: Sebastian Wick <sebastian.wick@redhat.com>
Part-of: <https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/2191>
This commit is contained in:
Niels De Graef 2019-10-16 12:11:33 +02:00 committed by Marge Bot
parent 358c10de14
commit 5181a826d1
7 changed files with 691 additions and 0 deletions

View File

@ -0,0 +1,49 @@
/*
* 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/>.
*/
#ifndef META_MULTI_TEXTURE_FORMAT_PRIVATE_H
#define META_MULTI_TEXTURE_FORMAT_PRIVATE_H
#include <cogl/cogl.h>
#include "meta/meta-multi-texture-format.h"
G_BEGIN_DECLS
const char * meta_multi_texture_format_to_string (MetaMultiTextureFormat format);
int meta_multi_texture_format_get_n_planes (MetaMultiTextureFormat format);
void meta_multi_texture_format_get_subformats (MetaMultiTextureFormat format,
CoglPixelFormat *formats_out);
void meta_multi_texture_format_get_plane_indices (MetaMultiTextureFormat format,
uint8_t *plane_indices);
void meta_multi_texture_format_get_subsampling_factors (MetaMultiTextureFormat format,
uint8_t *horizontal_factors,
uint8_t *vertical_factors);
gboolean meta_multi_texture_format_get_snippets (MetaMultiTextureFormat format,
CoglSnippet **fragment_globals_snippet,
CoglSnippet **fragment_snippet);
G_END_DECLS
#endif /* META_MULTI_TEXTURE_FORMAT_PRIVATE_H */

View File

@ -0,0 +1,228 @@
/*
* 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/>.
*/
/**
* SECTION:meta-multi-texture-format
* @title: MetaMultiTextureFormat
* @short_description: A representation for complex pixel formats
*
* Some pixel formats that are used in the wild are a bit more complex than
* just ARGB and all its variants. For example: a component might be put in a
* different plane (i.e. at a different place in memory). Another example are
* formats that use Y, U, and V components rather than RGB; if we composit them
* onto an RGBA framebuffer, we have to make sure for example that these get
* converted to the right color format first (using e.g. a shader).
*/
#include "config.h"
#include "compositor/meta-multi-texture-format-private.h"
#include <cogl/cogl.h>
#include <stdlib.h>
#include <string.h>
static const char *shader_global_conversions =
"vec4 yuv_to_rgb(vec4 yuva) \n"
"{ \n"
" vec4 res; \n"
" float Y = 1.16438356 * (yuva.x - 0.0625); \n"
" float su = yuva.y - 0.5; \n"
" float sv = yuva.z - 0.5; \n"
" res.r = Y + 1.59602678 * sv; \n"
" res.g = Y - 0.39176229 * su - 0.81296764 * sv; \n"
" res.b = Y + 2.01723214 * su; \n"
" res.rgb *= yuva.w; \n"
" res.a = yuva.w; \n"
" return res; \n"
"} \n";
static const char rgba_shader[] =
"cogl_color_out = \n"
" texture2D(cogl_sampler0, cogl_tex_coord0_in.st) * cogl_color_in.a; \n";
/* Shader for a single YUV plane */
static const char y_xuxv_shader[] =
"vec4 yuva = vec4(0.0, 0.0, 0.0, cogl_color_in.a); \n"
"yuva.x = texture2D(cogl_sampler0, cogl_tex_coord0_in.st).x; \n"
"yuva.yz = texture2D(cogl_sampler1, cogl_tex_coord1_in.st).ga; \n"
"cogl_color_out = yuv_to_rgb(yuva); \n";
/* Shader for 1 Y-plane and 1 UV-plane */
static const char nv12_shader[] =
"vec4 yuva = vec4(0.0, 0.0, 0.0, cogl_color_in.a); \n"
"yuva.x = texture2D(cogl_sampler0, cogl_tex_coord0_in.st).x; \n"
"yuva.yz = texture2D(cogl_sampler1, cogl_tex_coord1_in.st).rg; \n"
"cogl_color_out = yuv_to_rgb(yuva); \n";
/* Shader for 1 Y-plane, 1 U-plane and 1 V-plane */
static const char yuv420_shader[] =
"vec4 yuva = vec4(0.0, 0.0, 0.0, cogl_color_in.a); \n"
"yuva.x = texture2D(cogl_sampler0, cogl_tex_coord0_in.st).x; \n"
"yuva.y = texture2D(cogl_sampler1, cogl_tex_coord1_in.st).x; \n"
"yuva.z = texture2D(cogl_sampler2, cogl_tex_coord2_in.st).x; \n"
"cogl_color_out = yuv_to_rgb(yuva); \n";
typedef struct _MetaMultiTextureFormatInfo
{
MetaMultiTextureFormat multi_format;
const char *name;
uint8_t n_planes;
/* Per plane-information */
CoglPixelFormat subformats[COGL_PIXEL_FORMAT_MAX_PLANES]; /* influences how we deal with it on a GL level */
uint8_t plane_indices[COGL_PIXEL_FORMAT_MAX_PLANES]; /* source plane */
uint8_t hsub[COGL_PIXEL_FORMAT_MAX_PLANES]; /* horizontal subsampling */
uint8_t vsub[COGL_PIXEL_FORMAT_MAX_PLANES]; /* vertical subsampling */
/* Shaders */
const char *rgb_shader; /* Shader to convert to RGBA (or NULL) */
} MetaMultiTextureFormatInfo;
/* NOTE: The actual enum values are used as the index, so you don't need to
* loop over the table */
static MetaMultiTextureFormatInfo multi_format_table[] = {
/* Invalid */
{},
/* Simple */
{
.name = "",
.n_planes = 1,
.subformats = { COGL_PIXEL_FORMAT_ANY },
.plane_indices = { 0 },
.hsub = { 1 },
.vsub = { 1 },
.rgb_shader = rgba_shader,
},
/* Packed YUV */
{
.name = "YUYV",
.n_planes = 2,
.subformats = { COGL_PIXEL_FORMAT_RG_88, COGL_PIXEL_FORMAT_BGRA_8888_PRE },
.plane_indices = { 0, 0 },
.hsub = { 1, 2 },
.vsub = { 1, 1 },
.rgb_shader = y_xuxv_shader,
},
/* 2 plane YUV */
{
.name = "NV12",
.n_planes = 2,
.subformats = { COGL_PIXEL_FORMAT_G_8, COGL_PIXEL_FORMAT_RG_88 },
.plane_indices = { 0, 1 },
.hsub = { 1, 2 },
.vsub = { 1, 2 },
.rgb_shader = nv12_shader,
},
/* 3 plane YUV */
{
.name = "YUV420",
.n_planes = 3,
.subformats = { COGL_PIXEL_FORMAT_G_8, COGL_PIXEL_FORMAT_G_8, COGL_PIXEL_FORMAT_G_8 },
.plane_indices = { 0, 1, 2 },
.hsub = { 1, 2, 2 },
.vsub = { 1, 2, 2 },
.rgb_shader = yuv420_shader,
},
};
const char *
meta_multi_texture_format_to_string (MetaMultiTextureFormat format)
{
g_return_val_if_fail (format < G_N_ELEMENTS (multi_format_table), NULL);
return multi_format_table[format].name;
}
int
meta_multi_texture_format_get_n_planes (MetaMultiTextureFormat format)
{
g_return_val_if_fail (format < G_N_ELEMENTS (multi_format_table), 0);
return multi_format_table[format].n_planes;
}
void
meta_multi_texture_format_get_subformats (MetaMultiTextureFormat format,
CoglPixelFormat *formats_out)
{
size_t i;
g_return_if_fail (format < G_N_ELEMENTS (multi_format_table));
for (i = 0; i < multi_format_table[format].n_planes; i++)
formats_out[i] = multi_format_table[format].subformats[i];
}
void
meta_multi_texture_format_get_plane_indices (MetaMultiTextureFormat format,
uint8_t *plane_indices)
{
size_t i;
g_return_if_fail (format < G_N_ELEMENTS (multi_format_table));
for (i = 0; i < multi_format_table[format].n_planes; i++)
plane_indices[i] = multi_format_table[format].plane_indices[i];
}
void
meta_multi_texture_format_get_subsampling_factors (MetaMultiTextureFormat format,
uint8_t *horizontal_factors,
uint8_t *vertical_factors)
{
size_t i;
g_return_if_fail (format < G_N_ELEMENTS (multi_format_table));
for (i = 0; i < multi_format_table[format].n_planes; i++)
{
horizontal_factors[i] = multi_format_table[format].hsub[i];
vertical_factors[i] = multi_format_table[format].vsub[i];
}
}
gboolean
meta_multi_texture_format_get_snippets (MetaMultiTextureFormat format,
CoglSnippet **fragment_globals_snippet,
CoglSnippet **fragment_snippet)
{
g_return_val_if_fail (format < G_N_ELEMENTS (multi_format_table), FALSE);
if (multi_format_table[format].rgb_shader == NULL)
return FALSE;
if (fragment_globals_snippet)
{
*fragment_globals_snippet =
cogl_snippet_new (COGL_SNIPPET_HOOK_FRAGMENT_GLOBALS,
shader_global_conversions,
NULL);
}
if (fragment_snippet)
{
*fragment_snippet =
cogl_snippet_new (COGL_SNIPPET_HOOK_FRAGMENT,
NULL,
multi_format_table[format].rgb_shader);
}
return TRUE;
}

View File

@ -0,0 +1,290 @@
/*
* 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/>.
*/
/**
* SECTION:meta-multi-texture
* @title: MetaMultiTexture
* @short_description: A texture that can have multiple planes.
*
* #MetaMultiTexture 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 #MetaMultiTexture 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
* #MetaMultiTexture 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 meta_multi_texture_get_width() and its analogous version
* for the height to get the correct size of the texture.
*/
#include "config.h"
#include "meta/meta-multi-texture.h"
#include "meta/meta-enum-types.h"
struct _MetaMultiTexture
{
GObject parent_instance;
MetaMultiTextureFormat format;
int n_planes;
CoglTexture **planes;
};
G_DEFINE_TYPE (MetaMultiTexture, meta_multi_texture, G_TYPE_OBJECT);
/**
* meta_multi_texture_get_format:
* @multi_texture: a #MetaMultiTexture
*
* Returns the #MetaMultiTextureFormat that is used by this texture.
*
* Returns: The texture format that is used by this #MetaMultiTexture.
*/
MetaMultiTextureFormat
meta_multi_texture_get_format (MetaMultiTexture *multi_texture)
{
g_return_val_if_fail (META_IS_MULTI_TEXTURE (multi_texture), META_MULTI_TEXTURE_FORMAT_SIMPLE);
return multi_texture->format;
}
/**
* meta_multi_texture_is_simple:
* @multi_texture: a #MetaMultiTexture
*
* A small function that checks whether the given multi texture uses a "simple"
* format, i.e. one that can be represented by a #CoglPixelFormat.
*
* Returns: Whether the texture format is #META_MULTI_TEXTURE_FORMAT_SIMPLE
*/
gboolean
meta_multi_texture_is_simple (MetaMultiTexture *multi_texture)
{
g_return_val_if_fail (META_IS_MULTI_TEXTURE (multi_texture), FALSE);
return multi_texture->format == META_MULTI_TEXTURE_FORMAT_SIMPLE;
}
/**
* meta_multi_texture_get_n_planes:
* @multi_texture: a #MetaMultiTexture
*
* 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 #MetaMultiTexture.
*/
int
meta_multi_texture_get_n_planes (MetaMultiTexture *multi_texture)
{
g_return_val_if_fail (META_IS_MULTI_TEXTURE (multi_texture), 0);
return multi_texture->n_planes;
}
/**
* meta_multi_texture_get_plane:
* @multi_texture: a #MetaMultiTexture
* @index: the index of the plane
*
* Returns the n'th plane of the #MetaMultiTexture. Note that it's a programming
* error to use with an index larger than meta_multi_texture_get_n_planes().
*
* Returns: (transfer none): The plane at the given @index.
*/
CoglTexture *
meta_multi_texture_get_plane (MetaMultiTexture *multi_texture,
int index)
{
g_return_val_if_fail (META_IS_MULTI_TEXTURE (multi_texture), 0);
g_return_val_if_fail (index < multi_texture->n_planes, NULL);
return multi_texture->planes[index];
}
/**
* meta_multi_texture_get_width:
* @multi_texture: a #MetaMultiTexture
*
* Returns the width of the #MetaMultiTexture. 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.
*/
int
meta_multi_texture_get_width (MetaMultiTexture *multi_texture)
{
g_return_val_if_fail (META_IS_MULTI_TEXTURE (multi_texture), 0);
return cogl_texture_get_width (multi_texture->planes[0]);
}
/**
* meta_multi_texture_get_height:
* @multi_texture: a #MetaMultiTexture
*
* Returns the height of the #MetaMultiTexture. 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.
*/
int
meta_multi_texture_get_height (MetaMultiTexture *multi_texture)
{
g_return_val_if_fail (META_IS_MULTI_TEXTURE (multi_texture), 0);
return cogl_texture_get_height (multi_texture->planes[0]);
}
static void
meta_multi_texture_finalize (GObject *object)
{
MetaMultiTexture *multi_texture = META_MULTI_TEXTURE (object);
int i;
for (i = 0; i < multi_texture->n_planes; i++)
cogl_clear_object (&multi_texture->planes[i]);
g_free (multi_texture->planes);
G_OBJECT_CLASS (meta_multi_texture_parent_class)->finalize (object);
}
static void
meta_multi_texture_init (MetaMultiTexture *multi_texture)
{
}
static void
meta_multi_texture_class_init (MetaMultiTextureClass *klass)
{
GObjectClass *gobj_class = G_OBJECT_CLASS (klass);
gobj_class->finalize = meta_multi_texture_finalize;
}
/**
* meta_multi_texture_new:
* @format: The format of the #MetaMultiTexture
* @planes: (transfer full): The actual planes of the texture
* @n_planes: The number of planes
*
* Creates a #MetaMultiTexture with the given @format. Each of the
* #CoglTexture<!-- -->s represents a plane.
*
* Returns: (transfer full): A new #MetaMultiTexture. Use g_object_unref() when
* you're done with it.
*/
MetaMultiTexture *
meta_multi_texture_new (MetaMultiTextureFormat format,
CoglTexture **planes,
int n_planes)
{
MetaMultiTexture *multi_texture;
g_return_val_if_fail (planes != NULL, NULL);
g_return_val_if_fail (n_planes > 0, NULL);
multi_texture = g_object_new (META_TYPE_MULTI_TEXTURE, NULL);
multi_texture->format = format;
multi_texture->n_planes = n_planes;
multi_texture->planes = planes;
return multi_texture;
}
/**
* meta_multi_texture_new_simple:
* @plane: (transfer full): The single plane of the texture
*
* Creates a #MetaMultiTexture for a "simple" texture, i.e. with only one
* plane, in a format that can be represented using #CoglPixelFormat.
*
* Returns: (transfer full): A new #MetaMultiTexture. Use g_object_unref() when
* you're done with it.
*/
MetaMultiTexture *
meta_multi_texture_new_simple (CoglTexture *plane)
{
MetaMultiTexture *multi_texture;
g_return_val_if_fail (plane != NULL, NULL);
multi_texture = g_object_new (META_TYPE_MULTI_TEXTURE, NULL);
multi_texture->format = META_MULTI_TEXTURE_FORMAT_SIMPLE;
multi_texture->n_planes = 1;
multi_texture->planes = g_malloc (sizeof (CoglTexture *));
multi_texture->planes[0] = plane;
return multi_texture;
}
/**
* meta_multi_texture_to_string:
* @multi_texture: a #MetaMultiTexture
*
* Returns a string representation of @multi_texture, useful for debugging
* purposes.
*
* Returns: (transfer full): A string representation of @multi_texture. Use
* g_free() when done with it.
*/
char *
meta_multi_texture_to_string (MetaMultiTexture *multi_texture)
{
g_autoptr (GString) str = NULL;
g_autofree char *format_str = NULL;
g_autofree char *ret = NULL;
uint8_t i;
str = g_string_new ("");
g_string_append_printf (str, "MetaMultiTexture (%p) {\n", multi_texture);
format_str = g_enum_to_string (META_TYPE_MULTI_TEXTURE_FORMAT, multi_texture->format);
g_string_append_printf (str, " .format = %s;\n", format_str);
g_string_append_printf (str, " .n_planes = %u;\n", multi_texture->n_planes);
g_string_append (str, " .planes = {\n");
for (i = 0; i < multi_texture->n_planes; i++)
{
CoglTexture *plane = multi_texture->planes[i];
CoglPixelFormat plane_format = _cogl_texture_get_format (plane);
g_string_append_printf (str, " (%p) { .format = %s },\n",
plane,
cogl_pixel_format_to_string (plane_format));
}
g_string_append (str, " }\n");
g_string_append (str, "}");
ret = g_string_free (g_steal_pointer (&str), FALSE);
return g_steal_pointer (&ret);
}

View File

@ -320,6 +320,9 @@ mutter_sources = [
'compositor/meta-later.c',
'compositor/meta-module.c',
'compositor/meta-module.h',
'compositor/meta-multi-texture.c',
'compositor/meta-multi-texture-format.c',
'compositor/meta-multi-texture-format-private.h',
'compositor/meta-plugin.c',
'compositor/meta-plugin-manager.c',
'compositor/meta-plugin-manager.h',

View File

@ -24,6 +24,8 @@ mutter_public_headers = [
'meta-launch-context.h',
'meta-later.h',
'meta-monitor-manager.h',
'meta-multi-texture.h',
'meta-multi-texture-format.h',
'meta-plugin.h',
'meta-remote-access-controller.h',
'meta-selection.h',

View File

@ -0,0 +1,46 @@
/*
* 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/>.
*/
#ifndef META_MULTI_TEXTURE_FORMAT_H
#define META_MULTI_TEXTURE_FORMAT_H
#include <glib.h>
G_BEGIN_DECLS
/**
* MetaMultiTextureFormat:
* @META_MULTI_TEXTURE_FORMAT_INVALID: Invalid value
* @META_MULTI_TEXTURE_FORMAT_SIMPLE: Any format supported by Cogl (see #CoglPixelFormat)
* @META_MULTI_TEXTURE_FORMAT_YUYV: YUYV, 32 bits, 16 bpc (Y), 8 bpc (U & V)
* @META_MULTI_TEXTURE_FORMAT_NV12: 2 planes: 1 Y-plane, 1 UV-plane (2x2 subsampled)
* @META_MULTI_TEXTURE_FORMAT_YUV420: 3 planes: 1 Y-plane, 1 U-plane (2x2 subsampled), 1 V-plane (2x2 subsampled)
*/
typedef enum _MetaMultiTextureFormat
{
META_MULTI_TEXTURE_FORMAT_INVALID,
META_MULTI_TEXTURE_FORMAT_SIMPLE,
META_MULTI_TEXTURE_FORMAT_YUYV,
META_MULTI_TEXTURE_FORMAT_NV12,
META_MULTI_TEXTURE_FORMAT_YUV420,
} MetaMultiTextureFormat;
G_END_DECLS
#endif /* META_MULTI_TEXTURE_FORMAT_H */

View File

@ -0,0 +1,73 @@
/*
* 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 META_MULTI_TEXTURE_H
#define META_MULTI_TEXTURE_H
#include <glib-object.h>
#include <cogl/cogl.h>
#include <meta/common.h>
#include "meta/meta-multi-texture-format.h"
G_BEGIN_DECLS
#define META_TYPE_MULTI_TEXTURE (meta_multi_texture_get_type ())
META_EXPORT
G_DECLARE_FINAL_TYPE (MetaMultiTexture,
meta_multi_texture,
META,
MULTI_TEXTURE,
GObject)
META_EXPORT
MetaMultiTexture * meta_multi_texture_new (MetaMultiTextureFormat format,
CoglTexture **planes,
int n_planes);
META_EXPORT
MetaMultiTexture * meta_multi_texture_new_simple (CoglTexture *plane);
META_EXPORT
MetaMultiTextureFormat meta_multi_texture_get_format (MetaMultiTexture *multi_texture);
META_EXPORT
gboolean meta_multi_texture_is_simple (MetaMultiTexture *multi_texture);
META_EXPORT
int meta_multi_texture_get_n_planes (MetaMultiTexture *multi_texture);
META_EXPORT
CoglTexture * meta_multi_texture_get_plane (MetaMultiTexture *multi_texture,
int index);
META_EXPORT
int meta_multi_texture_get_width (MetaMultiTexture *multi_texture);
META_EXPORT
int meta_multi_texture_get_height (MetaMultiTexture *multi_texture);
META_EXPORT
char * meta_multi_texture_to_string (MetaMultiTexture *multi_texture);
G_END_DECLS
#endif /* META_MULTI_TEXTURE_H */