diff options
author | Mingi Sung | 2024-10-16 00:38:17 +0900 |
---|---|---|
committer | Mingi Sung | 2024-10-16 00:38:17 +0900 |
commit | c3d96e89e1f1846d397ffc495a40444f947cdb95 (patch) | |
tree | a21e0804fe72af7aebfbc2d868313995543dd84e | |
parent | 22c14bc6be506728c73ce9e33fc0b7b6c3562d66 (diff) | |
parent | 17f392adebadf8b6751bf51d2507ae5df8797b29 (diff) | |
download | aur-c3d96e89e1f1846d397ffc495a40444f947cdb95.tar.gz |
Merge branch 'gnome-47' into unstable
-rw-r--r-- | .SRCINFO | 6 | ||||
-rw-r--r-- | PKGBUILD | 8 | ||||
-rw-r--r-- | mr1441.patch | 728 |
3 files changed, 661 insertions, 81 deletions
@@ -1,7 +1,7 @@ pkgbase = mutter-performance-unstable pkgdesc = A window manager for GNOME | Attempts to improve performances with non-upstreamed merge-requests and frequent stable branch resync pkgver = 47.0.r23.g6e1e870e5 - pkgrel = 1 + pkgrel = 2 epoch = 1 url = https://gitlab.gnome.org/GNOME/mutter arch = x86_64 @@ -79,11 +79,11 @@ pkgbase = mutter-performance-unstable source = mr3751.patch sha256sums = 6763e710815990ececee06dddf08588040bc5f1bb34a088dcbb96b6719b0dbc7 sha256sums = ba56c003c1c16f1f8e411f6d5213878bcf059d4d39ece100fc414228a1bf22d5 - sha256sums = 56df87f26755332dc7a4895a6fc523000a92f683ed6b4323cf8703b595deb126 + sha256sums = 7f374786d11684488f825de877633bcb175669461ca081694bd269fcc17d7788 sha256sums = 67943a22cb75df955fc475e5ae101984d87e4a1f51d56be5f50696cc3355a3c4 b2sums = 060181a2af6f9c5f9b6a302766af70d512164c62c17466553154b17c8b6e739bbe1ba8e1ab3f2f34d6866e214a4099185399192055a1cf3e30a2773e3d6b8599 b2sums = f989bc2ceb52aad3c6a23c439df3bbc672bc11d561a247d19971d30cc85ed5d42295de40f8e55b13404ed32aa44f12307c9f5b470f2e288d1c9c8329255c43bf - b2sums = 0a24bfb28c63776227cb6ade3b3fe74809a22628d90210fe448994e074a4c75793d02393b85d12c3ce841ae13080c17c2baed9435e79e10746121ccaf49cb1ec + b2sums = 8e4edb66654ad223e513aac3bd781176e144c8a34d3bbf76416a0168b5c3f59d8a4d44af9fbeb4270849930d550cf75bdbf03084a5e1fdf7cca2a77592b78516 b2sums = e13742a68cd831827e88ddf1801caca39fa9c77dd8c08a851bc87914f2961119fc1a7643628fc63cad8dedf03533148539a242cca23313c250bd65867ea84d8d pkgname = mutter-performance-unstable @@ -21,7 +21,7 @@ _pkgname=mutter pkgname=mutter-performance-unstable epoch=1 pkgver=47.0.r23.g6e1e870e5 -pkgrel=1 +pkgrel=2 pkgdesc="A window manager for GNOME | Attempts to improve performances with non-upstreamed merge-requests and frequent stable branch resync" url="https://gitlab.gnome.org/GNOME/mutter" arch=(x86_64 aarch64) @@ -104,11 +104,11 @@ source=("git+$url.git#commit=$_commit" 'mr3751.patch') sha256sums=('6763e710815990ececee06dddf08588040bc5f1bb34a088dcbb96b6719b0dbc7' 'ba56c003c1c16f1f8e411f6d5213878bcf059d4d39ece100fc414228a1bf22d5' - '56df87f26755332dc7a4895a6fc523000a92f683ed6b4323cf8703b595deb126' + '7f374786d11684488f825de877633bcb175669461ca081694bd269fcc17d7788' '67943a22cb75df955fc475e5ae101984d87e4a1f51d56be5f50696cc3355a3c4') b2sums=('060181a2af6f9c5f9b6a302766af70d512164c62c17466553154b17c8b6e739bbe1ba8e1ab3f2f34d6866e214a4099185399192055a1cf3e30a2773e3d6b8599' 'f989bc2ceb52aad3c6a23c439df3bbc672bc11d561a247d19971d30cc85ed5d42295de40f8e55b13404ed32aa44f12307c9f5b470f2e288d1c9c8329255c43bf' - '0a24bfb28c63776227cb6ade3b3fe74809a22628d90210fe448994e074a4c75793d02393b85d12c3ce841ae13080c17c2baed9435e79e10746121ccaf49cb1ec' + '8e4edb66654ad223e513aac3bd781176e144c8a34d3bbf76416a0168b5c3f59d8a4d44af9fbeb4270849930d550cf75bdbf03084a5e1fdf7cca2a77592b78516' 'e13742a68cd831827e88ddf1801caca39fa9c77dd8c08a851bc87914f2961119fc1a7643628fc63cad8dedf03533148539a242cca23313c250bd65867ea84d8d') pkgver() { @@ -207,7 +207,7 @@ prepare() { # Type: 1 # Status: 2 & 3 # Comment: Helps GPU frequencies to scale up. - # Included: !4015 !4027 + # Included: !4015 !4027 !4060 !4073 pick_mr '1441' 'mr1441.patch' 'patch' } diff --git a/mr1441.patch b/mr1441.patch index 46a2407a59cd..d45dacfeba1e 100644 --- a/mr1441.patch +++ b/mr1441.patch @@ -1,6 +1,6 @@ -From 95d7bc12da169609b9c0a39c94c9128150ac7eac Mon Sep 17 00:00:00 2001 +From 0a55ee55d993cee18a5270e4ef52266bfe5ef62e Mon Sep 17 00:00:00 2001 From: Mingi Sung <sungmg@saltyming.net> -Date: Tue, 8 Oct 2024 18:16:41 +0900 +Date: Wed, 16 Oct 2024 00:32:09 +0900 Subject: [PATCH] Merge branch 'sungmg-triple-buffering-v4-47' into gnome-47 Use triple buffering if and when the previous frame is running late. @@ -19,11 +19,13 @@ Commit: 511a502e1a6ff6c88dcb650f1bee8f6eb894d1f6 Included: https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/4015 Included: https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/4027 +Included: https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/4060 +Included: https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/4073 Source: https://git.saltyming.net/sungmg/mutter-performance-source Signed-off-by: Mingi Sung <sungmg@saltyming.net> --- - clutter/clutter/clutter-frame-clock.c | 372 +++++++++++++++++---- + clutter/clutter/clutter-frame-clock.c | 372 ++++++++++++--- clutter/clutter/clutter-frame-clock.h | 11 +- clutter/clutter/clutter-frame-private.h | 1 + clutter/clutter/clutter-frame.c | 13 + @@ -31,22 +33,22 @@ Signed-off-by: Mingi Sung <sungmg@saltyming.net> clutter/clutter/clutter-stage-view.c | 11 +- cogl/cogl/cogl-onscreen-private.h | 5 +- cogl/cogl/cogl-onscreen.c | 8 + - src/backends/meta-egl.c | 71 ++++ - src/backends/meta-egl.h | 18 + + src/backends/meta-egl.c | 96 ++++ + src/backends/meta-egl.h | 25 + src/backends/meta-stage-impl.c | 2 + - src/backends/native/meta-drm-buffer-gbm.c | 188 ++++++++--- + src/backends/native/meta-drm-buffer-gbm.c | 188 ++++++-- src/backends/native/meta-drm-buffer-gbm.h | 6 + src/backends/native/meta-frame-native.c | 31 ++ src/backends/native/meta-frame-native.h | 9 + src/backends/native/meta-kms.c | 9 + src/backends/native/meta-kms.h | 2 + - src/backends/native/meta-onscreen-native.c | 397 +++++++++++++++++++---- + src/backends/native/meta-onscreen-native.c | 578 +++++++++++++++++++---- src/backends/native/meta-onscreen-native.h | 2 + - src/backends/native/meta-renderer-native-gles3.c | 54 +-- - src/backends/native/meta-renderer-native-gles3.h | 2 +- + src/backends/native/meta-renderer-native-gles3.c | 251 ++++++---- + src/backends/native/meta-renderer-native-gles3.h | 17 +- src/backends/native/meta-renderer-native.c | 34 +- - src/tests/native-kms-render.c | 106 ++++-- - 23 files changed, 1090 insertions(+), 269 deletions(-) + src/tests/native-kms-render.c | 106 ++++- + 23 files changed, 1458 insertions(+), 326 deletions(-) diff --git a/clutter/clutter/clutter-frame-clock.c b/clutter/clutter/clutter-frame-clock.c index 0cc1f2eb4a..3418cb86c0 100644 @@ -863,10 +865,18 @@ index 3bcb23307e..cde6da308f 100644 cogl_onscreen_add_frame_callback (CoglOnscreen *onscreen, CoglFrameCallback callback, diff --git a/src/backends/meta-egl.c b/src/backends/meta-egl.c -index cc023f705c..50da9c4646 100644 +index cc023f705c..9bc73a254b 100644 --- a/src/backends/meta-egl.c +++ b/src/backends/meta-egl.c -@@ -44,6 +44,10 @@ struct _MetaEgl +@@ -26,6 +26,7 @@ + #include <EGL/egl.h> + #include <EGL/eglext.h> + #include <EGL/eglmesaext.h> ++#include <EGL/eglplatform.h> + #include <gio/gio.h> + #include <glib.h> + #include <glib-object.h> +@@ -44,6 +45,10 @@ struct _MetaEgl PFNEGLCREATEIMAGEKHRPROC eglCreateImageKHR; PFNEGLDESTROYIMAGEKHRPROC eglDestroyImageKHR; @@ -877,7 +887,43 @@ index cc023f705c..50da9c4646 100644 PFNEGLBINDWAYLANDDISPLAYWL eglBindWaylandDisplayWL; PFNEGLQUERYWAYLANDBUFFERWL eglQueryWaylandBufferWL; -@@ -1162,6 +1166,69 @@ meta_egl_query_display_attrib (MetaEgl *egl, +@@ -72,6 +77,8 @@ struct _MetaEgl + PFNEGLQUERYDMABUFMODIFIERSEXTPROC eglQueryDmaBufModifiersEXT; + + PFNEGLQUERYDISPLAYATTRIBEXTPROC eglQueryDisplayAttribEXT; ++ ++ PFNEGLQUERYSURFACEPROC eglQuerySurface; + }; + + G_DEFINE_TYPE (MetaEgl, meta_egl, G_TYPE_OBJECT) +@@ -1143,6 +1150,26 @@ meta_egl_query_dma_buf_modifiers (MetaEgl *egl, + return TRUE; + } + ++gboolean ++meta_egl_query_surface (MetaEgl *egl, ++ EGLDisplay display, ++ EGLSurface surface, ++ EGLint attribute, ++ EGLint *value, ++ GError **error) ++{ ++ if (!is_egl_proc_valid (egl->eglQuerySurface, error)) ++ return FALSE; ++ ++ if (!egl->eglQuerySurface (display, surface, attribute, value)) ++ { ++ set_egl_error (error); ++ return FALSE; ++ } ++ ++ return TRUE; ++} ++ + gboolean + meta_egl_query_display_attrib (MetaEgl *egl, + EGLDisplay display, +@@ -1162,6 +1189,69 @@ meta_egl_query_display_attrib (MetaEgl *egl, return TRUE; } @@ -947,7 +993,7 @@ index cc023f705c..50da9c4646 100644 #define GET_EGL_PROC_ADDR(proc) \ egl->proc = (void *) eglGetProcAddress (#proc); -@@ -1175,6 +1242,10 @@ meta_egl_constructed (GObject *object) +@@ -1175,6 +1265,10 @@ meta_egl_constructed (GObject *object) GET_EGL_PROC_ADDR (eglCreateImageKHR); GET_EGL_PROC_ADDR (eglDestroyImageKHR); @@ -958,11 +1004,32 @@ index cc023f705c..50da9c4646 100644 GET_EGL_PROC_ADDR (eglBindWaylandDisplayWL); GET_EGL_PROC_ADDR (eglQueryWaylandBufferWL); +@@ -1203,6 +1297,8 @@ meta_egl_constructed (GObject *object) + GET_EGL_PROC_ADDR (eglQueryDmaBufModifiersEXT); + + GET_EGL_PROC_ADDR (eglQueryDisplayAttribEXT); ++ ++ GET_EGL_PROC_ADDR (eglQuerySurface); + } + + #undef GET_EGL_PROC_ADDR diff --git a/src/backends/meta-egl.h b/src/backends/meta-egl.h -index 8b955c90c3..af3150c3c9 100644 +index 8b955c90c3..9c8ab779a2 100644 --- a/src/backends/meta-egl.h +++ b/src/backends/meta-egl.h -@@ -276,3 +276,21 @@ gboolean meta_egl_query_display_attrib (MetaEgl *egl, +@@ -271,8 +271,33 @@ gboolean meta_egl_query_dma_buf_modifiers (MetaEgl *egl, + EGLint *num_formats, + GError **error); + ++gboolean meta_egl_query_surface (MetaEgl *egl, ++ EGLDisplay display, ++ EGLSurface surface, ++ EGLint attribute, ++ EGLint *value, ++ GError **error); ++ + gboolean meta_egl_query_display_attrib (MetaEgl *egl, + EGLDisplay display, EGLint attribute, EGLAttrib *value, GError **error); @@ -1375,7 +1442,7 @@ index f5ec4c1c3b..77fd62662d 100644 MetaKmsFlags flags, GError **error); diff --git a/src/backends/native/meta-onscreen-native.c b/src/backends/native/meta-onscreen-native.c -index 021ada3677..a9d54f43c0 100644 +index 021ada3677..bf221129ab 100644 --- a/src/backends/native/meta-onscreen-native.c +++ b/src/backends/native/meta-onscreen-native.c @@ -29,6 +29,7 @@ @@ -1386,7 +1453,39 @@ index 021ada3677..a9d54f43c0 100644 #include <drm_fourcc.h> #include "backends/meta-egl-ext.h" -@@ -76,7 +77,7 @@ typedef struct _MetaOnscreenNativeSecondaryGpuState +@@ -53,6 +54,18 @@ + #include "common/meta-cogl-drm-formats.h" + #include "common/meta-drm-format-helpers.h" + ++/* ++ The maximum amount of damage rectangles to maintain. At a certain point there are so many damage rectangles that ++ individually processing them isn't worth the time they save based on a full redraw, which is determined by this ++ number. ++*/ ++#define MAX_DAMAGE_RECTANGLES 16 ++ ++/* ++ The maximum supported buffer age for secondary GPU surfaces. ++*/ ++#define MAX_SECONDARY_GPU_BUFFER_AGE 4 ++ + typedef enum _MetaSharedFramebufferImportStatus + { + /* Not tried importing yet. */ +@@ -63,6 +76,12 @@ typedef enum _MetaSharedFramebufferImportStatus + META_SHARED_FRAMEBUFFER_IMPORT_STATUS_OK + } MetaSharedFramebufferImportStatus; + ++typedef struct _MetaOnscreenNativeSecondaryGpuDamageRectangleInfo ++{ ++ MtkRectangle rectangles[MAX_DAMAGE_RECTANGLES]; ++ int n_rectangles; ++} MetaOnscreenNativeSecondaryGpuDamageRectangleInfo; ++ + typedef struct _MetaOnscreenNativeSecondaryGpuState + { + MetaGpuKms *gpu_kms; +@@ -76,9 +95,11 @@ typedef struct _MetaOnscreenNativeSecondaryGpuState struct { MetaDrmBufferDumb *current_dumb_fb; @@ -1394,8 +1493,12 @@ index 021ada3677..a9d54f43c0 100644 + MetaDrmBufferDumb *dumb_fbs[3]; } cpu; ++ MetaOnscreenNativeSecondaryGpuDamageRectangleInfo damage_rectangles[MAX_SECONDARY_GPU_BUFFER_AGE]; ++ gboolean noted_primary_gpu_copy_ok; -@@ -103,6 +104,8 @@ struct _MetaOnscreenNative + gboolean noted_primary_gpu_copy_failed; + MetaSharedFramebufferImportStatus import_status; +@@ -103,6 +124,8 @@ struct _MetaOnscreenNative MetaOnscreenNativeSecondaryGpuState *secondary_gpu_state; ClutterFrame *presented_frame; @@ -1404,7 +1507,7 @@ index 021ada3677..a9d54f43c0 100644 ClutterFrame *next_frame; struct { -@@ -117,6 +120,9 @@ struct _MetaOnscreenNative +@@ -117,6 +140,9 @@ struct _MetaOnscreenNative } egl; #endif @@ -1414,7 +1517,7 @@ index 021ada3677..a9d54f43c0 100644 gboolean frame_sync_requested; gboolean frame_sync_enabled; -@@ -138,6 +144,13 @@ G_DEFINE_TYPE (MetaOnscreenNative, meta_onscreen_native, +@@ -138,6 +164,13 @@ G_DEFINE_TYPE (MetaOnscreenNative, meta_onscreen_native, static GQuark blit_source_quark = 0; @@ -1428,7 +1531,7 @@ index 021ada3677..a9d54f43c0 100644 static gboolean init_secondary_gpu_state (MetaRendererNative *renderer_native, CoglOnscreen *onscreen, -@@ -148,20 +161,20 @@ meta_onscreen_native_swap_drm_fb (CoglOnscreen *onscreen) +@@ -148,20 +181,20 @@ meta_onscreen_native_swap_drm_fb (CoglOnscreen *onscreen) { MetaOnscreenNative *onscreen_native = META_ONSCREEN_NATIVE (onscreen); @@ -1453,7 +1556,7 @@ index 021ada3677..a9d54f43c0 100644 } static void -@@ -199,7 +212,7 @@ meta_onscreen_native_notify_frame_complete (CoglOnscreen *onscreen) +@@ -199,7 +232,7 @@ meta_onscreen_native_notify_frame_complete (CoglOnscreen *onscreen) info = cogl_onscreen_pop_head_frame_info (onscreen); @@ -1462,7 +1565,7 @@ index 021ada3677..a9d54f43c0 100644 _cogl_onscreen_notify_frame_sync (onscreen, info); _cogl_onscreen_notify_complete (onscreen, info); -@@ -241,6 +254,7 @@ notify_view_crtc_presented (MetaRendererView *view, +@@ -241,6 +274,7 @@ notify_view_crtc_presented (MetaRendererView *view, meta_onscreen_native_notify_frame_complete (onscreen); meta_onscreen_native_swap_drm_fb (onscreen); @@ -1470,7 +1573,7 @@ index 021ada3677..a9d54f43c0 100644 } static void -@@ -290,15 +304,13 @@ page_flip_feedback_ready (MetaKmsCrtc *kms_crtc, +@@ -290,15 +324,13 @@ page_flip_feedback_ready (MetaKmsCrtc *kms_crtc, CoglFramebuffer *framebuffer = clutter_stage_view_get_onscreen (CLUTTER_STAGE_VIEW (view)); CoglOnscreen *onscreen = COGL_ONSCREEN (framebuffer); @@ -1487,7 +1590,7 @@ index 021ada3677..a9d54f43c0 100644 } static void -@@ -368,7 +380,8 @@ page_flip_feedback_discarded (MetaKmsCrtc *kms_crtc, +@@ -368,7 +400,8 @@ page_flip_feedback_discarded (MetaKmsCrtc *kms_crtc, } meta_onscreen_native_notify_frame_complete (onscreen); @@ -1497,7 +1600,7 @@ index 021ada3677..a9d54f43c0 100644 } static const MetaKmsPageFlipListenerVtable page_flip_listener_vtable = { -@@ -429,18 +442,36 @@ custom_egl_stream_page_flip (gpointer custom_page_flip_data, +@@ -429,18 +462,36 @@ custom_egl_stream_page_flip (gpointer custom_page_flip_data, } #endif /* HAVE_EGL_DEVICE */ @@ -1537,7 +1640,7 @@ index 021ada3677..a9d54f43c0 100644 static void apply_transform (MetaCrtcKms *crtc_kms, MetaKmsPlaneAssignment *kms_plane_assignment, -@@ -517,7 +548,7 @@ meta_onscreen_native_flip_crtc (CoglOnscreen *onscreen, +@@ -517,7 +568,7 @@ meta_onscreen_native_flip_crtc (CoglOnscreen *onscreen, { MetaOnscreenNative *onscreen_native = META_ONSCREEN_NATIVE (onscreen); MetaRendererNative *renderer_native = onscreen_native->renderer_native; @@ -1546,7 +1649,7 @@ index 021ada3677..a9d54f43c0 100644 MetaFrameNative *frame_native; MetaGpuKms *render_gpu = onscreen_native->render_gpu; MetaCrtcKms *crtc_kms = META_CRTC_KMS (crtc); -@@ -533,6 +564,7 @@ meta_onscreen_native_flip_crtc (CoglOnscreen *onscreen, +@@ -533,6 +584,7 @@ meta_onscreen_native_flip_crtc (CoglOnscreen *onscreen, COGL_TRACE_BEGIN_SCOPED (MetaOnscreenNativeFlipCrtcs, "Meta::OnscreenNative::flip_crtc()"); @@ -1554,7 +1657,7 @@ index 021ada3677..a9d54f43c0 100644 g_return_if_fail (frame); gpu_kms = META_GPU_KMS (meta_crtc_get_gpu (crtc)); -@@ -595,6 +627,10 @@ meta_onscreen_native_flip_crtc (CoglOnscreen *onscreen, +@@ -595,6 +647,10 @@ meta_onscreen_native_flip_crtc (CoglOnscreen *onscreen, #endif } @@ -1565,24 +1668,124 @@ index 021ada3677..a9d54f43c0 100644 meta_kms_update_add_page_flip_listener (kms_update, kms_crtc, &page_flip_listener_vtable, -@@ -851,12 +887,15 @@ copy_shared_framebuffer_gpu (CoglOnscreen *onscreen, +@@ -831,11 +887,94 @@ import_shared_framebuffer (CoglOnscreen *onscreen, + return imported_buffer; + } + ++static void ++push_secondary_gpu_damage_rectangles (MetaOnscreenNativeSecondaryGpuState *secondary_gpu_state, ++ const int *rectangles, ++ int n_rectangles) ++{ ++ int i; ++ ++ if (n_rectangles > MAX_DAMAGE_RECTANGLES) ++ n_rectangles = 0; ++ ++ for (i = MAX_SECONDARY_GPU_BUFFER_AGE - 1; i > 0; --i) ++ { ++ if (secondary_gpu_state->damage_rectangles[i - 1].n_rectangles > 0) ++ memcpy (secondary_gpu_state->damage_rectangles[i].rectangles, ++ secondary_gpu_state->damage_rectangles[i - 1].rectangles, ++ secondary_gpu_state->damage_rectangles[i - 1].n_rectangles * sizeof (MtkRectangle)); ++ ++ secondary_gpu_state->damage_rectangles[i].n_rectangles = secondary_gpu_state->damage_rectangles[i - 1].n_rectangles; ++ } ++ ++ if (n_rectangles > 0) ++ memcpy (secondary_gpu_state->damage_rectangles[0].rectangles, ++ rectangles, ++ n_rectangles * sizeof (MtkRectangle)); ++ ++ secondary_gpu_state->damage_rectangles[0].n_rectangles = n_rectangles; ++} ++ ++static int ++calculate_secondary_gpu_damage_rectangle_count (MetaOnscreenNativeSecondaryGpuState *secondary_gpu_state, ++ int buffer_age) ++{ ++ int i; ++ int union_n_rectangles = 0; ++ ++ for (i = 0; i <= buffer_age; ++i) ++ { ++ /* Everything being damaged in a previous frame means we also need to damage everything now. */ ++ if (secondary_gpu_state->damage_rectangles[i].n_rectangles == 0) ++ return 0; ++ ++ union_n_rectangles += secondary_gpu_state->damage_rectangles[i].n_rectangles; ++ } ++ ++ return union_n_rectangles; ++} ++ ++static int ++get_secondary_gpu_buffer_age (MetaOnscreenNativeSecondaryGpuState *secondary_gpu_state, ++ MetaRendererNativeGpuData *renderer_gpu_data) ++{ ++ MetaRendererNative *renderer_native = renderer_gpu_data->renderer_native; ++ MetaEgl *egl = meta_renderer_native_get_egl (renderer_native); ++ MetaRenderDevice *render_device; ++ EGLDisplay egl_display; ++ int buffer_age; ++ g_autoptr (GError) error = NULL; ++ ++ render_device = renderer_gpu_data->render_device; ++ egl_display = meta_render_device_get_egl_display (render_device); ++ ++ if (!meta_egl_query_surface (egl, egl_display, secondary_gpu_state->egl_surface, EGL_BUFFER_AGE_EXT, &buffer_age, &error)) ++ { ++ g_warning ("Failed to query age of surface, ignoring damage rectangles and fully redrawing, " ++ "which may cause increased GPU power consumption: %s", error->message); ++ ++ return 0; ++ } ++ ++ if (buffer_age > MAX_SECONDARY_GPU_BUFFER_AGE) ++ { ++ g_warning ("Secondary GPU provides buffers of age %i, which is older than supported; " ++ "ignoring damage rectangles and fully redrawing which may cause incraesed GPU power consumption", ++ buffer_age); ++ ++ return 0; ++ } ++ ++ return buffer_age; ++} ++ + static MetaDrmBuffer * + copy_shared_framebuffer_gpu (CoglOnscreen *onscreen, + MetaOnscreenNativeSecondaryGpuState *secondary_gpu_state, + MetaRendererNativeGpuData *renderer_gpu_data, + MetaDrmBuffer *primary_gpu_fb, ++ const int *rectangles, ++ int n_rectangles, + GError **error) + { + MetaRendererNative *renderer_native = renderer_gpu_data->renderer_native; +@@ -851,12 +990,20 @@ copy_shared_framebuffer_gpu (CoglOnscreen *onscreen, MetaDrmBufferFlags flags; MetaDrmBufferGbm *buffer_gbm = NULL; struct gbm_bo *bo; ++ EGLImageKHR egl_image; + EGLSync egl_sync = EGL_NO_SYNC; + g_autofd int sync_fd = -1; -+ EGLImageKHR egl_image; ++ int buffer_age = 0; ++ int blit_n_rectangles = 0; ++ MtkRectangle *blit_rectangles = NULL; COGL_TRACE_BEGIN_SCOPED (CopySharedFramebufferSecondaryGpu, "copy_shared_framebuffer_gpu()"); ++ push_secondary_gpu_damage_rectangles (secondary_gpu_state, rectangles, n_rectangles); ++ if (renderer_gpu_data->secondary.needs_explicit_sync) - cogl_framebuffer_finish (COGL_FRAMEBUFFER (onscreen)); + sync_fd = cogl_context_get_latest_sync_fd (cogl_context); render_device = renderer_gpu_data->render_device; egl_display = meta_render_device_get_egl_display (render_device); -@@ -872,13 +911,51 @@ copy_shared_framebuffer_gpu (CoglOnscreen *onscreen, +@@ -872,14 +1019,96 @@ copy_shared_framebuffer_gpu (CoglOnscreen *onscreen, goto done; } @@ -1624,6 +1827,48 @@ index 021ada3677..a9d54f43c0 100644 + { + g_prefix_error (error, "Failed to create EGL image from buffer object for secondary GPU: "); + goto done; ++ ++ buffer_age = get_secondary_gpu_buffer_age (secondary_gpu_state, renderer_gpu_data); ++ blit_n_rectangles = calculate_secondary_gpu_damage_rectangle_count (secondary_gpu_state, buffer_age); ++ ++ if (blit_n_rectangles > 0) ++ { ++ int i; ++ int offset = 0; ++ ++ /* Will tend to overallocate a bit if reduction happens below, but doesn't matter much since it's pretty small. */ ++ blit_rectangles = g_newa (MtkRectangle, blit_n_rectangles); ++ ++ GHashTable* hash_table = g_hash_table_new (g_str_hash, g_str_equal); ++ ++ for (i = 0; i <= buffer_age; ++i) ++ { ++ int j; ++ ++ for (j = 0; j < secondary_gpu_state->damage_rectangles[i].n_rectangles; ++j) ++ { ++ char hash_table_key[100]; ++ ++ g_snprintf (hash_table_key, ++ 100, ++ "%i_%i_%i_%i", ++ secondary_gpu_state->damage_rectangles[i].rectangles[j].x, ++ secondary_gpu_state->damage_rectangles[i].rectangles[j].y, ++ secondary_gpu_state->damage_rectangles[i].rectangles[j].width, ++ secondary_gpu_state->damage_rectangles[i].rectangles[j].height); ++ ++ if (g_hash_table_lookup_extended (hash_table, hash_table_key, NULL, NULL)) ++ continue; ++ ++ g_hash_table_insert (hash_table, hash_table_key, NULL); ++ ++ memcpy (&blit_rectangles[offset++], &secondary_gpu_state->damage_rectangles[i].rectangles[j], sizeof(MtkRectangle)); ++ } ++ } ++ ++ g_hash_table_destroy (hash_table); ++ ++ blit_n_rectangles = offset; + } + if (!meta_renderer_native_gles3_blit_shared_bo (egl, @@ -1633,9 +1878,12 @@ index 021ada3677..a9d54f43c0 100644 - secondary_gpu_state->egl_surface, + egl_image, bo, ++ blit_rectangles, ++ blit_n_rectangles, error)) { -@@ -919,6 +996,17 @@ copy_shared_framebuffer_gpu (CoglOnscreen *onscreen, + g_prefix_error (error, "Failed to blit shared framebuffer: "); +@@ -919,6 +1148,17 @@ copy_shared_framebuffer_gpu (CoglOnscreen *onscreen, g_object_unref); done: @@ -1653,7 +1901,7 @@ index 021ada3677..a9d54f43c0 100644 _cogl_winsys_egl_ensure_current (cogl_display); return buffer_gbm ? META_DRM_BUFFER (buffer_gbm) : NULL; -@@ -928,12 +1016,17 @@ static MetaDrmBufferDumb * +@@ -928,12 +1168,17 @@ static MetaDrmBufferDumb * secondary_gpu_get_next_dumb_buffer (MetaOnscreenNativeSecondaryGpuState *secondary_gpu_state) { MetaDrmBufferDumb *current_dumb_fb; @@ -1675,7 +1923,37 @@ index 021ada3677..a9d54f43c0 100644 } static MetaDrmBuffer * -@@ -1269,10 +1362,36 @@ swap_buffer_result_feedback (const MetaKmsFeedback *kms_feedback, +@@ -1009,10 +1254,8 @@ copy_shared_framebuffer_primary_gpu (CoglOnscreen *onscre + error->message); + return NULL; + } +- /* Limit the number of individual copies to 16 */ +-#define MAX_RECTS 16 + +- if (n_rectangles == 0 || n_rectangles > MAX_RECTS) ++ if (n_rectangles == 0 || n_rectangles > MAX_DAMAGE_RECTANGLES) + { + if (!cogl_blit_framebuffer (framebuffer, COGL_FRAMEBUFFER (dmabuf_fb), + 0, 0, 0, 0, +@@ -1177,6 +1420,8 @@ static MetaDrmBuffer * + acquire_front_buffer (CoglOnscreen *onscreen, + MetaDrmBuffer *primary_gpu_fb, + MetaDrmBuffer *secondary_gpu_fb, ++ const int *rectangles, ++ int n_rectangles, + GError **error) + { + MetaOnscreenNative *onscreen_native = META_ONSCREEN_NATIVE (onscreen); +@@ -1222,6 +1467,8 @@ acquire_front_buffer (CoglOnscreen *onscreen, + secondary_gpu_state, + renderer_gpu_data, + primary_gpu_fb, ++ rectangles, ++ n_rectangles, + error); + } + +@@ -1269,10 +1516,36 @@ swap_buffer_result_feedback (const MetaKmsFeedback *kms_feedback, g_warning ("Page flip failed: %s", error->message); frame_info = cogl_onscreen_peek_head_frame_info (onscreen); @@ -1715,7 +1993,7 @@ index 021ada3677..a9d54f43c0 100644 } static const MetaKmsResultListenerVtable swap_buffer_result_listener_vtable = { -@@ -1292,35 +1411,37 @@ meta_onscreen_native_swap_buffers_with_damage (CoglOnscreen *onscreen, +@@ -1292,35 +1565,37 @@ meta_onscreen_native_swap_buffers_with_damage (CoglOnscreen *onscreen, CoglRendererEGL *cogl_renderer_egl = cogl_renderer->winsys; MetaRendererNativeGpuData *renderer_gpu_data = cogl_renderer_egl->platform; MetaRendererNative *renderer_native = renderer_gpu_data->renderer_native; @@ -1764,7 +2042,33 @@ index 021ada3677..a9d54f43c0 100644 secondary_gpu_fb = update_secondary_gpu_state_pre_swap_buffers (onscreen, rectangles, -@@ -1402,15 +1523,86 @@ meta_onscreen_native_swap_buffers_with_damage (CoglOnscreen *onscreen, +@@ -1334,12 +1609,12 @@ meta_onscreen_native_swap_buffers_with_damage (CoglOnscreen *onscreen, + secondary_gpu_data = + meta_renderer_native_get_gpu_data (renderer_native, + secondary_gpu_state->gpu_kms); +- if (secondary_gpu_data->secondary.copy_mode == +- META_SHARED_FRAMEBUFFER_COPY_MODE_SECONDARY_GPU) +- create_timestamp_query = FALSE; ++ secondary_gpu_used = ++ secondary_gpu_data->secondary.copy_mode == ++ META_SHARED_FRAMEBUFFER_COPY_MODE_SECONDARY_GPU; + } + +- if (create_timestamp_query) ++ if (!secondary_gpu_used) + cogl_onscreen_egl_maybe_create_timestamp_query (onscreen, frame_info); + + parent_class = COGL_ONSCREEN_CLASS (meta_onscreen_native_parent_class); +@@ -1377,6 +1652,8 @@ meta_onscreen_native_swap_buffers_with_damage (CoglOnscreen *onscreen, + buffer = acquire_front_buffer (onscreen, + primary_gpu_fb, + secondary_gpu_fb, ++ rectangles, ++ n_rectangles, + &error); + if (buffer == NULL) + { +@@ -1402,15 +1679,86 @@ meta_onscreen_native_swap_buffers_with_damage (CoglOnscreen *onscreen, #endif } @@ -1855,7 +2159,7 @@ index 021ada3677..a9d54f43c0 100644 kms_update = meta_frame_native_ensure_kms_update (frame_native, kms_device); meta_kms_update_add_result_listener (kms_update, -@@ -1432,13 +1624,11 @@ meta_onscreen_native_swap_buffers_with_damage (CoglOnscreen *onscreen, +@@ -1432,13 +1780,11 @@ meta_onscreen_native_swap_buffers_with_damage (CoglOnscreen *onscreen, { meta_renderer_native_queue_power_save_page_flip (renderer_native, onscreen); @@ -1870,7 +2174,7 @@ index 021ada3677..a9d54f43c0 100644 switch (renderer_gpu_data->mode) { -@@ -1453,8 +1643,6 @@ meta_onscreen_native_swap_buffers_with_damage (CoglOnscreen *onscreen, +@@ -1453,8 +1799,6 @@ meta_onscreen_native_swap_buffers_with_damage (CoglOnscreen *onscreen, kms_update = meta_frame_native_steal_kms_update (frame_native); meta_renderer_native_queue_mode_set_update (renderer_native, kms_update); @@ -1879,7 +2183,7 @@ index 021ada3677..a9d54f43c0 100644 return; } else if (meta_renderer_native_has_pending_mode_set (renderer_native)) -@@ -1468,8 +1656,6 @@ meta_onscreen_native_swap_buffers_with_damage (CoglOnscreen *onscreen, +@@ -1468,8 +1812,6 @@ meta_onscreen_native_swap_buffers_with_damage (CoglOnscreen *onscreen, meta_frame_native_steal_kms_update (frame_native); meta_renderer_native_post_mode_set_updates (renderer_native); @@ -1888,7 +2192,7 @@ index 021ada3677..a9d54f43c0 100644 return; } break; -@@ -1485,8 +1671,6 @@ meta_onscreen_native_swap_buffers_with_damage (CoglOnscreen *onscreen, +@@ -1485,8 +1827,6 @@ meta_onscreen_native_swap_buffers_with_damage (CoglOnscreen *onscreen, kms_update); meta_renderer_native_post_mode_set_updates (renderer_native); @@ -1897,8 +2201,21 @@ index 021ada3677..a9d54f43c0 100644 return; } break; -@@ -1503,13 +1687,6 @@ meta_onscreen_native_swap_buffers_with_damage (CoglOnscreen *onscreen, - meta_kms_update_set_sync_fd (kms_update, sync_fd); +@@ -1499,17 +1839,17 @@ meta_onscreen_native_swap_buffers_with_damage (CoglOnscreen *onscreen, + meta_kms_device_get_path (kms_device)); + + kms_update = meta_frame_native_steal_kms_update (frame_native); +- sync_fd = cogl_context_get_latest_sync_fd (cogl_context); +- meta_kms_update_set_sync_fd (kms_update, sync_fd); ++ ++ if (!secondary_gpu_used) ++ { ++ int sync_fd; ++ ++ sync_fd = cogl_context_get_latest_sync_fd (cogl_context); ++ meta_kms_update_set_sync_fd (kms_update, sync_fd); ++ } ++ meta_kms_device_post_update (kms_device, kms_update, META_KMS_UPDATE_FLAG_NONE); - clutter_frame_set_result (frame, CLUTTER_FRAME_RESULT_PENDING_PRESENTED); @@ -1911,7 +2228,7 @@ index 021ada3677..a9d54f43c0 100644 } gboolean -@@ -1577,11 +1754,11 @@ scanout_result_feedback (const MetaKmsFeedback *kms_feedback, +@@ -1577,11 +1917,11 @@ scanout_result_feedback (const MetaKmsFeedback *kms_feedback, G_IO_ERROR_PERMISSION_DENIED)) { ClutterStageView *view = CLUTTER_STAGE_VIEW (onscreen_native->view); @@ -1927,7 +2244,7 @@ index 021ada3677..a9d54f43c0 100644 g_warning ("Direct scanout page flip failed: %s", error->message); -@@ -1594,7 +1771,7 @@ scanout_result_feedback (const MetaKmsFeedback *kms_feedback, +@@ -1594,7 +1934,7 @@ scanout_result_feedback (const MetaKmsFeedback *kms_feedback, frame_info->flags |= COGL_FRAME_INFO_FLAG_SYMBOLIC; meta_onscreen_native_notify_frame_complete (onscreen); @@ -1936,7 +2253,7 @@ index 021ada3677..a9d54f43c0 100644 } static const MetaKmsResultListenerVtable scanout_result_listener_vtable = { -@@ -1646,13 +1823,24 @@ meta_onscreen_native_direct_scanout (CoglOnscreen *onscreen, +@@ -1646,13 +1986,24 @@ meta_onscreen_native_direct_scanout (CoglOnscreen *onscreen, return FALSE; } @@ -1963,7 +2280,7 @@ index 021ada3677..a9d54f43c0 100644 meta_frame_native_set_scanout (frame_native, scanout); meta_frame_native_set_buffer (frame_native, -@@ -1899,22 +2087,79 @@ meta_onscreen_native_finish_frame (CoglOnscreen *onscreen, +@@ -1899,22 +2250,79 @@ meta_onscreen_native_finish_frame (CoglOnscreen *onscreen, MetaKmsDevice *kms_device = meta_kms_crtc_get_device (kms_crtc); MetaFrameNative *frame_native = meta_frame_native_from_frame (frame); MetaKmsUpdate *kms_update; @@ -2051,7 +2368,7 @@ index 021ada3677..a9d54f43c0 100644 meta_kms_update_add_result_listener (kms_update, &finish_frame_result_listener_vtable, NULL, -@@ -1937,7 +2182,17 @@ meta_onscreen_native_finish_frame (CoglOnscreen *onscreen, +@@ -1937,7 +2345,17 @@ meta_onscreen_native_finish_frame (CoglOnscreen *onscreen, meta_kms_update_set_flushing (kms_update, kms_crtc); meta_kms_device_post_update (kms_device, kms_update, META_KMS_UPDATE_FLAG_NONE); @@ -2070,7 +2387,7 @@ index 021ada3677..a9d54f43c0 100644 } static gboolean -@@ -2842,6 +3097,8 @@ meta_onscreen_native_dispose (GObject *object) +@@ -2842,6 +3260,8 @@ meta_onscreen_native_dispose (GObject *object) meta_onscreen_native_detach (onscreen_native); g_clear_pointer (&onscreen_native->next_frame, clutter_frame_unref); @@ -2093,17 +2410,263 @@ index 0e1193325a..e30357d19d 100644 MetaRendererView *view); diff --git a/src/backends/native/meta-renderer-native-gles3.c b/src/backends/native/meta-renderer-native-gles3.c -index 159e2daef0..51a449a96d 100644 +index 159e2daef0..4c84b6ddb3 100644 --- a/src/backends/native/meta-renderer-native-gles3.c +++ b/src/backends/native/meta-renderer-native-gles3.c -@@ -352,21 +352,12 @@ meta_renderer_native_gles3_blit_shared_bo (MetaEgl *egl, - MetaGles3 *gles3, - EGLDisplay egl_display, - EGLContext egl_context, +@@ -196,11 +196,13 @@ ensure_shader_program (ContextData *context_data, + "attribute vec2 position;\n" + "attribute vec2 texcoord;\n" + "varying vec2 v_texcoord;\n" ++ "uniform float framebuffer_width;\n" ++ "uniform float framebuffer_height;\n" + "\n" + "void main()\n" + "{\n" +- " gl_Position = vec4(position, 0.0, 1.0);\n" +- " v_texcoord = texcoord;\n" ++ " gl_Position = vec4(position.x / framebuffer_width * 2.0 - 1.0, position.y / framebuffer_height * 2.0 - 1.0, 0.0, 1.0);\n" ++ " v_texcoord = vec2(texcoord.x / framebuffer_width, texcoord.y / framebuffer_height);\n" + "}\n"; + + static const char fragment_shader_source[] = +@@ -215,16 +217,8 @@ ensure_shader_program (ContextData *context_data, + " gl_FragColor = texture2D(s_texture, v_texcoord);\n" + "}\n"; + +- static const GLfloat box[] = +- { /* position texcoord */ +- -1.0f, +1.0f, 0.0f, 0.0f, +- +1.0f, +1.0f, 1.0f, 0.0f, +- +1.0f, -1.0f, 1.0f, 1.0f, +- -1.0f, -1.0f, 0.0f, 1.0f, +- }; + GLint linked; + GLuint vertex_shader, fragment_shader; +- GLint position_attrib, texcoord_attrib; + GLuint shader_program; + + if (context_data->shader_program) +@@ -254,23 +248,15 @@ ensure_shader_program (ContextData *context_data, + } + + GLBAS (gles3, glUseProgram, (shader_program)); +- +- position_attrib = glGetAttribLocation (shader_program, "position"); +- GLBAS (gles3, glEnableVertexAttribArray, (position_attrib)); +- GLBAS (gles3, glVertexAttribPointer, +- (position_attrib, 2, GL_FLOAT, GL_FALSE, 4 * sizeof (GLfloat), box)); +- +- texcoord_attrib = glGetAttribLocation (shader_program, "texcoord"); +- GLBAS (gles3, glEnableVertexAttribArray, (texcoord_attrib)); +- GLBAS (gles3, glVertexAttribPointer, +- (texcoord_attrib, 2, GL_FLOAT, GL_FALSE, 4 * sizeof (GLfloat), box + 2)); + } + + static void +-blit_egl_image (MetaGles3 *gles3, +- EGLImageKHR egl_image, +- int width, +- int height) ++blit_egl_image (MetaGles3 *gles3, ++ EGLImageKHR egl_image, ++ int width, ++ int height, ++ const MtkRectangle *rectangles, ++ int n_rectangles) + { + GLuint texture; + GLuint framebuffer; +@@ -301,29 +287,152 @@ blit_egl_image (MetaGles3 *gles3, + GL_TEXTURE_2D, texture, 0)); + + GLBAS (gles3, glBindFramebuffer, (GL_READ_FRAMEBUFFER, framebuffer)); +- GLBAS (gles3, glBlitFramebuffer, (0, height, width, 0, +- 0, 0, width, height, +- GL_COLOR_BUFFER_BIT, +- GL_NEAREST)); ++ ++ if (n_rectangles > 0) ++ { ++ int i; ++ ++ for (i = 0; i < n_rectangles; ++i) ++ { ++ GLint x1 = rectangles[i].x; ++ GLint y1 = height - rectangles[i].y - rectangles[i].height; ++ GLint src_y1 = rectangles[i].y; ++ GLint x2 = x1 + rectangles[i].width; ++ GLint y2 = y1 + rectangles[i].height; ++ GLint src_y2 = src_y1 + rectangles[i].height; ++ ++ GLBAS (gles3, glBlitFramebuffer, (x1, src_y2, x2, src_y1, ++ x1, height - rectangles[i].y - rectangles[i].height, x2, y2, ++ GL_COLOR_BUFFER_BIT, ++ GL_NEAREST)); ++ } ++ } ++ else ++ GLBAS (gles3, glBlitFramebuffer, (0, height, width, 0, ++ 0, 0, width, height, ++ GL_COLOR_BUFFER_BIT, ++ GL_NEAREST)); ++ + + GLBAS (gles3, glDeleteTextures, (1, &texture)); + GLBAS (gles3, glDeleteFramebuffers, (1, &framebuffer)); + } + + static void +-paint_egl_image (ContextData *context_data, +- MetaGles3 *gles3, +- EGLImageKHR egl_image, +- int width, +- int height) ++paint_egl_image (ContextData *context_data, ++ MetaGles3 *gles3, ++ EGLImageKHR egl_image, ++ int width, ++ int height, ++ const MtkRectangle *rectangles, ++ int n_rectangles) + { ++ static const uint triangle_count_per_rectangle = 2; ++ static const uint vertex_per_triangle = 3; ++ static const uint values_per_vertex = 4; ++ ++ const MtkRectangle full_damage_rectangle = {0, 0, width, height}; ++ ++ int i; + GLuint texture; ++ GLint *vertices = NULL; ++ GLuint vertex_buffer_object; ++ GLuint vertex_array_object; ++ GLint position_attrib, texcoord_attrib; ++ GLint framebuffer_width_uniform, framebuffer_height_uniform; ++ GLuint components_per_rectangle = triangle_count_per_rectangle * vertex_per_triangle * values_per_vertex; ++ GLuint size_per_rectangle = components_per_rectangle * sizeof(GLint); ++ GLuint vertices_size; ++ ++ if (n_rectangles == 0) ++ { ++ n_rectangles = 1; ++ rectangles = &full_damage_rectangle; ++ } ++ ++ vertices_size = n_rectangles * size_per_rectangle; ++ ++ vertices = g_alloca (vertices_size); ++ ++ for (i = 0; i < n_rectangles; ++i) ++ { ++ const MtkRectangle *rectangle = &rectangles[i]; ++ GLint *rectangle_vertices = &vertices[i * components_per_rectangle]; ++ ++ int reversed_rect_y = height - rectangles[i].y - rectangles[i].height; ++ ++ GLint x1 = rectangle->x; ++ GLint y1 = reversed_rect_y; ++ GLint x2 = rectangle->x + rectangle->width; ++ GLint y2 = reversed_rect_y + rectangle->height; ++ ++ GLint u1 = rectangle->x; ++ GLint v1 = rectangle->y; ++ GLint u2 = rectangle->x + rectangle->width; ++ GLint v2 = rectangle->y + rectangle->height; ++ ++ rectangle_vertices[0] = x1; ++ rectangle_vertices[1] = y2; ++ rectangle_vertices[2] = u1; ++ rectangle_vertices[3] = v1; ++ ++ rectangle_vertices[4] = x2; ++ rectangle_vertices[5] = y2; ++ rectangle_vertices[6] = u2; ++ rectangle_vertices[7] = v1; ++ ++ rectangle_vertices[8] = x1; ++ rectangle_vertices[9] = y1; ++ rectangle_vertices[10] = u1; ++ rectangle_vertices[11] = v2; ++ ++ rectangle_vertices[12] = x1; ++ rectangle_vertices[13] = y1; ++ rectangle_vertices[14] = u1; ++ rectangle_vertices[15] = v2; ++ ++ rectangle_vertices[16] = x2; ++ rectangle_vertices[17] = y2; ++ rectangle_vertices[18] = u2; ++ rectangle_vertices[19] = v1; ++ ++ rectangle_vertices[20] = x2; ++ rectangle_vertices[21] = y1; ++ rectangle_vertices[22] = u2; ++ rectangle_vertices[23] = v2; ++ } + + meta_gles3_clear_error (gles3); + ensure_shader_program (context_data, gles3); + ++ g_return_if_fail (context_data->shader_program); ++ + GLBAS (gles3, glViewport, (0, 0, width, height)); + ++ GLBAS (gles3, glGenVertexArrays, (1, &vertex_array_object)); ++ GLBAS (gles3, glBindVertexArray, (vertex_array_object)); ++ ++ GLBAS (gles3, glGenBuffers, (1, &vertex_buffer_object)); ++ GLBAS (gles3, glBindBuffer, (GL_ARRAY_BUFFER, vertex_buffer_object)); ++ GLBAS (gles3, glBufferData, ++ (GL_ARRAY_BUFFER, vertices_size, vertices, GL_DYNAMIC_DRAW)); ++ ++ position_attrib = glGetAttribLocation (context_data->shader_program, "position"); ++ GLBAS (gles3, glEnableVertexAttribArray, (position_attrib)); ++ GLBAS (gles3, glVertexAttribPointer, ++ (position_attrib, 2, GL_INT, GL_FALSE, 4 * sizeof (GLint), NULL)); ++ ++ texcoord_attrib = glGetAttribLocation (context_data->shader_program, "texcoord"); ++ GLBAS (gles3, glEnableVertexAttribArray, (texcoord_attrib)); ++ GLBAS (gles3, glVertexAttribPointer, ++ (texcoord_attrib, 2, GL_INT, GL_FALSE, 4 * sizeof (GLint), (void*)(sizeof(GLint) * 2))); ++ ++ framebuffer_width_uniform = glGetUniformLocation (context_data->shader_program, "framebuffer_width"); ++ GLBAS (gles3, glUniform1f, (framebuffer_width_uniform, width)); ++ ++ framebuffer_height_uniform = glGetUniformLocation (context_data->shader_program, "framebuffer_height"); ++ GLBAS (gles3, glUniform1f, (framebuffer_height_uniform, height)); ++ + GLBAS (gles3, glActiveTexture, (GL_TEXTURE0)); + GLBAS (gles3, glGenTextures, (1, &texture)); + GLBAS (gles3, glBindTexture, (GL_TEXTURE_EXTERNAL_OES, texture)); +@@ -342,31 +451,26 @@ paint_egl_image (ContextData *context_data, + GL_TEXTURE_WRAP_T, + GL_CLAMP_TO_EDGE)); + +- GLBAS (gles3, glDrawArrays, (GL_TRIANGLE_FAN, 0, 4)); ++ GLBAS (gles3, glDrawArrays, (GL_TRIANGLES, 0, triangle_count_per_rectangle * vertex_per_triangle * n_rectangles)); + + GLBAS (gles3, glDeleteTextures, (1, &texture)); ++ GLBAS (gles3, glDeleteBuffers, (1, &vertex_buffer_object)); ++ GLBAS (gles3, glDeleteVertexArrays, (1, &vertex_array_object)); + } + + gboolean +-meta_renderer_native_gles3_blit_shared_bo (MetaEgl *egl, +- MetaGles3 *gles3, +- EGLDisplay egl_display, +- EGLContext egl_context, - EGLSurface egl_surface, -+ EGLImageKHR egl_image, - struct gbm_bo *shared_bo, - GError **error) +- struct gbm_bo *shared_bo, +- GError **error) ++meta_renderer_native_gles3_blit_shared_bo (MetaEgl *egl, ++ MetaGles3 *gles3, ++ EGLDisplay egl_display, ++ EGLContext egl_context, ++ EGLImageKHR egl_image, ++ struct gbm_bo *shared_bo, ++ const MtkRectangle *rectangles, ++ int n_rectangles, ++ GError **error) { - int shared_bo_fd; unsigned int width; @@ -2119,7 +2682,7 @@ index 159e2daef0..51a449a96d 100644 GQuark context_data_quark; ContextData *context_data; gboolean can_blit; -@@ -390,57 +381,14 @@ meta_renderer_native_gles3_blit_shared_bo (MetaEgl *egl, +@@ -390,56 +494,13 @@ meta_renderer_native_gles3_blit_shared_bo (MetaEgl *egl, gbm_bo_get_format (shared_bo), gbm_bo_get_modifier (shared_bo)); @@ -2168,28 +2731,45 @@ index 159e2daef0..51a449a96d 100644 - return FALSE; if (can_blit) - blit_egl_image (gles3, egl_image, width, height); +- blit_egl_image (gles3, egl_image, width, height); ++ blit_egl_image (gles3, egl_image, width, height, rectangles, n_rectangles); else - paint_egl_image (context_data, gles3, egl_image, width, height); - -- meta_egl_destroy_image (egl, egl_display, egl_image, NULL); +- paint_egl_image (context_data, gles3, egl_image, width, height); - +- meta_egl_destroy_image (egl, egl_display, egl_image, NULL); ++ paint_egl_image (context_data, gles3, egl_image, width, height, rectangles, n_rectangles); + return TRUE; } - diff --git a/src/backends/native/meta-renderer-native-gles3.h b/src/backends/native/meta-renderer-native-gles3.h -index f5791a171f..6a935c7e6b 100644 +index f5791a171f..c13ebb9180 100644 --- a/src/backends/native/meta-renderer-native-gles3.h +++ b/src/backends/native/meta-renderer-native-gles3.h -@@ -30,7 +30,7 @@ gboolean meta_renderer_native_gles3_blit_shared_bo (MetaEgl *egl, - MetaGles3 *gles3, - EGLDisplay egl_display, - EGLContext egl_context, -- EGLSurface egl_surface, -+ EGLImageKHR egl_image, - struct gbm_bo *shared_bo, - GError **error); +@@ -25,14 +25,17 @@ + #include "backends/meta-egl.h" + #include "backends/meta-gles3.h" ++#include "mtk/mtk.h" + +-gboolean meta_renderer_native_gles3_blit_shared_bo (MetaEgl *egl, +- MetaGles3 *gles3, +- EGLDisplay egl_display, +- EGLContext egl_context, +- EGLSurface egl_surface, +- struct gbm_bo *shared_bo, +- GError **error); ++gboolean meta_renderer_native_gles3_blit_shared_bo (MetaEgl *egl, ++ MetaGles3 *gles3, ++ EGLDisplay egl_display, ++ EGLContext egl_context, ++ EGLImageKHR egl_image, ++ struct gbm_bo *shared_bo, ++ const MtkRectangle *rectangles, ++ int n_rectangles, ++ GError **error); + + void meta_renderer_native_gles3_forget_context (MetaGles3 *gles3, + EGLContext egl_context); diff --git a/src/backends/native/meta-renderer-native.c b/src/backends/native/meta-renderer-native.c index 7034206bcd..d4ff9e2177 100644 --- a/src/backends/native/meta-renderer-native.c |