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 }