Compare commits
5 Commits
citadel
...
wip/nielsd
Author | SHA1 | Date | |
---|---|---|---|
|
302128d6bb | ||
|
ee17ddc18e | ||
|
f11ca9cfaf | ||
|
c2e191fe3f | ||
|
65a3b13b2f |
480
src/compositor/meta-multi-texture-format.c
Normal file
480
src/compositor/meta-multi-texture-format.c
Normal file
@ -0,0 +1,480 @@
|
||||
/*
|
||||
* 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 "meta/meta-multi-texture-format.h"
|
||||
|
||||
#include <cogl/cogl.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#define _YUV_TO_RGB(res, y, u, v) \
|
||||
"vec4 " res ";\n" \
|
||||
res ".r = (" y ") + 1.59765625 * (" v ");\n" \
|
||||
res ".g = (" y ") - 0.390625 * (" u ") - 0.8125 * (" v ");\n" \
|
||||
res ".b = (" y ") + 2.015625 * (" u ");\n" \
|
||||
res ".a = 1.0;\n"
|
||||
|
||||
/* Shader for a single YUV plane */
|
||||
#define YUV_TO_RGB_FUNC "meta_yuv_to_rgba"
|
||||
static const char yuv_to_rgb_shader[] =
|
||||
"vec4\n"
|
||||
YUV_TO_RGB_FUNC " (vec2 UV)\n"
|
||||
"{\n"
|
||||
" vec4 orig_color = texture2D(cogl_sampler0, UV);\n"
|
||||
" float y = 1.16438356 * (orig_color.r - 0.0625);\n"
|
||||
" float u = orig_color.g - 0.5;\n"
|
||||
" float v = orig_color.b - 0.5;\n"
|
||||
_YUV_TO_RGB ("color", "y", "u", "v")
|
||||
" return color;\n"
|
||||
"}\n";
|
||||
|
||||
/* Shader for 1 Y-plane and 1 UV-plane */
|
||||
#define Y_UV_TO_RGB_FUNC "meta_y_uv_to_rgba"
|
||||
static const char y_uv_to_rgb_shader[] =
|
||||
"vec4\n"
|
||||
Y_UV_TO_RGB_FUNC "(vec2 UV)\n"
|
||||
"{\n"
|
||||
" float y = 1.1640625 * (texture2D (cogl_sampler0, UV).x - 0.0625);\n"
|
||||
" vec2 uv = texture2D (cogl_sampler1, UV).rg;\n"
|
||||
" uv -= 0.5;\n"
|
||||
" float u = uv.x;\n"
|
||||
" float v = uv.y;\n"
|
||||
_YUV_TO_RGB ("color", "y", "u", "v")
|
||||
" return color;\n"
|
||||
"}\n";
|
||||
|
||||
/* Shader for 1 Y-plane, 1 U-plane and 1 V-plane */
|
||||
#define Y_U_V_TO_RGB_FUNC "meta_y_u_v_to_rgba"
|
||||
static const char y_u_v_to_rgb_shader[] =
|
||||
"vec4\n"
|
||||
Y_U_V_TO_RGB_FUNC "(vec2 UV)\n"
|
||||
"{\n"
|
||||
" float y = 1.16438356 * (texture2D(cogl_sampler0, UV).x - 0.0625);\n"
|
||||
" float u = texture2D(cogl_sampler1, UV).x - 0.5;\n"
|
||||
" float v = texture2D(cogl_sampler2, UV).x - 0.5;\n"
|
||||
_YUV_TO_RGB ("color", "y", "u", "v")
|
||||
" return color;\n"
|
||||
"}\n";
|
||||
|
||||
|
||||
typedef struct _MetaMultiTextureFormatInfo
|
||||
{
|
||||
MetaMultiTextureFormat multi_format;
|
||||
uint8_t n_planes;
|
||||
|
||||
/* Per plane-information */
|
||||
uint8_t bpp[COGL_PIXEL_FORMAT_MAX_PLANES]; /* Bytes per pixel (without subsampling) */
|
||||
uint8_t hsub[COGL_PIXEL_FORMAT_MAX_PLANES]; /* horizontal subsampling */
|
||||
uint8_t vsub[COGL_PIXEL_FORMAT_MAX_PLANES]; /* vertical subsampling */
|
||||
CoglPixelFormat subformats[COGL_PIXEL_FORMAT_MAX_PLANES]; /* influences how we deal with it on a GL level */
|
||||
|
||||
/* Shaders */
|
||||
const char *rgb_shaderfunc; /* Shader name to convert to RGBA (or NULL) */
|
||||
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[] = {
|
||||
/* Simple */
|
||||
{
|
||||
.n_planes = 1,
|
||||
.bpp = { 4 },
|
||||
.hsub = { 1 },
|
||||
.vsub = { 1 },
|
||||
.subformats = { COGL_PIXEL_FORMAT_ANY },
|
||||
.rgb_shaderfunc = NULL,
|
||||
.rgb_shader = NULL,
|
||||
},
|
||||
/* Packed YUV */
|
||||
{ /* YUYV */
|
||||
.n_planes = 1,
|
||||
.bpp = { 4 },
|
||||
.hsub = { 1 },
|
||||
.vsub = { 1 },
|
||||
.subformats = { COGL_PIXEL_FORMAT_ARGB_8888 },
|
||||
.rgb_shaderfunc = YUV_TO_RGB_FUNC,
|
||||
.rgb_shader = yuv_to_rgb_shader,
|
||||
},
|
||||
{ /* YVYU */
|
||||
.n_planes = 1,
|
||||
.bpp = { 4 },
|
||||
.hsub = { 1 },
|
||||
.vsub = { 1 },
|
||||
.subformats = { COGL_PIXEL_FORMAT_ARGB_8888 },
|
||||
.rgb_shaderfunc = YUV_TO_RGB_FUNC,
|
||||
.rgb_shader = yuv_to_rgb_shader,
|
||||
},
|
||||
{ /* UYVY */
|
||||
.n_planes = 1,
|
||||
.bpp = { 4 },
|
||||
.hsub = { 1 },
|
||||
.vsub = { 1 },
|
||||
.subformats = { COGL_PIXEL_FORMAT_ARGB_8888 },
|
||||
.rgb_shaderfunc = YUV_TO_RGB_FUNC,
|
||||
.rgb_shader = yuv_to_rgb_shader,
|
||||
},
|
||||
{ /* VYUY */
|
||||
.n_planes = 1,
|
||||
.bpp = { 4 },
|
||||
.hsub = { 1 },
|
||||
.vsub = { 1 },
|
||||
.subformats = { COGL_PIXEL_FORMAT_ARGB_8888 },
|
||||
.rgb_shaderfunc = YUV_TO_RGB_FUNC,
|
||||
.rgb_shader = yuv_to_rgb_shader,
|
||||
},
|
||||
{ /* AYUV */
|
||||
.n_planes = 1,
|
||||
.bpp = { 4 },
|
||||
.hsub = { 1 },
|
||||
.vsub = { 1 },
|
||||
.subformats = { COGL_PIXEL_FORMAT_ARGB_8888 },
|
||||
.rgb_shaderfunc = YUV_TO_RGB_FUNC,
|
||||
.rgb_shader = yuv_to_rgb_shader,
|
||||
},
|
||||
/* 2 plane RGB + A */
|
||||
{ /* XRGB8888_A8 */
|
||||
.n_planes = 2,
|
||||
.bpp = { 4, 1 },
|
||||
.hsub = { 1, 1 },
|
||||
.vsub = { 1, 1 },
|
||||
.subformats = { COGL_PIXEL_FORMAT_ARGB_8888, COGL_PIXEL_FORMAT_A_8 },
|
||||
.rgb_shaderfunc = NULL,
|
||||
.rgb_shader = NULL,
|
||||
},
|
||||
{ /* XBGR8888_A8 */
|
||||
.n_planes = 2,
|
||||
.bpp = { 4, 1 },
|
||||
.hsub = { 1, 1 },
|
||||
.vsub = { 1, 1 },
|
||||
.subformats = { COGL_PIXEL_FORMAT_ABGR_8888, COGL_PIXEL_FORMAT_A_8 },
|
||||
.rgb_shaderfunc = NULL,
|
||||
.rgb_shader = NULL,
|
||||
},
|
||||
{ /* RGBX8888_A8 */
|
||||
.n_planes = 2,
|
||||
.bpp = { 4, 1 },
|
||||
.hsub = { 1, 1 },
|
||||
.vsub = { 1, 1 },
|
||||
.subformats = { COGL_PIXEL_FORMAT_RGBA_8888, COGL_PIXEL_FORMAT_A_8 },
|
||||
.rgb_shaderfunc = NULL,
|
||||
.rgb_shader = NULL,
|
||||
},
|
||||
{ /* BGRX8888_A8 */
|
||||
.n_planes = 2,
|
||||
.bpp = { 4, 1 },
|
||||
.hsub = { 1, 1 },
|
||||
.vsub = { 1, 1 },
|
||||
.subformats = { COGL_PIXEL_FORMAT_BGRA_8888, COGL_PIXEL_FORMAT_A_8 },
|
||||
.rgb_shaderfunc = NULL,
|
||||
.rgb_shader = NULL,
|
||||
},
|
||||
{ /* RGB888_A8 */
|
||||
.n_planes = 2,
|
||||
.bpp = { 3, 1 },
|
||||
.hsub = { 1, 1 },
|
||||
.vsub = { 1, 1 },
|
||||
.subformats = { COGL_PIXEL_FORMAT_RGB_888, COGL_PIXEL_FORMAT_A_8 },
|
||||
.rgb_shaderfunc = NULL,
|
||||
.rgb_shader = NULL,
|
||||
},
|
||||
{ /* BGR888_A8 */
|
||||
.n_planes = 2,
|
||||
.bpp = { 3, 1 },
|
||||
.hsub = { 1, 1 },
|
||||
.vsub = { 1, 1 },
|
||||
.subformats = { COGL_PIXEL_FORMAT_BGR_888, COGL_PIXEL_FORMAT_A_8 },
|
||||
.rgb_shaderfunc = NULL,
|
||||
.rgb_shader = NULL,
|
||||
},
|
||||
{ /* RGB565_A8 */
|
||||
.n_planes = 2,
|
||||
.bpp = { 2, 1 },
|
||||
.hsub = { 1, 1 },
|
||||
.vsub = { 1, 1 },
|
||||
.subformats = { COGL_PIXEL_FORMAT_RGB_565, COGL_PIXEL_FORMAT_A_8 },
|
||||
.rgb_shaderfunc = NULL,
|
||||
.rgb_shader = NULL,
|
||||
},
|
||||
{ /* BGR565_A8 */
|
||||
.n_planes = 2,
|
||||
.bpp = { 2, 1 },
|
||||
.hsub = { 1, 1 },
|
||||
.vsub = { 1, 1 },
|
||||
.subformats = { COGL_PIXEL_FORMAT_RGB_565, COGL_PIXEL_FORMAT_A_8 },
|
||||
.rgb_shaderfunc = NULL,
|
||||
.rgb_shader = NULL,
|
||||
},
|
||||
/* 2 plane YUV */
|
||||
{ /* NV12 */
|
||||
.n_planes = 2,
|
||||
.bpp = { 1, 2 },
|
||||
.hsub = { 1, 2 },
|
||||
.vsub = { 1, 2 },
|
||||
.subformats = { COGL_PIXEL_FORMAT_G_8, COGL_PIXEL_FORMAT_RG_88 },
|
||||
.rgb_shaderfunc = Y_UV_TO_RGB_FUNC,
|
||||
.rgb_shader = y_uv_to_rgb_shader,
|
||||
},
|
||||
{ /* NV21 */
|
||||
.n_planes = 2,
|
||||
.bpp = { 1, 2 },
|
||||
.hsub = { 1, 2 },
|
||||
.vsub = { 1, 2 },
|
||||
.subformats = { COGL_PIXEL_FORMAT_G_8, COGL_PIXEL_FORMAT_RG_88 },
|
||||
.rgb_shaderfunc = Y_UV_TO_RGB_FUNC,
|
||||
.rgb_shader = y_uv_to_rgb_shader,
|
||||
},
|
||||
{ /* NV16 */
|
||||
.n_planes = 2,
|
||||
.bpp = { 1, 2 },
|
||||
.hsub = { 1, 2 },
|
||||
.vsub = { 1, 1 },
|
||||
.subformats = { COGL_PIXEL_FORMAT_G_8, COGL_PIXEL_FORMAT_RG_88 },
|
||||
.rgb_shaderfunc = Y_UV_TO_RGB_FUNC,
|
||||
.rgb_shader = y_uv_to_rgb_shader,
|
||||
},
|
||||
{ /* NV61 */
|
||||
.n_planes = 2,
|
||||
.bpp = { 1, 2 },
|
||||
.hsub = { 1, 2 },
|
||||
.vsub = { 1, 1 },
|
||||
.subformats = { COGL_PIXEL_FORMAT_G_8, COGL_PIXEL_FORMAT_RG_88 },
|
||||
.rgb_shaderfunc = Y_UV_TO_RGB_FUNC,
|
||||
.rgb_shader = y_uv_to_rgb_shader,
|
||||
},
|
||||
{ /* NV24 */
|
||||
.n_planes = 2,
|
||||
.bpp = { 1, 2 },
|
||||
.hsub = { 1, 1 },
|
||||
.vsub = { 1, 1 },
|
||||
.subformats = { COGL_PIXEL_FORMAT_G_8, COGL_PIXEL_FORMAT_RG_88 },
|
||||
.rgb_shaderfunc = Y_UV_TO_RGB_FUNC,
|
||||
.rgb_shader = y_uv_to_rgb_shader,
|
||||
},
|
||||
{ /* NV42 */
|
||||
.n_planes = 2,
|
||||
.bpp = { 1, 2 },
|
||||
.hsub = { 1, 1 },
|
||||
.vsub = { 1, 1 },
|
||||
.subformats = { COGL_PIXEL_FORMAT_G_8, COGL_PIXEL_FORMAT_RG_88 },
|
||||
.rgb_shaderfunc = Y_UV_TO_RGB_FUNC,
|
||||
.rgb_shader = y_uv_to_rgb_shader,
|
||||
},
|
||||
/* 3 plane YUV */
|
||||
{ /* YUV410 */
|
||||
.n_planes = 3,
|
||||
.bpp = { 1, 1, 1 },
|
||||
.hsub = { 1, 4, 4 },
|
||||
.vsub = { 1, 4, 4 },
|
||||
.subformats = { COGL_PIXEL_FORMAT_G_8, COGL_PIXEL_FORMAT_G_8, COGL_PIXEL_FORMAT_G_8 },
|
||||
.rgb_shaderfunc = Y_U_V_TO_RGB_FUNC,
|
||||
.rgb_shader = y_u_v_to_rgb_shader,
|
||||
},
|
||||
{ /* YVU410 */
|
||||
.n_planes = 3,
|
||||
.bpp = { 1, 1, 1 },
|
||||
.hsub = { 1, 4, 4 },
|
||||
.vsub = { 1, 4, 4 },
|
||||
.subformats = { COGL_PIXEL_FORMAT_G_8, COGL_PIXEL_FORMAT_G_8, COGL_PIXEL_FORMAT_G_8 },
|
||||
.rgb_shaderfunc = Y_U_V_TO_RGB_FUNC,
|
||||
.rgb_shader = y_u_v_to_rgb_shader,
|
||||
},
|
||||
{ /* YUV411 */
|
||||
.n_planes = 3,
|
||||
.bpp = { 1, 1, 1 },
|
||||
.hsub = { 1, 4, 4 },
|
||||
.vsub = { 1, 1, 1 },
|
||||
.subformats = { COGL_PIXEL_FORMAT_G_8, COGL_PIXEL_FORMAT_G_8, COGL_PIXEL_FORMAT_G_8 },
|
||||
.rgb_shaderfunc = Y_U_V_TO_RGB_FUNC,
|
||||
.rgb_shader = y_u_v_to_rgb_shader,
|
||||
},
|
||||
{ /* YVU411 */
|
||||
.n_planes = 3,
|
||||
.bpp = { 1, 1, 1 },
|
||||
.hsub = { 1, 4, 4 },
|
||||
.vsub = { 1, 1, 1 },
|
||||
.subformats = { COGL_PIXEL_FORMAT_G_8, COGL_PIXEL_FORMAT_G_8, COGL_PIXEL_FORMAT_G_8 },
|
||||
.rgb_shaderfunc = Y_U_V_TO_RGB_FUNC,
|
||||
.rgb_shader = y_u_v_to_rgb_shader,
|
||||
},
|
||||
{ /* YUV420 */
|
||||
.n_planes = 3,
|
||||
.bpp = { 1, 1, 1 },
|
||||
.hsub = { 1, 2, 2 },
|
||||
.vsub = { 1, 2, 2 },
|
||||
.subformats = { COGL_PIXEL_FORMAT_G_8, COGL_PIXEL_FORMAT_G_8, COGL_PIXEL_FORMAT_G_8 },
|
||||
.rgb_shaderfunc = Y_U_V_TO_RGB_FUNC,
|
||||
.rgb_shader = y_u_v_to_rgb_shader,
|
||||
},
|
||||
{ /* YVU420 */
|
||||
.n_planes = 3,
|
||||
.bpp = { 1, 1, 1 },
|
||||
.hsub = { 1, 2, 2 },
|
||||
.vsub = { 1, 2, 2 },
|
||||
.subformats = { COGL_PIXEL_FORMAT_G_8, COGL_PIXEL_FORMAT_G_8, COGL_PIXEL_FORMAT_G_8 },
|
||||
.rgb_shaderfunc = Y_U_V_TO_RGB_FUNC,
|
||||
.rgb_shader = y_u_v_to_rgb_shader,
|
||||
},
|
||||
{ /* YUV422 */
|
||||
.n_planes = 3,
|
||||
.bpp = { 1, 1, 1 },
|
||||
.hsub = { 1, 2, 2 },
|
||||
.vsub = { 1, 1, 1 },
|
||||
.subformats = { COGL_PIXEL_FORMAT_G_8, COGL_PIXEL_FORMAT_G_8, COGL_PIXEL_FORMAT_G_8 },
|
||||
.rgb_shaderfunc = Y_U_V_TO_RGB_FUNC,
|
||||
.rgb_shader = y_u_v_to_rgb_shader,
|
||||
},
|
||||
{ /* YVU422 */
|
||||
.n_planes = 3,
|
||||
.bpp = { 1, 1, 1 },
|
||||
.hsub = { 1, 2, 2 },
|
||||
.vsub = { 1, 1, 1 },
|
||||
.subformats = { COGL_PIXEL_FORMAT_G_8, COGL_PIXEL_FORMAT_G_8, COGL_PIXEL_FORMAT_G_8 },
|
||||
.rgb_shaderfunc = Y_U_V_TO_RGB_FUNC,
|
||||
.rgb_shader = y_u_v_to_rgb_shader,
|
||||
},
|
||||
{ /* YUV444 */
|
||||
.n_planes = 3,
|
||||
.bpp = { 1, 1, 1 },
|
||||
.hsub = { 1, 1, 1 },
|
||||
.vsub = { 1, 1, 1 },
|
||||
.subformats = { COGL_PIXEL_FORMAT_G_8, COGL_PIXEL_FORMAT_G_8, COGL_PIXEL_FORMAT_G_8 },
|
||||
.rgb_shaderfunc = Y_U_V_TO_RGB_FUNC,
|
||||
.rgb_shader = y_u_v_to_rgb_shader,
|
||||
},
|
||||
{ /* YVU444 */
|
||||
.n_planes = 3,
|
||||
.bpp = { 1, 1, 1 },
|
||||
.hsub = { 1, 1, 1 },
|
||||
.vsub = { 1, 1, 1 },
|
||||
.subformats = { COGL_PIXEL_FORMAT_G_8, COGL_PIXEL_FORMAT_G_8, COGL_PIXEL_FORMAT_G_8 },
|
||||
.rgb_shaderfunc = Y_U_V_TO_RGB_FUNC,
|
||||
.rgb_shader = y_u_v_to_rgb_shader,
|
||||
},
|
||||
};
|
||||
|
||||
void
|
||||
meta_multi_texture_format_get_bytes_per_pixel (MetaMultiTextureFormat format,
|
||||
uint8_t *bpp_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++)
|
||||
bpp_out[i] = multi_format_table[format].bpp[i];
|
||||
}
|
||||
|
||||
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_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];
|
||||
}
|
||||
}
|
||||
|
||||
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];
|
||||
}
|
||||
|
||||
gboolean
|
||||
meta_multi_texture_format_needs_shaders (MetaMultiTextureFormat format)
|
||||
{
|
||||
g_return_val_if_fail (format < G_N_ELEMENTS (multi_format_table), FALSE);
|
||||
|
||||
return multi_format_table[format].rgb_shaderfunc != NULL;
|
||||
}
|
||||
|
||||
gboolean
|
||||
meta_multi_texture_format_get_snippets (MetaMultiTextureFormat format,
|
||||
CoglSnippet **vertex_snippet,
|
||||
CoglSnippet **fragment_snippet,
|
||||
CoglSnippet **layer_snippet)
|
||||
{
|
||||
const char *shader_func;
|
||||
const char *shader_impl;
|
||||
g_autofree char *layer_hook = NULL;
|
||||
|
||||
g_return_val_if_fail (format < G_N_ELEMENTS (multi_format_table), FALSE);
|
||||
|
||||
/* Get the function name; bail out early if we don't need a shader */
|
||||
shader_func = multi_format_table[format].rgb_shaderfunc;
|
||||
if (shader_func == NULL)
|
||||
return FALSE;
|
||||
|
||||
shader_impl = multi_format_table[format].rgb_shader;
|
||||
|
||||
/* Make sure we actually call the function */
|
||||
layer_hook = g_strdup_printf ("cogl_layer = %s(cogl_tex_coord0_in.st);\n",
|
||||
shader_func);
|
||||
|
||||
if (vertex_snippet)
|
||||
*vertex_snippet = cogl_snippet_new (COGL_SNIPPET_HOOK_VERTEX_GLOBALS,
|
||||
shader_impl,
|
||||
NULL);
|
||||
|
||||
if (fragment_snippet)
|
||||
*fragment_snippet = cogl_snippet_new (COGL_SNIPPET_HOOK_FRAGMENT_GLOBALS,
|
||||
shader_impl,
|
||||
NULL);
|
||||
|
||||
if (layer_snippet)
|
||||
*layer_snippet = cogl_snippet_new (COGL_SNIPPET_HOOK_LAYER_FRAGMENT,
|
||||
NULL,
|
||||
layer_hook);
|
||||
|
||||
return TRUE;
|
||||
}
|
285
src/compositor/meta-multi-texture.c
Normal file
285
src/compositor/meta-multi-texture.c
Normal file
@ -0,0 +1,285 @@
|
||||
/*
|
||||
* 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 "meta/meta-multi-texture.h"
|
||||
#include "meta/meta-enum-types.h"
|
||||
|
||||
struct _MetaMultiTexture
|
||||
{
|
||||
GObject parent_instance;
|
||||
|
||||
MetaMultiTextureFormat format;
|
||||
|
||||
guint n_planes;
|
||||
CoglTexture **planes;
|
||||
};
|
||||
|
||||
G_DEFINE_TYPE (MetaMultiTexture, meta_multi_texture, G_TYPE_OBJECT);
|
||||
|
||||
/**
|
||||
* meta_multi_texture_get_format:
|
||||
* @self: 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 *self)
|
||||
{
|
||||
g_return_val_if_fail (META_IS_MULTI_TEXTURE (self), META_MULTI_TEXTURE_FORMAT_SIMPLE);
|
||||
|
||||
return self->format;
|
||||
}
|
||||
|
||||
/**
|
||||
* meta_multi_texture_is_simple:
|
||||
* @self: 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 *self)
|
||||
{
|
||||
g_return_val_if_fail (META_IS_MULTI_TEXTURE (self), FALSE);
|
||||
|
||||
return self->format == META_MULTI_TEXTURE_FORMAT_SIMPLE;
|
||||
}
|
||||
|
||||
/**
|
||||
* meta_multi_texture_get_n_planes:
|
||||
* @self: 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.
|
||||
*/
|
||||
guint
|
||||
meta_multi_texture_get_n_planes (MetaMultiTexture *self)
|
||||
{
|
||||
g_return_val_if_fail (META_IS_MULTI_TEXTURE (self), 0);
|
||||
|
||||
return self->n_planes;
|
||||
}
|
||||
|
||||
/**
|
||||
* meta_multi_texture_get_plane:
|
||||
* @self: 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 *self, guint index)
|
||||
{
|
||||
g_return_val_if_fail (META_IS_MULTI_TEXTURE (self), 0);
|
||||
g_return_val_if_fail (index < self->n_planes, NULL);
|
||||
|
||||
return self->planes[index];
|
||||
}
|
||||
|
||||
/**
|
||||
* meta_multi_texture_get_width:
|
||||
* @self: 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 *self)
|
||||
{
|
||||
g_return_val_if_fail (META_IS_MULTI_TEXTURE (self), 0);
|
||||
|
||||
return cogl_texture_get_width (self->planes[0]);
|
||||
}
|
||||
|
||||
/**
|
||||
* meta_multi_texture_get_height:
|
||||
* @self: 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 *self)
|
||||
{
|
||||
g_return_val_if_fail (META_IS_MULTI_TEXTURE (self), 0);
|
||||
|
||||
return cogl_texture_get_height (self->planes[0]);
|
||||
}
|
||||
|
||||
static void
|
||||
meta_multi_texture_finalize (GObject *object)
|
||||
{
|
||||
MetaMultiTexture *self = META_MULTI_TEXTURE (object);
|
||||
int i;
|
||||
|
||||
for (i = 0; i < self->n_planes; i++)
|
||||
cogl_clear_object (&self->planes[i]);
|
||||
|
||||
g_free (self->planes);
|
||||
|
||||
G_OBJECT_CLASS (meta_multi_texture_parent_class)->finalize (object);
|
||||
}
|
||||
|
||||
static void
|
||||
meta_multi_texture_init (MetaMultiTexture *self)
|
||||
{
|
||||
}
|
||||
|
||||
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,
|
||||
guint n_planes)
|
||||
{
|
||||
MetaMultiTexture *self;
|
||||
|
||||
g_return_val_if_fail (planes != NULL, NULL);
|
||||
g_return_val_if_fail (n_planes > 0, NULL);
|
||||
|
||||
self = g_object_new (META_TYPE_MULTI_TEXTURE, NULL);
|
||||
self->format = format;
|
||||
self->n_planes = n_planes;
|
||||
self->planes = planes;
|
||||
|
||||
return self;
|
||||
}
|
||||
|
||||
/**
|
||||
* 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 *self;
|
||||
|
||||
g_return_val_if_fail (plane != NULL, NULL);
|
||||
|
||||
self = g_object_new (META_TYPE_MULTI_TEXTURE, NULL);
|
||||
self->format = META_MULTI_TEXTURE_FORMAT_SIMPLE;
|
||||
self->n_planes = 1;
|
||||
self->planes = g_malloc (sizeof (CoglTexture *));
|
||||
self->planes[0] = plane;
|
||||
|
||||
return self;
|
||||
}
|
||||
|
||||
/**
|
||||
* meta_multi_texture_to_string:
|
||||
* @self: a #MetaMultiTexture
|
||||
*
|
||||
* 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 *
|
||||
meta_multi_texture_to_string (MetaMultiTexture *self)
|
||||
{
|
||||
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", self);
|
||||
format_str = g_enum_to_string (META_TYPE_MULTI_TEXTURE_FORMAT, self->format);
|
||||
g_string_append_printf (str, " .format = %s;\n", format_str);
|
||||
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];
|
||||
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);
|
||||
}
|
@ -32,7 +32,7 @@
|
||||
|
||||
MetaShapedTexture *meta_shaped_texture_new (void);
|
||||
void meta_shaped_texture_set_texture (MetaShapedTexture *stex,
|
||||
CoglTexture *texture);
|
||||
MetaMultiTexture *multi_texture);
|
||||
void meta_shaped_texture_set_is_y_inverted (MetaShapedTexture *stex,
|
||||
gboolean is_y_inverted);
|
||||
void meta_shaped_texture_set_snippet (MetaShapedTexture *stex,
|
||||
|
@ -74,7 +74,7 @@ struct _MetaShapedTexture
|
||||
|
||||
MetaTextureTower *paint_tower;
|
||||
|
||||
CoglTexture *texture;
|
||||
MetaMultiTexture *texture;
|
||||
CoglTexture *mask_texture;
|
||||
CoglSnippet *snippet;
|
||||
|
||||
@ -249,24 +249,31 @@ static CoglPipeline *
|
||||
get_base_pipeline (MetaShapedTexture *stex,
|
||||
CoglContext *ctx)
|
||||
{
|
||||
guint i, n_planes;
|
||||
MetaMultiTextureFormat format;
|
||||
CoglPipeline *pipeline;
|
||||
CoglMatrix matrix;
|
||||
|
||||
if (stex->base_pipeline)
|
||||
return stex->base_pipeline;
|
||||
|
||||
/* We'll add as many layers as there are planes in the multi texture,
|
||||
* plus an extra one for the mask */
|
||||
n_planes = meta_multi_texture_get_n_planes (stex->texture);
|
||||
|
||||
pipeline = cogl_pipeline_new (ctx);
|
||||
cogl_pipeline_set_layer_wrap_mode_s (pipeline, 0,
|
||||
COGL_PIPELINE_WRAP_MODE_CLAMP_TO_EDGE);
|
||||
cogl_pipeline_set_layer_wrap_mode_t (pipeline, 0,
|
||||
COGL_PIPELINE_WRAP_MODE_CLAMP_TO_EDGE);
|
||||
cogl_pipeline_set_layer_wrap_mode_s (pipeline, 1,
|
||||
COGL_PIPELINE_WRAP_MODE_CLAMP_TO_EDGE);
|
||||
cogl_pipeline_set_layer_wrap_mode_t (pipeline, 1,
|
||||
COGL_PIPELINE_WRAP_MODE_CLAMP_TO_EDGE);
|
||||
|
||||
for (i = 0; i < n_planes; i++)
|
||||
{
|
||||
cogl_pipeline_set_layer_wrap_mode_s (pipeline, i,
|
||||
COGL_PIPELINE_WRAP_MODE_CLAMP_TO_EDGE);
|
||||
cogl_pipeline_set_layer_wrap_mode_t (pipeline, i,
|
||||
COGL_PIPELINE_WRAP_MODE_CLAMP_TO_EDGE);
|
||||
}
|
||||
|
||||
cogl_matrix_init_identity (&matrix);
|
||||
|
||||
/* Apply Y-inversion if necessary */
|
||||
if (!stex->is_y_inverted)
|
||||
{
|
||||
cogl_matrix_scale (&matrix, 1, -1, 1);
|
||||
@ -274,6 +281,7 @@ get_base_pipeline (MetaShapedTexture *stex,
|
||||
cogl_pipeline_set_layer_matrix (pipeline, 0, &matrix);
|
||||
}
|
||||
|
||||
/* Apply transformation if needed */
|
||||
if (stex->transform != META_MONITOR_TRANSFORM_NORMAL)
|
||||
{
|
||||
graphene_euler_t euler;
|
||||
@ -316,6 +324,7 @@ get_base_pipeline (MetaShapedTexture *stex,
|
||||
cogl_matrix_translate (&matrix, -0.5, -0.5, 0.0);
|
||||
}
|
||||
|
||||
/* Apply viewport scaling if neeed */
|
||||
if (stex->has_viewport_src_rect)
|
||||
{
|
||||
float scaled_tex_width = stex->tex_width / (float) stex->buffer_scale;
|
||||
@ -348,9 +357,29 @@ get_base_pipeline (MetaShapedTexture *stex,
|
||||
0);
|
||||
}
|
||||
|
||||
cogl_pipeline_set_layer_matrix (pipeline, 0, &matrix);
|
||||
cogl_pipeline_set_layer_matrix (pipeline, 1, &matrix);
|
||||
for (i = 0; i < n_planes + 1; i++)
|
||||
cogl_pipeline_set_layer_matrix (pipeline, i, &matrix);
|
||||
|
||||
/* Add color conversion shaders if needed */
|
||||
format = meta_multi_texture_get_format (stex->texture);
|
||||
if (meta_multi_texture_format_needs_shaders (format))
|
||||
{
|
||||
CoglSnippet *vertex_snippet;
|
||||
CoglSnippet *fragment_snippet;
|
||||
CoglSnippet *layer_snippet;
|
||||
|
||||
meta_multi_texture_format_get_snippets (format,
|
||||
&vertex_snippet,
|
||||
&fragment_snippet,
|
||||
&layer_snippet);
|
||||
cogl_pipeline_add_snippet (pipeline, vertex_snippet);
|
||||
cogl_pipeline_add_snippet (pipeline, fragment_snippet);
|
||||
|
||||
for (i = 0; i < n_planes; i++)
|
||||
cogl_pipeline_add_layer_snippet (pipeline, i, layer_snippet);
|
||||
}
|
||||
|
||||
/* And custom external shaders (e.g. for EGLStreams) */
|
||||
if (stex->snippet)
|
||||
cogl_pipeline_add_layer_snippet (pipeline, 0, stex->snippet);
|
||||
|
||||
@ -371,12 +400,14 @@ get_masked_pipeline (MetaShapedTexture *stex,
|
||||
CoglContext *ctx)
|
||||
{
|
||||
CoglPipeline *pipeline;
|
||||
guint n_planes;
|
||||
|
||||
if (stex->masked_pipeline)
|
||||
return stex->masked_pipeline;
|
||||
|
||||
pipeline = cogl_pipeline_copy (get_base_pipeline (stex, ctx));
|
||||
cogl_pipeline_set_layer_combine (pipeline, 1,
|
||||
n_planes = meta_multi_texture_get_n_planes (stex->texture);
|
||||
cogl_pipeline_set_layer_combine (pipeline, n_planes,
|
||||
"RGBA = MODULATE (PREVIOUS, TEXTURE[A])",
|
||||
NULL);
|
||||
|
||||
@ -457,18 +488,18 @@ paint_clipped_rectangle_node (MetaShapedTexture *stex,
|
||||
}
|
||||
|
||||
static void
|
||||
set_cogl_texture (MetaShapedTexture *stex,
|
||||
CoglTexture *cogl_tex)
|
||||
set_multi_texture (MetaShapedTexture *stex,
|
||||
MetaMultiTexture *multi_tex)
|
||||
{
|
||||
int width, height;
|
||||
|
||||
cogl_clear_object (&stex->texture);
|
||||
g_clear_object (&stex->texture);
|
||||
|
||||
if (cogl_tex != NULL)
|
||||
if (multi_tex != NULL)
|
||||
{
|
||||
stex->texture = cogl_object_ref (cogl_tex);
|
||||
width = cogl_texture_get_width (COGL_TEXTURE (cogl_tex));
|
||||
height = cogl_texture_get_height (COGL_TEXTURE (cogl_tex));
|
||||
stex->texture = g_object_ref (multi_tex);
|
||||
width = meta_multi_texture_get_width (multi_tex);
|
||||
height = meta_multi_texture_get_height (multi_tex);
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -490,7 +521,7 @@ set_cogl_texture (MetaShapedTexture *stex,
|
||||
* damage. */
|
||||
|
||||
if (stex->create_mipmaps)
|
||||
meta_texture_tower_set_base_texture (stex->paint_tower, cogl_tex);
|
||||
meta_texture_tower_set_base_texture (stex->paint_tower, multi_tex);
|
||||
}
|
||||
|
||||
static gboolean
|
||||
@ -522,7 +553,7 @@ static void
|
||||
do_paint_content (MetaShapedTexture *stex,
|
||||
ClutterPaintNode *root_node,
|
||||
ClutterPaintContext *paint_context,
|
||||
CoglTexture *paint_tex,
|
||||
MetaMultiTexture *paint_tex,
|
||||
ClutterActorBox *alloc,
|
||||
uint8_t opacity)
|
||||
{
|
||||
@ -534,6 +565,7 @@ do_paint_content (MetaShapedTexture *stex,
|
||||
CoglPipelineFilter filter;
|
||||
CoglFramebuffer *framebuffer;
|
||||
int sample_width, sample_height;
|
||||
guint n_planes;
|
||||
|
||||
ensure_size_valid (stex);
|
||||
|
||||
@ -609,6 +641,8 @@ do_paint_content (MetaShapedTexture *stex,
|
||||
}
|
||||
}
|
||||
|
||||
n_planes = meta_multi_texture_get_n_planes (paint_tex);
|
||||
|
||||
/* First, paint the unblended parts, which are part of the opaque region. */
|
||||
if (use_opaque_region)
|
||||
{
|
||||
@ -620,8 +654,14 @@ do_paint_content (MetaShapedTexture *stex,
|
||||
CoglPipeline *opaque_pipeline;
|
||||
|
||||
opaque_pipeline = get_unblended_pipeline (stex, ctx);
|
||||
cogl_pipeline_set_layer_texture (opaque_pipeline, 0, paint_tex);
|
||||
cogl_pipeline_set_layer_filters (opaque_pipeline, 0, filter, filter);
|
||||
|
||||
for (i = 0; i < n_planes; i++)
|
||||
{
|
||||
CoglTexture *plane = meta_multi_texture_get_plane (paint_tex, i);
|
||||
|
||||
cogl_pipeline_set_layer_texture (opaque_pipeline, i, plane);
|
||||
cogl_pipeline_set_layer_filters (opaque_pipeline, i, filter, filter);
|
||||
}
|
||||
|
||||
n_rects = cairo_region_num_rectangles (stex->opaque_region);
|
||||
for (i = 0; i < n_rects; i++)
|
||||
@ -648,6 +688,7 @@ do_paint_content (MetaShapedTexture *stex,
|
||||
if (!blended_tex_region || !cairo_region_is_empty (blended_tex_region))
|
||||
{
|
||||
CoglPipeline *blended_pipeline;
|
||||
guint i;
|
||||
|
||||
if (stex->mask_texture == NULL)
|
||||
{
|
||||
@ -656,16 +697,20 @@ do_paint_content (MetaShapedTexture *stex,
|
||||
else
|
||||
{
|
||||
blended_pipeline = get_masked_pipeline (stex, ctx);
|
||||
cogl_pipeline_set_layer_texture (blended_pipeline, 1, stex->mask_texture);
|
||||
cogl_pipeline_set_layer_filters (blended_pipeline, 1, filter, filter);
|
||||
cogl_pipeline_set_layer_texture (blended_pipeline, n_planes, stex->mask_texture);
|
||||
cogl_pipeline_set_layer_filters (blended_pipeline, n_planes, filter, filter);
|
||||
}
|
||||
|
||||
cogl_pipeline_set_layer_texture (blended_pipeline, 0, paint_tex);
|
||||
cogl_pipeline_set_layer_filters (blended_pipeline, 0, filter, filter);
|
||||
for (i = 0; i < n_planes; i++)
|
||||
{
|
||||
CoglTexture *plane = meta_multi_texture_get_plane (paint_tex, i);
|
||||
|
||||
CoglColor color;
|
||||
cogl_color_init_from_4ub (&color, opacity, opacity, opacity, opacity);
|
||||
cogl_pipeline_set_color (blended_pipeline, &color);
|
||||
cogl_pipeline_set_layer_texture (blended_pipeline, i, plane);
|
||||
cogl_pipeline_set_layer_filters (blended_pipeline, i, filter, filter);
|
||||
}
|
||||
|
||||
cogl_pipeline_set_color4ub (blended_pipeline,
|
||||
opacity, opacity, opacity, opacity);
|
||||
|
||||
if (blended_tex_region)
|
||||
{
|
||||
@ -702,11 +747,11 @@ do_paint_content (MetaShapedTexture *stex,
|
||||
g_clear_pointer (&blended_tex_region, cairo_region_destroy);
|
||||
}
|
||||
|
||||
static CoglTexture *
|
||||
select_texture_for_paint (MetaShapedTexture *stex,
|
||||
static MetaMultiTexture *
|
||||
select_texture_for_paint (MetaShapedTexture *stex,
|
||||
ClutterPaintContext *paint_context)
|
||||
{
|
||||
CoglTexture *texture = NULL;
|
||||
MetaMultiTexture *texture = NULL;
|
||||
int64_t now;
|
||||
|
||||
if (!stex->texture)
|
||||
@ -754,7 +799,7 @@ meta_shaped_texture_paint_content (ClutterContent *content,
|
||||
{
|
||||
MetaShapedTexture *stex = META_SHAPED_TEXTURE (content);
|
||||
ClutterActorBox alloc;
|
||||
CoglTexture *paint_tex = NULL;
|
||||
MetaMultiTexture *paint_tex = NULL;
|
||||
uint8_t opacity;
|
||||
|
||||
/* The GL EXT_texture_from_pixmap extension does allow for it to be
|
||||
@ -817,7 +862,7 @@ meta_shaped_texture_set_create_mipmaps (MetaShapedTexture *stex,
|
||||
|
||||
if (create_mipmaps != stex->create_mipmaps)
|
||||
{
|
||||
CoglTexture *base_texture;
|
||||
MetaMultiTexture *base_texture;
|
||||
stex->create_mipmaps = create_mipmaps;
|
||||
base_texture = create_mipmaps ? stex->texture : NULL;
|
||||
meta_texture_tower_set_base_texture (stex->paint_tower, base_texture);
|
||||
@ -964,18 +1009,18 @@ meta_shaped_texture_update_area (MetaShapedTexture *stex,
|
||||
/**
|
||||
* meta_shaped_texture_set_texture:
|
||||
* @stex: The #MetaShapedTexture
|
||||
* @pixmap: The #CoglTexture to display
|
||||
* @pixmap: The #MetaMultiTexture to display
|
||||
*/
|
||||
void
|
||||
meta_shaped_texture_set_texture (MetaShapedTexture *stex,
|
||||
CoglTexture *texture)
|
||||
MetaMultiTexture *texture)
|
||||
{
|
||||
g_return_if_fail (META_IS_SHAPED_TEXTURE (stex));
|
||||
|
||||
if (stex->texture == texture)
|
||||
return;
|
||||
|
||||
set_cogl_texture (stex, texture);
|
||||
set_multi_texture (stex, texture);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -1016,11 +1061,11 @@ meta_shaped_texture_set_snippet (MetaShapedTexture *stex,
|
||||
*
|
||||
* Returns: (transfer none): the unshaped texture
|
||||
*/
|
||||
CoglTexture *
|
||||
MetaMultiTexture *
|
||||
meta_shaped_texture_get_texture (MetaShapedTexture *stex)
|
||||
{
|
||||
g_return_val_if_fail (META_IS_SHAPED_TEXTURE (stex), NULL);
|
||||
return COGL_TEXTURE (stex->texture);
|
||||
return stex->texture;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -1058,13 +1103,19 @@ meta_shaped_texture_get_opaque_region (MetaShapedTexture *stex)
|
||||
gboolean
|
||||
meta_shaped_texture_has_alpha (MetaShapedTexture *stex)
|
||||
{
|
||||
CoglTexture *texture;
|
||||
MetaMultiTexture *multi_texture;
|
||||
CoglTexture *cogl_texture;
|
||||
|
||||
texture = stex->texture;
|
||||
if (!texture)
|
||||
multi_texture = stex->texture;
|
||||
if (!multi_texture)
|
||||
return TRUE;
|
||||
|
||||
switch (cogl_texture_get_components (texture))
|
||||
/* FIXME: for now we don't support alpha (except simple textures) */
|
||||
if (meta_multi_texture_get_n_planes (multi_texture) > 1)
|
||||
return FALSE;
|
||||
|
||||
cogl_texture = meta_multi_texture_get_plane (multi_texture, 0);
|
||||
switch (cogl_texture_get_components (cogl_texture))
|
||||
{
|
||||
case COGL_TEXTURE_COMPONENTS_A:
|
||||
case COGL_TEXTURE_COMPONENTS_RGBA:
|
||||
@ -1082,12 +1133,12 @@ meta_shaped_texture_has_alpha (MetaShapedTexture *stex)
|
||||
gboolean
|
||||
meta_shaped_texture_is_opaque (MetaShapedTexture *stex)
|
||||
{
|
||||
CoglTexture *texture;
|
||||
MetaMultiTexture *multi_texture;
|
||||
cairo_rectangle_int_t opaque_rect;
|
||||
|
||||
texture = stex->texture;
|
||||
if (!texture)
|
||||
return FALSE;
|
||||
multi_texture = stex->texture;
|
||||
if (!multi_texture)
|
||||
return TRUE;
|
||||
|
||||
if (!meta_shaped_texture_has_alpha (stex))
|
||||
return TRUE;
|
||||
@ -1179,7 +1230,13 @@ meta_shaped_texture_reset_viewport_dst_size (MetaShapedTexture *stex)
|
||||
static gboolean
|
||||
should_get_via_offscreen (MetaShapedTexture *stex)
|
||||
{
|
||||
if (!cogl_texture_is_get_data_supported (stex->texture))
|
||||
CoglTexture *cogl_texture;
|
||||
|
||||
if (meta_multi_texture_get_n_planes (stex->texture) > 1)
|
||||
return FALSE;
|
||||
|
||||
cogl_texture = meta_multi_texture_get_plane (stex->texture, 0);
|
||||
if (!cogl_texture_is_get_data_supported (cogl_texture))
|
||||
return TRUE;
|
||||
|
||||
if (stex->has_viewport_src_rect || stex->has_viewport_dst_size)
|
||||
@ -1322,9 +1379,7 @@ meta_shaped_texture_get_image (MetaShapedTexture *stex,
|
||||
|
||||
g_return_val_if_fail (META_IS_SHAPED_TEXTURE (stex), NULL);
|
||||
|
||||
texture = COGL_TEXTURE (stex->texture);
|
||||
|
||||
if (texture == NULL)
|
||||
if (stex->texture == NULL)
|
||||
return NULL;
|
||||
|
||||
ensure_size_valid (stex);
|
||||
@ -1367,6 +1422,9 @@ meta_shaped_texture_get_image (MetaShapedTexture *stex,
|
||||
image_height);
|
||||
}
|
||||
|
||||
/* We know that we only have 1 plane at this point */
|
||||
texture = meta_multi_texture_get_plane (stex->texture, 0);
|
||||
|
||||
if (image_clip)
|
||||
texture = cogl_texture_new_from_sub_texture (texture,
|
||||
image_clip->x,
|
||||
|
@ -46,7 +46,7 @@ struct _MetaSurfaceActorX11
|
||||
|
||||
MetaDisplay *display;
|
||||
|
||||
CoglTexture *texture;
|
||||
MetaMultiTexture *texture;
|
||||
Pixmap pixmap;
|
||||
Damage damage;
|
||||
|
||||
@ -109,7 +109,7 @@ detach_pixmap (MetaSurfaceActorX11 *self)
|
||||
self->pixmap = None;
|
||||
meta_x11_error_trap_pop (display->x11_display);
|
||||
|
||||
g_clear_pointer (&self->texture, cogl_object_unref);
|
||||
g_clear_object (&self->texture);
|
||||
}
|
||||
|
||||
static void
|
||||
@ -119,23 +119,23 @@ set_pixmap (MetaSurfaceActorX11 *self,
|
||||
CoglContext *ctx = clutter_backend_get_cogl_context (clutter_get_default_backend ());
|
||||
MetaShapedTexture *stex = meta_surface_actor_get_texture (META_SURFACE_ACTOR (self));
|
||||
GError *error = NULL;
|
||||
CoglTexture *texture;
|
||||
CoglTexture *cogl_texture;
|
||||
|
||||
g_assert (self->pixmap == None);
|
||||
self->pixmap = pixmap;
|
||||
|
||||
texture = COGL_TEXTURE (cogl_texture_pixmap_x11_new (ctx, self->pixmap, FALSE, &error));
|
||||
cogl_texture = COGL_TEXTURE (cogl_texture_pixmap_x11_new (ctx, self->pixmap, FALSE, &error));
|
||||
|
||||
if (error != NULL)
|
||||
{
|
||||
g_warning ("Failed to allocate stex texture: %s", error->message);
|
||||
g_error_free (error);
|
||||
}
|
||||
else if (G_UNLIKELY (!cogl_texture_pixmap_x11_is_using_tfp_extension (COGL_TEXTURE_PIXMAP_X11 (texture))))
|
||||
else if (G_UNLIKELY (!cogl_texture_pixmap_x11_is_using_tfp_extension (COGL_TEXTURE_PIXMAP_X11 (cogl_texture))))
|
||||
g_warning ("NOTE: Not using GLX TFP!\n");
|
||||
|
||||
self->texture = texture;
|
||||
meta_shaped_texture_set_texture (stex, texture);
|
||||
self->texture = meta_multi_texture_new_simple (cogl_texture);
|
||||
meta_shaped_texture_set_texture (stex, self->texture);
|
||||
}
|
||||
|
||||
static void
|
||||
@ -192,6 +192,7 @@ meta_surface_actor_x11_process_damage (MetaSurfaceActor *actor,
|
||||
int x, int y, int width, int height)
|
||||
{
|
||||
MetaSurfaceActorX11 *self = META_SURFACE_ACTOR_X11 (actor);
|
||||
CoglTexturePixmapX11 *pixmap;
|
||||
|
||||
self->received_damage = TRUE;
|
||||
|
||||
@ -215,8 +216,12 @@ meta_surface_actor_x11_process_damage (MetaSurfaceActor *actor,
|
||||
if (!is_visible (self))
|
||||
return;
|
||||
|
||||
cogl_texture_pixmap_x11_update_area (COGL_TEXTURE_PIXMAP_X11 (self->texture),
|
||||
x, y, width, height);
|
||||
/* We don't support multi-plane or YUV based formats here */
|
||||
if (!meta_multi_texture_is_simple (self->texture))
|
||||
return;
|
||||
|
||||
pixmap = COGL_TEXTURE_PIXMAP_X11 (meta_multi_texture_get_plane (self->texture, 0));
|
||||
cogl_texture_pixmap_x11_update_area (pixmap, x, y, width, height);
|
||||
}
|
||||
|
||||
static void
|
||||
|
@ -58,8 +58,8 @@ typedef struct
|
||||
struct _MetaTextureTower
|
||||
{
|
||||
int n_levels;
|
||||
CoglTexture *textures[MAX_TEXTURE_LEVELS];
|
||||
CoglOffscreen *fbos[MAX_TEXTURE_LEVELS];
|
||||
MetaMultiTexture *textures[MAX_TEXTURE_LEVELS];
|
||||
GList *fbos[MAX_TEXTURE_LEVELS];
|
||||
Box invalid[MAX_TEXTURE_LEVELS];
|
||||
CoglPipeline *pipeline_template;
|
||||
};
|
||||
@ -113,7 +113,7 @@ meta_texture_tower_free (MetaTextureTower *tower)
|
||||
*/
|
||||
void
|
||||
meta_texture_tower_set_base_texture (MetaTextureTower *tower,
|
||||
CoglTexture *texture)
|
||||
MetaMultiTexture *texture)
|
||||
{
|
||||
int i;
|
||||
|
||||
@ -126,20 +126,12 @@ meta_texture_tower_set_base_texture (MetaTextureTower *tower,
|
||||
{
|
||||
for (i = 1; i < tower->n_levels; i++)
|
||||
{
|
||||
if (tower->textures[i] != NULL)
|
||||
{
|
||||
cogl_object_unref (tower->textures[i]);
|
||||
tower->textures[i] = NULL;
|
||||
}
|
||||
|
||||
if (tower->fbos[i] != NULL)
|
||||
{
|
||||
cogl_object_unref (tower->fbos[i]);
|
||||
tower->fbos[i] = NULL;
|
||||
}
|
||||
g_clear_object (&tower->textures[i]);
|
||||
g_list_free_full (tower->fbos[i], cogl_object_unref);
|
||||
tower->fbos[i] = NULL;
|
||||
}
|
||||
|
||||
cogl_object_unref (tower->textures[0]);
|
||||
g_object_unref (tower->textures[0]);
|
||||
}
|
||||
|
||||
tower->textures[0] = texture;
|
||||
@ -148,10 +140,10 @@ meta_texture_tower_set_base_texture (MetaTextureTower *tower,
|
||||
{
|
||||
int width, height;
|
||||
|
||||
cogl_object_ref (tower->textures[0]);
|
||||
g_object_ref (tower->textures[0]);
|
||||
|
||||
width = cogl_texture_get_width (tower->textures[0]);
|
||||
height = cogl_texture_get_height (tower->textures[0]);
|
||||
width = meta_multi_texture_get_width (tower->textures[0]);
|
||||
height = meta_multi_texture_get_height (tower->textures[0]);
|
||||
|
||||
tower->n_levels = 1 + MAX ((int)(M_LOG2E * log (width)), (int)(M_LOG2E * log (height)));
|
||||
tower->n_levels = MIN(tower->n_levels, MAX_TEXTURE_LEVELS);
|
||||
@ -192,8 +184,8 @@ meta_texture_tower_update_area (MetaTextureTower *tower,
|
||||
if (tower->textures[0] == NULL)
|
||||
return;
|
||||
|
||||
texture_width = cogl_texture_get_width (tower->textures[0]);
|
||||
texture_height = cogl_texture_get_height (tower->textures[0]);
|
||||
texture_width = meta_multi_texture_get_width (tower->textures[0]);
|
||||
texture_height = meta_multi_texture_get_height (tower->textures[0]);
|
||||
|
||||
invalid.x1 = x;
|
||||
invalid.y1 = y;
|
||||
@ -355,9 +347,26 @@ texture_tower_create_texture (MetaTextureTower *tower,
|
||||
int width,
|
||||
int height)
|
||||
{
|
||||
tower->textures[level] = cogl_texture_new_with_size (width, height,
|
||||
COGL_TEXTURE_NO_AUTO_MIPMAP,
|
||||
TEXTURE_FORMAT);
|
||||
MetaMultiTextureFormat format;
|
||||
guint i, n_planes;
|
||||
GPtrArray *planes;
|
||||
CoglTexture **textures;
|
||||
|
||||
format = meta_multi_texture_get_format (tower->textures[0]);
|
||||
n_planes = meta_multi_texture_format_get_n_planes (format);
|
||||
planes = g_ptr_array_new_full (n_planes, g_object_unref);
|
||||
for (i = 0; i < n_planes; i++)
|
||||
{
|
||||
CoglTexture *texture;
|
||||
|
||||
texture = cogl_texture_new_with_size (width, height,
|
||||
COGL_TEXTURE_NO_AUTO_MIPMAP,
|
||||
TEXTURE_FORMAT);
|
||||
g_ptr_array_add (planes, texture);
|
||||
}
|
||||
|
||||
textures = (CoglTexture **) g_ptr_array_free (planes, FALSE);
|
||||
tower->textures[level] = meta_multi_texture_new (format, textures, n_planes);
|
||||
|
||||
tower->invalid[level].x1 = 0;
|
||||
tower->invalid[level].y1 = 0;
|
||||
@ -369,51 +378,69 @@ static void
|
||||
texture_tower_revalidate (MetaTextureTower *tower,
|
||||
int level)
|
||||
{
|
||||
CoglTexture *source_texture = tower->textures[level - 1];
|
||||
int source_texture_width = cogl_texture_get_width (source_texture);
|
||||
int source_texture_height = cogl_texture_get_height (source_texture);
|
||||
CoglTexture *dest_texture = tower->textures[level];
|
||||
int dest_texture_width = cogl_texture_get_width (dest_texture);
|
||||
int dest_texture_height = cogl_texture_get_height (dest_texture);
|
||||
MetaMultiTexture *src_tex = tower->textures[level - 1];
|
||||
int src_width = meta_multi_texture_get_width (src_tex);
|
||||
int src_height = meta_multi_texture_get_height (src_tex);
|
||||
guint src_n_planes = meta_multi_texture_get_n_planes (src_tex);
|
||||
MetaMultiTexture *dest_tex = tower->textures[level];
|
||||
int dest_width = meta_multi_texture_get_width (dest_tex);
|
||||
int dest_height = meta_multi_texture_get_height (dest_tex);
|
||||
Box *invalid = &tower->invalid[level];
|
||||
CoglFramebuffer *fb;
|
||||
GError *catch_error = NULL;
|
||||
CoglPipeline *pipeline;
|
||||
guint i;
|
||||
|
||||
if (tower->fbos[level] == NULL)
|
||||
tower->fbos[level] = cogl_offscreen_new_with_texture (dest_texture);
|
||||
|
||||
fb = COGL_FRAMEBUFFER (tower->fbos[level]);
|
||||
|
||||
if (!cogl_framebuffer_allocate (fb, &catch_error))
|
||||
/* FIXME: cogl_offscreen_texture_new_with_texture doesn't work for
|
||||
* multi-plane textures, so we have to make an FBO for each layer */
|
||||
for (i = 0; i < src_n_planes; i++)
|
||||
{
|
||||
g_error_free (catch_error);
|
||||
return;
|
||||
Box *invalid = &tower->invalid[level];
|
||||
CoglTexture *src_plane, *dest_plane;
|
||||
CoglFramebuffer *fb;
|
||||
GError *catch_error = NULL;
|
||||
CoglPipeline *pipeline;
|
||||
|
||||
src_plane = meta_multi_texture_get_plane (src_tex, i);
|
||||
dest_plane = meta_multi_texture_get_plane (dest_tex, i);
|
||||
|
||||
if (g_list_nth (tower->fbos[level], i) != NULL)
|
||||
{
|
||||
fb = COGL_FRAMEBUFFER (g_list_nth (tower->fbos[level], i)->data);
|
||||
}
|
||||
else
|
||||
{
|
||||
fb = COGL_FRAMEBUFFER (cogl_offscreen_new_with_texture (dest_plane));
|
||||
tower->fbos[level] = g_list_append (tower->fbos[level], fb);
|
||||
}
|
||||
|
||||
if (!cogl_framebuffer_allocate (fb, &catch_error))
|
||||
{
|
||||
g_error_free (catch_error);
|
||||
return;
|
||||
}
|
||||
|
||||
cogl_framebuffer_orthographic (fb, 0, 0, dest_width, dest_height, -1., 1.);
|
||||
|
||||
if (!tower->pipeline_template)
|
||||
{
|
||||
CoglContext *ctx =
|
||||
clutter_backend_get_cogl_context (clutter_get_default_backend ());
|
||||
tower->pipeline_template = cogl_pipeline_new (ctx);
|
||||
cogl_pipeline_set_blend (tower->pipeline_template, "RGBA = ADD (SRC_COLOR, 0)", NULL);
|
||||
}
|
||||
|
||||
pipeline = cogl_pipeline_copy (tower->pipeline_template);
|
||||
cogl_pipeline_set_layer_texture (pipeline, 0, src_plane);
|
||||
|
||||
cogl_framebuffer_draw_textured_rectangle (fb, pipeline,
|
||||
invalid->x1, invalid->y1,
|
||||
invalid->x2, invalid->y2,
|
||||
(2. * invalid->x1) / src_width,
|
||||
(2. * invalid->y1) / src_height,
|
||||
(2. * invalid->x2) / src_width,
|
||||
(2. * invalid->y2) / src_height);
|
||||
|
||||
cogl_object_unref (pipeline);
|
||||
}
|
||||
|
||||
cogl_framebuffer_orthographic (fb, 0, 0, dest_texture_width, dest_texture_height, -1., 1.);
|
||||
|
||||
if (!tower->pipeline_template)
|
||||
{
|
||||
CoglContext *ctx =
|
||||
clutter_backend_get_cogl_context (clutter_get_default_backend ());
|
||||
tower->pipeline_template = cogl_pipeline_new (ctx);
|
||||
cogl_pipeline_set_blend (tower->pipeline_template, "RGBA = ADD (SRC_COLOR, 0)", NULL);
|
||||
}
|
||||
|
||||
pipeline = cogl_pipeline_copy (tower->pipeline_template);
|
||||
cogl_pipeline_set_layer_texture (pipeline, 0, tower->textures[level - 1]);
|
||||
|
||||
cogl_framebuffer_draw_textured_rectangle (fb, pipeline,
|
||||
invalid->x1, invalid->y1,
|
||||
invalid->x2, invalid->y2,
|
||||
(2. * invalid->x1) / source_texture_width,
|
||||
(2. * invalid->y1) / source_texture_height,
|
||||
(2. * invalid->x2) / source_texture_width,
|
||||
(2. * invalid->y2) / source_texture_height);
|
||||
|
||||
cogl_object_unref (pipeline);
|
||||
|
||||
tower->invalid[level].x1 = tower->invalid[level].x2 = 0;
|
||||
tower->invalid[level].y1 = tower->invalid[level].y2 = 0;
|
||||
}
|
||||
@ -432,8 +459,8 @@ texture_tower_revalidate (MetaTextureTower *tower,
|
||||
* Return value: the COGL texture handle to use for painting, or
|
||||
* %NULL if no base texture has yet been set.
|
||||
*/
|
||||
CoglTexture *
|
||||
meta_texture_tower_get_paint_texture (MetaTextureTower *tower,
|
||||
MetaMultiTexture *
|
||||
meta_texture_tower_get_paint_texture (MetaTextureTower *tower,
|
||||
ClutterPaintContext *paint_context)
|
||||
{
|
||||
int texture_width, texture_height;
|
||||
@ -444,8 +471,8 @@ meta_texture_tower_get_paint_texture (MetaTextureTower *tower,
|
||||
if (tower->textures[0] == NULL)
|
||||
return NULL;
|
||||
|
||||
texture_width = cogl_texture_get_width (tower->textures[0]);
|
||||
texture_height = cogl_texture_get_height (tower->textures[0]);
|
||||
texture_width = meta_multi_texture_get_width (tower->textures[0]);
|
||||
texture_height = meta_multi_texture_get_height (tower->textures[0]);
|
||||
|
||||
level = get_paint_level (paint_context, texture_width, texture_height);
|
||||
if (level < 0) /* singular paint matrix, scaled to nothing */
|
||||
|
@ -24,6 +24,7 @@
|
||||
#define __META_TEXTURE_TOWER_H__
|
||||
|
||||
#include "clutter/clutter.h"
|
||||
#include <meta/meta-multi-texture.h>
|
||||
|
||||
G_BEGIN_DECLS
|
||||
|
||||
@ -54,13 +55,13 @@ typedef struct _MetaTextureTower MetaTextureTower;
|
||||
MetaTextureTower *meta_texture_tower_new (void);
|
||||
void meta_texture_tower_free (MetaTextureTower *tower);
|
||||
void meta_texture_tower_set_base_texture (MetaTextureTower *tower,
|
||||
CoglTexture *texture);
|
||||
MetaMultiTexture *texture);
|
||||
void meta_texture_tower_update_area (MetaTextureTower *tower,
|
||||
int x,
|
||||
int y,
|
||||
int width,
|
||||
int height);
|
||||
CoglTexture *meta_texture_tower_get_paint_texture (MetaTextureTower *tower,
|
||||
MetaMultiTexture *meta_texture_tower_get_paint_texture (MetaTextureTower *tower,
|
||||
ClutterPaintContext *paint_context);
|
||||
|
||||
G_END_DECLS
|
||||
|
@ -302,6 +302,8 @@ mutter_sources = [
|
||||
'compositor/meta-feedback-actor-private.h',
|
||||
'compositor/meta-module.c',
|
||||
'compositor/meta-module.h',
|
||||
'compositor/meta-multi-texture.c',
|
||||
'compositor/meta-multi-texture-format.c',
|
||||
'compositor/meta-plugin.c',
|
||||
'compositor/meta-plugin-manager.c',
|
||||
'compositor/meta-plugin-manager.h',
|
||||
|
@ -20,6 +20,8 @@ mutter_public_headers = [
|
||||
'meta-inhibit-shortcuts-dialog.h',
|
||||
'meta-launch-context.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',
|
||||
|
138
src/meta/meta-multi-texture-format.h
Normal file
138
src/meta/meta-multi-texture-format.h
Normal file
@ -0,0 +1,138 @@
|
||||
/*
|
||||
* 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_FORMAT_H__
|
||||
#define __META_MULTI_TEXTURE_FORMAT_H__
|
||||
|
||||
#include <glib.h>
|
||||
#include <cogl/cogl.h>
|
||||
#include <meta/common.h>
|
||||
|
||||
G_BEGIN_DECLS
|
||||
|
||||
/**
|
||||
* MetaMultiTextureFormat:
|
||||
* @META_MULTI_TEXTURE_FORMAT_FORMAT_SIMPLE: Any format supported by Cogl (see #CoglPixelFormat)
|
||||
* @META_MULTI_TEXTURE_FORMAT_FORMAT_YUYV: YUYV, 32 bits, 16 bpc (Y), 8 bpc (U & V)
|
||||
* @META_MULTI_TEXTURE_FORMAT_FORMAT_YVYU: YVYU, 32 bits, 16 bpc (Y), 8 bpc (V & U)
|
||||
* @META_MULTI_TEXTURE_FORMAT_FORMAT_UYVY: UYVY, 32 bits, 16 bpc (Y), 8 bpc (V & U)
|
||||
* @META_MULTI_TEXTURE_FORMAT_FORMAT_VYUY: VYUV, 32 bits, 16 bpc (Y), 8 bpc (V & U)
|
||||
* @META_MULTI_TEXTURE_FORMAT_FORMAT_AYUV: AYUV, 32 bits, 8 bpc
|
||||
* @META_MULTI_TEXTURE_FORMAT_FORMAT_XRGB8888_A8: 2 planes: 1 RGB-plane (64-bit), 1 alpha-plane
|
||||
* @META_MULTI_TEXTURE_FORMAT_FORMAT_XBGR8888_A8: 2 planes: 1 BGR-plane (64-bit), 1 alpha-plane
|
||||
* @META_MULTI_TEXTURE_FORMAT_FORMAT_RGBX8888_A8: 2 planes: 1 RGB-plane (64-bit), 1 alpha-plane
|
||||
* @META_MULTI_TEXTURE_FORMAT_FORMAT_BGRX8888_A8: 2 planes: 1 BGR-plane (64-bit), 1 alpha-plane
|
||||
* @META_MULTI_TEXTURE_FORMAT_FORMAT_RGB888_A8: 2 planes: 1 RGB-plane (32-bit), 1 alpha-plane
|
||||
* @META_MULTI_TEXTURE_FORMAT_FORMAT_BGR888_A8: 2 planes: 1 BGR-plane (32-bit), 1 alpha-plane
|
||||
* @META_MULTI_TEXTURE_FORMAT_FORMAT_RGB565_A8: 2 planes: 1 RGB-plane (16-bit), 1 alpha-plane
|
||||
* @META_MULTI_TEXTURE_FORMAT_FORMAT_BGR565_A8: 2 planes: 1 BGR-plane (16-bit), 1 alpha-plane
|
||||
* @META_MULTI_TEXTURE_FORMAT_FORMAT_NV12: 2 planes: 1 Y-plane, 1 UV-plane (2x2 subsampled)
|
||||
* @META_MULTI_TEXTURE_FORMAT_FORMAT_NV21: 2 planes: 1 Y-plane, 1 VU-plane (2x2 subsampled)
|
||||
* @META_MULTI_TEXTURE_FORMAT_FORMAT_NV16: 2 planes: 1 Y-plane, 1 UV-plane (2x1 subsampled)
|
||||
* @META_MULTI_TEXTURE_FORMAT_FORMAT_NV61: 2 planes: 1 Y-plane, 1 VU-plane (2x1 subsampled)
|
||||
* @META_MULTI_TEXTURE_FORMAT_FORMAT_NV24: 2 planes: 1 Y-plane, 1 UV-plane
|
||||
* @META_MULTI_TEXTURE_FORMAT_FORMAT_NV42: 2 planes: 1 Y-plane, 1 VU-plane
|
||||
* @META_MULTI_TEXTURE_FORMAT_FORMAT_YUV410: 3 planes: 1 Y-plane, 1 U-plane (4x4 subsampled), 1 V-plane (4x4 subsampled)
|
||||
* @META_MULTI_TEXTURE_FORMAT_FORMAT_YVU410: 3 planes: 1 Y-plane, 1 V-plane (4x4 subsampled), 1 U-plane (4x4 subsampled)
|
||||
* @META_MULTI_TEXTURE_FORMAT_FORMAT_YUV411: 3 planes: 1 Y-plane, 1 U-plane (4x1 subsampled), 1 V-plane (4x1 subsampled)
|
||||
* @META_MULTI_TEXTURE_FORMAT_FORMAT_YVU411: 3 planes: 1 Y-plane, 1 V-plane (4x1 subsampled), 1 U-plane (4x1 subsampled)
|
||||
* @META_MULTI_TEXTURE_FORMAT_FORMAT_YUV420: 3 planes: 1 Y-plane, 1 U-plane (2x2 subsampled), 1 V-plane (2x2 subsampled)
|
||||
* @META_MULTI_TEXTURE_FORMAT_FORMAT_YVU420: 3 planes: 1 Y-plane, 1 V-plane (2x2 subsampled), 1 U-plane (2x2 subsampled)
|
||||
* @META_MULTI_TEXTURE_FORMAT_FORMAT_YUV422: 3 planes: 1 Y-plane, 1 U-plane (2x1 subsampled), 1 V-plane (2x1 subsampled)
|
||||
* @META_MULTI_TEXTURE_FORMAT_FORMAT_YVU422: 3 planes: 1 Y-plane, 1 V-plane (2x1 subsampled), 1 U-plane (2x1 subsampled)
|
||||
* @META_MULTI_TEXTURE_FORMAT_FORMAT_YUV444: 3 planes: 1 Y-plane, 1 U-plane, 1 V-plane
|
||||
* @META_MULTI_TEXTURE_FORMAT_FORMAT_YVU444: 3 planes: 1 Y-plane, 1 V-plane, 1 U-plane
|
||||
*
|
||||
* XXX write docs
|
||||
*/
|
||||
typedef enum _MetaMultiTextureFormat
|
||||
{
|
||||
META_MULTI_TEXTURE_FORMAT_SIMPLE,
|
||||
|
||||
/* The following list is somewhat synced with Linux's <drm_fourcc.h> */
|
||||
|
||||
/* Packed YUV */
|
||||
META_MULTI_TEXTURE_FORMAT_YUYV,
|
||||
META_MULTI_TEXTURE_FORMAT_YVYU,
|
||||
META_MULTI_TEXTURE_FORMAT_UYVY,
|
||||
META_MULTI_TEXTURE_FORMAT_VYUY,
|
||||
|
||||
META_MULTI_TEXTURE_FORMAT_AYUV,
|
||||
|
||||
/* 2 plane RGB + A */
|
||||
META_MULTI_TEXTURE_FORMAT_XRGB8888_A8,
|
||||
META_MULTI_TEXTURE_FORMAT_XBGR8888_A8,
|
||||
META_MULTI_TEXTURE_FORMAT_RGBX8888_A8,
|
||||
META_MULTI_TEXTURE_FORMAT_BGRX8888_A8,
|
||||
META_MULTI_TEXTURE_FORMAT_RGB888_A8,
|
||||
META_MULTI_TEXTURE_FORMAT_BGR888_A8,
|
||||
META_MULTI_TEXTURE_FORMAT_RGB565_A8,
|
||||
META_MULTI_TEXTURE_FORMAT_BGR565_A8,
|
||||
|
||||
/* 2 plane YUV */
|
||||
META_MULTI_TEXTURE_FORMAT_NV12,
|
||||
META_MULTI_TEXTURE_FORMAT_NV21,
|
||||
META_MULTI_TEXTURE_FORMAT_NV16,
|
||||
META_MULTI_TEXTURE_FORMAT_NV61,
|
||||
META_MULTI_TEXTURE_FORMAT_NV24,
|
||||
META_MULTI_TEXTURE_FORMAT_NV42,
|
||||
|
||||
/* 3 plane YUV */
|
||||
META_MULTI_TEXTURE_FORMAT_YUV410,
|
||||
META_MULTI_TEXTURE_FORMAT_YVU410,
|
||||
META_MULTI_TEXTURE_FORMAT_YUV411,
|
||||
META_MULTI_TEXTURE_FORMAT_YVU411,
|
||||
META_MULTI_TEXTURE_FORMAT_YUV420,
|
||||
META_MULTI_TEXTURE_FORMAT_YVU420,
|
||||
META_MULTI_TEXTURE_FORMAT_YUV422,
|
||||
META_MULTI_TEXTURE_FORMAT_YVU422,
|
||||
META_MULTI_TEXTURE_FORMAT_YUV444,
|
||||
META_MULTI_TEXTURE_FORMAT_YVU444
|
||||
} MetaMultiTextureFormat;
|
||||
|
||||
META_EXPORT
|
||||
void meta_multi_texture_format_get_bytes_per_pixel (MetaMultiTextureFormat format,
|
||||
uint8_t *bpp_out);
|
||||
|
||||
META_EXPORT
|
||||
int meta_multi_texture_format_get_n_planes (MetaMultiTextureFormat format);
|
||||
|
||||
META_EXPORT
|
||||
void meta_multi_texture_format_get_subsampling_factors (MetaMultiTextureFormat format,
|
||||
uint8_t *horizontal_factors,
|
||||
uint8_t *vertical_factors);
|
||||
|
||||
META_EXPORT
|
||||
void meta_multi_texture_format_get_subformats (MetaMultiTextureFormat format,
|
||||
CoglPixelFormat *formats_out);
|
||||
|
||||
META_EXPORT
|
||||
gboolean meta_multi_texture_format_needs_shaders (MetaMultiTextureFormat format);
|
||||
|
||||
META_EXPORT
|
||||
gboolean meta_multi_texture_format_get_snippets (MetaMultiTextureFormat format,
|
||||
CoglSnippet **vertex_snippet,
|
||||
CoglSnippet **fragment_snippet,
|
||||
CoglSnippet **layer_snippet);
|
||||
|
||||
G_END_DECLS
|
||||
|
||||
#endif
|
72
src/meta/meta-multi-texture.h
Normal file
72
src/meta/meta-multi-texture.h
Normal file
@ -0,0 +1,72 @@
|
||||
/*
|
||||
* 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,
|
||||
guint n_planes);
|
||||
|
||||
META_EXPORT
|
||||
MetaMultiTexture * meta_multi_texture_new_simple (CoglTexture *plane);
|
||||
|
||||
META_EXPORT
|
||||
MetaMultiTextureFormat meta_multi_texture_get_format (MetaMultiTexture *self);
|
||||
|
||||
META_EXPORT
|
||||
gboolean meta_multi_texture_is_simple (MetaMultiTexture *self);
|
||||
|
||||
META_EXPORT
|
||||
guint meta_multi_texture_get_n_planes (MetaMultiTexture *self);
|
||||
|
||||
META_EXPORT
|
||||
CoglTexture * meta_multi_texture_get_plane (MetaMultiTexture *self,
|
||||
guint index);
|
||||
|
||||
META_EXPORT
|
||||
int meta_multi_texture_get_width (MetaMultiTexture *self);
|
||||
|
||||
META_EXPORT
|
||||
int meta_multi_texture_get_height (MetaMultiTexture *self);
|
||||
|
||||
META_EXPORT
|
||||
char * meta_multi_texture_to_string (MetaMultiTexture *self);
|
||||
|
||||
G_END_DECLS
|
||||
|
||||
#endif
|
@ -28,6 +28,7 @@
|
||||
|
||||
#include "clutter/clutter.h"
|
||||
#include <meta/common.h>
|
||||
#include <meta/meta-multi-texture.h>
|
||||
|
||||
G_BEGIN_DECLS
|
||||
|
||||
@ -45,7 +46,7 @@ void meta_shaped_texture_set_create_mipmaps (MetaShapedTexture *stex,
|
||||
gboolean create_mipmaps);
|
||||
|
||||
META_EXPORT
|
||||
CoglTexture * meta_shaped_texture_get_texture (MetaShapedTexture *stex);
|
||||
MetaMultiTexture * meta_shaped_texture_get_texture (MetaShapedTexture *stex);
|
||||
|
||||
META_EXPORT
|
||||
void meta_shaped_texture_set_mask_texture (MetaShapedTexture *stex,
|
||||
|
@ -155,7 +155,7 @@ meta_wayland_buffer_realize (MetaWaylandBuffer *buffer)
|
||||
|
||||
buffer->egl_stream.stream = stream;
|
||||
buffer->type = META_WAYLAND_BUFFER_TYPE_EGL_STREAM;
|
||||
buffer->egl_stream.texture = COGL_TEXTURE (texture);
|
||||
buffer->egl_stream.texture = meta_multi_texture_new_simple (COGL_TEXTURE (texture));
|
||||
buffer->is_y_inverted = meta_wayland_egl_stream_is_y_inverted (stream);
|
||||
|
||||
return TRUE;
|
||||
@ -182,46 +182,53 @@ meta_wayland_buffer_realize (MetaWaylandBuffer *buffer)
|
||||
}
|
||||
|
||||
static void
|
||||
shm_buffer_get_cogl_pixel_format (struct wl_shm_buffer *shm_buffer,
|
||||
CoglPixelFormat *format_out,
|
||||
CoglTextureComponents *components_out)
|
||||
shm_buffer_get_format (struct wl_shm_buffer *shm_buffer,
|
||||
MetaMultiTextureFormat *multi_format_out,
|
||||
CoglPixelFormat *cogl_format_out,
|
||||
CoglTextureComponents *components_out)
|
||||
{
|
||||
CoglPixelFormat format;
|
||||
MetaMultiTextureFormat multi_format = META_MULTI_TEXTURE_FORMAT_SIMPLE;
|
||||
CoglPixelFormat cogl_format = COGL_PIXEL_FORMAT_ANY;
|
||||
CoglTextureComponents components = COGL_TEXTURE_COMPONENTS_RGBA;
|
||||
|
||||
switch (wl_shm_buffer_get_format (shm_buffer))
|
||||
{
|
||||
#if G_BYTE_ORDER == G_BIG_ENDIAN
|
||||
case WL_SHM_FORMAT_ARGB8888:
|
||||
format = COGL_PIXEL_FORMAT_ARGB_8888_PRE;
|
||||
cogl_format = COGL_PIXEL_FORMAT_ARGB_8888_PRE;
|
||||
break;
|
||||
case WL_SHM_FORMAT_XRGB8888:
|
||||
format = COGL_PIXEL_FORMAT_ARGB_8888;
|
||||
cogl_format = COGL_PIXEL_FORMAT_ARGB_8888;
|
||||
components = COGL_TEXTURE_COMPONENTS_RGB;
|
||||
break;
|
||||
#elif G_BYTE_ORDER == G_LITTLE_ENDIAN
|
||||
case WL_SHM_FORMAT_ARGB8888:
|
||||
format = COGL_PIXEL_FORMAT_BGRA_8888_PRE;
|
||||
cogl_format = COGL_PIXEL_FORMAT_BGRA_8888_PRE;
|
||||
break;
|
||||
case WL_SHM_FORMAT_XRGB8888:
|
||||
format = COGL_PIXEL_FORMAT_BGRA_8888;
|
||||
cogl_format = COGL_PIXEL_FORMAT_BGRA_8888;
|
||||
components = COGL_TEXTURE_COMPONENTS_RGB;
|
||||
break;
|
||||
#endif
|
||||
case WL_SHM_FORMAT_NV12:
|
||||
multi_format = META_MULTI_TEXTURE_FORMAT_NV12;
|
||||
break;
|
||||
default:
|
||||
g_warn_if_reached ();
|
||||
format = COGL_PIXEL_FORMAT_ARGB_8888;
|
||||
cogl_format = COGL_PIXEL_FORMAT_ARGB_8888;
|
||||
}
|
||||
|
||||
if (format_out)
|
||||
*format_out = format;
|
||||
if (multi_format_out)
|
||||
*multi_format_out = multi_format;
|
||||
if (cogl_format_out)
|
||||
*cogl_format_out = cogl_format;
|
||||
if (components_out)
|
||||
*components_out = components;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
shm_buffer_attach (MetaWaylandBuffer *buffer,
|
||||
CoglTexture **texture,
|
||||
MetaMultiTexture **texture,
|
||||
GError **error)
|
||||
{
|
||||
MetaBackend *backend = meta_get_backend ();
|
||||
@ -229,76 +236,139 @@ shm_buffer_attach (MetaWaylandBuffer *buffer,
|
||||
CoglContext *cogl_context = clutter_backend_get_cogl_context (clutter_backend);
|
||||
struct wl_shm_buffer *shm_buffer;
|
||||
int stride, width, height;
|
||||
CoglPixelFormat format;
|
||||
MetaMultiTextureFormat multi_format;
|
||||
CoglTextureComponents components;
|
||||
CoglBitmap *bitmap;
|
||||
CoglTexture *new_texture;
|
||||
uint8_t h_factors[3], v_factors[3], bpp[3];
|
||||
CoglPixelFormat subformats[3];
|
||||
guint i, n_planes;
|
||||
gsize plane_offset = 0;
|
||||
guint8 *data;
|
||||
GPtrArray *planes;
|
||||
|
||||
shm_buffer = wl_shm_buffer_get (buffer->resource);
|
||||
|
||||
/* Query the necessary properties */
|
||||
stride = wl_shm_buffer_get_stride (shm_buffer);
|
||||
width = wl_shm_buffer_get_width (shm_buffer);
|
||||
height = wl_shm_buffer_get_height (shm_buffer);
|
||||
shm_buffer_get_cogl_pixel_format (shm_buffer, &format, &components);
|
||||
shm_buffer_get_format (shm_buffer, &multi_format, &subformats[0], &components);
|
||||
|
||||
if (*texture &&
|
||||
cogl_texture_get_width (*texture) == width &&
|
||||
cogl_texture_get_height (*texture) == height &&
|
||||
cogl_texture_get_components (*texture) == components &&
|
||||
_cogl_texture_get_format (*texture) == format)
|
||||
/* Fetch some properties from the pixel format */
|
||||
n_planes = meta_multi_texture_format_get_n_planes (multi_format);
|
||||
if (multi_format == META_MULTI_TEXTURE_FORMAT_SIMPLE)
|
||||
{
|
||||
buffer->is_y_inverted = TRUE;
|
||||
return TRUE;
|
||||
/* In the simple case, we can fall back to CoglPixelFormat */
|
||||
bpp[0] = cogl_pixel_format_get_bytes_per_pixel (subformats[0], 0);
|
||||
h_factors[0] = 1; /* No subsampling */
|
||||
v_factors[0] = 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
meta_multi_texture_format_get_subformats (multi_format, subformats);
|
||||
meta_multi_texture_format_get_bytes_per_pixel (multi_format, bpp);
|
||||
meta_multi_texture_format_get_subsampling_factors (multi_format, h_factors, v_factors);
|
||||
}
|
||||
|
||||
cogl_clear_object (texture);
|
||||
if (*texture &&
|
||||
meta_multi_texture_get_width (*texture) == width &&
|
||||
meta_multi_texture_get_height (*texture) == height &&
|
||||
meta_multi_texture_get_format (*texture) == multi_format)
|
||||
{
|
||||
CoglTexture *cogl_texture = meta_multi_texture_get_plane (*texture, 0);
|
||||
if (cogl_texture_get_components (cogl_texture) == components &&
|
||||
_cogl_texture_get_format (cogl_texture) == subformats[0])
|
||||
{
|
||||
buffer->is_y_inverted = TRUE;
|
||||
return TRUE;
|
||||
}
|
||||
}
|
||||
|
||||
g_clear_object (texture);
|
||||
|
||||
wl_shm_buffer_begin_access (shm_buffer);
|
||||
data = wl_shm_buffer_get_data (shm_buffer);
|
||||
|
||||
bitmap = cogl_bitmap_new_for_data (cogl_context,
|
||||
width, height,
|
||||
format,
|
||||
stride,
|
||||
wl_shm_buffer_get_data (shm_buffer));
|
||||
|
||||
new_texture = COGL_TEXTURE (cogl_texture_2d_new_from_bitmap (bitmap));
|
||||
cogl_texture_set_components (new_texture, components);
|
||||
|
||||
if (!cogl_texture_allocate (new_texture, error))
|
||||
planes = g_ptr_array_new_full (n_planes, cogl_object_unref);
|
||||
for (i = 0; i < n_planes; i++)
|
||||
{
|
||||
g_clear_pointer (&new_texture, cogl_object_unref);
|
||||
if (g_error_matches (*error, COGL_TEXTURE_ERROR, COGL_TEXTURE_ERROR_SIZE))
|
||||
int plane_stride;
|
||||
CoglBitmap *plane_bitmap;
|
||||
CoglTexture *plane_texture;
|
||||
|
||||
/* Adjust the stride: map to the amount of pixels and calculate how many
|
||||
* bytes that takes in the current plane */
|
||||
plane_stride = (stride / bpp[0]) * bpp[i] / h_factors[i];
|
||||
|
||||
/* Define the bitmap that of this plane */
|
||||
plane_bitmap = cogl_bitmap_new_for_data (cogl_context,
|
||||
width / h_factors[i],
|
||||
height / v_factors[i],
|
||||
subformats[i],
|
||||
plane_stride,
|
||||
data + plane_offset);
|
||||
if (!plane_bitmap)
|
||||
goto failure;
|
||||
|
||||
/* Create a texture out of it so we can upload it to the GPU */
|
||||
plane_texture = COGL_TEXTURE (cogl_texture_2d_new_from_bitmap (plane_bitmap));
|
||||
|
||||
/* Separately set the components (necessary for e.g. XRGB, NV12) */
|
||||
/* cogl_texture_set_components (plane_texture, components[i]); */
|
||||
|
||||
if (!cogl_texture_allocate (plane_texture, error))
|
||||
{
|
||||
CoglTexture2DSliced *texture_sliced;
|
||||
|
||||
cogl_clear_object (&plane_texture);
|
||||
|
||||
/* If it didn't work due to an NPOT size, try again with an atlas texture */
|
||||
if (!g_error_matches (*error, COGL_TEXTURE_ERROR, COGL_TEXTURE_ERROR_SIZE))
|
||||
{
|
||||
cogl_object_unref (plane_bitmap);
|
||||
goto failure;
|
||||
}
|
||||
|
||||
g_clear_error (error);
|
||||
|
||||
texture_sliced =
|
||||
cogl_texture_2d_sliced_new_from_bitmap (bitmap,
|
||||
cogl_texture_2d_sliced_new_from_bitmap (plane_bitmap,
|
||||
COGL_TEXTURE_MAX_WASTE);
|
||||
new_texture = COGL_TEXTURE (texture_sliced);
|
||||
cogl_texture_set_components (new_texture, components);
|
||||
plane_texture = COGL_TEXTURE (texture_sliced);
|
||||
|
||||
if (!cogl_texture_allocate (new_texture, error))
|
||||
g_clear_pointer (&new_texture, cogl_object_unref);
|
||||
/* cogl_texture_set_components (plane_texture, components[i]); */
|
||||
|
||||
if (!cogl_texture_allocate (plane_texture, error))
|
||||
{
|
||||
cogl_clear_object (&plane_texture);
|
||||
goto failure;
|
||||
}
|
||||
}
|
||||
|
||||
g_ptr_array_add (planes, plane_texture);
|
||||
|
||||
/* Calculate the next plane start in the buffer (consider subsampling) */
|
||||
plane_offset += plane_stride * (height / v_factors[i]);
|
||||
}
|
||||
|
||||
cogl_object_unref (bitmap);
|
||||
*texture = meta_multi_texture_new (multi_format,
|
||||
(CoglTexture **) g_ptr_array_free (planes, FALSE),
|
||||
n_planes);
|
||||
|
||||
wl_shm_buffer_end_access (shm_buffer);
|
||||
|
||||
if (!new_texture)
|
||||
return FALSE;
|
||||
|
||||
*texture = new_texture;
|
||||
buffer->is_y_inverted = TRUE;
|
||||
|
||||
return TRUE;
|
||||
|
||||
failure:
|
||||
wl_shm_buffer_end_access (shm_buffer);
|
||||
g_ptr_array_free (planes, TRUE);
|
||||
*texture = NULL;
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
egl_image_buffer_attach (MetaWaylandBuffer *buffer,
|
||||
CoglTexture **texture,
|
||||
MetaMultiTexture **texture,
|
||||
GError **error)
|
||||
{
|
||||
MetaBackend *backend = meta_get_backend ();
|
||||
@ -307,15 +377,15 @@ egl_image_buffer_attach (MetaWaylandBuffer *buffer,
|
||||
CoglContext *cogl_context = clutter_backend_get_cogl_context (clutter_backend);
|
||||
EGLDisplay egl_display = cogl_egl_context_get_egl_display (cogl_context);
|
||||
int format, width, height, y_inverted;
|
||||
CoglPixelFormat cogl_format;
|
||||
EGLImageKHR egl_image;
|
||||
CoglEglImageFlags flags;
|
||||
CoglTexture2D *texture_2d;
|
||||
MetaMultiTextureFormat multi_format = META_MULTI_TEXTURE_FORMAT_SIMPLE;
|
||||
CoglPixelFormat cogl_format = COGL_PIXEL_FORMAT_ANY;
|
||||
guint i, n_planes;
|
||||
GPtrArray *planes;
|
||||
|
||||
if (buffer->egl_image.texture)
|
||||
{
|
||||
cogl_clear_object (texture);
|
||||
*texture = cogl_object_ref (buffer->egl_image.texture);
|
||||
g_clear_object (texture);
|
||||
*texture = g_object_ref (buffer->egl_image.texture);
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
@ -339,6 +409,7 @@ egl_image_buffer_attach (MetaWaylandBuffer *buffer,
|
||||
NULL))
|
||||
y_inverted = EGL_TRUE;
|
||||
|
||||
/* Query the color format */
|
||||
switch (format)
|
||||
{
|
||||
case EGL_TEXTURE_RGB:
|
||||
@ -347,6 +418,16 @@ egl_image_buffer_attach (MetaWaylandBuffer *buffer,
|
||||
case EGL_TEXTURE_RGBA:
|
||||
cogl_format = COGL_PIXEL_FORMAT_RGBA_8888_PRE;
|
||||
break;
|
||||
case EGL_TEXTURE_Y_UV_WL:
|
||||
/* Technically it can be anything with a separate Y and UV plane
|
||||
* but since this is only used for shaders later, it's ok */
|
||||
multi_format = META_MULTI_TEXTURE_FORMAT_NV12;
|
||||
break;
|
||||
case EGL_TEXTURE_Y_U_V_WL:
|
||||
/* Technically it can be anything with a separate Y and UV plane
|
||||
* but since this is only used for shaders later, it's ok */
|
||||
multi_format = META_MULTI_TEXTURE_FORMAT_YUV444;
|
||||
break;
|
||||
default:
|
||||
g_set_error (error, G_IO_ERROR,
|
||||
G_IO_ERROR_FAILED,
|
||||
@ -354,41 +435,70 @@ egl_image_buffer_attach (MetaWaylandBuffer *buffer,
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
/* The WL_bind_wayland_display spec states that EGL_NO_CONTEXT is to be used
|
||||
* in conjunction with the EGL_WAYLAND_BUFFER_WL target. */
|
||||
egl_image = meta_egl_create_image (egl, egl_display, EGL_NO_CONTEXT,
|
||||
EGL_WAYLAND_BUFFER_WL, buffer->resource,
|
||||
NULL,
|
||||
error);
|
||||
if (egl_image == EGL_NO_IMAGE_KHR)
|
||||
return FALSE;
|
||||
/* Each EGLImage is a plane in the final texture */
|
||||
n_planes = meta_multi_texture_format_get_n_planes (multi_format);
|
||||
planes = g_ptr_array_new_full (n_planes, cogl_object_unref);
|
||||
|
||||
flags = COGL_EGL_IMAGE_FLAG_NONE;
|
||||
texture_2d = cogl_egl_texture_2d_new_from_image (cogl_context,
|
||||
width, height,
|
||||
cogl_format,
|
||||
egl_image,
|
||||
flags,
|
||||
error);
|
||||
g_warning ("Got EGL with format %u", multi_format);
|
||||
|
||||
meta_egl_destroy_image (egl, egl_display, egl_image, NULL);
|
||||
for (i = 0; i < n_planes; i++)
|
||||
{
|
||||
EGLint egl_attribs[3];
|
||||
EGLImageKHR egl_img;
|
||||
CoglEglImageFlags flags;
|
||||
CoglTexture2D *texture_2d;
|
||||
|
||||
if (!texture_2d)
|
||||
return FALSE;
|
||||
/* Specify that we want the i'th plane */
|
||||
egl_attribs[0] = EGL_WAYLAND_PLANE_WL;
|
||||
egl_attribs[1] = i;
|
||||
egl_attribs[2] = EGL_NONE;
|
||||
|
||||
buffer->egl_image.texture = COGL_TEXTURE (texture_2d);
|
||||
/* The WL_bind_wayland_display spec states that EGL_NO_CONTEXT is to be
|
||||
* used in conjunction with the EGL_WAYLAND_BUFFER_WL target. */
|
||||
egl_img = meta_egl_create_image (egl, egl_display, EGL_NO_CONTEXT,
|
||||
EGL_WAYLAND_BUFFER_WL, buffer->resource,
|
||||
egl_attribs,
|
||||
error);
|
||||
|
||||
if (G_UNLIKELY (egl_img == EGL_NO_IMAGE_KHR))
|
||||
goto on_error;
|
||||
|
||||
flags = COGL_EGL_IMAGE_FLAG_NONE;
|
||||
texture_2d = cogl_egl_texture_2d_new_from_image (cogl_context,
|
||||
width, height,
|
||||
cogl_format,
|
||||
egl_img,
|
||||
flags,
|
||||
error);
|
||||
|
||||
meta_egl_destroy_image (egl, egl_display, egl_img, NULL);
|
||||
|
||||
if (G_UNLIKELY (!texture_2d))
|
||||
goto on_error;
|
||||
|
||||
g_ptr_array_add (planes, COGL_TEXTURE (texture_2d));
|
||||
}
|
||||
|
||||
buffer->egl_image.texture =
|
||||
meta_multi_texture_new (multi_format,
|
||||
(CoglTexture**) g_ptr_array_free (planes, FALSE),
|
||||
n_planes);
|
||||
buffer->is_y_inverted = !!y_inverted;
|
||||
|
||||
cogl_clear_object (texture);
|
||||
*texture = cogl_object_ref (buffer->egl_image.texture);
|
||||
g_clear_object (texture);
|
||||
*texture = g_object_ref (buffer->egl_image.texture);
|
||||
|
||||
return TRUE;
|
||||
|
||||
on_error:
|
||||
g_ptr_array_free (planes, TRUE);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
#ifdef HAVE_WAYLAND_EGLSTREAM
|
||||
static gboolean
|
||||
egl_stream_buffer_attach (MetaWaylandBuffer *buffer,
|
||||
CoglTexture **texture,
|
||||
MetaMultiTexture **texture,
|
||||
GError **error)
|
||||
{
|
||||
MetaWaylandEglStream *stream = buffer->egl_stream.stream;
|
||||
@ -398,8 +508,8 @@ egl_stream_buffer_attach (MetaWaylandBuffer *buffer,
|
||||
if (!meta_wayland_egl_stream_attach (stream, error))
|
||||
return FALSE;
|
||||
|
||||
cogl_clear_object (texture);
|
||||
*texture = cogl_object_ref (buffer->egl_stream.texture);
|
||||
g_clear_object (texture);
|
||||
*texture = g_object_ref (buffer->egl_stream.texture);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
@ -408,8 +518,8 @@ egl_stream_buffer_attach (MetaWaylandBuffer *buffer,
|
||||
/**
|
||||
* meta_wayland_buffer_attach:
|
||||
* @buffer: a pointer to a #MetaWaylandBuffer
|
||||
* @texture: (inout) (transfer full): a #CoglTexture representing the surface
|
||||
* content
|
||||
* @texture: (inout) (transfer full): a #MetaMultiTexture representing the
|
||||
* surface content
|
||||
* @error: return location for error or %NULL
|
||||
*
|
||||
* This function should be passed a pointer to the texture used to draw the
|
||||
@ -426,7 +536,7 @@ egl_stream_buffer_attach (MetaWaylandBuffer *buffer,
|
||||
*/
|
||||
gboolean
|
||||
meta_wayland_buffer_attach (MetaWaylandBuffer *buffer,
|
||||
CoglTexture **texture,
|
||||
MetaMultiTexture **texture,
|
||||
GError **error)
|
||||
{
|
||||
g_return_val_if_fail (buffer->resource, FALSE);
|
||||
@ -493,56 +603,102 @@ meta_wayland_buffer_is_y_inverted (MetaWaylandBuffer *buffer)
|
||||
|
||||
static gboolean
|
||||
process_shm_buffer_damage (MetaWaylandBuffer *buffer,
|
||||
CoglTexture *texture,
|
||||
MetaMultiTexture *texture,
|
||||
cairo_region_t *region,
|
||||
GError **error)
|
||||
{
|
||||
struct wl_shm_buffer *shm_buffer;
|
||||
int i, n_rectangles;
|
||||
gboolean set_texture_failed = FALSE;
|
||||
CoglPixelFormat format;
|
||||
MetaMultiTextureFormat multi_format = META_MULTI_TEXTURE_FORMAT_SIMPLE;
|
||||
CoglTextureComponents components;
|
||||
const uint8_t *data;
|
||||
int32_t stride, height;
|
||||
uint8_t h_factors[3], v_factors[3], bpp[3];
|
||||
CoglPixelFormat subformats[3];
|
||||
gsize plane_offset = 0;
|
||||
guint i, n_planes;
|
||||
int j, n_rectangles;
|
||||
|
||||
n_rectangles = cairo_region_num_rectangles (region);
|
||||
|
||||
shm_buffer = wl_shm_buffer_get (buffer->resource);
|
||||
|
||||
shm_buffer_get_cogl_pixel_format (shm_buffer, &format, NULL);
|
||||
g_return_val_if_fail (cogl_pixel_format_get_n_planes (format) == 1, FALSE);
|
||||
|
||||
/* Get the data */
|
||||
wl_shm_buffer_begin_access (shm_buffer);
|
||||
data = wl_shm_buffer_get_data (shm_buffer);
|
||||
|
||||
for (i = 0; i < n_rectangles; i++)
|
||||
/* Query the necessary properties */
|
||||
stride = wl_shm_buffer_get_stride (shm_buffer);
|
||||
height = wl_shm_buffer_get_height (shm_buffer);
|
||||
shm_buffer_get_format (shm_buffer, &multi_format, &subformats[0], &components);
|
||||
|
||||
/* Fetch some properties from the pixel format */
|
||||
n_planes = meta_multi_texture_format_get_n_planes (multi_format);
|
||||
if (multi_format == META_MULTI_TEXTURE_FORMAT_SIMPLE)
|
||||
{
|
||||
const uint8_t *data = wl_shm_buffer_get_data (shm_buffer);
|
||||
int32_t stride = wl_shm_buffer_get_stride (shm_buffer);
|
||||
cairo_rectangle_int_t rect;
|
||||
int bpp;
|
||||
|
||||
bpp = cogl_pixel_format_get_bytes_per_pixel (format, 0);
|
||||
cairo_region_get_rectangle (region, i, &rect);
|
||||
|
||||
if (!_cogl_texture_set_region (texture,
|
||||
rect.width, rect.height,
|
||||
format,
|
||||
stride,
|
||||
data + rect.x * bpp + rect.y * stride,
|
||||
rect.x, rect.y,
|
||||
0,
|
||||
error))
|
||||
{
|
||||
set_texture_failed = TRUE;
|
||||
break;
|
||||
}
|
||||
/* In the simple case, we can fall back to CoglPixelFormat */
|
||||
bpp[0] = cogl_pixel_format_get_bytes_per_pixel (subformats[0], 0);
|
||||
h_factors[0] = 1; /* No subsampling */
|
||||
v_factors[0] = 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
meta_multi_texture_format_get_subformats (multi_format, subformats);
|
||||
meta_multi_texture_format_get_bytes_per_pixel (multi_format, bpp);
|
||||
meta_multi_texture_format_get_subsampling_factors (multi_format, h_factors, v_factors);
|
||||
}
|
||||
|
||||
wl_shm_buffer_end_access (shm_buffer);
|
||||
/* Go over each plane and process the regions */
|
||||
for (i = 0; i < n_planes; i++)
|
||||
{
|
||||
CoglTexture *plane;
|
||||
int plane_stride;
|
||||
|
||||
plane = meta_multi_texture_get_plane (texture, i);
|
||||
plane_stride = (stride / bpp[0]) * bpp[i] / h_factors[i];
|
||||
|
||||
for (j = 0; j < n_rectangles; j++)
|
||||
{
|
||||
cairo_rectangle_int_t rect;
|
||||
gsize rect_offset;
|
||||
|
||||
cairo_region_get_rectangle (region, j, &rect);
|
||||
|
||||
/* It's possible we get a faulty rectangle of size zero: ignore */
|
||||
if (rect.height == 0 || rect.width == 0)
|
||||
continue;
|
||||
|
||||
rect_offset = plane_offset
|
||||
+ rect.y * plane_stride / v_factors[i] /* Find the right row */
|
||||
+ rect.x * bpp[i] / h_factors[i]; /* and the right column */
|
||||
|
||||
if (!_cogl_texture_set_region (plane,
|
||||
rect.width / h_factors[i],
|
||||
rect.height / v_factors[i],
|
||||
subformats[i],
|
||||
plane_stride,
|
||||
data + rect_offset,
|
||||
rect.x, rect.y,
|
||||
0,
|
||||
error))
|
||||
{
|
||||
set_texture_failed = TRUE;
|
||||
goto out;
|
||||
}
|
||||
}
|
||||
|
||||
/* Calculate the next plane start in the buffer (consider subsampling) */
|
||||
plane_offset += plane_stride * (height / v_factors[i]);
|
||||
}
|
||||
|
||||
out:
|
||||
wl_shm_buffer_end_access (shm_buffer);
|
||||
return !set_texture_failed;
|
||||
}
|
||||
|
||||
void
|
||||
meta_wayland_buffer_process_damage (MetaWaylandBuffer *buffer,
|
||||
CoglTexture *texture,
|
||||
MetaMultiTexture *texture,
|
||||
cairo_region_t *region)
|
||||
{
|
||||
gboolean res = FALSE;
|
||||
@ -582,12 +738,12 @@ meta_wayland_buffer_finalize (GObject *object)
|
||||
{
|
||||
MetaWaylandBuffer *buffer = META_WAYLAND_BUFFER (object);
|
||||
|
||||
g_clear_pointer (&buffer->egl_image.texture, cogl_object_unref);
|
||||
g_clear_object (&buffer->egl_image.texture);
|
||||
#ifdef HAVE_WAYLAND_EGLSTREAM
|
||||
g_clear_pointer (&buffer->egl_stream.texture, cogl_object_unref);
|
||||
g_clear_object (&buffer->egl_stream.texture);
|
||||
g_clear_object (&buffer->egl_stream.stream);
|
||||
#endif
|
||||
g_clear_pointer (&buffer->dma_buf.texture, cogl_object_unref);
|
||||
g_clear_object (&buffer->dma_buf.texture);
|
||||
g_clear_object (&buffer->dma_buf.dma_buf);
|
||||
|
||||
G_OBJECT_CLASS (meta_wayland_buffer_parent_class)->finalize (object);
|
||||
|
@ -29,6 +29,7 @@
|
||||
#include <wayland-server.h>
|
||||
|
||||
#include "cogl/cogl.h"
|
||||
#include "meta/meta-multi-texture.h"
|
||||
#include "wayland/meta-wayland-types.h"
|
||||
#include "wayland/meta-wayland-egl-stream.h"
|
||||
#include "wayland/meta-wayland-dma-buf.h"
|
||||
@ -56,19 +57,19 @@ struct _MetaWaylandBuffer
|
||||
MetaWaylandBufferType type;
|
||||
|
||||
struct {
|
||||
CoglTexture *texture;
|
||||
MetaMultiTexture *texture;
|
||||
} egl_image;
|
||||
|
||||
#ifdef HAVE_WAYLAND_EGLSTREAM
|
||||
struct {
|
||||
MetaWaylandEglStream *stream;
|
||||
CoglTexture *texture;
|
||||
MetaMultiTexture *texture;
|
||||
} egl_stream;
|
||||
#endif
|
||||
|
||||
struct {
|
||||
MetaWaylandDmaBufBuffer *dma_buf;
|
||||
CoglTexture *texture;
|
||||
MetaMultiTexture *texture;
|
||||
} dma_buf;
|
||||
};
|
||||
|
||||
@ -81,12 +82,12 @@ struct wl_resource * meta_wayland_buffer_get_resource (MetaWaylandBuff
|
||||
gboolean meta_wayland_buffer_is_realized (MetaWaylandBuffer *buffer);
|
||||
gboolean meta_wayland_buffer_realize (MetaWaylandBuffer *buffer);
|
||||
gboolean meta_wayland_buffer_attach (MetaWaylandBuffer *buffer,
|
||||
CoglTexture **texture,
|
||||
MetaMultiTexture **texture,
|
||||
GError **error);
|
||||
CoglSnippet * meta_wayland_buffer_create_snippet (MetaWaylandBuffer *buffer);
|
||||
gboolean meta_wayland_buffer_is_y_inverted (MetaWaylandBuffer *buffer);
|
||||
void meta_wayland_buffer_process_damage (MetaWaylandBuffer *buffer,
|
||||
CoglTexture *texture,
|
||||
MetaMultiTexture *texture,
|
||||
cairo_region_t *region);
|
||||
|
||||
#endif /* META_WAYLAND_BUFFER_H */
|
||||
|
@ -90,7 +90,7 @@ meta_wayland_dma_buf_realize_texture (MetaWaylandBuffer *buffer,
|
||||
CoglPixelFormat cogl_format;
|
||||
EGLImageKHR egl_image;
|
||||
CoglEglImageFlags flags;
|
||||
CoglTexture2D *texture;
|
||||
CoglTexture2D *cogl_texture;
|
||||
|
||||
if (buffer->dma_buf.texture)
|
||||
return TRUE;
|
||||
@ -146,20 +146,20 @@ meta_wayland_dma_buf_realize_texture (MetaWaylandBuffer *buffer,
|
||||
return FALSE;
|
||||
|
||||
flags = COGL_EGL_IMAGE_FLAG_NO_GET_DATA;
|
||||
texture = cogl_egl_texture_2d_new_from_image (cogl_context,
|
||||
dma_buf->width,
|
||||
dma_buf->height,
|
||||
cogl_format,
|
||||
egl_image,
|
||||
flags,
|
||||
error);
|
||||
cogl_texture = cogl_egl_texture_2d_new_from_image (cogl_context,
|
||||
dma_buf->width,
|
||||
dma_buf->height,
|
||||
cogl_format,
|
||||
egl_image,
|
||||
flags,
|
||||
error);
|
||||
|
||||
meta_egl_destroy_image (egl, egl_display, egl_image, NULL);
|
||||
|
||||
if (!texture)
|
||||
if (!cogl_texture)
|
||||
return FALSE;
|
||||
|
||||
buffer->dma_buf.texture = COGL_TEXTURE (texture);
|
||||
buffer->dma_buf.texture = meta_multi_texture_new_simple (COGL_TEXTURE (cogl_texture));
|
||||
buffer->is_y_inverted = dma_buf->is_y_inverted;
|
||||
|
||||
return TRUE;
|
||||
@ -167,14 +167,14 @@ meta_wayland_dma_buf_realize_texture (MetaWaylandBuffer *buffer,
|
||||
|
||||
gboolean
|
||||
meta_wayland_dma_buf_buffer_attach (MetaWaylandBuffer *buffer,
|
||||
CoglTexture **texture,
|
||||
MetaMultiTexture **texture,
|
||||
GError **error)
|
||||
{
|
||||
if (!meta_wayland_dma_buf_realize_texture (buffer, error))
|
||||
return FALSE;
|
||||
|
||||
cogl_clear_object (texture);
|
||||
*texture = cogl_object_ref (buffer->dma_buf.texture);
|
||||
g_clear_object (texture);
|
||||
*texture = g_object_ref (buffer->dma_buf.texture);
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
|
@ -31,6 +31,7 @@
|
||||
#include <glib-object.h>
|
||||
|
||||
#include "cogl/cogl.h"
|
||||
#include "meta/meta-multi-texture.h"
|
||||
#include "wayland/meta-wayland-types.h"
|
||||
|
||||
#define META_TYPE_WAYLAND_DMA_BUF_BUFFER (meta_wayland_dma_buf_buffer_get_type ())
|
||||
@ -43,7 +44,7 @@ gboolean meta_wayland_dma_buf_init (MetaWaylandCompositor *compositor);
|
||||
|
||||
gboolean
|
||||
meta_wayland_dma_buf_buffer_attach (MetaWaylandBuffer *buffer,
|
||||
CoglTexture **texture,
|
||||
MetaMultiTexture **texture,
|
||||
GError **error);
|
||||
|
||||
MetaWaylandDmaBufBuffer *
|
||||
|
@ -241,7 +241,7 @@ get_buffer_width (MetaWaylandSurface *surface)
|
||||
MetaWaylandBuffer *buffer = meta_wayland_surface_get_buffer (surface);
|
||||
|
||||
if (buffer)
|
||||
return cogl_texture_get_width (surface->texture);
|
||||
return meta_multi_texture_get_width (surface->texture);
|
||||
else
|
||||
return 0;
|
||||
}
|
||||
@ -252,7 +252,7 @@ get_buffer_height (MetaWaylandSurface *surface)
|
||||
MetaWaylandBuffer *buffer = meta_wayland_surface_get_buffer (surface);
|
||||
|
||||
if (buffer)
|
||||
return cogl_texture_get_height (surface->texture);
|
||||
return meta_multi_texture_get_height (surface->texture);
|
||||
else
|
||||
return 0;
|
||||
}
|
||||
@ -658,7 +658,7 @@ meta_wayland_surface_apply_state (MetaWaylandSurface *surface,
|
||||
}
|
||||
else
|
||||
{
|
||||
cogl_clear_object (&surface->texture);
|
||||
g_clear_object (&surface->texture);
|
||||
}
|
||||
|
||||
/* If the newly attached buffer is going to be accessed directly without
|
||||
@ -1277,7 +1277,7 @@ wl_surface_destructor (struct wl_resource *resource)
|
||||
|
||||
if (surface->buffer_held)
|
||||
meta_wayland_surface_unref_buffer_use_count (surface);
|
||||
g_clear_pointer (&surface->texture, cogl_object_unref);
|
||||
g_clear_object (&surface->texture);
|
||||
g_clear_object (&surface->buffer_ref.buffer);
|
||||
|
||||
g_clear_object (&surface->cached_state);
|
||||
@ -1854,7 +1854,7 @@ meta_wayland_surface_is_shortcuts_inhibited (MetaWaylandSurface *surface,
|
||||
return g_hash_table_contains (surface->shortcut_inhibited_seats, seat);
|
||||
}
|
||||
|
||||
CoglTexture *
|
||||
MetaMultiTexture *
|
||||
meta_wayland_surface_get_texture (MetaWaylandSurface *surface)
|
||||
{
|
||||
return surface->texture;
|
||||
|
@ -153,7 +153,7 @@ struct _MetaWaylandSurface
|
||||
GHashTable *outputs_to_destroy_notify_id;
|
||||
MetaMonitorTransform buffer_transform;
|
||||
|
||||
CoglTexture *texture;
|
||||
MetaMultiTexture *texture;
|
||||
|
||||
/* Buffer reference state. */
|
||||
struct {
|
||||
@ -327,7 +327,7 @@ void meta_wayland_surface_restore_shortcuts (MetaWaylandSurface *
|
||||
gboolean meta_wayland_surface_is_shortcuts_inhibited (MetaWaylandSurface *surface,
|
||||
MetaWaylandSeat *seat);
|
||||
|
||||
CoglTexture * meta_wayland_surface_get_texture (MetaWaylandSurface *surface);
|
||||
MetaMultiTexture * meta_wayland_surface_get_texture (MetaWaylandSurface *surface);
|
||||
|
||||
MetaSurfaceActor * meta_wayland_surface_get_actor (MetaWaylandSurface *surface);
|
||||
|
||||
|
@ -306,6 +306,24 @@ meta_wayland_log_func (const char *fmt,
|
||||
g_free (str);
|
||||
}
|
||||
|
||||
static void
|
||||
add_supported_shm_formats (struct wl_display *display)
|
||||
{
|
||||
guint i;
|
||||
|
||||
/* Note that a Wayland compositor should support WL_SHM_FORMAT_ARGB8888 and
|
||||
* WL_SHM_FORMAT_XRGB8888 by default, so no need to add it here. */
|
||||
static const guint32 SUPPORTED_FORMATS[] = {
|
||||
WL_SHM_FORMAT_NV12,
|
||||
WL_SHM_FORMAT_NV21,
|
||||
};
|
||||
|
||||
for (i = 0; i < G_N_ELEMENTS (SUPPORTED_FORMATS); i++)
|
||||
{
|
||||
wl_display_add_shm_format (display, SUPPORTED_FORMATS[i]);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
meta_wayland_compositor_init (MetaWaylandCompositor *compositor)
|
||||
{
|
||||
@ -318,6 +336,8 @@ meta_wayland_compositor_init (MetaWaylandCompositor *compositor)
|
||||
compositor->wayland_display = wl_display_create ();
|
||||
if (compositor->wayland_display == NULL)
|
||||
g_error ("Failed to create the global wl_display");
|
||||
|
||||
add_supported_shm_formats (compositor->wayland_display);
|
||||
}
|
||||
|
||||
static void
|
||||
|
Loading…
x
Reference in New Issue
Block a user