third_party/virtualbox/src/VBox/Devices/Graphics/DevVGA-SVGA3d-ogl.cpp
/**
 * Gathers the GL_EXTENSIONS list, storing it as a space padded list at
 * @a ppszExtensions.
 *
 * @returns VINF_SUCCESS or VERR_NO_STR_MEMORY
 * @param   ppszExtensions      Pointer to the string pointer. Free with RTStrFree.
 * @param   fGLProfileVersion   The OpenGL profile version.
 */
Gathers the GL_EXTENSIONS list, storing it as a space padded list at
@a ppszExtensions.

@returns VINF_SUCCESS or VERR_NO_STR_MEMORY
@param   ppszExtensions      Pointer to the string pointer.
Gathers the GL_EXTENSIONS list storing it as a space padded list at @a ppszExtensions . @returns VINF_SUCCESS or VERR_NO_STR_MEMORY @param ppszExtensions Pointer to the string pointer .
static int vmsvga3dGatherExtensions(char **ppszExtensions, float fGLProfileVersion)
{
    int rc;
    *ppszExtensions = NULL;
    const char *pszExtensions = (const char *)glGetString(GL_EXTENSIONS);
    if (pszExtensions)
    {
        rc = RTStrAAppendExN(ppszExtensions, 3, " ", (size_t)1, pszExtensions, RTSTR_MAX, " ", (size_t)1);
        AssertLogRelRCReturn(rc, rc);
    }
    else
    {
#ifndef GL_NUM_EXTENSIONS
# define GL_NUM_EXTENSIONS 0x821D
#endif
        GLint cExtensions = 1024;
        glGetIntegerv(GL_NUM_EXTENSIONS, &cExtensions);
        Assert(cExtensions != 1024);
        PFNGLGETSTRINGIPROC pfnGlGetStringi = (PFNGLGETSTRINGIPROC)OGLGETPROCADDRESS("glGetStringi");
        AssertLogRelReturn(pfnGlGetStringi, VERR_NOT_SUPPORTED);
        rc = RTStrAAppend(ppszExtensions, " ");
        for (GLint i = 0; RT_SUCCESS(rc) && i < cExtensions; i++)
        {
            const char *pszExt = (const char *)pfnGlGetStringi(GL_EXTENSIONS, i);
            if (pszExt)
                rc = RTStrAAppendExN(ppszExtensions, 2, pfnGlGetStringi(GL_EXTENSIONS, i), RTSTR_MAX, " ", (size_t)1);
        }
        AssertRCReturn(rc, rc);
    }
#if 1
    static const struct
    {
        float fGLVersion;
        const char *pszzExtensions;
    } s_aPromotedExtensions[] =
    {
        {
            1.1f,
            " GL_EXT_vertex_array \0"
            " GL_EXT_polygon_offset \0"
            " GL_EXT_blend_logic_op \0"
            " GL_EXT_texture \0"
            " GL_EXT_copy_texture \0"
            " GL_EXT_subtexture \0"
            " GL_EXT_texture_object \0"
            " GL_ARB_framebuffer_object \0"
            " GL_ARB_map_buffer_range \0"
            " GL_ARB_vertex_array_object \0"
            "\0"
        },
        {
            1.2f,
            " EXT_texture3D \0"
            " EXT_bgra \0"
            " EXT_packed_pixels \0"
            " EXT_rescale_normal \0"
            " EXT_separate_specular_color \0"
            " SGIS_texture_edge_clamp \0"
            " SGIS_texture_lod \0"
            " EXT_draw_range_elements \0"
            "\0"
        },
        {
            1.3f,
            " GL_ARB_texture_compression \0"
            " GL_ARB_texture_cube_map \0"
            " GL_ARB_multisample \0"
            " GL_ARB_multitexture \0"
            " GL_ARB_texture_env_add \0"
            " GL_ARB_texture_env_combine \0"
            " GL_ARB_texture_env_dot3 \0"
            " GL_ARB_texture_border_clamp \0"
            " GL_ARB_transpose_matrix \0"
            "\0"
        },
        {
            1.5f,
            " GL_SGIS_generate_mipmap \0"
            " GL_ARB_depth_texture \0"
            " GL_ARB_shadow \0"
            " GL_EXT_fog_coord \0"
            " GL_EXT_multi_draw_arrays \0"
            " GL_ARB_point_parameters \0"
            " GL_EXT_secondary_color \0"
            " GL_EXT_blend_func_separate \0"
            " GL_EXT_stencil_wrap \0"
            " GL_ARB_texture_env_crossbar \0"
            " GL_EXT_texture_lod_bias \0"
            " GL_ARB_texture_mirrored_repeat \0"
            " GL_ARB_window_pos \0"
            "\0"
        },
        {
            1.6f,
            " GL_ARB_vertex_buffer_object \0"
            " GL_ARB_occlusion_query \0"
            " GL_EXT_shadow_funcs \0"
        },
        {
            2.0f,
            " GL_ARB_shader_objects \0" 
            " GL_ARB_vertex_shader \0" 
            " GL_ARB_fragment_shader \0" 
            " GL_ARB_shading_language_100 \0" 
            " GL_ARB_draw_buffers \0"
            " GL_ARB_texture_non_power_of_two \0"
            " GL_ARB_point_sprite \0"
            " GL_ATI_separate_stencil \0"
            " GL_EXT_stencil_two_side \0"
            "\0"
        },
        {
            2.1f,
            " GL_ARB_pixel_buffer_object \0"
            " GL_EXT_texture_sRGB \0"
            "\0"
        },
        {
            3.0f,
            " GL_ARB_framebuffer_object \0"
            " GL_ARB_map_buffer_range \0"
            " GL_ARB_vertex_array_object \0"
            "\0"
        },
        {
            3.1f,
            " GL_ARB_copy_buffer \0"
            " GL_ARB_uniform_buffer_object \0"
            "\0"
        },
        {
            3.2f,
            " GL_ARB_vertex_array_bgra \0"
            " GL_ARB_draw_elements_base_vertex \0"
            " GL_ARB_fragment_coord_conventions \0"
            " GL_ARB_provoking_vertex \0"
            " GL_ARB_seamless_cube_map \0"
            " GL_ARB_texture_multisample \0"
            " GL_ARB_depth_clamp \0"
            " GL_ARB_sync \0"
            " GL_ARB_geometry_shader4 \0" 
            "\0"
        },
        {
            3.3f,
            " GL_ARB_blend_func_extended \0"
            " GL_ARB_sampler_objects \0"
            " GL_ARB_explicit_attrib_location \0"
            " GL_ARB_occlusion_query2 \0"
            " GL_ARB_shader_bit_encoding \0"
            " GL_ARB_texture_rgb10_a2ui \0"
            " GL_ARB_texture_swizzle \0"
            " GL_ARB_timer_query \0"
            " GL_ARB_vertex_type_2_10_10_10_rev \0"
            "\0"
        },
        {
            4.0f,
            " GL_ARB_texture_query_lod \0"
            " GL_ARB_draw_indirect \0"
            " GL_ARB_gpu_shader5 \0"
            " GL_ARB_gpu_shader_fp64 \0"
            " GL_ARB_shader_subroutine \0"
            " GL_ARB_tessellation_shader \0"
            " GL_ARB_texture_buffer_object_rgb32 \0"
            " GL_ARB_texture_cube_map_array \0"
            " GL_ARB_texture_gather \0"
            " GL_ARB_transform_feedback2 \0"
            " GL_ARB_transform_feedback3 \0"
            "\0"
        },
        {
            4.1f,
            " GL_ARB_ES2_compatibility \0"
            " GL_ARB_get_program_binary \0"
            " GL_ARB_separate_shader_objects \0"
            " GL_ARB_shader_precision \0"
            " GL_ARB_vertex_attrib_64bit \0"
            " GL_ARB_viewport_array \0"
            "\0"
        }
    };
    uint32_t cPromoted = 0;
    for (uint32_t i = 0; i < RT_ELEMENTS(s_aPromotedExtensions) && s_aPromotedExtensions[i].fGLVersion <= fGLProfileVersion; i++)
    {
        const char *pszExt = s_aPromotedExtensions[i].pszzExtensions;
        while (*pszExt)
        {
# ifdef VBOX_STRICT
            size_t cchExt = strlen(pszExt);
            Assert(cchExt > 3);
            Assert(pszExt[0] == ' ');
            Assert(pszExt[1] != ' ');
            Assert(pszExt[cchExt - 2] != ' ');
            Assert(pszExt[cchExt - 1] == ' ');
# endif
            if (strstr(*ppszExtensions, pszExt) == NULL)
            {
                if (cPromoted++ == 0)
                {
                    rc = RTStrAAppend(ppszExtensions, " <promoted-extensions:> <promoted-extensions:> <promoted-extensions:> ");
                    AssertRCReturn(rc, rc);
                }
                rc = RTStrAAppend(ppszExtensions, pszExt);
                AssertRCReturn(rc, rc);
            }
            pszExt = strchr(pszExt, '\0') + 1;
        }
    }
#endif
    return VINF_SUCCESS;
}
static int vmsvga3dGatherExtensions ( char * * ppszExtensions , float fGLProfileVersion ) { int rc ; * ppszExtensions = NULL ; const char * pszExtensions = ( const char * ) glGetString ( GL_EXTENSIONS ) ; if ( pszExtensions ) { rc = RTStrAAppendExN ( ppszExtensions , 3 , " " , ( size_t ) 1 , pszExtensions , RTSTR_MAX , " " , ( size_t ) 1 ) ; AssertLogRelRCReturn ( rc , rc ) ; } else { #ifndef GL_NUM_EXTENSIONS # define GL_NUM_EXTENSIONS  0x821D #endif GLint cExtensions = 1024 ; glGetIntegerv ( GL_NUM_EXTENSIONS , & cExtensions ) ; Assert ( cExtensions != 1024 ) ; PFNGLGETSTRINGIPROC pfnGlGetStringi = ( PFNGLGETSTRINGIPROC ) OGLGETPROCADDRESS ( " " ) ; AssertLogRelReturn ( pfnGlGetStringi , VERR_NOT_SUPPORTED ) ; rc = RTStrAAppend ( ppszExtensions , " " ) ; for ( GLint i = 0 ; RT_SUCCESS ( rc ) && i < cExtensions ; i ++ ) { const char * pszExt = ( const char * ) pfnGlGetStringi ( GL_EXTENSIONS , i ) ; if ( pszExt ) rc = RTStrAAppendExN ( ppszExtensions , 2 , pfnGlGetStringi ( GL_EXTENSIONS , i ) , RTSTR_MAX , " " , ( size_t ) 1 ) ; } AssertRCReturn ( rc , rc ) ; } #if 1 static const struct { float fGLVersion ; const char * pszzExtensions ; } s_aPromotedExtensions [ ] = { { 1.1f , " \0 " " \0 " " \0 " " \0 " " \0 " " \0 " " \0 " " \0 " " \0 " " \0 " " \0 " } , { 1.2f , " \0 " " \0 " " \0 " " \0 " " \0 " " \0 " " \0 " " \0 " " \0 " } , { 1.3f , " \0 " " \0 " " \0 " " \0 " " \0 " " \0 " " \0 " " \0 " " \0 " " \0 " } , { 1.5f , " \0 " " \0 " " \0 " " \0 " " \0 " " \0 " " \0 " " \0 " " \0 " " \0 " " \0 " " \0 " " \0 " " \0 " } , { 1.6f , " \0 " " \0 " " \0 " } , { 2.0f , " \0 " " \0 " " \0 " " \0 " " \0 " " \0 " " \0 " " \0 " " \0 " " \0 " } , { 2.1f , " \0 " " \0 " " \0 " } , { 3.0f , " \0 " " \0 " " \0 " " \0 " } , { 3.1f , " \0 " " \0 " " \0 " } , { 3.2f , " \0 " " \0 " " \0 " " \0 " " \0 " " \0 " " \0 " " \0 " " \0 " " \0 " } , { 3.3f , " \0 " " \0 " " \0 " " \0 " " \0 " " \0 " " \0 " " \0 " " \0 " " \0 " } , { 4.0f , " \0 " " \0 " " \0 " " \0 " " \0 " " \0 " " \0 " " \0 " " \0 " " \0 " " \0 " " \0 " } , { 4.1f , " \0 " " \0 " " \0 " " \0 " " \0 " " \0 " " \0 " } } ; uint32_t cPromoted = 0 ; for ( uint32_t i = 0 ; i < RT_ELEMENTS ( s_aPromotedExtensions ) && s_aPromotedExtensions [ i ] . fGLVersion <= fGLProfileVersion ; i ++ ) { const char * pszExt = s_aPromotedExtensions [ i ] . pszzExtensions ; while ( * pszExt ) { # ifdef VBOX_STRICT size_t cchExt = strlen ( pszExt ) ; Assert ( cchExt > 3 ) ; Assert ( pszExt [ 0 ] == ' ' ) ; Assert ( pszExt [ 1 ] != ' ' ) ; Assert ( pszExt [ cchExt - 2 ] != ' ' ) ; Assert ( pszExt [ cchExt - 1 ] == ' ' ) ; # endif if ( strstr ( * ppszExtensions , pszExt ) == NULL ) { if ( cPromoted ++ == 0 ) { rc = RTStrAAppend ( ppszExtensions , " " ) ; AssertRCReturn ( rc , rc ) ; } rc = RTStrAAppend ( ppszExtensions , pszExt ) ; AssertRCReturn ( rc , rc ) ; } pszExt = strchr ( pszExt , ' \0 ' ) + 1 ; } } #endif return VINF_SUCCESS ; }
Gathers the GL_EXTENSIONS list, storing it as a space padded list at
 @a ppszExtensions.
Gathers the GL_EXTENSIONS list storing it as a space padded list at @a ppszExtensions .
/*
     * Try the old glGetString interface first.
     */ /*
         * The new interface where each extension string is retrieved separately.
         * Note! Cannot use VMSVGA3D_INIT_CHECKED_GL_GET_INTEGER_VALUE here because
         *       the above GL_EXTENSIONS error lingers on darwin. sucks.
         */ /*
     * Add extensions promoted into the core OpenGL profile.
     */ /*" GL_NV_blend_equare \0"*/ /*??*/ /*??*/ /*??*/ /*??*/ /*??*/