aboutsummaryrefslogtreecommitdiff
path: root/mesalib
diff options
context:
space:
mode:
Diffstat (limited to 'mesalib')
-rw-r--r--mesalib/Makefile6
-rw-r--r--mesalib/configure.ac75
-rw-r--r--mesalib/src/gallium/auxiliary/util/u_debug.c2
-rw-r--r--mesalib/src/gallium/auxiliary/util/u_format.csv14
-rw-r--r--mesalib/src/glsl/Makefile27
-rw-r--r--mesalib/src/glsl/SConscript1
-rw-r--r--mesalib/src/glsl/ir_optimization.h4
-rw-r--r--mesalib/src/glsl/lower_variable_index_to_cond_assign.cpp309
-rw-r--r--mesalib/src/glsl/lower_vec_index_to_cond_assign.cpp91
-rw-r--r--mesalib/src/glsl/main.cpp60
-rw-r--r--mesalib/src/glsl/standalone_scaffolding.cpp91
-rw-r--r--mesalib/src/glsl/standalone_scaffolding.h54
-rw-r--r--mesalib/src/glsl/test.cpp78
-rw-r--r--mesalib/src/glsl/test_optpass.cpp273
-rw-r--r--mesalib/src/glsl/test_optpass.h30
-rw-r--r--mesalib/src/mesa/drivers/common/meta.c14
-rw-r--r--mesalib/src/mesa/main/compiler.h42
-rw-r--r--mesalib/src/mesa/main/get.c4
-rw-r--r--mesalib/src/mesa/main/texcompress.c205
-rw-r--r--mesalib/src/mesa/main/texcompress.h121
-rw-r--r--mesalib/src/mesa/main/texparam.c20
-rw-r--r--mesalib/src/mesa/program/ir_to_mesa.cpp20
-rw-r--r--mesalib/src/mesa/program/prog_optimize.c9
23 files changed, 1220 insertions, 330 deletions
diff --git a/mesalib/Makefile b/mesalib/Makefile
index 817f3d370..916c49841 100644
--- a/mesalib/Makefile
+++ b/mesalib/Makefile
@@ -21,6 +21,10 @@ all: default
doxygen:
cd doxygen && $(MAKE)
+check:
+ cd src/glsl/tests/ && ./optimization-test
+ @echo "All tests passed."
+
clean:
-@touch $(TOP)/configs/current
-@for dir in $(SUBDIRS) ; do \
@@ -51,7 +55,7 @@ install:
done
-.PHONY: default doxygen clean realclean distclean install
+.PHONY: default doxygen clean realclean distclean install check
# If there's no current configuration file
$(TOP)/configs/current:
diff --git a/mesalib/configure.ac b/mesalib/configure.ac
index 86ba87b39..5c832e646 100644
--- a/mesalib/configure.ac
+++ b/mesalib/configure.ac
@@ -1326,6 +1326,41 @@ AC_SUBST([OSMESA_PC_REQ])
AC_SUBST([OSMESA_PC_LIB_PRIV])
dnl
+dnl gbm configuration
+dnl
+if test "x$enable_gbm" = xauto; then
+ case "$with_egl_platforms" in
+ *drm*)
+ enable_gbm=yes ;;
+ *)
+ enable_gbm=no ;;
+ esac
+fi
+if test "x$enable_gbm" = xyes; then
+ SRC_DIRS="$SRC_DIRS gbm"
+ GBM_BACKEND_DIRS=""
+
+ PKG_CHECK_MODULES([LIBUDEV], [libudev], [],
+ AC_MSG_ERROR([gbm needs udev]))
+ GBM_LIB_DEPS="$DLOPEN_LIBS $LIBUDEV_LIBS"
+
+ if test "x$enable_dri" = xyes; then
+ GBM_BACKEND_DIRS="$GBM_BACKEND_DIRS dri"
+ if test "$SHARED_GLAPI" -eq 0; then
+ AC_MSG_ERROR([gbm_dri requires --enable-shared-glapi])
+ fi
+ fi
+fi
+AC_SUBST([GBM_LIB_DEPS])
+AC_SUBST([GBM_BACKEND_DIRS])
+GBM_PC_REQ_PRIV="libudev"
+GBM_PC_LIB_PRIV="$DLOPEN_LIBS"
+GBM_PC_CFLAGS=
+AC_SUBST([GBM_PC_REQ_PRIV])
+AC_SUBST([GBM_PC_LIB_PRIV])
+AC_SUBST([GBM_PC_CFLAGS])
+
+dnl
dnl EGL configuration
dnl
EGL_CLIENT_APIS=""
@@ -1367,41 +1402,6 @@ AC_SUBST([EGL_LIB_DEPS])
AC_SUBST([EGL_DRIVERS_DIRS])
dnl
-dnl gbm configuration
-dnl
-if test "x$enable_gbm" = xauto; then
- case "$with_egl_platforms" in
- *drm*)
- enable_gbm=yes ;;
- *)
- enable_gbm=no ;;
- esac
-fi
-if test "x$enable_gbm" = xyes; then
- SRC_DIRS="$SRC_DIRS gbm"
- GBM_BACKEND_DIRS=""
-
- PKG_CHECK_MODULES([LIBUDEV], [libudev], [],
- AC_MSG_ERROR([gbm needs udev]))
- GBM_LIB_DEPS="$DLOPEN_LIBS $LIBUDEV_LIBS"
-
- if test "x$enable_dri" = xyes; then
- GBM_BACKEND_DIRS="$GBM_BACKEND_DIRS dri"
- if test "$SHARED_GLAPI" -eq 0; then
- AC_MSG_ERROR([gbm_dri requires --enable-shared-glapi])
- fi
- fi
-fi
-AC_SUBST([GBM_LIB_DEPS])
-AC_SUBST([GBM_BACKEND_DIRS])
-GBM_PC_REQ_PRIV="libudev"
-GBM_PC_LIB_PRIV="$DLOPEN_LIBS"
-GBM_PC_CFLAGS=
-AC_SUBST([GBM_PC_REQ_PRIV])
-AC_SUBST([GBM_PC_LIB_PRIV])
-AC_SUBST([GBM_PC_CFLAGS])
-
-dnl
dnl EGL Gallium configuration
dnl
if test "x$enable_gallium_egl" = xyes; then
@@ -1699,9 +1699,6 @@ dnl Gallium configuration
dnl
if test "x$with_gallium_drivers" != x; then
SRC_DIRS="$SRC_DIRS gallium gallium/winsys gallium/targets"
- AC_PATH_PROG([LLVM_CONFIG], [llvm-config], [no])
-else
- LLVM_CONFIG=no
fi
AC_SUBST([LLVM_CFLAGS])
@@ -1821,6 +1818,8 @@ if test "x$enable_gallium_llvm" = xauto; then
esac
fi
if test "x$enable_gallium_llvm" = xyes; then
+ AC_PATH_PROG([LLVM_CONFIG], [llvm-config], [no])
+
if test "x$LLVM_CONFIG" != xno; then
LLVM_VERSION=`$LLVM_CONFIG --version`
LLVM_CFLAGS=`$LLVM_CONFIG --cppflags|sed 's/-DNDEBUG\>//g'`
diff --git a/mesalib/src/gallium/auxiliary/util/u_debug.c b/mesalib/src/gallium/auxiliary/util/u_debug.c
index 004df439f..2d6193039 100644
--- a/mesalib/src/gallium/auxiliary/util/u_debug.c
+++ b/mesalib/src/gallium/auxiliary/util/u_debug.c
@@ -730,7 +730,7 @@ debug_dump_float_rgba_bmp(const char *filename,
pixel.rgbRed = float_to_ubyte(ptr[x*4 + 0]);
pixel.rgbGreen = float_to_ubyte(ptr[x*4 + 1]);
pixel.rgbBlue = float_to_ubyte(ptr[x*4 + 2]);
- pixel.rgbAlpha = 255;
+ pixel.rgbAlpha = float_to_ubyte(ptr[x*4 + 3]);
os_stream_write(stream, &pixel, 4);
}
}
diff --git a/mesalib/src/gallium/auxiliary/util/u_format.csv b/mesalib/src/gallium/auxiliary/util/u_format.csv
index 347e2beb8..a3d2aae62 100644
--- a/mesalib/src/gallium/auxiliary/util/u_format.csv
+++ b/mesalib/src/gallium/auxiliary/util/u_format.csv
@@ -260,10 +260,10 @@ PIPE_FORMAT_R10G10B10X2_USCALED , plain, 1, 1, u10 , u10 , u10 , x2 , xyz1, r
# A.k.a. D3DDECLTYPE_DEC3N
PIPE_FORMAT_R10G10B10X2_SNORM , plain, 1, 1, sn10, sn10, sn10 , x2 , xyz1, rgb
-PIPE_FORMAT_YV12 , subsampled, 1, 1, x8 , x8 , x8 , x8 , xyzw, yuv
-PIPE_FORMAT_YV16 , subsampled, 1, 1, x8 , x8 , x8 , x8 , xyzw, yuv
-PIPE_FORMAT_IYUV , subsampled, 1, 1, x8 , x8 , x8 , x8 , xyzw, yuv
-PIPE_FORMAT_NV12 , subsampled, 1, 1, x8 , x8 , x8 , x8 , xyzw, yuv
-PIPE_FORMAT_NV21 , subsampled, 1, 1, x8 , x8 , x8 , x8 , xyzw, yuv
-PIPE_FORMAT_IA44 , subsampled, 1, 1, x8 , x8 , x8 , x8 , xyzw, yuv
-PIPE_FORMAT_AI44 , subsampled, 1, 1, x8 , x8 , x8 , x8 , xyzw, yuv
+PIPE_FORMAT_YV12 , other, 1, 1, x8 , x8 , x8 , x8 , xyzw, yuv
+PIPE_FORMAT_YV16 , other, 1, 1, x8 , x8 , x8 , x8 , xyzw, yuv
+PIPE_FORMAT_IYUV , other, 1, 1, x8 , x8 , x8 , x8 , xyzw, yuv
+PIPE_FORMAT_NV12 , other, 1, 1, x8 , x8 , x8 , x8 , xyzw, yuv
+PIPE_FORMAT_NV21 , other, 1, 1, x8 , x8 , x8 , x8 , xyzw, yuv
+PIPE_FORMAT_IA44 , other, 1, 1, x8 , x8 , x8 , x8 , xyzw, yuv
+PIPE_FORMAT_AI44 , other, 1, 1, x8 , x8 , x8 , x8 , xyzw, yuv
diff --git a/mesalib/src/glsl/Makefile b/mesalib/src/glsl/Makefile
index d1422c2a4..005b51d72 100644
--- a/mesalib/src/glsl/Makefile
+++ b/mesalib/src/glsl/Makefile
@@ -89,18 +89,32 @@ CXX_SOURCES = \
LIBS = \
$(TOP)/src/glsl/libglsl.a
-APPS = glsl_compiler glcpp/glcpp
+APPS = glsl_compiler glsl_test glcpp/glcpp
GLSL2_C_SOURCES = \
../mesa/program/hash_table.c \
../mesa/program/symbol_table.c
GLSL2_CXX_SOURCES = \
- main.cpp
+ main.cpp \
+ standalone_scaffolding.cpp
GLSL2_OBJECTS = \
$(GLSL2_C_SOURCES:.c=.o) \
$(GLSL2_CXX_SOURCES:.cpp=.o)
+TEST_C_SOURCES = \
+ ../mesa/program/hash_table.c \
+ ../mesa/program/symbol_table.c
+
+TEST_CXX_SOURCES = \
+ standalone_scaffolding.cpp \
+ test.cpp \
+ test_optpass.cpp
+
+TEST_OBJECTS = \
+ $(TEST_C_SOURCES:.c=.o) \
+ $(TEST_CXX_SOURCES:.cpp=.o)
+
### Basic defines ###
DEFINES += \
@@ -129,7 +143,9 @@ ALL_SOURCES = \
$(C_SOURCES) \
$(CXX_SOURCES) \
$(GLSL2_CXX_SOURCES) \
- $(GLSL2_C_SOURCES)
+ $(GLSL2_C_SOURCES) \
+ $(TEST_CXX_SOURCES) \
+ $(TEST_C_SOURCES)
##### TARGETS #####
@@ -151,7 +167,7 @@ depend: $(ALL_SOURCES) Makefile
# Remove .o and backup files
clean: clean-dricore
- rm -f $(GLCPP_OBJECTS) $(GLSL2_OBJECTS) $(OBJECTS) lib$(LIBNAME).a depend depend.bak builtin_function.cpp builtin_function.o builtin_stubs.o builtin_compiler
+ rm -f $(GLCPP_OBJECTS) $(GLSL2_OBJECTS) $(TEST_OBJECTS) $(OBJECTS) lib$(LIBNAME).a depend depend.bak builtin_function.cpp builtin_function.o builtin_stubs.o builtin_compiler
-rm -f $(APPS)
clean-dricore:
@@ -174,6 +190,9 @@ install-dricore: default
glsl_compiler: $(GLSL2_OBJECTS) libglsl.a builtin_stubs.o
$(APP_CXX) $(INCLUDES) $(CFLAGS) $(LDFLAGS) $(GLSL2_OBJECTS) builtin_stubs.o $(LIBS) -o $@
+glsl_test: $(TEST_OBJECTS) libglsl.a builtin_stubs.o
+ $(APP_CXX) $(INCLUDES) $(CFLAGS) $(LDFLAGS) $(TEST_OBJECTS) builtin_stubs.o $(LIBS) -o $@
+
glcpp: glcpp/glcpp
glcpp/glcpp: $(GLCPP_OBJECTS)
$(APP_CC) $(INCLUDES) $(CFLAGS) $(LDFLAGS) $(GLCPP_OBJECTS) -o $@
diff --git a/mesalib/src/glsl/SConscript b/mesalib/src/glsl/SConscript
index ea104abb8..1da58a91f 100644
--- a/mesalib/src/glsl/SConscript
+++ b/mesalib/src/glsl/SConscript
@@ -96,6 +96,7 @@ glsl_sources = [
'opt_tree_grafting.cpp',
'ralloc.c',
's_expression.cpp',
+ 'standalone_scaffolding.cpp',
'strtod.c',
]
diff --git a/mesalib/src/glsl/ir_optimization.h b/mesalib/src/glsl/ir_optimization.h
index 59a040751..f7808bdda 100644
--- a/mesalib/src/glsl/ir_optimization.h
+++ b/mesalib/src/glsl/ir_optimization.h
@@ -69,3 +69,7 @@ bool lower_variable_index_to_cond_assign(exec_list *instructions,
bool lower_input, bool lower_output, bool lower_temp, bool lower_uniform);
bool lower_quadop_vector(exec_list *instructions, bool dont_lower_swz);
bool optimize_redundant_jumps(exec_list *instructions);
+
+ir_rvalue *
+compare_index_block(exec_list *instructions, ir_variable *index,
+ unsigned base, unsigned components, void *mem_ctx);
diff --git a/mesalib/src/glsl/lower_variable_index_to_cond_assign.cpp b/mesalib/src/glsl/lower_variable_index_to_cond_assign.cpp
index 8eb1612f0..f8e4a1de4 100644
--- a/mesalib/src/glsl/lower_variable_index_to_cond_assign.cpp
+++ b/mesalib/src/glsl/lower_variable_index_to_cond_assign.cpp
@@ -29,6 +29,21 @@
*
* Pre-DX10 GPUs often don't have a native way to do this operation,
* and this works around that.
+ *
+ * The lowering process proceeds as follows. Each non-constant index
+ * found in an r-value is converted to a canonical form \c array[i]. Each
+ * element of the array is conditionally assigned to a temporary by comparing
+ * \c i to a constant index. This is done by cloning the canonical form and
+ * replacing all occurances of \c i with a constant. Each remaining occurance
+ * of the canonical form in the IR is replaced with a dereference of the
+ * temporary variable.
+ *
+ * L-values with non-constant indices are handled similarly. In this case,
+ * the RHS of the assignment is assigned to a temporary. The non-constant
+ * index is replace with the canonical form (just like for r-values). The
+ * temporary is conditionally assigned to each element of the canonical form
+ * by comparing \c i with each index. The same clone-and-replace scheme is
+ * used.
*/
#include "ir.h"
@@ -37,10 +52,140 @@
#include "glsl_types.h"
#include "main/macros.h"
+/**
+ * Generate a comparison value for a block of indices
+ *
+ * Lowering passes for non-constant indexing of arrays, matrices, or vectors
+ * can use this to generate blocks of index comparison values.
+ *
+ * \param instructions List where new instructions will be appended
+ * \param index \c ir_variable containing the desired index
+ * \param base Base value for this block of comparisons
+ * \param components Number of unique index values to compare. This must
+ * be on the range [1, 4].
+ * \param mem_ctx ralloc memory context to be used for all allocations.
+ *
+ * \returns
+ * An \c ir_rvalue that \b must be cloned for each use in conditional
+ * assignments, etc.
+ */
+ir_rvalue *
+compare_index_block(exec_list *instructions, ir_variable *index,
+ unsigned base, unsigned components, void *mem_ctx)
+{
+ ir_rvalue *broadcast_index = new(mem_ctx) ir_dereference_variable(index);
+
+ assert(index->type->is_scalar());
+ assert(index->type->base_type == GLSL_TYPE_INT);
+ assert(components >= 1 && components <= 4);
+
+ if (components > 1) {
+ const ir_swizzle_mask m = { 0, 0, 0, 0, components, false };
+ broadcast_index = new(mem_ctx) ir_swizzle(broadcast_index, m);
+ }
+
+ /* Compare the desired index value with the next block of four indices.
+ */
+ ir_constant_data test_indices_data;
+ memset(&test_indices_data, 0, sizeof(test_indices_data));
+ test_indices_data.i[0] = base;
+ test_indices_data.i[1] = base + 1;
+ test_indices_data.i[2] = base + 2;
+ test_indices_data.i[3] = base + 3;
+
+ ir_constant *const test_indices =
+ new(mem_ctx) ir_constant(broadcast_index->type,
+ &test_indices_data);
+
+ ir_rvalue *const condition_val =
+ new(mem_ctx) ir_expression(ir_binop_equal,
+ &glsl_type::bool_type[components - 1],
+ broadcast_index,
+ test_indices);
+
+ ir_variable *const condition =
+ new(mem_ctx) ir_variable(condition_val->type,
+ "dereference_condition",
+ ir_var_temporary);
+ instructions->push_tail(condition);
+
+ ir_rvalue *const cond_deref =
+ new(mem_ctx) ir_dereference_variable(condition);
+ instructions->push_tail(new(mem_ctx) ir_assignment(cond_deref, condition_val, 0));
+
+ return cond_deref;
+}
+
+static inline bool
+is_array_or_matrix(const ir_instruction *ir)
+{
+ return (ir->type->is_array() || ir->type->is_matrix());
+}
+
+/**
+ * Replace a dereference of a variable with a specified r-value
+ *
+ * Each time a dereference of the specified value is replaced, the r-value
+ * tree is cloned.
+ */
+class deref_replacer : public ir_rvalue_visitor {
+public:
+ deref_replacer(const ir_variable *variable_to_replace, ir_rvalue *value)
+ : variable_to_replace(variable_to_replace), value(value),
+ progress(false)
+ {
+ assert(this->variable_to_replace != NULL);
+ assert(this->value != NULL);
+ }
+
+ virtual void handle_rvalue(ir_rvalue **rvalue)
+ {
+ ir_dereference_variable *const dv = (*rvalue)->as_dereference_variable();
+
+ if ((dv != NULL) && (dv->var == this->variable_to_replace)) {
+ this->progress = true;
+ *rvalue = this->value->clone(ralloc_parent(*rvalue), NULL);
+ }
+ }
+
+ const ir_variable *variable_to_replace;
+ ir_rvalue *value;
+ bool progress;
+};
+
+/**
+ * Find a variable index dereference of an array in an rvalue tree
+ */
+class find_variable_index : public ir_hierarchical_visitor {
+public:
+ find_variable_index()
+ : deref(NULL)
+ {
+ /* empty */
+ }
+
+ virtual ir_visitor_status visit_enter(ir_dereference_array *ir)
+ {
+ if (is_array_or_matrix(ir->array)
+ && (ir->array_index->as_constant() == NULL)) {
+ this->deref = ir;
+ return visit_stop;
+ }
+
+ return visit_continue;
+ }
+
+ /**
+ * First array dereference found in the tree that has a non-constant index.
+ */
+ ir_dereference_array *deref;
+};
+
struct assignment_generator
{
ir_instruction* base_ir;
- ir_rvalue* array;
+ ir_dereference *rvalue;
+ ir_variable *old_index;
bool is_write;
unsigned int write_mask;
ir_variable* var;
@@ -55,18 +200,23 @@ struct assignment_generator
* underlying variable.
*/
void *mem_ctx = ralloc_parent(base_ir);
- ir_dereference *element =
- new(mem_ctx) ir_dereference_array(this->array->clone(mem_ctx, NULL),
- new(mem_ctx) ir_constant(i));
- ir_rvalue *variable = new(mem_ctx) ir_dereference_variable(this->var);
- ir_assignment *assignment;
- if (is_write) {
- assignment = new(mem_ctx) ir_assignment(element, variable, condition,
- write_mask);
- } else {
- assignment = new(mem_ctx) ir_assignment(variable, element, condition);
- }
+ /* Clone the old r-value in its entirety. Then replace any occurances of
+ * the old variable index with the new constant index.
+ */
+ ir_dereference *element = this->rvalue->clone(mem_ctx, NULL);
+ ir_constant *const index = new(mem_ctx) ir_constant(i);
+ deref_replacer r(this->old_index, index);
+ element->accept(&r);
+ assert(r.progress);
+
+ /* Generate a conditional assignment to (or from) the constant indexed
+ * array dereference.
+ */
+ ir_rvalue *variable = new(mem_ctx) ir_dereference_variable(this->var);
+ ir_assignment *const assignment = (is_write)
+ ? new(mem_ctx) ir_assignment(element, variable, condition, write_mask)
+ : new(mem_ctx) ir_assignment(variable, element, condition);
list->push_tail(assignment);
}
@@ -118,54 +268,17 @@ struct switch_generator
for (unsigned i = first; i < end; i += 4) {
const unsigned comps = MIN2(condition_components, end - i);
- ir_rvalue *broadcast_index =
- new(this->mem_ctx) ir_dereference_variable(index);
-
- if (comps) {
- const ir_swizzle_mask m = { 0, 0, 0, 0, comps, false };
- broadcast_index = new(this->mem_ctx) ir_swizzle(broadcast_index, m);
- }
-
- /* Compare the desired index value with the next block of four indices.
- */
- ir_constant_data test_indices_data;
- memset(&test_indices_data, 0, sizeof(test_indices_data));
- test_indices_data.i[0] = i;
- test_indices_data.i[1] = i + 1;
- test_indices_data.i[2] = i + 2;
- test_indices_data.i[3] = i + 3;
- ir_constant *const test_indices =
- new(this->mem_ctx) ir_constant(broadcast_index->type,
- &test_indices_data);
-
- ir_rvalue *const condition_val =
- new(this->mem_ctx) ir_expression(ir_binop_equal,
- &glsl_type::bool_type[comps - 1],
- broadcast_index,
- test_indices);
-
- ir_variable *const condition =
- new(this->mem_ctx) ir_variable(condition_val->type,
- "dereference_array_condition",
- ir_var_temporary);
- list->push_tail(condition);
-
ir_rvalue *const cond_deref =
- new(this->mem_ctx) ir_dereference_variable(condition);
- list->push_tail(new(this->mem_ctx) ir_assignment(cond_deref,
- condition_val, 0));
+ compare_index_block(list, index, i, comps, this->mem_ctx);
if (comps == 1) {
- ir_rvalue *const cond_deref =
- new(this->mem_ctx) ir_dereference_variable(condition);
-
- this->generator.generate(i, cond_deref, list);
+ this->generator.generate(i, cond_deref->clone(this->mem_ctx, NULL),
+ list);
} else {
for (unsigned j = 0; j < comps; j++) {
- ir_rvalue *const cond_deref =
- new(this->mem_ctx) ir_dereference_variable(condition);
ir_rvalue *const cond_swiz =
- new(this->mem_ctx) ir_swizzle(cond_deref, j, 0, 0, 0, 1);
+ new(this->mem_ctx) ir_swizzle(cond_deref->clone(this->mem_ctx, NULL),
+ j, 0, 0, 0, 1);
this->generator.generate(i + j, cond_swiz, list);
}
@@ -233,21 +346,18 @@ public:
bool lower_temps;
bool lower_uniforms;
- bool is_array_or_matrix(const ir_instruction *ir) const
- {
- return (ir->type->is_array() || ir->type->is_matrix());
- }
-
- bool needs_lowering(ir_dereference_array *deref) const
+ bool storage_type_needs_lowering(ir_dereference_array *deref) const
{
- if (deref == NULL || deref->array_index->as_constant()
- || !is_array_or_matrix(deref->array))
- return false;
-
- if (deref->array->ir_type == ir_type_constant)
+ /* If a variable isn't eventually the target of this dereference, then
+ * it must be a constant or some sort of anonymous temporary storage.
+ *
+ * FINISHME: Is this correct? Most drivers treat arrays of constants as
+ * FINISHME: uniforms. It seems like this should do the same.
+ */
+ const ir_variable *const var = deref->array->variable_referenced();
+ if (var == NULL)
return this->lower_temps;
- const ir_variable *const var = deref->array->variable_referenced();
switch (var->mode) {
case ir_var_auto:
case ir_var_temporary:
@@ -267,8 +377,18 @@ public:
return false;
}
+ bool needs_lowering(ir_dereference_array *deref) const
+ {
+ if (deref == NULL || deref->array_index->as_constant()
+ || !is_array_or_matrix(deref->array))
+ return false;
+
+ return this->storage_type_needs_lowering(deref);
+ }
+
ir_variable *convert_dereference_array(ir_dereference_array *orig_deref,
- ir_assignment* orig_assign)
+ ir_assignment* orig_assign,
+ ir_dereference *orig_base)
{
assert(is_array_or_matrix(orig_deref->array));
@@ -314,9 +434,12 @@ public:
new(mem_ctx) ir_assignment(lhs, orig_deref->array_index, NULL);
base_ir->insert_before(assign);
+ orig_deref->array_index = lhs->clone(mem_ctx, NULL);
+
assignment_generator ag;
- ag.array = orig_deref->array;
+ ag.rvalue = orig_base;
ag.base_ir = base_ir;
+ ag.old_index = index;
ag.var = var;
if (orig_assign) {
ag.is_write = true;
@@ -327,21 +450,40 @@ public:
switch_generator sg(ag, index, 4, 4);
- exec_list list;
- sg.generate(0, length, &list);
- base_ir->insert_before(&list);
+ /* If the original assignment has a condition, respect that original
+ * condition! This is acomplished by wrapping the new conditional
+ * assignments in an if-statement that uses the original condition.
+ */
+ if ((orig_assign != NULL) && (orig_assign->condition != NULL)) {
+ /* No need to clone the condition because the IR that it hangs on is
+ * going to be removed from the instruction sequence.
+ */
+ ir_if *if_stmt = new(mem_ctx) ir_if(orig_assign->condition);
+
+ sg.generate(0, length, &if_stmt->then_instructions);
+ base_ir->insert_before(if_stmt);
+ } else {
+ exec_list list;
+
+ sg.generate(0, length, &list);
+ base_ir->insert_before(&list);
+ }
return var;
}
virtual void handle_rvalue(ir_rvalue **pir)
{
+ if (this->in_assignee)
+ return;
+
if (!*pir)
return;
ir_dereference_array* orig_deref = (*pir)->as_dereference_array();
if (needs_lowering(orig_deref)) {
- ir_variable* var = convert_dereference_array(orig_deref, 0);
+ ir_variable *var =
+ convert_dereference_array(orig_deref, NULL, orig_deref);
assert(var);
*pir = new(ralloc_parent(base_ir)) ir_dereference_variable(var);
this->progress = true;
@@ -353,10 +495,11 @@ public:
{
ir_rvalue_visitor::visit_leave(ir);
- ir_dereference_array *orig_deref = ir->lhs->as_dereference_array();
+ find_variable_index f;
+ ir->lhs->accept(&f);
- if (needs_lowering(orig_deref)) {
- convert_dereference_array(orig_deref, ir);
+ if ((f.deref != NULL) && storage_type_needs_lowering(f.deref)) {
+ convert_dereference_array(f.deref, ir, ir->lhs);
ir->remove();
this->progress = true;
}
@@ -377,7 +520,17 @@ lower_variable_index_to_cond_assign(exec_list *instructions,
lower_temp,
lower_uniform);
- visit_list_elements(&v, instructions);
-
- return v.progress;
+ /* Continue lowering until no progress is made. If there are multiple
+ * levels of indirection (e.g., non-constant indexing of array elements and
+ * matrix columns of an array of matrix), each pass will only lower one
+ * level of indirection.
+ */
+ bool progress_ever = false;
+ do {
+ v.progress = false;
+ visit_list_elements(&v, instructions);
+ progress_ever = v.progress || progress_ever;
+ } while (v.progress);
+
+ return progress_ever;
}
diff --git a/mesalib/src/glsl/lower_vec_index_to_cond_assign.cpp b/mesalib/src/glsl/lower_vec_index_to_cond_assign.cpp
index 3c4d93201..fce9c3424 100644
--- a/mesalib/src/glsl/lower_vec_index_to_cond_assign.cpp
+++ b/mesalib/src/glsl/lower_vec_index_to_cond_assign.cpp
@@ -71,8 +71,6 @@ ir_vec_index_to_cond_assign_visitor::convert_vec_index_to_cond_assign(ir_rvalue
ir_assignment *assign;
ir_variable *index, *var;
ir_dereference *deref;
- ir_expression *condition;
- ir_swizzle *swizzle;
int i;
if (!orig_deref)
@@ -86,39 +84,52 @@ ir_vec_index_to_cond_assign_visitor::convert_vec_index_to_cond_assign(ir_rvalue
assert(orig_deref->array_index->type->base_type == GLSL_TYPE_INT);
+ exec_list list;
+
/* Store the index to a temporary to avoid reusing its tree. */
index = new(base_ir) ir_variable(glsl_type::int_type,
"vec_index_tmp_i",
ir_var_temporary);
- base_ir->insert_before(index);
+ list.push_tail(index);
deref = new(base_ir) ir_dereference_variable(index);
assign = new(base_ir) ir_assignment(deref, orig_deref->array_index, NULL);
- base_ir->insert_before(assign);
+ list.push_tail(assign);
/* Temporary where we store whichever value we swizzle out. */
var = new(base_ir) ir_variable(ir->type, "vec_index_tmp_v",
ir_var_temporary);
- base_ir->insert_before(var);
+ list.push_tail(var);
+
+ /* Generate a single comparison condition "mask" for all of the components
+ * in the vector.
+ */
+ ir_rvalue *const cond_deref =
+ compare_index_block(&list, index, 0,
+ orig_deref->array->type->vector_elements,
+ mem_ctx);
/* Generate a conditional move of each vector element to the temp. */
for (i = 0; i < orig_deref->array->type->vector_elements; i++) {
- deref = new(base_ir) ir_dereference_variable(index);
- condition = new(base_ir) ir_expression(ir_binop_equal,
- glsl_type::bool_type,
- deref,
- new(base_ir) ir_constant(i));
+ ir_rvalue *condition_swizzle =
+ new(base_ir) ir_swizzle(cond_deref->clone(ir, NULL), i, 0, 0, 0, 1);
/* Just clone the rest of the deref chain when trying to get at the
* underlying variable.
*/
- swizzle = new(base_ir) ir_swizzle(orig_deref->array->clone(mem_ctx, NULL),
- i, 0, 0, 0, 1);
+ ir_rvalue *swizzle =
+ new(base_ir) ir_swizzle(orig_deref->array->clone(mem_ctx, NULL),
+ i, 0, 0, 0, 1);
deref = new(base_ir) ir_dereference_variable(var);
- assign = new(base_ir) ir_assignment(deref, swizzle, condition);
- base_ir->insert_before(assign);
+ assign = new(base_ir) ir_assignment(deref, swizzle, condition_swizzle);
+ list.push_tail(assign);
}
+ /* Put all of the new instructions in the IR stream before the old
+ * instruction.
+ */
+ base_ir->insert_before(&list);
+
this->progress = true;
return new(base_ir) ir_dereference_variable(var);
}
@@ -171,42 +182,66 @@ ir_vec_index_to_cond_assign_visitor::visit_leave(ir_assignment *ir)
assert(orig_deref->array_index->type->base_type == GLSL_TYPE_INT);
+ exec_list list;
+
/* Store the index to a temporary to avoid reusing its tree. */
index = new(ir) ir_variable(glsl_type::int_type, "vec_index_tmp_i",
ir_var_temporary);
- ir->insert_before(index);
+ list.push_tail(index);
deref = new(ir) ir_dereference_variable(index);
assign = new(ir) ir_assignment(deref, orig_deref->array_index, NULL);
- ir->insert_before(assign);
+ list.push_tail(assign);
/* Store the RHS to a temporary to avoid reusing its tree. */
var = new(ir) ir_variable(ir->rhs->type, "vec_index_tmp_v",
ir_var_temporary);
- ir->insert_before(var);
+ list.push_tail(var);
deref = new(ir) ir_dereference_variable(var);
assign = new(ir) ir_assignment(deref, ir->rhs, NULL);
- ir->insert_before(assign);
+ list.push_tail(assign);
+
+ /* Generate a single comparison condition "mask" for all of the components
+ * in the vector.
+ */
+ ir_rvalue *const cond_deref =
+ compare_index_block(&list, index, 0,
+ orig_deref->array->type->vector_elements,
+ mem_ctx);
/* Generate a conditional move of each vector element to the temp. */
for (i = 0; i < orig_deref->array->type->vector_elements; i++) {
- ir_rvalue *condition, *swizzle;
+ ir_rvalue *condition_swizzle =
+ new(ir) ir_swizzle(cond_deref->clone(ir, NULL), i, 0, 0, 0, 1);
- deref = new(ir) ir_dereference_variable(index);
- condition = new(ir) ir_expression(ir_binop_equal,
- glsl_type::bool_type,
- deref,
- new(ir) ir_constant(i));
/* Just clone the rest of the deref chain when trying to get at the
* underlying variable.
*/
- swizzle = new(ir) ir_swizzle(orig_deref->array->clone(mem_ctx, NULL),
- i, 0, 0, 0, 1);
+ ir_rvalue *swizzle =
+ new(ir) ir_swizzle(orig_deref->array->clone(mem_ctx, NULL),
+ i, 0, 0, 0, 1);
deref = new(ir) ir_dereference_variable(var);
- assign = new(ir) ir_assignment(swizzle, deref, condition);
- ir->insert_before(assign);
+ assign = new(ir) ir_assignment(swizzle, deref, condition_swizzle);
+ list.push_tail(assign);
}
+
+ /* If the original assignment has a condition, respect that original
+ * condition! This is acomplished by wrapping the new conditional
+ * assignments in an if-statement that uses the original condition.
+ */
+ if (ir->condition != NULL) {
+ /* No need to clone the condition because the IR that it hangs on is
+ * going to be removed from the instruction sequence.
+ */
+ ir_if *if_stmt = new(mem_ctx) ir_if(ir->condition);
+
+ list.move_nodes_to(&if_stmt->then_instructions);
+ ir->insert_before(if_stmt);
+ } else {
+ ir->insert_before(&list);
+ }
+
ir->remove();
this->progress = true;
diff --git a/mesalib/src/glsl/main.cpp b/mesalib/src/glsl/main.cpp
index 7952bb1a3..9f85096e1 100644
--- a/mesalib/src/glsl/main.cpp
+++ b/mesalib/src/glsl/main.cpp
@@ -29,80 +29,26 @@
#include "ir_print_visitor.h"
#include "program.h"
#include "loop_analysis.h"
-
-extern "C" struct gl_shader *
-_mesa_new_shader(struct gl_context *ctx, GLuint name, GLenum type);
-
-extern "C" void
-_mesa_reference_shader(struct gl_context *ctx, struct gl_shader **ptr,
- struct gl_shader *sh);
-
-/* Copied from shader_api.c for the stand-alone compiler.
- */
-void
-_mesa_reference_shader(struct gl_context *ctx, struct gl_shader **ptr,
- struct gl_shader *sh)
-{
- *ptr = sh;
-}
-
-struct gl_shader *
-_mesa_new_shader(struct gl_context *ctx, GLuint name, GLenum type)
-{
- struct gl_shader *shader;
-
- (void) ctx;
-
- assert(type == GL_FRAGMENT_SHADER || type == GL_VERTEX_SHADER);
- shader = rzalloc(NULL, struct gl_shader);
- if (shader) {
- shader->Type = type;
- shader->Name = name;
- shader->RefCount = 1;
- }
- return shader;
-}
+#include "standalone_scaffolding.h"
static void
initialize_context(struct gl_context *ctx, gl_api api)
{
- memset(ctx, 0, sizeof(*ctx));
-
- ctx->API = api;
-
- ctx->Extensions.ARB_ES2_compatibility = GL_TRUE;
- ctx->Extensions.ARB_draw_buffers = GL_TRUE;
- ctx->Extensions.ARB_draw_instanced = GL_TRUE;
- ctx->Extensions.ARB_fragment_coord_conventions = GL_TRUE;
- ctx->Extensions.EXT_texture_array = GL_TRUE;
- ctx->Extensions.NV_texture_rectangle = GL_TRUE;
- ctx->Extensions.EXT_texture3D = GL_TRUE;
+ initialize_context_to_defaults(ctx, api);
/* GLSL 1.30 isn't fully supported, but we need to advertise 1.30 so that
* the built-in functions for 1.30 can be built.
*/
ctx->Const.GLSLVersion = 130;
- /* 1.10 minimums. */
- ctx->Const.MaxLights = 8;
ctx->Const.MaxClipPlanes = 8;
- ctx->Const.MaxTextureUnits = 2;
+ ctx->Const.MaxDrawBuffers = 2;
/* More than the 1.10 minimum to appease parser tests taken from
* apps that (hopefully) already checked the number of coords.
*/
ctx->Const.MaxTextureCoordUnits = 4;
- ctx->Const.VertexProgram.MaxAttribs = 16;
- ctx->Const.VertexProgram.MaxUniformComponents = 512;
- ctx->Const.MaxVarying = 8;
- ctx->Const.MaxVertexTextureImageUnits = 0;
- ctx->Const.MaxCombinedTextureImageUnits = 2;
- ctx->Const.MaxTextureImageUnits = 2;
- ctx->Const.FragmentProgram.MaxUniformComponents = 64;
-
- ctx->Const.MaxDrawBuffers = 2;
-
ctx->Driver.NewShader = _mesa_new_shader;
}
diff --git a/mesalib/src/glsl/standalone_scaffolding.cpp b/mesalib/src/glsl/standalone_scaffolding.cpp
new file mode 100644
index 000000000..696ea757e
--- /dev/null
+++ b/mesalib/src/glsl/standalone_scaffolding.cpp
@@ -0,0 +1,91 @@
+/*
+ * Copyright © 2011 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.
+ */
+
+/* This file declares stripped-down versions of functions that
+ * normally exist outside of the glsl folder, so that they can be used
+ * when running the GLSL compiler standalone (for unit testing or
+ * compiling builtins).
+ */
+
+#include "standalone_scaffolding.h"
+
+#include <assert.h>
+#include <string.h>
+#include "ralloc.h"
+
+void
+_mesa_reference_shader(struct gl_context *ctx, struct gl_shader **ptr,
+ struct gl_shader *sh)
+{
+ *ptr = sh;
+}
+
+struct gl_shader *
+_mesa_new_shader(struct gl_context *ctx, GLuint name, GLenum type)
+{
+ struct gl_shader *shader;
+
+ (void) ctx;
+
+ assert(type == GL_FRAGMENT_SHADER || type == GL_VERTEX_SHADER);
+ shader = rzalloc(NULL, struct gl_shader);
+ if (shader) {
+ shader->Type = type;
+ shader->Name = name;
+ shader->RefCount = 1;
+ }
+ return shader;
+}
+
+void initialize_context_to_defaults(struct gl_context *ctx, gl_api api)
+{
+ memset(ctx, 0, sizeof(*ctx));
+
+ ctx->API = api;
+
+ ctx->Extensions.ARB_ES2_compatibility = true;
+ ctx->Extensions.ARB_draw_buffers = true;
+ ctx->Extensions.ARB_draw_instanced = true;
+ ctx->Extensions.ARB_fragment_coord_conventions = true;
+ ctx->Extensions.EXT_texture_array = true;
+ ctx->Extensions.NV_texture_rectangle = true;
+ ctx->Extensions.EXT_texture3D = true;
+
+ ctx->Const.GLSLVersion = 120;
+
+ /* 1.20 minimums. */
+ ctx->Const.MaxLights = 8;
+ ctx->Const.MaxClipPlanes = 6;
+ ctx->Const.MaxTextureUnits = 2;
+ ctx->Const.MaxTextureCoordUnits = 2;
+ ctx->Const.VertexProgram.MaxAttribs = 16;
+
+ ctx->Const.VertexProgram.MaxUniformComponents = 512;
+ ctx->Const.MaxVarying = 8; /* == gl_MaxVaryingFloats / 4 */
+ ctx->Const.MaxVertexTextureImageUnits = 0;
+ ctx->Const.MaxCombinedTextureImageUnits = 2;
+ ctx->Const.MaxTextureImageUnits = 2;
+ ctx->Const.FragmentProgram.MaxUniformComponents = 64;
+
+ ctx->Const.MaxDrawBuffers = 1;
+}
diff --git a/mesalib/src/glsl/standalone_scaffolding.h b/mesalib/src/glsl/standalone_scaffolding.h
new file mode 100644
index 000000000..877332006
--- /dev/null
+++ b/mesalib/src/glsl/standalone_scaffolding.h
@@ -0,0 +1,54 @@
+/*
+ * Copyright © 2011 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.
+ */
+
+/* This file declares stripped-down versions of functions that
+ * normally exist outside of the glsl folder, so that they can be used
+ * when running the GLSL compiler standalone (for unit testing or
+ * compiling builtins).
+ */
+
+#pragma once
+#ifndef STANDALONE_SCAFFOLDING_H
+#define STANDALONE_SCAFFOLDING_H
+
+#include "main/mtypes.h"
+
+extern "C" void
+_mesa_reference_shader(struct gl_context *ctx, struct gl_shader **ptr,
+ struct gl_shader *sh);
+
+extern "C" struct gl_shader *
+_mesa_new_shader(struct gl_context *ctx, GLuint name, GLenum type);
+
+/**
+ * Initialize the given gl_context structure to a reasonable set of
+ * defaults representing the minimum capabilities required by the
+ * OpenGL spec.
+ *
+ * This is used when compiling builtin functions and in testing, when
+ * we don't have a connection to an actual driver.
+ */
+void initialize_context_to_defaults(struct gl_context *ctx, gl_api api);
+
+
+#endif /* STANDALONE_SCAFFOLDING_H */
diff --git a/mesalib/src/glsl/test.cpp b/mesalib/src/glsl/test.cpp
new file mode 100644
index 000000000..b1ff92ed1
--- /dev/null
+++ b/mesalib/src/glsl/test.cpp
@@ -0,0 +1,78 @@
+/*
+ * Copyright © 2011 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.
+ */
+
+/**
+ * \file test.cpp
+ *
+ * Standalone tests for the GLSL compiler.
+ *
+ * This file provides a standalone executable which can be used to
+ * test components of the GLSL.
+ *
+ * Each test is a function with the same signature as main(). The
+ * main function interprets its first argument as the name of the test
+ * to run, strips out that argument, and then calls the test function.
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "test_optpass.h"
+
+/**
+ * Print proper usage and exit with failure.
+ */
+static void
+usage_fail(const char *name)
+{
+ printf("*** usage: %s <command> <options>\n", name);
+ printf("\n");
+ printf("Possible commands are:\n");
+ printf(" optpass: test an optimization pass in isolation\n");
+ exit(EXIT_FAILURE);
+}
+
+static const char *extract_command_from_argv(int *argc, char **argv)
+{
+ if (*argc < 2) {
+ usage_fail(argv[0]);
+ }
+ const char *command = argv[1];
+ --*argc;
+ memmove(&argv[1], &argv[2], (*argc) * sizeof(argv[1]));
+ return command;
+}
+
+int main(int argc, char **argv)
+{
+ const char *command = extract_command_from_argv(&argc, argv);
+ if (strcmp(command, "optpass") == 0) {
+ return test_optpass(argc, argv);
+ } else {
+ usage_fail(argv[0]);
+ }
+
+ /* Execution should never reach here. */
+ return EXIT_FAILURE;
+}
diff --git a/mesalib/src/glsl/test_optpass.cpp b/mesalib/src/glsl/test_optpass.cpp
new file mode 100644
index 000000000..89b7f8338
--- /dev/null
+++ b/mesalib/src/glsl/test_optpass.cpp
@@ -0,0 +1,273 @@
+/*
+ * Copyright © 2011 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.
+ */
+
+/**
+ * \file test_optpass.cpp
+ *
+ * Standalone test for optimization passes.
+ *
+ * This file provides the "optpass" command for the standalone
+ * glsl_test app. It accepts either GLSL or high-level IR as input,
+ * and performs the optimiation passes specified on the command line.
+ * It outputs the IR, both before and after optimiations.
+ */
+
+#include <string>
+#include <iostream>
+#include <sstream>
+#include <getopt.h>
+
+#include "ast.h"
+#include "ir_optimization.h"
+#include "ir_print_visitor.h"
+#include "program.h"
+#include "ir_reader.h"
+#include "standalone_scaffolding.h"
+
+using namespace std;
+
+static string read_stdin_to_eof()
+{
+ stringbuf sb;
+ cin.get(sb, '\0');
+ return sb.str();
+}
+
+static GLboolean
+do_optimization(struct exec_list *ir, const char *optimization)
+{
+ int int_0;
+ int int_1;
+ int int_2;
+ int int_3;
+ int int_4;
+
+ if (sscanf(optimization, "do_common_optimization ( %d , %d ) ",
+ &int_0, &int_1) == 2) {
+ return do_common_optimization(ir, int_0 != 0, int_1);
+ } else if (strcmp(optimization, "do_algebraic") == 0) {
+ return do_algebraic(ir);
+ } else if (strcmp(optimization, "do_constant_folding") == 0) {
+ return do_constant_folding(ir);
+ } else if (strcmp(optimization, "do_constant_variable") == 0) {
+ return do_constant_variable(ir);
+ } else if (strcmp(optimization, "do_constant_variable_unlinked") == 0) {
+ return do_constant_variable_unlinked(ir);
+ } else if (strcmp(optimization, "do_copy_propagation") == 0) {
+ return do_copy_propagation(ir);
+ } else if (strcmp(optimization, "do_copy_propagation_elements") == 0) {
+ return do_copy_propagation_elements(ir);
+ } else if (strcmp(optimization, "do_constant_propagation") == 0) {
+ return do_constant_propagation(ir);
+ } else if (strcmp(optimization, "do_dead_code") == 0) {
+ return do_dead_code(ir);
+ } else if (strcmp(optimization, "do_dead_code_local") == 0) {
+ return do_dead_code_local(ir);
+ } else if (strcmp(optimization, "do_dead_code_unlinked") == 0) {
+ return do_dead_code_unlinked(ir);
+ } else if (strcmp(optimization, "do_dead_functions") == 0) {
+ return do_dead_functions(ir);
+ } else if (strcmp(optimization, "do_function_inlining") == 0) {
+ return do_function_inlining(ir);
+ } else if (sscanf(optimization,
+ "do_lower_jumps ( %d , %d , %d , %d , %d ) ",
+ &int_0, &int_1, &int_2, &int_3, &int_4) == 5) {
+ return do_lower_jumps(ir, int_0 != 0, int_1 != 0, int_2 != 0,
+ int_3 != 0, int_4 != 0);
+ } else if (strcmp(optimization, "do_lower_texture_projection") == 0) {
+ return do_lower_texture_projection(ir);
+ } else if (strcmp(optimization, "do_if_simplification") == 0) {
+ return do_if_simplification(ir);
+ } else if (strcmp(optimization, "do_discard_simplification") == 0) {
+ return do_discard_simplification(ir);
+ } else if (sscanf(optimization, "lower_if_to_cond_assign ( %d ) ",
+ &int_0) == 1) {
+ return lower_if_to_cond_assign(ir, int_0);
+ } else if (strcmp(optimization, "do_mat_op_to_vec") == 0) {
+ return do_mat_op_to_vec(ir);
+ } else if (strcmp(optimization, "do_noop_swizzle") == 0) {
+ return do_noop_swizzle(ir);
+ } else if (strcmp(optimization, "do_structure_splitting") == 0) {
+ return do_structure_splitting(ir);
+ } else if (strcmp(optimization, "do_swizzle_swizzle") == 0) {
+ return do_swizzle_swizzle(ir);
+ } else if (strcmp(optimization, "do_tree_grafting") == 0) {
+ return do_tree_grafting(ir);
+ } else if (strcmp(optimization, "do_vec_index_to_cond_assign") == 0) {
+ return do_vec_index_to_cond_assign(ir);
+ } else if (strcmp(optimization, "do_vec_index_to_swizzle") == 0) {
+ return do_vec_index_to_swizzle(ir);
+ } else if (strcmp(optimization, "lower_discard") == 0) {
+ return lower_discard(ir);
+ } else if (sscanf(optimization, "lower_instructions ( %d ) ",
+ &int_0) == 1) {
+ return lower_instructions(ir, int_0);
+ } else if (strcmp(optimization, "lower_noise") == 0) {
+ return lower_noise(ir);
+ } else if (sscanf(optimization, "lower_variable_index_to_cond_assign "
+ "( %d , %d , %d , %d ) ", &int_0, &int_1, &int_2,
+ &int_3) == 4) {
+ return lower_variable_index_to_cond_assign(ir, int_0 != 0, int_1 != 0,
+ int_2 != 0, int_3 != 0);
+ } else if (sscanf(optimization, "lower_quadop_vector ( %d ) ",
+ &int_0) == 1) {
+ return lower_quadop_vector(ir, int_0 != 0);
+ } else if (strcmp(optimization, "optimize_redundant_jumps") == 0) {
+ return optimize_redundant_jumps(ir);
+ } else {
+ printf("Unrecognized optimization %s\n", optimization);
+ exit(EXIT_FAILURE);
+ return false;
+ }
+}
+
+static GLboolean
+do_optimization_passes(struct exec_list *ir, char **optimizations,
+ int num_optimizations, bool quiet)
+{
+ GLboolean overall_progress = false;
+
+ for (int i = 0; i < num_optimizations; ++i) {
+ const char *optimization = optimizations[i];
+ if (!quiet) {
+ printf("*** Running optimization %s...", optimization);
+ }
+ GLboolean progress = do_optimization(ir, optimization);
+ if (!quiet) {
+ printf("%s\n", progress ? "progress" : "no progress");
+ }
+ validate_ir_tree(ir);
+
+ overall_progress = overall_progress || progress;
+ }
+
+ return overall_progress;
+}
+
+int test_optpass(int argc, char **argv)
+{
+ int input_format_ir = 0; /* 0=glsl, 1=ir */
+ int loop = 0;
+ int shader_type = GL_VERTEX_SHADER;
+ int quiet = 0;
+
+ const struct option optpass_opts[] = {
+ { "input-ir", no_argument, &input_format_ir, 1 },
+ { "input-glsl", no_argument, &input_format_ir, 0 },
+ { "loop", no_argument, &loop, 1 },
+ { "vertex-shader", no_argument, &shader_type, GL_VERTEX_SHADER },
+ { "fragment-shader", no_argument, &shader_type, GL_FRAGMENT_SHADER },
+ { "quiet", no_argument, &quiet, 1 },
+ { NULL, 0, NULL, 0 }
+ };
+
+ int idx = 0;
+ int c;
+ while ((c = getopt_long(argc, argv, "", optpass_opts, &idx)) != -1) {
+ if (c != 0) {
+ printf("*** usage: %s optpass <optimizations> <options>\n", argv[0]);
+ printf("\n");
+ printf("Possible options are:\n");
+ printf(" --input-ir: input format is IR\n");
+ printf(" --input-glsl: input format is GLSL (the default)\n");
+ printf(" --loop: run optimizations repeatedly until no progress\n");
+ printf(" --vertex-shader: test with a vertex shader (the default)\n");
+ printf(" --fragment-shader: test with a fragment shader\n");
+ exit(EXIT_FAILURE);
+ }
+ }
+
+ struct gl_context local_ctx;
+ struct gl_context *ctx = &local_ctx;
+ initialize_context_to_defaults(ctx, API_OPENGL);
+
+ ctx->Driver.NewShader = _mesa_new_shader;
+
+ struct gl_shader *shader = rzalloc(NULL, struct gl_shader);
+ shader->Type = shader_type;
+
+ string input = read_stdin_to_eof();
+
+ struct _mesa_glsl_parse_state *state
+ = new(shader) _mesa_glsl_parse_state(ctx, shader->Type, shader);
+
+ if (input_format_ir) {
+ shader->ir = new(shader) exec_list;
+ _mesa_glsl_initialize_types(state);
+ _mesa_glsl_read_ir(state, shader->ir, input.c_str(), true);
+ } else {
+ shader->Source = input.c_str();
+ const char *source = shader->Source;
+ state->error = preprocess(state, &source, &state->info_log,
+ state->extensions, ctx->API) != 0;
+
+ if (!state->error) {
+ _mesa_glsl_lexer_ctor(state, source);
+ _mesa_glsl_parse(state);
+ _mesa_glsl_lexer_dtor(state);
+ }
+
+ shader->ir = new(shader) exec_list;
+ if (!state->error && !state->translation_unit.is_empty())
+ _mesa_ast_to_hir(shader->ir, state);
+ }
+
+ /* Print out the initial IR */
+ if (!state->error && !quiet) {
+ printf("*** pre-optimization IR:\n");
+ _mesa_print_ir(shader->ir, state);
+ printf("\n--\n");
+ }
+
+ /* Optimization passes */
+ if (!state->error) {
+ GLboolean progress;
+ do {
+ progress = do_optimization_passes(shader->ir, &argv[optind],
+ argc - optind, quiet != 0);
+ } while (loop && progress);
+ }
+
+ /* Print out the resulting IR */
+ if (!state->error) {
+ if (!quiet) {
+ printf("*** resulting IR:\n");
+ }
+ _mesa_print_ir(shader->ir, state);
+ if (!quiet) {
+ printf("\n--\n");
+ }
+ }
+
+ if (state->error) {
+ printf("*** error(s) occurred:\n");
+ printf("%s\n", state->info_log);
+ printf("--\n");
+ }
+
+ ralloc_free(state);
+ ralloc_free(shader);
+
+ return state->error;
+}
+
diff --git a/mesalib/src/glsl/test_optpass.h b/mesalib/src/glsl/test_optpass.h
new file mode 100644
index 000000000..923ccf3de
--- /dev/null
+++ b/mesalib/src/glsl/test_optpass.h
@@ -0,0 +1,30 @@
+/*
+ * Copyright © 2011 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.
+ */
+
+#pragma once
+#ifndef TEST_OPTPASS_H
+#define TEST_OPTPASS_H
+
+int test_optpass(int argc, char **argv);
+
+#endif /* TEST_OPTPASS_H */
diff --git a/mesalib/src/mesa/drivers/common/meta.c b/mesalib/src/mesa/drivers/common/meta.c
index fa78674e4..26c895196 100644
--- a/mesalib/src/mesa/drivers/common/meta.c
+++ b/mesalib/src/mesa/drivers/common/meta.c
@@ -90,13 +90,14 @@
#define META_SCISSOR 0x100
#define META_SHADER 0x200
#define META_STENCIL_TEST 0x400
-#define META_TRANSFORM 0x800 /**< modelview, projection, clip planes */
+#define META_TRANSFORM 0x800 /**< modelview/projection matrix state */
#define META_TEXTURE 0x1000
#define META_VERTEX 0x2000
#define META_VIEWPORT 0x4000
#define META_CLAMP_FRAGMENT_COLOR 0x8000
#define META_CLAMP_VERTEX_COLOR 0x10000
#define META_CONDITIONAL_RENDER 0x20000
+#define META_CLIP 0x40000
/*@}*/
@@ -165,6 +166,8 @@ struct save_state
GLfloat ModelviewMatrix[16];
GLfloat ProjectionMatrix[16];
GLfloat TextureMatrix[16];
+
+ /** META_CLIP */
GLbitfield ClipPlanesEnabled;
/** META_TEXTURE */
@@ -547,6 +550,9 @@ _mesa_meta_begin(struct gl_context *ctx, GLbitfield state)
_mesa_Ortho(0.0, ctx->DrawBuffer->Width,
0.0, ctx->DrawBuffer->Height,
-1.0, 1.0);
+ }
+
+ if (state & META_CLIP) {
save->ClipPlanesEnabled = ctx->Transform.ClipPlanesEnabled;
if (ctx->Transform.ClipPlanesEnabled) {
GLuint i;
@@ -846,7 +852,9 @@ _mesa_meta_end(struct gl_context *ctx)
_mesa_LoadMatrixf(save->ProjectionMatrix);
_mesa_MatrixMode(save->MatrixMode);
+ }
+ if (state & META_CLIP) {
if (save->ClipPlanesEnabled) {
GLuint i;
for (i = 0; i < ctx->Const.MaxClipPlanes; i++) {
@@ -1669,6 +1677,7 @@ _mesa_meta_glsl_Clear(struct gl_context *ctx, GLbitfield buffers)
META_STENCIL_TEST |
META_VERTEX |
META_VIEWPORT |
+ META_CLIP |
META_CLAMP_FRAGMENT_COLOR);
if (!(buffers & BUFFER_BITS_COLOR)) {
@@ -1783,6 +1792,7 @@ _mesa_meta_CopyPixels(struct gl_context *ctx, GLint srcX, GLint srcY,
META_SHADER |
META_TEXTURE |
META_TRANSFORM |
+ META_CLIP |
META_VERTEX |
META_VIEWPORT));
@@ -2104,6 +2114,7 @@ _mesa_meta_DrawPixels(struct gl_context *ctx,
META_SHADER |
META_TEXTURE |
META_TRANSFORM |
+ META_CLIP |
META_VERTEX |
META_VIEWPORT |
META_CLAMP_FRAGMENT_COLOR |
@@ -2313,6 +2324,7 @@ _mesa_meta_Bitmap(struct gl_context *ctx,
META_SHADER |
META_TEXTURE |
META_TRANSFORM |
+ META_CLIP |
META_VERTEX |
META_VIEWPORT));
diff --git a/mesalib/src/mesa/main/compiler.h b/mesalib/src/mesa/main/compiler.h
index 743841be4..d736fdfc5 100644
--- a/mesalib/src/mesa/main/compiler.h
+++ b/mesalib/src/mesa/main/compiler.h
@@ -139,26 +139,28 @@ extern "C" {
/**
* Function inlining
*/
-#if defined(__GNUC__)
-# define INLINE __inline__
-#elif defined(__MSC__)
-# define INLINE __inline
-#elif defined(_MSC_VER)
-# define INLINE __inline
-#elif defined(__ICL)
-# define INLINE __inline
-#elif defined(__INTEL_COMPILER)
-# define INLINE inline
-#elif defined(__WATCOMC__) && (__WATCOMC__ >= 1100)
-# define INLINE __inline
-#elif defined(__SUNPRO_C) && defined(__C99FEATURES__)
-# define INLINE inline
-# define __inline inline
-# define __inline__ inline
-#elif (__STDC_VERSION__ >= 199901L) /* C99 */
-# define INLINE inline
-#else
-# define INLINE
+#ifndef INLINE
+# if defined(__GNUC__)
+# define INLINE __inline__
+# elif defined(__MSC__)
+# define INLINE __inline
+# elif defined(_MSC_VER)
+# define INLINE __inline
+# elif defined(__ICL)
+# define INLINE __inline
+# elif defined(__INTEL_COMPILER)
+# define INLINE inline
+# elif defined(__WATCOMC__) && (__WATCOMC__ >= 1100)
+# define INLINE __inline
+# elif defined(__SUNPRO_C) && defined(__C99FEATURES__)
+# define INLINE inline
+# define __inline inline
+# define __inline__ inline
+# elif (__STDC_VERSION__ >= 199901L) /* C99 */
+# define INLINE inline
+# else
+# define INLINE
+# endif
#endif
diff --git a/mesalib/src/mesa/main/get.c b/mesalib/src/mesa/main/get.c
index 0492e1585..d32c68a53 100644
--- a/mesalib/src/mesa/main/get.c
+++ b/mesalib/src/mesa/main/get.c
@@ -1569,11 +1569,11 @@ find_custom_value(struct gl_context *ctx, const struct value_desc *d, union valu
break;
case GL_NUM_COMPRESSED_TEXTURE_FORMATS_ARB:
- v->value_int = _mesa_get_compressed_formats(ctx, NULL, GL_FALSE);
+ v->value_int = _mesa_get_compressed_formats(ctx, NULL);
break;
case GL_COMPRESSED_TEXTURE_FORMATS_ARB:
v->value_int_n.n =
- _mesa_get_compressed_formats(ctx, v->value_int_n.ints, GL_FALSE);
+ _mesa_get_compressed_formats(ctx, v->value_int_n.ints);
ASSERT(v->value_int_n.n <= 100);
break;
diff --git a/mesalib/src/mesa/main/texcompress.c b/mesalib/src/mesa/main/texcompress.c
index d820ae927..42bd1eee5 100644
--- a/mesalib/src/mesa/main/texcompress.c
+++ b/mesalib/src/mesa/main/texcompress.c
@@ -40,19 +40,192 @@
/**
+ * Get the GL base format of a specified GL compressed texture format
+ *
+ * From page 232 of the OpenGL 3.3 (Compatiblity Profile) spec:
+ *
+ * "Compressed Internal Format Base Internal Format Type
+ * --------------------------- -------------------- ---------
+ * COMPRESSED_ALPHA ALPHA Generic
+ * COMPRESSED_LUMINANCE LUMINANCE Generic
+ * COMPRESSED_LUMINANCE_ALPHA LUMINANCE_ALPHA Generic
+ * COMPRESSED_INTENSITY INTENSITY Generic
+ * COMPRESSED_RED RED Generic
+ * COMPRESSED_RG RG Generic
+ * COMPRESSED_RGB RGB Generic
+ * COMPRESSED_RGBA RGBA Generic
+ * COMPRESSED_SRGB RGB Generic
+ * COMPRESSED_SRGB_ALPHA RGBA Generic
+ * COMPRESSED_SLUMINANCE LUMINANCE Generic
+ * COMPRESSED_SLUMINANCE_ALPHA LUMINANCE_ALPHA Generic
+ * COMPRESSED_RED_RGTC1 RED Specific
+ * COMPRESSED_SIGNED_RED_RGTC1 RED Specific
+ * COMPRESSED_RG_RGTC2 RG Specific
+ * COMPRESSED_SIGNED_RG_RGTC2 RG Specific"
+ *
+ * \return
+ * The base format of \c format if \c format is a compressed format (either
+ * generic or specific. Otherwise 0 is returned.
+ */
+GLenum
+_mesa_gl_compressed_format_base_format(GLenum format)
+{
+ switch (format) {
+ case GL_COMPRESSED_RED:
+ case GL_COMPRESSED_RED_RGTC1:
+ case GL_COMPRESSED_SIGNED_RED_RGTC1:
+ return GL_RED;
+
+ case GL_COMPRESSED_RG:
+ case GL_COMPRESSED_RG_RGTC2:
+ case GL_COMPRESSED_SIGNED_RG_RGTC2:
+ return GL_RG;
+
+ case GL_COMPRESSED_RGB:
+ case GL_COMPRESSED_SRGB:
+ case GL_COMPRESSED_RGB_S3TC_DXT1_EXT:
+ case GL_COMPRESSED_RGB_FXT1_3DFX:
+ case GL_COMPRESSED_SRGB_S3TC_DXT1_EXT:
+ return GL_RGB;
+
+ case GL_COMPRESSED_RGBA:
+ case GL_COMPRESSED_SRGB_ALPHA:
+ case GL_COMPRESSED_RGBA_BPTC_UNORM_ARB:
+ case GL_COMPRESSED_SRGB_ALPHA_BPTC_UNORM_ARB:
+ case GL_COMPRESSED_RGB_BPTC_SIGNED_FLOAT_ARB:
+ case GL_COMPRESSED_RGB_BPTC_UNSIGNED_FLOAT_ARB:
+ case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT:
+ case GL_COMPRESSED_RGBA_S3TC_DXT3_EXT:
+ case GL_COMPRESSED_RGBA_S3TC_DXT5_EXT:
+ case GL_COMPRESSED_RGBA_FXT1_3DFX:
+ case GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT1_EXT:
+ case GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT3_EXT:
+ case GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT5_EXT:
+ return GL_RGBA;
+
+ case GL_COMPRESSED_ALPHA:
+ return GL_ALPHA;
+
+ case GL_COMPRESSED_LUMINANCE:
+ case GL_COMPRESSED_SLUMINANCE:
+ case GL_COMPRESSED_LUMINANCE_LATC1_EXT:
+ case GL_COMPRESSED_SIGNED_LUMINANCE_LATC1_EXT:
+ return GL_LUMINANCE;
+
+ case GL_COMPRESSED_LUMINANCE_ALPHA:
+ case GL_COMPRESSED_SLUMINANCE_ALPHA:
+ case GL_COMPRESSED_LUMINANCE_ALPHA_LATC2_EXT:
+ case GL_COMPRESSED_SIGNED_LUMINANCE_ALPHA_LATC2_EXT:
+ case GL_COMPRESSED_LUMINANCE_ALPHA_3DC_ATI:
+ return GL_LUMINANCE_ALPHA;
+
+ case GL_COMPRESSED_INTENSITY:
+ return GL_INTENSITY;
+
+ default:
+ return 0;
+ }
+}
+
+/**
* Return list of (and count of) all specific texture compression
* formats that are supported.
*
+ * Some formats are \b not returned by this function. The
+ * \c GL_COMPRESSED_TEXTURE_FORMATS query only returns formats that are
+ * "suitable for general-purpose usage." All texture compression extensions
+ * have taken this to mean either linear RGB or linear RGBA.
+ *
+ * The GL_ARB_texture_compress_rgtc spec says:
+ *
+ * "19) Should the GL_NUM_COMPRESSED_TEXTURE_FORMATS and
+ * GL_COMPRESSED_TEXTURE_FORMATS queries return the RGTC formats?
+ *
+ * RESOLVED: No.
+ *
+ * The OpenGL 2.1 specification says "The only values returned
+ * by this query [GL_COMPRESSED_TEXTURE_FORMATS"] are those
+ * corresponding to formats suitable for general-purpose usage.
+ * The renderer will not enumerate formats with restrictions that
+ * need to be specifically understood prior to use."
+ *
+ * Compressed textures with just red or red-green components are
+ * not general-purpose so should not be returned by these queries
+ * because they have restrictions.
+ *
+ * Applications that seek to use the RGTC formats should do so
+ * by looking for this extension's name in the string returned by
+ * glGetString(GL_EXTENSIONS) rather than
+ * what GL_NUM_COMPRESSED_TEXTURE_FORMATS and
+ * GL_COMPRESSED_TEXTURE_FORMATS return."
+ *
+ * There is nearly identical wording in the GL_EXT_texture_compression_rgtc
+ * spec.
+ *
+ * The GL_EXT_texture_rRGB spec says:
+ *
+ * "22) Should the new COMPRESSED_SRGB_* formats be listed in an
+ * implementation's GL_COMPRESSED_TEXTURE_FORMATS list?
+ *
+ * RESOLVED: No. Section 3.8.1 says formats listed by
+ * GL_COMPRESSED_TEXTURE_FORMATS are "suitable for general-purpose
+ * usage." The non-linear distribution of red, green, and
+ * blue for these sRGB compressed formats makes them not really
+ * general-purpose."
+ *
+ * The GL_EXT_texture_compression_latc spec says:
+ *
+ * "16) Should the GL_NUM_COMPRESSED_TEXTURE_FORMATS and
+ * GL_COMPRESSED_TEXTURE_FORMATS queries return the LATC formats?
+ *
+ * RESOLVED: No.
+ *
+ * The OpenGL 2.1 specification says "The only values returned
+ * by this query [GL_COMPRESSED_TEXTURE_FORMATS"] are those
+ * corresponding to formats suitable for general-purpose usage.
+ * The renderer will not enumerate formats with restrictions that
+ * need to be specifically understood prior to use."
+ *
+ * Historically, OpenGL implementation have advertised the RGB and
+ * RGBA versions of the S3TC extensions compressed format tokens
+ * through this mechanism.
+ *
+ * The specification is not sufficiently clear about what "suitable
+ * for general-purpose usage" means. Historically that seems to mean
+ * unsigned RGB or unsigned RGBA. The DXT1 format supporting alpha
+ * (GL_COMPRESSED_RGBA_S3TC_DXT1_EXT) is not exposed in the list (at
+ * least for NVIDIA drivers) because the alpha is always 1.0 expect
+ * when it is 0.0 when RGB is required to be black. NVIDIA's even
+ * limits itself to true linear RGB or RGBA formats, specifically
+ * not including EXT_texture_sRGB's sRGB S3TC compressed formats.
+ *
+ * Adding luminance and luminance-alpha texture formats (and
+ * certainly signed versions of luminance and luminance-alpha
+ * formats!) invites potential comptaibility problems with old
+ * applications using this mechanism since old applications are
+ * unlikely to expect non-RGB or non-RGBA formats to be advertised
+ * through this mechanism. However no specific misinteractions
+ * with old applications is known.
+ *
+ * Applications that seek to use the LATC formats should do so
+ * by looking for this extension's name in the string returned by
+ * glGetString(GL_EXTENSIONS) rather than
+ * what GL_NUM_COMPRESSED_TEXTURE_FORMATS and
+ * GL_COMPRESSED_TEXTURE_FORMATS return."
+ *
+ * There is no formal spec for GL_ATI_texture_compression_3dc. Since the
+ * formats added by this extension are luminance-alpha formats, it is
+ * reasonable to expect them to follow the same rules as
+ * GL_EXT_texture_compression_latc. At the very least, Catalyst 11.6 does not
+ * expose the 3dc formats through this mechanism.
+ *
* \param ctx the GL context
* \param formats the resulting format list (may be NULL).
- * \param all if true return all formats, even those with some kind
- * of restrictions/limitations (See GL_ARB_texture_compression
- * spec for more info).
*
* \return number of formats.
*/
GLuint
-_mesa_get_compressed_formats(struct gl_context *ctx, GLint *formats, GLboolean all)
+_mesa_get_compressed_formats(struct gl_context *ctx, GLint *formats)
{
GLuint n = 0;
if (ctx->Extensions.TDFX_texture_compression_FXT1) {
@@ -64,24 +237,15 @@ _mesa_get_compressed_formats(struct gl_context *ctx, GLint *formats, GLboolean a
n += 2;
}
}
- /* don't return RGTC - ARB_texture_compression_rgtc query 19 */
+
if (ctx->Extensions.EXT_texture_compression_s3tc) {
if (formats) {
formats[n++] = GL_COMPRESSED_RGB_S3TC_DXT1_EXT;
- /* This format has some restrictions/limitations and so should
- * not be returned via the GL_COMPRESSED_TEXTURE_FORMATS query.
- * Specifically, all transparent pixels become black. NVIDIA
- * omits this format too.
- */
- if (all)
- formats[n++] = GL_COMPRESSED_RGBA_S3TC_DXT1_EXT;
formats[n++] = GL_COMPRESSED_RGBA_S3TC_DXT3_EXT;
formats[n++] = GL_COMPRESSED_RGBA_S3TC_DXT5_EXT;
}
else {
n += 3;
- if (all)
- n += 1;
}
}
if (ctx->Extensions.S3_s3tc) {
@@ -95,19 +259,6 @@ _mesa_get_compressed_formats(struct gl_context *ctx, GLint *formats, GLboolean a
n += 4;
}
}
-#if FEATURE_EXT_texture_sRGB
- if (ctx->Extensions.EXT_texture_sRGB) {
- if (formats) {
- formats[n++] = GL_COMPRESSED_SRGB_S3TC_DXT1_EXT;
- formats[n++] = GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT1_EXT;
- formats[n++] = GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT3_EXT;
- formats[n++] = GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT5_EXT;
- }
- else {
- n += 4;
- }
- }
-#endif /* FEATURE_EXT_texture_sRGB */
return n;
#if FEATURE_ES1 || FEATURE_ES2
diff --git a/mesalib/src/mesa/main/texcompress.h b/mesalib/src/mesa/main/texcompress.h
index fd42f6402..375cf90c8 100644
--- a/mesalib/src/mesa/main/texcompress.h
+++ b/mesalib/src/mesa/main/texcompress.h
@@ -1,59 +1,62 @@
-/*
- * Mesa 3-D graphics library
- * Version: 6.5.1
- *
- * Copyright (C) 1999-2006 Brian Paul 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
- * BRIAN PAUL 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 TEXCOMPRESS_H
-#define TEXCOMPRESS_H
-
-#include "formats.h"
-#include "glheader.h"
-#include "mfeatures.h"
-
-struct gl_context;
-
-#if _HAVE_FULL_GL
-
-extern GLuint
-_mesa_get_compressed_formats(struct gl_context *ctx, GLint *formats, GLboolean all);
-
-extern gl_format
-_mesa_glenum_to_compressed_format(GLenum format);
-
-extern GLenum
-_mesa_compressed_format_to_glenum(struct gl_context *ctx, GLuint mesaFormat);
-
-extern GLubyte *
-_mesa_compressed_image_address(GLint col, GLint row, GLint img,
- gl_format mesaFormat,
- GLsizei width, const GLubyte *image);
-
-#else /* _HAVE_FULL_GL */
-
-/* no-op macros */
-#define _mesa_get_compressed_formats( c, f ) 0
-#define _mesa_compressed_image_address(c, r, i, f, w, i2 ) 0
-#define _mesa_compress_teximage( c, w, h, sF, s, sRS, dF, d, drs ) ((void)0)
-
-#endif /* _HAVE_FULL_GL */
-
-#endif /* TEXCOMPRESS_H */
+/*
+ * Mesa 3-D graphics library
+ * Version: 6.5.1
+ *
+ * Copyright (C) 1999-2006 Brian Paul 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
+ * BRIAN PAUL 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 TEXCOMPRESS_H
+#define TEXCOMPRESS_H
+
+#include "formats.h"
+#include "glheader.h"
+#include "mfeatures.h"
+
+struct gl_context;
+
+#if _HAVE_FULL_GL
+
+extern GLenum
+_mesa_gl_compressed_format_base_format(GLenum format);
+
+extern GLuint
+_mesa_get_compressed_formats(struct gl_context *ctx, GLint *formats);
+
+extern gl_format
+_mesa_glenum_to_compressed_format(GLenum format);
+
+extern GLenum
+_mesa_compressed_format_to_glenum(struct gl_context *ctx, GLuint mesaFormat);
+
+extern GLubyte *
+_mesa_compressed_image_address(GLint col, GLint row, GLint img,
+ gl_format mesaFormat,
+ GLsizei width, const GLubyte *image);
+
+#else /* _HAVE_FULL_GL */
+
+/* no-op macros */
+#define _mesa_get_compressed_formats( c, f ) 0
+#define _mesa_compressed_image_address(c, r, i, f, w, i2 ) 0
+#define _mesa_compress_teximage( c, w, h, sF, s, sRS, dF, d, drs ) ((void)0)
+
+#endif /* _HAVE_FULL_GL */
+
+#endif /* TEXCOMPRESS_H */
diff --git a/mesalib/src/mesa/main/texparam.c b/mesalib/src/mesa/main/texparam.c
index 4b9dcb5d3..c4ec29533 100644
--- a/mesalib/src/mesa/main/texparam.c
+++ b/mesalib/src/mesa/main/texparam.c
@@ -915,9 +915,23 @@ _mesa_GetTexLevelParameteriv( GLenum target, GLint level,
*params = _mesa_compressed_format_to_glenum(ctx, texFormat);
}
else {
- /* return the user's requested internal format */
- *params = img->InternalFormat;
- }
+ /* If the true internal format is not compressed but the user
+ * requested a generic compressed format, we have to return the
+ * generic base format that matches.
+ *
+ * From page 119 (page 129 of the PDF) of the OpenGL 1.3 spec:
+ *
+ * "If no specific compressed format is available,
+ * internalformat is instead replaced by the corresponding base
+ * internal format."
+ *
+ * Otherwise just return the user's requested internal format
+ */
+ const GLenum f =
+ _mesa_gl_compressed_format_base_format(img->InternalFormat);
+
+ *params = (f != 0) ? f : img->InternalFormat;
+ }
break;
case GL_TEXTURE_BORDER:
*params = img->Border;
diff --git a/mesalib/src/mesa/program/ir_to_mesa.cpp b/mesalib/src/mesa/program/ir_to_mesa.cpp
index 738e97ca5..8b4a535b7 100644
--- a/mesalib/src/mesa/program/ir_to_mesa.cpp
+++ b/mesalib/src/mesa/program/ir_to_mesa.cpp
@@ -134,7 +134,7 @@ src_reg::src_reg(dst_reg reg)
this->index = reg.index;
this->swizzle = SWIZZLE_XYZW;
this->negate = 0;
- this->reladdr = NULL;
+ this->reladdr = reg.reladdr;
}
dst_reg::dst_reg(src_reg reg)
@@ -1415,9 +1415,9 @@ ir_to_mesa_visitor::visit(ir_dereference_variable *ir)
case ir_var_in:
case ir_var_inout:
/* The linker assigns locations for varyings and attributes,
- * including deprecated builtins (like gl_Color), user-assign
- * generic attributes (glBindVertexLocation), and
- * user-defined varyings.
+ * including deprecated builtins (like gl_Color),
+ * user-assigned generic attributes (glBindVertexLocation),
+ * and user-defined varyings.
*
* FINISHME: We would hit this path for function arguments. Fix!
*/
@@ -1496,6 +1496,18 @@ ir_to_mesa_visitor::visit(ir_dereference_array *ir)
this->result, src_reg_for_float(element_size));
}
+ /* If there was already a relative address register involved, add the
+ * new and the old together to get the new offset.
+ */
+ if (src.reladdr != NULL) {
+ src_reg accum_reg = get_temp(glsl_type::float_type);
+
+ emit(ir, OPCODE_ADD, dst_reg(accum_reg),
+ index_reg, *src.reladdr);
+
+ index_reg = accum_reg;
+ }
+
src.reladdr = ralloc(mem_ctx, src_reg);
memcpy(src.reladdr, &index_reg, sizeof(index_reg));
}
diff --git a/mesalib/src/mesa/program/prog_optimize.c b/mesalib/src/mesa/program/prog_optimize.c
index 8a40fa69e..f4a7a638d 100644
--- a/mesalib/src/mesa/program/prog_optimize.c
+++ b/mesalib/src/mesa/program/prog_optimize.c
@@ -1319,6 +1319,15 @@ _mesa_simplify_cmp(struct gl_program * program)
inst->Opcode = OPCODE_MOV;
inst->SrcReg[0] = inst->SrcReg[1];
+
+ /* Unused operands are expected to have the file set to
+ * PROGRAM_UNDEFINED. This is how _mesa_init_instructions initializes
+ * all of the sources.
+ */
+ inst->SrcReg[1].File = PROGRAM_UNDEFINED;
+ inst->SrcReg[1].Swizzle = SWIZZLE_NOOP;
+ inst->SrcReg[2].File = PROGRAM_UNDEFINED;
+ inst->SrcReg[2].Swizzle = SWIZZLE_NOOP;
}
}
if (dbg) {