[mutter] cogl: Allow glBlitFramebuffer between onscreen/offscreen



commit 45289b3d65e308117f1bc8fe6a4c88c1baaacca7
Author: Pekka Paalanen <pekka paalanen collabora com>
Date:   Mon May 6 15:08:29 2019 +0300

    cogl: Allow glBlitFramebuffer between onscreen/offscreen
    
    Depends on "cogl: Replace ANGLE with GLES3 and NV framebuffer_blit"
    
    Allow blitting between onscreen and offscreen framebuffers by doing the y-flip
    as necessary. This was not possible with ANGLE, but now with ANGLE gone,
    glBlitFramebuffer supports flipping the copied image.
    
    This will be useful in follow-up work to copy from onscreen primary GPU
    framebuffer to an offscreen secondary GPU framebuffer.
    
    https://gitlab.gnome.org/GNOME/mutter/merge_requests/615

 cogl/cogl/cogl-framebuffer-private.h      | 14 ++++------
 cogl/cogl/cogl-framebuffer.c              | 46 +++++++++++++++++++++++++------
 cogl/cogl/driver/gl/cogl-framebuffer-gl.c |  5 +---
 3 files changed, 43 insertions(+), 22 deletions(-)
---
diff --git a/cogl/cogl/cogl-framebuffer-private.h b/cogl/cogl/cogl-framebuffer-private.h
index 7b2560173..1605fcdc4 100644
--- a/cogl/cogl/cogl-framebuffer-private.h
+++ b/cogl/cogl/cogl-framebuffer-private.h
@@ -378,7 +378,11 @@ _cogl_push_framebuffers (CoglFramebuffer *draw_buffer,
  * This blits a region of the color buffer of the source buffer
  * to the destination buffer. This function should only be
  * called if the COGL_PRIVATE_FEATURE_OFFSCREEN_BLIT feature is
- * advertised. The two buffers must both be offscreen.
+ * advertised.
+ *
+ * The source and destination rectangles are defined in offscreen
+ * framebuffer orientation. When copying between an offscreen and
+ * onscreen framebuffers, the image is y-flipped accordingly.
  *
  * The two buffers must have the same value types (e.g. floating-point,
  * unsigned int, signed int, or fixed-point), but color formats do not
@@ -393,14 +397,6 @@ _cogl_push_framebuffers (CoglFramebuffer *draw_buffer,
  * scale the results it may make more sense to draw a primitive
  * instead.
  *
- * We can only really support blitting between two offscreen buffers
- * for this function on GLES2.0. This is because we effectively render
- * upside down to offscreen buffers to maintain Cogl's representation
- * of the texture coordinate system where 0,0 is the top left of the
- * texture. If we were to blit from an offscreen to an onscreen buffer
- * then we would need to mirror the blit along the x-axis but the GLES
- * extension does not support this.
- *
  * The GL function is documented to be affected by the scissor. This
  * function therefore ensure that an empty clip stack is flushed
  * before performing the blit which means the scissor is effectively
diff --git a/cogl/cogl/cogl-framebuffer.c b/cogl/cogl/cogl-framebuffer.c
index 1c046476e..45c532cff 100644
--- a/cogl/cogl/cogl-framebuffer.c
+++ b/cogl/cogl/cogl-framebuffer.c
@@ -1352,15 +1352,12 @@ _cogl_blit_framebuffer (CoglFramebuffer *src,
                         int height)
 {
   CoglContext *ctx = src->context;
+  int src_x1, src_y1, src_x2, src_y2;
+  int dst_x1, dst_y1, dst_x2, dst_y2;
 
   g_return_if_fail (_cogl_has_private_feature
                     (ctx, COGL_PRIVATE_FEATURE_OFFSCREEN_BLIT));
 
-  /* We can only support blitting between offscreen buffers because
-     otherwise we would need to mirror the image and GLES2.0 doesn't
-     support this */
-  g_return_if_fail (cogl_is_offscreen (src));
-  g_return_if_fail (cogl_is_offscreen (dest));
   /* The buffers must use the same premult convention */
   g_return_if_fail ((src->internal_format & COGL_PREMULT_BIT) ==
                     (dest->internal_format & COGL_PREMULT_BIT));
@@ -1384,10 +1381,41 @@ _cogl_blit_framebuffer (CoglFramebuffer *src,
    * as changed */
   ctx->current_draw_buffer_changes |= COGL_FRAMEBUFFER_STATE_CLIP;
 
-  ctx->glBlitFramebuffer (src_x, src_y,
-                          src_x + width, src_y + height,
-                          dst_x, dst_y,
-                          dst_x + width, dst_y + height,
+  /* Offscreens we do the normal way, onscreens need an y-flip. Even if
+   * we consider offscreens to be rendered upside-down, the offscreen
+   * orientation is in this function's API. */
+  if (cogl_is_offscreen (src))
+    {
+      src_x1 = src_x;
+      src_y1 = src_y;
+      src_x2 = src_x + width;
+      src_y2 = src_y + height;
+    }
+  else
+    {
+      src_x1 = src_x;
+      src_y1 = cogl_framebuffer_get_height (src) - src_y;
+      src_x2 = src_x + width;
+      src_y2 = src_y1 - height;
+    }
+
+  if (cogl_is_offscreen (dest))
+    {
+      dst_x1 = dst_x;
+      dst_y1 = dst_y;
+      dst_x2 = dst_x + width;
+      dst_y2 = dst_y + height;
+    }
+  else
+    {
+      dst_x1 = dst_x;
+      dst_y1 = cogl_framebuffer_get_height (dest) - dst_y;
+      dst_x2 = dst_x + width;
+      dst_y2 = dst_y1 - height;
+    }
+
+  ctx->glBlitFramebuffer (src_x1, src_y1, src_x2, src_y2,
+                          dst_x1, dst_y1, dst_x2, dst_y2,
                           GL_COLOR_BUFFER_BIT,
                           GL_NEAREST);
 }
diff --git a/cogl/cogl/driver/gl/cogl-framebuffer-gl.c b/cogl/cogl/driver/gl/cogl-framebuffer-gl.c
index b8fd2f689..ec9230c6a 100644
--- a/cogl/cogl/driver/gl/cogl-framebuffer-gl.c
+++ b/cogl/cogl/driver/gl/cogl-framebuffer-gl.c
@@ -385,12 +385,9 @@ _cogl_framebuffer_gl_flush_state (CoglFramebuffer *draw_buffer,
       else
         {
           /* NB: Currently we only take advantage of binding separate
-           * read/write buffers for offscreen framebuffer blit
-           * purposes.  */
+           * read/write buffers for framebuffer blit purposes. */
           g_return_if_fail (_cogl_has_private_feature
                                 (ctx, COGL_PRIVATE_FEATURE_OFFSCREEN_BLIT));
-          g_return_if_fail (draw_buffer->type == COGL_FRAMEBUFFER_TYPE_OFFSCREEN);
-          g_return_if_fail (read_buffer->type == COGL_FRAMEBUFFER_TYPE_OFFSCREEN);
 
           _cogl_framebuffer_gl_bind (draw_buffer, GL_DRAW_FRAMEBUFFER);
           _cogl_framebuffer_gl_bind (read_buffer, GL_READ_FRAMEBUFFER);


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]