1 /**************************************************************************
3 * Copyright 2013-2014 RAD Game Tools and Valve Software
6 * Permission is hereby granted, free of charge, to any person obtaining a copy
7 * of this software and associated documentation files (the "Software"), to deal
8 * in the Software without restriction, including without limitation the rights
9 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10 * copies of the Software, and to permit persons to whom the Software is
11 * furnished to do so, subject to the following conditions:
13 * The above copyright notice and this permission notice shall be included in
14 * all copies or substantial portions of the Software.
16 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
24 **************************************************************************/
26 // File: vogl_context_info.cpp
27 #include "vogl_context_info.h"
28 #include "vogl_entrypoints.h"
30 #include "vogl_console.h"
34 int vogl_determine_attrib_list_array_size(const int *attrib_list)
47 int key = attrib_list[n];
52 int val = attrib_list[n];
53 VOGL_NOTE_UNUSED(val);
61 vogl_context_attribs::vogl_context_attribs()
66 vogl_context_attribs::vogl_context_attribs(const int *pAttribs)
73 vogl_context_attribs::vogl_context_attribs(const int *pAttribs, uint num_attribs)
77 init(pAttribs, num_attribs);
80 vogl_context_attribs::vogl_context_attribs(const attrib_vec &vec)
84 init(vec.get_ptr(), vec.size());
87 void vogl_context_attribs::init(const int *pAttribs)
91 init(pAttribs, vogl_determine_attrib_list_array_size(pAttribs));
94 void vogl_context_attribs::init(const int *pAttribs, uint num_attribs)
100 if ((pAttribs) && (num_attribs))
102 m_attribs.append(pAttribs, num_attribs);
106 void vogl_context_attribs::init(const attrib_vec &vec)
110 init(vec.get_ptr(), vec.size());
113 int vogl_context_attribs::find_value_ofs(int key_to_find) const
118 while (ofs < m_attribs.size())
120 int key = m_attribs[ofs];
124 if (++ofs >= m_attribs.size())
127 if (key == key_to_find)
136 bool vogl_context_attribs::get_value(int key_to_find, int &val) const
140 int ofs = find_value_ofs(key_to_find);
147 val = m_attribs[ofs];
151 bool vogl_context_attribs::check() const
155 if (!m_attribs.size())
158 if (m_attribs.back() != 0)
164 int key = m_attribs[ofs];
169 if (ofs >= m_attribs.size())
173 } while (ofs < m_attribs.size());
178 bool vogl_context_attribs::serialize(vogl::json_node &node) const
182 json_node &attribs_array = node.add_array("attribs");
183 for (uint i = 0; i < m_attribs.size(); i++)
184 attribs_array.add_value(m_attribs[i]);
189 bool vogl_context_attribs::deserialize(const vogl::json_node &node)
193 const json_node *pAttribs_array = node.find_child_array("attribs");
197 m_attribs.resize(pAttribs_array->size());
198 for (uint i = 0; i < pAttribs_array->size(); i++)
199 m_attribs[i] = pAttribs_array->value_as_int(i);
204 void vogl_context_attribs::add_key(int key, int value)
208 if (m_attribs.size())
210 VOGL_ASSERT(m_attribs.back() == 0);
211 if (m_attribs.back() == 0)
212 m_attribs.resize(m_attribs.size() - 1);
215 m_attribs.push_back(key);
216 m_attribs.push_back(value);
217 m_attribs.push_back(0);
220 vogl_context_info::vogl_context_info()
221 : m_version(VOGL_GL_VERSION_UNKNOWN),
222 m_forward_compatible(false),
223 m_core_profile(false),
224 m_debug_context(false),
225 m_max_vertex_attribs(0),
226 m_max_texture_coords(0),
227 m_max_texture_units(0),
228 m_max_texture_image_units(0),
229 m_max_combined_texture_coords(0),
230 m_max_draw_buffers(0),
232 m_max_uniform_buffer_bindings(0),
233 m_max_arb_program_matrices(0),
234 m_max_arb_vertex_program_env_params(0),
235 m_max_arb_fragment_program_env_params(0),
236 m_max_transform_feedback_separate_attribs(0),
242 vogl_context_info::vogl_context_info(const vogl_context_desc &desc)
243 : m_version(VOGL_GL_VERSION_UNKNOWN),
244 m_forward_compatible(false),
245 m_core_profile(false),
246 m_debug_context(false),
247 m_max_vertex_attribs(0),
248 m_max_texture_coords(0),
249 m_max_texture_units(0),
250 m_max_texture_image_units(0),
251 m_max_combined_texture_coords(0),
252 m_max_draw_buffers(0),
254 m_max_uniform_buffer_bindings(0),
255 m_max_arb_program_matrices(0),
256 m_max_arb_vertex_program_env_params(0),
257 m_max_arb_fragment_program_env_params(0),
258 m_max_transform_feedback_separate_attribs(0),
266 void vogl_context_info::query_string(vogl::dynamic_string &str, GLenum name)
270 const char *pStr = reinterpret_cast<const char *>(GL_ENTRYPOINT(glGetString)(name));
271 str.set(pStr ? pStr : "");
273 vogl_check_gl_error();
276 vogl_gl_version_t vogl_context_info::parse_version_string(const vogl::dynamic_string &str)
281 return VOGL_GL_VERSION_UNKNOWN;
283 // major_number.minor_number major_number.minor_number.release_number
284 // release_number can be very large (tens of thousands)
285 // optionally followed by vendor/driver info
287 int major = 0, minor = 0;
288 uint n = sscanf(str.get_ptr(), "%d.%d", &major, &minor);
289 if ((n < 2) || (major < 1) || (minor < 0) || (minor > 255))
291 console::error("%s: Failed parsing GL/GLSL version string \"%s\"!\n", VOGL_METHOD_NAME, str.get_ptr());
293 return VOGL_GL_VERSION_UNKNOWN;
296 return VOGL_CREATE_GL_VERSION(major, minor, 0);
299 // See http://www.opengl.org/registry/specs/ARB/glx_create_context.txt
300 bool vogl_context_info::init(const vogl_context_desc &desc)
306 if (!GL_ENTRYPOINT(glGetString))
311 vogl_check_gl_error();
313 query_string(m_version_str, GL_VERSION);
314 query_string(m_glsl_version_str, GL_SHADING_LANGUAGE_VERSION);
315 query_string(m_vendor_str, GL_VENDOR);
316 query_string(m_renderer_str, GL_RENDERER);
318 // Update btrace with our gl info.
319 btrace_get_glinfo().version_str = m_version_str;
320 btrace_get_glinfo().glsl_version_str = m_glsl_version_str;
321 btrace_get_glinfo().vendor_str = m_vendor_str;
322 btrace_get_glinfo().renderer_str = m_renderer_str;
324 m_version = parse_version_string(m_version_str);
325 m_glsl_version = parse_version_string(m_glsl_version_str);
327 if (vogl_check_gl_error())
329 console::warning("%s: GL error querying context vendor/renderer/version strings!\n", VOGL_METHOD_NAME);
332 m_forward_compatible = false;
333 m_core_profile = false;
334 m_debug_context = false;
336 // glGetInteger is GL >= 3.0 (even if glGetIntegerv can still be non-null on lower version contexts)
337 if ((GL_ENTRYPOINT(glGetIntegerv)) && (m_version >= VOGL_GL_VERSION_3_0))
339 GLint major_vers = -1, minor_vers = -1;
340 GL_ENTRYPOINT(glGetIntegerv)(GL_MAJOR_VERSION, &major_vers);
341 GL_ENTRYPOINT(glGetIntegerv)(GL_MINOR_VERSION, &minor_vers);
343 if (!vogl_check_gl_error())
345 if ((major_vers > 0) && (minor_vers >= 0))
347 vogl_gl_version_t context_version = VOGL_CREATE_GL_VERSION(major_vers, minor_vers, 0);
348 VOGL_ASSERT(m_version == context_version);
349 m_version = context_version;
353 GLint context_flags = 0;
354 GL_ENTRYPOINT(glGetIntegerv)(GL_CONTEXT_FLAGS, &context_flags);
355 if (!vogl_check_gl_error())
357 if (context_flags & GL_CONTEXT_FLAG_DEBUG_BIT)
358 m_debug_context = true;
360 // forward compat is GL >= 3.0
361 if (context_flags & GL_CONTEXT_FLAG_FORWARD_COMPATIBLE_BIT)
362 m_forward_compatible = true;
365 // GL_CONTEXT_PROFILE_MASK is GL 3.2 or greater - (the core profile bit is ignored for context versions requested <v3.2)
366 if (m_version >= VOGL_GL_VERSION_3_2)
368 GLint profile_mask = 0;
369 GL_ENTRYPOINT(glGetIntegerv)(GL_CONTEXT_PROFILE_MASK, &profile_mask);
371 if (!vogl_check_gl_error())
373 if (profile_mask & GL_CONTEXT_CORE_PROFILE_BIT)
375 VOGL_ASSERT((profile_mask & GL_CONTEXT_COMPATIBILITY_PROFILE_BIT) == 0);
376 m_core_profile = true;
382 determine_core_extensions();
384 bool success = query_extensions();
386 m_is_valid = success && (m_version >= VOGL_GL_VERSION_1_0);
388 init_context_limits();
390 vogl_check_gl_error();
395 void vogl_context_info::init_context_limits()
401 m_max_vertex_attribs = vogl_get_gl_integer(GL_MAX_VERTEX_ATTRIBS);
404 m_max_texture_coords = is_core_profile() ? 0 : vogl_get_gl_integer(GL_MAX_TEXTURE_COORDS);
407 m_max_texture_units = is_core_profile() ? 0 : vogl_get_gl_integer(GL_MAX_TEXTURE_UNITS);
410 m_max_texture_image_units = vogl_get_gl_integer(GL_MAX_TEXTURE_IMAGE_UNITS);
413 m_max_combined_texture_coords = vogl_get_gl_integer(GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS);
416 m_max_draw_buffers = (get_version() >= VOGL_GL_VERSION_2_0) ? vogl_get_gl_integer(GL_MAX_DRAW_BUFFERS) : 0;
419 m_max_lights = is_core_profile() ? 0 : vogl_get_gl_integer(GL_MAX_LIGHTS);
422 m_max_uniform_buffer_bindings = vogl_get_gl_integer(GL_MAX_UNIFORM_BUFFER_BINDINGS);
425 m_max_transform_feedback_separate_attribs = (get_version() >= VOGL_GL_VERSION_3_0) ? vogl_get_gl_integer(GL_MAX_TRANSFORM_FEEDBACK_SEPARATE_ATTRIBS) : 0;
428 if (!is_core_profile() && supports_extension("GL_ARB_vertex_program") && GL_ENTRYPOINT(glGetProgramivARB))
430 m_max_arb_program_matrices = vogl_get_gl_integer(GL_MAX_PROGRAM_MATRICES_ARB);
432 GL_ENTRYPOINT(glGetProgramivARB)(GL_VERTEX_PROGRAM_ARB, GL_MAX_PROGRAM_ENV_PARAMETERS_ARB, reinterpret_cast<GLint *>(&m_max_arb_vertex_program_env_params));
435 GL_ENTRYPOINT(glGetProgramivARB)(GL_FRAGMENT_PROGRAM_ARB, GL_MAX_PROGRAM_ENV_PARAMETERS_ARB, reinterpret_cast<GLint *>(&m_max_arb_fragment_program_env_params));
440 bool vogl_context_info::query_extensions()
444 // glGetStringi is available in OpenGL3.0 and newer
445 if (GL_ENTRYPOINT(glGetStringi))
447 GLint num_extensions = 0;
448 GL_ENTRYPOINT(glGetIntegerv)(GL_NUM_EXTENSIONS, &num_extensions);
450 m_extensions.reserve(num_extensions + 200);
452 for (int i = 0; i < num_extensions; i++)
454 const GLubyte *pGLExt = reinterpret_cast<const GLubyte *>(GL_ENTRYPOINT(glGetStringi)(GL_EXTENSIONS, i));
457 m_extensions.enlarge(1)->set(reinterpret_cast<const char *>(pGLExt));
458 m_extensions.back().tolower();
463 // glGetString(GL_EXTENSIONS) is only supported in OpenGL3.0 and older.
464 // It was deprecrated in 3.1, so it is available in a compatibility profile (GL_ARB_compatibility).
465 if (get_version() <= VOGL_GL_VERSION_3_0 || is_compatibility_profile())
467 const char *pExtensions = reinterpret_cast<const char *>(GL_ENTRYPOINT(glGetString)(GL_EXTENSIONS));
470 dynamic_string extensions(pExtensions);
471 dynamic_string_array tokens;
472 extensions.tokenize(" \t", tokens, true);
473 m_extensions.append(tokens);
477 if (GL_ENTRYPOINT(glXQueryExtensionsString))
479 const char *pExtensions = reinterpret_cast<const char *>(GL_ENTRYPOINT(glXQueryExtensionsString)(GL_ENTRYPOINT(glXGetCurrentDisplay)(), 0));
482 dynamic_string extensions(pExtensions);
483 dynamic_string_array tokens;
484 extensions.tokenize(" \t", tokens, true);
485 m_extensions.append(tokens);
489 m_extensions.unique();
494 void vogl_context_info::clear()
500 m_version = VOGL_GL_VERSION_UNKNOWN;
501 m_glsl_version = VOGL_GL_VERSION_UNKNOWN;
503 m_forward_compatible = false;
504 m_core_profile = false;
505 m_debug_context = false;
507 m_version_str.clear();
508 m_glsl_version_str.clear();
509 m_vendor_str.clear();
510 m_renderer_str.clear();
511 m_extensions.clear();
512 m_core_extensions.clear();
514 m_max_vertex_attribs = 0;
515 m_max_texture_coords = 0;
516 m_max_texture_units = 0;
517 m_max_texture_image_units = 0;
518 m_max_combined_texture_coords = 0;
519 m_max_draw_buffers = 0;
521 m_max_uniform_buffer_bindings = 0;
522 m_max_arb_program_matrices = 0;
523 m_max_arb_vertex_program_env_params = 0;
524 m_max_arb_fragment_program_env_params = 0;
525 m_max_transform_feedback_separate_attribs = 0;
530 // I've seen some engines do this, they must have a reason.
531 // Some newer drivers don't report back extensions added to core GL. So make a separate list that contains those extensions.
532 // TODO: I'm not so sure about this whole idea.
533 // TODO: Make sure all this makes sense in core profiles.
534 void vogl_context_info::determine_core_extensions()
541 m_core_extensions.push_back(#x); \
543 if (m_version >= VOGL_GL_VERSION_1_2)
545 ADD_EXT(GL_EXT_texture3D);
546 ADD_EXT(GL_EXT_bgra);
547 ADD_EXT(GL_EXT_packed_pixels);
548 ADD_EXT(GL_EXT_rescale_normal);
549 ADD_EXT(GL_EXT_separate_specular_color);
550 ADD_EXT(GL_SGIS_texture_edge_clamp);
551 ADD_EXT(GL_SGIS_texture_lod);
552 ADD_EXT(GL_EXT_draw_range_elements);
555 if (m_version >= VOGL_GL_VERSION_1_3)
557 ADD_EXT(GL_ARB_texture_compression);
558 ADD_EXT(GL_ARB_texture_cube_map);
559 ADD_EXT(GL_ARB_multisample);
560 ADD_EXT(GL_ARB_multitexture);
561 ADD_EXT(GL_ARB_transpose_matrix);
562 ADD_EXT(GL_ARB_texture_env_add);
563 ADD_EXT(GL_ARB_texture_env_combine);
564 ADD_EXT(GL_ARB_texture_env_dot3);
565 ADD_EXT(GL_ARB_texture_border_clamp);
568 if (m_version >= VOGL_GL_VERSION_1_4)
570 ADD_EXT(GL_EXT_blend_color);
571 ADD_EXT(GL_EXT_blend_minmax);
572 ADD_EXT(GL_EXT_blend_subtract);
573 ADD_EXT(GL_SGIS_generate_mipmap);
574 ADD_EXT(GL_NV_blend_square);
575 ADD_EXT(GL_ARB_depth_texture);
576 ADD_EXT(GL_ARB_shadow);
577 ADD_EXT(GL_EXT_fog_coord);
578 ADD_EXT(GL_EXT_multi_draw_arrays);
579 ADD_EXT(GL_ARB_point_parameters);
580 ADD_EXT(GL_EXT_secondary_color);
581 ADD_EXT(GL_EXT_blend_func_separate);
582 ADD_EXT(GL_EXT_stencil_wrap);
583 ADD_EXT(GL_ARB_texture_env_crossbar);
584 ADD_EXT(GL_EXT_texture_lod_bias);
585 ADD_EXT(GL_ARB_texture_mirrored_repeat);
586 ADD_EXT(GL_ARB_window_pos);
589 if (m_version >= VOGL_GL_VERSION_1_5)
591 ADD_EXT(GL_ARB_vertex_buffer_object);
592 ADD_EXT(GL_ARB_occlusion_query);
593 ADD_EXT(GL_EXT_shadow_funcs);
596 if (m_version >= VOGL_GL_VERSION_2_0)
598 ADD_EXT(GL_ARB_shader_objects);
599 ADD_EXT(GL_ARB_vertex_shader);
600 ADD_EXT(GL_ARB_fragment_shader);
601 ADD_EXT(GL_ARB_shading_language_100);
602 ADD_EXT(GL_ARB_draw_buffers);
603 ADD_EXT(GL_ARB_texture_non_power_of_two);
604 ADD_EXT(GL_ARB_point_sprite);
605 ADD_EXT(GL_EXT_blend_equation_separate);
608 if (m_version >= VOGL_GL_VERSION_2_1)
610 ADD_EXT(GL_EXT_texture_sRGB);
611 ADD_EXT(GL_ARB_pixel_buffer_object);
614 if (m_version >= VOGL_GL_VERSION_3_0)
616 ADD_EXT(GL_EXT_framebuffer_sRGB);
617 ADD_EXT(GL_EXT_gpu_shader4);
618 ADD_EXT(GL_NV_conditional_render);
619 ADD_EXT(GL_ARB_color_buffer_float);
620 ADD_EXT(GL_ARB_depth_buffer_float);
621 ADD_EXT(GL_ARB_texture_float);
622 ADD_EXT(GL_EXT_packed_float);
623 ADD_EXT(GL_EXT_texture_shared_exponent);
624 ADD_EXT(GL_EXT_framebuffer_object);
625 ADD_EXT(GL_NV_half_float);
626 ADD_EXT(GL_EXT_texture_integer);
627 ADD_EXT(GL_EXT_texture_array);
628 ADD_EXT(GL_EXT_packed_depth_stencil);
629 ADD_EXT(GL_EXT_draw_buffers2);
630 ADD_EXT(GL_EXT_texture_compression_rgtc);
631 ADD_EXT(GL_EXT_transform_feedback);
632 ADD_EXT(GL_APPLE_vertex_array_object);
633 ADD_EXT(GL_ARB_half_float_pixel);
634 ADD_EXT(GL_EXT_framebuffer_multisample);
635 ADD_EXT(GL_EXT_framebuffer_blit);
638 if (m_version >= VOGL_GL_VERSION_3_2)
640 ADD_EXT(GL_ARB_sync);
644 m_core_extensions.unique();
647 bool vogl_context_info::serialize(vogl::json_node &node, const vogl_blob_manager &blob_manager) const
657 if (!m_desc.serialize(node, blob_manager))
660 node.add_key_value("version_major", VOGL_GL_VERSION_GET_MAJOR(m_version));
661 node.add_key_value("version_minor", VOGL_GL_VERSION_GET_MINOR(m_version));
662 node.add_key_value("version_patch", VOGL_GL_VERSION_GET_PATCH(m_version));
664 node.add_key_value("glsl_version_major", VOGL_GL_VERSION_GET_MAJOR(m_glsl_version));
665 node.add_key_value("glsl_version_minor", VOGL_GL_VERSION_GET_MINOR(m_glsl_version));
667 node.add_key_value("forward_compatible", m_forward_compatible);
668 node.add_key_value("core_profile", m_core_profile);
669 node.add_key_value("debug_context", m_debug_context);
671 node.add_key_value("version_string", m_version_str);
672 node.add_key_value("glsl_version_string", m_glsl_version_str);
673 node.add_key_value("vendor_string", m_vendor_str);
674 node.add_key_value("renderer_string", m_renderer_str);
676 node.add_key_value("max_vertex_attribs", m_max_vertex_attribs);
677 node.add_key_value("max_texture_coords", m_max_texture_coords);
678 node.add_key_value("max_texture_units", m_max_texture_units);
679 node.add_key_value("max_texture_image_units", m_max_texture_image_units);
680 node.add_key_value("max_combined_texture_coords", m_max_combined_texture_coords);
681 node.add_key_value("max_draw_buffers", m_max_draw_buffers);
682 node.add_key_value("max_lights", m_max_lights);
683 node.add_key_value("max_uniform_buffer_bindings", m_max_uniform_buffer_bindings);
684 node.add_key_value("max_arb_program_matrices", m_max_arb_program_matrices);
685 node.add_key_value("max_arb_vertex_program_env_params", m_max_arb_vertex_program_env_params);
686 node.add_key_value("max_arb_fragment_program_env_params", m_max_arb_fragment_program_env_params);
687 node.add_key_value("max_transform_feedback_separate_attribs", m_max_transform_feedback_separate_attribs);
689 json_node &extensions_array = node.add_array("extensions");
690 for (uint i = 0; i < m_extensions.size(); i++)
691 extensions_array.add_value(m_extensions[i]);
696 bool vogl_context_info::deserialize(const vogl::json_node &node, const vogl_blob_manager &blob_manager)
702 if (!node.is_object())
705 bool success = node.get_value_as_string("version_string", m_version_str);
707 if (!m_desc.deserialize(node, blob_manager))
710 int version_major = 0, version_minor = 0, version_patch = 0;
711 version_major = node.value_as_int("version_major");
712 version_minor = node.value_as_int("version_minor");
713 version_patch = node.value_as_int("version_patch");
714 m_version = VOGL_CREATE_GL_VERSION(version_major, version_minor, version_patch);
716 int glsl_version_major = 0, glsl_version_minor = 0;
717 glsl_version_major = node.value_as_int("glsl_version_major");
718 glsl_version_minor = node.value_as_int("glsl_version_minor");
719 m_glsl_version = VOGL_CREATE_GL_VERSION(glsl_version_major, glsl_version_minor, 0);
721 m_forward_compatible = node.value_as_bool("forward_compatible");
722 m_core_profile = node.value_as_bool("core_profile");
723 m_debug_context = node.value_as_bool("debug_context");
724 m_glsl_version_str = node.value_as_string("glsl_version_string");
725 m_vendor_str = node.value_as_string("vendor_string");
726 m_renderer_str = node.value_as_string("renderer_string");
728 m_max_vertex_attribs = node.value_as_uint32("max_vertex_attribs");
729 m_max_texture_coords = node.value_as_uint32("max_texture_coords");
730 m_max_texture_units = node.value_as_uint32("max_texture_units");
731 m_max_texture_image_units = node.value_as_uint32("max_texture_image_units");
732 m_max_combined_texture_coords = node.value_as_uint32("max_combined_texture_coords");
733 m_max_draw_buffers = node.value_as_uint32("max_draw_buffers");
734 m_max_lights = node.value_as_uint32("max_lights");
735 m_max_uniform_buffer_bindings = node.value_as_uint32("max_uniform_buffer_bindings");
736 m_max_arb_program_matrices = node.value_as_uint32("max_arb_program_matrices");
737 m_max_arb_vertex_program_env_params = node.value_as_uint32("max_arb_vertex_program_env_params");
738 m_max_arb_fragment_program_env_params = node.value_as_uint32("max_arb_fragment_program_env_params");
739 m_max_transform_feedback_separate_attribs = node.value_as_uint32("max_transform_feedback_separate_attribs");
741 const json_node *pExtensions_array = node.find_child_array("extensions");
742 if (pExtensions_array)
744 m_extensions.resize(pExtensions_array->size());
746 for (uint i = 0; i < pExtensions_array->size(); i++)
747 m_extensions[i] = pExtensions_array->get_value(i).as_string();
749 m_extensions.unique();
752 determine_core_extensions();
754 VOGL_ASSERT(success);
756 m_is_valid = success;
761 bool vogl_context_info::supports_extension(const char *pExt) const
771 vogl::dynamic_string ext(pExt);
773 if (!ext.begins_with("GL_", true))
775 vogl_warning_printf("%s: Extension does not begin with \"GL_\" prefix, was this intended?\n", VOGL_METHOD_NAME);
779 // Let's see if this is ever necessary. Also not sure how it interacts with core profiles, yet.
780 if (m_core_extensions.find_sorted(ext) >= 0)
784 return m_extensions.find_sorted(ext) >= 0;