Blame SOURCES/0001-cogl-Prefer-swizzling-to-convert-BGRA-buffers.patch

db633a
From 32faf80489f8ee7b4c973660c286f6d228f8e738 Mon Sep 17 00:00:00 2001
db633a
From: Carlos Garnacho <carlosg@gnome.org>
db633a
Date: Sat, 25 Feb 2017 23:21:06 +0100
db633a
Subject: [PATCH] cogl: Prefer swizzling to convert BGRA buffers
db633a
db633a
(squashed/rebased for gnome-3-22)
db633a
db633a
If the GL implementation/hw supports the GL_*_texture_swizzle extension,
db633a
pretend that BGRA textures shall contain RGBA data, and let the flipping
db633a
happen when the texture will be used in the rendering pipeline.
db633a
db633a
This avoids rather expensive format conversions when forcing BGRA buffers
db633a
into RGBA textures, which happens rather often with WL_SHM_FORMAT_ARGB8888
db633a
buffers (like gtk+ uses) in little-endian machines.
db633a
db633a
In intel/mesa/wayland, the performance improvement is rather noticeable,
db633a
CPU% as seen by top decreases from 45-50% to 25-30% when running
db633a
gtk+/tests/scrolling-performance with a cairo renderer.
db633a
db633a
https://bugzilla.gnome.org/show_bug.cgi?id=779234
db633a
---
db633a
 cogl/cogl/cogl-driver.h                         |  7 +++++
db633a
 cogl/cogl/driver/gl/cogl-framebuffer-gl.c       |  9 ++++++
db633a
 cogl/cogl/driver/gl/cogl-texture-2d-gl.c        | 11 ++++----
db633a
 cogl/cogl/driver/gl/gl/cogl-driver-gl.c         | 37 +++++++++++++++++++++----
db633a
 cogl/cogl/driver/gl/gl/cogl-texture-driver-gl.c | 12 ++++++++
db633a
 cogl/cogl/driver/gl/gles/cogl-driver-gles.c     | 26 +++++++++++++----
db633a
 cogl/cogl/driver/nop/cogl-driver-nop.c          |  1 +
db633a
 7 files changed, 87 insertions(+), 16 deletions(-)
db633a
db633a
diff --git a/cogl/cogl/cogl-driver.h b/cogl/cogl/cogl-driver.h
db633a
index 648228c..85aa0d8 100644
db633a
--- a/cogl/cogl/cogl-driver.h
db633a
+++ b/cogl/cogl/cogl-driver.h
db633a
@@ -55,6 +55,13 @@ struct _CoglDriverVtable
db633a
                           GLenum *out_glintformat,
db633a
                           GLenum *out_glformat,
db633a
                           GLenum *out_gltype);
db633a
+  CoglPixelFormat
db633a
+  (* pixel_format_to_gl_with_target) (CoglContext *context,
db633a
+                                      CoglPixelFormat format,
db633a
+                                      CoglPixelFormat target_format,
db633a
+                                      GLenum *out_glintformat,
db633a
+                                      GLenum *out_glformat,
db633a
+                                      GLenum *out_gltype);
db633a
 
db633a
   CoglBool
db633a
   (* update_features) (CoglContext *context,
db633a
diff --git a/cogl/cogl/driver/gl/cogl-framebuffer-gl.c b/cogl/cogl/driver/gl/cogl-framebuffer-gl.c
db633a
index 18ba08a..2af36f0 100644
db633a
--- a/cogl/cogl/driver/gl/cogl-framebuffer-gl.c
db633a
+++ b/cogl/cogl/driver/gl/cogl-framebuffer-gl.c
db633a
@@ -1418,6 +1418,15 @@ _cogl_framebuffer_gl_read_pixels_into_bitmap (CoglFramebuffer *framebuffer,
db633a
                                                             &gl_format,
db633a
                                                             &gl_type);
db633a
 
db633a
+  /* As we are reading pixels, we want to consider the bitmap according to
db633a
+   * its real pixel format, not the swizzled channels we pretend face to the
db633a
+   * pipeline.
db633a
+   */
db633a
+  if ((format == COGL_PIXEL_FORMAT_BGRA_8888 ||
db633a
+       format == COGL_PIXEL_FORMAT_BGRA_8888_PRE) &&
db633a
+      _cogl_has_private_feature (ctx, COGL_PRIVATE_FEATURE_TEXTURE_SWIZZLE))
db633a
+    gl_format = GL_BGRA;
db633a
+
db633a
   /* NB: All offscreen rendering is done upside down so there is no need
db633a
    * to flip in this case... */
db633a
   if (_cogl_has_private_feature (ctx, COGL_PRIVATE_FEATURE_MESA_PACK_INVERT) &&
db633a
diff --git a/cogl/cogl/driver/gl/cogl-texture-2d-gl.c b/cogl/cogl/driver/gl/cogl-texture-2d-gl.c
db633a
index 1193df4..817dd53 100644
db633a
--- a/cogl/cogl/driver/gl/cogl-texture-2d-gl.c
db633a
+++ b/cogl/cogl/driver/gl/cogl-texture-2d-gl.c
db633a
@@ -657,11 +657,12 @@ _cogl_texture_2d_gl_copy_from_bitmap (CoglTexture2D *tex_2d,
db633a
 
db633a
   upload_format = cogl_bitmap_get_format (upload_bmp);
db633a
 
db633a
-  ctx->driver_vtable->pixel_format_to_gl (ctx,
db633a
-                                          upload_format,
db633a
-                                          NULL, /* internal format */
db633a
-                                          &gl_format,
db633a
-                                          &gl_type);
db633a
+  ctx->driver_vtable->pixel_format_to_gl_with_target (ctx,
db633a
+                                                      upload_format,
db633a
+                                                      _cogl_texture_get_format (tex),
db633a
+                                                      NULL, /* internal gl format */
db633a
+                                                      &gl_format,
db633a
+                                                      &gl_type);
db633a
 
db633a
   /* If this touches the first pixel then we'll update our copy */
db633a
   if (dst_x == 0 && dst_y == 0 &&
db633a
diff --git a/cogl/cogl/driver/gl/gl/cogl-driver-gl.c b/cogl/cogl/driver/gl/gl/cogl-driver-gl.c
db633a
index 2b9a49c..178262a 100644
db633a
--- a/cogl/cogl/driver/gl/gl/cogl-driver-gl.c
db633a
+++ b/cogl/cogl/driver/gl/gl/cogl-driver-gl.c
db633a
@@ -96,11 +96,12 @@ _cogl_driver_pixel_format_from_gl_internal (CoglContext *context,
db633a
 }
db633a
 
db633a
 static CoglPixelFormat
db633a
-_cogl_driver_pixel_format_to_gl (CoglContext *context,
db633a
-                                 CoglPixelFormat  format,
db633a
-                                 GLenum *out_glintformat,
db633a
-                                 GLenum *out_glformat,
db633a
-                                 GLenum *out_gltype)
db633a
+_cogl_driver_pixel_format_to_gl_with_target (CoglContext *context,
db633a
+                                             CoglPixelFormat format,
db633a
+                                             CoglPixelFormat target_format,
db633a
+                                             GLenum *out_glintformat,
db633a
+                                             GLenum *out_glformat,
db633a
+                                             GLenum *out_gltype)
db633a
 {
db633a
   CoglPixelFormat required_format;
db633a
   GLenum glintformat = 0;
db633a
@@ -174,7 +175,16 @@ _cogl_driver_pixel_format_to_gl (CoglContext *context,
db633a
     case COGL_PIXEL_FORMAT_BGRA_8888:
db633a
     case COGL_PIXEL_FORMAT_BGRA_8888_PRE:
db633a
       glintformat = GL_RGBA;
db633a
-      glformat = GL_BGRA;
db633a
+      /* If the driver has texture_swizzle, pretend internal
db633a
+       * and buffer format are the same here, the pixels
db633a
+       * will be flipped through this extension.
db633a
+       */
db633a
+      if (target_format == format &&
db633a
+          _cogl_has_private_feature
db633a
+          (context, COGL_PRIVATE_FEATURE_TEXTURE_SWIZZLE))
db633a
+        glformat = GL_RGBA;
db633a
+      else
db633a
+        glformat = GL_BGRA;
db633a
       gltype = GL_UNSIGNED_BYTE;
db633a
       break;
db633a
 
db633a
@@ -289,6 +299,20 @@ _cogl_driver_pixel_format_to_gl (CoglContext *context,
db633a
   return required_format;
db633a
 }
db633a
 
db633a
+static CoglPixelFormat
db633a
+_cogl_driver_pixel_format_to_gl (CoglContext *context,
db633a
+                                 CoglPixelFormat  format,
db633a
+                                 GLenum *out_glintformat,
db633a
+                                 GLenum *out_glformat,
db633a
+                                 GLenum *out_gltype)
db633a
+{
db633a
+  return _cogl_driver_pixel_format_to_gl_with_target (context,
db633a
+                                                      format, format,
db633a
+                                                      out_glintformat,
db633a
+                                                      out_glformat,
db633a
+                                                      out_gltype);
db633a
+}
db633a
+
db633a
 static CoglBool
db633a
 _cogl_get_gl_version (CoglContext *ctx,
db633a
                       int *major_out,
db633a
@@ -669,6 +693,7 @@ _cogl_driver_gl =
db633a
   {
db633a
     _cogl_driver_pixel_format_from_gl_internal,
db633a
     _cogl_driver_pixel_format_to_gl,
db633a
+    _cogl_driver_pixel_format_to_gl_with_target,
db633a
     _cogl_driver_update_features,
db633a
     _cogl_offscreen_gl_allocate,
db633a
     _cogl_offscreen_gl_free,
db633a
diff --git a/cogl/cogl/driver/gl/gl/cogl-texture-driver-gl.c b/cogl/cogl/driver/gl/gl/cogl-texture-driver-gl.c
db633a
index c76a0cf..d5ee4b4 100644
db633a
--- a/cogl/cogl/driver/gl/gl/cogl-texture-driver-gl.c
db633a
+++ b/cogl/cogl/driver/gl/gl/cogl-texture-driver-gl.c
db633a
@@ -114,6 +114,18 @@ _cogl_texture_driver_gen (CoglContext *ctx,
db633a
                                  red_swizzle) );
db633a
     }
db633a
 
db633a
+  /* If swizzle extension is available, prefer it to flip bgra buffers to rgba */
db633a
+  if ((internal_format == COGL_PIXEL_FORMAT_BGRA_8888 ||
db633a
+       internal_format == COGL_PIXEL_FORMAT_BGRA_8888_PRE) &&
db633a
+      _cogl_has_private_feature (ctx, COGL_PRIVATE_FEATURE_TEXTURE_SWIZZLE))
db633a
+    {
db633a
+      static const GLint bgra_swizzle[] = { GL_BLUE, GL_GREEN, GL_RED, GL_ALPHA };
db633a
+
db633a
+      GE( ctx, glTexParameteriv (gl_target,
db633a
+                                 GL_TEXTURE_SWIZZLE_RGBA,
db633a
+                                 bgra_swizzle) );
db633a
+    }
db633a
+
db633a
   return tex;
db633a
 }
db633a
 
db633a
diff --git a/cogl/cogl/driver/gl/gles/cogl-driver-gles.c b/cogl/cogl/driver/gl/gles/cogl-driver-gles.c
db633a
index bf63fcc..521f6ef 100644
db633a
--- a/cogl/cogl/driver/gl/gles/cogl-driver-gles.c
db633a
+++ b/cogl/cogl/driver/gl/gles/cogl-driver-gles.c
db633a
@@ -67,11 +67,12 @@ _cogl_driver_pixel_format_from_gl_internal (CoglContext *context,
db633a
 }
db633a
 
db633a
 static CoglPixelFormat
db633a
-_cogl_driver_pixel_format_to_gl (CoglContext *context,
db633a
-                                 CoglPixelFormat  format,
db633a
-                                 GLenum *out_glintformat,
db633a
-                                 GLenum *out_glformat,
db633a
-                                 GLenum *out_gltype)
db633a
+_cogl_driver_pixel_format_to_gl_with_target (CoglContext *context,
db633a
+                                             CoglPixelFormat format,
db633a
+                                             CoglPixelFormat target_format,
db633a
+                                             GLenum *out_glintformat,
db633a
+                                             GLenum *out_glformat,
db633a
+                                             GLenum *out_gltype)
db633a
 {
db633a
   CoglPixelFormat required_format;
db633a
   GLenum glintformat;
db633a
@@ -219,6 +220,20 @@ _cogl_driver_pixel_format_to_gl (CoglContext *context,
db633a
   return required_format;
db633a
 }
db633a
 
db633a
+static CoglPixelFormat
db633a
+_cogl_driver_pixel_format_to_gl (CoglContext *context,
db633a
+                                 CoglPixelFormat  format,
db633a
+                                 GLenum *out_glintformat,
db633a
+                                 GLenum *out_glformat,
db633a
+                                 GLenum *out_gltype)
db633a
+{
db633a
+  return _cogl_driver_pixel_format_to_gl_with_target (context,
db633a
+                                                      format, format,
db633a
+                                                      out_glintformat,
db633a
+                                                      out_glformat,
db633a
+                                                      out_gltype);
db633a
+}
db633a
+
db633a
 static CoglBool
db633a
 _cogl_get_gl_version (CoglContext *ctx,
db633a
                       int *major_out,
db633a
@@ -457,6 +472,7 @@ _cogl_driver_gles =
db633a
   {
db633a
     _cogl_driver_pixel_format_from_gl_internal,
db633a
     _cogl_driver_pixel_format_to_gl,
db633a
+    _cogl_driver_pixel_format_to_gl_with_target,
db633a
     _cogl_driver_update_features,
db633a
     _cogl_offscreen_gl_allocate,
db633a
     _cogl_offscreen_gl_free,
db633a
diff --git a/cogl/cogl/driver/nop/cogl-driver-nop.c b/cogl/cogl/driver/nop/cogl-driver-nop.c
db633a
index d9b1d0f..6e04e71 100644
db633a
--- a/cogl/cogl/driver/nop/cogl-driver-nop.c
db633a
+++ b/cogl/cogl/driver/nop/cogl-driver-nop.c
db633a
@@ -61,6 +61,7 @@ _cogl_driver_nop =
db633a
   {
db633a
     NULL, /* pixel_format_from_gl_internal */
db633a
     NULL, /* pixel_format_to_gl */
db633a
+    NULL, /* pixel_format_to_gl_with_target */
db633a
     _cogl_driver_update_features,
db633a
     _cogl_offscreen_nop_allocate,
db633a
     _cogl_offscreen_nop_free,
db633a
-- 
db633a
2.9.3
db633a