summaryrefslogtreecommitdiffstats
path: root/src/egl/main/eglconfig.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/egl/main/eglconfig.c')
-rw-r--r--src/egl/main/eglconfig.c286
1 files changed, 286 insertions, 0 deletions
diff --git a/src/egl/main/eglconfig.c b/src/egl/main/eglconfig.c
new file mode 100644
index 00000000000..765e2e3dbeb
--- /dev/null
+++ b/src/egl/main/eglconfig.c
@@ -0,0 +1,286 @@
+#include <string.h>
+#include <assert.h>
+#include "eglconfig.h"
+#include "egldisplay.h"
+#include "egldriver.h"
+#include "eglglobals.h"
+
+
+#define MIN2(A, B) (((A) < (B)) ? (A) : (B))
+
+
+/**
+ * Init the given _EGLconfig to default values.
+ * \param id the configuration's ID.
+ */
+void
+_eglInitConfig(_EGLConfig *config, EGLint id)
+{
+ memset(config, 0, sizeof(*config));
+ config->Handle = id;
+ SET_CONFIG_ATTRIB(config, EGL_CONFIG_ID, id);
+ SET_CONFIG_ATTRIB(config, EGL_BIND_TO_TEXTURE_RGB, EGL_DONT_CARE);
+ SET_CONFIG_ATTRIB(config, EGL_BIND_TO_TEXTURE_RGBA, EGL_DONT_CARE);
+ SET_CONFIG_ATTRIB(config, EGL_CONFIG_CAVEAT, EGL_DONT_CARE);
+ SET_CONFIG_ATTRIB(config, EGL_NATIVE_RENDERABLE, EGL_DONT_CARE);
+ SET_CONFIG_ATTRIB(config, EGL_NATIVE_VISUAL_TYPE, EGL_DONT_CARE);
+ SET_CONFIG_ATTRIB(config, EGL_MIN_SWAP_INTERVAL, EGL_DONT_CARE);
+ SET_CONFIG_ATTRIB(config, EGL_MAX_SWAP_INTERVAL, EGL_DONT_CARE);
+ SET_CONFIG_ATTRIB(config, EGL_SURFACE_TYPE, EGL_WINDOW_BIT);
+ SET_CONFIG_ATTRIB(config, EGL_TRANSPARENT_TYPE, EGL_NONE);
+ SET_CONFIG_ATTRIB(config, EGL_TRANSPARENT_RED_VALUE, EGL_DONT_CARE);
+ SET_CONFIG_ATTRIB(config, EGL_TRANSPARENT_GREEN_VALUE, EGL_DONT_CARE);
+ SET_CONFIG_ATTRIB(config, EGL_TRANSPARENT_BLUE_VALUE, EGL_DONT_CARE);
+}
+
+
+/**
+ * Given an EGLConfig handle, return the corresponding _EGLConfig object.
+ */
+_EGLConfig *
+_eglLookupConfig(_EGLDriver *drv, EGLDisplay dpy, EGLConfig config)
+{
+ EGLint i;
+ _EGLDisplay *disp = _eglLookupDisplay(dpy);
+ for (i = 0; i < disp->NumConfigs; i++) {
+ if (disp->Configs[i].Handle == config) {
+ return disp->Configs + i;
+ }
+ }
+ return NULL;
+}
+
+
+
+/**
+ * Parse the attrib_list to fill in the fields of the given _egl_config
+ * Return EGL_FALSE if any errors, EGL_TRUE otherwise.
+ */
+EGLBoolean
+_eglParseConfigAttribs(_EGLConfig *config, const EGLint *attrib_list)
+{
+ EGLint i;
+
+ /* XXX set all config attribs to EGL_DONT_CARE */
+
+ for (i = 0; attrib_list && attrib_list[i] != EGL_NONE; i++) {
+ EGLint k = attrib_list[i] - FIRST_ATTRIB;
+ if (k >= 0 && k < MAX_ATTRIBS) {
+ config->Attrib[k] = attrib_list[++i];
+ }
+ else {
+ _eglError(EGL_BAD_ATTRIBUTE, "eglChooseConfig");
+ return EGL_FALSE;
+ }
+ }
+ return EGL_TRUE;
+}
+
+
+#define EXACT 1
+#define ATLEAST 2
+#define MASK 3
+#define SMALLER 4
+#define SPECIAL 5
+#define NONE 6
+
+struct sort_info {
+ EGLint Attribute;
+ EGLint MatchCriteria;
+ EGLint SortOrder;
+};
+
+/* This encodes the info from Table 3.5 of the EGL spec, ordered by
+ * Sort Priority.
+ */
+static struct sort_info SortInfo[] = {
+ { EGL_CONFIG_CAVEAT, EXACT, SPECIAL },
+ { EGL_RED_SIZE, ATLEAST, SPECIAL },
+ { EGL_GREEN_SIZE, ATLEAST, SPECIAL },
+ { EGL_BLUE_SIZE, ATLEAST, SPECIAL },
+ { EGL_ALPHA_SIZE, ATLEAST, SPECIAL },
+ { EGL_BUFFER_SIZE, ATLEAST, SMALLER },
+ { EGL_SAMPLE_BUFFERS, ATLEAST, SMALLER },
+ { EGL_SAMPLES, ATLEAST, SMALLER },
+ { EGL_DEPTH_SIZE, ATLEAST, SMALLER },
+ { EGL_STENCIL_SIZE, ATLEAST, SMALLER },
+ { EGL_NATIVE_VISUAL_TYPE, EXACT, SPECIAL },
+ { EGL_CONFIG_ID, EXACT, SMALLER },
+ { EGL_BIND_TO_TEXTURE_RGB, EXACT, NONE },
+ { EGL_BIND_TO_TEXTURE_RGBA, EXACT, NONE },
+ { EGL_LEVEL, EXACT, NONE },
+ { EGL_NATIVE_RENDERABLE, EXACT, NONE },
+ { EGL_MAX_SWAP_INTERVAL, EXACT, NONE },
+ { EGL_MIN_SWAP_INTERVAL, EXACT, NONE },
+ { EGL_SURFACE_TYPE, MASK, NONE },
+ { EGL_TRANSPARENT_TYPE, EXACT, NONE },
+ { EGL_TRANSPARENT_RED_VALUE, EXACT, NONE },
+ { EGL_TRANSPARENT_GREEN_VALUE, EXACT, NONE },
+ { EGL_TRANSPARENT_BLUE_VALUE, EXACT, NONE },
+ { 0, 0, 0 }
+};
+
+
+/**
+ * Return EGL_TRUE if the attributes of c meet or exceed the minimums
+ * specified by min.
+ */
+EGLBoolean
+_eglConfigQualifies(const _EGLConfig *c, const _EGLConfig *min)
+{
+ EGLint i;
+ for (i = 0; SortInfo[i].Attribute != 0; i++) {
+ const EGLint mv = GET_CONFIG_ATTRIB(min, SortInfo[i].Attribute);
+ if (mv != EGL_DONT_CARE) {
+ const EGLint cv = GET_CONFIG_ATTRIB(c, SortInfo[i].Attribute);
+ if (SortInfo[i].MatchCriteria == EXACT) {
+ if (cv != mv) {
+ return EGL_FALSE;
+ }
+ }
+ else if (SortInfo[i].MatchCriteria == ATLEAST) {
+ if (cv < mv) {
+ return EGL_FALSE;
+ }
+ }
+ else {
+ assert(SortInfo[i].MatchCriteria == MASK);
+ if ((mv & cv) != mv) {
+ return EGL_FALSE;
+ }
+ }
+ }
+ }
+ return EGL_TRUE;
+}
+
+
+/**
+ * Compare configs 'a' and 'b' and return -1 if a belongs before b,
+ * 1 if a belongs after b, or 0 if they're equal.
+ */
+EGLint
+_eglCompareConfigs(const _EGLConfig *a, const _EGLConfig *b)
+{
+ EGLint i;
+ for (i = 0; SortInfo[i].Attribute != 0; i++) {
+ const EGLint av = GET_CONFIG_ATTRIB(a, SortInfo[i].Attribute);
+ const EGLint bv = GET_CONFIG_ATTRIB(b, SortInfo[i].Attribute);
+ if (SortInfo[i].SortOrder == SMALLER) {
+ if (av < bv)
+ return -1;
+ else if (av > bv)
+ return 1;
+ /* else, continue examining attribute values */
+ }
+ else if (SortInfo[i].SortOrder == SPECIAL) {
+ if (SortInfo[i].Attribute == EGL_CONFIG_CAVEAT) {
+ /* values are EGL_NONE, SLOW_CONFIG, or NON_CONFORMANT_CONFIG */
+ if (av < bv)
+ return -1;
+ else if (av > bv)
+ return 1;
+ }
+ else if (SortInfo[i].Attribute == EGL_RED_SIZE ||
+ SortInfo[i].Attribute == EGL_GREEN_SIZE ||
+ SortInfo[i].Attribute == EGL_BLUE_SIZE ||
+ SortInfo[i].Attribute == EGL_ALPHA_SIZE) {
+ if (av > bv)
+ return -1;
+ else if (av < bv)
+ return 1;
+ }
+ else {
+ assert(SortInfo[i].Attribute == EGL_NATIVE_VISUAL_TYPE);
+ if (av < bv)
+ return -1;
+ else if (av > bv)
+ return 1;
+ }
+ }
+ else {
+ assert(SortInfo[i].SortOrder == NONE);
+ /* continue examining attribute values */
+ }
+ }
+ return 0;
+}
+
+
+/**
+ * Typical fallback routine for eglChooseConfig
+ */
+EGLBoolean
+_eglChooseConfig(_EGLDriver *drv, EGLDisplay dpy, const EGLint *attrib_list, EGLConfig *configs, EGLint config_size, EGLint *num_config)
+{
+ _EGLDisplay *disp = _eglLookupDisplay(dpy);
+ _EGLConfig criteria;
+ EGLint i;
+
+ /* parse the attrib_list to initialize criteria */
+ if (!_eglParseConfigAttribs(&criteria, attrib_list)) {
+ return EGL_FALSE;
+ }
+
+ *num_config = 0;
+ for (i = 0; i < disp->NumConfigs; i++) {
+ const _EGLConfig *conf = disp->Configs + i;
+ if (_eglConfigQualifies(conf, &criteria)) {
+ if (*num_config < config_size) {
+ /* save */
+ configs[*num_config] = conf->Handle;
+ (*num_config)++;
+ }
+ else {
+ break;
+ }
+ }
+ }
+
+ /* XXX sort the list here */
+
+ return EGL_TRUE;
+}
+
+
+/**
+ * Fallback for eglGetConfigAttrib.
+ */
+EGLBoolean
+_eglGetConfigAttrib(_EGLDriver *drv, EGLDisplay dpy, EGLConfig config, EGLint attribute, EGLint *value)
+{
+ const _EGLConfig *conf = _eglLookupConfig(drv, dpy, config);
+ const EGLint k = attribute - FIRST_ATTRIB;
+ if (k >= 0 && k < MAX_ATTRIBS) {
+ *value = conf->Attrib[k];
+ return EGL_TRUE;
+ }
+ else {
+ _eglError(EGL_BAD_ATTRIBUTE, "eglGetConfigAttrib");
+ return EGL_FALSE;
+ }
+}
+
+
+/**
+ * Fallback for eglGetConfigs.
+ */
+EGLBoolean
+_eglGetConfigs(_EGLDriver *drv, EGLDisplay dpy, EGLConfig *configs, EGLint config_size, EGLint *num_config)
+{
+ _EGLDisplay *disp = _eglLookupDisplay(dpy);
+
+ if (!drv->Initialized) {
+ _eglError(EGL_NOT_INITIALIZED, "eglGetConfigs");
+ return EGL_FALSE;
+ }
+
+ *num_config = MIN2(disp->NumConfigs, config_size);
+ if (configs) {
+ EGLint i;
+ for (i = 0; i < *num_config; i++) {
+ configs[i] = disp->Configs[i].Handle;
+ }
+ }
+ return EGL_TRUE;
+}