aboutsummaryrefslogtreecommitdiff
path: root/mesalib/src
diff options
context:
space:
mode:
Diffstat (limited to 'mesalib/src')
-rw-r--r--mesalib/src/gallium/auxiliary/Makefile.sources1
-rw-r--r--mesalib/src/gallium/auxiliary/hud/hud_driver_query.c5
-rw-r--r--mesalib/src/gallium/auxiliary/hud/hud_private.h2
-rw-r--r--mesalib/src/gallium/auxiliary/util/u_blitter.c1
-rw-r--r--mesalib/src/gallium/auxiliary/util/u_debug_flush.c2
-rw-r--r--mesalib/src/gallium/auxiliary/util/u_debug_memory.c2
-rw-r--r--mesalib/src/gallium/auxiliary/util/u_dirty_surfaces.h2
-rw-r--r--mesalib/src/glsl/Makefile.sources1
-rw-r--r--mesalib/src/glsl/ast_to_hir.cpp40
-rw-r--r--mesalib/src/glsl/ast_type.cpp10
-rw-r--r--mesalib/src/glsl/builtin_functions.cpp130
-rw-r--r--mesalib/src/glsl/builtin_types.cpp2
-rw-r--r--mesalib/src/glsl/builtin_variables.cpp37
-rw-r--r--mesalib/src/glsl/glcpp/glcpp-parse.y3
-rw-r--r--mesalib/src/glsl/glsl_lexer.ll2
-rw-r--r--mesalib/src/glsl/glsl_parser.yy36
-rw-r--r--mesalib/src/glsl/glsl_parser_extras.cpp24
-rw-r--r--mesalib/src/glsl/glsl_parser_extras.h42
-rw-r--r--mesalib/src/glsl/ir_set_program_inouts.cpp16
-rw-r--r--mesalib/src/glsl/link_uniform_blocks.cpp8
-rw-r--r--mesalib/src/glsl/link_uniforms.cpp6
-rw-r--r--mesalib/src/glsl/linker.cpp50
-rw-r--r--mesalib/src/glsl/nir/glsl_to_nir.cpp136
-rw-r--r--mesalib/src/glsl/nir/nir.c226
-rw-r--r--mesalib/src/glsl/nir/nir.h58
-rw-r--r--mesalib/src/glsl/nir/nir_builder.h6
-rw-r--r--mesalib/src/glsl/nir/nir_from_ssa.c150
-rw-r--r--mesalib/src/glsl/nir/nir_intrinsics.h34
-rw-r--r--mesalib/src/glsl/nir/nir_lower_atomics.c3
-rw-r--r--mesalib/src/glsl/nir/nir_lower_locals_to_regs.c14
-rw-r--r--mesalib/src/glsl/nir/nir_lower_samplers.cpp61
-rw-r--r--mesalib/src/glsl/nir/nir_lower_tex_projector.c12
-rw-r--r--mesalib/src/glsl/nir/nir_lower_to_source_mods.c20
-rw-r--r--mesalib/src/glsl/nir/nir_lower_vars_to_ssa.c3
-rw-r--r--mesalib/src/glsl/nir/nir_opcodes.py2
-rw-r--r--mesalib/src/glsl/nir/nir_opt_algebraic.py27
-rw-r--r--mesalib/src/glsl/nir/nir_opt_copy_propagate.c71
-rw-r--r--mesalib/src/glsl/nir/nir_opt_gcm.c14
-rw-r--r--mesalib/src/glsl/nir/nir_opt_global_to_local.c13
-rw-r--r--mesalib/src/glsl/nir/nir_opt_peephole_ffma.c9
-rw-r--r--mesalib/src/glsl/nir/nir_opt_peephole_select.c10
-rw-r--r--mesalib/src/glsl/nir/nir_search.c31
-rw-r--r--mesalib/src/glsl/nir/nir_to_ssa.c19
-rw-r--r--mesalib/src/glsl/nir/nir_validate.c160
-rw-r--r--mesalib/src/glsl/opt_dead_builtin_varyings.cpp10
-rw-r--r--mesalib/src/hgl/GLDispatcher.cpp5
-rw-r--r--mesalib/src/hgl/GLDispatcher.h4
-rw-r--r--mesalib/src/hgl/SConscript1
-rw-r--r--mesalib/src/loader/loader.h9
-rw-r--r--mesalib/src/mapi/glapi/gen/ARB_direct_state_access.xml225
-rw-r--r--mesalib/src/mapi/glapi/gen/ARB_framebuffer_object.xml2
-rw-r--r--mesalib/src/mapi/glapi/gen/ARB_vertex_attrib_64bit.xml70
-rw-r--r--mesalib/src/mapi/glapi/gen/Makefile.am1
-rw-r--r--mesalib/src/mapi/glapi/gen/gl_API.xml4
-rw-r--r--mesalib/src/mapi/glapi/gen/gl_genexec.py4
-rw-r--r--mesalib/src/mapi/glapi/glapi_priv.h8
-rw-r--r--mesalib/src/mesa/Makefile.sources2
-rw-r--r--mesalib/src/mesa/drivers/common/driverfuncs.c2
-rw-r--r--mesalib/src/mesa/drivers/common/meta.c3
-rw-r--r--mesalib/src/mesa/drivers/dri/swrast/swrast.c17
-rw-r--r--mesalib/src/mesa/main/api_arrayelt.c79
-rw-r--r--mesalib/src/mesa/main/api_loopback.c60
-rw-r--r--mesalib/src/mesa/main/api_loopback.h16
-rw-r--r--mesalib/src/mesa/main/arrayobj.c192
-rw-r--r--mesalib/src/mesa/main/arrayobj.h9
-rw-r--r--mesalib/src/mesa/main/blend.c37
-rw-r--r--mesalib/src/mesa/main/blend.h16
-rw-r--r--mesalib/src/mesa/main/blit.c219
-rw-r--r--mesalib/src/mesa/main/blit.h13
-rw-r--r--mesalib/src/mesa/main/bufferobj.c105
-rw-r--r--mesalib/src/mesa/main/buffers.c261
-rw-r--r--mesalib/src/mesa/main/buffers.h29
-rw-r--r--mesalib/src/mesa/main/clear.c106
-rw-r--r--mesalib/src/mesa/main/clear.h16
-rw-r--r--mesalib/src/mesa/main/compute.c20
-rw-r--r--mesalib/src/mesa/main/context.c7
-rw-r--r--mesalib/src/mesa/main/context.h20
-rw-r--r--mesalib/src/mesa/main/dd.h20
-rw-r--r--mesalib/src/mesa/main/extensions.c3
-rw-r--r--mesalib/src/mesa/main/fbobject.c1308
-rw-r--r--mesalib/src/mesa/main/fbobject.h81
-rw-r--r--mesalib/src/mesa/main/ffvertex_prog.c2
-rw-r--r--mesalib/src/mesa/main/framebuffer.c23
-rw-r--r--mesalib/src/mesa/main/framebuffer.h7
-rw-r--r--mesalib/src/mesa/main/genmipmap.c7
-rw-r--r--mesalib/src/mesa/main/get.c9
-rw-r--r--mesalib/src/mesa/main/mtypes.h17
-rw-r--r--mesalib/src/mesa/main/pipelineobj.c6
-rw-r--r--mesalib/src/mesa/main/queryobj.c19
-rw-r--r--mesalib/src/mesa/main/readpix.c4
-rw-r--r--mesalib/src/mesa/main/samplerobj.c7
-rw-r--r--mesalib/src/mesa/main/shader_query.cpp24
-rw-r--r--mesalib/src/mesa/main/shaderimage.c130
-rw-r--r--mesalib/src/mesa/main/shaderimage.h21
-rw-r--r--mesalib/src/mesa/main/state.c25
-rw-r--r--mesalib/src/mesa/main/texenv.c2
-rw-r--r--mesalib/src/mesa/main/texgetimage.c14
-rw-r--r--mesalib/src/mesa/main/teximage.c74
-rw-r--r--mesalib/src/mesa/main/texobj.c14
-rw-r--r--mesalib/src/mesa/main/texparam.c86
-rw-r--r--mesalib/src/mesa/main/texstorage.c7
-rw-r--r--mesalib/src/mesa/main/transformfeedback.c42
-rw-r--r--mesalib/src/mesa/main/uniform_query.cpp4
-rw-r--r--mesalib/src/mesa/main/varray.c857
-rw-r--r--mesalib/src/mesa/main/varray.h55
-rw-r--r--mesalib/src/mesa/main/version.c332
-rw-r--r--mesalib/src/mesa/main/vtxfmt.c12
-rw-r--r--mesalib/src/mesa/program/prog_statevars.c4
-rw-r--r--mesalib/src/mesa/program/prog_to_nir.c2
-rw-r--r--mesalib/src/mesa/program/program.c3
-rw-r--r--mesalib/src/mesa/program/program.h22
-rw-r--r--mesalib/src/mesa/state_tracker/st_atom_array.c172
-rw-r--r--mesalib/src/mesa/state_tracker/st_atom_framebuffer.c5
-rw-r--r--mesalib/src/mesa/state_tracker/st_cb_fbo.c2
-rw-r--r--mesalib/src/mesa/state_tracker/st_cb_flush.c35
-rw-r--r--mesalib/src/mesa/state_tracker/st_cb_flush.h3
-rw-r--r--mesalib/src/mesa/state_tracker/st_cb_perfmon.c425
-rw-r--r--mesalib/src/mesa/state_tracker/st_cb_perfmon.h64
-rw-r--r--mesalib/src/mesa/state_tracker/st_context.c16
-rw-r--r--mesalib/src/mesa/state_tracker/st_context.h3
-rw-r--r--mesalib/src/mesa/state_tracker/st_extensions.c10
-rw-r--r--mesalib/src/mesa/state_tracker/st_format.c2
-rw-r--r--mesalib/src/mesa/state_tracker/st_glsl_to_tgsi.cpp30
-rw-r--r--mesalib/src/mesa/state_tracker/st_manager.c4
-rw-r--r--mesalib/src/mesa/state_tracker/st_program.c5
-rw-r--r--mesalib/src/mesa/state_tracker/st_program.h1
-rw-r--r--mesalib/src/mesa/swrast/s_drawpix.c29
-rw-r--r--mesalib/src/mesa/swrast/s_texrender.c2
-rw-r--r--mesalib/src/mesa/vbo/vbo_attrib_tmp.h119
-rw-r--r--mesalib/src/mesa/vbo/vbo_context.h17
-rw-r--r--mesalib/src/mesa/vbo/vbo_exec_api.c83
-rw-r--r--mesalib/src/mesa/vbo/vbo_save_api.c14
-rw-r--r--mesalib/src/mesa/vbo/vbo_split_copy.c1
-rw-r--r--mesalib/src/util/Makefile.sources1
-rw-r--r--mesalib/src/util/list.h (renamed from mesalib/src/gallium/auxiliary/util/u_double_list.h)93
135 files changed, 5744 insertions, 1708 deletions
diff --git a/mesalib/src/gallium/auxiliary/Makefile.sources b/mesalib/src/gallium/auxiliary/Makefile.sources
index ec7547cad..62e6b94ca 100644
--- a/mesalib/src/gallium/auxiliary/Makefile.sources
+++ b/mesalib/src/gallium/auxiliary/Makefile.sources
@@ -197,7 +197,6 @@ C_SOURCES := \
util/u_dirty_surfaces.h \
util/u_dl.c \
util/u_dl.h \
- util/u_double_list.h \
util/u_draw.c \
util/u_draw.h \
util/u_draw_quad.c \
diff --git a/mesalib/src/gallium/auxiliary/hud/hud_driver_query.c b/mesalib/src/gallium/auxiliary/hud/hud_driver_query.c
index 53771fcae..603aba7e8 100644
--- a/mesalib/src/gallium/auxiliary/hud/hud_driver_query.c
+++ b/mesalib/src/gallium/auxiliary/hud/hud_driver_query.c
@@ -187,6 +187,7 @@ hud_driver_query_install(struct hud_pane *pane, struct pipe_context *pipe,
struct pipe_screen *screen = pipe->screen;
struct pipe_driver_query_info query;
unsigned num_queries, i;
+ boolean uses_byte_units;
boolean found = FALSE;
if (!screen->get_driver_query_info)
@@ -205,7 +206,9 @@ hud_driver_query_install(struct hud_pane *pane, struct pipe_context *pipe,
if (!found)
return FALSE;
+ uses_byte_units = query.type == PIPE_DRIVER_QUERY_TYPE_BYTES;
hud_pipe_query_install(pane, pipe, query.name, query.query_type, 0,
- query.max_value, query.uses_byte_units);
+ query.max_value.u64, uses_byte_units);
+
return TRUE;
}
diff --git a/mesalib/src/gallium/auxiliary/hud/hud_private.h b/mesalib/src/gallium/auxiliary/hud/hud_private.h
index 230f02664..632926b87 100644
--- a/mesalib/src/gallium/auxiliary/hud/hud_private.h
+++ b/mesalib/src/gallium/auxiliary/hud/hud_private.h
@@ -29,7 +29,7 @@
#define HUD_PRIVATE_H
#include "pipe/p_context.h"
-#include "util/u_double_list.h"
+#include "util/list.h"
struct hud_graph {
/* initialized by common code */
diff --git a/mesalib/src/gallium/auxiliary/util/u_blitter.c b/mesalib/src/gallium/auxiliary/util/u_blitter.c
index 9d087fe8a..24a5b93e1 100644
--- a/mesalib/src/gallium/auxiliary/util/u_blitter.c
+++ b/mesalib/src/gallium/auxiliary/util/u_blitter.c
@@ -1306,6 +1306,7 @@ void util_blitter_default_src_texture(struct pipe_sampler_view *src_templ,
unsigned srclevel)
{
memset(src_templ, 0, sizeof(*src_templ));
+ src_templ->target = src->target;
src_templ->format = util_format_linear(src->format);
src_templ->u.tex.first_level = srclevel;
src_templ->u.tex.last_level = srclevel;
diff --git a/mesalib/src/gallium/auxiliary/util/u_debug_flush.c b/mesalib/src/gallium/auxiliary/util/u_debug_flush.c
index cdefca2fb..52e72cd6d 100644
--- a/mesalib/src/gallium/auxiliary/util/u_debug_flush.c
+++ b/mesalib/src/gallium/auxiliary/util/u_debug_flush.c
@@ -44,7 +44,7 @@
#include "util/u_memory.h"
#include "util/u_debug_flush.h"
#include "util/u_hash_table.h"
-#include "util/u_double_list.h"
+#include "util/list.h"
#include "util/u_inlines.h"
#include "util/u_string.h"
#include "os/os_thread.h"
diff --git a/mesalib/src/gallium/auxiliary/util/u_debug_memory.c b/mesalib/src/gallium/auxiliary/util/u_debug_memory.c
index 1ad0e7220..747837cd1 100644
--- a/mesalib/src/gallium/auxiliary/util/u_debug_memory.c
+++ b/mesalib/src/gallium/auxiliary/util/u_debug_memory.c
@@ -42,7 +42,7 @@
#include "util/u_debug.h"
#include "util/u_debug_stack.h"
-#include "util/u_double_list.h"
+#include "util/list.h"
#define DEBUG_MEMORY_MAGIC 0x6e34090aU
diff --git a/mesalib/src/gallium/auxiliary/util/u_dirty_surfaces.h b/mesalib/src/gallium/auxiliary/util/u_dirty_surfaces.h
index f3618d9be..d31f8b917 100644
--- a/mesalib/src/gallium/auxiliary/util/u_dirty_surfaces.h
+++ b/mesalib/src/gallium/auxiliary/util/u_dirty_surfaces.h
@@ -29,7 +29,7 @@
#include "pipe/p_state.h"
-#include "util/u_double_list.h"
+#include "util/list.h"
#include "util/u_math.h"
struct pipe_context;
diff --git a/mesalib/src/glsl/Makefile.sources b/mesalib/src/glsl/Makefile.sources
index c471eca23..d784a8107 100644
--- a/mesalib/src/glsl/Makefile.sources
+++ b/mesalib/src/glsl/Makefile.sources
@@ -22,6 +22,7 @@ NIR_FILES = \
nir/glsl_to_nir.h \
nir/nir.c \
nir/nir.h \
+ nir/nir_array.h \
nir/nir_builder.h \
nir/nir_constant_expressions.h \
nir/nir_dominance.c \
diff --git a/mesalib/src/glsl/ast_to_hir.cpp b/mesalib/src/glsl/ast_to_hir.cpp
index 18b82e3be..14e630905 100644
--- a/mesalib/src/glsl/ast_to_hir.cpp
+++ b/mesalib/src/glsl/ast_to_hir.cpp
@@ -1558,6 +1558,18 @@ ast_expression::do_hir(exec_list *instructions,
error_emitted = true;
}
+ /* From section 4.1.7 of the GLSL 4.50 spec (Opaque Types):
+ *
+ * "Except for array indexing, structure member selection, and
+ * parentheses, opaque variables are not allowed to be operands in
+ * expressions; such use results in a compile-time error."
+ */
+ if (type->contains_opaque()) {
+ _mesa_glsl_error(&loc, state, "opaque variables cannot be operands "
+ "of the ?: operator");
+ error_emitted = true;
+ }
+
ir_constant *cond_val = op[0]->constant_expression_value();
if (then_instructions.is_empty()
@@ -2357,6 +2369,14 @@ apply_image_qualifier_to_variable(const struct ast_type_qualifier *qual,
var->data.image_format = GL_NONE;
}
+ } else if (qual->flags.q.read_only ||
+ qual->flags.q.write_only ||
+ qual->flags.q.coherent ||
+ qual->flags.q._volatile ||
+ qual->flags.q.restrict_flag ||
+ qual->flags.q.explicit_image_format) {
+ _mesa_glsl_error(loc, state, "memory qualifiers may only be applied to "
+ "images");
}
}
@@ -2781,8 +2801,21 @@ apply_type_qualifier_to_variable(const struct ast_type_qualifier *qual,
validate_matrix_layout_for_type(state, loc, var->type, var);
}
- if (var->type->contains_image())
- apply_image_qualifier_to_variable(qual, var, state, loc);
+ apply_image_qualifier_to_variable(qual, var, state, loc);
+
+ /* From section 4.4.1.3 of the GLSL 4.50 specification (Fragment Shader
+ * Inputs):
+ *
+ * "Fragment shaders also allow the following layout qualifier on in only
+ * (not with variable declarations)
+ * layout-qualifier-id
+ * early_fragment_tests
+ * [...]"
+ */
+ if (qual->flags.q.early_fragment_tests) {
+ _mesa_glsl_error(loc, state, "early_fragment_tests layout qualifier only "
+ "valid in fragment shader input layout declaration.");
+ }
}
/**
@@ -3541,6 +3574,9 @@ ast_declarator_list::hir(exec_list *instructions,
case GLSL_TYPE_INT:
if (state->is_version(120, 300))
break;
+ case GLSL_TYPE_DOUBLE:
+ if (check_type->base_type == GLSL_TYPE_DOUBLE && (state->is_version(410, 0) || state->ARB_vertex_attrib_64bit_enable))
+ break;
/* FALLTHROUGH */
default:
_mesa_glsl_error(& loc, state,
diff --git a/mesalib/src/glsl/ast_type.cpp b/mesalib/src/glsl/ast_type.cpp
index b596cd59e..1bcf6a2e8 100644
--- a/mesalib/src/glsl/ast_type.cpp
+++ b/mesalib/src/glsl/ast_type.cpp
@@ -293,11 +293,7 @@ ast_type_qualifier::merge_in_qualifier(YYLTYPE *loc,
valid_in_mask.flags.q.invocations = 1;
break;
case MESA_SHADER_FRAGMENT:
- if (q.flags.q.early_fragment_tests) {
- state->early_fragment_tests = true;
- } else {
- _mesa_glsl_error(loc, state, "invalid input layout qualifier");
- }
+ valid_in_mask.flags.q.early_fragment_tests = 1;
break;
case MESA_SHADER_COMPUTE:
create_cs_ast |=
@@ -345,6 +341,10 @@ ast_type_qualifier::merge_in_qualifier(YYLTYPE *loc,
this->invocations = q.invocations;
}
+ if (q.flags.q.early_fragment_tests) {
+ state->fs_early_fragment_tests = true;
+ }
+
if (create_gs_ast) {
node = new(mem_ctx) ast_gs_input_layout(*loc, q.prim_type);
} else if (create_cs_ast) {
diff --git a/mesalib/src/glsl/builtin_functions.cpp b/mesalib/src/glsl/builtin_functions.cpp
index 524b8d6e8..97055d85d 100644
--- a/mesalib/src/glsl/builtin_functions.cpp
+++ b/mesalib/src/glsl/builtin_functions.cpp
@@ -136,6 +136,12 @@ v140(const _mesa_glsl_parse_state *state)
}
static bool
+es31(const _mesa_glsl_parse_state *state)
+{
+ return state->is_version(0, 310);
+}
+
+static bool
texture_rectangle(const _mesa_glsl_parse_state *state)
{
return state->ARB_texture_rectangle_enable;
@@ -194,7 +200,8 @@ shader_bit_encoding(const _mesa_glsl_parse_state *state)
static bool
shader_integer_mix(const _mesa_glsl_parse_state *state)
{
- return v130(state) && state->EXT_shader_integer_mix_enable;
+ return state->is_version(450, 310) ||
+ (v130(state) && state->EXT_shader_integer_mix_enable);
}
static bool
@@ -219,10 +226,17 @@ gpu_shader5(const _mesa_glsl_parse_state *state)
}
static bool
-shader_packing_or_gpu_shader5(const _mesa_glsl_parse_state *state)
+gpu_shader5_or_es31(const _mesa_glsl_parse_state *state)
+{
+ return state->is_version(400, 310) || state->ARB_gpu_shader5_enable;
+}
+
+static bool
+shader_packing_or_es31_or_gpu_shader5(const _mesa_glsl_parse_state *state)
{
return state->ARB_shading_language_packing_enable ||
- gpu_shader5(state);
+ state->ARB_gpu_shader5_enable ||
+ state->is_version(400, 310);
}
static bool
@@ -297,15 +311,24 @@ texture_gather(const _mesa_glsl_parse_state *state)
state->ARB_gpu_shader5_enable;
}
+static bool
+texture_gather_or_es31(const _mesa_glsl_parse_state *state)
+{
+ return state->is_version(400, 310) ||
+ state->ARB_texture_gather_enable ||
+ state->ARB_gpu_shader5_enable;
+}
+
/* Only ARB_texture_gather but not GLSL 4.0 or ARB_gpu_shader5.
* used for relaxation of const offset requirements.
*/
static bool
-texture_gather_only(const _mesa_glsl_parse_state *state)
+texture_gather_only_or_es31(const _mesa_glsl_parse_state *state)
{
return !state->is_version(400, 0) &&
!state->ARB_gpu_shader5_enable &&
- state->ARB_texture_gather_enable;
+ (state->ARB_texture_gather_enable ||
+ state->is_version(0, 310));
}
/* Desktop GL or OES_standard_derivatives + fragment shader only */
@@ -359,7 +382,7 @@ tex3d_lod(const _mesa_glsl_parse_state *state)
static bool
shader_atomic_counters(const _mesa_glsl_parse_state *state)
{
- return state->ARB_shader_atomic_counters_enable;
+ return state->has_atomic_counters();
}
static bool
@@ -1161,12 +1184,12 @@ builtin_builder::create_builtins()
add_function("packUnorm2x16", _packUnorm2x16(shader_packing_or_es3_or_gpu_shader5), NULL);
add_function("packSnorm2x16", _packSnorm2x16(shader_packing_or_es3), NULL);
- add_function("packUnorm4x8", _packUnorm4x8(shader_packing_or_gpu_shader5), NULL);
- add_function("packSnorm4x8", _packSnorm4x8(shader_packing_or_gpu_shader5), NULL);
+ add_function("packUnorm4x8", _packUnorm4x8(shader_packing_or_es31_or_gpu_shader5), NULL);
+ add_function("packSnorm4x8", _packSnorm4x8(shader_packing_or_es31_or_gpu_shader5), NULL);
add_function("unpackUnorm2x16", _unpackUnorm2x16(shader_packing_or_es3_or_gpu_shader5), NULL);
add_function("unpackSnorm2x16", _unpackSnorm2x16(shader_packing_or_es3), NULL);
- add_function("unpackUnorm4x8", _unpackUnorm4x8(shader_packing_or_gpu_shader5), NULL);
- add_function("unpackSnorm4x8", _unpackSnorm4x8(shader_packing_or_gpu_shader5), NULL);
+ add_function("unpackUnorm4x8", _unpackUnorm4x8(shader_packing_or_es31_or_gpu_shader5), NULL);
+ add_function("unpackSnorm4x8", _unpackSnorm4x8(shader_packing_or_es31_or_gpu_shader5), NULL);
add_function("packHalf2x16", _packHalf2x16(shader_packing_or_es3), NULL);
add_function("unpackHalf2x16", _unpackHalf2x16(shader_packing_or_es3), NULL);
add_function("packDouble2x32", _packDouble2x32(fp64), NULL);
@@ -2202,61 +2225,69 @@ builtin_builder::create_builtins()
NULL);
add_function("textureGather",
- _texture(ir_tg4, texture_gather, glsl_type::vec4_type, glsl_type::sampler2D_type, glsl_type::vec2_type),
- _texture(ir_tg4, texture_gather, glsl_type::ivec4_type, glsl_type::isampler2D_type, glsl_type::vec2_type),
- _texture(ir_tg4, texture_gather, glsl_type::uvec4_type, glsl_type::usampler2D_type, glsl_type::vec2_type),
+ _texture(ir_tg4, texture_gather_or_es31, glsl_type::vec4_type, glsl_type::sampler2D_type, glsl_type::vec2_type),
+ _texture(ir_tg4, texture_gather_or_es31, glsl_type::ivec4_type, glsl_type::isampler2D_type, glsl_type::vec2_type),
+ _texture(ir_tg4, texture_gather_or_es31, glsl_type::uvec4_type, glsl_type::usampler2D_type, glsl_type::vec2_type),
_texture(ir_tg4, gpu_shader5, glsl_type::vec4_type, glsl_type::sampler2DRect_type, glsl_type::vec2_type),
_texture(ir_tg4, gpu_shader5, glsl_type::ivec4_type, glsl_type::isampler2DRect_type, glsl_type::vec2_type),
_texture(ir_tg4, gpu_shader5, glsl_type::uvec4_type, glsl_type::usampler2DRect_type, glsl_type::vec2_type),
- _texture(ir_tg4, texture_gather, glsl_type::vec4_type, glsl_type::sampler2DArray_type, glsl_type::vec3_type),
- _texture(ir_tg4, texture_gather, glsl_type::ivec4_type, glsl_type::isampler2DArray_type, glsl_type::vec3_type),
- _texture(ir_tg4, texture_gather, glsl_type::uvec4_type, glsl_type::usampler2DArray_type, glsl_type::vec3_type),
+ _texture(ir_tg4, texture_gather_or_es31, glsl_type::vec4_type, glsl_type::sampler2DArray_type, glsl_type::vec3_type),
+ _texture(ir_tg4, texture_gather_or_es31, glsl_type::ivec4_type, glsl_type::isampler2DArray_type, glsl_type::vec3_type),
+ _texture(ir_tg4, texture_gather_or_es31, glsl_type::uvec4_type, glsl_type::usampler2DArray_type, glsl_type::vec3_type),
- _texture(ir_tg4, texture_gather, glsl_type::vec4_type, glsl_type::samplerCube_type, glsl_type::vec3_type),
- _texture(ir_tg4, texture_gather, glsl_type::ivec4_type, glsl_type::isamplerCube_type, glsl_type::vec3_type),
- _texture(ir_tg4, texture_gather, glsl_type::uvec4_type, glsl_type::usamplerCube_type, glsl_type::vec3_type),
+ _texture(ir_tg4, texture_gather_or_es31, glsl_type::vec4_type, glsl_type::samplerCube_type, glsl_type::vec3_type),
+ _texture(ir_tg4, texture_gather_or_es31, glsl_type::ivec4_type, glsl_type::isamplerCube_type, glsl_type::vec3_type),
+ _texture(ir_tg4, texture_gather_or_es31, glsl_type::uvec4_type, glsl_type::usamplerCube_type, glsl_type::vec3_type),
_texture(ir_tg4, texture_gather, glsl_type::vec4_type, glsl_type::samplerCubeArray_type, glsl_type::vec4_type),
_texture(ir_tg4, texture_gather, glsl_type::ivec4_type, glsl_type::isamplerCubeArray_type, glsl_type::vec4_type),
_texture(ir_tg4, texture_gather, glsl_type::uvec4_type, glsl_type::usamplerCubeArray_type, glsl_type::vec4_type),
- _texture(ir_tg4, gpu_shader5, glsl_type::vec4_type, glsl_type::sampler2D_type, glsl_type::vec2_type, TEX_COMPONENT),
- _texture(ir_tg4, gpu_shader5, glsl_type::ivec4_type, glsl_type::isampler2D_type, glsl_type::vec2_type, TEX_COMPONENT),
- _texture(ir_tg4, gpu_shader5, glsl_type::uvec4_type, glsl_type::usampler2D_type, glsl_type::vec2_type, TEX_COMPONENT),
+ _texture(ir_tg4, gpu_shader5_or_es31, glsl_type::vec4_type, glsl_type::sampler2D_type, glsl_type::vec2_type, TEX_COMPONENT),
+ _texture(ir_tg4, gpu_shader5_or_es31, glsl_type::ivec4_type, glsl_type::isampler2D_type, glsl_type::vec2_type, TEX_COMPONENT),
+ _texture(ir_tg4, gpu_shader5_or_es31, glsl_type::uvec4_type, glsl_type::usampler2D_type, glsl_type::vec2_type, TEX_COMPONENT),
_texture(ir_tg4, gpu_shader5, glsl_type::vec4_type, glsl_type::sampler2DRect_type, glsl_type::vec2_type, TEX_COMPONENT),
_texture(ir_tg4, gpu_shader5, glsl_type::ivec4_type, glsl_type::isampler2DRect_type, glsl_type::vec2_type, TEX_COMPONENT),
_texture(ir_tg4, gpu_shader5, glsl_type::uvec4_type, glsl_type::usampler2DRect_type, glsl_type::vec2_type, TEX_COMPONENT),
- _texture(ir_tg4, gpu_shader5, glsl_type::vec4_type, glsl_type::sampler2DArray_type, glsl_type::vec3_type, TEX_COMPONENT),
- _texture(ir_tg4, gpu_shader5, glsl_type::ivec4_type, glsl_type::isampler2DArray_type, glsl_type::vec3_type, TEX_COMPONENT),
- _texture(ir_tg4, gpu_shader5, glsl_type::uvec4_type, glsl_type::usampler2DArray_type, glsl_type::vec3_type, TEX_COMPONENT),
+ _texture(ir_tg4, gpu_shader5_or_es31, glsl_type::vec4_type, glsl_type::sampler2DArray_type, glsl_type::vec3_type, TEX_COMPONENT),
+ _texture(ir_tg4, gpu_shader5_or_es31, glsl_type::ivec4_type, glsl_type::isampler2DArray_type, glsl_type::vec3_type, TEX_COMPONENT),
+ _texture(ir_tg4, gpu_shader5_or_es31, glsl_type::uvec4_type, glsl_type::usampler2DArray_type, glsl_type::vec3_type, TEX_COMPONENT),
- _texture(ir_tg4, gpu_shader5, glsl_type::vec4_type, glsl_type::samplerCube_type, glsl_type::vec3_type, TEX_COMPONENT),
- _texture(ir_tg4, gpu_shader5, glsl_type::ivec4_type, glsl_type::isamplerCube_type, glsl_type::vec3_type, TEX_COMPONENT),
- _texture(ir_tg4, gpu_shader5, glsl_type::uvec4_type, glsl_type::usamplerCube_type, glsl_type::vec3_type, TEX_COMPONENT),
+ _texture(ir_tg4, gpu_shader5_or_es31, glsl_type::vec4_type, glsl_type::samplerCube_type, glsl_type::vec3_type, TEX_COMPONENT),
+ _texture(ir_tg4, gpu_shader5_or_es31, glsl_type::ivec4_type, glsl_type::isamplerCube_type, glsl_type::vec3_type, TEX_COMPONENT),
+ _texture(ir_tg4, gpu_shader5_or_es31, glsl_type::uvec4_type, glsl_type::usamplerCube_type, glsl_type::vec3_type, TEX_COMPONENT),
_texture(ir_tg4, gpu_shader5, glsl_type::vec4_type, glsl_type::samplerCubeArray_type, glsl_type::vec4_type, TEX_COMPONENT),
_texture(ir_tg4, gpu_shader5, glsl_type::ivec4_type, glsl_type::isamplerCubeArray_type, glsl_type::vec4_type, TEX_COMPONENT),
_texture(ir_tg4, gpu_shader5, glsl_type::uvec4_type, glsl_type::usamplerCubeArray_type, glsl_type::vec4_type, TEX_COMPONENT),
- _texture(ir_tg4, gpu_shader5, glsl_type::vec4_type, glsl_type::sampler2DShadow_type, glsl_type::vec2_type),
- _texture(ir_tg4, gpu_shader5, glsl_type::vec4_type, glsl_type::sampler2DArrayShadow_type, glsl_type::vec3_type),
- _texture(ir_tg4, gpu_shader5, glsl_type::vec4_type, glsl_type::samplerCubeShadow_type, glsl_type::vec3_type),
+ _texture(ir_tg4, gpu_shader5_or_es31, glsl_type::vec4_type, glsl_type::sampler2DShadow_type, glsl_type::vec2_type),
+ _texture(ir_tg4, gpu_shader5_or_es31, glsl_type::vec4_type, glsl_type::sampler2DArrayShadow_type, glsl_type::vec3_type),
+ _texture(ir_tg4, gpu_shader5_or_es31, glsl_type::vec4_type, glsl_type::samplerCubeShadow_type, glsl_type::vec3_type),
_texture(ir_tg4, gpu_shader5, glsl_type::vec4_type, glsl_type::samplerCubeArrayShadow_type, glsl_type::vec4_type),
_texture(ir_tg4, gpu_shader5, glsl_type::vec4_type, glsl_type::sampler2DRectShadow_type, glsl_type::vec2_type),
NULL);
add_function("textureGatherOffset",
- _texture(ir_tg4, texture_gather_only, glsl_type::vec4_type, glsl_type::sampler2D_type, glsl_type::vec2_type, TEX_OFFSET),
- _texture(ir_tg4, texture_gather_only, glsl_type::ivec4_type, glsl_type::isampler2D_type, glsl_type::vec2_type, TEX_OFFSET),
- _texture(ir_tg4, texture_gather_only, glsl_type::uvec4_type, glsl_type::usampler2D_type, glsl_type::vec2_type, TEX_OFFSET),
+ _texture(ir_tg4, texture_gather_only_or_es31, glsl_type::vec4_type, glsl_type::sampler2D_type, glsl_type::vec2_type, TEX_OFFSET),
+ _texture(ir_tg4, texture_gather_only_or_es31, glsl_type::ivec4_type, glsl_type::isampler2D_type, glsl_type::vec2_type, TEX_OFFSET),
+ _texture(ir_tg4, texture_gather_only_or_es31, glsl_type::uvec4_type, glsl_type::usampler2D_type, glsl_type::vec2_type, TEX_OFFSET),
+
+ _texture(ir_tg4, texture_gather_only_or_es31, glsl_type::vec4_type, glsl_type::sampler2DArray_type, glsl_type::vec3_type, TEX_OFFSET),
+ _texture(ir_tg4, texture_gather_only_or_es31, glsl_type::ivec4_type, glsl_type::isampler2DArray_type, glsl_type::vec3_type, TEX_OFFSET),
+ _texture(ir_tg4, texture_gather_only_or_es31, glsl_type::uvec4_type, glsl_type::usampler2DArray_type, glsl_type::vec3_type, TEX_OFFSET),
- _texture(ir_tg4, texture_gather_only, glsl_type::vec4_type, glsl_type::sampler2DArray_type, glsl_type::vec3_type, TEX_OFFSET),
- _texture(ir_tg4, texture_gather_only, glsl_type::ivec4_type, glsl_type::isampler2DArray_type, glsl_type::vec3_type, TEX_OFFSET),
- _texture(ir_tg4, texture_gather_only, glsl_type::uvec4_type, glsl_type::usampler2DArray_type, glsl_type::vec3_type, TEX_OFFSET),
+ _texture(ir_tg4, es31, glsl_type::vec4_type, glsl_type::sampler2D_type, glsl_type::vec2_type, TEX_OFFSET | TEX_COMPONENT),
+ _texture(ir_tg4, es31, glsl_type::ivec4_type, glsl_type::isampler2D_type, glsl_type::vec2_type, TEX_OFFSET | TEX_COMPONENT),
+ _texture(ir_tg4, es31, glsl_type::uvec4_type, glsl_type::usampler2D_type, glsl_type::vec2_type, TEX_OFFSET | TEX_COMPONENT),
+
+ _texture(ir_tg4, es31, glsl_type::vec4_type, glsl_type::sampler2DArray_type, glsl_type::vec3_type, TEX_OFFSET | TEX_COMPONENT),
+ _texture(ir_tg4, es31, glsl_type::ivec4_type, glsl_type::isampler2DArray_type, glsl_type::vec3_type, TEX_OFFSET | TEX_COMPONENT),
+ _texture(ir_tg4, es31, glsl_type::uvec4_type, glsl_type::usampler2DArray_type, glsl_type::vec3_type, TEX_OFFSET | TEX_COMPONENT),
_texture(ir_tg4, gpu_shader5, glsl_type::vec4_type, glsl_type::sampler2D_type, glsl_type::vec2_type, TEX_OFFSET_NONCONST),
_texture(ir_tg4, gpu_shader5, glsl_type::ivec4_type, glsl_type::isampler2D_type, glsl_type::vec2_type, TEX_OFFSET_NONCONST),
@@ -2285,6 +2316,9 @@ builtin_builder::create_builtins()
_texture(ir_tg4, gpu_shader5, glsl_type::vec4_type, glsl_type::sampler2DShadow_type, glsl_type::vec2_type, TEX_OFFSET_NONCONST),
_texture(ir_tg4, gpu_shader5, glsl_type::vec4_type, glsl_type::sampler2DArrayShadow_type, glsl_type::vec3_type, TEX_OFFSET_NONCONST),
_texture(ir_tg4, gpu_shader5, glsl_type::vec4_type, glsl_type::sampler2DRectShadow_type, glsl_type::vec2_type, TEX_OFFSET_NONCONST),
+
+ _texture(ir_tg4, es31, glsl_type::vec4_type, glsl_type::sampler2DShadow_type, glsl_type::vec2_type, TEX_OFFSET),
+ _texture(ir_tg4, es31, glsl_type::vec4_type, glsl_type::sampler2DArrayShadow_type, glsl_type::vec3_type, TEX_OFFSET),
NULL);
add_function("textureGatherOffsets",
@@ -4445,7 +4479,7 @@ builtin_builder::_bitfieldExtract(const glsl_type *type)
ir_variable *value = in_var(type, "value");
ir_variable *offset = in_var(glsl_type::int_type, "offset");
ir_variable *bits = in_var(glsl_type::int_type, "bits");
- MAKE_SIG(type, gpu_shader5, 3, value, offset, bits);
+ MAKE_SIG(type, gpu_shader5_or_es31, 3, value, offset, bits);
body.emit(ret(expr(ir_triop_bitfield_extract, value, offset, bits)));
@@ -4459,33 +4493,33 @@ builtin_builder::_bitfieldInsert(const glsl_type *type)
ir_variable *insert = in_var(type, "insert");
ir_variable *offset = in_var(glsl_type::int_type, "offset");
ir_variable *bits = in_var(glsl_type::int_type, "bits");
- MAKE_SIG(type, gpu_shader5, 4, base, insert, offset, bits);
+ MAKE_SIG(type, gpu_shader5_or_es31, 4, base, insert, offset, bits);
body.emit(ret(bitfield_insert(base, insert, offset, bits)));
return sig;
}
-UNOP(bitfieldReverse, ir_unop_bitfield_reverse, gpu_shader5)
+UNOP(bitfieldReverse, ir_unop_bitfield_reverse, gpu_shader5_or_es31)
ir_function_signature *
builtin_builder::_bitCount(const glsl_type *type)
{
- return unop(gpu_shader5, ir_unop_bit_count,
+ return unop(gpu_shader5_or_es31, ir_unop_bit_count,
glsl_type::ivec(type->vector_elements), type);
}
ir_function_signature *
builtin_builder::_findLSB(const glsl_type *type)
{
- return unop(gpu_shader5, ir_unop_find_lsb,
+ return unop(gpu_shader5_or_es31, ir_unop_find_lsb,
glsl_type::ivec(type->vector_elements), type);
}
ir_function_signature *
builtin_builder::_findMSB(const glsl_type *type)
{
- return unop(gpu_shader5, ir_unop_find_msb,
+ return unop(gpu_shader5_or_es31, ir_unop_find_msb,
glsl_type::ivec(type->vector_elements), type);
}
@@ -4505,7 +4539,7 @@ builtin_builder::_fma(builtin_available_predicate avail, const glsl_type *type)
ir_function_signature *
builtin_builder::_ldexp(const glsl_type *x_type, const glsl_type *exp_type)
{
- return binop(ir_binop_ldexp, x_type->base_type == GLSL_TYPE_DOUBLE ? fp64 : gpu_shader5, x_type, x_type, exp_type);
+ return binop(ir_binop_ldexp, x_type->base_type == GLSL_TYPE_DOUBLE ? fp64 : gpu_shader5_or_es31, x_type, x_type, exp_type);
}
ir_function_signature *
@@ -4526,7 +4560,7 @@ builtin_builder::_frexp(const glsl_type *x_type, const glsl_type *exp_type)
{
ir_variable *x = in_var(x_type, "x");
ir_variable *exponent = out_var(exp_type, "exp");
- MAKE_SIG(x_type, gpu_shader5, 2, x, exponent);
+ MAKE_SIG(x_type, gpu_shader5_or_es31, 2, x, exponent);
const unsigned vec_elem = x_type->vector_elements;
const glsl_type *bvec = glsl_type::get_instance(GLSL_TYPE_BOOL, vec_elem, 1);
@@ -4575,7 +4609,7 @@ builtin_builder::_uaddCarry(const glsl_type *type)
ir_variable *x = in_var(type, "x");
ir_variable *y = in_var(type, "y");
ir_variable *carry = out_var(type, "carry");
- MAKE_SIG(type, gpu_shader5, 3, x, y, carry);
+ MAKE_SIG(type, gpu_shader5_or_es31, 3, x, y, carry);
body.emit(assign(carry, ir_builder::carry(x, y)));
body.emit(ret(add(x, y)));
@@ -4589,7 +4623,7 @@ builtin_builder::_usubBorrow(const glsl_type *type)
ir_variable *x = in_var(type, "x");
ir_variable *y = in_var(type, "y");
ir_variable *borrow = out_var(type, "borrow");
- MAKE_SIG(type, gpu_shader5, 3, x, y, borrow);
+ MAKE_SIG(type, gpu_shader5_or_es31, 3, x, y, borrow);
body.emit(assign(borrow, ir_builder::borrow(x, y)));
body.emit(ret(sub(x, y)));
@@ -4607,7 +4641,7 @@ builtin_builder::_mulExtended(const glsl_type *type)
ir_variable *y = in_var(type, "y");
ir_variable *msb = out_var(type, "msb");
ir_variable *lsb = out_var(type, "lsb");
- MAKE_SIG(glsl_type::void_type, gpu_shader5, 4, x, y, msb, lsb);
+ MAKE_SIG(glsl_type::void_type, gpu_shader5_or_es31, 4, x, y, msb, lsb);
body.emit(assign(msb, imul_high(x, y)));
body.emit(assign(lsb, mul(x, y)));
diff --git a/mesalib/src/glsl/builtin_types.cpp b/mesalib/src/glsl/builtin_types.cpp
index fef86df28..d92e2eb30 100644
--- a/mesalib/src/glsl/builtin_types.cpp
+++ b/mesalib/src/glsl/builtin_types.cpp
@@ -372,7 +372,7 @@ _mesa_glsl_initialize_types(struct _mesa_glsl_parse_state *state)
add_type(symbols, glsl_type::uimage2DMSArray_type);
}
- if (state->ARB_shader_atomic_counters_enable) {
+ if (state->has_atomic_counters()) {
add_type(symbols, glsl_type::atomic_uint_type);
}
diff --git a/mesalib/src/glsl/builtin_variables.cpp b/mesalib/src/glsl/builtin_variables.cpp
index 21e7331c7..6806aa1f9 100644
--- a/mesalib/src/glsl/builtin_variables.cpp
+++ b/mesalib/src/glsl/builtin_variables.cpp
@@ -653,19 +653,46 @@ builtin_variable_generator::generate_constants()
add_const("gl_MaxTextureCoords", state->Const.MaxTextureCoords);
}
- if (state->ARB_shader_atomic_counters_enable) {
+ if (state->has_atomic_counters()) {
add_const("gl_MaxVertexAtomicCounters",
state->Const.MaxVertexAtomicCounters);
- add_const("gl_MaxGeometryAtomicCounters",
- state->Const.MaxGeometryAtomicCounters);
add_const("gl_MaxFragmentAtomicCounters",
state->Const.MaxFragmentAtomicCounters);
add_const("gl_MaxCombinedAtomicCounters",
state->Const.MaxCombinedAtomicCounters);
add_const("gl_MaxAtomicCounterBindings",
state->Const.MaxAtomicBufferBindings);
- add_const("gl_MaxTessControlAtomicCounters", 0);
- add_const("gl_MaxTessEvaluationAtomicCounters", 0);
+
+ /* When Mesa adds support for GL_OES_geometry_shader and
+ * GL_OES_tessellation_shader, this will need to change.
+ */
+ if (!state->es_shader) {
+ add_const("gl_MaxGeometryAtomicCounters",
+ state->Const.MaxGeometryAtomicCounters);
+ add_const("gl_MaxTessControlAtomicCounters", 0);
+ add_const("gl_MaxTessEvaluationAtomicCounters", 0);
+ }
+ }
+
+ if (state->is_version(420, 310)) {
+ add_const("gl_MaxVertexAtomicCounterBuffers",
+ state->Const.MaxVertexAtomicCounterBuffers);
+ add_const("gl_MaxFragmentAtomicCounterBuffers",
+ state->Const.MaxFragmentAtomicCounterBuffers);
+ add_const("gl_MaxCombinedAtomicCounterBuffers",
+ state->Const.MaxCombinedAtomicCounterBuffers);
+ add_const("gl_MaxAtomicCounterBufferSize",
+ state->Const.MaxAtomicCounterBufferSize);
+
+ /* When Mesa adds support for GL_OES_geometry_shader and
+ * GL_OES_tessellation_shader, this will need to change.
+ */
+ if (!state->es_shader) {
+ add_const("gl_MaxGeometryAtomicCounterBuffers",
+ state->Const.MaxGeometryAtomicCounterBuffers);
+ add_const("gl_MaxTessControlAtomicCounterBuffers", 0);
+ add_const("gl_MaxTessEvaluationAtomicCounterBuffers", 0);
+ }
}
if (state->is_version(430, 0) || state->ARB_compute_shader_enable) {
diff --git a/mesalib/src/glsl/glcpp/glcpp-parse.y b/mesalib/src/glsl/glcpp/glcpp-parse.y
index cfceca66b..a11b6b2c7 100644
--- a/mesalib/src/glsl/glcpp/glcpp-parse.y
+++ b/mesalib/src/glsl/glcpp/glcpp-parse.y
@@ -2448,6 +2448,9 @@ _glcpp_parser_handle_version_declaration(glcpp_parser_t *parser, intmax_t versio
if (extensions->ARB_gpu_shader_fp64)
add_builtin_define(parser, "GL_ARB_gpu_shader_fp64", 1);
+ if (extensions->ARB_vertex_attrib_64bit)
+ add_builtin_define(parser, "GL_ARB_vertex_attrib_64bit", 1);
+
if (extensions->AMD_vertex_shader_layer)
add_builtin_define(parser, "GL_AMD_vertex_shader_layer", 1);
diff --git a/mesalib/src/glsl/glsl_lexer.ll b/mesalib/src/glsl/glsl_lexer.ll
index 2785ed168..10db5b8b6 100644
--- a/mesalib/src/glsl/glsl_lexer.ll
+++ b/mesalib/src/glsl/glsl_lexer.ll
@@ -409,7 +409,7 @@ restrict KEYWORD_WITH_ALT(420, 300, 420, 0, yyextra->ARB_shader_image_load_store
readonly KEYWORD_WITH_ALT(420, 300, 420, 0, yyextra->ARB_shader_image_load_store_enable, READONLY);
writeonly KEYWORD_WITH_ALT(420, 300, 420, 0, yyextra->ARB_shader_image_load_store_enable, WRITEONLY);
-atomic_uint KEYWORD_WITH_ALT(420, 300, 420, 0, yyextra->ARB_shader_atomic_counters_enable, ATOMIC_UINT);
+atomic_uint KEYWORD_WITH_ALT(420, 300, 420, 310, yyextra->ARB_shader_atomic_counters_enable, ATOMIC_UINT);
struct return STRUCT;
void return VOID_TOK;
diff --git a/mesalib/src/glsl/glsl_parser.yy b/mesalib/src/glsl/glsl_parser.yy
index aceb3b916..3ce9e103f 100644
--- a/mesalib/src/glsl/glsl_parser.yy
+++ b/mesalib/src/glsl/glsl_parser.yy
@@ -214,6 +214,7 @@ static bool match_layout_qualifier(const char *s1, const char *s2,
%type <type_qualifier> layout_qualifier
%type <type_qualifier> layout_qualifier_id_list layout_qualifier_id
%type <type_qualifier> interface_block_layout_qualifier
+%type <type_qualifier> memory_qualifier
%type <type_qualifier> interface_qualifier
%type <type_specifier> type_specifier
%type <type_specifier> type_specifier_nonarray
@@ -1000,6 +1001,11 @@ parameter_qualifier:
$$ = $2;
$$.precision = $1;
}
+ | memory_qualifier parameter_qualifier
+ {
+ $$ = $1;
+ $$.merge_qualifier(&@1, state, $2);
+ }
parameter_direction_qualifier:
IN_TOK
@@ -1360,6 +1366,21 @@ layout_qualifier_id:
if (!$$.flags.i &&
match_layout_qualifier($1, "early_fragment_tests", state) == 0) {
+ /* From section 4.4.1.3 of the GLSL 4.50 specification
+ * (Fragment Shader Inputs):
+ *
+ * "Fragment shaders also allow the following layout
+ * qualifier on in only (not with variable declarations)
+ * layout-qualifier-id
+ * early_fragment_tests
+ * [...]"
+ */
+ if (state->stage != MESA_SHADER_FRAGMENT) {
+ _mesa_glsl_error(& @1, state,
+ "early_fragment_tests layout qualifier only "
+ "valid in fragment shaders");
+ }
+
$$.flags.q.early_fragment_tests = 1;
}
}
@@ -1404,13 +1425,13 @@ layout_qualifier_id:
}
if ((state->ARB_shading_language_420pack_enable ||
- state->ARB_shader_atomic_counters_enable) &&
+ state->has_atomic_counters()) &&
match_layout_qualifier("binding", $1, state) == 0) {
$$.flags.q.explicit_binding = 1;
$$.binding = $3;
}
- if (state->ARB_shader_atomic_counters_enable &&
+ if (state->has_atomic_counters() &&
match_layout_qualifier("offset", $1, state) == 0) {
$$.flags.q.explicit_offset = 1;
$$.offset = $3;
@@ -1581,6 +1602,7 @@ type_qualifier:
| storage_qualifier
| interpolation_qualifier
| layout_qualifier
+ | memory_qualifier
| precision_qualifier
{
memset(&$$, 0, sizeof($$));
@@ -1718,6 +1740,11 @@ type_qualifier:
$$ = $2;
$$.precision = $1;
}
+ | memory_qualifier type_qualifier
+ {
+ $$ = $1;
+ $$.merge_qualifier(&@1, state, $2);
+ }
;
auxiliary_storage_qualifier:
@@ -1778,7 +1805,10 @@ storage_qualifier:
memset(& $$, 0, sizeof($$));
$$.flags.q.uniform = 1;
}
- | COHERENT
+ ;
+
+memory_qualifier:
+ COHERENT
{
memset(& $$, 0, sizeof($$));
$$.flags.q.coherent = 1;
diff --git a/mesalib/src/glsl/glsl_parser_extras.cpp b/mesalib/src/glsl/glsl_parser_extras.cpp
index 0aa3c54fc..be6713c46 100644
--- a/mesalib/src/glsl/glsl_parser_extras.cpp
+++ b/mesalib/src/glsl/glsl_parser_extras.cpp
@@ -117,6 +117,16 @@ _mesa_glsl_parse_state::_mesa_glsl_parse_state(struct gl_context *_ctx,
this->Const.MaxFragmentAtomicCounters = ctx->Const.Program[MESA_SHADER_FRAGMENT].MaxAtomicCounters;
this->Const.MaxCombinedAtomicCounters = ctx->Const.MaxCombinedAtomicCounters;
this->Const.MaxAtomicBufferBindings = ctx->Const.MaxAtomicBufferBindings;
+ this->Const.MaxVertexAtomicCounterBuffers =
+ ctx->Const.Program[MESA_SHADER_VERTEX].MaxAtomicBuffers;
+ this->Const.MaxGeometryAtomicCounterBuffers =
+ ctx->Const.Program[MESA_SHADER_GEOMETRY].MaxAtomicBuffers;
+ this->Const.MaxFragmentAtomicCounterBuffers =
+ ctx->Const.Program[MESA_SHADER_FRAGMENT].MaxAtomicBuffers;
+ this->Const.MaxCombinedAtomicCounterBuffers =
+ ctx->Const.MaxCombinedAtomicBuffers;
+ this->Const.MaxAtomicCounterBufferSize =
+ ctx->Const.MaxAtomicBufferSize;
/* Compute shader constants */
for (unsigned i = 0; i < ARRAY_SIZE(this->Const.MaxComputeWorkGroupCount); i++)
@@ -143,9 +153,9 @@ _mesa_glsl_parse_state::_mesa_glsl_parse_state(struct gl_context *_ctx,
this->num_user_structures = 0;
/* supported_versions should be large enough to support the known desktop
- * GLSL versions plus 2 GLES versions (ES2 & ES3)
+ * GLSL versions plus 3 GLES versions (ES 1.00, ES 3.00, and ES 3.10))
*/
- STATIC_ASSERT((ARRAY_SIZE(known_desktop_glsl_versions) + 2) ==
+ STATIC_ASSERT((ARRAY_SIZE(known_desktop_glsl_versions) + 3) ==
ARRAY_SIZE(this->supported_versions));
/* Populate the list of supported GLSL versions */
@@ -175,6 +185,11 @@ _mesa_glsl_parse_state::_mesa_glsl_parse_state(struct gl_context *_ctx,
this->supported_versions[this->num_supported_versions].es = true;
this->num_supported_versions++;
}
+ if (_mesa_is_gles31(ctx)) {
+ this->supported_versions[this->num_supported_versions].ver = 310;
+ this->supported_versions[this->num_supported_versions].es = true;
+ this->num_supported_versions++;
+ }
/* Create a string for use in error messages to tell the user which GLSL
* versions are supported.
@@ -212,7 +227,7 @@ _mesa_glsl_parse_state::_mesa_glsl_parse_state(struct gl_context *_ctx,
this->gs_input_size = 0;
this->in_qualifier = new(this) ast_type_qualifier();
this->out_qualifier = new(this) ast_type_qualifier();
- this->early_fragment_tests = false;
+ this->fs_early_fragment_tests = false;
memset(this->atomic_counter_offsets, 0,
sizeof(this->atomic_counter_offsets));
this->allow_extension_directive_midshader =
@@ -565,6 +580,7 @@ static const _mesa_glsl_extension _mesa_glsl_supported_extensions[] = {
EXT(ARB_texture_query_lod, true, false, ARB_texture_query_lod),
EXT(ARB_texture_rectangle, true, false, dummy_true),
EXT(ARB_uniform_buffer_object, true, false, ARB_uniform_buffer_object),
+ EXT(ARB_vertex_attrib_64bit, true, false, ARB_vertex_attrib_64bit),
EXT(ARB_viewport_array, true, false, ARB_viewport_array),
/* KHR extensions go here, sorted alphabetically.
@@ -1418,6 +1434,7 @@ set_shader_inout_layout(struct gl_shader *shader,
assert(!state->fs_redeclares_gl_fragcoord);
assert(!state->fs_pixel_center_integer);
assert(!state->fs_origin_upper_left);
+ assert(!state->fs_early_fragment_tests);
}
switch (shader->Stage) {
@@ -1460,6 +1477,7 @@ set_shader_inout_layout(struct gl_shader *shader,
shader->origin_upper_left = state->fs_origin_upper_left;
shader->ARB_fragment_coord_conventions_enable =
state->ARB_fragment_coord_conventions_enable;
+ shader->EarlyFragmentTests = state->fs_early_fragment_tests;
break;
default:
diff --git a/mesalib/src/glsl/glsl_parser_extras.h b/mesalib/src/glsl/glsl_parser_extras.h
index dae7864fd..9a0c24e67 100644
--- a/mesalib/src/glsl/glsl_parser_extras.h
+++ b/mesalib/src/glsl/glsl_parser_extras.h
@@ -160,7 +160,7 @@ struct _mesa_glsl_parse_state {
{
if (!this->has_separate_shader_objects()) {
const char *const requirement = this->es_shader
- ? "GL_EXT_separate_shader_objects extension"
+ ? "GL_EXT_separate_shader_objects extension or GLSL ES 310"
: "GL_ARB_separate_shader_objects extension or GLSL 420";
_mesa_glsl_error(locp, this, "%s explicit location requires %s",
@@ -175,17 +175,26 @@ struct _mesa_glsl_parse_state {
const ir_variable *)
{
if (!this->has_explicit_attrib_location() ||
- !this->ARB_explicit_uniform_location_enable) {
+ !this->has_explicit_uniform_location()) {
+ const char *const requirement = this->es_shader
+ ? "GLSL ES 310"
+ : "GL_ARB_explicit_uniform_location and either "
+ "GL_ARB_explicit_attrib_location or GLSL 330.";
+
_mesa_glsl_error(locp, this,
- "uniform explicit location requires "
- "GL_ARB_explicit_uniform_location and either "
- "GL_ARB_explicit_attrib_location or GLSL 330.");
+ "uniform explicit location requires %s",
+ requirement);
return false;
}
return true;
}
+ bool has_atomic_counters() const
+ {
+ return ARB_shader_atomic_counters_enable || is_version(420, 310);
+ }
+
bool has_explicit_attrib_stream() const
{
return ARB_gpu_shader5_enable || is_version(400, 0);
@@ -196,6 +205,11 @@ struct _mesa_glsl_parse_state {
return ARB_explicit_attrib_location_enable || is_version(330, 300);
}
+ bool has_explicit_uniform_location() const
+ {
+ return ARB_explicit_uniform_location_enable || is_version(430, 310);
+ }
+
bool has_uniform_buffer_objects() const
{
return ARB_uniform_buffer_object_enable || is_version(140, 300);
@@ -203,7 +217,7 @@ struct _mesa_glsl_parse_state {
bool has_separate_shader_objects() const
{
- return ARB_separate_shader_objects_enable || is_version(410, 0)
+ return ARB_separate_shader_objects_enable || is_version(410, 310)
|| EXT_separate_shader_objects_enable;
}
@@ -224,7 +238,7 @@ struct _mesa_glsl_parse_state {
struct {
unsigned ver;
bool es;
- } supported_versions[14];
+ } supported_versions[15];
bool es_shader;
unsigned language_version;
@@ -339,6 +353,16 @@ struct _mesa_glsl_parse_state {
unsigned MaxCombinedAtomicCounters;
unsigned MaxAtomicBufferBindings;
+ /* These are also atomic counter related, but they weren't added to
+ * until atomic counters were added to core in GLSL 4.20 and GLSL ES
+ * 3.10.
+ */
+ unsigned MaxVertexAtomicCounterBuffers;
+ unsigned MaxGeometryAtomicCounterBuffers;
+ unsigned MaxFragmentAtomicCounterBuffers;
+ unsigned MaxCombinedAtomicCounterBuffers;
+ unsigned MaxAtomicCounterBufferSize;
+
/* ARB_compute_shader */
unsigned MaxComputeWorkGroupCount[3];
unsigned MaxComputeWorkGroupSize[3];
@@ -458,6 +482,8 @@ struct _mesa_glsl_parse_state {
bool ARB_texture_rectangle_warn;
bool ARB_uniform_buffer_object_enable;
bool ARB_uniform_buffer_object_warn;
+ bool ARB_vertex_attrib_64bit_enable;
+ bool ARB_vertex_attrib_64bit_warn;
bool ARB_viewport_array_enable;
bool ARB_viewport_array_warn;
@@ -510,7 +536,7 @@ struct _mesa_glsl_parse_state {
*/
unsigned gs_input_size;
- bool early_fragment_tests;
+ bool fs_early_fragment_tests;
/** Atomic counter offsets by binding */
unsigned atomic_counter_offsets[MAX_COMBINED_ATOMIC_BUFFERS];
diff --git a/mesalib/src/glsl/ir_set_program_inouts.cpp b/mesalib/src/glsl/ir_set_program_inouts.cpp
index e877a2019..b968a1efd 100644
--- a/mesalib/src/glsl/ir_set_program_inouts.cpp
+++ b/mesalib/src/glsl/ir_set_program_inouts.cpp
@@ -105,13 +105,10 @@ mark(struct gl_program *prog, ir_variable *var, int offset, int len,
int idx = var->data.location + var->data.index + offset + i;
GLbitfield64 bitfield = BITFIELD64_BIT(idx);
- /* dvec3 and dvec4 take up 2 slots */
- if (dual_slot) {
- idx += i;
- bitfield |= bitfield << 1;
- }
if (var->data.mode == ir_var_shader_in) {
- prog->InputsRead |= bitfield;
+ prog->InputsRead |= bitfield;
+ if (dual_slot)
+ prog->DoubleInputsRead |= bitfield;
if (is_fragment_shader) {
gl_fragment_program *fprog = (gl_fragment_program *) prog;
fprog->InterpQualifier[idx] =
@@ -120,13 +117,6 @@ mark(struct gl_program *prog, ir_variable *var, int offset, int len,
fprog->IsCentroid |= bitfield;
if (var->data.sample)
fprog->IsSample |= bitfield;
-
- /* Set the InterpQualifier of the next slot to the same as the
- * current one, since dvec3 and dvec4 spans 2 slots.
- */
- if (dual_slot)
- fprog->InterpQualifier[idx + 1] =
- (glsl_interp_qualifier) var->data.interpolation;
}
} else if (var->data.mode == ir_var_system_value) {
prog->SystemValuesRead |= bitfield;
diff --git a/mesalib/src/glsl/link_uniform_blocks.cpp b/mesalib/src/glsl/link_uniform_blocks.cpp
index 6ca41107e..898544bea 100644
--- a/mesalib/src/glsl/link_uniform_blocks.cpp
+++ b/mesalib/src/glsl/link_uniform_blocks.cpp
@@ -67,14 +67,14 @@ private:
assert(!"Should not get here.");
}
- virtual void enter_record(const glsl_type *type, const char *name,
+ virtual void enter_record(const glsl_type *type, const char *,
bool row_major) {
assert(type->is_record());
this->offset = glsl_align(
this->offset, type->std140_base_alignment(row_major));
}
- virtual void leave_record(const glsl_type *type, const char *name,
+ virtual void leave_record(const glsl_type *type, const char *,
bool row_major) {
assert(type->is_record());
@@ -90,8 +90,8 @@ private:
}
virtual void visit_field(const glsl_type *type, const char *name,
- bool row_major, const glsl_type *record_type,
- bool last_field)
+ bool row_major, const glsl_type *,
+ bool /* last_field */)
{
assert(this->index < this->num_variables);
diff --git a/mesalib/src/glsl/link_uniforms.cpp b/mesalib/src/glsl/link_uniforms.cpp
index d5ca23a38..2c928e144 100644
--- a/mesalib/src/glsl/link_uniforms.cpp
+++ b/mesalib/src/glsl/link_uniforms.cpp
@@ -544,7 +544,7 @@ private:
assert(!"Should not get here.");
}
- virtual void enter_record(const glsl_type *type, const char *name,
+ virtual void enter_record(const glsl_type *type, const char *,
bool row_major) {
assert(type->is_record());
if (this->ubo_block_index == -1)
@@ -553,7 +553,7 @@ private:
this->ubo_byte_offset, type->std140_base_alignment(row_major));
}
- virtual void leave_record(const glsl_type *type, const char *name,
+ virtual void leave_record(const glsl_type *type, const char *,
bool row_major) {
assert(type->is_record());
if (this->ubo_block_index == -1)
@@ -564,7 +564,7 @@ private:
virtual void visit_field(const glsl_type *type, const char *name,
bool row_major, const glsl_type *record_type,
- bool last_field)
+ bool /* last_field */)
{
assert(!type->without_array()->is_record());
assert(!type->without_array()->is_interface());
diff --git a/mesalib/src/glsl/linker.cpp b/mesalib/src/glsl/linker.cpp
index 21fde9444..ea73c6f9d 100644
--- a/mesalib/src/glsl/linker.cpp
+++ b/mesalib/src/glsl/linker.cpp
@@ -1413,6 +1413,8 @@ link_fs_input_layout_qualifiers(struct gl_shader_program *prog,
linked_shader->origin_upper_left = shader->origin_upper_left;
linked_shader->pixel_center_integer = shader->pixel_center_integer;
}
+
+ linked_shader->EarlyFragmentTests |= shader->EarlyFragmentTests;
}
}
@@ -1975,6 +1977,7 @@ assign_attribute_or_color_locations(gl_shader_program *prog,
} to_assign[16];
unsigned num_attr = 0;
+ unsigned total_attribs_size = 0;
foreach_in_list(ir_instruction, node, sh->ir) {
ir_variable *const var = node->as_variable();
@@ -2016,12 +2019,41 @@ assign_attribute_or_color_locations(gl_shader_program *prog,
}
}
+ const unsigned slots = var->type->count_attribute_slots();
+
+ /* From GL4.5 core spec, section 11.1.1 (Vertex Attributes):
+ *
+ * "A program with more than the value of MAX_VERTEX_ATTRIBS active
+ * attribute variables may fail to link, unless device-dependent
+ * optimizations are able to make the program fit within available
+ * hardware resources. For the purposes of this test, attribute variables
+ * of the type dvec3, dvec4, dmat2x3, dmat2x4, dmat3, dmat3x4, dmat4x3,
+ * and dmat4 may count as consuming twice as many attributes as equivalent
+ * single-precision types. While these types use the same number of
+ * generic attributes as their single-precision equivalents,
+ * implementations are permitted to consume two single-precision vectors
+ * of internal storage for each three- or four-component double-precision
+ * vector."
+ * Until someone has a good reason in Mesa, enforce that now.
+ */
+ if (target_index == MESA_SHADER_VERTEX) {
+ total_attribs_size += slots;
+ if (var->type->without_array() == glsl_type::dvec3_type ||
+ var->type->without_array() == glsl_type::dvec4_type ||
+ var->type->without_array() == glsl_type::dmat2x3_type ||
+ var->type->without_array() == glsl_type::dmat2x4_type ||
+ var->type->without_array() == glsl_type::dmat3_type ||
+ var->type->without_array() == glsl_type::dmat3x4_type ||
+ var->type->without_array() == glsl_type::dmat4x3_type ||
+ var->type->without_array() == glsl_type::dmat4_type)
+ total_attribs_size += slots;
+ }
+
/* If the variable is not a built-in and has a location statically
* assigned in the shader (presumably via a layout qualifier), make sure
* that it doesn't collide with other assigned locations. Otherwise,
* add it to the list of variables that need linker-assigned locations.
*/
- const unsigned slots = var->type->count_attribute_slots();
if (var->data.location != -1) {
if (var->data.location >= generic_base && var->data.index < 1) {
/* From page 61 of the OpenGL 4.0 spec:
@@ -2141,6 +2173,15 @@ assign_attribute_or_color_locations(gl_shader_program *prog,
num_attr++;
}
+ if (target_index == MESA_SHADER_VERTEX) {
+ if (total_attribs_size > max_index) {
+ linker_error(prog,
+ "attempt to use %d vertex attribute slots only %d available ",
+ total_attribs_size, max_index);
+ return false;
+ }
+ }
+
/* If all of the attributes were assigned locations by the application (or
* are built-in attributes with fixed locations), return early. This should
* be the common case.
@@ -2556,6 +2597,7 @@ add_interface_variables(struct gl_shader_program *shProg,
{
foreach_in_list(ir_instruction, node, sh->ir) {
ir_variable *var = node->as_variable();
+ uint8_t mask = 0;
if (!var)
continue;
@@ -2571,6 +2613,10 @@ add_interface_variables(struct gl_shader_program *shProg,
var->data.location != SYSTEM_VALUE_VERTEX_ID_ZERO_BASE &&
var->data.location != SYSTEM_VALUE_INSTANCE_ID)
continue;
+ /* Mark special built-in inputs referenced by the vertex stage so
+ * that they are considered active by the shader queries.
+ */
+ mask = (1 << (MESA_SHADER_VERTEX));
/* FALLTHROUGH */
case ir_var_shader_in:
if (programInterface != GL_PROGRAM_INPUT)
@@ -2585,7 +2631,7 @@ add_interface_variables(struct gl_shader_program *shProg,
};
if (!add_program_resource(shProg, programInterface, var,
- build_stageref(shProg, var->name)))
+ build_stageref(shProg, var->name) | mask))
return false;
}
return true;
diff --git a/mesalib/src/glsl/nir/glsl_to_nir.cpp b/mesalib/src/glsl/nir/glsl_to_nir.cpp
index f6b8331d4..af758ceb0 100644
--- a/mesalib/src/glsl/nir/glsl_to_nir.cpp
+++ b/mesalib/src/glsl/nir/glsl_to_nir.cpp
@@ -614,27 +614,135 @@ nir_visitor::visit(ir_call *ir)
op = nir_intrinsic_atomic_counter_inc_var;
} else if (strcmp(ir->callee_name(), "__intrinsic_atomic_predecrement") == 0) {
op = nir_intrinsic_atomic_counter_dec_var;
+ } else if (strcmp(ir->callee_name(), "__intrinsic_image_load") == 0) {
+ op = nir_intrinsic_image_load;
+ } else if (strcmp(ir->callee_name(), "__intrinsic_image_store") == 0) {
+ op = nir_intrinsic_image_store;
+ } else if (strcmp(ir->callee_name(), "__intrinsic_image_atomic_add") == 0) {
+ op = nir_intrinsic_image_atomic_add;
+ } else if (strcmp(ir->callee_name(), "__intrinsic_image_atomic_min") == 0) {
+ op = nir_intrinsic_image_atomic_min;
+ } else if (strcmp(ir->callee_name(), "__intrinsic_image_atomic_max") == 0) {
+ op = nir_intrinsic_image_atomic_max;
+ } else if (strcmp(ir->callee_name(), "__intrinsic_image_atomic_and") == 0) {
+ op = nir_intrinsic_image_atomic_and;
+ } else if (strcmp(ir->callee_name(), "__intrinsic_image_atomic_or") == 0) {
+ op = nir_intrinsic_image_atomic_or;
+ } else if (strcmp(ir->callee_name(), "__intrinsic_image_atomic_xor") == 0) {
+ op = nir_intrinsic_image_atomic_xor;
+ } else if (strcmp(ir->callee_name(), "__intrinsic_image_atomic_exchange") == 0) {
+ op = nir_intrinsic_image_atomic_exchange;
+ } else if (strcmp(ir->callee_name(), "__intrinsic_image_atomic_comp_swap") == 0) {
+ op = nir_intrinsic_image_atomic_comp_swap;
+ } else if (strcmp(ir->callee_name(), "__intrinsic_memory_barrier") == 0) {
+ op = nir_intrinsic_memory_barrier;
} else {
unreachable("not reached");
}
nir_intrinsic_instr *instr = nir_intrinsic_instr_create(shader, op);
- ir_dereference *param =
- (ir_dereference *) ir->actual_parameters.get_head();
- instr->variables[0] = evaluate_deref(&instr->instr, param);
- nir_ssa_dest_init(&instr->instr, &instr->dest, 1, NULL);
+
+ switch (op) {
+ case nir_intrinsic_atomic_counter_read_var:
+ case nir_intrinsic_atomic_counter_inc_var:
+ case nir_intrinsic_atomic_counter_dec_var: {
+ ir_dereference *param =
+ (ir_dereference *) ir->actual_parameters.get_head();
+ instr->variables[0] = evaluate_deref(&instr->instr, param);
+ nir_ssa_dest_init(&instr->instr, &instr->dest, 1, NULL);
+ break;
+ }
+ case nir_intrinsic_image_load:
+ case nir_intrinsic_image_store:
+ case nir_intrinsic_image_atomic_add:
+ case nir_intrinsic_image_atomic_min:
+ case nir_intrinsic_image_atomic_max:
+ case nir_intrinsic_image_atomic_and:
+ case nir_intrinsic_image_atomic_or:
+ case nir_intrinsic_image_atomic_xor:
+ case nir_intrinsic_image_atomic_exchange:
+ case nir_intrinsic_image_atomic_comp_swap: {
+ nir_ssa_undef_instr *instr_undef =
+ nir_ssa_undef_instr_create(shader, 1);
+ nir_instr_insert_after_cf_list(this->cf_node_list,
+ &instr_undef->instr);
+
+ /* Set the image variable dereference. */
+ exec_node *param = ir->actual_parameters.get_head();
+ ir_dereference *image = (ir_dereference *)param;
+ const glsl_type *type =
+ image->variable_referenced()->type->without_array();
+
+ instr->variables[0] = evaluate_deref(&instr->instr, image);
+ param = param->get_next();
+
+ /* Set the address argument, extending the coordinate vector to four
+ * components.
+ */
+ const nir_src src_addr = evaluate_rvalue((ir_dereference *)param);
+ nir_alu_instr *instr_addr = nir_alu_instr_create(shader, nir_op_vec4);
+ nir_ssa_dest_init(&instr_addr->instr, &instr_addr->dest.dest, 4, NULL);
+
+ for (int i = 0; i < 4; i++) {
+ if (i < type->coordinate_components()) {
+ instr_addr->src[i].src = src_addr;
+ instr_addr->src[i].swizzle[0] = i;
+ } else {
+ instr_addr->src[i].src = nir_src_for_ssa(&instr_undef->def);
+ }
+ }
+
+ nir_instr_insert_after_cf_list(cf_node_list, &instr_addr->instr);
+ instr->src[0] = nir_src_for_ssa(&instr_addr->dest.dest.ssa);
+ param = param->get_next();
+
+ /* Set the sample argument, which is undefined for single-sample
+ * images.
+ */
+ if (type->sampler_dimensionality == GLSL_SAMPLER_DIM_MS) {
+ instr->src[1] = evaluate_rvalue((ir_dereference *)param);
+ param = param->get_next();
+ } else {
+ instr->src[1] = nir_src_for_ssa(&instr_undef->def);
+ }
+
+ /* Set the intrinsic parameters. */
+ if (!param->is_tail_sentinel()) {
+ instr->src[2] = evaluate_rvalue((ir_dereference *)param);
+ param = param->get_next();
+ }
+
+ if (!param->is_tail_sentinel()) {
+ instr->src[3] = evaluate_rvalue((ir_dereference *)param);
+ param = param->get_next();
+ }
+
+ /* Set the intrinsic destination. */
+ if (ir->return_deref)
+ nir_ssa_dest_init(&instr->instr, &instr->dest,
+ ir->return_deref->type->vector_elements, NULL);
+ break;
+ }
+ case nir_intrinsic_memory_barrier:
+ break;
+ default:
+ unreachable("not reached");
+ }
nir_instr_insert_after_cf_list(this->cf_node_list, &instr->instr);
- nir_intrinsic_instr *store_instr =
- nir_intrinsic_instr_create(shader, nir_intrinsic_store_var);
- store_instr->num_components = 1;
+ if (ir->return_deref) {
+ nir_intrinsic_instr *store_instr =
+ nir_intrinsic_instr_create(shader, nir_intrinsic_store_var);
+ store_instr->num_components = ir->return_deref->type->vector_elements;
- store_instr->variables[0] = evaluate_deref(&store_instr->instr, ir->return_deref);
- store_instr->src[0].is_ssa = true;
- store_instr->src[0].ssa = &instr->dest.ssa;
+ store_instr->variables[0] =
+ evaluate_deref(&store_instr->instr, ir->return_deref);
+ store_instr->src[0] = nir_src_for_ssa(&instr->dest.ssa);
- nir_instr_insert_after_cf_list(this->cf_node_list, &store_instr->instr);
+ nir_instr_insert_after_cf_list(this->cf_node_list,
+ &store_instr->instr);
+ }
return;
}
@@ -824,7 +932,7 @@ nir_visitor::evaluate_rvalue(ir_rvalue* ir)
nir_dest *dest = get_instr_dest(this->result);
assert(dest->is_ssa);
- nir_src src;
+ nir_src src = NIR_SRC_INIT;
src.is_ssa = true;
src.ssa = &dest->ssa;
@@ -1038,8 +1146,8 @@ nir_visitor::visit(ir_expression *ir)
case ir_unop_rcp: emit(nir_op_frcp, dest_size, srcs); break;
case ir_unop_rsq: emit(nir_op_frsq, dest_size, srcs); break;
case ir_unop_sqrt: emit(nir_op_fsqrt, dest_size, srcs); break;
- case ir_unop_exp: emit(nir_op_fexp, dest_size, srcs); break;
- case ir_unop_log: emit(nir_op_flog, dest_size, srcs); break;
+ case ir_unop_exp: unreachable("ir_unop_exp should have been lowered");
+ case ir_unop_log: unreachable("ir_unop_log should have been lowered");
case ir_unop_exp2: emit(nir_op_fexp2, dest_size, srcs); break;
case ir_unop_log2: emit(nir_op_flog2, dest_size, srcs); break;
case ir_unop_i2f:
diff --git a/mesalib/src/glsl/nir/nir.c b/mesalib/src/glsl/nir/nir.c
index 4cc074b80..f03e80a4e 100644
--- a/mesalib/src/glsl/nir/nir.c
+++ b/mesalib/src/glsl/nir/nir.c
@@ -58,12 +58,9 @@ reg_create(void *mem_ctx, struct exec_list *list)
nir_register *reg = ralloc(mem_ctx, nir_register);
reg->parent_instr = NULL;
- reg->uses = _mesa_set_create(reg, _mesa_hash_pointer,
- _mesa_key_pointer_equal);
- reg->defs = _mesa_set_create(reg, _mesa_hash_pointer,
- _mesa_key_pointer_equal);
- reg->if_uses = _mesa_set_create(reg, _mesa_hash_pointer,
- _mesa_key_pointer_equal);
+ list_inithead(&reg->uses);
+ list_inithead(&reg->defs);
+ list_inithead(&reg->if_uses);
reg->num_components = 0;
reg->num_array_elems = 0;
@@ -1070,11 +1067,14 @@ update_if_uses(nir_cf_node *node)
nir_if *if_stmt = nir_cf_node_as_if(node);
- struct set *if_uses_set = if_stmt->condition.is_ssa ?
- if_stmt->condition.ssa->if_uses :
- if_stmt->condition.reg.reg->uses;
-
- _mesa_set_add(if_uses_set, if_stmt);
+ if_stmt->condition.parent_if = if_stmt;
+ if (if_stmt->condition.is_ssa) {
+ list_addtail(&if_stmt->condition.use_link,
+ &if_stmt->condition.ssa->if_uses);
+ } else {
+ list_addtail(&if_stmt->condition.use_link,
+ &if_stmt->condition.reg.reg->if_uses);
+ }
}
void
@@ -1227,16 +1227,7 @@ cleanup_cf_node(nir_cf_node *node)
foreach_list_typed(nir_cf_node, child, node, &if_stmt->else_list)
cleanup_cf_node(child);
- struct set *if_uses;
- if (if_stmt->condition.is_ssa) {
- if_uses = if_stmt->condition.ssa->if_uses;
- } else {
- if_uses = if_stmt->condition.reg.reg->if_uses;
- }
-
- struct set_entry *entry = _mesa_set_search(if_uses, if_stmt);
- assert(entry);
- _mesa_set_remove(if_uses, entry);
+ list_del(&if_stmt->condition.use_link);
break;
}
@@ -1293,9 +1284,9 @@ add_use_cb(nir_src *src, void *state)
{
nir_instr *instr = state;
- struct set *uses_set = src->is_ssa ? src->ssa->uses : src->reg.reg->uses;
-
- _mesa_set_add(uses_set, instr);
+ src->parent_instr = instr;
+ list_addtail(&src->use_link,
+ src->is_ssa ? &src->ssa->uses : &src->reg.reg->uses);
return true;
}
@@ -1320,8 +1311,10 @@ add_reg_def_cb(nir_dest *dest, void *state)
{
nir_instr *instr = state;
- if (!dest->is_ssa)
- _mesa_set_add(dest->reg.reg->defs, instr);
+ if (!dest->is_ssa) {
+ dest->reg.parent_instr = instr;
+ list_addtail(&dest->reg.def_link, &dest->reg.reg->defs);
+ }
return true;
}
@@ -1436,13 +1429,7 @@ nir_instr_insert_after_cf_list(struct exec_list *list, nir_instr *after)
static bool
remove_use_cb(nir_src *src, void *state)
{
- nir_instr *instr = state;
-
- struct set *uses_set = src->is_ssa ? src->ssa->uses : src->reg.reg->uses;
-
- struct set_entry *entry = _mesa_set_search(uses_set, instr);
- if (entry)
- _mesa_set_remove(uses_set, entry);
+ list_del(&src->use_link);
return true;
}
@@ -1450,16 +1437,8 @@ remove_use_cb(nir_src *src, void *state)
static bool
remove_def_cb(nir_dest *dest, void *state)
{
- nir_instr *instr = state;
-
- if (dest->is_ssa)
- return true;
-
- nir_register *reg = dest->reg.reg;
-
- struct set_entry *entry = _mesa_set_search(reg->defs, instr);
- if (entry)
- _mesa_set_remove(reg->defs, entry);
+ if (!dest->is_ssa)
+ list_del(&dest->reg.def_link);
return true;
}
@@ -1834,64 +1813,77 @@ nir_srcs_equal(nir_src src1, nir_src src2)
}
static bool
-src_does_not_use_def(nir_src *src, void *void_def)
+src_is_valid(const nir_src *src)
{
- nir_ssa_def *def = void_def;
-
- if (src->is_ssa) {
- return src->ssa != def;
- } else {
- return true;
- }
+ return src->is_ssa ? (src->ssa != NULL) : (src->reg.reg != NULL);
}
-static bool
-src_does_not_use_reg(nir_src *src, void *void_reg)
+static void
+src_remove_all_uses(nir_src *src)
{
- nir_register *reg = void_reg;
+ for (; src; src = src->is_ssa ? NULL : src->reg.indirect) {
+ if (!src_is_valid(src))
+ continue;
- if (src->is_ssa) {
- return true;
- } else {
- return src->reg.reg != reg;
+ list_del(&src->use_link);
+ }
+}
+
+static void
+src_add_all_uses(nir_src *src, nir_instr *parent_instr, nir_if *parent_if)
+{
+ for (; src; src = src->is_ssa ? NULL : src->reg.indirect) {
+ if (!src_is_valid(src))
+ continue;
+
+ if (parent_instr) {
+ src->parent_instr = parent_instr;
+ if (src->is_ssa)
+ list_addtail(&src->use_link, &src->ssa->uses);
+ else
+ list_addtail(&src->use_link, &src->reg.reg->uses);
+ } else {
+ assert(parent_if);
+ src->parent_if = parent_if;
+ if (src->is_ssa)
+ list_addtail(&src->use_link, &src->ssa->if_uses);
+ else
+ list_addtail(&src->use_link, &src->reg.reg->if_uses);
+ }
}
}
void
nir_instr_rewrite_src(nir_instr *instr, nir_src *src, nir_src new_src)
{
- nir_src old_src = *src;
+ assert(!src_is_valid(src) || src->parent_instr == instr);
+
+ src_remove_all_uses(src);
*src = new_src;
+ src_add_all_uses(src, instr, NULL);
+}
- for (nir_src *iter_src = &old_src; iter_src;
- iter_src = iter_src->is_ssa ? NULL : iter_src->reg.indirect) {
- if (iter_src->is_ssa) {
- nir_ssa_def *ssa = iter_src->ssa;
- if (ssa && nir_foreach_src(instr, src_does_not_use_def, ssa)) {
- struct set_entry *entry = _mesa_set_search(ssa->uses, instr);
- assert(entry);
- _mesa_set_remove(ssa->uses, entry);
- }
- } else {
- nir_register *reg = iter_src->reg.reg;
- if (reg && nir_foreach_src(instr, src_does_not_use_reg, reg)) {
- struct set_entry *entry = _mesa_set_search(reg->uses, instr);
- assert(entry);
- _mesa_set_remove(reg->uses, entry);
- }
- }
- }
+void
+nir_instr_move_src(nir_instr *dest_instr, nir_src *dest, nir_src *src)
+{
+ assert(!src_is_valid(dest) || dest->parent_instr == dest_instr);
- for (nir_src *iter_src = &new_src; iter_src;
- iter_src = iter_src->is_ssa ? NULL : iter_src->reg.indirect) {
- if (iter_src->is_ssa) {
- if (iter_src->ssa)
- _mesa_set_add(iter_src->ssa->uses, instr);
- } else {
- if (iter_src->reg.reg)
- _mesa_set_add(iter_src->reg.reg->uses, instr);
- }
- }
+ src_remove_all_uses(dest);
+ src_remove_all_uses(src);
+ *dest = *src;
+ *src = NIR_SRC_INIT;
+ src_add_all_uses(dest, dest_instr, NULL);
+}
+
+void
+nir_if_rewrite_condition(nir_if *if_stmt, nir_src new_src)
+{
+ nir_src *src = &if_stmt->condition;
+ assert(!src_is_valid(src) || src->parent_if == if_stmt);
+
+ src_remove_all_uses(src);
+ *src = new_src;
+ src_add_all_uses(src, NULL, if_stmt);
}
void
@@ -1900,10 +1892,8 @@ nir_ssa_def_init(nir_instr *instr, nir_ssa_def *def,
{
def->name = name;
def->parent_instr = instr;
- def->uses = _mesa_set_create(instr, _mesa_hash_pointer,
- _mesa_key_pointer_equal);
- def->if_uses = _mesa_set_create(instr, _mesa_hash_pointer,
- _mesa_key_pointer_equal);
+ list_inithead(&def->uses);
+ list_inithead(&def->if_uses);
def->num_components = num_components;
if (instr->block) {
@@ -1924,57 +1914,23 @@ nir_ssa_dest_init(nir_instr *instr, nir_dest *dest,
nir_ssa_def_init(instr, &dest->ssa, num_components, name);
}
-struct ssa_def_rewrite_state {
- void *mem_ctx;
- nir_ssa_def *old;
- nir_src new_src;
-};
-
-static bool
-ssa_def_rewrite_uses_src(nir_src *src, void *void_state)
-{
- struct ssa_def_rewrite_state *state = void_state;
-
- if (src->is_ssa && src->ssa == state->old)
- nir_src_copy(src, &state->new_src, state->mem_ctx);
-
- return true;
-}
-
void
nir_ssa_def_rewrite_uses(nir_ssa_def *def, nir_src new_src, void *mem_ctx)
{
- struct ssa_def_rewrite_state state;
- state.mem_ctx = mem_ctx;
- state.old = def;
- state.new_src = new_src;
-
assert(!new_src.is_ssa || def != new_src.ssa);
- struct set *new_uses, *new_if_uses;
- if (new_src.is_ssa) {
- new_uses = new_src.ssa->uses;
- new_if_uses = new_src.ssa->if_uses;
- } else {
- new_uses = new_src.reg.reg->uses;
- new_if_uses = new_src.reg.reg->if_uses;
- }
-
- struct set_entry *entry;
- set_foreach(def->uses, entry) {
- nir_instr *instr = (nir_instr *)entry->key;
-
- _mesa_set_remove(def->uses, entry);
- nir_foreach_src(instr, ssa_def_rewrite_uses_src, &state);
- _mesa_set_add(new_uses, instr);
+ nir_foreach_use_safe(def, use_src) {
+ nir_instr *src_parent_instr = use_src->parent_instr;
+ list_del(&use_src->use_link);
+ nir_src_copy(use_src, &new_src, mem_ctx);
+ src_add_all_uses(use_src, src_parent_instr, NULL);
}
- set_foreach(def->if_uses, entry) {
- nir_if *if_use = (nir_if *)entry->key;
-
- _mesa_set_remove(def->if_uses, entry);
- nir_src_copy(&if_use->condition, &new_src, mem_ctx);
- _mesa_set_add(new_if_uses, if_use);
+ nir_foreach_if_use_safe(def, use_src) {
+ nir_if *src_parent_if = use_src->parent_if;
+ list_del(&use_src->use_link);
+ nir_src_copy(use_src, &new_src, mem_ctx);
+ src_add_all_uses(use_src, NULL, src_parent_if);
}
}
diff --git a/mesalib/src/glsl/nir/nir.h b/mesalib/src/glsl/nir/nir.h
index 98b0ec328..697d37e95 100644
--- a/mesalib/src/glsl/nir/nir.h
+++ b/mesalib/src/glsl/nir/nir.h
@@ -30,6 +30,7 @@
#include "util/hash_table.h"
#include "../list.h"
#include "GL/gl.h" /* GLenum */
+#include "util/list.h"
#include "util/ralloc.h"
#include "util/set.h"
#include "util/bitset.h"
@@ -397,13 +398,13 @@ typedef struct {
struct nir_instr *parent_instr;
/** set of nir_instr's where this register is used (read from) */
- struct set *uses;
+ struct list_head uses;
/** set of nir_instr's where this register is defined (written to) */
- struct set *defs;
+ struct list_head defs;
/** set of nir_if's where this register is used as a condition */
- struct set *if_uses;
+ struct list_head if_uses;
} nir_register;
typedef enum {
@@ -462,10 +463,10 @@ typedef struct {
nir_instr *parent_instr;
/** set of nir_instr's where this register is used (read from) */
- struct set *uses;
+ struct list_head uses;
/** set of nir_if's where this register is used as a condition */
- struct set *if_uses;
+ struct list_head if_uses;
uint8_t num_components;
} nir_ssa_def;
@@ -481,6 +482,9 @@ typedef struct {
} nir_reg_src;
typedef struct {
+ nir_instr *parent_instr;
+ struct list_head def_link;
+
nir_register *reg;
struct nir_src *indirect; /** < NULL for no indirect offset */
unsigned base_offset;
@@ -488,8 +492,17 @@ typedef struct {
/* TODO def-use chain goes here */
} nir_reg_dest;
+struct nir_if;
+
typedef struct nir_src {
union {
+ nir_instr *parent_instr;
+ struct nir_if *parent_if;
+ };
+
+ struct list_head use_link;
+
+ union {
nir_reg_src reg;
nir_ssa_def *ssa;
};
@@ -497,6 +510,20 @@ typedef struct nir_src {
bool is_ssa;
} nir_src;
+#define NIR_SRC_INIT (nir_src) { { NULL } }
+
+#define nir_foreach_use(reg_or_ssa_def, src) \
+ list_for_each_entry(nir_src, src, &(reg_or_ssa_def)->uses, use_link)
+
+#define nir_foreach_use_safe(reg_or_ssa_def, src) \
+ list_for_each_entry_safe(nir_src, src, &(reg_or_ssa_def)->uses, use_link)
+
+#define nir_foreach_if_use(reg_or_ssa_def, src) \
+ list_for_each_entry(nir_src, src, &(reg_or_ssa_def)->if_uses, use_link)
+
+#define nir_foreach_if_use_safe(reg_or_ssa_def, src) \
+ list_for_each_entry_safe(nir_src, src, &(reg_or_ssa_def)->if_uses, use_link)
+
typedef struct {
union {
nir_reg_dest reg;
@@ -506,10 +533,18 @@ typedef struct {
bool is_ssa;
} nir_dest;
+#define NIR_DEST_INIT (nir_dest) { { { NULL } } }
+
+#define nir_foreach_def(reg, dest) \
+ list_for_each_entry(nir_dest, dest, &(reg)->defs, reg.def_link)
+
+#define nir_foreach_def_safe(reg, dest) \
+ list_for_each_entry_safe(nir_dest, dest, &(reg)->defs, reg.def_link)
+
static inline nir_src
nir_src_for_ssa(nir_ssa_def *def)
{
- nir_src src;
+ nir_src src = NIR_SRC_INIT;
src.is_ssa = true;
src.ssa = def;
@@ -520,7 +555,7 @@ nir_src_for_ssa(nir_ssa_def *def)
static inline nir_src
nir_src_for_reg(nir_register *reg)
{
- nir_src src;
+ nir_src src = NIR_SRC_INIT;
src.is_ssa = false;
src.reg.reg = reg;
@@ -543,12 +578,9 @@ nir_src_get_parent_instr(const nir_src *src)
static inline nir_dest
nir_dest_for_reg(nir_register *reg)
{
- nir_dest dest;
+ nir_dest dest = NIR_DEST_INIT;
- dest.is_ssa = false;
dest.reg.reg = reg;
- dest.reg.indirect = NULL;
- dest.reg.base_offset = 0;
return dest;
}
@@ -1207,7 +1239,7 @@ nir_block_last_instr(nir_block *block)
#define nir_foreach_instr_safe(block, instr) \
foreach_list_typed_safe(nir_instr, instr, node, &(block)->instr_list)
-typedef struct {
+typedef struct nir_if {
nir_cf_node cf_node;
nir_src condition;
@@ -1548,6 +1580,8 @@ bool nir_foreach_src(nir_instr *instr, nir_foreach_src_cb cb, void *state);
nir_const_value *nir_src_as_const_value(nir_src src);
bool nir_srcs_equal(nir_src src1, nir_src src2);
void nir_instr_rewrite_src(nir_instr *instr, nir_src *src, nir_src new_src);
+void nir_instr_move_src(nir_instr *dest_instr, nir_src *dest, nir_src *src);
+void nir_if_rewrite_condition(nir_if *if_stmt, nir_src new_src);
void nir_ssa_dest_init(nir_instr *instr, nir_dest *dest,
unsigned num_components, const char *name);
diff --git a/mesalib/src/glsl/nir/nir_builder.h b/mesalib/src/glsl/nir/nir_builder.h
index d1419ee21..9223e8380 100644
--- a/mesalib/src/glsl/nir/nir_builder.h
+++ b/mesalib/src/glsl/nir/nir_builder.h
@@ -231,8 +231,7 @@ static inline nir_ssa_def *
nir_swizzle(nir_builder *build, nir_ssa_def *src, unsigned swiz[4],
unsigned num_components, bool use_fmov)
{
- nir_alu_src alu_src;
- memset(&alu_src, 0, sizeof(alu_src));
+ nir_alu_src alu_src = { NIR_SRC_INIT };
alu_src.src = nir_src_for_ssa(src);
for (int i = 0; i < 4; i++)
alu_src.swizzle[i] = swiz[i];
@@ -251,8 +250,7 @@ nir_ssa_for_src(nir_builder *build, nir_src src, int num_components)
if (src.is_ssa && src.ssa->num_components == num_components)
return src.ssa;
- nir_alu_src alu;
- memset(&alu, 0, sizeof(alu));
+ nir_alu_src alu = { NIR_SRC_INIT };
alu.src = src;
for (int j = 0; j < 4; j++)
alu.swizzle[j] = j;
diff --git a/mesalib/src/glsl/nir/nir_from_ssa.c b/mesalib/src/glsl/nir/nir_from_ssa.c
index 6a3b141bd..67733e6da 100644
--- a/mesalib/src/glsl/nir/nir_from_ssa.c
+++ b/mesalib/src/glsl/nir/nir_from_ssa.c
@@ -37,7 +37,6 @@
struct from_ssa_state {
void *mem_ctx;
void *dead_ctx;
- struct hash_table *ssa_table;
struct hash_table *merge_node_table;
nir_instr *instr;
nir_function_impl *impl;
@@ -344,45 +343,31 @@ isolate_phi_nodes_block(nir_block *block, void *void_state)
get_parallel_copy_at_end_of_block(src->pred);
assert(pcopy);
- nir_parallel_copy_entry *entry = ralloc(state->dead_ctx,
- nir_parallel_copy_entry);
- exec_list_push_tail(&pcopy->entries, &entry->node);
-
- nir_src_copy(&entry->src, &src->src, state->dead_ctx);
- _mesa_set_add(src->src.ssa->uses, &pcopy->instr);
-
+ nir_parallel_copy_entry *entry = rzalloc(state->dead_ctx,
+ nir_parallel_copy_entry);
nir_ssa_dest_init(&pcopy->instr, &entry->dest,
phi->dest.ssa.num_components, src->src.ssa->name);
+ exec_list_push_tail(&pcopy->entries, &entry->node);
- struct set_entry *use_entry =
- _mesa_set_search(src->src.ssa->uses, instr);
- if (use_entry)
- /* It is possible that a phi node can use the same source twice
- * but for different basic blocks. If that happens, entry will
- * be NULL because we already deleted it. This is safe
- * because, by the time the loop is done, we will have deleted
- * all of the sources of the phi from their respective use sets
- * and moved them to the parallel copy definitions.
- */
- _mesa_set_remove(src->src.ssa->uses, use_entry);
+ assert(src->src.is_ssa);
+ nir_instr_rewrite_src(&pcopy->instr, &entry->src, src->src);
- src->src.ssa = &entry->dest.ssa;
- _mesa_set_add(entry->dest.ssa.uses, instr);
+ nir_instr_rewrite_src(&phi->instr, &src->src,
+ nir_src_for_ssa(&entry->dest.ssa));
}
- nir_parallel_copy_entry *entry = ralloc(state->dead_ctx,
- nir_parallel_copy_entry);
- exec_list_push_tail(&block_pcopy->entries, &entry->node);
-
+ nir_parallel_copy_entry *entry = rzalloc(state->dead_ctx,
+ nir_parallel_copy_entry);
nir_ssa_dest_init(&block_pcopy->instr, &entry->dest,
phi->dest.ssa.num_components, phi->dest.ssa.name);
+ exec_list_push_tail(&block_pcopy->entries, &entry->node);
+
nir_ssa_def_rewrite_uses(&phi->dest.ssa,
nir_src_for_ssa(&entry->dest.ssa),
state->mem_ctx);
- entry->src.is_ssa = true;
- entry->src.ssa = &phi->dest.ssa;
- _mesa_set_add(phi->dest.ssa.uses, &block_pcopy->instr);
+ nir_instr_rewrite_src(&block_pcopy->instr, &entry->src,
+ nir_src_for_ssa(&phi->dest.ssa));
}
return true;
@@ -415,7 +400,7 @@ coalesce_phi_nodes_block(nir_block *block, void *void_state)
}
static void
-agressive_coalesce_parallel_copy(nir_parallel_copy_instr *pcopy,
+aggressive_coalesce_parallel_copy(nir_parallel_copy_instr *pcopy,
struct from_ssa_state *state)
{
nir_foreach_parallel_copy_entry(pcopy, entry) {
@@ -444,7 +429,7 @@ agressive_coalesce_parallel_copy(nir_parallel_copy_instr *pcopy,
}
static bool
-agressive_coalesce_block(nir_block *block, void *void_state)
+aggressive_coalesce_block(nir_block *block, void *void_state)
{
struct from_ssa_state *state = void_state;
@@ -457,7 +442,7 @@ agressive_coalesce_block(nir_block *block, void *void_state)
start_pcopy = nir_instr_as_parallel_copy(instr);
- agressive_coalesce_parallel_copy(start_pcopy, state);
+ aggressive_coalesce_parallel_copy(start_pcopy, state);
break;
}
@@ -467,17 +452,21 @@ agressive_coalesce_block(nir_block *block, void *void_state)
get_parallel_copy_at_end_of_block(block);
if (end_pcopy && end_pcopy != start_pcopy)
- agressive_coalesce_parallel_copy(end_pcopy, state);
+ aggressive_coalesce_parallel_copy(end_pcopy, state);
return true;
}
-static nir_register *
-get_register_for_ssa_def(nir_ssa_def *def, struct from_ssa_state *state)
+static bool
+rewrite_ssa_def(nir_ssa_def *def, void *void_state)
{
+ struct from_ssa_state *state = void_state;
+ nir_register *reg;
+
struct hash_entry *entry =
_mesa_hash_table_search(state->merge_node_table, def);
if (entry) {
+ /* In this case, we're part of a phi web. Use the web's register. */
merge_node *node = (merge_node *)entry->data;
/* If it doesn't have a register yet, create one. Note that all of
@@ -491,20 +480,15 @@ get_register_for_ssa_def(nir_ssa_def *def, struct from_ssa_state *state)
node->set->reg->num_array_elems = 0;
}
- return node->set->reg;
- }
-
- entry = _mesa_hash_table_search(state->ssa_table, def);
- if (entry) {
- return (nir_register *)entry->data;
+ reg = node->set->reg;
} else {
/* We leave load_const SSA values alone. They act as immediates to
* the backend. If it got coalesced into a phi, that's ok.
*/
if (def->parent_instr->type == nir_instr_type_load_const)
- return NULL;
+ return true;
- nir_register *reg = nir_local_reg_create(state->impl);
+ reg = nir_local_reg_create(state->impl);
reg->name = def->name;
reg->num_components = def->num_components;
reg->num_array_elems = 0;
@@ -516,57 +500,24 @@ get_register_for_ssa_def(nir_ssa_def *def, struct from_ssa_state *state)
*/
if (def->parent_instr->type != nir_instr_type_ssa_undef)
reg->parent_instr = def->parent_instr;
-
- _mesa_hash_table_insert(state->ssa_table, def, reg);
- return reg;
}
-}
-
-static bool
-rewrite_ssa_src(nir_src *src, void *void_state)
-{
- struct from_ssa_state *state = void_state;
- if (src->is_ssa) {
- nir_register *reg = get_register_for_ssa_def(src->ssa, state);
+ nir_ssa_def_rewrite_uses(def, nir_src_for_reg(reg), state->mem_ctx);
+ assert(list_empty(&def->uses) && list_empty(&def->if_uses));
- if (reg == NULL) {
- assert(src->ssa->parent_instr->type == nir_instr_type_load_const);
- return true;
- }
-
- memset(src, 0, sizeof *src);
- src->reg.reg = reg;
-
- /* We don't need to remove it from the uses set because that is going
- * away. We just need to add it to the one for the register. */
- _mesa_set_add(reg->uses, state->instr);
- }
-
- return true;
-}
-
-static bool
-rewrite_ssa_dest(nir_dest *dest, void *void_state)
-{
- struct from_ssa_state *state = void_state;
-
- if (dest->is_ssa) {
- nir_register *reg = get_register_for_ssa_def(&dest->ssa, state);
-
- if (reg == NULL) {
- assert(dest->ssa.parent_instr->type == nir_instr_type_load_const);
- return true;
- }
+ if (def->parent_instr->type == nir_instr_type_ssa_undef)
+ return true;
- _mesa_set_destroy(dest->ssa.uses, NULL);
- _mesa_set_destroy(dest->ssa.if_uses, NULL);
+ assert(def->parent_instr->type != nir_instr_type_load_const);
- memset(dest, 0, sizeof *dest);
- dest->reg.reg = reg;
+ /* At this point we know a priori that this SSA def is part of a
+ * nir_dest. We can use exec_node_data to get the dest pointer.
+ */
+ nir_dest *dest = exec_node_data(nir_dest, def, ssa);
- _mesa_set_add(reg->defs, state->instr);
- }
+ *dest = nir_dest_for_reg(reg);
+ dest->reg.parent_instr = state->instr;
+ list_addtail(&dest->reg.def_link, &reg->defs);
return true;
}
@@ -581,8 +532,7 @@ resolve_registers_block(nir_block *block, void *void_state)
nir_foreach_instr_safe(block, instr) {
state->instr = instr;
- nir_foreach_src(instr, rewrite_ssa_src, state);
- nir_foreach_dest(instr, rewrite_ssa_dest, state);
+ nir_foreach_ssa_def(instr, rewrite_ssa_def, state);
if (instr->type == nir_instr_type_ssa_undef ||
instr->type == nir_instr_type_phi) {
@@ -592,23 +542,6 @@ resolve_registers_block(nir_block *block, void *void_state)
}
state->instr = NULL;
- nir_if *following_if = nir_block_get_following_if(block);
- if (following_if && following_if->condition.is_ssa) {
- nir_register *reg = get_register_for_ssa_def(following_if->condition.ssa,
- state);
- if (reg) {
- memset(&following_if->condition, 0, sizeof following_if->condition);
- following_if->condition.reg.reg = reg;
-
- _mesa_set_add(reg->if_uses, following_if);
- } else {
- /* FIXME: We really shouldn't hit this. We should be doing
- * constant control flow propagation.
- */
- assert(following_if->condition.ssa->parent_instr->type == nir_instr_type_load_const);
- }
- }
-
return true;
}
@@ -853,10 +786,8 @@ nir_convert_from_ssa_impl(nir_function_impl *impl)
nir_metadata_dominance);
nir_foreach_block(impl, coalesce_phi_nodes_block, &state);
- nir_foreach_block(impl, agressive_coalesce_block, &state);
+ nir_foreach_block(impl, aggressive_coalesce_block, &state);
- state.ssa_table = _mesa_hash_table_create(NULL, _mesa_hash_pointer,
- _mesa_key_pointer_equal);
nir_foreach_block(impl, resolve_registers_block, &state);
nir_foreach_block(impl, resolve_parallel_copies_block, &state);
@@ -865,7 +796,6 @@ nir_convert_from_ssa_impl(nir_function_impl *impl)
nir_metadata_dominance);
/* Clean up dead instructions and the hash tables */
- _mesa_hash_table_destroy(state.ssa_table, NULL);
_mesa_hash_table_destroy(state.merge_node_table, NULL);
ralloc_free(state.dead_ctx);
}
diff --git a/mesalib/src/glsl/nir/nir_intrinsics.h b/mesalib/src/glsl/nir/nir_intrinsics.h
index 8e28765c1..10192c531 100644
--- a/mesalib/src/glsl/nir/nir_intrinsics.h
+++ b/mesalib/src/glsl/nir/nir_intrinsics.h
@@ -68,6 +68,13 @@ INTRINSIC(interp_var_at_offset, 1, ARR(2), true, 0, 1, 0,
#define BARRIER(name) INTRINSIC(name, 0, ARR(), false, 0, 0, 0, 0)
BARRIER(discard)
+
+/*
+ * Memory barrier with semantics analogous to the memoryBarrier() GLSL
+ * intrinsic.
+ */
+BARRIER(memory_barrier)
+
/** A conditional discard, with a single boolean source. */
INTRINSIC(discard_if, 1, ARR(1), false, 0, 0, 0, 0)
@@ -89,6 +96,33 @@ ATOMIC(inc, 0)
ATOMIC(dec, 0)
ATOMIC(read, NIR_INTRINSIC_CAN_ELIMINATE)
+/*
+ * Image load, store and atomic intrinsics.
+ *
+ * All image intrinsics take an image target passed as a nir_variable. Image
+ * variables contain a number of memory and layout qualifiers that influence
+ * the semantics of the intrinsic.
+ *
+ * All image intrinsics take a four-coordinate vector and a sample index as
+ * first two sources, determining the location within the image that will be
+ * accessed by the intrinsic. Components not applicable to the image target
+ * in use are undefined. Image store takes an additional four-component
+ * argument with the value to be written, and image atomic operations take
+ * either one or two additional scalar arguments with the same meaning as in
+ * the ARB_shader_image_load_store specification.
+ */
+INTRINSIC(image_load, 2, ARR(4, 1), true, 4, 1, 0,
+ NIR_INTRINSIC_CAN_ELIMINATE)
+INTRINSIC(image_store, 3, ARR(4, 1, 4), false, 0, 1, 0, 0)
+INTRINSIC(image_atomic_add, 3, ARR(4, 1, 1), true, 1, 1, 0, 0)
+INTRINSIC(image_atomic_min, 3, ARR(4, 1, 1), true, 1, 1, 0, 0)
+INTRINSIC(image_atomic_max, 3, ARR(4, 1, 1), true, 1, 1, 0, 0)
+INTRINSIC(image_atomic_and, 3, ARR(4, 1, 1), true, 1, 1, 0, 0)
+INTRINSIC(image_atomic_or, 3, ARR(4, 1, 1), true, 1, 1, 0, 0)
+INTRINSIC(image_atomic_xor, 3, ARR(4, 1, 1), true, 1, 1, 0, 0)
+INTRINSIC(image_atomic_exchange, 3, ARR(4, 1, 1), true, 1, 1, 0, 0)
+INTRINSIC(image_atomic_comp_swap, 4, ARR(4, 1, 1, 1), true, 1, 1, 0, 0)
+
#define SYSTEM_VALUE(name, components) \
INTRINSIC(load_##name, 0, ARR(), true, components, 0, 0, \
NIR_INTRINSIC_CAN_ELIMINATE | NIR_INTRINSIC_CAN_REORDER)
diff --git a/mesalib/src/glsl/nir/nir_lower_atomics.c b/mesalib/src/glsl/nir/nir_lower_atomics.c
index e82df0169..f6f89020f 100644
--- a/mesalib/src/glsl/nir/nir_lower_atomics.c
+++ b/mesalib/src/glsl/nir/nir_lower_atomics.c
@@ -78,7 +78,8 @@ lower_instr(nir_intrinsic_instr *instr, nir_function_impl *impl)
nir_deref_as_array(instr->variables[0]->deref.child);
assert(deref_array->deref.child == NULL);
- offset_const->value.u[0] += deref_array->base_offset;
+ offset_const->value.u[0] +=
+ deref_array->base_offset * ATOMIC_COUNTER_SIZE;
if (deref_array->deref_array_type == nir_deref_array_type_indirect) {
nir_load_const_instr *atomic_counter_size =
diff --git a/mesalib/src/glsl/nir/nir_lower_locals_to_regs.c b/mesalib/src/glsl/nir/nir_lower_locals_to_regs.c
index bc6a3d320..28fdec50e 100644
--- a/mesalib/src/glsl/nir/nir_lower_locals_to_regs.c
+++ b/mesalib/src/glsl/nir/nir_lower_locals_to_regs.c
@@ -269,18 +269,16 @@ lower_locals_to_regs_block(nir_block *block, void *void_state)
static nir_block *
compute_reg_usedef_lca(nir_register *reg)
{
- struct set_entry *entry;
nir_block *lca = NULL;
- set_foreach(reg->defs, entry)
- lca = nir_dominance_lca(lca, ((nir_instr *)entry->key)->block);
+ list_for_each_entry(nir_dest, def_dest, &reg->defs, reg.def_link)
+ lca = nir_dominance_lca(lca, def_dest->reg.parent_instr->block);
- set_foreach(reg->uses, entry)
- lca = nir_dominance_lca(lca, ((nir_instr *)entry->key)->block);
+ list_for_each_entry(nir_src, use_src, &reg->uses, use_link)
+ lca = nir_dominance_lca(lca, use_src->parent_instr->block);
- set_foreach(reg->if_uses, entry) {
- nir_if *if_stmt = (nir_if *)entry->key;
- nir_cf_node *prev_node = nir_cf_node_prev(&if_stmt->cf_node);
+ list_for_each_entry(nir_src, use_src, &reg->if_uses, use_link) {
+ nir_cf_node *prev_node = nir_cf_node_prev(&use_src->parent_if->cf_node);
assert(prev_node->type == nir_cf_node_block);
lca = nir_dominance_lca(lca, nir_cf_node_as_block(prev_node));
}
diff --git a/mesalib/src/glsl/nir/nir_lower_samplers.cpp b/mesalib/src/glsl/nir/nir_lower_samplers.cpp
index cf8ab8325..7a0b0a09f 100644
--- a/mesalib/src/glsl/nir/nir_lower_samplers.cpp
+++ b/mesalib/src/glsl/nir/nir_lower_samplers.cpp
@@ -70,44 +70,45 @@ lower_sampler(nir_tex_instr *instr, const struct gl_shader_program *shader_progr
case nir_deref_type_array: {
nir_deref_array *deref_array = nir_deref_as_array(deref->child);
+ assert(deref_array->deref_array_type != nir_deref_array_type_wildcard);
+
+ if (deref_array->deref.child) {
+ ralloc_asprintf_append(&name, "[%u]",
+ deref_array->deref_array_type == nir_deref_array_type_direct ?
+ deref_array->base_offset : 0);
+ } else {
+ assert(deref->child->type->base_type == GLSL_TYPE_SAMPLER);
+ instr->sampler_index = deref_array->base_offset;
+ }
+
/* XXX: We're assuming here that the indirect is the last array
* thing we have. This should be ok for now as we don't support
* arrays_of_arrays yet.
*/
-
- instr->sampler_index *= glsl_get_length(deref->type);
- switch (deref_array->deref_array_type) {
- case nir_deref_array_type_direct:
- instr->sampler_index += deref_array->base_offset;
- if (deref_array->deref.child)
- ralloc_asprintf_append(&name, "[%u]", deref_array->base_offset);
- break;
- case nir_deref_array_type_indirect: {
- instr->src = reralloc(instr, instr->src, nir_tex_src,
- instr->num_srcs + 1);
- memset(&instr->src[instr->num_srcs], 0, sizeof *instr->src);
+ if (deref_array->deref_array_type == nir_deref_array_type_indirect) {
+ /* First, we have to resize the array of texture sources */
+ nir_tex_src *new_srcs = rzalloc_array(instr, nir_tex_src,
+ instr->num_srcs + 1);
+
+ for (unsigned i = 0; i < instr->num_srcs; i++) {
+ new_srcs[i].src_type = instr->src[i].src_type;
+ nir_instr_move_src(&instr->instr, &new_srcs[i].src,
+ &instr->src[i].src);
+ }
+
+ ralloc_free(instr->src);
+ instr->src = new_srcs;
+
+ /* Now we can go ahead and move the source over to being a
+ * first-class texture source.
+ */
instr->src[instr->num_srcs].src_type = nir_tex_src_sampler_offset;
instr->num_srcs++;
-
- nir_instr_rewrite_src(&instr->instr,
- &instr->src[instr->num_srcs - 1].src,
- deref_array->indirect);
+ nir_instr_move_src(&instr->instr,
+ &instr->src[instr->num_srcs - 1].src,
+ &deref_array->indirect);
instr->sampler_array_size = glsl_get_length(deref->type);
-
- nir_src empty;
- memset(&empty, 0, sizeof empty);
- nir_instr_rewrite_src(&instr->instr, &deref_array->indirect, empty);
-
- if (deref_array->deref.child)
- ralloc_strcat(&name, "[0]");
- break;
- }
-
- case nir_deref_array_type_wildcard:
- unreachable("Cannot copy samplers");
- default:
- unreachable("Invalid deref array type");
}
break;
}
diff --git a/mesalib/src/glsl/nir/nir_lower_tex_projector.c b/mesalib/src/glsl/nir/nir_lower_tex_projector.c
index 6b0e9c340..357131cd7 100644
--- a/mesalib/src/glsl/nir/nir_lower_tex_projector.c
+++ b/mesalib/src/glsl/nir/nir_lower_tex_projector.c
@@ -109,12 +109,12 @@ nir_lower_tex_projector_block(nir_block *block, void *void_state)
/* Now move the later tex sources down the array so that the projector
* disappears.
*/
- nir_src dead;
- memset(&dead, 0, sizeof dead);
- nir_instr_rewrite_src(&tex->instr, &tex->src[proj_index].src, dead);
- memmove(&tex->src[proj_index],
- &tex->src[proj_index + 1],
- (tex->num_srcs - proj_index) * sizeof(*tex->src));
+ nir_instr_rewrite_src(&tex->instr, &tex->src[proj_index].src,
+ NIR_SRC_INIT);
+ for (int i = proj_index + 1; i < tex->num_srcs; i++) {
+ tex->src[i-1].src_type = tex->src[i].src_type;
+ nir_instr_move_src(&tex->instr, &tex->src[i-1].src, &tex->src[i].src);
+ }
tex->num_srcs--;
}
diff --git a/mesalib/src/glsl/nir/nir_lower_to_source_mods.c b/mesalib/src/glsl/nir/nir_lower_to_source_mods.c
index 7b4a0f657..94c7e36d4 100644
--- a/mesalib/src/glsl/nir/nir_lower_to_source_mods.c
+++ b/mesalib/src/glsl/nir/nir_lower_to_source_mods.c
@@ -88,8 +88,8 @@ nir_lower_to_source_mods_block(nir_block *block, void *state)
alu->src[i].swizzle[j] = parent->src[0].swizzle[alu->src[i].swizzle[j]];
}
- if (parent->dest.dest.ssa.uses->entries == 0 &&
- parent->dest.dest.ssa.if_uses->entries == 0)
+ if (list_empty(&parent->dest.dest.ssa.uses) &&
+ list_empty(&parent->dest.dest.ssa.if_uses))
nir_instr_remove(&parent->instr);
}
@@ -131,13 +131,13 @@ nir_lower_to_source_mods_block(nir_block *block, void *state)
if (nir_op_infos[alu->op].output_type != nir_type_float)
continue;
- if (alu->dest.dest.ssa.if_uses->entries != 0)
+ if (!list_empty(&alu->dest.dest.ssa.if_uses))
continue;
bool all_children_are_sat = true;
- struct set_entry *entry;
- set_foreach(alu->dest.dest.ssa.uses, entry) {
- const nir_instr *child = entry->key;
+ nir_foreach_use(&alu->dest.dest.ssa, child_src) {
+ assert(child_src->is_ssa);
+ nir_instr *child = child_src->parent_instr;
if (child->type != nir_instr_type_alu) {
all_children_are_sat = false;
continue;
@@ -161,8 +161,12 @@ nir_lower_to_source_mods_block(nir_block *block, void *state)
alu->dest.saturate = true;
- set_foreach(alu->dest.dest.ssa.uses, entry) {
- nir_alu_instr *child_alu = nir_instr_as_alu((nir_instr *)entry->key);
+ nir_foreach_use(&alu->dest.dest.ssa, child_src) {
+ assert(child_src->is_ssa);
+ nir_instr *child = child_src->parent_instr;
+ assert(child->type == nir_instr_type_alu);
+ nir_alu_instr *child_alu = nir_instr_as_alu(child);
+
child_alu->op = nir_op_fmov;
child_alu->dest.saturate = false;
/* We could propagate the dest of our instruction to the
diff --git a/mesalib/src/glsl/nir/nir_lower_vars_to_ssa.c b/mesalib/src/glsl/nir/nir_lower_vars_to_ssa.c
index bb60f4601..ccb8f99df 100644
--- a/mesalib/src/glsl/nir/nir_lower_vars_to_ssa.c
+++ b/mesalib/src/glsl/nir/nir_lower_vars_to_ssa.c
@@ -567,10 +567,11 @@ add_phi_sources(nir_block *block, nir_block *pred,
nir_phi_src *src = ralloc(phi, nir_phi_src);
src->pred = pred;
+ src->src.parent_instr = &phi->instr;
src->src.is_ssa = true;
src->src.ssa = get_ssa_def_for_block(node, pred, state);
- _mesa_set_add(src->src.ssa->uses, instr);
+ list_addtail(&src->src.use_link, &src->src.ssa->uses);
exec_list_push_tail(&phi->srcs, &src->node);
}
diff --git a/mesalib/src/glsl/nir/nir_opcodes.py b/mesalib/src/glsl/nir/nir_opcodes.py
index 264806f5d..56e96d912 100644
--- a/mesalib/src/glsl/nir/nir_opcodes.py
+++ b/mesalib/src/glsl/nir/nir_opcodes.py
@@ -153,8 +153,6 @@ unop("fsat", tfloat, "(src0 > 1.0f) ? 1.0f : ((src0 <= 0.0f) ? 0.0f : src0)")
unop("frcp", tfloat, "1.0f / src0")
unop("frsq", tfloat, "1.0f / sqrtf(src0)")
unop("fsqrt", tfloat, "sqrtf(src0)")
-unop("fexp", tfloat, "expf(src0)") # < e^x
-unop("flog", tfloat, "logf(src0)") # log base e
unop("fexp2", tfloat, "exp2f(src0)")
unop("flog2", tfloat, "log2f(src0)")
unop_convert("f2i", tfloat, tint, "src0") # Float-to-integer conversion.
diff --git a/mesalib/src/glsl/nir/nir_opt_algebraic.py b/mesalib/src/glsl/nir/nir_opt_algebraic.py
index 2a2b9561e..fa039222f 100644
--- a/mesalib/src/glsl/nir/nir_opt_algebraic.py
+++ b/mesalib/src/glsl/nir/nir_opt_algebraic.py
@@ -83,24 +83,37 @@ optimizations = [
# Comparison simplifications
(('inot', ('flt', a, b)), ('fge', a, b)),
(('inot', ('fge', a, b)), ('flt', a, b)),
+ (('inot', ('feq', a, b)), ('fne', a, b)),
+ (('inot', ('fne', a, b)), ('feq', a, b)),
(('inot', ('ilt', a, b)), ('ige', a, b)),
(('inot', ('ige', a, b)), ('ilt', a, b)),
+ (('inot', ('ieq', a, b)), ('ine', a, b)),
+ (('inot', ('ine', a, b)), ('ieq', a, b)),
(('fge', ('fneg', ('fabs', a)), 0.0), ('feq', a, 0.0)),
(('bcsel', ('flt', a, b), a, b), ('fmin', a, b)),
(('bcsel', ('flt', a, b), b, a), ('fmax', a, b)),
(('bcsel', ('inot', 'a@bool'), b, c), ('bcsel', a, c, b)),
(('bcsel', a, ('bcsel', a, b, c), d), ('bcsel', a, b, d)),
+ (('fmin', a, a), a),
+ (('fmax', a, a), a),
+ (('imin', a, a), a),
+ (('imax', a, a), a),
+ (('umin', a, a), a),
+ (('umax', a, a), a),
(('fmin', ('fmax', a, 0.0), 1.0), ('fsat', a), '!options->lower_fsat'),
(('fsat', a), ('fmin', ('fmax', a, 0.0), 1.0), 'options->lower_fsat'),
(('fsat', ('fsat', a)), ('fsat', a)),
(('fmin', ('fmax', ('fmin', ('fmax', a, 0.0), 1.0), 0.0), 1.0), ('fmin', ('fmax', a, 0.0), 1.0)),
(('ior', ('flt', a, b), ('flt', a, c)), ('flt', a, ('fmax', b, c))),
+ (('ior', ('flt', a, c), ('flt', b, c)), ('flt', ('fmin', a, b), c)),
(('ior', ('fge', a, b), ('fge', a, c)), ('fge', a, ('fmin', b, c))),
+ (('ior', ('fge', a, c), ('fge', b, c)), ('fge', ('fmax', a, b), c)),
(('slt', a, b), ('b2f', ('flt', a, b)), 'options->lower_scmp'),
(('sge', a, b), ('b2f', ('fge', a, b)), 'options->lower_scmp'),
(('seq', a, b), ('b2f', ('feq', a, b)), 'options->lower_scmp'),
(('sne', a, b), ('b2f', ('fne', a, b)), 'options->lower_scmp'),
# Emulating booleans
+ (('imul', ('b2i', a), ('b2i', b)), ('b2i', ('iand', a, b))),
(('fmul', ('b2f', a), ('b2f', b)), ('b2f', ('iand', a, b))),
(('fsat', ('fadd', ('b2f', a), ('b2f', b))), ('b2f', ('ior', a, b))),
(('iand', 'a@bool', 1.0), ('b2f', a)),
@@ -136,36 +149,23 @@ optimizations = [
(('ushr', a, 0), a),
# Exponential/logarithmic identities
(('fexp2', ('flog2', a)), a), # 2^lg2(a) = a
- (('fexp', ('flog', a)), a), # e^ln(a) = a
(('flog2', ('fexp2', a)), a), # lg2(2^a) = a
- (('flog', ('fexp', a)), a), # ln(e^a) = a
(('fpow', a, b), ('fexp2', ('fmul', ('flog2', a), b)), 'options->lower_fpow'), # a^b = 2^(lg2(a)*b)
(('fexp2', ('fmul', ('flog2', a), b)), ('fpow', a, b), '!options->lower_fpow'), # 2^(lg2(a)*b) = a^b
- (('fexp', ('fmul', ('flog', a), b)), ('fpow', a, b), '!options->lower_fpow'), # e^(ln(a)*b) = a^b
(('fpow', a, 1.0), a),
(('fpow', a, 2.0), ('fmul', a, a)),
(('fpow', a, 4.0), ('fmul', ('fmul', a, a), ('fmul', a, a))),
(('fpow', 2.0, a), ('fexp2', a)),
(('fsqrt', ('fexp2', a)), ('fexp2', ('fmul', 0.5, a))),
- (('fsqrt', ('fexp', a)), ('fexp', ('fmul', 0.5, a))),
(('frcp', ('fexp2', a)), ('fexp2', ('fneg', a))),
- (('frcp', ('fexp', a)), ('fexp', ('fneg', a))),
(('frsq', ('fexp2', a)), ('fexp2', ('fmul', -0.5, a))),
- (('frsq', ('fexp', a)), ('fexp', ('fmul', -0.5, a))),
(('flog2', ('fsqrt', a)), ('fmul', 0.5, ('flog2', a))),
- (('flog', ('fsqrt', a)), ('fmul', 0.5, ('flog', a))),
(('flog2', ('frcp', a)), ('fneg', ('flog2', a))),
- (('flog', ('frcp', a)), ('fneg', ('flog', a))),
(('flog2', ('frsq', a)), ('fmul', -0.5, ('flog2', a))),
- (('flog', ('frsq', a)), ('fmul', -0.5, ('flog', a))),
(('flog2', ('fpow', a, b)), ('fmul', b, ('flog2', a))),
- (('flog', ('fpow', a, b)), ('fmul', b, ('flog', a))),
(('fadd', ('flog2', a), ('flog2', b)), ('flog2', ('fmul', a, b))),
- (('fadd', ('flog', a), ('flog', b)), ('flog', ('fmul', a, b))),
(('fadd', ('flog2', a), ('fneg', ('flog2', b))), ('flog2', ('fdiv', a, b))),
- (('fadd', ('flog', a), ('fneg', ('flog', b))), ('flog', ('fdiv', a, b))),
(('fmul', ('fexp2', a), ('fexp2', b)), ('fexp2', ('fadd', a, b))),
- (('fmul', ('fexp', a), ('fexp', b)), ('fexp', ('fadd', a, b))),
# Division and reciprocal
(('fdiv', 1.0, a), ('frcp', a)),
(('frcp', ('frcp', a)), a),
@@ -187,6 +187,7 @@ optimizations = [
(('fcsel', a, b, b), b),
# Conversions
+ (('i2b', ('b2i', a)), a),
(('f2i', ('ftrunc', a)), ('f2i', a)),
(('f2u', ('ftrunc', a)), ('f2u', a)),
diff --git a/mesalib/src/glsl/nir/nir_opt_copy_propagate.c b/mesalib/src/glsl/nir/nir_opt_copy_propagate.c
index ee78e5aa0..71367d001 100644
--- a/mesalib/src/glsl/nir/nir_opt_copy_propagate.c
+++ b/mesalib/src/glsl/nir/nir_opt_copy_propagate.c
@@ -93,62 +93,6 @@ is_swizzleless_move(nir_alu_instr *instr)
}
}
-typedef struct {
- nir_ssa_def *def;
- bool found;
-} search_def_state;
-
-static bool
-search_def(nir_src *src, void *_state)
-{
- search_def_state *state = (search_def_state *) _state;
-
- if (src->is_ssa && src->ssa == state->def)
- state->found = true;
-
- return true;
-}
-
-static void
-rewrite_src_instr(nir_src *src, nir_ssa_def *new_def, nir_instr *parent_instr)
-{
- nir_ssa_def *old_def = src->ssa;
-
- src->ssa = new_def;
-
- /*
- * The instruction could still use the old definition in one of its other
- * sources, so only remove the instruction from the uses if there are no
- * more uses left.
- */
-
- search_def_state search_state;
- search_state.def = old_def;
- search_state.found = false;
- nir_foreach_src(parent_instr, search_def, &search_state);
- if (!search_state.found) {
- struct set_entry *entry = _mesa_set_search(old_def->uses, parent_instr);
- assert(entry);
- _mesa_set_remove(old_def->uses, entry);
- }
-
- _mesa_set_add(new_def->uses, parent_instr);
-}
-
-static void
-rewrite_src_if(nir_if *if_stmt, nir_ssa_def *new_def)
-{
- nir_ssa_def *old_def = if_stmt->condition.ssa;
-
- if_stmt->condition.ssa = new_def;
-
- struct set_entry *entry = _mesa_set_search(old_def->if_uses, if_stmt);
- assert(entry);
- _mesa_set_remove(old_def->if_uses, entry);
-
- _mesa_set_add(new_def->if_uses, if_stmt);
-}
-
static bool
copy_prop_src(nir_src *src, nir_instr *parent_instr, nir_if *parent_if)
{
@@ -178,10 +122,14 @@ copy_prop_src(nir_src *src, nir_instr *parent_instr, nir_if *parent_if)
return false;
}
- if (parent_instr)
- rewrite_src_instr(src, alu_instr->src[0].src.ssa, parent_instr);
- else
- rewrite_src_if(parent_if, alu_instr->src[0].src.ssa);
+ if (parent_instr) {
+ nir_instr_rewrite_src(parent_instr, src,
+ nir_src_for_ssa(alu_instr->src[0].src.ssa));
+ } else {
+ assert(src == &parent_if->condition);
+ nir_if_rewrite_condition(parent_if,
+ nir_src_for_ssa(alu_instr->src[0].src.ssa));
+ }
return true;
}
@@ -234,7 +182,8 @@ copy_prop_alu_src(nir_alu_instr *parent_alu_instr, unsigned index)
for (unsigned i = 0; i < 4; i++)
src->swizzle[i] = new_swizzle[i];
- rewrite_src_instr(&src->src, def, &parent_alu_instr->instr);
+ nir_instr_rewrite_src(&parent_alu_instr->instr, &src->src,
+ nir_src_for_ssa(def));
return true;
}
diff --git a/mesalib/src/glsl/nir/nir_opt_gcm.c b/mesalib/src/glsl/nir/nir_opt_gcm.c
index b4f5fd3d5..44068bf37 100644
--- a/mesalib/src/glsl/nir/nir_opt_gcm.c
+++ b/mesalib/src/glsl/nir/nir_opt_gcm.c
@@ -279,9 +279,8 @@ gcm_schedule_late_def(nir_ssa_def *def, void *void_state)
nir_block *lca = NULL;
- struct set_entry *entry;
- set_foreach(def->uses, entry) {
- nir_instr *use_instr = (nir_instr *)entry->key;
+ nir_foreach_use(def, use_src) {
+ nir_instr *use_instr = use_src->parent_instr;
gcm_schedule_late_instr(use_instr, state);
@@ -304,8 +303,8 @@ gcm_schedule_late_def(nir_ssa_def *def, void *void_state)
}
}
- set_foreach(def->if_uses, entry) {
- nir_if *if_stmt = (nir_if *)entry->key;
+ nir_foreach_if_use(def, use_src) {
+ nir_if *if_stmt = use_src->parent_if;
/* For if statements, we consider the block to be the one immediately
* preceding the if CF node.
@@ -377,9 +376,8 @@ gcm_place_instr(nir_instr *instr, struct gcm_state *state);
static bool
gcm_place_instr_def(nir_ssa_def *def, void *state)
{
- struct set_entry *entry;
- set_foreach(def->uses, entry)
- gcm_place_instr((nir_instr *)entry->key, state);
+ nir_foreach_use(def, use_src)
+ gcm_place_instr(use_src->parent_instr, state);
return false;
}
diff --git a/mesalib/src/glsl/nir/nir_opt_global_to_local.c b/mesalib/src/glsl/nir/nir_opt_global_to_local.c
index 00db37ba7..bccb45b62 100644
--- a/mesalib/src/glsl/nir/nir_opt_global_to_local.c
+++ b/mesalib/src/glsl/nir/nir_opt_global_to_local.c
@@ -34,9 +34,8 @@ global_to_local(nir_register *reg)
assert(reg->is_global);
- struct set_entry *entry;
- set_foreach(reg->defs, entry) {
- nir_instr *instr = (nir_instr *) entry->key;
+ nir_foreach_def(reg, def_dest) {
+ nir_instr *instr = def_dest->reg.parent_instr;
nir_function_impl *instr_impl =
nir_cf_node_get_function(&instr->block->cf_node);
if (impl != NULL) {
@@ -47,8 +46,8 @@ global_to_local(nir_register *reg)
}
}
- set_foreach(reg->uses, entry) {
- nir_instr *instr = (nir_instr *) entry->key;
+ nir_foreach_use(reg, use_src) {
+ nir_instr *instr = use_src->parent_instr;
nir_function_impl *instr_impl =
nir_cf_node_get_function(&instr->block->cf_node);
if (impl != NULL) {
@@ -59,8 +58,8 @@ global_to_local(nir_register *reg)
}
}
- set_foreach(reg->if_uses, entry) {
- nir_if *if_stmt = (nir_if *) entry->key;
+ nir_foreach_if_use(reg, use_src) {
+ nir_if *if_stmt = use_src->parent_if;
nir_function_impl *if_impl = nir_cf_node_get_function(&if_stmt->cf_node);
if (impl != NULL) {
if (impl != if_impl)
diff --git a/mesalib/src/glsl/nir/nir_opt_peephole_ffma.c b/mesalib/src/glsl/nir/nir_opt_peephole_ffma.c
index 9d5646fe6..b430eac8e 100644
--- a/mesalib/src/glsl/nir/nir_opt_peephole_ffma.c
+++ b/mesalib/src/glsl/nir/nir_opt_peephole_ffma.c
@@ -41,12 +41,11 @@ struct peephole_ffma_state {
static inline bool
are_all_uses_fadd(nir_ssa_def *def)
{
- if (def->if_uses->entries > 0)
+ if (!list_empty(&def->if_uses))
return false;
- struct set_entry *use_iter;
- set_foreach(def->uses, use_iter) {
- nir_instr *use_instr = (nir_instr *)use_iter->key;
+ nir_foreach_use(def, use_src) {
+ nir_instr *use_instr = use_src->parent_instr;
if (use_instr->type != nir_instr_type_alu)
return false;
@@ -220,7 +219,7 @@ nir_opt_peephole_ffma_block(nir_block *block, void *void_state)
state->mem_ctx);
nir_instr_insert_before(&add->instr, &ffma->instr);
- assert(add->dest.dest.ssa.uses->entries == 0);
+ assert(list_empty(&add->dest.dest.ssa.uses));
nir_instr_remove(&add->instr);
state->progress = true;
diff --git a/mesalib/src/glsl/nir/nir_opt_peephole_select.c b/mesalib/src/glsl/nir/nir_opt_peephole_select.c
index f400cfd66..82c65bb44 100644
--- a/mesalib/src/glsl/nir/nir_opt_peephole_select.c
+++ b/mesalib/src/glsl/nir/nir_opt_peephole_select.c
@@ -98,15 +98,13 @@ block_check_for_allowed_instrs(nir_block *block)
return false;
/* It cannot have any if-uses */
- if (mov->dest.dest.ssa.if_uses->entries != 0)
+ if (!list_empty(&mov->dest.dest.ssa.if_uses))
return false;
/* The only uses of this definition must be phi's in the successor */
- struct set_entry *entry;
- set_foreach(mov->dest.dest.ssa.uses, entry) {
- const nir_instr *dest_instr = entry->key;
- if (dest_instr->type != nir_instr_type_phi ||
- dest_instr->block != block->successors[0])
+ nir_foreach_use(&mov->dest.dest.ssa, use) {
+ if (use->parent_instr->type != nir_instr_type_phi ||
+ use->parent_instr->block != block->successors[0])
return false;
}
break;
diff --git a/mesalib/src/glsl/nir/nir_search.c b/mesalib/src/glsl/nir/nir_search.c
index 5ba016085..0c4e48ce9 100644
--- a/mesalib/src/glsl/nir/nir_search.c
+++ b/mesalib/src/glsl/nir/nir_search.c
@@ -73,6 +73,14 @@ match_value(const nir_search_value *value, nir_alu_instr *instr, unsigned src,
{
uint8_t new_swizzle[4];
+ /* If the source is an explicitly sized source, then we need to reset
+ * both the number of components and the swizzle.
+ */
+ if (nir_op_infos[instr->op].input_sizes[src] != 0) {
+ num_components = nir_op_infos[instr->op].input_sizes[src];
+ swizzle = identity_swizzle;
+ }
+
for (int i = 0; i < num_components; ++i)
new_swizzle[i] = instr->src[src].swizzle[swizzle[i]];
@@ -90,6 +98,7 @@ match_value(const nir_search_value *value, nir_alu_instr *instr, unsigned src,
case nir_search_value_variable: {
nir_search_variable *var = nir_search_value_as_variable(value);
+ assert(var->variable < NIR_SEARCH_MAX_VARIABLES);
if (state->variables_seen & (1 << var->variable)) {
if (!nir_srcs_equal(state->variables[var->variable].src,
@@ -198,16 +207,13 @@ match_expression(const nir_search_expression *expr, nir_alu_instr *instr,
}
}
+ /* Stash off the current variables_seen bitmask. This way we can
+ * restore it prior to matching in the commutative case below.
+ */
+ unsigned variables_seen_stash = state->variables_seen;
+
bool matched = true;
for (unsigned i = 0; i < nir_op_infos[instr->op].num_inputs; i++) {
- /* If the source is an explicitly sized source, then we need to reset
- * both the number of components and the swizzle.
- */
- if (nir_op_infos[instr->op].input_sizes[i] != 0) {
- num_components = nir_op_infos[instr->op].input_sizes[i];
- swizzle = identity_swizzle;
- }
-
if (!match_value(expr->srcs[i], instr, i, num_components,
swizzle, state)) {
matched = false;
@@ -220,6 +226,13 @@ match_expression(const nir_search_expression *expr, nir_alu_instr *instr,
if (nir_op_infos[instr->op].algebraic_properties & NIR_OP_IS_COMMUTATIVE) {
assert(nir_op_infos[instr->op].num_inputs == 2);
+
+ /* Restore the variables_seen bitmask. If we don't do this, then we
+ * could end up with an erroneous failure due to variables found in the
+ * first match attempt above not matching those in the second.
+ */
+ state->variables_seen = variables_seen_stash;
+
if (!match_value(expr->srcs[0], instr, 1, num_components,
swizzle, state))
return false;
@@ -276,7 +289,7 @@ construct_value(const nir_search_value *value, nir_alu_type type,
const nir_search_variable *var = nir_search_value_as_variable(value);
assert(state->variables_seen & (1 << var->variable));
- nir_alu_src val;
+ nir_alu_src val = { NIR_SRC_INIT };
nir_alu_src_copy(&val, &state->variables[var->variable], mem_ctx);
assert(!var->is_constant);
diff --git a/mesalib/src/glsl/nir/nir_to_ssa.c b/mesalib/src/glsl/nir/nir_to_ssa.c
index 53ff54766..a3c35fa04 100644
--- a/mesalib/src/glsl/nir/nir_to_ssa.c
+++ b/mesalib/src/glsl/nir/nir_to_ssa.c
@@ -89,9 +89,8 @@ insert_phi_nodes(nir_function_impl *impl)
w_start = w_end = 0;
iter_count++;
- struct set_entry *entry;
- set_foreach(reg->defs, entry) {
- nir_instr *def = (nir_instr *) entry->key;
+ nir_foreach_def(reg, dest) {
+ nir_instr *def = dest->reg.parent_instr;
if (work[def->block->index] < iter_count)
W[w_end++] = def->block;
work[def->block->index] = iter_count;
@@ -99,6 +98,7 @@ insert_phi_nodes(nir_function_impl *impl)
while (w_start != w_end) {
nir_block *cur = W[w_start++];
+ struct set_entry *entry;
set_foreach(cur->dom_frontier, entry) {
nir_block *next = (nir_block *) entry->key;
@@ -190,13 +190,12 @@ rewrite_use(nir_src *src, void *_state)
if (state->states[index].stack == NULL)
return true;
- src->is_ssa = true;
- src->ssa = get_ssa_src(src->reg.reg, state);
-
+ nir_ssa_def *def = get_ssa_src(src->reg.reg, state);
if (state->parent_instr)
- _mesa_set_add(src->ssa->uses, state->parent_instr);
+ nir_instr_rewrite_src(state->parent_instr, src, nir_src_for_ssa(def));
else
- _mesa_set_add(src->ssa->if_uses, state->parent_if);
+ nir_if_rewrite_condition(state->parent_if, nir_src_for_ssa(def));
+
return true;
}
@@ -219,6 +218,7 @@ rewrite_def_forwards(nir_dest *dest, void *_state)
name = ralloc_asprintf(state->mem_ctx, "%s_%u", dest->reg.reg->name,
state->states[index].num_defs);
+ list_del(&dest->reg.def_link);
nir_ssa_dest_init(state->parent_instr, dest, reg->num_components, name);
/* push our SSA destination on the stack */
@@ -270,6 +270,7 @@ rewrite_alu_instr_forward(nir_alu_instr *instr, rewrite_state *state)
reg->name, state->states[index].num_defs);
instr->dest.write_mask = (1 << num_components) - 1;
+ list_del(&instr->dest.dest.reg.def_link);
nir_ssa_dest_init(&instr->instr, &instr->dest.dest, num_components, name);
if (nir_op_infos[instr->op].output_size == 0) {
@@ -484,7 +485,7 @@ init_rewrite_state(nir_function_impl *impl, rewrite_state *state)
* called after phi nodes are inserted so we can count phi node
* definitions too.
*/
- unsigned stack_size = reg->defs->entries;
+ unsigned stack_size = list_length(&reg->defs);
state->states[reg->index].stack = ralloc_array(state->states,
nir_ssa_def *,
diff --git a/mesalib/src/glsl/nir/nir_validate.c b/mesalib/src/glsl/nir/nir_validate.c
index a7aa79837..da92ed904 100644
--- a/mesalib/src/glsl/nir/nir_validate.c
+++ b/mesalib/src/glsl/nir/nir_validate.c
@@ -97,50 +97,47 @@ typedef struct {
static void validate_src(nir_src *src, validate_state *state);
static void
-validate_reg_src(nir_reg_src *src, validate_state *state)
+validate_reg_src(nir_src *src, validate_state *state)
{
- assert(src->reg != NULL);
+ assert(src->reg.reg != NULL);
struct hash_entry *entry;
- entry = _mesa_hash_table_search(state->regs, src->reg);
+ entry = _mesa_hash_table_search(state->regs, src->reg.reg);
assert(entry);
reg_validate_state *reg_state = (reg_validate_state *) entry->data;
if (state->instr) {
- _mesa_set_add(reg_state->uses, state->instr);
-
- assert(_mesa_set_search(src->reg->uses, state->instr));
+ _mesa_set_add(reg_state->uses, src);
} else {
assert(state->if_stmt);
- _mesa_set_add(reg_state->if_uses, state->if_stmt);
-
- assert(_mesa_set_search(src->reg->if_uses, state->if_stmt));
+ _mesa_set_add(reg_state->if_uses, src);
}
- if (!src->reg->is_global) {
+ if (!src->reg.reg->is_global) {
assert(reg_state->where_defined == state->impl &&
"using a register declared in a different function");
}
- assert((src->reg->num_array_elems == 0 ||
- src->base_offset < src->reg->num_array_elems) &&
+ assert((src->reg.reg->num_array_elems == 0 ||
+ src->reg.base_offset < src->reg.reg->num_array_elems) &&
"definitely out-of-bounds array access");
- if (src->indirect) {
- assert(src->reg->num_array_elems != 0);
- assert((src->indirect->is_ssa || src->indirect->reg.indirect == NULL) &&
+ if (src->reg.indirect) {
+ assert(src->reg.reg->num_array_elems != 0);
+ assert((src->reg.indirect->is_ssa ||
+ src->reg.indirect->reg.indirect == NULL) &&
"only one level of indirection allowed");
- validate_src(src->indirect, state);
+ validate_src(src->reg.indirect, state);
}
}
static void
-validate_ssa_src(nir_ssa_def *def, validate_state *state)
+validate_ssa_src(nir_src *src, validate_state *state)
{
- assert(def != NULL);
+ assert(src->ssa != NULL);
- struct hash_entry *entry = _mesa_hash_table_search(state->ssa_defs, def);
+ struct hash_entry *entry = _mesa_hash_table_search(state->ssa_defs, src->ssa);
assert(entry);
@@ -150,14 +147,10 @@ validate_ssa_src(nir_ssa_def *def, validate_state *state)
"using an SSA value defined in a different function");
if (state->instr) {
- _mesa_set_add(def_state->uses, state->instr);
-
- assert(_mesa_set_search(def->uses, state->instr));
+ _mesa_set_add(def_state->uses, src);
} else {
assert(state->if_stmt);
- _mesa_set_add(def_state->if_uses, state->if_stmt);
-
- assert(_mesa_set_search(def->if_uses, state->if_stmt));
+ _mesa_set_add(def_state->if_uses, src);
}
/* TODO validate that the use is dominated by the definition */
@@ -166,10 +159,15 @@ validate_ssa_src(nir_ssa_def *def, validate_state *state)
static void
validate_src(nir_src *src, validate_state *state)
{
+ if (state->instr)
+ assert(src->parent_instr == state->instr);
+ else
+ assert(src->parent_if == state->if_stmt);
+
if (src->is_ssa)
- validate_ssa_src(src->ssa, state);
+ validate_ssa_src(src, state);
else
- validate_reg_src(&src->reg, state);
+ validate_reg_src(src, state);
}
static void
@@ -201,8 +199,7 @@ validate_reg_dest(nir_reg_dest *dest, validate_state *state)
{
assert(dest->reg != NULL);
- struct set_entry *entry = _mesa_set_search(dest->reg->defs, state->instr);
- assert(entry && "definition not in nir_register.defs");
+ assert(dest->parent_instr == state->instr);
struct hash_entry *entry2;
entry2 = _mesa_hash_table_search(state->regs, dest->reg);
@@ -210,7 +207,7 @@ validate_reg_dest(nir_reg_dest *dest, validate_state *state)
assert(entry2);
reg_validate_state *reg_state = (reg_validate_state *) entry2->data;
- _mesa_set_add(reg_state->defs, state->instr);
+ _mesa_set_add(reg_state->defs, dest);
if (!dest->reg->is_global) {
assert(reg_state->where_defined == state->impl &&
@@ -236,8 +233,13 @@ validate_ssa_def(nir_ssa_def *def, validate_state *state)
assert(!BITSET_TEST(state->ssa_defs_found, def->index));
BITSET_SET(state->ssa_defs_found, def->index);
+ assert(def->parent_instr == state->instr);
+
assert(def->num_components <= 4);
+ list_validate(&def->uses);
+ list_validate(&def->if_uses);
+
ssa_def_validate_state *def_state = ralloc(state->ssa_defs,
ssa_def_validate_state);
def_state->where_defined = state->impl;
@@ -699,6 +701,10 @@ prevalidate_reg_decl(nir_register *reg, bool is_global, validate_state *state)
assert(!BITSET_TEST(state->regs_found, reg->index));
BITSET_SET(state->regs_found, reg->index);
+ list_validate(&reg->uses);
+ list_validate(&reg->defs);
+ list_validate(&reg->if_uses);
+
reg_validate_state *reg_state = ralloc(state->regs, reg_validate_state);
reg_state->uses = _mesa_set_create(reg_state, _mesa_hash_pointer,
_mesa_key_pointer_equal);
@@ -719,47 +725,47 @@ postvalidate_reg_decl(nir_register *reg, validate_state *state)
reg_validate_state *reg_state = (reg_validate_state *) entry->data;
- if (reg_state->uses->entries != reg->uses->entries) {
+ nir_foreach_use(reg, src) {
+ struct set_entry *entry = _mesa_set_search(reg_state->uses, src);
+ assert(entry);
+ _mesa_set_remove(reg_state->uses, entry);
+ }
+
+ if (reg_state->uses->entries != 0) {
printf("extra entries in register uses:\n");
struct set_entry *entry;
- set_foreach(reg->uses, entry) {
- struct set_entry *entry2 =
- _mesa_set_search(reg_state->uses, entry->key);
-
- if (entry2 == NULL) {
- printf("%p\n", entry->key);
- }
- }
+ set_foreach(reg_state->uses, entry)
+ printf("%p\n", entry->key);
abort();
}
- if (reg_state->if_uses->entries != reg->if_uses->entries) {
+ nir_foreach_if_use(reg, src) {
+ struct set_entry *entry = _mesa_set_search(reg_state->if_uses, src);
+ assert(entry);
+ _mesa_set_remove(reg_state->if_uses, entry);
+ }
+
+ if (reg_state->if_uses->entries != 0) {
printf("extra entries in register if_uses:\n");
struct set_entry *entry;
- set_foreach(reg->if_uses, entry) {
- struct set_entry *entry2 =
- _mesa_set_search(reg_state->if_uses, entry->key);
-
- if (entry2 == NULL) {
- printf("%p\n", entry->key);
- }
- }
+ set_foreach(reg_state->if_uses, entry)
+ printf("%p\n", entry->key);
abort();
}
- if (reg_state->defs->entries != reg->defs->entries) {
+ nir_foreach_def(reg, src) {
+ struct set_entry *entry = _mesa_set_search(reg_state->defs, src);
+ assert(entry);
+ _mesa_set_remove(reg_state->defs, entry);
+ }
+
+ if (reg_state->defs->entries != 0) {
printf("extra entries in register defs:\n");
struct set_entry *entry;
- set_foreach(reg->defs, entry) {
- struct set_entry *entry2 =
- _mesa_set_search(reg_state->defs, entry->key);
-
- if (entry2 == NULL) {
- printf("%p\n", entry->key);
- }
- }
+ set_foreach(reg_state->defs, entry)
+ printf("%p\n", entry->key);
abort();
}
@@ -788,32 +794,32 @@ postvalidate_ssa_def(nir_ssa_def *def, void *void_state)
struct hash_entry *entry = _mesa_hash_table_search(state->ssa_defs, def);
ssa_def_validate_state *def_state = (ssa_def_validate_state *)entry->data;
- if (def_state->uses->entries != def->uses->entries) {
- printf("extra entries in SSA def uses:\n");
- struct set_entry *entry;
- set_foreach(def->uses, entry) {
- struct set_entry *entry2 =
- _mesa_set_search(def_state->uses, entry->key);
+ nir_foreach_use(def, src) {
+ struct set_entry *entry = _mesa_set_search(def_state->uses, src);
+ assert(entry);
+ _mesa_set_remove(def_state->uses, entry);
+ }
- if (entry2 == NULL) {
- printf("%p\n", entry->key);
- }
- }
+ if (def_state->uses->entries != 0) {
+ printf("extra entries in register uses:\n");
+ struct set_entry *entry;
+ set_foreach(def_state->uses, entry)
+ printf("%p\n", entry->key);
abort();
}
- if (def_state->if_uses->entries != def->if_uses->entries) {
- printf("extra entries in SSA def uses:\n");
- struct set_entry *entry;
- set_foreach(def->if_uses, entry) {
- struct set_entry *entry2 =
- _mesa_set_search(def_state->if_uses, entry->key);
+ nir_foreach_if_use(def, src) {
+ struct set_entry *entry = _mesa_set_search(def_state->if_uses, src);
+ assert(entry);
+ _mesa_set_remove(def_state->if_uses, entry);
+ }
- if (entry2 == NULL) {
- printf("%p\n", entry->key);
- }
- }
+ if (def_state->if_uses->entries != 0) {
+ printf("extra entries in register uses:\n");
+ struct set_entry *entry;
+ set_foreach(def_state->if_uses, entry)
+ printf("%p\n", entry->key);
abort();
}
diff --git a/mesalib/src/glsl/opt_dead_builtin_varyings.cpp b/mesalib/src/glsl/opt_dead_builtin_varyings.cpp
index 92f20c71d..31719d20c 100644
--- a/mesalib/src/glsl/opt_dead_builtin_varyings.cpp
+++ b/mesalib/src/glsl/opt_dead_builtin_varyings.cpp
@@ -99,6 +99,16 @@ public:
}
else {
this->fragdata_usage |= 1 << index->get_uint_component(0);
+ /* Don't lower fragdata array if the output variable
+ * is not a float variable (or float vector) because it will
+ * generate wrong register assignments because of different
+ * data types.
+ */
+ if (var->type->gl_type != GL_FLOAT &&
+ var->type->gl_type != GL_FLOAT_VEC2 &&
+ var->type->gl_type != GL_FLOAT_VEC3 &&
+ var->type->gl_type != GL_FLOAT_VEC4)
+ this->lower_fragdata_array = false;
}
/* Don't visit the leaves of ir_dereference_array. */
diff --git a/mesalib/src/hgl/GLDispatcher.cpp b/mesalib/src/hgl/GLDispatcher.cpp
index 46b91d57c..a1e905361 100644
--- a/mesalib/src/hgl/GLDispatcher.cpp
+++ b/mesalib/src/hgl/GLDispatcher.cpp
@@ -1,6 +1,6 @@
/*
* Copyright 1998-1999 Precision Insight, Inc., Cedar Park, Texas.
- * Copyright 2000-2012 Haiku, Inc. All Rights Reserved.
+ * Copyright 2000-2015 Haiku, Inc. All Rights Reserved.
* Distributed under the terms of the MIT License.
*
* Authors:
@@ -10,10 +10,11 @@
*/
-extern "C" {
#include "glapi/glapi.h"
#include "glapi/glapi_priv.h"
+
+extern "C" {
/*
* NOTE: this file portion implements C-based dispatch of the OpenGL entrypoints
* (glAccum, glBegin, etc).
diff --git a/mesalib/src/hgl/GLDispatcher.h b/mesalib/src/hgl/GLDispatcher.h
index 44bca8ce5..7ee095d91 100644
--- a/mesalib/src/hgl/GLDispatcher.h
+++ b/mesalib/src/hgl/GLDispatcher.h
@@ -1,6 +1,6 @@
/*
* Copyright 1998-1999 Precision Insight, Inc., Cedar Park, Texas.
- * Copyright 2000-2012 Haiku, Inc. All Rights Reserved.
+ * Copyright 2000-2015 Haiku, Inc. All Rights Reserved.
* Distributed under the terms of the MIT License.
*
* Authors:
@@ -17,9 +17,7 @@
#include "glheader.h"
-extern "C" {
#include "glapi/glapi.h"
-}
class BGLDispatcher
diff --git a/mesalib/src/hgl/SConscript b/mesalib/src/hgl/SConscript
index 70db1494d..71881f504 100644
--- a/mesalib/src/hgl/SConscript
+++ b/mesalib/src/hgl/SConscript
@@ -6,6 +6,7 @@ Import('*')
env = env.Clone()
env.Append(CPPPATH = [
+ '#/src',
'#/src/mapi',
'#/src/mesa',
'#/src/mesa/main',
diff --git a/mesalib/src/loader/loader.h b/mesalib/src/loader/loader.h
index 810e7da7f..60c58f2f8 100644
--- a/mesalib/src/loader/loader.h
+++ b/mesalib/src/loader/loader.h
@@ -27,6 +27,10 @@
#ifndef LOADER_H
#define LOADER_H
+#ifdef __cplusplus
+extern "C" {
+#endif
+
/* Helpers to figure out driver and device name, eg. from pci-id, etc. */
#define _LOADER_DRI (1 << 0)
@@ -61,4 +65,9 @@ loader_get_user_preferred_fd(int default_fd, int *different_device);
void
loader_set_logger(void (*logger)(int level, const char *fmt, ...));
+
+#ifdef __cplusplus
+}
+#endif
+
#endif /* LOADER_H */
diff --git a/mesalib/src/mapi/glapi/gen/ARB_direct_state_access.xml b/mesalib/src/mapi/glapi/gen/ARB_direct_state_access.xml
index 8a092d697..bb9baf5a3 100644
--- a/mesalib/src/mapi/glapi/gen/ARB_direct_state_access.xml
+++ b/mesalib/src/mapi/glapi/gen/ARB_direct_state_access.xml
@@ -152,6 +152,135 @@
<param name="data" type="GLvoid *" />
</function>
+ <!-- Framebuffer object functions -->
+
+ <function name="CreateFramebuffers" offset="assign">
+ <param name="n" type="GLsizei" />
+ <param name="framebuffers" type="GLuint *" />
+ </function>
+
+ <function name="NamedFramebufferRenderbuffer" offset="assign">
+ <param name="framebuffer" type="GLuint" />
+ <param name="attachment" type="GLenum" />
+ <param name="renderbuffertarget" type="GLenum" />
+ <param name="renderbuffer" type="GLuint" />
+ </function>
+
+ <function name="NamedFramebufferParameteri" offset="assign">
+ <param name="framebuffer" type="GLuint" />
+ <param name="pname" type="GLenum" />
+ <param name="param" type="GLint" />
+ </function>
+
+ <function name="NamedFramebufferTexture" offset="assign">
+ <param name="framebuffer" type="GLuint" />
+ <param name="attachment" type="GLenum" />
+ <param name="texture" type="GLuint" />
+ <param name="level" type="GLint" />
+ </function>
+
+ <function name="NamedFramebufferTextureLayer" offset="assign">
+ <param name="framebuffer" type="GLuint" />
+ <param name="attachment" type="GLenum" />
+ <param name="texture" type="GLuint" />
+ <param name="level" type="GLint" />
+ <param name="layer" type="GLint" />
+ </function>
+
+ <function name="NamedFramebufferDrawBuffer" offset="assign">
+ <param name="framebuffer" type="GLuint" />
+ <param name="buf" type="GLenum" />
+ </function>
+
+ <function name="NamedFramebufferDrawBuffers" offset="assign">
+ <param name="framebuffer" type="GLuint" />
+ <param name="n" type="GLsizei" />
+ <param name="bufs" type="const GLenum *" />
+ </function>
+
+ <function name="NamedFramebufferReadBuffer" offset="assign">
+ <param name="framebuffer" type="GLuint" />
+ <param name="buf" type="GLenum" />
+ </function>
+
+ <function name="InvalidateNamedFramebufferData" offset="assign">
+ <param name="framebuffer" type="GLuint" />
+ <param name="numAttachments" type="GLsizei" />
+ <param name="attachments" type="const GLenum *" />
+ </function>
+
+ <function name="InvalidateNamedFramebufferSubData" offset="assign">
+ <param name="framebuffer" type="GLuint" />
+ <param name="numAttachments" type="GLsizei" />
+ <param name="attachments" type="const GLenum *" />
+ <param name="x" type="GLint" />
+ <param name="y" type="GLint" />
+ <param name="width" type="GLsizei" />
+ <param name="height" type="GLsizei" />
+ </function>
+
+ <function name="ClearNamedFramebufferiv" offset="assign">
+ <param name="framebuffer" type="GLuint" />
+ <param name="buffer" type="GLenum" />
+ <param name="drawbuffer" type="GLint" />
+ <param name="value" type="const GLint *" />
+ </function>
+
+ <function name="ClearNamedFramebufferuiv" offset="assign">
+ <param name="framebuffer" type="GLuint" />
+ <param name="buffer" type="GLenum" />
+ <param name="drawbuffer" type="GLint" />
+ <param name="value" type="const GLuint *" />
+ </function>
+
+ <function name="ClearNamedFramebufferfv" offset="assign">
+ <param name="framebuffer" type="GLuint" />
+ <param name="buffer" type="GLenum" />
+ <param name="drawbuffer" type="GLint" />
+ <param name="value" type="const GLfloat *" />
+ </function>
+
+ <function name="ClearNamedFramebufferfi" offset="assign">
+ <param name="framebuffer" type="GLuint" />
+ <param name="buffer" type="GLenum" />
+ <param name="depth" type="GLfloat" />
+ <param name="stencil" type="GLint" />
+ </function>
+
+ <function name="BlitNamedFramebuffer" offset="assign">
+ <param name="readFramebuffer" type="GLuint" />
+ <param name="drawFramebuffer" type="GLuint" />
+ <param name="srcX0" type="GLint" />
+ <param name="srcY0" type="GLint" />
+ <param name="srcX1" type="GLint" />
+ <param name="srcY1" type="GLint" />
+ <param name="dstX0" type="GLint" />
+ <param name="dstY0" type="GLint" />
+ <param name="dstX1" type="GLint" />
+ <param name="dstY1" type="GLint" />
+ <param name="mask" type="GLbitfield" />
+ <param name="filter" type="GLenum" />
+ </function>
+
+ <function name="CheckNamedFramebufferStatus" offset="assign">
+ <return type="GLenum" />
+ <param name="framebuffer" type="GLuint" />
+ <param name="target" type="GLenum" />
+ </function>
+
+ <function name="GetNamedFramebufferParameteriv" offset="assign">
+ <param name="framebuffer" type="GLuint" />
+ <param name="pname" type="GLenum" />
+ <param name="param" type="GLint *" />
+ </function>
+
+ <function name="GetNamedFramebufferAttachmentParameteriv" offset="assign">
+ <param name="framebuffer" type="GLuint" />
+ <param name="attachment" type="GLenum" />
+ <param name="pname" type="GLenum" />
+ <param name="params" type="GLint *" />
+ </function>
+
<!-- Renderbuffer object functions -->
<function name="CreateRenderbuffers" offset="assign">
@@ -448,6 +577,102 @@
<param name="params" type="GLint *" />
</function>
+ <!-- Vertex Array object functions -->
+
+ <function name="CreateVertexArrays" offset="assign">
+ <param name="n" type="GLsizei" />
+ <param name="arrays" type="GLuint *" />
+ </function>
+
+ <function name="DisableVertexArrayAttrib" offset="assign">
+ <param name="vaobj" type="GLuint" />
+ <param name="index" type="GLuint" />
+ </function>
+
+ <function name="EnableVertexArrayAttrib" offset="assign">
+ <param name="vaobj" type="GLuint" />
+ <param name="index" type="GLuint" />
+ </function>
+
+ <function name="VertexArrayElementBuffer" offset="assign">
+ <param name="vaobj" type="GLuint" />
+ <param name="buffer" type="GLuint" />
+ </function>
+
+ <function name="VertexArrayVertexBuffer" offset="assign">
+ <param name="vaobj" type="GLuint" />
+ <param name="bindingindex" type="GLuint" />
+ <param name="buffer" type="GLuint" />
+ <param name="offset" type="GLintptr" />
+ <param name="stride" type="GLsizei" />
+ </function>
+
+ <function name="VertexArrayVertexBuffers" offset="assign">
+ <param name="vaobj" type="GLuint" />
+ <param name="first" type="GLuint" />
+ <param name="count" type="GLsizei" />
+ <param name="buffers" type="const GLuint *" />
+ <param name="offsets" type="const GLintptr *" />
+ <param name="strides" type="const GLsizei *" />
+ </function>
+
+ <function name="VertexArrayAttribFormat" offset="assign">
+ <param name="vaobj" type="GLuint" />
+ <param name="attribindex" type="GLuint" />
+ <param name="size" type="GLint" />
+ <param name="type" type="GLenum" />
+ <param name="normalized" type="GLboolean" />
+ <param name="relativeoffset" type="GLuint" />
+ </function>
+
+ <function name="VertexArrayAttribIFormat" offset="assign">
+ <param name="vaobj" type="GLuint" />
+ <param name="attribindex" type="GLuint" />
+ <param name="size" type="GLint" />
+ <param name="type" type="GLenum" />
+ <param name="relativeoffset" type="GLuint" />
+ </function>
+
+ <function name="VertexArrayAttribLFormat" offset="assign">
+ <param name="vaobj" type="GLuint" />
+ <param name="attribindex" type="GLuint" />
+ <param name="size" type="GLint" />
+ <param name="type" type="GLenum" />
+ <param name="relativeoffset" type="GLuint" />
+ </function>
+
+ <function name="VertexArrayAttribBinding" offset="assign">
+ <param name="vaobj" type="GLuint" />
+ <param name="attribindex" type="GLuint" />
+ <param name="bindingindex" type="GLuint" />
+ </function>
+
+ <function name="VertexArrayBindingDivisor" offset="assign">
+ <param name="vaobj" type="GLuint" />
+ <param name="bindingindex" type="GLuint" />
+ <param name="divisor" type="GLuint" />
+ </function>
+
+ <function name="GetVertexArrayiv" offset="assign">
+ <param name="vaobj" type="GLuint" />
+ <param name="pname" type="GLenum" />
+ <param name="param" type="GLint *" />
+ </function>
+
+ <function name="GetVertexArrayIndexediv" offset="assign">
+ <param name="vaobj" type="GLuint" />
+ <param name="index" type="GLuint" />
+ <param name="pname" type="GLenum" />
+ <param name="param" type="GLint *" />
+ </function>
+
+ <function name="GetVertexArrayIndexed64iv" offset="assign">
+ <param name="vaobj" type="GLuint" />
+ <param name="index" type="GLuint" />
+ <param name="pname" type="GLenum" />
+ <param name="param" type="GLint64 *" />
+ </function>
+
<!-- Sampler object functions -->
<function name="CreateSamplers" offset="assign">
diff --git a/mesalib/src/mapi/glapi/gen/ARB_framebuffer_object.xml b/mesalib/src/mapi/glapi/gen/ARB_framebuffer_object.xml
index 7c547c167..999a8ef13 100644
--- a/mesalib/src/mapi/glapi/gen/ARB_framebuffer_object.xml
+++ b/mesalib/src/mapi/glapi/gen/ARB_framebuffer_object.xml
@@ -247,7 +247,7 @@
<param name="textarget" type="GLenum"/>
<param name="texture" type="GLuint"/>
<param name="level" type="GLint"/>
- <param name="zoffset" type="GLint"/>
+ <param name="layer" type="GLint"/>
<glx rop="4323"/>
</function>
diff --git a/mesalib/src/mapi/glapi/gen/ARB_vertex_attrib_64bit.xml b/mesalib/src/mapi/glapi/gen/ARB_vertex_attrib_64bit.xml
new file mode 100644
index 000000000..fc49f84b5
--- /dev/null
+++ b/mesalib/src/mapi/glapi/gen/ARB_vertex_attrib_64bit.xml
@@ -0,0 +1,70 @@
+<?xml version="1.0"?>
+<!DOCTYPE OpenGLAPI SYSTEM "gl_API.dtd">
+
+<OpenGLAPI>
+
+<category name="GL_ARB_vertex_attrib_64bit" number="99">
+
+ <function name="VertexAttribL1d" offset="assign">
+ <param name="index" type="GLuint"/>
+ <param name="x" type="GLdouble"/>
+ </function>
+
+ <function name="VertexAttribL2d" offset="assign">
+ <param name="index" type="GLuint"/>
+ <param name="x" type="GLdouble"/>
+ <param name="y" type="GLdouble"/>
+ </function>
+
+ <function name="VertexAttribL3d" offset="assign">
+ <param name="index" type="GLuint"/>
+ <param name="x" type="GLdouble"/>
+ <param name="y" type="GLdouble"/>
+ <param name="z" type="GLdouble"/>
+ </function>
+
+ <function name="VertexAttribL4d" offset="assign">
+ <param name="index" type="GLuint"/>
+ <param name="x" type="GLdouble"/>
+ <param name="y" type="GLdouble"/>
+ <param name="z" type="GLdouble"/>
+ <param name="w" type="GLdouble"/>
+ </function>
+
+ <function name="VertexAttribL1dv" offset="assign">
+ <param name="index" type="GLuint"/>
+ <param name="v" type="const GLdouble *"/>
+ </function>
+
+ <function name="VertexAttribL2dv" offset="assign">
+ <param name="index" type="GLuint"/>
+ <param name="v" type="const GLdouble *"/>
+ </function>
+
+ <function name="VertexAttribL3dv" offset="assign">
+ <param name="index" type="GLuint"/>
+ <param name="v" type="const GLdouble *"/>
+ </function>
+
+ <function name="VertexAttribL4dv" offset="assign">
+ <param name="index" type="GLuint"/>
+ <param name="v" type="const GLdouble *"/>
+ </function>
+
+ <function name="VertexAttribLPointer" offset="assign">
+ <param name="index" type="GLuint"/>
+ <param name="size" type="GLint"/>
+ <param name="type" type="GLenum"/>
+ <param name="stride" type="GLsizei"/>
+ <param name="pointer" type="const GLvoid *"/>
+ </function>
+
+ <function name="GetVertexAttribLdv" offset="assign">
+ <param name="index" type="GLuint"/>
+ <param name="pname" type="GLenum"/>
+ <param name="params" type="GLdouble *"/>
+ </function>
+</category>
+
+</OpenGLAPI>
+
diff --git a/mesalib/src/mapi/glapi/gen/Makefile.am b/mesalib/src/mapi/glapi/gen/Makefile.am
index 1c4b86aab..c8d417468 100644
--- a/mesalib/src/mapi/glapi/gen/Makefile.am
+++ b/mesalib/src/mapi/glapi/gen/Makefile.am
@@ -163,6 +163,7 @@ API_XML = \
ARB_texture_view.xml \
ARB_uniform_buffer_object.xml \
ARB_vertex_array_object.xml \
+ ARB_vertex_attrib_64bit.xml \
ARB_vertex_attrib_binding.xml \
ARB_viewport_array.xml \
AMD_draw_buffers_blend.xml \
diff --git a/mesalib/src/mapi/glapi/gen/gl_API.xml b/mesalib/src/mapi/glapi/gen/gl_API.xml
index a8a6db683..d1565989c 100644
--- a/mesalib/src/mapi/glapi/gen/gl_API.xml
+++ b/mesalib/src/mapi/glapi/gen/gl_API.xml
@@ -8253,7 +8253,9 @@
<!-- No new functions, types, enums. -->
</category>
-<!-- ARB extensions #99...#108 -->
+<xi:include href="ARB_vertex_attrib_64bit.xml" xmlns:xi="http://www.w3.org/2001/XInclude"/>
+
+<!-- ARB extensions #100...#108 -->
<xi:include href="ARB_ES2_compatibility.xml" xmlns:xi="http://www.w3.org/2001/XInclude"/>
diff --git a/mesalib/src/mapi/glapi/gen/gl_genexec.py b/mesalib/src/mapi/glapi/gen/gl_genexec.py
index 7151f0de1..4e76fe3c2 100644
--- a/mesalib/src/mapi/glapi/gen/gl_genexec.py
+++ b/mesalib/src/mapi/glapi/gen/gl_genexec.py
@@ -183,8 +183,8 @@ class PrintCode(gl_XML.gl_print_base):
if 'es1' in f.api_map:
condition_parts.append('ctx->API == API_OPENGLES')
if 'es2' in f.api_map:
- if f.api_map['es2'] == 3:
- condition_parts.append('_mesa_is_gles3(ctx)')
+ if f.api_map['es2'] > 2.0:
+ condition_parts.append('(ctx->API == API_OPENGLES2 && ctx->Version >= {0})'.format(int(f.api_map['es2'] * 10)))
else:
condition_parts.append('ctx->API == API_OPENGLES2')
if not condition_parts:
diff --git a/mesalib/src/mapi/glapi/glapi_priv.h b/mesalib/src/mapi/glapi/glapi_priv.h
index 50f710edc..337913acc 100644
--- a/mesalib/src/mapi/glapi/glapi_priv.h
+++ b/mesalib/src/mapi/glapi/glapi_priv.h
@@ -49,6 +49,10 @@ typedef void *GLeglImageOES;
#include "glapi/glapi.h"
+#ifdef __cplusplus
+extern "C" {
+#endif
+
/* getproc */
extern void
@@ -106,4 +110,8 @@ get_entrypoint_address(unsigned int functionOffset);
#define MAX_EXTENSION_FUNCS 256
+#ifdef __cplusplus
+}
+#endif
+
#endif
diff --git a/mesalib/src/mesa/Makefile.sources b/mesalib/src/mesa/Makefile.sources
index 1293d4135..83f500fbf 100644
--- a/mesalib/src/mesa/Makefile.sources
+++ b/mesalib/src/mesa/Makefile.sources
@@ -434,6 +434,8 @@ STATETRACKER_FILES = \
state_tracker/st_cb_flush.h \
state_tracker/st_cb_msaa.c \
state_tracker/st_cb_msaa.h \
+ state_tracker/st_cb_perfmon.c \
+ state_tracker/st_cb_perfmon.h \
state_tracker/st_cb_program.c \
state_tracker/st_cb_program.h \
state_tracker/st_cb_queryobj.c \
diff --git a/mesalib/src/mesa/drivers/common/driverfuncs.c b/mesalib/src/mesa/drivers/common/driverfuncs.c
index 0d094ddf4..71c1a7639 100644
--- a/mesalib/src/mesa/drivers/common/driverfuncs.c
+++ b/mesalib/src/mesa/drivers/common/driverfuncs.c
@@ -172,7 +172,7 @@ _mesa_init_driver_functions(struct dd_function_table *driver)
driver->UnmapRenderbuffer = _swrast_unmap_soft_renderbuffer;
driver->RenderTexture = _swrast_render_texture;
driver->FinishRenderTexture = _swrast_finish_render_texture;
- driver->FramebufferRenderbuffer = _mesa_framebuffer_renderbuffer;
+ driver->FramebufferRenderbuffer = _mesa_FramebufferRenderbuffer_sw;
driver->ValidateFramebuffer = _mesa_validate_framebuffer;
driver->BlitFramebuffer = _swrast_BlitFramebuffer;
diff --git a/mesalib/src/mesa/drivers/common/meta.c b/mesalib/src/mesa/drivers/common/meta.c
index d2ab7b8de..214a68a91 100644
--- a/mesalib/src/mesa/drivers/common/meta.c
+++ b/mesalib/src/mesa/drivers/common/meta.c
@@ -1211,7 +1211,8 @@ _mesa_meta_end(struct gl_context *ctx)
_mesa_BindRenderbuffer(GL_RENDERBUFFER, save->RenderbufferName);
if (state & MESA_META_DRAW_BUFFERS) {
- _mesa_drawbuffers(ctx, ctx->Const.MaxDrawBuffers, save->ColorDrawBuffers, NULL);
+ _mesa_drawbuffers(ctx, ctx->DrawBuffer, ctx->Const.MaxDrawBuffers,
+ save->ColorDrawBuffers, NULL);
}
ctx->Meta->SaveStackDepth--;
diff --git a/mesalib/src/mesa/drivers/dri/swrast/swrast.c b/mesalib/src/mesa/drivers/dri/swrast/swrast.c
index d1bb72139..cbc946c3f 100644
--- a/mesalib/src/mesa/drivers/dri/swrast/swrast.c
+++ b/mesalib/src/mesa/drivers/dri/swrast/swrast.c
@@ -61,6 +61,9 @@
#include "swrast_priv.h"
#include "swrast/s_context.h"
+#include <sys/types.h>
+#include <sys/sysctl.h>
+
const __DRIextension **__driDriverGetExtensions_swrast(void);
const char * const swrast_vendor_string = "Mesa Project";
@@ -137,6 +140,16 @@ swrast_query_renderer_integer(__DRIscreen *psp, int param,
value[0] = 0;
return 0;
case __DRI2_RENDERER_VIDEO_MEMORY: {
+ /* This should probably share code with os_get_total_physical_memory()
+ * from src/gallium/auxiliary/os/os_misc.c
+ */
+#if defined(CTL_HW) && defined(HW_MEMSIZE)
+ int mib[2] = { CTL_HW, HW_MEMSIZE };
+ unsigned long system_memory_bytes;
+ size_t len = sizeof(system_memory_bytes);
+ if (sysctl(mib, 2, &system_memory_bytes, &len, NULL, 0) != 0)
+ return -1;
+#elif defined(_SC_PHYS_PAGES) && defined(_SC_PAGE_SIZE)
/* XXX: Do we want to return the full amount of system memory ? */
const long system_memory_pages = sysconf(_SC_PHYS_PAGES);
const long system_page_size = sysconf(_SC_PAGE_SIZE);
@@ -146,6 +159,9 @@ swrast_query_renderer_integer(__DRIscreen *psp, int param,
const uint64_t system_memory_bytes = (uint64_t) system_memory_pages
* (uint64_t) system_page_size;
+#else
+#error "Unsupported platform"
+#endif
const unsigned system_memory_megabytes =
(unsigned) (system_memory_bytes / (1024 * 1024));
@@ -942,6 +958,7 @@ static const __DRIextension *swrast_driver_extensions[] = {
&driCoreExtension.base,
&driSWRastExtension.base,
&driCopySubBufferExtension.base,
+ &dri2ConfigQueryExtension.base,
&swrast_vtable.base,
NULL
};
diff --git a/mesalib/src/mesa/main/api_arrayelt.c b/mesalib/src/mesa/main/api_arrayelt.c
index ea015fd65..92d8238f4 100644
--- a/mesalib/src/mesa/main/api_arrayelt.c
+++ b/mesalib/src/mesa/main/api_arrayelt.c
@@ -1258,12 +1258,37 @@ VertexAttribI4uiv(GLuint index, const GLuint *v)
CALL_VertexAttribI4uivEXT(GET_DISPATCH(), (index, v));
}
+/* GL_DOUBLE unconverted attributes */
+
+static void GLAPIENTRY
+VertexAttribL1dv(GLuint index, const GLdouble *v)
+{
+ CALL_VertexAttribL1dv(GET_DISPATCH(), (index, v));
+}
+
+static void GLAPIENTRY
+VertexAttribL2dv(GLuint index, const GLdouble *v)
+{
+ CALL_VertexAttribL2dv(GET_DISPATCH(), (index, v));
+}
+
+static void GLAPIENTRY
+VertexAttribL3dv(GLuint index, const GLdouble *v)
+{
+ CALL_VertexAttribL3dv(GET_DISPATCH(), (index, v));
+}
+
+static void GLAPIENTRY
+VertexAttribL4dv(GLuint index, const GLdouble *v)
+{
+ CALL_VertexAttribL4dv(GET_DISPATCH(), (index, v));
+}
/*
* Array [unnormalized/normalized/integer][size][type] of VertexAttrib
* functions
*/
-static attrib_func AttribFuncsARB[3][4][NUM_TYPES] = {
+static attrib_func AttribFuncsARB[4][4][NUM_TYPES] = {
{
/* non-normalized */
{
@@ -1405,7 +1430,55 @@ static attrib_func AttribFuncsARB[3][4][NUM_TYPES] = {
NULL, /* GL_FLOAT */
NULL /* GL_DOUBLE */
}
+ },
+ {
+ /* double-valued */
+ {
+ /* size 1 */
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ (attrib_func) VertexAttribL1dv,
+ },
+ {
+ /* size 2 */
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ (attrib_func) VertexAttribL2dv,
+ },
+ {
+ /* size 3 */
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ (attrib_func) VertexAttribL3dv,
+ },
+ {
+ /* size 4 */
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ (attrib_func) VertexAttribL4dv,
+ }
}
+
};
@@ -1571,7 +1644,9 @@ _ae_update_state(struct gl_context *ctx)
* change from one execution of _ae_ArrayElement() to
* the next. Doing so caused UT to break.
*/
- if (at->array->Integer)
+ if (at->array->Doubles)
+ intOrNorm = 3;
+ else if (at->array->Integer)
intOrNorm = 2;
else if (at->array->Normalized)
intOrNorm = 1;
diff --git a/mesalib/src/mesa/main/api_loopback.c b/mesalib/src/mesa/main/api_loopback.c
index d10ae15ea..9932a8373 100644
--- a/mesalib/src/mesa/main/api_loopback.c
+++ b/mesalib/src/mesa/main/api_loopback.c
@@ -84,6 +84,10 @@
#define ATTRIBI_4UI(index,x,y,z,w) CALL_VertexAttribI4uiEXT(GET_DISPATCH(), (index,x,y,z,w))
+#define ATTRIB1_D(index,x) CALL_VertexAttribL1d(GET_DISPATCH(), (index,x))
+#define ATTRIB2_D(index,x,y) CALL_VertexAttribL2d(GET_DISPATCH(), (index,x,y))
+#define ATTRIB3_D(index,x,y,z) CALL_VertexAttribL3d(GET_DISPATCH(), (index,x,y,z))
+#define ATTRIB4_D(index,x,y,z,w) CALL_VertexAttribL4d(GET_DISPATCH(), (index,x,y,z,w))
void GLAPIENTRY
_mesa_Color3b( GLbyte red, GLbyte green, GLbyte blue )
@@ -1490,8 +1494,53 @@ _mesa_VertexAttribI4usv(GLuint index, const GLushort *v)
ATTRIBI_4UI(index, v[0], v[1], v[2], v[3]);
}
+void GLAPIENTRY
+_mesa_VertexAttribL1d(GLuint index, GLdouble x)
+{
+ ATTRIB1_D(index, x);
+}
+
+void GLAPIENTRY
+_mesa_VertexAttribL2d(GLuint index, GLdouble x, GLdouble y)
+{
+ ATTRIB2_D(index, x, y);
+}
+void GLAPIENTRY
+_mesa_VertexAttribL3d(GLuint index, GLdouble x, GLdouble y, GLdouble z)
+{
+ ATTRIB3_D(index, x, y, z);
+}
+void GLAPIENTRY
+_mesa_VertexAttribL4d(GLuint index, GLdouble x, GLdouble y, GLdouble z, GLdouble w)
+{
+ ATTRIB4_D(index, x, y, z, w);
+}
+
+void GLAPIENTRY
+_mesa_VertexAttribL1dv(GLuint index, const GLdouble *v)
+{
+ ATTRIB1_D(index, v[0]);
+}
+
+void GLAPIENTRY
+_mesa_VertexAttribL2dv(GLuint index, const GLdouble *v)
+{
+ ATTRIB2_D(index, v[0], v[1]);
+}
+
+void GLAPIENTRY
+_mesa_VertexAttribL3dv(GLuint index, const GLdouble *v)
+{
+ ATTRIB3_D(index, v[0], v[1], v[2]);
+}
+
+void GLAPIENTRY
+_mesa_VertexAttribL4dv(GLuint index, const GLdouble *v)
+{
+ ATTRIB4_D(index, v[0], v[1], v[2], v[3]);
+}
/*
* This code never registers handlers for any of the entry points
@@ -1723,5 +1772,16 @@ _mesa_loopback_init_api_table(const struct gl_context *ctx,
SET_VertexAttribI4sv(dest, _mesa_VertexAttribI4sv);
SET_VertexAttribI4ubv(dest, _mesa_VertexAttribI4ubv);
SET_VertexAttribI4usv(dest, _mesa_VertexAttribI4usv);
+
+ /* GL 4.1 / GL_ARB_vertex_attrib_64bit */
+ SET_VertexAttribL1d(dest, _mesa_VertexAttribL1d);
+ SET_VertexAttribL2d(dest, _mesa_VertexAttribL2d);
+ SET_VertexAttribL3d(dest, _mesa_VertexAttribL3d);
+ SET_VertexAttribL4d(dest, _mesa_VertexAttribL4d);
+
+ SET_VertexAttribL1dv(dest, _mesa_VertexAttribL1dv);
+ SET_VertexAttribL2dv(dest, _mesa_VertexAttribL2dv);
+ SET_VertexAttribL3dv(dest, _mesa_VertexAttribL3dv);
+ SET_VertexAttribL4dv(dest, _mesa_VertexAttribL4dv);
}
}
diff --git a/mesalib/src/mesa/main/api_loopback.h b/mesalib/src/mesa/main/api_loopback.h
index 44514405b..026bfd68e 100644
--- a/mesalib/src/mesa/main/api_loopback.h
+++ b/mesalib/src/mesa/main/api_loopback.h
@@ -464,5 +464,21 @@ _mesa_VertexAttribI4ubv(GLuint index, const GLubyte *v);
void GLAPIENTRY
_mesa_VertexAttribI4usv(GLuint index, const GLushort *v);
+void GLAPIENTRY
+_mesa_VertexAttribL1d(GLuint index, GLdouble x);
+void GLAPIENTRY
+_mesa_VertexAttribL2d(GLuint index, GLdouble x, GLdouble y);
+void GLAPIENTRY
+_mesa_VertexAttribL3d(GLuint index, GLdouble x, GLdouble y, GLdouble z);
+void GLAPIENTRY
+_mesa_VertexAttribL4d(GLuint index, GLdouble x, GLdouble y, GLdouble z, GLdouble w);
+void GLAPIENTRY
+_mesa_VertexAttribL1dv(GLuint index, const GLdouble *v);
+void GLAPIENTRY
+_mesa_VertexAttribL2dv(GLuint index, const GLdouble *v);
+void GLAPIENTRY
+_mesa_VertexAttribL3dv(GLuint index, const GLdouble *v);
+void GLAPIENTRY
+_mesa_VertexAttribL4dv(GLuint index, const GLdouble *v);
#endif /* API_LOOPBACK_H */
diff --git a/mesalib/src/mesa/main/arrayobj.c b/mesalib/src/mesa/main/arrayobj.c
index 3c8ffb5a4..320f435ea 100644
--- a/mesalib/src/mesa/main/arrayobj.c
+++ b/mesalib/src/mesa/main/arrayobj.c
@@ -75,6 +75,61 @@ _mesa_lookup_vao(struct gl_context *ctx, GLuint id)
/**
+ * Looks up the array object for the given ID.
+ *
+ * Unlike _mesa_lookup_vao, this function generates a GL_INVALID_OPERATION
+ * error if the array object does not exist. It also returns the default
+ * array object when ctx is a compatibility profile context and id is zero.
+ */
+struct gl_vertex_array_object *
+_mesa_lookup_vao_err(struct gl_context *ctx, GLuint id, const char *caller)
+{
+ /* The ARB_direct_state_access specification says:
+ *
+ * "<vaobj> is [compatibility profile:
+ * zero, indicating the default vertex array object, or]
+ * the name of the vertex array object."
+ */
+ if (id == 0) {
+ if (ctx->API == API_OPENGL_CORE) {
+ _mesa_error(ctx, GL_INVALID_OPERATION,
+ "%s(zero is not valid vaobj name in a core profile "
+ "context)", caller);
+ return NULL;
+ }
+
+ return ctx->Array.DefaultVAO;
+ } else {
+ struct gl_vertex_array_object *vao;
+
+ if (ctx->Array.LastLookedUpVAO &&
+ ctx->Array.LastLookedUpVAO->Name == id) {
+ vao = ctx->Array.LastLookedUpVAO;
+ } else {
+ vao = (struct gl_vertex_array_object *)
+ _mesa_HashLookup(ctx->Array.Objects, id);
+
+ /* The ARB_direct_state_access specification says:
+ *
+ * "An INVALID_OPERATION error is generated if <vaobj> is not
+ * [compatibility profile: zero or] the name of an existing
+ * vertex array object."
+ */
+ if (!vao || !vao->EverBound) {
+ _mesa_error(ctx, GL_INVALID_OPERATION,
+ "%s(non-existent vaobj=%u)", caller, id);
+ return NULL;
+ }
+
+ _mesa_reference_vao(ctx, &ctx->Array.LastLookedUpVAO, vao);
+ }
+
+ return vao;
+ }
+}
+
+
+/**
* For all the vertex binding points in the array object, unbind any pointers
* to any buffer objects (VBOs).
* This is done just prior to array object destruction.
@@ -200,6 +255,7 @@ init_array(struct gl_context *ctx,
array->Enabled = GL_FALSE;
array->Normalized = GL_FALSE;
array->Integer = GL_FALSE;
+ array->Doubles = GL_FALSE;
array->_ElementSize = size * _mesa_sizeof_type(type);
array->VertexBinding = index;
@@ -469,6 +525,9 @@ _mesa_DeleteVertexArrays(GLsizei n, const GLuint *ids)
/* The ID is immediately freed for re-use */
remove_array_object(ctx, obj);
+ if (ctx->Array.LastLookedUpVAO == obj)
+ _mesa_reference_vao(ctx, &ctx->Array.LastLookedUpVAO, NULL);
+
/* Unreference the array object.
* If refcount hits zero, the object will be deleted.
*/
@@ -480,19 +539,23 @@ _mesa_DeleteVertexArrays(GLsizei n, const GLuint *ids)
/**
* Generate a set of unique array object IDs and store them in \c arrays.
- * Helper for _mesa_GenVertexArrays[APPLE]() functions below.
+ * Helper for _mesa_GenVertexArrays[APPLE]() and _mesa_CreateVertexArrays()
+ * below.
+ *
* \param n Number of IDs to generate.
* \param arrays Array of \c n locations to store the IDs.
- * \param vboOnly Will arrays have to reside in VBOs?
+ * \param create Indicates that the objects should also be created.
+ * \param func The name of the GL entry point.
*/
static void
-gen_vertex_arrays(struct gl_context *ctx, GLsizei n, GLuint *arrays)
+gen_vertex_arrays(struct gl_context *ctx, GLsizei n, GLuint *arrays,
+ bool create, const char *func)
{
GLuint first;
GLint i;
if (n < 0) {
- _mesa_error(ctx, GL_INVALID_VALUE, "glGenVertexArrays");
+ _mesa_error(ctx, GL_INVALID_VALUE, "%s(n < 0)", func);
return;
}
@@ -502,16 +565,20 @@ gen_vertex_arrays(struct gl_context *ctx, GLsizei n, GLuint *arrays)
first = _mesa_HashFindFreeKeyBlock(ctx->Array.Objects, n);
- /* Allocate new, empty array objects and return identifiers */
+ /* For the sake of simplicity we create the array objects in both
+ * the Gen* and Create* cases. The only difference is the value of
+ * EverBound, which is set to true in the Create* case.
+ */
for (i = 0; i < n; i++) {
struct gl_vertex_array_object *obj;
GLuint name = first + i;
obj = (*ctx->Driver.NewArrayObject)( ctx, name );
if (!obj) {
- _mesa_error(ctx, GL_OUT_OF_MEMORY, "glGenVertexArrays");
+ _mesa_error(ctx, GL_OUT_OF_MEMORY, "%s", func);
return;
}
+ obj->EverBound = create;
save_array_object(ctx, obj);
arrays[i] = first + i;
}
@@ -526,7 +593,7 @@ void GLAPIENTRY
_mesa_GenVertexArrays(GLsizei n, GLuint *arrays)
{
GET_CURRENT_CONTEXT(ctx);
- gen_vertex_arrays(ctx, n, arrays);
+ gen_vertex_arrays(ctx, n, arrays, false, "glGenVertexArrays");
}
@@ -538,7 +605,27 @@ void GLAPIENTRY
_mesa_GenVertexArraysAPPLE(GLsizei n, GLuint *arrays)
{
GET_CURRENT_CONTEXT(ctx);
- gen_vertex_arrays(ctx, n, arrays);
+ gen_vertex_arrays(ctx, n, arrays, false, "glGenVertexArraysAPPLE");
+}
+
+
+/**
+ * ARB_direct_state_access
+ * Generates ID's and creates the array objects.
+ */
+void GLAPIENTRY
+_mesa_CreateVertexArrays(GLsizei n, GLuint *arrays)
+{
+ GET_CURRENT_CONTEXT(ctx);
+
+ if (!ctx->Extensions.ARB_direct_state_access) {
+ _mesa_error(ctx, GL_INVALID_OPERATION,
+ "glCreateVertexArrays(GL_ARB_direct_state_access "
+ "is not supported");
+ return;
+ }
+
+ gen_vertex_arrays(ctx, n, arrays, true, "glCreateVertexArrays");
}
@@ -565,3 +652,92 @@ _mesa_IsVertexArray( GLuint id )
return obj->EverBound;
}
+
+
+/**
+ * Sets the element array buffer binding of a vertex array object.
+ *
+ * This is the ARB_direct_state_access equivalent of
+ * glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, buffer).
+ */
+void GLAPIENTRY
+_mesa_VertexArrayElementBuffer(GLuint vaobj, GLuint buffer)
+{
+ GET_CURRENT_CONTEXT(ctx);
+ struct gl_vertex_array_object *vao;
+ struct gl_buffer_object *bufObj;
+
+ if (!ctx->Extensions.ARB_direct_state_access) {
+ _mesa_error(ctx, GL_INVALID_OPERATION,
+ "glVertexArrayElementBuffer(GL_ARB_direct_state_access "
+ "is not supported");
+ return;
+ }
+
+ ASSERT_OUTSIDE_BEGIN_END(ctx);
+
+ /* The GL_ARB_direct_state_access specification says:
+ *
+ * "An INVALID_OPERATION error is generated by VertexArrayElementBuffer
+ * if <vaobj> is not [compatibility profile: zero or] the name of an
+ * existing vertex array object."
+ */
+ vao =_mesa_lookup_vao_err(ctx, vaobj, "glVertexArrayElementBuffer");
+ if (!vao)
+ return;
+
+ /* The GL_ARB_direct_state_access specification says:
+ *
+ * "An INVALID_OPERATION error is generated if <buffer> is not zero or
+ * the name of an existing buffer object."
+ */
+ if (buffer != 0)
+ bufObj = _mesa_lookup_bufferobj_err(ctx, buffer,
+ "glVertexArrayElementBuffer");
+ else
+ bufObj = ctx->Shared->NullBufferObj;
+
+ if (bufObj)
+ _mesa_reference_buffer_object(ctx, &vao->IndexBufferObj, bufObj);
+}
+
+
+void GLAPIENTRY
+_mesa_GetVertexArrayiv(GLuint vaobj, GLenum pname, GLint *param)
+{
+ GET_CURRENT_CONTEXT(ctx);
+ struct gl_vertex_array_object *vao;
+
+ ASSERT_OUTSIDE_BEGIN_END(ctx);
+
+ if (!ctx->Extensions.ARB_direct_state_access) {
+ _mesa_error(ctx, GL_INVALID_OPERATION,
+ "glGetVertexArrayiv(GL_ARB_direct_state_access "
+ "is not supported");
+ return;
+ }
+
+ /* The GL_ARB_direct_state_access specification says:
+ *
+ * "An INVALID_OPERATION error is generated if <vaobj> is not
+ * [compatibility profile: zero or] the name of an existing
+ * vertex array object."
+ */
+ vao =_mesa_lookup_vao_err(ctx, vaobj, "glGetVertexArrayiv");
+ if (!vao)
+ return;
+
+ /* The GL_ARB_direct_state_access specification says:
+ *
+ * "An INVALID_ENUM error is generated if <pname> is not
+ * ELEMENT_ARRAY_BUFFER_BINDING."
+ */
+ if (pname != GL_ELEMENT_ARRAY_BUFFER_BINDING) {
+ _mesa_error(ctx, GL_INVALID_ENUM,
+ "glGetVertexArrayiv(pname != "
+ "GL_ELEMENT_ARRAY_BUFFER_BINDING)");
+ return;
+ }
+
+ param[0] = vao->IndexBufferObj->Name;
+}
diff --git a/mesalib/src/mesa/main/arrayobj.h b/mesalib/src/mesa/main/arrayobj.h
index 3c1f91835..6a4247f4a 100644
--- a/mesalib/src/mesa/main/arrayobj.h
+++ b/mesalib/src/mesa/main/arrayobj.h
@@ -49,6 +49,9 @@ extern struct gl_vertex_array_object *
_mesa_lookup_vao(struct gl_context *ctx, GLuint id);
extern struct gl_vertex_array_object *
+_mesa_lookup_vao_err(struct gl_context *ctx, GLuint id, const char *caller);
+
+extern struct gl_vertex_array_object *
_mesa_new_vao(struct gl_context *ctx, GLuint name);
extern void
@@ -93,6 +96,12 @@ void GLAPIENTRY _mesa_GenVertexArrays(GLsizei n, GLuint *arrays);
void GLAPIENTRY _mesa_GenVertexArraysAPPLE(GLsizei n, GLuint *buffer);
+void GLAPIENTRY _mesa_CreateVertexArrays(GLsizei n, GLuint *arrays);
+
GLboolean GLAPIENTRY _mesa_IsVertexArray( GLuint id );
+void GLAPIENTRY _mesa_VertexArrayElementBuffer(GLuint vaobj, GLuint buffer);
+
+void GLAPIENTRY _mesa_GetVertexArrayiv(GLuint vaobj, GLenum pname, GLint *param);
+
#endif /* ARRAYOBJ_H */
diff --git a/mesalib/src/mesa/main/blend.c b/mesalib/src/mesa/main/blend.c
index 774fc888e..d869fa2aa 100644
--- a/mesalib/src/mesa/main/blend.c
+++ b/mesalib/src/mesa/main/blend.c
@@ -769,7 +769,7 @@ _mesa_ClampColor(GLenum target, GLenum clamp)
}
FLUSH_VERTICES(ctx, _NEW_LIGHT);
ctx->Light.ClampVertexColor = clamp;
- _mesa_update_clamp_vertex_color(ctx);
+ _mesa_update_clamp_vertex_color(ctx, ctx->DrawBuffer);
break;
case GL_CLAMP_FRAGMENT_COLOR_ARB:
if (ctx->API == API_OPENGL_CORE &&
@@ -778,7 +778,7 @@ _mesa_ClampColor(GLenum target, GLenum clamp)
}
FLUSH_VERTICES(ctx, _NEW_FRAG_CLAMP);
ctx->Color.ClampFragmentColor = clamp;
- _mesa_update_clamp_fragment_color(ctx);
+ _mesa_update_clamp_fragment_color(ctx, ctx->DrawBuffer);
break;
case GL_CLAMP_READ_COLOR_ARB:
ctx->Color.ClampReadColor = clamp;
@@ -807,50 +807,55 @@ get_clamp_color(const struct gl_framebuffer *fb, GLenum clamp)
}
GLboolean
-_mesa_get_clamp_fragment_color(const struct gl_context *ctx)
+_mesa_get_clamp_fragment_color(const struct gl_context *ctx,
+ const struct gl_framebuffer *drawFb)
{
- return get_clamp_color(ctx->DrawBuffer,
- ctx->Color.ClampFragmentColor);
+ return get_clamp_color(drawFb, ctx->Color.ClampFragmentColor);
}
GLboolean
-_mesa_get_clamp_vertex_color(const struct gl_context *ctx)
+_mesa_get_clamp_vertex_color(const struct gl_context *ctx,
+ const struct gl_framebuffer *drawFb)
{
- return get_clamp_color(ctx->DrawBuffer, ctx->Light.ClampVertexColor);
+ return get_clamp_color(drawFb, ctx->Light.ClampVertexColor);
}
GLboolean
-_mesa_get_clamp_read_color(const struct gl_context *ctx)
+_mesa_get_clamp_read_color(const struct gl_context *ctx,
+ const struct gl_framebuffer *readFb)
{
- return get_clamp_color(ctx->ReadBuffer, ctx->Color.ClampReadColor);
+ return get_clamp_color(readFb, ctx->Color.ClampReadColor);
}
/**
* Update the ctx->Color._ClampFragmentColor field
*/
void
-_mesa_update_clamp_fragment_color(struct gl_context *ctx)
+_mesa_update_clamp_fragment_color(struct gl_context *ctx,
+ const struct gl_framebuffer *drawFb)
{
- struct gl_framebuffer *fb = ctx->DrawBuffer;
-
/* Don't clamp if:
* - there is no colorbuffer
* - all colorbuffers are unsigned normalized, so clamping has no effect
* - there is an integer colorbuffer
*/
- if (!fb || !fb->_HasSNormOrFloatColorBuffer || fb->_IntegerColor)
+ if (!drawFb || !drawFb->_HasSNormOrFloatColorBuffer ||
+ drawFb->_IntegerColor)
ctx->Color._ClampFragmentColor = GL_FALSE;
else
- ctx->Color._ClampFragmentColor = _mesa_get_clamp_fragment_color(ctx);
+ ctx->Color._ClampFragmentColor =
+ _mesa_get_clamp_fragment_color(ctx, drawFb);
}
/**
* Update the ctx->Color._ClampVertexColor field
*/
void
-_mesa_update_clamp_vertex_color(struct gl_context *ctx)
+_mesa_update_clamp_vertex_color(struct gl_context *ctx,
+ const struct gl_framebuffer *drawFb)
{
- ctx->Light._ClampVertexColor = _mesa_get_clamp_vertex_color(ctx);
+ ctx->Light._ClampVertexColor =
+ _mesa_get_clamp_vertex_color(ctx, drawFb);
}
/**
diff --git a/mesalib/src/mesa/main/blend.h b/mesalib/src/mesa/main/blend.h
index fe31a7440..8ab9e02fc 100644
--- a/mesalib/src/mesa/main/blend.h
+++ b/mesalib/src/mesa/main/blend.h
@@ -37,6 +37,7 @@
#include "formats.h"
struct gl_context;
+struct gl_framebuffer;
extern void GLAPIENTRY
@@ -101,19 +102,24 @@ extern void GLAPIENTRY
_mesa_ClampColor(GLenum target, GLenum clamp);
extern GLboolean
-_mesa_get_clamp_fragment_color(const struct gl_context *ctx);
+_mesa_get_clamp_fragment_color(const struct gl_context *ctx,
+ const struct gl_framebuffer *drawFb);
extern GLboolean
-_mesa_get_clamp_vertex_color(const struct gl_context *ctx);
+_mesa_get_clamp_vertex_color(const struct gl_context *ctx,
+ const struct gl_framebuffer *drawFb);
extern GLboolean
-_mesa_get_clamp_read_color(const struct gl_context *ctx);
+_mesa_get_clamp_read_color(const struct gl_context *ctx,
+ const struct gl_framebuffer *readFb);
extern void
-_mesa_update_clamp_fragment_color(struct gl_context *ctx);
+_mesa_update_clamp_fragment_color(struct gl_context *ctx,
+ const struct gl_framebuffer *drawFb);
extern void
-_mesa_update_clamp_vertex_color(struct gl_context *ctx);
+_mesa_update_clamp_vertex_color(struct gl_context *ctx,
+ const struct gl_framebuffer *drawFb);
extern mesa_format
_mesa_get_render_format(const struct gl_context *ctx, mesa_format format);
diff --git a/mesalib/src/mesa/main/blit.c b/mesalib/src/mesa/main/blit.c
index 0694466eb..fac972450 100644
--- a/mesalib/src/mesa/main/blit.c
+++ b/mesalib/src/mesa/main/blit.c
@@ -34,6 +34,7 @@
#include "enums.h"
#include "blit.h"
#include "fbobject.h"
+#include "framebuffer.h"
#include "glformats.h"
#include "mtypes.h"
#include "state.h"
@@ -148,38 +149,25 @@ is_valid_blit_filter(const struct gl_context *ctx, GLenum filter)
}
-/**
- * Blit rectangular region, optionally from one framebuffer to another.
- *
- * Note, if the src buffer is multisampled and the dest is not, this is
- * when the samples must be resolved to a single color.
- */
-void GLAPIENTRY
-_mesa_BlitFramebuffer(GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1,
- GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1,
- GLbitfield mask, GLenum filter)
+void
+_mesa_blit_framebuffer(struct gl_context *ctx,
+ struct gl_framebuffer *readFb,
+ struct gl_framebuffer *drawFb,
+ GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1,
+ GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1,
+ GLbitfield mask, GLenum filter, const char *func)
{
const GLbitfield legalMaskBits = (GL_COLOR_BUFFER_BIT |
GL_DEPTH_BUFFER_BIT |
GL_STENCIL_BUFFER_BIT);
- const struct gl_framebuffer *readFb, *drawFb;
- GET_CURRENT_CONTEXT(ctx);
FLUSH_VERTICES(ctx, 0);
- if (MESA_VERBOSE & VERBOSE_API)
- _mesa_debug(ctx,
- "glBlitFramebuffer(%d, %d, %d, %d, %d, %d, %d, %d, 0x%x, %s)\n",
- srcX0, srcY0, srcX1, srcY1,
- dstX0, dstY0, dstX1, dstY1,
- mask, _mesa_lookup_enum_by_nr(filter));
-
- if (ctx->NewState) {
- _mesa_update_state(ctx);
- }
+ /* Update completeness status of readFb and drawFb. */
+ _mesa_update_framebuffer(ctx, readFb, drawFb);
- readFb = ctx->ReadBuffer;
- drawFb = ctx->DrawBuffer;
+ /* Make sure drawFb has an initialized bounding box. */
+ _mesa_update_draw_buffer_bounds(ctx, drawFb);
if (!readFb || !drawFb) {
/* This will normally never happen but someday we may want to
@@ -192,12 +180,12 @@ _mesa_BlitFramebuffer(GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1,
if (drawFb->_Status != GL_FRAMEBUFFER_COMPLETE_EXT ||
readFb->_Status != GL_FRAMEBUFFER_COMPLETE_EXT) {
_mesa_error(ctx, GL_INVALID_FRAMEBUFFER_OPERATION_EXT,
- "glBlitFramebufferEXT(incomplete draw/read buffers)");
+ "%s(incomplete draw/read buffers)", func);
return;
}
if (!is_valid_blit_filter(ctx, filter)) {
- _mesa_error(ctx, GL_INVALID_ENUM, "glBlitFramebufferEXT(%s)",
+ _mesa_error(ctx, GL_INVALID_ENUM, "%s(invalid filter %s)", func,
_mesa_lookup_enum_by_nr(filter));
return;
}
@@ -205,13 +193,13 @@ _mesa_BlitFramebuffer(GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1,
if ((filter == GL_SCALED_RESOLVE_FASTEST_EXT ||
filter == GL_SCALED_RESOLVE_NICEST_EXT) &&
(readFb->Visual.samples == 0 || drawFb->Visual.samples > 0)) {
- _mesa_error(ctx, GL_INVALID_OPERATION, "glBlitFramebufferEXT(%s)",
+ _mesa_error(ctx, GL_INVALID_OPERATION, "%s(%s: invalid samples)", func,
_mesa_lookup_enum_by_nr(filter));
return;
}
if (mask & ~legalMaskBits) {
- _mesa_error( ctx, GL_INVALID_VALUE, "glBlitFramebufferEXT(mask)");
+ _mesa_error(ctx, GL_INVALID_VALUE, "%s(invalid mask bits set)", func);
return;
}
@@ -219,13 +207,13 @@ _mesa_BlitFramebuffer(GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1,
if ((mask & (GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT))
&& filter != GL_NEAREST) {
_mesa_error(ctx, GL_INVALID_OPERATION,
- "glBlitFramebufferEXT(depth/stencil requires GL_NEAREST filter)");
+ "%s(depth/stencil requires GL_NEAREST filter)", func);
return;
}
/* get color read/draw renderbuffers */
if (mask & GL_COLOR_BUFFER_BIT) {
- const GLuint numColorDrawBuffers = ctx->DrawBuffer->_NumColorDrawBuffers;
+ const GLuint numColorDrawBuffers = drawFb->_NumColorDrawBuffers;
const struct gl_renderbuffer *colorReadRb = readFb->_ColorReadBuffer;
const struct gl_renderbuffer *colorDrawRb = NULL;
GLuint i;
@@ -241,7 +229,7 @@ _mesa_BlitFramebuffer(GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1,
}
else {
for (i = 0; i < numColorDrawBuffers; i++) {
- colorDrawRb = ctx->DrawBuffer->_ColorDrawBuffers[i];
+ colorDrawRb = drawFb->_ColorDrawBuffers[i];
if (!colorDrawRb)
continue;
@@ -257,15 +245,15 @@ _mesa_BlitFramebuffer(GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1,
*/
if (_mesa_is_gles3(ctx) && (colorDrawRb == colorReadRb)) {
_mesa_error(ctx, GL_INVALID_OPERATION,
- "glBlitFramebuffer(source and destination color "
- "buffer cannot be the same)");
+ "%s(source and destination color "
+ "buffer cannot be the same)", func);
return;
}
if (!compatible_color_datatypes(colorReadRb->Format,
colorDrawRb->Format)) {
_mesa_error(ctx, GL_INVALID_OPERATION,
- "glBlitFramebufferEXT(color buffer datatypes mismatch)");
+ "%s(color buffer datatypes mismatch)", func);
return;
}
/* extra checks for multisample copies... */
@@ -273,7 +261,7 @@ _mesa_BlitFramebuffer(GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1,
/* color formats must match */
if (!compatible_resolve_formats(colorReadRb, colorDrawRb)) {
_mesa_error(ctx, GL_INVALID_OPERATION,
- "glBlitFramebufferEXT(bad src/dst multisample pixel formats)");
+ "%s(bad src/dst multisample pixel formats)", func);
return;
}
}
@@ -286,7 +274,7 @@ _mesa_BlitFramebuffer(GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1,
GLenum type = _mesa_get_format_datatype(colorReadRb->Format);
if (type == GL_INT || type == GL_UNSIGNED_INT) {
_mesa_error(ctx, GL_INVALID_OPERATION,
- "glBlitFramebufferEXT(integer color type)");
+ "%s(integer color type)", func);
return;
}
}
@@ -306,15 +294,15 @@ _mesa_BlitFramebuffer(GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1,
* ignored."
*/
if ((readRb == NULL) || (drawRb == NULL)) {
- mask &= ~GL_STENCIL_BUFFER_BIT;
+ mask &= ~GL_STENCIL_BUFFER_BIT;
}
else {
int read_z_bits, draw_z_bits;
if (_mesa_is_gles3(ctx) && (drawRb == readRb)) {
_mesa_error(ctx, GL_INVALID_OPERATION,
- "glBlitFramebuffer(source and destination stencil "
- "buffer cannot be the same)");
+ "%s(source and destination stencil "
+ "buffer cannot be the same)", func);
return;
}
@@ -324,7 +312,7 @@ _mesa_BlitFramebuffer(GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1,
* there is only one: GL_UNSIGNED_INT.
*/
_mesa_error(ctx, GL_INVALID_OPERATION,
- "glBlitFramebuffer(stencil attachment format mismatch)");
+ "%s(stencil attachment format mismatch)", func);
return;
}
@@ -340,8 +328,8 @@ _mesa_BlitFramebuffer(GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1,
_mesa_get_format_datatype(readRb->Format) !=
_mesa_get_format_datatype(drawRb->Format))) {
- _mesa_error(ctx, GL_INVALID_OPERATION, "glBlitFramebuffer"
- "(stencil attachment depth format mismatch)");
+ _mesa_error(ctx, GL_INVALID_OPERATION,
+ "%s(stencil attachment depth format mismatch)", func);
return;
}
}
@@ -360,15 +348,15 @@ _mesa_BlitFramebuffer(GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1,
* ignored."
*/
if ((readRb == NULL) || (drawRb == NULL)) {
- mask &= ~GL_DEPTH_BUFFER_BIT;
+ mask &= ~GL_DEPTH_BUFFER_BIT;
}
else {
int read_s_bit, draw_s_bit;
if (_mesa_is_gles3(ctx) && (drawRb == readRb)) {
_mesa_error(ctx, GL_INVALID_OPERATION,
- "glBlitFramebuffer(source and destination depth "
- "buffer cannot be the same)");
+ "%s(source and destination depth "
+ "buffer cannot be the same)", func);
return;
}
@@ -377,7 +365,7 @@ _mesa_BlitFramebuffer(GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1,
(_mesa_get_format_datatype(readRb->Format) !=
_mesa_get_format_datatype(drawRb->Format))) {
_mesa_error(ctx, GL_INVALID_OPERATION,
- "glBlitFramebuffer(depth attachment format mismatch)");
+ "%s(depth attachment format mismatch)", func);
return;
}
@@ -389,8 +377,8 @@ _mesa_BlitFramebuffer(GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1,
* we should ignore the stencil format check.
*/
if (read_s_bit > 0 && draw_s_bit > 0 && read_s_bit != draw_s_bit) {
- _mesa_error(ctx, GL_INVALID_OPERATION, "glBlitFramebuffer"
- "(depth attachment stencil bits mismatch)");
+ _mesa_error(ctx, GL_INVALID_OPERATION,
+ "%s(depth attachment stencil bits mismatch)", func);
return;
}
}
@@ -406,7 +394,7 @@ _mesa_BlitFramebuffer(GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1,
*/
if (drawFb->Visual.samples > 0) {
_mesa_error(ctx, GL_INVALID_OPERATION,
- "glBlitFramebuffer(destination samples must be 0)");
+ "%s(destination samples must be 0)", func);
return;
}
@@ -426,7 +414,7 @@ _mesa_BlitFramebuffer(GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1,
&& (srcX0 != dstX0 || srcY0 != dstY0
|| srcX1 != dstX1 || srcY1 != dstY1)) {
_mesa_error(ctx, GL_INVALID_OPERATION,
- "glBlitFramebuffer(bad src/dst multisample region)");
+ "%s(bad src/dst multisample region)", func);
return;
}
} else {
@@ -434,7 +422,7 @@ _mesa_BlitFramebuffer(GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1,
drawFb->Visual.samples > 0 &&
readFb->Visual.samples != drawFb->Visual.samples) {
_mesa_error(ctx, GL_INVALID_OPERATION,
- "glBlitFramebufferEXT(mismatched samples)");
+ "%s(mismatched samples)", func);
return;
}
@@ -445,7 +433,7 @@ _mesa_BlitFramebuffer(GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1,
if (abs(srcX1 - srcX0) != abs(dstX1 - dstX0) ||
abs(srcY1 - srcY0) != abs(dstY1 - dstY0)) {
_mesa_error(ctx, GL_INVALID_OPERATION,
- "glBlitFramebufferEXT(bad src/dst multisample region sizes)");
+ "%s(bad src/dst multisample region sizes)", func);
return;
}
}
@@ -457,43 +445,44 @@ _mesa_BlitFramebuffer(GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1,
const struct gl_renderbuffer *colorDrawRb = NULL;
GLuint i = 0;
- printf("glBlitFramebuffer(%d, %d, %d, %d, %d, %d, %d, %d,"
- " 0x%x, 0x%x)\n",
- srcX0, srcY0, srcX1, srcY1,
- dstX0, dstY0, dstX1, dstY1,
- mask, filter);
+ printf("%s(%d, %d, %d, %d, %d, %d, %d, %d,"
+ " 0x%x, 0x%x)\n", func,
+ srcX0, srcY0, srcX1, srcY1,
+ dstX0, dstY0, dstX1, dstY1,
+ mask, filter);
+
if (colorReadRb) {
const struct gl_renderbuffer_attachment *att;
att = find_attachment(readFb, colorReadRb);
printf(" Src FBO %u RB %u (%dx%d) ",
- readFb->Name, colorReadRb->Name,
- colorReadRb->Width, colorReadRb->Height);
+ readFb->Name, colorReadRb->Name,
+ colorReadRb->Width, colorReadRb->Height);
if (att && att->Texture) {
printf("Tex %u tgt 0x%x level %u face %u",
- att->Texture->Name,
- att->Texture->Target,
- att->TextureLevel,
- att->CubeMapFace);
+ att->Texture->Name,
+ att->Texture->Target,
+ att->TextureLevel,
+ att->CubeMapFace);
}
printf("\n");
/* Print all active color render buffers */
- for (i = 0; i < ctx->DrawBuffer->_NumColorDrawBuffers; i++) {
- colorDrawRb = ctx->DrawBuffer->_ColorDrawBuffers[i];
+ for (i = 0; i < drawFb->_NumColorDrawBuffers; i++) {
+ colorDrawRb = drawFb->_ColorDrawBuffers[i];
if (!colorDrawRb)
continue;
att = find_attachment(drawFb, colorDrawRb);
printf(" Dst FBO %u RB %u (%dx%d) ",
- drawFb->Name, colorDrawRb->Name,
- colorDrawRb->Width, colorDrawRb->Height);
+ drawFb->Name, colorDrawRb->Name,
+ colorDrawRb->Width, colorDrawRb->Height);
if (att && att->Texture) {
printf("Tex %u tgt 0x%x level %u face %u",
- att->Texture->Name,
- att->Texture->Target,
- att->TextureLevel,
- att->CubeMapFace);
+ att->Texture->Name,
+ att->Texture->Target,
+ att->TextureLevel,
+ att->CubeMapFace);
}
printf("\n");
}
@@ -507,8 +496,94 @@ _mesa_BlitFramebuffer(GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1,
}
assert(ctx->Driver.BlitFramebuffer);
- ctx->Driver.BlitFramebuffer(ctx, ctx->ReadBuffer, ctx->DrawBuffer,
+ ctx->Driver.BlitFramebuffer(ctx, readFb, drawFb,
srcX0, srcY0, srcX1, srcY1,
dstX0, dstY0, dstX1, dstY1,
mask, filter);
}
+
+
+/**
+ * Blit rectangular region, optionally from one framebuffer to another.
+ *
+ * Note, if the src buffer is multisampled and the dest is not, this is
+ * when the samples must be resolved to a single color.
+ */
+void GLAPIENTRY
+_mesa_BlitFramebuffer(GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1,
+ GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1,
+ GLbitfield mask, GLenum filter)
+{
+ GET_CURRENT_CONTEXT(ctx);
+
+ if (MESA_VERBOSE & VERBOSE_API)
+ _mesa_debug(ctx,
+ "glBlitFramebuffer(%d, %d, %d, %d, "
+ " %d, %d, %d, %d, 0x%x, %s)\n",
+ srcX0, srcY0, srcX1, srcY1,
+ dstX0, dstY0, dstX1, dstY1,
+ mask, _mesa_lookup_enum_by_nr(filter));
+
+ _mesa_blit_framebuffer(ctx, ctx->ReadBuffer, ctx->DrawBuffer,
+ srcX0, srcY0, srcX1, srcY1,
+ dstX0, dstY0, dstX1, dstY1,
+ mask, filter, "glBlitFramebuffer");
+}
+
+
+void GLAPIENTRY
+_mesa_BlitNamedFramebuffer(GLuint readFramebuffer, GLuint drawFramebuffer,
+ GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1,
+ GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1,
+ GLbitfield mask, GLenum filter)
+{
+ GET_CURRENT_CONTEXT(ctx);
+ struct gl_framebuffer *readFb, *drawFb;
+
+ if (!ctx->Extensions.ARB_direct_state_access) {
+ _mesa_error(ctx, GL_INVALID_OPERATION,
+ "glBlitNamedFramebuffer(GL_ARB_direct_state_access "
+ "is not supported)");
+ return;
+ }
+
+ if (MESA_VERBOSE & VERBOSE_API)
+ _mesa_debug(ctx,
+ "glBlitNamedFramebuffer(%u %u %d, %d, %d, %d, "
+ " %d, %d, %d, %d, 0x%x, %s)\n",
+ readFramebuffer, drawFramebuffer,
+ srcX0, srcY0, srcX1, srcY1,
+ dstX0, dstY0, dstX1, dstY1,
+ mask, _mesa_lookup_enum_by_nr(filter));
+
+ /*
+ * According to PDF page 533 of the OpenGL 4.5 core spec (30.10.2014,
+ * Section 18.3 Copying Pixels):
+ * "... if readFramebuffer or drawFramebuffer is zero (for
+ * BlitNamedFramebuffer), then the default read or draw framebuffer is
+ * used as the corresponding source or destination framebuffer,
+ * respectively."
+ */
+ if (readFramebuffer) {
+ readFb = _mesa_lookup_framebuffer_err(ctx, readFramebuffer,
+ "glBlitNamedFramebuffer");
+ if (!readFb)
+ return;
+ }
+ else
+ readFb = ctx->WinSysReadBuffer;
+
+ if (drawFramebuffer) {
+ drawFb = _mesa_lookup_framebuffer_err(ctx, drawFramebuffer,
+ "glBlitNamedFramebuffer");
+ if (!drawFb)
+ return;
+ }
+ else
+ drawFb = ctx->WinSysDrawBuffer;
+
+ _mesa_blit_framebuffer(ctx, readFb, drawFb,
+ srcX0, srcY0, srcX1, srcY1,
+ dstX0, dstY0, dstX1, dstY1,
+ mask, filter, "glBlitNamedFramebuffer");
+}
diff --git a/mesalib/src/mesa/main/blit.h b/mesalib/src/mesa/main/blit.h
index 01a958af5..54b946e31 100644
--- a/mesalib/src/mesa/main/blit.h
+++ b/mesalib/src/mesa/main/blit.h
@@ -28,11 +28,24 @@
#include "glheader.h"
+extern void
+_mesa_blit_framebuffer(struct gl_context *ctx,
+ struct gl_framebuffer *readFb,
+ struct gl_framebuffer *drawFb,
+ GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1,
+ GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1,
+ GLbitfield mask, GLenum filter, const char *func);
extern void GLAPIENTRY
_mesa_BlitFramebuffer(GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1,
GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1,
GLbitfield mask, GLenum filter);
+extern void GLAPIENTRY
+_mesa_BlitNamedFramebuffer(GLuint readFramebuffer, GLuint drawFramebuffer,
+ GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1,
+ GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1,
+ GLbitfield mask, GLenum filter);
+
#endif /* BLIT_H */
diff --git a/mesalib/src/mesa/main/bufferobj.c b/mesalib/src/mesa/main/bufferobj.c
index 66dee6802..660bc9489 100644
--- a/mesalib/src/mesa/main/bufferobj.c
+++ b/mesalib/src/mesa/main/bufferobj.c
@@ -1303,6 +1303,12 @@ create_buffers(GLsizei n, GLuint *buffers, bool dsa)
const char *func = dsa ? "glCreateBuffers" : "glGenBuffers";
+ if (dsa && !ctx->Extensions.ARB_direct_state_access) {
+ _mesa_error(ctx, GL_INVALID_OPERATION,
+ "%s(GL_ARB_direct_state_access is not supported)", func);
+ return;
+ }
+
if (MESA_VERBOSE & VERBOSE_API)
_mesa_debug(ctx, "%s(%d)\n", func, n);
@@ -1477,6 +1483,13 @@ _mesa_NamedBufferStorage(GLuint buffer, GLsizeiptr size, const GLvoid *data,
GET_CURRENT_CONTEXT(ctx);
struct gl_buffer_object *bufObj;
+ if (!ctx->Extensions.ARB_direct_state_access) {
+ _mesa_error(ctx, GL_INVALID_OPERATION,
+ "glNamedBufferStorage(GL_ARB_direct_state_access "
+ "is not supported)");
+ return;
+ }
+
bufObj = _mesa_lookup_bufferobj_err(ctx, buffer, "glNamedBufferStorage");
if (!bufObj)
return;
@@ -1603,6 +1616,13 @@ _mesa_NamedBufferData(GLuint buffer, GLsizeiptr size, const GLvoid *data,
GET_CURRENT_CONTEXT(ctx);
struct gl_buffer_object *bufObj;
+ if (!ctx->Extensions.ARB_direct_state_access) {
+ _mesa_error(ctx, GL_INVALID_OPERATION,
+ "glNamedBufferData(GL_ARB_direct_state_access "
+ "is not supported)");
+ return;
+ }
+
bufObj = _mesa_lookup_bufferobj_err(ctx, buffer, "glNamedBufferData");
if (!bufObj)
return;
@@ -1673,6 +1693,13 @@ _mesa_NamedBufferSubData(GLuint buffer, GLintptr offset,
GET_CURRENT_CONTEXT(ctx);
struct gl_buffer_object *bufObj;
+ if (!ctx->Extensions.ARB_direct_state_access) {
+ _mesa_error(ctx, GL_INVALID_OPERATION,
+ "glNamedBufferSubData(GL_ARB_direct_state_access "
+ "is not supported)");
+ return;
+ }
+
bufObj = _mesa_lookup_bufferobj_err(ctx, buffer, "glNamedBufferSubData");
if (!bufObj)
return;
@@ -1710,6 +1737,13 @@ _mesa_GetNamedBufferSubData(GLuint buffer, GLintptr offset,
GET_CURRENT_CONTEXT(ctx);
struct gl_buffer_object *bufObj;
+ if (!ctx->Extensions.ARB_direct_state_access) {
+ _mesa_error(ctx, GL_INVALID_OPERATION,
+ "glGetNamedBufferSubData(GL_ARB_direct_state_access "
+ "is not supported)");
+ return;
+ }
+
bufObj = _mesa_lookup_bufferobj_err(ctx, buffer,
"glGetNamedBufferSubData");
if (!bufObj)
@@ -1805,6 +1839,13 @@ _mesa_ClearNamedBufferData(GLuint buffer, GLenum internalformat,
GET_CURRENT_CONTEXT(ctx);
struct gl_buffer_object *bufObj;
+ if (!ctx->Extensions.ARB_direct_state_access) {
+ _mesa_error(ctx, GL_INVALID_OPERATION,
+ "glClearNamedBufferData(GL_ARB_direct_state_access "
+ "is not supported)");
+ return;
+ }
+
bufObj = _mesa_lookup_bufferobj_err(ctx, buffer, "glClearNamedBufferData");
if (!bufObj)
return;
@@ -1842,6 +1883,13 @@ _mesa_ClearNamedBufferSubData(GLuint buffer, GLenum internalformat,
GET_CURRENT_CONTEXT(ctx);
struct gl_buffer_object *bufObj;
+ if (!ctx->Extensions.ARB_direct_state_access) {
+ _mesa_error(ctx, GL_INVALID_OPERATION,
+ "glClearNamedBufferSubData(GL_ARB_direct_state_access "
+ "is not supported)");
+ return;
+ }
+
bufObj = _mesa_lookup_bufferobj_err(ctx, buffer,
"glClearNamedBufferSubData");
if (!bufObj)
@@ -1930,6 +1978,13 @@ _mesa_UnmapNamedBuffer(GLuint buffer)
GET_CURRENT_CONTEXT(ctx);
struct gl_buffer_object *bufObj;
+ if (!ctx->Extensions.ARB_direct_state_access) {
+ _mesa_error(ctx, GL_INVALID_OPERATION,
+ "glUnmapNamedBuffer(GL_ARB_direct_state_access "
+ "is not supported)");
+ return GL_FALSE;
+ }
+
bufObj = _mesa_lookup_bufferobj_err(ctx, buffer, "glUnmapNamedBuffer");
if (!bufObj)
return GL_FALSE;
@@ -2039,6 +2094,13 @@ _mesa_GetNamedBufferParameteriv(GLuint buffer, GLenum pname, GLint *params)
struct gl_buffer_object *bufObj;
GLint64 parameter;
+ if (!ctx->Extensions.ARB_direct_state_access) {
+ _mesa_error(ctx, GL_INVALID_OPERATION,
+ "glGetNamedBufferParameteriv(GL_ARB_direct_state_access "
+ "is not supported)");
+ return;
+ }
+
bufObj = _mesa_lookup_bufferobj_err(ctx, buffer,
"glGetNamedBufferParameteriv");
if (!bufObj)
@@ -2059,6 +2121,13 @@ _mesa_GetNamedBufferParameteri64v(GLuint buffer, GLenum pname,
struct gl_buffer_object *bufObj;
GLint64 parameter;
+ if (!ctx->Extensions.ARB_direct_state_access) {
+ _mesa_error(ctx, GL_INVALID_OPERATION,
+ "glGetNamedBufferParameteri64v(GL_ARB_direct_state_access "
+ "is not supported)");
+ return;
+ }
+
bufObj = _mesa_lookup_bufferobj_err(ctx, buffer,
"glGetNamedBufferParameteri64v");
if (!bufObj)
@@ -2098,6 +2167,13 @@ _mesa_GetNamedBufferPointerv(GLuint buffer, GLenum pname, GLvoid **params)
GET_CURRENT_CONTEXT(ctx);
struct gl_buffer_object *bufObj;
+ if (!ctx->Extensions.ARB_direct_state_access) {
+ _mesa_error(ctx, GL_INVALID_OPERATION,
+ "glGetNamedBufferPointerv(GL_ARB_direct_state_access "
+ "is not supported)");
+ return;
+ }
+
if (pname != GL_BUFFER_MAP_POINTER) {
_mesa_error(ctx, GL_INVALID_ENUM, "glGetNamedBufferPointerv(pname != "
"GL_BUFFER_MAP_POINTER)");
@@ -2212,6 +2288,13 @@ _mesa_CopyNamedBufferSubData(GLuint readBuffer, GLuint writeBuffer,
GET_CURRENT_CONTEXT(ctx);
struct gl_buffer_object *src, *dst;
+ if (!ctx->Extensions.ARB_direct_state_access) {
+ _mesa_error(ctx, GL_INVALID_OPERATION,
+ "glCopyNamedBufferSubData(GL_ARB_direct_state_access "
+ "is not supported)");
+ return;
+ }
+
src = _mesa_lookup_bufferobj_err(ctx, readBuffer,
"glCopyNamedBufferSubData");
if (!src)
@@ -2430,6 +2513,13 @@ _mesa_MapNamedBufferRange(GLuint buffer, GLintptr offset, GLsizeiptr length,
GET_CURRENT_CONTEXT(ctx);
struct gl_buffer_object *bufObj;
+ if (!ctx->Extensions.ARB_direct_state_access) {
+ _mesa_error(ctx, GL_INVALID_OPERATION,
+ "glMapNamedBufferRange(GL_ARB_direct_state_access "
+ "is not supported)");
+ return NULL;
+ }
+
if (!ctx->Extensions.ARB_map_buffer_range) {
_mesa_error(ctx, GL_INVALID_OPERATION,
"glMapNamedBufferRange("
@@ -2497,6 +2587,13 @@ _mesa_MapNamedBuffer(GLuint buffer, GLenum access)
struct gl_buffer_object *bufObj;
GLbitfield accessFlags;
+ if (!ctx->Extensions.ARB_direct_state_access) {
+ _mesa_error(ctx, GL_INVALID_OPERATION,
+ "glMapNamedBuffer(GL_ARB_direct_state_access "
+ "is not supported)");
+ return NULL;
+ }
+
if (!get_map_buffer_access_flags(ctx, access, &accessFlags)) {
_mesa_error(ctx, GL_INVALID_ENUM, "glMapNamedBuffer(invalid access)");
return NULL;
@@ -2587,6 +2684,14 @@ _mesa_FlushMappedNamedBufferRange(GLuint buffer, GLintptr offset,
GET_CURRENT_CONTEXT(ctx);
struct gl_buffer_object *bufObj;
+ if (!ctx->Extensions.ARB_direct_state_access) {
+ _mesa_error(ctx, GL_INVALID_OPERATION,
+ "glFlushMappedNamedBufferRange(GL_ARB_direct_state_access "
+ "is not supported)");
+ return;
+ }
+
+
bufObj = _mesa_lookup_bufferobj_err(ctx, buffer,
"glFlushMappedNamedBufferRange");
if (!bufObj)
diff --git a/mesalib/src/mesa/main/buffers.c b/mesalib/src/mesa/main/buffers.c
index 37a979092..c83459add 100644
--- a/mesalib/src/mesa/main/buffers.c
+++ b/mesalib/src/mesa/main/buffers.c
@@ -242,16 +242,16 @@ read_buffer_enum_to_index(GLenum buffer)
*
* See the GL_EXT_framebuffer_object spec for more info.
*/
-void GLAPIENTRY
-_mesa_DrawBuffer(GLenum buffer)
+void
+_mesa_draw_buffer(struct gl_context *ctx, struct gl_framebuffer *fb,
+ GLenum buffer, const char *caller)
{
GLbitfield destMask;
- GET_CURRENT_CONTEXT(ctx);
FLUSH_VERTICES(ctx, 0);
if (MESA_VERBOSE & VERBOSE_API) {
- _mesa_debug(ctx, "glDrawBuffer %s\n", _mesa_lookup_enum_by_nr(buffer));
+ _mesa_debug(ctx, "%s %s\n", caller, _mesa_lookup_enum_by_nr(buffer));
}
if (buffer == GL_NONE) {
@@ -259,33 +259,67 @@ _mesa_DrawBuffer(GLenum buffer)
}
else {
const GLbitfield supportedMask
- = supported_buffer_bitmask(ctx, ctx->DrawBuffer);
+ = supported_buffer_bitmask(ctx, fb);
destMask = draw_buffer_enum_to_bitmask(ctx, buffer);
if (destMask == BAD_MASK) {
/* totally bogus buffer */
- _mesa_error(ctx, GL_INVALID_ENUM,
- "glDrawBuffer(buffer=0x%x)", buffer);
+ _mesa_error(ctx, GL_INVALID_ENUM, "%s(invalid buffer %s)", caller,
+ _mesa_lookup_enum_by_nr(buffer));
return;
}
destMask &= supportedMask;
if (destMask == 0x0) {
/* none of the named color buffers exist! */
- _mesa_error(ctx, GL_INVALID_OPERATION,
- "glDrawBuffer(buffer=0x%x)", buffer);
+ _mesa_error(ctx, GL_INVALID_OPERATION, "%s(invalid buffer %s)",
+ caller, _mesa_lookup_enum_by_nr(buffer));
return;
}
}
/* if we get here, there's no error so set new state */
- _mesa_drawbuffers(ctx, 1, &buffer, &destMask);
+ _mesa_drawbuffers(ctx, fb, 1, &buffer, &destMask);
+
+ /* Call device driver function only if fb is the bound draw buffer */
+ if (fb == ctx->DrawBuffer) {
+ if (ctx->Driver.DrawBuffers)
+ ctx->Driver.DrawBuffers(ctx, 1, &buffer);
+ else if (ctx->Driver.DrawBuffer)
+ ctx->Driver.DrawBuffer(ctx, buffer);
+ }
+}
- /*
- * Call device driver function.
- */
- if (ctx->Driver.DrawBuffers)
- ctx->Driver.DrawBuffers(ctx, 1, &buffer);
- else if (ctx->Driver.DrawBuffer)
- ctx->Driver.DrawBuffer(ctx, buffer);
+
+void GLAPIENTRY
+_mesa_DrawBuffer(GLenum buffer)
+{
+ GET_CURRENT_CONTEXT(ctx);
+ _mesa_draw_buffer(ctx, ctx->DrawBuffer, buffer, "glDrawBuffer");
+}
+
+
+void GLAPIENTRY
+_mesa_NamedFramebufferDrawBuffer(GLuint framebuffer, GLenum buf)
+{
+ GET_CURRENT_CONTEXT(ctx);
+ struct gl_framebuffer *fb;
+
+ if (!ctx->Extensions.ARB_direct_state_access) {
+ _mesa_error(ctx, GL_INVALID_OPERATION,
+ "glNamedFramebufferDrawBuffer(GL_ARB_direct_state_access "
+ "is not supported)");
+ return;
+ }
+
+ if (framebuffer) {
+ fb = _mesa_lookup_framebuffer_err(ctx, framebuffer,
+ "glNamedFramebufferDrawBuffer");
+ if (!fb)
+ return;
+ }
+ else
+ fb = ctx->WinSysDrawBuffer;
+
+ _mesa_draw_buffer(ctx, fb, buf, "glNamedFramebufferDrawBuffer");
}
@@ -298,13 +332,13 @@ _mesa_DrawBuffer(GLenum buffer)
* names cannot specify more than one buffer. For example,
* GL_FRONT_AND_BACK is illegal.
*/
-void GLAPIENTRY
-_mesa_DrawBuffers(GLsizei n, const GLenum *buffers)
+void
+_mesa_draw_buffers(struct gl_context *ctx, struct gl_framebuffer *fb,
+ GLsizei n, const GLenum *buffers, const char *caller)
{
GLuint output;
GLbitfield usedBufferMask, supportedMask;
GLbitfield destMask[MAX_DRAW_BUFFERS];
- GET_CURRENT_CONTEXT(ctx);
FLUSH_VERTICES(ctx, 0);
@@ -315,12 +349,18 @@ _mesa_DrawBuffers(GLsizei n, const GLenum *buffers)
* "An INVALID_VALUE error is generated if n is greater than
* MAX_DRAW_BUFFERS."
*/
- if (n < 0 || n > (GLsizei) ctx->Const.MaxDrawBuffers) {
- _mesa_error(ctx, GL_INVALID_VALUE, "glDrawBuffersARB(n)");
+ if (n < 0) {
+ _mesa_error(ctx, GL_INVALID_VALUE, "%s(n < 0)", caller);
+ return;
+ }
+
+ if (n > (GLsizei) ctx->Const.MaxDrawBuffers) {
+ _mesa_error(ctx, GL_INVALID_VALUE,
+ "%s(n > maximum number of draw buffers)", caller);
return;
}
- supportedMask = supported_buffer_bitmask(ctx, ctx->DrawBuffer);
+ supportedMask = supported_buffer_bitmask(ctx, fb);
usedBufferMask = 0x0;
/* From the ES 3.0 specification, page 180:
@@ -328,9 +368,9 @@ _mesa_DrawBuffers(GLsizei n, const GLenum *buffers)
* and the constant must be BACK or NONE."
* (same restriction applies with GL_EXT_draw_buffers specification)
*/
- if (ctx->API == API_OPENGLES2 && _mesa_is_winsys_fbo(ctx->DrawBuffer) &&
+ if (ctx->API == API_OPENGLES2 && _mesa_is_winsys_fbo(fb) &&
(n != 1 || (buffers[0] != GL_NONE && buffers[0] != GL_BACK))) {
- _mesa_error(ctx, GL_INVALID_OPERATION, "glDrawBuffers(buffer)");
+ _mesa_error(ctx, GL_INVALID_OPERATION, "%s(invalid buffers)", caller);
return;
}
@@ -362,9 +402,11 @@ _mesa_DrawBuffers(GLsizei n, const GLenum *buffers)
* or equal to the value of MAX_COLOR_ATTACHMENTS, then the error
* INVALID_OPERATION results."
*/
- if (_mesa_is_user_fbo(ctx->DrawBuffer) && buffers[output] >=
+ if (_mesa_is_user_fbo(fb) && buffers[output] >=
GL_COLOR_ATTACHMENT0 + ctx->Const.MaxDrawBuffers) {
- _mesa_error(ctx, GL_INVALID_OPERATION, "glDrawBuffersARB(buffer)");
+ _mesa_error(ctx, GL_INVALID_OPERATION,
+ "%s(buffers[%d] >= maximum number of draw buffers)",
+ caller, output);
return;
}
@@ -375,9 +417,10 @@ _mesa_DrawBuffers(GLsizei n, const GLenum *buffers)
* 4.5 or 4.6. Otherwise, an INVALID_ENUM error is generated.
*/
if (destMask[output] == BAD_MASK) {
- _mesa_error(ctx, GL_INVALID_ENUM, "glDrawBuffersARB(buffer)");
+ _mesa_error(ctx, GL_INVALID_ENUM, "%s(invalid buffer %s)",
+ caller, _mesa_lookup_enum_by_nr(buffers[output]));
return;
- }
+ }
/* From the OpenGL 4.0 specification, page 256:
* "For both the default framebuffer and framebuffer objects, the
@@ -390,7 +433,8 @@ _mesa_DrawBuffers(GLsizei n, const GLenum *buffers)
* but the Khronos conformance tests expect INVALID_ENUM.
*/
if (_mesa_bitcount(destMask[output]) > 1) {
- _mesa_error(ctx, GL_INVALID_ENUM, "glDrawBuffersARB(buffer)");
+ _mesa_error(ctx, GL_INVALID_ENUM, "%s(invalid buffer %s)",
+ caller, _mesa_lookup_enum_by_nr(buffers[output]));
return;
}
@@ -407,7 +451,8 @@ _mesa_DrawBuffers(GLsizei n, const GLenum *buffers)
destMask[output] &= supportedMask;
if (destMask[output] == 0) {
_mesa_error(ctx, GL_INVALID_OPERATION,
- "glDrawBuffersARB(unsupported buffer)");
+ "%s(unsupported buffer %s)",
+ caller, _mesa_lookup_enum_by_nr(buffers[output]));
return;
}
@@ -416,10 +461,12 @@ _mesa_DrawBuffers(GLsizei n, const GLenum *buffers)
* in bufs must be COLOR_ATTACHMENTi or NONE. [...] INVALID_OPERATION."
* (same restriction applies with GL_EXT_draw_buffers specification)
*/
- if (ctx->API == API_OPENGLES2 && _mesa_is_user_fbo(ctx->DrawBuffer) &&
+ if (ctx->API == API_OPENGLES2 && _mesa_is_user_fbo(fb) &&
buffers[output] != GL_NONE &&
buffers[output] != GL_COLOR_ATTACHMENT0 + output) {
- _mesa_error(ctx, GL_INVALID_OPERATION, "glDrawBuffers(buffer)");
+ _mesa_error(ctx, GL_INVALID_OPERATION,
+ "%s(unsupported buffer %s)",
+ caller, _mesa_lookup_enum_by_nr(buffers[output]));
return;
}
@@ -430,7 +477,8 @@ _mesa_DrawBuffers(GLsizei n, const GLenum *buffers)
*/
if (destMask[output] & usedBufferMask) {
_mesa_error(ctx, GL_INVALID_OPERATION,
- "glDrawBuffersARB(duplicated buffer)");
+ "%s(duplicated buffer %s)",
+ caller, _mesa_lookup_enum_by_nr(buffers[output]));
return;
}
@@ -440,17 +488,55 @@ _mesa_DrawBuffers(GLsizei n, const GLenum *buffers)
}
/* OK, if we get here, there were no errors so set the new state */
- _mesa_drawbuffers(ctx, n, buffers, destMask);
+ _mesa_drawbuffers(ctx, fb, n, buffers, destMask);
/*
- * Call device driver function. Note that n can be equal to 0,
+ * Call device driver function if fb is the bound draw buffer.
+ * Note that n can be equal to 0,
* in which case we don't want to reference buffers[0], which
* may not be valid.
*/
- if (ctx->Driver.DrawBuffers)
- ctx->Driver.DrawBuffers(ctx, n, buffers);
- else if (ctx->Driver.DrawBuffer)
- ctx->Driver.DrawBuffer(ctx, n > 0 ? buffers[0] : GL_NONE);
+ if (fb == ctx->DrawBuffer) {
+ if (ctx->Driver.DrawBuffers)
+ ctx->Driver.DrawBuffers(ctx, n, buffers);
+ else if (ctx->Driver.DrawBuffer)
+ ctx->Driver.DrawBuffer(ctx, n > 0 ? buffers[0] : GL_NONE);
+ }
+}
+
+
+void GLAPIENTRY
+_mesa_DrawBuffers(GLsizei n, const GLenum *buffers)
+{
+ GET_CURRENT_CONTEXT(ctx);
+ _mesa_draw_buffers(ctx, ctx->DrawBuffer, n, buffers, "glDrawBuffers");
+}
+
+
+void GLAPIENTRY
+_mesa_NamedFramebufferDrawBuffers(GLuint framebuffer, GLsizei n,
+ const GLenum *bufs)
+{
+ GET_CURRENT_CONTEXT(ctx);
+ struct gl_framebuffer *fb;
+
+ if (!ctx->Extensions.ARB_direct_state_access) {
+ _mesa_error(ctx, GL_INVALID_OPERATION,
+ "glNamedFramebufferDrawBuffers(GL_ARB_direct_state_access "
+ "is not supported)");
+ return;
+ }
+
+ if (framebuffer) {
+ fb = _mesa_lookup_framebuffer_err(ctx, framebuffer,
+ "glNamedFramebufferDrawBuffers");
+ if (!fb)
+ return;
+ }
+ else
+ fb = ctx->WinSysDrawBuffer;
+
+ _mesa_draw_buffers(ctx, fb, n, bufs, "glNamedFramebufferDrawBuffers");
}
@@ -459,13 +545,11 @@ _mesa_DrawBuffers(GLsizei n, const GLenum *buffers)
* actual change.
*/
static void
-updated_drawbuffers(struct gl_context *ctx)
+updated_drawbuffers(struct gl_context *ctx, struct gl_framebuffer *fb)
{
FLUSH_VERTICES(ctx, _NEW_BUFFERS);
if (ctx->API == API_OPENGL_COMPAT && !ctx->Extensions.ARB_ES2_compatibility) {
- struct gl_framebuffer *fb = ctx->DrawBuffer;
-
/* Flag the FBO as requiring validation. */
if (_mesa_is_user_fbo(fb)) {
fb->_Status = 0;
@@ -482,6 +566,7 @@ updated_drawbuffers(struct gl_context *ctx)
* so nothing should go wrong at this point.
*
* \param ctx current context
+ * \param fb the desired draw buffer
* \param n number of color outputs to set
* \param buffers array[n] of colorbuffer names, like GL_LEFT.
* \param destMask array[n] of BUFFER_BIT_* bitmasks which correspond to the
@@ -489,10 +574,9 @@ updated_drawbuffers(struct gl_context *ctx)
* BUFFER_BIT_FRONT_LEFT | BUFFER_BIT_BACK_LEFT).
*/
void
-_mesa_drawbuffers(struct gl_context *ctx, GLuint n, const GLenum *buffers,
- const GLbitfield *destMask)
+_mesa_drawbuffers(struct gl_context *ctx, struct gl_framebuffer *fb,
+ GLuint n, const GLenum *buffers, const GLbitfield *destMask)
{
- struct gl_framebuffer *fb = ctx->DrawBuffer;
GLbitfield mask[MAX_DRAW_BUFFERS];
GLuint buf;
@@ -518,7 +602,7 @@ _mesa_drawbuffers(struct gl_context *ctx, GLuint n, const GLenum *buffers,
while (destMask0) {
GLint bufIndex = ffs(destMask0) - 1;
if (fb->_ColorDrawBufferIndexes[count] != bufIndex) {
- updated_drawbuffers(ctx);
+ updated_drawbuffers(ctx, fb);
fb->_ColorDrawBufferIndexes[count] = bufIndex;
}
count++;
@@ -535,14 +619,14 @@ _mesa_drawbuffers(struct gl_context *ctx, GLuint n, const GLenum *buffers,
/* only one bit should be set in the destMask[buf] field */
assert(_mesa_bitcount(destMask[buf]) == 1);
if (fb->_ColorDrawBufferIndexes[buf] != bufIndex) {
- updated_drawbuffers(ctx);
+ updated_drawbuffers(ctx, fb);
fb->_ColorDrawBufferIndexes[buf] = bufIndex;
}
count = buf + 1;
}
else {
if (fb->_ColorDrawBufferIndexes[buf] != -1) {
- updated_drawbuffers(ctx);
+ updated_drawbuffers(ctx, fb);
fb->_ColorDrawBufferIndexes[buf] = -1;
}
}
@@ -554,7 +638,7 @@ _mesa_drawbuffers(struct gl_context *ctx, GLuint n, const GLenum *buffers,
/* set remaining outputs to -1 (GL_NONE) */
for (buf = fb->_NumColorDrawBuffers; buf < ctx->Const.MaxDrawBuffers; buf++) {
if (fb->_ColorDrawBufferIndexes[buf] != -1) {
- updated_drawbuffers(ctx);
+ updated_drawbuffers(ctx, fb);
fb->_ColorDrawBufferIndexes[buf] = -1;
}
}
@@ -566,7 +650,7 @@ _mesa_drawbuffers(struct gl_context *ctx, GLuint n, const GLenum *buffers,
/* also set context drawbuffer state */
for (buf = 0; buf < ctx->Const.MaxDrawBuffers; buf++) {
if (ctx->Color.DrawBuffer[buf] != fb->ColorDrawBuffer[buf]) {
- updated_drawbuffers(ctx);
+ updated_drawbuffers(ctx, fb);
ctx->Color.DrawBuffer[buf] = fb->ColorDrawBuffer[buf];
}
}
@@ -585,7 +669,7 @@ _mesa_update_draw_buffers(struct gl_context *ctx)
/* should be a window system FBO */
assert(_mesa_is_winsys_fbo(ctx->DrawBuffer));
- _mesa_drawbuffers(ctx, ctx->Const.MaxDrawBuffers,
+ _mesa_drawbuffers(ctx, ctx->DrawBuffer, ctx->Const.MaxDrawBuffers,
ctx->Color.DrawBuffer, NULL);
}
@@ -598,11 +682,10 @@ _mesa_update_draw_buffers(struct gl_context *ctx)
* \param bufferIndex the numerical index corresponding to 'buffer'
*/
void
-_mesa_readbuffer(struct gl_context *ctx, GLenum buffer, GLint bufferIndex)
+_mesa_readbuffer(struct gl_context *ctx, struct gl_framebuffer *fb,
+ GLenum buffer, GLint bufferIndex)
{
- struct gl_framebuffer *fb = ctx->ReadBuffer;
-
- if (_mesa_is_winsys_fbo(fb)) {
+ if ((fb == ctx->ReadBuffer) && _mesa_is_winsys_fbo(fb)) {
/* Only update the per-context READ_BUFFER state if we're bound to
* a window-system framebuffer.
*/
@@ -621,23 +704,17 @@ _mesa_readbuffer(struct gl_context *ctx, GLenum buffer, GLint bufferIndex)
* Called by glReadBuffer to set the source renderbuffer for reading pixels.
* \param mode color buffer such as GL_FRONT, GL_BACK, etc.
*/
-void GLAPIENTRY
-_mesa_ReadBuffer(GLenum buffer)
+void
+_mesa_read_buffer(struct gl_context *ctx, struct gl_framebuffer *fb,
+ GLenum buffer, const char *caller)
{
- struct gl_framebuffer *fb;
GLbitfield supportedMask;
GLint srcBuffer;
- GET_CURRENT_CONTEXT(ctx);
FLUSH_VERTICES(ctx, 0);
if (MESA_VERBOSE & VERBOSE_API)
- _mesa_debug(ctx, "glReadBuffer %s\n", _mesa_lookup_enum_by_nr(buffer));
-
- fb = ctx->ReadBuffer;
-
- if (MESA_VERBOSE & VERBOSE_API)
- _mesa_debug(ctx, "glReadBuffer %s\n", _mesa_lookup_enum_by_nr(buffer));
+ _mesa_debug(ctx, "%s %s\n", caller, _mesa_lookup_enum_by_nr(buffer));
if (buffer == GL_NONE) {
/* This is legal--it means that no buffer should be bound for reading. */
@@ -648,24 +725,60 @@ _mesa_ReadBuffer(GLenum buffer)
srcBuffer = read_buffer_enum_to_index(buffer);
if (srcBuffer == -1) {
_mesa_error(ctx, GL_INVALID_ENUM,
- "glReadBuffer(buffer=0x%x)", buffer);
+ "%s(invalid buffer %s)", caller,
+ _mesa_lookup_enum_by_nr(buffer));
return;
}
supportedMask = supported_buffer_bitmask(ctx, fb);
if (((1 << srcBuffer) & supportedMask) == 0) {
_mesa_error(ctx, GL_INVALID_OPERATION,
- "glReadBuffer(buffer=0x%x)", buffer);
+ "%s(invalid buffer %s)", caller,
+ _mesa_lookup_enum_by_nr(buffer));
return;
}
}
/* OK, all error checking has been completed now */
- _mesa_readbuffer(ctx, buffer, srcBuffer);
+ _mesa_readbuffer(ctx, fb, buffer, srcBuffer);
- /*
- * Call device driver function.
- */
- if (ctx->Driver.ReadBuffer)
- (*ctx->Driver.ReadBuffer)(ctx, buffer);
+ /* Call the device driver function only if fb is the bound read buffer */
+ if (fb == ctx->ReadBuffer) {
+ if (ctx->Driver.ReadBuffer)
+ (*ctx->Driver.ReadBuffer)(ctx, buffer);
+ }
+}
+
+
+void GLAPIENTRY
+_mesa_ReadBuffer(GLenum buffer)
+{
+ GET_CURRENT_CONTEXT(ctx);
+ _mesa_read_buffer(ctx, ctx->ReadBuffer, buffer, "glReadBuffer");
+}
+
+
+void GLAPIENTRY
+_mesa_NamedFramebufferReadBuffer(GLuint framebuffer, GLenum src)
+{
+ GET_CURRENT_CONTEXT(ctx);
+ struct gl_framebuffer *fb;
+
+ if (!ctx->Extensions.ARB_direct_state_access) {
+ _mesa_error(ctx, GL_INVALID_OPERATION,
+ "glNamedFramebufferReadBuffer(GL_ARB_direct_state_access "
+ "is not supported)");
+ return;
+ }
+
+ if (framebuffer) {
+ fb = _mesa_lookup_framebuffer_err(ctx, framebuffer,
+ "glNamedFramebufferReadBuffer");
+ if (!fb)
+ return;
+ }
+ else
+ fb = ctx->WinSysReadBuffer;
+
+ _mesa_read_buffer(ctx, fb, src, "glNamedFramebufferReadBuffer");
}
diff --git a/mesalib/src/mesa/main/buffers.h b/mesalib/src/mesa/main/buffers.h
index ebcfa1c1e..5aa79fda5 100644
--- a/mesalib/src/mesa/main/buffers.h
+++ b/mesalib/src/mesa/main/buffers.h
@@ -36,26 +36,51 @@
#include "glheader.h"
struct gl_context;
+struct gl_framebuffer;
+
+extern void
+_mesa_draw_buffer(struct gl_context *ctx, struct gl_framebuffer *fb,
+ GLenum buffer, const char *caller);
extern void GLAPIENTRY
_mesa_DrawBuffer( GLenum mode );
extern void GLAPIENTRY
+_mesa_NamedFramebufferDrawBuffer(GLuint framebuffer, GLenum buf);
+
+extern void
+_mesa_draw_buffers(struct gl_context *ctx, struct gl_framebuffer *fb,
+ GLsizei n, const GLenum *buffers, const char *caller);
+
+extern void GLAPIENTRY
_mesa_DrawBuffers(GLsizei n, const GLenum *buffers);
+extern void GLAPIENTRY
+_mesa_NamedFramebufferDrawBuffers(GLuint framebuffer, GLsizei n,
+ const GLenum *bufs);
+
extern void
-_mesa_drawbuffers(struct gl_context *ctx, GLuint n, const GLenum *buffers,
+_mesa_drawbuffers(struct gl_context *ctx, struct gl_framebuffer *fb,
+ GLuint n, const GLenum *buffers,
const GLbitfield *destMask);
extern void
-_mesa_readbuffer(struct gl_context *ctx, GLenum buffer, GLint bufferIndex);
+_mesa_readbuffer(struct gl_context *ctx, struct gl_framebuffer *fb,
+ GLenum buffer, GLint bufferIndex);
extern void
_mesa_update_draw_buffers(struct gl_context *ctx);
+extern void
+_mesa_read_buffer(struct gl_context *ctx, struct gl_framebuffer *fb,
+ GLenum buffer, const char *caller);
+
extern void GLAPIENTRY
_mesa_ReadBuffer( GLenum mode );
+extern void GLAPIENTRY
+_mesa_NamedFramebufferReadBuffer(GLuint framebuffer, GLenum src);
+
#endif
diff --git a/mesalib/src/mesa/main/clear.c b/mesalib/src/mesa/main/clear.c
index 8d707bc34..c6999f7fd 100644
--- a/mesalib/src/mesa/main/clear.c
+++ b/mesalib/src/mesa/main/clear.c
@@ -34,6 +34,8 @@
#include "clear.h"
#include "context.h"
#include "enums.h"
+#include "fbobject.h"
+#include "get.h"
#include "macros.h"
#include "mtypes.h"
#include "state.h"
@@ -400,6 +402,32 @@ _mesa_ClearBufferiv(GLenum buffer, GLint drawbuffer, const GLint *value)
/**
+ * The ClearBuffer framework is so complicated and so riddled with the
+ * assumption that the framebuffer is bound that, for now, we will just fake
+ * direct state access clearing for the user.
+ */
+void GLAPIENTRY
+_mesa_ClearNamedFramebufferiv(GLuint framebuffer, GLenum buffer,
+ GLint drawbuffer, const GLint *value)
+{
+ GLint oldfb;
+
+ GET_CURRENT_CONTEXT(ctx);
+ if (!ctx->Extensions.ARB_direct_state_access) {
+ _mesa_error(ctx, GL_INVALID_OPERATION,
+ "glClearNamedFramebufferiv(GL_ARB_direct_state_access "
+ "is not supported)");
+ return;
+ }
+
+ _mesa_GetIntegerv(GL_DRAW_FRAMEBUFFER_BINDING, &oldfb);
+ _mesa_BindFramebuffer(GL_DRAW_FRAMEBUFFER, framebuffer);
+ _mesa_ClearBufferiv(buffer, drawbuffer, value);
+ _mesa_BindFramebuffer(GL_DRAW_FRAMEBUFFER, (GLuint) oldfb);
+}
+
+
+/**
* New in GL 3.0
* Clear unsigned integer color buffer (not depth, not stencil).
*/
@@ -472,6 +500,32 @@ _mesa_ClearBufferuiv(GLenum buffer, GLint drawbuffer, const GLuint *value)
/**
+ * The ClearBuffer framework is so complicated and so riddled with the
+ * assumption that the framebuffer is bound that, for now, we will just fake
+ * direct state access clearing for the user.
+ */
+void GLAPIENTRY
+_mesa_ClearNamedFramebufferuiv(GLuint framebuffer, GLenum buffer,
+ GLint drawbuffer, const GLuint *value)
+{
+ GLint oldfb;
+
+ GET_CURRENT_CONTEXT(ctx);
+ if (!ctx->Extensions.ARB_direct_state_access) {
+ _mesa_error(ctx, GL_INVALID_OPERATION,
+ "glClearNamedFramebufferuiv(GL_ARB_direct_state_access "
+ "is not supported)");
+ return;
+ }
+
+ _mesa_GetIntegerv(GL_DRAW_FRAMEBUFFER_BINDING, &oldfb);
+ _mesa_BindFramebuffer(GL_DRAW_FRAMEBUFFER, framebuffer);
+ _mesa_ClearBufferuiv(buffer, drawbuffer, value);
+ _mesa_BindFramebuffer(GL_DRAW_FRAMEBUFFER, (GLuint) oldfb);
+}
+
+
+/**
* New in GL 3.0
* Clear fixed-pt or float color buffer or depth buffer (not stencil).
*/
@@ -565,6 +619,32 @@ _mesa_ClearBufferfv(GLenum buffer, GLint drawbuffer, const GLfloat *value)
/**
+ * The ClearBuffer framework is so complicated and so riddled with the
+ * assumption that the framebuffer is bound that, for now, we will just fake
+ * direct state access clearing for the user.
+ */
+void GLAPIENTRY
+_mesa_ClearNamedFramebufferfv(GLuint framebuffer, GLenum buffer,
+ GLint drawbuffer, const GLfloat *value)
+{
+ GLint oldfb;
+
+ GET_CURRENT_CONTEXT(ctx);
+ if (!ctx->Extensions.ARB_direct_state_access) {
+ _mesa_error(ctx, GL_INVALID_OPERATION,
+ "glClearNamedFramebufferfv(GL_ARB_direct_state_access "
+ "is not supported)");
+ return;
+ }
+
+ _mesa_GetIntegerv(GL_DRAW_FRAMEBUFFER_BINDING, &oldfb);
+ _mesa_BindFramebuffer(GL_DRAW_FRAMEBUFFER, framebuffer);
+ _mesa_ClearBufferfv(buffer, drawbuffer, value);
+ _mesa_BindFramebuffer(GL_DRAW_FRAMEBUFFER, (GLuint) oldfb);
+}
+
+
+/**
* New in GL 3.0
* Clear depth/stencil buffer only.
*/
@@ -626,3 +706,29 @@ _mesa_ClearBufferfi(GLenum buffer, GLint drawbuffer,
ctx->Stencil.Clear = clearStencilSave;
}
}
+
+
+/**
+ * The ClearBuffer framework is so complicated and so riddled with the
+ * assumption that the framebuffer is bound that, for now, we will just fake
+ * direct state access clearing for the user.
+ */
+void GLAPIENTRY
+_mesa_ClearNamedFramebufferfi(GLuint framebuffer, GLenum buffer,
+ GLfloat depth, GLint stencil)
+{
+ GLint oldfb;
+
+ GET_CURRENT_CONTEXT(ctx);
+ if (!ctx->Extensions.ARB_direct_state_access) {
+ _mesa_error(ctx, GL_INVALID_OPERATION,
+ "glClearNamedFramebufferfi(GL_ARB_direct_state_access "
+ "is not supported)");
+ return;
+ }
+
+ _mesa_GetIntegerv(GL_DRAW_FRAMEBUFFER_BINDING, &oldfb);
+ _mesa_BindFramebuffer(GL_DRAW_FRAMEBUFFER, framebuffer);
+ _mesa_ClearBufferfi(buffer, 0, depth, stencil);
+ _mesa_BindFramebuffer(GL_DRAW_FRAMEBUFFER, (GLuint) oldfb);
+}
diff --git a/mesalib/src/mesa/main/clear.h b/mesalib/src/mesa/main/clear.h
index 96ce47b92..c29850676 100644
--- a/mesalib/src/mesa/main/clear.h
+++ b/mesalib/src/mesa/main/clear.h
@@ -52,13 +52,29 @@ extern void GLAPIENTRY
_mesa_ClearBufferiv(GLenum buffer, GLint drawbuffer, const GLint *value);
extern void GLAPIENTRY
+_mesa_ClearNamedFramebufferiv(GLuint framebuffer, GLenum buffer,
+ GLint drawbuffer, const GLint *value);
+
+extern void GLAPIENTRY
_mesa_ClearBufferuiv(GLenum buffer, GLint drawbuffer, const GLuint *value);
extern void GLAPIENTRY
+_mesa_ClearNamedFramebufferuiv(GLuint framebuffer, GLenum buffer,
+ GLint drawbuffer, const GLuint *value);
+
+extern void GLAPIENTRY
_mesa_ClearBufferfv(GLenum buffer, GLint drawbuffer, const GLfloat *value);
extern void GLAPIENTRY
+_mesa_ClearNamedFramebufferfv(GLuint framebuffer, GLenum buffer,
+ GLint drawbuffer, const GLfloat *value);
+
+extern void GLAPIENTRY
_mesa_ClearBufferfi(GLenum buffer, GLint drawbuffer,
GLfloat depth, GLint stencil);
+extern void GLAPIENTRY
+_mesa_ClearNamedFramebufferfi(GLuint framebuffer, GLenum buffer,
+ GLfloat depth, GLint stencil);
+
#endif
diff --git a/mesalib/src/mesa/main/compute.c b/mesalib/src/mesa/main/compute.c
index 5756666b6..37a4ba70e 100644
--- a/mesalib/src/mesa/main/compute.c
+++ b/mesalib/src/mesa/main/compute.c
@@ -31,9 +31,27 @@ _mesa_DispatchCompute(GLuint num_groups_x,
GLuint num_groups_z)
{
GET_CURRENT_CONTEXT(ctx);
+ int i;
+ struct gl_shader_program *prog;
+ const GLuint num_groups[3] = { num_groups_x, num_groups_y, num_groups_z };
if (ctx->Extensions.ARB_compute_shader) {
- assert(!"TODO");
+ for (i = 0; i < 3; i++) {
+ if (num_groups[i] > ctx->Const.MaxComputeWorkGroupCount[i]) {
+ _mesa_error(ctx, GL_INVALID_VALUE,
+ "glDispatchCompute(num_groups_%c)", 'x' + i);
+ return;
+ }
+ }
+ if (!_mesa_valid_to_render(ctx, "glDispatchCompute"))
+ return;
+ prog = ctx->Shader.CurrentProgram[MESA_SHADER_COMPUTE];
+ if (prog == NULL || prog->_LinkedShaders[MESA_SHADER_COMPUTE] == NULL) {
+ _mesa_error(ctx, GL_INVALID_OPERATION,
+ "glDispatchCompute(no active compute shader)");
+ return;
+ }
+ ctx->Driver.DispatchCompute(ctx, num_groups);
} else {
_mesa_error(ctx, GL_INVALID_OPERATION,
"unsupported function (glDispatchCompute) called");
diff --git a/mesalib/src/mesa/main/context.c b/mesalib/src/mesa/main/context.c
index 4aaf8b1af..544cc142f 100644
--- a/mesalib/src/mesa/main/context.c
+++ b/mesalib/src/mesa/main/context.c
@@ -118,6 +118,7 @@
#include "scissor.h"
#include "shared.h"
#include "shaderobj.h"
+#include "shaderimage.h"
#include "util/simple_list.h"
#include "state.h"
#include "stencil.h"
@@ -821,6 +822,7 @@ init_attrib_groups(struct gl_context *ctx)
_mesa_init_feedback( ctx );
_mesa_init_fog( ctx );
_mesa_init_hint( ctx );
+ _mesa_init_image_units( ctx );
_mesa_init_line( ctx );
_mesa_init_lighting( ctx );
_mesa_init_matrix( ctx );
@@ -1563,7 +1565,8 @@ handle_first_current(struct gl_context *ctx)
else
buffer = GL_FRONT;
- _mesa_drawbuffers(ctx, 1, &buffer, NULL /* destMask */);
+ _mesa_drawbuffers(ctx, ctx->DrawBuffer, 1, &buffer,
+ NULL /* destMask */);
}
if (ctx->ReadBuffer != _mesa_get_incomplete_framebuffer()) {
@@ -1576,7 +1579,7 @@ handle_first_current(struct gl_context *ctx)
bufferIndex = BUFFER_FRONT_LEFT;
}
- _mesa_readbuffer(ctx, buffer, bufferIndex);
+ _mesa_readbuffer(ctx, ctx->ReadBuffer, buffer, bufferIndex);
}
}
diff --git a/mesalib/src/mesa/main/context.h b/mesalib/src/mesa/main/context.h
index 1cd89a84a..6f3c94101 100644
--- a/mesalib/src/mesa/main/context.h
+++ b/mesalib/src/mesa/main/context.h
@@ -285,7 +285,7 @@ do { \
/**
* Checks if the context is for Desktop GL (Compatibility or Core)
*/
-static inline GLboolean
+static inline bool
_mesa_is_desktop_gl(const struct gl_context *ctx)
{
return ctx->API == API_OPENGL_COMPAT || ctx->API == API_OPENGL_CORE;
@@ -295,7 +295,7 @@ _mesa_is_desktop_gl(const struct gl_context *ctx)
/**
* Checks if the context is for any GLES version
*/
-static inline GLboolean
+static inline bool
_mesa_is_gles(const struct gl_context *ctx)
{
return ctx->API == API_OPENGLES || ctx->API == API_OPENGLES2;
@@ -303,9 +303,9 @@ _mesa_is_gles(const struct gl_context *ctx)
/**
- * Checks if the context is for GLES 3.x
+ * Checks if the context is for GLES 3.0 or later
*/
-static inline GLboolean
+static inline bool
_mesa_is_gles3(const struct gl_context *ctx)
{
return ctx->API == API_OPENGLES2 && ctx->Version >= 30;
@@ -313,9 +313,19 @@ _mesa_is_gles3(const struct gl_context *ctx)
/**
+ * Checks if the context is for GLES 3.1 or later
+ */
+static inline bool
+_mesa_is_gles31(const struct gl_context *ctx)
+{
+ return ctx->API == API_OPENGLES2 && ctx->Version >= 31;
+}
+
+
+/**
* Checks if the context supports geometry shaders.
*/
-static inline GLboolean
+static inline bool
_mesa_has_geometry_shaders(const struct gl_context *ctx)
{
return _mesa_is_desktop_gl(ctx) &&
diff --git a/mesalib/src/mesa/main/dd.h b/mesalib/src/mesa/main/dd.h
index 0c1a13fa4..d783e3422 100644
--- a/mesalib/src/mesa/main/dd.h
+++ b/mesalib/src/mesa/main/dd.h
@@ -1005,6 +1005,13 @@ struct dd_function_table {
void (*MemoryBarrier)(struct gl_context *ctx, GLbitfield barriers);
/** @} */
+
+ /**
+ * \name GL_ARB_compute_shader interface
+ */
+ /*@{*/
+ void (*DispatchCompute)(struct gl_context *ctx, const GLuint *num_groups);
+ /*@}*/
};
@@ -1167,6 +1174,19 @@ typedef struct {
void (GLAPIENTRYP VertexAttribP4uiv)( GLuint index, GLenum type,
GLboolean normalized,
const GLuint *value);
+
+ /* GL_ARB_vertex_attrib_64bit / GL 4.1 */
+ void (GLAPIENTRYP VertexAttribL1d)( GLuint index, GLdouble x);
+ void (GLAPIENTRYP VertexAttribL2d)( GLuint index, GLdouble x, GLdouble y);
+ void (GLAPIENTRYP VertexAttribL3d)( GLuint index, GLdouble x, GLdouble y, GLdouble z);
+ void (GLAPIENTRYP VertexAttribL4d)( GLuint index, GLdouble x, GLdouble y, GLdouble z, GLdouble w);
+
+
+ void (GLAPIENTRYP VertexAttribL1dv)( GLuint index, const GLdouble *v);
+ void (GLAPIENTRYP VertexAttribL2dv)( GLuint index, const GLdouble *v);
+ void (GLAPIENTRYP VertexAttribL3dv)( GLuint index, const GLdouble *v);
+ void (GLAPIENTRYP VertexAttribL4dv)( GLuint index, const GLdouble *v);
+
} GLvertexformat;
diff --git a/mesalib/src/mesa/main/extensions.c b/mesalib/src/mesa/main/extensions.c
index 9be8993b0..c82416aa0 100644
--- a/mesalib/src/mesa/main/extensions.c
+++ b/mesalib/src/mesa/main/extensions.c
@@ -104,7 +104,7 @@ static const struct extension extension_table[] = {
{ "GL_ARB_depth_clamp", o(ARB_depth_clamp), GL, 2003 },
{ "GL_ARB_depth_texture", o(ARB_depth_texture), GLL, 2001 },
{ "GL_ARB_derivative_control", o(ARB_derivative_control), GL, 2014 },
- { "GL_ARB_direct_state_access", o(dummy_false), GL, 2014 },
+ { "GL_ARB_direct_state_access", o(ARB_direct_state_access), GL, 2014 },
{ "GL_ARB_draw_buffers", o(dummy_true), GL, 2002 },
{ "GL_ARB_draw_buffers_blend", o(ARB_draw_buffers_blend), GL, 2009 },
{ "GL_ARB_draw_elements_base_vertex", o(ARB_draw_elements_base_vertex), GL, 2009 },
@@ -203,6 +203,7 @@ static const struct extension extension_table[] = {
{ "GL_ARB_vertex_buffer_object", o(dummy_true), GLL, 2003 },
{ "GL_ARB_vertex_program", o(ARB_vertex_program), GLL, 2002 },
{ "GL_ARB_vertex_shader", o(ARB_vertex_shader), GL, 2002 },
+ { "GL_ARB_vertex_attrib_64bit", o(ARB_vertex_attrib_64bit), GLC, 2010 },
{ "GL_ARB_vertex_type_10f_11f_11f_rev", o(ARB_vertex_type_10f_11f_11f_rev), GL, 2013 },
{ "GL_ARB_vertex_type_2_10_10_10_rev", o(ARB_vertex_type_2_10_10_10_rev), GL, 2009 },
{ "GL_ARB_viewport_array", o(ARB_viewport_array), GLC, 2010 },
diff --git a/mesalib/src/mesa/main/fbobject.c b/mesalib/src/mesa/main/fbobject.c
index 27cf97f17..8db651ca2 100644
--- a/mesalib/src/mesa/main/fbobject.c
+++ b/mesalib/src/mesa/main/fbobject.c
@@ -121,6 +121,27 @@ _mesa_lookup_renderbuffer(struct gl_context *ctx, GLuint id)
/**
+ * A convenience function for direct state access that throws
+ * GL_INVALID_OPERATION if the renderbuffer doesn't exist.
+ */
+struct gl_renderbuffer *
+_mesa_lookup_renderbuffer_err(struct gl_context *ctx, GLuint id,
+ const char *func)
+{
+ struct gl_renderbuffer *rb;
+
+ rb = _mesa_lookup_renderbuffer(ctx, id);
+ if (!rb || rb == &DummyRenderbuffer) {
+ _mesa_error(ctx, GL_INVALID_OPERATION,
+ "%s(non-existent renderbuffer %u)", func, id);
+ return NULL;
+ }
+
+ return rb;
+}
+
+
+/**
* Helper routine for getting a gl_framebuffer.
*/
struct gl_framebuffer *
@@ -138,6 +159,27 @@ _mesa_lookup_framebuffer(struct gl_context *ctx, GLuint id)
/**
+ * A convenience function for direct state access that throws
+ * GL_INVALID_OPERATION if the framebuffer doesn't exist.
+ */
+struct gl_framebuffer *
+_mesa_lookup_framebuffer_err(struct gl_context *ctx, GLuint id,
+ const char *func)
+{
+ struct gl_framebuffer *fb;
+
+ fb = _mesa_lookup_framebuffer(ctx, id);
+ if (!fb || fb == &DummyFramebuffer) {
+ _mesa_error(ctx, GL_INVALID_OPERATION,
+ "%s(non-existent framebuffer %u)", func, id);
+ return NULL;
+ }
+
+ return fb;
+}
+
+
+/**
* Mark the given framebuffer as invalid. This will force the
* test for framebuffer completeness to be done before the framebuffer
* is used.
@@ -423,7 +465,7 @@ set_texture_attachment(struct gl_context *ctx,
struct gl_framebuffer *fb,
struct gl_renderbuffer_attachment *att,
struct gl_texture_object *texObj,
- GLenum texTarget, GLuint level, GLuint zoffset,
+ GLenum texTarget, GLuint level, GLuint layer,
GLboolean layered)
{
struct gl_renderbuffer *rb = att->Renderbuffer;
@@ -447,7 +489,7 @@ set_texture_attachment(struct gl_context *ctx,
/* always update these fields */
att->TextureLevel = level;
att->CubeMapFace = _mesa_tex_target_to_face(texTarget);
- att->Zoffset = zoffset;
+ att->Zoffset = layer;
att->Layered = layered;
att->Complete = GL_FALSE;
@@ -479,9 +521,10 @@ set_renderbuffer_attachment(struct gl_context *ctx,
* Attach a renderbuffer object to a framebuffer object.
*/
void
-_mesa_framebuffer_renderbuffer(struct gl_context *ctx,
- struct gl_framebuffer *fb,
- GLenum attachment, struct gl_renderbuffer *rb)
+_mesa_FramebufferRenderbuffer_sw(struct gl_context *ctx,
+ struct gl_framebuffer *fb,
+ GLenum attachment,
+ struct gl_renderbuffer *rb)
{
struct gl_renderbuffer_attachment *att;
@@ -1446,6 +1489,14 @@ void GLAPIENTRY
_mesa_CreateRenderbuffers(GLsizei n, GLuint *renderbuffers)
{
GET_CURRENT_CONTEXT(ctx);
+
+ if (!ctx->Extensions.ARB_direct_state_access) {
+ _mesa_error(ctx, GL_INVALID_OPERATION,
+ "glCreateRenderbuffers(GL_ARB_direct_state_access "
+ "is not supported)");
+ return;
+ }
+
create_render_buffers(ctx, n, renderbuffers, true);
}
@@ -1886,6 +1937,12 @@ renderbuffer_storage_named(GLuint renderbuffer, GLenum internalFormat,
{
GET_CURRENT_CONTEXT(ctx);
+ if (!ctx->Extensions.ARB_direct_state_access) {
+ _mesa_error(ctx, GL_INVALID_OPERATION,
+ "%s(GL_ARB_direct_state_access is not supported)", func);
+ return;
+ }
+
if (MESA_VERBOSE & VERBOSE_API) {
if (samples == NO_SAMPLES)
_mesa_debug(ctx, "%s(%u, %s, %d, %d)\n",
@@ -2140,6 +2197,13 @@ _mesa_GetNamedRenderbufferParameteriv(GLuint renderbuffer, GLenum pname,
{
GET_CURRENT_CONTEXT(ctx);
+ if (!ctx->Extensions.ARB_direct_state_access) {
+ _mesa_error(ctx, GL_INVALID_OPERATION,
+ "glGetNamedRenderbufferParameteriv("
+ "GL_ARB_direct_state_access is not supported)");
+ return;
+ }
+
struct gl_renderbuffer *rb = _mesa_lookup_renderbuffer(ctx, renderbuffer);
if (!rb || rb == &DummyRenderbuffer) {
/* ID was reserved, but no real renderbuffer object made yet */
@@ -2396,15 +2460,29 @@ _mesa_DeleteFramebuffers(GLsizei n, const GLuint *framebuffers)
}
-void GLAPIENTRY
-_mesa_GenFramebuffers(GLsizei n, GLuint *framebuffers)
+/**
+ * This is the implementation for glGenFramebuffers and glCreateFramebuffers.
+ * It is not exposed to the rest of Mesa to encourage the use of
+ * nameless buffers in driver internals.
+ */
+static void
+create_framebuffers(GLsizei n, GLuint *framebuffers, bool dsa)
{
GET_CURRENT_CONTEXT(ctx);
GLuint first;
GLint i;
+ struct gl_framebuffer *fb;
+
+ const char *func = dsa ? "glCreateFramebuffers" : "glGenFramebuffers";
+
+ if (dsa && !ctx->Extensions.ARB_direct_state_access) {
+ _mesa_error(ctx, GL_INVALID_OPERATION,
+ "%s(GL_ARB_direct_state_access is not supported)", func);
+ return;
+ }
if (n < 0) {
- _mesa_error(ctx, GL_INVALID_VALUE, "glGenFramebuffersEXT(n)");
+ _mesa_error(ctx, GL_INVALID_VALUE, "%s(n < 0)", func);
return;
}
@@ -2416,31 +2494,43 @@ _mesa_GenFramebuffers(GLsizei n, GLuint *framebuffers)
for (i = 0; i < n; i++) {
GLuint name = first + i;
framebuffers[i] = name;
- /* insert dummy placeholder into hash table */
+
+ if (dsa) {
+ fb = ctx->Driver.NewFramebuffer(ctx, framebuffers[i]);
+ if (!fb) {
+ _mesa_error(ctx, GL_OUT_OF_MEMORY, "%s", func);
+ return;
+ }
+ }
+ else
+ fb = &DummyFramebuffer;
+
mtx_lock(&ctx->Shared->Mutex);
- _mesa_HashInsert(ctx->Shared->FrameBuffers, name, &DummyFramebuffer);
+ _mesa_HashInsert(ctx->Shared->FrameBuffers, name, fb);
mtx_unlock(&ctx->Shared->Mutex);
}
}
-GLenum GLAPIENTRY
-_mesa_CheckFramebufferStatus(GLenum target)
+void GLAPIENTRY
+_mesa_GenFramebuffers(GLsizei n, GLuint *framebuffers)
{
- struct gl_framebuffer *buffer;
- GET_CURRENT_CONTEXT(ctx);
+ create_framebuffers(n, framebuffers, false);
+}
- ASSERT_OUTSIDE_BEGIN_END_WITH_RETVAL(ctx, 0);
- if (MESA_VERBOSE & VERBOSE_API)
- _mesa_debug(ctx, "glCheckFramebufferStatus(%s)\n",
- _mesa_lookup_enum_by_nr(target));
+void GLAPIENTRY
+_mesa_CreateFramebuffers(GLsizei n, GLuint *framebuffers)
+{
+ create_framebuffers(n, framebuffers, true);
+}
- buffer = get_framebuffer_target(ctx, target);
- if (!buffer) {
- _mesa_error(ctx, GL_INVALID_ENUM, "glCheckFramebufferStatus(target)");
- return 0;
- }
+
+GLenum
+_mesa_check_framebuffer_status(struct gl_context *ctx,
+ struct gl_framebuffer *buffer)
+{
+ ASSERT_OUTSIDE_BEGIN_END_WITH_RETVAL(ctx, 0);
if (_mesa_is_winsys_fbo(buffer)) {
/* EGL_KHR_surfaceless_context allows the winsys FBO to be incomplete. */
@@ -2461,6 +2551,74 @@ _mesa_CheckFramebufferStatus(GLenum target)
}
+GLenum GLAPIENTRY
+_mesa_CheckFramebufferStatus(GLenum target)
+{
+ struct gl_framebuffer *fb;
+ GET_CURRENT_CONTEXT(ctx);
+
+ if (MESA_VERBOSE & VERBOSE_API)
+ _mesa_debug(ctx, "glCheckFramebufferStatus(%s)\n",
+ _mesa_lookup_enum_by_nr(target));
+
+ fb = get_framebuffer_target(ctx, target);
+ if (!fb) {
+ _mesa_error(ctx, GL_INVALID_ENUM,
+ "glCheckFramebufferStatus(invalid target %s)",
+ _mesa_lookup_enum_by_nr(target));
+ return 0;
+ }
+
+ return _mesa_check_framebuffer_status(ctx, fb);
+}
+
+
+GLenum GLAPIENTRY
+_mesa_CheckNamedFramebufferStatus(GLuint framebuffer, GLenum target)
+{
+ struct gl_framebuffer *fb;
+ GET_CURRENT_CONTEXT(ctx);
+
+ if (!ctx->Extensions.ARB_direct_state_access) {
+ _mesa_error(ctx, GL_INVALID_OPERATION,
+ "glCheckNamedFramebufferStatus(GL_ARB_direct_state_access "
+ "is not supported)");
+ return 0;
+ }
+
+ /* Validate the target (for conformance's sake) and grab a reference to the
+ * default framebuffer in case framebuffer = 0.
+ * Section 9.4 Framebuffer Completeness of the OpenGL 4.5 core spec
+ * (30.10.2014, PDF page 336) says:
+ * "If framebuffer is zero, then the status of the default read or
+ * draw framebuffer (as determined by target) is returned."
+ */
+ switch (target) {
+ case GL_DRAW_FRAMEBUFFER:
+ case GL_FRAMEBUFFER:
+ fb = ctx->WinSysDrawBuffer;
+ break;
+ case GL_READ_FRAMEBUFFER:
+ fb = ctx->WinSysReadBuffer;
+ break;
+ default:
+ _mesa_error(ctx, GL_INVALID_ENUM,
+ "glCheckNamedFramebufferStatus(invalid target %s)",
+ _mesa_lookup_enum_by_nr(target));
+ return 0;
+ }
+
+ if (framebuffer) {
+ fb = _mesa_lookup_framebuffer_err(ctx, framebuffer,
+ "glCheckNamedFramebufferStatus");
+ if (!fb)
+ return 0;
+ }
+
+ return _mesa_check_framebuffer_status(ctx, fb);
+}
+
+
/**
* Replicate the src attachment point. Used by framebuffer_texture() when
* the same texture is attached at GL_DEPTH_ATTACHMENT and
@@ -2487,144 +2645,301 @@ reuse_framebuffer_texture_attachment(struct gl_framebuffer *fb,
/**
- * Common code called by glFramebufferTexture1D/2D/3D() and
- * glFramebufferTextureLayer().
+ * Common code called by gl*FramebufferTexture*() to retrieve the correct
+ * texture object pointer.
*
- * \param textarget is the textarget that was passed to the
- * glFramebufferTexture...() function, or 0 if the corresponding function
- * doesn't have a textarget parameter.
+ * \param texObj where the pointer to the texture object is returned. Note
+ * that a successful call may return texObj = NULL.
*
- * \param layered is true if this function was called from
- * glFramebufferTexture(), false otherwise.
+ * \return true if no errors, false if errors
*/
-static void
-framebuffer_texture(struct gl_context *ctx, const char *caller, GLenum target,
- GLenum attachment, GLenum textarget, GLuint texture,
- GLint level, GLuint zoffset, GLboolean layered)
+static bool
+get_texture_for_framebuffer(struct gl_context *ctx, GLuint texture,
+ bool layered, const char *caller,
+ struct gl_texture_object **texObj)
{
- struct gl_renderbuffer_attachment *att;
- struct gl_texture_object *texObj = NULL;
- struct gl_framebuffer *fb;
- GLenum maxLevelsTarget;
+ *texObj = NULL; /* This will get returned if texture = 0. */
- fb = get_framebuffer_target(ctx, target);
- if (!fb) {
- _mesa_error(ctx, GL_INVALID_ENUM,
- "glFramebufferTexture%s(target=0x%x)", caller, target);
- return;
+ if (!texture)
+ return true;
+
+ *texObj = _mesa_lookup_texture(ctx, texture);
+ if (*texObj == NULL || (*texObj)->Target == 0) {
+ /* Can't render to a non-existent texture object.
+ *
+ * The OpenGL 4.5 core spec (02.02.2015) in Section 9.2 Binding and
+ * Managing Framebuffer Objects specifies a different error
+ * depending upon the calling function (PDF pages 325-328).
+ * *FramebufferTexture (where layered = GL_TRUE) throws invalid
+ * value, while the other commands throw invalid operation (where
+ * layered = GL_FALSE).
+ */
+ const GLenum error = layered ? GL_INVALID_VALUE :
+ GL_INVALID_OPERATION;
+ _mesa_error(ctx, error,
+ "%s(non-existent texture %u)", caller, texture);
+ return false;
}
- /* check framebuffer binding */
- if (_mesa_is_winsys_fbo(fb)) {
- _mesa_error(ctx, GL_INVALID_OPERATION,
- "glFramebufferTexture%s", caller);
- return;
+ return true;
+}
+
+
+/**
+ * Common code called by gl*FramebufferTexture() to verify the texture target
+ * and decide whether or not the attachment should truly be considered
+ * layered.
+ *
+ * \param layered true if attachment should be considered layered, false if
+ * not
+ *
+ * \return true if no errors, false if errors
+ */
+static bool
+check_layered_texture_target(struct gl_context *ctx, GLenum target,
+ const char *caller, GLboolean *layered)
+{
+ *layered = GL_TRUE;
+
+ switch (target) {
+ case GL_TEXTURE_3D:
+ case GL_TEXTURE_1D_ARRAY_EXT:
+ case GL_TEXTURE_2D_ARRAY_EXT:
+ case GL_TEXTURE_CUBE_MAP:
+ case GL_TEXTURE_CUBE_MAP_ARRAY:
+ case GL_TEXTURE_2D_MULTISAMPLE_ARRAY:
+ return true;
+ case GL_TEXTURE_1D:
+ case GL_TEXTURE_2D:
+ case GL_TEXTURE_RECTANGLE:
+ case GL_TEXTURE_2D_MULTISAMPLE:
+ /* These texture types are valid to pass to
+ * glFramebufferTexture(), but since they aren't layered, it
+ * is equivalent to calling glFramebufferTexture{1D,2D}().
+ */
+ *layered = GL_FALSE;
+ return true;
}
- /* The textarget, level, and zoffset parameters are only validated if
- * texture is non-zero.
+ _mesa_error(ctx, GL_INVALID_OPERATION,
+ "%s(invalid texture target %s)", caller,
+ _mesa_lookup_enum_by_nr(target));
+ return false;
+}
+
+
+/**
+ * Common code called by gl*FramebufferTextureLayer() to verify the texture
+ * target.
+ *
+ * \return true if no errors, false if errors
+ */
+static bool
+check_texture_target(struct gl_context *ctx, GLenum target,
+ const char *caller)
+{
+ /* We're being called by glFramebufferTextureLayer().
+ * The only legal texture types for that function are 3D,
+ * cube-map, and 1D/2D/cube-map array textures.
*/
- if (texture) {
- GLboolean err = GL_TRUE;
-
- texObj = _mesa_lookup_texture(ctx, texture);
- if (texObj != NULL) {
- if (textarget == 0) {
- if (layered) {
- /* We're being called by glFramebufferTexture() and textarget
- * is not used.
- */
- switch (texObj->Target) {
- case GL_TEXTURE_3D:
- case GL_TEXTURE_1D_ARRAY_EXT:
- case GL_TEXTURE_2D_ARRAY_EXT:
- case GL_TEXTURE_CUBE_MAP:
- case GL_TEXTURE_CUBE_MAP_ARRAY:
- case GL_TEXTURE_2D_MULTISAMPLE_ARRAY:
- err = false;
- break;
- case GL_TEXTURE_1D:
- case GL_TEXTURE_2D:
- case GL_TEXTURE_RECTANGLE:
- case GL_TEXTURE_2D_MULTISAMPLE:
- /* These texture types are valid to pass to
- * glFramebufferTexture(), but since they aren't layered, it
- * is equivalent to calling glFramebufferTexture{1D,2D}().
- */
- err = false;
- layered = false;
- textarget = texObj->Target;
- break;
- default:
- err = true;
- break;
- }
- } else {
- /* We're being called by glFramebufferTextureLayer() and
- * textarget is not used. The only legal texture types for
- * that function are 3D and 1D/2D arrays textures.
- */
- err = (texObj->Target != GL_TEXTURE_3D) &&
- (texObj->Target != GL_TEXTURE_1D_ARRAY_EXT) &&
- (texObj->Target != GL_TEXTURE_2D_ARRAY_EXT) &&
- (texObj->Target != GL_TEXTURE_CUBE_MAP_ARRAY) &&
- (texObj->Target != GL_TEXTURE_2D_MULTISAMPLE_ARRAY);
- }
- }
- else {
- /* Make sure textarget is consistent with the texture's type */
- err = (texObj->Target == GL_TEXTURE_CUBE_MAP)
- ? !_mesa_is_cube_face(textarget)
- : (texObj->Target != textarget);
- }
+ switch (target) {
+ case GL_TEXTURE_3D:
+ case GL_TEXTURE_1D_ARRAY:
+ case GL_TEXTURE_2D_ARRAY:
+ case GL_TEXTURE_CUBE_MAP_ARRAY:
+ case GL_TEXTURE_2D_MULTISAMPLE_ARRAY:
+ return true;
+ case GL_TEXTURE_CUBE_MAP:
+ /* This target is valid in TextureLayer when ARB_direct_state_access
+ * or OpenGL 4.5 is supported.
+ */
+ return ctx->Extensions.ARB_direct_state_access;
+ }
+
+ _mesa_error(ctx, GL_INVALID_OPERATION,
+ "%s(invalid texture target %s)", caller,
+ _mesa_lookup_enum_by_nr(target));
+ return false;
+}
+
+
+/**
+ * Common code called by glFramebufferTexture*D() to verify the texture
+ * target.
+ *
+ * \return true if no errors, false if errors
+ */
+static bool
+check_textarget(struct gl_context *ctx, int dims, GLenum target,
+ GLenum textarget, const char *caller)
+{
+ bool err = false;
+
+ switch (dims) {
+ case 1:
+ switch (textarget) {
+ case GL_TEXTURE_1D:
+ break;
+ case GL_TEXTURE_1D_ARRAY:
+ err = !ctx->Extensions.EXT_texture_array;
+ break;
+ default:
+ err = true;
}
- else {
- /* can't render to a non-existant texture */
- _mesa_error(ctx, GL_INVALID_OPERATION,
- "glFramebufferTexture%s(non existant texture)",
- caller);
- return;
+ break;
+ case 2:
+ switch (textarget) {
+ case GL_TEXTURE_2D:
+ break;
+ case GL_TEXTURE_RECTANGLE:
+ err = _mesa_is_gles(ctx)
+ || !ctx->Extensions.NV_texture_rectangle;
+ break;
+ case GL_TEXTURE_CUBE_MAP_POSITIVE_X:
+ case GL_TEXTURE_CUBE_MAP_NEGATIVE_X:
+ case GL_TEXTURE_CUBE_MAP_POSITIVE_Y:
+ case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y:
+ case GL_TEXTURE_CUBE_MAP_POSITIVE_Z:
+ case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z:
+ err = !ctx->Extensions.ARB_texture_cube_map;
+ break;
+ case GL_TEXTURE_2D_ARRAY:
+ err = (_mesa_is_gles(ctx) && ctx->Version < 30)
+ || !ctx->Extensions.EXT_texture_array;
+ break;
+ case GL_TEXTURE_2D_MULTISAMPLE:
+ case GL_TEXTURE_2D_MULTISAMPLE_ARRAY:
+ err = _mesa_is_gles(ctx)
+ || !ctx->Extensions.ARB_texture_multisample;
+ break;
+ default:
+ err = true;
}
+ break;
+ case 3:
+ if (textarget != GL_TEXTURE_3D)
+ err = true;
+ break;
+ default:
+ err = true;
+ }
- if (err) {
- _mesa_error(ctx, GL_INVALID_OPERATION,
- "glFramebufferTexture%s(texture target mismatch)",
- caller);
- return;
- }
+ if (err) {
+ _mesa_error(ctx, GL_INVALID_OPERATION,
+ "%s(invalid textarget %s)",
+ caller, _mesa_lookup_enum_by_nr(textarget));
+ return false;
+ }
- if (texObj->Target == GL_TEXTURE_3D) {
- const GLuint maxSize = 1 << (ctx->Const.Max3DTextureLevels - 1);
- if (zoffset >= maxSize) {
- _mesa_error(ctx, GL_INVALID_VALUE,
- "glFramebufferTexture%s(zoffset)", caller);
- return;
- }
+ /* Make sure textarget is consistent with the texture's type */
+ err = (target == GL_TEXTURE_CUBE_MAP) ?
+ !_mesa_is_cube_face(textarget): (target != textarget);
+
+ if (err) {
+ _mesa_error(ctx, GL_INVALID_OPERATION,
+ "%s(mismatched texture target)", caller);
+ return false;
+ }
+
+ return true;
+}
+
+
+/**
+ * Common code called by gl*FramebufferTextureLayer() and
+ * glFramebufferTexture3D() to validate the layer.
+ *
+ * \return true if no errors, false if errors
+ */
+static bool
+check_layer(struct gl_context *ctx, GLenum target, GLint layer,
+ const char *caller)
+{
+ /* Page 306 (page 328 of the PDF) of the OpenGL 4.5 (Core Profile)
+ * spec says:
+ *
+ * "An INVALID_VALUE error is generated if texture is non-zero
+ * and layer is negative."
+ */
+ if (layer < 0) {
+ _mesa_error(ctx, GL_INVALID_VALUE,
+ "%s(layer %u < 0)", caller, layer);
+ return false;
+ }
+
+ if (target == GL_TEXTURE_3D) {
+ const GLuint maxSize = 1 << (ctx->Const.Max3DTextureLevels - 1);
+ if (layer >= maxSize) {
+ _mesa_error(ctx, GL_INVALID_VALUE,
+ "%s(invalid layer %u)", caller, layer);
+ return false;
}
- else if ((texObj->Target == GL_TEXTURE_1D_ARRAY_EXT) ||
- (texObj->Target == GL_TEXTURE_2D_ARRAY_EXT) ||
- (texObj->Target == GL_TEXTURE_CUBE_MAP_ARRAY) ||
- (texObj->Target == GL_TEXTURE_2D_MULTISAMPLE_ARRAY)) {
- if (zoffset >= ctx->Const.MaxArrayTextureLayers) {
- _mesa_error(ctx, GL_INVALID_VALUE,
- "glFramebufferTexture%s(layer)", caller);
- return;
- }
+ }
+ else if ((target == GL_TEXTURE_1D_ARRAY) ||
+ (target == GL_TEXTURE_2D_ARRAY) ||
+ (target == GL_TEXTURE_CUBE_MAP_ARRAY) ||
+ (target == GL_TEXTURE_2D_MULTISAMPLE_ARRAY)) {
+ if (layer >= ctx->Const.MaxArrayTextureLayers) {
+ _mesa_error(ctx, GL_INVALID_VALUE,
+ "%s(layer %u >= GL_MAX_ARRAY_TEXTURE_LAYERS)",
+ caller, layer);
+ return false;
}
-
- maxLevelsTarget = textarget ? textarget : texObj->Target;
- if ((level < 0) ||
- (level >= _mesa_max_texture_levels(ctx, maxLevelsTarget))) {
+ }
+ else if (target == GL_TEXTURE_CUBE_MAP) {
+ if (layer >= 6) {
_mesa_error(ctx, GL_INVALID_VALUE,
- "glFramebufferTexture%s(level)", caller);
- return;
+ "%s(layer %u >= 6)", caller, layer);
+ return false;
}
}
+ return true;
+}
+
+
+/**
+ * Common code called by all gl*FramebufferTexture*() entry points to verify
+ * the level.
+ *
+ * \return true if no errors, false if errors
+ */
+static bool
+check_level(struct gl_context *ctx, GLenum target, GLint level,
+ const char *caller)
+{
+ if ((level < 0) ||
+ (level >= _mesa_max_texture_levels(ctx, target))) {
+ _mesa_error(ctx, GL_INVALID_VALUE,
+ "%s(invalid level %d)", caller, level);
+ return false;
+ }
+
+ return true;
+}
+
+
+void
+_mesa_framebuffer_texture(struct gl_context *ctx, struct gl_framebuffer *fb,
+ GLenum attachment,
+ struct gl_texture_object *texObj, GLenum textarget,
+ GLint level, GLuint layer, GLboolean layered,
+ const char *caller)
+{
+ struct gl_renderbuffer_attachment *att;
+
+ /* The window-system framebuffer object is immutable */
+ if (_mesa_is_winsys_fbo(fb)) {
+ _mesa_error(ctx, GL_INVALID_OPERATION, "%s(window-system framebuffer)",
+ caller);
+ return;
+ }
+
+ /* Not a hash lookup, so we can afford to get the attachment here. */
att = get_attachment(ctx, fb, attachment);
if (att == NULL) {
- _mesa_error(ctx, GL_INVALID_ENUM,
- "glFramebufferTexture%s(attachment)", caller);
+ _mesa_error(ctx, GL_INVALID_ENUM, "%s(invalid attachment %s)", caller,
+ _mesa_lookup_enum_by_nr(attachment));
return;
}
@@ -2637,7 +2952,7 @@ framebuffer_texture(struct gl_context *ctx, const char *caller, GLenum target,
level == fb->Attachment[BUFFER_STENCIL].TextureLevel &&
_mesa_tex_target_to_face(textarget) ==
fb->Attachment[BUFFER_STENCIL].CubeMapFace &&
- zoffset == fb->Attachment[BUFFER_STENCIL].Zoffset) {
+ layer == fb->Attachment[BUFFER_STENCIL].Zoffset) {
/* The texture object is already attached to the stencil attachment
* point. Don't create a new renderbuffer; just reuse the stencil
* attachment's. This is required to prevent a GL error in
@@ -2650,13 +2965,14 @@ framebuffer_texture(struct gl_context *ctx, const char *caller, GLenum target,
level == fb->Attachment[BUFFER_DEPTH].TextureLevel &&
_mesa_tex_target_to_face(textarget) ==
fb->Attachment[BUFFER_DEPTH].CubeMapFace &&
- zoffset == fb->Attachment[BUFFER_DEPTH].Zoffset) {
+ layer == fb->Attachment[BUFFER_DEPTH].Zoffset) {
/* As above, but with depth and stencil transposed. */
reuse_framebuffer_texture_attachment(fb, BUFFER_STENCIL,
BUFFER_DEPTH);
} else {
set_texture_attachment(ctx, fb, att, texObj, textarget,
- level, zoffset, layered);
+ level, layer, layered);
+
if (attachment == GL_DEPTH_STENCIL_ATTACHMENT) {
/* Above we created a new renderbuffer and attached it to the
* depth attachment point. Now attach it to the stencil attachment
@@ -2692,36 +3008,50 @@ framebuffer_texture(struct gl_context *ctx, const char *caller, GLenum target,
}
-void GLAPIENTRY
-_mesa_FramebufferTexture1D(GLenum target, GLenum attachment,
- GLenum textarget, GLuint texture, GLint level)
+static void
+framebuffer_texture_with_dims(int dims, GLenum target,
+ GLenum attachment, GLenum textarget,
+ GLuint texture, GLint level, GLint layer,
+ const char *caller)
{
GET_CURRENT_CONTEXT(ctx);
+ struct gl_framebuffer *fb;
+ struct gl_texture_object *texObj;
- if (texture != 0) {
- GLboolean error;
+ /* Get the framebuffer object */
+ fb = get_framebuffer_target(ctx, target);
+ if (!fb) {
+ _mesa_error(ctx, GL_INVALID_ENUM, "%s(invalid target %s)", caller,
+ _mesa_lookup_enum_by_nr(target));
+ return;
+ }
- switch (textarget) {
- case GL_TEXTURE_1D:
- error = GL_FALSE;
- break;
- case GL_TEXTURE_1D_ARRAY:
- error = !ctx->Extensions.EXT_texture_array;
- break;
- default:
- error = GL_TRUE;
- }
+ /* Get the texture object */
+ if (!get_texture_for_framebuffer(ctx, texture, false, caller, &texObj))
+ return;
- if (error) {
- _mesa_error(ctx, GL_INVALID_OPERATION,
- "glFramebufferTexture1D(textarget=%s)",
- _mesa_lookup_enum_by_nr(textarget));
+ if (texObj) {
+ if (!check_textarget(ctx, dims, texObj->Target, textarget, caller))
+ return;
+
+ if ((dims == 3) && !check_layer(ctx, texObj->Target, layer, caller))
return;
- }
}
- framebuffer_texture(ctx, "1D", target, attachment, textarget, texture,
- level, 0, GL_FALSE);
+ if (!check_level(ctx, textarget, level, caller))
+ return;
+
+ _mesa_framebuffer_texture(ctx, fb, attachment, texObj, textarget, level,
+ layer, GL_FALSE, caller);
+}
+
+
+void GLAPIENTRY
+_mesa_FramebufferTexture1D(GLenum target, GLenum attachment,
+ GLenum textarget, GLuint texture, GLint level)
+{
+ framebuffer_texture_with_dims(1, target, attachment, textarget, texture,
+ level, 0, "glFramebufferTexture1D");
}
@@ -2729,79 +3059,112 @@ void GLAPIENTRY
_mesa_FramebufferTexture2D(GLenum target, GLenum attachment,
GLenum textarget, GLuint texture, GLint level)
{
+ framebuffer_texture_with_dims(2, target, attachment, textarget, texture,
+ level, 0, "glFramebufferTexture2D");
+}
+
+
+void GLAPIENTRY
+_mesa_FramebufferTexture3D(GLenum target, GLenum attachment,
+ GLenum textarget, GLuint texture,
+ GLint level, GLint layer)
+{
+ framebuffer_texture_with_dims(3, target, attachment, textarget, texture,
+ level, layer, "glFramebufferTexture3D");
+}
+
+
+void GLAPIENTRY
+_mesa_FramebufferTextureLayer(GLenum target, GLenum attachment,
+ GLuint texture, GLint level, GLint layer)
+{
GET_CURRENT_CONTEXT(ctx);
+ struct gl_framebuffer *fb;
+ struct gl_texture_object *texObj;
+ GLenum textarget = 0;
- if (texture != 0) {
- GLboolean error;
+ const char *func = "glFramebufferTextureLayer";
- switch (textarget) {
- case GL_TEXTURE_2D:
- error = GL_FALSE;
- break;
- case GL_TEXTURE_RECTANGLE:
- error = _mesa_is_gles(ctx)
- || !ctx->Extensions.NV_texture_rectangle;
- break;
- case GL_TEXTURE_CUBE_MAP_POSITIVE_X:
- case GL_TEXTURE_CUBE_MAP_NEGATIVE_X:
- case GL_TEXTURE_CUBE_MAP_POSITIVE_Y:
- case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y:
- case GL_TEXTURE_CUBE_MAP_POSITIVE_Z:
- case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z:
- error = !ctx->Extensions.ARB_texture_cube_map;
- break;
- case GL_TEXTURE_2D_ARRAY:
- error = (_mesa_is_gles(ctx) && ctx->Version < 30)
- || !ctx->Extensions.EXT_texture_array;
- break;
- case GL_TEXTURE_2D_MULTISAMPLE:
- case GL_TEXTURE_2D_MULTISAMPLE_ARRAY:
- error = _mesa_is_gles(ctx)
- || !ctx->Extensions.ARB_texture_multisample;
- break;
- default:
- error = GL_TRUE;
- }
+ /* Get the framebuffer object */
+ fb = get_framebuffer_target(ctx, target);
+ if (!fb) {
+ _mesa_error(ctx, GL_INVALID_ENUM,
+ "glFramebufferTextureLayer(invalid target %s)",
+ _mesa_lookup_enum_by_nr(target));
+ return;
+ }
- if (error) {
- _mesa_error(ctx, GL_INVALID_OPERATION,
- "glFramebufferTexture2D(textarget=%s)",
- _mesa_lookup_enum_by_nr(textarget));
+ /* Get the texture object */
+ if (!get_texture_for_framebuffer(ctx, texture, false, func, &texObj))
+ return;
+
+ if (texObj) {
+ if (!check_texture_target(ctx, texObj->Target, func))
+ return;
+
+ if (!check_layer(ctx, texObj->Target, layer, func))
return;
+
+ if (!check_level(ctx, texObj->Target, level, func))
+ return;
+
+ if (texObj->Target == GL_TEXTURE_CUBE_MAP) {
+ assert(layer >= 0 && layer < 6);
+ textarget = GL_TEXTURE_CUBE_MAP_POSITIVE_X + layer;
+ layer = 0;
}
}
- framebuffer_texture(ctx, "2D", target, attachment, textarget, texture,
- level, 0, GL_FALSE);
+ _mesa_framebuffer_texture(ctx, fb, attachment, texObj, textarget, level,
+ layer, GL_FALSE, func);
}
void GLAPIENTRY
-_mesa_FramebufferTexture3D(GLenum target, GLenum attachment,
- GLenum textarget, GLuint texture,
- GLint level, GLint zoffset)
+_mesa_NamedFramebufferTextureLayer(GLuint framebuffer, GLenum attachment,
+ GLuint texture, GLint level, GLint layer)
{
GET_CURRENT_CONTEXT(ctx);
+ struct gl_framebuffer *fb;
+ struct gl_texture_object *texObj;
+ GLenum textarget = 0;
+
+ const char *func = "glNamedFramebufferTextureLayer";
- if ((texture != 0) && (textarget != GL_TEXTURE_3D)) {
+ if (!ctx->Extensions.ARB_direct_state_access) {
_mesa_error(ctx, GL_INVALID_OPERATION,
- "glFramebufferTexture3D(textarget)");
+ "%s(GL_ARB_direct_state_access is not supported)", func);
return;
}
- framebuffer_texture(ctx, "3D", target, attachment, textarget, texture,
- level, zoffset, GL_FALSE);
-}
+ /* Get the framebuffer object */
+ fb = _mesa_lookup_framebuffer_err(ctx, framebuffer, func);
+ if (!fb)
+ return;
+ /* Get the texture object */
+ if (!get_texture_for_framebuffer(ctx, texture, false, func, &texObj))
+ return;
-void GLAPIENTRY
-_mesa_FramebufferTextureLayer(GLenum target, GLenum attachment,
- GLuint texture, GLint level, GLint layer)
-{
- GET_CURRENT_CONTEXT(ctx);
+ if (texObj) {
+ if (!check_texture_target(ctx, texObj->Target, func))
+ return;
+
+ if (!check_layer(ctx, texObj->Target, layer, func))
+ return;
+
+ if (!check_level(ctx, texObj->Target, level, func))
+ return;
- framebuffer_texture(ctx, "Layer", target, attachment, 0, texture,
- level, layer, GL_FALSE);
+ if (texObj->Target == GL_TEXTURE_CUBE_MAP) {
+ assert(layer >= 0 && layer < 6);
+ textarget = GL_TEXTURE_CUBE_MAP_POSITIVE_X + layer;
+ layer = 0;
+ }
+ }
+
+ _mesa_framebuffer_texture(ctx, fb, attachment, texObj, textarget, level,
+ layer, GL_FALSE, func);
}
@@ -2810,82 +3173,121 @@ _mesa_FramebufferTexture(GLenum target, GLenum attachment,
GLuint texture, GLint level)
{
GET_CURRENT_CONTEXT(ctx);
+ struct gl_framebuffer *fb;
+ struct gl_texture_object *texObj;
+ GLboolean layered;
+
+ const char *func = "FramebufferTexture";
- if (_mesa_has_geometry_shaders(ctx)) {
- framebuffer_texture(ctx, "", target, attachment, 0, texture,
- level, 0, GL_TRUE);
- } else {
+ if (!_mesa_has_geometry_shaders(ctx)) {
_mesa_error(ctx, GL_INVALID_OPERATION,
"unsupported function (glFramebufferTexture) called");
+ return;
+ }
+
+ /* Get the framebuffer object */
+ fb = get_framebuffer_target(ctx, target);
+ if (!fb) {
+ _mesa_error(ctx, GL_INVALID_ENUM,
+ "glFramebufferTexture(invalid target %s)",
+ _mesa_lookup_enum_by_nr(target));
+ return;
}
+
+ /* Get the texture object */
+ if (!get_texture_for_framebuffer(ctx, texture, true, func, &texObj))
+ return;
+
+ if (texObj) {
+ if (!check_layered_texture_target(ctx, texObj->Target, func, &layered))
+ return;
+
+ if (!check_level(ctx, texObj->Target, level, func))
+ return;
+ }
+
+ _mesa_framebuffer_texture(ctx, fb, attachment, texObj, 0, level,
+ 0, layered, func);
}
void GLAPIENTRY
-_mesa_FramebufferRenderbuffer(GLenum target, GLenum attachment,
- GLenum renderbufferTarget,
- GLuint renderbuffer)
+_mesa_NamedFramebufferTexture(GLuint framebuffer, GLenum attachment,
+ GLuint texture, GLint level)
{
- struct gl_renderbuffer_attachment *att;
- struct gl_framebuffer *fb;
- struct gl_renderbuffer *rb;
GET_CURRENT_CONTEXT(ctx);
+ struct gl_framebuffer *fb;
+ struct gl_texture_object *texObj;
+ GLboolean layered;
- fb = get_framebuffer_target(ctx, target);
- if (!fb) {
- _mesa_error(ctx, GL_INVALID_ENUM,
- "glFramebufferRenderbuffer(target)");
+ const char *func = "glNamedFramebufferTexture";
+
+ if (!ctx->Extensions.ARB_direct_state_access) {
+ _mesa_error(ctx, GL_INVALID_OPERATION,
+ "%s(GL_ARB_direct_state_access is not supported)", func);
return;
}
- if (renderbufferTarget != GL_RENDERBUFFER_EXT) {
- _mesa_error(ctx, GL_INVALID_ENUM,
- "glFramebufferRenderbuffer(renderbufferTarget)");
+ if (!_mesa_has_geometry_shaders(ctx)) {
+ _mesa_error(ctx, GL_INVALID_OPERATION,
+ "unsupported function (glNamedFramebufferTexture) called");
return;
}
+ /* Get the framebuffer object */
+ fb = _mesa_lookup_framebuffer_err(ctx, framebuffer, func);
+ if (!fb)
+ return;
+
+ /* Get the texture object */
+ if (!get_texture_for_framebuffer(ctx, texture, true, func, &texObj))
+ return;
+
+ if (texObj) {
+ if (!check_layered_texture_target(ctx, texObj->Target, func,
+ &layered))
+ return;
+
+ if (!check_level(ctx, texObj->Target, level, func))
+ return;
+ }
+
+ _mesa_framebuffer_texture(ctx, fb, attachment, texObj, 0, level,
+ 0, layered, func);
+}
+
+
+void
+_mesa_framebuffer_renderbuffer(struct gl_context *ctx,
+ struct gl_framebuffer *fb,
+ GLenum attachment,
+ struct gl_renderbuffer *rb,
+ const char *func)
+{
+ struct gl_renderbuffer_attachment *att;
+
if (_mesa_is_winsys_fbo(fb)) {
/* Can't attach new renderbuffers to a window system framebuffer */
- _mesa_error(ctx, GL_INVALID_OPERATION, "glFramebufferRenderbuffer");
+ _mesa_error(ctx, GL_INVALID_OPERATION,
+ "%s(window-system framebuffer)", func);
return;
}
att = get_attachment(ctx, fb, attachment);
if (att == NULL) {
_mesa_error(ctx, GL_INVALID_ENUM,
- "glFramebufferRenderbuffer(invalid attachment %s)",
+ "%s(invalid attachment %s)", func,
_mesa_lookup_enum_by_nr(attachment));
return;
}
- if (renderbuffer) {
- rb = _mesa_lookup_renderbuffer(ctx, renderbuffer);
- if (!rb) {
- _mesa_error(ctx, GL_INVALID_OPERATION,
- "glFramebufferRenderbuffer(non-existant"
- " renderbuffer %u)", renderbuffer);
- return;
- }
- else if (rb == &DummyRenderbuffer) {
- _mesa_error(ctx, GL_INVALID_OPERATION,
- "glFramebufferRenderbuffer(renderbuffer %u)",
- renderbuffer);
- return;
- }
- }
- else {
- /* remove renderbuffer attachment */
- rb = NULL;
- }
-
if (attachment == GL_DEPTH_STENCIL_ATTACHMENT &&
rb && rb->Format != MESA_FORMAT_NONE) {
/* make sure the renderbuffer is a depth/stencil format */
const GLenum baseFormat = _mesa_get_format_base_format(rb->Format);
if (baseFormat != GL_DEPTH_STENCIL) {
_mesa_error(ctx, GL_INVALID_OPERATION,
- "glFramebufferRenderbuffer(renderbuffer"
- " is not DEPTH_STENCIL format)");
+ "%s(renderbuffer is not DEPTH_STENCIL format)", func);
return;
}
}
@@ -2903,24 +3305,99 @@ _mesa_FramebufferRenderbuffer(GLenum target, GLenum attachment,
void GLAPIENTRY
-_mesa_GetFramebufferAttachmentParameteriv(GLenum target, GLenum attachment,
- GLenum pname, GLint *params)
+_mesa_FramebufferRenderbuffer(GLenum target, GLenum attachment,
+ GLenum renderbuffertarget,
+ GLuint renderbuffer)
{
- const struct gl_renderbuffer_attachment *att;
- struct gl_framebuffer *buffer;
- GLenum err;
+ struct gl_framebuffer *fb;
+ struct gl_renderbuffer *rb;
GET_CURRENT_CONTEXT(ctx);
- /* The error differs in GL and GLES. */
- err = _mesa_is_desktop_gl(ctx) ? GL_INVALID_OPERATION : GL_INVALID_ENUM;
+ fb = get_framebuffer_target(ctx, target);
+ if (!fb) {
+ _mesa_error(ctx, GL_INVALID_ENUM,
+ "glFramebufferRenderbuffer(invalid target %s)",
+ _mesa_lookup_enum_by_nr(target));
+ return;
+ }
- buffer = get_framebuffer_target(ctx, target);
- if (!buffer) {
+ if (renderbuffertarget != GL_RENDERBUFFER) {
_mesa_error(ctx, GL_INVALID_ENUM,
- "glGetFramebufferAttachmentParameteriv(target)");
+ "glFramebufferRenderbuffer(renderbuffertarget is not "
+ "GL_RENDERBUFFER)");
return;
}
+ if (renderbuffer) {
+ rb = _mesa_lookup_renderbuffer_err(ctx, renderbuffer,
+ "glFramebufferRenderbuffer");
+ if (!rb)
+ return;
+ }
+ else {
+ /* remove renderbuffer attachment */
+ rb = NULL;
+ }
+
+ _mesa_framebuffer_renderbuffer(ctx, fb, attachment, rb,
+ "glFramebufferRenderbuffer");
+}
+
+
+void GLAPIENTRY
+_mesa_NamedFramebufferRenderbuffer(GLuint framebuffer, GLenum attachment,
+ GLenum renderbuffertarget,
+ GLuint renderbuffer)
+{
+ struct gl_framebuffer *fb;
+ struct gl_renderbuffer *rb;
+ GET_CURRENT_CONTEXT(ctx);
+
+ if (!ctx->Extensions.ARB_direct_state_access) {
+ _mesa_error(ctx, GL_INVALID_OPERATION,
+ "glNamedFramebufferRenderbuffer(GL_ARB_direct_state_access "
+ "is not supported)");
+ return;
+ }
+
+ fb = _mesa_lookup_framebuffer_err(ctx, framebuffer,
+ "glNamedFramebufferRenderbuffer");
+
+ if (renderbuffertarget != GL_RENDERBUFFER) {
+ _mesa_error(ctx, GL_INVALID_ENUM,
+ "glNamedFramebufferRenderbuffer(renderbuffertarget is not "
+ "GL_RENDERBUFFER)");
+ return;
+ }
+
+ if (renderbuffer) {
+ rb = _mesa_lookup_renderbuffer_err(ctx, renderbuffer,
+ "glNamedFramebufferRenderbuffer");
+ if (!rb)
+ return;
+ }
+ else {
+ /* remove renderbuffer attachment */
+ rb = NULL;
+ }
+
+ _mesa_framebuffer_renderbuffer(ctx, fb, attachment, rb,
+ "glNamedFramebufferRenderbuffer");
+}
+
+
+void
+_mesa_get_framebuffer_attachment_parameter(struct gl_context *ctx,
+ struct gl_framebuffer *buffer,
+ GLenum attachment, GLenum pname,
+ GLint *params, const char *caller)
+{
+ const struct gl_renderbuffer_attachment *att;
+ GLenum err;
+
+ /* The error differs in GL and GLES. */
+ err = _mesa_is_desktop_gl(ctx) ? GL_INVALID_OPERATION : GL_INVALID_ENUM;
+
if (_mesa_is_winsys_fbo(buffer)) {
/* Page 126 (page 136 of the PDF) of the OpenGL ES 2.0.25 spec
* says:
@@ -2936,14 +3413,15 @@ _mesa_GetFramebufferAttachmentParameteriv(GLenum target, GLenum attachment,
!ctx->Extensions.ARB_framebuffer_object)
&& !_mesa_is_gles3(ctx)) {
_mesa_error(ctx, GL_INVALID_OPERATION,
- "glGetFramebufferAttachmentParameteriv(bound FBO = 0)");
+ "%s(window-system framebuffer)", caller);
return;
}
if (_mesa_is_gles3(ctx) && attachment != GL_BACK &&
attachment != GL_DEPTH && attachment != GL_STENCIL) {
_mesa_error(ctx, GL_INVALID_ENUM,
- "glGetFramebufferAttachmentParameteriv(attachment)");
+ "%s(invalid attachment %s)", caller,
+ _mesa_lookup_enum_by_nr(attachment));
return;
}
/* the default / window-system FBO */
@@ -2955,8 +3433,8 @@ _mesa_GetFramebufferAttachmentParameteriv(GLenum target, GLenum attachment,
}
if (att == NULL) {
- _mesa_error(ctx, GL_INVALID_ENUM,
- "glGetFramebufferAttachmentParameteriv(attachment)");
+ _mesa_error(ctx, GL_INVALID_ENUM, "%s(invalid attachment %s)", caller,
+ _mesa_lookup_enum_by_nr(attachment));
return;
}
@@ -2970,9 +3448,8 @@ _mesa_GetFramebufferAttachmentParameteriv(GLenum target, GLenum attachment,
* attachment, since it does not have a single format."
*/
_mesa_error(ctx, GL_INVALID_OPERATION,
- "glGetFramebufferAttachmentParameteriv("
- "GL_FRAMEBUFFER_ATTACHMENT_COMPONENT_TYPE"
- " is invalid for depth+stencil attachment)");
+ "%s(GL_FRAMEBUFFER_ATTACHMENT_COMPONENT_TYPE"
+ " is invalid for depth+stencil attachment)", caller);
return;
}
/* the depth and stencil attachments must point to the same buffer */
@@ -2980,8 +3457,7 @@ _mesa_GetFramebufferAttachmentParameteriv(GLenum target, GLenum attachment,
stencilAtt = get_attachment(ctx, buffer, GL_STENCIL_ATTACHMENT);
if (depthAtt->Renderbuffer != stencilAtt->Renderbuffer) {
_mesa_error(ctx, GL_INVALID_OPERATION,
- "glGetFramebufferAttachmentParameteriv(DEPTH/STENCIL"
- " attachments differ)");
+ "%s(DEPTH/STENCIL attachments differ)", caller);
return;
}
}
@@ -3014,8 +3490,8 @@ _mesa_GetFramebufferAttachmentParameteriv(GLenum target, GLenum attachment,
*params = att->TextureLevel;
}
else if (att->Type == GL_NONE) {
- _mesa_error(ctx, err,
- "glGetFramebufferAttachmentParameteriv(pname)");
+ _mesa_error(ctx, err, "%s(invalid pname %s)", caller,
+ _mesa_lookup_enum_by_nr(pname));
}
else {
goto invalid_pname_enum;
@@ -3031,8 +3507,8 @@ _mesa_GetFramebufferAttachmentParameteriv(GLenum target, GLenum attachment,
}
}
else if (att->Type == GL_NONE) {
- _mesa_error(ctx, err,
- "glGetFramebufferAttachmentParameteriv(pname)");
+ _mesa_error(ctx, err, "%s(invalid pname %s)", caller,
+ _mesa_lookup_enum_by_nr(pname));
}
else {
goto invalid_pname_enum;
@@ -3042,8 +3518,8 @@ _mesa_GetFramebufferAttachmentParameteriv(GLenum target, GLenum attachment,
if (ctx->API == API_OPENGLES) {
goto invalid_pname_enum;
} else if (att->Type == GL_NONE) {
- _mesa_error(ctx, err,
- "glGetFramebufferAttachmentParameteriv(pname)");
+ _mesa_error(ctx, err, "%s(invalid pname %s)", caller,
+ _mesa_lookup_enum_by_nr(pname));
} else if (att->Type == GL_TEXTURE) {
if (att->Texture && (att->Texture->Target == GL_TEXTURE_3D ||
att->Texture->Target == GL_TEXTURE_2D_ARRAY)) {
@@ -3064,8 +3540,8 @@ _mesa_GetFramebufferAttachmentParameteriv(GLenum target, GLenum attachment,
goto invalid_pname_enum;
}
else if (att->Type == GL_NONE) {
- _mesa_error(ctx, err,
- "glGetFramebufferAttachmentParameteriv(pname)");
+ _mesa_error(ctx, err, "%s(invalid pname %s)", caller,
+ _mesa_lookup_enum_by_nr(pname));
}
else {
if (ctx->Extensions.EXT_framebuffer_sRGB) {
@@ -3087,8 +3563,8 @@ _mesa_GetFramebufferAttachmentParameteriv(GLenum target, GLenum attachment,
goto invalid_pname_enum;
}
else if (att->Type == GL_NONE) {
- _mesa_error(ctx, err,
- "glGetFramebufferAttachmentParameteriv(pname)");
+ _mesa_error(ctx, err, "%s(invalid pname %s)", caller,
+ _mesa_lookup_enum_by_nr(pname));
}
else {
mesa_format format = att->Renderbuffer->Format;
@@ -3103,9 +3579,9 @@ _mesa_GetFramebufferAttachmentParameteriv(GLenum target, GLenum attachment,
if (_mesa_is_gles3(ctx) &&
attachment == GL_DEPTH_STENCIL_ATTACHMENT) {
_mesa_error(ctx, GL_INVALID_OPERATION,
- "glGetFramebufferAttachmentParameteriv(cannot query "
+ "%s(cannot query "
"GL_FRAMEBUFFER_ATTACHMENT_COMPONENT_TYPE of "
- "GL_DEPTH_STENCIL_ATTACHMENT");
+ "GL_DEPTH_STENCIL_ATTACHMENT)", caller);
return;
}
@@ -3139,8 +3615,8 @@ _mesa_GetFramebufferAttachmentParameteriv(GLenum target, GLenum attachment,
goto invalid_pname_enum;
}
else if (att->Type == GL_NONE) {
- _mesa_error(ctx, err,
- "glGetFramebufferAttachmentParameteriv(pname)");
+ _mesa_error(ctx, err, "%s(invalid pname %s)", caller,
+ _mesa_lookup_enum_by_nr(pname));
}
else if (att->Texture) {
const struct gl_texture_image *texImage =
@@ -3159,8 +3635,7 @@ _mesa_GetFramebufferAttachmentParameteriv(GLenum target, GLenum attachment,
att->Renderbuffer->Format);
}
else {
- _mesa_problem(ctx, "glGetFramebufferAttachmentParameterivEXT:"
- " invalid FBO attachment structure");
+ _mesa_problem(ctx, "%s: invalid FBO attachment structure", caller);
}
return;
case GL_FRAMEBUFFER_ATTACHMENT_LAYERED:
@@ -3169,8 +3644,8 @@ _mesa_GetFramebufferAttachmentParameteriv(GLenum target, GLenum attachment,
} else if (att->Type == GL_TEXTURE) {
*params = att->Layered;
} else if (att->Type == GL_NONE) {
- _mesa_error(ctx, err,
- "glGetFramebufferAttachmentParameteriv(pname)");
+ _mesa_error(ctx, err, "%s(invalid pname %s)", caller,
+ _mesa_lookup_enum_by_nr(pname));
} else {
goto invalid_pname_enum;
}
@@ -3182,30 +3657,145 @@ _mesa_GetFramebufferAttachmentParameteriv(GLenum target, GLenum attachment,
return;
invalid_pname_enum:
- _mesa_error(ctx, GL_INVALID_ENUM,
- "glGetFramebufferAttachmentParameteriv(pname)");
+ _mesa_error(ctx, GL_INVALID_ENUM, "%s(invalid pname %s)", caller,
+ _mesa_lookup_enum_by_nr(pname));
return;
}
+void GLAPIENTRY
+_mesa_GetFramebufferAttachmentParameteriv(GLenum target, GLenum attachment,
+ GLenum pname, GLint *params)
+{
+ GET_CURRENT_CONTEXT(ctx);
+ struct gl_framebuffer *buffer;
+
+ buffer = get_framebuffer_target(ctx, target);
+ if (!buffer) {
+ _mesa_error(ctx, GL_INVALID_ENUM,
+ "glGetFramebufferAttachmentParameteriv(invalid target %s)",
+ _mesa_lookup_enum_by_nr(target));
+ return;
+ }
+
+ _mesa_get_framebuffer_attachment_parameter(ctx, buffer, attachment, pname,
+ params,
+ "glGetFramebufferAttachmentParameteriv");
+}
+
+
+void GLAPIENTRY
+_mesa_GetNamedFramebufferAttachmentParameteriv(GLuint framebuffer,
+ GLenum attachment,
+ GLenum pname, GLint *params)
+{
+ GET_CURRENT_CONTEXT(ctx);
+ struct gl_framebuffer *buffer;
+
+ if (!ctx->Extensions.ARB_direct_state_access) {
+ _mesa_error(ctx, GL_INVALID_OPERATION,
+ "glGetNamedFramebufferAttachmentParameteriv("
+ "GL_ARB_direct_state_access is not supported)");
+ return;
+ }
+
+ if (framebuffer) {
+ buffer = _mesa_lookup_framebuffer_err(ctx, framebuffer,
+ "glGetNamedFramebufferAttachmentParameteriv");
+ if (!buffer)
+ return;
+ }
+ else {
+ /*
+ * Section 9.2 Binding and Managing Framebuffer Objects of the OpenGL
+ * 4.5 core spec (30.10.2014, PDF page 314):
+ * "If framebuffer is zero, then the default draw framebuffer is
+ * queried."
+ */
+ buffer = ctx->WinSysDrawBuffer;
+ }
+
+ _mesa_get_framebuffer_attachment_parameter(ctx, buffer, attachment, pname,
+ params,
+ "glGetNamedFramebufferAttachmentParameteriv");
+}
+
+
+void GLAPIENTRY
+_mesa_NamedFramebufferParameteri(GLuint framebuffer, GLenum pname,
+ GLint param)
+{
+ GET_CURRENT_CONTEXT(ctx);
+
+ (void) framebuffer;
+ (void) pname;
+ (void) param;
+
+ if (!ctx->Extensions.ARB_direct_state_access) {
+ _mesa_error(ctx, GL_INVALID_OPERATION,
+ "glNamedFramebufferParameteri("
+ "GL_ARB_direct_state_access is not supported)");
+ return;
+ }
+
+ _mesa_error(ctx, GL_INVALID_OPERATION,
+ "glNamedFramebufferParameteri not supported "
+ "(ARB_framebuffer_no_attachments not implemented)");
+}
+
+
+void GLAPIENTRY
+_mesa_GetNamedFramebufferParameteriv(GLuint framebuffer, GLenum pname,
+ GLint *param)
+{
+ GET_CURRENT_CONTEXT(ctx);
+
+ (void) framebuffer;
+ (void) pname;
+ (void) param;
+
+ if (!ctx->Extensions.ARB_direct_state_access) {
+ _mesa_error(ctx, GL_INVALID_OPERATION,
+ "glNamedFramebufferParameteriv("
+ "GL_ARB_direct_state_access is not supported)");
+ return;
+ }
+
+ _mesa_error(ctx, GL_INVALID_OPERATION,
+ "glGetNamedFramebufferParameteriv not supported "
+ "(ARB_framebuffer_no_attachments not implemented)");
+}
+
+
static void
-invalidate_framebuffer_storage(GLenum target, GLsizei numAttachments,
+invalidate_framebuffer_storage(struct gl_context *ctx,
+ struct gl_framebuffer *fb,
+ GLsizei numAttachments,
const GLenum *attachments, GLint x, GLint y,
GLsizei width, GLsizei height, const char *name)
{
int i;
- struct gl_framebuffer *fb;
- GET_CURRENT_CONTEXT(ctx);
- fb = get_framebuffer_target(ctx, target);
- if (!fb) {
- _mesa_error(ctx, GL_INVALID_ENUM, "%s(target)", name);
+ /* Section 17.4 Whole Framebuffer Operations of the OpenGL 4.5 Core
+ * Spec (2.2.2015, PDF page 522) says:
+ * "An INVALID_VALUE error is generated if numAttachments, width, or
+ * height is negative."
+ */
+ if (numAttachments < 0) {
+ _mesa_error(ctx, GL_INVALID_VALUE,
+ "%s(numAttachments < 0)", name);
return;
}
- if (numAttachments < 0) {
+ if (width < 0) {
_mesa_error(ctx, GL_INVALID_VALUE,
- "%s(numAttachments < 0)", name);
+ "%s(width < 0)", name);
+ return;
+ }
+
+ if (height < 0) {
+ _mesa_error(ctx, GL_INVALID_VALUE,
+ "%s(height < 0)", name);
return;
}
@@ -3301,7 +3891,8 @@ invalidate_framebuffer_storage(GLenum target, GLsizei numAttachments,
return;
invalid_enum:
- _mesa_error(ctx, GL_INVALID_ENUM, "%s(attachment)", name);
+ _mesa_error(ctx, GL_INVALID_ENUM, "%s(invalid attachment %s)", name,
+ _mesa_lookup_enum_by_nr(attachments[i]));
return;
}
@@ -3311,16 +3902,74 @@ _mesa_InvalidateSubFramebuffer(GLenum target, GLsizei numAttachments,
const GLenum *attachments, GLint x, GLint y,
GLsizei width, GLsizei height)
{
- invalidate_framebuffer_storage(target, numAttachments, attachments,
+ struct gl_framebuffer *fb;
+ GET_CURRENT_CONTEXT(ctx);
+
+ fb = get_framebuffer_target(ctx, target);
+ if (!fb) {
+ _mesa_error(ctx, GL_INVALID_ENUM,
+ "glInvalidateSubFramebuffer(invalid target %s)",
+ _mesa_lookup_enum_by_nr(target));
+ return;
+ }
+
+ invalidate_framebuffer_storage(ctx, fb, numAttachments, attachments,
x, y, width, height,
"glInvalidateSubFramebuffer");
}
void GLAPIENTRY
+_mesa_InvalidateNamedFramebufferSubData(GLuint framebuffer,
+ GLsizei numAttachments,
+ const GLenum *attachments,
+ GLint x, GLint y,
+ GLsizei width, GLsizei height)
+{
+ struct gl_framebuffer *fb;
+ GET_CURRENT_CONTEXT(ctx);
+
+ if (!ctx->Extensions.ARB_direct_state_access) {
+ _mesa_error(ctx, GL_INVALID_OPERATION,
+ "glInvalidateNamedFramebufferSubData("
+ "GL_ARB_direct_state_access is not supported)");
+ return;
+ }
+
+ /* The OpenGL 4.5 core spec (02.02.2015) says (in Section 17.4 Whole
+ * Framebuffer Operations, PDF page 522): "If framebuffer is zero, the
+ * default draw framebuffer is affected."
+ */
+ if (framebuffer) {
+ fb = _mesa_lookup_framebuffer_err(ctx, framebuffer,
+ "glInvalidateNamedFramebufferSubData");
+ if (!fb)
+ return;
+ }
+ else
+ fb = ctx->WinSysDrawBuffer;
+
+ invalidate_framebuffer_storage(ctx, fb, numAttachments, attachments,
+ x, y, width, height,
+ "glInvalidateNamedFramebufferSubData");
+}
+
+
+void GLAPIENTRY
_mesa_InvalidateFramebuffer(GLenum target, GLsizei numAttachments,
const GLenum *attachments)
{
+ struct gl_framebuffer *fb;
+ GET_CURRENT_CONTEXT(ctx);
+
+ fb = get_framebuffer_target(ctx, target);
+ if (!fb) {
+ _mesa_error(ctx, GL_INVALID_ENUM,
+ "glInvalidateFramebuffer(invalid target %s)",
+ _mesa_lookup_enum_by_nr(target));
+ return;
+ }
+
/* The GL_ARB_invalidate_subdata spec says:
*
* "The command
@@ -3333,7 +3982,7 @@ _mesa_InvalidateFramebuffer(GLenum target, GLsizei numAttachments,
* <width>, <height> equal to 0, 0, <MAX_VIEWPORT_DIMS[0]>,
* <MAX_VIEWPORT_DIMS[1]> respectively."
*/
- invalidate_framebuffer_storage(target, numAttachments, attachments,
+ invalidate_framebuffer_storage(ctx, fb, numAttachments, attachments,
0, 0,
MAX_VIEWPORT_WIDTH, MAX_VIEWPORT_HEIGHT,
"glInvalidateFramebuffer");
@@ -3341,6 +3990,53 @@ _mesa_InvalidateFramebuffer(GLenum target, GLsizei numAttachments,
void GLAPIENTRY
+_mesa_InvalidateNamedFramebufferData(GLuint framebuffer,
+ GLsizei numAttachments,
+ const GLenum *attachments)
+{
+ struct gl_framebuffer *fb;
+ GET_CURRENT_CONTEXT(ctx);
+
+ if (!ctx->Extensions.ARB_direct_state_access) {
+ _mesa_error(ctx, GL_INVALID_OPERATION,
+ "glInvalidateNamedFramebufferData("
+ "GL_ARB_direct_state_access is not supported)");
+ return;
+ }
+
+ /* The OpenGL 4.5 core spec (02.02.2015) says (in Section 17.4 Whole
+ * Framebuffer Operations, PDF page 522): "If framebuffer is zero, the
+ * default draw framebuffer is affected."
+ */
+ if (framebuffer) {
+ fb = _mesa_lookup_framebuffer_err(ctx, framebuffer,
+ "glInvalidateNamedFramebufferData");
+ if (!fb)
+ return;
+ }
+ else
+ fb = ctx->WinSysDrawBuffer;
+
+ /* The GL_ARB_invalidate_subdata spec says:
+ *
+ * "The command
+ *
+ * void InvalidateFramebuffer(enum target,
+ * sizei numAttachments,
+ * const enum *attachments);
+ *
+ * is equivalent to the command InvalidateSubFramebuffer with <x>, <y>,
+ * <width>, <height> equal to 0, 0, <MAX_VIEWPORT_DIMS[0]>,
+ * <MAX_VIEWPORT_DIMS[1]> respectively."
+ */
+ invalidate_framebuffer_storage(ctx, fb, numAttachments, attachments,
+ 0, 0,
+ MAX_VIEWPORT_WIDTH, MAX_VIEWPORT_HEIGHT,
+ "glInvalidateNamedFramebufferData");
+}
+
+
+void GLAPIENTRY
_mesa_DiscardFramebufferEXT(GLenum target, GLsizei numAttachments,
const GLenum *attachments)
{
diff --git a/mesalib/src/mesa/main/fbobject.h b/mesalib/src/mesa/main/fbobject.h
index 61aa1f503..9f570db3a 100644
--- a/mesalib/src/mesa/main/fbobject.h
+++ b/mesalib/src/mesa/main/fbobject.h
@@ -64,9 +64,17 @@ _mesa_get_incomplete_framebuffer(void);
extern struct gl_renderbuffer *
_mesa_lookup_renderbuffer(struct gl_context *ctx, GLuint id);
+extern struct gl_renderbuffer *
+_mesa_lookup_renderbuffer_err(struct gl_context *ctx, GLuint id,
+ const char *func);
+
extern struct gl_framebuffer *
_mesa_lookup_framebuffer(struct gl_context *ctx, GLuint id);
+extern struct gl_framebuffer *
+_mesa_lookup_framebuffer_err(struct gl_context *ctx, GLuint id,
+ const char *func);
+
void
_mesa_update_texture_renderbuffer(struct gl_context *ctx,
@@ -74,9 +82,17 @@ _mesa_update_texture_renderbuffer(struct gl_context *ctx,
struct gl_renderbuffer_attachment *att);
extern void
+_mesa_FramebufferRenderbuffer_sw(struct gl_context *ctx,
+ struct gl_framebuffer *fb,
+ GLenum attachment,
+ struct gl_renderbuffer *rb);
+
+extern void
_mesa_framebuffer_renderbuffer(struct gl_context *ctx,
struct gl_framebuffer *fb,
- GLenum attachment, struct gl_renderbuffer *rb);
+ GLenum attachment,
+ struct gl_renderbuffer *rb,
+ const char *func);
extern void
_mesa_validate_framebuffer(struct gl_context *ctx, struct gl_framebuffer *fb);
@@ -99,6 +115,24 @@ _mesa_detach_renderbuffer(struct gl_context *ctx,
struct gl_framebuffer *fb,
const void *att);
+extern void
+_mesa_framebuffer_texture(struct gl_context *ctx, struct gl_framebuffer *fb,
+ GLenum attachment,
+ struct gl_texture_object *texObj, GLenum textarget,
+ GLint level, GLuint layer, GLboolean layered,
+ const char *caller);
+
+extern GLenum
+_mesa_check_framebuffer_status(struct gl_context *ctx,
+ struct gl_framebuffer *fb);
+
+extern void
+_mesa_get_framebuffer_attachment_parameter(struct gl_context *ctx,
+ struct gl_framebuffer *buffer,
+ GLenum attachment, GLenum pname,
+ GLint *params, const char *caller);
+
+
extern GLboolean GLAPIENTRY
_mesa_IsRenderbuffer(GLuint renderbuffer);
@@ -165,9 +199,15 @@ _mesa_DeleteFramebuffers(GLsizei n, const GLuint *framebuffers);
extern void GLAPIENTRY
_mesa_GenFramebuffers(GLsizei n, GLuint *framebuffers);
+extern void GLAPIENTRY
+_mesa_CreateFramebuffers(GLsizei n, GLuint *framebuffers);
+
extern GLenum GLAPIENTRY
_mesa_CheckFramebufferStatus(GLenum target);
+extern GLenum GLAPIENTRY
+_mesa_CheckNamedFramebufferStatus(GLuint framebuffer, GLenum target);
+
extern void GLAPIENTRY
_mesa_FramebufferTexture1D(GLenum target, GLenum attachment,
GLenum textarget, GLuint texture, GLint level);
@@ -179,24 +219,49 @@ _mesa_FramebufferTexture2D(GLenum target, GLenum attachment,
extern void GLAPIENTRY
_mesa_FramebufferTexture3D(GLenum target, GLenum attachment,
GLenum textarget, GLuint texture,
- GLint level, GLint zoffset);
+ GLint level, GLint layer);
extern void GLAPIENTRY
_mesa_FramebufferTextureLayer(GLenum target, GLenum attachment,
GLuint texture, GLint level, GLint layer);
extern void GLAPIENTRY
+_mesa_NamedFramebufferTextureLayer(GLuint framebuffer, GLenum attachment,
+ GLuint texture, GLint level, GLint layer);
+
+extern void GLAPIENTRY
_mesa_FramebufferTexture(GLenum target, GLenum attachment,
GLuint texture, GLint level);
extern void GLAPIENTRY
+_mesa_NamedFramebufferTexture(GLuint framebuffer, GLenum attachment,
+ GLuint texture, GLint level);
+
+extern void GLAPIENTRY
_mesa_FramebufferRenderbuffer(GLenum target, GLenum attachment,
GLenum renderbuffertarget,
GLuint renderbuffer);
extern void GLAPIENTRY
+_mesa_NamedFramebufferRenderbuffer(GLuint framebuffer, GLenum attachment,
+ GLenum renderbuffertarget,
+ GLuint renderbuffer);
+
+extern void GLAPIENTRY
_mesa_GetFramebufferAttachmentParameteriv(GLenum target, GLenum attachment,
GLenum pname, GLint *params);
+extern void GLAPIENTRY
+_mesa_GetNamedFramebufferAttachmentParameteriv(GLuint framebuffer,
+ GLenum attachment,
+ GLenum pname, GLint *params);
+
+extern void GLAPIENTRY
+_mesa_NamedFramebufferParameteri(GLuint framebuffer, GLenum pname,
+ GLint param);
+
+extern void GLAPIENTRY
+_mesa_GetNamedFramebufferParameteriv(GLuint framebuffer, GLenum pname,
+ GLint *param);
extern void GLAPIENTRY
_mesa_InvalidateSubFramebuffer(GLenum target, GLsizei numAttachments,
@@ -204,10 +269,22 @@ _mesa_InvalidateSubFramebuffer(GLenum target, GLsizei numAttachments,
GLsizei width, GLsizei height);
extern void GLAPIENTRY
+_mesa_InvalidateNamedFramebufferSubData(GLuint framebuffer,
+ GLsizei numAttachments,
+ const GLenum *attachments,
+ GLint x, GLint y,
+ GLsizei width, GLsizei height);
+
+extern void GLAPIENTRY
_mesa_InvalidateFramebuffer(GLenum target, GLsizei numAttachments,
const GLenum *attachments);
extern void GLAPIENTRY
+_mesa_InvalidateNamedFramebufferData(GLuint framebuffer,
+ GLsizei numAttachments,
+ const GLenum *attachments);
+
+extern void GLAPIENTRY
_mesa_DiscardFramebufferEXT(GLenum target, GLsizei numAttachments,
const GLenum *attachments);
diff --git a/mesalib/src/mesa/main/ffvertex_prog.c b/mesalib/src/mesa/main/ffvertex_prog.c
index 7fdd9bab6..70adaf885 100644
--- a/mesalib/src/mesa/main/ffvertex_prog.c
+++ b/mesalib/src/mesa/main/ffvertex_prog.c
@@ -135,7 +135,7 @@ static GLboolean check_active_shininess( struct gl_context *ctx,
(key->light_color_material_mask & (1 << attr)))
return GL_TRUE;
- if (key->varying_vp_inputs & VERT_ATTRIB_GENERIC(attr))
+ if (key->varying_vp_inputs & VERT_BIT_GENERIC(attr))
return GL_TRUE;
if (ctx->Light.Material.Attrib[attr][0] != 0.0F)
diff --git a/mesalib/src/mesa/main/framebuffer.c b/mesalib/src/mesa/main/framebuffer.c
index 4f7736a64..665a5ba14 100644
--- a/mesalib/src/mesa/main/framebuffer.c
+++ b/mesalib/src/mesa/main/framebuffer.c
@@ -312,7 +312,7 @@ _mesa_resize_framebuffer(struct gl_context *ctx, struct gl_framebuffer *fb,
if (ctx) {
/* update scissor / window bounds */
- _mesa_update_draw_buffer_bounds(ctx);
+ _mesa_update_draw_buffer_bounds(ctx, ctx->DrawBuffer);
/* Signal new buffer state so that swrast will update its clipping
* info (the CLIP_BIT flag).
*/
@@ -413,9 +413,9 @@ _mesa_scissor_bounding_box(const struct gl_context *ctx,
* \param ctx the GL context.
*/
void
-_mesa_update_draw_buffer_bounds(struct gl_context *ctx)
+_mesa_update_draw_buffer_bounds(struct gl_context *ctx,
+ struct gl_framebuffer *buffer)
{
- struct gl_framebuffer *buffer = ctx->DrawBuffer;
int bbox[4];
if (!buffer)
@@ -652,7 +652,7 @@ update_framebuffer(struct gl_context *ctx, struct gl_framebuffer *fb)
* context state (GL_READ_BUFFER too).
*/
if (fb->ColorDrawBuffer[0] != ctx->Color.DrawBuffer[0]) {
- _mesa_drawbuffers(ctx, ctx->Const.MaxDrawBuffers,
+ _mesa_drawbuffers(ctx, fb, ctx->Const.MaxDrawBuffers,
ctx->Color.DrawBuffer, NULL);
}
}
@@ -678,24 +678,21 @@ update_framebuffer(struct gl_context *ctx, struct gl_framebuffer *fb)
/**
- * Update state related to the current draw/read framebuffers.
+ * Update state related to the draw/read framebuffers.
*/
void
-_mesa_update_framebuffer(struct gl_context *ctx)
+_mesa_update_framebuffer(struct gl_context *ctx,
+ struct gl_framebuffer *readFb,
+ struct gl_framebuffer *drawFb)
{
- struct gl_framebuffer *drawFb;
- struct gl_framebuffer *readFb;
-
assert(ctx);
- drawFb = ctx->DrawBuffer;
- readFb = ctx->ReadBuffer;
update_framebuffer(ctx, drawFb);
if (readFb != drawFb)
update_framebuffer(ctx, readFb);
- _mesa_update_clamp_vertex_color(ctx);
- _mesa_update_clamp_fragment_color(ctx);
+ _mesa_update_clamp_vertex_color(ctx, drawFb);
+ _mesa_update_clamp_fragment_color(ctx, drawFb);
}
diff --git a/mesalib/src/mesa/main/framebuffer.h b/mesalib/src/mesa/main/framebuffer.h
index a4274216e..d02b86f20 100644
--- a/mesalib/src/mesa/main/framebuffer.h
+++ b/mesalib/src/mesa/main/framebuffer.h
@@ -77,14 +77,17 @@ _mesa_scissor_bounding_box(const struct gl_context *ctx,
unsigned idx, int *bbox);
extern void
-_mesa_update_draw_buffer_bounds(struct gl_context *ctx);
+_mesa_update_draw_buffer_bounds(struct gl_context *ctx,
+ struct gl_framebuffer *drawFb);
extern void
_mesa_update_framebuffer_visual(struct gl_context *ctx,
struct gl_framebuffer *fb);
extern void
-_mesa_update_framebuffer(struct gl_context *ctx);
+_mesa_update_framebuffer(struct gl_context *ctx,
+ struct gl_framebuffer *readFb,
+ struct gl_framebuffer *drawFb);
extern GLboolean
_mesa_source_buffer_exists(struct gl_context *ctx, GLenum format);
diff --git a/mesalib/src/mesa/main/genmipmap.c b/mesalib/src/mesa/main/genmipmap.c
index 9aef09019..32b9460ad 100644
--- a/mesalib/src/mesa/main/genmipmap.c
+++ b/mesalib/src/mesa/main/genmipmap.c
@@ -158,6 +158,13 @@ _mesa_GenerateTextureMipmap(GLuint texture)
struct gl_texture_object *texObj;
GET_CURRENT_CONTEXT(ctx);
+ if (!ctx->Extensions.ARB_direct_state_access) {
+ _mesa_error(ctx, GL_INVALID_OPERATION,
+ "glGenerateTextureMipmap(GL_ARB_direct_state_access "
+ "is not supported)");
+ return;
+ }
+
texObj = _mesa_lookup_texture_err(ctx, texture, "glGenerateTextureMipmap");
if (!texObj)
return;
diff --git a/mesalib/src/mesa/main/get.c b/mesalib/src/mesa/main/get.c
index a881bc589..8a6c81aff 100644
--- a/mesalib/src/mesa/main/get.c
+++ b/mesalib/src/mesa/main/get.c
@@ -909,13 +909,13 @@ find_custom_value(struct gl_context *ctx, const struct value_desc *d, union valu
break;
case GL_FOG_COLOR:
- if (_mesa_get_clamp_fragment_color(ctx))
+ if (_mesa_get_clamp_fragment_color(ctx, ctx->DrawBuffer))
COPY_4FV(v->value_float_4, ctx->Fog.Color);
else
COPY_4FV(v->value_float_4, ctx->Fog.ColorUnclamped);
break;
case GL_COLOR_CLEAR_VALUE:
- if (_mesa_get_clamp_fragment_color(ctx)) {
+ if (_mesa_get_clamp_fragment_color(ctx, ctx->DrawBuffer)) {
v->value_float_4[0] = CLAMP(ctx->Color.ClearColor.f[0], 0.0F, 1.0F);
v->value_float_4[1] = CLAMP(ctx->Color.ClearColor.f[1], 0.0F, 1.0F);
v->value_float_4[2] = CLAMP(ctx->Color.ClearColor.f[2], 0.0F, 1.0F);
@@ -924,13 +924,13 @@ find_custom_value(struct gl_context *ctx, const struct value_desc *d, union valu
COPY_4FV(v->value_float_4, ctx->Color.ClearColor.f);
break;
case GL_BLEND_COLOR_EXT:
- if (_mesa_get_clamp_fragment_color(ctx))
+ if (_mesa_get_clamp_fragment_color(ctx, ctx->DrawBuffer))
COPY_4FV(v->value_float_4, ctx->Color.BlendColor);
else
COPY_4FV(v->value_float_4, ctx->Color.BlendColorUnclamped);
break;
case GL_ALPHA_TEST_REF:
- if (_mesa_get_clamp_fragment_color(ctx))
+ if (_mesa_get_clamp_fragment_color(ctx, ctx->DrawBuffer))
v->value_float = ctx->Color.AlphaRef;
else
v->value_float = ctx->Color.AlphaRefUnclamped;
@@ -1911,6 +1911,7 @@ find_value_indexed(const char *func, GLenum pname, GLuint index, union value *v)
if (index >= ctx->Const.Program[MESA_SHADER_VERTEX].MaxAttribs)
goto invalid_value;
v->value_int = ctx->Array.VAO->VertexBinding[VERT_ATTRIB_GENERIC(index)].Stride;
+ return TYPE_INT;
/* ARB_shader_image_load_store */
case GL_IMAGE_BINDING_NAME: {
diff --git a/mesalib/src/mesa/main/mtypes.h b/mesalib/src/mesa/main/mtypes.h
index fb4143086..83425176a 100644
--- a/mesalib/src/mesa/main/mtypes.h
+++ b/mesalib/src/mesa/main/mtypes.h
@@ -695,7 +695,8 @@ struct gl_current_attrib
* \note Index and Edgeflag current values are stored as floats in the
* SIX and SEVEN attribute slots.
*/
- GLfloat Attrib[VERT_ATTRIB_MAX][4]; /**< Position, color, texcoords, etc */
+ /* we need double storage for this for vertex attrib 64bit */
+ GLfloat Attrib[VERT_ATTRIB_MAX][4*2]; /**< Position, color, texcoords, etc */
/**
* \name Current raster position attributes (always valid).
@@ -1523,6 +1524,7 @@ struct gl_client_array
GLboolean Enabled; /**< Enabled flag is a boolean */
GLboolean Normalized; /**< GL_ARB_vertex_program */
GLboolean Integer; /**< Integer-valued? */
+ GLboolean Doubles; /**< double precision values are not converted to floats */
GLuint InstanceDivisor; /**< GL_ARB_instanced_arrays */
struct gl_buffer_object *BufferObj;/**< GL_ARB_vertex_buffer_object */
@@ -1553,6 +1555,7 @@ struct gl_vertex_attrib_array
GLboolean Enabled; /**< Whether the array is enabled */
GLboolean Normalized; /**< Fixed-point values are normalized when converted to floats */
GLboolean Integer; /**< Fixed-point values are not converted to floats */
+ GLboolean Doubles; /**< double precision values are not converted to floats */
GLuint _ElementSize; /**< Size of each element in bytes */
GLuint VertexBinding; /**< Vertex buffer binding */
};
@@ -1671,6 +1674,9 @@ struct gl_array_attrib
/** The default vertex array object */
struct gl_vertex_array_object *DefaultVAO;
+ /** The last VAO accessed by a DSA function */
+ struct gl_vertex_array_object *LastLookedUpVAO;
+
/** Array objects (GL_ARB/APPLE_vertex_array_object) */
struct _mesa_HashTable *Objects;
@@ -2090,6 +2096,7 @@ struct gl_program
struct nir_shader *nir;
GLbitfield64 InputsRead; /**< Bitmask of which input regs are read */
+ GLbitfield64 DoubleInputsRead; /**< Bitmask of which input regs are read and are doubles */
GLbitfield64 OutputsWritten; /**< Bitmask of which output regs are written */
GLbitfield SystemValuesRead; /**< Bitmask of SYSTEM_VALUE_x inputs used */
GLbitfield InputFlags[MAX_PROGRAM_INPUTS]; /**< PROG_PARAM_BIT_x flags */
@@ -2499,6 +2506,12 @@ struct gl_shader
GLuint NumImages;
/**
+ * Whether early fragment tests are enabled as defined by
+ * ARB_shader_image_load_store.
+ */
+ bool EarlyFragmentTests;
+
+ /**
* Compute shader state from ARB_compute_shader layout qualifiers.
*/
struct {
@@ -3608,6 +3621,7 @@ struct gl_extensions
GLboolean ARB_depth_clamp;
GLboolean ARB_depth_texture;
GLboolean ARB_derivative_control;
+ GLboolean ARB_direct_state_access;
GLboolean ARB_draw_buffers_blend;
GLboolean ARB_draw_elements_base_vertex;
GLboolean ARB_draw_indirect;
@@ -3672,6 +3686,7 @@ struct gl_extensions
GLboolean ARB_transform_feedback3;
GLboolean ARB_transform_feedback_instanced;
GLboolean ARB_uniform_buffer_object;
+ GLboolean ARB_vertex_attrib_64bit;
GLboolean ARB_vertex_program;
GLboolean ARB_vertex_shader;
GLboolean ARB_vertex_type_10f_11f_11f_rev;
diff --git a/mesalib/src/mesa/main/pipelineobj.c b/mesalib/src/mesa/main/pipelineobj.c
index 0fefa7d56..a33cdd139 100644
--- a/mesalib/src/mesa/main/pipelineobj.c
+++ b/mesalib/src/mesa/main/pipelineobj.c
@@ -553,6 +553,12 @@ _mesa_CreateProgramPipelines(GLsizei n, GLuint *pipelines)
{
GET_CURRENT_CONTEXT(ctx);
+ if (!ctx->Extensions.ARB_direct_state_access) {
+ _mesa_error(ctx, GL_INVALID_OPERATION, "glCreateProgramPipelines("
+ "GL_ARB_direct_state_access is not supported)");
+ return;
+ }
+
create_program_pipelines(ctx, n, pipelines, true);
}
diff --git a/mesalib/src/mesa/main/queryobj.c b/mesalib/src/mesa/main/queryobj.c
index fbccf3fe6..2784b4c05 100644
--- a/mesalib/src/mesa/main/queryobj.c
+++ b/mesalib/src/mesa/main/queryobj.c
@@ -284,6 +284,13 @@ _mesa_CreateQueries(GLenum target, GLsizei n, GLuint *ids)
{
GET_CURRENT_CONTEXT(ctx);
+ if (!ctx->Extensions.ARB_direct_state_access) {
+ _mesa_error(ctx, GL_INVALID_OPERATION,
+ "glCreateQueries(GL_ARB_direct_state_access "
+ "is not supported)");
+ return;
+ }
+
switch (target) {
case GL_SAMPLES_PASSED:
case GL_ANY_SAMPLES_PASSED:
@@ -776,6 +783,9 @@ _mesa_GetQueryObjectiv(GLuint id, GLenum pname, GLint *params)
ctx->Driver.CheckQuery( ctx, q );
*params = q->Ready;
break;
+ case GL_QUERY_TARGET:
+ *params = q->Target;
+ break;
default:
_mesa_error(ctx, GL_INVALID_ENUM, "glGetQueryObjectivARB(pname)");
return;
@@ -827,6 +837,9 @@ _mesa_GetQueryObjectuiv(GLuint id, GLenum pname, GLuint *params)
ctx->Driver.CheckQuery( ctx, q );
*params = q->Ready;
break;
+ case GL_QUERY_TARGET:
+ *params = q->Target;
+ break;
default:
_mesa_error(ctx, GL_INVALID_ENUM, "glGetQueryObjectuivARB(pname)");
return;
@@ -867,6 +880,9 @@ _mesa_GetQueryObjecti64v(GLuint id, GLenum pname, GLint64EXT *params)
ctx->Driver.CheckQuery( ctx, q );
*params = q->Ready;
break;
+ case GL_QUERY_TARGET:
+ *params = q->Target;
+ break;
default:
_mesa_error(ctx, GL_INVALID_ENUM, "glGetQueryObjecti64vARB(pname)");
return;
@@ -907,6 +923,9 @@ _mesa_GetQueryObjectui64v(GLuint id, GLenum pname, GLuint64EXT *params)
ctx->Driver.CheckQuery( ctx, q );
*params = q->Ready;
break;
+ case GL_QUERY_TARGET:
+ *params = q->Target;
+ break;
default:
_mesa_error(ctx, GL_INVALID_ENUM, "glGetQueryObjectui64vARB(pname)");
return;
diff --git a/mesalib/src/mesa/main/readpix.c b/mesalib/src/mesa/main/readpix.c
index ed0104c9e..df46f8361 100644
--- a/mesalib/src/mesa/main/readpix.c
+++ b/mesalib/src/mesa/main/readpix.c
@@ -83,7 +83,7 @@ get_readpixels_transfer_ops(const struct gl_context *ctx, mesa_format texFormat,
if (uses_blit) {
/* For blit-based ReadPixels packing, the clamping is done automatically
* unless the type is float. */
- if (_mesa_get_clamp_read_color(ctx) &&
+ if (_mesa_get_clamp_read_color(ctx, ctx->ReadBuffer) &&
(type == GL_FLOAT || type == GL_HALF_FLOAT)) {
transferOps |= IMAGE_CLAMP_BIT;
}
@@ -91,7 +91,7 @@ get_readpixels_transfer_ops(const struct gl_context *ctx, mesa_format texFormat,
else {
/* For CPU-based ReadPixels packing, the clamping must always be done
* for non-float types, */
- if (_mesa_get_clamp_read_color(ctx) ||
+ if (_mesa_get_clamp_read_color(ctx, ctx->ReadBuffer) ||
(type != GL_FLOAT && type != GL_HALF_FLOAT)) {
transferOps |= IMAGE_CLAMP_BIT;
}
diff --git a/mesalib/src/mesa/main/samplerobj.c b/mesalib/src/mesa/main/samplerobj.c
index a3aacc66a..60711a5b5 100644
--- a/mesalib/src/mesa/main/samplerobj.c
+++ b/mesalib/src/mesa/main/samplerobj.c
@@ -221,6 +221,13 @@ void GLAPIENTRY
_mesa_CreateSamplers(GLsizei count, GLuint *samplers)
{
GET_CURRENT_CONTEXT(ctx);
+
+ if (!ctx->Extensions.ARB_direct_state_access) {
+ _mesa_error(ctx, GL_INVALID_OPERATION, "glCreateSamplers("
+ "GL_ARB_direct_state_access is not supported)");
+ return;
+ }
+
create_samplers(ctx, count, samplers, "glCreateSamplers");
}
diff --git a/mesalib/src/mesa/main/shader_query.cpp b/mesalib/src/mesa/main/shader_query.cpp
index d2ca49b43..3445f89a3 100644
--- a/mesalib/src/mesa/main/shader_query.cpp
+++ b/mesalib/src/mesa/main/shader_query.cpp
@@ -28,6 +28,7 @@
* \author Ian Romanick <ian.d.romanick@intel.com>
*/
+#include "main/context.h"
#include "main/core.h"
#include "glsl_symbol_table.h"
#include "ir.h"
@@ -809,6 +810,8 @@ stage_from_enum(GLenum ref)
return MESA_SHADER_GEOMETRY;
case GL_REFERENCED_BY_FRAGMENT_SHADER:
return MESA_SHADER_FRAGMENT;
+ case GL_REFERENCED_BY_COMPUTE_SHADER:
+ return MESA_SHADER_COMPUTE;
default:
assert(!"shader stage not supported");
return MESA_SHADER_STAGES;
@@ -824,6 +827,10 @@ is_resource_referenced(struct gl_shader_program *shProg,
struct gl_program_resource *res,
GLuint index, uint8_t stage)
{
+ /* First, check if we even have such a stage active. */
+ if (!shProg->_LinkedShaders[stage])
+ return false;
+
if (res->Type == GL_ATOMIC_COUNTER_BUFFER)
return RESOURCE_ATC(res)->StageReferences[stage];
@@ -979,6 +986,10 @@ _mesa_program_resource_prop(struct gl_shader_program *shProg,
case GL_NUM_ACTIVE_VARIABLES:
case GL_ACTIVE_VARIABLES:
return get_buffer_property(shProg, res, prop, val, caller);
+ case GL_REFERENCED_BY_COMPUTE_SHADER:
+ if (!_mesa_has_compute_shaders(ctx))
+ goto invalid_enum;
+ /* fallthrough */
case GL_REFERENCED_BY_VERTEX_SHADER:
case GL_REFERENCED_BY_GEOMETRY_SHADER:
case GL_REFERENCED_BY_FRAGMENT_SHADER:
@@ -1015,17 +1026,18 @@ _mesa_program_resource_prop(struct gl_shader_program *shProg,
case GL_IS_PER_PATCH:
case GL_REFERENCED_BY_TESS_CONTROL_SHADER:
case GL_REFERENCED_BY_TESS_EVALUATION_SHADER:
- /* GL_ARB_compute_shader */
- case GL_REFERENCED_BY_COMPUTE_SHADER:
default:
- _mesa_error(ctx, GL_INVALID_ENUM, "%s(%s prop %s)", caller,
- _mesa_lookup_enum_by_nr(res->Type),
- _mesa_lookup_enum_by_nr(prop));
- return 0;
+ goto invalid_enum;
}
#undef VALIDATE_TYPE
+invalid_enum:
+ _mesa_error(ctx, GL_INVALID_ENUM, "%s(%s prop %s)", caller,
+ _mesa_lookup_enum_by_nr(res->Type),
+ _mesa_lookup_enum_by_nr(prop));
+ return 0;
+
invalid_operation:
_mesa_error(ctx, GL_INVALID_OPERATION, "%s(%s prop %s)", caller,
_mesa_lookup_enum_by_nr(res->Type),
diff --git a/mesalib/src/mesa/main/shaderimage.c b/mesalib/src/mesa/main/shaderimage.c
index dcbcca623..80b77275f 100644
--- a/mesalib/src/mesa/main/shaderimage.c
+++ b/mesalib/src/mesa/main/shaderimage.c
@@ -58,8 +58,8 @@
# define MESA_FORMAT_SIGNED_RG_8 MESA_FORMAT_R8G8_SNORM
#endif
-static mesa_format
-get_image_format(GLenum format)
+mesa_format
+_mesa_get_shader_image_format(GLenum format)
{
switch (format) {
case GL_RGBA32F:
@@ -331,19 +331,33 @@ get_image_format_class(mesa_format format)
}
}
+void
+_mesa_init_image_units(struct gl_context *ctx)
+{
+ unsigned i;
+
+ for (i = 0; i < ARRAY_SIZE(ctx->ImageUnits); ++i) {
+ struct gl_image_unit *u = &ctx->ImageUnits[i];
+ u->Access = GL_READ_ONLY;
+ u->Format = GL_R8;
+ u->_ActualFormat = _mesa_get_shader_image_format(u->Format);
+ }
+}
+
static GLboolean
validate_image_unit(struct gl_context *ctx, struct gl_image_unit *u)
{
struct gl_texture_object *t = u->TexObj;
- struct gl_texture_image *img;
+ mesa_format tex_format;
- if (!t || u->Level < t->BaseLevel ||
- u->Level > t->_MaxLevel)
+ if (!t)
return GL_FALSE;
_mesa_test_texobj_completeness(ctx, t);
- if ((u->Level == t->BaseLevel && !t->_BaseComplete) ||
+ if (u->Level < t->BaseLevel ||
+ u->Level > t->_MaxLevel ||
+ (u->Level == t->BaseLevel && !t->_BaseComplete) ||
(u->Level != t->BaseLevel && !t->_MipmapComplete))
return GL_FALSE;
@@ -351,25 +365,32 @@ validate_image_unit(struct gl_context *ctx, struct gl_image_unit *u)
u->Layer >= _mesa_get_texture_layers(t, u->Level))
return GL_FALSE;
- if (t->Target == GL_TEXTURE_CUBE_MAP)
- img = t->Image[u->Layer][u->Level];
- else
- img = t->Image[0][u->Level];
+ if (t->Target == GL_TEXTURE_BUFFER) {
+ tex_format = _mesa_get_shader_image_format(t->BufferObjectFormat);
+
+ } else {
+ struct gl_texture_image *img = (t->Target == GL_TEXTURE_CUBE_MAP ?
+ t->Image[u->Layer][u->Level] :
+ t->Image[0][u->Level]);
- if (!img || img->Border ||
- get_image_format_class(img->TexFormat) == IMAGE_FORMAT_CLASS_NONE ||
- img->NumSamples > ctx->Const.MaxImageSamples)
+ if (!img || img->Border || img->NumSamples > ctx->Const.MaxImageSamples)
+ return GL_FALSE;
+
+ tex_format = _mesa_get_shader_image_format(img->InternalFormat);
+ }
+
+ if (!tex_format)
return GL_FALSE;
switch (t->ImageFormatCompatibilityType) {
case GL_IMAGE_FORMAT_COMPATIBILITY_BY_SIZE:
- if (_mesa_get_format_bytes(img->TexFormat) !=
+ if (_mesa_get_format_bytes(tex_format) !=
_mesa_get_format_bytes(u->_ActualFormat))
return GL_FALSE;
break;
case GL_IMAGE_FORMAT_COMPATIBILITY_BY_CLASS:
- if (get_image_format_class(img->TexFormat) !=
+ if (get_image_format_class(tex_format) !=
get_image_format_class(u->_ActualFormat))
return GL_FALSE;
break;
@@ -421,7 +442,7 @@ validate_bind_image_texture(struct gl_context *ctx, GLuint unit,
return GL_FALSE;
}
- if (!get_image_format(format)) {
+ if (!_mesa_get_shader_image_format(format)) {
_mesa_error(ctx, GL_INVALID_VALUE, "glBindImageTexture(format)");
return GL_FALSE;
}
@@ -435,7 +456,6 @@ _mesa_BindImageTexture(GLuint unit, GLuint texture, GLint level,
GLenum format)
{
GET_CURRENT_CONTEXT(ctx);
- struct gl_texture_object *t = NULL;
struct gl_image_unit *u;
if (!validate_bind_image_texture(ctx, unit, texture, level,
@@ -448,34 +468,34 @@ _mesa_BindImageTexture(GLuint unit, GLuint texture, GLint level,
ctx->NewDriverState |= ctx->DriverFlags.NewImageUnits;
if (texture) {
- t = _mesa_lookup_texture(ctx, texture);
+ struct gl_texture_object *t = _mesa_lookup_texture(ctx, texture);
+
if (!t) {
_mesa_error(ctx, GL_INVALID_VALUE, "glBindImageTexture(texture)");
return;
}
_mesa_reference_texobj(&u->TexObj, t);
- u->Level = level;
- u->Access = access;
- u->Format = format;
- u->_ActualFormat = get_image_format(format);
-
- if (_mesa_tex_target_is_layered(t->Target)) {
- u->Layered = layered;
- u->Layer = (layered ? 0 : layer);
- } else {
- u->Layered = GL_FALSE;
- u->Layer = 0;
- }
-
} else {
_mesa_reference_texobj(&u->TexObj, NULL);
}
+ u->Level = level;
+ u->Access = access;
+ u->Format = format;
+ u->_ActualFormat = _mesa_get_shader_image_format(format);
u->_Valid = validate_image_unit(ctx, u);
+ if (u->TexObj && _mesa_tex_target_is_layered(u->TexObj->Target)) {
+ u->Layered = layered;
+ u->Layer = (layered ? 0 : layer);
+ } else {
+ u->Layered = GL_FALSE;
+ u->Layer = 0;
+ }
+
if (ctx->Driver.BindImageTexture)
- ctx->Driver.BindImageTexture(ctx, u, t, level, layered,
+ ctx->Driver.BindImageTexture(ctx, u, u->TexObj, level, layered,
layer, access, format);
}
@@ -535,8 +555,7 @@ _mesa_BindImageTextures(GLuint first, GLsizei count, const GLuint *textures)
if (texture != 0) {
struct gl_texture_object *texObj;
- struct gl_texture_image *image;
- mesa_format actualFormat;
+ GLenum tex_format;
if (!u->TexObj || u->TexObj->Name != texture) {
texObj = _mesa_lookup_texture_locked(ctx, texture);
@@ -557,25 +576,30 @@ _mesa_BindImageTextures(GLuint first, GLsizei count, const GLuint *textures)
texObj = u->TexObj;
}
- image = texObj->Image[0][0];
+ if (texObj->Target == GL_TEXTURE_BUFFER) {
+ tex_format = texObj->BufferObjectFormat;
+ } else {
+ struct gl_texture_image *image = texObj->Image[0][0];
- if (!image || image->Width == 0 || image->Height == 0 || image->Depth == 0) {
- /* The ARB_multi_bind spec says:
- *
- * "An INVALID_OPERATION error is generated if the width,
- * height, or depth of the level zero texture image of
- * any texture in <textures> is zero (per binding)."
- */
- _mesa_error(ctx, GL_INVALID_OPERATION,
- "glBindImageTextures(the width, height or depth "
- "of the level zero texture image of "
- "textures[%d]=%u is zero)", i, texture);
- continue;
- }
+ if (!image || image->Width == 0 || image->Height == 0 ||
+ image->Depth == 0) {
+ /* The ARB_multi_bind spec says:
+ *
+ * "An INVALID_OPERATION error is generated if the width,
+ * height, or depth of the level zero texture image of
+ * any texture in <textures> is zero (per binding)."
+ */
+ _mesa_error(ctx, GL_INVALID_OPERATION,
+ "glBindImageTextures(the width, height or depth "
+ "of the level zero texture image of "
+ "textures[%d]=%u is zero)", i, texture);
+ continue;
+ }
- actualFormat = get_image_format(image->InternalFormat);
+ tex_format = image->InternalFormat;
+ }
- if (actualFormat == MESA_FORMAT_NONE) {
+ if (_mesa_get_shader_image_format(tex_format) == MESA_FORMAT_NONE) {
/* The ARB_multi_bind spec says:
*
* "An INVALID_OPERATION error is generated if the internal
@@ -586,7 +610,7 @@ _mesa_BindImageTextures(GLuint first, GLsizei count, const GLuint *textures)
"glBindImageTextures(the internal format %s of "
"the level zero texture image of textures[%d]=%u "
"is not supported)",
- _mesa_lookup_enum_by_nr(image->InternalFormat),
+ _mesa_lookup_enum_by_nr(tex_format),
i, texture);
continue;
}
@@ -597,8 +621,8 @@ _mesa_BindImageTextures(GLuint first, GLsizei count, const GLuint *textures)
u->Layered = _mesa_tex_target_is_layered(texObj->Target);
u->Layer = 0;
u->Access = GL_READ_WRITE;
- u->Format = image->InternalFormat;
- u->_ActualFormat = actualFormat;
+ u->Format = tex_format;
+ u->_ActualFormat = _mesa_get_shader_image_format(tex_format);
u->_Valid = validate_image_unit(ctx, u);
} else {
/* Unbind the texture from the unit */
diff --git a/mesalib/src/mesa/main/shaderimage.h b/mesalib/src/mesa/main/shaderimage.h
index 733ac7747..33d8a1eff 100644
--- a/mesalib/src/mesa/main/shaderimage.h
+++ b/mesalib/src/mesa/main/shaderimage.h
@@ -28,10 +28,27 @@
#define SHADERIMAGE_H
#include "glheader.h"
+#include "formats.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
struct gl_context;
/**
+ * Get the matching mesa_format for a shader image format GL enum.
+ */
+mesa_format
+_mesa_get_shader_image_format(GLenum format);
+
+/**
+ * Initialize a context's shader image units to the default state.
+ */
+void
+_mesa_init_image_units(struct gl_context *ctx);
+
+/**
* Recalculate the \c _Valid flag of a context's shader image units.
*
* To be called when the state of any texture bound to an image unit
@@ -51,4 +68,8 @@ _mesa_BindImageTextures(GLuint first, GLsizei count, const GLuint *textures);
void GLAPIENTRY
_mesa_MemoryBarrier(GLbitfield barriers);
+#ifdef __cplusplus
+}
+#endif
+
#endif
diff --git a/mesalib/src/mesa/main/state.c b/mesalib/src/mesa/main/state.c
index cc84c6148..2657c532f 100644
--- a/mesalib/src/mesa/main/state.c
+++ b/mesalib/src/mesa/main/state.c
@@ -101,9 +101,12 @@ update_program(struct gl_context *ctx)
ctx->_Shader->CurrentProgram[MESA_SHADER_GEOMETRY];
struct gl_shader_program *fsProg =
ctx->_Shader->CurrentProgram[MESA_SHADER_FRAGMENT];
+ const struct gl_shader_program *csProg =
+ ctx->_Shader->CurrentProgram[MESA_SHADER_COMPUTE];
const struct gl_vertex_program *prevVP = ctx->VertexProgram._Current;
const struct gl_fragment_program *prevFP = ctx->FragmentProgram._Current;
const struct gl_geometry_program *prevGP = ctx->GeometryProgram._Current;
+ const struct gl_compute_program *prevCP = ctx->ComputeProgram._Current;
GLbitfield new_state = 0x0;
/*
@@ -199,6 +202,16 @@ update_program(struct gl_context *ctx)
_mesa_reference_vertprog(ctx, &ctx->VertexProgram._Current, NULL);
}
+ if (csProg && csProg->LinkStatus
+ && csProg->_LinkedShaders[MESA_SHADER_COMPUTE]) {
+ /* Use GLSL compute shader */
+ _mesa_reference_compprog(ctx, &ctx->ComputeProgram._Current,
+ gl_compute_program(csProg->_LinkedShaders[MESA_SHADER_COMPUTE]->Program));
+ } else {
+ /* no compute program */
+ _mesa_reference_compprog(ctx, &ctx->ComputeProgram._Current, NULL);
+ }
+
/* Let the driver know what's happening:
*/
if (ctx->FragmentProgram._Current != prevFP) {
@@ -225,6 +238,14 @@ update_program(struct gl_context *ctx)
}
}
+ if (ctx->ComputeProgram._Current != prevCP) {
+ new_state |= _NEW_PROGRAM;
+ if (ctx->Driver.BindProgram) {
+ ctx->Driver.BindProgram(ctx, GL_COMPUTE_PROGRAM_NV,
+ (struct gl_program *) ctx->ComputeProgram._Current);
+ }
+ }
+
return new_state;
}
@@ -368,10 +389,10 @@ _mesa_update_state_locked( struct gl_context *ctx )
update_frontbit( ctx );
if (new_state & _NEW_BUFFERS)
- _mesa_update_framebuffer(ctx);
+ _mesa_update_framebuffer(ctx, ctx->ReadBuffer, ctx->DrawBuffer);
if (new_state & (_NEW_SCISSOR | _NEW_BUFFERS | _NEW_VIEWPORT))
- _mesa_update_draw_buffer_bounds( ctx );
+ _mesa_update_draw_buffer_bounds(ctx, ctx->DrawBuffer);
if (new_state & _NEW_LIGHT)
_mesa_update_lighting( ctx );
diff --git a/mesalib/src/mesa/main/texenv.c b/mesalib/src/mesa/main/texenv.c
index ec521e6c6..3edafc0f7 100644
--- a/mesalib/src/mesa/main/texenv.c
+++ b/mesalib/src/mesa/main/texenv.c
@@ -646,7 +646,7 @@ _mesa_GetTexEnvfv( GLenum target, GLenum pname, GLfloat *params )
if (pname == GL_TEXTURE_ENV_COLOR) {
if(ctx->NewState & (_NEW_BUFFERS | _NEW_FRAG_CLAMP))
_mesa_update_state(ctx);
- if (_mesa_get_clamp_fragment_color(ctx))
+ if (_mesa_get_clamp_fragment_color(ctx, ctx->DrawBuffer))
COPY_4FV( params, texUnit->EnvColor );
else
COPY_4FV( params, texUnit->EnvColorUnclamped );
diff --git a/mesalib/src/mesa/main/texgetimage.c b/mesalib/src/mesa/main/texgetimage.c
index 92b4d6795..f582a7f78 100644
--- a/mesalib/src/mesa/main/texgetimage.c
+++ b/mesalib/src/mesa/main/texgetimage.c
@@ -1108,6 +1108,13 @@ _mesa_GetTextureImage(GLuint texture, GLint level, GLenum format,
GLenum err;
GET_CURRENT_CONTEXT(ctx);
+ if (!ctx->Extensions.ARB_direct_state_access) {
+ _mesa_error(ctx, GL_INVALID_OPERATION,
+ "glGetTextureImage(GL_ARB_direct_state_access "
+ "is not supported)");
+ return;
+ }
+
/*
* This has been moved here because a format/type mismatch can cause a NULL
* texImage object, which in turn causes the mismatch error to be
@@ -1344,6 +1351,13 @@ _mesa_GetCompressedTextureImage(GLuint texture, GLint level,
GLint image_stride;
GET_CURRENT_CONTEXT(ctx);
+ if (!ctx->Extensions.ARB_direct_state_access) {
+ _mesa_error(ctx, GL_INVALID_OPERATION,
+ "glGetCompressedTextureImage(GL_ARB_direct_state_access "
+ "is not supported)");
+ return;
+ }
+
texObj = _mesa_lookup_texture_err(ctx, texture,
"glGetCompressedTextureImage");
if (!texObj)
diff --git a/mesalib/src/mesa/main/teximage.c b/mesalib/src/mesa/main/teximage.c
index 7bc1da7f8..7616fd7ce 100644
--- a/mesalib/src/mesa/main/teximage.c
+++ b/mesalib/src/mesa/main/teximage.c
@@ -3624,6 +3624,13 @@ texturesubimage(struct gl_context *ctx, GLuint dims,
_mesa_lookup_enum_by_nr(format),
_mesa_lookup_enum_by_nr(type), pixels);
+ if (!ctx->Extensions.ARB_direct_state_access) {
+ _mesa_error(ctx, GL_INVALID_OPERATION,
+ "glTextureSubImage%uD(GL_ARB_direct_state_access "
+ "is not supported)", dims);
+ return;
+ }
+
/* Get the texture object by Name. */
texObj = _mesa_lookup_texture(ctx, texture);
if (!texObj) {
@@ -4183,6 +4190,12 @@ _mesa_CopyTextureSubImage1D(GLuint texture, GLint level,
const char *self = "glCopyTextureSubImage1D";
GET_CURRENT_CONTEXT(ctx);
+ if (!ctx->Extensions.ARB_direct_state_access) {
+ _mesa_error(ctx, GL_INVALID_OPERATION,
+ "%s(GL_ARB_direct_state_access is not supported)", self);
+ return;
+ }
+
texObj = _mesa_lookup_texture_err(ctx, texture, self);
if (!texObj)
return;
@@ -4207,6 +4220,12 @@ _mesa_CopyTextureSubImage2D(GLuint texture, GLint level,
const char *self = "glCopyTextureSubImage2D";
GET_CURRENT_CONTEXT(ctx);
+ if (!ctx->Extensions.ARB_direct_state_access) {
+ _mesa_error(ctx, GL_INVALID_OPERATION,
+ "%s(GL_ARB_direct_state_access is not supported)", self);
+ return;
+ }
+
texObj = _mesa_lookup_texture_err(ctx, texture, self);
if (!texObj)
return;
@@ -4234,6 +4253,12 @@ _mesa_CopyTextureSubImage3D(GLuint texture, GLint level,
const char *self = "glCopyTextureSubImage3D";
GET_CURRENT_CONTEXT(ctx);
+ if (!ctx->Extensions.ARB_direct_state_access) {
+ _mesa_error(ctx, GL_INVALID_OPERATION,
+ "%s(GL_ARB_direct_state_access is not supported)", self);
+ return;
+ }
+
texObj = _mesa_lookup_texture_err(ctx, texture, self);
if (!texObj)
return;
@@ -4829,6 +4854,13 @@ _mesa_CompressedTextureSubImage1D(GLuint texture, GLint level, GLint xoffset,
GET_CURRENT_CONTEXT(ctx);
+ if (!ctx->Extensions.ARB_direct_state_access) {
+ _mesa_error(ctx, GL_INVALID_OPERATION,
+ "glCompressedTextureSubImage1D(GL_ARB_direct_state_access "
+ "is not supported)");
+ return;
+ }
+
texObj = _mesa_lookup_texture_err(ctx, texture,
"glCompressedTextureSubImage1D");
if (!texObj)
@@ -4907,6 +4939,13 @@ _mesa_CompressedTextureSubImage2D(GLuint texture, GLint level, GLint xoffset,
GET_CURRENT_CONTEXT(ctx);
+ if (!ctx->Extensions.ARB_direct_state_access) {
+ _mesa_error(ctx, GL_INVALID_OPERATION,
+ "glCompressedTextureSubImage2D(GL_ARB_direct_state_access "
+ "is not supported)");
+ return;
+ }
+
texObj = _mesa_lookup_texture_err(ctx, texture,
"glCompressedTextureSubImage2D");
if (!texObj)
@@ -4985,6 +5024,13 @@ _mesa_CompressedTextureSubImage3D(GLuint texture, GLint level, GLint xoffset,
GET_CURRENT_CONTEXT(ctx);
+ if (!ctx->Extensions.ARB_direct_state_access) {
+ _mesa_error(ctx, GL_INVALID_OPERATION,
+ "glCompressedTextureSubImage3D(GL_ARB_direct_state_access "
+ "is not supported)");
+ return;
+ }
+
texObj = _mesa_lookup_texture_err(ctx, texture,
"glCompressedTextureSubImage3D");
if (!texObj)
@@ -5469,6 +5515,13 @@ _mesa_TextureBuffer(GLuint texture, GLenum internalFormat, GLuint buffer)
GET_CURRENT_CONTEXT(ctx);
+ if (!ctx->Extensions.ARB_direct_state_access) {
+ _mesa_error(ctx, GL_INVALID_OPERATION,
+ "glTextureBuffer(GL_ARB_direct_state_access "
+ "is not supported)");
+ return;
+ }
+
if (buffer) {
bufObj = _mesa_lookup_bufferobj_err(ctx, buffer, "glTextureBuffer");
if (!bufObj)
@@ -5497,6 +5550,13 @@ _mesa_TextureBufferRange(GLuint texture, GLenum internalFormat, GLuint buffer,
GET_CURRENT_CONTEXT(ctx);
+ if (!ctx->Extensions.ARB_direct_state_access) {
+ _mesa_error(ctx, GL_INVALID_OPERATION,
+ "glTextureBufferRange(GL_ARB_direct_state_access "
+ "is not supported)");
+ return;
+ }
+
if (buffer) {
bufObj = _mesa_lookup_bufferobj_err(ctx, buffer,
"glTextureBufferRange");
@@ -5801,6 +5861,13 @@ _mesa_TextureStorage2DMultisample(GLuint texture, GLsizei samples,
struct gl_texture_object *texObj;
GET_CURRENT_CONTEXT(ctx);
+ if (!ctx->Extensions.ARB_direct_state_access) {
+ _mesa_error(ctx, GL_INVALID_OPERATION,
+ "glTextureStorage2DMultisample(GL_ARB_direct_state_access "
+ "is not supported)");
+ return;
+ }
+
texObj = _mesa_lookup_texture_err(ctx, texture,
"glTextureStorage2DMultisample");
if (!texObj)
@@ -5821,6 +5888,13 @@ _mesa_TextureStorage3DMultisample(GLuint texture, GLsizei samples,
struct gl_texture_object *texObj;
GET_CURRENT_CONTEXT(ctx);
+ if (!ctx->Extensions.ARB_direct_state_access) {
+ _mesa_error(ctx, GL_INVALID_OPERATION,
+ "glTextureStorage3DMultisample(GL_ARB_direct_state_access "
+ "is not supported)");
+ return;
+ }
+
/* Get the texture object by Name. */
texObj = _mesa_lookup_texture_err(ctx, texture,
"glTextureStorage3DMultisample");
diff --git a/mesalib/src/mesa/main/texobj.c b/mesalib/src/mesa/main/texobj.c
index c563f1e74..d51e6954b 100644
--- a/mesalib/src/mesa/main/texobj.c
+++ b/mesalib/src/mesa/main/texobj.c
@@ -1317,6 +1317,13 @@ _mesa_CreateTextures(GLenum target, GLsizei n, GLuint *textures)
GLint targetIndex;
GET_CURRENT_CONTEXT(ctx);
+ if (!ctx->Extensions.ARB_direct_state_access) {
+ _mesa_error(ctx, GL_INVALID_OPERATION,
+ "glCreateTextures(GL_ARB_direct_state_access "
+ "is not supported)");
+ return;
+ }
+
/*
* The 4.5 core profile spec (30.10.2014) doesn't specify what
* glCreateTextures should do with invalid targets, which was probably an
@@ -1808,6 +1815,13 @@ _mesa_BindTextureUnit(GLuint unit, GLuint texture)
_mesa_debug(ctx, "glBindTextureUnit %s %d\n",
_mesa_lookup_enum_by_nr(GL_TEXTURE0+unit), (GLint) texture);
+ if (!ctx->Extensions.ARB_direct_state_access) {
+ _mesa_error(ctx, GL_INVALID_OPERATION,
+ "glBindTextureUnit(GL_ARB_direct_state_access "
+ "is not supported)");
+ return;
+ }
+
/* Section 8.1 (Texture Objects) of the OpenGL 4.5 core profile spec
* (20141030) says:
* "When texture is zero, each of the targets enumerated at the
diff --git a/mesalib/src/mesa/main/texparam.c b/mesalib/src/mesa/main/texparam.c
index b5d42d304..1fa583002 100644
--- a/mesalib/src/mesa/main/texparam.c
+++ b/mesalib/src/mesa/main/texparam.c
@@ -1108,6 +1108,13 @@ _mesa_TextureParameterfv(GLuint texture, GLenum pname, const GLfloat *params)
struct gl_texture_object *texObj;
GET_CURRENT_CONTEXT(ctx);
+ if (!ctx->Extensions.ARB_direct_state_access) {
+ _mesa_error(ctx, GL_INVALID_OPERATION,
+ "glTextureParameterfv(GL_ARB_direct_state_access "
+ "is not supported)");
+ return;
+ }
+
texObj = get_texobj_by_name(ctx, texture, GL_FALSE);
if (!texObj) {
/* User passed a non-generated name. */
@@ -1124,6 +1131,13 @@ _mesa_TextureParameterf(GLuint texture, GLenum pname, GLfloat param)
struct gl_texture_object *texObj;
GET_CURRENT_CONTEXT(ctx);
+ if (!ctx->Extensions.ARB_direct_state_access) {
+ _mesa_error(ctx, GL_INVALID_OPERATION,
+ "glTextureParameterf(GL_ARB_direct_state_access "
+ "is not supported)");
+ return;
+ }
+
texObj = get_texobj_by_name(ctx, texture, GL_FALSE);
if (!texObj) {
/* User passed a non-generated name. */
@@ -1140,6 +1154,13 @@ _mesa_TextureParameteri(GLuint texture, GLenum pname, GLint param)
struct gl_texture_object *texObj;
GET_CURRENT_CONTEXT(ctx);
+ if (!ctx->Extensions.ARB_direct_state_access) {
+ _mesa_error(ctx, GL_INVALID_OPERATION,
+ "glTextureParameteri(GL_ARB_direct_state_access "
+ "is not supported)");
+ return;
+ }
+
texObj = get_texobj_by_name(ctx, texture, GL_FALSE);
if (!texObj) {
/* User passed a non-generated name. */
@@ -1157,6 +1178,13 @@ _mesa_TextureParameteriv(GLuint texture, GLenum pname,
struct gl_texture_object *texObj;
GET_CURRENT_CONTEXT(ctx);
+ if (!ctx->Extensions.ARB_direct_state_access) {
+ _mesa_error(ctx, GL_INVALID_OPERATION,
+ "glTextureParameteriv(GL_ARB_direct_state_access "
+ "is not supported)");
+ return;
+ }
+
texObj = get_texobj_by_name(ctx, texture, GL_FALSE);
if (!texObj) {
/* User passed a non-generated name. */
@@ -1174,6 +1202,13 @@ _mesa_TextureParameterIiv(GLuint texture, GLenum pname, const GLint *params)
struct gl_texture_object *texObj;
GET_CURRENT_CONTEXT(ctx);
+ if (!ctx->Extensions.ARB_direct_state_access) {
+ _mesa_error(ctx, GL_INVALID_OPERATION,
+ "glTextureParameterIiv(GL_ARB_direct_state_access "
+ "is not supported)");
+ return;
+ }
+
texObj = get_texobj_by_name(ctx, texture, GL_FALSE);
if (!texObj) {
/* User passed a non-generated name. */
@@ -1191,6 +1226,13 @@ _mesa_TextureParameterIuiv(GLuint texture, GLenum pname, const GLuint *params)
struct gl_texture_object *texObj;
GET_CURRENT_CONTEXT(ctx);
+ if (!ctx->Extensions.ARB_direct_state_access) {
+ _mesa_error(ctx, GL_INVALID_OPERATION,
+ "glTextureParameterIuiv(GL_ARB_direct_state_access "
+ "is not supported)");
+ return;
+ }
+
texObj = get_texobj_by_name(ctx, texture, GL_FALSE);
if (!texObj) {
/* User passed a non-generated name. */
@@ -1650,6 +1692,13 @@ _mesa_GetTextureLevelParameterfv(GLuint texture, GLint level,
GLint iparam;
GET_CURRENT_CONTEXT(ctx);
+ if (!ctx->Extensions.ARB_direct_state_access) {
+ _mesa_error(ctx, GL_INVALID_OPERATION,
+ "glGetTextureLevelParameterfv(GL_ARB_direct_state_access "
+ "is not supported)");
+ return;
+ }
+
texObj = _mesa_lookup_texture_err(ctx, texture,
"glGetTextureLevelParameterfv");
if (!texObj)
@@ -1668,6 +1717,13 @@ _mesa_GetTextureLevelParameteriv(GLuint texture, GLint level,
struct gl_texture_object *texObj;
GET_CURRENT_CONTEXT(ctx);
+ if (!ctx->Extensions.ARB_direct_state_access) {
+ _mesa_error(ctx, GL_INVALID_OPERATION,
+ "glGetTextureLevelParameteriv(GL_ARB_direct_state_access "
+ "is not supported)");
+ return;
+ }
+
texObj = _mesa_lookup_texture_err(ctx, texture,
"glGetTextureLevelParameteriv");
if (!texObj)
@@ -1709,7 +1765,7 @@ get_tex_parameterfv(struct gl_context *ctx,
if (ctx->NewState & (_NEW_BUFFERS | _NEW_FRAG_CLAMP))
_mesa_update_state_locked(ctx);
- if (_mesa_get_clamp_fragment_color(ctx)) {
+ if (_mesa_get_clamp_fragment_color(ctx, ctx->DrawBuffer)) {
params[0] = CLAMP(obj->Sampler.BorderColor.f[0], 0.0F, 1.0F);
params[1] = CLAMP(obj->Sampler.BorderColor.f[1], 0.0F, 1.0F);
params[2] = CLAMP(obj->Sampler.BorderColor.f[2], 0.0F, 1.0F);
@@ -2227,6 +2283,13 @@ _mesa_GetTextureParameterfv(GLuint texture, GLenum pname, GLfloat *params)
struct gl_texture_object *obj;
GET_CURRENT_CONTEXT(ctx);
+ if (!ctx->Extensions.ARB_direct_state_access) {
+ _mesa_error(ctx, GL_INVALID_OPERATION,
+ "glGetTextureParameterfv(GL_ARB_direct_state_access "
+ "is not supported)");
+ return;
+ }
+
obj = get_texobj_by_name(ctx, texture, GL_TRUE);
if (!obj) {
/* User passed a non-generated name. */
@@ -2244,6 +2307,13 @@ _mesa_GetTextureParameteriv(GLuint texture, GLenum pname, GLint *params)
struct gl_texture_object *obj;
GET_CURRENT_CONTEXT(ctx);
+ if (!ctx->Extensions.ARB_direct_state_access) {
+ _mesa_error(ctx, GL_INVALID_OPERATION,
+ "glGetTextureParameteriv(GL_ARB_direct_state_access "
+ "is not supported)");
+ return;
+ }
+
obj = get_texobj_by_name(ctx, texture, GL_TRUE);
if (!obj) {
/* User passed a non-generated name. */
@@ -2261,6 +2331,13 @@ _mesa_GetTextureParameterIiv(GLuint texture, GLenum pname, GLint *params)
struct gl_texture_object *texObj;
GET_CURRENT_CONTEXT(ctx);
+ if (!ctx->Extensions.ARB_direct_state_access) {
+ _mesa_error(ctx, GL_INVALID_OPERATION,
+ "glGetTextureParameterIiv(GL_ARB_direct_state_access "
+ "is not supported)");
+ return;
+ }
+
texObj = get_texobj_by_name(ctx, texture, GL_TRUE);
if (!texObj) {
/* User passed a non-generated name. */
@@ -2279,6 +2356,13 @@ _mesa_GetTextureParameterIuiv(GLuint texture, GLenum pname, GLuint *params)
struct gl_texture_object *texObj;
GET_CURRENT_CONTEXT(ctx);
+ if (!ctx->Extensions.ARB_direct_state_access) {
+ _mesa_error(ctx, GL_INVALID_OPERATION,
+ "glGetTextureParameterIuiv(GL_ARB_direct_state_access "
+ "is not supported)");
+ return;
+ }
+
texObj = get_texobj_by_name(ctx, texture, GL_TRUE);
if (!texObj) {
/* User passed a non-generated name. */
diff --git a/mesalib/src/mesa/main/texstorage.c b/mesalib/src/mesa/main/texstorage.c
index 53cb2c091..dee74a825 100644
--- a/mesalib/src/mesa/main/texstorage.c
+++ b/mesalib/src/mesa/main/texstorage.c
@@ -507,6 +507,13 @@ texturestorage(GLuint dims, GLuint texture, GLsizei levels,
_mesa_lookup_enum_by_nr(internalformat),
width, height, depth);
+ if (!ctx->Extensions.ARB_direct_state_access) {
+ _mesa_error(ctx, GL_INVALID_OPERATION,
+ "glTextureStorage%uD(GL_ARB_direct_state_access "
+ "is not supported)", dims);
+ return;
+ }
+
/* Check the format to make sure it is sized. */
if (!_mesa_is_legal_tex_storage_format(ctx, internalformat)) {
_mesa_error(ctx, GL_INVALID_ENUM,
diff --git a/mesalib/src/mesa/main/transformfeedback.c b/mesalib/src/mesa/main/transformfeedback.c
index 103011ce5..642fa9647 100644
--- a/mesalib/src/mesa/main/transformfeedback.c
+++ b/mesalib/src/mesa/main/transformfeedback.c
@@ -706,6 +706,13 @@ _mesa_TransformFeedbackBufferBase(GLuint xfb, GLuint index, GLuint buffer)
struct gl_transform_feedback_object *obj;
struct gl_buffer_object *bufObj;
+ if (!ctx->Extensions.ARB_direct_state_access) {
+ _mesa_error(ctx, GL_INVALID_OPERATION,
+ "glTransformFeedbackBufferBase(GL_ARB_direct_state_access "
+ "is not supported)");
+ return;
+ }
+
obj = lookup_transform_feedback_object_err(ctx, xfb,
"glTransformFeedbackBufferBase");
if(!obj) {
@@ -729,6 +736,13 @@ _mesa_TransformFeedbackBufferRange(GLuint xfb, GLuint index, GLuint buffer,
struct gl_transform_feedback_object *obj;
struct gl_buffer_object *bufObj;
+ if (!ctx->Extensions.ARB_direct_state_access) {
+ _mesa_error(ctx, GL_INVALID_OPERATION,
+ "glTransformFeedbackBufferRange(GL_ARB_direct_state_access "
+ "is not supported)");
+ return;
+ }
+
obj = lookup_transform_feedback_object_err(ctx, xfb,
"glTransformFeedbackBufferRange");
if(!obj) {
@@ -1045,6 +1059,13 @@ _mesa_CreateTransformFeedbacks(GLsizei n, GLuint *names)
{
GET_CURRENT_CONTEXT(ctx);
+ if (!ctx->Extensions.ARB_direct_state_access) {
+ _mesa_error(ctx, GL_INVALID_OPERATION,
+ "glCreateTransformFeedbacks(GL_ARB_direct_state_access "
+ "is not supported)");
+ return;
+ }
+
create_transform_feedbacks(ctx, n, names, true);
}
@@ -1215,6 +1236,13 @@ _mesa_GetTransformFeedbackiv(GLuint xfb, GLenum pname, GLint *param)
struct gl_transform_feedback_object *obj;
GET_CURRENT_CONTEXT(ctx);
+ if (!ctx->Extensions.ARB_direct_state_access) {
+ _mesa_error(ctx, GL_INVALID_OPERATION,
+ "glGetTransformFeedbackiv(GL_ARB_direct_state_access "
+ "is not supported)");
+ return;
+ }
+
obj = lookup_transform_feedback_object_err(ctx, xfb,
"glGetTransformFeedbackiv");
if(!obj) {
@@ -1241,6 +1269,13 @@ _mesa_GetTransformFeedbacki_v(GLuint xfb, GLenum pname, GLuint index,
struct gl_transform_feedback_object *obj;
GET_CURRENT_CONTEXT(ctx);
+ if (!ctx->Extensions.ARB_direct_state_access) {
+ _mesa_error(ctx, GL_INVALID_OPERATION,
+ "glGetTransformFeedbacki_v(GL_ARB_direct_state_access "
+ "is not supported)");
+ return;
+ }
+
obj = lookup_transform_feedback_object_err(ctx, xfb,
"glGetTransformFeedbacki_v");
if(!obj) {
@@ -1270,6 +1305,13 @@ _mesa_GetTransformFeedbacki64_v(GLuint xfb, GLenum pname, GLuint index,
struct gl_transform_feedback_object *obj;
GET_CURRENT_CONTEXT(ctx);
+ if (!ctx->Extensions.ARB_direct_state_access) {
+ _mesa_error(ctx, GL_INVALID_OPERATION,
+ "glGetTransformFeedbacki64_v(GL_ARB_direct_state_access "
+ "is not supported)");
+ return;
+ }
+
obj = lookup_transform_feedback_object_err(ctx, xfb,
"glGetTransformFeedbacki64_v");
if(!obj) {
diff --git a/mesalib/src/mesa/main/uniform_query.cpp b/mesalib/src/mesa/main/uniform_query.cpp
index 3e857ed10..728bd1bac 100644
--- a/mesalib/src/mesa/main/uniform_query.cpp
+++ b/mesalib/src/mesa/main/uniform_query.cpp
@@ -347,7 +347,8 @@ _mesa_get_uniform(struct gl_context *ctx, GLuint program, GLint location,
&&
(uni->type->base_type == GLSL_TYPE_INT
|| uni->type->base_type == GLSL_TYPE_UINT
- || uni->type->base_type == GLSL_TYPE_SAMPLER))) {
+ || uni->type->base_type == GLSL_TYPE_SAMPLER
+ || uni->type->base_type == GLSL_TYPE_IMAGE))) {
memcpy(paramsOut, src, bytes);
} else {
union gl_constant_value *const dst =
@@ -366,6 +367,7 @@ _mesa_get_uniform(struct gl_context *ctx, GLuint program, GLint location,
break;
case GLSL_TYPE_INT:
case GLSL_TYPE_SAMPLER:
+ case GLSL_TYPE_IMAGE:
dst[i].f = (float) src[i].i;
break;
case GLSL_TYPE_BOOL:
diff --git a/mesalib/src/mesa/main/varray.c b/mesalib/src/mesa/main/varray.c
index 42e7f89b2..da6bbce52 100644
--- a/mesalib/src/mesa/main/varray.c
+++ b/mesalib/src/mesa/main/varray.c
@@ -66,6 +66,21 @@
#define UNSIGNED_INT_10F_11F_11F_REV_BIT (1 << 14)
#define ALL_TYPE_BITS ((1 << 15) - 1)
+#define ATTRIB_FORMAT_TYPES_MASK (BYTE_BIT | UNSIGNED_BYTE_BIT | \
+ SHORT_BIT | UNSIGNED_SHORT_BIT | \
+ INT_BIT | UNSIGNED_INT_BIT | \
+ HALF_BIT | FLOAT_BIT | DOUBLE_BIT | \
+ FIXED_GL_BIT | \
+ UNSIGNED_INT_2_10_10_10_REV_BIT | \
+ INT_2_10_10_10_REV_BIT | \
+ UNSIGNED_INT_10F_11F_11F_REV_BIT)
+
+#define ATTRIB_IFORMAT_TYPES_MASK (BYTE_BIT | UNSIGNED_BYTE_BIT | \
+ SHORT_BIT | UNSIGNED_SHORT_BIT | \
+ INT_BIT | UNSIGNED_INT_BIT)
+
+#define ATTRIB_LFORMAT_TYPES_MASK DOUBLE_BIT
+
/** Convert GL datatype enum into a <type>_BIT value seen above */
static GLbitfield
@@ -113,10 +128,11 @@ type_to_bit(const struct gl_context *ctx, GLenum type)
* Sets the VertexBinding field in the vertex attribute given by attribIndex.
*/
static void
-vertex_attrib_binding(struct gl_context *ctx, GLuint attribIndex,
+vertex_attrib_binding(struct gl_context *ctx,
+ struct gl_vertex_array_object *vao,
+ GLuint attribIndex,
GLuint bindingIndex)
{
- struct gl_vertex_array_object *vao = ctx->Array.VAO;
struct gl_vertex_attrib_array *array = &vao->VertexAttrib[attribIndex];
if (array->VertexBinding != bindingIndex) {
@@ -139,11 +155,12 @@ vertex_attrib_binding(struct gl_context *ctx, GLuint attribIndex,
* and sets the Offset and Stride fields.
*/
static void
-bind_vertex_buffer(struct gl_context *ctx, GLuint index,
+bind_vertex_buffer(struct gl_context *ctx,
+ struct gl_vertex_array_object *vao,
+ GLuint index,
struct gl_buffer_object *vbo,
GLintptr offset, GLsizei stride)
{
- struct gl_vertex_array_object *vao = ctx->Array.VAO;
struct gl_vertex_buffer_binding *binding = &vao->VertexBinding[index];
if (binding->BufferObj != vbo ||
@@ -167,10 +184,11 @@ bind_vertex_buffer(struct gl_context *ctx, GLuint index,
* given by bindingIndex.
*/
static void
-vertex_binding_divisor(struct gl_context *ctx, GLuint bindingIndex,
+vertex_binding_divisor(struct gl_context *ctx,
+ struct gl_vertex_array_object *vao,
+ GLuint bindingIndex,
GLuint divisor)
{
- struct gl_vertex_array_object *vao = ctx->Array.VAO;
struct gl_vertex_buffer_binding *binding =
&vao->VertexBinding[bindingIndex];
@@ -243,15 +261,17 @@ get_legal_types_mask(const struct gl_context *ctx)
* \param type Datatype of each component (GL_FLOAT, GL_INT, etc)
* \param normalized Whether integer types are converted to floats in [-1, 1]
* \param integer Integer-valued values (will not be normalized to [-1, 1])
+ * \param doubles Double values not reduced to floats
* \param relativeOffset Offset of the first element relative to the binding offset.
*/
static bool
update_array_format(struct gl_context *ctx,
const char *func,
+ struct gl_vertex_array_object *vao,
GLuint attrib, GLbitfield legalTypesMask,
GLint sizeMin, GLint sizeMax,
GLint size, GLenum type,
- GLboolean normalized, GLboolean integer,
+ GLboolean normalized, GLboolean integer, GLboolean doubles,
GLuint relativeOffset)
{
struct gl_vertex_attrib_array *array;
@@ -362,16 +382,17 @@ update_array_format(struct gl_context *ctx,
elementSize = _mesa_bytes_per_vertex_attrib(size, type);
assert(elementSize != -1);
- array = &ctx->Array.VAO->VertexAttrib[attrib];
+ array = &vao->VertexAttrib[attrib];
array->Size = size;
array->Type = type;
array->Format = format;
array->Normalized = normalized;
array->Integer = integer;
+ array->Doubles = doubles;
array->RelativeOffset = relativeOffset;
array->_ElementSize = elementSize;
- ctx->Array.VAO->NewArrays |= VERT_BIT(attrib);
+ vao->NewArrays |= VERT_BIT(attrib);
ctx->NewState |= _NEW_ARRAY;
return true;
@@ -392,6 +413,7 @@ update_array_format(struct gl_context *ctx,
* \param stride stride between elements, in elements
* \param normalized are integer types converted to floats in [-1, 1]?
* \param integer integer-valued values (will not be normalized to [-1,1])
+ * \param doubles Double values not reduced to floats
* \param ptr the address (or offset inside VBO) of the array data
*/
static void
@@ -400,7 +422,7 @@ update_array(struct gl_context *ctx,
GLuint attrib, GLbitfield legalTypesMask,
GLint sizeMin, GLint sizeMax,
GLint size, GLenum type, GLsizei stride,
- GLboolean normalized, GLboolean integer,
+ GLboolean normalized, GLboolean integer, GLboolean doubles,
const GLvoid *ptr)
{
struct gl_vertex_attrib_array *array;
@@ -453,13 +475,14 @@ update_array(struct gl_context *ctx,
return;
}
- if (!update_array_format(ctx, func, attrib, legalTypesMask, sizeMin,
- sizeMax, size, type, normalized, integer, 0)) {
+ if (!update_array_format(ctx, func, ctx->Array.VAO, attrib,
+ legalTypesMask, sizeMin, sizeMax,
+ size, type, normalized, integer, doubles, 0)) {
return;
}
/* Reset the vertex attrib binding */
- vertex_attrib_binding(ctx, attrib, attrib);
+ vertex_attrib_binding(ctx, ctx->Array.VAO, attrib, attrib);
/* The Stride and Ptr fields are not set by update_array_format() */
array = &ctx->Array.VAO->VertexAttrib[attrib];
@@ -468,7 +491,7 @@ update_array(struct gl_context *ctx,
/* Update the vertex buffer binding */
effectiveStride = stride != 0 ? stride : array->_ElementSize;
- bind_vertex_buffer(ctx, attrib, ctx->Array.ArrayBufferObj,
+ bind_vertex_buffer(ctx, ctx->Array.VAO, attrib, ctx->Array.ArrayBufferObj,
(GLintptr) ptr, effectiveStride);
}
@@ -488,7 +511,7 @@ _mesa_VertexPointer(GLint size, GLenum type, GLsizei stride, const GLvoid *ptr)
update_array(ctx, "glVertexPointer", VERT_ATTRIB_POS,
legalTypes, 2, 4,
- size, type, stride, GL_FALSE, GL_FALSE, ptr);
+ size, type, stride, GL_FALSE, GL_FALSE, GL_FALSE, ptr);
}
@@ -507,7 +530,7 @@ _mesa_NormalPointer(GLenum type, GLsizei stride, const GLvoid *ptr )
update_array(ctx, "glNormalPointer", VERT_ATTRIB_NORMAL,
legalTypes, 3, 3,
- 3, type, stride, GL_TRUE, GL_FALSE, ptr);
+ 3, type, stride, GL_TRUE, GL_FALSE, GL_FALSE, ptr);
}
@@ -529,7 +552,7 @@ _mesa_ColorPointer(GLint size, GLenum type, GLsizei stride, const GLvoid *ptr)
update_array(ctx, "glColorPointer", VERT_ATTRIB_COLOR0,
legalTypes, sizeMin, BGRA_OR_4,
- size, type, stride, GL_TRUE, GL_FALSE, ptr);
+ size, type, stride, GL_TRUE, GL_FALSE, GL_FALSE, ptr);
}
@@ -543,7 +566,7 @@ _mesa_FogCoordPointer(GLenum type, GLsizei stride, const GLvoid *ptr)
update_array(ctx, "glFogCoordPointer", VERT_ATTRIB_FOG,
legalTypes, 1, 1,
- 1, type, stride, GL_FALSE, GL_FALSE, ptr);
+ 1, type, stride, GL_FALSE, GL_FALSE, GL_FALSE, ptr);
}
@@ -558,7 +581,7 @@ _mesa_IndexPointer(GLenum type, GLsizei stride, const GLvoid *ptr)
update_array(ctx, "glIndexPointer", VERT_ATTRIB_COLOR_INDEX,
legalTypes, 1, 1,
- 1, type, stride, GL_FALSE, GL_FALSE, ptr);
+ 1, type, stride, GL_FALSE, GL_FALSE, GL_FALSE, ptr);
}
@@ -578,7 +601,7 @@ _mesa_SecondaryColorPointer(GLint size, GLenum type,
update_array(ctx, "glSecondaryColorPointer", VERT_ATTRIB_COLOR1,
legalTypes, 3, BGRA_OR_4,
- size, type, stride, GL_TRUE, GL_FALSE, ptr);
+ size, type, stride, GL_TRUE, GL_FALSE, GL_FALSE, ptr);
}
@@ -600,7 +623,7 @@ _mesa_TexCoordPointer(GLint size, GLenum type, GLsizei stride,
update_array(ctx, "glTexCoordPointer", VERT_ATTRIB_TEX(unit),
legalTypes, sizeMin, 4,
- size, type, stride, GL_FALSE, GL_FALSE,
+ size, type, stride, GL_FALSE, GL_FALSE, GL_FALSE,
ptr);
}
@@ -617,7 +640,7 @@ _mesa_EdgeFlagPointer(GLsizei stride, const GLvoid *ptr)
update_array(ctx, "glEdgeFlagPointer", VERT_ATTRIB_EDGEFLAG,
legalTypes, 1, 1,
- 1, GL_UNSIGNED_BYTE, stride, GL_FALSE, integer, ptr);
+ 1, GL_UNSIGNED_BYTE, stride, GL_FALSE, integer, GL_FALSE, ptr);
}
@@ -637,7 +660,7 @@ _mesa_PointSizePointerOES(GLenum type, GLsizei stride, const GLvoid *ptr)
update_array(ctx, "glPointSizePointer", VERT_ATTRIB_POINT_SIZE,
legalTypes, 1, 1,
- 1, type, stride, GL_FALSE, GL_FALSE, ptr);
+ 1, type, stride, GL_FALSE, GL_FALSE, GL_FALSE, ptr);
}
@@ -668,7 +691,7 @@ _mesa_VertexAttribPointer(GLuint index, GLint size, GLenum type,
update_array(ctx, "glVertexAttribPointer", VERT_ATTRIB_GENERIC(index),
legalTypes, 1, BGRA_OR_4,
- size, type, stride, normalized, GL_FALSE, ptr);
+ size, type, stride, normalized, GL_FALSE, GL_FALSE, ptr);
}
@@ -696,24 +719,36 @@ _mesa_VertexAttribIPointer(GLuint index, GLint size, GLenum type,
update_array(ctx, "glVertexAttribIPointer", VERT_ATTRIB_GENERIC(index),
legalTypes, 1, 4,
- size, type, stride, normalized, integer, ptr);
+ size, type, stride, normalized, integer, GL_FALSE, ptr);
}
-
-
void GLAPIENTRY
-_mesa_EnableVertexAttribArray(GLuint index)
+_mesa_VertexAttribLPointer(GLuint index, GLint size, GLenum type,
+ GLsizei stride, const GLvoid *ptr)
{
- struct gl_vertex_array_object *vao;
GET_CURRENT_CONTEXT(ctx);
-
+ const GLbitfield legalTypes = (DOUBLE_BIT);
if (index >= ctx->Const.Program[MESA_SHADER_VERTEX].MaxAttribs) {
- _mesa_error(ctx, GL_INVALID_VALUE,
- "glEnableVertexAttribArrayARB(index)");
+ _mesa_error(ctx, GL_INVALID_VALUE, "glVertexAttribLPointer(index)");
return;
}
- vao = ctx->Array.VAO;
+ update_array(ctx, "glVertexAttribLPointer", VERT_ATTRIB_GENERIC(index),
+ legalTypes, 1, 4,
+ size, type, stride, GL_TRUE, GL_FALSE, GL_TRUE, ptr);
+}
+
+
+static void
+enable_vertex_array_attrib(struct gl_context *ctx,
+ struct gl_vertex_array_object *vao,
+ GLuint index,
+ const char *func)
+{
+ if (index >= ctx->Const.Program[MESA_SHADER_VERTEX].MaxAttribs) {
+ _mesa_error(ctx, GL_INVALID_VALUE, "%s(index)", func);
+ return;
+ }
assert(VERT_ATTRIB_GENERIC(index) < ARRAY_SIZE(vao->VertexAttrib));
@@ -728,18 +763,52 @@ _mesa_EnableVertexAttribArray(GLuint index)
void GLAPIENTRY
-_mesa_DisableVertexAttribArray(GLuint index)
+_mesa_EnableVertexAttribArray(GLuint index)
{
- struct gl_vertex_array_object *vao;
GET_CURRENT_CONTEXT(ctx);
+ enable_vertex_array_attrib(ctx, ctx->Array.VAO, index,
+ "glEnableVertexAttribArray");
+}
- if (index >= ctx->Const.Program[MESA_SHADER_VERTEX].MaxAttribs) {
- _mesa_error(ctx, GL_INVALID_VALUE,
- "glDisableVertexAttribArrayARB(index)");
+
+void GLAPIENTRY
+_mesa_EnableVertexArrayAttrib(GLuint vaobj, GLuint index)
+{
+ GET_CURRENT_CONTEXT(ctx);
+ struct gl_vertex_array_object *vao;
+
+ if (!ctx->Extensions.ARB_direct_state_access) {
+ _mesa_error(ctx, GL_INVALID_OPERATION,
+ "glEnableVertexArrayAttrib(GL_ARB_direct_state_access "
+ "is not supported");
return;
}
- vao = ctx->Array.VAO;
+ /* The ARB_direct_state_access specification says:
+ *
+ * "An INVALID_OPERATION error is generated by EnableVertexArrayAttrib
+ * and DisableVertexArrayAttrib if <vaobj> is not
+ * [compatibility profile: zero or] the name of an existing vertex
+ * array object."
+ */
+ vao = _mesa_lookup_vao_err(ctx, vaobj, "glEnableVertexArrayAttrib");
+ if (!vao)
+ return;
+
+ enable_vertex_array_attrib(ctx, vao, index, "glEnableVertexArrayAttrib");
+}
+
+
+static void
+disable_vertex_array_attrib(struct gl_context *ctx,
+ struct gl_vertex_array_object *vao,
+ GLuint index,
+ const char *func)
+{
+ if (index >= ctx->Const.Program[MESA_SHADER_VERTEX].MaxAttribs) {
+ _mesa_error(ctx, GL_INVALID_VALUE, "%s(index)", func);
+ return;
+ }
assert(VERT_ATTRIB_GENERIC(index) < ARRAY_SIZE(vao->VertexAttrib));
@@ -753,16 +822,54 @@ _mesa_DisableVertexAttribArray(GLuint index)
}
+void GLAPIENTRY
+_mesa_DisableVertexAttribArray(GLuint index)
+{
+ GET_CURRENT_CONTEXT(ctx);
+ disable_vertex_array_attrib(ctx, ctx->Array.VAO, index,
+ "glDisableVertexAttribArray");
+}
+
+
+void GLAPIENTRY
+_mesa_DisableVertexArrayAttrib(GLuint vaobj, GLuint index)
+{
+ GET_CURRENT_CONTEXT(ctx);
+ struct gl_vertex_array_object *vao;
+
+ if (!ctx->Extensions.ARB_direct_state_access) {
+ _mesa_error(ctx, GL_INVALID_OPERATION,
+ "glDisableVertexArrayAttrib(GL_ARB_direct_state_access "
+ "is not supported");
+ return;
+ }
+
+ /* The ARB_direct_state_access specification says:
+ *
+ * "An INVALID_OPERATION error is generated by EnableVertexArrayAttrib
+ * and DisableVertexArrayAttrib if <vaobj> is not
+ * [compatibility profile: zero or] the name of an existing vertex
+ * array object."
+ */
+ vao = _mesa_lookup_vao_err(ctx, vaobj, "glDisableVertexArrayAttrib");
+ if (!vao)
+ return;
+
+ disable_vertex_array_attrib(ctx, vao, index, "glDisableVertexArrayAttrib");
+}
+
+
/**
* Return info for a vertex attribute array (no alias with legacy
* vertex attributes (pos, normal, color, etc)). This function does
* not handle the 4-element GL_CURRENT_VERTEX_ATTRIB_ARB query.
*/
static GLuint
-get_vertex_array_attrib(struct gl_context *ctx, GLuint index, GLenum pname,
- const char *caller)
+get_vertex_array_attrib(struct gl_context *ctx,
+ const struct gl_vertex_array_object *vao,
+ GLuint index, GLenum pname,
+ const char *caller)
{
- const struct gl_vertex_array_object *vao = ctx->Array.VAO;
const struct gl_vertex_attrib_array *array;
if (index >= ctx->Const.Program[MESA_SHADER_VERTEX].MaxAttribs) {
@@ -794,6 +901,11 @@ get_vertex_array_attrib(struct gl_context *ctx, GLuint index, GLenum pname,
return array->Integer;
}
goto error;
+ case GL_VERTEX_ATTRIB_ARRAY_LONG:
+ if (_mesa_is_desktop_gl(ctx)) {
+ return array->Doubles;
+ }
+ goto error;
case GL_VERTEX_ATTRIB_ARRAY_DIVISOR_ARB:
if ((_mesa_is_desktop_gl(ctx) && ctx->Extensions.ARB_instanced_arrays)
|| _mesa_is_gles3(ctx)) {
@@ -853,7 +965,8 @@ _mesa_GetVertexAttribfv(GLuint index, GLenum pname, GLfloat *params)
}
}
else {
- params[0] = (GLfloat) get_vertex_array_attrib(ctx, index, pname,
+ params[0] = (GLfloat) get_vertex_array_attrib(ctx, ctx->Array.VAO,
+ index, pname,
"glGetVertexAttribfv");
}
}
@@ -874,11 +987,32 @@ _mesa_GetVertexAttribdv(GLuint index, GLenum pname, GLdouble *params)
}
}
else {
- params[0] = (GLdouble) get_vertex_array_attrib(ctx, index, pname,
+ params[0] = (GLdouble) get_vertex_array_attrib(ctx, ctx->Array.VAO,
+ index, pname,
"glGetVertexAttribdv");
}
}
+void GLAPIENTRY
+_mesa_GetVertexAttribLdv(GLuint index, GLenum pname, GLdouble *params)
+{
+ GET_CURRENT_CONTEXT(ctx);
+
+ if (pname == GL_CURRENT_VERTEX_ATTRIB_ARB) {
+ const GLdouble *v = (const GLdouble *)get_current_attrib(ctx, index, "glGetVertexAttribLdv");
+ if (v != NULL) {
+ params[0] = v[0];
+ params[1] = v[1];
+ params[2] = v[2];
+ params[3] = v[3];
+ }
+ }
+ else {
+ params[0] = (GLdouble) get_vertex_array_attrib(ctx, ctx->Array.VAO,
+ index, pname,
+ "glGetVertexAttribLdv");
+ }
+}
void GLAPIENTRY
_mesa_GetVertexAttribiv(GLuint index, GLenum pname, GLint *params)
@@ -896,7 +1030,8 @@ _mesa_GetVertexAttribiv(GLuint index, GLenum pname, GLint *params)
}
}
else {
- params[0] = (GLint) get_vertex_array_attrib(ctx, index, pname,
+ params[0] = (GLint) get_vertex_array_attrib(ctx, ctx->Array.VAO,
+ index, pname,
"glGetVertexAttribiv");
}
}
@@ -916,7 +1051,8 @@ _mesa_GetVertexAttribIiv(GLuint index, GLenum pname, GLint *params)
}
}
else {
- params[0] = (GLint) get_vertex_array_attrib(ctx, index, pname,
+ params[0] = (GLint) get_vertex_array_attrib(ctx, ctx->Array.VAO,
+ index, pname,
"glGetVertexAttribIiv");
}
}
@@ -936,7 +1072,8 @@ _mesa_GetVertexAttribIuiv(GLuint index, GLenum pname, GLuint *params)
}
}
else {
- params[0] = get_vertex_array_attrib(ctx, index, pname,
+ params[0] = get_vertex_array_attrib(ctx, ctx->Array.VAO,
+ index, pname,
"glGetVertexAttribIuiv");
}
}
@@ -963,6 +1100,138 @@ _mesa_GetVertexAttribPointerv(GLuint index, GLenum pname, GLvoid **pointer)
}
+/** ARB_direct_state_access */
+void GLAPIENTRY
+_mesa_GetVertexArrayIndexediv(GLuint vaobj, GLuint index,
+ GLenum pname, GLint *params)
+{
+ GET_CURRENT_CONTEXT(ctx);
+ struct gl_vertex_array_object *vao;
+
+ if (!ctx->Extensions.ARB_direct_state_access) {
+ _mesa_error(ctx, GL_INVALID_OPERATION,
+ "glGetVertexArrayIndexediv(GL_ARB_direct_state_access "
+ "is not supported");
+ return;
+ }
+
+ /* The ARB_direct_state_access specification says:
+ *
+ * "An INVALID_OPERATION error is generated if <vaobj> is not
+ * [compatibility profile: zero or] the name of an existing
+ * vertex array object."
+ */
+ vao = _mesa_lookup_vao_err(ctx, vaobj, "glGetVertexArrayIndexediv");
+ if (!vao)
+ return;
+
+ /* The ARB_direct_state_access specification says:
+ *
+ * "For GetVertexArrayIndexediv, <pname> must be one of
+ * VERTEX_ATTRIB_ARRAY_ENABLED, VERTEX_ATTRIB_ARRAY_SIZE,
+ * VERTEX_ATTRIB_ARRAY_STRIDE, VERTEX_ATTRIB_ARRAY_TYPE,
+ * VERTEX_ATTRIB_ARRAY_NORMALIZED, VERTEX_ATTRIB_ARRAY_INTEGER,
+ * VERTEX_ATTRIB_ARRAY_LONG, VERTEX_ATTRIB_ARRAY_DIVISOR, or
+ * VERTEX_ATTRIB_RELATIVE_OFFSET."
+ *
+ * and:
+ *
+ * "Add GetVertexArrayIndexediv in 'Get Command' for
+ * VERTEX_ATTRIB_ARRAY_BUFFER_BINDING
+ * VERTEX_ATTRIB_BINDING,
+ * VERTEX_ATTRIB_RELATIVE_OFFSET,
+ * VERTEX_BINDING_OFFSET, and
+ * VERTEX_BINDING_STRIDE states"
+ *
+ * The only parameter name common to both lists is
+ * VERTEX_ATTRIB_RELATIVE_OFFSET. Also note that VERTEX_BINDING_BUFFER
+ * and VERTEX_BINDING_DIVISOR are missing from both lists. It seems
+ * pretty clear however that the intent is that it should be possible
+ * to query all vertex attrib and binding states that can be set with
+ * a DSA function.
+ */
+ switch (pname) {
+ case GL_VERTEX_BINDING_OFFSET:
+ params[0] = vao->VertexBinding[VERT_ATTRIB_GENERIC(index)].Offset;
+ break;
+ case GL_VERTEX_BINDING_STRIDE:
+ params[0] = vao->VertexBinding[VERT_ATTRIB_GENERIC(index)].Stride;
+ break;
+ case GL_VERTEX_BINDING_DIVISOR:
+ params[0] = vao->VertexBinding[VERT_ATTRIB_GENERIC(index)].InstanceDivisor;
+ break;
+ case GL_VERTEX_BINDING_BUFFER:
+ params[0] = vao->VertexBinding[VERT_ATTRIB_GENERIC(index)].BufferObj->Name;
+ break;
+ default:
+ params[0] = get_vertex_array_attrib(ctx, vao, index, pname,
+ "glGetVertexArrayIndexediv");
+ break;
+ }
+}
+
+
+void GLAPIENTRY
+_mesa_GetVertexArrayIndexed64iv(GLuint vaobj, GLuint index,
+ GLenum pname, GLint64 *params)
+{
+ GET_CURRENT_CONTEXT(ctx);
+ struct gl_vertex_array_object *vao;
+
+ if (!ctx->Extensions.ARB_direct_state_access) {
+ _mesa_error(ctx, GL_INVALID_OPERATION,
+ "glGetVertexArrayIndexed64iv(GL_ARB_direct_state_access "
+ "is not supported");
+ return;
+ }
+
+
+ /* The ARB_direct_state_access specification says:
+ *
+ * "An INVALID_OPERATION error is generated if <vaobj> is not
+ * [compatibility profile: zero or] the name of an existing
+ * vertex array object."
+ */
+ vao = _mesa_lookup_vao_err(ctx, vaobj, "glGetVertexArrayIndexed64iv");
+ if (!vao)
+ return;
+
+ /* The ARB_direct_state_access specification says:
+ *
+ * "For GetVertexArrayIndexed64iv, <pname> must be
+ * VERTEX_BINDING_OFFSET."
+ *
+ * and:
+ *
+ * "An INVALID_ENUM error is generated if <pname> is not one of
+ * the valid values listed above for the corresponding command."
+ */
+ if (pname != GL_VERTEX_BINDING_OFFSET) {
+ _mesa_error(ctx, GL_INVALID_ENUM, "glGetVertexArrayIndexed64iv("
+ "pname != GL_VERTEX_BINDING_OFFSET)");
+ return;
+ }
+
+ /* The ARB_direct_state_access specification says:
+ *
+ * "An INVALID_VALUE error is generated if <index> is greater than
+ * or equal to the value of MAX_VERTEX_ATTRIBS."
+ *
+ * Since the index refers to a buffer binding in this case, the intended
+ * limit must be MAX_VERTEX_ATTRIB_BINDINGS. Both limits are currently
+ * required to be the same, so in practice this doesn't matter.
+ */
+ if (index >= ctx->Const.MaxVertexAttribBindings) {
+ _mesa_error(ctx, GL_INVALID_VALUE, "glGetVertexArrayIndexed64iv("
+ "index %d >= the value of GL_MAX_VERTEX_ATTRIB_BINDINGS (%d))",
+ index, ctx->Const.MaxVertexAttribBindings);
+ return;
+ }
+
+ params[0] = vao->VertexBinding[VERT_ATTRIB_GENERIC(index)].Offset;
+}
+
+
void GLAPIENTRY
_mesa_VertexPointerEXT(GLint size, GLenum type, GLsizei stride,
GLsizei count, const GLvoid *ptr)
@@ -1337,6 +1606,7 @@ _mesa_VertexAttribDivisor(GLuint index, GLuint divisor)
GET_CURRENT_CONTEXT(ctx);
const GLuint genericIndex = VERT_ATTRIB_GENERIC(index);
+ struct gl_vertex_array_object * const vao = ctx->Array.VAO;
if (!ctx->Extensions.ARB_instanced_arrays) {
_mesa_error(ctx, GL_INVALID_OPERATION, "glVertexAttribDivisor()");
@@ -1349,7 +1619,7 @@ _mesa_VertexAttribDivisor(GLuint index, GLuint divisor)
return;
}
- assert(genericIndex < ARRAY_SIZE(ctx->Array.VAO->VertexAttrib));
+ assert(genericIndex < ARRAY_SIZE(vao->VertexAttrib));
/* The ARB_vertex_attrib_binding spec says:
*
@@ -1362,8 +1632,8 @@ _mesa_VertexAttribDivisor(GLuint index, GLuint divisor)
* VertexAttribBinding(index, index);
* VertexBindingDivisor(index, divisor);"
*/
- vertex_attrib_binding(ctx, genericIndex, genericIndex);
- vertex_binding_divisor(ctx, genericIndex, divisor);
+ vertex_attrib_binding(ctx, vao, genericIndex, genericIndex);
+ vertex_binding_divisor(ctx, vao, genericIndex, divisor);
}
@@ -1395,38 +1665,25 @@ _mesa_primitive_restart_index(const struct gl_context *ctx, GLenum ib_type)
/**
* GL_ARB_vertex_attrib_binding
*/
-void GLAPIENTRY
-_mesa_BindVertexBuffer(GLuint bindingIndex, GLuint buffer, GLintptr offset,
- GLsizei stride)
+static void
+vertex_array_vertex_buffer(struct gl_context *ctx, struct gl_vertex_array_object *vao,
+ GLuint bindingIndex, GLuint buffer, GLintptr offset,
+ GLsizei stride, const char *func)
{
- GET_CURRENT_CONTEXT(ctx);
- const struct gl_vertex_array_object *vao = ctx->Array.VAO;
struct gl_buffer_object *vbo;
ASSERT_OUTSIDE_BEGIN_END(ctx);
/* The ARB_vertex_attrib_binding spec says:
*
- * "An INVALID_OPERATION error is generated if no vertex array object
- * is bound."
- */
- if (ctx->API == API_OPENGL_CORE &&
- ctx->Array.VAO == ctx->Array.DefaultVAO) {
- _mesa_error(ctx, GL_INVALID_OPERATION,
- "glBindVertexBuffer(No array object bound)");
- return;
- }
-
- /* The ARB_vertex_attrib_binding spec says:
- *
* "An INVALID_VALUE error is generated if <bindingindex> is greater than
* the value of MAX_VERTEX_ATTRIB_BINDINGS."
*/
if (bindingIndex >= ctx->Const.MaxVertexAttribBindings) {
_mesa_error(ctx, GL_INVALID_VALUE,
- "glBindVertexBuffer(bindingindex=%u > "
+ "%s(bindingindex=%u > "
"GL_MAX_VERTEX_ATTRIB_BINDINGS)",
- bindingIndex);
+ func, bindingIndex);
return;
}
@@ -1437,21 +1694,21 @@ _mesa_BindVertexBuffer(GLuint bindingIndex, GLuint buffer, GLintptr offset,
*/
if (offset < 0) {
_mesa_error(ctx, GL_INVALID_VALUE,
- "glBindVertexBuffer(offset=%" PRId64 " < 0)",
- (int64_t) offset);
+ "%s(offset=%" PRId64 " < 0)",
+ func, (int64_t) offset);
return;
}
if (stride < 0) {
_mesa_error(ctx, GL_INVALID_VALUE,
- "glBindVertexBuffer(stride=%d < 0)", stride);
+ "%s(stride=%d < 0)", func, stride);
return;
}
if (ctx->API == API_OPENGL_CORE && ctx->Version >= 44 &&
stride > ctx->Const.MaxVertexAttribStride) {
- _mesa_error(ctx, GL_INVALID_VALUE, "glBindVertexBuffer(stride=%d > "
- "GL_MAX_VERTEX_ATTRIB_STRIDE)", stride);
+ _mesa_error(ctx, GL_INVALID_VALUE, "%s(stride=%d > "
+ "GL_MAX_VERTEX_ATTRIB_STRIDE)", func, stride);
return;
}
@@ -1471,7 +1728,7 @@ _mesa_BindVertexBuffer(GLuint bindingIndex, GLuint buffer, GLintptr offset,
* object references (automatically gen it).
*/
if (!_mesa_handle_bind_buffer_gen(ctx, GL_ARRAY_BUFFER, buffer,
- &vbo, "glBindVertexBuffer"))
+ &vbo, func))
return;
} else {
/* The ARB_vertex_attrib_binding spec says:
@@ -1482,33 +1739,75 @@ _mesa_BindVertexBuffer(GLuint bindingIndex, GLuint buffer, GLintptr offset,
vbo = ctx->Shared->NullBufferObj;
}
- bind_vertex_buffer(ctx, VERT_ATTRIB_GENERIC(bindingIndex),
+ bind_vertex_buffer(ctx, vao, VERT_ATTRIB_GENERIC(bindingIndex),
vbo, offset, stride);
}
void GLAPIENTRY
-_mesa_BindVertexBuffers(GLuint first, GLsizei count, const GLuint *buffers,
- const GLintptr *offsets, const GLsizei *strides)
+_mesa_BindVertexBuffer(GLuint bindingIndex, GLuint buffer, GLintptr offset,
+ GLsizei stride)
{
GET_CURRENT_CONTEXT(ctx);
- struct gl_vertex_array_object * const vao = ctx->Array.VAO;
- GLuint i;
-
- ASSERT_OUTSIDE_BEGIN_END(ctx);
/* The ARB_vertex_attrib_binding spec says:
*
- * "An INVALID_OPERATION error is generated if no
- * vertex array object is bound."
+ * "An INVALID_OPERATION error is generated if no vertex array object
+ * is bound."
*/
if (ctx->API == API_OPENGL_CORE &&
ctx->Array.VAO == ctx->Array.DefaultVAO) {
_mesa_error(ctx, GL_INVALID_OPERATION,
- "glBindVertexBuffers(No array object bound)");
+ "glBindVertexBuffer(No array object bound)");
return;
}
+ vertex_array_vertex_buffer(ctx, ctx->Array.VAO, bindingIndex,
+ buffer, offset, stride, "glBindVertexBuffer");
+}
+
+
+void GLAPIENTRY
+_mesa_VertexArrayVertexBuffer(GLuint vaobj, GLuint bindingIndex, GLuint buffer,
+ GLintptr offset, GLsizei stride)
+{
+ GET_CURRENT_CONTEXT(ctx);
+ struct gl_vertex_array_object *vao;
+
+ if (!ctx->Extensions.ARB_direct_state_access) {
+ _mesa_error(ctx, GL_INVALID_OPERATION,
+ "glVertexArrayVertexBuffer(GL_ARB_direct_state_access "
+ "is not supported");
+ return;
+ }
+
+ /* The ARB_direct_state_access specification says:
+ *
+ * "An INVALID_OPERATION error is generated by VertexArrayVertexBuffer
+ * if <vaobj> is not [compatibility profile: zero or] the name of an
+ * existing vertex array object."
+ */
+ vao = _mesa_lookup_vao_err(ctx, vaobj, "glVertexArrayVertexBuffer");
+ if (!vao)
+ return;
+
+ vertex_array_vertex_buffer(ctx, vao, bindingIndex,
+ buffer, offset, stride,
+ "glVertexArrayVertexBuffer");
+}
+
+
+static void
+vertex_array_vertex_buffers(struct gl_context *ctx,
+ struct gl_vertex_array_object *vao,
+ GLuint first, GLsizei count, const GLuint *buffers,
+ const GLintptr *offsets, const GLsizei *strides,
+ const char *func)
+{
+ GLuint i;
+
+ ASSERT_OUTSIDE_BEGIN_END(ctx);
+
/* The ARB_multi_bind spec says:
*
* "An INVALID_OPERATION error is generated if <first> + <count>
@@ -1516,9 +1815,9 @@ _mesa_BindVertexBuffers(GLuint first, GLsizei count, const GLuint *buffers,
*/
if (first + count > ctx->Const.MaxVertexAttribBindings) {
_mesa_error(ctx, GL_INVALID_OPERATION,
- "glBindVertexBuffers(first=%u + count=%d > the value of "
+ "%s(first=%u + count=%d > the value of "
"GL_MAX_VERTEX_ATTRIB_BINDINGS=%u)",
- first, count, ctx->Const.MaxVertexAttribBindings);
+ func, first, count, ctx->Const.MaxVertexAttribBindings);
return;
}
@@ -1535,7 +1834,8 @@ _mesa_BindVertexBuffers(GLuint first, GLsizei count, const GLuint *buffers,
struct gl_buffer_object *vbo = ctx->Shared->NullBufferObj;
for (i = 0; i < count; i++)
- bind_vertex_buffer(ctx, VERT_ATTRIB_GENERIC(first + i), vbo, 0, 16);
+ bind_vertex_buffer(ctx, vao, VERT_ATTRIB_GENERIC(first + i),
+ vbo, 0, 16);
return;
}
@@ -1571,23 +1871,23 @@ _mesa_BindVertexBuffers(GLuint first, GLsizei count, const GLuint *buffers,
*/
if (offsets[i] < 0) {
_mesa_error(ctx, GL_INVALID_VALUE,
- "glBindVertexBuffers(offsets[%u]=%" PRId64 " < 0)",
- i, (int64_t) offsets[i]);
+ "%s(offsets[%u]=%" PRId64 " < 0)",
+ func, i, (int64_t) offsets[i]);
continue;
}
if (strides[i] < 0) {
_mesa_error(ctx, GL_INVALID_VALUE,
- "glBindVertexBuffers(strides[%u]=%d < 0)",
- i, strides[i]);
+ "%s(strides[%u]=%d < 0)",
+ func, i, strides[i]);
continue;
}
if (ctx->API == API_OPENGL_CORE && ctx->Version >= 44 &&
strides[i] > ctx->Const.MaxVertexAttribStride) {
_mesa_error(ctx, GL_INVALID_VALUE,
- "glBindVertexBuffers(strides[%u]=%d > "
- "GL_MAX_VERTEX_ATTRIB_STRIDE)", i, strides[i]);
+ "%s(strides[%u]=%d > "
+ "GL_MAX_VERTEX_ATTRIB_STRIDE)", func, i, strides[i]);
continue;
}
@@ -1598,8 +1898,7 @@ _mesa_BindVertexBuffers(GLuint first, GLsizei count, const GLuint *buffers,
if (buffers[i] == binding->BufferObj->Name)
vbo = binding->BufferObj;
else
- vbo = _mesa_multi_bind_lookup_bufferobj(ctx, buffers, i,
- "glBindVertexBuffers");
+ vbo = _mesa_multi_bind_lookup_bufferobj(ctx, buffers, i, func);
if (!vbo)
continue;
@@ -1607,8 +1906,8 @@ _mesa_BindVertexBuffers(GLuint first, GLsizei count, const GLuint *buffers,
vbo = ctx->Shared->NullBufferObj;
}
- bind_vertex_buffer(ctx, VERT_ATTRIB_GENERIC(first + i), vbo,
- offsets[i], strides[i]);
+ bind_vertex_buffer(ctx, vao, VERT_ATTRIB_GENERIC(first + i),
+ vbo, offsets[i], strides[i]);
}
_mesa_end_bufferobj_lookups(ctx);
@@ -1616,65 +1915,68 @@ _mesa_BindVertexBuffers(GLuint first, GLsizei count, const GLuint *buffers,
void GLAPIENTRY
-_mesa_VertexAttribFormat(GLuint attribIndex, GLint size, GLenum type,
- GLboolean normalized, GLuint relativeOffset)
+_mesa_BindVertexBuffers(GLuint first, GLsizei count, const GLuint *buffers,
+ const GLintptr *offsets, const GLsizei *strides)
{
- const GLbitfield legalTypes = (BYTE_BIT | UNSIGNED_BYTE_BIT |
- SHORT_BIT | UNSIGNED_SHORT_BIT |
- INT_BIT | UNSIGNED_INT_BIT |
- HALF_BIT | FLOAT_BIT | DOUBLE_BIT |
- FIXED_GL_BIT |
- UNSIGNED_INT_2_10_10_10_REV_BIT |
- INT_2_10_10_10_REV_BIT |
- UNSIGNED_INT_10F_11F_11F_REV_BIT);
-
GET_CURRENT_CONTEXT(ctx);
- ASSERT_OUTSIDE_BEGIN_END(ctx);
/* The ARB_vertex_attrib_binding spec says:
*
- * "An INVALID_OPERATION error is generated under any of the following
- * conditions:
- * - if no vertex array object is currently bound (see section 2.10);
- * - ..."
+ * "An INVALID_OPERATION error is generated if no
+ * vertex array object is bound."
*/
if (ctx->API == API_OPENGL_CORE &&
ctx->Array.VAO == ctx->Array.DefaultVAO) {
_mesa_error(ctx, GL_INVALID_OPERATION,
- "glVertexAttribFormat(No array object bound)");
+ "glBindVertexBuffers(No array object bound)");
return;
}
- /* The ARB_vertex_attrib_binding spec says:
- *
- * "The error INVALID_VALUE is generated if index is greater than or equal
- * to the value of MAX_VERTEX_ATTRIBS."
- */
- if (attribIndex >= ctx->Const.Program[MESA_SHADER_VERTEX].MaxAttribs) {
- _mesa_error(ctx, GL_INVALID_VALUE,
- "glVertexAttribFormat(attribindex=%u > "
- "GL_MAX_VERTEX_ATTRIBS)",
- attribIndex);
+ vertex_array_vertex_buffers(ctx, ctx->Array.VAO, first, count,
+ buffers, offsets, strides,
+ "glBindVertexBuffers");
+}
+
+
+void GLAPIENTRY
+_mesa_VertexArrayVertexBuffers(GLuint vaobj, GLuint first, GLsizei count,
+ const GLuint *buffers,
+ const GLintptr *offsets, const GLsizei *strides)
+{
+ GET_CURRENT_CONTEXT(ctx);
+ struct gl_vertex_array_object *vao;
+
+ if (!ctx->Extensions.ARB_direct_state_access) {
+ _mesa_error(ctx, GL_INVALID_OPERATION,
+ "glVertexArrayVertexBuffers(GL_ARB_direct_state_access "
+ "is not supported");
return;
}
- FLUSH_VERTICES(ctx, 0);
- update_array_format(ctx, "glVertexAttribFormat",
- VERT_ATTRIB_GENERIC(attribIndex),
- legalTypes, 1, BGRA_OR_4, size, type, normalized,
- GL_FALSE, relativeOffset);
+ /* The ARB_direct_state_access specification says:
+ *
+ * "An INVALID_OPERATION error is generated by VertexArrayVertexBuffer
+ * if <vaobj> is not [compatibility profile: zero or] the name of an
+ * existing vertex array object."
+ */
+ vao = _mesa_lookup_vao_err(ctx, vaobj, "glVertexArrayVertexBuffers");
+ if (!vao)
+ return;
+
+ vertex_array_vertex_buffers(ctx, vao, first, count,
+ buffers, offsets, strides,
+ "glVertexArrayVertexBuffers");
}
-void GLAPIENTRY
-_mesa_VertexAttribIFormat(GLuint attribIndex, GLint size, GLenum type,
- GLuint relativeOffset)
+static void
+vertex_attrib_format(GLuint attribIndex, GLint size, GLenum type,
+ GLboolean normalized, GLboolean integer,
+ GLboolean doubles, GLbitfield legalTypes,
+ GLsizei maxSize, GLuint relativeOffset,
+ const char *func)
{
- const GLbitfield legalTypes = (BYTE_BIT | UNSIGNED_BYTE_BIT |
- SHORT_BIT | UNSIGNED_SHORT_BIT |
- INT_BIT | UNSIGNED_INT_BIT);
-
GET_CURRENT_CONTEXT(ctx);
ASSERT_OUTSIDE_BEGIN_END(ctx);
@@ -1684,33 +1986,59 @@ _mesa_VertexAttribIFormat(GLuint attribIndex, GLint size, GLenum type,
* conditions:
* - if no vertex array object is currently bound (see section 2.10);
* - ..."
+ *
+ * This error condition only applies to VertexAttribFormat and
+ * VertexAttribIFormat in the extension spec, but we assume that this
+ * is an oversight. In the OpenGL 4.3 (Core Profile) spec, it applies
+ * to all three functions.
*/
if (ctx->API == API_OPENGL_CORE &&
ctx->Array.VAO == ctx->Array.DefaultVAO) {
_mesa_error(ctx, GL_INVALID_OPERATION,
- "glVertexAttribIFormat(No array object bound)");
+ "%s(No array object bound)", func);
return;
}
/* The ARB_vertex_attrib_binding spec says:
*
- * "The error INVALID_VALUE is generated if index is greater than
- * or equal to the value of MAX_VERTEX_ATTRIBS."
+ * "The error INVALID_VALUE is generated if index is greater than or equal
+ * to the value of MAX_VERTEX_ATTRIBS."
*/
if (attribIndex >= ctx->Const.Program[MESA_SHADER_VERTEX].MaxAttribs) {
_mesa_error(ctx, GL_INVALID_VALUE,
- "glVertexAttribIFormat(attribindex=%u > "
+ "%s(attribindex=%u > "
"GL_MAX_VERTEX_ATTRIBS)",
- attribIndex);
+ func, attribIndex);
return;
}
FLUSH_VERTICES(ctx, 0);
- update_array_format(ctx, "glVertexAttribIFormat",
+ update_array_format(ctx, func, ctx->Array.VAO,
VERT_ATTRIB_GENERIC(attribIndex),
- legalTypes, 1, 4, size, type, GL_FALSE, GL_TRUE,
- relativeOffset);
+ legalTypes, 1, maxSize, size, type,
+ normalized, integer, doubles, relativeOffset);
+}
+
+
+void GLAPIENTRY
+_mesa_VertexAttribFormat(GLuint attribIndex, GLint size, GLenum type,
+ GLboolean normalized, GLuint relativeOffset)
+{
+ vertex_attrib_format(attribIndex, size, type, normalized,
+ GL_FALSE, GL_FALSE, ATTRIB_FORMAT_TYPES_MASK,
+ BGRA_OR_4, relativeOffset,
+ "glVertexAttribFormat");
+}
+
+
+void GLAPIENTRY
+_mesa_VertexAttribIFormat(GLuint attribIndex, GLint size, GLenum type,
+ GLuint relativeOffset)
+{
+ vertex_attrib_format(attribIndex, size, type, GL_FALSE,
+ GL_TRUE, GL_FALSE, ATTRIB_IFORMAT_TYPES_MASK, 4,
+ relativeOffset, "glVertexAttribIFormat");
}
@@ -1718,67 +2046,104 @@ void GLAPIENTRY
_mesa_VertexAttribLFormat(GLuint attribIndex, GLint size, GLenum type,
GLuint relativeOffset)
{
- const GLbitfield legalTypes = DOUBLE_BIT;
+ vertex_attrib_format(attribIndex, size, type, GL_FALSE, GL_FALSE,
+ GL_TRUE, ATTRIB_LFORMAT_TYPES_MASK, 4,
+ relativeOffset, "glVertexAttribLFormat");
+}
+
+static void
+vertex_array_attrib_format(GLuint vaobj, GLuint attribIndex, GLint size,
+ GLenum type, GLboolean normalized,
+ GLboolean integer, GLboolean doubles,
+ GLbitfield legalTypes, GLsizei maxSize,
+ GLuint relativeOffset, const char *func)
+{
GET_CURRENT_CONTEXT(ctx);
+ struct gl_vertex_array_object *vao;
+
+ if (!ctx->Extensions.ARB_direct_state_access) {
+ _mesa_error(ctx, GL_INVALID_OPERATION,
+ "%s(GL_ARB_direct_state_access is not supported", func);
+ return;
+ }
+
ASSERT_OUTSIDE_BEGIN_END(ctx);
- /* Page 298 of the PDF of the OpenGL 4.3 (Core Profile) spec says:
- *
- * "An INVALID_OPERATION error is generated under any of the following
- * conditions:
- * • if no vertex array object is currently bound (see section 10.4);
- * • ..."
+ /* The ARB_direct_state_access spec says:
*
- * This language is missing from the extension spec, but we assume
- * that this is an oversight.
+ * "An INVALID_OPERATION error is generated by VertexArrayAttrib*Format
+ * if <vaobj> is not [compatibility profile: zero or] the name of an
+ * existing vertex array object."
*/
- if (ctx->API == API_OPENGL_CORE &&
- ctx->Array.VAO == ctx->Array.DefaultVAO) {
- _mesa_error(ctx, GL_INVALID_OPERATION,
- "glVertexAttribLFormat(No array object bound)");
+ vao = _mesa_lookup_vao_err(ctx, vaobj, func);
+ if (!vao)
return;
- }
/* The ARB_vertex_attrib_binding spec says:
*
- * "The error INVALID_VALUE is generated if <attribindex> is greater than
- * or equal to the value of MAX_VERTEX_ATTRIBS."
+ * "The error INVALID_VALUE is generated if index is greater than or equal
+ * to the value of MAX_VERTEX_ATTRIBS."
*/
if (attribIndex >= ctx->Const.Program[MESA_SHADER_VERTEX].MaxAttribs) {
_mesa_error(ctx, GL_INVALID_VALUE,
- "glVertexAttribLFormat(attribindex=%u > "
- "GL_MAX_VERTEX_ATTRIBS)",
- attribIndex);
+ "%s(attribindex=%u > GL_MAX_VERTEX_ATTRIBS)",
+ func, attribIndex);
return;
}
FLUSH_VERTICES(ctx, 0);
- update_array_format(ctx, "glVertexAttribLFormat",
+ update_array_format(ctx, func, vao,
VERT_ATTRIB_GENERIC(attribIndex),
- legalTypes, 1, 4, size, type, GL_FALSE, GL_FALSE,
- relativeOffset);
+ legalTypes, 1, maxSize, size, type, normalized,
+ integer, doubles, relativeOffset);
}
void GLAPIENTRY
-_mesa_VertexAttribBinding(GLuint attribIndex, GLuint bindingIndex)
+_mesa_VertexArrayAttribFormat(GLuint vaobj, GLuint attribIndex, GLint size,
+ GLenum type, GLboolean normalized,
+ GLuint relativeOffset)
{
- GET_CURRENT_CONTEXT(ctx);
- ASSERT_OUTSIDE_BEGIN_END(ctx);
+ vertex_array_attrib_format(vaobj, attribIndex, size, type, normalized,
+ GL_FALSE, GL_FALSE, ATTRIB_FORMAT_TYPES_MASK,
+ BGRA_OR_4, relativeOffset,
+ "glVertexArrayAttribFormat");
+}
- /* The ARB_vertex_attrib_binding spec says:
- *
- * "An INVALID_OPERATION error is generated if no vertex array object
- * is bound."
- */
- if (ctx->API == API_OPENGL_CORE &&
- ctx->Array.VAO == ctx->Array.DefaultVAO) {
- _mesa_error(ctx, GL_INVALID_OPERATION,
- "glVertexAttribBinding(No array object bound)");
- return;
- }
+
+void GLAPIENTRY
+_mesa_VertexArrayAttribIFormat(GLuint vaobj, GLuint attribIndex,
+ GLint size, GLenum type,
+ GLuint relativeOffset)
+{
+ vertex_array_attrib_format(vaobj, attribIndex, size, type, GL_FALSE,
+ GL_TRUE, GL_FALSE, ATTRIB_IFORMAT_TYPES_MASK,
+ 4, relativeOffset,
+ "glVertexArrayAttribIFormat");
+}
+
+
+void GLAPIENTRY
+_mesa_VertexArrayAttribLFormat(GLuint vaobj, GLuint attribIndex,
+ GLint size, GLenum type,
+ GLuint relativeOffset)
+{
+ vertex_array_attrib_format(vaobj, attribIndex, size, type, GL_FALSE,
+ GL_FALSE, GL_TRUE, ATTRIB_LFORMAT_TYPES_MASK,
+ 4, relativeOffset,
+ "glVertexArrayAttribLFormat");
+}
+
+
+static void
+vertex_array_attrib_binding(struct gl_context *ctx,
+ struct gl_vertex_array_object *vao,
+ GLuint attribIndex, GLuint bindingIndex,
+ const char *func)
+{
+ ASSERT_OUTSIDE_BEGIN_END(ctx);
/* The ARB_vertex_attrib_binding spec says:
*
@@ -1789,38 +2154,32 @@ _mesa_VertexAttribBinding(GLuint attribIndex, GLuint bindingIndex)
*/
if (attribIndex >= ctx->Const.Program[MESA_SHADER_VERTEX].MaxAttribs) {
_mesa_error(ctx, GL_INVALID_VALUE,
- "glVertexAttribBinding(attribindex=%u >= "
+ "%s(attribindex=%u >= "
"GL_MAX_VERTEX_ATTRIBS)",
- attribIndex);
+ func, attribIndex);
return;
}
if (bindingIndex >= ctx->Const.MaxVertexAttribBindings) {
_mesa_error(ctx, GL_INVALID_VALUE,
- "glVertexAttribBinding(bindingindex=%u >= "
+ "%s(bindingindex=%u >= "
"GL_MAX_VERTEX_ATTRIB_BINDINGS)",
- bindingIndex);
+ func, bindingIndex);
return;
}
- assert(VERT_ATTRIB_GENERIC(attribIndex) <
- ARRAY_SIZE(ctx->Array.VAO->VertexAttrib));
+ assert(VERT_ATTRIB_GENERIC(attribIndex) < ARRAY_SIZE(vao->VertexAttrib));
- vertex_attrib_binding(ctx, VERT_ATTRIB_GENERIC(attribIndex),
+ vertex_attrib_binding(ctx, vao,
+ VERT_ATTRIB_GENERIC(attribIndex),
VERT_ATTRIB_GENERIC(bindingIndex));
}
void GLAPIENTRY
-_mesa_VertexBindingDivisor(GLuint bindingIndex, GLuint divisor)
+_mesa_VertexAttribBinding(GLuint attribIndex, GLuint bindingIndex)
{
GET_CURRENT_CONTEXT(ctx);
- ASSERT_OUTSIDE_BEGIN_END(ctx);
-
- if (!ctx->Extensions.ARB_instanced_arrays) {
- _mesa_error(ctx, GL_INVALID_OPERATION, "glVertexBindingDivisor()");
- return;
- }
/* The ARB_vertex_attrib_binding spec says:
*
@@ -1830,7 +2189,54 @@ _mesa_VertexBindingDivisor(GLuint bindingIndex, GLuint divisor)
if (ctx->API == API_OPENGL_CORE &&
ctx->Array.VAO == ctx->Array.DefaultVAO) {
_mesa_error(ctx, GL_INVALID_OPERATION,
- "glVertexBindingDivisor(No array object bound)");
+ "glVertexAttribBinding(No array object bound)");
+ return;
+ }
+
+ vertex_array_attrib_binding(ctx, ctx->Array.VAO,
+ attribIndex, bindingIndex,
+ "glVertexAttribBinding");
+}
+
+
+void GLAPIENTRY
+_mesa_VertexArrayAttribBinding(GLuint vaobj, GLuint attribIndex, GLuint bindingIndex)
+{
+ GET_CURRENT_CONTEXT(ctx);
+ struct gl_vertex_array_object *vao;
+
+ if (!ctx->Extensions.ARB_direct_state_access) {
+ _mesa_error(ctx, GL_INVALID_OPERATION,
+ "glVertexArrayAttribBinding(GL_ARB_direct_state_access "
+ "is not supported");
+ return;
+ }
+
+ /* The ARB_direct_state_access specification says:
+ *
+ * "An INVALID_OPERATION error is generated by VertexArrayAttribBinding
+ * if <vaobj> is not [compatibility profile: zero or] the name of an
+ * existing vertex array object."
+ */
+ vao = _mesa_lookup_vao_err(ctx, vaobj, "glVertexArrayAttribBinding");
+ if (!vao)
+ return;
+
+ vertex_array_attrib_binding(ctx, vao, attribIndex, bindingIndex,
+ "glVertexArrayAttribBinding");
+}
+
+
+static void
+vertex_array_binding_divisor(struct gl_context *ctx,
+ struct gl_vertex_array_object *vao,
+ GLuint bindingIndex, GLuint divisor,
+ const char *func)
+{
+ ASSERT_OUTSIDE_BEGIN_END(ctx);
+
+ if (!ctx->Extensions.ARB_instanced_arrays) {
+ _mesa_error(ctx, GL_INVALID_OPERATION, "%s()", func);
return;
}
@@ -1841,13 +2247,64 @@ _mesa_VertexBindingDivisor(GLuint bindingIndex, GLuint divisor)
*/
if (bindingIndex >= ctx->Const.MaxVertexAttribBindings) {
_mesa_error(ctx, GL_INVALID_VALUE,
- "glVertexBindingDivisor(bindingindex=%u > "
+ "%s(bindingindex=%u > "
"GL_MAX_VERTEX_ATTRIB_BINDINGS)",
- bindingIndex);
+ func, bindingIndex);
return;
}
- vertex_binding_divisor(ctx, VERT_ATTRIB_GENERIC(bindingIndex), divisor);
+ vertex_binding_divisor(ctx, vao, VERT_ATTRIB_GENERIC(bindingIndex), divisor);
+}
+
+
+void GLAPIENTRY
+_mesa_VertexBindingDivisor(GLuint bindingIndex, GLuint divisor)
+{
+ GET_CURRENT_CONTEXT(ctx);
+
+ /* The ARB_vertex_attrib_binding spec says:
+ *
+ * "An INVALID_OPERATION error is generated if no vertex array object
+ * is bound."
+ */
+ if (ctx->API == API_OPENGL_CORE &&
+ ctx->Array.VAO == ctx->Array.DefaultVAO) {
+ _mesa_error(ctx, GL_INVALID_OPERATION,
+ "glVertexBindingDivisor(No array object bound)");
+ return;
+ }
+
+ vertex_array_binding_divisor(ctx, ctx->Array.VAO,
+ bindingIndex, divisor,
+ "glVertexBindingDivisor");
+}
+
+
+void GLAPIENTRY
+_mesa_VertexArrayBindingDivisor(GLuint vaobj, GLuint bindingIndex, GLuint divisor)
+{
+ struct gl_vertex_array_object *vao;
+ GET_CURRENT_CONTEXT(ctx);
+
+ if (!ctx->Extensions.ARB_direct_state_access) {
+ _mesa_error(ctx, GL_INVALID_OPERATION,
+ "glVertexArrayBindingDivisor(GL_ARB_direct_state_access "
+ "is not supported");
+ return;
+ }
+
+ /* The ARB_direct_state_access specification says:
+ *
+ * "An INVALID_OPERATION error is generated by VertexArrayBindingDivisor
+ * if <vaobj> is not [compatibility profile: zero or] the name of an
+ * existing vertex array object."
+ */
+ vao = _mesa_lookup_vao_err(ctx, vaobj, "glVertexArrayBindingDivisor");
+ if (!vao)
+ return;
+
+ vertex_array_binding_divisor(ctx, vao, bindingIndex, divisor,
+ "glVertexArrayBindingDivisor");
}
@@ -1868,6 +2325,7 @@ _mesa_copy_client_array(struct gl_context *ctx,
dst->Enabled = src->Enabled;
dst->Normalized = src->Normalized;
dst->Integer = src->Integer;
+ dst->Doubles = src->Doubles;
dst->InstanceDivisor = src->InstanceDivisor;
dst->_ElementSize = src->_ElementSize;
_mesa_reference_buffer_object(ctx, &dst->BufferObj, src->BufferObj);
@@ -1885,6 +2343,7 @@ _mesa_copy_vertex_attrib_array(struct gl_context *ctx,
dst->RelativeOffset = src->RelativeOffset;
dst->Format = src->Format;
dst->Integer = src->Integer;
+ dst->Doubles = src->Doubles;
dst->Normalized = src->Normalized;
dst->Ptr = src->Ptr;
dst->Enabled = src->Enabled;
diff --git a/mesalib/src/mesa/main/varray.h b/mesalib/src/mesa/main/varray.h
index 4e4bd5f80..5583ed5a1 100644
--- a/mesalib/src/mesa/main/varray.h
+++ b/mesalib/src/mesa/main/varray.h
@@ -68,6 +68,7 @@ _mesa_update_client_array(struct gl_context *ctx,
dst->Enabled = src->Enabled;
dst->Normalized = src->Normalized;
dst->Integer = src->Integer;
+ dst->Doubles = src->Doubles;
dst->InstanceDivisor = binding->InstanceDivisor;
dst->_ElementSize = src->_ElementSize;
_mesa_reference_buffer_object(ctx, &dst->BufferObj, binding->BufferObj);
@@ -166,22 +167,34 @@ void GLAPIENTRY
_mesa_VertexAttribIPointer(GLuint index, GLint size, GLenum type,
GLsizei stride, const GLvoid *ptr);
+extern void GLAPIENTRY
+_mesa_VertexAttribLPointer(GLuint index, GLint size, GLenum type,
+ GLsizei stride, const GLvoid *pointer);
extern void GLAPIENTRY
_mesa_EnableVertexAttribArray(GLuint index);
extern void GLAPIENTRY
+_mesa_EnableVertexArrayAttrib(GLuint vaobj, GLuint index);
+
+
+extern void GLAPIENTRY
_mesa_DisableVertexAttribArray(GLuint index);
extern void GLAPIENTRY
-_mesa_GetVertexAttribdv(GLuint index, GLenum pname, GLdouble *params);
+_mesa_DisableVertexArrayAttrib(GLuint vaobj, GLuint index);
+
+extern void GLAPIENTRY
+_mesa_GetVertexAttribdv(GLuint index, GLenum pname, GLdouble *params);
extern void GLAPIENTRY
_mesa_GetVertexAttribfv(GLuint index, GLenum pname, GLfloat *params);
+extern void GLAPIENTRY
+_mesa_GetVertexAttribLdv(GLuint index, GLenum pname, GLdouble *params);
extern void GLAPIENTRY
_mesa_GetVertexAttribiv(GLuint index, GLenum pname, GLint *params);
@@ -199,6 +212,16 @@ extern void GLAPIENTRY
_mesa_GetVertexAttribPointerv(GLuint index, GLenum pname, GLvoid **pointer);
+void GLAPIENTRY
+_mesa_GetVertexArrayIndexediv(GLuint vaobj, GLuint index,
+ GLenum pname, GLint *param);
+
+
+void GLAPIENTRY
+_mesa_GetVertexArrayIndexed64iv(GLuint vaobj, GLuint index,
+ GLenum pname, GLint64 *param);
+
+
extern void GLAPIENTRY
_mesa_InterleavedArrays(GLenum format, GLsizei stride, const GLvoid *pointer);
@@ -278,27 +301,57 @@ _mesa_BindVertexBuffer(GLuint bindingIndex, GLuint buffer, GLintptr offset,
GLsizei stride);
extern void GLAPIENTRY
+_mesa_VertexArrayVertexBuffer(GLuint vaobj, GLuint bindingIndex, GLuint buffer,
+ GLintptr offset, GLsizei stride);
+
+extern void GLAPIENTRY
_mesa_BindVertexBuffers(GLuint first, GLsizei count, const GLuint *buffers,
const GLintptr *offsets, const GLsizei *strides);
extern void GLAPIENTRY
+_mesa_VertexArrayVertexBuffers(GLuint vaobj, GLuint first, GLsizei count,
+ const GLuint *buffers,
+ const GLintptr *offsets, const GLsizei *strides);
+
+extern void GLAPIENTRY
_mesa_VertexAttribFormat(GLuint attribIndex, GLint size, GLenum type,
GLboolean normalized, GLuint relativeOffset);
extern void GLAPIENTRY
+_mesa_VertexArrayAttribFormat(GLuint vaobj, GLuint attribIndex, GLint size,
+ GLenum type, GLboolean normalized,
+ GLuint relativeOffset);
+
+extern void GLAPIENTRY
_mesa_VertexAttribIFormat(GLuint attribIndex, GLint size, GLenum type,
GLuint relativeOffset);
extern void GLAPIENTRY
+_mesa_VertexArrayAttribIFormat(GLuint vaobj, GLuint attribIndex,
+ GLint size, GLenum type,
+ GLuint relativeOffset);
+
+extern void GLAPIENTRY
_mesa_VertexAttribLFormat(GLuint attribIndex, GLint size, GLenum type,
GLuint relativeOffset);
extern void GLAPIENTRY
+_mesa_VertexArrayAttribLFormat(GLuint vaobj, GLuint attribIndex,
+ GLint size, GLenum type,
+ GLuint relativeOffset);
+
+extern void GLAPIENTRY
_mesa_VertexAttribBinding(GLuint attribIndex, GLuint bindingIndex);
extern void GLAPIENTRY
+_mesa_VertexArrayAttribBinding(GLuint vaobj, GLuint attribIndex,
+ GLuint bindingIndex);
+
+extern void GLAPIENTRY
_mesa_VertexBindingDivisor(GLuint bindingIndex, GLuint divisor);
+extern void GLAPIENTRY
+_mesa_VertexArrayBindingDivisor(GLuint vaobj, GLuint bindingIndex, GLuint divisor);
extern void
_mesa_copy_client_array(struct gl_context *ctx,
diff --git a/mesalib/src/mesa/main/version.c b/mesalib/src/mesa/main/version.c
index 5b8ac0a5c..699a0de46 100644
--- a/mesalib/src/mesa/main/version.c
+++ b/mesalib/src/mesa/main/version.c
@@ -32,23 +32,16 @@
/**
* Scans 'string' to see if it ends with 'ending'.
*/
-static GLboolean
+static bool
check_for_ending(const char *string, const char *ending)
{
- int len1, len2;
+ const size_t len1 = strlen(string);
+ const size_t len2 = strlen(ending);
- len1 = strlen(string);
- len2 = strlen(ending);
+ if (len2 > len1)
+ return false;
- if (len2 > len1) {
- return GL_FALSE;
- }
-
- if (strcmp(string + (len1 - len2), ending) == 0) {
- return GL_TRUE;
- } else {
- return GL_FALSE;
- }
+ return strcmp(string + (len1 - len2), ending) == 0;
}
/**
@@ -58,15 +51,14 @@ check_for_ending(const char *string, const char *ending)
* fwd_context is only valid if version > 0
*/
static void
-get_gl_override(int *version, GLboolean *fwd_context,
- GLboolean *compat_context)
+get_gl_override(int *version, bool *fwd_context, bool *compat_context)
{
const char *env_var = "MESA_GL_VERSION_OVERRIDE";
const char *version_str;
int major, minor, n;
static int override_version = -1;
- static GLboolean fc_suffix = GL_FALSE;
- static GLboolean compat_suffix = GL_FALSE;
+ static bool fc_suffix = false;
+ static bool compat_suffix = false;
if (override_version < 0) {
override_version = 0;
@@ -78,12 +70,14 @@ get_gl_override(int *version, GLboolean *fwd_context,
n = sscanf(version_str, "%u.%u", &major, &minor);
if (n != 2) {
- fprintf(stderr, "error: invalid value for %s: %s\n", env_var, version_str);
+ fprintf(stderr, "error: invalid value for %s: %s\n",
+ env_var, version_str);
override_version = 0;
} else {
override_version = major * 10 + minor;
if (override_version < 30 && fc_suffix) {
- fprintf(stderr, "error: invalid value for %s: %s\n", env_var, version_str);
+ fprintf(stderr, "error: invalid value for %s: %s\n",
+ env_var, version_str);
}
}
}
@@ -134,7 +128,7 @@ _mesa_override_gl_version_contextless(struct gl_constants *consts,
gl_api *apiOut, GLuint *versionOut)
{
int version;
- GLboolean fwd_context, compat_context;
+ bool fwd_context, compat_context;
get_gl_override(&version, &fwd_context, &compat_context);
@@ -148,9 +142,9 @@ _mesa_override_gl_version_contextless(struct gl_constants *consts,
} else {
*apiOut = API_OPENGL_COMPAT;
}
- return GL_TRUE;
+ return true;
}
- return GL_FALSE;
+ return false;
}
void
@@ -171,7 +165,7 @@ int
_mesa_get_gl_version_override(void)
{
int version;
- GLboolean fwd_context, compat_context;
+ bool fwd_context, compat_context;
get_gl_override(&version, &fwd_context, &compat_context);
@@ -211,121 +205,121 @@ compute_version(const struct gl_extensions *extensions,
{
GLuint major, minor, version;
- const GLboolean ver_1_3 = (extensions->ARB_texture_border_clamp &&
- extensions->ARB_texture_cube_map &&
- extensions->ARB_texture_env_combine &&
- extensions->ARB_texture_env_dot3);
- const GLboolean ver_1_4 = (ver_1_3 &&
- extensions->ARB_depth_texture &&
- extensions->ARB_shadow &&
- extensions->ARB_texture_env_crossbar &&
- extensions->EXT_blend_color &&
- extensions->EXT_blend_func_separate &&
- extensions->EXT_blend_minmax &&
- extensions->EXT_point_parameters);
- const GLboolean ver_1_5 = (ver_1_4 &&
- extensions->ARB_occlusion_query);
- const GLboolean ver_2_0 = (ver_1_5 &&
- extensions->ARB_point_sprite &&
- extensions->ARB_vertex_shader &&
- extensions->ARB_fragment_shader &&
- extensions->ARB_texture_non_power_of_two &&
- extensions->EXT_blend_equation_separate &&
-
- /* Technically, 2.0 requires the functionality
- * of the EXT version. Enable 2.0 if either
- * extension is available, and assume that a
- * driver that only exposes the ATI extension
- * will fallback to software when necessary.
- */
- (extensions->EXT_stencil_two_side
- || extensions->ATI_separate_stencil));
- const GLboolean ver_2_1 = (ver_2_0 &&
- extensions->EXT_pixel_buffer_object &&
- extensions->EXT_texture_sRGB);
- const GLboolean ver_3_0 = (ver_2_1 &&
- consts->GLSLVersion >= 130 &&
- (consts->MaxSamples >= 4 || consts->FakeSWMSAA) &&
- (api == API_OPENGL_CORE ||
- extensions->ARB_color_buffer_float) &&
- extensions->ARB_depth_buffer_float &&
- extensions->ARB_half_float_vertex &&
- extensions->ARB_map_buffer_range &&
- extensions->ARB_shader_texture_lod &&
- extensions->ARB_texture_float &&
- extensions->ARB_texture_rg &&
- extensions->ARB_texture_compression_rgtc &&
- extensions->EXT_draw_buffers2 &&
- extensions->ARB_framebuffer_object &&
- extensions->EXT_framebuffer_sRGB &&
- extensions->EXT_packed_float &&
- extensions->EXT_texture_array &&
- extensions->EXT_texture_shared_exponent &&
- extensions->EXT_transform_feedback &&
- extensions->NV_conditional_render);
- const GLboolean ver_3_1 = (ver_3_0 &&
- consts->GLSLVersion >= 140 &&
- extensions->ARB_draw_instanced &&
- extensions->ARB_texture_buffer_object &&
- extensions->ARB_uniform_buffer_object &&
- extensions->EXT_texture_snorm &&
- extensions->NV_primitive_restart &&
- extensions->NV_texture_rectangle &&
- consts->Program[MESA_SHADER_VERTEX].MaxTextureImageUnits >= 16);
- const GLboolean ver_3_2 = (ver_3_1 &&
- consts->GLSLVersion >= 150 &&
- extensions->ARB_depth_clamp &&
- extensions->ARB_draw_elements_base_vertex &&
- extensions->ARB_fragment_coord_conventions &&
- extensions->EXT_provoking_vertex &&
- extensions->ARB_seamless_cube_map &&
- extensions->ARB_sync &&
- extensions->ARB_texture_multisample &&
- extensions->EXT_vertex_array_bgra);
- const GLboolean ver_3_3 = (ver_3_2 &&
- consts->GLSLVersion >= 330 &&
- extensions->ARB_blend_func_extended &&
- extensions->ARB_explicit_attrib_location &&
- extensions->ARB_instanced_arrays &&
- extensions->ARB_occlusion_query2 &&
- extensions->ARB_shader_bit_encoding &&
- extensions->ARB_texture_rgb10_a2ui &&
- extensions->ARB_timer_query &&
- extensions->ARB_vertex_type_2_10_10_10_rev &&
- extensions->EXT_texture_swizzle);
- /* ARB_sampler_objects is always enabled in mesa */
-
- const GLboolean ver_4_0 = (ver_3_3 &&
- consts->GLSLVersion >= 400 &&
- extensions->ARB_draw_buffers_blend &&
- extensions->ARB_draw_indirect &&
- extensions->ARB_gpu_shader5 &&
- extensions->ARB_gpu_shader_fp64 &&
- extensions->ARB_sample_shading &&
- 0/*extensions->ARB_shader_subroutine*/ &&
- extensions->ARB_tessellation_shader &&
- extensions->ARB_texture_buffer_object_rgb32 &&
- extensions->ARB_texture_cube_map_array &&
- extensions->ARB_texture_query_lod &&
- extensions->ARB_transform_feedback2 &&
- extensions->ARB_transform_feedback3);
- const GLboolean ver_4_1 = (ver_4_0 &&
- consts->GLSLVersion >= 410 &&
- extensions->ARB_ES2_compatibility &&
- extensions->ARB_shader_precision &&
- 0/*extensions->ARB_vertex_attrib_64bit*/ &&
- extensions->ARB_viewport_array);
- const GLboolean ver_4_2 = (ver_4_1 &&
- consts->GLSLVersion >= 420 &&
- extensions->ARB_base_instance &&
- extensions->ARB_conservative_depth &&
- extensions->ARB_internalformat_query &&
- extensions->ARB_shader_atomic_counters &&
- extensions->ARB_shader_image_load_store &&
- extensions->ARB_shading_language_420pack &&
- extensions->ARB_shading_language_packing &&
- extensions->ARB_texture_compression_bptc &&
- extensions->ARB_transform_feedback_instanced);
+ const bool ver_1_3 = (extensions->ARB_texture_border_clamp &&
+ extensions->ARB_texture_cube_map &&
+ extensions->ARB_texture_env_combine &&
+ extensions->ARB_texture_env_dot3);
+ const bool ver_1_4 = (ver_1_3 &&
+ extensions->ARB_depth_texture &&
+ extensions->ARB_shadow &&
+ extensions->ARB_texture_env_crossbar &&
+ extensions->EXT_blend_color &&
+ extensions->EXT_blend_func_separate &&
+ extensions->EXT_blend_minmax &&
+ extensions->EXT_point_parameters);
+ const bool ver_1_5 = (ver_1_4 &&
+ extensions->ARB_occlusion_query);
+ const bool ver_2_0 = (ver_1_5 &&
+ extensions->ARB_point_sprite &&
+ extensions->ARB_vertex_shader &&
+ extensions->ARB_fragment_shader &&
+ extensions->ARB_texture_non_power_of_two &&
+ extensions->EXT_blend_equation_separate &&
+
+ /* Technically, 2.0 requires the functionality of the
+ * EXT version. Enable 2.0 if either extension is
+ * available, and assume that a driver that only
+ * exposes the ATI extension will fallback to
+ * software when necessary.
+ */
+ (extensions->EXT_stencil_two_side
+ || extensions->ATI_separate_stencil));
+ const bool ver_2_1 = (ver_2_0 &&
+ extensions->EXT_pixel_buffer_object &&
+ extensions->EXT_texture_sRGB);
+ const bool ver_3_0 = (ver_2_1 &&
+ consts->GLSLVersion >= 130 &&
+ (consts->MaxSamples >= 4 || consts->FakeSWMSAA) &&
+ (api == API_OPENGL_CORE ||
+ extensions->ARB_color_buffer_float) &&
+ extensions->ARB_depth_buffer_float &&
+ extensions->ARB_half_float_vertex &&
+ extensions->ARB_map_buffer_range &&
+ extensions->ARB_shader_texture_lod &&
+ extensions->ARB_texture_float &&
+ extensions->ARB_texture_rg &&
+ extensions->ARB_texture_compression_rgtc &&
+ extensions->EXT_draw_buffers2 &&
+ extensions->ARB_framebuffer_object &&
+ extensions->EXT_framebuffer_sRGB &&
+ extensions->EXT_packed_float &&
+ extensions->EXT_texture_array &&
+ extensions->EXT_texture_shared_exponent &&
+ extensions->EXT_transform_feedback &&
+ extensions->NV_conditional_render);
+ const bool ver_3_1 = (ver_3_0 &&
+ consts->GLSLVersion >= 140 &&
+ extensions->ARB_draw_instanced &&
+ extensions->ARB_texture_buffer_object &&
+ extensions->ARB_uniform_buffer_object &&
+ extensions->EXT_texture_snorm &&
+ extensions->NV_primitive_restart &&
+ extensions->NV_texture_rectangle &&
+ consts->Program[MESA_SHADER_VERTEX].MaxTextureImageUnits >= 16);
+ const bool ver_3_2 = (ver_3_1 &&
+ consts->GLSLVersion >= 150 &&
+ extensions->ARB_depth_clamp &&
+ extensions->ARB_draw_elements_base_vertex &&
+ extensions->ARB_fragment_coord_conventions &&
+ extensions->EXT_provoking_vertex &&
+ extensions->ARB_seamless_cube_map &&
+ extensions->ARB_sync &&
+ extensions->ARB_texture_multisample &&
+ extensions->EXT_vertex_array_bgra);
+ const bool ver_3_3 = (ver_3_2 &&
+ consts->GLSLVersion >= 330 &&
+ extensions->ARB_blend_func_extended &&
+ extensions->ARB_explicit_attrib_location &&
+ extensions->ARB_instanced_arrays &&
+ extensions->ARB_occlusion_query2 &&
+ extensions->ARB_shader_bit_encoding &&
+ extensions->ARB_texture_rgb10_a2ui &&
+ extensions->ARB_timer_query &&
+ extensions->ARB_vertex_type_2_10_10_10_rev &&
+ extensions->EXT_texture_swizzle);
+ /* ARB_sampler_objects is always enabled in mesa */
+
+ const bool ver_4_0 = (ver_3_3 &&
+ consts->GLSLVersion >= 400 &&
+ extensions->ARB_draw_buffers_blend &&
+ extensions->ARB_draw_indirect &&
+ extensions->ARB_gpu_shader5 &&
+ extensions->ARB_gpu_shader_fp64 &&
+ extensions->ARB_sample_shading &&
+ false /*extensions->ARB_shader_subroutine*/ &&
+ extensions->ARB_tessellation_shader &&
+ extensions->ARB_texture_buffer_object_rgb32 &&
+ extensions->ARB_texture_cube_map_array &&
+ extensions->ARB_texture_query_lod &&
+ extensions->ARB_transform_feedback2 &&
+ extensions->ARB_transform_feedback3);
+ const bool ver_4_1 = (ver_4_0 &&
+ consts->GLSLVersion >= 410 &&
+ extensions->ARB_ES2_compatibility &&
+ extensions->ARB_shader_precision &&
+ extensions->ARB_vertex_attrib_64bit &&
+ extensions->ARB_viewport_array);
+ const bool ver_4_2 = (ver_4_1 &&
+ consts->GLSLVersion >= 420 &&
+ extensions->ARB_base_instance &&
+ extensions->ARB_conservative_depth &&
+ extensions->ARB_internalformat_query &&
+ extensions->ARB_shader_atomic_counters &&
+ extensions->ARB_shader_image_load_store &&
+ extensions->ARB_shading_language_420pack &&
+ extensions->ARB_shading_language_packing &&
+ extensions->ARB_texture_compression_bptc &&
+ extensions->ARB_transform_feedback_instanced);
if (ver_4_2) {
major = 4;
@@ -392,11 +386,11 @@ static GLuint
compute_version_es1(const struct gl_extensions *extensions)
{
/* OpenGL ES 1.0 is derived from OpenGL 1.3 */
- const GLboolean ver_1_0 = (extensions->ARB_texture_env_combine &&
- extensions->ARB_texture_env_dot3);
+ const bool ver_1_0 = (extensions->ARB_texture_env_combine &&
+ extensions->ARB_texture_env_dot3);
/* OpenGL ES 1.1 is derived from OpenGL 1.5 */
- const GLboolean ver_1_1 = (ver_1_0 &&
- extensions->EXT_point_parameters);
+ const bool ver_1_1 = (ver_1_0 &&
+ extensions->EXT_point_parameters);
if (ver_1_1) {
return 11;
@@ -411,34 +405,34 @@ static GLuint
compute_version_es2(const struct gl_extensions *extensions)
{
/* OpenGL ES 2.0 is derived from OpenGL 2.0 */
- const GLboolean ver_2_0 = (extensions->ARB_texture_cube_map &&
- extensions->EXT_blend_color &&
- extensions->EXT_blend_func_separate &&
- extensions->EXT_blend_minmax &&
- extensions->ARB_vertex_shader &&
- extensions->ARB_fragment_shader &&
- extensions->ARB_texture_non_power_of_two &&
- extensions->EXT_blend_equation_separate);
+ const bool ver_2_0 = (extensions->ARB_texture_cube_map &&
+ extensions->EXT_blend_color &&
+ extensions->EXT_blend_func_separate &&
+ extensions->EXT_blend_minmax &&
+ extensions->ARB_vertex_shader &&
+ extensions->ARB_fragment_shader &&
+ extensions->ARB_texture_non_power_of_two &&
+ extensions->EXT_blend_equation_separate);
/* FINISHME: This list isn't quite right. */
- const GLboolean ver_3_0 = (extensions->ARB_half_float_vertex &&
- extensions->ARB_internalformat_query &&
- extensions->ARB_map_buffer_range &&
- extensions->ARB_shader_texture_lod &&
- extensions->ARB_texture_float &&
- extensions->ARB_texture_rg &&
- extensions->ARB_depth_buffer_float &&
- extensions->EXT_draw_buffers2 &&
- /* extensions->ARB_framebuffer_object && */
- extensions->EXT_framebuffer_sRGB &&
- extensions->EXT_packed_float &&
- extensions->EXT_texture_array &&
- extensions->EXT_texture_shared_exponent &&
- extensions->EXT_transform_feedback &&
- extensions->ARB_draw_instanced &&
- extensions->ARB_uniform_buffer_object &&
- extensions->EXT_texture_snorm &&
- extensions->NV_primitive_restart &&
- extensions->OES_depth_texture_cube_map);
+ const bool ver_3_0 = (extensions->ARB_half_float_vertex &&
+ extensions->ARB_internalformat_query &&
+ extensions->ARB_map_buffer_range &&
+ extensions->ARB_shader_texture_lod &&
+ extensions->ARB_texture_float &&
+ extensions->ARB_texture_rg &&
+ extensions->ARB_depth_buffer_float &&
+ extensions->EXT_draw_buffers2 &&
+ /* extensions->ARB_framebuffer_object && */
+ extensions->EXT_framebuffer_sRGB &&
+ extensions->EXT_packed_float &&
+ extensions->EXT_texture_array &&
+ extensions->EXT_texture_shared_exponent &&
+ extensions->EXT_transform_feedback &&
+ extensions->ARB_draw_instanced &&
+ extensions->ARB_uniform_buffer_object &&
+ extensions->EXT_texture_snorm &&
+ extensions->NV_primitive_restart &&
+ extensions->OES_depth_texture_cube_map);
if (ver_3_0) {
return 30;
} else if (ver_2_0) {
diff --git a/mesalib/src/mesa/main/vtxfmt.c b/mesalib/src/mesa/main/vtxfmt.c
index fc0a01edf..d7ef7e278 100644
--- a/mesalib/src/mesa/main/vtxfmt.c
+++ b/mesalib/src/mesa/main/vtxfmt.c
@@ -206,6 +206,18 @@ install_vtxfmt(struct gl_context *ctx, struct _glapi_table *tab,
SET_VertexAttribP3uiv(tab, vfmt->VertexAttribP3uiv);
SET_VertexAttribP4uiv(tab, vfmt->VertexAttribP4uiv);
}
+
+ if (_mesa_is_desktop_gl(ctx)) {
+ SET_VertexAttribL1d(tab, vfmt->VertexAttribL1d);
+ SET_VertexAttribL2d(tab, vfmt->VertexAttribL2d);
+ SET_VertexAttribL3d(tab, vfmt->VertexAttribL3d);
+ SET_VertexAttribL4d(tab, vfmt->VertexAttribL4d);
+
+ SET_VertexAttribL1dv(tab, vfmt->VertexAttribL1dv);
+ SET_VertexAttribL2dv(tab, vfmt->VertexAttribL2dv);
+ SET_VertexAttribL3dv(tab, vfmt->VertexAttribL3dv);
+ SET_VertexAttribL4dv(tab, vfmt->VertexAttribL4dv);
+ }
}
diff --git a/mesalib/src/mesa/program/prog_statevars.c b/mesalib/src/mesa/program/prog_statevars.c
index 0c0c87faa..bdb335e4b 100644
--- a/mesalib/src/mesa/program/prog_statevars.c
+++ b/mesalib/src/mesa/program/prog_statevars.c
@@ -244,14 +244,14 @@ _mesa_fetch_state(struct gl_context *ctx, const gl_state_index state[],
{
/* state[1] is the texture unit */
const GLuint unit = (GLuint) state[1];
- if (_mesa_get_clamp_fragment_color(ctx))
+ if (_mesa_get_clamp_fragment_color(ctx, ctx->DrawBuffer))
COPY_4V(value, ctx->Texture.Unit[unit].EnvColor);
else
COPY_4V(value, ctx->Texture.Unit[unit].EnvColorUnclamped);
}
return;
case STATE_FOG_COLOR:
- if (_mesa_get_clamp_fragment_color(ctx))
+ if (_mesa_get_clamp_fragment_color(ctx, ctx->DrawBuffer))
COPY_4V(value, ctx->Fog.Color);
else
COPY_4V(value, ctx->Fog.ColorUnclamped);
diff --git a/mesalib/src/mesa/program/prog_to_nir.c b/mesalib/src/mesa/program/prog_to_nir.c
index ff3d9f3be..6c5fa51ec 100644
--- a/mesalib/src/mesa/program/prog_to_nir.c
+++ b/mesalib/src/mesa/program/prog_to_nir.c
@@ -710,7 +710,7 @@ static const nir_op op_trans[MAX_OPCODE] = {
[OPCODE_DST] = 0,
[OPCODE_END] = 0,
[OPCODE_EX2] = nir_op_fexp2,
- [OPCODE_EXP] = nir_op_fexp,
+ [OPCODE_EXP] = 0,
[OPCODE_FLR] = nir_op_ffloor,
[OPCODE_FRC] = nir_op_ffract,
[OPCODE_LG2] = nir_op_flog2,
diff --git a/mesalib/src/mesa/program/program.c b/mesalib/src/mesa/program/program.c
index 4f28e2a3b..fb61f4d36 100644
--- a/mesalib/src/mesa/program/program.c
+++ b/mesalib/src/mesa/program/program.c
@@ -102,6 +102,8 @@ _mesa_init_program(struct gl_context *ctx)
_mesa_reference_geomprog(ctx, &ctx->GeometryProgram.Current,
NULL);
+ _mesa_reference_compprog(ctx, &ctx->ComputeProgram.Current, NULL);
+
/* XXX probably move this stuff */
ctx->ATIFragmentShader.Enabled = GL_FALSE;
ctx->ATIFragmentShader.Current = ctx->Shared->DefaultFragmentShader;
@@ -121,6 +123,7 @@ _mesa_free_program_data(struct gl_context *ctx)
_mesa_reference_fragprog(ctx, &ctx->FragmentProgram.Current, NULL);
_mesa_delete_shader_cache(ctx, ctx->FragmentProgram.Cache);
_mesa_reference_geomprog(ctx, &ctx->GeometryProgram.Current, NULL);
+ _mesa_reference_compprog(ctx, &ctx->ComputeProgram.Current, NULL);
/* XXX probably move this stuff */
if (ctx->ATIFragmentShader.Current) {
diff --git a/mesalib/src/mesa/program/program.h b/mesalib/src/mesa/program/program.h
index 0b0d1ac6f..2d92ab2f1 100644
--- a/mesalib/src/mesa/program/program.h
+++ b/mesalib/src/mesa/program/program.h
@@ -138,6 +138,15 @@ _mesa_reference_geomprog(struct gl_context *ctx,
(struct gl_program *) prog);
}
+static inline void
+_mesa_reference_compprog(struct gl_context *ctx,
+ struct gl_compute_program **ptr,
+ struct gl_compute_program *prog)
+{
+ _mesa_reference_program(ctx, (struct gl_program **) ptr,
+ (struct gl_program *) prog);
+}
+
extern struct gl_program *
_mesa_clone_program(struct gl_context *ctx, const struct gl_program *prog);
@@ -276,6 +285,19 @@ gl_geometry_program_const(const struct gl_program *prog)
}
+static inline struct gl_compute_program *
+gl_compute_program(struct gl_program *prog)
+{
+ return (struct gl_compute_program *) prog;
+}
+
+static inline const struct gl_compute_program *
+gl_compute_program_const(const struct gl_program *prog)
+{
+ return (const struct gl_compute_program *) prog;
+}
+
+
#ifdef __cplusplus
} /* extern "C" */
#endif
diff --git a/mesalib/src/mesa/state_tracker/st_atom_array.c b/mesalib/src/mesa/state_tracker/st_atom_array.c
index d4fb8b862..56b8019a3 100644
--- a/mesalib/src/mesa/state_tracker/st_atom_array.c
+++ b/mesalib/src/mesa/state_tracker/st_atom_array.c
@@ -44,7 +44,6 @@
#include "cso_cache/cso_context.h"
#include "util/u_math.h"
-
#include "main/bufferobj.h"
#include "main/glformats.h"
@@ -311,6 +310,18 @@ st_pipe_vertex_format(GLenum type, GLuint size, GLenum format,
return PIPE_FORMAT_NONE; /* silence compiler warning */
}
+static const struct gl_client_array *
+get_client_array(const struct st_vertex_program *vp,
+ const struct gl_client_array **arrays,
+ int attr)
+{
+ const GLuint mesaAttr = vp->index_to_input[attr];
+ /* st_program uses 0xffffffff to denote a double placeholder attribute */
+ if (mesaAttr == ST_DOUBLE_ATTRIB_PLACEHOLDER)
+ return NULL;
+ return arrays[mesaAttr];
+}
+
/**
* Examine the active arrays to determine if we have interleaved
* vertex arrays all living in one VBO, or all living in user space.
@@ -327,11 +338,16 @@ is_interleaved_arrays(const struct st_vertex_program *vp,
GLboolean userSpaceBuffer = GL_FALSE;
for (attr = 0; attr < vpv->num_inputs; attr++) {
- const GLuint mesaAttr = vp->index_to_input[attr];
- const struct gl_client_array *array = arrays[mesaAttr];
- const struct gl_buffer_object *bufObj = array->BufferObj;
- const GLsizei stride = array->StrideB; /* in bytes */
+ const struct gl_client_array *array;
+ const struct gl_buffer_object *bufObj;
+ GLsizei stride;
+
+ array = get_client_array(vp, arrays, attr);
+ if (!array)
+ continue;
+ stride = array->StrideB; /* in bytes */
+ bufObj = array->BufferObj;
if (attr == 0) {
/* save info about the first array */
firstStride = stride;
@@ -358,6 +374,55 @@ is_interleaved_arrays(const struct st_vertex_program *vp,
return GL_TRUE;
}
+static void init_velement(struct pipe_vertex_element *velement,
+ int src_offset, int format,
+ int instance_divisor, int vbo_index)
+{
+ velement->src_offset = src_offset;
+ velement->src_format = format;
+ velement->instance_divisor = instance_divisor;
+ velement->vertex_buffer_index = vbo_index;
+ assert(velement->src_format);
+}
+
+static void init_velement_lowered(struct st_context *st,
+ struct pipe_vertex_element *velements,
+ int src_offset, int format,
+ int instance_divisor, int vbo_index,
+ int nr_components, GLboolean doubles,
+ GLuint *attr_idx)
+{
+ int idx = *attr_idx;
+ if (doubles) {
+ int lower_format;
+
+ if (nr_components == 1)
+ lower_format = PIPE_FORMAT_R32G32_UINT;
+ else if (nr_components >= 2)
+ lower_format = PIPE_FORMAT_R32G32B32A32_UINT;
+
+ init_velement(&velements[idx], src_offset,
+ lower_format, instance_divisor, vbo_index);
+ idx++;
+
+ if (nr_components > 2) {
+ if (nr_components == 3)
+ lower_format = PIPE_FORMAT_R32G32_UINT;
+ else if (nr_components >= 4)
+ lower_format = PIPE_FORMAT_R32G32B32A32_UINT;
+
+ init_velement(&velements[idx], src_offset + 4 * sizeof(float),
+ lower_format, instance_divisor, vbo_index);
+ idx++;
+ }
+ } else {
+ init_velement(&velements[idx], src_offset,
+ format, instance_divisor, vbo_index);
+ idx++;
+ }
+ *attr_idx = idx;
+}
+
/**
* Set up for drawing interleaved arrays that all live in one VBO
* or all live in user space.
@@ -365,13 +430,15 @@ is_interleaved_arrays(const struct st_vertex_program *vp,
* \param velements returns vertex element info
*/
static boolean
-setup_interleaved_attribs(const struct st_vertex_program *vp,
+setup_interleaved_attribs(struct st_context *st,
+ const struct st_vertex_program *vp,
const struct st_vp_variant *vpv,
const struct gl_client_array **arrays,
struct pipe_vertex_buffer *vbuffer,
- struct pipe_vertex_element velements[])
+ struct pipe_vertex_element velements[],
+ unsigned *num_velements)
{
- GLuint attr;
+ GLuint attr, attr_idx;
const GLubyte *low_addr = NULL;
GLboolean usingVBO; /* all arrays in a VBO? */
struct gl_buffer_object *bufobj;
@@ -381,8 +448,10 @@ setup_interleaved_attribs(const struct st_vertex_program *vp,
* Init bufobj and stride.
*/
if (vpv->num_inputs) {
- const GLuint mesaAttr0 = vp->index_to_input[0];
- const struct gl_client_array *array = arrays[mesaAttr0];
+ const struct gl_client_array *array;
+
+ array = get_client_array(vp, arrays, 0);
+ assert(array);
/* Since we're doing interleaved arrays, we know there'll be at most
* one buffer object and the stride will be the same for all arrays.
@@ -394,7 +463,11 @@ setup_interleaved_attribs(const struct st_vertex_program *vp,
low_addr = arrays[vp->index_to_input[0]]->Ptr;
for (attr = 1; attr < vpv->num_inputs; attr++) {
- const GLubyte *start = arrays[vp->index_to_input[attr]]->Ptr;
+ const GLubyte *start;
+ array = get_client_array(vp, arrays, attr);
+ if (!array)
+ continue;
+ start = array->Ptr;
low_addr = MIN2(low_addr, start);
}
}
@@ -408,25 +481,33 @@ setup_interleaved_attribs(const struct st_vertex_program *vp,
/* are the arrays in user space? */
usingVBO = _mesa_is_bufferobj(bufobj);
+ attr_idx = 0;
for (attr = 0; attr < vpv->num_inputs; attr++) {
- const GLuint mesaAttr = vp->index_to_input[attr];
- const struct gl_client_array *array = arrays[mesaAttr];
- unsigned src_offset = (unsigned) (array->Ptr - low_addr);
+ const struct gl_client_array *array;
+ unsigned src_offset;
+ unsigned src_format;
+
+ array = get_client_array(vp, arrays, attr);
+ if (!array)
+ continue;
+ src_offset = (unsigned) (array->Ptr - low_addr);
assert(array->_ElementSize ==
_mesa_bytes_per_vertex_attrib(array->Size, array->Type));
- velements[attr].src_offset = src_offset;
- velements[attr].instance_divisor = array->InstanceDivisor;
- velements[attr].vertex_buffer_index = 0;
- velements[attr].src_format = st_pipe_vertex_format(array->Type,
- array->Size,
- array->Format,
- array->Normalized,
- array->Integer);
- assert(velements[attr].src_format);
+ src_format = st_pipe_vertex_format(array->Type,
+ array->Size,
+ array->Format,
+ array->Normalized,
+ array->Integer);
+
+ init_velement_lowered(st, velements, src_offset, src_format,
+ array->InstanceDivisor, 0,
+ array->Size, array->Doubles, &attr_idx);
}
+ *num_velements = attr_idx;
+
/*
* Return the vbuffer info and setup user-space attrib info, if needed.
*/
@@ -472,17 +553,25 @@ setup_non_interleaved_attribs(struct st_context *st,
const struct st_vp_variant *vpv,
const struct gl_client_array **arrays,
struct pipe_vertex_buffer vbuffer[],
- struct pipe_vertex_element velements[])
+ struct pipe_vertex_element velements[],
+ unsigned *num_velements)
{
struct gl_context *ctx = st->ctx;
- GLuint attr;
+ GLuint attr, attr_idx = 0;
for (attr = 0; attr < vpv->num_inputs; attr++) {
const GLuint mesaAttr = vp->index_to_input[attr];
- const struct gl_client_array *array = arrays[mesaAttr];
- struct gl_buffer_object *bufobj = array->BufferObj;
- GLsizei stride = array->StrideB;
+ const struct gl_client_array *array;
+ struct gl_buffer_object *bufobj;
+ GLsizei stride;
+ unsigned src_format;
+ array = get_client_array(vp, arrays, attr);
+ if (!array)
+ continue;
+
+ stride = array->StrideB;
+ bufobj = array->BufferObj;
assert(array->_ElementSize ==
_mesa_bytes_per_vertex_attrib(array->Size, array->Type));
@@ -524,16 +613,19 @@ setup_non_interleaved_attribs(struct st_context *st,
/* common-case setup */
vbuffer[attr].stride = stride; /* in bytes */
- velements[attr].src_offset = 0;
- velements[attr].instance_divisor = array->InstanceDivisor;
- velements[attr].vertex_buffer_index = attr;
- velements[attr].src_format = st_pipe_vertex_format(array->Type,
- array->Size,
- array->Format,
- array->Normalized,
- array->Integer);
- assert(velements[attr].src_format);
+ src_format = st_pipe_vertex_format(array->Type,
+ array->Size,
+ array->Format,
+ array->Normalized,
+ array->Integer);
+
+ init_velement_lowered(st, velements, 0, src_format,
+ array->InstanceDivisor, attr,
+ array->Size, array->Doubles, &attr_idx);
+
}
+
+ *num_velements = attr_idx;
return TRUE;
}
@@ -563,25 +655,23 @@ static void update_array(struct st_context *st)
* Setup the vbuffer[] and velements[] arrays.
*/
if (is_interleaved_arrays(vp, vpv, arrays)) {
- if (!setup_interleaved_attribs(vp, vpv, arrays, vbuffer, velements)) {
+ if (!setup_interleaved_attribs(st, vp, vpv, arrays, vbuffer, velements, &num_velements)) {
st->vertex_array_out_of_memory = TRUE;
return;
}
num_vbuffers = 1;
- num_velements = vpv->num_inputs;
if (num_velements == 0)
num_vbuffers = 0;
}
else {
if (!setup_non_interleaved_attribs(st, vp, vpv, arrays, vbuffer,
- velements)) {
+ velements, &num_velements)) {
st->vertex_array_out_of_memory = TRUE;
return;
}
num_vbuffers = vpv->num_inputs;
- num_velements = vpv->num_inputs;
}
cso_set_vertex_buffers(st->cso_context, 0, num_vbuffers, vbuffer);
diff --git a/mesalib/src/mesa/state_tracker/st_atom_framebuffer.c b/mesalib/src/mesa/state_tracker/st_atom_framebuffer.c
index b195c55b3..ae883a253 100644
--- a/mesalib/src/mesa/state_tracker/st_atom_framebuffer.c
+++ b/mesalib/src/mesa/state_tracker/st_atom_framebuffer.c
@@ -134,7 +134,10 @@ update_framebuffer_state( struct st_context *st )
else {
strb = st_renderbuffer(fb->Attachment[BUFFER_STENCIL].Renderbuffer);
if (strb) {
- assert(strb->surface);
+ if (strb->is_rtt) {
+ /* rendering to a GL texture, may have to update surface */
+ st_update_renderbuffer_surface(st, strb);
+ }
pipe_surface_reference(&framebuffer->zsbuf, strb->surface);
update_framebuffer_size(framebuffer, strb->surface);
}
diff --git a/mesalib/src/mesa/state_tracker/st_cb_fbo.c b/mesalib/src/mesa/state_tracker/st_cb_fbo.c
index 296ea1e0d..0399eef72 100644
--- a/mesalib/src/mesa/state_tracker/st_cb_fbo.c
+++ b/mesalib/src/mesa/state_tracker/st_cb_fbo.c
@@ -842,7 +842,7 @@ void st_init_fbo_functions(struct dd_function_table *functions)
functions->NewFramebuffer = st_new_framebuffer;
functions->NewRenderbuffer = st_new_renderbuffer;
functions->BindFramebuffer = st_bind_framebuffer;
- functions->FramebufferRenderbuffer = _mesa_framebuffer_renderbuffer;
+ functions->FramebufferRenderbuffer = _mesa_FramebufferRenderbuffer_sw;
functions->RenderTexture = st_render_texture;
functions->FinishRenderTexture = st_finish_render_texture;
functions->ValidateFramebuffer = st_validate_framebuffer;
diff --git a/mesalib/src/mesa/state_tracker/st_cb_flush.c b/mesalib/src/mesa/state_tracker/st_cb_flush.c
index ca51eeee3..82affd2de 100644
--- a/mesalib/src/mesa/state_tracker/st_cb_flush.c
+++ b/mesalib/src/mesa/state_tracker/st_cb_flush.c
@@ -141,11 +141,44 @@ static void st_glFinish(struct gl_context *ctx)
}
-void st_init_flush_functions(struct dd_function_table *functions)
+/**
+ * Query information about GPU resets observed by this context
+ *
+ * Called via \c dd_function_table::GetGraphicsResetStatus.
+ */
+static GLenum
+st_get_graphics_reset_status(struct gl_context *ctx)
+{
+ struct st_context *st = st_context(ctx);
+ enum pipe_reset_status status;
+
+ status = st->pipe->get_device_reset_status(st->pipe);
+
+ switch (status) {
+ case PIPE_NO_RESET:
+ return GL_NO_ERROR;
+ case PIPE_GUILTY_CONTEXT_RESET:
+ return GL_GUILTY_CONTEXT_RESET_ARB;
+ case PIPE_INNOCENT_CONTEXT_RESET:
+ return GL_INNOCENT_CONTEXT_RESET_ARB;
+ case PIPE_UNKNOWN_CONTEXT_RESET:
+ return GL_UNKNOWN_CONTEXT_RESET_ARB;
+ default:
+ assert(0);
+ return GL_NO_ERROR;
+ }
+}
+
+
+void st_init_flush_functions(struct pipe_screen *screen,
+ struct dd_function_table *functions)
{
functions->Flush = st_glFlush;
functions->Finish = st_glFinish;
+ if (screen->get_param(screen, PIPE_CAP_DEVICE_RESET_STATUS_QUERY))
+ functions->GetGraphicsResetStatus = st_get_graphics_reset_status;
+
/* Windows opengl32.dll calls glFinish prior to every swapbuffers.
* This is unnecessary and degrades performance. Luckily we have some
* scope to work around this, as the externally-visible behaviour of
diff --git a/mesalib/src/mesa/state_tracker/st_cb_flush.h b/mesalib/src/mesa/state_tracker/st_cb_flush.h
index 84ffc63ae..f92dcd56b 100644
--- a/mesalib/src/mesa/state_tracker/st_cb_flush.h
+++ b/mesalib/src/mesa/state_tracker/st_cb_flush.h
@@ -37,7 +37,8 @@ struct pipe_fence_handle;
struct st_context;
extern void
-st_init_flush_functions(struct dd_function_table *functions);
+st_init_flush_functions(struct pipe_screen *screen,
+ struct dd_function_table *functions);
extern void
st_flush(struct st_context *st,
diff --git a/mesalib/src/mesa/state_tracker/st_cb_perfmon.c b/mesalib/src/mesa/state_tracker/st_cb_perfmon.c
new file mode 100644
index 000000000..1bb5be397
--- /dev/null
+++ b/mesalib/src/mesa/state_tracker/st_cb_perfmon.c
@@ -0,0 +1,425 @@
+/*
+ * Copyright (C) 2013 Christoph Bumiller
+ * Copyright (C) 2015 Samuel Pitoiset
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+/**
+ * Performance monitoring counters interface to gallium.
+ */
+
+#include "st_debug.h"
+#include "st_context.h"
+#include "st_cb_bitmap.h"
+#include "st_cb_perfmon.h"
+
+#include "util/bitset.h"
+
+#include "pipe/p_context.h"
+#include "pipe/p_screen.h"
+#include "util/u_memory.h"
+
+/**
+ * Return a PIPE_QUERY_x type >= PIPE_QUERY_DRIVER_SPECIFIC, or -1 if
+ * the driver-specific query doesn't exist.
+ */
+static int
+find_query_type(struct pipe_screen *screen, const char *name)
+{
+ int num_queries;
+ int type = -1;
+ int i;
+
+ num_queries = screen->get_driver_query_info(screen, 0, NULL);
+ if (!num_queries)
+ return type;
+
+ for (i = 0; i < num_queries; i++) {
+ struct pipe_driver_query_info info;
+
+ if (!screen->get_driver_query_info(screen, i, &info))
+ continue;
+
+ if (!strncmp(info.name, name, strlen(name))) {
+ type = info.query_type;
+ break;
+ }
+ }
+ return type;
+}
+
+/**
+ * Return TRUE if the underlying driver expose GPU counters.
+ */
+static bool
+has_gpu_counters(struct pipe_screen *screen)
+{
+ int num_groups, gid;
+
+ num_groups = screen->get_driver_query_group_info(screen, 0, NULL);
+ for (gid = 0; gid < num_groups; gid++) {
+ struct pipe_driver_query_group_info group_info;
+
+ if (!screen->get_driver_query_group_info(screen, gid, &group_info))
+ continue;
+
+ if (group_info.type == PIPE_DRIVER_QUERY_GROUP_TYPE_GPU)
+ return true;
+ }
+ return false;
+}
+
+static bool
+init_perf_monitor(struct gl_context *ctx, struct gl_perf_monitor_object *m)
+{
+ struct st_perf_monitor_object *stm = st_perf_monitor_object(m);
+ struct pipe_screen *screen = st_context(ctx)->pipe->screen;
+ struct pipe_context *pipe = st_context(ctx)->pipe;
+ int gid, cid;
+
+ st_flush_bitmap_cache(st_context(ctx));
+
+ /* Create a query for each active counter. */
+ for (gid = 0; gid < ctx->PerfMonitor.NumGroups; gid++) {
+ const struct gl_perf_monitor_group *g = &ctx->PerfMonitor.Groups[gid];
+
+ if (m->ActiveGroups[gid] > g->MaxActiveCounters) {
+ /* Maximum number of counters reached. Cannot start the session. */
+ if (ST_DEBUG & DEBUG_MESA) {
+ debug_printf("Maximum number of counters reached. "
+ "Cannot start the session!\n");
+ }
+ return false;
+ }
+
+ for (cid = 0; cid < g->NumCounters; cid++) {
+ const struct gl_perf_monitor_counter *c = &g->Counters[cid];
+ struct st_perf_counter_object *cntr;
+ int query_type;
+
+ if (!BITSET_TEST(m->ActiveCounters[gid], cid))
+ continue;
+
+ query_type = find_query_type(screen, c->Name);
+ assert(query_type != -1);
+
+ cntr = CALLOC_STRUCT(st_perf_counter_object);
+ if (!cntr)
+ return false;
+
+ cntr->query = pipe->create_query(pipe, query_type, 0);
+ cntr->id = cid;
+ cntr->group_id = gid;
+
+ list_addtail(&cntr->list, &stm->active_counters);
+ }
+ }
+ return true;
+}
+
+static void
+reset_perf_monitor(struct st_perf_monitor_object *stm,
+ struct pipe_context *pipe)
+{
+ struct st_perf_counter_object *cntr, *tmp;
+
+ LIST_FOR_EACH_ENTRY_SAFE(cntr, tmp, &stm->active_counters, list) {
+ if (cntr->query)
+ pipe->destroy_query(pipe, cntr->query);
+ list_del(&cntr->list);
+ free(cntr);
+ }
+}
+
+static struct gl_perf_monitor_object *
+st_NewPerfMonitor(struct gl_context *ctx)
+{
+ struct st_perf_monitor_object *stq = ST_CALLOC_STRUCT(st_perf_monitor_object);
+ if (stq) {
+ list_inithead(&stq->active_counters);
+ return &stq->base;
+ }
+ return NULL;
+}
+
+static void
+st_DeletePerfMonitor(struct gl_context *ctx, struct gl_perf_monitor_object *m)
+{
+ struct st_perf_monitor_object *stm = st_perf_monitor_object(m);
+ struct pipe_context *pipe = st_context(ctx)->pipe;
+
+ reset_perf_monitor(stm, pipe);
+ FREE(stm);
+}
+
+static GLboolean
+st_BeginPerfMonitor(struct gl_context *ctx, struct gl_perf_monitor_object *m)
+{
+ struct st_perf_monitor_object *stm = st_perf_monitor_object(m);
+ struct pipe_context *pipe = st_context(ctx)->pipe;
+ struct st_perf_counter_object *cntr;
+
+ if (LIST_IS_EMPTY(&stm->active_counters)) {
+ /* Create a query for each active counter before starting
+ * a new monitoring session. */
+ if (!init_perf_monitor(ctx, m))
+ goto fail;
+ }
+
+ /* Start the query for each active counter. */
+ LIST_FOR_EACH_ENTRY(cntr, &stm->active_counters, list) {
+ if (!pipe->begin_query(pipe, cntr->query))
+ goto fail;
+ }
+ return true;
+
+fail:
+ /* Failed to start the monitoring session. */
+ reset_perf_monitor(stm, pipe);
+ return false;
+}
+
+static void
+st_EndPerfMonitor(struct gl_context *ctx, struct gl_perf_monitor_object *m)
+{
+ struct st_perf_monitor_object *stm = st_perf_monitor_object(m);
+ struct pipe_context *pipe = st_context(ctx)->pipe;
+ struct st_perf_counter_object *cntr;
+
+ /* Stop the query for each active counter. */
+ LIST_FOR_EACH_ENTRY(cntr, &stm->active_counters, list)
+ pipe->end_query(pipe, cntr->query);
+}
+
+static void
+st_ResetPerfMonitor(struct gl_context *ctx, struct gl_perf_monitor_object *m)
+{
+ struct st_perf_monitor_object *stm = st_perf_monitor_object(m);
+ struct pipe_context *pipe = st_context(ctx)->pipe;
+
+ if (!m->Ended)
+ st_EndPerfMonitor(ctx, m);
+
+ reset_perf_monitor(stm, pipe);
+
+ if (m->Active)
+ st_BeginPerfMonitor(ctx, m);
+}
+
+static GLboolean
+st_IsPerfMonitorResultAvailable(struct gl_context *ctx,
+ struct gl_perf_monitor_object *m)
+{
+ struct st_perf_monitor_object *stm = st_perf_monitor_object(m);
+ struct pipe_context *pipe = st_context(ctx)->pipe;
+ struct st_perf_counter_object *cntr;
+
+ if (LIST_IS_EMPTY(&stm->active_counters))
+ return false;
+
+ /* The result of a monitoring session is only available if the query of
+ * each active counter is idle. */
+ LIST_FOR_EACH_ENTRY(cntr, &stm->active_counters, list) {
+ union pipe_query_result result;
+ if (!pipe->get_query_result(pipe, cntr->query, FALSE, &result)) {
+ /* The query is busy. */
+ return false;
+ }
+ }
+ return true;
+}
+
+static void
+st_GetPerfMonitorResult(struct gl_context *ctx,
+ struct gl_perf_monitor_object *m,
+ GLsizei dataSize,
+ GLuint *data,
+ GLint *bytesWritten)
+{
+ struct st_perf_monitor_object *stm = st_perf_monitor_object(m);
+ struct pipe_context *pipe = st_context(ctx)->pipe;
+ struct st_perf_counter_object *cntr;
+
+ /* Copy data to the supplied array (data).
+ *
+ * The output data format is: <group ID, counter ID, value> for each
+ * active counter. The API allows counters to appear in any order.
+ */
+ GLsizei offset = 0;
+
+ /* Read query results for each active counter. */
+ LIST_FOR_EACH_ENTRY(cntr, &stm->active_counters, list) {
+ union pipe_query_result result = { 0 };
+ int gid, cid;
+ GLenum type;
+
+ cid = cntr->id;
+ gid = cntr->group_id;
+ type = ctx->PerfMonitor.Groups[gid].Counters[cid].Type;
+
+ if (!pipe->get_query_result(pipe, cntr->query, TRUE, &result))
+ continue;
+
+ data[offset++] = gid;
+ data[offset++] = cid;
+ switch (type) {
+ case GL_UNSIGNED_INT64_AMD:
+ *(uint64_t *)&data[offset] = result.u64;
+ offset += sizeof(uint64_t) / sizeof(GLuint);
+ break;
+ case GL_UNSIGNED_INT:
+ *(uint32_t *)&data[offset] = result.u32;
+ offset += sizeof(uint32_t) / sizeof(GLuint);
+ break;
+ case GL_FLOAT:
+ case GL_PERCENTAGE_AMD:
+ *(GLfloat *)&data[offset] = result.f;
+ offset += sizeof(GLfloat) / sizeof(GLuint);
+ break;
+ }
+ }
+
+ if (bytesWritten)
+ *bytesWritten = offset * sizeof(GLuint);
+}
+
+
+bool
+st_init_perfmon(struct st_context *st)
+{
+ struct gl_perf_monitor_state *perfmon = &st->ctx->PerfMonitor;
+ struct pipe_screen *screen = st->pipe->screen;
+ struct gl_perf_monitor_group *groups = NULL;
+ int num_counters, num_groups;
+ int gid, cid;
+
+ if (!screen->get_driver_query_info || !screen->get_driver_query_group_info)
+ return false;
+
+ if (!has_gpu_counters(screen)) {
+ /* According to the spec, GL_AMD_performance_monitor must only
+ * expose GPU counters. */
+ return false;
+ }
+
+ /* Get the number of available queries. */
+ num_counters = screen->get_driver_query_info(screen, 0, NULL);
+ if (!num_counters)
+ return false;
+
+ /* Get the number of available groups. */
+ num_groups = screen->get_driver_query_group_info(screen, 0, NULL);
+ if (num_groups)
+ groups = CALLOC(num_groups, sizeof(*groups));
+ if (!groups)
+ return false;
+
+ for (gid = 0; gid < num_groups; gid++) {
+ struct gl_perf_monitor_group *g = &groups[perfmon->NumGroups];
+ struct pipe_driver_query_group_info group_info;
+ struct gl_perf_monitor_counter *counters = NULL;
+
+ if (!screen->get_driver_query_group_info(screen, gid, &group_info))
+ continue;
+
+ if (group_info.type != PIPE_DRIVER_QUERY_GROUP_TYPE_GPU)
+ continue;
+
+ g->Name = group_info.name;
+ g->MaxActiveCounters = group_info.max_active_queries;
+ g->NumCounters = 0;
+ g->Counters = NULL;
+
+ if (group_info.num_queries)
+ counters = CALLOC(group_info.num_queries, sizeof(*counters));
+ if (!counters)
+ goto fail;
+
+ for (cid = 0; cid < num_counters; cid++) {
+ struct gl_perf_monitor_counter *c = &counters[g->NumCounters];
+ struct pipe_driver_query_info info;
+
+ if (!screen->get_driver_query_info(screen, cid, &info))
+ continue;
+ if (info.group_id != gid)
+ continue;
+
+ c->Name = info.name;
+ switch (info.type) {
+ case PIPE_DRIVER_QUERY_TYPE_UINT64:
+ c->Minimum.u64 = 0;
+ c->Maximum.u64 = info.max_value.u64 ? info.max_value.u64 : -1;
+ c->Type = GL_UNSIGNED_INT64_AMD;
+ break;
+ case PIPE_DRIVER_QUERY_TYPE_UINT:
+ c->Minimum.u32 = 0;
+ c->Maximum.u32 = info.max_value.u32 ? info.max_value.u32 : -1;
+ c->Type = GL_UNSIGNED_INT;
+ break;
+ case PIPE_DRIVER_QUERY_TYPE_FLOAT:
+ c->Minimum.f = 0.0;
+ c->Maximum.f = info.max_value.f ? info.max_value.f : -1;
+ c->Type = GL_FLOAT;
+ break;
+ case PIPE_DRIVER_QUERY_TYPE_PERCENTAGE:
+ c->Minimum.f = 0.0f;
+ c->Maximum.f = 100.0f;
+ c->Type = GL_PERCENTAGE_AMD;
+ break;
+ default:
+ unreachable("Invalid driver query type!");
+ }
+ g->NumCounters++;
+ }
+ g->Counters = counters;
+ perfmon->NumGroups++;
+ }
+ perfmon->Groups = groups;
+
+ return true;
+
+fail:
+ for (gid = 0; gid < num_groups; gid++)
+ FREE((void *)groups[gid].Counters);
+ FREE(groups);
+ return false;
+}
+
+void
+st_destroy_perfmon(struct st_context *st)
+{
+ struct gl_perf_monitor_state *perfmon = &st->ctx->PerfMonitor;
+ int gid;
+
+ for (gid = 0; gid < perfmon->NumGroups; gid++)
+ FREE((void *)perfmon->Groups[gid].Counters);
+ FREE((void *)perfmon->Groups);
+}
+
+void st_init_perfmon_functions(struct dd_function_table *functions)
+{
+ functions->NewPerfMonitor = st_NewPerfMonitor;
+ functions->DeletePerfMonitor = st_DeletePerfMonitor;
+ functions->BeginPerfMonitor = st_BeginPerfMonitor;
+ functions->EndPerfMonitor = st_EndPerfMonitor;
+ functions->ResetPerfMonitor = st_ResetPerfMonitor;
+ functions->IsPerfMonitorResultAvailable = st_IsPerfMonitorResultAvailable;
+ functions->GetPerfMonitorResult = st_GetPerfMonitorResult;
+}
diff --git a/mesalib/src/mesa/state_tracker/st_cb_perfmon.h b/mesalib/src/mesa/state_tracker/st_cb_perfmon.h
new file mode 100644
index 000000000..13d3627de
--- /dev/null
+++ b/mesalib/src/mesa/state_tracker/st_cb_perfmon.h
@@ -0,0 +1,64 @@
+/*
+ * Copyright (C) 2013 Christoph Bumiller
+ * Copyright (C) 2015 Samuel Pitoiset
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+#ifndef ST_CB_PERFMON_H
+#define ST_CB_PERFMON_H
+
+#include "util/list.h"
+
+/**
+ * Subclass of gl_perf_monitor_object
+ */
+struct st_perf_monitor_object
+{
+ struct gl_perf_monitor_object base;
+ struct list_head active_counters;
+};
+
+struct st_perf_counter_object
+{
+ struct list_head list;
+ struct pipe_query *query;
+ int id;
+ int group_id;
+};
+
+/**
+ * Cast wrapper
+ */
+static INLINE struct st_perf_monitor_object *
+st_perf_monitor_object(struct gl_perf_monitor_object *q)
+{
+ return (struct st_perf_monitor_object *)q;
+}
+
+bool
+st_init_perfmon(struct st_context *st);
+
+void
+st_destroy_perfmon(struct st_context *st);
+
+extern void
+st_init_perfmon_functions(struct dd_function_table *functions);
+
+#endif
diff --git a/mesalib/src/mesa/state_tracker/st_context.c b/mesalib/src/mesa/state_tracker/st_context.c
index 5fe132ac2..69e0f929d 100644
--- a/mesalib/src/mesa/state_tracker/st_context.c
+++ b/mesalib/src/mesa/state_tracker/st_context.c
@@ -51,6 +51,7 @@
#include "st_cb_fbo.h"
#include "st_cb_feedback.h"
#include "st_cb_msaa.h"
+#include "st_cb_perfmon.h"
#include "st_cb_program.h"
#include "st_cb_queryobj.h"
#include "st_cb_readpixels.h"
@@ -116,6 +117,7 @@ st_destroy_context_priv(struct st_context *st)
st_destroy_bitmap(st);
st_destroy_drawpix(st);
st_destroy_drawtex(st);
+ st_destroy_perfmon(st);
for (shader = 0; shader < ARRAY_SIZE(st->state.sampler_views); shader++) {
for (i = 0; i < ARRAY_SIZE(st->state.sampler_views[0]); i++) {
@@ -250,6 +252,12 @@ st_create_context_priv( struct gl_context *ctx, struct pipe_context *pipe,
st_init_extensions(st->pipe->screen, &ctx->Const,
&ctx->Extensions, &st->options, ctx->Mesa_DXTn);
+ if (st_init_perfmon(st)) {
+ /* GL_AMD_performance_monitor is only enabled when the underlying
+ * driver expose GPU hardware performance counters. */
+ ctx->Extensions.AMD_performance_monitor = GL_TRUE;
+ }
+
/* Enable shader-based fallbacks for ARB_color_buffer_float if needed. */
if (screen->get_param(screen, PIPE_CAP_VERTEX_COLOR_UNCLAMPED)) {
if (!screen->get_param(screen, PIPE_CAP_VERTEX_COLOR_CLAMPED)) {
@@ -313,7 +321,7 @@ struct st_context *st_create_context(gl_api api, struct pipe_context *pipe,
struct st_context *st;
memset(&funcs, 0, sizeof(funcs));
- st_init_driver_functions(&funcs);
+ st_init_driver_functions(pipe->screen, &funcs);
ctx = _mesa_create_context(api, visual, shareCtx, &funcs);
if (!ctx) {
@@ -393,7 +401,8 @@ void st_destroy_context( struct st_context *st )
}
-void st_init_driver_functions(struct dd_function_table *functions)
+void st_init_driver_functions(struct pipe_screen *screen,
+ struct dd_function_table *functions)
{
_mesa_init_shader_object_functions(functions);
_mesa_init_sampler_object_functions(functions);
@@ -414,13 +423,14 @@ void st_init_driver_functions(struct dd_function_table *functions)
st_init_fbo_functions(functions);
st_init_feedback_functions(functions);
st_init_msaa_functions(functions);
+ st_init_perfmon_functions(functions);
st_init_program_functions(functions);
st_init_query_functions(functions);
st_init_cond_render_functions(functions);
st_init_readpixels_functions(functions);
st_init_texture_functions(functions);
st_init_texture_barrier_functions(functions);
- st_init_flush_functions(functions);
+ st_init_flush_functions(screen, functions);
st_init_string_functions(functions);
st_init_viewport_functions(functions);
diff --git a/mesalib/src/mesa/state_tracker/st_context.h b/mesalib/src/mesa/state_tracker/st_context.h
index 8a9504bb7..dac5a4b90 100644
--- a/mesalib/src/mesa/state_tracker/st_context.h
+++ b/mesalib/src/mesa/state_tracker/st_context.h
@@ -237,7 +237,8 @@ struct st_framebuffer
};
-extern void st_init_driver_functions(struct dd_function_table *functions);
+extern void st_init_driver_functions(struct pipe_screen *screen,
+ struct dd_function_table *functions);
void st_invalidate_state(struct gl_context * ctx, GLuint new_state);
diff --git a/mesalib/src/mesa/state_tracker/st_extensions.c b/mesalib/src/mesa/state_tracker/st_extensions.c
index 82e4a3009..23a45883d 100644
--- a/mesalib/src/mesa/state_tracker/st_extensions.c
+++ b/mesalib/src/mesa/state_tracker/st_extensions.c
@@ -650,6 +650,12 @@ void st_init_extensions(struct pipe_screen *screen,
ARRAY_SIZE(vertex_mapping), PIPE_BUFFER,
PIPE_BIND_VERTEX_BUFFER);
+ /* ARB_direct_state_access requires OpenGL 2.0. Assume that all drivers
+ * that support NPOT textures are able to support GL 2.0.
+ */
+ if (extensions->ARB_texture_non_power_of_two)
+ extensions->ARB_direct_state_access = GL_TRUE;
+
if (extensions->ARB_stencil_texturing)
extensions->ARB_texture_stencil8 = GL_TRUE;
@@ -909,6 +915,8 @@ void st_init_extensions(struct pipe_screen *screen,
if (screen->get_shader_param(screen, PIPE_SHADER_VERTEX,
PIPE_SHADER_CAP_DOUBLES) &&
screen->get_shader_param(screen, PIPE_SHADER_FRAGMENT,
- PIPE_SHADER_CAP_DOUBLES))
+ PIPE_SHADER_CAP_DOUBLES)) {
extensions->ARB_gpu_shader_fp64 = GL_TRUE;
+ extensions->ARB_vertex_attrib_64bit = GL_TRUE;
+ }
}
diff --git a/mesalib/src/mesa/state_tracker/st_format.c b/mesalib/src/mesa/state_tracker/st_format.c
index 181465dd8..db7b5b71d 100644
--- a/mesalib/src/mesa/state_tracker/st_format.c
+++ b/mesalib/src/mesa/state_tracker/st_format.c
@@ -991,7 +991,7 @@ static const struct format_mapping format_map[] = {
{
{ GL_RGB10, 0 },
{ PIPE_FORMAT_B10G10R10X2_UNORM, PIPE_FORMAT_B10G10R10A2_UNORM,
- DEFAULT_RGB_FORMATS }
+ PIPE_FORMAT_R10G10B10A2_UNORM, DEFAULT_RGB_FORMATS }
},
{
{ GL_RGB10_A2, 0 },
diff --git a/mesalib/src/mesa/state_tracker/st_glsl_to_tgsi.cpp b/mesalib/src/mesa/state_tracker/st_glsl_to_tgsi.cpp
index 93671ba9c..f0f2a77d0 100644
--- a/mesalib/src/mesa/state_tracker/st_glsl_to_tgsi.cpp
+++ b/mesalib/src/mesa/state_tracker/st_glsl_to_tgsi.cpp
@@ -88,6 +88,7 @@ public:
this->reladdr = NULL;
this->reladdr2 = NULL;
this->has_index2 = false;
+ this->double_reg2 = false;
}
st_src_reg(gl_register_file file, int index, int type)
@@ -101,6 +102,7 @@ public:
this->reladdr = NULL;
this->reladdr2 = NULL;
this->has_index2 = false;
+ this->double_reg2 = false;
}
st_src_reg(gl_register_file file, int index, int type, int index2D)
@@ -114,6 +116,7 @@ public:
this->reladdr = NULL;
this->reladdr2 = NULL;
this->has_index2 = false;
+ this->double_reg2 = false;
}
st_src_reg()
@@ -127,6 +130,7 @@ public:
this->reladdr = NULL;
this->reladdr2 = NULL;
this->has_index2 = false;
+ this->double_reg2 = false;
}
explicit st_src_reg(st_dst_reg reg);
@@ -141,6 +145,11 @@ public:
st_src_reg *reladdr;
st_src_reg *reladdr2;
bool has_index2;
+ /*
+ * Is this the second half of a double register pair?
+ * currently used for input mapping only.
+ */
+ bool double_reg2;
};
class st_dst_reg {
@@ -197,6 +206,7 @@ st_src_reg::st_src_reg(st_dst_reg reg)
this->index2D = 0;
this->reladdr2 = NULL;
this->has_index2 = false;
+ this->double_reg2 = false;
}
st_dst_reg::st_dst_reg(st_src_reg reg)
@@ -677,8 +687,10 @@ glsl_to_tgsi_visitor::emit(ir_instruction *ir, unsigned op,
if (dinst->src[j].type == GLSL_TYPE_DOUBLE) {
dinst->src[j].index = initial_src_idx[j];
- if (swz > 1)
+ if (swz > 1) {
+ dinst->src[j].double_reg2 = true;
dinst->src[j].index++;
+ }
if (swz & 1)
dinst->src[j].swizzle = MAKE_SWIZZLE4(SWIZZLE_Z, SWIZZLE_W, SWIZZLE_Z, SWIZZLE_W);
@@ -1941,7 +1953,7 @@ glsl_to_tgsi_visitor::visit(ir_expression *ir)
break;
case ir_unop_i2b:
if (native_integers)
- emit(ir, TGSI_OPCODE_INEG, result_dst, op[0]);
+ emit(ir, TGSI_OPCODE_USNE, result_dst, op[0], st_src_reg_for_int(0));
else
emit(ir, TGSI_OPCODE_SNE, result_dst, op[0], st_src_reg_for_float(0.0));
break;
@@ -2611,6 +2623,7 @@ glsl_to_tgsi_visitor::visit(ir_assignment *ir)
assert(!ir->lhs->type->is_scalar() && !ir->lhs->type->is_vector());
l.writemask = WRITEMASK_XYZW;
} else if (ir->lhs->type->is_scalar() &&
+ !ir->lhs->type->is_double() &&
ir->lhs->variable_referenced()->data.mode == ir_var_shader_out) {
/* FINISHME: This hack makes writing to gl_FragDepth, which lives in the
* FINISHME: W component of fragment shader output zero, work correctly.
@@ -3704,6 +3717,7 @@ glsl_to_tgsi_visitor::copy_propagate(void)
} else {
if (first->src[0].file != copy_chan->src[0].file ||
first->src[0].index != copy_chan->src[0].index ||
+ first->src[0].double_reg2 != copy_chan->src[0].double_reg2 ||
first->src[0].index2D != copy_chan->src[0].index2D) {
good = false;
break;
@@ -3719,6 +3733,7 @@ glsl_to_tgsi_visitor::copy_propagate(void)
inst->src[r].index = first->src[0].index;
inst->src[r].index2D = first->src[0].index2D;
inst->src[r].has_index2 = first->src[0].has_index2;
+ inst->src[r].double_reg2 = first->src[0].double_reg2;
int swizzle = 0;
for (int i = 0; i < 4; i++) {
@@ -4551,6 +4566,9 @@ dst_register(struct st_translate *t,
static struct ureg_src
src_register(struct st_translate *t, const st_src_reg *reg)
{
+ int index = reg->index;
+ int double_reg2 = reg->double_reg2 ? 1 : 0;
+
switch(reg->file) {
case PROGRAM_UNDEFINED:
return ureg_imm4f(t->ureg, 0, 0, 0, 0);
@@ -4576,8 +4594,12 @@ src_register(struct st_translate *t, const st_src_reg *reg)
return t->immediates[reg->index];
case PROGRAM_INPUT:
- assert(t->inputMapping[reg->index] < ARRAY_SIZE(t->inputs));
- return t->inputs[t->inputMapping[reg->index]];
+ /* GLSL inputs are 64-bit containers, so we have to
+ * map back to the original index and add the offset after
+ * mapping. */
+ index -= double_reg2;
+ assert(t->inputMapping[index] < ARRAY_SIZE(t->inputs));
+ return t->inputs[t->inputMapping[index] + double_reg2];
case PROGRAM_OUTPUT:
assert(t->outputMapping[reg->index] < ARRAY_SIZE(t->outputs));
diff --git a/mesalib/src/mesa/state_tracker/st_manager.c b/mesalib/src/mesa/state_tracker/st_manager.c
index 840f76a13..0376954f7 100644
--- a/mesalib/src/mesa/state_tracker/st_manager.c
+++ b/mesalib/src/mesa/state_tracker/st_manager.c
@@ -680,6 +680,10 @@ st_api_create_context(struct st_api *stapi, struct st_manager *smapi,
if (attribs->flags & ST_CONTEXT_FLAG_FORWARD_COMPATIBLE)
st->ctx->Const.ContextFlags |= GL_CONTEXT_FLAG_FORWARD_COMPATIBLE_BIT;
+ if (attribs->flags & ST_CONTEXT_FLAG_ROBUST_ACCESS)
+ st->ctx->Const.ContextFlags |= GL_CONTEXT_FLAG_ROBUST_ACCESS_BIT_ARB;
+ if (attribs->flags & ST_CONTEXT_FLAG_RESET_NOTIFICATION_ENABLED)
+ st->ctx->Const.ResetStrategy = GL_LOSE_CONTEXT_ON_RESET_ARB;
/* need to perform version check */
if (attribs->major > 1 || attribs->minor > 0) {
diff --git a/mesalib/src/mesa/state_tracker/st_program.c b/mesalib/src/mesa/state_tracker/st_program.c
index d93b3c7bc..a9110d3c6 100644
--- a/mesalib/src/mesa/state_tracker/st_program.c
+++ b/mesalib/src/mesa/state_tracker/st_program.c
@@ -194,6 +194,11 @@ st_prepare_vertex_program(struct gl_context *ctx,
stvp->input_to_index[attr] = stvp->num_inputs;
stvp->index_to_input[stvp->num_inputs] = attr;
stvp->num_inputs++;
+ if ((stvp->Base.Base.DoubleInputsRead & BITFIELD64_BIT(attr)) != 0) {
+ /* add placeholder for second part of a double attribute */
+ stvp->index_to_input[stvp->num_inputs] = ST_DOUBLE_ATTRIB_PLACEHOLDER;
+ stvp->num_inputs++;
+ }
}
}
/* bit of a hack, presetup potentially unused edgeflag input */
diff --git a/mesalib/src/mesa/state_tracker/st_program.h b/mesalib/src/mesa/state_tracker/st_program.h
index b2c86faec..a2c56062d 100644
--- a/mesalib/src/mesa/state_tracker/st_program.h
+++ b/mesalib/src/mesa/state_tracker/st_program.h
@@ -45,6 +45,7 @@
extern "C" {
#endif
+#define ST_DOUBLE_ATTRIB_PLACEHOLDER 0xffffffff
/** Fragment program variant key */
struct st_fp_variant_key
diff --git a/mesalib/src/mesa/swrast/s_drawpix.c b/mesalib/src/mesa/swrast/s_drawpix.c
index bf427266c..fb677ee1b 100644
--- a/mesalib/src/mesa/swrast/s_drawpix.c
+++ b/mesalib/src/mesa/swrast/s_drawpix.c
@@ -448,14 +448,34 @@ draw_rgba_pixels( struct gl_context *ctx, GLint x, GLint y,
{
const GLbitfield interpMask = span.interpMask;
const GLbitfield arrayMask = span.arrayMask;
- const GLint srcStride
- = _mesa_image_row_stride(unpack, width, format, type);
GLint skipPixels = 0;
/* use span array for temp color storage */
GLfloat *rgba = (GLfloat *) span.array->attribs[VARYING_SLOT_COL0];
void *tempImage = NULL;
- if (unpack->SwapBytes) {
+ /* We have to deal with GL_COLOR_INDEX manually because
+ * _mesa_format_convert does not handle this format. So what we do here is
+ * convert it to RGBA ubyte first and then convert from that to dst as
+ * usual.
+ */
+ if (format == GL_COLOR_INDEX) {
+ /* This will handle byte swapping and transferops if needed */
+ tempImage =
+ _mesa_unpack_color_index_to_rgba_ubyte(ctx, 2,
+ pixels, format, type,
+ width, height, 1,
+ unpack,
+ transferOps);
+ if (!tempImage) {
+ _mesa_error(ctx, GL_OUT_OF_MEMORY, "glDrawPixels");
+ return;
+ }
+
+ transferOps = 0;
+ pixels = tempImage;
+ format = GL_RGBA;
+ type = GL_UNSIGNED_BYTE;
+ } else if (unpack->SwapBytes) {
/* We have to handle byte-swapping scenarios before calling
* _mesa_format_convert
*/
@@ -476,6 +496,9 @@ draw_rgba_pixels( struct gl_context *ctx, GLint x, GLint y,
}
}
+ const GLint srcStride
+ = _mesa_image_row_stride(unpack, width, format, type);
+
/* if the span is wider than SWRAST_MAX_WIDTH we have to do it in chunks */
while (skipPixels < width) {
const GLint spanWidth = MIN2(width - skipPixels, SWRAST_MAX_WIDTH);
diff --git a/mesalib/src/mesa/swrast/s_texrender.c b/mesalib/src/mesa/swrast/s_texrender.c
index fa853c919..4e41b3b72 100644
--- a/mesalib/src/mesa/swrast/s_texrender.c
+++ b/mesalib/src/mesa/swrast/s_texrender.c
@@ -72,7 +72,7 @@ update_wrapper(struct gl_context *ctx, struct gl_renderbuffer_attachment *att)
* \param fb the framebuffer object the texture is being bound to
* \param att the fb attachment point of the texture
*
- * \sa _mesa_framebuffer_renderbuffer
+ * \sa _mesa_FramebufferRenderbuffer_sw
*/
void
_swrast_render_texture(struct gl_context *ctx,
diff --git a/mesalib/src/mesa/vbo/vbo_attrib_tmp.h b/mesalib/src/mesa/vbo/vbo_attrib_tmp.h
index 17e057836..e73b8fb5f 100644
--- a/mesalib/src/mesa/vbo/vbo_attrib_tmp.h
+++ b/mesalib/src/mesa/vbo/vbo_attrib_tmp.h
@@ -31,14 +31,16 @@ USE OR OTHER DEALINGS IN THE SOFTWARE.
/* ATTR */
#define ATTRI( A, N, V0, V1, V2, V3 ) \
- ATTR_UNION(A, N, GL_INT, INT_AS_UNION(V0), INT_AS_UNION(V1), \
+ ATTR_UNION(A, N, GL_INT, fi_type, INT_AS_UNION(V0), INT_AS_UNION(V1), \
INT_AS_UNION(V2), INT_AS_UNION(V3))
#define ATTRUI( A, N, V0, V1, V2, V3 ) \
- ATTR_UNION(A, N, GL_UNSIGNED_INT, UINT_AS_UNION(V0), UINT_AS_UNION(V1), \
+ ATTR_UNION(A, N, GL_UNSIGNED_INT, fi_type, UINT_AS_UNION(V0), UINT_AS_UNION(V1), \
UINT_AS_UNION(V2), UINT_AS_UNION(V3))
#define ATTRF( A, N, V0, V1, V2, V3 ) \
- ATTR_UNION(A, N, GL_FLOAT, FLOAT_AS_UNION(V0), FLOAT_AS_UNION(V1),\
+ ATTR_UNION(A, N, GL_FLOAT, fi_type, FLOAT_AS_UNION(V0), FLOAT_AS_UNION(V1),\
FLOAT_AS_UNION(V2), FLOAT_AS_UNION(V3))
+#define ATTRD( A, N, V0, V1, V2, V3 ) \
+ ATTR_UNION(A, N, GL_DOUBLE, double, V0, V1, V2, V3)
/* float */
@@ -232,6 +234,19 @@ static inline float conv_i2_to_norm_float(const struct gl_context *ctx, int i2)
ERROR(GL_INVALID_VALUE); \
} while(0)
+
+/* Doubles */
+#define ATTR1DV( A, V ) ATTRD( A, 1, (V)[0], 0, 0, 1 )
+#define ATTR2DV( A, V ) ATTRD( A, 2, (V)[0], (V)[1], 0, 1 )
+#define ATTR3DV( A, V ) ATTRD( A, 3, (V)[0], (V)[1], (V)[2], 1 )
+#define ATTR4DV( A, V ) ATTRD( A, 4, (V)[0], (V)[1], (V)[2], (V)[3] )
+
+#define ATTR1D( A, X ) ATTRD( A, 1, X, 0, 0, 1 )
+#define ATTR2D( A, X, Y ) ATTRD( A, 2, X, Y, 0, 1 )
+#define ATTR3D( A, X, Y, Z ) ATTRD( A, 3, X, Y, Z, 1 )
+#define ATTR4D( A, X, Y, Z, W ) ATTRD( A, 4, X, Y, Z, W )
+
+
static void GLAPIENTRY
TAG(Vertex2f)(GLfloat x, GLfloat y)
{
@@ -1190,6 +1205,104 @@ TAG(VertexAttribP4uiv)(GLuint index, GLenum type, GLboolean normalized,
}
+
+static void GLAPIENTRY
+TAG(VertexAttribL1d)(GLuint index, GLdouble x)
+{
+ GET_CURRENT_CONTEXT(ctx);
+ if (index == 0 && _mesa_attr_zero_aliases_vertex(ctx))
+ ATTR1D(0, x);
+ else if (index < MAX_VERTEX_GENERIC_ATTRIBS)
+ ATTR1D(VBO_ATTRIB_GENERIC0 + index, x);
+ else
+ ERROR(GL_INVALID_VALUE);
+}
+
+static void GLAPIENTRY
+TAG(VertexAttribL1dv)(GLuint index, const GLdouble * v)
+{
+ GET_CURRENT_CONTEXT(ctx);
+ if (index == 0 && _mesa_attr_zero_aliases_vertex(ctx))
+ ATTR1DV(0, v);
+ else if (index < MAX_VERTEX_GENERIC_ATTRIBS)
+ ATTR1DV(VBO_ATTRIB_GENERIC0 + index, v);
+ else
+ ERROR(GL_INVALID_VALUE);
+}
+
+static void GLAPIENTRY
+TAG(VertexAttribL2d)(GLuint index, GLdouble x, GLdouble y)
+{
+ GET_CURRENT_CONTEXT(ctx);
+ if (index == 0 && _mesa_attr_zero_aliases_vertex(ctx))
+ ATTR2D(0, x, y);
+ else if (index < MAX_VERTEX_GENERIC_ATTRIBS)
+ ATTR2D(VBO_ATTRIB_GENERIC0 + index, x, y);
+ else
+ ERROR(GL_INVALID_VALUE);
+}
+
+static void GLAPIENTRY
+TAG(VertexAttribL2dv)(GLuint index, const GLdouble * v)
+{
+ GET_CURRENT_CONTEXT(ctx);
+ if (index == 0 && _mesa_attr_zero_aliases_vertex(ctx))
+ ATTR2DV(0, v);
+ else if (index < MAX_VERTEX_GENERIC_ATTRIBS)
+ ATTR2DV(VBO_ATTRIB_GENERIC0 + index, v);
+ else
+ ERROR(GL_INVALID_VALUE);
+}
+
+static void GLAPIENTRY
+TAG(VertexAttribL3d)(GLuint index, GLdouble x, GLdouble y, GLdouble z)
+{
+ GET_CURRENT_CONTEXT(ctx);
+ if (index == 0 && _mesa_attr_zero_aliases_vertex(ctx))
+ ATTR3D(0, x, y, z);
+ else if (index < MAX_VERTEX_GENERIC_ATTRIBS)
+ ATTR3D(VBO_ATTRIB_GENERIC0 + index, x, y, z);
+ else
+ ERROR(GL_INVALID_VALUE);
+}
+
+static void GLAPIENTRY
+TAG(VertexAttribL3dv)(GLuint index, const GLdouble * v)
+{
+ GET_CURRENT_CONTEXT(ctx);
+ if (index == 0 && _mesa_attr_zero_aliases_vertex(ctx))
+ ATTR3DV(0, v);
+ else if (index < MAX_VERTEX_GENERIC_ATTRIBS)
+ ATTR3DV(VBO_ATTRIB_GENERIC0 + index, v);
+ else
+ ERROR(GL_INVALID_VALUE);
+}
+
+static void GLAPIENTRY
+TAG(VertexAttribL4d)(GLuint index, GLdouble x, GLdouble y, GLdouble z, GLdouble w)
+{
+ GET_CURRENT_CONTEXT(ctx);
+ if (index == 0 && _mesa_attr_zero_aliases_vertex(ctx))
+ ATTR4D(0, x, y, z, w);
+ else if (index < MAX_VERTEX_GENERIC_ATTRIBS)
+ ATTR4D(VBO_ATTRIB_GENERIC0 + index, x, y, z, w);
+ else
+ ERROR(GL_INVALID_VALUE);
+}
+
+static void GLAPIENTRY
+TAG(VertexAttribL4dv)(GLuint index, const GLdouble * v)
+{
+ GET_CURRENT_CONTEXT(ctx);
+ if (index == 0 && _mesa_attr_zero_aliases_vertex(ctx))
+ ATTR4DV(0, v);
+ else if (index < MAX_VERTEX_GENERIC_ATTRIBS)
+ ATTR4DV(VBO_ATTRIB_GENERIC0 + index, v);
+ else
+ ERROR(GL_INVALID_VALUE);
+}
+
+
#undef ATTR1FV
#undef ATTR2FV
#undef ATTR3FV
diff --git a/mesalib/src/mesa/vbo/vbo_context.h b/mesalib/src/mesa/vbo/vbo_context.h
index 6099b56e6..a376efe34 100644
--- a/mesalib/src/mesa/vbo/vbo_context.h
+++ b/mesalib/src/mesa/vbo/vbo_context.h
@@ -146,6 +146,7 @@ vbo_attrtype_to_integer_flag(GLenum format)
{
switch (format) {
case GL_FLOAT:
+ case GL_DOUBLE:
return GL_FALSE;
case GL_INT:
case GL_UNSIGNED_INT:
@@ -156,6 +157,22 @@ vbo_attrtype_to_integer_flag(GLenum format)
}
}
+static inline GLboolean
+vbo_attrtype_to_double_flag(GLenum format)
+{
+ switch (format) {
+ case GL_FLOAT:
+ case GL_INT:
+ case GL_UNSIGNED_INT:
+ return GL_FALSE;
+ case GL_DOUBLE:
+ return GL_TRUE;
+ default:
+ assert(0);
+ return GL_FALSE;
+ }
+}
+
/**
* Return default component values for the given format.
* The return type is an array of fi_types, because that's how we declare
diff --git a/mesalib/src/mesa/vbo/vbo_exec_api.c b/mesalib/src/mesa/vbo/vbo_exec_api.c
index 48680ec88..138cd6051 100644
--- a/mesalib/src/mesa/vbo/vbo_exec_api.c
+++ b/mesalib/src/mesa/vbo/vbo_exec_api.c
@@ -159,27 +159,36 @@ static void vbo_exec_copy_to_current( struct vbo_exec_context *exec )
* ctx->Current.Attrib and ctx->Light.Material.Attrib arrays.
*/
GLfloat *current = (GLfloat *)vbo->currval[i].Ptr;
- fi_type tmp[4];
+ fi_type tmp[8]; /* space for doubles */
+ int dmul = exec->vtx.attrtype[i] == GL_DOUBLE ? 2 : 1;
+
+ if (exec->vtx.attrtype[i] == GL_DOUBLE) {
+ memset(tmp, 0, sizeof(tmp));
+ memcpy(tmp, exec->vtx.attrptr[i], exec->vtx.attrsz[i] * sizeof(GLfloat));
+ } else {
+ COPY_CLEAN_4V_TYPE_AS_UNION(tmp,
+ exec->vtx.attrsz[i],
+ exec->vtx.attrptr[i],
+ exec->vtx.attrtype[i]);
+ }
- COPY_CLEAN_4V_TYPE_AS_UNION(tmp,
- exec->vtx.attrsz[i],
- exec->vtx.attrptr[i],
- exec->vtx.attrtype[i]);
-
if (exec->vtx.attrtype[i] != vbo->currval[i].Type ||
- memcmp(current, tmp, sizeof(tmp)) != 0) {
- memcpy(current, tmp, sizeof(tmp));
+ memcmp(current, tmp, 4 * sizeof(GLfloat) * dmul) != 0) {
+ memcpy(current, tmp, 4 * sizeof(GLfloat) * dmul);
/* Given that we explicitly state size here, there is no need
* for the COPY_CLEAN above, could just copy 16 bytes and be
* done. The only problem is when Mesa accesses ctx->Current
* directly.
*/
- vbo->currval[i].Size = exec->vtx.attrsz[i];
- vbo->currval[i]._ElementSize = vbo->currval[i].Size * sizeof(GLfloat);
+ /* Size here is in components - not bytes */
+ vbo->currval[i].Size = exec->vtx.attrsz[i] / dmul;
+ vbo->currval[i]._ElementSize = vbo->currval[i].Size * sizeof(GLfloat) * dmul;
vbo->currval[i].Type = exec->vtx.attrtype[i];
vbo->currval[i].Integer =
vbo_attrtype_to_integer_flag(exec->vtx.attrtype[i]);
+ vbo->currval[i].Doubles =
+ vbo_attrtype_to_double_flag(exec->vtx.attrtype[i]);
/* This triggers rather too much recalculation of Mesa state
* that doesn't get used (eg light positions).
@@ -214,13 +223,17 @@ vbo_exec_copy_from_current(struct vbo_exec_context *exec)
GLint i;
for (i = VBO_ATTRIB_POS + 1; i < VBO_ATTRIB_MAX; i++) {
- const fi_type *current = (fi_type *) vbo->currval[i].Ptr;
- switch (exec->vtx.attrsz[i]) {
- case 4: exec->vtx.attrptr[i][3] = current[3];
- case 3: exec->vtx.attrptr[i][2] = current[2];
- case 2: exec->vtx.attrptr[i][1] = current[1];
- case 1: exec->vtx.attrptr[i][0] = current[0];
- break;
+ if (exec->vtx.attrtype[i] == GL_DOUBLE) {
+ memcpy(exec->vtx.attrptr[i], vbo->currval[i].Ptr, exec->vtx.attrsz[i] * sizeof(GLfloat));
+ } else {
+ const fi_type *current = (fi_type *) vbo->currval[i].Ptr;
+ switch (exec->vtx.attrsz[i]) {
+ case 4: exec->vtx.attrptr[i][3] = current[3];
+ case 3: exec->vtx.attrptr[i][2] = current[2];
+ case 2: exec->vtx.attrptr[i][1] = current[1];
+ case 1: exec->vtx.attrptr[i][0] = current[0];
+ break;
+ }
}
}
}
@@ -364,11 +377,11 @@ vbo_exec_wrap_upgrade_vertex(struct vbo_exec_context *exec,
* glTexCoord4f() call. We promote the array from size=2 to size=4.
*/
static void
-vbo_exec_fixup_vertex(struct gl_context *ctx, GLuint attr, GLuint newSize)
+vbo_exec_fixup_vertex(struct gl_context *ctx, GLuint attr, GLuint newSize, GLenum newType)
{
struct vbo_exec_context *exec = &vbo_context(ctx)->exec;
- if (newSize > exec->vtx.attrsz[attr]) {
+ if (newSize > exec->vtx.attrsz[attr] || newType != exec->vtx.attrtype[attr]) {
/* New size is larger. Need to flush existing vertices and get
* an enlarged vertex format.
*/
@@ -401,18 +414,19 @@ vbo_exec_fixup_vertex(struct gl_context *ctx, GLuint attr, GLuint newSize)
* This macro is used to implement all the glVertex, glColor, glTexCoord,
* glVertexAttrib, etc functions.
*/
-#define ATTR_UNION( A, N, T, V0, V1, V2, V3 ) \
+#define ATTR_UNION( A, N, T, C, V0, V1, V2, V3 ) \
do { \
struct vbo_exec_context *exec = &vbo_context(ctx)->exec; \
- \
+ int sz = (sizeof(C) / sizeof(GLfloat)); \
if (unlikely(!(ctx->Driver.NeedFlush & FLUSH_UPDATE_CURRENT))) \
ctx->Driver.BeginVertices( ctx ); \
- \
- if (unlikely(exec->vtx.active_sz[A] != N)) \
- vbo_exec_fixup_vertex(ctx, A, N); \
- \
+ \
+ if (unlikely(exec->vtx.active_sz[A] != N * sz) || \
+ unlikely(exec->vtx.attrtype[A] != T)) \
+ vbo_exec_fixup_vertex(ctx, A, N * sz, T); \
+ \
{ \
- fi_type *dest = exec->vtx.attrptr[A]; \
+ C *dest = (C *)exec->vtx.attrptr[A]; \
if (N>0) dest[0] = V0; \
if (N>1) dest[1] = V1; \
if (N>2) dest[2] = V2; \
@@ -438,7 +452,6 @@ do { \
} \
} while (0)
-
#define ERROR(err) _mesa_error( ctx, err, __func__ )
#define TAG(x) vbo_##x
@@ -575,7 +588,7 @@ static void GLAPIENTRY vbo_exec_EvalCoord1f( GLfloat u )
for (i = 0; i <= VBO_ATTRIB_TEX7; i++) {
if (exec->eval.map1[i].map)
if (exec->vtx.active_sz[i] != exec->eval.map1[i].sz)
- vbo_exec_fixup_vertex( ctx, i, exec->eval.map1[i].sz );
+ vbo_exec_fixup_vertex( ctx, i, exec->eval.map1[i].sz, GL_FLOAT );
}
}
@@ -602,12 +615,12 @@ static void GLAPIENTRY vbo_exec_EvalCoord2f( GLfloat u, GLfloat v )
for (i = 0; i <= VBO_ATTRIB_TEX7; i++) {
if (exec->eval.map2[i].map)
if (exec->vtx.active_sz[i] != exec->eval.map2[i].sz)
- vbo_exec_fixup_vertex( ctx, i, exec->eval.map2[i].sz );
+ vbo_exec_fixup_vertex( ctx, i, exec->eval.map2[i].sz, GL_FLOAT );
}
if (ctx->Eval.AutoNormal)
if (exec->vtx.active_sz[VBO_ATTRIB_NORMAL] != 3)
- vbo_exec_fixup_vertex( ctx, VBO_ATTRIB_NORMAL, 3 );
+ vbo_exec_fixup_vertex( ctx, VBO_ATTRIB_NORMAL, 3, GL_FLOAT );
}
memcpy( exec->vtx.copied.buffer, exec->vtx.vertex,
@@ -968,6 +981,16 @@ static void vbo_exec_vtxfmt_init( struct vbo_exec_context *exec )
vfmt->VertexAttribP3uiv = vbo_VertexAttribP3uiv;
vfmt->VertexAttribP4ui = vbo_VertexAttribP4ui;
vfmt->VertexAttribP4uiv = vbo_VertexAttribP4uiv;
+
+ vfmt->VertexAttribL1d = vbo_VertexAttribL1d;
+ vfmt->VertexAttribL2d = vbo_VertexAttribL2d;
+ vfmt->VertexAttribL3d = vbo_VertexAttribL3d;
+ vfmt->VertexAttribL4d = vbo_VertexAttribL4d;
+
+ vfmt->VertexAttribL1dv = vbo_VertexAttribL1dv;
+ vfmt->VertexAttribL2dv = vbo_VertexAttribL2dv;
+ vfmt->VertexAttribL3dv = vbo_VertexAttribL3dv;
+ vfmt->VertexAttribL4dv = vbo_VertexAttribL4dv;
}
diff --git a/mesalib/src/mesa/vbo/vbo_save_api.c b/mesalib/src/mesa/vbo/vbo_save_api.c
index 5927beeb3..29de3d38a 100644
--- a/mesalib/src/mesa/vbo/vbo_save_api.c
+++ b/mesalib/src/mesa/vbo/vbo_save_api.c
@@ -772,7 +772,7 @@ _save_reset_vertex(struct gl_context *ctx)
* 3f version won't otherwise set color[3] to 1.0 -- this is the job
* of the chooser function when switching between Color4f and Color3f.
*/
-#define ATTR_UNION(A, N, T, V0, V1, V2, V3) \
+#define ATTR_UNION(A, N, T, C, V0, V1, V2, V3) \
do { \
struct vbo_save_context *save = &vbo_context(ctx)->save; \
\
@@ -780,7 +780,7 @@ do { \
save_fixup_vertex(ctx, A, N); \
\
{ \
- fi_type *dest = save->attrptr[A]; \
+ C *dest = (C *)save->attrptr[A]; \
if (N>0) dest[0] = V0; \
if (N>1) dest[1] = V1; \
if (N>2) dest[2] = V2; \
@@ -1372,6 +1372,16 @@ _save_vtxfmt_init(struct gl_context *ctx)
vfmt->VertexAttribP3uiv = _save_VertexAttribP3uiv;
vfmt->VertexAttribP4uiv = _save_VertexAttribP4uiv;
+ vfmt->VertexAttribL1d = _save_VertexAttribL1d;
+ vfmt->VertexAttribL2d = _save_VertexAttribL2d;
+ vfmt->VertexAttribL3d = _save_VertexAttribL3d;
+ vfmt->VertexAttribL4d = _save_VertexAttribL4d;
+
+ vfmt->VertexAttribL1dv = _save_VertexAttribL1dv;
+ vfmt->VertexAttribL2dv = _save_VertexAttribL2dv;
+ vfmt->VertexAttribL3dv = _save_VertexAttribL3dv;
+ vfmt->VertexAttribL4dv = _save_VertexAttribL4dv;
+
/* This will all require us to fallback to saving the list as opcodes:
*/
vfmt->CallList = _save_CallList;
diff --git a/mesalib/src/mesa/vbo/vbo_split_copy.c b/mesalib/src/mesa/vbo/vbo_split_copy.c
index d1107dd84..7b1e20b18 100644
--- a/mesalib/src/mesa/vbo/vbo_split_copy.c
+++ b/mesalib/src/mesa/vbo/vbo_split_copy.c
@@ -533,6 +533,7 @@ replay_init( struct copy_context *copy )
dst->Enabled = GL_TRUE;
dst->Normalized = src->Normalized;
dst->Integer = src->Integer;
+ dst->Doubles = src->Doubles;
dst->BufferObj = ctx->Shared->NullBufferObj;
dst->_ElementSize = src->_ElementSize;
diff --git a/mesalib/src/util/Makefile.sources b/mesalib/src/util/Makefile.sources
index 3e0d02bad..dc5593918 100644
--- a/mesalib/src/util/Makefile.sources
+++ b/mesalib/src/util/Makefile.sources
@@ -7,6 +7,7 @@ MESA_UTIL_FILES := \
format_srgb.h \
hash_table.c \
hash_table.h \
+ list.h \
macros.h \
ralloc.c \
ralloc.h \
diff --git a/mesalib/src/gallium/auxiliary/util/u_double_list.h b/mesalib/src/util/list.h
index 247f0f282..946034710 100644
--- a/mesalib/src/gallium/auxiliary/util/u_double_list.h
+++ b/mesalib/src/util/list.h
@@ -1,8 +1,8 @@
/**************************************************************************
- *
+ *
* Copyright 2006 VMware, Inc., Bismarck, ND. USA.
* All Rights Reserved.
- *
+ *
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the
* "Software"), to deal in the Software without restriction, including
@@ -10,36 +10,37 @@
* distribute, sub license, and/or sell copies of the Software, and to
* permit persons to whom the Software is furnished to do so, subject to
* the following conditions:
- *
+ *
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
- * THE COPYRIGHT HOLDERS, AUTHORS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM,
- * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
- * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
+ * THE COPYRIGHT HOLDERS, AUTHORS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM,
+ * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
+ * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
* USE OR OTHER DEALINGS IN THE SOFTWARE.
*
* The above copyright notice and this permission notice (including the
* next paragraph) shall be included in all copies or substantial portions
* of the Software.
- *
+ *
**************************************************************************/
/**
* \file
* List macros heavily inspired by the Linux kernel
* list handling. No list looping yet.
- *
+ *
* Is not threadsafe, so common operations need to
* be protected using an external mutex.
*/
-#ifndef _U_DOUBLE_LIST_H_
-#define _U_DOUBLE_LIST_H_
+#ifndef _UTIL_LIST_H_
+#define _UTIL_LIST_H_
+#include <stdbool.h>
#include <stddef.h>
-#include "pipe/p_compiler.h"
+#include <assert.h>
struct list_head
@@ -48,13 +49,13 @@ struct list_head
struct list_head *next;
};
-static INLINE void list_inithead(struct list_head *item)
+static inline void list_inithead(struct list_head *item)
{
item->prev = item;
item->next = item;
}
-static INLINE void list_add(struct list_head *item, struct list_head *list)
+static inline void list_add(struct list_head *item, struct list_head *list)
{
item->prev = list;
item->next = list->next;
@@ -62,7 +63,7 @@ static INLINE void list_add(struct list_head *item, struct list_head *list)
list->next = item;
}
-static INLINE void list_addtail(struct list_head *item, struct list_head *list)
+static inline void list_addtail(struct list_head *item, struct list_head *list)
{
item->next = list;
item->prev = list->prev;
@@ -70,7 +71,7 @@ static INLINE void list_addtail(struct list_head *item, struct list_head *list)
list->prev = item;
}
-static INLINE void list_replace(struct list_head *from, struct list_head *to)
+static inline void list_replace(struct list_head *from, struct list_head *to)
{
to->prev = from->prev;
to->next = from->next;
@@ -78,14 +79,14 @@ static INLINE void list_replace(struct list_head *from, struct list_head *to)
from->prev->next = to;
}
-static INLINE void list_del(struct list_head *item)
+static inline void list_del(struct list_head *item)
{
item->prev->next = item->next;
item->next->prev = item->prev;
item->prev = item->next = NULL;
}
-static INLINE void list_delinit(struct list_head *item)
+static inline void list_delinit(struct list_head *item)
{
item->prev->next = item->next;
item->next->prev = item->prev;
@@ -93,6 +94,28 @@ static INLINE void list_delinit(struct list_head *item)
item->prev = item;
}
+static inline bool list_empty(struct list_head *list)
+{
+ return list->next == list;
+}
+
+static inline unsigned list_length(struct list_head *list)
+{
+ struct list_head *node;
+ unsigned length = 0;
+ for (node = list->next; node != list; node = node->next)
+ length++;
+ return length;
+}
+
+static inline void list_validate(struct list_head *list)
+{
+ struct list_head *node;
+ assert(list->next->prev == list && list->prev->next == list);
+ for (node = list->next; node != list; node = node->next)
+ assert(node->next->prev == node && node->prev->next == node);
+}
+
#define LIST_INITHEAD(__item) list_inithead(__item)
#define LIST_ADD(__item, __list) list_add(__item, __list)
#define LIST_ADDTAIL(__item, __list) list_addtail(__item, __list)
@@ -144,4 +167,38 @@ static INLINE void list_delinit(struct list_head *item)
&pos->member != (head); \
pos = container_of(pos->member.prev, pos, member))
-#endif /*_U_DOUBLE_LIST_H_*/
+#define list_for_each_entry(type, pos, head, member) \
+ for (type *pos = LIST_ENTRY(type, (head)->next, member); \
+ &pos->member != (head); \
+ pos = LIST_ENTRY(type, pos->member.next, member))
+
+#define list_for_each_entry_safe(type, pos, head, member) \
+ for (type *pos = LIST_ENTRY(type, (head)->next, member), \
+ *__next = LIST_ENTRY(type, pos->member.next, member); \
+ &pos->member != (head); \
+ pos = __next, \
+ __next = LIST_ENTRY(type, __next->member.next, member))
+
+#define list_for_each_entry_rev(type, pos, head, member) \
+ for (type *pos = LIST_ENTRY(type, (head)->prev, member); \
+ &pos->member != (head); \
+ pos = LIST_ENTRY(type, pos->member.prev, member))
+
+#define list_for_each_entry_safe_rev(type, pos, head, member) \
+ for (type *pos = LIST_ENTRY(type, (head)->prev, member), \
+ *__prev = LIST_ENTRY(type, pos->member.prev, member); \
+ &pos->member != (head); \
+ pos = __prev, \
+ __prev = LIST_ENTRY(type, __prev->member.prev, member))
+
+#define list_for_each_entry_from(type, pos, start, head, member) \
+ for (type *pos = LIST_ENTRY(type, (start), member); \
+ &pos->member != (head); \
+ pos = LIST_ENTRY(type, pos->member.next, member))
+
+#define list_for_each_entry_from_rev(type, pos, start, head, member) \
+ for (type *pos = LIST_ENTRY(type, (start), member); \
+ &pos->member != (head); \
+ pos = LIST_ENTRY(type, pos->member.prev, member))
+
+#endif /*_UTIL_LIST_H_*/