diff options
author | marha <marha@users.sourceforge.net> | 2015-03-22 14:10:47 +0100 |
---|---|---|
committer | marha <marha@users.sourceforge.net> | 2015-03-22 14:10:47 +0100 |
commit | 3bc24b271f45f9f33484b8cf53b44f33f7e8a237 (patch) | |
tree | 193651a94adb3804e800747e993d07b92688e4d4 /mesalib/src | |
parent | c646056120fe14e4c4ccf81bac5d78d61225a8e8 (diff) | |
parent | 82c8df11062f72a7d467e26cedbbd8b322ff7a70 (diff) | |
download | vcxsrv-3bc24b271f45f9f33484b8cf53b44f33f7e8a237.tar.gz vcxsrv-3bc24b271f45f9f33484b8cf53b44f33f7e8a237.tar.bz2 vcxsrv-3bc24b271f45f9f33484b8cf53b44f33f7e8a237.zip |
Merge remote-tracking branch 'origin/released'
Conflicts:
mesalib/src/mapi/glapi/glapi.h
mesalib/src/mapi/glapi/glapi_nop.c
mesalib/src/mesa/main/bufferobj.c
Diffstat (limited to 'mesalib/src')
97 files changed, 2850 insertions, 1806 deletions
diff --git a/mesalib/src/gallium/Makefile.am b/mesalib/src/gallium/Makefile.am index 652cb1310..ede6e2123 100644 --- a/mesalib/src/gallium/Makefile.am +++ b/mesalib/src/gallium/Makefile.am @@ -11,7 +11,6 @@ SUBDIRS += auxiliary ## SUBDIRS += \ - drivers/galahad \ drivers/noop \ drivers/trace \ drivers/rbug @@ -96,14 +95,6 @@ if HAVE_DRI2 SUBDIRS += winsys/sw/kms-dri endif -if HAVE_EGL_PLATFORM_FBDEV -SUBDIRS += winsys/sw/fbdev -endif - -if HAVE_EGL_PLATFORM_WAYLAND -SUBDIRS += winsys/sw/wayland -endif - SUBDIRS += winsys/sw/wrapper ## @@ -114,8 +105,6 @@ EXTRA_DIST = \ docs \ README.portability \ SConscript \ - state_trackers/gbm \ - targets/gbm \ winsys/sw/gdi \ winsys/sw/hgl diff --git a/mesalib/src/gallium/SConscript b/mesalib/src/gallium/SConscript index 9b9011f7f..680ad925f 100644 --- a/mesalib/src/gallium/SConscript +++ b/mesalib/src/gallium/SConscript @@ -12,7 +12,6 @@ SConscript('auxiliary/SConscript') # These are common and work across all platforms SConscript([ - 'drivers/galahad/SConscript', 'drivers/llvmpipe/SConscript', 'drivers/rbug/SConscript', 'drivers/softpipe/SConscript', diff --git a/mesalib/src/gallium/auxiliary/util/u_slab.h b/mesalib/src/gallium/auxiliary/util/u_slab.h index 29d0252ba..0df039bcd 100644 --- a/mesalib/src/gallium/auxiliary/util/u_slab.h +++ b/mesalib/src/gallium/auxiliary/util/u_slab.h @@ -81,7 +81,16 @@ void util_slab_destroy(struct util_slab_mempool *pool); void util_slab_set_thread_safety(struct util_slab_mempool *pool, enum util_slab_threading threading); -#define util_slab_alloc(pool) (pool)->alloc(pool) -#define util_slab_free(pool, ptr) (pool)->free(pool, ptr) +static inline void * +util_slab_alloc(struct util_slab_mempool *pool) +{ + return pool->alloc(pool); +} + +static inline void +util_slab_free(struct util_slab_mempool *pool, void *ptr) +{ + pool->free(pool, ptr); +} #endif diff --git a/mesalib/src/glsl/SConscript b/mesalib/src/glsl/SConscript index 26de455f0..284b37584 100644 --- a/mesalib/src/glsl/SConscript +++ b/mesalib/src/glsl/SConscript @@ -24,22 +24,26 @@ env.Prepend(LIBS = [mesautil]) # Make glcpp-parse.h and glsl_parser.h reachable from the include path. env.Append(CPPPATH = [Dir('.').abspath, Dir('glcpp').abspath]) -env.Append(YACCFLAGS = '-d -p "glcpp_parser_"') +glcpp_env = env.Clone() +glcpp_env.Append(YACCFLAGS = [ + '-d', + '-p', 'glcpp_parser_' +]) -parser_env = env.Clone() -parser_env.Append(YACCFLAGS = [ +glsl_env = env.Clone() +glsl_env.Append(YACCFLAGS = [ '--defines=%s' % File('glsl_parser.h').abspath, '-p', '_mesa_glsl_', ]) # without this line scons will expect "glsl_parser.hpp" instead of # "glsl_parser.h", causing glsl_parser.cpp to be regenerated every time -parser_env['YACCHXXFILESUFFIX'] = '.h' +glsl_env['YACCHXXFILESUFFIX'] = '.h' -glcpp_lexer = env.CFile('glcpp/glcpp-lex.c', 'glcpp/glcpp-lex.l') -glcpp_parser = env.CFile('glcpp/glcpp-parse.c', 'glcpp/glcpp-parse.y') -glsl_lexer = parser_env.CXXFile('glsl_lexer.cpp', 'glsl_lexer.ll') -glsl_parser = parser_env.CXXFile('glsl_parser.cpp', 'glsl_parser.yy') +glcpp_lexer = glcpp_env.CFile('glcpp/glcpp-lex.c', 'glcpp/glcpp-lex.l') +glcpp_parser = glcpp_env.CFile('glcpp/glcpp-parse.c', 'glcpp/glcpp-parse.y') +glsl_lexer = glsl_env.CXXFile('glsl_lexer.cpp', 'glsl_lexer.ll') +glsl_parser = glsl_env.CXXFile('glsl_parser.cpp', 'glsl_parser.yy') # common generated sources glsl_sources = [ diff --git a/mesalib/src/glsl/ast_to_hir.cpp b/mesalib/src/glsl/ast_to_hir.cpp index acb5c763c..d387b2e35 100644 --- a/mesalib/src/glsl/ast_to_hir.cpp +++ b/mesalib/src/glsl/ast_to_hir.cpp @@ -1617,6 +1617,12 @@ ast_expression::do_hir(exec_list *instructions, && cond_val != NULL) { result = cond_val->value.b[0] ? op[1] : op[2]; } else { + /* The copy to conditional_tmp reads the whole array. */ + if (type->is_array()) { + mark_whole_array_access(op[1]); + mark_whole_array_access(op[2]); + } + ir_variable *const tmp = new(ctx) ir_variable(type, "conditional_tmp", ir_var_temporary); instructions->push_tail(tmp); diff --git a/mesalib/src/glsl/builtin_functions.cpp b/mesalib/src/glsl/builtin_functions.cpp index 28bcfdb3c..e46db8552 100755 --- a/mesalib/src/glsl/builtin_functions.cpp +++ b/mesalib/src/glsl/builtin_functions.cpp @@ -201,7 +201,7 @@ static bool shader_packing_or_es3(const _mesa_glsl_parse_state *state) { return state->ARB_shading_language_packing_enable || - state->is_version(400, 300); + state->is_version(420, 300); } static bool diff --git a/mesalib/src/glsl/glsl_parser.yy b/mesalib/src/glsl/glsl_parser.yy index 4a2ebeb40..d33fcfe6b 100644 --- a/mesalib/src/glsl/glsl_parser.yy +++ b/mesalib/src/glsl/glsl_parser.yy @@ -35,6 +35,10 @@ #include "glsl_types.h" #include "main/context.h" +#ifdef _MSC_VER +#pragma warning( disable : 4065 ) // switch statement contains 'default' but no 'case' labels +#endif + #undef yyerror static void yyerror(YYLTYPE *loc, _mesa_glsl_parse_state *st, const char *msg) diff --git a/mesalib/src/glsl/ir.h b/mesalib/src/glsl/ir.h index 25f2ecada..fdc22edf1 100644 --- a/mesalib/src/glsl/ir.h +++ b/mesalib/src/glsl/ir.h @@ -119,6 +119,7 @@ public: /*@{*/ class ir_rvalue *as_rvalue() { + assume(this != NULL); if (ir_type == ir_type_dereference_array || ir_type == ir_type_dereference_record || ir_type == ir_type_dereference_variable || @@ -132,6 +133,7 @@ public: class ir_dereference *as_dereference() { + assume(this != NULL); if (ir_type == ir_type_dereference_array || ir_type == ir_type_dereference_record || ir_type == ir_type_dereference_variable) @@ -141,6 +143,7 @@ public: class ir_jump *as_jump() { + assume(this != NULL); if (ir_type == ir_type_loop_jump || ir_type == ir_type_return || ir_type == ir_type_discard) @@ -151,6 +154,7 @@ public: #define AS_CHILD(TYPE) \ class ir_##TYPE * as_##TYPE() \ { \ + assume(this != NULL); \ return ir_type == ir_type_##TYPE ? (ir_##TYPE *) this : NULL; \ } AS_CHILD(variable) diff --git a/mesalib/src/glsl/ir_constant_expression.cpp b/mesalib/src/glsl/ir_constant_expression.cpp index e24cad98d..d198276c6 100755 --- a/mesalib/src/glsl/ir_constant_expression.cpp +++ b/mesalib/src/glsl/ir_constant_expression.cpp @@ -35,6 +35,7 @@ #include <math.h> #include "main/core.h" /* for MAX2, MIN2, CLAMP */ +#include "util/rounding.h" /* for _mesa_roundeven */ #include "ir.h" #include "glsl_types.h" #include "program/hash_table.h" @@ -238,8 +239,8 @@ pack_snorm_1x8(float x) * We must first cast the float to an int, because casting a negative * float to a uint is undefined. */ - return (uint8_t) (int8_t) - _mesa_round_to_even(CLAMP(x, -1.0f, +1.0f) * 127.0f); + return (uint8_t) (int) + _mesa_roundevenf(CLAMP(x, -1.0f, +1.0f) * 127.0f); } /** @@ -260,8 +261,8 @@ pack_snorm_1x16(float x) * We must first cast the float to an int, because casting a negative * float to a uint is undefined. */ - return (uint16_t) (int16_t) - _mesa_round_to_even(CLAMP(x, -1.0f, +1.0f) * 32767.0f); + return (uint16_t) (int) + _mesa_roundevenf(CLAMP(x, -1.0f, +1.0f) * 32767.0f); } /** @@ -315,7 +316,7 @@ pack_unorm_1x8(float x) * * packUnorm4x8: round(clamp(c, 0, +1) * 255.0) */ - return (uint8_t) _mesa_round_to_even(CLAMP(x, 0.0f, 1.0f) * 255.0f); + return (uint8_t) (int) _mesa_roundevenf(CLAMP(x, 0.0f, 1.0f) * 255.0f); } /** @@ -333,7 +334,8 @@ pack_unorm_1x16(float x) * * packUnorm2x16: round(clamp(c, 0, +1) * 65535.0) */ - return (uint16_t) _mesa_round_to_even(CLAMP(x, 0.0f, 1.0f) * 65535.0f); + return (uint16_t) (int) + _mesa_roundevenf(CLAMP(x, 0.0f, 1.0f) * 65535.0f); } /** @@ -726,9 +728,9 @@ ir_expression::constant_expression_value(struct hash_table *variable_context) case ir_unop_round_even: for (unsigned c = 0; c < op[0]->type->components(); c++) { if (op[0]->type->base_type == GLSL_TYPE_DOUBLE) - data.d[c] = _mesa_round_to_even(op[0]->value.d[c]); + data.d[c] = _mesa_roundeven(op[0]->value.d[c]); else - data.f[c] = _mesa_round_to_even(op[0]->value.f[c]); + data.f[c] = _mesa_roundevenf(op[0]->value.f[c]); } break; diff --git a/mesalib/src/glsl/linker.cpp b/mesalib/src/glsl/linker.cpp index 0c4467779..4349f0973 100644 --- a/mesalib/src/glsl/linker.cpp +++ b/mesalib/src/glsl/linker.cpp @@ -2542,8 +2542,9 @@ link_shaders(struct gl_context *ctx, struct gl_shader_program *prog) goto done; } - prog->ARB_fragment_coord_conventions_enable |= - prog->Shaders[i]->ARB_fragment_coord_conventions_enable; + if (prog->Shaders[i]->ARB_fragment_coord_conventions_enable) { + prog->ARB_fragment_coord_conventions_enable = true; + } gl_shader_stage shader_type = prog->Shaders[i]->Stage; shader_list[shader_type][num_shaders[shader_type]] = prog->Shaders[i]; diff --git a/mesalib/src/glsl/list.h b/mesalib/src/glsl/list.h index 8554a4652..d855240cb 100644 --- a/mesalib/src/glsl/list.h +++ b/mesalib/src/glsl/list.h @@ -692,7 +692,7 @@ inline void exec_node::insert_before(exec_list *before) exec_node_data(__type, (__list)->head, __field), \ * __next = \ exec_node_data(__type, (__node)->__field.next, __field); \ - __next != NULL; \ + (__node)->__field.next != NULL; \ __node = __next, __next = \ exec_node_data(__type, (__next)->__field.next, __field)) @@ -701,7 +701,7 @@ inline void exec_node::insert_before(exec_list *before) exec_node_data(__type, (__list)->tail_pred, __field), \ * __prev = \ exec_node_data(__type, (__node)->__field.prev, __field); \ - __prev != NULL; \ + (__node)->__field.prev != NULL; \ __node = __prev, __prev = \ exec_node_data(__type, (__prev)->__field.prev, __field)) diff --git a/mesalib/src/glsl/nir/glsl_to_nir.cpp b/mesalib/src/glsl/nir/glsl_to_nir.cpp index adef19c80..357944da6 100644 --- a/mesalib/src/glsl/nir/glsl_to_nir.cpp +++ b/mesalib/src/glsl/nir/glsl_to_nir.cpp @@ -43,7 +43,7 @@ namespace { class nir_visitor : public ir_visitor { public: - nir_visitor(nir_shader *shader, bool supports_ints); + nir_visitor(nir_shader *shader, gl_shader_stage stage); ~nir_visitor(); virtual void visit(ir_variable *); @@ -83,6 +83,7 @@ private: bool supports_ints; nir_shader *shader; + gl_shader_stage stage; nir_function_impl *impl; exec_list *cf_node_list; nir_instr *result; /* result of the expression tree last visited */ @@ -124,59 +125,24 @@ private: }; /* end of anonymous namespace */ -static const nir_shader_compiler_options default_options = { -}; - nir_shader * -glsl_to_nir(exec_list *ir, _mesa_glsl_parse_state *state, - bool native_integers) +glsl_to_nir(struct gl_shader *sh, const nir_shader_compiler_options *options) { - const nir_shader_compiler_options *options; - - if (state) { - struct gl_context *ctx = state->ctx; - struct gl_shader_compiler_options *gl_options = - &ctx->Const.ShaderCompilerOptions[state->stage]; - - if (!gl_options->NirOptions) { - nir_shader_compiler_options *new_options = - rzalloc(ctx, nir_shader_compiler_options); - options = gl_options->NirOptions = new_options; - - if (gl_options->EmitNoPow) - new_options->lower_fpow = true; - } else { - options = gl_options->NirOptions; - } - } else { - options = &default_options; - } - nir_shader *shader = nir_shader_create(NULL, options); - if (state) { - shader->num_user_structures = state->num_user_structures; - shader->user_structures = ralloc_array(shader, glsl_type *, - shader->num_user_structures); - memcpy(shader->user_structures, state->user_structures, - shader->num_user_structures * sizeof(glsl_type *)); - } else { - shader->num_user_structures = 0; - shader->user_structures = NULL; - } - - nir_visitor v1(shader, native_integers); + nir_visitor v1(shader, sh->Stage); nir_function_visitor v2(&v1); - v2.run(ir); - visit_exec_list(ir, &v1); + v2.run(sh->ir); + visit_exec_list(sh->ir, &v1); return shader; } -nir_visitor::nir_visitor(nir_shader *shader, bool supports_ints) +nir_visitor::nir_visitor(nir_shader *shader, gl_shader_stage stage) { - this->supports_ints = supports_ints; + this->supports_ints = shader->options->native_integers; this->shader = shader; + this->stage = stage; this->is_global = true; this->var_table = _mesa_hash_table_create(NULL, _mesa_hash_pointer, _mesa_key_pointer_equal); @@ -285,7 +251,8 @@ nir_visitor::visit(ir_variable *ir) break; case ir_var_shader_in: - if (ir->data.location == VARYING_SLOT_FACE) { + if (stage == MESA_SHADER_FRAGMENT && + ir->data.location == VARYING_SLOT_FACE) { /* For whatever reason, GLSL IR makes gl_FrontFacing an input */ var->data.location = SYSTEM_VALUE_FRONT_FACE; var->data.mode = nir_var_system_value; @@ -385,15 +352,15 @@ nir_visitor::visit(ir_variable *ir) break; case nir_var_shader_in: - _mesa_hash_table_insert(shader->inputs, var->name, var); + exec_list_push_tail(&shader->inputs, &var->node); break; case nir_var_shader_out: - _mesa_hash_table_insert(shader->outputs, var->name, var); + exec_list_push_tail(&shader->outputs, &var->node); break; case nir_var_uniform: - _mesa_hash_table_insert(shader->uniforms, var->name, var); + exec_list_push_tail(&shader->uniforms, &var->node); break; case nir_var_system_value: diff --git a/mesalib/src/glsl/nir/glsl_to_nir.h b/mesalib/src/glsl/nir/glsl_to_nir.h index 58b2cee6a..3801e8c55 100644 --- a/mesalib/src/glsl/nir/glsl_to_nir.h +++ b/mesalib/src/glsl/nir/glsl_to_nir.h @@ -32,8 +32,8 @@ extern "C" { #endif -nir_shader *glsl_to_nir(exec_list * ir, _mesa_glsl_parse_state *state, - bool native_integers); +nir_shader *glsl_to_nir(struct gl_shader *sh, + const nir_shader_compiler_options *options); #ifdef __cplusplus } diff --git a/mesalib/src/glsl/nir/nir.c b/mesalib/src/glsl/nir/nir.c index ab57fd4e2..6459d5108 100644 --- a/mesalib/src/glsl/nir/nir.c +++ b/mesalib/src/glsl/nir/nir.c @@ -33,18 +33,12 @@ nir_shader_create(void *mem_ctx, const nir_shader_compiler_options *options) { nir_shader *shader = ralloc(mem_ctx, nir_shader); - shader->uniforms = _mesa_hash_table_create(shader, _mesa_key_hash_string, - _mesa_key_string_equal); - shader->inputs = _mesa_hash_table_create(shader, _mesa_key_hash_string, - _mesa_key_string_equal); - shader->outputs = _mesa_hash_table_create(shader, _mesa_key_hash_string, - _mesa_key_string_equal); + exec_list_make_empty(&shader->uniforms); + exec_list_make_empty(&shader->inputs); + exec_list_make_empty(&shader->outputs); shader->options = options; - shader->num_user_structures = 0; - shader->user_structures = NULL; - exec_list_make_empty(&shader->functions); exec_list_make_empty(&shader->registers); exec_list_make_empty(&shader->globals); diff --git a/mesalib/src/glsl/nir/nir.h b/mesalib/src/glsl/nir/nir.h index d5df59609..29fe94243 100644 --- a/mesalib/src/glsl/nir/nir.h +++ b/mesalib/src/glsl/nir/nir.h @@ -1370,17 +1370,23 @@ typedef struct nir_shader_compiler_options { bool lower_fsqrt; /** lowers fneg and ineg to fsub and isub. */ bool lower_negate; + + /** + * Does the driver support real 32-bit integers? (Otherwise, integers + * are simulated by floats.) + */ + bool native_integers; } nir_shader_compiler_options; typedef struct nir_shader { /** hash table of name -> uniform nir_variable */ - struct hash_table *uniforms; + struct exec_list uniforms; /** hash table of name -> input nir_variable */ - struct hash_table *inputs; + struct exec_list inputs; /** hash table of name -> output nir_variable */ - struct hash_table *outputs; + struct exec_list outputs; /** Set of driver-specific options for the shader. * @@ -1400,10 +1406,6 @@ typedef struct nir_shader { /** list of global register in the shader */ struct exec_list registers; - /** structures used in this shader */ - unsigned num_user_structures; - struct glsl_type **user_structures; - /** next available global register index */ unsigned reg_alloc; @@ -1575,6 +1577,13 @@ void nir_lower_global_vars_to_local(nir_shader *shader); void nir_lower_locals_to_regs(nir_shader *shader); +void nir_assign_var_locations_scalar(struct exec_list *var_list, + unsigned *size); +void nir_assign_var_locations_scalar_direct_first(nir_shader *shader, + struct exec_list *var_list, + unsigned *direct_size, + unsigned *size); + void nir_lower_io(nir_shader *shader); void nir_lower_vars_to_ssa(nir_shader *shader); diff --git a/mesalib/src/glsl/nir/nir_constant_expressions.py b/mesalib/src/glsl/nir/nir_constant_expressions.py index 22bc4f095..bf82fe533 100644 --- a/mesalib/src/glsl/nir/nir_constant_expressions.py +++ b/mesalib/src/glsl/nir/nir_constant_expressions.py @@ -28,6 +28,7 @@ template = """\ #include <math.h> #include "main/core.h" +#include "util/rounding.h" /* for _mesa_roundeven */ #include "nir_constant_expressions.h" #if defined(_MSC_VER) && (_MSC_VER < 1800) @@ -68,8 +69,8 @@ pack_snorm_1x8(float x) * We must first cast the float to an int, because casting a negative * float to a uint is undefined. */ - return (uint8_t) (int8_t) - _mesa_round_to_even(CLAMP(x, -1.0f, +1.0f) * 127.0f); + return (uint8_t) (int) + _mesa_roundevenf(CLAMP(x, -1.0f, +1.0f) * 127.0f); } /** @@ -90,8 +91,8 @@ pack_snorm_1x16(float x) * We must first cast the float to an int, because casting a negative * float to a uint is undefined. */ - return (uint16_t) (int16_t) - _mesa_round_to_even(CLAMP(x, -1.0f, +1.0f) * 32767.0f); + return (uint16_t) (int) + _mesa_roundevenf(CLAMP(x, -1.0f, +1.0f) * 32767.0f); } /** @@ -145,7 +146,8 @@ pack_unorm_1x8(float x) * * packUnorm4x8: round(clamp(c, 0, +1) * 255.0) */ - return (uint8_t) _mesa_round_to_even(CLAMP(x, 0.0f, 1.0f) * 255.0f); + return (uint8_t) (int) + _mesa_roundevenf(CLAMP(x, 0.0f, 1.0f) * 255.0f); } /** @@ -163,7 +165,8 @@ pack_unorm_1x16(float x) * * packUnorm2x16: round(clamp(c, 0, +1) * 65535.0) */ - return (uint16_t) _mesa_round_to_even(CLAMP(x, 0.0f, 1.0f) * 65535.0f); + return (uint16_t) (int) + _mesa_roundevenf(CLAMP(x, 0.0f, 1.0f) * 65535.0f); } /** diff --git a/mesalib/src/glsl/nir/nir_intrinsics.h b/mesalib/src/glsl/nir/nir_intrinsics.h index 3bf102fc1..8e28765c1 100644 --- a/mesalib/src/glsl/nir/nir_intrinsics.h +++ b/mesalib/src/glsl/nir/nir_intrinsics.h @@ -95,6 +95,8 @@ ATOMIC(read, NIR_INTRINSIC_CAN_ELIMINATE) SYSTEM_VALUE(front_face, 1) SYSTEM_VALUE(vertex_id, 1) +SYSTEM_VALUE(vertex_id_zero_base, 1) +SYSTEM_VALUE(base_vertex, 1) SYSTEM_VALUE(instance_id, 1) SYSTEM_VALUE(sample_id, 1) SYSTEM_VALUE(sample_pos, 2) diff --git a/mesalib/src/glsl/nir/nir_lower_io.c b/mesalib/src/glsl/nir/nir_lower_io.c index 207f8daa1..03eed04e1 100644 --- a/mesalib/src/glsl/nir/nir_lower_io.c +++ b/mesalib/src/glsl/nir/nir_lower_io.c @@ -76,15 +76,12 @@ type_size(const struct glsl_type *type) return 0; } -static void -assign_var_locations(struct hash_table *ht, unsigned *size) +void +nir_assign_var_locations_scalar(struct exec_list *var_list, unsigned *size) { unsigned location = 0; - struct hash_entry *entry; - hash_table_foreach(ht, entry) { - nir_variable *var = (nir_variable *) entry->data; - + foreach_list_typed(nir_variable, var, node, var_list) { /* * UBO's have their own address spaces, so don't count them towards the * number of global uniforms @@ -99,14 +96,6 @@ assign_var_locations(struct hash_table *ht, unsigned *size) *size = location; } -static void -assign_var_locations_shader(nir_shader *shader) -{ - assign_var_locations(shader->inputs, &shader->num_inputs); - assign_var_locations(shader->outputs, &shader->num_outputs); - assign_var_locations(shader->uniforms, &shader->num_uniforms); -} - static bool deref_has_indirect(nir_deref_var *deref) { @@ -121,6 +110,77 @@ deref_has_indirect(nir_deref_var *deref) return false; } +static bool +mark_indirect_uses_block(nir_block *block, void *void_state) +{ + struct set *indirect_set = void_state; + + nir_foreach_instr(block, instr) { + if (instr->type != nir_instr_type_intrinsic) + continue; + + nir_intrinsic_instr *intrin = nir_instr_as_intrinsic(instr); + + for (unsigned i = 0; + i < nir_intrinsic_infos[intrin->intrinsic].num_variables; i++) { + if (deref_has_indirect(intrin->variables[i])) + _mesa_set_add(indirect_set, intrin->variables[i]->var); + } + } + + return true; +} + +/* Identical to nir_assign_var_locations_packed except that it assigns + * locations to the variables that are used 100% directly first and then + * assigns locations to variables that are used indirectly. + */ +void +nir_assign_var_locations_scalar_direct_first(nir_shader *shader, + struct exec_list *var_list, + unsigned *direct_size, + unsigned *size) +{ + struct set *indirect_set = _mesa_set_create(NULL, _mesa_hash_pointer, + _mesa_key_pointer_equal); + + nir_foreach_overload(shader, overload) { + if (overload->impl) + nir_foreach_block(overload->impl, mark_indirect_uses_block, + indirect_set); + } + + unsigned location = 0; + + foreach_list_typed(nir_variable, var, node, var_list) { + if (var->data.mode == nir_var_uniform && var->interface_type != NULL) + continue; + + if (_mesa_set_search(indirect_set, var)) + continue; + + var->data.driver_location = location; + location += type_size(var->type); + } + + *direct_size = location; + + foreach_list_typed(nir_variable, var, node, var_list) { + if (var->data.mode == nir_var_uniform && var->interface_type != NULL) + continue; + + if (!_mesa_set_search(indirect_set, var)) + continue; + + var->data.driver_location = location; + location += type_size(var->type); + } + + *size = location; + + _mesa_set_destroy(indirect_set, NULL); +} + static unsigned get_io_offset(nir_deref_var *deref, nir_instr *instr, nir_src *indirect, struct lower_io_state *state) @@ -307,8 +367,6 @@ nir_lower_io_impl(nir_function_impl *impl) void nir_lower_io(nir_shader *shader) { - assign_var_locations_shader(shader); - nir_foreach_overload(shader, overload) { if (overload->impl) nir_lower_io_impl(overload->impl); diff --git a/mesalib/src/glsl/nir/nir_lower_system_values.c b/mesalib/src/glsl/nir/nir_lower_system_values.c index 328d4f1ab..a6eec653e 100644 --- a/mesalib/src/glsl/nir/nir_lower_system_values.c +++ b/mesalib/src/glsl/nir/nir_lower_system_values.c @@ -49,6 +49,12 @@ convert_instr(nir_intrinsic_instr *instr) case SYSTEM_VALUE_VERTEX_ID: op = nir_intrinsic_load_vertex_id; break; + case SYSTEM_VALUE_VERTEX_ID_ZERO_BASE: + op = nir_intrinsic_load_vertex_id_zero_base; + break; + case SYSTEM_VALUE_BASE_VERTEX: + op = nir_intrinsic_load_base_vertex; + break; case SYSTEM_VALUE_INSTANCE_ID: op = nir_intrinsic_load_instance_id; break; 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 9e9a418e3..86e6ab416 100644 --- a/mesalib/src/glsl/nir/nir_lower_vars_to_ssa.c +++ b/mesalib/src/glsl/nir/nir_lower_vars_to_ssa.c @@ -35,6 +35,13 @@ struct deref_node { bool lower_to_ssa; + /* Only valid for things that end up in the direct list. + * Note that multiple nir_deref_vars may correspond to this node, but they + * will all be equivalent, so any is as good as the other. + */ + nir_deref_var *deref; + struct exec_node direct_derefs_link; + struct set *loads; struct set *stores; struct set *copies; @@ -69,7 +76,7 @@ struct lower_variables_state { * wildcards and no indirects, these are precisely the derefs that we * can actually consider lowering. */ - struct hash_table *direct_deref_nodes; + struct exec_list direct_deref_nodes; /* Controls whether get_deref_node will add variables to the * direct_deref_nodes table. This is turned on when we are initially @@ -83,88 +90,6 @@ struct lower_variables_state { struct hash_table *phi_table; }; -/* The following two functions implement a hash and equality check for - * variable dreferences. When the hash or equality function encounters an - * array, all indirects are treated as equal and are never equal to a - * direct dereference or a wildcard. - */ -static uint32_t -hash_deref(const void *void_deref) -{ - uint32_t hash = _mesa_fnv32_1a_offset_bias; - - const nir_deref_var *deref_var = void_deref; - hash = _mesa_fnv32_1a_accumulate(hash, deref_var->var); - - for (const nir_deref *deref = deref_var->deref.child; - deref; deref = deref->child) { - switch (deref->deref_type) { - case nir_deref_type_array: { - nir_deref_array *deref_array = nir_deref_as_array(deref); - - hash = _mesa_fnv32_1a_accumulate(hash, deref_array->deref_array_type); - - if (deref_array->deref_array_type == nir_deref_array_type_direct) - hash = _mesa_fnv32_1a_accumulate(hash, deref_array->base_offset); - break; - } - case nir_deref_type_struct: { - nir_deref_struct *deref_struct = nir_deref_as_struct(deref); - hash = _mesa_fnv32_1a_accumulate(hash, deref_struct->index); - break; - } - default: - assert("Invalid deref chain"); - } - } - - return hash; -} - -static bool -derefs_equal(const void *void_a, const void *void_b) -{ - const nir_deref_var *a_var = void_a; - const nir_deref_var *b_var = void_b; - - if (a_var->var != b_var->var) - return false; - - for (const nir_deref *a = a_var->deref.child, *b = b_var->deref.child; - a != NULL; a = a->child, b = b->child) { - if (a->deref_type != b->deref_type) - return false; - - switch (a->deref_type) { - case nir_deref_type_array: { - nir_deref_array *a_arr = nir_deref_as_array(a); - nir_deref_array *b_arr = nir_deref_as_array(b); - - if (a_arr->deref_array_type != b_arr->deref_array_type) - return false; - - if (a_arr->deref_array_type == nir_deref_array_type_direct && - a_arr->base_offset != b_arr->base_offset) - return false; - break; - } - case nir_deref_type_struct: - if (nir_deref_as_struct(a)->index != nir_deref_as_struct(b)->index) - return false; - break; - default: - assert("Invalid deref chain"); - return false; - } - - assert((a->child == NULL) == (b->child == NULL)); - if((a->child == NULL) != (b->child == NULL)) - return false; - } - - return true; -} - static int type_get_length(const struct glsl_type *type) { @@ -195,6 +120,8 @@ deref_node_create(struct deref_node *parent, struct deref_node *node = rzalloc_size(mem_ctx, size); node->type = type; node->parent = parent; + node->deref = NULL; + exec_node_init(&node->direct_derefs_link); return node; } @@ -297,8 +224,14 @@ get_deref_node(nir_deref_var *deref, struct lower_variables_state *state) assert(node); - if (is_direct && state->add_to_direct_deref_nodes) - _mesa_hash_table_insert(state->direct_deref_nodes, deref, node); + /* Only insert if it isn't already in the list. */ + if (is_direct && state->add_to_direct_deref_nodes && + node->direct_derefs_link.next == NULL) { + node->deref = deref; + assert(deref->var != NULL); + exec_list_push_tail(&state->direct_deref_nodes, + &node->direct_derefs_link); + } return node; } @@ -917,10 +850,8 @@ insert_phi_nodes(struct lower_variables_state *state) unsigned w_start, w_end; unsigned iter_count = 0; - struct hash_entry *deref_entry; - hash_table_foreach(state->direct_deref_nodes, deref_entry) { - struct deref_node *node = deref_entry->data; - + foreach_list_typed(struct deref_node, node, direct_derefs_link, + &state->direct_deref_nodes) { if (node->stores == NULL) continue; @@ -1014,8 +945,7 @@ nir_lower_vars_to_ssa_impl(nir_function_impl *impl) state.deref_var_nodes = _mesa_hash_table_create(state.dead_ctx, _mesa_hash_pointer, _mesa_key_pointer_equal); - state.direct_deref_nodes = _mesa_hash_table_create(state.dead_ctx, - hash_deref, derefs_equal); + exec_list_make_empty(&state.direct_deref_nodes); state.phi_table = _mesa_hash_table_create(state.dead_ctx, _mesa_hash_pointer, _mesa_key_pointer_equal); @@ -1035,18 +965,17 @@ nir_lower_vars_to_ssa_impl(nir_function_impl *impl) /* We're about to iterate through direct_deref_nodes. Don't modify it. */ state.add_to_direct_deref_nodes = false; - struct hash_entry *entry; - hash_table_foreach(state.direct_deref_nodes, entry) { - nir_deref_var *deref = (void *)entry->key; - struct deref_node *node = entry->data; + foreach_list_typed_safe(struct deref_node, node, direct_derefs_link, + &state.direct_deref_nodes) { + nir_deref_var *deref = node->deref; if (deref->var->data.mode != nir_var_local) { - _mesa_hash_table_remove(state.direct_deref_nodes, entry); + exec_node_remove(&node->direct_derefs_link); continue; } if (deref_may_be_aliased(deref, &state)) { - _mesa_hash_table_remove(state.direct_deref_nodes, entry); + exec_node_remove(&node->direct_derefs_link); continue; } diff --git a/mesalib/src/glsl/nir/nir_opcodes.py b/mesalib/src/glsl/nir/nir_opcodes.py index 77f3bb826..062cd628b 100644 --- a/mesalib/src/glsl/nir/nir_opcodes.py +++ b/mesalib/src/glsl/nir/nir_opcodes.py @@ -183,7 +183,7 @@ unop("ftrunc", tfloat, "truncf(src0)") unop("fceil", tfloat, "ceilf(src0)") unop("ffloor", tfloat, "floorf(src0)") unop("ffract", tfloat, "src0 - floorf(src0)") -unop("fround_even", tfloat, "_mesa_round_to_even(src0)") +unop("fround_even", tfloat, "_mesa_roundevenf(src0)") # Trigonometric operations. diff --git a/mesalib/src/glsl/nir/nir_opt_algebraic.py b/mesalib/src/glsl/nir/nir_opt_algebraic.py index 7bf643134..ef855aa77 100644 --- a/mesalib/src/glsl/nir/nir_opt_algebraic.py +++ b/mesalib/src/glsl/nir/nir_opt_algebraic.py @@ -56,6 +56,10 @@ optimizations = [ (('iabs', ('ineg', a)), ('iabs', a)), (('fadd', a, 0.0), a), (('iadd', a, 0), a), + (('fadd', ('fmul', a, b), ('fmul', a, c)), ('fmul', a, ('fadd', b, c))), + (('iadd', ('imul', a, b), ('imul', a, c)), ('imul', a, ('iadd', b, c))), + (('fadd', ('fneg', a), a), 0.0), + (('iadd', ('ineg', a), a), 0), (('fmul', a, 0.0), 0.0), (('imul', a, 0), 0), (('fmul', a, 1.0), a), diff --git a/mesalib/src/glsl/nir/nir_opt_peephole_select.c b/mesalib/src/glsl/nir/nir_opt_peephole_select.c index ab08f286f..b89451b09 100644 --- a/mesalib/src/glsl/nir/nir_opt_peephole_select.c +++ b/mesalib/src/glsl/nir/nir_opt_peephole_select.c @@ -52,36 +52,66 @@ struct peephole_select_state { }; static bool -are_all_move_to_phi(nir_block *block) +block_check_for_allowed_instrs(nir_block *block) { nir_foreach_instr(block, instr) { - if (instr->type != nir_instr_type_alu) - return false; + switch (instr->type) { + case nir_instr_type_intrinsic: { + nir_intrinsic_instr *intrin = nir_instr_as_intrinsic(instr); + + switch (intrin->intrinsic) { + case nir_intrinsic_load_var: + switch (intrin->variables[0]->var->data.mode) { + case nir_var_shader_in: + case nir_var_uniform: + break; + + default: + return false; + } + break; + + default: + return false; + } - /* It must be a move operation */ - nir_alu_instr *mov = nir_instr_as_alu(instr); - if (mov->op != nir_op_fmov && mov->op != nir_op_imov) - return false; + break; + } - /* Can't handle saturate */ - if (mov->dest.saturate) - return false; + case nir_instr_type_load_const: + break; - /* It must be SSA */ - if (!mov->dest.dest.is_ssa) - return false; + case nir_instr_type_alu: { + /* It must be a move operation */ + nir_alu_instr *mov = nir_instr_as_alu(instr); + if (mov->op != nir_op_fmov && mov->op != nir_op_imov) + return false; - /* It cannot have any if-uses */ - if (mov->dest.dest.ssa.if_uses->entries != 0) - return false; + /* Can't handle saturate */ + if (mov->dest.saturate) + return false; + + /* It must be SSA */ + if (!mov->dest.dest.is_ssa) + 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]) + /* It cannot have any if-uses */ + if (mov->dest.dest.ssa.if_uses->entries != 0) 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]) + return false; + } + break; + } + + default: + return false; } } @@ -119,8 +149,9 @@ nir_opt_peephole_select_block(nir_block *block, void *void_state) nir_block *then_block = nir_cf_node_as_block(then_node); nir_block *else_block = nir_cf_node_as_block(else_node); - /* ... and those blocks must only contain move-to-phi. */ - if (!are_all_move_to_phi(then_block) || !are_all_move_to_phi(else_block)) + /* ... and those blocks must only contain "allowed" instructions. */ + if (!block_check_for_allowed_instrs(then_block) || + !block_check_for_allowed_instrs(else_block)) return true; /* At this point, we know that the previous CFG node is an if-then @@ -129,6 +160,25 @@ nir_opt_peephole_select_block(nir_block *block, void *void_state) * selects. */ + nir_block *prev_block = nir_cf_node_as_block(nir_cf_node_prev(prev_node)); + assert(prev_block->cf_node.type == nir_cf_node_block); + + /* First, we move the remaining instructions from the blocks to the + * block before. We have already guaranteed that this is safe by + * calling block_check_for_allowed_instrs() + */ + nir_foreach_instr_safe(then_block, instr) { + exec_node_remove(&instr->node); + instr->block = prev_block; + exec_list_push_tail(&prev_block->instr_list, &instr->node); + } + + nir_foreach_instr_safe(else_block, instr) { + exec_node_remove(&instr->node); + instr->block = prev_block; + exec_list_push_tail(&prev_block->instr_list, &instr->node); + } + nir_foreach_instr_safe(block, instr) { if (instr->type != nir_instr_type_phi) break; @@ -145,19 +195,7 @@ nir_opt_peephole_select_block(nir_block *block, void *void_state) assert(src->src.is_ssa); unsigned idx = src->pred == then_block ? 1 : 2; - - if (src->src.ssa->parent_instr->block == src->pred) { - /* We already know that this instruction must be a move with - * this phi's in this block as its only users. - */ - nir_alu_instr *mov = nir_instr_as_alu(src->src.ssa->parent_instr); - assert(mov->instr.type == nir_instr_type_alu); - assert(mov->op == nir_op_fmov || mov->op == nir_op_imov); - - nir_alu_src_copy(&sel->src[idx], &mov->src[0], state->mem_ctx); - } else { - nir_src_copy(&sel->src[idx].src, &src->src, state->mem_ctx); - } + nir_src_copy(&sel->src[idx].src, &src->src, state->mem_ctx); } nir_ssa_dest_init(&sel->instr, &sel->dest.dest, diff --git a/mesalib/src/glsl/nir/nir_print.c b/mesalib/src/glsl/nir/nir_print.c index 6a3c6a027..fa11a312e 100644 --- a/mesalib/src/glsl/nir/nir_print.c +++ b/mesalib/src/glsl/nir/nir_print.c @@ -228,7 +228,7 @@ print_var_decl(nir_variable *var, print_var_state *state, FILE *fp) if (var->data.mode == nir_var_shader_in || var->data.mode == nir_var_shader_out || var->data.mode == nir_var_uniform) { - fprintf(fp, " (%u)", var->data.driver_location); + fprintf(fp, " (%u, %u)", var->data.location, var->data.driver_location); } fprintf(fp, "\n"); @@ -844,22 +844,16 @@ nir_print_shader(nir_shader *shader, FILE *fp) print_var_state state; init_print_state(&state); - for (unsigned i = 0; i < shader->num_user_structures; i++) { - glsl_print_struct(shader->user_structures[i], fp); - } - - struct hash_entry *entry; - - hash_table_foreach(shader->uniforms, entry) { - print_var_decl((nir_variable *) entry->data, &state, fp); + foreach_list_typed(nir_variable, var, node, &shader->uniforms) { + print_var_decl(var, &state, fp); } - hash_table_foreach(shader->inputs, entry) { - print_var_decl((nir_variable *) entry->data, &state, fp); + foreach_list_typed(nir_variable, var, node, &shader->inputs) { + print_var_decl(var, &state, fp); } - hash_table_foreach(shader->outputs, entry) { - print_var_decl((nir_variable *) entry->data, &state, fp); + foreach_list_typed(nir_variable, var, node, &shader->outputs) { + print_var_decl(var, &state, fp); } foreach_list_typed(nir_variable, var, node, &shader->globals) { diff --git a/mesalib/src/glsl/nir/nir_validate.c b/mesalib/src/glsl/nir/nir_validate.c index a3fe9d620..f247ae069 100644 --- a/mesalib/src/glsl/nir/nir_validate.c +++ b/mesalib/src/glsl/nir/nir_validate.c @@ -931,17 +931,19 @@ nir_validate_shader(nir_shader *shader) state.shader = shader; - struct hash_entry *entry; - hash_table_foreach(shader->uniforms, entry) { - validate_var_decl((nir_variable *) entry->data, true, &state); + exec_list_validate(&shader->uniforms); + foreach_list_typed(nir_variable, var, node, &shader->uniforms) { + validate_var_decl(var, true, &state); } - hash_table_foreach(shader->inputs, entry) { - validate_var_decl((nir_variable *) entry->data, true, &state); + exec_list_validate(&shader->inputs); + foreach_list_typed(nir_variable, var, node, &shader->inputs) { + validate_var_decl(var, true, &state); } - hash_table_foreach(shader->outputs, entry) { - validate_var_decl((nir_variable *) entry->data, true, &state); + exec_list_validate(&shader->outputs); + foreach_list_typed(nir_variable, var, node, &shader->outputs) { + validate_var_decl(var, true, &state); } exec_list_validate(&shader->globals); diff --git a/mesalib/src/glsl/nir/nir_worklist.c b/mesalib/src/glsl/nir/nir_worklist.c index a8baae937..3087a1d23 100644 --- a/mesalib/src/glsl/nir/nir_worklist.c +++ b/mesalib/src/glsl/nir/nir_worklist.c @@ -82,7 +82,7 @@ nir_block_worklist_push_head(nir_block_worklist *w, nir_block *block) } nir_block * -nir_block_worklist_peek_head(nir_block_worklist *w) +nir_block_worklist_peek_head(const nir_block_worklist *w) { assert(w->count > 0); @@ -114,18 +114,18 @@ nir_block_worklist_push_tail(nir_block_worklist *w, nir_block *block) w->count++; - unsigned tail = w->start = (w->start + w->count - 1) % w->size; + unsigned tail = (w->start + w->count - 1) % w->size; w->blocks[tail] = block; BITSET_SET(w->blocks_present, block->index); } nir_block * -nir_block_worklist_peek_tail(nir_block_worklist *w) +nir_block_worklist_peek_tail(const nir_block_worklist *w) { assert(w->count > 0); - unsigned tail = w->start = (w->start + w->count - 1) % w->size; + unsigned tail = (w->start + w->count - 1) % w->size; return w->blocks[tail]; } @@ -135,7 +135,7 @@ nir_block_worklist_pop_tail(nir_block_worklist *w) { assert(w->count > 0); - unsigned tail = w->start = (w->start + w->count - 1) % w->size; + unsigned tail = (w->start + w->count - 1) % w->size; w->count--; diff --git a/mesalib/src/glsl/nir/nir_worklist.h b/mesalib/src/glsl/nir/nir_worklist.h index d5a8568e4..829bff24a 100644 --- a/mesalib/src/glsl/nir/nir_worklist.h +++ b/mesalib/src/glsl/nir/nir_worklist.h @@ -74,13 +74,13 @@ nir_block_worklist_is_empty(const nir_block_worklist *w) void nir_block_worklist_push_head(nir_block_worklist *w, nir_block *block); -nir_block *nir_block_worklist_peek_head(nir_block_worklist *w); +nir_block *nir_block_worklist_peek_head(const nir_block_worklist *w); nir_block *nir_block_worklist_pop_head(nir_block_worklist *w); void nir_block_worklist_push_tail(nir_block_worklist *w, nir_block *block); -nir_block *nir_block_worklist_peek_tail(nir_block_worklist *w); +nir_block *nir_block_worklist_peek_tail(const nir_block_worklist *w); nir_block *nir_block_worklist_pop_tail(nir_block_worklist *w); diff --git a/mesalib/src/glsl/opt_algebraic.cpp b/mesalib/src/glsl/opt_algebraic.cpp index c6040bff8..69c03ea8b 100644 --- a/mesalib/src/glsl/opt_algebraic.cpp +++ b/mesalib/src/glsl/opt_algebraic.cpp @@ -626,9 +626,18 @@ ir_algebraic_visitor::handle_expression(ir_expression *ir) if (!is_vec_zero(zero)) continue; - return new(mem_ctx) ir_expression(ir->operation, - add->operands[0], - neg(add->operands[1])); + /* Depending of the zero position we want to optimize + * (0 cmp x+y) into (-x cmp y) or (x+y cmp 0) into (x cmp -y) + */ + if (add_pos == 1) { + return new(mem_ctx) ir_expression(ir->operation, + neg(add->operands[0]), + add->operands[1]); + } else { + return new(mem_ctx) ir_expression(ir->operation, + add->operands[0], + neg(add->operands[1])); + } } break; diff --git a/mesalib/src/loader/loader.c b/mesalib/src/loader/loader.c index 9ff511522..17bf13360 100644 --- a/mesalib/src/loader/loader.c +++ b/mesalib/src/loader/loader.c @@ -64,6 +64,7 @@ * Rob Clark <robclark@freedesktop.org> */ +#include <sys/stat.h> #include <stdarg.h> #include <stdio.h> #include <string.h> @@ -80,7 +81,6 @@ #endif #endif #ifdef HAVE_SYSFS -#include <sys/stat.h> #include <sys/types.h> #endif #include "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 2fe1638fd..641e68f71 100644 --- a/mesalib/src/mapi/glapi/gen/ARB_direct_state_access.xml +++ b/mesalib/src/mapi/glapi/gen/ARB_direct_state_access.xml @@ -7,6 +7,110 @@ <enum name="QUERY_TARGET" value="0x82EA"/> <enum name="TEXTURE_BINDING" value="0x82EB"/> + <!-- Buffer object functions --> + + <function name="CreateBuffers" offset="assign"> + <param name="n" type="GLsizei" /> + <param name="buffers" type="GLuint *" /> + </function> + + <function name="NamedBufferStorage" offset="assign"> + <param name="buffer" type="GLuint" /> + <param name="size" type="GLsizeiptr" /> + <param name="data" type="const GLvoid *" /> + <param name="flags" type="GLbitfield" /> + </function> + + <function name="NamedBufferData" offset="assign"> + <param name="buffer" type="GLuint" /> + <param name="size" type="GLsizeiptr" /> + <param name="data" type="const GLvoid *" /> + <param name="usage" type="GLenum" /> + </function> + + <function name="NamedBufferSubData" offset="assign"> + <param name="buffer" type="GLuint" /> + <param name="offset" type="GLintptr" /> + <param name="size" type="GLsizeiptr" /> + <param name="data" type="const GLvoid *" /> + </function> + + <function name="CopyNamedBufferSubData" offset="assign"> + <param name="readBuffer" type="GLuint" /> + <param name="writeBuffer" type="GLuint" /> + <param name="readOffset" type="GLintptr" /> + <param name="writeOffset" type="GLintptr" /> + <param name="size" type="GLsizeiptr" /> + </function> + + <function name="ClearNamedBufferData" offset="assign"> + <param name="buffer" type="GLuint" /> + <param name="internalformat" type="GLenum" /> + <param name="format" type="GLenum" /> + <param name="type" type="GLenum" /> + <param name="data" type="const GLvoid *" /> + </function> + + <function name="ClearNamedBufferSubData" offset="assign"> + <param name="buffer" type="GLuint" /> + <param name="internalformat" type="GLenum" /> + <param name="offset" type="GLintptr" /> + <param name="size" type="GLsizeiptr" /> + <param name="format" type="GLenum" /> + <param name="type" type="GLenum" /> + <param name="data" type="const GLvoid *" /> + </function> + + <function name="MapNamedBuffer" offset="assign"> + <return type="GLvoid *" /> + <param name="buffer" type="GLuint" /> + <param name="access" type="GLenum" /> + </function> + + <function name="MapNamedBufferRange" offset="assign"> + <return type="GLvoid *" /> + <param name="buffer" type="GLuint" /> + <param name="offset" type="GLintptr" /> + <param name="length" type="GLsizeiptr" /> + <param name="access" type="GLbitfield" /> + </function> + + <function name="UnmapNamedBuffer" offset="assign"> + <return type="GLboolean" /> + <param name="buffer" type="GLuint" /> + </function> + + <function name="FlushMappedNamedBufferRange" offset="assign"> + <param name="buffer" type="GLuint" /> + <param name="offset" type="GLintptr" /> + <param name="length" type="GLsizeiptr" /> + </function> + + <function name="GetNamedBufferParameteriv" offset="assign"> + <param name="buffer" type="GLuint" /> + <param name="pname" type="GLenum" /> + <param name="params" type="GLint *" /> + </function> + + <function name="GetNamedBufferParameteri64v" offset="assign"> + <param name="buffer" type="GLuint" /> + <param name="pname" type="GLenum" /> + <param name="params" type="GLint64 *" /> + </function> + + <function name="GetNamedBufferPointerv" offset="assign"> + <param name="buffer" type="GLuint" /> + <param name="pname" type="GLenum" /> + <param name="params" type="GLvoid **" /> + </function> + + <function name="GetNamedBufferSubData" offset="assign"> + <param name="buffer" type="GLuint" /> + <param name="offset" type="GLintptr" /> + <param name="size" type="GLsizeiptr" /> + <param name="data" type="GLvoid *" /> + </function> + <!-- Texture object functions --> <function name="CreateTextures" offset="assign"> @@ -21,6 +125,14 @@ <param name="buffer" type="GLuint" /> </function> + <function name="TextureBufferRange" offset="assign"> + <param name="texture" type="GLuint" /> + <param name="internalformat" type="GLenum" /> + <param name="buffer" type="GLuint" /> + <param name="offset" type="GLintptr" /> + <param name="size" type="GLsizeiptr" /> + </function> + <function name="TextureStorage1D" offset="assign"> <param name="texture" type="GLuint" /> <param name="levels" type="GLsizei" /> diff --git a/mesalib/src/mapi/glapi/gen/gl_enums.py b/mesalib/src/mapi/glapi/gen/gl_enums.py index a756ad971..7c55ee443 100755 --- a/mesalib/src/mapi/glapi/gen/gl_enums.py +++ b/mesalib/src/mapi/glapi/gen/gl_enums.py @@ -157,6 +157,12 @@ _mesa_lookup_prim_by_nr(GLuint nr) string_offsets = {} i = 0; + print '#if defined(__GNUC__)' + print '# define LONGSTRING __extension__' + print '#else' + print '# define LONGSTRING' + print '#endif' + print '' print 'LONGSTRING static const char enum_string_table[] = ' for enum, name in enum_table: print ' "%s\\0"' % (name) diff --git a/mesalib/src/mapi/glapi/glapi.h b/mesalib/src/mapi/glapi/glapi.h index 89fb1dceb..8084e5757 100755 --- a/mesalib/src/mapi/glapi/glapi.h +++ b/mesalib/src/mapi/glapi/glapi.h @@ -76,6 +76,8 @@ struct _glapi_table; typedef void (*_glapi_proc)(void); /* generic function pointer */ +typedef void (*_glapi_nop_handler_proc)(const char *name); + typedef void (*_glapi_warning_func)(void *ctx, const char *str, ...); @@ -179,6 +181,14 @@ extern struct _glapi_table * _glapi_create_table_from_handle(void *handle, const char *symbol_prefix); +void +_glapi_set_nop_handler(_glapi_nop_handler_proc func); + +/** Return pointer to new dispatch table filled with no-op functions */ +struct _glapi_table * +_glapi_new_nop_table(unsigned num_entries); + + #ifdef __cplusplus } diff --git a/mesalib/src/mapi/glapi/glapi_getproc.c b/mesalib/src/mapi/glapi/glapi_getproc.c index d52b26450..7f4dc7f4d 100644 --- a/mesalib/src/mapi/glapi/glapi_getproc.c +++ b/mesalib/src/mapi/glapi/glapi_getproc.c @@ -30,6 +30,9 @@ */ +#include <assert.h> +#include <string.h> +#include <stdlib.h> #include "glapi/glapi_priv.h" #include "glapi/glapitable.h" @@ -37,6 +40,7 @@ #define FIRST_DYNAMIC_OFFSET (sizeof(struct _glapi_table) / sizeof(void *)) + /********************************************************************** * Static function management. */ diff --git a/mesalib/src/mapi/glapi/glapi_nop.c b/mesalib/src/mapi/glapi/glapi_nop.c index cbfbd2433..e006e0259 100644..100755 --- a/mesalib/src/mapi/glapi/glapi_nop.c +++ b/mesalib/src/mapi/glapi/glapi_nop.c @@ -30,14 +30,22 @@ * This file defines a special dispatch table which is loaded with no-op * functions. * - * When there's no current rendering context, calling a GL function like - * glBegin() is a no-op. Apps should never normally do this. So as a - * debugging aid, each of the no-op functions will emit a warning to - * stderr if the MESA_DEBUG or LIBGL_DEBUG env var is set. + * Mesa can register a "no-op handler function" which will be called in + * the event that a no-op function is called. + * + * In the past, the dispatch table was loaded with pointers to a single + * no-op function. But that broke on Windows because the GL entrypoints + * use __stdcall convention. __stdcall means the callee cleans up the + * stack. So one no-op function can't properly clean up the stack. This + * would lead to crashes. + * + * Another benefit of unique no-op functions is we can accurately report + * the function's name in an error message. */ - +#include <stdlib.h> +#include <string.h> #include "glapi/glapi_priv.h" #undef _GLAPI_EXPORT @@ -53,25 +61,32 @@ _glapi_set_warning_func(_glapi_proc func) { } -/* - * When GLAPIENTRY is __stdcall (i.e. Windows), the stack is popped by the - * callee making the number/type of arguments significant. + +/** + * We'll jump though this function pointer whenever a no-op function + * is called. + */ +static _glapi_nop_handler_proc nop_handler = NULL; + + +/** + * Register the no-op handler call-back function. */ -#if defined(_WIN32) || defined(DEBUG) +_GLAPI_EXPORT void +_glapi_set_nop_handler(_glapi_nop_handler_proc func) +{ + nop_handler = func; +} + /** * Called by each of the no-op GL entrypoints. */ -static int -Warn(const char *func) +static void +nop(const char *func) { -#if defined(DEBUG) - if (getenv("MESA_DEBUG") || getenv("LIBGL_DEBUG")) { - fprintf(stderr, "GL User Error: gl%s called without a rendering context\n", - func); - } -#endif - return 0; + if (nop_handler) + nop_handler(func); } @@ -81,7 +96,8 @@ Warn(const char *func) static GLint NoOpUnused(void) { - return Warn(" function"); + nop("unused GL entry point"); + return 0; } /* @@ -91,31 +107,28 @@ NoOpUnused(void) #define KEYWORD1_ALT static #define KEYWORD2 GLAPIENTRY #define NAME(func) NoOp##func -#define DISPATCH(func, args, msg) Warn(#func); -#define RETURN_DISPATCH(func, args, msg) Warn(#func); return 0 +#define DISPATCH(func, args, msg) nop(#func); +#define RETURN_DISPATCH(func, args, msg) nop(#func); return 0 /* * Defines for the table of no-op entry points. */ #define TABLE_ENTRY(name) (_glapi_proc) NoOp##name +#define DISPATCH_TABLE_NAME __glapi_noop_table +#define UNUSED_TABLE_NAME __unused_noop_functions + +#include "glapi/gen/glapitemp.h" -#else -static int -NoOpGeneric(void) +/** Return pointer to new dispatch table filled with no-op functions */ +struct _glapi_table * _GLAPI_EXPORT +_glapi_new_nop_table(unsigned num_entries) { - if (getenv("MESA_DEBUG") || getenv("LIBGL_DEBUG")) { - fprintf(stderr, "GL User Error: calling GL function without a rendering context\n"); + struct _glapi_table *table = malloc(num_entries * sizeof(_glapi_proc)); + if (table) { + memcpy(table, __glapi_noop_table, + num_entries * sizeof(_glapi_proc)); } - return 0; + return table; } - -#define TABLE_ENTRY(name) (_glapi_proc) NoOpGeneric - -#endif - -#define DISPATCH_TABLE_NAME __glapi_noop_table -#define UNUSED_TABLE_NAME __unused_noop_functions - -#include "glapi/gen/glapitemp.h" diff --git a/mesalib/src/mapi/glapi/glapi_priv.h b/mesalib/src/mapi/glapi/glapi_priv.h index 0a998b475..cb4cb5b97 100644 --- a/mesalib/src/mapi/glapi/glapi_priv.h +++ b/mesalib/src/mapi/glapi/glapi_priv.h @@ -26,9 +26,6 @@ #ifndef _GLAPI_PRIV_H #define _GLAPI_PRIV_H -#include <stdlib.h> -#include <string.h> -#include <stdio.h> #ifdef HAVE_DIX_CONFIG_H #include <dix-config.h> diff --git a/mesalib/src/mapi/mapi_glapi.c b/mesalib/src/mapi/mapi_glapi.c index 127dfafac..70605f3df 100644 --- a/mesalib/src/mapi/mapi_glapi.c +++ b/mesalib/src/mapi/mapi_glapi.c @@ -27,6 +27,7 @@ */ #include <string.h> +#include <stdlib.h> #include "glapi/glapi.h" #include "u_current.h" #include "table.h" /* for MAPI_TABLE_NUM_SLOTS */ @@ -222,6 +223,28 @@ _glapi_get_proc_name(unsigned int offset) return stub ? stub_get_name(stub) : NULL; } +/** Return pointer to new dispatch table filled with no-op functions */ +struct _glapi_table * +_glapi_new_nop_table(unsigned num_entries) +{ + struct _glapi_table *table; + + if (num_entries > MAPI_TABLE_NUM_SLOTS) + num_entries = MAPI_TABLE_NUM_SLOTS; + + table = malloc(num_entries * sizeof(mapi_func)); + if (table) { + memcpy(table, table_noop_array, num_entries * sizeof(mapi_func)); + } + return table; +} + +void +_glapi_set_nop_handler(_glapi_nop_handler_proc func) +{ + table_set_noop_handler(func); +} + /** * This is a deprecated function which should not be used anymore. * It's only present to satisfy linking with older versions of libGL. diff --git a/mesalib/src/mapi/table.c b/mesalib/src/mapi/table.c index 0d2866618..748750197 100644 --- a/mesalib/src/mapi/table.c +++ b/mesalib/src/mapi/table.c @@ -30,16 +30,29 @@ #include "table.h" +static nop_handler_proc nop_handler = NULL; + +void +table_set_noop_handler(nop_handler_proc func) +{ + nop_handler = func; +} + static void noop_warn(const char *name) { - static int debug = -1; + if (nop_handler) { + nop_handler(name); + } + else { + static int debug = -1; - if (debug < 0) - debug = (getenv("MESA_DEBUG") || getenv("LIBGL_DEBUG")); + if (debug < 0) + debug = (getenv("MESA_DEBUG") || getenv("LIBGL_DEBUG")); - if (debug) - fprintf(stderr, "%s is no-op\n", name); + if (debug) + fprintf(stderr, "%s is no-op\n", name); + } } static int diff --git a/mesalib/src/mapi/table.h b/mesalib/src/mapi/table.h index e2d6ef03d..a1af40c6f 100644 --- a/mesalib/src/mapi/table.h +++ b/mesalib/src/mapi/table.h @@ -41,6 +41,14 @@ struct mapi_table; extern const mapi_func table_noop_array[]; + +typedef void (*nop_handler_proc)(const char *name); + + +void +table_set_noop_handler(nop_handler_proc func); + + /** * Get the no-op dispatch table. */ diff --git a/mesalib/src/mesa/SConscript b/mesalib/src/mesa/SConscript index 81939f981..a563fd2ff 100644 --- a/mesalib/src/mesa/SConscript +++ b/mesalib/src/mesa/SConscript @@ -39,18 +39,13 @@ else: # parse Makefile.sources source_lists = env.ParseSourceList('Makefile.sources') -env.Append(YACCFLAGS = '-d -p "_mesa_program_"') -program_lex = env.CFile('program/lex.yy.c', 'program/program_lexer.l') -program_parse = env.CFile('program/program_parse.tab.c', - 'program/program_parse.y') -program_sources = source_lists['PROGRAM_FILES'] + [ - program_lex, - program_parse[0], -] +env.Append(YACCFLAGS = ['-d', '-p', '_mesa_program_']) +env.CFile('program/lex.yy.c', 'program/program_lexer.l') +env.CFile('program/program_parse.tab.c', 'program/program_parse.y') mesa_sources = ( source_lists['MESA_FILES'] + - program_sources + + source_lists['PROGRAM_FILES'] + source_lists['STATETRACKER_FILES'] ) @@ -135,7 +130,9 @@ def write_git_sha1_h_file(filename): (commit, foo) = subprocess.Popen(args, stdout=subprocess.PIPE).communicate() except: # git log command didn't work - if not os.path.exists(filename): + dirname = os.path.dirname(filename) + if not os.path.exists(dirname): + os.makedirs(dirname) # create an empty file if none already exists f = open(filename, "w") f.close() diff --git a/mesalib/src/mesa/drivers/common/meta.c b/mesalib/src/mesa/drivers/common/meta.c index fdc4cf1e9..cf99d9563 100644 --- a/mesalib/src/mesa/drivers/common/meta.c +++ b/mesalib/src/mesa/drivers/common/meta.c @@ -247,9 +247,9 @@ _mesa_meta_setup_blit_shader(struct gl_context *ctx, struct blit_shader_table *table) { char *vs_source, *fs_source; - void *const mem_ctx = ralloc_context(NULL); struct blit_shader *shader = choose_blit_shader(target, table); const char *vs_input, *vs_output, *fs_input, *vs_preprocess, *fs_preprocess; + void *mem_ctx; if (ctx->Const.GLSLVersion < 130) { vs_preprocess = ""; @@ -273,6 +273,8 @@ _mesa_meta_setup_blit_shader(struct gl_context *ctx, return; } + mem_ctx = ralloc_context(NULL); + vs_source = ralloc_asprintf(mem_ctx, "%s\n" "%s vec2 position;\n" diff --git a/mesalib/src/mesa/drivers/common/meta_tex_subimage.c b/mesalib/src/mesa/drivers/common/meta_tex_subimage.c index e29addb73..ad6e7873e 100644 --- a/mesalib/src/mesa/drivers/common/meta_tex_subimage.c +++ b/mesalib/src/mesa/drivers/common/meta_tex_subimage.c @@ -150,9 +150,6 @@ _mesa_meta_pbo_TexSubImage(struct gl_context *ctx, GLuint dims, bool success = false; int z; - /* XXX: This should probably be passed in from somewhere */ - const char *where = "_mesa_meta_pbo_TexSubImage"; - if (!_mesa_is_bufferobj(packing->BufferObj) && !create_pbo) return false; @@ -165,19 +162,6 @@ _mesa_meta_pbo_TexSubImage(struct gl_context *ctx, GLuint dims, if (ctx->_ImageTransferState) return false; - if (!_mesa_validate_pbo_access(dims, packing, width, height, depth, - format, type, INT_MAX, pixels)) { - _mesa_error(ctx, GL_INVALID_OPERATION, - "%s(out of bounds PBO access)", where); - return true; - } - - if (_mesa_check_disallowed_mapping(packing->BufferObj)) { - /* buffer is mapped - that's an error */ - _mesa_error(ctx, GL_INVALID_OPERATION, "%s(PBO is mapped)", where); - return true; - } - /* For arrays, use a tall (height * depth) 2D texture but taking into * account the inter-image padding specified with the image height packing * property. @@ -277,9 +261,6 @@ _mesa_meta_pbo_GetTexSubImage(struct gl_context *ctx, GLuint dims, bool success = false; int z; - /* XXX: This should probably be passed in from somewhere */ - const char *where = "_mesa_meta_pbo_GetTexSubImage"; - if (!_mesa_is_bufferobj(packing->BufferObj)) return false; @@ -292,19 +273,6 @@ _mesa_meta_pbo_GetTexSubImage(struct gl_context *ctx, GLuint dims, if (ctx->_ImageTransferState) return false; - if (!_mesa_validate_pbo_access(dims, packing, width, height, depth, - format, type, INT_MAX, pixels)) { - _mesa_error(ctx, GL_INVALID_OPERATION, - "%s(out of bounds PBO access)", where); - return true; - } - - if (_mesa_check_disallowed_mapping(packing->BufferObj)) { - /* buffer is mapped - that's an error */ - _mesa_error(ctx, GL_INVALID_OPERATION, "%s(PBO is mapped)", where); - return true; - } - /* For arrays, use a tall (height * depth) 2D texture but taking into * account the inter-image padding specified with the image height packing * property. diff --git a/mesalib/src/mesa/drivers/dri/common/dri_test.c b/mesalib/src/mesa/drivers/dri/common/dri_test.c index 7ab50d923..57bfa5b93 100644 --- a/mesalib/src/mesa/drivers/dri/common/dri_test.c +++ b/mesalib/src/mesa/drivers/dri/common/dri_test.c @@ -76,6 +76,17 @@ _glapi_get_dispatch_table_size(void) return 0; } +PUBLIC void +_glapi_set_nop_handler(_glapi_nop_handler_proc func) +{ +} + +PUBLIC struct _glapi_table * +_glapi_new_nop_table(unsigned num_entries) +{ + return NULL; +} + #ifndef NO_MAIN int main(int argc, char** argv) { diff --git a/mesalib/src/mesa/main/api_exec.h b/mesalib/src/mesa/main/api_exec.h index 1e4a9d61a..12249fec2 100644 --- a/mesalib/src/mesa/main/api_exec.h +++ b/mesalib/src/mesa/main/api_exec.h @@ -30,12 +30,8 @@ extern "C" { #endif -struct _glapi_table; struct gl_context; -extern struct _glapi_table * -_mesa_alloc_dispatch_table(void); - extern void _mesa_initialize_exec_table(struct gl_context *ctx); diff --git a/mesalib/src/mesa/main/bufferobj.c b/mesalib/src/mesa/main/bufferobj.c index 008d1aa5f..25110c33b 100755 --- a/mesalib/src/mesa/main/bufferobj.c +++ b/mesalib/src/mesa/main/bufferobj.c @@ -232,67 +232,62 @@ bufferobj_range_mapped(const struct gl_buffer_object *obj, * \c glClearBufferSubData. * * \param ctx GL context. - * \param target Buffer object target on which to operate. + * \param bufObj The buffer object. * \param offset Offset of the first byte of the subdata range. * \param size Size, in bytes, of the subdata range. * \param mappedRange If true, checks if an overlapping range is mapped. * If false, checks if buffer is mapped. - * \param errorNoBuffer Error code if no buffer is bound to target. * \param caller Name of calling function for recording errors. - * \return A pointer to the buffer object bound to \c target in the - * specified context or \c NULL if any of the parameter or state - * conditions are invalid. + * \return false if error, true otherwise * * \sa glBufferSubDataARB, glGetBufferSubDataARB, glClearBufferSubData */ -static struct gl_buffer_object * -buffer_object_subdata_range_good(struct gl_context * ctx, GLenum target, - GLintptrARB offset, GLsizeiptrARB size, - bool mappedRange, GLenum errorNoBuffer, - const char *caller) +static bool +buffer_object_subdata_range_good(struct gl_context *ctx, + struct gl_buffer_object *bufObj, + GLintptr offset, GLsizeiptr size, + bool mappedRange, const char *caller) { - struct gl_buffer_object *bufObj; - if (size < 0) { _mesa_error(ctx, GL_INVALID_VALUE, "%s(size < 0)", caller); - return NULL; + return false; } if (offset < 0) { _mesa_error(ctx, GL_INVALID_VALUE, "%s(offset < 0)", caller); - return NULL; + return false; } - bufObj = get_buffer(ctx, caller, target, errorNoBuffer); - if (!bufObj) - return NULL; - if (offset + size > bufObj->Size) { _mesa_error(ctx, GL_INVALID_VALUE, "%s(offset %lu + size %lu > buffer size %lu)", caller, (unsigned long) offset, (unsigned long) size, (unsigned long) bufObj->Size); - return NULL; + return false; } if (bufObj->Mappings[MAP_USER].AccessFlags & GL_MAP_PERSISTENT_BIT) - return bufObj; + return true; if (mappedRange) { if (bufferobj_range_mapped(bufObj, offset, size)) { - _mesa_error(ctx, GL_INVALID_OPERATION, "%s", caller); - return NULL; + _mesa_error(ctx, GL_INVALID_OPERATION, + "%s(range is mapped without persistent bit)", + caller); + return false; } } else { if (_mesa_bufferobj_mapped(bufObj, MAP_USER)) { - _mesa_error(ctx, GL_INVALID_OPERATION, "%s", caller); - return NULL; + _mesa_error(ctx, GL_INVALID_OPERATION, + "%s(buffer is mapped without persistent bit)", + caller); + return false; } } - return bufObj; + return true; } @@ -561,9 +556,9 @@ _mesa_total_buffer_object_memory(struct gl_context *ctx) * \sa glBufferDataARB, dd_function_table::BufferData. */ GLboolean -_mesa_buffer_data( struct gl_context *ctx, GLenum target, GLsizeiptrARB size, - const GLvoid * data, GLenum usage, GLenum storageFlags, - struct gl_buffer_object * bufObj ) +buffer_data_fallback(struct gl_context *ctx, GLenum target, GLsizeiptr size, + const GLvoid *data, GLenum usage, GLenum storageFlags, + struct gl_buffer_object *bufObj) { void * new_data; @@ -607,9 +602,9 @@ _mesa_buffer_data( struct gl_context *ctx, GLenum target, GLsizeiptrARB size, * \sa glBufferSubDataARB, dd_function_table::BufferSubData. */ void -_mesa_buffer_subdata( struct gl_context *ctx, GLintptrARB offset, - GLsizeiptrARB size, const GLvoid * data, - struct gl_buffer_object * bufObj ) +buffer_sub_data_fallback(struct gl_context *ctx, GLintptr offset, + GLsizeiptr size, const GLvoid *data, + struct gl_buffer_object *bufObj) { (void) ctx; @@ -670,11 +665,11 @@ _mesa_buffer_get_subdata( struct gl_context *ctx, GLintptrARB offset, * dd_function_table::ClearBufferSubData. */ void -_mesa_buffer_clear_subdata(struct gl_context *ctx, - GLintptr offset, GLsizeiptr size, - const GLvoid *clearValue, - GLsizeiptr clearValueSize, - struct gl_buffer_object *bufObj) +_mesa_ClearBufferSubData_sw(struct gl_context *ctx, + GLintptr offset, GLsizeiptr size, + const GLvoid *clearValue, + GLsizeiptr clearValueSize, + struct gl_buffer_object *bufObj) { GLsizeiptr i; GLubyte *dest; @@ -711,10 +706,10 @@ _mesa_buffer_clear_subdata(struct gl_context *ctx, * Called via glMapBufferRange(). */ static void * -_mesa_buffer_map_range( struct gl_context *ctx, GLintptr offset, - GLsizeiptr length, GLbitfield access, - struct gl_buffer_object *bufObj, - gl_map_buffer_index index) +map_buffer_range_fallback(struct gl_context *ctx, GLintptr offset, + GLsizeiptr length, GLbitfield access, + struct gl_buffer_object *bufObj, + gl_map_buffer_index index) { (void) ctx; assert(!_mesa_bufferobj_mapped(bufObj, index)); @@ -732,10 +727,10 @@ _mesa_buffer_map_range( struct gl_context *ctx, GLintptr offset, * Called via glFlushMappedBufferRange(). */ static void -_mesa_buffer_flush_mapped_range( struct gl_context *ctx, - GLintptr offset, GLsizeiptr length, - struct gl_buffer_object *obj, - gl_map_buffer_index index) +flush_mapped_buffer_range_fallback(struct gl_context *ctx, + GLintptr offset, GLsizeiptr length, + struct gl_buffer_object *obj, + gl_map_buffer_index index) { (void) ctx; (void) offset; @@ -746,15 +741,15 @@ _mesa_buffer_flush_mapped_range( struct gl_context *ctx, /** - * Default callback for \c dd_function_table::MapBuffer(). + * Default callback for \c dd_function_table::UnmapBuffer(). * * The input parameters will have been already tested for errors. * * \sa glUnmapBufferARB, dd_function_table::UnmapBuffer */ GLboolean -_mesa_buffer_unmap(struct gl_context *ctx, struct gl_buffer_object *bufObj, - gl_map_buffer_index index) +unmap_buffer_fallback(struct gl_context *ctx, struct gl_buffer_object *bufObj, + gl_map_buffer_index index) { (void) ctx; /* XXX we might assert here that bufObj->Pointer is non-null */ @@ -771,11 +766,11 @@ _mesa_buffer_unmap(struct gl_context *ctx, struct gl_buffer_object *bufObj, * Called via glCopyBufferSubData(). */ static void -_mesa_copy_buffer_subdata(struct gl_context *ctx, - struct gl_buffer_object *src, - struct gl_buffer_object *dst, - GLintptr readOffset, GLintptr writeOffset, - GLsizeiptr size) +copy_buffer_sub_data_fallback(struct gl_context *ctx, + struct gl_buffer_object *src, + struct gl_buffer_object *dst, + GLintptr readOffset, GLintptr writeOffset, + GLsizeiptr size) { GLubyte *srcPtr, *dstPtr; @@ -1006,6 +1001,27 @@ _mesa_lookup_bufferobj_locked(struct gl_context *ctx, GLuint buffer) _mesa_HashLookupLocked(ctx->Shared->BufferObjects, buffer); } +/** + * A convenience function for direct state access functions that throws + * GL_INVALID_OPERATION if buffer is not the name of an existing + * buffer object. + */ +struct gl_buffer_object * +_mesa_lookup_bufferobj_err(struct gl_context *ctx, GLuint buffer, + const char *caller) +{ + struct gl_buffer_object *bufObj; + + bufObj = _mesa_lookup_bufferobj(ctx, buffer); + if (!bufObj || bufObj == &DummyBufferObject) { + _mesa_error(ctx, GL_INVALID_OPERATION, + "%s(non-existent buffer object %u)", caller, buffer); + return NULL; + } + + return bufObj; +} + void _mesa_begin_bufferobj_lookups(struct gl_context *ctx) @@ -1098,20 +1114,20 @@ _mesa_init_buffer_object_functions(struct dd_function_table *driver) /* GL_ARB_vertex/pixel_buffer_object */ driver->NewBufferObject = _mesa_new_buffer_object; driver->DeleteBuffer = _mesa_delete_buffer_object; - driver->BufferData = _mesa_buffer_data; - driver->BufferSubData = _mesa_buffer_subdata; + driver->BufferData = buffer_data_fallback; + driver->BufferSubData = buffer_sub_data_fallback; driver->GetBufferSubData = _mesa_buffer_get_subdata; - driver->UnmapBuffer = _mesa_buffer_unmap; + driver->UnmapBuffer = unmap_buffer_fallback; /* GL_ARB_clear_buffer_object */ - driver->ClearBufferSubData = _mesa_buffer_clear_subdata; + driver->ClearBufferSubData = _mesa_ClearBufferSubData_sw; /* GL_ARB_map_buffer_range */ - driver->MapBufferRange = _mesa_buffer_map_range; - driver->FlushMappedBufferRange = _mesa_buffer_flush_mapped_range; + driver->MapBufferRange = map_buffer_range_fallback; + driver->FlushMappedBufferRange = flush_mapped_buffer_range_fallback; /* GL_ARB_copy_buffer */ - driver->CopyBufferSubData = _mesa_copy_buffer_subdata; + driver->CopyBufferSubData = copy_buffer_sub_data_fallback; } @@ -1273,27 +1289,29 @@ _mesa_DeleteBuffers(GLsizei n, const GLuint *ids) /** - * Generate a set of unique buffer object IDs and store them in \c buffer. - * - * \param n Number of IDs to generate. - * \param buffer Array of \c n locations to store the IDs. + * This is the implementation for glGenBuffers and glCreateBuffers. It is not + * exposed to the rest of Mesa to encourage the use of nameless buffers in + * driver internals. */ -void GLAPIENTRY -_mesa_GenBuffers(GLsizei n, GLuint *buffer) +static void +create_buffers(GLsizei n, GLuint *buffers, bool dsa) { GET_CURRENT_CONTEXT(ctx); GLuint first; GLint i; + struct gl_buffer_object *buf; + + const char *func = dsa ? "glCreateBuffers" : "glGenBuffers"; if (MESA_VERBOSE & VERBOSE_API) - _mesa_debug(ctx, "glGenBuffers(%d)\n", n); + _mesa_debug(ctx, "%s(%d)\n", func, n); if (n < 0) { - _mesa_error(ctx, GL_INVALID_VALUE, "glGenBuffersARB"); + _mesa_error(ctx, GL_INVALID_VALUE, "%s(n %d < 0)", func, n); return; } - if (!buffer) { + if (!buffers) { return; } @@ -1304,16 +1322,53 @@ _mesa_GenBuffers(GLsizei n, GLuint *buffer) first = _mesa_HashFindFreeKeyBlock(ctx->Shared->BufferObjects, n); - /* Insert the ID and pointer to dummy buffer object into hash table */ + /* Insert the ID and pointer into the hash table. If non-DSA, insert a + * DummyBufferObject. Otherwise, create a new buffer object and insert + * it. + */ for (i = 0; i < n; i++) { - _mesa_HashInsert(ctx->Shared->BufferObjects, first + i, - &DummyBufferObject); - buffer[i] = first + i; + buffers[i] = first + i; + if (dsa) { + assert(ctx->Driver.NewBufferObject); + buf = ctx->Driver.NewBufferObject(ctx, buffers[i]); + if (!buf) { + _mesa_error(ctx, GL_OUT_OF_MEMORY, "%s", func); + return; + } + } + else + buf = &DummyBufferObject; + + _mesa_HashInsert(ctx->Shared->BufferObjects, buffers[i], buf); } mtx_unlock(&ctx->Shared->Mutex); } +/** + * Generate a set of unique buffer object IDs and store them in \c buffers. + * + * \param n Number of IDs to generate. + * \param buffers Array of \c n locations to store the IDs. + */ +void GLAPIENTRY +_mesa_GenBuffers(GLsizei n, GLuint *buffers) +{ + create_buffers(n, buffers, false); +} + +/** + * Create a set of buffer objects and store their unique IDs in \c buffers. + * + * \param n Number of IDs to generate. + * \param buffers Array of \c n locations to store the IDs. + */ +void GLAPIENTRY +_mesa_CreateBuffers(GLsizei n, GLuint *buffers) +{ + create_buffers(n, buffers, true); +} + /** * Determine if ID is the name of a buffer object. @@ -1337,15 +1392,13 @@ _mesa_IsBuffer(GLuint id) } -void GLAPIENTRY -_mesa_BufferStorage(GLenum target, GLsizeiptr size, const GLvoid *data, - GLbitfield flags) +void +_mesa_buffer_storage(struct gl_context *ctx, struct gl_buffer_object *bufObj, + GLenum target, GLsizeiptr size, const GLvoid *data, + GLbitfield flags, const char *func) { - GET_CURRENT_CONTEXT(ctx); - struct gl_buffer_object *bufObj; - if (size <= 0) { - _mesa_error(ctx, GL_INVALID_VALUE, "glBufferStorage(size <= 0)"); + _mesa_error(ctx, GL_INVALID_VALUE, "%s(size <= 0)", func); return; } @@ -1355,27 +1408,25 @@ _mesa_BufferStorage(GLenum target, GLsizeiptr size, const GLvoid *data, GL_MAP_COHERENT_BIT | GL_DYNAMIC_STORAGE_BIT | GL_CLIENT_STORAGE_BIT)) { - _mesa_error(ctx, GL_INVALID_VALUE, "glBufferStorage(flags)"); + _mesa_error(ctx, GL_INVALID_VALUE, "%s(invalid flag bits set)", func); return; } if (flags & GL_MAP_PERSISTENT_BIT && !(flags & (GL_MAP_READ_BIT | GL_MAP_WRITE_BIT))) { - _mesa_error(ctx, GL_INVALID_VALUE, "glBufferStorage(flags!=READ/WRITE)"); + _mesa_error(ctx, GL_INVALID_VALUE, + "%s(PERSISTENT and flags!=READ/WRITE)", func); return; } if (flags & GL_MAP_COHERENT_BIT && !(flags & GL_MAP_PERSISTENT_BIT)) { - _mesa_error(ctx, GL_INVALID_VALUE, "glBufferStorage(flags!=PERSISTENT)"); + _mesa_error(ctx, GL_INVALID_VALUE, + "%s(COHERENT and flags!=PERSISTENT)", func); return; } - bufObj = get_buffer(ctx, "glBufferStorage", target, GL_INVALID_OPERATION); - if (!bufObj) - return; - if (bufObj->Immutable) { - _mesa_error(ctx, GL_INVALID_OPERATION, "glBufferStorage(immutable)"); + _mesa_error(ctx, GL_INVALID_OPERATION, "%s(immutable)", func); return; } @@ -1395,31 +1446,65 @@ _mesa_BufferStorage(GLenum target, GLsizeiptr size, const GLvoid *data, * glBufferStorage is not described in the spec, Graham Sellers * said that it should behave the same as glBufferData. */ - _mesa_error(ctx, GL_INVALID_OPERATION, "glBufferStorage()"); + _mesa_error(ctx, GL_INVALID_OPERATION, "%s", func); } else { - _mesa_error(ctx, GL_OUT_OF_MEMORY, "glBufferStorage()"); + _mesa_error(ctx, GL_OUT_OF_MEMORY, "%s", func); } } } +void GLAPIENTRY +_mesa_BufferStorage(GLenum target, GLsizeiptr size, const GLvoid *data, + GLbitfield flags) +{ + GET_CURRENT_CONTEXT(ctx); + struct gl_buffer_object *bufObj; + + bufObj = get_buffer(ctx, "glBufferStorage", target, GL_INVALID_OPERATION); + if (!bufObj) + return; + + _mesa_buffer_storage(ctx, bufObj, target, size, data, flags, + "glBufferStorage"); +} void GLAPIENTRY -_mesa_BufferData(GLenum target, GLsizeiptrARB size, - const GLvoid * data, GLenum usage) +_mesa_NamedBufferStorage(GLuint buffer, GLsizeiptr size, const GLvoid *data, + GLbitfield flags) { GET_CURRENT_CONTEXT(ctx); struct gl_buffer_object *bufObj; + + bufObj = _mesa_lookup_bufferobj_err(ctx, buffer, "glNamedBufferStorage"); + if (!bufObj) + return; + + /* + * In direct state access, buffer objects have an unspecified target since + * they are not required to be bound. + */ + _mesa_buffer_storage(ctx, bufObj, GL_NONE, size, data, flags, + "glNamedBufferStorage"); +} + + +void +_mesa_buffer_data(struct gl_context *ctx, struct gl_buffer_object *bufObj, + GLenum target, GLsizeiptr size, const GLvoid *data, + GLenum usage, const char *func) +{ bool valid_usage; if (MESA_VERBOSE & VERBOSE_API) - _mesa_debug(ctx, "glBufferData(%s, %ld, %p, %s)\n", + _mesa_debug(ctx, "%s(%s, %ld, %p, %s)\n", + func, _mesa_lookup_enum_by_nr(target), (long int) size, data, _mesa_lookup_enum_by_nr(usage)); if (size < 0) { - _mesa_error(ctx, GL_INVALID_VALUE, "glBufferDataARB(size < 0)"); + _mesa_error(ctx, GL_INVALID_VALUE, "%s(size < 0)", func); return; } @@ -1448,16 +1533,13 @@ _mesa_BufferData(GLenum target, GLsizeiptrARB size, } if (!valid_usage) { - _mesa_error(ctx, GL_INVALID_ENUM, "glBufferData(usage)"); + _mesa_error(ctx, GL_INVALID_ENUM, "%s(invalid usage: %s)", func, + _mesa_lookup_enum_by_nr(usage)); return; } - bufObj = get_buffer(ctx, "glBufferDataARB", target, GL_INVALID_OPERATION); - if (!bufObj) - return; - if (bufObj->Immutable) { - _mesa_error(ctx, GL_INVALID_OPERATION, "glBufferData(immutable)"); + _mesa_error(ctx, GL_INVALID_OPERATION, "%s(immutable)", func); return; } @@ -1490,33 +1572,73 @@ _mesa_BufferData(GLenum target, GLsizeiptrARB size, * EXTERNAL_VIRTUAL_MEMORY_BUFFER_AMD, and the store cannot be * mapped to the GPU address space. */ - _mesa_error(ctx, GL_INVALID_OPERATION, "glBufferData()"); + _mesa_error(ctx, GL_INVALID_OPERATION, "%s", func); } else { - _mesa_error(ctx, GL_OUT_OF_MEMORY, "glBufferData()"); + _mesa_error(ctx, GL_OUT_OF_MEMORY, "%s", func); } } } +void GLAPIENTRY +_mesa_BufferData(GLenum target, GLsizeiptr size, + const GLvoid *data, GLenum usage) +{ + GET_CURRENT_CONTEXT(ctx); + struct gl_buffer_object *bufObj; + + bufObj = get_buffer(ctx, "glBufferData", target, GL_INVALID_OPERATION); + if (!bufObj) + return; + + _mesa_buffer_data(ctx, bufObj, target, size, data, usage, + "glBufferData"); +} void GLAPIENTRY -_mesa_BufferSubData(GLenum target, GLintptrARB offset, - GLsizeiptrARB size, const GLvoid * data) +_mesa_NamedBufferData(GLuint buffer, GLsizeiptr size, const GLvoid *data, + GLenum usage) { GET_CURRENT_CONTEXT(ctx); struct gl_buffer_object *bufObj; - bufObj = buffer_object_subdata_range_good( ctx, target, offset, size, - false, GL_INVALID_OPERATION, - "glBufferSubDataARB" ); - if (!bufObj) { + bufObj = _mesa_lookup_bufferobj_err(ctx, buffer, "glNamedBufferData"); + if (!bufObj) + return; + + /* In direct state access, buffer objects have an unspecified target since + * they are not required to be bound. + */ + _mesa_buffer_data(ctx, bufObj, GL_NONE, size, data, usage, + "glNamedBufferData"); +} + + +/** + * Implementation for glBufferSubData and glNamedBufferSubData. + * + * \param ctx GL context. + * \param bufObj The buffer object. + * \param offset Offset of the first byte of the subdata range. + * \param size Size, in bytes, of the subdata range. + * \param data The data store. + * \param func Name of calling function for recording errors. + * + */ +void +_mesa_buffer_sub_data(struct gl_context *ctx, struct gl_buffer_object *bufObj, + GLintptr offset, GLsizeiptr size, const GLvoid *data, + const char *func) +{ + if (!buffer_object_subdata_range_good(ctx, bufObj, offset, size, + false, func)) { /* error already recorded */ return; } if (bufObj->Immutable && !(bufObj->StorageFlags & GL_DYNAMIC_STORAGE_BIT)) { - _mesa_error(ctx, GL_INVALID_OPERATION, "glBufferSubData"); + _mesa_error(ctx, GL_INVALID_OPERATION, "%s", func); return; } @@ -1526,105 +1648,107 @@ _mesa_BufferSubData(GLenum target, GLintptrARB offset, bufObj->Written = GL_TRUE; assert(ctx->Driver.BufferSubData); - ctx->Driver.BufferSubData( ctx, offset, size, data, bufObj ); + ctx->Driver.BufferSubData(ctx, offset, size, data, bufObj); } +void GLAPIENTRY +_mesa_BufferSubData(GLenum target, GLintptr offset, + GLsizeiptr size, const GLvoid *data) +{ + GET_CURRENT_CONTEXT(ctx); + struct gl_buffer_object *bufObj; + + bufObj = get_buffer(ctx, "glBufferSubData", target, GL_INVALID_OPERATION); + if (!bufObj) + return; + + _mesa_buffer_sub_data(ctx, bufObj, offset, size, data, "glBufferSubData"); +} void GLAPIENTRY -_mesa_GetBufferSubData(GLenum target, GLintptrARB offset, - GLsizeiptrARB size, void * data) +_mesa_NamedBufferSubData(GLuint buffer, GLintptr offset, + GLsizeiptr size, const GLvoid *data) { GET_CURRENT_CONTEXT(ctx); struct gl_buffer_object *bufObj; - bufObj = buffer_object_subdata_range_good(ctx, target, offset, size, - false, GL_INVALID_OPERATION, - "glGetBufferSubDataARB"); - if (!bufObj) { - /* error already recorded */ + bufObj = _mesa_lookup_bufferobj_err(ctx, buffer, "glNamedBufferSubData"); + if (!bufObj) return; - } - assert(ctx->Driver.GetBufferSubData); - ctx->Driver.GetBufferSubData( ctx, offset, size, data, bufObj ); + _mesa_buffer_sub_data(ctx, bufObj, offset, size, data, + "glNamedBufferSubData"); } void GLAPIENTRY -_mesa_ClearBufferData(GLenum target, GLenum internalformat, GLenum format, - GLenum type, const GLvoid* data) +_mesa_GetBufferSubData(GLenum target, GLintptr offset, + GLsizeiptr size, GLvoid *data) { GET_CURRENT_CONTEXT(ctx); - struct gl_buffer_object* bufObj; - mesa_format mesaFormat; - GLubyte clearValue[MAX_PIXEL_BYTES]; - GLsizeiptr clearValueSize; + struct gl_buffer_object *bufObj; - bufObj = get_buffer(ctx, "glClearBufferData", target, GL_INVALID_VALUE); - if (!bufObj) { + bufObj = get_buffer(ctx, "glGetBufferSubData", target, + GL_INVALID_OPERATION); + if (!bufObj) return; - } - if (_mesa_check_disallowed_mapping(bufObj)) { - _mesa_error(ctx, GL_INVALID_OPERATION, - "glClearBufferData(buffer currently mapped)"); + if (!buffer_object_subdata_range_good(ctx, bufObj, offset, size, false, + "glGetBufferSubData")) { return; } - mesaFormat = validate_clear_buffer_format(ctx, internalformat, - format, type, - "glClearBufferData"); - if (mesaFormat == MESA_FORMAT_NONE) { - return; - } + assert(ctx->Driver.GetBufferSubData); + ctx->Driver.GetBufferSubData(ctx, offset, size, data, bufObj); +} - clearValueSize = _mesa_get_format_bytes(mesaFormat); - if (bufObj->Size % clearValueSize != 0) { - _mesa_error(ctx, GL_INVALID_VALUE, - "glClearBufferData(size is not a multiple of " - "internalformat size)"); - return; - } +void GLAPIENTRY +_mesa_GetNamedBufferSubData(GLuint buffer, GLintptr offset, + GLsizeiptr size, GLvoid *data) +{ + GET_CURRENT_CONTEXT(ctx); + struct gl_buffer_object *bufObj; - if (data == NULL) { - /* clear to zeros, per the spec */ - ctx->Driver.ClearBufferSubData(ctx, 0, bufObj->Size, - NULL, clearValueSize, bufObj); + bufObj = _mesa_lookup_bufferobj_err(ctx, buffer, + "glGetNamedBufferSubData"); + if (!bufObj) return; - } - if (!convert_clear_buffer_data(ctx, mesaFormat, clearValue, - format, type, data, "glClearBufferData")) { + if (!buffer_object_subdata_range_good(ctx, bufObj, offset, size, false, + "glGetNamedBufferSubData")) { return; } - ctx->Driver.ClearBufferSubData(ctx, 0, bufObj->Size, - clearValue, clearValueSize, bufObj); + assert(ctx->Driver.GetBufferSubData); + ctx->Driver.GetBufferSubData(ctx, offset, size, data, bufObj); } -void GLAPIENTRY -_mesa_ClearBufferSubData(GLenum target, GLenum internalformat, - GLintptr offset, GLsizeiptr size, - GLenum format, GLenum type, - const GLvoid* data) +/** + * \param subdata true if caller is *SubData, false if *Data + */ +void +_mesa_clear_buffer_sub_data(struct gl_context *ctx, + struct gl_buffer_object *bufObj, + GLenum internalformat, + GLintptr offset, GLsizeiptr size, + GLenum format, GLenum type, + const GLvoid *data, + const char *func, bool subdata) { - GET_CURRENT_CONTEXT(ctx); - struct gl_buffer_object* bufObj; mesa_format mesaFormat; GLubyte clearValue[MAX_PIXEL_BYTES]; GLsizeiptr clearValueSize; - bufObj = buffer_object_subdata_range_good(ctx, target, offset, size, - true, GL_INVALID_VALUE, - "glClearBufferSubData"); - if (!bufObj) { + /* This checks for disallowed mappings. */ + if (!buffer_object_subdata_range_good(ctx, bufObj, offset, size, + subdata, func)) { return; } mesaFormat = validate_clear_buffer_format(ctx, internalformat, - format, type, - "glClearBufferSubData"); + format, type, func); + if (mesaFormat == MESA_FORMAT_NONE) { return; } @@ -1632,8 +1756,8 @@ _mesa_ClearBufferSubData(GLenum target, GLenum internalformat, clearValueSize = _mesa_get_format_bytes(mesaFormat); if (offset % clearValueSize != 0 || size % clearValueSize != 0) { _mesa_error(ctx, GL_INVALID_VALUE, - "glClearBufferSubData(offset or size is not a multiple of " - "internalformat size)"); + "%s(offset or size is not a multiple of " + "internalformat size)", func); return; } @@ -1647,8 +1771,7 @@ _mesa_ClearBufferSubData(GLenum target, GLenum internalformat, } if (!convert_clear_buffer_data(ctx, mesaFormat, clearValue, - format, type, data, - "glClearBufferSubData")) { + format, type, data, func)) { return; } @@ -1658,131 +1781,87 @@ _mesa_ClearBufferSubData(GLenum target, GLenum internalformat, } } - -void * GLAPIENTRY -_mesa_MapBuffer(GLenum target, GLenum access) +void GLAPIENTRY +_mesa_ClearBufferData(GLenum target, GLenum internalformat, GLenum format, + GLenum type, const GLvoid *data) { GET_CURRENT_CONTEXT(ctx); - struct gl_buffer_object * bufObj; - GLbitfield accessFlags; - void *map; - bool valid_access; + struct gl_buffer_object *bufObj; - ASSERT_OUTSIDE_BEGIN_END_WITH_RETVAL(ctx, NULL); + bufObj = get_buffer(ctx, "glClearBufferData", target, GL_INVALID_VALUE); + if (!bufObj) + return; - switch (access) { - case GL_READ_ONLY_ARB: - accessFlags = GL_MAP_READ_BIT; - valid_access = _mesa_is_desktop_gl(ctx); - break; - case GL_WRITE_ONLY_ARB: - accessFlags = GL_MAP_WRITE_BIT; - valid_access = true; - break; - case GL_READ_WRITE_ARB: - accessFlags = GL_MAP_READ_BIT | GL_MAP_WRITE_BIT; - valid_access = _mesa_is_desktop_gl(ctx); - break; - default: - valid_access = false; - break; - } + _mesa_clear_buffer_sub_data(ctx, bufObj, internalformat, 0, bufObj->Size, + format, type, data, + "glClearBufferData", false); +} - if (!valid_access) { - _mesa_error(ctx, GL_INVALID_ENUM, "glMapBufferARB(access)"); - return NULL; - } +void GLAPIENTRY +_mesa_ClearNamedBufferData(GLuint buffer, GLenum internalformat, + GLenum format, GLenum type, const GLvoid *data) +{ + GET_CURRENT_CONTEXT(ctx); + struct gl_buffer_object *bufObj; - bufObj = get_buffer(ctx, "glMapBufferARB", target, GL_INVALID_OPERATION); + bufObj = _mesa_lookup_bufferobj_err(ctx, buffer, "glClearNamedBufferData"); if (!bufObj) - return NULL; + return; - if (accessFlags & GL_MAP_READ_BIT && - !(bufObj->StorageFlags & GL_MAP_READ_BIT)) { - _mesa_error(ctx, GL_INVALID_OPERATION, - "glMapBuffer(invalid read flag)"); - return NULL; - } + _mesa_clear_buffer_sub_data(ctx, bufObj, internalformat, 0, bufObj->Size, + format, type, data, + "glClearNamedBufferData", false); +} - if (accessFlags & GL_MAP_WRITE_BIT && - !(bufObj->StorageFlags & GL_MAP_WRITE_BIT)) { - _mesa_error(ctx, GL_INVALID_OPERATION, - "glMapBuffer(invalid write flag)"); - return NULL; - } - if (_mesa_bufferobj_mapped(bufObj, MAP_USER)) { - _mesa_error(ctx, GL_INVALID_OPERATION, "glMapBufferARB(already mapped)"); - return NULL; - } - - if (!bufObj->Size) { - _mesa_error(ctx, GL_OUT_OF_MEMORY, - "glMapBuffer(buffer size = 0)"); - return NULL; - } +void GLAPIENTRY +_mesa_ClearBufferSubData(GLenum target, GLenum internalformat, + GLintptr offset, GLsizeiptr size, + GLenum format, GLenum type, + const GLvoid *data) +{ + GET_CURRENT_CONTEXT(ctx); + struct gl_buffer_object *bufObj; - assert(ctx->Driver.MapBufferRange); - map = ctx->Driver.MapBufferRange(ctx, 0, bufObj->Size, accessFlags, bufObj, - MAP_USER); - if (!map) { - _mesa_error(ctx, GL_OUT_OF_MEMORY, "glMapBufferARB(map failed)"); - return NULL; - } - else { - /* The driver callback should have set these fields. - * This is important because other modules (like VBO) might call - * the driver function directly. - */ - assert(bufObj->Mappings[MAP_USER].Pointer == map); - assert(bufObj->Mappings[MAP_USER].Length == bufObj->Size); - assert(bufObj->Mappings[MAP_USER].Offset == 0); - bufObj->Mappings[MAP_USER].AccessFlags = accessFlags; - } + bufObj = get_buffer(ctx, "glClearBufferSubData", target, GL_INVALID_VALUE); + if (!bufObj) + return; - if (access == GL_WRITE_ONLY_ARB || access == GL_READ_WRITE_ARB) - bufObj->Written = GL_TRUE; + _mesa_clear_buffer_sub_data(ctx, bufObj, internalformat, offset, size, + format, type, data, + "glClearBufferSubData", true); +} -#ifdef VBO_DEBUG - printf("glMapBufferARB(%u, sz %ld, access 0x%x)\n", - bufObj->Name, bufObj->Size, access); - if (access == GL_WRITE_ONLY_ARB) { - GLuint i; - GLubyte *b = (GLubyte *) bufObj->Pointer; - for (i = 0; i < bufObj->Size; i++) - b[i] = i & 0xff; - } -#endif +void GLAPIENTRY +_mesa_ClearNamedBufferSubData(GLuint buffer, GLenum internalformat, + GLintptr offset, GLsizeiptr size, + GLenum format, GLenum type, + const GLvoid *data) +{ + GET_CURRENT_CONTEXT(ctx); + struct gl_buffer_object *bufObj; -#ifdef BOUNDS_CHECK - { - GLubyte *buf = (GLubyte *) bufObj->Pointer; - GLuint i; - /* buffer is 100 bytes larger than requested, fill with magic value */ - for (i = 0; i < 100; i++) { - buf[bufObj->Size - i - 1] = 123; - } - } -#endif + bufObj = _mesa_lookup_bufferobj_err(ctx, buffer, + "glClearNamedBufferSubData"); + if (!bufObj) + return; - return bufObj->Mappings[MAP_USER].Pointer; + _mesa_clear_buffer_sub_data(ctx, bufObj, internalformat, offset, size, + format, type, data, + "glClearNamedBufferSubData", true); } -GLboolean GLAPIENTRY -_mesa_UnmapBuffer(GLenum target) +GLboolean +_mesa_unmap_buffer(struct gl_context *ctx, struct gl_buffer_object *bufObj, + const char *func) { - GET_CURRENT_CONTEXT(ctx); - struct gl_buffer_object *bufObj; GLboolean status = GL_TRUE; ASSERT_OUTSIDE_BEGIN_END_WITH_RETVAL(ctx, GL_FALSE); - bufObj = get_buffer(ctx, "glUnmapBufferARB", target, GL_INVALID_OPERATION); - if (!bufObj) - return GL_FALSE; - if (!_mesa_bufferobj_mapped(bufObj, MAP_USER)) { - _mesa_error(ctx, GL_INVALID_OPERATION, "glUnmapBufferARB"); + _mesa_error(ctx, GL_INVALID_OPERATION, + "%s(buffer is not mapped)", func); return GL_FALSE; } @@ -1831,129 +1910,164 @@ _mesa_UnmapBuffer(GLenum target) return status; } +GLboolean GLAPIENTRY +_mesa_UnmapBuffer(GLenum target) +{ + GET_CURRENT_CONTEXT(ctx); + struct gl_buffer_object *bufObj; -void GLAPIENTRY -_mesa_GetBufferParameteriv(GLenum target, GLenum pname, GLint *params) + bufObj = get_buffer(ctx, "glUnmapBuffer", target, GL_INVALID_OPERATION); + if (!bufObj) + return GL_FALSE; + + return _mesa_unmap_buffer(ctx, bufObj, "glUnmapBuffer"); +} + +GLboolean GLAPIENTRY +_mesa_UnmapNamedBuffer(GLuint buffer) { GET_CURRENT_CONTEXT(ctx); struct gl_buffer_object *bufObj; - bufObj = get_buffer(ctx, "glGetBufferParameterivARB", target, - GL_INVALID_OPERATION); + bufObj = _mesa_lookup_bufferobj_err(ctx, buffer, "glUnmapNamedBuffer"); if (!bufObj) - return; + return GL_FALSE; + return _mesa_unmap_buffer(ctx, bufObj, "glUnmapNamedBuffer"); +} + + +static bool +get_buffer_parameter(struct gl_context *ctx, + struct gl_buffer_object *bufObj, GLenum pname, + GLint64 *params, const char *func) +{ switch (pname) { case GL_BUFFER_SIZE_ARB: - *params = (GLint) bufObj->Size; - return; + *params = bufObj->Size; + break; case GL_BUFFER_USAGE_ARB: *params = bufObj->Usage; - return; + break; case GL_BUFFER_ACCESS_ARB: *params = simplified_access_mode(ctx, bufObj->Mappings[MAP_USER].AccessFlags); - return; + break; case GL_BUFFER_MAPPED_ARB: *params = _mesa_bufferobj_mapped(bufObj, MAP_USER); - return; + break; case GL_BUFFER_ACCESS_FLAGS: if (!ctx->Extensions.ARB_map_buffer_range) goto invalid_pname; *params = bufObj->Mappings[MAP_USER].AccessFlags; - return; + break; case GL_BUFFER_MAP_OFFSET: if (!ctx->Extensions.ARB_map_buffer_range) goto invalid_pname; - *params = (GLint) bufObj->Mappings[MAP_USER].Offset; - return; + *params = bufObj->Mappings[MAP_USER].Offset; + break; case GL_BUFFER_MAP_LENGTH: if (!ctx->Extensions.ARB_map_buffer_range) goto invalid_pname; - *params = (GLint) bufObj->Mappings[MAP_USER].Length; - return; + *params = bufObj->Mappings[MAP_USER].Length; + break; case GL_BUFFER_IMMUTABLE_STORAGE: if (!ctx->Extensions.ARB_buffer_storage) goto invalid_pname; *params = bufObj->Immutable; - return; + break; case GL_BUFFER_STORAGE_FLAGS: if (!ctx->Extensions.ARB_buffer_storage) goto invalid_pname; *params = bufObj->StorageFlags; - return; + break; default: - ; /* fall-through */ + goto invalid_pname; } + return true; + invalid_pname: - _mesa_error(ctx, GL_INVALID_ENUM, "glGetBufferParameterivARB(pname=%s)", + _mesa_error(ctx, GL_INVALID_ENUM, "%s(invalid pname: %s)", func, _mesa_lookup_enum_by_nr(pname)); + return false; } +void GLAPIENTRY +_mesa_GetBufferParameteriv(GLenum target, GLenum pname, GLint *params) +{ + GET_CURRENT_CONTEXT(ctx); + struct gl_buffer_object *bufObj; + GLint64 parameter; + + bufObj = get_buffer(ctx, "glGetBufferParameteriv", target, + GL_INVALID_OPERATION); + if (!bufObj) + return; + + if (!get_buffer_parameter(ctx, bufObj, pname, ¶meter, + "glGetBufferParameteriv")) + return; /* Error already recorded. */ + + *params = (GLint) parameter; +} -/** - * New in GL 3.2 - * This is pretty much a duplicate of GetBufferParameteriv() but the - * GL_BUFFER_SIZE_ARB attribute will be 64-bits on a 64-bit system. - */ void GLAPIENTRY _mesa_GetBufferParameteri64v(GLenum target, GLenum pname, GLint64 *params) { GET_CURRENT_CONTEXT(ctx); struct gl_buffer_object *bufObj; + GLint64 parameter; bufObj = get_buffer(ctx, "glGetBufferParameteri64v", target, GL_INVALID_OPERATION); if (!bufObj) return; - switch (pname) { - case GL_BUFFER_SIZE_ARB: - *params = bufObj->Size; - return; - case GL_BUFFER_USAGE_ARB: - *params = bufObj->Usage; - return; - case GL_BUFFER_ACCESS_ARB: - *params = simplified_access_mode(ctx, - bufObj->Mappings[MAP_USER].AccessFlags); - return; - case GL_BUFFER_ACCESS_FLAGS: - if (!ctx->Extensions.ARB_map_buffer_range) - goto invalid_pname; - *params = bufObj->Mappings[MAP_USER].AccessFlags; - return; - case GL_BUFFER_MAPPED_ARB: - *params = _mesa_bufferobj_mapped(bufObj, MAP_USER); - return; - case GL_BUFFER_MAP_OFFSET: - if (!ctx->Extensions.ARB_map_buffer_range) - goto invalid_pname; - *params = bufObj->Mappings[MAP_USER].Offset; - return; - case GL_BUFFER_MAP_LENGTH: - if (!ctx->Extensions.ARB_map_buffer_range) - goto invalid_pname; - *params = bufObj->Mappings[MAP_USER].Length; - return; - case GL_BUFFER_IMMUTABLE_STORAGE: - if (!ctx->Extensions.ARB_buffer_storage) - goto invalid_pname; - *params = bufObj->Immutable; + if (!get_buffer_parameter(ctx, bufObj, pname, ¶meter, + "glGetBufferParameteri64v")) + return; /* Error already recorded. */ + + *params = parameter; +} + +void GLAPIENTRY +_mesa_GetNamedBufferParameteriv(GLuint buffer, GLenum pname, GLint *params) +{ + GET_CURRENT_CONTEXT(ctx); + struct gl_buffer_object *bufObj; + GLint64 parameter; + + bufObj = _mesa_lookup_bufferobj_err(ctx, buffer, + "glGetNamedBufferParameteriv"); + if (!bufObj) return; - case GL_BUFFER_STORAGE_FLAGS: - if (!ctx->Extensions.ARB_buffer_storage) - goto invalid_pname; - *params = bufObj->StorageFlags; + + if (!get_buffer_parameter(ctx, bufObj, pname, ¶meter, + "glGetNamedBufferParameteriv")) + return; /* Error already recorded. */ + + *params = (GLint) parameter; +} + +void GLAPIENTRY +_mesa_GetNamedBufferParameteri64v(GLuint buffer, GLenum pname, + GLint64 *params) +{ + GET_CURRENT_CONTEXT(ctx); + struct gl_buffer_object *bufObj; + GLint64 parameter; + + bufObj = _mesa_lookup_bufferobj_err(ctx, buffer, + "glGetNamedBufferParameteri64v"); + if (!bufObj) return; - default: - ; /* fall-through */ - } -invalid_pname: - _mesa_error(ctx, GL_INVALID_ENUM, "glGetBufferParameteri64v(pname=%s)", - _mesa_lookup_enum_by_nr(pname)); + if (!get_buffer_parameter(ctx, bufObj, pname, ¶meter, + "glGetNamedBufferParameteri64v")) + return; /* Error already recorded. */ + + *params = parameter; } @@ -1961,14 +2075,15 @@ void GLAPIENTRY _mesa_GetBufferPointerv(GLenum target, GLenum pname, GLvoid **params) { GET_CURRENT_CONTEXT(ctx); - struct gl_buffer_object * bufObj; + struct gl_buffer_object *bufObj; - if (pname != GL_BUFFER_MAP_POINTER_ARB) { - _mesa_error(ctx, GL_INVALID_ENUM, "glGetBufferPointervARB(pname)"); + if (pname != GL_BUFFER_MAP_POINTER) { + _mesa_error(ctx, GL_INVALID_ENUM, "glGetBufferPointerv(pname != " + "GL_BUFFER_MAP_POINTER)"); return; } - bufObj = get_buffer(ctx, "glGetBufferPointervARB", target, + bufObj = get_buffer(ctx, "glGetBufferPointerv", target, GL_INVALID_OPERATION); if (!bufObj) return; @@ -1976,66 +2091,75 @@ _mesa_GetBufferPointerv(GLenum target, GLenum pname, GLvoid **params) *params = bufObj->Mappings[MAP_USER].Pointer; } - void GLAPIENTRY -_mesa_CopyBufferSubData(GLenum readTarget, GLenum writeTarget, - GLintptr readOffset, GLintptr writeOffset, - GLsizeiptr size) +_mesa_GetNamedBufferPointerv(GLuint buffer, GLenum pname, GLvoid **params) { GET_CURRENT_CONTEXT(ctx); - struct gl_buffer_object *src, *dst; + struct gl_buffer_object *bufObj; - src = get_buffer(ctx, "glCopyBufferSubData", readTarget, - GL_INVALID_OPERATION); - if (!src) + if (pname != GL_BUFFER_MAP_POINTER) { + _mesa_error(ctx, GL_INVALID_ENUM, "glGetNamedBufferPointerv(pname != " + "GL_BUFFER_MAP_POINTER)"); return; + } - dst = get_buffer(ctx, "glCopyBufferSubData", writeTarget, - GL_INVALID_OPERATION); - if (!dst) + bufObj = _mesa_lookup_bufferobj_err(ctx, buffer, + "glGetNamedBufferPointerv"); + if (!bufObj) return; + *params = bufObj->Mappings[MAP_USER].Pointer; +} + + +void +_mesa_copy_buffer_sub_data(struct gl_context *ctx, + struct gl_buffer_object *src, + struct gl_buffer_object *dst, + GLintptr readOffset, GLintptr writeOffset, + GLsizeiptr size, const char *func) +{ if (_mesa_check_disallowed_mapping(src)) { _mesa_error(ctx, GL_INVALID_OPERATION, - "glCopyBufferSubData(readBuffer is mapped)"); + "%s(readBuffer is mapped)", func); return; } if (_mesa_check_disallowed_mapping(dst)) { _mesa_error(ctx, GL_INVALID_OPERATION, - "glCopyBufferSubData(writeBuffer is mapped)"); + "%s(writeBuffer is mapped)", func); return; } if (readOffset < 0) { _mesa_error(ctx, GL_INVALID_VALUE, - "glCopyBufferSubData(readOffset = %d)", (int) readOffset); + "%s(readOffset %d < 0)", func, (int) readOffset); return; } if (writeOffset < 0) { _mesa_error(ctx, GL_INVALID_VALUE, - "glCopyBufferSubData(writeOffset = %d)", (int) writeOffset); + "%s(writeOffset %d < 0)", func, (int) writeOffset); return; } if (size < 0) { _mesa_error(ctx, GL_INVALID_VALUE, - "glCopyBufferSubData(writeOffset = %d)", (int) size); + "%s(size %d < 0)", func, (int) size); return; } if (readOffset + size > src->Size) { _mesa_error(ctx, GL_INVALID_VALUE, - "glCopyBufferSubData(readOffset + size = %d)", - (int) (readOffset + size)); + "%s(readOffset %d + size %d > src_buffer_size %d)", func, + (int) readOffset, (int) size, (int) src->Size); return; } if (writeOffset + size > dst->Size) { _mesa_error(ctx, GL_INVALID_VALUE, - "glCopyBufferSubData(writeOffset + size = %d)", - (int) (writeOffset + size)); + "%s(writeOffset %d + size %d > dst_buffer_size %d)", func, + (int) writeOffset, (int) size, (int) dst->Size); return; } @@ -2049,7 +2173,7 @@ _mesa_CopyBufferSubData(GLenum readTarget, GLenum writeTarget, else { /* overlapping src/dst is illegal */ _mesa_error(ctx, GL_INVALID_VALUE, - "glCopyBufferSubData(overlapping src/dst)"); + "%s(overlapping src/dst)", func); return; } } @@ -2057,36 +2181,71 @@ _mesa_CopyBufferSubData(GLenum readTarget, GLenum writeTarget, ctx->Driver.CopyBufferSubData(ctx, src, dst, readOffset, writeOffset, size); } +void GLAPIENTRY +_mesa_CopyBufferSubData(GLenum readTarget, GLenum writeTarget, + GLintptr readOffset, GLintptr writeOffset, + GLsizeiptr size) +{ + GET_CURRENT_CONTEXT(ctx); + struct gl_buffer_object *src, *dst; + + src = get_buffer(ctx, "glCopyBufferSubData", readTarget, + GL_INVALID_OPERATION); + if (!src) + return; -/** - * See GL_ARB_map_buffer_range spec - */ -void * GLAPIENTRY -_mesa_MapBufferRange(GLenum target, GLintptr offset, GLsizeiptr length, - GLbitfield access) + dst = get_buffer(ctx, "glCopyBufferSubData", writeTarget, + GL_INVALID_OPERATION); + if (!dst) + return; + + _mesa_copy_buffer_sub_data(ctx, src, dst, readOffset, writeOffset, size, + "glCopyBufferSubData"); +} + +void GLAPIENTRY +_mesa_CopyNamedBufferSubData(GLuint readBuffer, GLuint writeBuffer, + GLintptr readOffset, GLintptr writeOffset, + GLsizeiptr size) { GET_CURRENT_CONTEXT(ctx); - struct gl_buffer_object *bufObj; + struct gl_buffer_object *src, *dst; + + src = _mesa_lookup_bufferobj_err(ctx, readBuffer, + "glCopyNamedBufferSubData"); + if (!src) + return; + + dst = _mesa_lookup_bufferobj_err(ctx, writeBuffer, + "glCopyNamedBufferSubData"); + if (!dst) + return; + + _mesa_copy_buffer_sub_data(ctx, src, dst, readOffset, writeOffset, size, + "glCopyNamedBufferSubData"); +} + + +void * +_mesa_map_buffer_range(struct gl_context *ctx, + struct gl_buffer_object *bufObj, + GLintptr offset, GLsizeiptr length, + GLbitfield access, const char *func) +{ void *map; GLbitfield allowed_access; ASSERT_OUTSIDE_BEGIN_END_WITH_RETVAL(ctx, NULL); - if (!ctx->Extensions.ARB_map_buffer_range) { - _mesa_error(ctx, GL_INVALID_OPERATION, - "glMapBufferRange(extension not supported)"); - return NULL; - } - if (offset < 0) { _mesa_error(ctx, GL_INVALID_VALUE, - "glMapBufferRange(offset = %ld)", (long)offset); + "%s(offset %ld < 0)", func, (long) offset); return NULL; } if (length < 0) { _mesa_error(ctx, GL_INVALID_VALUE, - "glMapBufferRange(length = %ld)", (long)length); + "%s(length %ld < 0)", func, (long) length); return NULL; } @@ -2096,10 +2255,13 @@ _mesa_MapBufferRange(GLenum target, GLintptr offset, GLsizeiptr length, * conditions: * * * <length> is zero." + * + * Additionally, page 94 of the PDF of the OpenGL 4.5 core spec + * (30.10.2014) also says this, so it's no longer allowed for desktop GL, + * either. */ - if (_mesa_is_gles(ctx) && length == 0) { - _mesa_error(ctx, GL_INVALID_OPERATION, - "glMapBufferRange(length = 0)"); + if (length == 0) { + _mesa_error(ctx, GL_INVALID_OPERATION, "%s(length = 0)", func); return NULL; } @@ -2116,14 +2278,15 @@ _mesa_MapBufferRange(GLenum target, GLintptr offset, GLsizeiptr length, } if (access & ~allowed_access) { - /* generate an error if any other than allowed bit is set */ - _mesa_error(ctx, GL_INVALID_VALUE, "glMapBufferRange(access)"); + /* generate an error if any bits other than those allowed are set */ + _mesa_error(ctx, GL_INVALID_VALUE, + "%s(access has undefined bits set)", func); return NULL; } if ((access & (GL_MAP_READ_BIT | GL_MAP_WRITE_BIT)) == 0) { _mesa_error(ctx, GL_INVALID_OPERATION, - "glMapBufferRange(access indicates neither read or write)"); + "%s(access indicates neither read or write)", func); return NULL; } @@ -2132,82 +2295,69 @@ _mesa_MapBufferRange(GLenum target, GLintptr offset, GLsizeiptr length, GL_MAP_INVALIDATE_BUFFER_BIT | GL_MAP_UNSYNCHRONIZED_BIT))) { _mesa_error(ctx, GL_INVALID_OPERATION, - "glMapBufferRange(invalid access flags)"); + "%s(read access with disallowed bits)", func); return NULL; } if ((access & GL_MAP_FLUSH_EXPLICIT_BIT) && ((access & GL_MAP_WRITE_BIT) == 0)) { _mesa_error(ctx, GL_INVALID_OPERATION, - "glMapBufferRange(invalid access flags)"); + "%s(access has flush explicit without write)", func); return NULL; } - bufObj = get_buffer(ctx, "glMapBufferRange", target, GL_INVALID_OPERATION); - if (!bufObj) - return NULL; - if (access & GL_MAP_READ_BIT && !(bufObj->StorageFlags & GL_MAP_READ_BIT)) { _mesa_error(ctx, GL_INVALID_OPERATION, - "glMapBufferRange(invalid read flag)"); + "%s(buffer does not allow read access)", func); return NULL; } if (access & GL_MAP_WRITE_BIT && !(bufObj->StorageFlags & GL_MAP_WRITE_BIT)) { _mesa_error(ctx, GL_INVALID_OPERATION, - "glMapBufferRange(invalid write flag)"); + "%s(buffer does not allow write access)", func); return NULL; } if (access & GL_MAP_COHERENT_BIT && !(bufObj->StorageFlags & GL_MAP_COHERENT_BIT)) { _mesa_error(ctx, GL_INVALID_OPERATION, - "glMapBufferRange(invalid coherent flag)"); + "%s(buffer does not allow coherent access)", func); return NULL; } if (access & GL_MAP_PERSISTENT_BIT && !(bufObj->StorageFlags & GL_MAP_PERSISTENT_BIT)) { _mesa_error(ctx, GL_INVALID_OPERATION, - "glMapBufferRange(invalid persistent flag)"); + "%s(buffer does not allow persistent access)", func); return NULL; } if (offset + length > bufObj->Size) { _mesa_error(ctx, GL_INVALID_VALUE, - "glMapBufferRange(offset + length > size)"); + "%s(offset %ld + length %ld > buffer_size %ld)", func, + offset, length, bufObj->Size); return NULL; } if (_mesa_bufferobj_mapped(bufObj, MAP_USER)) { _mesa_error(ctx, GL_INVALID_OPERATION, - "glMapBufferRange(buffer already mapped)"); + "%s(buffer already mapped)", func); return NULL; } if (!bufObj->Size) { - _mesa_error(ctx, GL_OUT_OF_MEMORY, - "glMapBufferRange(buffer size = 0)"); + _mesa_error(ctx, GL_OUT_OF_MEMORY, "%s(buffer size = 0)", func); return NULL; } - /* Mapping zero bytes should return a non-null pointer. */ - if (!length) { - static long dummy = 0; - bufObj->Mappings[MAP_USER].Pointer = &dummy; - bufObj->Mappings[MAP_USER].Length = length; - bufObj->Mappings[MAP_USER].Offset = offset; - bufObj->Mappings[MAP_USER].AccessFlags = access; - return bufObj->Mappings[MAP_USER].Pointer; - } assert(ctx->Driver.MapBufferRange); map = ctx->Driver.MapBufferRange(ctx, offset, length, access, bufObj, MAP_USER); if (!map) { - _mesa_error(ctx, GL_OUT_OF_MEMORY, "glMapBufferARB(map failed)"); + _mesa_error(ctx, GL_OUT_OF_MEMORY, "%s(map failed)", func); } else { /* The driver callback should have set all these fields. @@ -2220,61 +2370,189 @@ _mesa_MapBufferRange(GLenum target, GLintptr offset, GLsizeiptr length, assert(bufObj->Mappings[MAP_USER].AccessFlags == access); } + if (access & GL_MAP_WRITE_BIT) + bufObj->Written = GL_TRUE; + +#ifdef VBO_DEBUG + if (strstr(func, "Range") == NULL) { /* If not MapRange */ + printf("glMapBuffer(%u, sz %ld, access 0x%x)\n", + bufObj->Name, bufObj->Size, access); + /* Access must be write only */ + if ((access & GL_MAP_WRITE_BIT) && (!(access & ~GL_MAP_WRITE_BIT))) { + GLuint i; + GLubyte *b = (GLubyte *) bufObj->Pointer; + for (i = 0; i < bufObj->Size; i++) + b[i] = i & 0xff; + } + } +#endif + +#ifdef BOUNDS_CHECK + if (strstr(func, "Range") == NULL) { /* If not MapRange */ + GLubyte *buf = (GLubyte *) bufObj->Pointer; + GLuint i; + /* buffer is 100 bytes larger than requested, fill with magic value */ + for (i = 0; i < 100; i++) { + buf[bufObj->Size - i - 1] = 123; + } + } +#endif + return map; } +void * GLAPIENTRY +_mesa_MapBufferRange(GLenum target, GLintptr offset, GLsizeiptr length, + GLbitfield access) +{ + GET_CURRENT_CONTEXT(ctx); + struct gl_buffer_object *bufObj; + + if (!ctx->Extensions.ARB_map_buffer_range) { + _mesa_error(ctx, GL_INVALID_OPERATION, + "glMapBufferRange(ARB_map_buffer_range not supported)"); + return NULL; + } + + bufObj = get_buffer(ctx, "glMapBufferRange", target, GL_INVALID_OPERATION); + if (!bufObj) + return NULL; + + return _mesa_map_buffer_range(ctx, bufObj, offset, length, access, + "glMapBufferRange"); +} + +void * GLAPIENTRY +_mesa_MapNamedBufferRange(GLuint buffer, GLintptr offset, GLsizeiptr length, + GLbitfield access) +{ + GET_CURRENT_CONTEXT(ctx); + struct gl_buffer_object *bufObj; + + if (!ctx->Extensions.ARB_map_buffer_range) { + _mesa_error(ctx, GL_INVALID_OPERATION, + "glMapNamedBufferRange(" + "ARB_map_buffer_range not supported)"); + return NULL; + } + + bufObj = _mesa_lookup_bufferobj_err(ctx, buffer, "glMapNamedBufferRange"); + if (!bufObj) + return NULL; + + return _mesa_map_buffer_range(ctx, bufObj, offset, length, access, + "glMapNamedBufferRange"); +} /** - * See GL_ARB_map_buffer_range spec + * Converts GLenum access from MapBuffer and MapNamedBuffer into + * flags for input to _mesa_map_buffer_range. + * + * \return true if the type of requested access is permissible. */ -void GLAPIENTRY -_mesa_FlushMappedBufferRange(GLenum target, GLintptr offset, GLsizeiptr length) +static bool +get_map_buffer_access_flags(struct gl_context *ctx, GLenum access, + GLbitfield *flags) +{ + switch (access) { + case GL_READ_ONLY_ARB: + *flags = GL_MAP_READ_BIT; + return _mesa_is_desktop_gl(ctx); + case GL_WRITE_ONLY_ARB: + *flags = GL_MAP_WRITE_BIT; + return true; + case GL_READ_WRITE_ARB: + *flags = GL_MAP_READ_BIT | GL_MAP_WRITE_BIT; + return _mesa_is_desktop_gl(ctx); + default: + return false; + } +} + +void * GLAPIENTRY +_mesa_MapBuffer(GLenum target, GLenum access) +{ + GET_CURRENT_CONTEXT(ctx); + struct gl_buffer_object *bufObj; + GLbitfield accessFlags; + + if (!get_map_buffer_access_flags(ctx, access, &accessFlags)) { + _mesa_error(ctx, GL_INVALID_ENUM, "glMapBuffer(invalid access)"); + return NULL; + } + + bufObj = get_buffer(ctx, "glMapBuffer", target, GL_INVALID_OPERATION); + if (!bufObj) + return NULL; + + return _mesa_map_buffer_range(ctx, bufObj, 0, bufObj->Size, accessFlags, + "glMapBuffer"); +} + +void * GLAPIENTRY +_mesa_MapNamedBuffer(GLuint buffer, GLenum access) { GET_CURRENT_CONTEXT(ctx); struct gl_buffer_object *bufObj; + GLbitfield accessFlags; + if (!get_map_buffer_access_flags(ctx, access, &accessFlags)) { + _mesa_error(ctx, GL_INVALID_ENUM, "glMapNamedBuffer(invalid access)"); + return NULL; + } + + bufObj = _mesa_lookup_bufferobj_err(ctx, buffer, "glMapNamedBuffer"); + if (!bufObj) + return NULL; + + return _mesa_map_buffer_range(ctx, bufObj, 0, bufObj->Size, accessFlags, + "glMapNamedBuffer"); +} + + +void +_mesa_flush_mapped_buffer_range(struct gl_context *ctx, + struct gl_buffer_object *bufObj, + GLintptr offset, GLsizeiptr length, + const char *func) +{ if (!ctx->Extensions.ARB_map_buffer_range) { _mesa_error(ctx, GL_INVALID_OPERATION, - "glFlushMappedBufferRange(extension not supported)"); + "%s(ARB_map_buffer_range not supported)", func); return; } if (offset < 0) { _mesa_error(ctx, GL_INVALID_VALUE, - "glFlushMappedBufferRange(offset = %ld)", (long)offset); + "%s(offset %ld < 0)", func, (long) offset); return; } if (length < 0) { _mesa_error(ctx, GL_INVALID_VALUE, - "glFlushMappedBufferRange(length = %ld)", (long)length); + "%s(length %ld < 0)", func, (long) length); return; } - bufObj = get_buffer(ctx, "glFlushMappedBufferRange", target, - GL_INVALID_OPERATION); - if (!bufObj) - return; - if (!_mesa_bufferobj_mapped(bufObj, MAP_USER)) { /* buffer is not mapped */ _mesa_error(ctx, GL_INVALID_OPERATION, - "glFlushMappedBufferRange(buffer is not mapped)"); + "%s(buffer is not mapped)", func); return; } if ((bufObj->Mappings[MAP_USER].AccessFlags & GL_MAP_FLUSH_EXPLICIT_BIT) == 0) { _mesa_error(ctx, GL_INVALID_OPERATION, - "glFlushMappedBufferRange(GL_MAP_FLUSH_EXPLICIT_BIT not set)"); + "%s(GL_MAP_FLUSH_EXPLICIT_BIT not set)", func); return; } if (offset + length > bufObj->Mappings[MAP_USER].Length) { _mesa_error(ctx, GL_INVALID_VALUE, - "glFlushMappedBufferRange(offset %ld + length %ld > mapped length %ld)", - (long)offset, (long)length, - (long)bufObj->Mappings[MAP_USER].Length); + "%s(offset %ld + length %ld > mapped length %ld)", func, + (long) offset, (long) length, + (long) bufObj->Mappings[MAP_USER].Length); return; } @@ -2285,6 +2563,38 @@ _mesa_FlushMappedBufferRange(GLenum target, GLintptr offset, GLsizeiptr length) MAP_USER); } +void GLAPIENTRY +_mesa_FlushMappedBufferRange(GLenum target, GLintptr offset, + GLsizeiptr length) +{ + GET_CURRENT_CONTEXT(ctx); + struct gl_buffer_object *bufObj; + + bufObj = get_buffer(ctx, "glFlushMappedBufferRange", target, + GL_INVALID_OPERATION); + if (!bufObj) + return; + + _mesa_flush_mapped_buffer_range(ctx, bufObj, offset, length, + "glFlushMappedBufferRange"); +} + +void GLAPIENTRY +_mesa_FlushMappedNamedBufferRange(GLuint buffer, GLintptr offset, + GLsizeiptr length) +{ + GET_CURRENT_CONTEXT(ctx); + struct gl_buffer_object *bufObj; + + bufObj = _mesa_lookup_bufferobj_err(ctx, buffer, + "glFlushMappedNamedBufferRange"); + if (!bufObj) + return; + + _mesa_flush_mapped_buffer_range(ctx, bufObj, offset, length, + "glFlushMappedNamedBufferRange"); +} + static GLenum buffer_object_purgeable(struct gl_context *ctx, GLuint name, GLenum option) diff --git a/mesalib/src/mesa/main/bufferobj.h b/mesalib/src/mesa/main/bufferobj.h index fe294fc0b..b5d73aec0 100644 --- a/mesalib/src/mesa/main/bufferobj.h +++ b/mesalib/src/mesa/main/bufferobj.h @@ -89,6 +89,10 @@ _mesa_lookup_bufferobj(struct gl_context *ctx, GLuint buffer); extern struct gl_buffer_object * _mesa_lookup_bufferobj_locked(struct gl_context *ctx, GLuint buffer); +extern struct gl_buffer_object * +_mesa_lookup_bufferobj_err(struct gl_context *ctx, GLuint buffer, + const char *caller); + extern void _mesa_begin_bufferobj_lookups(struct gl_context *ctx); @@ -126,15 +130,62 @@ extern void _mesa_init_buffer_object_functions(struct dd_function_table *driver); extern void +_mesa_buffer_storage(struct gl_context *ctx, struct gl_buffer_object *bufObj, + GLenum target, GLsizeiptr size, const GLvoid *data, + GLbitfield flags, const char *func); + +extern void +_mesa_buffer_data(struct gl_context *ctx, struct gl_buffer_object *bufObj, + GLenum target, GLsizeiptr size, const GLvoid *data, + GLenum usage, const char *func); + +extern void +_mesa_buffer_sub_data(struct gl_context *ctx, struct gl_buffer_object *bufObj, + GLintptr offset, GLsizeiptr size, const GLvoid *data, + const char *func); + +extern void _mesa_buffer_unmap_all_mappings(struct gl_context *ctx, struct gl_buffer_object *bufObj); extern void -_mesa_buffer_clear_subdata(struct gl_context *ctx, - GLintptr offset, GLsizeiptr size, - const GLvoid *clearValue, - GLsizeiptr clearValueSize, - struct gl_buffer_object *bufObj); +_mesa_copy_buffer_sub_data(struct gl_context *ctx, + struct gl_buffer_object *src, + struct gl_buffer_object *dst, + GLintptr readOffset, GLintptr writeOffset, + GLsizeiptr size, const char *func); + +extern void * +_mesa_map_buffer_range(struct gl_context *ctx, + struct gl_buffer_object *bufObj, + GLintptr offset, GLsizeiptr length, + GLbitfield access, const char *func); + +extern void +_mesa_flush_mapped_buffer_range(struct gl_context *ctx, + struct gl_buffer_object *bufObj, + GLintptr offset, GLsizeiptr length, + const char *func); + +extern void +_mesa_ClearBufferSubData_sw(struct gl_context *ctx, + GLintptr offset, GLsizeiptr size, + const GLvoid *clearValue, + GLsizeiptr clearValueSize, + struct gl_buffer_object *bufObj); + +extern void +_mesa_clear_buffer_sub_data(struct gl_context *ctx, + struct gl_buffer_object *bufObj, + GLenum internalformat, + GLintptr offset, GLsizeiptr size, + GLenum format, GLenum type, + const GLvoid *data, + const char *func, bool subdata); + +extern GLboolean +_mesa_unmap_buffer(struct gl_context *ctx, struct gl_buffer_object *bufObj, + const char *func); /* * API functions @@ -146,7 +197,10 @@ void GLAPIENTRY _mesa_DeleteBuffers(GLsizei n, const GLuint * buffer); void GLAPIENTRY -_mesa_GenBuffers(GLsizei n, GLuint * buffer); +_mesa_GenBuffers(GLsizei n, GLuint *buffers); + +void GLAPIENTRY +_mesa_CreateBuffers(GLsizei n, GLuint *buffers); GLboolean GLAPIENTRY _mesa_IsBuffer(GLuint buffer); @@ -156,34 +210,61 @@ _mesa_BufferStorage(GLenum target, GLsizeiptr size, const GLvoid *data, GLbitfield flags); void GLAPIENTRY -_mesa_BufferData(GLenum target, GLsizeiptrARB size, - const GLvoid * data, GLenum usage); +_mesa_NamedBufferStorage(GLuint buffer, GLsizeiptr size, const GLvoid *data, + GLbitfield flags); + +void GLAPIENTRY +_mesa_BufferData(GLenum target, GLsizeiptr size, + const GLvoid *data, GLenum usage); + +void GLAPIENTRY +_mesa_NamedBufferData(GLuint buffer, GLsizeiptr size, + const GLvoid *data, GLenum usage); + +void GLAPIENTRY +_mesa_BufferSubData(GLenum target, GLintptr offset, + GLsizeiptr size, const GLvoid *data); void GLAPIENTRY -_mesa_BufferSubData(GLenum target, GLintptrARB offset, - GLsizeiptrARB size, const GLvoid * data); +_mesa_NamedBufferSubData(GLuint buffer, GLintptr offset, + GLsizeiptr size, const GLvoid *data); void GLAPIENTRY -_mesa_GetBufferSubData(GLenum target, GLintptrARB offset, - GLsizeiptrARB size, void * data); +_mesa_GetBufferSubData(GLenum target, GLintptr offset, + GLsizeiptr size, GLvoid *data); + +void GLAPIENTRY +_mesa_GetNamedBufferSubData(GLuint buffer, GLintptr offset, + GLsizeiptr size, GLvoid *data); void GLAPIENTRY _mesa_ClearBufferData(GLenum target, GLenum internalformat, GLenum format, GLenum type, - const GLvoid * data); + const GLvoid *data); + +void GLAPIENTRY +_mesa_ClearNamedBufferData(GLuint buffer, GLenum internalformat, + GLenum format, GLenum type, + const GLvoid *data); void GLAPIENTRY _mesa_ClearBufferSubData(GLenum target, GLenum internalformat, GLintptr offset, GLsizeiptr size, GLenum format, GLenum type, - const GLvoid * data); + const GLvoid *data); -void * GLAPIENTRY -_mesa_MapBuffer(GLenum target, GLenum access); +void GLAPIENTRY +_mesa_ClearNamedBufferSubData(GLuint buffer, GLenum internalformat, + GLintptr offset, GLsizeiptr size, + GLenum format, GLenum type, + const GLvoid *data); GLboolean GLAPIENTRY _mesa_UnmapBuffer(GLenum target); +GLboolean GLAPIENTRY +_mesa_UnmapNamedBuffer(GLuint buffer); + void GLAPIENTRY _mesa_GetBufferParameteriv(GLenum target, GLenum pname, GLint *params); @@ -191,21 +272,52 @@ void GLAPIENTRY _mesa_GetBufferParameteri64v(GLenum target, GLenum pname, GLint64 *params); void GLAPIENTRY +_mesa_GetNamedBufferParameteriv(GLuint buffer, GLenum pname, GLint *params); + +void GLAPIENTRY +_mesa_GetNamedBufferParameteri64v(GLuint buffer, GLenum pname, + GLint64 *params); + +void GLAPIENTRY _mesa_GetBufferPointerv(GLenum target, GLenum pname, GLvoid **params); void GLAPIENTRY +_mesa_GetNamedBufferPointerv(GLuint buffer, GLenum pname, GLvoid **params); + + +void GLAPIENTRY _mesa_CopyBufferSubData(GLenum readTarget, GLenum writeTarget, GLintptr readOffset, GLintptr writeOffset, GLsizeiptr size); +void GLAPIENTRY +_mesa_CopyNamedBufferSubData(GLuint readBuffer, GLuint writeBuffer, + GLintptr readOffset, GLintptr writeOffset, + GLsizeiptr size); + void * GLAPIENTRY _mesa_MapBufferRange(GLenum target, GLintptr offset, GLsizeiptr length, GLbitfield access); +void * GLAPIENTRY +_mesa_MapNamedBufferRange(GLuint buffer, GLintptr offset, GLsizeiptr length, + GLbitfield access); + +void * GLAPIENTRY +_mesa_MapBuffer(GLenum target, GLenum access); + +void * GLAPIENTRY +_mesa_MapNamedBuffer(GLuint buffer, GLenum access); + + void GLAPIENTRY _mesa_FlushMappedBufferRange(GLenum target, GLintptr offset, GLsizeiptr length); +void GLAPIENTRY +_mesa_FlushMappedNamedBufferRange(GLuint buffer, GLintptr offset, + GLsizeiptr length); + GLenum GLAPIENTRY _mesa_ObjectPurgeableAPPLE(GLenum objectType, GLuint name, GLenum option); diff --git a/mesalib/src/mesa/main/compiler.h b/mesalib/src/mesa/main/compiler.h index 95581fb49..55152fdef 100644 --- a/mesalib/src/mesa/main/compiler.h +++ b/mesalib/src/mesa/main/compiler.h @@ -57,29 +57,6 @@ extern "C" { # elif !defined(__sparc__) && defined(__sparc) # define __sparc__ # endif -# if !defined(__volatile) -# define __volatile volatile -# endif -#endif - - -/** - * Disable assorted warnings - */ -#if defined(_WIN32) && !defined(__CYGWIN__) -# if !defined(__GNUC__) /* mingw environment */ -# pragma warning( disable : 4068 ) /* unknown pragma */ -# pragma warning( disable : 4710 ) /* function 'foo' not inlined */ -# pragma warning( disable : 4711 ) /* function 'foo' selected for automatic inline expansion */ -# pragma warning( disable : 4127 ) /* conditional expression is constant */ -# if defined(MESA_MINWARN) -# pragma warning( disable : 4244 ) /* '=' : conversion from 'const double ' to 'float ', possible loss of data */ -# pragma warning( disable : 4018 ) /* '<' : signed/unsigned mismatch */ -# pragma warning( disable : 4305 ) /* '=' : truncation from 'const double ' to 'float ' */ -# pragma warning( disable : 4550 ) /* 'function' undefined; assuming extern returning int */ -# pragma warning( disable : 4761 ) /* integral size mismatch in argument; conversion supplied */ -# endif -# endif #endif @@ -101,14 +78,6 @@ extern "C" { #elif defined(__APPLE__) #include <CoreFoundation/CFByteOrder.h> #define CPU_TO_LE32( x ) CFSwapInt32HostToLittle( x ) -#elif (defined(_AIX)) -static inline GLuint CPU_TO_LE32(GLuint x) -{ - return (((x & 0x000000ff) << 24) | - ((x & 0x0000ff00) << 8) | - ((x & 0x00ff0000) >> 8) | - ((x & 0xff000000) >> 24)); -} #elif defined(__OpenBSD__) #include <sys/types.h> #define CPU_TO_LE32( x ) htole32( x ) @@ -125,34 +94,6 @@ static inline GLuint CPU_TO_LE32(GLuint x) -/** - * Create a macro so that asm functions can be linked into compilers other - * than GNU C - */ -#ifndef _ASMAPI -#if defined(_WIN32) -#define _ASMAPI __cdecl -#else -#define _ASMAPI -#endif -#ifdef PTR_DECL_IN_FRONT -#define _ASMAPIP * _ASMAPI -#else -#define _ASMAPIP _ASMAPI * -#endif -#endif - - -/** - * LONGSTRING macro - * gcc -pedantic warns about long string literals, LONGSTRING silences that. - */ -#if !defined(__GNUC__) -# define LONGSTRING -#else -# define LONGSTRING __extension__ -#endif - #define IEEE_ONE 0x3f800000 diff --git a/mesalib/src/mesa/main/context.c b/mesalib/src/mesa/main/context.c index 22c2341d6..c1acda980 100644 --- a/mesalib/src/mesa/main/context.c +++ b/mesalib/src/mesa/main/context.c @@ -882,18 +882,35 @@ update_default_objects(struct gl_context *ctx) /** - * This is the default function we plug into all dispatch table slots - * This helps prevents a segfault when someone calls a GL function without - * first checking if the extension's supported. + * This function is called by the glapi no-op functions. For each OpenGL + * function/entrypoint there's a simple no-op function. These "no-op" + * functions call this function. + * + * If there's a current OpenGL context for the calling thread, we record a + * GL_INVALID_OPERATION error. This can happen either because the app's + * calling an unsupported extension function, or calling an illegal function + * (such as glClear between glBegin/glEnd). + * + * If there's no current OpenGL context for the calling thread, we can + * print a message to stderr. + * + * \param name the name of the OpenGL function, without the "gl" prefix */ -int -_mesa_generic_nop(void) +static void +nop_handler(const char *name) { GET_CURRENT_CONTEXT(ctx); - _mesa_error(ctx, GL_INVALID_OPERATION, - "unsupported function called " - "(unsupported extension or deprecated function?)"); - return 0; + if (ctx) { + _mesa_error(ctx, GL_INVALID_OPERATION, "gl%s(invalid call)", name); + } +#if defined(DEBUG) + else if (getenv("MESA_DEBUG") || getenv("LIBGL_DEBUG")) { + fprintf(stderr, + "GL User Error: gl%s called without a rendering context\n", + name); + fflush(stderr); + } +#endif } @@ -909,16 +926,13 @@ nop_glFlush(void) #endif -extern void (*__glapi_noop_table[])(void); - - /** - * Allocate and initialize a new dispatch table. All the dispatch - * function pointers will point at the _mesa_generic_nop() function - * which raises GL_INVALID_OPERATION. + * Allocate and initialize a new dispatch table. The table will be + * populated with pointers to "no-op" functions. In turn, the no-op + * functions will call nop_handler() above. */ -struct _glapi_table * -_mesa_alloc_dispatch_table(void) +static struct _glapi_table * +alloc_dispatch_table(void) { /* Find the larger of Mesa's dispatch table and libGL's dispatch table. * In practice, this'll be the same for stand-alone Mesa. But for DRI @@ -926,23 +940,10 @@ _mesa_alloc_dispatch_table(void) * DRI drivers. */ GLint numEntries = MAX2(_glapi_get_dispatch_table_size(), _gloffset_COUNT); - struct _glapi_table *table; - - table = malloc(numEntries * sizeof(_glapi_proc)); - if (table) { - _glapi_proc *entry = (_glapi_proc *) table; - GLint i; - for (i = 0; i < numEntries; i++) { -#if defined(_WIN32) - /* FIXME: This will not generate an error, but at least it won't - * corrupt the stack like _mesa_generic_nop does. */ - entry[i] = __glapi_noop_table[i]; -#else - entry[i] = (_glapi_proc) _mesa_generic_nop; -#endif - } + struct _glapi_table *table = _glapi_new_nop_table(numEntries); #if defined(_WIN32) + if (table) { /* This is a special case for Windows in the event that * wglGetProcAddress is called between glBegin/End(). * @@ -960,8 +961,11 @@ _mesa_alloc_dispatch_table(void) * assertion passes and the test continues. */ SET_Flush(table, nop_glFlush); -#endif } +#endif + + _glapi_set_nop_handler(nop_handler); + return table; } @@ -997,7 +1001,7 @@ create_beginend_table(const struct gl_context *ctx) { struct _glapi_table *table; - table = _mesa_alloc_dispatch_table(); + table = alloc_dispatch_table(); if (!table) return NULL; @@ -1136,7 +1140,7 @@ _mesa_initialize_context(struct gl_context *ctx, goto fail; /* setup the API dispatch tables with all nop functions */ - ctx->OutsideBeginEnd = _mesa_alloc_dispatch_table(); + ctx->OutsideBeginEnd = alloc_dispatch_table(); if (!ctx->OutsideBeginEnd) goto fail; ctx->Exec = ctx->OutsideBeginEnd; @@ -1163,7 +1167,7 @@ _mesa_initialize_context(struct gl_context *ctx, switch (ctx->API) { case API_OPENGL_COMPAT: ctx->BeginEnd = create_beginend_table(ctx); - ctx->Save = _mesa_alloc_dispatch_table(); + ctx->Save = alloc_dispatch_table(); if (!ctx->BeginEnd || !ctx->Save) goto fail; diff --git a/mesalib/src/mesa/main/context.h b/mesalib/src/mesa/main/context.h index d5650877e..1cd89a84a 100644 --- a/mesalib/src/mesa/main/context.h +++ b/mesalib/src/mesa/main/context.h @@ -175,9 +175,6 @@ _mesa_finish(struct gl_context *ctx); extern void _mesa_flush(struct gl_context *ctx); -extern int -_mesa_generic_nop(void); - extern void GLAPIENTRY _mesa_Finish( void ); diff --git a/mesalib/src/mesa/main/copyimage.c b/mesalib/src/mesa/main/copyimage.c index 455929dc2..fd22f2889 100644 --- a/mesalib/src/mesa/main/copyimage.c +++ b/mesalib/src/mesa/main/copyimage.c @@ -33,6 +33,12 @@ #include "texobj.h" #include "fbobject.h" #include "textureview.h" +#include "glformats.h" + +enum mesa_block_class { + BLOCK_CLASS_128_BITS, + BLOCK_CLASS_64_BITS +}; static bool prepare_target(struct gl_context *ctx, GLuint name, GLenum *target, int level, @@ -253,6 +259,124 @@ check_region_bounds(struct gl_context *ctx, struct gl_texture_image *tex_image, return true; } +static bool +compressed_format_compatible(struct gl_context *ctx, + GLenum compressedFormat, GLenum otherFormat) +{ + enum mesa_block_class compressedClass, otherClass; + + /* Two view-incompatible compressed formats are never compatible. */ + if (_mesa_is_compressed_format(ctx, otherFormat)) { + return false; + } + + /* + * From ARB_copy_image spec: + * Table 4.X.1 (Compatible internal formats for copying between + * compressed and uncompressed internal formats) + * --------------------------------------------------------------------- + * | Texel / | Uncompressed | | + * | Block | internal format | Compressed internal format | + * | size | | | + * --------------------------------------------------------------------- + * | 128-bit | RGBA32UI, | COMPRESSED_RGBA_S3TC_DXT3_EXT, | + * | | RGBA32I, | COMPRESSED_SRGB_ALPHA_S3TC_DXT3_EXT,| + * | | RGBA32F | COMPRESSED_RGBA_S3TC_DXT5_EXT, | + * | | | COMPRESSED_SRGB_ALPHA_S3TC_DXT5_EXT,| + * | | | COMPRESSED_RG_RGTC2, | + * | | | COMPRESSED_SIGNED_RG_RGTC2, | + * | | | COMPRESSED_RGBA_BPTC_UNORM, | + * | | | COMPRESSED_SRGB_ALPHA_BPTC_UNORM, | + * | | | COMPRESSED_RGB_BPTC_SIGNED_FLOAT, | + * | | | COMPRESSED_RGB_BPTC_UNSIGNED_FLOAT | + * --------------------------------------------------------------------- + * | 64-bit | RGBA16F, RG32F, | COMPRESSED_RGB_S3TC_DXT1_EXT, | + * | | RGBA16UI, RG32UI, | COMPRESSED_SRGB_S3TC_DXT1_EXT, | + * | | RGBA16I, RG32I, | COMPRESSED_RGBA_S3TC_DXT1_EXT, | + * | | RGBA16, | COMPRESSED_SRGB_ALPHA_S3TC_DXT1_EXT,| + * | | RGBA16_SNORM | COMPRESSED_RED_RGTC1, | + * | | | COMPRESSED_SIGNED_RED_RGTC1 | + * --------------------------------------------------------------------- + */ + + switch (compressedFormat) { + case GL_COMPRESSED_RGBA_S3TC_DXT3_EXT: + case GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT3_EXT: + case GL_COMPRESSED_RGBA_S3TC_DXT5_EXT: + case GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT5_EXT: + case GL_COMPRESSED_RG_RGTC2: + case GL_COMPRESSED_SIGNED_RG_RGTC2: + case GL_COMPRESSED_RGBA_BPTC_UNORM: + case GL_COMPRESSED_SRGB_ALPHA_BPTC_UNORM: + case GL_COMPRESSED_RGB_BPTC_SIGNED_FLOAT: + case GL_COMPRESSED_RGB_BPTC_UNSIGNED_FLOAT: + compressedClass = BLOCK_CLASS_128_BITS; + break; + case GL_COMPRESSED_RGB_S3TC_DXT1_EXT: + case GL_COMPRESSED_SRGB_S3TC_DXT1_EXT: + case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT: + case GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT1_EXT: + case GL_COMPRESSED_RED_RGTC1: + case GL_COMPRESSED_SIGNED_RED_RGTC1: + compressedClass = BLOCK_CLASS_64_BITS; + break; + default: + return false; + } + + switch (otherFormat) { + case GL_RGBA32UI: + case GL_RGBA32I: + case GL_RGBA32F: + otherClass = BLOCK_CLASS_128_BITS; + break; + case GL_RGBA16F: + case GL_RG32F: + case GL_RGBA16UI: + case GL_RG32UI: + case GL_RGBA16I: + case GL_RG32I: + case GL_RGBA16: + case GL_RGBA16_SNORM: + otherClass = BLOCK_CLASS_64_BITS; + break; + default: + return false; + } + + return compressedClass == otherClass; +} + +static bool +copy_format_compatible(struct gl_context *ctx, + GLenum srcFormat, GLenum dstFormat) +{ + /* + * From ARB_copy_image spec: + * For the purposes of CopyImageSubData, two internal formats + * are considered compatible if any of the following conditions are + * met: + * * the formats are the same, + * * the formats are considered compatible according to the + * compatibility rules used for texture views as defined in + * section 3.9.X. In particular, if both internal formats are listed + * in the same entry of Table 3.X.2, they are considered compatible, or + * * one format is compressed and the other is uncompressed and + * Table 4.X.1 lists the two formats in the same row. + */ + + if (_mesa_texture_view_compatible_format(ctx, srcFormat, dstFormat)) { + /* Also checks if formats are equal. */ + return true; + } else if (_mesa_is_compressed_format(ctx, srcFormat)) { + return compressed_format_compatible(ctx, srcFormat, dstFormat); + } else if (_mesa_is_compressed_format(ctx, dstFormat)) { + return compressed_format_compatible(ctx, dstFormat, srcFormat); + } + + return false; +} + void GLAPIENTRY _mesa_CopyImageSubData(GLuint srcName, GLenum srcTarget, GLint srcLevel, GLint srcX, GLint srcY, GLint srcZ, @@ -265,7 +389,7 @@ _mesa_CopyImageSubData(GLuint srcName, GLenum srcTarget, GLint srcLevel, struct gl_texture_object *srcTexObj, *dstTexObj; struct gl_texture_image *srcTexImage, *dstTexImage; GLuint src_bw, src_bh, dst_bw, dst_bh; - int i, srcNewZ, dstNewZ, Bpt; + int i, srcNewZ, dstNewZ; if (MESA_VERBOSE & VERBOSE_API) _mesa_debug(ctx, "glCopyImageSubData(%u, %s, %d, %d, %d, %d, " @@ -306,15 +430,6 @@ _mesa_CopyImageSubData(GLuint srcName, GLenum srcTarget, GLint srcLevel, goto cleanup; } - /* Very simple sanity check. This is sufficient if one of the textures - * is compressed. */ - Bpt = _mesa_get_format_bytes(srcTexImage->TexFormat); - if (_mesa_get_format_bytes(dstTexImage->TexFormat) != Bpt) { - _mesa_error(ctx, GL_INVALID_VALUE, - "glCopyImageSubData(internalFormat mismatch)"); - goto cleanup; - } - if (!check_region_bounds(ctx, srcTexImage, srcX, srcY, srcZ, srcWidth, srcHeight, srcDepth, "src")) goto cleanup; @@ -324,17 +439,11 @@ _mesa_CopyImageSubData(GLuint srcName, GLenum srcTarget, GLint srcLevel, (srcHeight / src_bh) * dst_bh, srcDepth, "dst")) goto cleanup; - if (_mesa_is_format_compressed(srcTexImage->TexFormat)) { - /* XXX: Technically, we should probaby do some more specific checking - * here. However, this should be sufficient for all compressed - * formats that mesa supports since it is a direct memory copy. - */ - } else if (_mesa_is_format_compressed(dstTexImage->TexFormat)) { - } else if (_mesa_texture_view_compatible_format(ctx, - srcTexImage->InternalFormat, - dstTexImage->InternalFormat)) { - } else { - return; /* Error logged by _mesa_texture_view_compatible_format */ + if (!copy_format_compatible(ctx, srcTexImage->InternalFormat, + dstTexImage->InternalFormat)) { + _mesa_error(ctx, GL_INVALID_OPERATION, + "glCopyImageSubData(internalFormat mismatch)"); + goto cleanup; } for (i = 0; i < srcDepth; ++i) { diff --git a/mesalib/src/mesa/main/formats.c b/mesalib/src/mesa/main/formats.c index 422c9dc46..2bc8bcad9 100644 --- a/mesalib/src/mesa/main/formats.c +++ b/mesalib/src/mesa/main/formats.c @@ -388,7 +388,7 @@ array_formats_equal(const void *a, const void *b) } static void -format_array_format_table_init() +format_array_format_table_init(void) { const struct gl_format_info *info; mesa_array_format array_format; diff --git a/mesalib/src/mesa/main/imports.c b/mesalib/src/mesa/main/imports.c index a7ffe2296..68c731657 100644 --- a/mesalib/src/mesa/main/imports.c +++ b/mesalib/src/mesa/main/imports.c @@ -45,6 +45,7 @@ #include <stdio.h> #include <stdarg.h> #include "c99_math.h" +#include "util/rounding.h" /* for _mesa_roundeven */ #include "imports.h" #include "context.h" #include "mtypes.h" @@ -307,26 +308,6 @@ _mesa_bitcount_64(uint64_t n) #endif -/* Using C99 rounding functions for roundToEven() implementation is - * difficult, because round(), rint, and nearbyint() are affected by - * fesetenv(), which the application may have done for its own - * purposes. Mesa's IROUND macro is close to what we want, but it - * rounds away from 0 on n + 0.5. - */ -int -_mesa_round_to_even(float val) -{ - int rounded = IROUND(val); - - if (val - floor(val) == 0.5) { - if (rounded % 2 != 0) - rounded += val > 0 ? -1 : 1; - } - - return rounded; -} - - /** * Convert a 4-byte float to a 2-byte half float. * @@ -388,7 +369,7 @@ _mesa_float_to_half(float val) * or normal. */ e = 0; - m = _mesa_round_to_even((1 << 24) * fabsf(fi.f)); + m = (int) _mesa_roundevenf((1 << 24) * fabsf(fi.f)); } else if (new_exp > 15) { /* map this value to infinity */ @@ -402,7 +383,7 @@ _mesa_float_to_half(float val) * either normal or infinite. */ e = new_exp + 15; - m = _mesa_round_to_even(flt_m / (float) (1 << 13)); + m = (int) _mesa_roundevenf(flt_m / (float) (1 << 13)); } } @@ -481,24 +462,6 @@ _mesa_half_to_float(GLhalfARB val) /** \name String */ /*@{*/ -/** - * Implemented using malloc() and strcpy. - * Note that NULL is handled accordingly. - */ -char * -_mesa_strdup( const char *s ) -{ - if (s) { - size_t l = strlen(s); - char *s2 = malloc(l + 1); - if (s2) - strcpy(s2, s); - return s2; - } - else { - return NULL; - } -} /** Compute simple checksum/hash for a string */ unsigned int diff --git a/mesalib/src/mesa/main/imports.h b/mesalib/src/mesa/main/imports.h index c211b1555..8877966ec 100755 --- a/mesalib/src/mesa/main/imports.h +++ b/mesalib/src/mesa/main/imports.h @@ -432,9 +432,6 @@ _mesa_fls(unsigned int n) #endif } -extern int -_mesa_round_to_even(float val); - extern GLhalfARB _mesa_float_to_half(float f); @@ -447,9 +444,6 @@ _mesa_half_is_negative(GLhalfARB h) return h & 0x8000; } -extern char * -_mesa_strdup( const char *s ); - extern unsigned int _mesa_str_checksum(const char *str); diff --git a/mesalib/src/mesa/main/mtypes.h b/mesalib/src/mesa/main/mtypes.h index efeee8bff..8e1dba6f0 100644 --- a/mesalib/src/mesa/main/mtypes.h +++ b/mesalib/src/mesa/main/mtypes.h @@ -693,15 +693,16 @@ struct gl_colorbuffer_attrib * \name Logic op */ /*@{*/ - GLenum LogicOp; /**< Logic operator */ GLboolean IndexLogicOpEnabled; /**< Color index logic op enabled flag */ GLboolean ColorLogicOpEnabled; /**< RGBA logic op enabled flag */ + GLenum LogicOp; /**< Logic operator */ + /*@}*/ GLboolean DitherFlag; /**< Dither enable flag */ - GLenum ClampFragmentColor; /**< GL_TRUE, GL_FALSE or GL_FIXED_ONLY_ARB */ GLboolean _ClampFragmentColor; /** < with GL_FIXED_ONLY_ARB resolved */ + GLenum ClampFragmentColor; /**< GL_TRUE, GL_FALSE or GL_FIXED_ONLY_ARB */ GLenum ClampReadColor; /**< GL_TRUE, GL_FALSE or GL_FIXED_ONLY_ARB */ GLboolean sRGBEnabled; /**< Framebuffer sRGB blending/updating requested */ @@ -799,6 +800,7 @@ struct gl_eval_attrib struct gl_fog_attrib { GLboolean Enabled; /**< Fog enabled flag */ + GLboolean ColorSumEnabled; GLfloat ColorUnclamped[4]; /**< Fog color */ GLfloat Color[4]; /**< Fog color */ GLfloat Density; /**< Density >= 0.0 */ @@ -806,7 +808,6 @@ struct gl_fog_attrib GLfloat End; /**< End distance in eye coords */ GLfloat Index; /**< Fog index */ GLenum Mode; /**< Fog mode */ - GLboolean ColorSumEnabled; GLenum FogCoordinateSource; /**< GL_EXT_fog_coord */ GLfloat _Scale; /**< (End == Start) ? 1.0 : 1.0 / (End - Start) */ GLenum FogDistanceMode; /**< GL_NV_fog_distance */ @@ -846,16 +847,17 @@ struct gl_light_attrib struct gl_material Material; GLboolean Enabled; /**< Lighting enabled flag */ + GLboolean ColorMaterialEnabled; + GLenum ShadeModel; /**< GL_FLAT or GL_SMOOTH */ GLenum ProvokingVertex; /**< GL_EXT_provoking_vertex */ GLenum ColorMaterialFace; /**< GL_FRONT, BACK or FRONT_AND_BACK */ GLenum ColorMaterialMode; /**< GL_AMBIENT, GL_DIFFUSE, etc */ GLbitfield _ColorMaterialBitmask; /**< bitmask formed from Face and Mode */ - GLboolean ColorMaterialEnabled; - GLenum ClampVertexColor; /**< GL_TRUE, GL_FALSE, GL_FIXED_ONLY */ - GLboolean _ClampVertexColor; - struct gl_light EnabledList; /**< List sentinel */ + + GLboolean _ClampVertexColor; + GLenum ClampVertexColor; /**< GL_TRUE, GL_FALSE, GL_FIXED_ONLY */ /** * Derived state for optimizations: @@ -863,6 +865,8 @@ struct gl_light_attrib /*@{*/ GLboolean _NeedEyeCoords; GLboolean _NeedVertices; /**< Use fast shader? */ + struct gl_light EnabledList; /**< List sentinel */ + GLfloat _BaseColor[2][3]; /*@}*/ }; @@ -900,13 +904,15 @@ struct gl_multisample_attrib GLboolean SampleAlphaToCoverage; GLboolean SampleAlphaToOne; GLboolean SampleCoverage; - GLfloat SampleCoverageValue; GLboolean SampleCoverageInvert; GLboolean SampleShading; - GLfloat MinSampleShadingValue; /* ARB_texture_multisample / GL3.2 additions */ GLboolean SampleMask; + + GLfloat SampleCoverageValue; + GLfloat MinSampleShadingValue; + /** The GL spec defines this as an array but >32x MSAA is madness */ GLbitfield SampleMaskValue; }; @@ -977,11 +983,11 @@ struct gl_pixel_attrib */ struct gl_point_attrib { - GLboolean SmoothFlag; /**< True if GL_POINT_SMOOTH is enabled */ GLfloat Size; /**< User-specified point size */ GLfloat Params[3]; /**< GL_EXT_point_parameters */ GLfloat MinSize, MaxSize; /**< GL_EXT_point_parameters */ GLfloat Threshold; /**< GL_EXT_point_parameters */ + GLboolean SmoothFlag; /**< True if GL_POINT_SMOOTH is enabled */ GLboolean _Attenuated; /**< True if Params != [1, 0, 0] */ GLboolean PointSprite; /**< GL_NV/ARB_point_sprite */ GLboolean CoordReplace[MAX_TEXTURE_COORD_UNITS]; /**< GL_ARB_point_sprite*/ @@ -1347,6 +1353,9 @@ struct gl_texture_unit GLfloat LodBias; /**< for biasing mipmap levels */ + /** Texture targets that have a non-default texture bound */ + GLbitfield _BoundTextures; + /** Current sampler object (GL_ARB_sampler_objects) */ struct gl_sampler_object *Sampler; @@ -1373,8 +1382,6 @@ struct gl_texture_unit /** Points to highest priority, complete and enabled texture object */ struct gl_texture_object *_Current; - /** Texture targets that have a non-default texture bound */ - GLbitfield _BoundTextures; }; @@ -1384,16 +1391,15 @@ struct gl_texture_unit struct gl_texture_attrib { GLuint CurrentUnit; /**< GL_ACTIVE_TEXTURE */ - struct gl_texture_unit Unit[MAX_COMBINED_TEXTURE_IMAGE_UNITS]; + + /** GL_ARB_seamless_cubemap */ + GLboolean CubeMapSeamless; struct gl_texture_object *ProxyTex[NUM_TEXTURE_TARGETS]; /** GL_ARB_texture_buffer_object */ struct gl_buffer_object *BufferObject; - /** GL_ARB_seamless_cubemap */ - GLboolean CubeMapSeamless; - /** Texture coord units/sets used for fragment texturing */ GLbitfield _EnabledCoordUnits; @@ -1411,6 +1417,8 @@ struct gl_texture_attrib /** Largest index + 1 of texture units that have had any CurrentTex set. */ GLint NumCurrentTexUsed; + + struct gl_texture_unit Unit[MAX_COMBINED_TEXTURE_IMAGE_UNITS]; }; @@ -1536,12 +1544,12 @@ struct gl_client_array GLenum Format; /**< default: GL_RGBA, but may be GL_BGRA */ GLsizei Stride; /**< user-specified stride */ GLsizei StrideB; /**< actual stride in bytes */ + GLuint _ElementSize; /**< size of each element in bytes */ const GLubyte *Ptr; /**< Points to array data */ GLboolean Enabled; /**< Enabled flag is a boolean */ GLboolean Normalized; /**< GL_ARB_vertex_program */ GLboolean Integer; /**< Integer-valued? */ GLuint InstanceDivisor; /**< GL_ARB_instanced_arrays */ - GLuint _ElementSize; /**< size of each element in bytes */ struct gl_buffer_object *BufferObj;/**< GL_ARB_vertex_buffer_object */ }; @@ -1600,9 +1608,11 @@ struct gl_vertex_array_object { /** Name of the VAO as received from glGenVertexArray. */ GLuint Name; - GLchar *Label; /**< GL_KHR_debug */ GLint RefCount; + + GLchar *Label; /**< GL_KHR_debug */ + mtx_t Mutex; /** @@ -1707,6 +1717,9 @@ struct gl_array_attrib GLuint RestartIndex; /*@}*/ + /** One of the DRAW_xxx flags, not consumed by drivers */ + gl_draw_method DrawMethod; + /* GL_ARB_vertex_buffer_object */ struct gl_buffer_object *ArrayBufferObj; @@ -1716,9 +1729,6 @@ struct gl_array_attrib */ const struct gl_client_array **_DrawArrays; /**< 0..VERT_ATTRIB_MAX-1 */ - /** One of the DRAW_xxx flags, not consumed by drivers */ - gl_draw_method DrawMethod; - /** Legal array datatypes and the API for which they have been computed */ GLbitfield LegalTypesMask; gl_api LegalTypesMaskAPI; @@ -1880,8 +1890,8 @@ struct gl_transform_feedback_info struct gl_transform_feedback_object { GLuint Name; /**< AKA the object ID */ - GLchar *Label; /**< GL_KHR_debug */ GLint RefCount; + GLchar *Label; /**< GL_KHR_debug */ GLboolean Active; /**< Is transform feedback enabled? */ GLboolean Paused; /**< Is transform feedback paused? */ GLboolean EndedAnytime; /**< Has EndTransformFeedback been called @@ -1889,14 +1899,6 @@ struct gl_transform_feedback_object GLboolean EverBound; /**< Has this object been bound? */ /** - * The shader program active when BeginTransformFeedback() was called. - * When active and unpaused, this equals ctx->Shader.CurrentProgram[stage], - * where stage is the pipeline stage that is the source of data for - * transform feedback. - */ - struct gl_shader_program *shader_program; - - /** * GLES: if Active is true, remaining number of primitives which can be * rendered without overflow. This is necessary to track because GLES * requires us to generate INVALID_OPERATION if a call to glDrawArrays or @@ -1907,6 +1909,14 @@ struct gl_transform_feedback_object */ unsigned GlesRemainingPrims; + /** + * The shader program active when BeginTransformFeedback() was called. + * When active and unpaused, this equals ctx->Shader.CurrentProgram[stage], + * where stage is the pipeline stage that is the source of data for + * transform feedback. + */ + struct gl_shader_program *shader_program; + /** The feedback buffers */ GLuint BufferNames[MAX_FEEDBACK_BUFFERS]; struct gl_buffer_object *Buffers[MAX_FEEDBACK_BUFFERS]; @@ -2229,8 +2239,9 @@ enum gl_frag_depth_layout struct gl_program { GLuint Id; - GLubyte *String; /**< Null-terminated program text */ GLint RefCount; + GLubyte *String; /**< Null-terminated program text */ + GLenum Target; /**< GL_VERTEX/FRAGMENT_PROGRAM_ARB, GL_GEOMETRY_PROGRAM_NV */ GLenum Format; /**< String encoding format */ @@ -2533,18 +2544,20 @@ struct gl_shader GLenum Type; gl_shader_stage Stage; GLuint Name; /**< AKA the handle */ - GLchar *Label; /**< GL_KHR_debug */ GLint RefCount; /**< Reference count */ + GLchar *Label; /**< GL_KHR_debug */ GLboolean DeletePending; GLboolean CompileStatus; - const GLchar *Source; /**< Source code string */ + bool IsES; /**< True if this shader uses GLSL ES */ + GLuint SourceChecksum; /**< for debug/logging purposes */ + const GLchar *Source; /**< Source code string */ + struct gl_program *Program; /**< Post-compile assembly code */ GLchar *InfoLog; struct gl_sl_pragmas Pragmas; unsigned Version; /**< GLSL version used for linking */ - GLboolean IsES; /**< True if this shader uses GLSL ES */ /** * \name Sampler tracking @@ -2588,8 +2601,8 @@ struct gl_shader * * These fields are only set post-linking. */ - struct gl_uniform_block *UniformBlocks; unsigned NumUniformBlocks; + struct gl_uniform_block *UniformBlocks; struct exec_list *ir; struct glsl_symbol_table *symbols; @@ -2879,8 +2892,8 @@ struct gl_shader_program */ unsigned LastClipDistanceArraySize; - struct gl_uniform_block *UniformBlocks; unsigned NumUniformBlocks; + struct gl_uniform_block *UniformBlocks; /** * Indices into the _LinkedShaders's UniformBlocks[] array for each stage @@ -2911,7 +2924,7 @@ struct gl_shader_program GLchar *InfoLog; unsigned Version; /**< GLSL version used for linking */ - GLboolean IsES; /**< True if this program uses GLSL ES */ + bool IsES; /**< True if this program uses GLSL ES */ /** * Per-stage shaders resulting from the first stage of linking. @@ -3036,7 +3049,7 @@ struct gl_shader_compiler_options struct gl_sl_pragmas DefaultPragmas; /**< Default #pragma settings */ - struct nir_shader_compiler_options *NirOptions; + const struct nir_shader_compiler_options *NirOptions; }; @@ -3265,9 +3278,10 @@ struct gl_framebuffer * polygon face orientation, and polygon stipple will have to be inverted. */ GLuint Name; + GLint RefCount; + GLchar *Label; /**< GL_KHR_debug */ - GLint RefCount; GLboolean DeletePending; /** @@ -3301,6 +3315,13 @@ struct gl_framebuffer GLboolean _AllColorBuffersFixedPoint; /* no integer, no float */ GLboolean _HasSNormOrFloatColorBuffer; + /** + * The maximum number of layers in the framebuffer, or 0 if the framebuffer + * is not layered. For cube maps and cube map arrays, each cube face + * counts as a layer. + */ + GLuint MaxNumLayers; + /** Array of all renderbuffer attachments, indexed by BUFFER_* tokens. */ struct gl_renderbuffer_attachment Attachment[BUFFER_COUNT]; @@ -3317,13 +3338,6 @@ struct gl_framebuffer struct gl_renderbuffer *_ColorDrawBuffers[MAX_DRAW_BUFFERS]; struct gl_renderbuffer *_ColorReadBuffer; - /** - * The maximum number of layers in the framebuffer, or 0 if the framebuffer - * is not layered. For cube maps and cube map arrays, each cube face - * counts as a layer. - */ - GLuint MaxNumLayers; - /** Delete this framebuffer */ void (*Delete)(struct gl_framebuffer *fb); }; @@ -4161,6 +4175,13 @@ struct gl_image_unit GLboolean Layered; /** + * GL_TRUE if the state of this image unit is valid and access from + * the shader is allowed. Otherwise loads from this unit should + * return zero and stores should have no effect. + */ + GLboolean _Valid; + + /** * Layer of the texture object bound to this unit, or zero if the * whole level is bound. */ @@ -4184,12 +4205,6 @@ struct gl_image_unit */ mesa_format _ActualFormat; - /** - * GL_TRUE if the state of this image unit is valid and access from - * the shader is allowed. Otherwise loads from this unit should - * return zero and stores should have no effect. - */ - GLboolean _Valid; }; /** diff --git a/mesalib/src/mesa/main/objectlabel.c b/mesalib/src/mesa/main/objectlabel.c index 78df96b9b..aecb5b1fa 100644 --- a/mesalib/src/mesa/main/objectlabel.c +++ b/mesalib/src/mesa/main/objectlabel.c @@ -76,7 +76,7 @@ set_label(struct gl_context *ctx, char **labelPtr, const char *label, MAX_LABEL_LENGTH); /* null-terminated string */ - *labelPtr = _mesa_strdup(label); + *labelPtr = strdup(label); } } } diff --git a/mesalib/src/mesa/main/pbo.c b/mesalib/src/mesa/main/pbo.c index 5c906ed74..0c1602532 100644 --- a/mesalib/src/mesa/main/pbo.c +++ b/mesalib/src/mesa/main/pbo.c @@ -80,7 +80,7 @@ _mesa_validate_pbo_access(GLuint dimensions, */ if (!_mesa_is_bufferobj(pack->BufferObj)) { offset = 0; - size = clientMemSize; + size = (clientMemSize == INT_MAX) ? UINTPTR_MAX : clientMemSize; } else { offset = (uintptr_t)ptr; size = pack->BufferObj->Size; @@ -164,23 +164,18 @@ _mesa_map_pbo_source(struct gl_context *ctx, return buf; } - /** - * Combine PBO-read validation and mapping. - * If any GL errors are detected, they'll be recorded and NULL returned. + * Perform PBO validation for read operations with uncompressed textures. + * If any GL errors are detected, false is returned, otherwise returns true. * \sa _mesa_validate_pbo_access - * \sa _mesa_map_pbo_source - * A call to this function should have a matching call to - * _mesa_unmap_pbo_source(). */ -const GLvoid * -_mesa_map_validate_pbo_source(struct gl_context *ctx, - GLuint dimensions, - const struct gl_pixelstore_attrib *unpack, - GLsizei width, GLsizei height, GLsizei depth, - GLenum format, GLenum type, - GLsizei clientMemSize, - const GLvoid *ptr, const char *where) +bool +_mesa_validate_pbo_source(struct gl_context *ctx, GLuint dimensions, + const struct gl_pixelstore_attrib *unpack, + GLsizei width, GLsizei height, GLsizei depth, + GLenum format, GLenum type, + GLsizei clientMemSize, + const GLvoid *ptr, const char *where) { assert(dimensions == 1 || dimensions == 2 || dimensions == 3); @@ -188,24 +183,85 @@ _mesa_map_validate_pbo_source(struct gl_context *ctx, format, type, clientMemSize, ptr)) { if (_mesa_is_bufferobj(unpack->BufferObj)) { _mesa_error(ctx, GL_INVALID_OPERATION, - "%s(out of bounds PBO access)", where); + "%s(out of bounds PBO access)", + where); } else { _mesa_error(ctx, GL_INVALID_OPERATION, "%s(out of bounds access: bufSize (%d) is too small)", where, clientMemSize); } - return NULL; + return false; } if (!_mesa_is_bufferobj(unpack->BufferObj)) { /* non-PBO access: no further validation to be done */ - return ptr; + return true; } if (_mesa_check_disallowed_mapping(unpack->BufferObj)) { /* buffer is already mapped - that's an error */ - _mesa_error(ctx, GL_INVALID_OPERATION, "%s(PBO is mapped)", where); - return NULL; + _mesa_error(ctx, GL_INVALID_OPERATION, "%s(PBO is mapped)", + where); + return false; + } + + return true; +} + +/** + * Perform PBO validation for read operations with compressed textures. + * If any GL errors are detected, false is returned, otherwise returns true. + */ +bool +_mesa_validate_pbo_source_compressed(struct gl_context *ctx, GLuint dimensions, + const struct gl_pixelstore_attrib *unpack, + GLsizei imageSize, const GLvoid *pixels, + const char *where) +{ + if (!_mesa_is_bufferobj(unpack->BufferObj)) { + /* not using a PBO */ + return true; + } + + if ((const GLubyte *) pixels + imageSize > + ((const GLubyte *) 0) + unpack->BufferObj->Size) { + /* out of bounds read! */ + _mesa_error(ctx, GL_INVALID_OPERATION, "%s(invalid PBO access)", + where); + return false; + } + + if (_mesa_check_disallowed_mapping(unpack->BufferObj)) { + /* buffer is already mapped - that's an error */ + _mesa_error(ctx, GL_INVALID_OPERATION, "%s(PBO is mapped)", + where); + return false; + } + + return true; +} + +/** + * Perform PBO-read mapping. + * If any GL errors are detected, they'll be recorded and NULL returned. + * \sa _mesa_validate_pbo_source + * \sa _mesa_map_pbo_source + * A call to this function should have a matching call to + * _mesa_unmap_pbo_source(). + */ +const GLvoid * +_mesa_map_validate_pbo_source(struct gl_context *ctx, + GLuint dimensions, + const struct gl_pixelstore_attrib *unpack, + GLsizei width, GLsizei height, GLsizei depth, + GLenum format, GLenum type, + GLsizei clientMemSize, + const GLvoid *ptr, const char *where) +{ + if (!_mesa_validate_pbo_source(ctx, dimensions, unpack, + width, height, depth, format, type, + clientMemSize, ptr, where)) { + return NULL; } ptr = _mesa_map_pbo_source(ctx, unpack, ptr); @@ -381,28 +437,27 @@ _mesa_validate_pbo_compressed_teximage(struct gl_context *ctx, { GLubyte *buf; + if (!_mesa_validate_pbo_source_compressed(ctx, dimensions, packing, + imageSize, pixels, funcName)) { + /* error is already set during validation */ + return NULL; + } + if (!_mesa_is_bufferobj(packing->BufferObj)) { /* not using a PBO - return pointer unchanged */ return pixels; } - if ((const GLubyte *) pixels + imageSize > - ((const GLubyte *) 0) + packing->BufferObj->Size) { - /* out of bounds read! */ - _mesa_error(ctx, GL_INVALID_OPERATION, "%s%uD(invalid PBO access)", - funcName, dimensions); - return NULL; - } buf = (GLubyte*) ctx->Driver.MapBufferRange(ctx, 0, packing->BufferObj->Size, GL_MAP_READ_BIT, packing->BufferObj, MAP_INTERNAL); - if (!buf) { - _mesa_error(ctx, GL_INVALID_OPERATION, "%s%uD(PBO is mapped)", funcName, - dimensions); - return NULL; - } + + /* Validation above already checked that PBO is not mapped, so buffer + * should not be null. + */ + assert(buf); return ADD_POINTERS(buf, pixels); } diff --git a/mesalib/src/mesa/main/pbo.h b/mesalib/src/mesa/main/pbo.h index 9851ef1a1..b3f24e62b 100644 --- a/mesalib/src/mesa/main/pbo.h +++ b/mesalib/src/mesa/main/pbo.h @@ -92,4 +92,18 @@ _mesa_unmap_teximage_pbo(struct gl_context *ctx, const struct gl_pixelstore_attrib *unpack); +extern bool +_mesa_validate_pbo_source(struct gl_context *ctx, GLuint dimensions, + const struct gl_pixelstore_attrib *unpack, + GLsizei width, GLsizei height, GLsizei depth, + GLenum format, GLenum type, + GLsizei clientMemSize, + const GLvoid *ptr, const char *where); + +extern bool +_mesa_validate_pbo_source_compressed(struct gl_context *ctx, GLuint dimensions, + const struct gl_pixelstore_attrib *unpack, + GLsizei imageSize, const GLvoid *ptr, + const char *where); + #endif diff --git a/mesalib/src/mesa/main/querymatrix.c b/mesalib/src/mesa/main/querymatrix.c index ef8517571..18361c929 100644 --- a/mesalib/src/mesa/main/querymatrix.c +++ b/mesalib/src/mesa/main/querymatrix.c @@ -13,7 +13,7 @@ #include <stdlib.h> -#include <math.h> +#include "c99_math.h" #include "glheader.h" #include "querymatrix.h" #include "main/get.h" @@ -37,169 +37,120 @@ #define INT_TO_FIXED(x) ((GLfixed) ((x) << 16)) #define FLOAT_TO_FIXED(x) ((GLfixed) ((x) * 65536.0)) -#if defined(fpclassify) -/* ISO C99 says that fpclassify is a macro. Assume that any implementation - * of fpclassify, whether it's in a C99 compiler or not, will be a macro. - */ -#elif defined(_MSC_VER) -/* Not required on VS2013 and above. */ -/* Oddly, the fpclassify() function doesn't exist in such a form - * on MSVC. This is an implementation using slightly different - * lower-level Windows functions. - */ -#include <float.h> - -enum {FP_NAN, FP_INFINITE, FP_ZERO, FP_SUBNORMAL, FP_NORMAL} -fpclassify(double x) -{ - switch(_fpclass(x)) { - case _FPCLASS_SNAN: /* signaling NaN */ - case _FPCLASS_QNAN: /* quiet NaN */ - return FP_NAN; - case _FPCLASS_NINF: /* negative infinity */ - case _FPCLASS_PINF: /* positive infinity */ - return FP_INFINITE; - case _FPCLASS_NN: /* negative normal */ - case _FPCLASS_PN: /* positive normal */ - return FP_NORMAL; - case _FPCLASS_ND: /* negative denormalized */ - case _FPCLASS_PD: /* positive denormalized */ - return FP_SUBNORMAL; - case _FPCLASS_NZ: /* negative zero */ - case _FPCLASS_PZ: /* positive zero */ - return FP_ZERO; - default: - /* Should never get here; but if we do, this will guarantee - * that the pattern is not treated like a number. - */ - return FP_NAN; - } -} - -#else - -enum {FP_NAN, FP_INFINITE, FP_ZERO, FP_SUBNORMAL, FP_NORMAL} -fpclassify(double x) -{ - /* XXX do something better someday */ - return FP_NORMAL; -} - -#endif -GLbitfield GLAPIENTRY _mesa_QueryMatrixxOES(GLfixed mantissa[16], GLint exponent[16]) +GLbitfield GLAPIENTRY +_mesa_QueryMatrixxOES(GLfixed mantissa[16], GLint exponent[16]) { - GLfloat matrix[16]; - GLint tmp; - GLenum currentMode = GL_FALSE; - GLenum desiredMatrix = GL_FALSE; - /* The bitfield returns 1 for each component that is invalid (i.e. - * NaN or Inf). In case of error, everything is invalid. - */ - GLbitfield rv; - register unsigned int i; - unsigned int bit; - - /* This data structure defines the mapping between the current matrix - * mode and the desired matrix identifier. - */ - static struct { - GLenum currentMode; - GLenum desiredMatrix; - } modes[] = { - {GL_MODELVIEW, GL_MODELVIEW_MATRIX}, - {GL_PROJECTION, GL_PROJECTION_MATRIX}, - {GL_TEXTURE, GL_TEXTURE_MATRIX}, - }; - - /* Call Mesa to get the current matrix in floating-point form. First, - * we have to figure out what the current matrix mode is. - */ - _mesa_GetIntegerv(GL_MATRIX_MODE, &tmp); - currentMode = (GLenum) tmp; - - /* The mode is either GL_FALSE, if for some reason we failed to query - * the mode, or a given mode from the above table. Search for the - * returned mode to get the desired matrix; if we don't find it, - * we can return immediately, as _mesa_GetInteger() will have - * logged the necessary error already. - */ - for (i = 0; i < sizeof(modes)/sizeof(modes[0]); i++) { - if (modes[i].currentMode == currentMode) { - desiredMatrix = modes[i].desiredMatrix; - break; - } - } - if (desiredMatrix == GL_FALSE) { - /* Early error means all values are invalid. */ - return 0xffff; - } - - /* Now pull the matrix itself. */ - _mesa_GetFloatv(desiredMatrix, matrix); - - rv = 0; - for (i = 0, bit = 1; i < 16; i++, bit<<=1) { - float normalizedFraction; - int exp; - - switch (fpclassify(matrix[i])) { - /* A "subnormal" or denormalized number is too small to be - * represented in normal format; but despite that it's a - * valid floating point number. FP_ZERO and FP_NORMAL - * are both valid as well. We should be fine treating - * these three cases as legitimate floating-point numbers. - */ - case FP_SUBNORMAL: - case FP_NORMAL: - case FP_ZERO: - normalizedFraction = (GLfloat)frexp(matrix[i], &exp); - mantissa[i] = FLOAT_TO_FIXED(normalizedFraction); - exponent[i] = (GLint) exp; - break; - - /* If the entry is not-a-number or an infinity, then the - * matrix component is invalid. The invalid flag for - * the component is already set; might as well set the - * other return values to known values. We'll set - * distinct values so that a savvy end user could determine - * whether the matrix component was a NaN or an infinity, - * but this is more useful for debugging than anything else - * since the standard doesn't specify any such magic - * values to return. - */ - case FP_NAN: - mantissa[i] = INT_TO_FIXED(0); - exponent[i] = (GLint) 0; - rv |= bit; - break; - - case FP_INFINITE: - /* Return +/- 1 based on whether it's a positive or - * negative infinity. - */ - if (matrix[i] > 0) { - mantissa[i] = INT_TO_FIXED(1); - } - else { - mantissa[i] = -INT_TO_FIXED(1); - } - exponent[i] = (GLint) 0; - rv |= bit; - break; - - /* We should never get here; but here's a catching case - * in case fpclassify() is returnings something unexpected. - */ - default: - mantissa[i] = INT_TO_FIXED(2); - exponent[i] = (GLint) 0; - rv |= bit; - break; - } - - } /* for each component */ - - /* All done */ - return rv; + GLfloat matrix[16]; + GLint tmp; + GLenum currentMode = GL_FALSE; + GLenum desiredMatrix = GL_FALSE; + /* The bitfield returns 1 for each component that is invalid (i.e. + * NaN or Inf). In case of error, everything is invalid. + */ + GLbitfield rv; + unsigned i, bit; + + /* This data structure defines the mapping between the current matrix + * mode and the desired matrix identifier. + */ + static const struct { + GLenum currentMode; + GLenum desiredMatrix; + } modes[] = { + {GL_MODELVIEW, GL_MODELVIEW_MATRIX}, + {GL_PROJECTION, GL_PROJECTION_MATRIX}, + {GL_TEXTURE, GL_TEXTURE_MATRIX}, + }; + + /* Call Mesa to get the current matrix in floating-point form. First, + * we have to figure out what the current matrix mode is. + */ + _mesa_GetIntegerv(GL_MATRIX_MODE, &tmp); + currentMode = (GLenum) tmp; + + /* The mode is either GL_FALSE, if for some reason we failed to query + * the mode, or a given mode from the above table. Search for the + * returned mode to get the desired matrix; if we don't find it, + * we can return immediately, as _mesa_GetInteger() will have + * logged the necessary error already. + */ + for (i = 0; i < ARRAY_SIZE(modes); i++) { + if (modes[i].currentMode == currentMode) { + desiredMatrix = modes[i].desiredMatrix; + break; + } + } + if (desiredMatrix == GL_FALSE) { + /* Early error means all values are invalid. */ + return 0xffff; + } + + /* Now pull the matrix itself. */ + _mesa_GetFloatv(desiredMatrix, matrix); + + rv = 0; + for (i = 0, bit = 1; i < 16; i++, bit<<=1) { + float normalizedFraction; + int exp; + + switch (fpclassify(matrix[i])) { + case FP_SUBNORMAL: + case FP_NORMAL: + case FP_ZERO: + /* A "subnormal" or denormalized number is too small to be + * represented in normal format; but despite that it's a + * valid floating point number. FP_ZERO and FP_NORMAL + * are both valid as well. We should be fine treating + * these three cases as legitimate floating-point numbers. + */ + normalizedFraction = (GLfloat)frexp(matrix[i], &exp); + mantissa[i] = FLOAT_TO_FIXED(normalizedFraction); + exponent[i] = (GLint) exp; + break; + + case FP_NAN: + /* If the entry is not-a-number or an infinity, then the + * matrix component is invalid. The invalid flag for + * the component is already set; might as well set the + * other return values to known values. We'll set + * distinct values so that a savvy end user could determine + * whether the matrix component was a NaN or an infinity, + * but this is more useful for debugging than anything else + * since the standard doesn't specify any such magic + * values to return. + */ + mantissa[i] = INT_TO_FIXED(0); + exponent[i] = (GLint) 0; + rv |= bit; + break; + + case FP_INFINITE: + /* Return +/- 1 based on whether it's a positive or + * negative infinity. + */ + if (matrix[i] > 0) { + mantissa[i] = INT_TO_FIXED(1); + } + else { + mantissa[i] = -INT_TO_FIXED(1); + } + exponent[i] = (GLint) 0; + rv |= bit; + break; + + default: + /* We should never get here; but here's a catching case + * in case fpclassify() is returnings something unexpected. + */ + mantissa[i] = INT_TO_FIXED(2); + exponent[i] = (GLint) 0; + rv |= bit; + break; + } + + } /* for each component */ + + /* All done */ + return rv; } diff --git a/mesalib/src/mesa/main/scissor.c b/mesalib/src/mesa/main/scissor.c index 83f39e2a0..bc8224c7d 100644 --- a/mesalib/src/mesa/main/scissor.c +++ b/mesalib/src/mesa/main/scissor.c @@ -201,13 +201,13 @@ void GLAPIENTRY _mesa_ScissorIndexed(GLuint index, GLint left, GLint bottom, GLsizei width, GLsizei height) { - ScissorIndexed(index, left, bottom, width, height, "glScissorIndexd"); + ScissorIndexed(index, left, bottom, width, height, "glScissorIndexed"); } void GLAPIENTRY _mesa_ScissorIndexedv(GLuint index, const GLint *v) { - ScissorIndexed(index, v[0], v[1], v[2], v[3], "glScissorIndexdv"); + ScissorIndexed(index, v[0], v[1], v[2], v[3], "glScissorIndexedv"); } /** diff --git a/mesalib/src/mesa/main/shaderapi.c b/mesalib/src/mesa/main/shaderapi.c index 5731d581a..30716f5e3 100644 --- a/mesalib/src/mesa/main/shaderapi.c +++ b/mesalib/src/mesa/main/shaderapi.c @@ -1027,15 +1027,14 @@ _mesa_active_program(struct gl_context *ctx, struct gl_shader_program *shProg, static void -use_shader_program(struct gl_context *ctx, GLenum type, +use_shader_program(struct gl_context *ctx, gl_shader_stage stage, struct gl_shader_program *shProg, struct gl_pipeline_object *shTarget) { struct gl_shader_program **target; - gl_shader_stage stage = _mesa_shader_enum_to_shader_stage(type); target = &shTarget->CurrentProgram[stage]; - if ((shProg == NULL) || (shProg->_LinkedShaders[stage] == NULL)) + if ((shProg != NULL) && (shProg->_LinkedShaders[stage] == NULL)) shProg = NULL; if (*target != shProg) { @@ -1048,17 +1047,17 @@ use_shader_program(struct gl_context *ctx, GLenum type, * it from that binding point as well. This ensures that the correct * semantics of glDeleteProgram are maintained. */ - switch (type) { - case GL_VERTEX_SHADER: + switch (stage) { + case MESA_SHADER_VERTEX: /* Empty for now. */ break; - case GL_GEOMETRY_SHADER_ARB: + case MESA_SHADER_GEOMETRY: /* Empty for now. */ break; - case GL_COMPUTE_SHADER: + case MESA_SHADER_COMPUTE: /* Empty for now. */ break; - case GL_FRAGMENT_SHADER: + case MESA_SHADER_FRAGMENT: if (*target == ctx->_Shader->_CurrentFragmentProgram) { _mesa_reference_shader_program(ctx, &ctx->_Shader->_CurrentFragmentProgram, @@ -1079,10 +1078,9 @@ use_shader_program(struct gl_context *ctx, GLenum type, void _mesa_use_program(struct gl_context *ctx, struct gl_shader_program *shProg) { - use_shader_program(ctx, GL_VERTEX_SHADER, shProg, &ctx->Shader); - use_shader_program(ctx, GL_GEOMETRY_SHADER_ARB, shProg, &ctx->Shader); - use_shader_program(ctx, GL_FRAGMENT_SHADER, shProg, &ctx->Shader); - use_shader_program(ctx, GL_COMPUTE_SHADER, shProg, &ctx->Shader); + int i; + for (i = 0; i < MESA_SHADER_STAGES; i++) + use_shader_program(ctx, i, shProg, &ctx->Shader); _mesa_active_program(ctx, shProg, "glUseProgram"); if (ctx->Driver.UseProgram) @@ -1460,7 +1458,7 @@ read_shader(const char *fname) fclose(f); - shader = _mesa_strdup(buffer); + shader = strdup(buffer); free(buffer); return shader; @@ -1889,7 +1887,8 @@ _mesa_use_shader_program(struct gl_context *ctx, GLenum type, struct gl_shader_program *shProg, struct gl_pipeline_object *shTarget) { - use_shader_program(ctx, type, shProg, shTarget); + gl_shader_stage stage = _mesa_shader_enum_to_shader_stage(type); + use_shader_program(ctx, stage, shProg, shTarget); if (ctx->Driver.UseProgram) ctx->Driver.UseProgram(ctx, shProg); diff --git a/mesalib/src/mesa/main/texgetimage.c b/mesalib/src/mesa/main/texgetimage.c index f975c160e..255d36559 100644 --- a/mesalib/src/mesa/main/texgetimage.c +++ b/mesalib/src/mesa/main/texgetimage.c @@ -1088,48 +1088,9 @@ _mesa_GetTextureImage(GLuint texture, GLint level, GLenum format, /* Must handle special case GL_TEXTURE_CUBE_MAP. */ if (texObj->Target == GL_TEXTURE_CUBE_MAP) { - /* Error checking */ - if (texObj->NumLayers < 6) { - /* Not enough image planes for a cube map. The spec does not say - * what should happen in this case because the user has always - * specified each cube face separately (using - * GL_TEXTURE_CUBE_MAP_POSITIVE_X+i) in previous GL versions. - * This is addressed in Khronos Bug 13223. - */ - _mesa_error(ctx, GL_INVALID_OPERATION, - "glGetTextureImage(insufficient cube map storage)"); - return; - } - - /* - * What do we do if the user created a texture with the following code - * and then called this function with its handle? - * - * GLuint tex; - * glCreateTextures(GL_TEXTURE_CUBE_MAP, 1, &tex); - * glBindTexture(GL_TEXTURE_CUBE_MAP, tex); - * glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_X, 0, ...); - * glTexImage2D(GL_TEXTURE_CUBE_MAP_NEGATIVE_X, 0, ...); - * glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_Y, 0, ...); - * // Note: GL_TEXTURE_CUBE_MAP_NEGATIVE_Y not set, or given the - * // wrong format, or given the wrong size, etc. - * glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_Z, 0, ...); - * glTexImage2D(GL_TEXTURE_CUBE_MAP_NEGATIVE_Z, 0, ...); - * - * A bug has been filed against the spec for this case. In the - * meantime, we will check for cube completeness. - * - * According to Section 8.17 Texture Completeness in the OpenGL 4.5 - * Core Profile spec (30.10.2014): - * "[A] cube map texture is cube complete if the - * following conditions all hold true: The [base level] texture - * images of each of the six cube map faces have identical, positive, - * and square dimensions. The [base level] images were each specified - * with the same internal format." - * - * It seems reasonable to check for cube completeness of an arbitrary - * level here so that the returned data has a consistent format and size - * and therefore fits in the user's buffer. + /* Make sure the texture object is a proper cube. + * (See texturesubimage in teximage.c for details on why this check is + * performed.) */ if (!_mesa_cube_level_complete(texObj, level)) { _mesa_error(ctx, GL_INVALID_OPERATION, @@ -1140,6 +1101,8 @@ _mesa_GetTextureImage(GLuint texture, GLint level, GLenum format, /* Copy each face. */ for (i = 0; i < 6; ++i) { texImage = texObj->Image[i][level]; + assert(texImage); + _mesa_get_texture_image(ctx, texObj, texImage, texObj->Target, level, format, type, bufSize, pixels, true); @@ -1340,13 +1303,21 @@ _mesa_GetCompressedTextureImage(GLuint texture, GLint level, /* Must handle special case GL_TEXTURE_CUBE_MAP. */ if (texObj->Target == GL_TEXTURE_CUBE_MAP) { - assert(texObj->NumLayers >= 6); + + /* Make sure the texture object is a proper cube. + * (See texturesubimage in teximage.c for details on why this check is + * performed.) + */ + if (!_mesa_cube_level_complete(texObj, level)) { + _mesa_error(ctx, GL_INVALID_OPERATION, + "glGetCompressedTextureImage(cube map incomplete)"); + return; + } /* Copy each face. */ for (i = 0; i < 6; ++i) { texImage = texObj->Image[i][level]; - if (!texImage) - return; + assert(texImage); _mesa_get_compressed_texture_image(ctx, texObj, texImage, texObj->Target, level, diff --git a/mesalib/src/mesa/main/teximage.c b/mesalib/src/mesa/main/teximage.c index 611d664b6..8d9d7cfc1 100644 --- a/mesalib/src/mesa/main/teximage.c +++ b/mesalib/src/mesa/main/teximage.c @@ -53,6 +53,7 @@ #include "mtypes.h" #include "glformats.h" #include "texstore.h" +#include "pbo.h" /** @@ -1619,32 +1620,30 @@ error_check_subtexture_dimensions(struct gl_context *ctx, GLuint dims, /* Check size */ if (subWidth < 0) { _mesa_error(ctx, GL_INVALID_VALUE, - "%s%dD(width=%d)", func, dims, subWidth); + "%s(width=%d)", func, subWidth); return GL_TRUE; } if (dims > 1 && subHeight < 0) { _mesa_error(ctx, GL_INVALID_VALUE, - "%s%dD(height=%d)", func, dims, subHeight); + "%s(height=%d)", func, subHeight); return GL_TRUE; } if (dims > 2 && subDepth < 0) { _mesa_error(ctx, GL_INVALID_VALUE, - "%s%dD(depth=%d)", func, dims, subDepth); + "%s(depth=%d)", func, subDepth); return GL_TRUE; } /* check xoffset and width */ if (xoffset < - (GLint) destImage->Border) { - _mesa_error(ctx, GL_INVALID_VALUE, "%s%dD(xoffset)", - func, dims); + _mesa_error(ctx, GL_INVALID_VALUE, "%s(xoffset)", func); return GL_TRUE; } if (xoffset + subWidth > (GLint) destImage->Width) { - _mesa_error(ctx, GL_INVALID_VALUE, "%s%dD(xoffset+width)", - func, dims); + _mesa_error(ctx, GL_INVALID_VALUE, "%s(xoffset+width)", func); return GL_TRUE; } @@ -1652,13 +1651,11 @@ error_check_subtexture_dimensions(struct gl_context *ctx, GLuint dims, if (dims > 1) { GLint yBorder = (target == GL_TEXTURE_1D_ARRAY) ? 0 : destImage->Border; if (yoffset < -yBorder) { - _mesa_error(ctx, GL_INVALID_VALUE, "%s%dD(yoffset)", - func, dims); + _mesa_error(ctx, GL_INVALID_VALUE, "%s(yoffset)", func); return GL_TRUE; } if (yoffset + subHeight > (GLint) destImage->Height) { - _mesa_error(ctx, GL_INVALID_VALUE, "%s%dD(yoffset+height)", - func, dims); + _mesa_error(ctx, GL_INVALID_VALUE, "%s(yoffset+height)", func); return GL_TRUE; } } @@ -1671,7 +1668,7 @@ error_check_subtexture_dimensions(struct gl_context *ctx, GLuint dims, 0 : destImage->Border; if (zoffset < -zBorder) { - _mesa_error(ctx, GL_INVALID_VALUE, "%s3D(zoffset)", func); + _mesa_error(ctx, GL_INVALID_VALUE, "%s(zoffset)", func); return GL_TRUE; } @@ -1679,7 +1676,7 @@ error_check_subtexture_dimensions(struct gl_context *ctx, GLuint dims, if (target == GL_TEXTURE_CUBE_MAP) depth = 6; if (zoffset + subDepth > depth) { - _mesa_error(ctx, GL_INVALID_VALUE, "%s3D(zoffset+depth)", func); + _mesa_error(ctx, GL_INVALID_VALUE, "%s(zoffset+depth)", func); return GL_TRUE; } } @@ -1697,8 +1694,8 @@ error_check_subtexture_dimensions(struct gl_context *ctx, GLuint dims, /* offset must be multiple of block size */ if ((xoffset % bw != 0) || (yoffset % bh != 0)) { _mesa_error(ctx, GL_INVALID_OPERATION, - "%s%dD(xoffset = %d, yoffset = %d)", - func, dims, xoffset, yoffset); + "%s(xoffset = %d, yoffset = %d)", + func, xoffset, yoffset); return GL_TRUE; } @@ -1710,14 +1707,14 @@ error_check_subtexture_dimensions(struct gl_context *ctx, GLuint dims, if ((subWidth % bw != 0) && (xoffset + subWidth != (GLint) destImage->Width)) { _mesa_error(ctx, GL_INVALID_OPERATION, - "%s%dD(width = %d)", func, dims, subWidth); + "%s(width = %d)", func, subWidth); return GL_TRUE; } if ((subHeight % bh != 0) && (yoffset + subHeight != (GLint) destImage->Height)) { _mesa_error(ctx, GL_INVALID_OPERATION, - "%s%dD(height = %d)", func, dims, subHeight); + "%s(height = %d)", func, subHeight); return GL_TRUE; } } @@ -2113,7 +2110,8 @@ texture_error_check( struct gl_context *ctx, GLint level, GLint internalFormat, GLenum format, GLenum type, GLint width, GLint height, - GLint depth, GLint border ) + GLint depth, GLint border, + const GLvoid *pixels ) { GLenum err; @@ -2198,6 +2196,13 @@ texture_error_check( struct gl_context *ctx, return GL_TRUE; } + /* validate the bound PBO, if any */ + if (!_mesa_validate_pbo_source(ctx, dimensions, &ctx->Unpack, + width, height, depth, format, type, + INT_MAX, pixels, "glTexImage")) { + return GL_TRUE; + } + /* make sure internal format and format basically agree */ if (!texture_formats_agree(internalFormat, format)) { _mesa_error(ctx, GL_INVALID_OPERATION, @@ -2294,7 +2299,7 @@ compressed_texture_error_check(struct gl_context *ctx, GLint dimensions, GLenum target, GLint level, GLenum internalFormat, GLsizei width, GLsizei height, GLsizei depth, GLint border, - GLsizei imageSize) + GLsizei imageSize, const GLvoid *data) { const GLint maxLevels = _mesa_max_texture_levels(ctx, target); GLint expectedSize; @@ -2322,6 +2327,13 @@ compressed_texture_error_check(struct gl_context *ctx, GLint dimensions, return GL_TRUE; } + /* validate the bound PBO, if any */ + if (!_mesa_validate_pbo_source_compressed(ctx, dimensions, &ctx->Unpack, + imageSize, data, + "glCompressedTexImage")) { + return GL_TRUE; + } + switch (internalFormat) { case GL_PALETTE4_RGB8_OES: case GL_PALETTE4_RGBA8_OES: @@ -2454,30 +2466,28 @@ texsubimage_error_check(struct gl_context *ctx, GLuint dimensions, GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLint width, GLint height, GLint depth, - GLenum format, GLenum type, bool dsa) + GLenum format, GLenum type, const GLvoid *pixels, + bool dsa, const char *callerName) { struct gl_texture_image *texImage; GLenum err; - const char* suffix = dsa ? "ture" : ""; if (!texObj) { /* must be out of memory */ - _mesa_error(ctx, GL_OUT_OF_MEMORY, "glTex%sSubImage%dD()", - suffix, dimensions); + _mesa_error(ctx, GL_OUT_OF_MEMORY, "%s()", callerName); return GL_TRUE; } /* check target (proxies not allowed) */ if (!legal_texsubimage_target(ctx, dimensions, target, dsa)) { - _mesa_error(ctx, GL_INVALID_ENUM, "glTex%sSubImage%uD(target=%s)", - suffix, dimensions, _mesa_lookup_enum_by_nr(target)); + _mesa_error(ctx, GL_INVALID_ENUM, "%s(target=%s)", + callerName, _mesa_lookup_enum_by_nr(target)); return GL_TRUE; } /* level check */ if (level < 0 || level >= _mesa_max_texture_levels(ctx, target)) { - _mesa_error(ctx, GL_INVALID_VALUE, "glTex%sSubImage%uD(level=%d)", - suffix, dimensions, level); + _mesa_error(ctx, GL_INVALID_VALUE, "%s(level=%d)", callerName, level); return GL_TRUE; } @@ -2489,9 +2499,8 @@ texsubimage_error_check(struct gl_context *ctx, GLuint dimensions, if (_mesa_is_gles(ctx) && !_mesa_is_gles3(ctx)) { err = _mesa_es_error_check_format_and_type(format, type, dimensions); if (err != GL_NO_ERROR) { - _mesa_error(ctx, err, - "glTex%sSubImage%dD(format = %s, type = %s)", - suffix, dimensions, _mesa_lookup_enum_by_nr(format), + _mesa_error(ctx, err, "%s(format = %s, type = %s)", + callerName, _mesa_lookup_enum_by_nr(format), _mesa_lookup_enum_by_nr(type)); return GL_TRUE; } @@ -2500,34 +2509,37 @@ texsubimage_error_check(struct gl_context *ctx, GLuint dimensions, err = _mesa_error_check_format_and_type(ctx, format, type); if (err != GL_NO_ERROR) { _mesa_error(ctx, err, - "glTex%sSubImage%dD(incompatible format = %s, type = %s)", - suffix, dimensions, _mesa_lookup_enum_by_nr(format), + "%s(incompatible format = %s, type = %s)", + callerName, _mesa_lookup_enum_by_nr(format), _mesa_lookup_enum_by_nr(type)); return GL_TRUE; } + /* validate the bound PBO, if any */ + if (!_mesa_validate_pbo_source(ctx, dimensions, &ctx->Unpack, + width, height, depth, format, type, + INT_MAX, pixels, callerName)) { + return GL_TRUE; + } + texImage = _mesa_select_tex_image(texObj, target, level); if (!texImage) { /* non-existant texture level */ - _mesa_error(ctx, GL_INVALID_OPERATION, - "glTex%sSubImage%dD(invalid texture image)", suffix, - dimensions); + _mesa_error(ctx, GL_INVALID_OPERATION, "%s(invalid texture image)", + callerName); return GL_TRUE; } if (error_check_subtexture_dimensions(ctx, dimensions, texImage, xoffset, yoffset, zoffset, - width, height, depth, - dsa ? "glTextureSubImage" : - "glTexSubImage")) { + width, height, depth, callerName)) { return GL_TRUE; } if (_mesa_is_format_compressed(texImage->TexFormat)) { if (compressedteximage_only_format(ctx, texImage->InternalFormat)) { _mesa_error(ctx, GL_INVALID_OPERATION, - "glTex%sSubImage%dD(no compression for format)", - suffix, dimensions); + "%s(no compression for format)", callerName); return GL_TRUE; } } @@ -2537,8 +2549,7 @@ texsubimage_error_check(struct gl_context *ctx, GLuint dimensions, if (_mesa_is_format_integer_color(texImage->TexFormat) != _mesa_is_enum_format_integer(format)) { _mesa_error(ctx, GL_INVALID_OPERATION, - "glTex%sSubImage%dD(integer/non-integer format mismatch)", - suffix, dimensions); + "%s(integer/non-integer format mismatch)", callerName); return GL_TRUE; } } @@ -2815,10 +2826,9 @@ copytexsubimage_error_check(struct gl_context *ctx, GLuint dimensions, const struct gl_texture_object *texObj, GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, - GLint width, GLint height, bool dsa) + GLint width, GLint height, const char *caller) { struct gl_texture_image *texImage; - const char *suffix = dsa ? "ture" : ""; /* Check that the source buffer is complete */ if (_mesa_is_user_fbo(ctx->ReadBuffer)) { @@ -2827,31 +2837,26 @@ copytexsubimage_error_check(struct gl_context *ctx, GLuint dimensions, } if (ctx->ReadBuffer->_Status != GL_FRAMEBUFFER_COMPLETE_EXT) { _mesa_error(ctx, GL_INVALID_FRAMEBUFFER_OPERATION_EXT, - "glCopyTex%sSubImage%dD(invalid readbuffer)", - suffix, dimensions); + "%s(invalid readbuffer)", caller); return GL_TRUE; } if (ctx->ReadBuffer->Visual.samples > 0) { _mesa_error(ctx, GL_INVALID_OPERATION, - "glCopyTex%sSubImage%dD(multisample FBO)", suffix, - dimensions); + "%s(multisample FBO)", caller); return GL_TRUE; } } /* Check level */ if (level < 0 || level >= _mesa_max_texture_levels(ctx, target)) { - _mesa_error(ctx, GL_INVALID_VALUE, - "glCopyTex%sSubImage%dD(level=%d)", suffix, - dimensions, level); + _mesa_error(ctx, GL_INVALID_VALUE, "%s(level=%d)", caller, level); return GL_TRUE; } /* Get dest image pointers */ if (!texObj) { - _mesa_error(ctx, GL_OUT_OF_MEMORY, "glCopyTex%sSubImage%dD()", - suffix, dimensions); + _mesa_error(ctx, GL_OUT_OF_MEMORY, "%s()", caller); return GL_TRUE; } @@ -2859,37 +2864,33 @@ copytexsubimage_error_check(struct gl_context *ctx, GLuint dimensions, if (!texImage) { /* destination image does not exist */ _mesa_error(ctx, GL_INVALID_OPERATION, - "glCopyTex%sSubImage%dD(invalid texture image)", - suffix, dimensions); + "%s(invalid texture image)", caller); return GL_TRUE; } if (error_check_subtexture_dimensions(ctx, dimensions, texImage, xoffset, yoffset, zoffset, - width, height, 1, dsa ? - "glCompressedTextureSubImage" : - "glCompressedTexSubImage")) { + width, height, 1, caller)) { return GL_TRUE; } if (_mesa_is_format_compressed(texImage->TexFormat)) { if (compressedteximage_only_format(ctx, texImage->InternalFormat)) { _mesa_error(ctx, GL_INVALID_OPERATION, - "glCopyTex%sSubImage%dD(no compression for format)", - suffix, dimensions); + "%s(no compression for format)", caller); return GL_TRUE; } } if (texImage->InternalFormat == GL_YCBCR_MESA) { - _mesa_error(ctx, GL_INVALID_OPERATION, "glCopyTex%sSubImage2D", suffix); + _mesa_error(ctx, GL_INVALID_OPERATION, "%s()", caller); return GL_TRUE; } if (!_mesa_source_buffer_exists(ctx, texImage->_BaseFormat)) { _mesa_error(ctx, GL_INVALID_OPERATION, - "glCopyTex%sSubImage%dD(missing readbuffer, format=0x%x)", - suffix, dimensions, texImage->_BaseFormat); + "%s(missing readbuffer, format=0x%x)", caller, + texImage->_BaseFormat); return GL_TRUE; } @@ -2907,8 +2908,7 @@ copytexsubimage_error_check(struct gl_context *ctx, GLuint dimensions, if (_mesa_is_format_integer_color(rb->Format) != _mesa_is_format_integer_color(texImage->TexFormat)) { _mesa_error(ctx, GL_INVALID_OPERATION, - "glCopyTex%sSubImage%dD(integer vs non-integer)", - suffix, dimensions); + "%s(integer vs non-integer)", caller); return GL_TRUE; } } @@ -3218,12 +3218,13 @@ teximage(struct gl_context *ctx, GLboolean compressed, GLuint dims, if (compressed_texture_error_check(ctx, dims, target, level, internalFormat, width, height, depth, - border, imageSize)) + border, imageSize, pixels)) return; } else { if (texture_error_check(ctx, dims, target, level, internalFormat, - format, type, width, height, depth, border)) + format, type, width, height, depth, border, + pixels)) return; } @@ -3562,7 +3563,8 @@ static void texsubimage(struct gl_context *ctx, GLuint dims, GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, - GLenum format, GLenum type, const GLvoid *pixels) + GLenum format, GLenum type, const GLvoid *pixels, + const char *callerName) { struct gl_texture_object *texObj; struct gl_texture_image *texImage; @@ -3573,7 +3575,8 @@ texsubimage(struct gl_context *ctx, GLuint dims, GLenum target, GLint level, if (texsubimage_error_check(ctx, dims, texObj, target, level, xoffset, yoffset, zoffset, - width, height, depth, format, type, false)) { + width, height, depth, format, type, + pixels, false, callerName)) { return; /* error was detected */ } @@ -3603,7 +3606,8 @@ texturesubimage(struct gl_context *ctx, GLuint dims, GLuint texture, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, - GLenum format, GLenum type, const GLvoid *pixels) + GLenum format, GLenum type, const GLvoid *pixels, + const char *callerName) { struct gl_texture_object *texObj; struct gl_texture_image *texImage; @@ -3627,7 +3631,8 @@ texturesubimage(struct gl_context *ctx, GLuint dims, if (texsubimage_error_check(ctx, dims, texObj, texObj->Target, level, xoffset, yoffset, zoffset, - width, height, depth, format, type, true)) { + width, height, depth, format, type, + pixels, true, callerName)) { return; /* error was detected */ } @@ -3636,20 +3641,6 @@ texturesubimage(struct gl_context *ctx, GLuint dims, if (texObj->Target == GL_TEXTURE_CUBE_MAP) { GLint rowStride; - /* Error checking */ - if (texObj->NumLayers < 6) { - /* Not enough image planes for a cube map. The spec does not say - * what should happen in this case because the user has always - * specified each cube face separately (using - * GL_TEXTURE_CUBE_MAP_POSITIVE_X+i) in previous GL versions. - * This is addressed in Khronos Bug 13223. - */ - _mesa_error(ctx, GL_INVALID_OPERATION, - "glTextureSubImage%uD(insufficient cube map storage)", - dims); - return; - } - /* * What do we do if the user created a texture with the following code * and then called this function with its handle? @@ -3691,6 +3682,8 @@ texturesubimage(struct gl_context *ctx, GLuint dims, /* Copy in each face. */ for (i = 0; i < 6; ++i) { texImage = texObj->Image[i][level]; + assert(texImage); + _mesa_texture_sub_image(ctx, 3, texObj, texImage, texObj->Target, level, xoffset, yoffset, zoffset, width, height, 1, format, @@ -3700,8 +3693,7 @@ texturesubimage(struct gl_context *ctx, GLuint dims, } else { texImage = _mesa_select_tex_image(texObj, texObj->Target, level); - if (!texImage) - return; + assert(texImage); _mesa_texture_sub_image(ctx, dims, texObj, texImage, texObj->Target, level, xoffset, yoffset, zoffset, @@ -3721,7 +3713,7 @@ _mesa_TexSubImage1D( GLenum target, GLint level, texsubimage(ctx, 1, target, level, xoffset, 0, 0, width, 1, 1, - format, type, pixels); + format, type, pixels, "glTexSubImage1D"); } @@ -3736,7 +3728,7 @@ _mesa_TexSubImage2D( GLenum target, GLint level, texsubimage(ctx, 2, target, level, xoffset, yoffset, 0, width, height, 1, - format, type, pixels); + format, type, pixels, "glTexSubImage2D"); } @@ -3752,7 +3744,7 @@ _mesa_TexSubImage3D( GLenum target, GLint level, texsubimage(ctx, 3, target, level, xoffset, yoffset, zoffset, width, height, depth, - format, type, pixels); + format, type, pixels, "glTexSubImage3D"); } void GLAPIENTRY @@ -3765,7 +3757,7 @@ _mesa_TextureSubImage1D(GLuint texture, GLint level, texturesubimage(ctx, 1, texture, level, xoffset, 0, 0, width, 1, 1, - format, type, pixels); + format, type, pixels, "glTextureSubImage1D"); } @@ -3780,7 +3772,7 @@ _mesa_TextureSubImage2D(GLuint texture, GLint level, texturesubimage(ctx, 2, texture, level, xoffset, yoffset, 0, width, height, 1, - format, type, pixels); + format, type, pixels, "glTextureSubImage2D"); } @@ -3795,7 +3787,7 @@ _mesa_TextureSubImage3D(GLuint texture, GLint level, texturesubimage(ctx, 3, texture, level, xoffset, yoffset, zoffset, width, height, depth, - format, type, pixels); + format, type, pixels, "glTextureSubImage3D"); } @@ -4040,15 +4032,14 @@ _mesa_copy_texture_sub_image(struct gl_context *ctx, GLuint dims, GLint xoffset, GLint yoffset, GLint zoffset, GLint x, GLint y, GLsizei width, GLsizei height, - bool dsa) + const char *caller) { struct gl_texture_image *texImage; FLUSH_VERTICES(ctx, 0); if (MESA_VERBOSE & (VERBOSE_API|VERBOSE_TEXTURE)) - _mesa_debug(ctx, "glCopyTex%sSubImage%uD %s %d %d %d %d %d %d %d %d\n", - dsa ? "ture" : "", dims, + _mesa_debug(ctx, "%s %s %d %d %d %d %d %d %d %d\n", caller, _mesa_lookup_enum_by_nr(target), level, xoffset, yoffset, zoffset, x, y, width, height); @@ -4057,7 +4048,7 @@ _mesa_copy_texture_sub_image(struct gl_context *ctx, GLuint dims, if (copytexsubimage_error_check(ctx, dims, texObj, target, level, xoffset, yoffset, zoffset, - width, height, dsa)) { + width, height, caller)) { return; } @@ -4103,14 +4094,14 @@ _mesa_CopyTexSubImage1D( GLenum target, GLint level, GLint xoffset, GLint x, GLint y, GLsizei width ) { struct gl_texture_object* texObj; + const char *self = "glCopyTexSubImage1D"; GET_CURRENT_CONTEXT(ctx); /* Check target (proxies not allowed). Target must be checked prior to * calling _mesa_get_current_tex_object. */ if (!legal_texsubimage_target(ctx, 1, target, false)) { - _mesa_error(ctx, GL_INVALID_ENUM, - "glCopyTexSubImage1D(invalid target %s)", + _mesa_error(ctx, GL_INVALID_ENUM, "%s(invalid target %s)", self, _mesa_lookup_enum_by_nr(target)); return; } @@ -4120,7 +4111,7 @@ _mesa_CopyTexSubImage1D( GLenum target, GLint level, return; _mesa_copy_texture_sub_image(ctx, 1, texObj, target, level, xoffset, 0, 0, - x, y, width, 1, false); + x, y, width, 1, self); } @@ -4131,14 +4122,14 @@ _mesa_CopyTexSubImage2D( GLenum target, GLint level, GLint x, GLint y, GLsizei width, GLsizei height ) { struct gl_texture_object* texObj; + const char *self = "glCopyTexSubImage2D"; GET_CURRENT_CONTEXT(ctx); /* Check target (proxies not allowed). Target must be checked prior to * calling _mesa_get_current_tex_object. */ if (!legal_texsubimage_target(ctx, 2, target, false)) { - _mesa_error(ctx, GL_INVALID_ENUM, - "glCopyTexSubImage2D(invalid target %s)", + _mesa_error(ctx, GL_INVALID_ENUM, "%s(invalid target %s)", self, _mesa_lookup_enum_by_nr(target)); return; } @@ -4149,7 +4140,7 @@ _mesa_CopyTexSubImage2D( GLenum target, GLint level, _mesa_copy_texture_sub_image(ctx, 2, texObj, target, level, xoffset, yoffset, 0, - x, y, width, height, false); + x, y, width, height, self); } @@ -4160,14 +4151,14 @@ _mesa_CopyTexSubImage3D( GLenum target, GLint level, GLint x, GLint y, GLsizei width, GLsizei height ) { struct gl_texture_object* texObj; + const char *self = "glCopyTexSubImage3D"; GET_CURRENT_CONTEXT(ctx); /* Check target (proxies not allowed). Target must be checked prior to * calling _mesa_get_current_tex_object. */ if (!legal_texsubimage_target(ctx, 3, target, false)) { - _mesa_error(ctx, GL_INVALID_ENUM, - "glCopyTexSubImage3D(invalid target %s)", + _mesa_error(ctx, GL_INVALID_ENUM, "%s(invalid target %s)", self, _mesa_lookup_enum_by_nr(target)); return; } @@ -4178,7 +4169,7 @@ _mesa_CopyTexSubImage3D( GLenum target, GLint level, _mesa_copy_texture_sub_image(ctx, 3, texObj, target, level, xoffset, yoffset, zoffset, - x, y, width, height, false); + x, y, width, height, self); } void GLAPIENTRY @@ -4186,22 +4177,22 @@ _mesa_CopyTextureSubImage1D(GLuint texture, GLint level, GLint xoffset, GLint x, GLint y, GLsizei width) { struct gl_texture_object* texObj; + const char *self = "glCopyTextureSubImage1D"; GET_CURRENT_CONTEXT(ctx); - texObj = _mesa_lookup_texture_err(ctx, texture, "glCopyTextureSubImage1D"); + texObj = _mesa_lookup_texture_err(ctx, texture, self); if (!texObj) return; /* Check target (proxies not allowed). */ if (!legal_texsubimage_target(ctx, 1, texObj->Target, true)) { - _mesa_error(ctx, GL_INVALID_ENUM, - "glCopyTextureSubImage1D(invalid target %s)", + _mesa_error(ctx, GL_INVALID_ENUM, "%s(invalid target %s)", self, _mesa_lookup_enum_by_nr(texObj->Target)); return; } _mesa_copy_texture_sub_image(ctx, 1, texObj, texObj->Target, level, - xoffset, 0, 0, x, y, width, 1, true); + xoffset, 0, 0, x, y, width, 1, self); } void GLAPIENTRY @@ -4210,23 +4201,23 @@ _mesa_CopyTextureSubImage2D(GLuint texture, GLint level, GLint x, GLint y, GLsizei width, GLsizei height) { struct gl_texture_object* texObj; + const char *self = "glCopyTextureSubImage2D"; GET_CURRENT_CONTEXT(ctx); - texObj = _mesa_lookup_texture_err(ctx, texture, "glCopyTextureSubImage2D"); + texObj = _mesa_lookup_texture_err(ctx, texture, self); if (!texObj) return; /* Check target (proxies not allowed). */ if (!legal_texsubimage_target(ctx, 2, texObj->Target, true)) { - _mesa_error(ctx, GL_INVALID_ENUM, - "glCopyTextureSubImage2D(invalid target %s)", + _mesa_error(ctx, GL_INVALID_ENUM, "%s(invalid target %s)", self, _mesa_lookup_enum_by_nr(texObj->Target)); return; } _mesa_copy_texture_sub_image(ctx, 2, texObj, texObj->Target, level, xoffset, yoffset, 0, - x, y, width, height, true); + x, y, width, height, self); } @@ -4237,23 +4228,31 @@ _mesa_CopyTextureSubImage3D(GLuint texture, GLint level, GLint x, GLint y, GLsizei width, GLsizei height) { struct gl_texture_object* texObj; + const char *self = "glCopyTextureSubImage3D"; GET_CURRENT_CONTEXT(ctx); - texObj = _mesa_lookup_texture_err(ctx, texture, "glCopyTextureSubImage3D"); + texObj = _mesa_lookup_texture_err(ctx, texture, self); if (!texObj) return; /* Check target (proxies not allowed). */ if (!legal_texsubimage_target(ctx, 3, texObj->Target, true)) { - _mesa_error(ctx, GL_INVALID_ENUM, - "glCopyTextureSubImage3D(invalid target %s)", + _mesa_error(ctx, GL_INVALID_ENUM, "%s(invalid target %s)", self, _mesa_lookup_enum_by_nr(texObj->Target)); return; } - _mesa_copy_texture_sub_image(ctx, 3, texObj, texObj->Target, level, - xoffset, yoffset, zoffset, - x, y, width, height, true); + if (texObj->Target == GL_TEXTURE_CUBE_MAP) { + /* Act like CopyTexSubImage2D */ + _mesa_copy_texture_sub_image(ctx, 2, texObj, + GL_TEXTURE_CUBE_MAP_POSITIVE_X + zoffset, + level, xoffset, yoffset, 0, + x, y, width, height, self); + } + else + _mesa_copy_texture_sub_image(ctx, 3, texObj, texObj->Target, level, + xoffset, yoffset, zoffset, + x, y, width, height, self); } static bool @@ -4636,68 +4635,72 @@ compressed_subtexture_error_check(struct gl_context *ctx, GLint dims, GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, - GLenum format, GLsizei imageSize, bool dsa) + GLenum format, GLsizei imageSize, + const GLvoid *data, const char *callerName) { struct gl_texture_image *texImage; GLint expectedSize; - const char *suffix = dsa ? "ture" : ""; /* this will catch any invalid compressed format token */ if (!_mesa_is_compressed_format(ctx, format)) { _mesa_error(ctx, GL_INVALID_ENUM, - "glCompressedTex%sSubImage%uD(format)", suffix, dims); + "%s(format)", callerName); return GL_TRUE; } if (level < 0 || level >= _mesa_max_texture_levels(ctx, target)) { _mesa_error(ctx, GL_INVALID_VALUE, - "glCompressedTex%sSubImage%uD(level=%d)", - suffix, dims, level); + "%s(level=%d)", + callerName, level); + return GL_TRUE; + } + + /* validate the bound PBO, if any */ + if (!_mesa_validate_pbo_source_compressed(ctx, dims, &ctx->Unpack, + imageSize, data, callerName)) { return GL_TRUE; } /* Check for invalid pixel storage modes */ if (!_mesa_compressed_pixel_storage_error_check(ctx, dims, - &ctx->Unpack, - dsa ? "glCompressedTextureSubImage" : - "glCompressedTexSubImage")) { + &ctx->Unpack, callerName)) { return GL_TRUE; } expectedSize = compressed_tex_size(width, height, depth, format); if (expectedSize != imageSize) { _mesa_error(ctx, GL_INVALID_VALUE, - "glCompressedTex%sSubImage%uD(size=%d)", - suffix, dims, imageSize); + "%s(size=%d)", + callerName, imageSize); return GL_TRUE; } texImage = _mesa_select_tex_image(texObj, target, level); if (!texImage) { _mesa_error(ctx, GL_INVALID_OPERATION, - "glCompressedTex%sSubImage%uD(invalid texture image)", - suffix, dims); + "%s(invalid texture image)", + callerName); return GL_TRUE; } if ((GLint) format != texImage->InternalFormat) { _mesa_error(ctx, GL_INVALID_OPERATION, - "glCompressedTex%sSubImage%uD(format=0x%x)", - suffix, dims, format); + "%s(format=0x%x)", + callerName, format); return GL_TRUE; } if (compressedteximage_only_format(ctx, format)) { _mesa_error(ctx, GL_INVALID_OPERATION, - "glCompressedTex%sSubImage%uD(format=0x%x cannot be updated)", - suffix, dims, format); + "%s(format=0x%x cannot be updated)", + callerName, format); return GL_TRUE; } if (error_check_subtexture_dimensions(ctx, dims, texImage, xoffset, yoffset, zoffset, width, height, depth, - "glCompressedTexSubImage")) { + callerName)) { return GL_TRUE; } @@ -4748,30 +4751,19 @@ _mesa_CompressedTexImage3D(GLenum target, GLint level, void _mesa_compressed_texture_sub_image(struct gl_context *ctx, GLuint dims, struct gl_texture_object *texObj, + struct gl_texture_image *texImage, GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLsizei imageSize, - const GLvoid *data, bool dsa) + const GLvoid *data) { - struct gl_texture_image *texImage; - - if (compressed_subtexture_error_check(ctx, dims, texObj, target, - level, xoffset, yoffset, zoffset, - width, height, depth, - format, imageSize, dsa)) { - return; - } - FLUSH_VERTICES(ctx, 0); _mesa_lock_texture(ctx, texObj); { - texImage = _mesa_select_tex_image(texObj, target, level); - assert(texImage); - if (width > 0 && height > 0 && depth > 0) { ctx->Driver.CompressedTexSubImage(ctx, dims, texImage, xoffset, yoffset, zoffset, @@ -4795,6 +4787,8 @@ _mesa_CompressedTexSubImage1D(GLenum target, GLint level, GLint xoffset, GLsizei imageSize, const GLvoid *data) { struct gl_texture_object *texObj; + struct gl_texture_image *texImage; + GET_CURRENT_CONTEXT(ctx); if (compressed_subtexture_target_check(ctx, target, 1, format, false, @@ -4806,9 +4800,20 @@ _mesa_CompressedTexSubImage1D(GLenum target, GLint level, GLint xoffset, if (!texObj) return; - _mesa_compressed_texture_sub_image(ctx, 1, texObj, target, level, + if (compressed_subtexture_error_check(ctx, 1, texObj, target, + level, xoffset, 0, 0, + width, 1, 1, + format, imageSize, data, + "glCompressedTexSubImage1D")) { + return; + } + + texImage = _mesa_select_tex_image(texObj, target, level); + assert(texImage); + + _mesa_compressed_texture_sub_image(ctx, 1, texObj, texImage, target, level, xoffset, 0, 0, width, 1, 1, - format, imageSize, data, false); + format, imageSize, data); } void GLAPIENTRY @@ -4817,6 +4822,8 @@ _mesa_CompressedTextureSubImage1D(GLuint texture, GLint level, GLint xoffset, GLsizei imageSize, const GLvoid *data) { struct gl_texture_object *texObj; + struct gl_texture_image *texImage; + GET_CURRENT_CONTEXT(ctx); texObj = _mesa_lookup_texture_err(ctx, texture, @@ -4830,9 +4837,21 @@ _mesa_CompressedTextureSubImage1D(GLuint texture, GLint level, GLint xoffset, return; } - _mesa_compressed_texture_sub_image(ctx, 1, texObj, texObj->Target, level, + if (compressed_subtexture_error_check(ctx, 1, texObj, texObj->Target, + level, xoffset, 0, 0, + width, 1, 1, + format, imageSize, data, + "glCompressedTextureSubImage1D")) { + return; + } + + texImage = _mesa_select_tex_image(texObj, texObj->Target, level); + assert(texImage); + + _mesa_compressed_texture_sub_image(ctx, 1, texObj, texImage, + texObj->Target, level, xoffset, 0, 0, width, 1, 1, - format, imageSize, data, true); + format, imageSize, data); } @@ -4843,6 +4862,8 @@ _mesa_CompressedTexSubImage2D(GLenum target, GLint level, GLint xoffset, const GLvoid *data) { struct gl_texture_object *texObj; + struct gl_texture_image *texImage; + GET_CURRENT_CONTEXT(ctx); if (compressed_subtexture_target_check(ctx, target, 2, format, false, @@ -4854,9 +4875,21 @@ _mesa_CompressedTexSubImage2D(GLenum target, GLint level, GLint xoffset, if (!texObj) return; - _mesa_compressed_texture_sub_image(ctx, 2, texObj, target, level, + if (compressed_subtexture_error_check(ctx, 2, texObj, target, + level, xoffset, yoffset, 0, + width, height, 1, + format, imageSize, data, + "glCompressedTexSubImage2D")) { + return; + } + + + texImage = _mesa_select_tex_image(texObj, target, level); + assert(texImage); + + _mesa_compressed_texture_sub_image(ctx, 2, texObj, texImage, target, level, xoffset, yoffset, 0, width, height, 1, - format, imageSize, data, false); + format, imageSize, data); } void GLAPIENTRY @@ -4867,6 +4900,8 @@ _mesa_CompressedTextureSubImage2D(GLuint texture, GLint level, GLint xoffset, const GLvoid *data) { struct gl_texture_object *texObj; + struct gl_texture_image *texImage; + GET_CURRENT_CONTEXT(ctx); texObj = _mesa_lookup_texture_err(ctx, texture, @@ -4880,9 +4915,21 @@ _mesa_CompressedTextureSubImage2D(GLuint texture, GLint level, GLint xoffset, return; } - _mesa_compressed_texture_sub_image(ctx, 2, texObj, texObj->Target, level, + if (compressed_subtexture_error_check(ctx, 2, texObj, texObj->Target, + level, xoffset, yoffset, 0, + width, height, 1, + format, imageSize, data, + "glCompressedTextureSubImage2D")) { + return; + } + + texImage = _mesa_select_tex_image(texObj, texObj->Target, level); + assert(texImage); + + _mesa_compressed_texture_sub_image(ctx, 2, texObj, texImage, + texObj->Target, level, xoffset, yoffset, 0, width, height, 1, - format, imageSize, data, true); + format, imageSize, data); } void GLAPIENTRY @@ -4892,6 +4939,8 @@ _mesa_CompressedTexSubImage3D(GLenum target, GLint level, GLint xoffset, GLsizei imageSize, const GLvoid *data) { struct gl_texture_object *texObj; + struct gl_texture_image *texImage; + GET_CURRENT_CONTEXT(ctx); if (compressed_subtexture_target_check(ctx, target, 3, format, false, @@ -4903,10 +4952,22 @@ _mesa_CompressedTexSubImage3D(GLenum target, GLint level, GLint xoffset, if (!texObj) return; - _mesa_compressed_texture_sub_image(ctx, 3, texObj, target, level, + if (compressed_subtexture_error_check(ctx, 3, texObj, target, + level, xoffset, yoffset, zoffset, + width, height, depth, + format, imageSize, data, + "glCompressedTexSubImage3D")) { + return; + } + + + texImage = _mesa_select_tex_image(texObj, target, level); + assert(texImage); + + _mesa_compressed_texture_sub_image(ctx, 3, texObj, texImage, target, level, xoffset, yoffset, zoffset, width, height, depth, - format, imageSize, data, false); + format, imageSize, data); } void GLAPIENTRY @@ -4917,6 +4978,8 @@ _mesa_CompressedTextureSubImage3D(GLuint texture, GLint level, GLint xoffset, const GLvoid *data) { struct gl_texture_object *texObj; + struct gl_texture_image *texImage; + GET_CURRENT_CONTEXT(ctx); texObj = _mesa_lookup_texture_err(ctx, texture, @@ -4930,10 +4993,60 @@ _mesa_CompressedTextureSubImage3D(GLuint texture, GLint level, GLint xoffset, return; } - _mesa_compressed_texture_sub_image(ctx, 3, texObj, texObj->Target, level, - xoffset, yoffset, zoffset, - width, height, depth, - format, imageSize, data, true); + if (compressed_subtexture_error_check(ctx, 3, texObj, texObj->Target, + level, xoffset, yoffset, zoffset, + width, height, depth, + format, imageSize, data, + "glCompressedTextureSubImage3D")) { + return; + } + + /* Must handle special case GL_TEXTURE_CUBE_MAP. */ + if (texObj->Target == GL_TEXTURE_CUBE_MAP) { + const char *pixels = data; + int i; + GLint image_stride; + + /* Make sure the texture object is a proper cube. + * (See texturesubimage in teximage.c for details on why this check is + * performed.) + */ + if (!_mesa_cube_level_complete(texObj, level)) { + _mesa_error(ctx, GL_INVALID_OPERATION, + "glCompressedTextureSubImage3D(cube map incomplete)"); + return; + } + + /* Copy in each face. */ + for (i = 0; i < 6; ++i) { + texImage = texObj->Image[i][level]; + assert(texImage); + + _mesa_compressed_texture_sub_image(ctx, 3, texObj, texImage, + texObj->Target, level, + xoffset, yoffset, zoffset, + width, height, 1, + format, imageSize, pixels); + + /* Compressed images don't have a client format */ + image_stride = _mesa_format_image_size(texImage->TexFormat, + texImage->Width, + texImage->Height, 1); + + pixels += image_stride; + imageSize -= image_stride; + } + } + else { + texImage = _mesa_select_tex_image(texObj, texObj->Target, level); + assert(texImage); + + _mesa_compressed_texture_sub_image(ctx, 3, texObj, texImage, + texObj->Target, level, + xoffset, yoffset, zoffset, + width, height, depth, + format, imageSize, data); + } } static mesa_format @@ -5152,24 +5265,34 @@ _mesa_validate_texbuffer_format(const struct gl_context *ctx, void _mesa_texture_buffer_range(struct gl_context *ctx, - struct gl_texture_object *texObj, GLenum target, + struct gl_texture_object *texObj, GLenum internalFormat, struct gl_buffer_object *bufObj, - GLintptr offset, GLsizeiptr size, bool range, - bool dsa) + GLintptr offset, GLsizeiptr size, + const char *caller) { mesa_format format; - FLUSH_VERTICES(ctx, 0); + /* NOTE: ARB_texture_buffer_object has interactions with + * the compatibility profile that are not implemented. + */ + if (!(ctx->API == API_OPENGL_CORE && + ctx->Extensions.ARB_texture_buffer_object)) { + _mesa_error(ctx, GL_INVALID_OPERATION, + "%s(ARB_texture_buffer_object is not" + " implemented for the compatibility profile)", caller); + return; + } format = _mesa_validate_texbuffer_format(ctx, internalFormat); if (format == MESA_FORMAT_NONE) { _mesa_error(ctx, GL_INVALID_ENUM, - "glTex%sBuffer%s(internalFormat 0x%x)", dsa ? "ture" : "", - range ? "Range" : "", internalFormat); + "%s(internalFormat 0x%x)", caller, internalFormat); return; } + FLUSH_VERTICES(ctx, 0); + _mesa_lock_texture(ctx, texObj); { _mesa_reference_buffer_object(ctx, &texObj->BufferObject, bufObj); @@ -5188,6 +5311,75 @@ _mesa_texture_buffer_range(struct gl_context *ctx, } +/** + * Make sure the texture buffer target is GL_TEXTURE_BUFFER. + * Return true if it is, and return false if it is not + * (and throw INVALID ENUM as dictated in the OpenGL 4.5 + * core spec, 02.02.2015, PDF page 245). + */ +static bool +check_texture_buffer_target(struct gl_context *ctx, GLenum target, + const char *caller) +{ + if (target != GL_TEXTURE_BUFFER_ARB) { + _mesa_error(ctx, GL_INVALID_ENUM, + "%s(texture target is not GL_TEXTURE_BUFFER)", caller); + return false; + } + else + return true; +} + +/** + * Check for errors related to the texture buffer range. + * Return false if errors are found, true if none are found. + */ +static bool +check_texture_buffer_range(struct gl_context *ctx, + struct gl_buffer_object *bufObj, + GLintptr offset, GLsizeiptr size, + const char *caller) +{ + /* OpenGL 4.5 core spec (02.02.2015) says in Section 8.9 Buffer + * Textures (PDF page 245): + * "An INVALID_VALUE error is generated if offset is negative, if + * size is less than or equal to zero, or if offset + size is greater + * than the value of BUFFER_SIZE for the buffer bound to target." + */ + if (offset < 0) { + _mesa_error(ctx, GL_INVALID_VALUE, "%s(offset=%d < 0)", caller, + (int) offset); + return false; + } + + if (size <= 0) { + _mesa_error(ctx, GL_INVALID_VALUE, "%s(size=%d <= 0)", caller, + (int) size); + return false; + } + + if (offset + size > bufObj->Size) { + _mesa_error(ctx, GL_INVALID_VALUE, + "%s(offset=%d + size=%d > buffer_size=%d)", caller, + (int) offset, (int) size, (int) bufObj->Size); + return false; + } + + /* OpenGL 4.5 core spec (02.02.2015) says in Section 8.9 Buffer + * Textures (PDF page 245): + * "An INVALID_VALUE error is generated if offset is not an integer + * multiple of the value of TEXTURE_BUFFER_OFFSET_ALIGNMENT." + */ + if (offset % ctx->Const.TextureBufferOffsetAlignment) { + _mesa_error(ctx, GL_INVALID_VALUE, + "%s(invalid offset alignment)", caller); + return false; + } + + return true; +} + + /** GL_ARB_texture_buffer_object */ void GLAPIENTRY _mesa_TexBuffer(GLenum target, GLenum internalFormat, GLuint buffer) @@ -5197,33 +5389,25 @@ _mesa_TexBuffer(GLenum target, GLenum internalFormat, GLuint buffer) GET_CURRENT_CONTEXT(ctx); - /* Need to catch this before it gets to _mesa_get_current_tex_object */ - if (target != GL_TEXTURE_BUFFER_ARB) { - _mesa_error(ctx, GL_INVALID_ENUM, "glTexBuffer(target)"); - return; - } - - /* NOTE: ARB_texture_buffer_object has interactions with - * the compatibility profile that are not implemented. + /* Need to catch a bad target before it gets to + * _mesa_get_current_tex_object. */ - if (!(ctx->API == API_OPENGL_CORE && - ctx->Extensions.ARB_texture_buffer_object)) { - _mesa_error(ctx, GL_INVALID_OPERATION, "glTexBuffer"); + if (!check_texture_buffer_target(ctx, target, "glTexBuffer")) return; - } - bufObj = _mesa_lookup_bufferobj(ctx, buffer); - if (!bufObj && buffer) { - _mesa_error(ctx, GL_INVALID_OPERATION, "glTexBuffer(buffer %u)", buffer); - return; - } + if (buffer) { + bufObj = _mesa_lookup_bufferobj_err(ctx, buffer, "glTexBuffer"); + if (!bufObj) + return; + } else + bufObj = NULL; texObj = _mesa_get_current_tex_object(ctx, target); if (!texObj) return; - _mesa_texture_buffer_range(ctx, texObj, target, internalFormat, bufObj, 0, - buffer ? -1 : 0, false, false); + _mesa_texture_buffer_range(ctx, texObj, internalFormat, bufObj, 0, + buffer ? -1 : 0, "glTexBuffer"); } @@ -5237,46 +5421,41 @@ _mesa_TexBufferRange(GLenum target, GLenum internalFormat, GLuint buffer, GET_CURRENT_CONTEXT(ctx); - /* Need to catch this before it gets to _mesa_get_current_tex_object */ - if (target != GL_TEXTURE_BUFFER_ARB) { - _mesa_error(ctx, GL_INVALID_ENUM, "glTexBufferRange(target)"); - return; - } - - if (!(ctx->API == API_OPENGL_CORE && - ctx->Extensions.ARB_texture_buffer_range)) { - _mesa_error(ctx, GL_INVALID_OPERATION, "glTexBufferRange"); + /* Need to catch a bad target before it gets to + * _mesa_get_current_tex_object. + */ + if (!check_texture_buffer_target(ctx, target, "glTexBufferRange")) return; - } - bufObj = _mesa_lookup_bufferobj(ctx, buffer); - if (bufObj) { - if (offset < 0 || - size <= 0 || - (offset + size) > bufObj->Size) { - _mesa_error(ctx, GL_INVALID_VALUE, "glTexBufferRange"); + if (buffer) { + bufObj = _mesa_lookup_bufferobj_err(ctx, buffer, "glTexBufferRange"); + if (!bufObj) return; - } - if (offset % ctx->Const.TextureBufferOffsetAlignment) { - _mesa_error(ctx, GL_INVALID_VALUE, - "glTexBufferRange(invalid offset alignment)"); + + if (!check_texture_buffer_range(ctx, bufObj, offset, size, + "glTexBufferRange")) return; - } - } else if (buffer) { - _mesa_error(ctx, GL_INVALID_OPERATION, "glTexBufferRange(buffer %u)", - buffer); - return; + } else { + + /* OpenGL 4.5 core spec (02.02.2015) says in Section 8.9 Buffer + * Textures (PDF page 254): + * "If buffer is zero, then any buffer object attached to the buffer + * texture is detached, the values offset and size are ignored and + * the state for offset and size for the buffer texture are reset to + * zero." + */ offset = 0; size = 0; + bufObj = NULL; } texObj = _mesa_get_current_tex_object(ctx, target); if (!texObj) return; - _mesa_texture_buffer_range(ctx, texObj, target, internalFormat, bufObj, - offset, size, true, false); + _mesa_texture_buffer_range(ctx, texObj, internalFormat, bufObj, + offset, size, "glTexBufferRange"); } void GLAPIENTRY @@ -5287,35 +5466,69 @@ _mesa_TextureBuffer(GLuint texture, GLenum internalFormat, GLuint buffer) GET_CURRENT_CONTEXT(ctx); - /* NOTE: ARB_texture_buffer_object has interactions with - * the compatibility profile that are not implemented. - */ - if (!(ctx->API == API_OPENGL_CORE && - ctx->Extensions.ARB_texture_buffer_object)) { - _mesa_error(ctx, GL_INVALID_OPERATION, "glTextureBuffer"); + if (buffer) { + bufObj = _mesa_lookup_bufferobj_err(ctx, buffer, "glTextureBuffer"); + if (!bufObj) + return; + } else + bufObj = NULL; + + /* Get the texture object by Name. */ + texObj = _mesa_lookup_texture_err(ctx, texture, "glTextureBuffer"); + if (!texObj) return; - } - bufObj = _mesa_lookup_bufferobj(ctx, buffer); - if (!bufObj && buffer) { - _mesa_error(ctx, GL_INVALID_OPERATION, "glTextureBuffer(buffer %u)", - buffer); + if (!check_texture_buffer_target(ctx, texObj->Target, "glTextureBuffer")) return; + + _mesa_texture_buffer_range(ctx, texObj, internalFormat, + bufObj, 0, buffer ? -1 : 0, "glTextureBuffer"); +} + +void GLAPIENTRY +_mesa_TextureBufferRange(GLuint texture, GLenum internalFormat, GLuint buffer, + GLintptr offset, GLsizeiptr size) +{ + struct gl_texture_object *texObj; + struct gl_buffer_object *bufObj; + + GET_CURRENT_CONTEXT(ctx); + + if (buffer) { + bufObj = _mesa_lookup_bufferobj_err(ctx, buffer, + "glTextureBufferRange"); + if (!bufObj) + return; + + if (!check_texture_buffer_range(ctx, bufObj, offset, size, + "glTextureBufferRange")) + return; + + } else { + + /* OpenGL 4.5 core spec (02.02.2015) says in Section 8.9 Buffer + * Textures (PDF page 254): + * "If buffer is zero, then any buffer object attached to the buffer + * texture is detached, the values offset and size are ignored and + * the state for offset and size for the buffer texture are reset to + * zero." + */ + offset = 0; + size = 0; + bufObj = NULL; } /* Get the texture object by Name. */ - texObj = _mesa_lookup_texture_err(ctx, texture, - "glTextureBuffer(texture)"); + texObj = _mesa_lookup_texture_err(ctx, texture, "glTextureBufferRange"); if (!texObj) return; - if (texObj->Target != GL_TEXTURE_BUFFER_ARB) { - _mesa_error(ctx, GL_INVALID_ENUM, "glTextureBuffer(target)"); + if (!check_texture_buffer_target(ctx, texObj->Target, + "glTextureBufferRange")) return; - } - _mesa_texture_buffer_range(ctx, texObj, texObj->Target, internalFormat, - bufObj, 0, buffer ? -1 : 0, false, true); + _mesa_texture_buffer_range(ctx, texObj, internalFormat, + bufObj, offset, size, "glTextureBufferRange"); } static GLboolean diff --git a/mesalib/src/mesa/main/teximage.h b/mesalib/src/mesa/main/teximage.h index b7336bc6c..1eebaa8b6 100644 --- a/mesalib/src/mesa/main/teximage.h +++ b/mesalib/src/mesa/main/teximage.h @@ -181,13 +181,14 @@ _mesa_texture_sub_image(struct gl_context *ctx, GLuint dims, extern void _mesa_compressed_texture_sub_image(struct gl_context *ctx, GLuint dims, struct gl_texture_object *texObj, + struct gl_texture_image *texImage, GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLsizei imageSize, - const GLvoid *data, bool dsa); + const GLvoid *data); extern void _mesa_copy_texture_sub_image(struct gl_context *ctx, GLuint dims, @@ -195,7 +196,8 @@ _mesa_copy_texture_sub_image(struct gl_context *ctx, GLuint dims, GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLint x, GLint y, - GLsizei width, GLsizei height, bool dsa); + GLsizei width, GLsizei height, + const char *caller); extern void _mesa_texture_image_multisample(struct gl_context *ctx, GLuint dims, @@ -208,11 +210,11 @@ _mesa_texture_image_multisample(struct gl_context *ctx, GLuint dims, extern void _mesa_texture_buffer_range(struct gl_context *ctx, - struct gl_texture_object *texObj, GLenum target, + struct gl_texture_object *texObj, GLenum internalFormat, struct gl_buffer_object *bufObj, - GLintptr offset, GLsizeiptr size, bool range, - bool dsa); + GLintptr offset, GLsizeiptr size, + const char *caller); /*@}*/ @@ -408,6 +410,10 @@ _mesa_TexBufferRange(GLenum target, GLenum internalFormat, GLuint buffer, extern void GLAPIENTRY _mesa_TextureBuffer(GLuint texture, GLenum internalFormat, GLuint buffer); +extern void GLAPIENTRY +_mesa_TextureBufferRange(GLuint texture, GLenum internalFormat, GLuint buffer, + GLintptr offset, GLsizeiptr size); + extern void GLAPIENTRY _mesa_TexImage2DMultisample(GLenum target, GLsizei samples, diff --git a/mesalib/src/mesa/main/transformfeedback.c b/mesalib/src/mesa/main/transformfeedback.c index a3e23ced5..ce678c864 100644 --- a/mesalib/src/mesa/main/transformfeedback.c +++ b/mesalib/src/mesa/main/transformfeedback.c @@ -762,7 +762,7 @@ _mesa_TransformFeedbackVaryings(GLuint program, GLsizei count, /* Save the new names and the count */ for (i = 0; i < count; i++) { - shProg->TransformFeedback.VaryingNames[i] = _mesa_strdup(varyings[i]); + shProg->TransformFeedback.VaryingNames[i] = strdup(varyings[i]); } shProg->TransformFeedback.NumVarying = count; diff --git a/mesalib/src/mesa/main/uniform_query.cpp b/mesalib/src/mesa/main/uniform_query.cpp index 9f82de952..2ab5528c3 100644 --- a/mesalib/src/mesa/main/uniform_query.cpp +++ b/mesalib/src/mesa/main/uniform_query.cpp @@ -260,8 +260,8 @@ validate_uniform_parameters(struct gl_context *ctx, if (uni->array_elements == 0) { if (count > 1) { _mesa_error(ctx, GL_INVALID_OPERATION, - "%s(count > 1 for non-array, location=%d)", - caller, location); + "%s(count = %u for non-array \"%s\"@%d)", + caller, count, uni->name, location); return NULL; } @@ -601,6 +601,46 @@ _mesa_propagate_uniforms_to_driver_storage(struct gl_uniform_storage *uni, } } + +/** + * Return printable string for a given GLSL_TYPE_x + */ +static const char * +glsl_type_name(enum glsl_base_type type) +{ + switch (type) { + case GLSL_TYPE_UINT: + return "uint"; + case GLSL_TYPE_INT: + return "int"; + case GLSL_TYPE_FLOAT: + return "float"; + case GLSL_TYPE_DOUBLE: + return "double"; + case GLSL_TYPE_BOOL: + return "bool"; + case GLSL_TYPE_SAMPLER: + return "sampler"; + case GLSL_TYPE_IMAGE: + return "image"; + case GLSL_TYPE_ATOMIC_UINT: + return "atomic_uint"; + case GLSL_TYPE_STRUCT: + return "struct"; + case GLSL_TYPE_INTERFACE: + return "interface"; + case GLSL_TYPE_ARRAY: + return "array"; + case GLSL_TYPE_VOID: + return "void"; + case GLSL_TYPE_ERROR: + return "error"; + default: + return "other"; + } +} + + /** * Called via glUniform*() functions. */ @@ -620,11 +660,28 @@ _mesa_uniform(struct gl_context *ctx, struct gl_shader_program *shProg, if (uni == NULL) return; + if (uni->type->is_matrix()) { + /* Can't set matrix uniforms (like mat4) with glUniform */ + _mesa_error(ctx, GL_INVALID_OPERATION, + "glUniform%u(uniform \"%s\"@%d is matrix)", + src_components, uni->name, location); + return; + } + /* Verify that the types are compatible. */ const unsigned components = uni->type->is_sampler() ? 1 : uni->type->vector_elements; + if (components != src_components) { + /* glUniformN() must match float/vecN type */ + _mesa_error(ctx, GL_INVALID_OPERATION, + "glUniform%u(\"%s\"@%u has %u components, not %u)", + src_components, uni->name, location, + components, src_components); + return; + } + bool match; switch (uni->type->base_type) { case GLSL_TYPE_BOOL: @@ -639,8 +696,12 @@ _mesa_uniform(struct gl_context *ctx, struct gl_shader_program *shProg, break; } - if (uni->type->is_matrix() || components != src_components || !match) { - _mesa_error(ctx, GL_INVALID_OPERATION, "glUniform(type mismatch)"); + if (!match) { + _mesa_error(ctx, GL_INVALID_OPERATION, + "glUniform%u(\"%s\"@%d is %s, not %s)", + src_components, uni->name, location, + glsl_type_name(uni->type->base_type), + glsl_type_name(basicType)); return; } diff --git a/mesalib/src/mesa/math/m_clip_tmp.h b/mesalib/src/mesa/math/m_clip_tmp.h index 45dec47f0..e289be7b3 100644 --- a/mesalib/src/mesa/math/m_clip_tmp.h +++ b/mesalib/src/mesa/math/m_clip_tmp.h @@ -40,7 +40,7 @@ * \param andMask bitwise-AND of clipMask values * \return proj_vec pointer */ -static GLvector4f * _XFORMAPI TAG(cliptest_points4)( GLvector4f *clip_vec, +static GLvector4f * TAG(cliptest_points4)( GLvector4f *clip_vec, GLvector4f *proj_vec, GLubyte clipMask[], GLubyte *orMask, @@ -120,7 +120,7 @@ static GLvector4f * _XFORMAPI TAG(cliptest_points4)( GLvector4f *clip_vec, * \param andMask bitwise-AND of clipMask values * \return clip_vec pointer */ -static GLvector4f * _XFORMAPI TAG(cliptest_np_points4)( GLvector4f *clip_vec, +static GLvector4f * TAG(cliptest_np_points4)( GLvector4f *clip_vec, GLvector4f *proj_vec, GLubyte clipMask[], GLubyte *orMask, @@ -177,7 +177,7 @@ static GLvector4f * _XFORMAPI TAG(cliptest_np_points4)( GLvector4f *clip_vec, } -static GLvector4f * _XFORMAPI TAG(cliptest_points3)( GLvector4f *clip_vec, +static GLvector4f * TAG(cliptest_points3)( GLvector4f *clip_vec, GLvector4f *proj_vec, GLubyte clipMask[], GLubyte *orMask, @@ -213,7 +213,7 @@ static GLvector4f * _XFORMAPI TAG(cliptest_points3)( GLvector4f *clip_vec, } -static GLvector4f * _XFORMAPI TAG(cliptest_points2)( GLvector4f *clip_vec, +static GLvector4f * TAG(cliptest_points2)( GLvector4f *clip_vec, GLvector4f *proj_vec, GLubyte clipMask[], GLubyte *orMask, diff --git a/mesalib/src/mesa/math/m_norm_tmp.h b/mesalib/src/mesa/math/m_norm_tmp.h index c8fab0ed3..d3ec1c22e 100644 --- a/mesalib/src/mesa/math/m_norm_tmp.h +++ b/mesalib/src/mesa/math/m_norm_tmp.h @@ -39,7 +39,7 @@ * optimization) * dest - the destination vector of normals */ -static void _XFORMAPI +static void TAG(transform_normalize_normals)( const GLmatrix *mat, GLfloat scale, const GLvector4f *in, @@ -106,7 +106,7 @@ TAG(transform_normalize_normals)( const GLmatrix *mat, } -static void _XFORMAPI +static void TAG(transform_normalize_normals_no_rot)( const GLmatrix *mat, GLfloat scale, const GLvector4f *in, @@ -171,7 +171,7 @@ TAG(transform_normalize_normals_no_rot)( const GLmatrix *mat, } -static void _XFORMAPI +static void TAG(transform_rescale_normals_no_rot)( const GLmatrix *mat, GLfloat scale, const GLvector4f *in, @@ -200,7 +200,7 @@ TAG(transform_rescale_normals_no_rot)( const GLmatrix *mat, } -static void _XFORMAPI +static void TAG(transform_rescale_normals)( const GLmatrix *mat, GLfloat scale, const GLvector4f *in, @@ -232,7 +232,7 @@ TAG(transform_rescale_normals)( const GLmatrix *mat, } -static void _XFORMAPI +static void TAG(transform_normals_no_rot)( const GLmatrix *mat, GLfloat scale, const GLvector4f *in, @@ -262,7 +262,7 @@ TAG(transform_normals_no_rot)( const GLmatrix *mat, } -static void _XFORMAPI +static void TAG(transform_normals)( const GLmatrix *mat, GLfloat scale, const GLvector4f *in, @@ -292,7 +292,7 @@ TAG(transform_normals)( const GLmatrix *mat, } -static void _XFORMAPI +static void TAG(normalize_normals)( const GLmatrix *mat, GLfloat scale, const GLvector4f *in, @@ -338,7 +338,7 @@ TAG(normalize_normals)( const GLmatrix *mat, } -static void _XFORMAPI +static void TAG(rescale_normals)( const GLmatrix *mat, GLfloat scale, const GLvector4f *in, @@ -361,7 +361,7 @@ TAG(rescale_normals)( const GLmatrix *mat, } -static void _XFORMAPI +static void TAG(init_c_norm_transform)( void ) { _mesa_normal_tab[NORM_TRANSFORM_NO_ROT] = diff --git a/mesalib/src/mesa/math/m_xform.h b/mesalib/src/mesa/math/m_xform.h index 2ed62e711..0bb8e9bd8 100644 --- a/mesalib/src/mesa/math/m_xform.h +++ b/mesalib/src/mesa/math/m_xform.h @@ -32,14 +32,6 @@ #include "math/m_matrix.h" #include "math/m_vector.h" -#ifdef USE_X86_ASM -#define _XFORMAPI _ASMAPI -#define _XFORMAPIP _ASMAPIP -#else -#define _XFORMAPI -#define _XFORMAPIP * -#endif - extern void _math_init_transformation(void); @@ -99,12 +91,12 @@ init_c_cliptest(void); #define CLIP_FRUSTUM_BITS 0x3f -typedef GLvector4f * (_XFORMAPIP clip_func)( GLvector4f *vClip, - GLvector4f *vProj, - GLubyte clipMask[], - GLubyte *orMask, - GLubyte *andMask, - GLboolean viewport_z_clip ); +typedef GLvector4f * (*clip_func)(GLvector4f *vClip, + GLvector4f *vProj, + GLubyte clipMask[], + GLubyte *orMask, + GLubyte *andMask, + GLboolean viewport_z_clip); typedef void (*dotprod_func)( GLfloat *out, GLuint out_stride, @@ -119,11 +111,11 @@ typedef void (*vec_copy_func)( GLvector4f *to, /* * Functions for transformation of normals in the VB. */ -typedef void (_XFORMAPIP normal_func)( const GLmatrix *mat, - GLfloat scale, - const GLvector4f *in, - const GLfloat lengths[], - GLvector4f *dest ); +typedef void (*normal_func)(const GLmatrix *mat, + GLfloat scale, + const GLvector4f *in, + const GLfloat lengths[], + GLvector4f *dest); /* Flags for selecting a normal transformation function. @@ -141,9 +133,9 @@ typedef void (_XFORMAPIP normal_func)( const GLmatrix *mat, * when the mask byte is zero. This is always present as a * parameter, to allow a unified interface. */ -typedef void (_XFORMAPIP transform_func)( GLvector4f *to_vec, - const GLfloat m[16], - const GLvector4f *from_vec ); +typedef void (*transform_func)(GLvector4f *to_vec, + const GLfloat m[16], + const GLvector4f *from_vec); extern dotprod_func _mesa_dotprod_tab[5]; diff --git a/mesalib/src/mesa/math/m_xform_tmp.h b/mesalib/src/mesa/math/m_xform_tmp.h index 8886c9646..af85de3d4 100644 --- a/mesalib/src/mesa/math/m_xform_tmp.h +++ b/mesalib/src/mesa/math/m_xform_tmp.h @@ -70,7 +70,7 @@ * driver-specific vertex format. */ -static void _XFORMAPI +static void TAG(transform_points1_general)( GLvector4f *to_vec, const GLfloat m[16], const GLvector4f *from_vec ) @@ -96,7 +96,7 @@ TAG(transform_points1_general)( GLvector4f *to_vec, to_vec->count = from_vec->count; } -static void _XFORMAPI +static void TAG(transform_points1_identity)( GLvector4f *to_vec, const GLfloat m[16], const GLvector4f *from_vec ) @@ -116,7 +116,7 @@ TAG(transform_points1_identity)( GLvector4f *to_vec, to_vec->count = from_vec->count; } -static void _XFORMAPI +static void TAG(transform_points1_2d)( GLvector4f *to_vec, const GLfloat m[16], const GLvector4f *from_vec ) @@ -138,7 +138,7 @@ TAG(transform_points1_2d)( GLvector4f *to_vec, to_vec->count = from_vec->count; } -static void _XFORMAPI +static void TAG(transform_points1_2d_no_rot)( GLvector4f *to_vec, const GLfloat m[16], const GLvector4f *from_vec ) @@ -159,7 +159,7 @@ TAG(transform_points1_2d_no_rot)( GLvector4f *to_vec, to_vec->count = from_vec->count; } -static void _XFORMAPI +static void TAG(transform_points1_3d)( GLvector4f *to_vec, const GLfloat m[16], const GLvector4f *from_vec ) @@ -183,7 +183,7 @@ TAG(transform_points1_3d)( GLvector4f *to_vec, } -static void _XFORMAPI +static void TAG(transform_points1_3d_no_rot)( GLvector4f *to_vec, const GLfloat m[16], const GLvector4f *from_vec ) @@ -206,7 +206,7 @@ TAG(transform_points1_3d_no_rot)( GLvector4f *to_vec, to_vec->count = from_vec->count; } -static void _XFORMAPI +static void TAG(transform_points1_perspective)( GLvector4f *to_vec, const GLfloat m[16], const GLvector4f *from_vec ) @@ -236,7 +236,7 @@ TAG(transform_points1_perspective)( GLvector4f *to_vec, * present early in the geometry pipeline and throughout the * texture pipeline. */ -static void _XFORMAPI +static void TAG(transform_points2_general)( GLvector4f *to_vec, const GLfloat m[16], const GLvector4f *from_vec ) @@ -262,7 +262,7 @@ TAG(transform_points2_general)( GLvector4f *to_vec, to_vec->count = from_vec->count; } -static void _XFORMAPI +static void TAG(transform_points2_identity)( GLvector4f *to_vec, const GLfloat m[16], const GLvector4f *from_vec ) @@ -283,7 +283,7 @@ TAG(transform_points2_identity)( GLvector4f *to_vec, to_vec->count = from_vec->count; } -static void _XFORMAPI +static void TAG(transform_points2_2d)( GLvector4f *to_vec, const GLfloat m[16], const GLvector4f *from_vec ) @@ -305,7 +305,7 @@ TAG(transform_points2_2d)( GLvector4f *to_vec, to_vec->count = from_vec->count; } -static void _XFORMAPI +static void TAG(transform_points2_2d_no_rot)( GLvector4f *to_vec, const GLfloat m[16], const GLvector4f *from_vec ) @@ -326,7 +326,7 @@ TAG(transform_points2_2d_no_rot)( GLvector4f *to_vec, to_vec->count = from_vec->count; } -static void _XFORMAPI +static void TAG(transform_points2_3d)( GLvector4f *to_vec, const GLfloat m[16], const GLvector4f *from_vec ) @@ -353,7 +353,7 @@ TAG(transform_points2_3d)( GLvector4f *to_vec, /* I would actually say this was a fairly important function, from * a texture transformation point of view. */ -static void _XFORMAPI +static void TAG(transform_points2_3d_no_rot)( GLvector4f *to_vec, const GLfloat m[16], const GLvector4f *from_vec ) @@ -382,7 +382,7 @@ TAG(transform_points2_3d_no_rot)( GLvector4f *to_vec, } -static void _XFORMAPI +static void TAG(transform_points2_perspective)( GLvector4f *to_vec, const GLfloat m[16], const GLvector4f *from_vec ) @@ -407,7 +407,7 @@ TAG(transform_points2_perspective)( GLvector4f *to_vec, -static void _XFORMAPI +static void TAG(transform_points3_general)( GLvector4f *to_vec, const GLfloat m[16], const GLvector4f *from_vec ) @@ -433,7 +433,7 @@ TAG(transform_points3_general)( GLvector4f *to_vec, to_vec->count = from_vec->count; } -static void _XFORMAPI +static void TAG(transform_points3_identity)( GLvector4f *to_vec, const GLfloat m[16], const GLvector4f *from_vec ) @@ -455,7 +455,7 @@ TAG(transform_points3_identity)( GLvector4f *to_vec, to_vec->count = from_vec->count; } -static void _XFORMAPI +static void TAG(transform_points3_2d)( GLvector4f *to_vec, const GLfloat m[16], const GLvector4f *from_vec ) @@ -478,7 +478,7 @@ TAG(transform_points3_2d)( GLvector4f *to_vec, to_vec->count = from_vec->count; } -static void _XFORMAPI +static void TAG(transform_points3_2d_no_rot)( GLvector4f *to_vec, const GLfloat m[16], const GLvector4f *from_vec ) @@ -500,7 +500,7 @@ TAG(transform_points3_2d_no_rot)( GLvector4f *to_vec, to_vec->count = from_vec->count; } -static void _XFORMAPI +static void TAG(transform_points3_3d)( GLvector4f *to_vec, const GLfloat m[16], const GLvector4f *from_vec ) @@ -526,7 +526,7 @@ TAG(transform_points3_3d)( GLvector4f *to_vec, /* previously known as ortho... */ -static void _XFORMAPI +static void TAG(transform_points3_3d_no_rot)( GLvector4f *to_vec, const GLfloat m[16], const GLvector4f *from_vec ) @@ -549,7 +549,7 @@ TAG(transform_points3_3d_no_rot)( GLvector4f *to_vec, to_vec->count = from_vec->count; } -static void _XFORMAPI +static void TAG(transform_points3_perspective)( GLvector4f *to_vec, const GLfloat m[16], const GLvector4f *from_vec ) @@ -575,7 +575,7 @@ TAG(transform_points3_perspective)( GLvector4f *to_vec, -static void _XFORMAPI +static void TAG(transform_points4_general)( GLvector4f *to_vec, const GLfloat m[16], const GLvector4f *from_vec ) @@ -601,7 +601,7 @@ TAG(transform_points4_general)( GLvector4f *to_vec, to_vec->count = from_vec->count; } -static void _XFORMAPI +static void TAG(transform_points4_identity)( GLvector4f *to_vec, const GLfloat m[16], const GLvector4f *from_vec ) @@ -624,7 +624,7 @@ TAG(transform_points4_identity)( GLvector4f *to_vec, to_vec->count = from_vec->count; } -static void _XFORMAPI +static void TAG(transform_points4_2d)( GLvector4f *to_vec, const GLfloat m[16], const GLvector4f *from_vec ) @@ -648,7 +648,7 @@ TAG(transform_points4_2d)( GLvector4f *to_vec, to_vec->count = from_vec->count; } -static void _XFORMAPI +static void TAG(transform_points4_2d_no_rot)( GLvector4f *to_vec, const GLfloat m[16], const GLvector4f *from_vec ) @@ -671,7 +671,7 @@ TAG(transform_points4_2d_no_rot)( GLvector4f *to_vec, to_vec->count = from_vec->count; } -static void _XFORMAPI +static void TAG(transform_points4_3d)( GLvector4f *to_vec, const GLfloat m[16], const GLvector4f *from_vec ) @@ -696,7 +696,7 @@ TAG(transform_points4_3d)( GLvector4f *to_vec, to_vec->count = from_vec->count; } -static void _XFORMAPI +static void TAG(transform_points4_3d_no_rot)( GLvector4f *to_vec, const GLfloat m[16], const GLvector4f *from_vec ) @@ -720,7 +720,7 @@ TAG(transform_points4_3d_no_rot)( GLvector4f *to_vec, to_vec->count = from_vec->count; } -static void _XFORMAPI +static void TAG(transform_points4_perspective)( GLvector4f *to_vec, const GLfloat m[16], const GLvector4f *from_vec ) @@ -753,7 +753,7 @@ static transform_func TAG(transform_tab_4)[7]; * optimized routines overwriting the arrays. This only occurs during * startup. */ -static void _XFORMAPI TAG(init_c_transformations)( void ) +static void TAG(init_c_transformations)( void ) { #define TAG_TAB _mesa_transform_tab #define TAG_TAB_1 TAG(transform_tab_1) diff --git a/mesalib/src/mesa/program/prog_instruction.c b/mesalib/src/mesa/program/prog_instruction.c index 6a9bcb7b5..f9ebe4e8f 100644 --- a/mesalib/src/mesa/program/prog_instruction.c +++ b/mesalib/src/mesa/program/prog_instruction.c @@ -89,7 +89,7 @@ _mesa_copy_instructions(struct prog_instruction *dest, memcpy(dest, src, n * sizeof(struct prog_instruction)); for (i = 0; i < n; i++) { if (src[i].Comment) - dest[i].Comment = _mesa_strdup(src[i].Comment); + dest[i].Comment = strdup(src[i].Comment); } return dest; } diff --git a/mesalib/src/mesa/program/prog_instruction.h b/mesalib/src/mesa/program/prog_instruction.h index 0957bd9d7..ab3acbc02 100644 --- a/mesalib/src/mesa/program/prog_instruction.h +++ b/mesalib/src/mesa/program/prog_instruction.h @@ -366,11 +366,11 @@ struct prog_instruction */ GLint BranchTarget; - /** for debugging purposes */ - const char *Comment; - /** for driver use (try to remove someday) */ GLint Aux; + + /** for debugging purposes */ + const char *Comment; }; diff --git a/mesalib/src/mesa/program/prog_parameter.c b/mesalib/src/mesa/program/prog_parameter.c index 5939f6f72..cdfe25145 100644 --- a/mesalib/src/mesa/program/prog_parameter.c +++ b/mesalib/src/mesa/program/prog_parameter.c @@ -148,7 +148,7 @@ _mesa_add_parameter(struct gl_program_parameter_list *paramList, for (i = 0; i < sz4; i++) { struct gl_program_parameter *p = paramList->Parameters + oldNum + i; - p->Name = name ? _mesa_strdup(name) : NULL; + p->Name = name ? strdup(name) : NULL; p->Type = type; p->Size = size; p->DataType = datatype; diff --git a/mesalib/src/mesa/program/prog_statevars.c b/mesalib/src/mesa/program/prog_statevars.c index 57b25a7e3..0c0c87faa 100644 --- a/mesalib/src/mesa/program/prog_statevars.c +++ b/mesalib/src/mesa/program/prog_statevars.c @@ -1045,7 +1045,7 @@ _mesa_program_state_string(const gl_state_index state[STATE_LENGTH]) break; } - return _mesa_strdup(str); + return strdup(str); } diff --git a/mesalib/src/mesa/program/program.c b/mesalib/src/mesa/program/program.c index 61a9e97c9..3c214d5e3 100644 --- a/mesalib/src/mesa/program/program.c +++ b/mesalib/src/mesa/program/program.c @@ -79,7 +79,7 @@ _mesa_init_program(struct gl_context *ctx) STATIC_ASSERT(NUM_TEXTURE_TARGETS <= (1 << 4)); ctx->Program.ErrorPos = -1; - ctx->Program.ErrorString = _mesa_strdup(""); + ctx->Program.ErrorString = strdup(""); ctx->VertexProgram.Enabled = GL_FALSE; ctx->VertexProgram.PointSizeEnabled = @@ -176,7 +176,7 @@ _mesa_set_program_error(struct gl_context *ctx, GLint pos, const char *string) free((void *) ctx->Program.ErrorString); if (!string) string = ""; - ctx->Program.ErrorString = _mesa_strdup(string); + ctx->Program.ErrorString = strdup(string); } @@ -483,7 +483,7 @@ _mesa_clone_program(struct gl_context *ctx, const struct gl_program *prog) assert(clone->Target == prog->Target); assert(clone->RefCount == 1); - clone->String = (GLubyte *) _mesa_strdup((char *) prog->String); + clone->String = (GLubyte *) strdup((char *) prog->String); clone->Format = prog->Format; clone->Instructions = _mesa_alloc_instructions(prog->NumInstructions); if (!clone->Instructions) { diff --git a/mesalib/src/mesa/state_tracker/st_cb_bufferobjects.c b/mesalib/src/mesa/state_tracker/st_cb_bufferobjects.c index 1dbc4b905..db254c214 100644 --- a/mesalib/src/mesa/state_tracker/st_cb_bufferobjects.c +++ b/mesalib/src/mesa/state_tracker/st_cb_bufferobjects.c @@ -485,8 +485,8 @@ st_clear_buffer_subdata(struct gl_context *ctx, static const char zeros[16] = {0}; if (!pipe->clear_buffer) { - _mesa_buffer_clear_subdata(ctx, offset, size, - clearValue, clearValueSize, bufObj); + _mesa_ClearBufferSubData_sw(ctx, offset, size, + clearValue, clearValueSize, bufObj); return; } diff --git a/mesalib/src/mesa/state_tracker/st_cb_texture.c b/mesalib/src/mesa/state_tracker/st_cb_texture.c index a8b19a1f3..5c520b44f 100644 --- a/mesalib/src/mesa/state_tracker/st_cb_texture.c +++ b/mesalib/src/mesa/state_tracker/st_cb_texture.c @@ -178,9 +178,6 @@ st_FreeTextureImageBuffer(struct gl_context *ctx, pipe_resource_reference(&stImage->pt, NULL); } - _mesa_align_free(stImage->TexData); - stImage->TexData = NULL; - free(stImage->transfer); stImage->transfer = NULL; stImage->num_transfers = 0; @@ -501,7 +498,6 @@ st_AllocTextureImageBuffer(struct gl_context *ctx, DBG("%s\n", __FUNCTION__); - assert(!stImage->TexData); assert(!stImage->pt); /* xxx this might be wrong */ /* Look if the parent texture object has space for this image */ @@ -1521,23 +1517,6 @@ copy_image_data_to_texture(struct st_context *st, pipe_resource_reference(&stImage->pt, NULL); } - else if (stImage->TexData) { - /* Copy from malloc'd memory */ - /* XXX this should be re-examined/tested with a compressed format */ - GLuint blockSize = util_format_get_blocksize(stObj->pt->format); - GLuint srcRowStride = stImage->base.Width * blockSize; - GLuint srcSliceStride = stImage->base.Height * srcRowStride; - st_texture_image_data(st, - stObj->pt, - stImage->base.Face, - dstLevel, - stImage->TexData, - srcRowStride, - srcSliceStride); - _mesa_align_free(stImage->TexData); - stImage->TexData = NULL; - } - pipe_resource_reference(&stImage->pt, stObj->pt); } 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 bd191d864..efee4b258 100644 --- a/mesalib/src/mesa/state_tracker/st_glsl_to_tgsi.cpp +++ b/mesalib/src/mesa/state_tracker/st_glsl_to_tgsi.cpp @@ -332,6 +332,7 @@ public: int glsl_version; bool native_integers; bool have_sqrt; + bool have_fma; variable_storage *find_variable_storage(ir_variable *var); @@ -836,6 +837,7 @@ glsl_to_tgsi_visitor::get_opcode(ir_instruction *ir, unsigned op, case3fid(ADD, UADD, DADD); case3fid(MUL, UMUL, DMUL); case3fid(MAD, UMAD, DMAD); + case3fid(FMA, UMAD, DFMA); case3(DIV, IDIV, UDIV); case4d(MAX, IMAX, UMAX, DMAX); case4d(MIN, IMIN, UMIN, DMIN); @@ -2222,10 +2224,11 @@ glsl_to_tgsi_visitor::visit(ir_expression *ir) emit(ir, TGSI_OPCODE_IMUL_HI, result_dst, op[0], op[1]); break; case ir_triop_fma: - /* NOTE: Perhaps there should be a special opcode that enforces fused - * mul-add. Just use MAD for now. - */ - emit(ir, TGSI_OPCODE_MAD, result_dst, op[0], op[1], op[2]); + /* In theory, MAD is incorrect here. */ + if (have_fma) + emit(ir, TGSI_OPCODE_FMA, result_dst, op[0], op[1], op[2]); + else + emit(ir, TGSI_OPCODE_MAD, result_dst, op[0], op[1], op[2]); break; case ir_unop_interpolate_at_centroid: emit(ir, TGSI_OPCODE_INTERP_CENTROID, result_dst, op[0]); @@ -5564,6 +5567,8 @@ get_mesa_program(struct gl_context *ctx, v->have_sqrt = pscreen->get_shader_param(pscreen, ptarget, PIPE_SHADER_CAP_TGSI_SQRT_SUPPORTED); + v->have_fma = pscreen->get_shader_param(pscreen, ptarget, + PIPE_SHADER_CAP_TGSI_FMA_SUPPORTED); _mesa_copy_linked_program_data(shader->Stage, shader_program, prog); _mesa_generate_parameters_list_for_uniforms(shader_program, shader, diff --git a/mesalib/src/mesa/state_tracker/st_texture.c b/mesalib/src/mesa/state_tracker/st_texture.c index ada984189..ca7c83c21 100644 --- a/mesalib/src/mesa/state_tracker/st_texture.c +++ b/mesalib/src/mesa/state_tracker/st_texture.c @@ -310,46 +310,6 @@ st_texture_image_unmap(struct st_context *st, *transfer = NULL; } - -/* Upload data for a particular image. - */ -void -st_texture_image_data(struct st_context *st, - struct pipe_resource *dst, - GLuint face, - GLuint level, - void *src, - GLuint src_row_stride, GLuint src_image_stride) -{ - struct pipe_context *pipe = st->pipe; - GLuint i; - const GLubyte *srcUB = src; - GLuint layers; - - if (dst->target == PIPE_TEXTURE_1D_ARRAY || - dst->target == PIPE_TEXTURE_2D_ARRAY || - dst->target == PIPE_TEXTURE_CUBE_ARRAY) - layers = dst->array_size; - else - layers = u_minify(dst->depth0, level); - - DBG("%s\n", __FUNCTION__); - - for (i = 0; i < layers; i++) { - struct pipe_box box; - u_box_2d_zslice(0, 0, face + i, - u_minify(dst->width0, level), - u_minify(dst->height0, level), - &box); - - pipe->transfer_inline_write(pipe, dst, level, PIPE_TRANSFER_WRITE, - &box, srcUB, src_row_stride, 0); - - srcUB += src_image_stride; - } -} - - /** * For debug only: get/print center pixel in the src resource. */ diff --git a/mesalib/src/mesa/state_tracker/st_texture.h b/mesalib/src/mesa/state_tracker/st_texture.h index 6b7f8c750..d8cd7c7b5 100644 --- a/mesalib/src/mesa/state_tracker/st_texture.h +++ b/mesalib/src/mesa/state_tracker/st_texture.h @@ -55,13 +55,7 @@ struct st_texture_image { struct gl_texture_image base; - /** Used to store texture data that doesn't fit in the parent - * object's mipmap buffer. - */ - GLubyte *TexData; - /* If stImage->pt != NULL, image data is stored here. - * Else if stImage->TexData != NULL, image is stored there. * Else there is no image data. */ struct pipe_resource *pt; @@ -230,16 +224,6 @@ st_texture_image_unmap(struct st_context *st, extern const GLuint * st_texture_depth_offsets(struct pipe_resource *pt, GLuint level); - -/* Upload an image into a texture - */ -extern void -st_texture_image_data(struct st_context *st, - struct pipe_resource *dst, - GLuint face, GLuint level, void *src, - GLuint src_row_pitch, GLuint src_image_pitch); - - /* Copy an image between two textures */ extern void diff --git a/mesalib/src/mesa/state_tracker/st_vdpau.c b/mesalib/src/mesa/state_tracker/st_vdpau.c index 6ccaf3e3f..63af1196a 100644 --- a/mesalib/src/mesa/state_tracker/st_vdpau.c +++ b/mesalib/src/mesa/state_tracker/st_vdpau.c @@ -66,7 +66,7 @@ st_vdpau_map_surface(struct gl_context *ctx, GLenum target, GLenum access, struct pipe_sampler_view templ, **sampler_view; mesa_format texFormat; - getProcAddr = ctx->vdpGetProcAddress; + getProcAddr = (void *)ctx->vdpGetProcAddress; if (output) { VdpOutputSurfaceGallium *f; diff --git a/mesalib/src/mesa/swrast/s_blend.c b/mesalib/src/mesa/swrast/s_blend.c index 7cb119407..8479b0bc0 100644 --- a/mesalib/src/mesa/swrast/s_blend.c +++ b/mesalib/src/mesa/swrast/s_blend.c @@ -48,9 +48,6 @@ #if defined(USE_MMX_ASM) #include "x86/mmx.h" #include "x86/common_x86_asm.h" -#define _BLENDAPI _ASMAPI -#else -#define _BLENDAPI #endif @@ -69,7 +66,7 @@ * No-op means the framebuffer values remain unchanged. * Any chanType ok. */ -static void _BLENDAPI +static void blend_noop(struct gl_context *ctx, GLuint n, const GLubyte mask[], GLvoid *src, const GLvoid *dst, GLenum chanType) { @@ -97,7 +94,7 @@ blend_noop(struct gl_context *ctx, GLuint n, const GLubyte mask[], * Special case for glBlendFunc(GL_ONE, GL_ZERO) * Any chanType ok. */ -static void _BLENDAPI +static void blend_replace(struct gl_context *ctx, GLuint n, const GLubyte mask[], GLvoid *src, const GLvoid *dst, GLenum chanType) { @@ -117,7 +114,7 @@ blend_replace(struct gl_context *ctx, GLuint n, const GLubyte mask[], * Common transparency blending mode: * glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA). */ -static void _BLENDAPI +static void blend_transparency_ubyte(struct gl_context *ctx, GLuint n, const GLubyte mask[], GLvoid *src, const GLvoid *dst, GLenum chanType) { @@ -162,7 +159,7 @@ blend_transparency_ubyte(struct gl_context *ctx, GLuint n, const GLubyte mask[], } -static void _BLENDAPI +static void blend_transparency_ushort(struct gl_context *ctx, GLuint n, const GLubyte mask[], GLvoid *src, const GLvoid *dst, GLenum chanType) { @@ -200,7 +197,7 @@ blend_transparency_ushort(struct gl_context *ctx, GLuint n, const GLubyte mask[] } -static void _BLENDAPI +static void blend_transparency_float(struct gl_context *ctx, GLuint n, const GLubyte mask[], GLvoid *src, const GLvoid *dst, GLenum chanType) { @@ -242,7 +239,7 @@ blend_transparency_float(struct gl_context *ctx, GLuint n, const GLubyte mask[], * Add src and dest: glBlendFunc(GL_ONE, GL_ONE). * Any chanType ok. */ -static void _BLENDAPI +static void blend_add(struct gl_context *ctx, GLuint n, const GLubyte mask[], GLvoid *src, const GLvoid *dst, GLenum chanType) { @@ -308,7 +305,7 @@ blend_add(struct gl_context *ctx, GLuint n, const GLubyte mask[], * Blend min function. * Any chanType ok. */ -static void _BLENDAPI +static void blend_min(struct gl_context *ctx, GLuint n, const GLubyte mask[], GLvoid *src, const GLvoid *dst, GLenum chanType) { @@ -361,7 +358,7 @@ blend_min(struct gl_context *ctx, GLuint n, const GLubyte mask[], * Blend max function. * Any chanType ok. */ -static void _BLENDAPI +static void blend_max(struct gl_context *ctx, GLuint n, const GLubyte mask[], GLvoid *src, const GLvoid *dst, GLenum chanType) { @@ -415,7 +412,7 @@ blend_max(struct gl_context *ctx, GLuint n, const GLubyte mask[], * Modulate: result = src * dest * Any chanType ok. */ -static void _BLENDAPI +static void blend_modulate(struct gl_context *ctx, GLuint n, const GLubyte mask[], GLvoid *src, const GLvoid *dst, GLenum chanType) { diff --git a/mesalib/src/mesa/swrast/s_context.c b/mesalib/src/mesa/swrast/s_context.c index 51cc22760..ecde292e3 100644 --- a/mesalib/src/mesa/swrast/s_context.c +++ b/mesalib/src/mesa/swrast/s_context.c @@ -409,7 +409,7 @@ _swrast_validate_point( struct gl_context *ctx, const SWvertex *v0 ) * Called via swrast->BlendFunc. Examine GL state to choose a blending * function, then call it. */ -static void _ASMAPI +static void _swrast_validate_blend_func(struct gl_context *ctx, GLuint n, const GLubyte mask[], GLvoid *src, const GLvoid *dst, GLenum chanType ) diff --git a/mesalib/src/mesa/swrast/s_context.h b/mesalib/src/mesa/swrast/s_context.h index d6fbc5d54..7cf0e30dc 100644 --- a/mesalib/src/mesa/swrast/s_context.h +++ b/mesalib/src/mesa/swrast/s_context.h @@ -58,10 +58,10 @@ typedef void (*texture_sample_func)(struct gl_context *ctx, GLuint n, const GLfloat texcoords[][4], const GLfloat lambda[], GLfloat rgba[][4]); -typedef void (_ASMAPIP blend_func)( struct gl_context *ctx, GLuint n, - const GLubyte mask[], - GLvoid *src, const GLvoid *dst, - GLenum chanType); +typedef void (*blend_func)(struct gl_context *ctx, GLuint n, + const GLubyte mask[], + GLvoid *src, const GLvoid *dst, + GLenum chanType); typedef void (*swrast_point_func)( struct gl_context *ctx, const SWvertex *); diff --git a/mesalib/src/mesa/swrast/s_span.c b/mesalib/src/mesa/swrast/s_span.c index 5d618f048..e304b6b5a 100644 --- a/mesalib/src/mesa/swrast/s_span.c +++ b/mesalib/src/mesa/swrast/s_span.c @@ -788,7 +788,7 @@ clip_span( struct gl_context *ctx, SWspan *span ) memmove(ARRAY, ARRAY + (SHIFT), (LEN) * sizeof(ARRAY[0])) for (i = 0; i < VARYING_SLOT_MAX; i++) { - if (span->arrayAttribs & (1 << i)) { + if (span->arrayAttribs & BITFIELD64_BIT(i)) { /* shift array elements left by 'leftClip' */ SHIFT_ARRAY(span->array->attribs[i], leftClip, n - leftClip); } diff --git a/mesalib/src/mesa/vbo/vbo_attrib_tmp.h b/mesalib/src/mesa/vbo/vbo_attrib_tmp.h index b1c3d9842..17e057836 100644 --- a/mesalib/src/mesa/vbo/vbo_attrib_tmp.h +++ b/mesalib/src/mesa/vbo/vbo_attrib_tmp.h @@ -30,35 +30,30 @@ USE OR OTHER DEALINGS IN THE SOFTWARE. /* ATTR */ -#define ATTR( A, N, T, V0, V1, V2, V3 ) \ - ATTR_##T((A), (N), (T), (V0), (V1), (V2), (V3)) - -#define ATTR_GL_UNSIGNED_INT( A, N, T, V0, V1, V2, V3 ) \ - ATTR_UNION(A, N, T, UINT_AS_UNION(V0), UINT_AS_UNION(V1), \ - UINT_AS_UNION(V2), UINT_AS_UNION(V3)) -#define ATTR_GL_INT( A, N, T, V0, V1, V2, V3 ) \ - ATTR_UNION(A, N, T, INT_AS_UNION(V0), INT_AS_UNION(V1), \ +#define ATTRI( A, N, V0, V1, V2, V3 ) \ + ATTR_UNION(A, N, GL_INT, INT_AS_UNION(V0), INT_AS_UNION(V1), \ INT_AS_UNION(V2), INT_AS_UNION(V3)) -#define ATTR_GL_FLOAT( A, N, T, V0, V1, V2, V3 ) \ - ATTR_UNION(A, N, T, FLOAT_AS_UNION(V0), FLOAT_AS_UNION(V1),\ +#define ATTRUI( A, N, V0, V1, V2, V3 ) \ + ATTR_UNION(A, N, GL_UNSIGNED_INT, 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),\ FLOAT_AS_UNION(V2), FLOAT_AS_UNION(V3)) /* float */ -#define ATTR1FV( A, V ) ATTR( A, 1, GL_FLOAT, (V)[0], 0, 0, 1 ) -#define ATTR2FV( A, V ) ATTR( A, 2, GL_FLOAT, (V)[0], (V)[1], 0, 1 ) -#define ATTR3FV( A, V ) ATTR( A, 3, GL_FLOAT, (V)[0], (V)[1], (V)[2], 1 ) -#define ATTR4FV( A, V ) ATTR( A, 4, GL_FLOAT, (V)[0], (V)[1], (V)[2], (V)[3] ) +#define ATTR1FV( A, V ) ATTRF( A, 1, (V)[0], 0, 0, 1 ) +#define ATTR2FV( A, V ) ATTRF( A, 2, (V)[0], (V)[1], 0, 1 ) +#define ATTR3FV( A, V ) ATTRF( A, 3, (V)[0], (V)[1], (V)[2], 1 ) +#define ATTR4FV( A, V ) ATTRF( A, 4, (V)[0], (V)[1], (V)[2], (V)[3] ) -#define ATTR1F( A, X ) ATTR( A, 1, GL_FLOAT, X, 0, 0, 1 ) -#define ATTR2F( A, X, Y ) ATTR( A, 2, GL_FLOAT, X, Y, 0, 1 ) -#define ATTR3F( A, X, Y, Z ) ATTR( A, 3, GL_FLOAT, X, Y, Z, 1 ) -#define ATTR4F( A, X, Y, Z, W ) ATTR( A, 4, GL_FLOAT, X, Y, Z, W ) +#define ATTR1F( A, X ) ATTRF( A, 1, X, 0, 0, 1 ) +#define ATTR2F( A, X, Y ) ATTRF( A, 2, X, Y, 0, 1 ) +#define ATTR3F( A, X, Y, Z ) ATTRF( A, 3, X, Y, Z, 1 ) +#define ATTR4F( A, X, Y, Z, W ) ATTRF( A, 4, X, Y, Z, W ) -/* int */ -#define ATTRI( A, N, X, Y, Z, W) ATTR( A, N, GL_INT, \ - X, Y, Z, W ) +/* int */ #define ATTR2IV( A, V ) ATTRI( A, 2, (V)[0], (V)[1], 0, 1 ) #define ATTR3IV( A, V ) ATTRI( A, 3, (V)[0], (V)[1], (V)[2], 1 ) #define ATTR4IV( A, V ) ATTRI( A, 4, (V)[0], (V)[1], (V)[2], (V)[3] ) @@ -70,9 +65,6 @@ USE OR OTHER DEALINGS IN THE SOFTWARE. /* uint */ -#define ATTRUI( A, N, X, Y, Z, W) ATTR( A, N, GL_UNSIGNED_INT, \ - X, Y, Z, W ) - #define ATTR2UIV( A, V ) ATTRUI( A, 2, (V)[0], (V)[1], 0, 1 ) #define ATTR3UIV( A, V ) ATTRUI( A, 3, (V)[0], (V)[1], (V)[2], 1 ) #define ATTR4UIV( A, V ) ATTRUI( A, 4, (V)[0], (V)[1], (V)[2], (V)[3] ) @@ -82,7 +74,7 @@ USE OR OTHER DEALINGS IN THE SOFTWARE. #define ATTR3UI( A, X, Y, Z ) ATTRUI( A, 3, X, Y, Z, 1 ) #define ATTR4UI( A, X, Y, Z, W ) ATTRUI( A, 4, X, Y, Z, W ) -#define MAT_ATTR( A, N, V ) ATTR( A, N, GL_FLOAT, (V)[0], (V)[1], (V)[2], (V)[3] ) +#define MAT_ATTR( A, N, V ) ATTRF( A, N, (V)[0], (V)[1], (V)[2], (V)[3] ) static inline float conv_ui10_to_norm_float(unsigned ui10) { @@ -94,20 +86,20 @@ static inline float conv_ui2_to_norm_float(unsigned ui2) return ui2 / 3.0f; } -#define ATTRUI10_1( A, UI ) ATTR( A, 1, GL_FLOAT, (UI) & 0x3ff, 0, 0, 1 ) -#define ATTRUI10_2( A, UI ) ATTR( A, 2, GL_FLOAT, (UI) & 0x3ff, ((UI) >> 10) & 0x3ff, 0, 1 ) -#define ATTRUI10_3( A, UI ) ATTR( A, 3, GL_FLOAT, (UI) & 0x3ff, ((UI) >> 10) & 0x3ff, ((UI) >> 20) & 0x3ff, 1 ) -#define ATTRUI10_4( A, UI ) ATTR( A, 4, GL_FLOAT, (UI) & 0x3ff, ((UI) >> 10) & 0x3ff, ((UI) >> 20) & 0x3ff, ((UI) >> 30) & 0x3 ) +#define ATTRUI10_1( A, UI ) ATTRF( A, 1, (UI) & 0x3ff, 0, 0, 1 ) +#define ATTRUI10_2( A, UI ) ATTRF( A, 2, (UI) & 0x3ff, ((UI) >> 10) & 0x3ff, 0, 1 ) +#define ATTRUI10_3( A, UI ) ATTRF( A, 3, (UI) & 0x3ff, ((UI) >> 10) & 0x3ff, ((UI) >> 20) & 0x3ff, 1 ) +#define ATTRUI10_4( A, UI ) ATTRF( A, 4, (UI) & 0x3ff, ((UI) >> 10) & 0x3ff, ((UI) >> 20) & 0x3ff, ((UI) >> 30) & 0x3 ) -#define ATTRUI10N_1( A, UI ) ATTR( A, 1, GL_FLOAT, conv_ui10_to_norm_float((UI) & 0x3ff), 0, 0, 1 ) -#define ATTRUI10N_2( A, UI ) ATTR( A, 2, GL_FLOAT, \ +#define ATTRUI10N_1( A, UI ) ATTRF( A, 1, conv_ui10_to_norm_float((UI) & 0x3ff), 0, 0, 1 ) +#define ATTRUI10N_2( A, UI ) ATTRF( A, 2, \ conv_ui10_to_norm_float((UI) & 0x3ff), \ conv_ui10_to_norm_float(((UI) >> 10) & 0x3ff), 0, 1 ) -#define ATTRUI10N_3( A, UI ) ATTR( A, 3, GL_FLOAT, \ +#define ATTRUI10N_3( A, UI ) ATTRF( A, 3, \ conv_ui10_to_norm_float((UI) & 0x3ff), \ conv_ui10_to_norm_float(((UI) >> 10) & 0x3ff), \ conv_ui10_to_norm_float(((UI) >> 20) & 0x3ff), 1 ) -#define ATTRUI10N_4( A, UI ) ATTR( A, 4, GL_FLOAT, \ +#define ATTRUI10N_4( A, UI ) ATTRF( A, 4, \ conv_ui10_to_norm_float((UI) & 0x3ff), \ conv_ui10_to_norm_float(((UI) >> 10) & 0x3ff), \ conv_ui10_to_norm_float(((UI) >> 20) & 0x3ff), \ @@ -180,30 +172,30 @@ static inline float conv_i2_to_norm_float(const struct gl_context *ctx, int i2) } } -#define ATTRI10_1( A, I10 ) ATTR( A, 1, GL_FLOAT, conv_i10_to_i((I10) & 0x3ff), 0, 0, 1 ) -#define ATTRI10_2( A, I10 ) ATTR( A, 2, GL_FLOAT, \ +#define ATTRI10_1( A, I10 ) ATTRF( A, 1, conv_i10_to_i((I10) & 0x3ff), 0, 0, 1 ) +#define ATTRI10_2( A, I10 ) ATTRF( A, 2, \ conv_i10_to_i((I10) & 0x3ff), \ conv_i10_to_i(((I10) >> 10) & 0x3ff), 0, 1 ) -#define ATTRI10_3( A, I10 ) ATTR( A, 3, GL_FLOAT, \ +#define ATTRI10_3( A, I10 ) ATTRF( A, 3, \ conv_i10_to_i((I10) & 0x3ff), \ conv_i10_to_i(((I10) >> 10) & 0x3ff), \ conv_i10_to_i(((I10) >> 20) & 0x3ff), 1 ) -#define ATTRI10_4( A, I10 ) ATTR( A, 4, GL_FLOAT, \ +#define ATTRI10_4( A, I10 ) ATTRF( A, 4, \ conv_i10_to_i((I10) & 0x3ff), \ conv_i10_to_i(((I10) >> 10) & 0x3ff), \ conv_i10_to_i(((I10) >> 20) & 0x3ff), \ conv_i2_to_i(((I10) >> 30) & 0x3)) -#define ATTRI10N_1(ctx, A, I10) ATTR(A, 1, GL_FLOAT, conv_i10_to_norm_float(ctx, (I10) & 0x3ff), 0, 0, 1 ) -#define ATTRI10N_2(ctx, A, I10) ATTR(A, 2, GL_FLOAT, \ +#define ATTRI10N_1(ctx, A, I10) ATTRF(A, 1, conv_i10_to_norm_float(ctx, (I10) & 0x3ff), 0, 0, 1 ) +#define ATTRI10N_2(ctx, A, I10) ATTRF(A, 2, \ conv_i10_to_norm_float(ctx, (I10) & 0x3ff), \ conv_i10_to_norm_float(ctx, ((I10) >> 10) & 0x3ff), 0, 1 ) -#define ATTRI10N_3(ctx, A, I10) ATTR(A, 3, GL_FLOAT, \ +#define ATTRI10N_3(ctx, A, I10) ATTRF(A, 3, \ conv_i10_to_norm_float(ctx, (I10) & 0x3ff), \ conv_i10_to_norm_float(ctx, ((I10) >> 10) & 0x3ff), \ conv_i10_to_norm_float(ctx, ((I10) >> 20) & 0x3ff), 1 ) -#define ATTRI10N_4(ctx, A, I10) ATTR(A, 4, GL_FLOAT, \ +#define ATTRI10N_4(ctx, A, I10) ATTRF(A, 4, \ conv_i10_to_norm_float(ctx, (I10) & 0x3ff), \ conv_i10_to_norm_float(ctx, ((I10) >> 10) & 0x3ff), \ conv_i10_to_norm_float(ctx, ((I10) >> 20) & 0x3ff), \ diff --git a/mesalib/src/mesa/vbo/vbo_exec_api.c b/mesalib/src/mesa/vbo/vbo_exec_api.c index 9669abe7d..02741c2bc 100644 --- a/mesalib/src/mesa/vbo/vbo_exec_api.c +++ b/mesalib/src/mesa/vbo/vbo_exec_api.c @@ -1239,7 +1239,7 @@ VertexAttrib4f_nopos(GLuint index, GLfloat x, GLfloat y, GLfloat z, GLfloat w) { GET_CURRENT_CONTEXT(ctx); if (index < MAX_VERTEX_GENERIC_ATTRIBS) - ATTR(VBO_ATTRIB_GENERIC0 + index, 4, GL_FLOAT, x, y, z, w); + ATTRF(VBO_ATTRIB_GENERIC0 + index, 4, x, y, z, w); else ERROR(GL_INVALID_VALUE); } diff --git a/mesalib/src/mesa/x86/3dnow.c b/mesalib/src/mesa/x86/3dnow.c index c46cfbc57..df7c64fcb 100644 --- a/mesalib/src/mesa/x86/3dnow.c +++ b/mesalib/src/mesa/x86/3dnow.c @@ -47,20 +47,20 @@ DECLARE_XFORM_GROUP( 3dnow, 3 ) DECLARE_XFORM_GROUP( 3dnow, 4 ) -extern void _ASMAPI +extern void _mesa_v16_3dnow_general_xform( GLfloat *first_vert, const GLfloat *m, const GLfloat *src, GLuint src_stride, GLuint count ); -extern void _ASMAPI +extern void _mesa_3dnow_project_vertices( GLfloat *first, GLfloat *last, const GLfloat *m, GLuint stride ); -extern void _ASMAPI +extern void _mesa_3dnow_project_clipped_vertices( GLfloat *first, GLfloat *last, const GLfloat *m, diff --git a/mesalib/src/mesa/x86/common_x86.c b/mesalib/src/mesa/x86/common_x86.c index 14b497d06..86fbca91e 100644 --- a/mesalib/src/mesa/x86/common_x86.c +++ b/mesalib/src/mesa/x86/common_x86.c @@ -68,12 +68,12 @@ static int detection_debug = GL_FALSE; /* No reason for this to be public. */ -extern GLuint _ASMAPI _mesa_x86_has_cpuid(void); -extern void _ASMAPI _mesa_x86_cpuid(GLuint op, GLuint *reg_eax, GLuint *reg_ebx, GLuint *reg_ecx, GLuint *reg_edx); -extern GLuint _ASMAPI _mesa_x86_cpuid_eax(GLuint op); -extern GLuint _ASMAPI _mesa_x86_cpuid_ebx(GLuint op); -extern GLuint _ASMAPI _mesa_x86_cpuid_ecx(GLuint op); -extern GLuint _ASMAPI _mesa_x86_cpuid_edx(GLuint op); +extern GLuint _mesa_x86_has_cpuid(void); +extern void _mesa_x86_cpuid(GLuint op, GLuint *reg_eax, GLuint *reg_ebx, GLuint *reg_ecx, GLuint *reg_edx); +extern GLuint _mesa_x86_cpuid_eax(GLuint op); +extern GLuint _mesa_x86_cpuid_ebx(GLuint op); +extern GLuint _mesa_x86_cpuid_ecx(GLuint op); +extern GLuint _mesa_x86_cpuid_edx(GLuint op); #if defined(USE_SSE_ASM) diff --git a/mesalib/src/mesa/x86/mmx.h b/mesalib/src/mesa/x86/mmx.h index 8101cf889..0c354907f 100644 --- a/mesalib/src/mesa/x86/mmx.h +++ b/mesalib/src/mesa/x86/mmx.h @@ -31,27 +31,27 @@ struct gl_context; -extern void _ASMAPI +extern void _mesa_mmx_blend_transparency( struct gl_context *ctx, GLuint n, const GLubyte mask[], GLvoid *rgba, const GLvoid *dest, GLenum chanType ); -extern void _ASMAPI +extern void _mesa_mmx_blend_add( struct gl_context *ctx, GLuint n, const GLubyte mask[], GLvoid *rgba, const GLvoid *dest, GLenum chanType ); -extern void _ASMAPI +extern void _mesa_mmx_blend_min( struct gl_context *ctx, GLuint n, const GLubyte mask[], GLvoid *rgba, const GLvoid *dest, GLenum chanType ); -extern void _ASMAPI +extern void _mesa_mmx_blend_max( struct gl_context *ctx, GLuint n, const GLubyte mask[], GLvoid *rgba, const GLvoid *dest, GLenum chanType ); -extern void _ASMAPI +extern void _mesa_mmx_blend_modulate( struct gl_context *ctx, GLuint n, const GLubyte mask[], GLvoid *rgba, const GLvoid *dest, GLenum chanType ); diff --git a/mesalib/src/mesa/x86/sse.c b/mesalib/src/mesa/x86/sse.c index 846184fa3..02fe18fa1 100644 --- a/mesalib/src/mesa/x86/sse.c +++ b/mesalib/src/mesa/x86/sse.c @@ -46,35 +46,35 @@ DECLARE_XFORM_GROUP( sse, 3 ) #if 1 /* Some functions are not written in SSE-assembly, because the fpu ones are faster */ -extern void _ASMAPI _mesa_sse_transform_normals_no_rot( NORM_ARGS ); -extern void _ASMAPI _mesa_sse_transform_rescale_normals( NORM_ARGS ); -extern void _ASMAPI _mesa_sse_transform_rescale_normals_no_rot( NORM_ARGS ); +extern void _mesa_sse_transform_normals_no_rot( NORM_ARGS ); +extern void _mesa_sse_transform_rescale_normals( NORM_ARGS ); +extern void _mesa_sse_transform_rescale_normals_no_rot( NORM_ARGS ); -extern void _ASMAPI _mesa_sse_transform_points4_general( XFORM_ARGS ); -extern void _ASMAPI _mesa_sse_transform_points4_3d( XFORM_ARGS ); +extern void _mesa_sse_transform_points4_general( XFORM_ARGS ); +extern void _mesa_sse_transform_points4_3d( XFORM_ARGS ); /* XXX this function segfaults, see below */ -extern void _ASMAPI _mesa_sse_transform_points4_identity( XFORM_ARGS ); +extern void _mesa_sse_transform_points4_identity( XFORM_ARGS ); /* XXX this one works, see below */ -extern void _ASMAPI _mesa_x86_transform_points4_identity( XFORM_ARGS ); +extern void _mesa_x86_transform_points4_identity( XFORM_ARGS ); #else DECLARE_NORM_GROUP( sse ) #endif -extern void _ASMAPI +extern void _mesa_v16_sse_general_xform( GLfloat *first_vert, const GLfloat *m, const GLfloat *src, GLuint src_stride, GLuint count ); -extern void _ASMAPI +extern void _mesa_sse_project_vertices( GLfloat *first, GLfloat *last, const GLfloat *m, GLuint stride ); -extern void _ASMAPI +extern void _mesa_sse_project_clipped_vertices( GLfloat *first, GLfloat *last, const GLfloat *m, diff --git a/mesalib/src/mesa/x86/x86_xform.c b/mesalib/src/mesa/x86/x86_xform.c index 007cd704d..8b5cf9139 100644 --- a/mesalib/src/mesa/x86/x86_xform.c +++ b/mesalib/src/mesa/x86/x86_xform.c @@ -54,7 +54,7 @@ DECLARE_XFORM_GROUP( x86, 3 ) DECLARE_XFORM_GROUP( x86, 4 ) -extern GLvector4f * _ASMAPI +extern GLvector4f * _mesa_x86_cliptest_points4( GLvector4f *clip_vec, GLvector4f *proj_vec, GLubyte clipMask[], @@ -62,7 +62,7 @@ _mesa_x86_cliptest_points4( GLvector4f *clip_vec, GLubyte *andMask, GLboolean viewport_z_clip ); -extern GLvector4f * _ASMAPI +extern GLvector4f * _mesa_x86_cliptest_points4_np( GLvector4f *clip_vec, GLvector4f *proj_vec, GLubyte clipMask[], @@ -70,7 +70,7 @@ _mesa_x86_cliptest_points4_np( GLvector4f *clip_vec, GLubyte *andMask, GLboolean viewport_z_clip ); -extern void _ASMAPI +extern void _mesa_v16_x86_cliptest_points4( GLfloat *first_vert, GLfloat *last_vert, GLubyte *or_mask, @@ -78,7 +78,7 @@ _mesa_v16_x86_cliptest_points4( GLfloat *first_vert, GLubyte *clip_mask, GLboolean viewport_z_clip ); -extern void _ASMAPI +extern void _mesa_v16_x86_general_xform( GLfloat *dest, const GLfloat *m, const GLfloat *src, diff --git a/mesalib/src/mesa/x86/x86_xform.h b/mesalib/src/mesa/x86/x86_xform.h index 12b9fb8ff..e398f64a4 100644 --- a/mesalib/src/mesa/x86/x86_xform.h +++ b/mesalib/src/mesa/x86/x86_xform.h @@ -39,13 +39,13 @@ const GLvector4f *from_vec #define DECLARE_XFORM_GROUP( pfx, sz ) \ -extern void _ASMAPI _mesa_##pfx##_transform_points##sz##_general( XFORM_ARGS ); \ -extern void _ASMAPI _mesa_##pfx##_transform_points##sz##_identity( XFORM_ARGS ); \ -extern void _ASMAPI _mesa_##pfx##_transform_points##sz##_3d_no_rot( XFORM_ARGS ); \ -extern void _ASMAPI _mesa_##pfx##_transform_points##sz##_perspective( XFORM_ARGS ); \ -extern void _ASMAPI _mesa_##pfx##_transform_points##sz##_2d( XFORM_ARGS ); \ -extern void _ASMAPI _mesa_##pfx##_transform_points##sz##_2d_no_rot( XFORM_ARGS ); \ -extern void _ASMAPI _mesa_##pfx##_transform_points##sz##_3d( XFORM_ARGS ); +extern void _mesa_##pfx##_transform_points##sz##_general( XFORM_ARGS ); \ +extern void _mesa_##pfx##_transform_points##sz##_identity( XFORM_ARGS ); \ +extern void _mesa_##pfx##_transform_points##sz##_3d_no_rot( XFORM_ARGS ); \ +extern void _mesa_##pfx##_transform_points##sz##_perspective( XFORM_ARGS ); \ +extern void _mesa_##pfx##_transform_points##sz##_2d( XFORM_ARGS ); \ +extern void _mesa_##pfx##_transform_points##sz##_2d_no_rot( XFORM_ARGS ); \ +extern void _mesa_##pfx##_transform_points##sz##_3d( XFORM_ARGS ); #define ASSIGN_XFORM_GROUP( pfx, sz ) \ _mesa_transform_tab[sz][MATRIX_GENERAL] = \ @@ -75,14 +75,14 @@ extern void _ASMAPI _mesa_##pfx##_transform_points##sz##_3d( XFORM_ARGS ); GLvector4f *dest #define DECLARE_NORM_GROUP( pfx ) \ -extern void _ASMAPI _mesa_##pfx##_rescale_normals( NORM_ARGS ); \ -extern void _ASMAPI _mesa_##pfx##_normalize_normals( NORM_ARGS ); \ -extern void _ASMAPI _mesa_##pfx##_transform_normals( NORM_ARGS ); \ -extern void _ASMAPI _mesa_##pfx##_transform_normals_no_rot( NORM_ARGS ); \ -extern void _ASMAPI _mesa_##pfx##_transform_rescale_normals( NORM_ARGS ); \ -extern void _ASMAPI _mesa_##pfx##_transform_rescale_normals_no_rot( NORM_ARGS ); \ -extern void _ASMAPI _mesa_##pfx##_transform_normalize_normals( NORM_ARGS ); \ -extern void _ASMAPI _mesa_##pfx##_transform_normalize_normals_no_rot( NORM_ARGS ); +extern void _mesa_##pfx##_rescale_normals( NORM_ARGS ); \ +extern void _mesa_##pfx##_normalize_normals( NORM_ARGS ); \ +extern void _mesa_##pfx##_transform_normals( NORM_ARGS ); \ +extern void _mesa_##pfx##_transform_normals_no_rot( NORM_ARGS ); \ +extern void _mesa_##pfx##_transform_rescale_normals( NORM_ARGS ); \ +extern void _mesa_##pfx##_transform_rescale_normals_no_rot( NORM_ARGS ); \ +extern void _mesa_##pfx##_transform_normalize_normals( NORM_ARGS ); \ +extern void _mesa_##pfx##_transform_normalize_normals_no_rot( NORM_ARGS ); #define ASSIGN_NORM_GROUP( pfx ) \ _mesa_normal_tab[NORM_RESCALE] = \ diff --git a/mesalib/src/util/Makefile.am b/mesalib/src/util/Makefile.am index ec49dc6cf..2e7542e42 100644 --- a/mesalib/src/util/Makefile.am +++ b/mesalib/src/util/Makefile.am @@ -50,7 +50,9 @@ endif libmesautil_la_LIBADD = $(SHA1_LIBS) -check_PROGRAMS = u_atomic_test +roundeven_test_LDADD = -lm + +check_PROGRAMS = u_atomic_test roundeven_test TESTS = $(check_PROGRAMS) BUILT_SOURCES = $(MESA_UTIL_GENERATED_FILES) diff --git a/mesalib/src/util/Makefile.sources b/mesalib/src/util/Makefile.sources index 560ea836a..3e0d02bad 100644 --- a/mesalib/src/util/Makefile.sources +++ b/mesalib/src/util/Makefile.sources @@ -14,6 +14,7 @@ MESA_UTIL_FILES := \ register_allocate.h \ rgtc.c \ rgtc.h \ + rounding.h \ set.c \ set.h \ simple_list.h \ diff --git a/mesalib/src/util/macros.h b/mesalib/src/util/macros.h index b862bfd5f..6c7bda7ae 100644 --- a/mesalib/src/util/macros.h +++ b/mesalib/src/util/macros.h @@ -73,15 +73,13 @@ do { \ assert(!str); \ __builtin_unreachable(); \ } while (0) -#elif _MSC_VER >= 1200 +#elif defined (_MSC_VER) #define unreachable(str) \ do { \ assert(!str); \ __assume(0); \ } while (0) -#endif - -#ifndef unreachable +#else #define unreachable(str) assert(!str) #endif @@ -99,7 +97,7 @@ do { \ #define assume(expr) ((expr) ? ((void) 0) \ : (assert(!"assumption failed"), \ __builtin_unreachable())) -#elif _MSC_VER >= 1200 +#elif defined (_MSC_VER) #define assume(expr) __assume(expr) #else #define assume(expr) assert(expr) @@ -178,5 +176,11 @@ do { \ # endif #endif +#ifdef HAVE_FUNC_ATTRIBUTE_UNUSED +#define UNUSED __attribute__((unused)) +#else +#define UNUSED +#endif + #endif /* UTIL_MACROS_H */ diff --git a/mesalib/src/util/roundeven_test.c b/mesalib/src/util/roundeven_test.c new file mode 100644 index 000000000..7526db1f3 --- /dev/null +++ b/mesalib/src/util/roundeven_test.c @@ -0,0 +1,140 @@ +/* + * Copyright © 2015 Intel Corporation + * + * 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 (including the next + * paragraph) 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. + */ + +#include <stdio.h> +#include <stdbool.h> +#include <string.h> +#include <math.h> + +#include "macros.h" +#include "rounding.h" + +int main(int argc, char *argv[]) +{ + const struct { + float input, expected; + } float_data[] = { + { 0.0, 0.0 }, + { nextafterf(0.5, 0.0), 0.0 }, + { 0.5, 0.0 }, + { nextafterf(0.5, 1.0), 1.0 }, + { 1.0, 1.0 }, + { nextafterf(1.5, 1.0), 1.0 }, + { 1.5, 2.0 }, + { nextafterf(1.5, 2.0), 2.0 }, + { 2.0, 2.0 }, + { nextafterf(2.5, 2.0), 2.0 }, + { 2.5, 2.0 }, + { nextafterf(2.5, 3.0), 3.0 }, + }; + + const struct { + double input, expected; + } double_data[] = { + { 0.0, 0.0 }, + { nextafter(0.5, 0.0), 0.0 }, + { 0.5, 0.0 }, + { nextafter(0.5, 1.0), 1.0 }, + { 1.0, 1.0 }, + { nextafter(1.5, 1.0), 1.0 }, + { 1.5, 2.0 }, + { nextafter(1.5, 2.0), 2.0 }, + { 2.0, 2.0 }, + { nextafter(2.5, 2.0), 2.0 }, + { 2.5, 2.0 }, + { nextafter(2.5, 3.0), 3.0 }, + }; + + bool failed = false; + int i; + + for (i = 0; i < ARRAY_SIZE(float_data); i++) { + float output = _mesa_roundevenf(float_data[i].input); + if (memcmp(&float_data[i].expected, &output, sizeof(float))) { + fprintf(stderr, "%d float: expected %f (%a) from " + "_mesa_roundevenf(%f (%a)) but got %f (%a)\n", + i, + float_data[i].expected, + float_data[i].expected, + float_data[i].input, + float_data[i].input, + output, + output); + failed = true; + } + } + + /* Test negated values */ + for (i = 0; i < ARRAY_SIZE(float_data); i++) { + float output = _mesa_roundevenf(-float_data[i].input); + float negated_expected = -float_data[i].expected; + if (memcmp(&negated_expected, &output, sizeof(float))) { + fprintf(stderr, "%d float: expected %f (%a) from " + "_mesa_roundevenf(%f (%a)) but got %f (%a)\n", + i, + negated_expected, + negated_expected, + -float_data[i].input, + -float_data[i].input, + output, + output); + failed = true; + } + } + + for (i = 0; i < ARRAY_SIZE(double_data); i++) { + double output = _mesa_roundeven(double_data[i].input); + if (memcmp(&double_data[i].expected, &output, sizeof(double))) { + fprintf(stderr, "%d double: expected %f (%a) from " + "_mesa_roundeven(%f (%a)) but got %f (%a)\n", + i, + double_data[i].expected, + double_data[i].expected, + double_data[i].input, + double_data[i].input, + output, + output); + failed = true; + } + } + + /* Test negated values */ + for (i = 0; i < ARRAY_SIZE(double_data); i++) { + double output = _mesa_roundeven(-double_data[i].input); + double negated_expected = -double_data[i].expected; + if (memcmp(&negated_expected, &output, sizeof(double))) { + fprintf(stderr, "%d double: expected %f (%a) from " + "_mesa_roundeven(%f (%a)) but got %f (%a)\n", + i, + negated_expected, + negated_expected, + -double_data[i].input, + -double_data[i].input, + output, + output); + failed = true; + } + } + + return failed; +} diff --git a/mesalib/src/util/rounding.h b/mesalib/src/util/rounding.h new file mode 100644 index 000000000..0cbe9269f --- /dev/null +++ b/mesalib/src/util/rounding.h @@ -0,0 +1,78 @@ +/* + * Copyright © 2015 Intel Corporation + * + * 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 (including the next + * paragraph) 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. + */ + +#include <math.h> + +#ifdef __SSE4_1__ +#include <smmintrin.h> +#endif + +/* The C standard library has functions round()/rint()/nearbyint() that round + * their arguments according to the rounding mode set in the floating-point + * control register. While there are trunc()/ceil()/floor() functions that do + * a specific operation without modifying the rounding mode, there is no + * roundeven() in any version of C. + * + * Technical Specification 18661 (ISO/IEC TS 18661-1:2014) adds roundeven(), + * but it's unfortunately not implemented by glibc. + * + * This implementation differs in that it does not raise the inexact exception. + * + * We use rint() to implement these functions, with the assumption that the + * floating-point rounding mode has not been changed from the default Round + * to Nearest. + */ + +/** + * \brief Rounds \c x to the nearest integer, with ties to the even integer. + */ +static inline float +_mesa_roundevenf(float x) +{ +#ifdef __SSE4_1__ + float ret; + __m128 m = _mm_load_ss(&x); + m = _mm_round_ss(m, m, _MM_FROUND_CUR_DIRECTION | _MM_FROUND_NO_EXC); + _mm_store_ss(&ret, m); + return ret; +#else + return rintf(x); +#endif +} + +/** + * \brief Rounds \c x to the nearest integer, with ties to the even integer. + */ +static inline double +_mesa_roundeven(double x) +{ +#ifdef __SSE4_1__ + double ret; + __m128d m = _mm_load_sd(&x); + m = _mm_round_sd(m, m, _MM_FROUND_CUR_DIRECTION | _MM_FROUND_NO_EXC); + _mm_store_sd(&ret, m); + return ret; +#else + return rint(x); +#endif +} diff --git a/mesalib/src/util/u_atomic.h b/mesalib/src/util/u_atomic.h index d15398e1e..e38395ac6 100644 --- a/mesalib/src/util/u_atomic.h +++ b/mesalib/src/util/u_atomic.h @@ -6,6 +6,8 @@ * */ +#include "no_extern_c.h" + #ifndef U_ATOMIC_H #define U_ATOMIC_H |