File 0006-base-Add-basic-support-for-EGL_KHR_partial_update.patch of Package libnvidia-egl-wayland2
From dcbb123f1804572889d2dc45af00e89ee9e5ff4f Mon Sep 17 00:00:00 2001
From: Kyle Brenneman <kbrenneman@nvidia.com>
Date: Tue, 14 Oct 2025 16:33:47 -0600
Subject: [PATCH 06/18] base: Add basic support for EGL_KHR_partial_update.
Add the necessary bookkeeping to handle EGL_KHR_partial_update and
EGL_EXT_buffer_age.
Added hook functions for eglQuerySurface and eglSetDamageRegionKHR.
Added flags to EplSurface to keep track of whether EGL_BUFFER_AGE has
been queried, and whether eglSetDamageRegionKHR has been called, since
that affects the error behavior of eglSetDamageRegionKHR.
Currently, it'll just return zero for EGL_BUFFER_AGE and ignore the
rectangles for eglSetDamageRegionKHR, which is valid if not very useful.
Later change will add functions to EplImplFuncs to plumb those through
to platform-specific handlers.
---
src/base/platform-base.c | 127 +++++++++++++++++++++++++++++++++++++++
src/base/platform-base.h | 14 +++++
2 files changed, 141 insertions(+)
diff --git a/src/base/platform-base.c b/src/base/platform-base.c
index 2560f14..94aa4b7 100644
--- a/src/base/platform-base.c
+++ b/src/base/platform-base.c
@@ -135,6 +135,7 @@ EplPlatformData *eplPlatformBaseAllocate(int major, int minor,
platform->egl.ChooseConfig = driver->getProcAddress("eglChooseConfig");
platform->egl.GetConfigAttrib = driver->getProcAddress("eglGetConfigAttrib");
platform->egl.GetConfigs = driver->getProcAddress("eglGetConfigs");
+ platform->egl.QuerySurface = driver->getProcAddress("eglQuerySurface");
platform->egl.QueryDeviceAttribEXT = driver->getProcAddress("eglQueryDeviceAttribEXT");
platform->egl.QueryDeviceStringEXT = driver->getProcAddress("eglQueryDeviceStringEXT");
platform->egl.QueryDevicesEXT = driver->getProcAddress("eglQueryDevicesEXT");
@@ -164,6 +165,7 @@ EplPlatformData *eplPlatformBaseAllocate(int major, int minor,
|| platform->egl.ChooseConfig == NULL
|| platform->egl.GetConfigAttrib == NULL
|| platform->egl.GetConfigs == NULL
+ || platform->egl.QuerySurface == NULL
|| platform->egl.QueryDeviceAttribEXT == NULL
|| platform->egl.QueryDeviceStringEXT == NULL
|| platform->egl.QueryDevicesEXT == NULL
@@ -1110,6 +1112,11 @@ static EGLBoolean HookSwapBuffersWithDamage(EGLDisplay edpy, EGLSurface esurf, c
else
{
ret = pdpy->platform->impl->SwapBuffers(pdpy->platform, pdpy, psurf, rects, n_rects);
+ if (ret)
+ {
+ psurf->setDamageRegionCalled = EGL_FALSE;
+ psurf->bufferAgeCalled = EGL_FALSE;
+ }
}
eplHookDisplaySurfaceEnd(pdpy, psurf);
@@ -1295,6 +1302,124 @@ static EGLBoolean HookSwapInterval(EGLDisplay edpy, EGLint interval)
return ret;
}
+static EGLBoolean HookQuerySurface(EGLDisplay edpy, EGLSurface esurf, EGLint attribute, EGLint *value)
+{
+ EplDisplay *pdpy;
+ EplSurface *psurf;
+ EGLBoolean ret = EGL_FALSE;
+
+ if (!eplHookDisplaySurface(edpy, esurf, &pdpy, &psurf))
+ {
+ return EGL_FALSE;
+ }
+
+ if (value == NULL)
+ {
+ eplSetError(pdpy->platform, EGL_BAD_PARAMETER, "value pointer must not be NULL");
+ goto done;
+ }
+
+ if (psurf != NULL)
+ {
+ if (attribute == EGL_BUFFER_AGE_KHR)
+ {
+ if (pdpy->platform->egl.GetCurrentSurface(EGL_DRAW) != esurf)
+ {
+ eplSetError(pdpy->platform, EGL_BAD_SURFACE, "EGLSurface %p is not current", esurf);
+ goto done;
+ }
+
+ // Note: This is where we'll call into the platform-specific code
+ // once we add a query function to EplImplFuncs. Until then,
+ // returning zero is valid (if not very useful).
+ *value = 0;
+
+ psurf->bufferAgeCalled = EGL_TRUE;
+ ret = EGL_TRUE;
+ }
+ else
+ {
+ // If it's not an attribute that we recognize, then pass the query
+ // through to the driver.
+ ret = pdpy->platform->egl.QuerySurface(pdpy->internal_display,
+ psurf->internal_surface, attribute, value);
+ }
+ }
+ else
+ {
+ // If it's not an EGLSurface that we recognize, then pass the query
+ // through to the driver.
+ ret = pdpy->platform->egl.QuerySurface(pdpy->internal_display,
+ esurf, attribute, value);
+ }
+
+done:
+ eplHookDisplaySurfaceEnd(pdpy, psurf);
+ return ret;
+}
+
+static EGLBoolean HookSetDamageRegion(EGLDisplay edpy, EGLSurface esurf, EGLint *rects, EGLint n_rects)
+{
+ EplDisplay *pdpy;
+ EplSurface *psurf;
+ EGLBoolean ret = EGL_FALSE;
+
+ if (!eplHookDisplaySurface(edpy, esurf, &pdpy, &psurf))
+ {
+ return EGL_FALSE;
+ }
+
+ if (psurf != NULL)
+ {
+ if (psurf->type != EPL_SURFACE_TYPE_WINDOW)
+ {
+ eplSetError(pdpy->platform, EGL_BAD_MATCH, "EGLSurface %p is not a postable surface", esurf);
+ goto done;
+ }
+ if (pdpy->platform->egl.GetCurrentSurface(EGL_DRAW) != esurf)
+ {
+ eplSetError(pdpy->platform, EGL_BAD_MATCH, "EGLSurface %p is not current", esurf);
+ goto done;
+ }
+ if (!psurf->bufferAgeCalled)
+ {
+ eplSetError(pdpy->platform, EGL_BAD_ACCESS,
+ "EGL_BUFFER_AGE_KHR must be queried before calling eglSetDamageRegionKHR");
+ goto done;
+ }
+ if (psurf->setDamageRegionCalled)
+ {
+ eplSetError(pdpy->platform, EGL_BAD_ACCESS,
+ "eglSetDamageRegionKHR has already been called this frame");
+ goto done;
+ }
+
+ /*
+ * Here's where we'd optionally call into the platform-specific code.
+ * Since eglSetDamageRegionKHR is just a hint, it's also valid to just
+ * ignore it.
+ */
+
+ psurf->setDamageRegionCalled = EGL_TRUE;
+ ret = EGL_TRUE;
+ }
+ else if (pdpy->platform->egl.SetDamageRegionKHR != NULL)
+ {
+ // We don't recgonize this EGLSurface, so pass it through to the driver.
+ ret = pdpy->platform->egl.SetDamageRegionKHR(pdpy->internal_display, esurf, rects, n_rects);
+ }
+ else
+ {
+ // If the driver doesn't support eglSetDamageRegionKHR, then just
+ // ignore it and return success.
+ ret = EGL_TRUE;
+ }
+
+done:
+ eplHookDisplaySurfaceEnd(pdpy, psurf);
+ return ret;
+}
+
static const EplHookFunc BASE_HOOK_FUNCTIONS[] =
{
{ "eglCreatePbufferSurface", HookCreatePbufferSurface },
@@ -1307,6 +1432,8 @@ static const EplHookFunc BASE_HOOK_FUNCTIONS[] =
{ "eglQueryDisplayAttribEXT", HookQueryDisplayAttrib },
{ "eglQueryDisplayAttribKHR", HookQueryDisplayAttrib },
{ "eglQueryDisplayAttribNV", HookQueryDisplayAttrib },
+ { "eglQuerySurface", HookQuerySurface },
+ { "eglSetDamageRegionKHR", HookSetDamageRegion },
{ "eglSwapBuffers", HookSwapBuffers },
{ "eglSwapBuffersWithDamageEXT", HookSwapBuffersWithDamage },
{ "eglSwapBuffersWithDamageKHR", HookSwapBuffersWithDamage },
diff --git a/src/base/platform-base.h b/src/base/platform-base.h
index 5616321..d615e46 100644
--- a/src/base/platform-base.h
+++ b/src/base/platform-base.h
@@ -88,6 +88,17 @@ typedef struct
*/
EplImplSurface *priv;
+ /**
+ * True if eglSetDamageRegionKHR has been called since the last
+ * eglSwapBuffers.
+ */
+ EGLBoolean setDamageRegionCalled;
+
+ /**
+ * True EGL_BUFFER_AGE has been queried since the last eglSwapBuffers.
+ */
+ EGLBoolean bufferAgeCalled;
+
struct glvnd_list entry;
} EplSurface;
@@ -218,6 +229,7 @@ typedef struct _EplPlatformData
PFNEGLWAITCLIENTPROC WaitClient;
PFNEGLWAITNATIVEPROC WaitNative;
PFNEGLSWAPINTERVALPROC SwapInterval;
+ PFNEGLQUERYSURFACEPROC QuerySurface;
PFNEGLQUERYDEVICEATTRIBEXTPROC QueryDeviceAttribEXT;
PFNEGLQUERYDEVICESTRINGEXTPROC QueryDeviceStringEXT;
@@ -226,6 +238,8 @@ typedef struct _EplPlatformData
PFNEGLSWAPBUFFERSWITHDAMAGEKHRPROC SwapBuffersWithDamage;
PFNEGLCREATESTREAMPRODUCERSURFACEKHRPROC CreateStreamProducerSurfaceKHR;
+
+ PFNEGLSETDAMAGEREGIONKHRPROC SetDamageRegionKHR;
} egl;
struct
--
2.51.0