eglconfig.c revision d06da508880e9baee403b0d0046764b31087cdfd
1/**
2 * EGL Configuration (pixel format) functions.
3 */
4
5
6#include <stdlib.h>
7#include <stdio.h>
8#include <string.h>
9#include <assert.h>
10#include "eglconfig.h"
11#include "egldisplay.h"
12#include "egldriver.h"
13#include "eglglobals.h"
14
15
16#define MIN2(A, B)  (((A) < (B)) ? (A) : (B))
17
18
19/**
20 * Convert an _EGLConfig to a __GLcontextModes object.
21 */
22static void
23_eglConfigToContextModesRec(const _EGLConfig *config, __GLcontextModes *mode)
24{
25   memset(mode, 0, sizeof(*mode));
26
27   mode->rgbMode = GL_TRUE; /* no color index */
28   mode->colorIndexMode = GL_FALSE;
29   mode->doubleBufferMode = GL_TRUE;
30   mode->stereoMode = GL_FALSE;
31
32   mode->redBits = GET_CONFIG_ATTRIB(config, EGL_RED_SIZE);
33   mode->greenBits = GET_CONFIG_ATTRIB(config, EGL_GREEN_SIZE);
34   mode->blueBits = GET_CONFIG_ATTRIB(config, EGL_BLUE_SIZE);
35   mode->alphaBits = GET_CONFIG_ATTRIB(config, EGL_ALPHA_SIZE);
36   mode->rgbBits = mode->redBits + mode->greenBits
37      + mode->blueBits + mode->alphaBits;
38
39   mode->depthBits = GET_CONFIG_ATTRIB(config, EGL_DEPTH_SIZE);
40   mode->haveDepthBuffer = mode->depthBits > 0;
41
42   mode->stencilBits = GET_CONFIG_ATTRIB(config, EGL_STENCIL_SIZE);
43   mode->haveStencilBuffer = mode->stencilBits > 0;
44
45   mode->level = GET_CONFIG_ATTRIB(config, EGL_LEVEL);
46   mode->samples = GET_CONFIG_ATTRIB(config, EGL_SAMPLES);
47   mode->sampleBuffers = GET_CONFIG_ATTRIB(config, EGL_SAMPLE_BUFFERS);
48}
49
50
51
52void
53_eglSetConfigAttrib(_EGLConfig *config, EGLint attr, EGLint val)
54{
55   config->Attrib[attr - FIRST_ATTRIB] = val;
56
57   switch (attr) {
58   case EGL_BUFFER_SIZE:
59      config->glmode.rgbBits = val;
60      break;
61   case EGL_ALPHA_SIZE:
62      config->glmode.alphaBits = val;
63      break;
64   case EGL_BLUE_SIZE:
65      config->glmode.blueBits = val;
66      break;
67   case EGL_GREEN_SIZE:
68      config->glmode.greenBits = val;
69      break;
70   case EGL_RED_SIZE:
71      config->glmode.redBits = val;
72      break;
73   case EGL_DEPTH_SIZE:
74      config->glmode.depthBits = val;
75      break;
76   case EGL_STENCIL_SIZE:
77      config->glmode.stencilBits = val;
78      break;
79   case EGL_CONFIG_CAVEAT:
80      break;
81   case EGL_CONFIG_ID:
82      break;
83   case EGL_LEVEL:
84      break;
85   case EGL_MAX_PBUFFER_HEIGHT:
86      break;
87   case EGL_MAX_PBUFFER_PIXELS:
88      break;
89   case EGL_MAX_PBUFFER_WIDTH:
90      break;
91   case EGL_NATIVE_RENDERABLE:
92      break;
93   case EGL_NATIVE_VISUAL_ID:
94      break;
95   case EGL_NATIVE_VISUAL_TYPE:
96      break;
97   case EGL_SAMPLES:
98      break;
99   case EGL_SAMPLE_BUFFERS:
100      break;
101   case EGL_SURFACE_TYPE:
102      config->glmode.drawableType = val;
103      break;
104   case EGL_TRANSPARENT_TYPE:
105      break;
106   case EGL_TRANSPARENT_BLUE_VALUE:
107      break;
108   case EGL_TRANSPARENT_GREEN_VALUE:
109      break;
110   case EGL_TRANSPARENT_RED_VALUE:
111      break;
112   case EGL_NONE:
113      break;
114   case EGL_BIND_TO_TEXTURE_RGB:
115      break;
116   case EGL_BIND_TO_TEXTURE_RGBA:
117      break;
118   case EGL_MIN_SWAP_INTERVAL:
119      break;
120   case EGL_MAX_SWAP_INTERVAL:
121      break;
122   default:
123      break;
124   }
125}
126
127
128/**
129 * Init the given _EGLconfig to default values.
130 * \param id  the configuration's ID.
131 */
132void
133_eglInitConfig(_EGLConfig *config, EGLint id)
134{
135   memset(config, 0, sizeof(*config));
136   config->Handle = id;
137   _eglSetConfigAttrib(config, EGL_CONFIG_ID,               id);
138   _eglSetConfigAttrib(config, EGL_BIND_TO_TEXTURE_RGB,     EGL_DONT_CARE);
139   _eglSetConfigAttrib(config, EGL_BIND_TO_TEXTURE_RGBA,    EGL_DONT_CARE);
140   _eglSetConfigAttrib(config, EGL_CONFIG_CAVEAT,           EGL_DONT_CARE);
141   _eglSetConfigAttrib(config, EGL_NATIVE_RENDERABLE,       EGL_DONT_CARE);
142   _eglSetConfigAttrib(config, EGL_NATIVE_VISUAL_TYPE,      EGL_DONT_CARE);
143   _eglSetConfigAttrib(config, EGL_MIN_SWAP_INTERVAL,       EGL_DONT_CARE);
144   _eglSetConfigAttrib(config, EGL_MAX_SWAP_INTERVAL,       EGL_DONT_CARE);
145   _eglSetConfigAttrib(config, EGL_SURFACE_TYPE,
146                   EGL_SCREEN_BIT_MESA | EGL_PBUFFER_BIT |
147                   EGL_PIXMAP_BIT | EGL_WINDOW_BIT);
148   _eglSetConfigAttrib(config, EGL_TRANSPARENT_TYPE,        EGL_NONE);
149   _eglSetConfigAttrib(config, EGL_TRANSPARENT_RED_VALUE,   EGL_DONT_CARE);
150   _eglSetConfigAttrib(config, EGL_TRANSPARENT_GREEN_VALUE, EGL_DONT_CARE);
151   _eglSetConfigAttrib(config, EGL_TRANSPARENT_BLUE_VALUE,  EGL_DONT_CARE);
152}
153
154
155/**
156 * Given an EGLConfig handle, return the corresponding _EGLConfig object.
157 */
158_EGLConfig *
159_eglLookupConfig(_EGLDriver *drv, EGLDisplay dpy, EGLConfig config)
160{
161   EGLint i;
162   _EGLDisplay *disp = _eglLookupDisplay(dpy);
163   for (i = 0; i < disp->NumConfigs; i++) {
164      if (disp->Configs[i].Handle == config) {
165          return disp->Configs + i;
166      }
167   }
168   return NULL;
169}
170
171
172/**
173 * Add the given _EGLConifg to the given display.
174 */
175_EGLConfig *
176_eglAddConfig(_EGLDisplay *display, const _EGLConfig *config)
177{
178   _EGLConfig *newConfigs;
179   EGLint n;
180
181   n = display->NumConfigs;
182
183   newConfigs = (_EGLConfig *) realloc(display->Configs,
184                                       (n + 1) * sizeof(_EGLConfig));
185   if (newConfigs) {
186      display->Configs = newConfigs;
187      display->Configs[n] = *config; /* copy struct */
188      display->Configs[n].Handle = n;
189      display->NumConfigs++;
190      return display->Configs + n;
191   }
192   else {
193      return NULL;
194   }
195}
196
197
198/**
199 * Parse the attrib_list to fill in the fields of the given _egl_config
200 * Return EGL_FALSE if any errors, EGL_TRUE otherwise.
201 */
202EGLBoolean
203_eglParseConfigAttribs(_EGLConfig *config, const EGLint *attrib_list)
204{
205   EGLint i;
206
207   /* XXX set all config attribs to EGL_DONT_CARE */
208
209   for (i = 0; attrib_list && attrib_list[i] != EGL_NONE; i++) {
210      EGLint k = attrib_list[i] - FIRST_ATTRIB;
211      if (k >= 0 && k < MAX_ATTRIBS) {
212         config->Attrib[k] = attrib_list[++i];
213      }
214      else {
215         _eglError(EGL_BAD_ATTRIBUTE, "eglChooseConfig");
216         return EGL_FALSE;
217      }
218   }
219   return EGL_TRUE;
220}
221
222
223#define EXACT 1
224#define ATLEAST 2
225#define MASK 3
226#define SMALLER 4
227#define SPECIAL 5
228#define NONE 6
229
230struct sort_info {
231   EGLint Attribute;
232   EGLint MatchCriteria;
233   EGLint SortOrder;
234};
235
236/* This encodes the info from Table 3.5 of the EGL spec, ordered by
237 * Sort Priority.
238 */
239static struct sort_info SortInfo[] = {
240   { EGL_CONFIG_CAVEAT,           EXACT,   SPECIAL },
241   { EGL_RED_SIZE,                ATLEAST, SPECIAL },
242   { EGL_GREEN_SIZE,              ATLEAST, SPECIAL },
243   { EGL_BLUE_SIZE,               ATLEAST, SPECIAL },
244   { EGL_ALPHA_SIZE,              ATLEAST, SPECIAL },
245   { EGL_BUFFER_SIZE,             ATLEAST, SMALLER },
246   { EGL_SAMPLE_BUFFERS,          ATLEAST, SMALLER },
247   { EGL_SAMPLES,                 ATLEAST, SMALLER },
248   { EGL_DEPTH_SIZE,              ATLEAST, SMALLER },
249   { EGL_STENCIL_SIZE,            ATLEAST, SMALLER },
250   { EGL_NATIVE_VISUAL_TYPE,      EXACT,   SPECIAL },
251   { EGL_CONFIG_ID,               EXACT,   SMALLER },
252   { EGL_BIND_TO_TEXTURE_RGB,     EXACT,   NONE    },
253   { EGL_BIND_TO_TEXTURE_RGBA,    EXACT,   NONE    },
254   { EGL_LEVEL,                   EXACT,   NONE    },
255   { EGL_NATIVE_RENDERABLE,       EXACT,   NONE    },
256   { EGL_MAX_SWAP_INTERVAL,       EXACT,   NONE    },
257   { EGL_MIN_SWAP_INTERVAL,       EXACT,   NONE    },
258   { EGL_SURFACE_TYPE,            MASK,    NONE    },
259   { EGL_TRANSPARENT_TYPE,        EXACT,   NONE    },
260   { EGL_TRANSPARENT_RED_VALUE,   EXACT,   NONE    },
261   { EGL_TRANSPARENT_GREEN_VALUE, EXACT,   NONE    },
262   { EGL_TRANSPARENT_BLUE_VALUE,  EXACT,   NONE    },
263   { 0, 0, 0 }
264};
265
266
267/**
268 * Return EGL_TRUE if the attributes of c meet or exceed the minimums
269 * specified by min.
270 */
271EGLBoolean
272_eglConfigQualifies(const _EGLConfig *c, const _EGLConfig *min)
273{
274   EGLint i;
275   for (i = 0; SortInfo[i].Attribute != 0; i++) {
276      const EGLint mv = GET_CONFIG_ATTRIB(min, SortInfo[i].Attribute);
277      if (mv != EGL_DONT_CARE) {
278         const EGLint cv = GET_CONFIG_ATTRIB(c, SortInfo[i].Attribute);
279         if (SortInfo[i].MatchCriteria == EXACT) {
280            if (cv != mv) {
281               return EGL_FALSE;
282            }
283         }
284         else if (SortInfo[i].MatchCriteria == ATLEAST) {
285            if (cv < mv) {
286               return EGL_FALSE;
287            }
288         }
289         else {
290            assert(SortInfo[i].MatchCriteria == MASK);
291            if ((mv & cv) != mv) {
292               return EGL_FALSE;
293            }
294         }
295      }
296   }
297   return EGL_TRUE;
298}
299
300
301/**
302 * Compare configs 'a' and 'b' and return -1 if a belongs before b,
303 * 1 if a belongs after b, or 0 if they're equal.
304 */
305EGLint
306_eglCompareConfigs(const _EGLConfig *a, const _EGLConfig *b)
307{
308   EGLint i;
309   for (i = 0; SortInfo[i].Attribute != 0; i++) {
310      const EGLint av = GET_CONFIG_ATTRIB(a, SortInfo[i].Attribute);
311      const EGLint bv = GET_CONFIG_ATTRIB(b, SortInfo[i].Attribute);
312      if (SortInfo[i].SortOrder == SMALLER) {
313         if (av < bv)
314            return -1;
315         else if (av > bv)
316            return 1;
317         /* else, continue examining attribute values */
318      }
319      else if (SortInfo[i].SortOrder == SPECIAL) {
320         if (SortInfo[i].Attribute == EGL_CONFIG_CAVEAT) {
321            /* values are EGL_NONE, SLOW_CONFIG, or NON_CONFORMANT_CONFIG */
322            if (av < bv)
323               return -1;
324            else if (av > bv)
325               return 1;
326         }
327         else if (SortInfo[i].Attribute == EGL_RED_SIZE ||
328                  SortInfo[i].Attribute == EGL_GREEN_SIZE ||
329                  SortInfo[i].Attribute == EGL_BLUE_SIZE ||
330                  SortInfo[i].Attribute == EGL_ALPHA_SIZE) {
331            if (av > bv)
332               return -1;
333            else if (av < bv)
334               return 1;
335         }
336         else {
337            assert(SortInfo[i].Attribute == EGL_NATIVE_VISUAL_TYPE);
338            if (av < bv)
339               return -1;
340            else if (av > bv)
341               return 1;
342         }
343      }
344      else {
345         assert(SortInfo[i].SortOrder == NONE);
346         /* continue examining attribute values */
347      }
348   }
349   return 0;
350}
351
352
353/**
354 * Typical fallback routine for eglChooseConfig
355 */
356EGLBoolean
357_eglChooseConfig(_EGLDriver *drv, EGLDisplay dpy, const EGLint *attrib_list, EGLConfig *configs, EGLint config_size, EGLint *num_config)
358{
359   _EGLDisplay *disp = _eglLookupDisplay(dpy);
360   _EGLConfig criteria;
361   EGLint i;
362
363   /* parse the attrib_list to initialize criteria */
364   if (!_eglParseConfigAttribs(&criteria, attrib_list)) {
365      return EGL_FALSE;
366   }
367
368   *num_config = 0;
369   for (i = 0; i < disp->NumConfigs; i++) {
370      const _EGLConfig *conf = disp->Configs + i;
371      if (_eglConfigQualifies(conf, &criteria)) {
372         if (*num_config < config_size) {
373            /* save */
374            configs[*num_config] = conf->Handle;
375            (*num_config)++;
376         }
377         else {
378            break;
379         }
380      }
381   }
382
383   /* XXX sort the list here */
384
385   return EGL_TRUE;
386}
387
388
389/**
390 * Fallback for eglGetConfigAttrib.
391 */
392EGLBoolean
393_eglGetConfigAttrib(_EGLDriver *drv, EGLDisplay dpy, EGLConfig config, EGLint attribute, EGLint *value)
394{
395   const _EGLConfig *conf = _eglLookupConfig(drv, dpy, config);
396   const EGLint k = attribute - FIRST_ATTRIB;
397   if (k >= 0 && k < MAX_ATTRIBS) {
398      *value = conf->Attrib[k];
399      return EGL_TRUE;
400   }
401   else {
402      _eglError(EGL_BAD_ATTRIBUTE, "eglGetConfigAttrib");
403      return EGL_FALSE;
404   }
405}
406
407
408/**
409 * Fallback for eglGetConfigs.
410 */
411EGLBoolean
412_eglGetConfigs(_EGLDriver *drv, EGLDisplay dpy, EGLConfig *configs, EGLint config_size, EGLint *num_config)
413{
414   _EGLDisplay *disp = _eglLookupDisplay(dpy);
415
416   if (!drv->Initialized) {
417      _eglError(EGL_NOT_INITIALIZED, "eglGetConfigs");
418      return EGL_FALSE;
419   }
420
421   if (configs) {
422      EGLint i;
423      *num_config = MIN2(disp->NumConfigs, config_size);
424      for (i = 0; i < *num_config; i++) {
425         configs[i] = disp->Configs[i].Handle;
426      }
427   } else
428      *num_config = disp->NumConfigs;
429
430   return EGL_TRUE;
431}
432
433
434/**
435 * Creates a set of \c __GLcontextModes that a driver will expose.
436 *
437 * A set of \c __GLcontextModes will be created based on the supplied
438 * parameters.  The number of modes processed will be 2 *
439 * \c num_depth_stencil_bits * \c num_db_modes.
440 *
441 * For the most part, data is just copied from \c depth_bits, \c stencil_bits,
442 * \c db_modes, and \c visType into each \c __GLcontextModes element.
443 * However, the meanings of \c fb_format and \c fb_type require further
444 * explanation.  The \c fb_format specifies which color components are in
445 * each pixel and what the default order is.  For example, \c GL_RGB specifies
446 * that red, green, blue are available and red is in the "most significant"
447 * position and blue is in the "least significant".  The \c fb_type specifies
448 * the bit sizes of each component and the actual ordering.  For example, if
449 * \c GL_UNSIGNED_SHORT_5_6_5_REV is specified with \c GL_RGB, bits [15:11]
450 * are the blue value, bits [10:5] are the green value, and bits [4:0] are
451 * the red value.
452 *
453 * One sublte issue is the combination of \c GL_RGB  or \c GL_BGR and either
454 * of the \c GL_UNSIGNED_INT_8_8_8_8 modes.  The resulting mask values in the
455 * \c __GLcontextModes structure is \b identical to the \c GL_RGBA or
456 * \c GL_BGRA case, except the \c alphaMask is zero.  This means that, as
457 * far as this routine is concerned, \c GL_RGB with \c GL_UNSIGNED_INT_8_8_8_8
458 * still uses 32-bits.
459 *
460 * If in doubt, look at the tables used in the function.
461 *
462 * \param ptr_to_modes  Pointer to a pointer to a linked list of
463 *                      \c __GLcontextModes.  Upon completion, a pointer to
464 *                      the next element to be process will be stored here.
465 *                      If the function fails and returns \c GL_FALSE, this
466 *                      value will be unmodified, but some elements in the
467 *                      linked list may be modified.
468 * \param fb_format     Format of the framebuffer.  Currently only \c GL_RGB,
469 *                      \c GL_RGBA, \c GL_BGR, and \c GL_BGRA are supported.
470 * \param fb_type       Type of the pixels in the framebuffer.  Currently only
471 *                      \c GL_UNSIGNED_SHORT_5_6_5,
472 *                      \c GL_UNSIGNED_SHORT_5_6_5_REV,
473 *                      \c GL_UNSIGNED_INT_8_8_8_8, and
474 *                      \c GL_UNSIGNED_INT_8_8_8_8_REV are supported.
475 * \param depth_bits    Array of depth buffer sizes to be exposed.
476 * \param stencil_bits  Array of stencil buffer sizes to be exposed.
477 * \param num_depth_stencil_bits  Number of entries in both \c depth_bits and
478 *                      \c stencil_bits.
479 * \param db_modes      Array of buffer swap modes.  If an element has a
480 *                      value of \c GLX_NONE, then it represents a
481 *                      single-buffered mode.  Other valid values are
482 *                      \c GLX_SWAP_EXCHANGE_OML, \c GLX_SWAP_COPY_OML, and
483 *                      \c GLX_SWAP_UNDEFINED_OML.  See the
484 *                      GLX_OML_swap_method extension spec for more details.
485 * \param num_db_modes  Number of entries in \c db_modes.
486 * \param visType       GLX visual type.  Usually either \c GLX_TRUE_COLOR or
487 *                      \c GLX_DIRECT_COLOR.
488 *
489 * \returns
490 * \c GL_TRUE on success or \c GL_FALSE on failure.  Currently the only
491 * cause of failure is a bad parameter (i.e., unsupported \c fb_format or
492 * \c fb_type).
493 *
494 * \todo
495 * There is currently no way to support packed RGB modes (i.e., modes with
496 * exactly 3 bytes per pixel) or floating-point modes.  This could probably
497 * be done by creating some new, private enums with clever names likes
498 * \c GL_UNSIGNED_3BYTE_8_8_8, \c GL_4FLOAT_32_32_32_32,
499 * \c GL_4HALF_16_16_16_16, etc.  We can cross that bridge when we come to it.
500 */
501GLboolean
502_eglFillInConfigs(_EGLConfig * configs,
503                GLenum fb_format, GLenum fb_type,
504                const u_int8_t * depth_bits, const u_int8_t * stencil_bits,
505                unsigned num_depth_stencil_bits,
506                const GLenum * db_modes, unsigned num_db_modes,
507                int visType) {
508   static const u_int8_t bits_table[3][4] = {
509            /* R  G  B  A */
510            { 5, 6, 5, 0 },  /* Any GL_UNSIGNED_SHORT_5_6_5 */
511            { 8, 8, 8, 0 },  /* Any RGB with any GL_UNSIGNED_INT_8_8_8_8 */
512            { 8, 8, 8, 8 }  /* Any RGBA with any GL_UNSIGNED_INT_8_8_8_8 */
513         };
514
515   /* The following arrays are all indexed by the fb_type masked with 0x07.
516    * Given the four supported fb_type values, this results in valid array
517    * indices of 3, 4, 5, and 7.
518    */
519   static const u_int32_t masks_table_rgb[8][4] = {
520            {0x00000000, 0x00000000, 0x00000000, 0x00000000},
521            {0x00000000, 0x00000000, 0x00000000, 0x00000000},
522            {0x00000000, 0x00000000, 0x00000000, 0x00000000},
523            {0x0000F800, 0x000007E0, 0x0000001F, 0x00000000},  /* 5_6_5       */
524            {0x0000001F, 0x000007E0, 0x0000F800, 0x00000000},  /* 5_6_5_REV   */
525            {0xFF000000, 0x00FF0000, 0x0000FF00, 0x00000000},  /* 8_8_8_8     */
526            {0x00000000, 0x00000000, 0x00000000, 0x00000000},
527            {0x000000FF, 0x0000FF00, 0x00FF0000, 0x00000000}  /* 8_8_8_8_REV */
528         };
529
530   static const u_int32_t masks_table_rgba[8][4] = {
531            {0x00000000, 0x00000000, 0x00000000, 0x00000000},
532            {0x00000000, 0x00000000, 0x00000000, 0x00000000},
533            {0x00000000, 0x00000000, 0x00000000, 0x00000000},
534            {0x0000F800, 0x000007E0, 0x0000001F, 0x00000000},  /* 5_6_5       */
535            {0x0000001F, 0x000007E0, 0x0000F800, 0x00000000},  /* 5_6_5_REV   */
536            {0xFF000000, 0x00FF0000, 0x0000FF00, 0x000000FF},  /* 8_8_8_8     */
537            {0x00000000, 0x00000000, 0x00000000, 0x00000000},
538            {0x000000FF, 0x0000FF00, 0x00FF0000, 0xFF000000},  /* 8_8_8_8_REV */
539         };
540
541   static const u_int32_t masks_table_bgr[8][4] = {
542            {0x00000000, 0x00000000, 0x00000000, 0x00000000},
543            {0x00000000, 0x00000000, 0x00000000, 0x00000000},
544            {0x00000000, 0x00000000, 0x00000000, 0x00000000},
545            {0x0000001F, 0x000007E0, 0x0000F800, 0x00000000},  /* 5_6_5       */
546            {0x0000F800, 0x000007E0, 0x0000001F, 0x00000000},  /* 5_6_5_REV   */
547            {0x0000FF00, 0x00FF0000, 0xFF000000, 0x00000000},  /* 8_8_8_8     */
548            {0x00000000, 0x00000000, 0x00000000, 0x00000000},
549            {0x00FF0000, 0x0000FF00, 0x000000FF, 0x00000000},  /* 8_8_8_8_REV */
550         };
551
552   static const u_int32_t masks_table_bgra[8][4] = {
553            {0x00000000, 0x00000000, 0x00000000, 0x00000000},
554            {0x00000000, 0x00000000, 0x00000000, 0x00000000},
555            {0x00000000, 0x00000000, 0x00000000, 0x00000000},
556            {0x0000001F, 0x000007E0, 0x0000F800, 0x00000000},  /* 5_6_5       */
557            {0x0000F800, 0x000007E0, 0x0000001F, 0x00000000},  /* 5_6_5_REV   */
558            {0x0000FF00, 0x00FF0000, 0xFF000000, 0x000000FF},  /* 8_8_8_8     */
559            {0x00000000, 0x00000000, 0x00000000, 0x00000000},
560            {0x00FF0000, 0x0000FF00, 0x000000FF, 0xFF000000},  /* 8_8_8_8_REV */
561         };
562
563   static const u_int8_t bytes_per_pixel[8] = {
564            0, 0, 0, 2, 2, 4, 0, 4
565         };
566
567   const u_int8_t * bits;
568   const u_int32_t * masks;
569   const int index = fb_type & 0x07;
570   _EGLConfig *config;
571   unsigned i;
572   unsigned j;
573   unsigned k;
574
575   if ( bytes_per_pixel[index] == 0 ) {
576      fprintf(stderr, "[%s:%u] Framebuffer type 0x%04x has 0 bytes per pixel.\n",
577               __FUNCTION__, __LINE__, fb_type);
578      return GL_FALSE;
579   }
580
581   /* Valid types are GL_UNSIGNED_SHORT_5_6_5 and GL_UNSIGNED_INT_8_8_8_8 and
582    * the _REV versions.
583    *
584    * Valid formats are GL_RGBA, GL_RGB, and GL_BGRA.
585    */
586   switch ( fb_format ) {
587   case GL_RGB:
588      bits = (bytes_per_pixel[index] == 2) ? bits_table[0] : bits_table[1];
589      masks = masks_table_rgb[index];
590      break;
591
592   case GL_RGBA:
593      bits = (bytes_per_pixel[index] == 2) ? bits_table[0] : bits_table[2];
594      masks = masks_table_rgba[index];
595      break;
596
597   case GL_BGR:
598      bits = (bytes_per_pixel[index] == 2) ? bits_table[0] : bits_table[1];
599      masks = masks_table_bgr[index];
600      break;
601
602   case GL_BGRA:
603      bits = (bytes_per_pixel[index] == 2) ? bits_table[0] : bits_table[2];
604      masks = masks_table_bgra[index];
605      break;
606
607   default:
608      fprintf(stderr, "[%s:%u] Framebuffer format 0x%04x is not GL_RGB, GL_RGBA, GL_BGR, or GL_BGRA.\n",
609               __FUNCTION__, __LINE__, fb_format);
610      return GL_FALSE;
611   }
612
613   config = configs;
614   for (k = 0; k < num_depth_stencil_bits; k++) {
615      for (i = 0; i < num_db_modes; i++)  {
616         for (j = 0; j < 2; j++) {
617
618            _eglSetConfigAttrib(config, EGL_RED_SIZE, bits[0]);
619            _eglSetConfigAttrib(config, EGL_GREEN_SIZE, bits[1]);
620            _eglSetConfigAttrib(config, EGL_BLUE_SIZE, bits[2]);
621            _eglSetConfigAttrib(config, EGL_ALPHA_SIZE, bits[3]);
622            config->glmode.redMask = masks[0];
623            config->glmode.greenMask = masks[1];
624            config->glmode.blueMask = masks[2];
625            config->glmode.alphaMask = masks[3];
626            _eglSetConfigAttrib(config, EGL_BUFFER_SIZE,
627                           config->glmode.redBits + config->glmode.greenBits +
628                           config->glmode.blueBits + config->glmode.alphaBits);
629
630            config->glmode.accumRedBits = 16 * j;
631            config->glmode.accumGreenBits = 16 * j;
632            config->glmode.accumBlueBits = 16 * j;
633            config->glmode.accumAlphaBits = (masks[3] != 0) ? 16 * j : 0;
634            config->glmode.visualRating = (j == 0) ? GLX_NONE : GLX_SLOW_CONFIG;
635
636            _eglSetConfigAttrib(config, EGL_STENCIL_SIZE, stencil_bits[k]);
637            _eglSetConfigAttrib(config, EGL_DEPTH_SIZE, depth_bits[i]);
638
639            config->glmode.visualType = visType;
640            config->glmode.renderType = GLX_RGBA_BIT;
641            _eglSetConfigAttrib(config, EGL_SURFACE_TYPE, EGL_SCREEN_BIT_MESA |
642                                EGL_PBUFFER_BIT | EGL_PIXMAP_BIT | EGL_WINDOW_BIT);
643
644            config->glmode.rgbMode = GL_TRUE;
645
646            if (db_modes[i] == GLX_NONE) {
647               config->glmode.doubleBufferMode = GL_FALSE;
648            } else {
649               config->glmode.doubleBufferMode = GL_TRUE;
650               config->glmode.swapMethod = db_modes[i];
651            }
652
653            config->glmode.haveAccumBuffer = ((config->glmode.accumRedBits +
654                                               config->glmode.accumGreenBits +
655                                               config->glmode.accumBlueBits +
656                                               config->glmode.accumAlphaBits) > 0);
657            config->glmode.haveDepthBuffer = (config->glmode.depthBits > 0);
658            config->glmode.haveStencilBuffer = (config->glmode.stencilBits > 0);
659            config++;
660         }
661      }
662   }
663   return GL_TRUE;
664}
665