egl/main: Add bits for EGL_KHR_mutable_render_buffer
authorChad Versace <chadversary@chromium.org>
Tue, 1 May 2018 05:32:25 +0000 (22:32 -0700)
committerChad Versace <chadversary@chromium.org>
Tue, 7 Aug 2018 18:11:05 +0000 (11:11 -0700)
A follow-up patch enables EGL_KHR_mutable_render_buffer for Android.
This patch is separate from the Android patch because I think it's
easier to review the platform-independent bits separately.

Reviewed-by: Tapani Pälli <tapani.palli@intel.com>
src/egl/main/eglapi.c
src/egl/main/eglconfig.c
src/egl/main/egldisplay.h
src/egl/main/eglsurface.c
src/egl/main/eglsurface.h

index 0960daccfb05938d5dfbda53e056665bfc94eed9..19fae12f5b7596e079590dacc47abc74f1c4468b 100644 (file)
@@ -509,6 +509,7 @@ _eglCreateExtensionsString(_EGLDisplay *dpy)
    _EGL_CHECK_EXTENSION(KHR_image);
    _EGL_CHECK_EXTENSION(KHR_image_base);
    _EGL_CHECK_EXTENSION(KHR_image_pixmap);
+   _EGL_CHECK_EXTENSION(KHR_mutable_render_buffer);
    _EGL_CHECK_EXTENSION(KHR_no_config_context);
    _EGL_CHECK_EXTENSION(KHR_partial_update);
    _EGL_CHECK_EXTENSION(KHR_reusable_sync);
index 461feb06423f3ee8eba2253151759b1d87b5c2cc..0456adf3caaa8df9d5fc5d8b8d4290d5d00b0c4c 100644 (file)
@@ -272,6 +272,7 @@ static const struct {
 EGLBoolean
 _eglValidateConfig(const _EGLConfig *conf, EGLBoolean for_matching)
 {
+   _EGLDisplay *disp = conf->Display;
    EGLint i, attr, val;
    EGLBoolean valid = EGL_TRUE;
 
@@ -340,6 +341,8 @@ _eglValidateConfig(const _EGLConfig *conf, EGLBoolean for_matching)
                    EGL_VG_ALPHA_FORMAT_PRE_BIT |
                    EGL_MULTISAMPLE_RESOLVE_BOX_BIT |
                    EGL_SWAP_BEHAVIOR_PRESERVED_BIT;
+            if (disp->Extensions.KHR_mutable_render_buffer)
+               mask |= EGL_MUTABLE_RENDER_BUFFER_BIT_KHR;
             break;
          case EGL_RENDERABLE_TYPE:
          case EGL_CONFORMANT:
index d7e51991a45d111891d21faa1df356aae3952b7a..4a7f248e34cc598d8ff70b248e500fa209645016 100644 (file)
@@ -127,6 +127,7 @@ struct _egl_extensions
    EGLBoolean KHR_image;
    EGLBoolean KHR_image_base;
    EGLBoolean KHR_image_pixmap;
+   EGLBoolean KHR_mutable_render_buffer;
    EGLBoolean KHR_no_config_context;
    EGLBoolean KHR_partial_update;
    EGLBoolean KHR_reusable_sync;
index 73c31e115884e63ce924926ec0bf1d1913018ba6..926b7ab569a3ded5be280a022915ec68a0d5d8f3 100644 (file)
@@ -123,6 +123,12 @@ _eglParseSurfaceAttribList(_EGLSurface *surf, const EGLint *attrib_list)
             break;
          }
          surf->RequestedRenderBuffer = val;
+         if (surf->Config->SurfaceType & EGL_MUTABLE_RENDER_BUFFER_BIT_KHR) {
+            /* Unlike normal EGLSurfaces, one with a mutable render buffer
+             * uses the application-chosen render buffer.
+             */
+            surf->ActiveRenderBuffer = val;
+         }
          break;
       case EGL_POST_SUB_BUFFER_SUPPORTED_NV:
          if (!dpy->Extensions.NV_post_sub_buffer ||
@@ -359,12 +365,19 @@ _eglQuerySurface(_EGLDriver *drv, _EGLDisplay *dpy, _EGLSurface *surface,
       *value = surface->SwapBehavior;
       break;
    case EGL_RENDER_BUFFER:
-      /* From the EGL 1.5 spec (2014.08.27):
+      /* From the EGL_KHR_mutable_render_buffer spec (v12):
        *
        *    Querying EGL_RENDER_BUFFER returns the buffer which client API
        *    rendering is requested to use. For a window surface, this is the
-       *    same attribute value specified when the surface was created. For
-       *    a pbuffer surface, it is always EGL_BACK_BUFFER . For a pixmap
+       *    attribute value specified when the surface was created or last set
+       *    via eglSurfaceAttrib.
+       *
+       * In other words, querying a window surface returns the value most
+       * recently *requested* by the user.
+       *
+       * The paragraph continues in the EGL 1.5 spec (2014.08.27):
+       *
+       *    For a pbuffer surface, it is always EGL_BACK_BUFFER . For a pixmap
        *    surface, it is always EGL_SINGLE_BUFFER . To determine the actual
        *    buffer being rendered to by a context, call eglQueryContext.
        */
@@ -472,6 +485,31 @@ _eglSurfaceAttrib(_EGLDriver *drv, _EGLDisplay *dpy, _EGLSurface *surface,
          break;
       surface->MultisampleResolve = value;
       break;
+   case EGL_RENDER_BUFFER:
+      if (!dpy->Extensions.KHR_mutable_render_buffer) {
+         err = EGL_BAD_ATTRIBUTE;
+         break;
+      }
+
+      if (value != EGL_BACK_BUFFER && value != EGL_SINGLE_BUFFER) {
+         err = EGL_BAD_PARAMETER;
+         break;
+      }
+
+      /* From the EGL_KHR_mutable_render_buffer spec (v12):
+       *
+       *    If attribute is EGL_RENDER_BUFFER, and the EGL_SURFACE_TYPE
+       *    attribute of the EGLConfig used to create surface does not contain
+       *    EGL_MUTABLE_RENDER_BUFFER_BIT_KHR, [...] an EGL_BAD_MATCH error is
+       *    generated [...].
+       */
+      if (!(surface->Config->SurfaceType & EGL_MUTABLE_RENDER_BUFFER_BIT_KHR)) {
+         err = EGL_BAD_MATCH;
+         break;
+      }
+
+      surface->RequestedRenderBuffer = value;
+      break;
    case EGL_SWAP_BEHAVIOR:
       switch (value) {
       case EGL_BUFFER_DESTROYED:
@@ -573,3 +611,18 @@ _eglSwapInterval(_EGLDriver *drv, _EGLDisplay *dpy, _EGLSurface *surf,
 {
    return EGL_TRUE;
 }
+
+EGLBoolean
+_eglSurfaceHasMutableRenderBuffer(_EGLSurface *surf)
+{
+   return surf->Type == EGL_WINDOW_BIT &&
+          surf->Config &&
+          (surf->Config->SurfaceType & EGL_MUTABLE_RENDER_BUFFER_BIT_KHR);
+}
+
+EGLBoolean
+_eglSurfaceInSharedBufferMode(_EGLSurface *surf)
+{
+   return _eglSurfaceHasMutableRenderBuffer(surf) &&
+          surf->ActiveRenderBuffer == EGL_SINGLE_BUFFER;
+}
index 06e3b5b1b815734692af9346599f396f946508e5..5d69bf487cfeebaa9d3fe6cdcfba7b97174706e2 100644 (file)
@@ -78,7 +78,20 @@ struct _egl_surface
     * surfaces, the EGL spec hard-codes the EGL_RENDER_BUFFER value and the
     * user must not provide it in the attribute list.
     *
-    * Refer to eglQuerySurface() in the EGL spec.
+    * Normally, the attribute is immutable and after surface creation.
+    * However, EGL_KHR_mutable_render_buffer allows the user to change it in
+    * window surfaces via eglSurfaceAttrib, in which case
+    * eglQuerySurface(EGL_RENDER_BUFFER) will immediately afterwards return
+    * the requested value but the actual render buffer used by the context
+    * does not change until completion of the next eglSwapBuffers call.
+    *
+    * From the EGL_KHR_mutable_render_buffer spec (v12):
+    *
+    *    Querying EGL_RENDER_BUFFER returns the buffer which client API
+    *    rendering is requested to use. For a window surface, this is the
+    *    attribute value specified when the surface was created or last set
+    *    via eglSurfaceAttrib.
+    *
     * eglQueryContext(EGL_RENDER_BUFFER) ignores this.
     */
    EGLenum RequestedRenderBuffer;
@@ -91,6 +104,19 @@ struct _egl_surface
     *
     * Refer to eglQueryContext(EGL_RENDER_BUFFER) in the EGL spec.
     * eglQuerySurface(EGL_RENDER_BUFFER) ignores this.
+    *
+    * If a window surface is bound as the draw surface and has a pending,
+    * user-requested change to EGL_RENDER_BUFFER, then the next eglSwapBuffers
+    * will flush the pending change. (The flush of EGL_RENDER_BUFFER state may
+    * occur without the implicit glFlush induced by eglSwapBuffers). The spec
+    * requires that the flush occur at that time and nowhere else. During the
+    * state-flush, we copy RequestedRenderBuffer to ActiveRenderBuffer.
+    *
+    * From the EGL_KHR_mutable_render_buffer spec (v12):
+    *
+    *    If [...] there is a pending change to the EGL_RENDER_BUFFER
+    *    attribute, eglSwapBuffers performs an implicit flush operation on the
+    *    context and effects the attribute change.
     */
    EGLenum ActiveRenderBuffer;
 
@@ -150,6 +176,11 @@ _eglReleaseTexImage(_EGLDriver *drv, _EGLDisplay *disp, _EGLSurface *surf, EGLin
 extern EGLBoolean
 _eglSwapInterval(_EGLDriver *drv, _EGLDisplay *dpy, _EGLSurface *surf, EGLint interval);
 
+extern EGLBoolean
+_eglSurfaceHasMutableRenderBuffer(_EGLSurface *surf);
+
+extern EGLBoolean
+_eglSurfaceInSharedBufferMode(_EGLSurface *surf);
 
 /**
  * Increment reference count for the surface.