gbm: factor out gbm_window_{init,teardown}
[mesa-waffle.git] / src / waffle / core / wcore_config_attrs.c
blob739fabd0300acedf8b164d8a399c3f2d15f9692b
1 // Copyright 2012 Intel Corporation
2 //
3 // All rights reserved.
4 //
5 // Redistribution and use in source and binary forms, with or without
6 // modification, are permitted provided that the following conditions are met:
7 //
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.
26 #include <assert.h>
27 #include <stdlib.h>
28 #include <string.h>
30 #include "wcore_attrib_list.h"
31 #include "wcore_config_attrs.h"
32 #include "wcore_error.h"
33 #include "wcore_util.h"
35 enum {
36 DEFAULT_ACCUM_BUFFER = false,
37 DEFAULT_DOUBLE_BUFFERED = true,
38 DEFAULT_SAMPLE_BUFFERS = false,
41 static bool
42 check_keys(const int32_t attrib_list[])
44 if (attrib_list == NULL)
45 return true;
47 for (int32_t i = 0; attrib_list[i]; i += 2) {
48 int32_t key = attrib_list[i];
50 switch (key) {
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:
58 case WAFFLE_RED_SIZE:
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:
64 case WAFFLE_SAMPLES:
65 case WAFFLE_SAMPLE_BUFFERS:
66 case WAFFLE_DOUBLE_BUFFERED:
67 case WAFFLE_ACCUM_BUFFER:
68 break;
69 default:
70 wcore_errorf(WAFFLE_ERROR_BAD_ATTRIBUTE,
71 "unrecognized attribute 0x%x at attrib_list[%d]",
72 key, i);
73 return false;
77 return true;
80 static bool
81 parse_bool(const int32_t attrib_list[], int32_t attrib_name,
82 bool *value, bool default_value)
84 int32_t raw_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) {
92 *value = raw_value;
93 } else {
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);
98 return false;
101 return true;
104 static bool
105 parse_context_api(struct wcore_config_attrs *attrs,
106 const int32_t attrib_list[])
108 bool found;
110 found = wcore_attrib_list32_get(attrib_list,
111 WAFFLE_CONTEXT_API, &attrs->context_api);
112 if (!found) {
113 wcore_errorf(WAFFLE_ERROR_BAD_ATTRIBUTE,
114 "required attribute WAFFLE_CONTEXT_API is missing");
115 return false;
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:
123 break;
124 default:
125 wcore_errorf(WAFFLE_ERROR_BAD_ATTRIBUTE,
126 "WAFFLE_CONTEXT_API has bad value %#x",
127 attrs->context_api);
128 return false;
131 return true;
134 static bool
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;
141 return true;
142 case WAFFLE_CONTEXT_OPENGL_ES1:
143 attrs->context_major_version = 1;
144 attrs->context_minor_version = 0;
145 return true;
146 case WAFFLE_CONTEXT_OPENGL_ES2:
147 attrs->context_major_version = 2;
148 attrs->context_minor_version = 0;
149 return true;
150 case WAFFLE_CONTEXT_OPENGL_ES3:
151 attrs->context_major_version = 3;
152 attrs->context_minor_version = 0;
153 return true;
154 default:
155 assert(false);
156 return false;
160 static bool
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");
172 return false;
175 if (attrs->context_minor_version < 0) {
176 wcore_errorf(WAFFLE_ERROR_BAD_ATTRIBUTE,
177 "WAFFLE_CONTEXT_MINOR_VERSION must be >= 0");
178 return false;
180 return true;
183 static bool
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;
191 else {
192 attrs->context_profile = WAFFLE_NONE;
194 break;
195 case WAFFLE_CONTEXT_OPENGL_ES1:
196 case WAFFLE_CONTEXT_OPENGL_ES2:
197 case WAFFLE_CONTEXT_OPENGL_ES3:
198 attrs->context_profile = WAFFLE_NONE;
199 break;
200 default:
201 assert(false);
202 return false;
205 return true;
208 static bool
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");
225 return false;
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 "
231 "WAFFLE_NONE");
232 return false;
234 break;
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 "
241 "WAFFLE_NONE");
242 return false;
244 break;
245 default:
246 assert(false);
247 return false;
250 return true;
253 static bool
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)) {
259 return false;
262 if (!attrs->context_forward_compatible) {
263 /* It's always valid to request a non-forward-compatible context. */
264 return true;
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");
271 return false;
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");
279 return false;
282 return true;
285 static bool
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;
298 attrs->red_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;
305 attrs->samples = 0;
306 attrs->double_buffered = true;
307 attrs->accum_buffer = false;
309 return true;
312 static bool
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];
320 switch (key) {
322 #define CASE_INT(enum_name, struct_memb) \
323 case enum_name: \
324 if (value < -1) { \
325 wcore_errorf(WAFFLE_ERROR_BAD_ATTRIBUTE, \
326 #enum_name " has bad value %d", value); \
327 return false; \
329 else { \
330 /* \
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. \
341 */ \
342 attrs->struct_memb = value; \
344 break;
346 #define CASE_BOOL(enum_name, struct_memb, default_value) \
347 case enum_name: \
348 if (!parse_bool(attrib_list, enum_name, \
349 &attrs->struct_memb, default_value)) { \
350 return false; \
352 break;
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.
360 break;
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);
376 default:
377 wcore_error_internal("%s", "bad attribute key should have "
378 "been found by check_keys()");
379 return false;
382 #undef CASE_INT
383 #undef CASE_BOOL
387 // Calculate rgb_size.
388 attrs->rgb_size = 0;
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;
401 return true;
404 static bool
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");
414 return false;
417 return true;
420 bool
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))
428 return false;
430 if (!parse_context_api(attrs, waffle_attrib_list))
431 return false;
433 if (!set_context_version_default(attrs))
434 return false;
436 if (!parse_context_version(attrs, waffle_attrib_list))
437 return false;
439 if (!set_context_profile_default(attrs))
440 return false;
442 if (!parse_context_profile(attrs, waffle_attrib_list))
443 return false;
445 if (!parse_context_forward_compatible(attrs, waffle_attrib_list))
446 return false;
448 if (!set_misc_defaults(attrs))
449 return false;
451 if (!parse_misc(attrs, waffle_attrib_list))
452 return false;
454 if (!check_final(attrs))
455 return false;
457 return true;
460 bool
461 wcore_config_attrs_version_eq(
462 const struct wcore_config_attrs *attrs,
463 int merged_version)
465 return
466 attrs->context_major_version == (merged_version / 10) &&
467 attrs->context_minor_version == (merged_version % 10);
470 bool
471 wcore_config_attrs_version_gt(
472 const struct wcore_config_attrs *attrs,
473 int merged_version)
475 return
476 attrs->context_major_version > (merged_version / 10) ||
477 (attrs->context_major_version == (merged_version / 10) &&
478 attrs->context_minor_version > (merged_version % 10));
481 bool
482 wcore_config_attrs_version_ge(
483 const struct wcore_config_attrs *attrs,
484 int merged_version)
486 return
487 attrs->context_major_version > (merged_version / 10) ||
488 (attrs->context_major_version == (merged_version / 10) &&
489 attrs->context_minor_version >= (merged_version % 10));
492 bool
493 wcore_config_attrs_version_lt(
494 const struct wcore_config_attrs *attrs,
495 int merged_version)
497 return !wcore_config_attrs_version_ge(attrs, merged_version);
500 bool
501 wcore_config_attrs_version_le(
502 const struct wcore_config_attrs *attrs,
503 int merged_version)
505 return !wcore_config_attrs_version_gt(attrs, merged_version);