| /************************************************************************** |
| * |
| * Copyright 2008 VMware, Inc. |
| * Copyright 2009-2010 Chia-I Wu <olvaffe@gmail.com> |
| * 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. |
| */ |
| |
| |
| #include <assert.h> |
| #include <stdlib.h> |
| #include <string.h> |
| #include "egldefines.h" |
| #include "egldisplay.h" |
| #include "egldriver.h" |
| #include "eglcontext.h" |
| #include "eglconfig.h" |
| #include "eglcurrent.h" |
| #include "egllog.h" |
| #include "eglsurface.h" |
| |
| #include "util/macros.h" |
| |
| /** |
| * Parse the list of surface attributes and return the proper error code. |
| */ |
| static EGLint |
| _eglParseSurfaceAttribList(_EGLSurface *surf, const EGLint *attrib_list) |
| { |
| _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 (disp->Extensions.NOK_texture_from_pixmap) |
| texture_type |= EGL_PIXMAP_BIT; |
| |
| for (i = 0; attrib_list[i] != EGL_NONE; i++) { |
| attr = attrib_list[i++]; |
| val = attrib_list[i]; |
| |
| switch (attr) { |
| /* 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: |
| break; |
| default: |
| err = EGL_BAD_ATTRIBUTE; |
| break; |
| } |
| if (err != EGL_SUCCESS) |
| break; |
| surf->VGColorspace = val; |
| break; |
| case EGL_VG_ALPHA_FORMAT: |
| switch (val) { |
| case EGL_VG_ALPHA_FORMAT_NONPRE: |
| case EGL_VG_ALPHA_FORMAT_PRE: |
| break; |
| default: |
| err = EGL_BAD_ATTRIBUTE; |
| break; |
| } |
| if (err != EGL_SUCCESS) |
| break; |
| surf->VGAlphaFormat = val; |
| break; |
| /* window surface attributes */ |
| case EGL_RENDER_BUFFER: |
| if (type != EGL_WINDOW_BIT) { |
| err = EGL_BAD_ATTRIBUTE; |
| break; |
| } |
| if (val != EGL_BACK_BUFFER && val != EGL_SINGLE_BUFFER) { |
| err = EGL_BAD_ATTRIBUTE; |
| 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 (!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) { |
| err = EGL_BAD_ATTRIBUTE; |
| break; |
| } |
| if (val < 0) { |
| err = EGL_BAD_PARAMETER; |
| break; |
| } |
| surf->Width = val; |
| break; |
| case EGL_HEIGHT: |
| if (type != EGL_PBUFFER_BIT) { |
| err = EGL_BAD_ATTRIBUTE; |
| break; |
| } |
| if (val < 0) { |
| err = EGL_BAD_PARAMETER; |
| break; |
| } |
| surf->Height = val; |
| break; |
| case EGL_LARGEST_PBUFFER: |
| if (type != EGL_PBUFFER_BIT) { |
| err = EGL_BAD_ATTRIBUTE; |
| break; |
| } |
| 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: |
| case EGL_NO_TEXTURE: |
| break; |
| default: |
| err = EGL_BAD_ATTRIBUTE; |
| break; |
| } |
| if (err != EGL_SUCCESS) |
| break; |
| surf->TextureFormat = val; |
| break; |
| case EGL_TEXTURE_TARGET: |
| if (!(type & texture_type)) { |
| err = EGL_BAD_ATTRIBUTE; |
| break; |
| } |
| |
| switch (val) { |
| case EGL_TEXTURE_2D: |
| case EGL_NO_TEXTURE: |
| break; |
| default: |
| err = EGL_BAD_ATTRIBUTE; |
| break; |
| } |
| if (err != EGL_SUCCESS) |
| break; |
| surf->TextureTarget = val; |
| break; |
| case EGL_MIPMAP_TEXTURE: |
| if (!(type & texture_type)) { |
| err = EGL_BAD_ATTRIBUTE; |
| break; |
| } |
| surf->MipmapTexture = !!val; |
| break; |
| /* no pixmap surface specific attributes */ |
| default: |
| err = EGL_BAD_ATTRIBUTE; |
| break; |
| } |
| |
| 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; |
| } |
| |
| |
| /** |
| * Do error check on parameters and initialize the given _EGLSurface object. |
| * \return EGL_TRUE if no errors, EGL_FALSE otherwise. |
| */ |
| EGLBoolean |
| _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"; |
| renderBuffer = EGL_SINGLE_BUFFER; |
| break; |
| case EGL_PBUFFER_BIT: |
| func = "eglCreatePBufferSurface"; |
| break; |
| default: |
| _eglLog(_EGL_WARNING, "Bad type in _eglInitSurface"); |
| return EGL_FALSE; |
| } |
| |
| if ((conf->SurfaceType & type) == 0) |
| /* The config can't be used to create a surface of this type */ |
| return _eglError(EGL_BAD_MATCH, func); |
| |
| _eglInitResource(&surf->Resource, sizeof(*surf), disp); |
| surf->Type = type; |
| surf->Config = conf; |
| surf->Lost = EGL_FALSE; |
| |
| surf->Width = 0; |
| surf->Height = 0; |
| surf->TextureFormat = EGL_NO_TEXTURE; |
| surf->TextureTarget = EGL_NO_TEXTURE; |
| surf->MipmapTexture = EGL_FALSE; |
| surf->LargestPbuffer = EGL_FALSE; |
| 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 = 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 */ |
| 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); |
| |
| /* 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; |
| |
| return EGL_TRUE; |
| } |
| |
| |
| EGLBoolean |
| _eglQuerySurface(_EGLDisplay *disp, _EGLSurface *surface, |
| EGLint attribute, EGLint *value) |
| { |
| switch (attribute) { |
| case EGL_WIDTH: |
| *value = surface->Width; |
| break; |
| case EGL_HEIGHT: |
| *value = surface->Height; |
| break; |
| case EGL_CONFIG_ID: |
| *value = surface->Config->ConfigID; |
| break; |
| case EGL_LARGEST_PBUFFER: |
| if (surface->Type == EGL_PBUFFER_BIT) |
| *value = surface->LargestPbuffer; |
| break; |
| case EGL_TEXTURE_FORMAT: |
| /* texture attributes: only for pbuffers, no error otherwise */ |
| if (surface->Type == EGL_PBUFFER_BIT) |
| *value = surface->TextureFormat; |
| break; |
| case EGL_TEXTURE_TARGET: |
| if (surface->Type == EGL_PBUFFER_BIT) |
| *value = surface->TextureTarget; |
| break; |
| case EGL_MIPMAP_TEXTURE: |
| if (surface->Type == EGL_PBUFFER_BIT) |
| *value = surface->MipmapTexture; |
| break; |
| case EGL_MIPMAP_LEVEL: |
| if (surface->Type == EGL_PBUFFER_BIT) |
| *value = surface->MipmapLevel; |
| break; |
| case EGL_SWAP_BEHAVIOR: |
| *value = surface->SwapBehavior; |
| break; |
| case EGL_RENDER_BUFFER: |
| /* 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; |
| break; |
| case EGL_HORIZONTAL_RESOLUTION: |
| *value = surface->HorizontalResolution; |
| break; |
| case EGL_VERTICAL_RESOLUTION: |
| *value = surface->VerticalResolution; |
| break; |
| case EGL_MULTISAMPLE_RESOLVE: |
| *value = surface->MultisampleResolve; |
| break; |
| case EGL_VG_ALPHA_FORMAT: |
| *value = surface->VGAlphaFormat; |
| break; |
| 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: |
| return _eglError(EGL_BAD_ATTRIBUTE, "eglQuerySurface"); |
| } |
| |
| return EGL_TRUE; |
| } |
| |
| |
| /** |
| * Default fallback routine - drivers might override this. |
| */ |
| EGLBoolean |
| _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 = surface->Config->RenderableType; |
| if (!(confval & all_es_bits)) { |
| err = EGL_BAD_PARAMETER; |
| break; |
| } |
| surface->MipmapLevel = value; |
| break; |
| case EGL_MULTISAMPLE_RESOLVE: |
| switch (value) { |
| case EGL_MULTISAMPLE_RESOLVE_DEFAULT: |
| break; |
| case EGL_MULTISAMPLE_RESOLVE_BOX: |
| confval = surface->Config->SurfaceType; |
| if (!(confval & EGL_MULTISAMPLE_RESOLVE_BOX_BIT)) |
| err = EGL_BAD_MATCH; |
| break; |
| default: |
| err = EGL_BAD_ATTRIBUTE; |
| break; |
| } |
| if (err != EGL_SUCCESS) |
| 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 = surface->Config->SurfaceType; |
| if (!(confval & EGL_SWAP_BEHAVIOR_PRESERVED_BIT)) |
| err = EGL_BAD_MATCH; |
| break; |
| default: |
| err = EGL_BAD_ATTRIBUTE; |
| break; |
| } |
| if (err != EGL_SUCCESS) |
| 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; |
| } |
| |
| if (err != EGL_SUCCESS) |
| return _eglError(err, "eglSurfaceAttrib"); |
| return EGL_TRUE; |
| } |
| |
| |
| EGLBoolean |
| _eglBindTexImage(const _EGLDriver *drv, _EGLDisplay *disp, _EGLSurface *surface, |
| EGLint buffer) |
| { |
| EGLint texture_type = EGL_PBUFFER_BIT; |
| |
| /* Just do basic error checking and return success/fail. |
| * Drivers must implement the real stuff. |
| */ |
| |
| if (disp->Extensions.NOK_texture_from_pixmap) |
| texture_type |= EGL_PIXMAP_BIT; |
| |
| if (!(surface->Type & texture_type)) |
| return _eglError(EGL_BAD_SURFACE, "eglBindTexImage"); |
| |
| if (surface->TextureFormat == EGL_NO_TEXTURE) |
| return _eglError(EGL_BAD_MATCH, "eglBindTexImage"); |
| |
| if (surface->TextureTarget == EGL_NO_TEXTURE) |
| return _eglError(EGL_BAD_MATCH, "eglBindTexImage"); |
| |
| if (buffer != EGL_BACK_BUFFER) |
| return _eglError(EGL_BAD_PARAMETER, "eglBindTexImage"); |
| |
| surface->BoundToTexture = EGL_TRUE; |
| |
| return EGL_TRUE; |
| } |
| |
| EGLBoolean |
| _eglReleaseTexImage(const _EGLDriver *drv, _EGLDisplay *disp, _EGLSurface *surf, |
| EGLint buffer) |
| { |
| /* Just do basic error checking and return success/fail. |
| * Drivers must implement the real stuff. |
| */ |
| |
| EGLint texture_type = EGL_PBUFFER_BIT; |
| |
| if (surf == EGL_NO_SURFACE) |
| return _eglError(EGL_BAD_SURFACE, "eglReleaseTexImage"); |
| |
| if (!surf->BoundToTexture) |
| { |
| /* Not an error, simply nothing to do */ |
| return EGL_TRUE; |
| } |
| |
| if (surf->TextureFormat == EGL_NO_TEXTURE) |
| return _eglError(EGL_BAD_MATCH, "eglReleaseTexImage"); |
| |
| if (buffer != EGL_BACK_BUFFER) |
| return _eglError(EGL_BAD_PARAMETER, "eglReleaseTexImage"); |
| |
| 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(const _EGLDriver *drv, _EGLDisplay *disp, _EGLSurface *surf, |
| EGLint interval) |
| { |
| 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; |
| } |