You can not select more than 25 topics
			Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
		
		
		
		
		
			
		
			
				
					
					
						
							516 lines
						
					
					
						
							11 KiB
						
					
					
				
			
		
		
	
	
							516 lines
						
					
					
						
							11 KiB
						
					
					
				/*
 | 
						|
 * Copyright © 2016, 2019 Collabora, Ltd.
 | 
						|
 * Copyright (c) 2018 DisplayLink (UK) Ltd.
 | 
						|
 *
 | 
						|
 * Permission is hereby granted, free of charge, to any person obtaining a
 | 
						|
 * copy of this software and associated documentation files (the "Software"),
 | 
						|
 * to deal in the Software without restriction, including without limitation
 | 
						|
 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
 | 
						|
 * and/or sell copies of the Software, and to permit persons to whom the
 | 
						|
 * Software is furnished to do so, subject to the following conditions:
 | 
						|
 *
 | 
						|
 * The above copyright notice and this permission notice (including the next
 | 
						|
 * paragraph) shall be included in all copies or substantial portions of the
 | 
						|
 * Software.
 | 
						|
 *
 | 
						|
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 | 
						|
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 | 
						|
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
 | 
						|
 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 | 
						|
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
 | 
						|
 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
 | 
						|
 * DEALINGS IN THE SOFTWARE.
 | 
						|
 *
 | 
						|
 * Author: Daniel Stone <daniels@collabora.com>
 | 
						|
 */
 | 
						|
 | 
						|
#include "config.h"
 | 
						|
 | 
						|
#include <endian.h>
 | 
						|
#include <inttypes.h>
 | 
						|
#include <stdbool.h>
 | 
						|
#include <unistd.h>
 | 
						|
#include <string.h>
 | 
						|
#include <drm_fourcc.h>
 | 
						|
#include <wayland-client-protocol.h>
 | 
						|
 | 
						|
#include "shared/helpers.h"
 | 
						|
#include "wayland-util.h"
 | 
						|
#include "pixel-formats.h"
 | 
						|
 | 
						|
#if ENABLE_EGL
 | 
						|
#include <EGL/egl.h>
 | 
						|
#include <EGL/eglext.h>
 | 
						|
#include <GLES2/gl2.h>
 | 
						|
#include <GLES2/gl2ext.h>
 | 
						|
#define GL_FORMAT(fmt) .gl_format = (fmt)
 | 
						|
#define GL_TYPE(type) .gl_type = (type)
 | 
						|
#define SAMPLER_TYPE(type) .sampler_type = (type)
 | 
						|
#else
 | 
						|
#define GL_FORMAT(fmt) .gl_format = 0
 | 
						|
#define GL_TYPE(type) .gl_type = 0
 | 
						|
#define SAMPLER_TYPE(type) .sampler_type = 0
 | 
						|
#endif
 | 
						|
 | 
						|
#define DRM_FORMAT(f) .format = DRM_FORMAT_ ## f, .drm_format_name = #f
 | 
						|
#define BITS_RGBA_FIXED(r_, g_, b_, a_) \
 | 
						|
	.bits.r = r_, \
 | 
						|
	.bits.g = g_, \
 | 
						|
	.bits.b = b_, \
 | 
						|
	.bits.a = a_, \
 | 
						|
	.component_type = PIXEL_COMPONENT_TYPE_FIXED
 | 
						|
 | 
						|
#include "shared/weston-egl-ext.h"
 | 
						|
 | 
						|
/**
 | 
						|
 * Table of DRM formats supported by Weston; RGB, ARGB and YUV formats are
 | 
						|
 * supported. Indexed/greyscale formats, and formats not containing complete
 | 
						|
 * colour channels, are not supported.
 | 
						|
 */
 | 
						|
static const struct pixel_format_info pixel_format_table[] = {
 | 
						|
	{
 | 
						|
		DRM_FORMAT(XRGB4444),
 | 
						|
		BITS_RGBA_FIXED(4, 4, 4, 0),
 | 
						|
	},
 | 
						|
	{
 | 
						|
		DRM_FORMAT(ARGB4444),
 | 
						|
		BITS_RGBA_FIXED(4, 4, 4, 4),
 | 
						|
		.opaque_substitute = DRM_FORMAT_XRGB4444,
 | 
						|
	},
 | 
						|
	{
 | 
						|
		DRM_FORMAT(XBGR4444),
 | 
						|
		BITS_RGBA_FIXED(4, 4, 4, 0),
 | 
						|
	},
 | 
						|
	{
 | 
						|
		DRM_FORMAT(ABGR4444),
 | 
						|
		BITS_RGBA_FIXED(4, 4, 4, 4),
 | 
						|
		.opaque_substitute = DRM_FORMAT_XBGR4444,
 | 
						|
	},
 | 
						|
	{
 | 
						|
		DRM_FORMAT(RGBX4444),
 | 
						|
		BITS_RGBA_FIXED(4, 4, 4, 0),
 | 
						|
# if __BYTE_ORDER == __LITTLE_ENDIAN
 | 
						|
		GL_FORMAT(GL_RGBA),
 | 
						|
		GL_TYPE(GL_UNSIGNED_SHORT_4_4_4_4),
 | 
						|
#endif
 | 
						|
	},
 | 
						|
	{
 | 
						|
		DRM_FORMAT(RGBA4444),
 | 
						|
		BITS_RGBA_FIXED(4, 4, 4, 4),
 | 
						|
		.opaque_substitute = DRM_FORMAT_RGBX4444,
 | 
						|
# if __BYTE_ORDER == __LITTLE_ENDIAN
 | 
						|
		GL_FORMAT(GL_RGBA),
 | 
						|
		GL_TYPE(GL_UNSIGNED_SHORT_4_4_4_4),
 | 
						|
#endif
 | 
						|
	},
 | 
						|
	{
 | 
						|
		DRM_FORMAT(BGRX4444),
 | 
						|
		BITS_RGBA_FIXED(4, 4, 4, 0),
 | 
						|
	},
 | 
						|
	{
 | 
						|
		DRM_FORMAT(BGRA4444),
 | 
						|
		BITS_RGBA_FIXED(4, 4, 4, 4),
 | 
						|
		.opaque_substitute = DRM_FORMAT_BGRX4444,
 | 
						|
	},
 | 
						|
	{
 | 
						|
		DRM_FORMAT(XRGB1555),
 | 
						|
		BITS_RGBA_FIXED(5, 5, 5, 0),
 | 
						|
		.depth = 15,
 | 
						|
		.bpp = 16,
 | 
						|
	},
 | 
						|
	{
 | 
						|
		DRM_FORMAT(ARGB1555),
 | 
						|
		BITS_RGBA_FIXED(5, 5, 5, 1),
 | 
						|
		.opaque_substitute = DRM_FORMAT_XRGB1555,
 | 
						|
	},
 | 
						|
	{
 | 
						|
		DRM_FORMAT(XBGR1555),
 | 
						|
		BITS_RGBA_FIXED(5, 5, 5, 0),
 | 
						|
	},
 | 
						|
	{
 | 
						|
		DRM_FORMAT(ABGR1555),
 | 
						|
		BITS_RGBA_FIXED(5, 5, 5, 1),
 | 
						|
		.opaque_substitute = DRM_FORMAT_XBGR1555,
 | 
						|
	},
 | 
						|
	{
 | 
						|
		DRM_FORMAT(RGBX5551),
 | 
						|
		BITS_RGBA_FIXED(5, 5, 5, 0),
 | 
						|
# if __BYTE_ORDER == __LITTLE_ENDIAN
 | 
						|
		GL_FORMAT(GL_RGBA),
 | 
						|
		GL_TYPE(GL_UNSIGNED_SHORT_5_5_5_1),
 | 
						|
#endif
 | 
						|
	},
 | 
						|
	{
 | 
						|
		DRM_FORMAT(RGBA5551),
 | 
						|
		BITS_RGBA_FIXED(5, 5, 5, 1),
 | 
						|
		.opaque_substitute = DRM_FORMAT_RGBX5551,
 | 
						|
# if __BYTE_ORDER == __LITTLE_ENDIAN
 | 
						|
		GL_FORMAT(GL_RGBA),
 | 
						|
		GL_TYPE(GL_UNSIGNED_SHORT_5_5_5_1),
 | 
						|
#endif
 | 
						|
	},
 | 
						|
	{
 | 
						|
		DRM_FORMAT(BGRX5551),
 | 
						|
		BITS_RGBA_FIXED(5, 5, 5, 0),
 | 
						|
	},
 | 
						|
	{
 | 
						|
		DRM_FORMAT(BGRA5551),
 | 
						|
		BITS_RGBA_FIXED(5, 5, 5, 1),
 | 
						|
		.opaque_substitute = DRM_FORMAT_BGRX5551,
 | 
						|
	},
 | 
						|
	{
 | 
						|
		DRM_FORMAT(RGB565),
 | 
						|
		BITS_RGBA_FIXED(5, 6, 5, 0),
 | 
						|
		.depth = 16,
 | 
						|
		.bpp = 16,
 | 
						|
# if __BYTE_ORDER == __LITTLE_ENDIAN
 | 
						|
		GL_FORMAT(GL_RGB),
 | 
						|
		GL_TYPE(GL_UNSIGNED_SHORT_5_6_5),
 | 
						|
#endif
 | 
						|
	},
 | 
						|
	{
 | 
						|
		DRM_FORMAT(BGR565),
 | 
						|
		BITS_RGBA_FIXED(5, 6, 5, 0),
 | 
						|
	},
 | 
						|
	{
 | 
						|
		DRM_FORMAT(RGB888),
 | 
						|
		BITS_RGBA_FIXED(8, 8, 8, 0),
 | 
						|
	},
 | 
						|
	{
 | 
						|
		DRM_FORMAT(BGR888),
 | 
						|
		BITS_RGBA_FIXED(8, 8, 8, 0),
 | 
						|
		GL_FORMAT(GL_RGB),
 | 
						|
		GL_TYPE(GL_UNSIGNED_BYTE),
 | 
						|
	},
 | 
						|
	{
 | 
						|
		DRM_FORMAT(XRGB8888),
 | 
						|
		BITS_RGBA_FIXED(8, 8, 8, 0),
 | 
						|
		.depth = 24,
 | 
						|
		.bpp = 32,
 | 
						|
		GL_FORMAT(GL_BGRA_EXT),
 | 
						|
		GL_TYPE(GL_UNSIGNED_BYTE),
 | 
						|
	},
 | 
						|
	{
 | 
						|
		DRM_FORMAT(ARGB8888),
 | 
						|
		BITS_RGBA_FIXED(8, 8, 8, 8),
 | 
						|
		.opaque_substitute = DRM_FORMAT_XRGB8888,
 | 
						|
		.depth = 32,
 | 
						|
		.bpp = 32,
 | 
						|
		GL_FORMAT(GL_BGRA_EXT),
 | 
						|
		GL_TYPE(GL_UNSIGNED_BYTE),
 | 
						|
	},
 | 
						|
	{
 | 
						|
		DRM_FORMAT(XBGR8888),
 | 
						|
		BITS_RGBA_FIXED(8, 8, 8, 0),
 | 
						|
		GL_FORMAT(GL_RGBA),
 | 
						|
		GL_TYPE(GL_UNSIGNED_BYTE),
 | 
						|
	},
 | 
						|
	{
 | 
						|
		DRM_FORMAT(ABGR8888),
 | 
						|
		BITS_RGBA_FIXED(8, 8, 8, 8),
 | 
						|
		.opaque_substitute = DRM_FORMAT_XBGR8888,
 | 
						|
		GL_FORMAT(GL_RGBA),
 | 
						|
		GL_TYPE(GL_UNSIGNED_BYTE),
 | 
						|
	},
 | 
						|
	{
 | 
						|
		DRM_FORMAT(RGBX8888),
 | 
						|
		BITS_RGBA_FIXED(8, 8, 8, 0),
 | 
						|
	},
 | 
						|
	{
 | 
						|
		DRM_FORMAT(RGBA8888),
 | 
						|
		BITS_RGBA_FIXED(8, 8, 8, 8),
 | 
						|
		.opaque_substitute = DRM_FORMAT_RGBX8888,
 | 
						|
	},
 | 
						|
	{
 | 
						|
		DRM_FORMAT(BGRX8888),
 | 
						|
		BITS_RGBA_FIXED(8, 8, 8, 0),
 | 
						|
	},
 | 
						|
	{
 | 
						|
		DRM_FORMAT(BGRA8888),
 | 
						|
		BITS_RGBA_FIXED(8, 8, 8, 8),
 | 
						|
		.opaque_substitute = DRM_FORMAT_BGRX8888,
 | 
						|
	},
 | 
						|
	{
 | 
						|
		DRM_FORMAT(XRGB2101010),
 | 
						|
		BITS_RGBA_FIXED(10, 10, 10, 0),
 | 
						|
		.depth = 30,
 | 
						|
		.bpp = 32,
 | 
						|
	},
 | 
						|
	{
 | 
						|
		DRM_FORMAT(ARGB2101010),
 | 
						|
		BITS_RGBA_FIXED(10, 10, 10, 2),
 | 
						|
		.opaque_substitute = DRM_FORMAT_XRGB2101010,
 | 
						|
	},
 | 
						|
	{
 | 
						|
		DRM_FORMAT(XBGR2101010),
 | 
						|
		BITS_RGBA_FIXED(10, 10, 10, 0),
 | 
						|
# if __BYTE_ORDER == __LITTLE_ENDIAN
 | 
						|
		GL_FORMAT(GL_RGBA),
 | 
						|
		GL_TYPE(GL_UNSIGNED_INT_2_10_10_10_REV_EXT),
 | 
						|
#endif
 | 
						|
	},
 | 
						|
	{
 | 
						|
		DRM_FORMAT(ABGR2101010),
 | 
						|
		BITS_RGBA_FIXED(10, 10, 10, 2),
 | 
						|
		.opaque_substitute = DRM_FORMAT_XBGR2101010,
 | 
						|
# if __BYTE_ORDER == __LITTLE_ENDIAN
 | 
						|
		GL_FORMAT(GL_RGBA),
 | 
						|
		GL_TYPE(GL_UNSIGNED_INT_2_10_10_10_REV_EXT),
 | 
						|
#endif
 | 
						|
	},
 | 
						|
	{
 | 
						|
		DRM_FORMAT(RGBX1010102),
 | 
						|
		BITS_RGBA_FIXED(10, 10, 10, 0),
 | 
						|
	},
 | 
						|
	{
 | 
						|
		DRM_FORMAT(RGBA1010102),
 | 
						|
		BITS_RGBA_FIXED(10, 10, 10, 2),
 | 
						|
		.opaque_substitute = DRM_FORMAT_RGBX1010102,
 | 
						|
	},
 | 
						|
	{
 | 
						|
		DRM_FORMAT(BGRX1010102),
 | 
						|
		BITS_RGBA_FIXED(10, 10, 10, 0),
 | 
						|
	},
 | 
						|
	{
 | 
						|
		DRM_FORMAT(BGRA1010102),
 | 
						|
		BITS_RGBA_FIXED(10, 10, 10, 2),
 | 
						|
		.opaque_substitute = DRM_FORMAT_BGRX1010102,
 | 
						|
	},
 | 
						|
	{
 | 
						|
		DRM_FORMAT(YUYV),
 | 
						|
		SAMPLER_TYPE(EGL_TEXTURE_Y_XUXV_WL),
 | 
						|
		.num_planes = 1,
 | 
						|
		.hsub = 2,
 | 
						|
	},
 | 
						|
	{
 | 
						|
		DRM_FORMAT(YVYU),
 | 
						|
		SAMPLER_TYPE(EGL_TEXTURE_Y_XUXV_WL),
 | 
						|
		.num_planes = 1,
 | 
						|
		.chroma_order = ORDER_VU,
 | 
						|
		.hsub = 2,
 | 
						|
	},
 | 
						|
	{
 | 
						|
		DRM_FORMAT(UYVY),
 | 
						|
		SAMPLER_TYPE(EGL_TEXTURE_Y_XUXV_WL),
 | 
						|
		.num_planes = 1,
 | 
						|
		.luma_chroma_order = ORDER_CHROMA_LUMA,
 | 
						|
		.hsub = 2,
 | 
						|
	},
 | 
						|
	{
 | 
						|
		DRM_FORMAT(VYUY),
 | 
						|
		SAMPLER_TYPE(EGL_TEXTURE_Y_XUXV_WL),
 | 
						|
		.num_planes = 1,
 | 
						|
		.luma_chroma_order = ORDER_CHROMA_LUMA,
 | 
						|
		.chroma_order = ORDER_VU,
 | 
						|
		.hsub = 2,
 | 
						|
	},
 | 
						|
	{
 | 
						|
		DRM_FORMAT(NV12),
 | 
						|
		SAMPLER_TYPE(EGL_TEXTURE_Y_UV_WL),
 | 
						|
		.num_planes = 2,
 | 
						|
		.hsub = 2,
 | 
						|
		.vsub = 2,
 | 
						|
	},
 | 
						|
	{
 | 
						|
		DRM_FORMAT(NV21),
 | 
						|
		SAMPLER_TYPE(EGL_TEXTURE_Y_UV_WL),
 | 
						|
		.num_planes = 2,
 | 
						|
		.chroma_order = ORDER_VU,
 | 
						|
		.hsub = 2,
 | 
						|
		.vsub = 2,
 | 
						|
	},
 | 
						|
	{
 | 
						|
		DRM_FORMAT(NV16),
 | 
						|
		SAMPLER_TYPE(EGL_TEXTURE_Y_UV_WL),
 | 
						|
		.num_planes = 2,
 | 
						|
		.hsub = 2,
 | 
						|
		.vsub = 1,
 | 
						|
	},
 | 
						|
	{
 | 
						|
		DRM_FORMAT(NV61),
 | 
						|
		SAMPLER_TYPE(EGL_TEXTURE_Y_UV_WL),
 | 
						|
		.num_planes = 2,
 | 
						|
		.chroma_order = ORDER_VU,
 | 
						|
		.hsub = 2,
 | 
						|
		.vsub = 1,
 | 
						|
	},
 | 
						|
	{
 | 
						|
		DRM_FORMAT(NV24),
 | 
						|
		SAMPLER_TYPE(EGL_TEXTURE_Y_UV_WL),
 | 
						|
		.num_planes = 2,
 | 
						|
	},
 | 
						|
	{
 | 
						|
		DRM_FORMAT(NV42),
 | 
						|
		SAMPLER_TYPE(EGL_TEXTURE_Y_UV_WL),
 | 
						|
		.num_planes = 2,
 | 
						|
		.chroma_order = ORDER_VU,
 | 
						|
	},
 | 
						|
	{
 | 
						|
		DRM_FORMAT(YUV410),
 | 
						|
		SAMPLER_TYPE(EGL_TEXTURE_Y_U_V_WL),
 | 
						|
		.num_planes = 3,
 | 
						|
		.hsub = 4,
 | 
						|
		.vsub = 4,
 | 
						|
	},
 | 
						|
	{
 | 
						|
		DRM_FORMAT(YVU410),
 | 
						|
		SAMPLER_TYPE(EGL_TEXTURE_Y_U_V_WL),
 | 
						|
		.num_planes = 3,
 | 
						|
		.chroma_order = ORDER_VU,
 | 
						|
		.hsub = 4,
 | 
						|
		.vsub = 4,
 | 
						|
	},
 | 
						|
	{
 | 
						|
		DRM_FORMAT(YUV411),
 | 
						|
		SAMPLER_TYPE(EGL_TEXTURE_Y_U_V_WL),
 | 
						|
		.num_planes = 3,
 | 
						|
		.hsub = 4,
 | 
						|
		.vsub = 1,
 | 
						|
	},
 | 
						|
	{
 | 
						|
		DRM_FORMAT(YVU411),
 | 
						|
		SAMPLER_TYPE(EGL_TEXTURE_Y_U_V_WL),
 | 
						|
		.num_planes = 3,
 | 
						|
		.chroma_order = ORDER_VU,
 | 
						|
		.hsub = 4,
 | 
						|
		.vsub = 1,
 | 
						|
	},
 | 
						|
	{
 | 
						|
		DRM_FORMAT(YUV420),
 | 
						|
		SAMPLER_TYPE(EGL_TEXTURE_Y_U_V_WL),
 | 
						|
		.num_planes = 3,
 | 
						|
		.hsub = 2,
 | 
						|
		.vsub = 2,
 | 
						|
	},
 | 
						|
	{
 | 
						|
		DRM_FORMAT(YVU420),
 | 
						|
		SAMPLER_TYPE(EGL_TEXTURE_Y_U_V_WL),
 | 
						|
		.num_planes = 3,
 | 
						|
		.chroma_order = ORDER_VU,
 | 
						|
		.hsub = 2,
 | 
						|
		.vsub = 2,
 | 
						|
	},
 | 
						|
	{
 | 
						|
		DRM_FORMAT(YUV422),
 | 
						|
		SAMPLER_TYPE(EGL_TEXTURE_Y_U_V_WL),
 | 
						|
		.num_planes = 3,
 | 
						|
		.hsub = 2,
 | 
						|
		.vsub = 1,
 | 
						|
	},
 | 
						|
	{
 | 
						|
		DRM_FORMAT(YVU422),
 | 
						|
		SAMPLER_TYPE(EGL_TEXTURE_Y_U_V_WL),
 | 
						|
		.num_planes = 3,
 | 
						|
		.chroma_order = ORDER_VU,
 | 
						|
		.hsub = 2,
 | 
						|
		.vsub = 1,
 | 
						|
	},
 | 
						|
	{
 | 
						|
		DRM_FORMAT(YUV444),
 | 
						|
		SAMPLER_TYPE(EGL_TEXTURE_Y_U_V_WL),
 | 
						|
		.num_planes = 3,
 | 
						|
	},
 | 
						|
	{
 | 
						|
		DRM_FORMAT(YVU444),
 | 
						|
		SAMPLER_TYPE(EGL_TEXTURE_Y_U_V_WL),
 | 
						|
		.num_planes = 3,
 | 
						|
		.chroma_order = ORDER_VU,
 | 
						|
	},
 | 
						|
};
 | 
						|
 | 
						|
WL_EXPORT const struct pixel_format_info *
 | 
						|
pixel_format_get_info_shm(uint32_t format)
 | 
						|
{
 | 
						|
	if (format == WL_SHM_FORMAT_XRGB8888)
 | 
						|
		return pixel_format_get_info(DRM_FORMAT_XRGB8888);
 | 
						|
	else if (format == WL_SHM_FORMAT_ARGB8888)
 | 
						|
		return pixel_format_get_info(DRM_FORMAT_ARGB8888);
 | 
						|
	else
 | 
						|
		return pixel_format_get_info(format);
 | 
						|
}
 | 
						|
 | 
						|
WL_EXPORT const struct pixel_format_info *
 | 
						|
pixel_format_get_info(uint32_t format)
 | 
						|
{
 | 
						|
	unsigned int i;
 | 
						|
 | 
						|
	for (i = 0; i < ARRAY_LENGTH(pixel_format_table); i++) {
 | 
						|
		if (pixel_format_table[i].format == format)
 | 
						|
			return &pixel_format_table[i];
 | 
						|
	}
 | 
						|
 | 
						|
	return NULL;
 | 
						|
}
 | 
						|
 | 
						|
WL_EXPORT const struct pixel_format_info *
 | 
						|
pixel_format_get_info_by_drm_name(const char *drm_format_name)
 | 
						|
{
 | 
						|
	const struct pixel_format_info *info;
 | 
						|
	unsigned int i;
 | 
						|
 | 
						|
	for (i = 0; i < ARRAY_LENGTH(pixel_format_table); i++) {
 | 
						|
		info = &pixel_format_table[i];
 | 
						|
		if (strcasecmp(info->drm_format_name, drm_format_name) == 0)
 | 
						|
			return info;
 | 
						|
	}
 | 
						|
 | 
						|
	return NULL;
 | 
						|
}
 | 
						|
 | 
						|
WL_EXPORT unsigned int
 | 
						|
pixel_format_get_plane_count(const struct pixel_format_info *info)
 | 
						|
{
 | 
						|
	return info->num_planes ? info->num_planes : 1;
 | 
						|
}
 | 
						|
 | 
						|
WL_EXPORT bool
 | 
						|
pixel_format_is_opaque(const struct pixel_format_info *info)
 | 
						|
{
 | 
						|
	return !info->opaque_substitute;
 | 
						|
}
 | 
						|
 | 
						|
WL_EXPORT const struct pixel_format_info *
 | 
						|
pixel_format_get_opaque_substitute(const struct pixel_format_info *info)
 | 
						|
{
 | 
						|
	if (!info->opaque_substitute)
 | 
						|
		return info;
 | 
						|
	else
 | 
						|
		return pixel_format_get_info(info->opaque_substitute);
 | 
						|
}
 | 
						|
 | 
						|
WL_EXPORT const struct pixel_format_info *
 | 
						|
pixel_format_get_info_by_opaque_substitute(uint32_t format)
 | 
						|
{
 | 
						|
	unsigned int i;
 | 
						|
 | 
						|
	for (i = 0; i < ARRAY_LENGTH(pixel_format_table); i++) {
 | 
						|
		if (pixel_format_table[i].opaque_substitute == format)
 | 
						|
			return &pixel_format_table[i];
 | 
						|
	}
 | 
						|
 | 
						|
	return NULL;
 | 
						|
}
 | 
						|
 | 
						|
WL_EXPORT unsigned int
 | 
						|
pixel_format_width_for_plane(const struct pixel_format_info *info,
 | 
						|
			     unsigned int plane,
 | 
						|
			     unsigned int width)
 | 
						|
{
 | 
						|
	/* We don't support any formats where the first plane is subsampled. */
 | 
						|
	if (plane == 0 || !info->hsub)
 | 
						|
		return width;
 | 
						|
 | 
						|
	return width / info->hsub;
 | 
						|
}
 | 
						|
 | 
						|
WL_EXPORT unsigned int
 | 
						|
pixel_format_height_for_plane(const struct pixel_format_info *info,
 | 
						|
			      unsigned int plane,
 | 
						|
			      unsigned int height)
 | 
						|
{
 | 
						|
	/* We don't support any formats where the first plane is subsampled. */
 | 
						|
	if (plane == 0 || !info->vsub)
 | 
						|
		return height;
 | 
						|
 | 
						|
	return height / info->vsub;
 | 
						|
}
 | 
						|
 |