/** * 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; }
struct dri2_egl_config * dri2_add_config(_EGLDisplay *disp, const __DRIconfig *dri_config, int id, int depth, EGLint surface_type, const EGLint *attr_list, const unsigned int *rgba_masks) { struct dri2_egl_config *conf; struct dri2_egl_display *dri2_dpy; _EGLConfig base; unsigned int attrib, value, double_buffer; EGLint key, bind_to_texture_rgb, bind_to_texture_rgba; unsigned int dri_masks[4] = { 0, 0, 0, 0 }; _EGLConfig *matching_config; EGLint num_configs = 0; EGLint config_id; int i; dri2_dpy = disp->DriverData; _eglInitConfig(&base, disp, id); i = 0; double_buffer = 0; bind_to_texture_rgb = 0; bind_to_texture_rgba = 0; while (dri2_dpy->core->indexConfigAttrib(dri_config, i++, &attrib, &value)) { switch (attrib) { case __DRI_ATTRIB_RENDER_TYPE: if (value & __DRI_ATTRIB_RGBA_BIT) value = EGL_RGB_BUFFER; else if (value & __DRI_ATTRIB_LUMINANCE_BIT) value = EGL_LUMINANCE_BUFFER; else /* not valid */; _eglSetConfigKey(&base, EGL_COLOR_BUFFER_TYPE, value); break; case __DRI_ATTRIB_CONFIG_CAVEAT: if (value & __DRI_ATTRIB_NON_CONFORMANT_CONFIG) value = EGL_NON_CONFORMANT_CONFIG; else if (value & __DRI_ATTRIB_SLOW_BIT) value = EGL_SLOW_CONFIG; else value = EGL_NONE; _eglSetConfigKey(&base, EGL_CONFIG_CAVEAT, value); break; case __DRI_ATTRIB_BIND_TO_TEXTURE_RGB: bind_to_texture_rgb = value; break; case __DRI_ATTRIB_BIND_TO_TEXTURE_RGBA: bind_to_texture_rgba = value; break; case __DRI_ATTRIB_DOUBLE_BUFFER: double_buffer = value; break; case __DRI_ATTRIB_RED_MASK: dri_masks[0] = value; break; case __DRI_ATTRIB_GREEN_MASK: dri_masks[1] = value; break; case __DRI_ATTRIB_BLUE_MASK: dri_masks[2] = value; break; case __DRI_ATTRIB_ALPHA_MASK: dri_masks[3] = value; break; default: key = dri2_to_egl_attribute_map[attrib]; if (key != 0) _eglSetConfigKey(&base, key, value); break; } } if (attr_list) for (i = 0; attr_list[i] != EGL_NONE; i += 2) _eglSetConfigKey(&base, attr_list[i], attr_list[i+1]); if (depth > 0 && depth != base.BufferSize) return NULL; if (rgba_masks && memcmp(rgba_masks, dri_masks, sizeof(dri_masks))) return NULL; base.NativeRenderable = EGL_TRUE; base.SurfaceType = surface_type; if (surface_type & (EGL_PBUFFER_BIT | (disp->Extensions.NOK_texture_from_pixmap ? EGL_PIXMAP_BIT : 0))) { base.BindToTextureRGB = bind_to_texture_rgb; if (base.AlphaSize > 0) base.BindToTextureRGBA = bind_to_texture_rgba; } base.RenderableType = disp->ClientAPIs; base.Conformant = disp->ClientAPIs; if (!_eglValidateConfig(&base, EGL_FALSE)) { _eglLog(_EGL_DEBUG, "DRI2: failed to validate config %d", id); return NULL; } config_id = base.ConfigID; base.ConfigID = EGL_DONT_CARE; base.SurfaceType = EGL_DONT_CARE; num_configs = _eglFilterArray(disp->Configs, (void **) &matching_config, 1, (_EGLArrayForEach) dri2_match_config, &base); if (num_configs == 1) { conf = (struct dri2_egl_config *) matching_config; if (double_buffer && !conf->dri_double_config) conf->dri_double_config = dri_config; else if (!double_buffer && !conf->dri_single_config) conf->dri_single_config = dri_config; else /* a similar config type is already added (unlikely) => discard */ return NULL; } else if (num_configs == 0) { conf = malloc(sizeof *conf); if (conf == NULL) return NULL; memcpy(&conf->base, &base, sizeof base); if (double_buffer) { conf->dri_double_config = dri_config; conf->dri_single_config = NULL; } else { conf->dri_single_config = dri_config; conf->dri_double_config = NULL; } conf->base.SurfaceType = 0; conf->base.ConfigID = config_id; _eglLinkConfig(&conf->base); } else { assert(0); return NULL; } if (double_buffer) { surface_type &= ~EGL_PIXMAP_BIT; if (dri2_dpy->swap_available) { conf->base.MinSwapInterval = 0; conf->base.MaxSwapInterval = 1000; /* XXX arbitrary value */ } } conf->base.SurfaceType |= surface_type; return conf; }