diff options
author | marha <marha@users.sourceforge.net> | 2015-05-15 19:14:42 +0200 |
---|---|---|
committer | marha <marha@users.sourceforge.net> | 2015-05-15 19:14:42 +0200 |
commit | 843964ee791452b197e41dacb0146f5b456ffaa5 (patch) | |
tree | b1b0734c17ce1d488aa4d6e95f27363d80731e10 /mesalib/src | |
parent | a71d524ecad48837e0124a03124bc05f59a48be7 (diff) | |
download | vcxsrv-843964ee791452b197e41dacb0146f5b456ffaa5.tar.gz vcxsrv-843964ee791452b197e41dacb0146f5b456ffaa5.tar.bz2 vcxsrv-843964ee791452b197e41dacb0146f5b456ffaa5.zip |
randrproto fontconfig libfontenc libxcb mesalib xserver pixman xkeyboard-config git update 15 May 2015
xserver commit bf6344e1913a5d24c2d68eaca999ea3d71e1b707
libxcb commit cb621341a62e6d2233db3e337611f6fdd4f675a6
libxcb/xcb-proto commit 4c550465934164aab2449a125f75f4ca07816233
xkeyboard-config commit 5da6d510b460cad1b31288618cc364e586576826
libX11 commit d3415d1f052530760b4617db45affcb984cfe35c
libXdmcp commit b10f382e3aa2e86cd5a2bc27d6758da55f0ab1f6
libXext commit efdcbb7634501e1117d422636a0a75d7ea84b16b
libfontenc commit 42f3a39c3085afd9ef904ae39102fd49bbc2e4a5
libXinerama commit edd95182b26eb5d576d4878c559e0f17dddaa909
libXau commit 1e4635be11154dd8262f37b379511bd627defa2a
xkbcomp commit 1ae525b3d236b59e6437b2b5433d460e18370973
pixman commit 82f9b4faaf1aa63ec26b0dfd227f1a8e5e139ae2
xextproto commit 66afec3f49e8eb0d4c2e9af7088fc3116d4bafd7
randrproto commit 895ee5264524c7c239ee4ef5e39c4e295323fb51
glproto commit bd3d751e1eb17efb39f65093271bb4ac071aa9e0
mkfontscale commit 87d628f8eec170ec13bb9feefb1ce05aed07d1d6
xwininfo commit 0c49f8f2bd56b1e77721e81030ea948386dcdf4e
libXft commit e8a83226bc10afb587f6f34daac44d2ef809c85e
libXmu commit 4459e6940fe3fdf26a8d5d4c71989498bc400a62
libxtrans commit 7cbad9fe2e61cd9d5caeaf361826a6f4bd320f03
fontconfig commit 55ff8419274fd5ce59675f220b85035a3986d6cf
mesa commit 3687d752e51829b4723c9abb07ae56d2bbcda570
Diffstat (limited to 'mesalib/src')
135 files changed, 5744 insertions, 1708 deletions
diff --git a/mesalib/src/gallium/auxiliary/Makefile.sources b/mesalib/src/gallium/auxiliary/Makefile.sources index ec7547cad..62e6b94ca 100644 --- a/mesalib/src/gallium/auxiliary/Makefile.sources +++ b/mesalib/src/gallium/auxiliary/Makefile.sources @@ -197,7 +197,6 @@ C_SOURCES := \ util/u_dirty_surfaces.h \ util/u_dl.c \ util/u_dl.h \ - util/u_double_list.h \ util/u_draw.c \ util/u_draw.h \ util/u_draw_quad.c \ diff --git a/mesalib/src/gallium/auxiliary/hud/hud_driver_query.c b/mesalib/src/gallium/auxiliary/hud/hud_driver_query.c index 53771fcae..603aba7e8 100644 --- a/mesalib/src/gallium/auxiliary/hud/hud_driver_query.c +++ b/mesalib/src/gallium/auxiliary/hud/hud_driver_query.c @@ -187,6 +187,7 @@ hud_driver_query_install(struct hud_pane *pane, struct pipe_context *pipe, struct pipe_screen *screen = pipe->screen; struct pipe_driver_query_info query; unsigned num_queries, i; + boolean uses_byte_units; boolean found = FALSE; if (!screen->get_driver_query_info) @@ -205,7 +206,9 @@ hud_driver_query_install(struct hud_pane *pane, struct pipe_context *pipe, if (!found) return FALSE; + uses_byte_units = query.type == PIPE_DRIVER_QUERY_TYPE_BYTES; hud_pipe_query_install(pane, pipe, query.name, query.query_type, 0, - query.max_value, query.uses_byte_units); + query.max_value.u64, uses_byte_units); + return TRUE; } diff --git a/mesalib/src/gallium/auxiliary/hud/hud_private.h b/mesalib/src/gallium/auxiliary/hud/hud_private.h index 230f02664..632926b87 100644 --- a/mesalib/src/gallium/auxiliary/hud/hud_private.h +++ b/mesalib/src/gallium/auxiliary/hud/hud_private.h @@ -29,7 +29,7 @@ #define HUD_PRIVATE_H #include "pipe/p_context.h" -#include "util/u_double_list.h" +#include "util/list.h" struct hud_graph { /* initialized by common code */ diff --git a/mesalib/src/gallium/auxiliary/util/u_blitter.c b/mesalib/src/gallium/auxiliary/util/u_blitter.c index 9d087fe8a..24a5b93e1 100644 --- a/mesalib/src/gallium/auxiliary/util/u_blitter.c +++ b/mesalib/src/gallium/auxiliary/util/u_blitter.c @@ -1306,6 +1306,7 @@ void util_blitter_default_src_texture(struct pipe_sampler_view *src_templ, unsigned srclevel) { memset(src_templ, 0, sizeof(*src_templ)); + src_templ->target = src->target; src_templ->format = util_format_linear(src->format); src_templ->u.tex.first_level = srclevel; src_templ->u.tex.last_level = srclevel; diff --git a/mesalib/src/gallium/auxiliary/util/u_debug_flush.c b/mesalib/src/gallium/auxiliary/util/u_debug_flush.c index cdefca2fb..52e72cd6d 100644 --- a/mesalib/src/gallium/auxiliary/util/u_debug_flush.c +++ b/mesalib/src/gallium/auxiliary/util/u_debug_flush.c @@ -44,7 +44,7 @@ #include "util/u_memory.h" #include "util/u_debug_flush.h" #include "util/u_hash_table.h" -#include "util/u_double_list.h" +#include "util/list.h" #include "util/u_inlines.h" #include "util/u_string.h" #include "os/os_thread.h" diff --git a/mesalib/src/gallium/auxiliary/util/u_debug_memory.c b/mesalib/src/gallium/auxiliary/util/u_debug_memory.c index 1ad0e7220..747837cd1 100644 --- a/mesalib/src/gallium/auxiliary/util/u_debug_memory.c +++ b/mesalib/src/gallium/auxiliary/util/u_debug_memory.c @@ -42,7 +42,7 @@ #include "util/u_debug.h" #include "util/u_debug_stack.h" -#include "util/u_double_list.h" +#include "util/list.h" #define DEBUG_MEMORY_MAGIC 0x6e34090aU diff --git a/mesalib/src/gallium/auxiliary/util/u_dirty_surfaces.h b/mesalib/src/gallium/auxiliary/util/u_dirty_surfaces.h index f3618d9be..d31f8b917 100644 --- a/mesalib/src/gallium/auxiliary/util/u_dirty_surfaces.h +++ b/mesalib/src/gallium/auxiliary/util/u_dirty_surfaces.h @@ -29,7 +29,7 @@ #include "pipe/p_state.h" -#include "util/u_double_list.h" +#include "util/list.h" #include "util/u_math.h" struct pipe_context; diff --git a/mesalib/src/glsl/Makefile.sources b/mesalib/src/glsl/Makefile.sources index c471eca23..d784a8107 100644 --- a/mesalib/src/glsl/Makefile.sources +++ b/mesalib/src/glsl/Makefile.sources @@ -22,6 +22,7 @@ NIR_FILES = \ nir/glsl_to_nir.h \ nir/nir.c \ nir/nir.h \ + nir/nir_array.h \ nir/nir_builder.h \ nir/nir_constant_expressions.h \ nir/nir_dominance.c \ diff --git a/mesalib/src/glsl/ast_to_hir.cpp b/mesalib/src/glsl/ast_to_hir.cpp index 18b82e3be..14e630905 100644 --- a/mesalib/src/glsl/ast_to_hir.cpp +++ b/mesalib/src/glsl/ast_to_hir.cpp @@ -1558,6 +1558,18 @@ ast_expression::do_hir(exec_list *instructions, error_emitted = true; } + /* From section 4.1.7 of the GLSL 4.50 spec (Opaque Types): + * + * "Except for array indexing, structure member selection, and + * parentheses, opaque variables are not allowed to be operands in + * expressions; such use results in a compile-time error." + */ + if (type->contains_opaque()) { + _mesa_glsl_error(&loc, state, "opaque variables cannot be operands " + "of the ?: operator"); + error_emitted = true; + } + ir_constant *cond_val = op[0]->constant_expression_value(); if (then_instructions.is_empty() @@ -2357,6 +2369,14 @@ apply_image_qualifier_to_variable(const struct ast_type_qualifier *qual, var->data.image_format = GL_NONE; } + } else if (qual->flags.q.read_only || + qual->flags.q.write_only || + qual->flags.q.coherent || + qual->flags.q._volatile || + qual->flags.q.restrict_flag || + qual->flags.q.explicit_image_format) { + _mesa_glsl_error(loc, state, "memory qualifiers may only be applied to " + "images"); } } @@ -2781,8 +2801,21 @@ apply_type_qualifier_to_variable(const struct ast_type_qualifier *qual, validate_matrix_layout_for_type(state, loc, var->type, var); } - if (var->type->contains_image()) - apply_image_qualifier_to_variable(qual, var, state, loc); + apply_image_qualifier_to_variable(qual, var, state, loc); + + /* From section 4.4.1.3 of the GLSL 4.50 specification (Fragment Shader + * Inputs): + * + * "Fragment shaders also allow the following layout qualifier on in only + * (not with variable declarations) + * layout-qualifier-id + * early_fragment_tests + * [...]" + */ + if (qual->flags.q.early_fragment_tests) { + _mesa_glsl_error(loc, state, "early_fragment_tests layout qualifier only " + "valid in fragment shader input layout declaration."); + } } /** @@ -3541,6 +3574,9 @@ ast_declarator_list::hir(exec_list *instructions, case GLSL_TYPE_INT: if (state->is_version(120, 300)) break; + case GLSL_TYPE_DOUBLE: + if (check_type->base_type == GLSL_TYPE_DOUBLE && (state->is_version(410, 0) || state->ARB_vertex_attrib_64bit_enable)) + break; /* FALLTHROUGH */ default: _mesa_glsl_error(& loc, state, diff --git a/mesalib/src/glsl/ast_type.cpp b/mesalib/src/glsl/ast_type.cpp index b596cd59e..1bcf6a2e8 100644 --- a/mesalib/src/glsl/ast_type.cpp +++ b/mesalib/src/glsl/ast_type.cpp @@ -293,11 +293,7 @@ ast_type_qualifier::merge_in_qualifier(YYLTYPE *loc, valid_in_mask.flags.q.invocations = 1; break; case MESA_SHADER_FRAGMENT: - if (q.flags.q.early_fragment_tests) { - state->early_fragment_tests = true; - } else { - _mesa_glsl_error(loc, state, "invalid input layout qualifier"); - } + valid_in_mask.flags.q.early_fragment_tests = 1; break; case MESA_SHADER_COMPUTE: create_cs_ast |= @@ -345,6 +341,10 @@ ast_type_qualifier::merge_in_qualifier(YYLTYPE *loc, this->invocations = q.invocations; } + if (q.flags.q.early_fragment_tests) { + state->fs_early_fragment_tests = true; + } + if (create_gs_ast) { node = new(mem_ctx) ast_gs_input_layout(*loc, q.prim_type); } else if (create_cs_ast) { diff --git a/mesalib/src/glsl/builtin_functions.cpp b/mesalib/src/glsl/builtin_functions.cpp index 524b8d6e8..97055d85d 100644 --- a/mesalib/src/glsl/builtin_functions.cpp +++ b/mesalib/src/glsl/builtin_functions.cpp @@ -136,6 +136,12 @@ v140(const _mesa_glsl_parse_state *state) } static bool +es31(const _mesa_glsl_parse_state *state) +{ + return state->is_version(0, 310); +} + +static bool texture_rectangle(const _mesa_glsl_parse_state *state) { return state->ARB_texture_rectangle_enable; @@ -194,7 +200,8 @@ shader_bit_encoding(const _mesa_glsl_parse_state *state) static bool shader_integer_mix(const _mesa_glsl_parse_state *state) { - return v130(state) && state->EXT_shader_integer_mix_enable; + return state->is_version(450, 310) || + (v130(state) && state->EXT_shader_integer_mix_enable); } static bool @@ -219,10 +226,17 @@ gpu_shader5(const _mesa_glsl_parse_state *state) } static bool -shader_packing_or_gpu_shader5(const _mesa_glsl_parse_state *state) +gpu_shader5_or_es31(const _mesa_glsl_parse_state *state) +{ + return state->is_version(400, 310) || state->ARB_gpu_shader5_enable; +} + +static bool +shader_packing_or_es31_or_gpu_shader5(const _mesa_glsl_parse_state *state) { return state->ARB_shading_language_packing_enable || - gpu_shader5(state); + state->ARB_gpu_shader5_enable || + state->is_version(400, 310); } static bool @@ -297,15 +311,24 @@ texture_gather(const _mesa_glsl_parse_state *state) state->ARB_gpu_shader5_enable; } +static bool +texture_gather_or_es31(const _mesa_glsl_parse_state *state) +{ + return state->is_version(400, 310) || + state->ARB_texture_gather_enable || + state->ARB_gpu_shader5_enable; +} + /* Only ARB_texture_gather but not GLSL 4.0 or ARB_gpu_shader5. * used for relaxation of const offset requirements. */ static bool -texture_gather_only(const _mesa_glsl_parse_state *state) +texture_gather_only_or_es31(const _mesa_glsl_parse_state *state) { return !state->is_version(400, 0) && !state->ARB_gpu_shader5_enable && - state->ARB_texture_gather_enable; + (state->ARB_texture_gather_enable || + state->is_version(0, 310)); } /* Desktop GL or OES_standard_derivatives + fragment shader only */ @@ -359,7 +382,7 @@ tex3d_lod(const _mesa_glsl_parse_state *state) static bool shader_atomic_counters(const _mesa_glsl_parse_state *state) { - return state->ARB_shader_atomic_counters_enable; + return state->has_atomic_counters(); } static bool @@ -1161,12 +1184,12 @@ builtin_builder::create_builtins() add_function("packUnorm2x16", _packUnorm2x16(shader_packing_or_es3_or_gpu_shader5), NULL); add_function("packSnorm2x16", _packSnorm2x16(shader_packing_or_es3), NULL); - add_function("packUnorm4x8", _packUnorm4x8(shader_packing_or_gpu_shader5), NULL); - add_function("packSnorm4x8", _packSnorm4x8(shader_packing_or_gpu_shader5), NULL); + add_function("packUnorm4x8", _packUnorm4x8(shader_packing_or_es31_or_gpu_shader5), NULL); + add_function("packSnorm4x8", _packSnorm4x8(shader_packing_or_es31_or_gpu_shader5), NULL); add_function("unpackUnorm2x16", _unpackUnorm2x16(shader_packing_or_es3_or_gpu_shader5), NULL); add_function("unpackSnorm2x16", _unpackSnorm2x16(shader_packing_or_es3), NULL); - add_function("unpackUnorm4x8", _unpackUnorm4x8(shader_packing_or_gpu_shader5), NULL); - add_function("unpackSnorm4x8", _unpackSnorm4x8(shader_packing_or_gpu_shader5), NULL); + add_function("unpackUnorm4x8", _unpackUnorm4x8(shader_packing_or_es31_or_gpu_shader5), NULL); + add_function("unpackSnorm4x8", _unpackSnorm4x8(shader_packing_or_es31_or_gpu_shader5), NULL); add_function("packHalf2x16", _packHalf2x16(shader_packing_or_es3), NULL); add_function("unpackHalf2x16", _unpackHalf2x16(shader_packing_or_es3), NULL); add_function("packDouble2x32", _packDouble2x32(fp64), NULL); @@ -2202,61 +2225,69 @@ builtin_builder::create_builtins() NULL); add_function("textureGather", - _texture(ir_tg4, texture_gather, glsl_type::vec4_type, glsl_type::sampler2D_type, glsl_type::vec2_type), - _texture(ir_tg4, texture_gather, glsl_type::ivec4_type, glsl_type::isampler2D_type, glsl_type::vec2_type), - _texture(ir_tg4, texture_gather, glsl_type::uvec4_type, glsl_type::usampler2D_type, glsl_type::vec2_type), + _texture(ir_tg4, texture_gather_or_es31, glsl_type::vec4_type, glsl_type::sampler2D_type, glsl_type::vec2_type), + _texture(ir_tg4, texture_gather_or_es31, glsl_type::ivec4_type, glsl_type::isampler2D_type, glsl_type::vec2_type), + _texture(ir_tg4, texture_gather_or_es31, glsl_type::uvec4_type, glsl_type::usampler2D_type, glsl_type::vec2_type), _texture(ir_tg4, gpu_shader5, glsl_type::vec4_type, glsl_type::sampler2DRect_type, glsl_type::vec2_type), _texture(ir_tg4, gpu_shader5, glsl_type::ivec4_type, glsl_type::isampler2DRect_type, glsl_type::vec2_type), _texture(ir_tg4, gpu_shader5, glsl_type::uvec4_type, glsl_type::usampler2DRect_type, glsl_type::vec2_type), - _texture(ir_tg4, texture_gather, glsl_type::vec4_type, glsl_type::sampler2DArray_type, glsl_type::vec3_type), - _texture(ir_tg4, texture_gather, glsl_type::ivec4_type, glsl_type::isampler2DArray_type, glsl_type::vec3_type), - _texture(ir_tg4, texture_gather, glsl_type::uvec4_type, glsl_type::usampler2DArray_type, glsl_type::vec3_type), + _texture(ir_tg4, texture_gather_or_es31, glsl_type::vec4_type, glsl_type::sampler2DArray_type, glsl_type::vec3_type), + _texture(ir_tg4, texture_gather_or_es31, glsl_type::ivec4_type, glsl_type::isampler2DArray_type, glsl_type::vec3_type), + _texture(ir_tg4, texture_gather_or_es31, glsl_type::uvec4_type, glsl_type::usampler2DArray_type, glsl_type::vec3_type), - _texture(ir_tg4, texture_gather, glsl_type::vec4_type, glsl_type::samplerCube_type, glsl_type::vec3_type), - _texture(ir_tg4, texture_gather, glsl_type::ivec4_type, glsl_type::isamplerCube_type, glsl_type::vec3_type), - _texture(ir_tg4, texture_gather, glsl_type::uvec4_type, glsl_type::usamplerCube_type, glsl_type::vec3_type), + _texture(ir_tg4, texture_gather_or_es31, glsl_type::vec4_type, glsl_type::samplerCube_type, glsl_type::vec3_type), + _texture(ir_tg4, texture_gather_or_es31, glsl_type::ivec4_type, glsl_type::isamplerCube_type, glsl_type::vec3_type), + _texture(ir_tg4, texture_gather_or_es31, glsl_type::uvec4_type, glsl_type::usamplerCube_type, glsl_type::vec3_type), _texture(ir_tg4, texture_gather, glsl_type::vec4_type, glsl_type::samplerCubeArray_type, glsl_type::vec4_type), _texture(ir_tg4, texture_gather, glsl_type::ivec4_type, glsl_type::isamplerCubeArray_type, glsl_type::vec4_type), _texture(ir_tg4, texture_gather, glsl_type::uvec4_type, glsl_type::usamplerCubeArray_type, glsl_type::vec4_type), - _texture(ir_tg4, gpu_shader5, glsl_type::vec4_type, glsl_type::sampler2D_type, glsl_type::vec2_type, TEX_COMPONENT), - _texture(ir_tg4, gpu_shader5, glsl_type::ivec4_type, glsl_type::isampler2D_type, glsl_type::vec2_type, TEX_COMPONENT), - _texture(ir_tg4, gpu_shader5, glsl_type::uvec4_type, glsl_type::usampler2D_type, glsl_type::vec2_type, TEX_COMPONENT), + _texture(ir_tg4, gpu_shader5_or_es31, glsl_type::vec4_type, glsl_type::sampler2D_type, glsl_type::vec2_type, TEX_COMPONENT), + _texture(ir_tg4, gpu_shader5_or_es31, glsl_type::ivec4_type, glsl_type::isampler2D_type, glsl_type::vec2_type, TEX_COMPONENT), + _texture(ir_tg4, gpu_shader5_or_es31, glsl_type::uvec4_type, glsl_type::usampler2D_type, glsl_type::vec2_type, TEX_COMPONENT), _texture(ir_tg4, gpu_shader5, glsl_type::vec4_type, glsl_type::sampler2DRect_type, glsl_type::vec2_type, TEX_COMPONENT), _texture(ir_tg4, gpu_shader5, glsl_type::ivec4_type, glsl_type::isampler2DRect_type, glsl_type::vec2_type, TEX_COMPONENT), _texture(ir_tg4, gpu_shader5, glsl_type::uvec4_type, glsl_type::usampler2DRect_type, glsl_type::vec2_type, TEX_COMPONENT), - _texture(ir_tg4, gpu_shader5, glsl_type::vec4_type, glsl_type::sampler2DArray_type, glsl_type::vec3_type, TEX_COMPONENT), - _texture(ir_tg4, gpu_shader5, glsl_type::ivec4_type, glsl_type::isampler2DArray_type, glsl_type::vec3_type, TEX_COMPONENT), - _texture(ir_tg4, gpu_shader5, glsl_type::uvec4_type, glsl_type::usampler2DArray_type, glsl_type::vec3_type, TEX_COMPONENT), + _texture(ir_tg4, gpu_shader5_or_es31, glsl_type::vec4_type, glsl_type::sampler2DArray_type, glsl_type::vec3_type, TEX_COMPONENT), + _texture(ir_tg4, gpu_shader5_or_es31, glsl_type::ivec4_type, glsl_type::isampler2DArray_type, glsl_type::vec3_type, TEX_COMPONENT), + _texture(ir_tg4, gpu_shader5_or_es31, glsl_type::uvec4_type, glsl_type::usampler2DArray_type, glsl_type::vec3_type, TEX_COMPONENT), - _texture(ir_tg4, gpu_shader5, glsl_type::vec4_type, glsl_type::samplerCube_type, glsl_type::vec3_type, TEX_COMPONENT), - _texture(ir_tg4, gpu_shader5, glsl_type::ivec4_type, glsl_type::isamplerCube_type, glsl_type::vec3_type, TEX_COMPONENT), - _texture(ir_tg4, gpu_shader5, glsl_type::uvec4_type, glsl_type::usamplerCube_type, glsl_type::vec3_type, TEX_COMPONENT), + _texture(ir_tg4, gpu_shader5_or_es31, glsl_type::vec4_type, glsl_type::samplerCube_type, glsl_type::vec3_type, TEX_COMPONENT), + _texture(ir_tg4, gpu_shader5_or_es31, glsl_type::ivec4_type, glsl_type::isamplerCube_type, glsl_type::vec3_type, TEX_COMPONENT), + _texture(ir_tg4, gpu_shader5_or_es31, glsl_type::uvec4_type, glsl_type::usamplerCube_type, glsl_type::vec3_type, TEX_COMPONENT), _texture(ir_tg4, gpu_shader5, glsl_type::vec4_type, glsl_type::samplerCubeArray_type, glsl_type::vec4_type, TEX_COMPONENT), _texture(ir_tg4, gpu_shader5, glsl_type::ivec4_type, glsl_type::isamplerCubeArray_type, glsl_type::vec4_type, TEX_COMPONENT), _texture(ir_tg4, gpu_shader5, glsl_type::uvec4_type, glsl_type::usamplerCubeArray_type, glsl_type::vec4_type, TEX_COMPONENT), - _texture(ir_tg4, gpu_shader5, glsl_type::vec4_type, glsl_type::sampler2DShadow_type, glsl_type::vec2_type), - _texture(ir_tg4, gpu_shader5, glsl_type::vec4_type, glsl_type::sampler2DArrayShadow_type, glsl_type::vec3_type), - _texture(ir_tg4, gpu_shader5, glsl_type::vec4_type, glsl_type::samplerCubeShadow_type, glsl_type::vec3_type), + _texture(ir_tg4, gpu_shader5_or_es31, glsl_type::vec4_type, glsl_type::sampler2DShadow_type, glsl_type::vec2_type), + _texture(ir_tg4, gpu_shader5_or_es31, glsl_type::vec4_type, glsl_type::sampler2DArrayShadow_type, glsl_type::vec3_type), + _texture(ir_tg4, gpu_shader5_or_es31, glsl_type::vec4_type, glsl_type::samplerCubeShadow_type, glsl_type::vec3_type), _texture(ir_tg4, gpu_shader5, glsl_type::vec4_type, glsl_type::samplerCubeArrayShadow_type, glsl_type::vec4_type), _texture(ir_tg4, gpu_shader5, glsl_type::vec4_type, glsl_type::sampler2DRectShadow_type, glsl_type::vec2_type), NULL); add_function("textureGatherOffset", - _texture(ir_tg4, texture_gather_only, glsl_type::vec4_type, glsl_type::sampler2D_type, glsl_type::vec2_type, TEX_OFFSET), - _texture(ir_tg4, texture_gather_only, glsl_type::ivec4_type, glsl_type::isampler2D_type, glsl_type::vec2_type, TEX_OFFSET), - _texture(ir_tg4, texture_gather_only, glsl_type::uvec4_type, glsl_type::usampler2D_type, glsl_type::vec2_type, TEX_OFFSET), + _texture(ir_tg4, texture_gather_only_or_es31, glsl_type::vec4_type, glsl_type::sampler2D_type, glsl_type::vec2_type, TEX_OFFSET), + _texture(ir_tg4, texture_gather_only_or_es31, glsl_type::ivec4_type, glsl_type::isampler2D_type, glsl_type::vec2_type, TEX_OFFSET), + _texture(ir_tg4, texture_gather_only_or_es31, glsl_type::uvec4_type, glsl_type::usampler2D_type, glsl_type::vec2_type, TEX_OFFSET), + + _texture(ir_tg4, texture_gather_only_or_es31, glsl_type::vec4_type, glsl_type::sampler2DArray_type, glsl_type::vec3_type, TEX_OFFSET), + _texture(ir_tg4, texture_gather_only_or_es31, glsl_type::ivec4_type, glsl_type::isampler2DArray_type, glsl_type::vec3_type, TEX_OFFSET), + _texture(ir_tg4, texture_gather_only_or_es31, glsl_type::uvec4_type, glsl_type::usampler2DArray_type, glsl_type::vec3_type, TEX_OFFSET), - _texture(ir_tg4, texture_gather_only, glsl_type::vec4_type, glsl_type::sampler2DArray_type, glsl_type::vec3_type, TEX_OFFSET), - _texture(ir_tg4, texture_gather_only, glsl_type::ivec4_type, glsl_type::isampler2DArray_type, glsl_type::vec3_type, TEX_OFFSET), - _texture(ir_tg4, texture_gather_only, glsl_type::uvec4_type, glsl_type::usampler2DArray_type, glsl_type::vec3_type, TEX_OFFSET), + _texture(ir_tg4, es31, glsl_type::vec4_type, glsl_type::sampler2D_type, glsl_type::vec2_type, TEX_OFFSET | TEX_COMPONENT), + _texture(ir_tg4, es31, glsl_type::ivec4_type, glsl_type::isampler2D_type, glsl_type::vec2_type, TEX_OFFSET | TEX_COMPONENT), + _texture(ir_tg4, es31, glsl_type::uvec4_type, glsl_type::usampler2D_type, glsl_type::vec2_type, TEX_OFFSET | TEX_COMPONENT), + + _texture(ir_tg4, es31, glsl_type::vec4_type, glsl_type::sampler2DArray_type, glsl_type::vec3_type, TEX_OFFSET | TEX_COMPONENT), + _texture(ir_tg4, es31, glsl_type::ivec4_type, glsl_type::isampler2DArray_type, glsl_type::vec3_type, TEX_OFFSET | TEX_COMPONENT), + _texture(ir_tg4, es31, glsl_type::uvec4_type, glsl_type::usampler2DArray_type, glsl_type::vec3_type, TEX_OFFSET | TEX_COMPONENT), _texture(ir_tg4, gpu_shader5, glsl_type::vec4_type, glsl_type::sampler2D_type, glsl_type::vec2_type, TEX_OFFSET_NONCONST), _texture(ir_tg4, gpu_shader5, glsl_type::ivec4_type, glsl_type::isampler2D_type, glsl_type::vec2_type, TEX_OFFSET_NONCONST), @@ -2285,6 +2316,9 @@ builtin_builder::create_builtins() _texture(ir_tg4, gpu_shader5, glsl_type::vec4_type, glsl_type::sampler2DShadow_type, glsl_type::vec2_type, TEX_OFFSET_NONCONST), _texture(ir_tg4, gpu_shader5, glsl_type::vec4_type, glsl_type::sampler2DArrayShadow_type, glsl_type::vec3_type, TEX_OFFSET_NONCONST), _texture(ir_tg4, gpu_shader5, glsl_type::vec4_type, glsl_type::sampler2DRectShadow_type, glsl_type::vec2_type, TEX_OFFSET_NONCONST), + + _texture(ir_tg4, es31, glsl_type::vec4_type, glsl_type::sampler2DShadow_type, glsl_type::vec2_type, TEX_OFFSET), + _texture(ir_tg4, es31, glsl_type::vec4_type, glsl_type::sampler2DArrayShadow_type, glsl_type::vec3_type, TEX_OFFSET), NULL); add_function("textureGatherOffsets", @@ -4445,7 +4479,7 @@ builtin_builder::_bitfieldExtract(const glsl_type *type) ir_variable *value = in_var(type, "value"); ir_variable *offset = in_var(glsl_type::int_type, "offset"); ir_variable *bits = in_var(glsl_type::int_type, "bits"); - MAKE_SIG(type, gpu_shader5, 3, value, offset, bits); + MAKE_SIG(type, gpu_shader5_or_es31, 3, value, offset, bits); body.emit(ret(expr(ir_triop_bitfield_extract, value, offset, bits))); @@ -4459,33 +4493,33 @@ builtin_builder::_bitfieldInsert(const glsl_type *type) ir_variable *insert = in_var(type, "insert"); ir_variable *offset = in_var(glsl_type::int_type, "offset"); ir_variable *bits = in_var(glsl_type::int_type, "bits"); - MAKE_SIG(type, gpu_shader5, 4, base, insert, offset, bits); + MAKE_SIG(type, gpu_shader5_or_es31, 4, base, insert, offset, bits); body.emit(ret(bitfield_insert(base, insert, offset, bits))); return sig; } -UNOP(bitfieldReverse, ir_unop_bitfield_reverse, gpu_shader5) +UNOP(bitfieldReverse, ir_unop_bitfield_reverse, gpu_shader5_or_es31) ir_function_signature * builtin_builder::_bitCount(const glsl_type *type) { - return unop(gpu_shader5, ir_unop_bit_count, + return unop(gpu_shader5_or_es31, ir_unop_bit_count, glsl_type::ivec(type->vector_elements), type); } ir_function_signature * builtin_builder::_findLSB(const glsl_type *type) { - return unop(gpu_shader5, ir_unop_find_lsb, + return unop(gpu_shader5_or_es31, ir_unop_find_lsb, glsl_type::ivec(type->vector_elements), type); } ir_function_signature * builtin_builder::_findMSB(const glsl_type *type) { - return unop(gpu_shader5, ir_unop_find_msb, + return unop(gpu_shader5_or_es31, ir_unop_find_msb, glsl_type::ivec(type->vector_elements), type); } @@ -4505,7 +4539,7 @@ builtin_builder::_fma(builtin_available_predicate avail, const glsl_type *type) ir_function_signature * builtin_builder::_ldexp(const glsl_type *x_type, const glsl_type *exp_type) { - return binop(ir_binop_ldexp, x_type->base_type == GLSL_TYPE_DOUBLE ? fp64 : gpu_shader5, x_type, x_type, exp_type); + return binop(ir_binop_ldexp, x_type->base_type == GLSL_TYPE_DOUBLE ? fp64 : gpu_shader5_or_es31, x_type, x_type, exp_type); } ir_function_signature * @@ -4526,7 +4560,7 @@ builtin_builder::_frexp(const glsl_type *x_type, const glsl_type *exp_type) { ir_variable *x = in_var(x_type, "x"); ir_variable *exponent = out_var(exp_type, "exp"); - MAKE_SIG(x_type, gpu_shader5, 2, x, exponent); + MAKE_SIG(x_type, gpu_shader5_or_es31, 2, x, exponent); const unsigned vec_elem = x_type->vector_elements; const glsl_type *bvec = glsl_type::get_instance(GLSL_TYPE_BOOL, vec_elem, 1); @@ -4575,7 +4609,7 @@ builtin_builder::_uaddCarry(const glsl_type *type) ir_variable *x = in_var(type, "x"); ir_variable *y = in_var(type, "y"); ir_variable *carry = out_var(type, "carry"); - MAKE_SIG(type, gpu_shader5, 3, x, y, carry); + MAKE_SIG(type, gpu_shader5_or_es31, 3, x, y, carry); body.emit(assign(carry, ir_builder::carry(x, y))); body.emit(ret(add(x, y))); @@ -4589,7 +4623,7 @@ builtin_builder::_usubBorrow(const glsl_type *type) ir_variable *x = in_var(type, "x"); ir_variable *y = in_var(type, "y"); ir_variable *borrow = out_var(type, "borrow"); - MAKE_SIG(type, gpu_shader5, 3, x, y, borrow); + MAKE_SIG(type, gpu_shader5_or_es31, 3, x, y, borrow); body.emit(assign(borrow, ir_builder::borrow(x, y))); body.emit(ret(sub(x, y))); @@ -4607,7 +4641,7 @@ builtin_builder::_mulExtended(const glsl_type *type) ir_variable *y = in_var(type, "y"); ir_variable *msb = out_var(type, "msb"); ir_variable *lsb = out_var(type, "lsb"); - MAKE_SIG(glsl_type::void_type, gpu_shader5, 4, x, y, msb, lsb); + MAKE_SIG(glsl_type::void_type, gpu_shader5_or_es31, 4, x, y, msb, lsb); body.emit(assign(msb, imul_high(x, y))); body.emit(assign(lsb, mul(x, y))); diff --git a/mesalib/src/glsl/builtin_types.cpp b/mesalib/src/glsl/builtin_types.cpp index fef86df28..d92e2eb30 100644 --- a/mesalib/src/glsl/builtin_types.cpp +++ b/mesalib/src/glsl/builtin_types.cpp @@ -372,7 +372,7 @@ _mesa_glsl_initialize_types(struct _mesa_glsl_parse_state *state) add_type(symbols, glsl_type::uimage2DMSArray_type); } - if (state->ARB_shader_atomic_counters_enable) { + if (state->has_atomic_counters()) { add_type(symbols, glsl_type::atomic_uint_type); } diff --git a/mesalib/src/glsl/builtin_variables.cpp b/mesalib/src/glsl/builtin_variables.cpp index 21e7331c7..6806aa1f9 100644 --- a/mesalib/src/glsl/builtin_variables.cpp +++ b/mesalib/src/glsl/builtin_variables.cpp @@ -653,19 +653,46 @@ builtin_variable_generator::generate_constants() add_const("gl_MaxTextureCoords", state->Const.MaxTextureCoords); } - if (state->ARB_shader_atomic_counters_enable) { + if (state->has_atomic_counters()) { add_const("gl_MaxVertexAtomicCounters", state->Const.MaxVertexAtomicCounters); - add_const("gl_MaxGeometryAtomicCounters", - state->Const.MaxGeometryAtomicCounters); add_const("gl_MaxFragmentAtomicCounters", state->Const.MaxFragmentAtomicCounters); add_const("gl_MaxCombinedAtomicCounters", state->Const.MaxCombinedAtomicCounters); add_const("gl_MaxAtomicCounterBindings", state->Const.MaxAtomicBufferBindings); - add_const("gl_MaxTessControlAtomicCounters", 0); - add_const("gl_MaxTessEvaluationAtomicCounters", 0); + + /* When Mesa adds support for GL_OES_geometry_shader and + * GL_OES_tessellation_shader, this will need to change. + */ + if (!state->es_shader) { + add_const("gl_MaxGeometryAtomicCounters", + state->Const.MaxGeometryAtomicCounters); + add_const("gl_MaxTessControlAtomicCounters", 0); + add_const("gl_MaxTessEvaluationAtomicCounters", 0); + } + } + + if (state->is_version(420, 310)) { + add_const("gl_MaxVertexAtomicCounterBuffers", + state->Const.MaxVertexAtomicCounterBuffers); + add_const("gl_MaxFragmentAtomicCounterBuffers", + state->Const.MaxFragmentAtomicCounterBuffers); + add_const("gl_MaxCombinedAtomicCounterBuffers", + state->Const.MaxCombinedAtomicCounterBuffers); + add_const("gl_MaxAtomicCounterBufferSize", + state->Const.MaxAtomicCounterBufferSize); + + /* When Mesa adds support for GL_OES_geometry_shader and + * GL_OES_tessellation_shader, this will need to change. + */ + if (!state->es_shader) { + add_const("gl_MaxGeometryAtomicCounterBuffers", + state->Const.MaxGeometryAtomicCounterBuffers); + add_const("gl_MaxTessControlAtomicCounterBuffers", 0); + add_const("gl_MaxTessEvaluationAtomicCounterBuffers", 0); + } } if (state->is_version(430, 0) || state->ARB_compute_shader_enable) { diff --git a/mesalib/src/glsl/glcpp/glcpp-parse.y b/mesalib/src/glsl/glcpp/glcpp-parse.y index cfceca66b..a11b6b2c7 100644 --- a/mesalib/src/glsl/glcpp/glcpp-parse.y +++ b/mesalib/src/glsl/glcpp/glcpp-parse.y @@ -2448,6 +2448,9 @@ _glcpp_parser_handle_version_declaration(glcpp_parser_t *parser, intmax_t versio if (extensions->ARB_gpu_shader_fp64) add_builtin_define(parser, "GL_ARB_gpu_shader_fp64", 1); + if (extensions->ARB_vertex_attrib_64bit) + add_builtin_define(parser, "GL_ARB_vertex_attrib_64bit", 1); + if (extensions->AMD_vertex_shader_layer) add_builtin_define(parser, "GL_AMD_vertex_shader_layer", 1); diff --git a/mesalib/src/glsl/glsl_lexer.ll b/mesalib/src/glsl/glsl_lexer.ll index 2785ed168..10db5b8b6 100644 --- a/mesalib/src/glsl/glsl_lexer.ll +++ b/mesalib/src/glsl/glsl_lexer.ll @@ -409,7 +409,7 @@ restrict KEYWORD_WITH_ALT(420, 300, 420, 0, yyextra->ARB_shader_image_load_store readonly KEYWORD_WITH_ALT(420, 300, 420, 0, yyextra->ARB_shader_image_load_store_enable, READONLY); writeonly KEYWORD_WITH_ALT(420, 300, 420, 0, yyextra->ARB_shader_image_load_store_enable, WRITEONLY); -atomic_uint KEYWORD_WITH_ALT(420, 300, 420, 0, yyextra->ARB_shader_atomic_counters_enable, ATOMIC_UINT); +atomic_uint KEYWORD_WITH_ALT(420, 300, 420, 310, yyextra->ARB_shader_atomic_counters_enable, ATOMIC_UINT); struct return STRUCT; void return VOID_TOK; diff --git a/mesalib/src/glsl/glsl_parser.yy b/mesalib/src/glsl/glsl_parser.yy index aceb3b916..3ce9e103f 100644 --- a/mesalib/src/glsl/glsl_parser.yy +++ b/mesalib/src/glsl/glsl_parser.yy @@ -214,6 +214,7 @@ static bool match_layout_qualifier(const char *s1, const char *s2, %type <type_qualifier> layout_qualifier %type <type_qualifier> layout_qualifier_id_list layout_qualifier_id %type <type_qualifier> interface_block_layout_qualifier +%type <type_qualifier> memory_qualifier %type <type_qualifier> interface_qualifier %type <type_specifier> type_specifier %type <type_specifier> type_specifier_nonarray @@ -1000,6 +1001,11 @@ parameter_qualifier: $$ = $2; $$.precision = $1; } + | memory_qualifier parameter_qualifier + { + $$ = $1; + $$.merge_qualifier(&@1, state, $2); + } parameter_direction_qualifier: IN_TOK @@ -1360,6 +1366,21 @@ layout_qualifier_id: if (!$$.flags.i && match_layout_qualifier($1, "early_fragment_tests", state) == 0) { + /* From section 4.4.1.3 of the GLSL 4.50 specification + * (Fragment Shader Inputs): + * + * "Fragment shaders also allow the following layout + * qualifier on in only (not with variable declarations) + * layout-qualifier-id + * early_fragment_tests + * [...]" + */ + if (state->stage != MESA_SHADER_FRAGMENT) { + _mesa_glsl_error(& @1, state, + "early_fragment_tests layout qualifier only " + "valid in fragment shaders"); + } + $$.flags.q.early_fragment_tests = 1; } } @@ -1404,13 +1425,13 @@ layout_qualifier_id: } if ((state->ARB_shading_language_420pack_enable || - state->ARB_shader_atomic_counters_enable) && + state->has_atomic_counters()) && match_layout_qualifier("binding", $1, state) == 0) { $$.flags.q.explicit_binding = 1; $$.binding = $3; } - if (state->ARB_shader_atomic_counters_enable && + if (state->has_atomic_counters() && match_layout_qualifier("offset", $1, state) == 0) { $$.flags.q.explicit_offset = 1; $$.offset = $3; @@ -1581,6 +1602,7 @@ type_qualifier: | storage_qualifier | interpolation_qualifier | layout_qualifier + | memory_qualifier | precision_qualifier { memset(&$$, 0, sizeof($$)); @@ -1718,6 +1740,11 @@ type_qualifier: $$ = $2; $$.precision = $1; } + | memory_qualifier type_qualifier + { + $$ = $1; + $$.merge_qualifier(&@1, state, $2); + } ; auxiliary_storage_qualifier: @@ -1778,7 +1805,10 @@ storage_qualifier: memset(& $$, 0, sizeof($$)); $$.flags.q.uniform = 1; } - | COHERENT + ; + +memory_qualifier: + COHERENT { memset(& $$, 0, sizeof($$)); $$.flags.q.coherent = 1; diff --git a/mesalib/src/glsl/glsl_parser_extras.cpp b/mesalib/src/glsl/glsl_parser_extras.cpp index 0aa3c54fc..be6713c46 100644 --- a/mesalib/src/glsl/glsl_parser_extras.cpp +++ b/mesalib/src/glsl/glsl_parser_extras.cpp @@ -117,6 +117,16 @@ _mesa_glsl_parse_state::_mesa_glsl_parse_state(struct gl_context *_ctx, this->Const.MaxFragmentAtomicCounters = ctx->Const.Program[MESA_SHADER_FRAGMENT].MaxAtomicCounters; this->Const.MaxCombinedAtomicCounters = ctx->Const.MaxCombinedAtomicCounters; this->Const.MaxAtomicBufferBindings = ctx->Const.MaxAtomicBufferBindings; + this->Const.MaxVertexAtomicCounterBuffers = + ctx->Const.Program[MESA_SHADER_VERTEX].MaxAtomicBuffers; + this->Const.MaxGeometryAtomicCounterBuffers = + ctx->Const.Program[MESA_SHADER_GEOMETRY].MaxAtomicBuffers; + this->Const.MaxFragmentAtomicCounterBuffers = + ctx->Const.Program[MESA_SHADER_FRAGMENT].MaxAtomicBuffers; + this->Const.MaxCombinedAtomicCounterBuffers = + ctx->Const.MaxCombinedAtomicBuffers; + this->Const.MaxAtomicCounterBufferSize = + ctx->Const.MaxAtomicBufferSize; /* Compute shader constants */ for (unsigned i = 0; i < ARRAY_SIZE(this->Const.MaxComputeWorkGroupCount); i++) @@ -143,9 +153,9 @@ _mesa_glsl_parse_state::_mesa_glsl_parse_state(struct gl_context *_ctx, this->num_user_structures = 0; /* supported_versions should be large enough to support the known desktop - * GLSL versions plus 2 GLES versions (ES2 & ES3) + * GLSL versions plus 3 GLES versions (ES 1.00, ES 3.00, and ES 3.10)) */ - STATIC_ASSERT((ARRAY_SIZE(known_desktop_glsl_versions) + 2) == + STATIC_ASSERT((ARRAY_SIZE(known_desktop_glsl_versions) + 3) == ARRAY_SIZE(this->supported_versions)); /* Populate the list of supported GLSL versions */ @@ -175,6 +185,11 @@ _mesa_glsl_parse_state::_mesa_glsl_parse_state(struct gl_context *_ctx, this->supported_versions[this->num_supported_versions].es = true; this->num_supported_versions++; } + if (_mesa_is_gles31(ctx)) { + this->supported_versions[this->num_supported_versions].ver = 310; + this->supported_versions[this->num_supported_versions].es = true; + this->num_supported_versions++; + } /* Create a string for use in error messages to tell the user which GLSL * versions are supported. @@ -212,7 +227,7 @@ _mesa_glsl_parse_state::_mesa_glsl_parse_state(struct gl_context *_ctx, this->gs_input_size = 0; this->in_qualifier = new(this) ast_type_qualifier(); this->out_qualifier = new(this) ast_type_qualifier(); - this->early_fragment_tests = false; + this->fs_early_fragment_tests = false; memset(this->atomic_counter_offsets, 0, sizeof(this->atomic_counter_offsets)); this->allow_extension_directive_midshader = @@ -565,6 +580,7 @@ static const _mesa_glsl_extension _mesa_glsl_supported_extensions[] = { EXT(ARB_texture_query_lod, true, false, ARB_texture_query_lod), EXT(ARB_texture_rectangle, true, false, dummy_true), EXT(ARB_uniform_buffer_object, true, false, ARB_uniform_buffer_object), + EXT(ARB_vertex_attrib_64bit, true, false, ARB_vertex_attrib_64bit), EXT(ARB_viewport_array, true, false, ARB_viewport_array), /* KHR extensions go here, sorted alphabetically. @@ -1418,6 +1434,7 @@ set_shader_inout_layout(struct gl_shader *shader, assert(!state->fs_redeclares_gl_fragcoord); assert(!state->fs_pixel_center_integer); assert(!state->fs_origin_upper_left); + assert(!state->fs_early_fragment_tests); } switch (shader->Stage) { @@ -1460,6 +1477,7 @@ set_shader_inout_layout(struct gl_shader *shader, shader->origin_upper_left = state->fs_origin_upper_left; shader->ARB_fragment_coord_conventions_enable = state->ARB_fragment_coord_conventions_enable; + shader->EarlyFragmentTests = state->fs_early_fragment_tests; break; default: diff --git a/mesalib/src/glsl/glsl_parser_extras.h b/mesalib/src/glsl/glsl_parser_extras.h index dae7864fd..9a0c24e67 100644 --- a/mesalib/src/glsl/glsl_parser_extras.h +++ b/mesalib/src/glsl/glsl_parser_extras.h @@ -160,7 +160,7 @@ struct _mesa_glsl_parse_state { { if (!this->has_separate_shader_objects()) { const char *const requirement = this->es_shader - ? "GL_EXT_separate_shader_objects extension" + ? "GL_EXT_separate_shader_objects extension or GLSL ES 310" : "GL_ARB_separate_shader_objects extension or GLSL 420"; _mesa_glsl_error(locp, this, "%s explicit location requires %s", @@ -175,17 +175,26 @@ struct _mesa_glsl_parse_state { const ir_variable *) { if (!this->has_explicit_attrib_location() || - !this->ARB_explicit_uniform_location_enable) { + !this->has_explicit_uniform_location()) { + const char *const requirement = this->es_shader + ? "GLSL ES 310" + : "GL_ARB_explicit_uniform_location and either " + "GL_ARB_explicit_attrib_location or GLSL 330."; + _mesa_glsl_error(locp, this, - "uniform explicit location requires " - "GL_ARB_explicit_uniform_location and either " - "GL_ARB_explicit_attrib_location or GLSL 330."); + "uniform explicit location requires %s", + requirement); return false; } return true; } + bool has_atomic_counters() const + { + return ARB_shader_atomic_counters_enable || is_version(420, 310); + } + bool has_explicit_attrib_stream() const { return ARB_gpu_shader5_enable || is_version(400, 0); @@ -196,6 +205,11 @@ struct _mesa_glsl_parse_state { return ARB_explicit_attrib_location_enable || is_version(330, 300); } + bool has_explicit_uniform_location() const + { + return ARB_explicit_uniform_location_enable || is_version(430, 310); + } + bool has_uniform_buffer_objects() const { return ARB_uniform_buffer_object_enable || is_version(140, 300); @@ -203,7 +217,7 @@ struct _mesa_glsl_parse_state { bool has_separate_shader_objects() const { - return ARB_separate_shader_objects_enable || is_version(410, 0) + return ARB_separate_shader_objects_enable || is_version(410, 310) || EXT_separate_shader_objects_enable; } @@ -224,7 +238,7 @@ struct _mesa_glsl_parse_state { struct { unsigned ver; bool es; - } supported_versions[14]; + } supported_versions[15]; bool es_shader; unsigned language_version; @@ -339,6 +353,16 @@ struct _mesa_glsl_parse_state { unsigned MaxCombinedAtomicCounters; unsigned MaxAtomicBufferBindings; + /* These are also atomic counter related, but they weren't added to + * until atomic counters were added to core in GLSL 4.20 and GLSL ES + * 3.10. + */ + unsigned MaxVertexAtomicCounterBuffers; + unsigned MaxGeometryAtomicCounterBuffers; + unsigned MaxFragmentAtomicCounterBuffers; + unsigned MaxCombinedAtomicCounterBuffers; + unsigned MaxAtomicCounterBufferSize; + /* ARB_compute_shader */ unsigned MaxComputeWorkGroupCount[3]; unsigned MaxComputeWorkGroupSize[3]; @@ -458,6 +482,8 @@ struct _mesa_glsl_parse_state { bool ARB_texture_rectangle_warn; bool ARB_uniform_buffer_object_enable; bool ARB_uniform_buffer_object_warn; + bool ARB_vertex_attrib_64bit_enable; + bool ARB_vertex_attrib_64bit_warn; bool ARB_viewport_array_enable; bool ARB_viewport_array_warn; @@ -510,7 +536,7 @@ struct _mesa_glsl_parse_state { */ unsigned gs_input_size; - bool early_fragment_tests; + bool fs_early_fragment_tests; /** Atomic counter offsets by binding */ unsigned atomic_counter_offsets[MAX_COMBINED_ATOMIC_BUFFERS]; diff --git a/mesalib/src/glsl/ir_set_program_inouts.cpp b/mesalib/src/glsl/ir_set_program_inouts.cpp index e877a2019..b968a1efd 100644 --- a/mesalib/src/glsl/ir_set_program_inouts.cpp +++ b/mesalib/src/glsl/ir_set_program_inouts.cpp @@ -105,13 +105,10 @@ mark(struct gl_program *prog, ir_variable *var, int offset, int len, int idx = var->data.location + var->data.index + offset + i; GLbitfield64 bitfield = BITFIELD64_BIT(idx); - /* dvec3 and dvec4 take up 2 slots */ - if (dual_slot) { - idx += i; - bitfield |= bitfield << 1; - } if (var->data.mode == ir_var_shader_in) { - prog->InputsRead |= bitfield; + prog->InputsRead |= bitfield; + if (dual_slot) + prog->DoubleInputsRead |= bitfield; if (is_fragment_shader) { gl_fragment_program *fprog = (gl_fragment_program *) prog; fprog->InterpQualifier[idx] = @@ -120,13 +117,6 @@ mark(struct gl_program *prog, ir_variable *var, int offset, int len, fprog->IsCentroid |= bitfield; if (var->data.sample) fprog->IsSample |= bitfield; - - /* Set the InterpQualifier of the next slot to the same as the - * current one, since dvec3 and dvec4 spans 2 slots. - */ - if (dual_slot) - fprog->InterpQualifier[idx + 1] = - (glsl_interp_qualifier) var->data.interpolation; } } else if (var->data.mode == ir_var_system_value) { prog->SystemValuesRead |= bitfield; diff --git a/mesalib/src/glsl/link_uniform_blocks.cpp b/mesalib/src/glsl/link_uniform_blocks.cpp index 6ca41107e..898544bea 100644 --- a/mesalib/src/glsl/link_uniform_blocks.cpp +++ b/mesalib/src/glsl/link_uniform_blocks.cpp @@ -67,14 +67,14 @@ private: assert(!"Should not get here."); } - virtual void enter_record(const glsl_type *type, const char *name, + virtual void enter_record(const glsl_type *type, const char *, bool row_major) { assert(type->is_record()); this->offset = glsl_align( this->offset, type->std140_base_alignment(row_major)); } - virtual void leave_record(const glsl_type *type, const char *name, + virtual void leave_record(const glsl_type *type, const char *, bool row_major) { assert(type->is_record()); @@ -90,8 +90,8 @@ private: } virtual void visit_field(const glsl_type *type, const char *name, - bool row_major, const glsl_type *record_type, - bool last_field) + bool row_major, const glsl_type *, + bool /* last_field */) { assert(this->index < this->num_variables); diff --git a/mesalib/src/glsl/link_uniforms.cpp b/mesalib/src/glsl/link_uniforms.cpp index d5ca23a38..2c928e144 100644 --- a/mesalib/src/glsl/link_uniforms.cpp +++ b/mesalib/src/glsl/link_uniforms.cpp @@ -544,7 +544,7 @@ private: assert(!"Should not get here."); } - virtual void enter_record(const glsl_type *type, const char *name, + virtual void enter_record(const glsl_type *type, const char *, bool row_major) { assert(type->is_record()); if (this->ubo_block_index == -1) @@ -553,7 +553,7 @@ private: this->ubo_byte_offset, type->std140_base_alignment(row_major)); } - virtual void leave_record(const glsl_type *type, const char *name, + virtual void leave_record(const glsl_type *type, const char *, bool row_major) { assert(type->is_record()); if (this->ubo_block_index == -1) @@ -564,7 +564,7 @@ private: virtual void visit_field(const glsl_type *type, const char *name, bool row_major, const glsl_type *record_type, - bool last_field) + bool /* last_field */) { assert(!type->without_array()->is_record()); assert(!type->without_array()->is_interface()); diff --git a/mesalib/src/glsl/linker.cpp b/mesalib/src/glsl/linker.cpp index 21fde9444..ea73c6f9d 100644 --- a/mesalib/src/glsl/linker.cpp +++ b/mesalib/src/glsl/linker.cpp @@ -1413,6 +1413,8 @@ link_fs_input_layout_qualifiers(struct gl_shader_program *prog, linked_shader->origin_upper_left = shader->origin_upper_left; linked_shader->pixel_center_integer = shader->pixel_center_integer; } + + linked_shader->EarlyFragmentTests |= shader->EarlyFragmentTests; } } @@ -1975,6 +1977,7 @@ assign_attribute_or_color_locations(gl_shader_program *prog, } to_assign[16]; unsigned num_attr = 0; + unsigned total_attribs_size = 0; foreach_in_list(ir_instruction, node, sh->ir) { ir_variable *const var = node->as_variable(); @@ -2016,12 +2019,41 @@ assign_attribute_or_color_locations(gl_shader_program *prog, } } + const unsigned slots = var->type->count_attribute_slots(); + + /* From GL4.5 core spec, section 11.1.1 (Vertex Attributes): + * + * "A program with more than the value of MAX_VERTEX_ATTRIBS active + * attribute variables may fail to link, unless device-dependent + * optimizations are able to make the program fit within available + * hardware resources. For the purposes of this test, attribute variables + * of the type dvec3, dvec4, dmat2x3, dmat2x4, dmat3, dmat3x4, dmat4x3, + * and dmat4 may count as consuming twice as many attributes as equivalent + * single-precision types. While these types use the same number of + * generic attributes as their single-precision equivalents, + * implementations are permitted to consume two single-precision vectors + * of internal storage for each three- or four-component double-precision + * vector." + * Until someone has a good reason in Mesa, enforce that now. + */ + if (target_index == MESA_SHADER_VERTEX) { + total_attribs_size += slots; + if (var->type->without_array() == glsl_type::dvec3_type || + var->type->without_array() == glsl_type::dvec4_type || + var->type->without_array() == glsl_type::dmat2x3_type || + var->type->without_array() == glsl_type::dmat2x4_type || + var->type->without_array() == glsl_type::dmat3_type || + var->type->without_array() == glsl_type::dmat3x4_type || + var->type->without_array() == glsl_type::dmat4x3_type || + var->type->without_array() == glsl_type::dmat4_type) + total_attribs_size += slots; + } + /* If the variable is not a built-in and has a location statically * assigned in the shader (presumably via a layout qualifier), make sure * that it doesn't collide with other assigned locations. Otherwise, * add it to the list of variables that need linker-assigned locations. */ - const unsigned slots = var->type->count_attribute_slots(); if (var->data.location != -1) { if (var->data.location >= generic_base && var->data.index < 1) { /* From page 61 of the OpenGL 4.0 spec: @@ -2141,6 +2173,15 @@ assign_attribute_or_color_locations(gl_shader_program *prog, num_attr++; } + if (target_index == MESA_SHADER_VERTEX) { + if (total_attribs_size > max_index) { + linker_error(prog, + "attempt to use %d vertex attribute slots only %d available ", + total_attribs_size, max_index); + return false; + } + } + /* If all of the attributes were assigned locations by the application (or * are built-in attributes with fixed locations), return early. This should * be the common case. @@ -2556,6 +2597,7 @@ add_interface_variables(struct gl_shader_program *shProg, { foreach_in_list(ir_instruction, node, sh->ir) { ir_variable *var = node->as_variable(); + uint8_t mask = 0; if (!var) continue; @@ -2571,6 +2613,10 @@ add_interface_variables(struct gl_shader_program *shProg, var->data.location != SYSTEM_VALUE_VERTEX_ID_ZERO_BASE && var->data.location != SYSTEM_VALUE_INSTANCE_ID) continue; + /* Mark special built-in inputs referenced by the vertex stage so + * that they are considered active by the shader queries. + */ + mask = (1 << (MESA_SHADER_VERTEX)); /* FALLTHROUGH */ case ir_var_shader_in: if (programInterface != GL_PROGRAM_INPUT) @@ -2585,7 +2631,7 @@ add_interface_variables(struct gl_shader_program *shProg, }; if (!add_program_resource(shProg, programInterface, var, - build_stageref(shProg, var->name))) + build_stageref(shProg, var->name) | mask)) return false; } return true; diff --git a/mesalib/src/glsl/nir/glsl_to_nir.cpp b/mesalib/src/glsl/nir/glsl_to_nir.cpp index f6b8331d4..af758ceb0 100644 --- a/mesalib/src/glsl/nir/glsl_to_nir.cpp +++ b/mesalib/src/glsl/nir/glsl_to_nir.cpp @@ -614,27 +614,135 @@ nir_visitor::visit(ir_call *ir) op = nir_intrinsic_atomic_counter_inc_var; } else if (strcmp(ir->callee_name(), "__intrinsic_atomic_predecrement") == 0) { op = nir_intrinsic_atomic_counter_dec_var; + } else if (strcmp(ir->callee_name(), "__intrinsic_image_load") == 0) { + op = nir_intrinsic_image_load; + } else if (strcmp(ir->callee_name(), "__intrinsic_image_store") == 0) { + op = nir_intrinsic_image_store; + } else if (strcmp(ir->callee_name(), "__intrinsic_image_atomic_add") == 0) { + op = nir_intrinsic_image_atomic_add; + } else if (strcmp(ir->callee_name(), "__intrinsic_image_atomic_min") == 0) { + op = nir_intrinsic_image_atomic_min; + } else if (strcmp(ir->callee_name(), "__intrinsic_image_atomic_max") == 0) { + op = nir_intrinsic_image_atomic_max; + } else if (strcmp(ir->callee_name(), "__intrinsic_image_atomic_and") == 0) { + op = nir_intrinsic_image_atomic_and; + } else if (strcmp(ir->callee_name(), "__intrinsic_image_atomic_or") == 0) { + op = nir_intrinsic_image_atomic_or; + } else if (strcmp(ir->callee_name(), "__intrinsic_image_atomic_xor") == 0) { + op = nir_intrinsic_image_atomic_xor; + } else if (strcmp(ir->callee_name(), "__intrinsic_image_atomic_exchange") == 0) { + op = nir_intrinsic_image_atomic_exchange; + } else if (strcmp(ir->callee_name(), "__intrinsic_image_atomic_comp_swap") == 0) { + op = nir_intrinsic_image_atomic_comp_swap; + } else if (strcmp(ir->callee_name(), "__intrinsic_memory_barrier") == 0) { + op = nir_intrinsic_memory_barrier; } else { unreachable("not reached"); } nir_intrinsic_instr *instr = nir_intrinsic_instr_create(shader, op); - ir_dereference *param = - (ir_dereference *) ir->actual_parameters.get_head(); - instr->variables[0] = evaluate_deref(&instr->instr, param); - nir_ssa_dest_init(&instr->instr, &instr->dest, 1, NULL); + + switch (op) { + case nir_intrinsic_atomic_counter_read_var: + case nir_intrinsic_atomic_counter_inc_var: + case nir_intrinsic_atomic_counter_dec_var: { + ir_dereference *param = + (ir_dereference *) ir->actual_parameters.get_head(); + instr->variables[0] = evaluate_deref(&instr->instr, param); + nir_ssa_dest_init(&instr->instr, &instr->dest, 1, NULL); + break; + } + case nir_intrinsic_image_load: + case nir_intrinsic_image_store: + case nir_intrinsic_image_atomic_add: + case nir_intrinsic_image_atomic_min: + case nir_intrinsic_image_atomic_max: + case nir_intrinsic_image_atomic_and: + case nir_intrinsic_image_atomic_or: + case nir_intrinsic_image_atomic_xor: + case nir_intrinsic_image_atomic_exchange: + case nir_intrinsic_image_atomic_comp_swap: { + nir_ssa_undef_instr *instr_undef = + nir_ssa_undef_instr_create(shader, 1); + nir_instr_insert_after_cf_list(this->cf_node_list, + &instr_undef->instr); + + /* Set the image variable dereference. */ + exec_node *param = ir->actual_parameters.get_head(); + ir_dereference *image = (ir_dereference *)param; + const glsl_type *type = + image->variable_referenced()->type->without_array(); + + instr->variables[0] = evaluate_deref(&instr->instr, image); + param = param->get_next(); + + /* Set the address argument, extending the coordinate vector to four + * components. + */ + const nir_src src_addr = evaluate_rvalue((ir_dereference *)param); + nir_alu_instr *instr_addr = nir_alu_instr_create(shader, nir_op_vec4); + nir_ssa_dest_init(&instr_addr->instr, &instr_addr->dest.dest, 4, NULL); + + for (int i = 0; i < 4; i++) { + if (i < type->coordinate_components()) { + instr_addr->src[i].src = src_addr; + instr_addr->src[i].swizzle[0] = i; + } else { + instr_addr->src[i].src = nir_src_for_ssa(&instr_undef->def); + } + } + + nir_instr_insert_after_cf_list(cf_node_list, &instr_addr->instr); + instr->src[0] = nir_src_for_ssa(&instr_addr->dest.dest.ssa); + param = param->get_next(); + + /* Set the sample argument, which is undefined for single-sample + * images. + */ + if (type->sampler_dimensionality == GLSL_SAMPLER_DIM_MS) { + instr->src[1] = evaluate_rvalue((ir_dereference *)param); + param = param->get_next(); + } else { + instr->src[1] = nir_src_for_ssa(&instr_undef->def); + } + + /* Set the intrinsic parameters. */ + if (!param->is_tail_sentinel()) { + instr->src[2] = evaluate_rvalue((ir_dereference *)param); + param = param->get_next(); + } + + if (!param->is_tail_sentinel()) { + instr->src[3] = evaluate_rvalue((ir_dereference *)param); + param = param->get_next(); + } + + /* Set the intrinsic destination. */ + if (ir->return_deref) + nir_ssa_dest_init(&instr->instr, &instr->dest, + ir->return_deref->type->vector_elements, NULL); + break; + } + case nir_intrinsic_memory_barrier: + break; + default: + unreachable("not reached"); + } nir_instr_insert_after_cf_list(this->cf_node_list, &instr->instr); - nir_intrinsic_instr *store_instr = - nir_intrinsic_instr_create(shader, nir_intrinsic_store_var); - store_instr->num_components = 1; + if (ir->return_deref) { + nir_intrinsic_instr *store_instr = + nir_intrinsic_instr_create(shader, nir_intrinsic_store_var); + store_instr->num_components = ir->return_deref->type->vector_elements; - store_instr->variables[0] = evaluate_deref(&store_instr->instr, ir->return_deref); - store_instr->src[0].is_ssa = true; - store_instr->src[0].ssa = &instr->dest.ssa; + store_instr->variables[0] = + evaluate_deref(&store_instr->instr, ir->return_deref); + store_instr->src[0] = nir_src_for_ssa(&instr->dest.ssa); - nir_instr_insert_after_cf_list(this->cf_node_list, &store_instr->instr); + nir_instr_insert_after_cf_list(this->cf_node_list, + &store_instr->instr); + } return; } @@ -824,7 +932,7 @@ nir_visitor::evaluate_rvalue(ir_rvalue* ir) nir_dest *dest = get_instr_dest(this->result); assert(dest->is_ssa); - nir_src src; + nir_src src = NIR_SRC_INIT; src.is_ssa = true; src.ssa = &dest->ssa; @@ -1038,8 +1146,8 @@ nir_visitor::visit(ir_expression *ir) case ir_unop_rcp: emit(nir_op_frcp, dest_size, srcs); break; case ir_unop_rsq: emit(nir_op_frsq, dest_size, srcs); break; case ir_unop_sqrt: emit(nir_op_fsqrt, dest_size, srcs); break; - case ir_unop_exp: emit(nir_op_fexp, dest_size, srcs); break; - case ir_unop_log: emit(nir_op_flog, dest_size, srcs); break; + case ir_unop_exp: unreachable("ir_unop_exp should have been lowered"); + case ir_unop_log: unreachable("ir_unop_log should have been lowered"); case ir_unop_exp2: emit(nir_op_fexp2, dest_size, srcs); break; case ir_unop_log2: emit(nir_op_flog2, dest_size, srcs); break; case ir_unop_i2f: diff --git a/mesalib/src/glsl/nir/nir.c b/mesalib/src/glsl/nir/nir.c index 4cc074b80..f03e80a4e 100644 --- a/mesalib/src/glsl/nir/nir.c +++ b/mesalib/src/glsl/nir/nir.c @@ -58,12 +58,9 @@ reg_create(void *mem_ctx, struct exec_list *list) nir_register *reg = ralloc(mem_ctx, nir_register); reg->parent_instr = NULL; - reg->uses = _mesa_set_create(reg, _mesa_hash_pointer, - _mesa_key_pointer_equal); - reg->defs = _mesa_set_create(reg, _mesa_hash_pointer, - _mesa_key_pointer_equal); - reg->if_uses = _mesa_set_create(reg, _mesa_hash_pointer, - _mesa_key_pointer_equal); + list_inithead(®->uses); + list_inithead(®->defs); + list_inithead(®->if_uses); reg->num_components = 0; reg->num_array_elems = 0; @@ -1070,11 +1067,14 @@ update_if_uses(nir_cf_node *node) nir_if *if_stmt = nir_cf_node_as_if(node); - struct set *if_uses_set = if_stmt->condition.is_ssa ? - if_stmt->condition.ssa->if_uses : - if_stmt->condition.reg.reg->uses; - - _mesa_set_add(if_uses_set, if_stmt); + if_stmt->condition.parent_if = if_stmt; + if (if_stmt->condition.is_ssa) { + list_addtail(&if_stmt->condition.use_link, + &if_stmt->condition.ssa->if_uses); + } else { + list_addtail(&if_stmt->condition.use_link, + &if_stmt->condition.reg.reg->if_uses); + } } void @@ -1227,16 +1227,7 @@ cleanup_cf_node(nir_cf_node *node) foreach_list_typed(nir_cf_node, child, node, &if_stmt->else_list) cleanup_cf_node(child); - struct set *if_uses; - if (if_stmt->condition.is_ssa) { - if_uses = if_stmt->condition.ssa->if_uses; - } else { - if_uses = if_stmt->condition.reg.reg->if_uses; - } - - struct set_entry *entry = _mesa_set_search(if_uses, if_stmt); - assert(entry); - _mesa_set_remove(if_uses, entry); + list_del(&if_stmt->condition.use_link); break; } @@ -1293,9 +1284,9 @@ add_use_cb(nir_src *src, void *state) { nir_instr *instr = state; - struct set *uses_set = src->is_ssa ? src->ssa->uses : src->reg.reg->uses; - - _mesa_set_add(uses_set, instr); + src->parent_instr = instr; + list_addtail(&src->use_link, + src->is_ssa ? &src->ssa->uses : &src->reg.reg->uses); return true; } @@ -1320,8 +1311,10 @@ add_reg_def_cb(nir_dest *dest, void *state) { nir_instr *instr = state; - if (!dest->is_ssa) - _mesa_set_add(dest->reg.reg->defs, instr); + if (!dest->is_ssa) { + dest->reg.parent_instr = instr; + list_addtail(&dest->reg.def_link, &dest->reg.reg->defs); + } return true; } @@ -1436,13 +1429,7 @@ nir_instr_insert_after_cf_list(struct exec_list *list, nir_instr *after) static bool remove_use_cb(nir_src *src, void *state) { - nir_instr *instr = state; - - struct set *uses_set = src->is_ssa ? src->ssa->uses : src->reg.reg->uses; - - struct set_entry *entry = _mesa_set_search(uses_set, instr); - if (entry) - _mesa_set_remove(uses_set, entry); + list_del(&src->use_link); return true; } @@ -1450,16 +1437,8 @@ remove_use_cb(nir_src *src, void *state) static bool remove_def_cb(nir_dest *dest, void *state) { - nir_instr *instr = state; - - if (dest->is_ssa) - return true; - - nir_register *reg = dest->reg.reg; - - struct set_entry *entry = _mesa_set_search(reg->defs, instr); - if (entry) - _mesa_set_remove(reg->defs, entry); + if (!dest->is_ssa) + list_del(&dest->reg.def_link); return true; } @@ -1834,64 +1813,77 @@ nir_srcs_equal(nir_src src1, nir_src src2) } static bool -src_does_not_use_def(nir_src *src, void *void_def) +src_is_valid(const nir_src *src) { - nir_ssa_def *def = void_def; - - if (src->is_ssa) { - return src->ssa != def; - } else { - return true; - } + return src->is_ssa ? (src->ssa != NULL) : (src->reg.reg != NULL); } -static bool -src_does_not_use_reg(nir_src *src, void *void_reg) +static void +src_remove_all_uses(nir_src *src) { - nir_register *reg = void_reg; + for (; src; src = src->is_ssa ? NULL : src->reg.indirect) { + if (!src_is_valid(src)) + continue; - if (src->is_ssa) { - return true; - } else { - return src->reg.reg != reg; + list_del(&src->use_link); + } +} + +static void +src_add_all_uses(nir_src *src, nir_instr *parent_instr, nir_if *parent_if) +{ + for (; src; src = src->is_ssa ? NULL : src->reg.indirect) { + if (!src_is_valid(src)) + continue; + + if (parent_instr) { + src->parent_instr = parent_instr; + if (src->is_ssa) + list_addtail(&src->use_link, &src->ssa->uses); + else + list_addtail(&src->use_link, &src->reg.reg->uses); + } else { + assert(parent_if); + src->parent_if = parent_if; + if (src->is_ssa) + list_addtail(&src->use_link, &src->ssa->if_uses); + else + list_addtail(&src->use_link, &src->reg.reg->if_uses); + } } } void nir_instr_rewrite_src(nir_instr *instr, nir_src *src, nir_src new_src) { - nir_src old_src = *src; + assert(!src_is_valid(src) || src->parent_instr == instr); + + src_remove_all_uses(src); *src = new_src; + src_add_all_uses(src, instr, NULL); +} - for (nir_src *iter_src = &old_src; iter_src; - iter_src = iter_src->is_ssa ? NULL : iter_src->reg.indirect) { - if (iter_src->is_ssa) { - nir_ssa_def *ssa = iter_src->ssa; - if (ssa && nir_foreach_src(instr, src_does_not_use_def, ssa)) { - struct set_entry *entry = _mesa_set_search(ssa->uses, instr); - assert(entry); - _mesa_set_remove(ssa->uses, entry); - } - } else { - nir_register *reg = iter_src->reg.reg; - if (reg && nir_foreach_src(instr, src_does_not_use_reg, reg)) { - struct set_entry *entry = _mesa_set_search(reg->uses, instr); - assert(entry); - _mesa_set_remove(reg->uses, entry); - } - } - } +void +nir_instr_move_src(nir_instr *dest_instr, nir_src *dest, nir_src *src) +{ + assert(!src_is_valid(dest) || dest->parent_instr == dest_instr); - for (nir_src *iter_src = &new_src; iter_src; - iter_src = iter_src->is_ssa ? NULL : iter_src->reg.indirect) { - if (iter_src->is_ssa) { - if (iter_src->ssa) - _mesa_set_add(iter_src->ssa->uses, instr); - } else { - if (iter_src->reg.reg) - _mesa_set_add(iter_src->reg.reg->uses, instr); - } - } + src_remove_all_uses(dest); + src_remove_all_uses(src); + *dest = *src; + *src = NIR_SRC_INIT; + src_add_all_uses(dest, dest_instr, NULL); +} + +void +nir_if_rewrite_condition(nir_if *if_stmt, nir_src new_src) +{ + nir_src *src = &if_stmt->condition; + assert(!src_is_valid(src) || src->parent_if == if_stmt); + + src_remove_all_uses(src); + *src = new_src; + src_add_all_uses(src, NULL, if_stmt); } void @@ -1900,10 +1892,8 @@ nir_ssa_def_init(nir_instr *instr, nir_ssa_def *def, { def->name = name; def->parent_instr = instr; - def->uses = _mesa_set_create(instr, _mesa_hash_pointer, - _mesa_key_pointer_equal); - def->if_uses = _mesa_set_create(instr, _mesa_hash_pointer, - _mesa_key_pointer_equal); + list_inithead(&def->uses); + list_inithead(&def->if_uses); def->num_components = num_components; if (instr->block) { @@ -1924,57 +1914,23 @@ nir_ssa_dest_init(nir_instr *instr, nir_dest *dest, nir_ssa_def_init(instr, &dest->ssa, num_components, name); } -struct ssa_def_rewrite_state { - void *mem_ctx; - nir_ssa_def *old; - nir_src new_src; -}; - -static bool -ssa_def_rewrite_uses_src(nir_src *src, void *void_state) -{ - struct ssa_def_rewrite_state *state = void_state; - - if (src->is_ssa && src->ssa == state->old) - nir_src_copy(src, &state->new_src, state->mem_ctx); - - return true; -} - void nir_ssa_def_rewrite_uses(nir_ssa_def *def, nir_src new_src, void *mem_ctx) { - struct ssa_def_rewrite_state state; - state.mem_ctx = mem_ctx; - state.old = def; - state.new_src = new_src; - assert(!new_src.is_ssa || def != new_src.ssa); - struct set *new_uses, *new_if_uses; - if (new_src.is_ssa) { - new_uses = new_src.ssa->uses; - new_if_uses = new_src.ssa->if_uses; - } else { - new_uses = new_src.reg.reg->uses; - new_if_uses = new_src.reg.reg->if_uses; - } - - struct set_entry *entry; - set_foreach(def->uses, entry) { - nir_instr *instr = (nir_instr *)entry->key; - - _mesa_set_remove(def->uses, entry); - nir_foreach_src(instr, ssa_def_rewrite_uses_src, &state); - _mesa_set_add(new_uses, instr); + nir_foreach_use_safe(def, use_src) { + nir_instr *src_parent_instr = use_src->parent_instr; + list_del(&use_src->use_link); + nir_src_copy(use_src, &new_src, mem_ctx); + src_add_all_uses(use_src, src_parent_instr, NULL); } - set_foreach(def->if_uses, entry) { - nir_if *if_use = (nir_if *)entry->key; - - _mesa_set_remove(def->if_uses, entry); - nir_src_copy(&if_use->condition, &new_src, mem_ctx); - _mesa_set_add(new_if_uses, if_use); + nir_foreach_if_use_safe(def, use_src) { + nir_if *src_parent_if = use_src->parent_if; + list_del(&use_src->use_link); + nir_src_copy(use_src, &new_src, mem_ctx); + src_add_all_uses(use_src, NULL, src_parent_if); } } diff --git a/mesalib/src/glsl/nir/nir.h b/mesalib/src/glsl/nir/nir.h index 98b0ec328..697d37e95 100644 --- a/mesalib/src/glsl/nir/nir.h +++ b/mesalib/src/glsl/nir/nir.h @@ -30,6 +30,7 @@ #include "util/hash_table.h" #include "../list.h" #include "GL/gl.h" /* GLenum */ +#include "util/list.h" #include "util/ralloc.h" #include "util/set.h" #include "util/bitset.h" @@ -397,13 +398,13 @@ typedef struct { struct nir_instr *parent_instr; /** set of nir_instr's where this register is used (read from) */ - struct set *uses; + struct list_head uses; /** set of nir_instr's where this register is defined (written to) */ - struct set *defs; + struct list_head defs; /** set of nir_if's where this register is used as a condition */ - struct set *if_uses; + struct list_head if_uses; } nir_register; typedef enum { @@ -462,10 +463,10 @@ typedef struct { nir_instr *parent_instr; /** set of nir_instr's where this register is used (read from) */ - struct set *uses; + struct list_head uses; /** set of nir_if's where this register is used as a condition */ - struct set *if_uses; + struct list_head if_uses; uint8_t num_components; } nir_ssa_def; @@ -481,6 +482,9 @@ typedef struct { } nir_reg_src; typedef struct { + nir_instr *parent_instr; + struct list_head def_link; + nir_register *reg; struct nir_src *indirect; /** < NULL for no indirect offset */ unsigned base_offset; @@ -488,8 +492,17 @@ typedef struct { /* TODO def-use chain goes here */ } nir_reg_dest; +struct nir_if; + typedef struct nir_src { union { + nir_instr *parent_instr; + struct nir_if *parent_if; + }; + + struct list_head use_link; + + union { nir_reg_src reg; nir_ssa_def *ssa; }; @@ -497,6 +510,20 @@ typedef struct nir_src { bool is_ssa; } nir_src; +#define NIR_SRC_INIT (nir_src) { { NULL } } + +#define nir_foreach_use(reg_or_ssa_def, src) \ + list_for_each_entry(nir_src, src, &(reg_or_ssa_def)->uses, use_link) + +#define nir_foreach_use_safe(reg_or_ssa_def, src) \ + list_for_each_entry_safe(nir_src, src, &(reg_or_ssa_def)->uses, use_link) + +#define nir_foreach_if_use(reg_or_ssa_def, src) \ + list_for_each_entry(nir_src, src, &(reg_or_ssa_def)->if_uses, use_link) + +#define nir_foreach_if_use_safe(reg_or_ssa_def, src) \ + list_for_each_entry_safe(nir_src, src, &(reg_or_ssa_def)->if_uses, use_link) + typedef struct { union { nir_reg_dest reg; @@ -506,10 +533,18 @@ typedef struct { bool is_ssa; } nir_dest; +#define NIR_DEST_INIT (nir_dest) { { { NULL } } } + +#define nir_foreach_def(reg, dest) \ + list_for_each_entry(nir_dest, dest, &(reg)->defs, reg.def_link) + +#define nir_foreach_def_safe(reg, dest) \ + list_for_each_entry_safe(nir_dest, dest, &(reg)->defs, reg.def_link) + static inline nir_src nir_src_for_ssa(nir_ssa_def *def) { - nir_src src; + nir_src src = NIR_SRC_INIT; src.is_ssa = true; src.ssa = def; @@ -520,7 +555,7 @@ nir_src_for_ssa(nir_ssa_def *def) static inline nir_src nir_src_for_reg(nir_register *reg) { - nir_src src; + nir_src src = NIR_SRC_INIT; src.is_ssa = false; src.reg.reg = reg; @@ -543,12 +578,9 @@ nir_src_get_parent_instr(const nir_src *src) static inline nir_dest nir_dest_for_reg(nir_register *reg) { - nir_dest dest; + nir_dest dest = NIR_DEST_INIT; - dest.is_ssa = false; dest.reg.reg = reg; - dest.reg.indirect = NULL; - dest.reg.base_offset = 0; return dest; } @@ -1207,7 +1239,7 @@ nir_block_last_instr(nir_block *block) #define nir_foreach_instr_safe(block, instr) \ foreach_list_typed_safe(nir_instr, instr, node, &(block)->instr_list) -typedef struct { +typedef struct nir_if { nir_cf_node cf_node; nir_src condition; @@ -1548,6 +1580,8 @@ bool nir_foreach_src(nir_instr *instr, nir_foreach_src_cb cb, void *state); nir_const_value *nir_src_as_const_value(nir_src src); bool nir_srcs_equal(nir_src src1, nir_src src2); void nir_instr_rewrite_src(nir_instr *instr, nir_src *src, nir_src new_src); +void nir_instr_move_src(nir_instr *dest_instr, nir_src *dest, nir_src *src); +void nir_if_rewrite_condition(nir_if *if_stmt, nir_src new_src); void nir_ssa_dest_init(nir_instr *instr, nir_dest *dest, unsigned num_components, const char *name); diff --git a/mesalib/src/glsl/nir/nir_builder.h b/mesalib/src/glsl/nir/nir_builder.h index d1419ee21..9223e8380 100644 --- a/mesalib/src/glsl/nir/nir_builder.h +++ b/mesalib/src/glsl/nir/nir_builder.h @@ -231,8 +231,7 @@ static inline nir_ssa_def * nir_swizzle(nir_builder *build, nir_ssa_def *src, unsigned swiz[4], unsigned num_components, bool use_fmov) { - nir_alu_src alu_src; - memset(&alu_src, 0, sizeof(alu_src)); + nir_alu_src alu_src = { NIR_SRC_INIT }; alu_src.src = nir_src_for_ssa(src); for (int i = 0; i < 4; i++) alu_src.swizzle[i] = swiz[i]; @@ -251,8 +250,7 @@ nir_ssa_for_src(nir_builder *build, nir_src src, int num_components) if (src.is_ssa && src.ssa->num_components == num_components) return src.ssa; - nir_alu_src alu; - memset(&alu, 0, sizeof(alu)); + nir_alu_src alu = { NIR_SRC_INIT }; alu.src = src; for (int j = 0; j < 4; j++) alu.swizzle[j] = j; diff --git a/mesalib/src/glsl/nir/nir_from_ssa.c b/mesalib/src/glsl/nir/nir_from_ssa.c index 6a3b141bd..67733e6da 100644 --- a/mesalib/src/glsl/nir/nir_from_ssa.c +++ b/mesalib/src/glsl/nir/nir_from_ssa.c @@ -37,7 +37,6 @@ struct from_ssa_state { void *mem_ctx; void *dead_ctx; - struct hash_table *ssa_table; struct hash_table *merge_node_table; nir_instr *instr; nir_function_impl *impl; @@ -344,45 +343,31 @@ isolate_phi_nodes_block(nir_block *block, void *void_state) get_parallel_copy_at_end_of_block(src->pred); assert(pcopy); - nir_parallel_copy_entry *entry = ralloc(state->dead_ctx, - nir_parallel_copy_entry); - exec_list_push_tail(&pcopy->entries, &entry->node); - - nir_src_copy(&entry->src, &src->src, state->dead_ctx); - _mesa_set_add(src->src.ssa->uses, &pcopy->instr); - + nir_parallel_copy_entry *entry = rzalloc(state->dead_ctx, + nir_parallel_copy_entry); nir_ssa_dest_init(&pcopy->instr, &entry->dest, phi->dest.ssa.num_components, src->src.ssa->name); + exec_list_push_tail(&pcopy->entries, &entry->node); - struct set_entry *use_entry = - _mesa_set_search(src->src.ssa->uses, instr); - if (use_entry) - /* It is possible that a phi node can use the same source twice - * but for different basic blocks. If that happens, entry will - * be NULL because we already deleted it. This is safe - * because, by the time the loop is done, we will have deleted - * all of the sources of the phi from their respective use sets - * and moved them to the parallel copy definitions. - */ - _mesa_set_remove(src->src.ssa->uses, use_entry); + assert(src->src.is_ssa); + nir_instr_rewrite_src(&pcopy->instr, &entry->src, src->src); - src->src.ssa = &entry->dest.ssa; - _mesa_set_add(entry->dest.ssa.uses, instr); + nir_instr_rewrite_src(&phi->instr, &src->src, + nir_src_for_ssa(&entry->dest.ssa)); } - nir_parallel_copy_entry *entry = ralloc(state->dead_ctx, - nir_parallel_copy_entry); - exec_list_push_tail(&block_pcopy->entries, &entry->node); - + nir_parallel_copy_entry *entry = rzalloc(state->dead_ctx, + nir_parallel_copy_entry); nir_ssa_dest_init(&block_pcopy->instr, &entry->dest, phi->dest.ssa.num_components, phi->dest.ssa.name); + exec_list_push_tail(&block_pcopy->entries, &entry->node); + nir_ssa_def_rewrite_uses(&phi->dest.ssa, nir_src_for_ssa(&entry->dest.ssa), state->mem_ctx); - entry->src.is_ssa = true; - entry->src.ssa = &phi->dest.ssa; - _mesa_set_add(phi->dest.ssa.uses, &block_pcopy->instr); + nir_instr_rewrite_src(&block_pcopy->instr, &entry->src, + nir_src_for_ssa(&phi->dest.ssa)); } return true; @@ -415,7 +400,7 @@ coalesce_phi_nodes_block(nir_block *block, void *void_state) } static void -agressive_coalesce_parallel_copy(nir_parallel_copy_instr *pcopy, +aggressive_coalesce_parallel_copy(nir_parallel_copy_instr *pcopy, struct from_ssa_state *state) { nir_foreach_parallel_copy_entry(pcopy, entry) { @@ -444,7 +429,7 @@ agressive_coalesce_parallel_copy(nir_parallel_copy_instr *pcopy, } static bool -agressive_coalesce_block(nir_block *block, void *void_state) +aggressive_coalesce_block(nir_block *block, void *void_state) { struct from_ssa_state *state = void_state; @@ -457,7 +442,7 @@ agressive_coalesce_block(nir_block *block, void *void_state) start_pcopy = nir_instr_as_parallel_copy(instr); - agressive_coalesce_parallel_copy(start_pcopy, state); + aggressive_coalesce_parallel_copy(start_pcopy, state); break; } @@ -467,17 +452,21 @@ agressive_coalesce_block(nir_block *block, void *void_state) get_parallel_copy_at_end_of_block(block); if (end_pcopy && end_pcopy != start_pcopy) - agressive_coalesce_parallel_copy(end_pcopy, state); + aggressive_coalesce_parallel_copy(end_pcopy, state); return true; } -static nir_register * -get_register_for_ssa_def(nir_ssa_def *def, struct from_ssa_state *state) +static bool +rewrite_ssa_def(nir_ssa_def *def, void *void_state) { + struct from_ssa_state *state = void_state; + nir_register *reg; + struct hash_entry *entry = _mesa_hash_table_search(state->merge_node_table, def); if (entry) { + /* In this case, we're part of a phi web. Use the web's register. */ merge_node *node = (merge_node *)entry->data; /* If it doesn't have a register yet, create one. Note that all of @@ -491,20 +480,15 @@ get_register_for_ssa_def(nir_ssa_def *def, struct from_ssa_state *state) node->set->reg->num_array_elems = 0; } - return node->set->reg; - } - - entry = _mesa_hash_table_search(state->ssa_table, def); - if (entry) { - return (nir_register *)entry->data; + reg = node->set->reg; } else { /* We leave load_const SSA values alone. They act as immediates to * the backend. If it got coalesced into a phi, that's ok. */ if (def->parent_instr->type == nir_instr_type_load_const) - return NULL; + return true; - nir_register *reg = nir_local_reg_create(state->impl); + reg = nir_local_reg_create(state->impl); reg->name = def->name; reg->num_components = def->num_components; reg->num_array_elems = 0; @@ -516,57 +500,24 @@ get_register_for_ssa_def(nir_ssa_def *def, struct from_ssa_state *state) */ if (def->parent_instr->type != nir_instr_type_ssa_undef) reg->parent_instr = def->parent_instr; - - _mesa_hash_table_insert(state->ssa_table, def, reg); - return reg; } -} - -static bool -rewrite_ssa_src(nir_src *src, void *void_state) -{ - struct from_ssa_state *state = void_state; - if (src->is_ssa) { - nir_register *reg = get_register_for_ssa_def(src->ssa, state); + nir_ssa_def_rewrite_uses(def, nir_src_for_reg(reg), state->mem_ctx); + assert(list_empty(&def->uses) && list_empty(&def->if_uses)); - if (reg == NULL) { - assert(src->ssa->parent_instr->type == nir_instr_type_load_const); - return true; - } - - memset(src, 0, sizeof *src); - src->reg.reg = reg; - - /* We don't need to remove it from the uses set because that is going - * away. We just need to add it to the one for the register. */ - _mesa_set_add(reg->uses, state->instr); - } - - return true; -} - -static bool -rewrite_ssa_dest(nir_dest *dest, void *void_state) -{ - struct from_ssa_state *state = void_state; - - if (dest->is_ssa) { - nir_register *reg = get_register_for_ssa_def(&dest->ssa, state); - - if (reg == NULL) { - assert(dest->ssa.parent_instr->type == nir_instr_type_load_const); - return true; - } + if (def->parent_instr->type == nir_instr_type_ssa_undef) + return true; - _mesa_set_destroy(dest->ssa.uses, NULL); - _mesa_set_destroy(dest->ssa.if_uses, NULL); + assert(def->parent_instr->type != nir_instr_type_load_const); - memset(dest, 0, sizeof *dest); - dest->reg.reg = reg; + /* At this point we know a priori that this SSA def is part of a + * nir_dest. We can use exec_node_data to get the dest pointer. + */ + nir_dest *dest = exec_node_data(nir_dest, def, ssa); - _mesa_set_add(reg->defs, state->instr); - } + *dest = nir_dest_for_reg(reg); + dest->reg.parent_instr = state->instr; + list_addtail(&dest->reg.def_link, ®->defs); return true; } @@ -581,8 +532,7 @@ resolve_registers_block(nir_block *block, void *void_state) nir_foreach_instr_safe(block, instr) { state->instr = instr; - nir_foreach_src(instr, rewrite_ssa_src, state); - nir_foreach_dest(instr, rewrite_ssa_dest, state); + nir_foreach_ssa_def(instr, rewrite_ssa_def, state); if (instr->type == nir_instr_type_ssa_undef || instr->type == nir_instr_type_phi) { @@ -592,23 +542,6 @@ resolve_registers_block(nir_block *block, void *void_state) } state->instr = NULL; - nir_if *following_if = nir_block_get_following_if(block); - if (following_if && following_if->condition.is_ssa) { - nir_register *reg = get_register_for_ssa_def(following_if->condition.ssa, - state); - if (reg) { - memset(&following_if->condition, 0, sizeof following_if->condition); - following_if->condition.reg.reg = reg; - - _mesa_set_add(reg->if_uses, following_if); - } else { - /* FIXME: We really shouldn't hit this. We should be doing - * constant control flow propagation. - */ - assert(following_if->condition.ssa->parent_instr->type == nir_instr_type_load_const); - } - } - return true; } @@ -853,10 +786,8 @@ nir_convert_from_ssa_impl(nir_function_impl *impl) nir_metadata_dominance); nir_foreach_block(impl, coalesce_phi_nodes_block, &state); - nir_foreach_block(impl, agressive_coalesce_block, &state); + nir_foreach_block(impl, aggressive_coalesce_block, &state); - state.ssa_table = _mesa_hash_table_create(NULL, _mesa_hash_pointer, - _mesa_key_pointer_equal); nir_foreach_block(impl, resolve_registers_block, &state); nir_foreach_block(impl, resolve_parallel_copies_block, &state); @@ -865,7 +796,6 @@ nir_convert_from_ssa_impl(nir_function_impl *impl) nir_metadata_dominance); /* Clean up dead instructions and the hash tables */ - _mesa_hash_table_destroy(state.ssa_table, NULL); _mesa_hash_table_destroy(state.merge_node_table, NULL); ralloc_free(state.dead_ctx); } diff --git a/mesalib/src/glsl/nir/nir_intrinsics.h b/mesalib/src/glsl/nir/nir_intrinsics.h index 8e28765c1..10192c531 100644 --- a/mesalib/src/glsl/nir/nir_intrinsics.h +++ b/mesalib/src/glsl/nir/nir_intrinsics.h @@ -68,6 +68,13 @@ INTRINSIC(interp_var_at_offset, 1, ARR(2), true, 0, 1, 0, #define BARRIER(name) INTRINSIC(name, 0, ARR(), false, 0, 0, 0, 0) BARRIER(discard) + +/* + * Memory barrier with semantics analogous to the memoryBarrier() GLSL + * intrinsic. + */ +BARRIER(memory_barrier) + /** A conditional discard, with a single boolean source. */ INTRINSIC(discard_if, 1, ARR(1), false, 0, 0, 0, 0) @@ -89,6 +96,33 @@ ATOMIC(inc, 0) ATOMIC(dec, 0) ATOMIC(read, NIR_INTRINSIC_CAN_ELIMINATE) +/* + * Image load, store and atomic intrinsics. + * + * All image intrinsics take an image target passed as a nir_variable. Image + * variables contain a number of memory and layout qualifiers that influence + * the semantics of the intrinsic. + * + * All image intrinsics take a four-coordinate vector and a sample index as + * first two sources, determining the location within the image that will be + * accessed by the intrinsic. Components not applicable to the image target + * in use are undefined. Image store takes an additional four-component + * argument with the value to be written, and image atomic operations take + * either one or two additional scalar arguments with the same meaning as in + * the ARB_shader_image_load_store specification. + */ +INTRINSIC(image_load, 2, ARR(4, 1), true, 4, 1, 0, + NIR_INTRINSIC_CAN_ELIMINATE) +INTRINSIC(image_store, 3, ARR(4, 1, 4), false, 0, 1, 0, 0) +INTRINSIC(image_atomic_add, 3, ARR(4, 1, 1), true, 1, 1, 0, 0) +INTRINSIC(image_atomic_min, 3, ARR(4, 1, 1), true, 1, 1, 0, 0) +INTRINSIC(image_atomic_max, 3, ARR(4, 1, 1), true, 1, 1, 0, 0) +INTRINSIC(image_atomic_and, 3, ARR(4, 1, 1), true, 1, 1, 0, 0) +INTRINSIC(image_atomic_or, 3, ARR(4, 1, 1), true, 1, 1, 0, 0) +INTRINSIC(image_atomic_xor, 3, ARR(4, 1, 1), true, 1, 1, 0, 0) +INTRINSIC(image_atomic_exchange, 3, ARR(4, 1, 1), true, 1, 1, 0, 0) +INTRINSIC(image_atomic_comp_swap, 4, ARR(4, 1, 1, 1), true, 1, 1, 0, 0) + #define SYSTEM_VALUE(name, components) \ INTRINSIC(load_##name, 0, ARR(), true, components, 0, 0, \ NIR_INTRINSIC_CAN_ELIMINATE | NIR_INTRINSIC_CAN_REORDER) diff --git a/mesalib/src/glsl/nir/nir_lower_atomics.c b/mesalib/src/glsl/nir/nir_lower_atomics.c index e82df0169..f6f89020f 100644 --- a/mesalib/src/glsl/nir/nir_lower_atomics.c +++ b/mesalib/src/glsl/nir/nir_lower_atomics.c @@ -78,7 +78,8 @@ lower_instr(nir_intrinsic_instr *instr, nir_function_impl *impl) nir_deref_as_array(instr->variables[0]->deref.child); assert(deref_array->deref.child == NULL); - offset_const->value.u[0] += deref_array->base_offset; + offset_const->value.u[0] += + deref_array->base_offset * ATOMIC_COUNTER_SIZE; if (deref_array->deref_array_type == nir_deref_array_type_indirect) { nir_load_const_instr *atomic_counter_size = diff --git a/mesalib/src/glsl/nir/nir_lower_locals_to_regs.c b/mesalib/src/glsl/nir/nir_lower_locals_to_regs.c index bc6a3d320..28fdec50e 100644 --- a/mesalib/src/glsl/nir/nir_lower_locals_to_regs.c +++ b/mesalib/src/glsl/nir/nir_lower_locals_to_regs.c @@ -269,18 +269,16 @@ lower_locals_to_regs_block(nir_block *block, void *void_state) static nir_block * compute_reg_usedef_lca(nir_register *reg) { - struct set_entry *entry; nir_block *lca = NULL; - set_foreach(reg->defs, entry) - lca = nir_dominance_lca(lca, ((nir_instr *)entry->key)->block); + list_for_each_entry(nir_dest, def_dest, ®->defs, reg.def_link) + lca = nir_dominance_lca(lca, def_dest->reg.parent_instr->block); - set_foreach(reg->uses, entry) - lca = nir_dominance_lca(lca, ((nir_instr *)entry->key)->block); + list_for_each_entry(nir_src, use_src, ®->uses, use_link) + lca = nir_dominance_lca(lca, use_src->parent_instr->block); - set_foreach(reg->if_uses, entry) { - nir_if *if_stmt = (nir_if *)entry->key; - nir_cf_node *prev_node = nir_cf_node_prev(&if_stmt->cf_node); + list_for_each_entry(nir_src, use_src, ®->if_uses, use_link) { + nir_cf_node *prev_node = nir_cf_node_prev(&use_src->parent_if->cf_node); assert(prev_node->type == nir_cf_node_block); lca = nir_dominance_lca(lca, nir_cf_node_as_block(prev_node)); } diff --git a/mesalib/src/glsl/nir/nir_lower_samplers.cpp b/mesalib/src/glsl/nir/nir_lower_samplers.cpp index cf8ab8325..7a0b0a09f 100644 --- a/mesalib/src/glsl/nir/nir_lower_samplers.cpp +++ b/mesalib/src/glsl/nir/nir_lower_samplers.cpp @@ -70,44 +70,45 @@ lower_sampler(nir_tex_instr *instr, const struct gl_shader_program *shader_progr case nir_deref_type_array: { nir_deref_array *deref_array = nir_deref_as_array(deref->child); + assert(deref_array->deref_array_type != nir_deref_array_type_wildcard); + + if (deref_array->deref.child) { + ralloc_asprintf_append(&name, "[%u]", + deref_array->deref_array_type == nir_deref_array_type_direct ? + deref_array->base_offset : 0); + } else { + assert(deref->child->type->base_type == GLSL_TYPE_SAMPLER); + instr->sampler_index = deref_array->base_offset; + } + /* XXX: We're assuming here that the indirect is the last array * thing we have. This should be ok for now as we don't support * arrays_of_arrays yet. */ - - instr->sampler_index *= glsl_get_length(deref->type); - switch (deref_array->deref_array_type) { - case nir_deref_array_type_direct: - instr->sampler_index += deref_array->base_offset; - if (deref_array->deref.child) - ralloc_asprintf_append(&name, "[%u]", deref_array->base_offset); - break; - case nir_deref_array_type_indirect: { - instr->src = reralloc(instr, instr->src, nir_tex_src, - instr->num_srcs + 1); - memset(&instr->src[instr->num_srcs], 0, sizeof *instr->src); + if (deref_array->deref_array_type == nir_deref_array_type_indirect) { + /* First, we have to resize the array of texture sources */ + nir_tex_src *new_srcs = rzalloc_array(instr, nir_tex_src, + instr->num_srcs + 1); + + for (unsigned i = 0; i < instr->num_srcs; i++) { + new_srcs[i].src_type = instr->src[i].src_type; + nir_instr_move_src(&instr->instr, &new_srcs[i].src, + &instr->src[i].src); + } + + ralloc_free(instr->src); + instr->src = new_srcs; + + /* Now we can go ahead and move the source over to being a + * first-class texture source. + */ instr->src[instr->num_srcs].src_type = nir_tex_src_sampler_offset; instr->num_srcs++; - - nir_instr_rewrite_src(&instr->instr, - &instr->src[instr->num_srcs - 1].src, - deref_array->indirect); + nir_instr_move_src(&instr->instr, + &instr->src[instr->num_srcs - 1].src, + &deref_array->indirect); instr->sampler_array_size = glsl_get_length(deref->type); - - nir_src empty; - memset(&empty, 0, sizeof empty); - nir_instr_rewrite_src(&instr->instr, &deref_array->indirect, empty); - - if (deref_array->deref.child) - ralloc_strcat(&name, "[0]"); - break; - } - - case nir_deref_array_type_wildcard: - unreachable("Cannot copy samplers"); - default: - unreachable("Invalid deref array type"); } break; } diff --git a/mesalib/src/glsl/nir/nir_lower_tex_projector.c b/mesalib/src/glsl/nir/nir_lower_tex_projector.c index 6b0e9c340..357131cd7 100644 --- a/mesalib/src/glsl/nir/nir_lower_tex_projector.c +++ b/mesalib/src/glsl/nir/nir_lower_tex_projector.c @@ -109,12 +109,12 @@ nir_lower_tex_projector_block(nir_block *block, void *void_state) /* Now move the later tex sources down the array so that the projector * disappears. */ - nir_src dead; - memset(&dead, 0, sizeof dead); - nir_instr_rewrite_src(&tex->instr, &tex->src[proj_index].src, dead); - memmove(&tex->src[proj_index], - &tex->src[proj_index + 1], - (tex->num_srcs - proj_index) * sizeof(*tex->src)); + nir_instr_rewrite_src(&tex->instr, &tex->src[proj_index].src, + NIR_SRC_INIT); + for (int i = proj_index + 1; i < tex->num_srcs; i++) { + tex->src[i-1].src_type = tex->src[i].src_type; + nir_instr_move_src(&tex->instr, &tex->src[i-1].src, &tex->src[i].src); + } tex->num_srcs--; } diff --git a/mesalib/src/glsl/nir/nir_lower_to_source_mods.c b/mesalib/src/glsl/nir/nir_lower_to_source_mods.c index 7b4a0f657..94c7e36d4 100644 --- a/mesalib/src/glsl/nir/nir_lower_to_source_mods.c +++ b/mesalib/src/glsl/nir/nir_lower_to_source_mods.c @@ -88,8 +88,8 @@ nir_lower_to_source_mods_block(nir_block *block, void *state) alu->src[i].swizzle[j] = parent->src[0].swizzle[alu->src[i].swizzle[j]]; } - if (parent->dest.dest.ssa.uses->entries == 0 && - parent->dest.dest.ssa.if_uses->entries == 0) + if (list_empty(&parent->dest.dest.ssa.uses) && + list_empty(&parent->dest.dest.ssa.if_uses)) nir_instr_remove(&parent->instr); } @@ -131,13 +131,13 @@ nir_lower_to_source_mods_block(nir_block *block, void *state) if (nir_op_infos[alu->op].output_type != nir_type_float) continue; - if (alu->dest.dest.ssa.if_uses->entries != 0) + if (!list_empty(&alu->dest.dest.ssa.if_uses)) continue; bool all_children_are_sat = true; - struct set_entry *entry; - set_foreach(alu->dest.dest.ssa.uses, entry) { - const nir_instr *child = entry->key; + nir_foreach_use(&alu->dest.dest.ssa, child_src) { + assert(child_src->is_ssa); + nir_instr *child = child_src->parent_instr; if (child->type != nir_instr_type_alu) { all_children_are_sat = false; continue; @@ -161,8 +161,12 @@ nir_lower_to_source_mods_block(nir_block *block, void *state) alu->dest.saturate = true; - set_foreach(alu->dest.dest.ssa.uses, entry) { - nir_alu_instr *child_alu = nir_instr_as_alu((nir_instr *)entry->key); + nir_foreach_use(&alu->dest.dest.ssa, child_src) { + assert(child_src->is_ssa); + nir_instr *child = child_src->parent_instr; + assert(child->type == nir_instr_type_alu); + nir_alu_instr *child_alu = nir_instr_as_alu(child); + child_alu->op = nir_op_fmov; child_alu->dest.saturate = false; /* We could propagate the dest of our instruction to the diff --git a/mesalib/src/glsl/nir/nir_lower_vars_to_ssa.c b/mesalib/src/glsl/nir/nir_lower_vars_to_ssa.c index bb60f4601..ccb8f99df 100644 --- a/mesalib/src/glsl/nir/nir_lower_vars_to_ssa.c +++ b/mesalib/src/glsl/nir/nir_lower_vars_to_ssa.c @@ -567,10 +567,11 @@ add_phi_sources(nir_block *block, nir_block *pred, nir_phi_src *src = ralloc(phi, nir_phi_src); src->pred = pred; + src->src.parent_instr = &phi->instr; src->src.is_ssa = true; src->src.ssa = get_ssa_def_for_block(node, pred, state); - _mesa_set_add(src->src.ssa->uses, instr); + list_addtail(&src->src.use_link, &src->src.ssa->uses); exec_list_push_tail(&phi->srcs, &src->node); } diff --git a/mesalib/src/glsl/nir/nir_opcodes.py b/mesalib/src/glsl/nir/nir_opcodes.py index 264806f5d..56e96d912 100644 --- a/mesalib/src/glsl/nir/nir_opcodes.py +++ b/mesalib/src/glsl/nir/nir_opcodes.py @@ -153,8 +153,6 @@ unop("fsat", tfloat, "(src0 > 1.0f) ? 1.0f : ((src0 <= 0.0f) ? 0.0f : src0)") unop("frcp", tfloat, "1.0f / src0") unop("frsq", tfloat, "1.0f / sqrtf(src0)") unop("fsqrt", tfloat, "sqrtf(src0)") -unop("fexp", tfloat, "expf(src0)") # < e^x -unop("flog", tfloat, "logf(src0)") # log base e unop("fexp2", tfloat, "exp2f(src0)") unop("flog2", tfloat, "log2f(src0)") unop_convert("f2i", tfloat, tint, "src0") # Float-to-integer conversion. diff --git a/mesalib/src/glsl/nir/nir_opt_algebraic.py b/mesalib/src/glsl/nir/nir_opt_algebraic.py index 2a2b9561e..fa039222f 100644 --- a/mesalib/src/glsl/nir/nir_opt_algebraic.py +++ b/mesalib/src/glsl/nir/nir_opt_algebraic.py @@ -83,24 +83,37 @@ optimizations = [ # Comparison simplifications (('inot', ('flt', a, b)), ('fge', a, b)), (('inot', ('fge', a, b)), ('flt', a, b)), + (('inot', ('feq', a, b)), ('fne', a, b)), + (('inot', ('fne', a, b)), ('feq', a, b)), (('inot', ('ilt', a, b)), ('ige', a, b)), (('inot', ('ige', a, b)), ('ilt', a, b)), + (('inot', ('ieq', a, b)), ('ine', a, b)), + (('inot', ('ine', a, b)), ('ieq', a, b)), (('fge', ('fneg', ('fabs', a)), 0.0), ('feq', a, 0.0)), (('bcsel', ('flt', a, b), a, b), ('fmin', a, b)), (('bcsel', ('flt', a, b), b, a), ('fmax', a, b)), (('bcsel', ('inot', 'a@bool'), b, c), ('bcsel', a, c, b)), (('bcsel', a, ('bcsel', a, b, c), d), ('bcsel', a, b, d)), + (('fmin', a, a), a), + (('fmax', a, a), a), + (('imin', a, a), a), + (('imax', a, a), a), + (('umin', a, a), a), + (('umax', a, a), a), (('fmin', ('fmax', a, 0.0), 1.0), ('fsat', a), '!options->lower_fsat'), (('fsat', a), ('fmin', ('fmax', a, 0.0), 1.0), 'options->lower_fsat'), (('fsat', ('fsat', a)), ('fsat', a)), (('fmin', ('fmax', ('fmin', ('fmax', a, 0.0), 1.0), 0.0), 1.0), ('fmin', ('fmax', a, 0.0), 1.0)), (('ior', ('flt', a, b), ('flt', a, c)), ('flt', a, ('fmax', b, c))), + (('ior', ('flt', a, c), ('flt', b, c)), ('flt', ('fmin', a, b), c)), (('ior', ('fge', a, b), ('fge', a, c)), ('fge', a, ('fmin', b, c))), + (('ior', ('fge', a, c), ('fge', b, c)), ('fge', ('fmax', a, b), c)), (('slt', a, b), ('b2f', ('flt', a, b)), 'options->lower_scmp'), (('sge', a, b), ('b2f', ('fge', a, b)), 'options->lower_scmp'), (('seq', a, b), ('b2f', ('feq', a, b)), 'options->lower_scmp'), (('sne', a, b), ('b2f', ('fne', a, b)), 'options->lower_scmp'), # Emulating booleans + (('imul', ('b2i', a), ('b2i', b)), ('b2i', ('iand', a, b))), (('fmul', ('b2f', a), ('b2f', b)), ('b2f', ('iand', a, b))), (('fsat', ('fadd', ('b2f', a), ('b2f', b))), ('b2f', ('ior', a, b))), (('iand', 'a@bool', 1.0), ('b2f', a)), @@ -136,36 +149,23 @@ optimizations = [ (('ushr', a, 0), a), # Exponential/logarithmic identities (('fexp2', ('flog2', a)), a), # 2^lg2(a) = a - (('fexp', ('flog', a)), a), # e^ln(a) = a (('flog2', ('fexp2', a)), a), # lg2(2^a) = a - (('flog', ('fexp', a)), a), # ln(e^a) = a (('fpow', a, b), ('fexp2', ('fmul', ('flog2', a), b)), 'options->lower_fpow'), # a^b = 2^(lg2(a)*b) (('fexp2', ('fmul', ('flog2', a), b)), ('fpow', a, b), '!options->lower_fpow'), # 2^(lg2(a)*b) = a^b - (('fexp', ('fmul', ('flog', a), b)), ('fpow', a, b), '!options->lower_fpow'), # e^(ln(a)*b) = a^b (('fpow', a, 1.0), a), (('fpow', a, 2.0), ('fmul', a, a)), (('fpow', a, 4.0), ('fmul', ('fmul', a, a), ('fmul', a, a))), (('fpow', 2.0, a), ('fexp2', a)), (('fsqrt', ('fexp2', a)), ('fexp2', ('fmul', 0.5, a))), - (('fsqrt', ('fexp', a)), ('fexp', ('fmul', 0.5, a))), (('frcp', ('fexp2', a)), ('fexp2', ('fneg', a))), - (('frcp', ('fexp', a)), ('fexp', ('fneg', a))), (('frsq', ('fexp2', a)), ('fexp2', ('fmul', -0.5, a))), - (('frsq', ('fexp', a)), ('fexp', ('fmul', -0.5, a))), (('flog2', ('fsqrt', a)), ('fmul', 0.5, ('flog2', a))), - (('flog', ('fsqrt', a)), ('fmul', 0.5, ('flog', a))), (('flog2', ('frcp', a)), ('fneg', ('flog2', a))), - (('flog', ('frcp', a)), ('fneg', ('flog', a))), (('flog2', ('frsq', a)), ('fmul', -0.5, ('flog2', a))), - (('flog', ('frsq', a)), ('fmul', -0.5, ('flog', a))), (('flog2', ('fpow', a, b)), ('fmul', b, ('flog2', a))), - (('flog', ('fpow', a, b)), ('fmul', b, ('flog', a))), (('fadd', ('flog2', a), ('flog2', b)), ('flog2', ('fmul', a, b))), - (('fadd', ('flog', a), ('flog', b)), ('flog', ('fmul', a, b))), (('fadd', ('flog2', a), ('fneg', ('flog2', b))), ('flog2', ('fdiv', a, b))), - (('fadd', ('flog', a), ('fneg', ('flog', b))), ('flog', ('fdiv', a, b))), (('fmul', ('fexp2', a), ('fexp2', b)), ('fexp2', ('fadd', a, b))), - (('fmul', ('fexp', a), ('fexp', b)), ('fexp', ('fadd', a, b))), # Division and reciprocal (('fdiv', 1.0, a), ('frcp', a)), (('frcp', ('frcp', a)), a), @@ -187,6 +187,7 @@ optimizations = [ (('fcsel', a, b, b), b), # Conversions + (('i2b', ('b2i', a)), a), (('f2i', ('ftrunc', a)), ('f2i', a)), (('f2u', ('ftrunc', a)), ('f2u', a)), diff --git a/mesalib/src/glsl/nir/nir_opt_copy_propagate.c b/mesalib/src/glsl/nir/nir_opt_copy_propagate.c index ee78e5aa0..71367d001 100644 --- a/mesalib/src/glsl/nir/nir_opt_copy_propagate.c +++ b/mesalib/src/glsl/nir/nir_opt_copy_propagate.c @@ -93,62 +93,6 @@ is_swizzleless_move(nir_alu_instr *instr) } } -typedef struct { - nir_ssa_def *def; - bool found; -} search_def_state; - -static bool -search_def(nir_src *src, void *_state) -{ - search_def_state *state = (search_def_state *) _state; - - if (src->is_ssa && src->ssa == state->def) - state->found = true; - - return true; -} - -static void -rewrite_src_instr(nir_src *src, nir_ssa_def *new_def, nir_instr *parent_instr) -{ - nir_ssa_def *old_def = src->ssa; - - src->ssa = new_def; - - /* - * The instruction could still use the old definition in one of its other - * sources, so only remove the instruction from the uses if there are no - * more uses left. - */ - - search_def_state search_state; - search_state.def = old_def; - search_state.found = false; - nir_foreach_src(parent_instr, search_def, &search_state); - if (!search_state.found) { - struct set_entry *entry = _mesa_set_search(old_def->uses, parent_instr); - assert(entry); - _mesa_set_remove(old_def->uses, entry); - } - - _mesa_set_add(new_def->uses, parent_instr); -} - -static void -rewrite_src_if(nir_if *if_stmt, nir_ssa_def *new_def) -{ - nir_ssa_def *old_def = if_stmt->condition.ssa; - - if_stmt->condition.ssa = new_def; - - struct set_entry *entry = _mesa_set_search(old_def->if_uses, if_stmt); - assert(entry); - _mesa_set_remove(old_def->if_uses, entry); - - _mesa_set_add(new_def->if_uses, if_stmt); -} - static bool copy_prop_src(nir_src *src, nir_instr *parent_instr, nir_if *parent_if) { @@ -178,10 +122,14 @@ copy_prop_src(nir_src *src, nir_instr *parent_instr, nir_if *parent_if) return false; } - if (parent_instr) - rewrite_src_instr(src, alu_instr->src[0].src.ssa, parent_instr); - else - rewrite_src_if(parent_if, alu_instr->src[0].src.ssa); + if (parent_instr) { + nir_instr_rewrite_src(parent_instr, src, + nir_src_for_ssa(alu_instr->src[0].src.ssa)); + } else { + assert(src == &parent_if->condition); + nir_if_rewrite_condition(parent_if, + nir_src_for_ssa(alu_instr->src[0].src.ssa)); + } return true; } @@ -234,7 +182,8 @@ copy_prop_alu_src(nir_alu_instr *parent_alu_instr, unsigned index) for (unsigned i = 0; i < 4; i++) src->swizzle[i] = new_swizzle[i]; - rewrite_src_instr(&src->src, def, &parent_alu_instr->instr); + nir_instr_rewrite_src(&parent_alu_instr->instr, &src->src, + nir_src_for_ssa(def)); return true; } diff --git a/mesalib/src/glsl/nir/nir_opt_gcm.c b/mesalib/src/glsl/nir/nir_opt_gcm.c index b4f5fd3d5..44068bf37 100644 --- a/mesalib/src/glsl/nir/nir_opt_gcm.c +++ b/mesalib/src/glsl/nir/nir_opt_gcm.c @@ -279,9 +279,8 @@ gcm_schedule_late_def(nir_ssa_def *def, void *void_state) nir_block *lca = NULL; - struct set_entry *entry; - set_foreach(def->uses, entry) { - nir_instr *use_instr = (nir_instr *)entry->key; + nir_foreach_use(def, use_src) { + nir_instr *use_instr = use_src->parent_instr; gcm_schedule_late_instr(use_instr, state); @@ -304,8 +303,8 @@ gcm_schedule_late_def(nir_ssa_def *def, void *void_state) } } - set_foreach(def->if_uses, entry) { - nir_if *if_stmt = (nir_if *)entry->key; + nir_foreach_if_use(def, use_src) { + nir_if *if_stmt = use_src->parent_if; /* For if statements, we consider the block to be the one immediately * preceding the if CF node. @@ -377,9 +376,8 @@ gcm_place_instr(nir_instr *instr, struct gcm_state *state); static bool gcm_place_instr_def(nir_ssa_def *def, void *state) { - struct set_entry *entry; - set_foreach(def->uses, entry) - gcm_place_instr((nir_instr *)entry->key, state); + nir_foreach_use(def, use_src) + gcm_place_instr(use_src->parent_instr, state); return false; } diff --git a/mesalib/src/glsl/nir/nir_opt_global_to_local.c b/mesalib/src/glsl/nir/nir_opt_global_to_local.c index 00db37ba7..bccb45b62 100644 --- a/mesalib/src/glsl/nir/nir_opt_global_to_local.c +++ b/mesalib/src/glsl/nir/nir_opt_global_to_local.c @@ -34,9 +34,8 @@ global_to_local(nir_register *reg) assert(reg->is_global); - struct set_entry *entry; - set_foreach(reg->defs, entry) { - nir_instr *instr = (nir_instr *) entry->key; + nir_foreach_def(reg, def_dest) { + nir_instr *instr = def_dest->reg.parent_instr; nir_function_impl *instr_impl = nir_cf_node_get_function(&instr->block->cf_node); if (impl != NULL) { @@ -47,8 +46,8 @@ global_to_local(nir_register *reg) } } - set_foreach(reg->uses, entry) { - nir_instr *instr = (nir_instr *) entry->key; + nir_foreach_use(reg, use_src) { + nir_instr *instr = use_src->parent_instr; nir_function_impl *instr_impl = nir_cf_node_get_function(&instr->block->cf_node); if (impl != NULL) { @@ -59,8 +58,8 @@ global_to_local(nir_register *reg) } } - set_foreach(reg->if_uses, entry) { - nir_if *if_stmt = (nir_if *) entry->key; + nir_foreach_if_use(reg, use_src) { + nir_if *if_stmt = use_src->parent_if; nir_function_impl *if_impl = nir_cf_node_get_function(&if_stmt->cf_node); if (impl != NULL) { if (impl != if_impl) diff --git a/mesalib/src/glsl/nir/nir_opt_peephole_ffma.c b/mesalib/src/glsl/nir/nir_opt_peephole_ffma.c index 9d5646fe6..b430eac8e 100644 --- a/mesalib/src/glsl/nir/nir_opt_peephole_ffma.c +++ b/mesalib/src/glsl/nir/nir_opt_peephole_ffma.c @@ -41,12 +41,11 @@ struct peephole_ffma_state { static inline bool are_all_uses_fadd(nir_ssa_def *def) { - if (def->if_uses->entries > 0) + if (!list_empty(&def->if_uses)) return false; - struct set_entry *use_iter; - set_foreach(def->uses, use_iter) { - nir_instr *use_instr = (nir_instr *)use_iter->key; + nir_foreach_use(def, use_src) { + nir_instr *use_instr = use_src->parent_instr; if (use_instr->type != nir_instr_type_alu) return false; @@ -220,7 +219,7 @@ nir_opt_peephole_ffma_block(nir_block *block, void *void_state) state->mem_ctx); nir_instr_insert_before(&add->instr, &ffma->instr); - assert(add->dest.dest.ssa.uses->entries == 0); + assert(list_empty(&add->dest.dest.ssa.uses)); nir_instr_remove(&add->instr); state->progress = true; diff --git a/mesalib/src/glsl/nir/nir_opt_peephole_select.c b/mesalib/src/glsl/nir/nir_opt_peephole_select.c index f400cfd66..82c65bb44 100644 --- a/mesalib/src/glsl/nir/nir_opt_peephole_select.c +++ b/mesalib/src/glsl/nir/nir_opt_peephole_select.c @@ -98,15 +98,13 @@ block_check_for_allowed_instrs(nir_block *block) return false; /* It cannot have any if-uses */ - if (mov->dest.dest.ssa.if_uses->entries != 0) + if (!list_empty(&mov->dest.dest.ssa.if_uses)) return false; /* The only uses of this definition must be phi's in the successor */ - struct set_entry *entry; - set_foreach(mov->dest.dest.ssa.uses, entry) { - const nir_instr *dest_instr = entry->key; - if (dest_instr->type != nir_instr_type_phi || - dest_instr->block != block->successors[0]) + nir_foreach_use(&mov->dest.dest.ssa, use) { + if (use->parent_instr->type != nir_instr_type_phi || + use->parent_instr->block != block->successors[0]) return false; } break; diff --git a/mesalib/src/glsl/nir/nir_search.c b/mesalib/src/glsl/nir/nir_search.c index 5ba016085..0c4e48ce9 100644 --- a/mesalib/src/glsl/nir/nir_search.c +++ b/mesalib/src/glsl/nir/nir_search.c @@ -73,6 +73,14 @@ match_value(const nir_search_value *value, nir_alu_instr *instr, unsigned src, { uint8_t new_swizzle[4]; + /* If the source is an explicitly sized source, then we need to reset + * both the number of components and the swizzle. + */ + if (nir_op_infos[instr->op].input_sizes[src] != 0) { + num_components = nir_op_infos[instr->op].input_sizes[src]; + swizzle = identity_swizzle; + } + for (int i = 0; i < num_components; ++i) new_swizzle[i] = instr->src[src].swizzle[swizzle[i]]; @@ -90,6 +98,7 @@ match_value(const nir_search_value *value, nir_alu_instr *instr, unsigned src, case nir_search_value_variable: { nir_search_variable *var = nir_search_value_as_variable(value); + assert(var->variable < NIR_SEARCH_MAX_VARIABLES); if (state->variables_seen & (1 << var->variable)) { if (!nir_srcs_equal(state->variables[var->variable].src, @@ -198,16 +207,13 @@ match_expression(const nir_search_expression *expr, nir_alu_instr *instr, } } + /* Stash off the current variables_seen bitmask. This way we can + * restore it prior to matching in the commutative case below. + */ + unsigned variables_seen_stash = state->variables_seen; + bool matched = true; for (unsigned i = 0; i < nir_op_infos[instr->op].num_inputs; i++) { - /* If the source is an explicitly sized source, then we need to reset - * both the number of components and the swizzle. - */ - if (nir_op_infos[instr->op].input_sizes[i] != 0) { - num_components = nir_op_infos[instr->op].input_sizes[i]; - swizzle = identity_swizzle; - } - if (!match_value(expr->srcs[i], instr, i, num_components, swizzle, state)) { matched = false; @@ -220,6 +226,13 @@ match_expression(const nir_search_expression *expr, nir_alu_instr *instr, if (nir_op_infos[instr->op].algebraic_properties & NIR_OP_IS_COMMUTATIVE) { assert(nir_op_infos[instr->op].num_inputs == 2); + + /* Restore the variables_seen bitmask. If we don't do this, then we + * could end up with an erroneous failure due to variables found in the + * first match attempt above not matching those in the second. + */ + state->variables_seen = variables_seen_stash; + if (!match_value(expr->srcs[0], instr, 1, num_components, swizzle, state)) return false; @@ -276,7 +289,7 @@ construct_value(const nir_search_value *value, nir_alu_type type, const nir_search_variable *var = nir_search_value_as_variable(value); assert(state->variables_seen & (1 << var->variable)); - nir_alu_src val; + nir_alu_src val = { NIR_SRC_INIT }; nir_alu_src_copy(&val, &state->variables[var->variable], mem_ctx); assert(!var->is_constant); diff --git a/mesalib/src/glsl/nir/nir_to_ssa.c b/mesalib/src/glsl/nir/nir_to_ssa.c index 53ff54766..a3c35fa04 100644 --- a/mesalib/src/glsl/nir/nir_to_ssa.c +++ b/mesalib/src/glsl/nir/nir_to_ssa.c @@ -89,9 +89,8 @@ insert_phi_nodes(nir_function_impl *impl) w_start = w_end = 0; iter_count++; - struct set_entry *entry; - set_foreach(reg->defs, entry) { - nir_instr *def = (nir_instr *) entry->key; + nir_foreach_def(reg, dest) { + nir_instr *def = dest->reg.parent_instr; if (work[def->block->index] < iter_count) W[w_end++] = def->block; work[def->block->index] = iter_count; @@ -99,6 +98,7 @@ insert_phi_nodes(nir_function_impl *impl) while (w_start != w_end) { nir_block *cur = W[w_start++]; + struct set_entry *entry; set_foreach(cur->dom_frontier, entry) { nir_block *next = (nir_block *) entry->key; @@ -190,13 +190,12 @@ rewrite_use(nir_src *src, void *_state) if (state->states[index].stack == NULL) return true; - src->is_ssa = true; - src->ssa = get_ssa_src(src->reg.reg, state); - + nir_ssa_def *def = get_ssa_src(src->reg.reg, state); if (state->parent_instr) - _mesa_set_add(src->ssa->uses, state->parent_instr); + nir_instr_rewrite_src(state->parent_instr, src, nir_src_for_ssa(def)); else - _mesa_set_add(src->ssa->if_uses, state->parent_if); + nir_if_rewrite_condition(state->parent_if, nir_src_for_ssa(def)); + return true; } @@ -219,6 +218,7 @@ rewrite_def_forwards(nir_dest *dest, void *_state) name = ralloc_asprintf(state->mem_ctx, "%s_%u", dest->reg.reg->name, state->states[index].num_defs); + list_del(&dest->reg.def_link); nir_ssa_dest_init(state->parent_instr, dest, reg->num_components, name); /* push our SSA destination on the stack */ @@ -270,6 +270,7 @@ rewrite_alu_instr_forward(nir_alu_instr *instr, rewrite_state *state) reg->name, state->states[index].num_defs); instr->dest.write_mask = (1 << num_components) - 1; + list_del(&instr->dest.dest.reg.def_link); nir_ssa_dest_init(&instr->instr, &instr->dest.dest, num_components, name); if (nir_op_infos[instr->op].output_size == 0) { @@ -484,7 +485,7 @@ init_rewrite_state(nir_function_impl *impl, rewrite_state *state) * called after phi nodes are inserted so we can count phi node * definitions too. */ - unsigned stack_size = reg->defs->entries; + unsigned stack_size = list_length(®->defs); state->states[reg->index].stack = ralloc_array(state->states, nir_ssa_def *, diff --git a/mesalib/src/glsl/nir/nir_validate.c b/mesalib/src/glsl/nir/nir_validate.c index a7aa79837..da92ed904 100644 --- a/mesalib/src/glsl/nir/nir_validate.c +++ b/mesalib/src/glsl/nir/nir_validate.c @@ -97,50 +97,47 @@ typedef struct { static void validate_src(nir_src *src, validate_state *state); static void -validate_reg_src(nir_reg_src *src, validate_state *state) +validate_reg_src(nir_src *src, validate_state *state) { - assert(src->reg != NULL); + assert(src->reg.reg != NULL); struct hash_entry *entry; - entry = _mesa_hash_table_search(state->regs, src->reg); + entry = _mesa_hash_table_search(state->regs, src->reg.reg); assert(entry); reg_validate_state *reg_state = (reg_validate_state *) entry->data; if (state->instr) { - _mesa_set_add(reg_state->uses, state->instr); - - assert(_mesa_set_search(src->reg->uses, state->instr)); + _mesa_set_add(reg_state->uses, src); } else { assert(state->if_stmt); - _mesa_set_add(reg_state->if_uses, state->if_stmt); - - assert(_mesa_set_search(src->reg->if_uses, state->if_stmt)); + _mesa_set_add(reg_state->if_uses, src); } - if (!src->reg->is_global) { + if (!src->reg.reg->is_global) { assert(reg_state->where_defined == state->impl && "using a register declared in a different function"); } - assert((src->reg->num_array_elems == 0 || - src->base_offset < src->reg->num_array_elems) && + assert((src->reg.reg->num_array_elems == 0 || + src->reg.base_offset < src->reg.reg->num_array_elems) && "definitely out-of-bounds array access"); - if (src->indirect) { - assert(src->reg->num_array_elems != 0); - assert((src->indirect->is_ssa || src->indirect->reg.indirect == NULL) && + if (src->reg.indirect) { + assert(src->reg.reg->num_array_elems != 0); + assert((src->reg.indirect->is_ssa || + src->reg.indirect->reg.indirect == NULL) && "only one level of indirection allowed"); - validate_src(src->indirect, state); + validate_src(src->reg.indirect, state); } } static void -validate_ssa_src(nir_ssa_def *def, validate_state *state) +validate_ssa_src(nir_src *src, validate_state *state) { - assert(def != NULL); + assert(src->ssa != NULL); - struct hash_entry *entry = _mesa_hash_table_search(state->ssa_defs, def); + struct hash_entry *entry = _mesa_hash_table_search(state->ssa_defs, src->ssa); assert(entry); @@ -150,14 +147,10 @@ validate_ssa_src(nir_ssa_def *def, validate_state *state) "using an SSA value defined in a different function"); if (state->instr) { - _mesa_set_add(def_state->uses, state->instr); - - assert(_mesa_set_search(def->uses, state->instr)); + _mesa_set_add(def_state->uses, src); } else { assert(state->if_stmt); - _mesa_set_add(def_state->if_uses, state->if_stmt); - - assert(_mesa_set_search(def->if_uses, state->if_stmt)); + _mesa_set_add(def_state->if_uses, src); } /* TODO validate that the use is dominated by the definition */ @@ -166,10 +159,15 @@ validate_ssa_src(nir_ssa_def *def, validate_state *state) static void validate_src(nir_src *src, validate_state *state) { + if (state->instr) + assert(src->parent_instr == state->instr); + else + assert(src->parent_if == state->if_stmt); + if (src->is_ssa) - validate_ssa_src(src->ssa, state); + validate_ssa_src(src, state); else - validate_reg_src(&src->reg, state); + validate_reg_src(src, state); } static void @@ -201,8 +199,7 @@ validate_reg_dest(nir_reg_dest *dest, validate_state *state) { assert(dest->reg != NULL); - struct set_entry *entry = _mesa_set_search(dest->reg->defs, state->instr); - assert(entry && "definition not in nir_register.defs"); + assert(dest->parent_instr == state->instr); struct hash_entry *entry2; entry2 = _mesa_hash_table_search(state->regs, dest->reg); @@ -210,7 +207,7 @@ validate_reg_dest(nir_reg_dest *dest, validate_state *state) assert(entry2); reg_validate_state *reg_state = (reg_validate_state *) entry2->data; - _mesa_set_add(reg_state->defs, state->instr); + _mesa_set_add(reg_state->defs, dest); if (!dest->reg->is_global) { assert(reg_state->where_defined == state->impl && @@ -236,8 +233,13 @@ validate_ssa_def(nir_ssa_def *def, validate_state *state) assert(!BITSET_TEST(state->ssa_defs_found, def->index)); BITSET_SET(state->ssa_defs_found, def->index); + assert(def->parent_instr == state->instr); + assert(def->num_components <= 4); + list_validate(&def->uses); + list_validate(&def->if_uses); + ssa_def_validate_state *def_state = ralloc(state->ssa_defs, ssa_def_validate_state); def_state->where_defined = state->impl; @@ -699,6 +701,10 @@ prevalidate_reg_decl(nir_register *reg, bool is_global, validate_state *state) assert(!BITSET_TEST(state->regs_found, reg->index)); BITSET_SET(state->regs_found, reg->index); + list_validate(®->uses); + list_validate(®->defs); + list_validate(®->if_uses); + reg_validate_state *reg_state = ralloc(state->regs, reg_validate_state); reg_state->uses = _mesa_set_create(reg_state, _mesa_hash_pointer, _mesa_key_pointer_equal); @@ -719,47 +725,47 @@ postvalidate_reg_decl(nir_register *reg, validate_state *state) reg_validate_state *reg_state = (reg_validate_state *) entry->data; - if (reg_state->uses->entries != reg->uses->entries) { + nir_foreach_use(reg, src) { + struct set_entry *entry = _mesa_set_search(reg_state->uses, src); + assert(entry); + _mesa_set_remove(reg_state->uses, entry); + } + + if (reg_state->uses->entries != 0) { printf("extra entries in register uses:\n"); struct set_entry *entry; - set_foreach(reg->uses, entry) { - struct set_entry *entry2 = - _mesa_set_search(reg_state->uses, entry->key); - - if (entry2 == NULL) { - printf("%p\n", entry->key); - } - } + set_foreach(reg_state->uses, entry) + printf("%p\n", entry->key); abort(); } - if (reg_state->if_uses->entries != reg->if_uses->entries) { + nir_foreach_if_use(reg, src) { + struct set_entry *entry = _mesa_set_search(reg_state->if_uses, src); + assert(entry); + _mesa_set_remove(reg_state->if_uses, entry); + } + + if (reg_state->if_uses->entries != 0) { printf("extra entries in register if_uses:\n"); struct set_entry *entry; - set_foreach(reg->if_uses, entry) { - struct set_entry *entry2 = - _mesa_set_search(reg_state->if_uses, entry->key); - - if (entry2 == NULL) { - printf("%p\n", entry->key); - } - } + set_foreach(reg_state->if_uses, entry) + printf("%p\n", entry->key); abort(); } - if (reg_state->defs->entries != reg->defs->entries) { + nir_foreach_def(reg, src) { + struct set_entry *entry = _mesa_set_search(reg_state->defs, src); + assert(entry); + _mesa_set_remove(reg_state->defs, entry); + } + + if (reg_state->defs->entries != 0) { printf("extra entries in register defs:\n"); struct set_entry *entry; - set_foreach(reg->defs, entry) { - struct set_entry *entry2 = - _mesa_set_search(reg_state->defs, entry->key); - - if (entry2 == NULL) { - printf("%p\n", entry->key); - } - } + set_foreach(reg_state->defs, entry) + printf("%p\n", entry->key); abort(); } @@ -788,32 +794,32 @@ postvalidate_ssa_def(nir_ssa_def *def, void *void_state) struct hash_entry *entry = _mesa_hash_table_search(state->ssa_defs, def); ssa_def_validate_state *def_state = (ssa_def_validate_state *)entry->data; - if (def_state->uses->entries != def->uses->entries) { - printf("extra entries in SSA def uses:\n"); - struct set_entry *entry; - set_foreach(def->uses, entry) { - struct set_entry *entry2 = - _mesa_set_search(def_state->uses, entry->key); + nir_foreach_use(def, src) { + struct set_entry *entry = _mesa_set_search(def_state->uses, src); + assert(entry); + _mesa_set_remove(def_state->uses, entry); + } - if (entry2 == NULL) { - printf("%p\n", entry->key); - } - } + if (def_state->uses->entries != 0) { + printf("extra entries in register uses:\n"); + struct set_entry *entry; + set_foreach(def_state->uses, entry) + printf("%p\n", entry->key); abort(); } - if (def_state->if_uses->entries != def->if_uses->entries) { - printf("extra entries in SSA def uses:\n"); - struct set_entry *entry; - set_foreach(def->if_uses, entry) { - struct set_entry *entry2 = - _mesa_set_search(def_state->if_uses, entry->key); + nir_foreach_if_use(def, src) { + struct set_entry *entry = _mesa_set_search(def_state->if_uses, src); + assert(entry); + _mesa_set_remove(def_state->if_uses, entry); + } - if (entry2 == NULL) { - printf("%p\n", entry->key); - } - } + if (def_state->if_uses->entries != 0) { + printf("extra entries in register uses:\n"); + struct set_entry *entry; + set_foreach(def_state->if_uses, entry) + printf("%p\n", entry->key); abort(); } diff --git a/mesalib/src/glsl/opt_dead_builtin_varyings.cpp b/mesalib/src/glsl/opt_dead_builtin_varyings.cpp index 92f20c71d..31719d20c 100644 --- a/mesalib/src/glsl/opt_dead_builtin_varyings.cpp +++ b/mesalib/src/glsl/opt_dead_builtin_varyings.cpp @@ -99,6 +99,16 @@ public: } else { this->fragdata_usage |= 1 << index->get_uint_component(0); + /* Don't lower fragdata array if the output variable + * is not a float variable (or float vector) because it will + * generate wrong register assignments because of different + * data types. + */ + if (var->type->gl_type != GL_FLOAT && + var->type->gl_type != GL_FLOAT_VEC2 && + var->type->gl_type != GL_FLOAT_VEC3 && + var->type->gl_type != GL_FLOAT_VEC4) + this->lower_fragdata_array = false; } /* Don't visit the leaves of ir_dereference_array. */ diff --git a/mesalib/src/hgl/GLDispatcher.cpp b/mesalib/src/hgl/GLDispatcher.cpp index 46b91d57c..a1e905361 100644 --- a/mesalib/src/hgl/GLDispatcher.cpp +++ b/mesalib/src/hgl/GLDispatcher.cpp @@ -1,6 +1,6 @@ /* * Copyright 1998-1999 Precision Insight, Inc., Cedar Park, Texas. - * Copyright 2000-2012 Haiku, Inc. All Rights Reserved. + * Copyright 2000-2015 Haiku, Inc. All Rights Reserved. * Distributed under the terms of the MIT License. * * Authors: @@ -10,10 +10,11 @@ */ -extern "C" { #include "glapi/glapi.h" #include "glapi/glapi_priv.h" + +extern "C" { /* * NOTE: this file portion implements C-based dispatch of the OpenGL entrypoints * (glAccum, glBegin, etc). diff --git a/mesalib/src/hgl/GLDispatcher.h b/mesalib/src/hgl/GLDispatcher.h index 44bca8ce5..7ee095d91 100644 --- a/mesalib/src/hgl/GLDispatcher.h +++ b/mesalib/src/hgl/GLDispatcher.h @@ -1,6 +1,6 @@ /* * Copyright 1998-1999 Precision Insight, Inc., Cedar Park, Texas. - * Copyright 2000-2012 Haiku, Inc. All Rights Reserved. + * Copyright 2000-2015 Haiku, Inc. All Rights Reserved. * Distributed under the terms of the MIT License. * * Authors: @@ -17,9 +17,7 @@ #include "glheader.h" -extern "C" { #include "glapi/glapi.h" -} class BGLDispatcher diff --git a/mesalib/src/hgl/SConscript b/mesalib/src/hgl/SConscript index 70db1494d..71881f504 100644 --- a/mesalib/src/hgl/SConscript +++ b/mesalib/src/hgl/SConscript @@ -6,6 +6,7 @@ Import('*') env = env.Clone() env.Append(CPPPATH = [ + '#/src', '#/src/mapi', '#/src/mesa', '#/src/mesa/main', diff --git a/mesalib/src/loader/loader.h b/mesalib/src/loader/loader.h index 810e7da7f..60c58f2f8 100644 --- a/mesalib/src/loader/loader.h +++ b/mesalib/src/loader/loader.h @@ -27,6 +27,10 @@ #ifndef LOADER_H #define LOADER_H +#ifdef __cplusplus +extern "C" { +#endif + /* Helpers to figure out driver and device name, eg. from pci-id, etc. */ #define _LOADER_DRI (1 << 0) @@ -61,4 +65,9 @@ loader_get_user_preferred_fd(int default_fd, int *different_device); void loader_set_logger(void (*logger)(int level, const char *fmt, ...)); + +#ifdef __cplusplus +} +#endif + #endif /* LOADER_H */ diff --git a/mesalib/src/mapi/glapi/gen/ARB_direct_state_access.xml b/mesalib/src/mapi/glapi/gen/ARB_direct_state_access.xml index 8a092d697..bb9baf5a3 100644 --- a/mesalib/src/mapi/glapi/gen/ARB_direct_state_access.xml +++ b/mesalib/src/mapi/glapi/gen/ARB_direct_state_access.xml @@ -152,6 +152,135 @@ <param name="data" type="GLvoid *" /> </function> + <!-- Framebuffer object functions --> + + <function name="CreateFramebuffers" offset="assign"> + <param name="n" type="GLsizei" /> + <param name="framebuffers" type="GLuint *" /> + </function> + + <function name="NamedFramebufferRenderbuffer" offset="assign"> + <param name="framebuffer" type="GLuint" /> + <param name="attachment" type="GLenum" /> + <param name="renderbuffertarget" type="GLenum" /> + <param name="renderbuffer" type="GLuint" /> + </function> + + <function name="NamedFramebufferParameteri" offset="assign"> + <param name="framebuffer" type="GLuint" /> + <param name="pname" type="GLenum" /> + <param name="param" type="GLint" /> + </function> + + <function name="NamedFramebufferTexture" offset="assign"> + <param name="framebuffer" type="GLuint" /> + <param name="attachment" type="GLenum" /> + <param name="texture" type="GLuint" /> + <param name="level" type="GLint" /> + </function> + + <function name="NamedFramebufferTextureLayer" offset="assign"> + <param name="framebuffer" type="GLuint" /> + <param name="attachment" type="GLenum" /> + <param name="texture" type="GLuint" /> + <param name="level" type="GLint" /> + <param name="layer" type="GLint" /> + </function> + + <function name="NamedFramebufferDrawBuffer" offset="assign"> + <param name="framebuffer" type="GLuint" /> + <param name="buf" type="GLenum" /> + </function> + + <function name="NamedFramebufferDrawBuffers" offset="assign"> + <param name="framebuffer" type="GLuint" /> + <param name="n" type="GLsizei" /> + <param name="bufs" type="const GLenum *" /> + </function> + + <function name="NamedFramebufferReadBuffer" offset="assign"> + <param name="framebuffer" type="GLuint" /> + <param name="buf" type="GLenum" /> + </function> + + <function name="InvalidateNamedFramebufferData" offset="assign"> + <param name="framebuffer" type="GLuint" /> + <param name="numAttachments" type="GLsizei" /> + <param name="attachments" type="const GLenum *" /> + </function> + + <function name="InvalidateNamedFramebufferSubData" offset="assign"> + <param name="framebuffer" type="GLuint" /> + <param name="numAttachments" type="GLsizei" /> + <param name="attachments" type="const GLenum *" /> + <param name="x" type="GLint" /> + <param name="y" type="GLint" /> + <param name="width" type="GLsizei" /> + <param name="height" type="GLsizei" /> + </function> + + <function name="ClearNamedFramebufferiv" offset="assign"> + <param name="framebuffer" type="GLuint" /> + <param name="buffer" type="GLenum" /> + <param name="drawbuffer" type="GLint" /> + <param name="value" type="const GLint *" /> + </function> + + <function name="ClearNamedFramebufferuiv" offset="assign"> + <param name="framebuffer" type="GLuint" /> + <param name="buffer" type="GLenum" /> + <param name="drawbuffer" type="GLint" /> + <param name="value" type="const GLuint *" /> + </function> + + <function name="ClearNamedFramebufferfv" offset="assign"> + <param name="framebuffer" type="GLuint" /> + <param name="buffer" type="GLenum" /> + <param name="drawbuffer" type="GLint" /> + <param name="value" type="const GLfloat *" /> + </function> + + <function name="ClearNamedFramebufferfi" offset="assign"> + <param name="framebuffer" type="GLuint" /> + <param name="buffer" type="GLenum" /> + <param name="depth" type="GLfloat" /> + <param name="stencil" type="GLint" /> + </function> + + <function name="BlitNamedFramebuffer" offset="assign"> + <param name="readFramebuffer" type="GLuint" /> + <param name="drawFramebuffer" type="GLuint" /> + <param name="srcX0" type="GLint" /> + <param name="srcY0" type="GLint" /> + <param name="srcX1" type="GLint" /> + <param name="srcY1" type="GLint" /> + <param name="dstX0" type="GLint" /> + <param name="dstY0" type="GLint" /> + <param name="dstX1" type="GLint" /> + <param name="dstY1" type="GLint" /> + <param name="mask" type="GLbitfield" /> + <param name="filter" type="GLenum" /> + </function> + + <function name="CheckNamedFramebufferStatus" offset="assign"> + <return type="GLenum" /> + <param name="framebuffer" type="GLuint" /> + <param name="target" type="GLenum" /> + </function> + + <function name="GetNamedFramebufferParameteriv" offset="assign"> + <param name="framebuffer" type="GLuint" /> + <param name="pname" type="GLenum" /> + <param name="param" type="GLint *" /> + </function> + + <function name="GetNamedFramebufferAttachmentParameteriv" offset="assign"> + <param name="framebuffer" type="GLuint" /> + <param name="attachment" type="GLenum" /> + <param name="pname" type="GLenum" /> + <param name="params" type="GLint *" /> + </function> + <!-- Renderbuffer object functions --> <function name="CreateRenderbuffers" offset="assign"> @@ -448,6 +577,102 @@ <param name="params" type="GLint *" /> </function> + <!-- Vertex Array object functions --> + + <function name="CreateVertexArrays" offset="assign"> + <param name="n" type="GLsizei" /> + <param name="arrays" type="GLuint *" /> + </function> + + <function name="DisableVertexArrayAttrib" offset="assign"> + <param name="vaobj" type="GLuint" /> + <param name="index" type="GLuint" /> + </function> + + <function name="EnableVertexArrayAttrib" offset="assign"> + <param name="vaobj" type="GLuint" /> + <param name="index" type="GLuint" /> + </function> + + <function name="VertexArrayElementBuffer" offset="assign"> + <param name="vaobj" type="GLuint" /> + <param name="buffer" type="GLuint" /> + </function> + + <function name="VertexArrayVertexBuffer" offset="assign"> + <param name="vaobj" type="GLuint" /> + <param name="bindingindex" type="GLuint" /> + <param name="buffer" type="GLuint" /> + <param name="offset" type="GLintptr" /> + <param name="stride" type="GLsizei" /> + </function> + + <function name="VertexArrayVertexBuffers" offset="assign"> + <param name="vaobj" type="GLuint" /> + <param name="first" type="GLuint" /> + <param name="count" type="GLsizei" /> + <param name="buffers" type="const GLuint *" /> + <param name="offsets" type="const GLintptr *" /> + <param name="strides" type="const GLsizei *" /> + </function> + + <function name="VertexArrayAttribFormat" offset="assign"> + <param name="vaobj" type="GLuint" /> + <param name="attribindex" type="GLuint" /> + <param name="size" type="GLint" /> + <param name="type" type="GLenum" /> + <param name="normalized" type="GLboolean" /> + <param name="relativeoffset" type="GLuint" /> + </function> + + <function name="VertexArrayAttribIFormat" offset="assign"> + <param name="vaobj" type="GLuint" /> + <param name="attribindex" type="GLuint" /> + <param name="size" type="GLint" /> + <param name="type" type="GLenum" /> + <param name="relativeoffset" type="GLuint" /> + </function> + + <function name="VertexArrayAttribLFormat" offset="assign"> + <param name="vaobj" type="GLuint" /> + <param name="attribindex" type="GLuint" /> + <param name="size" type="GLint" /> + <param name="type" type="GLenum" /> + <param name="relativeoffset" type="GLuint" /> + </function> + + <function name="VertexArrayAttribBinding" offset="assign"> + <param name="vaobj" type="GLuint" /> + <param name="attribindex" type="GLuint" /> + <param name="bindingindex" type="GLuint" /> + </function> + + <function name="VertexArrayBindingDivisor" offset="assign"> + <param name="vaobj" type="GLuint" /> + <param name="bindingindex" type="GLuint" /> + <param name="divisor" type="GLuint" /> + </function> + + <function name="GetVertexArrayiv" offset="assign"> + <param name="vaobj" type="GLuint" /> + <param name="pname" type="GLenum" /> + <param name="param" type="GLint *" /> + </function> + + <function name="GetVertexArrayIndexediv" offset="assign"> + <param name="vaobj" type="GLuint" /> + <param name="index" type="GLuint" /> + <param name="pname" type="GLenum" /> + <param name="param" type="GLint *" /> + </function> + + <function name="GetVertexArrayIndexed64iv" offset="assign"> + <param name="vaobj" type="GLuint" /> + <param name="index" type="GLuint" /> + <param name="pname" type="GLenum" /> + <param name="param" type="GLint64 *" /> + </function> + <!-- Sampler object functions --> <function name="CreateSamplers" offset="assign"> diff --git a/mesalib/src/mapi/glapi/gen/ARB_framebuffer_object.xml b/mesalib/src/mapi/glapi/gen/ARB_framebuffer_object.xml index 7c547c167..999a8ef13 100644 --- a/mesalib/src/mapi/glapi/gen/ARB_framebuffer_object.xml +++ b/mesalib/src/mapi/glapi/gen/ARB_framebuffer_object.xml @@ -247,7 +247,7 @@ <param name="textarget" type="GLenum"/> <param name="texture" type="GLuint"/> <param name="level" type="GLint"/> - <param name="zoffset" type="GLint"/> + <param name="layer" type="GLint"/> <glx rop="4323"/> </function> diff --git a/mesalib/src/mapi/glapi/gen/ARB_vertex_attrib_64bit.xml b/mesalib/src/mapi/glapi/gen/ARB_vertex_attrib_64bit.xml new file mode 100644 index 000000000..fc49f84b5 --- /dev/null +++ b/mesalib/src/mapi/glapi/gen/ARB_vertex_attrib_64bit.xml @@ -0,0 +1,70 @@ +<?xml version="1.0"?> +<!DOCTYPE OpenGLAPI SYSTEM "gl_API.dtd"> + +<OpenGLAPI> + +<category name="GL_ARB_vertex_attrib_64bit" number="99"> + + <function name="VertexAttribL1d" offset="assign"> + <param name="index" type="GLuint"/> + <param name="x" type="GLdouble"/> + </function> + + <function name="VertexAttribL2d" offset="assign"> + <param name="index" type="GLuint"/> + <param name="x" type="GLdouble"/> + <param name="y" type="GLdouble"/> + </function> + + <function name="VertexAttribL3d" offset="assign"> + <param name="index" type="GLuint"/> + <param name="x" type="GLdouble"/> + <param name="y" type="GLdouble"/> + <param name="z" type="GLdouble"/> + </function> + + <function name="VertexAttribL4d" offset="assign"> + <param name="index" type="GLuint"/> + <param name="x" type="GLdouble"/> + <param name="y" type="GLdouble"/> + <param name="z" type="GLdouble"/> + <param name="w" type="GLdouble"/> + </function> + + <function name="VertexAttribL1dv" offset="assign"> + <param name="index" type="GLuint"/> + <param name="v" type="const GLdouble *"/> + </function> + + <function name="VertexAttribL2dv" offset="assign"> + <param name="index" type="GLuint"/> + <param name="v" type="const GLdouble *"/> + </function> + + <function name="VertexAttribL3dv" offset="assign"> + <param name="index" type="GLuint"/> + <param name="v" type="const GLdouble *"/> + </function> + + <function name="VertexAttribL4dv" offset="assign"> + <param name="index" type="GLuint"/> + <param name="v" type="const GLdouble *"/> + </function> + + <function name="VertexAttribLPointer" offset="assign"> + <param name="index" type="GLuint"/> + <param name="size" type="GLint"/> + <param name="type" type="GLenum"/> + <param name="stride" type="GLsizei"/> + <param name="pointer" type="const GLvoid *"/> + </function> + + <function name="GetVertexAttribLdv" offset="assign"> + <param name="index" type="GLuint"/> + <param name="pname" type="GLenum"/> + <param name="params" type="GLdouble *"/> + </function> +</category> + +</OpenGLAPI> + diff --git a/mesalib/src/mapi/glapi/gen/Makefile.am b/mesalib/src/mapi/glapi/gen/Makefile.am index 1c4b86aab..c8d417468 100644 --- a/mesalib/src/mapi/glapi/gen/Makefile.am +++ b/mesalib/src/mapi/glapi/gen/Makefile.am @@ -163,6 +163,7 @@ API_XML = \ ARB_texture_view.xml \ ARB_uniform_buffer_object.xml \ ARB_vertex_array_object.xml \ + ARB_vertex_attrib_64bit.xml \ ARB_vertex_attrib_binding.xml \ ARB_viewport_array.xml \ AMD_draw_buffers_blend.xml \ diff --git a/mesalib/src/mapi/glapi/gen/gl_API.xml b/mesalib/src/mapi/glapi/gen/gl_API.xml index a8a6db683..d1565989c 100644 --- a/mesalib/src/mapi/glapi/gen/gl_API.xml +++ b/mesalib/src/mapi/glapi/gen/gl_API.xml @@ -8253,7 +8253,9 @@ <!-- No new functions, types, enums. --> </category> -<!-- ARB extensions #99...#108 --> +<xi:include href="ARB_vertex_attrib_64bit.xml" xmlns:xi="http://www.w3.org/2001/XInclude"/> + +<!-- ARB extensions #100...#108 --> <xi:include href="ARB_ES2_compatibility.xml" xmlns:xi="http://www.w3.org/2001/XInclude"/> diff --git a/mesalib/src/mapi/glapi/gen/gl_genexec.py b/mesalib/src/mapi/glapi/gen/gl_genexec.py index 7151f0de1..4e76fe3c2 100644 --- a/mesalib/src/mapi/glapi/gen/gl_genexec.py +++ b/mesalib/src/mapi/glapi/gen/gl_genexec.py @@ -183,8 +183,8 @@ class PrintCode(gl_XML.gl_print_base): if 'es1' in f.api_map: condition_parts.append('ctx->API == API_OPENGLES') if 'es2' in f.api_map: - if f.api_map['es2'] == 3: - condition_parts.append('_mesa_is_gles3(ctx)') + if f.api_map['es2'] > 2.0: + condition_parts.append('(ctx->API == API_OPENGLES2 && ctx->Version >= {0})'.format(int(f.api_map['es2'] * 10))) else: condition_parts.append('ctx->API == API_OPENGLES2') if not condition_parts: diff --git a/mesalib/src/mapi/glapi/glapi_priv.h b/mesalib/src/mapi/glapi/glapi_priv.h index 50f710edc..337913acc 100644 --- a/mesalib/src/mapi/glapi/glapi_priv.h +++ b/mesalib/src/mapi/glapi/glapi_priv.h @@ -49,6 +49,10 @@ typedef void *GLeglImageOES; #include "glapi/glapi.h" +#ifdef __cplusplus +extern "C" { +#endif + /* getproc */ extern void @@ -106,4 +110,8 @@ get_entrypoint_address(unsigned int functionOffset); #define MAX_EXTENSION_FUNCS 256 +#ifdef __cplusplus +} +#endif + #endif diff --git a/mesalib/src/mesa/Makefile.sources b/mesalib/src/mesa/Makefile.sources index 1293d4135..83f500fbf 100644 --- a/mesalib/src/mesa/Makefile.sources +++ b/mesalib/src/mesa/Makefile.sources @@ -434,6 +434,8 @@ STATETRACKER_FILES = \ state_tracker/st_cb_flush.h \ state_tracker/st_cb_msaa.c \ state_tracker/st_cb_msaa.h \ + state_tracker/st_cb_perfmon.c \ + state_tracker/st_cb_perfmon.h \ state_tracker/st_cb_program.c \ state_tracker/st_cb_program.h \ state_tracker/st_cb_queryobj.c \ diff --git a/mesalib/src/mesa/drivers/common/driverfuncs.c b/mesalib/src/mesa/drivers/common/driverfuncs.c index 0d094ddf4..71c1a7639 100644 --- a/mesalib/src/mesa/drivers/common/driverfuncs.c +++ b/mesalib/src/mesa/drivers/common/driverfuncs.c @@ -172,7 +172,7 @@ _mesa_init_driver_functions(struct dd_function_table *driver) driver->UnmapRenderbuffer = _swrast_unmap_soft_renderbuffer; driver->RenderTexture = _swrast_render_texture; driver->FinishRenderTexture = _swrast_finish_render_texture; - driver->FramebufferRenderbuffer = _mesa_framebuffer_renderbuffer; + driver->FramebufferRenderbuffer = _mesa_FramebufferRenderbuffer_sw; driver->ValidateFramebuffer = _mesa_validate_framebuffer; driver->BlitFramebuffer = _swrast_BlitFramebuffer; diff --git a/mesalib/src/mesa/drivers/common/meta.c b/mesalib/src/mesa/drivers/common/meta.c index d2ab7b8de..214a68a91 100644 --- a/mesalib/src/mesa/drivers/common/meta.c +++ b/mesalib/src/mesa/drivers/common/meta.c @@ -1211,7 +1211,8 @@ _mesa_meta_end(struct gl_context *ctx) _mesa_BindRenderbuffer(GL_RENDERBUFFER, save->RenderbufferName); if (state & MESA_META_DRAW_BUFFERS) { - _mesa_drawbuffers(ctx, ctx->Const.MaxDrawBuffers, save->ColorDrawBuffers, NULL); + _mesa_drawbuffers(ctx, ctx->DrawBuffer, ctx->Const.MaxDrawBuffers, + save->ColorDrawBuffers, NULL); } ctx->Meta->SaveStackDepth--; diff --git a/mesalib/src/mesa/drivers/dri/swrast/swrast.c b/mesalib/src/mesa/drivers/dri/swrast/swrast.c index d1bb72139..cbc946c3f 100644 --- a/mesalib/src/mesa/drivers/dri/swrast/swrast.c +++ b/mesalib/src/mesa/drivers/dri/swrast/swrast.c @@ -61,6 +61,9 @@ #include "swrast_priv.h" #include "swrast/s_context.h" +#include <sys/types.h> +#include <sys/sysctl.h> + const __DRIextension **__driDriverGetExtensions_swrast(void); const char * const swrast_vendor_string = "Mesa Project"; @@ -137,6 +140,16 @@ swrast_query_renderer_integer(__DRIscreen *psp, int param, value[0] = 0; return 0; case __DRI2_RENDERER_VIDEO_MEMORY: { + /* This should probably share code with os_get_total_physical_memory() + * from src/gallium/auxiliary/os/os_misc.c + */ +#if defined(CTL_HW) && defined(HW_MEMSIZE) + int mib[2] = { CTL_HW, HW_MEMSIZE }; + unsigned long system_memory_bytes; + size_t len = sizeof(system_memory_bytes); + if (sysctl(mib, 2, &system_memory_bytes, &len, NULL, 0) != 0) + return -1; +#elif defined(_SC_PHYS_PAGES) && defined(_SC_PAGE_SIZE) /* XXX: Do we want to return the full amount of system memory ? */ const long system_memory_pages = sysconf(_SC_PHYS_PAGES); const long system_page_size = sysconf(_SC_PAGE_SIZE); @@ -146,6 +159,9 @@ swrast_query_renderer_integer(__DRIscreen *psp, int param, const uint64_t system_memory_bytes = (uint64_t) system_memory_pages * (uint64_t) system_page_size; +#else +#error "Unsupported platform" +#endif const unsigned system_memory_megabytes = (unsigned) (system_memory_bytes / (1024 * 1024)); @@ -942,6 +958,7 @@ static const __DRIextension *swrast_driver_extensions[] = { &driCoreExtension.base, &driSWRastExtension.base, &driCopySubBufferExtension.base, + &dri2ConfigQueryExtension.base, &swrast_vtable.base, NULL }; diff --git a/mesalib/src/mesa/main/api_arrayelt.c b/mesalib/src/mesa/main/api_arrayelt.c index ea015fd65..92d8238f4 100644 --- a/mesalib/src/mesa/main/api_arrayelt.c +++ b/mesalib/src/mesa/main/api_arrayelt.c @@ -1258,12 +1258,37 @@ VertexAttribI4uiv(GLuint index, const GLuint *v) CALL_VertexAttribI4uivEXT(GET_DISPATCH(), (index, v)); } +/* GL_DOUBLE unconverted attributes */ + +static void GLAPIENTRY +VertexAttribL1dv(GLuint index, const GLdouble *v) +{ + CALL_VertexAttribL1dv(GET_DISPATCH(), (index, v)); +} + +static void GLAPIENTRY +VertexAttribL2dv(GLuint index, const GLdouble *v) +{ + CALL_VertexAttribL2dv(GET_DISPATCH(), (index, v)); +} + +static void GLAPIENTRY +VertexAttribL3dv(GLuint index, const GLdouble *v) +{ + CALL_VertexAttribL3dv(GET_DISPATCH(), (index, v)); +} + +static void GLAPIENTRY +VertexAttribL4dv(GLuint index, const GLdouble *v) +{ + CALL_VertexAttribL4dv(GET_DISPATCH(), (index, v)); +} /* * Array [unnormalized/normalized/integer][size][type] of VertexAttrib * functions */ -static attrib_func AttribFuncsARB[3][4][NUM_TYPES] = { +static attrib_func AttribFuncsARB[4][4][NUM_TYPES] = { { /* non-normalized */ { @@ -1405,7 +1430,55 @@ static attrib_func AttribFuncsARB[3][4][NUM_TYPES] = { NULL, /* GL_FLOAT */ NULL /* GL_DOUBLE */ } + }, + { + /* double-valued */ + { + /* size 1 */ + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + (attrib_func) VertexAttribL1dv, + }, + { + /* size 2 */ + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + (attrib_func) VertexAttribL2dv, + }, + { + /* size 3 */ + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + (attrib_func) VertexAttribL3dv, + }, + { + /* size 4 */ + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + (attrib_func) VertexAttribL4dv, + } } + }; @@ -1571,7 +1644,9 @@ _ae_update_state(struct gl_context *ctx) * change from one execution of _ae_ArrayElement() to * the next. Doing so caused UT to break. */ - if (at->array->Integer) + if (at->array->Doubles) + intOrNorm = 3; + else if (at->array->Integer) intOrNorm = 2; else if (at->array->Normalized) intOrNorm = 1; diff --git a/mesalib/src/mesa/main/api_loopback.c b/mesalib/src/mesa/main/api_loopback.c index d10ae15ea..9932a8373 100644 --- a/mesalib/src/mesa/main/api_loopback.c +++ b/mesalib/src/mesa/main/api_loopback.c @@ -84,6 +84,10 @@ #define ATTRIBI_4UI(index,x,y,z,w) CALL_VertexAttribI4uiEXT(GET_DISPATCH(), (index,x,y,z,w)) +#define ATTRIB1_D(index,x) CALL_VertexAttribL1d(GET_DISPATCH(), (index,x)) +#define ATTRIB2_D(index,x,y) CALL_VertexAttribL2d(GET_DISPATCH(), (index,x,y)) +#define ATTRIB3_D(index,x,y,z) CALL_VertexAttribL3d(GET_DISPATCH(), (index,x,y,z)) +#define ATTRIB4_D(index,x,y,z,w) CALL_VertexAttribL4d(GET_DISPATCH(), (index,x,y,z,w)) void GLAPIENTRY _mesa_Color3b( GLbyte red, GLbyte green, GLbyte blue ) @@ -1490,8 +1494,53 @@ _mesa_VertexAttribI4usv(GLuint index, const GLushort *v) ATTRIBI_4UI(index, v[0], v[1], v[2], v[3]); } +void GLAPIENTRY +_mesa_VertexAttribL1d(GLuint index, GLdouble x) +{ + ATTRIB1_D(index, x); +} + +void GLAPIENTRY +_mesa_VertexAttribL2d(GLuint index, GLdouble x, GLdouble y) +{ + ATTRIB2_D(index, x, y); +} +void GLAPIENTRY +_mesa_VertexAttribL3d(GLuint index, GLdouble x, GLdouble y, GLdouble z) +{ + ATTRIB3_D(index, x, y, z); +} +void GLAPIENTRY +_mesa_VertexAttribL4d(GLuint index, GLdouble x, GLdouble y, GLdouble z, GLdouble w) +{ + ATTRIB4_D(index, x, y, z, w); +} + +void GLAPIENTRY +_mesa_VertexAttribL1dv(GLuint index, const GLdouble *v) +{ + ATTRIB1_D(index, v[0]); +} + +void GLAPIENTRY +_mesa_VertexAttribL2dv(GLuint index, const GLdouble *v) +{ + ATTRIB2_D(index, v[0], v[1]); +} + +void GLAPIENTRY +_mesa_VertexAttribL3dv(GLuint index, const GLdouble *v) +{ + ATTRIB3_D(index, v[0], v[1], v[2]); +} + +void GLAPIENTRY +_mesa_VertexAttribL4dv(GLuint index, const GLdouble *v) +{ + ATTRIB4_D(index, v[0], v[1], v[2], v[3]); +} /* * This code never registers handlers for any of the entry points @@ -1723,5 +1772,16 @@ _mesa_loopback_init_api_table(const struct gl_context *ctx, SET_VertexAttribI4sv(dest, _mesa_VertexAttribI4sv); SET_VertexAttribI4ubv(dest, _mesa_VertexAttribI4ubv); SET_VertexAttribI4usv(dest, _mesa_VertexAttribI4usv); + + /* GL 4.1 / GL_ARB_vertex_attrib_64bit */ + SET_VertexAttribL1d(dest, _mesa_VertexAttribL1d); + SET_VertexAttribL2d(dest, _mesa_VertexAttribL2d); + SET_VertexAttribL3d(dest, _mesa_VertexAttribL3d); + SET_VertexAttribL4d(dest, _mesa_VertexAttribL4d); + + SET_VertexAttribL1dv(dest, _mesa_VertexAttribL1dv); + SET_VertexAttribL2dv(dest, _mesa_VertexAttribL2dv); + SET_VertexAttribL3dv(dest, _mesa_VertexAttribL3dv); + SET_VertexAttribL4dv(dest, _mesa_VertexAttribL4dv); } } diff --git a/mesalib/src/mesa/main/api_loopback.h b/mesalib/src/mesa/main/api_loopback.h index 44514405b..026bfd68e 100644 --- a/mesalib/src/mesa/main/api_loopback.h +++ b/mesalib/src/mesa/main/api_loopback.h @@ -464,5 +464,21 @@ _mesa_VertexAttribI4ubv(GLuint index, const GLubyte *v); void GLAPIENTRY _mesa_VertexAttribI4usv(GLuint index, const GLushort *v); +void GLAPIENTRY +_mesa_VertexAttribL1d(GLuint index, GLdouble x); +void GLAPIENTRY +_mesa_VertexAttribL2d(GLuint index, GLdouble x, GLdouble y); +void GLAPIENTRY +_mesa_VertexAttribL3d(GLuint index, GLdouble x, GLdouble y, GLdouble z); +void GLAPIENTRY +_mesa_VertexAttribL4d(GLuint index, GLdouble x, GLdouble y, GLdouble z, GLdouble w); +void GLAPIENTRY +_mesa_VertexAttribL1dv(GLuint index, const GLdouble *v); +void GLAPIENTRY +_mesa_VertexAttribL2dv(GLuint index, const GLdouble *v); +void GLAPIENTRY +_mesa_VertexAttribL3dv(GLuint index, const GLdouble *v); +void GLAPIENTRY +_mesa_VertexAttribL4dv(GLuint index, const GLdouble *v); #endif /* API_LOOPBACK_H */ diff --git a/mesalib/src/mesa/main/arrayobj.c b/mesalib/src/mesa/main/arrayobj.c index 3c8ffb5a4..320f435ea 100644 --- a/mesalib/src/mesa/main/arrayobj.c +++ b/mesalib/src/mesa/main/arrayobj.c @@ -75,6 +75,61 @@ _mesa_lookup_vao(struct gl_context *ctx, GLuint id) /** + * Looks up the array object for the given ID. + * + * Unlike _mesa_lookup_vao, this function generates a GL_INVALID_OPERATION + * error if the array object does not exist. It also returns the default + * array object when ctx is a compatibility profile context and id is zero. + */ +struct gl_vertex_array_object * +_mesa_lookup_vao_err(struct gl_context *ctx, GLuint id, const char *caller) +{ + /* The ARB_direct_state_access specification says: + * + * "<vaobj> is [compatibility profile: + * zero, indicating the default vertex array object, or] + * the name of the vertex array object." + */ + if (id == 0) { + if (ctx->API == API_OPENGL_CORE) { + _mesa_error(ctx, GL_INVALID_OPERATION, + "%s(zero is not valid vaobj name in a core profile " + "context)", caller); + return NULL; + } + + return ctx->Array.DefaultVAO; + } else { + struct gl_vertex_array_object *vao; + + if (ctx->Array.LastLookedUpVAO && + ctx->Array.LastLookedUpVAO->Name == id) { + vao = ctx->Array.LastLookedUpVAO; + } else { + vao = (struct gl_vertex_array_object *) + _mesa_HashLookup(ctx->Array.Objects, id); + + /* The ARB_direct_state_access specification says: + * + * "An INVALID_OPERATION error is generated if <vaobj> is not + * [compatibility profile: zero or] the name of an existing + * vertex array object." + */ + if (!vao || !vao->EverBound) { + _mesa_error(ctx, GL_INVALID_OPERATION, + "%s(non-existent vaobj=%u)", caller, id); + return NULL; + } + + _mesa_reference_vao(ctx, &ctx->Array.LastLookedUpVAO, vao); + } + + return vao; + } +} + + +/** * For all the vertex binding points in the array object, unbind any pointers * to any buffer objects (VBOs). * This is done just prior to array object destruction. @@ -200,6 +255,7 @@ init_array(struct gl_context *ctx, array->Enabled = GL_FALSE; array->Normalized = GL_FALSE; array->Integer = GL_FALSE; + array->Doubles = GL_FALSE; array->_ElementSize = size * _mesa_sizeof_type(type); array->VertexBinding = index; @@ -469,6 +525,9 @@ _mesa_DeleteVertexArrays(GLsizei n, const GLuint *ids) /* The ID is immediately freed for re-use */ remove_array_object(ctx, obj); + if (ctx->Array.LastLookedUpVAO == obj) + _mesa_reference_vao(ctx, &ctx->Array.LastLookedUpVAO, NULL); + /* Unreference the array object. * If refcount hits zero, the object will be deleted. */ @@ -480,19 +539,23 @@ _mesa_DeleteVertexArrays(GLsizei n, const GLuint *ids) /** * Generate a set of unique array object IDs and store them in \c arrays. - * Helper for _mesa_GenVertexArrays[APPLE]() functions below. + * Helper for _mesa_GenVertexArrays[APPLE]() and _mesa_CreateVertexArrays() + * below. + * * \param n Number of IDs to generate. * \param arrays Array of \c n locations to store the IDs. - * \param vboOnly Will arrays have to reside in VBOs? + * \param create Indicates that the objects should also be created. + * \param func The name of the GL entry point. */ static void -gen_vertex_arrays(struct gl_context *ctx, GLsizei n, GLuint *arrays) +gen_vertex_arrays(struct gl_context *ctx, GLsizei n, GLuint *arrays, + bool create, const char *func) { GLuint first; GLint i; if (n < 0) { - _mesa_error(ctx, GL_INVALID_VALUE, "glGenVertexArrays"); + _mesa_error(ctx, GL_INVALID_VALUE, "%s(n < 0)", func); return; } @@ -502,16 +565,20 @@ gen_vertex_arrays(struct gl_context *ctx, GLsizei n, GLuint *arrays) first = _mesa_HashFindFreeKeyBlock(ctx->Array.Objects, n); - /* Allocate new, empty array objects and return identifiers */ + /* For the sake of simplicity we create the array objects in both + * the Gen* and Create* cases. The only difference is the value of + * EverBound, which is set to true in the Create* case. + */ for (i = 0; i < n; i++) { struct gl_vertex_array_object *obj; GLuint name = first + i; obj = (*ctx->Driver.NewArrayObject)( ctx, name ); if (!obj) { - _mesa_error(ctx, GL_OUT_OF_MEMORY, "glGenVertexArrays"); + _mesa_error(ctx, GL_OUT_OF_MEMORY, "%s", func); return; } + obj->EverBound = create; save_array_object(ctx, obj); arrays[i] = first + i; } @@ -526,7 +593,7 @@ void GLAPIENTRY _mesa_GenVertexArrays(GLsizei n, GLuint *arrays) { GET_CURRENT_CONTEXT(ctx); - gen_vertex_arrays(ctx, n, arrays); + gen_vertex_arrays(ctx, n, arrays, false, "glGenVertexArrays"); } @@ -538,7 +605,27 @@ void GLAPIENTRY _mesa_GenVertexArraysAPPLE(GLsizei n, GLuint *arrays) { GET_CURRENT_CONTEXT(ctx); - gen_vertex_arrays(ctx, n, arrays); + gen_vertex_arrays(ctx, n, arrays, false, "glGenVertexArraysAPPLE"); +} + + +/** + * ARB_direct_state_access + * Generates ID's and creates the array objects. + */ +void GLAPIENTRY +_mesa_CreateVertexArrays(GLsizei n, GLuint *arrays) +{ + GET_CURRENT_CONTEXT(ctx); + + if (!ctx->Extensions.ARB_direct_state_access) { + _mesa_error(ctx, GL_INVALID_OPERATION, + "glCreateVertexArrays(GL_ARB_direct_state_access " + "is not supported"); + return; + } + + gen_vertex_arrays(ctx, n, arrays, true, "glCreateVertexArrays"); } @@ -565,3 +652,92 @@ _mesa_IsVertexArray( GLuint id ) return obj->EverBound; } + + +/** + * Sets the element array buffer binding of a vertex array object. + * + * This is the ARB_direct_state_access equivalent of + * glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, buffer). + */ +void GLAPIENTRY +_mesa_VertexArrayElementBuffer(GLuint vaobj, GLuint buffer) +{ + GET_CURRENT_CONTEXT(ctx); + struct gl_vertex_array_object *vao; + struct gl_buffer_object *bufObj; + + if (!ctx->Extensions.ARB_direct_state_access) { + _mesa_error(ctx, GL_INVALID_OPERATION, + "glVertexArrayElementBuffer(GL_ARB_direct_state_access " + "is not supported"); + return; + } + + ASSERT_OUTSIDE_BEGIN_END(ctx); + + /* The GL_ARB_direct_state_access specification says: + * + * "An INVALID_OPERATION error is generated by VertexArrayElementBuffer + * if <vaobj> is not [compatibility profile: zero or] the name of an + * existing vertex array object." + */ + vao =_mesa_lookup_vao_err(ctx, vaobj, "glVertexArrayElementBuffer"); + if (!vao) + return; + + /* The GL_ARB_direct_state_access specification says: + * + * "An INVALID_OPERATION error is generated if <buffer> is not zero or + * the name of an existing buffer object." + */ + if (buffer != 0) + bufObj = _mesa_lookup_bufferobj_err(ctx, buffer, + "glVertexArrayElementBuffer"); + else + bufObj = ctx->Shared->NullBufferObj; + + if (bufObj) + _mesa_reference_buffer_object(ctx, &vao->IndexBufferObj, bufObj); +} + + +void GLAPIENTRY +_mesa_GetVertexArrayiv(GLuint vaobj, GLenum pname, GLint *param) +{ + GET_CURRENT_CONTEXT(ctx); + struct gl_vertex_array_object *vao; + + ASSERT_OUTSIDE_BEGIN_END(ctx); + + if (!ctx->Extensions.ARB_direct_state_access) { + _mesa_error(ctx, GL_INVALID_OPERATION, + "glGetVertexArrayiv(GL_ARB_direct_state_access " + "is not supported"); + return; + } + + /* The GL_ARB_direct_state_access specification says: + * + * "An INVALID_OPERATION error is generated if <vaobj> is not + * [compatibility profile: zero or] the name of an existing + * vertex array object." + */ + vao =_mesa_lookup_vao_err(ctx, vaobj, "glGetVertexArrayiv"); + if (!vao) + return; + + /* The GL_ARB_direct_state_access specification says: + * + * "An INVALID_ENUM error is generated if <pname> is not + * ELEMENT_ARRAY_BUFFER_BINDING." + */ + if (pname != GL_ELEMENT_ARRAY_BUFFER_BINDING) { + _mesa_error(ctx, GL_INVALID_ENUM, + "glGetVertexArrayiv(pname != " + "GL_ELEMENT_ARRAY_BUFFER_BINDING)"); + return; + } + + param[0] = vao->IndexBufferObj->Name; +} diff --git a/mesalib/src/mesa/main/arrayobj.h b/mesalib/src/mesa/main/arrayobj.h index 3c1f91835..6a4247f4a 100644 --- a/mesalib/src/mesa/main/arrayobj.h +++ b/mesalib/src/mesa/main/arrayobj.h @@ -49,6 +49,9 @@ extern struct gl_vertex_array_object * _mesa_lookup_vao(struct gl_context *ctx, GLuint id); extern struct gl_vertex_array_object * +_mesa_lookup_vao_err(struct gl_context *ctx, GLuint id, const char *caller); + +extern struct gl_vertex_array_object * _mesa_new_vao(struct gl_context *ctx, GLuint name); extern void @@ -93,6 +96,12 @@ void GLAPIENTRY _mesa_GenVertexArrays(GLsizei n, GLuint *arrays); void GLAPIENTRY _mesa_GenVertexArraysAPPLE(GLsizei n, GLuint *buffer); +void GLAPIENTRY _mesa_CreateVertexArrays(GLsizei n, GLuint *arrays); + GLboolean GLAPIENTRY _mesa_IsVertexArray( GLuint id ); +void GLAPIENTRY _mesa_VertexArrayElementBuffer(GLuint vaobj, GLuint buffer); + +void GLAPIENTRY _mesa_GetVertexArrayiv(GLuint vaobj, GLenum pname, GLint *param); + #endif /* ARRAYOBJ_H */ diff --git a/mesalib/src/mesa/main/blend.c b/mesalib/src/mesa/main/blend.c index 774fc888e..d869fa2aa 100644 --- a/mesalib/src/mesa/main/blend.c +++ b/mesalib/src/mesa/main/blend.c @@ -769,7 +769,7 @@ _mesa_ClampColor(GLenum target, GLenum clamp) } FLUSH_VERTICES(ctx, _NEW_LIGHT); ctx->Light.ClampVertexColor = clamp; - _mesa_update_clamp_vertex_color(ctx); + _mesa_update_clamp_vertex_color(ctx, ctx->DrawBuffer); break; case GL_CLAMP_FRAGMENT_COLOR_ARB: if (ctx->API == API_OPENGL_CORE && @@ -778,7 +778,7 @@ _mesa_ClampColor(GLenum target, GLenum clamp) } FLUSH_VERTICES(ctx, _NEW_FRAG_CLAMP); ctx->Color.ClampFragmentColor = clamp; - _mesa_update_clamp_fragment_color(ctx); + _mesa_update_clamp_fragment_color(ctx, ctx->DrawBuffer); break; case GL_CLAMP_READ_COLOR_ARB: ctx->Color.ClampReadColor = clamp; @@ -807,50 +807,55 @@ get_clamp_color(const struct gl_framebuffer *fb, GLenum clamp) } GLboolean -_mesa_get_clamp_fragment_color(const struct gl_context *ctx) +_mesa_get_clamp_fragment_color(const struct gl_context *ctx, + const struct gl_framebuffer *drawFb) { - return get_clamp_color(ctx->DrawBuffer, - ctx->Color.ClampFragmentColor); + return get_clamp_color(drawFb, ctx->Color.ClampFragmentColor); } GLboolean -_mesa_get_clamp_vertex_color(const struct gl_context *ctx) +_mesa_get_clamp_vertex_color(const struct gl_context *ctx, + const struct gl_framebuffer *drawFb) { - return get_clamp_color(ctx->DrawBuffer, ctx->Light.ClampVertexColor); + return get_clamp_color(drawFb, ctx->Light.ClampVertexColor); } GLboolean -_mesa_get_clamp_read_color(const struct gl_context *ctx) +_mesa_get_clamp_read_color(const struct gl_context *ctx, + const struct gl_framebuffer *readFb) { - return get_clamp_color(ctx->ReadBuffer, ctx->Color.ClampReadColor); + return get_clamp_color(readFb, ctx->Color.ClampReadColor); } /** * Update the ctx->Color._ClampFragmentColor field */ void -_mesa_update_clamp_fragment_color(struct gl_context *ctx) +_mesa_update_clamp_fragment_color(struct gl_context *ctx, + const struct gl_framebuffer *drawFb) { - struct gl_framebuffer *fb = ctx->DrawBuffer; - /* Don't clamp if: * - there is no colorbuffer * - all colorbuffers are unsigned normalized, so clamping has no effect * - there is an integer colorbuffer */ - if (!fb || !fb->_HasSNormOrFloatColorBuffer || fb->_IntegerColor) + if (!drawFb || !drawFb->_HasSNormOrFloatColorBuffer || + drawFb->_IntegerColor) ctx->Color._ClampFragmentColor = GL_FALSE; else - ctx->Color._ClampFragmentColor = _mesa_get_clamp_fragment_color(ctx); + ctx->Color._ClampFragmentColor = + _mesa_get_clamp_fragment_color(ctx, drawFb); } /** * Update the ctx->Color._ClampVertexColor field */ void -_mesa_update_clamp_vertex_color(struct gl_context *ctx) +_mesa_update_clamp_vertex_color(struct gl_context *ctx, + const struct gl_framebuffer *drawFb) { - ctx->Light._ClampVertexColor = _mesa_get_clamp_vertex_color(ctx); + ctx->Light._ClampVertexColor = + _mesa_get_clamp_vertex_color(ctx, drawFb); } /** diff --git a/mesalib/src/mesa/main/blend.h b/mesalib/src/mesa/main/blend.h index fe31a7440..8ab9e02fc 100644 --- a/mesalib/src/mesa/main/blend.h +++ b/mesalib/src/mesa/main/blend.h @@ -37,6 +37,7 @@ #include "formats.h" struct gl_context; +struct gl_framebuffer; extern void GLAPIENTRY @@ -101,19 +102,24 @@ extern void GLAPIENTRY _mesa_ClampColor(GLenum target, GLenum clamp); extern GLboolean -_mesa_get_clamp_fragment_color(const struct gl_context *ctx); +_mesa_get_clamp_fragment_color(const struct gl_context *ctx, + const struct gl_framebuffer *drawFb); extern GLboolean -_mesa_get_clamp_vertex_color(const struct gl_context *ctx); +_mesa_get_clamp_vertex_color(const struct gl_context *ctx, + const struct gl_framebuffer *drawFb); extern GLboolean -_mesa_get_clamp_read_color(const struct gl_context *ctx); +_mesa_get_clamp_read_color(const struct gl_context *ctx, + const struct gl_framebuffer *readFb); extern void -_mesa_update_clamp_fragment_color(struct gl_context *ctx); +_mesa_update_clamp_fragment_color(struct gl_context *ctx, + const struct gl_framebuffer *drawFb); extern void -_mesa_update_clamp_vertex_color(struct gl_context *ctx); +_mesa_update_clamp_vertex_color(struct gl_context *ctx, + const struct gl_framebuffer *drawFb); extern mesa_format _mesa_get_render_format(const struct gl_context *ctx, mesa_format format); diff --git a/mesalib/src/mesa/main/blit.c b/mesalib/src/mesa/main/blit.c index 0694466eb..fac972450 100644 --- a/mesalib/src/mesa/main/blit.c +++ b/mesalib/src/mesa/main/blit.c @@ -34,6 +34,7 @@ #include "enums.h" #include "blit.h" #include "fbobject.h" +#include "framebuffer.h" #include "glformats.h" #include "mtypes.h" #include "state.h" @@ -148,38 +149,25 @@ is_valid_blit_filter(const struct gl_context *ctx, GLenum filter) } -/** - * Blit rectangular region, optionally from one framebuffer to another. - * - * Note, if the src buffer is multisampled and the dest is not, this is - * when the samples must be resolved to a single color. - */ -void GLAPIENTRY -_mesa_BlitFramebuffer(GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1, - GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1, - GLbitfield mask, GLenum filter) +void +_mesa_blit_framebuffer(struct gl_context *ctx, + struct gl_framebuffer *readFb, + struct gl_framebuffer *drawFb, + GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1, + GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1, + GLbitfield mask, GLenum filter, const char *func) { const GLbitfield legalMaskBits = (GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT); - const struct gl_framebuffer *readFb, *drawFb; - GET_CURRENT_CONTEXT(ctx); FLUSH_VERTICES(ctx, 0); - if (MESA_VERBOSE & VERBOSE_API) - _mesa_debug(ctx, - "glBlitFramebuffer(%d, %d, %d, %d, %d, %d, %d, %d, 0x%x, %s)\n", - srcX0, srcY0, srcX1, srcY1, - dstX0, dstY0, dstX1, dstY1, - mask, _mesa_lookup_enum_by_nr(filter)); - - if (ctx->NewState) { - _mesa_update_state(ctx); - } + /* Update completeness status of readFb and drawFb. */ + _mesa_update_framebuffer(ctx, readFb, drawFb); - readFb = ctx->ReadBuffer; - drawFb = ctx->DrawBuffer; + /* Make sure drawFb has an initialized bounding box. */ + _mesa_update_draw_buffer_bounds(ctx, drawFb); if (!readFb || !drawFb) { /* This will normally never happen but someday we may want to @@ -192,12 +180,12 @@ _mesa_BlitFramebuffer(GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1, if (drawFb->_Status != GL_FRAMEBUFFER_COMPLETE_EXT || readFb->_Status != GL_FRAMEBUFFER_COMPLETE_EXT) { _mesa_error(ctx, GL_INVALID_FRAMEBUFFER_OPERATION_EXT, - "glBlitFramebufferEXT(incomplete draw/read buffers)"); + "%s(incomplete draw/read buffers)", func); return; } if (!is_valid_blit_filter(ctx, filter)) { - _mesa_error(ctx, GL_INVALID_ENUM, "glBlitFramebufferEXT(%s)", + _mesa_error(ctx, GL_INVALID_ENUM, "%s(invalid filter %s)", func, _mesa_lookup_enum_by_nr(filter)); return; } @@ -205,13 +193,13 @@ _mesa_BlitFramebuffer(GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1, if ((filter == GL_SCALED_RESOLVE_FASTEST_EXT || filter == GL_SCALED_RESOLVE_NICEST_EXT) && (readFb->Visual.samples == 0 || drawFb->Visual.samples > 0)) { - _mesa_error(ctx, GL_INVALID_OPERATION, "glBlitFramebufferEXT(%s)", + _mesa_error(ctx, GL_INVALID_OPERATION, "%s(%s: invalid samples)", func, _mesa_lookup_enum_by_nr(filter)); return; } if (mask & ~legalMaskBits) { - _mesa_error( ctx, GL_INVALID_VALUE, "glBlitFramebufferEXT(mask)"); + _mesa_error(ctx, GL_INVALID_VALUE, "%s(invalid mask bits set)", func); return; } @@ -219,13 +207,13 @@ _mesa_BlitFramebuffer(GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1, if ((mask & (GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT)) && filter != GL_NEAREST) { _mesa_error(ctx, GL_INVALID_OPERATION, - "glBlitFramebufferEXT(depth/stencil requires GL_NEAREST filter)"); + "%s(depth/stencil requires GL_NEAREST filter)", func); return; } /* get color read/draw renderbuffers */ if (mask & GL_COLOR_BUFFER_BIT) { - const GLuint numColorDrawBuffers = ctx->DrawBuffer->_NumColorDrawBuffers; + const GLuint numColorDrawBuffers = drawFb->_NumColorDrawBuffers; const struct gl_renderbuffer *colorReadRb = readFb->_ColorReadBuffer; const struct gl_renderbuffer *colorDrawRb = NULL; GLuint i; @@ -241,7 +229,7 @@ _mesa_BlitFramebuffer(GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1, } else { for (i = 0; i < numColorDrawBuffers; i++) { - colorDrawRb = ctx->DrawBuffer->_ColorDrawBuffers[i]; + colorDrawRb = drawFb->_ColorDrawBuffers[i]; if (!colorDrawRb) continue; @@ -257,15 +245,15 @@ _mesa_BlitFramebuffer(GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1, */ if (_mesa_is_gles3(ctx) && (colorDrawRb == colorReadRb)) { _mesa_error(ctx, GL_INVALID_OPERATION, - "glBlitFramebuffer(source and destination color " - "buffer cannot be the same)"); + "%s(source and destination color " + "buffer cannot be the same)", func); return; } if (!compatible_color_datatypes(colorReadRb->Format, colorDrawRb->Format)) { _mesa_error(ctx, GL_INVALID_OPERATION, - "glBlitFramebufferEXT(color buffer datatypes mismatch)"); + "%s(color buffer datatypes mismatch)", func); return; } /* extra checks for multisample copies... */ @@ -273,7 +261,7 @@ _mesa_BlitFramebuffer(GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1, /* color formats must match */ if (!compatible_resolve_formats(colorReadRb, colorDrawRb)) { _mesa_error(ctx, GL_INVALID_OPERATION, - "glBlitFramebufferEXT(bad src/dst multisample pixel formats)"); + "%s(bad src/dst multisample pixel formats)", func); return; } } @@ -286,7 +274,7 @@ _mesa_BlitFramebuffer(GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1, GLenum type = _mesa_get_format_datatype(colorReadRb->Format); if (type == GL_INT || type == GL_UNSIGNED_INT) { _mesa_error(ctx, GL_INVALID_OPERATION, - "glBlitFramebufferEXT(integer color type)"); + "%s(integer color type)", func); return; } } @@ -306,15 +294,15 @@ _mesa_BlitFramebuffer(GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1, * ignored." */ if ((readRb == NULL) || (drawRb == NULL)) { - mask &= ~GL_STENCIL_BUFFER_BIT; + mask &= ~GL_STENCIL_BUFFER_BIT; } else { int read_z_bits, draw_z_bits; if (_mesa_is_gles3(ctx) && (drawRb == readRb)) { _mesa_error(ctx, GL_INVALID_OPERATION, - "glBlitFramebuffer(source and destination stencil " - "buffer cannot be the same)"); + "%s(source and destination stencil " + "buffer cannot be the same)", func); return; } @@ -324,7 +312,7 @@ _mesa_BlitFramebuffer(GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1, * there is only one: GL_UNSIGNED_INT. */ _mesa_error(ctx, GL_INVALID_OPERATION, - "glBlitFramebuffer(stencil attachment format mismatch)"); + "%s(stencil attachment format mismatch)", func); return; } @@ -340,8 +328,8 @@ _mesa_BlitFramebuffer(GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1, _mesa_get_format_datatype(readRb->Format) != _mesa_get_format_datatype(drawRb->Format))) { - _mesa_error(ctx, GL_INVALID_OPERATION, "glBlitFramebuffer" - "(stencil attachment depth format mismatch)"); + _mesa_error(ctx, GL_INVALID_OPERATION, + "%s(stencil attachment depth format mismatch)", func); return; } } @@ -360,15 +348,15 @@ _mesa_BlitFramebuffer(GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1, * ignored." */ if ((readRb == NULL) || (drawRb == NULL)) { - mask &= ~GL_DEPTH_BUFFER_BIT; + mask &= ~GL_DEPTH_BUFFER_BIT; } else { int read_s_bit, draw_s_bit; if (_mesa_is_gles3(ctx) && (drawRb == readRb)) { _mesa_error(ctx, GL_INVALID_OPERATION, - "glBlitFramebuffer(source and destination depth " - "buffer cannot be the same)"); + "%s(source and destination depth " + "buffer cannot be the same)", func); return; } @@ -377,7 +365,7 @@ _mesa_BlitFramebuffer(GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1, (_mesa_get_format_datatype(readRb->Format) != _mesa_get_format_datatype(drawRb->Format))) { _mesa_error(ctx, GL_INVALID_OPERATION, - "glBlitFramebuffer(depth attachment format mismatch)"); + "%s(depth attachment format mismatch)", func); return; } @@ -389,8 +377,8 @@ _mesa_BlitFramebuffer(GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1, * we should ignore the stencil format check. */ if (read_s_bit > 0 && draw_s_bit > 0 && read_s_bit != draw_s_bit) { - _mesa_error(ctx, GL_INVALID_OPERATION, "glBlitFramebuffer" - "(depth attachment stencil bits mismatch)"); + _mesa_error(ctx, GL_INVALID_OPERATION, + "%s(depth attachment stencil bits mismatch)", func); return; } } @@ -406,7 +394,7 @@ _mesa_BlitFramebuffer(GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1, */ if (drawFb->Visual.samples > 0) { _mesa_error(ctx, GL_INVALID_OPERATION, - "glBlitFramebuffer(destination samples must be 0)"); + "%s(destination samples must be 0)", func); return; } @@ -426,7 +414,7 @@ _mesa_BlitFramebuffer(GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1, && (srcX0 != dstX0 || srcY0 != dstY0 || srcX1 != dstX1 || srcY1 != dstY1)) { _mesa_error(ctx, GL_INVALID_OPERATION, - "glBlitFramebuffer(bad src/dst multisample region)"); + "%s(bad src/dst multisample region)", func); return; } } else { @@ -434,7 +422,7 @@ _mesa_BlitFramebuffer(GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1, drawFb->Visual.samples > 0 && readFb->Visual.samples != drawFb->Visual.samples) { _mesa_error(ctx, GL_INVALID_OPERATION, - "glBlitFramebufferEXT(mismatched samples)"); + "%s(mismatched samples)", func); return; } @@ -445,7 +433,7 @@ _mesa_BlitFramebuffer(GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1, if (abs(srcX1 - srcX0) != abs(dstX1 - dstX0) || abs(srcY1 - srcY0) != abs(dstY1 - dstY0)) { _mesa_error(ctx, GL_INVALID_OPERATION, - "glBlitFramebufferEXT(bad src/dst multisample region sizes)"); + "%s(bad src/dst multisample region sizes)", func); return; } } @@ -457,43 +445,44 @@ _mesa_BlitFramebuffer(GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1, const struct gl_renderbuffer *colorDrawRb = NULL; GLuint i = 0; - printf("glBlitFramebuffer(%d, %d, %d, %d, %d, %d, %d, %d," - " 0x%x, 0x%x)\n", - srcX0, srcY0, srcX1, srcY1, - dstX0, dstY0, dstX1, dstY1, - mask, filter); + printf("%s(%d, %d, %d, %d, %d, %d, %d, %d," + " 0x%x, 0x%x)\n", func, + srcX0, srcY0, srcX1, srcY1, + dstX0, dstY0, dstX1, dstY1, + mask, filter); + if (colorReadRb) { const struct gl_renderbuffer_attachment *att; att = find_attachment(readFb, colorReadRb); printf(" Src FBO %u RB %u (%dx%d) ", - readFb->Name, colorReadRb->Name, - colorReadRb->Width, colorReadRb->Height); + readFb->Name, colorReadRb->Name, + colorReadRb->Width, colorReadRb->Height); if (att && att->Texture) { printf("Tex %u tgt 0x%x level %u face %u", - att->Texture->Name, - att->Texture->Target, - att->TextureLevel, - att->CubeMapFace); + att->Texture->Name, + att->Texture->Target, + att->TextureLevel, + att->CubeMapFace); } printf("\n"); /* Print all active color render buffers */ - for (i = 0; i < ctx->DrawBuffer->_NumColorDrawBuffers; i++) { - colorDrawRb = ctx->DrawBuffer->_ColorDrawBuffers[i]; + for (i = 0; i < drawFb->_NumColorDrawBuffers; i++) { + colorDrawRb = drawFb->_ColorDrawBuffers[i]; if (!colorDrawRb) continue; att = find_attachment(drawFb, colorDrawRb); printf(" Dst FBO %u RB %u (%dx%d) ", - drawFb->Name, colorDrawRb->Name, - colorDrawRb->Width, colorDrawRb->Height); + drawFb->Name, colorDrawRb->Name, + colorDrawRb->Width, colorDrawRb->Height); if (att && att->Texture) { printf("Tex %u tgt 0x%x level %u face %u", - att->Texture->Name, - att->Texture->Target, - att->TextureLevel, - att->CubeMapFace); + att->Texture->Name, + att->Texture->Target, + att->TextureLevel, + att->CubeMapFace); } printf("\n"); } @@ -507,8 +496,94 @@ _mesa_BlitFramebuffer(GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1, } assert(ctx->Driver.BlitFramebuffer); - ctx->Driver.BlitFramebuffer(ctx, ctx->ReadBuffer, ctx->DrawBuffer, + ctx->Driver.BlitFramebuffer(ctx, readFb, drawFb, srcX0, srcY0, srcX1, srcY1, dstX0, dstY0, dstX1, dstY1, mask, filter); } + + +/** + * Blit rectangular region, optionally from one framebuffer to another. + * + * Note, if the src buffer is multisampled and the dest is not, this is + * when the samples must be resolved to a single color. + */ +void GLAPIENTRY +_mesa_BlitFramebuffer(GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1, + GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1, + GLbitfield mask, GLenum filter) +{ + GET_CURRENT_CONTEXT(ctx); + + if (MESA_VERBOSE & VERBOSE_API) + _mesa_debug(ctx, + "glBlitFramebuffer(%d, %d, %d, %d, " + " %d, %d, %d, %d, 0x%x, %s)\n", + srcX0, srcY0, srcX1, srcY1, + dstX0, dstY0, dstX1, dstY1, + mask, _mesa_lookup_enum_by_nr(filter)); + + _mesa_blit_framebuffer(ctx, ctx->ReadBuffer, ctx->DrawBuffer, + srcX0, srcY0, srcX1, srcY1, + dstX0, dstY0, dstX1, dstY1, + mask, filter, "glBlitFramebuffer"); +} + + +void GLAPIENTRY +_mesa_BlitNamedFramebuffer(GLuint readFramebuffer, GLuint drawFramebuffer, + GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1, + GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1, + GLbitfield mask, GLenum filter) +{ + GET_CURRENT_CONTEXT(ctx); + struct gl_framebuffer *readFb, *drawFb; + + if (!ctx->Extensions.ARB_direct_state_access) { + _mesa_error(ctx, GL_INVALID_OPERATION, + "glBlitNamedFramebuffer(GL_ARB_direct_state_access " + "is not supported)"); + return; + } + + if (MESA_VERBOSE & VERBOSE_API) + _mesa_debug(ctx, + "glBlitNamedFramebuffer(%u %u %d, %d, %d, %d, " + " %d, %d, %d, %d, 0x%x, %s)\n", + readFramebuffer, drawFramebuffer, + srcX0, srcY0, srcX1, srcY1, + dstX0, dstY0, dstX1, dstY1, + mask, _mesa_lookup_enum_by_nr(filter)); + + /* + * According to PDF page 533 of the OpenGL 4.5 core spec (30.10.2014, + * Section 18.3 Copying Pixels): + * "... if readFramebuffer or drawFramebuffer is zero (for + * BlitNamedFramebuffer), then the default read or draw framebuffer is + * used as the corresponding source or destination framebuffer, + * respectively." + */ + if (readFramebuffer) { + readFb = _mesa_lookup_framebuffer_err(ctx, readFramebuffer, + "glBlitNamedFramebuffer"); + if (!readFb) + return; + } + else + readFb = ctx->WinSysReadBuffer; + + if (drawFramebuffer) { + drawFb = _mesa_lookup_framebuffer_err(ctx, drawFramebuffer, + "glBlitNamedFramebuffer"); + if (!drawFb) + return; + } + else + drawFb = ctx->WinSysDrawBuffer; + + _mesa_blit_framebuffer(ctx, readFb, drawFb, + srcX0, srcY0, srcX1, srcY1, + dstX0, dstY0, dstX1, dstY1, + mask, filter, "glBlitNamedFramebuffer"); +} diff --git a/mesalib/src/mesa/main/blit.h b/mesalib/src/mesa/main/blit.h index 01a958af5..54b946e31 100644 --- a/mesalib/src/mesa/main/blit.h +++ b/mesalib/src/mesa/main/blit.h @@ -28,11 +28,24 @@ #include "glheader.h" +extern void +_mesa_blit_framebuffer(struct gl_context *ctx, + struct gl_framebuffer *readFb, + struct gl_framebuffer *drawFb, + GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1, + GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1, + GLbitfield mask, GLenum filter, const char *func); extern void GLAPIENTRY _mesa_BlitFramebuffer(GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1, GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1, GLbitfield mask, GLenum filter); +extern void GLAPIENTRY +_mesa_BlitNamedFramebuffer(GLuint readFramebuffer, GLuint drawFramebuffer, + GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1, + GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1, + GLbitfield mask, GLenum filter); + #endif /* BLIT_H */ diff --git a/mesalib/src/mesa/main/bufferobj.c b/mesalib/src/mesa/main/bufferobj.c index 66dee6802..660bc9489 100644 --- a/mesalib/src/mesa/main/bufferobj.c +++ b/mesalib/src/mesa/main/bufferobj.c @@ -1303,6 +1303,12 @@ create_buffers(GLsizei n, GLuint *buffers, bool dsa) const char *func = dsa ? "glCreateBuffers" : "glGenBuffers"; + if (dsa && !ctx->Extensions.ARB_direct_state_access) { + _mesa_error(ctx, GL_INVALID_OPERATION, + "%s(GL_ARB_direct_state_access is not supported)", func); + return; + } + if (MESA_VERBOSE & VERBOSE_API) _mesa_debug(ctx, "%s(%d)\n", func, n); @@ -1477,6 +1483,13 @@ _mesa_NamedBufferStorage(GLuint buffer, GLsizeiptr size, const GLvoid *data, GET_CURRENT_CONTEXT(ctx); struct gl_buffer_object *bufObj; + if (!ctx->Extensions.ARB_direct_state_access) { + _mesa_error(ctx, GL_INVALID_OPERATION, + "glNamedBufferStorage(GL_ARB_direct_state_access " + "is not supported)"); + return; + } + bufObj = _mesa_lookup_bufferobj_err(ctx, buffer, "glNamedBufferStorage"); if (!bufObj) return; @@ -1603,6 +1616,13 @@ _mesa_NamedBufferData(GLuint buffer, GLsizeiptr size, const GLvoid *data, GET_CURRENT_CONTEXT(ctx); struct gl_buffer_object *bufObj; + if (!ctx->Extensions.ARB_direct_state_access) { + _mesa_error(ctx, GL_INVALID_OPERATION, + "glNamedBufferData(GL_ARB_direct_state_access " + "is not supported)"); + return; + } + bufObj = _mesa_lookup_bufferobj_err(ctx, buffer, "glNamedBufferData"); if (!bufObj) return; @@ -1673,6 +1693,13 @@ _mesa_NamedBufferSubData(GLuint buffer, GLintptr offset, GET_CURRENT_CONTEXT(ctx); struct gl_buffer_object *bufObj; + if (!ctx->Extensions.ARB_direct_state_access) { + _mesa_error(ctx, GL_INVALID_OPERATION, + "glNamedBufferSubData(GL_ARB_direct_state_access " + "is not supported)"); + return; + } + bufObj = _mesa_lookup_bufferobj_err(ctx, buffer, "glNamedBufferSubData"); if (!bufObj) return; @@ -1710,6 +1737,13 @@ _mesa_GetNamedBufferSubData(GLuint buffer, GLintptr offset, GET_CURRENT_CONTEXT(ctx); struct gl_buffer_object *bufObj; + if (!ctx->Extensions.ARB_direct_state_access) { + _mesa_error(ctx, GL_INVALID_OPERATION, + "glGetNamedBufferSubData(GL_ARB_direct_state_access " + "is not supported)"); + return; + } + bufObj = _mesa_lookup_bufferobj_err(ctx, buffer, "glGetNamedBufferSubData"); if (!bufObj) @@ -1805,6 +1839,13 @@ _mesa_ClearNamedBufferData(GLuint buffer, GLenum internalformat, GET_CURRENT_CONTEXT(ctx); struct gl_buffer_object *bufObj; + if (!ctx->Extensions.ARB_direct_state_access) { + _mesa_error(ctx, GL_INVALID_OPERATION, + "glClearNamedBufferData(GL_ARB_direct_state_access " + "is not supported)"); + return; + } + bufObj = _mesa_lookup_bufferobj_err(ctx, buffer, "glClearNamedBufferData"); if (!bufObj) return; @@ -1842,6 +1883,13 @@ _mesa_ClearNamedBufferSubData(GLuint buffer, GLenum internalformat, GET_CURRENT_CONTEXT(ctx); struct gl_buffer_object *bufObj; + if (!ctx->Extensions.ARB_direct_state_access) { + _mesa_error(ctx, GL_INVALID_OPERATION, + "glClearNamedBufferSubData(GL_ARB_direct_state_access " + "is not supported)"); + return; + } + bufObj = _mesa_lookup_bufferobj_err(ctx, buffer, "glClearNamedBufferSubData"); if (!bufObj) @@ -1930,6 +1978,13 @@ _mesa_UnmapNamedBuffer(GLuint buffer) GET_CURRENT_CONTEXT(ctx); struct gl_buffer_object *bufObj; + if (!ctx->Extensions.ARB_direct_state_access) { + _mesa_error(ctx, GL_INVALID_OPERATION, + "glUnmapNamedBuffer(GL_ARB_direct_state_access " + "is not supported)"); + return GL_FALSE; + } + bufObj = _mesa_lookup_bufferobj_err(ctx, buffer, "glUnmapNamedBuffer"); if (!bufObj) return GL_FALSE; @@ -2039,6 +2094,13 @@ _mesa_GetNamedBufferParameteriv(GLuint buffer, GLenum pname, GLint *params) struct gl_buffer_object *bufObj; GLint64 parameter; + if (!ctx->Extensions.ARB_direct_state_access) { + _mesa_error(ctx, GL_INVALID_OPERATION, + "glGetNamedBufferParameteriv(GL_ARB_direct_state_access " + "is not supported)"); + return; + } + bufObj = _mesa_lookup_bufferobj_err(ctx, buffer, "glGetNamedBufferParameteriv"); if (!bufObj) @@ -2059,6 +2121,13 @@ _mesa_GetNamedBufferParameteri64v(GLuint buffer, GLenum pname, struct gl_buffer_object *bufObj; GLint64 parameter; + if (!ctx->Extensions.ARB_direct_state_access) { + _mesa_error(ctx, GL_INVALID_OPERATION, + "glGetNamedBufferParameteri64v(GL_ARB_direct_state_access " + "is not supported)"); + return; + } + bufObj = _mesa_lookup_bufferobj_err(ctx, buffer, "glGetNamedBufferParameteri64v"); if (!bufObj) @@ -2098,6 +2167,13 @@ _mesa_GetNamedBufferPointerv(GLuint buffer, GLenum pname, GLvoid **params) GET_CURRENT_CONTEXT(ctx); struct gl_buffer_object *bufObj; + if (!ctx->Extensions.ARB_direct_state_access) { + _mesa_error(ctx, GL_INVALID_OPERATION, + "glGetNamedBufferPointerv(GL_ARB_direct_state_access " + "is not supported)"); + return; + } + if (pname != GL_BUFFER_MAP_POINTER) { _mesa_error(ctx, GL_INVALID_ENUM, "glGetNamedBufferPointerv(pname != " "GL_BUFFER_MAP_POINTER)"); @@ -2212,6 +2288,13 @@ _mesa_CopyNamedBufferSubData(GLuint readBuffer, GLuint writeBuffer, GET_CURRENT_CONTEXT(ctx); struct gl_buffer_object *src, *dst; + if (!ctx->Extensions.ARB_direct_state_access) { + _mesa_error(ctx, GL_INVALID_OPERATION, + "glCopyNamedBufferSubData(GL_ARB_direct_state_access " + "is not supported)"); + return; + } + src = _mesa_lookup_bufferobj_err(ctx, readBuffer, "glCopyNamedBufferSubData"); if (!src) @@ -2430,6 +2513,13 @@ _mesa_MapNamedBufferRange(GLuint buffer, GLintptr offset, GLsizeiptr length, GET_CURRENT_CONTEXT(ctx); struct gl_buffer_object *bufObj; + if (!ctx->Extensions.ARB_direct_state_access) { + _mesa_error(ctx, GL_INVALID_OPERATION, + "glMapNamedBufferRange(GL_ARB_direct_state_access " + "is not supported)"); + return NULL; + } + if (!ctx->Extensions.ARB_map_buffer_range) { _mesa_error(ctx, GL_INVALID_OPERATION, "glMapNamedBufferRange(" @@ -2497,6 +2587,13 @@ _mesa_MapNamedBuffer(GLuint buffer, GLenum access) struct gl_buffer_object *bufObj; GLbitfield accessFlags; + if (!ctx->Extensions.ARB_direct_state_access) { + _mesa_error(ctx, GL_INVALID_OPERATION, + "glMapNamedBuffer(GL_ARB_direct_state_access " + "is not supported)"); + return NULL; + } + if (!get_map_buffer_access_flags(ctx, access, &accessFlags)) { _mesa_error(ctx, GL_INVALID_ENUM, "glMapNamedBuffer(invalid access)"); return NULL; @@ -2587,6 +2684,14 @@ _mesa_FlushMappedNamedBufferRange(GLuint buffer, GLintptr offset, GET_CURRENT_CONTEXT(ctx); struct gl_buffer_object *bufObj; + if (!ctx->Extensions.ARB_direct_state_access) { + _mesa_error(ctx, GL_INVALID_OPERATION, + "glFlushMappedNamedBufferRange(GL_ARB_direct_state_access " + "is not supported)"); + return; + } + + bufObj = _mesa_lookup_bufferobj_err(ctx, buffer, "glFlushMappedNamedBufferRange"); if (!bufObj) diff --git a/mesalib/src/mesa/main/buffers.c b/mesalib/src/mesa/main/buffers.c index 37a979092..c83459add 100644 --- a/mesalib/src/mesa/main/buffers.c +++ b/mesalib/src/mesa/main/buffers.c @@ -242,16 +242,16 @@ read_buffer_enum_to_index(GLenum buffer) * * See the GL_EXT_framebuffer_object spec for more info. */ -void GLAPIENTRY -_mesa_DrawBuffer(GLenum buffer) +void +_mesa_draw_buffer(struct gl_context *ctx, struct gl_framebuffer *fb, + GLenum buffer, const char *caller) { GLbitfield destMask; - GET_CURRENT_CONTEXT(ctx); FLUSH_VERTICES(ctx, 0); if (MESA_VERBOSE & VERBOSE_API) { - _mesa_debug(ctx, "glDrawBuffer %s\n", _mesa_lookup_enum_by_nr(buffer)); + _mesa_debug(ctx, "%s %s\n", caller, _mesa_lookup_enum_by_nr(buffer)); } if (buffer == GL_NONE) { @@ -259,33 +259,67 @@ _mesa_DrawBuffer(GLenum buffer) } else { const GLbitfield supportedMask - = supported_buffer_bitmask(ctx, ctx->DrawBuffer); + = supported_buffer_bitmask(ctx, fb); destMask = draw_buffer_enum_to_bitmask(ctx, buffer); if (destMask == BAD_MASK) { /* totally bogus buffer */ - _mesa_error(ctx, GL_INVALID_ENUM, - "glDrawBuffer(buffer=0x%x)", buffer); + _mesa_error(ctx, GL_INVALID_ENUM, "%s(invalid buffer %s)", caller, + _mesa_lookup_enum_by_nr(buffer)); return; } destMask &= supportedMask; if (destMask == 0x0) { /* none of the named color buffers exist! */ - _mesa_error(ctx, GL_INVALID_OPERATION, - "glDrawBuffer(buffer=0x%x)", buffer); + _mesa_error(ctx, GL_INVALID_OPERATION, "%s(invalid buffer %s)", + caller, _mesa_lookup_enum_by_nr(buffer)); return; } } /* if we get here, there's no error so set new state */ - _mesa_drawbuffers(ctx, 1, &buffer, &destMask); + _mesa_drawbuffers(ctx, fb, 1, &buffer, &destMask); + + /* Call device driver function only if fb is the bound draw buffer */ + if (fb == ctx->DrawBuffer) { + if (ctx->Driver.DrawBuffers) + ctx->Driver.DrawBuffers(ctx, 1, &buffer); + else if (ctx->Driver.DrawBuffer) + ctx->Driver.DrawBuffer(ctx, buffer); + } +} - /* - * Call device driver function. - */ - if (ctx->Driver.DrawBuffers) - ctx->Driver.DrawBuffers(ctx, 1, &buffer); - else if (ctx->Driver.DrawBuffer) - ctx->Driver.DrawBuffer(ctx, buffer); + +void GLAPIENTRY +_mesa_DrawBuffer(GLenum buffer) +{ + GET_CURRENT_CONTEXT(ctx); + _mesa_draw_buffer(ctx, ctx->DrawBuffer, buffer, "glDrawBuffer"); +} + + +void GLAPIENTRY +_mesa_NamedFramebufferDrawBuffer(GLuint framebuffer, GLenum buf) +{ + GET_CURRENT_CONTEXT(ctx); + struct gl_framebuffer *fb; + + if (!ctx->Extensions.ARB_direct_state_access) { + _mesa_error(ctx, GL_INVALID_OPERATION, + "glNamedFramebufferDrawBuffer(GL_ARB_direct_state_access " + "is not supported)"); + return; + } + + if (framebuffer) { + fb = _mesa_lookup_framebuffer_err(ctx, framebuffer, + "glNamedFramebufferDrawBuffer"); + if (!fb) + return; + } + else + fb = ctx->WinSysDrawBuffer; + + _mesa_draw_buffer(ctx, fb, buf, "glNamedFramebufferDrawBuffer"); } @@ -298,13 +332,13 @@ _mesa_DrawBuffer(GLenum buffer) * names cannot specify more than one buffer. For example, * GL_FRONT_AND_BACK is illegal. */ -void GLAPIENTRY -_mesa_DrawBuffers(GLsizei n, const GLenum *buffers) +void +_mesa_draw_buffers(struct gl_context *ctx, struct gl_framebuffer *fb, + GLsizei n, const GLenum *buffers, const char *caller) { GLuint output; GLbitfield usedBufferMask, supportedMask; GLbitfield destMask[MAX_DRAW_BUFFERS]; - GET_CURRENT_CONTEXT(ctx); FLUSH_VERTICES(ctx, 0); @@ -315,12 +349,18 @@ _mesa_DrawBuffers(GLsizei n, const GLenum *buffers) * "An INVALID_VALUE error is generated if n is greater than * MAX_DRAW_BUFFERS." */ - if (n < 0 || n > (GLsizei) ctx->Const.MaxDrawBuffers) { - _mesa_error(ctx, GL_INVALID_VALUE, "glDrawBuffersARB(n)"); + if (n < 0) { + _mesa_error(ctx, GL_INVALID_VALUE, "%s(n < 0)", caller); + return; + } + + if (n > (GLsizei) ctx->Const.MaxDrawBuffers) { + _mesa_error(ctx, GL_INVALID_VALUE, + "%s(n > maximum number of draw buffers)", caller); return; } - supportedMask = supported_buffer_bitmask(ctx, ctx->DrawBuffer); + supportedMask = supported_buffer_bitmask(ctx, fb); usedBufferMask = 0x0; /* From the ES 3.0 specification, page 180: @@ -328,9 +368,9 @@ _mesa_DrawBuffers(GLsizei n, const GLenum *buffers) * and the constant must be BACK or NONE." * (same restriction applies with GL_EXT_draw_buffers specification) */ - if (ctx->API == API_OPENGLES2 && _mesa_is_winsys_fbo(ctx->DrawBuffer) && + if (ctx->API == API_OPENGLES2 && _mesa_is_winsys_fbo(fb) && (n != 1 || (buffers[0] != GL_NONE && buffers[0] != GL_BACK))) { - _mesa_error(ctx, GL_INVALID_OPERATION, "glDrawBuffers(buffer)"); + _mesa_error(ctx, GL_INVALID_OPERATION, "%s(invalid buffers)", caller); return; } @@ -362,9 +402,11 @@ _mesa_DrawBuffers(GLsizei n, const GLenum *buffers) * or equal to the value of MAX_COLOR_ATTACHMENTS, then the error * INVALID_OPERATION results." */ - if (_mesa_is_user_fbo(ctx->DrawBuffer) && buffers[output] >= + if (_mesa_is_user_fbo(fb) && buffers[output] >= GL_COLOR_ATTACHMENT0 + ctx->Const.MaxDrawBuffers) { - _mesa_error(ctx, GL_INVALID_OPERATION, "glDrawBuffersARB(buffer)"); + _mesa_error(ctx, GL_INVALID_OPERATION, + "%s(buffers[%d] >= maximum number of draw buffers)", + caller, output); return; } @@ -375,9 +417,10 @@ _mesa_DrawBuffers(GLsizei n, const GLenum *buffers) * 4.5 or 4.6. Otherwise, an INVALID_ENUM error is generated. */ if (destMask[output] == BAD_MASK) { - _mesa_error(ctx, GL_INVALID_ENUM, "glDrawBuffersARB(buffer)"); + _mesa_error(ctx, GL_INVALID_ENUM, "%s(invalid buffer %s)", + caller, _mesa_lookup_enum_by_nr(buffers[output])); return; - } + } /* From the OpenGL 4.0 specification, page 256: * "For both the default framebuffer and framebuffer objects, the @@ -390,7 +433,8 @@ _mesa_DrawBuffers(GLsizei n, const GLenum *buffers) * but the Khronos conformance tests expect INVALID_ENUM. */ if (_mesa_bitcount(destMask[output]) > 1) { - _mesa_error(ctx, GL_INVALID_ENUM, "glDrawBuffersARB(buffer)"); + _mesa_error(ctx, GL_INVALID_ENUM, "%s(invalid buffer %s)", + caller, _mesa_lookup_enum_by_nr(buffers[output])); return; } @@ -407,7 +451,8 @@ _mesa_DrawBuffers(GLsizei n, const GLenum *buffers) destMask[output] &= supportedMask; if (destMask[output] == 0) { _mesa_error(ctx, GL_INVALID_OPERATION, - "glDrawBuffersARB(unsupported buffer)"); + "%s(unsupported buffer %s)", + caller, _mesa_lookup_enum_by_nr(buffers[output])); return; } @@ -416,10 +461,12 @@ _mesa_DrawBuffers(GLsizei n, const GLenum *buffers) * in bufs must be COLOR_ATTACHMENTi or NONE. [...] INVALID_OPERATION." * (same restriction applies with GL_EXT_draw_buffers specification) */ - if (ctx->API == API_OPENGLES2 && _mesa_is_user_fbo(ctx->DrawBuffer) && + if (ctx->API == API_OPENGLES2 && _mesa_is_user_fbo(fb) && buffers[output] != GL_NONE && buffers[output] != GL_COLOR_ATTACHMENT0 + output) { - _mesa_error(ctx, GL_INVALID_OPERATION, "glDrawBuffers(buffer)"); + _mesa_error(ctx, GL_INVALID_OPERATION, + "%s(unsupported buffer %s)", + caller, _mesa_lookup_enum_by_nr(buffers[output])); return; } @@ -430,7 +477,8 @@ _mesa_DrawBuffers(GLsizei n, const GLenum *buffers) */ if (destMask[output] & usedBufferMask) { _mesa_error(ctx, GL_INVALID_OPERATION, - "glDrawBuffersARB(duplicated buffer)"); + "%s(duplicated buffer %s)", + caller, _mesa_lookup_enum_by_nr(buffers[output])); return; } @@ -440,17 +488,55 @@ _mesa_DrawBuffers(GLsizei n, const GLenum *buffers) } /* OK, if we get here, there were no errors so set the new state */ - _mesa_drawbuffers(ctx, n, buffers, destMask); + _mesa_drawbuffers(ctx, fb, n, buffers, destMask); /* - * Call device driver function. Note that n can be equal to 0, + * Call device driver function if fb is the bound draw buffer. + * Note that n can be equal to 0, * in which case we don't want to reference buffers[0], which * may not be valid. */ - if (ctx->Driver.DrawBuffers) - ctx->Driver.DrawBuffers(ctx, n, buffers); - else if (ctx->Driver.DrawBuffer) - ctx->Driver.DrawBuffer(ctx, n > 0 ? buffers[0] : GL_NONE); + if (fb == ctx->DrawBuffer) { + if (ctx->Driver.DrawBuffers) + ctx->Driver.DrawBuffers(ctx, n, buffers); + else if (ctx->Driver.DrawBuffer) + ctx->Driver.DrawBuffer(ctx, n > 0 ? buffers[0] : GL_NONE); + } +} + + +void GLAPIENTRY +_mesa_DrawBuffers(GLsizei n, const GLenum *buffers) +{ + GET_CURRENT_CONTEXT(ctx); + _mesa_draw_buffers(ctx, ctx->DrawBuffer, n, buffers, "glDrawBuffers"); +} + + +void GLAPIENTRY +_mesa_NamedFramebufferDrawBuffers(GLuint framebuffer, GLsizei n, + const GLenum *bufs) +{ + GET_CURRENT_CONTEXT(ctx); + struct gl_framebuffer *fb; + + if (!ctx->Extensions.ARB_direct_state_access) { + _mesa_error(ctx, GL_INVALID_OPERATION, + "glNamedFramebufferDrawBuffers(GL_ARB_direct_state_access " + "is not supported)"); + return; + } + + if (framebuffer) { + fb = _mesa_lookup_framebuffer_err(ctx, framebuffer, + "glNamedFramebufferDrawBuffers"); + if (!fb) + return; + } + else + fb = ctx->WinSysDrawBuffer; + + _mesa_draw_buffers(ctx, fb, n, bufs, "glNamedFramebufferDrawBuffers"); } @@ -459,13 +545,11 @@ _mesa_DrawBuffers(GLsizei n, const GLenum *buffers) * actual change. */ static void -updated_drawbuffers(struct gl_context *ctx) +updated_drawbuffers(struct gl_context *ctx, struct gl_framebuffer *fb) { FLUSH_VERTICES(ctx, _NEW_BUFFERS); if (ctx->API == API_OPENGL_COMPAT && !ctx->Extensions.ARB_ES2_compatibility) { - struct gl_framebuffer *fb = ctx->DrawBuffer; - /* Flag the FBO as requiring validation. */ if (_mesa_is_user_fbo(fb)) { fb->_Status = 0; @@ -482,6 +566,7 @@ updated_drawbuffers(struct gl_context *ctx) * so nothing should go wrong at this point. * * \param ctx current context + * \param fb the desired draw buffer * \param n number of color outputs to set * \param buffers array[n] of colorbuffer names, like GL_LEFT. * \param destMask array[n] of BUFFER_BIT_* bitmasks which correspond to the @@ -489,10 +574,9 @@ updated_drawbuffers(struct gl_context *ctx) * BUFFER_BIT_FRONT_LEFT | BUFFER_BIT_BACK_LEFT). */ void -_mesa_drawbuffers(struct gl_context *ctx, GLuint n, const GLenum *buffers, - const GLbitfield *destMask) +_mesa_drawbuffers(struct gl_context *ctx, struct gl_framebuffer *fb, + GLuint n, const GLenum *buffers, const GLbitfield *destMask) { - struct gl_framebuffer *fb = ctx->DrawBuffer; GLbitfield mask[MAX_DRAW_BUFFERS]; GLuint buf; @@ -518,7 +602,7 @@ _mesa_drawbuffers(struct gl_context *ctx, GLuint n, const GLenum *buffers, while (destMask0) { GLint bufIndex = ffs(destMask0) - 1; if (fb->_ColorDrawBufferIndexes[count] != bufIndex) { - updated_drawbuffers(ctx); + updated_drawbuffers(ctx, fb); fb->_ColorDrawBufferIndexes[count] = bufIndex; } count++; @@ -535,14 +619,14 @@ _mesa_drawbuffers(struct gl_context *ctx, GLuint n, const GLenum *buffers, /* only one bit should be set in the destMask[buf] field */ assert(_mesa_bitcount(destMask[buf]) == 1); if (fb->_ColorDrawBufferIndexes[buf] != bufIndex) { - updated_drawbuffers(ctx); + updated_drawbuffers(ctx, fb); fb->_ColorDrawBufferIndexes[buf] = bufIndex; } count = buf + 1; } else { if (fb->_ColorDrawBufferIndexes[buf] != -1) { - updated_drawbuffers(ctx); + updated_drawbuffers(ctx, fb); fb->_ColorDrawBufferIndexes[buf] = -1; } } @@ -554,7 +638,7 @@ _mesa_drawbuffers(struct gl_context *ctx, GLuint n, const GLenum *buffers, /* set remaining outputs to -1 (GL_NONE) */ for (buf = fb->_NumColorDrawBuffers; buf < ctx->Const.MaxDrawBuffers; buf++) { if (fb->_ColorDrawBufferIndexes[buf] != -1) { - updated_drawbuffers(ctx); + updated_drawbuffers(ctx, fb); fb->_ColorDrawBufferIndexes[buf] = -1; } } @@ -566,7 +650,7 @@ _mesa_drawbuffers(struct gl_context *ctx, GLuint n, const GLenum *buffers, /* also set context drawbuffer state */ for (buf = 0; buf < ctx->Const.MaxDrawBuffers; buf++) { if (ctx->Color.DrawBuffer[buf] != fb->ColorDrawBuffer[buf]) { - updated_drawbuffers(ctx); + updated_drawbuffers(ctx, fb); ctx->Color.DrawBuffer[buf] = fb->ColorDrawBuffer[buf]; } } @@ -585,7 +669,7 @@ _mesa_update_draw_buffers(struct gl_context *ctx) /* should be a window system FBO */ assert(_mesa_is_winsys_fbo(ctx->DrawBuffer)); - _mesa_drawbuffers(ctx, ctx->Const.MaxDrawBuffers, + _mesa_drawbuffers(ctx, ctx->DrawBuffer, ctx->Const.MaxDrawBuffers, ctx->Color.DrawBuffer, NULL); } @@ -598,11 +682,10 @@ _mesa_update_draw_buffers(struct gl_context *ctx) * \param bufferIndex the numerical index corresponding to 'buffer' */ void -_mesa_readbuffer(struct gl_context *ctx, GLenum buffer, GLint bufferIndex) +_mesa_readbuffer(struct gl_context *ctx, struct gl_framebuffer *fb, + GLenum buffer, GLint bufferIndex) { - struct gl_framebuffer *fb = ctx->ReadBuffer; - - if (_mesa_is_winsys_fbo(fb)) { + if ((fb == ctx->ReadBuffer) && _mesa_is_winsys_fbo(fb)) { /* Only update the per-context READ_BUFFER state if we're bound to * a window-system framebuffer. */ @@ -621,23 +704,17 @@ _mesa_readbuffer(struct gl_context *ctx, GLenum buffer, GLint bufferIndex) * Called by glReadBuffer to set the source renderbuffer for reading pixels. * \param mode color buffer such as GL_FRONT, GL_BACK, etc. */ -void GLAPIENTRY -_mesa_ReadBuffer(GLenum buffer) +void +_mesa_read_buffer(struct gl_context *ctx, struct gl_framebuffer *fb, + GLenum buffer, const char *caller) { - struct gl_framebuffer *fb; GLbitfield supportedMask; GLint srcBuffer; - GET_CURRENT_CONTEXT(ctx); FLUSH_VERTICES(ctx, 0); if (MESA_VERBOSE & VERBOSE_API) - _mesa_debug(ctx, "glReadBuffer %s\n", _mesa_lookup_enum_by_nr(buffer)); - - fb = ctx->ReadBuffer; - - if (MESA_VERBOSE & VERBOSE_API) - _mesa_debug(ctx, "glReadBuffer %s\n", _mesa_lookup_enum_by_nr(buffer)); + _mesa_debug(ctx, "%s %s\n", caller, _mesa_lookup_enum_by_nr(buffer)); if (buffer == GL_NONE) { /* This is legal--it means that no buffer should be bound for reading. */ @@ -648,24 +725,60 @@ _mesa_ReadBuffer(GLenum buffer) srcBuffer = read_buffer_enum_to_index(buffer); if (srcBuffer == -1) { _mesa_error(ctx, GL_INVALID_ENUM, - "glReadBuffer(buffer=0x%x)", buffer); + "%s(invalid buffer %s)", caller, + _mesa_lookup_enum_by_nr(buffer)); return; } supportedMask = supported_buffer_bitmask(ctx, fb); if (((1 << srcBuffer) & supportedMask) == 0) { _mesa_error(ctx, GL_INVALID_OPERATION, - "glReadBuffer(buffer=0x%x)", buffer); + "%s(invalid buffer %s)", caller, + _mesa_lookup_enum_by_nr(buffer)); return; } } /* OK, all error checking has been completed now */ - _mesa_readbuffer(ctx, buffer, srcBuffer); + _mesa_readbuffer(ctx, fb, buffer, srcBuffer); - /* - * Call device driver function. - */ - if (ctx->Driver.ReadBuffer) - (*ctx->Driver.ReadBuffer)(ctx, buffer); + /* Call the device driver function only if fb is the bound read buffer */ + if (fb == ctx->ReadBuffer) { + if (ctx->Driver.ReadBuffer) + (*ctx->Driver.ReadBuffer)(ctx, buffer); + } +} + + +void GLAPIENTRY +_mesa_ReadBuffer(GLenum buffer) +{ + GET_CURRENT_CONTEXT(ctx); + _mesa_read_buffer(ctx, ctx->ReadBuffer, buffer, "glReadBuffer"); +} + + +void GLAPIENTRY +_mesa_NamedFramebufferReadBuffer(GLuint framebuffer, GLenum src) +{ + GET_CURRENT_CONTEXT(ctx); + struct gl_framebuffer *fb; + + if (!ctx->Extensions.ARB_direct_state_access) { + _mesa_error(ctx, GL_INVALID_OPERATION, + "glNamedFramebufferReadBuffer(GL_ARB_direct_state_access " + "is not supported)"); + return; + } + + if (framebuffer) { + fb = _mesa_lookup_framebuffer_err(ctx, framebuffer, + "glNamedFramebufferReadBuffer"); + if (!fb) + return; + } + else + fb = ctx->WinSysReadBuffer; + + _mesa_read_buffer(ctx, fb, src, "glNamedFramebufferReadBuffer"); } diff --git a/mesalib/src/mesa/main/buffers.h b/mesalib/src/mesa/main/buffers.h index ebcfa1c1e..5aa79fda5 100644 --- a/mesalib/src/mesa/main/buffers.h +++ b/mesalib/src/mesa/main/buffers.h @@ -36,26 +36,51 @@ #include "glheader.h" struct gl_context; +struct gl_framebuffer; + +extern void +_mesa_draw_buffer(struct gl_context *ctx, struct gl_framebuffer *fb, + GLenum buffer, const char *caller); extern void GLAPIENTRY _mesa_DrawBuffer( GLenum mode ); extern void GLAPIENTRY +_mesa_NamedFramebufferDrawBuffer(GLuint framebuffer, GLenum buf); + +extern void +_mesa_draw_buffers(struct gl_context *ctx, struct gl_framebuffer *fb, + GLsizei n, const GLenum *buffers, const char *caller); + +extern void GLAPIENTRY _mesa_DrawBuffers(GLsizei n, const GLenum *buffers); +extern void GLAPIENTRY +_mesa_NamedFramebufferDrawBuffers(GLuint framebuffer, GLsizei n, + const GLenum *bufs); + extern void -_mesa_drawbuffers(struct gl_context *ctx, GLuint n, const GLenum *buffers, +_mesa_drawbuffers(struct gl_context *ctx, struct gl_framebuffer *fb, + GLuint n, const GLenum *buffers, const GLbitfield *destMask); extern void -_mesa_readbuffer(struct gl_context *ctx, GLenum buffer, GLint bufferIndex); +_mesa_readbuffer(struct gl_context *ctx, struct gl_framebuffer *fb, + GLenum buffer, GLint bufferIndex); extern void _mesa_update_draw_buffers(struct gl_context *ctx); +extern void +_mesa_read_buffer(struct gl_context *ctx, struct gl_framebuffer *fb, + GLenum buffer, const char *caller); + extern void GLAPIENTRY _mesa_ReadBuffer( GLenum mode ); +extern void GLAPIENTRY +_mesa_NamedFramebufferReadBuffer(GLuint framebuffer, GLenum src); + #endif diff --git a/mesalib/src/mesa/main/clear.c b/mesalib/src/mesa/main/clear.c index 8d707bc34..c6999f7fd 100644 --- a/mesalib/src/mesa/main/clear.c +++ b/mesalib/src/mesa/main/clear.c @@ -34,6 +34,8 @@ #include "clear.h" #include "context.h" #include "enums.h" +#include "fbobject.h" +#include "get.h" #include "macros.h" #include "mtypes.h" #include "state.h" @@ -400,6 +402,32 @@ _mesa_ClearBufferiv(GLenum buffer, GLint drawbuffer, const GLint *value) /** + * The ClearBuffer framework is so complicated and so riddled with the + * assumption that the framebuffer is bound that, for now, we will just fake + * direct state access clearing for the user. + */ +void GLAPIENTRY +_mesa_ClearNamedFramebufferiv(GLuint framebuffer, GLenum buffer, + GLint drawbuffer, const GLint *value) +{ + GLint oldfb; + + GET_CURRENT_CONTEXT(ctx); + if (!ctx->Extensions.ARB_direct_state_access) { + _mesa_error(ctx, GL_INVALID_OPERATION, + "glClearNamedFramebufferiv(GL_ARB_direct_state_access " + "is not supported)"); + return; + } + + _mesa_GetIntegerv(GL_DRAW_FRAMEBUFFER_BINDING, &oldfb); + _mesa_BindFramebuffer(GL_DRAW_FRAMEBUFFER, framebuffer); + _mesa_ClearBufferiv(buffer, drawbuffer, value); + _mesa_BindFramebuffer(GL_DRAW_FRAMEBUFFER, (GLuint) oldfb); +} + + +/** * New in GL 3.0 * Clear unsigned integer color buffer (not depth, not stencil). */ @@ -472,6 +500,32 @@ _mesa_ClearBufferuiv(GLenum buffer, GLint drawbuffer, const GLuint *value) /** + * The ClearBuffer framework is so complicated and so riddled with the + * assumption that the framebuffer is bound that, for now, we will just fake + * direct state access clearing for the user. + */ +void GLAPIENTRY +_mesa_ClearNamedFramebufferuiv(GLuint framebuffer, GLenum buffer, + GLint drawbuffer, const GLuint *value) +{ + GLint oldfb; + + GET_CURRENT_CONTEXT(ctx); + if (!ctx->Extensions.ARB_direct_state_access) { + _mesa_error(ctx, GL_INVALID_OPERATION, + "glClearNamedFramebufferuiv(GL_ARB_direct_state_access " + "is not supported)"); + return; + } + + _mesa_GetIntegerv(GL_DRAW_FRAMEBUFFER_BINDING, &oldfb); + _mesa_BindFramebuffer(GL_DRAW_FRAMEBUFFER, framebuffer); + _mesa_ClearBufferuiv(buffer, drawbuffer, value); + _mesa_BindFramebuffer(GL_DRAW_FRAMEBUFFER, (GLuint) oldfb); +} + + +/** * New in GL 3.0 * Clear fixed-pt or float color buffer or depth buffer (not stencil). */ @@ -565,6 +619,32 @@ _mesa_ClearBufferfv(GLenum buffer, GLint drawbuffer, const GLfloat *value) /** + * The ClearBuffer framework is so complicated and so riddled with the + * assumption that the framebuffer is bound that, for now, we will just fake + * direct state access clearing for the user. + */ +void GLAPIENTRY +_mesa_ClearNamedFramebufferfv(GLuint framebuffer, GLenum buffer, + GLint drawbuffer, const GLfloat *value) +{ + GLint oldfb; + + GET_CURRENT_CONTEXT(ctx); + if (!ctx->Extensions.ARB_direct_state_access) { + _mesa_error(ctx, GL_INVALID_OPERATION, + "glClearNamedFramebufferfv(GL_ARB_direct_state_access " + "is not supported)"); + return; + } + + _mesa_GetIntegerv(GL_DRAW_FRAMEBUFFER_BINDING, &oldfb); + _mesa_BindFramebuffer(GL_DRAW_FRAMEBUFFER, framebuffer); + _mesa_ClearBufferfv(buffer, drawbuffer, value); + _mesa_BindFramebuffer(GL_DRAW_FRAMEBUFFER, (GLuint) oldfb); +} + + +/** * New in GL 3.0 * Clear depth/stencil buffer only. */ @@ -626,3 +706,29 @@ _mesa_ClearBufferfi(GLenum buffer, GLint drawbuffer, ctx->Stencil.Clear = clearStencilSave; } } + + +/** + * The ClearBuffer framework is so complicated and so riddled with the + * assumption that the framebuffer is bound that, for now, we will just fake + * direct state access clearing for the user. + */ +void GLAPIENTRY +_mesa_ClearNamedFramebufferfi(GLuint framebuffer, GLenum buffer, + GLfloat depth, GLint stencil) +{ + GLint oldfb; + + GET_CURRENT_CONTEXT(ctx); + if (!ctx->Extensions.ARB_direct_state_access) { + _mesa_error(ctx, GL_INVALID_OPERATION, + "glClearNamedFramebufferfi(GL_ARB_direct_state_access " + "is not supported)"); + return; + } + + _mesa_GetIntegerv(GL_DRAW_FRAMEBUFFER_BINDING, &oldfb); + _mesa_BindFramebuffer(GL_DRAW_FRAMEBUFFER, framebuffer); + _mesa_ClearBufferfi(buffer, 0, depth, stencil); + _mesa_BindFramebuffer(GL_DRAW_FRAMEBUFFER, (GLuint) oldfb); +} diff --git a/mesalib/src/mesa/main/clear.h b/mesalib/src/mesa/main/clear.h index 96ce47b92..c29850676 100644 --- a/mesalib/src/mesa/main/clear.h +++ b/mesalib/src/mesa/main/clear.h @@ -52,13 +52,29 @@ extern void GLAPIENTRY _mesa_ClearBufferiv(GLenum buffer, GLint drawbuffer, const GLint *value); extern void GLAPIENTRY +_mesa_ClearNamedFramebufferiv(GLuint framebuffer, GLenum buffer, + GLint drawbuffer, const GLint *value); + +extern void GLAPIENTRY _mesa_ClearBufferuiv(GLenum buffer, GLint drawbuffer, const GLuint *value); extern void GLAPIENTRY +_mesa_ClearNamedFramebufferuiv(GLuint framebuffer, GLenum buffer, + GLint drawbuffer, const GLuint *value); + +extern void GLAPIENTRY _mesa_ClearBufferfv(GLenum buffer, GLint drawbuffer, const GLfloat *value); extern void GLAPIENTRY +_mesa_ClearNamedFramebufferfv(GLuint framebuffer, GLenum buffer, + GLint drawbuffer, const GLfloat *value); + +extern void GLAPIENTRY _mesa_ClearBufferfi(GLenum buffer, GLint drawbuffer, GLfloat depth, GLint stencil); +extern void GLAPIENTRY +_mesa_ClearNamedFramebufferfi(GLuint framebuffer, GLenum buffer, + GLfloat depth, GLint stencil); + #endif diff --git a/mesalib/src/mesa/main/compute.c b/mesalib/src/mesa/main/compute.c index 5756666b6..37a4ba70e 100644 --- a/mesalib/src/mesa/main/compute.c +++ b/mesalib/src/mesa/main/compute.c @@ -31,9 +31,27 @@ _mesa_DispatchCompute(GLuint num_groups_x, GLuint num_groups_z) { GET_CURRENT_CONTEXT(ctx); + int i; + struct gl_shader_program *prog; + const GLuint num_groups[3] = { num_groups_x, num_groups_y, num_groups_z }; if (ctx->Extensions.ARB_compute_shader) { - assert(!"TODO"); + for (i = 0; i < 3; i++) { + if (num_groups[i] > ctx->Const.MaxComputeWorkGroupCount[i]) { + _mesa_error(ctx, GL_INVALID_VALUE, + "glDispatchCompute(num_groups_%c)", 'x' + i); + return; + } + } + if (!_mesa_valid_to_render(ctx, "glDispatchCompute")) + return; + prog = ctx->Shader.CurrentProgram[MESA_SHADER_COMPUTE]; + if (prog == NULL || prog->_LinkedShaders[MESA_SHADER_COMPUTE] == NULL) { + _mesa_error(ctx, GL_INVALID_OPERATION, + "glDispatchCompute(no active compute shader)"); + return; + } + ctx->Driver.DispatchCompute(ctx, num_groups); } else { _mesa_error(ctx, GL_INVALID_OPERATION, "unsupported function (glDispatchCompute) called"); diff --git a/mesalib/src/mesa/main/context.c b/mesalib/src/mesa/main/context.c index 4aaf8b1af..544cc142f 100644 --- a/mesalib/src/mesa/main/context.c +++ b/mesalib/src/mesa/main/context.c @@ -118,6 +118,7 @@ #include "scissor.h" #include "shared.h" #include "shaderobj.h" +#include "shaderimage.h" #include "util/simple_list.h" #include "state.h" #include "stencil.h" @@ -821,6 +822,7 @@ init_attrib_groups(struct gl_context *ctx) _mesa_init_feedback( ctx ); _mesa_init_fog( ctx ); _mesa_init_hint( ctx ); + _mesa_init_image_units( ctx ); _mesa_init_line( ctx ); _mesa_init_lighting( ctx ); _mesa_init_matrix( ctx ); @@ -1563,7 +1565,8 @@ handle_first_current(struct gl_context *ctx) else buffer = GL_FRONT; - _mesa_drawbuffers(ctx, 1, &buffer, NULL /* destMask */); + _mesa_drawbuffers(ctx, ctx->DrawBuffer, 1, &buffer, + NULL /* destMask */); } if (ctx->ReadBuffer != _mesa_get_incomplete_framebuffer()) { @@ -1576,7 +1579,7 @@ handle_first_current(struct gl_context *ctx) bufferIndex = BUFFER_FRONT_LEFT; } - _mesa_readbuffer(ctx, buffer, bufferIndex); + _mesa_readbuffer(ctx, ctx->ReadBuffer, buffer, bufferIndex); } } diff --git a/mesalib/src/mesa/main/context.h b/mesalib/src/mesa/main/context.h index 1cd89a84a..6f3c94101 100644 --- a/mesalib/src/mesa/main/context.h +++ b/mesalib/src/mesa/main/context.h @@ -285,7 +285,7 @@ do { \ /** * Checks if the context is for Desktop GL (Compatibility or Core) */ -static inline GLboolean +static inline bool _mesa_is_desktop_gl(const struct gl_context *ctx) { return ctx->API == API_OPENGL_COMPAT || ctx->API == API_OPENGL_CORE; @@ -295,7 +295,7 @@ _mesa_is_desktop_gl(const struct gl_context *ctx) /** * Checks if the context is for any GLES version */ -static inline GLboolean +static inline bool _mesa_is_gles(const struct gl_context *ctx) { return ctx->API == API_OPENGLES || ctx->API == API_OPENGLES2; @@ -303,9 +303,9 @@ _mesa_is_gles(const struct gl_context *ctx) /** - * Checks if the context is for GLES 3.x + * Checks if the context is for GLES 3.0 or later */ -static inline GLboolean +static inline bool _mesa_is_gles3(const struct gl_context *ctx) { return ctx->API == API_OPENGLES2 && ctx->Version >= 30; @@ -313,9 +313,19 @@ _mesa_is_gles3(const struct gl_context *ctx) /** + * Checks if the context is for GLES 3.1 or later + */ +static inline bool +_mesa_is_gles31(const struct gl_context *ctx) +{ + return ctx->API == API_OPENGLES2 && ctx->Version >= 31; +} + + +/** * Checks if the context supports geometry shaders. */ -static inline GLboolean +static inline bool _mesa_has_geometry_shaders(const struct gl_context *ctx) { return _mesa_is_desktop_gl(ctx) && diff --git a/mesalib/src/mesa/main/dd.h b/mesalib/src/mesa/main/dd.h index 0c1a13fa4..d783e3422 100644 --- a/mesalib/src/mesa/main/dd.h +++ b/mesalib/src/mesa/main/dd.h @@ -1005,6 +1005,13 @@ struct dd_function_table { void (*MemoryBarrier)(struct gl_context *ctx, GLbitfield barriers); /** @} */ + + /** + * \name GL_ARB_compute_shader interface + */ + /*@{*/ + void (*DispatchCompute)(struct gl_context *ctx, const GLuint *num_groups); + /*@}*/ }; @@ -1167,6 +1174,19 @@ typedef struct { void (GLAPIENTRYP VertexAttribP4uiv)( GLuint index, GLenum type, GLboolean normalized, const GLuint *value); + + /* GL_ARB_vertex_attrib_64bit / GL 4.1 */ + void (GLAPIENTRYP VertexAttribL1d)( GLuint index, GLdouble x); + void (GLAPIENTRYP VertexAttribL2d)( GLuint index, GLdouble x, GLdouble y); + void (GLAPIENTRYP VertexAttribL3d)( GLuint index, GLdouble x, GLdouble y, GLdouble z); + void (GLAPIENTRYP VertexAttribL4d)( GLuint index, GLdouble x, GLdouble y, GLdouble z, GLdouble w); + + + void (GLAPIENTRYP VertexAttribL1dv)( GLuint index, const GLdouble *v); + void (GLAPIENTRYP VertexAttribL2dv)( GLuint index, const GLdouble *v); + void (GLAPIENTRYP VertexAttribL3dv)( GLuint index, const GLdouble *v); + void (GLAPIENTRYP VertexAttribL4dv)( GLuint index, const GLdouble *v); + } GLvertexformat; diff --git a/mesalib/src/mesa/main/extensions.c b/mesalib/src/mesa/main/extensions.c index 9be8993b0..c82416aa0 100644 --- a/mesalib/src/mesa/main/extensions.c +++ b/mesalib/src/mesa/main/extensions.c @@ -104,7 +104,7 @@ static const struct extension extension_table[] = { { "GL_ARB_depth_clamp", o(ARB_depth_clamp), GL, 2003 }, { "GL_ARB_depth_texture", o(ARB_depth_texture), GLL, 2001 }, { "GL_ARB_derivative_control", o(ARB_derivative_control), GL, 2014 }, - { "GL_ARB_direct_state_access", o(dummy_false), GL, 2014 }, + { "GL_ARB_direct_state_access", o(ARB_direct_state_access), GL, 2014 }, { "GL_ARB_draw_buffers", o(dummy_true), GL, 2002 }, { "GL_ARB_draw_buffers_blend", o(ARB_draw_buffers_blend), GL, 2009 }, { "GL_ARB_draw_elements_base_vertex", o(ARB_draw_elements_base_vertex), GL, 2009 }, @@ -203,6 +203,7 @@ static const struct extension extension_table[] = { { "GL_ARB_vertex_buffer_object", o(dummy_true), GLL, 2003 }, { "GL_ARB_vertex_program", o(ARB_vertex_program), GLL, 2002 }, { "GL_ARB_vertex_shader", o(ARB_vertex_shader), GL, 2002 }, + { "GL_ARB_vertex_attrib_64bit", o(ARB_vertex_attrib_64bit), GLC, 2010 }, { "GL_ARB_vertex_type_10f_11f_11f_rev", o(ARB_vertex_type_10f_11f_11f_rev), GL, 2013 }, { "GL_ARB_vertex_type_2_10_10_10_rev", o(ARB_vertex_type_2_10_10_10_rev), GL, 2009 }, { "GL_ARB_viewport_array", o(ARB_viewport_array), GLC, 2010 }, diff --git a/mesalib/src/mesa/main/fbobject.c b/mesalib/src/mesa/main/fbobject.c index 27cf97f17..8db651ca2 100644 --- a/mesalib/src/mesa/main/fbobject.c +++ b/mesalib/src/mesa/main/fbobject.c @@ -121,6 +121,27 @@ _mesa_lookup_renderbuffer(struct gl_context *ctx, GLuint id) /** + * A convenience function for direct state access that throws + * GL_INVALID_OPERATION if the renderbuffer doesn't exist. + */ +struct gl_renderbuffer * +_mesa_lookup_renderbuffer_err(struct gl_context *ctx, GLuint id, + const char *func) +{ + struct gl_renderbuffer *rb; + + rb = _mesa_lookup_renderbuffer(ctx, id); + if (!rb || rb == &DummyRenderbuffer) { + _mesa_error(ctx, GL_INVALID_OPERATION, + "%s(non-existent renderbuffer %u)", func, id); + return NULL; + } + + return rb; +} + + +/** * Helper routine for getting a gl_framebuffer. */ struct gl_framebuffer * @@ -138,6 +159,27 @@ _mesa_lookup_framebuffer(struct gl_context *ctx, GLuint id) /** + * A convenience function for direct state access that throws + * GL_INVALID_OPERATION if the framebuffer doesn't exist. + */ +struct gl_framebuffer * +_mesa_lookup_framebuffer_err(struct gl_context *ctx, GLuint id, + const char *func) +{ + struct gl_framebuffer *fb; + + fb = _mesa_lookup_framebuffer(ctx, id); + if (!fb || fb == &DummyFramebuffer) { + _mesa_error(ctx, GL_INVALID_OPERATION, + "%s(non-existent framebuffer %u)", func, id); + return NULL; + } + + return fb; +} + + +/** * Mark the given framebuffer as invalid. This will force the * test for framebuffer completeness to be done before the framebuffer * is used. @@ -423,7 +465,7 @@ set_texture_attachment(struct gl_context *ctx, struct gl_framebuffer *fb, struct gl_renderbuffer_attachment *att, struct gl_texture_object *texObj, - GLenum texTarget, GLuint level, GLuint zoffset, + GLenum texTarget, GLuint level, GLuint layer, GLboolean layered) { struct gl_renderbuffer *rb = att->Renderbuffer; @@ -447,7 +489,7 @@ set_texture_attachment(struct gl_context *ctx, /* always update these fields */ att->TextureLevel = level; att->CubeMapFace = _mesa_tex_target_to_face(texTarget); - att->Zoffset = zoffset; + att->Zoffset = layer; att->Layered = layered; att->Complete = GL_FALSE; @@ -479,9 +521,10 @@ set_renderbuffer_attachment(struct gl_context *ctx, * Attach a renderbuffer object to a framebuffer object. */ void -_mesa_framebuffer_renderbuffer(struct gl_context *ctx, - struct gl_framebuffer *fb, - GLenum attachment, struct gl_renderbuffer *rb) +_mesa_FramebufferRenderbuffer_sw(struct gl_context *ctx, + struct gl_framebuffer *fb, + GLenum attachment, + struct gl_renderbuffer *rb) { struct gl_renderbuffer_attachment *att; @@ -1446,6 +1489,14 @@ void GLAPIENTRY _mesa_CreateRenderbuffers(GLsizei n, GLuint *renderbuffers) { GET_CURRENT_CONTEXT(ctx); + + if (!ctx->Extensions.ARB_direct_state_access) { + _mesa_error(ctx, GL_INVALID_OPERATION, + "glCreateRenderbuffers(GL_ARB_direct_state_access " + "is not supported)"); + return; + } + create_render_buffers(ctx, n, renderbuffers, true); } @@ -1886,6 +1937,12 @@ renderbuffer_storage_named(GLuint renderbuffer, GLenum internalFormat, { GET_CURRENT_CONTEXT(ctx); + if (!ctx->Extensions.ARB_direct_state_access) { + _mesa_error(ctx, GL_INVALID_OPERATION, + "%s(GL_ARB_direct_state_access is not supported)", func); + return; + } + if (MESA_VERBOSE & VERBOSE_API) { if (samples == NO_SAMPLES) _mesa_debug(ctx, "%s(%u, %s, %d, %d)\n", @@ -2140,6 +2197,13 @@ _mesa_GetNamedRenderbufferParameteriv(GLuint renderbuffer, GLenum pname, { GET_CURRENT_CONTEXT(ctx); + if (!ctx->Extensions.ARB_direct_state_access) { + _mesa_error(ctx, GL_INVALID_OPERATION, + "glGetNamedRenderbufferParameteriv(" + "GL_ARB_direct_state_access is not supported)"); + return; + } + struct gl_renderbuffer *rb = _mesa_lookup_renderbuffer(ctx, renderbuffer); if (!rb || rb == &DummyRenderbuffer) { /* ID was reserved, but no real renderbuffer object made yet */ @@ -2396,15 +2460,29 @@ _mesa_DeleteFramebuffers(GLsizei n, const GLuint *framebuffers) } -void GLAPIENTRY -_mesa_GenFramebuffers(GLsizei n, GLuint *framebuffers) +/** + * This is the implementation for glGenFramebuffers and glCreateFramebuffers. + * It is not exposed to the rest of Mesa to encourage the use of + * nameless buffers in driver internals. + */ +static void +create_framebuffers(GLsizei n, GLuint *framebuffers, bool dsa) { GET_CURRENT_CONTEXT(ctx); GLuint first; GLint i; + struct gl_framebuffer *fb; + + const char *func = dsa ? "glCreateFramebuffers" : "glGenFramebuffers"; + + if (dsa && !ctx->Extensions.ARB_direct_state_access) { + _mesa_error(ctx, GL_INVALID_OPERATION, + "%s(GL_ARB_direct_state_access is not supported)", func); + return; + } if (n < 0) { - _mesa_error(ctx, GL_INVALID_VALUE, "glGenFramebuffersEXT(n)"); + _mesa_error(ctx, GL_INVALID_VALUE, "%s(n < 0)", func); return; } @@ -2416,31 +2494,43 @@ _mesa_GenFramebuffers(GLsizei n, GLuint *framebuffers) for (i = 0; i < n; i++) { GLuint name = first + i; framebuffers[i] = name; - /* insert dummy placeholder into hash table */ + + if (dsa) { + fb = ctx->Driver.NewFramebuffer(ctx, framebuffers[i]); + if (!fb) { + _mesa_error(ctx, GL_OUT_OF_MEMORY, "%s", func); + return; + } + } + else + fb = &DummyFramebuffer; + mtx_lock(&ctx->Shared->Mutex); - _mesa_HashInsert(ctx->Shared->FrameBuffers, name, &DummyFramebuffer); + _mesa_HashInsert(ctx->Shared->FrameBuffers, name, fb); mtx_unlock(&ctx->Shared->Mutex); } } -GLenum GLAPIENTRY -_mesa_CheckFramebufferStatus(GLenum target) +void GLAPIENTRY +_mesa_GenFramebuffers(GLsizei n, GLuint *framebuffers) { - struct gl_framebuffer *buffer; - GET_CURRENT_CONTEXT(ctx); + create_framebuffers(n, framebuffers, false); +} - ASSERT_OUTSIDE_BEGIN_END_WITH_RETVAL(ctx, 0); - if (MESA_VERBOSE & VERBOSE_API) - _mesa_debug(ctx, "glCheckFramebufferStatus(%s)\n", - _mesa_lookup_enum_by_nr(target)); +void GLAPIENTRY +_mesa_CreateFramebuffers(GLsizei n, GLuint *framebuffers) +{ + create_framebuffers(n, framebuffers, true); +} - buffer = get_framebuffer_target(ctx, target); - if (!buffer) { - _mesa_error(ctx, GL_INVALID_ENUM, "glCheckFramebufferStatus(target)"); - return 0; - } + +GLenum +_mesa_check_framebuffer_status(struct gl_context *ctx, + struct gl_framebuffer *buffer) +{ + ASSERT_OUTSIDE_BEGIN_END_WITH_RETVAL(ctx, 0); if (_mesa_is_winsys_fbo(buffer)) { /* EGL_KHR_surfaceless_context allows the winsys FBO to be incomplete. */ @@ -2461,6 +2551,74 @@ _mesa_CheckFramebufferStatus(GLenum target) } +GLenum GLAPIENTRY +_mesa_CheckFramebufferStatus(GLenum target) +{ + struct gl_framebuffer *fb; + GET_CURRENT_CONTEXT(ctx); + + if (MESA_VERBOSE & VERBOSE_API) + _mesa_debug(ctx, "glCheckFramebufferStatus(%s)\n", + _mesa_lookup_enum_by_nr(target)); + + fb = get_framebuffer_target(ctx, target); + if (!fb) { + _mesa_error(ctx, GL_INVALID_ENUM, + "glCheckFramebufferStatus(invalid target %s)", + _mesa_lookup_enum_by_nr(target)); + return 0; + } + + return _mesa_check_framebuffer_status(ctx, fb); +} + + +GLenum GLAPIENTRY +_mesa_CheckNamedFramebufferStatus(GLuint framebuffer, GLenum target) +{ + struct gl_framebuffer *fb; + GET_CURRENT_CONTEXT(ctx); + + if (!ctx->Extensions.ARB_direct_state_access) { + _mesa_error(ctx, GL_INVALID_OPERATION, + "glCheckNamedFramebufferStatus(GL_ARB_direct_state_access " + "is not supported)"); + return 0; + } + + /* Validate the target (for conformance's sake) and grab a reference to the + * default framebuffer in case framebuffer = 0. + * Section 9.4 Framebuffer Completeness of the OpenGL 4.5 core spec + * (30.10.2014, PDF page 336) says: + * "If framebuffer is zero, then the status of the default read or + * draw framebuffer (as determined by target) is returned." + */ + switch (target) { + case GL_DRAW_FRAMEBUFFER: + case GL_FRAMEBUFFER: + fb = ctx->WinSysDrawBuffer; + break; + case GL_READ_FRAMEBUFFER: + fb = ctx->WinSysReadBuffer; + break; + default: + _mesa_error(ctx, GL_INVALID_ENUM, + "glCheckNamedFramebufferStatus(invalid target %s)", + _mesa_lookup_enum_by_nr(target)); + return 0; + } + + if (framebuffer) { + fb = _mesa_lookup_framebuffer_err(ctx, framebuffer, + "glCheckNamedFramebufferStatus"); + if (!fb) + return 0; + } + + return _mesa_check_framebuffer_status(ctx, fb); +} + + /** * Replicate the src attachment point. Used by framebuffer_texture() when * the same texture is attached at GL_DEPTH_ATTACHMENT and @@ -2487,144 +2645,301 @@ reuse_framebuffer_texture_attachment(struct gl_framebuffer *fb, /** - * Common code called by glFramebufferTexture1D/2D/3D() and - * glFramebufferTextureLayer(). + * Common code called by gl*FramebufferTexture*() to retrieve the correct + * texture object pointer. * - * \param textarget is the textarget that was passed to the - * glFramebufferTexture...() function, or 0 if the corresponding function - * doesn't have a textarget parameter. + * \param texObj where the pointer to the texture object is returned. Note + * that a successful call may return texObj = NULL. * - * \param layered is true if this function was called from - * glFramebufferTexture(), false otherwise. + * \return true if no errors, false if errors */ -static void -framebuffer_texture(struct gl_context *ctx, const char *caller, GLenum target, - GLenum attachment, GLenum textarget, GLuint texture, - GLint level, GLuint zoffset, GLboolean layered) +static bool +get_texture_for_framebuffer(struct gl_context *ctx, GLuint texture, + bool layered, const char *caller, + struct gl_texture_object **texObj) { - struct gl_renderbuffer_attachment *att; - struct gl_texture_object *texObj = NULL; - struct gl_framebuffer *fb; - GLenum maxLevelsTarget; + *texObj = NULL; /* This will get returned if texture = 0. */ - fb = get_framebuffer_target(ctx, target); - if (!fb) { - _mesa_error(ctx, GL_INVALID_ENUM, - "glFramebufferTexture%s(target=0x%x)", caller, target); - return; + if (!texture) + return true; + + *texObj = _mesa_lookup_texture(ctx, texture); + if (*texObj == NULL || (*texObj)->Target == 0) { + /* Can't render to a non-existent texture object. + * + * The OpenGL 4.5 core spec (02.02.2015) in Section 9.2 Binding and + * Managing Framebuffer Objects specifies a different error + * depending upon the calling function (PDF pages 325-328). + * *FramebufferTexture (where layered = GL_TRUE) throws invalid + * value, while the other commands throw invalid operation (where + * layered = GL_FALSE). + */ + const GLenum error = layered ? GL_INVALID_VALUE : + GL_INVALID_OPERATION; + _mesa_error(ctx, error, + "%s(non-existent texture %u)", caller, texture); + return false; } - /* check framebuffer binding */ - if (_mesa_is_winsys_fbo(fb)) { - _mesa_error(ctx, GL_INVALID_OPERATION, - "glFramebufferTexture%s", caller); - return; + return true; +} + + +/** + * Common code called by gl*FramebufferTexture() to verify the texture target + * and decide whether or not the attachment should truly be considered + * layered. + * + * \param layered true if attachment should be considered layered, false if + * not + * + * \return true if no errors, false if errors + */ +static bool +check_layered_texture_target(struct gl_context *ctx, GLenum target, + const char *caller, GLboolean *layered) +{ + *layered = GL_TRUE; + + switch (target) { + case GL_TEXTURE_3D: + case GL_TEXTURE_1D_ARRAY_EXT: + case GL_TEXTURE_2D_ARRAY_EXT: + case GL_TEXTURE_CUBE_MAP: + case GL_TEXTURE_CUBE_MAP_ARRAY: + case GL_TEXTURE_2D_MULTISAMPLE_ARRAY: + return true; + case GL_TEXTURE_1D: + case GL_TEXTURE_2D: + case GL_TEXTURE_RECTANGLE: + case GL_TEXTURE_2D_MULTISAMPLE: + /* These texture types are valid to pass to + * glFramebufferTexture(), but since they aren't layered, it + * is equivalent to calling glFramebufferTexture{1D,2D}(). + */ + *layered = GL_FALSE; + return true; } - /* The textarget, level, and zoffset parameters are only validated if - * texture is non-zero. + _mesa_error(ctx, GL_INVALID_OPERATION, + "%s(invalid texture target %s)", caller, + _mesa_lookup_enum_by_nr(target)); + return false; +} + + +/** + * Common code called by gl*FramebufferTextureLayer() to verify the texture + * target. + * + * \return true if no errors, false if errors + */ +static bool +check_texture_target(struct gl_context *ctx, GLenum target, + const char *caller) +{ + /* We're being called by glFramebufferTextureLayer(). + * The only legal texture types for that function are 3D, + * cube-map, and 1D/2D/cube-map array textures. */ - if (texture) { - GLboolean err = GL_TRUE; - - texObj = _mesa_lookup_texture(ctx, texture); - if (texObj != NULL) { - if (textarget == 0) { - if (layered) { - /* We're being called by glFramebufferTexture() and textarget - * is not used. - */ - switch (texObj->Target) { - case GL_TEXTURE_3D: - case GL_TEXTURE_1D_ARRAY_EXT: - case GL_TEXTURE_2D_ARRAY_EXT: - case GL_TEXTURE_CUBE_MAP: - case GL_TEXTURE_CUBE_MAP_ARRAY: - case GL_TEXTURE_2D_MULTISAMPLE_ARRAY: - err = false; - break; - case GL_TEXTURE_1D: - case GL_TEXTURE_2D: - case GL_TEXTURE_RECTANGLE: - case GL_TEXTURE_2D_MULTISAMPLE: - /* These texture types are valid to pass to - * glFramebufferTexture(), but since they aren't layered, it - * is equivalent to calling glFramebufferTexture{1D,2D}(). - */ - err = false; - layered = false; - textarget = texObj->Target; - break; - default: - err = true; - break; - } - } else { - /* We're being called by glFramebufferTextureLayer() and - * textarget is not used. The only legal texture types for - * that function are 3D and 1D/2D arrays textures. - */ - err = (texObj->Target != GL_TEXTURE_3D) && - (texObj->Target != GL_TEXTURE_1D_ARRAY_EXT) && - (texObj->Target != GL_TEXTURE_2D_ARRAY_EXT) && - (texObj->Target != GL_TEXTURE_CUBE_MAP_ARRAY) && - (texObj->Target != GL_TEXTURE_2D_MULTISAMPLE_ARRAY); - } - } - else { - /* Make sure textarget is consistent with the texture's type */ - err = (texObj->Target == GL_TEXTURE_CUBE_MAP) - ? !_mesa_is_cube_face(textarget) - : (texObj->Target != textarget); - } + switch (target) { + case GL_TEXTURE_3D: + case GL_TEXTURE_1D_ARRAY: + case GL_TEXTURE_2D_ARRAY: + case GL_TEXTURE_CUBE_MAP_ARRAY: + case GL_TEXTURE_2D_MULTISAMPLE_ARRAY: + return true; + case GL_TEXTURE_CUBE_MAP: + /* This target is valid in TextureLayer when ARB_direct_state_access + * or OpenGL 4.5 is supported. + */ + return ctx->Extensions.ARB_direct_state_access; + } + + _mesa_error(ctx, GL_INVALID_OPERATION, + "%s(invalid texture target %s)", caller, + _mesa_lookup_enum_by_nr(target)); + return false; +} + + +/** + * Common code called by glFramebufferTexture*D() to verify the texture + * target. + * + * \return true if no errors, false if errors + */ +static bool +check_textarget(struct gl_context *ctx, int dims, GLenum target, + GLenum textarget, const char *caller) +{ + bool err = false; + + switch (dims) { + case 1: + switch (textarget) { + case GL_TEXTURE_1D: + break; + case GL_TEXTURE_1D_ARRAY: + err = !ctx->Extensions.EXT_texture_array; + break; + default: + err = true; } - else { - /* can't render to a non-existant texture */ - _mesa_error(ctx, GL_INVALID_OPERATION, - "glFramebufferTexture%s(non existant texture)", - caller); - return; + break; + case 2: + switch (textarget) { + case GL_TEXTURE_2D: + break; + case GL_TEXTURE_RECTANGLE: + err = _mesa_is_gles(ctx) + || !ctx->Extensions.NV_texture_rectangle; + break; + case GL_TEXTURE_CUBE_MAP_POSITIVE_X: + case GL_TEXTURE_CUBE_MAP_NEGATIVE_X: + case GL_TEXTURE_CUBE_MAP_POSITIVE_Y: + case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y: + case GL_TEXTURE_CUBE_MAP_POSITIVE_Z: + case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z: + err = !ctx->Extensions.ARB_texture_cube_map; + break; + case GL_TEXTURE_2D_ARRAY: + err = (_mesa_is_gles(ctx) && ctx->Version < 30) + || !ctx->Extensions.EXT_texture_array; + break; + case GL_TEXTURE_2D_MULTISAMPLE: + case GL_TEXTURE_2D_MULTISAMPLE_ARRAY: + err = _mesa_is_gles(ctx) + || !ctx->Extensions.ARB_texture_multisample; + break; + default: + err = true; } + break; + case 3: + if (textarget != GL_TEXTURE_3D) + err = true; + break; + default: + err = true; + } - if (err) { - _mesa_error(ctx, GL_INVALID_OPERATION, - "glFramebufferTexture%s(texture target mismatch)", - caller); - return; - } + if (err) { + _mesa_error(ctx, GL_INVALID_OPERATION, + "%s(invalid textarget %s)", + caller, _mesa_lookup_enum_by_nr(textarget)); + return false; + } - if (texObj->Target == GL_TEXTURE_3D) { - const GLuint maxSize = 1 << (ctx->Const.Max3DTextureLevels - 1); - if (zoffset >= maxSize) { - _mesa_error(ctx, GL_INVALID_VALUE, - "glFramebufferTexture%s(zoffset)", caller); - return; - } + /* Make sure textarget is consistent with the texture's type */ + err = (target == GL_TEXTURE_CUBE_MAP) ? + !_mesa_is_cube_face(textarget): (target != textarget); + + if (err) { + _mesa_error(ctx, GL_INVALID_OPERATION, + "%s(mismatched texture target)", caller); + return false; + } + + return true; +} + + +/** + * Common code called by gl*FramebufferTextureLayer() and + * glFramebufferTexture3D() to validate the layer. + * + * \return true if no errors, false if errors + */ +static bool +check_layer(struct gl_context *ctx, GLenum target, GLint layer, + const char *caller) +{ + /* Page 306 (page 328 of the PDF) of the OpenGL 4.5 (Core Profile) + * spec says: + * + * "An INVALID_VALUE error is generated if texture is non-zero + * and layer is negative." + */ + if (layer < 0) { + _mesa_error(ctx, GL_INVALID_VALUE, + "%s(layer %u < 0)", caller, layer); + return false; + } + + if (target == GL_TEXTURE_3D) { + const GLuint maxSize = 1 << (ctx->Const.Max3DTextureLevels - 1); + if (layer >= maxSize) { + _mesa_error(ctx, GL_INVALID_VALUE, + "%s(invalid layer %u)", caller, layer); + return false; } - else if ((texObj->Target == GL_TEXTURE_1D_ARRAY_EXT) || - (texObj->Target == GL_TEXTURE_2D_ARRAY_EXT) || - (texObj->Target == GL_TEXTURE_CUBE_MAP_ARRAY) || - (texObj->Target == GL_TEXTURE_2D_MULTISAMPLE_ARRAY)) { - if (zoffset >= ctx->Const.MaxArrayTextureLayers) { - _mesa_error(ctx, GL_INVALID_VALUE, - "glFramebufferTexture%s(layer)", caller); - return; - } + } + else if ((target == GL_TEXTURE_1D_ARRAY) || + (target == GL_TEXTURE_2D_ARRAY) || + (target == GL_TEXTURE_CUBE_MAP_ARRAY) || + (target == GL_TEXTURE_2D_MULTISAMPLE_ARRAY)) { + if (layer >= ctx->Const.MaxArrayTextureLayers) { + _mesa_error(ctx, GL_INVALID_VALUE, + "%s(layer %u >= GL_MAX_ARRAY_TEXTURE_LAYERS)", + caller, layer); + return false; } - - maxLevelsTarget = textarget ? textarget : texObj->Target; - if ((level < 0) || - (level >= _mesa_max_texture_levels(ctx, maxLevelsTarget))) { + } + else if (target == GL_TEXTURE_CUBE_MAP) { + if (layer >= 6) { _mesa_error(ctx, GL_INVALID_VALUE, - "glFramebufferTexture%s(level)", caller); - return; + "%s(layer %u >= 6)", caller, layer); + return false; } } + return true; +} + + +/** + * Common code called by all gl*FramebufferTexture*() entry points to verify + * the level. + * + * \return true if no errors, false if errors + */ +static bool +check_level(struct gl_context *ctx, GLenum target, GLint level, + const char *caller) +{ + if ((level < 0) || + (level >= _mesa_max_texture_levels(ctx, target))) { + _mesa_error(ctx, GL_INVALID_VALUE, + "%s(invalid level %d)", caller, level); + return false; + } + + return true; +} + + +void +_mesa_framebuffer_texture(struct gl_context *ctx, struct gl_framebuffer *fb, + GLenum attachment, + struct gl_texture_object *texObj, GLenum textarget, + GLint level, GLuint layer, GLboolean layered, + const char *caller) +{ + struct gl_renderbuffer_attachment *att; + + /* The window-system framebuffer object is immutable */ + if (_mesa_is_winsys_fbo(fb)) { + _mesa_error(ctx, GL_INVALID_OPERATION, "%s(window-system framebuffer)", + caller); + return; + } + + /* Not a hash lookup, so we can afford to get the attachment here. */ att = get_attachment(ctx, fb, attachment); if (att == NULL) { - _mesa_error(ctx, GL_INVALID_ENUM, - "glFramebufferTexture%s(attachment)", caller); + _mesa_error(ctx, GL_INVALID_ENUM, "%s(invalid attachment %s)", caller, + _mesa_lookup_enum_by_nr(attachment)); return; } @@ -2637,7 +2952,7 @@ framebuffer_texture(struct gl_context *ctx, const char *caller, GLenum target, level == fb->Attachment[BUFFER_STENCIL].TextureLevel && _mesa_tex_target_to_face(textarget) == fb->Attachment[BUFFER_STENCIL].CubeMapFace && - zoffset == fb->Attachment[BUFFER_STENCIL].Zoffset) { + layer == fb->Attachment[BUFFER_STENCIL].Zoffset) { /* The texture object is already attached to the stencil attachment * point. Don't create a new renderbuffer; just reuse the stencil * attachment's. This is required to prevent a GL error in @@ -2650,13 +2965,14 @@ framebuffer_texture(struct gl_context *ctx, const char *caller, GLenum target, level == fb->Attachment[BUFFER_DEPTH].TextureLevel && _mesa_tex_target_to_face(textarget) == fb->Attachment[BUFFER_DEPTH].CubeMapFace && - zoffset == fb->Attachment[BUFFER_DEPTH].Zoffset) { + layer == fb->Attachment[BUFFER_DEPTH].Zoffset) { /* As above, but with depth and stencil transposed. */ reuse_framebuffer_texture_attachment(fb, BUFFER_STENCIL, BUFFER_DEPTH); } else { set_texture_attachment(ctx, fb, att, texObj, textarget, - level, zoffset, layered); + level, layer, layered); + if (attachment == GL_DEPTH_STENCIL_ATTACHMENT) { /* Above we created a new renderbuffer and attached it to the * depth attachment point. Now attach it to the stencil attachment @@ -2692,36 +3008,50 @@ framebuffer_texture(struct gl_context *ctx, const char *caller, GLenum target, } -void GLAPIENTRY -_mesa_FramebufferTexture1D(GLenum target, GLenum attachment, - GLenum textarget, GLuint texture, GLint level) +static void +framebuffer_texture_with_dims(int dims, GLenum target, + GLenum attachment, GLenum textarget, + GLuint texture, GLint level, GLint layer, + const char *caller) { GET_CURRENT_CONTEXT(ctx); + struct gl_framebuffer *fb; + struct gl_texture_object *texObj; - if (texture != 0) { - GLboolean error; + /* Get the framebuffer object */ + fb = get_framebuffer_target(ctx, target); + if (!fb) { + _mesa_error(ctx, GL_INVALID_ENUM, "%s(invalid target %s)", caller, + _mesa_lookup_enum_by_nr(target)); + return; + } - switch (textarget) { - case GL_TEXTURE_1D: - error = GL_FALSE; - break; - case GL_TEXTURE_1D_ARRAY: - error = !ctx->Extensions.EXT_texture_array; - break; - default: - error = GL_TRUE; - } + /* Get the texture object */ + if (!get_texture_for_framebuffer(ctx, texture, false, caller, &texObj)) + return; - if (error) { - _mesa_error(ctx, GL_INVALID_OPERATION, - "glFramebufferTexture1D(textarget=%s)", - _mesa_lookup_enum_by_nr(textarget)); + if (texObj) { + if (!check_textarget(ctx, dims, texObj->Target, textarget, caller)) + return; + + if ((dims == 3) && !check_layer(ctx, texObj->Target, layer, caller)) return; - } } - framebuffer_texture(ctx, "1D", target, attachment, textarget, texture, - level, 0, GL_FALSE); + if (!check_level(ctx, textarget, level, caller)) + return; + + _mesa_framebuffer_texture(ctx, fb, attachment, texObj, textarget, level, + layer, GL_FALSE, caller); +} + + +void GLAPIENTRY +_mesa_FramebufferTexture1D(GLenum target, GLenum attachment, + GLenum textarget, GLuint texture, GLint level) +{ + framebuffer_texture_with_dims(1, target, attachment, textarget, texture, + level, 0, "glFramebufferTexture1D"); } @@ -2729,79 +3059,112 @@ void GLAPIENTRY _mesa_FramebufferTexture2D(GLenum target, GLenum attachment, GLenum textarget, GLuint texture, GLint level) { + framebuffer_texture_with_dims(2, target, attachment, textarget, texture, + level, 0, "glFramebufferTexture2D"); +} + + +void GLAPIENTRY +_mesa_FramebufferTexture3D(GLenum target, GLenum attachment, + GLenum textarget, GLuint texture, + GLint level, GLint layer) +{ + framebuffer_texture_with_dims(3, target, attachment, textarget, texture, + level, layer, "glFramebufferTexture3D"); +} + + +void GLAPIENTRY +_mesa_FramebufferTextureLayer(GLenum target, GLenum attachment, + GLuint texture, GLint level, GLint layer) +{ GET_CURRENT_CONTEXT(ctx); + struct gl_framebuffer *fb; + struct gl_texture_object *texObj; + GLenum textarget = 0; - if (texture != 0) { - GLboolean error; + const char *func = "glFramebufferTextureLayer"; - switch (textarget) { - case GL_TEXTURE_2D: - error = GL_FALSE; - break; - case GL_TEXTURE_RECTANGLE: - error = _mesa_is_gles(ctx) - || !ctx->Extensions.NV_texture_rectangle; - break; - case GL_TEXTURE_CUBE_MAP_POSITIVE_X: - case GL_TEXTURE_CUBE_MAP_NEGATIVE_X: - case GL_TEXTURE_CUBE_MAP_POSITIVE_Y: - case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y: - case GL_TEXTURE_CUBE_MAP_POSITIVE_Z: - case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z: - error = !ctx->Extensions.ARB_texture_cube_map; - break; - case GL_TEXTURE_2D_ARRAY: - error = (_mesa_is_gles(ctx) && ctx->Version < 30) - || !ctx->Extensions.EXT_texture_array; - break; - case GL_TEXTURE_2D_MULTISAMPLE: - case GL_TEXTURE_2D_MULTISAMPLE_ARRAY: - error = _mesa_is_gles(ctx) - || !ctx->Extensions.ARB_texture_multisample; - break; - default: - error = GL_TRUE; - } + /* Get the framebuffer object */ + fb = get_framebuffer_target(ctx, target); + if (!fb) { + _mesa_error(ctx, GL_INVALID_ENUM, + "glFramebufferTextureLayer(invalid target %s)", + _mesa_lookup_enum_by_nr(target)); + return; + } - if (error) { - _mesa_error(ctx, GL_INVALID_OPERATION, - "glFramebufferTexture2D(textarget=%s)", - _mesa_lookup_enum_by_nr(textarget)); + /* Get the texture object */ + if (!get_texture_for_framebuffer(ctx, texture, false, func, &texObj)) + return; + + if (texObj) { + if (!check_texture_target(ctx, texObj->Target, func)) + return; + + if (!check_layer(ctx, texObj->Target, layer, func)) return; + + if (!check_level(ctx, texObj->Target, level, func)) + return; + + if (texObj->Target == GL_TEXTURE_CUBE_MAP) { + assert(layer >= 0 && layer < 6); + textarget = GL_TEXTURE_CUBE_MAP_POSITIVE_X + layer; + layer = 0; } } - framebuffer_texture(ctx, "2D", target, attachment, textarget, texture, - level, 0, GL_FALSE); + _mesa_framebuffer_texture(ctx, fb, attachment, texObj, textarget, level, + layer, GL_FALSE, func); } void GLAPIENTRY -_mesa_FramebufferTexture3D(GLenum target, GLenum attachment, - GLenum textarget, GLuint texture, - GLint level, GLint zoffset) +_mesa_NamedFramebufferTextureLayer(GLuint framebuffer, GLenum attachment, + GLuint texture, GLint level, GLint layer) { GET_CURRENT_CONTEXT(ctx); + struct gl_framebuffer *fb; + struct gl_texture_object *texObj; + GLenum textarget = 0; + + const char *func = "glNamedFramebufferTextureLayer"; - if ((texture != 0) && (textarget != GL_TEXTURE_3D)) { + if (!ctx->Extensions.ARB_direct_state_access) { _mesa_error(ctx, GL_INVALID_OPERATION, - "glFramebufferTexture3D(textarget)"); + "%s(GL_ARB_direct_state_access is not supported)", func); return; } - framebuffer_texture(ctx, "3D", target, attachment, textarget, texture, - level, zoffset, GL_FALSE); -} + /* Get the framebuffer object */ + fb = _mesa_lookup_framebuffer_err(ctx, framebuffer, func); + if (!fb) + return; + /* Get the texture object */ + if (!get_texture_for_framebuffer(ctx, texture, false, func, &texObj)) + return; -void GLAPIENTRY -_mesa_FramebufferTextureLayer(GLenum target, GLenum attachment, - GLuint texture, GLint level, GLint layer) -{ - GET_CURRENT_CONTEXT(ctx); + if (texObj) { + if (!check_texture_target(ctx, texObj->Target, func)) + return; + + if (!check_layer(ctx, texObj->Target, layer, func)) + return; + + if (!check_level(ctx, texObj->Target, level, func)) + return; - framebuffer_texture(ctx, "Layer", target, attachment, 0, texture, - level, layer, GL_FALSE); + if (texObj->Target == GL_TEXTURE_CUBE_MAP) { + assert(layer >= 0 && layer < 6); + textarget = GL_TEXTURE_CUBE_MAP_POSITIVE_X + layer; + layer = 0; + } + } + + _mesa_framebuffer_texture(ctx, fb, attachment, texObj, textarget, level, + layer, GL_FALSE, func); } @@ -2810,82 +3173,121 @@ _mesa_FramebufferTexture(GLenum target, GLenum attachment, GLuint texture, GLint level) { GET_CURRENT_CONTEXT(ctx); + struct gl_framebuffer *fb; + struct gl_texture_object *texObj; + GLboolean layered; + + const char *func = "FramebufferTexture"; - if (_mesa_has_geometry_shaders(ctx)) { - framebuffer_texture(ctx, "", target, attachment, 0, texture, - level, 0, GL_TRUE); - } else { + if (!_mesa_has_geometry_shaders(ctx)) { _mesa_error(ctx, GL_INVALID_OPERATION, "unsupported function (glFramebufferTexture) called"); + return; + } + + /* Get the framebuffer object */ + fb = get_framebuffer_target(ctx, target); + if (!fb) { + _mesa_error(ctx, GL_INVALID_ENUM, + "glFramebufferTexture(invalid target %s)", + _mesa_lookup_enum_by_nr(target)); + return; } + + /* Get the texture object */ + if (!get_texture_for_framebuffer(ctx, texture, true, func, &texObj)) + return; + + if (texObj) { + if (!check_layered_texture_target(ctx, texObj->Target, func, &layered)) + return; + + if (!check_level(ctx, texObj->Target, level, func)) + return; + } + + _mesa_framebuffer_texture(ctx, fb, attachment, texObj, 0, level, + 0, layered, func); } void GLAPIENTRY -_mesa_FramebufferRenderbuffer(GLenum target, GLenum attachment, - GLenum renderbufferTarget, - GLuint renderbuffer) +_mesa_NamedFramebufferTexture(GLuint framebuffer, GLenum attachment, + GLuint texture, GLint level) { - struct gl_renderbuffer_attachment *att; - struct gl_framebuffer *fb; - struct gl_renderbuffer *rb; GET_CURRENT_CONTEXT(ctx); + struct gl_framebuffer *fb; + struct gl_texture_object *texObj; + GLboolean layered; - fb = get_framebuffer_target(ctx, target); - if (!fb) { - _mesa_error(ctx, GL_INVALID_ENUM, - "glFramebufferRenderbuffer(target)"); + const char *func = "glNamedFramebufferTexture"; + + if (!ctx->Extensions.ARB_direct_state_access) { + _mesa_error(ctx, GL_INVALID_OPERATION, + "%s(GL_ARB_direct_state_access is not supported)", func); return; } - if (renderbufferTarget != GL_RENDERBUFFER_EXT) { - _mesa_error(ctx, GL_INVALID_ENUM, - "glFramebufferRenderbuffer(renderbufferTarget)"); + if (!_mesa_has_geometry_shaders(ctx)) { + _mesa_error(ctx, GL_INVALID_OPERATION, + "unsupported function (glNamedFramebufferTexture) called"); return; } + /* Get the framebuffer object */ + fb = _mesa_lookup_framebuffer_err(ctx, framebuffer, func); + if (!fb) + return; + + /* Get the texture object */ + if (!get_texture_for_framebuffer(ctx, texture, true, func, &texObj)) + return; + + if (texObj) { + if (!check_layered_texture_target(ctx, texObj->Target, func, + &layered)) + return; + + if (!check_level(ctx, texObj->Target, level, func)) + return; + } + + _mesa_framebuffer_texture(ctx, fb, attachment, texObj, 0, level, + 0, layered, func); +} + + +void +_mesa_framebuffer_renderbuffer(struct gl_context *ctx, + struct gl_framebuffer *fb, + GLenum attachment, + struct gl_renderbuffer *rb, + const char *func) +{ + struct gl_renderbuffer_attachment *att; + if (_mesa_is_winsys_fbo(fb)) { /* Can't attach new renderbuffers to a window system framebuffer */ - _mesa_error(ctx, GL_INVALID_OPERATION, "glFramebufferRenderbuffer"); + _mesa_error(ctx, GL_INVALID_OPERATION, + "%s(window-system framebuffer)", func); return; } att = get_attachment(ctx, fb, attachment); if (att == NULL) { _mesa_error(ctx, GL_INVALID_ENUM, - "glFramebufferRenderbuffer(invalid attachment %s)", + "%s(invalid attachment %s)", func, _mesa_lookup_enum_by_nr(attachment)); return; } - if (renderbuffer) { - rb = _mesa_lookup_renderbuffer(ctx, renderbuffer); - if (!rb) { - _mesa_error(ctx, GL_INVALID_OPERATION, - "glFramebufferRenderbuffer(non-existant" - " renderbuffer %u)", renderbuffer); - return; - } - else if (rb == &DummyRenderbuffer) { - _mesa_error(ctx, GL_INVALID_OPERATION, - "glFramebufferRenderbuffer(renderbuffer %u)", - renderbuffer); - return; - } - } - else { - /* remove renderbuffer attachment */ - rb = NULL; - } - if (attachment == GL_DEPTH_STENCIL_ATTACHMENT && rb && rb->Format != MESA_FORMAT_NONE) { /* make sure the renderbuffer is a depth/stencil format */ const GLenum baseFormat = _mesa_get_format_base_format(rb->Format); if (baseFormat != GL_DEPTH_STENCIL) { _mesa_error(ctx, GL_INVALID_OPERATION, - "glFramebufferRenderbuffer(renderbuffer" - " is not DEPTH_STENCIL format)"); + "%s(renderbuffer is not DEPTH_STENCIL format)", func); return; } } @@ -2903,24 +3305,99 @@ _mesa_FramebufferRenderbuffer(GLenum target, GLenum attachment, void GLAPIENTRY -_mesa_GetFramebufferAttachmentParameteriv(GLenum target, GLenum attachment, - GLenum pname, GLint *params) +_mesa_FramebufferRenderbuffer(GLenum target, GLenum attachment, + GLenum renderbuffertarget, + GLuint renderbuffer) { - const struct gl_renderbuffer_attachment *att; - struct gl_framebuffer *buffer; - GLenum err; + struct gl_framebuffer *fb; + struct gl_renderbuffer *rb; GET_CURRENT_CONTEXT(ctx); - /* The error differs in GL and GLES. */ - err = _mesa_is_desktop_gl(ctx) ? GL_INVALID_OPERATION : GL_INVALID_ENUM; + fb = get_framebuffer_target(ctx, target); + if (!fb) { + _mesa_error(ctx, GL_INVALID_ENUM, + "glFramebufferRenderbuffer(invalid target %s)", + _mesa_lookup_enum_by_nr(target)); + return; + } - buffer = get_framebuffer_target(ctx, target); - if (!buffer) { + if (renderbuffertarget != GL_RENDERBUFFER) { _mesa_error(ctx, GL_INVALID_ENUM, - "glGetFramebufferAttachmentParameteriv(target)"); + "glFramebufferRenderbuffer(renderbuffertarget is not " + "GL_RENDERBUFFER)"); return; } + if (renderbuffer) { + rb = _mesa_lookup_renderbuffer_err(ctx, renderbuffer, + "glFramebufferRenderbuffer"); + if (!rb) + return; + } + else { + /* remove renderbuffer attachment */ + rb = NULL; + } + + _mesa_framebuffer_renderbuffer(ctx, fb, attachment, rb, + "glFramebufferRenderbuffer"); +} + + +void GLAPIENTRY +_mesa_NamedFramebufferRenderbuffer(GLuint framebuffer, GLenum attachment, + GLenum renderbuffertarget, + GLuint renderbuffer) +{ + struct gl_framebuffer *fb; + struct gl_renderbuffer *rb; + GET_CURRENT_CONTEXT(ctx); + + if (!ctx->Extensions.ARB_direct_state_access) { + _mesa_error(ctx, GL_INVALID_OPERATION, + "glNamedFramebufferRenderbuffer(GL_ARB_direct_state_access " + "is not supported)"); + return; + } + + fb = _mesa_lookup_framebuffer_err(ctx, framebuffer, + "glNamedFramebufferRenderbuffer"); + + if (renderbuffertarget != GL_RENDERBUFFER) { + _mesa_error(ctx, GL_INVALID_ENUM, + "glNamedFramebufferRenderbuffer(renderbuffertarget is not " + "GL_RENDERBUFFER)"); + return; + } + + if (renderbuffer) { + rb = _mesa_lookup_renderbuffer_err(ctx, renderbuffer, + "glNamedFramebufferRenderbuffer"); + if (!rb) + return; + } + else { + /* remove renderbuffer attachment */ + rb = NULL; + } + + _mesa_framebuffer_renderbuffer(ctx, fb, attachment, rb, + "glNamedFramebufferRenderbuffer"); +} + + +void +_mesa_get_framebuffer_attachment_parameter(struct gl_context *ctx, + struct gl_framebuffer *buffer, + GLenum attachment, GLenum pname, + GLint *params, const char *caller) +{ + const struct gl_renderbuffer_attachment *att; + GLenum err; + + /* The error differs in GL and GLES. */ + err = _mesa_is_desktop_gl(ctx) ? GL_INVALID_OPERATION : GL_INVALID_ENUM; + if (_mesa_is_winsys_fbo(buffer)) { /* Page 126 (page 136 of the PDF) of the OpenGL ES 2.0.25 spec * says: @@ -2936,14 +3413,15 @@ _mesa_GetFramebufferAttachmentParameteriv(GLenum target, GLenum attachment, !ctx->Extensions.ARB_framebuffer_object) && !_mesa_is_gles3(ctx)) { _mesa_error(ctx, GL_INVALID_OPERATION, - "glGetFramebufferAttachmentParameteriv(bound FBO = 0)"); + "%s(window-system framebuffer)", caller); return; } if (_mesa_is_gles3(ctx) && attachment != GL_BACK && attachment != GL_DEPTH && attachment != GL_STENCIL) { _mesa_error(ctx, GL_INVALID_ENUM, - "glGetFramebufferAttachmentParameteriv(attachment)"); + "%s(invalid attachment %s)", caller, + _mesa_lookup_enum_by_nr(attachment)); return; } /* the default / window-system FBO */ @@ -2955,8 +3433,8 @@ _mesa_GetFramebufferAttachmentParameteriv(GLenum target, GLenum attachment, } if (att == NULL) { - _mesa_error(ctx, GL_INVALID_ENUM, - "glGetFramebufferAttachmentParameteriv(attachment)"); + _mesa_error(ctx, GL_INVALID_ENUM, "%s(invalid attachment %s)", caller, + _mesa_lookup_enum_by_nr(attachment)); return; } @@ -2970,9 +3448,8 @@ _mesa_GetFramebufferAttachmentParameteriv(GLenum target, GLenum attachment, * attachment, since it does not have a single format." */ _mesa_error(ctx, GL_INVALID_OPERATION, - "glGetFramebufferAttachmentParameteriv(" - "GL_FRAMEBUFFER_ATTACHMENT_COMPONENT_TYPE" - " is invalid for depth+stencil attachment)"); + "%s(GL_FRAMEBUFFER_ATTACHMENT_COMPONENT_TYPE" + " is invalid for depth+stencil attachment)", caller); return; } /* the depth and stencil attachments must point to the same buffer */ @@ -2980,8 +3457,7 @@ _mesa_GetFramebufferAttachmentParameteriv(GLenum target, GLenum attachment, stencilAtt = get_attachment(ctx, buffer, GL_STENCIL_ATTACHMENT); if (depthAtt->Renderbuffer != stencilAtt->Renderbuffer) { _mesa_error(ctx, GL_INVALID_OPERATION, - "glGetFramebufferAttachmentParameteriv(DEPTH/STENCIL" - " attachments differ)"); + "%s(DEPTH/STENCIL attachments differ)", caller); return; } } @@ -3014,8 +3490,8 @@ _mesa_GetFramebufferAttachmentParameteriv(GLenum target, GLenum attachment, *params = att->TextureLevel; } else if (att->Type == GL_NONE) { - _mesa_error(ctx, err, - "glGetFramebufferAttachmentParameteriv(pname)"); + _mesa_error(ctx, err, "%s(invalid pname %s)", caller, + _mesa_lookup_enum_by_nr(pname)); } else { goto invalid_pname_enum; @@ -3031,8 +3507,8 @@ _mesa_GetFramebufferAttachmentParameteriv(GLenum target, GLenum attachment, } } else if (att->Type == GL_NONE) { - _mesa_error(ctx, err, - "glGetFramebufferAttachmentParameteriv(pname)"); + _mesa_error(ctx, err, "%s(invalid pname %s)", caller, + _mesa_lookup_enum_by_nr(pname)); } else { goto invalid_pname_enum; @@ -3042,8 +3518,8 @@ _mesa_GetFramebufferAttachmentParameteriv(GLenum target, GLenum attachment, if (ctx->API == API_OPENGLES) { goto invalid_pname_enum; } else if (att->Type == GL_NONE) { - _mesa_error(ctx, err, - "glGetFramebufferAttachmentParameteriv(pname)"); + _mesa_error(ctx, err, "%s(invalid pname %s)", caller, + _mesa_lookup_enum_by_nr(pname)); } else if (att->Type == GL_TEXTURE) { if (att->Texture && (att->Texture->Target == GL_TEXTURE_3D || att->Texture->Target == GL_TEXTURE_2D_ARRAY)) { @@ -3064,8 +3540,8 @@ _mesa_GetFramebufferAttachmentParameteriv(GLenum target, GLenum attachment, goto invalid_pname_enum; } else if (att->Type == GL_NONE) { - _mesa_error(ctx, err, - "glGetFramebufferAttachmentParameteriv(pname)"); + _mesa_error(ctx, err, "%s(invalid pname %s)", caller, + _mesa_lookup_enum_by_nr(pname)); } else { if (ctx->Extensions.EXT_framebuffer_sRGB) { @@ -3087,8 +3563,8 @@ _mesa_GetFramebufferAttachmentParameteriv(GLenum target, GLenum attachment, goto invalid_pname_enum; } else if (att->Type == GL_NONE) { - _mesa_error(ctx, err, - "glGetFramebufferAttachmentParameteriv(pname)"); + _mesa_error(ctx, err, "%s(invalid pname %s)", caller, + _mesa_lookup_enum_by_nr(pname)); } else { mesa_format format = att->Renderbuffer->Format; @@ -3103,9 +3579,9 @@ _mesa_GetFramebufferAttachmentParameteriv(GLenum target, GLenum attachment, if (_mesa_is_gles3(ctx) && attachment == GL_DEPTH_STENCIL_ATTACHMENT) { _mesa_error(ctx, GL_INVALID_OPERATION, - "glGetFramebufferAttachmentParameteriv(cannot query " + "%s(cannot query " "GL_FRAMEBUFFER_ATTACHMENT_COMPONENT_TYPE of " - "GL_DEPTH_STENCIL_ATTACHMENT"); + "GL_DEPTH_STENCIL_ATTACHMENT)", caller); return; } @@ -3139,8 +3615,8 @@ _mesa_GetFramebufferAttachmentParameteriv(GLenum target, GLenum attachment, goto invalid_pname_enum; } else if (att->Type == GL_NONE) { - _mesa_error(ctx, err, - "glGetFramebufferAttachmentParameteriv(pname)"); + _mesa_error(ctx, err, "%s(invalid pname %s)", caller, + _mesa_lookup_enum_by_nr(pname)); } else if (att->Texture) { const struct gl_texture_image *texImage = @@ -3159,8 +3635,7 @@ _mesa_GetFramebufferAttachmentParameteriv(GLenum target, GLenum attachment, att->Renderbuffer->Format); } else { - _mesa_problem(ctx, "glGetFramebufferAttachmentParameterivEXT:" - " invalid FBO attachment structure"); + _mesa_problem(ctx, "%s: invalid FBO attachment structure", caller); } return; case GL_FRAMEBUFFER_ATTACHMENT_LAYERED: @@ -3169,8 +3644,8 @@ _mesa_GetFramebufferAttachmentParameteriv(GLenum target, GLenum attachment, } else if (att->Type == GL_TEXTURE) { *params = att->Layered; } else if (att->Type == GL_NONE) { - _mesa_error(ctx, err, - "glGetFramebufferAttachmentParameteriv(pname)"); + _mesa_error(ctx, err, "%s(invalid pname %s)", caller, + _mesa_lookup_enum_by_nr(pname)); } else { goto invalid_pname_enum; } @@ -3182,30 +3657,145 @@ _mesa_GetFramebufferAttachmentParameteriv(GLenum target, GLenum attachment, return; invalid_pname_enum: - _mesa_error(ctx, GL_INVALID_ENUM, - "glGetFramebufferAttachmentParameteriv(pname)"); + _mesa_error(ctx, GL_INVALID_ENUM, "%s(invalid pname %s)", caller, + _mesa_lookup_enum_by_nr(pname)); return; } +void GLAPIENTRY +_mesa_GetFramebufferAttachmentParameteriv(GLenum target, GLenum attachment, + GLenum pname, GLint *params) +{ + GET_CURRENT_CONTEXT(ctx); + struct gl_framebuffer *buffer; + + buffer = get_framebuffer_target(ctx, target); + if (!buffer) { + _mesa_error(ctx, GL_INVALID_ENUM, + "glGetFramebufferAttachmentParameteriv(invalid target %s)", + _mesa_lookup_enum_by_nr(target)); + return; + } + + _mesa_get_framebuffer_attachment_parameter(ctx, buffer, attachment, pname, + params, + "glGetFramebufferAttachmentParameteriv"); +} + + +void GLAPIENTRY +_mesa_GetNamedFramebufferAttachmentParameteriv(GLuint framebuffer, + GLenum attachment, + GLenum pname, GLint *params) +{ + GET_CURRENT_CONTEXT(ctx); + struct gl_framebuffer *buffer; + + if (!ctx->Extensions.ARB_direct_state_access) { + _mesa_error(ctx, GL_INVALID_OPERATION, + "glGetNamedFramebufferAttachmentParameteriv(" + "GL_ARB_direct_state_access is not supported)"); + return; + } + + if (framebuffer) { + buffer = _mesa_lookup_framebuffer_err(ctx, framebuffer, + "glGetNamedFramebufferAttachmentParameteriv"); + if (!buffer) + return; + } + else { + /* + * Section 9.2 Binding and Managing Framebuffer Objects of the OpenGL + * 4.5 core spec (30.10.2014, PDF page 314): + * "If framebuffer is zero, then the default draw framebuffer is + * queried." + */ + buffer = ctx->WinSysDrawBuffer; + } + + _mesa_get_framebuffer_attachment_parameter(ctx, buffer, attachment, pname, + params, + "glGetNamedFramebufferAttachmentParameteriv"); +} + + +void GLAPIENTRY +_mesa_NamedFramebufferParameteri(GLuint framebuffer, GLenum pname, + GLint param) +{ + GET_CURRENT_CONTEXT(ctx); + + (void) framebuffer; + (void) pname; + (void) param; + + if (!ctx->Extensions.ARB_direct_state_access) { + _mesa_error(ctx, GL_INVALID_OPERATION, + "glNamedFramebufferParameteri(" + "GL_ARB_direct_state_access is not supported)"); + return; + } + + _mesa_error(ctx, GL_INVALID_OPERATION, + "glNamedFramebufferParameteri not supported " + "(ARB_framebuffer_no_attachments not implemented)"); +} + + +void GLAPIENTRY +_mesa_GetNamedFramebufferParameteriv(GLuint framebuffer, GLenum pname, + GLint *param) +{ + GET_CURRENT_CONTEXT(ctx); + + (void) framebuffer; + (void) pname; + (void) param; + + if (!ctx->Extensions.ARB_direct_state_access) { + _mesa_error(ctx, GL_INVALID_OPERATION, + "glNamedFramebufferParameteriv(" + "GL_ARB_direct_state_access is not supported)"); + return; + } + + _mesa_error(ctx, GL_INVALID_OPERATION, + "glGetNamedFramebufferParameteriv not supported " + "(ARB_framebuffer_no_attachments not implemented)"); +} + + static void -invalidate_framebuffer_storage(GLenum target, GLsizei numAttachments, +invalidate_framebuffer_storage(struct gl_context *ctx, + struct gl_framebuffer *fb, + GLsizei numAttachments, const GLenum *attachments, GLint x, GLint y, GLsizei width, GLsizei height, const char *name) { int i; - struct gl_framebuffer *fb; - GET_CURRENT_CONTEXT(ctx); - fb = get_framebuffer_target(ctx, target); - if (!fb) { - _mesa_error(ctx, GL_INVALID_ENUM, "%s(target)", name); + /* Section 17.4 Whole Framebuffer Operations of the OpenGL 4.5 Core + * Spec (2.2.2015, PDF page 522) says: + * "An INVALID_VALUE error is generated if numAttachments, width, or + * height is negative." + */ + if (numAttachments < 0) { + _mesa_error(ctx, GL_INVALID_VALUE, + "%s(numAttachments < 0)", name); return; } - if (numAttachments < 0) { + if (width < 0) { _mesa_error(ctx, GL_INVALID_VALUE, - "%s(numAttachments < 0)", name); + "%s(width < 0)", name); + return; + } + + if (height < 0) { + _mesa_error(ctx, GL_INVALID_VALUE, + "%s(height < 0)", name); return; } @@ -3301,7 +3891,8 @@ invalidate_framebuffer_storage(GLenum target, GLsizei numAttachments, return; invalid_enum: - _mesa_error(ctx, GL_INVALID_ENUM, "%s(attachment)", name); + _mesa_error(ctx, GL_INVALID_ENUM, "%s(invalid attachment %s)", name, + _mesa_lookup_enum_by_nr(attachments[i])); return; } @@ -3311,16 +3902,74 @@ _mesa_InvalidateSubFramebuffer(GLenum target, GLsizei numAttachments, const GLenum *attachments, GLint x, GLint y, GLsizei width, GLsizei height) { - invalidate_framebuffer_storage(target, numAttachments, attachments, + struct gl_framebuffer *fb; + GET_CURRENT_CONTEXT(ctx); + + fb = get_framebuffer_target(ctx, target); + if (!fb) { + _mesa_error(ctx, GL_INVALID_ENUM, + "glInvalidateSubFramebuffer(invalid target %s)", + _mesa_lookup_enum_by_nr(target)); + return; + } + + invalidate_framebuffer_storage(ctx, fb, numAttachments, attachments, x, y, width, height, "glInvalidateSubFramebuffer"); } void GLAPIENTRY +_mesa_InvalidateNamedFramebufferSubData(GLuint framebuffer, + GLsizei numAttachments, + const GLenum *attachments, + GLint x, GLint y, + GLsizei width, GLsizei height) +{ + struct gl_framebuffer *fb; + GET_CURRENT_CONTEXT(ctx); + + if (!ctx->Extensions.ARB_direct_state_access) { + _mesa_error(ctx, GL_INVALID_OPERATION, + "glInvalidateNamedFramebufferSubData(" + "GL_ARB_direct_state_access is not supported)"); + return; + } + + /* The OpenGL 4.5 core spec (02.02.2015) says (in Section 17.4 Whole + * Framebuffer Operations, PDF page 522): "If framebuffer is zero, the + * default draw framebuffer is affected." + */ + if (framebuffer) { + fb = _mesa_lookup_framebuffer_err(ctx, framebuffer, + "glInvalidateNamedFramebufferSubData"); + if (!fb) + return; + } + else + fb = ctx->WinSysDrawBuffer; + + invalidate_framebuffer_storage(ctx, fb, numAttachments, attachments, + x, y, width, height, + "glInvalidateNamedFramebufferSubData"); +} + + +void GLAPIENTRY _mesa_InvalidateFramebuffer(GLenum target, GLsizei numAttachments, const GLenum *attachments) { + struct gl_framebuffer *fb; + GET_CURRENT_CONTEXT(ctx); + + fb = get_framebuffer_target(ctx, target); + if (!fb) { + _mesa_error(ctx, GL_INVALID_ENUM, + "glInvalidateFramebuffer(invalid target %s)", + _mesa_lookup_enum_by_nr(target)); + return; + } + /* The GL_ARB_invalidate_subdata spec says: * * "The command @@ -3333,7 +3982,7 @@ _mesa_InvalidateFramebuffer(GLenum target, GLsizei numAttachments, * <width>, <height> equal to 0, 0, <MAX_VIEWPORT_DIMS[0]>, * <MAX_VIEWPORT_DIMS[1]> respectively." */ - invalidate_framebuffer_storage(target, numAttachments, attachments, + invalidate_framebuffer_storage(ctx, fb, numAttachments, attachments, 0, 0, MAX_VIEWPORT_WIDTH, MAX_VIEWPORT_HEIGHT, "glInvalidateFramebuffer"); @@ -3341,6 +3990,53 @@ _mesa_InvalidateFramebuffer(GLenum target, GLsizei numAttachments, void GLAPIENTRY +_mesa_InvalidateNamedFramebufferData(GLuint framebuffer, + GLsizei numAttachments, + const GLenum *attachments) +{ + struct gl_framebuffer *fb; + GET_CURRENT_CONTEXT(ctx); + + if (!ctx->Extensions.ARB_direct_state_access) { + _mesa_error(ctx, GL_INVALID_OPERATION, + "glInvalidateNamedFramebufferData(" + "GL_ARB_direct_state_access is not supported)"); + return; + } + + /* The OpenGL 4.5 core spec (02.02.2015) says (in Section 17.4 Whole + * Framebuffer Operations, PDF page 522): "If framebuffer is zero, the + * default draw framebuffer is affected." + */ + if (framebuffer) { + fb = _mesa_lookup_framebuffer_err(ctx, framebuffer, + "glInvalidateNamedFramebufferData"); + if (!fb) + return; + } + else + fb = ctx->WinSysDrawBuffer; + + /* The GL_ARB_invalidate_subdata spec says: + * + * "The command + * + * void InvalidateFramebuffer(enum target, + * sizei numAttachments, + * const enum *attachments); + * + * is equivalent to the command InvalidateSubFramebuffer with <x>, <y>, + * <width>, <height> equal to 0, 0, <MAX_VIEWPORT_DIMS[0]>, + * <MAX_VIEWPORT_DIMS[1]> respectively." + */ + invalidate_framebuffer_storage(ctx, fb, numAttachments, attachments, + 0, 0, + MAX_VIEWPORT_WIDTH, MAX_VIEWPORT_HEIGHT, + "glInvalidateNamedFramebufferData"); +} + + +void GLAPIENTRY _mesa_DiscardFramebufferEXT(GLenum target, GLsizei numAttachments, const GLenum *attachments) { diff --git a/mesalib/src/mesa/main/fbobject.h b/mesalib/src/mesa/main/fbobject.h index 61aa1f503..9f570db3a 100644 --- a/mesalib/src/mesa/main/fbobject.h +++ b/mesalib/src/mesa/main/fbobject.h @@ -64,9 +64,17 @@ _mesa_get_incomplete_framebuffer(void); extern struct gl_renderbuffer * _mesa_lookup_renderbuffer(struct gl_context *ctx, GLuint id); +extern struct gl_renderbuffer * +_mesa_lookup_renderbuffer_err(struct gl_context *ctx, GLuint id, + const char *func); + extern struct gl_framebuffer * _mesa_lookup_framebuffer(struct gl_context *ctx, GLuint id); +extern struct gl_framebuffer * +_mesa_lookup_framebuffer_err(struct gl_context *ctx, GLuint id, + const char *func); + void _mesa_update_texture_renderbuffer(struct gl_context *ctx, @@ -74,9 +82,17 @@ _mesa_update_texture_renderbuffer(struct gl_context *ctx, struct gl_renderbuffer_attachment *att); extern void +_mesa_FramebufferRenderbuffer_sw(struct gl_context *ctx, + struct gl_framebuffer *fb, + GLenum attachment, + struct gl_renderbuffer *rb); + +extern void _mesa_framebuffer_renderbuffer(struct gl_context *ctx, struct gl_framebuffer *fb, - GLenum attachment, struct gl_renderbuffer *rb); + GLenum attachment, + struct gl_renderbuffer *rb, + const char *func); extern void _mesa_validate_framebuffer(struct gl_context *ctx, struct gl_framebuffer *fb); @@ -99,6 +115,24 @@ _mesa_detach_renderbuffer(struct gl_context *ctx, struct gl_framebuffer *fb, const void *att); +extern void +_mesa_framebuffer_texture(struct gl_context *ctx, struct gl_framebuffer *fb, + GLenum attachment, + struct gl_texture_object *texObj, GLenum textarget, + GLint level, GLuint layer, GLboolean layered, + const char *caller); + +extern GLenum +_mesa_check_framebuffer_status(struct gl_context *ctx, + struct gl_framebuffer *fb); + +extern void +_mesa_get_framebuffer_attachment_parameter(struct gl_context *ctx, + struct gl_framebuffer *buffer, + GLenum attachment, GLenum pname, + GLint *params, const char *caller); + + extern GLboolean GLAPIENTRY _mesa_IsRenderbuffer(GLuint renderbuffer); @@ -165,9 +199,15 @@ _mesa_DeleteFramebuffers(GLsizei n, const GLuint *framebuffers); extern void GLAPIENTRY _mesa_GenFramebuffers(GLsizei n, GLuint *framebuffers); +extern void GLAPIENTRY +_mesa_CreateFramebuffers(GLsizei n, GLuint *framebuffers); + extern GLenum GLAPIENTRY _mesa_CheckFramebufferStatus(GLenum target); +extern GLenum GLAPIENTRY +_mesa_CheckNamedFramebufferStatus(GLuint framebuffer, GLenum target); + extern void GLAPIENTRY _mesa_FramebufferTexture1D(GLenum target, GLenum attachment, GLenum textarget, GLuint texture, GLint level); @@ -179,24 +219,49 @@ _mesa_FramebufferTexture2D(GLenum target, GLenum attachment, extern void GLAPIENTRY _mesa_FramebufferTexture3D(GLenum target, GLenum attachment, GLenum textarget, GLuint texture, - GLint level, GLint zoffset); + GLint level, GLint layer); extern void GLAPIENTRY _mesa_FramebufferTextureLayer(GLenum target, GLenum attachment, GLuint texture, GLint level, GLint layer); extern void GLAPIENTRY +_mesa_NamedFramebufferTextureLayer(GLuint framebuffer, GLenum attachment, + GLuint texture, GLint level, GLint layer); + +extern void GLAPIENTRY _mesa_FramebufferTexture(GLenum target, GLenum attachment, GLuint texture, GLint level); extern void GLAPIENTRY +_mesa_NamedFramebufferTexture(GLuint framebuffer, GLenum attachment, + GLuint texture, GLint level); + +extern void GLAPIENTRY _mesa_FramebufferRenderbuffer(GLenum target, GLenum attachment, GLenum renderbuffertarget, GLuint renderbuffer); extern void GLAPIENTRY +_mesa_NamedFramebufferRenderbuffer(GLuint framebuffer, GLenum attachment, + GLenum renderbuffertarget, + GLuint renderbuffer); + +extern void GLAPIENTRY _mesa_GetFramebufferAttachmentParameteriv(GLenum target, GLenum attachment, GLenum pname, GLint *params); +extern void GLAPIENTRY +_mesa_GetNamedFramebufferAttachmentParameteriv(GLuint framebuffer, + GLenum attachment, + GLenum pname, GLint *params); + +extern void GLAPIENTRY +_mesa_NamedFramebufferParameteri(GLuint framebuffer, GLenum pname, + GLint param); + +extern void GLAPIENTRY +_mesa_GetNamedFramebufferParameteriv(GLuint framebuffer, GLenum pname, + GLint *param); extern void GLAPIENTRY _mesa_InvalidateSubFramebuffer(GLenum target, GLsizei numAttachments, @@ -204,10 +269,22 @@ _mesa_InvalidateSubFramebuffer(GLenum target, GLsizei numAttachments, GLsizei width, GLsizei height); extern void GLAPIENTRY +_mesa_InvalidateNamedFramebufferSubData(GLuint framebuffer, + GLsizei numAttachments, + const GLenum *attachments, + GLint x, GLint y, + GLsizei width, GLsizei height); + +extern void GLAPIENTRY _mesa_InvalidateFramebuffer(GLenum target, GLsizei numAttachments, const GLenum *attachments); extern void GLAPIENTRY +_mesa_InvalidateNamedFramebufferData(GLuint framebuffer, + GLsizei numAttachments, + const GLenum *attachments); + +extern void GLAPIENTRY _mesa_DiscardFramebufferEXT(GLenum target, GLsizei numAttachments, const GLenum *attachments); diff --git a/mesalib/src/mesa/main/ffvertex_prog.c b/mesalib/src/mesa/main/ffvertex_prog.c index 7fdd9bab6..70adaf885 100644 --- a/mesalib/src/mesa/main/ffvertex_prog.c +++ b/mesalib/src/mesa/main/ffvertex_prog.c @@ -135,7 +135,7 @@ static GLboolean check_active_shininess( struct gl_context *ctx, (key->light_color_material_mask & (1 << attr))) return GL_TRUE; - if (key->varying_vp_inputs & VERT_ATTRIB_GENERIC(attr)) + if (key->varying_vp_inputs & VERT_BIT_GENERIC(attr)) return GL_TRUE; if (ctx->Light.Material.Attrib[attr][0] != 0.0F) diff --git a/mesalib/src/mesa/main/framebuffer.c b/mesalib/src/mesa/main/framebuffer.c index 4f7736a64..665a5ba14 100644 --- a/mesalib/src/mesa/main/framebuffer.c +++ b/mesalib/src/mesa/main/framebuffer.c @@ -312,7 +312,7 @@ _mesa_resize_framebuffer(struct gl_context *ctx, struct gl_framebuffer *fb, if (ctx) { /* update scissor / window bounds */ - _mesa_update_draw_buffer_bounds(ctx); + _mesa_update_draw_buffer_bounds(ctx, ctx->DrawBuffer); /* Signal new buffer state so that swrast will update its clipping * info (the CLIP_BIT flag). */ @@ -413,9 +413,9 @@ _mesa_scissor_bounding_box(const struct gl_context *ctx, * \param ctx the GL context. */ void -_mesa_update_draw_buffer_bounds(struct gl_context *ctx) +_mesa_update_draw_buffer_bounds(struct gl_context *ctx, + struct gl_framebuffer *buffer) { - struct gl_framebuffer *buffer = ctx->DrawBuffer; int bbox[4]; if (!buffer) @@ -652,7 +652,7 @@ update_framebuffer(struct gl_context *ctx, struct gl_framebuffer *fb) * context state (GL_READ_BUFFER too). */ if (fb->ColorDrawBuffer[0] != ctx->Color.DrawBuffer[0]) { - _mesa_drawbuffers(ctx, ctx->Const.MaxDrawBuffers, + _mesa_drawbuffers(ctx, fb, ctx->Const.MaxDrawBuffers, ctx->Color.DrawBuffer, NULL); } } @@ -678,24 +678,21 @@ update_framebuffer(struct gl_context *ctx, struct gl_framebuffer *fb) /** - * Update state related to the current draw/read framebuffers. + * Update state related to the draw/read framebuffers. */ void -_mesa_update_framebuffer(struct gl_context *ctx) +_mesa_update_framebuffer(struct gl_context *ctx, + struct gl_framebuffer *readFb, + struct gl_framebuffer *drawFb) { - struct gl_framebuffer *drawFb; - struct gl_framebuffer *readFb; - assert(ctx); - drawFb = ctx->DrawBuffer; - readFb = ctx->ReadBuffer; update_framebuffer(ctx, drawFb); if (readFb != drawFb) update_framebuffer(ctx, readFb); - _mesa_update_clamp_vertex_color(ctx); - _mesa_update_clamp_fragment_color(ctx); + _mesa_update_clamp_vertex_color(ctx, drawFb); + _mesa_update_clamp_fragment_color(ctx, drawFb); } diff --git a/mesalib/src/mesa/main/framebuffer.h b/mesalib/src/mesa/main/framebuffer.h index a4274216e..d02b86f20 100644 --- a/mesalib/src/mesa/main/framebuffer.h +++ b/mesalib/src/mesa/main/framebuffer.h @@ -77,14 +77,17 @@ _mesa_scissor_bounding_box(const struct gl_context *ctx, unsigned idx, int *bbox); extern void -_mesa_update_draw_buffer_bounds(struct gl_context *ctx); +_mesa_update_draw_buffer_bounds(struct gl_context *ctx, + struct gl_framebuffer *drawFb); extern void _mesa_update_framebuffer_visual(struct gl_context *ctx, struct gl_framebuffer *fb); extern void -_mesa_update_framebuffer(struct gl_context *ctx); +_mesa_update_framebuffer(struct gl_context *ctx, + struct gl_framebuffer *readFb, + struct gl_framebuffer *drawFb); extern GLboolean _mesa_source_buffer_exists(struct gl_context *ctx, GLenum format); diff --git a/mesalib/src/mesa/main/genmipmap.c b/mesalib/src/mesa/main/genmipmap.c index 9aef09019..32b9460ad 100644 --- a/mesalib/src/mesa/main/genmipmap.c +++ b/mesalib/src/mesa/main/genmipmap.c @@ -158,6 +158,13 @@ _mesa_GenerateTextureMipmap(GLuint texture) struct gl_texture_object *texObj; GET_CURRENT_CONTEXT(ctx); + if (!ctx->Extensions.ARB_direct_state_access) { + _mesa_error(ctx, GL_INVALID_OPERATION, + "glGenerateTextureMipmap(GL_ARB_direct_state_access " + "is not supported)"); + return; + } + texObj = _mesa_lookup_texture_err(ctx, texture, "glGenerateTextureMipmap"); if (!texObj) return; diff --git a/mesalib/src/mesa/main/get.c b/mesalib/src/mesa/main/get.c index a881bc589..8a6c81aff 100644 --- a/mesalib/src/mesa/main/get.c +++ b/mesalib/src/mesa/main/get.c @@ -909,13 +909,13 @@ find_custom_value(struct gl_context *ctx, const struct value_desc *d, union valu break; case GL_FOG_COLOR: - if (_mesa_get_clamp_fragment_color(ctx)) + if (_mesa_get_clamp_fragment_color(ctx, ctx->DrawBuffer)) COPY_4FV(v->value_float_4, ctx->Fog.Color); else COPY_4FV(v->value_float_4, ctx->Fog.ColorUnclamped); break; case GL_COLOR_CLEAR_VALUE: - if (_mesa_get_clamp_fragment_color(ctx)) { + if (_mesa_get_clamp_fragment_color(ctx, ctx->DrawBuffer)) { v->value_float_4[0] = CLAMP(ctx->Color.ClearColor.f[0], 0.0F, 1.0F); v->value_float_4[1] = CLAMP(ctx->Color.ClearColor.f[1], 0.0F, 1.0F); v->value_float_4[2] = CLAMP(ctx->Color.ClearColor.f[2], 0.0F, 1.0F); @@ -924,13 +924,13 @@ find_custom_value(struct gl_context *ctx, const struct value_desc *d, union valu COPY_4FV(v->value_float_4, ctx->Color.ClearColor.f); break; case GL_BLEND_COLOR_EXT: - if (_mesa_get_clamp_fragment_color(ctx)) + if (_mesa_get_clamp_fragment_color(ctx, ctx->DrawBuffer)) COPY_4FV(v->value_float_4, ctx->Color.BlendColor); else COPY_4FV(v->value_float_4, ctx->Color.BlendColorUnclamped); break; case GL_ALPHA_TEST_REF: - if (_mesa_get_clamp_fragment_color(ctx)) + if (_mesa_get_clamp_fragment_color(ctx, ctx->DrawBuffer)) v->value_float = ctx->Color.AlphaRef; else v->value_float = ctx->Color.AlphaRefUnclamped; @@ -1911,6 +1911,7 @@ find_value_indexed(const char *func, GLenum pname, GLuint index, union value *v) if (index >= ctx->Const.Program[MESA_SHADER_VERTEX].MaxAttribs) goto invalid_value; v->value_int = ctx->Array.VAO->VertexBinding[VERT_ATTRIB_GENERIC(index)].Stride; + return TYPE_INT; /* ARB_shader_image_load_store */ case GL_IMAGE_BINDING_NAME: { diff --git a/mesalib/src/mesa/main/mtypes.h b/mesalib/src/mesa/main/mtypes.h index fb4143086..83425176a 100644 --- a/mesalib/src/mesa/main/mtypes.h +++ b/mesalib/src/mesa/main/mtypes.h @@ -695,7 +695,8 @@ struct gl_current_attrib * \note Index and Edgeflag current values are stored as floats in the * SIX and SEVEN attribute slots. */ - GLfloat Attrib[VERT_ATTRIB_MAX][4]; /**< Position, color, texcoords, etc */ + /* we need double storage for this for vertex attrib 64bit */ + GLfloat Attrib[VERT_ATTRIB_MAX][4*2]; /**< Position, color, texcoords, etc */ /** * \name Current raster position attributes (always valid). @@ -1523,6 +1524,7 @@ struct gl_client_array GLboolean Enabled; /**< Enabled flag is a boolean */ GLboolean Normalized; /**< GL_ARB_vertex_program */ GLboolean Integer; /**< Integer-valued? */ + GLboolean Doubles; /**< double precision values are not converted to floats */ GLuint InstanceDivisor; /**< GL_ARB_instanced_arrays */ struct gl_buffer_object *BufferObj;/**< GL_ARB_vertex_buffer_object */ @@ -1553,6 +1555,7 @@ struct gl_vertex_attrib_array GLboolean Enabled; /**< Whether the array is enabled */ GLboolean Normalized; /**< Fixed-point values are normalized when converted to floats */ GLboolean Integer; /**< Fixed-point values are not converted to floats */ + GLboolean Doubles; /**< double precision values are not converted to floats */ GLuint _ElementSize; /**< Size of each element in bytes */ GLuint VertexBinding; /**< Vertex buffer binding */ }; @@ -1671,6 +1674,9 @@ struct gl_array_attrib /** The default vertex array object */ struct gl_vertex_array_object *DefaultVAO; + /** The last VAO accessed by a DSA function */ + struct gl_vertex_array_object *LastLookedUpVAO; + /** Array objects (GL_ARB/APPLE_vertex_array_object) */ struct _mesa_HashTable *Objects; @@ -2090,6 +2096,7 @@ struct gl_program struct nir_shader *nir; GLbitfield64 InputsRead; /**< Bitmask of which input regs are read */ + GLbitfield64 DoubleInputsRead; /**< Bitmask of which input regs are read and are doubles */ GLbitfield64 OutputsWritten; /**< Bitmask of which output regs are written */ GLbitfield SystemValuesRead; /**< Bitmask of SYSTEM_VALUE_x inputs used */ GLbitfield InputFlags[MAX_PROGRAM_INPUTS]; /**< PROG_PARAM_BIT_x flags */ @@ -2499,6 +2506,12 @@ struct gl_shader GLuint NumImages; /** + * Whether early fragment tests are enabled as defined by + * ARB_shader_image_load_store. + */ + bool EarlyFragmentTests; + + /** * Compute shader state from ARB_compute_shader layout qualifiers. */ struct { @@ -3608,6 +3621,7 @@ struct gl_extensions GLboolean ARB_depth_clamp; GLboolean ARB_depth_texture; GLboolean ARB_derivative_control; + GLboolean ARB_direct_state_access; GLboolean ARB_draw_buffers_blend; GLboolean ARB_draw_elements_base_vertex; GLboolean ARB_draw_indirect; @@ -3672,6 +3686,7 @@ struct gl_extensions GLboolean ARB_transform_feedback3; GLboolean ARB_transform_feedback_instanced; GLboolean ARB_uniform_buffer_object; + GLboolean ARB_vertex_attrib_64bit; GLboolean ARB_vertex_program; GLboolean ARB_vertex_shader; GLboolean ARB_vertex_type_10f_11f_11f_rev; diff --git a/mesalib/src/mesa/main/pipelineobj.c b/mesalib/src/mesa/main/pipelineobj.c index 0fefa7d56..a33cdd139 100644 --- a/mesalib/src/mesa/main/pipelineobj.c +++ b/mesalib/src/mesa/main/pipelineobj.c @@ -553,6 +553,12 @@ _mesa_CreateProgramPipelines(GLsizei n, GLuint *pipelines) { GET_CURRENT_CONTEXT(ctx); + if (!ctx->Extensions.ARB_direct_state_access) { + _mesa_error(ctx, GL_INVALID_OPERATION, "glCreateProgramPipelines(" + "GL_ARB_direct_state_access is not supported)"); + return; + } + create_program_pipelines(ctx, n, pipelines, true); } diff --git a/mesalib/src/mesa/main/queryobj.c b/mesalib/src/mesa/main/queryobj.c index fbccf3fe6..2784b4c05 100644 --- a/mesalib/src/mesa/main/queryobj.c +++ b/mesalib/src/mesa/main/queryobj.c @@ -284,6 +284,13 @@ _mesa_CreateQueries(GLenum target, GLsizei n, GLuint *ids) { GET_CURRENT_CONTEXT(ctx); + if (!ctx->Extensions.ARB_direct_state_access) { + _mesa_error(ctx, GL_INVALID_OPERATION, + "glCreateQueries(GL_ARB_direct_state_access " + "is not supported)"); + return; + } + switch (target) { case GL_SAMPLES_PASSED: case GL_ANY_SAMPLES_PASSED: @@ -776,6 +783,9 @@ _mesa_GetQueryObjectiv(GLuint id, GLenum pname, GLint *params) ctx->Driver.CheckQuery( ctx, q ); *params = q->Ready; break; + case GL_QUERY_TARGET: + *params = q->Target; + break; default: _mesa_error(ctx, GL_INVALID_ENUM, "glGetQueryObjectivARB(pname)"); return; @@ -827,6 +837,9 @@ _mesa_GetQueryObjectuiv(GLuint id, GLenum pname, GLuint *params) ctx->Driver.CheckQuery( ctx, q ); *params = q->Ready; break; + case GL_QUERY_TARGET: + *params = q->Target; + break; default: _mesa_error(ctx, GL_INVALID_ENUM, "glGetQueryObjectuivARB(pname)"); return; @@ -867,6 +880,9 @@ _mesa_GetQueryObjecti64v(GLuint id, GLenum pname, GLint64EXT *params) ctx->Driver.CheckQuery( ctx, q ); *params = q->Ready; break; + case GL_QUERY_TARGET: + *params = q->Target; + break; default: _mesa_error(ctx, GL_INVALID_ENUM, "glGetQueryObjecti64vARB(pname)"); return; @@ -907,6 +923,9 @@ _mesa_GetQueryObjectui64v(GLuint id, GLenum pname, GLuint64EXT *params) ctx->Driver.CheckQuery( ctx, q ); *params = q->Ready; break; + case GL_QUERY_TARGET: + *params = q->Target; + break; default: _mesa_error(ctx, GL_INVALID_ENUM, "glGetQueryObjectui64vARB(pname)"); return; diff --git a/mesalib/src/mesa/main/readpix.c b/mesalib/src/mesa/main/readpix.c index ed0104c9e..df46f8361 100644 --- a/mesalib/src/mesa/main/readpix.c +++ b/mesalib/src/mesa/main/readpix.c @@ -83,7 +83,7 @@ get_readpixels_transfer_ops(const struct gl_context *ctx, mesa_format texFormat, if (uses_blit) { /* For blit-based ReadPixels packing, the clamping is done automatically * unless the type is float. */ - if (_mesa_get_clamp_read_color(ctx) && + if (_mesa_get_clamp_read_color(ctx, ctx->ReadBuffer) && (type == GL_FLOAT || type == GL_HALF_FLOAT)) { transferOps |= IMAGE_CLAMP_BIT; } @@ -91,7 +91,7 @@ get_readpixels_transfer_ops(const struct gl_context *ctx, mesa_format texFormat, else { /* For CPU-based ReadPixels packing, the clamping must always be done * for non-float types, */ - if (_mesa_get_clamp_read_color(ctx) || + if (_mesa_get_clamp_read_color(ctx, ctx->ReadBuffer) || (type != GL_FLOAT && type != GL_HALF_FLOAT)) { transferOps |= IMAGE_CLAMP_BIT; } diff --git a/mesalib/src/mesa/main/samplerobj.c b/mesalib/src/mesa/main/samplerobj.c index a3aacc66a..60711a5b5 100644 --- a/mesalib/src/mesa/main/samplerobj.c +++ b/mesalib/src/mesa/main/samplerobj.c @@ -221,6 +221,13 @@ void GLAPIENTRY _mesa_CreateSamplers(GLsizei count, GLuint *samplers) { GET_CURRENT_CONTEXT(ctx); + + if (!ctx->Extensions.ARB_direct_state_access) { + _mesa_error(ctx, GL_INVALID_OPERATION, "glCreateSamplers(" + "GL_ARB_direct_state_access is not supported)"); + return; + } + create_samplers(ctx, count, samplers, "glCreateSamplers"); } diff --git a/mesalib/src/mesa/main/shader_query.cpp b/mesalib/src/mesa/main/shader_query.cpp index d2ca49b43..3445f89a3 100644 --- a/mesalib/src/mesa/main/shader_query.cpp +++ b/mesalib/src/mesa/main/shader_query.cpp @@ -28,6 +28,7 @@ * \author Ian Romanick <ian.d.romanick@intel.com> */ +#include "main/context.h" #include "main/core.h" #include "glsl_symbol_table.h" #include "ir.h" @@ -809,6 +810,8 @@ stage_from_enum(GLenum ref) return MESA_SHADER_GEOMETRY; case GL_REFERENCED_BY_FRAGMENT_SHADER: return MESA_SHADER_FRAGMENT; + case GL_REFERENCED_BY_COMPUTE_SHADER: + return MESA_SHADER_COMPUTE; default: assert(!"shader stage not supported"); return MESA_SHADER_STAGES; @@ -824,6 +827,10 @@ is_resource_referenced(struct gl_shader_program *shProg, struct gl_program_resource *res, GLuint index, uint8_t stage) { + /* First, check if we even have such a stage active. */ + if (!shProg->_LinkedShaders[stage]) + return false; + if (res->Type == GL_ATOMIC_COUNTER_BUFFER) return RESOURCE_ATC(res)->StageReferences[stage]; @@ -979,6 +986,10 @@ _mesa_program_resource_prop(struct gl_shader_program *shProg, case GL_NUM_ACTIVE_VARIABLES: case GL_ACTIVE_VARIABLES: return get_buffer_property(shProg, res, prop, val, caller); + case GL_REFERENCED_BY_COMPUTE_SHADER: + if (!_mesa_has_compute_shaders(ctx)) + goto invalid_enum; + /* fallthrough */ case GL_REFERENCED_BY_VERTEX_SHADER: case GL_REFERENCED_BY_GEOMETRY_SHADER: case GL_REFERENCED_BY_FRAGMENT_SHADER: @@ -1015,17 +1026,18 @@ _mesa_program_resource_prop(struct gl_shader_program *shProg, case GL_IS_PER_PATCH: case GL_REFERENCED_BY_TESS_CONTROL_SHADER: case GL_REFERENCED_BY_TESS_EVALUATION_SHADER: - /* GL_ARB_compute_shader */ - case GL_REFERENCED_BY_COMPUTE_SHADER: default: - _mesa_error(ctx, GL_INVALID_ENUM, "%s(%s prop %s)", caller, - _mesa_lookup_enum_by_nr(res->Type), - _mesa_lookup_enum_by_nr(prop)); - return 0; + goto invalid_enum; } #undef VALIDATE_TYPE +invalid_enum: + _mesa_error(ctx, GL_INVALID_ENUM, "%s(%s prop %s)", caller, + _mesa_lookup_enum_by_nr(res->Type), + _mesa_lookup_enum_by_nr(prop)); + return 0; + invalid_operation: _mesa_error(ctx, GL_INVALID_OPERATION, "%s(%s prop %s)", caller, _mesa_lookup_enum_by_nr(res->Type), diff --git a/mesalib/src/mesa/main/shaderimage.c b/mesalib/src/mesa/main/shaderimage.c index dcbcca623..80b77275f 100644 --- a/mesalib/src/mesa/main/shaderimage.c +++ b/mesalib/src/mesa/main/shaderimage.c @@ -58,8 +58,8 @@ # define MESA_FORMAT_SIGNED_RG_8 MESA_FORMAT_R8G8_SNORM #endif -static mesa_format -get_image_format(GLenum format) +mesa_format +_mesa_get_shader_image_format(GLenum format) { switch (format) { case GL_RGBA32F: @@ -331,19 +331,33 @@ get_image_format_class(mesa_format format) } } +void +_mesa_init_image_units(struct gl_context *ctx) +{ + unsigned i; + + for (i = 0; i < ARRAY_SIZE(ctx->ImageUnits); ++i) { + struct gl_image_unit *u = &ctx->ImageUnits[i]; + u->Access = GL_READ_ONLY; + u->Format = GL_R8; + u->_ActualFormat = _mesa_get_shader_image_format(u->Format); + } +} + static GLboolean validate_image_unit(struct gl_context *ctx, struct gl_image_unit *u) { struct gl_texture_object *t = u->TexObj; - struct gl_texture_image *img; + mesa_format tex_format; - if (!t || u->Level < t->BaseLevel || - u->Level > t->_MaxLevel) + if (!t) return GL_FALSE; _mesa_test_texobj_completeness(ctx, t); - if ((u->Level == t->BaseLevel && !t->_BaseComplete) || + if (u->Level < t->BaseLevel || + u->Level > t->_MaxLevel || + (u->Level == t->BaseLevel && !t->_BaseComplete) || (u->Level != t->BaseLevel && !t->_MipmapComplete)) return GL_FALSE; @@ -351,25 +365,32 @@ validate_image_unit(struct gl_context *ctx, struct gl_image_unit *u) u->Layer >= _mesa_get_texture_layers(t, u->Level)) return GL_FALSE; - if (t->Target == GL_TEXTURE_CUBE_MAP) - img = t->Image[u->Layer][u->Level]; - else - img = t->Image[0][u->Level]; + if (t->Target == GL_TEXTURE_BUFFER) { + tex_format = _mesa_get_shader_image_format(t->BufferObjectFormat); + + } else { + struct gl_texture_image *img = (t->Target == GL_TEXTURE_CUBE_MAP ? + t->Image[u->Layer][u->Level] : + t->Image[0][u->Level]); - if (!img || img->Border || - get_image_format_class(img->TexFormat) == IMAGE_FORMAT_CLASS_NONE || - img->NumSamples > ctx->Const.MaxImageSamples) + if (!img || img->Border || img->NumSamples > ctx->Const.MaxImageSamples) + return GL_FALSE; + + tex_format = _mesa_get_shader_image_format(img->InternalFormat); + } + + if (!tex_format) return GL_FALSE; switch (t->ImageFormatCompatibilityType) { case GL_IMAGE_FORMAT_COMPATIBILITY_BY_SIZE: - if (_mesa_get_format_bytes(img->TexFormat) != + if (_mesa_get_format_bytes(tex_format) != _mesa_get_format_bytes(u->_ActualFormat)) return GL_FALSE; break; case GL_IMAGE_FORMAT_COMPATIBILITY_BY_CLASS: - if (get_image_format_class(img->TexFormat) != + if (get_image_format_class(tex_format) != get_image_format_class(u->_ActualFormat)) return GL_FALSE; break; @@ -421,7 +442,7 @@ validate_bind_image_texture(struct gl_context *ctx, GLuint unit, return GL_FALSE; } - if (!get_image_format(format)) { + if (!_mesa_get_shader_image_format(format)) { _mesa_error(ctx, GL_INVALID_VALUE, "glBindImageTexture(format)"); return GL_FALSE; } @@ -435,7 +456,6 @@ _mesa_BindImageTexture(GLuint unit, GLuint texture, GLint level, GLenum format) { GET_CURRENT_CONTEXT(ctx); - struct gl_texture_object *t = NULL; struct gl_image_unit *u; if (!validate_bind_image_texture(ctx, unit, texture, level, @@ -448,34 +468,34 @@ _mesa_BindImageTexture(GLuint unit, GLuint texture, GLint level, ctx->NewDriverState |= ctx->DriverFlags.NewImageUnits; if (texture) { - t = _mesa_lookup_texture(ctx, texture); + struct gl_texture_object *t = _mesa_lookup_texture(ctx, texture); + if (!t) { _mesa_error(ctx, GL_INVALID_VALUE, "glBindImageTexture(texture)"); return; } _mesa_reference_texobj(&u->TexObj, t); - u->Level = level; - u->Access = access; - u->Format = format; - u->_ActualFormat = get_image_format(format); - - if (_mesa_tex_target_is_layered(t->Target)) { - u->Layered = layered; - u->Layer = (layered ? 0 : layer); - } else { - u->Layered = GL_FALSE; - u->Layer = 0; - } - } else { _mesa_reference_texobj(&u->TexObj, NULL); } + u->Level = level; + u->Access = access; + u->Format = format; + u->_ActualFormat = _mesa_get_shader_image_format(format); u->_Valid = validate_image_unit(ctx, u); + if (u->TexObj && _mesa_tex_target_is_layered(u->TexObj->Target)) { + u->Layered = layered; + u->Layer = (layered ? 0 : layer); + } else { + u->Layered = GL_FALSE; + u->Layer = 0; + } + if (ctx->Driver.BindImageTexture) - ctx->Driver.BindImageTexture(ctx, u, t, level, layered, + ctx->Driver.BindImageTexture(ctx, u, u->TexObj, level, layered, layer, access, format); } @@ -535,8 +555,7 @@ _mesa_BindImageTextures(GLuint first, GLsizei count, const GLuint *textures) if (texture != 0) { struct gl_texture_object *texObj; - struct gl_texture_image *image; - mesa_format actualFormat; + GLenum tex_format; if (!u->TexObj || u->TexObj->Name != texture) { texObj = _mesa_lookup_texture_locked(ctx, texture); @@ -557,25 +576,30 @@ _mesa_BindImageTextures(GLuint first, GLsizei count, const GLuint *textures) texObj = u->TexObj; } - image = texObj->Image[0][0]; + if (texObj->Target == GL_TEXTURE_BUFFER) { + tex_format = texObj->BufferObjectFormat; + } else { + struct gl_texture_image *image = texObj->Image[0][0]; - if (!image || image->Width == 0 || image->Height == 0 || image->Depth == 0) { - /* The ARB_multi_bind spec says: - * - * "An INVALID_OPERATION error is generated if the width, - * height, or depth of the level zero texture image of - * any texture in <textures> is zero (per binding)." - */ - _mesa_error(ctx, GL_INVALID_OPERATION, - "glBindImageTextures(the width, height or depth " - "of the level zero texture image of " - "textures[%d]=%u is zero)", i, texture); - continue; - } + if (!image || image->Width == 0 || image->Height == 0 || + image->Depth == 0) { + /* The ARB_multi_bind spec says: + * + * "An INVALID_OPERATION error is generated if the width, + * height, or depth of the level zero texture image of + * any texture in <textures> is zero (per binding)." + */ + _mesa_error(ctx, GL_INVALID_OPERATION, + "glBindImageTextures(the width, height or depth " + "of the level zero texture image of " + "textures[%d]=%u is zero)", i, texture); + continue; + } - actualFormat = get_image_format(image->InternalFormat); + tex_format = image->InternalFormat; + } - if (actualFormat == MESA_FORMAT_NONE) { + if (_mesa_get_shader_image_format(tex_format) == MESA_FORMAT_NONE) { /* The ARB_multi_bind spec says: * * "An INVALID_OPERATION error is generated if the internal @@ -586,7 +610,7 @@ _mesa_BindImageTextures(GLuint first, GLsizei count, const GLuint *textures) "glBindImageTextures(the internal format %s of " "the level zero texture image of textures[%d]=%u " "is not supported)", - _mesa_lookup_enum_by_nr(image->InternalFormat), + _mesa_lookup_enum_by_nr(tex_format), i, texture); continue; } @@ -597,8 +621,8 @@ _mesa_BindImageTextures(GLuint first, GLsizei count, const GLuint *textures) u->Layered = _mesa_tex_target_is_layered(texObj->Target); u->Layer = 0; u->Access = GL_READ_WRITE; - u->Format = image->InternalFormat; - u->_ActualFormat = actualFormat; + u->Format = tex_format; + u->_ActualFormat = _mesa_get_shader_image_format(tex_format); u->_Valid = validate_image_unit(ctx, u); } else { /* Unbind the texture from the unit */ diff --git a/mesalib/src/mesa/main/shaderimage.h b/mesalib/src/mesa/main/shaderimage.h index 733ac7747..33d8a1eff 100644 --- a/mesalib/src/mesa/main/shaderimage.h +++ b/mesalib/src/mesa/main/shaderimage.h @@ -28,10 +28,27 @@ #define SHADERIMAGE_H #include "glheader.h" +#include "formats.h" + +#ifdef __cplusplus +extern "C" { +#endif struct gl_context; /** + * Get the matching mesa_format for a shader image format GL enum. + */ +mesa_format +_mesa_get_shader_image_format(GLenum format); + +/** + * Initialize a context's shader image units to the default state. + */ +void +_mesa_init_image_units(struct gl_context *ctx); + +/** * Recalculate the \c _Valid flag of a context's shader image units. * * To be called when the state of any texture bound to an image unit @@ -51,4 +68,8 @@ _mesa_BindImageTextures(GLuint first, GLsizei count, const GLuint *textures); void GLAPIENTRY _mesa_MemoryBarrier(GLbitfield barriers); +#ifdef __cplusplus +} +#endif + #endif diff --git a/mesalib/src/mesa/main/state.c b/mesalib/src/mesa/main/state.c index cc84c6148..2657c532f 100644 --- a/mesalib/src/mesa/main/state.c +++ b/mesalib/src/mesa/main/state.c @@ -101,9 +101,12 @@ update_program(struct gl_context *ctx) ctx->_Shader->CurrentProgram[MESA_SHADER_GEOMETRY]; struct gl_shader_program *fsProg = ctx->_Shader->CurrentProgram[MESA_SHADER_FRAGMENT]; + const struct gl_shader_program *csProg = + ctx->_Shader->CurrentProgram[MESA_SHADER_COMPUTE]; const struct gl_vertex_program *prevVP = ctx->VertexProgram._Current; const struct gl_fragment_program *prevFP = ctx->FragmentProgram._Current; const struct gl_geometry_program *prevGP = ctx->GeometryProgram._Current; + const struct gl_compute_program *prevCP = ctx->ComputeProgram._Current; GLbitfield new_state = 0x0; /* @@ -199,6 +202,16 @@ update_program(struct gl_context *ctx) _mesa_reference_vertprog(ctx, &ctx->VertexProgram._Current, NULL); } + if (csProg && csProg->LinkStatus + && csProg->_LinkedShaders[MESA_SHADER_COMPUTE]) { + /* Use GLSL compute shader */ + _mesa_reference_compprog(ctx, &ctx->ComputeProgram._Current, + gl_compute_program(csProg->_LinkedShaders[MESA_SHADER_COMPUTE]->Program)); + } else { + /* no compute program */ + _mesa_reference_compprog(ctx, &ctx->ComputeProgram._Current, NULL); + } + /* Let the driver know what's happening: */ if (ctx->FragmentProgram._Current != prevFP) { @@ -225,6 +238,14 @@ update_program(struct gl_context *ctx) } } + if (ctx->ComputeProgram._Current != prevCP) { + new_state |= _NEW_PROGRAM; + if (ctx->Driver.BindProgram) { + ctx->Driver.BindProgram(ctx, GL_COMPUTE_PROGRAM_NV, + (struct gl_program *) ctx->ComputeProgram._Current); + } + } + return new_state; } @@ -368,10 +389,10 @@ _mesa_update_state_locked( struct gl_context *ctx ) update_frontbit( ctx ); if (new_state & _NEW_BUFFERS) - _mesa_update_framebuffer(ctx); + _mesa_update_framebuffer(ctx, ctx->ReadBuffer, ctx->DrawBuffer); if (new_state & (_NEW_SCISSOR | _NEW_BUFFERS | _NEW_VIEWPORT)) - _mesa_update_draw_buffer_bounds( ctx ); + _mesa_update_draw_buffer_bounds(ctx, ctx->DrawBuffer); if (new_state & _NEW_LIGHT) _mesa_update_lighting( ctx ); diff --git a/mesalib/src/mesa/main/texenv.c b/mesalib/src/mesa/main/texenv.c index ec521e6c6..3edafc0f7 100644 --- a/mesalib/src/mesa/main/texenv.c +++ b/mesalib/src/mesa/main/texenv.c @@ -646,7 +646,7 @@ _mesa_GetTexEnvfv( GLenum target, GLenum pname, GLfloat *params ) if (pname == GL_TEXTURE_ENV_COLOR) { if(ctx->NewState & (_NEW_BUFFERS | _NEW_FRAG_CLAMP)) _mesa_update_state(ctx); - if (_mesa_get_clamp_fragment_color(ctx)) + if (_mesa_get_clamp_fragment_color(ctx, ctx->DrawBuffer)) COPY_4FV( params, texUnit->EnvColor ); else COPY_4FV( params, texUnit->EnvColorUnclamped ); diff --git a/mesalib/src/mesa/main/texgetimage.c b/mesalib/src/mesa/main/texgetimage.c index 92b4d6795..f582a7f78 100644 --- a/mesalib/src/mesa/main/texgetimage.c +++ b/mesalib/src/mesa/main/texgetimage.c @@ -1108,6 +1108,13 @@ _mesa_GetTextureImage(GLuint texture, GLint level, GLenum format, GLenum err; GET_CURRENT_CONTEXT(ctx); + if (!ctx->Extensions.ARB_direct_state_access) { + _mesa_error(ctx, GL_INVALID_OPERATION, + "glGetTextureImage(GL_ARB_direct_state_access " + "is not supported)"); + return; + } + /* * This has been moved here because a format/type mismatch can cause a NULL * texImage object, which in turn causes the mismatch error to be @@ -1344,6 +1351,13 @@ _mesa_GetCompressedTextureImage(GLuint texture, GLint level, GLint image_stride; GET_CURRENT_CONTEXT(ctx); + if (!ctx->Extensions.ARB_direct_state_access) { + _mesa_error(ctx, GL_INVALID_OPERATION, + "glGetCompressedTextureImage(GL_ARB_direct_state_access " + "is not supported)"); + return; + } + texObj = _mesa_lookup_texture_err(ctx, texture, "glGetCompressedTextureImage"); if (!texObj) diff --git a/mesalib/src/mesa/main/teximage.c b/mesalib/src/mesa/main/teximage.c index 7bc1da7f8..7616fd7ce 100644 --- a/mesalib/src/mesa/main/teximage.c +++ b/mesalib/src/mesa/main/teximage.c @@ -3624,6 +3624,13 @@ texturesubimage(struct gl_context *ctx, GLuint dims, _mesa_lookup_enum_by_nr(format), _mesa_lookup_enum_by_nr(type), pixels); + if (!ctx->Extensions.ARB_direct_state_access) { + _mesa_error(ctx, GL_INVALID_OPERATION, + "glTextureSubImage%uD(GL_ARB_direct_state_access " + "is not supported)", dims); + return; + } + /* Get the texture object by Name. */ texObj = _mesa_lookup_texture(ctx, texture); if (!texObj) { @@ -4183,6 +4190,12 @@ _mesa_CopyTextureSubImage1D(GLuint texture, GLint level, const char *self = "glCopyTextureSubImage1D"; GET_CURRENT_CONTEXT(ctx); + if (!ctx->Extensions.ARB_direct_state_access) { + _mesa_error(ctx, GL_INVALID_OPERATION, + "%s(GL_ARB_direct_state_access is not supported)", self); + return; + } + texObj = _mesa_lookup_texture_err(ctx, texture, self); if (!texObj) return; @@ -4207,6 +4220,12 @@ _mesa_CopyTextureSubImage2D(GLuint texture, GLint level, const char *self = "glCopyTextureSubImage2D"; GET_CURRENT_CONTEXT(ctx); + if (!ctx->Extensions.ARB_direct_state_access) { + _mesa_error(ctx, GL_INVALID_OPERATION, + "%s(GL_ARB_direct_state_access is not supported)", self); + return; + } + texObj = _mesa_lookup_texture_err(ctx, texture, self); if (!texObj) return; @@ -4234,6 +4253,12 @@ _mesa_CopyTextureSubImage3D(GLuint texture, GLint level, const char *self = "glCopyTextureSubImage3D"; GET_CURRENT_CONTEXT(ctx); + if (!ctx->Extensions.ARB_direct_state_access) { + _mesa_error(ctx, GL_INVALID_OPERATION, + "%s(GL_ARB_direct_state_access is not supported)", self); + return; + } + texObj = _mesa_lookup_texture_err(ctx, texture, self); if (!texObj) return; @@ -4829,6 +4854,13 @@ _mesa_CompressedTextureSubImage1D(GLuint texture, GLint level, GLint xoffset, GET_CURRENT_CONTEXT(ctx); + if (!ctx->Extensions.ARB_direct_state_access) { + _mesa_error(ctx, GL_INVALID_OPERATION, + "glCompressedTextureSubImage1D(GL_ARB_direct_state_access " + "is not supported)"); + return; + } + texObj = _mesa_lookup_texture_err(ctx, texture, "glCompressedTextureSubImage1D"); if (!texObj) @@ -4907,6 +4939,13 @@ _mesa_CompressedTextureSubImage2D(GLuint texture, GLint level, GLint xoffset, GET_CURRENT_CONTEXT(ctx); + if (!ctx->Extensions.ARB_direct_state_access) { + _mesa_error(ctx, GL_INVALID_OPERATION, + "glCompressedTextureSubImage2D(GL_ARB_direct_state_access " + "is not supported)"); + return; + } + texObj = _mesa_lookup_texture_err(ctx, texture, "glCompressedTextureSubImage2D"); if (!texObj) @@ -4985,6 +5024,13 @@ _mesa_CompressedTextureSubImage3D(GLuint texture, GLint level, GLint xoffset, GET_CURRENT_CONTEXT(ctx); + if (!ctx->Extensions.ARB_direct_state_access) { + _mesa_error(ctx, GL_INVALID_OPERATION, + "glCompressedTextureSubImage3D(GL_ARB_direct_state_access " + "is not supported)"); + return; + } + texObj = _mesa_lookup_texture_err(ctx, texture, "glCompressedTextureSubImage3D"); if (!texObj) @@ -5469,6 +5515,13 @@ _mesa_TextureBuffer(GLuint texture, GLenum internalFormat, GLuint buffer) GET_CURRENT_CONTEXT(ctx); + if (!ctx->Extensions.ARB_direct_state_access) { + _mesa_error(ctx, GL_INVALID_OPERATION, + "glTextureBuffer(GL_ARB_direct_state_access " + "is not supported)"); + return; + } + if (buffer) { bufObj = _mesa_lookup_bufferobj_err(ctx, buffer, "glTextureBuffer"); if (!bufObj) @@ -5497,6 +5550,13 @@ _mesa_TextureBufferRange(GLuint texture, GLenum internalFormat, GLuint buffer, GET_CURRENT_CONTEXT(ctx); + if (!ctx->Extensions.ARB_direct_state_access) { + _mesa_error(ctx, GL_INVALID_OPERATION, + "glTextureBufferRange(GL_ARB_direct_state_access " + "is not supported)"); + return; + } + if (buffer) { bufObj = _mesa_lookup_bufferobj_err(ctx, buffer, "glTextureBufferRange"); @@ -5801,6 +5861,13 @@ _mesa_TextureStorage2DMultisample(GLuint texture, GLsizei samples, struct gl_texture_object *texObj; GET_CURRENT_CONTEXT(ctx); + if (!ctx->Extensions.ARB_direct_state_access) { + _mesa_error(ctx, GL_INVALID_OPERATION, + "glTextureStorage2DMultisample(GL_ARB_direct_state_access " + "is not supported)"); + return; + } + texObj = _mesa_lookup_texture_err(ctx, texture, "glTextureStorage2DMultisample"); if (!texObj) @@ -5821,6 +5888,13 @@ _mesa_TextureStorage3DMultisample(GLuint texture, GLsizei samples, struct gl_texture_object *texObj; GET_CURRENT_CONTEXT(ctx); + if (!ctx->Extensions.ARB_direct_state_access) { + _mesa_error(ctx, GL_INVALID_OPERATION, + "glTextureStorage3DMultisample(GL_ARB_direct_state_access " + "is not supported)"); + return; + } + /* Get the texture object by Name. */ texObj = _mesa_lookup_texture_err(ctx, texture, "glTextureStorage3DMultisample"); diff --git a/mesalib/src/mesa/main/texobj.c b/mesalib/src/mesa/main/texobj.c index c563f1e74..d51e6954b 100644 --- a/mesalib/src/mesa/main/texobj.c +++ b/mesalib/src/mesa/main/texobj.c @@ -1317,6 +1317,13 @@ _mesa_CreateTextures(GLenum target, GLsizei n, GLuint *textures) GLint targetIndex; GET_CURRENT_CONTEXT(ctx); + if (!ctx->Extensions.ARB_direct_state_access) { + _mesa_error(ctx, GL_INVALID_OPERATION, + "glCreateTextures(GL_ARB_direct_state_access " + "is not supported)"); + return; + } + /* * The 4.5 core profile spec (30.10.2014) doesn't specify what * glCreateTextures should do with invalid targets, which was probably an @@ -1808,6 +1815,13 @@ _mesa_BindTextureUnit(GLuint unit, GLuint texture) _mesa_debug(ctx, "glBindTextureUnit %s %d\n", _mesa_lookup_enum_by_nr(GL_TEXTURE0+unit), (GLint) texture); + if (!ctx->Extensions.ARB_direct_state_access) { + _mesa_error(ctx, GL_INVALID_OPERATION, + "glBindTextureUnit(GL_ARB_direct_state_access " + "is not supported)"); + return; + } + /* Section 8.1 (Texture Objects) of the OpenGL 4.5 core profile spec * (20141030) says: * "When texture is zero, each of the targets enumerated at the diff --git a/mesalib/src/mesa/main/texparam.c b/mesalib/src/mesa/main/texparam.c index b5d42d304..1fa583002 100644 --- a/mesalib/src/mesa/main/texparam.c +++ b/mesalib/src/mesa/main/texparam.c @@ -1108,6 +1108,13 @@ _mesa_TextureParameterfv(GLuint texture, GLenum pname, const GLfloat *params) struct gl_texture_object *texObj; GET_CURRENT_CONTEXT(ctx); + if (!ctx->Extensions.ARB_direct_state_access) { + _mesa_error(ctx, GL_INVALID_OPERATION, + "glTextureParameterfv(GL_ARB_direct_state_access " + "is not supported)"); + return; + } + texObj = get_texobj_by_name(ctx, texture, GL_FALSE); if (!texObj) { /* User passed a non-generated name. */ @@ -1124,6 +1131,13 @@ _mesa_TextureParameterf(GLuint texture, GLenum pname, GLfloat param) struct gl_texture_object *texObj; GET_CURRENT_CONTEXT(ctx); + if (!ctx->Extensions.ARB_direct_state_access) { + _mesa_error(ctx, GL_INVALID_OPERATION, + "glTextureParameterf(GL_ARB_direct_state_access " + "is not supported)"); + return; + } + texObj = get_texobj_by_name(ctx, texture, GL_FALSE); if (!texObj) { /* User passed a non-generated name. */ @@ -1140,6 +1154,13 @@ _mesa_TextureParameteri(GLuint texture, GLenum pname, GLint param) struct gl_texture_object *texObj; GET_CURRENT_CONTEXT(ctx); + if (!ctx->Extensions.ARB_direct_state_access) { + _mesa_error(ctx, GL_INVALID_OPERATION, + "glTextureParameteri(GL_ARB_direct_state_access " + "is not supported)"); + return; + } + texObj = get_texobj_by_name(ctx, texture, GL_FALSE); if (!texObj) { /* User passed a non-generated name. */ @@ -1157,6 +1178,13 @@ _mesa_TextureParameteriv(GLuint texture, GLenum pname, struct gl_texture_object *texObj; GET_CURRENT_CONTEXT(ctx); + if (!ctx->Extensions.ARB_direct_state_access) { + _mesa_error(ctx, GL_INVALID_OPERATION, + "glTextureParameteriv(GL_ARB_direct_state_access " + "is not supported)"); + return; + } + texObj = get_texobj_by_name(ctx, texture, GL_FALSE); if (!texObj) { /* User passed a non-generated name. */ @@ -1174,6 +1202,13 @@ _mesa_TextureParameterIiv(GLuint texture, GLenum pname, const GLint *params) struct gl_texture_object *texObj; GET_CURRENT_CONTEXT(ctx); + if (!ctx->Extensions.ARB_direct_state_access) { + _mesa_error(ctx, GL_INVALID_OPERATION, + "glTextureParameterIiv(GL_ARB_direct_state_access " + "is not supported)"); + return; + } + texObj = get_texobj_by_name(ctx, texture, GL_FALSE); if (!texObj) { /* User passed a non-generated name. */ @@ -1191,6 +1226,13 @@ _mesa_TextureParameterIuiv(GLuint texture, GLenum pname, const GLuint *params) struct gl_texture_object *texObj; GET_CURRENT_CONTEXT(ctx); + if (!ctx->Extensions.ARB_direct_state_access) { + _mesa_error(ctx, GL_INVALID_OPERATION, + "glTextureParameterIuiv(GL_ARB_direct_state_access " + "is not supported)"); + return; + } + texObj = get_texobj_by_name(ctx, texture, GL_FALSE); if (!texObj) { /* User passed a non-generated name. */ @@ -1650,6 +1692,13 @@ _mesa_GetTextureLevelParameterfv(GLuint texture, GLint level, GLint iparam; GET_CURRENT_CONTEXT(ctx); + if (!ctx->Extensions.ARB_direct_state_access) { + _mesa_error(ctx, GL_INVALID_OPERATION, + "glGetTextureLevelParameterfv(GL_ARB_direct_state_access " + "is not supported)"); + return; + } + texObj = _mesa_lookup_texture_err(ctx, texture, "glGetTextureLevelParameterfv"); if (!texObj) @@ -1668,6 +1717,13 @@ _mesa_GetTextureLevelParameteriv(GLuint texture, GLint level, struct gl_texture_object *texObj; GET_CURRENT_CONTEXT(ctx); + if (!ctx->Extensions.ARB_direct_state_access) { + _mesa_error(ctx, GL_INVALID_OPERATION, + "glGetTextureLevelParameteriv(GL_ARB_direct_state_access " + "is not supported)"); + return; + } + texObj = _mesa_lookup_texture_err(ctx, texture, "glGetTextureLevelParameteriv"); if (!texObj) @@ -1709,7 +1765,7 @@ get_tex_parameterfv(struct gl_context *ctx, if (ctx->NewState & (_NEW_BUFFERS | _NEW_FRAG_CLAMP)) _mesa_update_state_locked(ctx); - if (_mesa_get_clamp_fragment_color(ctx)) { + if (_mesa_get_clamp_fragment_color(ctx, ctx->DrawBuffer)) { params[0] = CLAMP(obj->Sampler.BorderColor.f[0], 0.0F, 1.0F); params[1] = CLAMP(obj->Sampler.BorderColor.f[1], 0.0F, 1.0F); params[2] = CLAMP(obj->Sampler.BorderColor.f[2], 0.0F, 1.0F); @@ -2227,6 +2283,13 @@ _mesa_GetTextureParameterfv(GLuint texture, GLenum pname, GLfloat *params) struct gl_texture_object *obj; GET_CURRENT_CONTEXT(ctx); + if (!ctx->Extensions.ARB_direct_state_access) { + _mesa_error(ctx, GL_INVALID_OPERATION, + "glGetTextureParameterfv(GL_ARB_direct_state_access " + "is not supported)"); + return; + } + obj = get_texobj_by_name(ctx, texture, GL_TRUE); if (!obj) { /* User passed a non-generated name. */ @@ -2244,6 +2307,13 @@ _mesa_GetTextureParameteriv(GLuint texture, GLenum pname, GLint *params) struct gl_texture_object *obj; GET_CURRENT_CONTEXT(ctx); + if (!ctx->Extensions.ARB_direct_state_access) { + _mesa_error(ctx, GL_INVALID_OPERATION, + "glGetTextureParameteriv(GL_ARB_direct_state_access " + "is not supported)"); + return; + } + obj = get_texobj_by_name(ctx, texture, GL_TRUE); if (!obj) { /* User passed a non-generated name. */ @@ -2261,6 +2331,13 @@ _mesa_GetTextureParameterIiv(GLuint texture, GLenum pname, GLint *params) struct gl_texture_object *texObj; GET_CURRENT_CONTEXT(ctx); + if (!ctx->Extensions.ARB_direct_state_access) { + _mesa_error(ctx, GL_INVALID_OPERATION, + "glGetTextureParameterIiv(GL_ARB_direct_state_access " + "is not supported)"); + return; + } + texObj = get_texobj_by_name(ctx, texture, GL_TRUE); if (!texObj) { /* User passed a non-generated name. */ @@ -2279,6 +2356,13 @@ _mesa_GetTextureParameterIuiv(GLuint texture, GLenum pname, GLuint *params) struct gl_texture_object *texObj; GET_CURRENT_CONTEXT(ctx); + if (!ctx->Extensions.ARB_direct_state_access) { + _mesa_error(ctx, GL_INVALID_OPERATION, + "glGetTextureParameterIuiv(GL_ARB_direct_state_access " + "is not supported)"); + return; + } + texObj = get_texobj_by_name(ctx, texture, GL_TRUE); if (!texObj) { /* User passed a non-generated name. */ diff --git a/mesalib/src/mesa/main/texstorage.c b/mesalib/src/mesa/main/texstorage.c index 53cb2c091..dee74a825 100644 --- a/mesalib/src/mesa/main/texstorage.c +++ b/mesalib/src/mesa/main/texstorage.c @@ -507,6 +507,13 @@ texturestorage(GLuint dims, GLuint texture, GLsizei levels, _mesa_lookup_enum_by_nr(internalformat), width, height, depth); + if (!ctx->Extensions.ARB_direct_state_access) { + _mesa_error(ctx, GL_INVALID_OPERATION, + "glTextureStorage%uD(GL_ARB_direct_state_access " + "is not supported)", dims); + return; + } + /* Check the format to make sure it is sized. */ if (!_mesa_is_legal_tex_storage_format(ctx, internalformat)) { _mesa_error(ctx, GL_INVALID_ENUM, diff --git a/mesalib/src/mesa/main/transformfeedback.c b/mesalib/src/mesa/main/transformfeedback.c index 103011ce5..642fa9647 100644 --- a/mesalib/src/mesa/main/transformfeedback.c +++ b/mesalib/src/mesa/main/transformfeedback.c @@ -706,6 +706,13 @@ _mesa_TransformFeedbackBufferBase(GLuint xfb, GLuint index, GLuint buffer) struct gl_transform_feedback_object *obj; struct gl_buffer_object *bufObj; + if (!ctx->Extensions.ARB_direct_state_access) { + _mesa_error(ctx, GL_INVALID_OPERATION, + "glTransformFeedbackBufferBase(GL_ARB_direct_state_access " + "is not supported)"); + return; + } + obj = lookup_transform_feedback_object_err(ctx, xfb, "glTransformFeedbackBufferBase"); if(!obj) { @@ -729,6 +736,13 @@ _mesa_TransformFeedbackBufferRange(GLuint xfb, GLuint index, GLuint buffer, struct gl_transform_feedback_object *obj; struct gl_buffer_object *bufObj; + if (!ctx->Extensions.ARB_direct_state_access) { + _mesa_error(ctx, GL_INVALID_OPERATION, + "glTransformFeedbackBufferRange(GL_ARB_direct_state_access " + "is not supported)"); + return; + } + obj = lookup_transform_feedback_object_err(ctx, xfb, "glTransformFeedbackBufferRange"); if(!obj) { @@ -1045,6 +1059,13 @@ _mesa_CreateTransformFeedbacks(GLsizei n, GLuint *names) { GET_CURRENT_CONTEXT(ctx); + if (!ctx->Extensions.ARB_direct_state_access) { + _mesa_error(ctx, GL_INVALID_OPERATION, + "glCreateTransformFeedbacks(GL_ARB_direct_state_access " + "is not supported)"); + return; + } + create_transform_feedbacks(ctx, n, names, true); } @@ -1215,6 +1236,13 @@ _mesa_GetTransformFeedbackiv(GLuint xfb, GLenum pname, GLint *param) struct gl_transform_feedback_object *obj; GET_CURRENT_CONTEXT(ctx); + if (!ctx->Extensions.ARB_direct_state_access) { + _mesa_error(ctx, GL_INVALID_OPERATION, + "glGetTransformFeedbackiv(GL_ARB_direct_state_access " + "is not supported)"); + return; + } + obj = lookup_transform_feedback_object_err(ctx, xfb, "glGetTransformFeedbackiv"); if(!obj) { @@ -1241,6 +1269,13 @@ _mesa_GetTransformFeedbacki_v(GLuint xfb, GLenum pname, GLuint index, struct gl_transform_feedback_object *obj; GET_CURRENT_CONTEXT(ctx); + if (!ctx->Extensions.ARB_direct_state_access) { + _mesa_error(ctx, GL_INVALID_OPERATION, + "glGetTransformFeedbacki_v(GL_ARB_direct_state_access " + "is not supported)"); + return; + } + obj = lookup_transform_feedback_object_err(ctx, xfb, "glGetTransformFeedbacki_v"); if(!obj) { @@ -1270,6 +1305,13 @@ _mesa_GetTransformFeedbacki64_v(GLuint xfb, GLenum pname, GLuint index, struct gl_transform_feedback_object *obj; GET_CURRENT_CONTEXT(ctx); + if (!ctx->Extensions.ARB_direct_state_access) { + _mesa_error(ctx, GL_INVALID_OPERATION, + "glGetTransformFeedbacki64_v(GL_ARB_direct_state_access " + "is not supported)"); + return; + } + obj = lookup_transform_feedback_object_err(ctx, xfb, "glGetTransformFeedbacki64_v"); if(!obj) { diff --git a/mesalib/src/mesa/main/uniform_query.cpp b/mesalib/src/mesa/main/uniform_query.cpp index 3e857ed10..728bd1bac 100644 --- a/mesalib/src/mesa/main/uniform_query.cpp +++ b/mesalib/src/mesa/main/uniform_query.cpp @@ -347,7 +347,8 @@ _mesa_get_uniform(struct gl_context *ctx, GLuint program, GLint location, && (uni->type->base_type == GLSL_TYPE_INT || uni->type->base_type == GLSL_TYPE_UINT - || uni->type->base_type == GLSL_TYPE_SAMPLER))) { + || uni->type->base_type == GLSL_TYPE_SAMPLER + || uni->type->base_type == GLSL_TYPE_IMAGE))) { memcpy(paramsOut, src, bytes); } else { union gl_constant_value *const dst = @@ -366,6 +367,7 @@ _mesa_get_uniform(struct gl_context *ctx, GLuint program, GLint location, break; case GLSL_TYPE_INT: case GLSL_TYPE_SAMPLER: + case GLSL_TYPE_IMAGE: dst[i].f = (float) src[i].i; break; case GLSL_TYPE_BOOL: diff --git a/mesalib/src/mesa/main/varray.c b/mesalib/src/mesa/main/varray.c index 42e7f89b2..da6bbce52 100644 --- a/mesalib/src/mesa/main/varray.c +++ b/mesalib/src/mesa/main/varray.c @@ -66,6 +66,21 @@ #define UNSIGNED_INT_10F_11F_11F_REV_BIT (1 << 14) #define ALL_TYPE_BITS ((1 << 15) - 1) +#define ATTRIB_FORMAT_TYPES_MASK (BYTE_BIT | UNSIGNED_BYTE_BIT | \ + SHORT_BIT | UNSIGNED_SHORT_BIT | \ + INT_BIT | UNSIGNED_INT_BIT | \ + HALF_BIT | FLOAT_BIT | DOUBLE_BIT | \ + FIXED_GL_BIT | \ + UNSIGNED_INT_2_10_10_10_REV_BIT | \ + INT_2_10_10_10_REV_BIT | \ + UNSIGNED_INT_10F_11F_11F_REV_BIT) + +#define ATTRIB_IFORMAT_TYPES_MASK (BYTE_BIT | UNSIGNED_BYTE_BIT | \ + SHORT_BIT | UNSIGNED_SHORT_BIT | \ + INT_BIT | UNSIGNED_INT_BIT) + +#define ATTRIB_LFORMAT_TYPES_MASK DOUBLE_BIT + /** Convert GL datatype enum into a <type>_BIT value seen above */ static GLbitfield @@ -113,10 +128,11 @@ type_to_bit(const struct gl_context *ctx, GLenum type) * Sets the VertexBinding field in the vertex attribute given by attribIndex. */ static void -vertex_attrib_binding(struct gl_context *ctx, GLuint attribIndex, +vertex_attrib_binding(struct gl_context *ctx, + struct gl_vertex_array_object *vao, + GLuint attribIndex, GLuint bindingIndex) { - struct gl_vertex_array_object *vao = ctx->Array.VAO; struct gl_vertex_attrib_array *array = &vao->VertexAttrib[attribIndex]; if (array->VertexBinding != bindingIndex) { @@ -139,11 +155,12 @@ vertex_attrib_binding(struct gl_context *ctx, GLuint attribIndex, * and sets the Offset and Stride fields. */ static void -bind_vertex_buffer(struct gl_context *ctx, GLuint index, +bind_vertex_buffer(struct gl_context *ctx, + struct gl_vertex_array_object *vao, + GLuint index, struct gl_buffer_object *vbo, GLintptr offset, GLsizei stride) { - struct gl_vertex_array_object *vao = ctx->Array.VAO; struct gl_vertex_buffer_binding *binding = &vao->VertexBinding[index]; if (binding->BufferObj != vbo || @@ -167,10 +184,11 @@ bind_vertex_buffer(struct gl_context *ctx, GLuint index, * given by bindingIndex. */ static void -vertex_binding_divisor(struct gl_context *ctx, GLuint bindingIndex, +vertex_binding_divisor(struct gl_context *ctx, + struct gl_vertex_array_object *vao, + GLuint bindingIndex, GLuint divisor) { - struct gl_vertex_array_object *vao = ctx->Array.VAO; struct gl_vertex_buffer_binding *binding = &vao->VertexBinding[bindingIndex]; @@ -243,15 +261,17 @@ get_legal_types_mask(const struct gl_context *ctx) * \param type Datatype of each component (GL_FLOAT, GL_INT, etc) * \param normalized Whether integer types are converted to floats in [-1, 1] * \param integer Integer-valued values (will not be normalized to [-1, 1]) + * \param doubles Double values not reduced to floats * \param relativeOffset Offset of the first element relative to the binding offset. */ static bool update_array_format(struct gl_context *ctx, const char *func, + struct gl_vertex_array_object *vao, GLuint attrib, GLbitfield legalTypesMask, GLint sizeMin, GLint sizeMax, GLint size, GLenum type, - GLboolean normalized, GLboolean integer, + GLboolean normalized, GLboolean integer, GLboolean doubles, GLuint relativeOffset) { struct gl_vertex_attrib_array *array; @@ -362,16 +382,17 @@ update_array_format(struct gl_context *ctx, elementSize = _mesa_bytes_per_vertex_attrib(size, type); assert(elementSize != -1); - array = &ctx->Array.VAO->VertexAttrib[attrib]; + array = &vao->VertexAttrib[attrib]; array->Size = size; array->Type = type; array->Format = format; array->Normalized = normalized; array->Integer = integer; + array->Doubles = doubles; array->RelativeOffset = relativeOffset; array->_ElementSize = elementSize; - ctx->Array.VAO->NewArrays |= VERT_BIT(attrib); + vao->NewArrays |= VERT_BIT(attrib); ctx->NewState |= _NEW_ARRAY; return true; @@ -392,6 +413,7 @@ update_array_format(struct gl_context *ctx, * \param stride stride between elements, in elements * \param normalized are integer types converted to floats in [-1, 1]? * \param integer integer-valued values (will not be normalized to [-1,1]) + * \param doubles Double values not reduced to floats * \param ptr the address (or offset inside VBO) of the array data */ static void @@ -400,7 +422,7 @@ update_array(struct gl_context *ctx, GLuint attrib, GLbitfield legalTypesMask, GLint sizeMin, GLint sizeMax, GLint size, GLenum type, GLsizei stride, - GLboolean normalized, GLboolean integer, + GLboolean normalized, GLboolean integer, GLboolean doubles, const GLvoid *ptr) { struct gl_vertex_attrib_array *array; @@ -453,13 +475,14 @@ update_array(struct gl_context *ctx, return; } - if (!update_array_format(ctx, func, attrib, legalTypesMask, sizeMin, - sizeMax, size, type, normalized, integer, 0)) { + if (!update_array_format(ctx, func, ctx->Array.VAO, attrib, + legalTypesMask, sizeMin, sizeMax, + size, type, normalized, integer, doubles, 0)) { return; } /* Reset the vertex attrib binding */ - vertex_attrib_binding(ctx, attrib, attrib); + vertex_attrib_binding(ctx, ctx->Array.VAO, attrib, attrib); /* The Stride and Ptr fields are not set by update_array_format() */ array = &ctx->Array.VAO->VertexAttrib[attrib]; @@ -468,7 +491,7 @@ update_array(struct gl_context *ctx, /* Update the vertex buffer binding */ effectiveStride = stride != 0 ? stride : array->_ElementSize; - bind_vertex_buffer(ctx, attrib, ctx->Array.ArrayBufferObj, + bind_vertex_buffer(ctx, ctx->Array.VAO, attrib, ctx->Array.ArrayBufferObj, (GLintptr) ptr, effectiveStride); } @@ -488,7 +511,7 @@ _mesa_VertexPointer(GLint size, GLenum type, GLsizei stride, const GLvoid *ptr) update_array(ctx, "glVertexPointer", VERT_ATTRIB_POS, legalTypes, 2, 4, - size, type, stride, GL_FALSE, GL_FALSE, ptr); + size, type, stride, GL_FALSE, GL_FALSE, GL_FALSE, ptr); } @@ -507,7 +530,7 @@ _mesa_NormalPointer(GLenum type, GLsizei stride, const GLvoid *ptr ) update_array(ctx, "glNormalPointer", VERT_ATTRIB_NORMAL, legalTypes, 3, 3, - 3, type, stride, GL_TRUE, GL_FALSE, ptr); + 3, type, stride, GL_TRUE, GL_FALSE, GL_FALSE, ptr); } @@ -529,7 +552,7 @@ _mesa_ColorPointer(GLint size, GLenum type, GLsizei stride, const GLvoid *ptr) update_array(ctx, "glColorPointer", VERT_ATTRIB_COLOR0, legalTypes, sizeMin, BGRA_OR_4, - size, type, stride, GL_TRUE, GL_FALSE, ptr); + size, type, stride, GL_TRUE, GL_FALSE, GL_FALSE, ptr); } @@ -543,7 +566,7 @@ _mesa_FogCoordPointer(GLenum type, GLsizei stride, const GLvoid *ptr) update_array(ctx, "glFogCoordPointer", VERT_ATTRIB_FOG, legalTypes, 1, 1, - 1, type, stride, GL_FALSE, GL_FALSE, ptr); + 1, type, stride, GL_FALSE, GL_FALSE, GL_FALSE, ptr); } @@ -558,7 +581,7 @@ _mesa_IndexPointer(GLenum type, GLsizei stride, const GLvoid *ptr) update_array(ctx, "glIndexPointer", VERT_ATTRIB_COLOR_INDEX, legalTypes, 1, 1, - 1, type, stride, GL_FALSE, GL_FALSE, ptr); + 1, type, stride, GL_FALSE, GL_FALSE, GL_FALSE, ptr); } @@ -578,7 +601,7 @@ _mesa_SecondaryColorPointer(GLint size, GLenum type, update_array(ctx, "glSecondaryColorPointer", VERT_ATTRIB_COLOR1, legalTypes, 3, BGRA_OR_4, - size, type, stride, GL_TRUE, GL_FALSE, ptr); + size, type, stride, GL_TRUE, GL_FALSE, GL_FALSE, ptr); } @@ -600,7 +623,7 @@ _mesa_TexCoordPointer(GLint size, GLenum type, GLsizei stride, update_array(ctx, "glTexCoordPointer", VERT_ATTRIB_TEX(unit), legalTypes, sizeMin, 4, - size, type, stride, GL_FALSE, GL_FALSE, + size, type, stride, GL_FALSE, GL_FALSE, GL_FALSE, ptr); } @@ -617,7 +640,7 @@ _mesa_EdgeFlagPointer(GLsizei stride, const GLvoid *ptr) update_array(ctx, "glEdgeFlagPointer", VERT_ATTRIB_EDGEFLAG, legalTypes, 1, 1, - 1, GL_UNSIGNED_BYTE, stride, GL_FALSE, integer, ptr); + 1, GL_UNSIGNED_BYTE, stride, GL_FALSE, integer, GL_FALSE, ptr); } @@ -637,7 +660,7 @@ _mesa_PointSizePointerOES(GLenum type, GLsizei stride, const GLvoid *ptr) update_array(ctx, "glPointSizePointer", VERT_ATTRIB_POINT_SIZE, legalTypes, 1, 1, - 1, type, stride, GL_FALSE, GL_FALSE, ptr); + 1, type, stride, GL_FALSE, GL_FALSE, GL_FALSE, ptr); } @@ -668,7 +691,7 @@ _mesa_VertexAttribPointer(GLuint index, GLint size, GLenum type, update_array(ctx, "glVertexAttribPointer", VERT_ATTRIB_GENERIC(index), legalTypes, 1, BGRA_OR_4, - size, type, stride, normalized, GL_FALSE, ptr); + size, type, stride, normalized, GL_FALSE, GL_FALSE, ptr); } @@ -696,24 +719,36 @@ _mesa_VertexAttribIPointer(GLuint index, GLint size, GLenum type, update_array(ctx, "glVertexAttribIPointer", VERT_ATTRIB_GENERIC(index), legalTypes, 1, 4, - size, type, stride, normalized, integer, ptr); + size, type, stride, normalized, integer, GL_FALSE, ptr); } - - void GLAPIENTRY -_mesa_EnableVertexAttribArray(GLuint index) +_mesa_VertexAttribLPointer(GLuint index, GLint size, GLenum type, + GLsizei stride, const GLvoid *ptr) { - struct gl_vertex_array_object *vao; GET_CURRENT_CONTEXT(ctx); - + const GLbitfield legalTypes = (DOUBLE_BIT); if (index >= ctx->Const.Program[MESA_SHADER_VERTEX].MaxAttribs) { - _mesa_error(ctx, GL_INVALID_VALUE, - "glEnableVertexAttribArrayARB(index)"); + _mesa_error(ctx, GL_INVALID_VALUE, "glVertexAttribLPointer(index)"); return; } - vao = ctx->Array.VAO; + update_array(ctx, "glVertexAttribLPointer", VERT_ATTRIB_GENERIC(index), + legalTypes, 1, 4, + size, type, stride, GL_TRUE, GL_FALSE, GL_TRUE, ptr); +} + + +static void +enable_vertex_array_attrib(struct gl_context *ctx, + struct gl_vertex_array_object *vao, + GLuint index, + const char *func) +{ + if (index >= ctx->Const.Program[MESA_SHADER_VERTEX].MaxAttribs) { + _mesa_error(ctx, GL_INVALID_VALUE, "%s(index)", func); + return; + } assert(VERT_ATTRIB_GENERIC(index) < ARRAY_SIZE(vao->VertexAttrib)); @@ -728,18 +763,52 @@ _mesa_EnableVertexAttribArray(GLuint index) void GLAPIENTRY -_mesa_DisableVertexAttribArray(GLuint index) +_mesa_EnableVertexAttribArray(GLuint index) { - struct gl_vertex_array_object *vao; GET_CURRENT_CONTEXT(ctx); + enable_vertex_array_attrib(ctx, ctx->Array.VAO, index, + "glEnableVertexAttribArray"); +} - if (index >= ctx->Const.Program[MESA_SHADER_VERTEX].MaxAttribs) { - _mesa_error(ctx, GL_INVALID_VALUE, - "glDisableVertexAttribArrayARB(index)"); + +void GLAPIENTRY +_mesa_EnableVertexArrayAttrib(GLuint vaobj, GLuint index) +{ + GET_CURRENT_CONTEXT(ctx); + struct gl_vertex_array_object *vao; + + if (!ctx->Extensions.ARB_direct_state_access) { + _mesa_error(ctx, GL_INVALID_OPERATION, + "glEnableVertexArrayAttrib(GL_ARB_direct_state_access " + "is not supported"); return; } - vao = ctx->Array.VAO; + /* The ARB_direct_state_access specification says: + * + * "An INVALID_OPERATION error is generated by EnableVertexArrayAttrib + * and DisableVertexArrayAttrib if <vaobj> is not + * [compatibility profile: zero or] the name of an existing vertex + * array object." + */ + vao = _mesa_lookup_vao_err(ctx, vaobj, "glEnableVertexArrayAttrib"); + if (!vao) + return; + + enable_vertex_array_attrib(ctx, vao, index, "glEnableVertexArrayAttrib"); +} + + +static void +disable_vertex_array_attrib(struct gl_context *ctx, + struct gl_vertex_array_object *vao, + GLuint index, + const char *func) +{ + if (index >= ctx->Const.Program[MESA_SHADER_VERTEX].MaxAttribs) { + _mesa_error(ctx, GL_INVALID_VALUE, "%s(index)", func); + return; + } assert(VERT_ATTRIB_GENERIC(index) < ARRAY_SIZE(vao->VertexAttrib)); @@ -753,16 +822,54 @@ _mesa_DisableVertexAttribArray(GLuint index) } +void GLAPIENTRY +_mesa_DisableVertexAttribArray(GLuint index) +{ + GET_CURRENT_CONTEXT(ctx); + disable_vertex_array_attrib(ctx, ctx->Array.VAO, index, + "glDisableVertexAttribArray"); +} + + +void GLAPIENTRY +_mesa_DisableVertexArrayAttrib(GLuint vaobj, GLuint index) +{ + GET_CURRENT_CONTEXT(ctx); + struct gl_vertex_array_object *vao; + + if (!ctx->Extensions.ARB_direct_state_access) { + _mesa_error(ctx, GL_INVALID_OPERATION, + "glDisableVertexArrayAttrib(GL_ARB_direct_state_access " + "is not supported"); + return; + } + + /* The ARB_direct_state_access specification says: + * + * "An INVALID_OPERATION error is generated by EnableVertexArrayAttrib + * and DisableVertexArrayAttrib if <vaobj> is not + * [compatibility profile: zero or] the name of an existing vertex + * array object." + */ + vao = _mesa_lookup_vao_err(ctx, vaobj, "glDisableVertexArrayAttrib"); + if (!vao) + return; + + disable_vertex_array_attrib(ctx, vao, index, "glDisableVertexArrayAttrib"); +} + + /** * Return info for a vertex attribute array (no alias with legacy * vertex attributes (pos, normal, color, etc)). This function does * not handle the 4-element GL_CURRENT_VERTEX_ATTRIB_ARB query. */ static GLuint -get_vertex_array_attrib(struct gl_context *ctx, GLuint index, GLenum pname, - const char *caller) +get_vertex_array_attrib(struct gl_context *ctx, + const struct gl_vertex_array_object *vao, + GLuint index, GLenum pname, + const char *caller) { - const struct gl_vertex_array_object *vao = ctx->Array.VAO; const struct gl_vertex_attrib_array *array; if (index >= ctx->Const.Program[MESA_SHADER_VERTEX].MaxAttribs) { @@ -794,6 +901,11 @@ get_vertex_array_attrib(struct gl_context *ctx, GLuint index, GLenum pname, return array->Integer; } goto error; + case GL_VERTEX_ATTRIB_ARRAY_LONG: + if (_mesa_is_desktop_gl(ctx)) { + return array->Doubles; + } + goto error; case GL_VERTEX_ATTRIB_ARRAY_DIVISOR_ARB: if ((_mesa_is_desktop_gl(ctx) && ctx->Extensions.ARB_instanced_arrays) || _mesa_is_gles3(ctx)) { @@ -853,7 +965,8 @@ _mesa_GetVertexAttribfv(GLuint index, GLenum pname, GLfloat *params) } } else { - params[0] = (GLfloat) get_vertex_array_attrib(ctx, index, pname, + params[0] = (GLfloat) get_vertex_array_attrib(ctx, ctx->Array.VAO, + index, pname, "glGetVertexAttribfv"); } } @@ -874,11 +987,32 @@ _mesa_GetVertexAttribdv(GLuint index, GLenum pname, GLdouble *params) } } else { - params[0] = (GLdouble) get_vertex_array_attrib(ctx, index, pname, + params[0] = (GLdouble) get_vertex_array_attrib(ctx, ctx->Array.VAO, + index, pname, "glGetVertexAttribdv"); } } +void GLAPIENTRY +_mesa_GetVertexAttribLdv(GLuint index, GLenum pname, GLdouble *params) +{ + GET_CURRENT_CONTEXT(ctx); + + if (pname == GL_CURRENT_VERTEX_ATTRIB_ARB) { + const GLdouble *v = (const GLdouble *)get_current_attrib(ctx, index, "glGetVertexAttribLdv"); + if (v != NULL) { + params[0] = v[0]; + params[1] = v[1]; + params[2] = v[2]; + params[3] = v[3]; + } + } + else { + params[0] = (GLdouble) get_vertex_array_attrib(ctx, ctx->Array.VAO, + index, pname, + "glGetVertexAttribLdv"); + } +} void GLAPIENTRY _mesa_GetVertexAttribiv(GLuint index, GLenum pname, GLint *params) @@ -896,7 +1030,8 @@ _mesa_GetVertexAttribiv(GLuint index, GLenum pname, GLint *params) } } else { - params[0] = (GLint) get_vertex_array_attrib(ctx, index, pname, + params[0] = (GLint) get_vertex_array_attrib(ctx, ctx->Array.VAO, + index, pname, "glGetVertexAttribiv"); } } @@ -916,7 +1051,8 @@ _mesa_GetVertexAttribIiv(GLuint index, GLenum pname, GLint *params) } } else { - params[0] = (GLint) get_vertex_array_attrib(ctx, index, pname, + params[0] = (GLint) get_vertex_array_attrib(ctx, ctx->Array.VAO, + index, pname, "glGetVertexAttribIiv"); } } @@ -936,7 +1072,8 @@ _mesa_GetVertexAttribIuiv(GLuint index, GLenum pname, GLuint *params) } } else { - params[0] = get_vertex_array_attrib(ctx, index, pname, + params[0] = get_vertex_array_attrib(ctx, ctx->Array.VAO, + index, pname, "glGetVertexAttribIuiv"); } } @@ -963,6 +1100,138 @@ _mesa_GetVertexAttribPointerv(GLuint index, GLenum pname, GLvoid **pointer) } +/** ARB_direct_state_access */ +void GLAPIENTRY +_mesa_GetVertexArrayIndexediv(GLuint vaobj, GLuint index, + GLenum pname, GLint *params) +{ + GET_CURRENT_CONTEXT(ctx); + struct gl_vertex_array_object *vao; + + if (!ctx->Extensions.ARB_direct_state_access) { + _mesa_error(ctx, GL_INVALID_OPERATION, + "glGetVertexArrayIndexediv(GL_ARB_direct_state_access " + "is not supported"); + return; + } + + /* The ARB_direct_state_access specification says: + * + * "An INVALID_OPERATION error is generated if <vaobj> is not + * [compatibility profile: zero or] the name of an existing + * vertex array object." + */ + vao = _mesa_lookup_vao_err(ctx, vaobj, "glGetVertexArrayIndexediv"); + if (!vao) + return; + + /* The ARB_direct_state_access specification says: + * + * "For GetVertexArrayIndexediv, <pname> must be one of + * VERTEX_ATTRIB_ARRAY_ENABLED, VERTEX_ATTRIB_ARRAY_SIZE, + * VERTEX_ATTRIB_ARRAY_STRIDE, VERTEX_ATTRIB_ARRAY_TYPE, + * VERTEX_ATTRIB_ARRAY_NORMALIZED, VERTEX_ATTRIB_ARRAY_INTEGER, + * VERTEX_ATTRIB_ARRAY_LONG, VERTEX_ATTRIB_ARRAY_DIVISOR, or + * VERTEX_ATTRIB_RELATIVE_OFFSET." + * + * and: + * + * "Add GetVertexArrayIndexediv in 'Get Command' for + * VERTEX_ATTRIB_ARRAY_BUFFER_BINDING + * VERTEX_ATTRIB_BINDING, + * VERTEX_ATTRIB_RELATIVE_OFFSET, + * VERTEX_BINDING_OFFSET, and + * VERTEX_BINDING_STRIDE states" + * + * The only parameter name common to both lists is + * VERTEX_ATTRIB_RELATIVE_OFFSET. Also note that VERTEX_BINDING_BUFFER + * and VERTEX_BINDING_DIVISOR are missing from both lists. It seems + * pretty clear however that the intent is that it should be possible + * to query all vertex attrib and binding states that can be set with + * a DSA function. + */ + switch (pname) { + case GL_VERTEX_BINDING_OFFSET: + params[0] = vao->VertexBinding[VERT_ATTRIB_GENERIC(index)].Offset; + break; + case GL_VERTEX_BINDING_STRIDE: + params[0] = vao->VertexBinding[VERT_ATTRIB_GENERIC(index)].Stride; + break; + case GL_VERTEX_BINDING_DIVISOR: + params[0] = vao->VertexBinding[VERT_ATTRIB_GENERIC(index)].InstanceDivisor; + break; + case GL_VERTEX_BINDING_BUFFER: + params[0] = vao->VertexBinding[VERT_ATTRIB_GENERIC(index)].BufferObj->Name; + break; + default: + params[0] = get_vertex_array_attrib(ctx, vao, index, pname, + "glGetVertexArrayIndexediv"); + break; + } +} + + +void GLAPIENTRY +_mesa_GetVertexArrayIndexed64iv(GLuint vaobj, GLuint index, + GLenum pname, GLint64 *params) +{ + GET_CURRENT_CONTEXT(ctx); + struct gl_vertex_array_object *vao; + + if (!ctx->Extensions.ARB_direct_state_access) { + _mesa_error(ctx, GL_INVALID_OPERATION, + "glGetVertexArrayIndexed64iv(GL_ARB_direct_state_access " + "is not supported"); + return; + } + + + /* The ARB_direct_state_access specification says: + * + * "An INVALID_OPERATION error is generated if <vaobj> is not + * [compatibility profile: zero or] the name of an existing + * vertex array object." + */ + vao = _mesa_lookup_vao_err(ctx, vaobj, "glGetVertexArrayIndexed64iv"); + if (!vao) + return; + + /* The ARB_direct_state_access specification says: + * + * "For GetVertexArrayIndexed64iv, <pname> must be + * VERTEX_BINDING_OFFSET." + * + * and: + * + * "An INVALID_ENUM error is generated if <pname> is not one of + * the valid values listed above for the corresponding command." + */ + if (pname != GL_VERTEX_BINDING_OFFSET) { + _mesa_error(ctx, GL_INVALID_ENUM, "glGetVertexArrayIndexed64iv(" + "pname != GL_VERTEX_BINDING_OFFSET)"); + return; + } + + /* The ARB_direct_state_access specification says: + * + * "An INVALID_VALUE error is generated if <index> is greater than + * or equal to the value of MAX_VERTEX_ATTRIBS." + * + * Since the index refers to a buffer binding in this case, the intended + * limit must be MAX_VERTEX_ATTRIB_BINDINGS. Both limits are currently + * required to be the same, so in practice this doesn't matter. + */ + if (index >= ctx->Const.MaxVertexAttribBindings) { + _mesa_error(ctx, GL_INVALID_VALUE, "glGetVertexArrayIndexed64iv(" + "index %d >= the value of GL_MAX_VERTEX_ATTRIB_BINDINGS (%d))", + index, ctx->Const.MaxVertexAttribBindings); + return; + } + + params[0] = vao->VertexBinding[VERT_ATTRIB_GENERIC(index)].Offset; +} + + void GLAPIENTRY _mesa_VertexPointerEXT(GLint size, GLenum type, GLsizei stride, GLsizei count, const GLvoid *ptr) @@ -1337,6 +1606,7 @@ _mesa_VertexAttribDivisor(GLuint index, GLuint divisor) GET_CURRENT_CONTEXT(ctx); const GLuint genericIndex = VERT_ATTRIB_GENERIC(index); + struct gl_vertex_array_object * const vao = ctx->Array.VAO; if (!ctx->Extensions.ARB_instanced_arrays) { _mesa_error(ctx, GL_INVALID_OPERATION, "glVertexAttribDivisor()"); @@ -1349,7 +1619,7 @@ _mesa_VertexAttribDivisor(GLuint index, GLuint divisor) return; } - assert(genericIndex < ARRAY_SIZE(ctx->Array.VAO->VertexAttrib)); + assert(genericIndex < ARRAY_SIZE(vao->VertexAttrib)); /* The ARB_vertex_attrib_binding spec says: * @@ -1362,8 +1632,8 @@ _mesa_VertexAttribDivisor(GLuint index, GLuint divisor) * VertexAttribBinding(index, index); * VertexBindingDivisor(index, divisor);" */ - vertex_attrib_binding(ctx, genericIndex, genericIndex); - vertex_binding_divisor(ctx, genericIndex, divisor); + vertex_attrib_binding(ctx, vao, genericIndex, genericIndex); + vertex_binding_divisor(ctx, vao, genericIndex, divisor); } @@ -1395,38 +1665,25 @@ _mesa_primitive_restart_index(const struct gl_context *ctx, GLenum ib_type) /** * GL_ARB_vertex_attrib_binding */ -void GLAPIENTRY -_mesa_BindVertexBuffer(GLuint bindingIndex, GLuint buffer, GLintptr offset, - GLsizei stride) +static void +vertex_array_vertex_buffer(struct gl_context *ctx, struct gl_vertex_array_object *vao, + GLuint bindingIndex, GLuint buffer, GLintptr offset, + GLsizei stride, const char *func) { - GET_CURRENT_CONTEXT(ctx); - const struct gl_vertex_array_object *vao = ctx->Array.VAO; struct gl_buffer_object *vbo; ASSERT_OUTSIDE_BEGIN_END(ctx); /* The ARB_vertex_attrib_binding spec says: * - * "An INVALID_OPERATION error is generated if no vertex array object - * is bound." - */ - if (ctx->API == API_OPENGL_CORE && - ctx->Array.VAO == ctx->Array.DefaultVAO) { - _mesa_error(ctx, GL_INVALID_OPERATION, - "glBindVertexBuffer(No array object bound)"); - return; - } - - /* The ARB_vertex_attrib_binding spec says: - * * "An INVALID_VALUE error is generated if <bindingindex> is greater than * the value of MAX_VERTEX_ATTRIB_BINDINGS." */ if (bindingIndex >= ctx->Const.MaxVertexAttribBindings) { _mesa_error(ctx, GL_INVALID_VALUE, - "glBindVertexBuffer(bindingindex=%u > " + "%s(bindingindex=%u > " "GL_MAX_VERTEX_ATTRIB_BINDINGS)", - bindingIndex); + func, bindingIndex); return; } @@ -1437,21 +1694,21 @@ _mesa_BindVertexBuffer(GLuint bindingIndex, GLuint buffer, GLintptr offset, */ if (offset < 0) { _mesa_error(ctx, GL_INVALID_VALUE, - "glBindVertexBuffer(offset=%" PRId64 " < 0)", - (int64_t) offset); + "%s(offset=%" PRId64 " < 0)", + func, (int64_t) offset); return; } if (stride < 0) { _mesa_error(ctx, GL_INVALID_VALUE, - "glBindVertexBuffer(stride=%d < 0)", stride); + "%s(stride=%d < 0)", func, stride); return; } if (ctx->API == API_OPENGL_CORE && ctx->Version >= 44 && stride > ctx->Const.MaxVertexAttribStride) { - _mesa_error(ctx, GL_INVALID_VALUE, "glBindVertexBuffer(stride=%d > " - "GL_MAX_VERTEX_ATTRIB_STRIDE)", stride); + _mesa_error(ctx, GL_INVALID_VALUE, "%s(stride=%d > " + "GL_MAX_VERTEX_ATTRIB_STRIDE)", func, stride); return; } @@ -1471,7 +1728,7 @@ _mesa_BindVertexBuffer(GLuint bindingIndex, GLuint buffer, GLintptr offset, * object references (automatically gen it). */ if (!_mesa_handle_bind_buffer_gen(ctx, GL_ARRAY_BUFFER, buffer, - &vbo, "glBindVertexBuffer")) + &vbo, func)) return; } else { /* The ARB_vertex_attrib_binding spec says: @@ -1482,33 +1739,75 @@ _mesa_BindVertexBuffer(GLuint bindingIndex, GLuint buffer, GLintptr offset, vbo = ctx->Shared->NullBufferObj; } - bind_vertex_buffer(ctx, VERT_ATTRIB_GENERIC(bindingIndex), + bind_vertex_buffer(ctx, vao, VERT_ATTRIB_GENERIC(bindingIndex), vbo, offset, stride); } void GLAPIENTRY -_mesa_BindVertexBuffers(GLuint first, GLsizei count, const GLuint *buffers, - const GLintptr *offsets, const GLsizei *strides) +_mesa_BindVertexBuffer(GLuint bindingIndex, GLuint buffer, GLintptr offset, + GLsizei stride) { GET_CURRENT_CONTEXT(ctx); - struct gl_vertex_array_object * const vao = ctx->Array.VAO; - GLuint i; - - ASSERT_OUTSIDE_BEGIN_END(ctx); /* The ARB_vertex_attrib_binding spec says: * - * "An INVALID_OPERATION error is generated if no - * vertex array object is bound." + * "An INVALID_OPERATION error is generated if no vertex array object + * is bound." */ if (ctx->API == API_OPENGL_CORE && ctx->Array.VAO == ctx->Array.DefaultVAO) { _mesa_error(ctx, GL_INVALID_OPERATION, - "glBindVertexBuffers(No array object bound)"); + "glBindVertexBuffer(No array object bound)"); return; } + vertex_array_vertex_buffer(ctx, ctx->Array.VAO, bindingIndex, + buffer, offset, stride, "glBindVertexBuffer"); +} + + +void GLAPIENTRY +_mesa_VertexArrayVertexBuffer(GLuint vaobj, GLuint bindingIndex, GLuint buffer, + GLintptr offset, GLsizei stride) +{ + GET_CURRENT_CONTEXT(ctx); + struct gl_vertex_array_object *vao; + + if (!ctx->Extensions.ARB_direct_state_access) { + _mesa_error(ctx, GL_INVALID_OPERATION, + "glVertexArrayVertexBuffer(GL_ARB_direct_state_access " + "is not supported"); + return; + } + + /* The ARB_direct_state_access specification says: + * + * "An INVALID_OPERATION error is generated by VertexArrayVertexBuffer + * if <vaobj> is not [compatibility profile: zero or] the name of an + * existing vertex array object." + */ + vao = _mesa_lookup_vao_err(ctx, vaobj, "glVertexArrayVertexBuffer"); + if (!vao) + return; + + vertex_array_vertex_buffer(ctx, vao, bindingIndex, + buffer, offset, stride, + "glVertexArrayVertexBuffer"); +} + + +static void +vertex_array_vertex_buffers(struct gl_context *ctx, + struct gl_vertex_array_object *vao, + GLuint first, GLsizei count, const GLuint *buffers, + const GLintptr *offsets, const GLsizei *strides, + const char *func) +{ + GLuint i; + + ASSERT_OUTSIDE_BEGIN_END(ctx); + /* The ARB_multi_bind spec says: * * "An INVALID_OPERATION error is generated if <first> + <count> @@ -1516,9 +1815,9 @@ _mesa_BindVertexBuffers(GLuint first, GLsizei count, const GLuint *buffers, */ if (first + count > ctx->Const.MaxVertexAttribBindings) { _mesa_error(ctx, GL_INVALID_OPERATION, - "glBindVertexBuffers(first=%u + count=%d > the value of " + "%s(first=%u + count=%d > the value of " "GL_MAX_VERTEX_ATTRIB_BINDINGS=%u)", - first, count, ctx->Const.MaxVertexAttribBindings); + func, first, count, ctx->Const.MaxVertexAttribBindings); return; } @@ -1535,7 +1834,8 @@ _mesa_BindVertexBuffers(GLuint first, GLsizei count, const GLuint *buffers, struct gl_buffer_object *vbo = ctx->Shared->NullBufferObj; for (i = 0; i < count; i++) - bind_vertex_buffer(ctx, VERT_ATTRIB_GENERIC(first + i), vbo, 0, 16); + bind_vertex_buffer(ctx, vao, VERT_ATTRIB_GENERIC(first + i), + vbo, 0, 16); return; } @@ -1571,23 +1871,23 @@ _mesa_BindVertexBuffers(GLuint first, GLsizei count, const GLuint *buffers, */ if (offsets[i] < 0) { _mesa_error(ctx, GL_INVALID_VALUE, - "glBindVertexBuffers(offsets[%u]=%" PRId64 " < 0)", - i, (int64_t) offsets[i]); + "%s(offsets[%u]=%" PRId64 " < 0)", + func, i, (int64_t) offsets[i]); continue; } if (strides[i] < 0) { _mesa_error(ctx, GL_INVALID_VALUE, - "glBindVertexBuffers(strides[%u]=%d < 0)", - i, strides[i]); + "%s(strides[%u]=%d < 0)", + func, i, strides[i]); continue; } if (ctx->API == API_OPENGL_CORE && ctx->Version >= 44 && strides[i] > ctx->Const.MaxVertexAttribStride) { _mesa_error(ctx, GL_INVALID_VALUE, - "glBindVertexBuffers(strides[%u]=%d > " - "GL_MAX_VERTEX_ATTRIB_STRIDE)", i, strides[i]); + "%s(strides[%u]=%d > " + "GL_MAX_VERTEX_ATTRIB_STRIDE)", func, i, strides[i]); continue; } @@ -1598,8 +1898,7 @@ _mesa_BindVertexBuffers(GLuint first, GLsizei count, const GLuint *buffers, if (buffers[i] == binding->BufferObj->Name) vbo = binding->BufferObj; else - vbo = _mesa_multi_bind_lookup_bufferobj(ctx, buffers, i, - "glBindVertexBuffers"); + vbo = _mesa_multi_bind_lookup_bufferobj(ctx, buffers, i, func); if (!vbo) continue; @@ -1607,8 +1906,8 @@ _mesa_BindVertexBuffers(GLuint first, GLsizei count, const GLuint *buffers, vbo = ctx->Shared->NullBufferObj; } - bind_vertex_buffer(ctx, VERT_ATTRIB_GENERIC(first + i), vbo, - offsets[i], strides[i]); + bind_vertex_buffer(ctx, vao, VERT_ATTRIB_GENERIC(first + i), + vbo, offsets[i], strides[i]); } _mesa_end_bufferobj_lookups(ctx); @@ -1616,65 +1915,68 @@ _mesa_BindVertexBuffers(GLuint first, GLsizei count, const GLuint *buffers, void GLAPIENTRY -_mesa_VertexAttribFormat(GLuint attribIndex, GLint size, GLenum type, - GLboolean normalized, GLuint relativeOffset) +_mesa_BindVertexBuffers(GLuint first, GLsizei count, const GLuint *buffers, + const GLintptr *offsets, const GLsizei *strides) { - const GLbitfield legalTypes = (BYTE_BIT | UNSIGNED_BYTE_BIT | - SHORT_BIT | UNSIGNED_SHORT_BIT | - INT_BIT | UNSIGNED_INT_BIT | - HALF_BIT | FLOAT_BIT | DOUBLE_BIT | - FIXED_GL_BIT | - UNSIGNED_INT_2_10_10_10_REV_BIT | - INT_2_10_10_10_REV_BIT | - UNSIGNED_INT_10F_11F_11F_REV_BIT); - GET_CURRENT_CONTEXT(ctx); - ASSERT_OUTSIDE_BEGIN_END(ctx); /* The ARB_vertex_attrib_binding spec says: * - * "An INVALID_OPERATION error is generated under any of the following - * conditions: - * - if no vertex array object is currently bound (see section 2.10); - * - ..." + * "An INVALID_OPERATION error is generated if no + * vertex array object is bound." */ if (ctx->API == API_OPENGL_CORE && ctx->Array.VAO == ctx->Array.DefaultVAO) { _mesa_error(ctx, GL_INVALID_OPERATION, - "glVertexAttribFormat(No array object bound)"); + "glBindVertexBuffers(No array object bound)"); return; } - /* The ARB_vertex_attrib_binding spec says: - * - * "The error INVALID_VALUE is generated if index is greater than or equal - * to the value of MAX_VERTEX_ATTRIBS." - */ - if (attribIndex >= ctx->Const.Program[MESA_SHADER_VERTEX].MaxAttribs) { - _mesa_error(ctx, GL_INVALID_VALUE, - "glVertexAttribFormat(attribindex=%u > " - "GL_MAX_VERTEX_ATTRIBS)", - attribIndex); + vertex_array_vertex_buffers(ctx, ctx->Array.VAO, first, count, + buffers, offsets, strides, + "glBindVertexBuffers"); +} + + +void GLAPIENTRY +_mesa_VertexArrayVertexBuffers(GLuint vaobj, GLuint first, GLsizei count, + const GLuint *buffers, + const GLintptr *offsets, const GLsizei *strides) +{ + GET_CURRENT_CONTEXT(ctx); + struct gl_vertex_array_object *vao; + + if (!ctx->Extensions.ARB_direct_state_access) { + _mesa_error(ctx, GL_INVALID_OPERATION, + "glVertexArrayVertexBuffers(GL_ARB_direct_state_access " + "is not supported"); return; } - FLUSH_VERTICES(ctx, 0); - update_array_format(ctx, "glVertexAttribFormat", - VERT_ATTRIB_GENERIC(attribIndex), - legalTypes, 1, BGRA_OR_4, size, type, normalized, - GL_FALSE, relativeOffset); + /* The ARB_direct_state_access specification says: + * + * "An INVALID_OPERATION error is generated by VertexArrayVertexBuffer + * if <vaobj> is not [compatibility profile: zero or] the name of an + * existing vertex array object." + */ + vao = _mesa_lookup_vao_err(ctx, vaobj, "glVertexArrayVertexBuffers"); + if (!vao) + return; + + vertex_array_vertex_buffers(ctx, vao, first, count, + buffers, offsets, strides, + "glVertexArrayVertexBuffers"); } -void GLAPIENTRY -_mesa_VertexAttribIFormat(GLuint attribIndex, GLint size, GLenum type, - GLuint relativeOffset) +static void +vertex_attrib_format(GLuint attribIndex, GLint size, GLenum type, + GLboolean normalized, GLboolean integer, + GLboolean doubles, GLbitfield legalTypes, + GLsizei maxSize, GLuint relativeOffset, + const char *func) { - const GLbitfield legalTypes = (BYTE_BIT | UNSIGNED_BYTE_BIT | - SHORT_BIT | UNSIGNED_SHORT_BIT | - INT_BIT | UNSIGNED_INT_BIT); - GET_CURRENT_CONTEXT(ctx); ASSERT_OUTSIDE_BEGIN_END(ctx); @@ -1684,33 +1986,59 @@ _mesa_VertexAttribIFormat(GLuint attribIndex, GLint size, GLenum type, * conditions: * - if no vertex array object is currently bound (see section 2.10); * - ..." + * + * This error condition only applies to VertexAttribFormat and + * VertexAttribIFormat in the extension spec, but we assume that this + * is an oversight. In the OpenGL 4.3 (Core Profile) spec, it applies + * to all three functions. */ if (ctx->API == API_OPENGL_CORE && ctx->Array.VAO == ctx->Array.DefaultVAO) { _mesa_error(ctx, GL_INVALID_OPERATION, - "glVertexAttribIFormat(No array object bound)"); + "%s(No array object bound)", func); return; } /* The ARB_vertex_attrib_binding spec says: * - * "The error INVALID_VALUE is generated if index is greater than - * or equal to the value of MAX_VERTEX_ATTRIBS." + * "The error INVALID_VALUE is generated if index is greater than or equal + * to the value of MAX_VERTEX_ATTRIBS." */ if (attribIndex >= ctx->Const.Program[MESA_SHADER_VERTEX].MaxAttribs) { _mesa_error(ctx, GL_INVALID_VALUE, - "glVertexAttribIFormat(attribindex=%u > " + "%s(attribindex=%u > " "GL_MAX_VERTEX_ATTRIBS)", - attribIndex); + func, attribIndex); return; } FLUSH_VERTICES(ctx, 0); - update_array_format(ctx, "glVertexAttribIFormat", + update_array_format(ctx, func, ctx->Array.VAO, VERT_ATTRIB_GENERIC(attribIndex), - legalTypes, 1, 4, size, type, GL_FALSE, GL_TRUE, - relativeOffset); + legalTypes, 1, maxSize, size, type, + normalized, integer, doubles, relativeOffset); +} + + +void GLAPIENTRY +_mesa_VertexAttribFormat(GLuint attribIndex, GLint size, GLenum type, + GLboolean normalized, GLuint relativeOffset) +{ + vertex_attrib_format(attribIndex, size, type, normalized, + GL_FALSE, GL_FALSE, ATTRIB_FORMAT_TYPES_MASK, + BGRA_OR_4, relativeOffset, + "glVertexAttribFormat"); +} + + +void GLAPIENTRY +_mesa_VertexAttribIFormat(GLuint attribIndex, GLint size, GLenum type, + GLuint relativeOffset) +{ + vertex_attrib_format(attribIndex, size, type, GL_FALSE, + GL_TRUE, GL_FALSE, ATTRIB_IFORMAT_TYPES_MASK, 4, + relativeOffset, "glVertexAttribIFormat"); } @@ -1718,67 +2046,104 @@ void GLAPIENTRY _mesa_VertexAttribLFormat(GLuint attribIndex, GLint size, GLenum type, GLuint relativeOffset) { - const GLbitfield legalTypes = DOUBLE_BIT; + vertex_attrib_format(attribIndex, size, type, GL_FALSE, GL_FALSE, + GL_TRUE, ATTRIB_LFORMAT_TYPES_MASK, 4, + relativeOffset, "glVertexAttribLFormat"); +} + +static void +vertex_array_attrib_format(GLuint vaobj, GLuint attribIndex, GLint size, + GLenum type, GLboolean normalized, + GLboolean integer, GLboolean doubles, + GLbitfield legalTypes, GLsizei maxSize, + GLuint relativeOffset, const char *func) +{ GET_CURRENT_CONTEXT(ctx); + struct gl_vertex_array_object *vao; + + if (!ctx->Extensions.ARB_direct_state_access) { + _mesa_error(ctx, GL_INVALID_OPERATION, + "%s(GL_ARB_direct_state_access is not supported", func); + return; + } + ASSERT_OUTSIDE_BEGIN_END(ctx); - /* Page 298 of the PDF of the OpenGL 4.3 (Core Profile) spec says: - * - * "An INVALID_OPERATION error is generated under any of the following - * conditions: - * • if no vertex array object is currently bound (see section 10.4); - * • ..." + /* The ARB_direct_state_access spec says: * - * This language is missing from the extension spec, but we assume - * that this is an oversight. + * "An INVALID_OPERATION error is generated by VertexArrayAttrib*Format + * if <vaobj> is not [compatibility profile: zero or] the name of an + * existing vertex array object." */ - if (ctx->API == API_OPENGL_CORE && - ctx->Array.VAO == ctx->Array.DefaultVAO) { - _mesa_error(ctx, GL_INVALID_OPERATION, - "glVertexAttribLFormat(No array object bound)"); + vao = _mesa_lookup_vao_err(ctx, vaobj, func); + if (!vao) return; - } /* The ARB_vertex_attrib_binding spec says: * - * "The error INVALID_VALUE is generated if <attribindex> is greater than - * or equal to the value of MAX_VERTEX_ATTRIBS." + * "The error INVALID_VALUE is generated if index is greater than or equal + * to the value of MAX_VERTEX_ATTRIBS." */ if (attribIndex >= ctx->Const.Program[MESA_SHADER_VERTEX].MaxAttribs) { _mesa_error(ctx, GL_INVALID_VALUE, - "glVertexAttribLFormat(attribindex=%u > " - "GL_MAX_VERTEX_ATTRIBS)", - attribIndex); + "%s(attribindex=%u > GL_MAX_VERTEX_ATTRIBS)", + func, attribIndex); return; } FLUSH_VERTICES(ctx, 0); - update_array_format(ctx, "glVertexAttribLFormat", + update_array_format(ctx, func, vao, VERT_ATTRIB_GENERIC(attribIndex), - legalTypes, 1, 4, size, type, GL_FALSE, GL_FALSE, - relativeOffset); + legalTypes, 1, maxSize, size, type, normalized, + integer, doubles, relativeOffset); } void GLAPIENTRY -_mesa_VertexAttribBinding(GLuint attribIndex, GLuint bindingIndex) +_mesa_VertexArrayAttribFormat(GLuint vaobj, GLuint attribIndex, GLint size, + GLenum type, GLboolean normalized, + GLuint relativeOffset) { - GET_CURRENT_CONTEXT(ctx); - ASSERT_OUTSIDE_BEGIN_END(ctx); + vertex_array_attrib_format(vaobj, attribIndex, size, type, normalized, + GL_FALSE, GL_FALSE, ATTRIB_FORMAT_TYPES_MASK, + BGRA_OR_4, relativeOffset, + "glVertexArrayAttribFormat"); +} - /* The ARB_vertex_attrib_binding spec says: - * - * "An INVALID_OPERATION error is generated if no vertex array object - * is bound." - */ - if (ctx->API == API_OPENGL_CORE && - ctx->Array.VAO == ctx->Array.DefaultVAO) { - _mesa_error(ctx, GL_INVALID_OPERATION, - "glVertexAttribBinding(No array object bound)"); - return; - } + +void GLAPIENTRY +_mesa_VertexArrayAttribIFormat(GLuint vaobj, GLuint attribIndex, + GLint size, GLenum type, + GLuint relativeOffset) +{ + vertex_array_attrib_format(vaobj, attribIndex, size, type, GL_FALSE, + GL_TRUE, GL_FALSE, ATTRIB_IFORMAT_TYPES_MASK, + 4, relativeOffset, + "glVertexArrayAttribIFormat"); +} + + +void GLAPIENTRY +_mesa_VertexArrayAttribLFormat(GLuint vaobj, GLuint attribIndex, + GLint size, GLenum type, + GLuint relativeOffset) +{ + vertex_array_attrib_format(vaobj, attribIndex, size, type, GL_FALSE, + GL_FALSE, GL_TRUE, ATTRIB_LFORMAT_TYPES_MASK, + 4, relativeOffset, + "glVertexArrayAttribLFormat"); +} + + +static void +vertex_array_attrib_binding(struct gl_context *ctx, + struct gl_vertex_array_object *vao, + GLuint attribIndex, GLuint bindingIndex, + const char *func) +{ + ASSERT_OUTSIDE_BEGIN_END(ctx); /* The ARB_vertex_attrib_binding spec says: * @@ -1789,38 +2154,32 @@ _mesa_VertexAttribBinding(GLuint attribIndex, GLuint bindingIndex) */ if (attribIndex >= ctx->Const.Program[MESA_SHADER_VERTEX].MaxAttribs) { _mesa_error(ctx, GL_INVALID_VALUE, - "glVertexAttribBinding(attribindex=%u >= " + "%s(attribindex=%u >= " "GL_MAX_VERTEX_ATTRIBS)", - attribIndex); + func, attribIndex); return; } if (bindingIndex >= ctx->Const.MaxVertexAttribBindings) { _mesa_error(ctx, GL_INVALID_VALUE, - "glVertexAttribBinding(bindingindex=%u >= " + "%s(bindingindex=%u >= " "GL_MAX_VERTEX_ATTRIB_BINDINGS)", - bindingIndex); + func, bindingIndex); return; } - assert(VERT_ATTRIB_GENERIC(attribIndex) < - ARRAY_SIZE(ctx->Array.VAO->VertexAttrib)); + assert(VERT_ATTRIB_GENERIC(attribIndex) < ARRAY_SIZE(vao->VertexAttrib)); - vertex_attrib_binding(ctx, VERT_ATTRIB_GENERIC(attribIndex), + vertex_attrib_binding(ctx, vao, + VERT_ATTRIB_GENERIC(attribIndex), VERT_ATTRIB_GENERIC(bindingIndex)); } void GLAPIENTRY -_mesa_VertexBindingDivisor(GLuint bindingIndex, GLuint divisor) +_mesa_VertexAttribBinding(GLuint attribIndex, GLuint bindingIndex) { GET_CURRENT_CONTEXT(ctx); - ASSERT_OUTSIDE_BEGIN_END(ctx); - - if (!ctx->Extensions.ARB_instanced_arrays) { - _mesa_error(ctx, GL_INVALID_OPERATION, "glVertexBindingDivisor()"); - return; - } /* The ARB_vertex_attrib_binding spec says: * @@ -1830,7 +2189,54 @@ _mesa_VertexBindingDivisor(GLuint bindingIndex, GLuint divisor) if (ctx->API == API_OPENGL_CORE && ctx->Array.VAO == ctx->Array.DefaultVAO) { _mesa_error(ctx, GL_INVALID_OPERATION, - "glVertexBindingDivisor(No array object bound)"); + "glVertexAttribBinding(No array object bound)"); + return; + } + + vertex_array_attrib_binding(ctx, ctx->Array.VAO, + attribIndex, bindingIndex, + "glVertexAttribBinding"); +} + + +void GLAPIENTRY +_mesa_VertexArrayAttribBinding(GLuint vaobj, GLuint attribIndex, GLuint bindingIndex) +{ + GET_CURRENT_CONTEXT(ctx); + struct gl_vertex_array_object *vao; + + if (!ctx->Extensions.ARB_direct_state_access) { + _mesa_error(ctx, GL_INVALID_OPERATION, + "glVertexArrayAttribBinding(GL_ARB_direct_state_access " + "is not supported"); + return; + } + + /* The ARB_direct_state_access specification says: + * + * "An INVALID_OPERATION error is generated by VertexArrayAttribBinding + * if <vaobj> is not [compatibility profile: zero or] the name of an + * existing vertex array object." + */ + vao = _mesa_lookup_vao_err(ctx, vaobj, "glVertexArrayAttribBinding"); + if (!vao) + return; + + vertex_array_attrib_binding(ctx, vao, attribIndex, bindingIndex, + "glVertexArrayAttribBinding"); +} + + +static void +vertex_array_binding_divisor(struct gl_context *ctx, + struct gl_vertex_array_object *vao, + GLuint bindingIndex, GLuint divisor, + const char *func) +{ + ASSERT_OUTSIDE_BEGIN_END(ctx); + + if (!ctx->Extensions.ARB_instanced_arrays) { + _mesa_error(ctx, GL_INVALID_OPERATION, "%s()", func); return; } @@ -1841,13 +2247,64 @@ _mesa_VertexBindingDivisor(GLuint bindingIndex, GLuint divisor) */ if (bindingIndex >= ctx->Const.MaxVertexAttribBindings) { _mesa_error(ctx, GL_INVALID_VALUE, - "glVertexBindingDivisor(bindingindex=%u > " + "%s(bindingindex=%u > " "GL_MAX_VERTEX_ATTRIB_BINDINGS)", - bindingIndex); + func, bindingIndex); return; } - vertex_binding_divisor(ctx, VERT_ATTRIB_GENERIC(bindingIndex), divisor); + vertex_binding_divisor(ctx, vao, VERT_ATTRIB_GENERIC(bindingIndex), divisor); +} + + +void GLAPIENTRY +_mesa_VertexBindingDivisor(GLuint bindingIndex, GLuint divisor) +{ + GET_CURRENT_CONTEXT(ctx); + + /* The ARB_vertex_attrib_binding spec says: + * + * "An INVALID_OPERATION error is generated if no vertex array object + * is bound." + */ + if (ctx->API == API_OPENGL_CORE && + ctx->Array.VAO == ctx->Array.DefaultVAO) { + _mesa_error(ctx, GL_INVALID_OPERATION, + "glVertexBindingDivisor(No array object bound)"); + return; + } + + vertex_array_binding_divisor(ctx, ctx->Array.VAO, + bindingIndex, divisor, + "glVertexBindingDivisor"); +} + + +void GLAPIENTRY +_mesa_VertexArrayBindingDivisor(GLuint vaobj, GLuint bindingIndex, GLuint divisor) +{ + struct gl_vertex_array_object *vao; + GET_CURRENT_CONTEXT(ctx); + + if (!ctx->Extensions.ARB_direct_state_access) { + _mesa_error(ctx, GL_INVALID_OPERATION, + "glVertexArrayBindingDivisor(GL_ARB_direct_state_access " + "is not supported"); + return; + } + + /* The ARB_direct_state_access specification says: + * + * "An INVALID_OPERATION error is generated by VertexArrayBindingDivisor + * if <vaobj> is not [compatibility profile: zero or] the name of an + * existing vertex array object." + */ + vao = _mesa_lookup_vao_err(ctx, vaobj, "glVertexArrayBindingDivisor"); + if (!vao) + return; + + vertex_array_binding_divisor(ctx, vao, bindingIndex, divisor, + "glVertexArrayBindingDivisor"); } @@ -1868,6 +2325,7 @@ _mesa_copy_client_array(struct gl_context *ctx, dst->Enabled = src->Enabled; dst->Normalized = src->Normalized; dst->Integer = src->Integer; + dst->Doubles = src->Doubles; dst->InstanceDivisor = src->InstanceDivisor; dst->_ElementSize = src->_ElementSize; _mesa_reference_buffer_object(ctx, &dst->BufferObj, src->BufferObj); @@ -1885,6 +2343,7 @@ _mesa_copy_vertex_attrib_array(struct gl_context *ctx, dst->RelativeOffset = src->RelativeOffset; dst->Format = src->Format; dst->Integer = src->Integer; + dst->Doubles = src->Doubles; dst->Normalized = src->Normalized; dst->Ptr = src->Ptr; dst->Enabled = src->Enabled; diff --git a/mesalib/src/mesa/main/varray.h b/mesalib/src/mesa/main/varray.h index 4e4bd5f80..5583ed5a1 100644 --- a/mesalib/src/mesa/main/varray.h +++ b/mesalib/src/mesa/main/varray.h @@ -68,6 +68,7 @@ _mesa_update_client_array(struct gl_context *ctx, dst->Enabled = src->Enabled; dst->Normalized = src->Normalized; dst->Integer = src->Integer; + dst->Doubles = src->Doubles; dst->InstanceDivisor = binding->InstanceDivisor; dst->_ElementSize = src->_ElementSize; _mesa_reference_buffer_object(ctx, &dst->BufferObj, binding->BufferObj); @@ -166,22 +167,34 @@ void GLAPIENTRY _mesa_VertexAttribIPointer(GLuint index, GLint size, GLenum type, GLsizei stride, const GLvoid *ptr); +extern void GLAPIENTRY +_mesa_VertexAttribLPointer(GLuint index, GLint size, GLenum type, + GLsizei stride, const GLvoid *pointer); extern void GLAPIENTRY _mesa_EnableVertexAttribArray(GLuint index); extern void GLAPIENTRY +_mesa_EnableVertexArrayAttrib(GLuint vaobj, GLuint index); + + +extern void GLAPIENTRY _mesa_DisableVertexAttribArray(GLuint index); extern void GLAPIENTRY -_mesa_GetVertexAttribdv(GLuint index, GLenum pname, GLdouble *params); +_mesa_DisableVertexArrayAttrib(GLuint vaobj, GLuint index); + +extern void GLAPIENTRY +_mesa_GetVertexAttribdv(GLuint index, GLenum pname, GLdouble *params); extern void GLAPIENTRY _mesa_GetVertexAttribfv(GLuint index, GLenum pname, GLfloat *params); +extern void GLAPIENTRY +_mesa_GetVertexAttribLdv(GLuint index, GLenum pname, GLdouble *params); extern void GLAPIENTRY _mesa_GetVertexAttribiv(GLuint index, GLenum pname, GLint *params); @@ -199,6 +212,16 @@ extern void GLAPIENTRY _mesa_GetVertexAttribPointerv(GLuint index, GLenum pname, GLvoid **pointer); +void GLAPIENTRY +_mesa_GetVertexArrayIndexediv(GLuint vaobj, GLuint index, + GLenum pname, GLint *param); + + +void GLAPIENTRY +_mesa_GetVertexArrayIndexed64iv(GLuint vaobj, GLuint index, + GLenum pname, GLint64 *param); + + extern void GLAPIENTRY _mesa_InterleavedArrays(GLenum format, GLsizei stride, const GLvoid *pointer); @@ -278,27 +301,57 @@ _mesa_BindVertexBuffer(GLuint bindingIndex, GLuint buffer, GLintptr offset, GLsizei stride); extern void GLAPIENTRY +_mesa_VertexArrayVertexBuffer(GLuint vaobj, GLuint bindingIndex, GLuint buffer, + GLintptr offset, GLsizei stride); + +extern void GLAPIENTRY _mesa_BindVertexBuffers(GLuint first, GLsizei count, const GLuint *buffers, const GLintptr *offsets, const GLsizei *strides); extern void GLAPIENTRY +_mesa_VertexArrayVertexBuffers(GLuint vaobj, GLuint first, GLsizei count, + const GLuint *buffers, + const GLintptr *offsets, const GLsizei *strides); + +extern void GLAPIENTRY _mesa_VertexAttribFormat(GLuint attribIndex, GLint size, GLenum type, GLboolean normalized, GLuint relativeOffset); extern void GLAPIENTRY +_mesa_VertexArrayAttribFormat(GLuint vaobj, GLuint attribIndex, GLint size, + GLenum type, GLboolean normalized, + GLuint relativeOffset); + +extern void GLAPIENTRY _mesa_VertexAttribIFormat(GLuint attribIndex, GLint size, GLenum type, GLuint relativeOffset); extern void GLAPIENTRY +_mesa_VertexArrayAttribIFormat(GLuint vaobj, GLuint attribIndex, + GLint size, GLenum type, + GLuint relativeOffset); + +extern void GLAPIENTRY _mesa_VertexAttribLFormat(GLuint attribIndex, GLint size, GLenum type, GLuint relativeOffset); extern void GLAPIENTRY +_mesa_VertexArrayAttribLFormat(GLuint vaobj, GLuint attribIndex, + GLint size, GLenum type, + GLuint relativeOffset); + +extern void GLAPIENTRY _mesa_VertexAttribBinding(GLuint attribIndex, GLuint bindingIndex); extern void GLAPIENTRY +_mesa_VertexArrayAttribBinding(GLuint vaobj, GLuint attribIndex, + GLuint bindingIndex); + +extern void GLAPIENTRY _mesa_VertexBindingDivisor(GLuint bindingIndex, GLuint divisor); +extern void GLAPIENTRY +_mesa_VertexArrayBindingDivisor(GLuint vaobj, GLuint bindingIndex, GLuint divisor); extern void _mesa_copy_client_array(struct gl_context *ctx, diff --git a/mesalib/src/mesa/main/version.c b/mesalib/src/mesa/main/version.c index 5b8ac0a5c..699a0de46 100644 --- a/mesalib/src/mesa/main/version.c +++ b/mesalib/src/mesa/main/version.c @@ -32,23 +32,16 @@ /** * Scans 'string' to see if it ends with 'ending'. */ -static GLboolean +static bool check_for_ending(const char *string, const char *ending) { - int len1, len2; + const size_t len1 = strlen(string); + const size_t len2 = strlen(ending); - len1 = strlen(string); - len2 = strlen(ending); + if (len2 > len1) + return false; - if (len2 > len1) { - return GL_FALSE; - } - - if (strcmp(string + (len1 - len2), ending) == 0) { - return GL_TRUE; - } else { - return GL_FALSE; - } + return strcmp(string + (len1 - len2), ending) == 0; } /** @@ -58,15 +51,14 @@ check_for_ending(const char *string, const char *ending) * fwd_context is only valid if version > 0 */ static void -get_gl_override(int *version, GLboolean *fwd_context, - GLboolean *compat_context) +get_gl_override(int *version, bool *fwd_context, bool *compat_context) { const char *env_var = "MESA_GL_VERSION_OVERRIDE"; const char *version_str; int major, minor, n; static int override_version = -1; - static GLboolean fc_suffix = GL_FALSE; - static GLboolean compat_suffix = GL_FALSE; + static bool fc_suffix = false; + static bool compat_suffix = false; if (override_version < 0) { override_version = 0; @@ -78,12 +70,14 @@ get_gl_override(int *version, GLboolean *fwd_context, n = sscanf(version_str, "%u.%u", &major, &minor); if (n != 2) { - fprintf(stderr, "error: invalid value for %s: %s\n", env_var, version_str); + fprintf(stderr, "error: invalid value for %s: %s\n", + env_var, version_str); override_version = 0; } else { override_version = major * 10 + minor; if (override_version < 30 && fc_suffix) { - fprintf(stderr, "error: invalid value for %s: %s\n", env_var, version_str); + fprintf(stderr, "error: invalid value for %s: %s\n", + env_var, version_str); } } } @@ -134,7 +128,7 @@ _mesa_override_gl_version_contextless(struct gl_constants *consts, gl_api *apiOut, GLuint *versionOut) { int version; - GLboolean fwd_context, compat_context; + bool fwd_context, compat_context; get_gl_override(&version, &fwd_context, &compat_context); @@ -148,9 +142,9 @@ _mesa_override_gl_version_contextless(struct gl_constants *consts, } else { *apiOut = API_OPENGL_COMPAT; } - return GL_TRUE; + return true; } - return GL_FALSE; + return false; } void @@ -171,7 +165,7 @@ int _mesa_get_gl_version_override(void) { int version; - GLboolean fwd_context, compat_context; + bool fwd_context, compat_context; get_gl_override(&version, &fwd_context, &compat_context); @@ -211,121 +205,121 @@ compute_version(const struct gl_extensions *extensions, { GLuint major, minor, version; - const GLboolean ver_1_3 = (extensions->ARB_texture_border_clamp && - extensions->ARB_texture_cube_map && - extensions->ARB_texture_env_combine && - extensions->ARB_texture_env_dot3); - const GLboolean ver_1_4 = (ver_1_3 && - extensions->ARB_depth_texture && - extensions->ARB_shadow && - extensions->ARB_texture_env_crossbar && - extensions->EXT_blend_color && - extensions->EXT_blend_func_separate && - extensions->EXT_blend_minmax && - extensions->EXT_point_parameters); - const GLboolean ver_1_5 = (ver_1_4 && - extensions->ARB_occlusion_query); - const GLboolean ver_2_0 = (ver_1_5 && - extensions->ARB_point_sprite && - extensions->ARB_vertex_shader && - extensions->ARB_fragment_shader && - extensions->ARB_texture_non_power_of_two && - extensions->EXT_blend_equation_separate && - - /* Technically, 2.0 requires the functionality - * of the EXT version. Enable 2.0 if either - * extension is available, and assume that a - * driver that only exposes the ATI extension - * will fallback to software when necessary. - */ - (extensions->EXT_stencil_two_side - || extensions->ATI_separate_stencil)); - const GLboolean ver_2_1 = (ver_2_0 && - extensions->EXT_pixel_buffer_object && - extensions->EXT_texture_sRGB); - const GLboolean ver_3_0 = (ver_2_1 && - consts->GLSLVersion >= 130 && - (consts->MaxSamples >= 4 || consts->FakeSWMSAA) && - (api == API_OPENGL_CORE || - extensions->ARB_color_buffer_float) && - extensions->ARB_depth_buffer_float && - extensions->ARB_half_float_vertex && - extensions->ARB_map_buffer_range && - extensions->ARB_shader_texture_lod && - extensions->ARB_texture_float && - extensions->ARB_texture_rg && - extensions->ARB_texture_compression_rgtc && - extensions->EXT_draw_buffers2 && - extensions->ARB_framebuffer_object && - extensions->EXT_framebuffer_sRGB && - extensions->EXT_packed_float && - extensions->EXT_texture_array && - extensions->EXT_texture_shared_exponent && - extensions->EXT_transform_feedback && - extensions->NV_conditional_render); - const GLboolean ver_3_1 = (ver_3_0 && - consts->GLSLVersion >= 140 && - extensions->ARB_draw_instanced && - extensions->ARB_texture_buffer_object && - extensions->ARB_uniform_buffer_object && - extensions->EXT_texture_snorm && - extensions->NV_primitive_restart && - extensions->NV_texture_rectangle && - consts->Program[MESA_SHADER_VERTEX].MaxTextureImageUnits >= 16); - const GLboolean ver_3_2 = (ver_3_1 && - consts->GLSLVersion >= 150 && - extensions->ARB_depth_clamp && - extensions->ARB_draw_elements_base_vertex && - extensions->ARB_fragment_coord_conventions && - extensions->EXT_provoking_vertex && - extensions->ARB_seamless_cube_map && - extensions->ARB_sync && - extensions->ARB_texture_multisample && - extensions->EXT_vertex_array_bgra); - const GLboolean ver_3_3 = (ver_3_2 && - consts->GLSLVersion >= 330 && - extensions->ARB_blend_func_extended && - extensions->ARB_explicit_attrib_location && - extensions->ARB_instanced_arrays && - extensions->ARB_occlusion_query2 && - extensions->ARB_shader_bit_encoding && - extensions->ARB_texture_rgb10_a2ui && - extensions->ARB_timer_query && - extensions->ARB_vertex_type_2_10_10_10_rev && - extensions->EXT_texture_swizzle); - /* ARB_sampler_objects is always enabled in mesa */ - - const GLboolean ver_4_0 = (ver_3_3 && - consts->GLSLVersion >= 400 && - extensions->ARB_draw_buffers_blend && - extensions->ARB_draw_indirect && - extensions->ARB_gpu_shader5 && - extensions->ARB_gpu_shader_fp64 && - extensions->ARB_sample_shading && - 0/*extensions->ARB_shader_subroutine*/ && - extensions->ARB_tessellation_shader && - extensions->ARB_texture_buffer_object_rgb32 && - extensions->ARB_texture_cube_map_array && - extensions->ARB_texture_query_lod && - extensions->ARB_transform_feedback2 && - extensions->ARB_transform_feedback3); - const GLboolean ver_4_1 = (ver_4_0 && - consts->GLSLVersion >= 410 && - extensions->ARB_ES2_compatibility && - extensions->ARB_shader_precision && - 0/*extensions->ARB_vertex_attrib_64bit*/ && - extensions->ARB_viewport_array); - const GLboolean ver_4_2 = (ver_4_1 && - consts->GLSLVersion >= 420 && - extensions->ARB_base_instance && - extensions->ARB_conservative_depth && - extensions->ARB_internalformat_query && - extensions->ARB_shader_atomic_counters && - extensions->ARB_shader_image_load_store && - extensions->ARB_shading_language_420pack && - extensions->ARB_shading_language_packing && - extensions->ARB_texture_compression_bptc && - extensions->ARB_transform_feedback_instanced); + const bool ver_1_3 = (extensions->ARB_texture_border_clamp && + extensions->ARB_texture_cube_map && + extensions->ARB_texture_env_combine && + extensions->ARB_texture_env_dot3); + const bool ver_1_4 = (ver_1_3 && + extensions->ARB_depth_texture && + extensions->ARB_shadow && + extensions->ARB_texture_env_crossbar && + extensions->EXT_blend_color && + extensions->EXT_blend_func_separate && + extensions->EXT_blend_minmax && + extensions->EXT_point_parameters); + const bool ver_1_5 = (ver_1_4 && + extensions->ARB_occlusion_query); + const bool ver_2_0 = (ver_1_5 && + extensions->ARB_point_sprite && + extensions->ARB_vertex_shader && + extensions->ARB_fragment_shader && + extensions->ARB_texture_non_power_of_two && + extensions->EXT_blend_equation_separate && + + /* Technically, 2.0 requires the functionality of the + * EXT version. Enable 2.0 if either extension is + * available, and assume that a driver that only + * exposes the ATI extension will fallback to + * software when necessary. + */ + (extensions->EXT_stencil_two_side + || extensions->ATI_separate_stencil)); + const bool ver_2_1 = (ver_2_0 && + extensions->EXT_pixel_buffer_object && + extensions->EXT_texture_sRGB); + const bool ver_3_0 = (ver_2_1 && + consts->GLSLVersion >= 130 && + (consts->MaxSamples >= 4 || consts->FakeSWMSAA) && + (api == API_OPENGL_CORE || + extensions->ARB_color_buffer_float) && + extensions->ARB_depth_buffer_float && + extensions->ARB_half_float_vertex && + extensions->ARB_map_buffer_range && + extensions->ARB_shader_texture_lod && + extensions->ARB_texture_float && + extensions->ARB_texture_rg && + extensions->ARB_texture_compression_rgtc && + extensions->EXT_draw_buffers2 && + extensions->ARB_framebuffer_object && + extensions->EXT_framebuffer_sRGB && + extensions->EXT_packed_float && + extensions->EXT_texture_array && + extensions->EXT_texture_shared_exponent && + extensions->EXT_transform_feedback && + extensions->NV_conditional_render); + const bool ver_3_1 = (ver_3_0 && + consts->GLSLVersion >= 140 && + extensions->ARB_draw_instanced && + extensions->ARB_texture_buffer_object && + extensions->ARB_uniform_buffer_object && + extensions->EXT_texture_snorm && + extensions->NV_primitive_restart && + extensions->NV_texture_rectangle && + consts->Program[MESA_SHADER_VERTEX].MaxTextureImageUnits >= 16); + const bool ver_3_2 = (ver_3_1 && + consts->GLSLVersion >= 150 && + extensions->ARB_depth_clamp && + extensions->ARB_draw_elements_base_vertex && + extensions->ARB_fragment_coord_conventions && + extensions->EXT_provoking_vertex && + extensions->ARB_seamless_cube_map && + extensions->ARB_sync && + extensions->ARB_texture_multisample && + extensions->EXT_vertex_array_bgra); + const bool ver_3_3 = (ver_3_2 && + consts->GLSLVersion >= 330 && + extensions->ARB_blend_func_extended && + extensions->ARB_explicit_attrib_location && + extensions->ARB_instanced_arrays && + extensions->ARB_occlusion_query2 && + extensions->ARB_shader_bit_encoding && + extensions->ARB_texture_rgb10_a2ui && + extensions->ARB_timer_query && + extensions->ARB_vertex_type_2_10_10_10_rev && + extensions->EXT_texture_swizzle); + /* ARB_sampler_objects is always enabled in mesa */ + + const bool ver_4_0 = (ver_3_3 && + consts->GLSLVersion >= 400 && + extensions->ARB_draw_buffers_blend && + extensions->ARB_draw_indirect && + extensions->ARB_gpu_shader5 && + extensions->ARB_gpu_shader_fp64 && + extensions->ARB_sample_shading && + false /*extensions->ARB_shader_subroutine*/ && + extensions->ARB_tessellation_shader && + extensions->ARB_texture_buffer_object_rgb32 && + extensions->ARB_texture_cube_map_array && + extensions->ARB_texture_query_lod && + extensions->ARB_transform_feedback2 && + extensions->ARB_transform_feedback3); + const bool ver_4_1 = (ver_4_0 && + consts->GLSLVersion >= 410 && + extensions->ARB_ES2_compatibility && + extensions->ARB_shader_precision && + extensions->ARB_vertex_attrib_64bit && + extensions->ARB_viewport_array); + const bool ver_4_2 = (ver_4_1 && + consts->GLSLVersion >= 420 && + extensions->ARB_base_instance && + extensions->ARB_conservative_depth && + extensions->ARB_internalformat_query && + extensions->ARB_shader_atomic_counters && + extensions->ARB_shader_image_load_store && + extensions->ARB_shading_language_420pack && + extensions->ARB_shading_language_packing && + extensions->ARB_texture_compression_bptc && + extensions->ARB_transform_feedback_instanced); if (ver_4_2) { major = 4; @@ -392,11 +386,11 @@ static GLuint compute_version_es1(const struct gl_extensions *extensions) { /* OpenGL ES 1.0 is derived from OpenGL 1.3 */ - const GLboolean ver_1_0 = (extensions->ARB_texture_env_combine && - extensions->ARB_texture_env_dot3); + const bool ver_1_0 = (extensions->ARB_texture_env_combine && + extensions->ARB_texture_env_dot3); /* OpenGL ES 1.1 is derived from OpenGL 1.5 */ - const GLboolean ver_1_1 = (ver_1_0 && - extensions->EXT_point_parameters); + const bool ver_1_1 = (ver_1_0 && + extensions->EXT_point_parameters); if (ver_1_1) { return 11; @@ -411,34 +405,34 @@ static GLuint compute_version_es2(const struct gl_extensions *extensions) { /* OpenGL ES 2.0 is derived from OpenGL 2.0 */ - const GLboolean ver_2_0 = (extensions->ARB_texture_cube_map && - extensions->EXT_blend_color && - extensions->EXT_blend_func_separate && - extensions->EXT_blend_minmax && - extensions->ARB_vertex_shader && - extensions->ARB_fragment_shader && - extensions->ARB_texture_non_power_of_two && - extensions->EXT_blend_equation_separate); + const bool ver_2_0 = (extensions->ARB_texture_cube_map && + extensions->EXT_blend_color && + extensions->EXT_blend_func_separate && + extensions->EXT_blend_minmax && + extensions->ARB_vertex_shader && + extensions->ARB_fragment_shader && + extensions->ARB_texture_non_power_of_two && + extensions->EXT_blend_equation_separate); /* FINISHME: This list isn't quite right. */ - const GLboolean ver_3_0 = (extensions->ARB_half_float_vertex && - extensions->ARB_internalformat_query && - extensions->ARB_map_buffer_range && - extensions->ARB_shader_texture_lod && - extensions->ARB_texture_float && - extensions->ARB_texture_rg && - extensions->ARB_depth_buffer_float && - extensions->EXT_draw_buffers2 && - /* extensions->ARB_framebuffer_object && */ - extensions->EXT_framebuffer_sRGB && - extensions->EXT_packed_float && - extensions->EXT_texture_array && - extensions->EXT_texture_shared_exponent && - extensions->EXT_transform_feedback && - extensions->ARB_draw_instanced && - extensions->ARB_uniform_buffer_object && - extensions->EXT_texture_snorm && - extensions->NV_primitive_restart && - extensions->OES_depth_texture_cube_map); + const bool ver_3_0 = (extensions->ARB_half_float_vertex && + extensions->ARB_internalformat_query && + extensions->ARB_map_buffer_range && + extensions->ARB_shader_texture_lod && + extensions->ARB_texture_float && + extensions->ARB_texture_rg && + extensions->ARB_depth_buffer_float && + extensions->EXT_draw_buffers2 && + /* extensions->ARB_framebuffer_object && */ + extensions->EXT_framebuffer_sRGB && + extensions->EXT_packed_float && + extensions->EXT_texture_array && + extensions->EXT_texture_shared_exponent && + extensions->EXT_transform_feedback && + extensions->ARB_draw_instanced && + extensions->ARB_uniform_buffer_object && + extensions->EXT_texture_snorm && + extensions->NV_primitive_restart && + extensions->OES_depth_texture_cube_map); if (ver_3_0) { return 30; } else if (ver_2_0) { diff --git a/mesalib/src/mesa/main/vtxfmt.c b/mesalib/src/mesa/main/vtxfmt.c index fc0a01edf..d7ef7e278 100644 --- a/mesalib/src/mesa/main/vtxfmt.c +++ b/mesalib/src/mesa/main/vtxfmt.c @@ -206,6 +206,18 @@ install_vtxfmt(struct gl_context *ctx, struct _glapi_table *tab, SET_VertexAttribP3uiv(tab, vfmt->VertexAttribP3uiv); SET_VertexAttribP4uiv(tab, vfmt->VertexAttribP4uiv); } + + if (_mesa_is_desktop_gl(ctx)) { + SET_VertexAttribL1d(tab, vfmt->VertexAttribL1d); + SET_VertexAttribL2d(tab, vfmt->VertexAttribL2d); + SET_VertexAttribL3d(tab, vfmt->VertexAttribL3d); + SET_VertexAttribL4d(tab, vfmt->VertexAttribL4d); + + SET_VertexAttribL1dv(tab, vfmt->VertexAttribL1dv); + SET_VertexAttribL2dv(tab, vfmt->VertexAttribL2dv); + SET_VertexAttribL3dv(tab, vfmt->VertexAttribL3dv); + SET_VertexAttribL4dv(tab, vfmt->VertexAttribL4dv); + } } diff --git a/mesalib/src/mesa/program/prog_statevars.c b/mesalib/src/mesa/program/prog_statevars.c index 0c0c87faa..bdb335e4b 100644 --- a/mesalib/src/mesa/program/prog_statevars.c +++ b/mesalib/src/mesa/program/prog_statevars.c @@ -244,14 +244,14 @@ _mesa_fetch_state(struct gl_context *ctx, const gl_state_index state[], { /* state[1] is the texture unit */ const GLuint unit = (GLuint) state[1]; - if (_mesa_get_clamp_fragment_color(ctx)) + if (_mesa_get_clamp_fragment_color(ctx, ctx->DrawBuffer)) COPY_4V(value, ctx->Texture.Unit[unit].EnvColor); else COPY_4V(value, ctx->Texture.Unit[unit].EnvColorUnclamped); } return; case STATE_FOG_COLOR: - if (_mesa_get_clamp_fragment_color(ctx)) + if (_mesa_get_clamp_fragment_color(ctx, ctx->DrawBuffer)) COPY_4V(value, ctx->Fog.Color); else COPY_4V(value, ctx->Fog.ColorUnclamped); diff --git a/mesalib/src/mesa/program/prog_to_nir.c b/mesalib/src/mesa/program/prog_to_nir.c index ff3d9f3be..6c5fa51ec 100644 --- a/mesalib/src/mesa/program/prog_to_nir.c +++ b/mesalib/src/mesa/program/prog_to_nir.c @@ -710,7 +710,7 @@ static const nir_op op_trans[MAX_OPCODE] = { [OPCODE_DST] = 0, [OPCODE_END] = 0, [OPCODE_EX2] = nir_op_fexp2, - [OPCODE_EXP] = nir_op_fexp, + [OPCODE_EXP] = 0, [OPCODE_FLR] = nir_op_ffloor, [OPCODE_FRC] = nir_op_ffract, [OPCODE_LG2] = nir_op_flog2, diff --git a/mesalib/src/mesa/program/program.c b/mesalib/src/mesa/program/program.c index 4f28e2a3b..fb61f4d36 100644 --- a/mesalib/src/mesa/program/program.c +++ b/mesalib/src/mesa/program/program.c @@ -102,6 +102,8 @@ _mesa_init_program(struct gl_context *ctx) _mesa_reference_geomprog(ctx, &ctx->GeometryProgram.Current, NULL); + _mesa_reference_compprog(ctx, &ctx->ComputeProgram.Current, NULL); + /* XXX probably move this stuff */ ctx->ATIFragmentShader.Enabled = GL_FALSE; ctx->ATIFragmentShader.Current = ctx->Shared->DefaultFragmentShader; @@ -121,6 +123,7 @@ _mesa_free_program_data(struct gl_context *ctx) _mesa_reference_fragprog(ctx, &ctx->FragmentProgram.Current, NULL); _mesa_delete_shader_cache(ctx, ctx->FragmentProgram.Cache); _mesa_reference_geomprog(ctx, &ctx->GeometryProgram.Current, NULL); + _mesa_reference_compprog(ctx, &ctx->ComputeProgram.Current, NULL); /* XXX probably move this stuff */ if (ctx->ATIFragmentShader.Current) { diff --git a/mesalib/src/mesa/program/program.h b/mesalib/src/mesa/program/program.h index 0b0d1ac6f..2d92ab2f1 100644 --- a/mesalib/src/mesa/program/program.h +++ b/mesalib/src/mesa/program/program.h @@ -138,6 +138,15 @@ _mesa_reference_geomprog(struct gl_context *ctx, (struct gl_program *) prog); } +static inline void +_mesa_reference_compprog(struct gl_context *ctx, + struct gl_compute_program **ptr, + struct gl_compute_program *prog) +{ + _mesa_reference_program(ctx, (struct gl_program **) ptr, + (struct gl_program *) prog); +} + extern struct gl_program * _mesa_clone_program(struct gl_context *ctx, const struct gl_program *prog); @@ -276,6 +285,19 @@ gl_geometry_program_const(const struct gl_program *prog) } +static inline struct gl_compute_program * +gl_compute_program(struct gl_program *prog) +{ + return (struct gl_compute_program *) prog; +} + +static inline const struct gl_compute_program * +gl_compute_program_const(const struct gl_program *prog) +{ + return (const struct gl_compute_program *) prog; +} + + #ifdef __cplusplus } /* extern "C" */ #endif diff --git a/mesalib/src/mesa/state_tracker/st_atom_array.c b/mesalib/src/mesa/state_tracker/st_atom_array.c index d4fb8b862..56b8019a3 100644 --- a/mesalib/src/mesa/state_tracker/st_atom_array.c +++ b/mesalib/src/mesa/state_tracker/st_atom_array.c @@ -44,7 +44,6 @@ #include "cso_cache/cso_context.h" #include "util/u_math.h" - #include "main/bufferobj.h" #include "main/glformats.h" @@ -311,6 +310,18 @@ st_pipe_vertex_format(GLenum type, GLuint size, GLenum format, return PIPE_FORMAT_NONE; /* silence compiler warning */ } +static const struct gl_client_array * +get_client_array(const struct st_vertex_program *vp, + const struct gl_client_array **arrays, + int attr) +{ + const GLuint mesaAttr = vp->index_to_input[attr]; + /* st_program uses 0xffffffff to denote a double placeholder attribute */ + if (mesaAttr == ST_DOUBLE_ATTRIB_PLACEHOLDER) + return NULL; + return arrays[mesaAttr]; +} + /** * Examine the active arrays to determine if we have interleaved * vertex arrays all living in one VBO, or all living in user space. @@ -327,11 +338,16 @@ is_interleaved_arrays(const struct st_vertex_program *vp, GLboolean userSpaceBuffer = GL_FALSE; for (attr = 0; attr < vpv->num_inputs; attr++) { - const GLuint mesaAttr = vp->index_to_input[attr]; - const struct gl_client_array *array = arrays[mesaAttr]; - const struct gl_buffer_object *bufObj = array->BufferObj; - const GLsizei stride = array->StrideB; /* in bytes */ + const struct gl_client_array *array; + const struct gl_buffer_object *bufObj; + GLsizei stride; + + array = get_client_array(vp, arrays, attr); + if (!array) + continue; + stride = array->StrideB; /* in bytes */ + bufObj = array->BufferObj; if (attr == 0) { /* save info about the first array */ firstStride = stride; @@ -358,6 +374,55 @@ is_interleaved_arrays(const struct st_vertex_program *vp, return GL_TRUE; } +static void init_velement(struct pipe_vertex_element *velement, + int src_offset, int format, + int instance_divisor, int vbo_index) +{ + velement->src_offset = src_offset; + velement->src_format = format; + velement->instance_divisor = instance_divisor; + velement->vertex_buffer_index = vbo_index; + assert(velement->src_format); +} + +static void init_velement_lowered(struct st_context *st, + struct pipe_vertex_element *velements, + int src_offset, int format, + int instance_divisor, int vbo_index, + int nr_components, GLboolean doubles, + GLuint *attr_idx) +{ + int idx = *attr_idx; + if (doubles) { + int lower_format; + + if (nr_components == 1) + lower_format = PIPE_FORMAT_R32G32_UINT; + else if (nr_components >= 2) + lower_format = PIPE_FORMAT_R32G32B32A32_UINT; + + init_velement(&velements[idx], src_offset, + lower_format, instance_divisor, vbo_index); + idx++; + + if (nr_components > 2) { + if (nr_components == 3) + lower_format = PIPE_FORMAT_R32G32_UINT; + else if (nr_components >= 4) + lower_format = PIPE_FORMAT_R32G32B32A32_UINT; + + init_velement(&velements[idx], src_offset + 4 * sizeof(float), + lower_format, instance_divisor, vbo_index); + idx++; + } + } else { + init_velement(&velements[idx], src_offset, + format, instance_divisor, vbo_index); + idx++; + } + *attr_idx = idx; +} + /** * Set up for drawing interleaved arrays that all live in one VBO * or all live in user space. @@ -365,13 +430,15 @@ is_interleaved_arrays(const struct st_vertex_program *vp, * \param velements returns vertex element info */ static boolean -setup_interleaved_attribs(const struct st_vertex_program *vp, +setup_interleaved_attribs(struct st_context *st, + const struct st_vertex_program *vp, const struct st_vp_variant *vpv, const struct gl_client_array **arrays, struct pipe_vertex_buffer *vbuffer, - struct pipe_vertex_element velements[]) + struct pipe_vertex_element velements[], + unsigned *num_velements) { - GLuint attr; + GLuint attr, attr_idx; const GLubyte *low_addr = NULL; GLboolean usingVBO; /* all arrays in a VBO? */ struct gl_buffer_object *bufobj; @@ -381,8 +448,10 @@ setup_interleaved_attribs(const struct st_vertex_program *vp, * Init bufobj and stride. */ if (vpv->num_inputs) { - const GLuint mesaAttr0 = vp->index_to_input[0]; - const struct gl_client_array *array = arrays[mesaAttr0]; + const struct gl_client_array *array; + + array = get_client_array(vp, arrays, 0); + assert(array); /* Since we're doing interleaved arrays, we know there'll be at most * one buffer object and the stride will be the same for all arrays. @@ -394,7 +463,11 @@ setup_interleaved_attribs(const struct st_vertex_program *vp, low_addr = arrays[vp->index_to_input[0]]->Ptr; for (attr = 1; attr < vpv->num_inputs; attr++) { - const GLubyte *start = arrays[vp->index_to_input[attr]]->Ptr; + const GLubyte *start; + array = get_client_array(vp, arrays, attr); + if (!array) + continue; + start = array->Ptr; low_addr = MIN2(low_addr, start); } } @@ -408,25 +481,33 @@ setup_interleaved_attribs(const struct st_vertex_program *vp, /* are the arrays in user space? */ usingVBO = _mesa_is_bufferobj(bufobj); + attr_idx = 0; for (attr = 0; attr < vpv->num_inputs; attr++) { - const GLuint mesaAttr = vp->index_to_input[attr]; - const struct gl_client_array *array = arrays[mesaAttr]; - unsigned src_offset = (unsigned) (array->Ptr - low_addr); + const struct gl_client_array *array; + unsigned src_offset; + unsigned src_format; + + array = get_client_array(vp, arrays, attr); + if (!array) + continue; + src_offset = (unsigned) (array->Ptr - low_addr); assert(array->_ElementSize == _mesa_bytes_per_vertex_attrib(array->Size, array->Type)); - velements[attr].src_offset = src_offset; - velements[attr].instance_divisor = array->InstanceDivisor; - velements[attr].vertex_buffer_index = 0; - velements[attr].src_format = st_pipe_vertex_format(array->Type, - array->Size, - array->Format, - array->Normalized, - array->Integer); - assert(velements[attr].src_format); + src_format = st_pipe_vertex_format(array->Type, + array->Size, + array->Format, + array->Normalized, + array->Integer); + + init_velement_lowered(st, velements, src_offset, src_format, + array->InstanceDivisor, 0, + array->Size, array->Doubles, &attr_idx); } + *num_velements = attr_idx; + /* * Return the vbuffer info and setup user-space attrib info, if needed. */ @@ -472,17 +553,25 @@ setup_non_interleaved_attribs(struct st_context *st, const struct st_vp_variant *vpv, const struct gl_client_array **arrays, struct pipe_vertex_buffer vbuffer[], - struct pipe_vertex_element velements[]) + struct pipe_vertex_element velements[], + unsigned *num_velements) { struct gl_context *ctx = st->ctx; - GLuint attr; + GLuint attr, attr_idx = 0; for (attr = 0; attr < vpv->num_inputs; attr++) { const GLuint mesaAttr = vp->index_to_input[attr]; - const struct gl_client_array *array = arrays[mesaAttr]; - struct gl_buffer_object *bufobj = array->BufferObj; - GLsizei stride = array->StrideB; + const struct gl_client_array *array; + struct gl_buffer_object *bufobj; + GLsizei stride; + unsigned src_format; + array = get_client_array(vp, arrays, attr); + if (!array) + continue; + + stride = array->StrideB; + bufobj = array->BufferObj; assert(array->_ElementSize == _mesa_bytes_per_vertex_attrib(array->Size, array->Type)); @@ -524,16 +613,19 @@ setup_non_interleaved_attribs(struct st_context *st, /* common-case setup */ vbuffer[attr].stride = stride; /* in bytes */ - velements[attr].src_offset = 0; - velements[attr].instance_divisor = array->InstanceDivisor; - velements[attr].vertex_buffer_index = attr; - velements[attr].src_format = st_pipe_vertex_format(array->Type, - array->Size, - array->Format, - array->Normalized, - array->Integer); - assert(velements[attr].src_format); + src_format = st_pipe_vertex_format(array->Type, + array->Size, + array->Format, + array->Normalized, + array->Integer); + + init_velement_lowered(st, velements, 0, src_format, + array->InstanceDivisor, attr, + array->Size, array->Doubles, &attr_idx); + } + + *num_velements = attr_idx; return TRUE; } @@ -563,25 +655,23 @@ static void update_array(struct st_context *st) * Setup the vbuffer[] and velements[] arrays. */ if (is_interleaved_arrays(vp, vpv, arrays)) { - if (!setup_interleaved_attribs(vp, vpv, arrays, vbuffer, velements)) { + if (!setup_interleaved_attribs(st, vp, vpv, arrays, vbuffer, velements, &num_velements)) { st->vertex_array_out_of_memory = TRUE; return; } num_vbuffers = 1; - num_velements = vpv->num_inputs; if (num_velements == 0) num_vbuffers = 0; } else { if (!setup_non_interleaved_attribs(st, vp, vpv, arrays, vbuffer, - velements)) { + velements, &num_velements)) { st->vertex_array_out_of_memory = TRUE; return; } num_vbuffers = vpv->num_inputs; - num_velements = vpv->num_inputs; } cso_set_vertex_buffers(st->cso_context, 0, num_vbuffers, vbuffer); diff --git a/mesalib/src/mesa/state_tracker/st_atom_framebuffer.c b/mesalib/src/mesa/state_tracker/st_atom_framebuffer.c index b195c55b3..ae883a253 100644 --- a/mesalib/src/mesa/state_tracker/st_atom_framebuffer.c +++ b/mesalib/src/mesa/state_tracker/st_atom_framebuffer.c @@ -134,7 +134,10 @@ update_framebuffer_state( struct st_context *st ) else { strb = st_renderbuffer(fb->Attachment[BUFFER_STENCIL].Renderbuffer); if (strb) { - assert(strb->surface); + if (strb->is_rtt) { + /* rendering to a GL texture, may have to update surface */ + st_update_renderbuffer_surface(st, strb); + } pipe_surface_reference(&framebuffer->zsbuf, strb->surface); update_framebuffer_size(framebuffer, strb->surface); } diff --git a/mesalib/src/mesa/state_tracker/st_cb_fbo.c b/mesalib/src/mesa/state_tracker/st_cb_fbo.c index 296ea1e0d..0399eef72 100644 --- a/mesalib/src/mesa/state_tracker/st_cb_fbo.c +++ b/mesalib/src/mesa/state_tracker/st_cb_fbo.c @@ -842,7 +842,7 @@ void st_init_fbo_functions(struct dd_function_table *functions) functions->NewFramebuffer = st_new_framebuffer; functions->NewRenderbuffer = st_new_renderbuffer; functions->BindFramebuffer = st_bind_framebuffer; - functions->FramebufferRenderbuffer = _mesa_framebuffer_renderbuffer; + functions->FramebufferRenderbuffer = _mesa_FramebufferRenderbuffer_sw; functions->RenderTexture = st_render_texture; functions->FinishRenderTexture = st_finish_render_texture; functions->ValidateFramebuffer = st_validate_framebuffer; diff --git a/mesalib/src/mesa/state_tracker/st_cb_flush.c b/mesalib/src/mesa/state_tracker/st_cb_flush.c index ca51eeee3..82affd2de 100644 --- a/mesalib/src/mesa/state_tracker/st_cb_flush.c +++ b/mesalib/src/mesa/state_tracker/st_cb_flush.c @@ -141,11 +141,44 @@ static void st_glFinish(struct gl_context *ctx) } -void st_init_flush_functions(struct dd_function_table *functions) +/** + * Query information about GPU resets observed by this context + * + * Called via \c dd_function_table::GetGraphicsResetStatus. + */ +static GLenum +st_get_graphics_reset_status(struct gl_context *ctx) +{ + struct st_context *st = st_context(ctx); + enum pipe_reset_status status; + + status = st->pipe->get_device_reset_status(st->pipe); + + switch (status) { + case PIPE_NO_RESET: + return GL_NO_ERROR; + case PIPE_GUILTY_CONTEXT_RESET: + return GL_GUILTY_CONTEXT_RESET_ARB; + case PIPE_INNOCENT_CONTEXT_RESET: + return GL_INNOCENT_CONTEXT_RESET_ARB; + case PIPE_UNKNOWN_CONTEXT_RESET: + return GL_UNKNOWN_CONTEXT_RESET_ARB; + default: + assert(0); + return GL_NO_ERROR; + } +} + + +void st_init_flush_functions(struct pipe_screen *screen, + struct dd_function_table *functions) { functions->Flush = st_glFlush; functions->Finish = st_glFinish; + if (screen->get_param(screen, PIPE_CAP_DEVICE_RESET_STATUS_QUERY)) + functions->GetGraphicsResetStatus = st_get_graphics_reset_status; + /* Windows opengl32.dll calls glFinish prior to every swapbuffers. * This is unnecessary and degrades performance. Luckily we have some * scope to work around this, as the externally-visible behaviour of diff --git a/mesalib/src/mesa/state_tracker/st_cb_flush.h b/mesalib/src/mesa/state_tracker/st_cb_flush.h index 84ffc63ae..f92dcd56b 100644 --- a/mesalib/src/mesa/state_tracker/st_cb_flush.h +++ b/mesalib/src/mesa/state_tracker/st_cb_flush.h @@ -37,7 +37,8 @@ struct pipe_fence_handle; struct st_context; extern void -st_init_flush_functions(struct dd_function_table *functions); +st_init_flush_functions(struct pipe_screen *screen, + struct dd_function_table *functions); extern void st_flush(struct st_context *st, diff --git a/mesalib/src/mesa/state_tracker/st_cb_perfmon.c b/mesalib/src/mesa/state_tracker/st_cb_perfmon.c new file mode 100644 index 000000000..1bb5be397 --- /dev/null +++ b/mesalib/src/mesa/state_tracker/st_cb_perfmon.c @@ -0,0 +1,425 @@ +/* + * Copyright (C) 2013 Christoph Bumiller + * Copyright (C) 2015 Samuel Pitoiset + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + */ + +/** + * Performance monitoring counters interface to gallium. + */ + +#include "st_debug.h" +#include "st_context.h" +#include "st_cb_bitmap.h" +#include "st_cb_perfmon.h" + +#include "util/bitset.h" + +#include "pipe/p_context.h" +#include "pipe/p_screen.h" +#include "util/u_memory.h" + +/** + * Return a PIPE_QUERY_x type >= PIPE_QUERY_DRIVER_SPECIFIC, or -1 if + * the driver-specific query doesn't exist. + */ +static int +find_query_type(struct pipe_screen *screen, const char *name) +{ + int num_queries; + int type = -1; + int i; + + num_queries = screen->get_driver_query_info(screen, 0, NULL); + if (!num_queries) + return type; + + for (i = 0; i < num_queries; i++) { + struct pipe_driver_query_info info; + + if (!screen->get_driver_query_info(screen, i, &info)) + continue; + + if (!strncmp(info.name, name, strlen(name))) { + type = info.query_type; + break; + } + } + return type; +} + +/** + * Return TRUE if the underlying driver expose GPU counters. + */ +static bool +has_gpu_counters(struct pipe_screen *screen) +{ + int num_groups, gid; + + num_groups = screen->get_driver_query_group_info(screen, 0, NULL); + for (gid = 0; gid < num_groups; gid++) { + struct pipe_driver_query_group_info group_info; + + if (!screen->get_driver_query_group_info(screen, gid, &group_info)) + continue; + + if (group_info.type == PIPE_DRIVER_QUERY_GROUP_TYPE_GPU) + return true; + } + return false; +} + +static bool +init_perf_monitor(struct gl_context *ctx, struct gl_perf_monitor_object *m) +{ + struct st_perf_monitor_object *stm = st_perf_monitor_object(m); + struct pipe_screen *screen = st_context(ctx)->pipe->screen; + struct pipe_context *pipe = st_context(ctx)->pipe; + int gid, cid; + + st_flush_bitmap_cache(st_context(ctx)); + + /* Create a query for each active counter. */ + for (gid = 0; gid < ctx->PerfMonitor.NumGroups; gid++) { + const struct gl_perf_monitor_group *g = &ctx->PerfMonitor.Groups[gid]; + + if (m->ActiveGroups[gid] > g->MaxActiveCounters) { + /* Maximum number of counters reached. Cannot start the session. */ + if (ST_DEBUG & DEBUG_MESA) { + debug_printf("Maximum number of counters reached. " + "Cannot start the session!\n"); + } + return false; + } + + for (cid = 0; cid < g->NumCounters; cid++) { + const struct gl_perf_monitor_counter *c = &g->Counters[cid]; + struct st_perf_counter_object *cntr; + int query_type; + + if (!BITSET_TEST(m->ActiveCounters[gid], cid)) + continue; + + query_type = find_query_type(screen, c->Name); + assert(query_type != -1); + + cntr = CALLOC_STRUCT(st_perf_counter_object); + if (!cntr) + return false; + + cntr->query = pipe->create_query(pipe, query_type, 0); + cntr->id = cid; + cntr->group_id = gid; + + list_addtail(&cntr->list, &stm->active_counters); + } + } + return true; +} + +static void +reset_perf_monitor(struct st_perf_monitor_object *stm, + struct pipe_context *pipe) +{ + struct st_perf_counter_object *cntr, *tmp; + + LIST_FOR_EACH_ENTRY_SAFE(cntr, tmp, &stm->active_counters, list) { + if (cntr->query) + pipe->destroy_query(pipe, cntr->query); + list_del(&cntr->list); + free(cntr); + } +} + +static struct gl_perf_monitor_object * +st_NewPerfMonitor(struct gl_context *ctx) +{ + struct st_perf_monitor_object *stq = ST_CALLOC_STRUCT(st_perf_monitor_object); + if (stq) { + list_inithead(&stq->active_counters); + return &stq->base; + } + return NULL; +} + +static void +st_DeletePerfMonitor(struct gl_context *ctx, struct gl_perf_monitor_object *m) +{ + struct st_perf_monitor_object *stm = st_perf_monitor_object(m); + struct pipe_context *pipe = st_context(ctx)->pipe; + + reset_perf_monitor(stm, pipe); + FREE(stm); +} + +static GLboolean +st_BeginPerfMonitor(struct gl_context *ctx, struct gl_perf_monitor_object *m) +{ + struct st_perf_monitor_object *stm = st_perf_monitor_object(m); + struct pipe_context *pipe = st_context(ctx)->pipe; + struct st_perf_counter_object *cntr; + + if (LIST_IS_EMPTY(&stm->active_counters)) { + /* Create a query for each active counter before starting + * a new monitoring session. */ + if (!init_perf_monitor(ctx, m)) + goto fail; + } + + /* Start the query for each active counter. */ + LIST_FOR_EACH_ENTRY(cntr, &stm->active_counters, list) { + if (!pipe->begin_query(pipe, cntr->query)) + goto fail; + } + return true; + +fail: + /* Failed to start the monitoring session. */ + reset_perf_monitor(stm, pipe); + return false; +} + +static void +st_EndPerfMonitor(struct gl_context *ctx, struct gl_perf_monitor_object *m) +{ + struct st_perf_monitor_object *stm = st_perf_monitor_object(m); + struct pipe_context *pipe = st_context(ctx)->pipe; + struct st_perf_counter_object *cntr; + + /* Stop the query for each active counter. */ + LIST_FOR_EACH_ENTRY(cntr, &stm->active_counters, list) + pipe->end_query(pipe, cntr->query); +} + +static void +st_ResetPerfMonitor(struct gl_context *ctx, struct gl_perf_monitor_object *m) +{ + struct st_perf_monitor_object *stm = st_perf_monitor_object(m); + struct pipe_context *pipe = st_context(ctx)->pipe; + + if (!m->Ended) + st_EndPerfMonitor(ctx, m); + + reset_perf_monitor(stm, pipe); + + if (m->Active) + st_BeginPerfMonitor(ctx, m); +} + +static GLboolean +st_IsPerfMonitorResultAvailable(struct gl_context *ctx, + struct gl_perf_monitor_object *m) +{ + struct st_perf_monitor_object *stm = st_perf_monitor_object(m); + struct pipe_context *pipe = st_context(ctx)->pipe; + struct st_perf_counter_object *cntr; + + if (LIST_IS_EMPTY(&stm->active_counters)) + return false; + + /* The result of a monitoring session is only available if the query of + * each active counter is idle. */ + LIST_FOR_EACH_ENTRY(cntr, &stm->active_counters, list) { + union pipe_query_result result; + if (!pipe->get_query_result(pipe, cntr->query, FALSE, &result)) { + /* The query is busy. */ + return false; + } + } + return true; +} + +static void +st_GetPerfMonitorResult(struct gl_context *ctx, + struct gl_perf_monitor_object *m, + GLsizei dataSize, + GLuint *data, + GLint *bytesWritten) +{ + struct st_perf_monitor_object *stm = st_perf_monitor_object(m); + struct pipe_context *pipe = st_context(ctx)->pipe; + struct st_perf_counter_object *cntr; + + /* Copy data to the supplied array (data). + * + * The output data format is: <group ID, counter ID, value> for each + * active counter. The API allows counters to appear in any order. + */ + GLsizei offset = 0; + + /* Read query results for each active counter. */ + LIST_FOR_EACH_ENTRY(cntr, &stm->active_counters, list) { + union pipe_query_result result = { 0 }; + int gid, cid; + GLenum type; + + cid = cntr->id; + gid = cntr->group_id; + type = ctx->PerfMonitor.Groups[gid].Counters[cid].Type; + + if (!pipe->get_query_result(pipe, cntr->query, TRUE, &result)) + continue; + + data[offset++] = gid; + data[offset++] = cid; + switch (type) { + case GL_UNSIGNED_INT64_AMD: + *(uint64_t *)&data[offset] = result.u64; + offset += sizeof(uint64_t) / sizeof(GLuint); + break; + case GL_UNSIGNED_INT: + *(uint32_t *)&data[offset] = result.u32; + offset += sizeof(uint32_t) / sizeof(GLuint); + break; + case GL_FLOAT: + case GL_PERCENTAGE_AMD: + *(GLfloat *)&data[offset] = result.f; + offset += sizeof(GLfloat) / sizeof(GLuint); + break; + } + } + + if (bytesWritten) + *bytesWritten = offset * sizeof(GLuint); +} + + +bool +st_init_perfmon(struct st_context *st) +{ + struct gl_perf_monitor_state *perfmon = &st->ctx->PerfMonitor; + struct pipe_screen *screen = st->pipe->screen; + struct gl_perf_monitor_group *groups = NULL; + int num_counters, num_groups; + int gid, cid; + + if (!screen->get_driver_query_info || !screen->get_driver_query_group_info) + return false; + + if (!has_gpu_counters(screen)) { + /* According to the spec, GL_AMD_performance_monitor must only + * expose GPU counters. */ + return false; + } + + /* Get the number of available queries. */ + num_counters = screen->get_driver_query_info(screen, 0, NULL); + if (!num_counters) + return false; + + /* Get the number of available groups. */ + num_groups = screen->get_driver_query_group_info(screen, 0, NULL); + if (num_groups) + groups = CALLOC(num_groups, sizeof(*groups)); + if (!groups) + return false; + + for (gid = 0; gid < num_groups; gid++) { + struct gl_perf_monitor_group *g = &groups[perfmon->NumGroups]; + struct pipe_driver_query_group_info group_info; + struct gl_perf_monitor_counter *counters = NULL; + + if (!screen->get_driver_query_group_info(screen, gid, &group_info)) + continue; + + if (group_info.type != PIPE_DRIVER_QUERY_GROUP_TYPE_GPU) + continue; + + g->Name = group_info.name; + g->MaxActiveCounters = group_info.max_active_queries; + g->NumCounters = 0; + g->Counters = NULL; + + if (group_info.num_queries) + counters = CALLOC(group_info.num_queries, sizeof(*counters)); + if (!counters) + goto fail; + + for (cid = 0; cid < num_counters; cid++) { + struct gl_perf_monitor_counter *c = &counters[g->NumCounters]; + struct pipe_driver_query_info info; + + if (!screen->get_driver_query_info(screen, cid, &info)) + continue; + if (info.group_id != gid) + continue; + + c->Name = info.name; + switch (info.type) { + case PIPE_DRIVER_QUERY_TYPE_UINT64: + c->Minimum.u64 = 0; + c->Maximum.u64 = info.max_value.u64 ? info.max_value.u64 : -1; + c->Type = GL_UNSIGNED_INT64_AMD; + break; + case PIPE_DRIVER_QUERY_TYPE_UINT: + c->Minimum.u32 = 0; + c->Maximum.u32 = info.max_value.u32 ? info.max_value.u32 : -1; + c->Type = GL_UNSIGNED_INT; + break; + case PIPE_DRIVER_QUERY_TYPE_FLOAT: + c->Minimum.f = 0.0; + c->Maximum.f = info.max_value.f ? info.max_value.f : -1; + c->Type = GL_FLOAT; + break; + case PIPE_DRIVER_QUERY_TYPE_PERCENTAGE: + c->Minimum.f = 0.0f; + c->Maximum.f = 100.0f; + c->Type = GL_PERCENTAGE_AMD; + break; + default: + unreachable("Invalid driver query type!"); + } + g->NumCounters++; + } + g->Counters = counters; + perfmon->NumGroups++; + } + perfmon->Groups = groups; + + return true; + +fail: + for (gid = 0; gid < num_groups; gid++) + FREE((void *)groups[gid].Counters); + FREE(groups); + return false; +} + +void +st_destroy_perfmon(struct st_context *st) +{ + struct gl_perf_monitor_state *perfmon = &st->ctx->PerfMonitor; + int gid; + + for (gid = 0; gid < perfmon->NumGroups; gid++) + FREE((void *)perfmon->Groups[gid].Counters); + FREE((void *)perfmon->Groups); +} + +void st_init_perfmon_functions(struct dd_function_table *functions) +{ + functions->NewPerfMonitor = st_NewPerfMonitor; + functions->DeletePerfMonitor = st_DeletePerfMonitor; + functions->BeginPerfMonitor = st_BeginPerfMonitor; + functions->EndPerfMonitor = st_EndPerfMonitor; + functions->ResetPerfMonitor = st_ResetPerfMonitor; + functions->IsPerfMonitorResultAvailable = st_IsPerfMonitorResultAvailable; + functions->GetPerfMonitorResult = st_GetPerfMonitorResult; +} diff --git a/mesalib/src/mesa/state_tracker/st_cb_perfmon.h b/mesalib/src/mesa/state_tracker/st_cb_perfmon.h new file mode 100644 index 000000000..13d3627de --- /dev/null +++ b/mesalib/src/mesa/state_tracker/st_cb_perfmon.h @@ -0,0 +1,64 @@ +/* + * Copyright (C) 2013 Christoph Bumiller + * Copyright (C) 2015 Samuel Pitoiset + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + */ + +#ifndef ST_CB_PERFMON_H +#define ST_CB_PERFMON_H + +#include "util/list.h" + +/** + * Subclass of gl_perf_monitor_object + */ +struct st_perf_monitor_object +{ + struct gl_perf_monitor_object base; + struct list_head active_counters; +}; + +struct st_perf_counter_object +{ + struct list_head list; + struct pipe_query *query; + int id; + int group_id; +}; + +/** + * Cast wrapper + */ +static INLINE struct st_perf_monitor_object * +st_perf_monitor_object(struct gl_perf_monitor_object *q) +{ + return (struct st_perf_monitor_object *)q; +} + +bool +st_init_perfmon(struct st_context *st); + +void +st_destroy_perfmon(struct st_context *st); + +extern void +st_init_perfmon_functions(struct dd_function_table *functions); + +#endif diff --git a/mesalib/src/mesa/state_tracker/st_context.c b/mesalib/src/mesa/state_tracker/st_context.c index 5fe132ac2..69e0f929d 100644 --- a/mesalib/src/mesa/state_tracker/st_context.c +++ b/mesalib/src/mesa/state_tracker/st_context.c @@ -51,6 +51,7 @@ #include "st_cb_fbo.h" #include "st_cb_feedback.h" #include "st_cb_msaa.h" +#include "st_cb_perfmon.h" #include "st_cb_program.h" #include "st_cb_queryobj.h" #include "st_cb_readpixels.h" @@ -116,6 +117,7 @@ st_destroy_context_priv(struct st_context *st) st_destroy_bitmap(st); st_destroy_drawpix(st); st_destroy_drawtex(st); + st_destroy_perfmon(st); for (shader = 0; shader < ARRAY_SIZE(st->state.sampler_views); shader++) { for (i = 0; i < ARRAY_SIZE(st->state.sampler_views[0]); i++) { @@ -250,6 +252,12 @@ st_create_context_priv( struct gl_context *ctx, struct pipe_context *pipe, st_init_extensions(st->pipe->screen, &ctx->Const, &ctx->Extensions, &st->options, ctx->Mesa_DXTn); + if (st_init_perfmon(st)) { + /* GL_AMD_performance_monitor is only enabled when the underlying + * driver expose GPU hardware performance counters. */ + ctx->Extensions.AMD_performance_monitor = GL_TRUE; + } + /* Enable shader-based fallbacks for ARB_color_buffer_float if needed. */ if (screen->get_param(screen, PIPE_CAP_VERTEX_COLOR_UNCLAMPED)) { if (!screen->get_param(screen, PIPE_CAP_VERTEX_COLOR_CLAMPED)) { @@ -313,7 +321,7 @@ struct st_context *st_create_context(gl_api api, struct pipe_context *pipe, struct st_context *st; memset(&funcs, 0, sizeof(funcs)); - st_init_driver_functions(&funcs); + st_init_driver_functions(pipe->screen, &funcs); ctx = _mesa_create_context(api, visual, shareCtx, &funcs); if (!ctx) { @@ -393,7 +401,8 @@ void st_destroy_context( struct st_context *st ) } -void st_init_driver_functions(struct dd_function_table *functions) +void st_init_driver_functions(struct pipe_screen *screen, + struct dd_function_table *functions) { _mesa_init_shader_object_functions(functions); _mesa_init_sampler_object_functions(functions); @@ -414,13 +423,14 @@ void st_init_driver_functions(struct dd_function_table *functions) st_init_fbo_functions(functions); st_init_feedback_functions(functions); st_init_msaa_functions(functions); + st_init_perfmon_functions(functions); st_init_program_functions(functions); st_init_query_functions(functions); st_init_cond_render_functions(functions); st_init_readpixels_functions(functions); st_init_texture_functions(functions); st_init_texture_barrier_functions(functions); - st_init_flush_functions(functions); + st_init_flush_functions(screen, functions); st_init_string_functions(functions); st_init_viewport_functions(functions); diff --git a/mesalib/src/mesa/state_tracker/st_context.h b/mesalib/src/mesa/state_tracker/st_context.h index 8a9504bb7..dac5a4b90 100644 --- a/mesalib/src/mesa/state_tracker/st_context.h +++ b/mesalib/src/mesa/state_tracker/st_context.h @@ -237,7 +237,8 @@ struct st_framebuffer }; -extern void st_init_driver_functions(struct dd_function_table *functions); +extern void st_init_driver_functions(struct pipe_screen *screen, + struct dd_function_table *functions); void st_invalidate_state(struct gl_context * ctx, GLuint new_state); diff --git a/mesalib/src/mesa/state_tracker/st_extensions.c b/mesalib/src/mesa/state_tracker/st_extensions.c index 82e4a3009..23a45883d 100644 --- a/mesalib/src/mesa/state_tracker/st_extensions.c +++ b/mesalib/src/mesa/state_tracker/st_extensions.c @@ -650,6 +650,12 @@ void st_init_extensions(struct pipe_screen *screen, ARRAY_SIZE(vertex_mapping), PIPE_BUFFER, PIPE_BIND_VERTEX_BUFFER); + /* ARB_direct_state_access requires OpenGL 2.0. Assume that all drivers + * that support NPOT textures are able to support GL 2.0. + */ + if (extensions->ARB_texture_non_power_of_two) + extensions->ARB_direct_state_access = GL_TRUE; + if (extensions->ARB_stencil_texturing) extensions->ARB_texture_stencil8 = GL_TRUE; @@ -909,6 +915,8 @@ void st_init_extensions(struct pipe_screen *screen, if (screen->get_shader_param(screen, PIPE_SHADER_VERTEX, PIPE_SHADER_CAP_DOUBLES) && screen->get_shader_param(screen, PIPE_SHADER_FRAGMENT, - PIPE_SHADER_CAP_DOUBLES)) + PIPE_SHADER_CAP_DOUBLES)) { extensions->ARB_gpu_shader_fp64 = GL_TRUE; + extensions->ARB_vertex_attrib_64bit = GL_TRUE; + } } diff --git a/mesalib/src/mesa/state_tracker/st_format.c b/mesalib/src/mesa/state_tracker/st_format.c index 181465dd8..db7b5b71d 100644 --- a/mesalib/src/mesa/state_tracker/st_format.c +++ b/mesalib/src/mesa/state_tracker/st_format.c @@ -991,7 +991,7 @@ static const struct format_mapping format_map[] = { { { GL_RGB10, 0 }, { PIPE_FORMAT_B10G10R10X2_UNORM, PIPE_FORMAT_B10G10R10A2_UNORM, - DEFAULT_RGB_FORMATS } + PIPE_FORMAT_R10G10B10A2_UNORM, DEFAULT_RGB_FORMATS } }, { { GL_RGB10_A2, 0 }, diff --git a/mesalib/src/mesa/state_tracker/st_glsl_to_tgsi.cpp b/mesalib/src/mesa/state_tracker/st_glsl_to_tgsi.cpp index 93671ba9c..f0f2a77d0 100644 --- a/mesalib/src/mesa/state_tracker/st_glsl_to_tgsi.cpp +++ b/mesalib/src/mesa/state_tracker/st_glsl_to_tgsi.cpp @@ -88,6 +88,7 @@ public: this->reladdr = NULL; this->reladdr2 = NULL; this->has_index2 = false; + this->double_reg2 = false; } st_src_reg(gl_register_file file, int index, int type) @@ -101,6 +102,7 @@ public: this->reladdr = NULL; this->reladdr2 = NULL; this->has_index2 = false; + this->double_reg2 = false; } st_src_reg(gl_register_file file, int index, int type, int index2D) @@ -114,6 +116,7 @@ public: this->reladdr = NULL; this->reladdr2 = NULL; this->has_index2 = false; + this->double_reg2 = false; } st_src_reg() @@ -127,6 +130,7 @@ public: this->reladdr = NULL; this->reladdr2 = NULL; this->has_index2 = false; + this->double_reg2 = false; } explicit st_src_reg(st_dst_reg reg); @@ -141,6 +145,11 @@ public: st_src_reg *reladdr; st_src_reg *reladdr2; bool has_index2; + /* + * Is this the second half of a double register pair? + * currently used for input mapping only. + */ + bool double_reg2; }; class st_dst_reg { @@ -197,6 +206,7 @@ st_src_reg::st_src_reg(st_dst_reg reg) this->index2D = 0; this->reladdr2 = NULL; this->has_index2 = false; + this->double_reg2 = false; } st_dst_reg::st_dst_reg(st_src_reg reg) @@ -677,8 +687,10 @@ glsl_to_tgsi_visitor::emit(ir_instruction *ir, unsigned op, if (dinst->src[j].type == GLSL_TYPE_DOUBLE) { dinst->src[j].index = initial_src_idx[j]; - if (swz > 1) + if (swz > 1) { + dinst->src[j].double_reg2 = true; dinst->src[j].index++; + } if (swz & 1) dinst->src[j].swizzle = MAKE_SWIZZLE4(SWIZZLE_Z, SWIZZLE_W, SWIZZLE_Z, SWIZZLE_W); @@ -1941,7 +1953,7 @@ glsl_to_tgsi_visitor::visit(ir_expression *ir) break; case ir_unop_i2b: if (native_integers) - emit(ir, TGSI_OPCODE_INEG, result_dst, op[0]); + emit(ir, TGSI_OPCODE_USNE, result_dst, op[0], st_src_reg_for_int(0)); else emit(ir, TGSI_OPCODE_SNE, result_dst, op[0], st_src_reg_for_float(0.0)); break; @@ -2611,6 +2623,7 @@ glsl_to_tgsi_visitor::visit(ir_assignment *ir) assert(!ir->lhs->type->is_scalar() && !ir->lhs->type->is_vector()); l.writemask = WRITEMASK_XYZW; } else if (ir->lhs->type->is_scalar() && + !ir->lhs->type->is_double() && ir->lhs->variable_referenced()->data.mode == ir_var_shader_out) { /* FINISHME: This hack makes writing to gl_FragDepth, which lives in the * FINISHME: W component of fragment shader output zero, work correctly. @@ -3704,6 +3717,7 @@ glsl_to_tgsi_visitor::copy_propagate(void) } else { if (first->src[0].file != copy_chan->src[0].file || first->src[0].index != copy_chan->src[0].index || + first->src[0].double_reg2 != copy_chan->src[0].double_reg2 || first->src[0].index2D != copy_chan->src[0].index2D) { good = false; break; @@ -3719,6 +3733,7 @@ glsl_to_tgsi_visitor::copy_propagate(void) inst->src[r].index = first->src[0].index; inst->src[r].index2D = first->src[0].index2D; inst->src[r].has_index2 = first->src[0].has_index2; + inst->src[r].double_reg2 = first->src[0].double_reg2; int swizzle = 0; for (int i = 0; i < 4; i++) { @@ -4551,6 +4566,9 @@ dst_register(struct st_translate *t, static struct ureg_src src_register(struct st_translate *t, const st_src_reg *reg) { + int index = reg->index; + int double_reg2 = reg->double_reg2 ? 1 : 0; + switch(reg->file) { case PROGRAM_UNDEFINED: return ureg_imm4f(t->ureg, 0, 0, 0, 0); @@ -4576,8 +4594,12 @@ src_register(struct st_translate *t, const st_src_reg *reg) return t->immediates[reg->index]; case PROGRAM_INPUT: - assert(t->inputMapping[reg->index] < ARRAY_SIZE(t->inputs)); - return t->inputs[t->inputMapping[reg->index]]; + /* GLSL inputs are 64-bit containers, so we have to + * map back to the original index and add the offset after + * mapping. */ + index -= double_reg2; + assert(t->inputMapping[index] < ARRAY_SIZE(t->inputs)); + return t->inputs[t->inputMapping[index] + double_reg2]; case PROGRAM_OUTPUT: assert(t->outputMapping[reg->index] < ARRAY_SIZE(t->outputs)); diff --git a/mesalib/src/mesa/state_tracker/st_manager.c b/mesalib/src/mesa/state_tracker/st_manager.c index 840f76a13..0376954f7 100644 --- a/mesalib/src/mesa/state_tracker/st_manager.c +++ b/mesalib/src/mesa/state_tracker/st_manager.c @@ -680,6 +680,10 @@ st_api_create_context(struct st_api *stapi, struct st_manager *smapi, if (attribs->flags & ST_CONTEXT_FLAG_FORWARD_COMPATIBLE) st->ctx->Const.ContextFlags |= GL_CONTEXT_FLAG_FORWARD_COMPATIBLE_BIT; + if (attribs->flags & ST_CONTEXT_FLAG_ROBUST_ACCESS) + st->ctx->Const.ContextFlags |= GL_CONTEXT_FLAG_ROBUST_ACCESS_BIT_ARB; + if (attribs->flags & ST_CONTEXT_FLAG_RESET_NOTIFICATION_ENABLED) + st->ctx->Const.ResetStrategy = GL_LOSE_CONTEXT_ON_RESET_ARB; /* need to perform version check */ if (attribs->major > 1 || attribs->minor > 0) { diff --git a/mesalib/src/mesa/state_tracker/st_program.c b/mesalib/src/mesa/state_tracker/st_program.c index d93b3c7bc..a9110d3c6 100644 --- a/mesalib/src/mesa/state_tracker/st_program.c +++ b/mesalib/src/mesa/state_tracker/st_program.c @@ -194,6 +194,11 @@ st_prepare_vertex_program(struct gl_context *ctx, stvp->input_to_index[attr] = stvp->num_inputs; stvp->index_to_input[stvp->num_inputs] = attr; stvp->num_inputs++; + if ((stvp->Base.Base.DoubleInputsRead & BITFIELD64_BIT(attr)) != 0) { + /* add placeholder for second part of a double attribute */ + stvp->index_to_input[stvp->num_inputs] = ST_DOUBLE_ATTRIB_PLACEHOLDER; + stvp->num_inputs++; + } } } /* bit of a hack, presetup potentially unused edgeflag input */ diff --git a/mesalib/src/mesa/state_tracker/st_program.h b/mesalib/src/mesa/state_tracker/st_program.h index b2c86faec..a2c56062d 100644 --- a/mesalib/src/mesa/state_tracker/st_program.h +++ b/mesalib/src/mesa/state_tracker/st_program.h @@ -45,6 +45,7 @@ extern "C" { #endif +#define ST_DOUBLE_ATTRIB_PLACEHOLDER 0xffffffff /** Fragment program variant key */ struct st_fp_variant_key diff --git a/mesalib/src/mesa/swrast/s_drawpix.c b/mesalib/src/mesa/swrast/s_drawpix.c index bf427266c..fb677ee1b 100644 --- a/mesalib/src/mesa/swrast/s_drawpix.c +++ b/mesalib/src/mesa/swrast/s_drawpix.c @@ -448,14 +448,34 @@ draw_rgba_pixels( struct gl_context *ctx, GLint x, GLint y, { const GLbitfield interpMask = span.interpMask; const GLbitfield arrayMask = span.arrayMask; - const GLint srcStride - = _mesa_image_row_stride(unpack, width, format, type); GLint skipPixels = 0; /* use span array for temp color storage */ GLfloat *rgba = (GLfloat *) span.array->attribs[VARYING_SLOT_COL0]; void *tempImage = NULL; - if (unpack->SwapBytes) { + /* We have to deal with GL_COLOR_INDEX manually because + * _mesa_format_convert does not handle this format. So what we do here is + * convert it to RGBA ubyte first and then convert from that to dst as + * usual. + */ + if (format == GL_COLOR_INDEX) { + /* This will handle byte swapping and transferops if needed */ + tempImage = + _mesa_unpack_color_index_to_rgba_ubyte(ctx, 2, + pixels, format, type, + width, height, 1, + unpack, + transferOps); + if (!tempImage) { + _mesa_error(ctx, GL_OUT_OF_MEMORY, "glDrawPixels"); + return; + } + + transferOps = 0; + pixels = tempImage; + format = GL_RGBA; + type = GL_UNSIGNED_BYTE; + } else if (unpack->SwapBytes) { /* We have to handle byte-swapping scenarios before calling * _mesa_format_convert */ @@ -476,6 +496,9 @@ draw_rgba_pixels( struct gl_context *ctx, GLint x, GLint y, } } + const GLint srcStride + = _mesa_image_row_stride(unpack, width, format, type); + /* if the span is wider than SWRAST_MAX_WIDTH we have to do it in chunks */ while (skipPixels < width) { const GLint spanWidth = MIN2(width - skipPixels, SWRAST_MAX_WIDTH); diff --git a/mesalib/src/mesa/swrast/s_texrender.c b/mesalib/src/mesa/swrast/s_texrender.c index fa853c919..4e41b3b72 100644 --- a/mesalib/src/mesa/swrast/s_texrender.c +++ b/mesalib/src/mesa/swrast/s_texrender.c @@ -72,7 +72,7 @@ update_wrapper(struct gl_context *ctx, struct gl_renderbuffer_attachment *att) * \param fb the framebuffer object the texture is being bound to * \param att the fb attachment point of the texture * - * \sa _mesa_framebuffer_renderbuffer + * \sa _mesa_FramebufferRenderbuffer_sw */ void _swrast_render_texture(struct gl_context *ctx, diff --git a/mesalib/src/mesa/vbo/vbo_attrib_tmp.h b/mesalib/src/mesa/vbo/vbo_attrib_tmp.h index 17e057836..e73b8fb5f 100644 --- a/mesalib/src/mesa/vbo/vbo_attrib_tmp.h +++ b/mesalib/src/mesa/vbo/vbo_attrib_tmp.h @@ -31,14 +31,16 @@ USE OR OTHER DEALINGS IN THE SOFTWARE. /* ATTR */ #define ATTRI( A, N, V0, V1, V2, V3 ) \ - ATTR_UNION(A, N, GL_INT, INT_AS_UNION(V0), INT_AS_UNION(V1), \ + ATTR_UNION(A, N, GL_INT, fi_type, INT_AS_UNION(V0), INT_AS_UNION(V1), \ INT_AS_UNION(V2), INT_AS_UNION(V3)) #define ATTRUI( A, N, V0, V1, V2, V3 ) \ - ATTR_UNION(A, N, GL_UNSIGNED_INT, UINT_AS_UNION(V0), UINT_AS_UNION(V1), \ + ATTR_UNION(A, N, GL_UNSIGNED_INT, fi_type, UINT_AS_UNION(V0), UINT_AS_UNION(V1), \ UINT_AS_UNION(V2), UINT_AS_UNION(V3)) #define ATTRF( A, N, V0, V1, V2, V3 ) \ - ATTR_UNION(A, N, GL_FLOAT, FLOAT_AS_UNION(V0), FLOAT_AS_UNION(V1),\ + ATTR_UNION(A, N, GL_FLOAT, fi_type, FLOAT_AS_UNION(V0), FLOAT_AS_UNION(V1),\ FLOAT_AS_UNION(V2), FLOAT_AS_UNION(V3)) +#define ATTRD( A, N, V0, V1, V2, V3 ) \ + ATTR_UNION(A, N, GL_DOUBLE, double, V0, V1, V2, V3) /* float */ @@ -232,6 +234,19 @@ static inline float conv_i2_to_norm_float(const struct gl_context *ctx, int i2) ERROR(GL_INVALID_VALUE); \ } while(0) + +/* Doubles */ +#define ATTR1DV( A, V ) ATTRD( A, 1, (V)[0], 0, 0, 1 ) +#define ATTR2DV( A, V ) ATTRD( A, 2, (V)[0], (V)[1], 0, 1 ) +#define ATTR3DV( A, V ) ATTRD( A, 3, (V)[0], (V)[1], (V)[2], 1 ) +#define ATTR4DV( A, V ) ATTRD( A, 4, (V)[0], (V)[1], (V)[2], (V)[3] ) + +#define ATTR1D( A, X ) ATTRD( A, 1, X, 0, 0, 1 ) +#define ATTR2D( A, X, Y ) ATTRD( A, 2, X, Y, 0, 1 ) +#define ATTR3D( A, X, Y, Z ) ATTRD( A, 3, X, Y, Z, 1 ) +#define ATTR4D( A, X, Y, Z, W ) ATTRD( A, 4, X, Y, Z, W ) + + static void GLAPIENTRY TAG(Vertex2f)(GLfloat x, GLfloat y) { @@ -1190,6 +1205,104 @@ TAG(VertexAttribP4uiv)(GLuint index, GLenum type, GLboolean normalized, } + +static void GLAPIENTRY +TAG(VertexAttribL1d)(GLuint index, GLdouble x) +{ + GET_CURRENT_CONTEXT(ctx); + if (index == 0 && _mesa_attr_zero_aliases_vertex(ctx)) + ATTR1D(0, x); + else if (index < MAX_VERTEX_GENERIC_ATTRIBS) + ATTR1D(VBO_ATTRIB_GENERIC0 + index, x); + else + ERROR(GL_INVALID_VALUE); +} + +static void GLAPIENTRY +TAG(VertexAttribL1dv)(GLuint index, const GLdouble * v) +{ + GET_CURRENT_CONTEXT(ctx); + if (index == 0 && _mesa_attr_zero_aliases_vertex(ctx)) + ATTR1DV(0, v); + else if (index < MAX_VERTEX_GENERIC_ATTRIBS) + ATTR1DV(VBO_ATTRIB_GENERIC0 + index, v); + else + ERROR(GL_INVALID_VALUE); +} + +static void GLAPIENTRY +TAG(VertexAttribL2d)(GLuint index, GLdouble x, GLdouble y) +{ + GET_CURRENT_CONTEXT(ctx); + if (index == 0 && _mesa_attr_zero_aliases_vertex(ctx)) + ATTR2D(0, x, y); + else if (index < MAX_VERTEX_GENERIC_ATTRIBS) + ATTR2D(VBO_ATTRIB_GENERIC0 + index, x, y); + else + ERROR(GL_INVALID_VALUE); +} + +static void GLAPIENTRY +TAG(VertexAttribL2dv)(GLuint index, const GLdouble * v) +{ + GET_CURRENT_CONTEXT(ctx); + if (index == 0 && _mesa_attr_zero_aliases_vertex(ctx)) + ATTR2DV(0, v); + else if (index < MAX_VERTEX_GENERIC_ATTRIBS) + ATTR2DV(VBO_ATTRIB_GENERIC0 + index, v); + else + ERROR(GL_INVALID_VALUE); +} + +static void GLAPIENTRY +TAG(VertexAttribL3d)(GLuint index, GLdouble x, GLdouble y, GLdouble z) +{ + GET_CURRENT_CONTEXT(ctx); + if (index == 0 && _mesa_attr_zero_aliases_vertex(ctx)) + ATTR3D(0, x, y, z); + else if (index < MAX_VERTEX_GENERIC_ATTRIBS) + ATTR3D(VBO_ATTRIB_GENERIC0 + index, x, y, z); + else + ERROR(GL_INVALID_VALUE); +} + +static void GLAPIENTRY +TAG(VertexAttribL3dv)(GLuint index, const GLdouble * v) +{ + GET_CURRENT_CONTEXT(ctx); + if (index == 0 && _mesa_attr_zero_aliases_vertex(ctx)) + ATTR3DV(0, v); + else if (index < MAX_VERTEX_GENERIC_ATTRIBS) + ATTR3DV(VBO_ATTRIB_GENERIC0 + index, v); + else + ERROR(GL_INVALID_VALUE); +} + +static void GLAPIENTRY +TAG(VertexAttribL4d)(GLuint index, GLdouble x, GLdouble y, GLdouble z, GLdouble w) +{ + GET_CURRENT_CONTEXT(ctx); + if (index == 0 && _mesa_attr_zero_aliases_vertex(ctx)) + ATTR4D(0, x, y, z, w); + else if (index < MAX_VERTEX_GENERIC_ATTRIBS) + ATTR4D(VBO_ATTRIB_GENERIC0 + index, x, y, z, w); + else + ERROR(GL_INVALID_VALUE); +} + +static void GLAPIENTRY +TAG(VertexAttribL4dv)(GLuint index, const GLdouble * v) +{ + GET_CURRENT_CONTEXT(ctx); + if (index == 0 && _mesa_attr_zero_aliases_vertex(ctx)) + ATTR4DV(0, v); + else if (index < MAX_VERTEX_GENERIC_ATTRIBS) + ATTR4DV(VBO_ATTRIB_GENERIC0 + index, v); + else + ERROR(GL_INVALID_VALUE); +} + + #undef ATTR1FV #undef ATTR2FV #undef ATTR3FV diff --git a/mesalib/src/mesa/vbo/vbo_context.h b/mesalib/src/mesa/vbo/vbo_context.h index 6099b56e6..a376efe34 100644 --- a/mesalib/src/mesa/vbo/vbo_context.h +++ b/mesalib/src/mesa/vbo/vbo_context.h @@ -146,6 +146,7 @@ vbo_attrtype_to_integer_flag(GLenum format) { switch (format) { case GL_FLOAT: + case GL_DOUBLE: return GL_FALSE; case GL_INT: case GL_UNSIGNED_INT: @@ -156,6 +157,22 @@ vbo_attrtype_to_integer_flag(GLenum format) } } +static inline GLboolean +vbo_attrtype_to_double_flag(GLenum format) +{ + switch (format) { + case GL_FLOAT: + case GL_INT: + case GL_UNSIGNED_INT: + return GL_FALSE; + case GL_DOUBLE: + return GL_TRUE; + default: + assert(0); + return GL_FALSE; + } +} + /** * Return default component values for the given format. * The return type is an array of fi_types, because that's how we declare diff --git a/mesalib/src/mesa/vbo/vbo_exec_api.c b/mesalib/src/mesa/vbo/vbo_exec_api.c index 48680ec88..138cd6051 100644 --- a/mesalib/src/mesa/vbo/vbo_exec_api.c +++ b/mesalib/src/mesa/vbo/vbo_exec_api.c @@ -159,27 +159,36 @@ static void vbo_exec_copy_to_current( struct vbo_exec_context *exec ) * ctx->Current.Attrib and ctx->Light.Material.Attrib arrays. */ GLfloat *current = (GLfloat *)vbo->currval[i].Ptr; - fi_type tmp[4]; + fi_type tmp[8]; /* space for doubles */ + int dmul = exec->vtx.attrtype[i] == GL_DOUBLE ? 2 : 1; + + if (exec->vtx.attrtype[i] == GL_DOUBLE) { + memset(tmp, 0, sizeof(tmp)); + memcpy(tmp, exec->vtx.attrptr[i], exec->vtx.attrsz[i] * sizeof(GLfloat)); + } else { + COPY_CLEAN_4V_TYPE_AS_UNION(tmp, + exec->vtx.attrsz[i], + exec->vtx.attrptr[i], + exec->vtx.attrtype[i]); + } - COPY_CLEAN_4V_TYPE_AS_UNION(tmp, - exec->vtx.attrsz[i], - exec->vtx.attrptr[i], - exec->vtx.attrtype[i]); - if (exec->vtx.attrtype[i] != vbo->currval[i].Type || - memcmp(current, tmp, sizeof(tmp)) != 0) { - memcpy(current, tmp, sizeof(tmp)); + memcmp(current, tmp, 4 * sizeof(GLfloat) * dmul) != 0) { + memcpy(current, tmp, 4 * sizeof(GLfloat) * dmul); /* Given that we explicitly state size here, there is no need * for the COPY_CLEAN above, could just copy 16 bytes and be * done. The only problem is when Mesa accesses ctx->Current * directly. */ - vbo->currval[i].Size = exec->vtx.attrsz[i]; - vbo->currval[i]._ElementSize = vbo->currval[i].Size * sizeof(GLfloat); + /* Size here is in components - not bytes */ + vbo->currval[i].Size = exec->vtx.attrsz[i] / dmul; + vbo->currval[i]._ElementSize = vbo->currval[i].Size * sizeof(GLfloat) * dmul; vbo->currval[i].Type = exec->vtx.attrtype[i]; vbo->currval[i].Integer = vbo_attrtype_to_integer_flag(exec->vtx.attrtype[i]); + vbo->currval[i].Doubles = + vbo_attrtype_to_double_flag(exec->vtx.attrtype[i]); /* This triggers rather too much recalculation of Mesa state * that doesn't get used (eg light positions). @@ -214,13 +223,17 @@ vbo_exec_copy_from_current(struct vbo_exec_context *exec) GLint i; for (i = VBO_ATTRIB_POS + 1; i < VBO_ATTRIB_MAX; i++) { - const fi_type *current = (fi_type *) vbo->currval[i].Ptr; - switch (exec->vtx.attrsz[i]) { - case 4: exec->vtx.attrptr[i][3] = current[3]; - case 3: exec->vtx.attrptr[i][2] = current[2]; - case 2: exec->vtx.attrptr[i][1] = current[1]; - case 1: exec->vtx.attrptr[i][0] = current[0]; - break; + if (exec->vtx.attrtype[i] == GL_DOUBLE) { + memcpy(exec->vtx.attrptr[i], vbo->currval[i].Ptr, exec->vtx.attrsz[i] * sizeof(GLfloat)); + } else { + const fi_type *current = (fi_type *) vbo->currval[i].Ptr; + switch (exec->vtx.attrsz[i]) { + case 4: exec->vtx.attrptr[i][3] = current[3]; + case 3: exec->vtx.attrptr[i][2] = current[2]; + case 2: exec->vtx.attrptr[i][1] = current[1]; + case 1: exec->vtx.attrptr[i][0] = current[0]; + break; + } } } } @@ -364,11 +377,11 @@ vbo_exec_wrap_upgrade_vertex(struct vbo_exec_context *exec, * glTexCoord4f() call. We promote the array from size=2 to size=4. */ static void -vbo_exec_fixup_vertex(struct gl_context *ctx, GLuint attr, GLuint newSize) +vbo_exec_fixup_vertex(struct gl_context *ctx, GLuint attr, GLuint newSize, GLenum newType) { struct vbo_exec_context *exec = &vbo_context(ctx)->exec; - if (newSize > exec->vtx.attrsz[attr]) { + if (newSize > exec->vtx.attrsz[attr] || newType != exec->vtx.attrtype[attr]) { /* New size is larger. Need to flush existing vertices and get * an enlarged vertex format. */ @@ -401,18 +414,19 @@ vbo_exec_fixup_vertex(struct gl_context *ctx, GLuint attr, GLuint newSize) * This macro is used to implement all the glVertex, glColor, glTexCoord, * glVertexAttrib, etc functions. */ -#define ATTR_UNION( A, N, T, V0, V1, V2, V3 ) \ +#define ATTR_UNION( A, N, T, C, V0, V1, V2, V3 ) \ do { \ struct vbo_exec_context *exec = &vbo_context(ctx)->exec; \ - \ + int sz = (sizeof(C) / sizeof(GLfloat)); \ if (unlikely(!(ctx->Driver.NeedFlush & FLUSH_UPDATE_CURRENT))) \ ctx->Driver.BeginVertices( ctx ); \ - \ - if (unlikely(exec->vtx.active_sz[A] != N)) \ - vbo_exec_fixup_vertex(ctx, A, N); \ - \ + \ + if (unlikely(exec->vtx.active_sz[A] != N * sz) || \ + unlikely(exec->vtx.attrtype[A] != T)) \ + vbo_exec_fixup_vertex(ctx, A, N * sz, T); \ + \ { \ - fi_type *dest = exec->vtx.attrptr[A]; \ + C *dest = (C *)exec->vtx.attrptr[A]; \ if (N>0) dest[0] = V0; \ if (N>1) dest[1] = V1; \ if (N>2) dest[2] = V2; \ @@ -438,7 +452,6 @@ do { \ } \ } while (0) - #define ERROR(err) _mesa_error( ctx, err, __func__ ) #define TAG(x) vbo_##x @@ -575,7 +588,7 @@ static void GLAPIENTRY vbo_exec_EvalCoord1f( GLfloat u ) for (i = 0; i <= VBO_ATTRIB_TEX7; i++) { if (exec->eval.map1[i].map) if (exec->vtx.active_sz[i] != exec->eval.map1[i].sz) - vbo_exec_fixup_vertex( ctx, i, exec->eval.map1[i].sz ); + vbo_exec_fixup_vertex( ctx, i, exec->eval.map1[i].sz, GL_FLOAT ); } } @@ -602,12 +615,12 @@ static void GLAPIENTRY vbo_exec_EvalCoord2f( GLfloat u, GLfloat v ) for (i = 0; i <= VBO_ATTRIB_TEX7; i++) { if (exec->eval.map2[i].map) if (exec->vtx.active_sz[i] != exec->eval.map2[i].sz) - vbo_exec_fixup_vertex( ctx, i, exec->eval.map2[i].sz ); + vbo_exec_fixup_vertex( ctx, i, exec->eval.map2[i].sz, GL_FLOAT ); } if (ctx->Eval.AutoNormal) if (exec->vtx.active_sz[VBO_ATTRIB_NORMAL] != 3) - vbo_exec_fixup_vertex( ctx, VBO_ATTRIB_NORMAL, 3 ); + vbo_exec_fixup_vertex( ctx, VBO_ATTRIB_NORMAL, 3, GL_FLOAT ); } memcpy( exec->vtx.copied.buffer, exec->vtx.vertex, @@ -968,6 +981,16 @@ static void vbo_exec_vtxfmt_init( struct vbo_exec_context *exec ) vfmt->VertexAttribP3uiv = vbo_VertexAttribP3uiv; vfmt->VertexAttribP4ui = vbo_VertexAttribP4ui; vfmt->VertexAttribP4uiv = vbo_VertexAttribP4uiv; + + vfmt->VertexAttribL1d = vbo_VertexAttribL1d; + vfmt->VertexAttribL2d = vbo_VertexAttribL2d; + vfmt->VertexAttribL3d = vbo_VertexAttribL3d; + vfmt->VertexAttribL4d = vbo_VertexAttribL4d; + + vfmt->VertexAttribL1dv = vbo_VertexAttribL1dv; + vfmt->VertexAttribL2dv = vbo_VertexAttribL2dv; + vfmt->VertexAttribL3dv = vbo_VertexAttribL3dv; + vfmt->VertexAttribL4dv = vbo_VertexAttribL4dv; } diff --git a/mesalib/src/mesa/vbo/vbo_save_api.c b/mesalib/src/mesa/vbo/vbo_save_api.c index 5927beeb3..29de3d38a 100644 --- a/mesalib/src/mesa/vbo/vbo_save_api.c +++ b/mesalib/src/mesa/vbo/vbo_save_api.c @@ -772,7 +772,7 @@ _save_reset_vertex(struct gl_context *ctx) * 3f version won't otherwise set color[3] to 1.0 -- this is the job * of the chooser function when switching between Color4f and Color3f. */ -#define ATTR_UNION(A, N, T, V0, V1, V2, V3) \ +#define ATTR_UNION(A, N, T, C, V0, V1, V2, V3) \ do { \ struct vbo_save_context *save = &vbo_context(ctx)->save; \ \ @@ -780,7 +780,7 @@ do { \ save_fixup_vertex(ctx, A, N); \ \ { \ - fi_type *dest = save->attrptr[A]; \ + C *dest = (C *)save->attrptr[A]; \ if (N>0) dest[0] = V0; \ if (N>1) dest[1] = V1; \ if (N>2) dest[2] = V2; \ @@ -1372,6 +1372,16 @@ _save_vtxfmt_init(struct gl_context *ctx) vfmt->VertexAttribP3uiv = _save_VertexAttribP3uiv; vfmt->VertexAttribP4uiv = _save_VertexAttribP4uiv; + vfmt->VertexAttribL1d = _save_VertexAttribL1d; + vfmt->VertexAttribL2d = _save_VertexAttribL2d; + vfmt->VertexAttribL3d = _save_VertexAttribL3d; + vfmt->VertexAttribL4d = _save_VertexAttribL4d; + + vfmt->VertexAttribL1dv = _save_VertexAttribL1dv; + vfmt->VertexAttribL2dv = _save_VertexAttribL2dv; + vfmt->VertexAttribL3dv = _save_VertexAttribL3dv; + vfmt->VertexAttribL4dv = _save_VertexAttribL4dv; + /* This will all require us to fallback to saving the list as opcodes: */ vfmt->CallList = _save_CallList; diff --git a/mesalib/src/mesa/vbo/vbo_split_copy.c b/mesalib/src/mesa/vbo/vbo_split_copy.c index d1107dd84..7b1e20b18 100644 --- a/mesalib/src/mesa/vbo/vbo_split_copy.c +++ b/mesalib/src/mesa/vbo/vbo_split_copy.c @@ -533,6 +533,7 @@ replay_init( struct copy_context *copy ) dst->Enabled = GL_TRUE; dst->Normalized = src->Normalized; dst->Integer = src->Integer; + dst->Doubles = src->Doubles; dst->BufferObj = ctx->Shared->NullBufferObj; dst->_ElementSize = src->_ElementSize; diff --git a/mesalib/src/util/Makefile.sources b/mesalib/src/util/Makefile.sources index 3e0d02bad..dc5593918 100644 --- a/mesalib/src/util/Makefile.sources +++ b/mesalib/src/util/Makefile.sources @@ -7,6 +7,7 @@ MESA_UTIL_FILES := \ format_srgb.h \ hash_table.c \ hash_table.h \ + list.h \ macros.h \ ralloc.c \ ralloc.h \ diff --git a/mesalib/src/gallium/auxiliary/util/u_double_list.h b/mesalib/src/util/list.h index 247f0f282..946034710 100644 --- a/mesalib/src/gallium/auxiliary/util/u_double_list.h +++ b/mesalib/src/util/list.h @@ -1,8 +1,8 @@ /************************************************************************** - * + * * Copyright 2006 VMware, Inc., Bismarck, ND. USA. * All Rights Reserved. - * + * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the * "Software"), to deal in the Software without restriction, including @@ -10,36 +10,37 @@ * distribute, sub license, and/or sell copies of the Software, and to * permit persons to whom the Software is furnished to do so, subject to * the following conditions: - * + * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL - * THE COPYRIGHT HOLDERS, AUTHORS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, - * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR - * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE + * THE COPYRIGHT HOLDERS, AUTHORS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR + * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE * USE OR OTHER DEALINGS IN THE SOFTWARE. * * The above copyright notice and this permission notice (including the * next paragraph) shall be included in all copies or substantial portions * of the Software. - * + * **************************************************************************/ /** * \file * List macros heavily inspired by the Linux kernel * list handling. No list looping yet. - * + * * Is not threadsafe, so common operations need to * be protected using an external mutex. */ -#ifndef _U_DOUBLE_LIST_H_ -#define _U_DOUBLE_LIST_H_ +#ifndef _UTIL_LIST_H_ +#define _UTIL_LIST_H_ +#include <stdbool.h> #include <stddef.h> -#include "pipe/p_compiler.h" +#include <assert.h> struct list_head @@ -48,13 +49,13 @@ struct list_head struct list_head *next; }; -static INLINE void list_inithead(struct list_head *item) +static inline void list_inithead(struct list_head *item) { item->prev = item; item->next = item; } -static INLINE void list_add(struct list_head *item, struct list_head *list) +static inline void list_add(struct list_head *item, struct list_head *list) { item->prev = list; item->next = list->next; @@ -62,7 +63,7 @@ static INLINE void list_add(struct list_head *item, struct list_head *list) list->next = item; } -static INLINE void list_addtail(struct list_head *item, struct list_head *list) +static inline void list_addtail(struct list_head *item, struct list_head *list) { item->next = list; item->prev = list->prev; @@ -70,7 +71,7 @@ static INLINE void list_addtail(struct list_head *item, struct list_head *list) list->prev = item; } -static INLINE void list_replace(struct list_head *from, struct list_head *to) +static inline void list_replace(struct list_head *from, struct list_head *to) { to->prev = from->prev; to->next = from->next; @@ -78,14 +79,14 @@ static INLINE void list_replace(struct list_head *from, struct list_head *to) from->prev->next = to; } -static INLINE void list_del(struct list_head *item) +static inline void list_del(struct list_head *item) { item->prev->next = item->next; item->next->prev = item->prev; item->prev = item->next = NULL; } -static INLINE void list_delinit(struct list_head *item) +static inline void list_delinit(struct list_head *item) { item->prev->next = item->next; item->next->prev = item->prev; @@ -93,6 +94,28 @@ static INLINE void list_delinit(struct list_head *item) item->prev = item; } +static inline bool list_empty(struct list_head *list) +{ + return list->next == list; +} + +static inline unsigned list_length(struct list_head *list) +{ + struct list_head *node; + unsigned length = 0; + for (node = list->next; node != list; node = node->next) + length++; + return length; +} + +static inline void list_validate(struct list_head *list) +{ + struct list_head *node; + assert(list->next->prev == list && list->prev->next == list); + for (node = list->next; node != list; node = node->next) + assert(node->next->prev == node && node->prev->next == node); +} + #define LIST_INITHEAD(__item) list_inithead(__item) #define LIST_ADD(__item, __list) list_add(__item, __list) #define LIST_ADDTAIL(__item, __list) list_addtail(__item, __list) @@ -144,4 +167,38 @@ static INLINE void list_delinit(struct list_head *item) &pos->member != (head); \ pos = container_of(pos->member.prev, pos, member)) -#endif /*_U_DOUBLE_LIST_H_*/ +#define list_for_each_entry(type, pos, head, member) \ + for (type *pos = LIST_ENTRY(type, (head)->next, member); \ + &pos->member != (head); \ + pos = LIST_ENTRY(type, pos->member.next, member)) + +#define list_for_each_entry_safe(type, pos, head, member) \ + for (type *pos = LIST_ENTRY(type, (head)->next, member), \ + *__next = LIST_ENTRY(type, pos->member.next, member); \ + &pos->member != (head); \ + pos = __next, \ + __next = LIST_ENTRY(type, __next->member.next, member)) + +#define list_for_each_entry_rev(type, pos, head, member) \ + for (type *pos = LIST_ENTRY(type, (head)->prev, member); \ + &pos->member != (head); \ + pos = LIST_ENTRY(type, pos->member.prev, member)) + +#define list_for_each_entry_safe_rev(type, pos, head, member) \ + for (type *pos = LIST_ENTRY(type, (head)->prev, member), \ + *__prev = LIST_ENTRY(type, pos->member.prev, member); \ + &pos->member != (head); \ + pos = __prev, \ + __prev = LIST_ENTRY(type, __prev->member.prev, member)) + +#define list_for_each_entry_from(type, pos, start, head, member) \ + for (type *pos = LIST_ENTRY(type, (start), member); \ + &pos->member != (head); \ + pos = LIST_ENTRY(type, pos->member.next, member)) + +#define list_for_each_entry_from_rev(type, pos, start, head, member) \ + for (type *pos = LIST_ENTRY(type, (start), member); \ + &pos->member != (head); \ + pos = LIST_ENTRY(type, pos->member.prev, member)) + +#endif /*_UTIL_LIST_H_*/ |