diff options
Diffstat (limited to 'render/fx_renderer/pixel_format.c')
| -rw-r--r-- | render/fx_renderer/pixel_format.c | 175 | 
1 files changed, 175 insertions, 0 deletions
| diff --git a/render/fx_renderer/pixel_format.c b/render/fx_renderer/pixel_format.c new file mode 100644 index 0000000..2693018 --- /dev/null +++ b/render/fx_renderer/pixel_format.c @@ -0,0 +1,175 @@ +#include <drm_fourcc.h> +#include <GLES2/gl2.h> +#include <GLES2/gl2ext.h> +#include "render/fx_renderer/fx_renderer.h" + +/* + * The DRM formats are little endian while the GL formats are big endian, + * so DRM_FORMAT_ARGB8888 is actually compatible with GL_BGRA_EXT. + */ +static const struct fx_pixel_format formats[] = { +	{ +		.drm_format = DRM_FORMAT_ARGB8888, +		.gl_format = GL_BGRA_EXT, +		.gl_type = GL_UNSIGNED_BYTE, +		.has_alpha = true, +	}, +	{ +		.drm_format = DRM_FORMAT_XRGB8888, +		.gl_format = GL_BGRA_EXT, +		.gl_type = GL_UNSIGNED_BYTE, +		.has_alpha = false, +	}, +	{ +		.drm_format = DRM_FORMAT_XBGR8888, +		.gl_format = GL_RGBA, +		.gl_type = GL_UNSIGNED_BYTE, +		.has_alpha = false, +	}, +	{ +		.drm_format = DRM_FORMAT_ABGR8888, +		.gl_format = GL_RGBA, +		.gl_type = GL_UNSIGNED_BYTE, +		.has_alpha = true, +	}, +	{ +		.drm_format = DRM_FORMAT_BGR888, +		.gl_format = GL_RGB, +		.gl_type = GL_UNSIGNED_BYTE, +		.has_alpha = false, +	}, +#if WLR_LITTLE_ENDIAN +	{ +		.drm_format = DRM_FORMAT_RGBX4444, +		.gl_format = GL_RGBA, +		.gl_type = GL_UNSIGNED_SHORT_4_4_4_4, +		.has_alpha = false, +	}, +	{ +		.drm_format = DRM_FORMAT_RGBA4444, +		.gl_format = GL_RGBA, +		.gl_type = GL_UNSIGNED_SHORT_4_4_4_4, +		.has_alpha = true, +	}, +	{ +		.drm_format = DRM_FORMAT_RGBX5551, +		.gl_format = GL_RGBA, +		.gl_type = GL_UNSIGNED_SHORT_5_5_5_1, +		.has_alpha = false, +	}, +	{ +		.drm_format = DRM_FORMAT_RGBA5551, +		.gl_format = GL_RGBA, +		.gl_type = GL_UNSIGNED_SHORT_5_5_5_1, +		.has_alpha = true, +	}, +	{ +		.drm_format = DRM_FORMAT_RGB565, +		.gl_format = GL_RGB, +		.gl_type = GL_UNSIGNED_SHORT_5_6_5, +		.has_alpha = false, +	}, +	{ +		.drm_format = DRM_FORMAT_XBGR2101010, +		.gl_format = GL_RGBA, +		.gl_type = GL_UNSIGNED_INT_2_10_10_10_REV_EXT, +		.has_alpha = false, +	}, +	{ +		.drm_format = DRM_FORMAT_ABGR2101010, +		.gl_format = GL_RGBA, +		.gl_type = GL_UNSIGNED_INT_2_10_10_10_REV_EXT, +		.has_alpha = true, +	}, +	{ +		.drm_format = DRM_FORMAT_XBGR16161616F, +		.gl_format = GL_RGBA, +		.gl_type = GL_HALF_FLOAT_OES, +		.has_alpha = false, +	}, +	{ +		.drm_format = DRM_FORMAT_ABGR16161616F, +		.gl_format = GL_RGBA, +		.gl_type = GL_HALF_FLOAT_OES, +		.has_alpha = true, +	}, +	{ +		.drm_format = DRM_FORMAT_XBGR16161616, +		.gl_internalformat = GL_RGBA16_EXT, +		.gl_format = GL_RGBA, +		.gl_type = GL_UNSIGNED_SHORT, +		.has_alpha = false, +	}, +	{ +		.drm_format = DRM_FORMAT_ABGR16161616, +		.gl_internalformat = GL_RGBA16_EXT, +		.gl_format = GL_RGBA, +		.gl_type = GL_UNSIGNED_SHORT, +		.has_alpha = true, +	}, +#endif +}; + +// TODO: more pixel formats + +/* + * Return true if supported for texturing, even if other operations like + * reading aren't supported. + */ +bool is_fx_pixel_format_supported(const struct fx_renderer *renderer, +		const struct fx_pixel_format *format) { +	if (format->gl_type == GL_UNSIGNED_INT_2_10_10_10_REV_EXT +			&& !renderer->exts.EXT_texture_type_2_10_10_10_REV) { +		return false; +	} +	if (format->gl_type == GL_HALF_FLOAT_OES +			&& !renderer->exts.OES_texture_half_float_linear) { +		return false; +	} +	if (format->gl_type == GL_UNSIGNED_SHORT +			&& !renderer->exts.EXT_texture_norm16) { +		return false; +	} +	/* +	 * Note that we don't need to check for GL_EXT_texture_format_BGRA8888 +	 * here, since we've already checked if we have it at renderer creation +	 * time and bailed out if not. We do the check there because Wayland +	 * requires all compositors to support SHM buffers in that format. +	 */ +	return true; +} + +const struct fx_pixel_format *get_fx_format_from_drm(uint32_t fmt) { +	for (size_t i = 0; i < sizeof(formats) / sizeof(*formats); ++i) { +		if (formats[i].drm_format == fmt) { +			return &formats[i]; +		} +	} +	return NULL; +} + +const struct fx_pixel_format *get_fx_format_from_gl( +		GLint gl_format, GLint gl_type, bool alpha) { +	for (size_t i = 0; i < sizeof(formats) / sizeof(*formats); ++i) { +		if (formats[i].gl_format == gl_format && +				formats[i].gl_type == gl_type && +				formats[i].has_alpha == alpha) { +			return &formats[i]; +		} +	} +	return NULL; +} + +const uint32_t *get_fx_shm_formats(const struct fx_renderer *renderer, +		size_t *len) { +	static uint32_t shm_formats[sizeof(formats) / sizeof(formats[0])]; +	size_t j = 0; +	for (size_t i = 0; i < sizeof(formats) / sizeof(formats[0]); i++) { +		if (!is_fx_pixel_format_supported(renderer, &formats[i])) { +			continue; +		} +		shm_formats[j++] = formats[i].drm_format; +	} +	*len = j; +	return shm_formats; +} | 
