gsk: Support swizzle for gray and alpha formats
authorSophie Herold <sophie@hemio.de>
Fri, 26 May 2023 12:45:05 +0000 (14:45 +0200)
committerMatthias Clasen <mclasen@redhat.com>
Tue, 30 May 2023 18:41:01 +0000 (14:41 -0400)
Swizzling is needed to display one channel memory formats
as gray etc.

gdk/gdkgltexture.c
gdk/gdkmemoryformat.c
gdk/gdkmemoryformatprivate.h
gsk/gl/gskglcommandqueue.c
gsk/gskrendernodeparser.c

index e08711aaf2fa50dffff9d80cffe2a9a0534fa753..59244f4422865535ba5a0b49e1115e3650709b49 100644 (file)
@@ -147,8 +147,9 @@ gdk_gl_texture_find_format (gboolean         use_es,
   for (format = 0; format < GDK_MEMORY_N_FORMATS; format++)
     {
       GLenum q_internal_format, q_format, q_type;
+      GLint q_swizzle[4];
 
-      if (!gdk_memory_format_gl_format (format, use_es, gl_major, gl_minor, &q_internal_format, &q_format, &q_type))
+      if (!gdk_memory_format_gl_format (format, use_es, gl_major, gl_minor, &q_internal_format, &q_format, &q_type, &q_swizzle))
         continue;
 
       if (q_format != gl_format || q_type != gl_type)
@@ -170,6 +171,7 @@ gdk_gl_texture_do_download (GdkGLTexture *self,
   gsize expected_stride;
   Download *download = download_;
   GLenum gl_internal_format, gl_format, gl_type;
+  GLint gl_swizzle[4];
   int major, minor;
 
   expected_stride = texture->width * gdk_memory_format_bytes_per_pixel (download->format);
@@ -177,7 +179,7 @@ gdk_gl_texture_do_download (GdkGLTexture *self,
 
   if (download->stride == expected_stride &&
       !gdk_gl_context_get_use_es (context) &&
-      gdk_memory_format_gl_format (download->format, TRUE, major, minor, &gl_internal_format, &gl_format, &gl_type))
+      gdk_memory_format_gl_format (download->format, TRUE, major, minor, &gl_internal_format, &gl_format, &gl_type, &gl_swizzle))
     {
       glGetTexImage (GL_TEXTURE_2D,
                      0,
index 4e92efe980a9388bd17176046515ab4e0bf0479c..9493f10eb63e58d0ca8f27bf05815c32db273f85 100644 (file)
@@ -592,11 +592,13 @@ gdk_memory_format_gl_format (GdkMemoryFormat  format,
                              guint            gl_minor,
                              guint           *out_internal_format,
                              guint           *out_format,
-                             guint           *out_type)
+                             guint           *out_type,
+                             GLint          (*out_swizzle)[4])
 {
   *out_internal_format = memory_formats[format].gl.internal_format;
   *out_format = memory_formats[format].gl.format;
   *out_type = memory_formats[format].gl.type;
+  memcpy (out_swizzle, &memory_formats[format].gl.swizzle, sizeof(GLint) * 4);
 
   if (memory_formats[format].alpha == GDK_MEMORY_ALPHA_STRAIGHT)
     return FALSE;
index 477baef25ed2cea50005ddd95fa04ab7d904c95c..5f2b4c06ad8446e2fdcefdfd3e08d590d1bc9cd3 100644 (file)
@@ -21,6 +21,8 @@
 
 #include "gdkenums.h"
 
+#include <epoxy/gl.h>
+
 G_BEGIN_DECLS
 
 typedef enum {
@@ -39,7 +41,8 @@ gboolean                gdk_memory_format_gl_format         (GdkMemoryFormat
                                                              guint                       gl_minor,
                                                              guint                      *out_internal_format,
                                                              guint                      *out_format,
-                                                             guint                      *out_type);
+                                                             guint                      *out_type,
+                                                             GLint                     (*out_gizzle)[4]);
 
 void                    gdk_memory_convert                  (guchar                     *dest_data,
                                                              gsize                       dest_stride,
index 204d2555d949eed1213c4d0fcce7e15d1d9aa9d6..4a19f59c4f05390a0c6004bf4e543c20d452c092 100644 (file)
@@ -1454,7 +1454,8 @@ memory_format_gl_format (GdkMemoryFormat  data_format,
                          guint            minor,
                          guint           *gl_internalformat,
                          guint           *gl_format,
-                         guint           *gl_type)
+                         guint           *gl_type,
+                         GLint          (*gl_swizzle)[4])
 {
   if (gdk_memory_format_gl_format (data_format,
                                    use_es,
@@ -1462,7 +1463,8 @@ memory_format_gl_format (GdkMemoryFormat  data_format,
                                    minor,
                                    gl_internalformat,
                                    gl_format,
-                                   gl_type))
+                                   gl_type,
+                                   gl_swizzle))
     return data_format;
 
   if (gdk_memory_format_prefers_high_depth (data_format))
@@ -1474,7 +1476,8 @@ memory_format_gl_format (GdkMemoryFormat  data_format,
                                        minor,
                                        gl_internalformat,
                                        gl_format,
-                                       gl_type))
+                                       gl_type,
+                                       gl_swizzle))
         return data_format;
     }
 
@@ -1485,7 +1488,8 @@ memory_format_gl_format (GdkMemoryFormat  data_format,
                                     minor,
                                     gl_internalformat,
                                     gl_format,
-                                    gl_type))
+                                    gl_type,
+                                    gl_swizzle))
     {
       g_assert_not_reached ();
     }
@@ -1508,6 +1512,7 @@ gsk_gl_command_queue_do_upload_texture_chunk (GskGLCommandQueue *self,
   GLenum gl_internalformat;
   GLenum gl_format;
   GLenum gl_type;
+  GLint gl_swizzle[4];
   gsize bpp;
   gboolean use_es;
   int major, minor;
@@ -1524,7 +1529,8 @@ gsk_gl_command_queue_do_upload_texture_chunk (GskGLCommandQueue *self,
                                          minor,
                                          &gl_internalformat,
                                          &gl_format,
-                                         &gl_type);
+                                         &gl_type,
+                                         &gl_swizzle);
 
   gdk_texture_downloader_init (&downloader, texture);
   gdk_texture_downloader_set_format (&downloader, data_format);
@@ -1559,6 +1565,18 @@ gsk_gl_command_queue_do_upload_texture_chunk (GskGLCommandQueue *self,
 
   glPixelStorei (GL_UNPACK_ALIGNMENT, 4);
 
+  /* Only apply swizzle if really needed, might not even be
+   * supported if default values are set
+   */
+  if (gl_swizzle[0] != GL_RED || gl_swizzle[1] != GL_GREEN || gl_swizzle[2] != GL_BLUE)
+    {
+      /* Set each channel independently since GLES 3.0 doesn't support the iv method */
+      glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_SWIZZLE_R, gl_swizzle[0]);
+      glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_SWIZZLE_G, gl_swizzle[1]);
+      glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_SWIZZLE_B, gl_swizzle[2]);
+      glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_SWIZZLE_A, gl_swizzle[3]);
+    }
+
   g_bytes_unref (bytes);
 }
 
@@ -1573,6 +1591,7 @@ gsk_gl_command_queue_upload_texture_chunks (GskGLCommandQueue    *self,
   GLenum gl_internalformat;
   GLenum gl_format;
   GLenum gl_type;
+  GLint gl_swizzle[4];
   gboolean use_es;
   int texture_id;
   int major, minor;
@@ -1617,7 +1636,8 @@ gsk_gl_command_queue_upload_texture_chunks (GskGLCommandQueue    *self,
                            minor,
                            &gl_internalformat,
                            &gl_format,
-                           &gl_type);
+                           &gl_type,
+                           &gl_swizzle);
 
   glTexImage2D (GL_TEXTURE_2D, 0, gl_internalformat, width, height, 0, gl_format, gl_type, NULL);
 
index c8ffad4bd10b780de83cba0cb0f01ba4356758c0..fc1e1cd4220437b58cc89f1c868a00e19e145d28 100644 (file)
@@ -2892,6 +2892,14 @@ append_texture_param (Printer    *p,
     case GDK_MEMORY_R16G16B16:
     case GDK_MEMORY_R16G16B16A16_PREMULTIPLIED:
     case GDK_MEMORY_R16G16B16A16:
+    case GDK_MEMORY_G8A8_PREMULTIPLIED:
+    case GDK_MEMORY_G8A8:
+    case GDK_MEMORY_G8:
+    case GDK_MEMORY_G16A16_PREMULTIPLIED:
+    case GDK_MEMORY_G16A16:
+    case GDK_MEMORY_G16:
+    case GDK_MEMORY_A8:
+    case GDK_MEMORY_A16:
       bytes = gdk_texture_save_to_png_bytes (texture);
       g_string_append (p->str, "url(\"data:image/png;base64,");
       break;