/* * Copyright © 2016 Collabora, 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 */ #include "config.h" #include #include #include #include #include "helpers.h" #include "wayland-util.h" #include "pixel-formats.h" #include #include #include #include #include "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[] = { { .format = DRM_FORMAT_XRGB4444, }, { .format = DRM_FORMAT_ARGB4444, .opaque_substitute = DRM_FORMAT_XRGB4444, }, { .format = DRM_FORMAT_XBGR4444, }, { .format = DRM_FORMAT_ABGR4444, .opaque_substitute = DRM_FORMAT_XBGR4444, }, { .format = DRM_FORMAT_RGBX4444, .gl_format = GL_RGBA, .gl_type = GL_UNSIGNED_SHORT_4_4_4_4, }, { .format = DRM_FORMAT_RGBA4444, .opaque_substitute = DRM_FORMAT_RGBX4444, .gl_format = GL_RGBA, .gl_type = GL_UNSIGNED_SHORT_4_4_4_4, }, { .format = DRM_FORMAT_BGRX4444, .gl_format = GL_BGRA_EXT, .gl_type = GL_UNSIGNED_SHORT_4_4_4_4, }, { .format = DRM_FORMAT_BGRA4444, .opaque_substitute = DRM_FORMAT_BGRX4444, .gl_format = GL_BGRA_EXT, .gl_type = GL_UNSIGNED_SHORT_4_4_4_4, }, { .format = DRM_FORMAT_XRGB1555, .depth = 15, .bpp = 16, }, { .format = DRM_FORMAT_ARGB1555, .opaque_substitute = DRM_FORMAT_XRGB1555, }, { .format = DRM_FORMAT_XBGR1555, }, { .format = DRM_FORMAT_ABGR1555, .opaque_substitute = DRM_FORMAT_XBGR1555, }, { .format = DRM_FORMAT_RGBX5551, .gl_format = GL_RGBA, .gl_type = GL_UNSIGNED_SHORT_5_5_5_1, }, { .format = DRM_FORMAT_RGBA5551, .opaque_substitute = DRM_FORMAT_RGBX5551, .gl_format = GL_RGBA, .gl_type = GL_UNSIGNED_SHORT_5_5_5_1, }, { .format = DRM_FORMAT_BGRX5551, .gl_format = GL_BGRA_EXT, .gl_type = GL_UNSIGNED_SHORT_5_5_5_1, }, { .format = DRM_FORMAT_BGRA5551, .opaque_substitute = DRM_FORMAT_BGRX5551, .gl_format = GL_BGRA_EXT, .gl_type = GL_UNSIGNED_SHORT_5_5_5_1, }, { .format = DRM_FORMAT_RGB565, .depth = 16, .bpp = 16, .gl_format = GL_RGB, .gl_type = GL_UNSIGNED_SHORT_5_6_5, }, { .format = DRM_FORMAT_BGR565, }, { .format = DRM_FORMAT_RGB888, }, { .format = DRM_FORMAT_BGR888, .gl_type = GL_RGB, .gl_format = GL_UNSIGNED_BYTE, }, { .format = DRM_FORMAT_XRGB8888, .depth = 24, .bpp = 32, .gl_format = GL_BGRA_EXT, .gl_type = GL_UNSIGNED_BYTE, }, { .format = DRM_FORMAT_ARGB8888, .opaque_substitute = DRM_FORMAT_XRGB8888, .depth = 32, .bpp = 32, .gl_format = GL_BGRA_EXT, .gl_type = GL_UNSIGNED_BYTE, }, { .format = DRM_FORMAT_XBGR8888, .gl_format = GL_RGBA, .gl_type = GL_UNSIGNED_BYTE, }, { .format = DRM_FORMAT_ABGR8888, .opaque_substitute = DRM_FORMAT_XBGR8888, .gl_format = GL_RGBA, .gl_type = GL_UNSIGNED_BYTE, }, { .format = DRM_FORMAT_RGBX8888, }, { .format = DRM_FORMAT_RGBA8888, .opaque_substitute = DRM_FORMAT_RGBX8888, }, { .format = DRM_FORMAT_BGRX8888, }, { .format = DRM_FORMAT_BGRA8888, .opaque_substitute = DRM_FORMAT_BGRX8888, }, { .format = DRM_FORMAT_XRGB2101010, .depth = 30, .bpp = 32, }, { .format = DRM_FORMAT_ARGB2101010, .opaque_substitute = DRM_FORMAT_XRGB2101010, .gl_type = GL_BGRA_EXT, .gl_format = GL_UNSIGNED_INT_2_10_10_10_REV_EXT, }, { .format = DRM_FORMAT_XBGR2101010, .gl_type = GL_RGB, .gl_format = GL_UNSIGNED_INT_2_10_10_10_REV_EXT, }, { .format = DRM_FORMAT_ABGR2101010, .opaque_substitute = DRM_FORMAT_XBGR2101010, .gl_type = GL_RGBA, .gl_format = GL_UNSIGNED_INT_2_10_10_10_REV_EXT, }, { .format = DRM_FORMAT_RGBX1010102, }, { .format = DRM_FORMAT_RGBA1010102, .opaque_substitute = DRM_FORMAT_RGBX1010102, }, { .format = DRM_FORMAT_BGRX1010102, }, { .format = DRM_FORMAT_BGRA1010102, .opaque_substitute = DRM_FORMAT_BGRX1010102, }, { .format = DRM_FORMAT_YUYV, .sampler_type = EGL_TEXTURE_Y_XUXV_WL, .num_planes = 1, .hsub = 2, }, { .format = DRM_FORMAT_YVYU, .sampler_type = EGL_TEXTURE_Y_XUXV_WL, .num_planes = 1, .chroma_order = ORDER_VU, .hsub = 2, }, { .format = DRM_FORMAT_UYVY, .sampler_type = EGL_TEXTURE_Y_XUXV_WL, .num_planes = 1, .luma_chroma_order = ORDER_CHROMA_LUMA, }, { .format = DRM_FORMAT_VYUY, .sampler_type = EGL_TEXTURE_Y_XUXV_WL, .num_planes = 1, .luma_chroma_order = ORDER_CHROMA_LUMA, .chroma_order = ORDER_VU, }, { /* our one format with an alpha channel and no opaque equiv; * also cannot be trivially converted to RGB without writing * a new shader in gl-renderer */ .format = DRM_FORMAT_AYUV, .sampler_type = EGL_TEXTURE_Y_XUXV_WL, .num_planes = 1, }, { .format = DRM_FORMAT_NV12, .sampler_type = EGL_TEXTURE_Y_UV_WL, .num_planes = 2, .hsub = 2, .vsub = 2, }, { .format = DRM_FORMAT_NV21, .sampler_type = EGL_TEXTURE_Y_UV_WL, .num_planes = 2, .chroma_order = ORDER_VU, .hsub = 2, .vsub = 2, }, { .format = DRM_FORMAT_NV16, .sampler_type = EGL_TEXTURE_Y_UV_WL, .num_planes = 2, .hsub = 2, .vsub = 1, }, { .format = DRM_FORMAT_NV61, .sampler_type = EGL_TEXTURE_Y_UV_WL, .num_planes = 2, .chroma_order = ORDER_VU, .hsub = 2, .vsub = 1, }, { .format = DRM_FORMAT_NV24, .sampler_type = EGL_TEXTURE_Y_UV_WL, .num_planes = 2, }, { .format = DRM_FORMAT_NV42, .sampler_type = EGL_TEXTURE_Y_UV_WL, .num_planes = 2, .chroma_order = ORDER_VU, }, { .format = DRM_FORMAT_YUV410, .sampler_type = EGL_TEXTURE_Y_U_V_WL, .num_planes = 3, .hsub = 4, .vsub = 4, }, { .format = DRM_FORMAT_YVU410, .sampler_type = EGL_TEXTURE_Y_U_V_WL, .num_planes = 3, .chroma_order = ORDER_VU, .hsub = 4, .vsub = 4, }, { .format = DRM_FORMAT_YUV411, .sampler_type = EGL_TEXTURE_Y_U_V_WL, .num_planes = 3, .hsub = 4, .vsub = 1, }, { .format = DRM_FORMAT_YVU411, .sampler_type = EGL_TEXTURE_Y_U_V_WL, .num_planes = 3, .chroma_order = ORDER_VU, .hsub = 4, .vsub = 1, }, { .format = DRM_FORMAT_YUV420, .sampler_type = EGL_TEXTURE_Y_U_V_WL, .num_planes = 3, .hsub = 2, .vsub = 2, }, { .format = DRM_FORMAT_YVU420, .sampler_type = EGL_TEXTURE_Y_U_V_WL, .num_planes = 3, .chroma_order = ORDER_VU, .hsub = 2, .vsub = 2, }, { .format = DRM_FORMAT_YUV422, .sampler_type = EGL_TEXTURE_Y_U_V_WL, .num_planes = 3, .hsub = 2, .vsub = 1, }, { .format = DRM_FORMAT_YVU422, .sampler_type = EGL_TEXTURE_Y_U_V_WL, .num_planes = 3, .chroma_order = ORDER_VU, .hsub = 2, .vsub = 1, }, { .format = DRM_FORMAT_YUV444, .sampler_type = EGL_TEXTURE_Y_U_V_WL, .num_planes = 3, }, { .format = 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(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 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); }