summaryrefslogtreecommitdiff
path: root/render/fx_renderer/pixel_format.c
diff options
context:
space:
mode:
Diffstat (limited to 'render/fx_renderer/pixel_format.c')
-rw-r--r--render/fx_renderer/pixel_format.c175
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;
+}