diff options
-rw-r--r-- | src/egl/main/eglapi.c | 1 | ||||
-rw-r--r-- | src/egl/main/eglconfig.c | 3 | ||||
-rw-r--r-- | src/egl/main/egldisplay.h | 1 | ||||
-rw-r--r-- | src/egl/main/eglsurface.c | 59 | ||||
-rw-r--r-- | src/egl/main/eglsurface.h | 33 |
5 files changed, 93 insertions, 4 deletions
diff --git a/src/egl/main/eglapi.c b/src/egl/main/eglapi.c index 0960daccfb0..19fae12f5b7 100644 --- a/src/egl/main/eglapi.c +++ b/src/egl/main/eglapi.c @@ -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); diff --git a/src/egl/main/eglconfig.c b/src/egl/main/eglconfig.c index 461feb06423..0456adf3caa 100644 --- a/src/egl/main/eglconfig.c +++ b/src/egl/main/eglconfig.c @@ -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: diff --git a/src/egl/main/egldisplay.h b/src/egl/main/egldisplay.h index d7e51991a45..4a7f248e34c 100644 --- a/src/egl/main/egldisplay.h +++ b/src/egl/main/egldisplay.h @@ -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; diff --git a/src/egl/main/eglsurface.c b/src/egl/main/eglsurface.c index 73c31e11588..926b7ab569a 100644 --- a/src/egl/main/eglsurface.c +++ b/src/egl/main/eglsurface.c @@ -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; +} diff --git a/src/egl/main/eglsurface.h b/src/egl/main/eglsurface.h index 06e3b5b1b81..5d69bf487cf 100644 --- a/src/egl/main/eglsurface.h +++ b/src/egl/main/eglsurface.h @@ -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. |