3 // Copyright (C) 1999 Allen Akin All Rights Reserved.
5 // multisample changes: Copyright (c) 2008 VMware, Inc. All rights reserved.
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
16 // The above copyright notice and this permission notice shall be
17 // included in all copies or substantial portions of the
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.
34 // dsfilt.cpp: Implementation of drawing surface configuration filtering
46 ///////////////////////////////////////////////////////////////////////////////
48 ///////////////////////////////////////////////////////////////////////////////
49 DrawingSurfaceFilter::DrawingSurfaceFilter(const string
& s
):
50 lex(s
.c_str(), true) {
52 if (!varTableInitialized
)
58 throw Syntax("no criteria found", lex
.position());
60 catch (Lex::Lexical e
) {
61 throw Syntax(e
.err
, e
.position
);
64 // Make the final sort in order of increasing ID number:
67 # if defined(GLX_VERSION_1_3)
71 } // DrawingSurfaceFilter::DrawingSurfaceFilter
73 ///////////////////////////////////////////////////////////////////////////////
74 // matches - determine if a drawing surface config matches the specified
76 ///////////////////////////////////////////////////////////////////////////////
78 DrawingSurfaceFilter::matches(DrawingSurfaceConfig
& c
) {
79 // Process the RPN expression in ``condition'', using the supplied
80 // drawing surface configuration to determine values of variables.
84 for (vector
<int>::const_iterator p
= condition
.begin();
85 p
< condition
.end(); ++p
) {
90 right
= stack
.back(); stack
.pop_back();
91 stack
.back() += right
;
94 right
= stack
.back(); stack
.pop_back();
95 stack
.back() = stack
.back() && right
;
98 right
= stack
.back(); stack
.pop_back();
99 stack
.back() = (right
== 0)? 0: stack
.back() / right
;
102 right
= stack
.back(); stack
.pop_back();
103 stack
.back() = stack
.back() == right
;
106 right
= stack
.back(); stack
.pop_back();
107 stack
.back() = stack
.back() >= right
;
110 right
= stack
.back(); stack
.pop_back();
111 stack
.back() = stack
.back() > right
;
114 right
= stack
.back(); stack
.pop_back();
115 stack
.back() = stack
.back() <= right
;
118 right
= stack
.back(); stack
.pop_back();
119 stack
.back() = stack
.back() < right
;
122 right
= stack
.back(); stack
.pop_back();
123 stack
.back() = (right
== 0)? 0: stack
.back() % right
;
126 right
= stack
.back(); stack
.pop_back();
127 stack
.back() *= right
;
130 right
= stack
.back(); stack
.pop_back();
131 stack
.back() = stack
.back() != right
;
134 stack
.back() = -stack
.back();
137 stack
.back() = !stack
.back();
140 right
= stack
.back(); stack
.pop_back();
141 stack
.back() = stack
.back() || right
;
144 right
= stack
.back(); stack
.pop_back();
145 stack
.back() -= right
;
148 stack
.push_back(*++p
);
151 // Must be a variable.
152 stack
.push_back(FetchVariable(c
,
153 static_cast<Token
>(*p
)));
159 } // DrawingSurfaceFilter::matches
161 ///////////////////////////////////////////////////////////////////////////////
162 // filter - find and sort all matching drawing surface configurations
163 ///////////////////////////////////////////////////////////////////////////////
164 vector
<DrawingSurfaceConfig
*>
165 DrawingSurfaceFilter::filter(vector
<DrawingSurfaceConfig
*>& v
) {
166 return filter(v
, ~0u);
167 } // DrawingSurfaceFilter::filter
169 ///////////////////////////////////////////////////////////////////////////////
170 // filter - filter as above, but limit number of results
171 ///////////////////////////////////////////////////////////////////////////////
172 vector
<DrawingSurfaceConfig
*>
173 DrawingSurfaceFilter::filter(vector
<DrawingSurfaceConfig
*>& v
,
174 unsigned int maxConfigs
) {
175 vector
<DrawingSurfaceConfig
*> result
;
177 for (vector
<DrawingSurfaceConfig
*>::const_iterator p
= v
.begin();
178 p
< v
.end() && count
< maxConfigs
; ++p
) {
180 result
.push_back(*p
);
185 sort(result
.begin(), result
.end(), ConfigSort(sortKeys
));
187 } // DrawingSurfaceFilter::filter
189 ///////////////////////////////////////////////////////////////////////////////
190 // ConfigSort operator() - sort comparison for final ordering of configurations
191 ///////////////////////////////////////////////////////////////////////////////
193 DrawingSurfaceFilter::ConfigSort::operator()
194 (const DrawingSurfaceConfig
* c1
, const DrawingSurfaceConfig
* c2
) {
195 for (vector
<Token
>::const_iterator p
=keys
.begin(); p
<keys
.end(); ++p
) {
197 int d
= FetchVariable(*c1
, *p
) - FetchVariable(*c2
, *p
);
198 if (dir
== MAX
) // sort largest first?
201 return true; // c1 goes before c2
203 return false; // c1 goes after c2
205 return false; // order doesn't matter
208 ///////////////////////////////////////////////////////////////////////////////
209 // InitVarTable - initialize the table mapping variable names to token values
210 ///////////////////////////////////////////////////////////////////////////////
212 map
<string
,DrawingSurfaceFilter::Token
> DrawingSurfaceFilter::varTable
;
213 bool DrawingSurfaceFilter::varTableInitialized
;
216 DrawingSurfaceFilter::InitVarTable() {
217 varTable
["r"] = VAR_R
;
218 varTable
["g"] = VAR_G
;
219 varTable
["b"] = VAR_B
;
220 varTable
["a"] = VAR_A
;
221 varTable
["rgb"] = VAR_RGB
;
222 varTable
["rgba"] = VAR_RGBA
;
223 varTable
["ci"] = VAR_CI
;
224 varTable
["accumr"] = VAR_ACCUM_R
;
225 varTable
["accumg"] = VAR_ACCUM_G
;
226 varTable
["accumb"] = VAR_ACCUM_B
;
227 varTable
["accuma"] = VAR_ACCUM_A
;
228 varTable
["accumrgb"] = VAR_ACCUM_RGB
;
229 varTable
["accumrgba"] = VAR_ACCUM_RGBA
;
230 varTable
["samples"] = VAR_SAMPLES
;
231 varTable
["aux"] = VAR_AUX
;
232 varTable
["db"] = VAR_DB
;
233 varTable
["sb"] = VAR_SB
;
234 varTable
["id"] = VAR_ID
;
235 varTable
["fbcid"] = VAR_FBCID
;
236 varTable
["level"] = VAR_LEVEL
;
237 varTable
["main"] = VAR_MAIN
;
238 varTable
["overlay"] = VAR_OVERLAY
;
239 varTable
["underlay"] = VAR_UNDERLAY
;
240 varTable
["mono"] = VAR_MONO
;
241 varTable
["stereo"] = VAR_STEREO
;
242 varTable
["ms"] = VAR_MS
;
243 varTable
["s"] = VAR_S
;
244 varTable
["z"] = VAR_Z
;
245 varTable
["fast"] = VAR_FAST
;
246 varTable
["conformant"] = VAR_CONFORMANT
;
247 varTable
["transparent"] = VAR_TRANSPARENT
;
248 varTable
["transr"] = VAR_TRANS_R
;
249 varTable
["transg"] = VAR_TRANS_G
;
250 varTable
["transb"] = VAR_TRANS_B
;
251 varTable
["transa"] = VAR_TRANS_A
;
252 varTable
["transci"] = VAR_TRANS_CI
;
253 varTable
["window"] = VAR_WINDOW
;
254 varTable
["pbuffer"] = VAR_PBUFFER
;
255 varTable
["pixmap"] = VAR_PIXMAP
;
256 varTable
["glonly"] = VAR_GL_ONLY
;
257 varTable
["max"] = MAX
;
258 varTable
["min"] = MIN
;
260 varTableInitialized
= true;
261 } // DrawingSurfaceFilter::InitVarTable
263 ///////////////////////////////////////////////////////////////////////////////
264 // FetchVariable - fetch the value of a variable from a
265 // DrawingSurfaceConfig
266 ///////////////////////////////////////////////////////////////////////////////
269 DrawingSurfaceFilter::FetchVariable(const DrawingSurfaceConfig
& c
, Token v
) {
280 return min(c
.r
, min(c
.g
, c
.b
));
282 return min(c
.r
, min(c
.g
, min(c
.b
, c
.a
)));
285 return c
.canCI
? c
.bufSize
: 0;
296 return min(c
.accR
, min(c
.accG
, c
.accB
));
298 return min(c
.accR
, min(c
.accG
, min(c
.accB
, c
.accA
)));
312 # if defined(__X11__)
314 # elif defined(__WIN__)
318 # if defined(GLX_VERSION_1_3)
340 // XXX Can't support this at the moment; have no way to
355 case VAR_TRANSPARENT
:
356 return c
.transparent
;
371 # if defined(GLX_VERSION_1_3)
377 # if defined(__X11__)
384 return !c
.canWinSysRender
;
387 throw InternalError();
391 ///////////////////////////////////////////////////////////////////////////////
392 // GetSymbol - Fetch next symbol from the input string
393 ///////////////////////////////////////////////////////////////////////////////
395 DrawingSurfaceFilter::GetSymbol() {
399 Symbol
= varTable
[lex
.id
];
400 // Note: Because ERROR has value zero in the
401 // Token enumeration, if the user provides a
402 // variable that is not in varTable, then Symbol
403 // will be set to ERROR.
405 throw Syntax("unrecognized variable", lex
.position());
466 throw Syntax("unrecognized symbol", lex
.position());
470 } // DrawingSurfaceFilter::GetSymbol
472 ///////////////////////////////////////////////////////////////////////////////
474 // Syntax: arithExpr -> arithTerm {('+'|'-') arithTerm}
475 ///////////////////////////////////////////////////////////////////////////////
477 DrawingSurfaceFilter::ParseArithExpr() {
478 if (!ParseArithTerm())
482 if (Symbol
== ADD
|| Symbol
== SUB
) {
485 if (!ParseArithTerm())
486 throw Syntax("missing operand of + or -",
494 ///////////////////////////////////////////////////////////////////////////////
496 // Syntax: arithFactor -> ['+'|'-'|'!'] arithPrimary
497 ///////////////////////////////////////////////////////////////////////////////
499 DrawingSurfaceFilter::ParseArithFactor() {
500 if (Symbol
== ADD
|| Symbol
== SUB
|| Symbol
== NOT
) {
503 if (!ParseArithPrimary())
504 throw Syntax("missing operand of unary +, -, or !",
513 return ParseArithPrimary();
516 ///////////////////////////////////////////////////////////////////////////////
518 // Syntax: arithPrimary -> variable | constant | '(' expression ')'
519 ///////////////////////////////////////////////////////////////////////////////
521 DrawingSurfaceFilter::ParseArithPrimary() {
522 if (FIRST_VAR
< Symbol
&& Symbol
< LAST_VAR
) {
528 if (Symbol
== CONSTANT
) {
535 if (Symbol
== LPAREN
) {
537 if (!ParseExpression())
538 throw Syntax("missing expression after (",
540 if (Symbol
== RPAREN
) {
544 throw Syntax("missing )", lex
.position());
550 ///////////////////////////////////////////////////////////////////////////////
552 // Syntax: arithTerm -> arithFactor {('*'|'/'|'%') arithFactor}
553 ///////////////////////////////////////////////////////////////////////////////
555 DrawingSurfaceFilter::ParseArithTerm() {
556 if (!ParseArithFactor())
565 if (!ParseArithFactor())
566 throw Syntax("missing operand of *, /, or %",
574 ///////////////////////////////////////////////////////////////////////////////
576 // Syntax: boolFactor -> arithExpr [('<'|'>'|'<='|'>='|'=='|'!=') arithExpr]
577 ///////////////////////////////////////////////////////////////////////////////
579 DrawingSurfaceFilter::ParseBoolFactor() {
580 if (!ParseArithExpr())
591 if (!ParseArithExpr())
592 throw Syntax("missing operand of comparison",
600 ///////////////////////////////////////////////////////////////////////////////
602 // Syntax: boolTerm -> boolFactor {'&&' boolFactor}
603 ///////////////////////////////////////////////////////////////////////////////
605 DrawingSurfaceFilter::ParseBoolTerm() {
606 if (!ParseBoolFactor())
612 if (!ParseBoolFactor())
613 throw Syntax("missing operand of &&",
621 ///////////////////////////////////////////////////////////////////////////////
623 // Syntax: criteria -> criterion {',' criterion}
624 ///////////////////////////////////////////////////////////////////////////////
626 DrawingSurfaceFilter::ParseCriteria() {
627 /* Process all the user-specified conditions and sort keys: */
628 if (!ParseCriterion())
632 if (Symbol
== SEPARATOR
) {
634 if (!ParseCriterion())
635 throw Syntax("missing criterion after comma",
638 } else if (Symbol
== END
)
641 throw Syntax("expected comma or end of criteria",
646 ///////////////////////////////////////////////////////////////////////////////
648 // Syntax: criterion -> sortKey | expression
649 ///////////////////////////////////////////////////////////////////////////////
651 DrawingSurfaceFilter::ParseCriterion() {
654 return ParseExpression();
657 ///////////////////////////////////////////////////////////////////////////////
659 // Syntax: expression -> boolTerm {'||' boolTerm}
660 ///////////////////////////////////////////////////////////////////////////////
662 DrawingSurfaceFilter::ParseExpression() {
663 if (!ParseBoolTerm())
669 if (!ParseBoolTerm())
670 throw Syntax("missing operand of ||",
678 ///////////////////////////////////////////////////////////////////////////////
680 // Syntax: sortKey -> ('max'|'min') variable
681 ///////////////////////////////////////////////////////////////////////////////
683 DrawingSurfaceFilter::ParseSortKey() {
684 if (Symbol
== MAX
|| Symbol
== MIN
) {
687 if (FIRST_VAR
< Symbol
&& Symbol
< LAST_VAR
) {
690 // When sorting, eliminate visuals with a zero value
691 // for the key. This is hard to justify on grounds
692 // of orthogonality, but it seems to yield the right
693 // behavior (especially for ``min'').
699 throw Syntax("missing variable name after sort key",
704 } // DrawingSurfaceFilter::ParseSortKey