/** * Quick sort an array of configs. This differs from the standard * qsort() in that the compare function accepts an additional * argument. */ static void _eglSortConfigs(const _EGLConfig **configs, EGLint count, EGLint (*compare)(const _EGLConfig *, const _EGLConfig *, void *), void *priv_data) { const EGLint pivot = 0; EGLint i, j; if (count <= 1) return; _eglSwapConfigs(&configs[pivot], &configs[count / 2]); i = 1; j = count - 1; do { while (i < count && compare(configs[i], configs[pivot], priv_data) < 0) i++; while (compare(configs[j], configs[pivot], priv_data) > 0) j--; if (i < j) { _eglSwapConfigs(&configs[i], &configs[j]); i++; j--; } else if (i == j) { i++; j--; break; } } while (i <= j); _eglSwapConfigs(&configs[pivot], &configs[j]); _eglSortConfigs(configs, j, compare, priv_data); _eglSortConfigs(configs + i, count - i, compare, priv_data); }
/** * A helper function for implementing eglChooseConfig. See _eglFilterArray and * _eglSortConfigs for the meanings of match and compare. */ EGLBoolean _eglFilterConfigArray(_EGLArray *array, EGLConfig *configs, EGLint config_size, EGLint *num_configs, EGLBoolean (*match)(const _EGLConfig *, void *), EGLint (*compare)(const _EGLConfig *, const _EGLConfig *, void *), void *priv_data) { _EGLConfig **configList; EGLint i, count; if (!num_configs) return _eglError(EGL_BAD_PARAMETER, "eglChooseConfig"); /* get the number of matched configs */ count = _eglFilterArray(array, NULL, 0, (_EGLArrayForEach) match, priv_data); if (!count) { *num_configs = count; return EGL_TRUE; } configList = malloc(sizeof(*configList) * count); if (!configList) return _eglError(EGL_BAD_ALLOC, "eglChooseConfig(out of memory)"); /* get the matched configs */ _eglFilterArray(array, (void **) configList, count, (_EGLArrayForEach) match, priv_data); /* perform sorting of configs */ if (configs && count) { _eglSortConfigs((const _EGLConfig **) configList, count, compare, priv_data); count = MIN2(count, config_size); for (i = 0; i < count; i++) configs[i] = _eglGetConfigHandle(configList[i]); } free(configList); *num_configs = count; return EGL_TRUE; }
/** * Typical fallback routine for eglChooseConfig */ EGLBoolean _eglChooseConfig(_EGLDriver *drv, _EGLDisplay *disp, const EGLint *attrib_list, EGLConfig *configs, EGLint config_size, EGLint *num_configs) { _EGLConfig **configList, criteria; EGLint i, count; if (!num_configs) return _eglError(EGL_BAD_PARAMETER, "eglChooseConfigs"); _eglInitConfig(&criteria, disp, 0); if (!_eglParseConfigAttribList(&criteria, attrib_list)) return _eglError(EGL_BAD_ATTRIBUTE, "eglChooseConfig"); /* allocate array of config pointers */ configList = (_EGLConfig **) malloc(disp->NumConfigs * sizeof(_EGLConfig *)); if (!configList) return _eglError(EGL_BAD_ALLOC, "eglChooseConfig(out of memory)"); /* perform selection of configs */ count = 0; for (i = 0; i < disp->NumConfigs; i++) { if (_eglMatchConfig(disp->Configs[i], &criteria)) configList[count++] = disp->Configs[i]; } /* perform sorting of configs */ if (configs && count) { _eglSortConfigs((const _EGLConfig **) configList, count, _eglFallbackCompare, (void *) &criteria); count = MIN2(count, config_size); for (i = 0; i < count; i++) configs[i] = _eglGetConfigHandle(configList[i]); } free(configList); *num_configs = count; return EGL_TRUE; }