1bf215546Sopenharmony_ci/************************************************************************** 2bf215546Sopenharmony_ci * 3bf215546Sopenharmony_ci * Copyright 2008 VMware, Inc. 4bf215546Sopenharmony_ci * Copyright 2009-2010 Chia-I Wu <olvaffe@gmail.com> 5bf215546Sopenharmony_ci * Copyright 2010-2011 LunarG, Inc. 6bf215546Sopenharmony_ci * All Rights Reserved. 7bf215546Sopenharmony_ci * 8bf215546Sopenharmony_ci * Permission is hereby granted, free of charge, to any person obtaining a 9bf215546Sopenharmony_ci * copy of this software and associated documentation files (the 10bf215546Sopenharmony_ci * "Software"), to deal in the Software without restriction, including 11bf215546Sopenharmony_ci * without limitation the rights to use, copy, modify, merge, publish, 12bf215546Sopenharmony_ci * distribute, sub license, and/or sell copies of the Software, and to 13bf215546Sopenharmony_ci * permit persons to whom the Software is furnished to do so, subject to 14bf215546Sopenharmony_ci * the following conditions: 15bf215546Sopenharmony_ci * 16bf215546Sopenharmony_ci * The above copyright notice and this permission notice (including the 17bf215546Sopenharmony_ci * next paragraph) shall be included in all copies or substantial portions 18bf215546Sopenharmony_ci * of the Software. 19bf215546Sopenharmony_ci * 20bf215546Sopenharmony_ci * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 21bf215546Sopenharmony_ci * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 22bf215546Sopenharmony_ci * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 23bf215546Sopenharmony_ci * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 24bf215546Sopenharmony_ci * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 25bf215546Sopenharmony_ci * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 26bf215546Sopenharmony_ci * DEALINGS IN THE SOFTWARE. 27bf215546Sopenharmony_ci * 28bf215546Sopenharmony_ci **************************************************************************/ 29bf215546Sopenharmony_ci 30bf215546Sopenharmony_ci 31bf215546Sopenharmony_ci/** 32bf215546Sopenharmony_ci * EGL Configuration (pixel format) functions. 33bf215546Sopenharmony_ci */ 34bf215546Sopenharmony_ci 35bf215546Sopenharmony_ci 36bf215546Sopenharmony_ci#include <stdlib.h> 37bf215546Sopenharmony_ci#include <string.h> 38bf215546Sopenharmony_ci#include <assert.h> 39bf215546Sopenharmony_ci#include "util/macros.h" 40bf215546Sopenharmony_ci 41bf215546Sopenharmony_ci#include "eglconfig.h" 42bf215546Sopenharmony_ci#include "eglconfigdebug.h" 43bf215546Sopenharmony_ci#include "egldisplay.h" 44bf215546Sopenharmony_ci#include "eglcurrent.h" 45bf215546Sopenharmony_ci#include "egllog.h" 46bf215546Sopenharmony_ci 47bf215546Sopenharmony_ci 48bf215546Sopenharmony_ci 49bf215546Sopenharmony_ci 50bf215546Sopenharmony_ci/** 51bf215546Sopenharmony_ci * Init the given _EGLconfig to default values. 52bf215546Sopenharmony_ci * \param id the configuration's ID. 53bf215546Sopenharmony_ci * 54bf215546Sopenharmony_ci * Note that id must be positive for the config to be valid. 55bf215546Sopenharmony_ci * It is also recommended that when there are N configs, their 56bf215546Sopenharmony_ci * IDs are from 1 to N respectively. 57bf215546Sopenharmony_ci */ 58bf215546Sopenharmony_civoid 59bf215546Sopenharmony_ci_eglInitConfig(_EGLConfig *conf, _EGLDisplay *disp, EGLint id) 60bf215546Sopenharmony_ci{ 61bf215546Sopenharmony_ci memset(conf, 0, sizeof(*conf)); 62bf215546Sopenharmony_ci 63bf215546Sopenharmony_ci conf->Display = disp; 64bf215546Sopenharmony_ci 65bf215546Sopenharmony_ci /* some attributes take non-zero default values */ 66bf215546Sopenharmony_ci conf->ConfigID = id; 67bf215546Sopenharmony_ci conf->ConfigCaveat = EGL_NONE; 68bf215546Sopenharmony_ci conf->TransparentType = EGL_NONE; 69bf215546Sopenharmony_ci conf->NativeVisualType = EGL_NONE; 70bf215546Sopenharmony_ci conf->ColorBufferType = EGL_RGB_BUFFER; 71bf215546Sopenharmony_ci conf->ComponentType = EGL_COLOR_COMPONENT_TYPE_FIXED_EXT; 72bf215546Sopenharmony_ci} 73bf215546Sopenharmony_ci 74bf215546Sopenharmony_ci 75bf215546Sopenharmony_ci/** 76bf215546Sopenharmony_ci * Link a config to its display and return the handle of the link. 77bf215546Sopenharmony_ci * The handle can be passed to client directly. 78bf215546Sopenharmony_ci * 79bf215546Sopenharmony_ci * Note that we just save the ptr to the config (we don't copy the config). 80bf215546Sopenharmony_ci */ 81bf215546Sopenharmony_ciEGLConfig 82bf215546Sopenharmony_ci_eglLinkConfig(_EGLConfig *conf) 83bf215546Sopenharmony_ci{ 84bf215546Sopenharmony_ci _EGLDisplay *disp = conf->Display; 85bf215546Sopenharmony_ci 86bf215546Sopenharmony_ci /* sanity check */ 87bf215546Sopenharmony_ci assert(disp); 88bf215546Sopenharmony_ci assert(conf->ConfigID > 0); 89bf215546Sopenharmony_ci 90bf215546Sopenharmony_ci if (!disp->Configs) { 91bf215546Sopenharmony_ci disp->Configs = _eglCreateArray("Config", 16); 92bf215546Sopenharmony_ci if (!disp->Configs) 93bf215546Sopenharmony_ci return (EGLConfig) NULL; 94bf215546Sopenharmony_ci } 95bf215546Sopenharmony_ci 96bf215546Sopenharmony_ci _eglAppendArray(disp->Configs, (void *) conf); 97bf215546Sopenharmony_ci 98bf215546Sopenharmony_ci return (EGLConfig) conf; 99bf215546Sopenharmony_ci} 100bf215546Sopenharmony_ci 101bf215546Sopenharmony_ci 102bf215546Sopenharmony_ci/** 103bf215546Sopenharmony_ci * Lookup a handle to find the linked config. 104bf215546Sopenharmony_ci * Return NULL if the handle has no corresponding linked config. 105bf215546Sopenharmony_ci */ 106bf215546Sopenharmony_ci_EGLConfig * 107bf215546Sopenharmony_ci_eglLookupConfig(EGLConfig config, _EGLDisplay *disp) 108bf215546Sopenharmony_ci{ 109bf215546Sopenharmony_ci _EGLConfig *conf; 110bf215546Sopenharmony_ci 111bf215546Sopenharmony_ci if (!disp) 112bf215546Sopenharmony_ci return NULL; 113bf215546Sopenharmony_ci 114bf215546Sopenharmony_ci conf = (_EGLConfig *) _eglFindArray(disp->Configs, (void *) config); 115bf215546Sopenharmony_ci if (conf) 116bf215546Sopenharmony_ci assert(conf->Display == disp); 117bf215546Sopenharmony_ci 118bf215546Sopenharmony_ci return conf; 119bf215546Sopenharmony_ci} 120bf215546Sopenharmony_ci 121bf215546Sopenharmony_ci 122bf215546Sopenharmony_cienum type { 123bf215546Sopenharmony_ci ATTRIB_TYPE_INTEGER, 124bf215546Sopenharmony_ci ATTRIB_TYPE_BOOLEAN, 125bf215546Sopenharmony_ci ATTRIB_TYPE_BITMASK, 126bf215546Sopenharmony_ci ATTRIB_TYPE_ENUM, 127bf215546Sopenharmony_ci ATTRIB_TYPE_PSEUDO, /* non-queryable */ 128bf215546Sopenharmony_ci ATTRIB_TYPE_PLATFORM, /* platform-dependent */ 129bf215546Sopenharmony_ci}; 130bf215546Sopenharmony_ci 131bf215546Sopenharmony_cienum criterion { 132bf215546Sopenharmony_ci ATTRIB_CRITERION_EXACT, 133bf215546Sopenharmony_ci ATTRIB_CRITERION_ATLEAST, 134bf215546Sopenharmony_ci ATTRIB_CRITERION_MASK, 135bf215546Sopenharmony_ci ATTRIB_CRITERION_SPECIAL, 136bf215546Sopenharmony_ci ATTRIB_CRITERION_IGNORE 137bf215546Sopenharmony_ci}; 138bf215546Sopenharmony_ci 139bf215546Sopenharmony_ci 140bf215546Sopenharmony_ci/* EGL spec Table 3.1 and 3.4 */ 141bf215546Sopenharmony_cistatic const struct { 142bf215546Sopenharmony_ci EGLint attr; 143bf215546Sopenharmony_ci enum type type; 144bf215546Sopenharmony_ci enum criterion criterion; 145bf215546Sopenharmony_ci EGLint default_value; 146bf215546Sopenharmony_ci} _eglValidationTable[] = 147bf215546Sopenharmony_ci{ 148bf215546Sopenharmony_ci /* core */ 149bf215546Sopenharmony_ci { EGL_BUFFER_SIZE, ATTRIB_TYPE_INTEGER, 150bf215546Sopenharmony_ci ATTRIB_CRITERION_ATLEAST, 151bf215546Sopenharmony_ci 0 }, 152bf215546Sopenharmony_ci { EGL_RED_SIZE, ATTRIB_TYPE_INTEGER, 153bf215546Sopenharmony_ci ATTRIB_CRITERION_ATLEAST, 154bf215546Sopenharmony_ci 0 }, 155bf215546Sopenharmony_ci { EGL_GREEN_SIZE, ATTRIB_TYPE_INTEGER, 156bf215546Sopenharmony_ci ATTRIB_CRITERION_ATLEAST, 157bf215546Sopenharmony_ci 0 }, 158bf215546Sopenharmony_ci { EGL_BLUE_SIZE, ATTRIB_TYPE_INTEGER, 159bf215546Sopenharmony_ci ATTRIB_CRITERION_ATLEAST, 160bf215546Sopenharmony_ci 0 }, 161bf215546Sopenharmony_ci { EGL_LUMINANCE_SIZE, ATTRIB_TYPE_INTEGER, 162bf215546Sopenharmony_ci ATTRIB_CRITERION_ATLEAST, 163bf215546Sopenharmony_ci 0 }, 164bf215546Sopenharmony_ci { EGL_ALPHA_SIZE, ATTRIB_TYPE_INTEGER, 165bf215546Sopenharmony_ci ATTRIB_CRITERION_ATLEAST, 166bf215546Sopenharmony_ci 0 }, 167bf215546Sopenharmony_ci { EGL_ALPHA_MASK_SIZE, ATTRIB_TYPE_INTEGER, 168bf215546Sopenharmony_ci ATTRIB_CRITERION_ATLEAST, 169bf215546Sopenharmony_ci 0 }, 170bf215546Sopenharmony_ci { EGL_BIND_TO_TEXTURE_RGB, ATTRIB_TYPE_BOOLEAN, 171bf215546Sopenharmony_ci ATTRIB_CRITERION_EXACT, 172bf215546Sopenharmony_ci EGL_DONT_CARE }, 173bf215546Sopenharmony_ci { EGL_BIND_TO_TEXTURE_RGBA, ATTRIB_TYPE_BOOLEAN, 174bf215546Sopenharmony_ci ATTRIB_CRITERION_EXACT, 175bf215546Sopenharmony_ci EGL_DONT_CARE }, 176bf215546Sopenharmony_ci { EGL_COLOR_BUFFER_TYPE, ATTRIB_TYPE_ENUM, 177bf215546Sopenharmony_ci ATTRIB_CRITERION_EXACT, 178bf215546Sopenharmony_ci EGL_RGB_BUFFER }, 179bf215546Sopenharmony_ci { EGL_CONFIG_CAVEAT, ATTRIB_TYPE_ENUM, 180bf215546Sopenharmony_ci ATTRIB_CRITERION_EXACT, 181bf215546Sopenharmony_ci EGL_DONT_CARE }, 182bf215546Sopenharmony_ci { EGL_CONFIG_ID, ATTRIB_TYPE_INTEGER, 183bf215546Sopenharmony_ci ATTRIB_CRITERION_EXACT, 184bf215546Sopenharmony_ci EGL_DONT_CARE }, 185bf215546Sopenharmony_ci { EGL_CONFORMANT, ATTRIB_TYPE_BITMASK, 186bf215546Sopenharmony_ci ATTRIB_CRITERION_MASK, 187bf215546Sopenharmony_ci 0 }, 188bf215546Sopenharmony_ci { EGL_DEPTH_SIZE, ATTRIB_TYPE_INTEGER, 189bf215546Sopenharmony_ci ATTRIB_CRITERION_ATLEAST, 190bf215546Sopenharmony_ci 0 }, 191bf215546Sopenharmony_ci { EGL_LEVEL, ATTRIB_TYPE_PLATFORM, 192bf215546Sopenharmony_ci ATTRIB_CRITERION_EXACT, 193bf215546Sopenharmony_ci 0 }, 194bf215546Sopenharmony_ci { EGL_MAX_PBUFFER_WIDTH, ATTRIB_TYPE_INTEGER, 195bf215546Sopenharmony_ci ATTRIB_CRITERION_IGNORE, 196bf215546Sopenharmony_ci 0 }, 197bf215546Sopenharmony_ci { EGL_MAX_PBUFFER_HEIGHT, ATTRIB_TYPE_INTEGER, 198bf215546Sopenharmony_ci ATTRIB_CRITERION_IGNORE, 199bf215546Sopenharmony_ci 0 }, 200bf215546Sopenharmony_ci { EGL_MAX_PBUFFER_PIXELS, ATTRIB_TYPE_INTEGER, 201bf215546Sopenharmony_ci ATTRIB_CRITERION_IGNORE, 202bf215546Sopenharmony_ci 0 }, 203bf215546Sopenharmony_ci { EGL_MAX_SWAP_INTERVAL, ATTRIB_TYPE_INTEGER, 204bf215546Sopenharmony_ci ATTRIB_CRITERION_EXACT, 205bf215546Sopenharmony_ci EGL_DONT_CARE }, 206bf215546Sopenharmony_ci { EGL_MIN_SWAP_INTERVAL, ATTRIB_TYPE_INTEGER, 207bf215546Sopenharmony_ci ATTRIB_CRITERION_EXACT, 208bf215546Sopenharmony_ci EGL_DONT_CARE }, 209bf215546Sopenharmony_ci { EGL_NATIVE_RENDERABLE, ATTRIB_TYPE_BOOLEAN, 210bf215546Sopenharmony_ci ATTRIB_CRITERION_EXACT, 211bf215546Sopenharmony_ci EGL_DONT_CARE }, 212bf215546Sopenharmony_ci { EGL_NATIVE_VISUAL_ID, ATTRIB_TYPE_PLATFORM, 213bf215546Sopenharmony_ci ATTRIB_CRITERION_IGNORE, 214bf215546Sopenharmony_ci 0 }, 215bf215546Sopenharmony_ci { EGL_NATIVE_VISUAL_TYPE, ATTRIB_TYPE_PLATFORM, 216bf215546Sopenharmony_ci ATTRIB_CRITERION_EXACT, 217bf215546Sopenharmony_ci EGL_DONT_CARE }, 218bf215546Sopenharmony_ci { EGL_RENDERABLE_TYPE, ATTRIB_TYPE_BITMASK, 219bf215546Sopenharmony_ci ATTRIB_CRITERION_MASK, 220bf215546Sopenharmony_ci EGL_OPENGL_ES_BIT }, 221bf215546Sopenharmony_ci { EGL_SAMPLE_BUFFERS, ATTRIB_TYPE_INTEGER, 222bf215546Sopenharmony_ci ATTRIB_CRITERION_ATLEAST, 223bf215546Sopenharmony_ci 0 }, 224bf215546Sopenharmony_ci { EGL_SAMPLES, ATTRIB_TYPE_INTEGER, 225bf215546Sopenharmony_ci ATTRIB_CRITERION_ATLEAST, 226bf215546Sopenharmony_ci 0 }, 227bf215546Sopenharmony_ci { EGL_STENCIL_SIZE, ATTRIB_TYPE_INTEGER, 228bf215546Sopenharmony_ci ATTRIB_CRITERION_ATLEAST, 229bf215546Sopenharmony_ci 0 }, 230bf215546Sopenharmony_ci { EGL_SURFACE_TYPE, ATTRIB_TYPE_BITMASK, 231bf215546Sopenharmony_ci ATTRIB_CRITERION_MASK, 232bf215546Sopenharmony_ci EGL_WINDOW_BIT }, 233bf215546Sopenharmony_ci { EGL_TRANSPARENT_TYPE, ATTRIB_TYPE_ENUM, 234bf215546Sopenharmony_ci ATTRIB_CRITERION_EXACT, 235bf215546Sopenharmony_ci EGL_NONE }, 236bf215546Sopenharmony_ci { EGL_TRANSPARENT_RED_VALUE, ATTRIB_TYPE_INTEGER, 237bf215546Sopenharmony_ci ATTRIB_CRITERION_EXACT, 238bf215546Sopenharmony_ci EGL_DONT_CARE }, 239bf215546Sopenharmony_ci { EGL_TRANSPARENT_GREEN_VALUE, ATTRIB_TYPE_INTEGER, 240bf215546Sopenharmony_ci ATTRIB_CRITERION_EXACT, 241bf215546Sopenharmony_ci EGL_DONT_CARE }, 242bf215546Sopenharmony_ci { EGL_TRANSPARENT_BLUE_VALUE, ATTRIB_TYPE_INTEGER, 243bf215546Sopenharmony_ci ATTRIB_CRITERION_EXACT, 244bf215546Sopenharmony_ci EGL_DONT_CARE }, 245bf215546Sopenharmony_ci { EGL_MATCH_NATIVE_PIXMAP, ATTRIB_TYPE_PSEUDO, 246bf215546Sopenharmony_ci ATTRIB_CRITERION_SPECIAL, 247bf215546Sopenharmony_ci EGL_NONE }, 248bf215546Sopenharmony_ci /* extensions */ 249bf215546Sopenharmony_ci { EGL_Y_INVERTED_NOK, ATTRIB_TYPE_BOOLEAN, 250bf215546Sopenharmony_ci ATTRIB_CRITERION_EXACT, 251bf215546Sopenharmony_ci EGL_DONT_CARE }, 252bf215546Sopenharmony_ci { EGL_FRAMEBUFFER_TARGET_ANDROID, ATTRIB_TYPE_BOOLEAN, 253bf215546Sopenharmony_ci ATTRIB_CRITERION_EXACT, 254bf215546Sopenharmony_ci EGL_DONT_CARE }, 255bf215546Sopenharmony_ci { EGL_RECORDABLE_ANDROID, ATTRIB_TYPE_BOOLEAN, 256bf215546Sopenharmony_ci ATTRIB_CRITERION_EXACT, 257bf215546Sopenharmony_ci EGL_DONT_CARE }, 258bf215546Sopenharmony_ci { EGL_COLOR_COMPONENT_TYPE_EXT, ATTRIB_TYPE_ENUM, 259bf215546Sopenharmony_ci ATTRIB_CRITERION_EXACT, 260bf215546Sopenharmony_ci EGL_COLOR_COMPONENT_TYPE_FIXED_EXT }, 261bf215546Sopenharmony_ci}; 262bf215546Sopenharmony_ci 263bf215546Sopenharmony_ci 264bf215546Sopenharmony_ci/** 265bf215546Sopenharmony_ci * Return true if a config is valid. When for_matching is true, 266bf215546Sopenharmony_ci * EGL_DONT_CARE is accepted as a valid attribute value, and checks 267bf215546Sopenharmony_ci * for conflicting attribute values are skipped. 268bf215546Sopenharmony_ci * 269bf215546Sopenharmony_ci * Note that some attributes are platform-dependent and are not 270bf215546Sopenharmony_ci * checked. 271bf215546Sopenharmony_ci */ 272bf215546Sopenharmony_ciEGLBoolean 273bf215546Sopenharmony_ci_eglValidateConfig(const _EGLConfig *conf, EGLBoolean for_matching) 274bf215546Sopenharmony_ci{ 275bf215546Sopenharmony_ci _EGLDisplay *disp = conf->Display; 276bf215546Sopenharmony_ci EGLint i, attr, val; 277bf215546Sopenharmony_ci EGLBoolean valid = EGL_TRUE; 278bf215546Sopenharmony_ci 279bf215546Sopenharmony_ci /* check attributes by their types */ 280bf215546Sopenharmony_ci for (i = 0; i < ARRAY_SIZE(_eglValidationTable); i++) { 281bf215546Sopenharmony_ci EGLint mask; 282bf215546Sopenharmony_ci 283bf215546Sopenharmony_ci attr = _eglValidationTable[i].attr; 284bf215546Sopenharmony_ci val = _eglGetConfigKey(conf, attr); 285bf215546Sopenharmony_ci 286bf215546Sopenharmony_ci switch (_eglValidationTable[i].type) { 287bf215546Sopenharmony_ci case ATTRIB_TYPE_INTEGER: 288bf215546Sopenharmony_ci switch (attr) { 289bf215546Sopenharmony_ci case EGL_CONFIG_ID: 290bf215546Sopenharmony_ci /* config id must be positive */ 291bf215546Sopenharmony_ci if (val <= 0) 292bf215546Sopenharmony_ci valid = EGL_FALSE; 293bf215546Sopenharmony_ci break; 294bf215546Sopenharmony_ci case EGL_SAMPLE_BUFFERS: 295bf215546Sopenharmony_ci /* there can be at most 1 sample buffer */ 296bf215546Sopenharmony_ci if (val > 1 || val < 0) 297bf215546Sopenharmony_ci valid = EGL_FALSE; 298bf215546Sopenharmony_ci break; 299bf215546Sopenharmony_ci default: 300bf215546Sopenharmony_ci if (val < 0) 301bf215546Sopenharmony_ci valid = EGL_FALSE; 302bf215546Sopenharmony_ci break; 303bf215546Sopenharmony_ci } 304bf215546Sopenharmony_ci break; 305bf215546Sopenharmony_ci case ATTRIB_TYPE_BOOLEAN: 306bf215546Sopenharmony_ci if (val != EGL_TRUE && val != EGL_FALSE) 307bf215546Sopenharmony_ci valid = EGL_FALSE; 308bf215546Sopenharmony_ci break; 309bf215546Sopenharmony_ci case ATTRIB_TYPE_ENUM: 310bf215546Sopenharmony_ci switch (attr) { 311bf215546Sopenharmony_ci case EGL_CONFIG_CAVEAT: 312bf215546Sopenharmony_ci if (val != EGL_NONE && val != EGL_SLOW_CONFIG && 313bf215546Sopenharmony_ci val != EGL_NON_CONFORMANT_CONFIG) 314bf215546Sopenharmony_ci valid = EGL_FALSE; 315bf215546Sopenharmony_ci break; 316bf215546Sopenharmony_ci case EGL_TRANSPARENT_TYPE: 317bf215546Sopenharmony_ci if (val != EGL_NONE && val != EGL_TRANSPARENT_RGB) 318bf215546Sopenharmony_ci valid = EGL_FALSE; 319bf215546Sopenharmony_ci break; 320bf215546Sopenharmony_ci case EGL_COLOR_BUFFER_TYPE: 321bf215546Sopenharmony_ci if (val != EGL_RGB_BUFFER && val != EGL_LUMINANCE_BUFFER) 322bf215546Sopenharmony_ci valid = EGL_FALSE; 323bf215546Sopenharmony_ci break; 324bf215546Sopenharmony_ci case EGL_COLOR_COMPONENT_TYPE_EXT: 325bf215546Sopenharmony_ci if (val != EGL_COLOR_COMPONENT_TYPE_FIXED_EXT && 326bf215546Sopenharmony_ci val != EGL_COLOR_COMPONENT_TYPE_FLOAT_EXT) 327bf215546Sopenharmony_ci valid = EGL_FALSE; 328bf215546Sopenharmony_ci break; 329bf215546Sopenharmony_ci default: 330bf215546Sopenharmony_ci unreachable("check _eglValidationTable[]"); 331bf215546Sopenharmony_ci break; 332bf215546Sopenharmony_ci } 333bf215546Sopenharmony_ci break; 334bf215546Sopenharmony_ci case ATTRIB_TYPE_BITMASK: 335bf215546Sopenharmony_ci switch (attr) { 336bf215546Sopenharmony_ci case EGL_SURFACE_TYPE: 337bf215546Sopenharmony_ci mask = EGL_PBUFFER_BIT | 338bf215546Sopenharmony_ci EGL_PIXMAP_BIT | 339bf215546Sopenharmony_ci EGL_WINDOW_BIT | 340bf215546Sopenharmony_ci EGL_VG_COLORSPACE_LINEAR_BIT | 341bf215546Sopenharmony_ci EGL_VG_ALPHA_FORMAT_PRE_BIT | 342bf215546Sopenharmony_ci EGL_MULTISAMPLE_RESOLVE_BOX_BIT | 343bf215546Sopenharmony_ci EGL_SWAP_BEHAVIOR_PRESERVED_BIT; 344bf215546Sopenharmony_ci if (disp->Extensions.KHR_mutable_render_buffer) 345bf215546Sopenharmony_ci mask |= EGL_MUTABLE_RENDER_BUFFER_BIT_KHR; 346bf215546Sopenharmony_ci break; 347bf215546Sopenharmony_ci case EGL_RENDERABLE_TYPE: 348bf215546Sopenharmony_ci case EGL_CONFORMANT: 349bf215546Sopenharmony_ci mask = EGL_OPENGL_ES_BIT | 350bf215546Sopenharmony_ci EGL_OPENVG_BIT | 351bf215546Sopenharmony_ci EGL_OPENGL_ES2_BIT | 352bf215546Sopenharmony_ci EGL_OPENGL_ES3_BIT_KHR | 353bf215546Sopenharmony_ci EGL_OPENGL_BIT; 354bf215546Sopenharmony_ci break; 355bf215546Sopenharmony_ci default: 356bf215546Sopenharmony_ci unreachable("check _eglValidationTable[]"); 357bf215546Sopenharmony_ci mask = 0; 358bf215546Sopenharmony_ci break; 359bf215546Sopenharmony_ci } 360bf215546Sopenharmony_ci if (val & ~mask) 361bf215546Sopenharmony_ci valid = EGL_FALSE; 362bf215546Sopenharmony_ci break; 363bf215546Sopenharmony_ci case ATTRIB_TYPE_PLATFORM: 364bf215546Sopenharmony_ci /* unable to check platform-dependent attributes here */ 365bf215546Sopenharmony_ci break; 366bf215546Sopenharmony_ci case ATTRIB_TYPE_PSEUDO: 367bf215546Sopenharmony_ci /* pseudo attributes should not be set */ 368bf215546Sopenharmony_ci if (val != 0) 369bf215546Sopenharmony_ci valid = EGL_FALSE; 370bf215546Sopenharmony_ci break; 371bf215546Sopenharmony_ci } 372bf215546Sopenharmony_ci 373bf215546Sopenharmony_ci if (!valid && for_matching) { 374bf215546Sopenharmony_ci /* accept EGL_DONT_CARE as a valid value */ 375bf215546Sopenharmony_ci if (val == EGL_DONT_CARE) 376bf215546Sopenharmony_ci valid = EGL_TRUE; 377bf215546Sopenharmony_ci if (_eglValidationTable[i].criterion == ATTRIB_CRITERION_SPECIAL) 378bf215546Sopenharmony_ci valid = EGL_TRUE; 379bf215546Sopenharmony_ci } 380bf215546Sopenharmony_ci if (!valid) { 381bf215546Sopenharmony_ci _eglLog(_EGL_DEBUG, 382bf215546Sopenharmony_ci "attribute 0x%04x has an invalid value 0x%x", attr, val); 383bf215546Sopenharmony_ci break; 384bf215546Sopenharmony_ci } 385bf215546Sopenharmony_ci } 386bf215546Sopenharmony_ci 387bf215546Sopenharmony_ci /* any invalid attribute value should have been catched */ 388bf215546Sopenharmony_ci if (!valid || for_matching) 389bf215546Sopenharmony_ci return valid; 390bf215546Sopenharmony_ci 391bf215546Sopenharmony_ci /* now check for conflicting attribute values */ 392bf215546Sopenharmony_ci 393bf215546Sopenharmony_ci switch (conf->ColorBufferType) { 394bf215546Sopenharmony_ci case EGL_RGB_BUFFER: 395bf215546Sopenharmony_ci if (conf->LuminanceSize) 396bf215546Sopenharmony_ci valid = EGL_FALSE; 397bf215546Sopenharmony_ci if (conf->RedSize + conf->GreenSize + 398bf215546Sopenharmony_ci conf->BlueSize + conf->AlphaSize != conf->BufferSize) 399bf215546Sopenharmony_ci valid = EGL_FALSE; 400bf215546Sopenharmony_ci break; 401bf215546Sopenharmony_ci case EGL_LUMINANCE_BUFFER: 402bf215546Sopenharmony_ci if (conf->RedSize || conf->GreenSize || conf->BlueSize) 403bf215546Sopenharmony_ci valid = EGL_FALSE; 404bf215546Sopenharmony_ci if (conf->LuminanceSize + conf->AlphaSize != conf->BufferSize) 405bf215546Sopenharmony_ci valid = EGL_FALSE; 406bf215546Sopenharmony_ci break; 407bf215546Sopenharmony_ci } 408bf215546Sopenharmony_ci if (!valid) { 409bf215546Sopenharmony_ci _eglLog(_EGL_DEBUG, "conflicting color buffer type and channel sizes"); 410bf215546Sopenharmony_ci return EGL_FALSE; 411bf215546Sopenharmony_ci } 412bf215546Sopenharmony_ci 413bf215546Sopenharmony_ci if (!conf->SampleBuffers && conf->Samples) 414bf215546Sopenharmony_ci valid = EGL_FALSE; 415bf215546Sopenharmony_ci if (!valid) { 416bf215546Sopenharmony_ci _eglLog(_EGL_DEBUG, "conflicting samples and sample buffers"); 417bf215546Sopenharmony_ci return EGL_FALSE; 418bf215546Sopenharmony_ci } 419bf215546Sopenharmony_ci 420bf215546Sopenharmony_ci if (!(conf->SurfaceType & EGL_WINDOW_BIT)) { 421bf215546Sopenharmony_ci if (conf->NativeVisualID != 0 || conf->NativeVisualType != EGL_NONE) 422bf215546Sopenharmony_ci valid = EGL_FALSE; 423bf215546Sopenharmony_ci } 424bf215546Sopenharmony_ci if (!(conf->SurfaceType & EGL_PBUFFER_BIT)) { 425bf215546Sopenharmony_ci if (conf->BindToTextureRGB || conf->BindToTextureRGBA) 426bf215546Sopenharmony_ci valid = EGL_FALSE; 427bf215546Sopenharmony_ci } 428bf215546Sopenharmony_ci if (!valid) { 429bf215546Sopenharmony_ci _eglLog(_EGL_DEBUG, "conflicting surface type and native visual/texture binding"); 430bf215546Sopenharmony_ci return EGL_FALSE; 431bf215546Sopenharmony_ci } 432bf215546Sopenharmony_ci 433bf215546Sopenharmony_ci return valid; 434bf215546Sopenharmony_ci} 435bf215546Sopenharmony_ci 436bf215546Sopenharmony_ci 437bf215546Sopenharmony_ci/** 438bf215546Sopenharmony_ci * Return true if a config matches the criteria. This and 439bf215546Sopenharmony_ci * _eglParseConfigAttribList together implement the algorithm 440bf215546Sopenharmony_ci * described in "Selection of EGLConfigs". 441bf215546Sopenharmony_ci * 442bf215546Sopenharmony_ci * Note that attributes that are special (currently, only 443bf215546Sopenharmony_ci * EGL_MATCH_NATIVE_PIXMAP) are ignored. 444bf215546Sopenharmony_ci */ 445bf215546Sopenharmony_ciEGLBoolean 446bf215546Sopenharmony_ci_eglMatchConfig(const _EGLConfig *conf, const _EGLConfig *criteria) 447bf215546Sopenharmony_ci{ 448bf215546Sopenharmony_ci EGLint attr, val, i; 449bf215546Sopenharmony_ci EGLBoolean matched = EGL_TRUE; 450bf215546Sopenharmony_ci 451bf215546Sopenharmony_ci for (i = 0; i < ARRAY_SIZE(_eglValidationTable); i++) { 452bf215546Sopenharmony_ci EGLint cmp; 453bf215546Sopenharmony_ci if (_eglValidationTable[i].criterion == ATTRIB_CRITERION_IGNORE) 454bf215546Sopenharmony_ci continue; 455bf215546Sopenharmony_ci 456bf215546Sopenharmony_ci attr = _eglValidationTable[i].attr; 457bf215546Sopenharmony_ci cmp = _eglGetConfigKey(criteria, attr); 458bf215546Sopenharmony_ci if (cmp == EGL_DONT_CARE) 459bf215546Sopenharmony_ci continue; 460bf215546Sopenharmony_ci 461bf215546Sopenharmony_ci val = _eglGetConfigKey(conf, attr); 462bf215546Sopenharmony_ci switch (_eglValidationTable[i].criterion) { 463bf215546Sopenharmony_ci case ATTRIB_CRITERION_EXACT: 464bf215546Sopenharmony_ci if (val != cmp) 465bf215546Sopenharmony_ci matched = EGL_FALSE; 466bf215546Sopenharmony_ci break; 467bf215546Sopenharmony_ci case ATTRIB_CRITERION_ATLEAST: 468bf215546Sopenharmony_ci if (val < cmp) 469bf215546Sopenharmony_ci matched = EGL_FALSE; 470bf215546Sopenharmony_ci break; 471bf215546Sopenharmony_ci case ATTRIB_CRITERION_MASK: 472bf215546Sopenharmony_ci if ((val & cmp) != cmp) 473bf215546Sopenharmony_ci matched = EGL_FALSE; 474bf215546Sopenharmony_ci break; 475bf215546Sopenharmony_ci case ATTRIB_CRITERION_SPECIAL: 476bf215546Sopenharmony_ci /* ignored here */ 477bf215546Sopenharmony_ci break; 478bf215546Sopenharmony_ci case ATTRIB_CRITERION_IGNORE: 479bf215546Sopenharmony_ci unreachable("already handled above"); 480bf215546Sopenharmony_ci break; 481bf215546Sopenharmony_ci } 482bf215546Sopenharmony_ci 483bf215546Sopenharmony_ci if (!matched) { 484bf215546Sopenharmony_ci#ifndef DEBUG 485bf215546Sopenharmony_ci /* only print the common errors when DEBUG is not defined */ 486bf215546Sopenharmony_ci if (attr != EGL_RENDERABLE_TYPE) 487bf215546Sopenharmony_ci break; 488bf215546Sopenharmony_ci#endif 489bf215546Sopenharmony_ci _eglLog(_EGL_DEBUG, 490bf215546Sopenharmony_ci "the value (0x%x) of attribute 0x%04x did not meet the criteria (0x%x)", 491bf215546Sopenharmony_ci val, attr, cmp); 492bf215546Sopenharmony_ci break; 493bf215546Sopenharmony_ci } 494bf215546Sopenharmony_ci } 495bf215546Sopenharmony_ci 496bf215546Sopenharmony_ci return matched; 497bf215546Sopenharmony_ci} 498bf215546Sopenharmony_ci 499bf215546Sopenharmony_cistatic inline EGLBoolean 500bf215546Sopenharmony_ci_eglIsConfigAttribValid(_EGLConfig *conf, EGLint attr) 501bf215546Sopenharmony_ci{ 502bf215546Sopenharmony_ci if (_eglOffsetOfConfig(attr) < 0) 503bf215546Sopenharmony_ci return EGL_FALSE; 504bf215546Sopenharmony_ci 505bf215546Sopenharmony_ci switch (attr) { 506bf215546Sopenharmony_ci case EGL_Y_INVERTED_NOK: 507bf215546Sopenharmony_ci return conf->Display->Extensions.NOK_texture_from_pixmap; 508bf215546Sopenharmony_ci case EGL_FRAMEBUFFER_TARGET_ANDROID: 509bf215546Sopenharmony_ci return conf->Display->Extensions.ANDROID_framebuffer_target; 510bf215546Sopenharmony_ci case EGL_RECORDABLE_ANDROID: 511bf215546Sopenharmony_ci return conf->Display->Extensions.ANDROID_recordable; 512bf215546Sopenharmony_ci default: 513bf215546Sopenharmony_ci break; 514bf215546Sopenharmony_ci } 515bf215546Sopenharmony_ci 516bf215546Sopenharmony_ci return EGL_TRUE; 517bf215546Sopenharmony_ci} 518bf215546Sopenharmony_ci 519bf215546Sopenharmony_ci/** 520bf215546Sopenharmony_ci * Initialize a criteria config from the given attribute list. 521bf215546Sopenharmony_ci * Return EGL_FALSE if any of the attribute is invalid. 522bf215546Sopenharmony_ci */ 523bf215546Sopenharmony_ciEGLBoolean 524bf215546Sopenharmony_ci_eglParseConfigAttribList(_EGLConfig *conf, _EGLDisplay *disp, 525bf215546Sopenharmony_ci const EGLint *attrib_list) 526bf215546Sopenharmony_ci{ 527bf215546Sopenharmony_ci EGLint attr, val, i; 528bf215546Sopenharmony_ci 529bf215546Sopenharmony_ci _eglInitConfig(conf, disp, EGL_DONT_CARE); 530bf215546Sopenharmony_ci 531bf215546Sopenharmony_ci /* reset to default values */ 532bf215546Sopenharmony_ci for (i = 0; i < ARRAY_SIZE(_eglValidationTable); i++) { 533bf215546Sopenharmony_ci attr = _eglValidationTable[i].attr; 534bf215546Sopenharmony_ci val = _eglValidationTable[i].default_value; 535bf215546Sopenharmony_ci _eglSetConfigKey(conf, attr, val); 536bf215546Sopenharmony_ci } 537bf215546Sopenharmony_ci 538bf215546Sopenharmony_ci /* parse the list */ 539bf215546Sopenharmony_ci for (i = 0; attrib_list && attrib_list[i] != EGL_NONE; i += 2) { 540bf215546Sopenharmony_ci attr = attrib_list[i]; 541bf215546Sopenharmony_ci val = attrib_list[i + 1]; 542bf215546Sopenharmony_ci 543bf215546Sopenharmony_ci if (!_eglIsConfigAttribValid(conf, attr)) 544bf215546Sopenharmony_ci return EGL_FALSE; 545bf215546Sopenharmony_ci 546bf215546Sopenharmony_ci _eglSetConfigKey(conf, attr, val); 547bf215546Sopenharmony_ci } 548bf215546Sopenharmony_ci 549bf215546Sopenharmony_ci if (!_eglValidateConfig(conf, EGL_TRUE)) 550bf215546Sopenharmony_ci return EGL_FALSE; 551bf215546Sopenharmony_ci 552bf215546Sopenharmony_ci /* EGL_LEVEL and EGL_MATCH_NATIVE_PIXMAP cannot be EGL_DONT_CARE */ 553bf215546Sopenharmony_ci if (conf->Level == EGL_DONT_CARE || 554bf215546Sopenharmony_ci conf->MatchNativePixmap == EGL_DONT_CARE) 555bf215546Sopenharmony_ci return EGL_FALSE; 556bf215546Sopenharmony_ci 557bf215546Sopenharmony_ci /* ignore other attributes when EGL_CONFIG_ID is given */ 558bf215546Sopenharmony_ci if (conf->ConfigID != EGL_DONT_CARE) { 559bf215546Sopenharmony_ci for (i = 0; i < ARRAY_SIZE(_eglValidationTable); i++) { 560bf215546Sopenharmony_ci attr = _eglValidationTable[i].attr; 561bf215546Sopenharmony_ci if (attr != EGL_CONFIG_ID) 562bf215546Sopenharmony_ci _eglSetConfigKey(conf, attr, EGL_DONT_CARE); 563bf215546Sopenharmony_ci } 564bf215546Sopenharmony_ci } 565bf215546Sopenharmony_ci else { 566bf215546Sopenharmony_ci if (!(conf->SurfaceType & EGL_WINDOW_BIT)) 567bf215546Sopenharmony_ci conf->NativeVisualType = EGL_DONT_CARE; 568bf215546Sopenharmony_ci 569bf215546Sopenharmony_ci if (conf->TransparentType == EGL_NONE) { 570bf215546Sopenharmony_ci conf->TransparentRedValue = EGL_DONT_CARE; 571bf215546Sopenharmony_ci conf->TransparentGreenValue = EGL_DONT_CARE; 572bf215546Sopenharmony_ci conf->TransparentBlueValue = EGL_DONT_CARE; 573bf215546Sopenharmony_ci } 574bf215546Sopenharmony_ci } 575bf215546Sopenharmony_ci 576bf215546Sopenharmony_ci return EGL_TRUE; 577bf215546Sopenharmony_ci} 578bf215546Sopenharmony_ci 579bf215546Sopenharmony_ci 580bf215546Sopenharmony_ci/** 581bf215546Sopenharmony_ci * Decide the ordering of conf1 and conf2, under the given criteria. 582bf215546Sopenharmony_ci * When compare_id is true, this implements the algorithm described 583bf215546Sopenharmony_ci * in "Sorting of EGLConfigs". When compare_id is false, 584bf215546Sopenharmony_ci * EGL_CONFIG_ID is not compared. 585bf215546Sopenharmony_ci * 586bf215546Sopenharmony_ci * It returns a negative integer if conf1 is considered to come 587bf215546Sopenharmony_ci * before conf2; a positive integer if conf2 is considered to come 588bf215546Sopenharmony_ci * before conf1; zero if the ordering cannot be decided. 589bf215546Sopenharmony_ci * 590bf215546Sopenharmony_ci * Note that EGL_NATIVE_VISUAL_TYPE is platform-dependent and is 591bf215546Sopenharmony_ci * ignored here. 592bf215546Sopenharmony_ci */ 593bf215546Sopenharmony_ciEGLint 594bf215546Sopenharmony_ci_eglCompareConfigs(const _EGLConfig *conf1, const _EGLConfig *conf2, 595bf215546Sopenharmony_ci const _EGLConfig *criteria, EGLBoolean compare_id) 596bf215546Sopenharmony_ci{ 597bf215546Sopenharmony_ci const EGLint compare_attribs[] = { 598bf215546Sopenharmony_ci EGL_BUFFER_SIZE, 599bf215546Sopenharmony_ci EGL_SAMPLE_BUFFERS, 600bf215546Sopenharmony_ci EGL_SAMPLES, 601bf215546Sopenharmony_ci EGL_DEPTH_SIZE, 602bf215546Sopenharmony_ci EGL_STENCIL_SIZE, 603bf215546Sopenharmony_ci EGL_ALPHA_MASK_SIZE, 604bf215546Sopenharmony_ci }; 605bf215546Sopenharmony_ci EGLint val1, val2; 606bf215546Sopenharmony_ci EGLint i; 607bf215546Sopenharmony_ci 608bf215546Sopenharmony_ci if (conf1 == conf2) 609bf215546Sopenharmony_ci return 0; 610bf215546Sopenharmony_ci 611bf215546Sopenharmony_ci /* the enum values have the desired ordering */ 612bf215546Sopenharmony_ci STATIC_ASSERT(EGL_NONE < EGL_SLOW_CONFIG); 613bf215546Sopenharmony_ci STATIC_ASSERT(EGL_SLOW_CONFIG < EGL_NON_CONFORMANT_CONFIG); 614bf215546Sopenharmony_ci val1 = conf1->ConfigCaveat - conf2->ConfigCaveat; 615bf215546Sopenharmony_ci if (val1) 616bf215546Sopenharmony_ci return val1; 617bf215546Sopenharmony_ci 618bf215546Sopenharmony_ci /* the enum values have the desired ordering */ 619bf215546Sopenharmony_ci STATIC_ASSERT(EGL_RGB_BUFFER < EGL_LUMINANCE_BUFFER); 620bf215546Sopenharmony_ci val1 = conf1->ColorBufferType - conf2->ColorBufferType; 621bf215546Sopenharmony_ci if (val1) 622bf215546Sopenharmony_ci return val1; 623bf215546Sopenharmony_ci 624bf215546Sopenharmony_ci if (criteria) { 625bf215546Sopenharmony_ci val1 = val2 = 0; 626bf215546Sopenharmony_ci if (conf1->ColorBufferType == EGL_RGB_BUFFER) { 627bf215546Sopenharmony_ci if (criteria->RedSize > 0) { 628bf215546Sopenharmony_ci val1 += conf1->RedSize; 629bf215546Sopenharmony_ci val2 += conf2->RedSize; 630bf215546Sopenharmony_ci } 631bf215546Sopenharmony_ci if (criteria->GreenSize > 0) { 632bf215546Sopenharmony_ci val1 += conf1->GreenSize; 633bf215546Sopenharmony_ci val2 += conf2->GreenSize; 634bf215546Sopenharmony_ci } 635bf215546Sopenharmony_ci if (criteria->BlueSize > 0) { 636bf215546Sopenharmony_ci val1 += conf1->BlueSize; 637bf215546Sopenharmony_ci val2 += conf2->BlueSize; 638bf215546Sopenharmony_ci } 639bf215546Sopenharmony_ci } 640bf215546Sopenharmony_ci else { 641bf215546Sopenharmony_ci if (criteria->LuminanceSize > 0) { 642bf215546Sopenharmony_ci val1 += conf1->LuminanceSize; 643bf215546Sopenharmony_ci val2 += conf2->LuminanceSize; 644bf215546Sopenharmony_ci } 645bf215546Sopenharmony_ci } 646bf215546Sopenharmony_ci if (criteria->AlphaSize > 0) { 647bf215546Sopenharmony_ci val1 += conf1->AlphaSize; 648bf215546Sopenharmony_ci val2 += conf2->AlphaSize; 649bf215546Sopenharmony_ci } 650bf215546Sopenharmony_ci } 651bf215546Sopenharmony_ci else { 652bf215546Sopenharmony_ci /* assume the default criteria, which gives no specific ordering */ 653bf215546Sopenharmony_ci val1 = val2 = 0; 654bf215546Sopenharmony_ci } 655bf215546Sopenharmony_ci 656bf215546Sopenharmony_ci /* for color bits, larger one is preferred */ 657bf215546Sopenharmony_ci if (val1 != val2) 658bf215546Sopenharmony_ci return (val2 - val1); 659bf215546Sopenharmony_ci 660bf215546Sopenharmony_ci for (i = 0; i < ARRAY_SIZE(compare_attribs); i++) { 661bf215546Sopenharmony_ci val1 = _eglGetConfigKey(conf1, compare_attribs[i]); 662bf215546Sopenharmony_ci val2 = _eglGetConfigKey(conf2, compare_attribs[i]); 663bf215546Sopenharmony_ci if (val1 != val2) 664bf215546Sopenharmony_ci return (val1 - val2); 665bf215546Sopenharmony_ci } 666bf215546Sopenharmony_ci 667bf215546Sopenharmony_ci /* EGL_NATIVE_VISUAL_TYPE cannot be compared here */ 668bf215546Sopenharmony_ci 669bf215546Sopenharmony_ci return (compare_id) ? (conf1->ConfigID - conf2->ConfigID) : 0; 670bf215546Sopenharmony_ci} 671bf215546Sopenharmony_ci 672bf215546Sopenharmony_ci 673bf215546Sopenharmony_cistatic inline 674bf215546Sopenharmony_civoid _eglSwapConfigs(const _EGLConfig **conf1, const _EGLConfig **conf2) 675bf215546Sopenharmony_ci{ 676bf215546Sopenharmony_ci const _EGLConfig *tmp = *conf1; 677bf215546Sopenharmony_ci *conf1 = *conf2; 678bf215546Sopenharmony_ci *conf2 = tmp; 679bf215546Sopenharmony_ci} 680bf215546Sopenharmony_ci 681bf215546Sopenharmony_ci 682bf215546Sopenharmony_ci/** 683bf215546Sopenharmony_ci * Quick sort an array of configs. This differs from the standard 684bf215546Sopenharmony_ci * qsort() in that the compare function accepts an additional 685bf215546Sopenharmony_ci * argument. 686bf215546Sopenharmony_ci */ 687bf215546Sopenharmony_cistatic void 688bf215546Sopenharmony_ci_eglSortConfigs(const _EGLConfig **configs, EGLint count, 689bf215546Sopenharmony_ci EGLint (*compare)(const _EGLConfig *, const _EGLConfig *, 690bf215546Sopenharmony_ci void *), 691bf215546Sopenharmony_ci void *priv_data) 692bf215546Sopenharmony_ci{ 693bf215546Sopenharmony_ci const EGLint pivot = 0; 694bf215546Sopenharmony_ci EGLint i, j; 695bf215546Sopenharmony_ci 696bf215546Sopenharmony_ci if (count <= 1) 697bf215546Sopenharmony_ci return; 698bf215546Sopenharmony_ci 699bf215546Sopenharmony_ci _eglSwapConfigs(&configs[pivot], &configs[count / 2]); 700bf215546Sopenharmony_ci i = 1; 701bf215546Sopenharmony_ci j = count - 1; 702bf215546Sopenharmony_ci do { 703bf215546Sopenharmony_ci while (i < count && compare(configs[i], configs[pivot], priv_data) < 0) 704bf215546Sopenharmony_ci i++; 705bf215546Sopenharmony_ci while (compare(configs[j], configs[pivot], priv_data) > 0) 706bf215546Sopenharmony_ci j--; 707bf215546Sopenharmony_ci if (i < j) { 708bf215546Sopenharmony_ci _eglSwapConfigs(&configs[i], &configs[j]); 709bf215546Sopenharmony_ci i++; 710bf215546Sopenharmony_ci j--; 711bf215546Sopenharmony_ci } 712bf215546Sopenharmony_ci else if (i == j) { 713bf215546Sopenharmony_ci i++; 714bf215546Sopenharmony_ci j--; 715bf215546Sopenharmony_ci break; 716bf215546Sopenharmony_ci } 717bf215546Sopenharmony_ci } while (i <= j); 718bf215546Sopenharmony_ci _eglSwapConfigs(&configs[pivot], &configs[j]); 719bf215546Sopenharmony_ci 720bf215546Sopenharmony_ci _eglSortConfigs(configs, j, compare, priv_data); 721bf215546Sopenharmony_ci _eglSortConfigs(configs + i, count - i, compare, priv_data); 722bf215546Sopenharmony_ci} 723bf215546Sopenharmony_ci 724bf215546Sopenharmony_ci 725bf215546Sopenharmony_ci/** 726bf215546Sopenharmony_ci * A helper function for implementing eglChooseConfig. See _eglFilterArray and 727bf215546Sopenharmony_ci * _eglSortConfigs for the meanings of match and compare. 728bf215546Sopenharmony_ci */ 729bf215546Sopenharmony_ciEGLBoolean 730bf215546Sopenharmony_ci_eglFilterConfigArray(_EGLArray *array, EGLConfig *configs, 731bf215546Sopenharmony_ci EGLint config_size, EGLint *num_configs, 732bf215546Sopenharmony_ci EGLBoolean (*match)(const _EGLConfig *, void *), 733bf215546Sopenharmony_ci EGLint (*compare)(const _EGLConfig *, const _EGLConfig *, 734bf215546Sopenharmony_ci void *), 735bf215546Sopenharmony_ci void *priv_data) 736bf215546Sopenharmony_ci{ 737bf215546Sopenharmony_ci _EGLConfig **configList; 738bf215546Sopenharmony_ci EGLint i, count; 739bf215546Sopenharmony_ci 740bf215546Sopenharmony_ci /* get the number of matched configs */ 741bf215546Sopenharmony_ci count = _eglFilterArray(array, NULL, 0, 742bf215546Sopenharmony_ci (_EGLArrayForEach) match, priv_data); 743bf215546Sopenharmony_ci if (!count) { 744bf215546Sopenharmony_ci *num_configs = count; 745bf215546Sopenharmony_ci return EGL_TRUE; 746bf215546Sopenharmony_ci } 747bf215546Sopenharmony_ci 748bf215546Sopenharmony_ci configList = malloc(sizeof(*configList) * count); 749bf215546Sopenharmony_ci if (!configList) 750bf215546Sopenharmony_ci return _eglError(EGL_BAD_ALLOC, "eglChooseConfig(out of memory)"); 751bf215546Sopenharmony_ci 752bf215546Sopenharmony_ci /* get the matched configs */ 753bf215546Sopenharmony_ci _eglFilterArray(array, (void **) configList, count, 754bf215546Sopenharmony_ci (_EGLArrayForEach) match, priv_data); 755bf215546Sopenharmony_ci 756bf215546Sopenharmony_ci /* perform sorting of configs */ 757bf215546Sopenharmony_ci if (configs && count) { 758bf215546Sopenharmony_ci _eglSortConfigs((const _EGLConfig **) configList, count, 759bf215546Sopenharmony_ci compare, priv_data); 760bf215546Sopenharmony_ci count = MIN2(count, config_size); 761bf215546Sopenharmony_ci for (i = 0; i < count; i++) 762bf215546Sopenharmony_ci configs[i] = _eglGetConfigHandle(configList[i]); 763bf215546Sopenharmony_ci } 764bf215546Sopenharmony_ci 765bf215546Sopenharmony_ci free(configList); 766bf215546Sopenharmony_ci 767bf215546Sopenharmony_ci *num_configs = count; 768bf215546Sopenharmony_ci 769bf215546Sopenharmony_ci return EGL_TRUE; 770bf215546Sopenharmony_ci} 771bf215546Sopenharmony_ci 772bf215546Sopenharmony_ci 773bf215546Sopenharmony_cistatic EGLBoolean 774bf215546Sopenharmony_ci_eglFallbackMatch(const _EGLConfig *conf, void *priv_data) 775bf215546Sopenharmony_ci{ 776bf215546Sopenharmony_ci return _eglMatchConfig(conf, (const _EGLConfig *) priv_data); 777bf215546Sopenharmony_ci} 778bf215546Sopenharmony_ci 779bf215546Sopenharmony_ci 780bf215546Sopenharmony_cistatic EGLint 781bf215546Sopenharmony_ci_eglFallbackCompare(const _EGLConfig *conf1, const _EGLConfig *conf2, 782bf215546Sopenharmony_ci void *priv_data) 783bf215546Sopenharmony_ci{ 784bf215546Sopenharmony_ci return _eglCompareConfigs(conf1, conf2, 785bf215546Sopenharmony_ci (const _EGLConfig *) priv_data, EGL_TRUE); 786bf215546Sopenharmony_ci} 787bf215546Sopenharmony_ci 788bf215546Sopenharmony_ci 789bf215546Sopenharmony_ci/** 790bf215546Sopenharmony_ci * Typical fallback routine for eglChooseConfig 791bf215546Sopenharmony_ci */ 792bf215546Sopenharmony_ciEGLBoolean 793bf215546Sopenharmony_ci_eglChooseConfig(_EGLDisplay *disp, const EGLint *attrib_list, 794bf215546Sopenharmony_ci EGLConfig *configs, EGLint config_size, EGLint *num_configs) 795bf215546Sopenharmony_ci{ 796bf215546Sopenharmony_ci _EGLConfig criteria; 797bf215546Sopenharmony_ci EGLBoolean result; 798bf215546Sopenharmony_ci 799bf215546Sopenharmony_ci if (!_eglParseConfigAttribList(&criteria, disp, attrib_list)) 800bf215546Sopenharmony_ci return _eglError(EGL_BAD_ATTRIBUTE, "eglChooseConfig"); 801bf215546Sopenharmony_ci 802bf215546Sopenharmony_ci result = _eglFilterConfigArray(disp->Configs, 803bf215546Sopenharmony_ci configs, config_size, num_configs, 804bf215546Sopenharmony_ci _eglFallbackMatch, _eglFallbackCompare, 805bf215546Sopenharmony_ci (void *) &criteria); 806bf215546Sopenharmony_ci 807bf215546Sopenharmony_ci if (result && (_eglGetLogLevel() == _EGL_DEBUG)) 808bf215546Sopenharmony_ci eglPrintConfigDebug(disp, configs, *num_configs, EGL_TRUE); 809bf215546Sopenharmony_ci 810bf215546Sopenharmony_ci return result; 811bf215546Sopenharmony_ci} 812bf215546Sopenharmony_ci 813bf215546Sopenharmony_ci 814bf215546Sopenharmony_ci/** 815bf215546Sopenharmony_ci * Fallback for eglGetConfigAttrib. 816bf215546Sopenharmony_ci */ 817bf215546Sopenharmony_ciEGLBoolean 818bf215546Sopenharmony_ci_eglGetConfigAttrib(_EGLDisplay *disp, _EGLConfig *conf, 819bf215546Sopenharmony_ci EGLint attribute, EGLint *value) 820bf215546Sopenharmony_ci{ 821bf215546Sopenharmony_ci if (!_eglIsConfigAttribValid(conf, attribute)) 822bf215546Sopenharmony_ci return _eglError(EGL_BAD_ATTRIBUTE, "eglGetConfigAttrib"); 823bf215546Sopenharmony_ci 824bf215546Sopenharmony_ci /* nonqueryable attributes */ 825bf215546Sopenharmony_ci switch (attribute) { 826bf215546Sopenharmony_ci case EGL_MATCH_NATIVE_PIXMAP: 827bf215546Sopenharmony_ci return _eglError(EGL_BAD_ATTRIBUTE, "eglGetConfigAttrib"); 828bf215546Sopenharmony_ci break; 829bf215546Sopenharmony_ci default: 830bf215546Sopenharmony_ci break; 831bf215546Sopenharmony_ci } 832bf215546Sopenharmony_ci 833bf215546Sopenharmony_ci if (!value) 834bf215546Sopenharmony_ci return _eglError(EGL_BAD_PARAMETER, "eglGetConfigAttrib"); 835bf215546Sopenharmony_ci 836bf215546Sopenharmony_ci *value = _eglGetConfigKey(conf, attribute); 837bf215546Sopenharmony_ci return EGL_TRUE; 838bf215546Sopenharmony_ci} 839bf215546Sopenharmony_ci 840bf215546Sopenharmony_ci 841bf215546Sopenharmony_cistatic EGLBoolean 842bf215546Sopenharmony_ci_eglFlattenConfig(void *elem, void *buffer) 843bf215546Sopenharmony_ci{ 844bf215546Sopenharmony_ci _EGLConfig *conf = (_EGLConfig *) elem; 845bf215546Sopenharmony_ci EGLConfig *handle = (EGLConfig *) buffer; 846bf215546Sopenharmony_ci *handle = _eglGetConfigHandle(conf); 847bf215546Sopenharmony_ci return EGL_TRUE; 848bf215546Sopenharmony_ci} 849bf215546Sopenharmony_ci 850bf215546Sopenharmony_ci/** 851bf215546Sopenharmony_ci * Fallback for eglGetConfigs. 852bf215546Sopenharmony_ci */ 853bf215546Sopenharmony_ciEGLBoolean 854bf215546Sopenharmony_ci_eglGetConfigs(_EGLDisplay *disp, EGLConfig *configs, 855bf215546Sopenharmony_ci EGLint config_size, EGLint *num_config) 856bf215546Sopenharmony_ci{ 857bf215546Sopenharmony_ci *num_config = _eglFlattenArray(disp->Configs, (void *) configs, 858bf215546Sopenharmony_ci sizeof(configs[0]), config_size, _eglFlattenConfig); 859bf215546Sopenharmony_ci 860bf215546Sopenharmony_ci if (_eglGetLogLevel() == _EGL_DEBUG) 861bf215546Sopenharmony_ci eglPrintConfigDebug(disp, configs, *num_config, EGL_FALSE); 862bf215546Sopenharmony_ci 863bf215546Sopenharmony_ci return EGL_TRUE; 864bf215546Sopenharmony_ci} 865