From c81020559f329a516191927222b3698ba7370aca Mon Sep 17 00:00:00 2001 From: marha Date: Sun, 22 Dec 2013 12:51:45 +0100 Subject: libxtrans fontconfig glproto libX11 libxcb xcbproto mesa xserver pixman xkeyboard-config git update 22 Dec 2013 xserver commit a68df147421da21528b5be2d34678383922fa352 libxcb commit f653464554469b5767f1c99abced25a76bace047 libxcb/xcb-proto commit 4087fc682c5ceb849b74442e17a6b73176e5eecb xkeyboard-config commit a224a636139d22e1dc7ca7d23782cd656e87bcf5 libX11 commit 3d69b0a83e62f8f6fbdd952fc49cdbdf8825e1e6 libXdmcp commit 089081dca4ba3598c6f9bf401c029378943b5854 libXext commit bb24f2970f2e425f4df90c9b73d078ad15a73fbb libfontenc commit 3acba630d8b57084f7e92c15732408711ed5137a libXinerama commit edd95182b26eb5d576d4878c559e0f17dddaa909 libXau commit 304a11be4727c5a7feeb2501e8e001466f8ce84e xkbcomp commit e3e6e938535532bfad175c1635256ab7fb3ac943 pixman commit 945ab7a6f3eb6241f07e8f094dc0e647d1f10d9d xextproto commit 3f355f138d6df57e067458a20f47307883048adb randrproto commit e7526e6b5fe0966929cda10b2ded0258413744db glproto commit f84853d97d5749308992412a215fa518b6536eb3 mkfontscale commit 880a0c4733e62e54e6a0f1238c7430727d23657b xwininfo commit ba0d1b0da21d2dbdd81098ed5778f3792b472e13 libXft commit 4acfdaf95adb0a05c2a25550bdde036c865902f4 libXmu commit 22d9c590901e121936f50dee97dc60c4f7defb63 libxtrans commit 2c0a7840a28ae696e80e73157856d7a049fdf6c7 fontconfig commit 5c725f2f5829238d16116f782d00d8bb0defaf08 mesa commit 2efe7927d38983029784825fc4897e9b77aa237e --- mesalib/src/gallium/auxiliary/util/u_blitter.c | 286 +++-- mesalib/src/gallium/auxiliary/util/u_blitter.h | 13 +- mesalib/src/gallium/auxiliary/util/u_clear.h | 7 +- mesalib/src/gallium/auxiliary/util/u_framebuffer.c | 24 + mesalib/src/gallium/auxiliary/util/u_framebuffer.h | 5 + .../src/gallium/auxiliary/util/u_simple_shaders.c | 180 +++ .../src/gallium/auxiliary/util/u_simple_shaders.h | 14 + mesalib/src/glsl/ast.h | 1 + mesalib/src/glsl/ast_array_index.cpp | 8 +- mesalib/src/glsl/ast_function.cpp | 86 +- mesalib/src/glsl/ast_to_hir.cpp | 298 ++--- mesalib/src/glsl/ast_type.cpp | 3 +- mesalib/src/glsl/builtin_functions.cpp | 37 +- mesalib/src/glsl/builtin_variables.cpp | 50 +- mesalib/src/glsl/glsl_lexer.ll | 2 +- mesalib/src/glsl/glsl_parser.yy | 17 +- mesalib/src/glsl/glsl_parser_extras.cpp | 24 +- mesalib/src/glsl/glsl_parser_extras.h | 14 +- mesalib/src/glsl/glsl_types.cpp | 5 + mesalib/src/glsl/glsl_types.h | 6 + mesalib/src/glsl/ir.cpp | 65 +- mesalib/src/glsl/ir.h | 373 +++--- mesalib/src/glsl/ir_clone.cpp | 35 +- mesalib/src/glsl/ir_constant_expression.cpp | 2 +- mesalib/src/glsl/ir_function.cpp | 2 +- mesalib/src/glsl/ir_hv_accept.cpp | 20 - mesalib/src/glsl/ir_print_visitor.cpp | 27 +- mesalib/src/glsl/ir_reader.cpp | 42 +- mesalib/src/glsl/ir_set_program_inouts.cpp | 35 +- mesalib/src/glsl/ir_validate.cpp | 47 +- mesalib/src/glsl/link_atomics.cpp | 20 +- mesalib/src/glsl/link_functions.cpp | 10 +- mesalib/src/glsl/link_interface_blocks.cpp | 12 +- mesalib/src/glsl/link_uniform_initializers.cpp | 6 +- mesalib/src/glsl/link_uniforms.cpp | 20 +- mesalib/src/glsl/link_varyings.cpp | 98 +- mesalib/src/glsl/linker.cpp | 173 +-- mesalib/src/glsl/loop_analysis.cpp | 196 +++- mesalib/src/glsl/loop_analysis.h | 93 +- mesalib/src/glsl/loop_controls.cpp | 127 +-- mesalib/src/glsl/loop_unroll.cpp | 318 ++++-- mesalib/src/glsl/lower_clip_distance.cpp | 18 +- mesalib/src/glsl/lower_instructions.cpp | 4 +- mesalib/src/glsl/lower_named_interface_blocks.cpp | 21 +- mesalib/src/glsl/lower_output_reads.cpp | 2 +- mesalib/src/glsl/lower_packed_varyings.cpp | 21 +- mesalib/src/glsl/lower_ubo_reference.cpp | 2 +- .../glsl/lower_variable_index_to_cond_assign.cpp | 2 +- mesalib/src/glsl/opt_array_splitting.cpp | 4 +- mesalib/src/glsl/opt_constant_folding.cpp | 4 +- mesalib/src/glsl/opt_constant_propagation.cpp | 4 +- mesalib/src/glsl/opt_constant_variable.cpp | 4 +- mesalib/src/glsl/opt_copy_propagation.cpp | 4 +- mesalib/src/glsl/opt_copy_propagation_elements.cpp | 4 +- mesalib/src/glsl/opt_cse.cpp | 2 +- mesalib/src/glsl/opt_dead_builtin_varyings.cpp | 22 +- mesalib/src/glsl/opt_dead_code.cpp | 8 +- mesalib/src/glsl/opt_dead_code_local.cpp | 2 +- mesalib/src/glsl/opt_flip_matrices.cpp | 4 +- mesalib/src/glsl/opt_function_inlining.cpp | 14 +- mesalib/src/glsl/opt_structure_splitting.cpp | 4 +- mesalib/src/glsl/opt_tree_grafting.cpp | 10 +- mesalib/src/glsl/standalone_scaffolding.h | 2 +- .../src/mapi/glapi/gen/ARB_clear_buffer_object.xml | 50 + mesalib/src/mapi/glapi/gen/ARB_texture_view.xml | 23 + mesalib/src/mapi/glapi/gen/Makefile.am | 1 + mesalib/src/mapi/glapi/gen/gl_API.xml | 8 +- mesalib/src/mapi/glapi/gen/gl_genexec.py | 1 + mesalib/src/mapi/glapi/gen/gl_gentable.py | 2 + mesalib/src/mesa/Makefile.am | 6 +- mesalib/src/mesa/Makefile.sources | 1 + mesalib/src/mesa/SConscript | 1 + mesalib/src/mesa/drivers/common/driverfuncs.c | 3 + mesalib/src/mesa/drivers/dri/common/dri_util.c | 26 +- mesalib/src/mesa/drivers/dri/common/dri_util.h | 8 +- .../src/mesa/drivers/dri/common/megadriver_stub.c | 126 ++ mesalib/src/mesa/drivers/dri/swrast/swrast.c | 39 +- mesalib/src/mesa/main/attrib.c | 326 ++++-- mesalib/src/mesa/main/bufferobj.c | 406 ++++++- mesalib/src/mesa/main/bufferobj.h | 59 +- mesalib/src/mesa/main/clear.c | 31 +- mesalib/src/mesa/main/colortab.c | 20 +- mesalib/src/mesa/main/condrender.c | 4 +- mesalib/src/mesa/main/context.c | 1 + mesalib/src/mesa/main/convolve.c | 24 +- mesalib/src/mesa/main/dd.h | 11 + mesalib/src/mesa/main/dlist.c | 1074 ++++++----------- mesalib/src/mesa/main/enable.c | 19 - mesalib/src/mesa/main/extensions.c | 27 +- mesalib/src/mesa/main/fbobject.c | 31 +- mesalib/src/mesa/main/ff_fragment_shader.cpp | 16 +- mesalib/src/mesa/main/get.c | 8 +- mesalib/src/mesa/main/get_hash_params.py | 8 +- mesalib/src/mesa/main/getstring.c | 2 - mesalib/src/mesa/main/glformats.c | 12 +- mesalib/src/mesa/main/imports.c | 14 +- mesalib/src/mesa/main/mipmap.c | 8 +- mesalib/src/mesa/main/mipmap.h | 4 + mesalib/src/mesa/main/mtypes.h | 35 +- mesalib/src/mesa/main/performance_monitor.c | 19 + mesalib/src/mesa/main/performance_monitor.h | 3 + mesalib/src/mesa/main/shader_query.cpp | 36 +- mesalib/src/mesa/main/shaderapi.c | 2 +- mesalib/src/mesa/main/shaderobj.h | 2 +- mesalib/src/mesa/main/texgetimage.c | 3 +- mesalib/src/mesa/main/teximage.c | 255 ++--- mesalib/src/mesa/main/teximage.h | 4 + mesalib/src/mesa/main/texobj.c | 29 +- mesalib/src/mesa/main/texparam.c | 75 +- mesalib/src/mesa/main/texstorage.c | 36 +- mesalib/src/mesa/main/texstore.c | 1 + mesalib/src/mesa/main/textureview.c | 668 +++++++++++ mesalib/src/mesa/main/textureview.h | 43 + mesalib/src/mesa/main/version.c | 1 - mesalib/src/mesa/math/m_matrix.c | 13 +- mesalib/src/mesa/program/ir_to_mesa.cpp | 63 +- mesalib/src/mesa/program/prog_parameter.c | 3 +- mesalib/src/mesa/program/program.c | 8 + mesalib/src/mesa/program/program_parse_extra.c | 9 - .../src/mesa/state_tracker/st_atom_framebuffer.c | 58 +- mesalib/src/mesa/state_tracker/st_atom_sampler.c | 32 +- .../src/mesa/state_tracker/st_cb_bufferobjects.c | 3 + mesalib/src/mesa/state_tracker/st_cb_clear.c | 124 +- mesalib/src/mesa/state_tracker/st_cb_drawpixels.c | 19 +- mesalib/src/mesa/state_tracker/st_cb_fbo.c | 97 +- mesalib/src/mesa/state_tracker/st_cb_fbo.h | 10 +- mesalib/src/mesa/state_tracker/st_cb_readpixels.c | 4 +- mesalib/src/mesa/state_tracker/st_cb_texture.c | 10 +- mesalib/src/mesa/state_tracker/st_context.h | 1 + mesalib/src/mesa/state_tracker/st_extensions.c | 16 +- mesalib/src/mesa/state_tracker/st_format.c | 6 +- mesalib/src/mesa/state_tracker/st_format.h | 2 +- mesalib/src/mesa/state_tracker/st_glsl_to_tgsi.cpp | 74 +- mesalib/src/mesa/state_tracker/st_program.c | 9 + mesalib/src/mesa/state_tracker/st_texture.h | 6 + mesalib/src/mesa/swrast/s_texture.c | 7 +- mesalib/src/mesa/tnl/t_vertex.c | 6 +- mesalib/src/mesa/vbo/vbo_exec_api.c | 9 +- mesalib/src/mesa/x86/rtasm/x86sse.c | 1203 -------------------- mesalib/src/mesa/x86/rtasm/x86sse.h | 256 ----- 140 files changed, 4348 insertions(+), 4275 deletions(-) create mode 100644 mesalib/src/mapi/glapi/gen/ARB_clear_buffer_object.xml create mode 100644 mesalib/src/mapi/glapi/gen/ARB_texture_view.xml create mode 100644 mesalib/src/mesa/main/textureview.c create mode 100644 mesalib/src/mesa/main/textureview.h delete mode 100644 mesalib/src/mesa/x86/rtasm/x86sse.c delete mode 100644 mesalib/src/mesa/x86/rtasm/x86sse.h (limited to 'mesalib/src') diff --git a/mesalib/src/gallium/auxiliary/util/u_blitter.c b/mesalib/src/gallium/auxiliary/util/u_blitter.c index b95cbab12..9246bd722 100644 --- a/mesalib/src/gallium/auxiliary/util/u_blitter.c +++ b/mesalib/src/gallium/auxiliary/util/u_blitter.c @@ -51,6 +51,12 @@ #define INVALID_PTR ((void*)~0) +#define GET_CLEAR_BLEND_STATE_IDX(clear_buffers) \ + ((clear_buffers) / PIPE_CLEAR_COLOR0) + +#define NUM_RESOLVE_FRAG_SHADERS 5 /* MSAA 2x, 4x, 8x, 16x, 32x */ +#define GET_MSAA_RESOLVE_FS_IDX(nr_samples) (util_logbase2(nr_samples)-1) + struct blitter_context_priv { struct blitter_context base; @@ -65,6 +71,7 @@ struct blitter_context_priv /* Vertex shaders. */ void *vs; /**< Vertex shader which passes {pos, generic} to the output.*/ void *vs_pos_only; /**< Vertex shader which passes pos to the output.*/ + void *vs_layered; /**< Vertex shader which sets LAYER = INSTANCEID. */ /* Fragment shaders. */ void *fs_empty; @@ -87,8 +94,14 @@ struct blitter_context_priv void *fs_texfetch_depthstencil_msaa[PIPE_MAX_TEXTURE_TYPES]; void *fs_texfetch_stencil_msaa[PIPE_MAX_TEXTURE_TYPES]; + /* FS which outputs an average of all samples. */ + void *fs_resolve[PIPE_MAX_TEXTURE_TYPES][NUM_RESOLVE_FRAG_SHADERS][2]; + void *fs_resolve_sint[PIPE_MAX_TEXTURE_TYPES][NUM_RESOLVE_FRAG_SHADERS][2]; + void *fs_resolve_uint[PIPE_MAX_TEXTURE_TYPES][NUM_RESOLVE_FRAG_SHADERS][2]; + /* Blend state. */ void *blend[PIPE_MASK_RGBA+1]; /**< blend state with writemask */ + void *blend_clear[GET_CLEAR_BLEND_STATE_IDX(PIPE_CLEAR_COLOR)+1]; /* Depth stencil alpha state. */ void *dsa_write_depth_stencil; @@ -295,6 +308,7 @@ struct blitter_context *util_blitter_create(struct pipe_context *pipe) util_make_vertex_passthrough_shader(pipe, 2, semantic_names, semantic_indices); } + if (ctx->has_stream_out) { struct pipe_stream_output_info so; const uint semantic_names[] = { TGSI_SEMANTIC_POSITION }; @@ -310,6 +324,11 @@ struct blitter_context *util_blitter_create(struct pipe_context *pipe) semantic_indices, &so); } + if (pipe->screen->get_param(pipe->screen, PIPE_CAP_TGSI_INSTANCEID) && + pipe->screen->get_param(pipe->screen, PIPE_CAP_TGSI_VS_LAYER)) { + ctx->vs_layered = util_make_layered_clear_vertex_shader(pipe); + } + /* set invariant vertex coordinates */ for (i = 0; i < 4; i++) ctx->vertices[i][0][3] = 1; /*v.w*/ @@ -323,11 +342,15 @@ void util_blitter_destroy(struct blitter_context *blitter) { struct blitter_context_priv *ctx = (struct blitter_context_priv*)blitter; struct pipe_context *pipe = blitter->pipe; - int i; + int i, j, f; for (i = 0; i <= PIPE_MASK_RGBA; i++) { pipe->delete_blend_state(pipe, ctx->blend[i]); } + for (i = 0; i < Elements(ctx->blend_clear); i++) { + if (ctx->blend_clear[i]) + pipe->delete_blend_state(pipe, ctx->blend_clear[i]); + } pipe->delete_depth_stencil_alpha_state(pipe, ctx->dsa_keep_depth_stencil); pipe->delete_depth_stencil_alpha_state(pipe, ctx->dsa_write_depth_keep_stencil); @@ -357,7 +380,23 @@ void util_blitter_destroy(struct blitter_context *blitter) ctx->delete_fs_state(pipe, ctx->fs_texfetch_depthstencil[i]); if (ctx->fs_texfetch_stencil[i]) ctx->delete_fs_state(pipe, ctx->fs_texfetch_stencil[i]); + + for (j = 0; j< Elements(ctx->fs_resolve[i]); j++) + for (f = 0; f < 2; f++) + if (ctx->fs_resolve[i][j][f]) + ctx->delete_fs_state(pipe, ctx->fs_resolve[i][j][f]); + + for (j = 0; j< Elements(ctx->fs_resolve_sint[i]); j++) + for (f = 0; f < 2; f++) + if (ctx->fs_resolve_sint[i][j][f]) + ctx->delete_fs_state(pipe, ctx->fs_resolve_sint[i][j][f]); + + for (j = 0; j< Elements(ctx->fs_resolve_uint[i]); j++) + for (f = 0; f < 2; f++) + if (ctx->fs_resolve_uint[i][j][f]) + ctx->delete_fs_state(pipe, ctx->fs_resolve_uint[i][j][f]); } + ctx->delete_fs_state(pipe, ctx->fs_empty); ctx->delete_fs_state(pipe, ctx->fs_write_one_cbuf); ctx->delete_fs_state(pipe, ctx->fs_write_all_cbufs); @@ -711,22 +750,60 @@ static void blitter_set_dst_dimensions(struct blitter_context_priv *ctx, } static void *blitter_get_fs_texfetch_col(struct blitter_context_priv *ctx, + enum pipe_format format, enum pipe_texture_target target, - unsigned nr_samples) + unsigned src_nr_samples, + unsigned dst_nr_samples, + unsigned filter) { struct pipe_context *pipe = ctx->base.pipe; + unsigned tgsi_tex = util_pipe_tex_to_tgsi_tex(target, src_nr_samples); assert(target < PIPE_MAX_TEXTURE_TYPES); - if (nr_samples > 1) { - void **shader = &ctx->fs_texfetch_col_msaa[target]; + if (src_nr_samples > 1) { + void **shader; - /* Create the fragment shader on-demand. */ - if (!*shader) { - unsigned tgsi_tex = util_pipe_tex_to_tgsi_tex(target, - nr_samples); + if (dst_nr_samples <= 1) { + /* The destination has one sample, so we'll do color resolve. */ + boolean is_uint, is_sint; + unsigned index = GET_MSAA_RESOLVE_FS_IDX(src_nr_samples); - *shader = util_make_fs_blit_msaa_color(pipe, tgsi_tex); + is_uint = util_format_is_pure_uint(format); + is_sint = util_format_is_pure_sint(format); + + assert(filter < 2); + + if (is_uint) + shader = &ctx->fs_resolve_uint[target][index][filter]; + else if (is_sint) + shader = &ctx->fs_resolve_sint[target][index][filter]; + else + shader = &ctx->fs_resolve[target][index][filter]; + + if (!*shader) { + if (filter == PIPE_TEX_FILTER_LINEAR) { + *shader = util_make_fs_msaa_resolve_bilinear(pipe, tgsi_tex, + src_nr_samples, + is_uint, is_sint); + } + else { + *shader = util_make_fs_msaa_resolve(pipe, tgsi_tex, + src_nr_samples, + is_uint, is_sint); + } + } + } + else { + /* The destination has multiple samples, we'll do + * an MSAA->MSAA copy. + */ + shader = &ctx->fs_texfetch_col_msaa[target]; + + /* Create the fragment shader on-demand. */ + if (!*shader) { + *shader = util_make_fs_blit_msaa_color(pipe, tgsi_tex); + } } return *shader; @@ -735,11 +812,8 @@ static void *blitter_get_fs_texfetch_col(struct blitter_context_priv *ctx, /* Create the fragment shader on-demand. */ if (!*shader) { - unsigned tgsi_tex = util_pipe_tex_to_tgsi_tex(target, 0); - - *shader = - util_make_fragment_tex_shader(pipe, tgsi_tex, - TGSI_INTERPOLATE_LINEAR); + *shader = util_make_fragment_tex_shader(pipe, tgsi_tex, + TGSI_INTERPOLATE_LINEAR); } return *shader; @@ -864,7 +938,7 @@ void util_blitter_cache_all_shaders(struct blitter_context *blitter) { struct blitter_context_priv *ctx = (struct blitter_context_priv*)blitter; struct pipe_screen *screen = blitter->pipe->screen; - unsigned i, target, max_samples; + unsigned samples, j, f, target, max_samples; boolean has_arraytex, has_cubearraytex; max_samples = ctx->has_texture_multisample ? 2 : 1; @@ -874,7 +948,7 @@ void util_blitter_cache_all_shaders(struct blitter_context *blitter) PIPE_CAP_CUBE_MAP_ARRAY) != 0; /* It only matters if i <= 1 or > 1. */ - for (i = 1; i <= max_samples; i++) { + for (samples = 1; samples <= max_samples; samples++) { for (target = PIPE_TEXTURE_1D; target < PIPE_MAX_TEXTURE_TYPES; target++) { if (!has_arraytex && (target == PIPE_TEXTURE_1D_ARRAY || @@ -885,29 +959,55 @@ void util_blitter_cache_all_shaders(struct blitter_context *blitter) (target == PIPE_TEXTURE_CUBE_ARRAY)) continue; - if (i > 1 && + if (samples > 1 && (target != PIPE_TEXTURE_2D && target != PIPE_TEXTURE_2D_ARRAY)) continue; - blitter_get_fs_texfetch_col(ctx, target, i); - blitter_get_fs_texfetch_depth(ctx, target, i); + /* If samples == 1, the shaders read one texel. If samples >= 1, + * they read one sample. + */ + blitter_get_fs_texfetch_col(ctx, PIPE_FORMAT_R32_FLOAT, target, + samples, samples, 0); + blitter_get_fs_texfetch_depth(ctx, target, samples); if (ctx->has_stencil_export) { - blitter_get_fs_texfetch_depthstencil(ctx, target, i); - blitter_get_fs_texfetch_stencil(ctx, target, i); + blitter_get_fs_texfetch_depthstencil(ctx, target, samples); + blitter_get_fs_texfetch_stencil(ctx, target, samples); + } + + if (samples == 1) + continue; + + /* MSAA resolve shaders. */ + for (j = 2; j < 32; j++) { + if (!screen->is_format_supported(screen, PIPE_FORMAT_R32_FLOAT, + target, j, + PIPE_BIND_SAMPLER_VIEW)) { + continue; + } + + for (f = 0; f < 2; f++) { + blitter_get_fs_texfetch_col(ctx, PIPE_FORMAT_R32_FLOAT, target, + j, 1, f); + blitter_get_fs_texfetch_col(ctx, PIPE_FORMAT_R32_UINT, target, + j, 1, f); + blitter_get_fs_texfetch_col(ctx, PIPE_FORMAT_R32_SINT, target, + j, 1, f); + } } } } } static void blitter_set_common_draw_rect_state(struct blitter_context_priv *ctx, - boolean scissor) + boolean scissor, + boolean vs_layered) { struct pipe_context *pipe = ctx->base.pipe; pipe->bind_rasterizer_state(pipe, scissor ? ctx->rs_state_scissor : ctx->rs_state); - pipe->bind_vs_state(pipe, ctx->vs); + pipe->bind_vs_state(pipe, vs_layered ? ctx->vs_layered : ctx->vs); if (ctx->has_geometry_shader) pipe->bind_gs_state(pipe, NULL); if (ctx->has_stream_out) @@ -915,19 +1015,24 @@ static void blitter_set_common_draw_rect_state(struct blitter_context_priv *ctx, } static void blitter_draw(struct blitter_context_priv *ctx, - int x1, int y1, int x2, int y2, float depth) + int x1, int y1, int x2, int y2, float depth, + unsigned num_instances) { - struct pipe_resource *buf = NULL; - unsigned offset = 0; + struct pipe_context *pipe = ctx->base.pipe; + struct pipe_vertex_buffer vb = {0}; blitter_set_rectangle(ctx, x1, y1, x2, y2, depth); + vb.stride = 8 * sizeof(float); + u_upload_data(ctx->upload, 0, sizeof(ctx->vertices), ctx->vertices, - &offset, &buf); + &vb.buffer_offset, &vb.buffer); u_upload_unmap(ctx->upload); - util_draw_vertex_buffer(ctx->base.pipe, NULL, buf, ctx->base.vb_slot, - offset, PIPE_PRIM_TRIANGLE_FAN, 4, 2); - pipe_resource_reference(&buf, NULL); + + pipe->set_vertex_buffers(pipe, ctx->base.vb_slot, 1, &vb); + util_draw_arrays_instanced(pipe, PIPE_PRIM_TRIANGLE_FAN, 0, 4, + 0, num_instances); + pipe_resource_reference(&vb.buffer, NULL); } void util_blitter_draw_rectangle(struct blitter_context *blitter, @@ -949,11 +1054,47 @@ void util_blitter_draw_rectangle(struct blitter_context *blitter, default:; } - blitter_draw(ctx, x1, y1, x2, y2, depth); + blitter_draw(ctx, x1, y1, x2, y2, depth, 1); +} + +static void *get_clear_blend_state(struct blitter_context_priv *ctx, + unsigned clear_buffers) +{ + struct pipe_context *pipe = ctx->base.pipe; + int index; + + clear_buffers &= PIPE_CLEAR_COLOR; + + /* Return an existing blend state. */ + if (!clear_buffers) + return ctx->blend[0]; + + index = GET_CLEAR_BLEND_STATE_IDX(clear_buffers); + + if (ctx->blend_clear[index]) + return ctx->blend_clear[index]; + + /* Create a new one. */ + { + struct pipe_blend_state blend = {0}; + unsigned i; + + blend.independent_blend_enable = 1; + + for (i = 0; i < PIPE_MAX_COLOR_BUFS; i++) { + if (clear_buffers & (PIPE_CLEAR_COLOR0 << i)) { + blend.rt[i].colormask = PIPE_MASK_RGBA; + } + } + + ctx->blend_clear[index] = pipe->create_blend_state(pipe, &blend); + } + return ctx->blend_clear[index]; } static void util_blitter_clear_custom(struct blitter_context *blitter, unsigned width, unsigned height, + unsigned num_layers, unsigned clear_buffers, const union pipe_color_union *color, double depth, unsigned stencil, @@ -963,6 +1104,8 @@ static void util_blitter_clear_custom(struct blitter_context *blitter, struct pipe_context *pipe = ctx->base.pipe; struct pipe_stencil_ref sr = { { 0 } }; + assert(ctx->vs_layered || num_layers <= 1); + blitter_set_running_flag(ctx); blitter_check_saved_vertex_states(ctx); blitter_check_saved_fragment_states(ctx); @@ -971,10 +1114,8 @@ static void util_blitter_clear_custom(struct blitter_context *blitter, /* bind states */ if (custom_blend) { pipe->bind_blend_state(pipe, custom_blend); - } else if (clear_buffers & PIPE_CLEAR_COLOR) { - pipe->bind_blend_state(pipe, ctx->blend[PIPE_MASK_RGBA]); } else { - pipe->bind_blend_state(pipe, ctx->blend[0]); + pipe->bind_blend_state(pipe, get_clear_blend_state(ctx, clear_buffers)); } if (custom_dsa) { @@ -996,10 +1137,18 @@ static void util_blitter_clear_custom(struct blitter_context *blitter, ctx->bind_fs_state(pipe, ctx->fs_write_all_cbufs); pipe->set_sample_mask(pipe, ~0); - blitter_set_common_draw_rect_state(ctx, FALSE); blitter_set_dst_dimensions(ctx, width, height); - blitter->draw_rectangle(blitter, 0, 0, width, height, (float) depth, - UTIL_BLITTER_ATTRIB_COLOR, color); + + if (num_layers > 1 && ctx->vs_layered) { + blitter_set_common_draw_rect_state(ctx, FALSE, TRUE); + blitter_set_clear_color(ctx, color); + blitter_draw(ctx, 0, 0, width, height, depth, num_layers); + } + else { + blitter_set_common_draw_rect_state(ctx, FALSE, FALSE); + blitter->draw_rectangle(blitter, 0, 0, width, height, (float) depth, + UTIL_BLITTER_ATTRIB_COLOR, color); + } blitter_restore_vertex_states(ctx); blitter_restore_fragment_states(ctx); @@ -1008,12 +1157,12 @@ static void util_blitter_clear_custom(struct blitter_context *blitter, } void util_blitter_clear(struct blitter_context *blitter, - unsigned width, unsigned height, + unsigned width, unsigned height, unsigned num_layers, unsigned clear_buffers, const union pipe_color_union *color, double depth, unsigned stencil) { - util_blitter_clear_custom(blitter, width, height, + util_blitter_clear_custom(blitter, width, height, num_layers, clear_buffers, color, depth, stencil, NULL, NULL); } @@ -1023,7 +1172,7 @@ void util_blitter_custom_clear_depth(struct blitter_context *blitter, double depth, void *custom_dsa) { static const union pipe_color_union color; - util_blitter_clear_custom(blitter, width, height, 0, &color, depth, 0, + util_blitter_clear_custom(blitter, width, height, 0, 0, &color, depth, 0, NULL, custom_dsa); } @@ -1137,11 +1286,10 @@ static boolean is_blit_generic_supported(struct blitter_context *blitter, boolean util_blitter_is_copy_supported(struct blitter_context *blitter, const struct pipe_resource *dst, - const struct pipe_resource *src, - unsigned mask) + const struct pipe_resource *src) { return is_blit_generic_supported(blitter, dst, dst->format, - src, src->format, mask); + src, src->format, PIPE_MASK_RGBAZS); } boolean util_blitter_is_blit_supported(struct blitter_context *blitter, @@ -1159,8 +1307,7 @@ void util_blitter_copy_texture(struct blitter_context *blitter, unsigned dstx, unsigned dsty, unsigned dstz, struct pipe_resource *src, unsigned src_level, - const struct pipe_box *srcbox, unsigned mask, - boolean copy_all_samples) + const struct pipe_box *srcbox) { struct blitter_context_priv *ctx = (struct blitter_context_priv*)blitter; struct pipe_context *pipe = ctx->base.pipe; @@ -1185,8 +1332,7 @@ void util_blitter_copy_texture(struct blitter_context *blitter, /* Copy. */ util_blitter_blit_generic(blitter, dst_view, &dstbox, src_view, srcbox, src->width0, src->height0, - mask, PIPE_TEX_FILTER_NEAREST, NULL, - copy_all_samples); + PIPE_MASK_RGBAZS, PIPE_TEX_FILTER_NEAREST, NULL); pipe_surface_reference(&dst_view, NULL); pipe_sampler_view_reference(&src_view, NULL); @@ -1199,14 +1345,14 @@ void util_blitter_blit_generic(struct blitter_context *blitter, const struct pipe_box *srcbox, unsigned src_width0, unsigned src_height0, unsigned mask, unsigned filter, - const struct pipe_scissor_state *scissor, - boolean copy_all_samples) + const struct pipe_scissor_state *scissor) { struct blitter_context_priv *ctx = (struct blitter_context_priv*)blitter; struct pipe_context *pipe = ctx->base.pipe; struct pipe_framebuffer_state fb_state; enum pipe_texture_target src_target = src->texture->target; unsigned src_samples = src->texture->nr_samples; + unsigned dst_samples = dst->texture->nr_samples; boolean has_depth, has_stencil, has_color; boolean blit_stencil, blit_depth, blit_color; void *sampler_state; @@ -1231,6 +1377,12 @@ void util_blitter_blit_generic(struct blitter_context *blitter, return; } + if (blit_stencil || + (dstbox->width == abs(srcbox->width) && + dstbox->height == abs(srcbox->height))) { + filter = PIPE_TEX_FILTER_NEAREST; + } + /* Check whether the states are properly saved. */ blitter_set_running_flag(ctx); blitter_check_saved_vertex_states(ctx); @@ -1273,16 +1425,12 @@ void util_blitter_blit_generic(struct blitter_context *blitter, pipe->bind_blend_state(pipe, ctx->blend[mask & PIPE_MASK_RGBA]); pipe->bind_depth_stencil_alpha_state(pipe, ctx->dsa_keep_depth_stencil); ctx->bind_fs_state(pipe, - blitter_get_fs_texfetch_col(ctx, src_target, - src_samples)); + blitter_get_fs_texfetch_col(ctx, src->format, src_target, + src_samples, dst_samples, filter)); } /* Set the linear filter only for scaled color non-MSAA blits. */ - if (filter == PIPE_TEX_FILTER_LINEAR && - !blit_depth && !blit_stencil && - src_samples <= 1 && - (dstbox->width != abs(srcbox->width) || - dstbox->height != abs(srcbox->height))) { + if (filter == PIPE_TEX_FILTER_LINEAR) { if (src_target == PIPE_TEXTURE_RECT) { sampler_state = ctx->sampler_state_rect_linear; } else { @@ -1341,7 +1489,7 @@ void util_blitter_blit_generic(struct blitter_context *blitter, pipe->set_scissor_states(pipe, 0, 1, scissor); } - blitter_set_common_draw_rect_state(ctx, scissor != NULL); + blitter_set_common_draw_rect_state(ctx, scissor != NULL, FALSE); blitter_set_dst_dimensions(ctx, dst->width, dst->height); if ((src_target == PIPE_TEXTURE_1D || @@ -1388,10 +1536,9 @@ void util_blitter_blit_generic(struct blitter_context *blitter, pipe->set_framebuffer_state(pipe, &fb_state); /* See if we need to blit a multisample or singlesample buffer. */ - if (copy_all_samples && - src_samples == dst->texture->nr_samples && - dst->texture->nr_samples > 1) { - unsigned i, max_sample = MAX2(dst->texture->nr_samples, 1) - 1; + if (src_samples == dst_samples && dst_samples > 1) { + /* MSAA copy. */ + unsigned i, max_sample = dst_samples - 1; for (i = 0; i <= max_sample; i++) { pipe->set_sample_mask(pipe, 1 << i); @@ -1402,9 +1549,10 @@ void util_blitter_blit_generic(struct blitter_context *blitter, srcbox->y + srcbox->height); blitter_draw(ctx, dstbox->x, dstbox->y, dstbox->x + dstbox->width, - dstbox->y + dstbox->height, 0); + dstbox->y + dstbox->height, 0, 1); } } else { + /* Normal copy, MSAA upsampling, or MSAA resolve. */ pipe->set_sample_mask(pipe, ~0); blitter_set_texcoords(ctx, src, src_width0, src_height0, srcbox->z + z, 0, @@ -1413,7 +1561,7 @@ void util_blitter_blit_generic(struct blitter_context *blitter, srcbox->y + srcbox->height); blitter_draw(ctx, dstbox->x, dstbox->y, dstbox->x + dstbox->width, - dstbox->y + dstbox->height, 0); + dstbox->y + dstbox->height, 0, 1); } /* Get the next surface or (if this is the last iteration) @@ -1465,7 +1613,7 @@ util_blitter_blit(struct blitter_context *blitter, util_blitter_blit_generic(blitter, dst_view, &info->dst.box, src_view, &info->src.box, src->width0, src->height0, info->mask, info->filter, - info->scissor_enable ? &info->scissor : NULL, TRUE); + info->scissor_enable ? &info->scissor : NULL); pipe_surface_reference(&dst_view, NULL); pipe_sampler_view_reference(&src_view, NULL); @@ -1508,7 +1656,7 @@ void util_blitter_clear_render_target(struct blitter_context *blitter, pipe->set_framebuffer_state(pipe, &fb_state); pipe->set_sample_mask(pipe, ~0); - blitter_set_common_draw_rect_state(ctx, FALSE); + blitter_set_common_draw_rect_state(ctx, FALSE, FALSE); blitter_set_dst_dimensions(ctx, dstsurf->width, dstsurf->height); blitter->draw_rectangle(blitter, dstx, dsty, dstx+width, dsty+height, 0, UTIL_BLITTER_ATTRIB_COLOR, color); @@ -1576,7 +1724,7 @@ void util_blitter_clear_depth_stencil(struct blitter_context *blitter, pipe->set_framebuffer_state(pipe, &fb_state); pipe->set_sample_mask(pipe, ~0); - blitter_set_common_draw_rect_state(ctx, FALSE); + blitter_set_common_draw_rect_state(ctx, FALSE, FALSE); blitter_set_dst_dimensions(ctx, dstsurf->width, dstsurf->height); blitter->draw_rectangle(blitter, dstx, dsty, dstx+width, dsty+height, (float) depth, @@ -1633,7 +1781,7 @@ void util_blitter_custom_depth_stencil(struct blitter_context *blitter, pipe->set_framebuffer_state(pipe, &fb_state); pipe->set_sample_mask(pipe, sample_mask); - blitter_set_common_draw_rect_state(ctx, FALSE); + blitter_set_common_draw_rect_state(ctx, FALSE, FALSE); blitter_set_dst_dimensions(ctx, zsurf->width, zsurf->height); blitter->draw_rectangle(blitter, 0, 0, zsurf->width, zsurf->height, depth, UTIL_BLITTER_ATTRIB_NONE, NULL); @@ -1818,7 +1966,7 @@ void util_blitter_custom_resolve_color(struct blitter_context *blitter, fb_state.zsbuf = NULL; pipe->set_framebuffer_state(pipe, &fb_state); - blitter_set_common_draw_rect_state(ctx, FALSE); + blitter_set_common_draw_rect_state(ctx, FALSE, FALSE); blitter_set_dst_dimensions(ctx, src->width0, src->height0); blitter->draw_rectangle(blitter, 0, 0, src->width0, src->height0, 0, 0, NULL); @@ -1868,7 +2016,7 @@ void util_blitter_custom_color(struct blitter_context *blitter, pipe->set_framebuffer_state(pipe, &fb_state); pipe->set_sample_mask(pipe, ~0); - blitter_set_common_draw_rect_state(ctx, FALSE); + blitter_set_common_draw_rect_state(ctx, FALSE, FALSE); blitter_set_dst_dimensions(ctx, dstsurf->width, dstsurf->height); blitter->draw_rectangle(blitter, 0, 0, dstsurf->width, dstsurf->height, 0, 0, NULL); diff --git a/mesalib/src/gallium/auxiliary/util/u_blitter.h b/mesalib/src/gallium/auxiliary/util/u_blitter.h index d9cefde50..a30cdc36a 100644 --- a/mesalib/src/gallium/auxiliary/util/u_blitter.h +++ b/mesalib/src/gallium/auxiliary/util/u_blitter.h @@ -183,7 +183,7 @@ void util_blitter_draw_rectangle(struct blitter_context *blitter, * - blend state */ void util_blitter_clear(struct blitter_context *blitter, - unsigned width, unsigned height, + unsigned width, unsigned height, unsigned num_layers, unsigned clear_buffers, const union pipe_color_union *color, double depth, unsigned stencil); @@ -191,13 +191,10 @@ void util_blitter_clear(struct blitter_context *blitter, /** * Check if the blitter (with the help of the driver) can blit between * the two resources. - * The mask is a combination of the PIPE_MASK_* flags. - * Set to PIPE_MASK_RGBAZS if unsure. */ boolean util_blitter_is_copy_supported(struct blitter_context *blitter, const struct pipe_resource *dst, - const struct pipe_resource *src, - unsigned mask); + const struct pipe_resource *src); boolean util_blitter_is_blit_supported(struct blitter_context *blitter, const struct pipe_blit_info *info); @@ -221,8 +218,7 @@ void util_blitter_copy_texture(struct blitter_context *blitter, unsigned dstx, unsigned dsty, unsigned dstz, struct pipe_resource *src, unsigned src_level, - const struct pipe_box *srcbox, unsigned mask, - boolean copy_all_samples); + const struct pipe_box *srcbox); /** * This is a generic implementation of pipe->blit, which accepts @@ -250,8 +246,7 @@ void util_blitter_blit_generic(struct blitter_context *blitter, const struct pipe_box *srcbox, unsigned src_width0, unsigned src_height0, unsigned mask, unsigned filter, - const struct pipe_scissor_state *scissor, - boolean copy_all_samples); + const struct pipe_scissor_state *scissor); void util_blitter_blit(struct blitter_context *blitter, const struct pipe_blit_info *info); diff --git a/mesalib/src/gallium/auxiliary/util/u_clear.h b/mesalib/src/gallium/auxiliary/util/u_clear.h index e9fd874b1..75047c16b 100644 --- a/mesalib/src/gallium/auxiliary/util/u_clear.h +++ b/mesalib/src/gallium/auxiliary/util/u_clear.h @@ -42,9 +42,10 @@ util_clear(struct pipe_context *pipe, struct pipe_framebuffer_state *framebuffer, unsigned buffers, const union pipe_color_union *color, double depth, unsigned stencil) { - if (buffers & PIPE_CLEAR_COLOR) { - unsigned i; - for (i = 0; i < framebuffer->nr_cbufs; i++) { + unsigned i; + + for (i = 0; i < framebuffer->nr_cbufs; i++) { + if (buffers & (PIPE_CLEAR_COLOR0 << i)) { struct pipe_surface *ps = framebuffer->cbufs[i]; pipe->clear_render_target(pipe, ps, color, 0, 0, ps->width, ps->height); } diff --git a/mesalib/src/gallium/auxiliary/util/u_framebuffer.c b/mesalib/src/gallium/auxiliary/util/u_framebuffer.c index f84485d1f..683967237 100644 --- a/mesalib/src/gallium/auxiliary/util/u_framebuffer.c +++ b/mesalib/src/gallium/auxiliary/util/u_framebuffer.c @@ -147,3 +147,27 @@ util_framebuffer_min_size(const struct pipe_framebuffer_state *fb, return TRUE; } } + + +/** + * Return the number of layers set in the framebuffer state. + */ +unsigned +util_framebuffer_get_num_layers(const struct pipe_framebuffer_state *fb) +{ + unsigned i, num_layers = 0; + + for (i = 0; i < fb->nr_cbufs; i++) { + if (fb->cbufs[i]) { + unsigned num = fb->cbufs[i]->u.tex.last_layer - + fb->cbufs[i]->u.tex.first_layer + 1; + num_layers = MAX2(num_layers, num); + } + } + if (fb->zsbuf) { + unsigned num = fb->zsbuf->u.tex.last_layer - + fb->zsbuf->u.tex.first_layer + 1; + num_layers = MAX2(num_layers, num); + } + return num_layers; +} diff --git a/mesalib/src/gallium/auxiliary/util/u_framebuffer.h b/mesalib/src/gallium/auxiliary/util/u_framebuffer.h index a89066230..0e6c98363 100644 --- a/mesalib/src/gallium/auxiliary/util/u_framebuffer.h +++ b/mesalib/src/gallium/auxiliary/util/u_framebuffer.h @@ -55,6 +55,11 @@ util_framebuffer_min_size(const struct pipe_framebuffer_state *fb, unsigned *width, unsigned *height); + +extern unsigned +util_framebuffer_get_num_layers(const struct pipe_framebuffer_state *fb); + + #ifdef __cplusplus } #endif diff --git a/mesalib/src/gallium/auxiliary/util/u_simple_shaders.c b/mesalib/src/gallium/auxiliary/util/u_simple_shaders.c index c93d75469..82f23ebec 100644 --- a/mesalib/src/gallium/auxiliary/util/u_simple_shaders.c +++ b/mesalib/src/gallium/auxiliary/util/u_simple_shaders.c @@ -99,6 +99,32 @@ util_make_vertex_passthrough_shader_with_so(struct pipe_context *pipe, } +void *util_make_layered_clear_vertex_shader(struct pipe_context *pipe) +{ + static const char text[] = + "VERT\n" + "DCL IN[0]\n" + "DCL IN[1]\n" + "DCL SV[0], INSTANCEID\n" + "DCL OUT[0], POSITION\n" + "DCL OUT[1], GENERIC[0]\n" + "DCL OUT[2], LAYER\n" + + "MOV OUT[0], IN[0]\n" + "MOV OUT[1], IN[1]\n" + "MOV OUT[2], SV[0]\n" + "END\n"; + struct tgsi_token tokens[1000]; + struct pipe_shader_state state = {tokens}; + + if (!tgsi_text_translate(text, tokens, Elements(tokens))) { + assert(0); + return NULL; + } + return pipe->create_vs_state(pipe, &state); +} + + /** * Make simple fragment texture shader: * IMM {0,0,0,1} // (if writemask != 0xf) @@ -527,3 +553,157 @@ util_make_fs_blit_msaa_depthstencil(struct pipe_context *pipe, return pipe->create_fs_state(pipe, &state); } + + +void * +util_make_fs_msaa_resolve(struct pipe_context *pipe, + unsigned tgsi_tex, unsigned nr_samples, + boolean is_uint, boolean is_sint) +{ + struct ureg_program *ureg; + struct ureg_src sampler, coord; + struct ureg_dst out, tmp_sum, tmp_coord, tmp; + int i; + + ureg = ureg_create(TGSI_PROCESSOR_FRAGMENT); + if (!ureg) + return NULL; + + /* Declarations. */ + sampler = ureg_DECL_sampler(ureg, 0); + coord = ureg_DECL_fs_input(ureg, TGSI_SEMANTIC_GENERIC, 0, + TGSI_INTERPOLATE_LINEAR); + out = ureg_DECL_output(ureg, TGSI_SEMANTIC_COLOR, 0); + tmp_sum = ureg_DECL_temporary(ureg); + tmp_coord = ureg_DECL_temporary(ureg); + tmp = ureg_DECL_temporary(ureg); + + /* Instructions. */ + ureg_MOV(ureg, tmp_sum, ureg_imm1f(ureg, 0)); + ureg_F2U(ureg, tmp_coord, coord); + + for (i = 0; i < nr_samples; i++) { + /* Read one sample. */ + ureg_MOV(ureg, ureg_writemask(tmp_coord, TGSI_WRITEMASK_W), + ureg_imm1u(ureg, i)); + ureg_TXF(ureg, tmp, tgsi_tex, ureg_src(tmp_coord), sampler); + + if (is_uint) + ureg_U2F(ureg, tmp, ureg_src(tmp)); + else if (is_sint) + ureg_I2F(ureg, tmp, ureg_src(tmp)); + + /* Add it to the sum.*/ + ureg_ADD(ureg, tmp_sum, ureg_src(tmp_sum), ureg_src(tmp)); + } + + /* Calculate the average and return. */ + ureg_MUL(ureg, tmp_sum, ureg_src(tmp_sum), + ureg_imm1f(ureg, 1.0 / nr_samples)); + + if (is_uint) + ureg_F2U(ureg, out, ureg_src(tmp_sum)); + else if (is_sint) + ureg_F2I(ureg, out, ureg_src(tmp_sum)); + else + ureg_MOV(ureg, out, ureg_src(tmp_sum)); + + ureg_END(ureg); + + return ureg_create_shader_and_destroy(ureg, pipe); +} + + +void * +util_make_fs_msaa_resolve_bilinear(struct pipe_context *pipe, + unsigned tgsi_tex, unsigned nr_samples, + boolean is_uint, boolean is_sint) +{ + struct ureg_program *ureg; + struct ureg_src sampler, coord; + struct ureg_dst out, tmp, top, bottom; + struct ureg_dst tmp_coord[4], tmp_sum[4]; + int i, c; + + ureg = ureg_create(TGSI_PROCESSOR_FRAGMENT); + if (!ureg) + return NULL; + + /* Declarations. */ + sampler = ureg_DECL_sampler(ureg, 0); + coord = ureg_DECL_fs_input(ureg, TGSI_SEMANTIC_GENERIC, 0, + TGSI_INTERPOLATE_LINEAR); + out = ureg_DECL_output(ureg, TGSI_SEMANTIC_COLOR, 0); + for (c = 0; c < 4; c++) + tmp_sum[c] = ureg_DECL_temporary(ureg); + for (c = 0; c < 4; c++) + tmp_coord[c] = ureg_DECL_temporary(ureg); + tmp = ureg_DECL_temporary(ureg); + top = ureg_DECL_temporary(ureg); + bottom = ureg_DECL_temporary(ureg); + + /* Instructions. */ + for (c = 0; c < 4; c++) + ureg_MOV(ureg, tmp_sum[c], ureg_imm1f(ureg, 0)); + + /* Get 4 texture coordinates for the bilinear filter. */ + ureg_F2U(ureg, tmp_coord[0], coord); /* top-left */ + ureg_UADD(ureg, tmp_coord[1], ureg_src(tmp_coord[0]), + ureg_imm4u(ureg, 1, 0, 0, 0)); /* top-right */ + ureg_UADD(ureg, tmp_coord[2], ureg_src(tmp_coord[0]), + ureg_imm4u(ureg, 0, 1, 0, 0)); /* bottom-left */ + ureg_UADD(ureg, tmp_coord[3], ureg_src(tmp_coord[0]), + ureg_imm4u(ureg, 1, 1, 0, 0)); /* bottom-right */ + + for (i = 0; i < nr_samples; i++) { + for (c = 0; c < 4; c++) { + /* Read one sample. */ + ureg_MOV(ureg, ureg_writemask(tmp_coord[c], TGSI_WRITEMASK_W), + ureg_imm1u(ureg, i)); + ureg_TXF(ureg, tmp, tgsi_tex, ureg_src(tmp_coord[c]), sampler); + + if (is_uint) + ureg_U2F(ureg, tmp, ureg_src(tmp)); + else if (is_sint) + ureg_I2F(ureg, tmp, ureg_src(tmp)); + + /* Add it to the sum.*/ + ureg_ADD(ureg, tmp_sum[c], ureg_src(tmp_sum[c]), ureg_src(tmp)); + } + } + + /* Calculate the average. */ + for (c = 0; c < 4; c++) + ureg_MUL(ureg, tmp_sum[c], ureg_src(tmp_sum[c]), + ureg_imm1f(ureg, 1.0 / nr_samples)); + + /* Take the 4 average values and apply a standard bilinear filter. */ + ureg_FRC(ureg, tmp, coord); + + ureg_LRP(ureg, top, + ureg_scalar(ureg_src(tmp), 0), + ureg_src(tmp_sum[1]), + ureg_src(tmp_sum[0])); + + ureg_LRP(ureg, bottom, + ureg_scalar(ureg_src(tmp), 0), + ureg_src(tmp_sum[3]), + ureg_src(tmp_sum[2])); + + ureg_LRP(ureg, tmp, + ureg_scalar(ureg_src(tmp), 1), + ureg_src(bottom), + ureg_src(top)); + + /* Convert to the texture format and return. */ + if (is_uint) + ureg_F2U(ureg, out, ureg_src(tmp)); + else if (is_sint) + ureg_F2I(ureg, out, ureg_src(tmp)); + else + ureg_MOV(ureg, out, ureg_src(tmp)); + + ureg_END(ureg); + + return ureg_create_shader_and_destroy(ureg, pipe); +} diff --git a/mesalib/src/gallium/auxiliary/util/u_simple_shaders.h b/mesalib/src/gallium/auxiliary/util/u_simple_shaders.h index 016664d1b..e81d99414 100644 --- a/mesalib/src/gallium/auxiliary/util/u_simple_shaders.h +++ b/mesalib/src/gallium/auxiliary/util/u_simple_shaders.h @@ -56,6 +56,8 @@ util_make_vertex_passthrough_shader_with_so(struct pipe_context *pipe, const uint *semantic_indexes, const struct pipe_stream_output_info *so); +extern void * +util_make_layered_clear_vertex_shader(struct pipe_context *pipe); extern void * util_make_fragment_tex_shader_writemask(struct pipe_context *pipe, @@ -122,6 +124,18 @@ void * util_make_fs_blit_msaa_stencil(struct pipe_context *pipe, unsigned tgsi_tex); + +void * +util_make_fs_msaa_resolve(struct pipe_context *pipe, + unsigned tgsi_tex, unsigned nr_samples, + boolean is_uint, boolean is_sint); + + +void * +util_make_fs_msaa_resolve_bilinear(struct pipe_context *pipe, + unsigned tgsi_tex, unsigned nr_samples, + boolean is_uint, boolean is_sint); + #ifdef __cplusplus } #endif diff --git a/mesalib/src/glsl/ast.h b/mesalib/src/glsl/ast.h index 5c214b604..76911f056 100644 --- a/mesalib/src/glsl/ast.h +++ b/mesalib/src/glsl/ast.h @@ -357,6 +357,7 @@ struct ast_type_qualifier { unsigned in:1; unsigned out:1; unsigned centroid:1; + unsigned sample:1; unsigned uniform:1; unsigned smooth:1; unsigned flat:1; diff --git a/mesalib/src/glsl/ast_array_index.cpp b/mesalib/src/glsl/ast_array_index.cpp index f7b5e8350..a5f23206a 100644 --- a/mesalib/src/glsl/ast_array_index.cpp +++ b/mesalib/src/glsl/ast_array_index.cpp @@ -41,8 +41,8 @@ update_max_array_access(ir_rvalue *ir, unsigned idx, YYLTYPE *loc, { if (ir_dereference_variable *deref_var = ir->as_dereference_variable()) { ir_variable *var = deref_var->var; - if (idx > var->max_array_access) { - var->max_array_access = idx; + if (idx > var->data.max_array_access) { + var->data.max_array_access = idx; /* Check whether this access will, as a side effect, implicitly cause * the size of a built-in array to be too large. @@ -168,7 +168,7 @@ _mesa_ast_array_index_to_hir(void *mem_ctx, if (array->type->is_unsized_array()) { _mesa_glsl_error(&loc, state, "unsized array index must be constant"); } else if (array->type->fields.array->is_interface() - && array->variable_referenced()->mode == ir_var_uniform) { + && array->variable_referenced()->data.mode == ir_var_uniform) { /* Page 46 in section 4.3.7 of the OpenGL ES 3.00 spec says: * * "All indexes used to index a uniform block array must be @@ -184,7 +184,7 @@ _mesa_ast_array_index_to_hir(void *mem_ctx, */ ir_variable *v = array->whole_variable_referenced(); if (v != NULL) - v->max_array_access = array->type->array_size() - 1; + v->data.max_array_access = array->type->array_size() - 1; } /* From page 23 (29 of the PDF) of the GLSL 1.30 spec: diff --git a/mesalib/src/glsl/ast_function.cpp b/mesalib/src/glsl/ast_function.cpp index 2707522ef..e4c0fd1c4 100644 --- a/mesalib/src/glsl/ast_function.cpp +++ b/mesalib/src/glsl/ast_function.cpp @@ -123,7 +123,7 @@ verify_parameter_modes(_mesa_glsl_parse_state *state, YYLTYPE loc = actual_ast->get_location(); /* Verify that 'const_in' parameters are ir_constants. */ - if (formal->mode == ir_var_const_in && + if (formal->data.mode == ir_var_const_in && actual->ir_type != ir_type_constant) { _mesa_glsl_error(&loc, state, "parameter `in %s' must be a constant expression", @@ -132,10 +132,10 @@ verify_parameter_modes(_mesa_glsl_parse_state *state, } /* Verify that 'out' and 'inout' actual parameters are lvalues. */ - if (formal->mode == ir_var_function_out - || formal->mode == ir_var_function_inout) { + if (formal->data.mode == ir_var_function_out + || formal->data.mode == ir_var_function_inout) { const char *mode = NULL; - switch (formal->mode) { + switch (formal->data.mode) { case ir_var_function_out: mode = "out"; break; case ir_var_function_inout: mode = "inout"; break; default: assert(false); break; @@ -155,9 +155,9 @@ verify_parameter_modes(_mesa_glsl_parse_state *state, ir_variable *var = actual->variable_referenced(); if (var) - var->assigned = true; + var->data.assigned = true; - if (var && var->read_only) { + if (var && var->data.read_only) { _mesa_glsl_error(&loc, state, "function parameter '%s %s' references the " "read-only variable '%s'", @@ -274,20 +274,20 @@ fix_parameter(void *mem_ctx, ir_rvalue *actual, const glsl_type *formal_type, } /** - * If a function call is generated, \c call_ir will point to it on exit. - * Otherwise \c call_ir will be set to \c NULL. + * Generate a function call. + * + * For non-void functions, this returns a dereference of the temporary variable + * which stores the return value for the call. For void functions, this returns + * NULL. */ static ir_rvalue * generate_call(exec_list *instructions, ir_function_signature *sig, exec_list *actual_parameters, - ir_call **call_ir, struct _mesa_glsl_parse_state *state) { void *ctx = state; exec_list post_call_conversions; - *call_ir = NULL; - /* Perform implicit conversion of arguments. For out parameters, we need * to place them in a temporary variable and do the conversion after the * call takes place. Since we haven't emitted the call yet, we'll place @@ -304,7 +304,7 @@ generate_call(exec_list *instructions, ir_function_signature *sig, assert(formal != NULL); if (formal->type->is_numeric() || formal->type->is_boolean()) { - switch (formal->mode) { + switch (formal->data.mode) { case ir_var_const_in: case ir_var_function_in: { ir_rvalue *converted @@ -316,7 +316,7 @@ generate_call(exec_list *instructions, ir_function_signature *sig, case ir_var_function_inout: fix_parameter(ctx, actual, formal->type, instructions, &post_call_conversions, - formal->mode == ir_var_function_inout); + formal->data.mode == ir_var_function_inout); break; default: assert (!"Illegal formal parameter mode"); @@ -421,6 +421,25 @@ done: return sig; } +static void +print_function_prototypes(_mesa_glsl_parse_state *state, YYLTYPE *loc, + ir_function *f) +{ + if (f == NULL) + return; + + foreach_list (node, &f->signatures) { + ir_function_signature *sig = (ir_function_signature *) node; + + if (sig->is_builtin() && !sig->is_builtin_available(state)) + continue; + + char *str = prototype_string(sig->return_type, f->name, &sig->parameters); + _mesa_glsl_error(loc, state, " %s", str); + ralloc_free(str); + } +} + /** * Raise a "no matching function" error, listing all possible overloads the * compiler considered so developers can figure out what went wrong. @@ -431,30 +450,23 @@ no_matching_function_error(const char *name, exec_list *actual_parameters, _mesa_glsl_parse_state *state) { - char *str = prototype_string(NULL, name, actual_parameters); - _mesa_glsl_error(loc, state, "no matching function for call to `%s'", str); - ralloc_free(str); - - const char *prefix = "candidates are: "; + gl_shader *sh = _mesa_glsl_get_builtin_function_shader(); - for (int i = -1; i < (int) state->num_builtins_to_link; i++) { - glsl_symbol_table *syms = i >= 0 ? state->builtins_to_link[i]->symbols - : state->symbols; - ir_function *f = syms->get_function(name); - if (f == NULL) - continue; - - foreach_list (node, &f->signatures) { - ir_function_signature *sig = (ir_function_signature *) node; - - if (sig->is_builtin() && !sig->is_builtin_available(state)) - continue; + if (state->symbols->get_function(name) == NULL + && (!state->uses_builtin_functions + || sh->symbols->get_function(name) == NULL)) { + _mesa_glsl_error(loc, state, "no function with name '%s'", name); + } else { + char *str = prototype_string(NULL, name, actual_parameters); + _mesa_glsl_error(loc, state, + "no matching function for call to `%s'; candidates are:", + str); + ralloc_free(str); - str = prototype_string(sig->return_type, f->name, &sig->parameters); - _mesa_glsl_error(loc, state, "%s%s", prefix, str); - ralloc_free(str); + print_function_prototypes(state, loc, state->symbols->get_function(name)); - prefix = " "; + if (state->uses_builtin_functions) { + print_function_prototypes(state, loc, sh->symbols->get_function(name)); } } } @@ -1651,7 +1663,7 @@ ast_function_expression::hir(exec_list *instructions, } else { const ast_expression *id = subexpressions[0]; const char *func_name = id->primary_expression.identifier; - YYLTYPE loc = id->get_location(); + YYLTYPE loc = get_location(); exec_list actual_parameters; process_parameters(instructions, &actual_parameters, &this->expressions, @@ -1660,7 +1672,6 @@ ast_function_expression::hir(exec_list *instructions, ir_function_signature *sig = match_function_by_name(func_name, &actual_parameters, state); - ir_call *call = NULL; ir_rvalue *value = NULL; if (sig == NULL) { no_matching_function_error(func_name, &loc, &actual_parameters, state); @@ -1669,8 +1680,7 @@ ast_function_expression::hir(exec_list *instructions, /* an error has already been emitted */ value = ir_rvalue::error_value(ctx); } else { - value = generate_call(instructions, sig, &actual_parameters, - &call, state); + value = generate_call(instructions, sig, &actual_parameters, state); } return value; diff --git a/mesalib/src/glsl/ast_to_hir.cpp b/mesalib/src/glsl/ast_to_hir.cpp index 43cf49745..3bc181e87 100644 --- a/mesalib/src/glsl/ast_to_hir.cpp +++ b/mesalib/src/glsl/ast_to_hir.cpp @@ -728,7 +728,7 @@ mark_whole_array_access(ir_rvalue *access) ir_dereference_variable *deref = access->as_dereference_variable(); if (deref && deref->var) { - deref->var->max_array_access = deref->type->length - 1; + deref->var->data.max_array_access = deref->type->length - 1; } } @@ -767,7 +767,7 @@ do_assignment(exec_list *instructions, struct _mesa_glsl_parse_state *state, ir_variable *lhs_var = lhs->variable_referenced(); if (lhs_var) - lhs_var->assigned = true; + lhs_var->data.assigned = true; if (!error_emitted) { if (non_lvalue_description != NULL) { @@ -776,7 +776,7 @@ do_assignment(exec_list *instructions, struct _mesa_glsl_parse_state *state, non_lvalue_description); error_emitted = true; } else if (lhs->variable_referenced() != NULL - && lhs->variable_referenced()->read_only) { + && lhs->variable_referenced()->data.read_only) { _mesa_glsl_error(&lhs_loc, state, "assignment to read-only variable '%s'", lhs->variable_referenced()->name); @@ -819,11 +819,11 @@ do_assignment(exec_list *instructions, struct _mesa_glsl_parse_state *state, assert(var != NULL); - if (var->max_array_access >= unsigned(rhs->type->array_size())) { + if (var->data.max_array_access >= unsigned(rhs->type->array_size())) { /* FINISHME: This should actually log the location of the RHS. */ _mesa_glsl_error(& lhs_loc, state, "array size must be > %u due to " "previous access", - var->max_array_access); + var->data.max_array_access); } var->type = glsl_type::get_array_instance(lhs->type->element_type(), @@ -866,7 +866,7 @@ get_lvalue_copy(exec_list *instructions, ir_rvalue *lvalue) var = new(ctx) ir_variable(lvalue->type, "_post_incdec_tmp", ir_var_temporary); instructions->push_tail(var); - var->mode = ir_var_auto; + var->data.mode = ir_var_auto; instructions->push_tail(new(ctx) ir_assignment(new(ctx) ir_dereference_variable(var), lvalue)); @@ -1639,7 +1639,7 @@ ast_expression::hir(exec_list *instructions, state->symbols->get_variable(this->primary_expression.identifier); if (var != NULL) { - var->used = true; + var->data.used = true; result = new(ctx) ir_dereference_variable(var); } else { _mesa_glsl_error(& loc, state, "`%s' undeclared", @@ -1860,7 +1860,7 @@ ast_fully_specified_type::glsl_type(const char **name, if (type->base_type == GLSL_TYPE_FLOAT && state->es_shader - && state->target == fragment_shader + && state->target == MESA_SHADER_FRAGMENT && this->qualifier.precision == ast_precision_none && state->symbols->get_variable("#default precision") == NULL) { YYLTYPE loc = this->get_location(); @@ -1882,15 +1882,15 @@ ast_fully_specified_type::glsl_type(const char **name, * this function will produce undefined results. */ static bool -is_varying_var(ir_variable *var, _mesa_glsl_parser_targets target) +is_varying_var(ir_variable *var, gl_shader_type target) { switch (target) { - case vertex_shader: - return var->mode == ir_var_shader_out; - case fragment_shader: - return var->mode == ir_var_shader_in; + case MESA_SHADER_VERTEX: + return var->data.mode == ir_var_shader_out; + case MESA_SHADER_FRAGMENT: + return var->data.mode == ir_var_shader_in; default: - return var->mode == ir_var_shader_out || var->mode == ir_var_shader_in; + return var->data.mode == ir_var_shader_out || var->data.mode == ir_var_shader_in; } } @@ -1941,7 +1941,7 @@ validate_binding_qualifier(struct _mesa_glsl_parse_state *state, ir_variable *var, const ast_type_qualifier *qual) { - if (var->mode != ir_var_uniform) { + if (var->data.mode != ir_var_uniform) { _mesa_glsl_error(loc, state, "the \"binding\" qualifier only applies to uniforms"); return false; @@ -1985,13 +1985,13 @@ validate_binding_qualifier(struct _mesa_glsl_parse_state *state, */ unsigned limit = 0; switch (state->target) { - case vertex_shader: + case MESA_SHADER_VERTEX: limit = ctx->Const.VertexProgram.MaxTextureImageUnits; break; - case geometry_shader: + case MESA_SHADER_GEOMETRY: limit = ctx->Const.GeometryProgram.MaxTextureImageUnits; break; - case fragment_shader: + case MESA_SHADER_FRAGMENT: limit = ctx->Const.FragmentProgram.MaxTextureImageUnits; break; } @@ -2049,8 +2049,8 @@ interpret_interpolation_qualifier(const struct ast_type_qualifier *qual, } - if ((state->target == vertex_shader && mode == ir_var_shader_in) || - (state->target == fragment_shader && mode == ir_var_shader_out)) { + if ((state->target == MESA_SHADER_VERTEX && mode == ir_var_shader_in) || + (state->target == MESA_SHADER_FRAGMENT && mode == ir_var_shader_out)) { _mesa_glsl_error(loc, state, "interpolation qualifier `%s' cannot be applied to " "vertex shader inputs or fragment shader outputs", @@ -2077,8 +2077,8 @@ validate_explicit_location(const struct ast_type_qualifier *qual, * locations. */ switch (state->target) { - case vertex_shader: - if (var->mode == ir_var_shader_in) { + case MESA_SHADER_VERTEX: + if (var->data.mode == ir_var_shader_in) { if (!state->check_explicit_attrib_location_allowed(loc, var)) return; @@ -2088,14 +2088,14 @@ validate_explicit_location(const struct ast_type_qualifier *qual, fail = true; break; - case geometry_shader: + case MESA_SHADER_GEOMETRY: _mesa_glsl_error(loc, state, "geometry shader variables cannot be given " "explicit locations"); return; - case fragment_shader: - if (var->mode == ir_var_shader_out) { + case MESA_SHADER_FRAGMENT: + if (var->data.mode == ir_var_shader_out) { if (!state->check_explicit_attrib_location_allowed(loc, var)) return; @@ -2112,7 +2112,7 @@ validate_explicit_location(const struct ast_type_qualifier *qual, mode_string(var), _mesa_glsl_shader_target_name(state->target)); } else { - var->explicit_location = true; + var->data.explicit_location = true; /* This bit of silliness is needed because invalid explicit locations * are supposed to be flagged during linking. Small negative values @@ -2122,11 +2122,11 @@ validate_explicit_location(const struct ast_type_qualifier *qual, * ensures that negative values stay negative. */ if (qual->location >= 0) { - var->location = (state->target == vertex_shader) + var->data.location = (state->target == MESA_SHADER_VERTEX) ? (qual->location + VERT_ATTRIB_GENERIC0) : (qual->location + FRAG_RESULT_DATA0); } else { - var->location = qual->location; + var->data.location = qual->location; } if (qual->flags.q.explicit_index) { @@ -2143,8 +2143,8 @@ validate_explicit_location(const struct ast_type_qualifier *qual, _mesa_glsl_error(loc, state, "explicit index may only be 0 or 1"); } else { - var->explicit_index = true; - var->index = qual->index; + var->data.explicit_index = true; + var->data.index = qual->index; } } } @@ -2162,25 +2162,28 @@ apply_type_qualifier_to_variable(const struct ast_type_qualifier *qual, STATIC_ASSERT(sizeof(qual->flags.q) <= sizeof(qual->flags.i)); if (qual->flags.q.invariant) { - if (var->used) { + if (var->data.used) { _mesa_glsl_error(loc, state, "variable `%s' may not be redeclared " "`invariant' after being used", var->name); } else { - var->invariant = 1; + var->data.invariant = 1; } } if (qual->flags.q.constant || qual->flags.q.attribute || qual->flags.q.uniform - || (qual->flags.q.varying && (state->target == fragment_shader))) - var->read_only = 1; + || (qual->flags.q.varying && (state->target == MESA_SHADER_FRAGMENT))) + var->data.read_only = 1; if (qual->flags.q.centroid) - var->centroid = 1; + var->data.centroid = 1; - if (qual->flags.q.attribute && state->target != vertex_shader) { + if (qual->flags.q.sample) + var->data.sample = 1; + + if (qual->flags.q.attribute && state->target != MESA_SHADER_VERTEX) { var->type = glsl_type::error_type; _mesa_glsl_error(loc, state, "`attribute' variables may not be declared in the " @@ -2207,18 +2210,18 @@ apply_type_qualifier_to_variable(const struct ast_type_qualifier *qual, * the setting alone. */ if (qual->flags.q.in && qual->flags.q.out) - var->mode = ir_var_function_inout; + var->data.mode = ir_var_function_inout; else if (qual->flags.q.in) - var->mode = is_parameter ? ir_var_function_in : ir_var_shader_in; + var->data.mode = is_parameter ? ir_var_function_in : ir_var_shader_in; else if (qual->flags.q.attribute - || (qual->flags.q.varying && (state->target == fragment_shader))) - var->mode = ir_var_shader_in; + || (qual->flags.q.varying && (state->target == MESA_SHADER_FRAGMENT))) + var->data.mode = ir_var_shader_in; else if (qual->flags.q.out) - var->mode = is_parameter ? ir_var_function_out : ir_var_shader_out; - else if (qual->flags.q.varying && (state->target == vertex_shader)) - var->mode = ir_var_shader_out; + var->data.mode = is_parameter ? ir_var_function_out : ir_var_shader_out; + else if (qual->flags.q.varying && (state->target == MESA_SHADER_VERTEX)) + var->data.mode = ir_var_shader_out; else if (qual->flags.q.uniform) - var->mode = ir_var_uniform; + var->data.mode = ir_var_uniform; if (!is_parameter && is_varying_var(var, state->target)) { /* This variable is being used to link data between shader stages (in @@ -2270,28 +2273,28 @@ apply_type_qualifier_to_variable(const struct ast_type_qualifier *qual, if (state->all_invariant && (state->current_function == NULL)) { switch (state->target) { - case vertex_shader: - if (var->mode == ir_var_shader_out) - var->invariant = true; + case MESA_SHADER_VERTEX: + if (var->data.mode == ir_var_shader_out) + var->data.invariant = true; break; - case geometry_shader: - if ((var->mode == ir_var_shader_in) - || (var->mode == ir_var_shader_out)) - var->invariant = true; + case MESA_SHADER_GEOMETRY: + if ((var->data.mode == ir_var_shader_in) + || (var->data.mode == ir_var_shader_out)) + var->data.invariant = true; break; - case fragment_shader: - if (var->mode == ir_var_shader_in) - var->invariant = true; + case MESA_SHADER_FRAGMENT: + if (var->data.mode == ir_var_shader_in) + var->data.invariant = true; break; } } - var->interpolation = - interpret_interpolation_qualifier(qual, (ir_variable_mode) var->mode, + var->data.interpolation = + interpret_interpolation_qualifier(qual, (ir_variable_mode) var->data.mode, state, loc); - var->pixel_center_integer = qual->flags.q.pixel_center_integer; - var->origin_upper_left = qual->flags.q.origin_upper_left; + var->data.pixel_center_integer = qual->flags.q.pixel_center_integer; + var->data.origin_upper_left = qual->flags.q.origin_upper_left; if ((qual->flags.q.origin_upper_left || qual->flags.q.pixel_center_integer) && (strcmp(var->name, "gl_FragCoord") != 0)) { const char *const qual_string = (qual->flags.q.origin_upper_left) @@ -2312,27 +2315,28 @@ apply_type_qualifier_to_variable(const struct ast_type_qualifier *qual, if (qual->flags.q.explicit_binding && validate_binding_qualifier(state, loc, var, qual)) { - var->explicit_binding = true; - var->binding = qual->binding; + var->data.explicit_binding = true; + var->data.binding = qual->binding; } if (var->type->contains_atomic()) { - if (var->mode == ir_var_uniform) { - if (var->explicit_binding) { - unsigned *offset = &state->atomic_counter_offsets[var->binding]; + if (var->data.mode == ir_var_uniform) { + if (var->data.explicit_binding) { + unsigned *offset = + &state->atomic_counter_offsets[var->data.binding]; if (*offset % ATOMIC_COUNTER_SIZE) _mesa_glsl_error(loc, state, "misaligned atomic counter offset"); - var->atomic.offset = *offset; + var->data.atomic.offset = *offset; *offset += var->type->atomic_size(); } else { _mesa_glsl_error(loc, state, "atomic counters require explicit binding point"); } - } else if (var->mode != ir_var_function_in) { + } else if (var->data.mode != ir_var_function_in) { _mesa_glsl_error(loc, state, "atomic counters may only be declared as " "function parameters or uniform-qualified " "global variables"); @@ -2406,15 +2410,15 @@ apply_type_qualifier_to_variable(const struct ast_type_qualifier *qual, "gl_FragDepth"); } if (qual->flags.q.depth_any) - var->depth_layout = ir_depth_layout_any; + var->data.depth_layout = ir_depth_layout_any; else if (qual->flags.q.depth_greater) - var->depth_layout = ir_depth_layout_greater; + var->data.depth_layout = ir_depth_layout_greater; else if (qual->flags.q.depth_less) - var->depth_layout = ir_depth_layout_less; + var->data.depth_layout = ir_depth_layout_less; else if (qual->flags.q.depth_unchanged) - var->depth_layout = ir_depth_layout_unchanged; + var->data.depth_layout = ir_depth_layout_unchanged; else - var->depth_layout = ir_depth_layout_none; + var->data.depth_layout = ir_depth_layout_none; if (qual->flags.q.std140 || qual->flags.q.packed || @@ -2475,10 +2479,10 @@ get_variable_being_redeclared(ir_variable *var, YYLTYPE loc, const unsigned size = unsigned(var->type->array_size()); check_builtin_array_max_size(var->name, size, loc, state); - if ((size > 0) && (size <= earlier->max_array_access)) { + if ((size > 0) && (size <= earlier->data.max_array_access)) { _mesa_glsl_error(& loc, state, "array size must be > %u due to " "previous access", - earlier->max_array_access); + earlier->data.max_array_access); } earlier->type = var->type; @@ -2488,12 +2492,12 @@ get_variable_being_redeclared(ir_variable *var, YYLTYPE loc, state->is_version(150, 0)) && strcmp(var->name, "gl_FragCoord") == 0 && earlier->type == var->type - && earlier->mode == var->mode) { + && earlier->data.mode == var->data.mode) { /* Allow redeclaration of gl_FragCoord for ARB_fcc layout * qualifiers. */ - earlier->origin_upper_left = var->origin_upper_left; - earlier->pixel_center_integer = var->pixel_center_integer; + earlier->data.origin_upper_left = var->data.origin_upper_left; + earlier->data.pixel_center_integer = var->data.pixel_center_integer; /* According to section 4.3.7 of the GLSL 1.30 spec, * the following built-in varaibles can be redeclared with an @@ -2513,41 +2517,41 @@ get_variable_being_redeclared(ir_variable *var, YYLTYPE loc, || strcmp(var->name, "gl_Color") == 0 || strcmp(var->name, "gl_SecondaryColor") == 0) && earlier->type == var->type - && earlier->mode == var->mode) { - earlier->interpolation = var->interpolation; + && earlier->data.mode == var->data.mode) { + earlier->data.interpolation = var->data.interpolation; /* Layout qualifiers for gl_FragDepth. */ } else if ((state->AMD_conservative_depth_enable || state->ARB_conservative_depth_enable) && strcmp(var->name, "gl_FragDepth") == 0 && earlier->type == var->type - && earlier->mode == var->mode) { + && earlier->data.mode == var->data.mode) { /** From the AMD_conservative_depth spec: * Within any shader, the first redeclarations of gl_FragDepth * must appear before any use of gl_FragDepth. */ - if (earlier->used) { + if (earlier->data.used) { _mesa_glsl_error(&loc, state, "the first redeclaration of gl_FragDepth " "must appear before any use of gl_FragDepth"); } /* Prevent inconsistent redeclaration of depth layout qualifier. */ - if (earlier->depth_layout != ir_depth_layout_none - && earlier->depth_layout != var->depth_layout) { + if (earlier->data.depth_layout != ir_depth_layout_none + && earlier->data.depth_layout != var->data.depth_layout) { _mesa_glsl_error(&loc, state, "gl_FragDepth: depth layout is declared here " "as '%s, but it was previously declared as " "'%s'", - depth_layout_string(var->depth_layout), - depth_layout_string(earlier->depth_layout)); + depth_layout_string(var->data.depth_layout), + depth_layout_string(earlier->data.depth_layout)); } - earlier->depth_layout = var->depth_layout; + earlier->data.depth_layout = var->data.depth_layout; } else if (allow_all_redeclarations) { - if (earlier->mode != var->mode) { + if (earlier->data.mode != var->data.mode) { _mesa_glsl_error(&loc, state, "redeclaration of `%s' with incorrect qualifiers", var->name); @@ -2582,7 +2586,7 @@ process_initializer(ir_variable *var, ast_declaration *decl, * directly by an application via API commands, or indirectly by * OpenGL." */ - if (var->mode == ir_var_uniform) { + if (var->data.mode == ir_var_uniform) { state->check_version(120, 0, &initializer_loc, "cannot initialize uniforms"); } @@ -2592,11 +2596,11 @@ process_initializer(ir_variable *var, ast_declaration *decl, "cannot initialize samplers"); } - if ((var->mode == ir_var_shader_in) && (state->current_function == NULL)) { + if ((var->data.mode == ir_var_shader_in) && (state->current_function == NULL)) { _mesa_glsl_error(& initializer_loc, state, "cannot initialize %s shader input / %s", _mesa_glsl_shader_target_name(state->target), - (state->target == vertex_shader) + (state->target == MESA_SHADER_VERTEX) ? "attribute" : "varying"); } @@ -2647,9 +2651,9 @@ process_initializer(ir_variable *var, ast_declaration *decl, } if (rhs && !rhs->type->is_error()) { - bool temp = var->read_only; + bool temp = var->data.read_only; if (type->qualifier.flags.q.constant) - var->read_only = false; + var->data.read_only = false; /* Never emit code to initialize a uniform. */ @@ -2664,7 +2668,7 @@ process_initializer(ir_variable *var, ast_declaration *decl, initializer_type = rhs->type; var->constant_initializer = rhs->constant_expression_value(); - var->has_initializer = true; + var->data.has_initializer = true; /* If the declared variable is an unsized array, it must inherrit * its full type from the initializer. A declaration such as @@ -2688,7 +2692,7 @@ process_initializer(ir_variable *var, ast_declaration *decl, */ var->type = initializer_type; - var->read_only = temp; + var->data.read_only = temp; } return result; @@ -2840,23 +2844,23 @@ ast_declarator_list::hir(exec_list *instructions, _mesa_glsl_error(& loc, state, "undeclared variable `%s' cannot be marked " "invariant", decl->identifier); - } else if ((state->target == vertex_shader) - && (earlier->mode != ir_var_shader_out)) { + } else if ((state->target == MESA_SHADER_VERTEX) + && (earlier->data.mode != ir_var_shader_out)) { _mesa_glsl_error(& loc, state, "`%s' cannot be marked invariant, vertex shader " "outputs only", decl->identifier); - } else if ((state->target == fragment_shader) - && (earlier->mode != ir_var_shader_in)) { + } else if ((state->target == MESA_SHADER_FRAGMENT) + && (earlier->data.mode != ir_var_shader_in)) { _mesa_glsl_error(& loc, state, "`%s' cannot be marked invariant, fragment shader " "inputs only", decl->identifier); - } else if (earlier->used) { + } else if (earlier->data.used) { _mesa_glsl_error(& loc, state, "variable `%s' may not be redeclared " "`invariant' after being used", earlier->name); } else { - earlier->invariant = true; + earlier->data.invariant = true; } } @@ -2940,7 +2944,7 @@ ast_declarator_list::hir(exec_list *instructions, precision_names[this->type->qualifier.precision], type_name); } - } else { + } else if (this->type->specifier->structure == NULL) { _mesa_glsl_warning(&loc, state, "empty declaration"); } } @@ -3030,13 +3034,13 @@ ast_declarator_list::hir(exec_list *instructions, & loc, false); if (this->type->qualifier.flags.q.invariant) { - if ((state->target == vertex_shader) && - var->mode != ir_var_shader_out) { + if ((state->target == MESA_SHADER_VERTEX) && + var->data.mode != ir_var_shader_out) { _mesa_glsl_error(& loc, state, "`%s' cannot be marked invariant, vertex shader " "outputs only", var->name); - } else if ((state->target == fragment_shader) && - var->mode != ir_var_shader_in) { + } else if ((state->target == MESA_SHADER_FRAGMENT) && + var->data.mode != ir_var_shader_in) { /* FINISHME: Note that this doesn't work for invariant on * a function signature inval */ @@ -3073,10 +3077,10 @@ ast_declarator_list::hir(exec_list *instructions, "global scope%s", mode, var->name, extra); } - } else if (var->mode == ir_var_shader_in) { - var->read_only = true; + } else if (var->data.mode == ir_var_shader_in) { + var->data.read_only = true; - if (state->target == vertex_shader) { + if (state->target == MESA_SHADER_VERTEX) { bool error_emitted = false; /* From page 31 (page 37 of the PDF) of the GLSL 1.50 spec: @@ -3131,7 +3135,7 @@ ast_declarator_list::hir(exec_list *instructions, "cannot have array type")) { error_emitted = true; } - } else if (state->target == geometry_shader) { + } else if (state->target == MESA_SHADER_GEOMETRY) { /* From section 4.3.4 (Inputs) of the GLSL 1.50 spec: * * Geometry shader input variables get the per-vertex values @@ -3180,11 +3184,11 @@ ast_declarator_list::hir(exec_list *instructions, */ if (state->is_version(130, 300) && var->type->contains_integer() && - var->interpolation != INTERP_QUALIFIER_FLAT && - ((state->target == fragment_shader && var->mode == ir_var_shader_in) - || (state->target == vertex_shader && var->mode == ir_var_shader_out + var->data.interpolation != INTERP_QUALIFIER_FLAT && + ((state->target == MESA_SHADER_FRAGMENT && var->data.mode == ir_var_shader_in) + || (state->target == MESA_SHADER_VERTEX && var->data.mode == ir_var_shader_out && state->es_shader))) { - const char *var_type = (state->target == vertex_shader) ? + const char *var_type = (state->target == MESA_SHADER_VERTEX) ? "vertex output" : "fragment input"; _mesa_glsl_error(&loc, state, "if a %s is (or contains) " "an integer, then it must be qualified with 'flat'", @@ -3241,14 +3245,14 @@ ast_declarator_list::hir(exec_list *instructions, assert(i != NULL); switch (state->target) { - case vertex_shader: + case MESA_SHADER_VERTEX: if (this->type->qualifier.flags.q.in) { _mesa_glsl_error(&loc, state, "qualifier '%s' cannot be applied to vertex " "shader inputs", i); } break; - case fragment_shader: + case MESA_SHADER_FRAGMENT: if (this->type->qualifier.flags.q.out) { _mesa_glsl_error(&loc, state, "qualifier '%s' cannot be applied to fragment " @@ -3271,12 +3275,20 @@ ast_declarator_list::hir(exec_list *instructions, if (state->is_version(130, 300) && this->type->qualifier.flags.q.centroid && this->type->qualifier.flags.q.in - && state->target == vertex_shader) { + && state->target == MESA_SHADER_VERTEX) { _mesa_glsl_error(&loc, state, "'centroid in' cannot be used in a vertex shader"); } + if (state->target == MESA_SHADER_VERTEX + && this->type->qualifier.flags.q.sample + && this->type->qualifier.flags.q.in) { + + _mesa_glsl_error(&loc, state, + "'sample in' cannot be used in a vertex shader"); + } + /* Section 4.3.6 of the GLSL 1.30 specification states: * "It is an error to use centroid out in a fragment shader." * @@ -3284,7 +3296,7 @@ ast_declarator_list::hir(exec_list *instructions, * "It is an error to use auxiliary storage qualifiers or interpolation * qualifiers on an output in a fragment shader." */ - if (state->target == fragment_shader && + if (state->target == MESA_SHADER_FRAGMENT && this->type->qualifier.flags.q.out && this->type->qualifier.has_auxiliary_storage()) { _mesa_glsl_error(&loc, state, @@ -3363,12 +3375,12 @@ ast_declarator_list::hir(exec_list *instructions, false /* allow_all_redeclarations */); if (earlier != NULL) { if (strncmp(var->name, "gl_", 3) == 0 && - earlier->how_declared == ir_var_declared_in_block) { + earlier->data.how_declared == ir_var_declared_in_block) { _mesa_glsl_error(&loc, state, "`%s' has already been redeclared using " "gl_PerVertex", var->name); } - earlier->how_declared = ir_var_declared_normally; + earlier->data.how_declared = ir_var_declared_normally; } if (decl->initializer != NULL) { @@ -3548,7 +3560,7 @@ ast_parameter_declarator::hir(exec_list *instructions, * as out or inout function parameters, nor can they be assigned * into." */ - if ((var->mode == ir_var_function_inout || var->mode == ir_var_function_out) + if ((var->data.mode == ir_var_function_inout || var->data.mode == ir_var_function_out) && type->contains_sampler()) { _mesa_glsl_error(&loc, state, "out and inout parameters cannot contain samplers"); type = glsl_type::error_type; @@ -3568,7 +3580,7 @@ ast_parameter_declarator::hir(exec_list *instructions, * So for GLSL 1.10, passing an array as an out or inout parameter is not * allowed. This restriction is removed in GLSL 1.20, and in GLSL ES. */ - if ((var->mode == ir_var_function_inout || var->mode == ir_var_function_out) + if ((var->data.mode == ir_var_function_inout || var->data.mode == ir_var_function_out) && type->is_array() && !state->check_version(120, 100, &loc, "arrays cannot be out or inout parameters")) { @@ -3942,7 +3954,7 @@ ast_jump_statement::hir(exec_list *instructions, } case ast_discard: - if (state->target != fragment_shader) { + if (state->target != MESA_SHADER_FRAGMENT) { YYLTYPE loc = this->get_location(); _mesa_glsl_error(& loc, state, @@ -4480,7 +4492,7 @@ ast_type_specifier::hir(exec_list *instructions, if (type->base_type == GLSL_TYPE_FLOAT && state->es_shader - && state->target == fragment_shader) { + && state->target == MESA_SHADER_FRAGMENT) { /* Section 4.5.3 (Default Precision Qualifiers) of the GLSL ES 1.00 * spec says: * @@ -4662,6 +4674,7 @@ ast_process_structure_or_interface_block(exec_list *instructions, fields[i].interpolation = interpret_interpolation_qualifier(qual, var_mode, state, &loc); fields[i].centroid = qual->flags.q.centroid ? 1 : 0; + fields[i].sample = qual->flags.q.sample ? 1 : 0; if (qual->flags.q.row_major || qual->flags.q.column_major) { if (!qual->flags.q.uniform) { @@ -4782,7 +4795,7 @@ public: virtual ir_visitor_status visit(ir_dereference_variable *ir) { - if (ir->var->mode == mode && ir->var->get_interface_type() == block) { + if (ir->var->data.mode == mode && ir->var->get_interface_type() == block) { found = true; return visit_stop; } @@ -4930,6 +4943,8 @@ ast_interface_block::hir(exec_list *instructions, earlier_per_vertex->fields.structure[j].interpolation; fields[i].centroid = earlier_per_vertex->fields.structure[j].centroid; + fields[i].sample = + earlier_per_vertex->fields.structure[j].sample; } } @@ -4980,7 +4995,7 @@ ast_interface_block::hir(exec_list *instructions, * variable (or input block, see interface blocks below) needs to be * declared as an array. */ - if (state->target == geometry_shader && !this->is_array && + if (state->target == MESA_SHADER_GEOMETRY && !this->is_array && var_mode == ir_var_shader_in) { _mesa_glsl_error(&loc, state, "geometry shader inputs must be arrays"); } @@ -5035,7 +5050,7 @@ ast_interface_block::hir(exec_list *instructions, * geometry shader input. */ if (this->array_size == NULL && - (state->target != geometry_shader || !this->layout.flags.q.in)) { + (state->target != MESA_SHADER_GEOMETRY || !this->layout.flags.q.in)) { _mesa_glsl_error(&loc, state, "only geometry shader inputs may be unsized " "instance block arrays"); @@ -5054,7 +5069,7 @@ ast_interface_block::hir(exec_list *instructions, var_mode); } - if (state->target == geometry_shader && var_mode == ir_var_shader_in) + if (state->target == MESA_SHADER_GEOMETRY && var_mode == ir_var_shader_in) handle_geometry_shader_input_decl(state, loc, var); if (ir_variable *earlier = @@ -5063,7 +5078,7 @@ ast_interface_block::hir(exec_list *instructions, _mesa_glsl_error(&loc, state, "`%s' redeclared", this->instance_name); } - earlier->how_declared = ir_var_declared_normally; + earlier->data.how_declared = ir_var_declared_normally; earlier->type = var->type; earlier->reinit_interface_type(block_type); delete var; @@ -5082,8 +5097,9 @@ ast_interface_block::hir(exec_list *instructions, new(state) ir_variable(fields[i].type, ralloc_strdup(state, fields[i].name), var_mode); - var->interpolation = fields[i].interpolation; - var->centroid = fields[i].centroid; + var->data.interpolation = fields[i].interpolation; + var->data.centroid = fields[i].centroid; + var->data.sample = fields[i].sample; var->init_interface_type(block_type); if (redeclaring_per_vertex) { @@ -5094,11 +5110,11 @@ ast_interface_block::hir(exec_list *instructions, _mesa_glsl_error(&loc, state, "redeclaration of gl_PerVertex can only " "include built-in variables"); - } else if (earlier->how_declared == ir_var_declared_normally) { + } else if (earlier->data.how_declared == ir_var_declared_normally) { _mesa_glsl_error(&loc, state, "`%s' has already been redeclared", var->name); } else { - earlier->how_declared = ir_var_declared_in_block; + earlier->data.how_declared = ir_var_declared_in_block; earlier->reinit_interface_type(block_type); } continue; @@ -5111,8 +5127,8 @@ ast_interface_block::hir(exec_list *instructions, * the UBO declaration itself doesn't get an ir_variable unless it * has an instance name. This is ugly. */ - var->explicit_binding = this->layout.flags.q.explicit_binding; - var->binding = this->layout.binding; + var->data.explicit_binding = this->layout.flags.q.explicit_binding; + var->data.binding = this->layout.binding; state->symbols->add_variable(var); instructions->push_tail(var); @@ -5144,8 +5160,8 @@ ast_interface_block::hir(exec_list *instructions, ir_variable *const var = ((ir_instruction *) node)->as_variable(); if (var != NULL && var->get_interface_type() == earlier_per_vertex && - var->mode == var_mode) { - if (var->how_declared == ir_var_declared_normally) { + var->data.mode == var_mode) { + if (var->data.how_declared == ir_var_declared_normally) { _mesa_glsl_error(&loc, state, "redeclaration of gl_PerVertex cannot " "follow a redeclaration of `%s'", @@ -5200,7 +5216,7 @@ ast_gs_input_layout::hir(exec_list *instructions, */ foreach_list (node, instructions) { ir_variable *var = ((ir_instruction *) node)->as_variable(); - if (var == NULL || var->mode != ir_var_shader_in) + if (var == NULL || var->data.mode != ir_var_shader_in) continue; /* Note: gl_PrimitiveIDIn has mode ir_var_shader_in, but it's not an @@ -5208,12 +5224,12 @@ ast_gs_input_layout::hir(exec_list *instructions, */ if (var->type->is_unsized_array()) { - if (var->max_array_access >= num_vertices) { + if (var->data.max_array_access >= num_vertices) { _mesa_glsl_error(&loc, state, "this geometry shader input layout implies %u" " vertices, but an access to element %u of input" " `%s' already exists", num_vertices, - var->max_array_access, var->name); + var->data.max_array_access, var->name); } else { var->type = glsl_type::get_array_instance(var->type->fields.array, num_vertices); @@ -5241,7 +5257,7 @@ detect_conflicting_assignments(struct _mesa_glsl_parse_state *state, foreach_list(node, instructions) { ir_variable *var = ((ir_instruction *)node)->as_variable(); - if (!var || !var->assigned) + if (!var || !var->data.assigned) continue; if (strcmp(var->name, "gl_FragColor") == 0) @@ -5249,8 +5265,8 @@ detect_conflicting_assignments(struct _mesa_glsl_parse_state *state, else if (strcmp(var->name, "gl_FragData") == 0) gl_FragData_assigned = true; else if (strncmp(var->name, "gl_", 3) != 0) { - if (state->target == fragment_shader && - var->mode == ir_var_shader_out) { + if (state->target == MESA_SHADER_FRAGMENT && + var->data.mode == ir_var_shader_out) { user_defined_fs_output_assigned = true; user_defined_fs_output = var; } @@ -5331,7 +5347,7 @@ remove_per_vertex_blocks(exec_list *instructions, foreach_list_safe(node, instructions) { ir_variable *const var = ((ir_instruction *) node)->as_variable(); if (var != NULL && var->get_interface_type() == per_vertex && - var->mode == mode) { + var->data.mode == mode) { state->symbols->disable_variable(var->name); var->remove(); } diff --git a/mesalib/src/glsl/ast_type.cpp b/mesalib/src/glsl/ast_type.cpp index 2b088bf8b..d758bfa1f 100644 --- a/mesalib/src/glsl/ast_type.cpp +++ b/mesalib/src/glsl/ast_type.cpp @@ -90,7 +90,8 @@ ast_type_qualifier::has_storage() const bool ast_type_qualifier::has_auxiliary_storage() const { - return this->flags.q.centroid; + return this->flags.q.centroid + || this->flags.q.sample; } const char* diff --git a/mesalib/src/glsl/builtin_functions.cpp b/mesalib/src/glsl/builtin_functions.cpp index 8cb75e5ad..840a6c9a2 100644 --- a/mesalib/src/glsl/builtin_functions.cpp +++ b/mesalib/src/glsl/builtin_functions.cpp @@ -77,7 +77,7 @@ always_available(const _mesa_glsl_parse_state *state) static bool compatibility_vs_only(const _mesa_glsl_parse_state *state) { - return state->target == vertex_shader && + return state->target == MESA_SHADER_VERTEX && state->language_version <= 130 && !state->es_shader; } @@ -85,13 +85,13 @@ compatibility_vs_only(const _mesa_glsl_parse_state *state) static bool fs_only(const _mesa_glsl_parse_state *state) { - return state->target == fragment_shader; + return state->target == MESA_SHADER_FRAGMENT; } static bool gs_only(const _mesa_glsl_parse_state *state) { - return state->target == geometry_shader; + return state->target == MESA_SHADER_GEOMETRY; } static bool @@ -103,7 +103,7 @@ v110(const _mesa_glsl_parse_state *state) static bool v110_fs_only(const _mesa_glsl_parse_state *state) { - return !state->es_shader && state->target == fragment_shader; + return !state->es_shader && state->target == MESA_SHADER_FRAGMENT; } static bool @@ -122,7 +122,7 @@ static bool v130_fs_only(const _mesa_glsl_parse_state *state) { return state->is_version(130, 300) && - state->target == fragment_shader; + state->target == MESA_SHADER_FRAGMENT; } static bool @@ -155,7 +155,7 @@ lod_exists_in_stage(const _mesa_glsl_parse_state *state) * Since ARB_shader_texture_lod can only be enabled on desktop GLSL, we * don't need to explicitly check state->es_shader. */ - return state->target == vertex_shader || + return state->target == MESA_SHADER_VERTEX || state->is_version(130, 300) || state->ARB_shader_texture_lod_enable; } @@ -223,7 +223,7 @@ texture_array_lod(const _mesa_glsl_parse_state *state) static bool fs_texture_array(const _mesa_glsl_parse_state *state) { - return state->target == fragment_shader && + return state->target == MESA_SHADER_FRAGMENT && state->EXT_texture_array_enable; } @@ -243,7 +243,7 @@ texture_multisample(const _mesa_glsl_parse_state *state) static bool fs_texture_cube_map_array(const _mesa_glsl_parse_state *state) { - return state->target == fragment_shader && + return state->target == MESA_SHADER_FRAGMENT && (state->is_version(400, 0) || state->ARB_texture_cube_map_array_enable); } @@ -265,7 +265,7 @@ texture_query_levels(const _mesa_glsl_parse_state *state) static bool texture_query_lod(const _mesa_glsl_parse_state *state) { - return state->target == fragment_shader && + return state->target == MESA_SHADER_FRAGMENT && state->ARB_texture_query_lod_enable; } @@ -292,7 +292,7 @@ texture_gather_only(const _mesa_glsl_parse_state *state) static bool fs_oes_derivatives(const _mesa_glsl_parse_state *state) { - return state->target == fragment_shader && + return state->target == MESA_SHADER_FRAGMENT && (state->is_version(110, 300) || state->OES_standard_derivatives_enable); } @@ -318,7 +318,7 @@ tex3d(const _mesa_glsl_parse_state *state) static bool fs_tex3d(const _mesa_glsl_parse_state *state) { - return state->target == fragment_shader && + return state->target == MESA_SHADER_FRAGMENT && (!state->es_shader || state->OES_texture_3D_enable); } @@ -357,8 +357,6 @@ public: ir_function_signature *find(_mesa_glsl_parse_state *state, const char *name, exec_list *actual_parameters); -private: - void *mem_ctx; /** * A shader to hold all the built-in signatures; created by this module. * @@ -368,6 +366,9 @@ private: */ gl_shader *shader; +private: + void *mem_ctx; + /** Global variables used by built-in functions. */ ir_variable *gl_ModelViewProjectionMatrix; ir_variable *gl_Vertex; @@ -608,8 +609,7 @@ builtin_builder::find(_mesa_glsl_parse_state *state, * that the "no matching signature" error will list potential candidates * from the available built-ins. */ - state->builtins_to_link[0] = shader; - state->num_builtins_to_link = 1; + state->uses_builtin_functions = true; ir_function *f = shader->symbols->get_function(name); if (f == NULL) @@ -4020,4 +4020,11 @@ _mesa_glsl_find_builtin_function(_mesa_glsl_parse_state *state, { return builtins.find(state, name, actual_parameters); } + +gl_shader * +_mesa_glsl_get_builtin_function_shader() +{ + return builtins.shader; +} + /** @} */ diff --git a/mesalib/src/glsl/builtin_variables.cpp b/mesalib/src/glsl/builtin_variables.cpp index d57324c2f..ff9acb8d0 100644 --- a/mesalib/src/glsl/builtin_variables.cpp +++ b/mesalib/src/glsl/builtin_variables.cpp @@ -332,6 +332,7 @@ per_vertex_accumulator::add_field(int slot, const glsl_type *type, this->fields[this->num_fields].location = slot; this->fields[this->num_fields].interpolation = INTERP_QUALIFIER_NONE; this->fields[this->num_fields].centroid = 0; + this->fields[this->num_fields].sample = 0; this->num_fields++; } @@ -434,14 +435,14 @@ builtin_variable_generator::add_variable(const char *name, enum ir_variable_mode mode, int slot) { ir_variable *var = new(symtab) ir_variable(type, name, mode); - var->how_declared = ir_var_declared_implicitly; + var->data.how_declared = ir_var_declared_implicitly; - switch (var->mode) { + switch (var->data.mode) { case ir_var_auto: case ir_var_shader_in: case ir_var_uniform: case ir_var_system_value: - var->read_only = true; + var->data.read_only = true; break; case ir_var_shader_out: break; @@ -454,9 +455,9 @@ builtin_variable_generator::add_variable(const char *name, break; } - var->location = slot; - var->explicit_location = (slot >= 0); - var->explicit_index = 0; + var->data.location = slot; + var->data.explicit_location = (slot >= 0); + var->data.explicit_index = 0; /* Once the variable is created an initialized, add it to the symbol table * and add the declaration to the IR stream. @@ -523,7 +524,7 @@ builtin_variable_generator::add_const(const char *name, int value) ir_var_auto, -1); var->constant_value = new(var) ir_constant(value); var->constant_initializer = new(var) ir_constant(value); - var->has_initializer = true; + var->data.has_initializer = true; return var; } @@ -792,9 +793,9 @@ builtin_variable_generator::generate_gs_special_vars() */ ir_variable *var; var = add_input(VARYING_SLOT_PRIMITIVE_ID, int_t, "gl_PrimitiveIDIn"); - var->interpolation = INTERP_QUALIFIER_FLAT; + var->data.interpolation = INTERP_QUALIFIER_FLAT; var = add_output(VARYING_SLOT_PRIMITIVE_ID, int_t, "gl_PrimitiveID"); - var->interpolation = INTERP_QUALIFIER_FLAT; + var->data.interpolation = INTERP_QUALIFIER_FLAT; } @@ -812,7 +813,7 @@ builtin_variable_generator::generate_fs_special_vars() if (state->is_version(150, 0)) { ir_variable *var = add_input(VARYING_SLOT_PRIMITIVE_ID, int_t, "gl_PrimitiveID"); - var->interpolation = INTERP_QUALIFIER_FLAT; + var->data.interpolation = INTERP_QUALIFIER_FLAT; } /* gl_FragColor and gl_FragData were deprecated starting in desktop GLSL @@ -857,6 +858,10 @@ builtin_variable_generator::generate_fs_special_vars() */ add_output(FRAG_RESULT_SAMPLE_MASK, array(int_t, 1), "gl_SampleMask"); } + + if (state->ARB_gpu_shader5_enable) { + add_system_value(SYSTEM_VALUE_SAMPLE_MASK_IN, array(int_t, 1), "gl_SampleMaskIn"); + } } @@ -872,13 +877,13 @@ builtin_variable_generator::add_varying(int slot, const glsl_type *type, const char *name_as_gs_input) { switch (state->target) { - case geometry_shader: + case MESA_SHADER_GEOMETRY: this->per_vertex_in.add_field(slot, type, name); /* FALLTHROUGH */ - case vertex_shader: + case MESA_SHADER_VERTEX: this->per_vertex_out.add_field(slot, type, name); break; - case fragment_shader: + case MESA_SHADER_FRAGMENT: add_input(slot, type, name); break; } @@ -896,7 +901,7 @@ builtin_variable_generator::generate_varyings() add_varying(loc, type, name, name "In") /* gl_Position and gl_PointSize are not visible from fragment shaders. */ - if (state->target != fragment_shader) { + if (state->target != MESA_SHADER_FRAGMENT) { ADD_VARYING(VARYING_SLOT_POS, vec4_t, "gl_Position"); ADD_VARYING(VARYING_SLOT_PSIZ, float_t, "gl_PointSize"); } @@ -909,7 +914,7 @@ builtin_variable_generator::generate_varyings() if (compatibility) { ADD_VARYING(VARYING_SLOT_TEX0, array(vec4_t, 0), "gl_TexCoord"); ADD_VARYING(VARYING_SLOT_FOGC, float_t, "gl_FogFragCoord"); - if (state->target == fragment_shader) { + if (state->target == MESA_SHADER_FRAGMENT) { ADD_VARYING(VARYING_SLOT_COL0, vec4_t, "gl_Color"); ADD_VARYING(VARYING_SLOT_COL1, vec4_t, "gl_SecondaryColor"); } else { @@ -921,13 +926,13 @@ builtin_variable_generator::generate_varyings() } } - if (state->target == geometry_shader) { + if (state->target == MESA_SHADER_GEOMETRY) { const glsl_type *per_vertex_in_type = this->per_vertex_in.construct_interface_instance(); add_variable("gl_in", array(per_vertex_in_type, 0), ir_var_shader_in, -1); } - if (state->target == vertex_shader || state->target == geometry_shader) { + if (state->target == MESA_SHADER_VERTEX || state->target == MESA_SHADER_GEOMETRY) { const glsl_type *per_vertex_out_type = this->per_vertex_out.construct_interface_instance(); const glsl_struct_field *fields = per_vertex_out_type->fields.structure; @@ -935,8 +940,9 @@ builtin_variable_generator::generate_varyings() ir_variable *var = add_variable(fields[i].name, fields[i].type, ir_var_shader_out, fields[i].location); - var->interpolation = fields[i].interpolation; - var->centroid = fields[i].centroid; + var->data.interpolation = fields[i].interpolation; + var->data.centroid = fields[i].centroid; + var->data.sample = fields[i].sample; var->init_interface_type(per_vertex_out_type); } } @@ -958,13 +964,13 @@ _mesa_glsl_initialize_variables(exec_list *instructions, gen.generate_varyings(); switch (state->target) { - case vertex_shader: + case MESA_SHADER_VERTEX: gen.generate_vs_special_vars(); break; - case geometry_shader: + case MESA_SHADER_GEOMETRY: gen.generate_gs_special_vars(); break; - case fragment_shader: + case MESA_SHADER_FRAGMENT: gen.generate_fs_special_vars(); break; } diff --git a/mesalib/src/glsl/glsl_lexer.ll b/mesalib/src/glsl/glsl_lexer.ll index 822d70d6b..50875bf3b 100644 --- a/mesalib/src/glsl/glsl_lexer.ll +++ b/mesalib/src/glsl/glsl_lexer.ll @@ -520,7 +520,7 @@ readonly KEYWORD(0, 300, 0, 0, READONLY); writeonly KEYWORD(0, 300, 0, 0, WRITEONLY); resource KEYWORD(0, 300, 0, 0, RESOURCE); patch KEYWORD(0, 300, 0, 0, PATCH); -sample KEYWORD(0, 300, 0, 0, SAMPLE); +sample KEYWORD_WITH_ALT(400, 300, 400, 0, yyextra->ARB_gpu_shader5_enable, SAMPLE); subroutine KEYWORD(0, 300, 0, 0, SUBROUTINE); diff --git a/mesalib/src/glsl/glsl_parser.yy b/mesalib/src/glsl/glsl_parser.yy index ada3690f6..39767609d 100644 --- a/mesalib/src/glsl/glsl_parser.yy +++ b/mesalib/src/glsl/glsl_parser.yy @@ -1521,7 +1521,7 @@ type_qualifier: { if ($2.has_auxiliary_storage()) { _mesa_glsl_error(&@1, state, - "duplicate auxiliary storage qualifier (centroid)"); + "duplicate auxiliary storage qualifier (centroid or sample)"); } if (!state->ARB_shading_language_420pack_enable && @@ -1571,7 +1571,12 @@ auxiliary_storage_qualifier: memset(& $$, 0, sizeof($$)); $$.flags.q.centroid = 1; } - /* TODO: "sample" and "patch" also go here someday. */ + | SAMPLE + { + memset(& $$, 0, sizeof($$)); + $$.flags.q.sample = 1; + } + /* TODO: "patch" also goes here someday. */ storage_qualifier: CONST_TOK @@ -2214,11 +2219,11 @@ basic_interface_block: * "It is illegal to have an input block in a vertex shader * or an output block in a fragment shader" */ - if ((state->target == vertex_shader) && $1.flags.q.in) { + if ((state->target == MESA_SHADER_VERTEX) && $1.flags.q.in) { _mesa_glsl_error(& @1, state, "`in' interface block is not allowed for " "a vertex shader"); - } else if ((state->target == fragment_shader) && $1.flags.q.out) { + } else if ((state->target == MESA_SHADER_FRAGMENT) && $1.flags.q.out) { _mesa_glsl_error(& @1, state, "`out' interface block is not allowed for " "a fragment shader"); @@ -2372,7 +2377,7 @@ layout_defaults: { void *ctx = state; $$ = NULL; - if (state->target != geometry_shader) { + if (state->target != MESA_SHADER_GEOMETRY) { _mesa_glsl_error(& @1, state, "input layout qualifiers only valid in " "geometry shaders"); @@ -2400,7 +2405,7 @@ layout_defaults: | layout_qualifier OUT_TOK ';' { - if (state->target != geometry_shader) { + if (state->target != MESA_SHADER_GEOMETRY) { _mesa_glsl_error(& @1, state, "out layout qualifiers only valid in " "geometry shaders"); diff --git a/mesalib/src/glsl/glsl_parser_extras.cpp b/mesalib/src/glsl/glsl_parser_extras.cpp index d76d94b7a..5f19368d8 100644 --- a/mesalib/src/glsl/glsl_parser_extras.cpp +++ b/mesalib/src/glsl/glsl_parser_extras.cpp @@ -58,9 +58,9 @@ _mesa_glsl_parse_state::_mesa_glsl_parse_state(struct gl_context *_ctx, : ctx(_ctx), switch_state() { switch (target) { - case GL_VERTEX_SHADER: this->target = vertex_shader; break; - case GL_FRAGMENT_SHADER: this->target = fragment_shader; break; - case GL_GEOMETRY_SHADER: this->target = geometry_shader; break; + case GL_VERTEX_SHADER: this->target = MESA_SHADER_VERTEX; break; + case GL_FRAGMENT_SHADER: this->target = MESA_SHADER_FRAGMENT; break; + case GL_GEOMETRY_SHADER: this->target = MESA_SHADER_GEOMETRY; break; } this->scanner = NULL; @@ -76,7 +76,8 @@ _mesa_glsl_parse_state::_mesa_glsl_parse_state(struct gl_context *_ctx, this->loop_nesting_ast = NULL; this->struct_specifier_depth = 0; - this->num_builtins_to_link = 0; + + this->uses_builtin_functions = false; /* Set default language version and extensions */ this->language_version = ctx->Const.ForceGLSLVersion ? @@ -366,12 +367,12 @@ _mesa_glsl_shader_target_name(GLenum type) * our internal enum into short stage names. */ const char * -_mesa_glsl_shader_target_name(enum _mesa_glsl_parser_targets target) +_mesa_glsl_shader_target_name(gl_shader_type target) { switch (target) { - case vertex_shader: return "vertex"; - case fragment_shader: return "fragment"; - case geometry_shader: return "geometry"; + case MESA_SHADER_VERTEX: return "vertex"; + case MESA_SHADER_FRAGMENT: return "fragment"; + case MESA_SHADER_GEOMETRY: return "geometry"; } assert(!"Should not get here."); @@ -877,6 +878,8 @@ _mesa_ast_type_qualifier_print(const struct ast_type_qualifier *q) if (q->flags.q.centroid) printf("centroid "); + if (q->flags.q.sample) + printf("sample "); if (q->flags.q.uniform) printf("uniform "); if (q->flags.q.smooth) @@ -1532,10 +1535,7 @@ _mesa_glsl_compile_shader(struct gl_context *ctx, struct gl_shader *shader, shader->InfoLog = state->info_log; shader->Version = state->language_version; shader->IsES = state->es_shader; - - memcpy(shader->builtins_to_link, state->builtins_to_link, - sizeof(shader->builtins_to_link[0]) * state->num_builtins_to_link); - shader->num_builtins_to_link = state->num_builtins_to_link; + shader->uses_builtin_functions = state->uses_builtin_functions; if (shader->UniformBlocks) ralloc_free(shader->UniformBlocks); diff --git a/mesalib/src/glsl/glsl_parser_extras.h b/mesalib/src/glsl/glsl_parser_extras.h index d232bb3f6..622ddbac7 100644 --- a/mesalib/src/glsl/glsl_parser_extras.h +++ b/mesalib/src/glsl/glsl_parser_extras.h @@ -34,12 +34,6 @@ #include #include "glsl_symbol_table.h" -enum _mesa_glsl_parser_targets { - vertex_shader, - geometry_shader, - fragment_shader -}; - struct gl_context; struct glsl_switch_state { @@ -171,7 +165,7 @@ struct _mesa_glsl_parse_state { bool es_shader; unsigned language_version; - enum _mesa_glsl_parser_targets target; + gl_shader_type target; /** * Number of nested struct_specifier levels @@ -361,9 +355,7 @@ struct _mesa_glsl_parse_state { /** Extensions supported by the OpenGL implementation. */ const struct gl_extensions *extensions; - /** Shaders containing built-in functions that are used for linking. */ - struct gl_shader *builtins_to_link[16]; - unsigned num_builtins_to_link; + bool uses_builtin_functions; /** * For geometry shaders, size of the most recently seen input declaration @@ -433,7 +425,7 @@ extern bool _mesa_glsl_process_extension(const char *name, YYLTYPE *name_locp, * Get the textual name of the specified shader target */ extern const char * -_mesa_glsl_shader_target_name(enum _mesa_glsl_parser_targets target); +_mesa_glsl_shader_target_name(gl_shader_type target); #endif /* __cplusplus */ diff --git a/mesalib/src/glsl/glsl_types.cpp b/mesalib/src/glsl/glsl_types.cpp index f74013096..12d4ac0ee 100644 --- a/mesalib/src/glsl/glsl_types.cpp +++ b/mesalib/src/glsl/glsl_types.cpp @@ -103,6 +103,7 @@ glsl_type::glsl_type(const glsl_struct_field *fields, unsigned num_fields, this->fields.structure[i].location = fields[i].location; this->fields.structure[i].interpolation = fields[i].interpolation; this->fields.structure[i].centroid = fields[i].centroid; + this->fields.structure[i].sample = fields[i].sample; this->fields.structure[i].row_major = fields[i].row_major; } } @@ -130,6 +131,7 @@ glsl_type::glsl_type(const glsl_struct_field *fields, unsigned num_fields, this->fields.structure[i].location = fields[i].location; this->fields.structure[i].interpolation = fields[i].interpolation; this->fields.structure[i].centroid = fields[i].centroid; + this->fields.structure[i].sample = fields[i].sample; this->fields.structure[i].row_major = fields[i].row_major; } } @@ -483,6 +485,9 @@ glsl_type::record_key_compare(const void *a, const void *b) if (key1->fields.structure[i].centroid != key2->fields.structure[i].centroid) return 1; + if (key1->fields.structure[i].sample + != key2->fields.structure[i].sample) + return 1; } return 0; diff --git a/mesalib/src/glsl/glsl_types.h b/mesalib/src/glsl/glsl_types.h index 96eee5e64..fb7c9288d 100644 --- a/mesalib/src/glsl/glsl_types.h +++ b/mesalib/src/glsl/glsl_types.h @@ -634,6 +634,12 @@ struct glsl_struct_field { * in ir_variable::centroid). 0 otherwise. */ unsigned centroid:1; + + /** + * For interface blocks, 1 if this variable uses sample interpolation (as + * in ir_variable::sample). 0 otherwise. + */ + unsigned sample:1; }; static inline unsigned int diff --git a/mesalib/src/glsl/ir.cpp b/mesalib/src/glsl/ir.cpp index ffff2976a..04a7b874a 100644 --- a/mesalib/src/glsl/ir.cpp +++ b/mesalib/src/glsl/ir.cpp @@ -1277,11 +1277,6 @@ ir_constant::is_basis() const ir_loop::ir_loop() { this->ir_type = ir_type_loop; - this->cmp = ir_unop_neg; - this->from = NULL; - this->to = NULL; - this->increment = NULL; - this->counter = NULL; } @@ -1364,7 +1359,7 @@ ir_dereference::is_lvalue() const /* Every l-value derference chain eventually ends in a variable. */ - if ((var == NULL) || var->read_only) + if ((var == NULL) || var->data.read_only) return false; /* From page 17 (page 23 of the PDF) of the GLSL 1.20 spec: @@ -1584,29 +1579,36 @@ ir_swizzle::variable_referenced() const ir_variable::ir_variable(const struct glsl_type *type, const char *name, ir_variable_mode mode) - : max_array_access(0), max_ifc_array_access(NULL), - read_only(false), centroid(false), invariant(false), - how_declared(ir_var_declared_normally), mode(mode), - interpolation(INTERP_QUALIFIER_NONE), atomic() + : max_ifc_array_access(NULL) { this->ir_type = ir_type_variable; this->type = type; this->name = ralloc_strdup(this, name); - this->explicit_location = false; - this->has_initializer = false; - this->location = -1; - this->location_frac = 0; + this->data.explicit_location = false; + this->data.has_initializer = false; + this->data.location = -1; + this->data.location_frac = 0; this->warn_extension = NULL; this->constant_value = NULL; this->constant_initializer = NULL; - this->origin_upper_left = false; - this->pixel_center_integer = false; - this->depth_layout = ir_depth_layout_none; - this->used = false; + this->data.origin_upper_left = false; + this->data.pixel_center_integer = false; + this->data.depth_layout = ir_depth_layout_none; + this->data.used = false; + this->data.read_only = false; + this->data.centroid = false; + this->data.sample = false; + this->data.invariant = false; + this->data.how_declared = ir_var_declared_normally; + this->data.mode = mode; + this->data.interpolation = INTERP_QUALIFIER_NONE; + this->data.max_array_access = 0; + this->data.atomic.buffer_index = 0; + this->data.atomic.offset = 0; if (type != NULL) { if (type->base_type == GLSL_TYPE_SAMPLER) - this->read_only = true; + this->data.read_only = true; if (type->is_interface()) this->init_interface_type(type); @@ -1634,9 +1636,9 @@ interpolation_string(unsigned interpolation) glsl_interp_qualifier ir_variable::determine_interpolation_mode(bool flat_shade) { - if (this->interpolation != INTERP_QUALIFIER_NONE) - return (glsl_interp_qualifier) this->interpolation; - int location = this->location; + if (this->data.interpolation != INTERP_QUALIFIER_NONE) + return (glsl_interp_qualifier) this->data.interpolation; + int location = this->data.location; bool is_gl_Color = location == VARYING_SLOT_COL0 || location == VARYING_SLOT_COL1; if (flat_shade && is_gl_Color) @@ -1706,10 +1708,11 @@ ir_function_signature::qualifiers_match(exec_list *params) ir_variable *a = (ir_variable *)iter_a.get(); ir_variable *b = (ir_variable *)iter_b.get(); - if (a->read_only != b->read_only || - !modes_match(a->mode, b->mode) || - a->interpolation != b->interpolation || - a->centroid != b->centroid) { + if (a->data.read_only != b->data.read_only || + !modes_match(a->data.mode, b->data.mode) || + a->data.interpolation != b->data.interpolation || + a->data.centroid != b->data.centroid || + a->data.sample != b->data.sample) { /* parameter a's qualifiers don't match */ return a->name; @@ -1729,12 +1732,6 @@ ir_function_signature::replace_parameters(exec_list *new_params) * parameter information comes from the function prototype, it may either * specify incorrect parameter names or not have names at all. */ - foreach_iter(exec_list_iterator, iter, parameters) { - assert(((ir_instruction *) iter.get())->as_variable() != NULL); - - iter.remove(); - } - new_params->move_nodes_to(¶meters); } @@ -1899,9 +1896,9 @@ vertices_per_prim(GLenum prim) const char * mode_string(const ir_variable *var) { - switch (var->mode) { + switch (var->data.mode) { case ir_var_auto: - return (var->read_only) ? "global constant" : "global variable"; + return (var->data.read_only) ? "global constant" : "global variable"; case ir_var_uniform: return "uniform"; diff --git a/mesalib/src/glsl/ir.h b/mesalib/src/glsl/ir.h index 4f775da4b..780959b73 100644 --- a/mesalib/src/glsl/ir.h +++ b/mesalib/src/glsl/ir.h @@ -86,6 +86,7 @@ enum ir_node_type { ir_type_max /**< maximum ir_type enum number, for validation */ }; + /** * Base class of all IR instructions */ @@ -402,7 +403,7 @@ public: */ inline bool is_in_uniform_block() const { - return this->mode == ir_var_uniform && this->interface_type != NULL; + return this->data.mode == ir_var_uniform && this->interface_type != NULL; } /** @@ -501,13 +502,6 @@ public: */ const char *name; - /** - * Highest element accessed with a constant expression array index - * - * Not used for non-array variables. - */ - unsigned max_array_access; - /** * For variables which satisfy the is_interface_instance() predicate, this * points to an array of integers such that if the ith member of the @@ -521,177 +515,189 @@ public: */ unsigned *max_ifc_array_access; - /** - * Is the variable read-only? - * - * This is set for variables declared as \c const, shader inputs, - * and uniforms. - */ - unsigned read_only:1; - unsigned centroid:1; - unsigned invariant:1; - - /** - * Has this variable been used for reading or writing? - * - * Several GLSL semantic checks require knowledge of whether or not a - * variable has been used. For example, it is an error to redeclare a - * variable as invariant after it has been used. - * - * This is only maintained in the ast_to_hir.cpp path, not in - * Mesa's fixed function or ARB program paths. - */ - unsigned used:1; - - /** - * Has this variable been statically assigned? - * - * This answers whether the variable was assigned in any path of - * the shader during ast_to_hir. This doesn't answer whether it is - * still written after dead code removal, nor is it maintained in - * non-ast_to_hir.cpp (GLSL parsing) paths. - */ - unsigned assigned:1; - - /** - * Enum indicating how the variable was declared. See - * ir_var_declaration_type. - * - * This is used to detect certain kinds of illegal variable redeclarations. - */ - unsigned how_declared:2; - - /** - * Storage class of the variable. - * - * \sa ir_variable_mode - */ - unsigned mode:4; - - /** - * Interpolation mode for shader inputs / outputs - * - * \sa ir_variable_interpolation - */ - unsigned interpolation:2; - - /** - * \name ARB_fragment_coord_conventions - * @{ - */ - unsigned origin_upper_left:1; - unsigned pixel_center_integer:1; - /*@}*/ + struct ir_variable_data { - /** - * Was the location explicitly set in the shader? - * - * If the location is explicitly set in the shader, it \b cannot be changed - * by the linker or by the API (e.g., calls to \c glBindAttribLocation have - * no effect). - */ - unsigned explicit_location:1; - unsigned explicit_index:1; - - /** - * Was an initial binding explicitly set in the shader? - * - * If so, constant_value contains an integer ir_constant representing the - * initial binding point. - */ - unsigned explicit_binding:1; + /** + * Is the variable read-only? + * + * This is set for variables declared as \c const, shader inputs, + * and uniforms. + */ + unsigned read_only:1; + unsigned centroid:1; + unsigned sample:1; + unsigned invariant:1; + + /** + * Has this variable been used for reading or writing? + * + * Several GLSL semantic checks require knowledge of whether or not a + * variable has been used. For example, it is an error to redeclare a + * variable as invariant after it has been used. + * + * This is only maintained in the ast_to_hir.cpp path, not in + * Mesa's fixed function or ARB program paths. + */ + unsigned used:1; + + /** + * Has this variable been statically assigned? + * + * This answers whether the variable was assigned in any path of + * the shader during ast_to_hir. This doesn't answer whether it is + * still written after dead code removal, nor is it maintained in + * non-ast_to_hir.cpp (GLSL parsing) paths. + */ + unsigned assigned:1; - /** - * Does this variable have an initializer? - * - * This is used by the linker to cross-validiate initializers of global - * variables. - */ - unsigned has_initializer:1; + /** + * Enum indicating how the variable was declared. See + * ir_var_declaration_type. + * + * This is used to detect certain kinds of illegal variable redeclarations. + */ + unsigned how_declared:2; - /** - * Is this variable a generic output or input that has not yet been matched - * up to a variable in another stage of the pipeline? - * - * This is used by the linker as scratch storage while assigning locations - * to generic inputs and outputs. - */ - unsigned is_unmatched_generic_inout:1; + /** + * Storage class of the variable. + * + * \sa ir_variable_mode + */ + unsigned mode:4; - /** - * If non-zero, then this variable may be packed along with other variables - * into a single varying slot, so this offset should be applied when - * accessing components. For example, an offset of 1 means that the x - * component of this variable is actually stored in component y of the - * location specified by \c location. - */ - unsigned location_frac:2; + /** + * Interpolation mode for shader inputs / outputs + * + * \sa ir_variable_interpolation + */ + unsigned interpolation:2; - /** - * Non-zero if this variable was created by lowering a named interface - * block which was not an array. - * - * Note that this variable and \c from_named_ifc_block_array will never - * both be non-zero. - */ - unsigned from_named_ifc_block_nonarray:1; + /** + * \name ARB_fragment_coord_conventions + * @{ + */ + unsigned origin_upper_left:1; + unsigned pixel_center_integer:1; + /*@}*/ + + /** + * Was the location explicitly set in the shader? + * + * If the location is explicitly set in the shader, it \b cannot be changed + * by the linker or by the API (e.g., calls to \c glBindAttribLocation have + * no effect). + */ + unsigned explicit_location:1; + unsigned explicit_index:1; + + /** + * Was an initial binding explicitly set in the shader? + * + * If so, constant_value contains an integer ir_constant representing the + * initial binding point. + */ + unsigned explicit_binding:1; - /** - * Non-zero if this variable was created by lowering a named interface - * block which was an array. - * - * Note that this variable and \c from_named_ifc_block_nonarray will never - * both be non-zero. - */ - unsigned from_named_ifc_block_array:1; + /** + * Does this variable have an initializer? + * + * This is used by the linker to cross-validiate initializers of global + * variables. + */ + unsigned has_initializer:1; + + /** + * Is this variable a generic output or input that has not yet been matched + * up to a variable in another stage of the pipeline? + * + * This is used by the linker as scratch storage while assigning locations + * to generic inputs and outputs. + */ + unsigned is_unmatched_generic_inout:1; + + /** + * If non-zero, then this variable may be packed along with other variables + * into a single varying slot, so this offset should be applied when + * accessing components. For example, an offset of 1 means that the x + * component of this variable is actually stored in component y of the + * location specified by \c location. + */ + unsigned location_frac:2; + + /** + * Non-zero if this variable was created by lowering a named interface + * block which was not an array. + * + * Note that this variable and \c from_named_ifc_block_array will never + * both be non-zero. + */ + unsigned from_named_ifc_block_nonarray:1; + + /** + * Non-zero if this variable was created by lowering a named interface + * block which was an array. + * + * Note that this variable and \c from_named_ifc_block_nonarray will never + * both be non-zero. + */ + unsigned from_named_ifc_block_array:1; - /** - * \brief Layout qualifier for gl_FragDepth. - * - * This is not equal to \c ir_depth_layout_none if and only if this - * variable is \c gl_FragDepth and a layout qualifier is specified. - */ - ir_depth_layout depth_layout; + /** + * \brief Layout qualifier for gl_FragDepth. + * + * This is not equal to \c ir_depth_layout_none if and only if this + * variable is \c gl_FragDepth and a layout qualifier is specified. + */ + ir_depth_layout depth_layout; + + /** + * Storage location of the base of this variable + * + * The precise meaning of this field depends on the nature of the variable. + * + * - Vertex shader input: one of the values from \c gl_vert_attrib. + * - Vertex shader output: one of the values from \c gl_varying_slot. + * - Geometry shader input: one of the values from \c gl_varying_slot. + * - Geometry shader output: one of the values from \c gl_varying_slot. + * - Fragment shader input: one of the values from \c gl_varying_slot. + * - Fragment shader output: one of the values from \c gl_frag_result. + * - Uniforms: Per-stage uniform slot number for default uniform block. + * - Uniforms: Index within the uniform block definition for UBO members. + * - Other: This field is not currently used. + * + * If the variable is a uniform, shader input, or shader output, and the + * slot has not been assigned, the value will be -1. + */ + int location; - /** - * Storage location of the base of this variable - * - * The precise meaning of this field depends on the nature of the variable. - * - * - Vertex shader input: one of the values from \c gl_vert_attrib. - * - Vertex shader output: one of the values from \c gl_varying_slot. - * - Geometry shader input: one of the values from \c gl_varying_slot. - * - Geometry shader output: one of the values from \c gl_varying_slot. - * - Fragment shader input: one of the values from \c gl_varying_slot. - * - Fragment shader output: one of the values from \c gl_frag_result. - * - Uniforms: Per-stage uniform slot number for default uniform block. - * - Uniforms: Index within the uniform block definition for UBO members. - * - Other: This field is not currently used. - * - * If the variable is a uniform, shader input, or shader output, and the - * slot has not been assigned, the value will be -1. - */ - int location; + /** + * output index for dual source blending. + */ + int index; - /** - * output index for dual source blending. - */ - int index; + /** + * Initial binding point for a sampler or UBO. + * + * For array types, this represents the binding point for the first element. + */ + int binding; - /** - * Initial binding point for a sampler or UBO. - * - * For array types, this represents the binding point for the first element. - */ - int binding; + /** + * Location an atomic counter is stored at. + */ + struct { + unsigned buffer_index; + unsigned offset; + } atomic; + + /** + * Highest element accessed with a constant expression array index + * + * Not used for non-array variables. + */ + unsigned max_array_access; - /** - * Location an atomic counter is stored at. - */ - struct { - unsigned buffer_index; - unsigned offset; - } atomic; + } data; /** * Built-in state that backs this uniform @@ -1022,34 +1028,6 @@ public: /** List of ir_instruction that make up the body of the loop. */ exec_list body_instructions; - - /** - * \name Loop counter and controls - * - * Represents a loop like a FORTRAN \c do-loop. - * - * \note - * If \c from and \c to are the same value, the loop will execute once. - */ - /*@{*/ - ir_rvalue *from; /** Value of the loop counter on the first - * iteration of the loop. - */ - ir_rvalue *to; /** Value of the loop counter on the last - * iteration of the loop. - */ - ir_rvalue *increment; - ir_variable *counter; - - /** - * Comparison operation in the loop terminator. - * - * If any of the loop control fields are non-\c NULL, this field must be - * one of \c ir_binop_less, \c ir_binop_greater, \c ir_binop_lequal, - * \c ir_binop_gequal, \c ir_binop_equal, or \c ir_binop_nequal. - */ - int cmp; - /*@}*/ }; @@ -2344,6 +2322,9 @@ extern ir_function_signature * _mesa_glsl_find_builtin_function(_mesa_glsl_parse_state *state, const char *name, exec_list *actual_parameters); +extern gl_shader * +_mesa_glsl_get_builtin_function_shader(void); + extern void _mesa_glsl_release_functions(void); diff --git a/mesalib/src/glsl/ir_clone.cpp b/mesalib/src/glsl/ir_clone.cpp index 40ed33afc..4e5cf68ca 100644 --- a/mesalib/src/glsl/ir_clone.cpp +++ b/mesalib/src/glsl/ir_clone.cpp @@ -41,35 +41,19 @@ ir_variable * ir_variable::clone(void *mem_ctx, struct hash_table *ht) const { ir_variable *var = new(mem_ctx) ir_variable(this->type, this->name, - (ir_variable_mode) this->mode); + (ir_variable_mode) this->data.mode); - var->max_array_access = this->max_array_access; + var->data.max_array_access = this->data.max_array_access; if (this->is_interface_instance()) { var->max_ifc_array_access = rzalloc_array(var, unsigned, this->interface_type->length); memcpy(var->max_ifc_array_access, this->max_ifc_array_access, this->interface_type->length * sizeof(unsigned)); } - var->read_only = this->read_only; - var->centroid = this->centroid; - var->invariant = this->invariant; - var->interpolation = this->interpolation; - var->location = this->location; - var->index = this->index; - var->binding = this->binding; - var->atomic.buffer_index = this->atomic.buffer_index; - var->atomic.offset = this->atomic.offset; + + memcpy(&var->data, &this->data, sizeof(var->data)); + var->warn_extension = this->warn_extension; - var->origin_upper_left = this->origin_upper_left; - var->pixel_center_integer = this->pixel_center_integer; - var->explicit_location = this->explicit_location; - var->explicit_index = this->explicit_index; - var->explicit_binding = this->explicit_binding; - var->has_initializer = this->has_initializer; - var->depth_layout = this->depth_layout; - var->assigned = this->assigned; - var->how_declared = this->how_declared; - var->used = this->used; var->num_state_slots = this->num_state_slots; if (this->state_slots) { @@ -157,20 +141,11 @@ ir_loop::clone(void *mem_ctx, struct hash_table *ht) const { ir_loop *new_loop = new(mem_ctx) ir_loop(); - if (this->from) - new_loop->from = this->from->clone(mem_ctx, ht); - if (this->to) - new_loop->to = this->to->clone(mem_ctx, ht); - if (this->increment) - new_loop->increment = this->increment->clone(mem_ctx, ht); - new_loop->counter = counter; - foreach_iter(exec_list_iterator, iter, this->body_instructions) { ir_instruction *ir = (ir_instruction *)iter.get(); new_loop->body_instructions.push_tail(ir->clone(mem_ctx, ht)); } - new_loop->cmp = this->cmp; return new_loop; } diff --git a/mesalib/src/glsl/ir_constant_expression.cpp b/mesalib/src/glsl/ir_constant_expression.cpp index 0efd1d5b3..7ca865e22 100644 --- a/mesalib/src/glsl/ir_constant_expression.cpp +++ b/mesalib/src/glsl/ir_constant_expression.cpp @@ -1583,7 +1583,7 @@ ir_dereference_variable::constant_expression_value(struct hash_table *variable_c /* The constant_value of a uniform variable is its initializer, * not the lifetime constant value of the uniform. */ - if (var->mode == ir_var_uniform) + if (var->data.mode == ir_var_uniform) return NULL; if (!var->constant_value) diff --git a/mesalib/src/glsl/ir_function.cpp b/mesalib/src/glsl/ir_function.cpp index 53cf469d9..bd5318d23 100644 --- a/mesalib/src/glsl/ir_function.cpp +++ b/mesalib/src/glsl/ir_function.cpp @@ -66,7 +66,7 @@ parameter_lists_match(const exec_list *list_a, const exec_list *list_b) /* Try to find an implicit conversion from actual to param. */ inexact_match = true; - switch ((enum ir_variable_mode)(param->mode)) { + switch ((enum ir_variable_mode)(param->data.mode)) { case ir_var_auto: case ir_var_uniform: case ir_var_temporary: diff --git a/mesalib/src/glsl/ir_hv_accept.cpp b/mesalib/src/glsl/ir_hv_accept.cpp index 941b25e97..2a1f70e5b 100644 --- a/mesalib/src/glsl/ir_hv_accept.cpp +++ b/mesalib/src/glsl/ir_hv_accept.cpp @@ -91,26 +91,6 @@ ir_loop::accept(ir_hierarchical_visitor *v) if (s == visit_stop) return s; - if (s != visit_continue_with_parent) { - if (this->from) { - s = this->from->accept(v); - if (s != visit_continue) - return (s == visit_continue_with_parent) ? visit_continue : s; - } - - if (this->to) { - s = this->to->accept(v); - if (s != visit_continue) - return (s == visit_continue_with_parent) ? visit_continue : s; - } - - if (this->increment) { - s = this->increment->accept(v); - if (s != visit_continue) - return (s == visit_continue_with_parent) ? visit_continue : s; - } - } - return v->visit_leave(this); } diff --git a/mesalib/src/glsl/ir_print_visitor.cpp b/mesalib/src/glsl/ir_print_visitor.cpp index f85e573c4..01c5f7f1c 100644 --- a/mesalib/src/glsl/ir_print_visitor.cpp +++ b/mesalib/src/glsl/ir_print_visitor.cpp @@ -148,8 +148,9 @@ void ir_print_visitor::visit(ir_variable *ir) { printf("(declare "); - const char *const cent = (ir->centroid) ? "centroid " : ""; - const char *const inv = (ir->invariant) ? "invariant " : ""; + const char *const cent = (ir->data.centroid) ? "centroid " : ""; + const char *const samp = (ir->data.sample) ? "sample " : ""; + const char *const inv = (ir->data.invariant) ? "invariant " : ""; const char *const mode[] = { "", "uniform ", "shader_in ", "shader_out ", "in ", "out ", "inout ", "const_in ", "sys ", "temporary " }; @@ -157,8 +158,8 @@ void ir_print_visitor::visit(ir_variable *ir) const char *const interp[] = { "", "smooth", "flat", "noperspective" }; STATIC_ASSERT(ARRAY_SIZE(interp) == INTERP_QUALIFIER_COUNT); - printf("(%s%s%s%s) ", - cent, inv, mode[ir->mode], interp[ir->interpolation]); + printf("(%s%s%s%s%s) ", + cent, samp, inv, mode[ir->data.mode], interp[ir->data.interpolation]); print_type(ir->type); printf(" %s)", unique_name(ir)); @@ -416,9 +417,9 @@ void ir_print_visitor::visit(ir_constant *ir) if (ir->value.f[i] == 0.0f) /* 0.0 == -0.0, so print with %f to get the proper sign. */ printf("%.1f", ir->value.f[i]); - else if (abs(ir->value.f[i]) < 0.000001f) + else if (fabs(ir->value.f[i]) < 0.000001f) printf("%a", ir->value.f[i]); - else if (abs(ir->value.f[i]) > 1000000.0f) + else if (fabs(ir->value.f[i]) > 1000000.0f) printf("%e", ir->value.f[i]); else printf("%f", ir->value.f[i]); @@ -522,19 +523,7 @@ ir_print_visitor::visit(ir_if *ir) void ir_print_visitor::visit(ir_loop *ir) { - printf("(loop ("); - if (ir->counter != NULL) - ir->counter->accept(this); - printf(") ("); - if (ir->from != NULL) - ir->from->accept(this); - printf(") ("); - if (ir->to != NULL) - ir->to->accept(this); - printf(") ("); - if (ir->increment != NULL) - ir->increment->accept(this); - printf(") (\n"); + printf("(loop (\n"); indentation++; foreach_iter(exec_list_iterator, iter, ir->body_instructions) { diff --git a/mesalib/src/glsl/ir_reader.cpp b/mesalib/src/glsl/ir_reader.cpp index 00e2db9a3..7970112ec 100644 --- a/mesalib/src/glsl/ir_reader.cpp +++ b/mesalib/src/glsl/ir_reader.cpp @@ -412,33 +412,35 @@ ir_reader::read_declaration(s_expression *expr) // FINISHME: Check for duplicate/conflicting qualifiers. if (strcmp(qualifier->value(), "centroid") == 0) { - var->centroid = 1; + var->data.centroid = 1; + } else if (strcmp(qualifier->value(), "sample") == 0) { + var->data.sample = 1; } else if (strcmp(qualifier->value(), "invariant") == 0) { - var->invariant = 1; + var->data.invariant = 1; } else if (strcmp(qualifier->value(), "uniform") == 0) { - var->mode = ir_var_uniform; + var->data.mode = ir_var_uniform; } else if (strcmp(qualifier->value(), "auto") == 0) { - var->mode = ir_var_auto; + var->data.mode = ir_var_auto; } else if (strcmp(qualifier->value(), "in") == 0) { - var->mode = ir_var_function_in; + var->data.mode = ir_var_function_in; } else if (strcmp(qualifier->value(), "shader_in") == 0) { - var->mode = ir_var_shader_in; + var->data.mode = ir_var_shader_in; } else if (strcmp(qualifier->value(), "const_in") == 0) { - var->mode = ir_var_const_in; + var->data.mode = ir_var_const_in; } else if (strcmp(qualifier->value(), "out") == 0) { - var->mode = ir_var_function_out; + var->data.mode = ir_var_function_out; } else if (strcmp(qualifier->value(), "shader_out") == 0) { - var->mode = ir_var_shader_out; + var->data.mode = ir_var_shader_out; } else if (strcmp(qualifier->value(), "inout") == 0) { - var->mode = ir_var_function_inout; + var->data.mode = ir_var_function_inout; } else if (strcmp(qualifier->value(), "temporary") == 0) { - var->mode = ir_var_temporary; + var->data.mode = ir_var_temporary; } else if (strcmp(qualifier->value(), "smooth") == 0) { - var->interpolation = INTERP_QUALIFIER_SMOOTH; + var->data.interpolation = INTERP_QUALIFIER_SMOOTH; } else if (strcmp(qualifier->value(), "flat") == 0) { - var->interpolation = INTERP_QUALIFIER_FLAT; + var->data.interpolation = INTERP_QUALIFIER_FLAT; } else if (strcmp(qualifier->value(), "noperspective") == 0) { - var->interpolation = INTERP_QUALIFIER_NOPERSPECTIVE; + var->data.interpolation = INTERP_QUALIFIER_NOPERSPECTIVE; } else { ir_read_error(expr, "unknown qualifier: %s", qualifier->value()); return NULL; @@ -486,18 +488,16 @@ ir_reader::read_if(s_expression *expr, ir_loop *loop_ctx) ir_loop * ir_reader::read_loop(s_expression *expr) { - s_expression *s_counter, *s_from, *s_to, *s_inc, *s_body; + s_expression *s_body; - s_pattern pat[] = { "loop", s_counter, s_from, s_to, s_inc, s_body }; - if (!MATCH(expr, pat)) { - ir_read_error(expr, "expected (loop " - " )"); + s_pattern loop_pat[] = { "loop", s_body }; + if (!MATCH(expr, loop_pat)) { + ir_read_error(expr, "expected (loop )"); return NULL; } - // FINISHME: actually read the count/from/to fields. - ir_loop *loop = new(mem_ctx) ir_loop; + read_instructions(&loop->body_instructions, s_body, loop); if (state->error) { delete loop; diff --git a/mesalib/src/glsl/ir_set_program_inouts.cpp b/mesalib/src/glsl/ir_set_program_inouts.cpp index ab23538c3..0b49eb2b6 100644 --- a/mesalib/src/glsl/ir_set_program_inouts.cpp +++ b/mesalib/src/glsl/ir_set_program_inouts.cpp @@ -27,7 +27,7 @@ * Sets the InputsRead and OutputsWritten of Mesa programs. * * Additionally, for fragment shaders, sets the InterpQualifier array, the - * IsCentroid bitfield, and the UsesDFdy flag. + * IsCentroid and IsSample bitfields, and the UsesDFdy flag. * * Mesa programs (gl_program, not gl_shader_program) have a set of * flags indicating which varyings are read and written. Computing @@ -75,9 +75,9 @@ private: static inline bool is_shader_inout(ir_variable *var) { - return var->mode == ir_var_shader_in || - var->mode == ir_var_shader_out || - var->mode == ir_var_system_value; + return var->data.mode == ir_var_shader_in || + var->data.mode == ir_var_shader_out || + var->data.mode == ir_var_system_value; } static void @@ -93,20 +93,24 @@ mark(struct gl_program *prog, ir_variable *var, int offset, int len, */ for (int i = 0; i < len; i++) { - GLbitfield64 bitfield = BITFIELD64_BIT(var->location + var->index + offset + i); - if (var->mode == ir_var_shader_in) { + GLbitfield64 bitfield = + BITFIELD64_BIT(var->data.location + var->data.index + offset + i); + if (var->data.mode == ir_var_shader_in) { prog->InputsRead |= bitfield; if (is_fragment_shader) { gl_fragment_program *fprog = (gl_fragment_program *) prog; - fprog->InterpQualifier[var->location + var->index + offset + i] = - (glsl_interp_qualifier) var->interpolation; - if (var->centroid) + fprog->InterpQualifier[var->data.location + + var->data.index + offset + i] = + (glsl_interp_qualifier) var->data.interpolation; + if (var->data.centroid) fprog->IsCentroid |= bitfield; + if (var->data.sample) + fprog->IsSample |= bitfield; } - } else if (var->mode == ir_var_system_value) { + } else if (var->data.mode == ir_var_system_value) { prog->SystemValuesRead |= bitfield; } else { - assert(var->mode == ir_var_shader_out); + assert(var->data.mode == ir_var_shader_out); prog->OutputsWritten |= bitfield; } } @@ -121,7 +125,7 @@ ir_set_program_inouts_visitor::mark_whole_variable(ir_variable *var) { const glsl_type *type = var->type; if (this->shader_type == GL_GEOMETRY_SHADER && - var->mode == ir_var_shader_in && type->is_array()) { + var->data.mode == ir_var_shader_in && type->is_array()) { type = type->fields.array; } @@ -160,7 +164,7 @@ ir_set_program_inouts_visitor::try_mark_partial_variable(ir_variable *var, const glsl_type *type = var->type; if (this->shader_type == GL_GEOMETRY_SHADER && - var->mode == ir_var_shader_in) { + var->data.mode == ir_var_shader_in) { /* The only geometry shader input that is not an array is * gl_PrimitiveIDIn, and in that case, this code will never be reached, * because gl_PrimitiveIDIn can't be indexed into in array fashion. @@ -242,7 +246,7 @@ ir_set_program_inouts_visitor::visit_enter(ir_dereference_array *ir) if (ir_dereference_variable * const deref_var = inner_array->array->as_dereference_variable()) { if (this->shader_type == GL_GEOMETRY_SHADER && - deref_var->var->mode == ir_var_shader_in) { + deref_var->var->data.mode == ir_var_shader_in) { /* foo is a geometry shader input, so i is the vertex, and j the * part of the input we're accessing. */ @@ -261,7 +265,7 @@ ir_set_program_inouts_visitor::visit_enter(ir_dereference_array *ir) ir->array->as_dereference_variable()) { /* ir => foo[i], where foo is a variable. */ if (this->shader_type == GL_GEOMETRY_SHADER && - deref_var->var->mode == ir_var_shader_in) { + deref_var->var->data.mode == ir_var_shader_in) { /* foo is a geometry shader input, so i is the vertex, and we're * accessing the entire input. */ @@ -341,6 +345,7 @@ do_set_program_inouts(exec_list *instructions, struct gl_program *prog, gl_fragment_program *fprog = (gl_fragment_program *) prog; memset(fprog->InterpQualifier, 0, sizeof(fprog->InterpQualifier)); fprog->IsCentroid = 0; + fprog->IsSample = 0; fprog->UsesDFdy = false; fprog->UsesKill = false; } diff --git a/mesalib/src/glsl/ir_validate.cpp b/mesalib/src/glsl/ir_validate.cpp index 13e41a089..4bbb3ce65 100644 --- a/mesalib/src/glsl/ir_validate.cpp +++ b/mesalib/src/glsl/ir_validate.cpp @@ -63,7 +63,6 @@ public: virtual ir_visitor_status visit_enter(ir_if *ir); - virtual ir_visitor_status visit_leave(ir_loop *ir); virtual ir_visitor_status visit_enter(ir_function *ir); virtual ir_visitor_status visit_leave(ir_function *ir); virtual ir_visitor_status visit_enter(ir_function_signature *ir); @@ -148,42 +147,6 @@ ir_validate::visit_enter(ir_if *ir) } -ir_visitor_status -ir_validate::visit_leave(ir_loop *ir) -{ - if (ir->counter != NULL) { - if ((ir->from == NULL) || (ir->to == NULL) || (ir->increment == NULL)) { - printf("ir_loop has invalid loop controls:\n" - " counter: %p\n" - " from: %p\n" - " to: %p\n" - " increment: %p\n", - (void *) ir->counter, (void *) ir->from, (void *) ir->to, - (void *) ir->increment); - abort(); - } - - if ((ir->cmp < ir_binop_less) || (ir->cmp > ir_binop_nequal)) { - printf("ir_loop has invalid comparitor %d\n", ir->cmp); - abort(); - } - } else { - if ((ir->from != NULL) || (ir->to != NULL) || (ir->increment != NULL)) { - printf("ir_loop has invalid loop controls:\n" - " counter: %p\n" - " from: %p\n" - " to: %p\n" - " increment: %p\n", - (void *) ir->counter, (void *) ir->from, (void *) ir->to, - (void *) ir->increment); - abort(); - } - } - - return visit_continue; -} - - ir_visitor_status ir_validate::visit_enter(ir_function *ir) { @@ -679,9 +642,9 @@ ir_validate::visit(ir_variable *ir) * to be out of bounds. */ if (ir->type->array_size() > 0) { - if (ir->max_array_access >= ir->type->length) { + if (ir->data.max_array_access >= ir->type->length) { printf("ir_variable has maximum access out of bounds (%d vs %d)\n", - ir->max_array_access, ir->type->length - 1); + ir->data.max_array_access, ir->type->length - 1); ir->print(); abort(); } @@ -707,7 +670,7 @@ ir_validate::visit(ir_variable *ir) } } - if (ir->constant_initializer != NULL && !ir->has_initializer) { + if (ir->constant_initializer != NULL && !ir->data.has_initializer) { printf("ir_variable didn't have an initializer, but has a constant " "initializer value.\n"); ir->print(); @@ -789,8 +752,8 @@ ir_validate::visit_enter(ir_call *ir) printf("ir_call parameter type mismatch:\n"); goto dump_ir; } - if (formal_param->mode == ir_var_function_out - || formal_param->mode == ir_var_function_inout) { + if (formal_param->data.mode == ir_var_function_out + || formal_param->data.mode == ir_var_function_inout) { if (!actual_param->is_lvalue()) { printf("ir_call out/inout parameters must be lvalues:\n"); goto dump_ir; diff --git a/mesalib/src/glsl/link_atomics.cpp b/mesalib/src/glsl/link_atomics.cpp index 2466bbd79..33903ad54 100644 --- a/mesalib/src/glsl/link_atomics.cpp +++ b/mesalib/src/glsl/link_atomics.cpp @@ -73,16 +73,16 @@ namespace { const active_atomic_counter *const first = (active_atomic_counter *) a; const active_atomic_counter *const second = (active_atomic_counter *) b; - return int(first->var->atomic.offset) - int(second->var->atomic.offset); + return int(first->var->data.atomic.offset) - int(second->var->data.atomic.offset); } bool check_atomic_counters_overlap(const ir_variable *x, const ir_variable *y) { - return ((x->atomic.offset >= y->atomic.offset && - x->atomic.offset < y->atomic.offset + y->type->atomic_size()) || - (y->atomic.offset >= x->atomic.offset && - y->atomic.offset < x->atomic.offset + x->type->atomic_size())); + return ((x->data.atomic.offset >= y->data.atomic.offset && + x->data.atomic.offset < y->data.atomic.offset + y->type->atomic_size()) || + (y->data.atomic.offset >= x->data.atomic.offset && + y->data.atomic.offset < x->data.atomic.offset + x->type->atomic_size())); } active_atomic_buffer * @@ -107,7 +107,7 @@ namespace { unsigned id; bool found = prog->UniformHash->get(id, var->name); assert(found); - active_atomic_buffer *buf = &buffers[var->binding]; + active_atomic_buffer *buf = &buffers[var->data.binding]; /* If this is the first time the buffer is used, increment * the counter of buffers used. @@ -118,7 +118,7 @@ namespace { buf->push_back(id, var); buf->stage_references[i]++; - buf->size = MAX2(buf->size, var->atomic.offset + + buf->size = MAX2(buf->size, var->data.atomic.offset + var->type->atomic_size()); } } @@ -143,7 +143,7 @@ namespace { linker_error(prog, "Atomic counter %s declared at offset %d " "which is already in use.", buffers[i].counters[j].var->name, - buffers[i].counters[j].var->atomic.offset); + buffers[i].counters[j].var->data.atomic.offset); } } } @@ -190,9 +190,9 @@ link_assign_atomic_counter_resources(struct gl_context *ctx, gl_uniform_storage *const storage = &prog->UniformStorage[id]; mab.Uniforms[j] = id; - var->atomic.buffer_index = i; + var->data.atomic.buffer_index = i; storage->atomic_buffer_index = i; - storage->offset = var->atomic.offset; + storage->offset = var->data.atomic.offset; storage->array_stride = (var->type->is_array() ? var->type->element_type()->atomic_size() : 0); } diff --git a/mesalib/src/glsl/link_functions.cpp b/mesalib/src/glsl/link_functions.cpp index 68aa62032..56f3f207e 100644 --- a/mesalib/src/glsl/link_functions.cpp +++ b/mesalib/src/glsl/link_functions.cpp @@ -201,8 +201,9 @@ public: if (formal_param->type->is_array()) { ir_dereference_variable *deref = actual_param->as_dereference_variable(); if (deref && deref->var && deref->var->type->is_array()) { - deref->var->max_array_access = - MAX2(formal_param->max_array_access, deref->var->max_array_access); + deref->var->data.max_array_access = + MAX2(formal_param->data.max_array_access, + deref->var->data.max_array_access); } } } @@ -234,8 +235,9 @@ public: * we need to track the maximal access to the array as linking * pulls more functions in that access the array. */ - var->max_array_access = - MAX2(var->max_array_access, ir->var->max_array_access); + var->data.max_array_access = + MAX2(var->data.max_array_access, + ir->var->data.max_array_access); if (var->type->length == 0 && ir->var->type->length != 0) var->type = ir->var->type; diff --git a/mesalib/src/glsl/link_interface_blocks.cpp b/mesalib/src/glsl/link_interface_blocks.cpp index 6900fa94e..476963642 100644 --- a/mesalib/src/glsl/link_interface_blocks.cpp +++ b/mesalib/src/glsl/link_interface_blocks.cpp @@ -60,7 +60,7 @@ struct interface_block_definition if (var->type->is_array()) array_size = var->type->length; } - explicitly_declared = (var->how_declared != ir_var_declared_implicitly); + explicitly_declared = (var->data.how_declared != ir_var_declared_implicitly); } /** @@ -270,7 +270,7 @@ validate_intrastage_interface_blocks(struct gl_shader_program *prog, continue; interface_block_definitions *definitions; - switch (var->mode) { + switch (var->data.mode) { case ir_var_shader_in: definitions = &in_interfaces; break; @@ -298,7 +298,7 @@ validate_intrastage_interface_blocks(struct gl_shader_program *prog, */ definitions->store(def); } else if (!intrastage_match(prev_def, &def, - (ir_variable_mode) var->mode)) { + (ir_variable_mode) var->data.mode)) { linker_error(prog, "definitions of interface block `%s' do not" " match\n", iface_type->name); return; @@ -318,7 +318,7 @@ validate_interstage_inout_blocks(struct gl_shader_program *prog, /* Add input interfaces from the consumer to the symbol table. */ foreach_list(node, consumer->ir) { ir_variable *var = ((ir_instruction *) node)->as_variable(); - if (!var || !var->get_interface_type() || var->mode != ir_var_shader_in) + if (!var || !var->get_interface_type() || var->data.mode != ir_var_shader_in) continue; definitions.store(interface_block_definition(var)); @@ -327,7 +327,7 @@ validate_interstage_inout_blocks(struct gl_shader_program *prog, /* Verify that the producer's output interfaces match. */ foreach_list(node, producer->ir) { ir_variable *var = ((ir_instruction *) node)->as_variable(); - if (!var || !var->get_interface_type() || var->mode != ir_var_shader_out) + if (!var || !var->get_interface_type() || var->data.mode != ir_var_shader_out) continue; interface_block_definition *consumer_def = @@ -361,7 +361,7 @@ validate_interstage_uniform_blocks(struct gl_shader_program *prog, const gl_shader *stage = stages[i]; foreach_list(node, stage->ir) { ir_variable *var = ((ir_instruction *) node)->as_variable(); - if (!var || !var->get_interface_type() || var->mode != ir_var_uniform) + if (!var || !var->get_interface_type() || var->data.mode != ir_var_uniform) continue; interface_block_definition *old_def = diff --git a/mesalib/src/glsl/link_uniform_initializers.cpp b/mesalib/src/glsl/link_uniform_initializers.cpp index 786aaf0b4..04daa1760 100644 --- a/mesalib/src/glsl/link_uniform_initializers.cpp +++ b/mesalib/src/glsl/link_uniform_initializers.cpp @@ -224,15 +224,15 @@ link_set_uniform_initializers(struct gl_shader_program *prog) foreach_list(node, shader->ir) { ir_variable *const var = ((ir_instruction *) node)->as_variable(); - if (!var || var->mode != ir_var_uniform) + if (!var || var->data.mode != ir_var_uniform) continue; if (!mem_ctx) mem_ctx = ralloc_context(NULL); - if (var->explicit_binding) { + if (var->data.explicit_binding) { linker::set_uniform_binding(mem_ctx, prog, var->name, - var->type, var->binding); + var->type, var->data.binding); } else if (var->constant_value) { linker::set_uniform_initializer(mem_ctx, prog, var->name, var->type, var->constant_value); diff --git a/mesalib/src/glsl/link_uniforms.cpp b/mesalib/src/glsl/link_uniforms.cpp index 0a15739c2..bda6e4ffb 100644 --- a/mesalib/src/glsl/link_uniforms.cpp +++ b/mesalib/src/glsl/link_uniforms.cpp @@ -75,7 +75,7 @@ program_resource_visitor::process(ir_variable *var) */ /* Only strdup the name if we actually will need to modify it. */ - if (var->from_named_ifc_block_array) { + if (var->data.from_named_ifc_block_array) { /* lower_named_interface_blocks created this variable by lowering an * interface block array to an array variable. For example if the * original source code was: @@ -108,7 +108,7 @@ program_resource_visitor::process(ir_variable *var) recursion(var->type, &name, new_length, false, NULL); } ralloc_free(name); - } else if (var->from_named_ifc_block_nonarray) { + } else if (var->data.from_named_ifc_block_nonarray) { /* lower_named_interface_blocks created this variable by lowering a * named interface block (non-array) to an ordinary variable. For * example if the original source code was: @@ -408,10 +408,10 @@ public: const struct gl_uniform_block *const block = &prog->UniformBlocks[ubo_block_index]; - assert(var->location != -1); + assert(var->data.location != -1); const struct gl_uniform_buffer_variable *const ubo_var = - &block->Uniforms[var->location]; + &block->Uniforms[var->data.location]; ubo_row_major = ubo_var->RowMajor; ubo_byte_offset = ubo_var->Offset; @@ -637,10 +637,10 @@ link_update_uniform_buffer_variables(struct gl_shader *shader) if ((var == NULL) || !var->is_in_uniform_block()) continue; - assert(var->mode == ir_var_uniform); + assert(var->data.mode == ir_var_uniform); if (var->is_interface_instance()) { - var->location = 0; + var->data.location = 0; continue; } @@ -669,13 +669,13 @@ link_update_uniform_buffer_variables(struct gl_shader *shader) if (strncmp(var->name, begin, l) == 0) { found = true; - var->location = j; + var->data.location = j; break; } } else if (!strcmp(var->name, shader->UniformBlocks[i].Uniforms[j].Name)) { found = true; - var->location = j; + var->data.location = j; break; } } @@ -767,7 +767,7 @@ link_assign_uniform_locations(struct gl_shader_program *prog) foreach_list(node, sh->ir) { ir_variable *const var = ((ir_instruction *) node)->as_variable(); - if ((var == NULL) || (var->mode != ir_var_uniform)) + if ((var == NULL) || (var->data.mode != ir_var_uniform)) continue; /* FINISHME: Update code to process built-in uniforms! @@ -818,7 +818,7 @@ link_assign_uniform_locations(struct gl_shader_program *prog) foreach_list(node, prog->_LinkedShaders[i]->ir) { ir_variable *const var = ((ir_instruction *) node)->as_variable(); - if ((var == NULL) || (var->mode != ir_var_uniform)) + if ((var == NULL) || (var->data.mode != ir_var_uniform)) continue; /* FINISHME: Update code to process built-in uniforms! diff --git a/mesalib/src/glsl/link_varyings.cpp b/mesalib/src/glsl/link_varyings.cpp index be36b5f8f..229a4cb85 100644 --- a/mesalib/src/glsl/link_varyings.cpp +++ b/mesalib/src/glsl/link_varyings.cpp @@ -93,31 +93,43 @@ cross_validate_types_and_qualifiers(struct gl_shader_program *prog, /* Check that all of the qualifiers match between stages. */ - if (input->centroid != output->centroid) { + if (input->data.centroid != output->data.centroid) { linker_error(prog, "%s shader output `%s' %s centroid qualifier, " "but %s shader input %s centroid qualifier\n", _mesa_glsl_shader_target_name(producer_type), output->name, - (output->centroid) ? "has" : "lacks", + (output->data.centroid) ? "has" : "lacks", _mesa_glsl_shader_target_name(consumer_type), - (input->centroid) ? "has" : "lacks"); + (input->data.centroid) ? "has" : "lacks"); return; } - if (input->invariant != output->invariant) { + if (input->data.sample != output->data.sample) { + linker_error(prog, + "%s shader output `%s' %s sample qualifier, " + "but %s shader input %s sample qualifier\n", + _mesa_glsl_shader_target_name(producer_type), + output->name, + (output->data.sample) ? "has" : "lacks", + _mesa_glsl_shader_target_name(consumer_type), + (input->data.sample) ? "has" : "lacks"); + return; + } + + if (input->data.invariant != output->data.invariant) { linker_error(prog, "%s shader output `%s' %s invariant qualifier, " "but %s shader input %s invariant qualifier\n", _mesa_glsl_shader_target_name(producer_type), output->name, - (output->invariant) ? "has" : "lacks", + (output->data.invariant) ? "has" : "lacks", _mesa_glsl_shader_target_name(consumer_type), - (input->invariant) ? "has" : "lacks"); + (input->data.invariant) ? "has" : "lacks"); return; } - if (input->interpolation != output->interpolation) { + if (input->data.interpolation != output->data.interpolation) { linker_error(prog, "%s shader output `%s' specifies %s " "interpolation qualifier, " @@ -125,9 +137,9 @@ cross_validate_types_and_qualifiers(struct gl_shader_program *prog, "interpolation qualifier\n", _mesa_glsl_shader_target_name(producer_type), output->name, - interpolation_string(output->interpolation), + interpolation_string(output->data.interpolation), _mesa_glsl_shader_target_name(consumer_type), - interpolation_string(input->interpolation)); + interpolation_string(input->data.interpolation)); return; } } @@ -143,11 +155,11 @@ cross_validate_front_and_back_color(struct gl_shader_program *prog, GLenum consumer_type, GLenum producer_type) { - if (front_color != NULL && front_color->assigned) + if (front_color != NULL && front_color->data.assigned) cross_validate_types_and_qualifiers(prog, input, front_color, consumer_type, producer_type); - if (back_color != NULL && back_color->assigned) + if (back_color != NULL && back_color->data.assigned) cross_validate_types_and_qualifiers(prog, input, back_color, consumer_type, producer_type); } @@ -166,7 +178,7 @@ cross_validate_outputs_to_inputs(struct gl_shader_program *prog, foreach_list(node, producer->ir) { ir_variable *const var = ((ir_instruction *) node)->as_variable(); - if ((var == NULL) || (var->mode != ir_var_shader_out)) + if ((var == NULL) || (var->data.mode != ir_var_shader_out)) continue; parameters.add_variable(var); @@ -184,10 +196,10 @@ cross_validate_outputs_to_inputs(struct gl_shader_program *prog, foreach_list(node, consumer->ir) { ir_variable *const input = ((ir_instruction *) node)->as_variable(); - if ((input == NULL) || (input->mode != ir_var_shader_in)) + if ((input == NULL) || (input->data.mode != ir_var_shader_in)) continue; - if (strcmp(input->name, "gl_Color") == 0 && input->used) { + if (strcmp(input->name, "gl_Color") == 0 && input->data.used) { const ir_variable *const front_color = parameters.get_variable("gl_FrontColor"); @@ -197,7 +209,7 @@ cross_validate_outputs_to_inputs(struct gl_shader_program *prog, cross_validate_front_and_back_color(prog, input, front_color, back_color, consumer->Type, producer->Type); - } else if (strcmp(input->name, "gl_SecondaryColor") == 0 && input->used) { + } else if (strcmp(input->name, "gl_SecondaryColor") == 0 && input->data.used) { const ir_variable *const front_color = parameters.get_variable("gl_FrontSecondaryColor"); @@ -317,8 +329,8 @@ tfeedback_decl::assign_location(struct gl_context *ctx, assert(this->is_varying()); unsigned fine_location - = this->matched_candidate->toplevel_var->location * 4 - + this->matched_candidate->toplevel_var->location_frac + = this->matched_candidate->toplevel_var->data.location * 4 + + this->matched_candidate->toplevel_var->data.location_frac + this->matched_candidate->offset; if (this->matched_candidate->type->is_array()) { @@ -734,7 +746,7 @@ varying_matches::~varying_matches() void varying_matches::record(ir_variable *producer_var, ir_variable *consumer_var) { - if (!producer_var->is_unmatched_generic_inout) { + if (!producer_var->data.is_unmatched_generic_inout) { /* Either a location already exists for this variable (since it is part * of fixed functionality), or it has already been recorded as part of a * previous match. @@ -752,12 +764,14 @@ varying_matches::record(ir_variable *producer_var, ir_variable *consumer_var) * regardless of where they appear. We can trivially satisfy that * requirement by changing the interpolation type to flat here. */ - producer_var->centroid = false; - producer_var->interpolation = INTERP_QUALIFIER_FLAT; + producer_var->data.centroid = false; + producer_var->data.sample = false; + producer_var->data.interpolation = INTERP_QUALIFIER_FLAT; if (consumer_var) { - consumer_var->centroid = false; - consumer_var->interpolation = INTERP_QUALIFIER_FLAT; + consumer_var->data.centroid = false; + consumer_var->data.sample = false; + consumer_var->data.interpolation = INTERP_QUALIFIER_FLAT; } } @@ -784,9 +798,9 @@ varying_matches::record(ir_variable *producer_var, ir_variable *consumer_var) this->matches[this->num_matches].producer_var = producer_var; this->matches[this->num_matches].consumer_var = consumer_var; this->num_matches++; - producer_var->is_unmatched_generic_inout = 0; + producer_var->data.is_unmatched_generic_inout = 0; if (consumer_var) - consumer_var->is_unmatched_generic_inout = 0; + consumer_var->data.is_unmatched_generic_inout = 0; } @@ -838,12 +852,12 @@ varying_matches::store_locations(unsigned producer_base, unsigned slot = generic_location / 4; unsigned offset = generic_location % 4; - producer_var->location = producer_base + slot; - producer_var->location_frac = offset; + producer_var->data.location = producer_base + slot; + producer_var->data.location_frac = offset; if (consumer_var) { - assert(consumer_var->location == -1); - consumer_var->location = consumer_base + slot; - consumer_var->location_frac = offset; + assert(consumer_var->data.location == -1); + consumer_var->data.location = consumer_base + slot; + consumer_var->data.location_frac = offset; } } } @@ -873,9 +887,9 @@ varying_matches::compute_packing_class(ir_variable *var) * * Therefore, the packing class depends only on the interpolation type. */ - unsigned packing_class = var->centroid ? 1 : 0; + unsigned packing_class = var->data.centroid | (var->data.sample << 1); packing_class *= 4; - packing_class += var->interpolation; + packing_class += var->data.interpolation; return packing_class; } @@ -933,8 +947,8 @@ is_varying_var(GLenum shaderType, const ir_variable *var) { /* Only fragment shaders will take a varying variable as an input */ if (shaderType == GL_FRAGMENT_SHADER && - var->mode == ir_var_shader_in) { - switch (var->location) { + var->data.mode == ir_var_shader_in) { + switch (var->data.location) { case VARYING_SLOT_POS: case VARYING_SLOT_FACE: case VARYING_SLOT_PNTC: @@ -1082,7 +1096,7 @@ assign_varying_locations(struct gl_context *ctx, ir_variable *const input_var = ((ir_instruction *) node)->as_variable(); - if ((input_var != NULL) && (input_var->mode == ir_var_shader_in)) { + if ((input_var != NULL) && (input_var->data.mode == ir_var_shader_in)) { if (input_var->get_interface_type() != NULL) { char *const iface_field_name = ralloc_asprintf(mem_ctx, "%s.%s", @@ -1101,7 +1115,7 @@ assign_varying_locations(struct gl_context *ctx, foreach_list(node, producer->ir) { ir_variable *const output_var = ((ir_instruction *) node)->as_variable(); - if ((output_var == NULL) || (output_var->mode != ir_var_shader_out)) + if ((output_var == NULL) || (output_var->data.mode != ir_var_shader_out)) continue; tfeedback_candidate_generator g(mem_ctx, tfeedback_candidates); @@ -1121,7 +1135,7 @@ assign_varying_locations(struct gl_context *ctx, (ir_variable *) hash_table_find(consumer_inputs, output_var->name); } - if (input_var && input_var->mode != ir_var_shader_in) + if (input_var && input_var->data.mode != ir_var_shader_in) input_var = NULL; if (input_var) { @@ -1143,7 +1157,7 @@ assign_varying_locations(struct gl_context *ctx, return false; } - if (matched_candidate->toplevel_var->is_unmatched_generic_inout) + if (matched_candidate->toplevel_var->data.is_unmatched_generic_inout) matches.record(matched_candidate->toplevel_var, NULL); } @@ -1185,8 +1199,8 @@ assign_varying_locations(struct gl_context *ctx, foreach_list(node, consumer->ir) { ir_variable *const var = ((ir_instruction *) node)->as_variable(); - if (var && var->mode == ir_var_shader_in && - var->is_unmatched_generic_inout) { + if (var && var->data.mode == ir_var_shader_in && + var->data.is_unmatched_generic_inout) { if (prog->Version <= 120) { /* On page 25 (page 31 of the PDF) of the GLSL 1.20 spec: * @@ -1211,7 +1225,7 @@ assign_varying_locations(struct gl_context *ctx, /* An 'in' variable is only really a shader input if its * value is written by the previous stage. */ - var->mode = ir_var_auto; + var->data.mode = ir_var_auto; } } } @@ -1229,7 +1243,7 @@ check_against_output_limit(struct gl_context *ctx, foreach_list(node, producer->ir) { ir_variable *const var = ((ir_instruction *) node)->as_variable(); - if (var && var->mode == ir_var_shader_out && + if (var && var->data.mode == ir_var_shader_out && is_varying_var(producer->Type, var)) { output_vectors += var->type->count_attribute_slots(); } @@ -1278,7 +1292,7 @@ check_against_input_limit(struct gl_context *ctx, foreach_list(node, consumer->ir) { ir_variable *const var = ((ir_instruction *) node)->as_variable(); - if (var && var->mode == ir_var_shader_in && + if (var && var->data.mode == ir_var_shader_in && is_varying_var(consumer->Type, var)) { input_vectors += var->type->count_attribute_slots(); } diff --git a/mesalib/src/glsl/linker.cpp b/mesalib/src/glsl/linker.cpp index 1366077f7..a6133ea9c 100644 --- a/mesalib/src/glsl/linker.cpp +++ b/mesalib/src/glsl/linker.cpp @@ -114,8 +114,8 @@ public: ir_rvalue *param_rval = (ir_rvalue *)iter.get(); ir_variable *sig_param = (ir_variable *)sig_iter.get(); - if (sig_param->mode == ir_var_function_out || - sig_param->mode == ir_var_function_inout) { + if (sig_param->data.mode == ir_var_function_out || + sig_param->data.mode == ir_var_function_inout) { ir_variable *var = param_rval->variable_referenced(); if (var && strcmp(name, var->name) == 0) { found = true; @@ -198,7 +198,7 @@ public: virtual ir_visitor_status visit(ir_variable *var) { - if (!var->type->is_array() || var->mode != ir_var_shader_in) + if (!var->type->is_array() || var->data.mode != ir_var_shader_in) return visit_continue; unsigned size = var->type->length; @@ -217,16 +217,16 @@ public: * array using an index too large for its actual size assigned at link * time. */ - if (var->max_array_access >= this->num_vertices) { + if (var->data.max_array_access >= this->num_vertices) { linker_error(this->prog, "geometry shader accesses element %i of " "%s, but only %i input vertices\n", - var->max_array_access, var->name, this->num_vertices); + var->data.max_array_access, var->name, this->num_vertices); return visit_continue; } var->type = glsl_type::get_array_instance(var->type->element_type(), this->num_vertices); - var->max_array_access = this->num_vertices - 1; + var->data.max_array_access = this->num_vertices - 1; return visit_continue; } @@ -379,9 +379,9 @@ link_invalidate_variable_locations(exec_list *ir) * shader inputs (via layout(location=...)), and generic fragment shader * outputs (also via layout(location=...)). */ - if (!var->explicit_location) { - var->location = -1; - var->location_frac = 0; + if (!var->data.explicit_location) { + var->data.location = -1; + var->data.location_frac = 0; } /* ir_variable::is_unmatched_generic_inout is used by the linker while @@ -396,10 +396,10 @@ link_invalidate_variable_locations(exec_list *ir) * GL_ARB_separate_shader_objects is supported. When that extension is * implemented, this function will need some modifications. */ - if (!var->explicit_location) { - var->is_unmatched_generic_inout = 1; + if (!var->data.explicit_location) { + var->data.is_unmatched_generic_inout = 1; } else { - var->is_unmatched_generic_inout = 0; + var->data.is_unmatched_generic_inout = 0; } } } @@ -580,13 +580,13 @@ cross_validate_globals(struct gl_shader_program *prog, if (var == NULL) continue; - if (uniforms_only && (var->mode != ir_var_uniform)) + if (uniforms_only && (var->data.mode != ir_var_uniform)) continue; /* Don't cross validate temporaries that are at global scope. These * will eventually get pulled into the shaders 'main'. */ - if (var->mode == ir_var_temporary) + if (var->data.mode == ir_var_temporary) continue; /* If a global with this name has already been seen, verify that the @@ -619,17 +619,17 @@ cross_validate_globals(struct gl_shader_program *prog, } } - if (var->explicit_location) { - if (existing->explicit_location - && (var->location != existing->location)) { + if (var->data.explicit_location) { + if (existing->data.explicit_location + && (var->data.location != existing->data.location)) { linker_error(prog, "explicit locations for %s " "`%s' have differing values\n", mode_string(var), var->name); return; } - existing->location = var->location; - existing->explicit_location = true; + existing->data.location = var->data.location; + existing->data.explicit_location = true; } /* From the GLSL 4.20 specification: @@ -638,21 +638,21 @@ cross_validate_globals(struct gl_shader_program *prog, * opaque-uniform name. However, it is not an error to specify a * binding on some but not all declarations for the same name" */ - if (var->explicit_binding) { - if (existing->explicit_binding && - var->binding != existing->binding) { + if (var->data.explicit_binding) { + if (existing->data.explicit_binding && + var->data.binding != existing->data.binding) { linker_error(prog, "explicit bindings for %s " "`%s' have differing values\n", mode_string(var), var->name); return; } - existing->binding = var->binding; - existing->explicit_binding = true; + existing->data.binding = var->data.binding; + existing->data.explicit_binding = true; } if (var->type->contains_atomic() && - var->atomic.offset != existing->atomic.offset) { + var->data.atomic.offset != existing->data.atomic.offset) { linker_error(prog, "offset specifications for %s " "`%s' have differing values\n", mode_string(var), var->name); @@ -671,9 +671,9 @@ cross_validate_globals(struct gl_shader_program *prog, * of qualifiers." */ if (strcmp(var->name, "gl_FragDepth") == 0) { - bool layout_declared = var->depth_layout != ir_depth_layout_none; + bool layout_declared = var->data.depth_layout != ir_depth_layout_none; bool layout_differs = - var->depth_layout != existing->depth_layout; + var->data.depth_layout != existing->data.depth_layout; if (layout_declared && layout_differs) { linker_error(prog, @@ -682,7 +682,7 @@ cross_validate_globals(struct gl_shader_program *prog, "the same set of qualifiers."); } - if (var->used && layout_differs) { + if (var->data.used && layout_differs) { linker_error(prog, "If gl_FragDepth is redeclared with a layout " "qualifier in any fragment shader, it must be " @@ -734,8 +734,8 @@ cross_validate_globals(struct gl_shader_program *prog, } } - if (var->has_initializer) { - if (existing->has_initializer + if (var->data.has_initializer) { + if (existing->data.has_initializer && (var->constant_initializer == NULL || existing->constant_initializer == NULL)) { linker_error(prog, @@ -750,21 +750,27 @@ cross_validate_globals(struct gl_shader_program *prog, * otherwise) will propagate the existence to the variable * stored in the symbol table. */ - existing->has_initializer = true; + existing->data.has_initializer = true; } - if (existing->invariant != var->invariant) { + if (existing->data.invariant != var->data.invariant) { linker_error(prog, "declarations for %s `%s' have " "mismatching invariant qualifiers\n", mode_string(var), var->name); return; } - if (existing->centroid != var->centroid) { + if (existing->data.centroid != var->data.centroid) { linker_error(prog, "declarations for %s `%s' have " "mismatching centroid qualifiers\n", mode_string(var), var->name); return; } + if (existing->data.sample != var->data.sample) { + linker_error(prog, "declarations for %s `%s` have " + "mismatching sample qualifiers\n", + mode_string(var), var->name); + return; + } } else variables.add_variable(var); } @@ -884,7 +890,7 @@ remap_variables(ir_instruction *inst, struct gl_shader *target, virtual ir_visitor_status visit(ir_dereference_variable *ir) { - if (ir->var->mode == ir_var_temporary) { + if (ir->var->data.mode == ir_var_temporary) { ir_variable *var = (ir_variable *) hash_table_find(temps, ir->var); assert(var != NULL); @@ -958,13 +964,13 @@ move_non_declarations(exec_list *instructions, exec_node *last, continue; ir_variable *var = inst->as_variable(); - if ((var != NULL) && (var->mode != ir_var_temporary)) + if ((var != NULL) && (var->data.mode != ir_var_temporary)) continue; assert(inst->as_assignment() || inst->as_call() || inst->as_if() /* for initializers with the ?: operator */ - || ((var != NULL) && (var->mode == ir_var_temporary))); + || ((var != NULL) && (var->data.mode == ir_var_temporary))); if (make_copies) { inst = inst->clone(target, NULL); @@ -1036,7 +1042,7 @@ public: virtual ir_visitor_status visit(ir_variable *var) { - fixup_type(&var->type, var->max_array_access); + fixup_type(&var->type, var->data.max_array_access); if (var->type->is_interface()) { if (interface_contains_unsized_arrays(var->type)) { const glsl_type *new_type = @@ -1405,36 +1411,38 @@ link_intrastage_shaders(void *mem_ctx, insertion_point, true, linked); } - /* Resolve initializers for global variables in the linked shader. - */ - unsigned num_linking_shaders = num_shaders; - for (unsigned i = 0; i < num_shaders; i++) - num_linking_shaders += shader_list[i]->num_builtins_to_link; + /* Check if any shader needs built-in functions. */ + bool need_builtins = false; + for (unsigned i = 0; i < num_shaders; i++) { + if (shader_list[i]->uses_builtin_functions) { + need_builtins = true; + break; + } + } - gl_shader **linking_shaders = - (gl_shader **) calloc(num_linking_shaders, sizeof(gl_shader *)); + bool ok; + if (need_builtins) { + /* Make a temporary array one larger than shader_list, which will hold + * the built-in function shader as well. + */ + gl_shader **linking_shaders = (gl_shader **) + calloc(num_shaders + 1, sizeof(gl_shader *)); + memcpy(linking_shaders, shader_list, num_shaders * sizeof(gl_shader *)); + linking_shaders[num_shaders] = _mesa_glsl_get_builtin_function_shader(); - memcpy(linking_shaders, shader_list, - sizeof(linking_shaders[0]) * num_shaders); + ok = link_function_calls(prog, linked, linking_shaders, num_shaders + 1); - unsigned idx = num_shaders; - for (unsigned i = 0; i < num_shaders; i++) { - memcpy(&linking_shaders[idx], shader_list[i]->builtins_to_link, - sizeof(linking_shaders[0]) * shader_list[i]->num_builtins_to_link); - idx += shader_list[i]->num_builtins_to_link; + free(linking_shaders); + } else { + ok = link_function_calls(prog, linked, shader_list, num_shaders); } - assert(idx == num_linking_shaders); - if (!link_function_calls(prog, linked, linking_shaders, - num_linking_shaders)) { + if (!ok) { ctx->Driver.DeleteShader(ctx, linked); - free(linking_shaders); return NULL; } - free(linking_shaders); - /* At this point linked should contain all of the linked IR, so * validate it to make sure nothing went wrong. */ @@ -1486,7 +1494,7 @@ update_array_sizes(struct gl_shader_program *prog) foreach_list(node, prog->_LinkedShaders[i]->ir) { ir_variable *const var = ((ir_instruction *) node)->as_variable(); - if ((var == NULL) || (var->mode != ir_var_uniform) || + if ((var == NULL) || (var->data.mode != ir_var_uniform) || !var->type->is_array()) continue; @@ -1501,7 +1509,7 @@ update_array_sizes(struct gl_shader_program *prog) if (var->is_in_uniform_block() || var->type->contains_atomic()) continue; - unsigned int size = var->max_array_access; + unsigned int size = var->data.max_array_access; for (unsigned j = 0; j < MESA_SHADER_TYPES; j++) { if (prog->_LinkedShaders[j] == NULL) continue; @@ -1512,8 +1520,8 @@ update_array_sizes(struct gl_shader_program *prog) continue; if (strcmp(var->name, other_var->name) == 0 && - other_var->max_array_access > size) { - size = other_var->max_array_access; + other_var->data.max_array_access > size) { + size = other_var->data.max_array_access; } } } @@ -1652,16 +1660,17 @@ assign_attribute_or_color_locations(gl_shader_program *prog, foreach_list(node, sh->ir) { ir_variable *const var = ((ir_instruction *) node)->as_variable(); - if ((var == NULL) || (var->mode != (unsigned) direction)) + if ((var == NULL) || (var->data.mode != (unsigned) direction)) continue; - if (var->explicit_location) { - if ((var->location >= (int)(max_index + generic_base)) - || (var->location < 0)) { + if (var->data.explicit_location) { + if ((var->data.location >= (int)(max_index + generic_base)) + || (var->data.location < 0)) { linker_error(prog, "invalid explicit location %d specified for `%s'\n", - (var->location < 0) - ? var->location : var->location - generic_base, + (var->data.location < 0) + ? var->data.location + : var->data.location - generic_base, var->name); return false; } @@ -1670,8 +1679,8 @@ assign_attribute_or_color_locations(gl_shader_program *prog, if (prog->AttributeBindings->get(binding, var->name)) { assert(binding >= VERT_ATTRIB_GENERIC0); - var->location = binding; - var->is_unmatched_generic_inout = 0; + var->data.location = binding; + var->data.is_unmatched_generic_inout = 0; } } else if (target_index == MESA_SHADER_FRAGMENT) { unsigned binding; @@ -1679,11 +1688,11 @@ assign_attribute_or_color_locations(gl_shader_program *prog, if (prog->FragDataBindings->get(binding, var->name)) { assert(binding >= FRAG_RESULT_DATA0); - var->location = binding; - var->is_unmatched_generic_inout = 0; + var->data.location = binding; + var->data.is_unmatched_generic_inout = 0; if (prog->FragDataIndexBindings->get(index, var->name)) { - var->index = index; + var->data.index = index; } } } @@ -1694,8 +1703,8 @@ assign_attribute_or_color_locations(gl_shader_program *prog, * add it to the list of variables that need linker-assigned locations. */ const unsigned slots = var->type->count_attribute_slots(); - if (var->location != -1) { - if (var->location >= generic_base && var->index < 1) { + if (var->data.location != -1) { + if (var->data.location >= generic_base && var->data.index < 1) { /* From page 61 of the OpenGL 4.0 spec: * * "LinkProgram will fail if the attribute bindings assigned @@ -1729,7 +1738,7 @@ assign_attribute_or_color_locations(gl_shader_program *prog, /* Mask representing the contiguous slots that will be used by * this attribute. */ - const unsigned attr = var->location - generic_base; + const unsigned attr = var->data.location - generic_base; const unsigned use_mask = (1 << slots) - 1; /* Generate a link error if the set of bits requested for this @@ -1795,8 +1804,8 @@ assign_attribute_or_color_locations(gl_shader_program *prog, return false; } - to_assign[i].var->location = generic_base + location; - to_assign[i].var->is_unmatched_generic_inout = 0; + to_assign[i].var->data.location = generic_base + location; + to_assign[i].var->data.is_unmatched_generic_inout = 0; used_locations |= (use_mask << location); } @@ -1813,15 +1822,15 @@ demote_shader_inputs_and_outputs(gl_shader *sh, enum ir_variable_mode mode) foreach_list(node, sh->ir) { ir_variable *const var = ((ir_instruction *) node)->as_variable(); - if ((var == NULL) || (var->mode != int(mode))) + if ((var == NULL) || (var->data.mode != int(mode))) continue; /* A shader 'in' or 'out' variable is only really an input or output if * its value is used by other shader stages. This will cause the variable * to have a location assigned. */ - if (var->is_unmatched_generic_inout) { - var->mode = ir_var_auto; + if (var->data.is_unmatched_generic_inout) { + var->data.mode = ir_var_auto; } } } @@ -1849,12 +1858,12 @@ store_fragdepth_layout(struct gl_shader_program *prog) foreach_list(node, ir) { ir_variable *const var = ((ir_instruction *) node)->as_variable(); - if (var == NULL || var->mode != ir_var_shader_out) { + if (var == NULL || var->data.mode != ir_var_shader_out) { continue; } if (strcmp(var->name, "gl_FragDepth") == 0) { - switch (var->depth_layout) { + switch (var->data.depth_layout) { case ir_depth_layout_none: prog->FragDepthLayout = FRAG_DEPTH_LAYOUT_NONE; return; diff --git a/mesalib/src/glsl/loop_analysis.cpp b/mesalib/src/glsl/loop_analysis.cpp index b08241af5..fd2b6c923 100644 --- a/mesalib/src/glsl/loop_analysis.cpp +++ b/mesalib/src/glsl/loop_analysis.cpp @@ -33,6 +33,46 @@ static bool all_expression_operands_are_loop_constant(ir_rvalue *, static ir_rvalue *get_basic_induction_increment(ir_assignment *, hash_table *); +/** + * Record the fact that the given loop variable was referenced inside the loop. + * + * \arg in_assignee is true if the reference was on the LHS of an assignment. + * + * \arg in_conditional_code_or_nested_loop is true if the reference occurred + * inside an if statement or a nested loop. + * + * \arg current_assignment is the ir_assignment node that the loop variable is + * on the LHS of, if any (ignored if \c in_assignee is false). + */ +void +loop_variable::record_reference(bool in_assignee, + bool in_conditional_code_or_nested_loop, + ir_assignment *current_assignment) +{ + if (in_assignee) { + assert(current_assignment != NULL); + + if (in_conditional_code_or_nested_loop || + current_assignment->condition != NULL) { + this->conditional_or_nested_assignment = true; + } + + if (this->first_assignment == NULL) { + assert(this->num_assignments == 0); + + this->first_assignment = current_assignment; + } + + this->num_assignments++; + } else if (this->first_assignment == current_assignment) { + /* This catches the case where the variable is used in the RHS of an + * assignment where it is also in the LHS. + */ + this->read_before_write = true; + } +} + + loop_state::loop_state() { this->ht = hash_table_ctor(0, hash_table_pointer_hash, @@ -94,7 +134,7 @@ loop_terminator * loop_variable_state::insert(ir_if *if_stmt) { void *mem_ctx = ralloc_parent(this); - loop_terminator *t = rzalloc(mem_ctx, loop_terminator); + loop_terminator *t = new(mem_ctx) loop_terminator(); t->ir = if_stmt; this->terminators.push_tail(t); @@ -102,6 +142,33 @@ loop_variable_state::insert(ir_if *if_stmt) return t; } + +/** + * If the given variable already is recorded in the state for this loop, + * return the corresponding loop_variable object that records information + * about it. + * + * Otherwise, create a new loop_variable object to record information about + * the variable, and set its \c read_before_write field appropriately based on + * \c in_assignee. + * + * \arg in_assignee is true if this variable was encountered on the LHS of an + * assignment. + */ +loop_variable * +loop_variable_state::get_or_insert(ir_variable *var, bool in_assignee) +{ + loop_variable *lv = this->get(var); + + if (lv == NULL) { + lv = this->insert(var); + lv->read_before_write = !in_assignee; + } + + return lv; +} + + namespace { class loop_analysis : public ir_hierarchical_visitor { @@ -157,14 +224,14 @@ loop_analysis::visit(ir_loop_jump *ir) ir_visitor_status loop_analysis::visit_enter(ir_call *ir) { - /* If we're not somewhere inside a loop, there's nothing to do. */ - if (this->state.is_empty()) - return visit_continue; - - loop_variable_state *const ls = - (loop_variable_state *) this->state.get_head(); + /* Mark every loop that we're currently analyzing as containing an ir_call + * (even those at outer nesting levels). + */ + foreach_list(node, &this->state) { + loop_variable_state *const ls = (loop_variable_state *) node; + ls->contains_calls = true; + } - ls->contains_calls = true; return visit_continue_with_parent; } @@ -177,35 +244,18 @@ loop_analysis::visit(ir_dereference_variable *ir) if (this->state.is_empty()) return visit_continue; - loop_variable_state *const ls = - (loop_variable_state *) this->state.get_head(); - - ir_variable *var = ir->variable_referenced(); - loop_variable *lv = ls->get(var); - - if (lv == NULL) { - lv = ls->insert(var); - lv->read_before_write = !this->in_assignee; - } - - if (this->in_assignee) { - assert(this->current_assignment != NULL); + bool nested = false; - lv->conditional_assignment = (this->if_statement_depth > 0) - || (this->current_assignment->condition != NULL); + foreach_list(node, &this->state) { + loop_variable_state *const ls = (loop_variable_state *) node; - if (lv->first_assignment == NULL) { - assert(lv->num_assignments == 0); - - lv->first_assignment = this->current_assignment; - } + ir_variable *var = ir->variable_referenced(); + loop_variable *lv = ls->get_or_insert(var, this->in_assignee); - lv->num_assignments++; - } else if (lv->first_assignment == this->current_assignment) { - /* This catches the case where the variable is used in the RHS of an - * assignment where it is also in the LHS. - */ - lv->read_before_write = true; + lv->record_reference(this->in_assignee, + nested || this->if_statement_depth > 0, + this->current_assignment); + nested = true; } return visit_continue; @@ -286,7 +336,7 @@ loop_analysis::visit_leave(ir_loop *ir) foreach_list_safe(node, &ls->variables) { loop_variable *lv = (loop_variable *) node; - if (lv->conditional_assignment || (lv->num_assignments > 1)) + if (lv->conditional_or_nested_assignment || (lv->num_assignments > 1)) continue; /* Process the RHS of the assignment. If all of the variables @@ -326,9 +376,10 @@ loop_analysis::visit_leave(ir_loop *ir) assert(lv->num_assignments == 1); assert(lv->first_assignment != NULL); - /* The assignmnet to the variable in the loop must be unconditional. + /* The assignment to the variable in the loop must be unconditional and + * not inside a nested loop. */ - if (lv->conditional_assignment) + if (lv->conditional_or_nested_assignment) continue; /* Basic loop induction variables have a single assignment in the loop @@ -338,8 +389,6 @@ loop_analysis::visit_leave(ir_loop *ir) ir_rvalue *const inc = get_basic_induction_increment(lv->first_assignment, ls->var_hash); if (inc != NULL) { - lv->iv_scale = NULL; - lv->biv = lv->var; lv->increment = inc; lv->remove(); @@ -347,6 +396,75 @@ loop_analysis::visit_leave(ir_loop *ir) } } + /* Search the loop terminating conditions for those of the form 'i < c' + * where i is a loop induction variable, c is a constant, and < is any + * relative operator. From each of these we can infer an iteration count. + * Also figure out which terminator (if any) produces the smallest + * iteration count--this is the limiting terminator. + */ + foreach_list(node, &ls->terminators) { + loop_terminator *t = (loop_terminator *) node; + ir_if *if_stmt = t->ir; + + /* If-statements can be either 'if (expr)' or 'if (deref)'. We only care + * about the former here. + */ + ir_expression *cond = if_stmt->condition->as_expression(); + if (cond == NULL) + continue; + + switch (cond->operation) { + case ir_binop_less: + case ir_binop_greater: + case ir_binop_lequal: + case ir_binop_gequal: { + /* The expressions that we care about will either be of the form + * 'counter < limit' or 'limit < counter'. Figure out which is + * which. + */ + ir_rvalue *counter = cond->operands[0]->as_dereference_variable(); + ir_constant *limit = cond->operands[1]->as_constant(); + enum ir_expression_operation cmp = cond->operation; + + if (limit == NULL) { + counter = cond->operands[1]->as_dereference_variable(); + limit = cond->operands[0]->as_constant(); + + switch (cmp) { + case ir_binop_less: cmp = ir_binop_greater; break; + case ir_binop_greater: cmp = ir_binop_less; break; + case ir_binop_lequal: cmp = ir_binop_gequal; break; + case ir_binop_gequal: cmp = ir_binop_lequal; break; + default: assert(!"Should not get here."); + } + } + + if ((counter == NULL) || (limit == NULL)) + break; + + ir_variable *var = counter->variable_referenced(); + + ir_rvalue *init = find_initial_value(ir, var); + + loop_variable *lv = ls->get(var); + if (lv != NULL && lv->is_induction_var()) { + t->iterations = calculate_iterations(init, limit, lv->increment, + cmp); + + if (t->iterations >= 0 && + (ls->limiting_terminator == NULL || + t->iterations < ls->limiting_terminator->iterations)) { + ls->limiting_terminator = t; + } + } + break; + } + + default: + break; + } + } + return visit_continue; } diff --git a/mesalib/src/glsl/loop_analysis.h b/mesalib/src/glsl/loop_analysis.h index 769d62661..f841042f0 100644 --- a/mesalib/src/glsl/loop_analysis.h +++ b/mesalib/src/glsl/loop_analysis.h @@ -39,16 +39,12 @@ analyze_loop_variables(exec_list *instructions); /** * Fill in loop control fields * - * Based on analysis of loop variables, this function tries to remove sequences - * in the loop of the form + * Based on analysis of loop variables, this function tries to remove + * redundant sequences in the loop of the form * * (if (expression bool ...) (break)) * - * and fill in the \c ir_loop::from, \c ir_loop::to, and \c ir_loop::counter - * fields of the \c ir_loop. - * - * In this process, some conditional break-statements may be eliminated - * altogether. For example, if it is provable that one loop exit condition will + * For example, if it is provable that one loop exit condition will * always be satisfied before another, the unnecessary exit condition will be * removed. */ @@ -59,6 +55,13 @@ set_loop_controls(exec_list *instructions, loop_state *ls); extern bool unroll_loops(exec_list *instructions, loop_state *ls, unsigned max_iterations); +ir_rvalue * +find_initial_value(ir_loop *loop, ir_variable *var); + +int +calculate_iterations(ir_rvalue *from, ir_rvalue *to, ir_rvalue *increment, + enum ir_expression_operation op); + /** * Tracking for all variables used in a loop @@ -67,14 +70,10 @@ class loop_variable_state : public exec_node { public: class loop_variable *get(const ir_variable *); class loop_variable *insert(ir_variable *); + class loop_variable *get_or_insert(ir_variable *, bool in_assignee); class loop_terminator *insert(ir_if *); - /** - * Loop whose variable state is being tracked by this structure - */ - ir_loop *loop; - /** * Variables that have not yet been classified */ @@ -104,18 +103,17 @@ public: exec_list terminators; /** - * Hash table containing all variables accessed in this loop + * If any of the terminators in \c terminators leads to termination of the + * loop after a constant number of iterations, this is the terminator that + * leads to termination after the smallest number of iterations. Otherwise + * NULL. */ - hash_table *var_hash; + loop_terminator *limiting_terminator; /** - * Maximum number of loop iterations. - * - * If this value is negative, then the loop may be infinite. This actually - * means that analysis was unable to determine an upper bound on the number - * of loop iterations. + * Hash table containing all variables accessed in this loop */ - int max_iterations; + hash_table *var_hash; /** * Number of ir_loop_jump instructions that operate on this loop @@ -129,11 +127,11 @@ public: loop_variable_state() { - this->max_iterations = -1; this->num_loop_jumps = 0; this->contains_calls = false; this->var_hash = hash_table_ctor(0, hash_table_pointer_hash, hash_table_pointer_compare); + this->limiting_terminator = NULL; } ~loop_variable_state() @@ -171,8 +169,11 @@ public: /** Are all variables in the RHS of the assignment loop constants? */ bool rhs_clean; - /** Is there an assignment to the variable that is conditional? */ - bool conditional_assignment; + /** + * Is there an assignment to the variable that is conditional, or inside a + * nested loop? + */ + bool conditional_or_nested_assignment; /** Reference to the first assignment to the variable in the loop body. */ ir_assignment *first_assignment; @@ -181,27 +182,30 @@ public: unsigned num_assignments; /** - * Increment values for loop induction variables + * Increment value for a loop induction variable * - * Loop induction variables have a single increment of the form - * \c b * \c biv + \c c, where \c b and \c c are loop constants and \c i - * is a basic loop induction variable. + * If this is a loop induction variable, the amount by which the variable + * is incremented on each iteration through the loop. * - * If \c iv_scale is \c NULL, 1 is used. If \c biv is the same as \c var, - * then \c var is a basic loop induction variable. + * If this is not a loop induction variable, NULL. */ - /*@{*/ - ir_rvalue *iv_scale; - ir_variable *biv; ir_rvalue *increment; - /*@}*/ + + + inline bool is_induction_var() const + { + /* Induction variables always have a non-null increment, and vice + * versa. + */ + return this->increment != NULL; + } inline bool is_loop_constant() const { const bool is_const = (this->num_assignments == 0) || ((this->num_assignments == 1) - && !this->conditional_assignment + && !this->conditional_or_nested_assignment && !this->read_before_write && this->rhs_clean); @@ -213,16 +217,35 @@ public: /* Variables that are marked read-only *MUST* be loop constant. */ - assert(!this->var->read_only || (this->var->read_only && is_const)); + assert(!this->var->data.read_only + || (this->var->data.read_only && is_const)); return is_const; } + + void record_reference(bool in_assignee, + bool in_conditional_code_or_nested_loop, + ir_assignment *current_assignment); }; class loop_terminator : public exec_node { public: + loop_terminator() + : ir(NULL), iterations(-1) + { + } + + /** + * Statement which terminates the loop. + */ ir_if *ir; + + /** + * The number of iterations after which the terminator is known to + * terminate the loop (if that is a fixed value). Otherwise -1. + */ + int iterations; }; diff --git a/mesalib/src/glsl/loop_controls.cpp b/mesalib/src/glsl/loop_controls.cpp index 26481930d..3db06ad18 100644 --- a/mesalib/src/glsl/loop_controls.cpp +++ b/mesalib/src/glsl/loop_controls.cpp @@ -183,114 +183,41 @@ loop_control_visitor::visit_leave(ir_loop *ir) return visit_continue; } - /* Search the loop terminating conditions for one of the form 'i < c' where - * i is a loop induction variable, c is a constant, and < is any relative - * operator. - */ - int max_iterations = ls->max_iterations; - - if(ir->from && ir->to && ir->increment) - max_iterations = calculate_iterations(ir->from, ir->to, ir->increment, (ir_expression_operation)ir->cmp); - - if(max_iterations < 0) - max_iterations = INT_MAX; + if (ls->limiting_terminator != NULL) { + /* If the limiting terminator has an iteration count of zero, then we've + * proven that the loop cannot run, so delete it. + */ + int iterations = ls->limiting_terminator->iterations; + if (iterations == 0) { + ir->remove(); + this->progress = true; + return visit_continue; + } + } + /* Remove the conditional break statements associated with all terminators + * that are associated with a fixed iteration count, except for the one + * associated with the limiting terminator--that one needs to stay, since + * it terminates the loop. Exception: if the loop still has a normative + * bound, then that terminates the loop, so we don't even need the limiting + * terminator. + */ foreach_list(node, &ls->terminators) { loop_terminator *t = (loop_terminator *) node; - ir_if *if_stmt = t->ir; - /* If-statements can be either 'if (expr)' or 'if (deref)'. We only care - * about the former here. - */ - ir_expression *cond = if_stmt->condition->as_expression(); - if (cond == NULL) - continue; - - switch (cond->operation) { - case ir_binop_less: - case ir_binop_greater: - case ir_binop_lequal: - case ir_binop_gequal: { - /* The expressions that we care about will either be of the form - * 'counter < limit' or 'limit < counter'. Figure out which is - * which. - */ - ir_rvalue *counter = cond->operands[0]->as_dereference_variable(); - ir_constant *limit = cond->operands[1]->as_constant(); - enum ir_expression_operation cmp = cond->operation; - - if (limit == NULL) { - counter = cond->operands[1]->as_dereference_variable(); - limit = cond->operands[0]->as_constant(); - - switch (cmp) { - case ir_binop_less: cmp = ir_binop_greater; break; - case ir_binop_greater: cmp = ir_binop_less; break; - case ir_binop_lequal: cmp = ir_binop_gequal; break; - case ir_binop_gequal: cmp = ir_binop_lequal; break; - default: assert(!"Should not get here."); - } - } - - if ((counter == NULL) || (limit == NULL)) - break; - - ir_variable *var = counter->variable_referenced(); - - ir_rvalue *init = find_initial_value(ir, var); - - foreach_list(iv_node, &ls->induction_variables) { - loop_variable *lv = (loop_variable *) iv_node; - - if (lv->var == var) { - const int iterations = calculate_iterations(init, limit, - lv->increment, - cmp); - if (iterations >= 0) { - /* If the new iteration count is lower than the previously - * believed iteration count, update the loop control values. - */ - if (iterations < max_iterations) { - ir->from = init->clone(ir, NULL); - ir->to = limit->clone(ir, NULL); - ir->increment = lv->increment->clone(ir, NULL); - ir->counter = lv->var; - ir->cmp = cmp; - - max_iterations = iterations; - } - - /* Remove the conditional break statement. The loop - * controls are now set such that the exit condition will be - * satisfied. - */ - if_stmt->remove(); - - assert(ls->num_loop_jumps > 0); - ls->num_loop_jumps--; - - this->progress = true; - } - - break; - } - } - break; - } + if (t->iterations < 0) + continue; - default: - break; + if (t != ls->limiting_terminator) { + t->ir->remove(); + + assert(ls->num_loop_jumps > 0); + ls->num_loop_jumps--; + + this->progress = true; } } - /* If we have proven the one of the loop exit conditions is satisifed before - * running the loop once, remove the loop. - */ - if (max_iterations == 0) - ir->remove(); - else - ls->max_iterations = max_iterations; - return visit_continue; } diff --git a/mesalib/src/glsl/loop_unroll.cpp b/mesalib/src/glsl/loop_unroll.cpp index ff97766f1..6eced1736 100644 --- a/mesalib/src/glsl/loop_unroll.cpp +++ b/mesalib/src/glsl/loop_unroll.cpp @@ -37,6 +37,10 @@ public: } virtual ir_visitor_status visit_leave(ir_loop *ir); + void simple_unroll(ir_loop *ir, int iterations); + void complex_unroll(ir_loop *ir, int iterations, + bool continue_from_then_branch); + void splice_post_if_instructions(ir_if *ir_if, exec_list *splice_dest); loop_state *state; @@ -86,6 +90,138 @@ public: }; +/** + * Unroll a loop which does not contain any jumps. For example, if the input + * is: + * + * (loop (...) ...instrs...) + * + * And the iteration count is 3, the output will be: + * + * ...instrs... ...instrs... ...instrs... + */ +void +loop_unroll_visitor::simple_unroll(ir_loop *ir, int iterations) +{ + void *const mem_ctx = ralloc_parent(ir); + + for (int i = 0; i < iterations; i++) { + exec_list copy_list; + + copy_list.make_empty(); + clone_ir_list(mem_ctx, ©_list, &ir->body_instructions); + + ir->insert_before(©_list); + } + + /* The loop has been replaced by the unrolled copies. Remove the original + * loop from the IR sequence. + */ + ir->remove(); + + this->progress = true; +} + + +/** + * Unroll a loop whose last statement is an ir_if. If \c + * continue_from_then_branch is true, the loop is repeated only when the + * "then" branch of the if is taken; otherwise it is repeated only when the + * "else" branch of the if is taken. + * + * For example, if the input is: + * + * (loop (...) + * ...body... + * (if (cond) + * (...then_instrs...) + * (...else_instrs...))) + * + * And the iteration count is 3, and \c continue_from_then_branch is true, + * then the output will be: + * + * ...body... + * (if (cond) + * (...then_instrs... + * ...body... + * (if (cond) + * (...then_instrs... + * ...body... + * (if (cond) + * (...then_instrs...) + * (...else_instrs...))) + * (...else_instrs...))) + * (...else_instrs)) + */ +void +loop_unroll_visitor::complex_unroll(ir_loop *ir, int iterations, + bool continue_from_then_branch) +{ + void *const mem_ctx = ralloc_parent(ir); + ir_instruction *ir_to_replace = ir; + + for (int i = 0; i < iterations; i++) { + exec_list copy_list; + + copy_list.make_empty(); + clone_ir_list(mem_ctx, ©_list, &ir->body_instructions); + + ir_if *ir_if = ((ir_instruction *) copy_list.get_tail())->as_if(); + assert(ir_if != NULL); + + ir_to_replace->insert_before(©_list); + ir_to_replace->remove(); + + /* placeholder that will be removed in the next iteration */ + ir_to_replace = + new(mem_ctx) ir_loop_jump(ir_loop_jump::jump_continue); + + exec_list *const list = (continue_from_then_branch) + ? &ir_if->then_instructions : &ir_if->else_instructions; + + list->push_tail(ir_to_replace); + } + + ir_to_replace->remove(); + + this->progress = true; +} + + +/** + * Move all of the instructions which follow \c ir_if to the end of + * \c splice_dest. + * + * For example, in the code snippet: + * + * (if (cond) + * (...then_instructions... + * break) + * (...else_instructions...)) + * ...post_if_instructions... + * + * If \c ir_if points to the "if" instruction, and \c splice_dest points to + * (...else_instructions...), the code snippet is transformed into: + * + * (if (cond) + * (...then_instructions... + * break) + * (...else_instructions... + * ...post_if_instructions...)) + */ +void +loop_unroll_visitor::splice_post_if_instructions(ir_if *ir_if, + exec_list *splice_dest) +{ + while (!ir_if->get_next()->is_tail_sentinel()) { + ir_instruction *move_ir = (ir_instruction *) ir_if->get_next(); + + move_ir->remove(); + splice_dest->push_tail(move_ir); + } +} + + ir_visitor_status loop_unroll_visitor::visit_leave(ir_loop *ir) { @@ -100,14 +236,14 @@ loop_unroll_visitor::visit_leave(ir_loop *ir) return visit_continue; } - iterations = ls->max_iterations; - /* Don't try to unroll loops where the number of iterations is not known * at compile-time. */ - if (iterations < 0) + if (ls->limiting_terminator == NULL) return visit_continue; + iterations = ls->limiting_terminator->iterations; + /* Don't try to unroll loops that have zillions of iterations either. */ if (iterations > (int) max_iterations) @@ -120,127 +256,83 @@ loop_unroll_visitor::visit_leave(ir_loop *ir) if (count.fail || count.nodes * iterations > (int)max_iterations * 5) return visit_continue; - if (ls->num_loop_jumps > 1) - return visit_continue; - else if (ls->num_loop_jumps) { - ir_instruction *last_ir = (ir_instruction *) ir->body_instructions.get_tail(); - assert(last_ir != NULL); - - if (is_break(last_ir)) { - /* If the only loop-jump is a break at the end of the loop, the loop - * will execute exactly once. Remove the break, set the iteration - * count, and fall through to the normal unroller. - */ - last_ir->remove(); - iterations = 1; - - this->progress = true; - } else { - ir_if *ir_if = NULL; - ir_instruction *break_ir = NULL; - bool continue_from_then_branch = false; - - foreach_list(node, &ir->body_instructions) { - /* recognize loops in the form produced by ir_lower_jumps */ - ir_instruction *cur_ir = (ir_instruction *) node; - - ir_if = cur_ir->as_if(); - if (ir_if != NULL) { - /* Determine which if-statement branch, if any, ends with a - * break. The branch that did *not* have the break will get a - * temporary continue inserted in each iteration of the loop - * unroll. - * - * Note that since ls->num_loop_jumps is <= 1, it is impossible - * for both branches to end with a break. - */ - ir_instruction *ir_if_last = - (ir_instruction *) ir_if->then_instructions.get_tail(); - - if (is_break(ir_if_last)) { - continue_from_then_branch = false; - break_ir = ir_if_last; - break; - } else { - ir_if_last = - (ir_instruction *) ir_if->else_instructions.get_tail(); - - if (is_break(ir_if_last)) { - break_ir = ir_if_last; - continue_from_then_branch = true; - break; - } - } - } - } - - if (break_ir == NULL) - return visit_continue; - - /* move instructions after then if in the continue branch */ - while (!ir_if->get_next()->is_tail_sentinel()) { - ir_instruction *move_ir = (ir_instruction *) ir_if->get_next(); - - move_ir->remove(); - if (continue_from_then_branch) - ir_if->then_instructions.push_tail(move_ir); - else - ir_if->else_instructions.push_tail(move_ir); - } - - /* Remove the break from the if-statement. - */ - break_ir->remove(); - - void *const mem_ctx = ralloc_parent(ir); - ir_instruction *ir_to_replace = ir; - - for (int i = 0; i < iterations; i++) { - exec_list copy_list; + /* Note: the limiting terminator contributes 1 to ls->num_loop_jumps. + * We'll be removing the limiting terminator before we unroll. + */ + assert(ls->num_loop_jumps > 0); + unsigned predicted_num_loop_jumps = ls->num_loop_jumps - 1; - copy_list.make_empty(); - clone_ir_list(mem_ctx, ©_list, &ir->body_instructions); + if (predicted_num_loop_jumps > 1) + return visit_continue; - ir_if = ((ir_instruction *) copy_list.get_tail())->as_if(); - assert(ir_if != NULL); + if (predicted_num_loop_jumps == 0) { + ls->limiting_terminator->ir->remove(); + simple_unroll(ir, iterations); + return visit_continue; + } - ir_to_replace->insert_before(©_list); - ir_to_replace->remove(); + ir_instruction *last_ir = (ir_instruction *) ir->body_instructions.get_tail(); + assert(last_ir != NULL); - /* placeholder that will be removed in the next iteration */ - ir_to_replace = - new(mem_ctx) ir_loop_jump(ir_loop_jump::jump_continue); + if (is_break(last_ir)) { + /* If the only loop-jump is a break at the end of the loop, the loop + * will execute exactly once. Remove the break and use the simple + * unroller with an iteration count of 1. + */ + last_ir->remove(); - exec_list *const list = (continue_from_then_branch) - ? &ir_if->then_instructions : &ir_if->else_instructions; + ls->limiting_terminator->ir->remove(); + simple_unroll(ir, 1); + return visit_continue; + } - list->push_tail(ir_to_replace); + foreach_list(node, &ir->body_instructions) { + /* recognize loops in the form produced by ir_lower_jumps */ + ir_instruction *cur_ir = (ir_instruction *) node; + + /* Skip the limiting terminator, since it will go away when we + * unroll. + */ + if (cur_ir == ls->limiting_terminator->ir) + continue; + + ir_if *ir_if = cur_ir->as_if(); + if (ir_if != NULL) { + /* Determine which if-statement branch, if any, ends with a + * break. The branch that did *not* have the break will get a + * temporary continue inserted in each iteration of the loop + * unroll. + * + * Note that since ls->num_loop_jumps is <= 1, it is impossible + * for both branches to end with a break. + */ + ir_instruction *ir_if_last = + (ir_instruction *) ir_if->then_instructions.get_tail(); + + if (is_break(ir_if_last)) { + ls->limiting_terminator->ir->remove(); + splice_post_if_instructions(ir_if, &ir_if->else_instructions); + ir_if_last->remove(); + complex_unroll(ir, iterations, false); + return visit_continue; + } else { + ir_if_last = + (ir_instruction *) ir_if->else_instructions.get_tail(); + + if (is_break(ir_if_last)) { + ls->limiting_terminator->ir->remove(); + splice_post_if_instructions(ir_if, &ir_if->then_instructions); + ir_if_last->remove(); + complex_unroll(ir, iterations, true); + return visit_continue; + } } - - ir_to_replace->remove(); - - this->progress = true; - return visit_continue; } } - void *const mem_ctx = ralloc_parent(ir); - - for (int i = 0; i < iterations; i++) { - exec_list copy_list; - - copy_list.make_empty(); - clone_ir_list(mem_ctx, ©_list, &ir->body_instructions); - - ir->insert_before(©_list); - } - - /* The loop has been replaced by the unrolled copies. Remove the original - * loop from the IR sequence. + /* Did not find the break statement. It must be in a complex if-nesting, + * so don't try to unroll. */ - ir->remove(); - - this->progress = true; return visit_continue; } diff --git a/mesalib/src/glsl/lower_clip_distance.cpp b/mesalib/src/glsl/lower_clip_distance.cpp index 04fa6d410..bb4f6ab11 100644 --- a/mesalib/src/glsl/lower_clip_distance.cpp +++ b/mesalib/src/glsl/lower_clip_distance.cpp @@ -135,13 +135,13 @@ lower_clip_distance_visitor::visit(ir_variable *ir) "gl_ClipDistanceMESA"); this->new_clip_distance_1d_var->type = glsl_type::get_array_instance(glsl_type::vec4_type, new_size); - this->new_clip_distance_1d_var->max_array_access - = ir->max_array_access / 4; + this->new_clip_distance_1d_var->data.max_array_access + = ir->data.max_array_access / 4; ir->replace_with(this->new_clip_distance_1d_var); } else { /* 2D gl_ClipDistance (used for geometry input). */ - assert(ir->mode == ir_var_shader_in && + assert(ir->data.mode == ir_var_shader_in && this->shader_type == GL_GEOMETRY_SHADER_ARB); if (this->old_clip_distance_2d_var) return visit_continue; @@ -161,8 +161,8 @@ lower_clip_distance_visitor::visit(ir_variable *ir) glsl_type::get_array_instance(glsl_type::vec4_type, new_size), ir->type->array_size()); - this->new_clip_distance_2d_var->max_array_access - = ir->max_array_access / 4; + this->new_clip_distance_2d_var->data.max_array_access + = ir->data.max_array_access / 4; ir->replace_with(this->new_clip_distance_2d_var); } @@ -500,8 +500,8 @@ lower_clip_distance_visitor::visit_leave(ir_call *ir) this->base_ir->insert_before(temp_clip_distance); actual_param->replace_with( new(ctx) ir_dereference_variable(temp_clip_distance)); - if (formal_param->mode == ir_var_function_in - || formal_param->mode == ir_var_function_inout) { + if (formal_param->data.mode == ir_var_function_in + || formal_param->data.mode == ir_var_function_inout) { /* Copy from gl_ClipDistance to the temporary before the call. * Since we are going to insert this copy before the current * instruction, we need to visit it afterwards to make sure it @@ -513,8 +513,8 @@ lower_clip_distance_visitor::visit_leave(ir_call *ir) this->base_ir->insert_before(new_assignment); this->visit_new_assignment(new_assignment); } - if (formal_param->mode == ir_var_function_out - || formal_param->mode == ir_var_function_inout) { + if (formal_param->data.mode == ir_var_function_out + || formal_param->data.mode == ir_var_function_inout) { /* Copy from the temporary to gl_ClipDistance after the call. * Since visit_list_elements() has already decided which * instruction it's going to visit next, we need to visit diff --git a/mesalib/src/glsl/lower_instructions.cpp b/mesalib/src/glsl/lower_instructions.cpp index d01879cbd..8f8d448ea 100644 --- a/mesalib/src/glsl/lower_instructions.cpp +++ b/mesalib/src/glsl/lower_instructions.cpp @@ -383,7 +383,6 @@ lower_instructions_visitor::ldexp_to_arith(ir_expression *ir) /* Constants */ ir_constant *zeroi = ir_constant::zero(ir, ivec); - ir_constant *zerof = ir_constant::zero(ir, ir->type); ir_constant *sign_mantissa_mask = new(ir) ir_constant(0x807fffffu, vec_elem); ir_constant *sign_mask = new(ir) ir_constant(0x80000000u, vec_elem); @@ -429,8 +428,7 @@ lower_instructions_visitor::ldexp_to_arith(ir_expression *ir) */ i.insert_before(zero_sign_x); i.insert_before(assign(zero_sign_x, - bitcast_u2f(bit_or(bit_and(bitcast_f2u(x), sign_mask), - bitcast_f2u(zerof))))); + bitcast_u2f(bit_and(bitcast_f2u(x), sign_mask)))); i.insert_before(is_not_zero_or_underflow); i.insert_before(assign(is_not_zero_or_underflow, diff --git a/mesalib/src/glsl/lower_named_interface_blocks.cpp b/mesalib/src/glsl/lower_named_interface_blocks.cpp index d59d11150..09d867ea3 100644 --- a/mesalib/src/glsl/lower_named_interface_blocks.cpp +++ b/mesalib/src/glsl/lower_named_interface_blocks.cpp @@ -108,7 +108,7 @@ flatten_named_interface_blocks_declarations::run(exec_list *instructions) * but, this will require changes to the other uniform block * support code. */ - if (var->mode == ir_var_uniform) + if (var->data.mode == ir_var_uniform) continue; const glsl_type * iface_t = var->type; @@ -139,8 +139,8 @@ flatten_named_interface_blocks_declarations::run(exec_list *instructions) new_var = new(mem_ctx) ir_variable(iface_t->fields.structure[i].type, var_name, - (ir_variable_mode) var->mode); - new_var->from_named_ifc_block_nonarray = 1; + (ir_variable_mode) var->data.mode); + new_var->data.from_named_ifc_block_nonarray = 1; } else { const glsl_type *new_array_type = glsl_type::get_array_instance( @@ -149,14 +149,15 @@ flatten_named_interface_blocks_declarations::run(exec_list *instructions) new_var = new(mem_ctx) ir_variable(new_array_type, var_name, - (ir_variable_mode) var->mode); - new_var->from_named_ifc_block_array = 1; + (ir_variable_mode) var->data.mode); + new_var->data.from_named_ifc_block_array = 1; } - new_var->location = iface_t->fields.structure[i].location; - new_var->explicit_location = (new_var->location >= 0); - new_var->interpolation = + new_var->data.location = iface_t->fields.structure[i].location; + new_var->data.explicit_location = (new_var->data.location >= 0); + new_var->data.interpolation = iface_t->fields.structure[i].interpolation; - new_var->centroid = iface_t->fields.structure[i].centroid; + new_var->data.centroid = iface_t->fields.structure[i].centroid; + new_var->data.sample = iface_t->fields.structure[i].sample; new_var->init_interface_type(iface_t); hash_table_insert(interface_namespace, new_var, @@ -211,7 +212,7 @@ flatten_named_interface_blocks_declarations::handle_rvalue(ir_rvalue **rvalue) * but, this will require changes to the other uniform block * support code. */ - if (var->mode == ir_var_uniform) + if (var->data.mode == ir_var_uniform) return; if (var->get_interface_type() != NULL) { diff --git a/mesalib/src/glsl/lower_output_reads.cpp b/mesalib/src/glsl/lower_output_reads.cpp index 128b0b8cd..afe17766b 100644 --- a/mesalib/src/glsl/lower_output_reads.cpp +++ b/mesalib/src/glsl/lower_output_reads.cpp @@ -91,7 +91,7 @@ output_read_remover::~output_read_remover() ir_visitor_status output_read_remover::visit(ir_dereference_variable *ir) { - if (ir->var->mode != ir_var_shader_out) + if (ir->var->data.mode != ir_var_shader_out) return visit_continue; ir_variable *temp = (ir_variable *) hash_table_find(replacements, ir->var); diff --git a/mesalib/src/glsl/lower_packed_varyings.cpp b/mesalib/src/glsl/lower_packed_varyings.cpp index 61ee692f6..9edef5d04 100644 --- a/mesalib/src/glsl/lower_packed_varyings.cpp +++ b/mesalib/src/glsl/lower_packed_varyings.cpp @@ -258,8 +258,8 @@ lower_packed_varyings_visitor::run(exec_list *instructions) if (var == NULL) continue; - if (var->mode != this->mode || - var->location < (int) this->location_base || + if (var->data.mode != this->mode || + var->data.location < (int) this->location_base || !this->needs_lowering(var)) continue; @@ -268,18 +268,18 @@ lower_packed_varyings_visitor::run(exec_list *instructions) * safe, caller should ensure that integral varyings always use flat * interpolation, even when this is not required by GLSL. */ - assert(var->interpolation == INTERP_QUALIFIER_FLAT || + assert(var->data.interpolation == INTERP_QUALIFIER_FLAT || !var->type->contains_integer()); /* Change the old varying into an ordinary global. */ - var->mode = ir_var_auto; + var->data.mode = ir_var_auto; /* Create a reference to the old varying. */ ir_dereference_variable *deref = new(this->mem_ctx) ir_dereference_variable(var); /* Recursively pack or unpack it. */ - this->lower_rvalue(deref, var->location * 4 + var->location_frac, var, + this->lower_rvalue(deref, var->data.location * 4 + var->data.location_frac, var, var->name, this->gs_input_vertices != 0, 0); } } @@ -547,7 +547,7 @@ lower_packed_varyings_visitor::get_packed_varying_deref( if (this->packed_varyings[slot] == NULL) { char *packed_name = ralloc_asprintf(this->mem_ctx, "packed:%s", name); const glsl_type *packed_type; - if (unpacked_var->interpolation == INTERP_QUALIFIER_FLAT) + if (unpacked_var->data.interpolation == INTERP_QUALIFIER_FLAT) packed_type = glsl_type::ivec4_type; else packed_type = glsl_type::vec4_type; @@ -562,11 +562,12 @@ lower_packed_varyings_visitor::get_packed_varying_deref( /* Prevent update_array_sizes() from messing with the size of the * array. */ - packed_var->max_array_access = this->gs_input_vertices - 1; + packed_var->data.max_array_access = this->gs_input_vertices - 1; } - packed_var->centroid = unpacked_var->centroid; - packed_var->interpolation = unpacked_var->interpolation; - packed_var->location = location; + packed_var->data.centroid = unpacked_var->data.centroid; + packed_var->data.sample = unpacked_var->data.sample; + packed_var->data.interpolation = unpacked_var->data.interpolation; + packed_var->data.location = location; unpacked_var->insert_before(packed_var); this->packed_varyings[slot] = packed_var; } else { diff --git a/mesalib/src/glsl/lower_ubo_reference.cpp b/mesalib/src/glsl/lower_ubo_reference.cpp index 16b6801b8..c73b148b0 100644 --- a/mesalib/src/glsl/lower_ubo_reference.cpp +++ b/mesalib/src/glsl/lower_ubo_reference.cpp @@ -143,7 +143,7 @@ lower_ubo_reference_visitor::handle_rvalue(ir_rvalue **rvalue) struct gl_uniform_block *block = &shader->UniformBlocks[i]; this->ubo_var = var->is_interface_instance() - ? &block->Uniforms[0] : &block->Uniforms[var->location]; + ? &block->Uniforms[0] : &block->Uniforms[var->data.location]; break; } diff --git a/mesalib/src/glsl/lower_variable_index_to_cond_assign.cpp b/mesalib/src/glsl/lower_variable_index_to_cond_assign.cpp index 699fb3903..7c5d80f43 100644 --- a/mesalib/src/glsl/lower_variable_index_to_cond_assign.cpp +++ b/mesalib/src/glsl/lower_variable_index_to_cond_assign.cpp @@ -365,7 +365,7 @@ public: if (var == NULL) return this->lower_temps; - switch (var->mode) { + switch (var->data.mode) { case ir_var_auto: case ir_var_temporary: return this->lower_temps; diff --git a/mesalib/src/glsl/opt_array_splitting.cpp b/mesalib/src/glsl/opt_array_splitting.cpp index c7c5f6712..e946e0ae5 100644 --- a/mesalib/src/glsl/opt_array_splitting.cpp +++ b/mesalib/src/glsl/opt_array_splitting.cpp @@ -122,8 +122,8 @@ ir_array_reference_visitor::get_variable_entry(ir_variable *var) { assert(var); - if (var->mode != ir_var_auto && - var->mode != ir_var_temporary) + if (var->data.mode != ir_var_auto && + var->data.mode != ir_var_temporary) return NULL; if (!(var->type->is_array() || var->type->is_matrix())) diff --git a/mesalib/src/glsl/opt_constant_folding.cpp b/mesalib/src/glsl/opt_constant_folding.cpp index 072fefe9a..08a47b96b 100644 --- a/mesalib/src/glsl/opt_constant_folding.cpp +++ b/mesalib/src/glsl/opt_constant_folding.cpp @@ -127,8 +127,8 @@ ir_constant_folding_visitor::visit_enter(ir_call *ir) ir_rvalue *param_rval = (ir_rvalue *)iter.get(); ir_variable *sig_param = (ir_variable *)sig_iter.get(); - if (sig_param->mode == ir_var_function_in - || sig_param->mode == ir_var_const_in) { + if (sig_param->data.mode == ir_var_function_in + || sig_param->data.mode == ir_var_const_in) { ir_rvalue *new_param = param_rval; handle_rvalue(&new_param); diff --git a/mesalib/src/glsl/opt_constant_propagation.cpp b/mesalib/src/glsl/opt_constant_propagation.cpp index 2f65937fe..f1a6fbdaa 100644 --- a/mesalib/src/glsl/opt_constant_propagation.cpp +++ b/mesalib/src/glsl/opt_constant_propagation.cpp @@ -285,8 +285,8 @@ ir_constant_propagation_visitor::visit_enter(ir_call *ir) foreach_iter(exec_list_iterator, iter, ir->actual_parameters) { ir_variable *sig_param = (ir_variable *)sig_param_iter.get(); ir_rvalue *param = (ir_rvalue *)iter.get(); - if (sig_param->mode != ir_var_function_out - && sig_param->mode != ir_var_function_inout) { + if (sig_param->data.mode != ir_var_function_out + && sig_param->data.mode != ir_var_function_inout) { ir_rvalue *new_param = param; handle_rvalue(&new_param); if (new_param != param) diff --git a/mesalib/src/glsl/opt_constant_variable.cpp b/mesalib/src/glsl/opt_constant_variable.cpp index cbe6450c6..a026c51c3 100644 --- a/mesalib/src/glsl/opt_constant_variable.cpp +++ b/mesalib/src/glsl/opt_constant_variable.cpp @@ -137,8 +137,8 @@ ir_constant_variable_visitor::visit_enter(ir_call *ir) ir_rvalue *param_rval = (ir_rvalue *)iter.get(); ir_variable *param = (ir_variable *)sig_iter.get(); - if (param->mode == ir_var_function_out || - param->mode == ir_var_function_inout) { + if (param->data.mode == ir_var_function_out || + param->data.mode == ir_var_function_inout) { ir_variable *var = param_rval->variable_referenced(); struct assignment_entry *entry; diff --git a/mesalib/src/glsl/opt_copy_propagation.cpp b/mesalib/src/glsl/opt_copy_propagation.cpp index 7282b611e..db5dfc153 100644 --- a/mesalib/src/glsl/opt_copy_propagation.cpp +++ b/mesalib/src/glsl/opt_copy_propagation.cpp @@ -189,8 +189,8 @@ ir_copy_propagation_visitor::visit_enter(ir_call *ir) foreach_iter(exec_list_iterator, iter, ir->actual_parameters) { ir_variable *sig_param = (ir_variable *)sig_param_iter.get(); ir_instruction *ir = (ir_instruction *)iter.get(); - if (sig_param->mode != ir_var_function_out - && sig_param->mode != ir_var_function_inout) { + if (sig_param->data.mode != ir_var_function_out + && sig_param->data.mode != ir_var_function_inout) { ir->accept(this); } sig_param_iter.next(); diff --git a/mesalib/src/glsl/opt_copy_propagation_elements.cpp b/mesalib/src/glsl/opt_copy_propagation_elements.cpp index 6a19da40d..ba8a0f532 100644 --- a/mesalib/src/glsl/opt_copy_propagation_elements.cpp +++ b/mesalib/src/glsl/opt_copy_propagation_elements.cpp @@ -297,8 +297,8 @@ ir_copy_propagation_elements_visitor::visit_enter(ir_call *ir) foreach_iter(exec_list_iterator, iter, ir->actual_parameters) { ir_variable *sig_param = (ir_variable *)sig_param_iter.get(); ir_instruction *ir = (ir_instruction *)iter.get(); - if (sig_param->mode != ir_var_function_out - && sig_param->mode != ir_var_function_inout) { + if (sig_param->data.mode != ir_var_function_out + && sig_param->data.mode != ir_var_function_inout) { ir->accept(this); } sig_param_iter.next(); diff --git a/mesalib/src/glsl/opt_cse.cpp b/mesalib/src/glsl/opt_cse.cpp index 8f73940d8..a2b63ee99 100644 --- a/mesalib/src/glsl/opt_cse.cpp +++ b/mesalib/src/glsl/opt_cse.cpp @@ -193,7 +193,7 @@ is_cse_candidate_visitor::visit(ir_dereference_variable *ir) /* Currently, since we don't handle kills of the ae based on variables * getting assigned, we can only handle constant variables. */ - if (ir->var->read_only) { + if (ir->var->data.read_only) { return visit_continue; } else { ok = false; diff --git a/mesalib/src/glsl/opt_dead_builtin_varyings.cpp b/mesalib/src/glsl/opt_dead_builtin_varyings.cpp index b336bc0a8..a939a2b64 100644 --- a/mesalib/src/glsl/opt_dead_builtin_varyings.cpp +++ b/mesalib/src/glsl/opt_dead_builtin_varyings.cpp @@ -85,10 +85,10 @@ public: { ir_variable *var = ir->variable_referenced(); - if (!var || var->mode != this->mode) + if (!var || var->data.mode != this->mode) return visit_continue; - if (this->find_frag_outputs && var->location == FRAG_RESULT_DATA0) { + if (this->find_frag_outputs && var->data.location == FRAG_RESULT_DATA0) { this->fragdata_array = var; ir_constant *index = ir->array_index->as_constant(); @@ -105,7 +105,7 @@ public: return visit_continue_with_parent; } - if (!this->find_frag_outputs && var->location == VARYING_SLOT_TEX0) { + if (!this->find_frag_outputs && var->data.location == VARYING_SLOT_TEX0) { this->texcoord_array = var; ir_constant *index = ir->array_index->as_constant(); @@ -130,17 +130,17 @@ public: { ir_variable *var = ir->variable_referenced(); - if (var->mode != this->mode || !var->type->is_array()) + if (var->data.mode != this->mode || !var->type->is_array()) return visit_continue; - if (this->find_frag_outputs && var->location == FRAG_RESULT_DATA0) { + if (this->find_frag_outputs && var->data.location == FRAG_RESULT_DATA0) { /* This is a whole array dereference. */ this->fragdata_usage |= (1 << var->type->array_size()) - 1; this->lower_fragdata_array = false; return visit_continue; } - if (!this->find_frag_outputs && var->location == VARYING_SLOT_TEX0) { + if (!this->find_frag_outputs && var->data.location == VARYING_SLOT_TEX0) { /* This is a whole array dereference like "gl_TexCoord = x;", * there's probably no point in lowering that. */ @@ -152,7 +152,7 @@ public: virtual ir_visitor_status visit(ir_variable *var) { - if (var->mode != this->mode) + if (var->data.mode != this->mode) return visit_continue; /* Nothing to do here for fragment outputs. */ @@ -160,7 +160,7 @@ public: return visit_continue; /* Handle colors and fog. */ - switch (var->location) { + switch (var->data.location) { case VARYING_SLOT_COL0: this->color[0] = var; this->color_usage |= 1; @@ -358,9 +358,9 @@ public: new_var[i] = new(ctx) ir_variable(glsl_type::vec4_type, name, this->info->mode); - new_var[i]->location = start_location + i; - new_var[i]->explicit_location = true; - new_var[i]->explicit_index = 0; + new_var[i]->data.location = start_location + i; + new_var[i]->data.explicit_location = true; + new_var[i]->data.explicit_index = 0; } ir->head->insert_before(new_var[i]); diff --git a/mesalib/src/glsl/opt_dead_code.cpp b/mesalib/src/glsl/opt_dead_code.cpp index b65e5c2ce..a8d8b4a39 100644 --- a/mesalib/src/glsl/opt_dead_code.cpp +++ b/mesalib/src/glsl/opt_dead_code.cpp @@ -79,9 +79,9 @@ do_dead_code(exec_list *instructions, bool uniform_locations_assigned) /* Remove a single dead assignment to the variable we found. * Don't do so if it's a shader or function output, though. */ - if (entry->var->mode != ir_var_function_out && - entry->var->mode != ir_var_function_inout && - entry->var->mode != ir_var_shader_out) { + if (entry->var->data.mode != ir_var_function_out && + entry->var->data.mode != ir_var_function_inout && + entry->var->data.mode != ir_var_shader_out) { entry->assign->remove(); progress = true; @@ -99,7 +99,7 @@ do_dead_code(exec_list *instructions, bool uniform_locations_assigned) * stage. Also, once uniform locations have been assigned, the * declaration cannot be deleted. */ - if (entry->var->mode == ir_var_uniform && + if (entry->var->data.mode == ir_var_uniform && (uniform_locations_assigned || entry->var->constant_value)) continue; diff --git a/mesalib/src/glsl/opt_dead_code_local.cpp b/mesalib/src/glsl/opt_dead_code_local.cpp index 42a30b3d8..43a01662a 100644 --- a/mesalib/src/glsl/opt_dead_code_local.cpp +++ b/mesalib/src/glsl/opt_dead_code_local.cpp @@ -121,7 +121,7 @@ public: */ foreach_iter(exec_list_iterator, iter, *this->assignments) { assignment_entry *entry = (assignment_entry *)iter.get(); - if (entry->lhs->mode == ir_var_shader_out) { + if (entry->lhs->data.mode == ir_var_shader_out) { if (debug) printf("kill %s\n", entry->lhs->name); entry->remove(); diff --git a/mesalib/src/glsl/opt_flip_matrices.cpp b/mesalib/src/glsl/opt_flip_matrices.cpp index 2107b1d47..9044fd680 100644 --- a/mesalib/src/glsl/opt_flip_matrices.cpp +++ b/mesalib/src/glsl/opt_flip_matrices.cpp @@ -104,8 +104,8 @@ matrix_flipper::visit_enter(ir_expression *ir) var_ref->var = texmat_transpose; - texmat_transpose->max_array_access = - MAX2(texmat_transpose->max_array_access, mat_var->max_array_access); + texmat_transpose->data.max_array_access = + MAX2(texmat_transpose->data.max_array_access, mat_var->data.max_array_access); progress = true; } diff --git a/mesalib/src/glsl/opt_function_inlining.cpp b/mesalib/src/glsl/opt_function_inlining.cpp index f8033a095..c8f42a424 100644 --- a/mesalib/src/glsl/opt_function_inlining.cpp +++ b/mesalib/src/glsl/opt_function_inlining.cpp @@ -132,21 +132,21 @@ ir_call::generate_inline(ir_instruction *next_ir) parameters[i] = NULL; } else { parameters[i] = sig_param->clone(ctx, ht); - parameters[i]->mode = ir_var_auto; + parameters[i]->data.mode = ir_var_auto; /* Remove the read-only decoration becuase we're going to write * directly to this variable. If the cloned variable is left * read-only and the inlined function is inside a loop, the loop * analysis code will get confused. */ - parameters[i]->read_only = false; + parameters[i]->data.read_only = false; next_ir->insert_before(parameters[i]); } /* Move the actual param into our param variable if it's an 'in' type. */ - if (parameters[i] && (sig_param->mode == ir_var_function_in || - sig_param->mode == ir_var_const_in || - sig_param->mode == ir_var_function_inout)) { + if (parameters[i] && (sig_param->data.mode == ir_var_function_in || + sig_param->data.mode == ir_var_const_in || + sig_param->data.mode == ir_var_function_inout)) { ir_assignment *assign; assign = new(ctx) ir_assignment(new(ctx) ir_dereference_variable(parameters[i]), @@ -202,8 +202,8 @@ ir_call::generate_inline(ir_instruction *next_ir) const ir_variable *const sig_param = (ir_variable *) sig_param_iter.get(); /* Move our param variable into the actual param if it's an 'out' type. */ - if (parameters[i] && (sig_param->mode == ir_var_function_out || - sig_param->mode == ir_var_function_inout)) { + if (parameters[i] && (sig_param->data.mode == ir_var_function_out || + sig_param->data.mode == ir_var_function_inout)) { ir_assignment *assign; assign = new(ctx) ir_assignment(param->clone(ctx, NULL)->as_rvalue(), diff --git a/mesalib/src/glsl/opt_structure_splitting.cpp b/mesalib/src/glsl/opt_structure_splitting.cpp index 9f4b3dd8f..414f0000d 100644 --- a/mesalib/src/glsl/opt_structure_splitting.cpp +++ b/mesalib/src/glsl/opt_structure_splitting.cpp @@ -103,8 +103,8 @@ ir_structure_reference_visitor::get_variable_entry(ir_variable *var) { assert(var); - if (!var->type->is_record() || var->mode == ir_var_uniform - || var->mode == ir_var_shader_in || var->mode == ir_var_shader_out) + if (!var->type->is_record() || var->data.mode == ir_var_uniform + || var->data.mode == ir_var_shader_in || var->data.mode == ir_var_shader_out) return NULL; foreach_iter(exec_list_iterator, iter, this->variable_list) { diff --git a/mesalib/src/glsl/opt_tree_grafting.cpp b/mesalib/src/glsl/opt_tree_grafting.cpp index 46c06e6c4..6d75a1573 100644 --- a/mesalib/src/glsl/opt_tree_grafting.cpp +++ b/mesalib/src/glsl/opt_tree_grafting.cpp @@ -211,8 +211,8 @@ ir_tree_grafting_visitor::visit_enter(ir_call *ir) ir_rvalue *ir = (ir_rvalue *)iter.get(); ir_rvalue *new_ir = ir; - if (sig_param->mode != ir_var_function_in - && sig_param->mode != ir_var_const_in) { + if (sig_param->data.mode != ir_var_function_in + && sig_param->data.mode != ir_var_const_in) { if (check_graft(ir, sig_param) == visit_stop) return visit_stop; continue; @@ -361,9 +361,9 @@ tree_grafting_basic_block(ir_instruction *bb_first, if (!lhs_var) continue; - if (lhs_var->mode == ir_var_function_out || - lhs_var->mode == ir_var_function_inout || - lhs_var->mode == ir_var_shader_out) + if (lhs_var->data.mode == ir_var_function_out || + lhs_var->data.mode == ir_var_function_inout || + lhs_var->data.mode == ir_var_shader_out) continue; ir_variable_refcount_entry *entry = info->refs->get_variable_entry(lhs_var); diff --git a/mesalib/src/glsl/standalone_scaffolding.h b/mesalib/src/glsl/standalone_scaffolding.h index 7afb1c313..9f4818a8a 100644 --- a/mesalib/src/glsl/standalone_scaffolding.h +++ b/mesalib/src/glsl/standalone_scaffolding.h @@ -60,7 +60,7 @@ _mesa_shader_type_to_index(GLenum v) return MESA_SHADER_GEOMETRY; default: assert(!"bad value in _mesa_shader_type_to_index()"); - return MESA_SHADER_TYPES; + return MESA_SHADER_VERTEX; } } diff --git a/mesalib/src/mapi/glapi/gen/ARB_clear_buffer_object.xml b/mesalib/src/mapi/glapi/gen/ARB_clear_buffer_object.xml new file mode 100644 index 000000000..cb97a0185 --- /dev/null +++ b/mesalib/src/mapi/glapi/gen/ARB_clear_buffer_object.xml @@ -0,0 +1,50 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/mesalib/src/mapi/glapi/gen/ARB_texture_view.xml b/mesalib/src/mapi/glapi/gen/ARB_texture_view.xml new file mode 100644 index 000000000..3e6b8c904 --- /dev/null +++ b/mesalib/src/mapi/glapi/gen/ARB_texture_view.xml @@ -0,0 +1,23 @@ + + + + + + + + + + + + + + + + + + + + + + + diff --git a/mesalib/src/mapi/glapi/gen/Makefile.am b/mesalib/src/mapi/glapi/gen/Makefile.am index 7af769acf..65bd9137c 100644 --- a/mesalib/src/mapi/glapi/gen/Makefile.am +++ b/mesalib/src/mapi/glapi/gen/Makefile.am @@ -125,6 +125,7 @@ API_XML = \ ARB_texture_rg.xml \ ARB_texture_storage_multisample.xml \ ARB_texture_storage.xml \ + ARB_texture_view.xml \ ARB_vertex_array_object.xml \ ARB_vertex_attrib_binding.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 5c877aa3f..697b2ecce 100644 --- a/mesalib/src/mapi/glapi/gen/gl_API.xml +++ b/mesalib/src/mapi/glapi/gen/gl_API.xml @@ -8460,7 +8460,13 @@ - + + + + + + + diff --git a/mesalib/src/mapi/glapi/gen/gl_genexec.py b/mesalib/src/mapi/glapi/gen/gl_genexec.py index 3ce190fe3..b557b3b99 100644 --- a/mesalib/src/mapi/glapi/gen/gl_genexec.py +++ b/mesalib/src/mapi/glapi/gen/gl_genexec.py @@ -102,6 +102,7 @@ header = """/** #include "main/texstate.h" #include "main/texstorage.h" #include "main/texturebarrier.h" +#include "main/textureview.h" #include "main/transformfeedback.h" #include "main/mtypes.h" #include "main/varray.h" diff --git a/mesalib/src/mapi/glapi/gen/gl_gentable.py b/mesalib/src/mapi/glapi/gen/gl_gentable.py index fa9626825..35dddc7a0 100644 --- a/mesalib/src/mapi/glapi/gen/gl_gentable.py +++ b/mesalib/src/mapi/glapi/gen/gl_gentable.py @@ -50,7 +50,9 @@ header = """/* GLXEXT is the define used in the xserver when the GLX extension i #include #endif +#ifndef _WIN32 #include +#endif #include #include diff --git a/mesalib/src/mesa/Makefile.am b/mesalib/src/mesa/Makefile.am index a60600e03..884383652 100644 --- a/mesalib/src/mesa/Makefile.am +++ b/mesalib/src/mesa/Makefile.am @@ -103,7 +103,11 @@ noinst_PROGRAMS = gen_matypes gen_matypes_SOURCES = x86/gen_matypes.c BUILT_SOURCES += matypes.h -ARCH_LIBS = libmesa_sse41.la +ARCH_LIBS = + +if SSE41_SUPPORTED +ARCH_LIBS += libmesa_sse41.la +endif if HAVE_X86_64_ASM MESA_ASM_FILES_FOR_ARCH += $(X86_64_FILES) diff --git a/mesalib/src/mesa/Makefile.sources b/mesalib/src/mesa/Makefile.sources index a84f8a788..39525bc5b 100644 --- a/mesalib/src/mesa/Makefile.sources +++ b/mesalib/src/mesa/Makefile.sources @@ -103,6 +103,7 @@ MAIN_FILES = \ $(SRCDIR)main/texstate.c \ $(SRCDIR)main/texstorage.c \ $(SRCDIR)main/texstore.c \ + $(SRCDIR)main/textureview.c \ $(SRCDIR)main/texturebarrier.c \ $(SRCDIR)main/transformfeedback.c \ $(SRCDIR)main/uniforms.c \ diff --git a/mesalib/src/mesa/SConscript b/mesalib/src/mesa/SConscript index a2bb9f131..bb9b304ef 100644 --- a/mesalib/src/mesa/SConscript +++ b/mesalib/src/mesa/SConscript @@ -133,6 +133,7 @@ main_sources = [ 'main/texstorage.c', 'main/texstore.c', 'main/texturebarrier.c', + 'main/textureview.c', 'main/transformfeedback.c', 'main/uniform_query.cpp', 'main/uniforms.c', diff --git a/mesalib/src/mesa/drivers/common/driverfuncs.c b/mesalib/src/mesa/drivers/common/driverfuncs.c index 5faa98af1..f18568827 100644 --- a/mesalib/src/mesa/drivers/common/driverfuncs.c +++ b/mesalib/src/mesa/drivers/common/driverfuncs.c @@ -211,6 +211,9 @@ _mesa_init_driver_functions(struct dd_function_table *driver) /* GL_ARB_texture_storage */ driver->AllocTextureStorage = _mesa_alloc_texture_storage; + /* GL_ARB_texture_view */ + driver->TextureView = NULL; + /* GL_ARB_texture_multisample */ driver->GetSamplePosition = NULL; } diff --git a/mesalib/src/mesa/drivers/dri/common/dri_util.c b/mesalib/src/mesa/drivers/dri/common/dri_util.c index 0bce77ea9..d64821112 100644 --- a/mesalib/src/mesa/drivers/dri/common/dri_util.c +++ b/mesalib/src/mesa/drivers/dri/common/dri_util.c @@ -438,16 +438,19 @@ driCreateContextAttribs(__DRIscreen *screen, int api, return NULL; } - struct gl_context *ctx = context->driverPrivate; + *error = __DRI_CTX_ERROR_SUCCESS; + return context; +} + +void +driContextSetFlags(struct gl_context *ctx, uint32_t flags) +{ if ((flags & __DRI_CTX_FLAG_FORWARD_COMPATIBLE) != 0) ctx->Const.ContextFlags |= GL_CONTEXT_FLAG_FORWARD_COMPATIBLE_BIT; if ((flags & __DRI_CTX_FLAG_DEBUG) != 0) { ctx->Const.ContextFlags |= GL_CONTEXT_FLAG_DEBUG_BIT; ctx->Debug.DebugOutput = GL_TRUE; } - - *error = __DRI_CTX_ERROR_SUCCESS; - return context; } static __DRIcontext * @@ -873,3 +876,18 @@ const __DRIimageDriverExtension driImageDriverExtension = { .getAPIMask = driGetAPIMask, .createContextAttribs = driCreateContextAttribs, }; + +/* swrast copy sub buffer entrypoint. */ +static void driCopySubBuffer(__DRIdrawable *pdp, int x, int y, + int w, int h) +{ + assert(pdp->driScreenPriv->swrast_loader); + + pdp->driScreenPriv->driver->CopySubBuffer(pdp, x, y, w, h); +} + +/* for swrast only */ +const __DRIcopySubBufferExtension driCopySubBufferExtension = { + { __DRI_COPY_SUB_BUFFER, 1 }, + .copySubBuffer = driCopySubBuffer, +}; diff --git a/mesalib/src/mesa/drivers/dri/common/dri_util.h b/mesalib/src/mesa/drivers/dri/common/dri_util.h index 79a8564ad..a79a4ed7a 100644 --- a/mesalib/src/mesa/drivers/dri/common/dri_util.h +++ b/mesalib/src/mesa/drivers/dri/common/dri_util.h @@ -66,7 +66,7 @@ extern const __DRIcoreExtension driCoreExtension; extern const __DRIswrastExtension driSWRastExtension; extern const __DRIdri2Extension driDRI2Extension; extern const __DRI2configQueryExtension dri2ConfigQueryExtension; - +extern const __DRIcopySubBufferExtension driCopySubBufferExtension; /** * Driver callback functions. * @@ -115,6 +115,9 @@ struct __DriverAPIRec { int width, int height); void (*ReleaseBuffer) (__DRIscreen *screenPrivate, __DRIbuffer *buffer); + + void (*CopySubBuffer)(__DRIdrawable *driDrawPriv, int x, int y, + int w, int h); }; extern const struct __DriverAPIRec driDriverAPI; @@ -289,6 +292,9 @@ dri2InvalidateDrawable(__DRIdrawable *drawable); extern void driUpdateFramebufferSize(struct gl_context *ctx, const __DRIdrawable *dPriv); +extern void +driContextSetFlags(struct gl_context *ctx, uint32_t flags); + extern const __DRIimageDriverExtension driImageDriverExtension; #endif /* _DRI_UTIL_H_ */ diff --git a/mesalib/src/mesa/drivers/dri/common/megadriver_stub.c b/mesalib/src/mesa/drivers/dri/common/megadriver_stub.c index 6bf5d7327..a8217703d 100644 --- a/mesalib/src/mesa/drivers/dri/common/megadriver_stub.c +++ b/mesalib/src/mesa/drivers/dri/common/megadriver_stub.c @@ -23,6 +23,132 @@ #include #include "dri_util.h" +#include +#include "main/macros.h" + +/* We need GNU extensions to dlfcn.h in order to provide backward + * compatibility for the older DRI driver loader mechanism. (dladdr, + * Dl_info, and RTLD_DEFAULT are only defined when _GNU_SOURCE is + * defined.) + */ +#ifdef _GNU_SOURCE + +#define MEGADRIVER_STUB_MAX_EXTENSIONS 10 +#define LIB_PATH_SUFFIX "_dri.so" +#define LIB_PATH_SUFFIX_LENGTH (sizeof(LIB_PATH_SUFFIX)-1) + +/* This is the table of extensions that the loader will dlsym() for. + * + * Initially it is empty for the megadriver stub, but the library + * constructor may initialize it based on the name of the library that + * is being loaded. + */ +PUBLIC const __DRIextension * +__driDriverExtensions[MEGADRIVER_STUB_MAX_EXTENSIONS] = { + NULL +}; + +/** + * This is a constructor function for the megadriver dynamic library. + * + * When the driver is dlopen'ed, this function will run. It will + * search for the name of the foo_dri.so file that was opened using + * the dladdr function. + * + * After finding foo's name, it will call __driDriverGetExtensions_foo + * and use the return to update __driDriverExtensions to enable + * compatibility with older DRI driver loaders. + */ +__attribute__((constructor)) static void +megadriver_stub_init(void) +{ + Dl_info info; + char *driver_name; + size_t name_len; + char *get_extensions_name; + const __DRIextension **(*get_extensions)(void); + const __DRIextension **extensions; + int i; + + /* Call dladdr on __driDriverExtensions. We are really + * interested in the returned info.dli_fname so we can + * figure out the path name of the library being loaded. + */ + i = dladdr((void*) __driDriverExtensions, &info); + if (i == 0) + return; + + /* Search for the last '/' character in the path. */ + driver_name = strrchr(info.dli_fname, '/'); + if (driver_name != NULL) { + /* Skip '/' character */ + driver_name++; + } else { + /* Try using the start of the path */ + driver_name = (char*) info.dli_fname; + } + + /* Make sure the path ends with _dri.so */ + name_len = strlen(driver_name); + i = name_len - LIB_PATH_SUFFIX_LENGTH; + if (i < 0 || strcmp(driver_name + i, LIB_PATH_SUFFIX) != 0) + return; + + /* Duplicate the string so we can modify it. + * So far we've been using info.dli_fname. + */ + driver_name = strdup(driver_name); + if (!driver_name) + return; + + /* The path ends with _dri.so. Chop this part of the + * string off. Then we'll have the driver's final name. + */ + driver_name[i] = '\0'; + + i = asprintf(&get_extensions_name, "%s_%s", + __DRI_DRIVER_GET_EXTENSIONS, driver_name); + free(driver_name); + if (i == -1) + return; + + /* dlsym to get the driver's get extensions function. We + * don't have the dlopen handle, so we have to use + * RTLD_DEFAULT. It seems unlikely that the symbol will + * be found in another library, but this isn't optimal. + */ + get_extensions = dlsym(RTLD_DEFAULT, get_extensions_name); + free(get_extensions_name); + if (!get_extensions) + return; + + /* Use the newer DRI loader entrypoint to find extensions. + * We will then expose these extensions via the older + * __driDriverExtensions symbol. + */ + extensions = get_extensions(); + + /* Copy the extensions into the __driDriverExtensions array + * we declared. + */ + for (i = 0; i < ARRAY_SIZE(__driDriverExtensions); i++) { + __driDriverExtensions[i] = extensions[i]; + if (extensions[i] == NULL) + break; + } + + /* If the driver had more extensions than we reserved, then + * bail out. + */ + if (i == ARRAY_SIZE(__driDriverExtensions)) { + __driDriverExtensions[0] = NULL; + fprintf(stderr, "Megadriver stub did not reserve enough extension " + "slots.\n"); + return; + } +} + +#endif /* _GNU_SOURCE */ static const __DRIconfig **stub_error_init_screen(__DRIscreen *psp) diff --git a/mesalib/src/mesa/drivers/dri/swrast/swrast.c b/mesalib/src/mesa/drivers/dri/swrast/swrast.c index 73dc5c4c0..79a27408f 100644 --- a/mesalib/src/mesa/drivers/dri/swrast/swrast.c +++ b/mesalib/src/mesa/drivers/dri/swrast/swrast.c @@ -402,7 +402,7 @@ swrast_map_renderbuffer(struct gl_context *ctx, stride = w * cpp; xrb->Base.Buffer = malloc(h * stride); - sPriv->swrast_loader->getImage(dPriv, x, y, w, h, + sPriv->swrast_loader->getImage(dPriv, x, rb->Height - y - h, w, h, (char *) xrb->Base.Buffer, dPriv->loaderPrivate); @@ -705,6 +705,8 @@ dri_create_context(gl_api api, goto context_fail; } + driContextSetFlags(mesaCtx, flags); + /* do bounds checking to prevent segfaults and server crashes! */ mesaCtx->Const.CheckArrayBounds = GL_TRUE; @@ -820,6 +822,39 @@ dri_unbind_context(__DRIcontext * cPriv) return GL_TRUE; } +static void +dri_copy_sub_buffer(__DRIdrawable *dPriv, int x, int y, + int w, int h) +{ + __DRIscreen *sPriv = dPriv->driScreenPriv; + void *data; + int iy; + struct dri_drawable *drawable = dri_drawable(dPriv); + struct gl_framebuffer *fb; + struct dri_swrast_renderbuffer *frontrb, *backrb; + + TRACE; + + fb = &drawable->Base; + + frontrb = + dri_swrast_renderbuffer(fb->Attachment[BUFFER_FRONT_LEFT].Renderbuffer); + backrb = + dri_swrast_renderbuffer(fb->Attachment[BUFFER_BACK_LEFT].Renderbuffer); + + /* check for signle-buffered */ + if (backrb == NULL) + return; + + iy = frontrb->Base.Base.Height - y - h; + data = (char *)backrb->Base.Buffer + (iy * backrb->pitch) + (x * ((backrb->bpp + 7) / 8)); + sPriv->swrast_loader->putImage2(dPriv, __DRI_SWRAST_IMAGE_OP_SWAP, + x, iy, w, h, + frontrb->pitch, + data, + dPriv->loaderPrivate); +} + static const struct __DriverAPIRec swrast_driver_api = { .InitScreen = dri_init_screen, @@ -831,6 +866,7 @@ static const struct __DriverAPIRec swrast_driver_api = { .SwapBuffers = dri_swap_buffers, .MakeCurrent = dri_make_current, .UnbindContext = dri_unbind_context, + .CopySubBuffer = dri_copy_sub_buffer, }; static const struct __DRIDriverVtableExtensionRec swrast_vtable = { @@ -841,6 +877,7 @@ static const struct __DRIDriverVtableExtensionRec swrast_vtable = { static const __DRIextension *swrast_driver_extensions[] = { &driCoreExtension.base, &driSWRastExtension.base, + &driCopySubBufferExtension.base, &swrast_vtable.base, NULL }; diff --git a/mesalib/src/mesa/main/attrib.c b/mesalib/src/mesa/main/attrib.c index c9332bd52..30c815d67 100644 --- a/mesalib/src/mesa/main/attrib.c +++ b/mesalib/src/mesa/main/attrib.c @@ -182,7 +182,7 @@ struct texture_state * Allocate new attribute node of given type/kind. Attach payload data. * Insert it into the linked list named by 'head'. */ -static void +static bool save_attrib_data(struct gl_attrib_node **head, GLbitfield kind, void *payload) { @@ -196,7 +196,42 @@ save_attrib_data(struct gl_attrib_node **head, } else { /* out of memory! */ + return false; + } + return true; +} + + +/** + * Helper function for_mesa_PushAttrib for simple attributes. + * Allocates memory for attribute data and copies the given attribute data. + * \param head head of linked list to insert attribute data into + * \param attr_bit one of the GL__BIT flags + * \param attr_size number of bytes to allocate for attribute data + * \param attr_data the attribute data to copy + * \return true for success, false for out of memory + */ +static bool +push_attrib(struct gl_context *ctx, struct gl_attrib_node **head, + GLbitfield attr_bit, GLuint attr_size, const void *attr_data) +{ + void *attribute; + + attribute = MALLOC(attr_size); + if (attribute == NULL) { + _mesa_error(ctx, GL_OUT_OF_MEMORY, "glPushAttrib"); + return false; + } + + if (save_attrib_data(head, attr_bit, attribute)) { + memcpy(attribute, attr_data, attr_size); } + else { + FREE(attribute); + _mesa_error(ctx, GL_OUT_OF_MEMORY, "glPushAttrib"); + return false; + } + return true; } @@ -220,42 +255,58 @@ _mesa_PushAttrib(GLbitfield mask) head = NULL; if (mask & GL_ACCUM_BUFFER_BIT) { - struct gl_accum_attrib *attr; - attr = MALLOC_STRUCT( gl_accum_attrib ); - memcpy( attr, &ctx->Accum, sizeof(struct gl_accum_attrib) ); - save_attrib_data(&head, GL_ACCUM_BUFFER_BIT, attr); + if (!push_attrib(ctx, &head, GL_ACCUM_BUFFER_BIT, + sizeof(struct gl_accum_attrib), + (void*)&ctx->Accum)) + goto end; } if (mask & GL_COLOR_BUFFER_BIT) { GLuint i; struct gl_colorbuffer_attrib *attr; attr = MALLOC_STRUCT( gl_colorbuffer_attrib ); - memcpy( attr, &ctx->Color, sizeof(struct gl_colorbuffer_attrib) ); - /* push the Draw FBO's DrawBuffer[] state, not ctx->Color.DrawBuffer[] */ - for (i = 0; i < ctx->Const.MaxDrawBuffers; i ++) - attr->DrawBuffer[i] = ctx->DrawBuffer->ColorDrawBuffer[i]; - save_attrib_data(&head, GL_COLOR_BUFFER_BIT, attr); + if (attr == NULL) { + _mesa_error(ctx, GL_OUT_OF_MEMORY, "glPushAttrib"); + goto end; + } + + if (save_attrib_data(&head, GL_COLOR_BUFFER_BIT, attr)) { + memcpy(attr, &ctx->Color, sizeof(struct gl_colorbuffer_attrib)); + /* push the Draw FBO's DrawBuffer[] state, not ctx->Color.DrawBuffer[] */ + for (i = 0; i < ctx->Const.MaxDrawBuffers; i ++) + attr->DrawBuffer[i] = ctx->DrawBuffer->ColorDrawBuffer[i]; + } + else { + FREE(attr); + _mesa_error(ctx, GL_OUT_OF_MEMORY, "glPushAttrib"); + goto end; + } } if (mask & GL_CURRENT_BIT) { - struct gl_current_attrib *attr; - FLUSH_CURRENT( ctx, 0 ); - attr = MALLOC_STRUCT( gl_current_attrib ); - memcpy( attr, &ctx->Current, sizeof(struct gl_current_attrib) ); - save_attrib_data(&head, GL_CURRENT_BIT, attr); + FLUSH_CURRENT(ctx, 0); + if (!push_attrib(ctx, &head, GL_CURRENT_BIT, + sizeof(struct gl_current_attrib), + (void*)&ctx->Current)) + goto end; } if (mask & GL_DEPTH_BUFFER_BIT) { - struct gl_depthbuffer_attrib *attr; - attr = MALLOC_STRUCT( gl_depthbuffer_attrib ); - memcpy( attr, &ctx->Depth, sizeof(struct gl_depthbuffer_attrib) ); - save_attrib_data(&head, GL_DEPTH_BUFFER_BIT, attr); + if (!push_attrib(ctx, &head, GL_DEPTH_BUFFER_BIT, + sizeof(struct gl_depthbuffer_attrib), + (void*)&ctx->Depth)) + goto end; } if (mask & GL_ENABLE_BIT) { struct gl_enable_attrib *attr; GLuint i; attr = MALLOC_STRUCT( gl_enable_attrib ); + if (attr == NULL) { + _mesa_error(ctx, GL_OUT_OF_MEMORY, "glPushAttrib"); + goto end; + } + /* Copy enable flags from all other attributes into the enable struct. */ attr->AlphaTest = ctx->Color.AlphaEnabled; attr->AutoNormal = ctx->Eval.AutoNormal; @@ -322,97 +373,112 @@ _mesa_PushAttrib(GLbitfield mask) /* GL_ARB_fragment_program */ attr->FragmentProgram = ctx->FragmentProgram.Enabled; - save_attrib_data(&head, GL_ENABLE_BIT, attr); + if (!save_attrib_data(&head, GL_ENABLE_BIT, attr)) { + FREE(attr); + _mesa_error(ctx, GL_OUT_OF_MEMORY, "glPushAttrib"); + goto end; + } /* GL_ARB_framebuffer_sRGB / GL_EXT_framebuffer_sRGB */ attr->sRGBEnabled = ctx->Color.sRGBEnabled; } if (mask & GL_EVAL_BIT) { - struct gl_eval_attrib *attr; - attr = MALLOC_STRUCT( gl_eval_attrib ); - memcpy( attr, &ctx->Eval, sizeof(struct gl_eval_attrib) ); - save_attrib_data(&head, GL_EVAL_BIT, attr); + if (!push_attrib(ctx, &head, GL_EVAL_BIT, + sizeof(struct gl_eval_attrib), + (void*)&ctx->Eval)) + goto end; } if (mask & GL_FOG_BIT) { - struct gl_fog_attrib *attr; - attr = MALLOC_STRUCT( gl_fog_attrib ); - memcpy( attr, &ctx->Fog, sizeof(struct gl_fog_attrib) ); - save_attrib_data(&head, GL_FOG_BIT, attr); + if (!push_attrib(ctx, &head, GL_FOG_BIT, + sizeof(struct gl_fog_attrib), + (void*)&ctx->Fog)) + goto end; } if (mask & GL_HINT_BIT) { - struct gl_hint_attrib *attr; - attr = MALLOC_STRUCT( gl_hint_attrib ); - memcpy( attr, &ctx->Hint, sizeof(struct gl_hint_attrib) ); - save_attrib_data(&head, GL_HINT_BIT, attr); + if (!push_attrib(ctx, &head, GL_HINT_BIT, + sizeof(struct gl_hint_attrib), + (void*)&ctx->Hint)) + goto end; } if (mask & GL_LIGHTING_BIT) { - struct gl_light_attrib *attr; - FLUSH_CURRENT(ctx, 0); /* flush material changes */ - attr = MALLOC_STRUCT( gl_light_attrib ); - memcpy( attr, &ctx->Light, sizeof(struct gl_light_attrib) ); - save_attrib_data(&head, GL_LIGHTING_BIT, attr); + FLUSH_CURRENT(ctx, 0); /* flush material changes */ + if (!push_attrib(ctx, &head, GL_LIGHTING_BIT, + sizeof(struct gl_light_attrib), + (void*)&ctx->Light)) + goto end; } if (mask & GL_LINE_BIT) { - struct gl_line_attrib *attr; - attr = MALLOC_STRUCT( gl_line_attrib ); - memcpy( attr, &ctx->Line, sizeof(struct gl_line_attrib) ); - save_attrib_data(&head, GL_LINE_BIT, attr); + if (!push_attrib(ctx, &head, GL_LINE_BIT, + sizeof(struct gl_line_attrib), + (void*)&ctx->Line)) + goto end; } if (mask & GL_LIST_BIT) { - struct gl_list_attrib *attr; - attr = MALLOC_STRUCT( gl_list_attrib ); - memcpy( attr, &ctx->List, sizeof(struct gl_list_attrib) ); - save_attrib_data(&head, GL_LIST_BIT, attr); + if (!push_attrib(ctx, &head, GL_LIST_BIT, + sizeof(struct gl_list_attrib), + (void*)&ctx->List)) + goto end; } if (mask & GL_PIXEL_MODE_BIT) { struct gl_pixel_attrib *attr; attr = MALLOC_STRUCT( gl_pixel_attrib ); - memcpy( attr, &ctx->Pixel, sizeof(struct gl_pixel_attrib) ); - /* push the Read FBO's ReadBuffer state, not ctx->Pixel.ReadBuffer */ - attr->ReadBuffer = ctx->ReadBuffer->ColorReadBuffer; - save_attrib_data(&head, GL_PIXEL_MODE_BIT, attr); + if (attr == NULL) { + _mesa_error(ctx, GL_OUT_OF_MEMORY, "glPushAttrib"); + goto end; + } + + if (save_attrib_data(&head, GL_PIXEL_MODE_BIT, attr)) { + memcpy(attr, &ctx->Pixel, sizeof(struct gl_pixel_attrib)); + /* push the Read FBO's ReadBuffer state, not ctx->Pixel.ReadBuffer */ + attr->ReadBuffer = ctx->ReadBuffer->ColorReadBuffer; + } + else { + FREE(attr); + _mesa_error(ctx, GL_OUT_OF_MEMORY, "glPushAttrib"); + goto end; + } } if (mask & GL_POINT_BIT) { - struct gl_point_attrib *attr; - attr = MALLOC_STRUCT( gl_point_attrib ); - memcpy( attr, &ctx->Point, sizeof(struct gl_point_attrib) ); - save_attrib_data(&head, GL_POINT_BIT, attr); + if (!push_attrib(ctx, &head, GL_POINT_BIT, + sizeof(struct gl_point_attrib), + (void*)&ctx->Point)) + goto end; } if (mask & GL_POLYGON_BIT) { - struct gl_polygon_attrib *attr; - attr = MALLOC_STRUCT( gl_polygon_attrib ); - memcpy( attr, &ctx->Polygon, sizeof(struct gl_polygon_attrib) ); - save_attrib_data(&head, GL_POLYGON_BIT, attr); + if (!push_attrib(ctx, &head, GL_POLYGON_BIT, + sizeof(struct gl_polygon_attrib), + (void*)&ctx->Polygon)) + goto end; } if (mask & GL_POLYGON_STIPPLE_BIT) { - GLuint *stipple; - stipple = malloc( 32*sizeof(GLuint) ); - memcpy( stipple, ctx->PolygonStipple, 32*sizeof(GLuint) ); - save_attrib_data(&head, GL_POLYGON_STIPPLE_BIT, stipple); + if (!push_attrib(ctx, &head, GL_POLYGON_STIPPLE_BIT, + sizeof(ctx->PolygonStipple), + (void*)&ctx->PolygonStipple)) + goto end; } if (mask & GL_SCISSOR_BIT) { - struct gl_scissor_attrib *attr; - attr = MALLOC_STRUCT( gl_scissor_attrib ); - memcpy( attr, &ctx->Scissor, sizeof(struct gl_scissor_attrib) ); - save_attrib_data(&head, GL_SCISSOR_BIT, attr); + if (!push_attrib(ctx, &head, GL_SCISSOR_BIT, + sizeof(struct gl_scissor_attrib), + (void*)&ctx->Scissor)) + goto end; } if (mask & GL_STENCIL_BUFFER_BIT) { - struct gl_stencil_attrib *attr; - attr = MALLOC_STRUCT( gl_stencil_attrib ); - memcpy( attr, &ctx->Stencil, sizeof(struct gl_stencil_attrib) ); - save_attrib_data(&head, GL_STENCIL_BUFFER_BIT, attr); + if (!push_attrib(ctx, &head, GL_STENCIL_BUFFER_BIT, + sizeof(struct gl_stencil_attrib), + (void*)&ctx->Stencil)) + goto end; } if (mask & GL_TEXTURE_BIT) { @@ -424,6 +490,12 @@ _mesa_PushAttrib(GLbitfield mask) goto end; } + if (!save_attrib_data(&head, GL_TEXTURE_BIT, texstate)) { + FREE(texstate); + _mesa_error(ctx, GL_OUT_OF_MEMORY, "glPushAttrib(GL_TEXTURE_BIT)"); + goto end; + } + _mesa_lock_context_textures(ctx); /* copy/save the bulk of texture state here */ @@ -450,35 +522,35 @@ _mesa_PushAttrib(GLbitfield mask) _mesa_reference_shared_state(ctx, &texstate->SharedRef, ctx->Shared); _mesa_unlock_context_textures(ctx); - - save_attrib_data(&head, GL_TEXTURE_BIT, texstate); } if (mask & GL_TRANSFORM_BIT) { - struct gl_transform_attrib *attr; - attr = MALLOC_STRUCT( gl_transform_attrib ); - memcpy( attr, &ctx->Transform, sizeof(struct gl_transform_attrib) ); - save_attrib_data(&head, GL_TRANSFORM_BIT, attr); + if (!push_attrib(ctx, &head, GL_TRANSFORM_BIT, + sizeof(struct gl_transform_attrib), + (void*)&ctx->Transform)) + goto end; } if (mask & GL_VIEWPORT_BIT) { - struct gl_viewport_attrib *attr; - attr = MALLOC_STRUCT( gl_viewport_attrib ); - memcpy( attr, &ctx->Viewport, sizeof(struct gl_viewport_attrib) ); - save_attrib_data(&head, GL_VIEWPORT_BIT, attr); + if (!push_attrib(ctx, &head, GL_VIEWPORT_BIT, + sizeof(struct gl_viewport_attrib), + (void*)&ctx->Viewport)) + goto end; } /* GL_ARB_multisample */ if (mask & GL_MULTISAMPLE_BIT_ARB) { - struct gl_multisample_attrib *attr; - attr = MALLOC_STRUCT( gl_multisample_attrib ); - memcpy( attr, &ctx->Multisample, sizeof(struct gl_multisample_attrib) ); - save_attrib_data(&head, GL_MULTISAMPLE_BIT_ARB, attr); + if (!push_attrib(ctx, &head, GL_MULTISAMPLE_BIT_ARB, + sizeof(struct gl_multisample_attrib), + (void*)&ctx->Multisample)) + goto end; } end: - ctx->AttribStack[ctx->AttribStackDepth] = head; - ctx->AttribStackDepth++; + if (head != NULL) { + ctx->AttribStack[ctx->AttribStackDepth] = head; + ctx->AttribStackDepth++; + } } @@ -641,12 +713,6 @@ pop_enable_group(struct gl_context *ctx, const struct gl_enable_attrib *enable) _mesa_set_enable(ctx, GL_TEXTURE_CUBE_MAP, !!(enabled & TEXTURE_CUBE_BIT)); } - if (ctx->Extensions.MESA_texture_array) { - _mesa_set_enable(ctx, GL_TEXTURE_1D_ARRAY_EXT, - !!(enabled & TEXTURE_1D_ARRAY_BIT)); - _mesa_set_enable(ctx, GL_TEXTURE_2D_ARRAY_EXT, - !!(enabled & TEXTURE_2D_ARRAY_BIT)); - } } if (ctx->Texture.Unit[i].TexGenEnabled != genEnabled) { @@ -688,12 +754,6 @@ pop_texture_group(struct gl_context *ctx, struct texture_state *texstate) _mesa_set_enable(ctx, GL_TEXTURE_RECTANGLE_NV, !!(unit->Enabled & TEXTURE_RECT_BIT)); } - if (ctx->Extensions.MESA_texture_array) { - _mesa_set_enable(ctx, GL_TEXTURE_1D_ARRAY_EXT, - !!(unit->Enabled & TEXTURE_1D_ARRAY_BIT)); - _mesa_set_enable(ctx, GL_TEXTURE_2D_ARRAY_EXT, - !!(unit->Enabled & TEXTURE_2D_ARRAY_BIT)); - } _mesa_TexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, unit->EnvMode); _mesa_TexEnvfv(GL_TEXTURE_ENV, GL_TEXTURE_ENV_COLOR, unit->EnvColor); _mesa_TexGeni(GL_S, GL_TEXTURE_GEN_MODE, unit->GenS.Mode); @@ -768,7 +828,7 @@ pop_texture_group(struct gl_context *ctx, struct texture_state *texstate) } else if ((obj->Target == GL_TEXTURE_1D_ARRAY_EXT || obj->Target == GL_TEXTURE_2D_ARRAY_EXT) && - !ctx->Extensions.MESA_texture_array) { + !ctx->Extensions.EXT_texture_array) { continue; } else if (obj->Target == GL_TEXTURE_CUBE_MAP_ARRAY && @@ -1482,13 +1542,20 @@ restore_array_attrib(struct gl_context *ctx, * init/alloc the fields of 'attrib'. * Needs to the init part matching free_array_attrib_data below. */ -static void +static bool init_array_attrib_data(struct gl_context *ctx, struct gl_array_attrib *attrib) { /* Get a non driver gl_array_object. */ attrib->ArrayObj = CALLOC_STRUCT( gl_array_object ); + + if (attrib->ArrayObj == NULL) { + _mesa_error(ctx, GL_OUT_OF_MEMORY, "glPushClientAttrib"); + return false; + } + _mesa_initialize_array_object(ctx, attrib->ArrayObj, 0); + return true; } /** @@ -1529,24 +1596,65 @@ _mesa_PushClientAttrib(GLbitfield mask) struct gl_pixelstore_attrib *attr; /* packing attribs */ attr = CALLOC_STRUCT( gl_pixelstore_attrib ); - copy_pixelstore(ctx, attr, &ctx->Pack); - save_attrib_data(&head, GL_CLIENT_PACK_BIT, attr); + if (attr == NULL) { + _mesa_error( ctx, GL_OUT_OF_MEMORY, "glPushClientAttrib" ); + goto end; + } + if (save_attrib_data(&head, GL_CLIENT_PACK_BIT, attr)) { + copy_pixelstore(ctx, attr, &ctx->Pack); + } + else { + _mesa_error( ctx, GL_OUT_OF_MEMORY, "glPushClientAttrib" ); + FREE(attr); + goto end; + } + /* unpacking attribs */ attr = CALLOC_STRUCT( gl_pixelstore_attrib ); - copy_pixelstore(ctx, attr, &ctx->Unpack); - save_attrib_data(&head, GL_CLIENT_UNPACK_BIT, attr); + if (attr == NULL) { + _mesa_error(ctx, GL_OUT_OF_MEMORY, "glPushClientAttrib"); + goto end; + } + + if (save_attrib_data(&head, GL_CLIENT_UNPACK_BIT, attr)) { + copy_pixelstore(ctx, attr, &ctx->Unpack); + } + else { + _mesa_error( ctx, GL_OUT_OF_MEMORY, "glPushClientAttrib" ); + FREE(attr); + goto end; + } } if (mask & GL_CLIENT_VERTEX_ARRAY_BIT) { struct gl_array_attrib *attr; attr = CALLOC_STRUCT( gl_array_attrib ); - init_array_attrib_data(ctx, attr); - save_array_attrib(ctx, attr, &ctx->Array); - save_attrib_data(&head, GL_CLIENT_VERTEX_ARRAY_BIT, attr); - } + if (attr == NULL) { + _mesa_error(ctx, GL_OUT_OF_MEMORY, "glPushClientAttrib"); + goto end; + } - ctx->ClientAttribStack[ctx->ClientAttribStackDepth] = head; - ctx->ClientAttribStackDepth++; + if (!init_array_attrib_data(ctx, attr)) { + FREE(attr); + goto end; + } + + if (save_attrib_data(&head, GL_CLIENT_VERTEX_ARRAY_BIT, attr)) { + save_array_attrib(ctx, attr, &ctx->Array); + } + else { + free_array_attrib_data(ctx, attr); + _mesa_error(ctx, GL_OUT_OF_MEMORY, "glPushClientAttrib"); + FREE(attr); + /* goto to keep safe from possible later changes */ + goto end; + } + } +end: + if (head != NULL) { + ctx->ClientAttribStack[ctx->ClientAttribStackDepth] = head; + ctx->ClientAttribStackDepth++; + } } diff --git a/mesalib/src/mesa/main/bufferobj.c b/mesalib/src/mesa/main/bufferobj.c index 8b5ebc489..a3d8f24b1 100644 --- a/mesalib/src/mesa/main/bufferobj.c +++ b/mesalib/src/mesa/main/bufferobj.c @@ -41,6 +41,9 @@ #include "fbobject.h" #include "mtypes.h" #include "texobj.h" +#include "teximage.h" +#include "glformats.h" +#include "texstore.h" #include "transformfeedback.h" #include "dispatch.h" @@ -124,11 +127,13 @@ get_buffer_target(struct gl_context *ctx, GLenum target) * Get the buffer object bound to the specified target in a GL context. * \param ctx the GL context * \param target the buffer object target to be retrieved. + * \param error the GL error to record if target is illegal. * \return pointer to the buffer object bound to \c target in the * specified context or \c NULL if \c target is invalid. */ static inline struct gl_buffer_object * -get_buffer(struct gl_context *ctx, const char *func, GLenum target) +get_buffer(struct gl_context *ctx, const char *func, GLenum target, + GLenum error) { struct gl_buffer_object **bufObj = get_buffer_target(ctx, target); @@ -138,7 +143,7 @@ get_buffer(struct gl_context *ctx, const char *func, GLenum target) } if (!_mesa_is_bufferobj(*bufObj)) { - _mesa_error(ctx, GL_INVALID_OPERATION, "%s(buffer 0)", func); + _mesa_error(ctx, error, "%s(no buffer bound)", func); return NULL; } @@ -185,26 +190,59 @@ simplified_access_mode(struct gl_context *ctx, GLbitfield access) } +/** + * Test if the buffer is mapped, and if so, if the mapped range overlaps the + * given range. + * The regions do not overlap if and only if the end of the given + * region is before the mapped region or the start of the given region + * is after the mapped region. + * + * \param obj Buffer object target on which to operate. + * \param offset Offset of the first byte of the subdata range. + * \param size Size, in bytes, of the subdata range. + * \return true if ranges overlap, false otherwise + * + */ +static bool +bufferobj_range_mapped(const struct gl_buffer_object *obj, + GLintptr offset, GLsizeiptr size) +{ + if (_mesa_bufferobj_mapped(obj)) { + const GLintptr end = offset + size; + const GLintptr mapEnd = obj->Offset + obj->Length; + + if (!(end <= obj->Offset || offset >= mapEnd)) { + return true; + } + } + return false; +} + + /** * Tests the subdata range parameters and sets the GL error code for - * \c glBufferSubDataARB and \c glGetBufferSubDataARB. + * \c glBufferSubDataARB, \c glGetBufferSubDataARB and + * \c glClearBufferSubData. * * \param ctx GL context. * \param target Buffer object target on which to operate. * \param offset Offset of the first byte of the subdata range. * \param size Size, in bytes, of the subdata range. + * \param mappedRange If true, checks if an overlapping range is mapped. + * If false, checks if buffer is mapped. + * \param errorNoBuffer Error code if no buffer is bound to target. * \param caller Name of calling function for recording errors. * \return A pointer to the buffer object bound to \c target in the * specified context or \c NULL if any of the parameter or state - * conditions for \c glBufferSubDataARB or \c glGetBufferSubDataARB - * are invalid. + * conditions are invalid. * - * \sa glBufferSubDataARB, glGetBufferSubDataARB + * \sa glBufferSubDataARB, glGetBufferSubDataARB, glClearBufferSubData */ static struct gl_buffer_object * -buffer_object_subdata_range_good( struct gl_context * ctx, GLenum target, - GLintptrARB offset, GLsizeiptrARB size, - const char *caller ) +buffer_object_subdata_range_good(struct gl_context * ctx, GLenum target, + GLintptrARB offset, GLsizeiptrARB size, + bool mappedRange, GLenum errorNoBuffer, + const char *caller) { struct gl_buffer_object *bufObj; @@ -218,28 +256,128 @@ buffer_object_subdata_range_good( struct gl_context * ctx, GLenum target, return NULL; } - bufObj = get_buffer(ctx, caller, target); + bufObj = get_buffer(ctx, caller, target, errorNoBuffer); if (!bufObj) return NULL; if (offset + size > bufObj->Size) { _mesa_error(ctx, GL_INVALID_VALUE, - "%s(offset %lu + size %lu > buffer size %lu)", caller, + "%s(offset %lu + size %lu > buffer size %lu)", caller, (unsigned long) offset, (unsigned long) size, (unsigned long) bufObj->Size); return NULL; } - if (_mesa_bufferobj_mapped(bufObj)) { - /* Buffer is currently mapped */ - _mesa_error(ctx, GL_INVALID_OPERATION, "%s", caller); - return NULL; + + if (mappedRange) { + if (bufferobj_range_mapped(bufObj, offset, size)) { + _mesa_error(ctx, GL_INVALID_OPERATION, "%s", caller); + return NULL; + } + } + else { + if (_mesa_bufferobj_mapped(bufObj)) { + _mesa_error(ctx, GL_INVALID_OPERATION, "%s", caller); + return NULL; + } } return bufObj; } +/** + * Test the format and type parameters and set the GL error code for + * \c glClearBufferData and \c glClearBufferSubData. + * + * \param ctx GL context. + * \param internalformat Format to which the data is to be converted. + * \param format Format of the supplied data. + * \param type Type of the supplied data. + * \param caller Name of calling function for recording errors. + * \return If internalformat, format and type are legal the gl_format + * corresponding to internalformat, otherwise MESA_FORMAT_NONE. + * + * \sa glClearBufferData and glClearBufferSubData + */ +static gl_format +validate_clear_buffer_format(struct gl_context *ctx, + GLenum internalformat, + GLenum format, GLenum type, + const char *caller) +{ + gl_format mesaFormat; + GLenum errorFormatType; + + mesaFormat = _mesa_validate_texbuffer_format(ctx, internalformat); + if (mesaFormat == MESA_FORMAT_NONE) { + _mesa_error(ctx, GL_INVALID_ENUM, + "%s(invalid internalformat)", caller); + return MESA_FORMAT_NONE; + } + + /* NOTE: not mentioned in ARB_clear_buffer_object but according to + * EXT_texture_integer there is no conversion between integer and + * non-integer formats + */ + if (_mesa_is_enum_format_signed_int(format) != + _mesa_is_format_integer_color(mesaFormat)) { + _mesa_error(ctx, GL_INVALID_OPERATION, + "%s(integer vs non-integer)", caller); + return MESA_FORMAT_NONE; + } + + if (!_mesa_is_color_format(format)) { + _mesa_error(ctx, GL_INVALID_ENUM, + "%s(format is not a color format)", caller); + return MESA_FORMAT_NONE; + } + + errorFormatType = _mesa_error_check_format_and_type(ctx, format, type); + if (errorFormatType != GL_NO_ERROR) { + _mesa_error(ctx, GL_INVALID_ENUM, + "%s(invalid format or type)", caller); + return MESA_FORMAT_NONE; + } + + return mesaFormat; +} + + +/** + * Convert user-specified clear value to the specified internal format. + * + * \param ctx GL context. + * \param internalformat Format to which the data is converted. + * \param clearValue Points to the converted clear value. + * \param format Format of the supplied data. + * \param type Type of the supplied data. + * \param data Data which is to be converted to internalformat. + * \param caller Name of calling function for recording errors. + * \return true if data could be converted, false otherwise. + * + * \sa glClearBufferData, glClearBufferSubData + */ +static bool +convert_clear_buffer_data(struct gl_context *ctx, + gl_format internalformat, + GLubyte *clearValue, GLenum format, GLenum type, + const GLvoid *data, const char *caller) +{ + GLenum internalformatBase = _mesa_get_format_base_format(internalformat); + + if (_mesa_texstore(ctx, 1, internalformatBase, internalformat, + 0, &clearValue, 1, 1, 1, + format, type, data, &ctx->Unpack)) { + return true; + } + else { + _mesa_error(ctx, GL_OUT_OF_MEMORY, "%s", caller); + return false; + } +} + + /** * Allocate and initialize a new buffer object. * @@ -504,6 +642,82 @@ _mesa_buffer_get_subdata( struct gl_context *ctx, GLintptrARB offset, } +/** + * Clear a subrange of the buffer object with copies of the supplied data. + * If data is NULL the buffer is filled with zeros. + * + * This is the default callback for \c dd_function_table::ClearBufferSubData() + * Note that all GL error checking will have been done already. + * + * \param ctx GL context. + * \param offset Offset of the first byte to be cleared. + * \param size Size, in bytes, of the to be cleared range. + * \param clearValue Source of the data. + * \param clearValueSize Size, in bytes, of the supplied data. + * \param bufObj Object to be cleared. + * + * \sa glClearBufferSubData, glClearBufferData and + * dd_function_table::ClearBufferSubData. + */ +static void +_mesa_buffer_clear_subdata(struct gl_context *ctx, + GLintptr offset, GLsizeiptr size, + const GLvoid *clearValue, + GLsizeiptr clearValueSize, + struct gl_buffer_object *bufObj) +{ + GLsizeiptr i; + GLubyte *dest; + + if (_mesa_bufferobj_mapped(bufObj)) { + GLubyte *data = malloc(size); + GLubyte *dataStart = data; + if (data == NULL) { + _mesa_error(ctx, GL_OUT_OF_MEMORY, "glClearBuffer[Sub]Data"); + return; + } + + if (clearValue == NULL) { + /* Clear with zeros, per the spec */ + memset(data, 0, size); + } + else { + for (i = 0; i < size/clearValueSize; ++i) { + memcpy(data, clearValue, clearValueSize); + data += clearValueSize; + } + } + ctx->Driver.BufferSubData(ctx, offset, size, dataStart, bufObj); + return; + } + + ASSERT(ctx->Driver.MapBufferRange); + dest = ctx->Driver.MapBufferRange(ctx, offset, size, + GL_MAP_WRITE_BIT | + GL_MAP_INVALIDATE_RANGE_BIT, + bufObj); + + if (!dest) { + _mesa_error(ctx, GL_OUT_OF_MEMORY, "glClearBuffer[Sub]Data"); + return; + } + + if (clearValue == NULL) { + /* Clear with zeros, per the spec */ + memset(dest, 0, size); + ctx->Driver.UnmapBuffer(ctx, bufObj); + return; + } + + for (i = 0; i < size/clearValueSize; ++i) { + memcpy(dest, clearValue, clearValueSize); + dest += clearValueSize; + } + + ctx->Driver.UnmapBuffer(ctx, bufObj); +} + + /** * Default fallback for \c dd_function_table::MapBufferRange(). * Called via glMapBufferRange(). @@ -810,6 +1024,9 @@ _mesa_init_buffer_object_functions(struct dd_function_table *driver) driver->GetBufferSubData = _mesa_buffer_get_subdata; driver->UnmapBuffer = _mesa_buffer_unmap; + /* GL_ARB_clear_buffer_object */ + driver->ClearBufferSubData = _mesa_buffer_clear_subdata; + /* GL_ARB_map_buffer_range */ driver->MapBufferRange = _mesa_buffer_map_range; driver->FlushMappedBufferRange = _mesa_buffer_flush_mapped_range; @@ -1064,7 +1281,7 @@ _mesa_BufferData(GLenum target, GLsizeiptrARB size, return; } - bufObj = get_buffer(ctx, "glBufferDataARB", target); + bufObj = get_buffer(ctx, "glBufferDataARB", target, GL_INVALID_OPERATION); if (!bufObj) return; @@ -1103,6 +1320,7 @@ _mesa_BufferSubData(GLenum target, GLintptrARB offset, struct gl_buffer_object *bufObj; bufObj = buffer_object_subdata_range_good( ctx, target, offset, size, + false, GL_INVALID_OPERATION, "glBufferSubDataARB" ); if (!bufObj) { /* error already recorded */ @@ -1126,8 +1344,9 @@ _mesa_GetBufferSubData(GLenum target, GLintptrARB offset, GET_CURRENT_CONTEXT(ctx); struct gl_buffer_object *bufObj; - bufObj = buffer_object_subdata_range_good( ctx, target, offset, size, - "glGetBufferSubDataARB" ); + bufObj = buffer_object_subdata_range_good(ctx, target, offset, size, + false, GL_INVALID_OPERATION, + "glGetBufferSubDataARB"); if (!bufObj) { /* error already recorded */ return; @@ -1138,6 +1357,111 @@ _mesa_GetBufferSubData(GLenum target, GLintptrARB offset, } +void GLAPIENTRY +_mesa_ClearBufferData(GLenum target, GLenum internalformat, GLenum format, + GLenum type, const GLvoid* data) +{ + GET_CURRENT_CONTEXT(ctx); + struct gl_buffer_object* bufObj; + gl_format mesaFormat; + GLubyte clearValue[MAX_PIXEL_BYTES]; + GLsizeiptr clearValueSize; + + bufObj = get_buffer(ctx, "glClearBufferData", target, GL_INVALID_VALUE); + if (!bufObj) { + return; + } + + if (_mesa_bufferobj_mapped(bufObj)) { + _mesa_error(ctx, GL_INVALID_OPERATION, + "glClearBufferData(buffer currently mapped)"); + return; + } + + mesaFormat = validate_clear_buffer_format(ctx, internalformat, + format, type, + "glClearBufferData"); + if (mesaFormat == MESA_FORMAT_NONE) { + return; + } + + clearValueSize = _mesa_get_format_bytes(mesaFormat); + if (bufObj->Size % clearValueSize != 0) { + _mesa_error(ctx, GL_INVALID_VALUE, + "glClearBufferData(size is not a multiple of " + "internalformat size)"); + return; + } + + if (data == NULL) { + /* clear to zeros, per the spec */ + ctx->Driver.ClearBufferSubData(ctx, 0, bufObj->Size, + NULL, 0, bufObj); + return; + } + + if (!convert_clear_buffer_data(ctx, mesaFormat, clearValue, + format, type, data, "glClearBufferData")) { + return; + } + + ctx->Driver.ClearBufferSubData(ctx, 0, bufObj->Size, + clearValue, clearValueSize, bufObj); +} + + +void GLAPIENTRY +_mesa_ClearBufferSubData(GLenum target, GLenum internalformat, + GLintptr offset, GLsizeiptr size, + GLenum format, GLenum type, + const GLvoid* data) +{ + GET_CURRENT_CONTEXT(ctx); + struct gl_buffer_object* bufObj; + gl_format mesaFormat; + GLubyte clearValue[MAX_PIXEL_BYTES]; + GLsizeiptr clearValueSize; + + bufObj = buffer_object_subdata_range_good(ctx, target, offset, size, + true, GL_INVALID_VALUE, + "glClearBufferSubData"); + if (!bufObj) { + return; + } + + mesaFormat = validate_clear_buffer_format(ctx, internalformat, + format, type, + "glClearBufferSubData"); + if (mesaFormat == MESA_FORMAT_NONE) { + return; + } + + clearValueSize = _mesa_get_format_bytes(mesaFormat); + if (offset % clearValueSize != 0 || size % clearValueSize != 0) { + _mesa_error(ctx, GL_INVALID_VALUE, + "glClearBufferSubData(offset or size is not a multiple of " + "internalformat size)"); + return; + } + + if (data == NULL) { + /* clear to zeros, per the spec */ + ctx->Driver.ClearBufferSubData(ctx, offset, size, + NULL, 0, bufObj); + return; + } + + if (!convert_clear_buffer_data(ctx, mesaFormat, clearValue, + format, type, data, + "glClearBufferSubData")) { + return; + } + + ctx->Driver.ClearBufferSubData(ctx, offset, size, + clearValue, clearValueSize, bufObj); +} + + void * GLAPIENTRY _mesa_MapBuffer(GLenum target, GLenum access) { @@ -1172,7 +1496,7 @@ _mesa_MapBuffer(GLenum target, GLenum access) return NULL; } - bufObj = get_buffer(ctx, "glMapBufferARB", target); + bufObj = get_buffer(ctx, "glMapBufferARB", target, GL_INVALID_OPERATION); if (!bufObj) return NULL; @@ -1241,7 +1565,7 @@ _mesa_UnmapBuffer(GLenum target) GLboolean status = GL_TRUE; ASSERT_OUTSIDE_BEGIN_END_WITH_RETVAL(ctx, GL_FALSE); - bufObj = get_buffer(ctx, "glUnmapBufferARB", target); + bufObj = get_buffer(ctx, "glUnmapBufferARB", target, GL_INVALID_OPERATION); if (!bufObj) return GL_FALSE; @@ -1302,7 +1626,8 @@ _mesa_GetBufferParameteriv(GLenum target, GLenum pname, GLint *params) GET_CURRENT_CONTEXT(ctx); struct gl_buffer_object *bufObj; - bufObj = get_buffer(ctx, "glGetBufferParameterivARB", target); + bufObj = get_buffer(ctx, "glGetBufferParameterivARB", target, + GL_INVALID_OPERATION); if (!bufObj) return; @@ -1355,7 +1680,8 @@ _mesa_GetBufferParameteri64v(GLenum target, GLenum pname, GLint64 *params) GET_CURRENT_CONTEXT(ctx); struct gl_buffer_object *bufObj; - bufObj = get_buffer(ctx, "glGetBufferParameteri64v", target); + bufObj = get_buffer(ctx, "glGetBufferParameteri64v", target, + GL_INVALID_OPERATION); if (!bufObj) return; @@ -1408,7 +1734,8 @@ _mesa_GetBufferPointerv(GLenum target, GLenum pname, GLvoid **params) return; } - bufObj = get_buffer(ctx, "glGetBufferPointervARB", target); + bufObj = get_buffer(ctx, "glGetBufferPointervARB", target, + GL_INVALID_OPERATION); if (!bufObj) return; @@ -1424,11 +1751,13 @@ _mesa_CopyBufferSubData(GLenum readTarget, GLenum writeTarget, GET_CURRENT_CONTEXT(ctx); struct gl_buffer_object *src, *dst; - src = get_buffer(ctx, "glCopyBufferSubData", readTarget); + src = get_buffer(ctx, "glCopyBufferSubData", readTarget, + GL_INVALID_OPERATION); if (!src) return; - dst = get_buffer(ctx, "glCopyBufferSubData", writeTarget); + dst = get_buffer(ctx, "glCopyBufferSubData", writeTarget, + GL_INVALID_OPERATION); if (!dst) return; @@ -1572,7 +1901,7 @@ _mesa_MapBufferRange(GLenum target, GLintptr offset, GLsizeiptr length, return NULL; } - bufObj = get_buffer(ctx, "glMapBufferRange", target); + bufObj = get_buffer(ctx, "glMapBufferRange", target, GL_INVALID_OPERATION); if (!bufObj) return NULL; @@ -1651,7 +1980,8 @@ _mesa_FlushMappedBufferRange(GLenum target, GLintptr offset, GLsizeiptr length) return; } - bufObj = get_buffer(ctx, "glFlushMappedBufferRange", target); + bufObj = get_buffer(ctx, "glFlushMappedBufferRange", target, + GL_INVALID_OPERATION); if (!bufObj) return; @@ -2331,23 +2661,11 @@ _mesa_InvalidateBufferSubData(GLuint buffer, GLintptr offset, * mapped by MapBuffer, or if the invalidate range intersects the range * currently mapped by MapBufferRange." */ - if (_mesa_bufferobj_mapped(bufObj)) { - const GLintptr mapEnd = bufObj->Offset + bufObj->Length; - - /* The regions do not overlap if and only if the end of the discard - * region is before the mapped region or the start of the discard region - * is after the mapped region. - * - * Note that 'end' and 'mapEnd' are the first byte *after* the discard - * region and the mapped region, repsectively. It is okay for that byte - * to be mapped (for 'end') or discarded (for 'mapEnd'). - */ - if (!(end <= bufObj->Offset || offset >= mapEnd)) { - _mesa_error(ctx, GL_INVALID_OPERATION, - "glInvalidateBufferSubData(intersection with mapped " - "range)"); - return; - } + if (bufferobj_range_mapped(bufObj, offset, length)) { + _mesa_error(ctx, GL_INVALID_OPERATION, + "glInvalidateBufferSubData(intersection with mapped " + "range)"); + return; } /* We don't actually do anything for this yet. Just return after diff --git a/mesalib/src/mesa/main/bufferobj.h b/mesalib/src/mesa/main/bufferobj.h index 0b898a21b..71988b0d9 100644 --- a/mesalib/src/mesa/main/bufferobj.h +++ b/mesalib/src/mesa/main/bufferobj.h @@ -57,10 +57,10 @@ _mesa_is_bufferobj(const struct gl_buffer_object *obj) extern void -_mesa_init_buffer_objects( struct gl_context *ctx ); +_mesa_init_buffer_objects(struct gl_context *ctx); extern void -_mesa_free_buffer_objects( struct gl_context *ctx ); +_mesa_free_buffer_objects(struct gl_context *ctx); extern bool _mesa_handle_bind_buffer_gen(struct gl_context *ctx, @@ -77,9 +77,9 @@ extern struct gl_buffer_object * _mesa_lookup_bufferobj(struct gl_context *ctx, GLuint buffer); extern void -_mesa_initialize_buffer_object( struct gl_context *ctx, - struct gl_buffer_object *obj, - GLuint name, GLenum target ); +_mesa_initialize_buffer_object(struct gl_context *ctx, + struct gl_buffer_object *obj, + GLuint name, GLenum target); extern void _mesa_reference_buffer_object_(struct gl_context *ctx, @@ -105,55 +105,90 @@ _mesa_init_buffer_object_functions(struct dd_function_table *driver); /* * API functions */ - void GLAPIENTRY _mesa_BindBuffer(GLenum target, GLuint buffer); + void GLAPIENTRY _mesa_DeleteBuffers(GLsizei n, const GLuint * buffer); + void GLAPIENTRY _mesa_GenBuffers(GLsizei n, GLuint * buffer); + GLboolean GLAPIENTRY _mesa_IsBuffer(GLuint buffer); + void GLAPIENTRY -_mesa_BufferData(GLenum target, GLsizeiptrARB size, const GLvoid * data, GLenum usage); +_mesa_BufferData(GLenum target, GLsizeiptrARB size, + const GLvoid * data, GLenum usage); + void GLAPIENTRY -_mesa_BufferSubData(GLenum target, GLintptrARB offset, GLsizeiptrARB size, const GLvoid * data); +_mesa_BufferSubData(GLenum target, GLintptrARB offset, + GLsizeiptrARB size, const GLvoid * data); + void GLAPIENTRY -_mesa_GetBufferSubData(GLenum target, GLintptrARB offset, GLsizeiptrARB size, void * data); +_mesa_GetBufferSubData(GLenum target, GLintptrARB offset, + GLsizeiptrARB size, void * data); + +void GLAPIENTRY +_mesa_ClearBufferData(GLenum target, GLenum internalformat, + GLenum format, GLenum type, + const GLvoid * data); + +void GLAPIENTRY +_mesa_ClearBufferSubData(GLenum target, GLenum internalformat, + GLintptr offset, GLsizeiptr size, + GLenum format, GLenum type, + const GLvoid * data); + void * GLAPIENTRY _mesa_MapBuffer(GLenum target, GLenum access); + GLboolean GLAPIENTRY _mesa_UnmapBuffer(GLenum target); + void GLAPIENTRY _mesa_GetBufferParameteriv(GLenum target, GLenum pname, GLint *params); + void GLAPIENTRY _mesa_GetBufferParameteri64v(GLenum target, GLenum pname, GLint64 *params); + void GLAPIENTRY _mesa_GetBufferPointerv(GLenum target, GLenum pname, GLvoid **params); + void GLAPIENTRY _mesa_CopyBufferSubData(GLenum readTarget, GLenum writeTarget, GLintptr readOffset, GLintptr writeOffset, GLsizeiptr size); + void * GLAPIENTRY _mesa_MapBufferRange(GLenum target, GLintptr offset, GLsizeiptr length, GLbitfield access); + void GLAPIENTRY -_mesa_FlushMappedBufferRange(GLenum target, GLintptr offset, GLsizeiptr length); +_mesa_FlushMappedBufferRange(GLenum target, + GLintptr offset, GLsizeiptr length); + GLenum GLAPIENTRY _mesa_ObjectPurgeableAPPLE(GLenum objectType, GLuint name, GLenum option); + GLenum GLAPIENTRY _mesa_ObjectUnpurgeableAPPLE(GLenum objectType, GLuint name, GLenum option); + void GLAPIENTRY -_mesa_GetObjectParameterivAPPLE(GLenum objectType, GLuint name, GLenum pname, - GLint* params); +_mesa_GetObjectParameterivAPPLE(GLenum objectType, GLuint name, + GLenum pname, GLint* params); + void GLAPIENTRY _mesa_BindBufferRange(GLenum target, GLuint index, GLuint buffer, GLintptr offset, GLsizeiptr size); + void GLAPIENTRY _mesa_BindBufferBase(GLenum target, GLuint index, GLuint buffer); + void GLAPIENTRY _mesa_InvalidateBufferSubData(GLuint buffer, GLintptr offset, GLsizeiptr length); + void GLAPIENTRY _mesa_InvalidateBufferData(GLuint buffer); diff --git a/mesalib/src/mesa/main/clear.c b/mesalib/src/mesa/main/clear.c index 304d135d1..f0b525fa0 100644 --- a/mesalib/src/mesa/main/clear.c +++ b/mesalib/src/mesa/main/clear.c @@ -219,7 +219,25 @@ make_color_buffer_mask(struct gl_context *ctx, GLint drawbuffer) const struct gl_renderbuffer_attachment *att = ctx->DrawBuffer->Attachment; GLbitfield mask = 0x0; - switch (drawbuffer) { + /* From the GL 4.0 specification: + * If buffer is COLOR, a particular draw buffer DRAW_BUFFERi is + * specified by passing i as the parameter drawbuffer, and value + * points to a four-element vector specifying the R, G, B, and A + * color to clear that draw buffer to. If the draw buffer is one + * of FRONT, BACK, LEFT, RIGHT, or FRONT_AND_BACK, identifying + * multiple buffers, each selected buffer is cleared to the same + * value. + * + * Note that "drawbuffer" and "draw buffer" have different meaning. + * "drawbuffer" specifies DRAW_BUFFERi, while "draw buffer" is what's + * assigned to DRAW_BUFFERi. It could be COLOR_ATTACHMENT0, FRONT, BACK, + * etc. + */ + if (drawbuffer < 0 || drawbuffer >= (GLint)ctx->Const.MaxDrawBuffers) { + return INVALID_MASK; + } + + switch (ctx->DrawBuffer->ColorDrawBuffer[drawbuffer]) { case GL_FRONT: if (att[BUFFER_FRONT_LEFT].Renderbuffer) mask |= BUFFER_BIT_FRONT_LEFT; @@ -255,11 +273,12 @@ make_color_buffer_mask(struct gl_context *ctx, GLint drawbuffer) mask |= BUFFER_BIT_BACK_RIGHT; break; default: - if (drawbuffer < 0 || drawbuffer >= (GLint)ctx->Const.MaxDrawBuffers) { - mask = INVALID_MASK; - } - else if (att[BUFFER_COLOR0 + drawbuffer].Renderbuffer) { - mask |= (BUFFER_BIT_COLOR0 << drawbuffer); + { + GLuint buf = ctx->DrawBuffer->_ColorDrawBufferIndexes[drawbuffer]; + + if (buf >= 0 && att[buf].Renderbuffer) { + mask |= 1 << buf; + } } } diff --git a/mesalib/src/mesa/main/colortab.c b/mesalib/src/mesa/main/colortab.c index 81e92d71c..a8edb03dd 100644 --- a/mesalib/src/mesa/main/colortab.c +++ b/mesalib/src/mesa/main/colortab.c @@ -44,7 +44,7 @@ _mesa_ColorTable( GLenum target, GLenum internalFormat, const GLvoid *data ) { GET_CURRENT_CONTEXT(ctx); - _mesa_error(ctx, GL_INVALID_ENUM, "glColorTable(target)"); + _mesa_error(ctx, GL_INVALID_OPERATION, "glColorTable"); } @@ -55,7 +55,7 @@ _mesa_ColorSubTable( GLenum target, GLsizei start, const GLvoid *data ) { GET_CURRENT_CONTEXT(ctx); - _mesa_error(ctx, GL_INVALID_ENUM, "glColorSubTable(target)"); + _mesa_error(ctx, GL_INVALID_OPERATION, "glColorSubTable"); } @@ -65,7 +65,7 @@ _mesa_CopyColorTable(GLenum target, GLenum internalformat, GLint x, GLint y, GLsizei width) { GET_CURRENT_CONTEXT(ctx); - _mesa_error(ctx, GL_INVALID_ENUM, "glCopyColorTable(target)"); + _mesa_error(ctx, GL_INVALID_OPERATION, "glCopyColorTable"); } @@ -75,7 +75,7 @@ _mesa_CopyColorSubTable(GLenum target, GLsizei start, GLint x, GLint y, GLsizei width) { GET_CURRENT_CONTEXT(ctx); - _mesa_error(ctx, GL_INVALID_ENUM, "glCopyColorSubTable(target)"); + _mesa_error(ctx, GL_INVALID_OPERATION, "glCopyColorSubTable"); } @@ -85,7 +85,7 @@ _mesa_GetnColorTableARB( GLenum target, GLenum format, GLenum type, GLsizei bufSize, GLvoid *data ) { GET_CURRENT_CONTEXT(ctx); - _mesa_error(ctx, GL_INVALID_ENUM, "glGetnColorTableARB(target)"); + _mesa_error(ctx, GL_INVALID_OPERATION, "glGetnColorTableARB"); } @@ -94,7 +94,7 @@ _mesa_GetColorTable( GLenum target, GLenum format, GLenum type, GLvoid *data ) { GET_CURRENT_CONTEXT(ctx); - _mesa_error(ctx, GL_INVALID_ENUM, "glGetColorTable(target)"); + _mesa_error(ctx, GL_INVALID_OPERATION, "glGetColorTable"); } @@ -103,7 +103,7 @@ _mesa_ColorTableParameterfv(GLenum target, GLenum pname, const GLfloat *params) { /* no extensions use this function */ GET_CURRENT_CONTEXT(ctx); - _mesa_error(ctx, GL_INVALID_ENUM, "glColorTableParameterfv(target)"); + _mesa_error(ctx, GL_INVALID_OPERATION, "glColorTableParameterfv"); } @@ -113,7 +113,7 @@ _mesa_ColorTableParameteriv(GLenum target, GLenum pname, const GLint *params) { /* no extensions use this function */ GET_CURRENT_CONTEXT(ctx); - _mesa_error(ctx, GL_INVALID_ENUM, "glColorTableParameteriv(target)"); + _mesa_error(ctx, GL_INVALID_OPERATION, "glColorTableParameteriv"); } @@ -122,7 +122,7 @@ void GLAPIENTRY _mesa_GetColorTableParameterfv( GLenum target, GLenum pname, GLfloat *params ) { GET_CURRENT_CONTEXT(ctx); - _mesa_error(ctx, GL_INVALID_ENUM, "glGetColorTableParameterfv(target)"); + _mesa_error(ctx, GL_INVALID_OPERATION, "glGetColorTableParameterfv"); } @@ -131,5 +131,5 @@ void GLAPIENTRY _mesa_GetColorTableParameteriv( GLenum target, GLenum pname, GLint *params ) { GET_CURRENT_CONTEXT(ctx); - _mesa_error(ctx, GL_INVALID_ENUM, "glGetColorTableParameteriv(target)"); + _mesa_error(ctx, GL_INVALID_OPERATION, "glGetColorTableParameteriv"); } diff --git a/mesalib/src/mesa/main/condrender.c b/mesalib/src/mesa/main/condrender.c index 3d9b0eca1..2632f7a1a 100644 --- a/mesalib/src/mesa/main/condrender.c +++ b/mesalib/src/mesa/main/condrender.c @@ -72,7 +72,9 @@ _mesa_BeginConditionalRender(GLuint queryId, GLenum mode) } ASSERT(q->Id == queryId); - if (q->Target != GL_SAMPLES_PASSED || q->Active) { + if ((q->Target != GL_SAMPLES_PASSED && + q->Target != GL_ANY_SAMPLES_PASSED && + q->Target != GL_ANY_SAMPLES_PASSED_CONSERVATIVE) || q->Active) { _mesa_error(ctx, GL_INVALID_OPERATION, "glBeginConditionalRender()"); return; } diff --git a/mesalib/src/mesa/main/context.c b/mesalib/src/mesa/main/context.c index 87a4a3545..658499fa4 100644 --- a/mesalib/src/mesa/main/context.c +++ b/mesalib/src/mesa/main/context.c @@ -1194,6 +1194,7 @@ _mesa_free_context_data( struct gl_context *ctx ) _mesa_free_sync_data(ctx); _mesa_free_varray_data(ctx); _mesa_free_transform_feedback(ctx); + _mesa_free_performance_monitors(ctx); _mesa_reference_buffer_object(ctx, &ctx->Pack.BufferObj, NULL); _mesa_reference_buffer_object(ctx, &ctx->Unpack.BufferObj, NULL); diff --git a/mesalib/src/mesa/main/convolve.c b/mesalib/src/mesa/main/convolve.c index f44031a9b..b13b89535 100644 --- a/mesalib/src/mesa/main/convolve.c +++ b/mesalib/src/mesa/main/convolve.c @@ -45,7 +45,7 @@ _mesa_ConvolutionFilter1D(GLenum target, GLenum internalFormat, GLsizei width, G { GET_CURRENT_CONTEXT(ctx); - _mesa_error(ctx, GL_INVALID_ENUM, "glConvolutionFilter1D"); + _mesa_error(ctx, GL_INVALID_OPERATION, "glConvolutionFilter1D"); } void GLAPIENTRY @@ -53,7 +53,7 @@ _mesa_ConvolutionFilter2D(GLenum target, GLenum internalFormat, GLsizei width, G { GET_CURRENT_CONTEXT(ctx); - _mesa_error(ctx, GL_INVALID_ENUM, "glConvolutionFilter2D"); + _mesa_error(ctx, GL_INVALID_OPERATION, "glConvolutionFilter2D"); } @@ -62,7 +62,7 @@ _mesa_ConvolutionParameterf(GLenum target, GLenum pname, GLfloat param) { GET_CURRENT_CONTEXT(ctx); - _mesa_error(ctx, GL_INVALID_ENUM, "glConvolutionParameterf"); + _mesa_error(ctx, GL_INVALID_OPERATION, "glConvolutionParameterf"); } @@ -71,7 +71,7 @@ _mesa_ConvolutionParameterfv(GLenum target, GLenum pname, const GLfloat *params) { GET_CURRENT_CONTEXT(ctx); - _mesa_error(ctx, GL_INVALID_ENUM, "glConvolutionParameterfv"); + _mesa_error(ctx, GL_INVALID_OPERATION, "glConvolutionParameterfv"); } @@ -80,7 +80,7 @@ _mesa_ConvolutionParameteri(GLenum target, GLenum pname, GLint param) { GET_CURRENT_CONTEXT(ctx); - _mesa_error(ctx, GL_INVALID_ENUM, "glConvolutionParameteri"); + _mesa_error(ctx, GL_INVALID_OPERATION, "glConvolutionParameteri"); } @@ -89,7 +89,7 @@ _mesa_ConvolutionParameteriv(GLenum target, GLenum pname, const GLint *params) { GET_CURRENT_CONTEXT(ctx); - _mesa_error(ctx, GL_INVALID_ENUM, "glConvolutionParameteriv"); + _mesa_error(ctx, GL_INVALID_OPERATION, "glConvolutionParameteriv"); } @@ -98,7 +98,7 @@ _mesa_CopyConvolutionFilter1D(GLenum target, GLenum internalFormat, GLint x, GLi { GET_CURRENT_CONTEXT(ctx); - _mesa_error(ctx, GL_INVALID_ENUM, "glCopyConvolutionFilter1D"); + _mesa_error(ctx, GL_INVALID_OPERATION, "glCopyConvolutionFilter1D"); } @@ -107,7 +107,7 @@ _mesa_CopyConvolutionFilter2D(GLenum target, GLenum internalFormat, GLint x, GLi { GET_CURRENT_CONTEXT(ctx); - _mesa_error(ctx, GL_INVALID_ENUM, "glCopyConvolutionFilter2D"); + _mesa_error(ctx, GL_INVALID_OPERATION, "glCopyConvolutionFilter2D"); } @@ -134,7 +134,7 @@ _mesa_GetConvolutionParameterfv(GLenum target, GLenum pname, GLfloat *params) { GET_CURRENT_CONTEXT(ctx); - _mesa_error(ctx, GL_INVALID_ENUM, "glGetConvolutionParameterfv"); + _mesa_error(ctx, GL_INVALID_OPERATION, "glGetConvolutionParameterfv"); } @@ -143,7 +143,7 @@ _mesa_GetConvolutionParameteriv(GLenum target, GLenum pname, GLint *params) { GET_CURRENT_CONTEXT(ctx); - _mesa_error(ctx, GL_INVALID_ENUM, "glGetConvolutionParameteriv"); + _mesa_error(ctx, GL_INVALID_OPERATION, "glGetConvolutionParameteriv"); } @@ -155,7 +155,7 @@ _mesa_GetnSeparableFilterARB(GLenum target, GLenum format, GLenum type, { GET_CURRENT_CONTEXT(ctx); - _mesa_error(ctx, GL_INVALID_ENUM, "glGetSeparableFilter"); + _mesa_error(ctx, GL_INVALID_OPERATION, "glGetSeparableFilter"); } @@ -173,5 +173,5 @@ _mesa_SeparableFilter2D(GLenum target, GLenum internalFormat, GLsizei width, GLs { GET_CURRENT_CONTEXT(ctx); - _mesa_error(ctx, GL_INVALID_ENUM, "glSeparableFilter2D"); + _mesa_error(ctx, GL_INVALID_OPERATION, "glSeparableFilter2D"); } diff --git a/mesalib/src/mesa/main/dd.h b/mesalib/src/mesa/main/dd.h index b5b874f47..6e73691ea 100644 --- a/mesalib/src/mesa/main/dd.h +++ b/mesalib/src/mesa/main/dd.h @@ -375,6 +375,11 @@ struct dd_function_table { GLsizei levels, GLsizei width, GLsizei height, GLsizei depth); + /** Called as part of glTextureView to add views to origTexObj */ + GLboolean (*TextureView)(struct gl_context *ctx, + struct gl_texture_object *texObj, + struct gl_texture_object *origTexObj); + /** * Map a renderbuffer into user space. * \param mode bitmask of GL_MAP_READ_BIT, GL_MAP_WRITE_BIT and @@ -569,6 +574,12 @@ struct dd_function_table { GLintptrARB offset, GLsizeiptrARB size, GLvoid *data, struct gl_buffer_object *obj ); + void (*ClearBufferSubData)( struct gl_context *ctx, + GLintptr offset, GLsizeiptr size, + const GLvoid *clearValue, + GLsizeiptr clearValueSize, + struct gl_buffer_object *obj ); + void (*CopyBufferSubData)( struct gl_context *ctx, struct gl_buffer_object *src, struct gl_buffer_object *dst, diff --git a/mesalib/src/mesa/main/dlist.c b/mesalib/src/mesa/main/dlist.c index 595641915..cb40ff4db 100644 --- a/mesalib/src/mesa/main/dlist.c +++ b/mesalib/src/mesa/main/dlist.c @@ -209,18 +209,6 @@ typedef enum OPCODE_COLOR_MASK, OPCODE_COLOR_MASK_INDEXED, OPCODE_COLOR_MATERIAL, - OPCODE_COLOR_TABLE, - OPCODE_COLOR_TABLE_PARAMETER_FV, - OPCODE_COLOR_TABLE_PARAMETER_IV, - OPCODE_COLOR_SUB_TABLE, - OPCODE_CONVOLUTION_FILTER_1D, - OPCODE_CONVOLUTION_FILTER_2D, - OPCODE_CONVOLUTION_PARAMETER_I, - OPCODE_CONVOLUTION_PARAMETER_IV, - OPCODE_CONVOLUTION_PARAMETER_F, - OPCODE_CONVOLUTION_PARAMETER_FV, - OPCODE_COPY_COLOR_SUB_TABLE, - OPCODE_COPY_COLOR_TABLE, OPCODE_COPY_PIXELS, OPCODE_COPY_TEX_IMAGE1D, OPCODE_COPY_TEX_IMAGE2D, @@ -243,7 +231,6 @@ typedef enum OPCODE_FRONT_FACE, OPCODE_FRUSTUM, OPCODE_HINT, - OPCODE_HISTOGRAM, OPCODE_INDEX_MASK, OPCODE_INIT_NAMES, OPCODE_LIGHT, @@ -260,7 +247,6 @@ typedef enum OPCODE_MAPGRID1, OPCODE_MAPGRID2, OPCODE_MATRIX_MODE, - OPCODE_MIN_MAX, OPCODE_MULT_MATRIX, OPCODE_ORTHO, OPCODE_PASSTHROUGH, @@ -281,8 +267,6 @@ typedef enum OPCODE_PUSH_NAME, OPCODE_RASTER_POS, OPCODE_READ_BUFFER, - OPCODE_RESET_HISTOGRAM, - OPCODE_RESET_MIN_MAX, OPCODE_ROTATE, OPCODE_SCALE, OPCODE_SCISSOR, @@ -486,6 +470,10 @@ typedef enum * Each instruction in the display list is stored as a sequence of * contiguous nodes in memory. * Each node is the union of a variety of data types. + * + * Note, all of these members should be 4 bytes in size or less for the + * sake of compact display lists. We store 8-byte pointers in a pair of + * these nodes using the save/get_pointer() functions below. */ union gl_dlist_node { @@ -500,14 +488,61 @@ union gl_dlist_node GLenum e; GLfloat f; GLsizei si; - GLvoid *data; - void *next; /* If prev node's opcode==OPCODE_CONTINUE */ }; typedef union gl_dlist_node Node; +/** How many 4-byte dwords to store a pointer */ +#define POINTER_DWORDS (sizeof(void *) / 4) + +/* We want to keep sizeof(union gl_dlist_node) == 4 to minimize + * space for display lists. The following types and functions are + * used to help store 4- and 8-byte pointers in 1 or 2 dlist_nodes. + */ +union pointer +{ + void *ptr; + GLuint dwords[POINTER_DWORDS]; +}; + + +/** + * Save a 4 or 8-byte pointer at dest (and dest+1). + */ +static inline void +save_pointer(union gl_dlist_node *dest, void *src) +{ + union pointer p; + unsigned i; + + STATIC_ASSERT(POINTER_DWORDS == 1 || POINTER_DWORDS == 2); + STATIC_ASSERT(sizeof(union gl_dlist_node) == 4); + + p.ptr = src; + + for (i = 0; i < POINTER_DWORDS; i++) + dest[i].ui = p.dwords[i]; +} + + +/** + * Retrieve a 4 or 8-byte pointer from node (node+1). + */ +static inline void * +get_pointer(const union gl_dlist_node *node) +{ + union pointer p; + unsigned i; + + for (i = 0; i < POINTER_DWORDS; i++) + p.dwords[i] = node[i].ui; + + return p.ptr; +} + + /** * Used to store a 64-bit uint in a pair of "Nodes" for the sake of 32-bit * environment. In 64-bit env, sizeof(Node)==8 anyway. @@ -520,9 +555,9 @@ union uint64_pair /** - * How many nodes to allocate at a time. - * - * \note Reduced now that we hold vertices etc. elsewhere. + * How many nodes to allocate at a time. Note that bulk vertex data + * from glBegin/glVertex/glEnd primitives will typically wind up in + * a VBO, and not directly in the display list itself. */ #define BLOCK_SIZE 256 @@ -538,14 +573,9 @@ static GLuint InstSize[OPCODE_END_OF_LIST + 1]; void mesa_print_display_list(GLuint list); -/**********************************************************************/ -/***** Private *****/ -/**********************************************************************/ - - /** - * Make an empty display list. This is used by glGenLists() to - * reserve display list IDs. + * Allocate a gl_display_list object with an initial block of storage. + * \param count how many display list nodes/tokes to allocate */ static struct gl_display_list * make_list(GLuint name, GLuint count) @@ -637,91 +667,75 @@ _mesa_delete_list(struct gl_context *ctx, struct gl_display_list *dlist) switch (opcode) { /* for some commands, we need to free malloc'd memory */ case OPCODE_MAP1: - free(n[6].data); + free(get_pointer(&n[6])); n += InstSize[n[0].opcode]; break; case OPCODE_MAP2: - free(n[10].data); + free(get_pointer(&n[10])); n += InstSize[n[0].opcode]; break; case OPCODE_DRAW_PIXELS: - free(n[5].data); + free(get_pointer(&n[5])); n += InstSize[n[0].opcode]; break; case OPCODE_BITMAP: - free(n[7].data); - n += InstSize[n[0].opcode]; - break; - case OPCODE_COLOR_TABLE: - free(n[6].data); - n += InstSize[n[0].opcode]; - break; - case OPCODE_COLOR_SUB_TABLE: - free(n[6].data); - n += InstSize[n[0].opcode]; - break; - case OPCODE_CONVOLUTION_FILTER_1D: - free(n[6].data); - n += InstSize[n[0].opcode]; - break; - case OPCODE_CONVOLUTION_FILTER_2D: - free(n[7].data); + free(get_pointer(&n[7])); n += InstSize[n[0].opcode]; break; case OPCODE_POLYGON_STIPPLE: - free(n[1].data); + free(get_pointer(&n[1])); n += InstSize[n[0].opcode]; break; case OPCODE_TEX_IMAGE1D: - free(n[8].data); + free(get_pointer(&n[8])); n += InstSize[n[0].opcode]; break; case OPCODE_TEX_IMAGE2D: - free(n[9].data); + free(get_pointer(&n[9])); n += InstSize[n[0].opcode]; break; case OPCODE_TEX_IMAGE3D: - free(n[10].data); + free(get_pointer(&n[10])); n += InstSize[n[0].opcode]; break; case OPCODE_TEX_SUB_IMAGE1D: - free(n[7].data); + free(get_pointer(&n[7])); n += InstSize[n[0].opcode]; break; case OPCODE_TEX_SUB_IMAGE2D: - free(n[9].data); + free(get_pointer(&n[9])); n += InstSize[n[0].opcode]; break; case OPCODE_TEX_SUB_IMAGE3D: - free(n[11].data); + free(get_pointer(&n[11])); n += InstSize[n[0].opcode]; break; case OPCODE_COMPRESSED_TEX_IMAGE_1D: - free(n[7].data); + free(get_pointer(&n[7])); n += InstSize[n[0].opcode]; break; case OPCODE_COMPRESSED_TEX_IMAGE_2D: - free(n[8].data); + free(get_pointer(&n[8])); n += InstSize[n[0].opcode]; break; case OPCODE_COMPRESSED_TEX_IMAGE_3D: - free(n[9].data); + free(get_pointer(&n[9])); n += InstSize[n[0].opcode]; break; case OPCODE_COMPRESSED_TEX_SUB_IMAGE_1D: - free(n[7].data); + free(get_pointer(&n[7])); n += InstSize[n[0].opcode]; break; case OPCODE_COMPRESSED_TEX_SUB_IMAGE_2D: - free(n[9].data); + free(get_pointer(&n[9])); n += InstSize[n[0].opcode]; break; case OPCODE_COMPRESSED_TEX_SUB_IMAGE_3D: - free(n[11].data); + free(get_pointer(&n[11])); n += InstSize[n[0].opcode]; break; case OPCODE_PROGRAM_STRING_ARB: - free(n[4].data); /* program string */ + free(get_pointer(&n[4])); /* program string */ n += InstSize[n[0].opcode]; break; case OPCODE_UNIFORM_1FV: @@ -736,7 +750,7 @@ _mesa_delete_list(struct gl_context *ctx, struct gl_display_list *dlist) case OPCODE_UNIFORM_2UIV: case OPCODE_UNIFORM_3UIV: case OPCODE_UNIFORM_4UIV: - free(n[3].data); + free(get_pointer(&n[3])); n += InstSize[n[0].opcode]; break; case OPCODE_UNIFORM_MATRIX22: @@ -748,12 +762,15 @@ _mesa_delete_list(struct gl_context *ctx, struct gl_display_list *dlist) case OPCODE_UNIFORM_MATRIX32: case OPCODE_UNIFORM_MATRIX34: case OPCODE_UNIFORM_MATRIX43: - free(n[4].data); + free(get_pointer(&n[4])); n += InstSize[n[0].opcode]; break; + case OPCODE_PIXEL_MAP: + free(get_pointer(&n[3])); + break; case OPCODE_CONTINUE: - n = (Node *) n[1].next; + n = (Node *) get_pointer(&n[1]); free(block); block = n; break; @@ -852,12 +869,6 @@ translate_id(GLsizei n, GLenum type, const GLvoid * list) } - - -/**********************************************************************/ -/***** Public *****/ -/**********************************************************************/ - /** * Wrapper for _mesa_unpack_image/bitmap() that handles pixel buffer objects. * If width < 0 or height < 0 or format or type are invalid we'll just @@ -929,6 +940,18 @@ unpack_image(struct gl_context *ctx, GLuint dimensions, return NULL; } + +/** Return copy of memory */ +static void * +memdup(const void *src, GLsizei bytes) +{ + void *b = bytes >= 0 ? malloc(bytes) : NULL; + if (b) + memcpy(b, src, bytes); + return b; +} + + /** * Allocate space for a display list instruction (opcode + payload space). * \param opcode the instruction opcode (OPCODE_* value) @@ -939,6 +962,7 @@ static Node * dlist_alloc(struct gl_context *ctx, OpCode opcode, GLuint bytes) { const GLuint numNodes = 1 + (bytes + sizeof(Node) - 1) / sizeof(Node); + const GLuint contNodes = 1 + POINTER_DWORDS; /* size of continue info */ Node *n; if (opcode < (GLuint) OPCODE_EXT_0) { @@ -952,7 +976,7 @@ dlist_alloc(struct gl_context *ctx, OpCode opcode, GLuint bytes) } } - if (ctx->ListState.CurrentPos + numNodes + 2 > BLOCK_SIZE) { + if (ctx->ListState.CurrentPos + numNodes + contNodes > BLOCK_SIZE) { /* This block is full. Allocate a new block and chain to it */ Node *newblock; n = ctx->ListState.CurrentBlock + ctx->ListState.CurrentPos; @@ -962,7 +986,7 @@ dlist_alloc(struct gl_context *ctx, OpCode opcode, GLuint bytes) _mesa_error(ctx, GL_OUT_OF_MEMORY, "Building display list"); return NULL; } - n[1].next = (Node *) newblock; + save_pointer(&n[1], newblock); ctx->ListState.CurrentBlock = newblock; ctx->ListState.CurrentPos = 0; } @@ -1043,6 +1067,37 @@ alloc_instruction(struct gl_context *ctx, OpCode opcode, GLuint nparams) } +/** + * Called by EndList to try to reduce memory used for the list. + */ +static void +trim_list(struct gl_context *ctx) +{ + /* If the list we're ending only has one allocated block of nodes/tokens + * and its size isn't a full block size, realloc the block to use less + * memory. This is important for apps that create many small display + * lists and apps that use glXUseXFont (many lists each containing one + * glBitmap call). + * Note: we currently only trim display lists that allocated one block + * of tokens. That hits the short list case which is what we're mainly + * concerned with. Trimming longer lists would involve traversing the + * linked list of blocks. + */ + struct gl_dlist_state *list = &ctx->ListState; + + if ((list->CurrentList->Head == list->CurrentBlock) && + (list->CurrentPos < BLOCK_SIZE)) { + /* There's only one block and it's not full, so realloc */ + GLuint newSize = list->CurrentPos * sizeof(Node); + list->CurrentList->Head = + list->CurrentBlock = realloc(list->CurrentBlock, newSize); + if (!list->CurrentBlock) { + _mesa_error(ctx, GL_OUT_OF_MEMORY, "glEndList"); + } + } +} + + /* * Display List compilation functions @@ -1106,7 +1161,7 @@ save_Bitmap(GLsizei width, GLsizei height, GET_CURRENT_CONTEXT(ctx); Node *n; ASSERT_OUTSIDE_SAVE_BEGIN_END_AND_FLUSH(ctx); - n = alloc_instruction(ctx, OPCODE_BITMAP, 7); + n = alloc_instruction(ctx, OPCODE_BITMAP, 6 + POINTER_DWORDS); if (n) { n[1].i = (GLint) width; n[2].i = (GLint) height; @@ -1114,8 +1169,9 @@ save_Bitmap(GLsizei width, GLsizei height, n[4].f = yorig; n[5].f = xmove; n[6].f = ymove; - n[7].data = unpack_image(ctx, 2, width, height, 1, GL_COLOR_INDEX, - GL_BITMAP, pixels, &ctx->Unpack); + save_pointer(&n[7], + unpack_image(ctx, 2, width, height, 1, GL_COLOR_INDEX, + GL_BITMAP, pixels, &ctx->Unpack)); } if (ctx->ExecuteFlag) { CALL_Bitmap(ctx->Exec, (width, height, @@ -1734,313 +1790,6 @@ save_ColorMaterial(GLenum face, GLenum mode) } -static void GLAPIENTRY -save_ColorTable(GLenum target, GLenum internalFormat, - GLsizei width, GLenum format, GLenum type, - const GLvoid * table) -{ - GET_CURRENT_CONTEXT(ctx); - if (_mesa_is_proxy_texture(target)) { - /* execute immediately */ - CALL_ColorTable(ctx->Exec, (target, internalFormat, width, - format, type, table)); - } - else { - Node *n; - ASSERT_OUTSIDE_SAVE_BEGIN_END_AND_FLUSH(ctx); - n = alloc_instruction(ctx, OPCODE_COLOR_TABLE, 6); - if (n) { - n[1].e = target; - n[2].e = internalFormat; - n[3].i = width; - n[4].e = format; - n[5].e = type; - n[6].data = unpack_image(ctx, 1, width, 1, 1, format, type, table, - &ctx->Unpack); - } - if (ctx->ExecuteFlag) { - CALL_ColorTable(ctx->Exec, (target, internalFormat, width, - format, type, table)); - } - } -} - - - -static void GLAPIENTRY -save_ColorTableParameterfv(GLenum target, GLenum pname, - const GLfloat *params) -{ - GET_CURRENT_CONTEXT(ctx); - Node *n; - - ASSERT_OUTSIDE_SAVE_BEGIN_END_AND_FLUSH(ctx); - - n = alloc_instruction(ctx, OPCODE_COLOR_TABLE_PARAMETER_FV, 6); - if (n) { - n[1].e = target; - n[2].e = pname; - n[3].f = params[0]; - if (pname == GL_COLOR_TABLE_SGI || - pname == GL_POST_CONVOLUTION_COLOR_TABLE_SGI || - pname == GL_TEXTURE_COLOR_TABLE_SGI) { - n[4].f = params[1]; - n[5].f = params[2]; - n[6].f = params[3]; - } - } - - if (ctx->ExecuteFlag) { - CALL_ColorTableParameterfv(ctx->Exec, (target, pname, params)); - } -} - - -static void GLAPIENTRY -save_ColorTableParameteriv(GLenum target, GLenum pname, const GLint *params) -{ - GET_CURRENT_CONTEXT(ctx); - Node *n; - - ASSERT_OUTSIDE_SAVE_BEGIN_END_AND_FLUSH(ctx); - - n = alloc_instruction(ctx, OPCODE_COLOR_TABLE_PARAMETER_IV, 6); - if (n) { - n[1].e = target; - n[2].e = pname; - n[3].i = params[0]; - if (pname == GL_COLOR_TABLE_SGI || - pname == GL_POST_CONVOLUTION_COLOR_TABLE_SGI || - pname == GL_TEXTURE_COLOR_TABLE_SGI) { - n[4].i = params[1]; - n[5].i = params[2]; - n[6].i = params[3]; - } - } - - if (ctx->ExecuteFlag) { - CALL_ColorTableParameteriv(ctx->Exec, (target, pname, params)); - } -} - - - -static void GLAPIENTRY -save_ColorSubTable(GLenum target, GLsizei start, GLsizei count, - GLenum format, GLenum type, const GLvoid * table) -{ - GET_CURRENT_CONTEXT(ctx); - Node *n; - ASSERT_OUTSIDE_SAVE_BEGIN_END_AND_FLUSH(ctx); - n = alloc_instruction(ctx, OPCODE_COLOR_SUB_TABLE, 6); - if (n) { - n[1].e = target; - n[2].i = start; - n[3].i = count; - n[4].e = format; - n[5].e = type; - n[6].data = unpack_image(ctx, 1, count, 1, 1, format, type, table, - &ctx->Unpack); - } - if (ctx->ExecuteFlag) { - CALL_ColorSubTable(ctx->Exec, - (target, start, count, format, type, table)); - } -} - - -static void GLAPIENTRY -save_CopyColorSubTable(GLenum target, GLsizei start, - GLint x, GLint y, GLsizei width) -{ - GET_CURRENT_CONTEXT(ctx); - Node *n; - - ASSERT_OUTSIDE_SAVE_BEGIN_END_AND_FLUSH(ctx); - n = alloc_instruction(ctx, OPCODE_COPY_COLOR_SUB_TABLE, 5); - if (n) { - n[1].e = target; - n[2].i = start; - n[3].i = x; - n[4].i = y; - n[5].i = width; - } - if (ctx->ExecuteFlag) { - CALL_CopyColorSubTable(ctx->Exec, (target, start, x, y, width)); - } -} - - -static void GLAPIENTRY -save_CopyColorTable(GLenum target, GLenum internalformat, - GLint x, GLint y, GLsizei width) -{ - GET_CURRENT_CONTEXT(ctx); - Node *n; - - ASSERT_OUTSIDE_SAVE_BEGIN_END_AND_FLUSH(ctx); - n = alloc_instruction(ctx, OPCODE_COPY_COLOR_TABLE, 5); - if (n) { - n[1].e = target; - n[2].e = internalformat; - n[3].i = x; - n[4].i = y; - n[5].i = width; - } - if (ctx->ExecuteFlag) { - CALL_CopyColorTable(ctx->Exec, (target, internalformat, x, y, width)); - } -} - - -static void GLAPIENTRY -save_ConvolutionFilter1D(GLenum target, GLenum internalFormat, GLsizei width, - GLenum format, GLenum type, const GLvoid * filter) -{ - GET_CURRENT_CONTEXT(ctx); - Node *n; - - ASSERT_OUTSIDE_SAVE_BEGIN_END_AND_FLUSH(ctx); - - n = alloc_instruction(ctx, OPCODE_CONVOLUTION_FILTER_1D, 6); - if (n) { - n[1].e = target; - n[2].e = internalFormat; - n[3].i = width; - n[4].e = format; - n[5].e = type; - n[6].data = unpack_image(ctx, 1, width, 1, 1, format, type, filter, - &ctx->Unpack); - } - if (ctx->ExecuteFlag) { - CALL_ConvolutionFilter1D(ctx->Exec, (target, internalFormat, width, - format, type, filter)); - } -} - - -static void GLAPIENTRY -save_ConvolutionFilter2D(GLenum target, GLenum internalFormat, - GLsizei width, GLsizei height, GLenum format, - GLenum type, const GLvoid * filter) -{ - GET_CURRENT_CONTEXT(ctx); - Node *n; - - ASSERT_OUTSIDE_SAVE_BEGIN_END_AND_FLUSH(ctx); - - n = alloc_instruction(ctx, OPCODE_CONVOLUTION_FILTER_2D, 7); - if (n) { - n[1].e = target; - n[2].e = internalFormat; - n[3].i = width; - n[4].i = height; - n[5].e = format; - n[6].e = type; - n[7].data = unpack_image(ctx, 2, width, height, 1, format, type, filter, - &ctx->Unpack); - } - if (ctx->ExecuteFlag) { - CALL_ConvolutionFilter2D(ctx->Exec, - (target, internalFormat, width, height, format, - type, filter)); - } -} - - -static void GLAPIENTRY -save_ConvolutionParameteri(GLenum target, GLenum pname, GLint param) -{ - GET_CURRENT_CONTEXT(ctx); - Node *n; - ASSERT_OUTSIDE_SAVE_BEGIN_END_AND_FLUSH(ctx); - n = alloc_instruction(ctx, OPCODE_CONVOLUTION_PARAMETER_I, 3); - if (n) { - n[1].e = target; - n[2].e = pname; - n[3].i = param; - } - if (ctx->ExecuteFlag) { - CALL_ConvolutionParameteri(ctx->Exec, (target, pname, param)); - } -} - - -static void GLAPIENTRY -save_ConvolutionParameteriv(GLenum target, GLenum pname, const GLint *params) -{ - GET_CURRENT_CONTEXT(ctx); - Node *n; - ASSERT_OUTSIDE_SAVE_BEGIN_END_AND_FLUSH(ctx); - n = alloc_instruction(ctx, OPCODE_CONVOLUTION_PARAMETER_IV, 6); - if (n) { - n[1].e = target; - n[2].e = pname; - n[3].i = params[0]; - if (pname == GL_CONVOLUTION_BORDER_COLOR || - pname == GL_CONVOLUTION_FILTER_SCALE || - pname == GL_CONVOLUTION_FILTER_BIAS) { - n[4].i = params[1]; - n[5].i = params[2]; - n[6].i = params[3]; - } - else { - n[4].i = n[5].i = n[6].i = 0; - } - } - if (ctx->ExecuteFlag) { - CALL_ConvolutionParameteriv(ctx->Exec, (target, pname, params)); - } -} - - -static void GLAPIENTRY -save_ConvolutionParameterf(GLenum target, GLenum pname, GLfloat param) -{ - GET_CURRENT_CONTEXT(ctx); - Node *n; - ASSERT_OUTSIDE_SAVE_BEGIN_END_AND_FLUSH(ctx); - n = alloc_instruction(ctx, OPCODE_CONVOLUTION_PARAMETER_F, 3); - if (n) { - n[1].e = target; - n[2].e = pname; - n[3].f = param; - } - if (ctx->ExecuteFlag) { - CALL_ConvolutionParameterf(ctx->Exec, (target, pname, param)); - } -} - - -static void GLAPIENTRY -save_ConvolutionParameterfv(GLenum target, GLenum pname, - const GLfloat *params) -{ - GET_CURRENT_CONTEXT(ctx); - Node *n; - ASSERT_OUTSIDE_SAVE_BEGIN_END_AND_FLUSH(ctx); - n = alloc_instruction(ctx, OPCODE_CONVOLUTION_PARAMETER_FV, 6); - if (n) { - n[1].e = target; - n[2].e = pname; - n[3].f = params[0]; - if (pname == GL_CONVOLUTION_BORDER_COLOR || - pname == GL_CONVOLUTION_FILTER_SCALE || - pname == GL_CONVOLUTION_FILTER_BIAS) { - n[4].f = params[1]; - n[5].f = params[2]; - n[6].f = params[3]; - } - else { - n[4].f = n[5].f = n[6].f = 0.0F; - } - } - if (ctx->ExecuteFlag) { - CALL_ConvolutionParameterfv(ctx->Exec, (target, pname, params)); - } -} - - static void GLAPIENTRY save_CopyPixels(GLint x, GLint y, GLsizei width, GLsizei height, GLenum type) { @@ -2314,14 +2063,15 @@ save_DrawPixels(GLsizei width, GLsizei height, ASSERT_OUTSIDE_SAVE_BEGIN_END_AND_FLUSH(ctx); - n = alloc_instruction(ctx, OPCODE_DRAW_PIXELS, 5); + n = alloc_instruction(ctx, OPCODE_DRAW_PIXELS, 4 + POINTER_DWORDS); if (n) { n[1].i = width; n[2].i = height; n[3].e = format; n[4].e = type; - n[5].data = unpack_image(ctx, 2, width, height, 1, format, type, - pixels, &ctx->Unpack); + save_pointer(&n[5], + unpack_image(ctx, 2, width, height, 1, format, type, + pixels, &ctx->Unpack)); } if (ctx->ExecuteFlag) { CALL_DrawPixels(ctx->Exec, (width, height, format, type, pixels)); @@ -2529,27 +2279,6 @@ save_Hint(GLenum target, GLenum mode) } -static void GLAPIENTRY -save_Histogram(GLenum target, GLsizei width, GLenum internalFormat, - GLboolean sink) -{ - GET_CURRENT_CONTEXT(ctx); - Node *n; - - ASSERT_OUTSIDE_SAVE_BEGIN_END_AND_FLUSH(ctx); - n = alloc_instruction(ctx, OPCODE_HISTOGRAM, 4); - if (n) { - n[1].e = target; - n[2].i = width; - n[3].e = internalFormat; - n[4].b = sink; - } - if (ctx->ExecuteFlag) { - CALL_Histogram(ctx->Exec, (target, width, internalFormat, sink)); - } -} - - static void GLAPIENTRY save_IndexMask(GLuint mask) { @@ -2890,7 +2619,7 @@ save_Map1d(GLenum target, GLdouble u1, GLdouble u2, GLint stride, GET_CURRENT_CONTEXT(ctx); Node *n; ASSERT_OUTSIDE_SAVE_BEGIN_END_AND_FLUSH(ctx); - n = alloc_instruction(ctx, OPCODE_MAP1, 6); + n = alloc_instruction(ctx, OPCODE_MAP1, 5 + POINTER_DWORDS); if (n) { GLfloat *pnts = _mesa_copy_map_points1d(target, stride, order, points); n[1].e = target; @@ -2898,7 +2627,7 @@ save_Map1d(GLenum target, GLdouble u1, GLdouble u2, GLint stride, n[3].f = (GLfloat) u2; n[4].i = _mesa_evaluator_components(target); /* stride */ n[5].i = order; - n[6].data = (void *) pnts; + save_pointer(&n[6], pnts); } if (ctx->ExecuteFlag) { CALL_Map1d(ctx->Exec, (target, u1, u2, stride, order, points)); @@ -2912,7 +2641,7 @@ save_Map1f(GLenum target, GLfloat u1, GLfloat u2, GLint stride, GET_CURRENT_CONTEXT(ctx); Node *n; ASSERT_OUTSIDE_SAVE_BEGIN_END_AND_FLUSH(ctx); - n = alloc_instruction(ctx, OPCODE_MAP1, 6); + n = alloc_instruction(ctx, OPCODE_MAP1, 5 + POINTER_DWORDS); if (n) { GLfloat *pnts = _mesa_copy_map_points1f(target, stride, order, points); n[1].e = target; @@ -2920,7 +2649,7 @@ save_Map1f(GLenum target, GLfloat u1, GLfloat u2, GLint stride, n[3].f = u2; n[4].i = _mesa_evaluator_components(target); /* stride */ n[5].i = order; - n[6].data = (void *) pnts; + save_pointer(&n[6], pnts); } if (ctx->ExecuteFlag) { CALL_Map1f(ctx->Exec, (target, u1, u2, stride, order, points)); @@ -2937,7 +2666,7 @@ save_Map2d(GLenum target, GET_CURRENT_CONTEXT(ctx); Node *n; ASSERT_OUTSIDE_SAVE_BEGIN_END_AND_FLUSH(ctx); - n = alloc_instruction(ctx, OPCODE_MAP2, 10); + n = alloc_instruction(ctx, OPCODE_MAP2, 9 + POINTER_DWORDS); if (n) { GLfloat *pnts = _mesa_copy_map_points2d(target, ustride, uorder, vstride, vorder, points); @@ -2951,7 +2680,7 @@ save_Map2d(GLenum target, n[7].i = _mesa_evaluator_components(target); /*vstride */ n[8].i = uorder; n[9].i = vorder; - n[10].data = (void *) pnts; + save_pointer(&n[10], pnts); } if (ctx->ExecuteFlag) { CALL_Map2d(ctx->Exec, (target, @@ -2970,7 +2699,7 @@ save_Map2f(GLenum target, GET_CURRENT_CONTEXT(ctx); Node *n; ASSERT_OUTSIDE_SAVE_BEGIN_END_AND_FLUSH(ctx); - n = alloc_instruction(ctx, OPCODE_MAP2, 10); + n = alloc_instruction(ctx, OPCODE_MAP2, 9 + POINTER_DWORDS); if (n) { GLfloat *pnts = _mesa_copy_map_points2f(target, ustride, uorder, vstride, vorder, points); @@ -2984,7 +2713,7 @@ save_Map2f(GLenum target, n[7].i = _mesa_evaluator_components(target); /*vstride */ n[8].i = uorder; n[9].i = vorder; - n[10].data = (void *) pnts; + save_pointer(&n[10], pnts); } if (ctx->ExecuteFlag) { CALL_Map2f(ctx->Exec, (target, u1, u2, ustride, uorder, @@ -3066,25 +2795,6 @@ save_MatrixMode(GLenum mode) } -static void GLAPIENTRY -save_Minmax(GLenum target, GLenum internalFormat, GLboolean sink) -{ - GET_CURRENT_CONTEXT(ctx); - Node *n; - - ASSERT_OUTSIDE_SAVE_BEGIN_END_AND_FLUSH(ctx); - n = alloc_instruction(ctx, OPCODE_MIN_MAX, 3); - if (n) { - n[1].e = target; - n[2].e = internalFormat; - n[3].b = sink; - } - if (ctx->ExecuteFlag) { - CALL_Minmax(ctx->Exec, (target, internalFormat, sink)); - } -} - - static void GLAPIENTRY save_MultMatrixf(const GLfloat * m) { @@ -3156,12 +2866,11 @@ save_PixelMapfv(GLenum map, GLint mapsize, const GLfloat *values) GET_CURRENT_CONTEXT(ctx); Node *n; ASSERT_OUTSIDE_SAVE_BEGIN_END_AND_FLUSH(ctx); - n = alloc_instruction(ctx, OPCODE_PIXEL_MAP, 3); + n = alloc_instruction(ctx, OPCODE_PIXEL_MAP, 2 + POINTER_DWORDS); if (n) { n[1].e = map; n[2].i = mapsize; - n[3].data = malloc(mapsize * sizeof(GLfloat)); - memcpy(n[3].data, (void *) values, mapsize * sizeof(GLfloat)); + save_pointer(&n[3], memdup(values, mapsize * sizeof(GLfloat))); } if (ctx->ExecuteFlag) { CALL_PixelMapfv(ctx->Exec, (map, mapsize, values)); @@ -3336,10 +3045,11 @@ save_PolygonStipple(const GLubyte * pattern) ASSERT_OUTSIDE_SAVE_BEGIN_END_AND_FLUSH(ctx); - n = alloc_instruction(ctx, OPCODE_POLYGON_STIPPLE, 1); + n = alloc_instruction(ctx, OPCODE_POLYGON_STIPPLE, POINTER_DWORDS); if (n) { - n[1].data = unpack_image(ctx, 2, 32, 32, 1, GL_COLOR_INDEX, GL_BITMAP, - pattern, &ctx->Unpack); + save_pointer(&n[1], + unpack_image(ctx, 2, 32, 32, 1, GL_COLOR_INDEX, GL_BITMAP, + pattern, &ctx->Unpack)); } if (ctx->ExecuteFlag) { CALL_PolygonStipple(ctx->Exec, ((GLubyte *) pattern)); @@ -3666,38 +3376,6 @@ save_ReadBuffer(GLenum mode) } -static void GLAPIENTRY -save_ResetHistogram(GLenum target) -{ - GET_CURRENT_CONTEXT(ctx); - Node *n; - ASSERT_OUTSIDE_SAVE_BEGIN_END_AND_FLUSH(ctx); - n = alloc_instruction(ctx, OPCODE_RESET_HISTOGRAM, 1); - if (n) { - n[1].e = target; - } - if (ctx->ExecuteFlag) { - CALL_ResetHistogram(ctx->Exec, (target)); - } -} - - -static void GLAPIENTRY -save_ResetMinmax(GLenum target) -{ - GET_CURRENT_CONTEXT(ctx); - Node *n; - ASSERT_OUTSIDE_SAVE_BEGIN_END_AND_FLUSH(ctx); - n = alloc_instruction(ctx, OPCODE_RESET_MIN_MAX, 1); - if (n) { - n[1].e = target; - } - if (ctx->ExecuteFlag) { - CALL_ResetMinmax(ctx->Exec, (target)); - } -} - - static void GLAPIENTRY save_Rotatef(GLfloat angle, GLfloat x, GLfloat y, GLfloat z) { @@ -4140,7 +3818,7 @@ save_TexImage1D(GLenum target, else { Node *n; ASSERT_OUTSIDE_SAVE_BEGIN_END_AND_FLUSH(ctx); - n = alloc_instruction(ctx, OPCODE_TEX_IMAGE1D, 8); + n = alloc_instruction(ctx, OPCODE_TEX_IMAGE1D, 7 + POINTER_DWORDS); if (n) { n[1].e = target; n[2].i = level; @@ -4149,8 +3827,9 @@ save_TexImage1D(GLenum target, n[5].i = border; n[6].e = format; n[7].e = type; - n[8].data = unpack_image(ctx, 1, width, 1, 1, format, type, - pixels, &ctx->Unpack); + save_pointer(&n[8], + unpack_image(ctx, 1, width, 1, 1, format, type, + pixels, &ctx->Unpack)); } if (ctx->ExecuteFlag) { CALL_TexImage1D(ctx->Exec, (target, level, components, width, @@ -4175,7 +3854,7 @@ save_TexImage2D(GLenum target, else { Node *n; ASSERT_OUTSIDE_SAVE_BEGIN_END_AND_FLUSH(ctx); - n = alloc_instruction(ctx, OPCODE_TEX_IMAGE2D, 9); + n = alloc_instruction(ctx, OPCODE_TEX_IMAGE2D, 8 + POINTER_DWORDS); if (n) { n[1].e = target; n[2].i = level; @@ -4185,8 +3864,9 @@ save_TexImage2D(GLenum target, n[6].i = border; n[7].e = format; n[8].e = type; - n[9].data = unpack_image(ctx, 2, width, height, 1, format, type, - pixels, &ctx->Unpack); + save_pointer(&n[9], + unpack_image(ctx, 2, width, height, 1, format, type, + pixels, &ctx->Unpack)); } if (ctx->ExecuteFlag) { CALL_TexImage2D(ctx->Exec, (target, level, components, width, @@ -4213,7 +3893,7 @@ save_TexImage3D(GLenum target, else { Node *n; ASSERT_OUTSIDE_SAVE_BEGIN_END_AND_FLUSH(ctx); - n = alloc_instruction(ctx, OPCODE_TEX_IMAGE3D, 10); + n = alloc_instruction(ctx, OPCODE_TEX_IMAGE3D, 9 + POINTER_DWORDS); if (n) { n[1].e = target; n[2].i = level; @@ -4224,8 +3904,9 @@ save_TexImage3D(GLenum target, n[7].i = border; n[8].e = format; n[9].e = type; - n[10].data = unpack_image(ctx, 3, width, height, depth, format, type, - pixels, &ctx->Unpack); + save_pointer(&n[10], + unpack_image(ctx, 3, width, height, depth, format, type, + pixels, &ctx->Unpack)); } if (ctx->ExecuteFlag) { CALL_TexImage3D(ctx->Exec, (target, level, internalFormat, width, @@ -4246,7 +3927,7 @@ save_TexSubImage1D(GLenum target, GLint level, GLint xoffset, ASSERT_OUTSIDE_SAVE_BEGIN_END_AND_FLUSH(ctx); - n = alloc_instruction(ctx, OPCODE_TEX_SUB_IMAGE1D, 7); + n = alloc_instruction(ctx, OPCODE_TEX_SUB_IMAGE1D, 6 + POINTER_DWORDS); if (n) { n[1].e = target; n[2].i = level; @@ -4254,8 +3935,9 @@ save_TexSubImage1D(GLenum target, GLint level, GLint xoffset, n[4].i = (GLint) width; n[5].e = format; n[6].e = type; - n[7].data = unpack_image(ctx, 1, width, 1, 1, format, type, - pixels, &ctx->Unpack); + save_pointer(&n[7], + unpack_image(ctx, 1, width, 1, 1, format, type, + pixels, &ctx->Unpack)); } if (ctx->ExecuteFlag) { CALL_TexSubImage1D(ctx->Exec, (target, level, xoffset, width, @@ -4275,7 +3957,7 @@ save_TexSubImage2D(GLenum target, GLint level, ASSERT_OUTSIDE_SAVE_BEGIN_END_AND_FLUSH(ctx); - n = alloc_instruction(ctx, OPCODE_TEX_SUB_IMAGE2D, 9); + n = alloc_instruction(ctx, OPCODE_TEX_SUB_IMAGE2D, 8 + POINTER_DWORDS); if (n) { n[1].e = target; n[2].i = level; @@ -4285,8 +3967,9 @@ save_TexSubImage2D(GLenum target, GLint level, n[6].i = (GLint) height; n[7].e = format; n[8].e = type; - n[9].data = unpack_image(ctx, 2, width, height, 1, format, type, - pixels, &ctx->Unpack); + save_pointer(&n[9], + unpack_image(ctx, 2, width, height, 1, format, type, + pixels, &ctx->Unpack)); } if (ctx->ExecuteFlag) { CALL_TexSubImage2D(ctx->Exec, (target, level, xoffset, yoffset, @@ -4306,7 +3989,7 @@ save_TexSubImage3D(GLenum target, GLint level, ASSERT_OUTSIDE_SAVE_BEGIN_END_AND_FLUSH(ctx); - n = alloc_instruction(ctx, OPCODE_TEX_SUB_IMAGE3D, 11); + n = alloc_instruction(ctx, OPCODE_TEX_SUB_IMAGE3D, 10 + POINTER_DWORDS); if (n) { n[1].e = target; n[2].i = level; @@ -4318,8 +4001,9 @@ save_TexSubImage3D(GLenum target, GLint level, n[8].i = (GLint) depth; n[9].e = format; n[10].e = type; - n[11].data = unpack_image(ctx, 3, width, height, depth, format, type, - pixels, &ctx->Unpack); + save_pointer(&n[11], + unpack_image(ctx, 3, width, height, depth, format, type, + pixels, &ctx->Unpack)); } if (ctx->ExecuteFlag) { CALL_TexSubImage3D(ctx->Exec, (target, level, @@ -4626,7 +4310,8 @@ save_CompressedTexImage1DARB(GLenum target, GLint level, Node *n; ASSERT_OUTSIDE_SAVE_BEGIN_END_AND_FLUSH(ctx); - n = alloc_instruction(ctx, OPCODE_COMPRESSED_TEX_IMAGE_1D, 7); + n = alloc_instruction(ctx, OPCODE_COMPRESSED_TEX_IMAGE_1D, + 6 + POINTER_DWORDS); if (n) { n[1].e = target; n[2].i = level; @@ -4634,7 +4319,8 @@ save_CompressedTexImage1DARB(GLenum target, GLint level, n[4].i = (GLint) width; n[5].i = border; n[6].i = imageSize; - n[7].data = copy_data(data, imageSize, "glCompressedTexImage1DARB"); + save_pointer(&n[7], + copy_data(data, imageSize, "glCompressedTexImage1DARB")); } if (ctx->ExecuteFlag) { CALL_CompressedTexImage1D(ctx->Exec, @@ -4662,7 +4348,8 @@ save_CompressedTexImage2DARB(GLenum target, GLint level, Node *n; ASSERT_OUTSIDE_SAVE_BEGIN_END_AND_FLUSH(ctx); - n = alloc_instruction(ctx, OPCODE_COMPRESSED_TEX_IMAGE_2D, 8); + n = alloc_instruction(ctx, OPCODE_COMPRESSED_TEX_IMAGE_2D, + 7 + POINTER_DWORDS); if (n) { n[1].e = target; n[2].i = level; @@ -4671,7 +4358,8 @@ save_CompressedTexImage2DARB(GLenum target, GLint level, n[5].i = (GLint) height; n[6].i = border; n[7].i = imageSize; - n[8].data = copy_data(data, imageSize, "glCompressedTexImage2DARB"); + save_pointer(&n[8], + copy_data(data, imageSize, "glCompressedTexImage2DARB")); } if (ctx->ExecuteFlag) { CALL_CompressedTexImage2D(ctx->Exec, @@ -4699,7 +4387,8 @@ save_CompressedTexImage3DARB(GLenum target, GLint level, Node *n; ASSERT_OUTSIDE_SAVE_BEGIN_END_AND_FLUSH(ctx); - n = alloc_instruction(ctx, OPCODE_COMPRESSED_TEX_IMAGE_3D, 9); + n = alloc_instruction(ctx, OPCODE_COMPRESSED_TEX_IMAGE_3D, + 8 + POINTER_DWORDS); if (n) { n[1].e = target; n[2].i = level; @@ -4709,7 +4398,8 @@ save_CompressedTexImage3DARB(GLenum target, GLint level, n[6].i = (GLint) depth; n[7].i = border; n[8].i = imageSize; - n[9].data = copy_data(data, imageSize, "glCompressedTexImage3DARB"); + save_pointer(&n[9], + copy_data(data, imageSize, "glCompressedTexImage3DARB")); } if (ctx->ExecuteFlag) { CALL_CompressedTexImage3D(ctx->Exec, @@ -4730,7 +4420,8 @@ save_CompressedTexSubImage1DARB(GLenum target, GLint level, GLint xoffset, GET_CURRENT_CONTEXT(ctx); ASSERT_OUTSIDE_SAVE_BEGIN_END_AND_FLUSH(ctx); - n = alloc_instruction(ctx, OPCODE_COMPRESSED_TEX_SUB_IMAGE_1D, 7); + n = alloc_instruction(ctx, OPCODE_COMPRESSED_TEX_SUB_IMAGE_1D, + 6 + POINTER_DWORDS); if (n) { n[1].e = target; n[2].i = level; @@ -4738,7 +4429,8 @@ save_CompressedTexSubImage1DARB(GLenum target, GLint level, GLint xoffset, n[4].i = (GLint) width; n[5].e = format; n[6].i = imageSize; - n[7].data = copy_data(data, imageSize, "glCompressedTexSubImage1DARB"); + save_pointer(&n[7], + copy_data(data, imageSize, "glCompressedTexSubImage1DARB")); } if (ctx->ExecuteFlag) { CALL_CompressedTexSubImage1D(ctx->Exec, (target, level, xoffset, @@ -4758,7 +4450,8 @@ save_CompressedTexSubImage2DARB(GLenum target, GLint level, GLint xoffset, GET_CURRENT_CONTEXT(ctx); ASSERT_OUTSIDE_SAVE_BEGIN_END_AND_FLUSH(ctx); - n = alloc_instruction(ctx, OPCODE_COMPRESSED_TEX_SUB_IMAGE_2D, 9); + n = alloc_instruction(ctx, OPCODE_COMPRESSED_TEX_SUB_IMAGE_2D, + 8 + POINTER_DWORDS); if (n) { n[1].e = target; n[2].i = level; @@ -4768,7 +4461,8 @@ save_CompressedTexSubImage2DARB(GLenum target, GLint level, GLint xoffset, n[6].i = (GLint) height; n[7].e = format; n[8].i = imageSize; - n[9].data = copy_data(data, imageSize, "glCompressedTexSubImage2DARB"); + save_pointer(&n[9], + copy_data(data, imageSize, "glCompressedTexSubImage2DARB")); } if (ctx->ExecuteFlag) { CALL_CompressedTexSubImage2D(ctx->Exec, @@ -4788,7 +4482,8 @@ save_CompressedTexSubImage3DARB(GLenum target, GLint level, GLint xoffset, GET_CURRENT_CONTEXT(ctx); ASSERT_OUTSIDE_SAVE_BEGIN_END_AND_FLUSH(ctx); - n = alloc_instruction(ctx, OPCODE_COMPRESSED_TEX_SUB_IMAGE_3D, 11); + n = alloc_instruction(ctx, OPCODE_COMPRESSED_TEX_SUB_IMAGE_3D, + 10 + POINTER_DWORDS); if (n) { n[1].e = target; n[2].i = level; @@ -4800,7 +4495,8 @@ save_CompressedTexSubImage3DARB(GLenum target, GLint level, GLint xoffset, n[8].i = (GLint) depth; n[9].e = format; n[10].i = imageSize; - n[11].data = copy_data(data, imageSize, "glCompressedTexSubImage3DARB"); + save_pointer(&n[11], + copy_data(data, imageSize, "glCompressedTexSubImage3DARB")); } if (ctx->ExecuteFlag) { CALL_CompressedTexSubImage3D(ctx->Exec, @@ -5098,7 +4794,7 @@ save_ProgramStringARB(GLenum target, GLenum format, GLsizei len, ASSERT_OUTSIDE_SAVE_BEGIN_END_AND_FLUSH(ctx); - n = alloc_instruction(ctx, OPCODE_PROGRAM_STRING_ARB, 4); + n = alloc_instruction(ctx, OPCODE_PROGRAM_STRING_ARB, 3 + POINTER_DWORDS); if (n) { GLubyte *programCopy = malloc(len); if (!programCopy) { @@ -5109,7 +4805,7 @@ save_ProgramStringARB(GLenum target, GLenum format, GLsizei len, n[1].e = target; n[2].e = format; n[3].i = len; - n[4].data = programCopy; + save_pointer(&n[4], programCopy); } if (ctx->ExecuteFlag) { CALL_ProgramStringARB(ctx->Exec, (target, format, len, string)); @@ -6284,28 +5980,17 @@ save_Uniform4fARB(GLint location, GLfloat x, GLfloat y, GLfloat z, GLfloat w) } -/** Return copy of memory */ -static void * -memdup(const void *src, GLsizei bytes) -{ - void *b = bytes >= 0 ? malloc(bytes) : NULL; - if (b) - memcpy(b, src, bytes); - return b; -} - - static void GLAPIENTRY save_Uniform1fvARB(GLint location, GLsizei count, const GLfloat *v) { GET_CURRENT_CONTEXT(ctx); Node *n; ASSERT_OUTSIDE_SAVE_BEGIN_END_AND_FLUSH(ctx); - n = alloc_instruction(ctx, OPCODE_UNIFORM_1FV, 3); + n = alloc_instruction(ctx, OPCODE_UNIFORM_1FV, 2 + POINTER_DWORDS); if (n) { n[1].i = location; n[2].i = count; - n[3].data = memdup(v, count * 1 * sizeof(GLfloat)); + save_pointer(&n[3], memdup(v, count * 1 * sizeof(GLfloat))); } if (ctx->ExecuteFlag) { CALL_Uniform1fv(ctx->Exec, (location, count, v)); @@ -6318,11 +6003,11 @@ save_Uniform2fvARB(GLint location, GLsizei count, const GLfloat *v) GET_CURRENT_CONTEXT(ctx); Node *n; ASSERT_OUTSIDE_SAVE_BEGIN_END_AND_FLUSH(ctx); - n = alloc_instruction(ctx, OPCODE_UNIFORM_2FV, 3); + n = alloc_instruction(ctx, OPCODE_UNIFORM_2FV, 2 + POINTER_DWORDS); if (n) { n[1].i = location; n[2].i = count; - n[3].data = memdup(v, count * 2 * sizeof(GLfloat)); + save_pointer(&n[3], memdup(v, count * 2 * sizeof(GLfloat))); } if (ctx->ExecuteFlag) { CALL_Uniform2fv(ctx->Exec, (location, count, v)); @@ -6335,11 +6020,11 @@ save_Uniform3fvARB(GLint location, GLsizei count, const GLfloat *v) GET_CURRENT_CONTEXT(ctx); Node *n; ASSERT_OUTSIDE_SAVE_BEGIN_END_AND_FLUSH(ctx); - n = alloc_instruction(ctx, OPCODE_UNIFORM_3FV, 3); + n = alloc_instruction(ctx, OPCODE_UNIFORM_3FV, 2 + POINTER_DWORDS); if (n) { n[1].i = location; n[2].i = count; - n[3].data = memdup(v, count * 3 * sizeof(GLfloat)); + save_pointer(&n[3], memdup(v, count * 3 * sizeof(GLfloat))); } if (ctx->ExecuteFlag) { CALL_Uniform3fv(ctx->Exec, (location, count, v)); @@ -6352,11 +6037,11 @@ save_Uniform4fvARB(GLint location, GLsizei count, const GLfloat *v) GET_CURRENT_CONTEXT(ctx); Node *n; ASSERT_OUTSIDE_SAVE_BEGIN_END_AND_FLUSH(ctx); - n = alloc_instruction(ctx, OPCODE_UNIFORM_4FV, 3); + n = alloc_instruction(ctx, OPCODE_UNIFORM_4FV, 2 + POINTER_DWORDS); if (n) { n[1].i = location; n[2].i = count; - n[3].data = memdup(v, count * 4 * sizeof(GLfloat)); + save_pointer(&n[3], memdup(v, count * 4 * sizeof(GLfloat))); } if (ctx->ExecuteFlag) { CALL_Uniform4fv(ctx->Exec, (location, count, v)); @@ -6442,11 +6127,11 @@ save_Uniform1ivARB(GLint location, GLsizei count, const GLint *v) GET_CURRENT_CONTEXT(ctx); Node *n; ASSERT_OUTSIDE_SAVE_BEGIN_END_AND_FLUSH(ctx); - n = alloc_instruction(ctx, OPCODE_UNIFORM_1IV, 3); + n = alloc_instruction(ctx, OPCODE_UNIFORM_1IV, 2 + POINTER_DWORDS); if (n) { n[1].i = location; n[2].i = count; - n[3].data = memdup(v, count * 1 * sizeof(GLint)); + save_pointer(&n[3], memdup(v, count * 1 * sizeof(GLint))); } if (ctx->ExecuteFlag) { CALL_Uniform1iv(ctx->Exec, (location, count, v)); @@ -6459,11 +6144,11 @@ save_Uniform2ivARB(GLint location, GLsizei count, const GLint *v) GET_CURRENT_CONTEXT(ctx); Node *n; ASSERT_OUTSIDE_SAVE_BEGIN_END_AND_FLUSH(ctx); - n = alloc_instruction(ctx, OPCODE_UNIFORM_2IV, 3); + n = alloc_instruction(ctx, OPCODE_UNIFORM_2IV, 2 + POINTER_DWORDS); if (n) { n[1].i = location; n[2].i = count; - n[3].data = memdup(v, count * 2 * sizeof(GLint)); + save_pointer(&n[3], memdup(v, count * 2 * sizeof(GLint))); } if (ctx->ExecuteFlag) { CALL_Uniform2iv(ctx->Exec, (location, count, v)); @@ -6476,11 +6161,11 @@ save_Uniform3ivARB(GLint location, GLsizei count, const GLint *v) GET_CURRENT_CONTEXT(ctx); Node *n; ASSERT_OUTSIDE_SAVE_BEGIN_END_AND_FLUSH(ctx); - n = alloc_instruction(ctx, OPCODE_UNIFORM_3IV, 3); + n = alloc_instruction(ctx, OPCODE_UNIFORM_3IV, 2 + POINTER_DWORDS); if (n) { n[1].i = location; n[2].i = count; - n[3].data = memdup(v, count * 3 * sizeof(GLint)); + save_pointer(&n[3], memdup(v, count * 3 * sizeof(GLint))); } if (ctx->ExecuteFlag) { CALL_Uniform3iv(ctx->Exec, (location, count, v)); @@ -6493,11 +6178,11 @@ save_Uniform4ivARB(GLint location, GLsizei count, const GLint *v) GET_CURRENT_CONTEXT(ctx); Node *n; ASSERT_OUTSIDE_SAVE_BEGIN_END_AND_FLUSH(ctx); - n = alloc_instruction(ctx, OPCODE_UNIFORM_4IV, 3); + n = alloc_instruction(ctx, OPCODE_UNIFORM_4IV, 2 + POINTER_DWORDS); if (n) { n[1].i = location; n[2].i = count; - n[3].data = memdup(v, count * 4 * sizeof(GLfloat)); + save_pointer(&n[3], memdup(v, count * 4 * sizeof(GLfloat))); } if (ctx->ExecuteFlag) { CALL_Uniform4iv(ctx->Exec, (location, count, v)); @@ -6584,11 +6269,11 @@ save_Uniform1uiv(GLint location, GLsizei count, const GLuint *v) GET_CURRENT_CONTEXT(ctx); Node *n; ASSERT_OUTSIDE_SAVE_BEGIN_END_AND_FLUSH(ctx); - n = alloc_instruction(ctx, OPCODE_UNIFORM_1UIV, 3); + n = alloc_instruction(ctx, OPCODE_UNIFORM_1UIV, 2 + POINTER_DWORDS); if (n) { n[1].i = location; n[2].i = count; - n[3].data = memdup(v, count * 1 * sizeof(*v)); + save_pointer(&n[3], memdup(v, count * 1 * sizeof(*v))); } if (ctx->ExecuteFlag) { /*CALL_Uniform1uiv(ctx->Exec, (location, count, v));*/ @@ -6601,11 +6286,11 @@ save_Uniform2uiv(GLint location, GLsizei count, const GLuint *v) GET_CURRENT_CONTEXT(ctx); Node *n; ASSERT_OUTSIDE_SAVE_BEGIN_END_AND_FLUSH(ctx); - n = alloc_instruction(ctx, OPCODE_UNIFORM_2UIV, 3); + n = alloc_instruction(ctx, OPCODE_UNIFORM_2UIV, 2 + POINTER_DWORDS); if (n) { n[1].i = location; n[2].i = count; - n[3].data = memdup(v, count * 2 * sizeof(*v)); + save_pointer(&n[3], memdup(v, count * 2 * sizeof(*v))); } if (ctx->ExecuteFlag) { /*CALL_Uniform2uiv(ctx->Exec, (location, count, v));*/ @@ -6618,11 +6303,11 @@ save_Uniform3uiv(GLint location, GLsizei count, const GLuint *v) GET_CURRENT_CONTEXT(ctx); Node *n; ASSERT_OUTSIDE_SAVE_BEGIN_END_AND_FLUSH(ctx); - n = alloc_instruction(ctx, OPCODE_UNIFORM_3UIV, 3); + n = alloc_instruction(ctx, OPCODE_UNIFORM_3UIV, 2 + POINTER_DWORDS); if (n) { n[1].i = location; n[2].i = count; - n[3].data = memdup(v, count * 3 * sizeof(*v)); + save_pointer(&n[3], memdup(v, count * 3 * sizeof(*v))); } if (ctx->ExecuteFlag) { /*CALL_Uniform3uiv(ctx->Exec, (location, count, v));*/ @@ -6635,11 +6320,11 @@ save_Uniform4uiv(GLint location, GLsizei count, const GLuint *v) GET_CURRENT_CONTEXT(ctx); Node *n; ASSERT_OUTSIDE_SAVE_BEGIN_END_AND_FLUSH(ctx); - n = alloc_instruction(ctx, OPCODE_UNIFORM_4UIV, 3); + n = alloc_instruction(ctx, OPCODE_UNIFORM_4UIV, 2 + POINTER_DWORDS); if (n) { n[1].i = location; n[2].i = count; - n[3].data = memdup(v, count * 4 * sizeof(*v)); + save_pointer(&n[3], memdup(v, count * 4 * sizeof(*v))); } if (ctx->ExecuteFlag) { /*CALL_Uniform4uiv(ctx->Exec, (location, count, v));*/ @@ -6655,12 +6340,12 @@ save_UniformMatrix2fvARB(GLint location, GLsizei count, GLboolean transpose, GET_CURRENT_CONTEXT(ctx); Node *n; ASSERT_OUTSIDE_SAVE_BEGIN_END_AND_FLUSH(ctx); - n = alloc_instruction(ctx, OPCODE_UNIFORM_MATRIX22, 4); + n = alloc_instruction(ctx, OPCODE_UNIFORM_MATRIX22, 3 + POINTER_DWORDS); if (n) { n[1].i = location; n[2].i = count; n[3].b = transpose; - n[4].data = memdup(m, count * 2 * 2 * sizeof(GLfloat)); + save_pointer(&n[4], memdup(m, count * 2 * 2 * sizeof(GLfloat))); } if (ctx->ExecuteFlag) { CALL_UniformMatrix2fv(ctx->Exec, (location, count, transpose, m)); @@ -6674,12 +6359,12 @@ save_UniformMatrix3fvARB(GLint location, GLsizei count, GLboolean transpose, GET_CURRENT_CONTEXT(ctx); Node *n; ASSERT_OUTSIDE_SAVE_BEGIN_END_AND_FLUSH(ctx); - n = alloc_instruction(ctx, OPCODE_UNIFORM_MATRIX33, 4); + n = alloc_instruction(ctx, OPCODE_UNIFORM_MATRIX33, 3 + POINTER_DWORDS); if (n) { n[1].i = location; n[2].i = count; n[3].b = transpose; - n[4].data = memdup(m, count * 3 * 3 * sizeof(GLfloat)); + save_pointer(&n[4], memdup(m, count * 3 * 3 * sizeof(GLfloat))); } if (ctx->ExecuteFlag) { CALL_UniformMatrix3fv(ctx->Exec, (location, count, transpose, m)); @@ -6693,12 +6378,12 @@ save_UniformMatrix4fvARB(GLint location, GLsizei count, GLboolean transpose, GET_CURRENT_CONTEXT(ctx); Node *n; ASSERT_OUTSIDE_SAVE_BEGIN_END_AND_FLUSH(ctx); - n = alloc_instruction(ctx, OPCODE_UNIFORM_MATRIX44, 4); + n = alloc_instruction(ctx, OPCODE_UNIFORM_MATRIX44, 3 + POINTER_DWORDS); if (n) { n[1].i = location; n[2].i = count; n[3].b = transpose; - n[4].data = memdup(m, count * 4 * 4 * sizeof(GLfloat)); + save_pointer(&n[4], memdup(m, count * 4 * 4 * sizeof(GLfloat))); } if (ctx->ExecuteFlag) { CALL_UniformMatrix4fv(ctx->Exec, (location, count, transpose, m)); @@ -6713,12 +6398,12 @@ save_UniformMatrix2x3fv(GLint location, GLsizei count, GLboolean transpose, GET_CURRENT_CONTEXT(ctx); Node *n; ASSERT_OUTSIDE_SAVE_BEGIN_END_AND_FLUSH(ctx); - n = alloc_instruction(ctx, OPCODE_UNIFORM_MATRIX23, 4); + n = alloc_instruction(ctx, OPCODE_UNIFORM_MATRIX23, 3 + POINTER_DWORDS); if (n) { n[1].i = location; n[2].i = count; n[3].b = transpose; - n[4].data = memdup(m, count * 2 * 3 * sizeof(GLfloat)); + save_pointer(&n[4], memdup(m, count * 2 * 3 * sizeof(GLfloat))); } if (ctx->ExecuteFlag) { CALL_UniformMatrix2x3fv(ctx->Exec, (location, count, transpose, m)); @@ -6732,12 +6417,12 @@ save_UniformMatrix3x2fv(GLint location, GLsizei count, GLboolean transpose, GET_CURRENT_CONTEXT(ctx); Node *n; ASSERT_OUTSIDE_SAVE_BEGIN_END_AND_FLUSH(ctx); - n = alloc_instruction(ctx, OPCODE_UNIFORM_MATRIX32, 4); + n = alloc_instruction(ctx, OPCODE_UNIFORM_MATRIX32, 3 + POINTER_DWORDS); if (n) { n[1].i = location; n[2].i = count; n[3].b = transpose; - n[4].data = memdup(m, count * 3 * 2 * sizeof(GLfloat)); + save_pointer(&n[4], memdup(m, count * 3 * 2 * sizeof(GLfloat))); } if (ctx->ExecuteFlag) { CALL_UniformMatrix3x2fv(ctx->Exec, (location, count, transpose, m)); @@ -6752,12 +6437,12 @@ save_UniformMatrix2x4fv(GLint location, GLsizei count, GLboolean transpose, GET_CURRENT_CONTEXT(ctx); Node *n; ASSERT_OUTSIDE_SAVE_BEGIN_END_AND_FLUSH(ctx); - n = alloc_instruction(ctx, OPCODE_UNIFORM_MATRIX24, 4); + n = alloc_instruction(ctx, OPCODE_UNIFORM_MATRIX24, 3 + POINTER_DWORDS); if (n) { n[1].i = location; n[2].i = count; n[3].b = transpose; - n[4].data = memdup(m, count * 2 * 4 * sizeof(GLfloat)); + save_pointer(&n[4], memdup(m, count * 2 * 4 * sizeof(GLfloat))); } if (ctx->ExecuteFlag) { CALL_UniformMatrix2x4fv(ctx->Exec, (location, count, transpose, m)); @@ -6771,12 +6456,12 @@ save_UniformMatrix4x2fv(GLint location, GLsizei count, GLboolean transpose, GET_CURRENT_CONTEXT(ctx); Node *n; ASSERT_OUTSIDE_SAVE_BEGIN_END_AND_FLUSH(ctx); - n = alloc_instruction(ctx, OPCODE_UNIFORM_MATRIX42, 4); + n = alloc_instruction(ctx, OPCODE_UNIFORM_MATRIX42, 3 + POINTER_DWORDS); if (n) { n[1].i = location; n[2].i = count; n[3].b = transpose; - n[4].data = memdup(m, count * 4 * 2 * sizeof(GLfloat)); + save_pointer(&n[4], memdup(m, count * 4 * 2 * sizeof(GLfloat))); } if (ctx->ExecuteFlag) { CALL_UniformMatrix4x2fv(ctx->Exec, (location, count, transpose, m)); @@ -6791,12 +6476,12 @@ save_UniformMatrix3x4fv(GLint location, GLsizei count, GLboolean transpose, GET_CURRENT_CONTEXT(ctx); Node *n; ASSERT_OUTSIDE_SAVE_BEGIN_END_AND_FLUSH(ctx); - n = alloc_instruction(ctx, OPCODE_UNIFORM_MATRIX34, 4); + n = alloc_instruction(ctx, OPCODE_UNIFORM_MATRIX34, 3 + POINTER_DWORDS); if (n) { n[1].i = location; n[2].i = count; n[3].b = transpose; - n[4].data = memdup(m, count * 3 * 4 * sizeof(GLfloat)); + save_pointer(&n[4], memdup(m, count * 3 * 4 * sizeof(GLfloat))); } if (ctx->ExecuteFlag) { CALL_UniformMatrix3x4fv(ctx->Exec, (location, count, transpose, m)); @@ -6810,12 +6495,12 @@ save_UniformMatrix4x3fv(GLint location, GLsizei count, GLboolean transpose, GET_CURRENT_CONTEXT(ctx); Node *n; ASSERT_OUTSIDE_SAVE_BEGIN_END_AND_FLUSH(ctx); - n = alloc_instruction(ctx, OPCODE_UNIFORM_MATRIX43, 4); + n = alloc_instruction(ctx, OPCODE_UNIFORM_MATRIX43, 3 + POINTER_DWORDS); if (n) { n[1].i = location; n[2].i = count; n[3].b = transpose; - n[4].data = memdup(m, count * 4 * 3 * sizeof(GLfloat)); + save_pointer(&n[4], memdup(m, count * 4 * 3 * sizeof(GLfloat))); } if (ctx->ExecuteFlag) { CALL_UniformMatrix4x3fv(ctx->Exec, (location, count, transpose, m)); @@ -7185,10 +6870,10 @@ save_WaitSync(GLsync sync, GLbitfield flags, GLuint64 timeout) if (n) { union uint64_pair p; p.uint64 = timeout; - n[1].data = sync; - n[2].e = flags; - n[3].ui = p.uint32[0]; - n[4].ui = p.uint32[1]; + n[1].bf = flags; + n[2].ui = p.uint32[0]; + n[3].ui = p.uint32[1]; + save_pointer(&n[4], sync); } if (ctx->ExecuteFlag) { CALL_WaitSync(ctx->Exec, (sync, flags, timeout)); @@ -7252,10 +6937,14 @@ static void save_error(struct gl_context *ctx, GLenum error, const char *s) { Node *n; - n = alloc_instruction(ctx, OPCODE_ERROR, 2); + n = alloc_instruction(ctx, OPCODE_ERROR, 1 + POINTER_DWORDS); if (n) { n[1].e = error; - n[2].data = (void *) s; + save_pointer(&n[2], (void *) s); + /* note: the data/string here doesn't have to be freed in + * _mesa_delete_list() since the string is never dynamically + * allocated. + */ } } @@ -7336,7 +7025,7 @@ execute_list(struct gl_context *ctx, GLuint list) else { switch (opcode) { case OPCODE_ERROR: - _mesa_error(ctx, n[1].e, "%s", (const char *) n[2].data); + _mesa_error(ctx, n[1].e, "%s", (const char *) get_pointer(&n[2])); break; case OPCODE_ACCUM: CALL_Accum(ctx->Exec, (n[1].e, n[2].f)); @@ -7353,7 +7042,7 @@ execute_list(struct gl_context *ctx, GLuint list) ctx->Unpack = ctx->DefaultPacking; CALL_Bitmap(ctx->Exec, ((GLsizei) n[1].i, (GLsizei) n[2].i, n[3].f, n[4].f, n[5].f, n[6].f, - (const GLubyte *) n[7].data)); + get_pointer(&n[7]))); ctx->Unpack = save; /* restore */ } break; @@ -7478,102 +7167,6 @@ execute_list(struct gl_context *ctx, GLuint list) case OPCODE_COLOR_MATERIAL: CALL_ColorMaterial(ctx->Exec, (n[1].e, n[2].e)); break; - case OPCODE_COLOR_TABLE: - { - const struct gl_pixelstore_attrib save = ctx->Unpack; - ctx->Unpack = ctx->DefaultPacking; - CALL_ColorTable(ctx->Exec, (n[1].e, n[2].e, n[3].i, n[4].e, - n[5].e, n[6].data)); - ctx->Unpack = save; /* restore */ - } - break; - case OPCODE_COLOR_TABLE_PARAMETER_FV: - { - GLfloat params[4]; - params[0] = n[3].f; - params[1] = n[4].f; - params[2] = n[5].f; - params[3] = n[6].f; - CALL_ColorTableParameterfv(ctx->Exec, - (n[1].e, n[2].e, params)); - } - break; - case OPCODE_COLOR_TABLE_PARAMETER_IV: - { - GLint params[4]; - params[0] = n[3].i; - params[1] = n[4].i; - params[2] = n[5].i; - params[3] = n[6].i; - CALL_ColorTableParameteriv(ctx->Exec, - (n[1].e, n[2].e, params)); - } - break; - case OPCODE_COLOR_SUB_TABLE: - { - const struct gl_pixelstore_attrib save = ctx->Unpack; - ctx->Unpack = ctx->DefaultPacking; - CALL_ColorSubTable(ctx->Exec, (n[1].e, n[2].i, n[3].i, - n[4].e, n[5].e, n[6].data)); - ctx->Unpack = save; /* restore */ - } - break; - case OPCODE_CONVOLUTION_FILTER_1D: - { - const struct gl_pixelstore_attrib save = ctx->Unpack; - ctx->Unpack = ctx->DefaultPacking; - CALL_ConvolutionFilter1D(ctx->Exec, (n[1].e, n[2].i, n[3].i, - n[4].e, n[5].e, - n[6].data)); - ctx->Unpack = save; /* restore */ - } - break; - case OPCODE_CONVOLUTION_FILTER_2D: - { - const struct gl_pixelstore_attrib save = ctx->Unpack; - ctx->Unpack = ctx->DefaultPacking; - CALL_ConvolutionFilter2D(ctx->Exec, (n[1].e, n[2].i, n[3].i, - n[4].i, n[5].e, n[6].e, - n[7].data)); - ctx->Unpack = save; /* restore */ - } - break; - case OPCODE_CONVOLUTION_PARAMETER_I: - CALL_ConvolutionParameteri(ctx->Exec, (n[1].e, n[2].e, n[3].i)); - break; - case OPCODE_CONVOLUTION_PARAMETER_IV: - { - GLint params[4]; - params[0] = n[3].i; - params[1] = n[4].i; - params[2] = n[5].i; - params[3] = n[6].i; - CALL_ConvolutionParameteriv(ctx->Exec, - (n[1].e, n[2].e, params)); - } - break; - case OPCODE_CONVOLUTION_PARAMETER_F: - CALL_ConvolutionParameterf(ctx->Exec, (n[1].e, n[2].e, n[3].f)); - break; - case OPCODE_CONVOLUTION_PARAMETER_FV: - { - GLfloat params[4]; - params[0] = n[3].f; - params[1] = n[4].f; - params[2] = n[5].f; - params[3] = n[6].f; - CALL_ConvolutionParameterfv(ctx->Exec, - (n[1].e, n[2].e, params)); - } - break; - case OPCODE_COPY_COLOR_SUB_TABLE: - CALL_CopyColorSubTable(ctx->Exec, (n[1].e, n[2].i, - n[3].i, n[4].i, n[5].i)); - break; - case OPCODE_COPY_COLOR_TABLE: - CALL_CopyColorSubTable(ctx->Exec, (n[1].e, n[2].i, - n[3].i, n[4].i, n[5].i)); - break; case OPCODE_COPY_PIXELS: CALL_CopyPixels(ctx->Exec, (n[1].i, n[2].i, (GLsizei) n[3].i, (GLsizei) n[4].i, @@ -7628,7 +7221,7 @@ execute_list(struct gl_context *ctx, GLuint list) const struct gl_pixelstore_attrib save = ctx->Unpack; ctx->Unpack = ctx->DefaultPacking; CALL_DrawPixels(ctx->Exec, (n[1].i, n[2].i, n[3].e, n[4].e, - n[5].data)); + get_pointer(&n[5]))); ctx->Unpack = save; /* restore */ } break; @@ -7665,9 +7258,6 @@ execute_list(struct gl_context *ctx, GLuint list) case OPCODE_HINT: CALL_Hint(ctx->Exec, (n[1].e, n[2].e)); break; - case OPCODE_HISTOGRAM: - CALL_Histogram(ctx->Exec, (n[1].e, n[2].i, n[3].e, n[4].b)); - break; case OPCODE_INDEX_MASK: CALL_IndexMask(ctx->Exec, (n[1].ui)); break; @@ -7733,7 +7323,7 @@ execute_list(struct gl_context *ctx, GLuint list) GLfloat u1 = n[2].f; GLfloat u2 = n[3].f; CALL_Map1f(ctx->Exec, (target, u1, u2, ustride, uorder, - (GLfloat *) n[6].data)); + (GLfloat *) get_pointer(&n[6]))); } break; case OPCODE_MAP2: @@ -7749,7 +7339,7 @@ execute_list(struct gl_context *ctx, GLuint list) GLint vorder = n[9].i; CALL_Map2f(ctx->Exec, (target, u1, u2, ustride, uorder, v1, v2, vstride, vorder, - (GLfloat *) n[10].data)); + (GLfloat *) get_pointer(&n[10]))); } break; case OPCODE_MAPGRID1: @@ -7762,9 +7352,6 @@ execute_list(struct gl_context *ctx, GLuint list) case OPCODE_MATRIX_MODE: CALL_MatrixMode(ctx->Exec, (n[1].e)); break; - case OPCODE_MIN_MAX: - CALL_Minmax(ctx->Exec, (n[1].e, n[2].e, n[3].b)); - break; case OPCODE_MULT_MATRIX: if (sizeof(Node) == sizeof(GLfloat)) { CALL_MultMatrixf(ctx->Exec, (&n[1].f)); @@ -7787,7 +7374,7 @@ execute_list(struct gl_context *ctx, GLuint list) break; case OPCODE_PIXEL_MAP: CALL_PixelMapfv(ctx->Exec, - (n[1].e, n[2].i, (GLfloat *) n[3].data)); + (n[1].e, n[2].i, get_pointer(&n[3]))); break; case OPCODE_PIXEL_TRANSFER: CALL_PixelTransferf(ctx->Exec, (n[1].e, n[2].f)); @@ -7814,7 +7401,7 @@ execute_list(struct gl_context *ctx, GLuint list) { const struct gl_pixelstore_attrib save = ctx->Unpack; ctx->Unpack = ctx->DefaultPacking; - CALL_PolygonStipple(ctx->Exec, ((GLubyte *) n[1].data)); + CALL_PolygonStipple(ctx->Exec, (get_pointer(&n[1]))); ctx->Unpack = save; /* restore */ } break; @@ -7848,12 +7435,6 @@ execute_list(struct gl_context *ctx, GLuint list) case OPCODE_READ_BUFFER: CALL_ReadBuffer(ctx->Exec, (n[1].e)); break; - case OPCODE_RESET_HISTOGRAM: - CALL_ResetHistogram(ctx->Exec, (n[1].e)); - break; - case OPCODE_RESET_MIN_MAX: - CALL_ResetMinmax(ctx->Exec, (n[1].e)); - break; case OPCODE_ROTATE: CALL_Rotatef(ctx->Exec, (n[1].f, n[2].f, n[3].f, n[4].f)); break; @@ -7930,7 +7511,7 @@ execute_list(struct gl_context *ctx, GLuint list) n[5].e, /* border */ n[6].e, /* format */ n[7].e, /* type */ - n[8].data)); + get_pointer(&n[8]))); ctx->Unpack = save; /* restore */ } break; @@ -7946,7 +7527,7 @@ execute_list(struct gl_context *ctx, GLuint list) n[6].e, /* border */ n[7].e, /* format */ n[8].e, /* type */ - n[9].data)); + get_pointer(&n[9]))); ctx->Unpack = save; /* restore */ } break; @@ -7963,7 +7544,7 @@ execute_list(struct gl_context *ctx, GLuint list) n[7].e, /* border */ n[8].e, /* format */ n[9].e, /* type */ - n[10].data)); + get_pointer(&n[10]))); ctx->Unpack = save; /* restore */ } break; @@ -7973,7 +7554,7 @@ execute_list(struct gl_context *ctx, GLuint list) ctx->Unpack = ctx->DefaultPacking; CALL_TexSubImage1D(ctx->Exec, (n[1].e, n[2].i, n[3].i, n[4].i, n[5].e, - n[6].e, n[7].data)); + n[6].e, get_pointer(&n[7]))); ctx->Unpack = save; /* restore */ } break; @@ -7984,7 +7565,7 @@ execute_list(struct gl_context *ctx, GLuint list) CALL_TexSubImage2D(ctx->Exec, (n[1].e, n[2].i, n[3].i, n[4].i, n[5].e, n[6].i, n[7].e, n[8].e, - n[9].data)); + get_pointer(&n[9]))); ctx->Unpack = save; /* restore */ } break; @@ -7995,7 +7576,7 @@ execute_list(struct gl_context *ctx, GLuint list) CALL_TexSubImage3D(ctx->Exec, (n[1].e, n[2].i, n[3].i, n[4].i, n[5].i, n[6].i, n[7].i, n[8].i, n[9].e, n[10].e, - n[11].data)); + get_pointer(&n[11]))); ctx->Unpack = save; /* restore */ } break; @@ -8014,36 +7595,38 @@ execute_list(struct gl_context *ctx, GLuint list) break; case OPCODE_COMPRESSED_TEX_IMAGE_1D: /* GL_ARB_texture_compression */ CALL_CompressedTexImage1D(ctx->Exec, (n[1].e, n[2].i, n[3].e, - n[4].i, n[5].i, n[6].i, - n[7].data)); + n[4].i, n[5].i, n[6].i, + get_pointer(&n[7]))); break; case OPCODE_COMPRESSED_TEX_IMAGE_2D: /* GL_ARB_texture_compression */ CALL_CompressedTexImage2D(ctx->Exec, (n[1].e, n[2].i, n[3].e, - n[4].i, n[5].i, n[6].i, - n[7].i, n[8].data)); + n[4].i, n[5].i, n[6].i, + n[7].i, get_pointer(&n[8]))); break; case OPCODE_COMPRESSED_TEX_IMAGE_3D: /* GL_ARB_texture_compression */ CALL_CompressedTexImage3D(ctx->Exec, (n[1].e, n[2].i, n[3].e, - n[4].i, n[5].i, n[6].i, - n[7].i, n[8].i, - n[9].data)); + n[4].i, n[5].i, n[6].i, + n[7].i, n[8].i, + get_pointer(&n[9]))); break; case OPCODE_COMPRESSED_TEX_SUB_IMAGE_1D: /* GL_ARB_texture_compress */ CALL_CompressedTexSubImage1D(ctx->Exec, (n[1].e, n[2].i, n[3].i, n[4].i, - n[5].e, n[6].i, n[7].data)); + n[5].e, n[6].i, + get_pointer(&n[7]))); break; case OPCODE_COMPRESSED_TEX_SUB_IMAGE_2D: /* GL_ARB_texture_compress */ CALL_CompressedTexSubImage2D(ctx->Exec, (n[1].e, n[2].i, n[3].i, n[4].i, n[5].i, n[6].i, n[7].e, n[8].i, - n[9].data)); + get_pointer(&n[9]))); break; case OPCODE_COMPRESSED_TEX_SUB_IMAGE_3D: /* GL_ARB_texture_compress */ CALL_CompressedTexSubImage3D(ctx->Exec, (n[1].e, n[2].i, n[3].i, n[4].i, n[5].i, n[6].i, n[7].i, n[8].i, - n[9].e, n[10].i, n[11].data)); + n[9].e, n[10].i, + get_pointer(&n[11]))); break; case OPCODE_SAMPLE_COVERAGE: /* GL_ARB_multisample */ CALL_SampleCoverage(ctx->Exec, (n[1].f, n[2].b)); @@ -8067,7 +7650,8 @@ execute_list(struct gl_context *ctx, GLuint list) break; case OPCODE_PROGRAM_STRING_ARB: CALL_ProgramStringARB(ctx->Exec, - (n[1].e, n[2].e, n[3].i, n[4].data)); + (n[1].e, n[2].e, n[3].i, + get_pointer(&n[4]))); break; case OPCODE_PROGRAM_ENV_PARAMETER_ARB: CALL_ProgramEnvParameter4fARB(ctx->Exec, (n[1].e, n[2].ui, n[3].f, @@ -8126,16 +7710,16 @@ execute_list(struct gl_context *ctx, GLuint list) (n[1].i, n[2].f, n[3].f, n[4].f, n[5].f)); break; case OPCODE_UNIFORM_1FV: - CALL_Uniform1fv(ctx->Exec, (n[1].i, n[2].i, n[3].data)); + CALL_Uniform1fv(ctx->Exec, (n[1].i, n[2].i, get_pointer(&n[3]))); break; case OPCODE_UNIFORM_2FV: - CALL_Uniform2fv(ctx->Exec, (n[1].i, n[2].i, n[3].data)); + CALL_Uniform2fv(ctx->Exec, (n[1].i, n[2].i, get_pointer(&n[3]))); break; case OPCODE_UNIFORM_3FV: - CALL_Uniform3fv(ctx->Exec, (n[1].i, n[2].i, n[3].data)); + CALL_Uniform3fv(ctx->Exec, (n[1].i, n[2].i, get_pointer(&n[3]))); break; case OPCODE_UNIFORM_4FV: - CALL_Uniform4fv(ctx->Exec, (n[1].i, n[2].i, n[3].data)); + CALL_Uniform4fv(ctx->Exec, (n[1].i, n[2].i, get_pointer(&n[3]))); break; case OPCODE_UNIFORM_1I: CALL_Uniform1i(ctx->Exec, (n[1].i, n[2].i)); @@ -8151,16 +7735,16 @@ execute_list(struct gl_context *ctx, GLuint list) (n[1].i, n[2].i, n[3].i, n[4].i, n[5].i)); break; case OPCODE_UNIFORM_1IV: - CALL_Uniform1iv(ctx->Exec, (n[1].i, n[2].i, n[3].data)); + CALL_Uniform1iv(ctx->Exec, (n[1].i, n[2].i, get_pointer(&n[3]))); break; case OPCODE_UNIFORM_2IV: - CALL_Uniform2iv(ctx->Exec, (n[1].i, n[2].i, n[3].data)); + CALL_Uniform2iv(ctx->Exec, (n[1].i, n[2].i, get_pointer(&n[3]))); break; case OPCODE_UNIFORM_3IV: - CALL_Uniform3iv(ctx->Exec, (n[1].i, n[2].i, n[3].data)); + CALL_Uniform3iv(ctx->Exec, (n[1].i, n[2].i, get_pointer(&n[3]))); break; case OPCODE_UNIFORM_4IV: - CALL_Uniform4iv(ctx->Exec, (n[1].i, n[2].i, n[3].data)); + CALL_Uniform4iv(ctx->Exec, (n[1].i, n[2].i, get_pointer(&n[3]))); break; case OPCODE_UNIFORM_1UI: /*CALL_Uniform1uiARB(ctx->Exec, (n[1].i, n[2].i));*/ @@ -8177,52 +7761,56 @@ execute_list(struct gl_context *ctx, GLuint list) */ break; case OPCODE_UNIFORM_1UIV: - /*CALL_Uniform1uivARB(ctx->Exec, (n[1].i, n[2].i, n[3].data));*/ + /*CALL_Uniform1uivARB(ctx->Exec, (n[1].i, n[2].i, + get_pointer(&n[3])));*/ break; case OPCODE_UNIFORM_2UIV: - /*CALL_Uniform2uivARB(ctx->Exec, (n[1].i, n[2].i, n[3].data));*/ + /*CALL_Uniform2uivARB(ctx->Exec, (n[1].i, n[2].i, + get_pointer(&n[3])));*/ break; case OPCODE_UNIFORM_3UIV: - /*CALL_Uniform3uivARB(ctx->Exec, (n[1].i, n[2].i, n[3].data));*/ + /*CALL_Uniform3uivARB(ctx->Exec, (n[1].i, n[2].i, + get_pointer(&n[3])));*/ break; case OPCODE_UNIFORM_4UIV: - /*CALL_Uniform4uivARB(ctx->Exec, (n[1].i, n[2].i, n[3].data));*/ + /*CALL_Uniform4uivARB(ctx->Exec, (n[1].i, n[2].i, + get_pointer(&n[3])));*/ break; case OPCODE_UNIFORM_MATRIX22: CALL_UniformMatrix2fv(ctx->Exec, - (n[1].i, n[2].i, n[3].b, n[4].data)); + (n[1].i, n[2].i, n[3].b, get_pointer(&n[4]))); break; case OPCODE_UNIFORM_MATRIX33: CALL_UniformMatrix3fv(ctx->Exec, - (n[1].i, n[2].i, n[3].b, n[4].data)); + (n[1].i, n[2].i, n[3].b, get_pointer(&n[4]))); break; case OPCODE_UNIFORM_MATRIX44: CALL_UniformMatrix4fv(ctx->Exec, - (n[1].i, n[2].i, n[3].b, n[4].data)); + (n[1].i, n[2].i, n[3].b, get_pointer(&n[4]))); break; case OPCODE_UNIFORM_MATRIX23: CALL_UniformMatrix2x3fv(ctx->Exec, - (n[1].i, n[2].i, n[3].b, n[4].data)); + (n[1].i, n[2].i, n[3].b, get_pointer(&n[4]))); break; case OPCODE_UNIFORM_MATRIX32: CALL_UniformMatrix3x2fv(ctx->Exec, - (n[1].i, n[2].i, n[3].b, n[4].data)); + (n[1].i, n[2].i, n[3].b, get_pointer(&n[4]))); break; case OPCODE_UNIFORM_MATRIX24: CALL_UniformMatrix2x4fv(ctx->Exec, - (n[1].i, n[2].i, n[3].b, n[4].data)); + (n[1].i, n[2].i, n[3].b, get_pointer(&n[4]))); break; case OPCODE_UNIFORM_MATRIX42: CALL_UniformMatrix4x2fv(ctx->Exec, - (n[1].i, n[2].i, n[3].b, n[4].data)); + (n[1].i, n[2].i, n[3].b, get_pointer(&n[4]))); break; case OPCODE_UNIFORM_MATRIX34: CALL_UniformMatrix3x4fv(ctx->Exec, - (n[1].i, n[2].i, n[3].b, n[4].data)); + (n[1].i, n[2].i, n[3].b, get_pointer(&n[4]))); break; case OPCODE_UNIFORM_MATRIX43: CALL_UniformMatrix4x3fv(ctx->Exec, - (n[1].i, n[2].i, n[3].b, n[4].data)); + (n[1].i, n[2].i, n[3].b, get_pointer(&n[4]))); break; case OPCODE_CLAMP_COLOR: @@ -8476,9 +8064,10 @@ execute_list(struct gl_context *ctx, GLuint list) case OPCODE_WAIT_SYNC: { union uint64_pair p; - p.uint32[0] = n[3].ui; - p.uint32[1] = n[4].ui; - CALL_WaitSync(ctx->Exec, (n[1].data, n[2].bf, p.uint64)); + p.uint32[0] = n[2].ui; + p.uint32[1] = n[3].ui; + CALL_WaitSync(ctx->Exec, + (get_pointer(&n[4]), n[1].bf, p.uint64)); } break; @@ -8495,7 +8084,7 @@ execute_list(struct gl_context *ctx, GLuint list) break; case OPCODE_CONTINUE: - n = (Node *) n[1].next; + n = (Node *) get_pointer(&n[1]); break; case OPCODE_END_OF_LIST: done = GL_TRUE; @@ -8684,6 +8273,8 @@ _mesa_EndList(void) (void) alloc_instruction(ctx, OPCODE_END_OF_LIST, 0); + trim_list(ctx); + /* Destroy old list, if any */ destroy_list(ctx, ctx->ListState.CurrentList->Name); @@ -8697,6 +8288,8 @@ _mesa_EndList(void) mesa_print_display_list(ctx->ListState.CurrentList->Name); ctx->ListState.CurrentList = NULL; + ctx->ListState.CurrentBlock = NULL; + ctx->ListState.CurrentPos = 0; ctx->ExecuteFlag = GL_TRUE; ctx->CompileFlag = GL_FALSE; @@ -8998,22 +8591,6 @@ _mesa_initialize_save_table(const struct gl_context *ctx) /* Not all are supported */ SET_BlendColor(table, save_BlendColor); SET_BlendEquation(table, save_BlendEquation); - SET_ColorSubTable(table, save_ColorSubTable); - SET_ColorTable(table, save_ColorTable); - SET_ColorTableParameterfv(table, save_ColorTableParameterfv); - SET_ColorTableParameteriv(table, save_ColorTableParameteriv); - SET_ConvolutionFilter1D(table, save_ConvolutionFilter1D); - SET_ConvolutionFilter2D(table, save_ConvolutionFilter2D); - SET_ConvolutionParameterf(table, save_ConvolutionParameterf); - SET_ConvolutionParameterfv(table, save_ConvolutionParameterfv); - SET_ConvolutionParameteri(table, save_ConvolutionParameteri); - SET_ConvolutionParameteriv(table, save_ConvolutionParameteriv); - SET_CopyColorSubTable(table, save_CopyColorSubTable); - SET_CopyColorTable(table, save_CopyColorTable); - SET_Histogram(table, save_Histogram); - SET_Minmax(table, save_Minmax); - SET_ResetHistogram(table, save_ResetHistogram); - SET_ResetMinmax(table, save_ResetMinmax); /* 2. GL_EXT_blend_color */ #if 0 @@ -9030,12 +8607,6 @@ _mesa_initialize_save_table(const struct gl_context *ctx) SET_TexSubImage3DEXT(table, save_TexSubImage3D); #endif - /* 14. GL_SGI_color_table */ -#if 0 - SET_ColorTableSGI(table, save_ColorTable); - SET_ColorSubTableSGI(table, save_ColorSubTable); -#endif - /* 37. GL_EXT_blend_minmax */ #if 0 SET_BlendEquationEXT(table, save_BlendEquationEXT); @@ -9332,7 +8903,8 @@ print_list(struct gl_context *ctx, GLuint list) break; case OPCODE_BITMAP: printf("Bitmap %d %d %g %g %g %g %p\n", n[1].i, n[2].i, - n[3].f, n[4].f, n[5].f, n[6].f, (void *) n[7].data); + n[3].f, n[4].f, n[5].f, n[6].f, + get_pointer(&n[7])); break; case OPCODE_CALL_LIST: printf("CallList %d\n", (int) n[1].ui); @@ -9341,16 +8913,6 @@ print_list(struct gl_context *ctx, GLuint list) printf("CallList %d + offset %u = %u\n", (int) n[1].ui, ctx->List.ListBase, ctx->List.ListBase + n[1].ui); break; - case OPCODE_COLOR_TABLE_PARAMETER_FV: - printf("ColorTableParameterfv %s %s %f %f %f %f\n", - enum_string(n[1].e), enum_string(n[2].e), - n[3].f, n[4].f, n[5].f, n[6].f); - break; - case OPCODE_COLOR_TABLE_PARAMETER_IV: - printf("ColorTableParameteriv %s %s %d %d %d %d\n", - enum_string(n[1].e), enum_string(n[2].e), - n[3].i, n[4].i, n[5].i, n[6].i); - break; case OPCODE_DISABLE: printf("Disable %s\n", enum_string(n[1].e)); break; @@ -9525,12 +9087,12 @@ print_list(struct gl_context *ctx, GLuint list) * meta opcodes/commands */ case OPCODE_ERROR: - printf("Error: %s %s\n", - enum_string(n[1].e), (const char *) n[2].data); + printf("Error: %s %s\n", enum_string(n[1].e), + (const char *) get_pointer(&n[2])); break; case OPCODE_CONTINUE: printf("DISPLAY-LIST-CONTINUE\n"); - n = (Node *) n[1].next; + n = (Node *) get_pointer(&n[1]); break; case OPCODE_END_OF_LIST: printf("END-LIST %u\n", list); diff --git a/mesalib/src/mesa/main/enable.c b/mesalib/src/mesa/main/enable.c index c047f5df2..bb4a23c91 100644 --- a/mesalib/src/mesa/main/enable.c +++ b/mesalib/src/mesa/main/enable.c @@ -934,25 +934,6 @@ _mesa_set_enable(struct gl_context *ctx, GLenum cap, GLboolean state) ctx->ATIFragmentShader.Enabled = state; break; - /* GL_MESA_texture_array */ - case GL_TEXTURE_1D_ARRAY_EXT: - if (ctx->API != API_OPENGL_COMPAT) - goto invalid_enum_error; - CHECK_EXTENSION(MESA_texture_array, cap); - if (!enable_texture(ctx, state, TEXTURE_1D_ARRAY_BIT)) { - return; - } - break; - - case GL_TEXTURE_2D_ARRAY_EXT: - if (ctx->API != API_OPENGL_COMPAT) - goto invalid_enum_error; - CHECK_EXTENSION(MESA_texture_array, cap); - if (!enable_texture(ctx, state, TEXTURE_2D_ARRAY_BIT)) { - return; - } - break; - case GL_TEXTURE_CUBE_MAP_SEAMLESS: if (!_mesa_is_desktop_gl(ctx)) goto invalid_enum_error; diff --git a/mesalib/src/mesa/main/extensions.c b/mesalib/src/mesa/main/extensions.c index 42da9057c..f0e1858e4 100644 --- a/mesalib/src/mesa/main/extensions.c +++ b/mesalib/src/mesa/main/extensions.c @@ -82,6 +82,7 @@ static const struct extension extension_table[] = { { "GL_ARB_ES3_compatibility", o(ARB_ES3_compatibility), GL, 2012 }, { "GL_ARB_base_instance", o(ARB_base_instance), GL, 2011 }, { "GL_ARB_blend_func_extended", o(ARB_blend_func_extended), GL, 2009 }, + { "GL_ARB_clear_buffer_object", o(dummy_true), GL, 2012 }, { "GL_ARB_color_buffer_float", o(ARB_color_buffer_float), GL, 2004 }, { "GL_ARB_copy_buffer", o(dummy_true), GL, 2008 }, { "GL_ARB_conservative_depth", o(ARB_conservative_depth), GL, 2011 }, @@ -158,6 +159,7 @@ static const struct extension extension_table[] = { { "GL_ARB_texture_rg", o(ARB_texture_rg), GL, 2008 }, { "GL_ARB_texture_storage", o(dummy_true), GL, 2011 }, { "GL_ARB_texture_storage_multisample", o(ARB_texture_multisample), GL, 2012 }, + { "GL_ARB_texture_view", o(ARB_texture_view), GL, 2012 }, { "GL_ARB_texture_swizzle", o(EXT_texture_swizzle), GL, 2008 }, { "GL_ARB_timer_query", o(ARB_timer_query), GL, 2010 }, { "GL_ARB_transform_feedback2", o(ARB_transform_feedback2), GL, 2010 }, @@ -199,7 +201,7 @@ static const struct extension extension_table[] = { { "GL_EXT_gpu_shader4", o(EXT_gpu_shader4), GL, 2006 }, { "GL_EXT_map_buffer_range", o(ARB_map_buffer_range), ES1 | ES2, 2012 }, { "GL_EXT_multi_draw_arrays", o(dummy_true), GLL | ES1 | ES2, 1999 }, - { "GL_EXT_packed_depth_stencil", o(EXT_packed_depth_stencil), GL, 2005 }, + { "GL_EXT_packed_depth_stencil", o(dummy_true), GL, 2005 }, { "GL_EXT_packed_float", o(EXT_packed_float), GL, 2004 }, { "GL_EXT_packed_pixels", o(dummy_true), GLL, 1997 }, { "GL_EXT_pixel_buffer_object", o(EXT_pixel_buffer_object), GL, 2004 }, @@ -272,7 +274,7 @@ static const struct extension extension_table[] = { { "GL_OES_framebuffer_object", o(dummy_true), ES1, 2005 }, { "GL_OES_get_program_binary", o(dummy_true), ES2, 2008 }, { "GL_OES_mapbuffer", o(dummy_true), ES1 | ES2, 2005 }, - { "GL_OES_packed_depth_stencil", o(EXT_packed_depth_stencil), ES1 | ES2, 2007 }, + { "GL_OES_packed_depth_stencil", o(dummy_true), ES1 | ES2, 2007 }, { "GL_OES_point_size_array", o(dummy_true), ES1, 2004 }, { "GL_OES_point_sprite", o(ARB_point_sprite), ES1, 2004 }, { "GL_OES_query_matrix", o(dummy_true), ES1, 2003 }, @@ -302,7 +304,7 @@ static const struct extension extension_table[] = { { "GL_AMD_performance_monitor", o(AMD_performance_monitor), GL, 2007 }, { "GL_AMD_seamless_cubemap_per_texture", o(AMD_seamless_cubemap_per_texture), GL, 2009 }, { "GL_AMD_shader_stencil_export", o(ARB_shader_stencil_export), GL, 2009 }, - { "GL_AMD_vertex_shader_layer", o(AMD_vertex_shader_layer), GL, 2012 }, + { "GL_AMD_vertex_shader_layer", o(AMD_vertex_shader_layer), GLC, 2012 }, { "GL_APPLE_object_purgeable", o(APPLE_object_purgeable), GL, 2006 }, { "GL_APPLE_packed_pixels", o(dummy_true), GLL, 2002 }, { "GL_APPLE_texture_max_level", o(dummy_true), ES1 | ES2, 2009 }, @@ -321,7 +323,6 @@ static const struct extension extension_table[] = { { "GL_IBM_texture_mirrored_repeat", o(dummy_true), GLL, 1998 }, { "GL_INGR_blend_func_separate", o(EXT_blend_func_separate), GLL, 1999 }, { "GL_MESA_pack_invert", o(MESA_pack_invert), GL, 2002 }, - { "GL_MESA_texture_array", o(MESA_texture_array), GLL, 2007 }, { "GL_MESA_texture_signed_rgba", o(EXT_texture_snorm), GL, 2009 }, { "GL_MESA_window_pos", o(dummy_true), GLL, 2000 }, { "GL_MESA_ycbcr_texture", o(MESA_ycbcr_texture), GL, 2002 }, @@ -333,7 +334,7 @@ static const struct extension extension_table[] = { { "GL_NV_fog_distance", o(NV_fog_distance), GLL, 2001 }, { "GL_NV_fragment_program_option", o(NV_fragment_program_option), GLL, 2005 }, { "GL_NV_light_max_exponent", o(dummy_true), GLL, 1999 }, - { "GL_NV_packed_depth_stencil", o(EXT_packed_depth_stencil), GL, 2000 }, + { "GL_NV_packed_depth_stencil", o(dummy_true), GL, 2000 }, { "GL_NV_point_sprite", o(NV_point_sprite), GL, 2001 }, { "GL_NV_primitive_restart", o(NV_primitive_restart), GLL, 2002 }, { "GL_NV_read_buffer", o(dummy_true), ES2, 2011 }, @@ -436,7 +437,6 @@ _mesa_enable_sw_extensions(struct gl_context *ctx) ctx->Extensions.EXT_depth_bounds_test = GL_TRUE; ctx->Extensions.EXT_draw_buffers2 = GL_TRUE; ctx->Extensions.EXT_framebuffer_blit = GL_TRUE; - ctx->Extensions.EXT_packed_depth_stencil = GL_TRUE; ctx->Extensions.EXT_pixel_buffer_object = GL_TRUE; ctx->Extensions.EXT_point_parameters = GL_TRUE; ctx->Extensions.EXT_provoking_vertex = GL_TRUE; @@ -453,7 +453,6 @@ _mesa_enable_sw_extensions(struct gl_context *ctx) /*ctx->Extensions.EXT_transform_feedback = GL_TRUE;*/ ctx->Extensions.EXT_vertex_array_bgra = GL_TRUE; ctx->Extensions.MESA_pack_invert = GL_TRUE; - ctx->Extensions.MESA_texture_array = GL_TRUE; ctx->Extensions.MESA_ycbcr_texture = GL_TRUE; ctx->Extensions.NV_conditional_render = GL_TRUE; ctx->Extensions.NV_point_sprite = GL_TRUE; @@ -480,7 +479,8 @@ set_extension( struct gl_context *ctx, const char *name, GLboolean state ) if (ctx->Extensions.String) { /* The string was already queried - can't change it now! */ - _mesa_problem(ctx, "Trying to enable/disable extension after glGetString(GL_EXTENSIONS): %s", name); + _mesa_problem(ctx, "Trying to enable/disable extension after " + "glGetString(GL_EXTENSIONS): %s", name); return GL_FALSE; } @@ -679,10 +679,10 @@ _mesa_make_extension_string(struct gl_context *ctx) return NULL; } - /* Sort extensions in chronological order because certain old applications (e.g., - * Quake3 demo) store the extension list in a static size buffer so chronologically - * order ensure that the extensions that such applications expect will fit into - * that buffer. + /* Sort extensions in chronological order because certain old applications + * (e.g., Quake3 demo) store the extension list in a static size buffer so + * chronologically order ensure that the extensions that such applications + * expect will fit into that buffer. */ j = 0; for (i = extension_table; i->name != 0; ++i) { @@ -693,7 +693,8 @@ _mesa_make_extension_string(struct gl_context *ctx) } } assert(j == count); - qsort(extension_indices, count, sizeof *extension_indices, extension_compare); + qsort(extension_indices, count, + sizeof *extension_indices, extension_compare); /* Build the extension string.*/ for (j = 0; j < count; ++j) { diff --git a/mesalib/src/mesa/main/fbobject.c b/mesalib/src/mesa/main/fbobject.c index 861885dd3..2892784f8 100644 --- a/mesalib/src/mesa/main/fbobject.c +++ b/mesalib/src/mesa/main/fbobject.c @@ -781,9 +781,8 @@ test_attachment_completeness(const struct gl_context *ctx, GLenum format, if (baseFormat == GL_DEPTH_COMPONENT) { /* OK */ } - else if (ctx->Extensions.EXT_packed_depth_stencil && - ctx->Extensions.ARB_depth_texture && - baseFormat == GL_DEPTH_STENCIL_EXT) { + else if (ctx->Extensions.ARB_depth_texture && + baseFormat == GL_DEPTH_STENCIL) { /* OK */ } else { @@ -794,9 +793,8 @@ test_attachment_completeness(const struct gl_context *ctx, GLenum format, } else { ASSERT(format == GL_STENCIL); - if (ctx->Extensions.EXT_packed_depth_stencil && - ctx->Extensions.ARB_depth_texture && - baseFormat == GL_DEPTH_STENCIL_EXT) { + if (ctx->Extensions.ARB_depth_texture && + baseFormat == GL_DEPTH_STENCIL) { /* OK */ } else { @@ -830,8 +828,7 @@ test_attachment_completeness(const struct gl_context *ctx, GLenum format, if (baseFormat == GL_DEPTH_COMPONENT) { /* OK */ } - else if (ctx->Extensions.EXT_packed_depth_stencil && - baseFormat == GL_DEPTH_STENCIL_EXT) { + else if (baseFormat == GL_DEPTH_STENCIL) { /* OK */ } else { @@ -842,11 +839,8 @@ test_attachment_completeness(const struct gl_context *ctx, GLenum format, } else { assert(format == GL_STENCIL); - if (baseFormat == GL_STENCIL_INDEX) { - /* OK */ - } - else if (ctx->Extensions.EXT_packed_depth_stencil && - baseFormat == GL_DEPTH_STENCIL_EXT) { + if (baseFormat == GL_STENCIL_INDEX || + baseFormat == GL_DEPTH_STENCIL) { /* OK */ } else { @@ -1457,13 +1451,10 @@ _mesa_base_fbo_format(struct gl_context *ctx, GLenum internalFormat) case GL_DEPTH_COMPONENT16: case GL_DEPTH_COMPONENT24: return GL_DEPTH_COMPONENT; - case GL_DEPTH_STENCIL_EXT: - return _mesa_is_desktop_gl(ctx) - && ctx->Extensions.EXT_packed_depth_stencil - ? GL_DEPTH_STENCIL_EXT : 0; - case GL_DEPTH24_STENCIL8_EXT: - return ctx->Extensions.EXT_packed_depth_stencil - ? GL_DEPTH_STENCIL_EXT : 0; + case GL_DEPTH_STENCIL: + return _mesa_is_desktop_gl(ctx) ? GL_DEPTH_STENCIL : 0; + case GL_DEPTH24_STENCIL8: + return GL_DEPTH_STENCIL; case GL_DEPTH_COMPONENT32F: return ctx->Version >= 30 || (ctx->API == API_OPENGL_COMPAT && ctx->Extensions.ARB_depth_buffer_float) diff --git a/mesalib/src/mesa/main/ff_fragment_shader.cpp b/mesalib/src/mesa/main/ff_fragment_shader.cpp index 01edd3ff8..ba6258d89 100644 --- a/mesalib/src/mesa/main/ff_fragment_shader.cpp +++ b/mesalib/src/mesa/main/ff_fragment_shader.cpp @@ -543,7 +543,8 @@ get_current_attrib(texenv_fragment_program *p, GLuint attrib) ir_rvalue *val; current = p->shader->symbols->get_variable("gl_CurrentAttribFragMESA"); - current->max_array_access = MAX2(current->max_array_access, attrib); + assert(current); + current->data.max_array_access = MAX2(current->data.max_array_access, attrib); val = new(p->mem_ctx) ir_dereference_variable(current); ir_rvalue *index = new(p->mem_ctx) ir_constant(attrib); return new(p->mem_ctx) ir_dereference_array(val, index); @@ -587,7 +588,7 @@ get_source(texenv_fragment_program *p, var = p->shader->symbols->get_variable("gl_TextureEnvColor"); assert(var); deref = new(p->mem_ctx) ir_dereference_variable(var); - var->max_array_access = MAX2(var->max_array_access, unit); + var->data.max_array_access = MAX2(var->data.max_array_access, unit); return new(p->mem_ctx) ir_dereference_array(deref, new(p->mem_ctx) ir_constant(unit)); @@ -927,7 +928,7 @@ static void load_texture( texenv_fragment_program *p, GLuint unit ) texcoord = new(p->mem_ctx) ir_dereference_variable(tc_array); ir_rvalue *index = new(p->mem_ctx) ir_constant(unit); texcoord = new(p->mem_ctx) ir_dereference_array(texcoord, index); - tc_array->max_array_access = MAX2(tc_array->max_array_access, unit); + tc_array->data.max_array_access = MAX2(tc_array->data.max_array_access, unit); } if (!p->state->unit[unit].enabled) { @@ -1096,14 +1097,16 @@ load_texunit_bumpmap( texenv_fragment_program *p, GLuint unit ) ir_variable *rot_mat_0, *rot_mat_1; rot_mat_0 = p->shader->symbols->get_variable("gl_BumpRotMatrix0MESA"); + assert(rot_mat_0); rot_mat_1 = p->shader->symbols->get_variable("gl_BumpRotMatrix1MESA"); + assert(rot_mat_1); ir_variable *tc_array = p->shader->symbols->get_variable("gl_TexCoord"); assert(tc_array); texcoord = new(p->mem_ctx) ir_dereference_variable(tc_array); ir_rvalue *index = new(p->mem_ctx) ir_constant(bumpedUnitNr); texcoord = new(p->mem_ctx) ir_dereference_array(texcoord, index); - tc_array->max_array_access = MAX2(tc_array->max_array_access, unit); + tc_array->data.max_array_access = MAX2(tc_array->data.max_array_access, unit); load_texenv_source( p, unit + SRC_TEXTURE0, unit ); @@ -1157,8 +1160,11 @@ emit_fog_instructions(texenv_fragment_program *p, fragcolor = swizzle_xyz(fog_result); oparams = p->shader->symbols->get_variable("gl_FogParamsOptimizedMESA"); + assert(oparams); fogcoord = p->shader->symbols->get_variable("gl_FogFragCoord"); + assert(fogcoord); params = p->shader->symbols->get_variable("gl_Fog"); + assert(params); f = new(p->mem_ctx) ir_dereference_variable(fogcoord); ir_variable *f_var = p->make_temp(glsl_type::float_type, "fog_factor"); @@ -1344,7 +1350,7 @@ create_new_program(struct gl_context *ctx, struct state_key *key) p.shader->CompileStatus = true; p.shader->Version = state->language_version; - p.shader->num_builtins_to_link = state->num_builtins_to_link; + p.shader->uses_builtin_functions = state->uses_builtin_functions; p.shader_program->Shaders = (gl_shader **)malloc(sizeof(*p.shader_program->Shaders)); p.shader_program->Shaders[0] = p.shader; diff --git a/mesalib/src/mesa/main/get.c b/mesalib/src/mesa/main/get.c index 7f233409e..691380898 100644 --- a/mesalib/src/mesa/main/get.c +++ b/mesalib/src/mesa/main/get.c @@ -327,8 +327,8 @@ static const int extra_EXT_framebuffer_sRGB_and_new_buffers[] = { EXTRA_END }; -static const int extra_MESA_texture_array_es3[] = { - EXT(MESA_texture_array), +static const int extra_EXT_texture_array_es3[] = { + EXT(EXT_texture_array), EXTRA_API_ES3, EXTRA_END }; @@ -339,7 +339,7 @@ static const int extra_ARB_shader_atomic_counters_and_geometry_shader[] = { }; EXTRA_EXT(ARB_texture_cube_map); -EXTRA_EXT(MESA_texture_array); +EXTRA_EXT(EXT_texture_array); EXTRA_EXT(NV_fog_distance); EXTRA_EXT(EXT_texture_filter_anisotropic); EXTRA_EXT(NV_point_sprite); @@ -565,8 +565,6 @@ find_custom_value(struct gl_context *ctx, const struct value_desc *d, union valu case GL_TEXTURE_1D: case GL_TEXTURE_2D: case GL_TEXTURE_3D: - case GL_TEXTURE_1D_ARRAY_EXT: - case GL_TEXTURE_2D_ARRAY_EXT: case GL_TEXTURE_CUBE_MAP_ARB: case GL_TEXTURE_RECTANGLE_NV: case GL_TEXTURE_EXTERNAL_OES: diff --git a/mesalib/src/mesa/main/get_hash_params.py b/mesalib/src/mesa/main/get_hash_params.py index 781b796ee..653bf6256 100644 --- a/mesalib/src/mesa/main/get_hash_params.py +++ b/mesalib/src/mesa/main/get_hash_params.py @@ -376,8 +376,8 @@ descriptor=[ [ "PIXEL_UNPACK_BUFFER_BINDING_EXT", "LOC_CUSTOM, TYPE_INT, 0, extra_EXT_pixel_buffer_object" ], # GL_EXT_texture_array - [ "TEXTURE_BINDING_2D_ARRAY", "LOC_CUSTOM, TYPE_INT, TEXTURE_2D_ARRAY_INDEX, extra_MESA_texture_array_es3" ], - [ "MAX_ARRAY_TEXTURE_LAYERS_EXT", "CONTEXT_INT(Const.MaxArrayTextureLayers), extra_MESA_texture_array_es3" ], + [ "TEXTURE_BINDING_2D_ARRAY", "LOC_CUSTOM, TYPE_INT, TEXTURE_2D_ARRAY_INDEX, extra_EXT_texture_array_es3" ], + [ "MAX_ARRAY_TEXTURE_LAYERS_EXT", "CONTEXT_INT(Const.MaxArrayTextureLayers), extra_EXT_texture_array_es3" ], # GL_EXT_transform_feedback [ "TRANSFORM_FEEDBACK_BUFFER_BINDING", "LOC_CUSTOM, TYPE_INT, 0, extra_EXT_transform_feedback" ], @@ -504,10 +504,8 @@ descriptor=[ [ "STEREO", "BUFFER_INT(Visual.stereoMode), NO_EXTRA" ], [ "TEXTURE_1D", "LOC_CUSTOM, TYPE_BOOLEAN, NO_OFFSET, NO_EXTRA" ], [ "TEXTURE_3D", "LOC_CUSTOM, TYPE_BOOLEAN, NO_OFFSET, NO_EXTRA" ], - [ "TEXTURE_1D_ARRAY_EXT", "LOC_CUSTOM, TYPE_BOOLEAN, NO_OFFSET, NO_EXTRA" ], - [ "TEXTURE_2D_ARRAY_EXT", "LOC_CUSTOM, TYPE_BOOLEAN, NO_OFFSET, NO_EXTRA" ], [ "TEXTURE_BINDING_1D", "LOC_CUSTOM, TYPE_INT, TEXTURE_1D_INDEX, NO_EXTRA" ], - [ "TEXTURE_BINDING_1D_ARRAY", "LOC_CUSTOM, TYPE_INT, TEXTURE_1D_ARRAY_INDEX, extra_MESA_texture_array" ], + [ "TEXTURE_BINDING_1D_ARRAY", "LOC_CUSTOM, TYPE_INT, TEXTURE_1D_ARRAY_INDEX, extra_EXT_texture_array" ], [ "TEXTURE_GEN_S", "LOC_TEXUNIT, TYPE_BIT_0, offsetof(struct gl_texture_unit, TexGenEnabled), NO_EXTRA" ], [ "TEXTURE_GEN_T", "LOC_TEXUNIT, TYPE_BIT_1, offsetof(struct gl_texture_unit, TexGenEnabled), NO_EXTRA" ], [ "TEXTURE_GEN_R", "LOC_TEXUNIT, TYPE_BIT_2, offsetof(struct gl_texture_unit, TexGenEnabled), NO_EXTRA" ], diff --git a/mesalib/src/mesa/main/getstring.c b/mesalib/src/mesa/main/getstring.c index d8189115a..b66e24788 100644 --- a/mesalib/src/mesa/main/getstring.c +++ b/mesalib/src/mesa/main/getstring.c @@ -42,8 +42,6 @@ shading_language_version(struct gl_context *ctx) case API_OPENGL_COMPAT: case API_OPENGL_CORE: switch (ctx->Const.GLSLVersion) { - case 110: - return (const GLubyte *) "1.10"; case 120: return (const GLubyte *) "1.20"; case 130: diff --git a/mesalib/src/mesa/main/glformats.c b/mesalib/src/mesa/main/glformats.c index 740faa890..bec7a9bbb 100644 --- a/mesalib/src/mesa/main/glformats.c +++ b/mesalib/src/mesa/main/glformats.c @@ -1301,9 +1301,6 @@ _mesa_error_check_format_and_type(const struct gl_context *ctx, return GL_INVALID_OPERATION; case GL_UNSIGNED_INT_24_8: - if (!ctx->Extensions.EXT_packed_depth_stencil) { - return GL_INVALID_ENUM; - } if (format != GL_DEPTH_STENCIL) { return GL_INVALID_OPERATION; } @@ -1484,9 +1481,8 @@ _mesa_error_check_format_and_type(const struct gl_context *ctx, else return GL_INVALID_OPERATION; - case GL_DEPTH_STENCIL_EXT: - if (ctx->Extensions.EXT_packed_depth_stencil && - type == GL_UNSIGNED_INT_24_8) + case GL_DEPTH_STENCIL: + if (type == GL_UNSIGNED_INT_24_8) return GL_NO_ERROR; else if (ctx->Extensions.ARB_depth_buffer_float && type == GL_FLOAT_32_UNSIGNED_INT_24_8_REV) @@ -1694,8 +1690,6 @@ GLenum _mesa_es3_error_check_format_and_type(GLenum format, GLenum type, GLenum internalFormat) { - GLboolean type_valid = GL_TRUE; - switch (format) { case GL_RGBA: switch (type) { @@ -2116,5 +2110,5 @@ _mesa_es3_error_check_format_and_type(GLenum format, GLenum type, break; } - return type_valid ? GL_NO_ERROR : GL_INVALID_OPERATION; + return GL_NO_ERROR; } diff --git a/mesalib/src/mesa/main/imports.c b/mesalib/src/mesa/main/imports.c index 277e9476a..4afe156b0 100644 --- a/mesalib/src/mesa/main/imports.c +++ b/mesalib/src/mesa/main/imports.c @@ -168,6 +168,8 @@ _mesa_align_calloc(size_t bytes, unsigned long alignment) * \param ptr pointer to the memory to be freed. * The actual address to free is stored in the word immediately before the * address the client sees. + * Note that it is legal to pass NULL pointer to this function and will be + * handled accordingly. */ void _mesa_align_free(void *ptr) @@ -177,9 +179,11 @@ _mesa_align_free(void *ptr) #elif defined(_WIN32) && defined(_MSC_VER) _aligned_free(ptr); #else - void **cubbyHole = (void **) ((char *) ptr - sizeof(void *)); - void *realAddr = *cubbyHole; - free(realAddr); + if (ptr) { + void **cubbyHole = (void **) ((char *) ptr - sizeof(void *)); + void *realAddr = *cubbyHole; + free(realAddr); + } #endif /* defined(HAVE_POSIX_MEMALIGN) */ } @@ -199,8 +203,8 @@ _mesa_align_realloc(void *oldBuffer, size_t oldSize, size_t newSize, if (newBuf && oldBuffer && copySize > 0) { memcpy(newBuf, oldBuffer, copySize); } - if (oldBuffer) - _mesa_align_free(oldBuffer); + + _mesa_align_free(oldBuffer); return newBuf; #endif } diff --git a/mesalib/src/mesa/main/mipmap.c b/mesalib/src/mesa/main/mipmap.c index 180f89116..033015780 100644 --- a/mesalib/src/mesa/main/mipmap.c +++ b/mesalib/src/mesa/main/mipmap.c @@ -1767,8 +1767,8 @@ _mesa_generate_mipmap_level(GLenum target, * compute next (level+1) image size * \return GL_FALSE if no smaller size can be generated (eg. src is 1x1x1 size) */ -static GLboolean -next_mipmap_level_size(GLenum target, GLint border, +GLboolean +_mesa_next_mipmap_level_size(GLenum target, GLint border, GLint srcWidth, GLint srcHeight, GLint srcDepth, GLint *dstWidth, GLint *dstHeight, GLint *dstDepth) { @@ -1911,7 +1911,7 @@ generate_mipmap_uncompressed(struct gl_context *ctx, GLenum target, srcDepth = srcImage->Depth; border = srcImage->Border; - nextLevel = next_mipmap_level_size(target, border, + nextLevel = _mesa_next_mipmap_level_size(target, border, srcWidth, srcHeight, srcDepth, &dstWidth, &dstHeight, &dstDepth); if (!nextLevel) @@ -2102,7 +2102,7 @@ generate_mipmap_compressed(struct gl_context *ctx, GLenum target, srcDepth = srcImage->Depth; border = srcImage->Border; - nextLevel = next_mipmap_level_size(target, border, + nextLevel = _mesa_next_mipmap_level_size(target, border, srcWidth, srcHeight, srcDepth, &dstWidth, &dstHeight, &dstDepth); if (!nextLevel) diff --git a/mesalib/src/mesa/main/mipmap.h b/mesalib/src/mesa/main/mipmap.h index d5bd1d83d..ee91df006 100644 --- a/mesalib/src/mesa/main/mipmap.h +++ b/mesalib/src/mesa/main/mipmap.h @@ -51,5 +51,9 @@ extern void _mesa_generate_mipmap(struct gl_context *ctx, GLenum target, struct gl_texture_object *texObj); +extern GLboolean +_mesa_next_mipmap_level_size(GLenum target, GLint border, + GLint srcWidth, GLint srcHeight, GLint srcDepth, + GLint *dstWidth, GLint *dstHeight, GLint *dstDepth); #endif /* MIPMAP_H */ diff --git a/mesalib/src/mesa/main/mtypes.h b/mesalib/src/mesa/main/mtypes.h index b4b432f40..f93bb5641 100644 --- a/mesalib/src/mesa/main/mtypes.h +++ b/mesalib/src/mesa/main/mtypes.h @@ -280,6 +280,7 @@ typedef enum */ #define SYSTEM_BIT_SAMPLE_ID BITFIELD64_BIT(SYSTEM_VALUE_SAMPLE_ID) #define SYSTEM_BIT_SAMPLE_POS BITFIELD64_BIT(SYSTEM_VALUE_SAMPLE_POS) +#define SYSTEM_BIT_SAMPLE_MASK_IN BITFIELD64_BIT(SYSTEM_VALUE_SAMPLE_MASK_IN) /** * Determine if the given gl_varying_slot appears in the fragment shader. @@ -1193,6 +1194,11 @@ struct gl_texture_object pressure? */ GLboolean Immutable; /**< GL_ARB_texture_storage */ + GLuint MinLevel; /**< GL_ARB_texture_view */ + GLuint MinLayer; /**< GL_ARB_texture_view */ + GLuint NumLevels; /**< GL_ARB_texture_view */ + GLuint NumLayers; /**< GL_ARB_texture_view */ + /** Actual texture images, indexed by [cube face] and [mipmap level] */ struct gl_texture_image *Image[MAX_FACES][MAX_TEXTURE_LEVELS]; @@ -1968,12 +1974,13 @@ typedef enum */ typedef enum { - SYSTEM_VALUE_FRONT_FACE, /**< Fragment shader only (not done yet) */ - SYSTEM_VALUE_VERTEX_ID, /**< Vertex shader only */ - SYSTEM_VALUE_INSTANCE_ID, /**< Vertex shader only */ - SYSTEM_VALUE_SAMPLE_ID, /**< Fragment shader only */ - SYSTEM_VALUE_SAMPLE_POS, /**< Fragment shader only */ - SYSTEM_VALUE_MAX /**< Number of values */ + SYSTEM_VALUE_FRONT_FACE, /**< Fragment shader only (not done yet) */ + SYSTEM_VALUE_VERTEX_ID, /**< Vertex shader only */ + SYSTEM_VALUE_INSTANCE_ID, /**< Vertex shader only */ + SYSTEM_VALUE_SAMPLE_ID, /**< Fragment shader only */ + SYSTEM_VALUE_SAMPLE_POS, /**< Fragment shader only */ + SYSTEM_VALUE_SAMPLE_MASK_IN, /**< Fragment shader only */ + SYSTEM_VALUE_MAX /**< Number of values */ } gl_system_value; @@ -2132,6 +2139,12 @@ struct gl_fragment_program * uses centroid interpolation, 0 otherwise. Unused inputs are 0. */ GLbitfield64 IsCentroid; + + /** + * Bitfield indicating, for each fragment shader input, 1 if that input + * uses sample interpolation, 0 otherwise. Unused inputs are 0. + */ + GLbitfield64 IsSample; }; @@ -2352,9 +2365,7 @@ struct gl_shader struct exec_list *ir; struct glsl_symbol_table *symbols; - /** Shaders containing built-in functions that are used for linking. */ - struct gl_shader *builtins_to_link[16]; - unsigned num_builtins_to_link; + bool uses_builtin_functions; /** * Geometry shader state from GLSL 1.50 layout qualifiers. @@ -2388,9 +2399,10 @@ typedef enum MESA_SHADER_VERTEX = 0, MESA_SHADER_GEOMETRY = 1, MESA_SHADER_FRAGMENT = 2, - MESA_SHADER_TYPES = 3 } gl_shader_type; +#define MESA_SHADER_TYPES (MESA_SHADER_FRAGMENT + 1) + struct gl_uniform_buffer_variable { @@ -3374,6 +3386,7 @@ struct gl_extensions GLboolean ARB_texture_query_lod; GLboolean ARB_texture_rg; GLboolean ARB_texture_rgb10_a2ui; + GLboolean ARB_texture_view; GLboolean ARB_timer_query; GLboolean ARB_transform_feedback2; GLboolean ARB_transform_feedback3; @@ -3395,7 +3408,6 @@ struct gl_extensions GLboolean EXT_framebuffer_sRGB; GLboolean EXT_gpu_program_parameters; GLboolean EXT_gpu_shader4; - GLboolean EXT_packed_depth_stencil; GLboolean EXT_packed_float; GLboolean EXT_pixel_buffer_object; GLboolean EXT_point_parameters; @@ -3432,7 +3444,6 @@ struct gl_extensions GLboolean ATI_fragment_shader; GLboolean ATI_separate_stencil; GLboolean MESA_pack_invert; - GLboolean MESA_texture_array; GLboolean MESA_ycbcr_texture; GLboolean NV_conditional_render; GLboolean NV_fog_distance; diff --git a/mesalib/src/mesa/main/performance_monitor.c b/mesalib/src/mesa/main/performance_monitor.c index 4981e6fb2..e62f77012 100644 --- a/mesalib/src/mesa/main/performance_monitor.c +++ b/mesalib/src/mesa/main/performance_monitor.c @@ -93,6 +93,25 @@ fail: return NULL; } +static void +free_performance_monitor(GLuint key, void *data, void *user) +{ + struct gl_perf_monitor_object *m = data; + struct gl_context *ctx = user; + + ralloc_free(m->ActiveGroups); + ralloc_free(m->ActiveCounters); + ctx->Driver.DeletePerfMonitor(ctx, m); +} + +void +_mesa_free_performance_monitors(struct gl_context *ctx) +{ + _mesa_HashDeleteAll(ctx->PerfMonitor.Monitors, + free_performance_monitor, ctx); + _mesa_DeleteHashTable(ctx->PerfMonitor.Monitors); +} + static inline struct gl_perf_monitor_object * lookup_monitor(struct gl_context *ctx, GLuint id) { diff --git a/mesalib/src/mesa/main/performance_monitor.h b/mesalib/src/mesa/main/performance_monitor.h index a852a4184..76234e5c1 100644 --- a/mesalib/src/mesa/main/performance_monitor.h +++ b/mesalib/src/mesa/main/performance_monitor.h @@ -35,6 +35,9 @@ extern void _mesa_init_performance_monitors(struct gl_context *ctx); +extern void +_mesa_free_performance_monitors(struct gl_context *ctx); + extern void GLAPIENTRY _mesa_GetPerfMonitorGroupsAMD(GLint *numGroups, GLsizei groupsSize, GLuint *groups); diff --git a/mesalib/src/mesa/main/shader_query.cpp b/mesalib/src/mesa/main/shader_query.cpp index 3014a9778..f14e1a562 100644 --- a/mesalib/src/mesa/main/shader_query.cpp +++ b/mesalib/src/mesa/main/shader_query.cpp @@ -106,8 +106,8 @@ _mesa_GetActiveAttrib(GLhandleARB program, GLuint desired_index, const ir_variable *const var = ((ir_instruction *) node)->as_variable(); if (var == NULL - || var->mode != ir_var_shader_in - || var->location == -1) + || var->data.mode != ir_var_shader_in + || var->data.location == -1) continue; if (current_index == desired_index) { @@ -169,13 +169,13 @@ _mesa_GetAttribLocation(GLhandleARB program, const GLcharARB * name) * attribute, or if an error occurs, -1 will be returned." */ if (var == NULL - || var->mode != ir_var_shader_in - || var->location == -1 - || var->location < VERT_ATTRIB_GENERIC0) + || var->data.mode != ir_var_shader_in + || var->data.location == -1 + || var->data.location < VERT_ATTRIB_GENERIC0) continue; if (strcmp(var->name, name) == 0) - return var->location - VERT_ATTRIB_GENERIC0; + return var->data.location - VERT_ATTRIB_GENERIC0; } return -1; @@ -197,8 +197,8 @@ _mesa_count_active_attribs(struct gl_shader_program *shProg) const ir_variable *const var = ((ir_instruction *) node)->as_variable(); if (var == NULL - || var->mode != ir_var_shader_in - || var->location == -1) + || var->data.mode != ir_var_shader_in + || var->data.location == -1) continue; i++; @@ -223,8 +223,8 @@ _mesa_longest_attribute_name_length(struct gl_shader_program *shProg) const ir_variable *const var = ((ir_instruction *) node)->as_variable(); if (var == NULL - || var->mode != ir_var_shader_in - || var->location == -1) + || var->data.mode != ir_var_shader_in + || var->data.location == -1) continue; const size_t len = strlen(var->name); @@ -333,13 +333,13 @@ _mesa_GetFragDataIndex(GLuint program, const GLchar *name) * attribute, or if an error occurs, -1 will be returned." */ if (var == NULL - || var->mode != ir_var_shader_out - || var->location == -1 - || var->location < FRAG_RESULT_DATA0) + || var->data.mode != ir_var_shader_out + || var->data.location == -1 + || var->data.location < FRAG_RESULT_DATA0) continue; if (strcmp(var->name, name) == 0) - return var->index; + return var->data.index; } return -1; @@ -389,13 +389,13 @@ _mesa_GetFragDataLocation(GLuint program, const GLchar *name) * attribute, or if an error occurs, -1 will be returned." */ if (var == NULL - || var->mode != ir_var_shader_out - || var->location == -1 - || var->location < FRAG_RESULT_DATA0) + || var->data.mode != ir_var_shader_out + || var->data.location == -1 + || var->data.location < FRAG_RESULT_DATA0) continue; if (strcmp(var->name, name) == 0) - return var->location - FRAG_RESULT_DATA0; + return var->data.location - FRAG_RESULT_DATA0; } return -1; diff --git a/mesalib/src/mesa/main/shaderapi.c b/mesalib/src/mesa/main/shaderapi.c index 1d9aac39d..4f3be68a4 100644 --- a/mesalib/src/mesa/main/shaderapi.c +++ b/mesalib/src/mesa/main/shaderapi.c @@ -414,7 +414,7 @@ detach_shader(struct gl_context *ctx, GLuint program, GLuint shader) err = GL_INVALID_OPERATION; else err = GL_INVALID_VALUE; - _mesa_error(ctx, err, "glDetachProgram(shader)"); + _mesa_error(ctx, err, "glDetachShader(shader)"); return; } } diff --git a/mesalib/src/mesa/main/shaderobj.h b/mesalib/src/mesa/main/shaderobj.h index de1c9fcaf..aff178f26 100644 --- a/mesalib/src/mesa/main/shaderobj.h +++ b/mesalib/src/mesa/main/shaderobj.h @@ -113,7 +113,7 @@ _mesa_shader_type_to_index(GLenum v) return MESA_SHADER_GEOMETRY; default: ASSERT(0 && "bad value in _mesa_shader_type_to_index()"); - return MESA_SHADER_TYPES; + return MESA_SHADER_VERTEX; } } diff --git a/mesalib/src/mesa/main/texgetimage.c b/mesalib/src/mesa/main/texgetimage.c index d66ca1abc..200d29c2f 100644 --- a/mesalib/src/mesa/main/texgetimage.c +++ b/mesalib/src/mesa/main/texgetimage.c @@ -759,8 +759,7 @@ legal_getteximage_target(struct gl_context *ctx, GLenum target) return ctx->Extensions.NV_texture_rectangle; case GL_TEXTURE_1D_ARRAY_EXT: case GL_TEXTURE_2D_ARRAY_EXT: - return (ctx->Extensions.MESA_texture_array || - ctx->Extensions.EXT_texture_array); + return ctx->Extensions.EXT_texture_array; case GL_TEXTURE_CUBE_MAP_ARRAY: return ctx->Extensions.ARB_texture_cube_map_array; default: diff --git a/mesalib/src/mesa/main/teximage.c b/mesalib/src/mesa/main/teximage.c index 793c5d382..9c3f1e86e 100644 --- a/mesalib/src/mesa/main/teximage.c +++ b/mesalib/src/mesa/main/teximage.c @@ -48,6 +48,7 @@ #include "texobj.h" #include "texstate.h" #include "texstorage.h" +#include "textureview.h" #include "mtypes.h" #include "glformats.h" @@ -300,14 +301,12 @@ _mesa_base_tex_format( struct gl_context *ctx, GLint internalFormat ) } } - if (ctx->Extensions.EXT_packed_depth_stencil) { - switch (internalFormat) { - case GL_DEPTH_STENCIL_EXT: - case GL_DEPTH24_STENCIL8_EXT: - return GL_DEPTH_STENCIL_EXT; - default: - ; /* fallthrough */ - } + switch (internalFormat) { + case GL_DEPTH_STENCIL: + case GL_DEPTH24_STENCIL8: + return GL_DEPTH_STENCIL; + default: + ; /* fallthrough */ } if (ctx->Extensions.EXT_texture_sRGB) { @@ -752,8 +751,7 @@ _mesa_select_tex_object(struct gl_context *ctx, const struct gl_texture_unit *texUnit, GLenum target) { - const GLboolean arrayTex = (ctx->Extensions.MESA_texture_array || - ctx->Extensions.EXT_texture_array); + const GLboolean arrayTex = ctx->Extensions.EXT_texture_array; switch (target) { case GL_TEXTURE_1D: @@ -1018,8 +1016,7 @@ _mesa_max_texture_levels(struct gl_context *ctx, GLenum target) case GL_PROXY_TEXTURE_1D_ARRAY_EXT: case GL_TEXTURE_2D_ARRAY_EXT: case GL_PROXY_TEXTURE_2D_ARRAY_EXT: - return (ctx->Extensions.MESA_texture_array || - ctx->Extensions.EXT_texture_array) + return ctx->Extensions.EXT_texture_array ? ctx->Const.MaxTextureLevels : 0; case GL_TEXTURE_CUBE_MAP_ARRAY: case GL_PROXY_TEXTURE_CUBE_MAP_ARRAY: @@ -1726,8 +1723,7 @@ target_can_be_compressed(const struct gl_context *ctx, GLenum target, return ctx->Extensions.ARB_texture_cube_map; case GL_PROXY_TEXTURE_2D_ARRAY_EXT: case GL_TEXTURE_2D_ARRAY_EXT: - return (ctx->Extensions.MESA_texture_array || - ctx->Extensions.EXT_texture_array); + return ctx->Extensions.EXT_texture_array; case GL_PROXY_TEXTURE_CUBE_MAP_ARRAY: case GL_TEXTURE_CUBE_MAP_ARRAY: return ctx->Extensions.ARB_texture_cube_map_array; @@ -1775,9 +1771,7 @@ legal_teximage_target(struct gl_context *ctx, GLuint dims, GLenum target) && ctx->Extensions.NV_texture_rectangle; case GL_TEXTURE_1D_ARRAY_EXT: case GL_PROXY_TEXTURE_1D_ARRAY_EXT: - return _mesa_is_desktop_gl(ctx) - && (ctx->Extensions.MESA_texture_array || - ctx->Extensions.EXT_texture_array); + return _mesa_is_desktop_gl(ctx) && ctx->Extensions.EXT_texture_array; default: return GL_FALSE; } @@ -1788,14 +1782,10 @@ legal_teximage_target(struct gl_context *ctx, GLuint dims, GLenum target) case GL_PROXY_TEXTURE_3D: return _mesa_is_desktop_gl(ctx); case GL_TEXTURE_2D_ARRAY_EXT: - return (_mesa_is_desktop_gl(ctx) - && (ctx->Extensions.MESA_texture_array || - ctx->Extensions.EXT_texture_array)) + return (_mesa_is_desktop_gl(ctx) && ctx->Extensions.EXT_texture_array) || _mesa_is_gles3(ctx); case GL_PROXY_TEXTURE_2D_ARRAY_EXT: - return _mesa_is_desktop_gl(ctx) - && (ctx->Extensions.MESA_texture_array || - ctx->Extensions.EXT_texture_array); + return _mesa_is_desktop_gl(ctx) && ctx->Extensions.EXT_texture_array; case GL_TEXTURE_CUBE_MAP_ARRAY: case GL_PROXY_TEXTURE_CUBE_MAP_ARRAY: return ctx->Extensions.ARB_texture_cube_map_array; @@ -1836,9 +1826,7 @@ legal_texsubimage_target(struct gl_context *ctx, GLuint dims, GLenum target) return _mesa_is_desktop_gl(ctx) && ctx->Extensions.NV_texture_rectangle; case GL_TEXTURE_1D_ARRAY_EXT: - return _mesa_is_desktop_gl(ctx) - && (ctx->Extensions.MESA_texture_array || - ctx->Extensions.EXT_texture_array); + return _mesa_is_desktop_gl(ctx) && ctx->Extensions.EXT_texture_array; default: return GL_FALSE; } @@ -1847,9 +1835,7 @@ legal_texsubimage_target(struct gl_context *ctx, GLuint dims, GLenum target) case GL_TEXTURE_3D: return GL_TRUE; case GL_TEXTURE_2D_ARRAY_EXT: - return (_mesa_is_desktop_gl(ctx) - && (ctx->Extensions.MESA_texture_array || - ctx->Extensions.EXT_texture_array)) + return (_mesa_is_desktop_gl(ctx) && ctx->Extensions.EXT_texture_array) || _mesa_is_gles3(ctx); case GL_TEXTURE_CUBE_MAP_ARRAY: case GL_PROXY_TEXTURE_CUBE_MAP_ARRAY: @@ -2870,7 +2856,7 @@ _mesa_choose_texture_format(struct gl_context *ctx, } /* If the application requested compression to an S3TC format but we don't - * have the DTXn library, force a generic compressed format instead. + * have the DXTn library, force a generic compressed format instead. */ if (internalFormat != format && format != GL_NONE) { const GLenum before = internalFormat; @@ -3892,87 +3878,108 @@ _mesa_CompressedTexSubImage3D(GLenum target, GLint level, GLint xoffset, static gl_format get_texbuffer_format(const struct gl_context *ctx, GLenum internalFormat) { + if (ctx->API != API_OPENGL_CORE) { + switch (internalFormat) { + case GL_ALPHA8: + return MESA_FORMAT_A8; + case GL_ALPHA16: + return MESA_FORMAT_A16; + case GL_ALPHA16F_ARB: + return MESA_FORMAT_ALPHA_FLOAT16; + case GL_ALPHA32F_ARB: + return MESA_FORMAT_ALPHA_FLOAT32; + case GL_ALPHA8I_EXT: + return MESA_FORMAT_ALPHA_INT8; + case GL_ALPHA16I_EXT: + return MESA_FORMAT_ALPHA_INT16; + case GL_ALPHA32I_EXT: + return MESA_FORMAT_ALPHA_INT32; + case GL_ALPHA8UI_EXT: + return MESA_FORMAT_ALPHA_UINT8; + case GL_ALPHA16UI_EXT: + return MESA_FORMAT_ALPHA_UINT16; + case GL_ALPHA32UI_EXT: + return MESA_FORMAT_ALPHA_UINT32; + case GL_LUMINANCE8: + return MESA_FORMAT_L8; + case GL_LUMINANCE16: + return MESA_FORMAT_L16; + case GL_LUMINANCE16F_ARB: + return MESA_FORMAT_LUMINANCE_FLOAT16; + case GL_LUMINANCE32F_ARB: + return MESA_FORMAT_LUMINANCE_FLOAT32; + case GL_LUMINANCE8I_EXT: + return MESA_FORMAT_LUMINANCE_INT8; + case GL_LUMINANCE16I_EXT: + return MESA_FORMAT_LUMINANCE_INT16; + case GL_LUMINANCE32I_EXT: + return MESA_FORMAT_LUMINANCE_INT32; + case GL_LUMINANCE8UI_EXT: + return MESA_FORMAT_LUMINANCE_UINT8; + case GL_LUMINANCE16UI_EXT: + return MESA_FORMAT_LUMINANCE_UINT16; + case GL_LUMINANCE32UI_EXT: + return MESA_FORMAT_LUMINANCE_UINT32; + case GL_LUMINANCE8_ALPHA8: + return MESA_FORMAT_AL88; + case GL_LUMINANCE16_ALPHA16: + return MESA_FORMAT_AL1616; + case GL_LUMINANCE_ALPHA16F_ARB: + return MESA_FORMAT_LUMINANCE_ALPHA_FLOAT16; + case GL_LUMINANCE_ALPHA32F_ARB: + return MESA_FORMAT_LUMINANCE_ALPHA_FLOAT32; + case GL_LUMINANCE_ALPHA8I_EXT: + return MESA_FORMAT_LUMINANCE_ALPHA_INT8; + case GL_LUMINANCE_ALPHA16I_EXT: + return MESA_FORMAT_LUMINANCE_ALPHA_INT8; + case GL_LUMINANCE_ALPHA32I_EXT: + return MESA_FORMAT_LUMINANCE_ALPHA_INT16; + case GL_LUMINANCE_ALPHA8UI_EXT: + return MESA_FORMAT_LUMINANCE_ALPHA_UINT8; + case GL_LUMINANCE_ALPHA16UI_EXT: + return MESA_FORMAT_LUMINANCE_ALPHA_UINT16; + case GL_LUMINANCE_ALPHA32UI_EXT: + return MESA_FORMAT_LUMINANCE_ALPHA_UINT32; + case GL_INTENSITY8: + return MESA_FORMAT_I8; + case GL_INTENSITY16: + return MESA_FORMAT_I16; + case GL_INTENSITY16F_ARB: + return MESA_FORMAT_INTENSITY_FLOAT16; + case GL_INTENSITY32F_ARB: + return MESA_FORMAT_INTENSITY_FLOAT32; + case GL_INTENSITY8I_EXT: + return MESA_FORMAT_INTENSITY_INT8; + case GL_INTENSITY16I_EXT: + return MESA_FORMAT_INTENSITY_INT16; + case GL_INTENSITY32I_EXT: + return MESA_FORMAT_INTENSITY_INT32; + case GL_INTENSITY8UI_EXT: + return MESA_FORMAT_INTENSITY_UINT8; + case GL_INTENSITY16UI_EXT: + return MESA_FORMAT_INTENSITY_UINT16; + case GL_INTENSITY32UI_EXT: + return MESA_FORMAT_INTENSITY_UINT32; + default: + break; + } + } + + if (ctx->API == API_OPENGL_CORE && + ctx->Extensions.ARB_texture_buffer_object_rgb32) { + switch (internalFormat) { + case GL_RGB32F: + return MESA_FORMAT_RGB_FLOAT32; + case GL_RGB32UI: + return MESA_FORMAT_RGB_UINT32; + case GL_RGB32I: + return MESA_FORMAT_RGB_INT32; + default: + break; + } + } + switch (internalFormat) { - case GL_ALPHA8: - return MESA_FORMAT_A8; - case GL_ALPHA16: - return MESA_FORMAT_A16; - case GL_ALPHA16F_ARB: - return MESA_FORMAT_ALPHA_FLOAT16; - case GL_ALPHA32F_ARB: - return MESA_FORMAT_ALPHA_FLOAT32; - case GL_ALPHA8I_EXT: - return MESA_FORMAT_ALPHA_INT8; - case GL_ALPHA16I_EXT: - return MESA_FORMAT_ALPHA_INT16; - case GL_ALPHA32I_EXT: - return MESA_FORMAT_ALPHA_INT32; - case GL_ALPHA8UI_EXT: - return MESA_FORMAT_ALPHA_UINT8; - case GL_ALPHA16UI_EXT: - return MESA_FORMAT_ALPHA_UINT16; - case GL_ALPHA32UI_EXT: - return MESA_FORMAT_ALPHA_UINT32; - case GL_LUMINANCE8: - return MESA_FORMAT_L8; - case GL_LUMINANCE16: - return MESA_FORMAT_L16; - case GL_LUMINANCE16F_ARB: - return MESA_FORMAT_LUMINANCE_FLOAT16; - case GL_LUMINANCE32F_ARB: - return MESA_FORMAT_LUMINANCE_FLOAT32; - case GL_LUMINANCE8I_EXT: - return MESA_FORMAT_LUMINANCE_INT8; - case GL_LUMINANCE16I_EXT: - return MESA_FORMAT_LUMINANCE_INT16; - case GL_LUMINANCE32I_EXT: - return MESA_FORMAT_LUMINANCE_INT32; - case GL_LUMINANCE8UI_EXT: - return MESA_FORMAT_LUMINANCE_UINT8; - case GL_LUMINANCE16UI_EXT: - return MESA_FORMAT_LUMINANCE_UINT16; - case GL_LUMINANCE32UI_EXT: - return MESA_FORMAT_LUMINANCE_UINT32; - case GL_LUMINANCE8_ALPHA8: - return MESA_FORMAT_AL88; - case GL_LUMINANCE16_ALPHA16: - return MESA_FORMAT_AL1616; - case GL_LUMINANCE_ALPHA16F_ARB: - return MESA_FORMAT_LUMINANCE_ALPHA_FLOAT16; - case GL_LUMINANCE_ALPHA32F_ARB: - return MESA_FORMAT_LUMINANCE_ALPHA_FLOAT32; - case GL_LUMINANCE_ALPHA8I_EXT: - return MESA_FORMAT_LUMINANCE_ALPHA_INT8; - case GL_LUMINANCE_ALPHA16I_EXT: - return MESA_FORMAT_LUMINANCE_ALPHA_INT8; - case GL_LUMINANCE_ALPHA32I_EXT: - return MESA_FORMAT_LUMINANCE_ALPHA_INT16; - case GL_LUMINANCE_ALPHA8UI_EXT: - return MESA_FORMAT_LUMINANCE_ALPHA_UINT8; - case GL_LUMINANCE_ALPHA16UI_EXT: - return MESA_FORMAT_LUMINANCE_ALPHA_UINT16; - case GL_LUMINANCE_ALPHA32UI_EXT: - return MESA_FORMAT_LUMINANCE_ALPHA_UINT32; - case GL_INTENSITY8: - return MESA_FORMAT_I8; - case GL_INTENSITY16: - return MESA_FORMAT_I16; - case GL_INTENSITY16F_ARB: - return MESA_FORMAT_INTENSITY_FLOAT16; - case GL_INTENSITY32F_ARB: - return MESA_FORMAT_INTENSITY_FLOAT32; - case GL_INTENSITY8I_EXT: - return MESA_FORMAT_INTENSITY_INT8; - case GL_INTENSITY16I_EXT: - return MESA_FORMAT_INTENSITY_INT16; - case GL_INTENSITY32I_EXT: - return MESA_FORMAT_INTENSITY_INT32; - case GL_INTENSITY8UI_EXT: - return MESA_FORMAT_INTENSITY_UINT8; - case GL_INTENSITY16UI_EXT: - return MESA_FORMAT_INTENSITY_UINT16; - case GL_INTENSITY32UI_EXT: - return MESA_FORMAT_INTENSITY_UINT32; case GL_RGBA8: return MESA_FORMAT_RGBA8888_REV; case GL_RGBA16: @@ -4036,21 +4043,15 @@ get_texbuffer_format(const struct gl_context *ctx, GLenum internalFormat) case GL_R32UI: return MESA_FORMAT_R_UINT32; - case GL_RGB32F: - return MESA_FORMAT_RGB_FLOAT32; - case GL_RGB32UI: - return MESA_FORMAT_RGB_UINT32; - case GL_RGB32I: - return MESA_FORMAT_RGB_INT32; - default: return MESA_FORMAT_NONE; } } -static gl_format -validate_texbuffer_format(const struct gl_context *ctx, GLenum internalFormat) +gl_format +_mesa_validate_texbuffer_format(const struct gl_context *ctx, + GLenum internalFormat) { gl_format format = get_texbuffer_format(ctx, internalFormat); GLenum datatype; @@ -4065,15 +4066,10 @@ validate_texbuffer_format(const struct gl_context *ctx, GLenum internalFormat) if (datatype == GL_HALF_FLOAT && !ctx->Extensions.ARB_half_float_pixel) return MESA_FORMAT_NONE; - /* The GL_ARB_texture_rg and GL_ARB_texture_buffer_object specs don't make - * any mention of R/RG formats, but they appear in the GL 3.1 core - * specification. - */ - if (ctx->Version <= 30) { + if (!ctx->Extensions.ARB_texture_rg) { GLenum base_format = _mesa_get_format_base_format(format); - if (base_format == GL_R || base_format == GL_RG) - return MESA_FORMAT_NONE; + return MESA_FORMAT_NONE; } if (!ctx->Extensions.ARB_texture_buffer_object_rgb32) { @@ -4100,7 +4096,7 @@ texbufferrange(struct gl_context *ctx, GLenum target, GLenum internalFormat, return; } - format = validate_texbuffer_format(ctx, internalFormat); + format = _mesa_validate_texbuffer_format(ctx, internalFormat); if (format == MESA_FORMAT_NONE) { _mesa_error(ctx, GL_INVALID_ENUM, "glTexBuffer(internalFormat 0x%x)", internalFormat); @@ -4348,6 +4344,11 @@ teximagemultisample(GLuint dims, GLenum target, GLsizei samples, } texObj->Immutable = immutable; + + if (immutable) { + _mesa_set_texture_view_state(ctx, texObj, target, 1); + } + _mesa_update_fbo_texture(ctx, texObj, 0, 0); } } diff --git a/mesalib/src/mesa/main/teximage.h b/mesalib/src/mesa/main/teximage.h index 792383d2f..0b5786340 100644 --- a/mesalib/src/mesa/main/teximage.h +++ b/mesalib/src/mesa/main/teximage.h @@ -147,6 +147,10 @@ _mesa_legal_texture_dimensions(struct gl_context *ctx, GLenum target, GLint level, GLint width, GLint height, GLint depth, GLint border); +extern gl_format +_mesa_validate_texbuffer_format(const struct gl_context *ctx, + GLenum internalFormat); + /** * Lock a texture for updating. See also _mesa_lock_context_textures(). */ diff --git a/mesalib/src/mesa/main/texobj.c b/mesalib/src/mesa/main/texobj.c index abd30c563..d6510fefd 100644 --- a/mesalib/src/mesa/main/texobj.c +++ b/mesalib/src/mesa/main/texobj.c @@ -552,7 +552,7 @@ _mesa_test_texobj_completeness( const struct gl_context *ctx, t->_MaxLevel = MIN3(t->MaxLevel, /* 'p' in the GL spec */ - baseLevel + baseImage->MaxNumLevels - 1, + (int) (baseLevel + baseImage->MaxNumLevels - 1), /* 'q' in the GL spec */ maxLevels - 1); @@ -889,6 +889,8 @@ count_tex_size(GLuint key, void *data, void *userData) (const struct gl_texture_object *) data; GLuint *total = (GLuint *) userData; + (void) key; + *total = *total + texture_size(texObj); } @@ -1171,7 +1173,7 @@ _mesa_DeleteTextures( GLsizei n, const GLuint *textures) * \return TEXTURE_x_INDEX or -1 if target is invalid */ static GLint -target_enum_to_index(struct gl_context *ctx, GLenum target) +target_enum_to_index(const struct gl_context *ctx, GLenum target) { switch (target) { case GL_TEXTURE_1D: @@ -1179,25 +1181,21 @@ target_enum_to_index(struct gl_context *ctx, GLenum target) case GL_TEXTURE_2D: return TEXTURE_2D_INDEX; case GL_TEXTURE_3D: - return TEXTURE_3D_INDEX; - case GL_TEXTURE_CUBE_MAP_ARB: + return ctx->API != API_OPENGLES ? TEXTURE_3D_INDEX : -1; + case GL_TEXTURE_CUBE_MAP: return ctx->Extensions.ARB_texture_cube_map ? TEXTURE_CUBE_INDEX : -1; - case GL_TEXTURE_RECTANGLE_NV: + case GL_TEXTURE_RECTANGLE: return _mesa_is_desktop_gl(ctx) && ctx->Extensions.NV_texture_rectangle ? TEXTURE_RECT_INDEX : -1; - case GL_TEXTURE_1D_ARRAY_EXT: - return _mesa_is_desktop_gl(ctx) - && (ctx->Extensions.EXT_texture_array - || ctx->Extensions.MESA_texture_array) + case GL_TEXTURE_1D_ARRAY: + return _mesa_is_desktop_gl(ctx) && ctx->Extensions.EXT_texture_array ? TEXTURE_1D_ARRAY_INDEX : -1; - case GL_TEXTURE_2D_ARRAY_EXT: - return (_mesa_is_desktop_gl(ctx) - && (ctx->Extensions.EXT_texture_array - || ctx->Extensions.MESA_texture_array)) + case GL_TEXTURE_2D_ARRAY: + return (_mesa_is_desktop_gl(ctx) && ctx->Extensions.EXT_texture_array) || _mesa_is_gles3(ctx) ? TEXTURE_2D_ARRAY_INDEX : -1; - case GL_TEXTURE_BUFFER_ARB: + case GL_TEXTURE_BUFFER: return ctx->API == API_OPENGL_CORE && ctx->Extensions.ARB_texture_buffer_object ? TEXTURE_BUFFER_INDEX : -1; @@ -1205,7 +1203,8 @@ target_enum_to_index(struct gl_context *ctx, GLenum target) return _mesa_is_gles(ctx) && ctx->Extensions.OES_EGL_image_external ? TEXTURE_EXTERNAL_INDEX : -1; case GL_TEXTURE_CUBE_MAP_ARRAY: - return TEXTURE_CUBE_ARRAY_INDEX; + return _mesa_is_desktop_gl(ctx) && ctx->Extensions.ARB_texture_cube_map_array + ? TEXTURE_CUBE_ARRAY_INDEX : -1; case GL_TEXTURE_2D_MULTISAMPLE: return _mesa_is_desktop_gl(ctx) && ctx->Extensions.ARB_texture_multisample ? TEXTURE_2D_MULTISAMPLE_INDEX: -1; diff --git a/mesalib/src/mesa/main/texparam.c b/mesalib/src/mesa/main/texparam.c index 7092c630b..94e498d20 100644 --- a/mesalib/src/mesa/main/texparam.c +++ b/mesalib/src/mesa/main/texparam.c @@ -158,16 +158,13 @@ get_texobj(struct gl_context *ctx, GLenum target, GLboolean get) } break; case GL_TEXTURE_1D_ARRAY_EXT: - if (_mesa_is_desktop_gl(ctx) - && (ctx->Extensions.MESA_texture_array || - ctx->Extensions.EXT_texture_array)) { + if (_mesa_is_desktop_gl(ctx) && ctx->Extensions.EXT_texture_array) { return texUnit->CurrentTex[TEXTURE_1D_ARRAY_INDEX]; } break; case GL_TEXTURE_2D_ARRAY_EXT: if ((_mesa_is_desktop_gl(ctx) || _mesa_is_gles3(ctx)) - && (ctx->Extensions.MESA_texture_array || - ctx->Extensions.EXT_texture_array)) { + && ctx->Extensions.EXT_texture_array) { return texUnit->CurrentTex[TEXTURE_2D_ARRAY_INDEX]; } break; @@ -1046,8 +1043,7 @@ legal_get_tex_level_parameter_target(struct gl_context *ctx, GLenum target) case GL_PROXY_TEXTURE_1D_ARRAY_EXT: case GL_TEXTURE_2D_ARRAY_EXT: case GL_PROXY_TEXTURE_2D_ARRAY_EXT: - return (ctx->Extensions.MESA_texture_array || - ctx->Extensions.EXT_texture_array); + return ctx->Extensions.EXT_texture_array; case GL_TEXTURE_BUFFER: /* GetTexLevelParameter accepts GL_TEXTURE_BUFFER in GL 3.1+ contexts, * but not in earlier versions that expose ARB_texture_buffer_object. @@ -1166,10 +1162,7 @@ get_tex_level_parameter_image(struct gl_context *ctx, goto invalid_pname; *params = _mesa_get_format_bits(texFormat, pname); break; - case GL_TEXTURE_STENCIL_SIZE_EXT: - if (!ctx->Extensions.EXT_packed_depth_stencil && - !ctx->Extensions.ARB_framebuffer_object) - goto invalid_pname; + case GL_TEXTURE_STENCIL_SIZE: *params = _mesa_get_format_bits(texFormat, pname); break; case GL_TEXTURE_SHARED_SIZE: @@ -1562,9 +1555,35 @@ _mesa_GetTexParameterfv( GLenum target, GLenum pname, GLfloat *params ) break; case GL_TEXTURE_IMMUTABLE_LEVELS: - if (!_mesa_is_gles3(ctx)) + if (_mesa_is_gles3(ctx) || + (_mesa_is_desktop_gl(ctx) && ctx->Extensions.ARB_texture_view)) + *params = (GLfloat) obj->ImmutableLevels; + else goto invalid_pname; - *params = (GLfloat) obj->ImmutableLevels; + break; + + case GL_TEXTURE_VIEW_MIN_LEVEL: + if (!ctx->Extensions.ARB_texture_view) + goto invalid_pname; + *params = (GLfloat) obj->MinLevel; + break; + + case GL_TEXTURE_VIEW_NUM_LEVELS: + if (!ctx->Extensions.ARB_texture_view) + goto invalid_pname; + *params = (GLfloat) obj->NumLevels; + break; + + case GL_TEXTURE_VIEW_MIN_LAYER: + if (!ctx->Extensions.ARB_texture_view) + goto invalid_pname; + *params = (GLfloat) obj->MinLayer; + break; + + case GL_TEXTURE_VIEW_NUM_LAYERS: + if (!ctx->Extensions.ARB_texture_view) + goto invalid_pname; + *params = (GLfloat) obj->NumLayers; break; case GL_REQUIRED_TEXTURE_IMAGE_UNITS_OES: @@ -1746,9 +1765,35 @@ _mesa_GetTexParameteriv( GLenum target, GLenum pname, GLint *params ) break; case GL_TEXTURE_IMMUTABLE_LEVELS: - if (!_mesa_is_gles3(ctx)) + if (_mesa_is_gles3(ctx) || + (_mesa_is_desktop_gl(ctx) && ctx->Extensions.ARB_texture_view)) + *params = obj->ImmutableLevels; + else + goto invalid_pname; + break; + + case GL_TEXTURE_VIEW_MIN_LEVEL: + if (!ctx->Extensions.ARB_texture_view) + goto invalid_pname; + *params = (GLint) obj->MinLevel; + break; + + case GL_TEXTURE_VIEW_NUM_LEVELS: + if (!ctx->Extensions.ARB_texture_view) + goto invalid_pname; + *params = (GLint) obj->NumLevels; + break; + + case GL_TEXTURE_VIEW_MIN_LAYER: + if (!ctx->Extensions.ARB_texture_view) + goto invalid_pname; + *params = (GLint) obj->MinLayer; + break; + + case GL_TEXTURE_VIEW_NUM_LAYERS: + if (!ctx->Extensions.ARB_texture_view) goto invalid_pname; - *params = obj->ImmutableLevels; + *params = (GLint) obj->NumLayers; break; case GL_REQUIRED_TEXTURE_IMAGE_UNITS_OES: diff --git a/mesalib/src/mesa/main/texstorage.c b/mesalib/src/mesa/main/texstorage.c index 84b8f8224..5062fdb4f 100644 --- a/mesalib/src/mesa/main/texstorage.c +++ b/mesalib/src/mesa/main/texstorage.c @@ -37,7 +37,9 @@ #include "macros.h" #include "teximage.h" #include "texobj.h" +#include "mipmap.h" #include "texstorage.h" +#include "textureview.h" #include "mtypes.h" @@ -73,8 +75,7 @@ legal_texobj_target(struct gl_context *ctx, GLuint dims, GLenum target) return ctx->Extensions.NV_texture_rectangle; case GL_TEXTURE_1D_ARRAY: case GL_PROXY_TEXTURE_1D_ARRAY: - return (ctx->Extensions.MESA_texture_array || - ctx->Extensions.EXT_texture_array); + return ctx->Extensions.EXT_texture_array; default: return GL_FALSE; } @@ -85,8 +86,7 @@ legal_texobj_target(struct gl_context *ctx, GLuint dims, GLenum target) return GL_TRUE; case GL_TEXTURE_2D_ARRAY: case GL_PROXY_TEXTURE_2D_ARRAY: - return (ctx->Extensions.MESA_texture_array || - ctx->Extensions.EXT_texture_array); + return ctx->Extensions.EXT_texture_array; case GL_TEXTURE_CUBE_MAP_ARRAY: case GL_PROXY_TEXTURE_CUBE_MAP_ARRAY: return ctx->Extensions.ARB_texture_cube_map_array; @@ -100,27 +100,6 @@ legal_texobj_target(struct gl_context *ctx, GLuint dims, GLenum target) } -/** - * Compute the size of the next mipmap level. - */ -static void -next_mipmap_level_size(GLenum target, - GLint *width, GLint *height, GLint *depth) -{ - if (*width > 1) { - *width /= 2; - } - - if ((*height > 1) && (target != GL_TEXTURE_1D_ARRAY)) { - *height /= 2; - } - - if ((*depth > 1) && (target != GL_TEXTURE_2D_ARRAY)) { - *depth /= 2; - } -} - - /** Helper to get a particular texture image in a texture object */ static struct gl_texture_image * get_tex_image(struct gl_context *ctx, @@ -164,7 +143,8 @@ initialize_texture_fields(struct gl_context *ctx, 0, internalFormat, texFormat); } - next_mipmap_level_size(target, &levelWidth, &levelHeight, &levelDepth); + _mesa_next_mipmap_level_size(target, 0, levelWidth, levelHeight, levelDepth, + &levelWidth, &levelHeight, &levelDepth); } return GL_TRUE; } @@ -436,8 +416,8 @@ texstorage(GLuint dims, GLenum target, GLsizei levels, GLenum internalformat, return; } - texObj->Immutable = GL_TRUE; - texObj->ImmutableLevels = levels; + _mesa_set_texture_view_state(ctx, texObj, target, levels); + } } diff --git a/mesalib/src/mesa/main/texstore.c b/mesalib/src/mesa/main/texstore.c index 76d8d9ba3..5adbd5dc9 100644 --- a/mesalib/src/mesa/main/texstore.c +++ b/mesalib/src/mesa/main/texstore.c @@ -3864,6 +3864,7 @@ _mesa_texstore_memcpy(TEXSTORE_PARAMS) /** * Store user data into texture memory. * Called via glTex[Sub]Image1/2/3D() + * \return GL_TRUE for success, GL_FALSE for failure (out of memory). */ GLboolean _mesa_texstore(TEXSTORE_PARAMS) diff --git a/mesalib/src/mesa/main/textureview.c b/mesalib/src/mesa/main/textureview.c new file mode 100644 index 000000000..5f88a4171 --- /dev/null +++ b/mesalib/src/mesa/main/textureview.c @@ -0,0 +1,668 @@ +/* + * Mesa 3-D graphics library + * + * Copyright (C) 2013 LunarG, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included + * in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + * + * Authors: + * Courtney Goeltzenleuchter + */ + + +/** + * \file textureview.c + * GL_ARB_texture_view functions + */ + +#include "glheader.h" +#include "context.h" +#include "enums.h" +#include "imports.h" +#include "macros.h" +#include "teximage.h" +#include "texobj.h" +#include "mipmap.h" +#include "texstorage.h" +#include "textureview.h" +#include "stdbool.h" +#include "mtypes.h" + +/* Table 3.X.2 (Compatible internal formats for TextureView) + --------------------------------------------------------------------------- + | Class | Internal formats | + --------------------------------------------------------------------------- + | VIEW_CLASS_128_BITS | RGBA32F, RGBA32UI, RGBA32I | + --------------------------------------------------------------------------- + | VIEW_CLASS_96_BITS | RGB32F, RGB32UI, RGB32I | + --------------------------------------------------------------------------- + | VIEW_CLASS_64_BITS | RGBA16F, RG32F, RGBA16UI, RG32UI, RGBA16I, | + | | RG32I, RGBA16, RGBA16_SNORM | + --------------------------------------------------------------------------- + | VIEW_CLASS_48_BITS | RGB16, RGB16_SNORM, RGB16F, RGB16UI, RGB16I | + --------------------------------------------------------------------------- + | VIEW_CLASS_32_BITS | RG16F, R11F_G11F_B10F, R32F, | + | | RGB10_A2UI, RGBA8UI, RG16UI, R32UI, | + | | RGBA8I, RG16I, R32I, RGB10_A2, RGBA8, RG16, | + | | RGBA8_SNORM, RG16_SNORM, SRGB8_ALPHA8, RGB9_E5 | + --------------------------------------------------------------------------- + | VIEW_CLASS_24_BITS | RGB8, RGB8_SNORM, SRGB8, RGB8UI, RGB8I | + --------------------------------------------------------------------------- + | VIEW_CLASS_16_BITS | R16F, RG8UI, R16UI, RG8I, R16I, RG8, R16, | + | | RG8_SNORM, R16_SNORM | + --------------------------------------------------------------------------- + | VIEW_CLASS_8_BITS | R8UI, R8I, R8, R8_SNORM | + --------------------------------------------------------------------------- + | VIEW_CLASS_RGTC1_RED | COMPRESSED_RED_RGTC1, | + | | COMPRESSED_SIGNED_RED_RGTC1 | + --------------------------------------------------------------------------- + | VIEW_CLASS_RGTC2_RG | COMPRESSED_RG_RGTC2, | + | | COMPRESSED_SIGNED_RG_RGTC2 | + --------------------------------------------------------------------------- + | VIEW_CLASS_BPTC_UNORM | COMPRESSED_RGBA_BPTC_UNORM, | + | | COMPRESSED_SRGB_ALPHA_BPTC_UNORM | + --------------------------------------------------------------------------- + | VIEW_CLASS_BPTC_FLOAT | COMPRESSED_RGB_BPTC_SIGNED_FLOAT, | + | | COMPRESSED_RGB_BPTC_UNSIGNED_FLOAT | + --------------------------------------------------------------------------- + */ +struct internal_format_class_info { + GLenum view_class; + GLenum internal_format; +}; +static const struct internal_format_class_info compatible_internal_formats[] = { + {GL_VIEW_CLASS_128_BITS, GL_RGBA32F}, + {GL_VIEW_CLASS_128_BITS, GL_RGBA32UI}, + {GL_VIEW_CLASS_128_BITS, GL_RGBA32I}, + {GL_VIEW_CLASS_96_BITS, GL_RGB32F}, + {GL_VIEW_CLASS_96_BITS, GL_RGB32UI}, + {GL_VIEW_CLASS_96_BITS, GL_RGB32I}, + {GL_VIEW_CLASS_64_BITS, GL_RGBA16F}, + {GL_VIEW_CLASS_64_BITS, GL_RG32F}, + {GL_VIEW_CLASS_64_BITS, GL_RGBA16UI}, + {GL_VIEW_CLASS_64_BITS, GL_RG32UI}, + {GL_VIEW_CLASS_64_BITS, GL_RGBA16I}, + {GL_VIEW_CLASS_64_BITS, GL_RG32I}, + {GL_VIEW_CLASS_64_BITS, GL_RGBA16}, + {GL_VIEW_CLASS_64_BITS, GL_RGBA16_SNORM}, + {GL_VIEW_CLASS_48_BITS, GL_RGB16}, + {GL_VIEW_CLASS_48_BITS, GL_RGB16_SNORM}, + {GL_VIEW_CLASS_48_BITS, GL_RGB16F}, + {GL_VIEW_CLASS_48_BITS, GL_RGB16UI}, + {GL_VIEW_CLASS_48_BITS, GL_RGB16I}, + {GL_VIEW_CLASS_32_BITS, GL_RG16F}, + {GL_VIEW_CLASS_32_BITS, GL_R11F_G11F_B10F}, + {GL_VIEW_CLASS_32_BITS, GL_R32F}, + {GL_VIEW_CLASS_32_BITS, GL_RGB10_A2UI}, + {GL_VIEW_CLASS_32_BITS, GL_RGBA8UI}, + {GL_VIEW_CLASS_32_BITS, GL_RG16UI}, + {GL_VIEW_CLASS_32_BITS, GL_R32UI}, + {GL_VIEW_CLASS_32_BITS, GL_RGBA8I}, + {GL_VIEW_CLASS_32_BITS, GL_RG16I}, + {GL_VIEW_CLASS_32_BITS, GL_R32I}, + {GL_VIEW_CLASS_32_BITS, GL_RGB10_A2}, + {GL_VIEW_CLASS_32_BITS, GL_RGBA8}, + {GL_VIEW_CLASS_32_BITS, GL_RG16}, + {GL_VIEW_CLASS_32_BITS, GL_RGBA8_SNORM}, + {GL_VIEW_CLASS_32_BITS, GL_RG16_SNORM}, + {GL_VIEW_CLASS_32_BITS, GL_SRGB8_ALPHA8}, + {GL_VIEW_CLASS_32_BITS, GL_RGB9_E5}, + {GL_VIEW_CLASS_24_BITS, GL_RGB8}, + {GL_VIEW_CLASS_24_BITS, GL_RGB8_SNORM}, + {GL_VIEW_CLASS_24_BITS, GL_SRGB8}, + {GL_VIEW_CLASS_24_BITS, GL_RGB8UI}, + {GL_VIEW_CLASS_24_BITS, GL_RGB8I}, + {GL_VIEW_CLASS_16_BITS, GL_R16F}, + {GL_VIEW_CLASS_16_BITS, GL_RG8UI}, + {GL_VIEW_CLASS_16_BITS, GL_R16UI}, + {GL_VIEW_CLASS_16_BITS, GL_RG8I}, + {GL_VIEW_CLASS_16_BITS, GL_R16I}, + {GL_VIEW_CLASS_16_BITS, GL_RG8}, + {GL_VIEW_CLASS_16_BITS, GL_R16}, + {GL_VIEW_CLASS_16_BITS, GL_RG8_SNORM}, + {GL_VIEW_CLASS_16_BITS, GL_R16_SNORM}, + {GL_VIEW_CLASS_8_BITS, GL_R8UI}, + {GL_VIEW_CLASS_8_BITS, GL_R8I}, + {GL_VIEW_CLASS_8_BITS, GL_R8}, + {GL_VIEW_CLASS_8_BITS, GL_R8_SNORM}, + {GL_VIEW_CLASS_RGTC1_RED, GL_COMPRESSED_RED_RGTC1}, + {GL_VIEW_CLASS_RGTC1_RED, GL_COMPRESSED_SIGNED_RED_RGTC1}, + {GL_VIEW_CLASS_RGTC2_RG, GL_COMPRESSED_RG_RGTC2}, + {GL_VIEW_CLASS_RGTC2_RG, GL_COMPRESSED_SIGNED_RG_RGTC2}, + {GL_VIEW_CLASS_BPTC_UNORM, GL_COMPRESSED_RGBA_BPTC_UNORM_ARB}, + {GL_VIEW_CLASS_BPTC_UNORM, GL_COMPRESSED_SRGB_ALPHA_BPTC_UNORM_ARB}, + {GL_VIEW_CLASS_BPTC_FLOAT, GL_COMPRESSED_RGB_BPTC_SIGNED_FLOAT_ARB}, + {GL_VIEW_CLASS_BPTC_FLOAT, GL_COMPRESSED_RGB_BPTC_UNSIGNED_FLOAT_ARB}, +}; + +static const struct internal_format_class_info s3tc_compatible_internal_formats[] = { + {GL_VIEW_CLASS_S3TC_DXT1_RGB, GL_COMPRESSED_RGB_S3TC_DXT1_EXT}, + {GL_VIEW_CLASS_S3TC_DXT1_RGB, GL_COMPRESSED_SRGB_S3TC_DXT1_EXT}, + {GL_VIEW_CLASS_S3TC_DXT1_RGBA, GL_COMPRESSED_RGBA_S3TC_DXT1_EXT}, + {GL_VIEW_CLASS_S3TC_DXT1_RGBA, GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT1_EXT}, + {GL_VIEW_CLASS_S3TC_DXT3_RGBA, GL_COMPRESSED_RGBA_S3TC_DXT3_EXT}, + {GL_VIEW_CLASS_S3TC_DXT3_RGBA, GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT3_EXT}, + {GL_VIEW_CLASS_S3TC_DXT5_RGBA, GL_COMPRESSED_RGBA_S3TC_DXT5_EXT}, + {GL_VIEW_CLASS_S3TC_DXT5_RGBA, GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT5_EXT}, +}; + +/** + * Lookup format view class based on internalformat + * \return VIEW_CLASS if internalformat found in table, false otherwise. + */ +static GLenum +lookup_view_class(struct gl_context *ctx, GLenum internalformat) +{ + GLuint i; + + for (i = 0; i < ARRAY_SIZE(compatible_internal_formats); i++) { + if (compatible_internal_formats[i].internal_format == internalformat) + return compatible_internal_formats[i].view_class; + } + + if (ctx->Extensions.EXT_texture_compression_s3tc && ctx->Extensions.EXT_texture_sRGB) { + for (i = 0; i < ARRAY_SIZE(s3tc_compatible_internal_formats); i++) { + if (s3tc_compatible_internal_formats[i].internal_format == internalformat) + return s3tc_compatible_internal_formats[i].view_class; + } + } + return GL_FALSE; +} + +/** + * Initialize new texture's gl_texture_image structures. Will not call driver + * to allocate new space, simply record relevant layer, face, format, etc. + * \return GL_FALSE if any error, GL_TRUE otherwise. + */ +static GLboolean +initialize_texture_fields(struct gl_context *ctx, + GLenum target, + struct gl_texture_object *texObj, + GLint levels, + GLsizei width, GLsizei height, GLsizei depth, + GLenum internalFormat, gl_format texFormat) +{ + const GLuint numFaces = _mesa_num_tex_faces(target); + GLint level, levelWidth = width, levelHeight = height, levelDepth = depth; + GLuint face; + + /* Pretend we are bound to initialize the gl_texture_image structs */ + texObj->Target = target; + + /* Set up all the texture object's gl_texture_images */ + for (level = 0; level < levels; level++) { + for (face = 0; face < numFaces; face++) { + struct gl_texture_image *texImage; + GLenum faceTarget = target; + + if (target == GL_TEXTURE_CUBE_MAP) + faceTarget = GL_TEXTURE_CUBE_MAP_POSITIVE_X + face; + + texImage = _mesa_get_tex_image(ctx, texObj, faceTarget, level); + + if (!texImage) { + _mesa_error(ctx, GL_OUT_OF_MEMORY, "glTexStorage"); + return GL_FALSE; + } + + _mesa_init_teximage_fields(ctx, texImage, + levelWidth, levelHeight, levelDepth, + 0, internalFormat, texFormat); + } + + _mesa_next_mipmap_level_size(target, 0, levelWidth, levelHeight, levelDepth, + &levelWidth, &levelHeight, &levelDepth); + } + + /* "unbind" */ + texObj->Target = 0; + + return GL_TRUE; +} + +#define RETURN_IF_SUPPORTED(t) do { \ + if (newTarget == GL_ ## t) \ + return true; \ +} while (0) + +/** + * Check for compatible target + * If an error is found, record it with _mesa_error() + * \return false if any error, true otherwise. + */ +static bool +target_valid(struct gl_context *ctx, GLenum origTarget, GLenum newTarget) +{ + /* + * From ARB_texture_view spec: + --------------------------------------------------------------------------------------------------------- + | Original target | Valid new targets | + --------------------------------------------------------------------------------------------------------- + | TEXTURE_1D | TEXTURE_1D, TEXTURE_1D_ARRAY | + | ------------------------------------------------------------------------------------------------------- | + | TEXTURE_2D | TEXTURE_2D, TEXTURE_2D_ARRAY | + | ------------------------------------------------------------------------------------------------------- | + | TEXTURE_3D | TEXTURE_3D | + | ------------------------------------------------------------------------------------------------------- | + | TEXTURE_CUBE_MAP | TEXTURE_CUBE_MAP, TEXTURE_2D, TEXTURE_2D_ARRAY, TEXTURE_CUBE_MAP_ARRAY | + | ------------------------------------------------------------------------------------------------------- | + | TEXTURE_RECTANGLE | TEXTURE_RECTANGLE | + | ------------------------------------------------------------------------------------------------------- | + | TEXTURE_BUFFER | | + | ------------------------------------------------------------------------------------------------------- | + | TEXTURE_1D_ARRAY | TEXTURE_1D_ARRAY, TEXTURE_1D | + | ------------------------------------------------------------------------------------------------------- | + | TEXTURE_2D_ARRAY | TEXTURE_2D_ARRAY, TEXTURE_2D, TEXTURE_CUBE_MAP, TEXTURE_CUBE_MAP_ARRAY | + | ------------------------------------------------------------------------------------------------------- | + | TEXTURE_CUBE_MAP_ARRAY | TEXTURE_CUBE_MAP_ARRAY, TEXTURE_2D_ARRAY, TEXTURE_2D, TEXTURE_CUBE_MAP | + | ------------------------------------------------------------------------------------------------------- | + | TEXTURE_2D_MULTISAMPLE | TEXTURE_2D_MULTISAMPLE, TEXTURE_2D_MULTISAMPLE_ARRAY | + | ------------------------------------------------------------------------------------------------------- | + | TEXTURE_2D_MULTISAMPLE_ARRAY | TEXTURE_2D_MULTISAMPLE, TEXTURE_2D_MULTISAMPLE_ARRAY | + --------------------------------------------------------------------------------------------------------- + */ + + switch (origTarget) { + case GL_TEXTURE_1D: + case GL_TEXTURE_1D_ARRAY: + RETURN_IF_SUPPORTED(TEXTURE_1D); + RETURN_IF_SUPPORTED(TEXTURE_1D_ARRAY); + break; + case GL_TEXTURE_2D: + RETURN_IF_SUPPORTED(TEXTURE_2D); + RETURN_IF_SUPPORTED(TEXTURE_2D_ARRAY); + break; + case GL_TEXTURE_3D: + RETURN_IF_SUPPORTED(TEXTURE_3D); + break; + case GL_TEXTURE_RECTANGLE: + RETURN_IF_SUPPORTED(TEXTURE_RECTANGLE); + break; + case GL_TEXTURE_CUBE_MAP: + case GL_TEXTURE_2D_ARRAY: + case GL_TEXTURE_CUBE_MAP_ARRAY: + RETURN_IF_SUPPORTED(TEXTURE_2D); + RETURN_IF_SUPPORTED(TEXTURE_2D_ARRAY); + RETURN_IF_SUPPORTED(TEXTURE_CUBE_MAP); + RETURN_IF_SUPPORTED(TEXTURE_CUBE_MAP_ARRAY); + break; + case GL_TEXTURE_2D_MULTISAMPLE: + case GL_TEXTURE_2D_MULTISAMPLE_ARRAY: + RETURN_IF_SUPPORTED(TEXTURE_2D_MULTISAMPLE); + RETURN_IF_SUPPORTED(TEXTURE_2D_MULTISAMPLE_ARRAY); + break; + } + _mesa_error(ctx, GL_INVALID_OPERATION, + "glTextureView(illegal target=%s)", + _mesa_lookup_enum_by_nr(newTarget)); + return false; +} +#undef RETURN_IF_SUPPORTED + +/** + * Check for compatible format + * If an error is found, record it with _mesa_error() + * \return false if any error, true otherwise. + */ +static bool +compatible_format(struct gl_context *ctx, const struct gl_texture_object *origTexObj, + GLenum internalformat) +{ + /* Level 0 of a texture created by glTextureStorage or glTextureView + * is always defined. + */ + struct gl_texture_image *texImage = origTexObj->Image[0][0]; + GLint origInternalFormat = texImage->InternalFormat; + unsigned int origViewClass, newViewClass; + + /* The two textures' internal formats must be compatible according to + * Table 3.X.2 (Compatible internal formats for TextureView) + * if the internal format exists in that table the view class must match. + * The internal formats must be identical if not in that table, + * or an INVALID_OPERATION error is generated. + */ + if (origInternalFormat == internalformat) + return true; + + origViewClass = lookup_view_class(ctx, origInternalFormat); + newViewClass = lookup_view_class(ctx, internalformat); + if ((origViewClass == newViewClass) && origViewClass != false) + return true; + + _mesa_error(ctx, GL_INVALID_OPERATION, + "glTextureView(internalformat %s not compatible with origtexture %s)", + _mesa_lookup_enum_by_nr(internalformat), + _mesa_lookup_enum_by_nr(origInternalFormat)); + return false; +} +/** + * Helper function for TexStorage and teximagemultisample to set immutable + * texture state needed by ARB_texture_view. + */ +void +_mesa_set_texture_view_state(struct gl_context *ctx, + struct gl_texture_object *texObj, + GLenum target, GLuint levels) +{ + struct gl_texture_image *texImage; + + /* Get a reference to what will become this View's base level */ + texImage = _mesa_select_tex_image(ctx, texObj, target, 0); + + /* When an immutable texture is created via glTexStorage or glTexImageMultisample, + * TEXTURE_IMMUTABLE_FORMAT becomes TRUE. + * TEXTURE_IMMUTABLE_LEVELS and TEXTURE_VIEW_NUM_LEVELS become levels. + * If the texture target is TEXTURE_1D_ARRAY then + * TEXTURE_VIEW_NUM_LAYERS becomes height. + * If the texture target is TEXTURE_2D_ARRAY, TEXTURE_CUBE_MAP_ARRAY, + * or TEXTURE_2D_MULTISAMPLE_ARRAY then TEXTURE_VIEW_NUM_LAYERS becomes depth. + * If the texture target is TEXTURE_CUBE_MAP, then + * TEXTURE_VIEW_NUM_LAYERS becomes 6. + * For any other texture target, TEXTURE_VIEW_NUM_LAYERS becomes 1. + * + * ARB_texture_multisample: Multisample textures do + * not have multiple image levels. + */ + + texObj->Immutable = GL_TRUE; + texObj->ImmutableLevels = levels; + texObj->MinLevel = 0; + texObj->NumLevels = levels; + texObj->MinLayer = 0; + texObj->NumLayers = 1; + switch (target) { + case GL_TEXTURE_1D_ARRAY: + texObj->NumLayers = texImage->Height; + break; + + case GL_TEXTURE_2D_MULTISAMPLE: + texObj->NumLevels = 1; + texObj->ImmutableLevels = 1; + break; + + case GL_TEXTURE_2D_MULTISAMPLE_ARRAY: + texObj->NumLevels = 1; + texObj->ImmutableLevels = 1; + /* fall through to set NumLayers */ + + case GL_TEXTURE_2D_ARRAY: + case GL_TEXTURE_CUBE_MAP_ARRAY: + texObj->NumLayers = texImage->Depth; + break; + + case GL_TEXTURE_CUBE_MAP: + texObj->NumLayers = 6; + break; + + } +} + +/** + * glTextureView (ARB_texture_view) + * If an error is found, record it with _mesa_error() + * \return none. + */ +void GLAPIENTRY +_mesa_TextureView(GLuint texture, GLenum target, GLuint origtexture, + GLenum internalformat, + GLuint minlevel, GLuint numlevels, + GLuint minlayer, GLuint numlayers) +{ + struct gl_texture_object *texObj; + struct gl_texture_object *origTexObj; + struct gl_texture_image *origTexImage; + GLuint newViewMinLevel, newViewMinLayer; + GLuint newViewNumLevels, newViewNumLayers; + GLsizei width, height, depth; + gl_format texFormat; + GLboolean sizeOK, dimensionsOK; + GLenum faceTarget; + + GET_CURRENT_CONTEXT(ctx); + + if (MESA_VERBOSE & (VERBOSE_API | VERBOSE_TEXTURE)) + _mesa_debug(ctx, "glTextureView %d %s %d %s %d %d %d %d\n", + texture, _mesa_lookup_enum_by_nr(target), origtexture, + _mesa_lookup_enum_by_nr(internalformat), + minlevel, numlevels, minlayer, numlayers); + + if (origtexture == 0) { + _mesa_error(ctx, GL_INVALID_VALUE, "glTextureView(origtexture = %u)", origtexture); + return; + } + + /* Need original texture information to validate arguments */ + origTexObj = _mesa_lookup_texture(ctx, origtexture); + + /* If is not the name of a texture, INVALID_VALUE is generated. */ + if (!origTexObj) { + _mesa_error(ctx, GL_INVALID_VALUE, "glTextureView(origtexture = %u)", origtexture); + return; + } + + /* If 's TEXTURE_IMMUTABLE_FORMAT value is not TRUE, + * INVALID_OPERATION is generated. + */ + if (!origTexObj->Immutable) { + _mesa_error(ctx, GL_INVALID_OPERATION, "glTextureView(origtexture not immutable)"); + return; + } + + /* If is 0, INVALID_VALUE is generated. */ + if (texture == 0) { + _mesa_error(ctx, GL_INVALID_VALUE, "glTextureView(texture = 0)"); + return; + } + + /* If is not a valid name returned by GenTextures, + * the error INVALID_OPERATION is generated. + */ + texObj = _mesa_lookup_texture(ctx, texture); + if (texObj == NULL) { + _mesa_error(ctx, GL_INVALID_OPERATION, "glTextureView(texture = %u non-gen name)", texture); + return; + } + + /* If has already been bound and given a target, then + * the error INVALID_OPERATION is generated. + */ + if (texObj->Target) { + _mesa_error(ctx, GL_INVALID_OPERATION, "glTextureView(texture = %u already bound)", texture); + return; + } + + /* Check for compatible target */ + if (!target_valid(ctx, origTexObj->Target, target)) { + return; /* error was recorded */ + } + + /* minlevel and minlayer are relative to the view of origtexture + * If minlevel or minlayer is greater than level or layer, respectively, + * of origtexture return INVALID_VALUE. + */ + newViewMinLevel = origTexObj->MinLevel + minlevel; + newViewMinLayer = origTexObj->MinLayer + minlayer; + if (newViewMinLevel >= (origTexObj->MinLevel + origTexObj->NumLevels)) { + _mesa_error(ctx, GL_INVALID_VALUE, + "glTextureView(new minlevel (%d) > orig minlevel (%d) + orig numlevels (%d))", + newViewMinLevel, origTexObj->MinLevel, origTexObj->NumLevels); + return; + } + + if (newViewMinLayer >= (origTexObj->MinLayer + origTexObj->NumLayers)) { + _mesa_error(ctx, GL_INVALID_VALUE, + "glTextureView(new minlayer (%d) > orig minlayer (%d) + orig numlayers (%d))", + newViewMinLayer, origTexObj->MinLayer, origTexObj->NumLayers); + return; + } + + if (!compatible_format(ctx, origTexObj, internalformat)) { + return; /* Error logged */ + } + + texFormat = _mesa_choose_texture_format(ctx, texObj, target, 0, + internalformat, GL_NONE, GL_NONE); + assert(texFormat != MESA_FORMAT_NONE); + if (texFormat == MESA_FORMAT_NONE) return; + + newViewNumLevels = MIN2(numlevels, origTexObj->NumLevels - minlevel); + newViewNumLayers = MIN2(numlayers, origTexObj->NumLayers - minlayer); + + faceTarget = origTexObj->Target; + if (faceTarget == GL_TEXTURE_CUBE_MAP) + faceTarget = GL_TEXTURE_CUBE_MAP_POSITIVE_X + minlayer; + + /* Get a reference to what will become this View's base level */ + origTexImage = _mesa_select_tex_image(ctx, origTexObj, + faceTarget, minlevel); + width = origTexImage->Width; + height = origTexImage->Height; + depth = origTexImage->Depth; + + /* Adjust width, height, depth to be appropriate for new target */ + switch (target) { + case GL_TEXTURE_1D: + case GL_TEXTURE_3D: + break; + + case GL_TEXTURE_1D_ARRAY: + height = (GLsizei) newViewNumLayers; + break; + + case GL_TEXTURE_2D: + case GL_TEXTURE_2D_MULTISAMPLE: + case GL_TEXTURE_RECTANGLE: + case GL_TEXTURE_CUBE_MAP: + depth = 1; + break; + + case GL_TEXTURE_2D_ARRAY: + case GL_TEXTURE_CUBE_MAP_ARRAY: + case GL_TEXTURE_2D_MULTISAMPLE_ARRAY: + depth = newViewNumLayers; + break; + } + + /* If the dimensions of the original texture are larger than the maximum + * supported dimensions of the new target, the error INVALID_OPERATION is + * generated. For example, if the original texture has a TEXTURE_2D_ARRAY + * target and its width is greater than MAX_CUBE_MAP_TEXTURE_SIZE, an error + * will be generated if TextureView is called to create a TEXTURE_CUBE_MAP + * view. + */ + dimensionsOK = _mesa_legal_texture_dimensions(ctx, target, 0, + width, height, depth, 0); + if (!dimensionsOK) { + _mesa_error(ctx, GL_INVALID_OPERATION, "glTextureView(invalid width or height or depth)"); + return; + } + + sizeOK = ctx->Driver.TestProxyTexImage(ctx, target, 0, texFormat, + width, height, depth, 0); + if (!sizeOK) { + _mesa_error(ctx, GL_INVALID_OPERATION, "glTextureView(invalid texture size)"); + return; + } + + /* If is TEXTURE_1D, TEXTURE_2D, TEXTURE_3D, TEXTURE_RECTANGLE, + * or TEXTURE_2D_MULTISAMPLE and does not equal 1, the error + * INVALID_VALUE is generated. + */ + switch (target) { + case GL_TEXTURE_1D: + case GL_TEXTURE_2D: + case GL_TEXTURE_3D: + case GL_TEXTURE_RECTANGLE: + case GL_TEXTURE_2D_MULTISAMPLE: + if (numlayers != 1) { + _mesa_error(ctx, GL_INVALID_VALUE, "glTextureView(numlayers %d != 1)", numlayers); + return; + } + break; + + case GL_TEXTURE_CUBE_MAP: + /* If the new texture's target is TEXTURE_CUBE_MAP, the clamped + * must be equal to 6. + */ + if (newViewNumLayers != 6) { + _mesa_error(ctx, GL_INVALID_VALUE, "glTextureView(clamped numlayers %d != 6)", + newViewNumLayers); + return; + } + break; + + case GL_TEXTURE_CUBE_MAP_ARRAY: + /* If the new texture's target is TEXTURE_CUBE_MAP_ARRAY, + * then counts layer-faces rather than layers, + * and the clamped must be a multiple of 6. + * Otherwise, the error INVALID_VALUE is generated. + */ + if ((newViewNumLayers % 6) != 0) { + _mesa_error(ctx, GL_INVALID_VALUE, + "glTextureView(clamped numlayers %d is not a multiple of 6)", + newViewNumLayers); + return; + } + break; + } + + /* If the new texture's target is TEXTURE_CUBE_MAP or + * TEXTURE_CUBE_MAP_ARRAY, the width and height of the original texture's + * levels must be equal otherwise the error INVALID_OPERATION is generated. + */ + if ((target == GL_TEXTURE_CUBE_MAP || target == GL_TEXTURE_CUBE_MAP_ARRAY) && + (origTexImage->Width != origTexImage->Height)) { + _mesa_error(ctx, GL_INVALID_OPERATION, "glTextureView(origtexture width (%d) != height (%d))", + origTexImage->Width, origTexImage->Height); + return; + } + + /* When the original texture's target is TEXTURE_CUBE_MAP, the layer + * parameters are interpreted in the same order as if it were a + * TEXTURE_CUBE_MAP_ARRAY with 6 layer-faces. + */ + + /* If the internal format does not exactly match the internal format of the + * original texture, the contents of the memory are reinterpreted in the + * same manner as for image bindings described in + * section 3.9.20 (Texture Image Loads and Stores). + */ + + /* TEXTURE_BASE_LEVEL and TEXTURE_MAX_LEVEL are interpreted + * relative to the view and not relative to the original data store. + */ + + if (!initialize_texture_fields(ctx, target, texObj, newViewNumLevels, + width, height, depth, + internalformat, texFormat)) { + return; /* Already recorded error */ + } + + texObj->MinLevel = newViewMinLevel; + texObj->MinLayer = newViewMinLayer; + texObj->NumLevels = newViewNumLevels; + texObj->NumLayers = newViewNumLayers; + texObj->Immutable = GL_TRUE; + texObj->ImmutableLevels = origTexObj->ImmutableLevels; + texObj->Target = target; + + if (ctx->Driver.TextureView != NULL && !ctx->Driver.TextureView(ctx, texObj, origTexObj)) { + return; /* driver recorded error */ + } +} diff --git a/mesalib/src/mesa/main/textureview.h b/mesalib/src/mesa/main/textureview.h new file mode 100644 index 000000000..3088ac193 --- /dev/null +++ b/mesalib/src/mesa/main/textureview.h @@ -0,0 +1,43 @@ +/* + * Mesa 3-D graphics library + * + * Copyright (C) 2012-2013 LunarG, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included + * in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + * + * Authors: + * Courtney Goeltzenleuchter + */ + + +#ifndef TEXTUREVIEW_H +#define TEXTUREVIEW_H + + +extern void GLAPIENTRY +_mesa_TextureView(GLuint texture, GLenum target, GLuint origtexture, + GLenum internalformat, + GLuint minlevel, GLuint numlevels, + GLuint minlayer, GLuint numlayers); + +extern void +_mesa_set_texture_view_state(struct gl_context *ctx, struct gl_texture_object *texObj, + GLenum target, GLuint levels); + +#endif /* TEXTUREVIEW_H */ diff --git a/mesalib/src/mesa/main/version.c b/mesalib/src/mesa/main/version.c index 55411faf8..00eeca764 100644 --- a/mesalib/src/mesa/main/version.c +++ b/mesalib/src/mesa/main/version.c @@ -224,7 +224,6 @@ compute_version(struct gl_context *ctx) (ctx->Extensions.EXT_stencil_two_side || ctx->Extensions.ATI_separate_stencil)); const GLboolean ver_2_1 = (ver_2_0 && - ctx->Const.GLSLVersion >= 120 && ctx->Extensions.EXT_pixel_buffer_object && ctx->Extensions.EXT_texture_sRGB); const GLboolean ver_3_0 = (ver_2_1 && diff --git a/mesalib/src/mesa/math/m_matrix.c b/mesalib/src/mesa/math/m_matrix.c index 290231527..274f969d2 100644 --- a/mesalib/src/mesa/math/m_matrix.c +++ b/mesalib/src/mesa/math/m_matrix.c @@ -1488,14 +1488,11 @@ _math_matrix_ctr( GLmatrix *m ) void _math_matrix_dtr( GLmatrix *m ) { - if (m->m) { - _mesa_align_free( m->m ); - m->m = NULL; - } - if (m->inv) { - _mesa_align_free( m->inv ); - m->inv = NULL; - } + _mesa_align_free( m->m ); + m->m = NULL; + + _mesa_align_free( m->inv ); + m->inv = NULL; } /*@}*/ diff --git a/mesalib/src/mesa/program/ir_to_mesa.cpp b/mesalib/src/mesa/program/ir_to_mesa.cpp index c833a12f2..23d479c32 100644 --- a/mesalib/src/mesa/program/ir_to_mesa.cpp +++ b/mesalib/src/mesa/program/ir_to_mesa.cpp @@ -681,11 +681,11 @@ ir_to_mesa_visitor::visit(ir_variable *ir) if (strcmp(ir->name, "gl_FragCoord") == 0) { struct gl_fragment_program *fp = (struct gl_fragment_program *)this->prog; - fp->OriginUpperLeft = ir->origin_upper_left; - fp->PixelCenterInteger = ir->pixel_center_integer; + fp->OriginUpperLeft = ir->data.origin_upper_left; + fp->PixelCenterInteger = ir->data.pixel_center_integer; } - if (ir->mode == ir_var_uniform && strncmp(ir->name, "gl_", 3) == 0) { + if (ir->data.mode == ir_var_uniform && strncmp(ir->name, "gl_", 3) == 0) { unsigned int i; const ir_state_slot *const slots = ir->state_slots; assert(ir->state_slots != NULL); @@ -759,49 +759,10 @@ ir_to_mesa_visitor::visit(ir_variable *ir) void ir_to_mesa_visitor::visit(ir_loop *ir) { - ir_dereference_variable *counter = NULL; - - if (ir->counter != NULL) - counter = new(mem_ctx) ir_dereference_variable(ir->counter); - - if (ir->from != NULL) { - assert(ir->counter != NULL); - - ir_assignment *a = - new(mem_ctx) ir_assignment(counter, ir->from, NULL); - - a->accept(this); - } - emit(NULL, OPCODE_BGNLOOP); - if (ir->to) { - ir_expression *e = - new(mem_ctx) ir_expression(ir->cmp, glsl_type::bool_type, - counter, ir->to); - ir_if *if_stmt = new(mem_ctx) ir_if(e); - - ir_loop_jump *brk = - new(mem_ctx) ir_loop_jump(ir_loop_jump::jump_break); - - if_stmt->then_instructions.push_tail(brk); - - if_stmt->accept(this); - } - visit_exec_list(&ir->body_instructions, this); - if (ir->increment) { - ir_expression *e = - new(mem_ctx) ir_expression(ir_binop_add, counter->type, - counter, ir->increment); - - ir_assignment *a = - new(mem_ctx) ir_assignment(counter, e, NULL); - - a->accept(this); - } - emit(NULL, OPCODE_ENDLOOP); } @@ -1567,10 +1528,10 @@ ir_to_mesa_visitor::visit(ir_dereference_variable *ir) ir_variable *var = ir->var; if (!entry) { - switch (var->mode) { + switch (var->data.mode) { case ir_var_uniform: entry = new(mem_ctx) variable_storage(var, PROGRAM_UNIFORM, - var->location); + var->data.location); this->variables.push_tail(entry); break; case ir_var_shader_in: @@ -1579,21 +1540,21 @@ ir_to_mesa_visitor::visit(ir_dereference_variable *ir) * user-assigned generic attributes (glBindVertexLocation), * and user-defined varyings. */ - assert(var->location != -1); + assert(var->data.location != -1); entry = new(mem_ctx) variable_storage(var, PROGRAM_INPUT, - var->location); + var->data.location); break; case ir_var_shader_out: - assert(var->location != -1); + assert(var->data.location != -1); entry = new(mem_ctx) variable_storage(var, PROGRAM_OUTPUT, - var->location); + var->data.location); break; case ir_var_system_value: entry = new(mem_ctx) variable_storage(var, PROGRAM_SYSTEM_VALUE, - var->location); + var->data.location); break; case ir_var_auto: case ir_var_temporary: @@ -2443,7 +2404,7 @@ public: this->idx = -1; this->program_resource_visitor::process(var); - var->location = this->idx; + var->data.location = this->idx; } private: @@ -2538,7 +2499,7 @@ _mesa_generate_parameters_list_for_uniforms(struct gl_shader_program foreach_list(node, sh->ir) { ir_variable *var = ((ir_instruction *) node)->as_variable(); - if ((var == NULL) || (var->mode != ir_var_uniform) + if ((var == NULL) || (var->data.mode != ir_var_uniform) || var->is_in_uniform_block() || (strncmp(var->name, "gl_", 3) == 0)) continue; diff --git a/mesalib/src/mesa/program/prog_parameter.c b/mesalib/src/mesa/program/prog_parameter.c index 4d9cf08d2..54531d255 100644 --- a/mesalib/src/mesa/program/prog_parameter.c +++ b/mesalib/src/mesa/program/prog_parameter.c @@ -83,8 +83,7 @@ _mesa_free_parameter_list(struct gl_program_parameter_list *paramList) free((void *)paramList->Parameters[i].Name); } free(paramList->Parameters); - if (paramList->ParameterValues) - _mesa_align_free(paramList->ParameterValues); + _mesa_align_free(paramList->ParameterValues); free(paramList); } diff --git a/mesalib/src/mesa/program/program.c b/mesalib/src/mesa/program/program.c index 01f8c6f11..cdf1c03fa 100644 --- a/mesalib/src/mesa/program/program.c +++ b/mesalib/src/mesa/program/program.c @@ -1049,6 +1049,14 @@ _mesa_get_min_invocations_per_fragment(struct gl_context *ctx, * has no effect." */ if (ctx->Multisample.Enabled) { + /* The ARB_gpu_shader5 specification says: + * + * "Use of the "sample" qualifier on a fragment shader input + * forces per-sample shading" + */ + if (prog->IsSample) + return MAX2(ctx->DrawBuffer->Visual.samples, 1); + if (prog->Base.SystemValuesRead & (SYSTEM_BIT_SAMPLE_ID | SYSTEM_BIT_SAMPLE_POS)) return MAX2(ctx->DrawBuffer->Visual.samples, 1); diff --git a/mesalib/src/mesa/program/program_parse_extra.c b/mesalib/src/mesa/program/program_parse_extra.c index e8e1912eb..a9e364045 100644 --- a/mesalib/src/mesa/program/program_parse_extra.c +++ b/mesalib/src/mesa/program/program_parse_extra.c @@ -256,15 +256,6 @@ _mesa_ARBfp_parse_option(struct asm_parser_state *state, const char *option) return 1; } } - } else if (strncmp(option, "MESA_", 5) == 0) { - option += 5; - - if (strcmp(option, "texture_array") == 0) { - if (state->ctx->Extensions.MESA_texture_array) { - state->option.TexArray = 1; - return 1; - } - } } return 0; diff --git a/mesalib/src/mesa/state_tracker/st_atom_framebuffer.c b/mesalib/src/mesa/state_tracker/st_atom_framebuffer.c index c752640f4..51f079cda 100644 --- a/mesalib/src/mesa/state_tracker/st_atom_framebuffer.c +++ b/mesalib/src/mesa/state_tracker/st_atom_framebuffer.c @@ -43,56 +43,6 @@ #include "util/u_format.h" -/** - * When doing GL render to texture, we have to be sure that finalize_texture() - * didn't yank out the pipe_resource that we earlier created a surface for. - * Check for that here and create a new surface if needed. - */ -static void -update_renderbuffer_surface(struct st_context *st, - struct st_renderbuffer *strb) -{ - struct pipe_context *pipe = st->pipe; - struct pipe_resource *resource = strb->rtt ? strb->rtt->pt : strb->texture; - int rtt_width = strb->Base.Width; - int rtt_height = strb->Base.Height; - enum pipe_format format = st->ctx->Color.sRGBEnabled ? resource->format : util_format_linear(resource->format); - - if (!strb->surface || - strb->surface->texture->nr_samples != strb->Base.NumSamples || - strb->surface->format != format || - strb->surface->texture != resource || - strb->surface->width != rtt_width || - strb->surface->height != rtt_height) { - GLuint level; - /* find matching mipmap level size */ - for (level = 0; level <= resource->last_level; level++) { - if (u_minify(resource->width0, level) == rtt_width && - u_minify(resource->height0, level) == rtt_height) { - struct pipe_surface surf_tmpl; - memset(&surf_tmpl, 0, sizeof(surf_tmpl)); - surf_tmpl.format = format; - surf_tmpl.u.tex.level = level; - surf_tmpl.u.tex.first_layer = strb->rtt_face + strb->rtt_slice; - surf_tmpl.u.tex.last_layer = strb->rtt_face + strb->rtt_slice; - - pipe_surface_reference(&strb->surface, NULL); - - strb->surface = pipe->create_surface(pipe, - resource, - &surf_tmpl); -#if 0 - printf("-- alloc new surface %d x %d into tex %p\n", - strb->surface->width, strb->surface->height, - texture); -#endif - break; - } - } - } -} - - /** * Update framebuffer state (color, depth, stencil, etc. buffers) */ @@ -121,10 +71,10 @@ update_framebuffer_state( struct st_context *st ) if (strb) { /*printf("--------- framebuffer surface rtt %p\n", strb->rtt);*/ - if (strb->rtt || + if (strb->is_rtt || (strb->texture && util_format_is_srgb(strb->texture->format))) { /* rendering to a GL texture, may have to update surface */ - update_renderbuffer_surface(st, strb); + st_update_renderbuffer_surface(st, strb); } if (strb->surface) { @@ -144,9 +94,9 @@ update_framebuffer_state( struct st_context *st ) */ strb = st_renderbuffer(fb->Attachment[BUFFER_DEPTH].Renderbuffer); if (strb) { - if (strb->rtt) { + if (strb->is_rtt) { /* rendering to a GL texture, may have to update surface */ - update_renderbuffer_surface(st, strb); + st_update_renderbuffer_surface(st, strb); } pipe_surface_reference(&framebuffer->zsbuf, strb->surface); } diff --git a/mesalib/src/mesa/state_tracker/st_atom_sampler.c b/mesalib/src/mesa/state_tracker/st_atom_sampler.c index 302e12981..57670ce25 100644 --- a/mesalib/src/mesa/state_tracker/st_atom_sampler.c +++ b/mesalib/src/mesa/state_tracker/st_atom_sampler.c @@ -130,15 +130,20 @@ convert_sampler(struct st_context *st, struct pipe_sampler_state *sampler, GLuint texUnit) { - struct gl_texture_object *texobj; + const struct gl_texture_object *texobj; struct gl_context *ctx = st->ctx; struct gl_sampler_object *msamp; + const struct gl_texture_image *teximg; + GLenum texBaseFormat; texobj = ctx->Texture.Unit[texUnit]._Current; if (!texobj) { texobj = _mesa_get_fallback_texture(ctx, TEXTURE_2D_INDEX); } + teximg = texobj->Image[0][texobj->BaseLevel]; + texBaseFormat = teximg ? teximg->_BaseFormat : GL_RGBA; + msamp = _mesa_get_samplerobj(ctx, texUnit); memset(sampler, 0, sizeof(*sampler)); @@ -170,21 +175,15 @@ convert_sampler(struct st_context *st, assert(sampler->min_lod <= sampler->max_lod); } + /* For non-black borders... */ if (msamp->BorderColor.ui[0] || msamp->BorderColor.ui[1] || msamp->BorderColor.ui[2] || msamp->BorderColor.ui[3]) { - struct st_texture_object *stobj = st_texture_object(texobj); - struct gl_texture_image *teximg; - GLboolean is_integer = GL_FALSE; + const struct st_texture_object *stobj = st_texture_object_const(texobj); + const GLboolean is_integer = texobj->_IsIntegerFormat; union pipe_color_union border_color; - teximg = texobj->Image[0][texobj->BaseLevel]; - - if (teximg) { - is_integer = _mesa_is_enum_format_integer(teximg->InternalFormat); - } - if (st->apply_texture_swizzle_to_border_color && stobj->sampler_view) { const unsigned char swz[4] = { @@ -196,25 +195,26 @@ convert_sampler(struct st_context *st, st_translate_color(&msamp->BorderColor, &border_color, - teximg ? teximg->_BaseFormat : GL_RGBA, is_integer); + texBaseFormat, is_integer); util_format_apply_color_swizzle(&sampler->border_color, &border_color, swz, is_integer); } else { st_translate_color(&msamp->BorderColor, &sampler->border_color, - teximg ? teximg->_BaseFormat : GL_RGBA, is_integer); + texBaseFormat, is_integer); } } sampler->max_anisotropy = (msamp->MaxAnisotropy == 1.0 ? 0 : (GLuint) msamp->MaxAnisotropy); - /* only care about ARB_shadow, not SGI shadow */ - if (msamp->CompareMode == GL_COMPARE_R_TO_TEXTURE) { + /* If sampling a depth texture and using shadow comparison */ + if ((texBaseFormat == GL_DEPTH_COMPONENT || + texBaseFormat == GL_DEPTH_STENCIL) && + msamp->CompareMode == GL_COMPARE_R_TO_TEXTURE) { sampler->compare_mode = PIPE_TEX_COMPARE_R_TO_TEXTURE; - sampler->compare_func - = st_compare_func_to_pipe(msamp->CompareFunc); + sampler->compare_func = st_compare_func_to_pipe(msamp->CompareFunc); } sampler->seamless_cube_map = diff --git a/mesalib/src/mesa/state_tracker/st_cb_bufferobjects.c b/mesalib/src/mesa/state_tracker/st_cb_bufferobjects.c index 7fa4cbdc4..230ab5449 100644 --- a/mesalib/src/mesa/state_tracker/st_cb_bufferobjects.c +++ b/mesalib/src/mesa/state_tracker/st_cb_bufferobjects.c @@ -422,6 +422,9 @@ st_bufferobj_validate_usage(struct st_context *st, void st_init_bufferobject_functions(struct dd_function_table *functions) { + /* plug in default driver fallbacks (such as for ClearBufferSubData) */ + _mesa_init_buffer_object_functions(functions); + functions->NewBufferObject = st_bufferobj_alloc; functions->DeleteBuffer = st_bufferobj_free; functions->BufferData = st_bufferobj_data; diff --git a/mesalib/src/mesa/state_tracker/st_cb_clear.c b/mesalib/src/mesa/state_tracker/st_cb_clear.c index 8da664afb..887e58bd9 100644 --- a/mesalib/src/mesa/state_tracker/st_cb_clear.c +++ b/mesalib/src/mesa/state_tracker/st_cb_clear.c @@ -51,6 +51,7 @@ #include "pipe/p_state.h" #include "pipe/p_defines.h" #include "util/u_format.h" +#include "util/u_framebuffer.h" #include "util/u_inlines.h" #include "util/u_simple_shaders.h" #include "util/u_draw_quad.h" @@ -129,6 +130,26 @@ set_vertex_shader(struct st_context *st) } +static void +set_vertex_shader_layered(struct st_context *st) +{ + struct pipe_context *pipe = st->pipe; + + if (!pipe->screen->get_param(pipe->screen, PIPE_CAP_TGSI_INSTANCEID) || + !pipe->screen->get_param(pipe->screen, PIPE_CAP_TGSI_VS_LAYER)) { + assert(!"Got layered clear, but the VS layer output is unsupported"); + set_vertex_shader(st); + return; + } + + if (!st->clear.vs_layered) { + st->clear.vs_layered = util_make_layered_clear_vertex_shader(pipe); + } + + cso_set_vertex_shader_handle(st->cso_context, st->clear.vs_layered); +} + + /** * Draw a screen-aligned quadrilateral. * Coords are clip coords with y=0=bottom. @@ -136,15 +157,19 @@ set_vertex_shader(struct st_context *st) static void draw_quad(struct st_context *st, float x0, float y0, float x1, float y1, GLfloat z, + unsigned num_instances, const union pipe_color_union *color) { - struct pipe_context *pipe = st->pipe; - struct pipe_resource *vbuf = NULL; - GLuint i, offset; + struct cso_context *cso = st->cso_context; + struct pipe_vertex_buffer vb = {0}; + GLuint i; float (*vertices)[2][4]; /**< vertex pos + color */ + vb.stride = 8 * sizeof(float); + if (u_upload_alloc(st->uploader, 0, 4 * sizeof(vertices[0]), - &offset, &vbuf, (void **) &vertices) != PIPE_OK) { + &vb.buffer_offset, &vb.buffer, + (void **) &vertices) != PIPE_OK) { return; } @@ -174,16 +199,10 @@ draw_quad(struct st_context *st, u_upload_unmap(st->uploader); /* draw */ - util_draw_vertex_buffer(pipe, - st->cso_context, - vbuf, - cso_get_aux_vertex_buffer_slot(st->cso_context), - offset, - PIPE_PRIM_TRIANGLE_FAN, - 4, /* verts */ - 2); /* attribs/vert */ - - pipe_resource_reference(&vbuf, NULL); + cso_set_vertex_buffers(cso, cso_get_aux_vertex_buffer_slot(cso), 1, &vb); + cso_draw_arrays_instanced(cso, PIPE_PRIM_TRIANGLE_FAN, 0, 4, + 0, num_instances); + pipe_resource_reference(&vb.buffer, NULL); } @@ -194,8 +213,7 @@ draw_quad(struct st_context *st, * ctx->DrawBuffer->_X/Ymin/max fields. */ static void -clear_with_quad(struct gl_context *ctx, - GLboolean color, GLboolean depth, GLboolean stencil) +clear_with_quad(struct gl_context *ctx, unsigned clear_buffers) { struct st_context *st = st_context(ctx); const struct gl_framebuffer *fb = ctx->DrawBuffer; @@ -205,7 +223,8 @@ clear_with_quad(struct gl_context *ctx, const GLfloat x1 = (GLfloat) ctx->DrawBuffer->_Xmax / fb_width * 2.0f - 1.0f; const GLfloat y0 = (GLfloat) ctx->DrawBuffer->_Ymin / fb_height * 2.0f - 1.0f; const GLfloat y1 = (GLfloat) ctx->DrawBuffer->_Ymax / fb_height * 2.0f - 1.0f; - union pipe_color_union clearColor; + unsigned num_layers = + util_framebuffer_get_num_layers(&st->state.framebuffer); /* printf("%s %s%s%s %f,%f %f,%f\n", __FUNCTION__, @@ -233,7 +252,7 @@ clear_with_quad(struct gl_context *ctx, { struct pipe_blend_state blend; memset(&blend, 0, sizeof(blend)); - if (color) { + if (clear_buffers & PIPE_CLEAR_COLOR) { int num_buffers = ctx->Extensions.EXT_draw_buffers2 ? ctx->DrawBuffer->_NumColorDrawBuffers : 1; int i; @@ -241,6 +260,9 @@ clear_with_quad(struct gl_context *ctx, blend.independent_blend_enable = num_buffers > 1; for (i = 0; i < num_buffers; i++) { + if (!(clear_buffers & (PIPE_CLEAR_COLOR0 << i))) + continue; + if (ctx->Color.ColorMask[i][0]) blend.rt[i].colormask |= PIPE_MASK_R; if (ctx->Color.ColorMask[i][1]) @@ -261,13 +283,13 @@ clear_with_quad(struct gl_context *ctx, { struct pipe_depth_stencil_alpha_state depth_stencil; memset(&depth_stencil, 0, sizeof(depth_stencil)); - if (depth) { + if (clear_buffers & PIPE_CLEAR_DEPTH) { depth_stencil.depth.enabled = 1; depth_stencil.depth.writemask = 1; depth_stencil.depth.func = PIPE_FUNC_ALWAYS; } - if (stencil) { + if (clear_buffers & PIPE_CLEAR_STENCIL) { struct pipe_stencil_ref stencil_ref; memset(&stencil_ref, 0, sizeof(stencil_ref)); depth_stencil.stencil[0].enabled = 1; @@ -305,21 +327,20 @@ clear_with_quad(struct gl_context *ctx, } set_fragment_shader(st); - set_vertex_shader(st); cso_set_geometry_shader_handle(st->cso_context, NULL); - if (ctx->DrawBuffer->_ColorDrawBuffers[0]) { - struct gl_renderbuffer *rb = ctx->DrawBuffer->_ColorDrawBuffers[0]; - GLboolean is_integer = _mesa_is_enum_format_integer(rb->InternalFormat); + if (num_layers > 1) + set_vertex_shader_layered(st); + else + set_vertex_shader(st); - st_translate_color(&ctx->Color.ClearColor, - &clearColor, - ctx->DrawBuffer->_ColorDrawBuffers[0]->_BaseFormat, - is_integer); - } + /* We can't translate the clear color to the colorbuffer format, + * because different colorbuffers may have different formats. + */ /* draw quad matching scissor rect */ - draw_quad(st, x0, y0, x1, y1, (GLfloat) ctx->Depth.Clear, &clearColor); + draw_quad(st, x0, y0, x1, y1, (GLfloat) ctx->Depth.Clear, num_layers, + (union pipe_color_union*)&ctx->Color.ClearColor); /* Restore pipe state */ cso_restore_blend(st->cso_context); @@ -351,6 +372,19 @@ is_scissor_enabled(struct gl_context *ctx, struct gl_renderbuffer *rb) } +/** + * Return if all of the color channels are masked. + */ +static INLINE GLboolean +is_color_disabled(struct gl_context *ctx, int i) +{ + return !ctx->Color.ColorMask[i][0] && + !ctx->Color.ColorMask[i][1] && + !ctx->Color.ColorMask[i][2] && + !ctx->Color.ColorMask[i][3]; +} + + /** * Return if any of the color channels are masked. */ @@ -408,11 +442,14 @@ st_Clear(struct gl_context *ctx, GLbitfield mask) if (!strb || !strb->surface) continue; + if (is_color_disabled(ctx, colormask_index)) + continue; + if (is_scissor_enabled(ctx, rb) || is_color_masked(ctx, colormask_index)) - quad_buffers |= PIPE_CLEAR_COLOR; + quad_buffers |= PIPE_CLEAR_COLOR0 << i; else - clear_buffers |= PIPE_CLEAR_COLOR; + clear_buffers |= PIPE_CLEAR_COLOR0 << i; } } } @@ -445,24 +482,13 @@ st_Clear(struct gl_context *ctx, GLbitfield mask) */ if (quad_buffers) { quad_buffers |= clear_buffers; - clear_with_quad(ctx, - quad_buffers & PIPE_CLEAR_COLOR, - quad_buffers & PIPE_CLEAR_DEPTH, - quad_buffers & PIPE_CLEAR_STENCIL); + clear_with_quad(ctx, quad_buffers); } else if (clear_buffers) { - union pipe_color_union clearColor; - - if (ctx->DrawBuffer->_ColorDrawBuffers[0]) { - struct gl_renderbuffer *rb = ctx->DrawBuffer->_ColorDrawBuffers[0]; - GLboolean is_integer = _mesa_is_enum_format_integer(rb->InternalFormat); - - st_translate_color(&ctx->Color.ClearColor, - &clearColor, - ctx->DrawBuffer->_ColorDrawBuffers[0]->_BaseFormat, - is_integer); - } - - st->pipe->clear(st->pipe, clear_buffers, &clearColor, + /* We can't translate the clear color to the colorbuffer format, + * because different colorbuffers may have different formats. + */ + st->pipe->clear(st->pipe, clear_buffers, + (union pipe_color_union*)&ctx->Color.ClearColor, ctx->Depth.Clear, ctx->Stencil.Clear); } if (mask & BUFFER_BIT_ACCUM) diff --git a/mesalib/src/mesa/state_tracker/st_cb_drawpixels.c b/mesalib/src/mesa/state_tracker/st_cb_drawpixels.c index 2ce4728ad..3058dfb5b 100644 --- a/mesalib/src/mesa/state_tracker/st_cb_drawpixels.c +++ b/mesalib/src/mesa/state_tracker/st_cb_drawpixels.c @@ -878,7 +878,8 @@ draw_stencil_pixels(struct gl_context *ctx, GLint x, GLint y, } stmap = pipe_transfer_map(pipe, strb->texture, - strb->rtt_level, strb->rtt_face + strb->rtt_slice, + strb->surface->u.tex.level, + strb->surface->u.tex.first_layer, usage, x, y, width, height, &pt); @@ -1263,8 +1264,8 @@ copy_stencil_pixels(struct gl_context *ctx, GLint srcx, GLint srcy, /* map the stencil buffer */ drawMap = pipe_transfer_map(pipe, rbDraw->texture, - rbDraw->rtt_level, - rbDraw->rtt_face + rbDraw->rtt_slice, + rbDraw->surface->u.tex.level, + rbDraw->surface->u.tex.first_layer, usage, dstx, dsty, width, height, &ptDraw); @@ -1422,20 +1423,20 @@ blit_copy_pixels(struct gl_context *ctx, GLint srcx, GLint srcy, memset(&blit, 0, sizeof(blit)); blit.src.resource = rbRead->texture; - blit.src.level = rbRead->rtt_level; + blit.src.level = rbRead->surface->u.tex.level; blit.src.format = rbRead->texture->format; blit.src.box.x = readX; blit.src.box.y = readY; - blit.src.box.z = rbRead->rtt_face + rbRead->rtt_slice; + blit.src.box.z = rbRead->surface->u.tex.first_layer; blit.src.box.width = readW; blit.src.box.height = readH; blit.src.box.depth = 1; blit.dst.resource = rbDraw->texture; - blit.dst.level = rbDraw->rtt_level; + blit.dst.level = rbDraw->surface->u.tex.level; blit.dst.format = rbDraw->texture->format; blit.dst.box.x = drawX; blit.dst.box.y = drawY; - blit.dst.box.z = rbDraw->rtt_face + rbDraw->rtt_slice; + blit.dst.box.z = rbDraw->surface->u.tex.first_layer; blit.dst.box.width = drawW; blit.dst.box.height = drawH; blit.dst.box.depth = 1; @@ -1633,11 +1634,11 @@ st_CopyPixels(struct gl_context *ctx, GLint srcx, GLint srcy, memset(&blit, 0, sizeof(blit)); blit.src.resource = rbRead->texture; - blit.src.level = rbRead->rtt_level; + blit.src.level = rbRead->surface->u.tex.level; blit.src.format = rbRead->texture->format; blit.src.box.x = readX; blit.src.box.y = readY; - blit.src.box.z = rbRead->rtt_face + rbRead->rtt_slice; + blit.src.box.z = rbRead->surface->u.tex.first_layer; blit.src.box.width = readW; blit.src.box.height = readH; blit.src.box.depth = 1; diff --git a/mesalib/src/mesa/state_tracker/st_cb_fbo.c b/mesalib/src/mesa/state_tracker/st_cb_fbo.c index 20894825f..70baa9965 100644 --- a/mesalib/src/mesa/state_tracker/st_cb_fbo.c +++ b/mesalib/src/mesa/state_tracker/st_cb_fbo.c @@ -388,6 +388,72 @@ st_bind_framebuffer(struct gl_context *ctx, GLenum target, } +/** + * Create or update the pipe_surface of a FBO renderbuffer. + * This is usually called after st_finalize_texture. + */ +void +st_update_renderbuffer_surface(struct st_context *st, + struct st_renderbuffer *strb) +{ + struct pipe_context *pipe = st->pipe; + struct pipe_resource *resource = strb->texture; + int rtt_width = strb->Base.Width; + int rtt_height = strb->Base.Height; + int rtt_depth = strb->Base.Depth; + enum pipe_format format = st->ctx->Color.sRGBEnabled ? resource->format : + util_format_linear(resource->format); + unsigned first_layer, last_layer, level; + + if (resource->target == PIPE_TEXTURE_1D_ARRAY) { + rtt_depth = rtt_height; + rtt_height = 1; + } + + /* find matching mipmap level size */ + for (level = 0; level <= resource->last_level; level++) { + if (u_minify(resource->width0, level) == rtt_width && + u_minify(resource->height0, level) == rtt_height && + (resource->target != PIPE_TEXTURE_3D || + u_minify(resource->depth0, level) == rtt_depth)) { + break; + } + } + assert(level <= resource->last_level); + + /* determine the layer bounds */ + if (strb->rtt_layered) { + first_layer = 0; + last_layer = util_max_layer(strb->texture, level); + } + else { + first_layer = + last_layer = strb->rtt_face + strb->rtt_slice; + } + + if (!strb->surface || + strb->surface->texture->nr_samples != strb->Base.NumSamples || + strb->surface->format != format || + strb->surface->texture != resource || + strb->surface->width != rtt_width || + strb->surface->height != rtt_height || + strb->surface->u.tex.level != level || + strb->surface->u.tex.first_layer != first_layer || + strb->surface->u.tex.last_layer != last_layer) { + /* create a new pipe_surface */ + struct pipe_surface surf_tmpl; + memset(&surf_tmpl, 0, sizeof(surf_tmpl)); + surf_tmpl.format = format; + surf_tmpl.u.tex.level = level; + surf_tmpl.u.tex.first_layer = first_layer; + surf_tmpl.u.tex.last_layer = last_layer; + + pipe_surface_reference(&strb->surface, NULL); + + strb->surface = pipe->create_surface(pipe, resource, &surf_tmpl); + } +} + /** * Called by ctx->Driver.RenderTexture */ @@ -401,8 +467,6 @@ st_render_texture(struct gl_context *ctx, struct gl_renderbuffer *rb = att->Renderbuffer; struct st_renderbuffer *strb = st_renderbuffer(rb); struct pipe_resource *pt; - struct st_texture_object *stObj; - struct pipe_surface surf_tmpl; if (!st_finalize_texture(ctx, pipe, att->Texture)) return; @@ -410,31 +474,16 @@ st_render_texture(struct gl_context *ctx, pt = st_get_texobj_resource(att->Texture); assert(pt); - /* get the texture for the texture object */ - stObj = st_texture_object(att->Texture); - /* point renderbuffer at texobject */ - strb->rtt = stObj; - strb->rtt_level = att->TextureLevel; + strb->is_rtt = TRUE; strb->rtt_face = att->CubeMapFace; strb->rtt_slice = att->Zoffset; - - pipe_resource_reference( &strb->texture, pt ); + strb->rtt_layered = att->Layered; + pipe_resource_reference(&strb->texture, pt); pipe_surface_release(pipe, &strb->surface); - assert(strb->rtt_level <= strb->texture->last_level); - - /* new surface for rendering into the texture */ - memset(&surf_tmpl, 0, sizeof(surf_tmpl)); - surf_tmpl.format = ctx->Color.sRGBEnabled - ? strb->texture->format : util_format_linear(strb->texture->format); - surf_tmpl.u.tex.level = strb->rtt_level; - surf_tmpl.u.tex.first_layer = strb->rtt_face + strb->rtt_slice; - surf_tmpl.u.tex.last_layer = strb->rtt_face + strb->rtt_slice; - strb->surface = pipe->create_surface(pipe, - strb->texture, - &surf_tmpl); + st_update_renderbuffer_surface(st, strb); strb->Base.Format = st_pipe_format_to_mesa_format(pt->format); @@ -464,7 +513,7 @@ st_finish_render_texture(struct gl_context *ctx, struct gl_renderbuffer *rb) if (!strb) return; - strb->rtt = NULL; + strb->is_rtt = FALSE; /* restore previous framebuffer state */ st_invalidate_state(ctx, _NEW_BUFFERS); @@ -706,8 +755,8 @@ st_MapRenderbuffer(struct gl_context *ctx, map = pipe_transfer_map(pipe, strb->texture, - strb->rtt_level, - strb->rtt_face + strb->rtt_slice, + strb->surface->u.tex.level, + strb->surface->u.tex.first_layer, usage, x, y2, w, h, &strb->transfer); if (map) { if (invert) { diff --git a/mesalib/src/mesa/state_tracker/st_cb_fbo.h b/mesalib/src/mesa/state_tracker/st_cb_fbo.h index f335c371b..88fccc298 100644 --- a/mesalib/src/mesa/state_tracker/st_cb_fbo.h +++ b/mesalib/src/mesa/state_tracker/st_cb_fbo.h @@ -58,8 +58,10 @@ struct st_renderbuffer boolean software; void *data; - struct st_texture_object *rtt; /**< GL render to texture's texture */ - unsigned rtt_level, rtt_face, rtt_slice; + /* Inputs from Driver.RenderTexture, don't use directly. */ + boolean is_rtt; /**< whether Driver.RenderTexture was called */ + unsigned rtt_face, rtt_slice; + boolean rtt_layered; /**< whether glFramebufferTexture was called */ }; @@ -73,6 +75,10 @@ st_renderbuffer(struct gl_renderbuffer *rb) extern struct gl_renderbuffer * st_new_renderbuffer_fb(enum pipe_format format, int samples, boolean sw); +extern void +st_update_renderbuffer_surface(struct st_context *st, + struct st_renderbuffer *strb); + extern void st_init_fbo_functions(struct dd_function_table *functions); diff --git a/mesalib/src/mesa/state_tracker/st_cb_readpixels.c b/mesalib/src/mesa/state_tracker/st_cb_readpixels.c index b5df58c03..7547dfd8b 100644 --- a/mesalib/src/mesa/state_tracker/st_cb_readpixels.c +++ b/mesalib/src/mesa/state_tracker/st_cb_readpixels.c @@ -166,7 +166,7 @@ st_readpixels(struct gl_context *ctx, GLint x, GLint y, } blit.src.resource = src; - blit.src.level = strb->rtt_level; + blit.src.level = strb->surface->u.tex.level; blit.src.format = src_format; blit.dst.resource = dst; blit.dst.level = 0; @@ -175,7 +175,7 @@ st_readpixels(struct gl_context *ctx, GLint x, GLint y, blit.dst.box.x = 0; blit.src.box.y = y; blit.dst.box.y = 0; - blit.src.box.z = strb->rtt_face + strb->rtt_slice; + blit.src.box.z = strb->surface->u.tex.first_layer; blit.dst.box.z = 0; blit.src.box.width = blit.dst.box.width = width; blit.src.box.height = blit.dst.box.height = height; diff --git a/mesalib/src/mesa/state_tracker/st_cb_texture.c b/mesalib/src/mesa/state_tracker/st_cb_texture.c index faa9ee3f6..c09f34e37 100644 --- a/mesalib/src/mesa/state_tracker/st_cb_texture.c +++ b/mesalib/src/mesa/state_tracker/st_cb_texture.c @@ -175,10 +175,8 @@ st_FreeTextureImageBuffer(struct gl_context *ctx, pipe_resource_reference(&stImage->pt, NULL); } - if (stImage->TexData) { - _mesa_align_free(stImage->TexData); - stImage->TexData = NULL; - } + _mesa_align_free(stImage->TexData); + stImage->TexData = NULL; } @@ -1156,8 +1154,8 @@ fallback_copy_texsubimage(struct gl_context *ctx, map = pipe_transfer_map(pipe, strb->texture, - strb->rtt_level, - strb->rtt_face + strb->rtt_slice, + strb->surface->u.tex.level, + strb->surface->u.tex.first_layer, PIPE_TRANSFER_READ, srcX, srcY, width, height, &src_trans); diff --git a/mesalib/src/mesa/state_tracker/st_context.h b/mesalib/src/mesa/state_tracker/st_context.h index ab89b4947..cd0a5ae98 100644 --- a/mesalib/src/mesa/state_tracker/st_context.h +++ b/mesalib/src/mesa/state_tracker/st_context.h @@ -178,6 +178,7 @@ struct st_context struct pipe_viewport_state viewport; void *vs; void *fs; + void *vs_layered; } clear; /** used for anything using util_draw_vertex_buffer */ diff --git a/mesalib/src/mesa/state_tracker/st_extensions.c b/mesalib/src/mesa/state_tracker/st_extensions.c index cd10a0c9d..5e4a3b398 100644 --- a/mesalib/src/mesa/state_tracker/st_extensions.c +++ b/mesalib/src/mesa/state_tracker/st_extensions.c @@ -406,7 +406,6 @@ void st_init_extensions(struct st_context *st) { o(NV_texture_barrier), PIPE_CAP_TEXTURE_BARRIER }, /* GL_NV_point_sprite is not supported by gallium because we don't * support the GL_POINT_SPRITE_R_MODE_NV option. */ - { o(MESA_texture_array), PIPE_CAP_MAX_TEXTURE_ARRAY_LAYERS }, { o(OES_standard_derivatives), PIPE_CAP_SM3 }, { o(ARB_texture_cube_map_array), PIPE_CAP_CUBE_MAP_ARRAY }, @@ -444,11 +443,6 @@ void st_init_extensions(struct st_context *st) { { o(ARB_depth_buffer_float) }, { PIPE_FORMAT_Z32_FLOAT, PIPE_FORMAT_Z32_FLOAT_S8X24_UINT } }, - - { { o(EXT_packed_depth_stencil) }, - { PIPE_FORMAT_S8_UINT_Z24_UNORM, - PIPE_FORMAT_Z24_UNORM_S8_UINT }, - GL_TRUE }, /* at least one format must be supported */ }; /* Required: sampler support */ @@ -605,6 +599,13 @@ void st_init_extensions(struct st_context *st) ctx->Const.ForceGLSLVersion = st->options.force_glsl_version; } + /* This extension needs full OpenGL 3.2, but we don't know if that's + * supported at this point. Only check the GLSL version. */ + if (ctx->Const.GLSLVersion >= 150 && + screen->get_param(screen, PIPE_CAP_TGSI_VS_LAYER)) { + ctx->Extensions.AMD_vertex_shader_layer = GL_TRUE; + } + if (ctx->Const.GLSLVersion >= 130) { ctx->Const.NativeIntegers = GL_TRUE; ctx->Const.MaxClipPlanes = 8; @@ -758,8 +759,7 @@ void st_init_extensions(struct st_context *st) PIPE_BUFFER, PIPE_BIND_SAMPLER_VIEW); } - if (screen->get_param(screen, PIPE_CAP_MIXED_FRAMEBUFFER_SIZES) && - ctx->Extensions.EXT_packed_depth_stencil) { + if (screen->get_param(screen, PIPE_CAP_MIXED_FRAMEBUFFER_SIZES)) { ctx->Extensions.ARB_framebuffer_object = GL_TRUE; } diff --git a/mesalib/src/mesa/state_tracker/st_format.c b/mesalib/src/mesa/state_tracker/st_format.c index ec2552384..6acf98390 100644 --- a/mesalib/src/mesa/state_tracker/st_format.c +++ b/mesalib/src/mesa/state_tracker/st_format.c @@ -1854,12 +1854,12 @@ st_QuerySamplesForFormat(struct gl_context *ctx, GLenum target, * Similarly for texture border colors. */ void -st_translate_color(union gl_color_union *colorIn, +st_translate_color(const union gl_color_union *colorIn, union pipe_color_union *colorOut, GLenum baseFormat, GLboolean is_integer) { if (is_integer) { - int *in = colorIn->i; + const int *in = colorIn->i; int *out = colorOut->i; switch (baseFormat) { @@ -1901,7 +1901,7 @@ st_translate_color(union gl_color_union *colorIn, } } else { - float *in = colorIn->f; + const float *in = colorIn->f; float *out = colorOut->f; switch (baseFormat) { diff --git a/mesalib/src/mesa/state_tracker/st_format.h b/mesalib/src/mesa/state_tracker/st_format.h index 6e97dcb96..3278748d0 100644 --- a/mesalib/src/mesa/state_tracker/st_format.h +++ b/mesalib/src/mesa/state_tracker/st_format.h @@ -73,7 +73,7 @@ st_QuerySamplesForFormat(struct gl_context *ctx, GLenum target, extern void -st_translate_color(union gl_color_union *colorIn, +st_translate_color(const union gl_color_union *colorIn, union pipe_color_union *colorOut, GLenum baseFormat, GLboolean is_integer); 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 ac95968d6..1331c73dc 100644 --- a/mesalib/src/mesa/state_tracker/st_glsl_to_tgsi.cpp +++ b/mesalib/src/mesa/state_tracker/st_glsl_to_tgsi.cpp @@ -1056,11 +1056,11 @@ glsl_to_tgsi_visitor::visit(ir_variable *ir) if (strcmp(ir->name, "gl_FragCoord") == 0) { struct gl_fragment_program *fp = (struct gl_fragment_program *)this->prog; - fp->OriginUpperLeft = ir->origin_upper_left; - fp->PixelCenterInteger = ir->pixel_center_integer; + fp->OriginUpperLeft = ir->data.origin_upper_left; + fp->PixelCenterInteger = ir->data.pixel_center_integer; } - if (ir->mode == ir_var_uniform && strncmp(ir->name, "gl_", 3) == 0) { + if (ir->data.mode == ir_var_uniform && strncmp(ir->name, "gl_", 3) == 0) { unsigned int i; const ir_state_slot *const slots = ir->state_slots; assert(ir->state_slots != NULL); @@ -1137,53 +1137,10 @@ glsl_to_tgsi_visitor::visit(ir_variable *ir) void glsl_to_tgsi_visitor::visit(ir_loop *ir) { - ir_dereference_variable *counter = NULL; - - if (ir->counter != NULL) - counter = new(ir) ir_dereference_variable(ir->counter); - - if (ir->from != NULL) { - assert(ir->counter != NULL); - - ir_assignment *a = new(ir) ir_assignment(counter, ir->from, NULL); - - a->accept(this); - delete a; - } - emit(NULL, TGSI_OPCODE_BGNLOOP); - if (ir->to) { - ir_expression *e = - new(ir) ir_expression(ir->cmp, glsl_type::bool_type, - counter, ir->to); - ir_if *if_stmt = new(ir) ir_if(e); - - ir_loop_jump *brk = new(ir) ir_loop_jump(ir_loop_jump::jump_break); - - if_stmt->then_instructions.push_tail(brk); - - if_stmt->accept(this); - - delete if_stmt; - delete e; - delete brk; - } - visit_exec_list(&ir->body_instructions, this); - if (ir->increment) { - ir_expression *e = - new(ir) ir_expression(ir_binop_add, counter->type, - counter, ir->increment); - - ir_assignment *a = new(ir) ir_assignment(counter, e, NULL); - - a->accept(this); - delete a; - delete e; - } - emit(NULL, TGSI_OPCODE_ENDLOOP); } @@ -2063,10 +2020,10 @@ glsl_to_tgsi_visitor::visit(ir_dereference_variable *ir) ir_variable *var = ir->var; if (!entry) { - switch (var->mode) { + switch (var->data.mode) { case ir_var_uniform: entry = new(mem_ctx) variable_storage(var, PROGRAM_UNIFORM, - var->location); + var->data.location); this->variables.push_tail(entry); break; case ir_var_shader_in: @@ -2075,21 +2032,22 @@ glsl_to_tgsi_visitor::visit(ir_dereference_variable *ir) * generic attributes (glBindVertexLocation), and * user-defined varyings. */ - assert(var->location != -1); + assert(var->data.location != -1); entry = new(mem_ctx) variable_storage(var, PROGRAM_INPUT, - var->location); + var->data.location); break; case ir_var_shader_out: - assert(var->location != -1); + assert(var->data.location != -1); entry = new(mem_ctx) variable_storage(var, PROGRAM_OUTPUT, - var->location + var->index); + var->data.location + + var->data.index); break; case ir_var_system_value: entry = new(mem_ctx) variable_storage(var, PROGRAM_SYSTEM_VALUE, - var->location); + var->data.location); break; case ir_var_auto: case ir_var_temporary: @@ -2388,7 +2346,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->variable_referenced()->mode == ir_var_shader_out) { + 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. */ @@ -2664,8 +2622,8 @@ glsl_to_tgsi_visitor::visit(ir_call *ir) ir_rvalue *param_rval = (ir_rvalue *)iter.get(); ir_variable *param = (ir_variable *)sig_iter.get(); - if (param->mode == ir_var_function_in || - param->mode == ir_var_function_inout) { + if (param->data.mode == ir_var_function_in || + param->data.mode == ir_var_function_inout) { variable_storage *storage = find_variable_storage(param); assert(storage); @@ -2700,8 +2658,8 @@ glsl_to_tgsi_visitor::visit(ir_call *ir) ir_rvalue *param_rval = (ir_rvalue *)iter.get(); ir_variable *param = (ir_variable *)sig_iter.get(); - if (param->mode == ir_var_function_out || - param->mode == ir_var_function_inout) { + if (param->data.mode == ir_var_function_out || + param->data.mode == ir_var_function_inout) { variable_storage *storage = find_variable_storage(param); assert(storage); diff --git a/mesalib/src/mesa/state_tracker/st_program.c b/mesalib/src/mesa/state_tracker/st_program.c index f010e1889..f72122b4f 100644 --- a/mesalib/src/mesa/state_tracker/st_program.c +++ b/mesalib/src/mesa/state_tracker/st_program.c @@ -258,6 +258,10 @@ st_prepare_vertex_program(struct gl_context *ctx, stvp->output_semantic_name[slot] = TGSI_SEMANTIC_CLIPVERTEX; stvp->output_semantic_index[slot] = 0; break; + case VARYING_SLOT_LAYER: + stvp->output_semantic_name[slot] = TGSI_SEMANTIC_LAYER; + stvp->output_semantic_index[slot] = 0; + break; case VARYING_SLOT_TEX0: case VARYING_SLOT_TEX1: @@ -563,6 +567,11 @@ st_translate_fragment_program(struct st_context *st, input_semantic_index[slot] = 0; interpMode[slot] = TGSI_INTERPOLATE_CONSTANT; break; + case VARYING_SLOT_PRIMITIVE_ID: + input_semantic_name[slot] = TGSI_SEMANTIC_PRIMID; + input_semantic_index[slot] = 0; + interpMode[slot] = TGSI_INTERPOLATE_CONSTANT; + break; case VARYING_SLOT_CLIP_DIST0: input_semantic_name[slot] = TGSI_SEMANTIC_CLIPDIST; input_semantic_index[slot] = 0; diff --git a/mesalib/src/mesa/state_tracker/st_texture.h b/mesalib/src/mesa/state_tracker/st_texture.h index c15aeaea6..ac93d9655 100644 --- a/mesalib/src/mesa/state_tracker/st_texture.h +++ b/mesalib/src/mesa/state_tracker/st_texture.h @@ -112,6 +112,12 @@ st_texture_object(struct gl_texture_object *obj) return (struct st_texture_object *) obj; } +static INLINE const struct st_texture_object * +st_texture_object_const(const struct gl_texture_object *obj) +{ + return (const struct st_texture_object *) obj; +} + static INLINE struct pipe_resource * st_get_texobj_resource(struct gl_texture_object *texObj) diff --git a/mesalib/src/mesa/swrast/s_texture.c b/mesalib/src/mesa/swrast/s_texture.c index 27803c553..c08a4e9d1 100644 --- a/mesalib/src/mesa/swrast/s_texture.c +++ b/mesalib/src/mesa/swrast/s_texture.c @@ -164,10 +164,9 @@ _swrast_free_texture_image_buffer(struct gl_context *ctx, struct gl_texture_image *texImage) { struct swrast_texture_image *swImage = swrast_texture_image(texImage); - if (swImage->Buffer) { - _mesa_align_free(swImage->Buffer); - swImage->Buffer = NULL; - } + + _mesa_align_free(swImage->Buffer); + swImage->Buffer = NULL; free(swImage->ImageSlices); swImage->ImageSlices = NULL; diff --git a/mesalib/src/mesa/tnl/t_vertex.c b/mesalib/src/mesa/tnl/t_vertex.c index c7a745ed7..8c4195eed 100644 --- a/mesalib/src/mesa/tnl/t_vertex.c +++ b/mesalib/src/mesa/tnl/t_vertex.c @@ -546,10 +546,8 @@ void _tnl_free_vertices( struct gl_context *ctx ) struct tnl_clipspace *vtx = GET_VERTEX_STATE(ctx); struct tnl_clipspace_fastpath *fp, *tmp; - if (vtx->vertex_buf) { - _mesa_align_free(vtx->vertex_buf); - vtx->vertex_buf = NULL; - } + _mesa_align_free(vtx->vertex_buf); + vtx->vertex_buf = NULL; for (fp = vtx->fastpath ; fp ; fp = tmp) { tmp = fp->next; diff --git a/mesalib/src/mesa/vbo/vbo_exec_api.c b/mesalib/src/mesa/vbo/vbo_exec_api.c index c84d97f56..6feda1657 100644 --- a/mesalib/src/mesa/vbo/vbo_exec_api.c +++ b/mesalib/src/mesa/vbo/vbo_exec_api.c @@ -990,11 +990,10 @@ void vbo_use_buffer_objects(struct gl_context *ctx) /* Make sure this func is only used once */ assert(exec->vtx.bufferobj == ctx->Shared->NullBufferObj); - if (exec->vtx.buffer_map) { - _mesa_align_free(exec->vtx.buffer_map); - exec->vtx.buffer_map = NULL; - exec->vtx.buffer_ptr = NULL; - } + + _mesa_align_free(exec->vtx.buffer_map); + exec->vtx.buffer_map = NULL; + exec->vtx.buffer_ptr = NULL; /* Allocate a real buffer object now */ _mesa_reference_buffer_object(ctx, &exec->vtx.bufferobj, NULL); diff --git a/mesalib/src/mesa/x86/rtasm/x86sse.c b/mesalib/src/mesa/x86/rtasm/x86sse.c deleted file mode 100644 index c93faba79..000000000 --- a/mesalib/src/mesa/x86/rtasm/x86sse.c +++ /dev/null @@ -1,1203 +0,0 @@ -#ifdef USE_X86_ASM -#if defined(__i386__) || defined(__386__) - -#include "main/imports.h" -#include "x86sse.h" - -#define DISASSEM 0 -#define X86_TWOB 0x0f - -#if 0 -static unsigned char *cptr( void (*label)() ) -{ - return (unsigned char *)(unsigned long)label; -} -#endif - - -static void do_realloc( struct x86_function *p ) -{ - if (p->size == 0) { - p->size = 1024; - p->store = _mesa_exec_malloc(p->size); - p->csr = p->store; - } - else { - unsigned used = p->csr - p->store; - unsigned char *tmp = p->store; - p->size *= 2; - p->store = _mesa_exec_malloc(p->size); - memcpy(p->store, tmp, used); - p->csr = p->store + used; - _mesa_exec_free(tmp); - } -} - -/* Emit bytes to the instruction stream: - */ -static unsigned char *reserve( struct x86_function *p, int bytes ) -{ - if (p->csr + bytes - p->store > p->size) - do_realloc(p); - - { - unsigned char *csr = p->csr; - p->csr += bytes; - return csr; - } -} - - - -static void emit_1b( struct x86_function *p, char b0 ) -{ - char *csr = (char *)reserve(p, 1); - *csr = b0; -} - -static void emit_1i( struct x86_function *p, int i0 ) -{ - int *icsr = (int *)reserve(p, sizeof(i0)); - *icsr = i0; -} - -static void emit_1ub( struct x86_function *p, unsigned char b0 ) -{ - unsigned char *csr = reserve(p, 1); - *csr++ = b0; -} - -static void emit_2ub( struct x86_function *p, unsigned char b0, unsigned char b1 ) -{ - unsigned char *csr = reserve(p, 2); - *csr++ = b0; - *csr++ = b1; -} - -static void emit_3ub( struct x86_function *p, unsigned char b0, unsigned char b1, unsigned char b2 ) -{ - unsigned char *csr = reserve(p, 3); - *csr++ = b0; - *csr++ = b1; - *csr++ = b2; -} - - -/* Build a modRM byte + possible displacement. No treatment of SIB - * indexing. BZZT - no way to encode an absolute address. - */ -static void emit_modrm( struct x86_function *p, - struct x86_reg reg, - struct x86_reg regmem ) -{ - unsigned char val = 0; - - assert(reg.mod == mod_REG); - - val |= regmem.mod << 6; /* mod field */ - val |= reg.idx << 3; /* reg field */ - val |= regmem.idx; /* r/m field */ - - emit_1ub(p, val); - - /* Oh-oh we've stumbled into the SIB thing. - */ - if (regmem.file == file_REG32 && - regmem.idx == reg_SP) { - emit_1ub(p, 0x24); /* simplistic! */ - } - - switch (regmem.mod) { - case mod_REG: - case mod_INDIRECT: - break; - case mod_DISP8: - emit_1b(p, regmem.disp); - break; - case mod_DISP32: - emit_1i(p, regmem.disp); - break; - default: - assert(0); - break; - } -} - - -static void emit_modrm_noreg( struct x86_function *p, - unsigned op, - struct x86_reg regmem ) -{ - struct x86_reg dummy = x86_make_reg(file_REG32, op); - emit_modrm(p, dummy, regmem); -} - -/* Many x86 instructions have two opcodes to cope with the situations - * where the destination is a register or memory reference - * respectively. This function selects the correct opcode based on - * the arguments presented. - */ -static void emit_op_modrm( struct x86_function *p, - unsigned char op_dst_is_reg, - unsigned char op_dst_is_mem, - struct x86_reg dst, - struct x86_reg src ) -{ - switch (dst.mod) { - case mod_REG: - emit_1ub(p, op_dst_is_reg); - emit_modrm(p, dst, src); - break; - case mod_INDIRECT: - case mod_DISP32: - case mod_DISP8: - assert(src.mod == mod_REG); - emit_1ub(p, op_dst_is_mem); - emit_modrm(p, src, dst); - break; - default: - assert(0); - break; - } -} - - - - - - - -/* Create and manipulate registers and regmem values: - */ -struct x86_reg x86_make_reg( enum x86_reg_file file, - enum x86_reg_name idx ) -{ - struct x86_reg reg; - - reg.file = file; - reg.idx = idx; - reg.mod = mod_REG; - reg.disp = 0; - - return reg; -} - -struct x86_reg x86_make_disp( struct x86_reg reg, - int disp ) -{ - assert(reg.file == file_REG32); - - if (reg.mod == mod_REG) - reg.disp = disp; - else - reg.disp += disp; - - if (reg.disp == 0) - reg.mod = mod_INDIRECT; - else if (reg.disp <= 127 && reg.disp >= -128) - reg.mod = mod_DISP8; - else - reg.mod = mod_DISP32; - - return reg; -} - -struct x86_reg x86_deref( struct x86_reg reg ) -{ - return x86_make_disp(reg, 0); -} - -struct x86_reg x86_get_base_reg( struct x86_reg reg ) -{ - return x86_make_reg( reg.file, reg.idx ); -} - -unsigned char *x86_get_label( struct x86_function *p ) -{ - return p->csr; -} - - - -/*********************************************************************** - * x86 instructions - */ - - -void x86_jcc( struct x86_function *p, - enum x86_cc cc, - unsigned char *label ) -{ - int offset = label - (x86_get_label(p) + 2); - - if (offset <= 127 && offset >= -128) { - emit_1ub(p, 0x70 + cc); - emit_1b(p, (char) offset); - } - else { - offset = label - (x86_get_label(p) + 6); - emit_2ub(p, 0x0f, 0x80 + cc); - emit_1i(p, offset); - } -} - -/* Always use a 32bit offset for forward jumps: - */ -unsigned char *x86_jcc_forward( struct x86_function *p, - enum x86_cc cc ) -{ - emit_2ub(p, 0x0f, 0x80 + cc); - emit_1i(p, 0); - return x86_get_label(p); -} - -unsigned char *x86_jmp_forward( struct x86_function *p) -{ - emit_1ub(p, 0xe9); - emit_1i(p, 0); - return x86_get_label(p); -} - -unsigned char *x86_call_forward( struct x86_function *p) -{ - emit_1ub(p, 0xe8); - emit_1i(p, 0); - return x86_get_label(p); -} - -/* Fixup offset from forward jump: - */ -void x86_fixup_fwd_jump( struct x86_function *p, - unsigned char *fixup ) -{ - *(int *)(fixup - 4) = x86_get_label(p) - fixup; -} - -void x86_jmp( struct x86_function *p, unsigned char *label) -{ - emit_1ub(p, 0xe9); - emit_1i(p, label - x86_get_label(p) - 4); -} - -#if 0 -/* This doesn't work once we start reallocating & copying the - * generated code on buffer fills, because the call is relative to the - * current pc. - */ -void x86_call( struct x86_function *p, void (*label)()) -{ - emit_1ub(p, 0xe8); - emit_1i(p, cptr(label) - x86_get_label(p) - 4); -} -#else -void x86_call( struct x86_function *p, struct x86_reg reg) -{ - emit_1ub(p, 0xff); - emit_modrm_noreg(p, 2, reg); -} -#endif - - -/* michal: - * Temporary. As I need immediate operands, and dont want to mess with the codegen, - * I load the immediate into general purpose register and use it. - */ -void x86_mov_reg_imm( struct x86_function *p, struct x86_reg dst, int imm ) -{ - assert(dst.mod == mod_REG); - emit_1ub(p, 0xb8 + dst.idx); - emit_1i(p, imm); -} - -void x86_push( struct x86_function *p, - struct x86_reg reg ) -{ - assert(reg.mod == mod_REG); - emit_1ub(p, 0x50 + reg.idx); - p->stack_offset += 4; -} - -void x86_pop( struct x86_function *p, - struct x86_reg reg ) -{ - assert(reg.mod == mod_REG); - emit_1ub(p, 0x58 + reg.idx); - p->stack_offset -= 4; -} - -void x86_inc( struct x86_function *p, - struct x86_reg reg ) -{ - assert(reg.mod == mod_REG); - emit_1ub(p, 0x40 + reg.idx); -} - -void x86_dec( struct x86_function *p, - struct x86_reg reg ) -{ - assert(reg.mod == mod_REG); - emit_1ub(p, 0x48 + reg.idx); -} - -void x86_ret( struct x86_function *p ) -{ - emit_1ub(p, 0xc3); -} - -void x86_sahf( struct x86_function *p ) -{ - emit_1ub(p, 0x9e); -} - -void x86_mov( struct x86_function *p, - struct x86_reg dst, - struct x86_reg src ) -{ - emit_op_modrm( p, 0x8b, 0x89, dst, src ); -} - -void x86_xor( struct x86_function *p, - struct x86_reg dst, - struct x86_reg src ) -{ - emit_op_modrm( p, 0x33, 0x31, dst, src ); -} - -void x86_cmp( struct x86_function *p, - struct x86_reg dst, - struct x86_reg src ) -{ - emit_op_modrm( p, 0x3b, 0x39, dst, src ); -} - -void x86_lea( struct x86_function *p, - struct x86_reg dst, - struct x86_reg src ) -{ - emit_1ub(p, 0x8d); - emit_modrm( p, dst, src ); -} - -void x86_test( struct x86_function *p, - struct x86_reg dst, - struct x86_reg src ) -{ - emit_1ub(p, 0x85); - emit_modrm( p, dst, src ); -} - -void x86_add( struct x86_function *p, - struct x86_reg dst, - struct x86_reg src ) -{ - emit_op_modrm(p, 0x03, 0x01, dst, src ); -} - -void x86_mul( struct x86_function *p, - struct x86_reg src ) -{ - assert (src.file == file_REG32 && src.mod == mod_REG); - emit_op_modrm(p, 0xf7, 0, x86_make_reg (file_REG32, reg_SP), src ); -} - -void x86_sub( struct x86_function *p, - struct x86_reg dst, - struct x86_reg src ) -{ - emit_op_modrm(p, 0x2b, 0x29, dst, src ); -} - -void x86_or( struct x86_function *p, - struct x86_reg dst, - struct x86_reg src ) -{ - emit_op_modrm( p, 0x0b, 0x09, dst, src ); -} - -void x86_and( struct x86_function *p, - struct x86_reg dst, - struct x86_reg src ) -{ - emit_op_modrm( p, 0x23, 0x21, dst, src ); -} - - - -/*********************************************************************** - * SSE instructions - */ - - -void sse_movss( struct x86_function *p, - struct x86_reg dst, - struct x86_reg src ) -{ - emit_2ub(p, 0xF3, X86_TWOB); - emit_op_modrm( p, 0x10, 0x11, dst, src ); -} - -void sse_movaps( struct x86_function *p, - struct x86_reg dst, - struct x86_reg src ) -{ - emit_1ub(p, X86_TWOB); - emit_op_modrm( p, 0x28, 0x29, dst, src ); -} - -void sse_movups( struct x86_function *p, - struct x86_reg dst, - struct x86_reg src ) -{ - emit_1ub(p, X86_TWOB); - emit_op_modrm( p, 0x10, 0x11, dst, src ); -} - -void sse_movhps( struct x86_function *p, - struct x86_reg dst, - struct x86_reg src ) -{ - assert(dst.mod != mod_REG || src.mod != mod_REG); - emit_1ub(p, X86_TWOB); - emit_op_modrm( p, 0x16, 0x17, dst, src ); /* cf movlhps */ -} - -void sse_movlps( struct x86_function *p, - struct x86_reg dst, - struct x86_reg src ) -{ - assert(dst.mod != mod_REG || src.mod != mod_REG); - emit_1ub(p, X86_TWOB); - emit_op_modrm( p, 0x12, 0x13, dst, src ); /* cf movhlps */ -} - -void sse_maxps( struct x86_function *p, - struct x86_reg dst, - struct x86_reg src ) -{ - emit_2ub(p, X86_TWOB, 0x5F); - emit_modrm( p, dst, src ); -} - -void sse_maxss( struct x86_function *p, - struct x86_reg dst, - struct x86_reg src ) -{ - emit_3ub(p, 0xF3, X86_TWOB, 0x5F); - emit_modrm( p, dst, src ); -} - -void sse_divss( struct x86_function *p, - struct x86_reg dst, - struct x86_reg src ) -{ - emit_3ub(p, 0xF3, X86_TWOB, 0x5E); - emit_modrm( p, dst, src ); -} - -void sse_minps( struct x86_function *p, - struct x86_reg dst, - struct x86_reg src ) -{ - emit_2ub(p, X86_TWOB, 0x5D); - emit_modrm( p, dst, src ); -} - -void sse_subps( struct x86_function *p, - struct x86_reg dst, - struct x86_reg src ) -{ - emit_2ub(p, X86_TWOB, 0x5C); - emit_modrm( p, dst, src ); -} - -void sse_mulps( struct x86_function *p, - struct x86_reg dst, - struct x86_reg src ) -{ - emit_2ub(p, X86_TWOB, 0x59); - emit_modrm( p, dst, src ); -} - -void sse_mulss( struct x86_function *p, - struct x86_reg dst, - struct x86_reg src ) -{ - emit_3ub(p, 0xF3, X86_TWOB, 0x59); - emit_modrm( p, dst, src ); -} - -void sse_addps( struct x86_function *p, - struct x86_reg dst, - struct x86_reg src ) -{ - emit_2ub(p, X86_TWOB, 0x58); - emit_modrm( p, dst, src ); -} - -void sse_addss( struct x86_function *p, - struct x86_reg dst, - struct x86_reg src ) -{ - emit_3ub(p, 0xF3, X86_TWOB, 0x58); - emit_modrm( p, dst, src ); -} - -void sse_andnps( struct x86_function *p, - struct x86_reg dst, - struct x86_reg src ) -{ - emit_2ub(p, X86_TWOB, 0x55); - emit_modrm( p, dst, src ); -} - -void sse_andps( struct x86_function *p, - struct x86_reg dst, - struct x86_reg src ) -{ - emit_2ub(p, X86_TWOB, 0x54); - emit_modrm( p, dst, src ); -} - -void sse_rsqrtps( struct x86_function *p, - struct x86_reg dst, - struct x86_reg src ) -{ - emit_2ub(p, X86_TWOB, 0x52); - emit_modrm( p, dst, src ); -} - -void sse_rsqrtss( struct x86_function *p, - struct x86_reg dst, - struct x86_reg src ) -{ - emit_3ub(p, 0xF3, X86_TWOB, 0x52); - emit_modrm( p, dst, src ); - -} - -void sse_movhlps( struct x86_function *p, - struct x86_reg dst, - struct x86_reg src ) -{ - assert(dst.mod == mod_REG && src.mod == mod_REG); - emit_2ub(p, X86_TWOB, 0x12); - emit_modrm( p, dst, src ); -} - -void sse_movlhps( struct x86_function *p, - struct x86_reg dst, - struct x86_reg src ) -{ - assert(dst.mod == mod_REG && src.mod == mod_REG); - emit_2ub(p, X86_TWOB, 0x16); - emit_modrm( p, dst, src ); -} - -void sse_orps( struct x86_function *p, - struct x86_reg dst, - struct x86_reg src ) -{ - emit_2ub(p, X86_TWOB, 0x56); - emit_modrm( p, dst, src ); -} - -void sse_xorps( struct x86_function *p, - struct x86_reg dst, - struct x86_reg src ) -{ - emit_2ub(p, X86_TWOB, 0x57); - emit_modrm( p, dst, src ); -} - -void sse_cvtps2pi( struct x86_function *p, - struct x86_reg dst, - struct x86_reg src ) -{ - assert(dst.file == file_MMX && - (src.file == file_XMM || src.mod != mod_REG)); - - p->need_emms = 1; - - emit_2ub(p, X86_TWOB, 0x2d); - emit_modrm( p, dst, src ); -} - - -/* Shufps can also be used to implement a reduced swizzle when dest == - * arg0. - */ -void sse_shufps( struct x86_function *p, - struct x86_reg dest, - struct x86_reg arg0, - unsigned char shuf) -{ - emit_2ub(p, X86_TWOB, 0xC6); - emit_modrm(p, dest, arg0); - emit_1ub(p, shuf); -} - -void sse_cmpps( struct x86_function *p, - struct x86_reg dest, - struct x86_reg arg0, - unsigned char cc) -{ - emit_2ub(p, X86_TWOB, 0xC2); - emit_modrm(p, dest, arg0); - emit_1ub(p, cc); -} - -void sse_pmovmskb( struct x86_function *p, - struct x86_reg dest, - struct x86_reg src) -{ - emit_3ub(p, 0x66, X86_TWOB, 0xD7); - emit_modrm(p, dest, src); -} - -/*********************************************************************** - * SSE2 instructions - */ - -/** - * Perform a reduced swizzle: - */ -void sse2_pshufd( struct x86_function *p, - struct x86_reg dest, - struct x86_reg arg0, - unsigned char shuf) -{ - emit_3ub(p, 0x66, X86_TWOB, 0x70); - emit_modrm(p, dest, arg0); - emit_1ub(p, shuf); -} - -void sse2_cvttps2dq( struct x86_function *p, - struct x86_reg dst, - struct x86_reg src ) -{ - emit_3ub( p, 0xF3, X86_TWOB, 0x5B ); - emit_modrm( p, dst, src ); -} - -void sse2_cvtps2dq( struct x86_function *p, - struct x86_reg dst, - struct x86_reg src ) -{ - emit_3ub(p, 0x66, X86_TWOB, 0x5B); - emit_modrm( p, dst, src ); -} - -void sse2_packssdw( struct x86_function *p, - struct x86_reg dst, - struct x86_reg src ) -{ - emit_3ub(p, 0x66, X86_TWOB, 0x6B); - emit_modrm( p, dst, src ); -} - -void sse2_packsswb( struct x86_function *p, - struct x86_reg dst, - struct x86_reg src ) -{ - emit_3ub(p, 0x66, X86_TWOB, 0x63); - emit_modrm( p, dst, src ); -} - -void sse2_packuswb( struct x86_function *p, - struct x86_reg dst, - struct x86_reg src ) -{ - emit_3ub(p, 0x66, X86_TWOB, 0x67); - emit_modrm( p, dst, src ); -} - -void sse2_rcpps( struct x86_function *p, - struct x86_reg dst, - struct x86_reg src ) -{ - emit_2ub(p, X86_TWOB, 0x53); - emit_modrm( p, dst, src ); -} - -void sse2_rcpss( struct x86_function *p, - struct x86_reg dst, - struct x86_reg src ) -{ - emit_3ub(p, 0xF3, X86_TWOB, 0x53); - emit_modrm( p, dst, src ); -} - -void sse2_movd( struct x86_function *p, - struct x86_reg dst, - struct x86_reg src ) -{ - emit_2ub(p, 0x66, X86_TWOB); - emit_op_modrm( p, 0x6e, 0x7e, dst, src ); -} - - - - -/*********************************************************************** - * x87 instructions - */ -void x87_fist( struct x86_function *p, struct x86_reg dst ) -{ - emit_1ub(p, 0xdb); - emit_modrm_noreg(p, 2, dst); -} - -void x87_fistp( struct x86_function *p, struct x86_reg dst ) -{ - emit_1ub(p, 0xdb); - emit_modrm_noreg(p, 3, dst); -} - -void x87_fild( struct x86_function *p, struct x86_reg arg ) -{ - emit_1ub(p, 0xdf); - emit_modrm_noreg(p, 0, arg); -} - -void x87_fldz( struct x86_function *p ) -{ - emit_2ub(p, 0xd9, 0xee); -} - - -void x87_fldcw( struct x86_function *p, struct x86_reg arg ) -{ - assert(arg.file == file_REG32); - assert(arg.mod != mod_REG); - emit_1ub(p, 0xd9); - emit_modrm_noreg(p, 5, arg); -} - -void x87_fld1( struct x86_function *p ) -{ - emit_2ub(p, 0xd9, 0xe8); -} - -void x87_fldl2e( struct x86_function *p ) -{ - emit_2ub(p, 0xd9, 0xea); -} - -void x87_fldln2( struct x86_function *p ) -{ - emit_2ub(p, 0xd9, 0xed); -} - -void x87_fwait( struct x86_function *p ) -{ - emit_1ub(p, 0x9b); -} - -void x87_fnclex( struct x86_function *p ) -{ - emit_2ub(p, 0xdb, 0xe2); -} - -void x87_fclex( struct x86_function *p ) -{ - x87_fwait(p); - x87_fnclex(p); -} - - -static void x87_arith_op( struct x86_function *p, struct x86_reg dst, struct x86_reg arg, - unsigned char dst0ub0, - unsigned char dst0ub1, - unsigned char arg0ub0, - unsigned char arg0ub1, - unsigned char argmem_noreg) -{ - assert(dst.file == file_x87); - - if (arg.file == file_x87) { - if (dst.idx == 0) - emit_2ub(p, dst0ub0, dst0ub1+arg.idx); - else if (arg.idx == 0) - emit_2ub(p, arg0ub0, arg0ub1+arg.idx); - else - assert(0); - } - else if (dst.idx == 0) { - assert(arg.file == file_REG32); - emit_1ub(p, 0xd8); - emit_modrm_noreg(p, argmem_noreg, arg); - } - else - assert(0); -} - -void x87_fmul( struct x86_function *p, struct x86_reg dst, struct x86_reg arg ) -{ - x87_arith_op(p, dst, arg, - 0xd8, 0xc8, - 0xdc, 0xc8, - 4); -} - -void x87_fsub( struct x86_function *p, struct x86_reg dst, struct x86_reg arg ) -{ - x87_arith_op(p, dst, arg, - 0xd8, 0xe0, - 0xdc, 0xe8, - 4); -} - -void x87_fsubr( struct x86_function *p, struct x86_reg dst, struct x86_reg arg ) -{ - x87_arith_op(p, dst, arg, - 0xd8, 0xe8, - 0xdc, 0xe0, - 5); -} - -void x87_fadd( struct x86_function *p, struct x86_reg dst, struct x86_reg arg ) -{ - x87_arith_op(p, dst, arg, - 0xd8, 0xc0, - 0xdc, 0xc0, - 0); -} - -void x87_fdiv( struct x86_function *p, struct x86_reg dst, struct x86_reg arg ) -{ - x87_arith_op(p, dst, arg, - 0xd8, 0xf0, - 0xdc, 0xf8, - 6); -} - -void x87_fdivr( struct x86_function *p, struct x86_reg dst, struct x86_reg arg ) -{ - x87_arith_op(p, dst, arg, - 0xd8, 0xf8, - 0xdc, 0xf0, - 7); -} - -void x87_fmulp( struct x86_function *p, struct x86_reg dst ) -{ - assert(dst.file == file_x87); - assert(dst.idx >= 1); - emit_2ub(p, 0xde, 0xc8+dst.idx); -} - -void x87_fsubp( struct x86_function *p, struct x86_reg dst ) -{ - assert(dst.file == file_x87); - assert(dst.idx >= 1); - emit_2ub(p, 0xde, 0xe8+dst.idx); -} - -void x87_fsubrp( struct x86_function *p, struct x86_reg dst ) -{ - assert(dst.file == file_x87); - assert(dst.idx >= 1); - emit_2ub(p, 0xde, 0xe0+dst.idx); -} - -void x87_faddp( struct x86_function *p, struct x86_reg dst ) -{ - assert(dst.file == file_x87); - assert(dst.idx >= 1); - emit_2ub(p, 0xde, 0xc0+dst.idx); -} - -void x87_fdivp( struct x86_function *p, struct x86_reg dst ) -{ - assert(dst.file == file_x87); - assert(dst.idx >= 1); - emit_2ub(p, 0xde, 0xf8+dst.idx); -} - -void x87_fdivrp( struct x86_function *p, struct x86_reg dst ) -{ - assert(dst.file == file_x87); - assert(dst.idx >= 1); - emit_2ub(p, 0xde, 0xf0+dst.idx); -} - -void x87_fucom( struct x86_function *p, struct x86_reg arg ) -{ - assert(arg.file == file_x87); - emit_2ub(p, 0xdd, 0xe0+arg.idx); -} - -void x87_fucomp( struct x86_function *p, struct x86_reg arg ) -{ - assert(arg.file == file_x87); - emit_2ub(p, 0xdd, 0xe8+arg.idx); -} - -void x87_fucompp( struct x86_function *p ) -{ - emit_2ub(p, 0xda, 0xe9); -} - -void x87_fxch( struct x86_function *p, struct x86_reg arg ) -{ - assert(arg.file == file_x87); - emit_2ub(p, 0xd9, 0xc8+arg.idx); -} - -void x87_fabs( struct x86_function *p ) -{ - emit_2ub(p, 0xd9, 0xe1); -} - -void x87_fchs( struct x86_function *p ) -{ - emit_2ub(p, 0xd9, 0xe0); -} - -void x87_fcos( struct x86_function *p ) -{ - emit_2ub(p, 0xd9, 0xff); -} - - -void x87_fprndint( struct x86_function *p ) -{ - emit_2ub(p, 0xd9, 0xfc); -} - -void x87_fscale( struct x86_function *p ) -{ - emit_2ub(p, 0xd9, 0xfd); -} - -void x87_fsin( struct x86_function *p ) -{ - emit_2ub(p, 0xd9, 0xfe); -} - -void x87_fsincos( struct x86_function *p ) -{ - emit_2ub(p, 0xd9, 0xfb); -} - -void x87_fsqrt( struct x86_function *p ) -{ - emit_2ub(p, 0xd9, 0xfa); -} - -void x87_fxtract( struct x86_function *p ) -{ - emit_2ub(p, 0xd9, 0xf4); -} - -/* st0 = (2^st0)-1 - * - * Restrictions: -1.0 <= st0 <= 1.0 - */ -void x87_f2xm1( struct x86_function *p ) -{ - emit_2ub(p, 0xd9, 0xf0); -} - -/* st1 = st1 * log2(st0); - * pop_stack; - */ -void x87_fyl2x( struct x86_function *p ) -{ - emit_2ub(p, 0xd9, 0xf1); -} - -/* st1 = st1 * log2(st0 + 1.0); - * pop_stack; - * - * A fast operation, with restrictions: -.29 < st0 < .29 - */ -void x87_fyl2xp1( struct x86_function *p ) -{ - emit_2ub(p, 0xd9, 0xf9); -} - - -void x87_fld( struct x86_function *p, struct x86_reg arg ) -{ - if (arg.file == file_x87) - emit_2ub(p, 0xd9, 0xc0 + arg.idx); - else { - emit_1ub(p, 0xd9); - emit_modrm_noreg(p, 0, arg); - } -} - -void x87_fst( struct x86_function *p, struct x86_reg dst ) -{ - if (dst.file == file_x87) - emit_2ub(p, 0xdd, 0xd0 + dst.idx); - else { - emit_1ub(p, 0xd9); - emit_modrm_noreg(p, 2, dst); - } -} - -void x87_fstp( struct x86_function *p, struct x86_reg dst ) -{ - if (dst.file == file_x87) - emit_2ub(p, 0xdd, 0xd8 + dst.idx); - else { - emit_1ub(p, 0xd9); - emit_modrm_noreg(p, 3, dst); - } -} - -void x87_fcom( struct x86_function *p, struct x86_reg dst ) -{ - if (dst.file == file_x87) - emit_2ub(p, 0xd8, 0xd0 + dst.idx); - else { - emit_1ub(p, 0xd8); - emit_modrm_noreg(p, 2, dst); - } -} - -void x87_fcomp( struct x86_function *p, struct x86_reg dst ) -{ - if (dst.file == file_x87) - emit_2ub(p, 0xd8, 0xd8 + dst.idx); - else { - emit_1ub(p, 0xd8); - emit_modrm_noreg(p, 3, dst); - } -} - - -void x87_fnstsw( struct x86_function *p, struct x86_reg dst ) -{ - assert(dst.file == file_REG32); - - if (dst.idx == reg_AX && - dst.mod == mod_REG) - emit_2ub(p, 0xdf, 0xe0); - else { - emit_1ub(p, 0xdd); - emit_modrm_noreg(p, 7, dst); - } -} - - - - -/*********************************************************************** - * MMX instructions - */ - -void mmx_emms( struct x86_function *p ) -{ - assert(p->need_emms); - emit_2ub(p, 0x0f, 0x77); - p->need_emms = 0; -} - -void mmx_packssdw( struct x86_function *p, - struct x86_reg dst, - struct x86_reg src ) -{ - assert(dst.file == file_MMX && - (src.file == file_MMX || src.mod != mod_REG)); - - p->need_emms = 1; - - emit_2ub(p, X86_TWOB, 0x6b); - emit_modrm( p, dst, src ); -} - -void mmx_packuswb( struct x86_function *p, - struct x86_reg dst, - struct x86_reg src ) -{ - assert(dst.file == file_MMX && - (src.file == file_MMX || src.mod != mod_REG)); - - p->need_emms = 1; - - emit_2ub(p, X86_TWOB, 0x67); - emit_modrm( p, dst, src ); -} - -void mmx_movd( struct x86_function *p, - struct x86_reg dst, - struct x86_reg src ) -{ - p->need_emms = 1; - emit_1ub(p, X86_TWOB); - emit_op_modrm( p, 0x6e, 0x7e, dst, src ); -} - -void mmx_movq( struct x86_function *p, - struct x86_reg dst, - struct x86_reg src ) -{ - p->need_emms = 1; - emit_1ub(p, X86_TWOB); - emit_op_modrm( p, 0x6f, 0x7f, dst, src ); -} - - -/*********************************************************************** - * Helper functions - */ - - -/* Retreive a reference to one of the function arguments, taking into - * account any push/pop activity: - */ -struct x86_reg x86_fn_arg( struct x86_function *p, - unsigned arg ) -{ - return x86_make_disp(x86_make_reg(file_REG32, reg_SP), - p->stack_offset + arg * 4); /* ??? */ -} - - -void x86_init_func( struct x86_function *p ) -{ - p->size = 0; - p->store = NULL; - p->csr = p->store; -} - -int x86_init_func_size( struct x86_function *p, unsigned code_size ) -{ - p->size = code_size; - p->store = _mesa_exec_malloc(code_size); - p->csr = p->store; - return p->store != NULL; -} - -void x86_release_func( struct x86_function *p ) -{ - _mesa_exec_free(p->store); - p->store = NULL; - p->csr = NULL; - p->size = 0; -} - - -void (*x86_get_func( struct x86_function *p ))(void) -{ - if (DISASSEM && p->store) - printf("disassemble %p %p\n", p->store, p->csr); - return (void (*)(void)) (unsigned long) p->store; -} - -#else - -void x86sse_dummy( void ) -{ -} - -#endif - -#else /* USE_X86_ASM */ - -int x86sse_c_dummy_var; /* silence warning */ - -#endif /* USE_X86_ASM */ diff --git a/mesalib/src/mesa/x86/rtasm/x86sse.h b/mesalib/src/mesa/x86/rtasm/x86sse.h deleted file mode 100644 index f6282f5bd..000000000 --- a/mesalib/src/mesa/x86/rtasm/x86sse.h +++ /dev/null @@ -1,256 +0,0 @@ - -#ifndef _X86SSE_H_ -#define _X86SSE_H_ - -#if defined(__i386__) || defined(__386__) - -/* It is up to the caller to ensure that instructions issued are - * suitable for the host cpu. There are no checks made in this module - * for mmx/sse/sse2 support on the cpu. - */ -struct x86_reg { - unsigned file:3; - unsigned idx:3; - unsigned mod:2; /* mod_REG if this is just a register */ - int disp:24; /* only +/- 23bits of offset - should be enough... */ -}; - -struct x86_function { - unsigned size; - unsigned char *store; - unsigned char *csr; - unsigned stack_offset; - int need_emms; - const char *fn; -}; - -enum x86_reg_file { - file_REG32, - file_MMX, - file_XMM, - file_x87 -}; - -/* Values for mod field of modr/m byte - */ -enum x86_reg_mod { - mod_INDIRECT, - mod_DISP8, - mod_DISP32, - mod_REG -}; - -enum x86_reg_name { - reg_AX, - reg_CX, - reg_DX, - reg_BX, - reg_SP, - reg_BP, - reg_SI, - reg_DI -}; - - -enum x86_cc { - cc_O, /* overflow */ - cc_NO, /* not overflow */ - cc_NAE, /* not above or equal / carry */ - cc_AE, /* above or equal / not carry */ - cc_E, /* equal / zero */ - cc_NE /* not equal / not zero */ -}; - -enum sse_cc { - cc_Equal, - cc_LessThan, - cc_LessThanEqual, - cc_Unordered, - cc_NotEqual, - cc_NotLessThan, - cc_NotLessThanEqual, - cc_Ordered -}; - -#define cc_Z cc_E -#define cc_NZ cc_NE - -/* Begin/end/retreive function creation: - */ - - -void x86_init_func( struct x86_function *p ); -int x86_init_func_size( struct x86_function *p, unsigned code_size ); -void x86_release_func( struct x86_function *p ); -void (*x86_get_func( struct x86_function *p ))( void ); - - - -/* Create and manipulate registers and regmem values: - */ -struct x86_reg x86_make_reg( enum x86_reg_file file, - enum x86_reg_name idx ); - -struct x86_reg x86_make_disp( struct x86_reg reg, - int disp ); - -struct x86_reg x86_deref( struct x86_reg reg ); - -struct x86_reg x86_get_base_reg( struct x86_reg reg ); - - -/* Labels, jumps and fixup: - */ -unsigned char *x86_get_label( struct x86_function *p ); - -void x86_jcc( struct x86_function *p, - enum x86_cc cc, - unsigned char *label ); - -unsigned char *x86_jcc_forward( struct x86_function *p, - enum x86_cc cc ); - -unsigned char *x86_jmp_forward( struct x86_function *p); - -unsigned char *x86_call_forward( struct x86_function *p); - -void x86_fixup_fwd_jump( struct x86_function *p, - unsigned char *fixup ); - -void x86_jmp( struct x86_function *p, unsigned char *label ); - -/* void x86_call( struct x86_function *p, void (*label)() ); */ -void x86_call( struct x86_function *p, struct x86_reg reg); - -/* michal: - * Temporary. As I need immediate operands, and dont want to mess with the codegen, - * I load the immediate into general purpose register and use it. - */ -void x86_mov_reg_imm( struct x86_function *p, struct x86_reg dst, int imm ); - - -/* Macro for sse_shufps() and sse2_pshufd(): - */ -#define SHUF(_x,_y,_z,_w) (((_x)<<0) | ((_y)<<2) | ((_z)<<4) | ((_w)<<6)) -#define SHUF_NOOP RSW(0,1,2,3) -#define GET_SHUF(swz, idx) (((swz) >> ((idx)*2)) & 0x3) - -void mmx_emms( struct x86_function *p ); -void mmx_movd( struct x86_function *p, struct x86_reg dst, struct x86_reg src ); -void mmx_movq( struct x86_function *p, struct x86_reg dst, struct x86_reg src ); -void mmx_packssdw( struct x86_function *p, struct x86_reg dst, struct x86_reg src ); -void mmx_packuswb( struct x86_function *p, struct x86_reg dst, struct x86_reg src ); - -void sse2_cvtps2dq( struct x86_function *p, struct x86_reg dst, struct x86_reg src ); -void sse2_cvttps2dq( struct x86_function *p, struct x86_reg dst, struct x86_reg src ); -void sse2_movd( struct x86_function *p, struct x86_reg dst, struct x86_reg src ); -void sse2_packssdw( struct x86_function *p, struct x86_reg dst, struct x86_reg src ); -void sse2_packsswb( struct x86_function *p, struct x86_reg dst, struct x86_reg src ); -void sse2_packuswb( struct x86_function *p, struct x86_reg dst, struct x86_reg src ); -void sse2_pshufd( struct x86_function *p, struct x86_reg dest, struct x86_reg arg0, - unsigned char shuf ); -void sse2_rcpps( struct x86_function *p, struct x86_reg dst, struct x86_reg src ); -void sse2_rcpss( struct x86_function *p, struct x86_reg dst, struct x86_reg src ); - -void sse_addps( struct x86_function *p, struct x86_reg dst, struct x86_reg src ); -void sse_addss( struct x86_function *p, struct x86_reg dst, struct x86_reg src ); -void sse_cvtps2pi( struct x86_function *p, struct x86_reg dst, struct x86_reg src ); -void sse_divss( struct x86_function *p, struct x86_reg dst, struct x86_reg src ); -void sse_andnps( struct x86_function *p, struct x86_reg dst, struct x86_reg src ); -void sse_andps( struct x86_function *p, struct x86_reg dst, struct x86_reg src ); -void sse_cmpps( struct x86_function *p, struct x86_reg dst, struct x86_reg src, - unsigned char cc ); -void sse_maxps( struct x86_function *p, struct x86_reg dst, struct x86_reg src ); -void sse_maxss( struct x86_function *p, struct x86_reg dst, struct x86_reg src ); -void sse_minps( struct x86_function *p, struct x86_reg dst, struct x86_reg src ); -void sse_movaps( struct x86_function *p, struct x86_reg dst, struct x86_reg src ); -void sse_movhlps( struct x86_function *p, struct x86_reg dst, struct x86_reg src ); -void sse_movhps( struct x86_function *p, struct x86_reg dst, struct x86_reg src ); -void sse_movlhps( struct x86_function *p, struct x86_reg dst, struct x86_reg src ); -void sse_movlps( struct x86_function *p, struct x86_reg dst, struct x86_reg src ); -void sse_movss( struct x86_function *p, struct x86_reg dst, struct x86_reg src ); -void sse_movups( struct x86_function *p, struct x86_reg dst, struct x86_reg src ); -void sse_mulps( struct x86_function *p, struct x86_reg dst, struct x86_reg src ); -void sse_mulss( struct x86_function *p, struct x86_reg dst, struct x86_reg src ); -void sse_orps( struct x86_function *p, struct x86_reg dst, struct x86_reg src ); -void sse_xorps( struct x86_function *p, struct x86_reg dst, struct x86_reg src ); -void sse_subps( struct x86_function *p, struct x86_reg dst, struct x86_reg src ); -void sse_rsqrtps( struct x86_function *p, struct x86_reg dst, struct x86_reg src ); -void sse_rsqrtss( struct x86_function *p, struct x86_reg dst, struct x86_reg src ); -void sse_shufps( struct x86_function *p, struct x86_reg dest, struct x86_reg arg0, - unsigned char shuf ); -void sse_pmovmskb( struct x86_function *p, struct x86_reg dest, struct x86_reg src ); - -void x86_add( struct x86_function *p, struct x86_reg dst, struct x86_reg src ); -void x86_and( struct x86_function *p, struct x86_reg dst, struct x86_reg src ); -void x86_cmp( struct x86_function *p, struct x86_reg dst, struct x86_reg src ); -void x86_dec( struct x86_function *p, struct x86_reg reg ); -void x86_inc( struct x86_function *p, struct x86_reg reg ); -void x86_lea( struct x86_function *p, struct x86_reg dst, struct x86_reg src ); -void x86_mov( struct x86_function *p, struct x86_reg dst, struct x86_reg src ); -void x86_mul( struct x86_function *p, struct x86_reg src ); -void x86_or( struct x86_function *p, struct x86_reg dst, struct x86_reg src ); -void x86_pop( struct x86_function *p, struct x86_reg reg ); -void x86_push( struct x86_function *p, struct x86_reg reg ); -void x86_ret( struct x86_function *p ); -void x86_sub( struct x86_function *p, struct x86_reg dst, struct x86_reg src ); -void x86_test( struct x86_function *p, struct x86_reg dst, struct x86_reg src ); -void x86_xor( struct x86_function *p, struct x86_reg dst, struct x86_reg src ); -void x86_sahf( struct x86_function *p ); - -void x87_f2xm1( struct x86_function *p ); -void x87_fabs( struct x86_function *p ); -void x87_fadd( struct x86_function *p, struct x86_reg dst, struct x86_reg arg ); -void x87_faddp( struct x86_function *p, struct x86_reg dst ); -void x87_fchs( struct x86_function *p ); -void x87_fclex( struct x86_function *p ); -void x87_fcom( struct x86_function *p, struct x86_reg dst ); -void x87_fcomp( struct x86_function *p, struct x86_reg dst ); -void x87_fcos( struct x86_function *p ); -void x87_fdiv( struct x86_function *p, struct x86_reg dst, struct x86_reg arg ); -void x87_fdivp( struct x86_function *p, struct x86_reg dst ); -void x87_fdivr( struct x86_function *p, struct x86_reg dst, struct x86_reg arg ); -void x87_fdivrp( struct x86_function *p, struct x86_reg dst ); -void x87_fild( struct x86_function *p, struct x86_reg arg ); -void x87_fist( struct x86_function *p, struct x86_reg dst ); -void x87_fistp( struct x86_function *p, struct x86_reg dst ); -void x87_fld( struct x86_function *p, struct x86_reg arg ); -void x87_fld1( struct x86_function *p ); -void x87_fldcw( struct x86_function *p, struct x86_reg arg ); -void x87_fldl2e( struct x86_function *p ); -void x87_fldln2( struct x86_function *p ); -void x87_fldz( struct x86_function *p ); -void x87_fmul( struct x86_function *p, struct x86_reg dst, struct x86_reg arg ); -void x87_fmulp( struct x86_function *p, struct x86_reg dst ); -void x87_fnclex( struct x86_function *p ); -void x87_fprndint( struct x86_function *p ); -void x87_fscale( struct x86_function *p ); -void x87_fsin( struct x86_function *p ); -void x87_fsincos( struct x86_function *p ); -void x87_fsqrt( struct x86_function *p ); -void x87_fst( struct x86_function *p, struct x86_reg dst ); -void x87_fstp( struct x86_function *p, struct x86_reg dst ); -void x87_fsub( struct x86_function *p, struct x86_reg dst, struct x86_reg arg ); -void x87_fsubp( struct x86_function *p, struct x86_reg dst ); -void x87_fsubr( struct x86_function *p, struct x86_reg dst, struct x86_reg arg ); -void x87_fsubrp( struct x86_function *p, struct x86_reg dst ); -void x87_fxch( struct x86_function *p, struct x86_reg dst ); -void x87_fxtract( struct x86_function *p ); -void x87_fyl2x( struct x86_function *p ); -void x87_fyl2xp1( struct x86_function *p ); -void x87_fwait( struct x86_function *p ); -void x87_fnstsw( struct x86_function *p, struct x86_reg dst ); -void x87_fucompp( struct x86_function *p ); -void x87_fucomp( struct x86_function *p, struct x86_reg arg ); -void x87_fucom( struct x86_function *p, struct x86_reg arg ); - - - -/* Retreive a reference to one of the function arguments, taking into - * account any push/pop activity. Note - doesn't track explict - * manipulation of ESP by other instructions. - */ -struct x86_reg x86_fn_arg( struct x86_function *p, unsigned arg ); - -#endif -#endif -- cgit v1.2.3