Subversion Repositories Kolibri OS

Rev

Details | Last modification | View Log | RSS feed

Rev Author Line No. Line
5563 serge 1
/**************************************************************************
2
 *
3
 * Copyright 2008 Tungsten Graphics, Inc., Cedar Park, Texas.
4
 * Copyright 2009-2010 Chia-I Wu 
5
 * Copyright 2010-2011 LunarG, Inc.
6
 * All Rights Reserved.
7
 *
8
 * Permission is hereby granted, free of charge, to any person obtaining a
9
 * copy of this software and associated documentation files (the
10
 * "Software"), to deal in the Software without restriction, including
11
 * without limitation the rights to use, copy, modify, merge, publish,
12
 * distribute, sub license, and/or sell copies of the Software, and to
13
 * permit persons to whom the Software is furnished to do so, subject to
14
 * the following conditions:
15
 *
16
 * The above copyright notice and this permission notice (including the
17
 * next paragraph) shall be included in all copies or substantial portions
18
 * of the Software.
19
 *
20
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
21
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
22
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
23
 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
24
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
25
 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
26
 * DEALINGS IN THE SOFTWARE.
27
 *
28
 **************************************************************************/
29
 
30
 
31
/**
32
 * EGL Configuration (pixel format) functions.
33
 */
34
 
35
 
36
#include 
37
#include 
38
#include 
39
#include "eglconfig.h"
40
#include "egldisplay.h"
41
#include "eglcurrent.h"
42
#include "egllog.h"
43
 
44
 
45
#define MIN2(A, B)  (((A) < (B)) ? (A) : (B))
46
 
47
 
48
/**
49
 * Init the given _EGLconfig to default values.
50
 * \param id  the configuration's ID.
51
 *
52
 * Note that id must be positive for the config to be valid.
53
 * It is also recommended that when there are N configs, their
54
 * IDs are from 1 to N respectively.
55
 */
56
void
57
_eglInitConfig(_EGLConfig *conf, _EGLDisplay *dpy, EGLint id)
58
{
59
   memset(conf, 0, sizeof(*conf));
60
 
61
   conf->Display = dpy;
62
 
63
   /* some attributes take non-zero default values */
64
   conf->ConfigID = id;
65
   conf->ConfigCaveat = EGL_NONE;
66
   conf->TransparentType = EGL_NONE;
67
   conf->NativeVisualType = EGL_NONE;
68
   conf->ColorBufferType = EGL_RGB_BUFFER;
69
}
70
 
71
 
72
/**
73
 * Link a config to its display and return the handle of the link.
74
 * The handle can be passed to client directly.
75
 *
76
 * Note that we just save the ptr to the config (we don't copy the config).
77
 */
78
PUBLIC EGLConfig
79
_eglLinkConfig(_EGLConfig *conf)
80
{
81
   _EGLDisplay *dpy = conf->Display;
82
 
83
   /* sanity check */
84
   assert(dpy && conf->ConfigID > 0);
85
 
86
   if (!dpy->Configs) {
87
      dpy->Configs = _eglCreateArray("Config", 16);
88
      if (!dpy->Configs)
89
         return (EGLConfig) NULL;
90
   }
91
 
92
   _eglAppendArray(dpy->Configs, (void *) conf);
93
 
94
   return (EGLConfig) conf;
95
}
96
 
97
 
98
/**
99
 * Lookup a handle to find the linked config.
100
 * Return NULL if the handle has no corresponding linked config.
101
 */
102
_EGLConfig *
103
_eglLookupConfig(EGLConfig config, _EGLDisplay *dpy)
104
{
105
   _EGLConfig *conf;
106
 
107
   if (!dpy)
108
      return NULL;
109
 
110
   conf = (_EGLConfig *) _eglFindArray(dpy->Configs, (void *) config);
111
   if (conf)
112
      assert(conf->Display == dpy);
113
 
114
   return conf;
115
}
116
 
117
 
118
enum {
119
   /* types */
120
   ATTRIB_TYPE_INTEGER,
121
   ATTRIB_TYPE_BOOLEAN,
122
   ATTRIB_TYPE_BITMASK,
123
   ATTRIB_TYPE_ENUM,
124
   ATTRIB_TYPE_PSEUDO, /* non-queryable */
125
   ATTRIB_TYPE_PLATFORM, /* platform-dependent */
126
   /* criteria */
127
   ATTRIB_CRITERION_EXACT,
128
   ATTRIB_CRITERION_ATLEAST,
129
   ATTRIB_CRITERION_MASK,
130
   ATTRIB_CRITERION_SPECIAL,
131
   ATTRIB_CRITERION_IGNORE
132
};
133
 
134
 
135
/* EGL spec Table 3.1 and 3.4 */
136
static const struct {
137
   EGLint attr;
138
   EGLint type;
139
   EGLint criterion;
140
   EGLint default_value;
141
} _eglValidationTable[] =
142
{
143
   /* core */
144
   { EGL_BUFFER_SIZE,               ATTRIB_TYPE_INTEGER,
145
                                    ATTRIB_CRITERION_ATLEAST,
146
 
147
   { EGL_RED_SIZE,                  ATTRIB_TYPE_INTEGER,
148
                                    ATTRIB_CRITERION_ATLEAST,
149
 
150
   { EGL_GREEN_SIZE,                ATTRIB_TYPE_INTEGER,
151
                                    ATTRIB_CRITERION_ATLEAST,
152
 
153
   { EGL_BLUE_SIZE,                 ATTRIB_TYPE_INTEGER,
154
                                    ATTRIB_CRITERION_ATLEAST,
155
 
156
   { EGL_LUMINANCE_SIZE,            ATTRIB_TYPE_INTEGER,
157
                                    ATTRIB_CRITERION_ATLEAST,
158
 
159
   { EGL_ALPHA_SIZE,                ATTRIB_TYPE_INTEGER,
160
                                    ATTRIB_CRITERION_ATLEAST,
161
 
162
   { EGL_ALPHA_MASK_SIZE,           ATTRIB_TYPE_INTEGER,
163
                                    ATTRIB_CRITERION_ATLEAST,
164
 
165
   { EGL_BIND_TO_TEXTURE_RGB,       ATTRIB_TYPE_BOOLEAN,
166
                                    ATTRIB_CRITERION_EXACT,
167
                                    EGL_DONT_CARE },
168
   { EGL_BIND_TO_TEXTURE_RGBA,      ATTRIB_TYPE_BOOLEAN,
169
                                    ATTRIB_CRITERION_EXACT,
170
                                    EGL_DONT_CARE },
171
   { EGL_COLOR_BUFFER_TYPE,         ATTRIB_TYPE_ENUM,
172
                                    ATTRIB_CRITERION_EXACT,
173
                                    EGL_RGB_BUFFER },
174
   { EGL_CONFIG_CAVEAT,             ATTRIB_TYPE_ENUM,
175
                                    ATTRIB_CRITERION_EXACT,
176
                                    EGL_DONT_CARE },
177
   { EGL_CONFIG_ID,                 ATTRIB_TYPE_INTEGER,
178
                                    ATTRIB_CRITERION_EXACT,
179
                                    EGL_DONT_CARE },
180
   { EGL_CONFORMANT,                ATTRIB_TYPE_BITMASK,
181
                                    ATTRIB_CRITERION_MASK,
182
 
183
   { EGL_DEPTH_SIZE,                ATTRIB_TYPE_INTEGER,
184
                                    ATTRIB_CRITERION_ATLEAST,
185
 
186
   { EGL_LEVEL,                     ATTRIB_TYPE_PLATFORM,
187
                                    ATTRIB_CRITERION_EXACT,
188
 
189
   { EGL_MAX_PBUFFER_WIDTH,         ATTRIB_TYPE_INTEGER,
190
                                    ATTRIB_CRITERION_IGNORE,
191
 
192
   { EGL_MAX_PBUFFER_HEIGHT,        ATTRIB_TYPE_INTEGER,
193
                                    ATTRIB_CRITERION_IGNORE,
194
 
195
   { EGL_MAX_PBUFFER_PIXELS,        ATTRIB_TYPE_INTEGER,
196
                                    ATTRIB_CRITERION_IGNORE,
197
 
198
   { EGL_MAX_SWAP_INTERVAL,         ATTRIB_TYPE_INTEGER,
199
                                    ATTRIB_CRITERION_EXACT,
200
                                    EGL_DONT_CARE },
201
   { EGL_MIN_SWAP_INTERVAL,         ATTRIB_TYPE_INTEGER,
202
                                    ATTRIB_CRITERION_EXACT,
203
                                    EGL_DONT_CARE },
204
   { EGL_NATIVE_RENDERABLE,         ATTRIB_TYPE_BOOLEAN,
205
                                    ATTRIB_CRITERION_EXACT,
206
                                    EGL_DONT_CARE },
207
   { EGL_NATIVE_VISUAL_ID,          ATTRIB_TYPE_PLATFORM,
208
                                    ATTRIB_CRITERION_IGNORE,
209
 
210
   { EGL_NATIVE_VISUAL_TYPE,        ATTRIB_TYPE_PLATFORM,
211
                                    ATTRIB_CRITERION_EXACT,
212
                                    EGL_DONT_CARE },
213
   { EGL_RENDERABLE_TYPE,           ATTRIB_TYPE_BITMASK,
214
                                    ATTRIB_CRITERION_MASK,
215
                                    EGL_OPENGL_ES_BIT },
216
   { EGL_SAMPLE_BUFFERS,            ATTRIB_TYPE_INTEGER,
217
                                    ATTRIB_CRITERION_ATLEAST,
218
 
219
   { EGL_SAMPLES,                   ATTRIB_TYPE_INTEGER,
220
                                    ATTRIB_CRITERION_ATLEAST,
221
 
222
   { EGL_STENCIL_SIZE,              ATTRIB_TYPE_INTEGER,
223
                                    ATTRIB_CRITERION_ATLEAST,
224
 
225
   { EGL_SURFACE_TYPE,              ATTRIB_TYPE_BITMASK,
226
                                    ATTRIB_CRITERION_MASK,
227
                                    EGL_WINDOW_BIT },
228
   { EGL_TRANSPARENT_TYPE,          ATTRIB_TYPE_ENUM,
229
                                    ATTRIB_CRITERION_EXACT,
230
                                    EGL_NONE },
231
   { EGL_TRANSPARENT_RED_VALUE,     ATTRIB_TYPE_INTEGER,
232
                                    ATTRIB_CRITERION_EXACT,
233
                                    EGL_DONT_CARE },
234
   { EGL_TRANSPARENT_GREEN_VALUE,   ATTRIB_TYPE_INTEGER,
235
                                    ATTRIB_CRITERION_EXACT,
236
                                    EGL_DONT_CARE },
237
   { EGL_TRANSPARENT_BLUE_VALUE,    ATTRIB_TYPE_INTEGER,
238
                                    ATTRIB_CRITERION_EXACT,
239
                                    EGL_DONT_CARE },
240
   { EGL_MATCH_NATIVE_PIXMAP,       ATTRIB_TYPE_PSEUDO,
241
                                    ATTRIB_CRITERION_SPECIAL,
242
                                    EGL_NONE },
243
   /* extensions */
244
   { EGL_Y_INVERTED_NOK,            ATTRIB_TYPE_BOOLEAN,
245
                                    ATTRIB_CRITERION_EXACT,
246
                                    EGL_DONT_CARE }
247
};
248
 
249
 
250
/**
251
 * Return true if a config is valid.  When for_matching is true,
252
 * EGL_DONT_CARE is accepted as a valid attribute value, and checks
253
 * for conflicting attribute values are skipped.
254
 *
255
 * Note that some attributes are platform-dependent and are not
256
 * checked.
257
 */
258
EGLBoolean
259
_eglValidateConfig(const _EGLConfig *conf, EGLBoolean for_matching)
260
{
261
   EGLint i, attr, val;
262
   EGLBoolean valid = EGL_TRUE;
263
 
264
   /* check attributes by their types */
265
   for (i = 0; i < ARRAY_SIZE(_eglValidationTable); i++) {
266
      EGLint mask;
267
 
268
      attr = _eglValidationTable[i].attr;
269
      val = _eglGetConfigKey(conf, attr);
270
 
271
      switch (_eglValidationTable[i].type) {
272
      case ATTRIB_TYPE_INTEGER:
273
         switch (attr) {
274
         case EGL_CONFIG_ID:
275
            /* config id must be positive */
276
            if (val <= 0)
277
               valid = EGL_FALSE;
278
            break;
279
         case EGL_SAMPLE_BUFFERS:
280
            /* there can be at most 1 sample buffer */
281
            if (val > 1 || val < 0)
282
               valid = EGL_FALSE;
283
            break;
284
         default:
285
            if (val < 0)
286
               valid = EGL_FALSE;
287
            break;
288
         }
289
         break;
290
      case ATTRIB_TYPE_BOOLEAN:
291
         if (val != EGL_TRUE && val != EGL_FALSE)
292
            valid = EGL_FALSE;
293
         break;
294
      case ATTRIB_TYPE_ENUM:
295
         switch (attr) {
296
         case EGL_CONFIG_CAVEAT:
297
            if (val != EGL_NONE && val != EGL_SLOW_CONFIG &&
298
                val != EGL_NON_CONFORMANT_CONFIG)
299
               valid = EGL_FALSE;
300
            break;
301
         case EGL_TRANSPARENT_TYPE:
302
            if (val != EGL_NONE && val != EGL_TRANSPARENT_RGB)
303
               valid = EGL_FALSE;
304
            break;
305
         case EGL_COLOR_BUFFER_TYPE:
306
            if (val != EGL_RGB_BUFFER && val != EGL_LUMINANCE_BUFFER)
307
               valid = EGL_FALSE;
308
            break;
309
         default:
310
            assert(0);
311
            break;
312
         }
313
         break;
314
      case ATTRIB_TYPE_BITMASK:
315
         switch (attr) {
316
         case EGL_SURFACE_TYPE:
317
            mask = EGL_PBUFFER_BIT |
318
                   EGL_PIXMAP_BIT |
319
                   EGL_WINDOW_BIT |
320
                   EGL_VG_COLORSPACE_LINEAR_BIT |
321
                   EGL_VG_ALPHA_FORMAT_PRE_BIT |
322
                   EGL_MULTISAMPLE_RESOLVE_BOX_BIT |
323
                   EGL_SWAP_BEHAVIOR_PRESERVED_BIT;
324
#ifdef EGL_MESA_screen_surface
325
            if (conf->Display->Extensions.MESA_screen_surface)
326
               mask |= EGL_SCREEN_BIT_MESA;
327
#endif
328
            break;
329
         case EGL_RENDERABLE_TYPE:
330
         case EGL_CONFORMANT:
331
            mask = EGL_OPENGL_ES_BIT |
332
                   EGL_OPENVG_BIT |
333
                   EGL_OPENGL_ES2_BIT |
334
                   EGL_OPENGL_ES3_BIT_KHR |
335
                   EGL_OPENGL_BIT;
336
            break;
337
         default:
338
            assert(0);
339
            mask = 0;
340
            break;
341
         }
342
         if (val & ~mask)
343
            valid = EGL_FALSE;
344
         break;
345
      case ATTRIB_TYPE_PLATFORM:
346
         /* unable to check platform-dependent attributes here */
347
         break;
348
      case ATTRIB_TYPE_PSEUDO:
349
         /* pseudo attributes should not be set */
350
         if (val != 0)
351
            valid = EGL_FALSE;
352
         break;
353
      default:
354
         assert(0);
355
         break;
356
      }
357
 
358
      if (!valid && for_matching) {
359
         /* accept EGL_DONT_CARE as a valid value */
360
         if (val == EGL_DONT_CARE)
361
            valid = EGL_TRUE;
362
         if (_eglValidationTable[i].criterion == ATTRIB_CRITERION_SPECIAL)
363
            valid = EGL_TRUE;
364
      }
365
      if (!valid) {
366
         _eglLog(_EGL_DEBUG,
367
               "attribute 0x%04x has an invalid value 0x%x", attr, val);
368
         break;
369
      }
370
   }
371
 
372
   /* any invalid attribute value should have been catched */
373
   if (!valid || for_matching)
374
      return valid;
375
 
376
   /* now check for conflicting attribute values */
377
 
378
   switch (conf->ColorBufferType) {
379
   case EGL_RGB_BUFFER:
380
      if (conf->LuminanceSize)
381
         valid = EGL_FALSE;
382
      if (conf->RedSize + conf->GreenSize +
383
            conf->BlueSize + conf->AlphaSize != conf->BufferSize)
384
         valid = EGL_FALSE;
385
      break;
386
   case EGL_LUMINANCE_BUFFER:
387
      if (conf->RedSize || conf->GreenSize || conf->BlueSize)
388
         valid = EGL_FALSE;
389
      if (conf->LuminanceSize + conf->AlphaSize != conf->BufferSize)
390
         valid = EGL_FALSE;
391
      break;
392
   }
393
   if (!valid) {
394
      _eglLog(_EGL_DEBUG, "conflicting color buffer type and channel sizes");
395
      return EGL_FALSE;
396
   }
397
 
398
   if (!conf->SampleBuffers && conf->Samples)
399
      valid = EGL_FALSE;
400
   if (!valid) {
401
      _eglLog(_EGL_DEBUG, "conflicting samples and sample buffers");
402
      return EGL_FALSE;
403
   }
404
 
405
   if (!(conf->SurfaceType & EGL_WINDOW_BIT)) {
406
      if (conf->NativeVisualID != 0 || conf->NativeVisualType != EGL_NONE)
407
         valid = EGL_FALSE;
408
   }
409
   if (!(conf->SurfaceType & EGL_PBUFFER_BIT)) {
410
      if (conf->BindToTextureRGB || conf->BindToTextureRGBA)
411
         valid = EGL_FALSE;
412
   }
413
   if (!valid) {
414
      _eglLog(_EGL_DEBUG, "conflicting surface type and native visual/texture binding");
415
      return EGL_FALSE;
416
   }
417
 
418
   return valid;
419
}
420
 
421
 
422
/**
423
 * Return true if a config matches the criteria.  This and
424
 * _eglParseConfigAttribList together implement the algorithm
425
 * described in "Selection of EGLConfigs".
426
 *
427
 * Note that attributes that are special (currently, only
428
 * EGL_MATCH_NATIVE_PIXMAP) are ignored.
429
 */
430
EGLBoolean
431
_eglMatchConfig(const _EGLConfig *conf, const _EGLConfig *criteria)
432
{
433
   EGLint attr, val, i;
434
   EGLBoolean matched = EGL_TRUE;
435
 
436
   for (i = 0; i < ARRAY_SIZE(_eglValidationTable); i++) {
437
      EGLint cmp;
438
      if (_eglValidationTable[i].criterion == ATTRIB_CRITERION_IGNORE)
439
         continue;
440
 
441
      attr = _eglValidationTable[i].attr;
442
      cmp = _eglGetConfigKey(criteria, attr);
443
      if (cmp == EGL_DONT_CARE)
444
         continue;
445
 
446
      val = _eglGetConfigKey(conf, attr);
447
      switch (_eglValidationTable[i].criterion) {
448
      case ATTRIB_CRITERION_EXACT:
449
         if (val != cmp)
450
            matched = EGL_FALSE;
451
         break;
452
      case ATTRIB_CRITERION_ATLEAST:
453
         if (val < cmp)
454
            matched = EGL_FALSE;
455
         break;
456
      case ATTRIB_CRITERION_MASK:
457
         if ((val & cmp) != cmp)
458
            matched = EGL_FALSE;
459
         break;
460
      case ATTRIB_CRITERION_SPECIAL:
461
         /* ignored here */
462
         break;
463
      default:
464
         assert(0);
465
         break;
466
      }
467
 
468
      if (!matched) {
469
#ifndef DEBUG
470
         /* only print the common errors when DEBUG is not defined */
471
         if (attr != EGL_RENDERABLE_TYPE)
472
            break;
473
#endif
474
         _eglLog(_EGL_DEBUG,
475
               "the value (0x%x) of attribute 0x%04x did not meet the criteria (0x%x)",
476
               val, attr, cmp);
477
         break;
478
      }
479
   }
480
 
481
   return matched;
482
}
483
 
484
static INLINE EGLBoolean
485
_eglIsConfigAttribValid(_EGLConfig *conf, EGLint attr)
486
{
487
   if (_eglOffsetOfConfig(attr) < 0)
488
      return EGL_FALSE;
489
 
490
   switch (attr) {
491
   case EGL_Y_INVERTED_NOK:
492
      return conf->Display->Extensions.NOK_texture_from_pixmap;
493
   default:
494
      break;
495
   }
496
 
497
   return EGL_TRUE;
498
}
499
 
500
/**
501
 * Initialize a criteria config from the given attribute list.
502
 * Return EGL_FALSE if any of the attribute is invalid.
503
 */
504
EGLBoolean
505
_eglParseConfigAttribList(_EGLConfig *conf, _EGLDisplay *dpy,
506
                          const EGLint *attrib_list)
507
{
508
   EGLint attr, val, i;
509
 
510
   _eglInitConfig(conf, dpy, EGL_DONT_CARE);
511
 
512
   /* reset to default values */
513
   for (i = 0; i < ARRAY_SIZE(_eglValidationTable); i++) {
514
      attr = _eglValidationTable[i].attr;
515
      val = _eglValidationTable[i].default_value;
516
      _eglSetConfigKey(conf, attr, val);
517
   }
518
 
519
   /* parse the list */
520
   for (i = 0; attrib_list && attrib_list[i] != EGL_NONE; i += 2) {
521
      attr = attrib_list[i];
522
      val = attrib_list[i + 1];
523
 
524
      if (!_eglIsConfigAttribValid(conf, attr))
525
	 return EGL_FALSE;
526
 
527
      _eglSetConfigKey(conf, attr, val);
528
   }
529
 
530
   if (!_eglValidateConfig(conf, EGL_TRUE))
531
      return EGL_FALSE;
532
 
533
   /* EGL_LEVEL and EGL_MATCH_NATIVE_PIXMAP cannot be EGL_DONT_CARE */
534
   if (conf->Level == EGL_DONT_CARE ||
535
       conf->MatchNativePixmap == EGL_DONT_CARE)
536
      return EGL_FALSE;
537
 
538
   /* ignore other attributes when EGL_CONFIG_ID is given */
539
   if (conf->ConfigID != EGL_DONT_CARE) {
540
      for (i = 0; i < ARRAY_SIZE(_eglValidationTable); i++) {
541
         attr = _eglValidationTable[i].attr;
542
         if (attr != EGL_CONFIG_ID)
543
            _eglSetConfigKey(conf, attr, EGL_DONT_CARE);
544
      }
545
   }
546
   else {
547
      if (!(conf->SurfaceType & EGL_WINDOW_BIT))
548
         conf->NativeVisualType = EGL_DONT_CARE;
549
 
550
      if (conf->TransparentType == EGL_NONE) {
551
         conf->TransparentRedValue = EGL_DONT_CARE;
552
         conf->TransparentGreenValue = EGL_DONT_CARE;
553
         conf->TransparentBlueValue = EGL_DONT_CARE;
554
      }
555
   }
556
 
557
   return EGL_TRUE;
558
}
559
 
560
 
561
/**
562
 * Decide the ordering of conf1 and conf2, under the given criteria.
563
 * When compare_id is true, this implements the algorithm described
564
 * in "Sorting of EGLConfigs".  When compare_id is false,
565
 * EGL_CONFIG_ID is not compared.
566
 *
567
 * It returns a negative integer if conf1 is considered to come
568
 * before conf2;  a positive integer if conf2 is considered to come
569
 * before conf1;  zero if the ordering cannot be decided.
570
 *
571
 * Note that EGL_NATIVE_VISUAL_TYPE is platform-dependent and is
572
 * ignored here.
573
 */
574
EGLint
575
_eglCompareConfigs(const _EGLConfig *conf1, const _EGLConfig *conf2,
576
                   const _EGLConfig *criteria, EGLBoolean compare_id)
577
{
578
   const EGLint compare_attribs[] = {
579
      EGL_BUFFER_SIZE,
580
      EGL_SAMPLE_BUFFERS,
581
      EGL_SAMPLES,
582
      EGL_DEPTH_SIZE,
583
      EGL_STENCIL_SIZE,
584
      EGL_ALPHA_MASK_SIZE,
585
   };
586
   EGLint val1, val2;
587
   EGLint i;
588
 
589
   if (conf1 == conf2)
590
      return 0;
591
 
592
   /* the enum values have the desired ordering */
593
   assert(EGL_NONE < EGL_SLOW_CONFIG);
594
   assert(EGL_SLOW_CONFIG < EGL_NON_CONFORMANT_CONFIG);
595
   val1 = conf1->ConfigCaveat - conf2->ConfigCaveat;
596
   if (val1)
597
      return val1;
598
 
599
   /* the enum values have the desired ordering */
600
   assert(EGL_RGB_BUFFER < EGL_LUMINANCE_BUFFER);
601
   val1 = conf1->ColorBufferType - conf2->ColorBufferType;
602
   if (val1)
603
      return val1;
604
 
605
   if (criteria) {
606
      val1 = val2 = 0;
607
      if (conf1->ColorBufferType == EGL_RGB_BUFFER) {
608
         if (criteria->RedSize > 0) {
609
            val1 += conf1->RedSize;
610
            val2 += conf2->RedSize;
611
         }
612
         if (criteria->GreenSize > 0) {
613
            val1 += conf1->GreenSize;
614
            val2 += conf2->GreenSize;
615
         }
616
         if (criteria->BlueSize > 0) {
617
            val1 += conf1->BlueSize;
618
            val2 += conf2->BlueSize;
619
         }
620
      }
621
      else {
622
         if (criteria->LuminanceSize > 0) {
623
            val1 += conf1->LuminanceSize;
624
            val2 += conf2->LuminanceSize;
625
         }
626
      }
627
      if (criteria->AlphaSize > 0) {
628
         val1 += conf1->AlphaSize;
629
         val2 += conf2->AlphaSize;
630
      }
631
   }
632
   else {
633
      /* assume the default criteria, which gives no specific ordering */
634
      val1 = val2 = 0;
635
   }
636
 
637
   /* for color bits, larger one is preferred */
638
   if (val1 != val2)
639
      return (val2 - val1);
640
 
641
   for (i = 0; i < ARRAY_SIZE(compare_attribs); i++) {
642
      val1 = _eglGetConfigKey(conf1, compare_attribs[i]);
643
      val2 = _eglGetConfigKey(conf2, compare_attribs[i]);
644
      if (val1 != val2)
645
         return (val1 - val2);
646
   }
647
 
648
   /* EGL_NATIVE_VISUAL_TYPE cannot be compared here */
649
 
650
   return (compare_id) ? (conf1->ConfigID - conf2->ConfigID) : 0;
651
}
652
 
653
 
654
static INLINE
655
void _eglSwapConfigs(const _EGLConfig **conf1, const _EGLConfig **conf2)
656
{
657
   const _EGLConfig *tmp = *conf1;
658
   *conf1 = *conf2;
659
   *conf2 = tmp;
660
}
661
 
662
 
663
/**
664
 * Quick sort an array of configs.  This differs from the standard
665
 * qsort() in that the compare function accepts an additional
666
 * argument.
667
 */
668
static void
669
_eglSortConfigs(const _EGLConfig **configs, EGLint count,
670
                EGLint (*compare)(const _EGLConfig *, const _EGLConfig *,
671
                                  void *),
672
                void *priv_data)
673
{
674
   const EGLint pivot = 0;
675
   EGLint i, j;
676
 
677
   if (count <= 1)
678
      return;
679
 
680
   _eglSwapConfigs(&configs[pivot], &configs[count / 2]);
681
   i = 1;
682
   j = count - 1;
683
   do {
684
      while (i < count && compare(configs[i], configs[pivot], priv_data) < 0)
685
         i++;
686
      while (compare(configs[j], configs[pivot], priv_data) > 0)
687
         j--;
688
      if (i < j) {
689
         _eglSwapConfigs(&configs[i], &configs[j]);
690
         i++;
691
         j--;
692
      }
693
      else if (i == j) {
694
         i++;
695
         j--;
696
         break;
697
      }
698
   } while (i <= j);
699
   _eglSwapConfigs(&configs[pivot], &configs[j]);
700
 
701
   _eglSortConfigs(configs, j, compare, priv_data);
702
   _eglSortConfigs(configs + i, count - i, compare, priv_data);
703
}
704
 
705
 
706
/**
707
 * A helper function for implementing eglChooseConfig.  See _eglFilterArray and
708
 * _eglSortConfigs for the meanings of match and compare.
709
 */
710
EGLBoolean
711
_eglFilterConfigArray(_EGLArray *array, EGLConfig *configs,
712
                      EGLint config_size, EGLint *num_configs,
713
                      EGLBoolean (*match)(const _EGLConfig *, void *),
714
                      EGLint (*compare)(const _EGLConfig *, const _EGLConfig *,
715
                                        void *),
716
                      void *priv_data)
717
{
718
   _EGLConfig **configList;
719
   EGLint i, count;
720
 
721
   if (!num_configs)
722
      return _eglError(EGL_BAD_PARAMETER, "eglChooseConfigs");
723
 
724
   /* get the number of matched configs */
725
   count = _eglFilterArray(array, NULL, 0,
726
         (_EGLArrayForEach) match, priv_data);
727
   if (!count) {
728
      *num_configs = count;
729
      return EGL_TRUE;
730
   }
731
 
732
   configList = malloc(sizeof(*configList) * count);
733
   if (!configList)
734
      return _eglError(EGL_BAD_ALLOC, "eglChooseConfig(out of memory)");
735
 
736
   /* get the matched configs */
737
   _eglFilterArray(array, (void **) configList, count,
738
         (_EGLArrayForEach) match, priv_data);
739
 
740
   /* perform sorting of configs */
741
   if (configs && count) {
742
      _eglSortConfigs((const _EGLConfig **) configList, count,
743
                      compare, priv_data);
744
      count = MIN2(count, config_size);
745
      for (i = 0; i < count; i++)
746
         configs[i] = _eglGetConfigHandle(configList[i]);
747
   }
748
 
749
   free(configList);
750
 
751
   *num_configs = count;
752
 
753
   return EGL_TRUE;
754
}
755
 
756
 
757
static EGLBoolean
758
_eglFallbackMatch(const _EGLConfig *conf, void *priv_data)
759
{
760
   return _eglMatchConfig(conf, (const _EGLConfig *) priv_data);
761
}
762
 
763
 
764
static EGLint
765
_eglFallbackCompare(const _EGLConfig *conf1, const _EGLConfig *conf2,
766
                    void *priv_data)
767
{
768
   return _eglCompareConfigs(conf1, conf2,
769
         (const _EGLConfig *) priv_data, EGL_TRUE);
770
}
771
 
772
 
773
/**
774
 * Typical fallback routine for eglChooseConfig
775
 */
776
EGLBoolean
777
_eglChooseConfig(_EGLDriver *drv, _EGLDisplay *disp, const EGLint *attrib_list,
778
                 EGLConfig *configs, EGLint config_size, EGLint *num_configs)
779
{
780
   _EGLConfig criteria;
781
 
782
   if (!_eglParseConfigAttribList(&criteria, disp, attrib_list))
783
      return _eglError(EGL_BAD_ATTRIBUTE, "eglChooseConfig");
784
 
785
   return _eglFilterConfigArray(disp->Configs,
786
         configs, config_size, num_configs,
787
         _eglFallbackMatch, _eglFallbackCompare,
788
         (void *) &criteria);
789
}
790
 
791
 
792
/**
793
 * Fallback for eglGetConfigAttrib.
794
 */
795
EGLBoolean
796
_eglGetConfigAttrib(_EGLDriver *drv, _EGLDisplay *dpy, _EGLConfig *conf,
797
                    EGLint attribute, EGLint *value)
798
{
799
   if (!_eglIsConfigAttribValid(conf, attribute))
800
      return _eglError(EGL_BAD_ATTRIBUTE, "eglGetConfigAttrib");
801
 
802
   /* nonqueryable attributes */
803
   switch (attribute) {
804
   case EGL_MATCH_NATIVE_PIXMAP:
805
      return _eglError(EGL_BAD_ATTRIBUTE, "eglGetConfigAttrib");
806
      break;
807
   default:
808
      break;
809
   }
810
 
811
   if (!value)
812
      return _eglError(EGL_BAD_PARAMETER, "eglGetConfigAttrib");
813
 
814
   *value = _eglGetConfigKey(conf, attribute);
815
   return EGL_TRUE;
816
}
817
 
818
 
819
static EGLBoolean
820
_eglFlattenConfig(void *elem, void *buffer)
821
{
822
   _EGLConfig *conf = (_EGLConfig *) elem;
823
   EGLConfig *handle = (EGLConfig *) buffer;
824
   *handle = _eglGetConfigHandle(conf);
825
   return EGL_TRUE;
826
}
827
 
828
/**
829
 * Fallback for eglGetConfigs.
830
 */
831
EGLBoolean
832
_eglGetConfigs(_EGLDriver *drv, _EGLDisplay *disp, EGLConfig *configs,
833
               EGLint config_size, EGLint *num_config)
834
{
835
   if (!num_config)
836
      return _eglError(EGL_BAD_PARAMETER, "eglGetConfigs");
837
 
838
   *num_config = _eglFlattenArray(disp->Configs, (void *) configs,
839
         sizeof(configs[0]), config_size, _eglFlattenConfig);
840
 
841
   return EGL_TRUE;
842
}