git.lucas.co / cce-compositor
Wayland compositor (wlroots)
git clone https://git.lucas.co/cce-compositor.git

scenefx/render/fx_renderer/pixel_format.c (4.2K)

  1 #include <drm_fourcc.h>
  2 #include <GLES2/gl2.h>
  3 #include <GLES2/gl2ext.h>
  4 
  5 #include "render/fx_renderer/fx_renderer.h"
  6 #include "render/pixel_format.h"
  7 
  8 /*
  9  * The DRM formats are little endian while the GL formats are big endian,
 10  * so DRM_FORMAT_ARGB8888 is actually compatible with GL_BGRA_EXT.
 11  */
 12 static const struct fx_pixel_format formats[] = {
 13 	{
 14 		.drm_format = DRM_FORMAT_ARGB8888,
 15 		.gl_format = GL_BGRA_EXT,
 16 		.gl_type = GL_UNSIGNED_BYTE,
 17 	},
 18 	{
 19 		.drm_format = DRM_FORMAT_XRGB8888,
 20 		.gl_format = GL_BGRA_EXT,
 21 		.gl_type = GL_UNSIGNED_BYTE,
 22 	},
 23 	{
 24 		.drm_format = DRM_FORMAT_XBGR8888,
 25 		.gl_format = GL_RGBA,
 26 		.gl_type = GL_UNSIGNED_BYTE,
 27 	},
 28 	{
 29 		.drm_format = DRM_FORMAT_ABGR8888,
 30 		.gl_format = GL_RGBA,
 31 		.gl_type = GL_UNSIGNED_BYTE,
 32 	},
 33 	{
 34 		.drm_format = DRM_FORMAT_BGR888,
 35 		.gl_format = GL_RGB,
 36 		.gl_type = GL_UNSIGNED_BYTE,
 37 	},
 38 #if WLR_LITTLE_ENDIAN
 39 	{
 40 		.drm_format = DRM_FORMAT_RGBX4444,
 41 		.gl_format = GL_RGBA,
 42 		.gl_type = GL_UNSIGNED_SHORT_4_4_4_4,
 43 	},
 44 	{
 45 		.drm_format = DRM_FORMAT_RGBA4444,
 46 		.gl_format = GL_RGBA,
 47 		.gl_type = GL_UNSIGNED_SHORT_4_4_4_4,
 48 	},
 49 	{
 50 		.drm_format = DRM_FORMAT_RGBX5551,
 51 		.gl_format = GL_RGBA,
 52 		.gl_type = GL_UNSIGNED_SHORT_5_5_5_1,
 53 	},
 54 	{
 55 		.drm_format = DRM_FORMAT_RGBA5551,
 56 		.gl_format = GL_RGBA,
 57 		.gl_type = GL_UNSIGNED_SHORT_5_5_5_1,
 58 	},
 59 	{
 60 		.drm_format = DRM_FORMAT_RGB565,
 61 		.gl_format = GL_RGB,
 62 		.gl_type = GL_UNSIGNED_SHORT_5_6_5,
 63 	},
 64 	{
 65 		.drm_format = DRM_FORMAT_XBGR2101010,
 66 		.gl_format = GL_RGBA,
 67 		.gl_type = GL_UNSIGNED_INT_2_10_10_10_REV_EXT,
 68 	},
 69 	{
 70 		.drm_format = DRM_FORMAT_ABGR2101010,
 71 		.gl_format = GL_RGBA,
 72 		.gl_type = GL_UNSIGNED_INT_2_10_10_10_REV_EXT,
 73 	},
 74 	{
 75 		.drm_format = DRM_FORMAT_BGR161616F,
 76 		.gl_format = GL_RGB,
 77 		.gl_type = GL_HALF_FLOAT_OES,
 78 	},
 79 	{
 80 		.drm_format = DRM_FORMAT_XBGR16161616F,
 81 		.gl_format = GL_RGBA,
 82 		.gl_type = GL_HALF_FLOAT_OES,
 83 	},
 84 	{
 85 		.drm_format = DRM_FORMAT_ABGR16161616F,
 86 		.gl_format = GL_RGBA,
 87 		.gl_type = GL_HALF_FLOAT_OES,
 88 	},
 89 	{
 90 		.drm_format = DRM_FORMAT_BGR161616,
 91 		.gl_internalformat = GL_RGB16_EXT,
 92 		.gl_format = GL_RGB,
 93 		.gl_type = GL_UNSIGNED_SHORT,
 94 	},
 95 	{
 96 		.drm_format = DRM_FORMAT_XBGR16161616,
 97 		.gl_internalformat = GL_RGBA16_EXT,
 98 		.gl_format = GL_RGBA,
 99 		.gl_type = GL_UNSIGNED_SHORT,
100 	},
101 	{
102 		.drm_format = DRM_FORMAT_ABGR16161616,
103 		.gl_internalformat = GL_RGBA16_EXT,
104 		.gl_format = GL_RGBA,
105 		.gl_type = GL_UNSIGNED_SHORT,
106 	},
107 #endif
108 };
109 
110 // TODO: more pixel formats
111 
112 /*
113  * Return true if supported for texturing, even if other operations like
114  * reading aren't supported.
115  */
116 bool is_fx_pixel_format_supported(const struct fx_renderer *renderer,
117 		const struct fx_pixel_format *format) {
118 	if (format->gl_type == GL_UNSIGNED_INT_2_10_10_10_REV_EXT
119 			&& !renderer->exts.EXT_texture_type_2_10_10_10_REV) {
120 		return false;
121 	}
122 	if (format->gl_type == GL_HALF_FLOAT_OES
123 			&& !renderer->exts.OES_texture_half_float_linear) {
124 		return false;
125 	}
126 	if (format->gl_type == GL_UNSIGNED_SHORT
127 			&& !renderer->exts.EXT_texture_norm16) {
128 		return false;
129 	}
130 	/*
131 	 * Note that we don't need to check for GL_EXT_texture_format_BGRA8888
132 	 * here, since we've already checked if we have it at renderer creation
133 	 * time and bailed out if not. We do the check there because Wayland
134 	 * requires all compositors to support SHM buffers in that format.
135 	 */
136 	return true;
137 }
138 
139 const struct fx_pixel_format *get_fx_format_from_drm(uint32_t fmt) {
140 	for (size_t i = 0; i < sizeof(formats) / sizeof(*formats); ++i) {
141 		if (formats[i].drm_format == fmt) {
142 			return &formats[i];
143 		}
144 	}
145 	return NULL;
146 }
147 
148 const struct fx_pixel_format *get_fx_format_from_gl(
149 		GLint gl_format, GLint gl_type, bool alpha) {
150 	for (size_t i = 0; i < sizeof(formats) / sizeof(*formats); ++i) {
151 		if (formats[i].gl_format != gl_format ||
152 				formats[i].gl_type != gl_type) {
153 			continue;
154 		}
155 
156 		if (pixel_format_has_alpha(formats[i].drm_format) != alpha) {
157 			continue;
158 		}
159 
160 		return &formats[i];
161 	}
162 	return NULL;
163 }
164 
165 void get_fx_shm_formats(const struct fx_renderer *renderer,
166 		struct wlr_drm_format_set *out) {
167 	for (size_t i = 0; i < sizeof(formats) / sizeof(formats[0]); i++) {
168 		if (!is_fx_pixel_format_supported(renderer, &formats[i])) {
169 			continue;
170 		}
171 		wlr_drm_format_set_add(out, formats[i].drm_format, DRM_FORMAT_MOD_INVALID);
172 		wlr_drm_format_set_add(out, formats[i].drm_format, DRM_FORMAT_MOD_LINEAR);
173 	}
174 }