eglconfig.c revision 4a49301e
14a49301eSmrg/** 24a49301eSmrg * EGL Configuration (pixel format) functions. 34a49301eSmrg */ 44a49301eSmrg 54a49301eSmrg 64a49301eSmrg#include <stdlib.h> 74a49301eSmrg#include <stdio.h> 84a49301eSmrg#include <string.h> 94a49301eSmrg#include <assert.h> 104a49301eSmrg#include "eglconfig.h" 114a49301eSmrg#include "egldisplay.h" 124a49301eSmrg#include "egldriver.h" 134a49301eSmrg#include "eglglobals.h" 144a49301eSmrg#include "egllog.h" 154a49301eSmrg 164a49301eSmrg 174a49301eSmrg#define MIN2(A, B) (((A) < (B)) ? (A) : (B)) 184a49301eSmrg#define ARRAY_SIZE(a) (sizeof(a) / sizeof((a)[0])) 194a49301eSmrg 204a49301eSmrg 214a49301eSmrg/** 224a49301eSmrg * Init the given _EGLconfig to default values. 234a49301eSmrg * \param id the configuration's ID. 244a49301eSmrg * 254a49301eSmrg * Note that id must be positive for the config to be valid. 264a49301eSmrg * It is also recommended that when there are N configs, their 274a49301eSmrg * IDs are from 1 to N respectively. 284a49301eSmrg */ 294a49301eSmrgvoid 304a49301eSmrg_eglInitConfig(_EGLConfig *config, EGLint id) 314a49301eSmrg{ 324a49301eSmrg memset(config, 0, sizeof(*config)); 334a49301eSmrg 344a49301eSmrg /* some attributes take non-zero default values */ 354a49301eSmrg SET_CONFIG_ATTRIB(config, EGL_CONFIG_ID, id); 364a49301eSmrg SET_CONFIG_ATTRIB(config, EGL_CONFIG_CAVEAT, EGL_NONE); 374a49301eSmrg SET_CONFIG_ATTRIB(config, EGL_TRANSPARENT_TYPE, EGL_NONE); 384a49301eSmrg SET_CONFIG_ATTRIB(config, EGL_NATIVE_VISUAL_TYPE, EGL_NONE); 394a49301eSmrg#ifdef EGL_VERSION_1_2 404a49301eSmrg SET_CONFIG_ATTRIB(config, EGL_COLOR_BUFFER_TYPE, EGL_RGB_BUFFER); 414a49301eSmrg#endif /* EGL_VERSION_1_2 */ 424a49301eSmrg} 434a49301eSmrg 444a49301eSmrg 454a49301eSmrg/** 464a49301eSmrg * Link a config to a display and return the handle of the link. 474a49301eSmrg * The handle can be passed to client directly. 484a49301eSmrg * 494a49301eSmrg * Note that we just save the ptr to the config (we don't copy the config). 504a49301eSmrg */ 514a49301eSmrgEGLConfig 524a49301eSmrg_eglAddConfig(_EGLDisplay *dpy, _EGLConfig *conf) 534a49301eSmrg{ 544a49301eSmrg _EGLConfig **configs; 554a49301eSmrg 564a49301eSmrg /* sanity check */ 574a49301eSmrg assert(GET_CONFIG_ATTRIB(conf, EGL_CONFIG_ID) > 0); 584a49301eSmrg 594a49301eSmrg configs = dpy->Configs; 604a49301eSmrg if (dpy->NumConfigs >= dpy->MaxConfigs) { 614a49301eSmrg EGLint new_size = dpy->MaxConfigs + 16; 624a49301eSmrg assert(dpy->NumConfigs < new_size); 634a49301eSmrg 644a49301eSmrg configs = realloc(dpy->Configs, new_size * sizeof(dpy->Configs[0])); 654a49301eSmrg if (!configs) 664a49301eSmrg return (EGLConfig) NULL; 674a49301eSmrg 684a49301eSmrg dpy->Configs = configs; 694a49301eSmrg dpy->MaxConfigs = new_size; 704a49301eSmrg } 714a49301eSmrg 724a49301eSmrg conf->Display = dpy; 734a49301eSmrg dpy->Configs[dpy->NumConfigs++] = conf; 744a49301eSmrg 754a49301eSmrg return (EGLConfig) conf; 764a49301eSmrg} 774a49301eSmrg 784a49301eSmrg 794a49301eSmrg#ifndef _EGL_SKIP_HANDLE_CHECK 804a49301eSmrg 814a49301eSmrg 824a49301eSmrgEGLBoolean 834a49301eSmrg_eglCheckConfigHandle(EGLConfig config, _EGLDisplay *dpy) 844a49301eSmrg{ 854a49301eSmrg EGLint num_configs = (dpy) ? dpy->NumConfigs : 0; 864a49301eSmrg EGLint i; 874a49301eSmrg 884a49301eSmrg for (i = 0; i < num_configs; i++) { 894a49301eSmrg _EGLConfig *conf = dpy->Configs[i]; 904a49301eSmrg if (conf == (_EGLConfig *) config) { 914a49301eSmrg assert(conf->Display == dpy); 924a49301eSmrg break; 934a49301eSmrg } 944a49301eSmrg } 954a49301eSmrg return (i < num_configs); 964a49301eSmrg} 974a49301eSmrg 984a49301eSmrg 994a49301eSmrg#endif /* _EGL_SKIP_HANDLE_CHECK */ 1004a49301eSmrg 1014a49301eSmrg 1024a49301eSmrgenum { 1034a49301eSmrg /* types */ 1044a49301eSmrg ATTRIB_TYPE_INTEGER, 1054a49301eSmrg ATTRIB_TYPE_BOOLEAN, 1064a49301eSmrg ATTRIB_TYPE_BITMASK, 1074a49301eSmrg ATTRIB_TYPE_ENUM, 1084a49301eSmrg ATTRIB_TYPE_PSEUDO, /* non-queryable */ 1094a49301eSmrg ATTRIB_TYPE_PLATFORM, /* platform-dependent */ 1104a49301eSmrg /* criteria */ 1114a49301eSmrg ATTRIB_CRITERION_EXACT, 1124a49301eSmrg ATTRIB_CRITERION_ATLEAST, 1134a49301eSmrg ATTRIB_CRITERION_MASK, 1144a49301eSmrg ATTRIB_CRITERION_SPECIAL, 1154a49301eSmrg ATTRIB_CRITERION_IGNORE, 1164a49301eSmrg}; 1174a49301eSmrg 1184a49301eSmrg 1194a49301eSmrg/* EGL spec Table 3.1 and 3.4 */ 1204a49301eSmrgstatic const struct { 1214a49301eSmrg EGLint attr; 1224a49301eSmrg EGLint type; 1234a49301eSmrg EGLint criterion; 1244a49301eSmrg EGLint default_value; 1254a49301eSmrg} _eglValidationTable[] = 1264a49301eSmrg{ 1274a49301eSmrg { EGL_BUFFER_SIZE, ATTRIB_TYPE_INTEGER, 1284a49301eSmrg ATTRIB_CRITERION_ATLEAST, 1294a49301eSmrg 0 }, 1304a49301eSmrg { EGL_RED_SIZE, ATTRIB_TYPE_INTEGER, 1314a49301eSmrg ATTRIB_CRITERION_ATLEAST, 1324a49301eSmrg 0 }, 1334a49301eSmrg { EGL_GREEN_SIZE, ATTRIB_TYPE_INTEGER, 1344a49301eSmrg ATTRIB_CRITERION_ATLEAST, 1354a49301eSmrg 0 }, 1364a49301eSmrg { EGL_BLUE_SIZE, ATTRIB_TYPE_INTEGER, 1374a49301eSmrg ATTRIB_CRITERION_ATLEAST, 1384a49301eSmrg 0 }, 1394a49301eSmrg { EGL_LUMINANCE_SIZE, ATTRIB_TYPE_INTEGER, 1404a49301eSmrg ATTRIB_CRITERION_ATLEAST, 1414a49301eSmrg 0 }, 1424a49301eSmrg { EGL_ALPHA_SIZE, ATTRIB_TYPE_INTEGER, 1434a49301eSmrg ATTRIB_CRITERION_ATLEAST, 1444a49301eSmrg 0 }, 1454a49301eSmrg { EGL_ALPHA_MASK_SIZE, ATTRIB_TYPE_INTEGER, 1464a49301eSmrg ATTRIB_CRITERION_ATLEAST, 1474a49301eSmrg 0 }, 1484a49301eSmrg { EGL_BIND_TO_TEXTURE_RGB, ATTRIB_TYPE_BOOLEAN, 1494a49301eSmrg ATTRIB_CRITERION_EXACT, 1504a49301eSmrg EGL_DONT_CARE }, 1514a49301eSmrg { EGL_BIND_TO_TEXTURE_RGBA, ATTRIB_TYPE_BOOLEAN, 1524a49301eSmrg ATTRIB_CRITERION_EXACT, 1534a49301eSmrg EGL_DONT_CARE }, 1544a49301eSmrg { EGL_COLOR_BUFFER_TYPE, ATTRIB_TYPE_ENUM, 1554a49301eSmrg ATTRIB_CRITERION_EXACT, 1564a49301eSmrg EGL_RGB_BUFFER }, 1574a49301eSmrg { EGL_CONFIG_CAVEAT, ATTRIB_TYPE_ENUM, 1584a49301eSmrg ATTRIB_CRITERION_EXACT, 1594a49301eSmrg EGL_DONT_CARE }, 1604a49301eSmrg { EGL_CONFIG_ID, ATTRIB_TYPE_INTEGER, 1614a49301eSmrg ATTRIB_CRITERION_EXACT, 1624a49301eSmrg EGL_DONT_CARE }, 1634a49301eSmrg { EGL_CONFORMANT, ATTRIB_TYPE_BITMASK, 1644a49301eSmrg ATTRIB_CRITERION_MASK, 1654a49301eSmrg 0 }, 1664a49301eSmrg { EGL_DEPTH_SIZE, ATTRIB_TYPE_INTEGER, 1674a49301eSmrg ATTRIB_CRITERION_ATLEAST, 1684a49301eSmrg 0 }, 1694a49301eSmrg { EGL_LEVEL, ATTRIB_TYPE_PLATFORM, 1704a49301eSmrg ATTRIB_CRITERION_EXACT, 1714a49301eSmrg 0 }, 1724a49301eSmrg { EGL_MAX_PBUFFER_WIDTH, ATTRIB_TYPE_INTEGER, 1734a49301eSmrg ATTRIB_CRITERION_IGNORE, 1744a49301eSmrg 0 }, 1754a49301eSmrg { EGL_MAX_PBUFFER_HEIGHT, ATTRIB_TYPE_INTEGER, 1764a49301eSmrg ATTRIB_CRITERION_IGNORE, 1774a49301eSmrg 0 }, 1784a49301eSmrg { EGL_MAX_PBUFFER_PIXELS, ATTRIB_TYPE_INTEGER, 1794a49301eSmrg ATTRIB_CRITERION_IGNORE, 1804a49301eSmrg 0 }, 1814a49301eSmrg { EGL_MAX_SWAP_INTERVAL, ATTRIB_TYPE_INTEGER, 1824a49301eSmrg ATTRIB_CRITERION_EXACT, 1834a49301eSmrg EGL_DONT_CARE }, 1844a49301eSmrg { EGL_MIN_SWAP_INTERVAL, ATTRIB_TYPE_INTEGER, 1854a49301eSmrg ATTRIB_CRITERION_EXACT, 1864a49301eSmrg EGL_DONT_CARE }, 1874a49301eSmrg { EGL_NATIVE_RENDERABLE, ATTRIB_TYPE_BOOLEAN, 1884a49301eSmrg ATTRIB_CRITERION_EXACT, 1894a49301eSmrg EGL_DONT_CARE }, 1904a49301eSmrg { EGL_NATIVE_VISUAL_ID, ATTRIB_TYPE_PLATFORM, 1914a49301eSmrg ATTRIB_CRITERION_IGNORE, 1924a49301eSmrg 0 }, 1934a49301eSmrg { EGL_NATIVE_VISUAL_TYPE, ATTRIB_TYPE_PLATFORM, 1944a49301eSmrg ATTRIB_CRITERION_EXACT, 1954a49301eSmrg EGL_DONT_CARE }, 1964a49301eSmrg { EGL_RENDERABLE_TYPE, ATTRIB_TYPE_BITMASK, 1974a49301eSmrg ATTRIB_CRITERION_MASK, 1984a49301eSmrg EGL_OPENGL_ES_BIT }, 1994a49301eSmrg { EGL_SAMPLE_BUFFERS, ATTRIB_TYPE_INTEGER, 2004a49301eSmrg ATTRIB_CRITERION_ATLEAST, 2014a49301eSmrg 0 }, 2024a49301eSmrg { EGL_SAMPLES, ATTRIB_TYPE_INTEGER, 2034a49301eSmrg ATTRIB_CRITERION_ATLEAST, 2044a49301eSmrg 0 }, 2054a49301eSmrg { EGL_STENCIL_SIZE, ATTRIB_TYPE_INTEGER, 2064a49301eSmrg ATTRIB_CRITERION_ATLEAST, 2074a49301eSmrg 0 }, 2084a49301eSmrg { EGL_SURFACE_TYPE, ATTRIB_TYPE_BITMASK, 2094a49301eSmrg ATTRIB_CRITERION_MASK, 2104a49301eSmrg EGL_WINDOW_BIT }, 2114a49301eSmrg { EGL_TRANSPARENT_TYPE, ATTRIB_TYPE_ENUM, 2124a49301eSmrg ATTRIB_CRITERION_EXACT, 2134a49301eSmrg EGL_NONE }, 2144a49301eSmrg { EGL_TRANSPARENT_RED_VALUE, ATTRIB_TYPE_INTEGER, 2154a49301eSmrg ATTRIB_CRITERION_EXACT, 2164a49301eSmrg EGL_DONT_CARE }, 2174a49301eSmrg { EGL_TRANSPARENT_GREEN_VALUE, ATTRIB_TYPE_INTEGER, 2184a49301eSmrg ATTRIB_CRITERION_EXACT, 2194a49301eSmrg EGL_DONT_CARE }, 2204a49301eSmrg { EGL_TRANSPARENT_BLUE_VALUE, ATTRIB_TYPE_INTEGER, 2214a49301eSmrg ATTRIB_CRITERION_EXACT, 2224a49301eSmrg EGL_DONT_CARE }, 2234a49301eSmrg /* these are not real attributes */ 2244a49301eSmrg { EGL_MATCH_NATIVE_PIXMAP, ATTRIB_TYPE_PSEUDO, 2254a49301eSmrg ATTRIB_CRITERION_SPECIAL, 2264a49301eSmrg EGL_NONE }, 2274a49301eSmrg { EGL_PRESERVED_RESOURCES, ATTRIB_TYPE_PSEUDO, 2284a49301eSmrg ATTRIB_CRITERION_IGNORE, 2294a49301eSmrg 0 }, 2304a49301eSmrg { EGL_NONE, ATTRIB_TYPE_PSEUDO, 2314a49301eSmrg ATTRIB_CRITERION_IGNORE, 2324a49301eSmrg 0 } 2334a49301eSmrg}; 2344a49301eSmrg 2354a49301eSmrg 2364a49301eSmrg/** 2374a49301eSmrg * Return true if a config is valid. When for_matching is true, 2384a49301eSmrg * EGL_DONT_CARE is accepted as a valid attribute value, and checks 2394a49301eSmrg * for conflicting attribute values are skipped. 2404a49301eSmrg * 2414a49301eSmrg * Note that some attributes are platform-dependent and are not 2424a49301eSmrg * checked. 2434a49301eSmrg */ 2444a49301eSmrgEGLBoolean 2454a49301eSmrg_eglValidateConfig(const _EGLConfig *conf, EGLBoolean for_matching) 2464a49301eSmrg{ 2474a49301eSmrg EGLint i, attr, val; 2484a49301eSmrg EGLBoolean valid = EGL_TRUE; 2494a49301eSmrg EGLint red_size = 0, green_size = 0, blue_size = 0, luminance_size = 0; 2504a49301eSmrg EGLint alpha_size = 0, buffer_size = 0; 2514a49301eSmrg 2524a49301eSmrg /* all attributes should have been listed */ 2534a49301eSmrg assert(ARRAY_SIZE(_eglValidationTable) == _EGL_CONFIG_NUM_ATTRIBS); 2544a49301eSmrg 2554a49301eSmrg /* check attributes by their types */ 2564a49301eSmrg for (i = 0; i < ARRAY_SIZE(_eglValidationTable); i++) { 2574a49301eSmrg EGLint mask; 2584a49301eSmrg 2594a49301eSmrg attr = _eglValidationTable[i].attr; 2604a49301eSmrg val = GET_CONFIG_ATTRIB(conf, attr); 2614a49301eSmrg 2624a49301eSmrg switch (_eglValidationTable[i].type) { 2634a49301eSmrg case ATTRIB_TYPE_INTEGER: 2644a49301eSmrg switch (attr) { 2654a49301eSmrg case EGL_CONFIG_ID: 2664a49301eSmrg /* config id must be positive */ 2674a49301eSmrg if (val <= 0) 2684a49301eSmrg valid = EGL_FALSE; 2694a49301eSmrg break; 2704a49301eSmrg case EGL_SAMPLE_BUFFERS: 2714a49301eSmrg /* there can be at most 1 sample buffer */ 2724a49301eSmrg if (val > 1) 2734a49301eSmrg valid = EGL_FALSE; 2744a49301eSmrg break; 2754a49301eSmrg case EGL_RED_SIZE: 2764a49301eSmrg red_size = val; 2774a49301eSmrg break; 2784a49301eSmrg case EGL_GREEN_SIZE: 2794a49301eSmrg green_size = val; 2804a49301eSmrg break; 2814a49301eSmrg case EGL_BLUE_SIZE: 2824a49301eSmrg blue_size = val; 2834a49301eSmrg break; 2844a49301eSmrg case EGL_LUMINANCE_SIZE: 2854a49301eSmrg luminance_size = val; 2864a49301eSmrg break; 2874a49301eSmrg case EGL_ALPHA_SIZE: 2884a49301eSmrg alpha_size = val; 2894a49301eSmrg break; 2904a49301eSmrg case EGL_BUFFER_SIZE: 2914a49301eSmrg buffer_size = val; 2924a49301eSmrg break; 2934a49301eSmrg } 2944a49301eSmrg if (val < 0) 2954a49301eSmrg valid = EGL_FALSE; 2964a49301eSmrg break; 2974a49301eSmrg case ATTRIB_TYPE_BOOLEAN: 2984a49301eSmrg if (val != EGL_TRUE && val != EGL_FALSE) 2994a49301eSmrg valid = EGL_FALSE; 3004a49301eSmrg break; 3014a49301eSmrg case ATTRIB_TYPE_ENUM: 3024a49301eSmrg switch (attr) { 3034a49301eSmrg case EGL_CONFIG_CAVEAT: 3044a49301eSmrg if (val != EGL_NONE && val != EGL_SLOW_CONFIG && 3054a49301eSmrg val != EGL_NON_CONFORMANT_CONFIG) 3064a49301eSmrg valid = EGL_FALSE; 3074a49301eSmrg break; 3084a49301eSmrg case EGL_TRANSPARENT_TYPE: 3094a49301eSmrg if (val != EGL_NONE && val != EGL_TRANSPARENT_RGB) 3104a49301eSmrg valid = EGL_FALSE; 3114a49301eSmrg break; 3124a49301eSmrg case EGL_COLOR_BUFFER_TYPE: 3134a49301eSmrg if (val != EGL_RGB_BUFFER && val != EGL_LUMINANCE_BUFFER) 3144a49301eSmrg valid = EGL_FALSE; 3154a49301eSmrg break; 3164a49301eSmrg default: 3174a49301eSmrg assert(0); 3184a49301eSmrg break; 3194a49301eSmrg } 3204a49301eSmrg break; 3214a49301eSmrg case ATTRIB_TYPE_BITMASK: 3224a49301eSmrg switch (attr) { 3234a49301eSmrg case EGL_SURFACE_TYPE: 3244a49301eSmrg mask = EGL_PBUFFER_BIT | 3254a49301eSmrg EGL_PIXMAP_BIT | 3264a49301eSmrg EGL_WINDOW_BIT | 3274a49301eSmrg EGL_VG_COLORSPACE_LINEAR_BIT | 3284a49301eSmrg EGL_VG_ALPHA_FORMAT_PRE_BIT | 3294a49301eSmrg EGL_MULTISAMPLE_RESOLVE_BOX_BIT | 3304a49301eSmrg EGL_SWAP_BEHAVIOR_PRESERVED_BIT; 3314a49301eSmrg break; 3324a49301eSmrg case EGL_RENDERABLE_TYPE: 3334a49301eSmrg case EGL_CONFORMANT: 3344a49301eSmrg mask = EGL_OPENGL_ES_BIT | 3354a49301eSmrg EGL_OPENVG_BIT | 3364a49301eSmrg EGL_OPENGL_ES2_BIT | 3374a49301eSmrg EGL_OPENGL_BIT; 3384a49301eSmrg break; 3394a49301eSmrg default: 3404a49301eSmrg assert(0); 3414a49301eSmrg break; 3424a49301eSmrg } 3434a49301eSmrg if (val & ~mask) 3444a49301eSmrg valid = EGL_FALSE; 3454a49301eSmrg break; 3464a49301eSmrg case ATTRIB_TYPE_PLATFORM: 3474a49301eSmrg /* unable to check platform-dependent attributes here */ 3484a49301eSmrg break; 3494a49301eSmrg case ATTRIB_TYPE_PSEUDO: 3504a49301eSmrg /* pseudo attributes should not be set */ 3514a49301eSmrg if (val != 0) 3524a49301eSmrg valid = EGL_FALSE; 3534a49301eSmrg break; 3544a49301eSmrg default: 3554a49301eSmrg assert(0); 3564a49301eSmrg break; 3574a49301eSmrg } 3584a49301eSmrg 3594a49301eSmrg if (!valid && for_matching) { 3604a49301eSmrg /* accept EGL_DONT_CARE as a valid value */ 3614a49301eSmrg if (val == EGL_DONT_CARE) 3624a49301eSmrg valid = EGL_TRUE; 3634a49301eSmrg if (_eglValidationTable[i].criterion == ATTRIB_CRITERION_SPECIAL) 3644a49301eSmrg valid = EGL_TRUE; 3654a49301eSmrg } 3664a49301eSmrg if (!valid) 3674a49301eSmrg break; 3684a49301eSmrg } 3694a49301eSmrg 3704a49301eSmrg /* any invalid attribute value should have been catched */ 3714a49301eSmrg if (!valid || for_matching) 3724a49301eSmrg return valid; 3734a49301eSmrg 3744a49301eSmrg /* now check for conflicting attribute values */ 3754a49301eSmrg 3764a49301eSmrg switch (GET_CONFIG_ATTRIB(conf, EGL_COLOR_BUFFER_TYPE)) { 3774a49301eSmrg case EGL_RGB_BUFFER: 3784a49301eSmrg if (luminance_size) 3794a49301eSmrg valid = EGL_FALSE; 3804a49301eSmrg if (red_size + green_size + blue_size + alpha_size != buffer_size) 3814a49301eSmrg valid = EGL_FALSE; 3824a49301eSmrg break; 3834a49301eSmrg case EGL_LUMINANCE_BUFFER: 3844a49301eSmrg if (red_size || green_size || blue_size) 3854a49301eSmrg valid = EGL_FALSE; 3864a49301eSmrg if (luminance_size + alpha_size != buffer_size) 3874a49301eSmrg valid = EGL_FALSE; 3884a49301eSmrg break; 3894a49301eSmrg } 3904a49301eSmrg 3914a49301eSmrg val = GET_CONFIG_ATTRIB(conf, EGL_SAMPLE_BUFFERS); 3924a49301eSmrg if (!val && GET_CONFIG_ATTRIB(conf, EGL_SAMPLES)) 3934a49301eSmrg valid = EGL_FALSE; 3944a49301eSmrg 3954a49301eSmrg val = GET_CONFIG_ATTRIB(conf, EGL_SURFACE_TYPE); 3964a49301eSmrg if (!(val & EGL_WINDOW_BIT)) { 3974a49301eSmrg if (GET_CONFIG_ATTRIB(conf, EGL_NATIVE_VISUAL_ID) != 0 || 3984a49301eSmrg GET_CONFIG_ATTRIB(conf, EGL_NATIVE_VISUAL_TYPE) != EGL_NONE) 3994a49301eSmrg valid = EGL_FALSE; 4004a49301eSmrg } 4014a49301eSmrg if (!(val & EGL_PBUFFER_BIT)) { 4024a49301eSmrg if (GET_CONFIG_ATTRIB(conf, EGL_BIND_TO_TEXTURE_RGB) || 4034a49301eSmrg GET_CONFIG_ATTRIB(conf, EGL_BIND_TO_TEXTURE_RGBA)) 4044a49301eSmrg valid = EGL_FALSE; 4054a49301eSmrg } 4064a49301eSmrg 4074a49301eSmrg return valid; 4084a49301eSmrg} 4094a49301eSmrg 4104a49301eSmrg 4114a49301eSmrg/** 4124a49301eSmrg * Return true if a config matches the criteria. This and 4134a49301eSmrg * _eglParseConfigAttribList together implement the algorithm 4144a49301eSmrg * described in "Selection of EGLConfigs". 4154a49301eSmrg * 4164a49301eSmrg * Note that attributes that are special (currently, only 4174a49301eSmrg * EGL_MATCH_NATIVE_PIXMAP) are ignored. 4184a49301eSmrg */ 4194a49301eSmrgEGLBoolean 4204a49301eSmrg_eglMatchConfig(const _EGLConfig *conf, const _EGLConfig *criteria) 4214a49301eSmrg{ 4224a49301eSmrg EGLint attr, val, i; 4234a49301eSmrg EGLBoolean matched = EGL_TRUE; 4244a49301eSmrg 4254a49301eSmrg for (i = 0; i < ARRAY_SIZE(_eglValidationTable); i++) { 4264a49301eSmrg EGLint cmp; 4274a49301eSmrg if (_eglValidationTable[i].criterion == ATTRIB_CRITERION_IGNORE) 4284a49301eSmrg continue; 4294a49301eSmrg 4304a49301eSmrg attr = _eglValidationTable[i].attr; 4314a49301eSmrg cmp = GET_CONFIG_ATTRIB(criteria, attr); 4324a49301eSmrg if (cmp == EGL_DONT_CARE) 4334a49301eSmrg continue; 4344a49301eSmrg 4354a49301eSmrg val = GET_CONFIG_ATTRIB(conf, attr); 4364a49301eSmrg switch (_eglValidationTable[i].criterion) { 4374a49301eSmrg case ATTRIB_CRITERION_EXACT: 4384a49301eSmrg if (val != cmp) 4394a49301eSmrg matched = EGL_FALSE; 4404a49301eSmrg break; 4414a49301eSmrg case ATTRIB_CRITERION_ATLEAST: 4424a49301eSmrg if (val < cmp) 4434a49301eSmrg matched = EGL_FALSE; 4444a49301eSmrg break; 4454a49301eSmrg case ATTRIB_CRITERION_MASK: 4464a49301eSmrg if ((val & cmp) != cmp) 4474a49301eSmrg matched = EGL_FALSE; 4484a49301eSmrg break; 4494a49301eSmrg case ATTRIB_CRITERION_SPECIAL: 4504a49301eSmrg /* ignored here */ 4514a49301eSmrg break; 4524a49301eSmrg default: 4534a49301eSmrg assert(0); 4544a49301eSmrg break; 4554a49301eSmrg } 4564a49301eSmrg 4574a49301eSmrg if (!matched) 4584a49301eSmrg break; 4594a49301eSmrg } 4604a49301eSmrg 4614a49301eSmrg return matched; 4624a49301eSmrg} 4634a49301eSmrg 4644a49301eSmrg 4654a49301eSmrg/** 4664a49301eSmrg * Initialize a criteria config from the given attribute list. 4674a49301eSmrg * Return EGL_FALSE if any of the attribute is invalid. 4684a49301eSmrg */ 4694a49301eSmrgEGLBoolean 4704a49301eSmrg_eglParseConfigAttribList(_EGLConfig *conf, const EGLint *attrib_list) 4714a49301eSmrg{ 4724a49301eSmrg EGLint attr, val, i; 4734a49301eSmrg EGLint config_id = 0, level = 0; 4744a49301eSmrg EGLBoolean has_native_visual_type = EGL_FALSE; 4754a49301eSmrg EGLBoolean has_transparent_color = EGL_FALSE; 4764a49301eSmrg 4774a49301eSmrg /* reset to default values */ 4784a49301eSmrg for (i = 0; i < ARRAY_SIZE(_eglValidationTable); i++) { 4794a49301eSmrg attr = _eglValidationTable[i].attr; 4804a49301eSmrg val = _eglValidationTable[i].default_value; 4814a49301eSmrg SET_CONFIG_ATTRIB(conf, attr, val); 4824a49301eSmrg } 4834a49301eSmrg 4844a49301eSmrg /* parse the list */ 4854a49301eSmrg for (i = 0; attrib_list && attrib_list[i] != EGL_NONE; i += 2) { 4864a49301eSmrg EGLint idx; 4874a49301eSmrg 4884a49301eSmrg attr = attrib_list[i]; 4894a49301eSmrg val = attrib_list[i + 1]; 4904a49301eSmrg 4914a49301eSmrg idx = _eglIndexConfig(conf, attr); 4924a49301eSmrg if (idx < 0) 4934a49301eSmrg return EGL_FALSE; 4944a49301eSmrg conf->Storage[idx] = val; 4954a49301eSmrg 4964a49301eSmrg /* rememeber some attributes for post-processing */ 4974a49301eSmrg switch (attr) { 4984a49301eSmrg case EGL_CONFIG_ID: 4994a49301eSmrg config_id = val; 5004a49301eSmrg break; 5014a49301eSmrg case EGL_LEVEL: 5024a49301eSmrg level = val; 5034a49301eSmrg break; 5044a49301eSmrg case EGL_NATIVE_VISUAL_TYPE: 5054a49301eSmrg has_native_visual_type = EGL_TRUE; 5064a49301eSmrg break; 5074a49301eSmrg case EGL_TRANSPARENT_RED_VALUE: 5084a49301eSmrg case EGL_TRANSPARENT_GREEN_VALUE: 5094a49301eSmrg case EGL_TRANSPARENT_BLUE_VALUE: 5104a49301eSmrg has_transparent_color = EGL_TRUE; 5114a49301eSmrg break; 5124a49301eSmrg default: 5134a49301eSmrg break; 5144a49301eSmrg } 5154a49301eSmrg } 5164a49301eSmrg 5174a49301eSmrg if (!_eglValidateConfig(conf, EGL_TRUE)) 5184a49301eSmrg return EGL_FALSE; 5194a49301eSmrg 5204a49301eSmrg /* the spec says that EGL_LEVEL cannot be EGL_DONT_CARE */ 5214a49301eSmrg if (level == EGL_DONT_CARE) 5224a49301eSmrg return EGL_FALSE; 5234a49301eSmrg 5244a49301eSmrg /* ignore other attributes when EGL_CONFIG_ID is given */ 5254a49301eSmrg if (config_id > 0) { 5264a49301eSmrg _eglResetConfigKeys(conf, EGL_DONT_CARE); 5274a49301eSmrg SET_CONFIG_ATTRIB(conf, EGL_CONFIG_ID, config_id); 5284a49301eSmrg } 5294a49301eSmrg else { 5304a49301eSmrg if (has_native_visual_type) { 5314a49301eSmrg val = GET_CONFIG_ATTRIB(conf, EGL_SURFACE_TYPE); 5324a49301eSmrg if (!(val & EGL_WINDOW_BIT)) 5334a49301eSmrg SET_CONFIG_ATTRIB(conf, EGL_NATIVE_VISUAL_TYPE, EGL_DONT_CARE); 5344a49301eSmrg } 5354a49301eSmrg 5364a49301eSmrg if (has_transparent_color) { 5374a49301eSmrg val = GET_CONFIG_ATTRIB(conf, EGL_TRANSPARENT_TYPE); 5384a49301eSmrg if (val == EGL_NONE) { 5394a49301eSmrg SET_CONFIG_ATTRIB(conf, EGL_TRANSPARENT_RED_VALUE, 5404a49301eSmrg EGL_DONT_CARE); 5414a49301eSmrg SET_CONFIG_ATTRIB(conf, EGL_TRANSPARENT_GREEN_VALUE, 5424a49301eSmrg EGL_DONT_CARE); 5434a49301eSmrg SET_CONFIG_ATTRIB(conf, EGL_TRANSPARENT_BLUE_VALUE, 5444a49301eSmrg EGL_DONT_CARE); 5454a49301eSmrg } 5464a49301eSmrg } 5474a49301eSmrg } 5484a49301eSmrg 5494a49301eSmrg return EGL_TRUE; 5504a49301eSmrg} 5514a49301eSmrg 5524a49301eSmrg 5534a49301eSmrg/** 5544a49301eSmrg * Decide the ordering of conf1 and conf2, under the given criteria. 5554a49301eSmrg * When compare_id is true, this implements the algorithm described 5564a49301eSmrg * in "Sorting of EGLConfigs". When compare_id is false, 5574a49301eSmrg * EGL_CONFIG_ID is not compared. 5584a49301eSmrg * 5594a49301eSmrg * It returns a negative integer if conf1 is considered to come 5604a49301eSmrg * before conf2; a positive integer if conf2 is considered to come 5614a49301eSmrg * before conf1; zero if the ordering cannot be decided. 5624a49301eSmrg * 5634a49301eSmrg * Note that EGL_NATIVE_VISUAL_TYPE is platform-dependent and is 5644a49301eSmrg * ignored here. 5654a49301eSmrg */ 5664a49301eSmrgEGLint 5674a49301eSmrg_eglCompareConfigs(const _EGLConfig *conf1, const _EGLConfig *conf2, 5684a49301eSmrg const _EGLConfig *criteria, EGLBoolean compare_id) 5694a49301eSmrg{ 5704a49301eSmrg const EGLint compare_attribs[] = { 5714a49301eSmrg EGL_BUFFER_SIZE, 5724a49301eSmrg EGL_SAMPLE_BUFFERS, 5734a49301eSmrg EGL_SAMPLES, 5744a49301eSmrg EGL_DEPTH_SIZE, 5754a49301eSmrg EGL_STENCIL_SIZE, 5764a49301eSmrg EGL_ALPHA_MASK_SIZE, 5774a49301eSmrg }; 5784a49301eSmrg EGLint val1, val2; 5794a49301eSmrg EGLBoolean rgb_buffer; 5804a49301eSmrg EGLint i; 5814a49301eSmrg 5824a49301eSmrg if (conf1 == conf2) 5834a49301eSmrg return 0; 5844a49301eSmrg 5854a49301eSmrg /* the enum values have the desired ordering */ 5864a49301eSmrg assert(EGL_NONE < EGL_SLOW_CONFIG); 5874a49301eSmrg assert(EGL_SLOW_CONFIG < EGL_NON_CONFORMANT_CONFIG); 5884a49301eSmrg val1 = GET_CONFIG_ATTRIB(conf1, EGL_CONFIG_CAVEAT); 5894a49301eSmrg val2 = GET_CONFIG_ATTRIB(conf2, EGL_CONFIG_CAVEAT); 5904a49301eSmrg if (val1 != val2) 5914a49301eSmrg return (val1 - val2); 5924a49301eSmrg 5934a49301eSmrg /* the enum values have the desired ordering */ 5944a49301eSmrg assert(EGL_RGB_BUFFER < EGL_LUMINANCE_BUFFER); 5954a49301eSmrg val1 = GET_CONFIG_ATTRIB(conf1, EGL_COLOR_BUFFER_TYPE); 5964a49301eSmrg val2 = GET_CONFIG_ATTRIB(conf2, EGL_COLOR_BUFFER_TYPE); 5974a49301eSmrg if (val1 != val2) 5984a49301eSmrg return (val1 - val2); 5994a49301eSmrg rgb_buffer = (val1 == EGL_RGB_BUFFER); 6004a49301eSmrg 6014a49301eSmrg if (criteria) { 6024a49301eSmrg val1 = val2 = 0; 6034a49301eSmrg if (rgb_buffer) { 6044a49301eSmrg if (GET_CONFIG_ATTRIB(criteria, EGL_RED_SIZE) > 0) { 6054a49301eSmrg val1 += GET_CONFIG_ATTRIB(conf1, EGL_RED_SIZE); 6064a49301eSmrg val2 += GET_CONFIG_ATTRIB(conf2, EGL_RED_SIZE); 6074a49301eSmrg } 6084a49301eSmrg if (GET_CONFIG_ATTRIB(criteria, EGL_GREEN_SIZE) > 0) { 6094a49301eSmrg val1 += GET_CONFIG_ATTRIB(conf1, EGL_GREEN_SIZE); 6104a49301eSmrg val2 += GET_CONFIG_ATTRIB(conf2, EGL_GREEN_SIZE); 6114a49301eSmrg } 6124a49301eSmrg if (GET_CONFIG_ATTRIB(criteria, EGL_BLUE_SIZE) > 0) { 6134a49301eSmrg val1 += GET_CONFIG_ATTRIB(conf1, EGL_BLUE_SIZE); 6144a49301eSmrg val2 += GET_CONFIG_ATTRIB(conf2, EGL_BLUE_SIZE); 6154a49301eSmrg } 6164a49301eSmrg } 6174a49301eSmrg else { 6184a49301eSmrg if (GET_CONFIG_ATTRIB(criteria, EGL_LUMINANCE_SIZE) > 0) { 6194a49301eSmrg val1 += GET_CONFIG_ATTRIB(conf1, EGL_LUMINANCE_SIZE); 6204a49301eSmrg val2 += GET_CONFIG_ATTRIB(conf2, EGL_LUMINANCE_SIZE); 6214a49301eSmrg } 6224a49301eSmrg } 6234a49301eSmrg if (GET_CONFIG_ATTRIB(criteria, EGL_ALPHA_SIZE) > 0) { 6244a49301eSmrg val1 += GET_CONFIG_ATTRIB(conf1, EGL_ALPHA_SIZE); 6254a49301eSmrg val2 += GET_CONFIG_ATTRIB(conf2, EGL_ALPHA_SIZE); 6264a49301eSmrg } 6274a49301eSmrg } 6284a49301eSmrg else { 6294a49301eSmrg /* assume the default criteria, which gives no specific ordering */ 6304a49301eSmrg val1 = val2 = 0; 6314a49301eSmrg } 6324a49301eSmrg 6334a49301eSmrg /* for color bits, larger one is preferred */ 6344a49301eSmrg if (val1 != val2) 6354a49301eSmrg return (val2 - val1); 6364a49301eSmrg 6374a49301eSmrg for (i = 0; i < ARRAY_SIZE(compare_attribs); i++) { 6384a49301eSmrg val1 = GET_CONFIG_ATTRIB(conf1, compare_attribs[i]); 6394a49301eSmrg val2 = GET_CONFIG_ATTRIB(conf2, compare_attribs[i]); 6404a49301eSmrg if (val1 != val2) 6414a49301eSmrg return (val1 - val2); 6424a49301eSmrg } 6434a49301eSmrg 6444a49301eSmrg /* EGL_NATIVE_VISUAL_TYPE cannot be compared here */ 6454a49301eSmrg 6464a49301eSmrg if (compare_id) { 6474a49301eSmrg val1 = GET_CONFIG_ATTRIB(conf1, EGL_CONFIG_ID); 6484a49301eSmrg val2 = GET_CONFIG_ATTRIB(conf2, EGL_CONFIG_ID); 6494a49301eSmrg assert(val1 != val2); 6504a49301eSmrg } 6514a49301eSmrg else { 6524a49301eSmrg val1 = val2 = 0; 6534a49301eSmrg } 6544a49301eSmrg 6554a49301eSmrg return (val1 - val2); 6564a49301eSmrg} 6574a49301eSmrg 6584a49301eSmrg 6594a49301eSmrgstatic INLINE 6604a49301eSmrgvoid _eglSwapConfigs(const _EGLConfig **conf1, const _EGLConfig **conf2) 6614a49301eSmrg{ 6624a49301eSmrg const _EGLConfig *tmp = *conf1; 6634a49301eSmrg *conf1 = *conf2; 6644a49301eSmrg *conf2 = tmp; 6654a49301eSmrg} 6664a49301eSmrg 6674a49301eSmrg 6684a49301eSmrg/** 6694a49301eSmrg * Quick sort an array of configs. This differs from the standard 6704a49301eSmrg * qsort() in that the compare function accepts an additional 6714a49301eSmrg * argument. 6724a49301eSmrg */ 6734a49301eSmrgvoid 6744a49301eSmrg_eglSortConfigs(const _EGLConfig **configs, EGLint count, 6754a49301eSmrg EGLint (*compare)(const _EGLConfig *, const _EGLConfig *, 6764a49301eSmrg void *), 6774a49301eSmrg void *priv_data) 6784a49301eSmrg{ 6794a49301eSmrg const EGLint pivot = 0; 6804a49301eSmrg EGLint i, j; 6814a49301eSmrg 6824a49301eSmrg if (count <= 1) 6834a49301eSmrg return; 6844a49301eSmrg 6854a49301eSmrg _eglSwapConfigs(&configs[pivot], &configs[count / 2]); 6864a49301eSmrg i = 1; 6874a49301eSmrg j = count - 1; 6884a49301eSmrg do { 6894a49301eSmrg while (i < count && compare(configs[i], configs[pivot], priv_data) < 0) 6904a49301eSmrg i++; 6914a49301eSmrg while (compare(configs[j], configs[pivot], priv_data) > 0) 6924a49301eSmrg j--; 6934a49301eSmrg if (i < j) { 6944a49301eSmrg _eglSwapConfigs(&configs[i], &configs[j]); 6954a49301eSmrg i++; 6964a49301eSmrg j--; 6974a49301eSmrg } 6984a49301eSmrg else if (i == j) { 6994a49301eSmrg i++; 7004a49301eSmrg j--; 7014a49301eSmrg break; 7024a49301eSmrg } 7034a49301eSmrg } while (i <= j); 7044a49301eSmrg _eglSwapConfigs(&configs[pivot], &configs[j]); 7054a49301eSmrg 7064a49301eSmrg _eglSortConfigs(configs, j, compare, priv_data); 7074a49301eSmrg _eglSortConfigs(configs + i, count - i, compare, priv_data); 7084a49301eSmrg} 7094a49301eSmrg 7104a49301eSmrg 7114a49301eSmrgstatic int 7124a49301eSmrg_eglFallbackCompare(const _EGLConfig *conf1, const _EGLConfig *conf2, 7134a49301eSmrg void *priv_data) 7144a49301eSmrg{ 7154a49301eSmrg const _EGLConfig *criteria = (const _EGLConfig *) priv_data; 7164a49301eSmrg return _eglCompareConfigs(conf1, conf2, criteria, EGL_TRUE); 7174a49301eSmrg} 7184a49301eSmrg 7194a49301eSmrg 7204a49301eSmrg/** 7214a49301eSmrg * Typical fallback routine for eglChooseConfig 7224a49301eSmrg */ 7234a49301eSmrgEGLBoolean 7244a49301eSmrg_eglChooseConfig(_EGLDriver *drv, _EGLDisplay *disp, const EGLint *attrib_list, 7254a49301eSmrg EGLConfig *configs, EGLint config_size, EGLint *num_configs) 7264a49301eSmrg{ 7274a49301eSmrg _EGLConfig **configList, criteria; 7284a49301eSmrg EGLint i, count; 7294a49301eSmrg 7304a49301eSmrg if (!num_configs) 7314a49301eSmrg return _eglError(EGL_BAD_PARAMETER, "eglChooseConfigs"); 7324a49301eSmrg 7334a49301eSmrg _eglInitConfig(&criteria, 0); 7344a49301eSmrg if (!_eglParseConfigAttribList(&criteria, attrib_list)) 7354a49301eSmrg return _eglError(EGL_BAD_ATTRIBUTE, "eglChooseConfig"); 7364a49301eSmrg 7374a49301eSmrg /* allocate array of config pointers */ 7384a49301eSmrg configList = (_EGLConfig **) 7394a49301eSmrg malloc(disp->NumConfigs * sizeof(_EGLConfig *)); 7404a49301eSmrg if (!configList) 7414a49301eSmrg return _eglError(EGL_BAD_ALLOC, "eglChooseConfig(out of memory)"); 7424a49301eSmrg 7434a49301eSmrg /* perform selection of configs */ 7444a49301eSmrg count = 0; 7454a49301eSmrg for (i = 0; i < disp->NumConfigs; i++) { 7464a49301eSmrg if (_eglMatchConfig(disp->Configs[i], &criteria)) 7474a49301eSmrg configList[count++] = disp->Configs[i]; 7484a49301eSmrg } 7494a49301eSmrg 7504a49301eSmrg /* perform sorting of configs */ 7514a49301eSmrg if (configs && count) { 7524a49301eSmrg _eglSortConfigs((const _EGLConfig **) configList, count, 7534a49301eSmrg _eglFallbackCompare, (void *) &criteria); 7544a49301eSmrg count = MIN2(count, config_size); 7554a49301eSmrg for (i = 0; i < count; i++) 7564a49301eSmrg configs[i] = _eglGetConfigHandle(configList[i]); 7574a49301eSmrg } 7584a49301eSmrg 7594a49301eSmrg free(configList); 7604a49301eSmrg 7614a49301eSmrg *num_configs = count; 7624a49301eSmrg 7634a49301eSmrg return EGL_TRUE; 7644a49301eSmrg} 7654a49301eSmrg 7664a49301eSmrg 7674a49301eSmrgstatic INLINE EGLBoolean 7684a49301eSmrg_eglIsConfigAttribValid(_EGLConfig *conf, EGLint attr) 7694a49301eSmrg{ 7704a49301eSmrg if (_eglIndexConfig(conf, attr) < 0) 7714a49301eSmrg return EGL_FALSE; 7724a49301eSmrg 7734a49301eSmrg /* there are some holes in the range */ 7744a49301eSmrg switch (attr) { 7754a49301eSmrg case EGL_PRESERVED_RESOURCES: 7764a49301eSmrg case EGL_NONE: 7774a49301eSmrg#ifdef EGL_VERSION_1_4 7784a49301eSmrg case EGL_MATCH_NATIVE_PIXMAP: 7794a49301eSmrg#endif 7804a49301eSmrg return EGL_FALSE; 7814a49301eSmrg default: 7824a49301eSmrg break; 7834a49301eSmrg } 7844a49301eSmrg 7854a49301eSmrg return EGL_TRUE; 7864a49301eSmrg} 7874a49301eSmrg 7884a49301eSmrg 7894a49301eSmrg/** 7904a49301eSmrg * Fallback for eglGetConfigAttrib. 7914a49301eSmrg */ 7924a49301eSmrgEGLBoolean 7934a49301eSmrg_eglGetConfigAttrib(_EGLDriver *drv, _EGLDisplay *dpy, _EGLConfig *conf, 7944a49301eSmrg EGLint attribute, EGLint *value) 7954a49301eSmrg{ 7964a49301eSmrg if (!_eglIsConfigAttribValid(conf, attribute)) 7974a49301eSmrg return _eglError(EGL_BAD_ATTRIBUTE, "eglGetConfigAttrib"); 7984a49301eSmrg if (!value) 7994a49301eSmrg return _eglError(EGL_BAD_PARAMETER, "eglGetConfigAttrib"); 8004a49301eSmrg 8014a49301eSmrg *value = GET_CONFIG_ATTRIB(conf, attribute); 8024a49301eSmrg return EGL_TRUE; 8034a49301eSmrg} 8044a49301eSmrg 8054a49301eSmrg 8064a49301eSmrg/** 8074a49301eSmrg * Fallback for eglGetConfigs. 8084a49301eSmrg */ 8094a49301eSmrgEGLBoolean 8104a49301eSmrg_eglGetConfigs(_EGLDriver *drv, _EGLDisplay *disp, EGLConfig *configs, 8114a49301eSmrg EGLint config_size, EGLint *num_config) 8124a49301eSmrg{ 8134a49301eSmrg if (!num_config) 8144a49301eSmrg return _eglError(EGL_BAD_PARAMETER, "eglGetConfigs"); 8154a49301eSmrg 8164a49301eSmrg if (configs) { 8174a49301eSmrg EGLint i; 8184a49301eSmrg *num_config = MIN2(disp->NumConfigs, config_size); 8194a49301eSmrg for (i = 0; i < *num_config; i++) 8204a49301eSmrg configs[i] = _eglGetConfigHandle(disp->Configs[i]); 8214a49301eSmrg } 8224a49301eSmrg else { 8234a49301eSmrg /* just return total number of supported configs */ 8244a49301eSmrg *num_config = disp->NumConfigs; 8254a49301eSmrg } 8264a49301eSmrg 8274a49301eSmrg return EGL_TRUE; 8284a49301eSmrg} 829