Add more structure constructor tests.
[piglit/hramrach.git] / tests / glean / dsconfig.cpp
blobb446176a7123239a709a8ea7fa3a551971d9b5dd
1 // BEGIN_COPYRIGHT
2 //
3 // Copyright (C) 1999 Allen Akin All Rights Reserved.
4 //
5 // multisample changes: Copyright (c) 2008 VMware, Inc. All rights reserved.
6 //
7 // Permission is hereby granted, free of charge, to any person
8 // obtaining a copy of this software and associated documentation
9 // files (the "Software"), to deal in the Software without
10 // restriction, including without limitation the rights to use,
11 // copy, modify, merge, publish, distribute, sublicense, and/or
12 // sell copies of the Software, and to permit persons to whom the
13 // Software is furnished to do so, subject to the following
14 // conditions:
15 //
16 // The above copyright notice and this permission notice shall be
17 // included in all copies or substantial portions of the
18 // Software.
19 //
20 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY
21 // KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
22 // WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
23 // PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL ALLEN AKIN BE
24 // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
25 // AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF
26 // OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
27 // DEALINGS IN THE SOFTWARE.
28 //
29 // END_COPYRIGHT
32 // dsconfig.cpp: Implementation of drawing surface configuration utilities
33 #include "dsconfig.h"
34 #include <iostream>
35 #include <sstream>
36 #include <cstring>
37 #include <map>
38 #include <limits.h>
40 #ifdef __WIN__
41 // disable the annoying warning : "forcing value to bool 'true' or 'false' (performance warning)"
42 #pragma warning (disable : 4800)
43 #endif
46 #include "lex.h"
50 namespace {
52 #ifdef __X11__
54 bool
55 haveGLXExtension(::Display* dpy, const char* extName) {
56 const char* extString =
57 glXQueryExtensionsString(dpy, DefaultScreen(dpy));
58 // We don't cache the result, so that subsequent calls
59 // with different values of ``dpy'' will work correctly.
60 // Would be nice to improve this, though.
62 const char* start = extString;
63 for (;;) {
64 const char* where = strstr(start, extName);
65 if (!where)
66 return false;
68 // Make sure we're not fooled by extensions whose names
69 // have the desired extName as an initial substring:
70 const char* terminator = where + strlen(extName);
71 if ((where == start || where[-1] == ' ')
72 && (*terminator == ' ' || *terminator == 0))
73 return true;
75 start = terminator;
78 return false;
79 } // haveGLXExtension
81 #endif
83 typedef enum { // These variable tags are used as array indices,
84 // so they should represent a small dense set of
85 // nonnegative integers. 0 is reserved.
86 VID = 1,
87 VFBCID,
88 VCANRGBA,
89 VR,
90 VG,
91 VB,
92 VA,
93 VCANCI,
94 VBUFSIZE,
95 VLEVEL,
96 VDB,
97 VSTEREO,
98 VAUX,
99 VZ,
101 VACCUMR,
102 VACCUMG,
103 VACCUMB,
104 VACCUMA,
105 VSAMPLES,
106 VCANWINDOW,
107 VCANPIXMAP,
108 VCANPBUFFER,
109 VMAXPBUFFERWIDTH,
110 VMAXPBUFFERHEIGHT,
111 VMAXPBUFFERPIXELS,
112 VCANWINSYSRENDER,
113 VFAST,
114 VCONFORMANT,
115 VTRANSPARENT,
116 VTRANSR,
117 VTRANSG,
118 VTRANSB,
119 VTRANSA,
120 VTRANSI,
121 V_LAST
122 } CanonVar;
124 static struct {CanonVar var; const char* name;} varNames[] = {
125 {VID, "id"},
126 {VFBCID, "fbcID"},
127 {VCANRGBA, "canRGBA"},
128 {VR, "r"},
129 {VG, "g"},
130 {VB, "b"},
131 {VA, "a"},
132 {VCANCI, "canCI"},
133 {VBUFSIZE, "bufSize"},
134 {VLEVEL, "level"},
135 {VDB, "db"},
136 {VSTEREO, "stereo"},
137 {VAUX, "aux"},
138 {VZ, "z"},
139 {VS, "s"},
140 {VACCUMR, "accumR"},
141 {VACCUMG, "accumG"},
142 {VACCUMB, "accumB"},
143 {VACCUMA, "accumA"},
144 {VSAMPLES, "multisample"},
145 {VCANWINDOW, "window"},
146 {VCANPIXMAP, "pixmap"},
147 {VCANPBUFFER, "pBuffer"},
148 {VMAXPBUFFERWIDTH, "maxPBufferWidth"},
149 {VMAXPBUFFERHEIGHT, "maxPBufferHeight"},
150 {VMAXPBUFFERPIXELS, "maxPBufferPixels"},
151 {VCANWINSYSRENDER, "winsys"},
152 {VFAST, "fast"},
153 {VCONFORMANT, "conformant"},
154 {VTRANSPARENT, "transparent"},
155 {VTRANSR, "transR"},
156 {VTRANSG, "transG"},
157 {VTRANSB, "transB"},
158 {VTRANSA, "transA"},
159 {VTRANSI, "transI"}
162 const char* mapVarToName[V_LAST];
163 map<string, CanonVar> mapNameToVar;
164 bool mapsInitialized = false;
166 void
167 initializeMaps() {
168 for (unsigned i = 0; i < sizeof(varNames)/sizeof(varNames[0]); ++i) {
169 mapVarToName[varNames[i].var] = varNames[i].name;
170 mapNameToVar[varNames[i].name] = varNames[i].var;
172 mapsInitialized = true;
173 } // initializeMaps
175 template<class T> inline T abs(T a) {return (a < 0)? -a: a;}
177 } // anonymous namespace
180 namespace GLEAN {
182 // init all config fields to zero
183 void
184 DrawingSurfaceConfig::zeroFields()
186 #if defined(__X11__)
187 visID = 0;
188 # if defined(GLX_VERSION_1_3)
189 fbcID = 0;
190 # endif
191 #elif defined(__WIN__)
192 pfdID = 0;
193 #elif defined(__AGL__)
194 pfID = 0;
195 #else
196 # error "what's the config ID?"
197 #endif
198 canRGBA = 0;
199 canCI = 0;
200 bufSize = 0;
201 level = 0;
202 db = 0;
203 stereo = 0;
204 aux = 0;
205 r = 0;
206 g = 0;
207 b = 0;
208 a = 0;
209 z = 0;
210 s = 0;
211 accR = 0;
212 accG = 0;
213 accB = 0;
214 accA = 0;
215 samples = 0;
216 canWindow = 0;
217 #if defined(__X11__)
218 canPixmap = 0;
219 #if defined(GLX_VERSION_1_3)
220 canPBuffer = 0;
221 maxPBufferWidth = 0;
222 maxPBufferHeight = 0;
223 maxPBufferPixels = 0;
224 #endif
225 #endif
226 canWinSysRender = 0;
227 fast = 0;
228 conformant = 0;
229 transparent = 0;
230 transR = 0;
231 transG = 0;
232 transB = 0;
233 transA = 0;
234 transI = 0;
238 #if defined(__X11__)
240 DrawingSurfaceConfig::DrawingSurfaceConfig(::Display* dpy, ::XVisualInfo* pvi) {
241 if (!mapsInitialized)
242 initializeMaps();
244 int var;
246 vi = pvi;
247 visID = vi->visualid;
248 # if defined(GLX_VERSION_1_3)
249 fbcID = 0;
250 # endif
252 glXGetConfig(dpy, vi, GLX_RGBA, &var);
253 canRGBA = var;
254 canCI = !var;
255 // There is no dual-personality Visual support in early
256 // versions of GLX.
258 glXGetConfig(dpy, vi, GLX_BUFFER_SIZE, &bufSize);
260 glXGetConfig(dpy, vi, GLX_LEVEL, &level);
262 glXGetConfig(dpy, vi, GLX_DOUBLEBUFFER, &var);
263 db = var;
265 glXGetConfig(dpy, vi, GLX_STEREO, &var);
266 stereo = var;
268 glXGetConfig(dpy, vi, GLX_AUX_BUFFERS, &aux);
270 if (canRGBA) {
271 glXGetConfig(dpy, vi, GLX_RED_SIZE, &r);
272 glXGetConfig(dpy, vi, GLX_GREEN_SIZE, &g);
273 glXGetConfig(dpy, vi, GLX_BLUE_SIZE, &b);
274 glXGetConfig(dpy, vi, GLX_ALPHA_SIZE, &a);
275 } else
276 r = g = b = a = 0;
278 glXGetConfig(dpy, vi, GLX_DEPTH_SIZE, &z);
280 glXGetConfig(dpy, vi, GLX_STENCIL_SIZE, &s);
282 if (canRGBA) {
283 glXGetConfig(dpy, vi, GLX_ACCUM_RED_SIZE, &accR);
284 glXGetConfig(dpy, vi, GLX_ACCUM_GREEN_SIZE, &accG);
285 glXGetConfig(dpy, vi, GLX_ACCUM_BLUE_SIZE, &accB);
286 glXGetConfig(dpy, vi, GLX_ACCUM_ALPHA_SIZE, &accA);
287 } else
288 accR = accG = accB = accA = 0;
290 // Note that samples=0 means no multisampling!
291 // One might think that one sample per pixel means non-multisampling
292 // but that's not the convention used here.
293 samples = 0;
294 if (canRGBA) {
295 int sampBuf = 0;
296 glXGetConfig(dpy, vi, GLX_SAMPLE_BUFFERS, &sampBuf);
297 if (sampBuf) {
298 glXGetConfig(dpy, vi, GLX_SAMPLES, &samples);
302 canWindow = canPixmap = true;
303 // Only guaranteed in early versions of GLX.
305 # if defined(GLX_VERSION_1_3)
306 canPBuffer = 0;
307 maxPBufferWidth = 0;
308 maxPBufferHeight = 0;
309 maxPBufferPixels = 0;
310 # endif
312 canWinSysRender = true;
313 // Only guaranteed in early versions of GLX.
315 fast = true;
316 conformant = true;
317 # if defined(GLX_EXT_visual_rating)
318 if (haveGLXExtension(dpy, "GLX_EXT_visual_rating")) {
319 glXGetConfig(dpy, vi, GLX_VISUAL_CAVEAT_EXT, &var);
320 if (var == GLX_SLOW_VISUAL_EXT)
321 fast = false;
322 else if (var == GLX_NON_CONFORMANT_VISUAL_EXT)
323 conformant = false;
325 # endif
327 transparent = false;
328 transR = transG = transB = transA = transI = 0;
329 # if defined(GLX_EXT_visual_info)
330 if (haveGLXExtension(dpy, "GLX_EXT_visual_info")) {
331 glXGetConfig(dpy, vi, GLX_TRANSPARENT_TYPE_EXT, &var);
332 if (var == GLX_TRANSPARENT_RGB_EXT) {
333 glXGetConfig(dpy, vi,
334 GLX_TRANSPARENT_RED_VALUE_EXT, &transR);
335 glXGetConfig(dpy, vi,
336 GLX_TRANSPARENT_GREEN_VALUE_EXT, &transG);
337 glXGetConfig(dpy, vi,
338 GLX_TRANSPARENT_BLUE_VALUE_EXT, &transB);
339 glXGetConfig(dpy, vi,
340 GLX_TRANSPARENT_ALPHA_VALUE_EXT, &transA);
341 } else
342 glXGetConfig(dpy, vi,
343 GLX_TRANSPARENT_INDEX_VALUE_EXT, &transI);
345 # endif
346 } // DrawingSurfaceConfig::DrawingSurfaceConfig
348 #if defined(GLX_VERSION_1_3)
349 DrawingSurfaceConfig::DrawingSurfaceConfig(::Display* dpy, ::GLXFBConfig* pfbc)
351 // silence warnings about unused parameters:
352 (void) dpy;
353 (void) pfbc;
355 if (!mapsInitialized)
356 initializeMaps();
357 // XXX Need to write drawing surface config code for GLX 1.3
358 cerr << "GLX 1.3 version of DrawingSurfaceConfig constructor is not"
359 "implemented.\n";
360 } // DrawingSurfaceConfig::DrawingSurfaceConfig
361 #endif
363 #elif defined(__WIN__)
365 DrawingSurfaceConfig::DrawingSurfaceConfig(int id, ::PIXELFORMATDESCRIPTOR *ppfd)
367 if (!mapsInitialized)
368 initializeMaps();
370 pfd = ppfd;
371 pfdID = id;
373 canRGBA = pfd->iPixelType == PFD_TYPE_RGBA;
374 canCI = pfd->iPixelType == PFD_TYPE_COLORINDEX;
376 bufSize = pfd->cColorBits + pfd->cAlphaBits;
378 level = 0;
380 db = pfd->dwFlags & PFD_DOUBLEBUFFER;
382 stereo = pfd->dwFlags & PFD_STEREO;
384 aux = pfd->cAuxBuffers;
386 if (canRGBA) {
387 r = pfd->cRedBits;
388 g = pfd->cGreenBits;
389 b = pfd->cBlueBits;
390 a = pfd->cAlphaBits;
392 else
393 r = g = b = a = 0;
395 z = pfd->cDepthBits;
396 s = pfd->cStencilBits;
398 accR = pfd->cAccumRedBits;
399 accG = pfd->cAccumGreenBits;
400 accB = pfd->cAccumBlueBits;
401 accA = pfd->cAccumAlphaBits;
403 samples = 0; // XXX implement properly for Windows!
405 canWindow = pfd->dwFlags & PFD_DRAW_TO_WINDOW;
407 canWinSysRender = pfd->dwFlags & PFD_SUPPORT_GDI;
409 if (pfd->dwFlags & PFD_GENERIC_FORMAT)
411 if (pfd->dwFlags & PFD_GENERIC_ACCELERATED)
413 // it's an MCD - at least it has some acceleration
414 fast = true;
416 else
418 // it's software
419 fast = false;
422 else
424 // it's an ICD
425 fast = true;
428 // we'll assume that the OpenGL implementation thinks it is conformant
429 conformant = true;
431 // chromakeying isn't supported
432 transparent = false;
433 transR = transG = transB = transA = transI = 0;
435 #elif defined(__BEWIN__)
437 DrawingSurfaceConfig::DrawingSurfaceConfig() {
439 if (!mapsInitialized)
440 initializeMaps();
442 /* these values are estimates for the moment */
443 level = 0;
444 db = 1;
445 stereo =0;
446 r = g = b = a = 32;
448 z = 30;
449 accR = 32;
450 accG = 32;
451 accB = 32;
452 accA = 32;
454 samples = 0;
456 canWindow = 1;
457 canWinSysRender = 1;
459 // This is a software-mode assumption
460 fast = false;
462 // we'll assume that the OpenGL implementation thinks it is conformant
463 conformant = true;
465 // chromakeying isn't supported
466 transparent = false;
467 transR = transG = transB = transA = transI = 0;
470 #elif defined(__AGL__)
472 DrawingSurfaceConfig::DrawingSurfaceConfig(int id, ::AGLPixelFormat pfd)
474 int i;
476 if (!mapsInitialized)
477 initializeMaps();
479 pf = pfd;
481 if (aglDescribePixelFormat( pf, AGL_RGBA, &i))
482 canRGBA = (i == GL_TRUE);
483 canCI = (i == GL_FALSE);
485 if (aglDescribePixelFormat( pf, AGL_BUFFER_SIZE, &i))
486 bufSize = i;
488 level = 0;
490 if (aglDescribePixelFormat( pf, AGL_DOUBLEBUFFER, &i))
491 db = (i == GL_TRUE);
492 if (aglDescribePixelFormat( pf, AGL_STEREO, &i))
493 stereo = (i == GL_TRUE);
494 if (aglDescribePixelFormat( pf, AGL_AUX_BUFFERS, &i))
495 aux = i;
497 if (canRGBA) {
498 aglDescribePixelFormat( pf, AGL_RED_SIZE, &r);
499 aglDescribePixelFormat( pf, AGL_GREEN_SIZE, &g);
500 aglDescribePixelFormat( pf, AGL_BLUE_SIZE, &b);
501 aglDescribePixelFormat( pf, AGL_ALPHA_SIZE, &a);
503 //this is a workaround for some versions of AGL
504 if (r == 10)
506 r=g=b=8;
507 bufSize = r + g + b + a;
510 else
511 r = g = b = a = 0;
513 samples = 0; // XXX implement properly for AGL
515 aglDescribePixelFormat( pf, AGL_DEPTH_SIZE, & z);
516 aglDescribePixelFormat( pf, AGL_STENCIL_SIZE, & s);
518 aglDescribePixelFormat( pf, AGL_ACCUM_RED_SIZE, & accR);
519 aglDescribePixelFormat( pf, AGL_ACCUM_GREEN_SIZE, & accG);
520 aglDescribePixelFormat( pf, AGL_ACCUM_BLUE_SIZE, & accB);
521 aglDescribePixelFormat( pf, AGL_ACCUM_ALPHA_SIZE, & accA);
523 aglDescribePixelFormat( pf, AGL_WINDOW, &i);
524 canWindow = i;
525 aglDescribePixelFormat( pf, AGL_OFFSCREEN, &i);
526 canWinSysRender = i;
527 aglDescribePixelFormat( pf, AGL_ACCELERATED, & i);
528 fast = i;
530 // we'll assume that the OpenGL implementation thinks it is conformant
531 conformant = true;
533 // chromakeying isn't supported
534 transparent = false;
535 transR = transG = transB = transA = transI = 0;
538 #endif
540 DrawingSurfaceConfig::DrawingSurfaceConfig(string& str) {
541 if (!mapsInitialized)
542 initializeMaps();
544 zeroFields();
546 try {
547 Lex lex(str.c_str());
549 for (lex.next(); lex.token != Lex::END; lex.next()) {
550 if (lex.token != Lex::ID)
551 throw Syntax("expected variable name",
552 lex.position());
553 lex.next();
554 if (lex.token != Lex::ICONST)
555 throw Syntax("expected integer value",
556 lex.position());
558 // Yes, this is an unpleasantly verbose way to
559 // handle this problem. However, it will be
560 // necessary when we have to deal with attributes
561 // that aren't all of a simple integral type.
563 switch (mapNameToVar[lex.id]) {
564 case VID:
565 # if defined(__X11__)
566 visID = lex.iValue;
567 # endif
568 break;
569 case VFBCID:
570 # if defined(GLX_VERSION_1_3)
571 fbcID = lex.iValue;
572 # endif
573 break;
574 case VCANRGBA:
575 canRGBA = lex.iValue;
576 break;
577 case VR:
578 r = lex.iValue;
579 break;
580 case VG:
581 g = lex.iValue;
582 break;
583 case VB:
584 b = lex.iValue;
585 break;
586 case VA:
587 a = lex.iValue;
588 break;
589 case VCANCI:
590 canCI = lex.iValue;
591 break;
592 case VBUFSIZE:
593 bufSize = lex.iValue;
594 break;
595 case VLEVEL:
596 level = lex.iValue;
597 break;
598 case VDB:
599 db = lex.iValue;
600 break;
601 case VSTEREO:
602 stereo = lex.iValue;
603 break;
604 case VAUX:
605 aux = lex.iValue;
606 break;
607 case VZ:
608 z = lex.iValue;
609 break;
610 case VS:
611 s = lex.iValue;
612 break;
613 case VACCUMR:
614 accR = lex.iValue;
615 break;
616 case VACCUMG:
617 accG = lex.iValue;
618 break;
619 case VACCUMB:
620 accB = lex.iValue;
621 break;
622 case VACCUMA:
623 accA = lex.iValue;
624 break;
625 case VSAMPLES:
626 samples = lex.iValue;
627 break;
628 case VCANWINDOW:
629 canWindow = lex.iValue;
630 break;
631 case VCANPIXMAP:
632 # if defined(__X11__)
633 canPixmap = lex.iValue;
634 # endif
635 break;
636 case VCANPBUFFER:
637 # if defined(GLX_VERSION_1_3)
638 canPBuffer = lex.iValue;
639 # endif
640 break;
641 case VMAXPBUFFERWIDTH:
642 # if defined(GLX_VERSION_1_3)
643 maxPBufferWidth = lex.iValue;
644 # endif
645 break;
646 case VMAXPBUFFERHEIGHT:
647 # if defined(GLX_VERSION_1_3)
648 maxPBufferHeight = lex.iValue;
649 # endif
650 break;
651 case VMAXPBUFFERPIXELS:
652 # if defined(GLX_VERSION_1_3)
653 maxPBufferPixels = lex.iValue;
654 # endif
655 break;
656 case VCANWINSYSRENDER:
657 canWinSysRender = lex.iValue;
658 break;
659 case VFAST:
660 fast = lex.iValue;
661 break;
662 case VCONFORMANT:
663 conformant = lex.iValue;
664 break;
665 case VTRANSPARENT:
666 transparent = lex.iValue;
667 break;
668 case VTRANSR:
669 transR = lex.iValue;
670 break;
671 case VTRANSG:
672 transG = lex.iValue;
673 break;
674 case VTRANSB:
675 transB = lex.iValue;
676 break;
677 case VTRANSA:
678 transA = lex.iValue;
679 break;
680 case VTRANSI:
681 transI = lex.iValue;
682 break;
683 default:
684 throw Syntax("unrecognized variable",
685 lex.position());
689 catch (Lex::Lexical e) {
690 throw Syntax(e.err, e.position);
692 } // DrawingSurfaceConfing::DrawingSurfaceConfig
695 ///////////////////////////////////////////////////////////////////////////////
696 // canonicalDescription - return a description string that can be used
697 // to reconstruct the essential attributes of a drawing surface
698 // configuration. Note that visual ID numbers are included for
699 // completeness, but they must be ignored when attempting to compare
700 // two surface configurations; there's no guarantee that they'll be
701 // valid (or even relevant, since they may have been created on another
702 // OS).
704 // This is ugly code, but it keeps the names used here and in
705 // the string-based constructor for DrawingSurfaceConfig in sync
706 // automatically.
707 ///////////////////////////////////////////////////////////////////////////////
708 string
709 DrawingSurfaceConfig::canonicalDescription() {
710 ostringstream s;
712 # if defined(__X11__)
713 s << mapVarToName[VID] << ' ' << visID;
714 # if defined(GLX_VERSION_1_3)
715 s << ' ' << mapVarToName[VFBCID] << ' ' << fbcID;
716 # endif
717 # elif defined(__WIN__)
718 s << mapVarToName[VID] << ' ' << pfdID;
719 # endif
721 s << ' ' << mapVarToName[VCANRGBA] << ' ' << canRGBA;
722 s << ' ' << mapVarToName[VR] << ' ' << r
723 << ' ' << mapVarToName[VG] << ' ' << g
724 << ' ' << mapVarToName[VB] << ' ' << b
725 << ' ' << mapVarToName[VA] << ' ' << a;
727 s << ' ' << mapVarToName[VCANCI] << ' ' << canCI;
729 s << ' ' << mapVarToName[VBUFSIZE] << ' ' << bufSize;
731 s << ' ' << mapVarToName[VLEVEL] << ' ' << level;
733 s << ' ' << mapVarToName[VDB] << ' ' << db;
735 s << ' ' << mapVarToName[VSTEREO] << ' '<< stereo;
737 s << ' ' << mapVarToName[VAUX] << ' ' << aux;
739 s << ' ' << mapVarToName[VZ] << ' ' << z;
741 s << ' ' << mapVarToName[VS] << ' ' << DrawingSurfaceConfig::s;
743 s << ' ' << mapVarToName[VACCUMR] << ' ' << accR
744 << ' ' << mapVarToName[VACCUMG] << ' ' << accG
745 << ' ' << mapVarToName[VACCUMB] << ' ' << accB
746 << ' ' << mapVarToName[VACCUMA] << ' ' << accA;
748 s << ' ' << mapVarToName[VSAMPLES] << ' ' << samples;
750 s << ' ' << mapVarToName[VCANWINDOW] << ' ' << canWindow;
752 # if defined(__X11__)
753 s << ' ' << mapVarToName[VCANPIXMAP] << ' ' << canPixmap;
755 # if defined(GLX_VERSION_1_3)
756 s << ' ' << mapVarToName[VCANPBUFFER] << ' ' << canPBuffer;
757 s << ' ' << mapVarToName[VMAXPBUFFERWIDTH] << ' ' << maxPBufferWidth;
758 s << ' ' << mapVarToName[VMAXPBUFFERHEIGHT] << ' ' << maxPBufferHeight;
759 s << ' ' << mapVarToName[VMAXPBUFFERPIXELS] << ' ' << maxPBufferPixels;
760 # endif
762 # endif
764 s << ' ' << mapVarToName[VCANWINSYSRENDER] << ' ' << canWinSysRender;
766 s << ' ' << mapVarToName[VFAST] << ' ' << fast;
768 s << ' ' << mapVarToName[VCONFORMANT] << ' ' << conformant;
770 s << ' ' << mapVarToName[VTRANSPARENT] << ' ' << transparent;
771 s << ' ' << mapVarToName[VTRANSR] << ' ' << transR
772 << ' ' << mapVarToName[VTRANSG] << ' ' << transG
773 << ' ' << mapVarToName[VTRANSB] << ' ' << transB
774 << ' ' << mapVarToName[VTRANSA] << ' ' << transA
775 << ' ' << mapVarToName[VTRANSI] << ' ' << transI;
777 return s.str();
778 } // DrawingSurfaceConfig::canonicalDescription
780 ///////////////////////////////////////////////////////////////////////////////
781 // conciseDescription - return a description string that's appropriate for
782 // reading by humans, rather than parsing by machine.
783 ///////////////////////////////////////////////////////////////////////////////
784 string
785 DrawingSurfaceConfig::conciseDescription() {
786 ostringstream s;
788 if (canRGBA && canCI)
789 s << "dual ";
791 if (canRGBA) {
792 if (a) {
793 if (r == g && g == b && b == a)
794 s << "rgba" << r;
795 else
796 s << "r" << r << "g" << g << "b" << b
797 << "a" << a;
798 } else {
799 if (r == g && g == b)
800 s << "rgb" << r;
801 else
802 s << "r" << r << "g" << g << "b" << b;
806 if (canCI) {
807 if (canRGBA) s << "+";
808 s << "ci" << bufSize;
811 if (level < 0)
812 s << ", underlay";
813 else if (level > 0)
814 s << ", overlay";
816 if (db)
817 s << ", db";
819 if (stereo)
820 s << ", stereo";
822 if (aux)
823 s << ", aux" << aux;
825 if (z)
826 s << ", z" << z;
828 if (DrawingSurfaceConfig::s)
829 s << ", s" << DrawingSurfaceConfig::s;
831 if (accR) {
832 if (accA) {
833 if (accR == accG && accG == accB
834 && accB == accA)
835 s << ", accrgba" << accR;
836 else
837 s << ", accr" << accR << "g" << accG
838 << "b" << accB << "a" << accA;
839 } else {
840 if (accR == accG && accG == accB)
841 s << ", accrgb" << accR;
842 else
843 s << ", accr" << accR << "g" << accG
844 << "b" << accB;
848 if (samples) {
849 s << ", samples" << samples;
853 s << ", ";
854 bool sep = false;
855 if (canWindow) {
856 s << "win";
857 sep = true;
859 # if defined(__X11__)
860 if (canPixmap) {
861 if (sep)
862 s << "+";
863 s << "pmap";
864 sep = true;
866 # endif
867 # if defined(GLX_VERSION_1_3)
868 if (canPBuffer) {
869 if (sep)
870 s << "+";
871 s << "pbuf";
873 # endif
876 if (!fast)
877 s << ", slow";
879 if (!conformant)
880 s << ", nonconformant";
882 if (transparent) {
883 if (canRGBA) {
884 s << ", transrgba (" << transR << "," << transG
885 << "," << transB << "," << transA << ")";
887 if (canCI) {
888 s << ", transci (" << transI << ")";
892 # if defined(__X11__)
893 s << ", id " << visID;
894 # if defined(GLX_VERSION_1_3)
895 if (fbcID)
896 s << ", fbcid " << fbcID;
897 # endif
898 # elif defined(__WIN__)
899 s << ", id " << pfdID;
900 # endif
902 return s.str();
903 } // DrawingSurfaceConfig::conciseDescription
905 ///////////////////////////////////////////////////////////////////////////////
906 // match - select a config that ``matches'' the current config.
907 // To keep this problem manageable, we'll assume that both the config
908 // to be matched (call it the ``A'' config) and the vector of configs to
909 // choose from (call them the ``B'' configs) were selected by a test
910 // using a single filter. Thus we can ignore any differences in buffer
911 // availability (because we know those are irrelevant to the test), and
912 // concentrate on picking configs for which the available buffers are
913 // (in some sense) closest in size.
915 // This will not be an acceptable solution in all cases, but it should
916 // suffice for many.
917 ///////////////////////////////////////////////////////////////////////////////
919 DrawingSurfaceConfig::match(vector<DrawingSurfaceConfig*>& choices) {
920 typedef vector<DrawingSurfaceConfig*>::iterator cptr;
922 // first try finding an exact match
923 for (cptr p = choices.begin(); p < choices.end(); ++p) {
924 DrawingSurfaceConfig& c = **p;
925 if (equal(c)) {
926 int pos = static_cast<int>(p - choices.begin());
927 return pos;
931 // next try finding the closest match
932 int best = -1;
933 int bestError = INT_MAX;
935 for (cptr p = choices.begin(); p < choices.end(); ++p) {
936 DrawingSurfaceConfig& c = **p;
937 int error = 0;
939 if (bufSize && c.bufSize)
940 error += abs(bufSize - c.bufSize);
941 if (r && c.r)
942 error += abs(r - c.r);
943 if (g && c.g)
944 error += abs(g - c.g);
945 if (b && c.b)
946 error += abs(b - c.b);
947 if (a && c.a)
948 error += abs(a - c.a);
949 if (z && c.z)
950 error += abs(z - c.z);
951 if (s && c.s)
952 error += abs(s - c.s);
953 if (accR && c.accR)
954 error += abs(accR - c.accR);
955 if (accG && c.accG)
956 error += abs(accG - c.accG);
957 if (accB && c.accB)
958 error += abs(accB - c.accB);
959 if (accA && c.accA)
960 error += abs(accA - c.accA);
961 // Use a huge error value for multisample mismatch.
962 // Not sure this is the best solution.
963 if (samples != c.samples)
964 error += 1000;
966 if (error < bestError) {
967 bestError = error;
968 best = static_cast<int>(p - choices.begin());
972 return best;
973 } // DrawingSurfaceConfig::match
975 // are two surface configs exactly the same?
976 bool
977 DrawingSurfaceConfig::equal(const DrawingSurfaceConfig &config) const
979 if (
980 #if defined(__X11__)
981 visID == config.visID &&
982 # if defined(GLX_VERSION_1_3)
983 fbcID == config.fbcID &&
984 # endif
985 #elif defined(__WIN__)
986 pfdID == config.pfdID &&
987 #elif defined(__AGL__)
988 pfID == config.pfID &&
989 #else
990 # error "what's the config ID?"
991 #endif
992 canRGBA == config.canRGBA &&
993 canCI == config.canCI &&
994 bufSize == config.bufSize &&
995 level == config.level &&
996 db == config.db &&
997 stereo == config.stereo &&
998 aux == config.aux &&
999 r == config.r &&
1000 g == config.g &&
1001 b == config.b &&
1002 a == config.a &&
1003 z == config.z &&
1004 s == config.s &&
1005 accR == config.accR &&
1006 accG == config.accG &&
1007 accB == config.accB &&
1008 accA == config.accA &&
1009 samples == config.samples &&
1010 canWindow == config.canWindow &&
1011 #if defined(__X11__)
1012 canPixmap == config.canPixmap &&
1013 #if defined(GLX_VERSION_1_3)
1014 canPBuffer == config.canPBuffer &&
1015 maxPBufferWidth == config.maxPBufferWidth &&
1016 maxPBufferHeight == config.maxPBufferHeight &&
1017 maxPBufferPixels == config.maxPBufferPixels &&
1018 #endif
1019 #endif
1020 canWinSysRender == config.canWinSysRender &&
1021 fast == config.fast &&
1022 conformant == config.conformant &&
1023 transparent == config.transparent &&
1024 transR == config.transR &&
1025 transG == config.transG &&
1026 transB == config.transB &&
1027 transA == config.transA &&
1028 transI == config.transI
1030 return true;
1031 else
1032 return false;
1035 } // namespace GLEAN