cogl: Add support for partial update

Add support for a cogl function to set the damage_region on an onscreen
framebuffer.
The goal of this is to enable using the EGL_KHR_partial_update extension
which can potentially reduce memory bandwidth usage by some GPUs,
particularly on embedded GPUs that operate on a tiling rendering model.

Part-of: <https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/2023>
This commit is contained in:
Erico Nunes 2021-09-22 22:25:37 +02:00 committed by Marge Bot
parent 331f08fc40
commit 87965b5ce2
4 changed files with 72 additions and 0 deletions

View File

@ -300,6 +300,19 @@ cogl_onscreen_bind (CoglOnscreen *onscreen)
COGL_ONSCREEN_GET_CLASS (onscreen)->bind (onscreen); COGL_ONSCREEN_GET_CLASS (onscreen)->bind (onscreen);
} }
void
cogl_onscreen_queue_damage_region (CoglOnscreen *onscreen,
const int *rectangles,
int n_rectangles)
{
CoglOnscreenClass *klass = COGL_ONSCREEN_GET_CLASS (onscreen);
if (!klass->queue_damage_region)
return;
klass->queue_damage_region (onscreen, rectangles, n_rectangles);
}
void void
cogl_onscreen_swap_buffers_with_damage (CoglOnscreen *onscreen, cogl_onscreen_swap_buffers_with_damage (CoglOnscreen *onscreen,
const int *rectangles, const int *rectangles,

View File

@ -74,6 +74,10 @@ struct _CoglOnscreenClass
CoglFrameInfo *info, CoglFrameInfo *info,
gpointer user_data); gpointer user_data);
void (* queue_damage_region) (CoglOnscreen *onscreen,
const int *rectangles,
int n_rectangles);
gboolean (* direct_scanout) (CoglOnscreen *onscreen, gboolean (* direct_scanout) (CoglOnscreen *onscreen,
CoglScanout *scanout, CoglScanout *scanout,
CoglFrameInfo *info, CoglFrameInfo *info,
@ -227,6 +231,23 @@ cogl_onscreen_swap_buffers (CoglOnscreen *onscreen,
COGL_EXPORT int COGL_EXPORT int
cogl_onscreen_get_buffer_age (CoglOnscreen *onscreen); cogl_onscreen_get_buffer_age (CoglOnscreen *onscreen);
/**
* cogl_onscreen_queue_damage_region:
* @onscreen: A #CoglOnscreen framebuffer
* @rectangles: An array of integer 4-tuples representing damaged
* rectangles as (x, y, width, height) tuples.
* @n_rectangles: The number of 4-tuples to be read from @rectangles
*
* Implementation for https://www.khronos.org/registry/EGL/extensions/KHR/EGL_KHR_partial_update.txt
* This immediately queues state to OpenGL that will be used for the
* next swap.
* This needs to be called every frame.
*/
COGL_EXPORT void
cogl_onscreen_queue_damage_region (CoglOnscreen *onscreen,
const int *rectangles,
int n_rectangles);
/** /**
* cogl_onscreen_swap_buffers_with_damage: * cogl_onscreen_swap_buffers_with_damage:
* @onscreen: A #CoglOnscreen framebuffer * @onscreen: A #CoglOnscreen framebuffer

View File

@ -242,6 +242,31 @@ cogl_onscreen_egl_swap_region (CoglOnscreen *onscreen,
g_warning ("Error reported by eglSwapBuffersRegion"); g_warning ("Error reported by eglSwapBuffersRegion");
} }
static void
cogl_onscreen_egl_queue_damage_region (CoglOnscreen *onscreen,
const int *rectangles,
int n_rectangles)
{
CoglOnscreenEgl *onscreen_egl = COGL_ONSCREEN_EGL (onscreen);
CoglOnscreenEglPrivate *priv =
cogl_onscreen_egl_get_instance_private (onscreen_egl);
CoglFramebuffer *framebuffer = COGL_FRAMEBUFFER (onscreen);
CoglContext *context = cogl_framebuffer_get_context (framebuffer);
CoglRenderer *renderer = context->display->renderer;
CoglRendererEGL *egl_renderer = renderer->winsys;
g_return_if_fail (n_rectangles > 0);
if (!egl_renderer->pf_eglSetDamageRegion)
return;
if (egl_renderer->pf_eglSetDamageRegion (egl_renderer->edpy,
priv->egl_surface,
rectangles,
n_rectangles) == EGL_FALSE)
g_warning ("Error reported by eglSetDamageRegion");
}
static void static void
cogl_onscreen_egl_swap_buffers_with_damage (CoglOnscreen *onscreen, cogl_onscreen_egl_swap_buffers_with_damage (CoglOnscreen *onscreen,
const int *rectangles, const int *rectangles,
@ -345,6 +370,8 @@ cogl_onscreen_egl_class_init (CoglOnscreenEglClass *klass)
object_class->dispose = cogl_onscreen_egl_dispose; object_class->dispose = cogl_onscreen_egl_dispose;
onscreen_class->bind = cogl_onscreen_egl_bind; onscreen_class->bind = cogl_onscreen_egl_bind;
onscreen_class->queue_damage_region =
cogl_onscreen_egl_queue_damage_region;
onscreen_class->swap_buffers_with_damage = onscreen_class->swap_buffers_with_damage =
cogl_onscreen_egl_swap_buffers_with_damage; cogl_onscreen_egl_swap_buffers_with_damage;
onscreen_class->swap_region = cogl_onscreen_egl_swap_region; onscreen_class->swap_region = cogl_onscreen_egl_swap_region;

View File

@ -116,6 +116,17 @@ COGL_WINSYS_FEATURE_FUNCTION (EGLBoolean, eglSwapBuffersWithDamage,
EGLint n_rects)) EGLint n_rects))
COGL_WINSYS_FEATURE_END () COGL_WINSYS_FEATURE_END ()
COGL_WINSYS_FEATURE_BEGIN (partial_update,
"KHR\0",
"partial_update\0",
COGL_EGL_WINSYS_FEATURE_BUFFER_AGE)
COGL_WINSYS_FEATURE_FUNCTION (EGLBoolean, eglSetDamageRegion,
(EGLDisplay dpy,
EGLSurface surface,
const EGLint *rects,
EGLint n_rects))
COGL_WINSYS_FEATURE_END ()
#if defined(EGL_KHR_fence_sync) || defined(EGL_KHR_reusable_sync) #if defined(EGL_KHR_fence_sync) || defined(EGL_KHR_reusable_sync)
COGL_WINSYS_FEATURE_BEGIN (fence_sync, COGL_WINSYS_FEATURE_BEGIN (fence_sync,
"KHR\0", "KHR\0",