X-Git-Url: https://git.libre-soc.org/?p=mesa.git;a=blobdiff_plain;f=src%2Fegl%2Fmain%2Feglsurface.c;h=e38f377dc8d5797cb828dfd3d20980ad46bd1319;hp=d46bdb0672e9659901196ab9b974c9ef433cbd3b;hb=347840cf43624bdb2a5ce820e1001842e3f75ded;hpb=431a51b9af32980ae8a544d129bf567287887376 diff --git a/src/egl/main/eglsurface.c b/src/egl/main/eglsurface.c index d46bdb0672e..e38f377dc8d 100644 --- a/src/egl/main/eglsurface.c +++ b/src/egl/main/eglsurface.c @@ -1,3 +1,33 @@ +/************************************************************************** + * + * Copyright 2008 VMware, Inc. + * Copyright 2009-2010 Chia-I Wu + * Copyright 2010 LunarG, Inc. + * All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sub license, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice (including the + * next paragraph) shall be included in all copies or substantial portions + * of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + * + **************************************************************************/ + + /** * Surface-related functions. */ @@ -6,29 +36,16 @@ #include #include #include +#include "egldefines.h" #include "egldisplay.h" +#include "egldriver.h" #include "eglcontext.h" #include "eglconfig.h" #include "eglcurrent.h" #include "egllog.h" #include "eglsurface.h" - -static void -_eglClampSwapInterval(_EGLSurface *surf, EGLint interval) -{ - EGLint bound = GET_CONFIG_ATTRIB(surf->Config, EGL_MAX_SWAP_INTERVAL); - if (interval >= bound) { - interval = bound; - } - else { - bound = GET_CONFIG_ATTRIB(surf->Config, EGL_MIN_SWAP_INTERVAL); - if (interval < bound) - interval = bound; - } - surf->SwapInterval = interval; -} - +#include "util/macros.h" /** * Parse the list of surface attributes and return the proper error code. @@ -36,28 +53,126 @@ _eglClampSwapInterval(_EGLSurface *surf, EGLint interval) static EGLint _eglParseSurfaceAttribList(_EGLSurface *surf, const EGLint *attrib_list) { - _EGLDisplay *dpy = surf->Resource.Display; + _EGLDisplay *disp = surf->Resource.Display; EGLint type = surf->Type; EGLint texture_type = EGL_PBUFFER_BIT; EGLint i, err = EGL_SUCCESS; + EGLint attr = EGL_NONE; + EGLint val = EGL_NONE; if (!attrib_list) return EGL_SUCCESS; - if (dpy->Extensions.NOK_texture_from_pixmap) + if (disp->Extensions.NOK_texture_from_pixmap) texture_type |= EGL_PIXMAP_BIT; for (i = 0; attrib_list[i] != EGL_NONE; i++) { - EGLint attr = attrib_list[i++]; - EGLint val = attrib_list[i]; + attr = attrib_list[i++]; + val = attrib_list[i]; switch (attr) { - /* common (except for screen surfaces) attributes */ - case EGL_VG_COLORSPACE: - if (type == EGL_SCREEN_BIT_MESA) { + /* common attributes */ + case EGL_GL_COLORSPACE_KHR: + if (!disp->Extensions.KHR_gl_colorspace) { err = EGL_BAD_ATTRIBUTE; break; } + switch (val) { + case EGL_GL_COLORSPACE_SRGB_KHR: + case EGL_GL_COLORSPACE_LINEAR_KHR: + break; + default: + err = EGL_BAD_ATTRIBUTE; + } + if (err != EGL_SUCCESS) + break; + surf->GLColorspace = val; + break; + case EGL_SMPTE2086_DISPLAY_PRIMARY_RX_EXT: + if (!disp->Extensions.EXT_surface_SMPTE2086_metadata) { + err = EGL_BAD_ATTRIBUTE; + break; + } + surf->HdrMetadata.display_primary_r.x = val; + break; + case EGL_SMPTE2086_DISPLAY_PRIMARY_RY_EXT: + if (!disp->Extensions.EXT_surface_SMPTE2086_metadata) { + err = EGL_BAD_ATTRIBUTE; + break; + } + surf->HdrMetadata.display_primary_r.y = val; + break; + case EGL_SMPTE2086_DISPLAY_PRIMARY_GX_EXT: + if (!disp->Extensions.EXT_surface_SMPTE2086_metadata) { + err = EGL_BAD_ATTRIBUTE; + break; + } + surf->HdrMetadata.display_primary_g.x = val; + break; + case EGL_SMPTE2086_DISPLAY_PRIMARY_GY_EXT: + if (!disp->Extensions.EXT_surface_SMPTE2086_metadata) { + err = EGL_BAD_ATTRIBUTE; + break; + } + surf->HdrMetadata.display_primary_g.y = val; + break; + case EGL_SMPTE2086_DISPLAY_PRIMARY_BX_EXT: + if (!disp->Extensions.EXT_surface_SMPTE2086_metadata) { + err = EGL_BAD_ATTRIBUTE; + break; + } + surf->HdrMetadata.display_primary_b.x = val; + break; + case EGL_SMPTE2086_DISPLAY_PRIMARY_BY_EXT: + if (!disp->Extensions.EXT_surface_SMPTE2086_metadata) { + err = EGL_BAD_ATTRIBUTE; + break; + } + surf->HdrMetadata.display_primary_b.y = val; + break; + case EGL_SMPTE2086_WHITE_POINT_X_EXT: + if (!disp->Extensions.EXT_surface_SMPTE2086_metadata) { + err = EGL_BAD_ATTRIBUTE; + break; + } + surf->HdrMetadata.white_point.x = val; + break; + case EGL_SMPTE2086_WHITE_POINT_Y_EXT: + if (!disp->Extensions.EXT_surface_SMPTE2086_metadata) { + err = EGL_BAD_ATTRIBUTE; + break; + } + surf->HdrMetadata.white_point.y = val; + break; + case EGL_SMPTE2086_MAX_LUMINANCE_EXT: + if (!disp->Extensions.EXT_surface_SMPTE2086_metadata) { + err = EGL_BAD_ATTRIBUTE; + break; + } + surf->HdrMetadata.max_luminance = val; + break; + case EGL_SMPTE2086_MIN_LUMINANCE_EXT: + if (!disp->Extensions.EXT_surface_SMPTE2086_metadata) { + err = EGL_BAD_ATTRIBUTE; + break; + } + surf->HdrMetadata.min_luminance = val; + break; + case EGL_CTA861_3_MAX_CONTENT_LIGHT_LEVEL_EXT: + if (!disp->Extensions.EXT_surface_CTA861_3_metadata) { + err = EGL_BAD_ATTRIBUTE; + break; + } + surf->HdrMetadata.max_cll = val; + break; + case EGL_CTA861_3_MAX_FRAME_AVERAGE_LEVEL_EXT: + if (!disp->Extensions.EXT_surface_CTA861_3_metadata) { + err = EGL_BAD_ATTRIBUTE; + break; + } + surf->HdrMetadata.max_fall = val; + break; + case EGL_VG_COLORSPACE: switch (val) { case EGL_VG_COLORSPACE_sRGB: case EGL_VG_COLORSPACE_LINEAR: @@ -71,10 +186,6 @@ _eglParseSurfaceAttribList(_EGLSurface *surf, const EGLint *attrib_list) surf->VGColorspace = val; break; case EGL_VG_ALPHA_FORMAT: - if (type == EGL_SCREEN_BIT_MESA) { - err = EGL_BAD_ATTRIBUTE; - break; - } switch (val) { case EGL_VG_ALPHA_FORMAT_NONPRE: case EGL_VG_ALPHA_FORMAT_PRE: @@ -97,11 +208,29 @@ _eglParseSurfaceAttribList(_EGLSurface *surf, const EGLint *attrib_list) err = EGL_BAD_ATTRIBUTE; break; } - surf->RenderBuffer = val; + 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 (!disp->Extensions.NV_post_sub_buffer || + type != EGL_WINDOW_BIT) { + err = EGL_BAD_ATTRIBUTE; + break; + } + if (val != EGL_TRUE && val != EGL_FALSE) { + err = EGL_BAD_PARAMETER; + break; + } + surf->PostSubBufferSupportedNV = val; break; /* pbuffer surface attributes */ case EGL_WIDTH: - if (type != EGL_PBUFFER_BIT && type != EGL_SCREEN_BIT_MESA) { + if (type != EGL_PBUFFER_BIT) { err = EGL_BAD_ATTRIBUTE; break; } @@ -112,7 +241,7 @@ _eglParseSurfaceAttribList(_EGLSurface *surf, const EGLint *attrib_list) surf->Width = val; break; case EGL_HEIGHT: - if (type != EGL_PBUFFER_BIT && type != EGL_SCREEN_BIT_MESA) { + if (type != EGL_PBUFFER_BIT) { err = EGL_BAD_ATTRIBUTE; break; } @@ -129,11 +258,13 @@ _eglParseSurfaceAttribList(_EGLSurface *surf, const EGLint *attrib_list) } surf->LargestPbuffer = !!val; break; + /* for eglBindTexImage */ case EGL_TEXTURE_FORMAT: if (!(type & texture_type)) { err = EGL_BAD_ATTRIBUTE; break; } + switch (val) { case EGL_TEXTURE_RGB: case EGL_TEXTURE_RGBA: @@ -152,6 +283,7 @@ _eglParseSurfaceAttribList(_EGLSurface *surf, const EGLint *attrib_list) err = EGL_BAD_ATTRIBUTE; break; } + switch (val) { case EGL_TEXTURE_2D: case EGL_NO_TEXTURE: @@ -177,12 +309,21 @@ _eglParseSurfaceAttribList(_EGLSurface *surf, const EGLint *attrib_list) break; } - if (err != EGL_SUCCESS) { - _eglLog(_EGL_WARNING, "bad surface attribute 0x%04x", attr); + if (err != EGL_SUCCESS) break; + } + + if (err == EGL_SUCCESS && type == EGL_PBUFFER_BIT) { + if ((surf->TextureTarget == EGL_NO_TEXTURE && surf->TextureFormat != EGL_NO_TEXTURE) || + (surf->TextureFormat == EGL_NO_TEXTURE && surf->TextureTarget != EGL_NO_TEXTURE)) { + attr = surf->TextureTarget == EGL_NO_TEXTURE ? EGL_TEXTURE_TARGET : EGL_TEXTURE_FORMAT; + err = EGL_BAD_MATCH; } } + if (err != EGL_SUCCESS) + _eglLog(_EGL_WARNING, "bad surface attribute 0x%04x", attr); + return err; } @@ -192,16 +333,23 @@ _eglParseSurfaceAttribList(_EGLSurface *surf, const EGLint *attrib_list) * \return EGL_TRUE if no errors, EGL_FALSE otherwise. */ EGLBoolean -_eglInitSurface(_EGLSurface *surf, _EGLDisplay *dpy, EGLint type, - _EGLConfig *conf, const EGLint *attrib_list) +_eglInitSurface(_EGLSurface *surf, _EGLDisplay *disp, EGLint type, + _EGLConfig *conf, const EGLint *attrib_list, + void *native_surface) { const char *func; EGLint renderBuffer = EGL_BACK_BUFFER; + EGLint swapBehavior = EGL_BUFFER_DESTROYED; EGLint err; + /* Swap behavior can be preserved only if config supports this. */ + if (conf->SurfaceType & EGL_SWAP_BEHAVIOR_PRESERVED_BIT) + swapBehavior = EGL_BUFFER_PRESERVED; + switch (type) { case EGL_WINDOW_BIT: func = "eglCreateWindowSurface"; + swapBehavior = EGL_BUFFER_DESTROYED; break; case EGL_PIXMAP_BIT: func = "eglCreatePixmapSurface"; @@ -210,25 +358,19 @@ _eglInitSurface(_EGLSurface *surf, _EGLDisplay *dpy, EGLint type, case EGL_PBUFFER_BIT: func = "eglCreatePBufferSurface"; break; - case EGL_SCREEN_BIT_MESA: - func = "eglCreateScreenSurface"; - renderBuffer = EGL_SINGLE_BUFFER; /* XXX correct? */ - break; default: _eglLog(_EGL_WARNING, "Bad type in _eglInitSurface"); return EGL_FALSE; } - if ((GET_CONFIG_ATTRIB(conf, EGL_SURFACE_TYPE) & type) == 0) { + if ((conf->SurfaceType & type) == 0) /* The config can't be used to create a surface of this type */ - _eglError(EGL_BAD_CONFIG, func); - return EGL_FALSE; - } + return _eglError(EGL_BAD_MATCH, func); - memset(surf, 0, sizeof(_EGLSurface)); - surf->Resource.Display = dpy; + _eglInitResource(&surf->Resource, sizeof(*surf), disp); surf->Type = type; surf->Config = conf; + surf->Lost = EGL_FALSE; surf->Width = 0; surf->Height = 0; @@ -236,49 +378,58 @@ _eglInitSurface(_EGLSurface *surf, _EGLDisplay *dpy, EGLint type, surf->TextureTarget = EGL_NO_TEXTURE; surf->MipmapTexture = EGL_FALSE; surf->LargestPbuffer = EGL_FALSE; - surf->RenderBuffer = renderBuffer; + surf->RequestedRenderBuffer = renderBuffer; + surf->ActiveRenderBuffer = renderBuffer; surf->VGAlphaFormat = EGL_VG_ALPHA_FORMAT_NONPRE; surf->VGColorspace = EGL_VG_COLORSPACE_sRGB; + surf->GLColorspace = EGL_GL_COLORSPACE_LINEAR_KHR; surf->MipmapLevel = 0; surf->MultisampleResolve = EGL_MULTISAMPLE_RESOLVE_DEFAULT; - surf->SwapBehavior = EGL_BUFFER_DESTROYED; + surf->SwapBehavior = swapBehavior; surf->HorizontalResolution = EGL_UNKNOWN; surf->VerticalResolution = EGL_UNKNOWN; surf->AspectRatio = EGL_UNKNOWN; + surf->PostSubBufferSupportedNV = EGL_FALSE; + surf->SetDamageRegionCalled = EGL_FALSE; + surf->BufferAgeRead = EGL_FALSE; + /* the default swap interval is 1 */ - _eglClampSwapInterval(surf, 1); + surf->SwapInterval = 1; + + surf->HdrMetadata.display_primary_r.x = EGL_DONT_CARE; + surf->HdrMetadata.display_primary_r.y = EGL_DONT_CARE; + surf->HdrMetadata.display_primary_g.x = EGL_DONT_CARE; + surf->HdrMetadata.display_primary_g.y = EGL_DONT_CARE; + surf->HdrMetadata.display_primary_b.x = EGL_DONT_CARE; + surf->HdrMetadata.display_primary_b.y = EGL_DONT_CARE; + surf->HdrMetadata.white_point.x = EGL_DONT_CARE; + surf->HdrMetadata.white_point.y = EGL_DONT_CARE; + surf->HdrMetadata.max_luminance = EGL_DONT_CARE; + surf->HdrMetadata.min_luminance = EGL_DONT_CARE; + surf->HdrMetadata.max_cll = EGL_DONT_CARE; + surf->HdrMetadata.max_fall = EGL_DONT_CARE; err = _eglParseSurfaceAttribList(surf, attrib_list); if (err != EGL_SUCCESS) return _eglError(err, func); - return EGL_TRUE; -} + /* if EGL_LARGEST_PBUFFER in use, clamp width and height */ + if (surf->LargestPbuffer) { + surf->Width = MIN2(surf->Width, _EGL_MAX_PBUFFER_WIDTH); + surf->Height = MIN2(surf->Height, _EGL_MAX_PBUFFER_HEIGHT); + } + surf->NativeSurface = native_surface; -EGLBoolean -_eglSwapBuffers(_EGLDriver *drv, _EGLDisplay *dpy, _EGLSurface *surf) -{ - /* Drivers have to do the actual buffer swap. */ return EGL_TRUE; } EGLBoolean -_eglCopyBuffers(_EGLDriver *drv, _EGLDisplay *dpy, _EGLSurface *surf, - EGLNativePixmapType target) -{ - /* copy surface to native pixmap */ - /* All implementation burdon for this is in the device driver */ - return EGL_FALSE; -} - - -EGLBoolean -_eglQuerySurface(_EGLDriver *drv, _EGLDisplay *dpy, _EGLSurface *surface, +_eglQuerySurface(_EGLDisplay *disp, _EGLSurface *surface, EGLint attribute, EGLint *value) { switch (attribute) { @@ -289,10 +440,11 @@ _eglQuerySurface(_EGLDriver *drv, _EGLDisplay *dpy, _EGLSurface *surface, *value = surface->Height; break; case EGL_CONFIG_ID: - *value = GET_CONFIG_ATTRIB(surface->Config, EGL_CONFIG_ID); + *value = surface->Config->ConfigID; break; case EGL_LARGEST_PBUFFER: - *value = surface->LargestPbuffer; + if (surface->Type == EGL_PBUFFER_BIT) + *value = surface->LargestPbuffer; break; case EGL_TEXTURE_FORMAT: /* texture attributes: only for pbuffers, no error otherwise */ @@ -315,7 +467,35 @@ _eglQuerySurface(_EGLDriver *drv, _EGLDisplay *dpy, _EGLSurface *surface, *value = surface->SwapBehavior; break; case EGL_RENDER_BUFFER: - *value = surface->RenderBuffer; + /* 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. + * + * 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. + */ + switch (surface->Type) { + default: + unreachable("bad EGLSurface type"); + case EGL_WINDOW_BIT: + *value = surface->RequestedRenderBuffer; + break; + case EGL_PBUFFER_BIT: + *value = EGL_BACK_BUFFER; + break; + case EGL_PIXMAP_BIT: + *value = EGL_SINGLE_BUFFER; + break; + } break; case EGL_PIXEL_ASPECT_RATIO: *value = surface->AspectRatio; @@ -335,74 +515,98 @@ _eglQuerySurface(_EGLDriver *drv, _EGLDisplay *dpy, _EGLSurface *surface, case EGL_VG_COLORSPACE: *value = surface->VGColorspace; break; + case EGL_GL_COLORSPACE_KHR: + if (!disp->Extensions.KHR_gl_colorspace) + return _eglError(EGL_BAD_ATTRIBUTE, "eglQuerySurface"); + + *value = surface->GLColorspace; + break; + case EGL_POST_SUB_BUFFER_SUPPORTED_NV: + *value = surface->PostSubBufferSupportedNV; + break; + case EGL_BUFFER_AGE_EXT: + /* Both EXT_buffer_age and KHR_partial_update accept EGL_BUFFER_AGE_EXT. + * To be precise, the KHR one accepts EGL_BUFFER_AGE_KHR which is an + * alias with the same numeric value. + */ + if (!disp->Extensions.EXT_buffer_age && + !disp->Extensions.KHR_partial_update) + return _eglError(EGL_BAD_ATTRIBUTE, "eglQuerySurface"); + + _EGLContext *ctx = _eglGetCurrentContext(); + const _EGLDriver *drv = disp->Driver; + EGLint result = drv->QueryBufferAge(drv, disp, surface); + /* error happened */ + if (result < 0) + return EGL_FALSE; + if (_eglGetContextHandle(ctx) == EGL_NO_CONTEXT || + ctx->DrawSurface != surface) + return _eglError(EGL_BAD_SURFACE, "eglQuerySurface"); + + *value = result; + surface->BufferAgeRead = EGL_TRUE; + break; + case EGL_SMPTE2086_DISPLAY_PRIMARY_RX_EXT: + *value = surface->HdrMetadata.display_primary_r.x; + break; + case EGL_SMPTE2086_DISPLAY_PRIMARY_RY_EXT: + *value = surface->HdrMetadata.display_primary_r.y; + break; + case EGL_SMPTE2086_DISPLAY_PRIMARY_GX_EXT: + *value = surface->HdrMetadata.display_primary_g.x; + break; + case EGL_SMPTE2086_DISPLAY_PRIMARY_GY_EXT: + *value = surface->HdrMetadata.display_primary_g.y; + break; + case EGL_SMPTE2086_DISPLAY_PRIMARY_BX_EXT: + *value = surface->HdrMetadata.display_primary_b.x; + break; + case EGL_SMPTE2086_DISPLAY_PRIMARY_BY_EXT: + *value = surface->HdrMetadata.display_primary_b.y; + break; + case EGL_SMPTE2086_WHITE_POINT_X_EXT: + *value = surface->HdrMetadata.white_point.x; + break; + case EGL_SMPTE2086_WHITE_POINT_Y_EXT: + *value = surface->HdrMetadata.white_point.y; + break; + case EGL_SMPTE2086_MAX_LUMINANCE_EXT: + *value = surface->HdrMetadata.max_luminance; + break; + case EGL_SMPTE2086_MIN_LUMINANCE_EXT: + *value = surface->HdrMetadata.min_luminance; + break; + case EGL_CTA861_3_MAX_CONTENT_LIGHT_LEVEL_EXT: + *value = surface->HdrMetadata.max_cll; + break; + case EGL_CTA861_3_MAX_FRAME_AVERAGE_LEVEL_EXT: + *value = surface->HdrMetadata.max_fall; + break; default: - _eglError(EGL_BAD_ATTRIBUTE, "eglQuerySurface"); - return EGL_FALSE; + return _eglError(EGL_BAD_ATTRIBUTE, "eglQuerySurface"); } return EGL_TRUE; } -/** - * Drivers should do a proper implementation. - */ -_EGLSurface * -_eglCreateWindowSurface(_EGLDriver *drv, _EGLDisplay *dpy, _EGLConfig *conf, - EGLNativeWindowType window, const EGLint *attrib_list) -{ - return NULL; -} - - -/** - * Drivers should do a proper implementation. - */ -_EGLSurface * -_eglCreatePixmapSurface(_EGLDriver *drv, _EGLDisplay *dpy, _EGLConfig *conf, - EGLNativePixmapType pixmap, const EGLint *attrib_list) -{ - return NULL; -} - - -/** - * Drivers should do a proper implementation. - */ -_EGLSurface * -_eglCreatePbufferSurface(_EGLDriver *drv, _EGLDisplay *dpy, _EGLConfig *conf, - const EGLint *attrib_list) -{ - return NULL; -} - - -/** - * Default fallback routine - drivers should usually override this. - */ -EGLBoolean -_eglDestroySurface(_EGLDriver *drv, _EGLDisplay *dpy, _EGLSurface *surf) -{ - if (!_eglIsSurfaceBound(surf)) - free(surf); - return EGL_TRUE; -} - - /** * Default fallback routine - drivers might override this. */ EGLBoolean -_eglSurfaceAttrib(_EGLDriver *drv, _EGLDisplay *dpy, _EGLSurface *surface, +_eglSurfaceAttrib(const _EGLDriver *drv, _EGLDisplay *disp, _EGLSurface *surface, EGLint attribute, EGLint value) { EGLint confval; EGLint err = EGL_SUCCESS; + EGLint all_es_bits = EGL_OPENGL_ES_BIT | + EGL_OPENGL_ES2_BIT | + EGL_OPENGL_ES3_BIT_KHR; switch (attribute) { case EGL_MIPMAP_LEVEL: - confval = GET_CONFIG_ATTRIB(surface->Config, EGL_RENDERABLE_TYPE); - if (!(confval & (EGL_OPENGL_ES_BIT | EGL_OPENGL_ES2_BIT))) { + confval = surface->Config->RenderableType; + if (!(confval & all_es_bits)) { err = EGL_BAD_PARAMETER; break; } @@ -413,7 +617,7 @@ _eglSurfaceAttrib(_EGLDriver *drv, _EGLDisplay *dpy, _EGLSurface *surface, case EGL_MULTISAMPLE_RESOLVE_DEFAULT: break; case EGL_MULTISAMPLE_RESOLVE_BOX: - confval = GET_CONFIG_ATTRIB(surface->Config, EGL_SURFACE_TYPE); + confval = surface->Config->SurfaceType; if (!(confval & EGL_MULTISAMPLE_RESOLVE_BOX_BIT)) err = EGL_BAD_MATCH; break; @@ -425,12 +629,37 @@ _eglSurfaceAttrib(_EGLDriver *drv, _EGLDisplay *dpy, _EGLSurface *surface, break; surface->MultisampleResolve = value; break; + case EGL_RENDER_BUFFER: + if (!disp->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: break; case EGL_BUFFER_PRESERVED: - confval = GET_CONFIG_ATTRIB(surface->Config, EGL_SURFACE_TYPE); + confval = surface->Config->SurfaceType; if (!(confval & EGL_SWAP_BEHAVIOR_PRESERVED_BIT)) err = EGL_BAD_MATCH; break; @@ -442,6 +671,42 @@ _eglSurfaceAttrib(_EGLDriver *drv, _EGLDisplay *dpy, _EGLSurface *surface, break; surface->SwapBehavior = value; break; + case EGL_SMPTE2086_DISPLAY_PRIMARY_RX_EXT: + surface->HdrMetadata.display_primary_r.x = value; + break; + case EGL_SMPTE2086_DISPLAY_PRIMARY_RY_EXT: + surface->HdrMetadata.display_primary_r.y = value; + break; + case EGL_SMPTE2086_DISPLAY_PRIMARY_GX_EXT: + surface->HdrMetadata.display_primary_g.x = value; + break; + case EGL_SMPTE2086_DISPLAY_PRIMARY_GY_EXT: + surface->HdrMetadata.display_primary_g.y = value; + break; + case EGL_SMPTE2086_DISPLAY_PRIMARY_BX_EXT: + surface->HdrMetadata.display_primary_b.x = value; + break; + case EGL_SMPTE2086_DISPLAY_PRIMARY_BY_EXT: + surface->HdrMetadata.display_primary_b.y = value; + break; + case EGL_SMPTE2086_WHITE_POINT_X_EXT: + surface->HdrMetadata.white_point.x = value; + break; + case EGL_SMPTE2086_WHITE_POINT_Y_EXT: + surface->HdrMetadata.white_point.y = value; + break; + case EGL_SMPTE2086_MAX_LUMINANCE_EXT: + surface->HdrMetadata.max_luminance = value; + break; + case EGL_SMPTE2086_MIN_LUMINANCE_EXT: + surface->HdrMetadata.min_luminance = value; + break; + case EGL_CTA861_3_MAX_CONTENT_LIGHT_LEVEL_EXT: + surface->HdrMetadata.max_cll = value; + break; + case EGL_CTA861_3_MAX_FRAME_AVERAGE_LEVEL_EXT: + surface->HdrMetadata.max_fall = value; + break; default: err = EGL_BAD_ATTRIBUTE; break; @@ -454,8 +719,7 @@ _eglSurfaceAttrib(_EGLDriver *drv, _EGLDisplay *dpy, _EGLSurface *surface, EGLBoolean -_eglBindTexImage(_EGLDriver *drv, _EGLDisplay *dpy, _EGLSurface *surface, - EGLint buffer) +_eglBindTexImage(_EGLDisplay *disp, _EGLSurface *surface, EGLint buffer) { EGLint texture_type = EGL_PBUFFER_BIT; @@ -463,94 +727,79 @@ _eglBindTexImage(_EGLDriver *drv, _EGLDisplay *dpy, _EGLSurface *surface, * Drivers must implement the real stuff. */ - if (dpy->Extensions.NOK_texture_from_pixmap) + if (disp->Extensions.NOK_texture_from_pixmap) texture_type |= EGL_PIXMAP_BIT; - if (!(surface->Type & texture_type)) { - _eglError(EGL_BAD_SURFACE, "eglBindTexImage"); - return EGL_FALSE; - } + if (!(surface->Type & texture_type)) + return _eglError(EGL_BAD_SURFACE, "eglBindTexImage"); - if (surface->TextureFormat == EGL_NO_TEXTURE) { - _eglError(EGL_BAD_MATCH, "eglBindTexImage"); - return EGL_FALSE; - } + if (surface->TextureFormat == EGL_NO_TEXTURE) + return _eglError(EGL_BAD_MATCH, "eglBindTexImage"); - if (surface->TextureTarget == EGL_NO_TEXTURE) { - _eglError(EGL_BAD_MATCH, "eglBindTexImage"); - return EGL_FALSE; - } + if (surface->TextureTarget == EGL_NO_TEXTURE) + return _eglError(EGL_BAD_MATCH, "eglBindTexImage"); - if (buffer != EGL_BACK_BUFFER) { - _eglError(EGL_BAD_PARAMETER, "eglBindTexImage"); - return EGL_FALSE; - } + if (buffer != EGL_BACK_BUFFER) + return _eglError(EGL_BAD_PARAMETER, "eglBindTexImage"); surface->BoundToTexture = EGL_TRUE; return EGL_TRUE; } - EGLBoolean -_eglReleaseTexImage(_EGLDriver *drv, _EGLDisplay *dpy, _EGLSurface *surface, - EGLint buffer) +_eglReleaseTexImage(_EGLDisplay *disp, _EGLSurface *surf, EGLint buffer) { /* Just do basic error checking and return success/fail. * Drivers must implement the real stuff. */ - if (surface->Type != EGL_PBUFFER_BIT) { - _eglError(EGL_BAD_SURFACE, "eglBindTexImage"); - return EGL_FALSE; - } + EGLint texture_type = EGL_PBUFFER_BIT; - if (surface->TextureFormat == EGL_NO_TEXTURE) { - _eglError(EGL_BAD_MATCH, "eglBindTexImage"); - return EGL_FALSE; - } + if (surf == EGL_NO_SURFACE) + return _eglError(EGL_BAD_SURFACE, "eglReleaseTexImage"); - if (buffer != EGL_BACK_BUFFER) { - _eglError(EGL_BAD_PARAMETER, "eglReleaseTexImage"); - return EGL_FALSE; + if (!surf->BoundToTexture) + { + /* Not an error, simply nothing to do */ + return EGL_TRUE; } - if (!surface->BoundToTexture) { - _eglError(EGL_BAD_SURFACE, "eglReleaseTexImage"); - return EGL_FALSE; - } + if (surf->TextureFormat == EGL_NO_TEXTURE) + return _eglError(EGL_BAD_MATCH, "eglReleaseTexImage"); + + if (buffer != EGL_BACK_BUFFER) + return _eglError(EGL_BAD_PARAMETER, "eglReleaseTexImage"); - surface->BoundToTexture = EGL_FALSE; + if (disp->Extensions.NOK_texture_from_pixmap) + texture_type |= EGL_PIXMAP_BIT; + + if (!(surf->Type & texture_type)) + return _eglError(EGL_BAD_SURFACE, "eglReleaseTexImage"); + + surf->BoundToTexture = EGL_FALSE; return EGL_TRUE; } EGLBoolean -_eglSwapInterval(_EGLDriver *drv, _EGLDisplay *dpy, _EGLSurface *surf, - EGLint interval) +_eglSwapInterval(_EGLDisplay *disp, _EGLSurface *surf, EGLint interval) { - _eglClampSwapInterval(surf, interval); return EGL_TRUE; } - -#ifdef EGL_VERSION_1_2 - -/** - * Example function - drivers should do a proper implementation. - */ -_EGLSurface * -_eglCreatePbufferFromClientBuffer(_EGLDriver *drv, _EGLDisplay *dpy, - EGLenum buftype, EGLClientBuffer buffer, - _EGLConfig *conf, const EGLint *attrib_list) +EGLBoolean +_eglSurfaceHasMutableRenderBuffer(_EGLSurface *surf) { - if (buftype != EGL_OPENVG_IMAGE) { - _eglError(EGL_BAD_PARAMETER, "eglCreatePbufferFromClientBuffer"); - return NULL; - } - - return NULL; + return surf->Type == EGL_WINDOW_BIT && + surf->Config && + (surf->Config->SurfaceType & EGL_MUTABLE_RENDER_BUFFER_BIT_KHR); } -#endif /* EGL_VERSION_1_2 */ +EGLBoolean +_eglSurfaceInSharedBufferMode(_EGLSurface *surf) +{ + return _eglSurfaceHasMutableRenderBuffer(surf) && + surf->ActiveRenderBuffer == EGL_SINGLE_BUFFER; +}