eglconfig.c revision 01e04c3f
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> 3901e04c3fSmrg#include "c99_compat.h" 4001e04c3fSmrg#include "util/macros.h" 4101e04c3fSmrg 424a49301eSmrg#include "eglconfig.h" 434a49301eSmrg#include "egldisplay.h" 44cdc920a0Smrg#include "eglcurrent.h" 454a49301eSmrg#include "egllog.h" 464a49301eSmrg 474a49301eSmrg 484a49301eSmrg 494a49301eSmrg 504a49301eSmrg/** 514a49301eSmrg * Init the given _EGLconfig to default values. 524a49301eSmrg * \param id the configuration's ID. 534a49301eSmrg * 544a49301eSmrg * Note that id must be positive for the config to be valid. 554a49301eSmrg * It is also recommended that when there are N configs, their 564a49301eSmrg * IDs are from 1 to N respectively. 574a49301eSmrg */ 584a49301eSmrgvoid 593464ebd5Sriastradh_eglInitConfig(_EGLConfig *conf, _EGLDisplay *dpy, EGLint id) 604a49301eSmrg{ 613464ebd5Sriastradh memset(conf, 0, sizeof(*conf)); 624a49301eSmrg 633464ebd5Sriastradh conf->Display = dpy; 64cdc920a0Smrg 654a49301eSmrg /* some attributes take non-zero default values */ 663464ebd5Sriastradh conf->ConfigID = id; 673464ebd5Sriastradh conf->ConfigCaveat = EGL_NONE; 683464ebd5Sriastradh conf->TransparentType = EGL_NONE; 693464ebd5Sriastradh conf->NativeVisualType = EGL_NONE; 703464ebd5Sriastradh conf->ColorBufferType = EGL_RGB_BUFFER; 7101e04c3fSmrg conf->ComponentType = EGL_COLOR_COMPONENT_TYPE_FIXED_EXT; 724a49301eSmrg} 734a49301eSmrg 744a49301eSmrg 754a49301eSmrg/** 763464ebd5Sriastradh * Link a config to its display and return the handle of the link. 774a49301eSmrg * The handle can be passed to client directly. 784a49301eSmrg * 794a49301eSmrg * Note that we just save the ptr to the config (we don't copy the config). 804a49301eSmrg */ 8101e04c3fSmrgEGLConfig 823464ebd5Sriastradh_eglLinkConfig(_EGLConfig *conf) 834a49301eSmrg{ 843464ebd5Sriastradh _EGLDisplay *dpy = conf->Display; 854a49301eSmrg 864a49301eSmrg /* sanity check */ 8701e04c3fSmrg assert(dpy); 8801e04c3fSmrg assert(conf->ConfigID > 0); 894a49301eSmrg 903464ebd5Sriastradh if (!dpy->Configs) { 913464ebd5Sriastradh dpy->Configs = _eglCreateArray("Config", 16); 923464ebd5Sriastradh if (!dpy->Configs) 934a49301eSmrg return (EGLConfig) NULL; 944a49301eSmrg } 954a49301eSmrg 963464ebd5Sriastradh _eglAppendArray(dpy->Configs, (void *) conf); 974a49301eSmrg 984a49301eSmrg return (EGLConfig) conf; 994a49301eSmrg} 1004a49301eSmrg 1014a49301eSmrg 1023464ebd5Sriastradh/** 1033464ebd5Sriastradh * Lookup a handle to find the linked config. 1043464ebd5Sriastradh * Return NULL if the handle has no corresponding linked config. 1053464ebd5Sriastradh */ 1063464ebd5Sriastradh_EGLConfig * 1073464ebd5Sriastradh_eglLookupConfig(EGLConfig config, _EGLDisplay *dpy) 1084a49301eSmrg{ 1093464ebd5Sriastradh _EGLConfig *conf; 1104a49301eSmrg 1113464ebd5Sriastradh if (!dpy) 1123464ebd5Sriastradh return NULL; 1133464ebd5Sriastradh 1143464ebd5Sriastradh conf = (_EGLConfig *) _eglFindArray(dpy->Configs, (void *) config); 1153464ebd5Sriastradh if (conf) 1163464ebd5Sriastradh assert(conf->Display == dpy); 1173464ebd5Sriastradh 1183464ebd5Sriastradh return conf; 1194a49301eSmrg} 1204a49301eSmrg 1214a49301eSmrg 12201e04c3fSmrgenum type { 1234a49301eSmrg ATTRIB_TYPE_INTEGER, 1244a49301eSmrg ATTRIB_TYPE_BOOLEAN, 1254a49301eSmrg ATTRIB_TYPE_BITMASK, 1264a49301eSmrg ATTRIB_TYPE_ENUM, 1274a49301eSmrg ATTRIB_TYPE_PSEUDO, /* non-queryable */ 1284a49301eSmrg ATTRIB_TYPE_PLATFORM, /* platform-dependent */ 12901e04c3fSmrg}; 13001e04c3fSmrg 13101e04c3fSmrgenum criterion { 1324a49301eSmrg ATTRIB_CRITERION_EXACT, 1334a49301eSmrg ATTRIB_CRITERION_ATLEAST, 1344a49301eSmrg ATTRIB_CRITERION_MASK, 1354a49301eSmrg ATTRIB_CRITERION_SPECIAL, 136cdc920a0Smrg ATTRIB_CRITERION_IGNORE 1374a49301eSmrg}; 1384a49301eSmrg 1394a49301eSmrg 1404a49301eSmrg/* EGL spec Table 3.1 and 3.4 */ 1414a49301eSmrgstatic const struct { 1424a49301eSmrg EGLint attr; 14301e04c3fSmrg enum type type; 14401e04c3fSmrg enum criterion criterion; 1454a49301eSmrg EGLint default_value; 1464a49301eSmrg} _eglValidationTable[] = 1474a49301eSmrg{ 1483464ebd5Sriastradh /* core */ 1494a49301eSmrg { EGL_BUFFER_SIZE, ATTRIB_TYPE_INTEGER, 1504a49301eSmrg ATTRIB_CRITERION_ATLEAST, 1514a49301eSmrg 0 }, 1524a49301eSmrg { EGL_RED_SIZE, ATTRIB_TYPE_INTEGER, 1534a49301eSmrg ATTRIB_CRITERION_ATLEAST, 1544a49301eSmrg 0 }, 1554a49301eSmrg { EGL_GREEN_SIZE, ATTRIB_TYPE_INTEGER, 1564a49301eSmrg ATTRIB_CRITERION_ATLEAST, 1574a49301eSmrg 0 }, 1584a49301eSmrg { EGL_BLUE_SIZE, ATTRIB_TYPE_INTEGER, 1594a49301eSmrg ATTRIB_CRITERION_ATLEAST, 1604a49301eSmrg 0 }, 1614a49301eSmrg { EGL_LUMINANCE_SIZE, ATTRIB_TYPE_INTEGER, 1624a49301eSmrg ATTRIB_CRITERION_ATLEAST, 1634a49301eSmrg 0 }, 1644a49301eSmrg { EGL_ALPHA_SIZE, ATTRIB_TYPE_INTEGER, 1654a49301eSmrg ATTRIB_CRITERION_ATLEAST, 1664a49301eSmrg 0 }, 1674a49301eSmrg { EGL_ALPHA_MASK_SIZE, ATTRIB_TYPE_INTEGER, 1684a49301eSmrg ATTRIB_CRITERION_ATLEAST, 1694a49301eSmrg 0 }, 1704a49301eSmrg { EGL_BIND_TO_TEXTURE_RGB, ATTRIB_TYPE_BOOLEAN, 1714a49301eSmrg ATTRIB_CRITERION_EXACT, 1724a49301eSmrg EGL_DONT_CARE }, 1734a49301eSmrg { EGL_BIND_TO_TEXTURE_RGBA, ATTRIB_TYPE_BOOLEAN, 1744a49301eSmrg ATTRIB_CRITERION_EXACT, 1754a49301eSmrg EGL_DONT_CARE }, 1764a49301eSmrg { EGL_COLOR_BUFFER_TYPE, ATTRIB_TYPE_ENUM, 1774a49301eSmrg ATTRIB_CRITERION_EXACT, 1784a49301eSmrg EGL_RGB_BUFFER }, 1794a49301eSmrg { EGL_CONFIG_CAVEAT, ATTRIB_TYPE_ENUM, 1804a49301eSmrg ATTRIB_CRITERION_EXACT, 1814a49301eSmrg EGL_DONT_CARE }, 1824a49301eSmrg { EGL_CONFIG_ID, ATTRIB_TYPE_INTEGER, 1834a49301eSmrg ATTRIB_CRITERION_EXACT, 1844a49301eSmrg EGL_DONT_CARE }, 1854a49301eSmrg { EGL_CONFORMANT, ATTRIB_TYPE_BITMASK, 1864a49301eSmrg ATTRIB_CRITERION_MASK, 1874a49301eSmrg 0 }, 1884a49301eSmrg { EGL_DEPTH_SIZE, ATTRIB_TYPE_INTEGER, 1894a49301eSmrg ATTRIB_CRITERION_ATLEAST, 1904a49301eSmrg 0 }, 1914a49301eSmrg { EGL_LEVEL, ATTRIB_TYPE_PLATFORM, 1924a49301eSmrg ATTRIB_CRITERION_EXACT, 1934a49301eSmrg 0 }, 1944a49301eSmrg { EGL_MAX_PBUFFER_WIDTH, ATTRIB_TYPE_INTEGER, 1954a49301eSmrg ATTRIB_CRITERION_IGNORE, 1964a49301eSmrg 0 }, 1974a49301eSmrg { EGL_MAX_PBUFFER_HEIGHT, ATTRIB_TYPE_INTEGER, 1984a49301eSmrg ATTRIB_CRITERION_IGNORE, 1994a49301eSmrg 0 }, 2004a49301eSmrg { EGL_MAX_PBUFFER_PIXELS, ATTRIB_TYPE_INTEGER, 2014a49301eSmrg ATTRIB_CRITERION_IGNORE, 2024a49301eSmrg 0 }, 2034a49301eSmrg { EGL_MAX_SWAP_INTERVAL, ATTRIB_TYPE_INTEGER, 2044a49301eSmrg ATTRIB_CRITERION_EXACT, 2054a49301eSmrg EGL_DONT_CARE }, 2064a49301eSmrg { EGL_MIN_SWAP_INTERVAL, ATTRIB_TYPE_INTEGER, 2074a49301eSmrg ATTRIB_CRITERION_EXACT, 2084a49301eSmrg EGL_DONT_CARE }, 2094a49301eSmrg { EGL_NATIVE_RENDERABLE, ATTRIB_TYPE_BOOLEAN, 2104a49301eSmrg ATTRIB_CRITERION_EXACT, 2114a49301eSmrg EGL_DONT_CARE }, 2124a49301eSmrg { EGL_NATIVE_VISUAL_ID, ATTRIB_TYPE_PLATFORM, 2134a49301eSmrg ATTRIB_CRITERION_IGNORE, 2144a49301eSmrg 0 }, 2154a49301eSmrg { EGL_NATIVE_VISUAL_TYPE, ATTRIB_TYPE_PLATFORM, 2164a49301eSmrg ATTRIB_CRITERION_EXACT, 2174a49301eSmrg EGL_DONT_CARE }, 2184a49301eSmrg { EGL_RENDERABLE_TYPE, ATTRIB_TYPE_BITMASK, 2194a49301eSmrg ATTRIB_CRITERION_MASK, 2204a49301eSmrg EGL_OPENGL_ES_BIT }, 2214a49301eSmrg { EGL_SAMPLE_BUFFERS, ATTRIB_TYPE_INTEGER, 2224a49301eSmrg ATTRIB_CRITERION_ATLEAST, 2234a49301eSmrg 0 }, 2244a49301eSmrg { EGL_SAMPLES, ATTRIB_TYPE_INTEGER, 2254a49301eSmrg ATTRIB_CRITERION_ATLEAST, 2264a49301eSmrg 0 }, 2274a49301eSmrg { EGL_STENCIL_SIZE, ATTRIB_TYPE_INTEGER, 2284a49301eSmrg ATTRIB_CRITERION_ATLEAST, 2294a49301eSmrg 0 }, 2304a49301eSmrg { EGL_SURFACE_TYPE, ATTRIB_TYPE_BITMASK, 2314a49301eSmrg ATTRIB_CRITERION_MASK, 2324a49301eSmrg EGL_WINDOW_BIT }, 2334a49301eSmrg { EGL_TRANSPARENT_TYPE, ATTRIB_TYPE_ENUM, 2344a49301eSmrg ATTRIB_CRITERION_EXACT, 2354a49301eSmrg EGL_NONE }, 2364a49301eSmrg { EGL_TRANSPARENT_RED_VALUE, ATTRIB_TYPE_INTEGER, 2374a49301eSmrg ATTRIB_CRITERION_EXACT, 2384a49301eSmrg EGL_DONT_CARE }, 2394a49301eSmrg { EGL_TRANSPARENT_GREEN_VALUE, ATTRIB_TYPE_INTEGER, 2404a49301eSmrg ATTRIB_CRITERION_EXACT, 2414a49301eSmrg EGL_DONT_CARE }, 2424a49301eSmrg { EGL_TRANSPARENT_BLUE_VALUE, ATTRIB_TYPE_INTEGER, 2434a49301eSmrg ATTRIB_CRITERION_EXACT, 2444a49301eSmrg EGL_DONT_CARE }, 2454a49301eSmrg { EGL_MATCH_NATIVE_PIXMAP, ATTRIB_TYPE_PSEUDO, 2464a49301eSmrg ATTRIB_CRITERION_SPECIAL, 2474a49301eSmrg EGL_NONE }, 2483464ebd5Sriastradh /* extensions */ 2493464ebd5Sriastradh { EGL_Y_INVERTED_NOK, ATTRIB_TYPE_BOOLEAN, 2503464ebd5Sriastradh ATTRIB_CRITERION_EXACT, 25101e04c3fSmrg EGL_DONT_CARE }, 25201e04c3fSmrg { EGL_FRAMEBUFFER_TARGET_ANDROID, ATTRIB_TYPE_BOOLEAN, 25301e04c3fSmrg ATTRIB_CRITERION_EXACT, 25401e04c3fSmrg EGL_DONT_CARE }, 25501e04c3fSmrg { EGL_RECORDABLE_ANDROID, ATTRIB_TYPE_BOOLEAN, 25601e04c3fSmrg ATTRIB_CRITERION_EXACT, 25701e04c3fSmrg EGL_DONT_CARE }, 25801e04c3fSmrg { EGL_COLOR_COMPONENT_TYPE_EXT, ATTRIB_TYPE_ENUM, 25901e04c3fSmrg ATTRIB_CRITERION_EXACT, 26001e04c3fSmrg EGL_COLOR_COMPONENT_TYPE_FIXED_EXT }, 2614a49301eSmrg}; 2624a49301eSmrg 2634a49301eSmrg 2644a49301eSmrg/** 2654a49301eSmrg * Return true if a config is valid. When for_matching is true, 2664a49301eSmrg * EGL_DONT_CARE is accepted as a valid attribute value, and checks 2674a49301eSmrg * for conflicting attribute values are skipped. 2684a49301eSmrg * 2694a49301eSmrg * Note that some attributes are platform-dependent and are not 2704a49301eSmrg * checked. 2714a49301eSmrg */ 2724a49301eSmrgEGLBoolean 2734a49301eSmrg_eglValidateConfig(const _EGLConfig *conf, EGLBoolean for_matching) 2744a49301eSmrg{ 27501e04c3fSmrg _EGLDisplay *disp = conf->Display; 2764a49301eSmrg EGLint i, attr, val; 2774a49301eSmrg EGLBoolean valid = EGL_TRUE; 2784a49301eSmrg 2794a49301eSmrg /* check attributes by their types */ 2804a49301eSmrg for (i = 0; i < ARRAY_SIZE(_eglValidationTable); i++) { 2814a49301eSmrg EGLint mask; 2824a49301eSmrg 2834a49301eSmrg attr = _eglValidationTable[i].attr; 2843464ebd5Sriastradh val = _eglGetConfigKey(conf, attr); 2854a49301eSmrg 2864a49301eSmrg switch (_eglValidationTable[i].type) { 2874a49301eSmrg case ATTRIB_TYPE_INTEGER: 2884a49301eSmrg switch (attr) { 2894a49301eSmrg case EGL_CONFIG_ID: 2904a49301eSmrg /* config id must be positive */ 2914a49301eSmrg if (val <= 0) 2924a49301eSmrg valid = EGL_FALSE; 2934a49301eSmrg break; 2944a49301eSmrg case EGL_SAMPLE_BUFFERS: 2954a49301eSmrg /* there can be at most 1 sample buffer */ 2963464ebd5Sriastradh if (val > 1 || val < 0) 2974a49301eSmrg valid = EGL_FALSE; 2984a49301eSmrg break; 2993464ebd5Sriastradh default: 3003464ebd5Sriastradh if (val < 0) 3013464ebd5Sriastradh valid = EGL_FALSE; 3024a49301eSmrg break; 3034a49301eSmrg } 3044a49301eSmrg break; 3054a49301eSmrg case ATTRIB_TYPE_BOOLEAN: 3064a49301eSmrg if (val != EGL_TRUE && val != EGL_FALSE) 3074a49301eSmrg valid = EGL_FALSE; 3084a49301eSmrg break; 3094a49301eSmrg case ATTRIB_TYPE_ENUM: 3104a49301eSmrg switch (attr) { 3114a49301eSmrg case EGL_CONFIG_CAVEAT: 3124a49301eSmrg if (val != EGL_NONE && val != EGL_SLOW_CONFIG && 3134a49301eSmrg val != EGL_NON_CONFORMANT_CONFIG) 3144a49301eSmrg valid = EGL_FALSE; 3154a49301eSmrg break; 3164a49301eSmrg case EGL_TRANSPARENT_TYPE: 3174a49301eSmrg if (val != EGL_NONE && val != EGL_TRANSPARENT_RGB) 3184a49301eSmrg valid = EGL_FALSE; 3194a49301eSmrg break; 3204a49301eSmrg case EGL_COLOR_BUFFER_TYPE: 3214a49301eSmrg if (val != EGL_RGB_BUFFER && val != EGL_LUMINANCE_BUFFER) 3224a49301eSmrg valid = EGL_FALSE; 3234a49301eSmrg break; 32401e04c3fSmrg case EGL_COLOR_COMPONENT_TYPE_EXT: 32501e04c3fSmrg if (val != EGL_COLOR_COMPONENT_TYPE_FIXED_EXT && 32601e04c3fSmrg val != EGL_COLOR_COMPONENT_TYPE_FLOAT_EXT) 32701e04c3fSmrg valid = EGL_FALSE; 32801e04c3fSmrg break; 3294a49301eSmrg default: 33001e04c3fSmrg unreachable("check _eglValidationTable[]"); 3314a49301eSmrg break; 3324a49301eSmrg } 3334a49301eSmrg break; 3344a49301eSmrg case ATTRIB_TYPE_BITMASK: 3354a49301eSmrg switch (attr) { 3364a49301eSmrg case EGL_SURFACE_TYPE: 3374a49301eSmrg mask = EGL_PBUFFER_BIT | 3384a49301eSmrg EGL_PIXMAP_BIT | 3394a49301eSmrg EGL_WINDOW_BIT | 3404a49301eSmrg EGL_VG_COLORSPACE_LINEAR_BIT | 3414a49301eSmrg EGL_VG_ALPHA_FORMAT_PRE_BIT | 3424a49301eSmrg EGL_MULTISAMPLE_RESOLVE_BOX_BIT | 3434a49301eSmrg EGL_SWAP_BEHAVIOR_PRESERVED_BIT; 34401e04c3fSmrg if (disp->Extensions.KHR_mutable_render_buffer) 34501e04c3fSmrg mask |= EGL_MUTABLE_RENDER_BUFFER_BIT_KHR; 3464a49301eSmrg break; 3474a49301eSmrg case EGL_RENDERABLE_TYPE: 3484a49301eSmrg case EGL_CONFORMANT: 3494a49301eSmrg mask = EGL_OPENGL_ES_BIT | 3504a49301eSmrg EGL_OPENVG_BIT | 3514a49301eSmrg EGL_OPENGL_ES2_BIT | 352af69d88dSmrg EGL_OPENGL_ES3_BIT_KHR | 3534a49301eSmrg EGL_OPENGL_BIT; 3544a49301eSmrg break; 3554a49301eSmrg default: 35601e04c3fSmrg unreachable("check _eglValidationTable[]"); 357af69d88dSmrg mask = 0; 3584a49301eSmrg break; 3594a49301eSmrg } 3604a49301eSmrg if (val & ~mask) 3614a49301eSmrg valid = EGL_FALSE; 3624a49301eSmrg break; 3634a49301eSmrg case ATTRIB_TYPE_PLATFORM: 3644a49301eSmrg /* unable to check platform-dependent attributes here */ 3654a49301eSmrg break; 3664a49301eSmrg case ATTRIB_TYPE_PSEUDO: 3674a49301eSmrg /* pseudo attributes should not be set */ 3684a49301eSmrg if (val != 0) 3694a49301eSmrg valid = EGL_FALSE; 3704a49301eSmrg break; 3714a49301eSmrg } 3724a49301eSmrg 3734a49301eSmrg if (!valid && for_matching) { 3744a49301eSmrg /* accept EGL_DONT_CARE as a valid value */ 3754a49301eSmrg if (val == EGL_DONT_CARE) 3764a49301eSmrg valid = EGL_TRUE; 3774a49301eSmrg if (_eglValidationTable[i].criterion == ATTRIB_CRITERION_SPECIAL) 3784a49301eSmrg valid = EGL_TRUE; 3794a49301eSmrg } 380cdc920a0Smrg if (!valid) { 381cdc920a0Smrg _eglLog(_EGL_DEBUG, 382cdc920a0Smrg "attribute 0x%04x has an invalid value 0x%x", attr, val); 3834a49301eSmrg break; 384cdc920a0Smrg } 3854a49301eSmrg } 3864a49301eSmrg 3874a49301eSmrg /* any invalid attribute value should have been catched */ 3884a49301eSmrg if (!valid || for_matching) 3894a49301eSmrg return valid; 3904a49301eSmrg 3914a49301eSmrg /* now check for conflicting attribute values */ 3924a49301eSmrg 3933464ebd5Sriastradh switch (conf->ColorBufferType) { 3944a49301eSmrg case EGL_RGB_BUFFER: 3953464ebd5Sriastradh if (conf->LuminanceSize) 3964a49301eSmrg valid = EGL_FALSE; 3973464ebd5Sriastradh if (conf->RedSize + conf->GreenSize + 3983464ebd5Sriastradh conf->BlueSize + conf->AlphaSize != conf->BufferSize) 3994a49301eSmrg valid = EGL_FALSE; 4004a49301eSmrg break; 4014a49301eSmrg case EGL_LUMINANCE_BUFFER: 4023464ebd5Sriastradh if (conf->RedSize || conf->GreenSize || conf->BlueSize) 4034a49301eSmrg valid = EGL_FALSE; 4043464ebd5Sriastradh if (conf->LuminanceSize + conf->AlphaSize != conf->BufferSize) 4054a49301eSmrg valid = EGL_FALSE; 4064a49301eSmrg break; 4074a49301eSmrg } 408cdc920a0Smrg if (!valid) { 409cdc920a0Smrg _eglLog(_EGL_DEBUG, "conflicting color buffer type and channel sizes"); 410cdc920a0Smrg return EGL_FALSE; 411cdc920a0Smrg } 4124a49301eSmrg 4133464ebd5Sriastradh if (!conf->SampleBuffers && conf->Samples) 4144a49301eSmrg valid = EGL_FALSE; 415cdc920a0Smrg if (!valid) { 416cdc920a0Smrg _eglLog(_EGL_DEBUG, "conflicting samples and sample buffers"); 417cdc920a0Smrg return EGL_FALSE; 418cdc920a0Smrg } 4194a49301eSmrg 4203464ebd5Sriastradh if (!(conf->SurfaceType & EGL_WINDOW_BIT)) { 4213464ebd5Sriastradh if (conf->NativeVisualID != 0 || conf->NativeVisualType != EGL_NONE) 4224a49301eSmrg valid = EGL_FALSE; 4234a49301eSmrg } 4243464ebd5Sriastradh if (!(conf->SurfaceType & EGL_PBUFFER_BIT)) { 4253464ebd5Sriastradh if (conf->BindToTextureRGB || conf->BindToTextureRGBA) 4264a49301eSmrg valid = EGL_FALSE; 4274a49301eSmrg } 428cdc920a0Smrg if (!valid) { 429cdc920a0Smrg _eglLog(_EGL_DEBUG, "conflicting surface type and native visual/texture binding"); 430cdc920a0Smrg return EGL_FALSE; 431cdc920a0Smrg } 4324a49301eSmrg 4334a49301eSmrg return valid; 4344a49301eSmrg} 4354a49301eSmrg 4364a49301eSmrg 4374a49301eSmrg/** 4384a49301eSmrg * Return true if a config matches the criteria. This and 4394a49301eSmrg * _eglParseConfigAttribList together implement the algorithm 4404a49301eSmrg * described in "Selection of EGLConfigs". 4414a49301eSmrg * 4424a49301eSmrg * Note that attributes that are special (currently, only 4434a49301eSmrg * EGL_MATCH_NATIVE_PIXMAP) are ignored. 4444a49301eSmrg */ 4454a49301eSmrgEGLBoolean 4464a49301eSmrg_eglMatchConfig(const _EGLConfig *conf, const _EGLConfig *criteria) 4474a49301eSmrg{ 4484a49301eSmrg EGLint attr, val, i; 4494a49301eSmrg EGLBoolean matched = EGL_TRUE; 4504a49301eSmrg 4514a49301eSmrg for (i = 0; i < ARRAY_SIZE(_eglValidationTable); i++) { 4524a49301eSmrg EGLint cmp; 4534a49301eSmrg if (_eglValidationTable[i].criterion == ATTRIB_CRITERION_IGNORE) 4544a49301eSmrg continue; 4554a49301eSmrg 4564a49301eSmrg attr = _eglValidationTable[i].attr; 4573464ebd5Sriastradh cmp = _eglGetConfigKey(criteria, attr); 4584a49301eSmrg if (cmp == EGL_DONT_CARE) 4594a49301eSmrg continue; 4604a49301eSmrg 4613464ebd5Sriastradh val = _eglGetConfigKey(conf, attr); 4624a49301eSmrg switch (_eglValidationTable[i].criterion) { 4634a49301eSmrg case ATTRIB_CRITERION_EXACT: 4644a49301eSmrg if (val != cmp) 4654a49301eSmrg matched = EGL_FALSE; 4664a49301eSmrg break; 4674a49301eSmrg case ATTRIB_CRITERION_ATLEAST: 4684a49301eSmrg if (val < cmp) 4694a49301eSmrg matched = EGL_FALSE; 4704a49301eSmrg break; 4714a49301eSmrg case ATTRIB_CRITERION_MASK: 4724a49301eSmrg if ((val & cmp) != cmp) 4734a49301eSmrg matched = EGL_FALSE; 4744a49301eSmrg break; 4754a49301eSmrg case ATTRIB_CRITERION_SPECIAL: 4764a49301eSmrg /* ignored here */ 4774a49301eSmrg break; 47801e04c3fSmrg case ATTRIB_CRITERION_IGNORE: 47901e04c3fSmrg unreachable("already handled above"); 4804a49301eSmrg break; 4814a49301eSmrg } 4824a49301eSmrg 483cdc920a0Smrg if (!matched) { 4843464ebd5Sriastradh#ifndef DEBUG 4853464ebd5Sriastradh /* only print the common errors when DEBUG is not defined */ 4863464ebd5Sriastradh if (attr != EGL_RENDERABLE_TYPE) 4873464ebd5Sriastradh break; 4883464ebd5Sriastradh#endif 489cdc920a0Smrg _eglLog(_EGL_DEBUG, 490cdc920a0Smrg "the value (0x%x) of attribute 0x%04x did not meet the criteria (0x%x)", 491cdc920a0Smrg val, attr, cmp); 4924a49301eSmrg break; 493cdc920a0Smrg } 4944a49301eSmrg } 4954a49301eSmrg 4964a49301eSmrg return matched; 4974a49301eSmrg} 4984a49301eSmrg 49901e04c3fSmrgstatic inline EGLBoolean 5003464ebd5Sriastradh_eglIsConfigAttribValid(_EGLConfig *conf, EGLint attr) 5013464ebd5Sriastradh{ 5023464ebd5Sriastradh if (_eglOffsetOfConfig(attr) < 0) 5033464ebd5Sriastradh return EGL_FALSE; 5043464ebd5Sriastradh 5053464ebd5Sriastradh switch (attr) { 5063464ebd5Sriastradh case EGL_Y_INVERTED_NOK: 5073464ebd5Sriastradh return conf->Display->Extensions.NOK_texture_from_pixmap; 50801e04c3fSmrg case EGL_FRAMEBUFFER_TARGET_ANDROID: 50901e04c3fSmrg return conf->Display->Extensions.ANDROID_framebuffer_target; 51001e04c3fSmrg case EGL_RECORDABLE_ANDROID: 51101e04c3fSmrg return conf->Display->Extensions.ANDROID_recordable; 5123464ebd5Sriastradh default: 5133464ebd5Sriastradh break; 5143464ebd5Sriastradh } 5153464ebd5Sriastradh 5163464ebd5Sriastradh return EGL_TRUE; 5173464ebd5Sriastradh} 5184a49301eSmrg 5194a49301eSmrg/** 5204a49301eSmrg * Initialize a criteria config from the given attribute list. 5214a49301eSmrg * Return EGL_FALSE if any of the attribute is invalid. 5224a49301eSmrg */ 5234a49301eSmrgEGLBoolean 5243464ebd5Sriastradh_eglParseConfigAttribList(_EGLConfig *conf, _EGLDisplay *dpy, 5253464ebd5Sriastradh const EGLint *attrib_list) 5264a49301eSmrg{ 5274a49301eSmrg EGLint attr, val, i; 5283464ebd5Sriastradh 5293464ebd5Sriastradh _eglInitConfig(conf, dpy, EGL_DONT_CARE); 5304a49301eSmrg 5314a49301eSmrg /* reset to default values */ 5324a49301eSmrg for (i = 0; i < ARRAY_SIZE(_eglValidationTable); i++) { 5334a49301eSmrg attr = _eglValidationTable[i].attr; 5344a49301eSmrg val = _eglValidationTable[i].default_value; 5353464ebd5Sriastradh _eglSetConfigKey(conf, attr, val); 5364a49301eSmrg } 5374a49301eSmrg 5384a49301eSmrg /* parse the list */ 5394a49301eSmrg for (i = 0; attrib_list && attrib_list[i] != EGL_NONE; i += 2) { 5404a49301eSmrg attr = attrib_list[i]; 5414a49301eSmrg val = attrib_list[i + 1]; 5424a49301eSmrg 5433464ebd5Sriastradh if (!_eglIsConfigAttribValid(conf, attr)) 54401e04c3fSmrg return EGL_FALSE; 5454a49301eSmrg 5463464ebd5Sriastradh _eglSetConfigKey(conf, attr, val); 5474a49301eSmrg } 5484a49301eSmrg 5494a49301eSmrg if (!_eglValidateConfig(conf, EGL_TRUE)) 5504a49301eSmrg return EGL_FALSE; 5514a49301eSmrg 552af69d88dSmrg /* EGL_LEVEL and EGL_MATCH_NATIVE_PIXMAP cannot be EGL_DONT_CARE */ 553af69d88dSmrg if (conf->Level == EGL_DONT_CARE || 554af69d88dSmrg conf->MatchNativePixmap == EGL_DONT_CARE) 5554a49301eSmrg return EGL_FALSE; 5564a49301eSmrg 5574a49301eSmrg /* ignore other attributes when EGL_CONFIG_ID is given */ 5583464ebd5Sriastradh if (conf->ConfigID != EGL_DONT_CARE) { 5593464ebd5Sriastradh for (i = 0; i < ARRAY_SIZE(_eglValidationTable); i++) { 5603464ebd5Sriastradh attr = _eglValidationTable[i].attr; 5613464ebd5Sriastradh if (attr != EGL_CONFIG_ID) 5623464ebd5Sriastradh _eglSetConfigKey(conf, attr, EGL_DONT_CARE); 5633464ebd5Sriastradh } 5644a49301eSmrg } 5654a49301eSmrg else { 5663464ebd5Sriastradh if (!(conf->SurfaceType & EGL_WINDOW_BIT)) 5673464ebd5Sriastradh conf->NativeVisualType = EGL_DONT_CARE; 5684a49301eSmrg 5693464ebd5Sriastradh if (conf->TransparentType == EGL_NONE) { 5703464ebd5Sriastradh conf->TransparentRedValue = EGL_DONT_CARE; 5713464ebd5Sriastradh conf->TransparentGreenValue = EGL_DONT_CARE; 5723464ebd5Sriastradh conf->TransparentBlueValue = EGL_DONT_CARE; 5734a49301eSmrg } 5744a49301eSmrg } 5754a49301eSmrg 5764a49301eSmrg return EGL_TRUE; 5774a49301eSmrg} 5784a49301eSmrg 5794a49301eSmrg 5804a49301eSmrg/** 5814a49301eSmrg * Decide the ordering of conf1 and conf2, under the given criteria. 5824a49301eSmrg * When compare_id is true, this implements the algorithm described 5834a49301eSmrg * in "Sorting of EGLConfigs". When compare_id is false, 5844a49301eSmrg * EGL_CONFIG_ID is not compared. 5854a49301eSmrg * 5864a49301eSmrg * It returns a negative integer if conf1 is considered to come 5874a49301eSmrg * before conf2; a positive integer if conf2 is considered to come 5884a49301eSmrg * before conf1; zero if the ordering cannot be decided. 5894a49301eSmrg * 5904a49301eSmrg * Note that EGL_NATIVE_VISUAL_TYPE is platform-dependent and is 5914a49301eSmrg * ignored here. 5924a49301eSmrg */ 5934a49301eSmrgEGLint 5944a49301eSmrg_eglCompareConfigs(const _EGLConfig *conf1, const _EGLConfig *conf2, 5954a49301eSmrg const _EGLConfig *criteria, EGLBoolean compare_id) 5964a49301eSmrg{ 5974a49301eSmrg const EGLint compare_attribs[] = { 5984a49301eSmrg EGL_BUFFER_SIZE, 5994a49301eSmrg EGL_SAMPLE_BUFFERS, 6004a49301eSmrg EGL_SAMPLES, 6014a49301eSmrg EGL_DEPTH_SIZE, 6024a49301eSmrg EGL_STENCIL_SIZE, 6034a49301eSmrg EGL_ALPHA_MASK_SIZE, 6044a49301eSmrg }; 6054a49301eSmrg EGLint val1, val2; 6064a49301eSmrg EGLint i; 6074a49301eSmrg 6084a49301eSmrg if (conf1 == conf2) 6094a49301eSmrg return 0; 6104a49301eSmrg 6114a49301eSmrg /* the enum values have the desired ordering */ 61201e04c3fSmrg STATIC_ASSERT(EGL_NONE < EGL_SLOW_CONFIG); 61301e04c3fSmrg STATIC_ASSERT(EGL_SLOW_CONFIG < EGL_NON_CONFORMANT_CONFIG); 6143464ebd5Sriastradh val1 = conf1->ConfigCaveat - conf2->ConfigCaveat; 6153464ebd5Sriastradh if (val1) 6163464ebd5Sriastradh return val1; 6174a49301eSmrg 6184a49301eSmrg /* the enum values have the desired ordering */ 61901e04c3fSmrg STATIC_ASSERT(EGL_RGB_BUFFER < EGL_LUMINANCE_BUFFER); 6203464ebd5Sriastradh val1 = conf1->ColorBufferType - conf2->ColorBufferType; 6213464ebd5Sriastradh if (val1) 6223464ebd5Sriastradh return val1; 6234a49301eSmrg 6244a49301eSmrg if (criteria) { 6254a49301eSmrg val1 = val2 = 0; 6263464ebd5Sriastradh if (conf1->ColorBufferType == EGL_RGB_BUFFER) { 6273464ebd5Sriastradh if (criteria->RedSize > 0) { 6283464ebd5Sriastradh val1 += conf1->RedSize; 6293464ebd5Sriastradh val2 += conf2->RedSize; 6304a49301eSmrg } 6313464ebd5Sriastradh if (criteria->GreenSize > 0) { 6323464ebd5Sriastradh val1 += conf1->GreenSize; 6333464ebd5Sriastradh val2 += conf2->GreenSize; 6344a49301eSmrg } 6353464ebd5Sriastradh if (criteria->BlueSize > 0) { 6363464ebd5Sriastradh val1 += conf1->BlueSize; 6373464ebd5Sriastradh val2 += conf2->BlueSize; 6384a49301eSmrg } 6394a49301eSmrg } 6404a49301eSmrg else { 6413464ebd5Sriastradh if (criteria->LuminanceSize > 0) { 6423464ebd5Sriastradh val1 += conf1->LuminanceSize; 6433464ebd5Sriastradh val2 += conf2->LuminanceSize; 6444a49301eSmrg } 6454a49301eSmrg } 6463464ebd5Sriastradh if (criteria->AlphaSize > 0) { 6473464ebd5Sriastradh val1 += conf1->AlphaSize; 6483464ebd5Sriastradh val2 += conf2->AlphaSize; 6494a49301eSmrg } 6504a49301eSmrg } 6514a49301eSmrg else { 6524a49301eSmrg /* assume the default criteria, which gives no specific ordering */ 6534a49301eSmrg val1 = val2 = 0; 6544a49301eSmrg } 6554a49301eSmrg 6564a49301eSmrg /* for color bits, larger one is preferred */ 6574a49301eSmrg if (val1 != val2) 6584a49301eSmrg return (val2 - val1); 6594a49301eSmrg 6604a49301eSmrg for (i = 0; i < ARRAY_SIZE(compare_attribs); i++) { 6613464ebd5Sriastradh val1 = _eglGetConfigKey(conf1, compare_attribs[i]); 6623464ebd5Sriastradh val2 = _eglGetConfigKey(conf2, compare_attribs[i]); 6634a49301eSmrg if (val1 != val2) 6644a49301eSmrg return (val1 - val2); 6654a49301eSmrg } 6664a49301eSmrg 6674a49301eSmrg /* EGL_NATIVE_VISUAL_TYPE cannot be compared here */ 6684a49301eSmrg 6693464ebd5Sriastradh return (compare_id) ? (conf1->ConfigID - conf2->ConfigID) : 0; 6704a49301eSmrg} 6714a49301eSmrg 6724a49301eSmrg 67301e04c3fSmrgstatic inline 6744a49301eSmrgvoid _eglSwapConfigs(const _EGLConfig **conf1, const _EGLConfig **conf2) 6754a49301eSmrg{ 6764a49301eSmrg const _EGLConfig *tmp = *conf1; 6774a49301eSmrg *conf1 = *conf2; 6784a49301eSmrg *conf2 = tmp; 6794a49301eSmrg} 6804a49301eSmrg 6814a49301eSmrg 6824a49301eSmrg/** 6834a49301eSmrg * Quick sort an array of configs. This differs from the standard 6844a49301eSmrg * qsort() in that the compare function accepts an additional 6854a49301eSmrg * argument. 6864a49301eSmrg */ 687af69d88dSmrgstatic void 6884a49301eSmrg_eglSortConfigs(const _EGLConfig **configs, EGLint count, 6894a49301eSmrg EGLint (*compare)(const _EGLConfig *, const _EGLConfig *, 6904a49301eSmrg void *), 6914a49301eSmrg void *priv_data) 6924a49301eSmrg{ 6934a49301eSmrg const EGLint pivot = 0; 6944a49301eSmrg EGLint i, j; 6954a49301eSmrg 6964a49301eSmrg if (count <= 1) 6974a49301eSmrg return; 6984a49301eSmrg 6994a49301eSmrg _eglSwapConfigs(&configs[pivot], &configs[count / 2]); 7004a49301eSmrg i = 1; 7014a49301eSmrg j = count - 1; 7024a49301eSmrg do { 7034a49301eSmrg while (i < count && compare(configs[i], configs[pivot], priv_data) < 0) 7044a49301eSmrg i++; 7054a49301eSmrg while (compare(configs[j], configs[pivot], priv_data) > 0) 7064a49301eSmrg j--; 7074a49301eSmrg if (i < j) { 7084a49301eSmrg _eglSwapConfigs(&configs[i], &configs[j]); 7094a49301eSmrg i++; 7104a49301eSmrg j--; 7114a49301eSmrg } 7124a49301eSmrg else if (i == j) { 7134a49301eSmrg i++; 7144a49301eSmrg j--; 7154a49301eSmrg break; 7164a49301eSmrg } 7174a49301eSmrg } while (i <= j); 7184a49301eSmrg _eglSwapConfigs(&configs[pivot], &configs[j]); 7194a49301eSmrg 7204a49301eSmrg _eglSortConfigs(configs, j, compare, priv_data); 7214a49301eSmrg _eglSortConfigs(configs + i, count - i, compare, priv_data); 7224a49301eSmrg} 7234a49301eSmrg 7244a49301eSmrg 7254a49301eSmrg/** 726af69d88dSmrg * A helper function for implementing eglChooseConfig. See _eglFilterArray and 727af69d88dSmrg * _eglSortConfigs for the meanings of match and compare. 7284a49301eSmrg */ 7294a49301eSmrgEGLBoolean 730af69d88dSmrg_eglFilterConfigArray(_EGLArray *array, EGLConfig *configs, 731af69d88dSmrg EGLint config_size, EGLint *num_configs, 732af69d88dSmrg EGLBoolean (*match)(const _EGLConfig *, void *), 733af69d88dSmrg EGLint (*compare)(const _EGLConfig *, const _EGLConfig *, 734af69d88dSmrg void *), 735af69d88dSmrg void *priv_data) 7364a49301eSmrg{ 737af69d88dSmrg _EGLConfig **configList; 7384a49301eSmrg EGLint i, count; 7394a49301eSmrg 7404a49301eSmrg if (!num_configs) 74101e04c3fSmrg return _eglError(EGL_BAD_PARAMETER, "eglChooseConfig"); 7424a49301eSmrg 7433464ebd5Sriastradh /* get the number of matched configs */ 744af69d88dSmrg count = _eglFilterArray(array, NULL, 0, 745af69d88dSmrg (_EGLArrayForEach) match, priv_data); 7463464ebd5Sriastradh if (!count) { 7473464ebd5Sriastradh *num_configs = count; 7483464ebd5Sriastradh return EGL_TRUE; 7493464ebd5Sriastradh } 7503464ebd5Sriastradh 7513464ebd5Sriastradh configList = malloc(sizeof(*configList) * count); 7524a49301eSmrg if (!configList) 7534a49301eSmrg return _eglError(EGL_BAD_ALLOC, "eglChooseConfig(out of memory)"); 7544a49301eSmrg 7553464ebd5Sriastradh /* get the matched configs */ 756af69d88dSmrg _eglFilterArray(array, (void **) configList, count, 757af69d88dSmrg (_EGLArrayForEach) match, priv_data); 7584a49301eSmrg 7594a49301eSmrg /* perform sorting of configs */ 7604a49301eSmrg if (configs && count) { 7614a49301eSmrg _eglSortConfigs((const _EGLConfig **) configList, count, 762af69d88dSmrg compare, priv_data); 7634a49301eSmrg count = MIN2(count, config_size); 7644a49301eSmrg for (i = 0; i < count; i++) 7654a49301eSmrg configs[i] = _eglGetConfigHandle(configList[i]); 7664a49301eSmrg } 7674a49301eSmrg 7684a49301eSmrg free(configList); 7694a49301eSmrg 7704a49301eSmrg *num_configs = count; 7714a49301eSmrg 7724a49301eSmrg return EGL_TRUE; 7734a49301eSmrg} 7744a49301eSmrg 7754a49301eSmrg 776af69d88dSmrgstatic EGLBoolean 777af69d88dSmrg_eglFallbackMatch(const _EGLConfig *conf, void *priv_data) 778af69d88dSmrg{ 779af69d88dSmrg return _eglMatchConfig(conf, (const _EGLConfig *) priv_data); 780af69d88dSmrg} 781af69d88dSmrg 782af69d88dSmrg 783af69d88dSmrgstatic EGLint 784af69d88dSmrg_eglFallbackCompare(const _EGLConfig *conf1, const _EGLConfig *conf2, 785af69d88dSmrg void *priv_data) 786af69d88dSmrg{ 787af69d88dSmrg return _eglCompareConfigs(conf1, conf2, 788af69d88dSmrg (const _EGLConfig *) priv_data, EGL_TRUE); 789af69d88dSmrg} 790af69d88dSmrg 791af69d88dSmrg 792af69d88dSmrg/** 793af69d88dSmrg * Typical fallback routine for eglChooseConfig 794af69d88dSmrg */ 795af69d88dSmrgEGLBoolean 796af69d88dSmrg_eglChooseConfig(_EGLDriver *drv, _EGLDisplay *disp, const EGLint *attrib_list, 797af69d88dSmrg EGLConfig *configs, EGLint config_size, EGLint *num_configs) 798af69d88dSmrg{ 799af69d88dSmrg _EGLConfig criteria; 800af69d88dSmrg 801af69d88dSmrg if (!_eglParseConfigAttribList(&criteria, disp, attrib_list)) 802af69d88dSmrg return _eglError(EGL_BAD_ATTRIBUTE, "eglChooseConfig"); 803af69d88dSmrg 804af69d88dSmrg return _eglFilterConfigArray(disp->Configs, 805af69d88dSmrg configs, config_size, num_configs, 806af69d88dSmrg _eglFallbackMatch, _eglFallbackCompare, 807af69d88dSmrg (void *) &criteria); 808af69d88dSmrg} 809af69d88dSmrg 810af69d88dSmrg 8114a49301eSmrg/** 8124a49301eSmrg * Fallback for eglGetConfigAttrib. 8134a49301eSmrg */ 8144a49301eSmrgEGLBoolean 8154a49301eSmrg_eglGetConfigAttrib(_EGLDriver *drv, _EGLDisplay *dpy, _EGLConfig *conf, 8164a49301eSmrg EGLint attribute, EGLint *value) 8174a49301eSmrg{ 8184a49301eSmrg if (!_eglIsConfigAttribValid(conf, attribute)) 8194a49301eSmrg return _eglError(EGL_BAD_ATTRIBUTE, "eglGetConfigAttrib"); 8203464ebd5Sriastradh 8213464ebd5Sriastradh /* nonqueryable attributes */ 8223464ebd5Sriastradh switch (attribute) { 8233464ebd5Sriastradh case EGL_MATCH_NATIVE_PIXMAP: 8243464ebd5Sriastradh return _eglError(EGL_BAD_ATTRIBUTE, "eglGetConfigAttrib"); 8253464ebd5Sriastradh break; 8263464ebd5Sriastradh default: 8273464ebd5Sriastradh break; 8283464ebd5Sriastradh } 8293464ebd5Sriastradh 8304a49301eSmrg if (!value) 8314a49301eSmrg return _eglError(EGL_BAD_PARAMETER, "eglGetConfigAttrib"); 8324a49301eSmrg 8333464ebd5Sriastradh *value = _eglGetConfigKey(conf, attribute); 8344a49301eSmrg return EGL_TRUE; 8354a49301eSmrg} 8364a49301eSmrg 8374a49301eSmrg 8383464ebd5Sriastradhstatic EGLBoolean 8393464ebd5Sriastradh_eglFlattenConfig(void *elem, void *buffer) 8403464ebd5Sriastradh{ 8413464ebd5Sriastradh _EGLConfig *conf = (_EGLConfig *) elem; 8423464ebd5Sriastradh EGLConfig *handle = (EGLConfig *) buffer; 8433464ebd5Sriastradh *handle = _eglGetConfigHandle(conf); 8443464ebd5Sriastradh return EGL_TRUE; 8453464ebd5Sriastradh} 8463464ebd5Sriastradh 8474a49301eSmrg/** 8484a49301eSmrg * Fallback for eglGetConfigs. 8494a49301eSmrg */ 8504a49301eSmrgEGLBoolean 8514a49301eSmrg_eglGetConfigs(_EGLDriver *drv, _EGLDisplay *disp, EGLConfig *configs, 8524a49301eSmrg EGLint config_size, EGLint *num_config) 8534a49301eSmrg{ 8544a49301eSmrg if (!num_config) 8554a49301eSmrg return _eglError(EGL_BAD_PARAMETER, "eglGetConfigs"); 8564a49301eSmrg 8573464ebd5Sriastradh *num_config = _eglFlattenArray(disp->Configs, (void *) configs, 8583464ebd5Sriastradh sizeof(configs[0]), config_size, _eglFlattenConfig); 8594a49301eSmrg 8604a49301eSmrg return EGL_TRUE; 8614a49301eSmrg} 862