diff options
Diffstat (limited to 'mesalib/src')
142 files changed, 5685 insertions, 5817 deletions
diff --git a/mesalib/src/Makefile.am b/mesalib/src/Makefile.am index d4a7090dc..cede5083a 100644 --- a/mesalib/src/Makefile.am +++ b/mesalib/src/Makefile.am @@ -19,7 +19,7 @@ # FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS # IN THE SOFTWARE. -SUBDIRS = gtest mapi +SUBDIRS = gtest util mapi if NEED_OPENGL_COMMON SUBDIRS += glsl mesa diff --git a/mesalib/src/SConscript b/mesalib/src/SConscript index 93a490dca..2657bba47 100644 --- a/mesalib/src/SConscript +++ b/mesalib/src/SConscript @@ -4,6 +4,7 @@ Import('*') if env['platform'] == 'windows': SConscript('getopt/SConscript') +SConscript('util/SConscript') SConscript('glsl/SConscript') if env['hostonly']: diff --git a/mesalib/src/gallium/Automake.inc b/mesalib/src/gallium/Automake.inc index 73d65a4d1..74053eb2d 100644 --- a/mesalib/src/gallium/Automake.inc +++ b/mesalib/src/gallium/Automake.inc @@ -1,5 +1,6 @@ GALLIUM_CFLAGS = \ -I$(top_srcdir)/include \ + -I$(top_srcdir)/src \ -I$(top_srcdir)/src/gallium/include \ -I$(top_srcdir)/src/gallium/auxiliary \ $(DEFINES) @@ -10,6 +11,7 @@ GALLIUM_CFLAGS = \ # preprocessor is determined by the ordering of the -I flags. GALLIUM_DRIVER_CFLAGS = \ -I$(srcdir)/include \ + -I$(top_srcdir)/src \ -I$(top_srcdir)/include \ -I$(top_srcdir)/src/gallium/include \ -I$(top_srcdir)/src/gallium/auxiliary \ @@ -19,6 +21,7 @@ GALLIUM_DRIVER_CFLAGS = \ GALLIUM_DRIVER_CXXFLAGS = \ -I$(srcdir)/include \ + -I$(top_srcdir)/src \ -I$(top_srcdir)/include \ -I$(top_srcdir)/src/gallium/include \ -I$(top_srcdir)/src/gallium/auxiliary \ diff --git a/mesalib/src/gallium/SConscript b/mesalib/src/gallium/SConscript index 8d9849e00..cb6172007 100644 --- a/mesalib/src/gallium/SConscript +++ b/mesalib/src/gallium/SConscript @@ -71,6 +71,10 @@ if env['dri']: ]) SConscript([ + 'winsys/sw/kms-dri/SConscript', + ]) + + SConscript([ 'winsys/svga/drm/SConscript', ]) diff --git a/mesalib/src/gallium/auxiliary/Makefile.am b/mesalib/src/gallium/auxiliary/Makefile.am index 727ed1f98..493d306f6 100644 --- a/mesalib/src/gallium/auxiliary/Makefile.am +++ b/mesalib/src/gallium/auxiliary/Makefile.am @@ -39,10 +39,6 @@ indices/u_unfilled_gen.c: $(srcdir)/indices/u_unfilled_gen.py $(AM_V_at)$(MKDIR_P) indices $(AM_V_GEN) $(PYTHON2) $< > $@ -util/u_format_srgb.c: $(srcdir)/util/u_format_srgb.py - $(AM_V_at)$(MKDIR_P) util - $(AM_V_GEN) $(PYTHON2) $< > $@ - util/u_format_table.c: $(srcdir)/util/u_format_table.py $(srcdir)/util/u_format_pack.py $(srcdir)/util/u_format_parse.py $(srcdir)/util/u_format.csv $(AM_V_at)$(MKDIR_P) util $(AM_V_GEN) $(PYTHON2) $(srcdir)/util/u_format_table.py $(srcdir)/util/u_format.csv > $@ diff --git a/mesalib/src/gallium/auxiliary/Makefile.sources b/mesalib/src/gallium/auxiliary/Makefile.sources index 8919783c2..3eae9e525 100644 --- a/mesalib/src/gallium/auxiliary/Makefile.sources +++ b/mesalib/src/gallium/auxiliary/Makefile.sources @@ -162,7 +162,6 @@ C_SOURCES := \ GENERATED_SOURCES := \ indices/u_indices_gen.c \ indices/u_unfilled_gen.c \ - util/u_format_srgb.c \ util/u_format_table.c GALLIVM_SOURCES := \ diff --git a/mesalib/src/gallium/auxiliary/SConscript b/mesalib/src/gallium/auxiliary/SConscript index 31dfed316..94041d247 100644 --- a/mesalib/src/gallium/auxiliary/SConscript +++ b/mesalib/src/gallium/auxiliary/SConscript @@ -3,6 +3,7 @@ Import('*') from sys import executable as python_cmd env.Append(CPPPATH = [ + '#src', 'indices', 'util', ]) @@ -22,13 +23,6 @@ env.CodeGenerate( ) env.CodeGenerate( - target = 'util/u_format_srgb.c', - script = 'util/u_format_srgb.py', - source = [], - command = python_cmd + ' $SCRIPT > $TARGET' -) - -env.CodeGenerate( target = 'util/u_format_table.c', script = '#src/gallium/auxiliary/util/u_format_table.py', source = ['#src/gallium/auxiliary/util/u_format.csv'], diff --git a/mesalib/src/gallium/auxiliary/util/u_caps.c b/mesalib/src/gallium/auxiliary/util/u_caps.c index 623070755..ec8938b37 100644 --- a/mesalib/src/gallium/auxiliary/util/u_caps.c +++ b/mesalib/src/gallium/auxiliary/util/u_caps.c @@ -198,13 +198,13 @@ static unsigned caps_sm3[] = { UTIL_CHECK_SHADER(FRAGMENT, MAX_INPUTS, 10), UTIL_CHECK_SHADER(FRAGMENT, MAX_TEMPS, 32), UTIL_CHECK_SHADER(FRAGMENT, MAX_ADDRS, 1), - UTIL_CHECK_SHADER(FRAGMENT, MAX_CONSTS, 224), + UTIL_CHECK_SHADER(FRAGMENT, MAX_CONST_BUFFER_SIZE, 224 * 16), UTIL_CHECK_SHADER(VERTEX, MAX_INSTRUCTIONS, 512), UTIL_CHECK_SHADER(VERTEX, MAX_INPUTS, 16), UTIL_CHECK_SHADER(VERTEX, MAX_TEMPS, 32), UTIL_CHECK_SHADER(VERTEX, MAX_ADDRS, 2), - UTIL_CHECK_SHADER(VERTEX, MAX_CONSTS, 256), + UTIL_CHECK_SHADER(VERTEX, MAX_CONST_BUFFER_SIZE, 256 * 16), UTIL_CHECK_TERMINATE }; diff --git a/mesalib/src/gallium/auxiliary/util/u_format_pack.py b/mesalib/src/gallium/auxiliary/util/u_format_pack.py index f9496de6c..a553e2346 100644 --- a/mesalib/src/gallium/auxiliary/util/u_format_pack.py +++ b/mesalib/src/gallium/auxiliary/util/u_format_pack.py @@ -669,7 +669,7 @@ def generate(formats): print '#include "u_half.h"' print '#include "u_format.h"' print '#include "u_format_other.h"' - print '#include "u_format_srgb.h"' + print '#include "util/format_srgb.h"' print '#include "u_format_yuv.h"' print '#include "u_format_zs.h"' print diff --git a/mesalib/src/gallium/auxiliary/util/u_format_s3tc.c b/mesalib/src/gallium/auxiliary/util/u_format_s3tc.c index 11b46020b..7e05989e6 100644 --- a/mesalib/src/gallium/auxiliary/util/u_format_s3tc.c +++ b/mesalib/src/gallium/auxiliary/util/u_format_s3tc.c @@ -27,7 +27,7 @@ #include "u_math.h" #include "u_format.h" #include "u_format_s3tc.h" -#include "u_format_srgb.h" +#include "util/format_srgb.h" #if defined(_WIN32) || defined(WIN32) diff --git a/mesalib/src/gallium/auxiliary/util/u_math.h b/mesalib/src/gallium/auxiliary/util/u_math.h index f6dcb228f..2823e0570 100644 --- a/mesalib/src/gallium/auxiliary/util/u_math.h +++ b/mesalib/src/gallium/auxiliary/util/u_math.h @@ -616,6 +616,14 @@ fui( float f ) return fi.ui; } +static INLINE float +uif(uint32_t ui) +{ + union fi fi; + fi.ui = ui; + return fi.f; +} + /** * Convert ubyte to float in [0, 1]. @@ -817,7 +825,7 @@ util_memcpy_cpu_to_le32(void * restrict dest, const void * restrict src, size_t { #ifdef PIPE_ARCH_BIG_ENDIAN size_t i, e; - asset(n % 4 == 0); + assert(n % 4 == 0); for (i = 0, e = n / 4; i < e; i++) { uint32_t * restrict d = (uint32_t* restrict)dest; diff --git a/mesalib/src/gallium/auxiliary/util/u_prim.h b/mesalib/src/gallium/auxiliary/util/u_prim.h index fd95c0ba0..cf1a18f42 100644 --- a/mesalib/src/gallium/auxiliary/util/u_prim.h +++ b/mesalib/src/gallium/auxiliary/util/u_prim.h @@ -136,6 +136,21 @@ u_prim_vertex_count(unsigned prim) return (likely(prim < PIPE_PRIM_MAX)) ? &prim_table[prim] : NULL; } +/** + * Given a vertex count, return the number of primitives. + * For polygons, return the number of triangles. + */ +static INLINE unsigned +u_prims_for_vertices(unsigned prim, unsigned num) +{ + const struct u_prim_vertex_count *info = u_prim_vertex_count(prim); + + if (num < info->min) + return 0; + + return 1 + ((num - info->min) / info->incr); +} + static INLINE boolean u_validate_pipe_prim( unsigned pipe_prim, unsigned nr ) { const struct u_prim_vertex_count *count = u_prim_vertex_count(pipe_prim); diff --git a/mesalib/src/glsl/.gitignore b/mesalib/src/glsl/.gitignore index 43720f60b..dda423f83 100644 --- a/mesalib/src/glsl/.gitignore +++ b/mesalib/src/glsl/.gitignore @@ -4,3 +4,7 @@ glsl_parser.cpp glsl_parser.h glsl_parser.output glsl_test +subtest-cr/ +subtest-lf/ +subtest-cr-lf/ +subtest-lf-cr/ diff --git a/mesalib/src/glsl/Makefile.am b/mesalib/src/glsl/Makefile.am index 00261fd0d..0ccc81d75 100644 --- a/mesalib/src/glsl/Makefile.am +++ b/mesalib/src/glsl/Makefile.am @@ -21,6 +21,7 @@ AM_CPPFLAGS = \ -I$(top_srcdir)/include \ + -I$(top_srcdir)/src \ -I$(top_srcdir)/src/mapi \ -I$(top_srcdir)/src/mesa/ \ -I$(top_srcdir)/src/glsl/glcpp \ @@ -32,9 +33,9 @@ AM_CXXFLAGS = $(VISIBILITY_CXXFLAGS) include Makefile.sources TESTS = glcpp/tests/glcpp-test \ + glcpp/tests/glcpp-test-cr-lf \ tests/general-ir-test \ tests/optimization-test \ - tests/ralloc-test \ tests/sampler-types-test \ tests/uniform-initializer-test @@ -47,14 +48,12 @@ check_PROGRAMS = \ glcpp/glcpp \ glsl_test \ tests/general-ir-test \ - tests/ralloc-test \ tests/sampler-types-test \ tests/uniform-initializer-test noinst_PROGRAMS = glsl_compiler tests_general_ir_test_SOURCES = \ - $(top_srcdir)/src/mesa/main/hash_table.c \ $(top_srcdir)/src/mesa/main/imports.c \ $(top_srcdir)/src/mesa/program/prog_hash_table.c\ $(top_srcdir)/src/mesa/program/symbol_table.c \ @@ -72,7 +71,6 @@ tests_general_ir_test_LDADD = \ $(PTHREAD_LIBS) tests_uniform_initializer_test_SOURCES = \ - $(top_srcdir)/src/mesa/main/hash_table.c \ $(top_srcdir)/src/mesa/main/imports.c \ $(top_srcdir)/src/mesa/program/prog_hash_table.c\ $(top_srcdir)/src/mesa/program/symbol_table.c \ @@ -87,14 +85,6 @@ tests_uniform_initializer_test_LDADD = \ $(top_builddir)/src/glsl/libglsl.la \ $(PTHREAD_LIBS) -tests_ralloc_test_SOURCES = \ - tests/ralloc_test.cpp \ - $(top_builddir)/src/glsl/ralloc.c -tests_ralloc_test_CFLAGS = $(PTHREAD_CFLAGS) -tests_ralloc_test_LDADD = \ - $(top_builddir)/src/gtest/libgtest.la \ - $(PTHREAD_LIBS) - tests_sampler_types_test_SOURCES = \ $(top_srcdir)/src/mesa/program/prog_hash_table.c\ $(top_srcdir)/src/mesa/program/symbol_table.c \ @@ -107,6 +97,8 @@ tests_sampler_types_test_LDADD = \ $(top_builddir)/src/glsl/libglsl.la \ $(PTHREAD_LIBS) +libglcpp_la_LIBADD = \ + $(top_builddir)/src/util/libmesautil.la libglcpp_la_SOURCES = \ glcpp/glcpp-lex.c \ glcpp/glcpp-parse.c \ @@ -127,7 +119,6 @@ libglsl_la_SOURCES = \ $(LIBGLSL_FILES) glsl_compiler_SOURCES = \ - $(top_srcdir)/src/mesa/main/hash_table.c \ $(top_srcdir)/src/mesa/main/imports.c \ $(top_srcdir)/src/mesa/program/prog_hash_table.c \ $(top_srcdir)/src/mesa/program/symbol_table.c \ @@ -138,7 +129,6 @@ glsl_compiler_LDADD = \ $(PTHREAD_LIBS) glsl_test_SOURCES = \ - $(top_srcdir)/src/mesa/main/hash_table.c \ $(top_srcdir)/src/mesa/main/imports.c \ $(top_srcdir)/src/mesa/program/prog_hash_table.c \ $(top_srcdir)/src/mesa/program/symbol_table.c \ diff --git a/mesalib/src/glsl/Makefile.sources b/mesalib/src/glsl/Makefile.sources index b54eae72d..2131ddafb 100644 --- a/mesalib/src/glsl/Makefile.sources +++ b/mesalib/src/glsl/Makefile.sources @@ -6,7 +6,6 @@ GLSL_BUILDDIR = $(top_builddir)/src/glsl # libglcpp LIBGLCPP_FILES = \ - $(GLSL_SRCDIR)/ralloc.c \ $(GLSL_SRCDIR)/glcpp/pp.c LIBGLCPP_GENERATED_FILES = \ diff --git a/mesalib/src/glsl/SConscript b/mesalib/src/glsl/SConscript index dc354775a..847e96246 100644 --- a/mesalib/src/glsl/SConscript +++ b/mesalib/src/glsl/SConscript @@ -8,12 +8,15 @@ env = env.Clone() env.Prepend(CPPPATH = [ '#include', + '#src', '#src/mapi', '#src/mesa', '#src/glsl', '#src/glsl/glcpp', ]) +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]) @@ -55,7 +58,6 @@ if env['msvc']: # Copy these files to avoid generation object files into src/mesa/program env.Prepend(CPPPATH = ['#src/mesa/main']) -env.Command('hash_table.c', '#src/mesa/main/hash_table.c', Copy('$TARGET', '$SOURCE')) env.Command('imports.c', '#src/mesa/main/imports.c', Copy('$TARGET', '$SOURCE')) # Copy these files to avoid generation object files into src/mesa/program env.Prepend(CPPPATH = ['#src/mesa/program']) @@ -65,7 +67,6 @@ env.Command('symbol_table.c', '#src/mesa/program/symbol_table.c', Copy('$TARGET' compiler_objs = env.StaticObject(source_lists['GLSL_COMPILER_CXX_FILES']) mesa_objs = env.StaticObject([ - 'hash_table.c', 'imports.c', 'prog_hash_table.c', 'symbol_table.c', diff --git a/mesalib/src/glsl/ast_function.cpp b/mesalib/src/glsl/ast_function.cpp index 4981fe174..39c7beeb2 100644 --- a/mesalib/src/glsl/ast_function.cpp +++ b/mesalib/src/glsl/ast_function.cpp @@ -450,20 +450,21 @@ match_function_by_name(const char *name, goto done; /* no match */ if (f != NULL) { + /* In desktop GL, the presence of a user-defined signature hides any + * built-in signatures, so we must ignore them. In contrast, in ES2 + * user-defined signatures add new overloads, so we must consider them. + */ + bool allow_builtins = state->es_shader || !f->has_user_signature(); + /* Look for a match in the local shader. If exact, we're done. */ bool is_exact = false; sig = local_sig = f->matching_signature(state, actual_parameters, - &is_exact); + allow_builtins, &is_exact); if (is_exact) goto done; - if (!state->es_shader && f->has_user_signature()) { - /* In desktop GL, the presence of a user-defined signature hides any - * built-in signatures, so we must ignore them. In contrast, in ES2 - * user-defined signatures add new overloads, so we must proceed. - */ + if (!allow_builtins) goto done; - } } /* Local shader has no exact candidates; check the built-ins. */ diff --git a/mesalib/src/glsl/ast_to_hir.cpp b/mesalib/src/glsl/ast_to_hir.cpp index a15ee9c05..30b02d016 100644 --- a/mesalib/src/glsl/ast_to_hir.cpp +++ b/mesalib/src/glsl/ast_to_hir.cpp @@ -4110,12 +4110,27 @@ ast_function::hir(exec_list *instructions, name); } + /* Create an ir_function if one doesn't already exist. */ + f = state->symbols->get_function(name); + if (f == NULL) { + f = new(ctx) ir_function(name); + if (!state->symbols->add_function(f)) { + /* This function name shadows a non-function use of the same name. */ + YYLTYPE loc = this->get_location(); + + _mesa_glsl_error(&loc, state, "function name `%s' conflicts with " + "non-function", name); + return NULL; + } + + emit_function(state, f); + } + /* Verify that this function's signature either doesn't match a previously * seen signature for a function with the same name, or, if a match is found, * that the previously seen signature does not have an associated definition. */ - f = state->symbols->get_function(name); - if (f != NULL && (state->es_shader || f->has_user_signature())) { + if (state->es_shader || f->has_user_signature()) { sig = f->exact_matching_signature(state, &hir_parameters); if (sig != NULL) { const char *badvar = sig->qualifiers_match(&hir_parameters); @@ -4146,18 +4161,6 @@ ast_function::hir(exec_list *instructions, } } } - } else { - f = new(ctx) ir_function(name); - if (!state->symbols->add_function(f)) { - /* This function name shadows a non-function use of the same name. */ - YYLTYPE loc = this->get_location(); - - _mesa_glsl_error(&loc, state, "function name `%s' conflicts with " - "non-function", name); - return NULL; - } - - emit_function(state, f); } /* Verify the return type of main() */ @@ -4597,12 +4600,6 @@ ast_case_statement_list::hir(exec_list *instructions, */ if (!default_case.is_empty()) { - /* Default case was the last one, no checks required. */ - if (after_default.is_empty()) { - instructions->append_list(&default_case); - return NULL; - } - ir_rvalue *const true_val = new (state) ir_constant(true); ir_dereference_variable *deref_run_default_var = new(state) ir_dereference_variable(state->switch_state.run_default); @@ -4614,6 +4611,12 @@ ast_case_statement_list::hir(exec_list *instructions, new(state) ir_assignment(deref_run_default_var, true_val); instructions->push_tail(init_var); + /* Default case was the last one, no checks required. */ + if (after_default.is_empty()) { + instructions->append_list(&default_case); + return NULL; + } + foreach_in_list(ir_instruction, ir, &after_default) { ir_assignment *assign = ir->as_assignment(); @@ -5072,7 +5075,7 @@ ast_process_structure_or_interface_block(exec_list *instructions, YYLTYPE &loc, glsl_struct_field **fields_ret, bool is_interface, - bool block_row_major, + enum glsl_matrix_layout matrix_layout, bool allow_reserved_names, ir_variable_mode var_mode) { @@ -5203,13 +5206,29 @@ ast_process_structure_or_interface_block(exec_list *instructions, "in uniform blocks or structures."); } - if (field_type->is_matrix() || - (field_type->is_array() && field_type->fields.array->is_matrix())) { - fields[i].row_major = block_row_major; + /* Propogate row- / column-major information down the fields of the + * structure or interface block. Structures need this data because + * the structure may contain a structure that contains ... a matrix + * that need the proper layout. + */ + if (field_type->without_array()->is_matrix() + || field_type->without_array()->is_record()) { + /* If no layout is specified for the field, inherit the layout + * from the block. + */ + fields[i].matrix_layout = matrix_layout; + if (qual->flags.q.row_major) - fields[i].row_major = true; + fields[i].matrix_layout = GLSL_MATRIX_LAYOUT_ROW_MAJOR; else if (qual->flags.q.column_major) - fields[i].row_major = false; + fields[i].matrix_layout = GLSL_MATRIX_LAYOUT_COLUMN_MAJOR; + + /* If we're processing an interface block, the matrix layout must + * be decided by this point. + */ + assert(!is_interface + || fields[i].matrix_layout == GLSL_MATRIX_LAYOUT_ROW_MAJOR + || fields[i].matrix_layout == GLSL_MATRIX_LAYOUT_COLUMN_MAJOR); } i++; @@ -5264,7 +5283,7 @@ ast_struct_specifier::hir(exec_list *instructions, loc, &fields, false, - false, + GLSL_MATRIX_LAYOUT_INHERITED, false /* allow_reserved_names */, ir_var_auto); @@ -5364,8 +5383,13 @@ ast_interface_block::hir(exec_list *instructions, assert(!"interface block layout qualifier not found!"); } + enum glsl_matrix_layout matrix_layout = GLSL_MATRIX_LAYOUT_INHERITED; + if (this->layout.flags.q.row_major) + matrix_layout = GLSL_MATRIX_LAYOUT_ROW_MAJOR; + else if (this->layout.flags.q.column_major) + matrix_layout = GLSL_MATRIX_LAYOUT_COLUMN_MAJOR; + bool redeclaring_per_vertex = strcmp(this->block_name, "gl_PerVertex") == 0; - bool block_row_major = this->layout.flags.q.row_major; exec_list declared_variables; glsl_struct_field *fields; @@ -5381,7 +5405,7 @@ ast_interface_block::hir(exec_list *instructions, loc, &fields, true, - block_row_major, + matrix_layout, redeclaring_per_vertex, var_mode); @@ -5589,6 +5613,9 @@ ast_interface_block::hir(exec_list *instructions, var_mode); } + var->data.matrix_layout = matrix_layout == GLSL_MATRIX_LAYOUT_INHERITED + ? GLSL_MATRIX_LAYOUT_COLUMN_MAJOR : matrix_layout; + if (state->stage == MESA_SHADER_GEOMETRY && var_mode == ir_var_shader_in) handle_geometry_shader_input_decl(state, loc, var); @@ -5629,6 +5656,13 @@ ast_interface_block::hir(exec_list *instructions, var->data.sample = fields[i].sample; var->init_interface_type(block_type); + if (fields[i].matrix_layout == GLSL_MATRIX_LAYOUT_INHERITED) { + var->data.matrix_layout = matrix_layout == GLSL_MATRIX_LAYOUT_INHERITED + ? GLSL_MATRIX_LAYOUT_COLUMN_MAJOR : matrix_layout; + } else { + var->data.matrix_layout = fields[i].matrix_layout; + } + if (fields[i].stream != -1 && ((unsigned)fields[i].stream) != this->layout.stream) { _mesa_glsl_error(&loc, state, diff --git a/mesalib/src/glsl/builtin_functions.cpp b/mesalib/src/glsl/builtin_functions.cpp index e01742c4d..185fe98b3 100644 --- a/mesalib/src/glsl/builtin_functions.cpp +++ b/mesalib/src/glsl/builtin_functions.cpp @@ -706,7 +706,8 @@ builtin_builder::find(_mesa_glsl_parse_state *state, if (f == NULL) return NULL; - ir_function_signature *sig = f->matching_signature(state, actual_parameters); + ir_function_signature *sig = + f->matching_signature(state, actual_parameters, true); if (sig == NULL) return NULL; diff --git a/mesalib/src/glsl/builtin_types.cpp b/mesalib/src/glsl/builtin_types.cpp index 0a0fa8cd3..10fac0f81 100644 --- a/mesalib/src/glsl/builtin_types.cpp +++ b/mesalib/src/glsl/builtin_types.cpp @@ -36,6 +36,7 @@ #include "glsl_types.h" #include "glsl_parser_extras.h" +#include "util/macros.h" /** * Declarations of type flyweights (glsl_type::_foo_type) and @@ -48,69 +49,69 @@ #define STRUCT_TYPE(NAME) \ const glsl_type glsl_type::_struct_##NAME##_type = \ - glsl_type(NAME##_fields, Elements(NAME##_fields), #NAME); \ + glsl_type(NAME##_fields, ARRAY_SIZE(NAME##_fields), #NAME); \ const glsl_type *const glsl_type::struct_##NAME##_type = \ &glsl_type::_struct_##NAME##_type; static const struct glsl_struct_field gl_DepthRangeParameters_fields[] = { - { glsl_type::float_type, "near", false, -1 }, - { glsl_type::float_type, "far", false, -1 }, - { glsl_type::float_type, "diff", false, -1 }, + { glsl_type::float_type, "near", -1, 0, 0, 0, GLSL_MATRIX_LAYOUT_INHERITED, 0 }, + { glsl_type::float_type, "far", -1, 0, 0, 0, GLSL_MATRIX_LAYOUT_INHERITED, 0 }, + { glsl_type::float_type, "diff", -1, 0, 0, 0, GLSL_MATRIX_LAYOUT_INHERITED, 0 }, }; static const struct glsl_struct_field gl_PointParameters_fields[] = { - { glsl_type::float_type, "size", false, -1 }, - { glsl_type::float_type, "sizeMin", false, -1 }, - { glsl_type::float_type, "sizeMax", false, -1 }, - { glsl_type::float_type, "fadeThresholdSize", false, -1 }, - { glsl_type::float_type, "distanceConstantAttenuation", false, -1 }, - { glsl_type::float_type, "distanceLinearAttenuation", false, -1 }, - { glsl_type::float_type, "distanceQuadraticAttenuation", false, -1 }, + { glsl_type::float_type, "size", -1, 0, 0, 0, GLSL_MATRIX_LAYOUT_INHERITED, 0 }, + { glsl_type::float_type, "sizeMin", -1, 0, 0, 0, GLSL_MATRIX_LAYOUT_INHERITED, 0 }, + { glsl_type::float_type, "sizeMax", -1, 0, 0, 0, GLSL_MATRIX_LAYOUT_INHERITED, 0 }, + { glsl_type::float_type, "fadeThresholdSize", -1, 0, 0, 0, GLSL_MATRIX_LAYOUT_INHERITED, 0 }, + { glsl_type::float_type, "distanceConstantAttenuation", -1, 0, 0, 0, GLSL_MATRIX_LAYOUT_INHERITED, 0 }, + { glsl_type::float_type, "distanceLinearAttenuation", -1, 0, 0, 0, GLSL_MATRIX_LAYOUT_INHERITED, 0 }, + { glsl_type::float_type, "distanceQuadraticAttenuation", -1, 0, 0, 0, GLSL_MATRIX_LAYOUT_INHERITED, 0 }, }; static const struct glsl_struct_field gl_MaterialParameters_fields[] = { - { glsl_type::vec4_type, "emission", false, -1 }, - { glsl_type::vec4_type, "ambient", false, -1 }, - { glsl_type::vec4_type, "diffuse", false, -1 }, - { glsl_type::vec4_type, "specular", false, -1 }, - { glsl_type::float_type, "shininess", false, -1 }, + { glsl_type::vec4_type, "emission", -1, 0, 0, 0, GLSL_MATRIX_LAYOUT_INHERITED, 0 }, + { glsl_type::vec4_type, "ambient", -1, 0, 0, 0, GLSL_MATRIX_LAYOUT_INHERITED, 0 }, + { glsl_type::vec4_type, "diffuse", -1, 0, 0, 0, GLSL_MATRIX_LAYOUT_INHERITED, 0 }, + { glsl_type::vec4_type, "specular", -1, 0, 0, 0, GLSL_MATRIX_LAYOUT_INHERITED, 0 }, + { glsl_type::float_type, "shininess", -1, 0, 0, 0, GLSL_MATRIX_LAYOUT_INHERITED, 0 }, }; static const struct glsl_struct_field gl_LightSourceParameters_fields[] = { - { glsl_type::vec4_type, "ambient", false, -1 }, - { glsl_type::vec4_type, "diffuse", false, -1 }, - { glsl_type::vec4_type, "specular", false, -1 }, - { glsl_type::vec4_type, "position", false, -1 }, - { glsl_type::vec4_type, "halfVector", false, -1 }, - { glsl_type::vec3_type, "spotDirection", false, -1 }, - { glsl_type::float_type, "spotExponent", false, -1 }, - { glsl_type::float_type, "spotCutoff", false, -1 }, - { glsl_type::float_type, "spotCosCutoff", false, -1 }, - { glsl_type::float_type, "constantAttenuation", false, -1 }, - { glsl_type::float_type, "linearAttenuation", false, -1 }, - { glsl_type::float_type, "quadraticAttenuation", false, -1 }, + { glsl_type::vec4_type, "ambient", -1, 0, 0, 0, GLSL_MATRIX_LAYOUT_INHERITED, 0 }, + { glsl_type::vec4_type, "diffuse", -1, 0, 0, 0, GLSL_MATRIX_LAYOUT_INHERITED, 0 }, + { glsl_type::vec4_type, "specular", -1, 0, 0, 0, GLSL_MATRIX_LAYOUT_INHERITED, 0 }, + { glsl_type::vec4_type, "position", -1, 0, 0, 0, GLSL_MATRIX_LAYOUT_INHERITED, 0 }, + { glsl_type::vec4_type, "halfVector", -1, 0, 0, 0, GLSL_MATRIX_LAYOUT_INHERITED, 0 }, + { glsl_type::vec3_type, "spotDirection", -1, 0, 0, 0, GLSL_MATRIX_LAYOUT_INHERITED, 0 }, + { glsl_type::float_type, "spotExponent", -1, 0, 0, 0, GLSL_MATRIX_LAYOUT_INHERITED, 0 }, + { glsl_type::float_type, "spotCutoff", -1, 0, 0, 0, GLSL_MATRIX_LAYOUT_INHERITED, 0 }, + { glsl_type::float_type, "spotCosCutoff", -1, 0, 0, 0, GLSL_MATRIX_LAYOUT_INHERITED, 0 }, + { glsl_type::float_type, "constantAttenuation", -1, 0, 0, 0, GLSL_MATRIX_LAYOUT_INHERITED, 0 }, + { glsl_type::float_type, "linearAttenuation", -1, 0, 0, 0, GLSL_MATRIX_LAYOUT_INHERITED, 0 }, + { glsl_type::float_type, "quadraticAttenuation", -1, 0, 0, 0, GLSL_MATRIX_LAYOUT_INHERITED, 0 }, }; static const struct glsl_struct_field gl_LightModelParameters_fields[] = { - { glsl_type::vec4_type, "ambient", false, -1 }, + { glsl_type::vec4_type, "ambient", -1, 0, 0, 0, GLSL_MATRIX_LAYOUT_INHERITED, 0 }, }; static const struct glsl_struct_field gl_LightModelProducts_fields[] = { - { glsl_type::vec4_type, "sceneColor", false, -1 }, + { glsl_type::vec4_type, "sceneColor", -1, 0, 0, 0, GLSL_MATRIX_LAYOUT_INHERITED, 0 }, }; static const struct glsl_struct_field gl_LightProducts_fields[] = { - { glsl_type::vec4_type, "ambient", false, -1 }, - { glsl_type::vec4_type, "diffuse", false, -1 }, - { glsl_type::vec4_type, "specular", false, -1 }, + { glsl_type::vec4_type, "ambient", -1, 0, 0, 0, GLSL_MATRIX_LAYOUT_INHERITED, 0 }, + { glsl_type::vec4_type, "diffuse", -1, 0, 0, 0, GLSL_MATRIX_LAYOUT_INHERITED, 0 }, + { glsl_type::vec4_type, "specular", -1, 0, 0, 0, GLSL_MATRIX_LAYOUT_INHERITED, 0 }, }; static const struct glsl_struct_field gl_FogParameters_fields[] = { - { glsl_type::vec4_type, "color", false, -1 }, - { glsl_type::float_type, "density", false, -1 }, - { glsl_type::float_type, "start", false, -1 }, - { glsl_type::float_type, "end", false, -1 }, - { glsl_type::float_type, "scale", false, -1 }, + { glsl_type::vec4_type, "color", -1, 0, 0, 0, GLSL_MATRIX_LAYOUT_INHERITED, 0 }, + { glsl_type::float_type, "density", -1, 0, 0, 0, GLSL_MATRIX_LAYOUT_INHERITED, 0 }, + { glsl_type::float_type, "start", -1, 0, 0, 0, GLSL_MATRIX_LAYOUT_INHERITED, 0 }, + { glsl_type::float_type, "end", -1, 0, 0, 0, GLSL_MATRIX_LAYOUT_INHERITED, 0 }, + { glsl_type::float_type, "scale", -1, 0, 0, 0, GLSL_MATRIX_LAYOUT_INHERITED, 0 }, }; #include "builtin_type_macros.h" @@ -265,7 +266,7 @@ _mesa_glsl_initialize_types(struct _mesa_glsl_parse_state *state) { struct glsl_symbol_table *symbols = state->symbols; - for (unsigned i = 0; i < Elements(builtin_type_versions); i++) { + for (unsigned i = 0; i < ARRAY_SIZE(builtin_type_versions); i++) { const struct builtin_type_versions *const t = &builtin_type_versions[i]; if (state->is_version(t->min_gl, t->min_es)) { add_type(symbols, t->type); @@ -276,7 +277,7 @@ _mesa_glsl_initialize_types(struct _mesa_glsl_parse_state *state) * they're still present. We've removed them in 1.40+ (OpenGL 3.1+). */ if (!state->es_shader && state->language_version < 140) { - for (unsigned i = 0; i < Elements(deprecated_types); i++) { + for (unsigned i = 0; i < ARRAY_SIZE(deprecated_types); i++) { add_type(symbols, deprecated_types[i]); } } diff --git a/mesalib/src/glsl/builtin_variables.cpp b/mesalib/src/glsl/builtin_variables.cpp index 4c5b9c070..5b6f4ae62 100644 --- a/mesalib/src/glsl/builtin_variables.cpp +++ b/mesalib/src/glsl/builtin_variables.cpp @@ -317,7 +317,7 @@ per_vertex_accumulator::add_field(int slot, const glsl_type *type, assert(this->num_fields < ARRAY_SIZE(this->fields)); this->fields[this->num_fields].type = type; this->fields[this->num_fields].name = name; - this->fields[this->num_fields].row_major = false; + this->fields[this->num_fields].matrix_layout = GLSL_MATRIX_LAYOUT_INHERITED; this->fields[this->num_fields].location = slot; this->fields[this->num_fields].interpolation = INTERP_QUALIFIER_NONE; this->fields[this->num_fields].centroid = 0; diff --git a/mesalib/src/glsl/glcpp/glcpp-lex.l b/mesalib/src/glsl/glcpp/glcpp-lex.l index a1a8e76af..98d500ec0 100644 --- a/mesalib/src/glsl/glcpp/glcpp-lex.l +++ b/mesalib/src/glsl/glcpp/glcpp-lex.l @@ -52,14 +52,107 @@ void glcpp_set_column (int column_no , yyscan_t yyscanner); yylloc->last_column = yycolumn + 1; \ parser->has_new_line_number = 0; \ parser->has_new_source_number = 0; \ - } while(0); + } while(0); #define YY_USER_INIT \ do { \ yylineno = 1; \ - yycolumn = 1; \ + yycolumn = 0; \ yylloc->source = 0; \ } while(0) + +/* It's ugly to have macros that have return statements inside of + * them, but flex-based lexer generation is all built around the + * return statement. + * + * To mitigate the ugliness, we defer as much of the logic as possible + * to an actual function, not a macro (see + * glcpplex_update_state_per_token) and we make the word RETURN + * prominent in all of the macros which may return. + * + * The most-commonly-used macro is RETURN_TOKEN which will perform all + * necessary state updates based on the provided token,, then + * conditionally return the token. It will not return a token if the + * parser is currently skipping tokens, (such as within #if + * 0...#else). + * + * The RETURN_TOKEN_NEVER_SKIP macro is a lower-level variant that + * makes the token returning unconditional. This is needed for things + * like #if and the tokens of its condition, (since these must be + * evaluated by the parser even when otherwise skipping). + * + * Finally, RETURN_STRING_TOKEN is a simple convenience wrapper on top + * of RETURN_TOKEN that performs a string copy of yytext before the + * return. + */ +#define RETURN_TOKEN_NEVER_SKIP(token) \ + do { \ + if (glcpp_lex_update_state_per_token (parser, token)) \ + return token; \ + } while (0) + +#define RETURN_TOKEN(token) \ + do { \ + if (! parser->skipping) { \ + RETURN_TOKEN_NEVER_SKIP(token); \ + } \ + } while(0) + +#define RETURN_STRING_TOKEN(token) \ + do { \ + if (! parser->skipping) { \ + yylval->str = ralloc_strdup (yyextra, yytext); \ + RETURN_TOKEN_NEVER_SKIP (token); \ + } \ + } while(0) + + +/* Update all state necessary for each token being returned. + * + * Here we'll be tracking newlines and spaces so that the lexer can + * alter its behavior as necessary, (for example, '#' has special + * significance if it is the first non-whitespace, non-comment token + * in a line, but does not otherwise). + * + * NOTE: If this function returns FALSE, then no token should be + * returned at all. This is used to suprress duplicate SPACE tokens. + */ +static int +glcpp_lex_update_state_per_token (glcpp_parser_t *parser, int token) +{ + /* After the first non-space token in a line, we won't + * allow any '#' to introduce a directive. */ + if (token == NEWLINE) { + parser->first_non_space_token_this_line = 1; + } else if (token != SPACE) { + parser->first_non_space_token_this_line = 0; + } + + /* Track newlines just to know whether a newline needs + * to be inserted if end-of-file comes early. */ + if (token == NEWLINE) { + parser->last_token_was_newline = 1; + } else { + parser->last_token_was_newline = 0; + } + + /* Track spaces to avoid emitting multiple SPACE + * tokens in a row. */ + if (token == SPACE) { + if (! parser->last_token_was_space) { + parser->last_token_was_space = 1; + return 1; + } else { + parser->last_token_was_space = 1; + return 0; + } + } else { + parser->last_token_was_space = 0; + return 1; + } +} + + %} %option bison-bridge bison-locations reentrant noyywrap @@ -67,14 +160,19 @@ void glcpp_set_column (int column_no , yyscan_t yyscanner); %option prefix="glcpp_" %option stack %option never-interactive +%option warn nodefault + + /* Note: When adding any start conditions to this list, you must also + * update the "Internal compiler error" catch-all rule near the end of + * this file. */ -%x DONE COMMENT UNREACHABLE SKIP DEFINE NEWLINE_CATCHUP +%x COMMENT DEFINE DONE HASH NEWLINE_CATCHUP UNREACHABLE SPACE [[:space:]] NONSPACE [^[:space:]] -NEWLINE [\n] HSPACE [ \t] -HASH ^{HSPACE}*#{HSPACE}* +HASH # +NEWLINE (\r\n|\n\r|\r|\n) IDENTIFIER [_a-zA-Z][_a-zA-Z0-9]* PP_NUMBER [.]?[0-9]([._a-zA-Z0-9]|[eEpP][-+])* PUNCTUATION [][(){}.&*~!/%<>^|;,=+-] @@ -111,270 +209,357 @@ HEXADECIMAL_INTEGER 0[xX][0-9a-fA-F]+[uU]? parser->commented_newlines--; if (parser->commented_newlines == 0) BEGIN INITIAL; - return NEWLINE; + RETURN_TOKEN_NEVER_SKIP (NEWLINE); } - /* The handling of the SKIP vs INITIAL start states requires - * some special handling. Typically, a lexer would change - * start states with statements like "BEGIN SKIP" within the - * lexer rules. We can't get away with that here, since we - * need the parser to actually evaluate expressions for - * directives like "#if". + /* Set up the parser->skipping bit here before doing any lexing. + * + * This bit controls whether tokens are skipped, (as implemented by + * RETURN_TOKEN), such as between "#if 0" and "#endif". * - * So, here, in code that will be executed on every call to - * the lexer,and before any rules, we examine the skip_stack - * as set by the parser to know whether to change from INITIAL - * to SKIP or from SKIP back to INITIAL. + * The parser maintains a skip_stack indicating whether we should be + * skipping, (and nested levels of #if/#ifdef/#ifndef/#endif) will + * push and pop items from the stack. * - * Three cases cause us to switch out of the SKIP state and - * back to the INITIAL state: + * Here are the rules for determining whether we are skipping: * - * 1. The top of the skip_stack is of type SKIP_NO_SKIP - * This means we're still evaluating some #if - * hierarchy, but we're on a branch of it where - * content should not be skipped (such as "#if 1" or - * "#else" or so). + * 1. If the skip stack is NULL, we are outside of all #if blocks + * and we are not skipping. * - * 2. The skip_stack is NULL meaning that we've reached - * the last #endif. + * 2. If the skip stack is non-NULL, the type of the top node in + * the stack determines whether to skip. A type of + * SKIP_NO_SKIP is used for blocks wheere we are emitting + * tokens, (such as between #if 1 and #endif, or after the + * #else of an #if 0, etc.). * - * 3. The lexing_directive bit is set. This indicates that we are - * lexing a pre-processor directive, (such as #if, #elif, or - * #else). For the #if and #elif directives we always need to - * parse the conditions, (even if otherwise within an #if - * 0). And for #else, we want to be able to generate an error - * if any garbage follows #else. + * 3. The lexing_directive bit overrides the skip stack. This bit + * is set when we are actively lexing the expression for a + * pre-processor condition, (such as #if, #elif, or #else). In + * this case, even if otherwise skipping, we need to emit the + * tokens for this condition so that the parser can evaluate + * the expression. (For, #else, there's no expression, but we + * emit tokens so the parser can generate a nice error message + * if there are any tokens here). */ - if (YY_START == INITIAL || YY_START == SKIP) { - if (parser->lexing_directive || - parser->skip_stack == NULL || - parser->skip_stack->type == SKIP_NO_SKIP) - { - BEGIN INITIAL; - } else { - BEGIN SKIP; - } + if (parser->skip_stack && + parser->skip_stack->type != SKIP_NO_SKIP && + ! parser->lexing_directive) + { + parser->skipping = 1; + } else { + parser->skipping = 0; } /* Single-line comments */ -"//"[^\n]* { +<INITIAL,DEFINE,HASH>"//"[^\r\n]* { } /* Multi-line comments */ -"/*" { yy_push_state(COMMENT, yyscanner); } -<COMMENT>[^*\n]* -<COMMENT>[^*\n]*\n { yylineno++; yycolumn = 0; parser->commented_newlines++; } -<COMMENT>"*"+[^*/\n]* -<COMMENT>"*"+[^*/\n]*\n { yylineno++; yycolumn = 0; parser->commented_newlines++; } +<INITIAL,DEFINE,HASH>"/*" { yy_push_state(COMMENT, yyscanner); } +<COMMENT>[^*\r\n]* +<COMMENT>[^*\r\n]*{NEWLINE} { yylineno++; yycolumn = 0; parser->commented_newlines++; } +<COMMENT>"*"+[^*/\r\n]* +<COMMENT>"*"+[^*/\r\n]*{NEWLINE} { yylineno++; yycolumn = 0; parser->commented_newlines++; } <COMMENT>"*"+"/" { yy_pop_state(yyscanner); - if (yyextra->space_tokens) - return SPACE; + /* In the <HASH> start condition, we don't want any SPACE token. */ + if (yyextra->space_tokens && YY_START != HASH) + RETURN_TOKEN (SPACE); +} + +{HASH} { + + /* If the '#' is the first non-whitespace, non-comment token on this + * line, then it introduces a directive, switch to the <HASH> start + * condition. + * + * Otherwise, this is just punctuation, so return the HASH_TOKEN + * token. */ + if (parser->first_non_space_token_this_line) { + BEGIN HASH; + } + + RETURN_TOKEN_NEVER_SKIP (HASH_TOKEN); } -{HASH}version{HSPACE}+ { - yylval->str = ralloc_strdup (yyextra, yytext); +<HASH>version{HSPACE}+ { + BEGIN INITIAL; yyextra->space_tokens = 0; - return HASH_VERSION; + RETURN_STRING_TOKEN (VERSION_TOKEN); +} + + /* Swallow empty #pragma directives, (to avoid confusing the + * downstream compiler). */ +<HASH>pragma{HSPACE}*/{NEWLINE} { + BEGIN INITIAL; } /* glcpp doesn't handle #extension, #version, or #pragma directives. * Simply pass them through to the main compiler's lexer/parser. */ -{HASH}(extension|pragma)[^\n]* { - if (parser->commented_newlines) - BEGIN NEWLINE_CATCHUP; - yylval->str = ralloc_strdup (yyextra, yytext); - yylineno++; - yycolumn = 0; - return OTHER; +<HASH>(extension|pragma)[^\r\n]* { + BEGIN INITIAL; + RETURN_STRING_TOKEN (PRAGMA); } -{HASH}line{HSPACE}+ { - return HASH_LINE; +<HASH>line{HSPACE}+ { + BEGIN INITIAL; + RETURN_TOKEN (LINE); } -<SKIP,INITIAL>{ -{HASH}ifdef { +<HASH>{NEWLINE} { + BEGIN INITIAL; + RETURN_TOKEN_NEVER_SKIP (NEWLINE); +} + + /* For the pre-processor directives, we return these tokens + * even when we are otherwise skipping. */ +<HASH>ifdef { + BEGIN INITIAL; yyextra->lexing_directive = 1; yyextra->space_tokens = 0; - return HASH_IFDEF; + RETURN_TOKEN_NEVER_SKIP (IFDEF); } -{HASH}ifndef { +<HASH>ifndef { + BEGIN INITIAL; yyextra->lexing_directive = 1; yyextra->space_tokens = 0; - return HASH_IFNDEF; + RETURN_TOKEN_NEVER_SKIP (IFNDEF); } -{HASH}if/[^_a-zA-Z0-9] { +<HASH>if/[^_a-zA-Z0-9] { + BEGIN INITIAL; yyextra->lexing_directive = 1; yyextra->space_tokens = 0; - return HASH_IF; + RETURN_TOKEN_NEVER_SKIP (IF); } -{HASH}elif/[^_a-zA-Z0-9] { +<HASH>elif/[^_a-zA-Z0-9] { + BEGIN INITIAL; yyextra->lexing_directive = 1; yyextra->space_tokens = 0; - return HASH_ELIF; + RETURN_TOKEN_NEVER_SKIP (ELIF); } -{HASH}else { +<HASH>else { + BEGIN INITIAL; yyextra->space_tokens = 0; - return HASH_ELSE; + RETURN_TOKEN_NEVER_SKIP (ELSE); } -{HASH}endif { +<HASH>endif { + BEGIN INITIAL; yyextra->space_tokens = 0; - return HASH_ENDIF; -} + RETURN_TOKEN_NEVER_SKIP (ENDIF); } -<SKIP>[^\n] { - if (parser->commented_newlines) - BEGIN NEWLINE_CATCHUP; +<HASH>error[^\r\n]* { + BEGIN INITIAL; + RETURN_STRING_TOKEN (ERROR_TOKEN); } -{HASH}error.* { - char *p; - for (p = yytext; !isalpha(p[0]); p++); /* skip " # " */ - p += 5; /* skip "error" */ - glcpp_error(yylloc, yyextra, "#error%s", p); + /* After we see a "#define" we enter the <DEFINE> start state + * for the lexer. Within <DEFINE> we are looking for the first + * identifier and specifically checking whether the identifier + * is followed by a '(' or not, (to lex either a + * FUNC_IDENTIFIER or an OBJ_IDENITIFIER token). + * + * While in the <DEFINE> state we also need to explicitly + * handle a few other things that may appear before the + * identifier: + * + * * Comments, (handled above with the main support for + * comments). + * + * * Whitespace (simply ignored) + * + * * Anything else, (not an identifier, not a comment, + * and not whitespace). This will generate an error. + */ +<HASH>define{HSPACE}* { + if (! parser->skipping) { + BEGIN DEFINE; + yyextra->space_tokens = 0; + RETURN_TOKEN (DEFINE_TOKEN); + } } -{HASH}define{HSPACE}+ { +<HASH>undef { + BEGIN INITIAL; yyextra->space_tokens = 0; - yy_push_state(DEFINE, yyscanner); - return HASH_DEFINE; + RETURN_TOKEN (UNDEF); } +<HASH>{HSPACE}+ { + /* Nothing to do here. Importantly, don't leave the <HASH> + * start condition, since it's legal to have space between the + * '#' and the directive.. */ +} + + /* This will catch any non-directive garbage after a HASH */ +<HASH>{NONSPACE} { + BEGIN INITIAL; + RETURN_TOKEN (GARBAGE); +} + + /* An identifier immediately followed by '(' */ <DEFINE>{IDENTIFIER}/"(" { - yy_pop_state(yyscanner); - yylval->str = ralloc_strdup (yyextra, yytext); - return FUNC_IDENTIFIER; + BEGIN INITIAL; + RETURN_STRING_TOKEN (FUNC_IDENTIFIER); } + /* An identifier not immediately followed by '(' */ <DEFINE>{IDENTIFIER} { - yy_pop_state(yyscanner); - yylval->str = ralloc_strdup (yyextra, yytext); - return OBJ_IDENTIFIER; + BEGIN INITIAL; + RETURN_STRING_TOKEN (OBJ_IDENTIFIER); } -{HASH}undef { - yyextra->space_tokens = 0; - return HASH_UNDEF; + /* Whitespace */ +<DEFINE>{HSPACE}+ { + /* Just ignore it. Nothing to do here. */ } -{HASH} { - yyextra->space_tokens = 0; - return HASH; + /* '/' not followed by '*', so not a comment. This is an error. */ +<DEFINE>[/][^*]{NONSPACE}* { + BEGIN INITIAL; + glcpp_error(yylloc, yyextra, "#define followed by a non-identifier: %s", yytext); + RETURN_STRING_TOKEN (INTEGER_STRING); +} + + /* A character that can't start an identifier, comment, or + * space. This is an error. */ +<DEFINE>[^_a-zA-Z/[:space:]]{NONSPACE}* { + BEGIN INITIAL; + glcpp_error(yylloc, yyextra, "#define followed by a non-identifier: %s", yytext); + RETURN_STRING_TOKEN (INTEGER_STRING); } {DECIMAL_INTEGER} { - yylval->str = ralloc_strdup (yyextra, yytext); - return INTEGER_STRING; + RETURN_STRING_TOKEN (INTEGER_STRING); } {OCTAL_INTEGER} { - yylval->str = ralloc_strdup (yyextra, yytext); - return INTEGER_STRING; + RETURN_STRING_TOKEN (INTEGER_STRING); } {HEXADECIMAL_INTEGER} { - yylval->str = ralloc_strdup (yyextra, yytext); - return INTEGER_STRING; + RETURN_STRING_TOKEN (INTEGER_STRING); } "<<" { - return LEFT_SHIFT; + RETURN_TOKEN (LEFT_SHIFT); } ">>" { - return RIGHT_SHIFT; + RETURN_TOKEN (RIGHT_SHIFT); } "<=" { - return LESS_OR_EQUAL; + RETURN_TOKEN (LESS_OR_EQUAL); } ">=" { - return GREATER_OR_EQUAL; + RETURN_TOKEN (GREATER_OR_EQUAL); } "==" { - return EQUAL; + RETURN_TOKEN (EQUAL); } "!=" { - return NOT_EQUAL; + RETURN_TOKEN (NOT_EQUAL); } "&&" { - return AND; + RETURN_TOKEN (AND); } "||" { - return OR; + RETURN_TOKEN (OR); +} + +"++" { + RETURN_TOKEN (PLUS_PLUS); +} + +"--" { + RETURN_TOKEN (MINUS_MINUS); } "##" { - if (parser->is_gles) - glcpp_error(yylloc, yyextra, "Token pasting (##) is illegal in GLES"); - return PASTE; + if (! parser->skipping) { + if (parser->is_gles) + glcpp_error(yylloc, yyextra, "Token pasting (##) is illegal in GLES"); + RETURN_TOKEN (PASTE); + } } "defined" { - return DEFINED; + RETURN_TOKEN (DEFINED); } {IDENTIFIER} { - yylval->str = ralloc_strdup (yyextra, yytext); - return IDENTIFIER; + RETURN_STRING_TOKEN (IDENTIFIER); } {PP_NUMBER} { - yylval->str = ralloc_strdup (yyextra, yytext); - return OTHER; + RETURN_STRING_TOKEN (OTHER); } {PUNCTUATION} { - return yytext[0]; + RETURN_TOKEN (yytext[0]); } {OTHER}+ { - yylval->str = ralloc_strdup (yyextra, yytext); - return OTHER; + RETURN_STRING_TOKEN (OTHER); } {HSPACE} { if (yyextra->space_tokens) { - return SPACE; + RETURN_TOKEN (SPACE); } } -<SKIP,INITIAL>\n { + /* We preserve all newlines, even between #if 0..#endif, so no + skipping.. */ +<*>{NEWLINE} { if (parser->commented_newlines) { BEGIN NEWLINE_CATCHUP; + } else { + BEGIN INITIAL; } + yyextra->space_tokens = 1; yyextra->lexing_directive = 0; yylineno++; yycolumn = 0; - return NEWLINE; + RETURN_TOKEN_NEVER_SKIP (NEWLINE); } - /* Handle missing newline at EOF. */ -<INITIAL><<EOF>> { +<INITIAL,COMMENT,DEFINE,HASH><<EOF>> { + if (YY_START == COMMENT) + glcpp_error(yylloc, yyextra, "Unterminated comment"); BEGIN DONE; /* Don't keep matching this rule forever. */ yyextra->lexing_directive = 0; - return NEWLINE; + if (! parser->last_token_was_newline) + RETURN_TOKEN (NEWLINE); } + /* This is a catch-all to avoid the annoying default flex action which + * matches any character and prints it. If any input ever matches this + * rule, then we have made a mistake above and need to fix one or more + * of the preceding patterns to match that input. */ + +<*>. { + glcpp_error(yylloc, yyextra, "Internal compiler error: Unexpected character: %s", yytext); + /* We don't actually use the UNREACHABLE start condition. We - only have this action here so that we can pretend to call some + only have this block here so that we can pretend to call some generated functions, (to avoid "defined but not used" warnings. */ -<UNREACHABLE>. { - unput('.'); - yy_top_state(yyextra); + if (YY_START == UNREACHABLE) { + unput('.'); + yy_top_state(yyextra); + } } %% diff --git a/mesalib/src/glsl/glcpp/glcpp-parse.y b/mesalib/src/glsl/glcpp/glcpp-parse.y index 084078eb0..a61697394 100644 --- a/mesalib/src/glsl/glcpp/glcpp-parse.y +++ b/mesalib/src/glsl/glcpp/glcpp-parse.y @@ -57,6 +57,9 @@ _string_list_append_item (string_list_t *list, const char *str); static int _string_list_contains (string_list_t *list, const char *member, int *index); +static const char * +_string_list_has_duplicate (string_list_t *list); + static int _string_list_length (string_list_t *list); @@ -105,18 +108,25 @@ _parser_active_list_pop (glcpp_parser_t *parser); static int _parser_active_list_contains (glcpp_parser_t *parser, const char *identifier); +typedef enum { + EXPANSION_MODE_IGNORE_DEFINED, + EXPANSION_MODE_EVALUATE_DEFINED +} expansion_mode_t; + /* Expand list, and begin lexing from the result (after first * prefixing a token of type 'head_token_type'). */ static void _glcpp_parser_expand_and_lex_from (glcpp_parser_t *parser, int head_token_type, - token_list_t *list); + token_list_t *list, + expansion_mode_t mode); /* Perform macro expansion in-place on the given list. */ static void _glcpp_parser_expand_token_list (glcpp_parser_t *parser, - token_list_t *list); + token_list_t *list, + expansion_mode_t mode); static void _glcpp_parser_print_expanded_token_list (glcpp_parser_t *parser, @@ -164,14 +174,18 @@ add_builtin_define(glcpp_parser_t *parser, const char *name, int value); %lex-param {glcpp_parser_t *parser} %expect 0 -%token COMMA_FINAL DEFINED ELIF_EXPANDED HASH HASH_DEFINE FUNC_IDENTIFIER OBJ_IDENTIFIER HASH_ELIF HASH_ELSE HASH_ENDIF HASH_IF HASH_IFDEF HASH_IFNDEF HASH_LINE HASH_UNDEF HASH_VERSION IDENTIFIER IF_EXPANDED INTEGER INTEGER_STRING LINE_EXPANDED NEWLINE OTHER PLACEHOLDER SPACE + + /* We use HASH_TOKEN, DEFINE_TOKEN and VERSION_TOKEN (as opposed to + * HASH, DEFINE, and VERSION) to avoid conflicts with other symbols, + * (such as the <HASH> and <DEFINE> start conditions in the lexer). */ +%token DEFINED ELIF_EXPANDED HASH_TOKEN DEFINE_TOKEN FUNC_IDENTIFIER OBJ_IDENTIFIER ELIF ELSE ENDIF ERROR_TOKEN IF IFDEF IFNDEF LINE PRAGMA UNDEF VERSION_TOKEN GARBAGE IDENTIFIER IF_EXPANDED INTEGER INTEGER_STRING LINE_EXPANDED NEWLINE OTHER PLACEHOLDER SPACE PLUS_PLUS MINUS_MINUS %token PASTE %type <ival> INTEGER operator SPACE integer_constant %type <expression_value> expression -%type <str> IDENTIFIER FUNC_IDENTIFIER OBJ_IDENTIFIER INTEGER_STRING OTHER +%type <str> IDENTIFIER FUNC_IDENTIFIER OBJ_IDENTIFIER INTEGER_STRING OTHER ERROR_TOKEN PRAGMA %type <string_list> identifier_list -%type <token> preprocessing_token conditional_token -%type <token_list> pp_tokens replacement_list text_line conditional_tokens +%type <token> preprocessing_token +%type <token_list> pp_tokens replacement_list text_line %left OR %left AND %left '|' @@ -184,6 +198,8 @@ add_builtin_define(glcpp_parser_t *parser, const char *name, int value); %left '*' '/' '%' %right UNARY +%debug + %% input: @@ -192,27 +208,14 @@ input: ; line: - control_line { - ralloc_asprintf_rewrite_tail (&parser->output, &parser->output_length, "\n"); - } -| HASH_LINE { - glcpp_parser_resolve_implicit_version(parser); - } pp_tokens NEWLINE { - - if (parser->skip_stack == NULL || - parser->skip_stack->type == SKIP_NO_SKIP) - { - _glcpp_parser_expand_and_lex_from (parser, - LINE_EXPANDED, $3); - } - } + control_line +| SPACE control_line | text_line { _glcpp_parser_print_expanded_token_list (parser, $1); ralloc_asprintf_rewrite_tail (&parser->output, &parser->output_length, "\n"); ralloc_free ($1); } | expanded_line -| HASH non_directive ; expanded_line: @@ -259,29 +262,48 @@ define: ; control_line: - HASH_DEFINE { + control_line_success { + ralloc_asprintf_rewrite_tail (&parser->output, &parser->output_length, "\n"); + } +| control_line_error +| HASH_TOKEN LINE { + glcpp_parser_resolve_implicit_version(parser); + } pp_tokens NEWLINE { + + if (parser->skip_stack == NULL || + parser->skip_stack->type == SKIP_NO_SKIP) + { + _glcpp_parser_expand_and_lex_from (parser, + LINE_EXPANDED, $4, + EXPANSION_MODE_IGNORE_DEFINED); + } + } +; + +control_line_success: + HASH_TOKEN DEFINE_TOKEN { glcpp_parser_resolve_implicit_version(parser); } define -| HASH_UNDEF { +| HASH_TOKEN UNDEF { glcpp_parser_resolve_implicit_version(parser); } IDENTIFIER NEWLINE { macro_t *macro; - if (strcmp("__LINE__", $3) == 0 - || strcmp("__FILE__", $3) == 0 - || strcmp("__VERSION__", $3) == 0) + if (strcmp("__LINE__", $4) == 0 + || strcmp("__FILE__", $4) == 0 + || strcmp("__VERSION__", $4) == 0) glcpp_error(& @1, parser, "Built-in (pre-defined)" " macro names can not be undefined."); - macro = hash_table_find (parser->defines, $3); + macro = hash_table_find (parser->defines, $4); if (macro) { - hash_table_remove (parser->defines, $3); + hash_table_remove (parser->defines, $4); ralloc_free (macro); } - ralloc_free ($3); + ralloc_free ($4); } -| HASH_IF { +| HASH_TOKEN IF { glcpp_parser_resolve_implicit_version(parser); - } conditional_tokens NEWLINE { + } pp_tokens NEWLINE { /* Be careful to only evaluate the 'if' expression if * we are not skipping. When we are skipping, we * simply push a new 0-valued 'if' onto the skip @@ -293,7 +315,8 @@ control_line: parser->skip_stack->type == SKIP_NO_SKIP) { _glcpp_parser_expand_and_lex_from (parser, - IF_EXPANDED, $3); + IF_EXPANDED, $4, + EXPANSION_MODE_EVALUATE_DEFINED); } else { @@ -301,7 +324,7 @@ control_line: parser->skip_stack->type = SKIP_TO_ENDIF; } } -| HASH_IF NEWLINE { +| HASH_TOKEN IF NEWLINE { /* #if without an expression is only an error if we * are not skipping */ if (parser->skip_stack == NULL || @@ -311,21 +334,21 @@ control_line: } _glcpp_parser_skip_stack_push_if (parser, & @1, 0); } -| HASH_IFDEF { +| HASH_TOKEN IFDEF { glcpp_parser_resolve_implicit_version(parser); } IDENTIFIER junk NEWLINE { - macro_t *macro = hash_table_find (parser->defines, $3); - ralloc_free ($3); + macro_t *macro = hash_table_find (parser->defines, $4); + ralloc_free ($4); _glcpp_parser_skip_stack_push_if (parser, & @1, macro != NULL); } -| HASH_IFNDEF { +| HASH_TOKEN IFNDEF { glcpp_parser_resolve_implicit_version(parser); } IDENTIFIER junk NEWLINE { - macro_t *macro = hash_table_find (parser->defines, $3); - ralloc_free ($3); - _glcpp_parser_skip_stack_push_if (parser, & @2, macro == NULL); + macro_t *macro = hash_table_find (parser->defines, $4); + ralloc_free ($4); + _glcpp_parser_skip_stack_push_if (parser, & @3, macro == NULL); } -| HASH_ELIF conditional_tokens NEWLINE { +| HASH_TOKEN ELIF pp_tokens NEWLINE { /* Be careful to only evaluate the 'elif' expression * if we are not skipping. When we are skipping, we * simply change to a 0-valued 'elif' on the skip @@ -337,7 +360,8 @@ control_line: parser->skip_stack->type == SKIP_TO_ELSE) { _glcpp_parser_expand_and_lex_from (parser, - ELIF_EXPANDED, $2); + ELIF_EXPANDED, $3, + EXPANSION_MODE_EVALUATE_DEFINED); } else if (parser->skip_stack && parser->skip_stack->has_else) @@ -350,7 +374,7 @@ control_line: "elif", 0); } } -| HASH_ELIF NEWLINE { +| HASH_TOKEN ELIF NEWLINE { /* #elif without an expression is an error unless we * are skipping. */ if (parser->skip_stack && @@ -370,7 +394,7 @@ control_line: glcpp_warning(& @1, parser, "ignoring illegal #elif without expression"); } } -| HASH_ELSE { parser->lexing_directive = 1; } NEWLINE { +| HASH_TOKEN ELSE { parser->lexing_directive = 1; } NEWLINE { if (parser->skip_stack && parser->skip_stack->has_else) { @@ -383,24 +407,39 @@ control_line: parser->skip_stack->has_else = true; } } -| HASH_ENDIF { +| HASH_TOKEN ENDIF { _glcpp_parser_skip_stack_pop (parser, & @1); } NEWLINE -| HASH_VERSION integer_constant NEWLINE { +| HASH_TOKEN VERSION_TOKEN integer_constant NEWLINE { if (parser->version_resolved) { glcpp_error(& @1, parser, "#version must appear on the first line"); } - _glcpp_parser_handle_version_declaration(parser, $2, NULL, true); + _glcpp_parser_handle_version_declaration(parser, $3, NULL, true); } -| HASH_VERSION integer_constant IDENTIFIER NEWLINE { +| HASH_TOKEN VERSION_TOKEN integer_constant IDENTIFIER NEWLINE { if (parser->version_resolved) { glcpp_error(& @1, parser, "#version must appear on the first line"); } - _glcpp_parser_handle_version_declaration(parser, $2, $3, true); + _glcpp_parser_handle_version_declaration(parser, $3, $4, true); } -| HASH NEWLINE { +| HASH_TOKEN NEWLINE { glcpp_parser_resolve_implicit_version(parser); } +| HASH_TOKEN PRAGMA NEWLINE { + ralloc_asprintf_rewrite_tail (&parser->output, &parser->output_length, "#%s", $2); + } +; + +control_line_error: + HASH_TOKEN ERROR_TOKEN NEWLINE { + glcpp_error(& @1, parser, "#%s", $2); + } +| HASH_TOKEN DEFINE_TOKEN NEWLINE { + glcpp_error (& @1, parser, "#define without macro name"); + } +| HASH_TOKEN GARBAGE pp_tokens NEWLINE { + glcpp_error (& @1, parser, "Illegal non-directive after #"); + } ; integer_constant: @@ -612,12 +651,6 @@ text_line: | pp_tokens NEWLINE ; -non_directive: - pp_tokens NEWLINE { - yyerror (& @1, parser, "Invalid tokens after #"); - } -; - replacement_list: /* empty */ { $$ = NULL; } | pp_tokens @@ -630,31 +663,6 @@ junk: } ; -conditional_token: - /* Handle "defined" operator */ - DEFINED IDENTIFIER { - int v = hash_table_find (parser->defines, $2) ? 1 : 0; - $$ = _token_create_ival (parser, INTEGER, v); - } -| DEFINED '(' IDENTIFIER ')' { - int v = hash_table_find (parser->defines, $3) ? 1 : 0; - $$ = _token_create_ival (parser, INTEGER, v); - } -| preprocessing_token -; - -conditional_tokens: - /* Exactly the same as pp_tokens, but using conditional_token */ - conditional_token { - $$ = _token_list_create (parser); - _token_list_append ($$, $1); - } -| conditional_tokens conditional_token { - $$ = $1; - _token_list_append ($$, $2); - } -; - pp_tokens: preprocessing_token { parser->space_tokens = 1; @@ -680,6 +688,10 @@ preprocessing_token: $$ = _token_create_ival (parser, $1, $1); $$->location = yylloc; } +| DEFINED { + $$ = _token_create_ival (parser, DEFINED, DEFINED); + $$->location = yylloc; + } | OTHER { $$ = _token_create_str (parser, OTHER, $1); $$->location = yylloc; @@ -722,6 +734,8 @@ operator: | ',' { $$ = ','; } | '=' { $$ = '='; } | PASTE { $$ = PASTE; } +| PLUS_PLUS { $$ = PLUS_PLUS; } +| MINUS_MINUS { $$ = MINUS_MINUS; } ; %% @@ -777,6 +791,25 @@ _string_list_contains (string_list_t *list, const char *member, int *index) return 0; } +/* Return duplicate string in list (if any), NULL otherwise. */ +const char * +_string_list_has_duplicate (string_list_t *list) +{ + string_node_t *node, *dup; + + if (list == NULL) + return NULL; + + for (node = list->head; node; node = node->next) { + for (dup = node->next; dup; dup = dup->next) { + if (strcmp (node->str, dup->str) == 0) + return node->str; + } + } + + return NULL; +} + int _string_list_length (string_list_t *list) { @@ -1123,14 +1156,21 @@ _token_print (char **out, size_t *len, token_t *token) case PASTE: ralloc_asprintf_rewrite_tail (out, len, "##"); break; - case COMMA_FINAL: - ralloc_asprintf_rewrite_tail (out, len, ","); + case PLUS_PLUS: + ralloc_asprintf_rewrite_tail (out, len, "++"); + break; + case MINUS_MINUS: + ralloc_asprintf_rewrite_tail (out, len, "--"); + break; + case DEFINED: + ralloc_asprintf_rewrite_tail (out, len, "defined"); break; case PLACEHOLDER: /* Nothing to print. */ break; default: assert(!"Error: Don't know how to print token."); + break; } } @@ -1308,12 +1348,16 @@ glcpp_parser_create (const struct gl_extensions *extensions, gl_api api) parser->active = NULL; parser->lexing_directive = 0; parser->space_tokens = 1; + parser->last_token_was_newline = 0; + parser->last_token_was_space = 0; + parser->first_non_space_token_this_line = 1; parser->newline_as_space = 0; parser->in_control_line = 0; parser->paren_count = 0; parser->commented_newlines = 0; parser->skip_stack = NULL; + parser->skipping = 0; parser->lex_from_list = NULL; parser->lex_from_node = NULL; @@ -1459,15 +1503,143 @@ _token_list_create_with_one_integer (void *ctx, int ival) return _token_list_create_with_one_ival (ctx, INTEGER, ival); } +/* Evaluate a DEFINED token node (based on subsequent tokens in the list). + * + * Note: This function must only be called when "node" is a DEFINED token, + * (and will abort with an assertion failure otherwise). + * + * If "node" is followed, (ignoring any SPACE tokens), by an IDENTIFIER token + * (optionally preceded and followed by '(' and ')' tokens) then the following + * occurs: + * + * If the identifier is a defined macro, this function returns 1. + * + * If the identifier is not a defined macro, this function returns 0. + * + * In either case, *last will be updated to the last node in the list + * consumed by the evaluation, (either the token of the identifier or the + * token of the closing parenthesis). + * + * In all other cases, (such as "node is the final node of the list", or + * "missing closing parenthesis", etc.), this function generates a + * preprocessor error, returns -1 and *last will not be set. + */ +static int +_glcpp_parser_evaluate_defined (glcpp_parser_t *parser, + token_node_t *node, + token_node_t **last) +{ + token_node_t *argument, *defined = node; + + assert (node->token->type == DEFINED); + + node = node->next; + + /* Ignore whitespace after DEFINED token. */ + while (node && node->token->type == SPACE) + node = node->next; + + if (node == NULL) + goto FAIL; + + if (node->token->type == IDENTIFIER || node->token->type == OTHER) { + argument = node; + } else if (node->token->type == '(') { + node = node->next; + + /* Ignore whitespace after '(' token. */ + while (node && node->token->type == SPACE) + node = node->next; + + if (node == NULL || (node->token->type != IDENTIFIER && + node->token->type != OTHER)) + { + goto FAIL; + } + + argument = node; + + node = node->next; + + /* Ignore whitespace after identifier, before ')' token. */ + while (node && node->token->type == SPACE) + node = node->next; + + if (node == NULL || node->token->type != ')') + goto FAIL; + } else { + goto FAIL; + } + + *last = node; + + return hash_table_find (parser->defines, + argument->token->value.str) ? 1 : 0; + +FAIL: + glcpp_error (&defined->token->location, parser, + "\"defined\" not followed by an identifier"); + return -1; +} + +/* Evaluate all DEFINED nodes in a given list, modifying the list in place. + */ +static void +_glcpp_parser_evaluate_defined_in_list (glcpp_parser_t *parser, + token_list_t *list) +{ + token_node_t *node, *node_prev, *replacement, *last = NULL; + int value; + + if (list == NULL) + return; + + node_prev = NULL; + node = list->head; + + while (node) { + + if (node->token->type != DEFINED) + goto NEXT; + + value = _glcpp_parser_evaluate_defined (parser, node, &last); + if (value == -1) + goto NEXT; + + replacement = ralloc (list, token_node_t); + replacement->token = _token_create_ival (list, INTEGER, value); + + /* Splice replacement node into list, replacing from "node" + * through "last". */ + if (node_prev) + node_prev->next = replacement; + else + list->head = replacement; + replacement->next = last->next; + if (last == list->tail) + list->tail = replacement; + + node = replacement; + + NEXT: + node_prev = node; + node = node->next; + } +} + /* Perform macro expansion on 'list', placing the resulting tokens * into a new list which is initialized with a first token of type * 'head_token_type'. Then begin lexing from the resulting list, * (return to the current lexing source when this list is exhausted). + * + * See the documentation of _glcpp_parser_expand_token_list for a description + * of the "mode" parameter. */ static void _glcpp_parser_expand_and_lex_from (glcpp_parser_t *parser, int head_token_type, - token_list_t *list) + token_list_t *list, + expansion_mode_t mode) { token_list_t *expanded; token_t *token; @@ -1475,7 +1647,7 @@ _glcpp_parser_expand_and_lex_from (glcpp_parser_t *parser, expanded = _token_list_create (parser); token = _token_create_ival (parser, head_token_type, head_token_type); _token_list_append (expanded, token); - _glcpp_parser_expand_token_list (parser, list); + _glcpp_parser_expand_token_list (parser, list, mode); _token_list_append_list (expanded, list); glcpp_parser_lex_from (parser, expanded); } @@ -1538,12 +1710,15 @@ _glcpp_parser_apply_pastes (glcpp_parser_t *parser, token_list_t *list) * *last to the last node in the list that was consumed by the * expansion. Specifically, *last will be set as follows: as the * token of the closing right parenthesis. + * + * See the documentation of _glcpp_parser_expand_token_list for a description + * of the "mode" parameter. */ static token_list_t * _glcpp_parser_expand_function (glcpp_parser_t *parser, token_node_t *node, - token_node_t **last) - + token_node_t **last, + expansion_mode_t mode) { macro_t *macro; const char *identifier; @@ -1612,7 +1787,8 @@ _glcpp_parser_expand_function (glcpp_parser_t *parser, expanded_argument = _token_list_copy (parser, argument); _glcpp_parser_expand_token_list (parser, - expanded_argument); + expanded_argument, + mode); _token_list_append_list (substituted, expanded_argument); } else { @@ -1652,11 +1828,15 @@ _glcpp_parser_expand_function (glcpp_parser_t *parser, * * As the token of the closing right parenthesis in the case of * function-like macro expansion. + * + * See the documentation of _glcpp_parser_expand_token_list for a description + * of the "mode" parameter. */ static token_list_t * _glcpp_parser_expand_node (glcpp_parser_t *parser, token_node_t *node, - token_node_t **last) + token_node_t **last, + expansion_mode_t mode) { token_t *token = node->token; const char *identifier; @@ -1664,14 +1844,6 @@ _glcpp_parser_expand_node (glcpp_parser_t *parser, /* We only expand identifiers */ if (token->type != IDENTIFIER) { - /* We change any COMMA into a COMMA_FINAL to prevent - * it being mistaken for an argument separator - * later. */ - if (token->type == ',') { - token->type = COMMA_FINAL; - token->value.ival = COMMA_FINAL; - } - return NULL; } @@ -1723,7 +1895,7 @@ _glcpp_parser_expand_node (glcpp_parser_t *parser, return replacement; } - return _glcpp_parser_expand_function (parser, node, last); + return _glcpp_parser_expand_function (parser, node, last, mode); } /* Push a new identifier onto the parser's active list. @@ -1782,11 +1954,28 @@ _parser_active_list_contains (glcpp_parser_t *parser, const char *identifier) /* Walk over the token list replacing nodes with their expansion. * Whenever nodes are expanded the walking will walk over the new * nodes, continuing to expand as necessary. The results are placed in - * 'list' itself; + * 'list' itself. + * + * The "mode" argument controls the handling of any DEFINED tokens that + * result from expansion as follows: + * + * EXPANSION_MODE_IGNORE_DEFINED: Any resulting DEFINED tokens will be + * left in the final list, unevaluated. This is the correct mode + * for expanding any list in any context other than a + * preprocessor conditional, (#if or #elif). + * + * EXPANSION_MODE_EVALUATE_DEFINED: Any resulting DEFINED tokens will be + * evaluated to 0 or 1 tokens depending on whether the following + * token is the name of a defined macro. If the DEFINED token is + * not followed by an (optionally parenthesized) identifier, then + * an error will be generated. This the correct mode for + * expanding any list in the context of a preprocessor + * conditional, (#if or #elif). */ static void _glcpp_parser_expand_token_list (glcpp_parser_t *parser, - token_list_t *list) + token_list_t *list, + expansion_mode_t mode) { token_node_t *node_prev; token_node_t *node, *last = NULL; @@ -1801,15 +1990,23 @@ _glcpp_parser_expand_token_list (glcpp_parser_t *parser, node_prev = NULL; node = list->head; + if (mode == EXPANSION_MODE_EVALUATE_DEFINED) + _glcpp_parser_evaluate_defined_in_list (parser, list); + while (node) { while (parser->active && parser->active->marker == node) _parser_active_list_pop (parser); - expansion = _glcpp_parser_expand_node (parser, node, &last); + expansion = _glcpp_parser_expand_node (parser, node, &last, mode); if (expansion) { token_node_t *n; + if (mode == EXPANSION_MODE_EVALUATE_DEFINED) { + _glcpp_parser_evaluate_defined_in_list (parser, + expansion); + } + for (n = node; n != last->next; n = n->next) while (parser->active && parser->active->marker == n) @@ -1862,7 +2059,7 @@ _glcpp_parser_print_expanded_token_list (glcpp_parser_t *parser, if (list == NULL) return; - _glcpp_parser_expand_token_list (parser, list); + _glcpp_parser_expand_token_list (parser, list, EXPANSION_MODE_IGNORE_DEFINED); _token_list_trim_trailing_space (list); @@ -1923,6 +2120,10 @@ _define_object_macro (glcpp_parser_t *parser, { macro_t *macro, *previous; + /* We define pre-defined macros before we've started parsing the + * actual file. So if there's no location defined yet, that's what + * were doing and we don't want to generate an error for using the + * reserved names. */ if (loc != NULL) _check_for_reserved_macro_name(parser, loc, identifier); @@ -1955,9 +2156,16 @@ _define_function_macro (glcpp_parser_t *parser, token_list_t *replacements) { macro_t *macro, *previous; + const char *dup; _check_for_reserved_macro_name(parser, loc, identifier); + /* Check for any duplicate parameter names. */ + if ((dup = _string_list_has_duplicate (parameters)) != NULL) { + glcpp_error (loc, parser, "Duplicate macro parameter \"%s\"", + dup); + } + macro = ralloc (parser, macro_t); ralloc_steal (macro, parameters); ralloc_steal (macro, replacements); @@ -2020,11 +2228,11 @@ glcpp_parser_lex (YYSTYPE *yylval, YYLTYPE *yylloc, glcpp_parser_t *parser) if (ret == NEWLINE) parser->in_control_line = 0; } - else if (ret == HASH_DEFINE || - ret == HASH_UNDEF || ret == HASH_IF || - ret == HASH_IFDEF || ret == HASH_IFNDEF || - ret == HASH_ELIF || ret == HASH_ELSE || - ret == HASH_ENDIF || ret == HASH) + else if (ret == DEFINE_TOKEN || + ret == UNDEF || ret == IF || + ret == IFDEF || ret == IFNDEF || + ret == ELIF || ret == ELSE || + ret == ENDIF || ret == HASH_TOKEN) { parser->in_control_line = 1; } @@ -2117,7 +2325,7 @@ _glcpp_parser_skip_stack_change_if (glcpp_parser_t *parser, YYLTYPE *loc, const char *type, int condition) { if (parser->skip_stack == NULL) { - glcpp_error (loc, parser, "%s without #if\n", type); + glcpp_error (loc, parser, "#%s without #if\n", type); return; } @@ -2170,6 +2378,8 @@ _glcpp_parser_handle_version_declaration(glcpp_parser_t *parser, intmax_t versio if (extensions != NULL) { if (extensions->OES_EGL_image_external) add_builtin_define(parser, "GL_OES_EGL_image_external", 1); + if (extensions->OES_standard_derivatives) + add_builtin_define(parser, "GL_OES_standard_derivatives", 1); } } else { add_builtin_define(parser, "GL_ARB_draw_buffers", 1); diff --git a/mesalib/src/glsl/glcpp/glcpp.c b/mesalib/src/glsl/glcpp/glcpp.c index 07b1500b6..ca188015c 100644 --- a/mesalib/src/glsl/glcpp/glcpp.c +++ b/mesalib/src/glsl/glcpp/glcpp.c @@ -124,6 +124,7 @@ enum { const static struct option long_options[] = { {"disable-line-continuations", no_argument, 0, DISABLE_LINE_CONTINUATIONS_OPT }, + {"debug", no_argument, 0, 'd'}, {0, 0, 0, 0 } }; @@ -140,11 +141,14 @@ main (int argc, char *argv[]) init_fake_gl_context (&gl_ctx); - while ((c = getopt_long(argc, argv, "", long_options, NULL)) != -1) { + while ((c = getopt_long(argc, argv, "d", long_options, NULL)) != -1) { switch (c) { case DISABLE_LINE_CONTINUATIONS_OPT: gl_ctx.Const.DisableGLSLLineContinuations = true; break; + case 'd': + glcpp_parser_debug = 1; + break; default: usage (); exit (1); diff --git a/mesalib/src/glsl/glcpp/glcpp.h b/mesalib/src/glsl/glcpp/glcpp.h index 64b487202..70aa14b6e 100644 --- a/mesalib/src/glsl/glcpp/glcpp.h +++ b/mesalib/src/glsl/glcpp/glcpp.h @@ -29,7 +29,7 @@ #include "main/mtypes.h" -#include "../ralloc.h" +#include "util/ralloc.h" #include "program/hash_table.h" @@ -177,11 +177,15 @@ struct glcpp_parser { active_list_t *active; int lexing_directive; int space_tokens; + int last_token_was_newline; + int last_token_was_space; + int first_non_space_token_this_line; int newline_as_space; int in_control_line; int paren_count; int commented_newlines; skip_node_t *skip_stack; + int skipping; token_list_t *lex_from_list; token_node_t *lex_from_node; char *output; diff --git a/mesalib/src/glsl/glcpp/pp.c b/mesalib/src/glsl/glcpp/pp.c index 4a623f81e..a54bcbe16 100644 --- a/mesalib/src/glsl/glcpp/pp.c +++ b/mesalib/src/glsl/glcpp/pp.c @@ -70,6 +70,42 @@ glcpp_warning (YYLTYPE *locp, glcpp_parser_t *parser, const char *fmt, ...) &parser->info_log_length, "\n"); } +/* Given str, (that's expected to start with a newline terminator of some + * sort), return a pointer to the first character in str after the newline. + * + * A newline terminator can be any of the following sequences: + * + * "\r\n" + * "\n\r" + * "\n" + * "\r" + * + * And the longest such sequence will be skipped. + */ +static const char * +skip_newline (const char *str) +{ + const char *ret = str; + + if (ret == NULL) + return ret; + + if (*ret == '\0') + return ret; + + if (*ret == '\r') { + ret++; + if (*ret && *ret == '\n') + ret++; + } else if (*ret == '\n') { + ret++; + if (*ret && *ret == '\r') + ret++; + } + + return ret; +} + /* Remove any line continuation characters in the shader, (whether in * preprocessing directives or in GLSL code). */ @@ -78,10 +114,49 @@ remove_line_continuations(glcpp_parser_t *ctx, const char *shader) { char *clean = ralloc_strdup(ctx, ""); const char *backslash, *newline, *search_start; + const char *cr, *lf; + char newline_separator[3]; int collapsed_newlines = 0; search_start = shader; + /* Determine what flavor of newlines this shader is using. GLSL + * provides for 4 different possible ways to separate lines, (using + * one or two characters): + * + * "\n" (line-feed, like Linux, Unix, and new Mac OS) + * "\r" (carriage-return, like old Mac files) + * "\r\n" (carriage-return + line-feed, like DOS files) + * "\n\r" (line-feed + carriage-return, like nothing, really) + * + * This code explicitly supports a shader that uses a mixture of + * newline terminators and will properly handle line continuation + * backslashes followed by any of the above. + * + * But, since we must also insert additional newlines in the output + * (for any collapsed lines) we attempt to maintain consistency by + * examining the first encountered newline terminator, and using the + * same terminator for any newlines we insert. + */ + cr = strchr(search_start, '\r'); + lf = strchr(search_start, '\n'); + + newline_separator[0] = '\n'; + newline_separator[1] = '\0'; + newline_separator[2] = '\0'; + + if (cr == NULL) { + /* Nothing to do. */ + } else if (lf == NULL) { + newline_separator[0] = '\r'; + } else if (lf == cr + 1) { + newline_separator[0] = '\r'; + newline_separator[1] = '\n'; + } else if (cr == lf + 1) { + newline_separator[0] = '\n'; + newline_separator[1] = '\r'; + } + while (true) { backslash = strchr(search_start, '\\'); @@ -91,17 +166,24 @@ remove_line_continuations(glcpp_parser_t *ctx, const char *shader) * line numbers. */ if (collapsed_newlines) { - newline = strchr(search_start, '\n'); + cr = strchr (search_start, '\r'); + lf = strchr (search_start, '\n'); + if (cr && lf) + newline = cr < lf ? cr : lf; + else if (cr) + newline = cr; + else + newline = lf; if (newline && (backslash == NULL || newline < backslash)) { ralloc_strncat(&clean, shader, newline - shader + 1); while (collapsed_newlines) { - ralloc_strcat(&clean, "\n"); + ralloc_strcat(&clean, newline_separator); collapsed_newlines--; } - shader = newline + 1; + shader = skip_newline (newline); search_start = shader; } } @@ -116,15 +198,11 @@ remove_line_continuations(glcpp_parser_t *ctx, const char *shader) * advance the shader pointer to the character after the * newline. */ - if (backslash[1] == '\n' || - (backslash[1] == '\r' && backslash[2] == '\n')) + if (backslash[1] == '\r' || backslash[1] == '\n') { collapsed_newlines++; ralloc_strncat(&clean, shader, backslash - shader); - if (backslash[1] == '\n') - shader = backslash + 2; - else - shader = backslash + 3; + shader = skip_newline (backslash + 1); search_start = shader; } } diff --git a/mesalib/src/glsl/glsl_lexer.ll b/mesalib/src/glsl/glsl_lexer.ll index db7b1d179..b7c4aad3a 100644 --- a/mesalib/src/glsl/glsl_lexer.ll +++ b/mesalib/src/glsl/glsl_lexer.ll @@ -152,7 +152,11 @@ literal_integer(char *text, int len, struct _mesa_glsl_parse_state *state, %option never-interactive %option prefix="_mesa_glsl_lexer_" %option extra-type="struct _mesa_glsl_parse_state *" +%option warn nodefault + /* Note: When adding any start conditions to this list, you must also + * update the "Internal compiler error" catch-all rule near the end of + * this file. */ %x PP PRAGMA DEC_INT [1-9][0-9]* @@ -236,6 +240,7 @@ HASH ^{SPC}#{SPC} return INTCONSTANT; } <PP>\n { BEGIN 0; yylineno++; yycolumn = 0; return EOL; } +<PP>. { return yytext[0]; } \n { yylineno++; yycolumn = 0; } diff --git a/mesalib/src/glsl/glsl_parser_extras.cpp b/mesalib/src/glsl/glsl_parser_extras.cpp index 890123ad1..2d94d3554 100644 --- a/mesalib/src/glsl/glsl_parser_extras.cpp +++ b/mesalib/src/glsl/glsl_parser_extras.cpp @@ -31,7 +31,7 @@ extern "C" { #include "main/shaderobj.h" } -#include "ralloc.h" +#include "util/ralloc.h" #include "ast.h" #include "glsl_parser_extras.h" #include "glsl_parser.h" @@ -1487,7 +1487,7 @@ _mesa_glsl_compile_shader(struct gl_context *ctx, struct gl_shader *shader, if (shader->InfoLog) ralloc_free(shader->InfoLog); - shader->symbols = state->symbols; + shader->symbols = new(shader->ir) glsl_symbol_table; shader->CompileStatus = !state->error; shader->InfoLog = state->info_log; shader->Version = state->language_version; @@ -1500,6 +1500,30 @@ _mesa_glsl_compile_shader(struct gl_context *ctx, struct gl_shader *shader, /* Retain any live IR, but trash the rest. */ reparent_ir(shader->ir, shader->ir); + /* Destroy the symbol table. Create a new symbol table that contains only + * the variables and functions that still exist in the IR. The symbol + * table will be used later during linking. + * + * There must NOT be any freed objects still referenced by the symbol + * table. That could cause the linker to dereference freed memory. + * + * We don't have to worry about types or interface-types here because those + * are fly-weights that are looked up by glsl_type. + */ + foreach_in_list (ir_instruction, ir, shader->ir) { + switch (ir->ir_type) { + case ir_type_function: + shader->symbols->add_function((ir_function *) ir); + break; + case ir_type_variable: + shader->symbols->add_variable((ir_variable *) ir); + break; + default: + break; + } + } + + delete state->symbols; ralloc_free(state); } diff --git a/mesalib/src/glsl/glsl_types.cpp b/mesalib/src/glsl/glsl_types.cpp index f9cd258fe..66e9b1330 100644 --- a/mesalib/src/glsl/glsl_types.cpp +++ b/mesalib/src/glsl/glsl_types.cpp @@ -108,7 +108,7 @@ glsl_type::glsl_type(const glsl_struct_field *fields, unsigned num_fields, this->fields.structure[i].interpolation = fields[i].interpolation; this->fields.structure[i].centroid = fields[i].centroid; this->fields.structure[i].sample = fields[i].sample; - this->fields.structure[i].row_major = fields[i].row_major; + this->fields.structure[i].matrix_layout = fields[i].matrix_layout; } } @@ -136,7 +136,7 @@ glsl_type::glsl_type(const glsl_struct_field *fields, unsigned num_fields, this->fields.structure[i].interpolation = fields[i].interpolation; this->fields.structure[i].centroid = fields[i].centroid; this->fields.structure[i].sample = fields[i].sample; - this->fields.structure[i].row_major = fields[i].row_major; + this->fields.structure[i].matrix_layout = fields[i].matrix_layout; } } @@ -496,8 +496,8 @@ glsl_type::record_compare(const glsl_type *b) const if (strcmp(this->fields.structure[i].name, b->fields.structure[i].name) != 0) return false; - if (this->fields.structure[i].row_major - != b->fields.structure[i].row_major) + if (this->fields.structure[i].matrix_layout + != b->fields.structure[i].matrix_layout) return false; if (this->fields.structure[i].location != b->fields.structure[i].location) @@ -826,9 +826,18 @@ glsl_type::std140_base_alignment(bool row_major) const if (this->is_record()) { unsigned base_alignment = 16; for (unsigned i = 0; i < this->length; i++) { + bool field_row_major = row_major; + const enum glsl_matrix_layout matrix_layout = + glsl_matrix_layout(this->fields.structure[i].matrix_layout); + if (matrix_layout == GLSL_MATRIX_LAYOUT_ROW_MAJOR) { + field_row_major = true; + } else if (matrix_layout == GLSL_MATRIX_LAYOUT_COLUMN_MAJOR) { + field_row_major = false; + } + const struct glsl_type *field_type = this->fields.structure[i].type; base_alignment = MAX2(base_alignment, - field_type->std140_base_alignment(row_major)); + field_type->std140_base_alignment(field_row_major)); } return base_alignment; } @@ -872,8 +881,7 @@ glsl_type::std140_size(bool row_major) const * and <R> rows, the matrix is stored identically to a row of <S>*<R> * row vectors with <C> components each, according to rule (4). */ - if (this->is_matrix() || (this->is_array() && - this->fields.array->is_matrix())) { + if (this->without_array()->is_matrix()) { const struct glsl_type *element_type; const struct glsl_type *vec_type; unsigned int array_len; @@ -935,14 +943,29 @@ glsl_type::std140_size(bool row_major) const */ if (this->is_record()) { unsigned size = 0; + unsigned max_align = 0; + for (unsigned i = 0; i < this->length; i++) { + bool field_row_major = row_major; + const enum glsl_matrix_layout matrix_layout = + glsl_matrix_layout(this->fields.structure[i].matrix_layout); + if (matrix_layout == GLSL_MATRIX_LAYOUT_ROW_MAJOR) { + field_row_major = true; + } else if (matrix_layout == GLSL_MATRIX_LAYOUT_COLUMN_MAJOR) { + field_row_major = false; + } + const struct glsl_type *field_type = this->fields.structure[i].type; - unsigned align = field_type->std140_base_alignment(row_major); + unsigned align = field_type->std140_base_alignment(field_row_major); size = glsl_align(size, align); - size += field_type->std140_size(row_major); + size += field_type->std140_size(field_row_major); + + max_align = MAX2(align, max_align); + + if (field_type->is_record() && (i + 1 < this->length)) + size = glsl_align(size, 16); } - size = glsl_align(size, - this->fields.structure[0].type->std140_base_alignment(row_major)); + size = glsl_align(size, max_align); return size; } diff --git a/mesalib/src/glsl/glsl_types.h b/mesalib/src/glsl/glsl_types.h index 0b63d4850..d545533dc 100644 --- a/mesalib/src/glsl/glsl_types.h +++ b/mesalib/src/glsl/glsl_types.h @@ -79,9 +79,30 @@ enum glsl_interface_packing { GLSL_INTERFACE_PACKING_PACKED }; +enum glsl_matrix_layout { + /** + * The layout of the matrix is inherited from the object containing the + * matrix (the top level structure or the uniform block). + */ + GLSL_MATRIX_LAYOUT_INHERITED, + + /** + * Explicit column-major layout + * + * If a uniform block doesn't have an explicit layout set, it will default + * to this layout. + */ + GLSL_MATRIX_LAYOUT_COLUMN_MAJOR, + + /** + * Row-major layout + */ + GLSL_MATRIX_LAYOUT_ROW_MAJOR +}; + #ifdef __cplusplus #include "GL/gl.h" -#include "ralloc.h" +#include "util/ralloc.h" struct glsl_type { GLenum gl_type; @@ -465,6 +486,18 @@ struct glsl_type { } /** + * Get the type stripped of any arrays + * + * \return + * Pointer to the type of elements of the first non-array type for array + * types, or pointer to itself for non-array types. + */ + const glsl_type *without_array() const + { + return this->is_array() ? this->fields.array : this; + } + + /** * Return the amount of atomic counter storage required for a type. */ unsigned atomic_size() const @@ -643,7 +676,6 @@ private: struct glsl_struct_field { const struct glsl_type *type; const char *name; - bool row_major; /** * For interface blocks, gl_varying_slot corresponding to the input/output @@ -673,6 +705,11 @@ struct glsl_struct_field { unsigned sample:1; /** + * Layout of the matrix. Uses glsl_matrix_layout values. + */ + unsigned matrix_layout:2; + + /** * For interface blocks, it has a value if this variable uses multiple vertex * streams (as in ir_variable::stream). -1 otherwise. */ diff --git a/mesalib/src/glsl/ir.h b/mesalib/src/glsl/ir.h index ea19924ab..31c354556 100644 --- a/mesalib/src/glsl/ir.h +++ b/mesalib/src/glsl/ir.h @@ -29,7 +29,7 @@ #include <stdio.h> #include <stdlib.h> -#include "ralloc.h" +#include "util/ralloc.h" #include "glsl_types.h" #include "list.h" #include "ir_visitor.h" @@ -660,6 +660,11 @@ public: unsigned location_frac:2; /** + * Layout of the matrix. Uses glsl_matrix_layout values. + */ + unsigned matrix_layout:2; + + /** * Non-zero if this variable was created by lowering a named interface * block which was not an array. * @@ -974,6 +979,7 @@ public: */ ir_function_signature *matching_signature(_mesa_glsl_parse_state *state, const exec_list *actual_param, + bool allow_builtins, bool *match_is_exact); /** @@ -981,7 +987,8 @@ public: * conversions into account. */ ir_function_signature *matching_signature(_mesa_glsl_parse_state *state, - const exec_list *actual_param); + const exec_list *actual_param, + bool allow_builtins); /** * Find a signature that exactly matches a set of actual parameters without diff --git a/mesalib/src/glsl/ir_function.cpp b/mesalib/src/glsl/ir_function.cpp index 7d6c2f451..98bec45ce 100644 --- a/mesalib/src/glsl/ir_function.cpp +++ b/mesalib/src/glsl/ir_function.cpp @@ -281,15 +281,18 @@ choose_best_inexact_overload(_mesa_glsl_parse_state *state, ir_function_signature * ir_function::matching_signature(_mesa_glsl_parse_state *state, - const exec_list *actual_parameters) + const exec_list *actual_parameters, + bool allow_builtins) { bool is_exact; - return matching_signature(state, actual_parameters, &is_exact); + return matching_signature(state, actual_parameters, allow_builtins, + &is_exact); } ir_function_signature * ir_function::matching_signature(_mesa_glsl_parse_state *state, const exec_list *actual_parameters, + bool allow_builtins, bool *is_exact) { ir_function_signature **inexact_matches = NULL; @@ -308,7 +311,8 @@ ir_function::matching_signature(_mesa_glsl_parse_state *state, */ foreach_in_list(ir_function_signature, sig, &this->signatures) { /* Skip over any built-ins that aren't available in this shader. */ - if (sig->is_builtin() && !sig->is_builtin_available(state)) + if (sig->is_builtin() && (!allow_builtins || + !sig->is_builtin_available(state))) continue; switch (parameter_lists_match(state, & sig->parameters, actual_parameters)) { diff --git a/mesalib/src/glsl/ir_reader.cpp b/mesalib/src/glsl/ir_reader.cpp index e3566e1d6..ae00e7934 100644 --- a/mesalib/src/glsl/ir_reader.cpp +++ b/mesalib/src/glsl/ir_reader.cpp @@ -677,7 +677,8 @@ ir_reader::read_call(s_expression *expr) return NULL; } - ir_function_signature *callee = f->matching_signature(state, ¶meters); + ir_function_signature *callee = + f->matching_signature(state, ¶meters, true); if (callee == NULL) { ir_read_error(expr, "couldn't find matching signature for function " "%s", name->value()); diff --git a/mesalib/src/glsl/ir_variable_refcount.cpp b/mesalib/src/glsl/ir_variable_refcount.cpp index 923eb1a82..f67fe6784 100644 --- a/mesalib/src/glsl/ir_variable_refcount.cpp +++ b/mesalib/src/glsl/ir_variable_refcount.cpp @@ -33,7 +33,7 @@ #include "ir_visitor.h" #include "ir_variable_refcount.h" #include "glsl_types.h" -#include "main/hash_table.h" +#include "util/hash_table.h" ir_variable_refcount_visitor::ir_variable_refcount_visitor() { diff --git a/mesalib/src/glsl/link_functions.cpp b/mesalib/src/glsl/link_functions.cpp index 2ce9609b5..f86aec689 100644 --- a/mesalib/src/glsl/link_functions.cpp +++ b/mesalib/src/glsl/link_functions.cpp @@ -307,7 +307,7 @@ find_matching_signature(const char *name, const exec_list *actual_parameters, continue; ir_function_signature *sig = - f->matching_signature(NULL, actual_parameters); + f->matching_signature(NULL, actual_parameters, use_builtin); if ((sig == NULL) || (!sig->is_defined && !sig->is_intrinsic)) diff --git a/mesalib/src/glsl/link_uniform_block_active_visitor.cpp b/mesalib/src/glsl/link_uniform_block_active_visitor.cpp index 854309f9b..9da6a4bba 100644 --- a/mesalib/src/glsl/link_uniform_block_active_visitor.cpp +++ b/mesalib/src/glsl/link_uniform_block_active_visitor.cpp @@ -73,6 +73,45 @@ process_block(void *mem_ctx, struct hash_table *ht, ir_variable *var) } ir_visitor_status +link_uniform_block_active_visitor::visit(ir_variable *var) +{ + if (!var->is_in_uniform_block()) + return visit_continue; + + const glsl_type *const block_type = var->is_interface_instance() + ? var->type : var->get_interface_type(); + + /* Section 2.11.6 (Uniform Variables) of the OpenGL ES 3.0.3 spec says: + * + * "All members of a named uniform block declared with a shared or + * std140 layout qualifier are considered active, even if they are not + * referenced in any shader in the program. The uniform block itself is + * also considered active, even if no member of the block is + * referenced." + */ + if (block_type->interface_packing == GLSL_INTERFACE_PACKING_PACKED) + return visit_continue; + + /* Process the block. Bail if there was an error. + */ + link_uniform_block_active *const b = + process_block(this->mem_ctx, this->ht, var); + if (b == NULL) { + linker_error(this->prog, + "uniform block `%s' has mismatching definitions", + var->get_interface_type()->name); + this->success = false; + return visit_stop; + } + + assert(b->num_array_elements == 0); + assert(b->array_elements == NULL); + assert(b->type != NULL); + + return visit_continue; +} + +ir_visitor_status link_uniform_block_active_visitor::visit_enter(ir_dereference_array *ir) { ir_dereference_variable *const d = ir->array->as_dereference_variable(); diff --git a/mesalib/src/glsl/link_uniform_block_active_visitor.h b/mesalib/src/glsl/link_uniform_block_active_visitor.h index 524cd6b91..e5ea50155 100644 --- a/mesalib/src/glsl/link_uniform_block_active_visitor.h +++ b/mesalib/src/glsl/link_uniform_block_active_visitor.h @@ -26,7 +26,7 @@ #define LINK_UNIFORM_BLOCK_ACTIVE_VISITOR_H #include "ir.h" -#include "main/hash_table.h" +#include "util/hash_table.h" struct link_uniform_block_active { const glsl_type *type; @@ -51,6 +51,7 @@ public: virtual ir_visitor_status visit_enter(ir_dereference_array *); virtual ir_visitor_status visit(ir_dereference_variable *); + virtual ir_visitor_status visit(ir_variable *); bool success; diff --git a/mesalib/src/glsl/link_uniform_blocks.cpp b/mesalib/src/glsl/link_uniform_blocks.cpp index fef3626bf..536fcd458 100644 --- a/mesalib/src/glsl/link_uniform_blocks.cpp +++ b/mesalib/src/glsl/link_uniform_blocks.cpp @@ -26,7 +26,7 @@ #include "linker.h" #include "ir_uniform.h" #include "link_uniform_block_active_visitor.h" -#include "main/hash_table.h" +#include "util/hash_table.h" #include "program.h" namespace { @@ -68,7 +68,8 @@ private: } virtual void visit_field(const glsl_type *type, const char *name, - bool row_major, const glsl_type *record_type) + bool row_major, const glsl_type *record_type, + bool last_field) { assert(this->index < this->num_variables); @@ -76,7 +77,7 @@ private: v->Name = ralloc_strdup(mem_ctx, name); v->Type = type; - v->RowMajor = row_major; + v->RowMajor = type->without_array()->is_matrix() && row_major; if (this->is_array_instance) { v->IndexName = ralloc_strdup(mem_ctx, name); @@ -103,7 +104,20 @@ private: this->offset = glsl_align(this->offset, alignment); v->Offset = this->offset; + + /* If this is the last field of a structure, apply rule #9. The + * GL_ARB_uniform_buffer_object spec says: + * + * "The structure may have padding at the end; the base offset of + * the member following the sub-structure is rounded up to the next + * multiple of the base alignment of the structure." + * + * last_field won't be set if this is the last field of a UBO that is + * not a named instance. + */ this->offset += size; + if (last_field) + this->offset = glsl_align(this->offset, 16); /* From the GL_ARB_uniform_buffer_object spec: * diff --git a/mesalib/src/glsl/link_uniforms.cpp b/mesalib/src/glsl/link_uniforms.cpp index 6c731976b..3251097bc 100644 --- a/mesalib/src/glsl/link_uniforms.cpp +++ b/mesalib/src/glsl/link_uniforms.cpp @@ -59,13 +59,11 @@ values_for_type(const glsl_type *type) void program_resource_visitor::process(const glsl_type *type, const char *name) { - assert(type->is_record() - || (type->is_array() && type->fields.array->is_record()) - || type->is_interface() - || (type->is_array() && type->fields.array->is_interface())); + assert(type->without_array()->is_record() + || type->without_array()->is_interface()); char *name_copy = ralloc_strdup(NULL, name); - recursion(type, &name_copy, strlen(name), false, NULL); + recursion(type, &name_copy, strlen(name), false, NULL, false); ralloc_free(name_copy); } @@ -73,6 +71,8 @@ void program_resource_visitor::process(ir_variable *var) { const glsl_type *t = var->type; + const bool row_major = + var->data.matrix_layout == GLSL_MATRIX_LAYOUT_ROW_MAJOR; /* false is always passed for the row_major parameter to the other * processing functions because no information is available to do @@ -110,7 +110,7 @@ program_resource_visitor::process(ir_variable *var) * lowering is only applied to non-uniform interface blocks, so we * can safely pass false for row_major. */ - recursion(var->type, &name, new_length, false, NULL); + recursion(var->type, &name, new_length, row_major, NULL, false); } ralloc_free(name); } else if (var->data.from_named_ifc_block_nonarray) { @@ -134,29 +134,30 @@ program_resource_visitor::process(ir_variable *var) * is only applied to non-uniform interface blocks, so we can safely * pass false for row_major. */ - recursion(var->type, &name, strlen(name), false, NULL); + recursion(var->type, &name, strlen(name), row_major, NULL, false); ralloc_free(name); - } else if (t->is_record() || (t->is_array() && t->fields.array->is_record())) { + } else if (t->without_array()->is_record()) { char *name = ralloc_strdup(NULL, var->name); - recursion(var->type, &name, strlen(name), false, NULL); + recursion(var->type, &name, strlen(name), row_major, NULL, false); ralloc_free(name); } else if (t->is_interface()) { char *name = ralloc_strdup(NULL, var->type->name); - recursion(var->type, &name, strlen(name), false, NULL); + recursion(var->type, &name, strlen(name), row_major, NULL, false); ralloc_free(name); } else if (t->is_array() && t->fields.array->is_interface()) { char *name = ralloc_strdup(NULL, var->type->fields.array->name); - recursion(var->type, &name, strlen(name), false, NULL); + recursion(var->type, &name, strlen(name), row_major, NULL, false); ralloc_free(name); } else { - this->visit_field(t, var->name, false, NULL); + this->visit_field(t, var->name, row_major, NULL, false); } } void program_resource_visitor::recursion(const glsl_type *t, char **name, size_t name_length, bool row_major, - const glsl_type *record_type) + const glsl_type *record_type, + bool last_field) { /* Records need to have each field processed individually. * @@ -182,8 +183,25 @@ program_resource_visitor::recursion(const glsl_type *t, char **name, ralloc_asprintf_rewrite_tail(name, &new_length, ".%s", field); } + /* The layout of structures at the top level of the block is set + * during parsing. For matrices contained in multiple levels of + * structures in the block, the inner structures have no layout. + * These cases must potentially inherit the layout from the outer + * levels. + */ + bool field_row_major = row_major; + const enum glsl_matrix_layout matrix_layout = + glsl_matrix_layout(t->fields.structure[i].matrix_layout); + if (matrix_layout == GLSL_MATRIX_LAYOUT_ROW_MAJOR) { + field_row_major = true; + } else if (matrix_layout == GLSL_MATRIX_LAYOUT_COLUMN_MAJOR) { + field_row_major = false; + } + recursion(t->fields.structure[i].type, name, new_length, - t->fields.structure[i].row_major, record_type); + field_row_major, + record_type, + (i + 1) == t->length); /* Only the first leaf-field of the record gets called with the * record type pointer. @@ -202,7 +220,8 @@ program_resource_visitor::recursion(const glsl_type *t, char **name, ralloc_asprintf_rewrite_tail(name, &new_length, "[%u]", i); recursion(t->fields.array, name, new_length, row_major, - record_type); + record_type, + (i + 1) == t->length); /* Only the first leaf-field of the record gets called with the * record type pointer. @@ -210,14 +229,15 @@ program_resource_visitor::recursion(const glsl_type *t, char **name, record_type = NULL; } } else { - this->visit_field(t, *name, row_major, record_type); + this->visit_field(t, *name, row_major, record_type, last_field); } } void program_resource_visitor::visit_field(const glsl_type *type, const char *name, bool row_major, - const glsl_type *) + const glsl_type *, + bool /* last_field */) { visit_field(type, name, row_major); } @@ -299,10 +319,8 @@ private: virtual void visit_field(const glsl_type *type, const char *name, bool row_major) { - assert(!type->is_record()); - assert(!(type->is_array() && type->fields.array->is_record())); - assert(!type->is_interface()); - assert(!(type->is_array() && type->fields.array->is_interface())); + assert(!type->without_array()->is_record()); + assert(!type->without_array()->is_interface()); (void) row_major; @@ -427,7 +445,6 @@ public: */ if (var->is_interface_instance()) { ubo_byte_offset = 0; - ubo_row_major = false; } else { const struct gl_uniform_block *const block = &prog->UniformBlocks[ubo_block_index]; @@ -437,7 +454,6 @@ public: const struct gl_uniform_buffer_variable *const ubo_var = &block->Uniforms[var->data.location]; - ubo_row_major = ubo_var->RowMajor; ubo_byte_offset = ubo_var->Offset; } @@ -452,7 +468,6 @@ public: int ubo_block_index; int ubo_byte_offset; - bool ubo_row_major; gl_shader_stage shader_type; private: @@ -512,14 +527,11 @@ private: } virtual void visit_field(const glsl_type *type, const char *name, - bool row_major, const glsl_type *record_type) + bool row_major, const glsl_type *record_type, + bool last_field) { - assert(!type->is_record()); - assert(!(type->is_array() && type->fields.array->is_record())); - assert(!type->is_interface()); - assert(!(type->is_array() && type->fields.array->is_interface())); - - (void) row_major; + assert(!type->without_array()->is_record()); + assert(!type->without_array()->is_interface()); unsigned id; bool found = this->map->get(id, name); @@ -577,23 +589,25 @@ private: this->uniforms[id].block_index = this->ubo_block_index; const unsigned alignment = record_type - ? record_type->std140_base_alignment(ubo_row_major) - : type->std140_base_alignment(ubo_row_major); + ? record_type->std140_base_alignment(row_major) + : type->std140_base_alignment(row_major); this->ubo_byte_offset = glsl_align(this->ubo_byte_offset, alignment); this->uniforms[id].offset = this->ubo_byte_offset; - this->ubo_byte_offset += type->std140_size(ubo_row_major); + this->ubo_byte_offset += type->std140_size(row_major); + + if (last_field) + this->ubo_byte_offset = glsl_align(this->ubo_byte_offset, 16); if (type->is_array()) { this->uniforms[id].array_stride = - glsl_align(type->fields.array->std140_size(ubo_row_major), 16); + glsl_align(type->fields.array->std140_size(row_major), 16); } else { this->uniforms[id].array_stride = 0; } - if (type->is_matrix() || - (type->is_array() && type->fields.array->is_matrix())) { + if (type->without_array()->is_matrix()) { this->uniforms[id].matrix_stride = 16; - this->uniforms[id].row_major = ubo_row_major; + this->uniforms[id].row_major = row_major; } else { this->uniforms[id].matrix_stride = 0; this->uniforms[id].row_major = false; diff --git a/mesalib/src/glsl/link_varyings.cpp b/mesalib/src/glsl/link_varyings.cpp index a3fc2ae34..1438a4b16 100644 --- a/mesalib/src/glsl/link_varyings.cpp +++ b/mesalib/src/glsl/link_varyings.cpp @@ -1068,10 +1068,8 @@ private: virtual void visit_field(const glsl_type *type, const char *name, bool row_major) { - assert(!type->is_record()); - assert(!(type->is_array() && type->fields.array->is_record())); - assert(!type->is_interface()); - assert(!(type->is_array() && type->fields.array->is_interface())); + assert(!type->without_array()->is_record()); + assert(!type->without_array()->is_interface()); (void) row_major; diff --git a/mesalib/src/glsl/linker.cpp b/mesalib/src/glsl/linker.cpp index d588bc63e..0096fb023 100644 --- a/mesalib/src/glsl/linker.cpp +++ b/mesalib/src/glsl/linker.cpp @@ -1129,7 +1129,8 @@ get_main_function_signature(gl_shader *sh) * We don't have to check for multiple definitions of main (in multiple * shaders) because that would have already been caught above. */ - ir_function_signature *sig = f->matching_signature(NULL, &void_parameters); + ir_function_signature *sig = + f->matching_signature(NULL, &void_parameters, false); if ((sig != NULL) && sig->is_defined) { return sig; } diff --git a/mesalib/src/glsl/linker.h b/mesalib/src/glsl/linker.h index 130915db4..8851da6c8 100644 --- a/mesalib/src/glsl/linker.h +++ b/mesalib/src/glsl/linker.h @@ -138,11 +138,15 @@ protected: * \param name Fully qualified name of the field. * \param row_major For a matrix type, is it stored row-major. * \param record_type Type of the record containing the field. + * \param last_field Set if \c name is the last field of the structure + * containing it. This will always be false for items + * not contained in a structure or interface block. * * The default implementation just calls the other \c visit_field method. */ virtual void visit_field(const glsl_type *type, const char *name, - bool row_major, const glsl_type *record_type); + bool row_major, const glsl_type *record_type, + bool last_field); /** * Method invoked for each leaf of the variable @@ -168,9 +172,13 @@ private: /** * \param name_length Length of the current name \b not including the * terminating \c NUL character. + * \param last_field Set if \c name is the last field of the structure + * containing it. This will always be false for items + * not contained in a structure or interface block. */ void recursion(const glsl_type *t, char **name, size_t name_length, - bool row_major, const glsl_type *record_type); + bool row_major, const glsl_type *record_type, + bool last_field); }; void diff --git a/mesalib/src/glsl/list.h b/mesalib/src/glsl/list.h index 3ee6cdaa9..b6c32bccc 100644 --- a/mesalib/src/glsl/list.h +++ b/mesalib/src/glsl/list.h @@ -69,7 +69,7 @@ #endif #include <assert.h> -#include "ralloc.h" +#include "util/ralloc.h" struct exec_node { struct exec_node *next; diff --git a/mesalib/src/glsl/loop_controls.cpp b/mesalib/src/glsl/loop_controls.cpp index 36b49eb46..1c1d34fef 100644 --- a/mesalib/src/glsl/loop_controls.cpp +++ b/mesalib/src/glsl/loop_controls.cpp @@ -123,9 +123,20 @@ calculate_iterations(ir_rvalue *from, ir_rvalue *to, ir_rvalue *increment, bool valid_loop = false; for (unsigned i = 0; i < Elements(bias); i++) { - iter = (increment->type->is_integer()) - ? new(mem_ctx) ir_constant(iter_value + bias[i]) - : new(mem_ctx) ir_constant(float(iter_value + bias[i])); + /* Increment may be of type int, uint or float. */ + switch (increment->type->base_type) { + case GLSL_TYPE_INT: + iter = new(mem_ctx) ir_constant(iter_value + bias[i]); + break; + case GLSL_TYPE_UINT: + iter = new(mem_ctx) ir_constant(unsigned(iter_value + bias[i])); + break; + case GLSL_TYPE_FLOAT: + iter = new(mem_ctx) ir_constant(float(iter_value + bias[i])); + break; + default: + unreachable(!"Unsupported type for loop iterator."); + } ir_expression *const mul = new(mem_ctx) ir_expression(ir_binop_mul, increment->type, iter, diff --git a/mesalib/src/glsl/lower_packed_varyings.cpp b/mesalib/src/glsl/lower_packed_varyings.cpp index c72b80a32..780148315 100644 --- a/mesalib/src/glsl/lower_packed_varyings.cpp +++ b/mesalib/src/glsl/lower_packed_varyings.cpp @@ -655,7 +655,7 @@ lower_packed_varyings(void *mem_ctx, unsigned locations_used, ir_function *main_func = shader->symbols->get_function("main"); exec_list void_parameters; ir_function_signature *main_func_sig - = main_func->matching_signature(NULL, &void_parameters); + = main_func->matching_signature(NULL, &void_parameters, false); exec_list new_instructions; lower_packed_varyings_visitor visitor(mem_ctx, locations_used, mode, gs_input_vertices, &new_instructions); diff --git a/mesalib/src/glsl/lower_ubo_reference.cpp b/mesalib/src/glsl/lower_ubo_reference.cpp index 67b752d3d..3cdfc04ac 100644 --- a/mesalib/src/glsl/lower_ubo_reference.cpp +++ b/mesalib/src/glsl/lower_ubo_reference.cpp @@ -40,6 +40,96 @@ using namespace ir_builder; +/** + * Determine if a thing being dereferenced is row-major + * + * There is some trickery here. + * + * If the thing being dereferenced is a member of uniform block \b without an + * instance name, then the name of the \c ir_variable is the field name of an + * interface type. If this field is row-major, then the thing referenced is + * row-major. + * + * If the thing being dereferenced is a member of uniform block \b with an + * instance name, then the last dereference in the tree will be an + * \c ir_dereference_record. If that record field is row-major, then the + * thing referenced is row-major. + */ +static bool +is_dereferenced_thing_row_major(const ir_dereference *deref) +{ + bool matrix = false; + const ir_rvalue *ir = deref; + + while (true) { + matrix = matrix || ir->type->without_array()->is_matrix(); + + switch (ir->ir_type) { + case ir_type_dereference_array: { + const ir_dereference_array *const array_deref = + (const ir_dereference_array *) ir; + + ir = array_deref->array; + break; + } + + case ir_type_dereference_record: { + const ir_dereference_record *const record_deref = + (const ir_dereference_record *) ir; + + ir = record_deref->record; + + const int idx = ir->type->field_index(record_deref->field); + assert(idx >= 0); + + const enum glsl_matrix_layout matrix_layout = + glsl_matrix_layout(ir->type->fields.structure[idx].matrix_layout); + + switch (matrix_layout) { + case GLSL_MATRIX_LAYOUT_INHERITED: + break; + case GLSL_MATRIX_LAYOUT_COLUMN_MAJOR: + return false; + case GLSL_MATRIX_LAYOUT_ROW_MAJOR: + return matrix || deref->type->without_array()->is_record(); + } + + break; + } + + case ir_type_dereference_variable: { + const ir_dereference_variable *const var_deref = + (const ir_dereference_variable *) ir; + + const enum glsl_matrix_layout matrix_layout = + glsl_matrix_layout(var_deref->var->data.matrix_layout); + + switch (matrix_layout) { + case GLSL_MATRIX_LAYOUT_INHERITED: + assert(!matrix); + return false; + case GLSL_MATRIX_LAYOUT_COLUMN_MAJOR: + return false; + case GLSL_MATRIX_LAYOUT_ROW_MAJOR: + return matrix || deref->type->is_record(); + } + + unreachable("invalid matrix layout"); + break; + } + + default: + return false; + } + } + + /* The tree must have ended with a dereference that wasn't an + * ir_dereference_variable. That is invalid, and it should be impossible. + */ + unreachable("invalid dereference tree"); + return false; +} + namespace { class lower_ubo_reference_visitor : public ir_rvalue_enter_visitor { public: @@ -50,7 +140,7 @@ public: void handle_rvalue(ir_rvalue **rvalue); void emit_ubo_loads(ir_dereference *deref, ir_variable *base_offset, - unsigned int deref_offset); + unsigned int deref_offset, bool row_major); ir_expression *ubo_load(const struct glsl_type *type, ir_rvalue *offset); @@ -174,7 +264,7 @@ lower_ubo_reference_visitor::handle_rvalue(ir_rvalue **rvalue) ir_rvalue *offset = new(mem_ctx) ir_constant(0u); unsigned const_offset = 0; - bool row_major = ubo_var->RowMajor; + bool row_major = is_dereferenced_thing_row_major(deref); /* Calculate the offset to the start of the region of the UBO * dereferenced by *rvalue. This may be a variable offset if an @@ -219,7 +309,8 @@ lower_ubo_reference_visitor::handle_rvalue(ir_rvalue **rvalue) if (array_index->type->base_type == GLSL_TYPE_INT) array_index = i2u(array_index); - ir_constant *const_index = array_index->as_constant(); + ir_constant *const_index = + array_index->constant_expression_value(NULL); if (const_index) { const_offset += array_stride * const_index->value.u[0]; } else { @@ -236,20 +327,27 @@ lower_ubo_reference_visitor::handle_rvalue(ir_rvalue **rvalue) const glsl_type *struct_type = deref_record->record->type; unsigned intra_struct_offset = 0; - unsigned max_field_align = 16; for (unsigned int i = 0; i < struct_type->length; i++) { const glsl_type *type = struct_type->fields.structure[i].type; - unsigned field_align = type->std140_base_alignment(row_major); - max_field_align = MAX2(field_align, max_field_align); + + ir_dereference_record *field_deref = + new(mem_ctx) ir_dereference_record(deref_record->record, + struct_type->fields.structure[i].name); + const bool field_row_major = + is_dereferenced_thing_row_major(field_deref); + + ralloc_free(field_deref); + + unsigned field_align = type->std140_base_alignment(field_row_major); + intra_struct_offset = glsl_align(intra_struct_offset, field_align); if (strcmp(struct_type->fields.structure[i].name, deref_record->field) == 0) break; - intra_struct_offset += type->std140_size(row_major); + intra_struct_offset += type->std140_size(field_row_major); } - const_offset = glsl_align(const_offset, max_field_align); const_offset += intra_struct_offset; deref = deref_record->record->as_dereference(); @@ -278,7 +376,7 @@ lower_ubo_reference_visitor::handle_rvalue(ir_rvalue **rvalue) base_ir->insert_before(assign(load_offset, offset)); deref = new(mem_ctx) ir_dereference_variable(load_var); - emit_ubo_loads(deref, load_offset, const_offset); + emit_ubo_loads(deref, load_offset, const_offset, row_major); *rvalue = deref; progress = true; @@ -308,7 +406,8 @@ lower_ubo_reference_visitor::ubo_load(const glsl_type *type, void lower_ubo_reference_visitor::emit_ubo_loads(ir_dereference *deref, ir_variable *base_offset, - unsigned int deref_offset) + unsigned int deref_offset, + bool row_major) { if (deref->type->is_record()) { unsigned int field_offset = 0; @@ -322,18 +421,19 @@ lower_ubo_reference_visitor::emit_ubo_loads(ir_dereference *deref, field_offset = glsl_align(field_offset, - field->type->std140_base_alignment(ubo_var->RowMajor)); + field->type->std140_base_alignment(row_major)); - emit_ubo_loads(field_deref, base_offset, deref_offset + field_offset); + emit_ubo_loads(field_deref, base_offset, deref_offset + field_offset, + row_major); - field_offset += field->type->std140_size(ubo_var->RowMajor); + field_offset += field->type->std140_size(row_major); } return; } if (deref->type->is_array()) { unsigned array_stride = - glsl_align(deref->type->fields.array->std140_size(ubo_var->RowMajor), + glsl_align(deref->type->fields.array->std140_size(row_major), 16); for (unsigned i = 0; i < deref->type->length; i++) { @@ -342,7 +442,8 @@ lower_ubo_reference_visitor::emit_ubo_loads(ir_dereference *deref, new(mem_ctx) ir_dereference_array(deref->clone(mem_ctx, NULL), element); emit_ubo_loads(element_deref, base_offset, - deref_offset + i * array_stride); + deref_offset + i * array_stride, + row_major); } return; } @@ -354,10 +455,19 @@ lower_ubo_reference_visitor::emit_ubo_loads(ir_dereference *deref, new(mem_ctx) ir_dereference_array(deref->clone(mem_ctx, NULL), col); - /* std140 always rounds the stride of arrays (and matrices) - * to a vec4, so matrices are always 16 between columns/rows. - */ - emit_ubo_loads(col_deref, base_offset, deref_offset + i * 16); + if (row_major) { + /* For a row-major matrix, the next column starts at the next + * element. + */ + emit_ubo_loads(col_deref, base_offset, deref_offset + i * 4, + row_major); + } else { + /* std140 always rounds the stride of arrays (and matrices) to a + * vec4, so matrices are always 16 between columns/rows. + */ + emit_ubo_loads(col_deref, base_offset, deref_offset + i * 16, + row_major); + } } return; } @@ -365,7 +475,7 @@ lower_ubo_reference_visitor::emit_ubo_loads(ir_dereference *deref, assert(deref->type->is_scalar() || deref->type->is_vector()); - if (!ubo_var->RowMajor) { + if (!row_major) { ir_rvalue *offset = add(base_offset, new(mem_ctx) ir_constant(deref_offset)); base_ir->insert_before(assign(deref->clone(mem_ctx, NULL), diff --git a/mesalib/src/glsl/opt_dead_code.cpp b/mesalib/src/glsl/opt_dead_code.cpp index da90bfb40..f45bf5dfd 100644 --- a/mesalib/src/glsl/opt_dead_code.cpp +++ b/mesalib/src/glsl/opt_dead_code.cpp @@ -31,7 +31,7 @@ #include "ir_visitor.h" #include "ir_variable_refcount.h" #include "glsl_types.h" -#include "main/hash_table.h" +#include "util/hash_table.h" static bool debug = false; @@ -99,10 +99,31 @@ do_dead_code(exec_list *instructions, bool uniform_locations_assigned) * stage. Also, once uniform locations have been assigned, the * declaration cannot be deleted. */ - if (entry->var->data.mode == ir_var_uniform && - (uniform_locations_assigned || - entry->var->constant_value)) - continue; + if (entry->var->data.mode == ir_var_uniform) { + if (uniform_locations_assigned || entry->var->constant_value) + continue; + + /* Section 2.11.6 (Uniform Variables) of the OpenGL ES 3.0.3 spec + * says: + * + * "All members of a named uniform block declared with a + * shared or std140 layout qualifier are considered active, + * even if they are not referenced in any shader in the + * program. The uniform block itself is also considered + * active, even if no member of the block is referenced." + * + * If the variable is in a uniform block with one of those + * layouts, do not eliminate it. + */ + if (entry->var->is_in_uniform_block()) { + const glsl_type *const block_type = + entry->var->is_interface_instance() + ? entry->var->type : entry->var->get_interface_type(); + + if (block_type->interface_packing != GLSL_INTERFACE_PACKING_PACKED) + continue; + } + } entry->var->remove(); progress = true; diff --git a/mesalib/src/glsl/standalone_scaffolding.cpp b/mesalib/src/glsl/standalone_scaffolding.cpp index 809732c7e..abdd83a44 100644 --- a/mesalib/src/glsl/standalone_scaffolding.cpp +++ b/mesalib/src/glsl/standalone_scaffolding.cpp @@ -31,7 +31,7 @@ #include <assert.h> #include <string.h> -#include "ralloc.h" +#include "util/ralloc.h" void _mesa_warning(struct gl_context *ctx, const char *fmt, ...) diff --git a/mesalib/src/loader/Makefile.am b/mesalib/src/loader/Makefile.am index c02de6f59..16b9f8f70 100644 --- a/mesalib/src/loader/Makefile.am +++ b/mesalib/src/loader/Makefile.am @@ -26,6 +26,7 @@ noinst_LTLIBRARIES = libloader.la libloader_la_CPPFLAGS = \ $(DEFINES) \ -I$(top_srcdir)/include \ + -I$(top_srcdir)/src \ $(VISIBILITY_CFLAGS) \ $(LIBUDEV_CFLAGS) diff --git a/mesalib/src/mapi/glapi/gen/ARB_copy_image.xml b/mesalib/src/mapi/glapi/gen/ARB_copy_image.xml new file mode 100644 index 000000000..2fbd84557 --- /dev/null +++ b/mesalib/src/mapi/glapi/gen/ARB_copy_image.xml @@ -0,0 +1,28 @@ +<?xml version="1.0"?> +<!DOCTYPE OpenGLAPI SYSTEM "gl_API.dtd"> + +<OpenGLAPI> + +<category name="GL_ARB_copy_image" number="123"> + + <function name="CopyImageSubData" offset="assign"> + <param name="srcName" type="GLuint"/> + <param name="srcTarget" type="GLenum"/> + <param name="srcLevel" type="GLint"/> + <param name="srcX" type="GLint"/> + <param name="srcY" type="GLint"/> + <param name="srcZ" type="GLint"/> + <param name="dstName" type="GLuint"/> + <param name="dstTarget" type="GLenum"/> + <param name="dstLevel" type="GLint"/> + <param name="dstX" type="GLint"/> + <param name="dstY" type="GLint"/> + <param name="dstZ" type="GLint"/> + <param name="srcWidth" type="GLsizei"/> + <param name="srcHeight" type="GLsizei"/> + <param name="srcDepth" type="GLsizei"/> + </function> + +</category> + +</OpenGLAPI> diff --git a/mesalib/src/mapi/glapi/gen/GL4x.xml b/mesalib/src/mapi/glapi/gen/GL4x.xml index 8efef0b91..848316e9e 100644 --- a/mesalib/src/mapi/glapi/gen/GL4x.xml +++ b/mesalib/src/mapi/glapi/gen/GL4x.xml @@ -12,6 +12,32 @@ <function name="MinSampleShading" offset="assign"> <param name="value" type="GLfloat"/> </function> + + <function name="BlendFunci" static_dispatch="false" alias="BlendFunciARB"> + <param name="buf" type="GLuint"/> + <param name="sfactor" type="GLenum"/> + <param name="dfactor" type="GLenum"/> + </function> + + <function name="BlendFuncSeparatei" static_dispatch="false" alias="BlendFuncSeparateiARB"> + <param name="buf" type="GLuint"/> + <param name="sfactorRGB" type="GLenum"/> + <param name="dfactorRGB" type="GLenum"/> + <param name="sfactorAlpha" type="GLenum"/> + <param name="dfactorAlpha" type="GLenum"/> + </function> + + <function name="BlendEquationi" static_dispatch="false" alias="BlendEquationiARB"> + <param name="buf" type="GLuint"/> + <param name="mode" type="GLenum"/> + </function> + + <function name="BlendEquationSeparatei" static_dispatch="false" alias="BlendEquationSeparateiARB" > + <param name="buf" type="GLuint"/> + <param name="modeRGB" type="GLenum"/> + <param name="modeA" type="GLenum"/> + </function> + </category> <category name="4.3"> diff --git a/mesalib/src/mapi/glapi/gen/Makefile.am b/mesalib/src/mapi/glapi/gen/Makefile.am index 212731fa4..645def4ef 100644 --- a/mesalib/src/mapi/glapi/gen/Makefile.am +++ b/mesalib/src/mapi/glapi/gen/Makefile.am @@ -117,6 +117,7 @@ API_XML = \ ARB_compressed_texture_pixel_storage.xml \ ARB_compute_shader.xml \ ARB_copy_buffer.xml \ + ARB_copy_image.xml \ ARB_debug_output.xml \ ARB_depth_buffer_float.xml \ ARB_depth_clamp.xml \ diff --git a/mesalib/src/mapi/glapi/gen/gl_API.xml b/mesalib/src/mapi/glapi/gen/gl_API.xml index e011509e5..619717d9e 100644 --- a/mesalib/src/mapi/glapi/gen/gl_API.xml +++ b/mesalib/src/mapi/glapi/gen/gl_API.xml @@ -8302,7 +8302,7 @@ <xi:include href="ARB_compute_shader.xml" xmlns:xi="http://www.w3.org/2001/XInclude"/> -<!-- ARB extension #123 --> +<xi:include href="ARB_copy_image.xml" xmlns:xi="http://www.w3.org/2001/XInclude"/> <xi:include href="ARB_texture_view.xml" xmlns:xi="http://www.w3.org/2001/XInclude"/> diff --git a/mesalib/src/mapi/glapi/gen/gl_genexec.py b/mesalib/src/mapi/glapi/gen/gl_genexec.py index 460919397..d479e66da 100644 --- a/mesalib/src/mapi/glapi/gen/gl_genexec.py +++ b/mesalib/src/mapi/glapi/gen/gl_genexec.py @@ -62,6 +62,7 @@ header = """/** #include "main/condrender.h" #include "main/context.h" #include "main/convolve.h" +#include "main/copyimage.h" #include "main/depth.h" #include "main/dlist.h" #include "main/drawpix.h" diff --git a/mesalib/src/mapi/glapi/gen/gl_gentable.py b/mesalib/src/mapi/glapi/gen/gl_gentable.py index 9db6a773a..7577b66a6 100644 --- a/mesalib/src/mapi/glapi/gen/gl_gentable.py +++ b/mesalib/src/mapi/glapi/gen/gl_gentable.py @@ -42,7 +42,7 @@ header = """/* GLXEXT is the define used in the xserver when the GLX extension i #endif #if (defined(GLXEXT) && defined(HAVE_BACKTRACE)) \\ - || (!defined(GLXEXT) && defined(DEBUG) && !defined(_WIN32_WCE) && !defined(__CYGWIN__) && !defined(__MINGW32__) && !defined(__OpenBSD__) && !defined(__NetBSD__)) + || (!defined(GLXEXT) && defined(DEBUG) && !defined(_WIN32_WCE) && !defined(__CYGWIN__) && !defined(__MINGW32__) && !defined(__OpenBSD__) && !defined(__NetBSD__) && !defined(__DragonFly__)) #define USE_BACKTRACE #endif diff --git a/mesalib/src/mesa/Makefile.am b/mesalib/src/mesa/Makefile.am index 88eeff9ee..57c1e4a57 100644 --- a/mesalib/src/mesa/Makefile.am +++ b/mesalib/src/mesa/Makefile.am @@ -64,6 +64,7 @@ include Makefile.sources BUILT_SOURCES = \ main/get_hash.h \ + main/format_info.c \ $(BUILDDIR)main/git_sha1.h \ $(BUILDDIR)program/program_parse.tab.c \ $(BUILDDIR)program/lex.yy.c @@ -81,6 +82,15 @@ main/get_hash.h: $(GLAPI)/gl_and_es_API.xml main/get_hash_params.py \ -f $< > $@.tmp; \ mv $@.tmp $@; +main/format_info.c: main/formats.csv \ + main/format_parser.py main/format_info.py + $(AM_V_GEN)set -e; \ + $(PYTHON2) $(PYTHON_FLAGS) $(srcdir)/main/format_info.py \ + $< > $@.tmp; \ + mv $@.tmp $@; + +main/formats.c: main/format_info.c + noinst_LTLIBRARIES = $(ARCH_LIBS) if NEED_LIBMESA noinst_LTLIBRARIES += libmesa.la diff --git a/mesalib/src/mesa/Makefile.sources b/mesalib/src/mesa/Makefile.sources index f4904fbbd..594565771 100644 --- a/mesalib/src/mesa/Makefile.sources +++ b/mesalib/src/mesa/Makefile.sources @@ -3,6 +3,9 @@ # This file is among different build systems. SRCDIR must be defined with # a trailing slash because the Android build system leaves it undefined. +SRCDIR = $(top_srcdir)/src/mesa/ +BUILDDIR = $(top_builddir)/src/mesa/ + # this is part of MAIN_FILES MAIN_ES_FILES = \ $(SRCDIR)main/es1_conversion.c @@ -28,6 +31,7 @@ MAIN_FILES = \ $(SRCDIR)main/condrender.c \ $(SRCDIR)main/context.c \ $(SRCDIR)main/convolve.c \ + $(SRCDIR)main/copyimage.c \ $(SRCDIR)main/cpuinfo.c \ $(SRCDIR)main/debug.c \ $(SRCDIR)main/depth.c \ @@ -48,13 +52,13 @@ MAIN_FILES = \ $(SRCDIR)main/formats.c \ $(SRCDIR)main/format_pack.c \ $(SRCDIR)main/format_unpack.c \ + $(SRCDIR)main/format_utils.c \ $(SRCDIR)main/framebuffer.c \ $(SRCDIR)main/get.c \ $(SRCDIR)main/genmipmap.c \ $(SRCDIR)main/getstring.c \ $(SRCDIR)main/glformats.c \ $(SRCDIR)main/hash.c \ - $(SRCDIR)main/hash_table.c \ $(SRCDIR)main/hint.c \ $(SRCDIR)main/histogram.c \ $(SRCDIR)main/image.c \ @@ -321,6 +325,7 @@ SPARC_FILES = \ COMMON_DRIVER_FILES = \ $(SRCDIR)drivers/common/driverfuncs.c \ $(SRCDIR)drivers/common/meta_blit.c \ + $(SRCDIR)drivers/common/meta_copy_image.c \ $(SRCDIR)drivers/common/meta_generate_mipmap.c \ $(SRCDIR)drivers/common/meta.c @@ -349,6 +354,7 @@ MESA_GALLIUM_FILES = \ INCLUDE_DIRS = \ -I$(top_srcdir)/include \ + -I$(top_srcdir)/src \ -I$(top_srcdir)/src/glsl \ -I$(top_builddir)/src/glsl \ -I$(top_srcdir)/src/glsl/glcpp \ diff --git a/mesalib/src/mesa/SConscript b/mesalib/src/mesa/SConscript index f56578672..e7c4f5ca1 100644 --- a/mesalib/src/mesa/SConscript +++ b/mesalib/src/mesa/SConscript @@ -11,6 +11,7 @@ from sys import executable as python_cmd env = env.Clone() env.Append(CPPPATH = [ + '#/src', '#/src/mapi', '#/src/glsl', '#/src/mesa', @@ -31,316 +32,22 @@ else: ('HAVE_DLOPEN', '1'), ]) -# -# Source files -# - -main_sources = [ - 'main/api_arrayelt.c', - 'main/api_exec.c', - 'main/api_loopback.c', - 'main/api_validate.c', - 'main/accum.c', - 'main/arbprogram.c', - 'main/atifragshader.c', - 'main/attrib.c', - 'main/arrayobj.c', - 'main/blend.c', - 'main/blit.c', - 'main/bufferobj.c', - 'main/buffers.c', - 'main/clear.c', - 'main/clip.c', - 'main/colortab.c', - 'main/compute.c', - 'main/condrender.c', - 'main/context.c', - 'main/convolve.c', - 'main/cpuinfo.c', - 'main/debug.c', - 'main/depth.c', - 'main/dlist.c', - 'main/drawpix.c', - 'main/drawtex.c', - 'main/enable.c', - 'main/enums.c', - 'main/errors.c', - 'main/es1_conversion.c', - 'main/eval.c', - 'main/execmem.c', - 'main/extensions.c', - 'main/fbobject.c', - 'main/feedback.c', - 'main/ff_fragment_shader.cpp', - 'main/ffvertex_prog.c', - 'main/fog.c', - 'main/formatquery.c', - 'main/formats.c', - 'main/format_pack.c', - 'main/format_unpack.c', - 'main/framebuffer.c', - 'main/genmipmap.c', - 'main/getstring.c', - 'main/glformats.c', - 'main/hash.c', - 'main/hash_table.c', - 'main/hint.c', - 'main/histogram.c', - 'main/image.c', - 'main/imports.c', - 'main/light.c', - 'main/lines.c', - 'main/matrix.c', - 'main/mipmap.c', - 'main/mm.c', - 'main/multisample.c', - 'main/objectlabel.c', - 'main/pack.c', - 'main/pbo.c', - 'main/performance_monitor.c', - 'main/pipelineobj.c', - 'main/pixel.c', - 'main/pixelstore.c', - 'main/pixeltransfer.c', - 'main/points.c', - 'main/polygon.c', - 'main/querymatrix.c', - 'main/queryobj.c', - 'main/rastpos.c', - 'main/readpix.c', - 'main/remap.c', - 'main/renderbuffer.c', - 'main/samplerobj.c', - 'main/scissor.c', - 'main/set.c', - 'main/shaderapi.c', - 'main/shaderimage.c', - 'main/shaderobj.c', - 'main/shader_query.cpp', - 'main/shared.c', - 'main/state.c', - 'main/stencil.c', - 'main/syncobj.c', - 'main/texcompress.c', - 'main/texcompress_cpal.c', - 'main/texcompress_rgtc.c', - 'main/texcompress_s3tc.c', - 'main/texcompress_fxt1.c', - 'main/texcompress_etc.c', - 'main/texenv.c', - 'main/texformat.c', - 'main/texgen.c', - 'main/texgetimage.c', - 'main/teximage.c', - 'main/texobj.c', - 'main/texparam.c', - 'main/texstate.c', - 'main/texstorage.c', - 'main/texstore.c', - 'main/texturebarrier.c', - 'main/textureview.c', - 'main/transformfeedback.c', - 'main/uniform_query.cpp', - 'main/uniforms.c', - 'main/varray.c', - 'main/vdpau.c', - 'main/version.c', - 'main/viewport.c', - 'main/vtxfmt.c', -] - -glget_sources = [ - 'main/get.c', -] - -math_sources = [ - 'math/m_debug_clip.c', - 'math/m_debug_norm.c', - 'math/m_debug_xform.c', - 'math/m_eval.c', - 'math/m_matrix.c', - 'math/m_translate.c', - 'math/m_vector.c', - 'math/m_xform.c', -] - -swrast_sources = [ - 'swrast/s_aaline.c', - 'swrast/s_aatriangle.c', - 'swrast/s_alpha.c', - 'swrast/s_atifragshader.c', - 'swrast/s_bitmap.c', - 'swrast/s_blend.c', - 'swrast/s_blit.c', - 'swrast/s_clear.c', - 'swrast/s_copypix.c', - 'swrast/s_context.c', - 'swrast/s_depth.c', - 'swrast/s_drawpix.c', - 'swrast/s_feedback.c', - 'swrast/s_fog.c', - 'swrast/s_fragprog.c', - 'swrast/s_lines.c', - 'swrast/s_logic.c', - 'swrast/s_masking.c', - 'swrast/s_points.c', - 'swrast/s_renderbuffer.c', - 'swrast/s_span.c', - 'swrast/s_stencil.c', - 'swrast/s_texcombine.c', - 'swrast/s_texfetch.c', - 'swrast/s_texfilter.c', - 'swrast/s_texrender.c', - 'swrast/s_texture.c', - 'swrast/s_triangle.c', - 'swrast/s_zoom.c', -] - -swrast_setup_sources = [ - 'swrast_setup/ss_context.c', - 'swrast_setup/ss_triangle.c', -] - -tnl_sources = [ - 'tnl/t_context.c', - 'tnl/t_pipeline.c', - 'tnl/t_draw.c', - 'tnl/t_rasterpos.c', - 'tnl/t_vb_program.c', - 'tnl/t_vb_render.c', - 'tnl/t_vb_texgen.c', - 'tnl/t_vb_texmat.c', - 'tnl/t_vb_vertex.c', - 'tnl/t_vb_fog.c', - 'tnl/t_vb_light.c', - 'tnl/t_vb_normals.c', - 'tnl/t_vb_points.c', - 'tnl/t_vp_build.c', - 'tnl/t_vertex.c', - 'tnl/t_vertex_sse.c', - 'tnl/t_vertex_generic.c', -] - -vbo_sources = [ - 'vbo/vbo_context.c', - 'vbo/vbo_exec.c', - 'vbo/vbo_exec_api.c', - 'vbo/vbo_exec_array.c', - 'vbo/vbo_exec_draw.c', - 'vbo/vbo_exec_eval.c', - 'vbo/vbo_noop.c', - 'vbo/vbo_primitive_restart.c', - 'vbo/vbo_rebase.c', - 'vbo/vbo_split.c', - 'vbo/vbo_split_copy.c', - 'vbo/vbo_split_inplace.c', - 'vbo/vbo_save.c', - 'vbo/vbo_save_api.c', - 'vbo/vbo_save_draw.c', - 'vbo/vbo_save_loopback.c', -] - -statetracker_sources = [ - 'state_tracker/st_atom.c', - 'state_tracker/st_atom_array.c', - 'state_tracker/st_atom_blend.c', - 'state_tracker/st_atom_clip.c', - 'state_tracker/st_atom_constbuf.c', - 'state_tracker/st_atom_depth.c', - 'state_tracker/st_atom_framebuffer.c', - 'state_tracker/st_atom_msaa.c', - 'state_tracker/st_atom_pixeltransfer.c', - 'state_tracker/st_atom_sampler.c', - 'state_tracker/st_atom_scissor.c', - 'state_tracker/st_atom_shader.c', - 'state_tracker/st_atom_rasterizer.c', - 'state_tracker/st_atom_stipple.c', - 'state_tracker/st_atom_texture.c', - 'state_tracker/st_atom_viewport.c', - 'state_tracker/st_cb_bitmap.c', - 'state_tracker/st_cb_blit.c', - 'state_tracker/st_cb_bufferobjects.c', - 'state_tracker/st_cb_clear.c', - 'state_tracker/st_cb_condrender.c', - 'state_tracker/st_cb_flush.c', - 'state_tracker/st_cb_drawpixels.c', - 'state_tracker/st_cb_drawtex.c', - 'state_tracker/st_cb_eglimage.c', - 'state_tracker/st_cb_fbo.c', - 'state_tracker/st_cb_feedback.c', - 'state_tracker/st_cb_msaa.c', - 'state_tracker/st_cb_program.c', - 'state_tracker/st_cb_queryobj.c', - 'state_tracker/st_cb_rasterpos.c', - 'state_tracker/st_cb_readpixels.c', - 'state_tracker/st_cb_syncobj.c', - 'state_tracker/st_cb_strings.c', - 'state_tracker/st_cb_texture.c', - 'state_tracker/st_cb_texturebarrier.c', - 'state_tracker/st_cb_viewport.c', - 'state_tracker/st_cb_xformfb.c', - 'state_tracker/st_context.c', - 'state_tracker/st_debug.c', - 'state_tracker/st_draw.c', - 'state_tracker/st_draw_feedback.c', - 'state_tracker/st_extensions.c', - 'state_tracker/st_format.c', - 'state_tracker/st_glsl_to_tgsi.cpp', - 'state_tracker/st_gen_mipmap.c', - 'state_tracker/st_manager.c', - 'state_tracker/st_mesa_to_tgsi.c', - 'state_tracker/st_program.c', - 'state_tracker/st_texture.c', - 'state_tracker/st_vdpau.c', -] +# 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 = [ - 'program/arbprogparse.c', - 'program/prog_hash_table.c', - 'program/ir_to_mesa.cpp', - 'program/program.c', - 'program/program_parse_extra.c', - 'program/prog_cache.c', - 'program/prog_execute.c', - 'program/prog_instruction.c', - 'program/prog_noise.c', - 'program/prog_optimize.c', - 'program/prog_opt_constant_fold.c', - 'program/prog_parameter.c', - 'program/prog_parameter_layout.c', - 'program/prog_print.c', - 'program/prog_statevars.c', - 'program/programopt.c', - 'program/sampler.cpp', - 'program/symbol_table.c', - 'program/string_to_uint_map.cpp', +program_sources = source_lists['PROGRAM_FILES'] + [ program_lex, program_parse[0], ] -common_driver_sources = [ - 'drivers/common/driverfuncs.c', - 'drivers/common/meta.c', - 'drivers/common/meta_blit.c', - 'drivers/common/meta_generate_mipmap.c' -] - mesa_sources = ( - main_sources + - glget_sources + - math_sources + + source_lists['MESA_FILES'] + program_sources + - vbo_sources + - tnl_sources + - swrast_sources + - swrast_setup_sources + - common_driver_sources + - statetracker_sources + source_lists['STATETRACKER_FILES'] ) GLAPI = '#src/mapi/glapi/' @@ -352,6 +59,13 @@ get_hash_header = env.CodeGenerate( command = python_cmd + ' $SCRIPT ' + ' -f $SOURCE > $TARGET' ) +format_info = env.CodeGenerate( + target = 'main/format_info.c', + script = 'main/format_info.py', + source = 'main/formats.csv', + command = python_cmd + ' $SCRIPT ' + ' $SOURCE > $TARGET' +) + # # Assembly sources # @@ -364,45 +78,14 @@ if (env['gcc'] or env['clang']) and \ 'USE_3DNOW_ASM', 'USE_SSE_ASM', ]) - mesa_sources += [ - 'x86/common_x86.c', - 'x86/x86_xform.c', - 'x86/3dnow.c', - 'x86/sse.c', - 'x86/common_x86_asm.S', - 'x86/x86_xform2.S', - 'x86/x86_xform3.S', - 'x86/x86_xform4.S', - 'x86/x86_cliptest.S', - 'x86/mmx_blend.S', - 'x86/3dnow_xform1.S', - 'x86/3dnow_xform2.S', - 'x86/3dnow_xform3.S', - 'x86/3dnow_xform4.S', - 'x86/3dnow_normal.S', - 'x86/sse_xform1.S', - 'x86/sse_xform2.S', - 'x86/sse_xform3.S', - 'x86/sse_xform4.S', - 'x86/sse_normal.S', - 'x86/read_rgba_span_x86.S', - ] + mesa_sources += source_lists['X86_FILES'] elif env['machine'] == 'x86_64': env.Append(CPPDEFINES = [ 'USE_X86_64_ASM', ]) - mesa_sources += [ - 'x86/common_x86.c', - 'x86-64/x86-64.c', - 'x86-64/xform4.S', - ] + mesa_sources += source_lists['X86_64_FILES'] elif env['machine'] == 'sparc': - mesa_sources += [ - 'sparc/sparc.c', - 'sparc/sparc_clip.S', - 'sparc/norm.S', - 'sparc/xform.S', - ] + mesa_sources += source_lists['SPARC_FILES'] else: pass diff --git a/mesalib/src/mesa/drivers/common/meta.c b/mesalib/src/mesa/drivers/common/meta.c index b12898f26..a1d06d412 100644 --- a/mesalib/src/mesa/drivers/common/meta.c +++ b/mesalib/src/mesa/drivers/common/meta.c @@ -84,7 +84,7 @@ #include "drivers/common/meta.h" #include "main/enums.h" #include "main/glformats.h" -#include "../glsl/ralloc.h" +#include "util/ralloc.h" /** Return offset in bytes of the field within a vertex struct */ #define OFFSET(FIELD) ((void *) offsetof(struct vertex, FIELD)) @@ -101,18 +101,18 @@ static void meta_decompress_cleanup(struct decompress_state *decompress); static void meta_drawpix_cleanup(struct drawpix_state *drawpix); void -_mesa_meta_bind_fbo_image(GLenum attachment, +_mesa_meta_bind_fbo_image(GLenum fboTarget, GLenum attachment, struct gl_texture_image *texImage, GLuint layer) { struct gl_texture_object *texObj = texImage->TexObject; int level = texImage->Level; - GLenum target = texObj->Target; + GLenum texTarget = texObj->Target; - switch (target) { + switch (texTarget) { case GL_TEXTURE_1D: - _mesa_FramebufferTexture1D(GL_FRAMEBUFFER, + _mesa_FramebufferTexture1D(fboTarget, attachment, - target, + texTarget, texObj->Name, level); break; @@ -121,19 +121,19 @@ _mesa_meta_bind_fbo_image(GLenum attachment, case GL_TEXTURE_2D_MULTISAMPLE_ARRAY: case GL_TEXTURE_CUBE_MAP_ARRAY: case GL_TEXTURE_3D: - _mesa_FramebufferTextureLayer(GL_FRAMEBUFFER, + _mesa_FramebufferTextureLayer(fboTarget, attachment, texObj->Name, level, layer); break; default: /* 2D / cube */ - if (target == GL_TEXTURE_CUBE_MAP) - target = GL_TEXTURE_CUBE_MAP_POSITIVE_X + texImage->Face; + if (texTarget == GL_TEXTURE_CUBE_MAP) + texTarget = GL_TEXTURE_CUBE_MAP_POSITIVE_X + texImage->Face; - _mesa_FramebufferTexture2D(GL_FRAMEBUFFER, + _mesa_FramebufferTexture2D(fboTarget, attachment, - target, + texTarget, texObj->Name, level); } @@ -2732,9 +2732,9 @@ _mesa_meta_blit_shader_table_cleanup(struct blit_shader_table *table) static GLenum get_temp_image_type(struct gl_context *ctx, mesa_format format) { - GLenum baseFormat; - - baseFormat = _mesa_get_format_base_format(format); + const GLenum baseFormat = _mesa_get_format_base_format(format); + const GLenum datatype = _mesa_get_format_datatype(format); + const GLint format_red_bits = _mesa_get_format_bits(format, GL_RED_BITS); switch (baseFormat) { case GL_RGBA: @@ -2745,30 +2745,24 @@ get_temp_image_type(struct gl_context *ctx, mesa_format format) case GL_LUMINANCE: case GL_LUMINANCE_ALPHA: case GL_INTENSITY: - if (ctx->DrawBuffer->Visual.redBits <= 8) { + if (datatype == GL_INT || datatype == GL_UNSIGNED_INT) { + return datatype; + } else if (format_red_bits <= 8) { return GL_UNSIGNED_BYTE; - } else if (ctx->DrawBuffer->Visual.redBits <= 16) { + } else if (format_red_bits <= 16) { return GL_UNSIGNED_SHORT; - } else { - GLenum datatype = _mesa_get_format_datatype(format); - if (datatype == GL_INT || datatype == GL_UNSIGNED_INT) - return datatype; - return GL_FLOAT; } - case GL_DEPTH_COMPONENT: { - GLenum datatype = _mesa_get_format_datatype(format); + return GL_FLOAT; + case GL_DEPTH_COMPONENT: if (datatype == GL_FLOAT) return GL_FLOAT; else return GL_UNSIGNED_INT; - } - case GL_DEPTH_STENCIL: { - GLenum datatype = _mesa_get_format_datatype(format); + case GL_DEPTH_STENCIL: if (datatype == GL_FLOAT) return GL_FLOAT_32_UNSIGNED_INT_24_8_REV; else return GL_UNSIGNED_INT_24_8; - } default: _mesa_problem(ctx, "Unexpected format %d in get_temp_image_type()", baseFormat); @@ -2808,17 +2802,20 @@ copytexsubimage_using_blit_framebuffer(struct gl_context *ctx, GLuint dims, if (rb->_BaseFormat == GL_DEPTH_STENCIL || rb->_BaseFormat == GL_DEPTH_COMPONENT) { - _mesa_meta_bind_fbo_image(GL_DEPTH_ATTACHMENT, texImage, zoffset); + _mesa_meta_bind_fbo_image(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, + texImage, zoffset); mask = GL_DEPTH_BUFFER_BIT; if (rb->_BaseFormat == GL_DEPTH_STENCIL && texImage->_BaseFormat == GL_DEPTH_STENCIL) { - _mesa_meta_bind_fbo_image(GL_STENCIL_ATTACHMENT, texImage, zoffset); + _mesa_meta_bind_fbo_image(GL_FRAMEBUFFER, GL_STENCIL_ATTACHMENT, + texImage, zoffset); mask |= GL_STENCIL_BUFFER_BIT; } _mesa_DrawBuffer(GL_NONE); } else { - _mesa_meta_bind_fbo_image(GL_COLOR_ATTACHMENT0, texImage, zoffset); + _mesa_meta_bind_fbo_image(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, + texImage, zoffset); mask = GL_COLOR_BUFFER_BIT; _mesa_DrawBuffer(GL_COLOR_ATTACHMENT0); } @@ -3362,7 +3359,8 @@ cleartexsubimage_color(struct gl_context *ctx, GLenum datatype; GLenum status; - _mesa_meta_bind_fbo_image(GL_COLOR_ATTACHMENT0, texImage, zoffset); + _mesa_meta_bind_fbo_image(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, + texImage, zoffset); status = _mesa_CheckFramebufferStatus(GL_DRAW_FRAMEBUFFER); if (status != GL_FRAMEBUFFER_COMPLETE) @@ -3408,10 +3406,12 @@ cleartexsubimage_depth_stencil(struct gl_context *ctx, GLfloat depthValue; GLenum status; - _mesa_meta_bind_fbo_image(GL_DEPTH_ATTACHMENT, texImage, zoffset); + _mesa_meta_bind_fbo_image(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, + texImage, zoffset); if (texImage->_BaseFormat == GL_DEPTH_STENCIL) - _mesa_meta_bind_fbo_image(GL_STENCIL_ATTACHMENT, texImage, zoffset); + _mesa_meta_bind_fbo_image(GL_FRAMEBUFFER, GL_STENCIL_ATTACHMENT, + texImage, zoffset); status = _mesa_CheckFramebufferStatus(GL_DRAW_FRAMEBUFFER); if (status != GL_FRAMEBUFFER_COMPLETE) diff --git a/mesalib/src/mesa/drivers/common/meta.h b/mesalib/src/mesa/drivers/common/meta.h index b269dceed..e2da2f427 100644 --- a/mesalib/src/mesa/drivers/common/meta.h +++ b/mesalib/src/mesa/drivers/common/meta.h @@ -440,6 +440,14 @@ _mesa_meta_and_swrast_BlitFramebuffer(struct gl_context *ctx, GLint dstX1, GLint dstY1, GLbitfield mask, GLenum filter); +bool +_mesa_meta_CopyImageSubData_uncompressed(struct gl_context *ctx, + struct gl_texture_image *src_tex_image, + int src_x, int src_y, int src_z, + struct gl_texture_image *dst_tex_image, + int dst_x, int dst_y, int dst_z, + int src_width, int src_height); + extern void _mesa_meta_Clear(struct gl_context *ctx, GLbitfield buffers); @@ -570,7 +578,7 @@ void _mesa_meta_glsl_generate_mipmap_cleanup(struct gen_mipmap_state *mipmap); void -_mesa_meta_bind_fbo_image(GLenum attachment, +_mesa_meta_bind_fbo_image(GLenum target, GLenum attachment, struct gl_texture_image *texImage, GLuint layer); #endif /* META_H */ diff --git a/mesalib/src/mesa/drivers/common/meta_blit.c b/mesalib/src/mesa/drivers/common/meta_blit.c index bbf0c3c45..955e73f57 100644 --- a/mesalib/src/mesa/drivers/common/meta_blit.c +++ b/mesalib/src/mesa/drivers/common/meta_blit.c @@ -49,7 +49,7 @@ #include "main/viewport.h" #include "swrast/swrast.h" #include "drivers/common/meta.h" -#include "../glsl/ralloc.h" +#include "util/ralloc.h" /** Return offset in bytes of the field within a vertex struct */ #define OFFSET(FIELD) ((void *) offsetof(struct vertex, FIELD)) @@ -709,6 +709,9 @@ _mesa_meta_BlitFramebuffer(struct gl_context *ctx, */ _mesa_meta_begin(ctx, MESA_META_ALL & ~MESA_META_DRAW_BUFFERS); + /* Dithering shouldn't be performed for glBlitFramebuffer */ + _mesa_set_enable(ctx, GL_DITHER, GL_FALSE); + /* If the clipping earlier changed the destination rect at all, then * enable the scissor to clip to it. */ diff --git a/mesalib/src/mesa/drivers/common/meta_copy_image.c b/mesalib/src/mesa/drivers/common/meta_copy_image.c new file mode 100644 index 000000000..c40c2f011 --- /dev/null +++ b/mesalib/src/mesa/drivers/common/meta_copy_image.c @@ -0,0 +1,199 @@ +/* + * Mesa 3-D graphics library + * + * Copyright (C) 2014 Intel Corporation. All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included + * in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + */ + +#include "glheader.h" +#include "context.h" +#include "enums.h" +#include "imports.h" +#include "macros.h" +#include "teximage.h" +#include "texobj.h" +#include "fbobject.h" +#include "buffers.h" +#include "state.h" +#include "mtypes.h" +#include "meta.h" + +/* This function makes a texture view without bothering with all of the API + * checks. Most of them are the same for CopyTexSubImage so checking would + * be redundant. The one major difference is that we don't check for + * whether the texture is immutable or not. However, since the view will + * be created and then immediately destroyed, this should not be a problem. + */ +static bool +make_view(struct gl_context *ctx, struct gl_texture_image *tex_image, + struct gl_texture_image **view_tex_image, GLuint *view_tex_name, + GLenum internal_format) +{ + struct gl_texture_object *tex_obj = tex_image->TexObject; + struct gl_texture_object *view_tex_obj; + mesa_format tex_format; + + /* Set up the new texture object */ + _mesa_GenTextures(1, view_tex_name); + view_tex_obj = _mesa_lookup_texture(ctx, *view_tex_name); + if (!view_tex_obj) + return false; + + tex_format = _mesa_choose_texture_format(ctx, view_tex_obj, tex_obj->Target, + 0, internal_format, + GL_NONE, GL_NONE); + + if (!ctx->Driver.TestProxyTexImage(ctx, tex_obj->Target, 0, tex_format, + tex_image->Width, tex_image->Height, + tex_image->Depth, 0)) { + return false; + } + + view_tex_obj->Target = tex_obj->Target; + + *view_tex_image = _mesa_get_tex_image(ctx, view_tex_obj, tex_obj->Target, 0); + _mesa_init_teximage_fields(ctx, *view_tex_image, + tex_image->Width, tex_image->Height, + tex_image->Depth, + 0, internal_format, tex_format); + + view_tex_obj->MinLevel = 0; + view_tex_obj->NumLevels = 1; + view_tex_obj->MinLayer = tex_obj->MinLayer; + view_tex_obj->NumLayers = tex_obj->NumLayers; + view_tex_obj->Immutable = tex_obj->Immutable; + view_tex_obj->ImmutableLevels = tex_obj->ImmutableLevels; + view_tex_obj->Target = tex_obj->Target; + + if (ctx->Driver.TextureView != NULL && + !ctx->Driver.TextureView(ctx, view_tex_obj, tex_obj)) { + _mesa_DeleteTextures(1, view_tex_name); + *view_tex_name = 0; + return false; /* driver recorded error */ + } + + return true; +} + +/** A partial implementation of glCopyImageSubData + * + * This is a partial implementation of glCopyImageSubData that works only + * if both textures are uncompressed and the destination texture is + * renderable. It uses a slight abuse of a texture view (see make_view) to + * turn the source texture into the destination texture type and then uses + * _mesa_meta_BlitFramebuffers to do the copy. + */ +bool +_mesa_meta_CopyImageSubData_uncompressed(struct gl_context *ctx, + struct gl_texture_image *src_tex_image, + int src_x, int src_y, int src_z, + struct gl_texture_image *dst_tex_image, + int dst_x, int dst_y, int dst_z, + int src_width, int src_height) +{ + GLuint src_view_texture = 0; + struct gl_texture_image *src_view_tex_image; + GLuint fbos[2]; + bool success = false; + GLbitfield mask; + GLenum status, attachment; + + if (_mesa_is_format_compressed(dst_tex_image->TexFormat)) + return false; + + if (_mesa_is_format_compressed(src_tex_image->TexFormat)) + return false; + + if (src_tex_image->InternalFormat == dst_tex_image->InternalFormat) { + src_view_tex_image = src_tex_image; + } else { + if (!make_view(ctx, src_tex_image, &src_view_tex_image, &src_view_texture, + dst_tex_image->InternalFormat)) + goto cleanup; + } + + /* We really only need to stash the bound framebuffers. */ + _mesa_meta_begin(ctx, 0); + + _mesa_GenFramebuffers(2, fbos); + _mesa_BindFramebuffer(GL_READ_FRAMEBUFFER, fbos[0]); + _mesa_BindFramebuffer(GL_DRAW_FRAMEBUFFER, fbos[1]); + + switch (_mesa_get_format_base_format(src_tex_image->TexFormat)) { + case GL_DEPTH_COMPONENT: + attachment = GL_DEPTH_ATTACHMENT; + mask = GL_DEPTH_BUFFER_BIT; + break; + case GL_DEPTH_STENCIL: + attachment = GL_DEPTH_STENCIL_ATTACHMENT; + mask = GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT; + break; + case GL_STENCIL_INDEX: + attachment = GL_STENCIL_ATTACHMENT; + mask = GL_STENCIL_BUFFER_BIT; + break; + default: + attachment = GL_COLOR_ATTACHMENT0; + mask = GL_COLOR_BUFFER_BIT; + _mesa_DrawBuffer(GL_COLOR_ATTACHMENT0); + _mesa_ReadBuffer(GL_COLOR_ATTACHMENT0); + } + + _mesa_meta_bind_fbo_image(GL_READ_FRAMEBUFFER, attachment, + src_view_tex_image, src_z); + + status = _mesa_CheckFramebufferStatus(GL_READ_FRAMEBUFFER); + if (status != GL_FRAMEBUFFER_COMPLETE) + goto meta_end; + + _mesa_meta_bind_fbo_image(GL_DRAW_FRAMEBUFFER, attachment, + dst_tex_image, dst_z); + + status = _mesa_CheckFramebufferStatus(GL_DRAW_FRAMEBUFFER); + if (status != GL_FRAMEBUFFER_COMPLETE) + goto meta_end; + + /* Since we've bound a new draw framebuffer, we need to update its + * derived state -- _Xmin, etc -- for BlitFramebuffer's clipping to + * be correct. + */ + _mesa_update_state(ctx); + + /* We skip the core BlitFramebuffer checks for format consistency. + * We have already created views to ensure that the texture formats + * match. + */ + ctx->Driver.BlitFramebuffer(ctx, src_x, src_y, + src_x + src_width, src_y + src_height, + dst_x, dst_y, + dst_x + src_width, dst_y + src_height, + mask, GL_NEAREST); + + success = true; + +meta_end: + _mesa_DeleteFramebuffers(2, fbos); + _mesa_meta_end(ctx); + +cleanup: + _mesa_DeleteTextures(1, &src_view_texture); + + return success; +} diff --git a/mesalib/src/mesa/drivers/common/meta_generate_mipmap.c b/mesalib/src/mesa/drivers/common/meta_generate_mipmap.c index 4b1718df9..8ffd8da3b 100644 --- a/mesalib/src/mesa/drivers/common/meta_generate_mipmap.c +++ b/mesalib/src/mesa/drivers/common/meta_generate_mipmap.c @@ -104,7 +104,7 @@ fallback_required(struct gl_context *ctx, GLenum target, _mesa_GenFramebuffers(1, &mipmap->FBO); _mesa_BindFramebuffer(GL_FRAMEBUFFER_EXT, mipmap->FBO); - _mesa_meta_bind_fbo_image(GL_COLOR_ATTACHMENT0, baseImage, 0); + _mesa_meta_bind_fbo_image(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, baseImage, 0); status = _mesa_CheckFramebufferStatus(GL_FRAMEBUFFER_EXT); @@ -327,7 +327,7 @@ _mesa_meta_GenerateMipmap(struct gl_context *ctx, GLenum target, _mesa_BufferData(GL_ARRAY_BUFFER_ARB, sizeof(verts), verts, GL_DYNAMIC_DRAW_ARB); - _mesa_meta_bind_fbo_image(GL_COLOR_ATTACHMENT0, dstImage, layer); + _mesa_meta_bind_fbo_image(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, dstImage, layer); /* sanity check */ if (_mesa_CheckFramebufferStatus(GL_FRAMEBUFFER) != diff --git a/mesalib/src/mesa/drivers/dri/common/SConscript b/mesalib/src/mesa/drivers/dri/common/SConscript index d003139bf..0bee1b41f 100644 --- a/mesalib/src/mesa/drivers/dri/common/SConscript +++ b/mesalib/src/mesa/drivers/dri/common/SConscript @@ -10,6 +10,7 @@ drienv.Replace(CPPPATH = [ xmlpool_options.dir.dir, # Dir to generated xmlpool/options.h '#include', '#include/GL/internal', + '#src', '#src/mapi', '#src/gallium/include', '#src/gallium/auxiliary', diff --git a/mesalib/src/mesa/drivers/dri/common/xmlconfig.c b/mesalib/src/mesa/drivers/dri/common/xmlconfig.c index 58d0e0656..ce376475c 100644 --- a/mesalib/src/mesa/drivers/dri/common/xmlconfig.c +++ b/mesalib/src/mesa/drivers/dri/common/xmlconfig.c @@ -45,6 +45,8 @@ extern char *program_invocation_name, *program_invocation_short_name; # endif # define GET_PROGRAM_NAME() program_invocation_short_name +#elif defined(__CYGWIN__) +# define GET_PROGRAM_NAME() program_invocation_short_name #elif defined(__FreeBSD__) && (__FreeBSD__ >= 2) # include <osreldate.h> # if (__FreeBSD_version >= 440000) diff --git a/mesalib/src/mesa/drivers/dri/common/xmlconfig.h b/mesalib/src/mesa/drivers/dri/common/xmlconfig.h index af0323485..8969843bd 100644 --- a/mesalib/src/mesa/drivers/dri/common/xmlconfig.h +++ b/mesalib/src/mesa/drivers/dri/common/xmlconfig.h @@ -58,7 +58,7 @@ typedef struct driOptionInfo { char *name; /**< \brief Name */ driOptionType type; /**< \brief Type */ driOptionRange *ranges; /**< \brief Array of ranges */ - uint nRanges; /**< \brief Number of ranges */ + unsigned int nRanges; /**< \brief Number of ranges */ } driOptionInfo; /** \brief Option cache @@ -76,7 +76,7 @@ typedef struct driOptionCache { * \li Default values in screen * \li Actual values in contexts */ - uint tableSize; + unsigned int tableSize; /**< \brief Size of the arrays * * In the current implementation it's not actually a size but log2(size). diff --git a/mesalib/src/mesa/drivers/windows/gdi/SConscript b/mesalib/src/mesa/drivers/windows/gdi/SConscript index 10a7eeaa1..1f4d7e1fa 100644 --- a/mesalib/src/mesa/drivers/windows/gdi/SConscript +++ b/mesalib/src/mesa/drivers/windows/gdi/SConscript @@ -3,6 +3,7 @@ Import('*') env = env.Clone() env.Prepend(CPPPATH = [ + '#src', '#src/mapi', '#src/mesa', ]) @@ -16,6 +17,7 @@ if not env['gles']: env.Append(CPPDEFINES = ['_GLAPI_NO_EXPORTS']) env.Prepend(LIBS = [ + mesautil, glapi, mesa, glsl, diff --git a/mesalib/src/mesa/main/.gitignore b/mesalib/src/mesa/main/.gitignore index 837f49036..fec06291a 100644 --- a/mesalib/src/mesa/main/.gitignore +++ b/mesalib/src/mesa/main/.gitignore @@ -8,3 +8,4 @@ git_sha1.h.tmp remap_helper.h get_hash.h get_hash.h.tmp +format_info.c diff --git a/mesalib/src/mesa/main/bufferobj.c b/mesalib/src/mesa/main/bufferobj.c index 7b1bba097..b6879ceb5 100644 --- a/mesalib/src/mesa/main/bufferobj.c +++ b/mesalib/src/mesa/main/bufferobj.c @@ -31,6 +31,7 @@ */ #include <stdbool.h> +#include <inttypes.h> /* for PRId64 macro */ #include "glheader.h" #include "enums.h" #include "hash.h" @@ -832,6 +833,9 @@ _mesa_init_buffer_objects( struct gl_context *ctx ) _mesa_reference_buffer_object(ctx, &ctx->UniformBuffer, ctx->Shared->NullBufferObj); + _mesa_reference_buffer_object(ctx, &ctx->AtomicBuffer, + ctx->Shared->NullBufferObj); + _mesa_reference_buffer_object(ctx, &ctx->DrawIndirectBuffer, ctx->Shared->NullBufferObj); @@ -842,6 +846,14 @@ _mesa_init_buffer_objects( struct gl_context *ctx ) ctx->UniformBufferBindings[i].Offset = -1; ctx->UniformBufferBindings[i].Size = -1; } + + for (i = 0; i < MAX_COMBINED_ATOMIC_BUFFERS; i++) { + _mesa_reference_buffer_object(ctx, + &ctx->AtomicBufferBindings[i].BufferObject, + ctx->Shared->NullBufferObj); + ctx->AtomicBufferBindings[i].Offset = -1; + ctx->AtomicBufferBindings[i].Size = -1; + } } @@ -857,6 +869,8 @@ _mesa_free_buffer_objects( struct gl_context *ctx ) _mesa_reference_buffer_object(ctx, &ctx->UniformBuffer, NULL); + _mesa_reference_buffer_object(ctx, &ctx->AtomicBuffer, NULL); + _mesa_reference_buffer_object(ctx, &ctx->DrawIndirectBuffer, NULL); for (i = 0; i < MAX_COMBINED_UNIFORM_BUFFERS; i++) { @@ -864,6 +878,13 @@ _mesa_free_buffer_objects( struct gl_context *ctx ) &ctx->UniformBufferBindings[i].BufferObject, NULL); } + + for (i = 0; i < MAX_COMBINED_ATOMIC_BUFFERS; i++) { + _mesa_reference_buffer_object(ctx, + &ctx->AtomicBufferBindings[i].BufferObject, + NULL); + } + } bool @@ -1200,6 +1221,17 @@ _mesa_DeleteBuffers(GLsizei n, const GLuint *ids) _mesa_BindBuffer( GL_UNIFORM_BUFFER, 0 ); } + /* unbind Atomci Buffer binding points */ + for (j = 0; j < ctx->Const.MaxAtomicBufferBindings; j++) { + if (ctx->AtomicBufferBindings[j].BufferObject == bufObj) { + _mesa_BindBufferBase( GL_ATOMIC_COUNTER_BUFFER, j, 0 ); + } + } + + if (ctx->UniformBuffer == bufObj) { + _mesa_BindBuffer( GL_ATOMIC_COUNTER_BUFFER, 0 ); + } + /* unbind any pixel pack/unpack pointers bound to this buffer */ if (ctx->Pack.BufferObj == bufObj) { _mesa_BindBuffer( GL_PIXEL_PACK_BUFFER_EXT, 0 ); @@ -2793,8 +2825,8 @@ bind_buffers_check_offset_and_size(struct gl_context *ctx, * value in <offsets> is less than zero (per binding)." */ _mesa_error(ctx, GL_INVALID_VALUE, - "glBindBuffersRange(offsets[%u]=%lld < 0)", - index, (long long int) offsets[index]); + "glBindBuffersRange(offsets[%u]=%" PRId64 " < 0)", + index, (int64_t) offsets[index]); return false; } @@ -2805,8 +2837,8 @@ bind_buffers_check_offset_and_size(struct gl_context *ctx, * value in <sizes> is less than or equal to zero (per binding)." */ _mesa_error(ctx, GL_INVALID_VALUE, - "glBindBuffersRange(sizes[%u]=%lld <= 0)", - index, (long long int) sizes[index]); + "glBindBuffersRange(sizes[%u]=%" PRId64 " <= 0)", + index, (int64_t) sizes[index]); return false; } @@ -3001,11 +3033,11 @@ bind_uniform_buffers_range(struct gl_context *ctx, GLuint first, GLsizei count, */ if (offsets[i] & (ctx->Const.UniformBufferOffsetAlignment - 1)) { _mesa_error(ctx, GL_INVALID_VALUE, - "glBindBuffersRange(offsets[%u]=%lld is misaligned; " - "it must be a multiple of the value of " + "glBindBuffersRange(offsets[%u]=%" PRId64 + " is misaligned; it must be a multiple of the value of " "GL_UNIFORM_BUFFER_OFFSET_ALIGNMENT=%u when " "target=GL_UNIFORM_BUFFER)", - i, (long long int) offsets[i], + i, (int64_t) offsets[i], ctx->Const.UniformBufferOffsetAlignment); continue; } @@ -3239,19 +3271,19 @@ bind_xfb_buffers_range(struct gl_context *ctx, */ if (offsets[i] & 0x3) { _mesa_error(ctx, GL_INVALID_VALUE, - "glBindBuffersRange(offsets[%u]=%lld is misaligned; " - "it must be a multiple of 4 when " + "glBindBuffersRange(offsets[%u]=%" PRId64 + " is misaligned; it must be a multiple of 4 when " "target=GL_TRANSFORM_FEEDBACK_BUFFER)", - i, (long long int) offsets[i]); + i, (int64_t) offsets[i]); continue; } if (sizes[i] & 0x3) { _mesa_error(ctx, GL_INVALID_VALUE, - "glBindBuffersRange(sizes[%u]=%lld is misaligned; " - "it must be a multiple of 4 when " + "glBindBuffersRange(sizes[%u]=%" PRId64 + " is misaligned; it must be a multiple of 4 when " "target=GL_TRANSFORM_FEEDBACK_BUFFER)", - i, (long long int) sizes[i]); + i, (int64_t) sizes[i]); continue; } @@ -3457,10 +3489,10 @@ bind_atomic_buffers_range(struct gl_context *ctx, */ if (offsets[i] & (ATOMIC_COUNTER_SIZE - 1)) { _mesa_error(ctx, GL_INVALID_VALUE, - "glBindBuffersRange(offsets[%u]=%lld is misaligned; " - "it must be a multiple of %d when " + "glBindBuffersRange(offsets[%u]=%" PRId64 + " is misaligned; it must be a multiple of %d when " "target=GL_ATOMIC_COUNTER_BUFFER)", - i, (long long int) offsets[i], ATOMIC_COUNTER_SIZE); + i, (int64_t) offsets[i], ATOMIC_COUNTER_SIZE); continue; } diff --git a/mesalib/src/mesa/main/buffers.c b/mesalib/src/mesa/main/buffers.c index b13a7af65..140cf6e82 100644 --- a/mesalib/src/mesa/main/buffers.c +++ b/mesalib/src/mesa/main/buffers.c @@ -494,10 +494,11 @@ _mesa_drawbuffers(struct gl_context *ctx, GLuint n, const GLenum *buffers, } /* - * If n==1, destMask[0] may have up to four bits set. + * destMask[0] may have up to four bits set + * (ex: glDrawBuffer(GL_FRONT_AND_BACK)). * Otherwise, destMask[x] can only have one bit set. */ - if (n == 1) { + if (_mesa_bitcount(destMask[0]) > 1) { GLuint count = 0, destMask0 = destMask[0]; while (destMask0) { GLint bufIndex = ffs(destMask0) - 1; @@ -566,16 +567,11 @@ _mesa_drawbuffers(struct gl_context *ctx, GLuint n, const GLenum *buffers, void _mesa_update_draw_buffers(struct gl_context *ctx) { - GLenum buffers[MAX_DRAW_BUFFERS]; - GLuint i; - /* should be a window system FBO */ assert(_mesa_is_winsys_fbo(ctx->DrawBuffer)); - for (i = 0; i < ctx->Const.MaxDrawBuffers; i++) - buffers[i] = ctx->Color.DrawBuffer[i]; - - _mesa_drawbuffers(ctx, ctx->Const.MaxDrawBuffers, buffers, NULL); + _mesa_drawbuffers(ctx, ctx->Const.MaxDrawBuffers, + ctx->Color.DrawBuffer, NULL); } diff --git a/mesalib/src/mesa/main/compiler.h b/mesalib/src/mesa/main/compiler.h index 79d8740e5..35160223e 100644 --- a/mesalib/src/mesa/main/compiler.h +++ b/mesalib/src/mesa/main/compiler.h @@ -44,6 +44,8 @@ #include <float.h> #include <stdarg.h> +#include "util/macros.h" + #include "c99_compat.h" /* inline, __func__, etc. */ @@ -130,23 +132,6 @@ extern "C" { #endif -/** - * __builtin_expect macros - */ -#if !defined(__GNUC__) -# define __builtin_expect(x, y) (x) -#endif - -#ifndef likely -# ifdef __GNUC__ -# define likely(x) __builtin_expect(!!(x), 1) -# define unlikely(x) __builtin_expect(!!(x), 0) -# else -# define likely(x) (x) -# define unlikely(x) (x) -# endif -#endif - /* XXX: Use standard `__func__` instead */ #ifndef __FUNCTION__ # define __FUNCTION__ __func__ @@ -238,65 +223,16 @@ static INLINE GLuint CPU_TO_LE32(GLuint x) #endif -/** - * Static (compile-time) assertion. - * Basically, use COND to dimension an array. If COND is false/zero the - * array size will be -1 and we'll get a compilation error. - */ -#define STATIC_ASSERT(COND) \ - do { \ - (void) sizeof(char [1 - 2*!(COND)]); \ - } while (0) - -/** - * Unreachable macro. Useful for suppressing "control reaches end of non-void - * function" warnings. - */ -#if __GNUC__ >= 4 && __GNUC_MINOR__ >= 5 -#define unreachable(str) \ -do { \ - assert(!str); \ - __builtin_unreachable(); \ -} while (0) -#elif (defined(__clang__) && defined(__has_builtin)) -# if __has_builtin(__builtin_unreachable) -# define unreachable(str) \ -do { \ - assert(!str); \ - __builtin_unreachable(); \ -} while (0) -# endif -#endif - -#ifndef unreachable -#define unreachable(str) -#endif - /* * A trick to suppress uninitialized variable warning without generating any * code */ #define uninitialized_var(x) x = x -#if (__GNUC__ >= 3) -#define PRINTFLIKE(f, a) __attribute__ ((format(__printf__, f, a))) -#else -#define PRINTFLIKE(f, a) -#endif - #ifndef NULL #define NULL 0 #endif -/* Used to optionally mark structures with misaligned elements or size as - * packed, to trade off performance for space. - */ -#if (__GNUC__ >= 3) -#define PACKED __attribute__((__packed__)) -#else -#define PACKED -#endif - /** * LONGSTRING macro @@ -329,25 +265,7 @@ do { \ #define FLT_MAX_EXP 128 #endif - -/** - * USE_IEEE: Determine if we're using IEEE floating point - */ -#if defined(__i386__) || defined(__386__) || defined(__sparc__) || \ - defined(__s390__) || defined(__s390x__) || defined(__powerpc__) || \ - defined(__x86_64__) || \ - defined(__m68k__) || \ - defined(ia64) || defined(__ia64__) || \ - defined(__hppa__) || defined(hpux) || \ - defined(__mips) || defined(_MIPS_ARCH) || \ - defined(__arm__) || defined(__aarch64__) || \ - defined(__sh__) || defined(__m32r__) || \ - (defined(__sun) && defined(_IEEE_754)) || \ - defined(__alpha__) -#define USE_IEEE #define IEEE_ONE 0x3f800000 -#endif - /** * START/END_FAST_MATH macros: @@ -433,30 +351,6 @@ do { \ #endif #ifdef __cplusplus -/** - * Macro function that evaluates to true if T is a trivially - * destructible type -- that is, if its (non-virtual) destructor - * performs no action and all member variables and base classes are - * trivially destructible themselves. - */ -# if defined(__GNUC__) -# if ((__GNUC__ > 4) || ((__GNUC__ == 4) && (__GNUC_MINOR__ >= 3))) -# define HAS_TRIVIAL_DESTRUCTOR(T) __has_trivial_destructor(T) -# endif -# elif (defined(__clang__) && defined(__has_feature)) -# if __has_feature(has_trivial_destructor) -# define HAS_TRIVIAL_DESTRUCTOR(T) __has_trivial_destructor(T) -# endif -# endif -# ifndef HAS_TRIVIAL_DESTRUCTOR - /* It's always safe (if inefficient) to assume that a - * destructor is non-trivial. - */ -# define HAS_TRIVIAL_DESTRUCTOR(T) (false) -# endif -#endif - -#ifdef __cplusplus } #endif diff --git a/mesalib/src/mesa/main/copyimage.c b/mesalib/src/mesa/main/copyimage.c new file mode 100644 index 000000000..dcbc83de6 --- /dev/null +++ b/mesalib/src/mesa/main/copyimage.c @@ -0,0 +1,356 @@ +/* + * Mesa 3-D graphics library + * + * Copyright (C) 2014 Intel Corporation. All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included + * in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: + * Jason Ekstrand <jason.ekstrand@intel.com> + */ + +#include "glheader.h" +#include "errors.h" +#include "enums.h" +#include "copyimage.h" +#include "teximage.h" +#include "texobj.h" +#include "fbobject.h" +#include "textureview.h" + +static bool +prepare_target(struct gl_context *ctx, GLuint name, GLenum *target, int level, + struct gl_texture_object **tex_obj, + struct gl_texture_image **tex_image, GLuint *tmp_tex, + const char *dbg_prefix) +{ + struct gl_renderbuffer *rb; + + if (name == 0) { + _mesa_error(ctx, GL_INVALID_VALUE, + "glCopyImageSubData(%sName = %d)", dbg_prefix, name); + return false; + } + + /* + * INVALID_ENUM is generated + * * if either <srcTarget> or <dstTarget> + * - is not RENDERBUFFER or a valid non-proxy texture target + * - is TEXTURE_BUFFER, or + * - is one of the cubemap face selectors described in table 3.17, + */ + switch (*target) { + case GL_RENDERBUFFER: + /* Not a texture target, but valid */ + case GL_TEXTURE_1D: + case GL_TEXTURE_1D_ARRAY: + case GL_TEXTURE_2D: + case GL_TEXTURE_3D: + case GL_TEXTURE_CUBE_MAP: + case GL_TEXTURE_RECTANGLE: + case GL_TEXTURE_2D_ARRAY: + case GL_TEXTURE_CUBE_MAP_ARRAY: + case GL_TEXTURE_2D_MULTISAMPLE: + case GL_TEXTURE_2D_MULTISAMPLE_ARRAY: + /* These are all valid */ + break; + case GL_TEXTURE_EXTERNAL_OES: + /* Only exists in ES */ + case GL_TEXTURE_BUFFER: + default: + _mesa_error(ctx, GL_INVALID_ENUM, + "glCopyImageSubData(%sTarget = %s)", dbg_prefix, + _mesa_lookup_enum_by_nr(*target)); + return false; + } + + if (*target == GL_RENDERBUFFER) { + rb = _mesa_lookup_renderbuffer(ctx, name); + if (!rb) { + _mesa_error(ctx, GL_INVALID_VALUE, + "glCopyImageSubData(%sName = %u)", dbg_prefix, name); + return false; + } + + if (!rb->Name) { + _mesa_error(ctx, GL_INVALID_OPERATION, + "glCopyImageSubData(%sName incomplete)", dbg_prefix); + return false; + } + + if (level != 0) { + _mesa_error(ctx, GL_INVALID_VALUE, + "glCopyImageSubData(%sLevel = %u)", dbg_prefix, level); + return false; + } + + if (rb->NumSamples > 1) + *target = GL_TEXTURE_2D_MULTISAMPLE; + else + *target = GL_TEXTURE_2D; + + *tmp_tex = 0; + _mesa_GenTextures(1, tmp_tex); + if (*tmp_tex == 0) + return false; /* Error already set by GenTextures */ + + _mesa_BindTexture(*target, *tmp_tex); + *tex_obj = _mesa_lookup_texture(ctx, *tmp_tex); + *tex_image = _mesa_get_tex_image(ctx, *tex_obj, *target, 0); + + if (!ctx->Driver.BindRenderbufferTexImage(ctx, rb, *tex_image)) { + _mesa_problem(ctx, "Failed to create texture from renderbuffer"); + return false; + } + + if (ctx->Driver.FinishRenderTexture && !rb->NeedsFinishRenderTexture) { + rb->NeedsFinishRenderTexture = true; + ctx->Driver.FinishRenderTexture(ctx, rb); + } + } else { + *tex_obj = _mesa_lookup_texture(ctx, name); + if (!*tex_obj) { + _mesa_error(ctx, GL_INVALID_VALUE, + "glCopyImageSubData(%sName = %u)", dbg_prefix, name); + return false; + } + + _mesa_test_texobj_completeness(ctx, *tex_obj); + if (!(*tex_obj)->_BaseComplete || + (level != 0 && !(*tex_obj)->_MipmapComplete)) { + _mesa_error(ctx, GL_INVALID_OPERATION, + "glCopyImageSubData(%sName incomplete)", dbg_prefix); + return false; + } + + if ((*tex_obj)->Target != *target) { + _mesa_error(ctx, GL_INVALID_ENUM, + "glCopyImageSubData(%sTarget = %s)", dbg_prefix, + _mesa_lookup_enum_by_nr(*target)); + return false; + } + + if (level < 0 || level >= MAX_TEXTURE_LEVELS) { + _mesa_error(ctx, GL_INVALID_VALUE, + "glCopyImageSubData(%sLevel = %d)", dbg_prefix, level); + return false; + } + + *tex_image = _mesa_select_tex_image(ctx, *tex_obj, *target, level); + if (!*tex_image) { + _mesa_error(ctx, GL_INVALID_VALUE, + "glCopyImageSubData(%sLevel = %u)", dbg_prefix, level); + return false; + } + } + + return true; +} + +static bool +check_region_bounds(struct gl_context *ctx, struct gl_texture_image *tex_image, + int x, int y, int z, int width, int height, int depth, + const char *dbg_prefix) +{ + if (width < 0 || height < 0 || depth < 0) { + _mesa_error(ctx, GL_INVALID_VALUE, + "glCopyImageSubData(%sWidth, %sHeight, or %sDepth is negative)", + dbg_prefix, dbg_prefix, dbg_prefix); + return false; + } + + if (x < 0 || y < 0 || z < 0) { + _mesa_error(ctx, GL_INVALID_VALUE, + "glCopyImageSubData(%sX, %sY, or %sZ is negative)", + dbg_prefix, dbg_prefix, dbg_prefix); + return false; + } + + if (x + width > tex_image->Width) { + _mesa_error(ctx, GL_INVALID_VALUE, + "glCopyImageSubData(%sX or %sWidth exceeds image bounds)", + dbg_prefix, dbg_prefix); + return false; + } + + switch (tex_image->TexObject->Target) { + case GL_TEXTURE_1D: + case GL_TEXTURE_1D_ARRAY: + if (y != 0 || height != 1) { + _mesa_error(ctx, GL_INVALID_VALUE, + "glCopyImageSubData(%sY or %sHeight exceeds image bounds)", + dbg_prefix, dbg_prefix); + return false; + } + break; + default: + if (y + height > tex_image->Height) { + _mesa_error(ctx, GL_INVALID_VALUE, + "glCopyImageSubData(%sY or %sHeight exceeds image bounds)", + dbg_prefix, dbg_prefix); + return false; + } + break; + } + + switch (tex_image->TexObject->Target) { + case GL_TEXTURE_1D: + case GL_TEXTURE_2D: + case GL_TEXTURE_2D_MULTISAMPLE: + case GL_TEXTURE_RECTANGLE: + if (z != 0 || depth != 1) { + _mesa_error(ctx, GL_INVALID_VALUE, + "glCopyImageSubData(%sZ or %sDepth exceeds image bounds)", + dbg_prefix, dbg_prefix); + return false; + } + break; + case GL_TEXTURE_CUBE_MAP: + if (z < 0 || z + depth > 6) { + _mesa_error(ctx, GL_INVALID_VALUE, + "glCopyImageSubData(%sZ or %sDepth exceeds image bounds)", + dbg_prefix, dbg_prefix); + return false; + } + break; + case GL_TEXTURE_1D_ARRAY: + if (z < 0 || z + depth > tex_image->Height) { + _mesa_error(ctx, GL_INVALID_VALUE, + "glCopyImageSubData(%sZ or %sDepth exceeds image bounds)", + dbg_prefix, dbg_prefix); + return false; + } + break; + case GL_TEXTURE_CUBE_MAP_ARRAY: + case GL_TEXTURE_2D_ARRAY: + case GL_TEXTURE_2D_MULTISAMPLE_ARRAY: + case GL_TEXTURE_3D: + if (z < 0 || z + depth > tex_image->Depth) { + _mesa_error(ctx, GL_INVALID_VALUE, + "glCopyImageSubData(%sZ or %sDepth exceeds image bounds)", + dbg_prefix, dbg_prefix); + return false; + } + break; + } + + return true; +} + +void GLAPIENTRY +_mesa_CopyImageSubData(GLuint srcName, GLenum srcTarget, GLint srcLevel, + GLint srcX, GLint srcY, GLint srcZ, + GLuint dstName, GLenum dstTarget, GLint dstLevel, + GLint dstX, GLint dstY, GLint dstZ, + GLsizei srcWidth, GLsizei srcHeight, GLsizei srcDepth) +{ + GET_CURRENT_CONTEXT(ctx); + GLuint tmpTexNames[2] = { 0, 0 }; + 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; + + if (MESA_VERBOSE & VERBOSE_API) + _mesa_debug(ctx, "glCopyImageSubData(%u, %s, %d, %d, %d, %d, " + "%u, %s, %d, %d, %d, %d, " + "%d, %d, %d)\n", + srcName, _mesa_lookup_enum_by_nr(srcTarget), srcLevel, + srcX, srcY, srcZ, + dstName, _mesa_lookup_enum_by_nr(dstTarget), dstLevel, + dstX, dstY, dstZ, + srcWidth, srcHeight, srcWidth); + + if (!prepare_target(ctx, srcName, &srcTarget, srcLevel, + &srcTexObj, &srcTexImage, &tmpTexNames[0], "src")) + goto cleanup; + + if (!prepare_target(ctx, dstName, &dstTarget, dstLevel, + &dstTexObj, &dstTexImage, &tmpTexNames[1], "dst")) + goto cleanup; + + _mesa_get_format_block_size(srcTexImage->TexFormat, &src_bw, &src_bh); + if ((srcX % src_bw != 0) || (srcY % src_bh != 0) || + (srcWidth % src_bw != 0) || (srcHeight % src_bh != 0)) { + _mesa_error(ctx, GL_INVALID_VALUE, + "glCopyImageSubData(unaligned src rectangle)"); + goto cleanup; + } + + _mesa_get_format_block_size(dstTexImage->TexFormat, &dst_bw, &dst_bh); + if ((dstX % dst_bw != 0) || (dstY % dst_bh != 0)) { + _mesa_error(ctx, GL_INVALID_VALUE, + "glCopyImageSubData(unaligned dst rectangle)"); + 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; + + if (!check_region_bounds(ctx, dstTexImage, dstX, dstY, dstZ, + (srcWidth / src_bw) * dst_bw, + (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 loged by _mesa_texture_view_compatible_format */ + } + + for (i = 0; i < srcDepth; ++i) { + if (srcTexObj->Target == GL_TEXTURE_CUBE_MAP) { + srcTexImage = srcTexObj->Image[i + srcZ][srcLevel]; + srcNewZ = 0; + } else { + srcNewZ = srcZ + i; + } + + if (dstTexObj->Target == GL_TEXTURE_CUBE_MAP) { + dstTexImage = dstTexObj->Image[i + dstZ][dstLevel]; + dstNewZ = 0; + } else { + dstNewZ = dstZ + i; + } + + ctx->Driver.CopyImageSubData(ctx, srcTexImage, srcX, srcY, srcNewZ, + dstTexImage, dstX, dstY, dstNewZ, + srcWidth, srcHeight); + } + +cleanup: + _mesa_DeleteTextures(2, tmpTexNames); +} diff --git a/mesalib/src/mesa/main/copyimage.h b/mesalib/src/mesa/main/copyimage.h new file mode 100644 index 000000000..40e95b663 --- /dev/null +++ b/mesalib/src/mesa/main/copyimage.h @@ -0,0 +1,49 @@ +/* + * Mesa 3-D graphics library + * + * Copyright (C) 2014 Intel Corporation. All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included + * in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: + * Jason Ekstrand <jason.ekstrand@intel.com> + */ + + +#ifndef COPYIMAGE_H +#define COPYIMAGE_H + +#include "mtypes.h" + +#ifdef __cplusplus +extern "C" { +#endif + +extern void GLAPIENTRY +_mesa_CopyImageSubData(GLuint srcName, GLenum srcTarget, GLint srcLevel, + GLint srcX, GLint srcY, GLint srcZ, + GLuint destName, GLenum destTarget, GLint destLevel, + GLint destX, GLint destY, GLint destZ, + GLsizei srcWidth, GLsizei srcHeight, GLsizei srcDepth); + +#ifdef __cplusplus +} +#endif + +#endif /* COPYIMAGE_H */ diff --git a/mesalib/src/mesa/main/dd.h b/mesalib/src/mesa/main/dd.h index 89765351e..c130b14a5 100644 --- a/mesalib/src/mesa/main/dd.h +++ b/mesalib/src/mesa/main/dd.h @@ -269,6 +269,22 @@ struct dd_function_table { GLsizei width, GLsizei height); /** + * Called by glCopyImageSubData(). + * + * This function should copy one 2-D slice from srcTexImage to + * dstTexImage. If one of the textures is 3-D or is a 1-D or 2-D array + * texture, this function will be called multiple times: once for each + * slice. If one of the textures is a cube map, this function will be + * called once for each face to be copied. + */ + void (*CopyImageSubData)(struct gl_context *ctx, + struct gl_texture_image *src_image, + int src_x, int src_y, int src_z, + struct gl_texture_image *dstTexImage, + int dst_x, int dst_y, int dst_z, + int src_width, int src_height); + + /** * Called by glGenerateMipmap() or when GL_GENERATE_MIPMAP_SGIS is enabled. * Note that if the texture is a cube map, the <target> parameter will * indicate which cube face to generate (GL_POSITIVE/NEGATIVE_X/Y/Z). diff --git a/mesalib/src/mesa/main/enable.c b/mesalib/src/mesa/main/enable.c index 0f3bcf0a9..417548a3c 100644 --- a/mesalib/src/mesa/main/enable.c +++ b/mesalib/src/mesa/main/enable.c @@ -313,7 +313,7 @@ _mesa_set_enable(struct gl_context *ctx, GLenum cap, GLboolean state) } } break; - case GL_CLIP_DISTANCE0: + case GL_CLIP_DISTANCE0: /* aka GL_CLIP_PLANE0 */ case GL_CLIP_DISTANCE1: case GL_CLIP_DISTANCE2: case GL_CLIP_DISTANCE3: @@ -1202,7 +1202,7 @@ _mesa_IsEnabled( GLenum cap ) return ctx->Eval.AutoNormal; case GL_BLEND: return ctx->Color.BlendEnabled & 1; /* return state for buffer[0] */ - case GL_CLIP_DISTANCE0: + case GL_CLIP_DISTANCE0: /* aka GL_CLIP_PLANE0 */ case GL_CLIP_DISTANCE1: case GL_CLIP_DISTANCE2: case GL_CLIP_DISTANCE3: diff --git a/mesalib/src/mesa/main/errors.c b/mesalib/src/mesa/main/errors.c index aa0ff50ac..9cde1e020 100644 --- a/mesalib/src/mesa/main/errors.c +++ b/mesalib/src/mesa/main/errors.c @@ -36,7 +36,7 @@ #include "hash.h" #include "mtypes.h" #include "version.h" -#include "hash_table.h" +#include "util/hash_table.h" static mtx_t DynamicIDMutex = _MTX_INITIALIZER_NP; static GLuint NextDynamicID = 1; diff --git a/mesalib/src/mesa/main/extensions.c b/mesalib/src/mesa/main/extensions.c index 9ac8377a4..d60838a1c 100644 --- a/mesalib/src/mesa/main/extensions.c +++ b/mesalib/src/mesa/main/extensions.c @@ -95,6 +95,7 @@ static const struct extension extension_table[] = { { "GL_ARB_compressed_texture_pixel_storage", o(dummy_true), GL, 2011 }, { "GL_ARB_compute_shader", o(ARB_compute_shader), GL, 2012 }, { "GL_ARB_copy_buffer", o(dummy_true), GL, 2008 }, + { "GL_ARB_copy_image", o(ARB_copy_image), GL, 2012 }, { "GL_ARB_conservative_depth", o(ARB_conservative_depth), GL, 2011 }, { "GL_ARB_debug_output", o(dummy_true), GL, 2009 }, { "GL_ARB_depth_buffer_float", o(ARB_depth_buffer_float), GL, 2008 }, diff --git a/mesalib/src/mesa/main/format_info.py b/mesalib/src/mesa/main/format_info.py new file mode 100644 index 000000000..448bd0055 --- /dev/null +++ b/mesalib/src/mesa/main/format_info.py @@ -0,0 +1,192 @@ +#!/usr/bin/env python +# +# Copyright 2014 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, sub license, and/or sell copies of the Software, and to +# permit persons to whom the Software is furnished to do so, subject to +# the following conditions: +# +# The 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 NON-INFRINGEMENT. +# IN NO EVENT SHALL VMWARE AND/OR ITS SUPPLIERS BE LIABLE FOR +# ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, +# TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE +# SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +import format_parser as parser +import sys + +def get_gl_base_format(fmat): + if fmat.name == 'MESA_FORMAT_NONE': + return 'GL_NONE' + elif fmat.name in ['MESA_FORMAT_YCBCR', 'MESA_FORMAT_YCBCR_REV']: + return 'GL_YCBCR_MESA' + elif fmat.has_channel('r'): + if fmat.has_channel('g'): + if fmat.has_channel('b'): + if fmat.has_channel('a'): + return 'GL_RGBA' + else: + return 'GL_RGB' + else: + return 'GL_RG' + else: + return 'GL_RED' + elif fmat.has_channel('l'): + if fmat.has_channel('a'): + return 'GL_LUMINANCE_ALPHA' + else: + return 'GL_LUMINANCE' + elif fmat.has_channel('a') and fmat.num_channels() == 1: + return 'GL_ALPHA' + elif fmat.has_channel('z'): + if fmat.has_channel('s'): + return 'GL_DEPTH_STENCIL' + else: + return 'GL_DEPTH_COMPONENT' + elif fmat.has_channel('s'): + return 'GL_STENCIL_INDEX' + elif fmat.has_channel('i') and fmat.num_channels() == 1: + return 'GL_INTENSITY' + else: + assert False + +def get_gl_data_type(fmat): + if fmat.is_compressed(): + if 'SIGNED' in fmat.name or 'SNORM' in fmat.name: + return 'GL_SIGNED_NORMALIZED' + else: + return 'GL_UNSIGNED_NORMALIZED' + elif fmat.name in ['MESA_FORMAT_YCBCR', 'MESA_FORMAT_YCBCR_REV']: + return 'GL_UNSIGNED_NORMALIZED' + + channel = None + for chan in fmat.channels: + if chan.type == 'x' and len(fmat.channels) > 1: + continue # We can do better + elif chan.name == 's' and fmat.has_channel('z'): + continue # We'll use the type from the depth instead + + channel = chan + break; + + if channel.type == parser.UNSIGNED: + if channel.norm: + return 'GL_UNSIGNED_NORMALIZED' + else: + return 'GL_UNSIGNED_INT' + elif channel.type == parser.SIGNED: + if channel.norm: + return 'GL_SIGNED_NORMALIZED' + else: + return 'GL_INT' + elif channel.type == parser.FLOAT: + return 'GL_FLOAT' + elif channel.type == parser.VOID: + return 'GL_NONE' + else: + assert False + +def get_mesa_layout(fmat): + if fmat.layout == 'array': + return 'MESA_FORMAT_LAYOUT_ARRAY' + elif fmat.layout == 'packed': + return 'MESA_FORMAT_LAYOUT_PACKED' + else: + return 'MESA_FORMAT_LAYOUT_OTHER' + +def get_channel_bits(fmat, chan_name): + if fmat.is_compressed(): + # These values are pretty-much bogus, but OpenGL requires that we + # return an "approximate" number of bits. + if fmat.layout == 's3tc': + return 4 if fmat.has_channel(chan_name) else 0 + elif fmat.layout == 'fxt1': + if chan_name in 'rgb': + return 4 + elif chan_name == 'a': + return 1 if fmat.has_channel('a') else 0 + else: + return 0 + elif fmat.layout == 'rgtc': + return 8 if fmat.has_channel(chan_name) else 0 + elif fmat.layout in ('etc1', 'etc2'): + if fmat.name.endswith('_ALPHA1') and chan_name == 'a': + return 1 + + bits = 11 if fmat.name.endswith('11_EAC') else 8 + return bits if fmat.has_channel(chan_name) else 0 + else: + assert False + else: + # Uncompressed textures + for chan in fmat.channels: + if chan.name == chan_name: + return chan.size + return 0 + +formats = parser.parse(sys.argv[1]) + +print ''' +/* + * Mesa 3-D graphics library + * + * Copyright (c) 2014 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 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. + */ + + /* + * This file is AUTOGENERATED by format_info.py. Do not edit it + * manually or commit it into version control. + */ + +static struct gl_format_info format_info[MESA_FORMAT_COUNT] = +{ +''' + +for fmat in formats: + print ' {' + print ' {0},'.format(fmat.name) + print ' "{0}",'.format(fmat.name) + print ' {0},'.format(get_mesa_layout(fmat)) + print ' {0},'.format(get_gl_base_format(fmat)) + print ' {0},'.format(get_gl_data_type(fmat)) + + bits = [ get_channel_bits(fmat, name) for name in ['r', 'g', 'b', 'a']] + print ' {0},'.format(', '.join(map(str, bits))) + bits = [ get_channel_bits(fmat, name) for name in ['l', 'i', 'z', 's']] + print ' {0},'.format(', '.join(map(str, bits))) + + print ' {0}, {1}, {2},'.format(fmat.block_width, fmat.block_height, + int(fmat.block_size() / 8)) + + print ' {{ {0} }},'.format(', '.join(map(str, fmat.swizzle))) + print ' },' + +print '};' diff --git a/mesalib/src/mesa/main/format_pack.c b/mesalib/src/mesa/main/format_pack.c index c97c05297..6cbf8593b 100644 --- a/mesalib/src/mesa/main/format_pack.c +++ b/mesalib/src/mesa/main/format_pack.c @@ -41,6 +41,7 @@ #include "macros.h" #include "../../gallium/auxiliary/util/u_format_rgb9e5.h" #include "../../gallium/auxiliary/util/u_format_r11g11b10f.h" +#include "util/format_srgb.h" /** Helper struct for MESA_FORMAT_Z32_FLOAT_S8X24_UINT */ @@ -58,39 +59,6 @@ typedef void (*pack_float_rgba_row_func)(GLuint n, const GLfloat src[][4], void *dst); - -static inline GLfloat -linear_to_srgb(GLfloat cl) -{ - if (cl < 0.0f) - return 0.0f; - else if (cl < 0.0031308f) - return 12.92f * cl; - else if (cl < 1.0f) - return 1.055f * powf(cl, 0.41666f) - 0.055f; - else - return 1.0f; -} - - -static inline GLubyte -linear_float_to_srgb_ubyte(GLfloat cl) -{ - GLubyte res = FLOAT_TO_UBYTE(linear_to_srgb(cl)); - return res; -} - - -static inline GLubyte -linear_ubyte_to_srgb_ubyte(GLubyte cl) -{ - GLubyte res = FLOAT_TO_UBYTE(linear_to_srgb(cl / 255.0f)); - return res; -} - - - - /* * MESA_FORMAT_A8B8G8R8_UNORM */ @@ -1043,18 +1011,18 @@ static void pack_ubyte_BGR_SRGB8(const GLubyte src[4], void *dst) { GLubyte *d = ((GLubyte *) dst); - d[2] = linear_ubyte_to_srgb_ubyte(src[RCOMP]); - d[1] = linear_ubyte_to_srgb_ubyte(src[GCOMP]); - d[0] = linear_ubyte_to_srgb_ubyte(src[BCOMP]); + d[2] = util_format_linear_to_srgb_8unorm(src[RCOMP]); + d[1] = util_format_linear_to_srgb_8unorm(src[GCOMP]); + d[0] = util_format_linear_to_srgb_8unorm(src[BCOMP]); } static void pack_float_BGR_SRGB8(const GLfloat src[4], void *dst) { GLubyte *d = ((GLubyte *) dst); - d[2] = linear_float_to_srgb_ubyte(src[RCOMP]); - d[1] = linear_float_to_srgb_ubyte(src[GCOMP]); - d[0] = linear_float_to_srgb_ubyte(src[BCOMP]); + d[2] = util_format_linear_float_to_srgb_8unorm(src[RCOMP]); + d[1] = util_format_linear_float_to_srgb_8unorm(src[GCOMP]); + d[0] = util_format_linear_float_to_srgb_8unorm(src[BCOMP]); } @@ -1064,9 +1032,9 @@ static void pack_ubyte_A8B8G8R8_SRGB(const GLubyte src[4], void *dst) { GLuint *d = ((GLuint *) dst); - GLubyte r = linear_ubyte_to_srgb_ubyte(src[RCOMP]); - GLubyte g = linear_ubyte_to_srgb_ubyte(src[GCOMP]); - GLubyte b = linear_ubyte_to_srgb_ubyte(src[BCOMP]); + GLubyte r = util_format_linear_to_srgb_8unorm(src[RCOMP]); + GLubyte g = util_format_linear_to_srgb_8unorm(src[GCOMP]); + GLubyte b = util_format_linear_to_srgb_8unorm(src[BCOMP]); *d = PACK_COLOR_8888(r, g, b, src[ACOMP]); } @@ -1075,9 +1043,9 @@ pack_float_A8B8G8R8_SRGB(const GLfloat src[4], void *dst) { GLuint *d = ((GLuint *) dst); GLubyte r, g, b, a; - r = linear_float_to_srgb_ubyte(src[RCOMP]); - g = linear_float_to_srgb_ubyte(src[GCOMP]); - b = linear_float_to_srgb_ubyte(src[BCOMP]); + r = util_format_linear_float_to_srgb_8unorm(src[RCOMP]); + g = util_format_linear_float_to_srgb_8unorm(src[GCOMP]); + b = util_format_linear_float_to_srgb_8unorm(src[BCOMP]); UNCLAMPED_FLOAT_TO_UBYTE(a, src[ACOMP]); *d = PACK_COLOR_8888(r, g, b, a); } @@ -1089,9 +1057,9 @@ static void pack_ubyte_B8G8R8A8_SRGB(const GLubyte src[4], void *dst) { GLuint *d = ((GLuint *) dst); - GLubyte r = linear_ubyte_to_srgb_ubyte(src[RCOMP]); - GLubyte g = linear_ubyte_to_srgb_ubyte(src[GCOMP]); - GLubyte b = linear_ubyte_to_srgb_ubyte(src[BCOMP]); + GLubyte r = util_format_linear_to_srgb_8unorm(src[RCOMP]); + GLubyte g = util_format_linear_to_srgb_8unorm(src[GCOMP]); + GLubyte b = util_format_linear_to_srgb_8unorm(src[BCOMP]); *d = PACK_COLOR_8888(src[ACOMP], r, g, b); } @@ -1100,9 +1068,9 @@ pack_float_B8G8R8A8_SRGB(const GLfloat src[4], void *dst) { GLuint *d = ((GLuint *) dst); GLubyte r, g, b, a; - r = linear_float_to_srgb_ubyte(src[RCOMP]); - g = linear_float_to_srgb_ubyte(src[GCOMP]); - b = linear_float_to_srgb_ubyte(src[BCOMP]); + r = util_format_linear_float_to_srgb_8unorm(src[RCOMP]); + g = util_format_linear_float_to_srgb_8unorm(src[GCOMP]); + b = util_format_linear_float_to_srgb_8unorm(src[BCOMP]); UNCLAMPED_FLOAT_TO_UBYTE(a, src[ACOMP]); *d = PACK_COLOR_8888(a, r, g, b); } @@ -1114,9 +1082,9 @@ static void pack_ubyte_R8G8B8A8_SRGB(const GLubyte src[4], void *dst) { GLuint *d = ((GLuint *) dst); - GLubyte r = linear_ubyte_to_srgb_ubyte(src[RCOMP]); - GLubyte g = linear_ubyte_to_srgb_ubyte(src[GCOMP]); - GLubyte b = linear_ubyte_to_srgb_ubyte(src[BCOMP]); + GLubyte r = util_format_linear_to_srgb_8unorm(src[RCOMP]); + GLubyte g = util_format_linear_to_srgb_8unorm(src[GCOMP]); + GLubyte b = util_format_linear_to_srgb_8unorm(src[BCOMP]); *d = PACK_COLOR_8888(src[ACOMP], b, g, r); } @@ -1125,9 +1093,9 @@ pack_float_R8G8B8A8_SRGB(const GLfloat src[4], void *dst) { GLuint *d = ((GLuint *) dst); GLubyte r, g, b, a; - r = linear_float_to_srgb_ubyte(src[RCOMP]); - g = linear_float_to_srgb_ubyte(src[GCOMP]); - b = linear_float_to_srgb_ubyte(src[BCOMP]); + r = util_format_linear_float_to_srgb_8unorm(src[RCOMP]); + g = util_format_linear_float_to_srgb_8unorm(src[GCOMP]); + b = util_format_linear_float_to_srgb_8unorm(src[BCOMP]); UNCLAMPED_FLOAT_TO_UBYTE(a, src[ACOMP]); *d = PACK_COLOR_8888(a, b, g, r); } @@ -1139,14 +1107,14 @@ static void pack_ubyte_L_SRGB8(const GLubyte src[4], void *dst) { GLubyte *d = ((GLubyte *) dst); - *d = linear_ubyte_to_srgb_ubyte(src[RCOMP]); + *d = util_format_linear_to_srgb_8unorm(src[RCOMP]); } static void pack_float_L_SRGB8(const GLfloat src[4], void *dst) { GLubyte *d = ((GLubyte *) dst); - GLubyte l = linear_float_to_srgb_ubyte(src[RCOMP]); + GLubyte l = util_format_linear_float_to_srgb_8unorm(src[RCOMP]); *d = l; } @@ -1157,7 +1125,7 @@ static void pack_ubyte_L8A8_SRGB(const GLubyte src[4], void *dst) { GLushort *d = ((GLushort *) dst); - GLubyte l = linear_ubyte_to_srgb_ubyte(src[RCOMP]); + GLubyte l = util_format_linear_to_srgb_8unorm(src[RCOMP]); *d = PACK_COLOR_88(src[ACOMP], l); } @@ -1165,7 +1133,7 @@ static void pack_float_L8A8_SRGB(const GLfloat src[4], void *dst) { GLushort *d = ((GLushort *) dst); - GLubyte a, l = linear_float_to_srgb_ubyte(src[RCOMP]); + GLubyte a, l = util_format_linear_float_to_srgb_8unorm(src[RCOMP]); CLAMPED_FLOAT_TO_UBYTE(a, src[ACOMP]); *d = PACK_COLOR_88(a, l); } @@ -1742,9 +1710,9 @@ static void pack_float_R8G8B8X8_SRGB(const GLfloat src[4], void *dst) { GLuint *d = (GLuint *) dst; - GLubyte r = linear_float_to_srgb_ubyte(src[RCOMP]); - GLubyte g = linear_float_to_srgb_ubyte(src[GCOMP]); - GLubyte b = linear_float_to_srgb_ubyte(src[BCOMP]); + GLubyte r = util_format_linear_float_to_srgb_8unorm(src[RCOMP]); + GLubyte g = util_format_linear_float_to_srgb_8unorm(src[GCOMP]); + GLubyte b = util_format_linear_float_to_srgb_8unorm(src[BCOMP]); *d = PACK_COLOR_8888(127, b, g, r); } @@ -1892,9 +1860,9 @@ static void pack_float_B8G8R8X8_SRGB(const GLfloat src[4], void *dst) { GLuint *d = (GLuint *) dst; - GLubyte r = linear_float_to_srgb_ubyte(src[RCOMP]); - GLubyte g = linear_float_to_srgb_ubyte(src[GCOMP]); - GLubyte b = linear_float_to_srgb_ubyte(src[BCOMP]); + GLubyte r = util_format_linear_float_to_srgb_8unorm(src[RCOMP]); + GLubyte g = util_format_linear_float_to_srgb_8unorm(src[GCOMP]); + GLubyte b = util_format_linear_float_to_srgb_8unorm(src[BCOMP]); *d = PACK_COLOR_8888(127, r, g, b); } diff --git a/mesalib/src/mesa/main/format_parser.py b/mesalib/src/mesa/main/format_parser.py new file mode 100644 index 000000000..5e45c74de --- /dev/null +++ b/mesalib/src/mesa/main/format_parser.py @@ -0,0 +1,521 @@ +#!/usr/bin/env python +# +# Copyright 2009 VMware, Inc. +# Copyright 2014 Intel Corporation +# All Rights Reserved. +# +# Permission is hereby granted, free of charge, to any person obtaining a +# copy of this software and associated documentation files (the +# "Software"), to deal in the Software without restriction, including +# without limitation the rights to use, copy, modify, merge, publish, +# distribute, sub license, and/or sell copies of the Software, and to +# permit persons to whom the Software is furnished to do so, subject to +# the following conditions: +# +# The 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 NON-INFRINGEMENT. +# IN NO EVENT SHALL VMWARE AND/OR ITS SUPPLIERS BE LIABLE FOR +# ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, +# TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE +# SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +VOID = 'x' +UNSIGNED = 'u' +SIGNED = 's' +FLOAT = 'f' + +ARRAY = 'array' +PACKED = 'packed' +OTHER = 'other' + +RGB = 'rgb' +SRGB = 'srgb' +YUV = 'yuv' +ZS = 'zs' + +def is_power_of_two(x): + return not bool(x & (x - 1)) + +VERY_LARGE = 99999999999999999999999 + +class Channel: + """Describes a color channel.""" + + def __init__(self, type, norm, size): + self.type = type + self.norm = norm + self.size = size + self.sign = type in (SIGNED, FLOAT) + self.name = None # Set when the channels are added to the format + self.shift = -1 # Set when the channels are added to the format + self.index = -1 # Set when the channels are added to the format + + def __str__(self): + s = str(self.type) + if self.norm: + s += 'n' + s += str(self.size) + return s + + def __eq__(self, other): + return self.type == other.type and self.norm == other.norm and self.size == other.size + + def max(self): + """Returns the maximum representable number.""" + if self.type == FLOAT: + return VERY_LARGE + if self.norm: + return 1 + if self.type == UNSIGNED: + return (1 << self.size) - 1 + if self.type == SIGNED: + return (1 << (self.size - 1)) - 1 + assert False + + def min(self): + """Returns the minimum representable number.""" + if self.type == FLOAT: + return -VERY_LARGE + if self.type == UNSIGNED: + return 0 + if self.norm: + return -1 + if self.type == SIGNED: + return -(1 << (self.size - 1)) + assert False + + def one(self): + """Returns the value that represents 1.0f.""" + if self.type == UNSIGNED: + return (1 << self.size) - 1 + if self.type == SIGNED: + return (1 << (self.size - 1)) - 1 + else: + return 1 + + def is_power_of_two(self): + """Returns true if the size of this channel is a power of two.""" + return is_power_of_two(self.size) + +class Swizzle: + """Describes a swizzle operation. + + A Swizzle is a mapping from one set of channels in one format to the + channels in another. Each channel in the destination format is + associated with one of the following constants: + + * SWIZZLE_X: The first channel in the source format + * SWIZZLE_Y: The second channel in the source format + * SWIZZLE_Z: The third channel in the source format + * SWIZZLE_W: The fourth channel in the source format + * SWIZZLE_ZERO: The numeric constant 0 + * SWIZZLE_ONE: THe numeric constant 1 + * SWIZZLE_NONE: No data available for this channel + + Sometimes a Swizzle is represented by a 4-character string. In this + case, the source channels are represented by the characters "x", "y", + "z", and "w"; the numeric constants are represented as "0" and "1"; and + no mapping is represented by "_". For instance, the map from + luminance-alpha to rgba is given by "xxxy" because each of the three rgb + channels maps to the first luminance-alpha channel and the alpha channel + maps to second luminance-alpha channel. The mapping from bgr to rgba is + given by "zyx1" because the first three colors are reversed and alpha is + always 1. + """ + + __identity_str = 'xyzw01_' + + SWIZZLE_X = 0 + SWIZZLE_Y = 1 + SWIZZLE_Z = 2 + SWIZZLE_W = 3 + SWIZZLE_ZERO = 4 + SWIZZLE_ONE = 5 + SWIZZLE_NONE = 6 + + def __init__(self, swizzle): + """Creates a Swizzle object from a string or array.""" + if isinstance(swizzle, str): + swizzle = [Swizzle.__identity_str.index(c) for c in swizzle] + else: + swizzle = list(swizzle) + for s in swizzle: + assert isinstance(s, int) and 0 <= s and s <= Swizzle.SWIZZLE_NONE + + assert len(swizzle) <= 4 + + self.__list = swizzle + [Swizzle.SWIZZLE_NONE] * (4 - len(swizzle)) + assert len(self.__list) == 4 + + def __iter__(self): + """Returns an iterator that iterates over this Swizzle. + + The values that the iterator produces are described by the SWIZZLE_* + constants. + """ + return self.__list.__iter__() + + def __str__(self): + """Returns a string representation of this Swizzle.""" + return ''.join(Swizzle.__identity_str[i] for i in self.__list) + + def __getitem__(self, idx): + """Returns the SWIZZLE_* constant for the given destination channel. + + Valid values for the destination channel include any of the SWIZZLE_* + constants or any of the following single-character strings: "x", "y", + "z", "w", "r", "g", "b", "a", "z" "s". + """ + + if isinstance(idx, int): + assert idx >= Swizzle.SWIZZLE_X and idx <= Swizzle.SWIZZLE_NONE + if idx <= Swizzle.SWIZZLE_W: + return self.__list.__getitem__(idx) + else: + return idx + elif isinstance(idx, str): + if idx in 'xyzw': + idx = 'xyzw'.find(idx) + elif idx in 'rgba': + idx = 'rgba'.find(idx) + elif idx in 'zs': + idx = 'zs'.find(idx) + else: + assert False + return self.__list.__getitem__(idx) + else: + assert False + + def __mul__(self, other): + """Returns the composition of this Swizzle with another Swizzle. + + The resulting swizzle is such that, for any valid input to + __getitem__, (a * b)[i] = a[b[i]]. + """ + assert isinstance(other, Swizzle) + return Swizzle(self[x] for x in other) + + def inverse(self): + """Returns a pseudo-inverse of this swizzle. + + Since swizzling isn't necisaraly a bijection, a Swizzle can never + be truely inverted. However, the swizzle returned is *almost* the + inverse of this swizzle in the sense that, for each i in range(3), + a[a.inverse()[i]] is either i or SWIZZLE_NONE. If swizzle is just + a permutation with no channels added or removed, then this + function returns the actual inverse. + + This "pseudo-inverse" idea can be demonstrated by mapping from + luminance-alpha to rgba that is given by "xxxy". To get from rgba + to lumanence-alpha, we use Swizzle("xxxy").inverse() or "xw__". + This maps the first component in the lumanence-alpha texture is + the red component of the rgba image and the second to the alpha + component, exactly as you would expect. + """ + rev = [Swizzle.SWIZZLE_NONE] * 4 + for i in xrange(4): + for j in xrange(4): + if self.__list[j] == i and rev[i] == Swizzle.SWIZZLE_NONE: + rev[i] = j + return Swizzle(rev) + + +class Format: + """Describes a pixel format.""" + + def __init__(self, name, layout, block_width, block_height, channels, swizzle, colorspace): + """Constructs a Format from some metadata and a list of channels. + + The channel objects must be unique to this Format and should not be + re-used to construct another Format. This is because certain channel + information such as shift, offset, and the channel name are set when + the Format is created and are calculated based on the entire list of + channels. + + Arguments: + name -- Name of the format such as 'MESA_FORMAT_A8R8G8B8' + layout -- One of 'array', 'packed' 'other', or a compressed layout + block_width -- The block width if the format is compressed, 1 otherwise + block_height -- The block height if the format is compressed, 1 otherwise + channels -- A list of Channel objects + swizzle -- A Swizzle from this format to rgba + colorspace -- one of 'rgb', 'srgb', 'yuv', or 'zs' + """ + self.name = name + self.layout = layout + self.block_width = block_width + self.block_height = block_height + self.channels = channels + assert isinstance(swizzle, Swizzle) + self.swizzle = swizzle + self.name = name + assert colorspace in (RGB, SRGB, YUV, ZS) + self.colorspace = colorspace + + # Name the channels + chan_names = ['']*4 + if self.colorspace in (RGB, SRGB): + for (i, s) in enumerate(swizzle): + if s < 4: + chan_names[s] += 'rgba'[i] + elif colorspace == ZS: + for (i, s) in enumerate(swizzle): + if s < 4: + chan_names[s] += 'zs'[i] + else: + chan_names = ['x', 'y', 'z', 'w'] + + for c, name in zip(self.channels, chan_names): + assert c.name is None + if name == 'rgb': + c.name = 'l' + elif name == 'rgba': + c.name = 'i' + elif name == '': + c.name = 'x' + else: + c.name = name + + # Set indices and offsets + if self.layout == PACKED: + shift = 0 + for channel in self.channels: + assert channel.shift == -1 + channel.shift = shift + shift += channel.size + for idx, channel in enumerate(self.channels): + assert channel.index == -1 + channel.index = idx + else: + pass # Shift means nothing here + + def __str__(self): + return self.name + + def short_name(self): + """Returns a short name for a format. + + The short name should be suitable to be used as suffix in function + names. + """ + + name = self.name + if name.startswith('MESA_FORMAT_'): + name = name[len('MESA_FORMAT_'):] + name = name.lower() + return name + + def block_size(self): + """Returns the block size (in bits) of the format.""" + size = 0 + for channel in self.channels: + size += channel.size + return size + + def num_channels(self): + """Returns the number of channels in the format.""" + nr_channels = 0 + for channel in self.channels: + if channel.size: + nr_channels += 1 + return nr_channels + + def array_element(self): + """Returns a non-void channel if this format is an array, otherwise None. + + If the returned channel is not None, then this format can be + considered to be an array of num_channels() channels identical to the + returned channel. + """ + if self.layout == ARRAY: + return self.channels[0] + elif self.layout == PACKED: + ref_channel = self.channels[0] + if ref_channel.type == VOID: + ref_channel = self.channels[1] + for channel in self.channels: + if channel.size == 0 or channel.type == VOID: + continue + if channel.size != ref_channel.size or channel.size % 8 != 0: + return None + if channel.type != ref_channel.type: + return None + if channel.norm != ref_channel.norm: + return None + return ref_channel + else: + return None + + def is_array(self): + """Returns true if this format can be considered an array format. + + This function will return true if self.layout == 'array'. However, + some formats, such as MESA_FORMAT_A8G8B8R8, can be considered as + array formats even though they are technically packed. + """ + return self.array_element() != None + + def is_compressed(self): + """Returns true if this is a compressed format.""" + return self.block_width != 1 or self.block_height != 1 + + def is_int(self): + """Returns true if this format is an integer format. + + See also: is_norm() + """ + if self.layout not in (ARRAY, PACKED): + return False + for channel in self.channels: + if channel.type not in (VOID, UNSIGNED, SIGNED): + return False + return True + + def is_float(self): + """Returns true if this format is an floating-point format.""" + if self.layout not in (ARRAY, PACKED): + return False + for channel in self.channels: + if channel.type not in (VOID, FLOAT): + return False + return True + + def channel_type(self): + """Returns the type of the channels in this format.""" + _type = VOID + for c in self.channels: + if c.type == VOID: + continue + if _type == VOID: + _type = c.type + assert c.type == _type + return _type + + def channel_size(self): + """Returns the size (in bits) of the channels in this format. + + This function should only be called if all of the channels have the + same size. This is always the case if is_array() returns true. + """ + size = None + for c in self.channels: + if c.type == VOID: + continue + if size is None: + size = c.size + assert c.size == size + return size + + def max_channel_size(self): + """Returns the size of the largest channel.""" + size = 0 + for c in self.channels: + if c.type == VOID: + continue + size = max(size, c.size) + return size + + def is_normalized(self): + """Returns true if this format is normalized. + + While only integer formats can be normalized, not all integer formats + are normalized. Normalized integer formats are those where the + integer value is re-interpreted as a fixed point value in the range + [0, 1]. + """ + norm = None + for c in self.channels: + if c.type == VOID: + continue + if norm is None: + norm = c.norm + assert c.norm == norm + return norm + + def has_channel(self, name): + """Returns true if this format has the given channel.""" + if self.is_compressed(): + # Compressed formats are a bit tricky because the list of channels + # contains a single channel of type void. Since we don't have any + # channel information there, we pull it from the swizzle. + if str(self.swizzle) == 'xxxx': + return name == 'i' + elif str(self.swizzle)[0:3] in ('xxx', 'yyy'): + if name == 'l': + return True + elif name == 'a': + return self.swizzle['a'] <= Swizzle.SWIZZLE_W + else: + return False + elif name in 'rgba': + return self.swizzle[name] <= Swizzle.SWIZZLE_W + else: + return False + else: + for channel in self.channels: + if channel.name == name: + return True + return False + + def get_channel(self, name): + """Returns the channel with the given name if it exists.""" + for channel in self.channels: + if channel.name == name: + return channel + return None + +def _parse_channels(fields, layout, colorspace, swizzle): + channels = [] + for field in fields: + if not field: + continue + + type = field[0] if field[0] else 'x' + + if field[1] == 'n': + norm = True + size = int(field[2:]) + else: + norm = False + size = int(field[1:]) + + channel = Channel(type, norm, size) + channels.append(channel) + + return channels + +def parse(filename): + """Parse a format descrition in CSV format. + + This function parses the given CSV file and returns an iterable of + channels.""" + + with open(filename) as stream: + for line in stream: + try: + comment = line.index('#') + except ValueError: + pass + else: + line = line[:comment] + line = line.strip() + if not line: + continue + + fields = [field.strip() for field in line.split(',')] + + name = fields[0] + layout = fields[1] + block_width = int(fields[2]) + block_height = int(fields[3]) + colorspace = fields[9] + + swizzle = Swizzle(fields[8]) + channels = _parse_channels(fields[4:8], layout, colorspace, swizzle) + + yield Format(name, layout, block_width, block_height, channels, swizzle, colorspace) diff --git a/mesalib/src/mesa/main/format_unpack.c b/mesalib/src/mesa/main/format_unpack.c index ad5ea4cd1..b84ed0248 100644 --- a/mesalib/src/mesa/main/format_unpack.c +++ b/mesalib/src/mesa/main/format_unpack.c @@ -28,6 +28,7 @@ #include "macros.h" #include "../../gallium/auxiliary/util/u_format_rgb9e5.h" #include "../../gallium/auxiliary/util/u_format_r11g11b10f.h" +#include "util/format_srgb.h" /** Helper struct for MESA_FORMAT_Z32_FLOAT_S8X24_UINT */ @@ -53,34 +54,6 @@ struct z32f_x24s8 #define EXPAND_6_8(X) ( ((X) << 2) | ((X) >> 4) ) -/** - * Convert an 8-bit sRGB value from non-linear space to a - * linear RGB value in [0, 1]. - * Implemented with a 256-entry lookup table. - */ -GLfloat -_mesa_nonlinear_to_linear(GLubyte cs8) -{ - static GLfloat table[256]; - static GLboolean tableReady = GL_FALSE; - if (!tableReady) { - /* compute lookup table now */ - GLuint i; - for (i = 0; i < 256; i++) { - const GLfloat cs = UBYTE_TO_FLOAT(i); - if (cs <= 0.04045) { - table[i] = cs / 12.92f; - } - else { - table[i] = (GLfloat) pow((cs + 0.055) / 1.055, 2.4); - } - } - tableReady = GL_TRUE; - } - return table[cs8]; -} - - /**********************************************************************/ /* Unpack, returning GLfloat colors */ /**********************************************************************/ @@ -763,9 +736,9 @@ unpack_BGR_SRGB8(const void *src, GLfloat dst[][4], GLuint n) const GLubyte *s = (const GLubyte *) src; GLuint i; for (i = 0; i < n; i++) { - dst[i][RCOMP] = _mesa_nonlinear_to_linear(s[i*3+2]); - dst[i][GCOMP] = _mesa_nonlinear_to_linear(s[i*3+1]); - dst[i][BCOMP] = _mesa_nonlinear_to_linear(s[i*3+0]); + dst[i][RCOMP] = util_format_srgb_8unorm_to_linear_float(s[i*3+2]); + dst[i][GCOMP] = util_format_srgb_8unorm_to_linear_float(s[i*3+1]); + dst[i][BCOMP] = util_format_srgb_8unorm_to_linear_float(s[i*3+0]); dst[i][ACOMP] = 1.0F; } } @@ -776,9 +749,9 @@ unpack_A8B8G8R8_SRGB(const void *src, GLfloat dst[][4], GLuint n) const GLuint *s = ((const GLuint *) src); GLuint i; for (i = 0; i < n; i++) { - dst[i][RCOMP] = _mesa_nonlinear_to_linear( (s[i] >> 24) ); - dst[i][GCOMP] = _mesa_nonlinear_to_linear( (s[i] >> 16) & 0xff ); - dst[i][BCOMP] = _mesa_nonlinear_to_linear( (s[i] >> 8) & 0xff ); + dst[i][RCOMP] = util_format_srgb_8unorm_to_linear_float( (s[i] >> 24) ); + dst[i][GCOMP] = util_format_srgb_8unorm_to_linear_float( (s[i] >> 16) & 0xff ); + dst[i][BCOMP] = util_format_srgb_8unorm_to_linear_float( (s[i] >> 8) & 0xff ); dst[i][ACOMP] = UBYTE_TO_FLOAT( s[i] & 0xff ); /* linear! */ } } @@ -789,9 +762,9 @@ unpack_B8G8R8A8_SRGB(const void *src, GLfloat dst[][4], GLuint n) const GLuint *s = ((const GLuint *) src); GLuint i; for (i = 0; i < n; i++) { - dst[i][RCOMP] = _mesa_nonlinear_to_linear( (s[i] >> 16) & 0xff ); - dst[i][GCOMP] = _mesa_nonlinear_to_linear( (s[i] >> 8) & 0xff ); - dst[i][BCOMP] = _mesa_nonlinear_to_linear( (s[i] ) & 0xff ); + dst[i][RCOMP] = util_format_srgb_8unorm_to_linear_float( (s[i] >> 16) & 0xff ); + dst[i][GCOMP] = util_format_srgb_8unorm_to_linear_float( (s[i] >> 8) & 0xff ); + dst[i][BCOMP] = util_format_srgb_8unorm_to_linear_float( (s[i] ) & 0xff ); dst[i][ACOMP] = UBYTE_TO_FLOAT( s[i] >> 24 ); /* linear! */ } } @@ -802,9 +775,9 @@ unpack_R8G8B8A8_SRGB(const void *src, GLfloat dst[][4], GLuint n) const GLuint *s = ((const GLuint *) src); GLuint i; for (i = 0; i < n; i++) { - dst[i][RCOMP] = _mesa_nonlinear_to_linear( (s[i] ) & 0xff ); - dst[i][GCOMP] = _mesa_nonlinear_to_linear( (s[i] >> 8) & 0xff ); - dst[i][BCOMP] = _mesa_nonlinear_to_linear( (s[i] >> 16) & 0xff ); + dst[i][RCOMP] = util_format_srgb_8unorm_to_linear_float( (s[i] ) & 0xff ); + dst[i][GCOMP] = util_format_srgb_8unorm_to_linear_float( (s[i] >> 8) & 0xff ); + dst[i][BCOMP] = util_format_srgb_8unorm_to_linear_float( (s[i] >> 16) & 0xff ); dst[i][ACOMP] = UBYTE_TO_FLOAT( s[i] >> 24 ); /* linear! */ } } @@ -817,7 +790,7 @@ unpack_L_SRGB8(const void *src, GLfloat dst[][4], GLuint n) for (i = 0; i < n; i++) { dst[i][RCOMP] = dst[i][GCOMP] = - dst[i][BCOMP] = _mesa_nonlinear_to_linear(s[i]); + dst[i][BCOMP] = util_format_srgb_8unorm_to_linear_float(s[i]); dst[i][ACOMP] = 1.0F; } } @@ -830,7 +803,7 @@ unpack_L8A8_SRGB(const void *src, GLfloat dst[][4], GLuint n) for (i = 0; i < n; i++) { dst[i][RCOMP] = dst[i][GCOMP] = - dst[i][BCOMP] = _mesa_nonlinear_to_linear(s[i] & 0xff); + dst[i][BCOMP] = util_format_srgb_8unorm_to_linear_float(s[i] & 0xff); dst[i][ACOMP] = UBYTE_TO_FLOAT(s[i] >> 8); /* linear! */ } } @@ -2124,9 +2097,9 @@ unpack_R8G8B8X8_SRGB(const void *src, GLfloat dst[][4], GLuint n) const GLuint *s = ((const GLuint *) src); GLuint i; for (i = 0; i < n; i++) { - dst[i][RCOMP] = _mesa_nonlinear_to_linear( (s[i] ) & 0xff ); - dst[i][GCOMP] = _mesa_nonlinear_to_linear( (s[i] >> 8) & 0xff ); - dst[i][BCOMP] = _mesa_nonlinear_to_linear( (s[i] >> 16) & 0xff ); + dst[i][RCOMP] = util_format_srgb_8unorm_to_linear_float( (s[i] ) & 0xff ); + dst[i][GCOMP] = util_format_srgb_8unorm_to_linear_float( (s[i] >> 8) & 0xff ); + dst[i][BCOMP] = util_format_srgb_8unorm_to_linear_float( (s[i] >> 16) & 0xff ); dst[i][ACOMP] = UBYTE_TO_FLOAT( s[i] >> 24 ); /* linear! */ } } @@ -2319,9 +2292,9 @@ unpack_B8G8R8X8_SRGB(const void *src, GLfloat dst[][4], GLuint n) const GLuint *s = ((const GLuint *) src); GLuint i; for (i = 0; i < n; i++) { - dst[i][RCOMP] = _mesa_nonlinear_to_linear( (s[i] >> 16) & 0xff ); - dst[i][GCOMP] = _mesa_nonlinear_to_linear( (s[i] >> 8) & 0xff ); - dst[i][BCOMP] = _mesa_nonlinear_to_linear( (s[i] ) & 0xff ); + dst[i][RCOMP] = util_format_srgb_8unorm_to_linear_float( (s[i] >> 16) & 0xff ); + dst[i][GCOMP] = util_format_srgb_8unorm_to_linear_float( (s[i] >> 8) & 0xff ); + dst[i][BCOMP] = util_format_srgb_8unorm_to_linear_float( (s[i] ) & 0xff ); dst[i][ACOMP] = 1.0F; } } diff --git a/mesalib/src/mesa/main/format_unpack.h b/mesalib/src/mesa/main/format_unpack.h index 51f97df4d..eba3c6650 100644 --- a/mesalib/src/mesa/main/format_unpack.h +++ b/mesalib/src/mesa/main/format_unpack.h @@ -25,9 +25,6 @@ #ifndef FORMAT_UNPACK_H #define FORMAT_UNPACK_H -extern GLfloat -_mesa_nonlinear_to_linear(GLubyte cs8); - extern void _mesa_unpack_rgba_row(mesa_format format, GLuint n, const void *src, GLfloat dst[][4]); diff --git a/mesalib/src/mesa/main/format_utils.c b/mesalib/src/mesa/main/format_utils.c new file mode 100644 index 000000000..240e3bc0c --- /dev/null +++ b/mesalib/src/mesa/main/format_utils.c @@ -0,0 +1,977 @@ +/* + * Mesa 3-D graphics library + * + * Copyright (C) 2014 Intel Corporation All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included + * in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + */ + +#include "format_utils.h" +#include "glformats.h" + +static const uint8_t map_identity[7] = { 0, 1, 2, 3, 4, 5, 6 }; +static const uint8_t map_3210[7] = { 3, 2, 1, 0, 4, 5, 6 }; +static const uint8_t map_1032[7] = { 1, 0, 3, 2, 4, 5, 6 }; + +/** + * Describes a format as an array format, if possible + * + * A helper function for figuring out if a (possibly packed) format is + * actually an array format and, if so, what the array parameters are. + * + * \param[in] format the mesa format + * \param[out] type the GL type of the array (GL_BYTE, etc.) + * \param[out] num_components the number of components in the array + * \param[out] swizzle a swizzle describing how to get from the + * given format to RGBA + * \param[out] normalized for integer formats, this represents whether + * the format is a normalized integer or a + * regular integer + * \return true if this format is an array format, false otherwise + */ +bool +_mesa_format_to_array(mesa_format format, GLenum *type, int *num_components, + uint8_t swizzle[4], bool *normalized) +{ + int i; + GLuint format_components; + uint8_t packed_swizzle[4]; + const uint8_t *endian; + + if (_mesa_is_format_compressed(format)) + return false; + + *normalized = !_mesa_is_format_integer(format); + + _mesa_format_to_type_and_comps(format, type, &format_components); + + switch (_mesa_get_format_layout(format)) { + case MESA_FORMAT_LAYOUT_ARRAY: + *num_components = format_components; + _mesa_get_format_swizzle(format, swizzle); + return true; + case MESA_FORMAT_LAYOUT_PACKED: + switch (*type) { + case GL_UNSIGNED_BYTE: + case GL_BYTE: + if (_mesa_get_format_max_bits(format) != 8) + return false; + *num_components = _mesa_get_format_bytes(format); + switch (*num_components) { + case 1: + endian = map_identity; + break; + case 2: + endian = _mesa_little_endian() ? map_identity : map_1032; + break; + case 4: + endian = _mesa_little_endian() ? map_identity : map_3210; + break; + default: + endian = map_identity; + assert(!"Invalid number of components"); + } + break; + case GL_UNSIGNED_SHORT: + case GL_SHORT: + case GL_HALF_FLOAT: + if (_mesa_get_format_max_bits(format) != 16) + return false; + *num_components = _mesa_get_format_bytes(format) / 2; + switch (*num_components) { + case 1: + endian = map_identity; + break; + case 2: + endian = _mesa_little_endian() ? map_identity : map_1032; + break; + default: + endian = map_identity; + assert(!"Invalid number of components"); + } + break; + case GL_UNSIGNED_INT: + case GL_INT: + case GL_FLOAT: + /* This isn't packed. At least not really. */ + assert(format_components == 1); + if (_mesa_get_format_max_bits(format) != 32) + return false; + *num_components = format_components; + endian = map_identity; + break; + default: + return false; + } + + _mesa_get_format_swizzle(format, packed_swizzle); + + for (i = 0; i < 4; ++i) + swizzle[i] = endian[packed_swizzle[i]]; + + return true; + case MESA_FORMAT_LAYOUT_OTHER: + default: + return false; + } +} + +/* A bunch of format conversion macros and helper functions used below */ + +/* Only guaranteed to work for BITS <= 32 */ +#define MAX_UINT(BITS) ((BITS) == 32 ? UINT32_MAX : ((1u << (BITS)) - 1)) +#define MAX_INT(BITS) ((int)MAX_UINT((BITS) - 1)) + +/* Extends an integer of size SRC_BITS to one of size DST_BITS linearly */ +#define EXTEND_NORMALIZED_INT(X, SRC_BITS, DST_BITS) \ + (((X) * (int)(MAX_UINT(DST_BITS) / MAX_UINT(SRC_BITS))) + \ + ((DST_BITS % SRC_BITS) ? ((X) >> (SRC_BITS - DST_BITS % SRC_BITS)) : 0)) + +static inline float +unorm_to_float(unsigned x, unsigned src_bits) +{ + return x * (1.0f / (float)MAX_UINT(src_bits)); +} + +static inline float +snorm_to_float(int x, unsigned src_bits) +{ + if (x == -MAX_INT(src_bits)) + return -1.0f; + else + return x * (1.0f / (float)MAX_INT(src_bits)); +} + +static inline uint16_t +unorm_to_half(unsigned x, unsigned src_bits) +{ + return _mesa_float_to_half(unorm_to_float(x, src_bits)); +} + +static inline uint16_t +snorm_to_half(int x, unsigned src_bits) +{ + return _mesa_float_to_half(snorm_to_float(x, src_bits)); +} + +static inline unsigned +float_to_unorm(float x, unsigned dst_bits) +{ + if (x < 0.0f) + return 0; + else if (x > 1.0f) + return MAX_UINT(dst_bits); + else + return F_TO_I(x * MAX_UINT(dst_bits)); +} + +static inline unsigned +half_to_unorm(uint16_t x, unsigned dst_bits) +{ + return float_to_unorm(_mesa_half_to_float(x), dst_bits); +} + +static inline unsigned +unorm_to_unorm(unsigned x, unsigned src_bits, unsigned dst_bits) +{ + if (src_bits < dst_bits) + return EXTEND_NORMALIZED_INT(x, src_bits, dst_bits); + else + return x >> (src_bits - dst_bits); +} + +static inline unsigned +snorm_to_unorm(int x, unsigned src_bits, unsigned dst_bits) +{ + if (x < 0) + return 0; + else + return unorm_to_unorm(x, src_bits - 1, dst_bits); +} + +static inline int +float_to_snorm(float x, unsigned dst_bits) +{ + if (x < -1.0f) + return -MAX_INT(dst_bits); + else if (x > 1.0f) + return MAX_INT(dst_bits); + else + return F_TO_I(x * MAX_INT(dst_bits)); +} + +static inline int +half_to_snorm(uint16_t x, unsigned dst_bits) +{ + return float_to_snorm(_mesa_half_to_float(x), dst_bits); +} + +static inline int +unorm_to_snorm(unsigned x, unsigned src_bits, unsigned dst_bits) +{ + return unorm_to_unorm(x, src_bits, dst_bits - 1); +} + +static inline int +snorm_to_snorm(int x, unsigned src_bits, unsigned dst_bits) +{ + if (x < -MAX_INT(src_bits)) + return -MAX_INT(dst_bits); + else if (src_bits < dst_bits) + return EXTEND_NORMALIZED_INT(x, src_bits - 1, dst_bits - 1); + else + return x >> (src_bits - dst_bits); +} + +static inline unsigned +float_to_uint(float x) +{ + if (x < 0.0f) + return 0; + else + return x; +} + +static inline unsigned +half_to_uint(uint16_t x) +{ + if (_mesa_half_is_negative(x)) + return 0; + else + return _mesa_float_to_half(x); +} + +/** + * Attempts to perform the given swizzle-and-convert operation with memcpy + * + * This function determines if the given swizzle-and-convert operation can + * be done with a simple memcpy and, if so, does the memcpy. If not, it + * returns false and we fall back to the standard version below. + * + * The arguments are exactly the same as for _mesa_swizzle_and_convert + * + * \return true if it successfully performed the swizzle-and-convert + * operation with memcpy, false otherwise + */ +static bool +swizzle_convert_try_memcpy(void *dst, GLenum dst_type, int num_dst_channels, + const void *src, GLenum src_type, int num_src_channels, + const uint8_t swizzle[4], bool normalized, int count) +{ + int i; + + if (src_type != dst_type) + return false; + if (num_src_channels != num_dst_channels) + return false; + + for (i = 0; i < num_dst_channels; ++i) + if (swizzle[i] != i && swizzle[i] != MESA_FORMAT_SWIZZLE_NONE) + return false; + + memcpy(dst, src, count * num_src_channels * _mesa_sizeof_type(src_type)); + + return true; +} + +/** + * Represents a single instance of the standard swizzle-and-convert loop + * + * Any swizzle-and-convert operation simply loops through the pixels and + * performs the transformation operation one pixel at a time. This macro + * embodies one instance of the conversion loop. This way we can do all + * control flow outside of the loop and allow the compiler to unroll + * everything inside the loop. + * + * Note: This loop is carefully crafted for performance. Be careful when + * changing it and run some benchmarks to ensure no performance regressions + * if you do. + * + * \param DST_TYPE the C datatype of the destination + * \param DST_CHANS the number of destination channels + * \param SRC_TYPE the C datatype of the source + * \param SRC_CHANS the number of source channels + * \param CONV an expression for converting from the source data, + * storred in the variable "src", to the destination + * format + */ +#define SWIZZLE_CONVERT_LOOP(DST_TYPE, DST_CHANS, SRC_TYPE, SRC_CHANS, CONV) \ + for (s = 0; s < count; ++s) { \ + for (j = 0; j < SRC_CHANS; ++j) { \ + SRC_TYPE src = typed_src[j]; \ + tmp[j] = CONV; \ + } \ + \ + typed_dst[0] = tmp[swizzle_x]; \ + if (DST_CHANS > 1) { \ + typed_dst[1] = tmp[swizzle_y]; \ + if (DST_CHANS > 2) { \ + typed_dst[2] = tmp[swizzle_z]; \ + if (DST_CHANS > 3) { \ + typed_dst[3] = tmp[swizzle_w]; \ + } \ + } \ + } \ + typed_src += SRC_CHANS; \ + typed_dst += DST_CHANS; \ + } \ + +/** + * Represents a single swizzle-and-convert operation + * + * This macro represents everything done in a single swizzle-and-convert + * operation. The actual work is done by the SWIZZLE_CONVERT_LOOP macro. + * This macro acts as a wrapper that uses a nested switch to ensure that + * all looping parameters get unrolled. + * + * This macro makes assumptions about variables etc. in the calling + * function. Changes to _mesa_swizzle_and_convert may require changes to + * this macro. + * + * \param DST_TYPE the C datatype of the destination + * \param SRC_TYPE the C datatype of the source + * \param CONV an expression for converting from the source data, + * storred in the variable "src", to the destination + * format + */ +#define SWIZZLE_CONVERT(DST_TYPE, SRC_TYPE, CONV) \ + do { \ + const SRC_TYPE *typed_src = void_src; \ + DST_TYPE *typed_dst = void_dst; \ + DST_TYPE tmp[7]; \ + tmp[4] = 0; \ + tmp[5] = one; \ + switch (num_dst_channels) { \ + case 1: \ + switch (num_src_channels) { \ + case 1: \ + SWIZZLE_CONVERT_LOOP(DST_TYPE, 1, SRC_TYPE, 1, CONV) \ + break; \ + case 2: \ + SWIZZLE_CONVERT_LOOP(DST_TYPE, 1, SRC_TYPE, 2, CONV) \ + break; \ + case 3: \ + SWIZZLE_CONVERT_LOOP(DST_TYPE, 1, SRC_TYPE, 3, CONV) \ + break; \ + case 4: \ + SWIZZLE_CONVERT_LOOP(DST_TYPE, 1, SRC_TYPE, 4, CONV) \ + break; \ + } \ + break; \ + case 2: \ + switch (num_src_channels) { \ + case 1: \ + SWIZZLE_CONVERT_LOOP(DST_TYPE, 2, SRC_TYPE, 1, CONV) \ + break; \ + case 2: \ + SWIZZLE_CONVERT_LOOP(DST_TYPE, 2, SRC_TYPE, 2, CONV) \ + break; \ + case 3: \ + SWIZZLE_CONVERT_LOOP(DST_TYPE, 2, SRC_TYPE, 3, CONV) \ + break; \ + case 4: \ + SWIZZLE_CONVERT_LOOP(DST_TYPE, 2, SRC_TYPE, 4, CONV) \ + break; \ + } \ + break; \ + case 3: \ + switch (num_src_channels) { \ + case 1: \ + SWIZZLE_CONVERT_LOOP(DST_TYPE, 3, SRC_TYPE, 1, CONV) \ + break; \ + case 2: \ + SWIZZLE_CONVERT_LOOP(DST_TYPE, 3, SRC_TYPE, 2, CONV) \ + break; \ + case 3: \ + SWIZZLE_CONVERT_LOOP(DST_TYPE, 3, SRC_TYPE, 3, CONV) \ + break; \ + case 4: \ + SWIZZLE_CONVERT_LOOP(DST_TYPE, 3, SRC_TYPE, 4, CONV) \ + break; \ + } \ + break; \ + case 4: \ + switch (num_src_channels) { \ + case 1: \ + SWIZZLE_CONVERT_LOOP(DST_TYPE, 4, SRC_TYPE, 1, CONV) \ + break; \ + case 2: \ + SWIZZLE_CONVERT_LOOP(DST_TYPE, 4, SRC_TYPE, 2, CONV) \ + break; \ + case 3: \ + SWIZZLE_CONVERT_LOOP(DST_TYPE, 4, SRC_TYPE, 3, CONV) \ + break; \ + case 4: \ + SWIZZLE_CONVERT_LOOP(DST_TYPE, 4, SRC_TYPE, 4, CONV) \ + break; \ + } \ + break; \ + } \ + } while (0); + +/** + * Convert between array-based color formats. + * + * Most format conversion operations required by GL can be performed by + * converting one channel at a time, shuffling the channels around, and + * optionally filling missing channels with zeros and ones. This function + * does just that in a general, yet efficient, way. + * + * The swizzle parameter is an array of 4 numbers (see + * _mesa_get_format_swizzle) that describes where each channel in the + * destination should come from in the source. If swizzle[i] < 4 then it + * means that dst[i] = CONVERT(src[swizzle[i]]). If swizzle[i] is + * MESA_FORMAT_SWIZZLE_ZERO or MESA_FORMAT_SWIZZLE_ONE, the corresponding + * dst[i] will be filled with the appropreate representation of zero or one + * respectively. + * + * Under most circumstances, the source and destination images must be + * different as no care is taken not to clobber one with the other. + * However, if they have the same number of bits per pixel, it is safe to + * do an in-place conversion. + * + * \param[out] dst pointer to where the converted data should + * be stored + * + * \param[in] dst_type the destination GL type of the converted + * data (GL_BYTE, etc.) + * + * \param[in] num_dst_channels the number of channels in the converted + * data + * + * \param[in] src pointer to the source data + * + * \param[in] src_type the GL type of the source data (GL_BYTE, + * etc.) + * + * \param[in] num_src_channels the number of channels in the source data + * (the number of channels total, not just + * the number used) + * + * \param[in] swizzle describes how to get the destination data + * from the source data. + * + * \param[in] normalized for integer types, this indicates whether + * the data should be considered as integers + * or as normalized integers; + * + * \param[in] count the number of pixels to convert + */ +void +_mesa_swizzle_and_convert(void *void_dst, GLenum dst_type, int num_dst_channels, + const void *void_src, GLenum src_type, int num_src_channels, + const uint8_t swizzle[4], bool normalized, int count) +{ + int s, j; + register uint8_t swizzle_x, swizzle_y, swizzle_z, swizzle_w; + + if (swizzle_convert_try_memcpy(void_dst, dst_type, num_dst_channels, + void_src, src_type, num_src_channels, + swizzle, normalized, count)) + return; + + swizzle_x = swizzle[0]; + swizzle_y = swizzle[1]; + swizzle_z = swizzle[2]; + swizzle_w = swizzle[3]; + + switch (dst_type) { + case GL_FLOAT: + { + const float one = 1.0f; + switch (src_type) { + case GL_FLOAT: + SWIZZLE_CONVERT(float, float, src) + break; + case GL_HALF_FLOAT: + SWIZZLE_CONVERT(float, uint16_t, _mesa_half_to_float(src)) + break; + case GL_UNSIGNED_BYTE: + if (normalized) { + SWIZZLE_CONVERT(float, uint8_t, unorm_to_float(src, 8)) + } else { + SWIZZLE_CONVERT(float, uint8_t, src) + } + break; + case GL_BYTE: + if (normalized) { + SWIZZLE_CONVERT(float, int8_t, snorm_to_float(src, 8)) + } else { + SWIZZLE_CONVERT(float, int8_t, src) + } + break; + case GL_UNSIGNED_SHORT: + if (normalized) { + SWIZZLE_CONVERT(float, uint16_t, unorm_to_float(src, 16)) + } else { + SWIZZLE_CONVERT(float, uint16_t, src) + } + break; + case GL_SHORT: + if (normalized) { + SWIZZLE_CONVERT(float, int16_t, snorm_to_float(src, 16)) + } else { + SWIZZLE_CONVERT(float, int16_t, src) + } + break; + case GL_UNSIGNED_INT: + if (normalized) { + SWIZZLE_CONVERT(float, uint32_t, unorm_to_float(src, 32)) + } else { + SWIZZLE_CONVERT(float, uint32_t, src) + } + break; + case GL_INT: + if (normalized) { + SWIZZLE_CONVERT(float, int32_t, snorm_to_float(src, 32)) + } else { + SWIZZLE_CONVERT(float, int32_t, src) + } + break; + default: + assert(!"Invalid channel type combination"); + } + } + break; + case GL_HALF_FLOAT: + { + const uint16_t one = _mesa_float_to_half(1.0f); + switch (src_type) { + case GL_FLOAT: + SWIZZLE_CONVERT(uint16_t, float, _mesa_float_to_half(src)) + break; + case GL_HALF_FLOAT: + SWIZZLE_CONVERT(uint16_t, uint16_t, src) + break; + case GL_UNSIGNED_BYTE: + if (normalized) { + SWIZZLE_CONVERT(uint16_t, uint8_t, unorm_to_half(src, 8)) + } else { + SWIZZLE_CONVERT(uint16_t, uint8_t, _mesa_float_to_half(src)) + } + break; + case GL_BYTE: + if (normalized) { + SWIZZLE_CONVERT(uint16_t, int8_t, snorm_to_half(src, 8)) + } else { + SWIZZLE_CONVERT(uint16_t, int8_t, _mesa_float_to_half(src)) + } + break; + case GL_UNSIGNED_SHORT: + if (normalized) { + SWIZZLE_CONVERT(uint16_t, uint16_t, unorm_to_half(src, 16)) + } else { + SWIZZLE_CONVERT(uint16_t, uint16_t, _mesa_float_to_half(src)) + } + break; + case GL_SHORT: + if (normalized) { + SWIZZLE_CONVERT(uint16_t, int16_t, snorm_to_half(src, 16)) + } else { + SWIZZLE_CONVERT(uint16_t, int16_t, _mesa_float_to_half(src)) + } + break; + case GL_UNSIGNED_INT: + if (normalized) { + SWIZZLE_CONVERT(uint16_t, uint32_t, unorm_to_half(src, 32)) + } else { + SWIZZLE_CONVERT(uint16_t, uint32_t, _mesa_float_to_half(src)) + } + break; + case GL_INT: + if (normalized) { + SWIZZLE_CONVERT(uint16_t, int32_t, snorm_to_half(src, 32)) + } else { + SWIZZLE_CONVERT(uint16_t, int32_t, _mesa_float_to_half(src)) + } + break; + default: + assert(!"Invalid channel type combination"); + } + } + break; + case GL_UNSIGNED_BYTE: + { + const uint8_t one = normalized ? UINT8_MAX : 1; + switch (src_type) { + case GL_FLOAT: + if (normalized) { + SWIZZLE_CONVERT(uint8_t, float, float_to_unorm(src, 8)) + } else { + SWIZZLE_CONVERT(uint8_t, float, (src < 0) ? 0 : src) + } + break; + case GL_HALF_FLOAT: + if (normalized) { + SWIZZLE_CONVERT(uint8_t, uint16_t, half_to_unorm(src, 8)) + } else { + SWIZZLE_CONVERT(uint8_t, uint16_t, half_to_uint(src)) + } + break; + case GL_UNSIGNED_BYTE: + SWIZZLE_CONVERT(uint8_t, uint8_t, src) + break; + case GL_BYTE: + if (normalized) { + SWIZZLE_CONVERT(uint8_t, int8_t, snorm_to_unorm(src, 8, 8)) + } else { + SWIZZLE_CONVERT(uint8_t, int8_t, (src < 0) ? 0 : src) + } + break; + case GL_UNSIGNED_SHORT: + if (normalized) { + SWIZZLE_CONVERT(uint8_t, uint16_t, unorm_to_unorm(src, 16, 8)) + } else { + SWIZZLE_CONVERT(uint8_t, uint16_t, src) + } + break; + case GL_SHORT: + if (normalized) { + SWIZZLE_CONVERT(uint8_t, int16_t, snorm_to_unorm(src, 16, 8)) + } else { + SWIZZLE_CONVERT(uint8_t, int16_t, (src < 0) ? 0 : src) + } + break; + case GL_UNSIGNED_INT: + if (normalized) { + SWIZZLE_CONVERT(uint8_t, uint32_t, unorm_to_unorm(src, 32, 8)) + } else { + SWIZZLE_CONVERT(uint8_t, uint32_t, src) + } + break; + case GL_INT: + if (normalized) { + SWIZZLE_CONVERT(uint8_t, int32_t, snorm_to_unorm(src, 32, 8)) + } else { + SWIZZLE_CONVERT(uint8_t, int32_t, (src < 0) ? 0 : src) + } + break; + default: + assert(!"Invalid channel type combination"); + } + } + break; + case GL_BYTE: + { + const int8_t one = normalized ? INT8_MAX : 1; + switch (src_type) { + case GL_FLOAT: + if (normalized) { + SWIZZLE_CONVERT(uint8_t, float, float_to_snorm(src, 8)) + } else { + SWIZZLE_CONVERT(uint8_t, float, src) + } + break; + case GL_HALF_FLOAT: + if (normalized) { + SWIZZLE_CONVERT(uint8_t, uint16_t, half_to_snorm(src, 8)) + } else { + SWIZZLE_CONVERT(uint8_t, uint16_t, _mesa_half_to_float(src)) + } + break; + case GL_UNSIGNED_BYTE: + if (normalized) { + SWIZZLE_CONVERT(int8_t, uint8_t, unorm_to_snorm(src, 8, 8)) + } else { + SWIZZLE_CONVERT(int8_t, uint8_t, src) + } + break; + case GL_BYTE: + SWIZZLE_CONVERT(int8_t, int8_t, src) + break; + case GL_UNSIGNED_SHORT: + if (normalized) { + SWIZZLE_CONVERT(int8_t, uint16_t, unorm_to_snorm(src, 16, 8)) + } else { + SWIZZLE_CONVERT(int8_t, uint16_t, src) + } + break; + case GL_SHORT: + if (normalized) { + SWIZZLE_CONVERT(int8_t, int16_t, snorm_to_snorm(src, 16, 8)) + } else { + SWIZZLE_CONVERT(int8_t, int16_t, src) + } + break; + case GL_UNSIGNED_INT: + if (normalized) { + SWIZZLE_CONVERT(int8_t, uint32_t, unorm_to_snorm(src, 32, 8)) + } else { + SWIZZLE_CONVERT(int8_t, uint32_t, src) + } + break; + case GL_INT: + if (normalized) { + SWIZZLE_CONVERT(int8_t, int32_t, snorm_to_snorm(src, 32, 8)) + } else { + SWIZZLE_CONVERT(int8_t, int32_t, src) + } + break; + default: + assert(!"Invalid channel type combination"); + } + } + break; + case GL_UNSIGNED_SHORT: + { + const uint16_t one = normalized ? UINT16_MAX : 1; + switch (src_type) { + case GL_FLOAT: + if (normalized) { + SWIZZLE_CONVERT(uint16_t, float, float_to_unorm(src, 16)) + } else { + SWIZZLE_CONVERT(uint16_t, float, (src < 0) ? 0 : src) + } + break; + case GL_HALF_FLOAT: + if (normalized) { + SWIZZLE_CONVERT(uint16_t, uint16_t, half_to_unorm(src, 16)) + } else { + SWIZZLE_CONVERT(uint16_t, uint16_t, half_to_uint(src)) + } + break; + case GL_UNSIGNED_BYTE: + if (normalized) { + SWIZZLE_CONVERT(uint16_t, uint8_t, unorm_to_unorm(src, 8, 16)) + } else { + SWIZZLE_CONVERT(uint16_t, uint8_t, src) + } + break; + case GL_BYTE: + if (normalized) { + SWIZZLE_CONVERT(uint16_t, int8_t, snorm_to_unorm(src, 8, 16)) + } else { + SWIZZLE_CONVERT(uint16_t, int8_t, (src < 0) ? 0 : src) + } + break; + case GL_UNSIGNED_SHORT: + SWIZZLE_CONVERT(uint16_t, uint16_t, src) + break; + case GL_SHORT: + if (normalized) { + SWIZZLE_CONVERT(uint16_t, int16_t, snorm_to_unorm(src, 16, 16)) + } else { + SWIZZLE_CONVERT(uint16_t, int16_t, (src < 0) ? 0 : src) + } + break; + case GL_UNSIGNED_INT: + if (normalized) { + SWIZZLE_CONVERT(uint16_t, uint32_t, unorm_to_unorm(src, 32, 16)) + } else { + SWIZZLE_CONVERT(uint16_t, uint32_t, src) + } + break; + case GL_INT: + if (normalized) { + SWIZZLE_CONVERT(uint16_t, int32_t, snorm_to_unorm(src, 32, 16)) + } else { + SWIZZLE_CONVERT(uint16_t, int32_t, (src < 0) ? 0 : src) + } + break; + default: + assert(!"Invalid channel type combination"); + } + } + break; + case GL_SHORT: + { + const int16_t one = normalized ? INT16_MAX : 1; + switch (src_type) { + case GL_FLOAT: + if (normalized) { + SWIZZLE_CONVERT(uint16_t, float, float_to_snorm(src, 16)) + } else { + SWIZZLE_CONVERT(uint16_t, float, src) + } + break; + case GL_HALF_FLOAT: + if (normalized) { + SWIZZLE_CONVERT(uint16_t, uint16_t, half_to_snorm(src, 16)) + } else { + SWIZZLE_CONVERT(uint16_t, uint16_t, _mesa_half_to_float(src)) + } + break; + case GL_UNSIGNED_BYTE: + if (normalized) { + SWIZZLE_CONVERT(int16_t, uint8_t, unorm_to_snorm(src, 8, 16)) + } else { + SWIZZLE_CONVERT(int16_t, uint8_t, src) + } + break; + case GL_BYTE: + if (normalized) { + SWIZZLE_CONVERT(int16_t, int8_t, snorm_to_snorm(src, 8, 16)) + } else { + SWIZZLE_CONVERT(int16_t, int8_t, src) + } + break; + case GL_UNSIGNED_SHORT: + if (normalized) { + SWIZZLE_CONVERT(int16_t, uint16_t, unorm_to_snorm(src, 16, 16)) + } else { + SWIZZLE_CONVERT(int16_t, uint16_t, src) + } + break; + case GL_SHORT: + SWIZZLE_CONVERT(int16_t, int16_t, src) + break; + case GL_UNSIGNED_INT: + if (normalized) { + SWIZZLE_CONVERT(int16_t, uint32_t, unorm_to_snorm(src, 32, 16)) + } else { + SWIZZLE_CONVERT(int16_t, uint32_t, src) + } + break; + case GL_INT: + if (normalized) { + SWIZZLE_CONVERT(int16_t, int32_t, snorm_to_snorm(src, 32, 16)) + } else { + SWIZZLE_CONVERT(int16_t, int32_t, src) + } + break; + default: + assert(!"Invalid channel type combination"); + } + } + break; + case GL_UNSIGNED_INT: + { + const uint32_t one = normalized ? UINT32_MAX : 1; + switch (src_type) { case GL_FLOAT: + if (normalized) { + SWIZZLE_CONVERT(uint32_t, float, float_to_unorm(src, 32)) + } else { + SWIZZLE_CONVERT(uint32_t, float, (src < 0) ? 0 : src) + } + break; + case GL_HALF_FLOAT: + if (normalized) { + SWIZZLE_CONVERT(uint32_t, uint16_t, half_to_unorm(src, 32)) + } else { + SWIZZLE_CONVERT(uint32_t, uint16_t, half_to_uint(src)) + } + break; + case GL_UNSIGNED_BYTE: + if (normalized) { + SWIZZLE_CONVERT(uint32_t, uint8_t, unorm_to_unorm(src, 8, 32)) + } else { + SWIZZLE_CONVERT(uint32_t, uint8_t, src) + } + break; + case GL_BYTE: + if (normalized) { + SWIZZLE_CONVERT(uint32_t, int8_t, snorm_to_unorm(src, 8, 32)) + } else { + SWIZZLE_CONVERT(uint32_t, int8_t, (src < 0) ? 0 : src) + } + break; + case GL_UNSIGNED_SHORT: + if (normalized) { + SWIZZLE_CONVERT(uint32_t, uint16_t, unorm_to_unorm(src, 16, 32)) + } else { + SWIZZLE_CONVERT(uint32_t, uint16_t, src) + } + break; + case GL_SHORT: + if (normalized) { + SWIZZLE_CONVERT(uint32_t, int16_t, snorm_to_unorm(src, 16, 32)) + } else { + SWIZZLE_CONVERT(uint32_t, int16_t, (src < 0) ? 0 : src) + } + break; + case GL_UNSIGNED_INT: + SWIZZLE_CONVERT(uint32_t, uint32_t, src) + break; + case GL_INT: + if (normalized) { + SWIZZLE_CONVERT(uint32_t, int32_t, snorm_to_unorm(src, 32, 32)) + } else { + SWIZZLE_CONVERT(uint32_t, int32_t, (src < 0) ? 0 : src) + } + break; + default: + assert(!"Invalid channel type combination"); + } + } + break; + case GL_INT: + { + const int32_t one = normalized ? INT32_MAX : 1; + switch (src_type) { + case GL_FLOAT: + if (normalized) { + SWIZZLE_CONVERT(uint32_t, float, float_to_snorm(src, 32)) + } else { + SWIZZLE_CONVERT(uint32_t, float, src) + } + break; + case GL_HALF_FLOAT: + if (normalized) { + SWIZZLE_CONVERT(uint32_t, uint16_t, half_to_snorm(src, 32)) + } else { + SWIZZLE_CONVERT(uint32_t, uint16_t, _mesa_half_to_float(src)) + } + break; + case GL_UNSIGNED_BYTE: + if (normalized) { + SWIZZLE_CONVERT(int32_t, uint8_t, unorm_to_snorm(src, 8, 32)) + } else { + SWIZZLE_CONVERT(int32_t, uint8_t, src) + } + break; + case GL_BYTE: + if (normalized) { + SWIZZLE_CONVERT(int32_t, int8_t, snorm_to_snorm(src, 8, 32)) + } else { + SWIZZLE_CONVERT(int32_t, int8_t, src) + } + break; + case GL_UNSIGNED_SHORT: + if (normalized) { + SWIZZLE_CONVERT(int32_t, uint16_t, unorm_to_snorm(src, 16, 32)) + } else { + SWIZZLE_CONVERT(int32_t, uint16_t, src) + } + break; + case GL_SHORT: + if (normalized) { + SWIZZLE_CONVERT(int32_t, int16_t, snorm_to_snorm(src, 16, 32)) + } else { + SWIZZLE_CONVERT(int32_t, int16_t, src) + } + break; + case GL_UNSIGNED_INT: + if (normalized) { + SWIZZLE_CONVERT(int32_t, uint32_t, unorm_to_snorm(src, 32, 32)) + } else { + SWIZZLE_CONVERT(int32_t, uint32_t, src) + } + break; + case GL_INT: + SWIZZLE_CONVERT(int32_t, int32_t, src) + break; + default: + assert(!"Invalid channel type combination"); + } + } + break; + default: + assert(!"Invalid channel type"); + } +} diff --git a/mesalib/src/mesa/main/format_utils.h b/mesalib/src/mesa/main/format_utils.h new file mode 100644 index 000000000..9f778e377 --- /dev/null +++ b/mesalib/src/mesa/main/format_utils.h @@ -0,0 +1,45 @@ +/** + * \file format_utils.h + * A collection of format conversion utility functions. + */ + +/* + * Mesa 3-D graphics library + * + * Copyright (C) 1999-2006 Brian Paul All Rights Reserved. + * Copyright (C) 2014 Intel Corporation All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included + * in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + */ + +#ifndef FORMAT_UTILS_H +#define FORMAT_UTILS_H + +#include "imports.h" + +bool +_mesa_format_to_array(mesa_format, GLenum *type, int *num_components, + uint8_t swizzle[4], bool *normalized); + +void +_mesa_swizzle_and_convert(void *dst, GLenum dst_type, int num_dst_channels, + const void *src, GLenum src_type, int num_src_channels, + const uint8_t swizzle[4], bool normalized, int count); + +#endif diff --git a/mesalib/src/mesa/main/formats.c b/mesalib/src/mesa/main/formats.c index 1f20a9a6a..f03425e41 100644 --- a/mesalib/src/mesa/main/formats.c +++ b/mesalib/src/mesa/main/formats.c @@ -40,6 +40,8 @@ struct gl_format_info /** text name for debugging */ const char *StrName; + enum mesa_format_layout Layout; + /** * Base format is one of GL_RED, GL_RG, GL_RGB, GL_RGBA, GL_ALPHA, * GL_LUMINANCE, GL_LUMINANCE_ALPHA, GL_INTENSITY, GL_YCBCR_MESA, @@ -59,7 +61,6 @@ struct gl_format_info GLubyte AlphaBits; GLubyte LuminanceBits; GLubyte IntensityBits; - GLubyte IndexBits; GLubyte DepthBits; GLubyte StencilBits; @@ -68,1745 +69,11 @@ struct gl_format_info */ GLubyte BlockWidth, BlockHeight; GLubyte BytesPerBlock; -}; - -/** - * Info about each format. - * These must be in the same order as the MESA_FORMAT_* enums so that - * we can do lookups without searching. - */ -static struct gl_format_info format_info[MESA_FORMAT_COUNT] = -{ - /* Packed unorm formats */ - { - MESA_FORMAT_NONE, /* Name */ - "MESA_FORMAT_NONE", /* StrName */ - GL_NONE, /* BaseFormat */ - GL_NONE, /* DataType */ - 0, 0, 0, 0, /* Red/Green/Blue/AlphaBits */ - 0, 0, 0, 0, 0, /* Lum/Int/Index/Depth/StencilBits */ - 0, 0, 0 /* BlockWidth/Height,Bytes */ - }, - { - MESA_FORMAT_A8B8G8R8_UNORM, /* Name */ - "MESA_FORMAT_A8B8G8R8_UNORM",/* StrName */ - GL_RGBA, /* BaseFormat */ - GL_UNSIGNED_NORMALIZED, /* DataType */ - 8, 8, 8, 8, /* Red/Green/Blue/AlphaBits */ - 0, 0, 0, 0, 0, /* Lum/Int/Index/Depth/StencilBits */ - 1, 1, 4 /* BlockWidth/Height,Bytes */ - }, - { - MESA_FORMAT_X8B8G8R8_UNORM, /* Name */ - "MESA_FORMAT_X8B8G8R8_UNORM",/* StrName */ - GL_RGB, /* BaseFormat */ - GL_UNSIGNED_NORMALIZED, /* DataType */ - 8, 8, 8, 0, /* Red/Green/Blue/AlphaBits */ - 0, 0, 0, 0, 0, /* Lum/Int/Index/Depth/StencilBits */ - 1, 1, 4 /* BlockWidth/Height,Bytes */ - }, - { - MESA_FORMAT_R8G8B8A8_UNORM, /* Name */ - "MESA_FORMAT_R8G8B8A8_UNORM",/* StrName */ - GL_RGBA, /* BaseFormat */ - GL_UNSIGNED_NORMALIZED, /* DataType */ - 8, 8, 8, 8, /* Red/Green/Blue/AlphaBits */ - 0, 0, 0, 0, 0, /* Lum/Int/Index/Depth/StencilBits */ - 1, 1, 4 /* BlockWidth/Height,Bytes */ - }, - { - MESA_FORMAT_R8G8B8X8_UNORM, /* Name */ - "MESA_FORMAT_R8G8B8X8_UNORM",/* StrName */ - GL_RGB, /* BaseFormat */ - GL_UNSIGNED_NORMALIZED, /* DataType */ - 8, 8, 8, 0, /* Red/Green/Blue/AlphaBits */ - 0, 0, 0, 0, 0, /* Lum/Int/Index/Depth/StencilBits */ - 1, 1, 4 /* BlockWidth/Height,Bytes */ - }, - { - MESA_FORMAT_B8G8R8A8_UNORM, /* Name */ - "MESA_FORMAT_B8G8R8A8_UNORM",/* StrName */ - GL_RGBA, /* BaseFormat */ - GL_UNSIGNED_NORMALIZED, /* DataType */ - 8, 8, 8, 8, /* Red/Green/Blue/AlphaBits */ - 0, 0, 0, 0, 0, /* Lum/Int/Index/Depth/StencilBits */ - 1, 1, 4 /* BlockWidth/Height,Bytes */ - }, - { - MESA_FORMAT_B8G8R8X8_UNORM, /* Name */ - "MESA_FORMAT_B8G8R8X8_UNORM",/* StrName */ - GL_RGB, /* BaseFormat */ - GL_UNSIGNED_NORMALIZED, /* DataType */ - 8, 8, 8, 0, /* Red/Green/Blue/AlphaBits */ - 0, 0, 0, 0, 0, /* Lum/Int/Index/Depth/StencilBits */ - 1, 1, 4 /* BlockWidth/Height,Bytes */ - }, - { - MESA_FORMAT_A8R8G8B8_UNORM, /* Name */ - "MESA_FORMAT_A8R8G8B8_UNORM",/* StrName */ - GL_RGBA, /* BaseFormat */ - GL_UNSIGNED_NORMALIZED, /* DataType */ - 8, 8, 8, 8, /* Red/Green/Blue/AlphaBits */ - 0, 0, 0, 0, 0, /* Lum/Int/Index/Depth/StencilBits */ - 1, 1, 4 /* BlockWidth/Height,Bytes */ - }, - { - MESA_FORMAT_X8R8G8B8_UNORM, /* Name */ - "MESA_FORMAT_X8R8G8B8_UNORM",/* StrName */ - GL_RGB, /* BaseFormat */ - GL_UNSIGNED_NORMALIZED, /* DataType */ - 8, 8, 8, 0, /* Red/Green/Blue/AlphaBits */ - 0, 0, 0, 0, 0, /* Lum/Int/Index/Depth/StencilBits */ - 1, 1, 4 /* BlockWidth/Height,Bytes */ - }, - { - MESA_FORMAT_L16A16_UNORM, /* Name */ - "MESA_FORMAT_L16A16_UNORM", /* StrName */ - GL_LUMINANCE_ALPHA, /* BaseFormat */ - GL_UNSIGNED_NORMALIZED, /* DataType */ - 0, 0, 0, 16, /* Red/Green/Blue/AlphaBits */ - 16, 0, 0, 0, 0, /* Lum/Int/Index/Depth/StencilBits */ - 1, 1, 4 /* BlockWidth/Height,Bytes */ - }, - { - MESA_FORMAT_A16L16_UNORM, /* Name */ - "MESA_FORMAT_A16L16_UNORM", /* StrName */ - GL_LUMINANCE_ALPHA, /* BaseFormat */ - GL_UNSIGNED_NORMALIZED, /* DataType */ - 0, 0, 0, 16, /* Red/Green/Blue/AlphaBits */ - 16, 0, 0, 0, 0, /* Lum/Int/Index/Depth/StencilBits */ - 1, 1, 4 /* BlockWidth/Height,Bytes */ - }, - { - MESA_FORMAT_B5G6R5_UNORM, /* Name */ - "MESA_FORMAT_B5G6R5_UNORM", /* StrName */ - GL_RGB, /* BaseFormat */ - GL_UNSIGNED_NORMALIZED, /* DataType */ - 5, 6, 5, 0, /* Red/Green/Blue/AlphaBits */ - 0, 0, 0, 0, 0, /* Lum/Int/Index/Depth/StencilBits */ - 1, 1, 2 /* BlockWidth/Height,Bytes */ - }, - { - MESA_FORMAT_R5G6B5_UNORM, /* Name */ - "MESA_FORMAT_R5G6B5_UNORM", /* StrName */ - GL_RGB, /* BaseFormat */ - GL_UNSIGNED_NORMALIZED, /* DataType */ - 5, 6, 5, 0, /* Red/Green/Blue/AlphaBits */ - 0, 0, 0, 0, 0, /* Lum/Int/Index/Depth/StencilBits */ - 1, 1, 2 /* BlockWidth/Height,Bytes */ - }, - { - MESA_FORMAT_B4G4R4A4_UNORM, /* Name */ - "MESA_FORMAT_B4G4R4A4_UNORM",/* StrName */ - GL_RGBA, /* BaseFormat */ - GL_UNSIGNED_NORMALIZED, /* DataType */ - 4, 4, 4, 4, /* Red/Green/Blue/AlphaBits */ - 0, 0, 0, 0, 0, /* Lum/Int/Index/Depth/StencilBits */ - 1, 1, 2 /* BlockWidth/Height,Bytes */ - }, - { - MESA_FORMAT_B4G4R4X4_UNORM, - "MESA_FORMAT_B4G4R4X4_UNORM", - GL_RGB, - GL_UNSIGNED_NORMALIZED, - 4, 4, 4, 0, - 0, 0, 0, 0, 0, - 1, 1, 2 - }, - { - MESA_FORMAT_A4R4G4B4_UNORM, /* Name */ - "MESA_FORMAT_A4R4G4B4_UNORM",/* StrName */ - GL_RGBA, /* BaseFormat */ - GL_UNSIGNED_NORMALIZED, /* DataType */ - 4, 4, 4, 4, /* Red/Green/Blue/AlphaBits */ - 0, 0, 0, 0, 0, /* Lum/Int/Index/Depth/StencilBits */ - 1, 1, 2 /* BlockWidth/Height,Bytes */ - }, - { - MESA_FORMAT_A1B5G5R5_UNORM, /* Name */ - "MESA_FORMAT_A1B5G5R5_UNORM",/* StrName */ - GL_RGBA, /* BaseFormat */ - GL_UNSIGNED_NORMALIZED, /* DataType */ - 5, 5, 5, 1, /* Red/Green/Blue/AlphaBits */ - 0, 0, 0, 0, 0, /* Lum/Int/Index/Depth/StencilBits */ - 1, 1, 2 /* BlockWidth/Height,Bytes */ - }, - { - MESA_FORMAT_B5G5R5A1_UNORM, /* Name */ - "MESA_FORMAT_B5G5R5A1_UNORM",/* StrName */ - GL_RGBA, /* BaseFormat */ - GL_UNSIGNED_NORMALIZED, /* DataType */ - 5, 5, 5, 1, /* Red/Green/Blue/AlphaBits */ - 0, 0, 0, 0, 0, /* Lum/Int/Index/Depth/StencilBits */ - 1, 1, 2 /* BlockWidth/Height,Bytes */ - }, - { - MESA_FORMAT_B5G5R5X1_UNORM, - "MESA_FORMAT_B5G5R5X1_UNORM", - GL_RGB, - GL_UNSIGNED_NORMALIZED, - 5, 5, 5, 0, - 0, 0, 0, 0, 0, - 1, 1, 2 - }, - { - MESA_FORMAT_A1R5G5B5_UNORM, /* Name */ - "MESA_FORMAT_A1R5G5B5_UNORM",/* StrName */ - GL_RGBA, /* BaseFormat */ - GL_UNSIGNED_NORMALIZED, /* DataType */ - 5, 5, 5, 1, /* Red/Green/Blue/AlphaBits */ - 0, 0, 0, 0, 0, /* Lum/Int/Index/Depth/StencilBits */ - 1, 1, 2 /* BlockWidth/Height,Bytes */ - }, - { - MESA_FORMAT_L8A8_UNORM, /* Name */ - "MESA_FORMAT_L8A8_UNORM", /* StrName */ - GL_LUMINANCE_ALPHA, /* BaseFormat */ - GL_UNSIGNED_NORMALIZED, /* DataType */ - 0, 0, 0, 8, /* Red/Green/Blue/AlphaBits */ - 8, 0, 0, 0, 0, /* Lum/Int/Index/Depth/StencilBits */ - 1, 1, 2 /* BlockWidth/Height,Bytes */ - }, - { - MESA_FORMAT_A8L8_UNORM, /* Name */ - "MESA_FORMAT_A8L8_UNORM", /* StrName */ - GL_LUMINANCE_ALPHA, /* BaseFormat */ - GL_UNSIGNED_NORMALIZED, /* DataType */ - 0, 0, 0, 8, /* Red/Green/Blue/AlphaBits */ - 8, 0, 0, 0, 0, /* Lum/Int/Index/Depth/StencilBits */ - 1, 1, 2 /* BlockWidth/Height,Bytes */ - }, - { - MESA_FORMAT_R8G8_UNORM, - "MESA_FORMAT_R8G8_UNORM", - GL_RG, - GL_UNSIGNED_NORMALIZED, - 8, 8, 0, 0, - 0, 0, 0, 0, 0, - 1, 1, 2 - }, - { - MESA_FORMAT_G8R8_UNORM, - "MESA_FORMAT_G8R8_UNORM", - GL_RG, - GL_UNSIGNED_NORMALIZED, - 8, 8, 0, 0, - 0, 0, 0, 0, 0, - 1, 1, 2 - }, - { - MESA_FORMAT_L4A4_UNORM, /* Name */ - "MESA_FORMAT_L4A4_UNORM", /* StrName */ - GL_LUMINANCE_ALPHA, /* BaseFormat */ - GL_UNSIGNED_NORMALIZED, /* DataType */ - 0, 0, 0, 4, /* Red/Green/Blue/AlphaBits */ - 4, 0, 0, 0, 0, /* Lum/Int/Index/Depth/StencilBits */ - 1, 1, 1 /* BlockWidth/Height,Bytes */ - }, - { - MESA_FORMAT_B2G3R3_UNORM, /* Name */ - "MESA_FORMAT_B2G3R3_UNORM", /* StrName */ - GL_RGB, /* BaseFormat */ - GL_UNSIGNED_NORMALIZED, /* DataType */ - 3, 3, 2, 0, /* Red/Green/Blue/AlphaBits */ - 0, 0, 0, 0, 0, /* Lum/Int/Index/Depth/StencilBits */ - 1, 1, 1 /* BlockWidth/Height,Bytes */ - }, - { - MESA_FORMAT_R16G16_UNORM, - "MESA_FORMAT_R16G16_UNORM", - GL_RG, - GL_UNSIGNED_NORMALIZED, - 16, 16, 0, 0, - 0, 0, 0, 0, 0, - 1, 1, 4 - }, - { - MESA_FORMAT_G16R16_UNORM, - "MESA_FORMAT_G16R16_UNORM", - GL_RG, - GL_UNSIGNED_NORMALIZED, - 16, 16, 0, 0, - 0, 0, 0, 0, 0, - 1, 1, 4 - }, - { - MESA_FORMAT_B10G10R10A2_UNORM, - "MESA_FORMAT_B10G10R10A2_UNORM", - GL_RGBA, - GL_UNSIGNED_NORMALIZED, - 10, 10, 10, 2, - 0, 0, 0, 0, 0, - 1, 1, 4 - }, - { - MESA_FORMAT_B10G10R10X2_UNORM, - "MESA_FORMAT_B10G10R10X2_UNORM", - GL_RGB, - GL_UNSIGNED_NORMALIZED, - 10, 10, 10, 0, - 0, 0, 0, 0, 0, - 1, 1, 4 - }, - { - MESA_FORMAT_R10G10B10A2_UNORM, - "MESA_FORMAT_R10G10B10A2_UNORM", - GL_RGBA, - GL_UNSIGNED_NORMALIZED, - 10, 10, 10, 2, - 0, 0, 0, 0, 0, - 1, 1, 4 - }, - { - MESA_FORMAT_S8_UINT_Z24_UNORM, /* Name */ - "MESA_FORMAT_S8_UINT_Z24_UNORM", /* StrName */ - GL_DEPTH_STENCIL, /* BaseFormat */ - GL_UNSIGNED_NORMALIZED, /* DataType */ - 0, 0, 0, 0, /* Red/Green/Blue/AlphaBits */ - 0, 0, 0, 24, 8, /* Lum/Int/Index/Depth/StencilBits */ - 1, 1, 4 /* BlockWidth/Height,Bytes */ - }, - { - MESA_FORMAT_X8_UINT_Z24_UNORM, /* Name */ - "MESA_FORMAT_X8_UINT_Z24_UNORM", /* StrName */ - GL_DEPTH_COMPONENT, /* BaseFormat */ - GL_UNSIGNED_NORMALIZED, /* DataType */ - 0, 0, 0, 0, /* Red/Green/Blue/AlphaBits */ - 0, 0, 0, 24, 0, /* Lum/Int/Index/Depth/StencilBits */ - 1, 1, 4 /* BlockWidth/Height,Bytes */ - }, - { - MESA_FORMAT_Z24_UNORM_S8_UINT, /* Name */ - "MESA_FORMAT_Z24_UNORM_S8_UINT", /* StrName */ - GL_DEPTH_STENCIL, /* BaseFormat */ - GL_UNSIGNED_NORMALIZED, /* DataType */ - 0, 0, 0, 0, /* Red/Green/Blue/AlphaBits */ - 0, 0, 0, 24, 8, /* Lum/Int/Index/Depth/StencilBits */ - 1, 1, 4 /* BlockWidth/Height,Bytes */ - }, - { - MESA_FORMAT_Z24_UNORM_X8_UINT, /* Name */ - "MESA_FORMAT_Z24_UNORM_X8_UINT", /* StrName */ - GL_DEPTH_COMPONENT, /* BaseFormat */ - GL_UNSIGNED_NORMALIZED, /* DataType */ - 0, 0, 0, 0, /* Red/Green/Blue/AlphaBits */ - 0, 0, 0, 24, 0, /* Lum/Int/Index/Depth/StencilBits */ - 1, 1, 4 /* BlockWidth/Height,Bytes */ - }, - { - MESA_FORMAT_YCBCR, /* Name */ - "MESA_FORMAT_YCBCR", /* StrName */ - GL_YCBCR_MESA, /* BaseFormat */ - GL_UNSIGNED_NORMALIZED, /* DataType */ - 0, 0, 0, 0, /* Red/Green/Blue/AlphaBits */ - 0, 0, 0, 0, 0, /* Lum/Int/Index/Depth/StencilBits */ - 1, 1, 2 /* BlockWidth/Height,Bytes */ - }, - { - MESA_FORMAT_YCBCR_REV, /* Name */ - "MESA_FORMAT_YCBCR_REV", /* StrName */ - GL_YCBCR_MESA, /* BaseFormat */ - GL_UNSIGNED_NORMALIZED, /* DataType */ - 0, 0, 0, 0, /* Red/Green/Blue/AlphaBits */ - 0, 0, 0, 0, 0, /* Lum/Int/Index/Depth/StencilBits */ - 1, 1, 2 /* BlockWidth/Height,Bytes */ - }, - - /* Array unorm formats */ - { - MESA_FORMAT_A_UNORM8, /* Name */ - "MESA_FORMAT_A_UNORM8", /* StrName */ - GL_ALPHA, /* BaseFormat */ - GL_UNSIGNED_NORMALIZED, /* DataType */ - 0, 0, 0, 8, /* Red/Green/Blue/AlphaBits */ - 0, 0, 0, 0, 0, /* Lum/Int/Index/Depth/StencilBits */ - 1, 1, 1 /* BlockWidth/Height,Bytes */ - }, - { - MESA_FORMAT_A_UNORM16, /* Name */ - "MESA_FORMAT_A_UNORM16", /* StrName */ - GL_ALPHA, /* BaseFormat */ - GL_UNSIGNED_NORMALIZED, /* DataType */ - 0, 0, 0, 16, /* Red/Green/Blue/AlphaBits */ - 0, 0, 0, 0, 0, /* Lum/Int/Index/Depth/StencilBits */ - 1, 1, 2 /* BlockWidth/Height,Bytes */ - }, - { - MESA_FORMAT_L_UNORM8, /* Name */ - "MESA_FORMAT_L_UNORM8", /* StrName */ - GL_LUMINANCE, /* BaseFormat */ - GL_UNSIGNED_NORMALIZED, /* DataType */ - 0, 0, 0, 0, /* Red/Green/Blue/AlphaBits */ - 8, 0, 0, 0, 0, /* Lum/Int/Index/Depth/StencilBits */ - 1, 1, 1 /* BlockWidth/Height,Bytes */ - }, - { - MESA_FORMAT_L_UNORM16, /* Name */ - "MESA_FORMAT_L_UNORM16", /* StrName */ - GL_LUMINANCE, /* BaseFormat */ - GL_UNSIGNED_NORMALIZED, /* DataType */ - 0, 0, 0, 0, /* Red/Green/Blue/AlphaBits */ - 16, 0, 0, 0, 0, /* Lum/Int/Index/Depth/StencilBits */ - 1, 1, 2 /* BlockWidth/Height,Bytes */ - }, - { - MESA_FORMAT_I_UNORM8, /* Name */ - "MESA_FORMAT_I_UNORM8", /* StrName */ - GL_INTENSITY, /* BaseFormat */ - GL_UNSIGNED_NORMALIZED, /* DataType */ - 0, 0, 0, 0, /* Red/Green/Blue/AlphaBits */ - 0, 8, 0, 0, 0, /* Lum/Int/Index/Depth/StencilBits */ - 1, 1, 1 /* BlockWidth/Height,Bytes */ - }, - { - MESA_FORMAT_I_UNORM16, /* Name */ - "MESA_FORMAT_I_UNORM16", /* StrName */ - GL_INTENSITY, /* BaseFormat */ - GL_UNSIGNED_NORMALIZED, /* DataType */ - 0, 0, 0, 0, /* Red/Green/Blue/AlphaBits */ - 0, 16, 0, 0, 0, /* Lum/Int/Index/Depth/StencilBits */ - 1, 1, 2 /* BlockWidth/Height,Bytes */ - }, - { - MESA_FORMAT_R_UNORM8, - "MESA_FORMAT_R_UNORM8", - GL_RED, - GL_UNSIGNED_NORMALIZED, - 8, 0, 0, 0, - 0, 0, 0, 0, 0, - 1, 1, 1 - }, - { - MESA_FORMAT_R_UNORM16, - "MESA_FORMAT_R_UNORM16", - GL_RED, - GL_UNSIGNED_NORMALIZED, - 16, 0, 0, 0, - 0, 0, 0, 0, 0, - 1, 1, 2 - }, - { - MESA_FORMAT_BGR_UNORM8, /* Name */ - "MESA_FORMAT_BGR_UNORM8", /* StrName */ - GL_RGB, /* BaseFormat */ - GL_UNSIGNED_NORMALIZED, /* DataType */ - 8, 8, 8, 0, /* Red/Green/Blue/AlphaBits */ - 0, 0, 0, 0, 0, /* Lum/Int/Index/Depth/StencilBits */ - 1, 1, 3 /* BlockWidth/Height,Bytes */ - }, - { - MESA_FORMAT_RGB_UNORM8, /* Name */ - "MESA_FORMAT_RGB_UNORM8", /* StrName */ - GL_RGB, /* BaseFormat */ - GL_UNSIGNED_NORMALIZED, /* DataType */ - 8, 8, 8, 0, /* Red/Green/Blue/AlphaBits */ - 0, 0, 0, 0, 0, /* Lum/Int/Index/Depth/StencilBits */ - 1, 1, 3 /* BlockWidth/Height,Bytes */ - }, - { - MESA_FORMAT_RGBA_UNORM16, - "MESA_FORMAT_RGBA_UNORM16", - GL_RGBA, - GL_UNSIGNED_NORMALIZED, - 16, 16, 16, 16, - 0, 0, 0, 0, 0, - 1, 1, 8 - }, - { - MESA_FORMAT_RGBX_UNORM16, - "MESA_FORMAT_RGBX_UNORM16", - GL_RGB, - GL_UNSIGNED_NORMALIZED, - 16, 16, 16, 0, - 0, 0, 0, 0, 0, - 1, 1, 8 - }, - { - MESA_FORMAT_Z_UNORM16, /* Name */ - "MESA_FORMAT_Z_UNORM16", /* StrName */ - GL_DEPTH_COMPONENT, /* BaseFormat */ - GL_UNSIGNED_NORMALIZED, /* DataType */ - 0, 0, 0, 0, /* Red/Green/Blue/AlphaBits */ - 0, 0, 0, 16, 0, /* Lum/Int/Index/Depth/StencilBits */ - 1, 1, 2 /* BlockWidth/Height,Bytes */ - }, - { - MESA_FORMAT_Z_UNORM32, /* Name */ - "MESA_FORMAT_Z_UNORM32", /* StrName */ - GL_DEPTH_COMPONENT, /* BaseFormat */ - GL_UNSIGNED_NORMALIZED, /* DataType */ - 0, 0, 0, 0, /* Red/Green/Blue/AlphaBits */ - 0, 0, 0, 32, 0, /* Lum/Int/Index/Depth/StencilBits */ - 1, 1, 4 /* BlockWidth/Height,Bytes */ - }, - { - MESA_FORMAT_S_UINT8, /* Name */ - "MESA_FORMAT_S_UINT8", /* StrName */ - GL_STENCIL_INDEX, /* BaseFormat */ - GL_UNSIGNED_INT, /* DataType */ - 0, 0, 0, 0, /* Red/Green/Blue/AlphaBits */ - 0, 0, 0, 0, 8, /* Lum/Int/Index/Depth/StencilBits */ - 1, 1, 1 /* BlockWidth/Height,Bytes */ - }, - - /* Packed signed/normalized formats */ - { - MESA_FORMAT_A8B8G8R8_SNORM, - "MESA_FORMAT_A8B8G8R8_SNORM", - GL_RGBA, - GL_SIGNED_NORMALIZED, - 8, 8, 8, 8, - 0, 0, 0, 0, 0, - 1, 1, 4 - }, - { - MESA_FORMAT_X8B8G8R8_SNORM, - "MESA_FORMAT_X8B8G8R8_SNORM", - GL_RGB, - GL_SIGNED_NORMALIZED, - 8, 8, 8, 0, - 0, 0, 0, 0, 0, - 1, 1, 4 /* 4 bpp, but no alpha */ - }, - { - MESA_FORMAT_R8G8B8A8_SNORM, - "MESA_FORMAT_R8G8B8A8_SNORM", - GL_RGBA, - GL_SIGNED_NORMALIZED, - 8, 8, 8, 8, - 0, 0, 0, 0, 0, - 1, 1, 4 - }, - { - MESA_FORMAT_R8G8B8X8_SNORM, - "MESA_FORMAT_R8G8B8X8_SNORM", - GL_RGB, - GL_SIGNED_NORMALIZED, - 8, 8, 8, 0, - 0, 0, 0, 0, 0, - 1, 1, 4 - }, - { - MESA_FORMAT_R16G16_SNORM, - "MESA_FORMAT_R16G16_SNORM", - GL_RG, - GL_SIGNED_NORMALIZED, - 16, 16, 0, 0, - 0, 0, 0, 0, 0, - 1, 1, 4 - }, - { - MESA_FORMAT_G16R16_SNORM, - "MESA_FORMAT_G16R16_SNORM", - GL_RG, - GL_SIGNED_NORMALIZED, - 16, 16, 0, 0, - 0, 0, 0, 0, 0, - 1, 1, 4 - }, - { - MESA_FORMAT_R8G8_SNORM, - "MESA_FORMAT_R8G8_SNORM", - GL_RG, - GL_SIGNED_NORMALIZED, - 8, 8, 0, 0, - 0, 0, 0, 0, 0, - 1, 1, 2 - }, - { - MESA_FORMAT_G8R8_SNORM, - "MESA_FORMAT_G8R8_SNORM", - GL_RG, - GL_SIGNED_NORMALIZED, - 8, 8, 0, 0, - 0, 0, 0, 0, 0, - 1, 1, 2 - }, - { - MESA_FORMAT_L8A8_SNORM, - "MESA_FORMAT_L8A8_SNORM", - GL_LUMINANCE_ALPHA, - GL_SIGNED_NORMALIZED, - 0, 0, 0, 8, - 8, 0, 0, 0, 0, - 1, 1, 2 - }, - - /* Array signed/normalized formats */ - { - MESA_FORMAT_A_SNORM8, - "MESA_FORMAT_A_SNORM8", - GL_ALPHA, - GL_SIGNED_NORMALIZED, - 0, 0, 0, 8, - 0, 0, 0, 0, 0, - 1, 1, 1 - }, - { - MESA_FORMAT_A_SNORM16, - "MESA_FORMAT_A_SNORM16", - GL_ALPHA, - GL_SIGNED_NORMALIZED, - 0, 0, 0, 16, - 0, 0, 0, 0, 0, - 1, 1, 2 - }, - { - MESA_FORMAT_L_SNORM8, - "MESA_FORMAT_L_SNORM8", - GL_LUMINANCE, - GL_SIGNED_NORMALIZED, - 0, 0, 0, 0, - 8, 0, 0, 0, 0, - 1, 1, 1 - }, - { - MESA_FORMAT_L_SNORM16, - "MESA_FORMAT_L_SNORM16", - GL_LUMINANCE, - GL_SIGNED_NORMALIZED, - 0, 0, 0, 0, - 16, 0, 0, 0, 0, - 1, 1, 2 - }, - { - MESA_FORMAT_I_SNORM8, - "MESA_FORMAT_I_SNORM8", - GL_INTENSITY, - GL_SIGNED_NORMALIZED, - 0, 0, 0, 0, - 0, 8, 0, 0, 0, - 1, 1, 1 - }, - { - MESA_FORMAT_I_SNORM16, - "MESA_FORMAT_I_SNORM16", - GL_INTENSITY, - GL_SIGNED_NORMALIZED, - 0, 0, 0, 0, - 0, 16, 0, 0, 0, - 1, 1, 2 - }, - { - MESA_FORMAT_R_SNORM8, /* Name */ - "MESA_FORMAT_R_SNORM8", /* StrName */ - GL_RED, /* BaseFormat */ - GL_SIGNED_NORMALIZED, /* DataType */ - 8, 0, 0, 0, /* Red/Green/Blue/AlphaBits */ - 0, 0, 0, 0, 0, /* Lum/Int/Index/Depth/StencilBits */ - 1, 1, 1 /* BlockWidth/Height,Bytes */ - }, - { - MESA_FORMAT_R_SNORM16, - "MESA_FORMAT_R_SNORM16", - GL_RED, - GL_SIGNED_NORMALIZED, - 16, 0, 0, 0, - 0, 0, 0, 0, 0, - 1, 1, 2 - }, - { - MESA_FORMAT_LA_SNORM16, - "MESA_FORMAT_LA_SNORM16", - GL_LUMINANCE_ALPHA, - GL_SIGNED_NORMALIZED, - 0, 0, 0, 16, - 16, 0, 0, 0, 0, - 1, 1, 4 - }, - { - MESA_FORMAT_RGB_SNORM16, - "MESA_FORMAT_RGB_SNORM16", - GL_RGB, - GL_SIGNED_NORMALIZED, - 16, 16, 16, 0, - 0, 0, 0, 0, 0, - 1, 1, 6 - }, - { - MESA_FORMAT_RGBA_SNORM16, - "MESA_FORMAT_RGBA_SNORM16", - GL_RGBA, - GL_SIGNED_NORMALIZED, - 16, 16, 16, 16, - 0, 0, 0, 0, 0, - 1, 1, 8 - }, - { - MESA_FORMAT_RGBX_SNORM16, - "MESA_FORMAT_RGBX_SNORM16", - GL_RGB, - GL_SIGNED_NORMALIZED, - 16, 16, 16, 0, - 0, 0, 0, 0, 0, - 1, 1, 8 - }, - - /* Packed sRGB formats */ - { - MESA_FORMAT_A8B8G8R8_SRGB, - "MESA_FORMAT_A8B8G8R8_SRGB", - GL_RGBA, - GL_UNSIGNED_NORMALIZED, - 8, 8, 8, 8, - 0, 0, 0, 0, 0, - 1, 1, 4 - }, - { - MESA_FORMAT_B8G8R8A8_SRGB, - "MESA_FORMAT_B8G8R8A8_SRGB", - GL_RGBA, - GL_UNSIGNED_NORMALIZED, - 8, 8, 8, 8, - 0, 0, 0, 0, 0, - 1, 1, 4 - }, - { - MESA_FORMAT_B8G8R8X8_SRGB, - "MESA_FORMAT_B8G8R8X8_SRGB", - GL_RGB, - GL_UNSIGNED_NORMALIZED, - 8, 8, 8, 0, - 0, 0, 0, 0, 0, - 1, 1, 4 - }, - { - MESA_FORMAT_R8G8B8A8_SRGB, - "MESA_FORMAT_R8G8B8A8_SRGB", - GL_RGBA, - GL_UNSIGNED_NORMALIZED, - 8, 8, 8, 8, - 0, 0, 0, 0, 0, - 1, 1, 4 - }, - { - MESA_FORMAT_R8G8B8X8_SRGB, - "MESA_FORMAT_R8G8B8X8_SRGB", - GL_RGB, - GL_UNSIGNED_NORMALIZED, - 8, 8, 8, 0, - 0, 0, 0, 0, 0, - 1, 1, 4 - }, - { - MESA_FORMAT_L8A8_SRGB, - "MESA_FORMAT_L8A8_SRGB", - GL_LUMINANCE_ALPHA, - GL_UNSIGNED_NORMALIZED, - 0, 0, 0, 8, - 8, 0, 0, 0, 0, - 1, 1, 2 - }, - - /* Array sRGB formats */ - { - MESA_FORMAT_L_SRGB8, - "MESA_FORMAT_L_SRGB8", - GL_LUMINANCE, - GL_UNSIGNED_NORMALIZED, - 0, 0, 0, 0, - 8, 0, 0, 0, 0, - 1, 1, 1 - }, - { - MESA_FORMAT_BGR_SRGB8, - "MESA_FORMAT_BGR_SRGB8", - GL_RGB, - GL_UNSIGNED_NORMALIZED, - 8, 8, 8, 0, - 0, 0, 0, 0, 0, - 1, 1, 3 - }, - - /* Packed float formats */ - { - MESA_FORMAT_R9G9B9E5_FLOAT, - "MESA_FORMAT_RGB9_E5", - GL_RGB, - GL_FLOAT, - 9, 9, 9, 0, - 0, 0, 0, 0, 0, - 1, 1, 4 - }, - { - MESA_FORMAT_R11G11B10_FLOAT, - "MESA_FORMAT_R11G11B10_FLOAT", - GL_RGB, - GL_FLOAT, - 11, 11, 10, 0, - 0, 0, 0, 0, 0, - 1, 1, 4 - }, - { - MESA_FORMAT_Z32_FLOAT_S8X24_UINT, /* Name */ - "MESA_FORMAT_Z32_FLOAT_S8X24_UINT", /* StrName */ - GL_DEPTH_STENCIL, /* BaseFormat */ - /* DataType here is used to answer GL_TEXTURE_DEPTH_TYPE queries, and is - * never used for stencil because stencil is always GL_UNSIGNED_INT. - */ - GL_FLOAT, /* DataType */ - 0, 0, 0, 0, /* Red/Green/Blue/AlphaBits */ - 0, 0, 0, 32, 8, /* Lum/Int/Index/Depth/StencilBits */ - 1, 1, 8 /* BlockWidth/Height,Bytes */ - }, - - /* Array float formats */ - { - MESA_FORMAT_A_FLOAT16, - "MESA_FORMAT_A_FLOAT16", - GL_ALPHA, - GL_FLOAT, - 0, 0, 0, 16, - 0, 0, 0, 0, 0, - 1, 1, 2 - }, - { - MESA_FORMAT_A_FLOAT32, - "MESA_FORMAT_A_FLOAT32", - GL_ALPHA, - GL_FLOAT, - 0, 0, 0, 32, - 0, 0, 0, 0, 0, - 1, 1, 4 - }, - { - MESA_FORMAT_L_FLOAT16, - "MESA_FORMAT_L_FLOAT16", - GL_LUMINANCE, - GL_FLOAT, - 0, 0, 0, 0, - 16, 0, 0, 0, 0, - 1, 1, 2 - }, - { - MESA_FORMAT_L_FLOAT32, - "MESA_FORMAT_L_FLOAT32", - GL_LUMINANCE, - GL_FLOAT, - 0, 0, 0, 0, - 32, 0, 0, 0, 0, - 1, 1, 4 - }, - { - MESA_FORMAT_LA_FLOAT16, - "MESA_FORMAT_LA_FLOAT16", - GL_LUMINANCE_ALPHA, - GL_FLOAT, - 0, 0, 0, 16, - 16, 0, 0, 0, 0, - 1, 1, 4 - }, - { - MESA_FORMAT_LA_FLOAT32, - "MESA_FORMAT_LA_FLOAT32", - GL_LUMINANCE_ALPHA, - GL_FLOAT, - 0, 0, 0, 32, - 32, 0, 0, 0, 0, - 1, 1, 8 - }, - { - MESA_FORMAT_I_FLOAT16, - "MESA_FORMAT_I_FLOAT16", - GL_INTENSITY, - GL_FLOAT, - 0, 0, 0, 0, - 0, 16, 0, 0, 0, - 1, 1, 2 - }, - { - MESA_FORMAT_I_FLOAT32, - "MESA_FORMAT_I_FLOAT32", - GL_INTENSITY, - GL_FLOAT, - 0, 0, 0, 0, - 0, 32, 0, 0, 0, - 1, 1, 4 - }, - { - MESA_FORMAT_R_FLOAT16, - "MESA_FORMAT_R_FLOAT16", - GL_RED, - GL_FLOAT, - 16, 0, 0, 0, - 0, 0, 0, 0, 0, - 1, 1, 2 - }, - { - MESA_FORMAT_R_FLOAT32, - "MESA_FORMAT_R_FLOAT32", - GL_RED, - GL_FLOAT, - 32, 0, 0, 0, - 0, 0, 0, 0, 0, - 1, 1, 4 - }, - { - MESA_FORMAT_RG_FLOAT16, - "MESA_FORMAT_RG_FLOAT16", - GL_RG, - GL_FLOAT, - 16, 16, 0, 0, - 0, 0, 0, 0, 0, - 1, 1, 4 - }, - { - MESA_FORMAT_RG_FLOAT32, - "MESA_FORMAT_RG_FLOAT32", - GL_RG, - GL_FLOAT, - 32, 32, 0, 0, - 0, 0, 0, 0, 0, - 1, 1, 8 - }, - { - MESA_FORMAT_RGB_FLOAT16, - "MESA_FORMAT_RGB_FLOAT16", - GL_RGB, - GL_FLOAT, - 16, 16, 16, 0, - 0, 0, 0, 0, 0, - 1, 1, 6 - }, - { - MESA_FORMAT_RGB_FLOAT32, - "MESA_FORMAT_RGB_FLOAT32", - GL_RGB, - GL_FLOAT, - 32, 32, 32, 0, - 0, 0, 0, 0, 0, - 1, 1, 12 - }, - { - MESA_FORMAT_RGBA_FLOAT16, - "MESA_FORMAT_RGBA_FLOAT16", - GL_RGBA, - GL_FLOAT, - 16, 16, 16, 16, - 0, 0, 0, 0, 0, - 1, 1, 8 - }, - { - MESA_FORMAT_RGBA_FLOAT32, - "MESA_FORMAT_RGBA_FLOAT32", - GL_RGBA, - GL_FLOAT, - 32, 32, 32, 32, - 0, 0, 0, 0, 0, - 1, 1, 16 - }, - { - MESA_FORMAT_RGBX_FLOAT16, - "MESA_FORMAT_RGBX_FLOAT16", - GL_RGB, - GL_FLOAT, - 16, 16, 16, 0, - 0, 0, 0, 0, 0, - 1, 1, 8 - }, - { - MESA_FORMAT_RGBX_FLOAT32, - "MESA_FORMAT_RGBX_FLOAT32", - GL_RGB, - GL_FLOAT, - 32, 32, 32, 0, - 0, 0, 0, 0, 0, - 1, 1, 16 - }, - { - MESA_FORMAT_Z_FLOAT32, /* Name */ - "MESA_FORMAT_Z_FLOAT32", /* StrName */ - GL_DEPTH_COMPONENT, /* BaseFormat */ - GL_FLOAT, /* DataType */ - 0, 0, 0, 0, /* Red/Green/Blue/AlphaBits */ - 0, 0, 0, 32, 0, /* Lum/Int/Index/Depth/StencilBits */ - 1, 1, 4 /* BlockWidth/Height,Bytes */ - }, - - /* Packed signed/unsigned non-normalized integer formats */ - { - MESA_FORMAT_B10G10R10A2_UINT, - "MESA_FORMAT_B10G10R10A2_UINT", - GL_RGBA, - GL_UNSIGNED_INT, - 10, 10, 10, 2, - 0, 0, 0, 0, 0, - 1, 1, 4 - }, - { - MESA_FORMAT_R10G10B10A2_UINT, - "MESA_FORMAT_R10G10B10A2_UINT", - GL_RGBA, - GL_UNSIGNED_INT, - 10, 10, 10, 2, - 0, 0, 0, 0, 0, - 1, 1, 4 - }, - - /* Array signed/unsigned non-normalized integer formats */ - { - MESA_FORMAT_A_UINT8, - "MESA_FORMAT_A_UINT8", - GL_ALPHA, - GL_UNSIGNED_INT, - 0, 0, 0, 8, - 0, 0, 0, 0, 0, - 1, 1, 1 - }, - { - MESA_FORMAT_A_UINT16, - "MESA_FORMAT_A_UINT16", - GL_ALPHA, - GL_UNSIGNED_INT, - 0, 0, 0, 16, - 0, 0, 0, 0, 0, - 1, 1, 2 - }, - { - MESA_FORMAT_A_UINT32, - "MESA_FORMAT_A_UINT32", - GL_ALPHA, - GL_UNSIGNED_INT, - 0, 0, 0, 32, - 0, 0, 0, 0, 0, - 1, 1, 4 - }, - { - MESA_FORMAT_A_SINT8, - "MESA_FORMAT_A_SINT8", - GL_ALPHA, - GL_INT, - 0, 0, 0, 8, - 0, 0, 0, 0, 0, - 1, 1, 1 - }, - { - MESA_FORMAT_A_SINT16, - "MESA_FORMAT_A_SINT16", - GL_ALPHA, - GL_INT, - 0, 0, 0, 16, - 0, 0, 0, 0, 0, - 1, 1, 2 - }, - { - MESA_FORMAT_A_SINT32, - "MESA_FORMAT_A_SINT32", - GL_ALPHA, - GL_INT, - 0, 0, 0, 32, - 0, 0, 0, 0, 0, - 1, 1, 4 - }, - { - MESA_FORMAT_I_UINT8, - "MESA_FORMAT_I_UINT8", - GL_INTENSITY, - GL_UNSIGNED_INT, - 0, 0, 0, 0, - 0, 8, 0, 0, 0, - 1, 1, 1 - }, - { - MESA_FORMAT_I_UINT16, - "MESA_FORMAT_I_UINT16", - GL_INTENSITY, - GL_UNSIGNED_INT, - 0, 0, 0, 0, - 0, 16, 0, 0, 0, - 1, 1, 2 - }, - { - MESA_FORMAT_I_UINT32, - "MESA_FORMAT_I_UINT32", - GL_INTENSITY, - GL_UNSIGNED_INT, - 0, 0, 0, 0, - 0, 32, 0, 0, 0, - 1, 1, 4 - }, - { - MESA_FORMAT_I_SINT8, - "MESA_FORMAT_I_SINT8", - GL_INTENSITY, - GL_INT, - 0, 0, 0, 0, - 0, 8, 0, 0, 0, - 1, 1, 1 - }, - { - MESA_FORMAT_I_SINT16, - "MESA_FORMAT_I_SINT16", - GL_INTENSITY, - GL_INT, - 0, 0, 0, 0, - 0, 16, 0, 0, 0, - 1, 1, 2 - }, - { - MESA_FORMAT_I_SINT32, - "MESA_FORMAT_I_SINT32", - GL_INTENSITY, - GL_INT, - 0, 0, 0, 0, - 0, 32, 0, 0, 0, - 1, 1, 4 - }, - { - MESA_FORMAT_L_UINT8, - "MESA_FORMAT_L_UINT8", - GL_LUMINANCE, - GL_UNSIGNED_INT, - 0, 0, 0, 0, - 8, 0, 0, 0, 0, - 1, 1, 1 - }, - { - MESA_FORMAT_L_UINT16, - "MESA_FORMAT_L_UINT16", - GL_LUMINANCE, - GL_UNSIGNED_INT, - 0, 0, 0, 0, - 16, 0, 0, 0, 0, - 1, 1, 2 - }, - { - MESA_FORMAT_L_UINT32, - "MESA_FORMAT_L_UINT32", - GL_LUMINANCE, - GL_UNSIGNED_INT, - 0, 0, 0, 0, - 32, 0, 0, 0, 0, - 1, 1, 4 - }, - { - MESA_FORMAT_L_SINT8, - "MESA_FORMAT_L_SINT8", - GL_LUMINANCE, - GL_INT, - 0, 0, 0, 0, - 8, 0, 0, 0, 0, - 1, 1, 1 - }, - { - MESA_FORMAT_L_SINT16, - "MESA_FORMAT_L_SINT16", - GL_LUMINANCE, - GL_INT, - 0, 0, 0, 0, - 16, 0, 0, 0, 0, - 1, 1, 2 - }, - { - MESA_FORMAT_L_SINT32, - "MESA_FORMAT_L_SINT32", - GL_LUMINANCE, - GL_INT, - 0, 0, 0, 0, - 32, 0, 0, 0, 0, - 1, 1, 4 - }, - { - MESA_FORMAT_LA_UINT8, - "MESA_FORMAT_LA_UINT8", - GL_LUMINANCE_ALPHA, - GL_UNSIGNED_INT, - 0, 0, 0, 8, - 8, 0, 0, 0, 0, - 1, 1, 2 - }, - { - MESA_FORMAT_LA_UINT16, - "MESA_FORMAT_LA_UINT16", - GL_LUMINANCE_ALPHA, - GL_UNSIGNED_INT, - 0, 0, 0, 16, - 16, 0, 0, 0, 0, - 1, 1, 4 - }, - { - MESA_FORMAT_LA_UINT32, - "MESA_FORMAT_LA_UINT32", - GL_LUMINANCE_ALPHA, - GL_UNSIGNED_INT, - 0, 0, 0, 32, - 32, 0, 0, 0, 0, - 1, 1, 8 - }, - { - MESA_FORMAT_LA_SINT8, - "MESA_FORMAT_LA_SINT8", - GL_LUMINANCE_ALPHA, - GL_INT, - 0, 0, 0, 8, - 8, 0, 0, 0, 0, - 1, 1, 2 - }, - { - MESA_FORMAT_LA_SINT16, - "MESA_FORMAT_LA_SINT16", - GL_LUMINANCE_ALPHA, - GL_INT, - 0, 0, 0, 16, - 16, 0, 0, 0, 0, - 1, 1, 4 - }, - { - MESA_FORMAT_LA_SINT32, - "MESA_FORMAT_LA_SINT32", - GL_LUMINANCE_ALPHA, - GL_INT, - 0, 0, 0, 32, - 32, 0, 0, 0, 0, - 1, 1, 8 - }, - { - MESA_FORMAT_R_UINT8, - "MESA_FORMAT_R_UINT8", - GL_RED, - GL_UNSIGNED_INT, - 8, 0, 0, 0, - 0, 0, 0, 0, 0, - 1, 1, 1 - }, - { - MESA_FORMAT_R_UINT16, - "MESA_FORMAT_R_UINT16", - GL_RED, - GL_UNSIGNED_INT, - 16, 0, 0, 0, - 0, 0, 0, 0, 0, - 1, 1, 2 - }, - { - MESA_FORMAT_R_UINT32, - "MESA_FORMAT_R_UINT32", - GL_RED, - GL_UNSIGNED_INT, - 32, 0, 0, 0, - 0, 0, 0, 0, 0, - 1, 1, 4 - }, - { - MESA_FORMAT_R_SINT8, - "MESA_FORMAT_R_SINT8", - GL_RED, - GL_INT, - 8, 0, 0, 0, - 0, 0, 0, 0, 0, - 1, 1, 1 - }, - { - MESA_FORMAT_R_SINT16, - "MESA_FORMAT_R_SINT16", - GL_RED, - GL_INT, - 16, 0, 0, 0, - 0, 0, 0, 0, 0, - 1, 1, 2 - }, - { - MESA_FORMAT_R_SINT32, - "MESA_FORMAT_R_SINT32", - GL_RED, - GL_INT, - 32, 0, 0, 0, - 0, 0, 0, 0, 0, - 1, 1, 4 - }, - { - MESA_FORMAT_RG_UINT8, - "MESA_FORMAT_RG_UINT8", - GL_RG, - GL_UNSIGNED_INT, - 8, 8, 0, 0, - 0, 0, 0, 0, 0, - 1, 1, 2 - }, - { - MESA_FORMAT_RG_UINT16, - "MESA_FORMAT_RG_UINT16", - GL_RG, - GL_UNSIGNED_INT, - 16, 16, 0, 0, - 0, 0, 0, 0, 0, - 1, 1, 4 - }, - { - MESA_FORMAT_RG_UINT32, - "MESA_FORMAT_RG_UINT32", - GL_RG, - GL_UNSIGNED_INT, - 32, 32, 0, 0, - 0, 0, 0, 0, 0, - 1, 1, 8 - }, - { - MESA_FORMAT_RG_SINT8, - "MESA_FORMAT_RG_SINT8", - GL_RG, - GL_INT, - 8, 8, 0, 0, - 0, 0, 0, 0, 0, - 1, 1, 2 - }, - { - MESA_FORMAT_RG_SINT16, - "MESA_FORMAT_RG_SINT16", - GL_RG, - GL_INT, - 16, 16, 0, 0, - 0, 0, 0, 0, 0, - 1, 1, 4 - }, - { - MESA_FORMAT_RG_SINT32, - "MESA_FORMAT_RG_SINT32", - GL_RG, - GL_INT, - 32, 32, 0, 0, - 0, 0, 0, 0, 0, - 1, 1, 8 - }, - { - MESA_FORMAT_RGB_UINT8, - "MESA_FORMAT_RGB_UINT8", - GL_RGB, - GL_UNSIGNED_INT, - 8, 8, 8, 0, - 0, 0, 0, 0, 0, - 1, 1, 3 - }, - { - MESA_FORMAT_RGB_UINT16, - "MESA_FORMAT_RGB_UINT16", - GL_RGB, - GL_UNSIGNED_INT, - 16, 16, 16, 0, - 0, 0, 0, 0, 0, - 1, 1, 6 - }, - { - MESA_FORMAT_RGB_UINT32, - "MESA_FORMAT_RGB_UINT32", - GL_RGB, - GL_UNSIGNED_INT, - 32, 32, 32, 0, - 0, 0, 0, 0, 0, - 1, 1, 12 - }, - { - MESA_FORMAT_RGB_SINT8, - "MESA_FORMAT_RGB_SINT8", - GL_RGB, - GL_INT, - 8, 8, 8, 0, - 0, 0, 0, 0, 0, - 1, 1, 3 - }, - { - MESA_FORMAT_RGB_SINT16, - "MESA_FORMAT_RGB_SINT16", - GL_RGB, - GL_INT, - 16, 16, 16, 0, - 0, 0, 0, 0, 0, - 1, 1, 6 - }, - { - MESA_FORMAT_RGB_SINT32, - "MESA_FORMAT_RGB_SINT32", - GL_RGB, - GL_INT, - 32, 32, 32, 0, - 0, 0, 0, 0, 0, - 1, 1, 12 - }, - { - MESA_FORMAT_RGBA_UINT8, - "MESA_FORMAT_RGBA_UINT8", - GL_RGBA, - GL_UNSIGNED_INT, - 8, 8, 8, 8, - 0, 0, 0, 0, 0, - 1, 1, 4 - }, - { - MESA_FORMAT_RGBA_UINT16, - "MESA_FORMAT_RGBA_UINT16", - GL_RGBA, - GL_UNSIGNED_INT, - 16, 16, 16, 16, - 0, 0, 0, 0, 0, - 1, 1, 8 - }, - { - MESA_FORMAT_RGBA_UINT32, - "MESA_FORMAT_RGBA_UINT32", - GL_RGBA, - GL_UNSIGNED_INT, - 32, 32, 32, 32, - 0, 0, 0, 0, 0, - 1, 1, 16 - }, - { - MESA_FORMAT_RGBA_SINT8, - "MESA_FORMAT_RGBA_SINT8", - GL_RGBA, - GL_INT, - 8, 8, 8, 8, - 0, 0, 0, 0, 0, - 1, 1, 4 - }, - { - MESA_FORMAT_RGBA_SINT16, - "MESA_FORMAT_RGBA_SINT16", - GL_RGBA, - GL_INT, - 16, 16, 16, 16, - 0, 0, 0, 0, 0, - 1, 1, 8 - }, - { - MESA_FORMAT_RGBA_SINT32, - "MESA_FORMAT_RGBA_SINT32", - GL_RGBA, - GL_INT, - 32, 32, 32, 32, - 0, 0, 0, 0, 0, - 1, 1, 16 - }, - { - MESA_FORMAT_RGBX_UINT8, - "MESA_FORMAT_RGBX_UINT8", - GL_RGB, - GL_UNSIGNED_INT, - 8, 8, 8, 0, - 0, 0, 0, 0, 0, - 1, 1, 4 - }, - { - MESA_FORMAT_RGBX_UINT16, - "MESA_FORMAT_RGBX_UINT16", - GL_RGB, - GL_UNSIGNED_INT, - 16, 16, 16, 0, - 0, 0, 0, 0, 0, - 1, 1, 8 - }, - { - MESA_FORMAT_RGBX_UINT32, - "MESA_FORMAT_RGBX_UINT32", - GL_RGB, - GL_UNSIGNED_INT, - 32, 32, 32, 0, - 0, 0, 0, 0, 0, - 1, 1, 16 - }, - { - MESA_FORMAT_RGBX_SINT8, - "MESA_FORMAT_RGBX_SINT8", - GL_RGB, - GL_INT, - 8, 8, 8, 0, - 0, 0, 0, 0, 0, - 1, 1, 4 - }, - { - MESA_FORMAT_RGBX_SINT16, - "MESA_FORMAT_RGBX_SINT16", - GL_RGB, - GL_INT, - 16, 16, 16, 0, - 0, 0, 0, 0, 0, - 1, 1, 8 - }, - { - MESA_FORMAT_RGBX_SINT32, - "MESA_FORMAT_RGBX_SINT32", - GL_RGB, - GL_INT, - 32, 32, 32, 0, - 0, 0, 0, 0, 0, - 1, 1, 16 - }, - - /* DXT compressed formats */ - { - MESA_FORMAT_RGB_DXT1, /* Name */ - "MESA_FORMAT_RGB_DXT1", /* StrName */ - GL_RGB, /* BaseFormat */ - GL_UNSIGNED_NORMALIZED, /* DataType */ - 4, 4, 4, 0, /* approx Red/Green/Blue/AlphaBits */ - 0, 0, 0, 0, 0, /* Lum/Int/Index/Depth/StencilBits */ - 4, 4, 8 /* 8 bytes per 4x4 block */ - }, - { - MESA_FORMAT_RGBA_DXT1, - "MESA_FORMAT_RGBA_DXT1", - GL_RGBA, - GL_UNSIGNED_NORMALIZED, - 4, 4, 4, 4, - 0, 0, 0, 0, 0, - 4, 4, 8 /* 8 bytes per 4x4 block */ - }, - { - MESA_FORMAT_RGBA_DXT3, - "MESA_FORMAT_RGBA_DXT3", - GL_RGBA, - GL_UNSIGNED_NORMALIZED, - 4, 4, 4, 4, - 0, 0, 0, 0, 0, - 4, 4, 16 /* 16 bytes per 4x4 block */ - }, - { - MESA_FORMAT_RGBA_DXT5, - "MESA_FORMAT_RGBA_DXT5", - GL_RGBA, - GL_UNSIGNED_NORMALIZED, - 4, 4, 4, 4, - 0, 0, 0, 0, 0, - 4, 4, 16 /* 16 bytes per 4x4 block */ - }, - - /* DXT sRGB compressed formats */ - { - MESA_FORMAT_SRGB_DXT1, /* Name */ - "MESA_FORMAT_SRGB_DXT1", /* StrName */ - GL_RGB, /* BaseFormat */ - GL_UNSIGNED_NORMALIZED, /* DataType */ - 4, 4, 4, 0, /* approx Red/Green/Blue/AlphaBits */ - 0, 0, 0, 0, 0, /* Lum/Int/Index/Depth/StencilBits */ - 4, 4, 8 /* 8 bytes per 4x4 block */ - }, - { - MESA_FORMAT_SRGBA_DXT1, - "MESA_FORMAT_SRGBA_DXT1", - GL_RGBA, - GL_UNSIGNED_NORMALIZED, - 4, 4, 4, 4, - 0, 0, 0, 0, 0, - 4, 4, 8 /* 8 bytes per 4x4 block */ - }, - { - MESA_FORMAT_SRGBA_DXT3, - "MESA_FORMAT_SRGBA_DXT3", - GL_RGBA, - GL_UNSIGNED_NORMALIZED, - 4, 4, 4, 4, - 0, 0, 0, 0, 0, - 4, 4, 16 /* 16 bytes per 4x4 block */ - }, - { - MESA_FORMAT_SRGBA_DXT5, - "MESA_FORMAT_SRGBA_DXT5", - GL_RGBA, - GL_UNSIGNED_NORMALIZED, - 4, 4, 4, 4, - 0, 0, 0, 0, 0, - 4, 4, 16 /* 16 bytes per 4x4 block */ - }, - - /* FXT1 compressed formats */ - { - MESA_FORMAT_RGB_FXT1, - "MESA_FORMAT_RGB_FXT1", - GL_RGB, - GL_UNSIGNED_NORMALIZED, - 4, 4, 4, 0, /* approx Red/Green/BlueBits */ - 0, 0, 0, 0, 0, - 8, 4, 16 /* 16 bytes per 8x4 block */ - }, - { - MESA_FORMAT_RGBA_FXT1, - "MESA_FORMAT_RGBA_FXT1", - GL_RGBA, - GL_UNSIGNED_NORMALIZED, - 4, 4, 4, 1, /* approx Red/Green/Blue/AlphaBits */ - 0, 0, 0, 0, 0, - 8, 4, 16 /* 16 bytes per 8x4 block */ - }, - - /* RGTC compressed formats */ - { - MESA_FORMAT_R_RGTC1_UNORM, - "MESA_FORMAT_R_RGTC1_UNORM", - GL_RED, - GL_UNSIGNED_NORMALIZED, - 8, 0, 0, 0, - 0, 0, 0, 0, 0, - 4, 4, 8 /* 8 bytes per 4x4 block */ - }, - { - MESA_FORMAT_R_RGTC1_SNORM, - "MESA_FORMAT_R_RGTC1_SNORM", - GL_RED, - GL_SIGNED_NORMALIZED, - 8, 0, 0, 0, - 0, 0, 0, 0, 0, - 4, 4, 8 /* 8 bytes per 4x4 block */ - }, - { - MESA_FORMAT_RG_RGTC2_UNORM, - "MESA_FORMAT_RG_RGTC2_UNORM", - GL_RG, - GL_UNSIGNED_NORMALIZED, - 8, 8, 0, 0, - 0, 0, 0, 0, 0, - 4, 4, 16 /* 16 bytes per 4x4 block */ - }, - { - MESA_FORMAT_RG_RGTC2_SNORM, - "MESA_FORMAT_RG_RGTC2_SNORM", - GL_RG, - GL_SIGNED_NORMALIZED, - 8, 8, 0, 0, - 0, 0, 0, 0, 0, - 4, 4, 16 /* 16 bytes per 4x4 block */ - }, - - /* LATC1/2 compressed formats */ - { - MESA_FORMAT_L_LATC1_UNORM, - "MESA_FORMAT_L_LATC1_UNORM", - GL_LUMINANCE, - GL_UNSIGNED_NORMALIZED, - 0, 0, 0, 0, - 4, 0, 0, 0, 0, - 4, 4, 8 /* 8 bytes per 4x4 block */ - }, - { - MESA_FORMAT_L_LATC1_SNORM, - "MESA_FORMAT_L_LATC1_SNORM", - GL_LUMINANCE, - GL_SIGNED_NORMALIZED, - 0, 0, 0, 0, - 4, 0, 0, 0, 0, - 4, 4, 8 /* 8 bytes per 4x4 block */ - }, - { - MESA_FORMAT_LA_LATC2_UNORM, - "MESA_FORMAT_LA_LATC2_UNORM", - GL_LUMINANCE_ALPHA, - GL_UNSIGNED_NORMALIZED, - 0, 0, 0, 4, - 4, 0, 0, 0, 0, - 4, 4, 16 /* 16 bytes per 4x4 block */ - }, - { - MESA_FORMAT_LA_LATC2_SNORM, - "MESA_FORMAT_LA_LATC2_SNORM", - GL_LUMINANCE_ALPHA, - GL_SIGNED_NORMALIZED, - 0, 0, 0, 4, - 4, 0, 0, 0, 0, - 4, 4, 16 /* 16 bytes per 4x4 block */ - }, - - /* ETC1/2 compressed formats */ - { - MESA_FORMAT_ETC1_RGB8, - "MESA_FORMAT_ETC1_RGB8", - GL_RGB, - GL_UNSIGNED_NORMALIZED, - 8, 8, 8, 0, - 0, 0, 0, 0, 0, - 4, 4, 8 /* 8 bytes per 4x4 block */ - }, - { - MESA_FORMAT_ETC2_RGB8, - "MESA_FORMAT_ETC2_RGB8", - GL_RGB, - GL_UNSIGNED_NORMALIZED, - 8, 8, 8, 0, - 0, 0, 0, 0, 0, - 4, 4, 8 /* 8 bytes per 4x4 block */ - }, - { - MESA_FORMAT_ETC2_SRGB8, - "MESA_FORMAT_ETC2_SRGB8", - GL_RGB, - GL_UNSIGNED_NORMALIZED, - 8, 8, 8, 0, - 0, 0, 0, 0, 0, - 4, 4, 8 /* 8 bytes per 4x4 block */ - }, - { - MESA_FORMAT_ETC2_RGBA8_EAC, - "MESA_FORMAT_ETC2_RGBA8_EAC", - GL_RGBA, - GL_UNSIGNED_NORMALIZED, - 8, 8, 8, 8, - 0, 0, 0, 0, 0, - 4, 4, 16 /* 16 bytes per 4x4 block */ - }, - { - MESA_FORMAT_ETC2_SRGB8_ALPHA8_EAC, - "MESA_FORMAT_ETC2_SRGB8_ALPHA8_EAC", - GL_RGBA, - GL_UNSIGNED_NORMALIZED, - 8, 8, 8, 8, - 0, 0, 0, 0, 0, - 4, 4, 16 /* 16 bytes per 4x4 block */ - }, - { - MESA_FORMAT_ETC2_R11_EAC, - "MESA_FORMAT_ETC2_R11_EAC", - GL_RED, - GL_UNSIGNED_NORMALIZED, - 11, 0, 0, 0, - 0, 0, 0, 0, 0, - 4, 4, 8 /* 8 bytes per 4x4 block */ - }, - { - MESA_FORMAT_ETC2_RG11_EAC, - "MESA_FORMAT_ETC2_RG11_EAC", - GL_RG, - GL_UNSIGNED_NORMALIZED, - 11, 11, 0, 0, - 0, 0, 0, 0, 0, - 4, 4, 16 /* 16 bytes per 4x4 block */ - }, - { - MESA_FORMAT_ETC2_SIGNED_R11_EAC, - "MESA_FORMAT_ETC2_SIGNED_R11_EAC", - GL_RED, - GL_SIGNED_NORMALIZED, - 11, 0, 0, 0, - 0, 0, 0, 0, 0, - 4, 4, 8 /* 8 bytes per 4x4 block */ - }, - { - MESA_FORMAT_ETC2_SIGNED_RG11_EAC, - "MESA_FORMAT_ETC2_SIGNED_RG11_EAC", - GL_RG, - GL_SIGNED_NORMALIZED, - 11, 11, 0, 0, - 0, 0, 0, 0, 0, - 4, 4, 16 /* 16 bytes per 4x4 block */ - }, - { - MESA_FORMAT_ETC2_RGB8_PUNCHTHROUGH_ALPHA1, - "MESA_FORMAT_ETC2_RGB8_PUNCHTHROUGH_ALPHA1", - GL_RGBA, - GL_UNSIGNED_NORMALIZED, - 8, 8, 8, 1, - 0, 0, 0, 0, 0, - 4, 4, 8 /* 8 bytes per 4x4 block */ - }, - { - MESA_FORMAT_ETC2_SRGB8_PUNCHTHROUGH_ALPHA1, - "MESA_FORMAT_ETC2_SRGB8_PUNCHTHROUGH_ALPHA1", - GL_RGBA, - GL_UNSIGNED_NORMALIZED, - 8, 8, 8, 1, - 0, 0, 0, 0, 0, - 4, 4, 8 /* 8 bytes per 4x4 block */ - }, + uint8_t Swizzle[4]; }; - +#include "format_info.c" static const struct gl_format_info * _mesa_get_format_info(mesa_format format) @@ -1881,7 +148,7 @@ _mesa_get_format_bits(mesa_format format, GLenum pname) case GL_TEXTURE_LUMINANCE_SIZE: return info->LuminanceBits; case GL_INDEX_BITS: - return info->IndexBits; + return 0; case GL_DEPTH_BITS: case GL_TEXTURE_DEPTH_SIZE_ARB: case GL_RENDERBUFFER_DEPTH_SIZE_EXT: @@ -1915,6 +182,21 @@ _mesa_get_format_max_bits(mesa_format format) /** + * Return the layout type of the given format. + * The return value will be one of: + * MESA_FORMAT_LAYOUT_ARRAY + * MESA_FORMAT_LAYOUT_PACKED + * MESA_FORMAT_LAYOUT_OTHER + */ +extern enum mesa_format_layout +_mesa_get_format_layout(mesa_format format) +{ + const struct gl_format_info *info = _mesa_get_format_info(format); + return info->Layout; +} + + +/** * Return the data type (or more specifically, the data representation) * for the given format. * The return value will be one of: @@ -1961,6 +243,33 @@ _mesa_get_format_block_size(mesa_format format, GLuint *bw, GLuint *bh) } +/** + * Returns the an array of four numbers representing the transformation + * from the RGBA or SZ colorspace to the given format. For array formats, + * the i'th RGBA component is given by: + * + * if (swizzle[i] <= MESA_FORMAT_SWIZZLE_W) + * comp = data[swizzle[i]]; + * else if (swizzle[i] == MESA_FORMAT_SWIZZLE_ZERO) + * comp = 0; + * else if (swizzle[i] == MESA_FORMAT_SWIZZLE_ONE) + * comp = 1; + * else if (swizzle[i] == MESA_FORMAT_SWIZZLE_NONE) + * // data does not contain a channel of this format + * + * For packed formats, the swizzle gives the number of components left of + * the least significant bit. + * + * Compressed formats have no swizzle. + */ +void +_mesa_get_format_swizzle(mesa_format format, uint8_t swizzle_out[4]) +{ + const struct gl_format_info *info = _mesa_get_format_info(format); + memcpy(swizzle_out, info->Swizzle, sizeof(info->Swizzle)); +} + + /** Is the given format a compressed format? */ GLboolean _mesa_is_format_compressed(mesa_format format) @@ -2331,7 +640,6 @@ check_format_to_type_and_comps(void) } } - /** * Do sanity checking of the format info table. */ diff --git a/mesalib/src/mesa/main/formats.csv b/mesalib/src/mesa/main/formats.csv new file mode 100644 index 000000000..eade6facd --- /dev/null +++ b/mesalib/src/mesa/main/formats.csv @@ -0,0 +1,282 @@ +########################################################################### +# +# Copyright 2009-2010 VMware, Inc. +# Copyright 2014 Intel Corporation +# All Rights Reserved. +# +# Permission is hereby granted, free of charge, to any person obtaining a +# copy of this software and associated documentation files (the +# "Software"), to deal in the Software without restriction, including +# without limitation the rights to use, copy, modify, merge, publish, +# distribute, sub license, and/or sell copies of the Software, and to +# permit persons to whom the Software is furnished to do so, subject to +# the following conditions: +# +# The 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 NON-INFRINGEMENT. +# IN NO EVENT SHALL THE AUTHORS AND/OR ITS SUPPLIERS BE LIABLE FOR +# ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, +# TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE +# SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +# +########################################################################### + +# This CSV file has the input data for gen_format.h and gen_format.c +# +# Each format entry contains: +# - name, per enum mesa_format +# - layout +# - pixel block's width +# - pixel block's height +# - channel encoding (only meaningful for array or packed layout), containing for each +# channel the following information: +# - type, one of +# - 'x': void +# - 'u': unsigned +# - 's': signed +# - 'h': fixed +# - 'f': FLOAT +# - optionally followed by 'n' if it is normalized +# - number of bits +# - channel swizzle +# - color space: rgb, srgb, yub, sz + +# None +# Described as regular uint_8 bytes, i.e. MESA_FORMAT_R8_USCALED +MESA_FORMAT_NONE , other , 1, 1, x8 , , , , 0001, rgb + +# Packed unorm formats +MESA_FORMAT_A8B8G8R8_UNORM , packed, 1, 1, un8 , un8 , un8 , un8 , wzyx, rgb +MESA_FORMAT_X8B8G8R8_UNORM , packed, 1, 1, x8 , un8 , un8 , un8 , wzy1, rgb +MESA_FORMAT_R8G8B8A8_UNORM , packed, 1, 1, un8 , un8 , un8 , un8 , xyzw, rgb +MESA_FORMAT_R8G8B8X8_UNORM , packed, 1, 1, un8 , un8 , un8 , x8 , xyz1, rgb +MESA_FORMAT_B8G8R8A8_UNORM , packed, 1, 1, un8 , un8 , un8 , un8 , zyxw, rgb +MESA_FORMAT_B8G8R8X8_UNORM , packed, 1, 1, un8 , un8 , un8 , x8 , zyx1, rgb +MESA_FORMAT_A8R8G8B8_UNORM , packed, 1, 1, un8 , un8 , un8 , un8 , yzwx, rgb +MESA_FORMAT_X8R8G8B8_UNORM , packed, 1, 1, x8 , un8 , un8 , un8 , yzw1, rgb +MESA_FORMAT_L16A16_UNORM , packed, 1, 1, un16, un16, , , xxxy, rgb +MESA_FORMAT_A16L16_UNORM , packed, 1, 1, un16, un16, , , yyyx, rgb +MESA_FORMAT_B5G6R5_UNORM , packed, 1, 1, un5 , un6 , un5 , , zyx1, rgb +MESA_FORMAT_R5G6B5_UNORM , packed, 1, 1, un5 , un6 , un5 , , xyz1, rgb +MESA_FORMAT_B4G4R4A4_UNORM , packed, 1, 1, un4 , un4 , un4 , un4 , zyxw, rgb +MESA_FORMAT_B4G4R4X4_UNORM , packed, 1, 1, un4 , un4 , un4 , x4 , zyx1, rgb +MESA_FORMAT_A4R4G4B4_UNORM , packed, 1, 1, un4 , un4 , un4 , un4 , yzwx, rgb +MESA_FORMAT_A1B5G5R5_UNORM , packed, 1, 1, un1 , un5 , un5 , un5 , wzyx, rgb +MESA_FORMAT_B5G5R5A1_UNORM , packed, 1, 1, un5 , un5 , un5 , un1 , zyxw, rgb +MESA_FORMAT_B5G5R5X1_UNORM , packed, 1, 1, un5 , un5 , un5 , x1 , zyx1, rgb +MESA_FORMAT_A1R5G5B5_UNORM , packed, 1, 1, un1 , un5 , un5 , un5 , yzwx, rgb +MESA_FORMAT_L8A8_UNORM , packed, 1, 1, un8 , un8 , , , xxxy, rgb +MESA_FORMAT_A8L8_UNORM , packed, 1, 1, un8 , un8 , , , yyyx, rgb +MESA_FORMAT_R8G8_UNORM , packed, 1, 1, un8 , un8 , , , xy01, rgb +MESA_FORMAT_G8R8_UNORM , packed, 1, 1, un8 , un8 , , , yx01, rgb +MESA_FORMAT_L4A4_UNORM , packed, 1, 1, un4 , un4 , , , xxxy, rgb + +MESA_FORMAT_B2G3R3_UNORM , packed, 1, 1, un2 , un3 , un3 , , zyx1, rgb +MESA_FORMAT_R16G16_UNORM , packed, 1, 1, un16, un16, , , xy01, rgb +MESA_FORMAT_G16R16_UNORM , packed, 1, 1, un16, un16, , , yx01, rgb +MESA_FORMAT_B10G10R10A2_UNORM , packed, 1, 1, un10, un10, un10, un2 , zyxw, rgb +MESA_FORMAT_B10G10R10X2_UNORM , packed, 1, 1, un10, un10, un10, x2 , zyx1, rgb +MESA_FORMAT_R10G10B10A2_UNORM , packed, 1, 1, un10, un10, un10, un2 , xyzw, rgb + +MESA_FORMAT_S8_UINT_Z24_UNORM , packed, 1, 1, un24, u8 , , , xy__, zs +MESA_FORMAT_X8_UINT_Z24_UNORM , packed, 1, 1, un24, x8 , , , x___, zs +MESA_FORMAT_Z24_UNORM_S8_UINT , packed, 1, 1, u8 , un24, , , yx__, zs +MESA_FORMAT_Z24_UNORM_X8_UINT , packed, 1, 1, x8 , un24, , , y___, zs + +MESA_FORMAT_YCBCR , other , 1, 1, x16 , , , , xyzw, yuv +MESA_FORMAT_YCBCR_REV , other , 1, 1, x16 , , , , xyzw, yuv + +# Array normalized formats +MESA_FORMAT_A_UNORM8 , array , 1, 1, un8 , , , , 000x, rgb +MESA_FORMAT_A_UNORM16 , array , 1, 1, un16, , , , 000x, rgb +MESA_FORMAT_L_UNORM8 , array , 1, 1, un8 , , , , xxx1, rgb +MESA_FORMAT_L_UNORM16 , array , 1, 1, un16, , , , xxx1, rgb +MESA_FORMAT_I_UNORM8 , array , 1, 1, un8 , , , , xxxx, rgb +MESA_FORMAT_I_UNORM16 , array , 1, 1, un16, , , , xxxx, rgb +MESA_FORMAT_R_UNORM8 , array , 1, 1, un8 , , , , x001, rgb +MESA_FORMAT_R_UNORM16 , array , 1, 1, un16, , , , x001, rgb +MESA_FORMAT_BGR_UNORM8 , array , 1, 1, un8 , un8 , un8 , , zyx1, rgb +MESA_FORMAT_RGB_UNORM8 , array , 1, 1, un8 , un8 , un8 , , xyz1, rgb +MESA_FORMAT_RGBA_UNORM16 , array , 1, 1, un16, un16, un16, un16, xyzw, rgb +MESA_FORMAT_RGBX_UNORM16 , array , 1, 1, un16, un16, un16, x16 , xyz1, rgb + +MESA_FORMAT_Z_UNORM16 , array , 1, 1, un16, , , , x___, zs +MESA_FORMAT_Z_UNORM32 , array , 1, 1, un32, , , , x___, zs +MESA_FORMAT_S_UINT8 , array , 1, 1, u8 , , , , _x__, zs + +# Packed signed formats +MESA_FORMAT_A8B8G8R8_SNORM , packed, 1, 1, sn8 , sn8 , sn8 , sn8 , wzyx, rgb +MESA_FORMAT_X8B8G8R8_SNORM , packed, 1, 1, x8 , sn8 , sn8 , sn8 , wzy1, rgb +MESA_FORMAT_R8G8B8A8_SNORM , packed, 1, 1, sn8 , sn8 , sn8 , sn8 , xyzw, rgb +MESA_FORMAT_R8G8B8X8_SNORM , packed, 1, 1, sn8 , sn8 , sn8 , x8 , xyz1, rgb +MESA_FORMAT_R16G16_SNORM , packed, 1, 1, sn16, sn16, , , xy01, rgb +MESA_FORMAT_G16R16_SNORM , packed, 1, 1, sn16, sn16, , , yx01, rgb +MESA_FORMAT_R8G8_SNORM , packed, 1, 1, sn8 , sn8 , , , xy01, rgb +MESA_FORMAT_G8R8_SNORM , packed, 1, 1, sn8 , sn8 , , , yx01, rgb +MESA_FORMAT_L8A8_SNORM , packed, 1, 1, sn8 , sn8 , , , xxxy, rgb + +# Array signed/normalized formats +MESA_FORMAT_A_SNORM8 , array , 1, 1, sn8 , , , , 000x, rgb +MESA_FORMAT_A_SNORM16 , array , 1, 1, sn16, , , , 000x, rgb +MESA_FORMAT_L_SNORM8 , array , 1, 1, sn8 , , , , xxx1, rgb +MESA_FORMAT_L_SNORM16 , array , 1, 1, sn16, , , , xxx1, rgb +MESA_FORMAT_I_SNORM8 , array , 1, 1, sn8 , , , , xxxx, rgb +MESA_FORMAT_I_SNORM16 , array , 1, 1, sn16, , , , xxxx, rgb +MESA_FORMAT_R_SNORM8 , array , 1, 1, sn8 , , , , x001, rgb +MESA_FORMAT_R_SNORM16 , array , 1, 1, sn16, , , , x001, rgb +MESA_FORMAT_LA_SNORM16 , array , 1, 1, sn16, sn16, , , xxxy, rgb +MESA_FORMAT_RGB_SNORM16 , array , 1, 1, sn16, sn16, sn16, , xyz1, rgb +MESA_FORMAT_RGBA_SNORM16 , array , 1, 1, sn16, sn16, sn16, sn16, xyzw, rgb +MESA_FORMAT_RGBX_SNORM16 , array , 1, 1, sn16, sn16, sn16, x16 , xyz1, rgb + +# Packed sRGB formats +MESA_FORMAT_A8B8G8R8_SRGB , packed, 1, 1, un8 , un8 , un8 , un8 , wzyx, srgb +MESA_FORMAT_B8G8R8A8_SRGB , packed, 1, 1, un8 , un8 , un8 , un8 , zyxw, srgb +MESA_FORMAT_B8G8R8X8_SRGB , packed, 1, 1, un8 , un8 , un8 , x8 , zyx1, srgb +MESA_FORMAT_R8G8B8A8_SRGB , packed, 1, 1, un8 , un8 , un8 , un8 , xyzw, srgb +MESA_FORMAT_R8G8B8X8_SRGB , packed, 1, 1, un8 , un8 , un8 , x8 , xyz1, srgb +MESA_FORMAT_L8A8_SRGB , packed, 1, 1, un8 , un8 , , , xxxy, srgb + +# Array sRGB formats +MESA_FORMAT_L_SRGB8 , array , 1, 1, un8 , , , , xxx1, srgb +MESA_FORMAT_BGR_SRGB8 , array , 1, 1, un8 , un8 , un8 , , zyx1, srgb + +# Packed float formats +MESA_FORMAT_R9G9B9E5_FLOAT , other , 1, 1, f9 , f9 , f9 , x5 , xyz1, rgb +MESA_FORMAT_R11G11B10_FLOAT , packed, 1, 1, f11 , f11 , f10 , , xyz1, rgb +MESA_FORMAT_Z32_FLOAT_S8X24_UINT , packed, 1, 1, u8 , x24 , f32 , , zx__, zs + +# Array float formats +MESA_FORMAT_A_FLOAT16 , array , 1, 1, f16 , , , , 000x, rgb +MESA_FORMAT_A_FLOAT32 , array , 1, 1, f32 , , , , 000x, rgb +MESA_FORMAT_L_FLOAT16 , array , 1, 1, f16 , , , , xxx1, rgb +MESA_FORMAT_L_FLOAT32 , array , 1, 1, f32 , , , , xxx1, rgb +MESA_FORMAT_LA_FLOAT16 , array , 1, 1, f16 , f16 , , , xxxy, rgb +MESA_FORMAT_LA_FLOAT32 , array , 1, 1, f32 , f32 , , , xxxy, rgb +MESA_FORMAT_I_FLOAT16 , array , 1, 1, f16 , , , , xxxx, rgb +MESA_FORMAT_I_FLOAT32 , array , 1, 1, f32 , , , , xxxx, rgb +MESA_FORMAT_R_FLOAT16 , array , 1, 1, f16 , , , , x001, rgb +MESA_FORMAT_R_FLOAT32 , array , 1, 1, f32 , , , , x001, rgb +MESA_FORMAT_RG_FLOAT16 , array , 1, 1, f16 , f16 , , , xy01, rgb +MESA_FORMAT_RG_FLOAT32 , array , 1, 1, f32 , f32 , , , xy01, rgb +MESA_FORMAT_RGB_FLOAT16 , array , 1, 1, f16 , f16 , f16 , , xyz1, rgb +MESA_FORMAT_RGB_FLOAT32 , array , 1, 1, f32 , f32 , f32 , , xyz1, rgb +MESA_FORMAT_RGBA_FLOAT16 , array , 1, 1, f16 , f16 , f16 , f16 , xyzw, rgb +MESA_FORMAT_RGBA_FLOAT32 , array , 1, 1, f32 , f32 , f32 , f32 , xyzw, rgb +MESA_FORMAT_RGBX_FLOAT16 , array , 1, 1, f16 , f16 , f16 , x16 , xyz1, rgb +MESA_FORMAT_RGBX_FLOAT32 , array , 1, 1, f32 , f32 , f32 , x32 , xyz1, rgb +MESA_FORMAT_Z_FLOAT32 , array , 1, 1, f32 , , , , x___, zs + +# Packed signed/unsigned non-normalized integer formats +MESA_FORMAT_B10G10R10A2_UINT , packed, 1, 1, u10 , u10 , u10 , u2 , zyxw, rgb +MESA_FORMAT_R10G10B10A2_UINT , packed, 1, 1, u10 , u10 , u10 , u2 , xyzw, rgb + +# Array signed/unsigned non-normalized integer formats +MESA_FORMAT_A_UINT8 , array , 1, 1, u8 , , , , 000x, rgb +MESA_FORMAT_A_UINT16 , array , 1, 1, u16 , , , , 000x, rgb +MESA_FORMAT_A_UINT32 , array , 1, 1, u32 , , , , 000x, rgb +MESA_FORMAT_A_SINT8 , array , 1, 1, s8 , , , , 000x, rgb +MESA_FORMAT_A_SINT16 , array , 1, 1, s16 , , , , 000x, rgb +MESA_FORMAT_A_SINT32 , array , 1, 1, s32 , , , , 000x, rgb + +MESA_FORMAT_I_UINT8 , array , 1, 1, u8 , , , , xxxx, rgb +MESA_FORMAT_I_UINT16 , array , 1, 1, u16 , , , , xxxx, rgb +MESA_FORMAT_I_UINT32 , array , 1, 1, u32 , , , , xxxx, rgb +MESA_FORMAT_I_SINT8 , array , 1, 1, s8 , , , , xxxx, rgb +MESA_FORMAT_I_SINT16 , array , 1, 1, s16 , , , , xxxx, rgb +MESA_FORMAT_I_SINT32 , array , 1, 1, s32 , , , , xxxx, rgb + +MESA_FORMAT_L_UINT8 , array , 1, 1, u8 , , , , xxx1, rgb +MESA_FORMAT_L_UINT16 , array , 1, 1, u16 , , , , xxx1, rgb +MESA_FORMAT_L_UINT32 , array , 1, 1, u32 , , , , xxx1, rgb +MESA_FORMAT_L_SINT8 , array , 1, 1, s8 , , , , xxx1, rgb +MESA_FORMAT_L_SINT16 , array , 1, 1, s16 , , , , xxx1, rgb +MESA_FORMAT_L_SINT32 , array , 1, 1, s32 , , , , xxx1, rgb + +MESA_FORMAT_LA_UINT8 , array , 1, 1, u8 , u8 , , , xxxy, rgb +MESA_FORMAT_LA_UINT16 , array , 1, 1, u16 , u16 , , , xxxy, rgb +MESA_FORMAT_LA_UINT32 , array , 1, 1, u32 , u32 , , , xxxy, rgb +MESA_FORMAT_LA_SINT8 , array , 1, 1, s8 , s8 , , , xxxy, rgb +MESA_FORMAT_LA_SINT16 , array , 1, 1, s16 , s16 , , , xxxy, rgb +MESA_FORMAT_LA_SINT32 , array , 1, 1, s32 , s32 , , , xxxy, rgb + +MESA_FORMAT_R_UINT8 , array , 1, 1, u8 , , , , x001, rgb +MESA_FORMAT_R_UINT16 , array , 1, 1, u16 , , , , x001, rgb +MESA_FORMAT_R_UINT32 , array , 1, 1, u32 , , , , x001, rgb +MESA_FORMAT_R_SINT8 , array , 1, 1, s8 , , , , x001, rgb +MESA_FORMAT_R_SINT16 , array , 1, 1, s16 , , , , x001, rgb +MESA_FORMAT_R_SINT32 , array , 1, 1, s32 , , , , x001, rgb + +MESA_FORMAT_RG_UINT8 , array , 1, 1, u8 , u8 , , , xy01, rgb +MESA_FORMAT_RG_UINT16 , array , 1, 1, u16 , u16 , , , xy01, rgb +MESA_FORMAT_RG_UINT32 , array , 1, 1, u32 , u32 , , , xy01, rgb +MESA_FORMAT_RG_SINT8 , array , 1, 1, s8 , s8 , , , xy01, rgb +MESA_FORMAT_RG_SINT16 , array , 1, 1, s16 , s16 , , , xy01, rgb +MESA_FORMAT_RG_SINT32 , array , 1, 1, s32 , s32 , , , xy01, rgb + +MESA_FORMAT_RGB_UINT8 , array , 1, 1, u8 , u8 , u8 , , xyz1, rgb +MESA_FORMAT_RGB_UINT16 , array , 1, 1, u16 , u16 , u16 , , xyz1, rgb +MESA_FORMAT_RGB_UINT32 , array , 1, 1, u32 , u32 , u32 , , xyz1, rgb +MESA_FORMAT_RGB_SINT8 , array , 1, 1, s8 , s8 , s8 , , xyz1, rgb +MESA_FORMAT_RGB_SINT16 , array , 1, 1, s16 , s16 , s16 , , xyz1, rgb +MESA_FORMAT_RGB_SINT32 , array , 1, 1, s32 , s32 , s32 , , xyz1, rgb + +MESA_FORMAT_RGBA_UINT8 , array , 1, 1, u8 , u8 , u8 , u8 , xyzw, rgb +MESA_FORMAT_RGBA_UINT16 , array , 1, 1, u16 , u16 , u16 , u16 , xyzw, rgb +MESA_FORMAT_RGBA_UINT32 , array , 1, 1, u32 , u32 , u32 , u32 , xyzw, rgb +MESA_FORMAT_RGBA_SINT8 , array , 1, 1, s8 , s8 , s8 , s8 , xyzw, rgb +MESA_FORMAT_RGBA_SINT16 , array , 1, 1, s16 , s16 , s16 , s16 , xyzw, rgb +MESA_FORMAT_RGBA_SINT32 , array , 1, 1, s32 , s32 , s32 , s32 , xyzw, rgb + +MESA_FORMAT_RGBX_UINT8 , array , 1, 1, u8 , u8 , u8 , x8 , xyz1, rgb +MESA_FORMAT_RGBX_UINT16 , array , 1, 1, u16 , u16 , u16 , x16 , xyz1, rgb +MESA_FORMAT_RGBX_UINT32 , array , 1, 1, u32 , u32 , u32 , x32 , xyz1, rgb +MESA_FORMAT_RGBX_SINT8 , array , 1, 1, s8 , s8 , s8 , x8 , xyz1, rgb +MESA_FORMAT_RGBX_SINT16 , array , 1, 1, s16 , s16 , s16 , x16 , xyz1, rgb +MESA_FORMAT_RGBX_SINT32 , array , 1, 1, s32 , s32 , s32 , x32 , xyz1, rgb + +# DTX compressed formats +MESA_FORMAT_RGB_DXT1 , s3tc , 4, 4, x64 , , , , xyz1, rgb +MESA_FORMAT_RGBA_DXT1 , s3tc , 4, 4, x64 , , , , xyzw, rgb +MESA_FORMAT_RGBA_DXT3 , s3tc , 4, 4, x128, , , , xyzw, rgb +MESA_FORMAT_RGBA_DXT5 , s3tc , 4, 4, x128, , , , xyzw, rgb + +# DTX sRGB compressed formats +MESA_FORMAT_SRGB_DXT1 , s3tc , 4, 4, x64 , , , , xyz1, srgb +MESA_FORMAT_SRGBA_DXT1 , s3tc , 4, 4, x64 , , , , xyzw, srgb +MESA_FORMAT_SRGBA_DXT3 , s3tc , 4, 4, x128, , , , xyzw, srgb +MESA_FORMAT_SRGBA_DXT5 , s3tc , 4, 4, x128, , , , xyzw, srgb + +# FXT1 compressed formats +MESA_FORMAT_RGB_FXT1 , fxt1 , 8, 4, x128, , , , xyz1, rgb +MESA_FORMAT_RGBA_FXT1 , fxt1 , 8, 4, x128, , , , xyzw, rgb + +# RGTC compressed formats +MESA_FORMAT_R_RGTC1_UNORM , rgtc , 4, 4, x64 , , , , x001, rgb +MESA_FORMAT_R_RGTC1_SNORM , rgtc , 4, 4, x64 , , , , x001, rgb +MESA_FORMAT_RG_RGTC2_UNORM , rgtc , 4, 4, x128, , , , xy01, rgb +MESA_FORMAT_RG_RGTC2_SNORM , rgtc , 4, 4, x128, , , , xy01, rgb + +# LATC1/2 compressed formats +MESA_FORMAT_L_LATC1_UNORM , rgtc , 4, 4, x64 , , , , xxx1, rgb +MESA_FORMAT_L_LATC1_SNORM , rgtc , 4, 4, x64 , , , , xxx1, rgb +MESA_FORMAT_LA_LATC2_UNORM , rgtc , 4, 4, x128, , , , xxxy, rgb +MESA_FORMAT_LA_LATC2_SNORM , rgtc , 4, 4, x128, , , , xxxy, rgb + +# ETC1/2 compressed formats +MESA_FORMAT_ETC1_RGB8 , etc1 , 4, 4, x64 , , , , xyz1, rgb +MESA_FORMAT_ETC2_RGB8 , etc2 , 4, 4, x64 , , , , xyz1, rgb +MESA_FORMAT_ETC2_SRGB8 , etc2 , 4, 4, x64 , , , , xyz1, srgb +MESA_FORMAT_ETC2_RGBA8_EAC , etc2 , 4, 4, x128, , , , xyzw, rgb +MESA_FORMAT_ETC2_SRGB8_ALPHA8_EAC , etc2 , 4, 4, x128, , , , xyzw, srgb +MESA_FORMAT_ETC2_R11_EAC , etc2 , 4, 4, x64 , , , , x001, rgb +MESA_FORMAT_ETC2_RG11_EAC , etc2 , 4, 4, x128, , , , xy01, rgb +MESA_FORMAT_ETC2_SIGNED_R11_EAC , etc2 , 4, 4, x64 , , , , x001, rgb +MESA_FORMAT_ETC2_SIGNED_RG11_EAC , etc2 , 4, 4, x128, , , , xy01, rgb +MESA_FORMAT_ETC2_RGB8_PUNCHTHROUGH_ALPHA1 , etc2 , 4, 4, x64 , , , , xyzw, rgb +MESA_FORMAT_ETC2_SRGB8_PUNCHTHROUGH_ALPHA1, etc2 , 4, 4, x64 , , , , xyzw, srgb diff --git a/mesalib/src/mesa/main/formats.h b/mesalib/src/mesa/main/formats.h index dc50bc830..457c8abf8 100644 --- a/mesalib/src/mesa/main/formats.h +++ b/mesalib/src/mesa/main/formats.h @@ -35,6 +35,7 @@ #include <GL/gl.h> #include <stdbool.h> +#include <stdint.h> #ifdef __cplusplus @@ -56,6 +57,29 @@ extern "C" { */ #define MAX_PIXEL_BYTES 16 +/** + * Specifies the layout of a pixel format. See the MESA_FORMAT + * documentation below. + */ +enum mesa_format_layout { + MESA_FORMAT_LAYOUT_ARRAY, + MESA_FORMAT_LAYOUT_PACKED, + MESA_FORMAT_LAYOUT_OTHER, +}; + +/** + * An enum representing different possible swizzling values. This is used + * to interpret the output of _mesa_get_format_swizzle + */ +enum { + MESA_FORMAT_SWIZZLE_X = 0, + MESA_FORMAT_SWIZZLE_Y = 1, + MESA_FORMAT_SWIZZLE_Z = 2, + MESA_FORMAT_SWIZZLE_W = 3, + MESA_FORMAT_SWIZZLE_ZERO = 4, + MESA_FORMAT_SWIZZLE_ONE = 5, + MESA_FORMAT_SWIZZLE_NONE = 6, +}; /** * Mesa texture/renderbuffer image formats. @@ -419,6 +443,9 @@ _mesa_get_format_bits(mesa_format format, GLenum pname); extern GLuint _mesa_get_format_max_bits(mesa_format format); +extern enum mesa_format_layout +_mesa_get_format_layout(mesa_format format); + extern GLenum _mesa_get_format_datatype(mesa_format format); @@ -428,6 +455,9 @@ _mesa_get_format_base_format(mesa_format format); extern void _mesa_get_format_block_size(mesa_format format, GLuint *bw, GLuint *bh); +extern void +_mesa_get_format_swizzle(mesa_format format, uint8_t swizzle_out[4]); + extern GLboolean _mesa_is_format_compressed(mesa_format format); diff --git a/mesalib/src/mesa/main/get_hash_params.py b/mesalib/src/mesa/main/get_hash_params.py index 35d6172a3..ff858207b 100644 --- a/mesalib/src/mesa/main/get_hash_params.py +++ b/mesalib/src/mesa/main/get_hash_params.py @@ -84,6 +84,7 @@ descriptor=[ [ "SAMPLES_ARB", "BUFFER_INT(Visual.samples), extra_new_buffers" ], # GL_ARB_sample_shading + [ "SAMPLE_SHADING_ARB", "CONTEXT_BOOL(Multisample.SampleShading), extra_gl40_ARB_sample_shading" ], [ "MIN_SAMPLE_SHADING_VALUE_ARB", "CONTEXT_FLOAT(Multisample.MinSampleShadingValue), extra_gl40_ARB_sample_shading" ], # GL_SGIS_generate_mipmap diff --git a/mesalib/src/mesa/main/glformats.c b/mesalib/src/mesa/main/glformats.c index 304d45298..0fb25ba0f 100644 --- a/mesalib/src/mesa/main/glformats.c +++ b/mesalib/src/mesa/main/glformats.c @@ -353,6 +353,170 @@ _mesa_bytes_per_vertex_attrib(GLint comps, GLenum type) } } +/** + * Test if the given format is unsized. + */ +GLboolean +_mesa_is_enum_format_unsized(GLenum format) +{ + switch (format) { + case GL_RGBA: + case GL_BGRA: + case GL_ABGR_EXT: + case GL_RGB: + case GL_BGR: + case GL_RG: + case GL_RED: + case GL_GREEN: + case GL_BLUE: + case GL_ALPHA: + case GL_INTENSITY: + case GL_LUMINANCE: + case GL_LUMINANCE_ALPHA: + + case GL_SRGB: + case GL_SRGB_ALPHA: + case GL_SLUMINANCE: + case GL_SLUMINANCE_ALPHA: + + case GL_RGBA_SNORM: + case GL_RGB_SNORM: + case GL_RG_SNORM: + case GL_RED_SNORM: + case GL_ALPHA_SNORM: + case GL_INTENSITY_SNORM: + case GL_LUMINANCE_SNORM: + case GL_LUMINANCE_ALPHA_SNORM: + + case GL_RED_INTEGER: + case GL_GREEN_INTEGER: + case GL_BLUE_INTEGER: + case GL_ALPHA_INTEGER: + case GL_RGB_INTEGER: + case GL_RGBA_INTEGER: + case GL_BGR_INTEGER: + case GL_BGRA_INTEGER: + case GL_RG_INTEGER: + case GL_LUMINANCE_INTEGER_EXT: + case GL_LUMINANCE_ALPHA_INTEGER_EXT: + + case GL_DEPTH_COMPONENT: + case GL_DEPTH_STENCIL: + case GL_STENCIL_INDEX: + return GL_TRUE; + default: + return GL_FALSE; + } +} + +/** + * Test if the given format is a UNORM (unsigned-normalized) format. + */ +GLboolean +_mesa_is_enum_format_unorm(GLenum format) +{ + switch(format) { + case GL_RED: + case GL_GREEN: + case GL_BLUE: + case GL_ALPHA: + case GL_ALPHA4: + case GL_ALPHA8: + case GL_ALPHA12: + case GL_ALPHA16: + case 1: + case GL_LUMINANCE: + case GL_SLUMINANCE: + case GL_LUMINANCE4: + case GL_LUMINANCE8: + case GL_LUMINANCE12: + case GL_LUMINANCE16: + case 2: + case GL_LUMINANCE_ALPHA: + case GL_SLUMINANCE_ALPHA: + case GL_LUMINANCE4_ALPHA4: + case GL_LUMINANCE6_ALPHA2: + case GL_LUMINANCE8_ALPHA8: + case GL_LUMINANCE12_ALPHA4: + case GL_LUMINANCE12_ALPHA12: + case GL_LUMINANCE16_ALPHA16: + case GL_INTENSITY: + case GL_INTENSITY4: + case GL_INTENSITY8: + case GL_INTENSITY12: + case GL_INTENSITY16: + case GL_R8: + case GL_R16: + case GL_RG: + case GL_RG8: + case GL_RG16: + case 3: + case GL_RGB: + case GL_BGR: + case GL_SRGB: + case GL_R3_G3_B2: + case GL_RGB4: + case GL_RGB5: + case GL_RGB565: + case GL_RGB8: + case GL_RGB10: + case GL_RGB12: + case GL_RGB16: + case 4: + case GL_ABGR_EXT: + case GL_RGBA: + case GL_BGRA: + case GL_SRGB_ALPHA: + case GL_RGBA2: + case GL_RGBA4: + case GL_RGB5_A1: + case GL_RGBA8: + case GL_RGB10_A2: + case GL_RGBA12: + case GL_RGBA16: + return GL_TRUE; + default: + return GL_FALSE; + } +} + +/** + * Test if the given format is a SNORM (signed-normalized) format. + */ +GLboolean +_mesa_is_enum_format_snorm(GLenum format) +{ + switch (format) { + /* signed, normalized texture formats */ + case GL_RED_SNORM: + case GL_R8_SNORM: + case GL_R16_SNORM: + case GL_RG_SNORM: + case GL_RG8_SNORM: + case GL_RG16_SNORM: + case GL_RGB_SNORM: + case GL_RGB8_SNORM: + case GL_RGB16_SNORM: + case GL_RGBA_SNORM: + case GL_RGBA8_SNORM: + case GL_RGBA16_SNORM: + case GL_ALPHA_SNORM: + case GL_ALPHA8_SNORM: + case GL_ALPHA16_SNORM: + case GL_LUMINANCE_SNORM: + case GL_LUMINANCE8_SNORM: + case GL_LUMINANCE16_SNORM: + case GL_LUMINANCE_ALPHA_SNORM: + case GL_LUMINANCE8_ALPHA8_SNORM: + case GL_LUMINANCE16_ALPHA16_SNORM: + case GL_INTENSITY_SNORM: + case GL_INTENSITY8_SNORM: + case GL_INTENSITY16_SNORM: + return GL_TRUE; + default: + return GL_FALSE; + } +} /** * Test if the given format is an integer (non-normalized) format. diff --git a/mesalib/src/mesa/main/glformats.h b/mesalib/src/mesa/main/glformats.h index d64114ec9..7b0321570 100644 --- a/mesalib/src/mesa/main/glformats.h +++ b/mesalib/src/mesa/main/glformats.h @@ -57,6 +57,15 @@ extern GLboolean _mesa_is_type_unsigned(GLenum type); extern GLboolean +_mesa_is_enum_format_unsized(GLenum format); + +extern GLboolean +_mesa_is_enum_format_unorm(GLenum format); + +extern GLboolean +_mesa_is_enum_format_snorm(GLenum format); + +extern GLboolean _mesa_is_enum_format_integer(GLenum format); extern GLboolean diff --git a/mesalib/src/mesa/main/hash.c b/mesalib/src/mesa/main/hash.c index 674c29d65..52095f7d1 100644 --- a/mesalib/src/mesa/main/hash.c +++ b/mesalib/src/mesa/main/hash.c @@ -37,7 +37,7 @@ #include "glheader.h" #include "imports.h" #include "hash.h" -#include "hash_table.h" +#include "util/hash_table.h" /** * Magic GLuint object name that gets stored outside of the struct hash_table. diff --git a/mesalib/src/mesa/main/imports.h b/mesalib/src/mesa/main/imports.h index 09e55ebf0..59fd19c36 100644 --- a/mesalib/src/mesa/main/imports.h +++ b/mesalib/src/mesa/main/imports.h @@ -164,7 +164,6 @@ INV_SQRTF(float x) ***/ static inline GLfloat LOG2(GLfloat x) { -#ifdef USE_IEEE #if 0 /* This is pretty fast, but not accurate enough (only 2 fractional bits). * Based on code from http://www.stereopsis.com/log2.html @@ -186,13 +185,6 @@ static inline GLfloat LOG2(GLfloat x) num.i += 127 << 23; num.f = ((-1.0f/3) * num.f + 2) * num.f - 2.0f/3; return num.f + log_2; -#else - /* - * NOTE: log_base_2(x) = log(x) / log(2) - * NOTE: 1.442695 = 1/log(2). - */ - return (GLfloat) (log(x) * 1.442695F); -#endif } @@ -200,14 +192,7 @@ static inline GLfloat LOG2(GLfloat x) /*** *** IS_INF_OR_NAN: test if float is infinite or NaN ***/ -#ifdef USE_IEEE -static inline int IS_INF_OR_NAN( float x ) -{ - fi_type tmp; - tmp.f = x; - return !(int)((unsigned int)((tmp.i & 0x7fffffff)-0x7f800000) >> 31); -} -#elif defined(isfinite) +#if defined(isfinite) #define IS_INF_OR_NAN(x) (!isfinite(x)) #elif defined(finite) #define IS_INF_OR_NAN(x) (!finite(x)) @@ -321,7 +306,7 @@ static inline int IFLOOR(float f) __asm__ ("fstps %0" : "=m" (ai) : "t" (af) : "st"); __asm__ ("fstps %0" : "=m" (bi) : "t" (bf) : "st"); return (ai - bi) >> 1; -#elif defined(USE_IEEE) +#else int ai, bi; double af, bf; fi_type u; @@ -330,9 +315,6 @@ static inline int IFLOOR(float f) u.f = (float) af; ai = u.i; u.f = (float) bf; bi = u.i; return (ai - bi) >> 1; -#else - int i = IROUND(f); - return (i > f) ? i - 1 : i; #endif } @@ -356,7 +338,7 @@ static inline int ICEIL(float f) __asm__ ("fstps %0" : "=m" (ai) : "t" (af) : "st"); __asm__ ("fstps %0" : "=m" (bi) : "t" (bf) : "st"); return (ai - bi + 1) >> 1; -#elif defined(USE_IEEE) +#else int ai, bi; double af, bf; fi_type u; @@ -365,9 +347,6 @@ static inline int ICEIL(float f) u.f = (float) af; ai = u.i; u.f = (float) bf; bi = u.i; return (ai - bi + 1) >> 1; -#else - int i = IROUND(f); - return (i < f) ? i + 1 : i; #endif } @@ -552,6 +531,11 @@ _mesa_float_to_half(float f); extern float _mesa_half_to_float(GLhalfARB h); +static inline bool +_mesa_half_is_negative(GLhalfARB h) +{ + return h & 0x8000; +} extern void * _mesa_bsearch( const void *key, const void *base, size_t nmemb, size_t size, diff --git a/mesalib/src/mesa/main/macros.h b/mesalib/src/mesa/main/macros.h index 5228c3a8f..0ba658a9a 100644 --- a/mesalib/src/mesa/main/macros.h +++ b/mesalib/src/mesa/main/macros.h @@ -140,7 +140,7 @@ extern GLfloat _mesa_ubyte_to_float_color_tab[256]; *** UNCLAMPED_FLOAT_TO_UBYTE: clamp float to [0,1] and map to ubyte in [0,255] *** CLAMPED_FLOAT_TO_UBYTE: map float known to be in [0,1] to ubyte in [0,255] ***/ -#if defined(USE_IEEE) && !defined(DEBUG) +#ifndef DEBUG /* This function/macro is sensitive to precision. Test very carefully * if you change it! */ @@ -818,7 +818,9 @@ DIFFERENT_SIGNS(GLfloat x, GLfloat y) #define ENUM_TO_BOOLEAN(E) ((E) ? GL_TRUE : GL_FALSE) /* Compute the size of an array */ -#define ARRAY_SIZE(x) (sizeof(x) / sizeof(x[0])) +#ifndef ARRAY_SIZE +# define ARRAY_SIZE(x) (sizeof(x) / sizeof(x[0])) +#endif /* Stringify */ #define STRINGIFY(x) #x diff --git a/mesalib/src/mesa/main/mtypes.h b/mesalib/src/mesa/main/mtypes.h index 3f60a5530..e141ac658 100644 --- a/mesalib/src/mesa/main/mtypes.h +++ b/mesalib/src/mesa/main/mtypes.h @@ -1693,6 +1693,9 @@ struct gl_array_attrib /** One of the DRAW_xxx flags, not consumed by drivers */ gl_draw_method DrawMethod; + + /** Legal array datatypes */ + GLbitfield LegalTypesMask; }; @@ -2048,13 +2051,31 @@ typedef enum */ typedef enum { - SYSTEM_VALUE_FRONT_FACE, /**< Fragment shader only (not done yet) */ - SYSTEM_VALUE_VERTEX_ID, /**< Vertex shader only */ - SYSTEM_VALUE_INSTANCE_ID, /**< Vertex shader only */ - SYSTEM_VALUE_SAMPLE_ID, /**< Fragment shader only */ - SYSTEM_VALUE_SAMPLE_POS, /**< Fragment shader only */ - SYSTEM_VALUE_SAMPLE_MASK_IN, /**< Fragment shader only */ - SYSTEM_VALUE_INVOCATION_ID, /**< Geometry shader only */ + /** + * \name Vertex shader system values + */ + /*@{*/ + SYSTEM_VALUE_VERTEX_ID, + SYSTEM_VALUE_INSTANCE_ID, + /*@}*/ + + /** + * \name Geometry shader system values + */ + /*@{*/ + SYSTEM_VALUE_INVOCATION_ID, + /*@}*/ + + /** + * \name Fragment shader system values + */ + /*@{*/ + SYSTEM_VALUE_FRONT_FACE, /**< (not done yet) */ + SYSTEM_VALUE_SAMPLE_ID, + SYSTEM_VALUE_SAMPLE_POS, + SYSTEM_VALUE_SAMPLE_MASK_IN, + /*@}*/ + SYSTEM_VALUE_MAX /**< Number of values */ } gl_system_value; @@ -3531,6 +3552,7 @@ struct gl_extensions GLboolean ARB_color_buffer_float; GLboolean ARB_compute_shader; GLboolean ARB_conservative_depth; + GLboolean ARB_copy_image; GLboolean ARB_depth_buffer_float; GLboolean ARB_depth_clamp; GLboolean ARB_depth_texture; diff --git a/mesalib/src/mesa/main/performance_monitor.c b/mesalib/src/mesa/main/performance_monitor.c index c26eda4c6..c02910e31 100644 --- a/mesalib/src/mesa/main/performance_monitor.c +++ b/mesalib/src/mesa/main/performance_monitor.c @@ -43,7 +43,7 @@ #include "mtypes.h" #include "performance_monitor.h" #include "bitset.h" -#include "ralloc.h" +#include "util/ralloc.h" void _mesa_init_performance_monitors(struct gl_context *ctx) diff --git a/mesalib/src/mesa/main/pipelineobj.c b/mesalib/src/mesa/main/pipelineobj.c index 90c1d005f..017d4257e 100644 --- a/mesalib/src/mesa/main/pipelineobj.c +++ b/mesalib/src/mesa/main/pipelineobj.c @@ -44,7 +44,7 @@ #include "main/uniforms.h" #include "program/program.h" #include "program/prog_parameter.h" -#include "ralloc.h" +#include "util/ralloc.h" #include <stdbool.h> #include "../glsl/glsl_parser_extras.h" #include "../glsl/ir_uniform.h" diff --git a/mesalib/src/mesa/main/set.c b/mesalib/src/mesa/main/set.c index 989e5dece..52c1dabd8 100644 --- a/mesalib/src/mesa/main/set.c +++ b/mesalib/src/mesa/main/set.c @@ -36,7 +36,7 @@ #include "macros.h" #include "set.h" -#include "ralloc.h" +#include "util/ralloc.h" /* * From Knuth -- a good choice for hash/rehash values is p, p-2 where diff --git a/mesalib/src/mesa/main/shaderapi.c b/mesalib/src/mesa/main/shaderapi.c index 2bbef35d3..b4a5e7050 100644 --- a/mesalib/src/mesa/main/shaderapi.c +++ b/mesalib/src/mesa/main/shaderapi.c @@ -42,7 +42,6 @@ #include "main/dispatch.h" #include "main/enums.h" #include "main/hash.h" -#include "main/hash_table.h" #include "main/mtypes.h" #include "main/pipelineobj.h" #include "main/shaderapi.h" @@ -52,7 +51,8 @@ #include "program/program.h" #include "program/prog_print.h" #include "program/prog_parameter.h" -#include "ralloc.h" +#include "util/ralloc.h" +#include "util/hash_table.h" #include <stdbool.h> #include "../glsl/glsl_parser_extras.h" #include "../glsl/ir.h" diff --git a/mesalib/src/mesa/main/shaderobj.c b/mesalib/src/mesa/main/shaderobj.c index b9feff4a4..693e9a259 100644 --- a/mesalib/src/mesa/main/shaderobj.c +++ b/mesalib/src/mesa/main/shaderobj.c @@ -40,7 +40,7 @@ #include "program/program.h" #include "program/prog_parameter.h" #include "program/hash_table.h" -#include "ralloc.h" +#include "util/ralloc.h" /**********************************************************************/ /*** Shader object functions ***/ diff --git a/mesalib/src/mesa/main/shared.c b/mesalib/src/mesa/main/shared.c index 5ae7014b1..0189dd296 100644 --- a/mesalib/src/mesa/main/shared.c +++ b/mesalib/src/mesa/main/shared.c @@ -30,7 +30,6 @@ #include "imports.h" #include "mtypes.h" #include "hash.h" -#include "hash_table.h" #include "atifragshader.h" #include "bufferobj.h" #include "shared.h" @@ -42,6 +41,7 @@ #include "shaderobj.h" #include "syncobj.h" +#include "util/hash_table.h" /** * Allocate and initialize a shared context state structure. diff --git a/mesalib/src/mesa/main/syncobj.c b/mesalib/src/mesa/main/syncobj.c index a88d7e469..225399eda 100644 --- a/mesalib/src/mesa/main/syncobj.c +++ b/mesalib/src/mesa/main/syncobj.c @@ -64,7 +64,7 @@ #include "dispatch.h" #include "mtypes.h" #include "set.h" -#include "hash_table.h" +#include "util/hash_table.h" #include "syncobj.h" diff --git a/mesalib/src/mesa/main/texcompress_etc.c b/mesalib/src/mesa/main/texcompress_etc.c index ae973b001..98b4fe201 100644 --- a/mesalib/src/mesa/main/texcompress_etc.c +++ b/mesalib/src/mesa/main/texcompress_etc.c @@ -43,6 +43,7 @@ #include "texstore.h" #include "macros.h" #include "format_unpack.h" +#include "util/format_srgb.h" struct etc2_block { @@ -1307,9 +1308,9 @@ fetch_etc2_srgb8(const GLubyte *map, etc2_rgb8_fetch_texel(&block, i % 4, j % 4, dst, false /* punchthrough_alpha */); - texel[RCOMP] = _mesa_nonlinear_to_linear(dst[0]); - texel[GCOMP] = _mesa_nonlinear_to_linear(dst[1]); - texel[BCOMP] = _mesa_nonlinear_to_linear(dst[2]); + texel[RCOMP] = util_format_srgb_8unorm_to_linear_float(dst[0]); + texel[GCOMP] = util_format_srgb_8unorm_to_linear_float(dst[1]); + texel[BCOMP] = util_format_srgb_8unorm_to_linear_float(dst[2]); texel[ACOMP] = 1.0f; } @@ -1345,9 +1346,9 @@ fetch_etc2_srgb8_alpha8_eac(const GLubyte *map, etc2_rgba8_parse_block(&block, src); etc2_rgba8_fetch_texel(&block, i % 4, j % 4, dst); - texel[RCOMP] = _mesa_nonlinear_to_linear(dst[0]); - texel[GCOMP] = _mesa_nonlinear_to_linear(dst[1]); - texel[BCOMP] = _mesa_nonlinear_to_linear(dst[2]); + texel[RCOMP] = util_format_srgb_8unorm_to_linear_float(dst[0]); + texel[GCOMP] = util_format_srgb_8unorm_to_linear_float(dst[1]); + texel[BCOMP] = util_format_srgb_8unorm_to_linear_float(dst[2]); texel[ACOMP] = UBYTE_TO_FLOAT(dst[3]); } @@ -1473,9 +1474,9 @@ fetch_etc2_srgb8_punchthrough_alpha1(const GLubyte *map, true /* punchthrough alpha */); etc2_rgb8_fetch_texel(&block, i % 4, j % 4, dst, true /* punchthrough alpha */); - texel[RCOMP] = _mesa_nonlinear_to_linear(dst[0]); - texel[GCOMP] = _mesa_nonlinear_to_linear(dst[1]); - texel[BCOMP] = _mesa_nonlinear_to_linear(dst[2]); + texel[RCOMP] = util_format_srgb_8unorm_to_linear_float(dst[0]); + texel[GCOMP] = util_format_srgb_8unorm_to_linear_float(dst[1]); + texel[BCOMP] = util_format_srgb_8unorm_to_linear_float(dst[2]); texel[ACOMP] = UBYTE_TO_FLOAT(dst[3]); } diff --git a/mesalib/src/mesa/main/texcompress_s3tc.c b/mesalib/src/mesa/main/texcompress_s3tc.c index 894c46de1..5b275efe0 100644 --- a/mesalib/src/mesa/main/texcompress_s3tc.c +++ b/mesalib/src/mesa/main/texcompress_s3tc.c @@ -44,6 +44,7 @@ #include "texcompress_s3tc.h" #include "texstore.h" #include "format_unpack.h" +#include "util/format_srgb.h" #if defined(_WIN32) || defined(WIN32) @@ -419,9 +420,9 @@ fetch_srgb_dxt1(const GLubyte *map, if (fetch_ext_rgb_dxt1) { GLubyte tex[4]; fetch_ext_rgb_dxt1(rowStride, map, i, j, tex); - texel[RCOMP] = _mesa_nonlinear_to_linear(tex[RCOMP]); - texel[GCOMP] = _mesa_nonlinear_to_linear(tex[GCOMP]); - texel[BCOMP] = _mesa_nonlinear_to_linear(tex[BCOMP]); + texel[RCOMP] = util_format_srgb_8unorm_to_linear_float(tex[RCOMP]); + texel[GCOMP] = util_format_srgb_8unorm_to_linear_float(tex[GCOMP]); + texel[BCOMP] = util_format_srgb_8unorm_to_linear_float(tex[BCOMP]); texel[ACOMP] = UBYTE_TO_FLOAT(tex[ACOMP]); } else { @@ -436,9 +437,9 @@ fetch_srgba_dxt1(const GLubyte *map, if (fetch_ext_rgba_dxt1) { GLubyte tex[4]; fetch_ext_rgba_dxt1(rowStride, map, i, j, tex); - texel[RCOMP] = _mesa_nonlinear_to_linear(tex[RCOMP]); - texel[GCOMP] = _mesa_nonlinear_to_linear(tex[GCOMP]); - texel[BCOMP] = _mesa_nonlinear_to_linear(tex[BCOMP]); + texel[RCOMP] = util_format_srgb_8unorm_to_linear_float(tex[RCOMP]); + texel[GCOMP] = util_format_srgb_8unorm_to_linear_float(tex[GCOMP]); + texel[BCOMP] = util_format_srgb_8unorm_to_linear_float(tex[BCOMP]); texel[ACOMP] = UBYTE_TO_FLOAT(tex[ACOMP]); } else { @@ -453,9 +454,9 @@ fetch_srgba_dxt3(const GLubyte *map, if (fetch_ext_rgba_dxt3) { GLubyte tex[4]; fetch_ext_rgba_dxt3(rowStride, map, i, j, tex); - texel[RCOMP] = _mesa_nonlinear_to_linear(tex[RCOMP]); - texel[GCOMP] = _mesa_nonlinear_to_linear(tex[GCOMP]); - texel[BCOMP] = _mesa_nonlinear_to_linear(tex[BCOMP]); + texel[RCOMP] = util_format_srgb_8unorm_to_linear_float(tex[RCOMP]); + texel[GCOMP] = util_format_srgb_8unorm_to_linear_float(tex[GCOMP]); + texel[BCOMP] = util_format_srgb_8unorm_to_linear_float(tex[BCOMP]); texel[ACOMP] = UBYTE_TO_FLOAT(tex[ACOMP]); } else { @@ -470,9 +471,9 @@ fetch_srgba_dxt5(const GLubyte *map, if (fetch_ext_rgba_dxt5) { GLubyte tex[4]; fetch_ext_rgba_dxt5(rowStride, map, i, j, tex); - texel[RCOMP] = _mesa_nonlinear_to_linear(tex[RCOMP]); - texel[GCOMP] = _mesa_nonlinear_to_linear(tex[GCOMP]); - texel[BCOMP] = _mesa_nonlinear_to_linear(tex[BCOMP]); + texel[RCOMP] = util_format_srgb_8unorm_to_linear_float(tex[RCOMP]); + texel[GCOMP] = util_format_srgb_8unorm_to_linear_float(tex[GCOMP]); + texel[BCOMP] = util_format_srgb_8unorm_to_linear_float(tex[BCOMP]); texel[ACOMP] = UBYTE_TO_FLOAT(tex[ACOMP]); } else { diff --git a/mesalib/src/mesa/main/teximage.c b/mesalib/src/mesa/main/teximage.c index fb2dee7d8..bb050b188 100644 --- a/mesalib/src/mesa/main/teximage.c +++ b/mesalib/src/mesa/main/teximage.c @@ -1770,9 +1770,9 @@ compressedteximage_only_format(const struct gl_context *ctx, GLenum format) * Helper function to determine whether a target and specific compression * format are supported. */ -static GLboolean -target_can_be_compressed(const struct gl_context *ctx, GLenum target, - GLenum intFormat) +GLboolean +_mesa_target_can_be_compressed(const struct gl_context *ctx, GLenum target, + GLenum intFormat) { (void) intFormat; /* not used yet */ @@ -1781,6 +1781,7 @@ target_can_be_compressed(const struct gl_context *ctx, GLenum target, case GL_PROXY_TEXTURE_2D: return GL_TRUE; /* true for any compressed format so far */ case GL_PROXY_TEXTURE_CUBE_MAP: + case GL_TEXTURE_CUBE_MAP: case GL_TEXTURE_CUBE_MAP_POSITIVE_X: case GL_TEXTURE_CUBE_MAP_NEGATIVE_X: case GL_TEXTURE_CUBE_MAP_POSITIVE_Y: @@ -2211,7 +2212,7 @@ texture_error_check( struct gl_context *ctx, /* additional checks for compressed textures */ if (_mesa_is_compressed_format(ctx, internalFormat)) { - if (!target_can_be_compressed(ctx, target, internalFormat)) { + if (!_mesa_target_can_be_compressed(ctx, target, internalFormat)) { _mesa_error(ctx, GL_INVALID_ENUM, "glTexImage%dD(target can't be compressed)", dimensions); return GL_TRUE; @@ -2297,9 +2298,16 @@ compressed_texture_error_check(struct gl_context *ctx, GLint dimensions, GLenum error = GL_NO_ERROR; char *reason = ""; /* no error */ - if (!target_can_be_compressed(ctx, target, internalFormat)) { + if (!_mesa_target_can_be_compressed(ctx, target, internalFormat)) { reason = "target"; - error = GL_INVALID_ENUM; + /* From section 3.8.6, page 146 of OpenGL ES 3.0 spec: + * + * "The ETC2/EAC texture compression algorithm supports only + * two-dimensional images. If internalformat is an ETC2/EAC format, + * CompressedTexImage3D will generate an INVALID_OPERATION error if + * target is not TEXTURE_2D_ARRAY." + */ + error = _mesa_is_desktop_gl(ctx) ? GL_INVALID_ENUM : GL_INVALID_OPERATION; goto error; } @@ -2704,6 +2712,17 @@ copytexture_error_check( struct gl_context *ctx, GLuint dimensions, "glCopyTexImage%dD(srgb usage mismatch)", dimensions); return GL_TRUE; } + + /* Page 139, Table 3.15 of OpenGL ES 3.0 spec does not define ReadPixels + * types for SNORM formats. Also, conversion to SNORM formats is not + * allowed by Table 3.2 on Page 110. + */ + if(_mesa_is_enum_format_snorm(internalFormat)) { + _mesa_error(ctx, GL_INVALID_OPERATION, + "glCopyTexImage%dD(internalFormat=%s)", dimensions, + _mesa_lookup_enum_by_nr(internalFormat)); + return GL_TRUE; + } } if (!_mesa_source_buffer_exists(ctx, baseFormat)) { @@ -2722,6 +2741,8 @@ copytexture_error_check( struct gl_context *ctx, GLuint dimensions, if (_mesa_is_color_format(internalFormat)) { bool is_int = _mesa_is_enum_format_integer(internalFormat); bool is_rbint = _mesa_is_enum_format_integer(rb_internal_format); + bool is_unorm = _mesa_is_enum_format_unorm(internalFormat); + bool is_rbunorm = _mesa_is_enum_format_unorm(rb_internal_format); if (is_int || is_rbint) { if (is_int != is_rbint) { _mesa_error(ctx, GL_INVALID_OPERATION, @@ -2735,10 +2756,23 @@ copytexture_error_check( struct gl_context *ctx, GLuint dimensions, return GL_TRUE; } } + + /* From page 138 of OpenGL ES 3.0 spec: + * "The error INVALID_OPERATION is generated if floating-point RGBA + * data is required; if signed integer RGBA data is required and the + * format of the current color buffer is not signed integer; if + * unsigned integer RGBA data is required and the format of the + * current color buffer is not unsigned integer; or if fixed-point + * RGBA data is required and the format of the current color buffer + * is not fixed-point. + */ + if (_mesa_is_gles(ctx) && is_unorm != is_rbunorm) + _mesa_error(ctx, GL_INVALID_OPERATION, + "glCopyTexImage%dD(unorm vs non-unorm)", dimensions); } if (_mesa_is_compressed_format(ctx, internalFormat)) { - if (!target_can_be_compressed(ctx, target, internalFormat)) { + if (!_mesa_target_can_be_compressed(ctx, target, internalFormat)) { _mesa_error(ctx, GL_INVALID_ENUM, "glCopyTexImage%dD(target)", dimensions); return GL_TRUE; @@ -3608,6 +3642,28 @@ copytexsubimage_by_slice(struct gl_context *ctx, } } +static GLboolean +formats_differ_in_component_sizes (mesa_format f1, + mesa_format f2) +{ + GLint f1_r_bits = _mesa_get_format_bits(f1, GL_RED_BITS); + GLint f1_g_bits = _mesa_get_format_bits(f1, GL_GREEN_BITS); + GLint f1_b_bits = _mesa_get_format_bits(f1, GL_BLUE_BITS); + GLint f1_a_bits = _mesa_get_format_bits(f1, GL_ALPHA_BITS); + + GLint f2_r_bits = _mesa_get_format_bits(f2, GL_RED_BITS); + GLint f2_g_bits = _mesa_get_format_bits(f2, GL_GREEN_BITS); + GLint f2_b_bits = _mesa_get_format_bits(f2, GL_BLUE_BITS); + GLint f2_a_bits = _mesa_get_format_bits(f2, GL_ALPHA_BITS); + + if ((f1_r_bits && f2_r_bits && f1_r_bits != f2_r_bits) + || (f1_g_bits && f2_g_bits && f1_g_bits != f2_g_bits) + || (f1_b_bits && f2_b_bits && f1_b_bits != f2_b_bits) + || (f1_a_bits && f2_a_bits && f1_a_bits != f2_a_bits)) + return GL_TRUE; + + return GL_FALSE; +} /** * Implement the glCopyTexImage1/2D() functions. @@ -3621,6 +3677,7 @@ copyteximage(struct gl_context *ctx, GLuint dims, struct gl_texture_image *texImage; const GLuint face = _mesa_tex_target_to_face(target); mesa_format texFormat; + struct gl_renderbuffer *rb; FLUSH_VERTICES(ctx, 0); @@ -3650,6 +3707,40 @@ copyteximage(struct gl_context *ctx, GLuint dims, texFormat = _mesa_choose_texture_format(ctx, texObj, target, level, internalFormat, GL_NONE, GL_NONE); + + rb = _mesa_get_read_renderbuffer_for_format(ctx, internalFormat); + + if (_mesa_is_gles3(ctx)) { + if (_mesa_is_enum_format_unsized(internalFormat)) { + /* Conversion from GL_RGB10_A2 source buffer format is not allowed in + * OpenGL ES 3.0. Khronos bug# 9807. + */ + if (rb->InternalFormat == GL_RGB10_A2) { + _mesa_error(ctx, GL_INVALID_OPERATION, + "glCopyTexImage%uD(Reading from GL_RGB10_A2 buffer and" + " writing to unsized internal format)", dims); + return; + } + } + /* From Page 139 of OpenGL ES 3.0 spec: + * "If internalformat is sized, the internal format of the new texel + * array is internalformat, and this is also the new texel array’s + * effective internal format. If the component sizes of internalformat + * do not exactly match the corresponding component sizes of the source + * buffer’s effective internal format, described below, an + * INVALID_OPERATION error is generated. If internalformat is unsized, + * the internal format of the new texel array is the effective internal + * format of the source buffer, and this is also the new texel array’s + * effective internal format. + */ + else if (formats_differ_in_component_sizes (texFormat, rb->Format)) { + _mesa_error(ctx, GL_INVALID_OPERATION, + "glCopyTexImage%uD(componenet size changed in" + " internal format)", dims); + return; + } + } + assert(texFormat != MESA_FORMAT_NONE); if (!ctx->Driver.TestProxyTexImage(ctx, proxy_target(target), diff --git a/mesalib/src/mesa/main/teximage.h b/mesalib/src/mesa/main/teximage.h index 42305f44f..52bfa7816 100644 --- a/mesalib/src/mesa/main/teximage.h +++ b/mesalib/src/mesa/main/teximage.h @@ -123,6 +123,9 @@ _mesa_test_proxy_teximage(struct gl_context *ctx, GLenum target, GLint level, mesa_format format, GLint width, GLint height, GLint depth, GLint border); +extern GLboolean +_mesa_target_can_be_compressed(const struct gl_context *ctx, GLenum target, + GLenum intFormat); extern GLuint _mesa_tex_target_to_face(GLenum target); diff --git a/mesalib/src/mesa/main/texstorage.c b/mesalib/src/mesa/main/texstorage.c index 86c8f3c92..897d5891a 100644 --- a/mesalib/src/mesa/main/texstorage.c +++ b/mesalib/src/mesa/main/texstorage.c @@ -41,6 +41,7 @@ #include "texstorage.h" #include "textureview.h" #include "mtypes.h" +#include "glformats.h" @@ -53,6 +54,13 @@ static GLboolean legal_texobj_target(struct gl_context *ctx, GLuint dims, GLenum target) { + if (_mesa_is_gles3(ctx) + && target != GL_TEXTURE_2D + && target != GL_TEXTURE_CUBE_MAP + && target != GL_TEXTURE_3D + && target != GL_TEXTURE_2D_ARRAY) + return GL_FALSE; + switch (dims) { case 1: switch (target) { @@ -294,6 +302,23 @@ tex_storage_error_check(struct gl_context *ctx, GLuint dims, GLenum target, return GL_TRUE; } + /* From section 3.8.6, page 146 of OpenGL ES 3.0 spec: + * + * "The ETC2/EAC texture compression algorithm supports only + * two-dimensional images. If internalformat is an ETC2/EAC format, + * CompressedTexImage3D will generate an INVALID_OPERATION error if + * target is not TEXTURE_2D_ARRAY." + * + * This should also be applicable for glTexStorage3D(). + */ + if (_mesa_is_compressed_format(ctx, internalformat) + && !_mesa_target_can_be_compressed(ctx, target, internalformat)) { + _mesa_error(ctx, _mesa_is_desktop_gl(ctx)? + GL_INVALID_ENUM : GL_INVALID_OPERATION, + "glTexStorage3D(internalformat = %s)", + _mesa_lookup_enum_by_nr(internalformat)); + } + /* levels check */ if (levels < 1) { _mesa_error(ctx, GL_INVALID_VALUE, "glTexStorage%uD(levels < 1)", diff --git a/mesalib/src/mesa/main/texstore.c b/mesalib/src/mesa/main/texstore.c index aea53f8d1..0e036d9eb 100644 --- a/mesalib/src/mesa/main/texstore.c +++ b/mesalib/src/mesa/main/texstore.c @@ -55,6 +55,7 @@ #include "bufferobj.h" #include "colormac.h" #include "format_pack.h" +#include "format_utils.h" #include "image.h" #include "macros.h" #include "mipmap.h" @@ -87,35 +88,6 @@ enum { typedef GLboolean (*StoreTexImageFunc)(TEXSTORE_PARAMS); -/** - * Return GL_TRUE if the given image format is one that be converted - * to another format by swizzling. - */ -static GLboolean -can_swizzle(GLenum logicalBaseFormat) -{ - switch (logicalBaseFormat) { - case GL_RGBA: - case GL_RGB: - case GL_LUMINANCE_ALPHA: - case GL_INTENSITY: - case GL_ALPHA: - case GL_LUMINANCE: - case GL_RED: - case GL_GREEN: - case GL_BLUE: - case GL_BGR: - case GL_BGRA: - case GL_ABGR_EXT: - case GL_RG: - return GL_TRUE; - default: - return GL_FALSE; - } -} - - - enum { IDX_LUMINANCE = 0, IDX_ALPHA, @@ -233,21 +205,44 @@ static int get_map_idx(GLenum value) { switch (value) { - case GL_LUMINANCE: return IDX_LUMINANCE; - case GL_ALPHA: return IDX_ALPHA; - case GL_INTENSITY: return IDX_INTENSITY; - case GL_LUMINANCE_ALPHA: return IDX_LUMINANCE_ALPHA; - case GL_RGB: return IDX_RGB; - case GL_RGBA: return IDX_RGBA; - case GL_RED: return IDX_RED; - case GL_GREEN: return IDX_GREEN; - case GL_BLUE: return IDX_BLUE; - case GL_BGR: return IDX_BGR; - case GL_BGRA: return IDX_BGRA; - case GL_ABGR_EXT: return IDX_ABGR; - case GL_RG: return IDX_RG; + case GL_LUMINANCE: + case GL_LUMINANCE_INTEGER_EXT: + return IDX_LUMINANCE; + case GL_ALPHA: + case GL_ALPHA_INTEGER: + return IDX_ALPHA; + case GL_INTENSITY: + return IDX_INTENSITY; + case GL_LUMINANCE_ALPHA: + case GL_LUMINANCE_ALPHA_INTEGER_EXT: + return IDX_LUMINANCE_ALPHA; + case GL_RGB: + case GL_RGB_INTEGER: + return IDX_RGB; + case GL_RGBA: + case GL_RGBA_INTEGER: + return IDX_RGBA; + case GL_RED: + case GL_RED_INTEGER: + return IDX_RED; + case GL_GREEN: + return IDX_GREEN; + case GL_BLUE: + return IDX_BLUE; + case GL_BGR: + case GL_BGR_INTEGER: + return IDX_BGR; + case GL_BGRA: + case GL_BGRA_INTEGER: + return IDX_BGRA; + case GL_ABGR_EXT: + return IDX_ABGR; + case GL_RG: + case GL_RG_INTEGER: + return IDX_RG; default: - _mesa_problem(NULL, "Unexpected inFormat"); + _mesa_problem(NULL, "Unexpected inFormat %s", + _mesa_lookup_enum_by_nr(value)); return 0; } } @@ -662,257 +657,9 @@ _mesa_make_temp_ubyte_image(struct gl_context *ctx, GLuint dims, } -/** - * Copy GLubyte pixels from <src> to <dst> with swizzling. - * \param dst destination pixels - * \param dstComponents number of color components in destination pixels - * \param src source pixels - * \param srcComponents number of color components in source pixels - * \param map the swizzle mapping. map[X] says where to find the X component - * in the source image's pixels. For example, if the source image - * is GL_BGRA and X = red, map[0] yields 2. - * \param count number of pixels to copy/swizzle. - */ -static void -swizzle_copy(GLubyte *dst, GLuint dstComponents, const GLubyte *src, - GLuint srcComponents, const GLubyte *map, GLuint count) -{ -#define SWZ_CPY(dst, src, count, dstComps, srcComps) \ - do { \ - GLuint i; \ - for (i = 0; i < count; i++) { \ - GLuint j; \ - if (srcComps == 4) { \ - COPY_4UBV(tmp, src); \ - } \ - else { \ - for (j = 0; j < srcComps; j++) { \ - tmp[j] = src[j]; \ - } \ - } \ - src += srcComps; \ - for (j = 0; j < dstComps; j++) { \ - dst[j] = tmp[map[j]]; \ - } \ - dst += dstComps; \ - } \ - } while (0) - - GLubyte tmp[6]; - - tmp[ZERO] = 0x0; - tmp[ONE] = 0xff; - - ASSERT(srcComponents <= 4); - ASSERT(dstComponents <= 4); - - switch (dstComponents) { - case 4: - switch (srcComponents) { - case 4: - SWZ_CPY(dst, src, count, 4, 4); - break; - case 3: - SWZ_CPY(dst, src, count, 4, 3); - break; - case 2: - SWZ_CPY(dst, src, count, 4, 2); - break; - case 1: - SWZ_CPY(dst, src, count, 4, 1); - break; - default: - ; - } - break; - case 3: - switch (srcComponents) { - case 4: - SWZ_CPY(dst, src, count, 3, 4); - break; - case 3: - SWZ_CPY(dst, src, count, 3, 3); - break; - case 2: - SWZ_CPY(dst, src, count, 3, 2); - break; - case 1: - SWZ_CPY(dst, src, count, 3, 1); - break; - default: - ; - } - break; - case 2: - switch (srcComponents) { - case 4: - SWZ_CPY(dst, src, count, 2, 4); - break; - case 3: - SWZ_CPY(dst, src, count, 2, 3); - break; - case 2: - SWZ_CPY(dst, src, count, 2, 2); - break; - case 1: - SWZ_CPY(dst, src, count, 2, 1); - break; - default: - ; - } - break; - case 1: - switch (srcComponents) { - case 4: - SWZ_CPY(dst, src, count, 1, 4); - break; - case 3: - SWZ_CPY(dst, src, count, 1, 3); - break; - case 2: - SWZ_CPY(dst, src, count, 1, 2); - break; - case 1: - SWZ_CPY(dst, src, count, 1, 1); - break; - default: - ; - } - break; - default: - ; - } -#undef SWZ_CPY -} - - - static const GLubyte map_identity[6] = { 0, 1, 2, 3, ZERO, ONE }; static const GLubyte map_3210[6] = { 3, 2, 1, 0, ZERO, ONE }; - - -/** - * For 1-byte/pixel formats (or 8_8_8_8 packed formats), return a - * mapping array depending on endianness. - */ -static const GLubyte * -type_mapping( GLenum srcType ) -{ - switch (srcType) { - case GL_BYTE: - case GL_UNSIGNED_BYTE: - return map_identity; - case GL_UNSIGNED_INT_8_8_8_8: - return _mesa_little_endian() ? map_3210 : map_identity; - case GL_UNSIGNED_INT_8_8_8_8_REV: - return _mesa_little_endian() ? map_identity : map_3210; - default: - return NULL; - } -} - - -/** - * For 1-byte/pixel formats (or 8_8_8_8 packed formats), return a - * mapping array depending on pixelstore byte swapping state. - */ -static const GLubyte * -byteswap_mapping( GLboolean swapBytes, - GLenum srcType ) -{ - if (!swapBytes) - return map_identity; - - switch (srcType) { - case GL_BYTE: - case GL_UNSIGNED_BYTE: - return map_identity; - case GL_UNSIGNED_INT_8_8_8_8: - case GL_UNSIGNED_INT_8_8_8_8_REV: - return map_3210; - default: - return NULL; - } -} - - - -/** - * Transfer a GLubyte texture image with component swizzling. - */ -static void -_mesa_swizzle_ubyte_image(struct gl_context *ctx, - GLuint dimensions, - GLenum srcFormat, - GLenum srcType, - - GLenum baseInternalFormat, - - const GLubyte *rgba2dst, - GLuint dstComponents, - - GLint dstRowStride, - GLubyte **dstSlices, - - GLint srcWidth, GLint srcHeight, GLint srcDepth, - const GLvoid *srcAddr, - const struct gl_pixelstore_attrib *srcPacking ) -{ - GLint srcComponents = _mesa_components_in_format(srcFormat); - const GLubyte *srctype2ubyte, *swap; - GLubyte map[4], src2base[6], base2rgba[6]; - GLint i; - const GLint srcRowStride = - _mesa_image_row_stride(srcPacking, srcWidth, - srcFormat, GL_UNSIGNED_BYTE); - const GLint srcImageStride - = _mesa_image_image_stride(srcPacking, srcWidth, srcHeight, srcFormat, - GL_UNSIGNED_BYTE); - const GLubyte *srcImage - = (const GLubyte *) _mesa_image_address(dimensions, srcPacking, srcAddr, - srcWidth, srcHeight, srcFormat, - GL_UNSIGNED_BYTE, 0, 0, 0); - - (void) ctx; - - /* Translate from src->baseInternal->GL_RGBA->dst. This will - * correctly deal with RGBA->RGB->RGBA conversions where the final - * A value must be 0xff regardless of the incoming alpha values. - */ - compute_component_mapping(srcFormat, baseInternalFormat, src2base); - compute_component_mapping(baseInternalFormat, GL_RGBA, base2rgba); - swap = byteswap_mapping(srcPacking->SwapBytes, srcType); - srctype2ubyte = type_mapping(srcType); - - - for (i = 0; i < 4; i++) - map[i] = srctype2ubyte[swap[src2base[base2rgba[rgba2dst[i]]]]]; - -/* printf("map %d %d %d %d\n", map[0], map[1], map[2], map[3]); */ - - if (srcComponents == dstComponents && - srcRowStride == dstRowStride && - srcRowStride == srcWidth * srcComponents && - dimensions < 3) { - /* 1 and 2D images only */ - GLubyte *dstImage = dstSlices[0]; - swizzle_copy(dstImage, dstComponents, srcImage, srcComponents, map, - srcWidth * srcHeight); - } - else { - GLint img, row; - for (img = 0; img < srcDepth; img++) { - const GLubyte *srcRow = srcImage; - GLubyte *dstRow = dstSlices[img]; - for (row = 0; row < srcHeight; row++) { - swizzle_copy(dstRow, dstComponents, srcRow, srcComponents, map, srcWidth); - dstRow += dstRowStride; - srcRow += srcRowStride; - } - srcImage += srcImageStride; - } - } -} +static const GLubyte map_1032[6] = { 1, 0, 3, 2, ZERO, ONE }; /** @@ -988,6 +735,10 @@ store_ubyte_texture(TEXSTORE_PARAMS) if (!tempImage) return GL_FALSE; + /* This way we will use the RGB versions of the packing functions and it + * will work for both RGB and sRGB textures*/ + dstFormat = _mesa_get_srgb_format_linear(dstFormat); + src = tempImage; for (img = 0; img < srcDepth; img++) { _mesa_pack_ubyte_rgba_rect(dstFormat, srcWidth, srcHeight, @@ -1178,845 +929,13 @@ _mesa_texstore_rgb565(TEXSTORE_PARAMS) dst += dstRowStride; src += srcRowStride; } + return GL_TRUE; + } else { + return GL_FALSE; } - else { - return store_ubyte_texture(ctx, dims, baseInternalFormat, - dstFormat, dstRowStride, dstSlices, - srcWidth, srcHeight, srcDepth, - srcFormat, srcType, srcAddr, srcPacking); - } - return GL_TRUE; -} - - -/** - * Store a texture in MESA_FORMAT_A8B8G8R8_UNORM or MESA_FORMAT_R8G8B8A8_UNORM. - */ -static GLboolean -_mesa_texstore_rgba8888(TEXSTORE_PARAMS) -{ - const GLboolean littleEndian = _mesa_little_endian(); - - ASSERT(dstFormat == MESA_FORMAT_A8B8G8R8_UNORM || - dstFormat == MESA_FORMAT_R8G8B8A8_UNORM || - dstFormat == MESA_FORMAT_X8B8G8R8_UNORM || - dstFormat == MESA_FORMAT_R8G8B8X8_UNORM); - ASSERT(_mesa_get_format_bytes(dstFormat) == 4); - - if (!ctx->_ImageTransferState && - (srcType == GL_UNSIGNED_BYTE || - srcType == GL_UNSIGNED_INT_8_8_8_8 || - srcType == GL_UNSIGNED_INT_8_8_8_8_REV) && - can_swizzle(baseInternalFormat) && - can_swizzle(srcFormat)) { - - GLubyte dstmap[4]; - - /* dstmap - how to swizzle from RGBA to dst format: - */ - if ((littleEndian && (dstFormat == MESA_FORMAT_A8B8G8R8_UNORM || - dstFormat == MESA_FORMAT_X8B8G8R8_UNORM)) || - (!littleEndian && (dstFormat == MESA_FORMAT_R8G8B8A8_UNORM || - dstFormat == MESA_FORMAT_R8G8B8X8_UNORM))) { - dstmap[3] = 0; - dstmap[2] = 1; - dstmap[1] = 2; - dstmap[0] = 3; - } - else { - dstmap[3] = 3; - dstmap[2] = 2; - dstmap[1] = 1; - dstmap[0] = 0; - } - - _mesa_swizzle_ubyte_image(ctx, dims, - srcFormat, - srcType, - baseInternalFormat, - dstmap, 4, - dstRowStride, dstSlices, - srcWidth, srcHeight, srcDepth, srcAddr, - srcPacking); - } - else { - return store_ubyte_texture(ctx, dims, baseInternalFormat, - dstFormat, dstRowStride, dstSlices, - srcWidth, srcHeight, srcDepth, - srcFormat, srcType, srcAddr, srcPacking); - } - return GL_TRUE; -} - - -static GLboolean -_mesa_texstore_argb8888(TEXSTORE_PARAMS) -{ - const GLboolean littleEndian = _mesa_little_endian(); - - ASSERT(dstFormat == MESA_FORMAT_B8G8R8A8_UNORM || - dstFormat == MESA_FORMAT_A8R8G8B8_UNORM || - dstFormat == MESA_FORMAT_B8G8R8X8_UNORM || - dstFormat == MESA_FORMAT_X8R8G8B8_UNORM ); - ASSERT(_mesa_get_format_bytes(dstFormat) == 4); - - if (!ctx->_ImageTransferState && - !srcPacking->SwapBytes && - (dstFormat == MESA_FORMAT_B8G8R8A8_UNORM || - dstFormat == MESA_FORMAT_B8G8R8X8_UNORM) && - srcFormat == GL_RGB && - (baseInternalFormat == GL_RGBA || - baseInternalFormat == GL_RGB) && - srcType == GL_UNSIGNED_BYTE) { - int img, row, col; - for (img = 0; img < srcDepth; img++) { - const GLint srcRowStride = - _mesa_image_row_stride(srcPacking, srcWidth, srcFormat, srcType); - GLubyte *srcRow = (GLubyte *) _mesa_image_address(dims, srcPacking, - srcAddr, srcWidth, srcHeight, srcFormat, srcType, img, 0, 0); - GLubyte *dstRow = dstSlices[img]; - for (row = 0; row < srcHeight; row++) { - GLuint *d4 = (GLuint *) dstRow; - for (col = 0; col < srcWidth; col++) { - d4[col] = PACK_COLOR_8888(0xff, - srcRow[col * 3 + RCOMP], - srcRow[col * 3 + GCOMP], - srcRow[col * 3 + BCOMP]); - } - dstRow += dstRowStride; - srcRow += srcRowStride; - } - } - } - else if (!ctx->_ImageTransferState && - !srcPacking->SwapBytes && - dstFormat == MESA_FORMAT_B8G8R8A8_UNORM && - srcFormat == GL_LUMINANCE_ALPHA && - baseInternalFormat == GL_RGBA && - srcType == GL_UNSIGNED_BYTE) { - /* special case of storing LA -> ARGB8888 */ - int img, row, col; - const GLint srcRowStride = - _mesa_image_row_stride(srcPacking, srcWidth, srcFormat, srcType); - for (img = 0; img < srcDepth; img++) { - const GLubyte *srcRow = (const GLubyte *) - _mesa_image_address(dims, srcPacking, srcAddr, srcWidth, - srcHeight, srcFormat, srcType, img, 0, 0); - GLubyte *dstRow = dstSlices[img]; - for (row = 0; row < srcHeight; row++) { - GLuint *d4 = (GLuint *) dstRow; - for (col = 0; col < srcWidth; col++) { - GLubyte l = srcRow[col * 2 + 0], a = srcRow[col * 2 + 1]; - d4[col] = PACK_COLOR_8888(a, l, l, l); - } - dstRow += dstRowStride; - srcRow += srcRowStride; - } - } - } - else if (!ctx->_ImageTransferState && - !srcPacking->SwapBytes && - dstFormat == MESA_FORMAT_B8G8R8A8_UNORM && - srcFormat == GL_RGBA && - baseInternalFormat == GL_RGBA && - srcType == GL_UNSIGNED_BYTE) { - /* same as above case, but src data has alpha too */ - GLint img, row, col; - /* For some reason, streaming copies to write-combined regions - * are extremely sensitive to the characteristics of how the - * source data is retrieved. By reordering the source reads to - * be in-order, the speed of this operation increases by half. - * Strangely the same isn't required for the RGB path, above. - */ - for (img = 0; img < srcDepth; img++) { - const GLint srcRowStride = - _mesa_image_row_stride(srcPacking, srcWidth, srcFormat, srcType); - GLubyte *srcRow = (GLubyte *) _mesa_image_address(dims, srcPacking, - srcAddr, srcWidth, srcHeight, srcFormat, srcType, img, 0, 0); - GLubyte *dstRow = dstSlices[img]; - for (row = 0; row < srcHeight; row++) { - GLuint *d4 = (GLuint *) dstRow; - for (col = 0; col < srcWidth; col++) { - d4[col] = PACK_COLOR_8888(srcRow[col * 4 + ACOMP], - srcRow[col * 4 + RCOMP], - srcRow[col * 4 + GCOMP], - srcRow[col * 4 + BCOMP]); - } - dstRow += dstRowStride; - srcRow += srcRowStride; - } - } - } - else if (!ctx->_ImageTransferState && - (srcType == GL_UNSIGNED_BYTE || - srcType == GL_UNSIGNED_INT_8_8_8_8 || - srcType == GL_UNSIGNED_INT_8_8_8_8_REV) && - can_swizzle(baseInternalFormat) && - can_swizzle(srcFormat)) { - - GLubyte dstmap[4]; - - /* dstmap - how to swizzle from RGBA to dst format: - */ - if ((littleEndian && dstFormat == MESA_FORMAT_B8G8R8A8_UNORM) || - (littleEndian && dstFormat == MESA_FORMAT_B8G8R8X8_UNORM) || - (!littleEndian && dstFormat == MESA_FORMAT_A8R8G8B8_UNORM) || - (!littleEndian && dstFormat == MESA_FORMAT_X8R8G8B8_UNORM)) { - dstmap[3] = 3; /* alpha */ - dstmap[2] = 0; /* red */ - dstmap[1] = 1; /* green */ - dstmap[0] = 2; /* blue */ - } - else { - assert((littleEndian && dstFormat == MESA_FORMAT_A8R8G8B8_UNORM) || - (!littleEndian && dstFormat == MESA_FORMAT_B8G8R8A8_UNORM) || - (littleEndian && dstFormat == MESA_FORMAT_X8R8G8B8_UNORM) || - (!littleEndian && dstFormat == MESA_FORMAT_B8G8R8X8_UNORM)); - dstmap[3] = 2; - dstmap[2] = 1; - dstmap[1] = 0; - dstmap[0] = 3; - } - - _mesa_swizzle_ubyte_image(ctx, dims, - srcFormat, - srcType, - baseInternalFormat, - dstmap, 4, - dstRowStride, - dstSlices, - srcWidth, srcHeight, srcDepth, srcAddr, - srcPacking); - } - else { - return store_ubyte_texture(ctx, dims, baseInternalFormat, - dstFormat, dstRowStride, dstSlices, - srcWidth, srcHeight, srcDepth, - srcFormat, srcType, srcAddr, srcPacking); - } - return GL_TRUE; -} - - -static GLboolean -_mesa_texstore_rgb888(TEXSTORE_PARAMS) -{ - ASSERT(dstFormat == MESA_FORMAT_BGR_UNORM8); - ASSERT(_mesa_get_format_bytes(dstFormat) == 3); - - if (!ctx->_ImageTransferState && - !srcPacking->SwapBytes && - srcFormat == GL_RGBA && - srcType == GL_UNSIGNED_BYTE) { - /* extract RGB from RGBA */ - GLint img, row, col; - for (img = 0; img < srcDepth; img++) { - const GLint srcRowStride = - _mesa_image_row_stride(srcPacking, srcWidth, srcFormat, srcType); - GLubyte *srcRow = (GLubyte *) _mesa_image_address(dims, srcPacking, - srcAddr, srcWidth, srcHeight, srcFormat, srcType, img, 0, 0); - GLubyte *dstRow = dstSlices[img]; - for (row = 0; row < srcHeight; row++) { - for (col = 0; col < srcWidth; col++) { - dstRow[col * 3 + 0] = srcRow[col * 4 + BCOMP]; - dstRow[col * 3 + 1] = srcRow[col * 4 + GCOMP]; - dstRow[col * 3 + 2] = srcRow[col * 4 + RCOMP]; - } - dstRow += dstRowStride; - srcRow += srcRowStride; - } - } - } - else if (!ctx->_ImageTransferState && - srcType == GL_UNSIGNED_BYTE && - can_swizzle(baseInternalFormat) && - can_swizzle(srcFormat)) { - - GLubyte dstmap[4]; - - /* dstmap - how to swizzle from RGBA to dst format: - */ - dstmap[0] = 2; - dstmap[1] = 1; - dstmap[2] = 0; - dstmap[3] = ONE; /* ? */ - - _mesa_swizzle_ubyte_image(ctx, dims, - srcFormat, - srcType, - baseInternalFormat, - dstmap, 3, - dstRowStride, dstSlices, - srcWidth, srcHeight, srcDepth, srcAddr, - srcPacking); - } - else { - return store_ubyte_texture(ctx, dims, baseInternalFormat, - dstFormat, dstRowStride, dstSlices, - srcWidth, srcHeight, srcDepth, - srcFormat, srcType, srcAddr, srcPacking); - } - return GL_TRUE; -} - - -static GLboolean -_mesa_texstore_bgr888(TEXSTORE_PARAMS) -{ - ASSERT(dstFormat == MESA_FORMAT_RGB_UNORM8); - ASSERT(_mesa_get_format_bytes(dstFormat) == 3); - - if (!ctx->_ImageTransferState && - !srcPacking->SwapBytes && - srcFormat == GL_RGBA && - srcType == GL_UNSIGNED_BYTE) { - /* extract BGR from RGBA */ - int img, row, col; - for (img = 0; img < srcDepth; img++) { - const GLint srcRowStride = - _mesa_image_row_stride(srcPacking, srcWidth, srcFormat, srcType); - GLubyte *srcRow = (GLubyte *) _mesa_image_address(dims, srcPacking, - srcAddr, srcWidth, srcHeight, srcFormat, srcType, img, 0, 0); - GLubyte *dstRow = dstSlices[img]; - for (row = 0; row < srcHeight; row++) { - for (col = 0; col < srcWidth; col++) { - dstRow[col * 3 + 0] = srcRow[col * 4 + RCOMP]; - dstRow[col * 3 + 1] = srcRow[col * 4 + GCOMP]; - dstRow[col * 3 + 2] = srcRow[col * 4 + BCOMP]; - } - dstRow += dstRowStride; - srcRow += srcRowStride; - } - } - } - else if (!ctx->_ImageTransferState && - srcType == GL_UNSIGNED_BYTE && - can_swizzle(baseInternalFormat) && - can_swizzle(srcFormat)) { - - GLubyte dstmap[4]; - - /* dstmap - how to swizzle from RGBA to dst format: - */ - dstmap[0] = 0; - dstmap[1] = 1; - dstmap[2] = 2; - dstmap[3] = ONE; /* ? */ - - _mesa_swizzle_ubyte_image(ctx, dims, - srcFormat, - srcType, - baseInternalFormat, - dstmap, 3, - dstRowStride, dstSlices, - srcWidth, srcHeight, srcDepth, srcAddr, - srcPacking); - } - else { - return store_ubyte_texture(ctx, dims, baseInternalFormat, - dstFormat, dstRowStride, dstSlices, - srcWidth, srcHeight, srcDepth, - srcFormat, srcType, srcAddr, srcPacking); - } - return GL_TRUE; -} - - -static GLboolean -_mesa_texstore_argb2101010(TEXSTORE_PARAMS) -{ - ASSERT(dstFormat == MESA_FORMAT_B10G10R10A2_UNORM || - dstFormat == MESA_FORMAT_B10G10R10X2_UNORM); - ASSERT(_mesa_get_format_bytes(dstFormat) == 4); - - { - /* general path */ - /* Hardcode GL_RGBA as the base format, which forces alpha to 1.0 - * if the internal format is RGB. */ - const GLfloat *tempImage = _mesa_make_temp_float_image(ctx, dims, - baseInternalFormat, - GL_RGBA, - srcWidth, srcHeight, srcDepth, - srcFormat, srcType, srcAddr, - srcPacking, - ctx->_ImageTransferState); - const GLfloat *src = tempImage; - GLint img, row, col; - if (!tempImage) - return GL_FALSE; - for (img = 0; img < srcDepth; img++) { - GLubyte *dstRow = dstSlices[img]; - if (baseInternalFormat == GL_RGBA || baseInternalFormat == GL_RGB) { - for (row = 0; row < srcHeight; row++) { - GLuint *dstUI = (GLuint *) dstRow; - for (col = 0; col < srcWidth; col++) { - GLushort a,r,g,b; - - UNCLAMPED_FLOAT_TO_USHORT(a, src[ACOMP]); - UNCLAMPED_FLOAT_TO_USHORT(r, src[RCOMP]); - UNCLAMPED_FLOAT_TO_USHORT(g, src[GCOMP]); - UNCLAMPED_FLOAT_TO_USHORT(b, src[BCOMP]); - dstUI[col] = PACK_COLOR_2101010_US(a, r, g, b); - src += 4; - } - dstRow += dstRowStride; - } - } else { - ASSERT(0); - } - } - free((void *) tempImage); - } - return GL_TRUE; -} - - -/** - * Do texstore for 2-channel, 4-bit/channel, unsigned normalized formats. - */ -static GLboolean -_mesa_texstore_unorm44(TEXSTORE_PARAMS) -{ - const GLenum baseFormat = _mesa_get_format_base_format(dstFormat); - - ASSERT(dstFormat == MESA_FORMAT_L4A4_UNORM); - ASSERT(_mesa_get_format_bytes(dstFormat) == 1); - - { - /* general path */ - const GLubyte *tempImage = _mesa_make_temp_ubyte_image(ctx, dims, - baseInternalFormat, - baseFormat, - srcWidth, srcHeight, srcDepth, - srcFormat, srcType, srcAddr, - srcPacking); - const GLubyte *src = tempImage; - GLint img, row, col; - if (!tempImage) - return GL_FALSE; - for (img = 0; img < srcDepth; img++) { - GLubyte *dstRow = dstSlices[img]; - for (row = 0; row < srcHeight; row++) { - GLubyte *dstUS = (GLubyte *) dstRow; - for (col = 0; col < srcWidth; col++) { - /* src[0] is luminance, src[1] is alpha */ - dstUS[col] = PACK_COLOR_44( src[1], - src[0] ); - src += 2; - } - dstRow += dstRowStride; - } - } - free((void *) tempImage); - } - return GL_TRUE; -} - - -/** - * Do texstore for 2-channel, 8-bit/channel, unsigned normalized formats. - */ -static GLboolean -_mesa_texstore_unorm88(TEXSTORE_PARAMS) -{ - const GLboolean littleEndian = _mesa_little_endian(); - const GLenum baseFormat = _mesa_get_format_base_format(dstFormat); - - ASSERT(dstFormat == MESA_FORMAT_L8A8_UNORM || - dstFormat == MESA_FORMAT_A8L8_UNORM || - dstFormat == MESA_FORMAT_R8G8_UNORM || - dstFormat == MESA_FORMAT_G8R8_UNORM); - ASSERT(_mesa_get_format_bytes(dstFormat) == 2); - - if (!ctx->_ImageTransferState && - littleEndian && - srcType == GL_UNSIGNED_BYTE && - can_swizzle(baseInternalFormat) && - can_swizzle(srcFormat)) { - GLubyte dstmap[4]; - - /* dstmap - how to swizzle from RGBA to dst format: - */ - if (dstFormat == MESA_FORMAT_L8A8_UNORM || dstFormat == MESA_FORMAT_A8L8_UNORM) { - if ((littleEndian && dstFormat == MESA_FORMAT_L8A8_UNORM) || - (!littleEndian && dstFormat == MESA_FORMAT_A8L8_UNORM)) { - dstmap[0] = 0; - dstmap[1] = 3; - } - else { - dstmap[0] = 3; - dstmap[1] = 0; - } - } - else { - if ((littleEndian && dstFormat == MESA_FORMAT_R8G8_UNORM) || - (!littleEndian && dstFormat == MESA_FORMAT_G8R8_UNORM)) { - dstmap[0] = 0; - dstmap[1] = 1; - } - else { - dstmap[0] = 1; - dstmap[1] = 0; - } - } - dstmap[2] = ZERO; /* ? */ - dstmap[3] = ONE; /* ? */ - - _mesa_swizzle_ubyte_image(ctx, dims, - srcFormat, - srcType, - baseInternalFormat, - dstmap, 2, - dstRowStride, dstSlices, - srcWidth, srcHeight, srcDepth, srcAddr, - srcPacking); - } - else { - /* general path */ - const GLubyte *tempImage = _mesa_make_temp_ubyte_image(ctx, dims, - baseInternalFormat, - baseFormat, - srcWidth, srcHeight, srcDepth, - srcFormat, srcType, srcAddr, - srcPacking); - const GLubyte *src = tempImage; - GLint img, row, col; - if (!tempImage) - return GL_FALSE; - for (img = 0; img < srcDepth; img++) { - GLubyte *dstRow = dstSlices[img]; - for (row = 0; row < srcHeight; row++) { - GLushort *dstUS = (GLushort *) dstRow; - if (dstFormat == MESA_FORMAT_L8A8_UNORM || - dstFormat == MESA_FORMAT_R8G8_UNORM) { - for (col = 0; col < srcWidth; col++) { - /* src[0] is luminance (or R), src[1] is alpha (or G) */ - dstUS[col] = PACK_COLOR_88( src[1], - src[0] ); - src += 2; - } - } - else { - for (col = 0; col < srcWidth; col++) { - /* src[0] is luminance (or R), src[1] is alpha (or G) */ - dstUS[col] = PACK_COLOR_88_REV( src[1], - src[0] ); - src += 2; - } - } - dstRow += dstRowStride; - } - } - free((void *) tempImage); - } - return GL_TRUE; -} - - -/** - * Do texstore for 2-channel, 16-bit/channel, unsigned normalized formats. - */ -static GLboolean -_mesa_texstore_unorm1616(TEXSTORE_PARAMS) -{ - const GLenum baseFormat = _mesa_get_format_base_format(dstFormat); - - ASSERT(dstFormat == MESA_FORMAT_L16A16_UNORM || - dstFormat == MESA_FORMAT_A16L16_UNORM || - dstFormat == MESA_FORMAT_R16G16_UNORM || - dstFormat == MESA_FORMAT_G16R16_UNORM); - ASSERT(_mesa_get_format_bytes(dstFormat) == 4); - - { - /* general path */ - const GLfloat *tempImage = _mesa_make_temp_float_image(ctx, dims, - baseInternalFormat, - baseFormat, - srcWidth, srcHeight, srcDepth, - srcFormat, srcType, srcAddr, - srcPacking, - ctx->_ImageTransferState); - const GLfloat *src = tempImage; - GLint img, row, col; - if (!tempImage) - return GL_FALSE; - for (img = 0; img < srcDepth; img++) { - GLubyte *dstRow = dstSlices[img]; - for (row = 0; row < srcHeight; row++) { - GLuint *dstUI = (GLuint *) dstRow; - if (dstFormat == MESA_FORMAT_L16A16_UNORM || - dstFormat == MESA_FORMAT_R16G16_UNORM) { - for (col = 0; col < srcWidth; col++) { - GLushort l, a; - - UNCLAMPED_FLOAT_TO_USHORT(l, src[0]); - UNCLAMPED_FLOAT_TO_USHORT(a, src[1]); - dstUI[col] = PACK_COLOR_1616(a, l); - src += 2; - } - } - else { - for (col = 0; col < srcWidth; col++) { - GLushort l, a; - - UNCLAMPED_FLOAT_TO_USHORT(l, src[0]); - UNCLAMPED_FLOAT_TO_USHORT(a, src[1]); - dstUI[col] = PACK_COLOR_1616_REV(a, l); - src += 2; - } - } - dstRow += dstRowStride; - } - } - free((void *) tempImage); - } - return GL_TRUE; -} - - -/* Texstore for R16, A16, L16, I16. */ -static GLboolean -_mesa_texstore_unorm16(TEXSTORE_PARAMS) -{ - const GLenum baseFormat = _mesa_get_format_base_format(dstFormat); - - ASSERT(dstFormat == MESA_FORMAT_R_UNORM16 || - dstFormat == MESA_FORMAT_A_UNORM16 || - dstFormat == MESA_FORMAT_L_UNORM16 || - dstFormat == MESA_FORMAT_I_UNORM16); - ASSERT(_mesa_get_format_bytes(dstFormat) == 2); - - { - /* general path */ - const GLfloat *tempImage = _mesa_make_temp_float_image(ctx, dims, - baseInternalFormat, - baseFormat, - srcWidth, srcHeight, srcDepth, - srcFormat, srcType, srcAddr, - srcPacking, - ctx->_ImageTransferState); - const GLfloat *src = tempImage; - GLint img, row, col; - if (!tempImage) - return GL_FALSE; - for (img = 0; img < srcDepth; img++) { - GLubyte *dstRow = dstSlices[img]; - for (row = 0; row < srcHeight; row++) { - GLushort *dstUS = (GLushort *) dstRow; - for (col = 0; col < srcWidth; col++) { - GLushort r; - - UNCLAMPED_FLOAT_TO_USHORT(r, src[0]); - dstUS[col] = r; - src += 1; - } - dstRow += dstRowStride; - } - } - free((void *) tempImage); - } - return GL_TRUE; -} - - -static GLboolean -_mesa_texstore_rgba_16(TEXSTORE_PARAMS) -{ - ASSERT(dstFormat == MESA_FORMAT_RGBA_UNORM16 || - dstFormat == MESA_FORMAT_RGBX_UNORM16); - ASSERT(_mesa_get_format_bytes(dstFormat) == 8); - - { - /* general path */ - /* Hardcode GL_RGBA as the base format, which forces alpha to 1.0 - * if the internal format is RGB. */ - const GLfloat *tempImage = _mesa_make_temp_float_image(ctx, dims, - baseInternalFormat, - GL_RGBA, - srcWidth, srcHeight, srcDepth, - srcFormat, srcType, srcAddr, - srcPacking, - ctx->_ImageTransferState); - const GLfloat *src = tempImage; - GLint img, row, col; - - if (!tempImage) - return GL_FALSE; - - for (img = 0; img < srcDepth; img++) { - GLubyte *dstRow = dstSlices[img]; - for (row = 0; row < srcHeight; row++) { - GLushort *dstUS = (GLushort *) dstRow; - for (col = 0; col < srcWidth; col++) { - GLushort r, g, b, a; - - UNCLAMPED_FLOAT_TO_USHORT(r, src[0]); - UNCLAMPED_FLOAT_TO_USHORT(g, src[1]); - UNCLAMPED_FLOAT_TO_USHORT(b, src[2]); - UNCLAMPED_FLOAT_TO_USHORT(a, src[3]); - dstUS[col*4+0] = r; - dstUS[col*4+1] = g; - dstUS[col*4+2] = b; - dstUS[col*4+3] = a; - src += 4; - } - dstRow += dstRowStride; - } - } - free((void *) tempImage); - } - return GL_TRUE; -} - - -static GLboolean -_mesa_texstore_signed_rgba_16(TEXSTORE_PARAMS) -{ - const GLenum baseFormat = _mesa_get_format_base_format(dstFormat); - - ASSERT(dstFormat == MESA_FORMAT_RGB_SNORM16 || - dstFormat == MESA_FORMAT_RGBA_SNORM16 || - dstFormat == MESA_FORMAT_RGBX_SNORM16); - - { - /* general path */ - const GLfloat *tempImage = _mesa_make_temp_float_image(ctx, dims, - baseInternalFormat, - baseFormat, - srcWidth, srcHeight, srcDepth, - srcFormat, srcType, srcAddr, - srcPacking, - ctx->_ImageTransferState); - const GLfloat *src = tempImage; - const GLuint comps = _mesa_get_format_bytes(dstFormat) / 2; - GLint img, row, col; - - if (!tempImage) - return GL_FALSE; - - /* Note: tempImage is always float[4] / RGBA. We convert to 1, 2, - * 3 or 4 components/pixel here. - */ - for (img = 0; img < srcDepth; img++) { - GLubyte *dstRow = dstSlices[img]; - for (row = 0; row < srcHeight; row++) { - GLshort *dstRowS = (GLshort *) dstRow; - if (dstFormat == MESA_FORMAT_RGBA_SNORM16) { - for (col = 0; col < srcWidth; col++) { - GLuint c; - for (c = 0; c < comps; c++) { - GLshort p; - UNCLAMPED_FLOAT_TO_SHORT(p, src[col * 4 + c]); - dstRowS[col * comps + c] = p; - } - } - dstRow += dstRowStride; - src += 4 * srcWidth; - } - else if (dstFormat == MESA_FORMAT_RGBX_SNORM16) { - for (col = 0; col < srcWidth; col++) { - GLuint c; - - for (c = 0; c < 3; c++) { - GLshort p; - UNCLAMPED_FLOAT_TO_SHORT(p, src[col * 3 + c]); - dstRowS[col * comps + c] = p; - } - dstRowS[col * comps + 3] = 32767; - } - dstRow += dstRowStride; - src += 3 * srcWidth; - } - else { - for (col = 0; col < srcWidth; col++) { - GLuint c; - for (c = 0; c < comps; c++) { - GLshort p; - UNCLAMPED_FLOAT_TO_SHORT(p, src[col * 3 + c]); - dstRowS[col * comps + c] = p; - } - } - dstRow += dstRowStride; - src += 3 * srcWidth; - } - } - } - free((void *) tempImage); - } - return GL_TRUE; -} - - -/** - * Texstore for _mesa_texformat_a8, _mesa_texformat_l8, _mesa_texformat_i8. - */ -static GLboolean -_mesa_texstore_unorm8(TEXSTORE_PARAMS) -{ - const GLenum baseFormat = _mesa_get_format_base_format(dstFormat); - - ASSERT(dstFormat == MESA_FORMAT_A_UNORM8 || - dstFormat == MESA_FORMAT_L_UNORM8 || - dstFormat == MESA_FORMAT_I_UNORM8 || - dstFormat == MESA_FORMAT_R_UNORM8); - ASSERT(_mesa_get_format_bytes(dstFormat) == 1); - - if (!ctx->_ImageTransferState && - srcType == GL_UNSIGNED_BYTE && - can_swizzle(baseInternalFormat) && - can_swizzle(srcFormat)) { - GLubyte dstmap[4]; - - /* dstmap - how to swizzle from RGBA to dst format: - */ - if (dstFormat == MESA_FORMAT_A_UNORM8) { - dstmap[0] = 3; - } - else { - dstmap[0] = 0; - } - dstmap[1] = ZERO; /* ? */ - dstmap[2] = ZERO; /* ? */ - dstmap[3] = ONE; /* ? */ - - _mesa_swizzle_ubyte_image(ctx, dims, - srcFormat, - srcType, - baseInternalFormat, - dstmap, 1, - dstRowStride, dstSlices, - srcWidth, srcHeight, srcDepth, srcAddr, - srcPacking); - } - else { - /* general path */ - const GLubyte *tempImage = _mesa_make_temp_ubyte_image(ctx, dims, - baseInternalFormat, - baseFormat, - srcWidth, srcHeight, srcDepth, - srcFormat, srcType, srcAddr, - srcPacking); - const GLubyte *src = tempImage; - GLint img, row, col; - if (!tempImage) - return GL_FALSE; - for (img = 0; img < srcDepth; img++) { - GLubyte *dstRow = dstSlices[img]; - for (row = 0; row < srcHeight; row++) { - for (col = 0; col < srcWidth; col++) { - dstRow[col] = src[col]; - } - dstRow += dstRowStride; - src += srcWidth; - } - } - free((void *) tempImage); - } - return GL_TRUE; } - /** * Texstore for _mesa_texformat_ycbcr or _mesa_texformat_ycbcr_REV. */ @@ -2063,330 +982,6 @@ _mesa_texstore_ycbcr(TEXSTORE_PARAMS) /** - * Store a texture in a signed normalized 8-bit format. - */ -static GLboolean -_mesa_texstore_snorm8(TEXSTORE_PARAMS) -{ - const GLenum baseFormat = _mesa_get_format_base_format(dstFormat); - - ASSERT(dstFormat == MESA_FORMAT_A_SNORM8 || - dstFormat == MESA_FORMAT_L_SNORM8 || - dstFormat == MESA_FORMAT_I_SNORM8 || - dstFormat == MESA_FORMAT_R_SNORM8); - ASSERT(_mesa_get_format_bytes(dstFormat) == 1); - - { - /* general path */ - const GLfloat *tempImage = _mesa_make_temp_float_image(ctx, dims, - baseInternalFormat, - baseFormat, - srcWidth, srcHeight, srcDepth, - srcFormat, srcType, srcAddr, - srcPacking, - ctx->_ImageTransferState); - const GLfloat *src = tempImage; - GLint img, row, col; - if (!tempImage) - return GL_FALSE; - for (img = 0; img < srcDepth; img++) { - GLbyte *dstRow = (GLbyte *) dstSlices[img]; - for (row = 0; row < srcHeight; row++) { - for (col = 0; col < srcWidth; col++) { - dstRow[col] = FLOAT_TO_BYTE_TEX(src[col]); - } - dstRow += dstRowStride; - src += srcWidth; - } - } - free((void *) tempImage); - } - return GL_TRUE; -} - - -/** - * Store a texture in a signed normalized two-channel 16-bit format. - */ -static GLboolean -_mesa_texstore_snorm88(TEXSTORE_PARAMS) -{ - const GLenum baseFormat = _mesa_get_format_base_format(dstFormat); - - ASSERT(dstFormat == MESA_FORMAT_L8A8_SNORM || - dstFormat == MESA_FORMAT_G8R8_SNORM || - dstFormat == MESA_FORMAT_R8G8_SNORM); - ASSERT(_mesa_get_format_bytes(dstFormat) == 2); - - { - /* general path */ - const GLfloat *tempImage = _mesa_make_temp_float_image(ctx, dims, - baseInternalFormat, - baseFormat, - srcWidth, srcHeight, srcDepth, - srcFormat, srcType, srcAddr, - srcPacking, - ctx->_ImageTransferState); - const GLfloat *src = tempImage; - GLint img, row, col; - if (!tempImage) - return GL_FALSE; - for (img = 0; img < srcDepth; img++) { - GLbyte *dstRow = (GLbyte *) dstSlices[img]; - for (row = 0; row < srcHeight; row++) { - GLushort *dst = (GLushort *) dstRow; - - if (dstFormat == MESA_FORMAT_L8A8_SNORM || - dstFormat == MESA_FORMAT_R8G8_SNORM) { - for (col = 0; col < srcWidth; col++) { - GLubyte l = FLOAT_TO_BYTE_TEX(src[0]); - GLubyte a = FLOAT_TO_BYTE_TEX(src[1]); - - dst[col] = PACK_COLOR_88_REV(l, a); - src += 2; - } - } else { - for (col = 0; col < srcWidth; col++) { - GLubyte l = FLOAT_TO_BYTE_TEX(src[0]); - GLubyte a = FLOAT_TO_BYTE_TEX(src[1]); - - dst[col] = PACK_COLOR_88(l, a); - src += 2; - } - } - - dstRow += dstRowStride; - } - } - free((void *) tempImage); - } - return GL_TRUE; -} - -/* Texstore for signed R16, A16, L16, I16. */ -static GLboolean -_mesa_texstore_snorm16(TEXSTORE_PARAMS) -{ - const GLenum baseFormat = _mesa_get_format_base_format(dstFormat); - - ASSERT(dstFormat == MESA_FORMAT_R_SNORM16 || - dstFormat == MESA_FORMAT_A_SNORM16 || - dstFormat == MESA_FORMAT_L_SNORM16 || - dstFormat == MESA_FORMAT_I_SNORM16); - ASSERT(_mesa_get_format_bytes(dstFormat) == 2); - - { - /* general path */ - const GLfloat *tempImage = _mesa_make_temp_float_image(ctx, dims, - baseInternalFormat, - baseFormat, - srcWidth, srcHeight, srcDepth, - srcFormat, srcType, srcAddr, - srcPacking, - ctx->_ImageTransferState); - const GLfloat *src = tempImage; - GLint img, row, col; - if (!tempImage) - return GL_FALSE; - for (img = 0; img < srcDepth; img++) { - GLubyte *dstRow = dstSlices[img]; - for (row = 0; row < srcHeight; row++) { - GLshort *dstUS = (GLshort *) dstRow; - for (col = 0; col < srcWidth; col++) { - GLushort r; - - UNCLAMPED_FLOAT_TO_SHORT(r, src[0]); - dstUS[col] = r; - src += 1; - } - dstRow += dstRowStride; - } - } - free((void *) tempImage); - } - return GL_TRUE; -} - -/** - * Do texstore for 2-channel, 16-bit/channel, signed normalized formats. - */ -static GLboolean -_mesa_texstore_snorm1616(TEXSTORE_PARAMS) -{ - const GLenum baseFormat = _mesa_get_format_base_format(dstFormat); - - ASSERT(dstFormat == MESA_FORMAT_LA_SNORM16 || - dstFormat == MESA_FORMAT_G16R16_SNORM || - dstFormat == MESA_FORMAT_R16G16_SNORM); - ASSERT(_mesa_get_format_bytes(dstFormat) == 4); - - { - /* general path */ - const GLfloat *tempImage = _mesa_make_temp_float_image(ctx, dims, - baseInternalFormat, - baseFormat, - srcWidth, srcHeight, srcDepth, - srcFormat, srcType, srcAddr, - srcPacking, - ctx->_ImageTransferState); - const GLfloat *src = tempImage; - GLint img, row, col; - if (!tempImage) - return GL_FALSE; - for (img = 0; img < srcDepth; img++) { - GLubyte *dstRow = dstSlices[img]; - for (row = 0; row < srcHeight; row++) { - GLuint *dst = (GLuint *) dstRow; - - if (dstFormat == MESA_FORMAT_LA_SNORM16 || - dstFormat == MESA_FORMAT_R16G16_SNORM) { - for (col = 0; col < srcWidth; col++) { - GLushort l, a; - - UNCLAMPED_FLOAT_TO_SHORT(l, src[0]); - UNCLAMPED_FLOAT_TO_SHORT(a, src[1]); - dst[col] = PACK_COLOR_1616_REV(l, a); - src += 2; - } - } else { - for (col = 0; col < srcWidth; col++) { - GLushort l, a; - - UNCLAMPED_FLOAT_TO_SHORT(l, src[0]); - UNCLAMPED_FLOAT_TO_SHORT(a, src[1]); - dst[col] = PACK_COLOR_1616_REV(l, a); - src += 2; - } - } - - dstRow += dstRowStride; - } - } - free((void *) tempImage); - } - return GL_TRUE; -} - -/** - * Store a texture in MESA_FORMAT_X8B8G8R8_SNORM or - * MESA_FORMAT_R8G8B8X8_SNORM. - */ -static GLboolean -_mesa_texstore_signed_rgbx8888(TEXSTORE_PARAMS) -{ - const GLenum baseFormat = _mesa_get_format_base_format(dstFormat); - - ASSERT(dstFormat == MESA_FORMAT_X8B8G8R8_SNORM || - dstFormat == MESA_FORMAT_R8G8B8X8_SNORM); - ASSERT(_mesa_get_format_bytes(dstFormat) == 4); - - { - /* general path */ - const GLfloat *tempImage = _mesa_make_temp_float_image(ctx, dims, - baseInternalFormat, - baseFormat, - srcWidth, srcHeight, srcDepth, - srcFormat, srcType, srcAddr, - srcPacking, - ctx->_ImageTransferState); - const GLfloat *srcRow = tempImage; - GLint img, row, col; - if (!tempImage) - return GL_FALSE; - for (img = 0; img < srcDepth; img++) { - GLbyte *dstRow = (GLbyte *) dstSlices[img]; - for (row = 0; row < srcHeight; row++) { - GLbyte *dst = dstRow; - if (dstFormat == MESA_FORMAT_X8B8G8R8_SNORM) { - for (col = 0; col < srcWidth; col++) { - dst[3] = FLOAT_TO_BYTE_TEX(srcRow[RCOMP]); - dst[2] = FLOAT_TO_BYTE_TEX(srcRow[GCOMP]); - dst[1] = FLOAT_TO_BYTE_TEX(srcRow[BCOMP]); - dst[0] = 127; - srcRow += 3; - dst += 4; - } - } - else { - for (col = 0; col < srcWidth; col++) { - dst[0] = FLOAT_TO_BYTE_TEX(srcRow[RCOMP]); - dst[1] = FLOAT_TO_BYTE_TEX(srcRow[GCOMP]); - dst[2] = FLOAT_TO_BYTE_TEX(srcRow[BCOMP]); - dst[3] = 127; - srcRow += 3; - dst += 4; - } - } - dstRow += dstRowStride; - } - } - free((void *) tempImage); - } - return GL_TRUE; -} - - - -/** - * Store a texture in MESA_FORMAT_A8B8G8R8_SNORM or - * MESA_FORMAT_R8G8B8A8_SNORM - */ -static GLboolean -_mesa_texstore_signed_rgba8888(TEXSTORE_PARAMS) -{ - const GLenum baseFormat = _mesa_get_format_base_format(dstFormat); - - ASSERT(dstFormat == MESA_FORMAT_A8B8G8R8_SNORM || - dstFormat == MESA_FORMAT_R8G8B8A8_SNORM); - ASSERT(_mesa_get_format_bytes(dstFormat) == 4); - - { - /* general path */ - const GLfloat *tempImage = _mesa_make_temp_float_image(ctx, dims, - baseInternalFormat, - baseFormat, - srcWidth, srcHeight, srcDepth, - srcFormat, srcType, srcAddr, - srcPacking, - ctx->_ImageTransferState); - const GLfloat *srcRow = tempImage; - GLint img, row, col; - if (!tempImage) - return GL_FALSE; - for (img = 0; img < srcDepth; img++) { - GLbyte *dstRow = (GLbyte *) dstSlices[img]; - for (row = 0; row < srcHeight; row++) { - GLbyte *dst = dstRow; - if (dstFormat == MESA_FORMAT_A8B8G8R8_SNORM) { - for (col = 0; col < srcWidth; col++) { - dst[3] = FLOAT_TO_BYTE_TEX(srcRow[RCOMP]); - dst[2] = FLOAT_TO_BYTE_TEX(srcRow[GCOMP]); - dst[1] = FLOAT_TO_BYTE_TEX(srcRow[BCOMP]); - dst[0] = FLOAT_TO_BYTE_TEX(srcRow[ACOMP]); - srcRow += 4; - dst += 4; - } - } - else { - for (col = 0; col < srcWidth; col++) { - dst[0] = FLOAT_TO_BYTE_TEX(srcRow[RCOMP]); - dst[1] = FLOAT_TO_BYTE_TEX(srcRow[GCOMP]); - dst[2] = FLOAT_TO_BYTE_TEX(srcRow[BCOMP]); - dst[3] = FLOAT_TO_BYTE_TEX(srcRow[ACOMP]); - srcRow += 4; - dst += 4; - } - } - dstRow += dstRowStride; - } - } - free((void *) tempImage); - } - return GL_TRUE; -} - - -/** * Store a combined depth/stencil texture image. */ static GLboolean @@ -2599,742 +1194,6 @@ _mesa_texstore_s8(TEXSTORE_PARAMS) } -/** - * Store an image in any of the formats: - * _mesa_texformat_rgba_float32 - * _mesa_texformat_rgb_float32 - * _mesa_texformat_alpha_float32 - * _mesa_texformat_luminance_float32 - * _mesa_texformat_luminance_alpha_float32 - * _mesa_texformat_intensity_float32 - */ -static GLboolean -_mesa_texstore_rgba_float32(TEXSTORE_PARAMS) -{ - GLenum baseFormat = _mesa_get_format_base_format(dstFormat); - GLint components = _mesa_components_in_format(baseFormat); - - /* this forces alpha to 1 in _mesa_make_temp_float_image */ - if (dstFormat == MESA_FORMAT_RGBX_FLOAT32) { - baseFormat = GL_RGBA; - components = 4; - } - - ASSERT(dstFormat == MESA_FORMAT_RGBA_FLOAT32 || - dstFormat == MESA_FORMAT_RGB_FLOAT32 || - dstFormat == MESA_FORMAT_A_FLOAT32 || - dstFormat == MESA_FORMAT_L_FLOAT32 || - dstFormat == MESA_FORMAT_LA_FLOAT32 || - dstFormat == MESA_FORMAT_I_FLOAT32 || - dstFormat == MESA_FORMAT_R_FLOAT32 || - dstFormat == MESA_FORMAT_RG_FLOAT32 || - dstFormat == MESA_FORMAT_RGBX_FLOAT32); - ASSERT(baseInternalFormat == GL_RGBA || - baseInternalFormat == GL_RGB || - baseInternalFormat == GL_ALPHA || - baseInternalFormat == GL_LUMINANCE || - baseInternalFormat == GL_LUMINANCE_ALPHA || - baseInternalFormat == GL_INTENSITY || - baseInternalFormat == GL_RED || - baseInternalFormat == GL_RG); - ASSERT(_mesa_get_format_bytes(dstFormat) == components * sizeof(GLfloat)); - - { - /* general path */ - const GLfloat *tempImage = _mesa_make_temp_float_image(ctx, dims, - baseInternalFormat, - baseFormat, - srcWidth, srcHeight, srcDepth, - srcFormat, srcType, srcAddr, - srcPacking, - ctx->_ImageTransferState); - const GLfloat *srcRow = tempImage; - GLint bytesPerRow; - GLint img, row; - if (!tempImage) - return GL_FALSE; - bytesPerRow = srcWidth * components * sizeof(GLfloat); - for (img = 0; img < srcDepth; img++) { - GLubyte *dstRow = dstSlices[img]; - for (row = 0; row < srcHeight; row++) { - memcpy(dstRow, srcRow, bytesPerRow); - dstRow += dstRowStride; - srcRow += srcWidth * components; - } - } - - free((void *) tempImage); - } - return GL_TRUE; -} - - - -/** - * As above, but store 16-bit floats. - */ -static GLboolean -_mesa_texstore_rgba_float16(TEXSTORE_PARAMS) -{ - GLenum baseFormat = _mesa_get_format_base_format(dstFormat); - GLint components = _mesa_components_in_format(baseFormat); - - /* this forces alpha to 1 in _mesa_make_temp_float_image */ - if (dstFormat == MESA_FORMAT_RGBX_FLOAT16) { - baseFormat = GL_RGBA; - components = 4; - } - - ASSERT(dstFormat == MESA_FORMAT_RGBA_FLOAT16 || - dstFormat == MESA_FORMAT_RGB_FLOAT16 || - dstFormat == MESA_FORMAT_A_FLOAT16 || - dstFormat == MESA_FORMAT_L_FLOAT16 || - dstFormat == MESA_FORMAT_LA_FLOAT16 || - dstFormat == MESA_FORMAT_I_FLOAT16 || - dstFormat == MESA_FORMAT_R_FLOAT16 || - dstFormat == MESA_FORMAT_RG_FLOAT16 || - dstFormat == MESA_FORMAT_RGBX_FLOAT16); - ASSERT(baseInternalFormat == GL_RGBA || - baseInternalFormat == GL_RGB || - baseInternalFormat == GL_ALPHA || - baseInternalFormat == GL_LUMINANCE || - baseInternalFormat == GL_LUMINANCE_ALPHA || - baseInternalFormat == GL_INTENSITY || - baseInternalFormat == GL_RED || - baseInternalFormat == GL_RG); - ASSERT(_mesa_get_format_bytes(dstFormat) == components * sizeof(GLhalfARB)); - - { - /* general path */ - const GLfloat *tempImage = _mesa_make_temp_float_image(ctx, dims, - baseInternalFormat, - baseFormat, - srcWidth, srcHeight, srcDepth, - srcFormat, srcType, srcAddr, - srcPacking, - ctx->_ImageTransferState); - const GLfloat *src = tempImage; - GLint img, row; - if (!tempImage) - return GL_FALSE; - for (img = 0; img < srcDepth; img++) { - GLubyte *dstRow = dstSlices[img]; - for (row = 0; row < srcHeight; row++) { - GLhalfARB *dstTexel = (GLhalfARB *) dstRow; - GLint i; - for (i = 0; i < srcWidth * components; i++) { - dstTexel[i] = _mesa_float_to_half(src[i]); - } - dstRow += dstRowStride; - src += srcWidth * components; - } - } - - free((void *) tempImage); - } - return GL_TRUE; -} - - -/* non-normalized, signed int8 */ -static GLboolean -_mesa_texstore_rgba_int8(TEXSTORE_PARAMS) -{ - GLenum baseFormat = _mesa_get_format_base_format(dstFormat); - GLint components = _mesa_components_in_format(baseFormat); - - /* this forces alpha to 1 in make_temp_uint_image */ - if (dstFormat == MESA_FORMAT_RGBX_SINT8) { - baseFormat = GL_RGBA; - components = 4; - } - - ASSERT(dstFormat == MESA_FORMAT_R_SINT8 || - dstFormat == MESA_FORMAT_RG_SINT8 || - dstFormat == MESA_FORMAT_RGB_SINT8 || - dstFormat == MESA_FORMAT_RGBA_SINT8 || - dstFormat == MESA_FORMAT_A_SINT8 || - dstFormat == MESA_FORMAT_I_SINT8 || - dstFormat == MESA_FORMAT_L_SINT8 || - dstFormat == MESA_FORMAT_LA_SINT8 || - dstFormat == MESA_FORMAT_RGBX_SINT8); - ASSERT(baseInternalFormat == GL_RGBA || - baseInternalFormat == GL_RGB || - baseInternalFormat == GL_RG || - baseInternalFormat == GL_RED || - baseInternalFormat == GL_ALPHA || - baseInternalFormat == GL_LUMINANCE || - baseInternalFormat == GL_LUMINANCE_ALPHA || - baseInternalFormat == GL_INTENSITY); - ASSERT(_mesa_get_format_bytes(dstFormat) == components * sizeof(GLbyte)); - - { - /* general path */ - const GLuint *tempImage = make_temp_uint_image(ctx, dims, - baseInternalFormat, - baseFormat, - srcWidth, srcHeight, srcDepth, - srcFormat, srcType, - srcAddr, - srcPacking); - const GLuint *src = tempImage; - GLint img, row; - GLboolean is_unsigned = _mesa_is_type_unsigned(srcType); - if (!tempImage) - return GL_FALSE; - for (img = 0; img < srcDepth; img++) { - GLubyte *dstRow = dstSlices[img]; - for (row = 0; row < srcHeight; row++) { - GLbyte *dstTexel = (GLbyte *) dstRow; - GLint i; - if (is_unsigned) { - for (i = 0; i < srcWidth * components; i++) { - dstTexel[i] = (GLbyte) MIN2(src[i], 0x7f); - } - } else { - for (i = 0; i < srcWidth * components; i++) { - dstTexel[i] = (GLbyte) CLAMP((GLint) src[i], -0x80, 0x7f); - } - } - dstRow += dstRowStride; - src += srcWidth * components; - } - } - - free((void *) tempImage); - } - return GL_TRUE; -} - - -/* non-normalized, signed int16 */ -static GLboolean -_mesa_texstore_rgba_int16(TEXSTORE_PARAMS) -{ - GLenum baseFormat = _mesa_get_format_base_format(dstFormat); - GLint components = _mesa_components_in_format(baseFormat); - - /* this forces alpha to 1 in make_temp_uint_image */ - if (dstFormat == MESA_FORMAT_RGBX_SINT16) { - baseFormat = GL_RGBA; - components = 4; - } - - ASSERT(dstFormat == MESA_FORMAT_R_SINT16 || - dstFormat == MESA_FORMAT_RG_SINT16 || - dstFormat == MESA_FORMAT_RGB_SINT16 || - dstFormat == MESA_FORMAT_RGBA_SINT16 || - dstFormat == MESA_FORMAT_A_SINT16 || - dstFormat == MESA_FORMAT_L_SINT16 || - dstFormat == MESA_FORMAT_I_SINT16 || - dstFormat == MESA_FORMAT_LA_SINT16 || - dstFormat == MESA_FORMAT_RGBX_SINT16); - ASSERT(baseInternalFormat == GL_RGBA || - baseInternalFormat == GL_RGB || - baseInternalFormat == GL_RG || - baseInternalFormat == GL_RED || - baseInternalFormat == GL_ALPHA || - baseInternalFormat == GL_LUMINANCE || - baseInternalFormat == GL_LUMINANCE_ALPHA || - baseInternalFormat == GL_INTENSITY); - ASSERT(_mesa_get_format_bytes(dstFormat) == components * sizeof(GLshort)); - - { - /* general path */ - const GLuint *tempImage = make_temp_uint_image(ctx, dims, - baseInternalFormat, - baseFormat, - srcWidth, srcHeight, srcDepth, - srcFormat, srcType, - srcAddr, - srcPacking); - const GLuint *src = tempImage; - GLint img, row; - GLboolean is_unsigned = _mesa_is_type_unsigned(srcType); - if (!tempImage) - return GL_FALSE; - for (img = 0; img < srcDepth; img++) { - GLubyte *dstRow = dstSlices[img]; - for (row = 0; row < srcHeight; row++) { - GLshort *dstTexel = (GLshort *) dstRow; - GLint i; - if (is_unsigned) { - for (i = 0; i < srcWidth * components; i++) { - dstTexel[i] = (GLshort) MIN2(src[i], 0x7fff); - } - } else { - for (i = 0; i < srcWidth * components; i++) { - dstTexel[i] = (GLshort)CLAMP((GLint) src[i], -0x8000, 0x7fff); - } - } - dstRow += dstRowStride; - src += srcWidth * components; - } - } - - free((void *) tempImage); - } - return GL_TRUE; -} - - -/* non-normalized, signed int32 */ -static GLboolean -_mesa_texstore_rgba_int32(TEXSTORE_PARAMS) -{ - GLenum baseFormat = _mesa_get_format_base_format(dstFormat); - GLint components = _mesa_components_in_format(baseFormat); - - /* this forces alpha to 1 in make_temp_uint_image */ - if (dstFormat == MESA_FORMAT_RGBX_SINT32) { - baseFormat = GL_RGBA; - components = 4; - } - - ASSERT(dstFormat == MESA_FORMAT_R_SINT32 || - dstFormat == MESA_FORMAT_RG_SINT32 || - dstFormat == MESA_FORMAT_RGB_SINT32 || - dstFormat == MESA_FORMAT_RGBA_SINT32 || - dstFormat == MESA_FORMAT_A_SINT32 || - dstFormat == MESA_FORMAT_I_SINT32 || - dstFormat == MESA_FORMAT_L_SINT32 || - dstFormat == MESA_FORMAT_LA_SINT32 || - dstFormat == MESA_FORMAT_RGBX_SINT32); - ASSERT(baseInternalFormat == GL_RGBA || - baseInternalFormat == GL_RGB || - baseInternalFormat == GL_RG || - baseInternalFormat == GL_RED || - baseInternalFormat == GL_ALPHA || - baseInternalFormat == GL_LUMINANCE || - baseInternalFormat == GL_LUMINANCE_ALPHA || - baseInternalFormat == GL_INTENSITY); - ASSERT(_mesa_get_format_bytes(dstFormat) == components * sizeof(GLint)); - - { - /* general path */ - const GLuint *tempImage = make_temp_uint_image(ctx, dims, - baseInternalFormat, - baseFormat, - srcWidth, srcHeight, srcDepth, - srcFormat, srcType, - srcAddr, - srcPacking); - const GLuint *src = tempImage; - GLint img, row; - GLboolean is_unsigned = _mesa_is_type_unsigned(srcType); - if (!tempImage) - return GL_FALSE; - for (img = 0; img < srcDepth; img++) { - GLubyte *dstRow = dstSlices[img]; - for (row = 0; row < srcHeight; row++) { - GLint *dstTexel = (GLint *) dstRow; - GLint i; - if (is_unsigned) { - for (i = 0; i < srcWidth * components; i++) { - dstTexel[i] = (GLint) MIN2(src[i], 0x7fffffff); - } - } else { - for (i = 0; i < srcWidth * components; i++) { - dstTexel[i] = (GLint) src[i]; - } - } - dstRow += dstRowStride; - src += srcWidth * components; - } - } - - free((void *) tempImage); - } - return GL_TRUE; -} - - -/* non-normalized, unsigned int8 */ -static GLboolean -_mesa_texstore_rgba_uint8(TEXSTORE_PARAMS) -{ - GLenum baseFormat = _mesa_get_format_base_format(dstFormat); - GLint components = _mesa_components_in_format(baseFormat); - - /* this forces alpha to 1 in make_temp_uint_image */ - if (dstFormat == MESA_FORMAT_RGBX_UINT8) { - baseFormat = GL_RGBA; - components = 4; - } - - ASSERT(dstFormat == MESA_FORMAT_R_UINT8 || - dstFormat == MESA_FORMAT_RG_UINT8 || - dstFormat == MESA_FORMAT_RGB_UINT8 || - dstFormat == MESA_FORMAT_RGBA_UINT8 || - dstFormat == MESA_FORMAT_A_UINT8 || - dstFormat == MESA_FORMAT_I_UINT8 || - dstFormat == MESA_FORMAT_L_UINT8 || - dstFormat == MESA_FORMAT_LA_UINT8 || - dstFormat == MESA_FORMAT_RGBX_UINT8); - ASSERT(baseInternalFormat == GL_RGBA || - baseInternalFormat == GL_RGB || - baseInternalFormat == GL_RG || - baseInternalFormat == GL_RED || - baseInternalFormat == GL_ALPHA || - baseInternalFormat == GL_LUMINANCE || - baseInternalFormat == GL_LUMINANCE_ALPHA || - baseInternalFormat == GL_INTENSITY); - ASSERT(_mesa_get_format_bytes(dstFormat) == components * sizeof(GLubyte)); - - { - /* general path */ - const GLuint *tempImage = - make_temp_uint_image(ctx, dims, baseInternalFormat, baseFormat, - srcWidth, srcHeight, srcDepth, - srcFormat, srcType, srcAddr, srcPacking); - const GLuint *src = tempImage; - GLint img, row; - GLboolean is_unsigned = _mesa_is_type_unsigned(srcType); - if (!tempImage) - return GL_FALSE; - for (img = 0; img < srcDepth; img++) { - GLubyte *dstRow = dstSlices[img]; - for (row = 0; row < srcHeight; row++) { - GLubyte *dstTexel = (GLubyte *) dstRow; - GLint i; - if (is_unsigned) { - for (i = 0; i < srcWidth * components; i++) { - dstTexel[i] = (GLubyte) MIN2(src[i], 0xff); - } - } else { - for (i = 0; i < srcWidth * components; i++) { - dstTexel[i] = (GLubyte) CLAMP((GLint) src[i], 0, 0xff); - } - } - dstRow += dstRowStride; - src += srcWidth * components; - } - } - - free((void *) tempImage); - } - return GL_TRUE; -} - - -/* non-normalized, unsigned int16 */ -static GLboolean -_mesa_texstore_rgba_uint16(TEXSTORE_PARAMS) -{ - GLenum baseFormat = _mesa_get_format_base_format(dstFormat); - GLint components = _mesa_components_in_format(baseFormat); - - /* this forces alpha to 1 in make_temp_uint_image */ - if (dstFormat == MESA_FORMAT_RGBX_UINT16) { - baseFormat = GL_RGBA; - components = 4; - } - - ASSERT(dstFormat == MESA_FORMAT_R_UINT16 || - dstFormat == MESA_FORMAT_RG_UINT16 || - dstFormat == MESA_FORMAT_RGB_UINT16 || - dstFormat == MESA_FORMAT_RGBA_UINT16 || - dstFormat == MESA_FORMAT_A_UINT16 || - dstFormat == MESA_FORMAT_I_UINT16 || - dstFormat == MESA_FORMAT_L_UINT16 || - dstFormat == MESA_FORMAT_LA_UINT16 || - dstFormat == MESA_FORMAT_RGBX_UINT16); - ASSERT(baseInternalFormat == GL_RGBA || - baseInternalFormat == GL_RGB || - baseInternalFormat == GL_RG || - baseInternalFormat == GL_RED || - baseInternalFormat == GL_ALPHA || - baseInternalFormat == GL_LUMINANCE || - baseInternalFormat == GL_LUMINANCE_ALPHA || - baseInternalFormat == GL_INTENSITY); - ASSERT(_mesa_get_format_bytes(dstFormat) == components * sizeof(GLushort)); - - { - /* general path */ - const GLuint *tempImage = - make_temp_uint_image(ctx, dims, baseInternalFormat, baseFormat, - srcWidth, srcHeight, srcDepth, - srcFormat, srcType, srcAddr, srcPacking); - const GLuint *src = tempImage; - GLint img, row; - GLboolean is_unsigned = _mesa_is_type_unsigned(srcType); - if (!tempImage) - return GL_FALSE; - for (img = 0; img < srcDepth; img++) { - GLubyte *dstRow = dstSlices[img]; - for (row = 0; row < srcHeight; row++) { - GLushort *dstTexel = (GLushort *) dstRow; - GLint i; - if (is_unsigned) { - for (i = 0; i < srcWidth * components; i++) { - dstTexel[i] = (GLushort) MIN2(src[i], 0xffff); - } - } else { - for (i = 0; i < srcWidth * components; i++) { - dstTexel[i] = (GLushort) CLAMP((GLint) src[i], 0, 0xffff); - } - } - dstRow += dstRowStride; - src += srcWidth * components; - } - } - - free((void *) tempImage); - } - return GL_TRUE; -} - - -/* non-normalized, unsigned int32 */ -static GLboolean -_mesa_texstore_rgba_uint32(TEXSTORE_PARAMS) -{ - GLenum baseFormat = _mesa_get_format_base_format(dstFormat); - GLint components = _mesa_components_in_format(baseFormat); - - /* this forces alpha to 1 in make_temp_uint_image */ - if (dstFormat == MESA_FORMAT_RGBX_UINT32) { - baseFormat = GL_RGBA; - components = 4; - } - - ASSERT(dstFormat == MESA_FORMAT_R_UINT32 || - dstFormat == MESA_FORMAT_RG_UINT32 || - dstFormat == MESA_FORMAT_RGB_UINT32 || - dstFormat == MESA_FORMAT_RGBA_UINT32 || - dstFormat == MESA_FORMAT_A_UINT32 || - dstFormat == MESA_FORMAT_I_UINT32 || - dstFormat == MESA_FORMAT_L_UINT32 || - dstFormat == MESA_FORMAT_LA_UINT32 || - dstFormat == MESA_FORMAT_RGBX_UINT32); - ASSERT(baseInternalFormat == GL_RGBA || - baseInternalFormat == GL_RGB || - baseInternalFormat == GL_RG || - baseInternalFormat == GL_RED || - baseInternalFormat == GL_ALPHA || - baseInternalFormat == GL_LUMINANCE || - baseInternalFormat == GL_LUMINANCE_ALPHA || - baseInternalFormat == GL_INTENSITY); - ASSERT(_mesa_get_format_bytes(dstFormat) == components * sizeof(GLuint)); - - { - /* general path */ - const GLuint *tempImage = - make_temp_uint_image(ctx, dims, baseInternalFormat, baseFormat, - srcWidth, srcHeight, srcDepth, - srcFormat, srcType, srcAddr, srcPacking); - const GLuint *src = tempImage; - GLboolean is_unsigned = _mesa_is_type_unsigned(srcType); - GLint img, row; - if (!tempImage) - return GL_FALSE; - for (img = 0; img < srcDepth; img++) { - GLubyte *dstRow = dstSlices[img]; - for (row = 0; row < srcHeight; row++) { - GLuint *dstTexel = (GLuint *) dstRow; - GLint i; - if (is_unsigned) { - for (i = 0; i < srcWidth * components; i++) { - dstTexel[i] = src[i]; - } - } else { - for (i = 0; i < srcWidth * components; i++) { - dstTexel[i] = MAX2((GLint) src[i], 0); - } - } - dstRow += dstRowStride; - src += srcWidth * components; - } - } - - free((void *) tempImage); - } - return GL_TRUE; -} - - -static GLboolean -_mesa_texstore_srgb8(TEXSTORE_PARAMS) -{ - mesa_format newDstFormat; - GLboolean k; - - ASSERT(dstFormat == MESA_FORMAT_BGR_SRGB8); - - /* reuse normal rgb texstore code */ - newDstFormat = MESA_FORMAT_BGR_UNORM8; - - k = _mesa_texstore_rgb888(ctx, dims, baseInternalFormat, - newDstFormat, - dstRowStride, dstSlices, - srcWidth, srcHeight, srcDepth, - srcFormat, srcType, - srcAddr, srcPacking); - return k; -} - - -static GLboolean -_mesa_texstore_srgba8(TEXSTORE_PARAMS) -{ - mesa_format newDstFormat; - GLboolean k; - - ASSERT(dstFormat == MESA_FORMAT_A8B8G8R8_SRGB || - dstFormat == MESA_FORMAT_R8G8B8X8_SRGB || - dstFormat == MESA_FORMAT_R8G8B8A8_SRGB); - - newDstFormat = _mesa_get_srgb_format_linear(dstFormat); - - k = _mesa_texstore_rgba8888(ctx, dims, baseInternalFormat, - newDstFormat, - dstRowStride, dstSlices, - srcWidth, srcHeight, srcDepth, - srcFormat, srcType, - srcAddr, srcPacking); - return k; -} - - -static GLboolean -_mesa_texstore_sargb8(TEXSTORE_PARAMS) -{ - mesa_format newDstFormat; - GLboolean k; - - assert(dstFormat == MESA_FORMAT_B8G8R8A8_SRGB || - dstFormat == MESA_FORMAT_B8G8R8X8_SRGB); - - newDstFormat = _mesa_get_srgb_format_linear(dstFormat); - - k = _mesa_texstore_argb8888(ctx, dims, baseInternalFormat, - newDstFormat, - dstRowStride, dstSlices, - srcWidth, srcHeight, srcDepth, - srcFormat, srcType, - srcAddr, srcPacking); - return k; -} - - -static GLboolean -_mesa_texstore_sl8(TEXSTORE_PARAMS) -{ - mesa_format newDstFormat; - GLboolean k; - - ASSERT(dstFormat == MESA_FORMAT_L_SRGB8); - - newDstFormat = MESA_FORMAT_L_UNORM8; - - /* _mesa_textore_a8 handles luminance8 too */ - k = _mesa_texstore_unorm8(ctx, dims, baseInternalFormat, - newDstFormat, - dstRowStride, dstSlices, - srcWidth, srcHeight, srcDepth, - srcFormat, srcType, - srcAddr, srcPacking); - return k; -} - - -static GLboolean -_mesa_texstore_sla8(TEXSTORE_PARAMS) -{ - mesa_format newDstFormat; - GLboolean k; - - ASSERT(dstFormat == MESA_FORMAT_L8A8_SRGB); - - /* reuse normal luminance/alpha texstore code */ - newDstFormat = MESA_FORMAT_L8A8_UNORM; - - k = _mesa_texstore_unorm88(ctx, dims, baseInternalFormat, - newDstFormat, - dstRowStride, dstSlices, - srcWidth, srcHeight, srcDepth, - srcFormat, srcType, - srcAddr, srcPacking); - return k; -} - -static GLboolean -_mesa_texstore_rgb9_e5(TEXSTORE_PARAMS) -{ - const GLenum baseFormat = _mesa_get_format_base_format(dstFormat); - - ASSERT(dstFormat == MESA_FORMAT_R9G9B9E5_FLOAT); - ASSERT(baseInternalFormat == GL_RGB); - - { - /* general path */ - const GLfloat *tempImage = _mesa_make_temp_float_image(ctx, dims, - baseInternalFormat, - baseFormat, - srcWidth, srcHeight, srcDepth, - srcFormat, srcType, srcAddr, - srcPacking, - ctx->_ImageTransferState); - const GLfloat *srcRow = tempImage; - GLint img, row, col; - if (!tempImage) - return GL_FALSE; - for (img = 0; img < srcDepth; img++) { - GLubyte *dstRow = dstSlices[img]; - for (row = 0; row < srcHeight; row++) { - GLuint *dstUI = (GLuint*)dstRow; - for (col = 0; col < srcWidth; col++) { - dstUI[col] = float3_to_rgb9e5(&srcRow[col * 3]); - } - dstRow += dstRowStride; - srcRow += srcWidth * 3; - } - } - - free((void *) tempImage); - } - return GL_TRUE; -} - -static GLboolean -_mesa_texstore_r11_g11_b10f(TEXSTORE_PARAMS) -{ - const GLenum baseFormat = _mesa_get_format_base_format(dstFormat); - - ASSERT(dstFormat == MESA_FORMAT_R11G11B10_FLOAT); - ASSERT(baseInternalFormat == GL_RGB); - - { - /* general path */ - const GLfloat *tempImage = _mesa_make_temp_float_image(ctx, dims, - baseInternalFormat, - baseFormat, - srcWidth, srcHeight, srcDepth, - srcFormat, srcType, srcAddr, - srcPacking, - ctx->_ImageTransferState); - const GLfloat *srcRow = tempImage; - GLint img, row, col; - if (!tempImage) - return GL_FALSE; - for (img = 0; img < srcDepth; img++) { - GLubyte *dstRow = dstSlices[img]; - for (row = 0; row < srcHeight; row++) { - GLuint *dstUI = (GLuint*)dstRow; - for (col = 0; col < srcWidth; col++) { - dstUI[col] = float3_to_r11g11b10f(&srcRow[col * 3]); - } - dstRow += dstRowStride; - srcRow += srcWidth * 3; - } - } - - free((void *) tempImage); - } - return GL_TRUE; -} - - static GLboolean _mesa_texstore_z32f_x24s8(TEXSTORE_PARAMS) { @@ -3496,118 +1355,16 @@ _mesa_texstore_abgr2101010_uint(TEXSTORE_PARAMS) return GL_TRUE; } -static GLboolean -_mesa_texstore_abgr2101010(TEXSTORE_PARAMS) -{ - const GLenum baseFormat = _mesa_get_format_base_format(dstFormat); - - ASSERT(dstFormat == MESA_FORMAT_R10G10B10A2_UNORM); - ASSERT(_mesa_get_format_bytes(dstFormat) == 4); - - { - /* general path */ - const GLfloat *tempImage = _mesa_make_temp_float_image(ctx, dims, - baseInternalFormat, - baseFormat, - srcWidth, srcHeight, srcDepth, - srcFormat, srcType, srcAddr, - srcPacking, - ctx->_ImageTransferState); - const GLfloat *src = tempImage; - GLint img, row, col; - if (!tempImage) - return GL_FALSE; - for (img = 0; img < srcDepth; img++) { - GLubyte *dstRow = dstSlices[img]; - - for (row = 0; row < srcHeight; row++) { - GLuint *dstUI = (GLuint *) dstRow; - for (col = 0; col < srcWidth; col++) { - GLushort a,r,g,b; - - UNCLAMPED_FLOAT_TO_USHORT(a, src[ACOMP]); - UNCLAMPED_FLOAT_TO_USHORT(r, src[RCOMP]); - UNCLAMPED_FLOAT_TO_USHORT(g, src[GCOMP]); - UNCLAMPED_FLOAT_TO_USHORT(b, src[BCOMP]); - dstUI[col] = PACK_COLOR_2101010_US(a, b, g, r); - src += 4; - } - dstRow += dstRowStride; - } - } - free((void *) tempImage); - } - return GL_TRUE; -} static GLboolean -_mesa_texstore_null(TEXSTORE_PARAMS) -{ - (void) ctx; (void) dims; - (void) baseInternalFormat; - (void) dstFormat; - (void) dstRowStride; (void) dstSlices, - (void) srcWidth; (void) srcHeight; (void) srcDepth; - (void) srcFormat; (void) srcType; - (void) srcAddr; - (void) srcPacking; - - /* should never happen */ - _mesa_problem(NULL, "_mesa_texstore_null() is called"); - return GL_FALSE; -} - - -/** - * Return the StoreTexImageFunc pointer to store an image in the given format. - */ -static StoreTexImageFunc -_mesa_get_texstore_func(mesa_format format) +texstore_depth_stencil(TEXSTORE_PARAMS) { static StoreTexImageFunc table[MESA_FORMAT_COUNT]; static GLboolean initialized = GL_FALSE; if (!initialized) { - table[MESA_FORMAT_NONE] = _mesa_texstore_null; - - table[MESA_FORMAT_A8B8G8R8_UNORM] = _mesa_texstore_rgba8888; - table[MESA_FORMAT_R8G8B8A8_UNORM] = _mesa_texstore_rgba8888; - table[MESA_FORMAT_B8G8R8A8_UNORM] = _mesa_texstore_argb8888; - table[MESA_FORMAT_A8R8G8B8_UNORM] = _mesa_texstore_argb8888; - table[MESA_FORMAT_X8B8G8R8_UNORM] = _mesa_texstore_rgba8888; - table[MESA_FORMAT_R8G8B8X8_UNORM] = _mesa_texstore_rgba8888; - table[MESA_FORMAT_B8G8R8X8_UNORM] = _mesa_texstore_argb8888; - table[MESA_FORMAT_X8R8G8B8_UNORM] = _mesa_texstore_argb8888; - table[MESA_FORMAT_BGR_UNORM8] = _mesa_texstore_rgb888; - table[MESA_FORMAT_RGB_UNORM8] = _mesa_texstore_bgr888; - table[MESA_FORMAT_B5G6R5_UNORM] = _mesa_texstore_rgb565; - table[MESA_FORMAT_R5G6B5_UNORM] = _mesa_texstore_rgb565; - table[MESA_FORMAT_B4G4R4A4_UNORM] = store_ubyte_texture; - table[MESA_FORMAT_A4R4G4B4_UNORM] = store_ubyte_texture; - table[MESA_FORMAT_A1B5G5R5_UNORM] = store_ubyte_texture; - table[MESA_FORMAT_B5G5R5A1_UNORM] = store_ubyte_texture; - table[MESA_FORMAT_A1R5G5B5_UNORM] = store_ubyte_texture; - table[MESA_FORMAT_L4A4_UNORM] = _mesa_texstore_unorm44; - table[MESA_FORMAT_L8A8_UNORM] = _mesa_texstore_unorm88; - table[MESA_FORMAT_A8L8_UNORM] = _mesa_texstore_unorm88; - table[MESA_FORMAT_L16A16_UNORM] = _mesa_texstore_unorm1616; - table[MESA_FORMAT_A16L16_UNORM] = _mesa_texstore_unorm1616; - table[MESA_FORMAT_B2G3R3_UNORM] = store_ubyte_texture; - table[MESA_FORMAT_A_UNORM8] = _mesa_texstore_unorm8; - table[MESA_FORMAT_A_UNORM16] = _mesa_texstore_unorm16; - table[MESA_FORMAT_L_UNORM8] = _mesa_texstore_unorm8; - table[MESA_FORMAT_L_UNORM16] = _mesa_texstore_unorm16; - table[MESA_FORMAT_I_UNORM8] = _mesa_texstore_unorm8; - table[MESA_FORMAT_I_UNORM16] = _mesa_texstore_unorm16; - table[MESA_FORMAT_YCBCR] = _mesa_texstore_ycbcr; - table[MESA_FORMAT_YCBCR_REV] = _mesa_texstore_ycbcr; - table[MESA_FORMAT_R_UNORM8] = _mesa_texstore_unorm8; - table[MESA_FORMAT_R8G8_UNORM] = _mesa_texstore_unorm88; - table[MESA_FORMAT_G8R8_UNORM] = _mesa_texstore_unorm88; - table[MESA_FORMAT_R_UNORM16] = _mesa_texstore_unorm16; - table[MESA_FORMAT_R16G16_UNORM] = _mesa_texstore_unorm1616; - table[MESA_FORMAT_G16R16_UNORM] = _mesa_texstore_unorm1616; - table[MESA_FORMAT_B10G10R10A2_UNORM] = _mesa_texstore_argb2101010; + memset(table, 0, sizeof table); + table[MESA_FORMAT_S8_UINT_Z24_UNORM] = _mesa_texstore_z24_s8; table[MESA_FORMAT_Z24_UNORM_S8_UINT] = _mesa_texstore_s8_z24; table[MESA_FORMAT_Z_UNORM16] = _mesa_texstore_z16; @@ -3615,11 +1372,28 @@ _mesa_get_texstore_func(mesa_format format) table[MESA_FORMAT_X8_UINT_Z24_UNORM] = _mesa_texstore_z24_x8; table[MESA_FORMAT_Z_UNORM32] = _mesa_texstore_z32; table[MESA_FORMAT_S_UINT8] = _mesa_texstore_s8; - table[MESA_FORMAT_BGR_SRGB8] = _mesa_texstore_srgb8; - table[MESA_FORMAT_A8B8G8R8_SRGB] = _mesa_texstore_srgba8; - table[MESA_FORMAT_B8G8R8A8_SRGB] = _mesa_texstore_sargb8; - table[MESA_FORMAT_L_SRGB8] = _mesa_texstore_sl8; - table[MESA_FORMAT_L8A8_SRGB] = _mesa_texstore_sla8; + table[MESA_FORMAT_Z_FLOAT32] = _mesa_texstore_z32; + table[MESA_FORMAT_Z32_FLOAT_S8X24_UINT] = _mesa_texstore_z32f_x24s8; + + initialized = GL_TRUE; + } + + ASSERT(table[dstFormat]); + return table[dstFormat](ctx, dims, baseInternalFormat, + dstFormat, dstRowStride, dstSlices, + srcWidth, srcHeight, srcDepth, + srcFormat, srcType, srcAddr, srcPacking); +} + +static GLboolean +texstore_compressed(TEXSTORE_PARAMS) +{ + static StoreTexImageFunc table[MESA_FORMAT_COUNT]; + static GLboolean initialized = GL_FALSE; + + if (!initialized) { + memset(table, 0, sizeof table); + table[MESA_FORMAT_SRGB_DXT1] = _mesa_texstore_rgb_dxt1; table[MESA_FORMAT_SRGBA_DXT1] = _mesa_texstore_rgba_dxt1; table[MESA_FORMAT_SRGBA_DXT3] = _mesa_texstore_rgba_dxt3; @@ -3630,32 +1404,6 @@ _mesa_get_texstore_func(mesa_format format) table[MESA_FORMAT_RGBA_DXT1] = _mesa_texstore_rgba_dxt1; table[MESA_FORMAT_RGBA_DXT3] = _mesa_texstore_rgba_dxt3; table[MESA_FORMAT_RGBA_DXT5] = _mesa_texstore_rgba_dxt5; - table[MESA_FORMAT_RGBA_FLOAT32] = _mesa_texstore_rgba_float32; - table[MESA_FORMAT_RGBA_FLOAT16] = _mesa_texstore_rgba_float16; - table[MESA_FORMAT_RGB_FLOAT32] = _mesa_texstore_rgba_float32; - table[MESA_FORMAT_RGB_FLOAT16] = _mesa_texstore_rgba_float16; - table[MESA_FORMAT_A_FLOAT32] = _mesa_texstore_rgba_float32; - table[MESA_FORMAT_A_FLOAT16] = _mesa_texstore_rgba_float16; - table[MESA_FORMAT_L_FLOAT32] = _mesa_texstore_rgba_float32; - table[MESA_FORMAT_L_FLOAT16] = _mesa_texstore_rgba_float16; - table[MESA_FORMAT_LA_FLOAT32] = _mesa_texstore_rgba_float32; - table[MESA_FORMAT_LA_FLOAT16] = _mesa_texstore_rgba_float16; - table[MESA_FORMAT_I_FLOAT32] = _mesa_texstore_rgba_float32; - table[MESA_FORMAT_I_FLOAT16] = _mesa_texstore_rgba_float16; - table[MESA_FORMAT_R_FLOAT32] = _mesa_texstore_rgba_float32; - table[MESA_FORMAT_R_FLOAT16] = _mesa_texstore_rgba_float16; - table[MESA_FORMAT_RG_FLOAT32] = _mesa_texstore_rgba_float32; - table[MESA_FORMAT_RG_FLOAT16] = _mesa_texstore_rgba_float16; - table[MESA_FORMAT_R_SNORM8] = _mesa_texstore_snorm8; - table[MESA_FORMAT_R8G8_SNORM] = _mesa_texstore_snorm88; - table[MESA_FORMAT_X8B8G8R8_SNORM] = _mesa_texstore_signed_rgbx8888; - table[MESA_FORMAT_A8B8G8R8_SNORM] = _mesa_texstore_signed_rgba8888; - table[MESA_FORMAT_R8G8B8A8_SNORM] = _mesa_texstore_signed_rgba8888; - table[MESA_FORMAT_R_SNORM16] = _mesa_texstore_snorm16; - table[MESA_FORMAT_R16G16_SNORM] = _mesa_texstore_snorm1616; - table[MESA_FORMAT_RGB_SNORM16] = _mesa_texstore_signed_rgba_16; - table[MESA_FORMAT_RGBA_SNORM16] = _mesa_texstore_signed_rgba_16; - table[MESA_FORMAT_RGBA_UNORM16] = _mesa_texstore_rgba_16; table[MESA_FORMAT_R_RGTC1_UNORM] = _mesa_texstore_red_rgtc1; table[MESA_FORMAT_R_RGTC1_SNORM] = _mesa_texstore_signed_red_rgtc1; table[MESA_FORMAT_RG_RGTC2_UNORM] = _mesa_texstore_rg_rgtc2; @@ -3677,107 +1425,327 @@ _mesa_get_texstore_func(mesa_format format) _mesa_texstore_etc2_rgb8_punchthrough_alpha1; table[MESA_FORMAT_ETC2_SRGB8_PUNCHTHROUGH_ALPHA1] = _mesa_texstore_etc2_srgb8_punchthrough_alpha1; - table[MESA_FORMAT_A_SNORM8] = _mesa_texstore_snorm8; - table[MESA_FORMAT_L_SNORM8] = _mesa_texstore_snorm8; - table[MESA_FORMAT_L8A8_SNORM] = _mesa_texstore_snorm88; - table[MESA_FORMAT_I_SNORM8] = _mesa_texstore_snorm8; - table[MESA_FORMAT_A_SNORM16] = _mesa_texstore_snorm16; - table[MESA_FORMAT_L_SNORM16] = _mesa_texstore_snorm16; - table[MESA_FORMAT_LA_SNORM16] = _mesa_texstore_snorm1616; - table[MESA_FORMAT_I_SNORM16] = _mesa_texstore_snorm16; - table[MESA_FORMAT_R9G9B9E5_FLOAT] = _mesa_texstore_rgb9_e5; - table[MESA_FORMAT_R11G11B10_FLOAT] = _mesa_texstore_r11_g11_b10f; - table[MESA_FORMAT_Z_FLOAT32] = _mesa_texstore_z32; - table[MESA_FORMAT_Z32_FLOAT_S8X24_UINT] = _mesa_texstore_z32f_x24s8; - table[MESA_FORMAT_A_UINT8] = _mesa_texstore_rgba_uint8; - table[MESA_FORMAT_A_UINT16] = _mesa_texstore_rgba_uint16; - table[MESA_FORMAT_A_UINT32] = _mesa_texstore_rgba_uint32; - table[MESA_FORMAT_A_SINT8] = _mesa_texstore_rgba_int8; - table[MESA_FORMAT_A_SINT16] = _mesa_texstore_rgba_int16; - table[MESA_FORMAT_A_SINT32] = _mesa_texstore_rgba_int32; - - table[MESA_FORMAT_I_UINT8] = _mesa_texstore_rgba_uint8; - table[MESA_FORMAT_I_UINT16] = _mesa_texstore_rgba_uint16; - table[MESA_FORMAT_I_UINT32] = _mesa_texstore_rgba_uint32; - table[MESA_FORMAT_I_SINT8] = _mesa_texstore_rgba_int8; - table[MESA_FORMAT_I_SINT16] = _mesa_texstore_rgba_int16; - table[MESA_FORMAT_I_SINT32] = _mesa_texstore_rgba_int32; - - table[MESA_FORMAT_L_UINT8] = _mesa_texstore_rgba_uint8; - table[MESA_FORMAT_L_UINT16] = _mesa_texstore_rgba_uint16; - table[MESA_FORMAT_L_UINT32] = _mesa_texstore_rgba_uint32; - table[MESA_FORMAT_L_SINT8] = _mesa_texstore_rgba_int8; - table[MESA_FORMAT_L_SINT16] = _mesa_texstore_rgba_int16; - table[MESA_FORMAT_L_SINT32] = _mesa_texstore_rgba_int32; - - table[MESA_FORMAT_LA_UINT8] = _mesa_texstore_rgba_uint8; - table[MESA_FORMAT_LA_UINT16] = _mesa_texstore_rgba_uint16; - table[MESA_FORMAT_LA_UINT32] = _mesa_texstore_rgba_uint32; - table[MESA_FORMAT_LA_SINT8] = _mesa_texstore_rgba_int8; - table[MESA_FORMAT_LA_SINT16] = _mesa_texstore_rgba_int16; - table[MESA_FORMAT_LA_SINT32] = _mesa_texstore_rgba_int32; - - table[MESA_FORMAT_R_SINT8] = _mesa_texstore_rgba_int8; - table[MESA_FORMAT_RG_SINT8] = _mesa_texstore_rgba_int8; - table[MESA_FORMAT_RGB_SINT8] = _mesa_texstore_rgba_int8; - table[MESA_FORMAT_RGBA_SINT8] = _mesa_texstore_rgba_int8; - table[MESA_FORMAT_R_SINT16] = _mesa_texstore_rgba_int16; - table[MESA_FORMAT_RG_SINT16] = _mesa_texstore_rgba_int16; - table[MESA_FORMAT_RGB_SINT16] = _mesa_texstore_rgba_int16; - table[MESA_FORMAT_RGBA_SINT16] = _mesa_texstore_rgba_int16; - table[MESA_FORMAT_R_SINT32] = _mesa_texstore_rgba_int32; - table[MESA_FORMAT_RG_SINT32] = _mesa_texstore_rgba_int32; - table[MESA_FORMAT_RGB_SINT32] = _mesa_texstore_rgba_int32; - table[MESA_FORMAT_RGBA_SINT32] = _mesa_texstore_rgba_int32; - - table[MESA_FORMAT_R_UINT8] = _mesa_texstore_rgba_uint8; - table[MESA_FORMAT_RG_UINT8] = _mesa_texstore_rgba_uint8; - table[MESA_FORMAT_RGB_UINT8] = _mesa_texstore_rgba_uint8; - table[MESA_FORMAT_RGBA_UINT8] = _mesa_texstore_rgba_uint8; - table[MESA_FORMAT_R_UINT16] = _mesa_texstore_rgba_uint16; - table[MESA_FORMAT_RG_UINT16] = _mesa_texstore_rgba_uint16; - table[MESA_FORMAT_RGB_UINT16] = _mesa_texstore_rgba_uint16; - table[MESA_FORMAT_RGBA_UINT16] = _mesa_texstore_rgba_uint16; - table[MESA_FORMAT_R_UINT32] = _mesa_texstore_rgba_uint32; - table[MESA_FORMAT_RG_UINT32] = _mesa_texstore_rgba_uint32; - table[MESA_FORMAT_RGB_UINT32] = _mesa_texstore_rgba_uint32; - table[MESA_FORMAT_RGBA_UINT32] = _mesa_texstore_rgba_uint32; + initialized = GL_TRUE; + } + + ASSERT(table[dstFormat]); + return table[dstFormat](ctx, dims, baseInternalFormat, + dstFormat, dstRowStride, dstSlices, + srcWidth, srcHeight, srcDepth, + srcFormat, srcType, srcAddr, srcPacking); +} + +static void +invert_swizzle(uint8_t dst[4], const uint8_t src[4]) +{ + int i, j; + + dst[0] = MESA_FORMAT_SWIZZLE_NONE; + dst[1] = MESA_FORMAT_SWIZZLE_NONE; + dst[2] = MESA_FORMAT_SWIZZLE_NONE; + dst[3] = MESA_FORMAT_SWIZZLE_NONE; + + for (i = 0; i < 4; ++i) + for (j = 0; j < 4; ++j) + if (src[j] == i && dst[i] == MESA_FORMAT_SWIZZLE_NONE) + dst[i] = j; +} + +/** Store a texture by per-channel conversions and swizzling. + * + * This function attempts to perform a texstore operation by doing simple + * per-channel conversions and swizzling. This covers a huge chunk of the + * texture storage operations that anyone cares about. If this function is + * incapable of performing the operation, it bails and returns GL_FALSE. + */ +static GLboolean +texstore_swizzle(TEXSTORE_PARAMS) +{ + const GLint srcRowStride = _mesa_image_row_stride(srcPacking, srcWidth, + srcFormat, srcType); + const GLint srcImageStride = _mesa_image_image_stride(srcPacking, + srcWidth, srcHeight, srcFormat, srcType); + const GLubyte *srcImage = (const GLubyte *) _mesa_image_address(dims, + srcPacking, srcAddr, srcWidth, srcHeight, srcFormat, srcType, 0, 0, 0); + const int src_components = _mesa_components_in_format(srcFormat); + + GLubyte swizzle[4], rgba2base[6], base2src[6], rgba2dst[4], dst2rgba[4]; + const GLubyte *swap; + GLenum dst_type; + int dst_components; + bool is_array, normalized, need_swap; + GLint i, img, row; + const GLubyte *src_row; + GLubyte *dst_row; + + is_array = _mesa_format_to_array(dstFormat, &dst_type, &dst_components, + rgba2dst, &normalized); + + if (!is_array) + return GL_FALSE; + + switch (srcType) { + case GL_FLOAT: + case GL_UNSIGNED_BYTE: + case GL_BYTE: + case GL_UNSIGNED_SHORT: + case GL_SHORT: + case GL_UNSIGNED_INT: + case GL_INT: + /* If wa have to swap bytes in a multi-byte datatype, that means + * we're not doing an array conversion anymore */ + if (srcPacking->SwapBytes) + return GL_FALSE; + need_swap = false; + break; + case GL_UNSIGNED_INT_8_8_8_8: + need_swap = srcPacking->SwapBytes; + if (_mesa_little_endian()) + need_swap = !need_swap; + srcType = GL_UNSIGNED_BYTE; + break; + case GL_UNSIGNED_INT_8_8_8_8_REV: + need_swap = srcPacking->SwapBytes; + if (!_mesa_little_endian()) + need_swap = !need_swap; + srcType = GL_UNSIGNED_BYTE; + break; + default: + return GL_FALSE; + } + swap = need_swap ? map_3210 : map_identity; + + compute_component_mapping(srcFormat, baseInternalFormat, base2src); + compute_component_mapping(baseInternalFormat, GL_RGBA, rgba2base); + invert_swizzle(dst2rgba, rgba2dst); + + for (i = 0; i < 4; i++) { + if (dst2rgba[i] == MESA_FORMAT_SWIZZLE_NONE) + swizzle[i] = MESA_FORMAT_SWIZZLE_NONE; + else + swizzle[i] = swap[base2src[rgba2base[dst2rgba[i]]]]; + } + + /* Is it normalized? */ + normalized |= !_mesa_is_enum_format_integer(srcFormat); + + for (img = 0; img < srcDepth; img++) { + if (dstRowStride == srcWidth * dst_components && + srcRowStride == srcWidth * src_components) { + _mesa_swizzle_and_convert(dstSlices[img], dst_type, dst_components, + srcImage, srcType, src_components, + swizzle, normalized, srcWidth * srcHeight); + } else { + src_row = srcImage; + dst_row = dstSlices[img]; + for (row = 0; row < srcHeight; row++) { + _mesa_swizzle_and_convert(dst_row, dst_type, dst_components, + src_row, srcType, src_components, + swizzle, normalized, srcWidth); + dst_row += dstRowStride; + src_row += srcRowStride; + } + } + srcImage += srcImageStride; + } + + return GL_TRUE; +} + + +/** Stores a texture by converting float and then to the texture format + * + * This function performs a texstore operation by converting to float, + * applying pixel transfer ops, and then converting to the texture's + * internal format using pixel store functions. This function will work + * for any rgb or srgb textore format. + */ +static GLboolean +texstore_via_float(TEXSTORE_PARAMS) +{ + GLuint i, img, row; + const GLint src_stride = + _mesa_image_row_stride(srcPacking, srcWidth, srcFormat, srcType); + float *tmp_row; + bool need_convert; + uint8_t *src_row, *dst_row, map[4], rgba2base[6], base2rgba[6]; + + tmp_row = malloc(srcWidth * 4 * sizeof(*tmp_row)); + if (!tmp_row) + return GL_FALSE; + + /* The GL spec (4.0, compatibility profile) only specifies srgb + * conversion as something that is done in the sampler during the + * filtering process before the colors are handed to the shader. + * Furthermore, the flowchart (Figure 3.7 in the 4.0 compatibility spec) + * does not list RGB <-> sRGB conversions anywhere. Therefore, we just + * treat sRGB formats the same as RGB formats for the purposes of + * texture upload and transfer ops. + */ + dstFormat = _mesa_get_srgb_format_linear(dstFormat); + + need_convert = false; + if (baseInternalFormat != _mesa_get_format_base_format(dstFormat)) { + compute_component_mapping(GL_RGBA, baseInternalFormat, base2rgba); + compute_component_mapping(baseInternalFormat, GL_RGBA, rgba2base); + for (i = 0; i < 4; ++i) { + map[i] = base2rgba[rgba2base[i]]; + if (map[i] != i) + need_convert = true; + } + } + + for (img = 0; img < srcDepth; img++) { + dst_row = dstSlices[img]; + src_row = _mesa_image_address(dims, srcPacking, srcAddr, + srcWidth, srcHeight, + srcFormat, srcType, + img, 0, 0); + for (row = 0; row < srcHeight; row++) { + _mesa_unpack_color_span_float(ctx, srcWidth, GL_RGBA, tmp_row, + srcFormat, srcType, src_row, + srcPacking, ctx->_ImageTransferState); + if (need_convert) + _mesa_swizzle_and_convert(tmp_row, GL_FLOAT, 4, + tmp_row, GL_FLOAT, 4, + map, false, srcWidth); + _mesa_pack_float_rgba_row(dstFormat, srcWidth, + (const GLfloat (*)[4])tmp_row, + dst_row); + dst_row += dstRowStride; + src_row += src_stride; + } + } + + return GL_TRUE; +} + +/** Stores an integer rgba texture + * + * This function performs an integer texture storage operation by unpacking + * the texture to 32-bit integers, and repacking it into the internal + * format of the texture. This will work for any integer rgb texture + * storage operation. + */ +static GLboolean +texstore_rgba_integer(TEXSTORE_PARAMS) +{ + GLuint i, img, row, *tmp_row; + GLenum dst_type, tmp_type; + const GLint src_stride = + _mesa_image_row_stride(srcPacking, srcWidth, srcFormat, srcType); + int num_dst_components; + bool is_array, normalized; + uint8_t *src_row, *dst_row; + uint8_t swizzle[4], rgba2base[6], base2rgba[6], rgba2dst[4], dst2rgba[4]; + + tmp_row = malloc(srcWidth * 4 * sizeof(*tmp_row)); + if (!tmp_row) + return GL_FALSE; + + is_array = _mesa_format_to_array(dstFormat, &dst_type, &num_dst_components, + rgba2dst, &normalized); + + assert(is_array && !normalized); + + if (!is_array) + return GL_FALSE; + + invert_swizzle(dst2rgba, rgba2dst); + compute_component_mapping(GL_RGBA, baseInternalFormat, base2rgba); + compute_component_mapping(baseInternalFormat, GL_RGBA, rgba2base); + + for (i = 0; i < 4; ++i) { + if (dst2rgba[i] == MESA_FORMAT_SWIZZLE_NONE) + swizzle[i] = MESA_FORMAT_SWIZZLE_NONE; + else + swizzle[i] = base2rgba[rgba2base[dst2rgba[i]]]; + } + + if (_mesa_is_type_unsigned(srcType)) { + tmp_type = GL_UNSIGNED_INT; + } else { + tmp_type = GL_INT; + } + + for (img = 0; img < srcDepth; img++) { + dst_row = dstSlices[img]; + src_row = _mesa_image_address(dims, srcPacking, srcAddr, + srcWidth, srcHeight, + srcFormat, srcType, + img, 0, 0); + for (row = 0; row < srcHeight; row++) { + _mesa_unpack_color_span_uint(ctx, srcWidth, GL_RGBA, tmp_row, + srcFormat, srcType, src_row, srcPacking); + _mesa_swizzle_and_convert(dst_row, dst_type, num_dst_components, + tmp_row, tmp_type, 4, + swizzle, false, srcWidth); + dst_row += dstRowStride; + src_row += src_stride; + } + } + + return GL_TRUE; +} + +static GLboolean +texstore_rgba(TEXSTORE_PARAMS) +{ + static StoreTexImageFunc table[MESA_FORMAT_COUNT]; + static GLboolean initialized = GL_FALSE; + + if (!initialized) { + memset(table, 0, sizeof table); + + table[MESA_FORMAT_B5G6R5_UNORM] = _mesa_texstore_rgb565; + table[MESA_FORMAT_R5G6B5_UNORM] = _mesa_texstore_rgb565; + table[MESA_FORMAT_YCBCR] = _mesa_texstore_ycbcr; + table[MESA_FORMAT_YCBCR_REV] = _mesa_texstore_ycbcr; table[MESA_FORMAT_B10G10R10A2_UINT] = _mesa_texstore_argb2101010_uint; table[MESA_FORMAT_R10G10B10A2_UINT] = _mesa_texstore_abgr2101010_uint; - table[MESA_FORMAT_B4G4R4X4_UNORM] = store_ubyte_texture; - table[MESA_FORMAT_B5G5R5X1_UNORM] = store_ubyte_texture; - table[MESA_FORMAT_R8G8B8X8_SNORM] = _mesa_texstore_signed_rgbx8888; - table[MESA_FORMAT_R8G8B8X8_SRGB] = _mesa_texstore_srgba8; - table[MESA_FORMAT_R8G8B8A8_SRGB] = _mesa_texstore_srgba8; - table[MESA_FORMAT_RGBX_UINT8] = _mesa_texstore_rgba_uint8; - table[MESA_FORMAT_RGBX_SINT8] = _mesa_texstore_rgba_int8; - table[MESA_FORMAT_B10G10R10X2_UNORM] = _mesa_texstore_argb2101010; - table[MESA_FORMAT_RGBX_UNORM16] = _mesa_texstore_rgba_16; - table[MESA_FORMAT_RGBX_SNORM16] = _mesa_texstore_signed_rgba_16; - table[MESA_FORMAT_RGBX_FLOAT16] = _mesa_texstore_rgba_float16; - table[MESA_FORMAT_RGBX_UINT16] = _mesa_texstore_rgba_uint16; - table[MESA_FORMAT_RGBX_SINT16] = _mesa_texstore_rgba_int16; - table[MESA_FORMAT_RGBX_FLOAT32] = _mesa_texstore_rgba_float32; - table[MESA_FORMAT_RGBX_UINT32] = _mesa_texstore_rgba_uint32; - table[MESA_FORMAT_RGBX_SINT32] = _mesa_texstore_rgba_int32; - - table[MESA_FORMAT_R10G10B10A2_UNORM] = _mesa_texstore_abgr2101010; - - table[MESA_FORMAT_G8R8_SNORM] = _mesa_texstore_snorm88; - table[MESA_FORMAT_G16R16_SNORM] = _mesa_texstore_snorm1616; - - table[MESA_FORMAT_B8G8R8X8_SRGB] = _mesa_texstore_sargb8; - initialized = GL_TRUE; } - ASSERT(table[format]); - return table[format]; -} + if (table[dstFormat] && table[dstFormat](ctx, dims, baseInternalFormat, + dstFormat, dstRowStride, dstSlices, + srcWidth, srcHeight, srcDepth, + srcFormat, srcType, srcAddr, + srcPacking)) { + return GL_TRUE; + } + + if (texstore_swizzle(ctx, dims, baseInternalFormat, + dstFormat, + dstRowStride, dstSlices, + srcWidth, srcHeight, srcDepth, + srcFormat, srcType, srcAddr, srcPacking)) { + return GL_TRUE; + } + if (_mesa_is_format_integer(dstFormat)) { + return texstore_rgba_integer(ctx, dims, baseInternalFormat, + dstFormat, dstRowStride, dstSlices, + srcWidth, srcHeight, srcDepth, + srcFormat, srcType, srcAddr, + srcPacking); + } else if (_mesa_get_format_max_bits(dstFormat) <= 8 && + !_mesa_is_format_signed(dstFormat)) { + return store_ubyte_texture(ctx, dims, baseInternalFormat, + dstFormat, + dstRowStride, dstSlices, + srcWidth, srcHeight, srcDepth, + srcFormat, srcType, srcAddr, srcPacking); + } else { + return texstore_via_float(ctx, dims, baseInternalFormat, + dstFormat, dstRowStride, dstSlices, + srcWidth, srcHeight, srcDepth, + srcFormat, srcType, srcAddr, + srcPacking); + } +} GLboolean _mesa_texstore_needs_transfer_ops(struct gl_context *ctx, @@ -3863,8 +1831,6 @@ _mesa_texstore_memcpy(TEXSTORE_PARAMS) srcAddr, srcPacking); return GL_TRUE; } - - /** * Store user data into texture memory. * Called via glTex[Sub]Image1/2/3D() @@ -3873,9 +1839,6 @@ _mesa_texstore_memcpy(TEXSTORE_PARAMS) GLboolean _mesa_texstore(TEXSTORE_PARAMS) { - StoreTexImageFunc storeImage; - GLboolean success; - if (_mesa_texstore_memcpy(ctx, dims, baseInternalFormat, dstFormat, dstRowStride, dstSlices, @@ -3884,14 +1847,22 @@ _mesa_texstore(TEXSTORE_PARAMS) return GL_TRUE; } - storeImage = _mesa_get_texstore_func(dstFormat); - - success = storeImage(ctx, dims, baseInternalFormat, - dstFormat, - dstRowStride, dstSlices, - srcWidth, srcHeight, srcDepth, - srcFormat, srcType, srcAddr, srcPacking); - return success; + if (_mesa_is_depth_or_stencil_format(baseInternalFormat)) { + return texstore_depth_stencil(ctx, dims, baseInternalFormat, + dstFormat, dstRowStride, dstSlices, + srcWidth, srcHeight, srcDepth, + srcFormat, srcType, srcAddr, srcPacking); + } else if (_mesa_is_format_compressed(dstFormat)) { + return texstore_compressed(ctx, dims, baseInternalFormat, + dstFormat, dstRowStride, dstSlices, + srcWidth, srcHeight, srcDepth, + srcFormat, srcType, srcAddr, srcPacking); + } else { + return texstore_rgba(ctx, dims, baseInternalFormat, + dstFormat, dstRowStride, dstSlices, + srcWidth, srcHeight, srcDepth, + srcFormat, srcType, srcAddr, srcPacking); + } } diff --git a/mesalib/src/mesa/main/textureview.c b/mesalib/src/mesa/main/textureview.c index 77a3b782b..b3521e219 100644 --- a/mesalib/src/mesa/main/textureview.c +++ b/mesalib/src/mesa/main/textureview.c @@ -320,15 +320,11 @@ target_valid(struct gl_context *ctx, GLenum origTarget, GLenum newTarget) * If an error is found, record it with _mesa_error() * \return false if any error, true otherwise. */ -static bool -compatible_format(struct gl_context *ctx, const struct gl_texture_object *origTexObj, - GLenum internalformat) +GLboolean +_mesa_texture_view_compatible_format(struct gl_context *ctx, + GLenum origInternalFormat, + GLenum newInternalFormat) { - /* Level 0 of a texture created by glTextureStorage or glTextureView - * is always defined. - */ - struct gl_texture_image *texImage = origTexObj->Image[0][0]; - GLint origInternalFormat = texImage->InternalFormat; unsigned int origViewClass, newViewClass; /* The two textures' internal formats must be compatible according to @@ -337,19 +333,15 @@ compatible_format(struct gl_context *ctx, const struct gl_texture_object *origTe * The internal formats must be identical if not in that table, * or an INVALID_OPERATION error is generated. */ - if (origInternalFormat == internalformat) - return true; + if (origInternalFormat == newInternalFormat) + return GL_TRUE; origViewClass = lookup_view_class(ctx, origInternalFormat); - newViewClass = lookup_view_class(ctx, internalformat); + newViewClass = lookup_view_class(ctx, newInternalFormat); if ((origViewClass == newViewClass) && origViewClass != false) - return true; + return GL_TRUE; - _mesa_error(ctx, GL_INVALID_OPERATION, - "glTextureView(internalformat %s not compatible with origtexture %s)", - _mesa_lookup_enum_by_nr(internalformat), - _mesa_lookup_enum_by_nr(origInternalFormat)); - return false; + return GL_FALSE; } /** * Helper function for TexStorage and teximagemultisample to set immutable @@ -512,8 +504,14 @@ _mesa_TextureView(GLuint texture, GLenum target, GLuint origtexture, return; } - if (!compatible_format(ctx, origTexObj, internalformat)) { - return; /* Error logged */ + if (!_mesa_texture_view_compatible_format(ctx, + origTexObj->Image[0][0]->InternalFormat, + internalformat)) { + _mesa_error(ctx, GL_INVALID_OPERATION, + "glTextureView(internalformat %s not compatible with origtexture %s)", + _mesa_lookup_enum_by_nr(internalformat), + _mesa_lookup_enum_by_nr(origTexObj->Image[0][0]->InternalFormat)); + return; } texFormat = _mesa_choose_texture_format(ctx, texObj, target, 0, diff --git a/mesalib/src/mesa/main/textureview.h b/mesalib/src/mesa/main/textureview.h index 3088ac193..549a13cd8 100644 --- a/mesalib/src/mesa/main/textureview.h +++ b/mesalib/src/mesa/main/textureview.h @@ -29,6 +29,10 @@ #ifndef TEXTUREVIEW_H #define TEXTUREVIEW_H +GLboolean +_mesa_texture_view_compatible_format(struct gl_context *ctx, + GLenum origInternalFormat, + GLenum newInternalFormat); extern void GLAPIENTRY _mesa_TextureView(GLuint texture, GLenum target, GLuint origtexture, diff --git a/mesalib/src/mesa/main/uniform_query.cpp b/mesalib/src/mesa/main/uniform_query.cpp index 609d94bd7..7e630e65b 100644 --- a/mesalib/src/mesa/main/uniform_query.cpp +++ b/mesalib/src/mesa/main/uniform_query.cpp @@ -171,18 +171,17 @@ _mesa_GetActiveUniformsiv(GLuint program, _mesa_error(ctx, GL_INVALID_ENUM, "glGetActiveUniformsiv(pname)"); } -static bool +static struct gl_uniform_storage * validate_uniform_parameters(struct gl_context *ctx, struct gl_shader_program *shProg, GLint location, GLsizei count, - unsigned *loc, unsigned *array_index, const char *caller, bool negative_one_is_not_valid) { if (!shProg || !shProg->LinkStatus) { _mesa_error(ctx, GL_INVALID_OPERATION, "%s(program not linked)", caller); - return false; + return NULL; } if (location == -1) { @@ -214,7 +213,7 @@ validate_uniform_parameters(struct gl_context *ctx, caller, location); } - return false; + return NULL; } /* From page 12 (page 26 of the PDF) of the OpenGL 2.1 spec: @@ -224,7 +223,7 @@ validate_uniform_parameters(struct gl_context *ctx, */ if (count < 0) { _mesa_error(ctx, GL_INVALID_VALUE, "%s(count < 0)", caller); - return false; + return NULL; } /* Page 82 (page 96 of the PDF) of the OpenGL 2.1 spec says: @@ -243,14 +242,14 @@ validate_uniform_parameters(struct gl_context *ctx, if (location < -1) { _mesa_error(ctx, GL_INVALID_OPERATION, "%s(location=%d)", caller, location); - return false; + return NULL; } /* Check that the given location is in bounds of uniform remap table. */ if (location >= (GLint) shProg->NumUniformRemapTable) { _mesa_error(ctx, GL_INVALID_OPERATION, "%s(location=%d)", caller, location); - return false; + return NULL; } /* If the driver storage pointer in remap table is -1, we ignore silently. @@ -266,30 +265,33 @@ validate_uniform_parameters(struct gl_context *ctx, */ if (shProg->UniformRemapTable[location] == INACTIVE_UNIFORM_EXPLICIT_LOCATION) - return false; + return NULL; - _mesa_uniform_split_location_offset(shProg, location, loc, array_index); + struct gl_uniform_storage *const uni = shProg->UniformRemapTable[location]; - if (shProg->UniformStorage[*loc].array_elements == 0 && count > 1) { + if (uni->array_elements == 0 && count > 1) { _mesa_error(ctx, GL_INVALID_OPERATION, "%s(count > 1 for non-array, location=%d)", caller, location); - return false; + return NULL; } + /* The array index specified by the uniform location is just the uniform + * location minus the base location of of the uniform. + */ + *array_index = location - uni->remap_location; + /* If the uniform is an array, check that array_index is in bounds. * If not an array, check that array_index is zero. * array_index is unsigned so no need to check for less than zero. */ - unsigned limit = shProg->UniformStorage[*loc].array_elements; - if (limit == 0) - limit = 1; + const unsigned limit = MAX2(uni->array_elements, 1); if (*array_index >= limit) { _mesa_error(ctx, GL_INVALID_OPERATION, "%s(location=%d)", caller, location); - return false; + return NULL; } - return true; + return uni; } /** @@ -302,15 +304,14 @@ _mesa_get_uniform(struct gl_context *ctx, GLuint program, GLint location, { struct gl_shader_program *shProg = _mesa_lookup_shader_program_err(ctx, program, "glGetUniformfv"); - struct gl_uniform_storage *uni; - unsigned loc, offset; + unsigned offset; - if (!validate_uniform_parameters(ctx, shProg, location, 1, - &loc, &offset, "glGetUniform", true)) + struct gl_uniform_storage *const uni = + validate_uniform_parameters(ctx, shProg, location, 1, + &offset, "glGetUniform", true); + if (uni == NULL) return; - uni = &shProg->UniformStorage[loc]; - { unsigned elements = (uni->type->is_sampler()) ? 1 : uni->type->components(); @@ -607,18 +608,17 @@ _mesa_uniform(struct gl_context *ctx, struct gl_shader_program *shProg, GLint location, GLsizei count, const GLvoid *values, GLenum type) { - unsigned loc, offset; + unsigned offset; unsigned components; unsigned src_components; enum glsl_base_type basicType; - struct gl_uniform_storage *uni; - if (!validate_uniform_parameters(ctx, shProg, location, count, - &loc, &offset, "glUniform", false)) + struct gl_uniform_storage *const uni = + validate_uniform_parameters(ctx, shProg, location, count, + &offset, "glUniform", false); + if (uni == NULL) return; - uni = &shProg->UniformStorage[loc]; - /* Verify that the types are compatible. */ switch (type) { @@ -894,17 +894,17 @@ _mesa_uniform_matrix(struct gl_context *ctx, struct gl_shader_program *shProg, GLint location, GLsizei count, GLboolean transpose, const GLfloat *values) { - unsigned loc, offset; + unsigned offset; unsigned vectors; unsigned components; unsigned elements; - struct gl_uniform_storage *uni; - if (!validate_uniform_parameters(ctx, shProg, location, count, - &loc, &offset, "glUniformMatrix", false)) + struct gl_uniform_storage *const uni = + validate_uniform_parameters(ctx, shProg, location, count, + &offset, "glUniformMatrix", false); + if (uni == NULL) return; - uni = &shProg->UniformStorage[loc]; if (!uni->type->is_matrix()) { _mesa_error(ctx, GL_INVALID_OPERATION, "glUniformMatrix(non-matrix uniform)"); @@ -993,9 +993,7 @@ _mesa_uniform_matrix(struct gl_context *ctx, struct gl_shader_program *shProg, * * Returns the uniform index into UniformStorage (also the * glGetActiveUniformsiv uniform index), and stores the referenced - * array offset in *offset, or GL_INVALID_INDEX (-1). Those two - * return values can be encoded into a uniform location for - * glUniform* using _mesa_uniform_merge_location_offset(index, offset). + * array offset in *offset, or GL_INVALID_INDEX (-1). */ extern "C" unsigned _mesa_get_uniform_location(struct gl_context *ctx, diff --git a/mesalib/src/mesa/main/uniforms.c b/mesalib/src/mesa/main/uniforms.c index f450173af..0d0cbf57e 100644 --- a/mesalib/src/mesa/main/uniforms.c +++ b/mesalib/src/mesa/main/uniforms.c @@ -932,7 +932,8 @@ _mesa_GetUniformLocation(GLuint programObj, const GLcharARB *name) shProg->UniformStorage[index].atomic_buffer_index != -1) return -1; - return _mesa_uniform_merge_location_offset(shProg, index, offset); + /* location in remap table + array element offset */ + return shProg->UniformStorage[index].remap_location + offset; } GLuint GLAPIENTRY @@ -1089,18 +1090,38 @@ _mesa_GetActiveUniformBlockiv(GLuint program, params[0] = strlen(block->Name) + 1; return; - case GL_UNIFORM_BLOCK_ACTIVE_UNIFORMS: - params[0] = block->NumUniforms; + case GL_UNIFORM_BLOCK_ACTIVE_UNIFORMS: { + unsigned count = 0; + + for (i = 0; i < block->NumUniforms; i++) { + unsigned offset; + const int idx = + _mesa_get_uniform_location(ctx, shProg, + block->Uniforms[i].IndexName, + &offset); + if (idx != -1) + count++; + } + + params[0] = count; return; + } + + case GL_UNIFORM_BLOCK_ACTIVE_UNIFORM_INDICES: { + unsigned count = 0; - case GL_UNIFORM_BLOCK_ACTIVE_UNIFORM_INDICES: for (i = 0; i < block->NumUniforms; i++) { unsigned offset; - params[i] = _mesa_get_uniform_location(ctx, shProg, - block->Uniforms[i].IndexName, - &offset); + const int idx = + _mesa_get_uniform_location(ctx, shProg, + block->Uniforms[i].IndexName, + &offset); + + if (idx != -1) + params[count++] = idx; } return; + } case GL_UNIFORM_BLOCK_REFERENCED_BY_VERTEX_SHADER: params[0] = shProg->UniformBlockStageIndex[MESA_SHADER_VERTEX][uniformBlockIndex] != -1; diff --git a/mesalib/src/mesa/main/uniforms.h b/mesalib/src/mesa/main/uniforms.h index 10518dcbb..e7a370e84 100644 --- a/mesalib/src/mesa/main/uniforms.h +++ b/mesalib/src/mesa/main/uniforms.h @@ -323,69 +323,6 @@ struct gl_builtin_uniform_desc { unsigned int num_elements; }; -/** - * \name GLSL uniform arrays and structs require special handling. - * - * The GL_ARB_shader_objects spec says that if you use - * glGetUniformLocation to get the location of an array, you CANNOT - * access other elements of the array by adding an offset to the - * returned location. For example, you must call - * glGetUniformLocation("foo[16]") if you want to set the 16th element - * of the array with glUniform(). - * - * HOWEVER, some other OpenGL drivers allow accessing array elements - * by adding an offset to the returned array location. And some apps - * seem to depend on that behaviour. - * - * Mesa's gl_uniform_list doesn't directly support this since each - * entry in the list describes one uniform variable, not one uniform - * element. We could insert dummy entries in the list for each array - * element after [0] but that causes complications elsewhere. - * - * We solve this problem by creating multiple entries for uniform arrays - * in the UniformRemapTable so that their elements get sequential locations. - * - * Utility functions below offer functionality to split UniformRemapTable - * location in to location of the uniform in UniformStorage + offset to the - * array element (0 if not an array) and also merge it back again as the - * UniformRemapTable location. - * - */ -/*@{*/ -/** - * Combine the uniform's storage index and the array index - */ -static inline GLint -_mesa_uniform_merge_location_offset(const struct gl_shader_program *prog, - unsigned storage_index, - unsigned uniform_array_index) -{ - /* location in remap table + array element offset */ - return prog->UniformStorage[storage_index].remap_location + - uniform_array_index; -} - -/** - * Separate the uniform storage index and array index - */ -static inline void -_mesa_uniform_split_location_offset(const struct gl_shader_program *prog, - GLint location, unsigned *storage_index, - unsigned *uniform_array_index) -{ - *storage_index = prog->UniformRemapTable[location] - prog->UniformStorage; - *uniform_array_index = location - - prog->UniformRemapTable[location]->remap_location; - - /*gl_uniform_storage in UniformStorage with the calculated base_location - * must match with the entry in remap table - */ - assert(&prog->UniformStorage[*storage_index] == - prog->UniformRemapTable[location]); -} -/*@}*/ - - #ifdef __cplusplus } #endif diff --git a/mesalib/src/mesa/main/varray.c b/mesalib/src/mesa/main/varray.c index 46956efb5..230fb30cb 100644 --- a/mesalib/src/mesa/main/varray.c +++ b/mesalib/src/mesa/main/varray.c @@ -24,6 +24,8 @@ */ +#include <inttypes.h> /* for PRId64 macro */ + #include "glheader.h" #include "imports.h" #include "bufferobj.h" @@ -46,21 +48,22 @@ /** Used to indicate which GL datatypes are accepted by each of the * glVertex/Color/Attrib/EtcPointer() functions. */ -#define BOOL_BIT 0x1 -#define BYTE_BIT 0x2 -#define UNSIGNED_BYTE_BIT 0x4 -#define SHORT_BIT 0x8 -#define UNSIGNED_SHORT_BIT 0x10 -#define INT_BIT 0x20 -#define UNSIGNED_INT_BIT 0x40 -#define HALF_BIT 0x80 -#define FLOAT_BIT 0x100 -#define DOUBLE_BIT 0x200 -#define FIXED_ES_BIT 0x400 -#define FIXED_GL_BIT 0x800 -#define UNSIGNED_INT_2_10_10_10_REV_BIT 0x1000 -#define INT_2_10_10_10_REV_BIT 0x2000 -#define UNSIGNED_INT_10F_11F_11F_REV_BIT 0x4000 +#define BOOL_BIT (1 << 0) +#define BYTE_BIT (1 << 1) +#define UNSIGNED_BYTE_BIT (1 << 2) +#define SHORT_BIT (1 << 3) +#define UNSIGNED_SHORT_BIT (1 << 4) +#define INT_BIT (1 << 5) +#define UNSIGNED_INT_BIT (1 << 6) +#define HALF_BIT (1 << 7) +#define FLOAT_BIT (1 << 8) +#define DOUBLE_BIT (1 << 9) +#define FIXED_ES_BIT (1 << 10) +#define FIXED_GL_BIT (1 << 11) +#define UNSIGNED_INT_2_10_10_10_REV_BIT (1 << 12) +#define INT_2_10_10_10_REV_BIT (1 << 13) +#define UNSIGNED_INT_10F_11F_11F_REV_BIT (1 << 14) +#define ALL_TYPE_BITS ((1 << 15) - 1) /** Convert GL datatype enum into a <type>_BIT value seen above */ @@ -179,6 +182,53 @@ vertex_binding_divisor(struct gl_context *ctx, GLuint bindingIndex, /** + * Examine the API profile and extensions to determine which types are legal + * for vertex arrays. This is called once from update_array_format(). + */ +static GLbitfield +get_legal_types_mask(const struct gl_context *ctx) +{ + GLbitfield legalTypesMask = ALL_TYPE_BITS; + + if (_mesa_is_gles(ctx)) { + legalTypesMask &= ~(FIXED_GL_BIT | + DOUBLE_BIT | + UNSIGNED_INT_10F_11F_11F_REV_BIT); + + /* GL_INT and GL_UNSIGNED_INT data is not allowed in OpenGL ES until + * 3.0. The 2_10_10_10 types are added in OpenGL ES 3.0 or + * GL_OES_vertex_type_10_10_10_2. GL_HALF_FLOAT data is not allowed + * until 3.0 or with the GL_OES_vertex_half float extension, which isn't + * quite as trivial as we'd like because it uses a different enum value + * for GL_HALF_FLOAT_OES. + */ + if (ctx->Version < 30) { + legalTypesMask &= ~(UNSIGNED_INT_BIT | + INT_BIT | + UNSIGNED_INT_2_10_10_10_REV_BIT | + INT_2_10_10_10_REV_BIT | + HALF_BIT); + } + } + else { + legalTypesMask &= ~FIXED_ES_BIT; + + if (!ctx->Extensions.ARB_ES2_compatibility) + legalTypesMask &= ~FIXED_GL_BIT; + + if (!ctx->Extensions.ARB_vertex_type_2_10_10_10_rev) + legalTypesMask &= ~(UNSIGNED_INT_2_10_10_10_REV_BIT | + INT_2_10_10_10_REV_BIT); + + if (!ctx->Extensions.ARB_vertex_type_10f_11f_11f_rev) + legalTypesMask &= ~UNSIGNED_INT_10F_11F_11F_REV_BIT; + } + + return legalTypesMask; +} + + +/** * Does error checking and updates the format in an attrib array. * * Called by update_array() and VertexAttrib*Format(). @@ -208,40 +258,19 @@ update_array_format(struct gl_context *ctx, GLuint elementSize; GLenum format = GL_RGBA; - if (_mesa_is_gles(ctx)) { - legalTypesMask &= ~(FIXED_GL_BIT | DOUBLE_BIT | UNSIGNED_INT_10F_11F_11F_REV_BIT); - - /* GL_INT and GL_UNSIGNED_INT data is not allowed in OpenGL ES until - * 3.0. The 2_10_10_10 types are added in OpenGL ES 3.0 or - * GL_OES_vertex_type_10_10_10_2. GL_HALF_FLOAT data is not allowed - * until 3.0 or with the GL_OES_vertex_half float extension, which isn't - * quite as trivial as we'd like because it uses a different enum value - * for GL_HALF_FLOAT_OES. + if (ctx->Array.LegalTypesMask == 0) { + /* One-time initialization. We can't do this in _mesa_init_varrays() + * below because extensions are not yet enabled at that point. */ - if (ctx->Version < 30) { - legalTypesMask &= ~(UNSIGNED_INT_BIT - | INT_BIT - | UNSIGNED_INT_2_10_10_10_REV_BIT - | INT_2_10_10_10_REV_BIT - | HALF_BIT); - } + ctx->Array.LegalTypesMask = get_legal_types_mask(ctx); + } + + legalTypesMask &= ctx->Array.LegalTypesMask; + if (_mesa_is_gles(ctx) && sizeMax == BGRA_OR_4) { /* BGRA ordering is not supported in ES contexts. */ - if (sizeMax == BGRA_OR_4) - sizeMax = 4; - } else { - legalTypesMask &= ~FIXED_ES_BIT; - - if (!ctx->Extensions.ARB_ES2_compatibility) - legalTypesMask &= ~FIXED_GL_BIT; - - if (!ctx->Extensions.ARB_vertex_type_2_10_10_10_rev) - legalTypesMask &= ~(UNSIGNED_INT_2_10_10_10_REV_BIT | - INT_2_10_10_10_REV_BIT); - - if (!ctx->Extensions.ARB_vertex_type_10f_11f_11f_rev) - legalTypesMask &= ~UNSIGNED_INT_10F_11F_11F_REV_BIT; + sizeMax = 4; } typeBit = type_to_bit(ctx, type); @@ -1397,7 +1426,8 @@ _mesa_BindVertexBuffer(GLuint bindingIndex, GLuint buffer, GLintptr offset, */ if (offset < 0) { _mesa_error(ctx, GL_INVALID_VALUE, - "glBindVertexBuffer(offset=%lld < 0)", (long long)offset); + "glBindVertexBuffer(offset=%" PRId64 " < 0)", + (int64_t) offset); return; } @@ -1523,15 +1553,15 @@ _mesa_BindVertexBuffers(GLuint first, GLsizei count, const GLuint *buffers, */ if (offsets[i] < 0) { _mesa_error(ctx, GL_INVALID_VALUE, - "glBindVertexBuffer(offsets[%u]=%lldd < 0)", - i, (long long int) offsets[i]); + "glBindVertexBuffer(offsets[%u]=%" PRId64 " < 0)", + i, (int64_t) offsets[i]); continue; } if (strides[i] < 0) { _mesa_error(ctx, GL_INVALID_VALUE, - "glBindVertexBuffer(strides[%u]=%lld < 0)", - i, (long long int) strides[i]); + "glBindVertexBuffer(strides[%u]=%d < 0)", + i, strides[i]); continue; } diff --git a/mesalib/src/mesa/main/vdpau.c b/mesalib/src/mesa/main/vdpau.c index 975b812cd..e1c3e00ba 100644 --- a/mesalib/src/mesa/main/vdpau.c +++ b/mesalib/src/mesa/main/vdpau.c @@ -32,9 +32,9 @@ */ #include <stdbool.h> +#include "util/hash_table.h" #include "context.h" #include "glformats.h" -#include "hash_table.h" #include "set.h" #include "texobj.h" #include "teximage.h" diff --git a/mesalib/src/mesa/program/arbprogparse.c b/mesalib/src/mesa/program/arbprogparse.c index 5b9665091..7dec399a5 100644 --- a/mesalib/src/mesa/program/arbprogparse.c +++ b/mesalib/src/mesa/program/arbprogparse.c @@ -60,6 +60,7 @@ having three separate program parameter arrays. #include "prog_parameter.h" #include "prog_statevars.h" #include "prog_instruction.h" +#include "prog_optimize.h" #include "program_parser.h" @@ -84,6 +85,9 @@ _mesa_parse_arb_fragment_program(struct gl_context* ctx, GLenum target, return; } + if ((ctx->_Shader->Flags & GLSL_NO_OPT) == 0) + _mesa_optimize_program(ctx, &prog); + free(program->Base.String); /* Copy the relevant contents of the arb_program struct into the @@ -177,6 +181,9 @@ _mesa_parse_arb_vertex_program(struct gl_context *ctx, GLenum target, return; } + if ((ctx->_Shader->Flags & GLSL_NO_OPT) == 0) + _mesa_optimize_program(ctx, &prog); + free(program->Base.String); /* Copy the relevant contents of the arb_program struct into the diff --git a/mesalib/src/mesa/program/ir_to_mesa.cpp b/mesalib/src/mesa/program/ir_to_mesa.cpp index 2a82e9d9d..b088160d3 100644 --- a/mesalib/src/mesa/program/ir_to_mesa.cpp +++ b/mesalib/src/mesa/program/ir_to_mesa.cpp @@ -793,7 +793,7 @@ ir_to_mesa_visitor::visit(ir_function *ir) const ir_function_signature *sig; exec_list empty; - sig = ir->matching_signature(NULL, &empty); + sig = ir->matching_signature(NULL, &empty, false); assert(sig); diff --git a/mesalib/src/mesa/program/prog_execute.c b/mesalib/src/mesa/program/prog_execute.c index 115525eba..fcc9ed518 100644 --- a/mesalib/src/mesa/program/prog_execute.c +++ b/mesalib/src/mesa/program/prog_execute.c @@ -52,7 +52,6 @@ /** * Set x to positive or negative infinity. */ -#if defined(USE_IEEE) || defined(_WIN32) #define SET_POS_INFINITY(x) \ do { \ fi_type fi; \ @@ -65,10 +64,6 @@ fi.i = 0xFF800000; \ x = fi.f; \ } while (0) -#else -#define SET_POS_INFINITY(x) x = (GLfloat) HUGE_VAL -#define SET_NEG_INFINITY(x) x = (GLfloat) -HUGE_VAL -#endif #define SET_FLOAT_BITS(x, bits) ((fi_type *) (void *) &(x))->i = bits diff --git a/mesalib/src/mesa/program/program.c b/mesalib/src/mesa/program/program.c index aedce3e3c..ef5bf6b11 100644 --- a/mesalib/src/mesa/program/program.c +++ b/mesalib/src/mesa/program/program.c @@ -226,27 +226,24 @@ _mesa_find_line_column(const GLubyte *string, const GLubyte *pos, /** - * Initialize a new vertex/fragment program object. + * Initialize a new gl_program object. */ -static struct gl_program * -_mesa_init_program_struct( struct gl_context *ctx, struct gl_program *prog, - GLenum target, GLuint id) +static void +init_program_struct(struct gl_program *prog, GLenum target, GLuint id) { - (void) ctx; - if (prog) { - GLuint i; - memset(prog, 0, sizeof(*prog)); - prog->Id = id; - prog->Target = target; - prog->RefCount = 1; - prog->Format = GL_PROGRAM_FORMAT_ASCII_ARB; - - /* default mapping from samplers to texture units */ - for (i = 0; i < MAX_SAMPLERS; i++) - prog->SamplerUnits[i] = i; - } + GLuint i; - return prog; + assert(prog); + + memset(prog, 0, sizeof(*prog)); + prog->Id = id; + prog->Target = target; + prog->RefCount = 1; + prog->Format = GL_PROGRAM_FORMAT_ASCII_ARB; + + /* default mapping from samplers to texture units */ + for (i = 0; i < MAX_SAMPLERS; i++) + prog->SamplerUnits[i] = i; } @@ -254,13 +251,15 @@ _mesa_init_program_struct( struct gl_context *ctx, struct gl_program *prog, * Initialize a new fragment program object. */ struct gl_program * -_mesa_init_fragment_program( struct gl_context *ctx, struct gl_fragment_program *prog, - GLenum target, GLuint id) +_mesa_init_fragment_program(struct gl_context *ctx, + struct gl_fragment_program *prog, + GLenum target, GLuint id) { - if (prog) - return _mesa_init_program_struct( ctx, &prog->Base, target, id ); - else - return NULL; + if (prog) { + init_program_struct(&prog->Base, target, id); + return &prog->Base; + } + return NULL; } @@ -268,13 +267,15 @@ _mesa_init_fragment_program( struct gl_context *ctx, struct gl_fragment_program * Initialize a new vertex program object. */ struct gl_program * -_mesa_init_vertex_program( struct gl_context *ctx, struct gl_vertex_program *prog, - GLenum target, GLuint id) +_mesa_init_vertex_program(struct gl_context *ctx, + struct gl_vertex_program *prog, + GLenum target, GLuint id) { - if (prog) - return _mesa_init_program_struct( ctx, &prog->Base, target, id ); - else - return NULL; + if (prog) { + init_program_struct(&prog->Base, target, id); + return &prog->Base; + } + return NULL; } @@ -283,13 +284,14 @@ _mesa_init_vertex_program( struct gl_context *ctx, struct gl_vertex_program *pro */ struct gl_program * _mesa_init_compute_program(struct gl_context *ctx, - struct gl_compute_program *prog, GLenum target, - GLuint id) + struct gl_compute_program *prog, + GLenum target, GLuint id) { - if (prog) - return _mesa_init_program_struct( ctx, &prog->Base, target, id ); - else - return NULL; + if (prog) { + init_program_struct(&prog->Base, target, id); + return &prog->Base; + } + return NULL; } @@ -297,13 +299,15 @@ _mesa_init_compute_program(struct gl_context *ctx, * Initialize a new geometry program object. */ struct gl_program * -_mesa_init_geometry_program( struct gl_context *ctx, struct gl_geometry_program *prog, - GLenum target, GLuint id) +_mesa_init_geometry_program(struct gl_context *ctx, + struct gl_geometry_program *prog, + GLenum target, GLuint id) { - if (prog) - return _mesa_init_program_struct( ctx, &prog->Base, target, id ); - else - return NULL; + if (prog) { + init_program_struct(&prog->Base, target, id); + return &prog->Base; + } + return NULL; } diff --git a/mesalib/src/mesa/program/register_allocate.c b/mesalib/src/mesa/program/register_allocate.c index 6fac69033..549154e8a 100644 --- a/mesalib/src/mesa/program/register_allocate.c +++ b/mesalib/src/mesa/program/register_allocate.c @@ -71,8 +71,8 @@ */ #include <stdbool.h> -#include <ralloc.h> +#include "util/ralloc.h" #include "main/imports.h" #include "main/macros.h" #include "main/mtypes.h" diff --git a/mesalib/src/mesa/state_tracker/st_cb_bufferobjects.c b/mesalib/src/mesa/state_tracker/st_cb_bufferobjects.c index 3b4d28d47..e0cb979f2 100644 --- a/mesalib/src/mesa/state_tracker/st_cb_bufferobjects.c +++ b/mesalib/src/mesa/state_tracker/st_cb_bufferobjects.c @@ -31,6 +31,8 @@ */ +#include <inttypes.h> /* for PRId64 macro */ + #include "main/imports.h" #include "main/mtypes.h" #include "main/arrayobj.h" @@ -271,7 +273,8 @@ st_bufferobj_data(struct gl_context *ctx, pipe_resource_reference( &st_obj->buffer, NULL ); if (ST_DEBUG & DEBUG_BUFFER) { - debug_printf("Create buffer size %td bind 0x%x\n", size, bind); + debug_printf("Create buffer size %" PRId64 " bind 0x%x\n", + (int64_t) size, bind); } if (size != 0) { diff --git a/mesalib/src/mesa/state_tracker/st_cb_clear.c b/mesalib/src/mesa/state_tracker/st_cb_clear.c index 4bfa8d75a..2c1414e48 100644 --- a/mesalib/src/mesa/state_tracker/st_cb_clear.c +++ b/mesalib/src/mesa/state_tracker/st_cb_clear.c @@ -173,6 +173,9 @@ draw_quad(struct st_context *st, return; } + /* Convert Z from [0,1] to [-1,1] range */ + z = z * 2.0f - 1.0f; + /* positions */ vertices[0][0][0] = x0; vertices[0][0][1] = y0; @@ -319,11 +322,11 @@ clear_with_quad(struct gl_context *ctx, unsigned clear_buffers) struct pipe_viewport_state vp; vp.scale[0] = 0.5f * fb_width; vp.scale[1] = fb_height * (invert ? -0.5f : 0.5f); - vp.scale[2] = 1.0f; + vp.scale[2] = 0.5f; vp.scale[3] = 1.0f; vp.translate[0] = 0.5f * fb_width; vp.translate[1] = 0.5f * fb_height; - vp.translate[2] = 0.0f; + vp.translate[2] = 0.5f; vp.translate[3] = 0.0f; cso_set_viewport(st->cso_context, &vp); } diff --git a/mesalib/src/mesa/state_tracker/st_cb_drawpixels.c b/mesalib/src/mesa/state_tracker/st_cb_drawpixels.c index 6119cc275..d13a17f50 100644 --- a/mesalib/src/mesa/state_tracker/st_cb_drawpixels.c +++ b/mesalib/src/mesa/state_tracker/st_cb_drawpixels.c @@ -494,22 +494,19 @@ make_texture(struct st_context *st, pipeFormat = st_choose_matching_format(pipe->screen, PIPE_BIND_SAMPLER_VIEW, format, type, unpack->SwapBytes); - if (pipeFormat != PIPE_FORMAT_NONE) { - mformat = st_pipe_format_to_mesa_format(pipeFormat); - baseInternalFormat = _mesa_get_format_base_format(mformat); - } - else { + if (pipeFormat == PIPE_FORMAT_NONE) { /* Use the generic approach. */ GLenum intFormat = internal_format(ctx, format, type); - baseInternalFormat = _mesa_base_tex_format(ctx, intFormat); pipeFormat = st_choose_format(st, intFormat, format, type, PIPE_TEXTURE_2D, 0, PIPE_BIND_SAMPLER_VIEW, FALSE); assert(pipeFormat != PIPE_FORMAT_NONE); - mformat = st_pipe_format_to_mesa_format(pipeFormat); } + mformat = st_pipe_format_to_mesa_format(pipeFormat); + baseInternalFormat = _mesa_get_format_base_format(mformat); + pixels = _mesa_map_pbo_source(ctx, unpack, pixels); if (!pixels) return NULL; diff --git a/mesalib/src/mesa/state_tracker/st_cb_texture.c b/mesalib/src/mesa/state_tracker/st_cb_texture.c index aa6b05f0b..c4b2107ba 100644 --- a/mesalib/src/mesa/state_tracker/st_cb_texture.c +++ b/mesalib/src/mesa/state_tracker/st_cb_texture.c @@ -719,6 +719,8 @@ st_TexSubImage(struct gl_context *ctx, GLuint dims, /* From now on, we need the gallium representation of dimensions. */ if (gl_target == GL_TEXTURE_1D_ARRAY) { + zoffset = yoffset; + yoffset = 0; depth = height; height = 1; } diff --git a/mesalib/src/mesa/state_tracker/st_extensions.c b/mesalib/src/mesa/state_tracker/st_extensions.c index aa59fbfa9..7ac484056 100644 --- a/mesalib/src/mesa/state_tracker/st_extensions.c +++ b/mesalib/src/mesa/state_tracker/st_extensions.c @@ -146,7 +146,7 @@ void st_init_limits(struct st_context *st) c->MaxUniformBlockSize = screen->get_shader_param(screen, PIPE_SHADER_FRAGMENT, - PIPE_SHADER_CAP_MAX_CONSTS) * 16; + PIPE_SHADER_CAP_MAX_CONST_BUFFER_SIZE); if (c->MaxUniformBlockSize < 16384) { can_ubo = FALSE; } @@ -194,7 +194,8 @@ void st_init_limits(struct st_context *st) _min(screen->get_shader_param(screen, sh, PIPE_SHADER_CAP_MAX_ADDRS), MAX_PROGRAM_ADDRESS_REGS); pc->MaxParameters = pc->MaxNativeParameters = - screen->get_shader_param(screen, sh, PIPE_SHADER_CAP_MAX_CONSTS); + screen->get_shader_param(screen, sh, + PIPE_SHADER_CAP_MAX_CONST_BUFFER_SIZE) / sizeof(float[4]); pc->MaxUniformComponents = 4 * MIN2(pc->MaxNativeParameters, MAX_UNIFORMS); 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 5ea146547..0290553c6 100644 --- a/mesalib/src/mesa/state_tracker/st_glsl_to_tgsi.cpp +++ b/mesalib/src/mesa/state_tracker/st_glsl_to_tgsi.cpp @@ -1192,7 +1192,7 @@ glsl_to_tgsi_visitor::visit(ir_function *ir) const ir_function_signature *sig; exec_list empty; - sig = ir->matching_signature(NULL, &empty); + sig = ir->matching_signature(NULL, &empty, false); assert(sig); @@ -1354,7 +1354,7 @@ glsl_to_tgsi_visitor::visit(ir_expression *ir) /* Quick peephole: Emit OPCODE_MAD(-a, -b, a) instead of AND(a, NOT(b)) */ - if (ir->operation == ir_binop_logic_and) { + if (!native_integers && ir->operation == ir_binop_logic_and) { if (try_emit_mad_for_and_not(ir, 1)) return; if (try_emit_mad_for_and_not(ir, 0)) @@ -1947,16 +1947,16 @@ glsl_to_tgsi_visitor::visit(ir_expression *ir) break; case ir_binop_ubo_load: { - ir_constant *uniform_block = ir->operands[0]->as_constant(); + ir_constant *const_uniform_block = ir->operands[0]->as_constant(); ir_constant *const_offset_ir = ir->operands[1]->as_constant(); unsigned const_offset = const_offset_ir ? const_offset_ir->value.u[0] : 0; + unsigned const_block = const_uniform_block ? const_uniform_block->value.u[0] + 1 : 0; st_src_reg index_reg = get_temp(glsl_type::uint_type); st_src_reg cbuf; cbuf.type = glsl_type::vec4_type->base_type; cbuf.file = PROGRAM_CONSTANT; cbuf.index = 0; - cbuf.index2D = uniform_block->value.u[0] + 1; cbuf.reladdr = NULL; cbuf.negate = 0; @@ -1966,7 +1966,6 @@ glsl_to_tgsi_visitor::visit(ir_expression *ir) /* Constant index into constant buffer */ cbuf.reladdr = NULL; cbuf.index = const_offset / 16; - cbuf.has_index2 = true; } else { /* Relative/variable index into constant buffer */ @@ -1976,6 +1975,20 @@ glsl_to_tgsi_visitor::visit(ir_expression *ir) memcpy(cbuf.reladdr, &index_reg, sizeof(index_reg)); } + if (const_uniform_block) { + /* Constant constant buffer */ + cbuf.reladdr2 = NULL; + cbuf.index2D = const_block; + cbuf.has_index2 = true; + } + else { + /* Relative/variable constant buffer */ + cbuf.reladdr2 = ralloc(mem_ctx, st_src_reg); + cbuf.index2D = 1; + memcpy(cbuf.reladdr2, &op[0], sizeof(st_src_reg)); + cbuf.has_index2 = true; + } + cbuf.swizzle = swizzle_for_size(ir->type->vector_elements); cbuf.swizzle += MAKE_SWIZZLE4(const_offset % 16 / 4, const_offset % 16 / 4, @@ -3216,78 +3229,6 @@ count_resources(glsl_to_tgsi_visitor *v, gl_program *prog) _mesa_update_shader_textures_used(v->shader_program, prog); } -static void -set_uniform_initializer(struct gl_context *ctx, void *mem_ctx, - struct gl_shader_program *shader_program, - const char *name, const glsl_type *type, - ir_constant *val) -{ - if (type->is_record()) { - ir_constant *field_constant; - - field_constant = (ir_constant *)val->components.get_head(); - - for (unsigned int i = 0; i < type->length; i++) { - const glsl_type *field_type = type->fields.structure[i].type; - const char *field_name = ralloc_asprintf(mem_ctx, "%s.%s", name, - type->fields.structure[i].name); - set_uniform_initializer(ctx, mem_ctx, shader_program, field_name, - field_type, field_constant); - field_constant = (ir_constant *)field_constant->next; - } - return; - } - - unsigned offset; - unsigned index = _mesa_get_uniform_location(ctx, shader_program, name, - &offset); - if (offset == GL_INVALID_INDEX) { - fail_link(shader_program, - "Couldn't find uniform for initializer %s\n", name); - return; - } - int loc = _mesa_uniform_merge_location_offset(shader_program, index, offset); - - for (unsigned int i = 0; i < (type->is_array() ? type->length : 1); i++) { - ir_constant *element; - const glsl_type *element_type; - if (type->is_array()) { - element = val->array_elements[i]; - element_type = type->fields.array; - } else { - element = val; - element_type = type; - } - - void *values; - - if (element_type->base_type == GLSL_TYPE_BOOL) { - int *conv = ralloc_array(mem_ctx, int, element_type->components()); - for (unsigned int j = 0; j < element_type->components(); j++) { - conv[j] = element->value.b[j]; - } - values = (void *)conv; - element_type = glsl_type::get_instance(GLSL_TYPE_INT, - element_type->vector_elements, - 1); - } else { - values = &element->value; - } - - if (element_type->is_matrix()) { - _mesa_uniform_matrix(ctx, shader_program, - element_type->matrix_columns, - element_type->vector_elements, - loc, 1, GL_FALSE, (GLfloat *)values); - } else { - _mesa_uniform(ctx, shader_program, loc, element_type->matrix_columns, - values, element_type->gl_type); - } - - loc++; - } -} - /** * Returns the mask of channels (bitmask of WRITEMASK_X,Y,Z,W) which * are read from the given src in this instruction @@ -4225,14 +4166,22 @@ struct st_translate { }; /** Map Mesa's SYSTEM_VALUE_x to TGSI_SEMANTIC_x */ -static unsigned mesa_sysval_to_semantic[SYSTEM_VALUE_MAX] = { - TGSI_SEMANTIC_FACE, +const unsigned _mesa_sysval_to_semantic[SYSTEM_VALUE_MAX] = { + /* Vertex shader + */ TGSI_SEMANTIC_VERTEXID, TGSI_SEMANTIC_INSTANCEID, + + /* Geometry shader + */ + TGSI_SEMANTIC_INVOCATIONID, + + /* Fragment shader + */ + TGSI_SEMANTIC_FACE, TGSI_SEMANTIC_SAMPLEID, TGSI_SEMANTIC_SAMPLEPOS, TGSI_SEMANTIC_SAMPLEMASK, - TGSI_SEMANTIC_INVOCATIONID, }; /** @@ -4321,9 +4270,8 @@ dst_register(struct st_translate *t, return ureg_dst_undef(); case PROGRAM_TEMPORARY: - assert(index >= 0); - assert(index < (int) Elements(t->temps)); - + assert(index < Elements(t->temps)); + if (ureg_dst_is_undef(t->temps[index])) t->temps[index] = ureg_DECL_local_temporary(t->ureg); @@ -4332,8 +4280,7 @@ dst_register(struct st_translate *t, case PROGRAM_ARRAY: array = index >> 16; - assert(array >= 0); - assert(array < (int) Elements(t->arrays)); + assert(array < Elements(t->arrays)); if (ureg_dst_is_undef(t->arrays[array])) t->arrays[array] = ureg_DECL_array_temporary( @@ -4367,51 +4314,45 @@ dst_register(struct st_translate *t, * Map a glsl_to_tgsi src register to a TGSI ureg_src register. */ static struct ureg_src -src_register(struct st_translate *t, - gl_register_file file, - GLint index, GLint index2D) +src_register(struct st_translate *t, const struct st_src_reg *reg) { - switch(file) { + switch(reg->file) { case PROGRAM_UNDEFINED: return ureg_src_undef(); case PROGRAM_TEMPORARY: case PROGRAM_ARRAY: - return ureg_src(dst_register(t, file, index)); + return ureg_src(dst_register(t, reg->file, reg->index)); case PROGRAM_UNIFORM: - assert(index >= 0); - return t->constants[index]; + assert(reg->index >= 0); + return t->constants[reg->index]; case PROGRAM_STATE_VAR: case PROGRAM_CONSTANT: /* ie, immediate */ - if (index2D) { - struct ureg_src src; - src = ureg_src_register(TGSI_FILE_CONSTANT, index); - src.Dimension = 1; - src.DimensionIndex = index2D; - return src; - } else if (index < 0) + if (reg->has_index2) + return ureg_src_register(TGSI_FILE_CONSTANT, reg->index); + else if (reg->index < 0) return ureg_DECL_constant(t->ureg, 0); else - return t->constants[index]; + return t->constants[reg->index]; case PROGRAM_IMMEDIATE: - return t->immediates[index]; + return t->immediates[reg->index]; case PROGRAM_INPUT: - assert(t->inputMapping[index] < Elements(t->inputs)); - return t->inputs[t->inputMapping[index]]; + assert(t->inputMapping[reg->index] < Elements(t->inputs)); + return t->inputs[t->inputMapping[reg->index]]; case PROGRAM_OUTPUT: - assert(t->outputMapping[index] < Elements(t->outputs)); - return ureg_src(t->outputs[t->outputMapping[index]]); /* not needed? */ + assert(t->outputMapping[reg->index] < Elements(t->outputs)); + return ureg_src(t->outputs[t->outputMapping[reg->index]]); /* not needed? */ case PROGRAM_ADDRESS: - return ureg_src(t->address[index]); + return ureg_src(t->address[reg->index]); case PROGRAM_SYSTEM_VALUE: - assert(index < (int) Elements(t->systemValues)); - return t->systemValues[index]; + assert(reg->index < (int) Elements(t->systemValues)); + return t->systemValues[reg->index]; default: assert(!"unknown src register file"); @@ -4472,13 +4413,12 @@ translate_dst(struct st_translate *t, static struct ureg_src translate_src(struct st_translate *t, const st_src_reg *src_reg) { - struct ureg_src src = src_register(t, src_reg->file, src_reg->index, src_reg->index2D); + struct ureg_src src = src_register(t, src_reg); if (src_reg->has_index2) { /* 2D indexes occur with geometry shader inputs (attrib, vertex) * and UBO constant buffers (buffer, position). */ - src = src_register(t, src_reg->file, src_reg->index, src_reg->index2D); if (src_reg->reladdr2) src = ureg_src_dimension_indirect(src, ureg_src(t->address[1]), src_reg->index2D); @@ -4900,6 +4840,21 @@ st_translate_program( assert(numInputs <= Elements(t->inputs)); assert(numOutputs <= Elements(t->outputs)); + assert(_mesa_sysval_to_semantic[SYSTEM_VALUE_FRONT_FACE] == + TGSI_SEMANTIC_FACE); + assert(_mesa_sysval_to_semantic[SYSTEM_VALUE_VERTEX_ID] == + TGSI_SEMANTIC_VERTEXID); + assert(_mesa_sysval_to_semantic[SYSTEM_VALUE_INSTANCE_ID] == + TGSI_SEMANTIC_INSTANCEID); + assert(_mesa_sysval_to_semantic[SYSTEM_VALUE_SAMPLE_ID] == + TGSI_SEMANTIC_SAMPLEID); + assert(_mesa_sysval_to_semantic[SYSTEM_VALUE_SAMPLE_POS] == + TGSI_SEMANTIC_SAMPLEPOS); + assert(_mesa_sysval_to_semantic[SYSTEM_VALUE_SAMPLE_MASK_IN] == + TGSI_SEMANTIC_SAMPLEMASK); + assert(_mesa_sysval_to_semantic[SYSTEM_VALUE_INVOCATION_ID] == + TGSI_SEMANTIC_INVOCATIONID); + t = CALLOC_STRUCT(st_translate); if (!t) { ret = PIPE_ERROR_OUT_OF_MEMORY; @@ -5035,7 +4990,7 @@ st_translate_program( unsigned numSys = 0; for (i = 0; sysInputs; i++) { if (sysInputs & (1 << i)) { - unsigned semName = mesa_sysval_to_semantic[i]; + unsigned semName = _mesa_sysval_to_semantic[i]; t->systemValues[i] = ureg_DECL_system_value(ureg, numSys, semName, 0); if (semName == TGSI_SEMANTIC_INSTANCEID || semName == TGSI_SEMANTIC_VERTEXID) { @@ -5109,8 +5064,7 @@ st_translate_program( unsigned num_ubos = program->shader->NumUniformBlocks; for (i = 0; i < num_ubos; i++) { - unsigned size = - program->shader_program->UniformBlocks[i].UniformBufferSize; + unsigned size = program->shader->UniformBlocks[i].UniformBufferSize; unsigned num_const_vecs = (size + 15) / 16; unsigned first, last; assert(num_const_vecs > 0); diff --git a/mesalib/src/mesa/state_tracker/st_glsl_to_tgsi.h b/mesalib/src/mesa/state_tracker/st_glsl_to_tgsi.h index 2e7cb78d5..18f666f5b 100644 --- a/mesalib/src/mesa/state_tracker/st_glsl_to_tgsi.h +++ b/mesalib/src/mesa/state_tracker/st_glsl_to_tgsi.h @@ -73,6 +73,7 @@ st_translate_stream_output_info(struct glsl_to_tgsi_visitor *glsl_to_tgsi, const GLuint outputMapping[], struct pipe_stream_output_info *so); +extern const unsigned _mesa_sysval_to_semantic[SYSTEM_VALUE_MAX]; #ifdef __cplusplus } diff --git a/mesalib/src/mesa/state_tracker/st_mesa_to_tgsi.c b/mesalib/src/mesa/state_tracker/st_mesa_to_tgsi.c index 683cd1cac..26a5f51c7 100644 --- a/mesalib/src/mesa/state_tracker/st_mesa_to_tgsi.c +++ b/mesalib/src/mesa/state_tracker/st_mesa_to_tgsi.c @@ -44,6 +44,7 @@ #include "util/u_debug.h" #include "util/u_math.h" #include "util/u_memory.h" +#include "st_glsl_to_tgsi.h" /* for _mesa_sysval_to_semantic */ #define PROGRAM_ANY_CONST ((1 << PROGRAM_STATE_VAR) | \ @@ -96,14 +97,6 @@ struct st_translate { }; -/** Map Mesa's SYSTEM_VALUE_x to TGSI_SEMANTIC_x */ -static unsigned mesa_sysval_to_semantic[SYSTEM_VALUE_MAX] = { - TGSI_SEMANTIC_FACE, - TGSI_SEMANTIC_VERTEXID, - TGSI_SEMANTIC_INSTANCEID -}; - - /** * Make note of a branch to a label in the TGSI code. * After we've emitted all instructions, we'll go over the list @@ -1147,7 +1140,7 @@ st_translate_mesa_program( unsigned numSys = 0; for (i = 0; sysInputs; i++) { if (sysInputs & (1 << i)) { - unsigned semName = mesa_sysval_to_semantic[i]; + unsigned semName = _mesa_sysval_to_semantic[i]; t->systemValues[i] = ureg_DECL_system_value(ureg, numSys, semName, 0); if (semName == TGSI_SEMANTIC_INSTANCEID || semName == TGSI_SEMANTIC_VERTEXID) { diff --git a/mesalib/src/mesa/state_tracker/st_program.c b/mesalib/src/mesa/state_tracker/st_program.c index 9d7b7c475..fbf8930cb 100644 --- a/mesalib/src/mesa/state_tracker/st_program.c +++ b/mesalib/src/mesa/state_tracker/st_program.c @@ -393,13 +393,12 @@ st_translate_vertex_program(struct st_context *st, &vpv->tgsi.stream_output); } - vpv->driver_shader = pipe->create_vs_state(pipe, &vpv->tgsi); - if (ST_DEBUG & DEBUG_TGSI) { - tgsi_dump( vpv->tgsi.tokens, 0 ); + tgsi_dump(vpv->tgsi.tokens, 0); debug_printf("\n"); } + vpv->driver_shader = pipe->create_vs_state(pipe, &vpv->tgsi); return vpv; fail: @@ -804,15 +803,15 @@ st_translate_fragment_program(struct st_context *st, variant->tgsi.tokens = ureg_get_tokens( ureg, NULL ); ureg_destroy( ureg ); - /* fill in variant */ - variant->driver_shader = pipe->create_fs_state(pipe, &variant->tgsi); - variant->key = *key; - if (ST_DEBUG & DEBUG_TGSI) { - tgsi_dump( variant->tgsi.tokens, 0/*TGSI_DUMP_VERBOSE*/ ); + tgsi_dump(variant->tgsi.tokens, 0/*TGSI_DUMP_VERBOSE*/); debug_printf("\n"); } + /* fill in variant */ + variant->driver_shader = pipe->create_fs_state(pipe, &variant->tgsi); + variant->key = *key; + if (deleteFP) { /* Free the temporary program made above */ struct gl_fragment_program *fp = &stfp->Base; @@ -1173,10 +1172,6 @@ st_translate_geometry_program(struct st_context *st, &stgp->tgsi.stream_output); } - /* fill in new variant */ - gpv->driver_shader = pipe->create_gs_state(pipe, &stgp->tgsi); - gpv->key = *key; - if ((ST_DEBUG & DEBUG_TGSI) && (ST_DEBUG & DEBUG_MESA)) { _mesa_print_program(&stgp->Base.Base); debug_printf("\n"); @@ -1187,6 +1182,9 @@ st_translate_geometry_program(struct st_context *st, debug_printf("\n"); } + /* fill in new variant */ + gpv->driver_shader = pipe->create_gs_state(pipe, &stgp->tgsi); + gpv->key = *key; return gpv; } diff --git a/mesalib/src/mesa/swrast/s_texfetch.c b/mesalib/src/mesa/swrast/s_texfetch.c index e508368c8..aef023217 100644 --- a/mesalib/src/mesa/swrast/s_texfetch.c +++ b/mesalib/src/mesa/swrast/s_texfetch.c @@ -46,35 +46,7 @@ #include "s_texfetch.h" #include "../../gallium/auxiliary/util/u_format_rgb9e5.h" #include "../../gallium/auxiliary/util/u_format_r11g11b10f.h" - - -/** - * Convert an 8-bit sRGB value from non-linear space to a - * linear RGB value in [0, 1]. - * Implemented with a 256-entry lookup table. - */ -static inline GLfloat -nonlinear_to_linear(GLubyte cs8) -{ - static GLfloat table[256]; - static GLboolean tableReady = GL_FALSE; - if (!tableReady) { - /* compute lookup table now */ - GLuint i; - for (i = 0; i < 256; i++) { - const GLfloat cs = UBYTE_TO_FLOAT(i); - if (cs <= 0.04045) { - table[i] = cs / 12.92f; - } - else { - table[i] = (GLfloat) pow((cs + 0.055) / 1.055, 2.4); - } - } - tableReady = GL_TRUE; - } - return table[cs8]; -} - +#include "util/format_srgb.h" /* Texel fetch routines for all supported formats diff --git a/mesalib/src/mesa/swrast/s_texfetch_tmp.h b/mesalib/src/mesa/swrast/s_texfetch_tmp.h index deda59246..72037ec00 100644 --- a/mesalib/src/mesa/swrast/s_texfetch_tmp.h +++ b/mesalib/src/mesa/swrast/s_texfetch_tmp.h @@ -737,9 +737,9 @@ FETCH(BGR_SRGB8)(const struct swrast_texture_image *texImage, GLint i, GLint j, GLint k, GLfloat *texel) { const GLubyte *src = TEXEL_ADDR(GLubyte, texImage, i, j, k, 3); - texel[RCOMP] = nonlinear_to_linear(src[2]); - texel[GCOMP] = nonlinear_to_linear(src[1]); - texel[BCOMP] = nonlinear_to_linear(src[0]); + texel[RCOMP] = util_format_srgb_8unorm_to_linear_float(src[2]); + texel[GCOMP] = util_format_srgb_8unorm_to_linear_float(src[1]); + texel[BCOMP] = util_format_srgb_8unorm_to_linear_float(src[0]); texel[ACOMP] = 1.0F; } @@ -749,9 +749,9 @@ FETCH(A8B8G8R8_SRGB)(const struct swrast_texture_image *texImage, GLint i, GLint j, GLint k, GLfloat *texel) { const GLuint s = *TEXEL_ADDR(GLuint, texImage, i, j, k, 1); - texel[RCOMP] = nonlinear_to_linear( (s >> 24) ); - texel[GCOMP] = nonlinear_to_linear( (s >> 16) & 0xff ); - texel[BCOMP] = nonlinear_to_linear( (s >> 8) & 0xff ); + texel[RCOMP] = util_format_srgb_8unorm_to_linear_float( (s >> 24) ); + texel[GCOMP] = util_format_srgb_8unorm_to_linear_float( (s >> 16) & 0xff ); + texel[BCOMP] = util_format_srgb_8unorm_to_linear_float( (s >> 8) & 0xff ); texel[ACOMP] = UBYTE_TO_FLOAT( (s ) & 0xff ); /* linear! */ } @@ -761,9 +761,9 @@ FETCH(B8G8R8A8_SRGB)(const struct swrast_texture_image *texImage, GLint i, GLint j, GLint k, GLfloat *texel) { const GLuint s = *TEXEL_ADDR(GLuint, texImage, i, j, k, 1); - texel[RCOMP] = nonlinear_to_linear( (s >> 16) & 0xff ); - texel[GCOMP] = nonlinear_to_linear( (s >> 8) & 0xff ); - texel[BCOMP] = nonlinear_to_linear( (s ) & 0xff ); + texel[RCOMP] = util_format_srgb_8unorm_to_linear_float( (s >> 16) & 0xff ); + texel[GCOMP] = util_format_srgb_8unorm_to_linear_float( (s >> 8) & 0xff ); + texel[BCOMP] = util_format_srgb_8unorm_to_linear_float( (s ) & 0xff ); texel[ACOMP] = UBYTE_TO_FLOAT( (s >> 24) ); /* linear! */ } @@ -773,9 +773,9 @@ FETCH(R8G8B8A8_SRGB)(const struct swrast_texture_image *texImage, GLint i, GLint j, GLint k, GLfloat *texel) { const GLuint s = *TEXEL_ADDR(GLuint, texImage, i, j, k, 1); - texel[RCOMP] = nonlinear_to_linear( (s ) & 0xff ); - texel[GCOMP] = nonlinear_to_linear( (s >> 8) & 0xff ); - texel[BCOMP] = nonlinear_to_linear( (s >> 16) & 0xff ); + texel[RCOMP] = util_format_srgb_8unorm_to_linear_float( (s ) & 0xff ); + texel[GCOMP] = util_format_srgb_8unorm_to_linear_float( (s >> 8) & 0xff ); + texel[BCOMP] = util_format_srgb_8unorm_to_linear_float( (s >> 16) & 0xff ); texel[ACOMP] = UBYTE_TO_FLOAT( (s >> 24) ); /* linear! */ } @@ -785,9 +785,9 @@ FETCH(R8G8B8X8_SRGB)(const struct swrast_texture_image *texImage, GLint i, GLint j, GLint k, GLfloat *texel) { const GLuint s = *TEXEL_ADDR(GLuint, texImage, i, j, k, 1); - texel[RCOMP] = nonlinear_to_linear( (s ) & 0xff ); - texel[GCOMP] = nonlinear_to_linear( (s >> 8) & 0xff ); - texel[BCOMP] = nonlinear_to_linear( (s >> 16) & 0xff ); + texel[RCOMP] = util_format_srgb_8unorm_to_linear_float( (s ) & 0xff ); + texel[GCOMP] = util_format_srgb_8unorm_to_linear_float( (s >> 8) & 0xff ); + texel[BCOMP] = util_format_srgb_8unorm_to_linear_float( (s >> 16) & 0xff ); texel[ACOMP] = 1.0f; } @@ -799,7 +799,7 @@ FETCH(L_SRGB8)(const struct swrast_texture_image *texImage, const GLubyte *src = TEXEL_ADDR(GLubyte, texImage, i, j, k, 1); texel[RCOMP] = texel[GCOMP] = - texel[BCOMP] = nonlinear_to_linear(src[0]); + texel[BCOMP] = util_format_srgb_8unorm_to_linear_float(src[0]); texel[ACOMP] = 1.0F; } @@ -811,7 +811,7 @@ FETCH(L8A8_SRGB)(const struct swrast_texture_image *texImage, const GLubyte *src = TEXEL_ADDR(GLubyte, texImage, i, j, k, 2); texel[RCOMP] = texel[GCOMP] = - texel[BCOMP] = nonlinear_to_linear(src[0]); + texel[BCOMP] = util_format_srgb_8unorm_to_linear_float(src[0]); texel[ACOMP] = UBYTE_TO_FLOAT(src[1]); /* linear */ } diff --git a/mesalib/src/mesa/x86/common_x86.c b/mesalib/src/mesa/x86/common_x86.c index b401c354a..2a936a473 100644 --- a/mesalib/src/mesa/x86/common_x86.c +++ b/mesalib/src/mesa/x86/common_x86.c @@ -343,16 +343,18 @@ _mesa_get_x86_features(void) #endif #elif defined(USE_X86_64_ASM) - unsigned int uninitialized_var(eax), uninitialized_var(ebx), - uninitialized_var(ecx), uninitialized_var(edx); + { + unsigned int uninitialized_var(eax), uninitialized_var(ebx), + uninitialized_var(ecx), uninitialized_var(edx); - /* Always available on x86-64. */ - _mesa_x86_cpu_features |= X86_FEATURE_XMM | X86_FEATURE_XMM2; + /* Always available on x86-64. */ + _mesa_x86_cpu_features |= X86_FEATURE_XMM | X86_FEATURE_XMM2; - __get_cpuid(1, &eax, &ebx, &ecx, &edx); + __get_cpuid(1, &eax, &ebx, &ecx, &edx); - if (ecx & bit_SSE4_1) - _mesa_x86_cpu_features |= X86_FEATURE_SSE4_1; + if (ecx & bit_SSE4_1) + _mesa_x86_cpu_features |= X86_FEATURE_SSE4_1; + } #endif /* USE_X86_64_ASM */ (void) detection_debug; diff --git a/mesalib/src/util/.gitignore b/mesalib/src/util/.gitignore new file mode 100644 index 000000000..e945ecbb5 --- /dev/null +++ b/mesalib/src/util/.gitignore @@ -0,0 +1 @@ +format_srgb.c diff --git a/mesalib/src/util/Makefile.am b/mesalib/src/util/Makefile.am new file mode 100644 index 000000000..4733a1a74 --- /dev/null +++ b/mesalib/src/util/Makefile.am @@ -0,0 +1,41 @@ +# Copyright © 2014 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. + +SUBDIRS = . tests/hash_table + +include Makefile.sources + +noinst_LTLIBRARIES = libmesautil.la + +libmesautil_la_CPPFLAGS = \ + $(DEFINES) \ + -I$(top_srcdir)/include \ + $(VISIBILITY_CFLAGS) + +libmesautil_la_SOURCES = \ + $(MESA_UTIL_FILES) \ + $(MESA_UTIL_GENERATED_FILES) + +BUILT_SOURCES = $(MESA_UTIL_GENERATED_FILES) +CLEANFILES = $(BUILT_SOURCES) + +format_srgb.c: $(srcdir)/format_srgb.py + $(AM_V_GEN) $(PYTHON2) $< > $@ diff --git a/mesalib/src/util/Makefile.sources b/mesalib/src/util/Makefile.sources new file mode 100644 index 000000000..b99aa25e8 --- /dev/null +++ b/mesalib/src/util/Makefile.sources @@ -0,0 +1,6 @@ +MESA_UTIL_FILES := \ + hash_table.c \ + ralloc.c + +MESA_UTIL_GENERATED_FILES = \ + format_srgb.c diff --git a/mesalib/src/util/SConscript b/mesalib/src/util/SConscript new file mode 100644 index 000000000..84803c016 --- /dev/null +++ b/mesalib/src/util/SConscript @@ -0,0 +1,35 @@ +import common + +Import('*') + +from sys import executable as python_cmd + +env = env.Clone() + +env.Prepend(CPPPATH = [ + '#include', + '#src/util', +]) + +env.CodeGenerate( + target = 'format_srgb.c', + script = 'format_srgb.py', + source = [], + command = python_cmd + ' $SCRIPT > $TARGET' +) + +# parse Makefile.sources +source_lists = env.ParseSourceList('Makefile.sources') + +mesautil_sources = ( + source_lists['MESA_UTIL_FILES'] + + source_lists['MESA_UTIL_GENERATED_FILES'] +) + +mesautil = env.ConvenienceLibrary( + target = 'mesautil', + source = mesautil_sources, +) + +env.Alias('mesautil', mesautil) +Export('mesautil') diff --git a/mesalib/src/gallium/auxiliary/util/u_format_srgb.h b/mesalib/src/util/format_srgb.h index 740a91974..4a8d73f12 100644 --- a/mesalib/src/gallium/auxiliary/util/u_format_srgb.h +++ b/mesalib/src/util/format_srgb.h @@ -37,11 +37,9 @@ #ifndef U_FORMAT_SRGB_H_ #define U_FORMAT_SRGB_H_ - -#include "pipe/p_compiler.h" -#include "u_pack_color.h" -#include "u_math.h" - +#include <stdint.h> +#include <math.h> +#include "c99_compat.h" extern const float util_format_srgb_8unorm_to_linear_float_table[256]; @@ -56,54 +54,58 @@ extern const unsigned util_format_linear_to_srgb_helper_table[104]; +static inline float +util_format_linear_to_srgb_float(float cl) +{ + if (cl < 0.0f) + return 0.0f; + else if (cl < 0.0031308f) + return 12.92f * cl; + else if (cl < 1.0f) + return 1.055f * powf(cl, 0.41666f) - 0.055f; + else + return 1.0f; +} + + /** * Convert a unclamped linear float to srgb value in the [0,255]. */ -static INLINE uint8_t +static inline uint8_t util_format_linear_float_to_srgb_8unorm(float x) { - /* this would be exact but (probably much) slower */ - if (0) { - if (x >= 1.0f) - return 255; - else if (x >= 0.0031308f) - return float_to_ubyte(1.055f * powf(x, 0.41666666f) - 0.055f); - else if (x > 0.0f) - return float_to_ubyte(12.92f * x); - else - return 0; - } - else { - /* - * This is taken from https://gist.github.com/rygorous/2203834 - * Use LUT and do linear interpolation. - */ - union fi almostone, minval, f; - unsigned tab, bias, scale, t; - - almostone.ui = 0x3f7fffff; - minval.ui = (127-13) << 23; - - /* - * Clamp to [2^(-13), 1-eps]; these two values map to 0 and 1, respectively. - * The tests are carefully written so that NaNs map to 0, same as in the - * reference implementation. - */ - if (!(x > minval.f)) - x = minval.f; - if (x > almostone.f) - x = almostone.f; - - /* Do the table lookup and unpack bias, scale */ - f.f = x; - tab = util_format_linear_to_srgb_helper_table[(f.ui - minval.ui) >> 20]; - bias = (tab >> 16) << 9; - scale = tab & 0xffff; - - /* Grab next-highest mantissa bits and perform linear interpolation */ - t = (f.ui >> 12) & 0xff; - return (uint8_t) ((bias + scale*t) >> 16); - } + /* + * This is taken from https://gist.github.com/rygorous/2203834 + * Use LUT and do linear interpolation. + */ + union { + uint32_t ui; + float f; + } almostone, minval, f; + unsigned tab, bias, scale, t; + + almostone.ui = 0x3f7fffff; + minval.ui = (127-13) << 23; + + /* + * Clamp to [2^(-13), 1-eps]; these two values map to 0 and 1, respectively. + * The tests are carefully written so that NaNs map to 0, same as in the + * reference implementation. + */ + if (!(x > minval.f)) + x = minval.f; + if (x > almostone.f) + x = almostone.f; + + /* Do the table lookup and unpack bias, scale */ + f.f = x; + tab = util_format_linear_to_srgb_helper_table[(f.ui - minval.ui) >> 20]; + bias = (tab >> 16) << 9; + scale = tab & 0xffff; + + /* Grab next-highest mantissa bits and perform linear interpolation */ + t = (f.ui >> 12) & 0xff; + return (uint8_t) ((bias + scale*t) >> 16); } @@ -112,7 +114,7 @@ util_format_linear_float_to_srgb_8unorm(float x) * linear RGB value in [0, 1]. * Implemented with a 256-entry lookup table. */ -static INLINE float +static inline float util_format_srgb_8unorm_to_linear_float(uint8_t x) { return util_format_srgb_8unorm_to_linear_float_table[x]; @@ -127,7 +129,7 @@ util_format_srgb_8unorm_to_linear_float(uint8_t x) /** * Convert a 8bit normalized value from linear to srgb. */ -static INLINE uint8_t +static inline uint8_t util_format_linear_to_srgb_8unorm(uint8_t x) { return util_format_linear_to_srgb_8unorm_table[x]; @@ -137,7 +139,7 @@ util_format_linear_to_srgb_8unorm(uint8_t x) /** * Convert a 8bit normalized value from srgb to linear. */ -static INLINE uint8_t +static inline uint8_t util_format_srgb_to_linear_8unorm(uint8_t x) { return util_format_srgb_to_linear_8unorm_table[x]; diff --git a/mesalib/src/gallium/auxiliary/util/u_format_srgb.py b/mesalib/src/util/format_srgb.py index c6c02f053..d5cbcf764 100644 --- a/mesalib/src/gallium/auxiliary/util/u_format_srgb.py +++ b/mesalib/src/util/format_srgb.py @@ -109,7 +109,7 @@ def generate_srgb_tables(): start = ((127 - numexp) << 23) + bucket*(bucketsize << stepshift) sum_a = 0.0 sum_b = 0.0 - + for i in range(0, bucketsize): j = (i << stepshift) >> mantshift fint = start + (i << stepshift) @@ -123,7 +123,7 @@ def generate_srgb_tables(): scaled_a = solved_a * 65536.0 / 512.0 scaled_b = solved_b * 65536.0 - + int_a = int(scaled_a + 0.5) int_b = int(scaled_b + 0.5) @@ -146,9 +146,9 @@ def main(): # This will print the copyright message on the top of this file print CopyRight.strip() print - print '#include "u_format_srgb.h"' + print '#include "format_srgb.h"' print - generate_srgb_tables() + generate_srgb_tables() if __name__ == '__main__': diff --git a/mesalib/src/mesa/main/hash_table.c b/mesalib/src/util/hash_table.c index ad8f89852..1b6726c79 100644 --- a/mesalib/src/mesa/main/hash_table.c +++ b/mesalib/src/util/hash_table.c @@ -43,9 +43,9 @@ #include <stdlib.h> #include <string.h> -#include "main/hash_table.h" -#include "main/macros.h" +#include "hash_table.h" #include "ralloc.h" +#include "macros.h" static const uint32_t deleted_key_value; diff --git a/mesalib/src/mesa/main/hash_table.h b/mesalib/src/util/hash_table.h index f51131aee..d6b6ebf40 100644 --- a/mesalib/src/mesa/main/hash_table.h +++ b/mesalib/src/util/hash_table.h @@ -28,10 +28,11 @@ #ifndef _HASH_TABLE_H #define _HASH_TABLE_H +#include <stdlib.h> #include <inttypes.h> #include <stdbool.h> - -#include "compiler.h" +#include "c99_compat.h" +#include "macros.h" #ifdef __cplusplus extern "C" { diff --git a/mesalib/src/util/macros.h b/mesalib/src/util/macros.h new file mode 100644 index 000000000..ee05e05a4 --- /dev/null +++ b/mesalib/src/util/macros.h @@ -0,0 +1,128 @@ +/* + * Copyright © 2014 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. + */ + +#ifndef UTIL_MACROS_H +#define UTIL_MACROS_H + +/* Compute the size of an array */ +#ifndef ARRAY_SIZE +# define ARRAY_SIZE(x) (sizeof(x) / sizeof(*(x))) +#endif + + +/** + * __builtin_expect macros + */ +#if !defined(__GNUC__) +# define __builtin_expect(x, y) (x) +#endif + +#ifndef likely +# ifdef __GNUC__ +# define likely(x) __builtin_expect(!!(x), 1) +# define unlikely(x) __builtin_expect(!!(x), 0) +# else +# define likely(x) (x) +# define unlikely(x) (x) +# endif +#endif + + +/** + * Static (compile-time) assertion. + * Basically, use COND to dimension an array. If COND is false/zero the + * array size will be -1 and we'll get a compilation error. + */ +#define STATIC_ASSERT(COND) \ + do { \ + (void) sizeof(char [1 - 2*!(COND)]); \ + } while (0) + + +/** + * Unreachable macro. Useful for suppressing "control reaches end of non-void + * function" warnings. + */ +#if __GNUC__ >= 4 && __GNUC_MINOR__ >= 5 +#define unreachable(str) \ +do { \ + assert(!str); \ + __builtin_unreachable(); \ +} while (0) +#elif (defined(__clang__) && defined(__has_builtin)) +# if __has_builtin(__builtin_unreachable) +# define unreachable(str) \ +do { \ + assert(!str); \ + __builtin_unreachable(); \ +} while (0) +# endif +#endif + +#ifndef unreachable +#define unreachable(str) +#endif + + +#if (__GNUC__ >= 3) +#define PRINTFLIKE(f, a) __attribute__ ((format(__printf__, f, a))) +#else +#define PRINTFLIKE(f, a) +#endif + + +/* Used to optionally mark structures with misaligned elements or size as + * packed, to trade off performance for space. + */ +#if (__GNUC__ >= 3) +#define PACKED __attribute__((__packed__)) +#else +#define PACKED +#endif + + +#ifdef __cplusplus +/** + * Macro function that evaluates to true if T is a trivially + * destructible type -- that is, if its (non-virtual) destructor + * performs no action and all member variables and base classes are + * trivially destructible themselves. + */ +# if defined(__GNUC__) +# if ((__GNUC__ > 4) || ((__GNUC__ == 4) && (__GNUC_MINOR__ >= 3))) +# define HAS_TRIVIAL_DESTRUCTOR(T) __has_trivial_destructor(T) +# endif +# elif (defined(__clang__) && defined(__has_feature)) +# if __has_feature(has_trivial_destructor) +# define HAS_TRIVIAL_DESTRUCTOR(T) __has_trivial_destructor(T) +# endif +# endif +# ifndef HAS_TRIVIAL_DESTRUCTOR + /* It's always safe (if inefficient) to assume that a + * destructor is non-trivial. + */ +# define HAS_TRIVIAL_DESTRUCTOR(T) (false) +# endif +#endif + +#endif /* UTIL_MACROS_H */ diff --git a/mesalib/src/glsl/ralloc.c b/mesalib/src/util/ralloc.c index 36bc61fd0..36bc61fd0 100644 --- a/mesalib/src/glsl/ralloc.c +++ b/mesalib/src/util/ralloc.c diff --git a/mesalib/src/glsl/ralloc.h b/mesalib/src/util/ralloc.h index 1fe53573f..4b88f3286 100644 --- a/mesalib/src/glsl/ralloc.h +++ b/mesalib/src/util/ralloc.h @@ -53,7 +53,8 @@ extern "C" { #include <stddef.h> #include <stdarg.h> #include <stdbool.h> -#include "main/compiler.h" + +#include "macros.h" /** * \def ralloc(ctx, type) |