utils.c revision 17ef1f6074d6107c167f1956a5c60993904c0b72
1/*
2 * (C) Copyright IBM Corporation 2002, 2004
3 * All Rights Reserved.
4 *
5 * Permission is hereby granted, free of charge, to any person obtaining a
6 * copy of this software and associated documentation files (the "Software"),
7 * to deal in the Software without restriction, including without limitation
8 * on the rights to use, copy, modify, merge, publish, distribute, sub
9 * license, and/or sell copies of the Software, and to permit persons to whom
10 * the Software is furnished to do so, subject to the following conditions:
11 *
12 * The above copyright notice and this permission notice (including the next
13 * paragraph) shall be included in all copies or substantial portions of the
14 * Software.
15 *
16 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.  IN NO EVENT SHALL
19 * VA LINUX SYSTEM, IBM AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM,
20 * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
21 * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
22 * USE OR OTHER DEALINGS IN THE SOFTWARE.
23 */
24
25/**
26 * \file utils.c
27 * Utility functions for DRI drivers.
28 *
29 * \author Ian Romanick <idr@us.ibm.com>
30 */
31
32#include <string.h>
33#include <stdlib.h>
34#include "main/mtypes.h"
35#include "main/cpuinfo.h"
36#include "main/extensions.h"
37#include "glapi/dispatch.h"
38#include "utils.h"
39
40
41unsigned
42driParseDebugString( const char * debug,
43		     const struct dri_debug_control * control  )
44{
45   unsigned   flag;
46
47
48   flag = 0;
49   if ( debug != NULL ) {
50      while( control->string != NULL ) {
51	 if ( !strcmp( debug, "all" ) ||
52	      strstr( debug, control->string ) != NULL ) {
53	    flag |= control->flag;
54	 }
55
56	 control++;
57      }
58   }
59
60   return flag;
61}
62
63
64
65/**
66 * Create the \c GL_RENDERER string for DRI drivers.
67 *
68 * Almost all DRI drivers use a \c GL_RENDERER string of the form:
69 *
70 *    "Mesa DRI <chip> <driver date> <AGP speed) <CPU information>"
71 *
72 * Using the supplied chip name, driver data, and AGP speed, this function
73 * creates the string.
74 *
75 * \param buffer         Buffer to hold the \c GL_RENDERER string.
76 * \param hardware_name  Name of the hardware.
77 * \param driver_date    Driver date.
78 * \param agp_mode       AGP mode (speed).
79 *
80 * \returns
81 * The length of the string stored in \c buffer.  This does \b not include
82 * the terminating \c NUL character.
83 */
84unsigned
85driGetRendererString( char * buffer, const char * hardware_name,
86		      const char * driver_date, GLuint agp_mode )
87{
88   unsigned offset;
89   char *cpu;
90
91   offset = sprintf( buffer, "Mesa DRI %s %s", hardware_name, driver_date );
92
93   /* Append any AGP-specific information.
94    */
95   switch ( agp_mode ) {
96   case 1:
97   case 2:
98   case 4:
99   case 8:
100      offset += sprintf( & buffer[ offset ], " AGP %ux", agp_mode );
101      break;
102
103   default:
104      break;
105   }
106
107   /* Append any CPU-specific information.
108    */
109   cpu = _mesa_get_cpu_string();
110   if (cpu) {
111      offset += sprintf(buffer + offset, " %s", cpu);
112      _mesa_free(cpu);
113   }
114
115   return offset;
116}
117
118
119
120
121#define need_GL_ARB_draw_buffers
122#define need_GL_ARB_multisample
123#define need_GL_ARB_texture_compression
124#define need_GL_ARB_transpose_matrix
125#define need_GL_ARB_vertex_buffer_object
126#define need_GL_ARB_window_pos
127#define need_GL_EXT_compiled_vertex_array
128#define need_GL_EXT_multi_draw_arrays
129#define need_GL_EXT_polygon_offset
130#define need_GL_EXT_texture_object
131#define need_GL_EXT_vertex_array
132#define need_GL_IBM_multimode_draw_arrays
133#define need_GL_MESA_window_pos
134
135/* These are needed in *all* drivers because Mesa internally implements
136 * certain functionality in terms of functions provided by these extensions.
137 * For example, glBlendFunc is implemented by calling glBlendFuncSeparateEXT.
138 */
139#define need_GL_EXT_blend_func_separate
140#define need_GL_NV_vertex_program
141
142#include "main/remap_helper.h"
143
144static const struct dri_extension all_mesa_extensions[] = {
145   { "GL_ARB_draw_buffers",          GL_ARB_draw_buffers_functions },
146   { "GL_ARB_multisample",           GL_ARB_multisample_functions },
147   { "GL_ARB_texture_compression",   GL_ARB_texture_compression_functions },
148   { "GL_ARB_transpose_matrix",      GL_ARB_transpose_matrix_functions },
149   { "GL_ARB_vertex_buffer_object",  GL_ARB_vertex_buffer_object_functions},
150   { "GL_ARB_window_pos",            GL_ARB_window_pos_functions },
151   { "GL_EXT_blend_func_separate",   GL_EXT_blend_func_separate_functions },
152   { "GL_EXT_compiled_vertex_array", GL_EXT_compiled_vertex_array_functions },
153   { "GL_EXT_multi_draw_arrays",     GL_EXT_multi_draw_arrays_functions },
154   { "GL_EXT_polygon_offset",        GL_EXT_polygon_offset_functions },
155   { "GL_EXT_texture_object",        GL_EXT_texture_object_functions },
156   { "GL_EXT_vertex_array",          GL_EXT_vertex_array_functions },
157   { "GL_IBM_multimode_draw_arrays", GL_IBM_multimode_draw_arrays_functions },
158   { "GL_MESA_window_pos",           GL_MESA_window_pos_functions },
159   { "GL_NV_vertex_program",         GL_NV_vertex_program_functions },
160   { NULL,                           NULL }
161};
162
163
164/**
165 * Enable and map extensions supported by the driver.
166 *
167 * When ctx is NULL, extensions are not enabled, but their functions
168 * are still mapped.  When extensions_to_enable is NULL, all static
169 * functions known to mesa core are mapped.
170 *
171 * \bug
172 * ARB_imaging isn't handled properly.  In Mesa, enabling ARB_imaging also
173 * enables all the sub-extensions that are folded into it.  This means that
174 * we need to add entry-points (via \c driInitSingleExtension) for those
175 * new functions here.
176 */
177void driInitExtensions( GLcontext * ctx,
178			const struct dri_extension * extensions_to_enable,
179			GLboolean enable_imaging )
180{
181   static int first_time = 1;
182   unsigned   i;
183
184   if ( first_time ) {
185      first_time = 0;
186      driInitExtensions( NULL, all_mesa_extensions, GL_FALSE );
187   }
188
189   if ( (ctx != NULL) && enable_imaging ) {
190      _mesa_enable_imaging_extensions( ctx );
191   }
192
193   /* The caller is too lazy to list any extension */
194   if ( extensions_to_enable == NULL ) {
195      /* Map the static functions.  Together with those mapped by remap
196       * table, this should cover everything mesa core knows.
197       */
198      _mesa_map_static_functions();
199      return;
200   }
201
202   for ( i = 0 ; extensions_to_enable[i].name != NULL ; i++ ) {
203       driInitSingleExtension( ctx, & extensions_to_enable[i] );
204   }
205}
206
207
208
209
210/**
211 * Enable and map functions for a single extension
212 *
213 * \param ctx  Context where extension is to be enabled.
214 * \param ext  Extension that is to be enabled.
215 *
216 * \sa driInitExtensions, _mesa_enable_extension, _mesa_map_function_array
217 */
218void driInitSingleExtension( GLcontext * ctx,
219			     const struct dri_extension * ext )
220{
221    if ( ext->functions != NULL ) {
222       _mesa_map_function_array(ext->functions);
223    }
224
225    if ( ctx != NULL ) {
226	_mesa_enable_extension( ctx, ext->name );
227    }
228}
229
230
231/**
232 * Utility function used by drivers to test the verions of other components.
233 *
234 * If one of the version requirements is not met, a message is logged using
235 * \c __driUtilMessage.
236 *
237 * \param driver_name  Name of the driver.  Used in error messages.
238 * \param driActual    Actual DRI version supplied __driCreateNewScreen.
239 * \param driExpected  Minimum DRI version required by the driver.
240 * \param ddxActual    Actual DDX version supplied __driCreateNewScreen.
241 * \param ddxExpected  Minimum DDX minor and range of DDX major version required by the driver.
242 * \param drmActual    Actual DRM version supplied __driCreateNewScreen.
243 * \param drmExpected  Minimum DRM version required by the driver.
244 *
245 * \returns \c GL_TRUE if all version requirements are met.  Otherwise,
246 *          \c GL_FALSE is returned.
247 *
248 * \sa __driCreateNewScreen, driCheckDriDdxDrmVersions2, __driUtilMessage
249 *
250 * \todo
251 * Now that the old \c driCheckDriDdxDrmVersions function is gone, this
252 * function and \c driCheckDriDdxDrmVersions2 should be renamed.
253 */
254GLboolean
255driCheckDriDdxDrmVersions3(const char * driver_name,
256			   const __DRIversion * driActual,
257			   const __DRIversion * driExpected,
258			   const __DRIversion * ddxActual,
259			   const __DRIutilversion2 * ddxExpected,
260			   const __DRIversion * drmActual,
261			   const __DRIversion * drmExpected)
262{
263   static const char format[] = "%s DRI driver expected %s version %d.%d.x "
264       "but got version %d.%d.%d\n";
265   static const char format2[] = "%s DRI driver expected %s version %d-%d.%d.x "
266       "but got version %d.%d.%d\n";
267
268
269   /* Check the DRI version */
270   if ( (driActual->major != driExpected->major)
271	|| (driActual->minor < driExpected->minor) ) {
272      fprintf(stderr, format, driver_name, "DRI",
273		       driExpected->major, driExpected->minor,
274		       driActual->major, driActual->minor, driActual->patch);
275      return GL_FALSE;
276   }
277
278   /* Check that the DDX driver version is compatible */
279   /* for miniglx we pass in -1 so we can ignore the DDX version */
280   if ( (ddxActual->major != -1) && ((ddxActual->major < ddxExpected->major_min)
281	|| (ddxActual->major > ddxExpected->major_max)
282	|| (ddxActual->minor < ddxExpected->minor)) ) {
283      fprintf(stderr, format2, driver_name, "DDX",
284		       ddxExpected->major_min, ddxExpected->major_max, ddxExpected->minor,
285		       ddxActual->major, ddxActual->minor, ddxActual->patch);
286      return GL_FALSE;
287   }
288
289   /* Check that the DRM driver version is compatible */
290   if ( (drmActual->major != drmExpected->major)
291	|| (drmActual->minor < drmExpected->minor) ) {
292      fprintf(stderr, format, driver_name, "DRM",
293		       drmExpected->major, drmExpected->minor,
294		       drmActual->major, drmActual->minor, drmActual->patch);
295      return GL_FALSE;
296   }
297
298   return GL_TRUE;
299}
300
301GLboolean
302driCheckDriDdxDrmVersions2(const char * driver_name,
303			   const __DRIversion * driActual,
304			   const __DRIversion * driExpected,
305			   const __DRIversion * ddxActual,
306			   const __DRIversion * ddxExpected,
307			   const __DRIversion * drmActual,
308			   const __DRIversion * drmExpected)
309{
310   __DRIutilversion2 ddx_expected;
311   ddx_expected.major_min = ddxExpected->major;
312   ddx_expected.major_max = ddxExpected->major;
313   ddx_expected.minor = ddxExpected->minor;
314   ddx_expected.patch = ddxExpected->patch;
315   return driCheckDriDdxDrmVersions3(driver_name, driActual,
316				driExpected, ddxActual, & ddx_expected,
317				drmActual, drmExpected);
318}
319
320GLboolean driClipRectToFramebuffer( const GLframebuffer *buffer,
321				    GLint *x, GLint *y,
322				    GLsizei *width, GLsizei *height )
323{
324   /* left clipping */
325   if (*x < buffer->_Xmin) {
326      *width -= (buffer->_Xmin - *x);
327      *x = buffer->_Xmin;
328   }
329
330   /* right clipping */
331   if (*x + *width > buffer->_Xmax)
332      *width -= (*x + *width - buffer->_Xmax - 1);
333
334   if (*width <= 0)
335      return GL_FALSE;
336
337   /* bottom clipping */
338   if (*y < buffer->_Ymin) {
339      *height -= (buffer->_Ymin - *y);
340      *y = buffer->_Ymin;
341   }
342
343   /* top clipping */
344   if (*y + *height > buffer->_Ymax)
345      *height -= (*y + *height - buffer->_Ymax - 1);
346
347   if (*height <= 0)
348      return GL_FALSE;
349
350   return GL_TRUE;
351}
352
353/**
354 * Creates a set of \c __GLcontextModes that a driver will expose.
355 *
356 * A set of \c __GLcontextModes will be created based on the supplied
357 * parameters.  The number of modes processed will be 2 *
358 * \c num_depth_stencil_bits * \c num_db_modes.
359 *
360 * For the most part, data is just copied from \c depth_bits, \c stencil_bits,
361 * \c db_modes, and \c visType into each \c __GLcontextModes element.
362 * However, the meanings of \c fb_format and \c fb_type require further
363 * explanation.  The \c fb_format specifies which color components are in
364 * each pixel and what the default order is.  For example, \c GL_RGB specifies
365 * that red, green, blue are available and red is in the "most significant"
366 * position and blue is in the "least significant".  The \c fb_type specifies
367 * the bit sizes of each component and the actual ordering.  For example, if
368 * \c GL_UNSIGNED_SHORT_5_6_5_REV is specified with \c GL_RGB, bits [15:11]
369 * are the blue value, bits [10:5] are the green value, and bits [4:0] are
370 * the red value.
371 *
372 * One sublte issue is the combination of \c GL_RGB  or \c GL_BGR and either
373 * of the \c GL_UNSIGNED_INT_8_8_8_8 modes.  The resulting mask values in the
374 * \c __GLcontextModes structure is \b identical to the \c GL_RGBA or
375 * \c GL_BGRA case, except the \c alphaMask is zero.  This means that, as
376 * far as this routine is concerned, \c GL_RGB with \c GL_UNSIGNED_INT_8_8_8_8
377 * still uses 32-bits.
378 *
379 * If in doubt, look at the tables used in the function.
380 *
381 * \param ptr_to_modes  Pointer to a pointer to a linked list of
382 *                      \c __GLcontextModes.  Upon completion, a pointer to
383 *                      the next element to be process will be stored here.
384 *                      If the function fails and returns \c GL_FALSE, this
385 *                      value will be unmodified, but some elements in the
386 *                      linked list may be modified.
387 * \param fb_format     Format of the framebuffer.  Currently only \c GL_RGB,
388 *                      \c GL_RGBA, \c GL_BGR, and \c GL_BGRA are supported.
389 * \param fb_type       Type of the pixels in the framebuffer.  Currently only
390 *                      \c GL_UNSIGNED_SHORT_5_6_5,
391 *                      \c GL_UNSIGNED_SHORT_5_6_5_REV,
392 *                      \c GL_UNSIGNED_INT_8_8_8_8, and
393 *                      \c GL_UNSIGNED_INT_8_8_8_8_REV are supported.
394 * \param depth_bits    Array of depth buffer sizes to be exposed.
395 * \param stencil_bits  Array of stencil buffer sizes to be exposed.
396 * \param num_depth_stencil_bits  Number of entries in both \c depth_bits and
397 *                      \c stencil_bits.
398 * \param db_modes      Array of buffer swap modes.  If an element has a
399 *                      value of \c GLX_NONE, then it represents a
400 *                      single-buffered mode.  Other valid values are
401 *                      \c GLX_SWAP_EXCHANGE_OML, \c GLX_SWAP_COPY_OML, and
402 *                      \c GLX_SWAP_UNDEFINED_OML.  See the
403 *                      GLX_OML_swap_method extension spec for more details.
404 * \param num_db_modes  Number of entries in \c db_modes.
405 * \param msaa_samples  Array of msaa sample count. 0 represents a visual
406 *                      without a multisample buffer.
407 * \param num_msaa_modes Number of entries in \c msaa_samples.
408 * \param visType       GLX visual type.  Usually either \c GLX_TRUE_COLOR or
409 *                      \c GLX_DIRECT_COLOR.
410 *
411 * \returns
412 * \c GL_TRUE on success or \c GL_FALSE on failure.  Currently the only
413 * cause of failure is a bad parameter (i.e., unsupported \c fb_format or
414 * \c fb_type).
415 *
416 * \todo
417 * There is currently no way to support packed RGB modes (i.e., modes with
418 * exactly 3 bytes per pixel) or floating-point modes.  This could probably
419 * be done by creating some new, private enums with clever names likes
420 * \c GL_UNSIGNED_3BYTE_8_8_8, \c GL_4FLOAT_32_32_32_32,
421 * \c GL_4HALF_16_16_16_16, etc.  We can cross that bridge when we come to it.
422 */
423__DRIconfig **
424driCreateConfigs(GLenum fb_format, GLenum fb_type,
425		 const uint8_t * depth_bits, const uint8_t * stencil_bits,
426		 unsigned num_depth_stencil_bits,
427		 const GLenum * db_modes, unsigned num_db_modes,
428		 const uint8_t * msaa_samples, unsigned num_msaa_modes)
429{
430   static const uint8_t bits_table[4][4] = {
431     /* R  G  B  A */
432      { 3, 3, 2, 0 }, /* Any GL_UNSIGNED_BYTE_3_3_2 */
433      { 5, 6, 5, 0 }, /* Any GL_UNSIGNED_SHORT_5_6_5 */
434      { 8, 8, 8, 0 }, /* Any RGB with any GL_UNSIGNED_INT_8_8_8_8 */
435      { 8, 8, 8, 8 }  /* Any RGBA with any GL_UNSIGNED_INT_8_8_8_8 */
436   };
437
438   static const uint32_t masks_table_rgb[6][4] = {
439      { 0x000000E0, 0x0000001C, 0x00000003, 0x00000000 }, /* 3_3_2       */
440      { 0x00000007, 0x00000038, 0x000000C0, 0x00000000 }, /* 2_3_3_REV   */
441      { 0x0000F800, 0x000007E0, 0x0000001F, 0x00000000 }, /* 5_6_5       */
442      { 0x0000001F, 0x000007E0, 0x0000F800, 0x00000000 }, /* 5_6_5_REV   */
443      { 0xFF000000, 0x00FF0000, 0x0000FF00, 0x00000000 }, /* 8_8_8_8     */
444      { 0x000000FF, 0x0000FF00, 0x00FF0000, 0x00000000 }  /* 8_8_8_8_REV */
445   };
446
447   static const uint32_t masks_table_rgba[6][4] = {
448      { 0x000000E0, 0x0000001C, 0x00000003, 0x00000000 }, /* 3_3_2       */
449      { 0x00000007, 0x00000038, 0x000000C0, 0x00000000 }, /* 2_3_3_REV   */
450      { 0x0000F800, 0x000007E0, 0x0000001F, 0x00000000 }, /* 5_6_5       */
451      { 0x0000001F, 0x000007E0, 0x0000F800, 0x00000000 }, /* 5_6_5_REV   */
452      { 0xFF000000, 0x00FF0000, 0x0000FF00, 0x000000FF }, /* 8_8_8_8     */
453      { 0x000000FF, 0x0000FF00, 0x00FF0000, 0xFF000000 }, /* 8_8_8_8_REV */
454   };
455
456   static const uint32_t masks_table_bgr[6][4] = {
457      { 0x00000007, 0x00000038, 0x000000C0, 0x00000000 }, /* 3_3_2       */
458      { 0x000000E0, 0x0000001C, 0x00000003, 0x00000000 }, /* 2_3_3_REV   */
459      { 0x0000001F, 0x000007E0, 0x0000F800, 0x00000000 }, /* 5_6_5       */
460      { 0x0000F800, 0x000007E0, 0x0000001F, 0x00000000 }, /* 5_6_5_REV   */
461      { 0x0000FF00, 0x00FF0000, 0xFF000000, 0x00000000 }, /* 8_8_8_8     */
462      { 0x00FF0000, 0x0000FF00, 0x000000FF, 0x00000000 }, /* 8_8_8_8_REV */
463   };
464
465   static const uint32_t masks_table_bgra[6][4] = {
466      { 0x00000007, 0x00000038, 0x000000C0, 0x00000000 }, /* 3_3_2       */
467      { 0x000000E0, 0x0000001C, 0x00000003, 0x00000000 }, /* 2_3_3_REV   */
468      { 0x0000001F, 0x000007E0, 0x0000F800, 0x00000000 }, /* 5_6_5       */
469      { 0x0000F800, 0x000007E0, 0x0000001F, 0x00000000 }, /* 5_6_5_REV   */
470      { 0x0000FF00, 0x00FF0000, 0xFF000000, 0x000000FF }, /* 8_8_8_8     */
471      { 0x00FF0000, 0x0000FF00, 0x000000FF, 0xFF000000 }, /* 8_8_8_8_REV */
472   };
473
474   static const uint8_t bytes_per_pixel[6] = {
475      1, /* 3_3_2       */
476      1, /* 2_3_3_REV   */
477      2, /* 5_6_5       */
478      2, /* 5_6_5_REV   */
479      4, /* 8_8_8_8     */
480      4  /* 8_8_8_8_REV */
481   };
482
483   const uint8_t  * bits;
484   const uint32_t * masks;
485   int index;
486   __DRIconfig **configs, **c;
487   __GLcontextModes *modes;
488   unsigned i, j, k, h;
489   unsigned num_modes;
490   unsigned num_accum_bits = 2;
491
492   switch ( fb_type ) {
493      case GL_UNSIGNED_BYTE_3_3_2:
494	 index = 0;
495	 break;
496      case GL_UNSIGNED_BYTE_2_3_3_REV:
497	 index = 1;
498	 break;
499      case GL_UNSIGNED_SHORT_5_6_5:
500	 index = 2;
501	 break;
502      case GL_UNSIGNED_SHORT_5_6_5_REV:
503	 index = 3;
504	 break;
505      case GL_UNSIGNED_INT_8_8_8_8:
506	 index = 4;
507	 break;
508      case GL_UNSIGNED_INT_8_8_8_8_REV:
509	 index = 5;
510	 break;
511      default:
512	 fprintf( stderr, "[%s:%u] Unknown framebuffer type 0x%04x.\n",
513               __FUNCTION__, __LINE__, fb_type );
514	 return NULL;
515   }
516
517
518   /* Valid types are GL_UNSIGNED_SHORT_5_6_5 and GL_UNSIGNED_INT_8_8_8_8 and
519    * the _REV versions.
520    *
521    * Valid formats are GL_RGBA, GL_RGB, and GL_BGRA.
522    */
523
524   switch ( fb_format ) {
525      case GL_RGB:
526         masks = masks_table_rgb[ index ];
527         break;
528
529      case GL_RGBA:
530         masks = masks_table_rgba[ index ];
531         break;
532
533      case GL_BGR:
534         masks = masks_table_bgr[ index ];
535         break;
536
537      case GL_BGRA:
538         masks = masks_table_bgra[ index ];
539         break;
540
541      default:
542         fprintf( stderr, "[%s:%u] Unknown framebuffer format 0x%04x.\n",
543               __FUNCTION__, __LINE__, fb_format );
544         return NULL;
545   }
546
547   switch ( bytes_per_pixel[ index ] ) {
548      case 1:
549	 bits = bits_table[0];
550	 break;
551      case 2:
552	 bits = bits_table[1];
553	 break;
554      default:
555	 bits = ((fb_format == GL_RGB) || (fb_format == GL_BGR))
556	    ? bits_table[2]
557	    : bits_table[3];
558	 break;
559   }
560
561   num_modes = num_depth_stencil_bits * num_db_modes * num_accum_bits * num_msaa_modes;
562   configs = _mesa_calloc((num_modes + 1) * sizeof *configs);
563   if (configs == NULL)
564       return NULL;
565
566    c = configs;
567    for ( k = 0 ; k < num_depth_stencil_bits ; k++ ) {
568	for ( i = 0 ; i < num_db_modes ; i++ ) {
569	    for ( h = 0 ; h < num_msaa_modes; h++ ) {
570	    	for ( j = 0 ; j < num_accum_bits ; j++ ) {
571		    *c = _mesa_malloc (sizeof **c);
572		    modes = &(*c)->modes;
573		    c++;
574
575		    memset(modes, 0, sizeof *modes);
576		    modes->redBits   = bits[0];
577		    modes->greenBits = bits[1];
578		    modes->blueBits  = bits[2];
579		    modes->alphaBits = bits[3];
580		    modes->redMask   = masks[0];
581		    modes->greenMask = masks[1];
582		    modes->blueMask  = masks[2];
583		    modes->alphaMask = masks[3];
584		    modes->rgbBits   = modes->redBits + modes->greenBits
585		    	+ modes->blueBits + modes->alphaBits;
586
587		    modes->accumRedBits   = 16 * j;
588		    modes->accumGreenBits = 16 * j;
589		    modes->accumBlueBits  = 16 * j;
590		    modes->accumAlphaBits = (masks[3] != 0) ? 16 * j : 0;
591		    modes->visualRating = (j == 0) ? GLX_NONE : GLX_SLOW_CONFIG;
592
593		    modes->stencilBits = stencil_bits[k];
594		    modes->depthBits = depth_bits[k];
595
596		    modes->transparentPixel = GLX_NONE;
597		    modes->transparentRed = GLX_DONT_CARE;
598		    modes->transparentGreen = GLX_DONT_CARE;
599		    modes->transparentBlue = GLX_DONT_CARE;
600		    modes->transparentAlpha = GLX_DONT_CARE;
601		    modes->transparentIndex = GLX_DONT_CARE;
602		    modes->visualType = GLX_DONT_CARE;
603		    modes->renderType = GLX_RGBA_BIT;
604		    modes->drawableType = GLX_WINDOW_BIT;
605		    modes->rgbMode = GL_TRUE;
606
607		    if ( db_modes[i] == GLX_NONE ) {
608		    	modes->doubleBufferMode = GL_FALSE;
609		    }
610		    else {
611		    	modes->doubleBufferMode = GL_TRUE;
612		    	modes->swapMethod = db_modes[i];
613		    }
614
615		    modes->samples = msaa_samples[h];
616		    modes->sampleBuffers = modes->samples ? 1 : 0;
617
618
619		    modes->haveAccumBuffer = ((modes->accumRedBits +
620					   modes->accumGreenBits +
621					   modes->accumBlueBits +
622					   modes->accumAlphaBits) > 0);
623		    modes->haveDepthBuffer = (modes->depthBits > 0);
624		    modes->haveStencilBuffer = (modes->stencilBits > 0);
625
626		    modes->bindToTextureRgb = GL_TRUE;
627		    modes->bindToTextureRgba = GL_TRUE;
628		    modes->bindToMipmapTexture = GL_FALSE;
629		    modes->bindToTextureTargets = modes->rgbMode ?
630		    	__DRI_ATTRIB_TEXTURE_1D_BIT |
631		    	__DRI_ATTRIB_TEXTURE_2D_BIT |
632		    	__DRI_ATTRIB_TEXTURE_RECTANGLE_BIT :
633		    	0;
634		}
635	    }
636	}
637    }
638    *c = NULL;
639
640    return configs;
641}
642
643__DRIconfig **driConcatConfigs(__DRIconfig **a,
644			       __DRIconfig **b)
645{
646    __DRIconfig **all;
647    int i, j, index;
648
649    i = 0;
650    while (a[i] != NULL)
651	i++;
652    j = 0;
653    while (b[j] != NULL)
654	j++;
655
656    all = _mesa_malloc((i + j + 1) * sizeof *all);
657    index = 0;
658    for (i = 0; a[i] != NULL; i++)
659	all[index++] = a[i];
660    for (j = 0; b[j] != NULL; j++)
661	all[index++] = b[j];
662    all[index++] = NULL;
663
664    _mesa_free(a);
665    _mesa_free(b);
666
667    return all;
668}
669
670#define __ATTRIB(attrib, field) \
671    { attrib, offsetof(__GLcontextModes, field) }
672
673static const struct { unsigned int attrib, offset; } attribMap[] = {
674    __ATTRIB(__DRI_ATTRIB_BUFFER_SIZE,			rgbBits),
675    __ATTRIB(__DRI_ATTRIB_LEVEL,			level),
676    __ATTRIB(__DRI_ATTRIB_RED_SIZE,			redBits),
677    __ATTRIB(__DRI_ATTRIB_GREEN_SIZE,			greenBits),
678    __ATTRIB(__DRI_ATTRIB_BLUE_SIZE,			blueBits),
679    __ATTRIB(__DRI_ATTRIB_ALPHA_SIZE,			alphaBits),
680    __ATTRIB(__DRI_ATTRIB_DEPTH_SIZE,			depthBits),
681    __ATTRIB(__DRI_ATTRIB_STENCIL_SIZE,			stencilBits),
682    __ATTRIB(__DRI_ATTRIB_ACCUM_RED_SIZE,		accumRedBits),
683    __ATTRIB(__DRI_ATTRIB_ACCUM_GREEN_SIZE,		accumGreenBits),
684    __ATTRIB(__DRI_ATTRIB_ACCUM_BLUE_SIZE,		accumBlueBits),
685    __ATTRIB(__DRI_ATTRIB_ACCUM_ALPHA_SIZE,		accumAlphaBits),
686    __ATTRIB(__DRI_ATTRIB_SAMPLE_BUFFERS,		sampleBuffers),
687    __ATTRIB(__DRI_ATTRIB_SAMPLES,			samples),
688    __ATTRIB(__DRI_ATTRIB_DOUBLE_BUFFER,		doubleBufferMode),
689    __ATTRIB(__DRI_ATTRIB_STEREO,			stereoMode),
690    __ATTRIB(__DRI_ATTRIB_AUX_BUFFERS,			numAuxBuffers),
691    __ATTRIB(__DRI_ATTRIB_TRANSPARENT_TYPE,		transparentPixel),
692    __ATTRIB(__DRI_ATTRIB_TRANSPARENT_INDEX_VALUE,	transparentPixel),
693    __ATTRIB(__DRI_ATTRIB_TRANSPARENT_RED_VALUE,	transparentRed),
694    __ATTRIB(__DRI_ATTRIB_TRANSPARENT_GREEN_VALUE,	transparentGreen),
695    __ATTRIB(__DRI_ATTRIB_TRANSPARENT_BLUE_VALUE,	transparentBlue),
696    __ATTRIB(__DRI_ATTRIB_TRANSPARENT_ALPHA_VALUE,	transparentAlpha),
697    __ATTRIB(__DRI_ATTRIB_FLOAT_MODE,			floatMode),
698    __ATTRIB(__DRI_ATTRIB_RED_MASK,			redMask),
699    __ATTRIB(__DRI_ATTRIB_GREEN_MASK,			greenMask),
700    __ATTRIB(__DRI_ATTRIB_BLUE_MASK,			blueMask),
701    __ATTRIB(__DRI_ATTRIB_ALPHA_MASK,			alphaMask),
702    __ATTRIB(__DRI_ATTRIB_MAX_PBUFFER_WIDTH,		maxPbufferWidth),
703    __ATTRIB(__DRI_ATTRIB_MAX_PBUFFER_HEIGHT,		maxPbufferHeight),
704    __ATTRIB(__DRI_ATTRIB_MAX_PBUFFER_PIXELS,		maxPbufferPixels),
705    __ATTRIB(__DRI_ATTRIB_OPTIMAL_PBUFFER_WIDTH,	optimalPbufferWidth),
706    __ATTRIB(__DRI_ATTRIB_OPTIMAL_PBUFFER_HEIGHT,	optimalPbufferHeight),
707    __ATTRIB(__DRI_ATTRIB_SWAP_METHOD,			swapMethod),
708    __ATTRIB(__DRI_ATTRIB_BIND_TO_TEXTURE_RGB,		bindToTextureRgb),
709    __ATTRIB(__DRI_ATTRIB_BIND_TO_TEXTURE_RGBA,		bindToTextureRgba),
710    __ATTRIB(__DRI_ATTRIB_BIND_TO_MIPMAP_TEXTURE,	bindToMipmapTexture),
711    __ATTRIB(__DRI_ATTRIB_BIND_TO_TEXTURE_TARGETS,	bindToTextureTargets),
712    __ATTRIB(__DRI_ATTRIB_YINVERTED,			yInverted),
713
714    /* The struct field doesn't matter here, these are handled by the
715     * switch in driGetConfigAttribIndex.  We need them in the array
716     * so the iterator includes them though.*/
717    __ATTRIB(__DRI_ATTRIB_RENDER_TYPE,			level),
718    __ATTRIB(__DRI_ATTRIB_CONFIG_CAVEAT,		level),
719    __ATTRIB(__DRI_ATTRIB_SWAP_METHOD,			level)
720};
721
722#define ARRAY_SIZE(a) (sizeof (a) / sizeof ((a)[0]))
723
724static int
725driGetConfigAttribIndex(const __DRIconfig *config,
726			unsigned int index, unsigned int *value)
727{
728    switch (attribMap[index].attrib) {
729    case __DRI_ATTRIB_RENDER_TYPE:
730	if (config->modes.rgbMode)
731	    *value = __DRI_ATTRIB_RGBA_BIT;
732	else
733	    *value = __DRI_ATTRIB_COLOR_INDEX_BIT;
734	break;
735    case __DRI_ATTRIB_CONFIG_CAVEAT:
736	if (config->modes.visualRating == GLX_NON_CONFORMANT_CONFIG)
737	    *value = __DRI_ATTRIB_NON_CONFORMANT_CONFIG;
738	else if (config->modes.visualRating == GLX_SLOW_CONFIG)
739	    *value = __DRI_ATTRIB_SLOW_BIT;
740	else
741	    *value = 0;
742	break;
743    case __DRI_ATTRIB_SWAP_METHOD:
744	break;
745
746    case __DRI_ATTRIB_FLOAT_MODE:
747        *value = config->modes.floatMode;
748        break;
749
750    default:
751	*value = *(unsigned int *)
752	    ((char *) &config->modes + attribMap[index].offset);
753
754	break;
755    }
756
757    return GL_TRUE;
758}
759
760int
761driGetConfigAttrib(const __DRIconfig *config,
762		   unsigned int attrib, unsigned int *value)
763{
764    int i;
765
766    for (i = 0; i < ARRAY_SIZE(attribMap); i++)
767	if (attribMap[i].attrib == attrib)
768	    return driGetConfigAttribIndex(config, i, value);
769
770    return GL_FALSE;
771}
772
773int
774driIndexConfigAttrib(const __DRIconfig *config, int index,
775		     unsigned int *attrib, unsigned int *value)
776{
777    if (index >= 0 && index < ARRAY_SIZE(attribMap)) {
778	*attrib = attribMap[index].attrib;
779	return driGetConfigAttribIndex(config, index, value);
780    }
781
782    return GL_FALSE;
783}
784