eglconfig.c revision af69d88d
13464ebd5Sriastradh/************************************************************************** 23464ebd5Sriastradh * 3af69d88dSmrg * Copyright 2008 VMware, Inc. 43464ebd5Sriastradh * Copyright 2009-2010 Chia-I Wu <olvaffe@gmail.com> 53464ebd5Sriastradh * Copyright 2010-2011 LunarG, Inc. 63464ebd5Sriastradh * All Rights Reserved. 73464ebd5Sriastradh * 83464ebd5Sriastradh * Permission is hereby granted, free of charge, to any person obtaining a 93464ebd5Sriastradh * copy of this software and associated documentation files (the 103464ebd5Sriastradh * "Software"), to deal in the Software without restriction, including 113464ebd5Sriastradh * without limitation the rights to use, copy, modify, merge, publish, 123464ebd5Sriastradh * distribute, sub license, and/or sell copies of the Software, and to 133464ebd5Sriastradh * permit persons to whom the Software is furnished to do so, subject to 143464ebd5Sriastradh * the following conditions: 153464ebd5Sriastradh * 163464ebd5Sriastradh * The above copyright notice and this permission notice (including the 173464ebd5Sriastradh * next paragraph) shall be included in all copies or substantial portions 183464ebd5Sriastradh * of the Software. 193464ebd5Sriastradh * 203464ebd5Sriastradh * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 213464ebd5Sriastradh * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 223464ebd5Sriastradh * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 233464ebd5Sriastradh * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 243464ebd5Sriastradh * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 253464ebd5Sriastradh * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 263464ebd5Sriastradh * DEALINGS IN THE SOFTWARE. 273464ebd5Sriastradh * 283464ebd5Sriastradh **************************************************************************/ 293464ebd5Sriastradh 303464ebd5Sriastradh 314a49301eSmrg/** 324a49301eSmrg * EGL Configuration (pixel format) functions. 334a49301eSmrg */ 344a49301eSmrg 354a49301eSmrg 364a49301eSmrg#include <stdlib.h> 374a49301eSmrg#include <string.h> 384a49301eSmrg#include <assert.h> 394a49301eSmrg#include "eglconfig.h" 404a49301eSmrg#include "egldisplay.h" 41cdc920a0Smrg#include "eglcurrent.h" 424a49301eSmrg#include "egllog.h" 434a49301eSmrg 444a49301eSmrg 454a49301eSmrg#define MIN2(A, B) (((A) < (B)) ? (A) : (B)) 464a49301eSmrg 474a49301eSmrg 484a49301eSmrg/** 494a49301eSmrg * Init the given _EGLconfig to default values. 504a49301eSmrg * \param id the configuration's ID. 514a49301eSmrg * 524a49301eSmrg * Note that id must be positive for the config to be valid. 534a49301eSmrg * It is also recommended that when there are N configs, their 544a49301eSmrg * IDs are from 1 to N respectively. 554a49301eSmrg */ 564a49301eSmrgvoid 573464ebd5Sriastradh_eglInitConfig(_EGLConfig *conf, _EGLDisplay *dpy, EGLint id) 584a49301eSmrg{ 593464ebd5Sriastradh memset(conf, 0, sizeof(*conf)); 604a49301eSmrg 613464ebd5Sriastradh conf->Display = dpy; 62cdc920a0Smrg 634a49301eSmrg /* some attributes take non-zero default values */ 643464ebd5Sriastradh conf->ConfigID = id; 653464ebd5Sriastradh conf->ConfigCaveat = EGL_NONE; 663464ebd5Sriastradh conf->TransparentType = EGL_NONE; 673464ebd5Sriastradh conf->NativeVisualType = EGL_NONE; 683464ebd5Sriastradh conf->ColorBufferType = EGL_RGB_BUFFER; 694a49301eSmrg} 704a49301eSmrg 714a49301eSmrg 724a49301eSmrg/** 733464ebd5Sriastradh * Link a config to its display and return the handle of the link. 744a49301eSmrg * The handle can be passed to client directly. 754a49301eSmrg * 764a49301eSmrg * Note that we just save the ptr to the config (we don't copy the config). 774a49301eSmrg */ 783464ebd5SriastradhPUBLIC EGLConfig 793464ebd5Sriastradh_eglLinkConfig(_EGLConfig *conf) 804a49301eSmrg{ 813464ebd5Sriastradh _EGLDisplay *dpy = conf->Display; 824a49301eSmrg 834a49301eSmrg /* sanity check */ 843464ebd5Sriastradh assert(dpy && conf->ConfigID > 0); 854a49301eSmrg 863464ebd5Sriastradh if (!dpy->Configs) { 873464ebd5Sriastradh dpy->Configs = _eglCreateArray("Config", 16); 883464ebd5Sriastradh if (!dpy->Configs) 894a49301eSmrg return (EGLConfig) NULL; 904a49301eSmrg } 914a49301eSmrg 923464ebd5Sriastradh _eglAppendArray(dpy->Configs, (void *) conf); 934a49301eSmrg 944a49301eSmrg return (EGLConfig) conf; 954a49301eSmrg} 964a49301eSmrg 974a49301eSmrg 983464ebd5Sriastradh/** 993464ebd5Sriastradh * Lookup a handle to find the linked config. 1003464ebd5Sriastradh * Return NULL if the handle has no corresponding linked config. 1013464ebd5Sriastradh */ 1023464ebd5Sriastradh_EGLConfig * 1033464ebd5Sriastradh_eglLookupConfig(EGLConfig config, _EGLDisplay *dpy) 1044a49301eSmrg{ 1053464ebd5Sriastradh _EGLConfig *conf; 1064a49301eSmrg 1073464ebd5Sriastradh if (!dpy) 1083464ebd5Sriastradh return NULL; 1093464ebd5Sriastradh 1103464ebd5Sriastradh conf = (_EGLConfig *) _eglFindArray(dpy->Configs, (void *) config); 1113464ebd5Sriastradh if (conf) 1123464ebd5Sriastradh assert(conf->Display == dpy); 1133464ebd5Sriastradh 1143464ebd5Sriastradh return conf; 1154a49301eSmrg} 1164a49301eSmrg 1174a49301eSmrg 1184a49301eSmrgenum { 1194a49301eSmrg /* types */ 1204a49301eSmrg ATTRIB_TYPE_INTEGER, 1214a49301eSmrg ATTRIB_TYPE_BOOLEAN, 1224a49301eSmrg ATTRIB_TYPE_BITMASK, 1234a49301eSmrg ATTRIB_TYPE_ENUM, 1244a49301eSmrg ATTRIB_TYPE_PSEUDO, /* non-queryable */ 1254a49301eSmrg ATTRIB_TYPE_PLATFORM, /* platform-dependent */ 1264a49301eSmrg /* criteria */ 1274a49301eSmrg ATTRIB_CRITERION_EXACT, 1284a49301eSmrg ATTRIB_CRITERION_ATLEAST, 1294a49301eSmrg ATTRIB_CRITERION_MASK, 1304a49301eSmrg ATTRIB_CRITERION_SPECIAL, 131cdc920a0Smrg ATTRIB_CRITERION_IGNORE 1324a49301eSmrg}; 1334a49301eSmrg 1344a49301eSmrg 1354a49301eSmrg/* EGL spec Table 3.1 and 3.4 */ 1364a49301eSmrgstatic const struct { 1374a49301eSmrg EGLint attr; 1384a49301eSmrg EGLint type; 1394a49301eSmrg EGLint criterion; 1404a49301eSmrg EGLint default_value; 1414a49301eSmrg} _eglValidationTable[] = 1424a49301eSmrg{ 1433464ebd5Sriastradh /* core */ 1444a49301eSmrg { EGL_BUFFER_SIZE, ATTRIB_TYPE_INTEGER, 1454a49301eSmrg ATTRIB_CRITERION_ATLEAST, 1464a49301eSmrg 0 }, 1474a49301eSmrg { EGL_RED_SIZE, ATTRIB_TYPE_INTEGER, 1484a49301eSmrg ATTRIB_CRITERION_ATLEAST, 1494a49301eSmrg 0 }, 1504a49301eSmrg { EGL_GREEN_SIZE, ATTRIB_TYPE_INTEGER, 1514a49301eSmrg ATTRIB_CRITERION_ATLEAST, 1524a49301eSmrg 0 }, 1534a49301eSmrg { EGL_BLUE_SIZE, ATTRIB_TYPE_INTEGER, 1544a49301eSmrg ATTRIB_CRITERION_ATLEAST, 1554a49301eSmrg 0 }, 1564a49301eSmrg { EGL_LUMINANCE_SIZE, ATTRIB_TYPE_INTEGER, 1574a49301eSmrg ATTRIB_CRITERION_ATLEAST, 1584a49301eSmrg 0 }, 1594a49301eSmrg { EGL_ALPHA_SIZE, ATTRIB_TYPE_INTEGER, 1604a49301eSmrg ATTRIB_CRITERION_ATLEAST, 1614a49301eSmrg 0 }, 1624a49301eSmrg { EGL_ALPHA_MASK_SIZE, ATTRIB_TYPE_INTEGER, 1634a49301eSmrg ATTRIB_CRITERION_ATLEAST, 1644a49301eSmrg 0 }, 1654a49301eSmrg { EGL_BIND_TO_TEXTURE_RGB, ATTRIB_TYPE_BOOLEAN, 1664a49301eSmrg ATTRIB_CRITERION_EXACT, 1674a49301eSmrg EGL_DONT_CARE }, 1684a49301eSmrg { EGL_BIND_TO_TEXTURE_RGBA, ATTRIB_TYPE_BOOLEAN, 1694a49301eSmrg ATTRIB_CRITERION_EXACT, 1704a49301eSmrg EGL_DONT_CARE }, 1714a49301eSmrg { EGL_COLOR_BUFFER_TYPE, ATTRIB_TYPE_ENUM, 1724a49301eSmrg ATTRIB_CRITERION_EXACT, 1734a49301eSmrg EGL_RGB_BUFFER }, 1744a49301eSmrg { EGL_CONFIG_CAVEAT, ATTRIB_TYPE_ENUM, 1754a49301eSmrg ATTRIB_CRITERION_EXACT, 1764a49301eSmrg EGL_DONT_CARE }, 1774a49301eSmrg { EGL_CONFIG_ID, ATTRIB_TYPE_INTEGER, 1784a49301eSmrg ATTRIB_CRITERION_EXACT, 1794a49301eSmrg EGL_DONT_CARE }, 1804a49301eSmrg { EGL_CONFORMANT, ATTRIB_TYPE_BITMASK, 1814a49301eSmrg ATTRIB_CRITERION_MASK, 1824a49301eSmrg 0 }, 1834a49301eSmrg { EGL_DEPTH_SIZE, ATTRIB_TYPE_INTEGER, 1844a49301eSmrg ATTRIB_CRITERION_ATLEAST, 1854a49301eSmrg 0 }, 1864a49301eSmrg { EGL_LEVEL, ATTRIB_TYPE_PLATFORM, 1874a49301eSmrg ATTRIB_CRITERION_EXACT, 1884a49301eSmrg 0 }, 1894a49301eSmrg { EGL_MAX_PBUFFER_WIDTH, ATTRIB_TYPE_INTEGER, 1904a49301eSmrg ATTRIB_CRITERION_IGNORE, 1914a49301eSmrg 0 }, 1924a49301eSmrg { EGL_MAX_PBUFFER_HEIGHT, ATTRIB_TYPE_INTEGER, 1934a49301eSmrg ATTRIB_CRITERION_IGNORE, 1944a49301eSmrg 0 }, 1954a49301eSmrg { EGL_MAX_PBUFFER_PIXELS, ATTRIB_TYPE_INTEGER, 1964a49301eSmrg ATTRIB_CRITERION_IGNORE, 1974a49301eSmrg 0 }, 1984a49301eSmrg { EGL_MAX_SWAP_INTERVAL, ATTRIB_TYPE_INTEGER, 1994a49301eSmrg ATTRIB_CRITERION_EXACT, 2004a49301eSmrg EGL_DONT_CARE }, 2014a49301eSmrg { EGL_MIN_SWAP_INTERVAL, ATTRIB_TYPE_INTEGER, 2024a49301eSmrg ATTRIB_CRITERION_EXACT, 2034a49301eSmrg EGL_DONT_CARE }, 2044a49301eSmrg { EGL_NATIVE_RENDERABLE, ATTRIB_TYPE_BOOLEAN, 2054a49301eSmrg ATTRIB_CRITERION_EXACT, 2064a49301eSmrg EGL_DONT_CARE }, 2074a49301eSmrg { EGL_NATIVE_VISUAL_ID, ATTRIB_TYPE_PLATFORM, 2084a49301eSmrg ATTRIB_CRITERION_IGNORE, 2094a49301eSmrg 0 }, 2104a49301eSmrg { EGL_NATIVE_VISUAL_TYPE, ATTRIB_TYPE_PLATFORM, 2114a49301eSmrg ATTRIB_CRITERION_EXACT, 2124a49301eSmrg EGL_DONT_CARE }, 2134a49301eSmrg { EGL_RENDERABLE_TYPE, ATTRIB_TYPE_BITMASK, 2144a49301eSmrg ATTRIB_CRITERION_MASK, 2154a49301eSmrg EGL_OPENGL_ES_BIT }, 2164a49301eSmrg { EGL_SAMPLE_BUFFERS, ATTRIB_TYPE_INTEGER, 2174a49301eSmrg ATTRIB_CRITERION_ATLEAST, 2184a49301eSmrg 0 }, 2194a49301eSmrg { EGL_SAMPLES, ATTRIB_TYPE_INTEGER, 2204a49301eSmrg ATTRIB_CRITERION_ATLEAST, 2214a49301eSmrg 0 }, 2224a49301eSmrg { EGL_STENCIL_SIZE, ATTRIB_TYPE_INTEGER, 2234a49301eSmrg ATTRIB_CRITERION_ATLEAST, 2244a49301eSmrg 0 }, 2254a49301eSmrg { EGL_SURFACE_TYPE, ATTRIB_TYPE_BITMASK, 2264a49301eSmrg ATTRIB_CRITERION_MASK, 2274a49301eSmrg EGL_WINDOW_BIT }, 2284a49301eSmrg { EGL_TRANSPARENT_TYPE, ATTRIB_TYPE_ENUM, 2294a49301eSmrg ATTRIB_CRITERION_EXACT, 2304a49301eSmrg EGL_NONE }, 2314a49301eSmrg { EGL_TRANSPARENT_RED_VALUE, ATTRIB_TYPE_INTEGER, 2324a49301eSmrg ATTRIB_CRITERION_EXACT, 2334a49301eSmrg EGL_DONT_CARE }, 2344a49301eSmrg { EGL_TRANSPARENT_GREEN_VALUE, ATTRIB_TYPE_INTEGER, 2354a49301eSmrg ATTRIB_CRITERION_EXACT, 2364a49301eSmrg EGL_DONT_CARE }, 2374a49301eSmrg { EGL_TRANSPARENT_BLUE_VALUE, ATTRIB_TYPE_INTEGER, 2384a49301eSmrg ATTRIB_CRITERION_EXACT, 2394a49301eSmrg EGL_DONT_CARE }, 2404a49301eSmrg { EGL_MATCH_NATIVE_PIXMAP, ATTRIB_TYPE_PSEUDO, 2414a49301eSmrg ATTRIB_CRITERION_SPECIAL, 2424a49301eSmrg EGL_NONE }, 2433464ebd5Sriastradh /* extensions */ 2443464ebd5Sriastradh { EGL_Y_INVERTED_NOK, ATTRIB_TYPE_BOOLEAN, 2453464ebd5Sriastradh ATTRIB_CRITERION_EXACT, 2463464ebd5Sriastradh EGL_DONT_CARE } 2474a49301eSmrg}; 2484a49301eSmrg 2494a49301eSmrg 2504a49301eSmrg/** 2514a49301eSmrg * Return true if a config is valid. When for_matching is true, 2524a49301eSmrg * EGL_DONT_CARE is accepted as a valid attribute value, and checks 2534a49301eSmrg * for conflicting attribute values are skipped. 2544a49301eSmrg * 2554a49301eSmrg * Note that some attributes are platform-dependent and are not 2564a49301eSmrg * checked. 2574a49301eSmrg */ 2584a49301eSmrgEGLBoolean 2594a49301eSmrg_eglValidateConfig(const _EGLConfig *conf, EGLBoolean for_matching) 2604a49301eSmrg{ 2614a49301eSmrg EGLint i, attr, val; 2624a49301eSmrg EGLBoolean valid = EGL_TRUE; 2634a49301eSmrg 2644a49301eSmrg /* check attributes by their types */ 2654a49301eSmrg for (i = 0; i < ARRAY_SIZE(_eglValidationTable); i++) { 2664a49301eSmrg EGLint mask; 2674a49301eSmrg 2684a49301eSmrg attr = _eglValidationTable[i].attr; 2693464ebd5Sriastradh val = _eglGetConfigKey(conf, attr); 2704a49301eSmrg 2714a49301eSmrg switch (_eglValidationTable[i].type) { 2724a49301eSmrg case ATTRIB_TYPE_INTEGER: 2734a49301eSmrg switch (attr) { 2744a49301eSmrg case EGL_CONFIG_ID: 2754a49301eSmrg /* config id must be positive */ 2764a49301eSmrg if (val <= 0) 2774a49301eSmrg valid = EGL_FALSE; 2784a49301eSmrg break; 2794a49301eSmrg case EGL_SAMPLE_BUFFERS: 2804a49301eSmrg /* there can be at most 1 sample buffer */ 2813464ebd5Sriastradh if (val > 1 || val < 0) 2824a49301eSmrg valid = EGL_FALSE; 2834a49301eSmrg break; 2843464ebd5Sriastradh default: 2853464ebd5Sriastradh if (val < 0) 2863464ebd5Sriastradh valid = EGL_FALSE; 2874a49301eSmrg break; 2884a49301eSmrg } 2894a49301eSmrg break; 2904a49301eSmrg case ATTRIB_TYPE_BOOLEAN: 2914a49301eSmrg if (val != EGL_TRUE && val != EGL_FALSE) 2924a49301eSmrg valid = EGL_FALSE; 2934a49301eSmrg break; 2944a49301eSmrg case ATTRIB_TYPE_ENUM: 2954a49301eSmrg switch (attr) { 2964a49301eSmrg case EGL_CONFIG_CAVEAT: 2974a49301eSmrg if (val != EGL_NONE && val != EGL_SLOW_CONFIG && 2984a49301eSmrg val != EGL_NON_CONFORMANT_CONFIG) 2994a49301eSmrg valid = EGL_FALSE; 3004a49301eSmrg break; 3014a49301eSmrg case EGL_TRANSPARENT_TYPE: 3024a49301eSmrg if (val != EGL_NONE && val != EGL_TRANSPARENT_RGB) 3034a49301eSmrg valid = EGL_FALSE; 3044a49301eSmrg break; 3054a49301eSmrg case EGL_COLOR_BUFFER_TYPE: 3064a49301eSmrg if (val != EGL_RGB_BUFFER && val != EGL_LUMINANCE_BUFFER) 3074a49301eSmrg valid = EGL_FALSE; 3084a49301eSmrg break; 3094a49301eSmrg default: 3104a49301eSmrg assert(0); 3114a49301eSmrg break; 3124a49301eSmrg } 3134a49301eSmrg break; 3144a49301eSmrg case ATTRIB_TYPE_BITMASK: 3154a49301eSmrg switch (attr) { 3164a49301eSmrg case EGL_SURFACE_TYPE: 3174a49301eSmrg mask = EGL_PBUFFER_BIT | 3184a49301eSmrg EGL_PIXMAP_BIT | 3194a49301eSmrg EGL_WINDOW_BIT | 3204a49301eSmrg EGL_VG_COLORSPACE_LINEAR_BIT | 3214a49301eSmrg EGL_VG_ALPHA_FORMAT_PRE_BIT | 3224a49301eSmrg EGL_MULTISAMPLE_RESOLVE_BOX_BIT | 3234a49301eSmrg EGL_SWAP_BEHAVIOR_PRESERVED_BIT; 3243464ebd5Sriastradh#ifdef EGL_MESA_screen_surface 325cdc920a0Smrg if (conf->Display->Extensions.MESA_screen_surface) 326cdc920a0Smrg mask |= EGL_SCREEN_BIT_MESA; 3273464ebd5Sriastradh#endif 3284a49301eSmrg break; 3294a49301eSmrg case EGL_RENDERABLE_TYPE: 3304a49301eSmrg case EGL_CONFORMANT: 3314a49301eSmrg mask = EGL_OPENGL_ES_BIT | 3324a49301eSmrg EGL_OPENVG_BIT | 3334a49301eSmrg EGL_OPENGL_ES2_BIT | 334af69d88dSmrg EGL_OPENGL_ES3_BIT_KHR | 3354a49301eSmrg EGL_OPENGL_BIT; 3364a49301eSmrg break; 3374a49301eSmrg default: 3384a49301eSmrg assert(0); 339af69d88dSmrg mask = 0; 3404a49301eSmrg break; 3414a49301eSmrg } 3424a49301eSmrg if (val & ~mask) 3434a49301eSmrg valid = EGL_FALSE; 3444a49301eSmrg break; 3454a49301eSmrg case ATTRIB_TYPE_PLATFORM: 3464a49301eSmrg /* unable to check platform-dependent attributes here */ 3474a49301eSmrg break; 3484a49301eSmrg case ATTRIB_TYPE_PSEUDO: 3494a49301eSmrg /* pseudo attributes should not be set */ 3504a49301eSmrg if (val != 0) 3514a49301eSmrg valid = EGL_FALSE; 3524a49301eSmrg break; 3534a49301eSmrg default: 3544a49301eSmrg assert(0); 3554a49301eSmrg break; 3564a49301eSmrg } 3574a49301eSmrg 3584a49301eSmrg if (!valid && for_matching) { 3594a49301eSmrg /* accept EGL_DONT_CARE as a valid value */ 3604a49301eSmrg if (val == EGL_DONT_CARE) 3614a49301eSmrg valid = EGL_TRUE; 3624a49301eSmrg if (_eglValidationTable[i].criterion == ATTRIB_CRITERION_SPECIAL) 3634a49301eSmrg valid = EGL_TRUE; 3644a49301eSmrg } 365cdc920a0Smrg if (!valid) { 366cdc920a0Smrg _eglLog(_EGL_DEBUG, 367cdc920a0Smrg "attribute 0x%04x has an invalid value 0x%x", attr, val); 3684a49301eSmrg break; 369cdc920a0Smrg } 3704a49301eSmrg } 3714a49301eSmrg 3724a49301eSmrg /* any invalid attribute value should have been catched */ 3734a49301eSmrg if (!valid || for_matching) 3744a49301eSmrg return valid; 3754a49301eSmrg 3764a49301eSmrg /* now check for conflicting attribute values */ 3774a49301eSmrg 3783464ebd5Sriastradh switch (conf->ColorBufferType) { 3794a49301eSmrg case EGL_RGB_BUFFER: 3803464ebd5Sriastradh if (conf->LuminanceSize) 3814a49301eSmrg valid = EGL_FALSE; 3823464ebd5Sriastradh if (conf->RedSize + conf->GreenSize + 3833464ebd5Sriastradh conf->BlueSize + conf->AlphaSize != conf->BufferSize) 3844a49301eSmrg valid = EGL_FALSE; 3854a49301eSmrg break; 3864a49301eSmrg case EGL_LUMINANCE_BUFFER: 3873464ebd5Sriastradh if (conf->RedSize || conf->GreenSize || conf->BlueSize) 3884a49301eSmrg valid = EGL_FALSE; 3893464ebd5Sriastradh if (conf->LuminanceSize + conf->AlphaSize != conf->BufferSize) 3904a49301eSmrg valid = EGL_FALSE; 3914a49301eSmrg break; 3924a49301eSmrg } 393cdc920a0Smrg if (!valid) { 394cdc920a0Smrg _eglLog(_EGL_DEBUG, "conflicting color buffer type and channel sizes"); 395cdc920a0Smrg return EGL_FALSE; 396cdc920a0Smrg } 3974a49301eSmrg 3983464ebd5Sriastradh if (!conf->SampleBuffers && conf->Samples) 3994a49301eSmrg valid = EGL_FALSE; 400cdc920a0Smrg if (!valid) { 401cdc920a0Smrg _eglLog(_EGL_DEBUG, "conflicting samples and sample buffers"); 402cdc920a0Smrg return EGL_FALSE; 403cdc920a0Smrg } 4044a49301eSmrg 4053464ebd5Sriastradh if (!(conf->SurfaceType & EGL_WINDOW_BIT)) { 4063464ebd5Sriastradh if (conf->NativeVisualID != 0 || conf->NativeVisualType != EGL_NONE) 4074a49301eSmrg valid = EGL_FALSE; 4084a49301eSmrg } 4093464ebd5Sriastradh if (!(conf->SurfaceType & EGL_PBUFFER_BIT)) { 4103464ebd5Sriastradh if (conf->BindToTextureRGB || conf->BindToTextureRGBA) 4114a49301eSmrg valid = EGL_FALSE; 4124a49301eSmrg } 413cdc920a0Smrg if (!valid) { 414cdc920a0Smrg _eglLog(_EGL_DEBUG, "conflicting surface type and native visual/texture binding"); 415cdc920a0Smrg return EGL_FALSE; 416cdc920a0Smrg } 4174a49301eSmrg 4184a49301eSmrg return valid; 4194a49301eSmrg} 4204a49301eSmrg 4214a49301eSmrg 4224a49301eSmrg/** 4234a49301eSmrg * Return true if a config matches the criteria. This and 4244a49301eSmrg * _eglParseConfigAttribList together implement the algorithm 4254a49301eSmrg * described in "Selection of EGLConfigs". 4264a49301eSmrg * 4274a49301eSmrg * Note that attributes that are special (currently, only 4284a49301eSmrg * EGL_MATCH_NATIVE_PIXMAP) are ignored. 4294a49301eSmrg */ 4304a49301eSmrgEGLBoolean 4314a49301eSmrg_eglMatchConfig(const _EGLConfig *conf, const _EGLConfig *criteria) 4324a49301eSmrg{ 4334a49301eSmrg EGLint attr, val, i; 4344a49301eSmrg EGLBoolean matched = EGL_TRUE; 4354a49301eSmrg 4364a49301eSmrg for (i = 0; i < ARRAY_SIZE(_eglValidationTable); i++) { 4374a49301eSmrg EGLint cmp; 4384a49301eSmrg if (_eglValidationTable[i].criterion == ATTRIB_CRITERION_IGNORE) 4394a49301eSmrg continue; 4404a49301eSmrg 4414a49301eSmrg attr = _eglValidationTable[i].attr; 4423464ebd5Sriastradh cmp = _eglGetConfigKey(criteria, attr); 4434a49301eSmrg if (cmp == EGL_DONT_CARE) 4444a49301eSmrg continue; 4454a49301eSmrg 4463464ebd5Sriastradh val = _eglGetConfigKey(conf, attr); 4474a49301eSmrg switch (_eglValidationTable[i].criterion) { 4484a49301eSmrg case ATTRIB_CRITERION_EXACT: 4494a49301eSmrg if (val != cmp) 4504a49301eSmrg matched = EGL_FALSE; 4514a49301eSmrg break; 4524a49301eSmrg case ATTRIB_CRITERION_ATLEAST: 4534a49301eSmrg if (val < cmp) 4544a49301eSmrg matched = EGL_FALSE; 4554a49301eSmrg break; 4564a49301eSmrg case ATTRIB_CRITERION_MASK: 4574a49301eSmrg if ((val & cmp) != cmp) 4584a49301eSmrg matched = EGL_FALSE; 4594a49301eSmrg break; 4604a49301eSmrg case ATTRIB_CRITERION_SPECIAL: 4614a49301eSmrg /* ignored here */ 4624a49301eSmrg break; 4634a49301eSmrg default: 4644a49301eSmrg assert(0); 4654a49301eSmrg break; 4664a49301eSmrg } 4674a49301eSmrg 468cdc920a0Smrg if (!matched) { 4693464ebd5Sriastradh#ifndef DEBUG 4703464ebd5Sriastradh /* only print the common errors when DEBUG is not defined */ 4713464ebd5Sriastradh if (attr != EGL_RENDERABLE_TYPE) 4723464ebd5Sriastradh break; 4733464ebd5Sriastradh#endif 474cdc920a0Smrg _eglLog(_EGL_DEBUG, 475cdc920a0Smrg "the value (0x%x) of attribute 0x%04x did not meet the criteria (0x%x)", 476cdc920a0Smrg val, attr, cmp); 4774a49301eSmrg break; 478cdc920a0Smrg } 4794a49301eSmrg } 4804a49301eSmrg 4814a49301eSmrg return matched; 4824a49301eSmrg} 4834a49301eSmrg 4843464ebd5Sriastradhstatic INLINE EGLBoolean 4853464ebd5Sriastradh_eglIsConfigAttribValid(_EGLConfig *conf, EGLint attr) 4863464ebd5Sriastradh{ 4873464ebd5Sriastradh if (_eglOffsetOfConfig(attr) < 0) 4883464ebd5Sriastradh return EGL_FALSE; 4893464ebd5Sriastradh 4903464ebd5Sriastradh switch (attr) { 4913464ebd5Sriastradh case EGL_Y_INVERTED_NOK: 4923464ebd5Sriastradh return conf->Display->Extensions.NOK_texture_from_pixmap; 4933464ebd5Sriastradh default: 4943464ebd5Sriastradh break; 4953464ebd5Sriastradh } 4963464ebd5Sriastradh 4973464ebd5Sriastradh return EGL_TRUE; 4983464ebd5Sriastradh} 4994a49301eSmrg 5004a49301eSmrg/** 5014a49301eSmrg * Initialize a criteria config from the given attribute list. 5024a49301eSmrg * Return EGL_FALSE if any of the attribute is invalid. 5034a49301eSmrg */ 5044a49301eSmrgEGLBoolean 5053464ebd5Sriastradh_eglParseConfigAttribList(_EGLConfig *conf, _EGLDisplay *dpy, 5063464ebd5Sriastradh const EGLint *attrib_list) 5074a49301eSmrg{ 5084a49301eSmrg EGLint attr, val, i; 5093464ebd5Sriastradh 5103464ebd5Sriastradh _eglInitConfig(conf, dpy, EGL_DONT_CARE); 5114a49301eSmrg 5124a49301eSmrg /* reset to default values */ 5134a49301eSmrg for (i = 0; i < ARRAY_SIZE(_eglValidationTable); i++) { 5144a49301eSmrg attr = _eglValidationTable[i].attr; 5154a49301eSmrg val = _eglValidationTable[i].default_value; 5163464ebd5Sriastradh _eglSetConfigKey(conf, attr, val); 5174a49301eSmrg } 5184a49301eSmrg 5194a49301eSmrg /* parse the list */ 5204a49301eSmrg for (i = 0; attrib_list && attrib_list[i] != EGL_NONE; i += 2) { 5214a49301eSmrg attr = attrib_list[i]; 5224a49301eSmrg val = attrib_list[i + 1]; 5234a49301eSmrg 5243464ebd5Sriastradh if (!_eglIsConfigAttribValid(conf, attr)) 5253464ebd5Sriastradh return EGL_FALSE; 5264a49301eSmrg 5273464ebd5Sriastradh _eglSetConfigKey(conf, attr, val); 5284a49301eSmrg } 5294a49301eSmrg 5304a49301eSmrg if (!_eglValidateConfig(conf, EGL_TRUE)) 5314a49301eSmrg return EGL_FALSE; 5324a49301eSmrg 533af69d88dSmrg /* EGL_LEVEL and EGL_MATCH_NATIVE_PIXMAP cannot be EGL_DONT_CARE */ 534af69d88dSmrg if (conf->Level == EGL_DONT_CARE || 535af69d88dSmrg conf->MatchNativePixmap == EGL_DONT_CARE) 5364a49301eSmrg return EGL_FALSE; 5374a49301eSmrg 5384a49301eSmrg /* ignore other attributes when EGL_CONFIG_ID is given */ 5393464ebd5Sriastradh if (conf->ConfigID != EGL_DONT_CARE) { 5403464ebd5Sriastradh for (i = 0; i < ARRAY_SIZE(_eglValidationTable); i++) { 5413464ebd5Sriastradh attr = _eglValidationTable[i].attr; 5423464ebd5Sriastradh if (attr != EGL_CONFIG_ID) 5433464ebd5Sriastradh _eglSetConfigKey(conf, attr, EGL_DONT_CARE); 5443464ebd5Sriastradh } 5454a49301eSmrg } 5464a49301eSmrg else { 5473464ebd5Sriastradh if (!(conf->SurfaceType & EGL_WINDOW_BIT)) 5483464ebd5Sriastradh conf->NativeVisualType = EGL_DONT_CARE; 5494a49301eSmrg 5503464ebd5Sriastradh if (conf->TransparentType == EGL_NONE) { 5513464ebd5Sriastradh conf->TransparentRedValue = EGL_DONT_CARE; 5523464ebd5Sriastradh conf->TransparentGreenValue = EGL_DONT_CARE; 5533464ebd5Sriastradh conf->TransparentBlueValue = EGL_DONT_CARE; 5544a49301eSmrg } 5554a49301eSmrg } 5564a49301eSmrg 5574a49301eSmrg return EGL_TRUE; 5584a49301eSmrg} 5594a49301eSmrg 5604a49301eSmrg 5614a49301eSmrg/** 5624a49301eSmrg * Decide the ordering of conf1 and conf2, under the given criteria. 5634a49301eSmrg * When compare_id is true, this implements the algorithm described 5644a49301eSmrg * in "Sorting of EGLConfigs". When compare_id is false, 5654a49301eSmrg * EGL_CONFIG_ID is not compared. 5664a49301eSmrg * 5674a49301eSmrg * It returns a negative integer if conf1 is considered to come 5684a49301eSmrg * before conf2; a positive integer if conf2 is considered to come 5694a49301eSmrg * before conf1; zero if the ordering cannot be decided. 5704a49301eSmrg * 5714a49301eSmrg * Note that EGL_NATIVE_VISUAL_TYPE is platform-dependent and is 5724a49301eSmrg * ignored here. 5734a49301eSmrg */ 5744a49301eSmrgEGLint 5754a49301eSmrg_eglCompareConfigs(const _EGLConfig *conf1, const _EGLConfig *conf2, 5764a49301eSmrg const _EGLConfig *criteria, EGLBoolean compare_id) 5774a49301eSmrg{ 5784a49301eSmrg const EGLint compare_attribs[] = { 5794a49301eSmrg EGL_BUFFER_SIZE, 5804a49301eSmrg EGL_SAMPLE_BUFFERS, 5814a49301eSmrg EGL_SAMPLES, 5824a49301eSmrg EGL_DEPTH_SIZE, 5834a49301eSmrg EGL_STENCIL_SIZE, 5844a49301eSmrg EGL_ALPHA_MASK_SIZE, 5854a49301eSmrg }; 5864a49301eSmrg EGLint val1, val2; 5874a49301eSmrg EGLint i; 5884a49301eSmrg 5894a49301eSmrg if (conf1 == conf2) 5904a49301eSmrg return 0; 5914a49301eSmrg 5924a49301eSmrg /* the enum values have the desired ordering */ 5934a49301eSmrg assert(EGL_NONE < EGL_SLOW_CONFIG); 5944a49301eSmrg assert(EGL_SLOW_CONFIG < EGL_NON_CONFORMANT_CONFIG); 5953464ebd5Sriastradh val1 = conf1->ConfigCaveat - conf2->ConfigCaveat; 5963464ebd5Sriastradh if (val1) 5973464ebd5Sriastradh return val1; 5984a49301eSmrg 5994a49301eSmrg /* the enum values have the desired ordering */ 6004a49301eSmrg assert(EGL_RGB_BUFFER < EGL_LUMINANCE_BUFFER); 6013464ebd5Sriastradh val1 = conf1->ColorBufferType - conf2->ColorBufferType; 6023464ebd5Sriastradh if (val1) 6033464ebd5Sriastradh return val1; 6044a49301eSmrg 6054a49301eSmrg if (criteria) { 6064a49301eSmrg val1 = val2 = 0; 6073464ebd5Sriastradh if (conf1->ColorBufferType == EGL_RGB_BUFFER) { 6083464ebd5Sriastradh if (criteria->RedSize > 0) { 6093464ebd5Sriastradh val1 += conf1->RedSize; 6103464ebd5Sriastradh val2 += conf2->RedSize; 6114a49301eSmrg } 6123464ebd5Sriastradh if (criteria->GreenSize > 0) { 6133464ebd5Sriastradh val1 += conf1->GreenSize; 6143464ebd5Sriastradh val2 += conf2->GreenSize; 6154a49301eSmrg } 6163464ebd5Sriastradh if (criteria->BlueSize > 0) { 6173464ebd5Sriastradh val1 += conf1->BlueSize; 6183464ebd5Sriastradh val2 += conf2->BlueSize; 6194a49301eSmrg } 6204a49301eSmrg } 6214a49301eSmrg else { 6223464ebd5Sriastradh if (criteria->LuminanceSize > 0) { 6233464ebd5Sriastradh val1 += conf1->LuminanceSize; 6243464ebd5Sriastradh val2 += conf2->LuminanceSize; 6254a49301eSmrg } 6264a49301eSmrg } 6273464ebd5Sriastradh if (criteria->AlphaSize > 0) { 6283464ebd5Sriastradh val1 += conf1->AlphaSize; 6293464ebd5Sriastradh val2 += conf2->AlphaSize; 6304a49301eSmrg } 6314a49301eSmrg } 6324a49301eSmrg else { 6334a49301eSmrg /* assume the default criteria, which gives no specific ordering */ 6344a49301eSmrg val1 = val2 = 0; 6354a49301eSmrg } 6364a49301eSmrg 6374a49301eSmrg /* for color bits, larger one is preferred */ 6384a49301eSmrg if (val1 != val2) 6394a49301eSmrg return (val2 - val1); 6404a49301eSmrg 6414a49301eSmrg for (i = 0; i < ARRAY_SIZE(compare_attribs); i++) { 6423464ebd5Sriastradh val1 = _eglGetConfigKey(conf1, compare_attribs[i]); 6433464ebd5Sriastradh val2 = _eglGetConfigKey(conf2, compare_attribs[i]); 6444a49301eSmrg if (val1 != val2) 6454a49301eSmrg return (val1 - val2); 6464a49301eSmrg } 6474a49301eSmrg 6484a49301eSmrg /* EGL_NATIVE_VISUAL_TYPE cannot be compared here */ 6494a49301eSmrg 6503464ebd5Sriastradh return (compare_id) ? (conf1->ConfigID - conf2->ConfigID) : 0; 6514a49301eSmrg} 6524a49301eSmrg 6534a49301eSmrg 6544a49301eSmrgstatic INLINE 6554a49301eSmrgvoid _eglSwapConfigs(const _EGLConfig **conf1, const _EGLConfig **conf2) 6564a49301eSmrg{ 6574a49301eSmrg const _EGLConfig *tmp = *conf1; 6584a49301eSmrg *conf1 = *conf2; 6594a49301eSmrg *conf2 = tmp; 6604a49301eSmrg} 6614a49301eSmrg 6624a49301eSmrg 6634a49301eSmrg/** 6644a49301eSmrg * Quick sort an array of configs. This differs from the standard 6654a49301eSmrg * qsort() in that the compare function accepts an additional 6664a49301eSmrg * argument. 6674a49301eSmrg */ 668af69d88dSmrgstatic void 6694a49301eSmrg_eglSortConfigs(const _EGLConfig **configs, EGLint count, 6704a49301eSmrg EGLint (*compare)(const _EGLConfig *, const _EGLConfig *, 6714a49301eSmrg void *), 6724a49301eSmrg void *priv_data) 6734a49301eSmrg{ 6744a49301eSmrg const EGLint pivot = 0; 6754a49301eSmrg EGLint i, j; 6764a49301eSmrg 6774a49301eSmrg if (count <= 1) 6784a49301eSmrg return; 6794a49301eSmrg 6804a49301eSmrg _eglSwapConfigs(&configs[pivot], &configs[count / 2]); 6814a49301eSmrg i = 1; 6824a49301eSmrg j = count - 1; 6834a49301eSmrg do { 6844a49301eSmrg while (i < count && compare(configs[i], configs[pivot], priv_data) < 0) 6854a49301eSmrg i++; 6864a49301eSmrg while (compare(configs[j], configs[pivot], priv_data) > 0) 6874a49301eSmrg j--; 6884a49301eSmrg if (i < j) { 6894a49301eSmrg _eglSwapConfigs(&configs[i], &configs[j]); 6904a49301eSmrg i++; 6914a49301eSmrg j--; 6924a49301eSmrg } 6934a49301eSmrg else if (i == j) { 6944a49301eSmrg i++; 6954a49301eSmrg j--; 6964a49301eSmrg break; 6974a49301eSmrg } 6984a49301eSmrg } while (i <= j); 6994a49301eSmrg _eglSwapConfigs(&configs[pivot], &configs[j]); 7004a49301eSmrg 7014a49301eSmrg _eglSortConfigs(configs, j, compare, priv_data); 7024a49301eSmrg _eglSortConfigs(configs + i, count - i, compare, priv_data); 7034a49301eSmrg} 7044a49301eSmrg 7054a49301eSmrg 7064a49301eSmrg/** 707af69d88dSmrg * A helper function for implementing eglChooseConfig. See _eglFilterArray and 708af69d88dSmrg * _eglSortConfigs for the meanings of match and compare. 7094a49301eSmrg */ 7104a49301eSmrgEGLBoolean 711af69d88dSmrg_eglFilterConfigArray(_EGLArray *array, EGLConfig *configs, 712af69d88dSmrg EGLint config_size, EGLint *num_configs, 713af69d88dSmrg EGLBoolean (*match)(const _EGLConfig *, void *), 714af69d88dSmrg EGLint (*compare)(const _EGLConfig *, const _EGLConfig *, 715af69d88dSmrg void *), 716af69d88dSmrg void *priv_data) 7174a49301eSmrg{ 718af69d88dSmrg _EGLConfig **configList; 7194a49301eSmrg EGLint i, count; 7204a49301eSmrg 7214a49301eSmrg if (!num_configs) 7224a49301eSmrg return _eglError(EGL_BAD_PARAMETER, "eglChooseConfigs"); 7234a49301eSmrg 7243464ebd5Sriastradh /* get the number of matched configs */ 725af69d88dSmrg count = _eglFilterArray(array, NULL, 0, 726af69d88dSmrg (_EGLArrayForEach) match, priv_data); 7273464ebd5Sriastradh if (!count) { 7283464ebd5Sriastradh *num_configs = count; 7293464ebd5Sriastradh return EGL_TRUE; 7303464ebd5Sriastradh } 7313464ebd5Sriastradh 7323464ebd5Sriastradh configList = malloc(sizeof(*configList) * count); 7334a49301eSmrg if (!configList) 7344a49301eSmrg return _eglError(EGL_BAD_ALLOC, "eglChooseConfig(out of memory)"); 7354a49301eSmrg 7363464ebd5Sriastradh /* get the matched configs */ 737af69d88dSmrg _eglFilterArray(array, (void **) configList, count, 738af69d88dSmrg (_EGLArrayForEach) match, priv_data); 7394a49301eSmrg 7404a49301eSmrg /* perform sorting of configs */ 7414a49301eSmrg if (configs && count) { 7424a49301eSmrg _eglSortConfigs((const _EGLConfig **) configList, count, 743af69d88dSmrg compare, priv_data); 7444a49301eSmrg count = MIN2(count, config_size); 7454a49301eSmrg for (i = 0; i < count; i++) 7464a49301eSmrg configs[i] = _eglGetConfigHandle(configList[i]); 7474a49301eSmrg } 7484a49301eSmrg 7494a49301eSmrg free(configList); 7504a49301eSmrg 7514a49301eSmrg *num_configs = count; 7524a49301eSmrg 7534a49301eSmrg return EGL_TRUE; 7544a49301eSmrg} 7554a49301eSmrg 7564a49301eSmrg 757af69d88dSmrgstatic EGLBoolean 758af69d88dSmrg_eglFallbackMatch(const _EGLConfig *conf, void *priv_data) 759af69d88dSmrg{ 760af69d88dSmrg return _eglMatchConfig(conf, (const _EGLConfig *) priv_data); 761af69d88dSmrg} 762af69d88dSmrg 763af69d88dSmrg 764af69d88dSmrgstatic EGLint 765af69d88dSmrg_eglFallbackCompare(const _EGLConfig *conf1, const _EGLConfig *conf2, 766af69d88dSmrg void *priv_data) 767af69d88dSmrg{ 768af69d88dSmrg return _eglCompareConfigs(conf1, conf2, 769af69d88dSmrg (const _EGLConfig *) priv_data, EGL_TRUE); 770af69d88dSmrg} 771af69d88dSmrg 772af69d88dSmrg 773af69d88dSmrg/** 774af69d88dSmrg * Typical fallback routine for eglChooseConfig 775af69d88dSmrg */ 776af69d88dSmrgEGLBoolean 777af69d88dSmrg_eglChooseConfig(_EGLDriver *drv, _EGLDisplay *disp, const EGLint *attrib_list, 778af69d88dSmrg EGLConfig *configs, EGLint config_size, EGLint *num_configs) 779af69d88dSmrg{ 780af69d88dSmrg _EGLConfig criteria; 781af69d88dSmrg 782af69d88dSmrg if (!_eglParseConfigAttribList(&criteria, disp, attrib_list)) 783af69d88dSmrg return _eglError(EGL_BAD_ATTRIBUTE, "eglChooseConfig"); 784af69d88dSmrg 785af69d88dSmrg return _eglFilterConfigArray(disp->Configs, 786af69d88dSmrg configs, config_size, num_configs, 787af69d88dSmrg _eglFallbackMatch, _eglFallbackCompare, 788af69d88dSmrg (void *) &criteria); 789af69d88dSmrg} 790af69d88dSmrg 791af69d88dSmrg 7924a49301eSmrg/** 7934a49301eSmrg * Fallback for eglGetConfigAttrib. 7944a49301eSmrg */ 7954a49301eSmrgEGLBoolean 7964a49301eSmrg_eglGetConfigAttrib(_EGLDriver *drv, _EGLDisplay *dpy, _EGLConfig *conf, 7974a49301eSmrg EGLint attribute, EGLint *value) 7984a49301eSmrg{ 7994a49301eSmrg if (!_eglIsConfigAttribValid(conf, attribute)) 8004a49301eSmrg return _eglError(EGL_BAD_ATTRIBUTE, "eglGetConfigAttrib"); 8013464ebd5Sriastradh 8023464ebd5Sriastradh /* nonqueryable attributes */ 8033464ebd5Sriastradh switch (attribute) { 8043464ebd5Sriastradh case EGL_MATCH_NATIVE_PIXMAP: 8053464ebd5Sriastradh return _eglError(EGL_BAD_ATTRIBUTE, "eglGetConfigAttrib"); 8063464ebd5Sriastradh break; 8073464ebd5Sriastradh default: 8083464ebd5Sriastradh break; 8093464ebd5Sriastradh } 8103464ebd5Sriastradh 8114a49301eSmrg if (!value) 8124a49301eSmrg return _eglError(EGL_BAD_PARAMETER, "eglGetConfigAttrib"); 8134a49301eSmrg 8143464ebd5Sriastradh *value = _eglGetConfigKey(conf, attribute); 8154a49301eSmrg return EGL_TRUE; 8164a49301eSmrg} 8174a49301eSmrg 8184a49301eSmrg 8193464ebd5Sriastradhstatic EGLBoolean 8203464ebd5Sriastradh_eglFlattenConfig(void *elem, void *buffer) 8213464ebd5Sriastradh{ 8223464ebd5Sriastradh _EGLConfig *conf = (_EGLConfig *) elem; 8233464ebd5Sriastradh EGLConfig *handle = (EGLConfig *) buffer; 8243464ebd5Sriastradh *handle = _eglGetConfigHandle(conf); 8253464ebd5Sriastradh return EGL_TRUE; 8263464ebd5Sriastradh} 8273464ebd5Sriastradh 8284a49301eSmrg/** 8294a49301eSmrg * Fallback for eglGetConfigs. 8304a49301eSmrg */ 8314a49301eSmrgEGLBoolean 8324a49301eSmrg_eglGetConfigs(_EGLDriver *drv, _EGLDisplay *disp, EGLConfig *configs, 8334a49301eSmrg EGLint config_size, EGLint *num_config) 8344a49301eSmrg{ 8354a49301eSmrg if (!num_config) 8364a49301eSmrg return _eglError(EGL_BAD_PARAMETER, "eglGetConfigs"); 8374a49301eSmrg 8383464ebd5Sriastradh *num_config = _eglFlattenArray(disp->Configs, (void *) configs, 8393464ebd5Sriastradh sizeof(configs[0]), config_size, _eglFlattenConfig); 8404a49301eSmrg 8414a49301eSmrg return EGL_TRUE; 8424a49301eSmrg} 843