Compare commits
	
		
			8 Commits
		
	
	
		
			main
			...
			wip/nielsd
		
	
	| Author | SHA1 | Date | |
|---|---|---|---|
| 
						 | 
					919ae6b2b7 | ||
| 
						 | 
					1cb7146a2e | ||
| 
						 | 
					b998b543f9 | ||
| 
						 | 
					82149a3caa | ||
| 
						 | 
					ee17ddc18e | ||
| 
						 | 
					f11ca9cfaf | ||
| 
						 | 
					c2e191fe3f | ||
| 
						 | 
					65a3b13b2f | 
@@ -103,6 +103,8 @@ _cogl_texture_2d_create_base (CoglContext *ctx,
 | 
			
		||||
  _cogl_texture_init (tex, ctx, width, height, internal_format, loader,
 | 
			
		||||
                      &cogl_texture_2d_vtable);
 | 
			
		||||
 | 
			
		||||
  g_warning ("cogl_texture_2d_vtable = %p", &cogl_texture_2d_vtable);
 | 
			
		||||
 | 
			
		||||
  tex_2d->mipmaps_dirty = TRUE;
 | 
			
		||||
  tex_2d->auto_mipmap = TRUE;
 | 
			
		||||
  tex_2d->is_get_data_supported = TRUE;
 | 
			
		||||
 
 | 
			
		||||
@@ -47,7 +47,7 @@ option('native_backend',
 | 
			
		||||
 | 
			
		||||
option('remote_desktop',
 | 
			
		||||
  type: 'boolean',
 | 
			
		||||
  value: true,
 | 
			
		||||
  value: false,
 | 
			
		||||
  description: 'Enable remote desktop and screen cast support'
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										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 subtextures.
 | 
			
		||||
 *
 | 
			
		||||
 * #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 subtextures 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_subtextures;
 | 
			
		||||
  CoglTexture **subtextures;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
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_subtexture:
 | 
			
		||||
 * @self: a #MetaMultiTexture
 | 
			
		||||
 *
 | 
			
		||||
 * Returns the number of subtextures for this texture. For example, simple RGB
 | 
			
		||||
 * textures will have a single subtexture, while some more convoluted formats
 | 
			
		||||
 * like NV12 and YUV 4:4:4 can have 2 and 3 subtextures respectively.
 | 
			
		||||
 *
 | 
			
		||||
 * Returns: The number of subtextures in this #MetaMultiTexture.
 | 
			
		||||
 */
 | 
			
		||||
guint
 | 
			
		||||
meta_multi_texture_get_n_subtextures (MetaMultiTexture *self)
 | 
			
		||||
{
 | 
			
		||||
  g_return_val_if_fail (META_IS_MULTI_TEXTURE (self), 0);
 | 
			
		||||
 | 
			
		||||
  return self->n_subtextures;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * meta_multi_texture_get_subtexture:
 | 
			
		||||
 * @self: a #MetaMultiTexture
 | 
			
		||||
 * @index: the index of the subtexture
 | 
			
		||||
 *
 | 
			
		||||
 * Returns the n'th subtexture of the #MetaMultiTexture. Note that it's a
 | 
			
		||||
 * programming error to use with an index larger than
 | 
			
		||||
 * meta_multi_texture_get_n_subtextures().
 | 
			
		||||
 *
 | 
			
		||||
 * Returns: (transfer none): The subtexture at the given @index.
 | 
			
		||||
 */
 | 
			
		||||
CoglTexture *
 | 
			
		||||
meta_multi_texture_get_subtexture (MetaMultiTexture *self, guint index)
 | 
			
		||||
{
 | 
			
		||||
  g_return_val_if_fail (META_IS_MULTI_TEXTURE (self), 0);
 | 
			
		||||
  g_return_val_if_fail (index < self->n_subtextures, NULL);
 | 
			
		||||
 | 
			
		||||
  return self->subtextures[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->subtextures[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->subtextures[0]);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void
 | 
			
		||||
meta_multi_texture_finalize (GObject *object)
 | 
			
		||||
{
 | 
			
		||||
  MetaMultiTexture *self = META_MULTI_TEXTURE (object);
 | 
			
		||||
  int i;
 | 
			
		||||
 | 
			
		||||
  for (i = 0; i < self->n_subtextures; i++)
 | 
			
		||||
    cogl_clear_object (&self->subtextures[i]);
 | 
			
		||||
 | 
			
		||||
  g_free (self->subtextures);
 | 
			
		||||
 | 
			
		||||
  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
 | 
			
		||||
 * @subtextures: (transfer full): The actual subtextures of the texture
 | 
			
		||||
 * @n_subtextures: The number of subtextures
 | 
			
		||||
 *
 | 
			
		||||
 * Creates a #MetaMultiTexture with the given @format. Each of the
 | 
			
		||||
 * #CoglTexture<!-- -->s represents a subtexture.
 | 
			
		||||
 *
 | 
			
		||||
 * Returns: (transfer full): A new #MetaMultiTexture. Use g_object_unref() when
 | 
			
		||||
 * you're done with it.
 | 
			
		||||
 */
 | 
			
		||||
MetaMultiTexture *
 | 
			
		||||
meta_multi_texture_new (MetaMultiTextureFormat format,
 | 
			
		||||
                        CoglTexture          **subtextures,
 | 
			
		||||
                        guint                  n_subtextures)
 | 
			
		||||
{
 | 
			
		||||
  MetaMultiTexture *self;
 | 
			
		||||
 | 
			
		||||
  g_return_val_if_fail (subtextures != NULL, NULL);
 | 
			
		||||
  g_return_val_if_fail (n_subtextures > 0, NULL);
 | 
			
		||||
 | 
			
		||||
  self = g_object_new (META_TYPE_MULTI_TEXTURE, NULL);
 | 
			
		||||
  self->format = format;
 | 
			
		||||
  self->n_subtextures = n_subtextures;
 | 
			
		||||
  self->subtextures = subtextures;
 | 
			
		||||
 | 
			
		||||
  return self;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * meta_multi_texture_new_simple:
 | 
			
		||||
 * @subtexture: (transfer full): The single subtexture of the texture
 | 
			
		||||
 *
 | 
			
		||||
 * Creates a #MetaMultiTexture for a "simple" texture, i.e. with only one
 | 
			
		||||
 * subtexture, 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 *subtexture)
 | 
			
		||||
{
 | 
			
		||||
  MetaMultiTexture *self;
 | 
			
		||||
 | 
			
		||||
  g_return_val_if_fail (subtexture != NULL, NULL);
 | 
			
		||||
 | 
			
		||||
  self = g_object_new (META_TYPE_MULTI_TEXTURE, NULL);
 | 
			
		||||
  self->format = META_MULTI_TEXTURE_FORMAT_SIMPLE;
 | 
			
		||||
  self->n_subtextures = 1;
 | 
			
		||||
  self->subtextures = g_malloc (sizeof (CoglTexture *));
 | 
			
		||||
  self->subtextures[0] = subtexture;
 | 
			
		||||
 | 
			
		||||
  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_subtextures =  %u;\n", self->n_subtextures);
 | 
			
		||||
  g_string_append (str, "  .subtextures   =  {\n");
 | 
			
		||||
 | 
			
		||||
  for (i = 0; i < self->n_subtextures; i++)
 | 
			
		||||
    {
 | 
			
		||||
      CoglTexture *subtexture = self->subtextures[i];
 | 
			
		||||
      CoglPixelFormat subtexture_format = _cogl_texture_get_format (subtexture);
 | 
			
		||||
 | 
			
		||||
      g_string_append_printf (str, "    (%p) { .format = %s },\n",
 | 
			
		||||
                              subtexture,
 | 
			
		||||
                              cogl_pixel_format_to_string (subtexture_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_subtextures;
 | 
			
		||||
  MetaMultiTextureFormat format;
 | 
			
		||||
  CoglPipeline *pipeline;
 | 
			
		||||
  CoglMatrix matrix;
 | 
			
		||||
 | 
			
		||||
  if (stex->base_pipeline)
 | 
			
		||||
    return stex->base_pipeline;
 | 
			
		||||
 | 
			
		||||
  /* We'll add as many layers as there are subtextures in the multi texture,
 | 
			
		||||
   * plus an extra one for the mask */
 | 
			
		||||
  n_subtextures = meta_multi_texture_get_n_subtextures (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_subtextures; 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_subtextures + 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_subtextures; 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_subtextures;
 | 
			
		||||
 | 
			
		||||
  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_subtextures = meta_multi_texture_get_n_subtextures (stex->texture);
 | 
			
		||||
  cogl_pipeline_set_layer_combine (pipeline, n_subtextures,
 | 
			
		||||
                                   "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_subtextures;
 | 
			
		||||
 | 
			
		||||
  ensure_size_valid (stex);
 | 
			
		||||
 | 
			
		||||
@@ -565,8 +597,8 @@ do_paint_content (MetaShapedTexture   *stex,
 | 
			
		||||
    }
 | 
			
		||||
  else
 | 
			
		||||
    {
 | 
			
		||||
      sample_width = cogl_texture_get_width (stex->texture);
 | 
			
		||||
      sample_height = cogl_texture_get_height (stex->texture);
 | 
			
		||||
      sample_width = meta_multi_texture_get_width (stex->texture);
 | 
			
		||||
      sample_height = meta_multi_texture_get_height (stex->texture);
 | 
			
		||||
    }
 | 
			
		||||
  if (meta_monitor_transform_is_rotated (stex->transform))
 | 
			
		||||
    flip_ints (&sample_width, &sample_height);
 | 
			
		||||
@@ -609,6 +641,8 @@ do_paint_content (MetaShapedTexture   *stex,
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
  n_subtextures = meta_multi_texture_get_n_subtextures (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_subtextures; i++)
 | 
			
		||||
            {
 | 
			
		||||
              CoglTexture *subtexture = meta_multi_texture_get_subtexture (paint_tex, i);
 | 
			
		||||
 | 
			
		||||
              cogl_pipeline_set_layer_texture (opaque_pipeline, i, subtexture);
 | 
			
		||||
              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_subtextures, stex->mask_texture);
 | 
			
		||||
          cogl_pipeline_set_layer_filters (blended_pipeline, n_subtextures, 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_subtextures; i++)
 | 
			
		||||
        {
 | 
			
		||||
          CoglTexture *subtexture = meta_multi_texture_get_subtexture (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, subtexture);
 | 
			
		||||
          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_subtextures (multi_texture) > 1)
 | 
			
		||||
    return FALSE;
 | 
			
		||||
 | 
			
		||||
  cogl_texture = meta_multi_texture_get_subtexture (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_subtextures (stex->texture) > 1)
 | 
			
		||||
    return FALSE;
 | 
			
		||||
 | 
			
		||||
  cogl_texture = meta_multi_texture_get_subtexture (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 subtexture at this point */
 | 
			
		||||
  texture = meta_multi_texture_get_subtexture (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_subtexture (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,28 @@ 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_subtextures;
 | 
			
		||||
  GPtrArray *subtextures;
 | 
			
		||||
  CoglTexture **textures;
 | 
			
		||||
 | 
			
		||||
  format = meta_multi_texture_get_format (tower->textures[0]);
 | 
			
		||||
  n_subtextures = meta_multi_texture_format_get_n_planes (format);
 | 
			
		||||
  subtextures = g_ptr_array_new_full (n_subtextures, g_object_unref);
 | 
			
		||||
  for (i = 0; i < n_subtextures; i++)
 | 
			
		||||
    {
 | 
			
		||||
      CoglTexture *texture;
 | 
			
		||||
 | 
			
		||||
       texture = cogl_texture_new_with_size (width, height,
 | 
			
		||||
                                             COGL_TEXTURE_NO_AUTO_MIPMAP,
 | 
			
		||||
                                             TEXTURE_FORMAT);
 | 
			
		||||
       g_ptr_array_add (subtextures, texture);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
  textures = (CoglTexture **) g_ptr_array_free (subtextures, FALSE);
 | 
			
		||||
  tower->textures[level] = meta_multi_texture_new (format,
 | 
			
		||||
                                                   textures,
 | 
			
		||||
                                                   n_subtextures);
 | 
			
		||||
 | 
			
		||||
  tower->invalid[level].x1 = 0;
 | 
			
		||||
  tower->invalid[level].y1 = 0;
 | 
			
		||||
@@ -369,51 +380,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_subtextures = meta_multi_texture_get_n_subtextures (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_subtextures; i++)
 | 
			
		||||
    {
 | 
			
		||||
      g_error_free (catch_error);
 | 
			
		||||
      return;
 | 
			
		||||
      Box *invalid = &tower->invalid[level];
 | 
			
		||||
      CoglTexture *src_subtexture, *dest_subtexture;
 | 
			
		||||
      CoglFramebuffer *fb;
 | 
			
		||||
      GError *catch_error = NULL;
 | 
			
		||||
      CoglPipeline *pipeline;
 | 
			
		||||
 | 
			
		||||
      src_subtexture = meta_multi_texture_get_subtexture (src_tex, i);
 | 
			
		||||
      dest_subtexture = meta_multi_texture_get_subtexture (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_subtexture));
 | 
			
		||||
          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_subtexture);
 | 
			
		||||
 | 
			
		||||
      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 +461,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 +473,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          **subtextures,
 | 
			
		||||
                                                             guint                  n_subtextures);
 | 
			
		||||
 | 
			
		||||
META_EXPORT
 | 
			
		||||
MetaMultiTexture *     meta_multi_texture_new_simple        (CoglTexture *subtexture);
 | 
			
		||||
 | 
			
		||||
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_subtextures (MetaMultiTexture *self);
 | 
			
		||||
 | 
			
		||||
META_EXPORT
 | 
			
		||||
CoglTexture *          meta_multi_texture_get_subtexture    (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,50 @@ 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
 | 
			
		||||
    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,43 +233,51 @@ 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;
 | 
			
		||||
  CoglPixelFormat cogl_format;
 | 
			
		||||
  CoglTextureComponents components;
 | 
			
		||||
  CoglBitmap *bitmap;
 | 
			
		||||
  CoglTexture *new_texture;
 | 
			
		||||
  CoglTexture *new_cogl_tex;
 | 
			
		||||
 | 
			
		||||
  shm_buffer = wl_shm_buffer_get (buffer->resource);
 | 
			
		||||
  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, &cogl_format, &components);
 | 
			
		||||
 | 
			
		||||
  /* We only support "simple" textures for now */
 | 
			
		||||
  g_return_val_if_fail (multi_format == META_MULTI_TEXTURE_FORMAT_SIMPLE, FALSE);
 | 
			
		||||
 | 
			
		||||
  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)
 | 
			
		||||
      meta_multi_texture_get_width (*texture) == width &&
 | 
			
		||||
      meta_multi_texture_get_height (*texture) == height &&
 | 
			
		||||
      meta_multi_texture_get_format (*texture) == multi_format)
 | 
			
		||||
    {
 | 
			
		||||
      buffer->is_y_inverted = TRUE;
 | 
			
		||||
      return TRUE;
 | 
			
		||||
      CoglTexture *cogl_texture = meta_multi_texture_get_subtexture (*texture, 0);
 | 
			
		||||
      if (cogl_texture_get_components (cogl_texture) == components &&
 | 
			
		||||
          _cogl_texture_get_format (cogl_texture) == cogl_format)
 | 
			
		||||
        {
 | 
			
		||||
          buffer->is_y_inverted = TRUE;
 | 
			
		||||
          return TRUE;
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
  cogl_clear_object (texture);
 | 
			
		||||
  g_clear_object (texture);
 | 
			
		||||
 | 
			
		||||
  wl_shm_buffer_begin_access (shm_buffer);
 | 
			
		||||
 | 
			
		||||
  bitmap = cogl_bitmap_new_for_data (cogl_context,
 | 
			
		||||
                                     width, height,
 | 
			
		||||
                                     format,
 | 
			
		||||
                                     cogl_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);
 | 
			
		||||
  new_cogl_tex = COGL_TEXTURE (cogl_texture_2d_new_from_bitmap (bitmap));
 | 
			
		||||
  cogl_texture_set_components (new_cogl_tex, components);
 | 
			
		||||
 | 
			
		||||
  if (!cogl_texture_allocate (new_texture, error))
 | 
			
		||||
  if (!cogl_texture_allocate (new_cogl_tex, error))
 | 
			
		||||
    {
 | 
			
		||||
      g_clear_pointer (&new_texture, cogl_object_unref);
 | 
			
		||||
      g_clear_pointer (&new_cogl_tex, cogl_object_unref);
 | 
			
		||||
      if (g_error_matches (*error, COGL_TEXTURE_ERROR, COGL_TEXTURE_ERROR_SIZE))
 | 
			
		||||
        {
 | 
			
		||||
          CoglTexture2DSliced *texture_sliced;
 | 
			
		||||
@@ -275,11 +287,11 @@ shm_buffer_attach (MetaWaylandBuffer  *buffer,
 | 
			
		||||
          texture_sliced =
 | 
			
		||||
            cogl_texture_2d_sliced_new_from_bitmap (bitmap,
 | 
			
		||||
                                                    COGL_TEXTURE_MAX_WASTE);
 | 
			
		||||
          new_texture = COGL_TEXTURE (texture_sliced);
 | 
			
		||||
          cogl_texture_set_components (new_texture, components);
 | 
			
		||||
          new_cogl_tex = COGL_TEXTURE (texture_sliced);
 | 
			
		||||
          cogl_texture_set_components (new_cogl_tex, components);
 | 
			
		||||
 | 
			
		||||
          if (!cogl_texture_allocate (new_texture, error))
 | 
			
		||||
            g_clear_pointer (&new_texture, cogl_object_unref);
 | 
			
		||||
          if (!cogl_texture_allocate (new_cogl_tex, error))
 | 
			
		||||
            g_clear_pointer (&new_cogl_tex, cogl_object_unref);
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
@@ -287,10 +299,10 @@ shm_buffer_attach (MetaWaylandBuffer  *buffer,
 | 
			
		||||
 | 
			
		||||
  wl_shm_buffer_end_access (shm_buffer);
 | 
			
		||||
 | 
			
		||||
  if (!new_texture)
 | 
			
		||||
  if (!new_cogl_tex)
 | 
			
		||||
    return FALSE;
 | 
			
		||||
 | 
			
		||||
  *texture = new_texture;
 | 
			
		||||
  *texture = meta_multi_texture_new_simple (new_cogl_tex);
 | 
			
		||||
  buffer->is_y_inverted = TRUE;
 | 
			
		||||
 | 
			
		||||
  return TRUE;
 | 
			
		||||
@@ -298,7 +310,7 @@ shm_buffer_attach (MetaWaylandBuffer  *buffer,
 | 
			
		||||
 | 
			
		||||
static gboolean
 | 
			
		||||
egl_image_buffer_attach (MetaWaylandBuffer  *buffer,
 | 
			
		||||
                         CoglTexture       **texture,
 | 
			
		||||
                         MetaMultiTexture  **texture,
 | 
			
		||||
                         GError            **error)
 | 
			
		||||
{
 | 
			
		||||
  MetaBackend *backend = meta_get_backend ();
 | 
			
		||||
@@ -307,15 +319,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_subtextures;
 | 
			
		||||
  GPtrArray *subtextures;
 | 
			
		||||
 | 
			
		||||
  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 +351,7 @@ egl_image_buffer_attach (MetaWaylandBuffer  *buffer,
 | 
			
		||||
                                      NULL))
 | 
			
		||||
    y_inverted = EGL_TRUE;
 | 
			
		||||
 | 
			
		||||
  /* Query the color format */
 | 
			
		||||
  switch (format)
 | 
			
		||||
    {
 | 
			
		||||
    case EGL_TEXTURE_RGB:
 | 
			
		||||
@@ -347,6 +360,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 subtexture
 | 
			
		||||
       * 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 subtexture
 | 
			
		||||
       * 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 +377,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 subtexture in the final texture */
 | 
			
		||||
  n_subtextures = meta_multi_texture_format_get_n_planes (multi_format);
 | 
			
		||||
  subtextures = g_ptr_array_new_full (n_subtextures, 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_subtextures; 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 subtexture */
 | 
			
		||||
      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 (subtextures, COGL_TEXTURE (texture_2d));
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
  buffer->egl_image.texture =
 | 
			
		||||
      meta_multi_texture_new (multi_format,
 | 
			
		||||
                              (CoglTexture**) g_ptr_array_free (subtextures, FALSE),
 | 
			
		||||
                              n_subtextures);
 | 
			
		||||
  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 (subtextures, 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 +450,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 +460,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 +478,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,21 +545,24 @@ 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;
 | 
			
		||||
  CoglPixelFormat cogl_format;
 | 
			
		||||
  CoglTexture *cogl_texture;
 | 
			
		||||
 | 
			
		||||
  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);
 | 
			
		||||
  shm_buffer_get_format (shm_buffer, &multi_format, &cogl_format, NULL);
 | 
			
		||||
  g_return_val_if_fail (multi_format == META_MULTI_TEXTURE_FORMAT_SIMPLE, FALSE);
 | 
			
		||||
  cogl_texture = meta_multi_texture_get_subtexture (texture, 0);
 | 
			
		||||
 | 
			
		||||
  wl_shm_buffer_begin_access (shm_buffer);
 | 
			
		||||
 | 
			
		||||
@@ -518,12 +573,12 @@ process_shm_buffer_damage (MetaWaylandBuffer *buffer,
 | 
			
		||||
      cairo_rectangle_int_t rect;
 | 
			
		||||
      int bpp;
 | 
			
		||||
 | 
			
		||||
      bpp = cogl_pixel_format_get_bytes_per_pixel (format, 0);
 | 
			
		||||
      bpp = cogl_pixel_format_get_bytes_per_pixel (cogl_format, 0);
 | 
			
		||||
      cairo_region_get_rectangle (region, i, &rect);
 | 
			
		||||
 | 
			
		||||
      if (!_cogl_texture_set_region (texture,
 | 
			
		||||
      if (!_cogl_texture_set_region (cogl_texture,
 | 
			
		||||
                                     rect.width, rect.height,
 | 
			
		||||
                                     format,
 | 
			
		||||
                                     cogl_format,
 | 
			
		||||
                                     stride,
 | 
			
		||||
                                     data + rect.x * bpp + rect.y * stride,
 | 
			
		||||
                                     rect.x, rect.y,
 | 
			
		||||
@@ -542,7 +597,7 @@ process_shm_buffer_damage (MetaWaylandBuffer *buffer,
 | 
			
		||||
 | 
			
		||||
void
 | 
			
		||||
meta_wayland_buffer_process_damage (MetaWaylandBuffer *buffer,
 | 
			
		||||
                                    CoglTexture       *texture,
 | 
			
		||||
                                    MetaMultiTexture  *texture,
 | 
			
		||||
                                    cairo_region_t    *region)
 | 
			
		||||
{
 | 
			
		||||
  gboolean res = FALSE;
 | 
			
		||||
@@ -582,12 +637,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 */
 | 
			
		||||
 
 | 
			
		||||
@@ -58,16 +58,20 @@ update_cursor_sprite_texture (MetaWaylandCursorSurface *cursor_surface)
 | 
			
		||||
  MetaWaylandSurface *surface =
 | 
			
		||||
    meta_wayland_surface_role_get_surface (META_WAYLAND_SURFACE_ROLE (cursor_surface));
 | 
			
		||||
  MetaCursorSprite *cursor_sprite = META_CURSOR_SPRITE (priv->cursor_sprite);
 | 
			
		||||
  CoglTexture *texture;
 | 
			
		||||
  MetaMultiTexture *texture;
 | 
			
		||||
 | 
			
		||||
  if (!priv->cursor_renderer)
 | 
			
		||||
    return;
 | 
			
		||||
 | 
			
		||||
  texture = meta_wayland_surface_get_texture (surface);
 | 
			
		||||
 | 
			
		||||
  if (texture)
 | 
			
		||||
    {
 | 
			
		||||
      /* We don't support complex textures for cursors */
 | 
			
		||||
      g_return_if_fail (meta_multi_texture_is_simple (texture));
 | 
			
		||||
 | 
			
		||||
      meta_cursor_sprite_set_texture (cursor_sprite,
 | 
			
		||||
                                      texture,
 | 
			
		||||
                                      meta_multi_texture_get_subtexture (texture, 0),
 | 
			
		||||
                                      priv->hot_x * surface->scale,
 | 
			
		||||
                                      priv->hot_y * surface->scale);
 | 
			
		||||
    }
 | 
			
		||||
 
 | 
			
		||||
@@ -87,10 +87,12 @@ meta_wayland_dma_buf_realize_texture (MetaWaylandBuffer  *buffer,
 | 
			
		||||
  MetaWaylandDmaBufBuffer *dma_buf = buffer->dma_buf.dma_buf;
 | 
			
		||||
  uint32_t n_planes;
 | 
			
		||||
  uint64_t modifiers[META_WAYLAND_DMA_BUF_MAX_FDS];
 | 
			
		||||
  CoglPixelFormat cogl_format;
 | 
			
		||||
  MetaMultiTextureFormat multi_format = META_MULTI_TEXTURE_FORMAT_SIMPLE;
 | 
			
		||||
  CoglPixelFormat subformats[META_WAYLAND_DMA_BUF_MAX_FDS] = { COGL_PIXEL_FORMAT_ANY, };
 | 
			
		||||
  EGLImageKHR egl_image;
 | 
			
		||||
  CoglEglImageFlags flags;
 | 
			
		||||
  CoglTexture2D *texture;
 | 
			
		||||
  CoglTexture2D *cogl_texture;
 | 
			
		||||
  GPtrArray *planes;
 | 
			
		||||
 | 
			
		||||
  if (buffer->dma_buf.texture)
 | 
			
		||||
    return TRUE;
 | 
			
		||||
@@ -105,16 +107,55 @@ meta_wayland_dma_buf_realize_texture (MetaWaylandBuffer  *buffer,
 | 
			
		||||
     * and access the buffer memory at all.
 | 
			
		||||
     */
 | 
			
		||||
    case DRM_FORMAT_XRGB8888:
 | 
			
		||||
      cogl_format = COGL_PIXEL_FORMAT_RGB_888;
 | 
			
		||||
      subformats[0] = COGL_PIXEL_FORMAT_RGB_888;
 | 
			
		||||
      break;
 | 
			
		||||
    case DRM_FORMAT_ARGB8888:
 | 
			
		||||
      cogl_format = COGL_PIXEL_FORMAT_ARGB_8888_PRE;
 | 
			
		||||
      subformats[0] = COGL_PIXEL_FORMAT_ARGB_8888_PRE;
 | 
			
		||||
      break;
 | 
			
		||||
    case DRM_FORMAT_ARGB2101010:
 | 
			
		||||
      cogl_format = COGL_PIXEL_FORMAT_ARGB_2101010_PRE;
 | 
			
		||||
      subformats[0] = COGL_PIXEL_FORMAT_ARGB_2101010_PRE;
 | 
			
		||||
      break;
 | 
			
		||||
    case DRM_FORMAT_RGB565:
 | 
			
		||||
      cogl_format = COGL_PIXEL_FORMAT_RGB_565;
 | 
			
		||||
      subformats[0] = COGL_PIXEL_FORMAT_RGB_565;
 | 
			
		||||
      break;
 | 
			
		||||
    case DRM_FORMAT_YUYV:
 | 
			
		||||
      multi_format = META_MULTI_TEXTURE_FORMAT_YUYV;
 | 
			
		||||
      break;
 | 
			
		||||
    case DRM_FORMAT_NV12:
 | 
			
		||||
      multi_format = META_MULTI_TEXTURE_FORMAT_NV12;
 | 
			
		||||
      break;
 | 
			
		||||
    case DRM_FORMAT_NV21:
 | 
			
		||||
      multi_format = META_MULTI_TEXTURE_FORMAT_NV21;
 | 
			
		||||
      break;
 | 
			
		||||
    case DRM_FORMAT_YUV410:
 | 
			
		||||
      multi_format = META_MULTI_TEXTURE_FORMAT_YUV410;
 | 
			
		||||
      break;
 | 
			
		||||
    case DRM_FORMAT_YVU410:
 | 
			
		||||
      multi_format = META_MULTI_TEXTURE_FORMAT_YVU410;
 | 
			
		||||
      break;
 | 
			
		||||
    case DRM_FORMAT_YUV411:
 | 
			
		||||
      multi_format = META_MULTI_TEXTURE_FORMAT_YUV411;
 | 
			
		||||
      break;
 | 
			
		||||
    case DRM_FORMAT_YVU411:
 | 
			
		||||
      multi_format = META_MULTI_TEXTURE_FORMAT_YVU411;
 | 
			
		||||
      break;
 | 
			
		||||
    case DRM_FORMAT_YUV420:
 | 
			
		||||
      multi_format = META_MULTI_TEXTURE_FORMAT_YUV420;
 | 
			
		||||
      break;
 | 
			
		||||
    case DRM_FORMAT_YVU420:
 | 
			
		||||
      multi_format = META_MULTI_TEXTURE_FORMAT_YVU420;
 | 
			
		||||
      break;
 | 
			
		||||
    case DRM_FORMAT_YUV422:
 | 
			
		||||
      multi_format = META_MULTI_TEXTURE_FORMAT_YUV422;
 | 
			
		||||
      break;
 | 
			
		||||
    case DRM_FORMAT_YVU422:
 | 
			
		||||
      multi_format = META_MULTI_TEXTURE_FORMAT_YVU422;
 | 
			
		||||
      break;
 | 
			
		||||
    case DRM_FORMAT_YUV444:
 | 
			
		||||
      multi_format = META_MULTI_TEXTURE_FORMAT_YUV444;
 | 
			
		||||
      break;
 | 
			
		||||
    case DRM_FORMAT_YVU444:
 | 
			
		||||
      multi_format = META_MULTI_TEXTURE_FORMAT_YVU444;
 | 
			
		||||
      break;
 | 
			
		||||
    default:
 | 
			
		||||
      g_set_error (error, G_IO_ERROR,
 | 
			
		||||
@@ -123,6 +164,9 @@ meta_wayland_dma_buf_realize_texture (MetaWaylandBuffer  *buffer,
 | 
			
		||||
      return FALSE;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
  if (multi_format != META_MULTI_TEXTURE_FORMAT_SIMPLE)
 | 
			
		||||
    meta_multi_texture_format_get_subformats (multi_format, subformats);
 | 
			
		||||
 | 
			
		||||
  for (n_planes = 0; n_planes < META_WAYLAND_DMA_BUF_MAX_FDS; n_planes++)
 | 
			
		||||
    {
 | 
			
		||||
      if (dma_buf->fds[n_planes] < 0)
 | 
			
		||||
@@ -131,6 +175,8 @@ meta_wayland_dma_buf_realize_texture (MetaWaylandBuffer  *buffer,
 | 
			
		||||
      modifiers[n_planes] = dma_buf->drm_modifier;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
  planes = g_ptr_array_new_full (n_planes, cogl_object_unref);
 | 
			
		||||
 | 
			
		||||
  egl_image = meta_egl_create_dmabuf_image (egl,
 | 
			
		||||
                                            egl_display,
 | 
			
		||||
                                            dma_buf->width,
 | 
			
		||||
@@ -143,23 +189,36 @@ meta_wayland_dma_buf_realize_texture (MetaWaylandBuffer  *buffer,
 | 
			
		||||
                                            modifiers,
 | 
			
		||||
                                            error);
 | 
			
		||||
  if (egl_image == EGL_NO_IMAGE_KHR)
 | 
			
		||||
    return FALSE;
 | 
			
		||||
    {
 | 
			
		||||
      g_debug ("Couldn't create EGLImage from DMA-buf: %s", (*error)->message);
 | 
			
		||||
      return FALSE;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
  /* FIXME: at this point, we might want to try importing each plane separately */
 | 
			
		||||
 | 
			
		||||
  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,
 | 
			
		||||
                                                     subformats[0],
 | 
			
		||||
                                                     egl_image,
 | 
			
		||||
                                                     flags,
 | 
			
		||||
                                                     error);
 | 
			
		||||
 | 
			
		||||
  meta_egl_destroy_image (egl, egl_display, egl_image, NULL);
 | 
			
		||||
 | 
			
		||||
  if (!texture)
 | 
			
		||||
    return FALSE;
 | 
			
		||||
  if (cogl_texture == NULL)
 | 
			
		||||
    {
 | 
			
		||||
      g_debug ("Couldn't upload DMA-buf EGLImage: %s", *error? (*error)->message : "");
 | 
			
		||||
      return FALSE;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
  buffer->dma_buf.texture = COGL_TEXTURE (texture);
 | 
			
		||||
  g_ptr_array_add (planes, COGL_TEXTURE (cogl_texture));
 | 
			
		||||
 | 
			
		||||
  buffer->dma_buf.texture =
 | 
			
		||||
      meta_multi_texture_new (multi_format,
 | 
			
		||||
                              (CoglTexture**) g_ptr_array_free (planes, FALSE),
 | 
			
		||||
                              n_planes);
 | 
			
		||||
  buffer->is_y_inverted = dma_buf->is_y_inverted;
 | 
			
		||||
 | 
			
		||||
  return TRUE;
 | 
			
		||||
@@ -167,14 +226,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;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@@ -530,6 +589,7 @@ dma_buf_bind (struct wl_client *client,
 | 
			
		||||
  send_modifiers (resource, DRM_FORMAT_XRGB8888);
 | 
			
		||||
  send_modifiers (resource, DRM_FORMAT_ARGB2101010);
 | 
			
		||||
  send_modifiers (resource, DRM_FORMAT_RGB565);
 | 
			
		||||
  send_modifiers (resource, DRM_FORMAT_NV12);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 
 | 
			
		||||
@@ -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);
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user