diff options
Diffstat (limited to 'mesalib/src')
30 files changed, 787 insertions, 400 deletions
diff --git a/mesalib/src/gallium/auxiliary/util/u_blitter.c b/mesalib/src/gallium/auxiliary/util/u_blitter.c index 3e9cbffe9..6a9141209 100644 --- a/mesalib/src/gallium/auxiliary/util/u_blitter.c +++ b/mesalib/src/gallium/auxiliary/util/u_blitter.c @@ -276,7 +276,7 @@ struct blitter_context *util_blitter_create(struct pipe_context *pipe) for (i = 0; i < 4; i++) ctx->vertices[i][0][3] = 1; /*v.w*/ - ctx->upload = u_upload_create(pipe, 65536, 128, PIPE_BIND_VERTEX_BUFFER); + ctx->upload = u_upload_create(pipe, 65536, 4, PIPE_BIND_VERTEX_BUFFER); return &ctx->base; } diff --git a/mesalib/src/gallium/auxiliary/util/u_double_list.h b/mesalib/src/gallium/auxiliary/util/u_double_list.h index 29f0b9d09..9d1129b18 100644 --- a/mesalib/src/gallium/auxiliary/util/u_double_list.h +++ b/mesalib/src/gallium/auxiliary/util/u_double_list.h @@ -1,141 +1,146 @@ -/**************************************************************************
- *
- * Copyright 2006 Tungsten Graphics, Inc., Bismarck, ND. USA.
- * All Rights Reserved.
- *
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the
- * "Software"), to deal in the Software without restriction, including
- * 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 SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
- * THE COPYRIGHT HOLDERS, AUTHORS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM,
- * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
- * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
- * USE OR OTHER DEALINGS IN THE SOFTWARE.
- *
- * The above copyright notice and this permission notice (including the
- * next paragraph) shall be included in all copies or substantial portions
- * of the Software.
- *
- **************************************************************************/
-
-/**
- * \file
- * List macros heavily inspired by the Linux kernel
- * list handling. No list looping yet.
- *
- * Is not threadsafe, so common operations need to
- * be protected using an external mutex.
- */
-
-#ifndef _U_DOUBLE_LIST_H_
-#define _U_DOUBLE_LIST_H_
-
-
-#include <stddef.h>
-#include "pipe/p_compiler.h"
-
-
-struct list_head
-{
- struct list_head *prev;
- struct list_head *next;
-};
-
-static INLINE void list_inithead(struct list_head *item)
-{
- item->prev = item;
- item->next = item;
-}
-
-static INLINE void list_add(struct list_head *item, struct list_head *list)
-{
- item->prev = list;
- item->next = list->next;
- list->next->prev = item;
- list->next = item;
-}
-
-static INLINE void list_addtail(struct list_head *item, struct list_head *list)
-{
- item->next = list;
- item->prev = list->prev;
- list->prev->next = item;
- list->prev = item;
-}
-
-static INLINE void list_replace(struct list_head *from, struct list_head *to)
-{
- to->prev = from->prev;
- to->next = from->next;
- from->next->prev = to;
- from->prev->next = to;
-}
-
-static INLINE void list_del(struct list_head *item)
-{
- item->prev->next = item->next;
- item->next->prev = item->prev;
-}
-
-static INLINE void list_delinit(struct list_head *item)
-{
- item->prev->next = item->next;
- item->next->prev = item->prev;
- item->next = item;
- item->prev = item;
-}
-
-#define LIST_INITHEAD(__item) list_inithead(__item)
-#define LIST_ADD(__item, __list) list_add(__item, __list)
-#define LIST_ADDTAIL(__item, __list) list_addtail(__item, __list)
-#define LIST_REPLACE(__from, __to) list_replace(__from, __to)
-#define LIST_DEL(__item) list_del(__item)
-#define LIST_DELINIT(__item) list_delinit(__item)
-
-#define LIST_ENTRY(__type, __item, __field) \
- ((__type *)(((char *)(__item)) - offsetof(__type, __field)))
-
-#define LIST_IS_EMPTY(__list) \
- ((__list)->next == (__list))
-
-#ifndef container_of
-#define container_of(ptr, sample, member) \
- (void *)((char *)(ptr) \
- - ((char *)&(sample)->member - (char *)(sample)))
-#endif
-
-#define LIST_FOR_EACH_ENTRY(pos, head, member) \
- for (pos = container_of((head)->next, pos, member); \
- &pos->member != (head); \
- pos = container_of(pos->member.next, pos, member))
-
-#define LIST_FOR_EACH_ENTRY_SAFE(pos, storage, head, member) \
- for (pos = container_of((head)->next, pos, member), \
- storage = container_of(pos->member.next, pos, member); \
- &pos->member != (head); \
- pos = storage, storage = container_of(storage->member.next, storage, member))
-
-#define LIST_FOR_EACH_ENTRY_SAFE_REV(pos, storage, head, member) \
- for (pos = container_of((head)->prev, pos, member), \
- storage = container_of(pos->member.prev, pos, member); \
- &pos->member != (head); \
- pos = storage, storage = container_of(storage->member.prev, storage, member))
-
-#define LIST_FOR_EACH_ENTRY_FROM(pos, start, head, member) \
- for (pos = container_of((start), pos, member); \
- &pos->member != (head); \
- pos = container_of(pos->member.next, pos, member))
-
-#define LIST_FOR_EACH_ENTRY_FROM_REV(pos, start, head, member) \
- for (pos = container_of((start), pos, member); \
- &pos->member != (head); \
- pos = container_of(pos->member.prev, pos, member))
-
-#endif /*_U_DOUBLE_LIST_H_*/
+/************************************************************************** + * + * Copyright 2006 Tungsten Graphics, Inc., Bismarck, ND. USA. + * All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * 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 SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDERS, AUTHORS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR + * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE + * USE OR OTHER DEALINGS IN THE SOFTWARE. + * + * The above copyright notice and this permission notice (including the + * next paragraph) shall be included in all copies or substantial portions + * of the Software. + * + **************************************************************************/ + +/** + * \file + * List macros heavily inspired by the Linux kernel + * list handling. No list looping yet. + * + * Is not threadsafe, so common operations need to + * be protected using an external mutex. + */ + +#ifndef _U_DOUBLE_LIST_H_ +#define _U_DOUBLE_LIST_H_ + + +#include <stddef.h> +#include "pipe/p_compiler.h" + + +struct list_head +{ + struct list_head *prev; + struct list_head *next; +}; + +static INLINE void list_inithead(struct list_head *item) +{ + item->prev = item; + item->next = item; +} + +static INLINE void list_add(struct list_head *item, struct list_head *list) +{ + item->prev = list; + item->next = list->next; + list->next->prev = item; + list->next = item; +} + +static INLINE void list_addtail(struct list_head *item, struct list_head *list) +{ + item->next = list; + item->prev = list->prev; + list->prev->next = item; + list->prev = item; +} + +static INLINE void list_replace(struct list_head *from, struct list_head *to) +{ + to->prev = from->prev; + to->next = from->next; + from->next->prev = to; + from->prev->next = to; +} + +static INLINE void list_del(struct list_head *item) +{ + item->prev->next = item->next; + item->next->prev = item->prev; +} + +static INLINE void list_delinit(struct list_head *item) +{ + item->prev->next = item->next; + item->next->prev = item->prev; + item->next = item; + item->prev = item; +} + +#define LIST_INITHEAD(__item) list_inithead(__item) +#define LIST_ADD(__item, __list) list_add(__item, __list) +#define LIST_ADDTAIL(__item, __list) list_addtail(__item, __list) +#define LIST_REPLACE(__from, __to) list_replace(__from, __to) +#define LIST_DEL(__item) list_del(__item) +#define LIST_DELINIT(__item) list_delinit(__item) + +#define LIST_ENTRY(__type, __item, __field) \ + ((__type *)(((char *)(__item)) - offsetof(__type, __field))) + +#define LIST_IS_EMPTY(__list) \ + ((__list)->next == (__list)) + +/** + * Cast from a pointer to a member of a struct back to the containing struct. + * + * 'sample' MUST be initialized, or else the result is undefined! + */ +#ifndef container_of +#define container_of(ptr, sample, member) \ + (void *)((char *)(ptr) \ + - ((char *)&(sample)->member - (char *)(sample))) +#endif + +#define LIST_FOR_EACH_ENTRY(pos, head, member) \ + for (pos = NULL, pos = container_of((head)->next, pos, member); \ + &pos->member != (head); \ + pos = container_of(pos->member.next, pos, member)) + +#define LIST_FOR_EACH_ENTRY_SAFE(pos, storage, head, member) \ + for (pos = NULL, pos = container_of((head)->next, pos, member), \ + storage = container_of(pos->member.next, pos, member); \ + &pos->member != (head); \ + pos = storage, storage = container_of(storage->member.next, storage, member)) + +#define LIST_FOR_EACH_ENTRY_SAFE_REV(pos, storage, head, member) \ + for (pos = NULL, pos = container_of((head)->prev, pos, member), \ + storage = container_of(pos->member.prev, pos, member); \ + &pos->member != (head); \ + pos = storage, storage = container_of(storage->member.prev, storage, member)) + +#define LIST_FOR_EACH_ENTRY_FROM(pos, start, head, member) \ + for (pos = NULL, pos = container_of((start), pos, member); \ + &pos->member != (head); \ + pos = container_of(pos->member.next, pos, member)) + +#define LIST_FOR_EACH_ENTRY_FROM_REV(pos, start, head, member) \ + for (pos = NULL, pos = container_of((start), pos, member); \ + &pos->member != (head); \ + pos = container_of(pos->member.prev, pos, member)) + +#endif /*_U_DOUBLE_LIST_H_*/ diff --git a/mesalib/src/gallium/auxiliary/util/u_dual_blend.h b/mesalib/src/gallium/auxiliary/util/u_dual_blend.h new file mode 100644 index 000000000..e31d43c18 --- /dev/null +++ b/mesalib/src/gallium/auxiliary/util/u_dual_blend.h @@ -0,0 +1,26 @@ +#ifndef U_DUAL_BLEND_H +#define U_DUAL_BLEND_H + +#include "pipe/p_state.h" + +static INLINE boolean util_blend_factor_is_dual_src(int factor) +{ + return (factor == PIPE_BLENDFACTOR_SRC1_COLOR) || + (factor == PIPE_BLENDFACTOR_SRC1_ALPHA) || + (factor == PIPE_BLENDFACTOR_INV_SRC1_COLOR) || + (factor == PIPE_BLENDFACTOR_INV_SRC1_ALPHA); +} + +static INLINE boolean util_blend_state_is_dual(const struct pipe_blend_state *blend, + int index) +{ + if (util_blend_factor_is_dual_src(blend->rt[index].rgb_src_factor) || + util_blend_factor_is_dual_src(blend->rt[index].alpha_src_factor) || + util_blend_factor_is_dual_src(blend->rt[index].rgb_dst_factor) || + util_blend_factor_is_dual_src(blend->rt[index].alpha_dst_factor)) + return true; + return false; +} + + +#endif diff --git a/mesalib/src/gallium/auxiliary/util/u_linkage.h b/mesalib/src/gallium/auxiliary/util/u_linkage.h index 43ec917fc..7b23123d3 100644 --- a/mesalib/src/gallium/auxiliary/util/u_linkage.h +++ b/mesalib/src/gallium/auxiliary/util/u_linkage.h @@ -49,15 +49,16 @@ unsigned util_semantic_set_from_program_file(struct util_semantic_set *set, cons * * num_slots is the size of the layout array and hardware limit instead. * - * efficient_slots == 0 or efficient_solts == num_slots are typical settings. + * efficient_slots == 0 or efficient_slots == num_slots are typical settings. */ void util_semantic_layout_from_set(unsigned char *layout, const struct util_semantic_set *set, unsigned efficient_slots, unsigned num_slots); static INLINE void -util_semantic_table_from_layout(unsigned char *table, unsigned char *layout, unsigned char first_slot_value, unsigned char num_slots) +util_semantic_table_from_layout(unsigned char *table, size_t table_size, unsigned char *layout, + unsigned char first_slot_value, unsigned char num_slots) { - int i; - memset(table, 0xff, sizeof(table)); + unsigned char i; + memset(table, 0xff, table_size); for(i = 0; i < num_slots; ++i) table[layout[i]] = first_slot_value + i; diff --git a/mesalib/src/glsl/Makefile.sources b/mesalib/src/glsl/Makefile.sources index 15f5e1f50..5621e42b2 100644 --- a/mesalib/src/glsl/Makefile.sources +++ b/mesalib/src/glsl/Makefile.sources @@ -26,6 +26,7 @@ LIBGLSL_CXX_FILES := \ glsl_symbol_table.cpp \ hir_field_selection.cpp \ ir_basic_block.cpp \ + ir_builder.cpp \ ir_clone.cpp \ ir_constant_expression.cpp \ ir.cpp \ diff --git a/mesalib/src/glsl/ast.h b/mesalib/src/glsl/ast.h index 9b1e0b192..b096c838c 100644 --- a/mesalib/src/glsl/ast.h +++ b/mesalib/src/glsl/ast.h @@ -363,6 +363,11 @@ struct ast_type_qualifier { * qualifier is used. */ unsigned explicit_location:1; + /** + * Flag set if GL_ARB_explicit_attrib_location "index" layout + * qualifier is used. + */ + unsigned explicit_index:1; /** \name Layout qualifiers for GL_AMD_conservative_depth */ /** \{ */ @@ -386,6 +391,13 @@ struct ast_type_qualifier { * This field is only valid if \c explicit_location is set. */ int location; + /** + * Index specified via GL_ARB_explicit_attrib_location layout + * + * \note + * This field is only valid if \c explicit_index is set. + */ + int index; /** * Return true if and only if an interpolation qualifier is present. diff --git a/mesalib/src/glsl/ast_to_hir.cpp b/mesalib/src/glsl/ast_to_hir.cpp index f4dfc4ce3..820c86c5e 100644 --- a/mesalib/src/glsl/ast_to_hir.cpp +++ b/mesalib/src/glsl/ast_to_hir.cpp @@ -2092,14 +2092,21 @@ apply_type_qualifier_to_variable(const struct ast_type_qualifier *qual, } else { var->location = qual->location; } + if (qual->flags.q.explicit_index) { + var->explicit_index = true; + var->index = qual->index; + } } + } else if (qual->flags.q.explicit_index) { + _mesa_glsl_error(loc, state, + "explicit index requires explicit location\n"); } /* Does the declaration use the 'layout' keyword? */ const bool uses_layout = qual->flags.q.pixel_center_integer || qual->flags.q.origin_upper_left - || qual->flags.q.explicit_location; + || qual->flags.q.explicit_location; /* no need for index since it relies on location */ /* Does the declaration use the deprecated 'attribute' or 'varying' * keywords? diff --git a/mesalib/src/glsl/builtin_variables.cpp b/mesalib/src/glsl/builtin_variables.cpp index 516a69caf..03b64c931 100644 --- a/mesalib/src/glsl/builtin_variables.cpp +++ b/mesalib/src/glsl/builtin_variables.cpp @@ -408,6 +408,7 @@ add_variable(exec_list *instructions, glsl_symbol_table *symtab, var->location = slot; var->explicit_location = (slot >= 0); + var->explicit_index = 0; /* Once the variable is created an initialized, add it to the symbol table * and add the declaration to the IR stream. diff --git a/mesalib/src/glsl/glsl_parser.yy b/mesalib/src/glsl/glsl_parser.yy index 920213c30..5753acf3c 100644 --- a/mesalib/src/glsl/glsl_parser.yy +++ b/mesalib/src/glsl/glsl_parser.yy @@ -1103,8 +1103,14 @@ layout_qualifier_id_list: if ($1.flags.q.explicit_location) $$.location = $1.location; + if ($1.flags.q.explicit_index) + $$.index = $1.index; + if ($3.flags.q.explicit_location) $$.location = $3.location; + + if ($3.flags.q.explicit_index) + $$.index = $3.index; } ; @@ -1191,6 +1197,20 @@ layout_qualifier_id: YYERROR; } } + + if (strcmp("index", $1) == 0) { + got_one = true; + + $$.flags.q.explicit_index = 1; + + if ($3 >= 0) { + $$.index = $3; + } else { + _mesa_glsl_error(& @3, state, + "invalid index %d specified\n", $3); + YYERROR; + } + } } /* If the identifier didn't match any known layout identifiers, diff --git a/mesalib/src/glsl/ir.h b/mesalib/src/glsl/ir.h index b1ae6db74..d6c6a607a 100644 --- a/mesalib/src/glsl/ir.h +++ b/mesalib/src/glsl/ir.h @@ -386,6 +386,7 @@ public: * no effect). */ unsigned explicit_location:1; + unsigned explicit_index:1; /** * Does this variable have an initializer? @@ -421,6 +422,11 @@ public: int location; /** + * output index for dual source blending. + */ + int index; + + /** * Built-in state that backs this uniform * * Once set at variable creation, \c state_slots must remain invariant. diff --git a/mesalib/src/glsl/ir_builder.cpp b/mesalib/src/glsl/ir_builder.cpp new file mode 100644 index 000000000..9a16c90e5 --- /dev/null +++ b/mesalib/src/glsl/ir_builder.cpp @@ -0,0 +1,183 @@ +/* + * Copyright © 2012 Intel Corporation + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice (including the next + * paragraph) shall be included in all copies or substantial portions of the + * Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS + * IN THE SOFTWARE. + */ + +#include "ir_builder.h" +#include "program/prog_instruction.h" + +using namespace ir_builder; + +namespace ir_builder { + +void +ir_factory::emit(ir_instruction *ir) +{ + instructions->push_tail(ir); +} + +ir_variable * +ir_factory::make_temp(const glsl_type *type, const char *name) +{ + ir_variable *var; + + var = new(mem_ctx) ir_variable(type, name, ir_var_temporary); + emit(var); + + return var; +} + +ir_assignment * +assign(deref lhs, operand rhs, int writemask) +{ + void *mem_ctx = ralloc_parent(lhs.val); + + ir_assignment *assign = new(mem_ctx) ir_assignment(lhs.val, + rhs.val, + NULL, writemask); + + return assign; +} + +ir_assignment * +assign(deref lhs, operand rhs) +{ + return assign(lhs, rhs, (1 << lhs.val->type->vector_elements) - 1); +} + +ir_swizzle * +swizzle(operand a, int swizzle, int components) +{ + void *mem_ctx = ralloc_parent(a.val); + + return new(mem_ctx) ir_swizzle(a.val, + GET_SWZ(swizzle, 0), + GET_SWZ(swizzle, 1), + GET_SWZ(swizzle, 2), + GET_SWZ(swizzle, 3), + components); +} + +ir_swizzle * +swizzle_xxxx(operand a) +{ + return swizzle(a, SWIZZLE_XXXX, 4); +} + +ir_swizzle * +swizzle_yyyy(operand a) +{ + return swizzle(a, SWIZZLE_YYYY, 4); +} + +ir_swizzle * +swizzle_zzzz(operand a) +{ + return swizzle(a, SWIZZLE_ZZZZ, 4); +} + +ir_swizzle * +swizzle_wwww(operand a) +{ + return swizzle(a, SWIZZLE_WWWW, 4); +} + +ir_swizzle * +swizzle_x(operand a) +{ + return swizzle(a, SWIZZLE_XXXX, 1); +} + +ir_swizzle * +swizzle_y(operand a) +{ + return swizzle(a, SWIZZLE_YYYY, 1); +} + +ir_swizzle * +swizzle_z(operand a) +{ + return swizzle(a, SWIZZLE_ZZZZ, 1); +} + +ir_swizzle * +swizzle_w(operand a) +{ + return swizzle(a, SWIZZLE_WWWW, 1); +} + +ir_swizzle * +swizzle_xy(operand a) +{ + return swizzle(a, SWIZZLE_XYZW, 2); +} + +ir_swizzle * +swizzle_xyz(operand a) +{ + return swizzle(a, SWIZZLE_XYZW, 3); +} + +ir_swizzle * +swizzle_xyzw(operand a) +{ + return swizzle(a, SWIZZLE_XYZW, 4); +} + +ir_expression * +expr(ir_expression_operation op, operand a, operand b) +{ + void *mem_ctx = ralloc_parent(a.val); + + return new(mem_ctx) ir_expression(op, a.val, b.val); +} + +ir_expression *add(operand a, operand b) +{ + return expr(ir_binop_add, a, b); +} + +ir_expression *sub(operand a, operand b) +{ + return expr(ir_binop_sub, a, b); +} + +ir_expression *mul(operand a, operand b) +{ + return expr(ir_binop_mul, a, b); +} + +ir_expression *dot(operand a, operand b) +{ + return expr(ir_binop_dot, a, b); +} + +ir_expression * +saturate(operand a) +{ + void *mem_ctx = ralloc_parent(a.val); + + return expr(ir_binop_max, + expr(ir_binop_min, a, new(mem_ctx) ir_constant(1.0f)), + new(mem_ctx) ir_constant(0.0f)); +} + +} /* namespace ir_builder */ diff --git a/mesalib/src/glsl/ir_builder.h b/mesalib/src/glsl/ir_builder.h new file mode 100644 index 000000000..0ebcbab95 --- /dev/null +++ b/mesalib/src/glsl/ir_builder.h @@ -0,0 +1,105 @@ +/* + * Copyright © 2012 Intel Corporation + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice (including the next + * paragraph) shall be included in all copies or substantial portions of the + * Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS + * IN THE SOFTWARE. + */ + +#include "ir.h" + +namespace ir_builder { + +/** + * This little class exists to let the helper expression generators + * take either an ir_rvalue * or an ir_variable * to be automatically + * dereferenced, while still providing compile-time type checking. + * + * You don't have to explicitly call the constructor -- C++ will see + * that you passed an ir_variable, and silently call the + * operand(ir_variable *var) constructor behind your back. + */ +class operand { +public: + operand(ir_rvalue *val) + : val(val) + { + } + + operand(ir_variable *var) + { + void *mem_ctx = ralloc_parent(var); + val = new(mem_ctx) ir_dereference_variable(var); + } + + ir_rvalue *val; +}; + +/** Automatic generator for ir_dereference_variable on assignment LHS. + * + * \sa operand + */ +class deref { +public: + deref(ir_dereference *val) + : val(val) + { + } + + deref(ir_variable *var) + { + void *mem_ctx = ralloc_parent(var); + val = new(mem_ctx) ir_dereference_variable(var); + } + + + ir_dereference *val; +}; + +class ir_factory { +public: + void emit(ir_instruction *ir); + ir_variable *make_temp(const glsl_type *type, const char *name); + + exec_list *instructions; + void *mem_ctx; +}; + +ir_assignment *assign(deref lhs, operand rhs); +ir_assignment *assign(deref lhs, operand rhs, int writemask); + +ir_expression *expr(ir_expression_operation op, operand a, operand b); +ir_expression *add(operand a, operand b); +ir_expression *sub(operand a, operand b); +ir_expression *mul(operand a, operand b); +ir_expression *dot(operand a, operand b); +ir_expression *saturate(operand a); + +ir_swizzle *swizzle_xxxx(operand a); +ir_swizzle *swizzle_yyyy(operand a); +ir_swizzle *swizzle_zzzz(operand a); +ir_swizzle *swizzle_wwww(operand a); +ir_swizzle *swizzle_x(operand a); +ir_swizzle *swizzle_y(operand a); +ir_swizzle *swizzle_z(operand a); +ir_swizzle *swizzle_w(operand a); +ir_swizzle *swizzle_xy(operand a); +ir_swizzle *swizzle_xyz(operand a); +ir_swizzle *swizzle_xyzw(operand a); + +} /* namespace ir_builder */ diff --git a/mesalib/src/glsl/ir_clone.cpp b/mesalib/src/glsl/ir_clone.cpp index 26b0d8f5f..5a7a71cf6 100644 --- a/mesalib/src/glsl/ir_clone.cpp +++ b/mesalib/src/glsl/ir_clone.cpp @@ -57,6 +57,7 @@ ir_variable::clone(void *mem_ctx, struct hash_table *ht) const var->origin_upper_left = this->origin_upper_left; var->pixel_center_integer = this->pixel_center_integer; var->explicit_location = this->explicit_location; + var->explicit_index = this->explicit_index; var->has_initializer = this->has_initializer; var->depth_layout = this->depth_layout; @@ -74,6 +75,9 @@ ir_variable::clone(void *mem_ctx, struct hash_table *ht) const if (this->explicit_location) var->location = this->location; + if (this->explicit_index) + var->index = this->index; + if (this->constant_value) var->constant_value = this->constant_value->clone(mem_ctx, ht); diff --git a/mesalib/src/glsl/ir_set_program_inouts.cpp b/mesalib/src/glsl/ir_set_program_inouts.cpp index 8c2bc30d6..8f3edb969 100644 --- a/mesalib/src/glsl/ir_set_program_inouts.cpp +++ b/mesalib/src/glsl/ir_set_program_inouts.cpp @@ -81,12 +81,12 @@ mark(struct gl_program *prog, ir_variable *var, int offset, int len, */ for (int i = 0; i < len; i++) { - GLbitfield64 bitfield = BITFIELD64_BIT(var->location + offset + i); + GLbitfield64 bitfield = BITFIELD64_BIT(var->location + var->index + offset + i); if (var->mode == ir_var_in) { prog->InputsRead |= bitfield; if (is_fragment_shader) { gl_fragment_program *fprog = (gl_fragment_program *) prog; - fprog->InterpQualifier[var->location + offset + i] = + fprog->InterpQualifier[var->location + var->index + offset + i] = (glsl_interp_qualifier) var->interpolation; } } else if (var->mode == ir_var_system_value) { diff --git a/mesalib/src/glsl/linker.cpp b/mesalib/src/glsl/linker.cpp index 49b6b8f4a..6ba297237 100644 --- a/mesalib/src/glsl/linker.cpp +++ b/mesalib/src/glsl/linker.cpp @@ -1274,10 +1274,15 @@ assign_attribute_or_color_locations(gl_shader_program *prog, } } else if (target_index == MESA_SHADER_FRAGMENT) { unsigned binding; + unsigned index; if (prog->FragDataBindings->get(binding, var->name)) { assert(binding >= FRAG_RESULT_DATA0); var->location = binding; + + if (prog->FragDataIndexBindings->get(index, var->name)) { + var->index = index; + } } } @@ -1288,7 +1293,7 @@ assign_attribute_or_color_locations(gl_shader_program *prog, */ const unsigned slots = count_attribute_slots(var->type); if (var->location != -1) { - if (var->location >= generic_base) { + if (var->location >= generic_base && var->index < 1) { /* From page 61 of the OpenGL 4.0 spec: * * "LinkProgram will fail if the attribute bindings assigned @@ -1333,8 +1338,8 @@ assign_attribute_or_color_locations(gl_shader_program *prog, ? "vertex shader input" : "fragment shader output"; linker_error(prog, "insufficient contiguous locations " - "available for %s `%s'", string, - var->name); + "available for %s `%s' %d %d %d", string, + var->name, used_locations, use_mask, attr); return false; } @@ -2321,7 +2326,7 @@ link_shaders(struct gl_context *ctx, struct gl_shader_program *prog) goto done; } - if (!assign_attribute_or_color_locations(prog, MESA_SHADER_FRAGMENT, ctx->Const.MaxDrawBuffers)) { + if (!assign_attribute_or_color_locations(prog, MESA_SHADER_FRAGMENT, MAX2(ctx->Const.MaxDrawBuffers, ctx->Const.MaxDualSourceDrawBuffers))) { goto done; } diff --git a/mesalib/src/glsl/opt_if_simplification.cpp b/mesalib/src/glsl/opt_if_simplification.cpp index 940dd08d5..7e88208f7 100644 --- a/mesalib/src/glsl/opt_if_simplification.cpp +++ b/mesalib/src/glsl/opt_if_simplification.cpp @@ -66,6 +66,14 @@ do_if_simplification(exec_list *instructions) ir_visitor_status ir_if_simplification_visitor::visit_leave(ir_if *ir) { + /* If the if statement has nothing on either side, remove it. */ + if (ir->then_instructions.is_empty() && + ir->else_instructions.is_empty()) { + ir->remove(); + this->made_progress = true; + return visit_continue; + } + /* FINISHME: Ideally there would be a way to note that the condition results * FINISHME: in a constant before processing both of the other subtrees. * FINISHME: This can probably be done with some flags, but it would take diff --git a/mesalib/src/mesa/main/blend.c b/mesalib/src/mesa/main/blend.c index 09acdf5c5..bc446edca 100644 --- a/mesalib/src/mesa/main/blend.c +++ b/mesalib/src/mesa/main/blend.c @@ -63,6 +63,11 @@ legal_src_factor(const struct gl_context *ctx, GLenum factor) case GL_CONSTANT_ALPHA: case GL_ONE_MINUS_CONSTANT_ALPHA: return GL_TRUE; + case GL_SRC1_COLOR: + case GL_SRC1_ALPHA: + case GL_ONE_MINUS_SRC1_COLOR: + case GL_ONE_MINUS_SRC1_ALPHA: + return ctx->Extensions.ARB_blend_func_extended; default: return GL_FALSE; } @@ -93,6 +98,12 @@ legal_dst_factor(const struct gl_context *ctx, GLenum factor) case GL_CONSTANT_ALPHA: case GL_ONE_MINUS_CONSTANT_ALPHA: return GL_TRUE; + case GL_SRC_ALPHA_SATURATE: + case GL_SRC1_COLOR: + case GL_SRC1_ALPHA: + case GL_ONE_MINUS_SRC1_COLOR: + case GL_ONE_MINUS_SRC1_ALPHA: + return ctx->Extensions.ARB_blend_func_extended; default: return GL_FALSE; } diff --git a/mesalib/src/mesa/main/context.c b/mesalib/src/mesa/main/context.c index 83e5de47a..51b024143 100644 --- a/mesalib/src/mesa/main/context.c +++ b/mesalib/src/mesa/main/context.c @@ -1695,7 +1695,39 @@ _mesa_set_mvp_with_dp4( struct gl_context *ctx, ctx->mvp_with_dp4 = flag; } +static GLboolean +blend_factor_is_dual_src(GLenum factor) +{ + return factor == GL_SRC1_COLOR || factor == GL_SRC1_ALPHA || + factor == GL_ONE_MINUS_SRC1_COLOR || factor == GL_ONE_MINUS_SRC1_ALPHA; +} +/* + * ARB_blend_func_extended - ERRORS section + * "The error INVALID_OPERATION is generated by Begin or any procedure that + * implicitly calls Begin if any draw buffer has a blend function requiring the + * second color input (SRC1_COLOR, ONE_MINUS_SRC1_COLOR, SRC1_ALPHA or + * ONE_MINUS_SRC1_ALPHA), and a framebuffer is bound that has more than + * the value of MAX_DUAL_SOURCE_DRAW_BUFFERS-1 active color attachements." + */ +static GLboolean +_mesa_check_blend_func_error(struct gl_context *ctx) +{ + GLuint i; + for (i = 0; i < ctx->DrawBuffer->_NumColorDrawBuffers; i++) { + if (blend_factor_is_dual_src(ctx->Color.Blend[i].SrcRGB) || + blend_factor_is_dual_src(ctx->Color.Blend[i].DstRGB) || + blend_factor_is_dual_src(ctx->Color.Blend[i].SrcA) || + blend_factor_is_dual_src(ctx->Color.Blend[i].DstA)) { + if (i >= ctx->Const.MaxDualSourceDrawBuffers) { + _mesa_error(ctx, GL_INVALID_OPERATION, + "dual source blend on illegal attachment"); + return GL_FALSE; + } + } + } + return GL_TRUE; +} /** * Prior to drawing anything with glBegin, glDrawArrays, etc. this function @@ -1816,6 +1848,10 @@ _mesa_valid_to_render(struct gl_context *ctx, const char *where) return GL_FALSE; } + if (_mesa_check_blend_func_error(ctx) == GL_FALSE) { + return GL_FALSE; + } + #ifdef DEBUG if (ctx->Shader.Flags & GLSL_LOG) { struct gl_shader_program *shProg[MESA_SHADER_TYPES]; diff --git a/mesalib/src/mesa/main/extensions.c b/mesalib/src/mesa/main/extensions.c index 3ce4cd559..5f2c74a75 100644 --- a/mesalib/src/mesa/main/extensions.c +++ b/mesalib/src/mesa/main/extensions.c @@ -940,7 +940,7 @@ _mesa_get_enabled_extension(struct gl_context *ctx, GLuint index) n = 0; for (i = extension_table; i->name != 0; ++i) { if (n == index && base[i->offset]) { - return (GLubyte*) i->name; + return (const GLubyte*) i->name; } else if (base[i->offset]) { ++n; } diff --git a/mesalib/src/mesa/main/ff_fragment_shader.cpp b/mesalib/src/mesa/main/ff_fragment_shader.cpp index 7b830439d..3c91b1a42 100644 --- a/mesalib/src/mesa/main/ff_fragment_shader.cpp +++ b/mesalib/src/mesa/main/ff_fragment_shader.cpp @@ -45,12 +45,15 @@ extern "C" { #include "main/uniforms.h" #include "../glsl/glsl_types.h" #include "../glsl/ir.h" +#include "../glsl/ir_builder.h" #include "../glsl/glsl_symbol_table.h" #include "../glsl/glsl_parser_extras.h" #include "../glsl/ir_optimization.h" #include "../glsl/ir_print_visitor.h" #include "../program/ir_to_mesa.h" +using namespace ir_builder; + /* * Note on texture units: * @@ -508,12 +511,11 @@ static GLuint make_state_key( struct gl_context *ctx, struct state_key *key ) /** State used to build the fragment program: */ -struct texenv_fragment_program { +class texenv_fragment_program : public ir_factory { +public: struct gl_shader_program *shader_program; struct gl_shader *shader; - exec_list *instructions; exec_list *top_instructions; - void *mem_ctx; struct state_key *state; ir_variable *src_texture[MAX_TEXTURE_COORD_UNITS]; @@ -621,21 +623,15 @@ emit_combine_source(struct texenv_fragment_program *p, switch (operand) { case OPR_ONE_MINUS_SRC_COLOR: - return new(p->mem_ctx) ir_expression(ir_binop_sub, - new(p->mem_ctx) ir_constant(1.0f), - src); + return sub(new(p->mem_ctx) ir_constant(1.0f), src); case OPR_SRC_ALPHA: - return src->type->is_scalar() - ? src : (ir_rvalue *) new(p->mem_ctx) ir_swizzle(src, 3, 3, 3, 3, 1); + return src->type->is_scalar() ? src : swizzle_w(src); case OPR_ONE_MINUS_SRC_ALPHA: { - ir_rvalue *const scalar = (src->type->is_scalar()) - ? src : (ir_rvalue *) new(p->mem_ctx) ir_swizzle(src, 3, 3, 3, 3, 1); + ir_rvalue *const scalar = src->type->is_scalar() ? src : swizzle_w(src); - return new(p->mem_ctx) ir_expression(ir_binop_sub, - new(p->mem_ctx) ir_constant(1.0f), - scalar); + return sub(new(p->mem_ctx) ir_constant(1.0f), scalar); } case OPR_ZERO: @@ -696,7 +692,7 @@ smear(struct texenv_fragment_program *p, ir_rvalue *val) if (!val->type->is_scalar()) return val; - return new(p->mem_ctx) ir_swizzle(val, 0, 0, 0, 0, 4); + return swizzle_xxxx(val); } static ir_rvalue * @@ -720,73 +716,52 @@ emit_combine(struct texenv_fragment_program *p, return src[0]; case MODE_MODULATE: - return new(p->mem_ctx) ir_expression(ir_binop_mul, src[0], src[1]); + return mul(src[0], src[1]); case MODE_ADD: - return new(p->mem_ctx) ir_expression(ir_binop_add, src[0], src[1]); + return add(src[0], src[1]); case MODE_ADD_SIGNED: - tmp0 = new(p->mem_ctx) ir_expression(ir_binop_add, src[0], src[1]); - return new(p->mem_ctx) ir_expression(ir_binop_add, tmp0, - new(p->mem_ctx) ir_constant(-0.5f)); + return add(add(src[0], src[1]), new(p->mem_ctx) ir_constant(-0.5f)); case MODE_INTERPOLATE: /* Arg0 * (Arg2) + Arg1 * (1-Arg2) */ - tmp0 = new(p->mem_ctx) ir_expression(ir_binop_mul, src[0], src[2]); - - tmp1 = new(p->mem_ctx) ir_expression(ir_binop_sub, - new(p->mem_ctx) ir_constant(1.0f), - src[2]->clone(p->mem_ctx, NULL)); - tmp1 = new(p->mem_ctx) ir_expression(ir_binop_mul, src[1], tmp1); - - return new(p->mem_ctx) ir_expression(ir_binop_add, tmp0, tmp1); + tmp0 = mul(src[0], src[2]); + tmp1 = mul(src[1], sub(new(p->mem_ctx) ir_constant(1.0f), + src[2]->clone(p->mem_ctx, NULL))); + return add(tmp0, tmp1); case MODE_SUBTRACT: - return new(p->mem_ctx) ir_expression(ir_binop_sub, src[0], src[1]); + return sub(src[0], src[1]); case MODE_DOT3_RGBA: case MODE_DOT3_RGBA_EXT: case MODE_DOT3_RGB_EXT: case MODE_DOT3_RGB: { - tmp0 = new(p->mem_ctx) ir_expression(ir_binop_mul, src[0], - new(p->mem_ctx) ir_constant(2.0f)); - tmp0 = new(p->mem_ctx) ir_expression(ir_binop_add, tmp0, - new(p->mem_ctx) ir_constant(-1.0f)); - tmp0 = new(p->mem_ctx) ir_swizzle(smear(p, tmp0), 0, 1, 2, 3, 3); - - tmp1 = new(p->mem_ctx) ir_expression(ir_binop_mul, src[1], - new(p->mem_ctx) ir_constant(2.0f)); - tmp1 = new(p->mem_ctx) ir_expression(ir_binop_add, tmp1, - new(p->mem_ctx) ir_constant(-1.0f)); - tmp1 = new(p->mem_ctx) ir_swizzle(smear(p, tmp1), 0, 1, 2, 3, 3); - - return new(p->mem_ctx) ir_expression(ir_binop_dot, tmp0, tmp1); + tmp0 = mul(src[0], new(p->mem_ctx) ir_constant(2.0f)); + tmp0 = add(tmp0, new(p->mem_ctx) ir_constant(-1.0f)); + + tmp1 = mul(src[1], new(p->mem_ctx) ir_constant(2.0f)); + tmp1 = add(tmp1, new(p->mem_ctx) ir_constant(-1.0f)); + + return dot(swizzle_xyz(smear(p, tmp0)), swizzle_xyz(smear(p, tmp1))); } case MODE_MODULATE_ADD_ATI: - tmp0 = new(p->mem_ctx) ir_expression(ir_binop_mul, src[0], src[2]); - return new(p->mem_ctx) ir_expression(ir_binop_add, tmp0, src[1]); + return add(mul(src[0], src[2]), src[1]); case MODE_MODULATE_SIGNED_ADD_ATI: - tmp0 = new(p->mem_ctx) ir_expression(ir_binop_mul, src[0], src[2]); - tmp0 = new(p->mem_ctx) ir_expression(ir_binop_add, tmp0, src[1]); - return new(p->mem_ctx) ir_expression(ir_binop_add, tmp0, - new(p->mem_ctx) ir_constant(-0.5f)); + return add(add(mul(src[0], src[2]), src[1]), + new(p->mem_ctx) ir_constant(-0.5f)); case MODE_MODULATE_SUBTRACT_ATI: - tmp0 = new(p->mem_ctx) ir_expression(ir_binop_mul, src[0], src[2]); - return new(p->mem_ctx) ir_expression(ir_binop_sub, tmp0, src[1]); + return sub(mul(src[0], src[2]), src[1]); case MODE_ADD_PRODUCTS: - tmp0 = new(p->mem_ctx) ir_expression(ir_binop_mul, src[0], src[1]); - tmp1 = new(p->mem_ctx) ir_expression(ir_binop_mul, src[2], src[3]); - return new(p->mem_ctx) ir_expression(ir_binop_add, tmp0, tmp1); + return add(mul(src[0], src[1]), mul(src[2], src[3])); case MODE_ADD_PRODUCTS_SIGNED: - tmp0 = new(p->mem_ctx) ir_expression(ir_binop_mul, src[0], src[1]); - tmp1 = new(p->mem_ctx) ir_expression(ir_binop_mul, src[2], src[3]); - tmp0 = new(p->mem_ctx) ir_expression(ir_binop_add, tmp0, tmp1); - return new(p->mem_ctx) ir_expression(ir_binop_add, tmp0, - new(p->mem_ctx) ir_constant(-0.5f)); + return add(add(mul(src[0], src[1]), mul(src[2], src[3])), + new(p->mem_ctx) ir_constant(-0.5f)); case MODE_BUMP_ENVMAP_ATI: /* special - not handled here */ @@ -798,15 +773,6 @@ emit_combine(struct texenv_fragment_program *p, } } -static ir_rvalue * -saturate(struct texenv_fragment_program *p, ir_rvalue *val) -{ - val = new(p->mem_ctx) ir_expression(ir_binop_min, val, - new(p->mem_ctx) ir_constant(1.0f)); - return new(p->mem_ctx) ir_expression(ir_binop_max, val, - new(p->mem_ctx) ir_constant(0.0f)); -} - /** * Generate instructions for one texture unit's env/combiner mode. */ @@ -857,13 +823,8 @@ emit_texenv(struct texenv_fragment_program *p, GLuint unit) else alpha_saturate = GL_FALSE; - ir_variable *temp_var = new(p->mem_ctx) ir_variable(glsl_type::vec4_type, - "texenv_combine", - ir_var_temporary); - p->instructions->push_tail(temp_var); - + ir_variable *temp_var = p->make_temp(glsl_type::vec4_type, "texenv_combine"); ir_dereference *deref; - ir_assignment *assign; ir_rvalue *val; /* Emit the RGB and A combine ops @@ -876,11 +837,9 @@ emit_texenv(struct texenv_fragment_program *p, GLuint unit) key->unit[unit].OptRGB); val = smear(p, val); if (rgb_saturate) - val = saturate(p, val); + val = saturate(val); - deref = new(p->mem_ctx) ir_dereference_variable(temp_var); - assign = new(p->mem_ctx) ir_assignment(deref, val); - p->instructions->push_tail(assign); + p->emit(assign(temp_var, val)); } else if (key->unit[unit].ModeRGB == MODE_DOT3_RGBA_EXT || key->unit[unit].ModeRGB == MODE_DOT3_RGBA) { @@ -890,10 +849,8 @@ emit_texenv(struct texenv_fragment_program *p, GLuint unit) key->unit[unit].OptRGB); val = smear(p, val); if (rgb_saturate) - val = saturate(p, val); - deref = new(p->mem_ctx) ir_dereference_variable(temp_var); - assign = new(p->mem_ctx) ir_assignment(deref, val); - p->instructions->push_tail(assign); + val = saturate(val); + p->emit(assign(temp_var, val)); } else { /* Need to do something to stop from re-emitting identical @@ -903,25 +860,19 @@ emit_texenv(struct texenv_fragment_program *p, GLuint unit) key->unit[unit].NumArgsRGB, key->unit[unit].ModeRGB, key->unit[unit].OptRGB); - val = smear(p, val); - val = new(p->mem_ctx) ir_swizzle(val, 0, 1, 2, 3, 3); + val = swizzle_xyz(smear(p, val)); if (rgb_saturate) - val = saturate(p, val); - deref = new(p->mem_ctx) ir_dereference_variable(temp_var); - assign = new(p->mem_ctx) ir_assignment(deref, val, NULL, WRITEMASK_XYZ); - p->instructions->push_tail(assign); + val = saturate(val); + p->emit(assign(temp_var, val, WRITEMASK_XYZ)); val = emit_combine(p, unit, key->unit[unit].NumArgsA, key->unit[unit].ModeA, key->unit[unit].OptA); - val = smear(p, val); - val = new(p->mem_ctx) ir_swizzle(val, 3, 3, 3, 3, 1); + val = swizzle_w(smear(p, val)); if (alpha_saturate) - val = saturate(p, val); - deref = new(p->mem_ctx) ir_dereference_variable(temp_var); - assign = new(p->mem_ctx) ir_assignment(deref, val, NULL, WRITEMASK_W); - p->instructions->push_tail(assign); + val = saturate(val); + p->emit(assign(temp_var, val, WRITEMASK_W)); } deref = new(p->mem_ctx) ir_dereference_variable(temp_var); @@ -945,8 +896,7 @@ emit_texenv(struct texenv_fragment_program *p, GLuint unit) (ir_constant_data *)const_data); } - return saturate(p, new(p->mem_ctx) ir_expression(ir_binop_mul, - deref, shift)); + return saturate(mul(deref, shift)); } else return deref; @@ -959,7 +909,6 @@ emit_texenv(struct texenv_fragment_program *p, GLuint unit) static void load_texture( struct texenv_fragment_program *p, GLuint unit ) { ir_dereference *deref; - ir_assignment *assign; if (p->src_texture[unit]) return; @@ -981,15 +930,11 @@ static void load_texture( struct texenv_fragment_program *p, GLuint unit ) } if (!p->state->unit[unit].enabled) { - p->src_texture[unit] = new(p->mem_ctx) ir_variable(glsl_type::vec4_type, - "dummy_tex", - ir_var_temporary); - p->instructions->push_tail(p->src_texture[unit]); - - deref = new(p->mem_ctx) ir_dereference_variable(p->src_texture[unit]); - assign = new(p->mem_ctx) ir_assignment(deref, - new(p->mem_ctx) ir_constant(0.0f)); - p->instructions->push_tail(assign); + p->src_texture[unit] = p->make_temp(glsl_type::vec4_type, + "dummy_tex"); + p->emit(p->src_texture[unit]); + + p->emit(assign(p->src_texture[unit], new(p->mem_ctx) ir_constant(0.0f))); return ; } @@ -1051,10 +996,8 @@ static void load_texture( struct texenv_fragment_program *p, GLuint unit ) break; } - p->src_texture[unit] = new(p->mem_ctx) ir_variable(glsl_type::vec4_type, - "tex", - ir_var_temporary); - p->instructions->push_tail(p->src_texture[unit]); + p->src_texture[unit] = p->make_temp(glsl_type::vec4_type, + "tex"); ir_texture *tex = new(p->mem_ctx) ir_texture(ir_tex); @@ -1078,11 +1021,9 @@ static void load_texture( struct texenv_fragment_program *p, GLuint unit ) } texcoord = texcoord->clone(p->mem_ctx, NULL); - tex->projector = new(p->mem_ctx) ir_swizzle(texcoord, 3, 0, 0, 0, 1); + tex->projector = swizzle_w(texcoord); - deref = new(p->mem_ctx) ir_dereference_variable(p->src_texture[unit]); - assign = new(p->mem_ctx) ir_assignment(deref, tex); - p->instructions->push_tail(assign); + p->emit(assign(p->src_texture[unit], tex)); } static void @@ -1142,13 +1083,10 @@ load_texunit_bumpmap( struct texenv_fragment_program *p, GLuint unit ) GLuint bumpedUnitNr = key->unit[unit].OptRGB[1].Source - SRC_TEXTURE0; ir_rvalue *bump; ir_rvalue *texcoord; - ir_variable *rot_mat_0_var, *rot_mat_1_var; - ir_dereference_variable *rot_mat_0, *rot_mat_1; + ir_variable *rot_mat_0, *rot_mat_1; - rot_mat_0_var = p->shader->symbols->get_variable("gl_BumpRotMatrix0MESA"); - rot_mat_1_var = p->shader->symbols->get_variable("gl_BumpRotMatrix1MESA"); - rot_mat_0 = new(p->mem_ctx) ir_dereference_variable(rot_mat_0_var); - rot_mat_1 = new(p->mem_ctx) ir_dereference_variable(rot_mat_1_var); + rot_mat_0 = p->shader->symbols->get_variable("gl_BumpRotMatrix0MESA"); + rot_mat_1 = p->shader->symbols->get_variable("gl_BumpRotMatrix1MESA"); ir_variable *tc_array = p->shader->symbols->get_variable("gl_TexCoord"); assert(tc_array); @@ -1163,44 +1101,22 @@ load_texunit_bumpmap( struct texenv_fragment_program *p, GLuint unit ) * dest = Arg1 + (Arg0.xx * rotMat0) + (Arg0.yy * rotMat1) * note only 2 coords are affected the rest are left unchanged (mul by 0) */ - ir_dereference *deref; - ir_assignment *assign; ir_rvalue *bump_x, *bump_y; texcoord = smear(p, texcoord); /* bump_texcoord = texcoord */ - ir_variable *bumped = new(p->mem_ctx) ir_variable(texcoord->type, - "bump_texcoord", - ir_var_temporary); - p->instructions->push_tail(bumped); - - deref = new(p->mem_ctx) ir_dereference_variable(bumped); - assign = new(p->mem_ctx) ir_assignment(deref, texcoord); - p->instructions->push_tail(assign); + ir_variable *bumped = p->make_temp(texcoord->type, "bump_texcoord"); + p->emit(bumped); + p->emit(assign(bumped, texcoord)); /* bump_texcoord.xy += arg0.x * rotmat0 + arg0.y * rotmat1 */ bump = get_source(p, key->unit[unit].OptRGB[0].Source, unit); - bump_x = new(p->mem_ctx) ir_swizzle(bump, 0, 0, 0, 0, 1); - bump = bump->clone(p->mem_ctx, NULL); - bump_y = new(p->mem_ctx) ir_swizzle(bump, 1, 0, 0, 0, 1); - - bump_x = new(p->mem_ctx) ir_expression(ir_binop_mul, bump_x, rot_mat_0); - bump_y = new(p->mem_ctx) ir_expression(ir_binop_mul, bump_y, rot_mat_1); - - ir_expression *expr; - expr = new(p->mem_ctx) ir_expression(ir_binop_add, bump_x, bump_y); + bump_x = mul(swizzle_x(bump), rot_mat_0); + bump_y = mul(swizzle_y(bump->clone(p->mem_ctx, NULL)), rot_mat_1); - deref = new(p->mem_ctx) ir_dereference_variable(bumped); - expr = new(p->mem_ctx) ir_expression(ir_binop_add, - new(p->mem_ctx) ir_swizzle(deref, - 0, 1, 1, 1, - 2), - expr); - - deref = new(p->mem_ctx) ir_dereference_variable(bumped); - assign = new(p->mem_ctx) ir_assignment(deref, expr, NULL, WRITEMASK_XY); - p->instructions->push_tail(assign); + p->emit(assign(bumped, add(swizzle_xy(bumped), add(bump_x, bump_y)), + WRITEMASK_XY)); p->texcoord_tex[bumpedUnitNr] = bumped; } @@ -1220,31 +1136,22 @@ emit_fog_instructions(struct texenv_fragment_program *p, ir_rvalue *f, *temp; ir_variable *params, *oparams; ir_variable *fogcoord; - ir_assignment *assign; /* Temporary storage for the whole fog result. Fog calculations * only affect rgb so we're hanging on to the .a value of fragcolor * this way. */ - ir_variable *fog_result = new(p->mem_ctx) ir_variable(glsl_type::vec4_type, - "fog_result", - ir_var_auto); - p->instructions->push_tail(fog_result); - temp = new(p->mem_ctx) ir_dereference_variable(fog_result); - assign = new(p->mem_ctx) ir_assignment(temp, fragcolor); - p->instructions->push_tail(assign); + ir_variable *fog_result = p->make_temp(glsl_type::vec4_type, "fog_result"); + p->emit(assign(fog_result, fragcolor)); - temp = new(p->mem_ctx) ir_dereference_variable(fog_result); - fragcolor = new(p->mem_ctx) ir_swizzle(temp, 0, 1, 2, 3, 3); + fragcolor = swizzle_xyz(fog_result); oparams = p->shader->symbols->get_variable("gl_FogParamsOptimizedMESA"); fogcoord = p->shader->symbols->get_variable("gl_FogFragCoord"); params = p->shader->symbols->get_variable("gl_Fog"); f = new(p->mem_ctx) ir_dereference_variable(fogcoord); - ir_variable *f_var = new(p->mem_ctx) ir_variable(glsl_type::float_type, - "fog_factor", ir_var_auto); - p->instructions->push_tail(f_var); + ir_variable *f_var = p->make_temp(glsl_type::float_type, "fog_factor"); switch (key->fog_mode) { case FOG_LINEAR: @@ -1253,13 +1160,7 @@ emit_fog_instructions(struct texenv_fragment_program *p, * gl_MesaFogParamsOptimized gives us (-1 / (end - start)) and * (end / (end - start)) so we can generate a single MAD. */ - temp = new(p->mem_ctx) ir_dereference_variable(oparams); - temp = new(p->mem_ctx) ir_swizzle(temp, 0, 0, 0, 0, 1); - f = new(p->mem_ctx) ir_expression(ir_binop_mul, f, temp); - - temp = new(p->mem_ctx) ir_dereference_variable(oparams); - temp = new(p->mem_ctx) ir_swizzle(temp, 1, 0, 0, 0, 1); - f = new(p->mem_ctx) ir_expression(ir_binop_add, f, temp); + f = add(mul(f, swizzle_x(oparams)), swizzle_y(oparams)); break; case FOG_EXP: /* f = e^(-(density * fogcoord)) @@ -1268,9 +1169,7 @@ emit_fog_instructions(struct texenv_fragment_program *p, * use EXP2 which is generally the native instruction without * having to do any further math on the fog density uniform. */ - temp = new(p->mem_ctx) ir_dereference_variable(oparams); - temp = new(p->mem_ctx) ir_swizzle(temp, 2, 0, 0, 0, 1); - f = new(p->mem_ctx) ir_expression(ir_binop_mul, f, temp); + f = mul(f, swizzle_z(oparams)); f = new(p->mem_ctx) ir_expression(ir_unop_neg, f); f = new(p->mem_ctx) ir_expression(ir_unop_exp2, f); break; @@ -1281,50 +1180,23 @@ emit_fog_instructions(struct texenv_fragment_program *p, * can do this like FOG_EXP but with a squaring after the * multiply by density. */ - ir_variable *temp_var = new(p->mem_ctx) ir_variable(glsl_type::float_type, - "fog_temp", - ir_var_auto); - p->instructions->push_tail(temp_var); - - temp = new(p->mem_ctx) ir_dereference_variable(oparams); - temp = new(p->mem_ctx) ir_swizzle(temp, 3, 0, 0, 0, 1); - f = new(p->mem_ctx) ir_expression(ir_binop_mul, - f, temp); - - temp = new(p->mem_ctx) ir_dereference_variable(temp_var); - ir_assignment *assign = new(p->mem_ctx) ir_assignment(temp, f); - p->instructions->push_tail(assign); - - f = new(p->mem_ctx) ir_dereference_variable(temp_var); - temp = new(p->mem_ctx) ir_dereference_variable(temp_var); - f = new(p->mem_ctx) ir_expression(ir_binop_mul, f, temp); + ir_variable *temp_var = p->make_temp(glsl_type::float_type, "fog_temp"); + p->emit(assign(temp_var, mul(f, swizzle_w(oparams)))); + + f = mul(temp_var, temp_var); f = new(p->mem_ctx) ir_expression(ir_unop_neg, f); f = new(p->mem_ctx) ir_expression(ir_unop_exp2, f); break; } - f = saturate(p, f); + p->emit(assign(f_var, saturate(f))); - temp = new(p->mem_ctx) ir_dereference_variable(f_var); - assign = new(p->mem_ctx) ir_assignment(temp, f); - p->instructions->push_tail(assign); - - f = new(p->mem_ctx) ir_dereference_variable(f_var); - f = new(p->mem_ctx) ir_expression(ir_binop_sub, - new(p->mem_ctx) ir_constant(1.0f), - f); + f = sub(new(p->mem_ctx) ir_constant(1.0f), f_var); temp = new(p->mem_ctx) ir_dereference_variable(params); temp = new(p->mem_ctx) ir_dereference_record(temp, "color"); - temp = new(p->mem_ctx) ir_swizzle(temp, 0, 1, 2, 3, 3); - temp = new(p->mem_ctx) ir_expression(ir_binop_mul, temp, f); - - f = new(p->mem_ctx) ir_dereference_variable(f_var); - f = new(p->mem_ctx) ir_expression(ir_binop_mul, fragcolor, f); - f = new(p->mem_ctx) ir_expression(ir_binop_add, temp, f); + temp = mul(swizzle_xyz(temp), f); - ir_dereference *deref = new(p->mem_ctx) ir_dereference_variable(fog_result); - assign = new(p->mem_ctx) ir_assignment(deref, f, NULL, WRITEMASK_XYZ); - p->instructions->push_tail(assign); + p->emit(assign(fog_result, add(temp, mul(fragcolor, f_var)), WRITEMASK_XYZ)); return new(p->mem_ctx) ir_dereference_variable(fog_result); } @@ -1363,40 +1235,24 @@ emit_instructions(struct texenv_fragment_program *p) } ir_rvalue *cf = get_source(p, SRC_PREVIOUS, 0); - ir_dereference_variable *deref; - ir_assignment *assign; if (key->separate_specular) { - ir_rvalue *tmp0; - ir_variable *spec_result = new(p->mem_ctx) ir_variable(glsl_type::vec4_type, - "specular_add", - ir_var_temporary); - - p->instructions->push_tail(spec_result); - - deref = new(p->mem_ctx) ir_dereference_variable(spec_result); - assign = new(p->mem_ctx) ir_assignment(deref, cf); - p->instructions->push_tail(assign); - - deref = new(p->mem_ctx) ir_dereference_variable(spec_result); - tmp0 = new(p->mem_ctx) ir_swizzle(deref, 0, 1, 2, 3, 3); + ir_variable *spec_result = p->make_temp(glsl_type::vec4_type, + "specular_add"); + p->emit(assign(spec_result, cf)); ir_rvalue *secondary; if (p->state->inputs_available & FRAG_BIT_COL1) { ir_variable *var = p->shader->symbols->get_variable("gl_SecondaryColor"); assert(var); - secondary = new(p->mem_ctx) ir_dereference_variable(var); + secondary = swizzle_xyz(var); } else { - secondary = get_current_attrib(p, VERT_ATTRIB_COLOR1); + secondary = swizzle_xyz(get_current_attrib(p, VERT_ATTRIB_COLOR1)); } - secondary = new(p->mem_ctx) ir_swizzle(secondary, 0, 1, 2, 3, 3); - - tmp0 = new(p->mem_ctx) ir_expression(ir_binop_add, tmp0, secondary); - deref = new(p->mem_ctx) ir_dereference_variable(spec_result); - assign = new(p->mem_ctx) ir_assignment(deref, tmp0, NULL, WRITEMASK_XYZ); - p->instructions->push_tail(assign); + p->emit(assign(spec_result, add(swizzle_xyz(spec_result), secondary), + WRITEMASK_XYZ)); cf = new(p->mem_ctx) ir_dereference_variable(spec_result); } @@ -1407,9 +1263,7 @@ emit_instructions(struct texenv_fragment_program *p) ir_variable *frag_color = p->shader->symbols->get_variable("gl_FragColor"); assert(frag_color); - deref = new(p->mem_ctx) ir_dereference_variable(frag_color); - assign = new(p->mem_ctx) ir_assignment(deref, cf); - p->instructions->push_tail(assign); + p->emit(assign(frag_color, cf)); } /** @@ -1419,11 +1273,10 @@ emit_instructions(struct texenv_fragment_program *p) static struct gl_shader_program * create_new_program(struct gl_context *ctx, struct state_key *key) { - struct texenv_fragment_program p; + texenv_fragment_program p; unsigned int unit; _mesa_glsl_parse_state *state; - memset(&p, 0, sizeof(p)); p.mem_ctx = ralloc_context(NULL); p.shader = ctx->Driver.NewShader(ctx, 0, GL_FRAGMENT_SHADER); p.shader->ir = new(p.shader) exec_list; @@ -1457,7 +1310,7 @@ create_new_program(struct gl_context *ctx, struct state_key *key) p.src_previous = NULL; ir_function *main_f = new(p.mem_ctx) ir_function("main"); - p.instructions->push_tail(main_f); + p.emit(main_f); state->symbols->add_function(main_f); ir_function_signature *main_sig = diff --git a/mesalib/src/mesa/main/format_pack.c b/mesalib/src/mesa/main/format_pack.c index ff08ac561..7f0bda127 100644 --- a/mesalib/src/mesa/main/format_pack.c +++ b/mesalib/src/mesa/main/format_pack.c @@ -2605,7 +2605,7 @@ _mesa_pack_colormask(gl_format format, const GLubyte colorMask[4], void *dst) if (bits == 8) { GLubyte *d = (GLubyte *) dst; for (i = 0; i < bytes; i++) { - d[i] = d[i] ? 0xffff : 0x0; + d[i] = d[i] ? 0xff : 0x0; } } else if (bits == 16) { diff --git a/mesalib/src/mesa/main/get.c b/mesalib/src/mesa/main/get.c index 9a5ca5334..55dc20550 100644 --- a/mesalib/src/mesa/main/get.c +++ b/mesalib/src/mesa/main/get.c @@ -333,6 +333,7 @@ EXTRA_EXT(ARB_copy_buffer); EXTRA_EXT(EXT_framebuffer_sRGB); EXTRA_EXT(ARB_texture_buffer_object); EXTRA_EXT(OES_EGL_image_external); +EXTRA_EXT(ARB_blend_func_extended); static const int extra_ARB_vertex_program_ARB_fragment_program_NV_vertex_program[] = { @@ -1304,6 +1305,8 @@ static const struct value_desc values[] = { { GL_MAX_DEBUG_LOGGED_MESSAGES_ARB, CONST(MAX_DEBUG_LOGGED_MESSAGES), NO_EXTRA }, { GL_MAX_DEBUG_MESSAGE_LENGTH_ARB, CONST(MAX_DEBUG_MESSAGE_LENGTH), NO_EXTRA }, + { GL_MAX_DUAL_SOURCE_DRAW_BUFFERS, CONTEXT_INT(Const.MaxDualSourceDrawBuffers), extra_ARB_blend_func_extended }, + #endif /* FEATURE_GL */ }; diff --git a/mesalib/src/mesa/main/mtypes.h b/mesalib/src/mesa/main/mtypes.h index 8e441c232..bfa320a52 100644 --- a/mesalib/src/mesa/main/mtypes.h +++ b/mesalib/src/mesa/main/mtypes.h @@ -2263,6 +2263,7 @@ struct gl_shader_program * and they are \b not the values returned by \c glGetFragDataLocation. */ struct string_to_uint_map *FragDataBindings; + struct string_to_uint_map *FragDataIndexBindings; /** * Transform feedback varyings last specified by @@ -2814,6 +2815,9 @@ struct gl_constants /* GL_ARB_robustness */ GLenum ResetStrategy; + /* GL_ARB_blend_func_extended */ + GLuint MaxDualSourceDrawBuffers; + /** * Whether the implementation strips out and ignores texture borders. * diff --git a/mesalib/src/mesa/main/shader_query.cpp b/mesalib/src/mesa/main/shader_query.cpp index 8ab18126c..02a48ba60 100644 --- a/mesalib/src/mesa/main/shader_query.cpp +++ b/mesalib/src/mesa/main/shader_query.cpp @@ -239,10 +239,17 @@ void GLAPIENTRY _mesa_BindFragDataLocation(GLuint program, GLuint colorNumber, const GLchar *name) { + _mesa_BindFragDataLocationIndexed(program, colorNumber, 0, name); +} + +void GLAPIENTRY +_mesa_BindFragDataLocationIndexed(GLuint program, GLuint colorNumber, + GLuint index, const GLchar *name) +{ GET_CURRENT_CONTEXT(ctx); struct gl_shader_program *const shProg = - _mesa_lookup_shader_program_err(ctx, program, "glBindFragDataLocation"); + _mesa_lookup_shader_program_err(ctx, program, "glBindFragDataLocationIndexed"); if (!shProg) return; @@ -250,13 +257,22 @@ _mesa_BindFragDataLocation(GLuint program, GLuint colorNumber, return; if (strncmp(name, "gl_", 3) == 0) { - _mesa_error(ctx, GL_INVALID_OPERATION, - "glBindFragDataLocation(illegal name)"); + _mesa_error(ctx, GL_INVALID_OPERATION, "glBindFragDataLocationIndexed(illegal name)"); + return; + } + + if (index > 1) { + _mesa_error(ctx, GL_INVALID_VALUE, "glBindFragDataLocationIndexed(index)"); return; } - if (colorNumber >= ctx->Const.MaxDrawBuffers) { - _mesa_error(ctx, GL_INVALID_VALUE, "glBindFragDataLocation(index)"); + if (index == 0 && colorNumber >= ctx->Const.MaxDrawBuffers) { + _mesa_error(ctx, GL_INVALID_VALUE, "glBindFragDataLocationIndexed(colorNumber)"); + return; + } + + if (index == 1 && colorNumber >= ctx->Const.MaxDualSourceDrawBuffers) { + _mesa_error(ctx, GL_INVALID_VALUE, "glBindFragDataLocationIndexed(colorNumber)"); return; } @@ -265,11 +281,68 @@ _mesa_BindFragDataLocation(GLuint program, GLuint colorNumber, * between built-in attributes and user-defined attributes. */ shProg->FragDataBindings->put(colorNumber + FRAG_RESULT_DATA0, name); - + shProg->FragDataIndexBindings->put(index, name); /* * Note that this binding won't go into effect until * glLinkProgram is called again. */ + +} + +GLint GLAPIENTRY +_mesa_GetFragDataIndex(GLuint program, const GLchar *name) +{ + GET_CURRENT_CONTEXT(ctx); + struct gl_shader_program *const shProg = + _mesa_lookup_shader_program_err(ctx, program, "glGetFragDataIndex"); + + if (!shProg) { + return -1; + } + + if (!shProg->LinkStatus) { + _mesa_error(ctx, GL_INVALID_OPERATION, + "glGetFragDataIndex(program not linked)"); + return -1; + } + + if (!name) + return -1; + + if (strncmp(name, "gl_", 3) == 0) { + _mesa_error(ctx, GL_INVALID_OPERATION, + "glGetFragDataIndex(illegal name)"); + return -1; + } + + /* Not having a fragment shader is not an error. + */ + if (shProg->_LinkedShaders[MESA_SHADER_FRAGMENT] == NULL) + return -1; + + exec_list *ir = shProg->_LinkedShaders[MESA_SHADER_FRAGMENT]->ir; + foreach_list(node, ir) { + const ir_variable *const var = ((ir_instruction *) node)->as_variable(); + + /* The extra check against FRAG_RESULT_DATA0 is because + * glGetFragDataLocation cannot be used on "conventional" attributes. + * + * From page 95 of the OpenGL 3.0 spec: + * + * "If name is not an active attribute, if name is a conventional + * attribute, or if an error occurs, -1 will be returned." + */ + if (var == NULL + || var->mode != ir_var_out + || var->location == -1 + || var->location < FRAG_RESULT_DATA0) + continue; + + if (strcmp(var->name, name) == 0) + return var->index; + } + + return -1; } GLint GLAPIENTRY diff --git a/mesalib/src/mesa/main/shaderapi.c b/mesalib/src/mesa/main/shaderapi.c index 0e655a0d8..e0f20b638 100644 --- a/mesalib/src/mesa/main/shaderapi.c +++ b/mesalib/src/mesa/main/shaderapi.c @@ -1748,6 +1748,9 @@ _mesa_init_shader_dispatch(struct _glapi_table *exec) SET_ReleaseShaderCompiler(exec, _mesa_ReleaseShaderCompiler); SET_GetShaderPrecisionFormat(exec, _mesa_GetShaderPrecisionFormat); + /* GL_ARB_blend_func_extended */ + SET_BindFragDataLocationIndexed(exec, _mesa_BindFragDataLocationIndexed); + SET_GetFragDataIndex(exec, _mesa_GetFragDataIndex); #endif /* FEATURE_GL */ } diff --git a/mesalib/src/mesa/main/shaderapi.h b/mesalib/src/mesa/main/shaderapi.h index 0ffebdb07..4886959d5 100644 --- a/mesalib/src/mesa/main/shaderapi.h +++ b/mesalib/src/mesa/main/shaderapi.h @@ -86,6 +86,9 @@ _mesa_GetAttachedObjectsARB(GLhandleARB, GLsizei, GLsizei *, GLhandleARB *); extern GLint GLAPIENTRY _mesa_GetFragDataLocation(GLuint program, const GLchar *name); +extern GLint GLAPIENTRY +_mesa_GetFragDataIndex(GLuint program, const GLchar *name); + extern GLhandleARB GLAPIENTRY _mesa_GetHandleARB(GLenum pname); @@ -128,6 +131,10 @@ _mesa_BindFragDataLocation(GLuint program, GLuint colorNumber, const GLchar *name); extern void GLAPIENTRY +_mesa_BindFragDataLocationIndexed(GLuint program, GLuint colorNumber, + GLuint index, const GLchar *name); + +extern void GLAPIENTRY _mesa_GetActiveAttribARB(GLhandleARB, GLuint, GLsizei, GLsizei *, GLint *, GLenum *, GLcharARB *); diff --git a/mesalib/src/mesa/main/shaderobj.c b/mesalib/src/mesa/main/shaderobj.c index 36f208d6c..7eb6f0bda 100644 --- a/mesalib/src/mesa/main/shaderobj.c +++ b/mesalib/src/mesa/main/shaderobj.c @@ -242,6 +242,7 @@ _mesa_init_shader_program(struct gl_context *ctx, struct gl_shader_program *prog prog->AttributeBindings = string_to_uint_map_ctor(); prog->FragDataBindings = string_to_uint_map_ctor(); + prog->FragDataIndexBindings = string_to_uint_map_ctor(); #if FEATURE_ARB_geometry_shader4 prog->Geom.VerticesOut = 0; @@ -319,6 +320,11 @@ _mesa_free_shader_program_data(struct gl_context *ctx, shProg->FragDataBindings = NULL; } + if (shProg->FragDataIndexBindings) { + string_to_uint_map_dtor(shProg->FragDataIndexBindings); + shProg->FragDataIndexBindings = NULL; + } + /* detach shaders */ for (i = 0; i < shProg->NumShaders; i++) { _mesa_reference_shader(ctx, &shProg->Shaders[i], NULL); diff --git a/mesalib/src/mesa/state_tracker/st_atom_blend.c b/mesalib/src/mesa/state_tracker/st_atom_blend.c index 1ffc2f1b7..dea50af67 100644 --- a/mesalib/src/mesa/state_tracker/st_atom_blend.c +++ b/mesalib/src/mesa/state_tracker/st_atom_blend.c @@ -78,10 +78,10 @@ translate_blend(GLenum blend) return PIPE_BLENDFACTOR_CONST_COLOR; case GL_CONSTANT_ALPHA: return PIPE_BLENDFACTOR_CONST_ALPHA; - /* + case GL_SRC1_COLOR: return PIPE_BLENDFACTOR_SRC1_COLOR; + case GL_SRC1_ALPHA: return PIPE_BLENDFACTOR_SRC1_ALPHA; - */ case GL_ZERO: return PIPE_BLENDFACTOR_ZERO; case GL_ONE_MINUS_SRC_COLOR: @@ -96,10 +96,10 @@ translate_blend(GLenum blend) return PIPE_BLENDFACTOR_INV_CONST_COLOR; case GL_ONE_MINUS_CONSTANT_ALPHA: return PIPE_BLENDFACTOR_INV_CONST_ALPHA; - /* + case GL_ONE_MINUS_SRC1_COLOR: return PIPE_BLENDFACTOR_INV_SRC1_COLOR; + case GL_ONE_MINUS_SRC1_ALPHA: return PIPE_BLENDFACTOR_INV_SRC1_ALPHA; - */ default: assert("invalid GL token in translate_blend()" == NULL); return 0; diff --git a/mesalib/src/mesa/state_tracker/st_extensions.c b/mesalib/src/mesa/state_tracker/st_extensions.c index afea0ea4f..34e0329be 100644 --- a/mesalib/src/mesa/state_tracker/st_extensions.c +++ b/mesalib/src/mesa/state_tracker/st_extensions.c @@ -120,6 +120,10 @@ void st_init_limits(struct st_context *st) = _clamp(screen->get_param(screen, PIPE_CAP_MAX_RENDER_TARGETS), 1, MAX_DRAW_BUFFERS); + c->MaxDualSourceDrawBuffers + = _clamp(screen->get_param(screen, PIPE_CAP_MAX_DUAL_SOURCE_RENDER_TARGETS), + 0, MAX_DRAW_BUFFERS); + c->MaxLineWidth = _maxf(1.0f, screen->get_paramf(screen, PIPE_CAPF_MAX_LINE_WIDTH)); @@ -629,4 +633,7 @@ void st_init_extensions(struct st_context *st) break; } } + + if (ctx->Const.MaxDualSourceDrawBuffers > 0) + ctx->Extensions.ARB_blend_func_extended = GL_TRUE; } 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 ae8533e18..9e68deb34 100644 --- a/mesalib/src/mesa/state_tracker/st_glsl_to_tgsi.cpp +++ b/mesalib/src/mesa/state_tracker/st_glsl_to_tgsi.cpp @@ -1925,7 +1925,7 @@ glsl_to_tgsi_visitor::visit(ir_dereference_variable *ir) assert(var->location != -1); entry = new(mem_ctx) variable_storage(var, PROGRAM_OUTPUT, - var->location); + var->location + var->index); break; case ir_var_system_value: entry = new(mem_ctx) variable_storage(var, |