diff --git a/SOURCES/0001-cogl-Remove-unused-OFFSCREEN_BLIT-feature-flag.patch b/SOURCES/0001-cogl-Remove-unused-OFFSCREEN_BLIT-feature-flag.patch new file mode 100644 index 0000000..b2965a3 --- /dev/null +++ b/SOURCES/0001-cogl-Remove-unused-OFFSCREEN_BLIT-feature-flag.patch @@ -0,0 +1,37 @@ +From 251ef4ff4bacefac211e21873e10da7fa067dd68 Mon Sep 17 00:00:00 2001 +From: Pekka Paalanen +Date: Fri, 26 Apr 2019 12:23:18 +0300 +Subject: [PATCH 01/12] cogl: Remove unused OFFSCREEN_BLIT feature flag + +This named constant is never used anywhere. + +https://gitlab.gnome.org/GNOME/mutter/merge_requests/615 + +(cherry picked from commit c08a24bb40ad7aa7746e86251c9dbe6c264b4d7c) +--- + cogl/cogl/cogl-types.h | 2 -- + 1 file changed, 2 deletions(-) + +diff --git a/cogl/cogl/cogl-types.h b/cogl/cogl/cogl-types.h +index 690daa16a..69d304cf0 100644 +--- a/cogl/cogl/cogl-types.h ++++ b/cogl/cogl/cogl-types.h +@@ -325,7 +325,6 @@ typedef enum /*< prefix=COGL_PIXEL_FORMAT >*/ + * @COGL_FEATURE_SHADERS_GLSL: GLSL support + * @COGL_FEATURE_OFFSCREEN: FBO support + * @COGL_FEATURE_OFFSCREEN_MULTISAMPLE: Multisample support on FBOs +- * @COGL_FEATURE_OFFSCREEN_BLIT: Blit support on FBOs + * @COGL_FEATURE_FOUR_CLIP_PLANES: At least 4 clip planes available + * @COGL_FEATURE_STENCIL_BUFFER: Stencil buffer support + * @COGL_FEATURE_VBOS: VBO support +@@ -368,7 +367,6 @@ typedef enum + COGL_FEATURE_SHADERS_GLSL = (1 << 5), + COGL_FEATURE_OFFSCREEN = (1 << 6), + COGL_FEATURE_OFFSCREEN_MULTISAMPLE = (1 << 7), +- COGL_FEATURE_OFFSCREEN_BLIT = (1 << 8), + COGL_FEATURE_FOUR_CLIP_PLANES = (1 << 9), + COGL_FEATURE_STENCIL_BUFFER = (1 << 10), + COGL_FEATURE_VBOS = (1 << 11), +-- +2.21.0 + diff --git a/SOURCES/0002-cogl-Fix-doc-for-_cogl_blit_framebuffer.patch b/SOURCES/0002-cogl-Fix-doc-for-_cogl_blit_framebuffer.patch new file mode 100644 index 0000000..510b926 --- /dev/null +++ b/SOURCES/0002-cogl-Fix-doc-for-_cogl_blit_framebuffer.patch @@ -0,0 +1,42 @@ +From 801da0dab1d2928578e9b191ee1684bcc7154081 Mon Sep 17 00:00:00 2001 +From: Pekka Paalanen +Date: Tue, 30 Apr 2019 17:01:04 +0300 +Subject: [PATCH 02/12] cogl: Fix doc for _cogl_blit_framebuffer + +Commit 38921701e533b7fda38a236cc45aec2ed3afef8a added explicit source and +destination parameters. Fix the documentation to match. + +https://gitlab.gnome.org/GNOME/mutter/merge_requests/615 + +(cherry picked from commit fc0ce11fcd997af12fc2253eeb37e03cebb5964f) +--- + cogl/cogl/cogl-framebuffer-private.h | 6 +++--- + 1 file changed, 3 insertions(+), 3 deletions(-) + +diff --git a/cogl/cogl/cogl-framebuffer-private.h b/cogl/cogl/cogl-framebuffer-private.h +index 296788c2b..de886b64f 100644 +--- a/cogl/cogl/cogl-framebuffer-private.h ++++ b/cogl/cogl/cogl-framebuffer-private.h +@@ -4,6 +4,7 @@ + * A Low Level GPU Graphics and Utilities API + * + * Copyright (C) 2007,2008,2009 Intel Corporation. ++ * Copyright (C) 2019 DisplayLink (UK) Ltd. + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation +@@ -377,9 +378,8 @@ _cogl_push_framebuffers (CoglFramebuffer *draw_buffer, + * @width: Width of region to copy + * @height: Height of region to copy + * +- * This blits a region of the color buffer of the current draw buffer +- * to the current read buffer. The draw and read buffers can be set up +- * using _cogl_push_framebuffers(). This function should only be ++ * 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 and have the + * same format. +-- +2.21.0 + diff --git a/SOURCES/0003-cogl-Replace-ANGLE-with-GLES3-and-NV-framebuffer_bli.patch b/SOURCES/0003-cogl-Replace-ANGLE-with-GLES3-and-NV-framebuffer_bli.patch new file mode 100644 index 0000000..b41fa93 --- /dev/null +++ b/SOURCES/0003-cogl-Replace-ANGLE-with-GLES3-and-NV-framebuffer_bli.patch @@ -0,0 +1,77 @@ +From 04d921c2c1da571c8c61a4ca12a380bc3b9623fe Mon Sep 17 00:00:00 2001 +From: Pekka Paalanen +Date: Mon, 6 May 2019 13:40:31 +0300 +Subject: [PATCH 03/12] cogl: Replace ANGLE with GLES3 and NV framebuffer_blit + +ANGLE extensions are only provided by Google's Almost Native Graphics Layer +Engine (ANGLE) implementation. Therefore they do not seem too useful for +Mutter. + +The reason to drop GL_ANGLE_framebuffer_blit support is that it has more +limitations compared to the glBlitFramebuffer in GL_EXT_framebuffer_blit, +GL_NV_framebuffer_bit, OpenGL 3.0 and OpenGL ES 3.0. Most importantly, the +ANGLE version cannot flip the image while copying, which limits +_cogl_blit_framebuffer to only off-screen <-> off-screen copies. Follow-up work +will need off-screen <-> on-screen copies. + +Instead of adding yet more capability flags to Cogl, dropping ANGLE support +seems appropriate. + +The NV extension is added to the list of glBlitFramebuffer providers because it +provides the same support as ANGLE and more. + +Likewise OpenGL ES 3.0 is added to the list of glBlitFramebuffer providers +because e.g. Mesa GLES implementation usually provides it and that makes it +widely available, again surpassing the ANGLE supported features. + +Follow-up patches will lift some of the Cogl assumptions of what +glBlitFramebuffer cannot do. + +https://gitlab.gnome.org/GNOME/mutter/merge_requests/615 + +(cherry picked from commit 3e68c9e8faa78298039fa3583898f18550740812) +--- + cogl/cogl/cogl-framebuffer-private.h | 3 +-- + cogl/cogl/gl-prototypes/cogl-all-functions.h | 5 +++-- + 2 files changed, 4 insertions(+), 4 deletions(-) + +diff --git a/cogl/cogl/cogl-framebuffer-private.h b/cogl/cogl/cogl-framebuffer-private.h +index de886b64f..3aab852c4 100644 +--- a/cogl/cogl/cogl-framebuffer-private.h ++++ b/cogl/cogl/cogl-framebuffer-private.h +@@ -387,8 +387,7 @@ _cogl_push_framebuffers (CoglFramebuffer *draw_buffer, + * Note that this function differs a lot from the glBlitFramebuffer + * function provided by the GL_EXT_framebuffer_blit extension. Notably + * it doesn't support having different sizes for the source and +- * destination rectangle. This isn't supported by the corresponding +- * GL_ANGLE_framebuffer_blit extension on GLES2.0 and it doesn't seem ++ * destination rectangle. This doesn't seem + * like a particularly useful feature. If the application wanted to + * scale the results it may make more sense to draw a primitive + * instead. +diff --git a/cogl/cogl/gl-prototypes/cogl-all-functions.h b/cogl/cogl/gl-prototypes/cogl-all-functions.h +index 924ee349d..0af126059 100644 +--- a/cogl/cogl/gl-prototypes/cogl-all-functions.h ++++ b/cogl/cogl/gl-prototypes/cogl-all-functions.h +@@ -4,6 +4,7 @@ + * A Low Level GPU Graphics and Utilities API + * + * Copyright (C) 2009, 2011 Intel Corporation. ++ * Copyright (C) 2019 DisplayLink (UK) Ltd. + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation +@@ -132,8 +133,8 @@ COGL_EXT_END () + + + COGL_EXT_BEGIN (offscreen_blit, 3, 0, +- 0, /* not in either GLES */ +- "EXT\0ANGLE\0", ++ COGL_EXT_IN_GLES3, ++ "EXT\0NV\0", + "framebuffer_blit\0") + COGL_EXT_FUNCTION (void, glBlitFramebuffer, + (GLint srcX0, +-- +2.21.0 + diff --git a/SOURCES/0004-cogl-Relax-formats-on-glBlitFramebuffer.patch b/SOURCES/0004-cogl-Relax-formats-on-glBlitFramebuffer.patch new file mode 100644 index 0000000..751e0cb --- /dev/null +++ b/SOURCES/0004-cogl-Relax-formats-on-glBlitFramebuffer.patch @@ -0,0 +1,100 @@ +From 6c6c6ad5412f5bb13592630d7cb3b7aed25d159b Mon Sep 17 00:00:00 2001 +From: Pekka Paalanen +Date: Mon, 6 May 2019 14:09:16 +0300 +Subject: [PATCH 04/12] cogl: Relax formats on glBlitFramebuffer + +Depends on: "cogl: Replace ANGLE with GLES3 and NV framebuffer_blit" + +As a possible ANGLE implementation is not longer limiting the pixel format +matching, lift the requirement of having the same pixel format. + +We still cannot do a premult <-> non-premult conversion during a blit, so guard +against that. + +This will be useful in follow-up work to copy from onscreen primary GPU +framebuffer to an offscreen secondary GPU framebuffer if the formats do not +match exactly. + +https://gitlab.gnome.org/GNOME/mutter/merge_requests/615 + +(cherry picked from commit 6df34eb4b7c65210f4066f7eb9bd462278b7279b) +--- + cogl/cogl/cogl-blit.c | 10 ++++++---- + cogl/cogl/cogl-framebuffer-private.h | 8 ++++++-- + cogl/cogl/cogl-framebuffer.c | 6 ++++-- + 3 files changed, 16 insertions(+), 8 deletions(-) + +diff --git a/cogl/cogl/cogl-blit.c b/cogl/cogl/cogl-blit.c +index 74f404f3d..a61eb66d2 100644 +--- a/cogl/cogl/cogl-blit.c ++++ b/cogl/cogl/cogl-blit.c +@@ -4,6 +4,7 @@ + * A Low Level GPU Graphics and Utilities API + * + * Copyright (C) 2011 Intel Corporation. ++ * Copyright (C) 2019 DisplayLink (UK) Ltd. + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation +@@ -152,10 +153,11 @@ _cogl_blit_framebuffer_begin (CoglBlitData *data) + CoglFramebuffer *dst_fb, *src_fb; + CoglError *ignore_error = NULL; + +- /* We can only blit between FBOs if both textures are the same +- format and the blit framebuffer extension is supported */ +- if ((_cogl_texture_get_format (data->src_tex) & ~COGL_A_BIT) != +- (_cogl_texture_get_format (data->dst_tex) & ~COGL_A_BIT) || ++ /* We can only blit between FBOs if both textures have the same ++ premult convention and the blit framebuffer extension is ++ supported. */ ++ if ((_cogl_texture_get_format (data->src_tex) & COGL_PREMULT_BIT) != ++ (_cogl_texture_get_format (data->dst_tex) & COGL_PREMULT_BIT) || + !_cogl_has_private_feature (ctx, COGL_PRIVATE_FEATURE_OFFSCREEN_BLIT)) + return FALSE; + +diff --git a/cogl/cogl/cogl-framebuffer-private.h b/cogl/cogl/cogl-framebuffer-private.h +index 3aab852c4..b06fbaee1 100644 +--- a/cogl/cogl/cogl-framebuffer-private.h ++++ b/cogl/cogl/cogl-framebuffer-private.h +@@ -381,8 +381,12 @@ _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 and have the +- * same format. ++ * advertised. The two buffers must both be offscreen. ++ * ++ * 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 ++ * need to match. This limitation comes from OpenGL ES 3.0 definition ++ * of glBlitFramebuffer. + * + * Note that this function differs a lot from the glBlitFramebuffer + * function provided by the GL_EXT_framebuffer_blit extension. Notably +diff --git a/cogl/cogl/cogl-framebuffer.c b/cogl/cogl/cogl-framebuffer.c +index bd8a7fa42..0bc225945 100644 +--- a/cogl/cogl/cogl-framebuffer.c ++++ b/cogl/cogl/cogl-framebuffer.c +@@ -4,6 +4,7 @@ + * A Low Level GPU Graphics and Utilities API + * + * Copyright (C) 2007,2008,2009,2012 Intel Corporation. ++ * Copyright (C) 2019 DisplayLink (UK) Ltd. + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation +@@ -1468,8 +1469,9 @@ _cogl_blit_framebuffer (CoglFramebuffer *src, + support this */ + _COGL_RETURN_IF_FAIL (cogl_is_offscreen (src)); + _COGL_RETURN_IF_FAIL (cogl_is_offscreen (dest)); +- /* The buffers must be the same format */ +- _COGL_RETURN_IF_FAIL (src->internal_format == dest->internal_format); ++ /* The buffers must use the same premult convention */ ++ _COGL_RETURN_IF_FAIL ((src->internal_format & COGL_PREMULT_BIT) == ++ (dest->internal_format & COGL_PREMULT_BIT)); + + /* Make sure the current framebuffers are bound. We explicitly avoid + flushing the clip state so we can bind our own empty state */ +-- +2.21.0 + diff --git a/SOURCES/0005-cogl-Allow-glBlitFramebuffer-between-onscreen-offscr.patch b/SOURCES/0005-cogl-Allow-glBlitFramebuffer-between-onscreen-offscr.patch new file mode 100644 index 0000000..81d49d6 --- /dev/null +++ b/SOURCES/0005-cogl-Allow-glBlitFramebuffer-between-onscreen-offscr.patch @@ -0,0 +1,145 @@ +From e4b2234d9918e9d3357ac3c7ca3898599725d3da Mon Sep 17 00:00:00 2001 +From: Pekka Paalanen +Date: Mon, 6 May 2019 15:08:29 +0300 +Subject: [PATCH 05/12] 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 + +(cherry picked from commit 45289b3d65e308117f1bc8fe6a4c88c1baaacca7) +--- + 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 b06fbaee1..f68153d8b 100644 +--- a/cogl/cogl/cogl-framebuffer-private.h ++++ b/cogl/cogl/cogl-framebuffer-private.h +@@ -381,7 +381,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 +@@ -396,14 +400,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 0bc225945..90976a611 100644 +--- a/cogl/cogl/cogl-framebuffer.c ++++ b/cogl/cogl/cogl-framebuffer.c +@@ -1460,15 +1460,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; + + _COGL_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 */ +- _COGL_RETURN_IF_FAIL (cogl_is_offscreen (src)); +- _COGL_RETURN_IF_FAIL (cogl_is_offscreen (dest)); + /* The buffers must use the same premult convention */ + _COGL_RETURN_IF_FAIL ((src->internal_format & COGL_PREMULT_BIT) == + (dest->internal_format & COGL_PREMULT_BIT)); +@@ -1492,10 +1489,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 5402a7075..83e1d263a 100644 +--- a/cogl/cogl/driver/gl/cogl-framebuffer-gl.c ++++ b/cogl/cogl/driver/gl/cogl-framebuffer-gl.c +@@ -400,12 +400,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. */ + _COGL_RETURN_IF_FAIL (_cogl_has_private_feature + (ctx, COGL_PRIVATE_FEATURE_OFFSCREEN_BLIT)); +- _COGL_RETURN_IF_FAIL (draw_buffer->type == COGL_FRAMEBUFFER_TYPE_OFFSCREEN); +- _COGL_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); +-- +2.21.0 + diff --git a/SOURCES/0006-cogl-Rename-feature-OFFSCREEN_BLIT-to-BLIT_FRAMEBUFF.patch b/SOURCES/0006-cogl-Rename-feature-OFFSCREEN_BLIT-to-BLIT_FRAMEBUFF.patch new file mode 100644 index 0000000..6bc5e2c --- /dev/null +++ b/SOURCES/0006-cogl-Rename-feature-OFFSCREEN_BLIT-to-BLIT_FRAMEBUFF.patch @@ -0,0 +1,115 @@ +From 579c85d17b17fc7ad3d6c88af39932ce8faeaabe Mon Sep 17 00:00:00 2001 +From: Pekka Paalanen +Date: Mon, 6 May 2019 15:58:33 +0300 +Subject: [PATCH 06/12] cogl: Rename feature OFFSCREEN_BLIT to BLIT_FRAMEBUFFER + +The feature is not limited to offscreen framebuffer blits anymore since +"cogl: Allow glBlitFramebuffer between onscreen/offscreen". + +https://gitlab.gnome.org/GNOME/mutter/merge_requests/615 + +(cherry picked from commit 55c084e6e1059d8f94c699b01c408523ed504196) +--- + cogl/cogl/cogl-blit.c | 2 +- + cogl/cogl/cogl-framebuffer-private.h | 2 +- + cogl/cogl/cogl-framebuffer.c | 2 +- + cogl/cogl/cogl-private.h | 2 +- + cogl/cogl/driver/gl/cogl-framebuffer-gl.c | 2 +- + cogl/cogl/driver/gl/gl/cogl-driver-gl.c | 2 +- + cogl/cogl/driver/gl/gles/cogl-driver-gles.c | 2 +- + 7 files changed, 7 insertions(+), 7 deletions(-) + +diff --git a/cogl/cogl/cogl-blit.c b/cogl/cogl/cogl-blit.c +index a61eb66d2..c561b2e45 100644 +--- a/cogl/cogl/cogl-blit.c ++++ b/cogl/cogl/cogl-blit.c +@@ -158,7 +158,7 @@ _cogl_blit_framebuffer_begin (CoglBlitData *data) + supported. */ + if ((_cogl_texture_get_format (data->src_tex) & COGL_PREMULT_BIT) != + (_cogl_texture_get_format (data->dst_tex) & COGL_PREMULT_BIT) || +- !_cogl_has_private_feature (ctx, COGL_PRIVATE_FEATURE_OFFSCREEN_BLIT)) ++ !_cogl_has_private_feature (ctx, COGL_PRIVATE_FEATURE_BLIT_FRAMEBUFFER)) + return FALSE; + + dst_offscreen = _cogl_offscreen_new_with_texture_full +diff --git a/cogl/cogl/cogl-framebuffer-private.h b/cogl/cogl/cogl-framebuffer-private.h +index f68153d8b..cb1f87354 100644 +--- a/cogl/cogl/cogl-framebuffer-private.h ++++ b/cogl/cogl/cogl-framebuffer-private.h +@@ -380,7 +380,7 @@ _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 ++ * called if the COGL_PRIVATE_FEATURE_BLIT_FRAMEBUFFER feature is + * advertised. + * + * The source and destination rectangles are defined in offscreen +diff --git a/cogl/cogl/cogl-framebuffer.c b/cogl/cogl/cogl-framebuffer.c +index 90976a611..5cc4eada4 100644 +--- a/cogl/cogl/cogl-framebuffer.c ++++ b/cogl/cogl/cogl-framebuffer.c +@@ -1464,7 +1464,7 @@ _cogl_blit_framebuffer (CoglFramebuffer *src, + int dst_x1, dst_y1, dst_x2, dst_y2; + + _COGL_RETURN_IF_FAIL (_cogl_has_private_feature +- (ctx, COGL_PRIVATE_FEATURE_OFFSCREEN_BLIT)); ++ (ctx, COGL_PRIVATE_FEATURE_BLIT_FRAMEBUFFER)); + + /* The buffers must use the same premult convention */ + _COGL_RETURN_IF_FAIL ((src->internal_format & COGL_PREMULT_BIT) == +diff --git a/cogl/cogl/cogl-private.h b/cogl/cogl/cogl-private.h +index 9f918b851..d9fbe68c7 100644 +--- a/cogl/cogl/cogl-private.h ++++ b/cogl/cogl/cogl-private.h +@@ -42,7 +42,7 @@ typedef enum + { + COGL_PRIVATE_FEATURE_TEXTURE_2D_FROM_EGL_IMAGE, + COGL_PRIVATE_FEATURE_MESA_PACK_INVERT, +- COGL_PRIVATE_FEATURE_OFFSCREEN_BLIT, ++ COGL_PRIVATE_FEATURE_BLIT_FRAMEBUFFER, + COGL_PRIVATE_FEATURE_FOUR_CLIP_PLANES, + COGL_PRIVATE_FEATURE_PBOS, + COGL_PRIVATE_FEATURE_VBOS, +diff --git a/cogl/cogl/driver/gl/cogl-framebuffer-gl.c b/cogl/cogl/driver/gl/cogl-framebuffer-gl.c +index 83e1d263a..90d08954d 100644 +--- a/cogl/cogl/driver/gl/cogl-framebuffer-gl.c ++++ b/cogl/cogl/driver/gl/cogl-framebuffer-gl.c +@@ -402,7 +402,7 @@ _cogl_framebuffer_gl_flush_state (CoglFramebuffer *draw_buffer, + /* NB: Currently we only take advantage of binding separate + * read/write buffers for framebuffer blit purposes. */ + _COGL_RETURN_IF_FAIL (_cogl_has_private_feature +- (ctx, COGL_PRIVATE_FEATURE_OFFSCREEN_BLIT)); ++ (ctx, COGL_PRIVATE_FEATURE_BLIT_FRAMEBUFFER)); + + _cogl_framebuffer_gl_bind (draw_buffer, GL_DRAW_FRAMEBUFFER); + _cogl_framebuffer_gl_bind (read_buffer, GL_READ_FRAMEBUFFER); +diff --git a/cogl/cogl/driver/gl/gl/cogl-driver-gl.c b/cogl/cogl/driver/gl/gl/cogl-driver-gl.c +index 4d46844d5..e06e27961 100644 +--- a/cogl/cogl/driver/gl/gl/cogl-driver-gl.c ++++ b/cogl/cogl/driver/gl/gl/cogl-driver-gl.c +@@ -467,7 +467,7 @@ _cogl_driver_update_features (CoglContext *ctx, + + if (ctx->glBlitFramebuffer) + COGL_FLAGS_SET (private_features, +- COGL_PRIVATE_FEATURE_OFFSCREEN_BLIT, TRUE); ++ COGL_PRIVATE_FEATURE_BLIT_FRAMEBUFFER, TRUE); + + if (ctx->glRenderbufferStorageMultisampleIMG) + { +diff --git a/cogl/cogl/driver/gl/gles/cogl-driver-gles.c b/cogl/cogl/driver/gl/gles/cogl-driver-gles.c +index 23158d5c7..bcb0bdf07 100644 +--- a/cogl/cogl/driver/gl/gles/cogl-driver-gles.c ++++ b/cogl/cogl/driver/gl/gles/cogl-driver-gles.c +@@ -326,7 +326,7 @@ _cogl_driver_update_features (CoglContext *context, + + if (context->glBlitFramebuffer) + COGL_FLAGS_SET (private_features, +- COGL_PRIVATE_FEATURE_OFFSCREEN_BLIT, TRUE); ++ COGL_PRIVATE_FEATURE_BLIT_FRAMEBUFFER, TRUE); + + if (_cogl_check_extension ("GL_OES_element_index_uint", gl_extensions)) + { +-- +2.21.0 + diff --git a/SOURCES/0007-cogl-Expose-cogl_blit_framebuffer.patch b/SOURCES/0007-cogl-Expose-cogl_blit_framebuffer.patch new file mode 100644 index 0000000..a5c9686 --- /dev/null +++ b/SOURCES/0007-cogl-Expose-cogl_blit_framebuffer.patch @@ -0,0 +1,261 @@ +From be13d3c844a6623563ae4e74dbb3409baf16fc9c Mon Sep 17 00:00:00 2001 +From: Pekka Paalanen +Date: Mon, 3 Dec 2018 14:34:41 +0200 +Subject: [PATCH 07/12] cogl: Expose cogl_blit_framebuffer + +The function will be used in copying from a primary GPU framebuffer to a +secondary GPU framebuffer using the primary GPU specifically when the +secondary GPU is not render-capable. + +To allow falling back in case glBlitFramebuffer cannot be used, add boolean +return value, and GError argument for debugging purposes. + +https://gitlab.gnome.org/GNOME/mutter/merge_requests/615 +(cherry picked from commit 6061abbf90cd1d62e262ebf3636470d2219e04a7) +--- + cogl/cogl/cogl-blit.c | 11 ++--- + cogl/cogl/cogl-framebuffer-private.h | 55 ----------------------- + cogl/cogl/cogl-framebuffer.c | 40 +++++++++++------ + cogl/cogl/cogl-framebuffer.h | 66 +++++++++++++++++++++++++++- + 4 files changed, 98 insertions(+), 74 deletions(-) + +diff --git a/cogl/cogl/cogl-blit.c b/cogl/cogl/cogl-blit.c +index c561b2e45..ae5a8a345 100644 +--- a/cogl/cogl/cogl-blit.c ++++ b/cogl/cogl/cogl-blit.c +@@ -207,11 +207,12 @@ _cogl_blit_framebuffer_blit (CoglBlitData *data, + int width, + int height) + { +- _cogl_blit_framebuffer (data->src_fb, +- data->dest_fb, +- src_x, src_y, +- dst_x, dst_y, +- width, height); ++ cogl_blit_framebuffer (data->src_fb, ++ data->dest_fb, ++ src_x, src_y, ++ dst_x, dst_y, ++ width, height, ++ NULL); + } + + static void +diff --git a/cogl/cogl/cogl-framebuffer-private.h b/cogl/cogl/cogl-framebuffer-private.h +index cb1f87354..7d71fb1dc 100644 +--- a/cogl/cogl/cogl-framebuffer-private.h ++++ b/cogl/cogl/cogl-framebuffer-private.h +@@ -367,61 +367,6 @@ void + _cogl_push_framebuffers (CoglFramebuffer *draw_buffer, + CoglFramebuffer *read_buffer); + +-/* +- * _cogl_blit_framebuffer: +- * @src: The source #CoglFramebuffer +- * @dest: The destination #CoglFramebuffer +- * @src_x: Source x position +- * @src_y: Source y position +- * @dst_x: Destination x position +- * @dst_y: Destination y position +- * @width: Width of region to copy +- * @height: Height of region to copy +- * +- * 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_BLIT_FRAMEBUFFER feature is +- * 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 +- * need to match. This limitation comes from OpenGL ES 3.0 definition +- * of glBlitFramebuffer. +- * +- * Note that this function differs a lot from the glBlitFramebuffer +- * function provided by the GL_EXT_framebuffer_blit extension. Notably +- * it doesn't support having different sizes for the source and +- * destination rectangle. This doesn't seem +- * like a particularly useful feature. If the application wanted to +- * scale the results it may make more sense to draw a primitive +- * instead. +- * +- * 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 +- * ignored. +- * +- * The function also doesn't support specifying the buffers to copy +- * and instead only the color buffer is copied. When copying the depth +- * or stencil buffers the extension on GLES2.0 only supports copying +- * the full buffer which would be awkward to document with this +- * API. If we wanted to support that feature it may be better to have +- * a separate function to copy the entire buffer for a given mask. +- */ +-void +-_cogl_blit_framebuffer (CoglFramebuffer *src, +- CoglFramebuffer *dest, +- int src_x, +- int src_y, +- int dst_x, +- int dst_y, +- int width, +- int height); +- + void + _cogl_framebuffer_push_projection (CoglFramebuffer *framebuffer); + +diff --git a/cogl/cogl/cogl-framebuffer.c b/cogl/cogl/cogl-framebuffer.c +index 5cc4eada4..6d35c6b13 100644 +--- a/cogl/cogl/cogl-framebuffer.c ++++ b/cogl/cogl/cogl-framebuffer.c +@@ -1449,26 +1449,38 @@ cogl_framebuffer_read_pixels (CoglFramebuffer *framebuffer, + return ret; + } + +-void +-_cogl_blit_framebuffer (CoglFramebuffer *src, +- CoglFramebuffer *dest, +- int src_x, +- int src_y, +- int dst_x, +- int dst_y, +- int width, +- int height) ++gboolean ++cogl_blit_framebuffer (CoglFramebuffer *src, ++ CoglFramebuffer *dest, ++ int src_x, ++ int src_y, ++ int dst_x, ++ int dst_y, ++ int width, ++ int height, ++ GError **error) + { + CoglContext *ctx = src->context; + int src_x1, src_y1, src_x2, src_y2; + int dst_x1, dst_y1, dst_x2, dst_y2; + +- _COGL_RETURN_IF_FAIL (_cogl_has_private_feature +- (ctx, COGL_PRIVATE_FEATURE_BLIT_FRAMEBUFFER)); ++ if (!_cogl_has_private_feature (ctx, COGL_PRIVATE_FEATURE_BLIT_FRAMEBUFFER)) ++ { ++ g_set_error_literal (error, COGL_SYSTEM_ERROR, ++ COGL_SYSTEM_ERROR_UNSUPPORTED, ++ "Cogl BLIT_FRAMEBUFFER is not supported by the system."); ++ return FALSE; ++ } + + /* The buffers must use the same premult convention */ +- _COGL_RETURN_IF_FAIL ((src->internal_format & COGL_PREMULT_BIT) == +- (dest->internal_format & COGL_PREMULT_BIT)); ++ if ((src->internal_format & COGL_PREMULT_BIT) != ++ (dest->internal_format & COGL_PREMULT_BIT)) ++ { ++ g_set_error_literal (error, COGL_SYSTEM_ERROR, ++ COGL_SYSTEM_ERROR_UNSUPPORTED, ++ "cogl_blit_framebuffer premult mismatch."); ++ return FALSE; ++ } + + /* Make sure the current framebuffers are bound. We explicitly avoid + flushing the clip state so we can bind our own empty state */ +@@ -1526,6 +1538,8 @@ _cogl_blit_framebuffer (CoglFramebuffer *src, + dst_x1, dst_y1, dst_x2, dst_y2, + GL_COLOR_BUFFER_BIT, + GL_NEAREST); ++ ++ return TRUE; + } + + void +diff --git a/cogl/cogl/cogl-framebuffer.h b/cogl/cogl/cogl-framebuffer.h +index 48a77e1ed..230a78627 100644 +--- a/cogl/cogl/cogl-framebuffer.h ++++ b/cogl/cogl/cogl-framebuffer.h +@@ -3,7 +3,8 @@ + * + * A Low Level GPU Graphics and Utilities API + * +- * Copyright (C) 2011 Intel Corporation. ++ * Copyright (C) 2007,2008,2009,2011 Intel Corporation. ++ * Copyright (C) 2019 DisplayLink (UK) Ltd. + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation +@@ -1846,6 +1847,69 @@ typedef enum /*< prefix=COGL_FRAMEBUFFER_ERROR >*/ + gboolean + cogl_is_framebuffer (void *object); + ++/** ++ * cogl_blit_framebuffer: ++ * @src: The source #CoglFramebuffer ++ * @dest: The destination #CoglFramebuffer ++ * @src_x: Source x position ++ * @src_y: Source y position ++ * @dst_x: Destination x position ++ * @dst_y: Destination y position ++ * @width: Width of region to copy ++ * @height: Height of region to copy ++ * @error: optional error object ++ * ++ * @return FALSE for an immediately detected error, TRUE otherwise. ++ * ++ * 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_BLIT_FRAMEBUFFER feature is ++ * 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 ++ * need to match. This limitation comes from OpenGL ES 3.0 definition ++ * of glBlitFramebuffer. ++ * ++ * Note that this function differs a lot from the glBlitFramebuffer ++ * function provided by the GL_EXT_framebuffer_blit extension. Notably ++ * it doesn't support having different sizes for the source and ++ * destination rectangle. This doesn't seem ++ * like a particularly useful feature. If the application wanted to ++ * scale the results it may make more sense to draw a primitive ++ * instead. ++ * ++ * 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 ++ * ignored. ++ * ++ * The function also doesn't support specifying the buffers to copy ++ * and instead only the color buffer is copied. When copying the depth ++ * or stencil buffers the extension on GLES2.0 only supports copying ++ * the full buffer which would be awkward to document with this ++ * API. If we wanted to support that feature it may be better to have ++ * a separate function to copy the entire buffer for a given mask. ++ * ++ * The @c error argument is optional, it can be NULL. If it is not NULL ++ * and this function returns FALSE, an error object with a code from ++ * COGL_SYSTEM_ERROR will be created. ++ */ ++gboolean ++cogl_blit_framebuffer (CoglFramebuffer *src, ++ CoglFramebuffer *dest, ++ int src_x, ++ int src_y, ++ int dst_x, ++ int dst_y, ++ int width, ++ int height, ++ GError **error); ++ + G_END_DECLS + + #endif /* __COGL_FRAMEBUFFER_H */ +-- +2.21.0 + diff --git a/SOURCES/0008-clutter-stage-view-Use-cogl_blit_framebuffer-for-sha.patch b/SOURCES/0008-clutter-stage-view-Use-cogl_blit_framebuffer-for-sha.patch new file mode 100644 index 0000000..09e8db9 --- /dev/null +++ b/SOURCES/0008-clutter-stage-view-Use-cogl_blit_framebuffer-for-sha.patch @@ -0,0 +1,42 @@ +From bbeb161e8ab31bbef3c7d378e9a8d4ecc786c25d Mon Sep 17 00:00:00 2001 +From: Olivier Fourdan +Date: Thu, 26 Sep 2019 10:20:36 +0200 +Subject: [PATCH 08/12] clutter/stage-view: Use cogl_blit_framebuffer() for + shadow FB + +If there is no transformation, use `cogl_blit_framebuffer()` as a +shortcut in `clutter_stage_view_blit_offscreen()`, that dramatically +improves performance when using a shadow framebuffer. + +https://gitlab.gnome.org/GNOME/mutter/merge_requests/809 +(cherry picked from commit 3400c555a032832a689c208486891352a6cb92de) +--- + clutter/clutter/clutter-stage-view.c | 12 ++++++++++++ + 1 file changed, 12 insertions(+) + +diff --git a/clutter/clutter/clutter-stage-view.c b/clutter/clutter/clutter-stage-view.c +index cd6cd35cb..00cbfd1ce 100644 +--- a/clutter/clutter/clutter-stage-view.c ++++ b/clutter/clutter/clutter-stage-view.c +@@ -126,6 +126,18 @@ clutter_stage_view_blit_offscreen (ClutterStageView *view, + clutter_stage_view_get_instance_private (view); + CoglMatrix matrix; + ++ clutter_stage_view_get_offscreen_transformation_matrix (view, &matrix); ++ if (cogl_matrix_is_identity (&matrix)) ++ { ++ if (cogl_blit_framebuffer (priv->offscreen, ++ priv->framebuffer, ++ rect->x, rect->y, ++ rect->x, rect->y, ++ rect->width, rect->height, ++ NULL)) ++ return; ++ } ++ + clutter_stage_view_ensure_offscreen_blit_pipeline (view); + cogl_framebuffer_push_matrix (priv->framebuffer); + +-- +2.21.0 + diff --git a/SOURCES/0009-clutter-stage-view-Ignore-clipping-rectangle-for-off.patch b/SOURCES/0009-clutter-stage-view-Ignore-clipping-rectangle-for-off.patch new file mode 100644 index 0000000..ea67449 --- /dev/null +++ b/SOURCES/0009-clutter-stage-view-Ignore-clipping-rectangle-for-off.patch @@ -0,0 +1,49 @@ +From 46bb54bcd9c90f90dd170355209f8c379680d5c1 Mon Sep 17 00:00:00 2001 +From: Olivier Fourdan +Date: Tue, 1 Oct 2019 14:16:25 +0200 +Subject: [PATCH 09/12] clutter/stage-view: Ignore clipping rectangle for + offscreen blit +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +In `clutter_stage_view_blit_offscreen()`, the given clipping rectangle +is in “view” coordinates whereas we intend to copy the whole actual +framebuffer, meaning that we cannot use the clipping rectangle. + +Use the actual framebuffer size, starting at (0, 0) instead. + +That fixes the issue with partial repainting with shadow framebuffer +when fractional scaling is enabled. + +https://gitlab.gnome.org/GNOME/mutter/merge_requests/820 +(cherry picked from commit 0a3f25c3039b586f5b5721e91136c5d2fccecca1) +--- + clutter/clutter/clutter-stage-view.c | 9 ++++++--- + 1 file changed, 6 insertions(+), 3 deletions(-) + +diff --git a/clutter/clutter/clutter-stage-view.c b/clutter/clutter/clutter-stage-view.c +index 00cbfd1ce..503c31e78 100644 +--- a/clutter/clutter/clutter-stage-view.c ++++ b/clutter/clutter/clutter-stage-view.c +@@ -129,11 +129,14 @@ clutter_stage_view_blit_offscreen (ClutterStageView *view, + clutter_stage_view_get_offscreen_transformation_matrix (view, &matrix); + if (cogl_matrix_is_identity (&matrix)) + { ++ int fb_width = cogl_framebuffer_get_width (priv->framebuffer); ++ int fb_height = cogl_framebuffer_get_height (priv->framebuffer); ++ + if (cogl_blit_framebuffer (priv->offscreen, + priv->framebuffer, +- rect->x, rect->y, +- rect->x, rect->y, +- rect->width, rect->height, ++ 0, 0, ++ 0, 0, ++ fb_width, fb_height, + NULL)) + return; + } +-- +2.21.0 + diff --git a/SOURCES/0010-cogl-Flush-journal-before-blitting.patch b/SOURCES/0010-cogl-Flush-journal-before-blitting.patch new file mode 100644 index 0000000..f3935eb --- /dev/null +++ b/SOURCES/0010-cogl-Flush-journal-before-blitting.patch @@ -0,0 +1,34 @@ +From 4c7fe200e05f9a028d440ed2032961d1b798c83b Mon Sep 17 00:00:00 2001 +From: Olivier Fourdan +Date: Tue, 1 Oct 2019 15:54:47 +0200 +Subject: [PATCH 10/12] cogl: Flush journal before blitting + +Make sure to submit all pending primitives before blitting, otherwise +rendering from the shell may be incomplete leaving partial drawing of +the shell widgets. + +https://gitlab.gnome.org/GNOME/mutter/merge_requests/820 +(cherry picked from commit 0cdf13ac12c570d38737fddb68946157c0b7a4d2) +--- + cogl/cogl/cogl-framebuffer.c | 5 +++++ + 1 file changed, 5 insertions(+) + +diff --git a/cogl/cogl/cogl-framebuffer.c b/cogl/cogl/cogl-framebuffer.c +index 6d35c6b13..948cd112d 100644 +--- a/cogl/cogl/cogl-framebuffer.c ++++ b/cogl/cogl/cogl-framebuffer.c +@@ -1482,6 +1482,11 @@ cogl_blit_framebuffer (CoglFramebuffer *src, + return FALSE; + } + ++ /* Make sure any batched primitives get submitted to the driver ++ * before blitting ++ */ ++ _cogl_framebuffer_flush_journal (src); ++ + /* Make sure the current framebuffers are bound. We explicitly avoid + flushing the clip state so we can bind our own empty state */ + _cogl_framebuffer_flush_state (dest, +-- +2.21.0 + diff --git a/SOURCES/0011-clutter-stage-view-Separate-offscreen-and-shadowfb.patch b/SOURCES/0011-clutter-stage-view-Separate-offscreen-and-shadowfb.patch new file mode 100644 index 0000000..9dd46a0 --- /dev/null +++ b/SOURCES/0011-clutter-stage-view-Separate-offscreen-and-shadowfb.patch @@ -0,0 +1,304 @@ +From cf8f1fb8478e4b76c91e825d1537396b014689a0 Mon Sep 17 00:00:00 2001 +From: Olivier Fourdan +Date: Tue, 22 Oct 2019 17:03:03 +0200 +Subject: [PATCH 11/12] clutter/stage-view: Separate offscreen and shadowfb + +Previously, we would use a single offscreen framebuffer for both +transformations and when a shadow framebuffer should be used, but that +can be dreadfully slow when using software rendering with a discrete GPU +due to bandwidth limitations. + +Keep the offscreen framebuffer for transformations only and add another +intermediate shadow framebuffer used as a copy of the onscreen +framebuffer. + +https://gitlab.gnome.org/GNOME/mutter/merge_requests/917 + +(cherry picked from commit 2b8b450fe16c21f0f37a1779560c0e5da61a9b89) +--- + clutter/clutter/clutter-stage-view.c | 162 +++++++++++++++++----- + clutter/clutter/cogl/clutter-stage-cogl.c | 6 +- + 2 files changed, 128 insertions(+), 40 deletions(-) + +diff --git a/clutter/clutter/clutter-stage-view.c b/clutter/clutter/clutter-stage-view.c +index 503c31e78..c536ac720 100644 +--- a/clutter/clutter/clutter-stage-view.c ++++ b/clutter/clutter/clutter-stage-view.c +@@ -29,6 +29,7 @@ enum + PROP_LAYOUT, + PROP_FRAMEBUFFER, + PROP_OFFSCREEN, ++ PROP_SHADOWFB, + PROP_SCALE, + + PROP_LAST +@@ -43,7 +44,10 @@ typedef struct _ClutterStageViewPrivate + CoglFramebuffer *framebuffer; + + CoglOffscreen *offscreen; +- CoglPipeline *pipeline; ++ CoglPipeline *offscreen_pipeline; ++ ++ CoglOffscreen *shadowfb; ++ CoglPipeline *shadowfb_pipeline; + + guint dirty_viewport : 1; + guint dirty_projection : 1; +@@ -69,6 +73,8 @@ clutter_stage_view_get_framebuffer (ClutterStageView *view) + + if (priv->offscreen) + return priv->offscreen; ++ else if (priv->shadowfb) ++ return priv->shadowfb; + else + return priv->framebuffer; + } +@@ -82,6 +88,24 @@ clutter_stage_view_get_onscreen (ClutterStageView *view) + return priv->framebuffer; + } + ++static CoglPipeline * ++clutter_stage_view_create_framebuffer_pipeline (CoglFramebuffer *framebuffer) ++{ ++ CoglPipeline *pipeline; ++ ++ pipeline = cogl_pipeline_new (cogl_framebuffer_get_context (framebuffer)); ++ ++ cogl_pipeline_set_layer_filters (pipeline, 0, ++ COGL_PIPELINE_FILTER_NEAREST, ++ COGL_PIPELINE_FILTER_NEAREST); ++ cogl_pipeline_set_layer_texture (pipeline, 0, ++ cogl_offscreen_get_texture (framebuffer)); ++ cogl_pipeline_set_layer_wrap_mode (pipeline, 0, ++ COGL_PIPELINE_WRAP_MODE_CLAMP_TO_EDGE); ++ ++ return pipeline; ++} ++ + static void + clutter_stage_view_ensure_offscreen_blit_pipeline (ClutterStageView *view) + { +@@ -92,71 +116,122 @@ clutter_stage_view_ensure_offscreen_blit_pipeline (ClutterStageView *view) + + g_assert (priv->offscreen != NULL); + +- if (priv->pipeline) ++ if (priv->offscreen_pipeline) + return; + +- priv->pipeline = +- cogl_pipeline_new (cogl_framebuffer_get_context (priv->offscreen)); +- cogl_pipeline_set_layer_filters (priv->pipeline, 0, +- COGL_PIPELINE_FILTER_NEAREST, +- COGL_PIPELINE_FILTER_NEAREST); +- cogl_pipeline_set_layer_texture (priv->pipeline, 0, +- cogl_offscreen_get_texture (priv->offscreen)); +- cogl_pipeline_set_layer_wrap_mode (priv->pipeline, 0, +- COGL_PIPELINE_WRAP_MODE_CLAMP_TO_EDGE); ++ priv->offscreen_pipeline = ++ clutter_stage_view_create_framebuffer_pipeline (priv->offscreen); + + if (view_class->setup_offscreen_blit_pipeline) +- view_class->setup_offscreen_blit_pipeline (view, priv->pipeline); ++ view_class->setup_offscreen_blit_pipeline (view, priv->offscreen_pipeline); + } + +-void +-clutter_stage_view_invalidate_offscreen_blit_pipeline (ClutterStageView *view) ++static void ++clutter_stage_view_ensure_shadowfb_blit_pipeline (ClutterStageView *view) + { + ClutterStageViewPrivate *priv = + clutter_stage_view_get_instance_private (view); + +- g_clear_pointer (&priv->pipeline, cogl_object_unref); ++ if (priv->shadowfb_pipeline) ++ return; ++ ++ priv->shadowfb_pipeline = ++ clutter_stage_view_create_framebuffer_pipeline (priv->shadowfb); + } + + void +-clutter_stage_view_blit_offscreen (ClutterStageView *view, +- const cairo_rectangle_int_t *rect) ++clutter_stage_view_invalidate_offscreen_blit_pipeline (ClutterStageView *view) + { + ClutterStageViewPrivate *priv = + clutter_stage_view_get_instance_private (view); ++ ++ g_clear_pointer (&priv->offscreen_pipeline, cogl_object_unref); ++} ++ ++static void ++clutter_stage_view_copy_to_framebuffer (ClutterStageView *view, ++ const cairo_rectangle_int_t *rect, ++ CoglPipeline *pipeline, ++ CoglFramebuffer *src_framebuffer, ++ CoglFramebuffer *dst_framebuffer, ++ gboolean can_blit) ++{ + CoglMatrix matrix; + +- clutter_stage_view_get_offscreen_transformation_matrix (view, &matrix); +- if (cogl_matrix_is_identity (&matrix)) ++ /* First, try with blit */ ++ if (can_blit) + { +- int fb_width = cogl_framebuffer_get_width (priv->framebuffer); +- int fb_height = cogl_framebuffer_get_height (priv->framebuffer); +- +- if (cogl_blit_framebuffer (priv->offscreen, +- priv->framebuffer, ++ if (cogl_blit_framebuffer (src_framebuffer, ++ dst_framebuffer, + 0, 0, + 0, 0, +- fb_width, fb_height, ++ cogl_framebuffer_get_width (dst_framebuffer), ++ cogl_framebuffer_get_height (dst_framebuffer), + NULL)) + return; + } + +- clutter_stage_view_ensure_offscreen_blit_pipeline (view); +- cogl_framebuffer_push_matrix (priv->framebuffer); ++ /* If blit fails, fallback to the slower painting method */ ++ cogl_framebuffer_push_matrix (dst_framebuffer); + +- /* Set transform so 0,0 is on the top left corner and 1,1 on +- * the bottom right corner. +- */ + cogl_matrix_init_identity (&matrix); + cogl_matrix_translate (&matrix, -1, 1, 0); + cogl_matrix_scale (&matrix, 2, -2, 0); +- cogl_framebuffer_set_projection_matrix (priv->framebuffer, &matrix); ++ cogl_framebuffer_set_projection_matrix (dst_framebuffer, &matrix); + +- cogl_framebuffer_draw_rectangle (priv->framebuffer, +- priv->pipeline, ++ cogl_framebuffer_draw_rectangle (dst_framebuffer, ++ pipeline, + 0, 0, 1, 1); + +- cogl_framebuffer_pop_matrix (priv->framebuffer); ++ cogl_framebuffer_pop_matrix (dst_framebuffer); ++} ++ ++void ++clutter_stage_view_blit_offscreen (ClutterStageView *view, ++ const cairo_rectangle_int_t *rect) ++{ ++ ClutterStageViewPrivate *priv = ++ clutter_stage_view_get_instance_private (view); ++ ++ if (priv->offscreen) ++ { ++ gboolean can_blit; ++ CoglMatrix matrix; ++ ++ clutter_stage_view_ensure_offscreen_blit_pipeline (view); ++ clutter_stage_view_get_offscreen_transformation_matrix (view, &matrix); ++ can_blit = cogl_matrix_is_identity (&matrix); ++ ++ if (priv->shadowfb) ++ { ++ clutter_stage_view_copy_to_framebuffer (view, ++ rect, ++ priv->offscreen_pipeline, ++ priv->offscreen, ++ priv->shadowfb, ++ can_blit); ++ } ++ else ++ { ++ clutter_stage_view_copy_to_framebuffer (view, ++ rect, ++ priv->offscreen_pipeline, ++ priv->offscreen, ++ priv->framebuffer, ++ can_blit); ++ } ++ } ++ ++ if (priv->shadowfb) ++ { ++ clutter_stage_view_ensure_shadowfb_blit_pipeline (view); ++ clutter_stage_view_copy_to_framebuffer (view, ++ rect, ++ priv->shadowfb_pipeline, ++ priv->shadowfb, ++ priv->framebuffer, ++ TRUE); ++ } + } + + float +@@ -256,6 +331,9 @@ clutter_stage_view_get_property (GObject *object, + case PROP_OFFSCREEN: + g_value_set_boxed (value, priv->offscreen); + break; ++ case PROP_SHADOWFB: ++ g_value_set_boxed (value, priv->shadowfb); ++ break; + case PROP_SCALE: + g_value_set_float (value, priv->scale); + break; +@@ -301,6 +379,9 @@ clutter_stage_view_set_property (GObject *object, + case PROP_OFFSCREEN: + priv->offscreen = g_value_dup_boxed (value); + break; ++ case PROP_SHADOWFB: ++ priv->shadowfb = g_value_dup_boxed (value); ++ break; + case PROP_SCALE: + priv->scale = g_value_get_float (value); + break; +@@ -317,8 +398,10 @@ clutter_stage_view_dispose (GObject *object) + clutter_stage_view_get_instance_private (view); + + g_clear_pointer (&priv->framebuffer, cogl_object_unref); ++ g_clear_pointer (&priv->shadowfb, cogl_object_unref); + g_clear_pointer (&priv->offscreen, cogl_object_unref); +- g_clear_pointer (&priv->pipeline, cogl_object_unref); ++ g_clear_pointer (&priv->offscreen_pipeline, cogl_object_unref); ++ g_clear_pointer (&priv->shadowfb_pipeline, cogl_object_unref); + + G_OBJECT_CLASS (clutter_stage_view_parent_class)->dispose (object); + } +@@ -373,6 +456,15 @@ clutter_stage_view_class_init (ClutterStageViewClass *klass) + G_PARAM_CONSTRUCT_ONLY | + G_PARAM_STATIC_STRINGS); + ++ obj_props[PROP_SHADOWFB] = ++ g_param_spec_boxed ("shadowfb", ++ "Shadow framebuffer", ++ "Framebuffer used as intermediate shadow buffer", ++ COGL_TYPE_HANDLE, ++ G_PARAM_READWRITE | ++ G_PARAM_CONSTRUCT_ONLY | ++ G_PARAM_STATIC_STRINGS); ++ + obj_props[PROP_SCALE] = + g_param_spec_float ("scale", + "View scale", +diff --git a/clutter/clutter/cogl/clutter-stage-cogl.c b/clutter/clutter/cogl/clutter-stage-cogl.c +index e0c39185b..eab76e52f 100644 +--- a/clutter/clutter/cogl/clutter-stage-cogl.c ++++ b/clutter/clutter/cogl/clutter-stage-cogl.c +@@ -477,11 +477,7 @@ paint_stage (ClutterStageCogl *stage_cogl, + _clutter_stage_maybe_setup_viewport (stage, view); + _clutter_stage_paint_view (stage, view, clip); + +- if (clutter_stage_view_get_onscreen (view) != +- clutter_stage_view_get_framebuffer (view)) +- { +- clutter_stage_view_blit_offscreen (view, clip); +- } ++ clutter_stage_view_blit_offscreen (view, clip); + } + + static void +-- +2.21.0 + diff --git a/SOURCES/0012-renderer-native-Separate-offscreen-and-shadowfb.patch b/SOURCES/0012-renderer-native-Separate-offscreen-and-shadowfb.patch new file mode 100644 index 0000000..cd748a9 --- /dev/null +++ b/SOURCES/0012-renderer-native-Separate-offscreen-and-shadowfb.patch @@ -0,0 +1,98 @@ +From ca3e9e3b3b84fe95affbe5485212c6ecfa1a4b51 Mon Sep 17 00:00:00 2001 +From: Olivier Fourdan +Date: Tue, 22 Oct 2019 17:05:46 +0200 +Subject: [PATCH 12/12] renderer-native: Separate offscreen and shadowfb + +Create the intermediate shadow framebuffer for use exclusively when a +shadowfb is required. + +Keep the previous offscreen framebuffer is as an intermediate +framebuffer for transformations only. + +This way, we can apply transformations between in-memory framebuffers +prior to blit the result to screen, and achieve acceptable performance +even with software rendering on discrete GPU. + +https://gitlab.gnome.org/GNOME/mutter/merge_requests/917 + +(cherry picked from commit 551641c74822ca2e3c685e49603836ebf5397df2) +--- + src/backends/native/meta-renderer-native.c | 29 ++++++++++++++++++---- + 1 file changed, 24 insertions(+), 5 deletions(-) + +diff --git a/src/backends/native/meta-renderer-native.c b/src/backends/native/meta-renderer-native.c +index 3cd01bcb7..ffb64a6bd 100644 +--- a/src/backends/native/meta-renderer-native.c ++++ b/src/backends/native/meta-renderer-native.c +@@ -3287,7 +3287,6 @@ meta_renderer_native_create_onscreen (MetaRendererNative *renderer_native, + static CoglOffscreen * + meta_renderer_native_create_offscreen (MetaRendererNative *renderer, + CoglContext *context, +- MetaMonitorTransform transform, + gint view_width, + gint view_height, + GError **error) +@@ -3489,6 +3488,7 @@ meta_renderer_native_create_view (MetaRenderer *renderer, + MetaMonitorTransform view_transform; + CoglOnscreen *onscreen = NULL; + CoglOffscreen *offscreen = NULL; ++ CoglOffscreen *shadowfb = NULL; + float scale; + int width, height; + MetaRendererView *view; +@@ -3515,18 +3515,35 @@ meta_renderer_native_create_view (MetaRenderer *renderer, + if (!onscreen) + g_error ("Failed to allocate onscreen framebuffer: %s", error->message); + +- if (view_transform != META_MONITOR_TRANSFORM_NORMAL || +- should_force_shadow_fb (renderer_native, +- renderer_native->primary_gpu_kms)) ++ if (view_transform != META_MONITOR_TRANSFORM_NORMAL) + { + offscreen = meta_renderer_native_create_offscreen (renderer_native, + cogl_context, +- view_transform, + width, + height, + &error); + if (!offscreen) + g_error ("Failed to allocate back buffer texture: %s", error->message); ++ ++ } ++ ++ if (should_force_shadow_fb (renderer_native, ++ renderer_native->primary_gpu_kms)) ++ { ++ int shadow_width; ++ int shadow_height; ++ ++ /* The shadowfb must be the same size as the on-screen framebuffer */ ++ shadow_width = cogl_framebuffer_get_width (COGL_FRAMEBUFFER (onscreen)); ++ shadow_height = cogl_framebuffer_get_height (COGL_FRAMEBUFFER (onscreen)); ++ ++ shadowfb = meta_renderer_native_create_offscreen (renderer_native, ++ cogl_context, ++ shadow_width, ++ shadow_height, ++ &error); ++ if (!shadowfb) ++ g_error ("Failed to allocate shadow buffer texture: %s", error->message); + } + + view = g_object_new (META_TYPE_RENDERER_VIEW, +@@ -3534,10 +3551,12 @@ meta_renderer_native_create_view (MetaRenderer *renderer, + "scale", scale, + "framebuffer", onscreen, + "offscreen", offscreen, ++ "shadowfb", shadowfb, + "logical-monitor", logical_monitor, + "transform", view_transform, + NULL); + g_clear_pointer (&offscreen, cogl_object_unref); ++ g_clear_pointer (&shadowfb, cogl_object_unref); + + meta_onscreen_native_set_view (onscreen, view); + +-- +2.21.0 + diff --git a/SPECS/mutter.spec b/SPECS/mutter.spec index b24e8e4..0eef59a 100644 --- a/SPECS/mutter.spec +++ b/SPECS/mutter.spec @@ -8,7 +8,7 @@ Name: mutter Version: 3.32.2 -Release: 10%{?dist} +Release: 11%{?dist} Summary: Window and compositing manager based on Clutter License: GPLv2+ @@ -67,6 +67,21 @@ Patch116: 0001-iconcache-Avoid-xrender-picture-formats-when-creatin.patch Patch117: 0001-workspace-Focus-only-ancestors-that-are-focusable.patch Patch118: 0002-window-Emit-an-error-and-return-when-trying-to-activ.patch +# Improve shadow-fb performance on llvmpipe +# https://bugzilla.redhat.com/1757144 +Patch201: 0001-cogl-Remove-unused-OFFSCREEN_BLIT-feature-flag.patch +Patch202: 0002-cogl-Fix-doc-for-_cogl_blit_framebuffer.patch +Patch203: 0003-cogl-Replace-ANGLE-with-GLES3-and-NV-framebuffer_bli.patch +Patch204: 0004-cogl-Relax-formats-on-glBlitFramebuffer.patch +Patch205: 0005-cogl-Allow-glBlitFramebuffer-between-onscreen-offscr.patch +Patch206: 0006-cogl-Rename-feature-OFFSCREEN_BLIT-to-BLIT_FRAMEBUFF.patch +Patch207: 0007-cogl-Expose-cogl_blit_framebuffer.patch +Patch208: 0008-clutter-stage-view-Use-cogl_blit_framebuffer-for-sha.patch +Patch209: 0009-clutter-stage-view-Ignore-clipping-rectangle-for-off.patch +Patch210: 0010-cogl-Flush-journal-before-blitting.patch +Patch211: 0011-clutter-stage-view-Separate-offscreen-and-shadowfb.patch +Patch212: 0012-renderer-native-Separate-offscreen-and-shadowfb.patch + BuildRequires: chrpath BuildRequires: pango-devel BuildRequires: startup-notification-devel @@ -208,6 +223,10 @@ desktop-file-validate %{buildroot}/%{_datadir}/applications/%{name}.desktop %{_datadir}/mutter-%{mutter_api_version}/tests %changelog +* Wed Nov 13 2019 Olivier Fourdan - 3.32.2-11 +- Backports shadow FB improvements on llvmpipe + Resolves: #1757144 + * Fri Aug 16 2019 Jonas Ådahl - 3.32.2-10 - Don't focus or activate unmanaging windows Resolves: #1741547