mirror of
https://github.com/brl/mutter.git
synced 2025-02-23 16:34:10 +00:00

Split the struct into mutable and immutable parts. Access the mutable parts via getters and the immutable parts via a single struct. This avoids copying around the immutable parts. Part-of: <https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/3280>
231 lines
8.0 KiB
C
231 lines
8.0 KiB
C
/*
|
|
* 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 composite 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 y_uv_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 y_u_v_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 _MetaMultiTextureFormatFullInfo
|
|
{
|
|
MetaMultiTextureFormatInfo info;
|
|
|
|
/* Name */
|
|
const char *name;
|
|
/* Shader to convert to RGBA (or NULL) */
|
|
const char *rgb_shader;
|
|
/* Cached snippet */
|
|
GOnce snippet_once;
|
|
} MetaMultiTextureFormatFullInfo;
|
|
|
|
/* NOTE: The actual enum values are used as the index, so you don't need to
|
|
* loop over the table */
|
|
static MetaMultiTextureFormatFullInfo multi_format_table[] = {
|
|
/* Invalid */
|
|
[META_MULTI_TEXTURE_FORMAT_INVALID] = {},
|
|
/* Simple */
|
|
[META_MULTI_TEXTURE_FORMAT_SIMPLE] = {
|
|
.name = "",
|
|
.rgb_shader = rgba_shader,
|
|
.snippet_once = G_ONCE_INIT,
|
|
.info = {
|
|
.n_planes = 1,
|
|
.subformats = { COGL_PIXEL_FORMAT_ANY },
|
|
.plane_indices = { 0 },
|
|
.hsub = { 1 },
|
|
.vsub = { 1 },
|
|
},
|
|
},
|
|
/* Packed YUV */
|
|
[META_MULTI_TEXTURE_FORMAT_YUYV] = {
|
|
.name = "YUYV",
|
|
.rgb_shader = y_xuxv_shader,
|
|
.snippet_once = G_ONCE_INIT,
|
|
.info = {
|
|
.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 },
|
|
},
|
|
},
|
|
/* 2 plane YUV */
|
|
[META_MULTI_TEXTURE_FORMAT_NV12] = {
|
|
.name = "NV12",
|
|
.rgb_shader = y_uv_shader,
|
|
.snippet_once = G_ONCE_INIT,
|
|
.info = {
|
|
.n_planes = 2,
|
|
.subformats = { COGL_PIXEL_FORMAT_R_8, COGL_PIXEL_FORMAT_RG_88 },
|
|
.plane_indices = { 0, 1 },
|
|
.hsub = { 1, 2 },
|
|
.vsub = { 1, 2 },
|
|
},
|
|
},
|
|
[META_MULTI_TEXTURE_FORMAT_P010] = {
|
|
.name = "P010",
|
|
.rgb_shader = y_uv_shader,
|
|
.snippet_once = G_ONCE_INIT,
|
|
.info = {
|
|
.n_planes = 2,
|
|
.subformats = { COGL_PIXEL_FORMAT_R_16, COGL_PIXEL_FORMAT_RG_1616 },
|
|
.plane_indices = { 0, 1 },
|
|
.hsub = { 1, 2 },
|
|
.vsub = { 1, 2 },
|
|
},
|
|
},
|
|
/* 3 plane YUV */
|
|
[META_MULTI_TEXTURE_FORMAT_YUV420] = {
|
|
.name = "YUV420",
|
|
.rgb_shader = y_u_v_shader,
|
|
.snippet_once = G_ONCE_INIT,
|
|
.info = {
|
|
.n_planes = 3,
|
|
.subformats = { COGL_PIXEL_FORMAT_R_8, COGL_PIXEL_FORMAT_R_8, COGL_PIXEL_FORMAT_R_8 },
|
|
.plane_indices = { 0, 1, 2 },
|
|
.hsub = { 1, 2, 2 },
|
|
.vsub = { 1, 2, 2 },
|
|
},
|
|
},
|
|
};
|
|
|
|
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;
|
|
}
|
|
|
|
const MetaMultiTextureFormatInfo *
|
|
meta_multi_texture_format_get_info (MetaMultiTextureFormat format)
|
|
{
|
|
g_return_val_if_fail (format < G_N_ELEMENTS (multi_format_table), NULL);
|
|
|
|
return &multi_format_table[format].info;
|
|
}
|
|
|
|
static gpointer
|
|
create_globals_snippet (gpointer data)
|
|
{
|
|
return cogl_snippet_new (COGL_SNIPPET_HOOK_FRAGMENT_GLOBALS,
|
|
shader_global_conversions,
|
|
NULL);
|
|
}
|
|
|
|
static gpointer
|
|
create_format_snippet (gpointer data)
|
|
{
|
|
MetaMultiTextureFormat format =
|
|
(MetaMultiTextureFormat) GPOINTER_TO_INT (data);
|
|
|
|
return cogl_snippet_new (COGL_SNIPPET_HOOK_FRAGMENT,
|
|
NULL,
|
|
multi_format_table[format].rgb_shader);
|
|
}
|
|
|
|
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)
|
|
{
|
|
static GOnce globals_once = G_ONCE_INIT;
|
|
CoglSnippet *globals_snippet;
|
|
|
|
globals_snippet = g_once (&globals_once, create_globals_snippet, NULL);
|
|
*fragment_globals_snippet = g_object_ref (globals_snippet);
|
|
}
|
|
|
|
if (fragment_snippet)
|
|
{
|
|
CoglSnippet *format_snippet;
|
|
|
|
format_snippet = g_once (&multi_format_table[format].snippet_once,
|
|
create_format_snippet,
|
|
GINT_TO_POINTER (format));
|
|
*fragment_snippet = g_object_ref (format_snippet);
|
|
}
|
|
|
|
return TRUE;
|
|
}
|