~ubuntu-branches/ubuntu/quantal/mesa-glw/quantal

« back to all changes in this revision

Viewing changes to src/mesa/drivers/dri/common/utils.c

  • Committer: Bazaar Package Importer
  • Author(s): Morten Kjeldgaard
  • Date: 2008-05-06 16:19:15 UTC
  • Revision ID: james.westby@ubuntu.com-20080506161915-uynz7nftmfixu6bq
Tags: upstream-7.0.3
ImportĀ upstreamĀ versionĀ 7.0.3

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
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 "mtypes.h"
 
35
#include "extensions.h"
 
36
#include "utils.h"
 
37
#include "dispatch.h"
 
38
 
 
39
int driDispatchRemapTable[ driDispatchRemapTable_size ];
 
40
 
 
41
#if defined(USE_X86_ASM)
 
42
#include "x86/common_x86_asm.h"
 
43
#endif
 
44
 
 
45
#if defined(USE_PPC_ASM)
 
46
#include "ppc/common_ppc_features.h"
 
47
#endif
 
48
 
 
49
unsigned
 
50
driParseDebugString( const char * debug, 
 
51
                     const struct dri_debug_control * control  )
 
52
{
 
53
   unsigned   flag;
 
54
 
 
55
 
 
56
   flag = 0;
 
57
   if ( debug != NULL ) {
 
58
      while( control->string != NULL ) {
 
59
         if ( !strcmp( debug, "all" ) ||
 
60
              strstr( debug, control->string ) != NULL ) {
 
61
            flag |= control->flag;
 
62
         }
 
63
 
 
64
         control++;
 
65
      }
 
66
   }
 
67
 
 
68
   return flag;
 
69
}
 
70
 
 
71
 
 
72
 
 
73
/**
 
74
 * Create the \c GL_RENDERER string for DRI drivers.
 
75
 * 
 
76
 * Almost all DRI drivers use a \c GL_RENDERER string of the form:
 
77
 *
 
78
 *    "Mesa DRI <chip> <driver date> <AGP speed) <CPU information>"
 
79
 *
 
80
 * Using the supplied chip name, driver data, and AGP speed, this function
 
81
 * creates the string.
 
82
 * 
 
83
 * \param buffer         Buffer to hold the \c GL_RENDERER string.
 
84
 * \param hardware_name  Name of the hardware.
 
85
 * \param driver_date    Driver date.
 
86
 * \param agp_mode       AGP mode (speed).
 
87
 * 
 
88
 * \returns
 
89
 * The length of the string stored in \c buffer.  This does \b not include
 
90
 * the terminating \c NUL character.
 
91
 */
 
92
unsigned
 
93
driGetRendererString( char * buffer, const char * hardware_name,
 
94
                      const char * driver_date, GLuint agp_mode )
 
95
{
 
96
#define MAX_INFO   4
 
97
   const char * cpu[MAX_INFO];
 
98
   unsigned   next = 0;
 
99
   unsigned   i;
 
100
   unsigned   offset;
 
101
 
 
102
 
 
103
   offset = sprintf( buffer, "Mesa DRI %s %s", hardware_name, driver_date );
 
104
 
 
105
   /* Append any AGP-specific information.
 
106
    */
 
107
   switch ( agp_mode ) {
 
108
   case 1:
 
109
   case 2:
 
110
   case 4:
 
111
   case 8:
 
112
      offset += sprintf( & buffer[ offset ], " AGP %ux", agp_mode );
 
113
      break;
 
114
        
 
115
   default:
 
116
      break;
 
117
   }
 
118
 
 
119
   /* Append any CPU-specific information.
 
120
    */
 
121
#ifdef USE_X86_ASM
 
122
   if ( _mesa_x86_cpu_features ) {
 
123
      cpu[next] = " x86";
 
124
      next++;
 
125
   }
 
126
# ifdef USE_MMX_ASM
 
127
   if ( cpu_has_mmx ) {
 
128
      cpu[next] = (cpu_has_mmxext) ? "/MMX+" : "/MMX";
 
129
      next++;
 
130
   }
 
131
# endif
 
132
# ifdef USE_3DNOW_ASM
 
133
   if ( cpu_has_3dnow ) {
 
134
      cpu[next] = (cpu_has_3dnowext) ? "/3DNow!+" : "/3DNow!";
 
135
      next++;
 
136
   }
 
137
# endif
 
138
# ifdef USE_SSE_ASM
 
139
   if ( cpu_has_xmm ) {
 
140
      cpu[next] = (cpu_has_xmm2) ? "/SSE2" : "/SSE";
 
141
      next++;
 
142
   }
 
143
# endif
 
144
 
 
145
#elif defined(USE_SPARC_ASM)
 
146
 
 
147
   cpu[0] = " SPARC";
 
148
   next = 1;
 
149
 
 
150
#elif defined(USE_PPC_ASM)
 
151
   if ( _mesa_ppc_cpu_features ) {
 
152
      cpu[next] = (cpu_has_64) ? " PowerPC 64" : " PowerPC";
 
153
      next++;
 
154
   }
 
155
 
 
156
# ifdef USE_VMX_ASM
 
157
   if ( cpu_has_vmx ) {
 
158
      cpu[next] = "/Altivec";
 
159
      next++;
 
160
   }
 
161
# endif
 
162
 
 
163
   if ( ! cpu_has_fpu ) {
 
164
      cpu[next] = "/No FPU";
 
165
      next++;
 
166
   }
 
167
#endif
 
168
 
 
169
   for ( i = 0 ; i < next ; i++ ) {
 
170
      const size_t len = strlen( cpu[i] );
 
171
 
 
172
      strncpy( & buffer[ offset ], cpu[i], len );
 
173
      offset += len;
 
174
   }
 
175
 
 
176
   return offset;
 
177
}
 
178
 
 
179
 
 
180
 
 
181
 
 
182
#define need_GL_ARB_multisample
 
183
#define need_GL_ARB_transpose_matrix
 
184
#define need_GL_ARB_window_pos
 
185
#define need_GL_EXT_compiled_vertex_array
 
186
#define need_GL_EXT_polygon_offset
 
187
#define need_GL_EXT_texture_object
 
188
#define need_GL_EXT_vertex_array
 
189
#define need_GL_MESA_window_pos
 
190
 
 
191
/* These are needed in *all* drivers because Mesa internally implements
 
192
 * certain functionality in terms of functions provided by these extensions.
 
193
 * For example, glBlendFunc is implemented by calling glBlendFuncSeparateEXT.
 
194
 */
 
195
#define need_GL_EXT_blend_func_separate
 
196
#define need_GL_NV_vertex_program
 
197
 
 
198
#include "extension_helper.h"
 
199
 
 
200
static const struct dri_extension all_mesa_extensions[] = {
 
201
   { "GL_ARB_multisample",           GL_ARB_multisample_functions },
 
202
   { "GL_ARB_transpose_matrix",      GL_ARB_transpose_matrix_functions },
 
203
   { "GL_ARB_window_pos",            GL_ARB_window_pos_functions },
 
204
   { "GL_EXT_blend_func_separate",   GL_EXT_blend_func_separate_functions },
 
205
   { "GL_EXT_compiled_vertex_array", GL_EXT_compiled_vertex_array_functions },
 
206
   { "GL_EXT_polygon_offset",        GL_EXT_polygon_offset_functions },
 
207
   { "GL_EXT_texture_object",        GL_EXT_texture_object_functions },
 
208
   { "GL_EXT_vertex_array",          GL_EXT_vertex_array_functions },
 
209
   { "GL_MESA_window_pos",           GL_MESA_window_pos_functions },
 
210
   { "GL_NV_vertex_program",         GL_NV_vertex_program_functions },
 
211
   { NULL,                           NULL }
 
212
};
 
213
 
 
214
 
 
215
/**
 
216
 * Enable extensions supported by the driver.
 
217
 * 
 
218
 * \bug
 
219
 * ARB_imaging isn't handled properly.  In Mesa, enabling ARB_imaging also
 
220
 * enables all the sub-extensions that are folded into it.  This means that
 
221
 * we need to add entry-points (via \c driInitSingleExtension) for those
 
222
 * new functions here.
 
223
 */
 
224
void driInitExtensions( GLcontext * ctx,
 
225
                        const struct dri_extension * extensions_to_enable,
 
226
                        GLboolean enable_imaging )
 
227
{
 
228
   static int first_time = 1;
 
229
   unsigned   i;
 
230
 
 
231
   if ( first_time ) {
 
232
      for ( i = 0 ; i < driDispatchRemapTable_size ; i++ ) {
 
233
         driDispatchRemapTable[i] = -1;
 
234
      }
 
235
 
 
236
      first_time = 0;
 
237
      driInitExtensions( ctx, all_mesa_extensions, GL_FALSE );
 
238
   }
 
239
 
 
240
   if ( (ctx != NULL) && enable_imaging ) {
 
241
      _mesa_enable_imaging_extensions( ctx );
 
242
   }
 
243
 
 
244
   for ( i = 0 ; extensions_to_enable[i].name != NULL ; i++ ) {
 
245
       driInitSingleExtension( ctx, & extensions_to_enable[i] );
 
246
   }
 
247
}
 
248
 
 
249
 
 
250
 
 
251
 
 
252
/**
 
253
 * Enable and add dispatch functions for a single extension
 
254
 * 
 
255
 * \param ctx  Context where extension is to be enabled.
 
256
 * \param ext  Extension that is to be enabled.
 
257
 * 
 
258
 * \sa driInitExtensions, _mesa_enable_extension, _glapi_add_entrypoint
 
259
 *
 
260
 * \todo
 
261
 * Determine if it would be better to use \c strlen instead of the hardcoded
 
262
 * for-loops.
 
263
 */
 
264
void driInitSingleExtension( GLcontext * ctx,
 
265
                             const struct dri_extension * ext )
 
266
{
 
267
    unsigned i;
 
268
 
 
269
 
 
270
    if ( ext->functions != NULL ) {
 
271
        for ( i = 0 ; ext->functions[i].strings != NULL ; i++ ) {
 
272
            const char * functions[16];
 
273
            const char * parameter_signature;
 
274
            const char * str = ext->functions[i].strings;
 
275
            unsigned j;
 
276
            unsigned offset;
 
277
 
 
278
 
 
279
            /* Separate the parameter signature from the rest of the string.
 
280
             * If the parameter signature is empty (i.e., the string starts
 
281
             * with a NUL character), then the function has a void parameter
 
282
             * list.
 
283
             */
 
284
            parameter_signature = str;
 
285
            while ( str[0] != '\0' ) {
 
286
                str++;
 
287
            }
 
288
            str++;
 
289
 
 
290
 
 
291
            /* Divide the string into the substrings that name each
 
292
             * entry-point for the function.
 
293
             */
 
294
            for ( j = 0 ; j < 16 ; j++ ) {
 
295
                if ( str[0] == '\0' ) {
 
296
                    functions[j] = NULL;
 
297
                    break;
 
298
                }
 
299
 
 
300
                functions[j] = str;
 
301
 
 
302
                while ( str[0] != '\0' ) {
 
303
                    str++;
 
304
                }
 
305
                str++;
 
306
            }
 
307
 
 
308
 
 
309
            /* Add each entry-point to the dispatch table.
 
310
             */
 
311
            offset = _glapi_add_dispatch( functions, parameter_signature );
 
312
            if (offset == -1) {
 
313
                fprintf(stderr, "DISPATCH ERROR! _glapi_add_dispatch failed "
 
314
                        "to add %s!\n", functions[0]);
 
315
            }
 
316
            else if (ext->functions[i].remap_index != -1) {
 
317
                driDispatchRemapTable[ ext->functions[i].remap_index ] = 
 
318
                  offset;
 
319
            }
 
320
            else if (ext->functions[i].offset != offset) {
 
321
                fprintf(stderr, "DISPATCH ERROR! %s -> %u != %u\n",
 
322
                        functions[0], offset, ext->functions[i].offset);
 
323
            }
 
324
        }
 
325
    }
 
326
 
 
327
    if ( ctx != NULL ) {
 
328
        _mesa_enable_extension( ctx, ext->name );
 
329
    }
 
330
}
 
331
 
 
332
 
 
333
/**
 
334
 * Utility function used by drivers to test the verions of other components.
 
335
 *
 
336
 * If one of the version requirements is not met, a message is logged using
 
337
 * \c __driUtilMessage.
 
338
 *
 
339
 * \param driver_name  Name of the driver.  Used in error messages.
 
340
 * \param driActual    Actual DRI version supplied __driCreateNewScreen.
 
341
 * \param driExpected  Minimum DRI version required by the driver.
 
342
 * \param ddxActual    Actual DDX version supplied __driCreateNewScreen.
 
343
 * \param ddxExpected  Minimum DDX minor and range of DDX major version required by the driver.
 
344
 * \param drmActual    Actual DRM version supplied __driCreateNewScreen.
 
345
 * \param drmExpected  Minimum DRM version required by the driver.
 
346
 * 
 
347
 * \returns \c GL_TRUE if all version requirements are met.  Otherwise,
 
348
 *          \c GL_FALSE is returned.
 
349
 * 
 
350
 * \sa __driCreateNewScreen, driCheckDriDdxDrmVersions2, __driUtilMessage
 
351
 *
 
352
 * \todo
 
353
 * Now that the old \c driCheckDriDdxDrmVersions function is gone, this
 
354
 * function and \c driCheckDriDdxDrmVersions2 should be renamed.
 
355
 */
 
356
GLboolean
 
357
driCheckDriDdxDrmVersions3(const char * driver_name,
 
358
                           const __DRIversion * driActual,
 
359
                           const __DRIversion * driExpected,
 
360
                           const __DRIversion * ddxActual,
 
361
                           const __DRIutilversion2 * ddxExpected,
 
362
                           const __DRIversion * drmActual,
 
363
                           const __DRIversion * drmExpected)
 
364
{
 
365
   static const char format[] = "%s DRI driver expected %s version %d.%d.x "
 
366
       "but got version %d.%d.%d\n";
 
367
   static const char format2[] = "%s DRI driver expected %s version %d-%d.%d.x "
 
368
       "but got version %d.%d.%d\n";
 
369
 
 
370
 
 
371
   /* Check the DRI version */
 
372
   if ( (driActual->major != driExpected->major)
 
373
        || (driActual->minor < driExpected->minor) ) {
 
374
      fprintf(stderr, format, driver_name, "DRI",
 
375
                       driExpected->major, driExpected->minor,
 
376
                       driActual->major, driActual->minor, driActual->patch);
 
377
      return GL_FALSE;
 
378
   }
 
379
 
 
380
   /* Check that the DDX driver version is compatible */
 
381
   /* for miniglx we pass in -1 so we can ignore the DDX version */
 
382
   if ( (ddxActual->major != -1) && ((ddxActual->major < ddxExpected->major_min)
 
383
        || (ddxActual->major > ddxExpected->major_max)
 
384
        || (ddxActual->minor < ddxExpected->minor)) ) {
 
385
      fprintf(stderr, format2, driver_name, "DDX",
 
386
                       ddxExpected->major_min, ddxExpected->major_max, ddxExpected->minor,
 
387
                       ddxActual->major, ddxActual->minor, ddxActual->patch);
 
388
      return GL_FALSE;
 
389
   }
 
390
   
 
391
   /* Check that the DRM driver version is compatible */
 
392
   if ( (drmActual->major != drmExpected->major)
 
393
        || (drmActual->minor < drmExpected->minor) ) {
 
394
      fprintf(stderr, format, driver_name, "DRM",
 
395
                       drmExpected->major, drmExpected->minor,
 
396
                       drmActual->major, drmActual->minor, drmActual->patch);
 
397
      return GL_FALSE;
 
398
   }
 
399
 
 
400
   return GL_TRUE;
 
401
}
 
402
 
 
403
GLboolean
 
404
driCheckDriDdxDrmVersions2(const char * driver_name,
 
405
                           const __DRIversion * driActual,
 
406
                           const __DRIversion * driExpected,
 
407
                           const __DRIversion * ddxActual,
 
408
                           const __DRIversion * ddxExpected,
 
409
                           const __DRIversion * drmActual,
 
410
                           const __DRIversion * drmExpected)
 
411
{
 
412
   __DRIutilversion2 ddx_expected;
 
413
   ddx_expected.major_min = ddxExpected->major;
 
414
   ddx_expected.major_max = ddxExpected->major;
 
415
   ddx_expected.minor = ddxExpected->minor;
 
416
   ddx_expected.patch = ddxExpected->patch;
 
417
   return driCheckDriDdxDrmVersions3(driver_name, driActual,
 
418
                                driExpected, ddxActual, & ddx_expected,
 
419
                                drmActual, drmExpected);
 
420
}
 
421
 
 
422
 
 
423
 
 
424
GLint
 
425
driIntersectArea( drm_clip_rect_t rect1, drm_clip_rect_t rect2 )
 
426
{
 
427
   if (rect2.x1 > rect1.x1) rect1.x1 = rect2.x1;
 
428
   if (rect2.x2 < rect1.x2) rect1.x2 = rect2.x2;
 
429
   if (rect2.y1 > rect1.y1) rect1.y1 = rect2.y1;
 
430
   if (rect2.y2 < rect1.y2) rect1.y2 = rect2.y2;
 
431
 
 
432
   if (rect1.x1 > rect1.x2 || rect1.y1 > rect1.y2) return 0;
 
433
 
 
434
   return (rect1.x2 - rect1.x1) * (rect1.y2 - rect1.y1);
 
435
}
 
436
 
 
437
GLboolean driClipRectToFramebuffer( const GLframebuffer *buffer,
 
438
                                    GLint *x, GLint *y,
 
439
                                    GLsizei *width, GLsizei *height )
 
440
{
 
441
   /* left clipping */
 
442
   if (*x < buffer->_Xmin) {
 
443
      *width -= (buffer->_Xmin - *x);
 
444
      *x = buffer->_Xmin;
 
445
   }
 
446
 
 
447
   /* right clipping */
 
448
   if (*x + *width > buffer->_Xmax)
 
449
      *width -= (*x + *width - buffer->_Xmax - 1);
 
450
 
 
451
   if (*width <= 0)
 
452
      return GL_FALSE;
 
453
 
 
454
   /* bottom clipping */
 
455
   if (*y < buffer->_Ymin) {
 
456
      *height -= (buffer->_Ymin - *y);
 
457
      *y = buffer->_Ymin;
 
458
   }
 
459
 
 
460
   /* top clipping */
 
461
   if (*y + *height > buffer->_Ymax)
 
462
      *height -= (*y + *height - buffer->_Ymax - 1);
 
463
 
 
464
   if (*height <= 0)
 
465
      return GL_FALSE;
 
466
 
 
467
   return GL_TRUE;
 
468
}
 
469
 
 
470
 
 
471
 
 
472
/**
 
473
 * Creates a set of \c __GLcontextModes that a driver will expose.
 
474
 * 
 
475
 * A set of \c __GLcontextModes will be created based on the supplied
 
476
 * parameters.  The number of modes processed will be 2 *
 
477
 * \c num_depth_stencil_bits * \c num_db_modes.
 
478
 * 
 
479
 * For the most part, data is just copied from \c depth_bits, \c stencil_bits,
 
480
 * \c db_modes, and \c visType into each \c __GLcontextModes element.
 
481
 * However, the meanings of \c fb_format and \c fb_type require further
 
482
 * explanation.  The \c fb_format specifies which color components are in
 
483
 * each pixel and what the default order is.  For example, \c GL_RGB specifies
 
484
 * that red, green, blue are available and red is in the "most significant"
 
485
 * position and blue is in the "least significant".  The \c fb_type specifies
 
486
 * the bit sizes of each component and the actual ordering.  For example, if
 
487
 * \c GL_UNSIGNED_SHORT_5_6_5_REV is specified with \c GL_RGB, bits [15:11]
 
488
 * are the blue value, bits [10:5] are the green value, and bits [4:0] are
 
489
 * the red value.
 
490
 * 
 
491
 * One sublte issue is the combination of \c GL_RGB  or \c GL_BGR and either
 
492
 * of the \c GL_UNSIGNED_INT_8_8_8_8 modes.  The resulting mask values in the
 
493
 * \c __GLcontextModes structure is \b identical to the \c GL_RGBA or
 
494
 * \c GL_BGRA case, except the \c alphaMask is zero.  This means that, as
 
495
 * far as this routine is concerned, \c GL_RGB with \c GL_UNSIGNED_INT_8_8_8_8
 
496
 * still uses 32-bits.
 
497
 *
 
498
 * If in doubt, look at the tables used in the function.
 
499
 * 
 
500
 * \param ptr_to_modes  Pointer to a pointer to a linked list of
 
501
 *                      \c __GLcontextModes.  Upon completion, a pointer to
 
502
 *                      the next element to be process will be stored here.
 
503
 *                      If the function fails and returns \c GL_FALSE, this
 
504
 *                      value will be unmodified, but some elements in the
 
505
 *                      linked list may be modified.
 
506
 * \param fb_format     Format of the framebuffer.  Currently only \c GL_RGB,
 
507
 *                      \c GL_RGBA, \c GL_BGR, and \c GL_BGRA are supported.
 
508
 * \param fb_type       Type of the pixels in the framebuffer.  Currently only
 
509
 *                      \c GL_UNSIGNED_SHORT_5_6_5, 
 
510
 *                      \c GL_UNSIGNED_SHORT_5_6_5_REV,
 
511
 *                      \c GL_UNSIGNED_INT_8_8_8_8, and
 
512
 *                      \c GL_UNSIGNED_INT_8_8_8_8_REV are supported.
 
513
 * \param depth_bits    Array of depth buffer sizes to be exposed.
 
514
 * \param stencil_bits  Array of stencil buffer sizes to be exposed.
 
515
 * \param num_depth_stencil_bits  Number of entries in both \c depth_bits and
 
516
 *                      \c stencil_bits.
 
517
 * \param db_modes      Array of buffer swap modes.  If an element has a
 
518
 *                      value of \c GLX_NONE, then it represents a
 
519
 *                      single-buffered mode.  Other valid values are
 
520
 *                      \c GLX_SWAP_EXCHANGE_OML, \c GLX_SWAP_COPY_OML, and
 
521
 *                      \c GLX_SWAP_UNDEFINED_OML.  See the
 
522
 *                      GLX_OML_swap_method extension spec for more details.
 
523
 * \param num_db_modes  Number of entries in \c db_modes.
 
524
 * \param visType       GLX visual type.  Usually either \c GLX_TRUE_COLOR or
 
525
 *                      \c GLX_DIRECT_COLOR.
 
526
 * 
 
527
 * \returns
 
528
 * \c GL_TRUE on success or \c GL_FALSE on failure.  Currently the only
 
529
 * cause of failure is a bad parameter (i.e., unsupported \c fb_format or
 
530
 * \c fb_type).
 
531
 * 
 
532
 * \todo
 
533
 * There is currently no way to support packed RGB modes (i.e., modes with
 
534
 * exactly 3 bytes per pixel) or floating-point modes.  This could probably
 
535
 * be done by creating some new, private enums with clever names likes
 
536
 * \c GL_UNSIGNED_3BYTE_8_8_8, \c GL_4FLOAT_32_32_32_32, 
 
537
 * \c GL_4HALF_16_16_16_16, etc.  We can cross that bridge when we come to it.
 
538
 */
 
539
GLboolean
 
540
driFillInModes( __GLcontextModes ** ptr_to_modes,
 
541
                GLenum fb_format, GLenum fb_type,
 
542
                const u_int8_t * depth_bits, const u_int8_t * stencil_bits,
 
543
                unsigned num_depth_stencil_bits,
 
544
                const GLenum * db_modes, unsigned num_db_modes,
 
545
                int visType )
 
546
{
 
547
   static const u_int8_t bits_table[3][4] = {
 
548
     /* R  G  B  A */
 
549
      { 5, 6, 5, 0 }, /* Any GL_UNSIGNED_SHORT_5_6_5 */
 
550
      { 8, 8, 8, 0 }, /* Any RGB with any GL_UNSIGNED_INT_8_8_8_8 */
 
551
      { 8, 8, 8, 8 }  /* Any RGBA with any GL_UNSIGNED_INT_8_8_8_8 */
 
552
   };
 
553
 
 
554
   /* The following arrays are all indexed by the fb_type masked with 0x07.
 
555
    * Given the four supported fb_type values, this results in valid array
 
556
    * indices of 3, 4, 5, and 7.
 
557
    */
 
558
   static const u_int32_t masks_table_rgb[8][4] = {
 
559
      { 0x00000000, 0x00000000, 0x00000000, 0x00000000 },
 
560
      { 0x00000000, 0x00000000, 0x00000000, 0x00000000 },
 
561
      { 0x00000000, 0x00000000, 0x00000000, 0x00000000 },
 
562
      { 0x0000F800, 0x000007E0, 0x0000001F, 0x00000000 }, /* 5_6_5       */
 
563
      { 0x0000001F, 0x000007E0, 0x0000F800, 0x00000000 }, /* 5_6_5_REV   */
 
564
      { 0xFF000000, 0x00FF0000, 0x0000FF00, 0x00000000 }, /* 8_8_8_8     */
 
565
      { 0x00000000, 0x00000000, 0x00000000, 0x00000000 },
 
566
      { 0x000000FF, 0x0000FF00, 0x00FF0000, 0x00000000 }  /* 8_8_8_8_REV */
 
567
   };
 
568
 
 
569
   static const u_int32_t masks_table_rgba[8][4] = {
 
570
      { 0x00000000, 0x00000000, 0x00000000, 0x00000000 },
 
571
      { 0x00000000, 0x00000000, 0x00000000, 0x00000000 },
 
572
      { 0x00000000, 0x00000000, 0x00000000, 0x00000000 },
 
573
      { 0x0000F800, 0x000007E0, 0x0000001F, 0x00000000 }, /* 5_6_5       */
 
574
      { 0x0000001F, 0x000007E0, 0x0000F800, 0x00000000 }, /* 5_6_5_REV   */
 
575
      { 0xFF000000, 0x00FF0000, 0x0000FF00, 0x000000FF }, /* 8_8_8_8     */
 
576
      { 0x00000000, 0x00000000, 0x00000000, 0x00000000 },
 
577
      { 0x000000FF, 0x0000FF00, 0x00FF0000, 0xFF000000 }, /* 8_8_8_8_REV */
 
578
   };
 
579
 
 
580
   static const u_int32_t masks_table_bgr[8][4] = {
 
581
      { 0x00000000, 0x00000000, 0x00000000, 0x00000000 },
 
582
      { 0x00000000, 0x00000000, 0x00000000, 0x00000000 },
 
583
      { 0x00000000, 0x00000000, 0x00000000, 0x00000000 },
 
584
      { 0x0000001F, 0x000007E0, 0x0000F800, 0x00000000 }, /* 5_6_5       */
 
585
      { 0x0000F800, 0x000007E0, 0x0000001F, 0x00000000 }, /* 5_6_5_REV   */
 
586
      { 0x0000FF00, 0x00FF0000, 0xFF000000, 0x00000000 }, /* 8_8_8_8     */
 
587
      { 0x00000000, 0x00000000, 0x00000000, 0x00000000 },
 
588
      { 0x00FF0000, 0x0000FF00, 0x000000FF, 0x00000000 }, /* 8_8_8_8_REV */
 
589
   };
 
590
 
 
591
   static const u_int32_t masks_table_bgra[8][4] = {
 
592
      { 0x00000000, 0x00000000, 0x00000000, 0x00000000 },
 
593
      { 0x00000000, 0x00000000, 0x00000000, 0x00000000 },
 
594
      { 0x00000000, 0x00000000, 0x00000000, 0x00000000 },
 
595
      { 0x0000001F, 0x000007E0, 0x0000F800, 0x00000000 }, /* 5_6_5       */
 
596
      { 0x0000F800, 0x000007E0, 0x0000001F, 0x00000000 }, /* 5_6_5_REV   */
 
597
      { 0x0000FF00, 0x00FF0000, 0xFF000000, 0x000000FF }, /* 8_8_8_8     */
 
598
      { 0x00000000, 0x00000000, 0x00000000, 0x00000000 },
 
599
      { 0x00FF0000, 0x0000FF00, 0x000000FF, 0xFF000000 }, /* 8_8_8_8_REV */
 
600
   };
 
601
 
 
602
   static const u_int8_t bytes_per_pixel[8] = {
 
603
      0, 0, 0, 2, 2, 4, 0, 4
 
604
   };
 
605
 
 
606
   const u_int8_t  * bits;
 
607
   const u_int32_t * masks;
 
608
   const int index = fb_type & 0x07;
 
609
   __GLcontextModes * modes = *ptr_to_modes;
 
610
   unsigned i;
 
611
   unsigned j;
 
612
   unsigned k;
 
613
 
 
614
 
 
615
   if ( bytes_per_pixel[ index ] == 0 ) {
 
616
      fprintf( stderr, "[%s:%u] Framebuffer type 0x%04x has 0 bytes per pixel.\n",
 
617
               __FUNCTION__, __LINE__, fb_type );
 
618
      return GL_FALSE;
 
619
   }
 
620
 
 
621
 
 
622
   /* Valid types are GL_UNSIGNED_SHORT_5_6_5 and GL_UNSIGNED_INT_8_8_8_8 and
 
623
    * the _REV versions.
 
624
    *
 
625
    * Valid formats are GL_RGBA, GL_RGB, and GL_BGRA.
 
626
    */
 
627
 
 
628
   switch ( fb_format ) {
 
629
      case GL_RGB:
 
630
         bits = (bytes_per_pixel[ index ] == 2)
 
631
             ? bits_table[0] : bits_table[1];
 
632
         masks = masks_table_rgb[ index ];
 
633
         break;
 
634
 
 
635
      case GL_RGBA:
 
636
         bits = (bytes_per_pixel[ index ] == 2)
 
637
             ? bits_table[0] : bits_table[2];
 
638
         masks = masks_table_rgba[ index ];
 
639
         break;
 
640
 
 
641
      case GL_BGR:
 
642
         bits = (bytes_per_pixel[ index ] == 2)
 
643
             ? bits_table[0] : bits_table[1];
 
644
         masks = masks_table_bgr[ index ];
 
645
         break;
 
646
 
 
647
      case GL_BGRA:
 
648
         bits = (bytes_per_pixel[ index ] == 2)
 
649
             ? bits_table[0] : bits_table[2];
 
650
         masks = masks_table_bgra[ index ];
 
651
         break;
 
652
 
 
653
      default:
 
654
         fprintf( stderr, "[%s:%u] Framebuffer format 0x%04x is not GL_RGB, GL_RGBA, GL_BGR, or GL_BGRA.\n",
 
655
               __FUNCTION__, __LINE__, fb_format );
 
656
         return GL_FALSE;
 
657
   }
 
658
 
 
659
 
 
660
    for ( k = 0 ; k < num_depth_stencil_bits ; k++ ) {
 
661
        for ( i = 0 ; i < num_db_modes ; i++ ) {
 
662
            for ( j = 0 ; j < 2 ; j++ ) {
 
663
 
 
664
                modes->redBits   = bits[0];
 
665
                modes->greenBits = bits[1];
 
666
                modes->blueBits  = bits[2];
 
667
                modes->alphaBits = bits[3];
 
668
                modes->redMask   = masks[0];
 
669
                modes->greenMask = masks[1];
 
670
                modes->blueMask  = masks[2];
 
671
                modes->alphaMask = masks[3];
 
672
                modes->rgbBits   = modes->redBits + modes->greenBits
 
673
                    + modes->blueBits + modes->alphaBits;
 
674
 
 
675
                modes->accumRedBits   = 16 * j;
 
676
                modes->accumGreenBits = 16 * j;
 
677
                modes->accumBlueBits  = 16 * j;
 
678
                modes->accumAlphaBits = (masks[3] != 0) ? 16 * j : 0;
 
679
                modes->visualRating = (j == 0) ? GLX_NONE : GLX_SLOW_CONFIG;
 
680
 
 
681
                modes->stencilBits = stencil_bits[k];
 
682
                modes->depthBits = depth_bits[k];
 
683
 
 
684
                modes->visualType = visType;
 
685
                modes->renderType = GLX_RGBA_BIT;
 
686
                modes->drawableType = GLX_WINDOW_BIT;
 
687
                modes->rgbMode = GL_TRUE;
 
688
 
 
689
                if ( db_modes[i] == GLX_NONE ) {
 
690
                    modes->doubleBufferMode = GL_FALSE;
 
691
                }
 
692
                else {
 
693
                    modes->doubleBufferMode = GL_TRUE;
 
694
                    modes->swapMethod = db_modes[i];
 
695
                }
 
696
 
 
697
                modes->haveAccumBuffer = ((modes->accumRedBits +
 
698
                                           modes->accumGreenBits +
 
699
                                           modes->accumBlueBits +
 
700
                                           modes->accumAlphaBits) > 0);
 
701
                modes->haveDepthBuffer = (modes->depthBits > 0);
 
702
                modes->haveStencilBuffer = (modes->stencilBits > 0);
 
703
 
 
704
                modes = modes->next;
 
705
            }
 
706
        }
 
707
    }
 
708
 
 
709
    *ptr_to_modes = modes;
 
710
    return GL_TRUE;
 
711
}