Compare commits
	
		
			8 Commits
		
	
	
		
			3.37.2
			...
			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