1 // Copyright 2012 Intel Corporation
3 // All rights reserved.
5 // Redistribution and use in source and binary forms, with or without
6 // modification, are permitted provided that the following conditions are met:
8 // - Redistributions of source code must retain the above copyright notice, this
9 // list of conditions and the following disclaimer.
11 // - Redistributions in binary form must reproduce the above copyright notice,
12 // this list of conditions and the following disclaimer in the documentation
13 // and/or other materials provided with the distribution.
15 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
16 // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
17 // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
18 // DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
19 // FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
20 // DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
21 // SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
22 // CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
23 // OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
24 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
30 #include "wcore_attrib_list.h"
31 #include "wcore_config_attrs.h"
32 #include "wcore_error.h"
33 #include "wcore_util.h"
36 DEFAULT_ACCUM_BUFFER
= false,
37 DEFAULT_DOUBLE_BUFFERED
= true,
38 DEFAULT_SAMPLE_BUFFERS
= false,
42 check_keys(const int32_t attrib_list
[])
44 if (attrib_list
== NULL
)
47 for (int32_t i
= 0; attrib_list
[i
]; i
+= 2) {
48 int32_t key
= attrib_list
[i
];
51 case WAFFLE_CONTEXT_API
:
52 case WAFFLE_CONTEXT_MAJOR_VERSION
:
53 case WAFFLE_CONTEXT_MINOR_VERSION
:
54 case WAFFLE_CONTEXT_PROFILE
:
55 case WAFFLE_CONTEXT_FORWARD_COMPATIBLE
:
56 case WAFFLE_CONTEXT_DEBUG
:
57 case WAFFLE_CONTEXT_ROBUST_ACCESS
:
59 case WAFFLE_GREEN_SIZE
:
60 case WAFFLE_BLUE_SIZE
:
61 case WAFFLE_ALPHA_SIZE
:
62 case WAFFLE_DEPTH_SIZE
:
63 case WAFFLE_STENCIL_SIZE
:
65 case WAFFLE_SAMPLE_BUFFERS
:
66 case WAFFLE_DOUBLE_BUFFERED
:
67 case WAFFLE_ACCUM_BUFFER
:
70 wcore_errorf(WAFFLE_ERROR_BAD_ATTRIBUTE
,
71 "unrecognized attribute 0x%x at attrib_list[%d]",
81 parse_bool(const int32_t attrib_list
[], int32_t attrib_name
,
82 bool *value
, bool default_value
)
86 wcore_attrib_list32_get_with_default(attrib_list
, attrib_name
,
87 &raw_value
, default_value
);
89 if (raw_value
== WAFFLE_DONT_CARE
) {
90 *value
= default_value
;
91 } else if (raw_value
== true || raw_value
== false) {
94 wcore_errorf(WAFFLE_ERROR_BAD_ATTRIBUTE
,
95 "%s has bad value 0x%x. "
96 "Must be true(1), false(0), or WAFFLE_DONT_CARE(-1)",
97 wcore_enum_to_string(attrib_name
), raw_value
);
105 parse_context_api(struct wcore_config_attrs
*attrs
,
106 const int32_t attrib_list
[])
110 found
= wcore_attrib_list32_get(attrib_list
,
111 WAFFLE_CONTEXT_API
, &attrs
->context_api
);
113 wcore_errorf(WAFFLE_ERROR_BAD_ATTRIBUTE
,
114 "required attribute WAFFLE_CONTEXT_API is missing");
118 switch (attrs
->context_api
) {
119 case WAFFLE_CONTEXT_OPENGL
:
120 case WAFFLE_CONTEXT_OPENGL_ES1
:
121 case WAFFLE_CONTEXT_OPENGL_ES2
:
122 case WAFFLE_CONTEXT_OPENGL_ES3
:
125 wcore_errorf(WAFFLE_ERROR_BAD_ATTRIBUTE
,
126 "WAFFLE_CONTEXT_API has bad value %#x",
135 set_context_version_default(struct wcore_config_attrs
*attrs
)
137 switch (attrs
->context_api
) {
138 case WAFFLE_CONTEXT_OPENGL
:
139 attrs
->context_major_version
= 1;
140 attrs
->context_minor_version
= 0;
142 case WAFFLE_CONTEXT_OPENGL_ES1
:
143 attrs
->context_major_version
= 1;
144 attrs
->context_minor_version
= 0;
146 case WAFFLE_CONTEXT_OPENGL_ES2
:
147 attrs
->context_major_version
= 2;
148 attrs
->context_minor_version
= 0;
150 case WAFFLE_CONTEXT_OPENGL_ES3
:
151 attrs
->context_major_version
= 3;
152 attrs
->context_minor_version
= 0;
161 parse_context_version(struct wcore_config_attrs
*attrs
,
162 const int32_t attrib_list
[])
164 wcore_attrib_list32_get(attrib_list
, WAFFLE_CONTEXT_MAJOR_VERSION
,
165 &attrs
->context_major_version
);
166 wcore_attrib_list32_get(attrib_list
, WAFFLE_CONTEXT_MINOR_VERSION
,
167 &attrs
->context_minor_version
);
169 if (attrs
->context_major_version
< 1) {
170 wcore_errorf(WAFFLE_ERROR_BAD_ATTRIBUTE
,
171 "WAFFLE_CONTEXT_MAJOR_VERSION must be >= 1");
175 if (attrs
->context_minor_version
< 0) {
176 wcore_errorf(WAFFLE_ERROR_BAD_ATTRIBUTE
,
177 "WAFFLE_CONTEXT_MINOR_VERSION must be >= 0");
184 set_context_profile_default(struct wcore_config_attrs
*attrs
)
186 switch (attrs
->context_api
) {
187 case WAFFLE_CONTEXT_OPENGL
:
188 if (wcore_config_attrs_version_ge(attrs
, 32)) {
189 attrs
->context_profile
= WAFFLE_CONTEXT_CORE_PROFILE
;
192 attrs
->context_profile
= WAFFLE_NONE
;
195 case WAFFLE_CONTEXT_OPENGL_ES1
:
196 case WAFFLE_CONTEXT_OPENGL_ES2
:
197 case WAFFLE_CONTEXT_OPENGL_ES3
:
198 attrs
->context_profile
= WAFFLE_NONE
;
209 parse_context_profile(struct wcore_config_attrs
*attrs
,
210 const int32_t attrib_list
[])
212 wcore_attrib_list32_get(attrib_list
, WAFFLE_CONTEXT_PROFILE
,
213 &attrs
->context_profile
);
215 switch (attrs
->context_api
) {
216 case WAFFLE_CONTEXT_OPENGL
:
217 if (wcore_config_attrs_version_ge(attrs
, 32)
218 && attrs
->context_profile
!= WAFFLE_CONTEXT_CORE_PROFILE
219 && attrs
->context_profile
!= WAFFLE_CONTEXT_COMPATIBILITY_PROFILE
) {
220 wcore_errorf(WAFFLE_ERROR_BAD_ATTRIBUTE
,
221 "for OpenGL >= 3.2, "
222 "WAFFLE_CONTEXT_PROFILE must be either "
223 "WAFFLE_CONTEXT_CORE_PROFILE or "
224 "WAFFLE_CONTEXT_COMPATIBILITY_PROFILE");
227 else if (wcore_config_attrs_version_lt(attrs
, 32)
228 && attrs
->context_profile
!= WAFFLE_NONE
) {
229 wcore_errorf(WAFFLE_ERROR_BAD_ATTRIBUTE
,
230 "for OpenGL < 3.2, WAFFLE_CONTEXT_PROFILE must be "
235 case WAFFLE_CONTEXT_OPENGL_ES1
:
236 case WAFFLE_CONTEXT_OPENGL_ES2
:
237 case WAFFLE_CONTEXT_OPENGL_ES3
:
238 if (attrs
->context_profile
!= WAFFLE_NONE
) {
239 wcore_errorf(WAFFLE_ERROR_BAD_ATTRIBUTE
,
240 "for OpenGL ES, WAFFLE_CONTEXT_PROFILE must be "
254 parse_context_forward_compatible(struct wcore_config_attrs
*attrs
,
255 const int32_t attrib_list
[])
257 if (!parse_bool(attrib_list
, WAFFLE_CONTEXT_FORWARD_COMPATIBLE
,
258 &attrs
->context_forward_compatible
, false)) {
262 if (!attrs
->context_forward_compatible
) {
263 /* It's always valid to request a non-forward-compatible context. */
267 if (attrs
->context_api
!= WAFFLE_CONTEXT_OPENGL
) {
268 wcore_errorf(WAFFLE_ERROR_BAD_ATTRIBUTE
,
269 "To request a forward-compatible context, the context "
270 "API must be WAFFLE_CONTEXT_OPENGL");
275 if (wcore_config_attrs_version_lt(attrs
, 30)) {
276 wcore_errorf(WAFFLE_ERROR_BAD_ATTRIBUTE
,
277 "To request a forward-compatible context, the context "
278 "version must be at least 3.0");
286 set_misc_defaults(struct wcore_config_attrs
*attrs
)
288 // Per the GLX [1] and EGL [2] specs, the default value of each size
289 // attribute and `samples` is 0.
291 // [1] GLX 1.4 spec (2005.12.16), Table 3.4
292 // [2] EGL 1.4 spec (2011.04.06), Table 3.4
294 attrs
->context_debug
= false;
295 attrs
->context_robust
= false;
297 attrs
->rgba_size
= 0;
299 attrs
->green_size
= 0;
300 attrs
->blue_size
= 0;
301 attrs
->alpha_size
= 0;
302 attrs
->depth_size
= 0;
303 attrs
->stencil_size
= 0;
304 attrs
->sample_buffers
= 0;
306 attrs
->double_buffered
= true;
307 attrs
->accum_buffer
= false;
313 parse_misc(struct wcore_config_attrs
*attrs
,
314 const int32_t attrib_list
[])
316 for (int32_t i
= 0; attrib_list
[i
]; i
+= 2) {
317 int32_t key
= attrib_list
[i
+ 0];
318 int32_t value
= attrib_list
[i
+ 1];
322 #define CASE_INT(enum_name, struct_memb) \
325 wcore_errorf(WAFFLE_ERROR_BAD_ATTRIBUTE, \
326 #enum_name " has bad value %d", value); \
331 * Pass WAFFLE_DONT_CARE to platform module. \
333 * From the GLX 1.4 (2005.12.16) spec: \
334 * GLX_DONT_CARE may be specified for all \
335 * attributes except GLX_LEVEL. \
337 * From the EGL 1.4 (2011.04.06) spec: \
338 * EGL_DONT_CARE may be specified for all \
339 * attributes except EGL_LEVEL and \
340 * EGL_MATCH_NATIVE_PIXMAP. \
342 attrs->struct_memb = value; \
346 #define CASE_BOOL(enum_name, struct_memb, default_value) \
348 if (!parse_bool(attrib_list, enum_name, \
349 &attrs->struct_memb, default_value)) { \
354 case WAFFLE_CONTEXT_API
:
355 case WAFFLE_CONTEXT_MAJOR_VERSION
:
356 case WAFFLE_CONTEXT_MINOR_VERSION
:
357 case WAFFLE_CONTEXT_PROFILE
:
358 case WAFFLE_CONTEXT_FORWARD_COMPATIBLE
:
359 // These keys have already been parsed.
362 CASE_INT(WAFFLE_RED_SIZE
, red_size
)
363 CASE_INT(WAFFLE_GREEN_SIZE
, green_size
)
364 CASE_INT(WAFFLE_BLUE_SIZE
, blue_size
)
365 CASE_INT(WAFFLE_ALPHA_SIZE
, alpha_size
)
366 CASE_INT(WAFFLE_DEPTH_SIZE
, depth_size
)
367 CASE_INT(WAFFLE_STENCIL_SIZE
, stencil_size
)
368 CASE_INT(WAFFLE_SAMPLES
, samples
)
370 CASE_BOOL(WAFFLE_CONTEXT_DEBUG
, context_debug
, false);
371 CASE_BOOL(WAFFLE_CONTEXT_ROBUST_ACCESS
, context_robust
, false);
372 CASE_BOOL(WAFFLE_SAMPLE_BUFFERS
, sample_buffers
, DEFAULT_SAMPLE_BUFFERS
);
373 CASE_BOOL(WAFFLE_DOUBLE_BUFFERED
, double_buffered
, DEFAULT_DOUBLE_BUFFERED
);
374 CASE_BOOL(WAFFLE_ACCUM_BUFFER
, accum_buffer
, DEFAULT_ACCUM_BUFFER
);
377 wcore_error_internal("%s", "bad attribute key should have "
378 "been found by check_keys()");
387 // Calculate rgb_size.
389 if (attrs
->red_size
!= WAFFLE_DONT_CARE
)
390 attrs
->rgb_size
+= attrs
->red_size
;
391 if (attrs
->green_size
!= WAFFLE_DONT_CARE
)
392 attrs
->rgb_size
+= attrs
->green_size
;
393 if (attrs
->blue_size
!= WAFFLE_DONT_CARE
)
394 attrs
->rgb_size
+= attrs
->blue_size
;
396 // Calculate rgba_size.
397 attrs
->rgba_size
= attrs
->rgb_size
;
398 if (attrs
->alpha_size
!= WAFFLE_DONT_CARE
)
399 attrs
->rgba_size
+= attrs
->alpha_size
;
405 check_final(struct wcore_config_attrs
*attrs
)
407 if (attrs
->context_api
== WAFFLE_CONTEXT_OPENGL
408 && attrs
->context_profile
== WAFFLE_CONTEXT_CORE_PROFILE
409 && wcore_config_attrs_version_ge(attrs
, 32)
410 && attrs
->accum_buffer
) {
411 wcore_errorf(WAFFLE_ERROR_BAD_ATTRIBUTE
,
412 "%s", "WAFFLE_ACCUM_BUFFER must be false for"
413 "OpenGL Core profile");
421 wcore_config_attrs_parse(
422 const int32_t waffle_attrib_list
[],
423 struct wcore_config_attrs
*attrs
)
425 memset(attrs
, 0, sizeof(*attrs
));
427 if (!check_keys(waffle_attrib_list
))
430 if (!parse_context_api(attrs
, waffle_attrib_list
))
433 if (!set_context_version_default(attrs
))
436 if (!parse_context_version(attrs
, waffle_attrib_list
))
439 if (!set_context_profile_default(attrs
))
442 if (!parse_context_profile(attrs
, waffle_attrib_list
))
445 if (!parse_context_forward_compatible(attrs
, waffle_attrib_list
))
448 if (!set_misc_defaults(attrs
))
451 if (!parse_misc(attrs
, waffle_attrib_list
))
454 if (!check_final(attrs
))
461 wcore_config_attrs_version_eq(
462 const struct wcore_config_attrs
*attrs
,
466 attrs
->context_major_version
== (merged_version
/ 10) &&
467 attrs
->context_minor_version
== (merged_version
% 10);
471 wcore_config_attrs_version_gt(
472 const struct wcore_config_attrs
*attrs
,
476 attrs
->context_major_version
> (merged_version
/ 10) ||
477 (attrs
->context_major_version
== (merged_version
/ 10) &&
478 attrs
->context_minor_version
> (merged_version
% 10));
482 wcore_config_attrs_version_ge(
483 const struct wcore_config_attrs
*attrs
,
487 attrs
->context_major_version
> (merged_version
/ 10) ||
488 (attrs
->context_major_version
== (merged_version
/ 10) &&
489 attrs
->context_minor_version
>= (merged_version
% 10));
493 wcore_config_attrs_version_lt(
494 const struct wcore_config_attrs
*attrs
,
497 return !wcore_config_attrs_version_ge(attrs
, merged_version
);
501 wcore_config_attrs_version_le(
502 const struct wcore_config_attrs
*attrs
,
505 return !wcore_config_attrs_version_gt(attrs
, merged_version
);