diff options
Diffstat (limited to 'src/mesa')
74 files changed, 2087 insertions, 547 deletions
diff --git a/src/mesa/Android.libmesa_dricore.mk b/src/mesa/Android.libmesa_dricore.mk index a3e6c6d55ae..d7647a76bd0 100644 --- a/src/mesa/Android.libmesa_dricore.mk +++ b/src/mesa/Android.libmesa_dricore.mk @@ -48,9 +48,8 @@ endif # x86 endif # MESA_ENABLE_ASM ifeq ($(ARCH_X86_HAVE_SSE4_1),true) -LOCAL_SRC_FILES += \ - main/streaming-load-memcpy.c \ - main/sse_minmax.c +LOCAL_WHOLE_STATIC_LIBRARIES := \ + libmesa_sse41 LOCAL_CFLAGS := \ -msse4.1 \ -DUSE_SSE41 @@ -63,7 +62,7 @@ LOCAL_C_INCLUDES := \ $(MESA_TOP)/src/gallium/include \ $(MESA_TOP)/src/gallium/auxiliary -LOCAL_WHOLE_STATIC_LIBRARIES := \ +LOCAL_WHOLE_STATIC_LIBRARIES += \ libmesa_program include $(LOCAL_PATH)/Android.gen.mk diff --git a/src/mesa/Android.libmesa_sse41.mk b/src/mesa/Android.libmesa_sse41.mk new file mode 100644 index 00000000000..8562da60193 --- /dev/null +++ b/src/mesa/Android.libmesa_sse41.mk @@ -0,0 +1,44 @@ +# Copyright 2012 Intel Corporation +# Copyright (C) 2010-2011 Chia-I Wu <[email protected]> +# Copyright (C) 2010-2011 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. + +ifeq ($(ARCH_X86_HAVE_SSE4_1),true) + +LOCAL_PATH := $(call my-dir) + +include $(LOCAL_PATH)/Makefile.sources + +include $(CLEAR_VARS) + +LOCAL_MODULE := libmesa_sse41 + +LOCAL_SRC_FILES += \ + $(X86_SSE41_FILES) + +LOCAL_C_INCLUDES := \ + $(MESA_TOP)/src/mapi \ + $(MESA_TOP)/src/gallium/include \ + $(MESA_TOP)/src/gallium/auxiliary + +include $(MESA_COMMON_MK) +include $(BUILD_STATIC_LIBRARY) + +endif diff --git a/src/mesa/Android.libmesa_st_mesa.mk b/src/mesa/Android.libmesa_st_mesa.mk index 9fd9460a5ba..bbd39562785 100644 --- a/src/mesa/Android.libmesa_st_mesa.mk +++ b/src/mesa/Android.libmesa_st_mesa.mk @@ -47,6 +47,8 @@ endif # x86 endif # MESA_ENABLE_ASM ifeq ($(ARCH_X86_HAVE_SSE4_1),true) +LOCAL_WHOLE_STATIC_LIBRARIES := \ + libmesa_sse41 LOCAL_CFLAGS := \ -DUSE_SSE41 endif @@ -58,7 +60,7 @@ LOCAL_C_INCLUDES := \ $(MESA_TOP)/src/gallium/auxiliary \ $(MESA_TOP)/src/gallium/include -LOCAL_WHOLE_STATIC_LIBRARIES := \ +LOCAL_WHOLE_STATIC_LIBRARIES += \ libmesa_program include $(LOCAL_PATH)/Android.gen.mk diff --git a/src/mesa/Android.mk b/src/mesa/Android.mk index 20f781948be..9a1aef8b28e 100644 --- a/src/mesa/Android.mk +++ b/src/mesa/Android.mk @@ -24,5 +24,6 @@ include $(LOCAL_PATH)/Android.mesa_gen_matypes.mk include $(LOCAL_PATH)/Android.libmesa_glsl_utils.mk include $(LOCAL_PATH)/Android.libmesa_dricore.mk include $(LOCAL_PATH)/Android.libmesa_st_mesa.mk +include $(LOCAL_PATH)/Android.libmesa_sse41.mk include $(LOCAL_PATH)/program/Android.mk diff --git a/src/mesa/Makefile.sources b/src/mesa/Makefile.sources index a6c12c64828..7425f01273d 100644 --- a/src/mesa/Makefile.sources +++ b/src/mesa/Makefile.sources @@ -395,6 +395,7 @@ VBO_FILES = \ vbo/vbo_split_inplace.c STATETRACKER_FILES = \ + state_tracker/st_atifs_to_tgsi.c \ state_tracker/st_atom_array.c \ state_tracker/st_atom_atomicbuf.c \ state_tracker/st_atom_blend.c \ @@ -586,6 +587,10 @@ X86_64_FILES = \ x86-64/x86-64.h \ x86-64/xform4.S +X86_SSE41_FILES = \ + main/streaming-load-memcpy.c \ + main/sse_minmax.c + SPARC_FILES = \ sparc/sparc.h \ sparc/sparc_clip.S \ diff --git a/src/mesa/drivers/common/driverfuncs.c b/src/mesa/drivers/common/driverfuncs.c index e96f92af5bb..2730b7b2f2a 100644 --- a/src/mesa/drivers/common/driverfuncs.c +++ b/src/mesa/drivers/common/driverfuncs.c @@ -117,6 +117,9 @@ _mesa_init_driver_functions(struct dd_function_table *driver) driver->NewProgram = _mesa_new_program; driver->DeleteProgram = _mesa_delete_program; + /* ATI_fragment_shader */ + driver->NewATIfs = NULL; + /* simple state commands */ driver->AlphaFunc = NULL; driver->BlendColor = NULL; diff --git a/src/mesa/drivers/common/meta_generate_mipmap.c b/src/mesa/drivers/common/meta_generate_mipmap.c index d4b75390ebf..b81e179e2cd 100644 --- a/src/mesa/drivers/common/meta_generate_mipmap.c +++ b/src/mesa/drivers/common/meta_generate_mipmap.c @@ -137,21 +137,6 @@ _mesa_meta_glsl_generate_mipmap_cleanup(struct gl_context *ctx, _mesa_meta_blit_shader_table_cleanup(ctx, &mipmap->shaders); } -static GLboolean -prepare_mipmap_level(struct gl_context *ctx, - struct gl_texture_object *texObj, GLuint level, - GLsizei width, GLsizei height, GLsizei depth, - GLenum intFormat, mesa_format format) -{ - if (texObj->Target == GL_TEXTURE_1D_ARRAY) { - /* Work around Mesa expecting the number of array slices in "height". */ - height = depth; - depth = 1; - } - - return _mesa_prepare_mipmap_level(ctx, texObj, level, width, height, depth, - 0, intFormat, format); -} /** * Called via ctx->Driver.GenerateMipmap() @@ -270,6 +255,8 @@ _mesa_meta_GenerateMipmap(struct gl_context *ctx, GLenum target, /* texture is already locked, unlock now */ _mesa_unlock_texture(ctx, texObj); + _mesa_prepare_mipmap_levels(ctx, texObj, baseLevel, maxLevel); + for (dstLevel = baseLevel + 1; dstLevel <= maxLevel; dstLevel++) { const struct gl_texture_image *srcImage; struct gl_texture_image *dstImage; @@ -309,17 +296,14 @@ _mesa_meta_GenerateMipmap(struct gl_context *ctx, GLenum target, _mesa_texture_parameteriv(ctx, texObj, GL_TEXTURE_MAX_LEVEL, (GLint *) &dstLevel, false); - if (!prepare_mipmap_level(ctx, texObj, dstLevel, - dstWidth, dstHeight, dstDepth, - srcImage->InternalFormat, - srcImage->TexFormat)) { - /* All done. We either ran out of memory or we would go beyond the - * last valid level of an immutable texture if we continued. - */ - break; - } dstImage = _mesa_select_tex_image(texObj, faceTarget, dstLevel); + /* All done. We either ran out of memory or we would go beyond the last + * valid level of an immutable texture if we continued. + */ + if (dstImage == NULL) + break; + /* limit minification to src level */ _mesa_texture_parameteriv(ctx, texObj, GL_TEXTURE_MAX_LEVEL, (GLint *) &srcLevel, false); diff --git a/src/mesa/drivers/dri/i965/brw_fs_visitor.cpp b/src/mesa/drivers/dri/i965/brw_fs_visitor.cpp index f1da218ba63..daabf708b06 100644 --- a/src/mesa/drivers/dri/i965/brw_fs_visitor.cpp +++ b/src/mesa/drivers/dri/i965/brw_fs_visitor.cpp @@ -228,10 +228,16 @@ fs_visitor::emit_texture(ir_texture_opcode op, } /* fixup #layers for cube map arrays */ - if (op == ir_txs && is_cube_array) { + if (op == ir_txs && (devinfo->gen < 7 || is_cube_array)) { fs_reg depth = offset(dst, bld, 2); fs_reg fixed_depth = vgrf(glsl_type::int_type); - bld.emit(SHADER_OPCODE_INT_QUOTIENT, fixed_depth, depth, brw_imm_d(6)); + + if (is_cube_array) { + bld.emit(SHADER_OPCODE_INT_QUOTIENT, fixed_depth, depth, brw_imm_d(6)); + } else if (devinfo->gen < 7) { + /* Gen4-6 return 0 instead of 1 for single layer surfaces. */ + bld.emit_minmax(fixed_depth, depth, brw_imm_d(1), BRW_CONDITIONAL_GE); + } fs_reg *fixed_payload = ralloc_array(mem_ctx, fs_reg, inst->regs_written); int components = inst->regs_written / (inst->exec_size / 8); diff --git a/src/mesa/drivers/dri/i965/brw_link.cpp b/src/mesa/drivers/dri/i965/brw_link.cpp index b512f8b6ee1..c7d6fb8c79b 100644 --- a/src/mesa/drivers/dri/i965/brw_link.cpp +++ b/src/mesa/drivers/dri/i965/brw_link.cpp @@ -260,6 +260,6 @@ brw_link_shader(struct gl_context *ctx, struct gl_shader_program *shProg) if (brw->precompile && !brw_shader_precompile(ctx, shProg)) return false; - build_program_resource_list(shProg); + build_program_resource_list(ctx, shProg); return true; } diff --git a/src/mesa/drivers/dri/i965/brw_pipe_control.c b/src/mesa/drivers/dri/i965/brw_pipe_control.c index b41e28e1ec8..4672efdffc3 100644 --- a/src/mesa/drivers/dri/i965/brw_pipe_control.c +++ b/src/mesa/drivers/dri/i965/brw_pipe_control.c @@ -338,8 +338,6 @@ brw_emit_mi_flush(struct brw_context *brw) } brw_emit_pipe_control_flush(brw, flags); } - - brw_render_cache_set_clear(brw); } int diff --git a/src/mesa/drivers/dri/i965/brw_sampler_state.c b/src/mesa/drivers/dri/i965/brw_sampler_state.c index c20a02817f9..1dc7d71929c 100644 --- a/src/mesa/drivers/dri/i965/brw_sampler_state.c +++ b/src/mesa/drivers/dri/i965/brw_sampler_state.c @@ -459,10 +459,12 @@ brw_update_sampler_state(struct brw_context *brw, target == GL_TEXTURE_CUBE_MAP_ARRAY) { /* Cube maps must use the same wrap mode for all three coordinate * dimensions. Prior to Haswell, only CUBE and CLAMP are valid. + * + * Ivybridge and Baytrail seem to have problems with CUBE mode and + * integer formats. Fall back to CLAMP for now. */ if ((tex_cube_map_seamless || sampler->CubeMapSeamless) && - (sampler->MinFilter != GL_NEAREST || - sampler->MagFilter != GL_NEAREST)) { + !(brw->gen == 7 && !brw->is_haswell && is_integer_format)) { wrap_s = BRW_TEXCOORDMODE_CUBE; wrap_t = BRW_TEXCOORDMODE_CUBE; wrap_r = BRW_TEXCOORDMODE_CUBE; diff --git a/src/mesa/drivers/dri/i965/brw_schedule_instructions.cpp b/src/mesa/drivers/dri/i965/brw_schedule_instructions.cpp index 5b54b51395c..8d925843732 100644 --- a/src/mesa/drivers/dri/i965/brw_schedule_instructions.cpp +++ b/src/mesa/drivers/dri/i965/brw_schedule_instructions.cpp @@ -783,26 +783,13 @@ schedule_node::schedule_node(backend_instruction *inst, void instruction_scheduler::add_insts_from_block(bblock_t *block) { - /* Removing the last instruction from a basic block removes the block as - * well, so put a NOP at the end to keep it alive. - */ - if (!block->end()->is_control_flow()) { - backend_instruction *nop = new(mem_ctx) backend_instruction(); - nop->opcode = BRW_OPCODE_NOP; - block->end()->insert_after(block, nop); - } - - foreach_inst_in_block_safe(backend_instruction, inst, block) { - if (inst->opcode == BRW_OPCODE_NOP || inst->is_control_flow()) - continue; - + foreach_inst_in_block(backend_instruction, inst, block) { schedule_node *n = new(mem_ctx) schedule_node(inst, this); - this->instructions_to_schedule++; - - inst->remove(block); instructions.push_tail(n); } + + this->instructions_to_schedule = block->end_ip - block->start_ip + 1; } /** Recursive computation of the delay member of a node. */ @@ -905,6 +892,15 @@ fs_instruction_scheduler::is_compressed(fs_inst *inst) return inst->exec_size == 16; } +static bool +is_scheduling_barrier(const fs_inst *inst) +{ + return inst->opcode == FS_OPCODE_PLACEHOLDER_HALT || + inst->is_control_flow() || + inst->eot || + (inst->has_side_effects() && inst->opcode != FS_OPCODE_FB_WRITE); +} + void fs_instruction_scheduler::calculate_deps() { @@ -923,15 +919,6 @@ fs_instruction_scheduler::calculate_deps() */ schedule_node *last_fixed_grf_write = NULL; - /* The last instruction always needs to still be the last - * instruction. Either it's flow control (IF, ELSE, ENDIF, DO, - * WHILE) and scheduling other things after it would disturb the - * basic block, or it's FB_WRITE and we should do a better job at - * dead code elimination anyway. - */ - schedule_node *last = (schedule_node *)instructions.get_tail(); - add_barrier_deps(last); - memset(last_grf_write, 0, sizeof(last_grf_write)); memset(last_mrf_write, 0, sizeof(last_mrf_write)); @@ -939,9 +926,7 @@ fs_instruction_scheduler::calculate_deps() foreach_in_list(schedule_node, n, &instructions) { fs_inst *inst = (fs_inst *)n->inst; - if ((inst->opcode == FS_OPCODE_PLACEHOLDER_HALT || - inst->has_side_effects()) && - inst->opcode != FS_OPCODE_FB_WRITE) + if (is_scheduling_barrier(inst)) add_barrier_deps(n); /* read-after-write deps. */ @@ -964,10 +949,7 @@ fs_instruction_scheduler::calculate_deps() } } else if (inst->src[i].is_accumulator()) { add_dep(last_accumulator_write, n); - } else if (inst->src[i].file != BAD_FILE && - inst->src[i].file != IMM && - inst->src[i].file != UNIFORM) { - assert(inst->src[i].file != MRF); + } else if (inst->src[i].file == ARF) { add_barrier_deps(n); } } @@ -1026,8 +1008,7 @@ fs_instruction_scheduler::calculate_deps() } else if (inst->dst.is_accumulator()) { add_dep(last_accumulator_write, n); last_accumulator_write = n; - } else if (inst->dst.file != BAD_FILE && - !inst->dst.is_null()) { + } else if (inst->dst.file == ARF && !inst->dst.is_null()) { add_barrier_deps(n); } @@ -1080,10 +1061,7 @@ fs_instruction_scheduler::calculate_deps() } } else if (inst->src[i].is_accumulator()) { add_dep(n, last_accumulator_write, 0); - } else if (inst->src[i].file != BAD_FILE && - inst->src[i].file != IMM && - inst->src[i].file != UNIFORM) { - assert(inst->src[i].file != MRF); + } else if (inst->src[i].file == ARF) { add_barrier_deps(n); } } @@ -1140,8 +1118,7 @@ fs_instruction_scheduler::calculate_deps() } } else if (inst->dst.is_accumulator()) { last_accumulator_write = n; - } else if (inst->dst.file != BAD_FILE && - !inst->dst.is_null()) { + } else if (inst->dst.file == ARF && !inst->dst.is_null()) { add_barrier_deps(n); } @@ -1161,6 +1138,13 @@ fs_instruction_scheduler::calculate_deps() } } +static bool +is_scheduling_barrier(const vec4_instruction *inst) +{ + return inst->is_control_flow() || + inst->has_side_effects(); +} + void vec4_instruction_scheduler::calculate_deps() { @@ -1175,15 +1159,6 @@ vec4_instruction_scheduler::calculate_deps() */ schedule_node *last_fixed_grf_write = NULL; - /* The last instruction always needs to still be the last instruction. - * Either it's flow control (IF, ELSE, ENDIF, DO, WHILE) and scheduling - * other things after it would disturb the basic block, or it's the EOT - * URB_WRITE and we should do a better job at dead code eliminating - * anything that could have been scheduled after it. - */ - schedule_node *last = (schedule_node *)instructions.get_tail(); - add_barrier_deps(last); - memset(last_grf_write, 0, sizeof(last_grf_write)); memset(last_mrf_write, 0, sizeof(last_mrf_write)); @@ -1191,7 +1166,7 @@ vec4_instruction_scheduler::calculate_deps() foreach_in_list(schedule_node, n, &instructions) { vec4_instruction *inst = (vec4_instruction *)n->inst; - if (inst->has_side_effects() && inst->opcode != FS_OPCODE_FB_WRITE) + if (is_scheduling_barrier(inst)) add_barrier_deps(n); /* read-after-write deps. */ @@ -1204,12 +1179,7 @@ vec4_instruction_scheduler::calculate_deps() } else if (inst->src[i].is_accumulator()) { assert(last_accumulator_write); add_dep(last_accumulator_write, n); - } else if (inst->src[i].file != BAD_FILE && - inst->src[i].file != IMM && - inst->src[i].file != UNIFORM) { - /* No reads from MRF, and ATTR is already translated away */ - assert(inst->src[i].file != MRF && - inst->src[i].file != ATTR); + } else if (inst->src[i].file == ARF) { add_barrier_deps(n); } } @@ -1248,8 +1218,7 @@ vec4_instruction_scheduler::calculate_deps() } else if (inst->dst.is_accumulator()) { add_dep(last_accumulator_write, n); last_accumulator_write = n; - } else if (inst->dst.file != BAD_FILE && - !inst->dst.is_null()) { + } else if (inst->dst.file == ARF && !inst->dst.is_null()) { add_barrier_deps(n); } @@ -1291,11 +1260,7 @@ vec4_instruction_scheduler::calculate_deps() add_dep(n, last_fixed_grf_write); } else if (inst->src[i].is_accumulator()) { add_dep(n, last_accumulator_write); - } else if (inst->src[i].file != BAD_FILE && - inst->src[i].file != IMM && - inst->src[i].file != UNIFORM) { - assert(inst->src[i].file != MRF && - inst->src[i].file != ATTR); + } else if (inst->src[i].file == ARF) { add_barrier_deps(n); } } @@ -1330,8 +1295,7 @@ vec4_instruction_scheduler::calculate_deps() last_fixed_grf_write = n; } else if (inst->dst.is_accumulator()) { last_accumulator_write = n; - } else if (inst->dst.file != BAD_FILE && - !inst->dst.is_null()) { + } else if (inst->dst.file == ARF && !inst->dst.is_null()) { add_barrier_deps(n); } @@ -1500,7 +1464,6 @@ void instruction_scheduler::schedule_instructions(bblock_t *block) { const struct brw_device_info *devinfo = bs->devinfo; - backend_instruction *inst = block->end(); time = 0; if (!post_reg_alloc) reg_pressure = reg_pressure_in[block->num]; @@ -1519,7 +1482,8 @@ instruction_scheduler::schedule_instructions(bblock_t *block) /* Schedule this instruction. */ assert(chosen); chosen->remove(); - inst->insert_before(block, chosen->inst); + chosen->inst->exec_node::remove(); + block->instructions.push_tail(chosen->inst); instructions_to_schedule--; if (!post_reg_alloc) { @@ -1588,8 +1552,6 @@ instruction_scheduler::schedule_instructions(bblock_t *block) } } - if (block->end()->opcode == BRW_OPCODE_NOP) - block->end()->remove(block); assert(instructions_to_schedule == 0); block->cycle_count = time; @@ -1674,11 +1636,6 @@ fs_visitor::schedule_instructions(instruction_scheduler_mode mode) cfg->num_blocks, mode); sched.run(cfg); - if (unlikely(debug_enabled) && mode == SCHEDULE_POST) { - fprintf(stderr, "%s%d estimated execution time: %d cycles\n", - stage_abbrev, dispatch_width, sched.time); - } - invalidate_live_intervals(); } @@ -1688,10 +1645,5 @@ vec4_visitor::opt_schedule_instructions() vec4_instruction_scheduler sched(this, prog_data->total_grf); sched.run(cfg); - if (unlikely(debug_enabled)) { - fprintf(stderr, "%s estimated execution time: %d cycles\n", - stage_abbrev, sched.time); - } - invalidate_live_intervals(); } diff --git a/src/mesa/drivers/dri/i965/brw_shader.cpp b/src/mesa/drivers/dri/i965/brw_shader.cpp index 21977a23130..736deb443dd 100644 --- a/src/mesa/drivers/dri/i965/brw_shader.cpp +++ b/src/mesa/drivers/dri/i965/brw_shader.cpp @@ -948,6 +948,8 @@ adjust_later_block_ips(bblock_t *start_block, int ip_adjustment) void backend_instruction::insert_after(bblock_t *block, backend_instruction *inst) { + assert(this != inst); + if (!this->is_head_sentinel()) assert(inst_is_in_block(block, this) || !"Instruction not in block"); @@ -961,6 +963,8 @@ backend_instruction::insert_after(bblock_t *block, backend_instruction *inst) void backend_instruction::insert_before(bblock_t *block, backend_instruction *inst) { + assert(this != inst); + if (!this->is_tail_sentinel()) assert(inst_is_in_block(block, this) || !"Instruction not in block"); diff --git a/src/mesa/drivers/dri/i965/brw_vec4_generator.cpp b/src/mesa/drivers/dri/i965/brw_vec4_generator.cpp index c9728bfb694..4b3b08903c9 100644 --- a/src/mesa/drivers/dri/i965/brw_vec4_generator.cpp +++ b/src/mesa/drivers/dri/i965/brw_vec4_generator.cpp @@ -1973,7 +1973,6 @@ generate_code(struct brw_codegen *p, case TCS_OPCODE_SRC0_010_IS_ZERO: /* If src_reg had stride like fs_reg, we wouldn't need this. */ brw_MOV(p, brw_null_reg(), stride(src[0], 0, 1, 0)); - brw_inst_set_cond_modifier(devinfo, brw_last_inst, BRW_CONDITIONAL_Z); break; case TCS_OPCODE_RELEASE_INPUT: diff --git a/src/mesa/drivers/dri/i965/brw_vec4_tcs.cpp b/src/mesa/drivers/dri/i965/brw_vec4_tcs.cpp index 0ce48b8df5f..28aaaebd0b3 100644 --- a/src/mesa/drivers/dri/i965/brw_vec4_tcs.cpp +++ b/src/mesa/drivers/dri/i965/brw_vec4_tcs.cpp @@ -182,7 +182,9 @@ vec4_tcs_visitor::emit_thread_end() * we don't have stride in the vec4 world, nor UV immediates in * align16, so we need an opcode to get invocation_id<0,4,0>. */ - emit(TCS_OPCODE_SRC0_010_IS_ZERO, dst_null_d(), invocation_id); + set_condmod(BRW_CONDITIONAL_Z, + emit(TCS_OPCODE_SRC0_010_IS_ZERO, dst_null_d(), + invocation_id)); emit(IF(BRW_PREDICATE_NORMAL)); for (unsigned i = 0; i < key->input_vertices; i += 2) { /* If we have an odd number of input vertices, the last will be diff --git a/src/mesa/drivers/dri/i965/brw_vec4_visitor.cpp b/src/mesa/drivers/dri/i965/brw_vec4_visitor.cpp index 4cfbc143d5a..33c5f07cec9 100644 --- a/src/mesa/drivers/dri/i965/brw_vec4_visitor.cpp +++ b/src/mesa/drivers/dri/i965/brw_vec4_visitor.cpp @@ -1056,10 +1056,16 @@ vec4_visitor::emit_texture(ir_texture_opcode op, /* fixup num layers (z) for cube arrays: hardware returns faces * layers; * spec requires layers. */ - if (op == ir_txs && is_cube_array) { - emit_math(SHADER_OPCODE_INT_QUOTIENT, - writemask(inst->dst, WRITEMASK_Z), - src_reg(inst->dst), brw_imm_d(6)); + if (op == ir_txs) { + if (is_cube_array) { + emit_math(SHADER_OPCODE_INT_QUOTIENT, + writemask(inst->dst, WRITEMASK_Z), + src_reg(inst->dst), brw_imm_d(6)); + } else if (devinfo->gen < 7) { + /* Gen4-6 return 0 instead of 1 for single layer surfaces. */ + emit_minmax(BRW_CONDITIONAL_GE, writemask(inst->dst, WRITEMASK_Z), + src_reg(inst->dst), brw_imm_d(1)); + } } if (devinfo->gen == 6 && op == ir_tg4) { diff --git a/src/mesa/drivers/dri/i965/gen6_sol.c b/src/mesa/drivers/dri/i965/gen6_sol.c index 2f6eadffd2e..24bb4b41b1e 100644 --- a/src/mesa/drivers/dri/i965/gen6_sol.c +++ b/src/mesa/drivers/dri/i965/gen6_sol.c @@ -69,13 +69,13 @@ gen6_update_sol_surfaces(struct brw_context *brw) brw, xfb_obj->Buffers[buffer], &brw->gs.base.surf_offset[surf_index], linked_xfb_info->Outputs[i].NumComponents, - linked_xfb_info->BufferStride[buffer], buffer_offset); + linked_xfb_info->Buffers[buffer].Stride, buffer_offset); } else { brw_update_sol_surface( brw, xfb_obj->Buffers[buffer], &brw->ff_gs.surf_offset[surf_index], linked_xfb_info->Outputs[i].NumComponents, - linked_xfb_info->BufferStride[buffer], buffer_offset); + linked_xfb_info->Buffers[buffer].Stride, buffer_offset); } } else { if (!brw->geometry_program) @@ -256,7 +256,7 @@ brw_begin_transform_feedback(struct gl_context *ctx, GLenum mode, * overflowing any of the buffers currently being used for feedback. */ unsigned max_index - = _mesa_compute_max_transform_feedback_vertices(xfb_obj, + = _mesa_compute_max_transform_feedback_vertices(ctx, xfb_obj, linked_xfb_info); /* Initialize the SVBI 0 register to zero and set the maximum index. */ diff --git a/src/mesa/drivers/dri/i965/gen7_blorp.cpp b/src/mesa/drivers/dri/i965/gen7_blorp.cpp index 89b73ca7519..eae1e30e150 100644 --- a/src/mesa/drivers/dri/i965/gen7_blorp.cpp +++ b/src/mesa/drivers/dri/i965/gen7_blorp.cpp @@ -55,11 +55,8 @@ gen7_blorp_emit_urb_config(struct brw_context *brw) 0 /* gs_size */, urb_size / 2 /* fs_size */); - /* The minimum valid number of VS entries is 32. See 3DSTATE_URB_VS, Dword - * 1.15:0 "VS Number of URB Entries". - */ gen7_emit_urb_state(brw, - 32 /* num_vs_entries */, + brw->urb.min_vs_entries /* num_vs_entries */, 2 /* vs_size */, 2 /* vs_start */, 0 /* num_hs_entries */, diff --git a/src/mesa/drivers/dri/i965/gen7_sol_state.c b/src/mesa/drivers/dri/i965/gen7_sol_state.c index 8cd2fc4b48a..c44572c3438 100644 --- a/src/mesa/drivers/dri/i965/gen7_sol_state.c +++ b/src/mesa/drivers/dri/i965/gen7_sol_state.c @@ -70,7 +70,7 @@ upload_3dstate_so_buffers(struct brw_context *brw) continue; } - stride = linked_xfb_info->BufferStride[i] * 4; + stride = linked_xfb_info->Buffers[i].Stride * 4; start = xfb_obj->Offset[i]; assert(start % 4 == 0); diff --git a/src/mesa/drivers/dri/i965/gen8_ps_state.c b/src/mesa/drivers/dri/i965/gen8_ps_state.c index b9a06e7b2c7..7dfd4bfb8de 100644 --- a/src/mesa/drivers/dri/i965/gen8_ps_state.c +++ b/src/mesa/drivers/dri/i965/gen8_ps_state.c @@ -91,10 +91,15 @@ gen8_upload_ps_extra(struct brw_context *brw, * GEN8_PSX_PIXEL_SHADER_NO_RT_WRITE is not set it shouldn't make any * difference so we may just disable it here. * + * Gen8 hardware tries to compute ThreadDispatchEnable for us but doesn't + * take into account KillPixels when no depth or stencil writes are enabled. + * In order for occlusion queries to work correctly with no attachments, we + * need to force-enable here. + * * BRW_NEW_FS_PROG_DATA | BRW_NEW_FRAGMENT_PROGRAM | _NEW_BUFFERS | _NEW_COLOR */ - if (_mesa_active_fragment_shader_has_side_effects(&brw->ctx) && - !brw_color_buffer_write_enabled(brw)) + if ((_mesa_active_fragment_shader_has_side_effects(ctx) || + prog_data->uses_kill) && !brw_color_buffer_write_enabled(brw)) dw1 |= GEN8_PSX_SHADER_HAS_UAV; if (prog_data->computed_stencil) { diff --git a/src/mesa/drivers/dri/i965/gen8_sol_state.c b/src/mesa/drivers/dri/i965/gen8_sol_state.c index 58ead68e90c..f30818031f4 100644 --- a/src/mesa/drivers/dri/i965/gen8_sol_state.c +++ b/src/mesa/drivers/dri/i965/gen8_sol_state.c @@ -139,13 +139,13 @@ gen8_upload_3dstate_streamout(struct brw_context *brw, bool active, /* Set buffer pitches; 0 means unbound. */ if (xfb_obj->Buffers[0]) - dw3 |= linked_xfb_info->BufferStride[0] * 4; + dw3 |= linked_xfb_info->Buffers[0].Stride * 4; if (xfb_obj->Buffers[1]) - dw3 |= (linked_xfb_info->BufferStride[1] * 4) << 16; + dw3 |= (linked_xfb_info->Buffers[1].Stride * 4) << 16; if (xfb_obj->Buffers[2]) - dw4 |= linked_xfb_info->BufferStride[2] * 4; + dw4 |= linked_xfb_info->Buffers[2].Stride * 4; if (xfb_obj->Buffers[3]) - dw4 |= (linked_xfb_info->BufferStride[3] * 4) << 16; + dw4 |= (linked_xfb_info->Buffers[3].Stride * 4) << 16; } BEGIN_BATCH(5); diff --git a/src/mesa/drivers/dri/i965/intel_batchbuffer.c b/src/mesa/drivers/dri/i965/intel_batchbuffer.c index f77807472fd..e41f927819e 100644 --- a/src/mesa/drivers/dri/i965/intel_batchbuffer.c +++ b/src/mesa/drivers/dri/i965/intel_batchbuffer.c @@ -106,6 +106,32 @@ intel_batchbuffer_free(struct brw_context *brw) drm_intel_bo_unreference(brw->batch.bo); } +void +intel_batchbuffer_require_space(struct brw_context *brw, GLuint sz, + enum brw_gpu_ring ring) +{ + /* If we're switching rings, implicitly flush the batch. */ + if (unlikely(ring != brw->batch.ring) && brw->batch.ring != UNKNOWN_RING && + brw->gen >= 6) { + intel_batchbuffer_flush(brw); + } + +#ifdef DEBUG + assert(sz < BATCH_SZ - BATCH_RESERVED); +#endif + if (intel_batchbuffer_space(brw) < sz) + intel_batchbuffer_flush(brw); + + enum brw_gpu_ring prev_ring = brw->batch.ring; + /* The intel_batchbuffer_flush() calls above might have changed + * brw->batch.ring to UNKNOWN_RING, so we need to set it here at the end. + */ + brw->batch.ring = ring; + + if (unlikely(prev_ring == UNKNOWN_RING && ring == RENDER_RING)) + intel_batchbuffer_emit_render_ring_prelude(brw); +} + static void do_batch_dump(struct brw_context *brw) { diff --git a/src/mesa/drivers/dri/i965/intel_batchbuffer.h b/src/mesa/drivers/dri/i965/intel_batchbuffer.h index f47369029a0..aa1dc38babc 100644 --- a/src/mesa/drivers/dri/i965/intel_batchbuffer.h +++ b/src/mesa/drivers/dri/i965/intel_batchbuffer.h @@ -44,6 +44,8 @@ void intel_batchbuffer_init(struct brw_context *brw); void intel_batchbuffer_free(struct brw_context *brw); void intel_batchbuffer_save_state(struct brw_context *brw); void intel_batchbuffer_reset_to_saved(struct brw_context *brw); +void intel_batchbuffer_require_space(struct brw_context *brw, GLuint sz, + enum brw_gpu_ring ring); int _intel_batchbuffer_flush(struct brw_context *brw, const char *file, int line); @@ -117,32 +119,6 @@ intel_batchbuffer_emit_float(struct brw_context *brw, float f) } static inline void -intel_batchbuffer_require_space(struct brw_context *brw, GLuint sz, - enum brw_gpu_ring ring) -{ - /* If we're switching rings, implicitly flush the batch. */ - if (unlikely(ring != brw->batch.ring) && brw->batch.ring != UNKNOWN_RING && - brw->gen >= 6) { - intel_batchbuffer_flush(brw); - } - -#ifdef DEBUG - assert(sz < BATCH_SZ - BATCH_RESERVED); -#endif - if (intel_batchbuffer_space(brw) < sz) - intel_batchbuffer_flush(brw); - - enum brw_gpu_ring prev_ring = brw->batch.ring; - /* The intel_batchbuffer_flush() calls above might have changed - * brw->batch.ring to UNKNOWN_RING, so we need to set it here at the end. - */ - brw->batch.ring = ring; - - if (unlikely(prev_ring == UNKNOWN_RING && ring == RENDER_RING)) - intel_batchbuffer_emit_render_ring_prelude(brw); -} - -static inline void intel_batchbuffer_begin(struct brw_context *brw, int n, enum brw_gpu_ring ring) { intel_batchbuffer_require_space(brw, n * 4, ring); diff --git a/src/mesa/drivers/dri/i965/intel_fbo.c b/src/mesa/drivers/dri/i965/intel_fbo.c index b7b679686e5..7eb21acc40b 100644 --- a/src/mesa/drivers/dri/i965/intel_fbo.c +++ b/src/mesa/drivers/dri/i965/intel_fbo.c @@ -1065,7 +1065,28 @@ brw_render_cache_set_check_flush(struct brw_context *brw, drm_intel_bo *bo) if (!_mesa_set_search(brw->render_cache, bo)) return; - brw_emit_mi_flush(brw); + if (brw->gen >= 6) { + if (brw->gen == 6) { + /* [Dev-SNB{W/A}]: Before a PIPE_CONTROL with Write Cache + * Flush Enable = 1, a PIPE_CONTROL with any non-zero + * post-sync-op is required. + */ + brw_emit_post_sync_nonzero_flush(brw); + } + + brw_emit_pipe_control_flush(brw, + PIPE_CONTROL_DEPTH_CACHE_FLUSH | + PIPE_CONTROL_RENDER_TARGET_FLUSH | + PIPE_CONTROL_CS_STALL); + + brw_emit_pipe_control_flush(brw, + PIPE_CONTROL_TEXTURE_CACHE_INVALIDATE | + PIPE_CONTROL_CONST_CACHE_INVALIDATE); + } else { + brw_emit_mi_flush(brw); + } + + brw_render_cache_set_clear(brw); } /** diff --git a/src/mesa/drivers/x11/fakeglx.c b/src/mesa/drivers/x11/fakeglx.c index 9286f718d00..80b71765e6c 100644 --- a/src/mesa/drivers/x11/fakeglx.c +++ b/src/mesa/drivers/x11/fakeglx.c @@ -74,6 +74,7 @@ "GLX_MESA_copy_sub_buffer " \ "GLX_MESA_pixmap_colormap " \ "GLX_MESA_release_buffers " \ + "GLX_ARB_create_context " \ "GLX_ARB_get_proc_address " \ "GLX_EXT_texture_from_pixmap " \ "GLX_EXT_visual_info " \ @@ -2831,6 +2832,56 @@ Fake_glXReleaseTexImageEXT(Display *dpy, GLXDrawable drawable, int buffer) } +static GLXContext +Fake_glXCreateContextAttribs(Display *dpy, GLXFBConfig config, + GLXContext share_context, Bool direct, + const int *attrib_list) +{ + XMesaContext xmCtx; + XMesaVisual xmvis = (XMesaVisual) config; + int i; + int major = 0, minor = 0, ctxFlags = 0, profileFlags = 0; + + for (i = 0; attrib_list[i]; i += 2) { + switch (attrib_list[i]) { + case GLX_CONTEXT_MAJOR_VERSION_ARB: + major = attrib_list[i + 1]; + break; + case GLX_CONTEXT_MINOR_VERSION_ARB: + minor = attrib_list[i + 1]; + break; + case GLX_CONTEXT_FLAGS_ARB: + ctxFlags = attrib_list[i + 1]; + break; + case GLX_CONTEXT_PROFILE_MASK_ARB: + profileFlags = attrib_list[i + 1]; + break; + default: + fprintf(stderr, "Bad attribute in glXCreateContextAttribs()\n"); + return 0; + } + } + + if (major * 10 + minor > 21) { + /* swrast only supports GL 2.1 and earlier */ + return 0; + } + + /* These are ignored for now. We'd have to enhance XMesaCreateContext + * to take these flags and the version, at least. + */ + (void) ctxFlags; + (void) profileFlags; + + /* deallocate unused windows/buffers */ + XMesaGarbageCollect(dpy); + + xmCtx = XMesaCreateContext(xmvis, (XMesaContext) share_context); + + return (GLXContext) xmCtx; +} + + /* silence warning */ extern struct _glxapi_table *_mesa_GetGLXDispatchTable(void); @@ -2990,5 +3041,6 @@ _mesa_GetGLXDispatchTable(void) glx.BindTexImageEXT = Fake_glXBindTexImageEXT; glx.ReleaseTexImageEXT = Fake_glXReleaseTexImageEXT; + glx.CreateContextAttribs = Fake_glXCreateContextAttribs; return &glx; } diff --git a/src/mesa/drivers/x11/glxapi.c b/src/mesa/drivers/x11/glxapi.c index a870e94ed4a..cc1bb2ab4b3 100644 --- a/src/mesa/drivers/x11/glxapi.c +++ b/src/mesa/drivers/x11/glxapi.c @@ -1319,6 +1319,9 @@ static struct name_address_pair GLX_functions[] = { { "glXBindTexImageEXT", (__GLXextFuncPtr) glXBindTexImageEXT }, { "glXReleaseTexImageEXT", (__GLXextFuncPtr) glXReleaseTexImageEXT }, + /*** GLX_ARB_create_context ***/ + { "glXCreateContextAttribsARB", (__GLXextFuncPtr) glXCreateContextAttribsARB }, + { NULL, NULL } /* end of list */ }; @@ -1370,3 +1373,20 @@ void PUBLIC { return glXGetProcAddressARB(procName); } + + +/** + * Added in GLX_ARB_create_context. + */ +GLXContext PUBLIC +glXCreateContextAttribsARB(Display *dpy, GLXFBConfig config, + GLXContext share_context, Bool direct, + const int *attrib_list) +{ + struct _glxapi_table *t; + GET_DISPATCH(dpy, t); + if (!t) + return 0; + return (t->CreateContextAttribs)(dpy, config, share_context, direct, + attrib_list); +} diff --git a/src/mesa/drivers/x11/glxapi.h b/src/mesa/drivers/x11/glxapi.h index bd6e97053e6..aff38f7531d 100644 --- a/src/mesa/drivers/x11/glxapi.h +++ b/src/mesa/drivers/x11/glxapi.h @@ -201,6 +201,11 @@ struct _glxapi_table { void (*BindTexImageEXT)(Display *dpy, GLXDrawable drawable, int buffer, const int *attrib_list); void (*ReleaseTexImageEXT)(Display *dpy, GLXDrawable drawable, int buffer); + + /*** GLX_ARB_create_context ***/ + GLXContext (*CreateContextAttribs)(Display *dpy, GLXFBConfig config, + GLXContext share_context, Bool direct, + const int *attrib_list); }; diff --git a/src/mesa/main/atifragshader.c b/src/mesa/main/atifragshader.c index 8fcbff6a7a4..34f45c68008 100644 --- a/src/mesa/main/atifragshader.c +++ b/src/mesa/main/atifragshader.c @@ -30,6 +30,7 @@ #include "main/mtypes.h" #include "main/dispatch.h" #include "main/atifragshader.h" +#include "program/program.h" #define MESA_DEBUG_ATI_FS 0 @@ -63,6 +64,7 @@ _mesa_delete_ati_fragment_shader(struct gl_context *ctx, struct ati_fragment_sha free(s->Instructions[i]); free(s->SetupInst[i]); } + _mesa_reference_program(ctx, &s->Program, NULL); free(s); } @@ -321,6 +323,8 @@ _mesa_BeginFragmentShaderATI(void) free(ctx->ATIFragmentShader.Current->SetupInst[i]); } + _mesa_reference_program(ctx, &ctx->ATIFragmentShader.Current->Program, NULL); + /* malloc the instructions here - not sure if the best place but its a start */ for (i = 0; i < MAX_NUM_PASSES_ATI; i++) { @@ -405,7 +409,14 @@ _mesa_EndFragmentShaderATI(void) } #endif - if (!ctx->Driver.ProgramStringNotify(ctx, GL_FRAGMENT_SHADER_ATI, NULL)) { + if (ctx->Driver.NewATIfs) { + struct gl_program *prog = ctx->Driver.NewATIfs(ctx, + ctx->ATIFragmentShader.Current); + _mesa_reference_program(ctx, &ctx->ATIFragmentShader.Current->Program, prog); + } + + if (!ctx->Driver.ProgramStringNotify(ctx, GL_FRAGMENT_SHADER_ATI, + curProg->Program)) { ctx->ATIFragmentShader.Current->isValid = GL_FALSE; /* XXX is this the right error? */ _mesa_error(ctx, GL_INVALID_OPERATION, diff --git a/src/mesa/main/atifragshader.h b/src/mesa/main/atifragshader.h index 59011341018..0e32795da3b 100644 --- a/src/mesa/main/atifragshader.h +++ b/src/mesa/main/atifragshader.h @@ -16,6 +16,7 @@ struct gl_context; #define MAX_NUM_INSTRUCTIONS_PER_PASS_ATI 8 #define MAX_NUM_PASSES_ATI 2 #define MAX_NUM_FRAGMENT_REGISTERS_ATI 6 +#define MAX_NUM_FRAGMENT_CONSTANTS_ATI 8 struct ati_fs_opcode_st { diff --git a/src/mesa/main/bufferobj.c b/src/mesa/main/bufferobj.c index 9aec42508a7..731b62ebe21 100644 --- a/src/mesa/main/bufferobj.c +++ b/src/mesa/main/bufferobj.c @@ -148,8 +148,8 @@ get_buffer_target(struct gl_context *ctx, GLenum target) } break; case GL_TEXTURE_BUFFER: - if (ctx->API == API_OPENGL_CORE && - ctx->Extensions.ARB_texture_buffer_object) { + if (_mesa_has_ARB_texture_buffer_object(ctx) || + _mesa_has_OES_texture_buffer(ctx)) { return &ctx->Texture.BufferObject; } break; diff --git a/src/mesa/main/buffers.c b/src/mesa/main/buffers.c index 26dafd1b786..a28c5831576 100644 --- a/src/mesa/main/buffers.c +++ b/src/mesa/main/buffers.c @@ -222,6 +222,12 @@ read_buffer_enum_to_index(GLenum buffer) } } +static bool +is_legal_es3_readbuffer_enum(GLenum buf) +{ + return buf == GL_BACK || buf == GL_NONE || + (buf >= GL_COLOR_ATTACHMENT0 && buf <= GL_COLOR_ATTACHMENT31); +} /** * Called by glDrawBuffer() and glNamedFramebufferDrawBuffer(). @@ -715,7 +721,11 @@ read_buffer(struct gl_context *ctx, struct gl_framebuffer *fb, } else { /* general case / window-system framebuffer */ - srcBuffer = read_buffer_enum_to_index(buffer); + if (_mesa_is_gles3(ctx) && !is_legal_es3_readbuffer_enum(buffer)) + srcBuffer = -1; + else + srcBuffer = read_buffer_enum_to_index(buffer); + if (srcBuffer == -1) { _mesa_error(ctx, GL_INVALID_ENUM, "%s(invalid buffer %s)", caller, diff --git a/src/mesa/main/copyimage.c b/src/mesa/main/copyimage.c index d571d221bce..a0f1c691220 100644 --- a/src/mesa/main/copyimage.c +++ b/src/mesa/main/copyimage.c @@ -25,6 +25,7 @@ * Jason Ekstrand <[email protected]> */ +#include "context.h" #include "glheader.h" #include "errors.h" #include "enums.h" @@ -360,8 +361,32 @@ compressed_format_compatible(const struct gl_context *ctx, case GL_COMPRESSED_SIGNED_RED_RGTC1: compressedClass = BLOCK_CLASS_64_BITS; break; + case GL_COMPRESSED_RGBA8_ETC2_EAC: + case GL_COMPRESSED_SRGB8_ALPHA8_ETC2_EAC: + case GL_COMPRESSED_RG11_EAC: + case GL_COMPRESSED_SIGNED_RG11_EAC: + if (_mesa_is_gles(ctx)) + compressedClass = BLOCK_CLASS_128_BITS; + else + return false; + break; + case GL_COMPRESSED_RGB8_ETC2: + case GL_COMPRESSED_SRGB8_ETC2: + case GL_COMPRESSED_R11_EAC: + case GL_COMPRESSED_SIGNED_R11_EAC: + case GL_COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_ETC2: + case GL_COMPRESSED_SRGB8_PUNCHTHROUGH_ALPHA1_ETC2: + if (_mesa_is_gles(ctx)) + compressedClass = BLOCK_CLASS_64_BITS; + else + return false; + break; default: - return false; + if (_mesa_is_gles(ctx) && _mesa_is_astc_format(compressedFormat)) + compressedClass = BLOCK_CLASS_128_BITS; + else + return false; + break; } switch (otherFormat) { diff --git a/src/mesa/main/dd.h b/src/mesa/main/dd.h index 60bc8ef4411..d62fee690f4 100644 --- a/src/mesa/main/dd.h +++ b/src/mesa/main/dd.h @@ -477,6 +477,11 @@ struct dd_function_table { /** Delete a program */ void (*DeleteProgram)(struct gl_context *ctx, struct gl_program *prog); /** + * Allocate a program to associate with the new ATI fragment shader (optional) + */ + struct gl_program * (*NewATIfs)(struct gl_context *ctx, + struct ati_fragment_shader *curProg); + /** * Notify driver that a program string (and GPU code) has been specified * or modified. Return GL_TRUE or GL_FALSE to indicate if the program is * supported by the driver. diff --git a/src/mesa/main/enable.c b/src/mesa/main/enable.c index b90a60ba03f..d2830770ec2 100644 --- a/src/mesa/main/enable.c +++ b/src/mesa/main/enable.c @@ -807,7 +807,7 @@ _mesa_set_enable(struct gl_context *ctx, GLenum cap, GLboolean state) /* GL_ARB_sample_shading */ case GL_SAMPLE_SHADING: - if (!_mesa_is_desktop_gl(ctx)) + if (!_mesa_is_desktop_gl(ctx) && !_mesa_is_gles3(ctx)) goto invalid_enum_error; CHECK_EXTENSION(ARB_sample_shading, cap); if (ctx->Multisample.SampleShading == state) @@ -1606,7 +1606,7 @@ _mesa_IsEnabled( GLenum cap ) /* ARB_sample_shading */ case GL_SAMPLE_SHADING: - if (!_mesa_is_desktop_gl(ctx)) + if (!_mesa_is_desktop_gl(ctx) && !_mesa_is_gles3(ctx)) goto invalid_enum_error; CHECK_EXTENSION(ARB_sample_shading); return ctx->Multisample.SampleShading; diff --git a/src/mesa/main/extensions_table.h b/src/mesa/main/extensions_table.h index 54a5bb057a3..7c36b1e1d0b 100644 --- a/src/mesa/main/extensions_table.h +++ b/src/mesa/main/extensions_table.h @@ -186,11 +186,13 @@ EXT(EXT_blend_subtract , dummy_true EXT(EXT_buffer_storage , ARB_buffer_storage , x , x , x , 31, 2015) EXT(EXT_color_buffer_float , dummy_true , x , x , ES1, 30, 2013) EXT(EXT_compiled_vertex_array , dummy_true , GLL, x , x , x , 1996) +EXT(EXT_copy_image , OES_copy_image , x , x , x , 30, 2014) EXT(EXT_copy_texture , dummy_true , GLL, x , x , x , 1995) EXT(EXT_depth_bounds_test , EXT_depth_bounds_test , GLL, GLC, x , x , 2002) EXT(EXT_discard_framebuffer , dummy_true , x , x , ES1, ES2, 2009) EXT(EXT_draw_buffers , dummy_true , x , x , x , ES2, 2012) EXT(EXT_draw_buffers2 , EXT_draw_buffers2 , GLL, GLC, x , x , 2006) +EXT(EXT_draw_buffers_indexed , ARB_draw_buffers_blend , x , x , x , 30, 2014) EXT(EXT_draw_elements_base_vertex , ARB_draw_elements_base_vertex , x , x , x , ES2, 2014) EXT(EXT_draw_instanced , ARB_draw_instanced , GLL, GLC, x , x , 2006) EXT(EXT_draw_range_elements , dummy_true , GLL, x , x , x , 1997) @@ -228,6 +230,7 @@ EXT(EXT_texture , dummy_true EXT(EXT_texture3D , dummy_true , GLL, x , x , x , 1996) EXT(EXT_texture_array , EXT_texture_array , GLL, GLC, x , x , 2006) EXT(EXT_texture_border_clamp , ARB_texture_border_clamp , x , x , x , ES2, 2014) +EXT(EXT_texture_buffer , OES_texture_buffer , x , x , x , 31, 2014) EXT(EXT_texture_compression_dxt1 , ANGLE_texture_compression_dxt , GLL, GLC, ES1, ES2, 2004) EXT(EXT_texture_compression_latc , EXT_texture_compression_latc , GLL, x , x , x , 2006) EXT(EXT_texture_compression_rgtc , ARB_texture_compression_rgtc , GLL, GLC, x , x , 2004) @@ -308,10 +311,12 @@ EXT(OES_blend_subtract , dummy_true EXT(OES_byte_coordinates , dummy_true , x , x , ES1, x , 2002) EXT(OES_compressed_ETC1_RGB8_texture , OES_compressed_ETC1_RGB8_texture , x , x , ES1, ES2, 2005) EXT(OES_compressed_paletted_texture , dummy_true , x , x , ES1, x , 2003) +EXT(OES_copy_image , OES_copy_image , x , x , x , 30, 2014) EXT(OES_depth24 , dummy_true , x , x , ES1, ES2, 2005) EXT(OES_depth32 , dummy_false , x , x , x , x , 2005) EXT(OES_depth_texture , ARB_depth_texture , x , x , x , ES2, 2006) EXT(OES_depth_texture_cube_map , OES_depth_texture_cube_map , x , x , x , ES2, 2012) +EXT(OES_draw_buffers_indexed , ARB_draw_buffers_blend , x , x , x , 30, 2014) EXT(OES_draw_elements_base_vertex , ARB_draw_elements_base_vertex , x , x , x , ES2, 2014) EXT(OES_draw_texture , OES_draw_texture , x , x , ES1, x , 2004) EXT(OES_element_index_uint , dummy_true , x , x , ES1, ES2, 2005) @@ -329,7 +334,10 @@ EXT(OES_point_sprite , ARB_point_sprite EXT(OES_query_matrix , dummy_true , x , x , ES1, x , 2003) EXT(OES_read_format , dummy_true , GLL, GLC, ES1, x , 2003) EXT(OES_rgb8_rgba8 , dummy_true , x , x , ES1, ES2, 2005) +EXT(OES_sample_shading , OES_sample_variables , x , x , x , 30, 2014) +EXT(OES_sample_variables , OES_sample_variables , x , x , x , 30, 2014) EXT(OES_shader_image_atomic , ARB_shader_image_load_store , x , x , x , 31, 2015) +EXT(OES_shader_multisample_interpolation , OES_sample_variables , x , x , x , 30, 2014) EXT(OES_single_precision , dummy_true , x , x , ES1, x , 2003) EXT(OES_standard_derivatives , OES_standard_derivatives , x , x , x , ES2, 2005) EXT(OES_stencil1 , dummy_false , x , x , x , x , 2005) @@ -339,6 +347,7 @@ EXT(OES_stencil_wrap , dummy_true EXT(OES_surfaceless_context , dummy_true , x , x , ES1, ES2, 2012) EXT(OES_texture_3D , dummy_true , x , x , x , ES2, 2005) EXT(OES_texture_border_clamp , ARB_texture_border_clamp , x , x , x , ES2, 2014) +EXT(OES_texture_buffer , OES_texture_buffer , x , x , x , 31, 2014) EXT(OES_texture_cube_map , ARB_texture_cube_map , x , x , ES1, x , 2007) EXT(OES_texture_env_crossbar , ARB_texture_env_crossbar , x , x , ES1, x , 2005) EXT(OES_texture_float , OES_texture_float , x , x , x , ES2, 2005) diff --git a/src/mesa/main/get.c b/src/mesa/main/get.c index b0fadc93aef..6829c33254c 100644 --- a/src/mesa/main/get.c +++ b/src/mesa/main/get.c @@ -408,6 +408,11 @@ static const int extra_ARB_gpu_shader5_or_oes_geometry_shader[] = { EXTRA_END }; +static const int extra_ARB_gpu_shader5_or_OES_sample_variables[] = { + EXT(ARB_gpu_shader5), + EXT(OES_sample_variables), +}; + EXTRA_EXT(ARB_texture_cube_map); EXTRA_EXT(EXT_texture_array); EXTRA_EXT(NV_fog_distance); @@ -1907,8 +1912,8 @@ tex_binding_to_index(const struct gl_context *ctx, GLenum binding) || _mesa_is_gles3(ctx) ? TEXTURE_2D_ARRAY_INDEX : -1; case GL_TEXTURE_BINDING_BUFFER: - return ctx->API == API_OPENGL_CORE && - ctx->Extensions.ARB_texture_buffer_object ? + return (_mesa_has_ARB_texture_buffer_object(ctx) || + _mesa_has_OES_texture_buffer(ctx)) ? TEXTURE_BUFFER_INDEX : -1; case GL_TEXTURE_BINDING_CUBE_MAP_ARRAY: return _mesa_is_desktop_gl(ctx) && ctx->Extensions.ARB_texture_cube_map_array diff --git a/src/mesa/main/get_hash_params.py b/src/mesa/main/get_hash_params.py index 12c21899cb1..a0cc4f8e842 100644 --- a/src/mesa/main/get_hash_params.py +++ b/src/mesa/main/get_hash_params.py @@ -503,6 +503,14 @@ descriptor=[ [ "MAX_COMBINED_SHADER_OUTPUT_RESOURCES", "CONTEXT_INT(Const.MaxCombinedShaderOutputResources), extra_ARB_shader_image_load_store_shader_storage_buffer_object_es31" ], ]}, +# Enums in OpenGL Core profile and ES 3.0 +{ "apis": ["GL_CORE", "GLES3"], "params": [ + # GL_ARB_gpu_shader5 / GL_OES_shader_multisample_interpolation + [ "MIN_FRAGMENT_INTERPOLATION_OFFSET", "CONTEXT_FLOAT(Const.MinFragmentInterpolationOffset), extra_ARB_gpu_shader5_or_OES_sample_variables" ], + [ "MAX_FRAGMENT_INTERPOLATION_OFFSET", "CONTEXT_FLOAT(Const.MaxFragmentInterpolationOffset), extra_ARB_gpu_shader5_or_OES_sample_variables" ], + [ "FRAGMENT_INTERPOLATION_OFFSET_BITS", "CONST(FRAGMENT_INTERPOLATION_OFFSET_BITS), extra_ARB_gpu_shader5_or_OES_sample_variables" ], +]}, + # Enums in OpenGL Core profile and ES 3.1 { "apis": ["GL_CORE", "GLES31"], "params": [ # GL_ARB_draw_indirect / GLES 3.1 @@ -535,6 +543,16 @@ descriptor=[ # GL_ARB_gpu_shader5 / GL_OES_geometry_shader [ "MAX_GEOMETRY_SHADER_INVOCATIONS", "CONST(MAX_GEOMETRY_SHADER_INVOCATIONS), extra_ARB_gpu_shader5_or_oes_geometry_shader" ], + +# GL_ARB_texture_buffer_object / GL_OES_texture_buffer + [ "MAX_TEXTURE_BUFFER_SIZE_ARB", "CONTEXT_INT(Const.MaxTextureBufferSize), extra_texture_buffer_object" ], + [ "TEXTURE_BINDING_BUFFER_ARB", "LOC_CUSTOM, TYPE_INT, 0, extra_texture_buffer_object" ], + [ "TEXTURE_BUFFER_DATA_STORE_BINDING_ARB", "LOC_CUSTOM, TYPE_INT, TEXTURE_BUFFER_INDEX, extra_texture_buffer_object" ], + [ "TEXTURE_BUFFER_FORMAT_ARB", "LOC_CUSTOM, TYPE_INT, 0, extra_texture_buffer_object" ], + [ "TEXTURE_BUFFER_ARB", "LOC_CUSTOM, TYPE_INT, 0, extra_texture_buffer_object" ], + +# GL_ARB_texture_buffer_range + [ "TEXTURE_BUFFER_OFFSET_ALIGNMENT", "CONTEXT_INT(Const.TextureBufferOffsetAlignment), extra_ARB_texture_buffer_range" ], ]}, # Remaining enums are only in OpenGL @@ -805,13 +823,6 @@ descriptor=[ # GL_ARB_color_buffer_float [ "RGBA_FLOAT_MODE_ARB", "BUFFER_FIELD(Visual.floatMode, TYPE_BOOLEAN), extra_core_ARB_color_buffer_float_and_new_buffers" ], -# GL_ARB_texture_buffer_object - [ "MAX_TEXTURE_BUFFER_SIZE_ARB", "CONTEXT_INT(Const.MaxTextureBufferSize), extra_texture_buffer_object" ], - [ "TEXTURE_BINDING_BUFFER_ARB", "LOC_CUSTOM, TYPE_INT, 0, extra_texture_buffer_object" ], - [ "TEXTURE_BUFFER_DATA_STORE_BINDING_ARB", "LOC_CUSTOM, TYPE_INT, TEXTURE_BUFFER_INDEX, extra_texture_buffer_object" ], - [ "TEXTURE_BUFFER_FORMAT_ARB", "LOC_CUSTOM, TYPE_INT, 0, extra_texture_buffer_object" ], - [ "TEXTURE_BUFFER_ARB", "LOC_CUSTOM, TYPE_INT, 0, extra_texture_buffer_object" ], - # GL 3.0 [ "CONTEXT_FLAGS", "CONTEXT_INT(Const.ContextFlags), extra_version_30" ], @@ -871,21 +882,12 @@ descriptor=[ # Enums restricted to OpenGL Core profile { "apis": ["GL_CORE"], "params": [ -# GL_ARB_texture_buffer_range - [ "TEXTURE_BUFFER_OFFSET_ALIGNMENT", "CONTEXT_INT(Const.TextureBufferOffsetAlignment), extra_ARB_texture_buffer_range" ], - # GL_ARB_viewport_array [ "MAX_VIEWPORTS", "CONTEXT_INT(Const.MaxViewports), extra_ARB_viewport_array" ], [ "VIEWPORT_SUBPIXEL_BITS", "CONTEXT_INT(Const.ViewportSubpixelBits), extra_ARB_viewport_array" ], [ "VIEWPORT_BOUNDS_RANGE", "CONTEXT_FLOAT2(Const.ViewportBounds), extra_ARB_viewport_array" ], [ "VIEWPORT_INDEX_PROVOKING_VERTEX", "CONTEXT_ENUM(Const.LayerAndVPIndexProvokingVertex), extra_ARB_viewport_array" ], -# GL_ARB_gpu_shader5 - [ "MAX_GEOMETRY_SHADER_INVOCATIONS", "CONST(MAX_GEOMETRY_SHADER_INVOCATIONS), extra_ARB_gpu_shader5" ], - [ "MIN_FRAGMENT_INTERPOLATION_OFFSET", "CONTEXT_FLOAT(Const.MinFragmentInterpolationOffset), extra_ARB_gpu_shader5" ], - [ "MAX_FRAGMENT_INTERPOLATION_OFFSET", "CONTEXT_FLOAT(Const.MaxFragmentInterpolationOffset), extra_ARB_gpu_shader5" ], - [ "FRAGMENT_INTERPOLATION_OFFSET_BITS", "CONST(FRAGMENT_INTERPOLATION_OFFSET_BITS), extra_ARB_gpu_shader5" ], - # GL_ARB_tessellation_shader [ "PATCH_VERTICES", "CONTEXT_INT(TessCtrlProgram.patch_vertices), extra_ARB_tessellation_shader" ], [ "PATCH_DEFAULT_OUTER_LEVEL", "CONTEXT_FLOAT4(TessCtrlProgram.patch_default_outer_level), extra_ARB_tessellation_shader" ], diff --git a/src/mesa/main/mipmap.c b/src/mesa/main/mipmap.c index 5a02780b960..5ff53f4265c 100644 --- a/src/mesa/main/mipmap.c +++ b/src/mesa/main/mipmap.c @@ -1810,11 +1810,11 @@ _mesa_next_mipmap_level_size(GLenum target, GLint border, * for mipmap generation. If not, (re) allocate it. * \return GL_TRUE if successful, GL_FALSE if mipmap generation should stop */ -GLboolean -_mesa_prepare_mipmap_level(struct gl_context *ctx, - struct gl_texture_object *texObj, GLuint level, - GLsizei width, GLsizei height, GLsizei depth, - GLsizei border, GLenum intFormat, mesa_format format) +static GLboolean +prepare_mipmap_level(struct gl_context *ctx, + struct gl_texture_object *texObj, GLuint level, + GLsizei width, GLsizei height, GLsizei depth, + GLsizei border, GLenum intFormat, mesa_format format) { const GLuint numFaces = _mesa_num_tex_faces(texObj->Target); GLuint face; @@ -1872,6 +1872,49 @@ _mesa_prepare_mipmap_level(struct gl_context *ctx, } +/** + * Prepare all mipmap levels beyond 'baseLevel' for mipmap generation. + * When finished, all the gl_texture_image structures for the smaller + * mipmap levels will be consistent with the base level (in terms of + * dimensions, format, etc). + */ +void +_mesa_prepare_mipmap_levels(struct gl_context *ctx, + struct gl_texture_object *texObj, + unsigned baseLevel, unsigned maxLevel) +{ + const struct gl_texture_image *baseImage = + _mesa_select_tex_image(texObj, texObj->Target, baseLevel); + const GLint border = 0; + GLint width = baseImage->Width; + GLint height = baseImage->Height; + GLint depth = baseImage->Depth; + const GLenum intFormat = baseImage->InternalFormat; + const mesa_format texFormat = baseImage->TexFormat; + GLint newWidth, newHeight, newDepth; + + /* Prepare baseLevel + 1, baseLevel + 2, ... */ + for (unsigned level = baseLevel + 1; level <= maxLevel; level++) { + if (!_mesa_next_mipmap_level_size(texObj->Target, border, + width, height, depth, + &newWidth, &newHeight, &newDepth)) { + /* all done */ + break; + } + + if (!prepare_mipmap_level(ctx, texObj, level, + newWidth, newHeight, newDepth, + border, intFormat, texFormat)) { + break; + } + + width = newWidth; + height = newHeight; + depth = newDepth; + } +} + + static void generate_mipmap_uncompressed(struct gl_context *ctx, GLenum target, struct gl_texture_object *texObj, @@ -1892,7 +1935,6 @@ generate_mipmap_uncompressed(struct gl_context *ctx, GLenum target, GLint dstWidth, dstHeight, dstDepth; GLint border; GLint slice; - GLboolean nextLevel; GLubyte **srcMaps, **dstMaps; GLboolean success = GL_TRUE; @@ -1904,22 +1946,14 @@ generate_mipmap_uncompressed(struct gl_context *ctx, GLenum target, srcDepth = srcImage->Depth; border = srcImage->Border; - nextLevel = _mesa_next_mipmap_level_size(target, border, - srcWidth, srcHeight, srcDepth, - &dstWidth, &dstHeight, &dstDepth); - if (!nextLevel) - return; - - if (!_mesa_prepare_mipmap_level(ctx, texObj, level + 1, - dstWidth, dstHeight, dstDepth, - border, srcImage->InternalFormat, - srcImage->TexFormat)) { - return; - } - /* get dest gl_texture_image */ dstImage = _mesa_select_tex_image(texObj, target, level + 1); - assert(dstImage); + if (!dstImage) { + break; + } + dstWidth = dstImage->Width; + dstHeight = dstImage->Height; + dstDepth = dstImage->Depth; if (target == GL_TEXTURE_1D_ARRAY) { srcDepth = srcHeight; @@ -2087,7 +2121,6 @@ generate_mipmap_compressed(struct gl_context *ctx, GLenum target, GLint srcWidth, srcHeight, srcDepth; GLint dstWidth, dstHeight, dstDepth; GLint border; - GLboolean nextLevel; GLuint temp_dst_row_stride, temp_dst_img_stride; /* in bytes */ GLint i; @@ -2099,23 +2132,14 @@ generate_mipmap_compressed(struct gl_context *ctx, GLenum target, srcDepth = srcImage->Depth; border = srcImage->Border; - nextLevel = _mesa_next_mipmap_level_size(target, border, - srcWidth, srcHeight, srcDepth, - &dstWidth, &dstHeight, &dstDepth); - if (!nextLevel) - goto end; - - if (!_mesa_prepare_mipmap_level(ctx, texObj, level + 1, - dstWidth, dstHeight, dstDepth, - border, srcImage->InternalFormat, - srcImage->TexFormat)) { - /* all done */ - goto end; - } - /* get dest gl_texture_image */ dstImage = _mesa_select_tex_image(texObj, target, level + 1); - assert(dstImage); + if (!dstImage) { + break; + } + dstWidth = dstImage->Width; + dstHeight = dstImage->Height; + dstDepth = dstImage->Depth; /* Compute dst image strides and alloc memory on first iteration */ temp_dst_row_stride = _mesa_format_row_stride(temp_format, dstWidth); @@ -2194,6 +2218,8 @@ _mesa_generate_mipmap(struct gl_context *ctx, GLenum target, maxLevel = MIN2(maxLevel, texObj->MaxLevel); + _mesa_prepare_mipmap_levels(ctx, texObj, texObj->BaseLevel, maxLevel); + if (_mesa_is_format_compressed(srcImage->TexFormat)) { generate_mipmap_compressed(ctx, target, texObj, srcImage, maxLevel); } else { diff --git a/src/mesa/main/mipmap.h b/src/mesa/main/mipmap.h index c0366d329a2..d11c7fada37 100644 --- a/src/mesa/main/mipmap.h +++ b/src/mesa/main/mipmap.h @@ -40,12 +40,10 @@ _mesa_generate_mipmap_level(GLenum target, GLubyte **dstData, GLint dstRowStride); - -extern GLboolean -_mesa_prepare_mipmap_level(struct gl_context *ctx, - struct gl_texture_object *texObj, GLuint level, - GLsizei width, GLsizei height, GLsizei depth, - GLsizei border, GLenum intFormat, mesa_format format); +void +_mesa_prepare_mipmap_levels(struct gl_context *ctx, + struct gl_texture_object *texObj, + unsigned baseLevel, unsigned maxLevel); extern void _mesa_generate_mipmap(struct gl_context *ctx, GLenum target, diff --git a/src/mesa/main/mtypes.h b/src/mesa/main/mtypes.h index 71aae178adf..d609ae92e0c 100644 --- a/src/mesa/main/mtypes.h +++ b/src/mesa/main/mtypes.h @@ -1618,7 +1618,9 @@ struct gl_transform_feedback_varying_info { char *Name; GLenum Type; + GLint BufferIndex; GLint Size; + GLint Offset; }; @@ -1644,15 +1646,33 @@ struct gl_transform_feedback_output }; +struct gl_transform_feedback_buffer +{ + unsigned Binding; + + unsigned NumVaryings; + + /** + * Total number of components stored in each buffer. This may be used by + * hardware back-ends to determine the correct stride when interleaving + * multiple transform feedback outputs in the same buffer. + */ + unsigned Stride; + + /** + * Which transform feedback stream this buffer binding is associated with. + */ + unsigned Stream; +}; + + /** Post-link transform feedback info. */ struct gl_transform_feedback_info { unsigned NumOutputs; - /** - * Number of transform feedback buffers in use by this program. - */ - unsigned NumBuffers; + /* Bitmask of active buffer indices. */ + unsigned ActiveBuffers; struct gl_transform_feedback_output *Outputs; @@ -1663,17 +1683,7 @@ struct gl_transform_feedback_info struct gl_transform_feedback_varying_info *Varyings; GLint NumVarying; - /** - * Total number of components stored in each buffer. This may be used by - * hardware back-ends to determine the correct stride when interleaving - * multiple transform feedback outputs in the same buffer. - */ - unsigned BufferStride[MAX_FEEDBACK_BUFFERS]; - - /** - * Which transform feedback stream this buffer binding is associated with. - */ - unsigned BufferStream[MAX_FEEDBACK_BUFFERS]; + struct gl_transform_feedback_buffer Buffers[MAX_FEEDBACK_BUFFERS]; }; @@ -2196,6 +2206,7 @@ struct ati_fragment_shader GLboolean interpinp1; GLboolean isValid; GLuint swizzlerq; + struct gl_program *Program; }; /** @@ -2306,7 +2317,7 @@ struct gl_shader * duplicated. */ unsigned NumBufferInterfaceBlocks; - struct gl_uniform_block *BufferInterfaceBlocks; + struct gl_uniform_block **BufferInterfaceBlocks; unsigned NumUniformBlocks; struct gl_uniform_block **UniformBlocks; @@ -2330,6 +2341,11 @@ struct gl_shader bool origin_upper_left; bool pixel_center_integer; + struct { + /** Global xfb_stride out qualifier if any */ + GLuint BufferStride[MAX_FEEDBACK_BUFFERS]; + } TransformFeedback; + /** * Tessellation Control shader state from layout qualifiers. */ @@ -2672,6 +2688,8 @@ struct gl_shader_program */ struct { GLenum BufferMode; + /** Global xfb_stride out qualifier if any */ + GLuint BufferStride[MAX_FEEDBACK_BUFFERS]; GLuint NumVarying; GLchar **VaryingNames; /**< Array [NumVarying] of char * */ } TransformFeedback; @@ -2827,13 +2845,6 @@ struct gl_shader_program int *InterfaceBlockStageIndex[MESA_SHADER_STAGES]; /** - * Indices into the BufferInterfaceBlocks[] array for Uniform Buffer - * Objects and Shader Storage Buffer Objects. - */ - unsigned *UboInterfaceBlockIndex; - unsigned *SsboInterfaceBlockIndex; - - /** * Map of active uniform names to locations * * Maps any active uniform that is not an array element to a location. @@ -3905,7 +3916,10 @@ struct gl_extensions GLboolean EXT_transform_feedback; GLboolean EXT_timer_query; GLboolean EXT_vertex_array_bgra; + GLboolean OES_copy_image; + GLboolean OES_sample_variables; GLboolean OES_standard_derivatives; + GLboolean OES_texture_buffer; /* vendor extensions */ GLboolean AMD_performance_monitor; GLboolean AMD_pinned_memory; diff --git a/src/mesa/main/multisample.c b/src/mesa/main/multisample.c index 77773a20883..5453e38632e 100644 --- a/src/mesa/main/multisample.c +++ b/src/mesa/main/multisample.c @@ -127,7 +127,8 @@ _mesa_MinSampleShading(GLclampf value) { GET_CURRENT_CONTEXT(ctx); - if (!ctx->Extensions.ARB_sample_shading || !_mesa_is_desktop_gl(ctx)) { + if (!_mesa_has_ARB_sample_shading(ctx) && + !_mesa_has_OES_sample_shading(ctx)) { _mesa_error(ctx, GL_INVALID_OPERATION, "glMinSampleShading"); return; } diff --git a/src/mesa/main/program_resource.c b/src/mesa/main/program_resource.c index 0d9f8aecf08..f2a9f006dd8 100644 --- a/src/mesa/main/program_resource.c +++ b/src/mesa/main/program_resource.c @@ -39,6 +39,7 @@ supported_interface_enum(struct gl_context *ctx, GLenum iface) case GL_UNIFORM_BLOCK: case GL_PROGRAM_INPUT: case GL_PROGRAM_OUTPUT: + case GL_TRANSFORM_FEEDBACK_BUFFER: case GL_TRANSFORM_FEEDBACK_VARYING: case GL_ATOMIC_COUNTER_BUFFER: case GL_BUFFER_VARIABLE: @@ -105,7 +106,8 @@ _mesa_GetProgramInterfaceiv(GLuint program, GLenum programInterface, (*params)++; break; case GL_MAX_NAME_LENGTH: - if (programInterface == GL_ATOMIC_COUNTER_BUFFER) { + if (programInterface == GL_ATOMIC_COUNTER_BUFFER || + programInterface == GL_TRANSFORM_FEEDBACK_BUFFER) { _mesa_error(ctx, GL_INVALID_OPERATION, "glGetProgramInterfaceiv(%s pname %s)", _mesa_enum_to_string(programInterface), @@ -165,6 +167,16 @@ _mesa_GetProgramInterfaceiv(GLuint program, GLenum programInterface, } } break; + case GL_TRANSFORM_FEEDBACK_BUFFER: + for (i = 0, *params = 0; i < shProg->NumProgramResourceList; i++) { + if (shProg->ProgramResourceList[i].Type == programInterface) { + struct gl_transform_feedback_buffer *buffer = + (struct gl_transform_feedback_buffer *) + shProg->ProgramResourceList[i].Data; + *params = MAX2(*params, buffer->NumVaryings); + } + } + break; default: _mesa_error(ctx, GL_INVALID_OPERATION, "glGetProgramInterfaceiv(%s pname %s)", @@ -289,6 +301,7 @@ _mesa_GetProgramResourceIndex(GLuint program, GLenum programInterface, return _mesa_program_resource_index(shProg, res); case GL_ATOMIC_COUNTER_BUFFER: + case GL_TRANSFORM_FEEDBACK_BUFFER: default: _mesa_error(ctx, GL_INVALID_ENUM, "glGetProgramResourceIndex(%s)", _mesa_enum_to_string(programInterface)); @@ -318,6 +331,7 @@ _mesa_GetProgramResourceName(GLuint program, GLenum programInterface, return; if (programInterface == GL_ATOMIC_COUNTER_BUFFER || + programInterface == GL_TRANSFORM_FEEDBACK_BUFFER || !supported_interface_enum(ctx, programInterface)) { _mesa_error(ctx, GL_INVALID_ENUM, "glGetProgramResourceName(%s)", _mesa_enum_to_string(programInterface)); diff --git a/src/mesa/main/shader_query.cpp b/src/mesa/main/shader_query.cpp index 4967e4b1df1..993dc863220 100644 --- a/src/mesa/main/shader_query.cpp +++ b/src/mesa/main/shader_query.cpp @@ -60,7 +60,8 @@ DECL_RESOURCE_FUNC(VAR, gl_shader_variable); DECL_RESOURCE_FUNC(UBO, gl_uniform_block); DECL_RESOURCE_FUNC(UNI, gl_uniform_storage); DECL_RESOURCE_FUNC(ATC, gl_active_atomic_buffer); -DECL_RESOURCE_FUNC(XFB, gl_transform_feedback_varying_info); +DECL_RESOURCE_FUNC(XFV, gl_transform_feedback_varying_info); +DECL_RESOURCE_FUNC(XFB, gl_transform_feedback_buffer); DECL_RESOURCE_FUNC(SUB, gl_subroutine_function); void GLAPIENTRY @@ -433,7 +434,7 @@ _mesa_program_resource_name(struct gl_program_resource *res) case GL_SHADER_STORAGE_BLOCK: return RESOURCE_UBO(res)->Name; case GL_TRANSFORM_FEEDBACK_VARYING: - return RESOURCE_XFB(res)->Name; + return RESOURCE_XFV(res)->Name; case GL_PROGRAM_INPUT: var = RESOURCE_VAR(res); /* Special case gl_VertexIDMESA -> gl_VertexID. */ @@ -473,8 +474,8 @@ _mesa_program_resource_array_size(struct gl_program_resource *res) { switch (res->Type) { case GL_TRANSFORM_FEEDBACK_VARYING: - return RESOURCE_XFB(res)->Size > 1 ? - RESOURCE_XFB(res)->Size : 0; + return RESOURCE_XFV(res)->Size > 1 ? + RESOURCE_XFV(res)->Size : 0; case GL_PROGRAM_INPUT: case GL_PROGRAM_OUTPUT: return RESOURCE_VAR(res)->type->length; @@ -670,6 +671,7 @@ _mesa_program_resource_index(struct gl_shader_program *shProg, return RESOURCE_SUB(res)->index; case GL_UNIFORM_BLOCK: case GL_SHADER_STORAGE_BLOCK: + case GL_TRANSFORM_FEEDBACK_BUFFER: case GL_TRANSFORM_FEEDBACK_VARYING: default: return calc_resource_index(shProg, res); @@ -707,6 +709,7 @@ _mesa_program_resource_find_index(struct gl_shader_program *shProg, case GL_UNIFORM_BLOCK: case GL_ATOMIC_COUNTER_BUFFER: case GL_SHADER_STORAGE_BLOCK: + case GL_TRANSFORM_FEEDBACK_BUFFER: if (_mesa_program_resource_index(shProg, res) == index) return res; break; @@ -1009,7 +1012,8 @@ get_buffer_property(struct gl_shader_program *shProg, GET_CURRENT_CONTEXT(ctx); if (res->Type != GL_UNIFORM_BLOCK && res->Type != GL_ATOMIC_COUNTER_BUFFER && - res->Type != GL_SHADER_STORAGE_BLOCK) + res->Type != GL_SHADER_STORAGE_BLOCK && + res->Type != GL_TRANSFORM_FEEDBACK_BUFFER) goto invalid_operation; if (res->Type == GL_UNIFORM_BLOCK) { @@ -1110,6 +1114,30 @@ get_buffer_property(struct gl_shader_program *shProg, } return RESOURCE_ATC(res)->NumUniforms; } + } else if (res->Type == GL_TRANSFORM_FEEDBACK_BUFFER) { + switch (prop) { + case GL_BUFFER_BINDING: + *val = RESOURCE_XFB(res)->Binding; + return 1; + case GL_NUM_ACTIVE_VARIABLES: + *val = RESOURCE_XFB(res)->NumVaryings; + return 1; + case GL_ACTIVE_VARIABLES: + int i = 0; + for ( ; i < shProg->LinkedTransformFeedback.NumVarying; i++) { + unsigned index = + shProg->LinkedTransformFeedback.Varyings[i].BufferIndex; + struct gl_program_resource *buf_res = + _mesa_program_resource_find_index(shProg, + GL_TRANSFORM_FEEDBACK_BUFFER, + index); + assert(buf_res); + if (res == buf_res) { + *val++ = i; + } + } + return RESOURCE_XFB(res)->NumVaryings; + } } assert(!"support for property type not implemented"); @@ -1140,6 +1168,7 @@ _mesa_program_resource_prop(struct gl_shader_program *shProg, case GL_NAME_LENGTH: switch (res->Type) { case GL_ATOMIC_COUNTER_BUFFER: + case GL_TRANSFORM_FEEDBACK_BUFFER: goto invalid_operation; default: /* Resource name length + terminator. */ @@ -1157,7 +1186,7 @@ _mesa_program_resource_prop(struct gl_shader_program *shProg, *val = RESOURCE_VAR(res)->type->gl_type; return 1; case GL_TRANSFORM_FEEDBACK_VARYING: - *val = RESOURCE_XFB(res)->Type; + *val = RESOURCE_XFV(res)->Type; return 1; default: goto invalid_operation; @@ -1180,15 +1209,23 @@ _mesa_program_resource_prop(struct gl_shader_program *shProg, *val = MAX2(_mesa_program_resource_array_size(res), 1); return 1; case GL_TRANSFORM_FEEDBACK_VARYING: - *val = MAX2(RESOURCE_XFB(res)->Size, 1); + *val = MAX2(RESOURCE_XFV(res)->Size, 1); return 1; default: goto invalid_operation; } case GL_OFFSET: - VALIDATE_TYPE_2(GL_UNIFORM, GL_BUFFER_VARIABLE); - *val = RESOURCE_UNI(res)->offset; - return 1; + switch (res->Type) { + case GL_UNIFORM: + case GL_BUFFER_VARIABLE: + *val = RESOURCE_UNI(res)->offset; + return 1; + case GL_TRANSFORM_FEEDBACK_VARYING: + *val = RESOURCE_XFV(res)->Offset; + return 1; + default: + goto invalid_operation; + } case GL_BLOCK_INDEX: VALIDATE_TYPE_2(GL_UNIFORM, GL_BUFFER_VARIABLE); *val = RESOURCE_UNI(res)->block_index; @@ -1314,6 +1351,16 @@ _mesa_program_resource_prop(struct gl_shader_program *shProg, default: goto invalid_operation; } + + case GL_TRANSFORM_FEEDBACK_BUFFER_INDEX: + VALIDATE_TYPE(GL_TRANSFORM_FEEDBACK_VARYING); + *val = RESOURCE_XFV(res)->BufferIndex; + return 1; + case GL_TRANSFORM_FEEDBACK_BUFFER_STRIDE: + VALIDATE_TYPE(GL_TRANSFORM_FEEDBACK_BUFFER); + *val = RESOURCE_XFB(res)->Stride * 4; + return 1; + default: goto invalid_enum; } diff --git a/src/mesa/main/shaderapi.c b/src/mesa/main/shaderapi.c index 32fad56f651..ba2607221d9 100644 --- a/src/mesa/main/shaderapi.c +++ b/src/mesa/main/shaderapi.c @@ -2568,7 +2568,6 @@ _mesa_UniformSubroutinesuiv(GLenum shadertype, GLsizei count, memcpy(&uni->storage[0], &indices[i], sizeof(GLuint) * uni_count); - uni->initialized = true; _mesa_propagate_uniforms_to_driver_storage(uni, 0, uni_count); i += uni_count; } while(i < count); @@ -2742,7 +2741,7 @@ _mesa_shader_init_subroutine_defaults(struct gl_shader *sh) for (j = 0; j < uni_count; j++) memcpy(&uni->storage[j], &val, sizeof(int)); - uni->initialized = true; + _mesa_propagate_uniforms_to_driver_storage(uni, 0, uni_count); } } diff --git a/src/mesa/main/shaderimage.c b/src/mesa/main/shaderimage.c index fd5934f939f..90643c4ed6d 100644 --- a/src/mesa/main/shaderimage.c +++ b/src/mesa/main/shaderimage.c @@ -583,8 +583,13 @@ _mesa_BindImageTexture(GLuint unit, GLuint texture, GLint level, * * "An INVALID_OPERATION error is generated if texture is not the name * of an immutable texture object." + * + * However note that issue 7 of the GL_OES_texture_buffer spec + * recognizes that there is no way to create immutable buffer textures, + * so those are excluded from this requirement. */ - if (_mesa_is_gles(ctx) && !t->Immutable) { + if (_mesa_is_gles(ctx) && !t->Immutable && + t->Target != GL_TEXTURE_BUFFER) { _mesa_error(ctx, GL_INVALID_OPERATION, "glBindImageTexture(!immutable)"); return; diff --git a/src/mesa/main/state.c b/src/mesa/main/state.c index 917ae4da023..bf6035e0142 100644 --- a/src/mesa/main/state.c +++ b/src/mesa/main/state.c @@ -124,7 +124,8 @@ update_program(struct gl_context *ctx) * follows: * 1. OpenGL 2.0/ARB vertex/fragment shaders * 2. ARB/NV vertex/fragment programs - * 3. Programs derived from fixed-function state. + * 3. ATI fragment shader + * 4. Programs derived from fixed-function state. * * Note: it's possible for a vertex shader to get used with a fragment * program (and vice versa) here, but in practice that shouldn't ever @@ -152,6 +153,17 @@ update_program(struct gl_context *ctx) _mesa_reference_fragprog(ctx, &ctx->FragmentProgram._TexEnvProgram, NULL); } + else if (ctx->ATIFragmentShader._Enabled && + ctx->ATIFragmentShader.Current->Program) { + /* Use the enabled ATI fragment shader's associated program */ + _mesa_reference_shader_program(ctx, + &ctx->_Shader->_CurrentFragmentProgram, + NULL); + _mesa_reference_fragprog(ctx, &ctx->FragmentProgram._Current, + gl_fragment_program(ctx->ATIFragmentShader.Current->Program)); + _mesa_reference_fragprog(ctx, &ctx->FragmentProgram._TexEnvProgram, + NULL); + } else if (ctx->FragmentProgram._MaintainTexEnvProgram) { /* Use fragment program generated from fixed-function state */ struct gl_shader_program *f = _mesa_get_fixed_func_fragment_program(ctx); diff --git a/src/mesa/main/tests/dispatch_sanity.cpp b/src/mesa/main/tests/dispatch_sanity.cpp index 09b97c33074..9f278be47ca 100644 --- a/src/mesa/main/tests/dispatch_sanity.cpp +++ b/src/mesa/main/tests/dispatch_sanity.cpp @@ -2450,6 +2450,26 @@ const struct function gles3_functions_possible[] = { { "glGetSamplerParameterIivOES", 30, -1 }, { "glGetSamplerParameterIuivOES", 30, -1 }, + /* GL_OES_texture_buffer */ + { "glTexBufferOES", 31, -1 }, + { "glTexBufferRangeOES", 31, -1 }, + + /* GL_OES_sample_shading */ + { "glMinSampleShadingOES", 30, -1 }, + + /* GL_OES_copy_image */ + { "glCopyImageSubDataOES", 30, -1 }, + + /* GL_OES_draw_buffers_indexed */ + { "glBlendFunciOES", 30, -1 }, + { "glBlendFuncSeparateiOES", 30, -1 }, + { "glBlendEquationiOES", 30, -1 }, + { "glBlendEquationSeparateiOES", 30, -1 }, + { "glColorMaskiOES", 30, -1 }, + { "glEnableiOES", 30, -1 }, + { "glDisableiOES", 30, -1 }, + { "glIsEnablediOES", 30, -1 }, + { NULL, 0, -1 } }; diff --git a/src/mesa/main/teximage.c b/src/mesa/main/teximage.c index 616a92953e7..6ac6fb109d3 100644 --- a/src/mesa/main/teximage.c +++ b/src/mesa/main/teximage.c @@ -499,8 +499,8 @@ _mesa_max_texture_levels(struct gl_context *ctx, GLenum target) return ctx->Extensions.ARB_texture_cube_map_array ? ctx->Const.MaxCubeTextureLevels : 0; case GL_TEXTURE_BUFFER: - return ctx->API == API_OPENGL_CORE && - ctx->Extensions.ARB_texture_buffer_object ? 1 : 0; + return (_mesa_has_ARB_texture_buffer_object(ctx) || + _mesa_has_OES_texture_buffer(ctx)) ? 1 : 0; case GL_TEXTURE_2D_MULTISAMPLE: case GL_PROXY_TEXTURE_2D_MULTISAMPLE: case GL_TEXTURE_2D_MULTISAMPLE_ARRAY: @@ -3484,6 +3484,24 @@ formats_differ_in_component_sizes(mesa_format f1, mesa_format f2) return GL_FALSE; } +static bool +can_avoid_reallocation(struct gl_texture_image *texImage, GLenum internalFormat, + mesa_format texFormat, GLint x, GLint y, GLsizei width, + GLsizei height, GLint border) +{ + if (texImage->InternalFormat != internalFormat) + return false; + if (texImage->TexFormat != texFormat) + return false; + if (texImage->Border != border) + return false; + if (texImage->Width2 != width) + return false; + if (texImage->Height2 != height) + return false; + return true; +} + /** * Implement the glCopyTexImage1/2D() functions. */ @@ -3527,6 +3545,24 @@ copyteximage(struct gl_context *ctx, GLuint dims, texFormat = _mesa_choose_texture_format(ctx, texObj, target, level, internalFormat, GL_NONE, GL_NONE); + /* First check if reallocating the texture buffer can be avoided. + * Without the realloc the copy can be 20x faster. + */ + _mesa_lock_texture(ctx, texObj); + { + texImage = _mesa_select_tex_image(texObj, target, level); + if (texImage && can_avoid_reallocation(texImage, internalFormat, texFormat, + x, y, width, height, border)) { + _mesa_unlock_texture(ctx, texObj); + return _mesa_copy_texture_sub_image(ctx, dims, texObj, target, level, + 0, 0, 0, x, y, width, height, + "CopyTexImage"); + } + } + _mesa_unlock_texture(ctx, texObj); + _mesa_perf_debug(ctx, MESA_DEBUG_SEVERITY_LOW, "glCopyTexImage " + "can't avoid reallocating texture storage\n"); + rb = _mesa_get_read_renderbuffer_for_format(ctx, internalFormat); if (_mesa_is_gles3(ctx)) { @@ -4681,7 +4717,7 @@ _mesa_CompressedTextureSubImage3D(GLuint texture, GLint level, GLint xoffset, static mesa_format get_texbuffer_format(const struct gl_context *ctx, GLenum internalFormat) { - if (ctx->API != API_OPENGL_CORE) { + if (ctx->API == API_OPENGL_COMPAT) { switch (internalFormat) { case GL_ALPHA8: return MESA_FORMAT_A_UNORM8; @@ -4768,8 +4804,8 @@ get_texbuffer_format(const struct gl_context *ctx, GLenum internalFormat) } } - if (ctx->API == API_OPENGL_CORE && - ctx->Extensions.ARB_texture_buffer_object_rgb32) { + if (_mesa_has_ARB_texture_buffer_object_rgb32(ctx) || + _mesa_has_OES_texture_buffer(ctx)) { switch (internalFormat) { case GL_RGB32F: return MESA_FORMAT_RGB_FLOAT32; @@ -4786,6 +4822,8 @@ get_texbuffer_format(const struct gl_context *ctx, GLenum internalFormat) case GL_RGBA8: return MESA_FORMAT_R8G8B8A8_UNORM; case GL_RGBA16: + if (_mesa_is_gles(ctx)) + return MESA_FORMAT_NONE; return MESA_FORMAT_RGBA_UNORM16; case GL_RGBA16F_ARB: return MESA_FORMAT_RGBA_FLOAT16; @@ -4807,6 +4845,8 @@ get_texbuffer_format(const struct gl_context *ctx, GLenum internalFormat) case GL_RG8: return MESA_FORMAT_R8G8_UNORM; case GL_RG16: + if (_mesa_is_gles(ctx)) + return MESA_FORMAT_NONE; return MESA_FORMAT_R16G16_UNORM; case GL_RG16F: return MESA_FORMAT_RG_FLOAT16; @@ -4828,6 +4868,8 @@ get_texbuffer_format(const struct gl_context *ctx, GLenum internalFormat) case GL_R8: return MESA_FORMAT_R_UNORM8; case GL_R16: + if (_mesa_is_gles(ctx)) + return MESA_FORMAT_NONE; return MESA_FORMAT_R_UNORM16; case GL_R16F: return MESA_FORMAT_R_FLOAT16; @@ -4905,8 +4947,8 @@ _mesa_texture_buffer_range(struct gl_context *ctx, /* NOTE: ARB_texture_buffer_object has interactions with * the compatibility profile that are not implemented. */ - if (!(ctx->API == API_OPENGL_CORE && - ctx->Extensions.ARB_texture_buffer_object)) { + if (!_mesa_has_ARB_texture_buffer_object(ctx) && + !_mesa_has_OES_texture_buffer(ctx)) { _mesa_error(ctx, GL_INVALID_OPERATION, "%s(ARB_texture_buffer_object is not" " implemented for the compatibility profile)", caller); diff --git a/src/mesa/main/texobj.c b/src/mesa/main/texobj.c index d8407f04340..c9502bda236 100644 --- a/src/mesa/main/texobj.c +++ b/src/mesa/main/texobj.c @@ -204,8 +204,8 @@ _mesa_get_current_tex_object(struct gl_context *ctx, GLenum target) case GL_PROXY_TEXTURE_2D_ARRAY_EXT: return arrayTex ? ctx->Texture.ProxyTex[TEXTURE_2D_ARRAY_INDEX] : NULL; case GL_TEXTURE_BUFFER: - return ctx->API == API_OPENGL_CORE && - ctx->Extensions.ARB_texture_buffer_object ? + return (_mesa_has_ARB_texture_buffer_object(ctx) || + _mesa_has_OES_texture_buffer(ctx)) ? texUnit->CurrentTex[TEXTURE_BUFFER_INDEX] : NULL; case GL_TEXTURE_EXTERNAL_OES: return _mesa_is_gles(ctx) && ctx->Extensions.OES_EGL_image_external @@ -1574,8 +1574,8 @@ _mesa_tex_target_to_index(const struct gl_context *ctx, GLenum target) || _mesa_is_gles3(ctx) ? TEXTURE_2D_ARRAY_INDEX : -1; case GL_TEXTURE_BUFFER: - return ctx->API == API_OPENGL_CORE && - ctx->Extensions.ARB_texture_buffer_object ? + return (_mesa_has_ARB_texture_buffer_object(ctx) || + _mesa_has_OES_texture_buffer(ctx)) ? TEXTURE_BUFFER_INDEX : -1; case GL_TEXTURE_EXTERNAL_OES: return _mesa_is_gles(ctx) && ctx->Extensions.OES_EGL_image_external diff --git a/src/mesa/main/texparam.c b/src/mesa/main/texparam.c index 9350ca5c035..ba83f8fda9a 100644 --- a/src/mesa/main/texparam.c +++ b/src/mesa/main/texparam.c @@ -1223,6 +1223,26 @@ _mesa_legal_get_tex_level_parameter_target(struct gl_context *ctx, GLenum target case GL_TEXTURE_2D_MULTISAMPLE: case GL_TEXTURE_2D_MULTISAMPLE_ARRAY: return ctx->Extensions.ARB_texture_multisample; + 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. + * + * From the ARB_texture_buffer_object spec: + * "(7) Do buffer textures support texture parameters (TexParameter) or + * queries (GetTexParameter, GetTexLevelParameter, GetTexImage)? + * + * RESOLVED: No. [...] Note that the spec edits above don't add + * explicit error language for any of these cases. That is because + * each of the functions enumerate the set of valid <target> + * parameters. Not editing the spec to allow TEXTURE_BUFFER_ARB in + * these cases means that target is not legal, and an INVALID_ENUM + * error should be generated." + * + * From the OpenGL 3.1 spec: + * "target may also be TEXTURE_BUFFER, indicating the texture buffer." + */ + return (ctx->API == API_OPENGL_CORE && ctx->Version >= 31) || + _mesa_has_OES_texture_buffer(ctx); } if (!_mesa_is_desktop_gl(ctx)) @@ -1247,25 +1267,6 @@ _mesa_legal_get_tex_level_parameter_target(struct gl_context *ctx, GLenum target case GL_PROXY_TEXTURE_1D_ARRAY_EXT: case GL_PROXY_TEXTURE_2D_ARRAY_EXT: 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. - * - * From the ARB_texture_buffer_object spec: - * "(7) Do buffer textures support texture parameters (TexParameter) or - * queries (GetTexParameter, GetTexLevelParameter, GetTexImage)? - * - * RESOLVED: No. [...] Note that the spec edits above don't add - * explicit error language for any of these cases. That is because - * each of the functions enumerate the set of valid <target> - * parameters. Not editing the spec to allow TEXTURE_BUFFER_ARB in - * these cases means that target is not legal, and an INVALID_ENUM - * error should be generated." - * - * From the OpenGL 3.1 spec: - * "target may also be TEXTURE_BUFFER, indicating the texture buffer." - */ - return ctx->API == API_OPENGL_CORE && ctx->Version >= 31; case GL_PROXY_TEXTURE_2D_MULTISAMPLE: case GL_PROXY_TEXTURE_2D_MULTISAMPLE_ARRAY: return ctx->Extensions.ARB_texture_multisample; @@ -1447,6 +1448,29 @@ get_tex_level_parameter_image(struct gl_context *ctx, *params = img->FixedSampleLocations; break; + /* There is never a buffer data store here, but these pnames still have + * to work. + */ + + /* GL_ARB_texture_buffer_object */ + case GL_TEXTURE_BUFFER_DATA_STORE_BINDING: + if (!ctx->Extensions.ARB_texture_buffer_object) + goto invalid_pname; + *params = 0; + break; + + /* GL_ARB_texture_buffer_range */ + case GL_TEXTURE_BUFFER_OFFSET: + if (!ctx->Extensions.ARB_texture_buffer_range) + goto invalid_pname; + *params = 0; + break; + case GL_TEXTURE_BUFFER_SIZE: + if (!ctx->Extensions.ARB_texture_buffer_range) + goto invalid_pname; + *params = 0; + break; + default: goto invalid_pname; } @@ -1468,13 +1492,24 @@ get_tex_level_parameter_buffer(struct gl_context *ctx, { const struct gl_buffer_object *bo = texObj->BufferObject; mesa_format texFormat = texObj->_BufferObjectFormat; + int bytes = MAX2(1, _mesa_get_format_bytes(texFormat)); GLenum internalFormat = texObj->BufferObjectFormat; GLenum baseFormat = _mesa_get_format_base_format(texFormat); const char *suffix = dsa ? "ture" : ""; if (!bo) { /* undefined texture buffer object */ - *params = pname == GL_TEXTURE_COMPONENTS ? 1 : 0; + switch (pname) { + case GL_TEXTURE_FIXED_SAMPLE_LOCATIONS: + *params = GL_TRUE; + break; + case GL_TEXTURE_INTERNAL_FORMAT: + *params = internalFormat; + break; + default: + *params = 0; + break; + } return; } @@ -1483,10 +1518,13 @@ get_tex_level_parameter_buffer(struct gl_context *ctx, *params = bo->Name; break; case GL_TEXTURE_WIDTH: - *params = bo->Size; + *params = ((texObj->BufferSize == -1) ? bo->Size : texObj->BufferSize) + / bytes; break; case GL_TEXTURE_HEIGHT: case GL_TEXTURE_DEPTH: + *params = 1; + break; case GL_TEXTURE_BORDER: case GL_TEXTURE_SHARED_SIZE: case GL_TEXTURE_COMPRESSED: @@ -1536,6 +1574,19 @@ get_tex_level_parameter_buffer(struct gl_context *ctx, *params = (texObj->BufferSize == -1) ? bo->Size : texObj->BufferSize; break; + /* GL_ARB_texture_multisample */ + case GL_TEXTURE_SAMPLES: + if (!ctx->Extensions.ARB_texture_multisample) + goto invalid_pname; + *params = 0; + break; + + case GL_TEXTURE_FIXED_SAMPLE_LOCATIONS: + if (!ctx->Extensions.ARB_texture_multisample) + goto invalid_pname; + *params = GL_TRUE; + break; + /* GL_ARB_texture_compression */ case GL_TEXTURE_COMPRESSED_IMAGE_SIZE: /* Always illegal for GL_TEXTURE_BUFFER */ diff --git a/src/mesa/main/textureview.c b/src/mesa/main/textureview.c index 419fbebf2f0..4b3b3245c2e 100644 --- a/src/mesa/main/textureview.c +++ b/src/mesa/main/textureview.c @@ -82,6 +82,39 @@ | | COMPRESSED_RGB_BPTC_UNSIGNED_FLOAT | --------------------------------------------------------------------------- */ + +#define VIEW_CLASS_GLES(x) (GL_VIEW_CLASS_BPTC_FLOAT + 1 + x) +#define VIEW_CLASS_EAC_R11 VIEW_CLASS_GLES(0) +#define VIEW_CLASS_EAC_RG11 VIEW_CLASS_GLES(1) +#define VIEW_CLASS_ETC2_RGB VIEW_CLASS_GLES(2) +#define VIEW_CLASS_ETC2_RGBA VIEW_CLASS_GLES(3) +#define VIEW_CLASS_ETC2_EAC_RGBA VIEW_CLASS_GLES(4) +#define VIEW_CLASS_ASTC_4x4_RGBA VIEW_CLASS_GLES(5) +#define VIEW_CLASS_ASTC_5x4_RGBA VIEW_CLASS_GLES(6) +#define VIEW_CLASS_ASTC_5x5_RGBA VIEW_CLASS_GLES(7) +#define VIEW_CLASS_ASTC_6x5_RGBA VIEW_CLASS_GLES(8) +#define VIEW_CLASS_ASTC_6x6_RGBA VIEW_CLASS_GLES(9) +#define VIEW_CLASS_ASTC_8x5_RGBA VIEW_CLASS_GLES(10) +#define VIEW_CLASS_ASTC_8x6_RGBA VIEW_CLASS_GLES(11) +#define VIEW_CLASS_ASTC_8x8_RGBA VIEW_CLASS_GLES(12) +#define VIEW_CLASS_ASTC_10x5_RGBA VIEW_CLASS_GLES(13) +#define VIEW_CLASS_ASTC_10x6_RGBA VIEW_CLASS_GLES(14) +#define VIEW_CLASS_ASTC_10x8_RGBA VIEW_CLASS_GLES(15) +#define VIEW_CLASS_ASTC_10x10_RGBA VIEW_CLASS_GLES(16) +#define VIEW_CLASS_ASTC_12x10_RGBA VIEW_CLASS_GLES(17) +#define VIEW_CLASS_ASTC_12x12_RGBA VIEW_CLASS_GLES(18) +#define VIEW_CLASS_ASTC_3x3x3_RGBA VIEW_CLASS_GLES(19) +#define VIEW_CLASS_ASTC_4x3x3_RGBA VIEW_CLASS_GLES(20) +#define VIEW_CLASS_ASTC_4x4x3_RGBA VIEW_CLASS_GLES(21) +#define VIEW_CLASS_ASTC_4x4x4_RGBA VIEW_CLASS_GLES(22) +#define VIEW_CLASS_ASTC_5x4x4_RGBA VIEW_CLASS_GLES(23) +#define VIEW_CLASS_ASTC_5x5x4_RGBA VIEW_CLASS_GLES(24) +#define VIEW_CLASS_ASTC_5x5x5_RGBA VIEW_CLASS_GLES(25) +#define VIEW_CLASS_ASTC_6x5x5_RGBA VIEW_CLASS_GLES(26) +#define VIEW_CLASS_ASTC_6x6x5_RGBA VIEW_CLASS_GLES(27) +#define VIEW_CLASS_ASTC_6x6x6_RGBA VIEW_CLASS_GLES(28) + + struct internal_format_class_info { GLenum view_class; GLenum internal_format; @@ -162,6 +195,41 @@ static const struct internal_format_class_info s3tc_compatible_internal_formats[ {GL_VIEW_CLASS_S3TC_DXT5_RGBA, GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT5_EXT}, }; +static const struct internal_format_class_info gles_etc2_compatible_internal_formats[] = { + {VIEW_CLASS_EAC_R11, GL_COMPRESSED_R11_EAC}, + {VIEW_CLASS_EAC_R11, GL_COMPRESSED_SIGNED_R11_EAC}, + {VIEW_CLASS_EAC_RG11, GL_COMPRESSED_RG11_EAC}, + {VIEW_CLASS_EAC_RG11, GL_COMPRESSED_SIGNED_RG11_EAC}, + {VIEW_CLASS_ETC2_RGB, GL_COMPRESSED_RGB8_ETC2}, + {VIEW_CLASS_ETC2_RGB, GL_COMPRESSED_SRGB8_ETC2}, + {VIEW_CLASS_ETC2_RGBA, GL_COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_ETC2}, + {VIEW_CLASS_ETC2_RGBA, GL_COMPRESSED_SRGB8_PUNCHTHROUGH_ALPHA1_ETC2}, + {VIEW_CLASS_ETC2_EAC_RGBA, GL_COMPRESSED_RGBA8_ETC2_EAC}, + {VIEW_CLASS_ETC2_EAC_RGBA, GL_COMPRESSED_SRGB8_ALPHA8_ETC2_EAC}, +}; + +static const struct internal_format_class_info gles_astc_compatible_internal_formats[] = { +#define ASTC_FMT(size) \ + {VIEW_CLASS_ASTC_##size## _RGBA, GL_COMPRESSED_RGBA_ASTC_##size##_KHR}, \ + {VIEW_CLASS_ASTC_##size##_RGBA, GL_COMPRESSED_SRGB8_ALPHA8_ASTC_##size##_KHR} + + ASTC_FMT(4x4), + ASTC_FMT(5x4), + ASTC_FMT(5x5), + ASTC_FMT(6x5), + ASTC_FMT(6x6), + ASTC_FMT(8x5), + ASTC_FMT(8x6), + ASTC_FMT(8x8), + ASTC_FMT(10x5), + ASTC_FMT(10x6), + ASTC_FMT(10x8), + ASTC_FMT(10x10), + ASTC_FMT(12x10), + ASTC_FMT(12x12), +#undef ASTC_FMT +}; + GLenum _mesa_texture_view_lookup_view_class(const struct gl_context *ctx, GLenum internalformat) { @@ -180,6 +248,24 @@ _mesa_texture_view_lookup_view_class(const struct gl_context *ctx, GLenum intern return s3tc_compatible_internal_formats[i].view_class; } } + + if (_mesa_is_gles3(ctx)) { + for (i = 0; i < ARRAY_SIZE(gles_etc2_compatible_internal_formats); i++) { + if (gles_etc2_compatible_internal_formats[i].internal_format + == internalformat) + return gles_etc2_compatible_internal_formats[i].view_class; + } + + if (ctx->Extensions.KHR_texture_compression_astc_ldr) { + for (i = 0; i < ARRAY_SIZE(gles_astc_compatible_internal_formats); i++) { + if (gles_astc_compatible_internal_formats[i].internal_format + == internalformat) + return gles_astc_compatible_internal_formats[i].view_class; + } + } + + /* FINISHME: Add 3D OES formats when supported */ + } return GL_FALSE; } diff --git a/src/mesa/main/transformfeedback.c b/src/mesa/main/transformfeedback.c index f73a89f6c0f..c92f0ccd5a5 100644 --- a/src/mesa/main/transformfeedback.c +++ b/src/mesa/main/transformfeedback.c @@ -347,23 +347,25 @@ compute_transform_feedback_buffer_sizes( * enabled transform feedback buffers without overflowing any of them. */ unsigned -_mesa_compute_max_transform_feedback_vertices( +_mesa_compute_max_transform_feedback_vertices(struct gl_context *ctx, const struct gl_transform_feedback_object *obj, const struct gl_transform_feedback_info *info) { unsigned max_index = 0xffffffff; unsigned i; - for (i = 0; i < info->NumBuffers; ++i) { - unsigned stride = info->BufferStride[i]; - unsigned max_for_this_buffer; + for (i = 0; i < ctx->Const.MaxTransformFeedbackBuffers; i++) { + if ((info->ActiveBuffers >> i) & 1) { + unsigned stride = info->Buffers[i].Stride; + unsigned max_for_this_buffer; - /* Skip any inactive buffers, which have a stride of 0. */ - if (stride == 0) - continue; + /* Skip any inactive buffers, which have a stride of 0. */ + if (stride == 0) + continue; - max_for_this_buffer = obj->Size[i] / (4 * stride); - max_index = MIN2(max_index, max_for_this_buffer); + max_for_this_buffer = obj->Size[i] / (4 * stride); + max_index = MIN2(max_index, max_for_this_buffer); + } } return max_index; @@ -445,12 +447,14 @@ _mesa_BeginTransformFeedback(GLenum mode) return; } - for (i = 0; i < info->NumBuffers; ++i) { - if (obj->BufferNames[i] == 0) { - _mesa_error(ctx, GL_INVALID_OPERATION, - "glBeginTransformFeedback(binding point %d does not have " - "a buffer object bound)", i); - return; + for (i = 0; i < ctx->Const.MaxTransformFeedbackBuffers; i++) { + if ((info->ActiveBuffers >> i) & 1) { + if (obj->BufferNames[i] == 0) { + _mesa_error(ctx, GL_INVALID_OPERATION, + "glBeginTransformFeedback(binding point %d does not " + "have a buffer object bound)", i); + return; + } } } @@ -470,7 +474,7 @@ _mesa_BeginTransformFeedback(GLenum mode) * feedback. */ unsigned max_vertices - = _mesa_compute_max_transform_feedback_vertices(obj, info); + = _mesa_compute_max_transform_feedback_vertices(ctx, obj, info); obj->GlesRemainingPrims = max_vertices / vertices_per_prim; } diff --git a/src/mesa/main/transformfeedback.h b/src/mesa/main/transformfeedback.h index eb274ad6540..c83f917a532 100644 --- a/src/mesa/main/transformfeedback.h +++ b/src/mesa/main/transformfeedback.h @@ -50,7 +50,7 @@ extern void _mesa_init_transform_feedback_functions(struct dd_function_table *driver); extern unsigned -_mesa_compute_max_transform_feedback_vertices( +_mesa_compute_max_transform_feedback_vertices( struct gl_context *ctx, const struct gl_transform_feedback_object *obj, const struct gl_transform_feedback_info *info); diff --git a/src/mesa/main/uniform_query.cpp b/src/mesa/main/uniform_query.cpp index 2ced201ebca..ab5c3cd9249 100644 --- a/src/mesa/main/uniform_query.cpp +++ b/src/mesa/main/uniform_query.cpp @@ -815,8 +815,6 @@ _mesa_uniform(struct gl_context *ctx, struct gl_shader_program *shProg, } } - uni->initialized = true; - _mesa_propagate_uniforms_to_driver_storage(uni, offset, count); /* If the uniform is a sampler, do the extra magic necessary to propagate @@ -1030,8 +1028,6 @@ _mesa_uniform_matrix(struct gl_context *ctx, struct gl_shader_program *shProg, } } - uni->initialized = true; - _mesa_propagate_uniforms_to_driver_storage(uni, offset, count); } diff --git a/src/mesa/main/uniforms.c b/src/mesa/main/uniforms.c index b1968b3f795..7dcbdccf442 100644 --- a/src/mesa/main/uniforms.c +++ b/src/mesa/main/uniforms.c @@ -1018,26 +1018,11 @@ _mesa_UniformBlockBinding(GLuint program, if (shProg->UniformBlocks[uniformBlockIndex]->Binding != uniformBlockBinding) { - int i; FLUSH_VERTICES(ctx, 0); ctx->NewDriverState |= ctx->DriverFlags.NewUniformBuffer; - const int interface_block_index = - shProg->UboInterfaceBlockIndex[uniformBlockIndex]; - - shProg->BufferInterfaceBlocks[interface_block_index].Binding = - uniformBlockBinding; - - for (i = 0; i < MESA_SHADER_STAGES; i++) { - int stage_index = - shProg->InterfaceBlockStageIndex[i][interface_block_index]; - - if (stage_index != -1) { - struct gl_shader *sh = shProg->_LinkedShaders[i]; - sh->BufferInterfaceBlocks[stage_index].Binding = uniformBlockBinding; - } - } + shProg->UniformBlocks[uniformBlockIndex]->Binding = uniformBlockBinding; } } @@ -1076,26 +1061,12 @@ _mesa_ShaderStorageBlockBinding(GLuint program, if (shProg->ShaderStorageBlocks[shaderStorageBlockIndex]->Binding != shaderStorageBlockBinding) { - int i; FLUSH_VERTICES(ctx, 0); ctx->NewDriverState |= ctx->DriverFlags.NewShaderStorageBuffer; - const int interface_block_index = - shProg->SsboInterfaceBlockIndex[shaderStorageBlockIndex]; - - shProg->BufferInterfaceBlocks[interface_block_index].Binding = + shProg->ShaderStorageBlocks[shaderStorageBlockIndex]->Binding = shaderStorageBlockBinding; - - for (i = 0; i < MESA_SHADER_STAGES; i++) { - int stage_index = - shProg->InterfaceBlockStageIndex[i][interface_block_index]; - - if (stage_index != -1) { - struct gl_shader *sh = shProg->_LinkedShaders[i]; - sh->BufferInterfaceBlocks[stage_index].Binding = shaderStorageBlockBinding; - } - } } } diff --git a/src/mesa/program/ir_to_mesa.cpp b/src/mesa/program/ir_to_mesa.cpp index 1d9047ee6fd..35a68562001 100644 --- a/src/mesa/program/ir_to_mesa.cpp +++ b/src/mesa/program/ir_to_mesa.cpp @@ -2976,7 +2976,7 @@ _mesa_ir_link_shader(struct gl_context *ctx, struct gl_shader_program *prog) _mesa_reference_program(ctx, &linked_prog, NULL); } - build_program_resource_list(prog); + build_program_resource_list(ctx, prog); return prog->LinkStatus; } diff --git a/src/mesa/program/prog_to_nir.c b/src/mesa/program/prog_to_nir.c index 16b79c94c84..a6119ae4e7c 100644 --- a/src/mesa/program/prog_to_nir.c +++ b/src/mesa/program/prog_to_nir.c @@ -59,7 +59,6 @@ struct ptn_compile { #define SWIZ(X, Y, Z, W) \ (unsigned[4]){ SWIZZLE_##X, SWIZZLE_##Y, SWIZZLE_##Z, SWIZZLE_##W } -#define ptn_swizzle(b, src, x, y, z, w) nir_swizzle(b, src, SWIZ(x, y, z, w), 4, true) #define ptn_channel(b, src, ch) nir_swizzle(b, src, SWIZ(ch, ch, ch, ch), 1, true) static nir_ssa_def * @@ -491,11 +490,11 @@ ptn_xpd(nir_builder *b, nir_alu_dest dest, nir_ssa_def **src) ptn_move_dest_masked(b, dest, nir_fsub(b, nir_fmul(b, - ptn_swizzle(b, src[0], Y, Z, X, X), - ptn_swizzle(b, src[1], Z, X, Y, X)), + nir_swizzle(b, src[0], SWIZ(Y, Z, X, W), 3, true), + nir_swizzle(b, src[1], SWIZ(Z, X, Y, W), 3, true)), nir_fmul(b, - ptn_swizzle(b, src[1], Y, Z, X, X), - ptn_swizzle(b, src[0], Z, X, Y, X))), + nir_swizzle(b, src[1], SWIZ(Y, Z, X, W), 3, true), + nir_swizzle(b, src[0], SWIZ(Z, X, Y, W), 3, true))), WRITEMASK_XYZ); ptn_move_dest_masked(b, dest, nir_imm_float(b, 1.0), WRITEMASK_W); } @@ -545,7 +544,7 @@ ptn_lrp(nir_builder *b, nir_alu_dest dest, nir_ssa_def **src) } static void -ptn_kil(nir_builder *b, nir_alu_dest dest, nir_ssa_def **src) +ptn_kil(nir_builder *b, nir_ssa_def **src) { nir_ssa_def *cmp = b->shader->options->native_integers ? nir_bany_inequal4(b, nir_flt(b, src[0], nir_imm_float(b, 0.0)), nir_imm_int(b, 0)) : @@ -642,7 +641,8 @@ ptn_tex(nir_builder *b, nir_alu_dest dest, nir_ssa_def **src, unsigned src_number = 0; instr->src[src_number].src = - nir_src_for_ssa(ptn_swizzle(b, src[0], X, Y, Z, W)); + nir_src_for_ssa(nir_swizzle(b, src[0], SWIZ(X, Y, Z, W), + instr->coord_components, true)); instr->src[src_number].src_type = nir_tex_src_coord; src_number++; @@ -830,7 +830,7 @@ ptn_emit_instruction(struct ptn_compile *c, struct prog_instruction *prog_inst) break; case OPCODE_KIL: - ptn_kil(b, dest, src); + ptn_kil(b, src); break; case OPCODE_CMP: diff --git a/src/mesa/program/program.h b/src/mesa/program/program.h index 24e05974dc3..09e69280d46 100644 --- a/src/mesa/program/program.h +++ b/src/mesa/program/program.h @@ -172,6 +172,8 @@ _mesa_program_enum_to_shader_stage(GLenum v) return MESA_SHADER_VERTEX; case GL_FRAGMENT_PROGRAM_ARB: return MESA_SHADER_FRAGMENT; + case GL_FRAGMENT_SHADER_ATI: + return MESA_SHADER_FRAGMENT; case GL_GEOMETRY_PROGRAM_NV: return MESA_SHADER_GEOMETRY; case GL_TESS_CONTROL_PROGRAM_NV: diff --git a/src/mesa/state_tracker/st_atifs_to_tgsi.c b/src/mesa/state_tracker/st_atifs_to_tgsi.c new file mode 100644 index 00000000000..66f442aee5a --- /dev/null +++ b/src/mesa/state_tracker/st_atifs_to_tgsi.c @@ -0,0 +1,845 @@ +/* + * Copyright (C) 2016 Miklós Máté + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + */ + +#include "main/mtypes.h" +#include "main/atifragshader.h" +#include "main/errors.h" +#include "program/prog_parameter.h" + +#include "tgsi/tgsi_ureg.h" +#include "tgsi/tgsi_scan.h" +#include "tgsi/tgsi_transform.h" + +#include "st_program.h" +#include "st_atifs_to_tgsi.h" + +/** + * Intermediate state used during shader translation. + */ +struct st_translate { + struct ureg_program *ureg; + struct ati_fragment_shader *atifs; + + struct ureg_dst temps[MAX_PROGRAM_TEMPS]; + struct ureg_src *constants; + struct ureg_dst outputs[PIPE_MAX_SHADER_OUTPUTS]; + struct ureg_src inputs[PIPE_MAX_SHADER_INPUTS]; + struct ureg_src samplers[PIPE_MAX_SAMPLERS]; + + const GLuint *inputMapping; + const GLuint *outputMapping; + + unsigned current_pass; + + bool regs_written[MAX_NUM_PASSES_ATI][MAX_NUM_FRAGMENT_REGISTERS_ATI]; + + boolean error; +}; + +struct instruction_desc { + unsigned TGSI_opcode; + const char *name; + unsigned char arg_count; +}; + +static const struct instruction_desc inst_desc[] = { + {TGSI_OPCODE_MOV, "MOV", 1}, + {TGSI_OPCODE_NOP, "UND", 0}, /* unused */ + {TGSI_OPCODE_ADD, "ADD", 2}, + {TGSI_OPCODE_MUL, "MUL", 2}, + {TGSI_OPCODE_SUB, "SUB", 2}, + {TGSI_OPCODE_DP3, "DOT3", 2}, + {TGSI_OPCODE_DP4, "DOT4", 2}, + {TGSI_OPCODE_MAD, "MAD", 3}, + {TGSI_OPCODE_LRP, "LERP", 3}, + {TGSI_OPCODE_NOP, "CND", 3}, + {TGSI_OPCODE_NOP, "CND0", 3}, + {TGSI_OPCODE_NOP, "DOT2_ADD", 3} +}; + +static struct ureg_dst +get_temp(struct st_translate *t, unsigned index) +{ + if (ureg_dst_is_undef(t->temps[index])) + t->temps[index] = ureg_DECL_temporary(t->ureg); + return t->temps[index]; +} + +static struct ureg_src +apply_swizzle(struct st_translate *t, + struct ureg_src src, GLuint swizzle) +{ + if (swizzle == GL_SWIZZLE_STR_ATI) { + return src; + } else if (swizzle == GL_SWIZZLE_STQ_ATI) { + return ureg_swizzle(src, + TGSI_SWIZZLE_X, + TGSI_SWIZZLE_Y, + TGSI_SWIZZLE_W, + TGSI_SWIZZLE_Z); + } else { + struct ureg_dst tmp[2]; + struct ureg_src imm[3]; + + tmp[0] = get_temp(t, MAX_NUM_FRAGMENT_REGISTERS_ATI); + tmp[1] = get_temp(t, MAX_NUM_FRAGMENT_REGISTERS_ATI + 1); + imm[0] = src; + imm[1] = ureg_imm4f(t->ureg, 1.0f, 1.0f, 0.0f, 0.0f); + imm[2] = ureg_imm4f(t->ureg, 0.0f, 0.0f, 1.0f, 1.0f); + ureg_insn(t->ureg, TGSI_OPCODE_MAD, &tmp[0], 1, imm, 3); + + if (swizzle == GL_SWIZZLE_STR_DR_ATI) { + imm[0] = ureg_scalar(src, TGSI_SWIZZLE_Z); + } else { + imm[0] = ureg_scalar(src, TGSI_SWIZZLE_W); + } + ureg_insn(t->ureg, TGSI_OPCODE_RCP, &tmp[1], 1, &imm[0], 1); + + imm[0] = ureg_src(tmp[0]); + imm[1] = ureg_src(tmp[1]); + ureg_insn(t->ureg, TGSI_OPCODE_MUL, &tmp[0], 1, imm, 2); + + return ureg_src(tmp[0]); + } +} + +static struct ureg_src +get_source(struct st_translate *t, GLuint src_type) +{ + if (src_type >= GL_REG_0_ATI && src_type <= GL_REG_5_ATI) { + if (t->regs_written[t->current_pass][src_type - GL_REG_0_ATI]) { + return ureg_src(get_temp(t, src_type - GL_REG_0_ATI)); + } else { + return ureg_imm1f(t->ureg, 0.0f); + } + } else if (src_type >= GL_CON_0_ATI && src_type <= GL_CON_7_ATI) { + return t->constants[src_type - GL_CON_0_ATI]; + } else if (src_type == GL_ZERO) { + return ureg_imm1f(t->ureg, 0.0f); + } else if (src_type == GL_ONE) { + return ureg_imm1f(t->ureg, 1.0f); + } else if (src_type == GL_PRIMARY_COLOR_ARB) { + return t->inputs[t->inputMapping[VARYING_SLOT_COL0]]; + } else if (src_type == GL_SECONDARY_INTERPOLATOR_ATI) { + return t->inputs[t->inputMapping[VARYING_SLOT_COL1]]; + } else { + /* frontend prevents this */ + unreachable("unknown source"); + } +} + +static struct ureg_src +prepare_argument(struct st_translate *t, const unsigned argId, + const struct atifragshader_src_register *srcReg) +{ + struct ureg_src src = get_source(t, srcReg->Index); + struct ureg_dst arg = get_temp(t, MAX_NUM_FRAGMENT_REGISTERS_ATI + argId); + + switch (srcReg->argRep) { + case GL_NONE: + break; + case GL_RED: + src = ureg_scalar(src, TGSI_SWIZZLE_X); + break; + case GL_GREEN: + src = ureg_scalar(src, TGSI_SWIZZLE_Y); + break; + case GL_BLUE: + src = ureg_scalar(src, TGSI_SWIZZLE_Z); + break; + case GL_ALPHA: + src = ureg_scalar(src, TGSI_SWIZZLE_W); + break; + } + ureg_insn(t->ureg, TGSI_OPCODE_MOV, &arg, 1, &src, 1); + + if (srcReg->argMod & GL_COMP_BIT_ATI) { + struct ureg_src modsrc[2]; + modsrc[0] = ureg_imm1f(t->ureg, 1.0f); + modsrc[1] = ureg_src(arg); + + ureg_insn(t->ureg, TGSI_OPCODE_SUB, &arg, 1, modsrc, 2); + } + if (srcReg->argMod & GL_BIAS_BIT_ATI) { + struct ureg_src modsrc[2]; + modsrc[0] = ureg_src(arg); + modsrc[1] = ureg_imm1f(t->ureg, 0.5f); + + ureg_insn(t->ureg, TGSI_OPCODE_SUB, &arg, 1, modsrc, 2); + } + if (srcReg->argMod & GL_2X_BIT_ATI) { + struct ureg_src modsrc[2]; + modsrc[0] = ureg_src(arg); + modsrc[1] = ureg_src(arg); + + ureg_insn(t->ureg, TGSI_OPCODE_ADD, &arg, 1, modsrc, 2); + } + if (srcReg->argMod & GL_NEGATE_BIT_ATI) { + struct ureg_src modsrc[2]; + modsrc[0] = ureg_src(arg); + modsrc[1] = ureg_imm1f(t->ureg, -1.0f); + + ureg_insn(t->ureg, TGSI_OPCODE_MUL, &arg, 1, modsrc, 2); + } + return ureg_src(arg); +} + +/* These instructions need special treatment */ +static void +emit_special_inst(struct st_translate *t, const struct instruction_desc *desc, + struct ureg_dst *dst, struct ureg_src *args, unsigned argcount) +{ + struct ureg_dst tmp[1]; + struct ureg_src src[3]; + + if (!strcmp(desc->name, "CND")) { + tmp[0] = get_temp(t, MAX_NUM_FRAGMENT_REGISTERS_ATI + 2); /* re-purpose a3 */ + src[0] = ureg_imm1f(t->ureg, 0.5f); + src[1] = args[2]; + ureg_insn(t->ureg, TGSI_OPCODE_SUB, tmp, 1, src, 2); + src[0] = ureg_src(tmp[0]); + src[1] = args[0]; + src[2] = args[1]; + ureg_insn(t->ureg, TGSI_OPCODE_CMP, dst, 1, src, 3); + } else if (!strcmp(desc->name, "CND0")) { + src[0] = args[2]; + src[1] = args[1]; + src[2] = args[0]; + ureg_insn(t->ureg, TGSI_OPCODE_CMP, dst, 1, src, 3); + } else if (!strcmp(desc->name, "DOT2_ADD")) { + /* note: DP2A is not implemented in most pipe drivers */ + tmp[0] = get_temp(t, MAX_NUM_FRAGMENT_REGISTERS_ATI); /* re-purpose a1 */ + src[0] = args[0]; + src[1] = args[1]; + ureg_insn(t->ureg, TGSI_OPCODE_DP2, tmp, 1, src, 2); + src[0] = ureg_src(tmp[0]); + src[1] = ureg_scalar(args[2], TGSI_SWIZZLE_Z); + ureg_insn(t->ureg, TGSI_OPCODE_ADD, dst, 1, src, 2); + } +} + +static void +emit_arith_inst(struct st_translate *t, + const struct instruction_desc *desc, + struct ureg_dst *dst, struct ureg_src *args, unsigned argcount) +{ + if (desc->TGSI_opcode == TGSI_OPCODE_NOP) { + return emit_special_inst(t, desc, dst, args, argcount); + } + + ureg_insn(t->ureg, desc->TGSI_opcode, dst, 1, args, argcount); +} + +static void +emit_dstmod(struct st_translate *t, + struct ureg_dst dst, GLuint dstMod) +{ + float imm; + struct ureg_src src[3]; + GLuint scale = dstMod & ~GL_SATURATE_BIT_ATI; + + if (dstMod == GL_NONE) { + return; + } + + switch (scale) { + case GL_2X_BIT_ATI: + imm = 2.0f; + break; + case GL_4X_BIT_ATI: + imm = 4.0f; + break; + case GL_8X_BIT_ATI: + imm = 8.0f; + break; + case GL_HALF_BIT_ATI: + imm = 0.5f; + break; + case GL_QUARTER_BIT_ATI: + imm = 0.25f; + break; + case GL_EIGHTH_BIT_ATI: + imm = 0.125f; + break; + default: + imm = 1.0f; + } + + src[0] = ureg_src(dst); + src[1] = ureg_imm1f(t->ureg, imm); + if (dstMod & GL_SATURATE_BIT_ATI) { + dst = ureg_saturate(dst); + } + ureg_insn(t->ureg, TGSI_OPCODE_MUL, &dst, 1, src, 2); +} + +/** + * Compile one setup instruction to TGSI instructions. + */ +static void +compile_setupinst(struct st_translate *t, + const unsigned r, + const struct atifs_setupinst *texinst) +{ + struct ureg_dst dst[1]; + struct ureg_src src[2]; + + if (!texinst->Opcode) + return; + + dst[0] = get_temp(t, r); + + GLuint pass_tex = texinst->src; + + if (pass_tex >= GL_TEXTURE0_ARB && pass_tex <= GL_TEXTURE7_ARB) { + unsigned attr = pass_tex - GL_TEXTURE0_ARB + VARYING_SLOT_TEX0; + + src[0] = t->inputs[t->inputMapping[attr]]; + } else if (pass_tex >= GL_REG_0_ATI && pass_tex <= GL_REG_5_ATI) { + unsigned reg = pass_tex - GL_REG_0_ATI; + + /* the frontend already validated that REG is only allowed in second pass */ + if (t->regs_written[0][reg]) { + src[0] = ureg_src(t->temps[reg]); + } else { + src[0] = ureg_imm1f(t->ureg, 0.0f); + } + } + src[0] = apply_swizzle(t, src[0], texinst->swizzle); + + if (texinst->Opcode == ATI_FRAGMENT_SHADER_SAMPLE_OP) { + /* by default texture and sampler indexes are the same */ + src[1] = t->samplers[r]; + /* the texture target is still unknown, it will be fixed in the draw call */ + ureg_tex_insn(t->ureg, TGSI_OPCODE_TEX, dst, 1, TGSI_TEXTURE_2D, + NULL, 0, src, 2); + } else if (texinst->Opcode == ATI_FRAGMENT_SHADER_PASS_OP) { + ureg_insn(t->ureg, TGSI_OPCODE_MOV, dst, 1, src, 1); + } + + t->regs_written[t->current_pass][r] = true; +} + +/** + * Compile one arithmetic operation COLOR&ALPHA pair into TGSI instructions. + */ +static void +compile_instruction(struct st_translate *t, + const struct atifs_instruction *inst) +{ + unsigned optype; + + for (optype = 0; optype < 2; optype++) { /* color, alpha */ + const struct instruction_desc *desc; + struct ureg_dst dst[1]; + struct ureg_src args[3]; /* arguments for the main operation */ + unsigned arg; + unsigned dstreg = inst->DstReg[optype].Index - GL_REG_0_ATI; + + if (!inst->Opcode[optype]) + continue; + + desc = &inst_desc[inst->Opcode[optype] - GL_MOV_ATI]; + + /* prepare the arguments */ + for (arg = 0; arg < desc->arg_count; arg++) { + if (arg >= inst->ArgCount[optype]) { + _mesa_warning(0, "Using 0 for missing argument %d of %s\n", + arg, desc->name); + args[arg] = ureg_imm1f(t->ureg, 0.0f); + } else { + args[arg] = prepare_argument(t, arg, + &inst->SrcReg[optype][arg]); + } + } + + /* prepare dst */ + dst[0] = get_temp(t, dstreg); + + if (optype) { + dst[0] = ureg_writemask(dst[0], TGSI_WRITEMASK_W); + } else { + GLuint dstMask = inst->DstReg[optype].dstMask; + if (dstMask == GL_NONE) { + dst[0] = ureg_writemask(dst[0], TGSI_WRITEMASK_XYZ); + } else { + dst[0] = ureg_writemask(dst[0], dstMask); /* the enum values match */ + } + } + + /* emit the main instruction */ + emit_arith_inst(t, desc, dst, args, arg); + + emit_dstmod(t, *dst, inst->DstReg[optype].dstMod); + + t->regs_written[t->current_pass][dstreg] = true; + } +} + +static void +finalize_shader(struct st_translate *t, unsigned numPasses) +{ + struct ureg_dst dst[1] = { { 0 } }; + struct ureg_src src[1] = { { 0 } }; + + if (t->regs_written[numPasses-1][0]) { + /* copy the result into the OUT slot */ + dst[0] = t->outputs[t->outputMapping[FRAG_RESULT_COLOR]]; + src[0] = ureg_src(t->temps[0]); + ureg_insn(t->ureg, TGSI_OPCODE_MOV, dst, 1, src, 1); + } + + /* signal the end of the program */ + ureg_insn(t->ureg, TGSI_OPCODE_END, dst, 0, src, 0); +} + +/** + * Called when a new variant is needed, we need to translate + * the ATI fragment shader to TGSI + */ +enum pipe_error +st_translate_atifs_program( + struct ureg_program *ureg, + struct ati_fragment_shader *atifs, + struct gl_program *program, + GLuint numInputs, + const GLuint inputMapping[], + const ubyte inputSemanticName[], + const ubyte inputSemanticIndex[], + const GLuint interpMode[], + GLuint numOutputs, + const GLuint outputMapping[], + const ubyte outputSemanticName[], + const ubyte outputSemanticIndex[]) +{ + enum pipe_error ret = PIPE_OK; + + unsigned pass, i, r; + + struct st_translate translate, *t; + t = &translate; + memset(t, 0, sizeof *t); + + t->inputMapping = inputMapping; + t->outputMapping = outputMapping; + t->ureg = ureg; + t->atifs = atifs; + + /* + * Declare input attributes. + */ + for (i = 0; i < numInputs; i++) { + t->inputs[i] = ureg_DECL_fs_input(ureg, + inputSemanticName[i], + inputSemanticIndex[i], + interpMode[i]); + } + + /* + * Declare output attributes: + * we always have numOutputs=1 and it's FRAG_RESULT_COLOR + */ + t->outputs[0] = ureg_DECL_output(ureg, + TGSI_SEMANTIC_COLOR, + outputSemanticIndex[0]); + + /* Emit constants and immediates. Mesa uses a single index space + * for these, so we put all the translated regs in t->constants. + */ + if (program->Parameters) { + t->constants = calloc(program->Parameters->NumParameters, + sizeof t->constants[0]); + if (t->constants == NULL) { + ret = PIPE_ERROR_OUT_OF_MEMORY; + goto out; + } + + for (i = 0; i < program->Parameters->NumParameters; i++) { + switch (program->Parameters->Parameters[i].Type) { + case PROGRAM_STATE_VAR: + case PROGRAM_UNIFORM: + t->constants[i] = ureg_DECL_constant(ureg, i); + break; + case PROGRAM_CONSTANT: + t->constants[i] = + ureg_DECL_immediate(ureg, + (const float*)program->Parameters->ParameterValues[i], + 4); + break; + default: + break; + } + } + } + + /* texture samplers */ + for (i = 0; i < MAX_NUM_FRAGMENT_REGISTERS_ATI; i++) { + if (program->SamplersUsed & (1 << i)) { + t->samplers[i] = ureg_DECL_sampler(ureg, i); + /* the texture target is still unknown, it will be fixed in the draw call */ + ureg_DECL_sampler_view(ureg, i, TGSI_TEXTURE_2D, + TGSI_RETURN_TYPE_FLOAT, + TGSI_RETURN_TYPE_FLOAT, + TGSI_RETURN_TYPE_FLOAT, + TGSI_RETURN_TYPE_FLOAT); + } + } + + /* emit instructions */ + for (pass = 0; pass < atifs->NumPasses; pass++) { + t->current_pass = pass; + for (r = 0; r < MAX_NUM_FRAGMENT_REGISTERS_ATI; r++) { + struct atifs_setupinst *texinst = &atifs->SetupInst[pass][r]; + compile_setupinst(t, r, texinst); + } + for (i = 0; i < atifs->numArithInstr[pass]; i++) { + struct atifs_instruction *inst = &atifs->Instructions[pass][i]; + compile_instruction(t, inst); + } + } + + finalize_shader(t, atifs->NumPasses); + +out: + free(t->constants); + + if (t->error) { + debug_printf("%s: translate error flag set\n", __func__); + } + + return ret; +} + +/** + * Called in ProgramStringNotify, we need to fill the metadata of the + * gl_program attached to the ati_fragment_shader + */ +void +st_init_atifs_prog(struct gl_context *ctx, struct gl_program *prog) +{ + /* we know this is st_fragment_program, because of st_new_ati_fs() */ + struct st_fragment_program *stfp = (struct st_fragment_program *) prog; + struct ati_fragment_shader *atifs = stfp->ati_fs; + + unsigned pass, i, r, optype, arg; + + static const gl_state_index fog_params_state[STATE_LENGTH] = + {STATE_INTERNAL, STATE_FOG_PARAMS_OPTIMIZED, 0, 0, 0}; + static const gl_state_index fog_color[STATE_LENGTH] = + {STATE_FOG_COLOR, 0, 0, 0, 0}; + + prog->InputsRead = 0; + prog->OutputsWritten = BITFIELD64_BIT(FRAG_RESULT_COLOR); + prog->SamplersUsed = 0; + prog->Parameters = _mesa_new_parameter_list(); + + /* fill in InputsRead, SamplersUsed, TexturesUsed */ + for (pass = 0; pass < atifs->NumPasses; pass++) { + for (r = 0; r < MAX_NUM_FRAGMENT_REGISTERS_ATI; r++) { + struct atifs_setupinst *texinst = &atifs->SetupInst[pass][r]; + GLuint pass_tex = texinst->src; + + if (texinst->Opcode == ATI_FRAGMENT_SHADER_SAMPLE_OP) { + /* mark which texcoords are used */ + prog->InputsRead |= BITFIELD64_BIT(VARYING_SLOT_TEX0 + pass_tex - GL_TEXTURE0_ARB); + /* by default there is 1:1 mapping between samplers and textures */ + prog->SamplersUsed |= (1 << r); + /* the target is unknown here, it will be fixed in the draw call */ + prog->TexturesUsed[r] = TEXTURE_2D_BIT; + } else if (texinst->Opcode == ATI_FRAGMENT_SHADER_PASS_OP) { + if (pass_tex >= GL_TEXTURE0_ARB && pass_tex <= GL_TEXTURE7_ARB) { + prog->InputsRead |= BITFIELD64_BIT(VARYING_SLOT_TEX0 + pass_tex - GL_TEXTURE0_ARB); + } + } + } + } + for (pass = 0; pass < atifs->NumPasses; pass++) { + for (i = 0; i < atifs->numArithInstr[pass]; i++) { + struct atifs_instruction *inst = &atifs->Instructions[pass][i]; + + for (optype = 0; optype < 2; optype++) { /* color, alpha */ + if (inst->Opcode[optype]) { + for (arg = 0; arg < inst->ArgCount[optype]; arg++) { + GLint index = inst->SrcReg[optype][arg].Index; + if (index == GL_PRIMARY_COLOR_EXT) { + prog->InputsRead |= BITFIELD64_BIT(VARYING_SLOT_COL0); + } else if (index == GL_SECONDARY_INTERPOLATOR_ATI) { + /* note: ATI_fragment_shader.txt never specifies what + * GL_SECONDARY_INTERPOLATOR_ATI is, swrast uses + * VARYING_SLOT_COL1 for this input */ + prog->InputsRead |= BITFIELD64_BIT(VARYING_SLOT_COL1); + } + } + } + } + } + } + /* we may need fog */ + prog->InputsRead |= BITFIELD64_BIT(VARYING_SLOT_FOGC); + + /* we always have the ATI_fs constants, and the fog params */ + for (i = 0; i < MAX_NUM_FRAGMENT_CONSTANTS_ATI; i++) { + _mesa_add_parameter(prog->Parameters, PROGRAM_UNIFORM, + NULL, 4, GL_FLOAT, NULL, NULL); + } + _mesa_add_state_reference(prog->Parameters, fog_params_state); + _mesa_add_state_reference(prog->Parameters, fog_color); + + prog->NumInstructions = 0; + prog->NumTemporaries = MAX_NUM_FRAGMENT_REGISTERS_ATI + 3; /* 3 input temps for arith ops */ + prog->NumParameters = MAX_NUM_FRAGMENT_CONSTANTS_ATI + 2; /* 2 state variables for fog */ +} + + +struct tgsi_atifs_transform { + struct tgsi_transform_context base; + struct tgsi_shader_info info; + const struct st_fp_variant_key *key; + bool first_instruction_emitted; + unsigned fog_factor_temp; + unsigned fog_clamp_imm; +}; + +static inline struct tgsi_atifs_transform * +tgsi_atifs_transform(struct tgsi_transform_context *tctx) +{ + return (struct tgsi_atifs_transform *)tctx; +} + +/* copied from st_cb_drawpixels_shader.c */ +static void +set_src(struct tgsi_full_instruction *inst, unsigned i, unsigned file, unsigned index, + unsigned x, unsigned y, unsigned z, unsigned w) +{ + inst->Src[i].Register.File = file; + inst->Src[i].Register.Index = index; + inst->Src[i].Register.SwizzleX = x; + inst->Src[i].Register.SwizzleY = y; + inst->Src[i].Register.SwizzleZ = z; + inst->Src[i].Register.SwizzleW = w; +} + +#define SET_SRC(inst, i, file, index, x, y, z, w) \ + set_src(inst, i, file, index, TGSI_SWIZZLE_##x, TGSI_SWIZZLE_##y, \ + TGSI_SWIZZLE_##z, TGSI_SWIZZLE_##w) + +static void +transform_decl(struct tgsi_transform_context *tctx, + struct tgsi_full_declaration *decl) +{ + struct tgsi_atifs_transform *ctx = tgsi_atifs_transform(tctx); + + if (decl->Declaration.File == TGSI_FILE_SAMPLER_VIEW) { + /* fix texture target */ + unsigned newtarget = ctx->key->texture_targets[decl->Range.First]; + if (newtarget) + decl->SamplerView.Resource = newtarget; + } + + tctx->emit_declaration(tctx, decl); +} + +static void +transform_instr(struct tgsi_transform_context *tctx, + struct tgsi_full_instruction *current_inst) +{ + struct tgsi_atifs_transform *ctx = tgsi_atifs_transform(tctx); + + if (ctx->first_instruction_emitted) + goto transform_inst; + + ctx->first_instruction_emitted = true; + + if (ctx->key->fog) { + /* add a new temp for the fog factor */ + ctx->fog_factor_temp = ctx->info.file_max[TGSI_FILE_TEMPORARY] + 1; + tgsi_transform_temp_decl(tctx, ctx->fog_factor_temp); + + /* add immediates for clamp */ + ctx->fog_clamp_imm = ctx->info.immediate_count; + tgsi_transform_immediate_decl(tctx, 1.0f, 0.0f, 0.0f, 0.0f); + } + +transform_inst: + if (current_inst->Instruction.Opcode == TGSI_OPCODE_TEX) { + /* fix texture target */ + unsigned newtarget = ctx->key->texture_targets[current_inst->Src[1].Register.Index]; + if (newtarget) + current_inst->Texture.Texture = newtarget; + + } else if (ctx->key->fog && current_inst->Instruction.Opcode == TGSI_OPCODE_MOV && + current_inst->Dst[0].Register.File == TGSI_FILE_OUTPUT) { + struct tgsi_full_instruction inst; + unsigned i; + int fogc_index = -1; + + /* find FOGC input */ + for (i = 0; i < ctx->info.num_inputs; i++) { + if (ctx->info.input_semantic_name[i] == TGSI_SEMANTIC_FOG) { + fogc_index = i; + break; + } + } + if (fogc_index < 0) { + /* should never be reached, because fog coord input is always declared */ + tctx->emit_instruction(tctx, current_inst); + return; + } + + /* compute the 1 component fog factor f */ + if (ctx->key->fog == 1) { + /* LINEAR formula: f = (end - z) / (end - start) + * with optimized parameters: + * f = MAD(fogcoord, oparams.x, oparams.y) + */ + inst = tgsi_default_full_instruction(); + inst.Instruction.Opcode = TGSI_OPCODE_MAD; + inst.Instruction.NumDstRegs = 1; + inst.Dst[0].Register.File = TGSI_FILE_TEMPORARY; + inst.Dst[0].Register.Index = ctx->fog_factor_temp; + inst.Dst[0].Register.WriteMask = TGSI_WRITEMASK_XYZW; + inst.Instruction.NumSrcRegs = 3; + SET_SRC(&inst, 0, TGSI_FILE_INPUT, fogc_index, X, Y, Z, W); + SET_SRC(&inst, 1, TGSI_FILE_CONSTANT, MAX_NUM_FRAGMENT_CONSTANTS_ATI, X, X, X, X); + SET_SRC(&inst, 2, TGSI_FILE_CONSTANT, MAX_NUM_FRAGMENT_CONSTANTS_ATI, Y, Y, Y, Y); + tctx->emit_instruction(tctx, &inst); + } else if (ctx->key->fog == 2) { + /* EXP formula: f = exp(-dens * z) + * with optimized parameters: + * f = MUL(fogcoord, oparams.z); f= EX2(-f) + */ + inst = tgsi_default_full_instruction(); + inst.Instruction.Opcode = TGSI_OPCODE_MUL; + inst.Instruction.NumDstRegs = 1; + inst.Dst[0].Register.File = TGSI_FILE_TEMPORARY; + inst.Dst[0].Register.Index = ctx->fog_factor_temp; + inst.Dst[0].Register.WriteMask = TGSI_WRITEMASK_XYZW; + inst.Instruction.NumSrcRegs = 2; + SET_SRC(&inst, 0, TGSI_FILE_INPUT, fogc_index, X, Y, Z, W); + SET_SRC(&inst, 1, TGSI_FILE_CONSTANT, MAX_NUM_FRAGMENT_CONSTANTS_ATI, Z, Z, Z, Z); + tctx->emit_instruction(tctx, &inst); + + inst = tgsi_default_full_instruction(); + inst.Instruction.Opcode = TGSI_OPCODE_EX2; + inst.Instruction.NumDstRegs = 1; + inst.Dst[0].Register.File = TGSI_FILE_TEMPORARY; + inst.Dst[0].Register.Index = ctx->fog_factor_temp; + inst.Dst[0].Register.WriteMask = TGSI_WRITEMASK_XYZW; + inst.Instruction.NumSrcRegs = 1; + SET_SRC(&inst, 0, TGSI_FILE_TEMPORARY, ctx->fog_factor_temp, X, Y, Z, W); + inst.Src[0].Register.Negate = 1; + tctx->emit_instruction(tctx, &inst); + } else if (ctx->key->fog == 3) { + /* EXP2 formula: f = exp(-(dens * z)^2) + * with optimized parameters: + * f = MUL(fogcoord, oparams.w); f=MUL(f, f); f= EX2(-f) + */ + inst = tgsi_default_full_instruction(); + inst.Instruction.Opcode = TGSI_OPCODE_MUL; + inst.Instruction.NumDstRegs = 1; + inst.Dst[0].Register.File = TGSI_FILE_TEMPORARY; + inst.Dst[0].Register.Index = ctx->fog_factor_temp; + inst.Dst[0].Register.WriteMask = TGSI_WRITEMASK_XYZW; + inst.Instruction.NumSrcRegs = 2; + SET_SRC(&inst, 0, TGSI_FILE_INPUT, fogc_index, X, Y, Z, W); + SET_SRC(&inst, 1, TGSI_FILE_CONSTANT, MAX_NUM_FRAGMENT_CONSTANTS_ATI, W, W, W, W); + tctx->emit_instruction(tctx, &inst); + + inst = tgsi_default_full_instruction(); + inst.Instruction.Opcode = TGSI_OPCODE_MUL; + inst.Instruction.NumDstRegs = 1; + inst.Dst[0].Register.File = TGSI_FILE_TEMPORARY; + inst.Dst[0].Register.Index = ctx->fog_factor_temp; + inst.Dst[0].Register.WriteMask = TGSI_WRITEMASK_XYZW; + inst.Instruction.NumSrcRegs = 2; + SET_SRC(&inst, 0, TGSI_FILE_TEMPORARY, ctx->fog_factor_temp, X, Y, Z, W); + SET_SRC(&inst, 1, TGSI_FILE_TEMPORARY, ctx->fog_factor_temp, X, Y, Z, W); + tctx->emit_instruction(tctx, &inst); + + inst = tgsi_default_full_instruction(); + inst.Instruction.Opcode = TGSI_OPCODE_EX2; + inst.Instruction.NumDstRegs = 1; + inst.Dst[0].Register.File = TGSI_FILE_TEMPORARY; + inst.Dst[0].Register.Index = ctx->fog_factor_temp; + inst.Dst[0].Register.WriteMask = TGSI_WRITEMASK_XYZW; + inst.Instruction.NumSrcRegs = 1; + SET_SRC(&inst, 0, TGSI_FILE_TEMPORARY, ctx->fog_factor_temp, X, Y, Z, W); + inst.Src[0].Register.Negate ^= 1; + tctx->emit_instruction(tctx, &inst); + } + /* f = CLAMP(f, 0.0, 1.0) */ + inst = tgsi_default_full_instruction(); + inst.Instruction.Opcode = TGSI_OPCODE_CLAMP; + inst.Instruction.NumDstRegs = 1; + inst.Dst[0].Register.File = TGSI_FILE_TEMPORARY; + inst.Dst[0].Register.Index = ctx->fog_factor_temp; + inst.Dst[0].Register.WriteMask = TGSI_WRITEMASK_XYZW; + inst.Instruction.NumSrcRegs = 3; + SET_SRC(&inst, 0, TGSI_FILE_TEMPORARY, ctx->fog_factor_temp, X, Y, Z, W); + SET_SRC(&inst, 1, TGSI_FILE_IMMEDIATE, ctx->fog_clamp_imm, Y, Y, Y, Y); // 0.0 + SET_SRC(&inst, 2, TGSI_FILE_IMMEDIATE, ctx->fog_clamp_imm, X, X, X, X); // 1.0 + tctx->emit_instruction(tctx, &inst); + + /* REG0 = LRP(f, REG0, fogcolor) */ + inst = tgsi_default_full_instruction(); + inst.Instruction.Opcode = TGSI_OPCODE_LRP; + inst.Instruction.NumDstRegs = 1; + inst.Dst[0].Register.File = TGSI_FILE_TEMPORARY; + inst.Dst[0].Register.Index = 0; + inst.Dst[0].Register.WriteMask = TGSI_WRITEMASK_XYZW; + inst.Instruction.NumSrcRegs = 3; + SET_SRC(&inst, 0, TGSI_FILE_TEMPORARY, ctx->fog_factor_temp, X, X, X, Y); + SET_SRC(&inst, 1, TGSI_FILE_TEMPORARY, 0, X, Y, Z, W); + SET_SRC(&inst, 2, TGSI_FILE_CONSTANT, MAX_NUM_FRAGMENT_CONSTANTS_ATI + 1, X, Y, Z, W); + tctx->emit_instruction(tctx, &inst); + } + + tctx->emit_instruction(tctx, current_inst); +} + +/* + * A post-process step in the draw call to fix texture targets and + * insert code for fog. + */ +const struct tgsi_token * +st_fixup_atifs(const struct tgsi_token *tokens, + const struct st_fp_variant_key *key) +{ + struct tgsi_atifs_transform ctx; + struct tgsi_token *newtoks; + int newlen; + + memset(&ctx, 0, sizeof(ctx)); + ctx.base.transform_declaration = transform_decl; + ctx.base.transform_instruction = transform_instr; + ctx.key = key; + tgsi_scan_shader(tokens, &ctx.info); + + newlen = tgsi_num_tokens(tokens) + 30; + newtoks = tgsi_alloc_tokens(newlen); + if (!newtoks) + return NULL; + + tgsi_transform_shader(tokens, newtoks, newlen, &ctx.base); + return newtoks; +} + diff --git a/src/mesa/state_tracker/st_atifs_to_tgsi.h b/src/mesa/state_tracker/st_atifs_to_tgsi.h new file mode 100644 index 00000000000..c1b6758ba02 --- /dev/null +++ b/src/mesa/state_tracker/st_atifs_to_tgsi.h @@ -0,0 +1,67 @@ +/* + * Copyright (C) 2016 Miklós Máté + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + */ + +#ifndef ST_ATIFS_TO_TGSI_H +#define ST_ATIFS_TO_TGSI_H + +#if defined __cplusplus +extern "C" { +#endif + +#include "main/glheader.h" +#include "pipe/p_defines.h" + +struct gl_context; +struct gl_program; +struct ureg_program; +struct tgsi_token; +struct ati_fragment_shader; +struct st_fp_variant_key; + +enum pipe_error +st_translate_atifs_program( + struct ureg_program *ureg, + struct ati_fragment_shader *atifs, + struct gl_program *program, + GLuint numInputs, + const GLuint inputMapping[], + const ubyte inputSemanticName[], + const ubyte inputSemanticIndex[], + const GLuint interpMode[], + GLuint numOutputs, + const GLuint outputMapping[], + const ubyte outputSemanticName[], + const ubyte outputSemanticIndex[]); + + +void +st_init_atifs_prog(struct gl_context *ctx, struct gl_program *prog); + +const struct tgsi_token * +st_fixup_atifs(const struct tgsi_token *tokens, + const struct st_fp_variant_key *key); + +#if defined __cplusplus +} /* extern "C" */ +#endif + +#endif /* ST_ATIFS_TO_TGSI_H */ diff --git a/src/mesa/state_tracker/st_atom_constbuf.c b/src/mesa/state_tracker/st_atom_constbuf.c index 407dfd31c80..a980dbedac5 100644 --- a/src/mesa/state_tracker/st_atom_constbuf.c +++ b/src/mesa/state_tracker/st_atom_constbuf.c @@ -64,6 +64,21 @@ void st_upload_constants( struct st_context *st, shader_type == PIPE_SHADER_TESS_EVAL || shader_type == PIPE_SHADER_COMPUTE); + /* update the ATI constants before rendering */ + if (shader_type == PIPE_SHADER_FRAGMENT && st->fp->ati_fs) { + struct ati_fragment_shader *ati_fs = st->fp->ati_fs; + unsigned c; + + for (c = 0; c < MAX_NUM_FRAGMENT_CONSTANTS_ATI; c++) { + if (ati_fs->LocalConstDef & (1 << c)) + memcpy(params->ParameterValues[c], + ati_fs->Constants[c], sizeof(GLfloat) * 4); + else + memcpy(params->ParameterValues[c], + st->ctx->ATIFragmentShader.GlobalConstants[c], sizeof(GLfloat) * 4); + } + } + /* update constants */ if (params && params->NumParameters) { struct pipe_constant_buffer cb; diff --git a/src/mesa/state_tracker/st_atom_sampler.c b/src/mesa/state_tracker/st_atom_sampler.c index 82dcf5ee0ca..a1cfa1c34c5 100644 --- a/src/mesa/state_tracker/st_atom_sampler.c +++ b/src/mesa/state_tracker/st_atom_sampler.c @@ -133,18 +133,19 @@ convert_sampler(struct st_context *st, { const struct gl_texture_object *texobj; struct gl_context *ctx = st->ctx; - struct gl_sampler_object *msamp; + const struct gl_sampler_object *msamp; GLenum texBaseFormat; texobj = ctx->Texture.Unit[texUnit]._Current; if (!texobj) { texobj = _mesa_get_fallback_texture(ctx, TEXTURE_2D_INDEX); + msamp = &texobj->Sampler; + } else { + msamp = _mesa_get_samplerobj(ctx, texUnit); } texBaseFormat = _mesa_texture_base_format(texobj); - msamp = _mesa_get_samplerobj(ctx, texUnit); - memset(sampler, 0, sizeof(*sampler)); sampler->wrap_s = gl_wrap_xlate(msamp->WrapS); sampler->wrap_t = gl_wrap_xlate(msamp->WrapT); diff --git a/src/mesa/state_tracker/st_atom_shader.c b/src/mesa/state_tracker/st_atom_shader.c index 709f0cbcb91..d0c2429dcef 100644 --- a/src/mesa/state_tracker/st_atom_shader.c +++ b/src/mesa/state_tracker/st_atom_shader.c @@ -38,18 +38,69 @@ #include "main/imports.h" #include "main/mtypes.h" #include "main/framebuffer.h" +#include "main/texobj.h" +#include "main/texstate.h" #include "program/program.h" #include "pipe/p_context.h" #include "pipe/p_shader_tokens.h" #include "util/u_simple_shaders.h" #include "cso_cache/cso_context.h" +#include "util/u_debug.h" #include "st_context.h" #include "st_atom.h" #include "st_program.h" +/** Compress the fog function enums into a 2-bit value */ +static GLuint +translate_fog_mode(GLenum mode) +{ + switch (mode) { + case GL_LINEAR: return 1; + case GL_EXP: return 2; + case GL_EXP2: return 3; + default: + return 0; + } +} + +static unsigned +get_texture_target(struct gl_context *ctx, const unsigned unit) +{ + struct gl_texture_object *texObj = _mesa_get_tex_unit(ctx, unit)->_Current; + gl_texture_index index; + + if (texObj) { + index = _mesa_tex_target_to_index(ctx, texObj->Target); + } else { + /* fallback for missing texture */ + index = TEXTURE_2D_INDEX; + } + + /* Map mesa texture target to TGSI texture target. + * Copied from st_mesa_to_tgsi.c, the shadow part is omitted */ + switch(index) { + case TEXTURE_2D_MULTISAMPLE_INDEX: return TGSI_TEXTURE_2D_MSAA; + case TEXTURE_2D_MULTISAMPLE_ARRAY_INDEX: return TGSI_TEXTURE_2D_ARRAY_MSAA; + case TEXTURE_BUFFER_INDEX: return TGSI_TEXTURE_BUFFER; + case TEXTURE_1D_INDEX: return TGSI_TEXTURE_1D; + case TEXTURE_2D_INDEX: return TGSI_TEXTURE_2D; + case TEXTURE_3D_INDEX: return TGSI_TEXTURE_3D; + case TEXTURE_CUBE_INDEX: return TGSI_TEXTURE_CUBE; + case TEXTURE_CUBE_ARRAY_INDEX: return TGSI_TEXTURE_CUBE_ARRAY; + case TEXTURE_RECT_INDEX: return TGSI_TEXTURE_RECT; + case TEXTURE_1D_ARRAY_INDEX: return TGSI_TEXTURE_1D_ARRAY; + case TEXTURE_2D_ARRAY_INDEX: return TGSI_TEXTURE_2D_ARRAY; + case TEXTURE_EXTERNAL_INDEX: return TGSI_TEXTURE_2D; + default: + debug_assert(0); + return TGSI_TEXTURE_1D; + } +} + + /** * Update fragment program state/atom. This involves translating the * Mesa fragment program into a gallium fragment program and binding it. @@ -79,6 +130,18 @@ update_fp( struct st_context *st ) st->ctx->Multisample.MinSampleShadingValue * _mesa_geometric_samples(st->ctx->DrawBuffer) > 1; + if (stfp->ati_fs) { + unsigned u; + + if (st->ctx->Fog.Enabled) { + key.fog = translate_fog_mode(st->ctx->Fog.Mode); + } + + for (u = 0; u < MAX_NUM_FRAGMENT_REGISTERS_ATI; u++) { + key.texture_targets[u] = get_texture_target(st->ctx, u); + } + } + st->fp_variant = st_get_fp_variant(st, stfp, &key); st_reference_fragprog(st, &st->fp, stfp); @@ -91,7 +154,7 @@ update_fp( struct st_context *st ) const struct st_tracked_state st_update_fp = { "st_update_fp", /* name */ { /* dirty */ - _NEW_BUFFERS | _NEW_MULTISAMPLE, /* mesa */ + _NEW_BUFFERS | _NEW_MULTISAMPLE | _NEW_FOG, /* mesa */ ST_NEW_FRAGMENT_PROGRAM /* st */ }, update_fp /* update */ diff --git a/src/mesa/state_tracker/st_cb_drawpixels.c b/src/mesa/state_tracker/st_cb_drawpixels.c index 09f4d8e00d1..01ed5441d11 100644 --- a/src/mesa/state_tracker/st_cb_drawpixels.c +++ b/src/mesa/state_tracker/st_cb_drawpixels.c @@ -1302,6 +1302,7 @@ blit_copy_pixels(struct gl_context *ctx, GLint srcx, GLint srcy, !ctx->FragmentProgram.Enabled && !ctx->VertexProgram.Enabled && !ctx->_Shader->CurrentProgram[MESA_SHADER_FRAGMENT] && + !ctx->ATIFragmentShader._Enabled && ctx->DrawBuffer->_NumColorDrawBuffers == 1 && !ctx->Query.CondRenderQuery && !ctx->Query.CurrentOcclusionObject) { diff --git a/src/mesa/state_tracker/st_cb_program.c b/src/mesa/state_tracker/st_cb_program.c index 27cc0f3d154..d79cfe239e4 100644 --- a/src/mesa/state_tracker/st_cb_program.c +++ b/src/mesa/state_tracker/st_cb_program.c @@ -46,6 +46,7 @@ #include "st_mesa_to_tgsi.h" #include "st_cb_program.h" #include "st_glsl_to_tgsi.h" +#include "st_atifs_to_tgsi.h" @@ -302,6 +303,22 @@ st_program_string_notify( struct gl_context *ctx, if (st->cp == stcp) st->dirty_cp.st |= ST_NEW_COMPUTE_PROGRAM; } + else if (target == GL_FRAGMENT_SHADER_ATI) { + assert(prog); + + struct st_fragment_program *stfp = (struct st_fragment_program *) prog; + assert(stfp->ati_fs); + assert(stfp->ati_fs->Program == prog); + + st_init_atifs_prog(ctx, prog); + + st_release_fp_variants(st, stfp); + if (!st_translate_fragment_program(st, stfp)) + return false; + + if (st->fp == stfp) + st->dirty.st |= ST_NEW_FRAGMENT_PROGRAM; + } if (ST_DEBUG & DEBUG_PRECOMPILE || st->shader_has_one_variant[stage]) @@ -310,6 +327,19 @@ st_program_string_notify( struct gl_context *ctx, return GL_TRUE; } +/** + * Called via ctx->Driver.NewATIfs() + * Called in glEndFragmentShaderATI() + */ +static struct gl_program * +st_new_ati_fs(struct gl_context *ctx, struct ati_fragment_shader *curProg) +{ + struct gl_program *prog = ctx->Driver.NewProgram(ctx, GL_FRAGMENT_PROGRAM_ARB, + curProg->Id); + struct st_fragment_program *stfp = (struct st_fragment_program *)prog; + stfp->ati_fs = curProg; + return prog; +} /** * Plug in the program and shader-related device driver functions. @@ -322,6 +352,7 @@ st_init_program_functions(struct dd_function_table *functions) functions->NewProgram = st_new_program; functions->DeleteProgram = st_delete_program; functions->ProgramStringNotify = st_program_string_notify; + functions->NewATIfs = st_new_ati_fs; functions->LinkShader = st_link_shader; } diff --git a/src/mesa/state_tracker/st_cb_texture.c b/src/mesa/state_tracker/st_cb_texture.c index 460c1790663..3980f5d2f51 100644 --- a/src/mesa/state_tracker/st_cb_texture.c +++ b/src/mesa/state_tracker/st_cb_texture.c @@ -2886,12 +2886,17 @@ st_finalize_texture(struct gl_context *ctx, /* Need to import images in main memory or held in other textures. */ if (stImage && stObj->pt != stImage->pt) { + GLuint height = stObj->height0; GLuint depth = stObj->depth0; + + if (stObj->base.Target != GL_TEXTURE_1D_ARRAY) + height = u_minify(height, level); if (stObj->base.Target == GL_TEXTURE_3D) depth = u_minify(depth, level); + if (level == 0 || (stImage->base.Width == u_minify(stObj->width0, level) && - stImage->base.Height == u_minify(stObj->height0, level) && + stImage->base.Height == height && stImage->base.Depth == depth)) { /* src image fits expected dest mipmap level size */ copy_image_data_to_texture(st, stObj, level, stImage); diff --git a/src/mesa/state_tracker/st_cb_xformfb.c b/src/mesa/state_tracker/st_cb_xformfb.c index 0c01cd5ab78..a5cf3dfd5a9 100644 --- a/src/mesa/state_tracker/st_cb_xformfb.c +++ b/src/mesa/state_tracker/st_cb_xformfb.c @@ -125,7 +125,7 @@ st_begin_transform_feedback(struct gl_context *ctx, GLenum mode, if (bo && bo->buffer) { unsigned stream = - obj->shader_program->LinkedTransformFeedback.BufferStream[i]; + obj->shader_program->LinkedTransformFeedback.Buffers[i].Stream; /* Check whether we need to recreate the target. */ if (!sobj->targets[i] || @@ -204,7 +204,7 @@ st_end_transform_feedback(struct gl_context *ctx, for (i = 0; i < ARRAY_SIZE(sobj->targets); i++) { unsigned stream = - obj->shader_program->LinkedTransformFeedback.BufferStream[i]; + obj->shader_program->LinkedTransformFeedback.Buffers[i].Stream; /* Is it not bound or already set for this stream? */ if (!sobj->targets[i] || sobj->draw_count[stream]) diff --git a/src/mesa/state_tracker/st_draw.c b/src/mesa/state_tracker/st_draw.c index fdd59a383a9..3db5749725e 100644 --- a/src/mesa/state_tracker/st_draw.c +++ b/src/mesa/state_tracker/st_draw.c @@ -127,35 +127,6 @@ setup_index_buffer(struct st_context *st, /** - * Prior to drawing, check that any uniforms referenced by the - * current shader have been set. If a uniform has not been set, - * issue a warning. - */ -static void -check_uniforms(struct gl_context *ctx) -{ - struct gl_shader_program **shProg = ctx->_Shader->CurrentProgram; - unsigned j; - - for (j = 0; j < 3; j++) { - unsigned i; - - if (shProg[j] == NULL || !shProg[j]->LinkStatus) - continue; - - for (i = 0; i < shProg[j]->NumUniformStorage; i++) { - const struct gl_uniform_storage *u = &shProg[j]->UniformStorage[i]; - if (!u->initialized) { - _mesa_warning(ctx, - "Using shader with uninitialized uniform: %s", - u->name); - } - } - } -} - - -/** * Translate OpenGL primtive type (GL_POINTS, GL_TRIANGLE_STRIP, etc) to * the corresponding Gallium type. */ @@ -203,14 +174,6 @@ st_draw_vbo(struct gl_context *ctx, /* Validate state. */ if (st->dirty.st || st->dirty.mesa || ctx->NewDriverState) { st_validate_state(st, ST_PIPELINE_RENDER); - -#if 0 - if (MESA_VERBOSE & VERBOSE_GLSL) { - check_uniforms(ctx); - } -#else - (void) check_uniforms; -#endif } if (st->vertex_array_out_of_memory) { diff --git a/src/mesa/state_tracker/st_extensions.c b/src/mesa/state_tracker/st_extensions.c index 2fdaba073a2..8748ab5c876 100644 --- a/src/mesa/state_tracker/st_extensions.c +++ b/src/mesa/state_tracker/st_extensions.c @@ -552,7 +552,6 @@ void st_init_extensions(struct pipe_screen *screen, boolean has_lib_dxtc) { unsigned i; - int glsl_feature_level; GLboolean *extension_table = (GLboolean *) extensions; static const struct st_extension_cap_mapping cap_mapping[] = { @@ -811,6 +810,7 @@ void st_init_extensions(struct pipe_screen *screen, extensions->EXT_texture_env_dot3 = GL_TRUE; extensions->EXT_vertex_array_bgra = GL_TRUE; + extensions->ATI_fragment_shader = GL_TRUE; extensions->ATI_texture_env_combine3 = GL_TRUE; extensions->MESA_pack_invert = GL_TRUE; @@ -844,12 +844,8 @@ void st_init_extensions(struct pipe_screen *screen, ARRAY_SIZE(vertex_mapping), PIPE_BUFFER, PIPE_BIND_VERTEX_BUFFER); - /* Figure out GLSL support. */ - glsl_feature_level = screen->get_param(screen, PIPE_CAP_GLSL_FEATURE_LEVEL); - - consts->GLSLVersion = glsl_feature_level; - if (glsl_feature_level >= 410) - consts->GLSLVersion = 410; + /* Figure out GLSL support and set GLSLVersion to it. */ + consts->GLSLVersion = screen->get_param(screen, PIPE_CAP_GLSL_FEATURE_LEVEL); _mesa_override_glsl_version(consts); @@ -858,9 +854,9 @@ void st_init_extensions(struct pipe_screen *screen, consts->ForceGLSLVersion = options->force_glsl_version; } - if (glsl_feature_level >= 400) + if (consts->GLSLVersion >= 400) extensions->ARB_gpu_shader5 = GL_TRUE; - if (glsl_feature_level >= 410) + if (consts->GLSLVersion >= 410) extensions->ARB_shader_precision = GL_TRUE; /* This extension needs full OpenGL 3.2, but we don't know if that's @@ -925,6 +921,23 @@ void st_init_extensions(struct pipe_screen *screen, extensions->ARB_sync = GL_TRUE; } + /* Needs PIPE_CAP_SAMPLE_SHADING + all the sample-related bits of + * ARB_gpu_shader5. This enables all the per-sample shading ES extensions. + */ + extensions->OES_sample_variables = extensions->ARB_sample_shading && + extensions->ARB_gpu_shader5; + + /* If we don't have native ETC2 support, we don't keep track of the + * original ETC2 data. This is necessary to be able to copy images between + * compatible view classes. + */ + if (extensions->ARB_copy_image && screen->is_format_supported( + screen, PIPE_FORMAT_ETC2_RGB8, + PIPE_TEXTURE_2D, 0, + PIPE_BIND_SAMPLER_VIEW)) { + extensions->OES_copy_image = GL_TRUE; + } + /* Maximum sample count. */ { enum pipe_format color_formats[] = { @@ -1020,6 +1033,12 @@ void st_init_extensions(struct pipe_screen *screen, PIPE_BIND_SAMPLER_VIEW); } + extensions->OES_texture_buffer = + extensions->ARB_texture_buffer_object && + extensions->ARB_texture_buffer_range && + extensions->ARB_texture_buffer_object_rgb32 && + extensions->ARB_shader_image_load_store; + /* Unpacking a varying in the fragment shader costs 1 texture indirection. * If the number of available texture indirections is very limited, then we * prefer to disable varying packing rather than run the risk of varying @@ -1036,7 +1055,7 @@ void st_init_extensions(struct pipe_screen *screen, consts->MaxViewports = screen->get_param(screen, PIPE_CAP_MAX_VIEWPORTS); if (consts->MaxViewports >= 16) { - if (glsl_feature_level >= 400) { + if (consts->GLSLVersion >= 400) { consts->ViewportBounds.Min = -32768.0; consts->ViewportBounds.Max = 32767.0; } else { diff --git a/src/mesa/state_tracker/st_gen_mipmap.c b/src/mesa/state_tracker/st_gen_mipmap.c index c4b3492b0d3..a14bbfabaa3 100644 --- a/src/mesa/state_tracker/st_gen_mipmap.c +++ b/src/mesa/state_tracker/st_gen_mipmap.c @@ -82,7 +82,6 @@ st_generate_mipmap(struct gl_context *ctx, GLenum target, const uint baseLevel = texObj->BaseLevel; enum pipe_format format; uint lastLevel, first_layer, last_layer; - uint dstLevel; if (!pt) return; @@ -103,42 +102,33 @@ st_generate_mipmap(struct gl_context *ctx, GLenum target, stObj->lastLevel = lastLevel; if (!texObj->Immutable) { - if (pt->last_level < lastLevel) { - /* The current gallium texture doesn't have space for all the - * mipmap levels we need to generate. So allocate a new texture. - */ - struct pipe_resource *oldTex = stObj->pt; - - /* create new texture with space for more levels */ - stObj->pt = st_texture_create(st, - oldTex->target, - oldTex->format, - lastLevel, - oldTex->width0, - oldTex->height0, - oldTex->depth0, - oldTex->array_size, - 0, - oldTex->bind); - - /* This will copy the old texture's base image into the new texture - * which we just allocated. - */ - st_finalize_texture(ctx, st->pipe, texObj); - - /* release the old tex (will likely be freed too) */ - pipe_resource_reference(&oldTex, NULL); - st_texture_release_all_sampler_views(st, stObj); - } - else { - /* Make sure that the base texture image data is present in the - * texture buffer. - */ - st_finalize_texture(ctx, st->pipe, texObj); - } + const GLboolean genSave = texObj->GenerateMipmap; + + /* Temporarily set GenerateMipmap to true so that allocate_full_mipmap() + * makes the right decision about full mipmap allocation. + */ + texObj->GenerateMipmap = GL_TRUE; + + _mesa_prepare_mipmap_levels(ctx, texObj, baseLevel, lastLevel); + + texObj->GenerateMipmap = genSave; + + /* At this point, memory for all the texture levels has been + * allocated. However, the base level image may be in one resource + * while the subsequent/smaller levels may be in another resource. + * Finalizing the texture will copy the base images from the former + * resource to the latter. + * + * After this, we'll have all mipmap levels in one resource. + */ + st_finalize_texture(ctx, st->pipe, texObj); } pt = stObj->pt; + if (!pt) { + _mesa_error(ctx, GL_OUT_OF_MEMORY, "mipmap generation"); + return; + } assert(pt->last_level >= lastLevel); @@ -169,48 +159,4 @@ st_generate_mipmap(struct gl_context *ctx, GLenum target, _mesa_generate_mipmap(ctx, target, texObj); } } - - /* Fill in the Mesa gl_texture_image fields */ - for (dstLevel = baseLevel + 1; dstLevel <= lastLevel; dstLevel++) { - const uint srcLevel = dstLevel - 1; - const struct gl_texture_image *srcImage - = _mesa_get_tex_image(ctx, texObj, target, srcLevel); - struct gl_texture_image *dstImage; - struct st_texture_image *stImage; - uint border = srcImage->Border; - uint dstWidth, dstHeight, dstDepth; - - dstWidth = u_minify(pt->width0, dstLevel); - if (texObj->Target == GL_TEXTURE_1D_ARRAY) { - dstHeight = pt->array_size; - } - else { - dstHeight = u_minify(pt->height0, dstLevel); - } - if (texObj->Target == GL_TEXTURE_2D_ARRAY || - texObj->Target == GL_TEXTURE_CUBE_MAP_ARRAY) { - dstDepth = pt->array_size; - } - else { - dstDepth = u_minify(pt->depth0, dstLevel); - } - - dstImage = _mesa_get_tex_image(ctx, texObj, target, dstLevel); - if (!dstImage) { - _mesa_error(ctx, GL_OUT_OF_MEMORY, "generating mipmaps"); - return; - } - - /* Free old image data */ - ctx->Driver.FreeTextureImageBuffer(ctx, dstImage); - - /* initialize new image */ - _mesa_init_teximage_fields(ctx, dstImage, dstWidth, dstHeight, - dstDepth, border, srcImage->InternalFormat, - srcImage->TexFormat); - - stImage = st_texture_image(dstImage); - - pipe_resource_reference(&stImage->pt, pt); - } } diff --git a/src/mesa/state_tracker/st_glsl_to_tgsi.cpp b/src/mesa/state_tracker/st_glsl_to_tgsi.cpp index 06b4bb41a9b..23786b85529 100644 --- a/src/mesa/state_tracker/st_glsl_to_tgsi.cpp +++ b/src/mesa/state_tracker/st_glsl_to_tgsi.cpp @@ -6811,7 +6811,7 @@ st_link_shader(struct gl_context *ctx, struct gl_shader_program *prog) validate_ir_tree(ir); } - build_program_resource_list(prog); + build_program_resource_list(ctx, prog); for (unsigned i = 0; i < MESA_SHADER_STAGES; i++) { struct gl_program *linked_prog; @@ -6861,7 +6861,7 @@ st_translate_stream_output_info(glsl_to_tgsi_visitor *glsl_to_tgsi, } for (i = 0; i < PIPE_MAX_SO_BUFFERS; i++) { - so->stride[i] = info->BufferStride[i]; + so->stride[i] = info->Buffers[i].Stride; } so->num_outputs = info->NumOutputs; } diff --git a/src/mesa/state_tracker/st_program.c b/src/mesa/state_tracker/st_program.c index 80dcfd82743..94dc48971ec 100644 --- a/src/mesa/state_tracker/st_program.c +++ b/src/mesa/state_tracker/st_program.c @@ -53,6 +53,7 @@ #include "st_context.h" #include "st_program.h" #include "st_mesa_to_tgsi.h" +#include "st_atifs_to_tgsi.h" #include "cso_cache/cso_context.h" @@ -811,7 +812,22 @@ st_translate_fragment_program(struct st_context *st, free_glsl_to_tgsi_visitor(stfp->glsl_to_tgsi); stfp->glsl_to_tgsi = NULL; - } else + } else if (stfp->ati_fs) + st_translate_atifs_program(ureg, + stfp->ati_fs, + &stfp->Base.Base, + /* inputs */ + fs_num_inputs, + inputMapping, + input_semantic_name, + input_semantic_index, + interpMode, + /* outputs */ + fs_num_outputs, + outputMapping, + fs_output_semantic_name, + fs_output_semantic_index); + else st_translate_mesa_program(st->ctx, TGSI_PROCESSOR_FRAGMENT, ureg, @@ -849,6 +865,16 @@ st_create_fp_variant(struct st_context *st, assert(!(key->bitmap && key->drawpixels)); + /* Fix texture targets and add fog for ATI_fs */ + if (stfp->ati_fs) { + const struct tgsi_token *tokens = st_fixup_atifs(tgsi.tokens, key); + + if (tokens) + tgsi.tokens = tokens; + else + fprintf(stderr, "mesa: cannot post-process ATI_fs\n"); + } + /* Emulate features. */ if (key->clamp_color || key->persample_shading) { const struct tgsi_token *tokens; @@ -858,9 +884,11 @@ st_create_fp_variant(struct st_context *st, tokens = tgsi_emulate(tgsi.tokens, flags); - if (tokens) + if (tokens) { + if (tgsi.tokens != stfp->tgsi.tokens) + tgsi_free_tokens(tgsi.tokens); tgsi.tokens = tokens; - else + } else fprintf(stderr, "mesa: cannot emulate deprecated features\n"); } diff --git a/src/mesa/state_tracker/st_program.h b/src/mesa/state_tracker/st_program.h index 028fba99a74..7c90fd74e14 100644 --- a/src/mesa/state_tracker/st_program.h +++ b/src/mesa/state_tracker/st_program.h @@ -35,6 +35,7 @@ #define ST_PROGRAM_H #include "main/mtypes.h" +#include "main/atifragshader.h" #include "program/program.h" #include "pipe/p_state.h" #include "st_context.h" @@ -65,6 +66,12 @@ struct st_fp_variant_key /** for ARB_sample_shading */ GLuint persample_shading:1; + + /** needed for ATI_fragment_shader */ + GLuint fog:2; + + /** needed for ATI_fragment_shader */ + char texture_targets[MAX_NUM_FRAGMENT_REGISTERS_ATI]; }; @@ -99,6 +106,7 @@ struct st_fragment_program struct gl_fragment_program Base; struct pipe_shader_state tgsi; struct glsl_to_tgsi_visitor* glsl_to_tgsi; + struct ati_fragment_shader *ati_fs; struct st_fp_variant *variants; }; diff --git a/src/mesa/state_tracker/st_vdpau.c b/src/mesa/state_tracker/st_vdpau.c index 71dd15bc4fe..b9abebfc7bf 100644 --- a/src/mesa/state_tracker/st_vdpau.c +++ b/src/mesa/state_tracker/st_vdpau.c @@ -39,8 +39,6 @@ #include "pipe/p_state.h" #include "pipe/p_video_codec.h" -#include "state_tracker/vdpau_interop.h" - #include "util/u_inlines.h" #include "st_vdpau.h" @@ -51,70 +49,155 @@ #ifdef HAVE_ST_VDPAU +#include "state_tracker/vdpau_interop.h" +#include "state_tracker/vdpau_dmabuf.h" +#include "state_tracker/vdpau_funcs.h" +#include "state_tracker/drm_driver.h" + +static struct pipe_resource * +st_vdpau_video_surface_gallium(struct gl_context *ctx, const GLvoid *vdpSurface, + GLuint index) +{ + int (*getProcAddr)(uint32_t device, uint32_t id, void **ptr); + uint32_t device = (uintptr_t)ctx->vdpDevice; + struct pipe_sampler_view *sv; + VdpVideoSurfaceGallium *f; + + struct pipe_video_buffer *buffer; + struct pipe_sampler_view **samplers; + + getProcAddr = (void *)ctx->vdpGetProcAddress; + if (getProcAddr(device, VDP_FUNC_ID_VIDEO_SURFACE_GALLIUM, (void**)&f)) + return NULL; + + buffer = f((uintptr_t)vdpSurface); + if (!buffer) + return NULL; + + samplers = buffer->get_sampler_view_planes(buffer); + if (!samplers) + return NULL; + + sv = samplers[index >> 1]; + if (!sv) + return NULL; + + return sv->texture; +} + +static struct pipe_resource * +st_vdpau_output_surface_gallium(struct gl_context *ctx, const GLvoid *vdpSurface) +{ + int (*getProcAddr)(uint32_t device, uint32_t id, void **ptr); + uint32_t device = (uintptr_t)ctx->vdpDevice; + VdpOutputSurfaceGallium *f; + + getProcAddr = (void *)ctx->vdpGetProcAddress; + if (getProcAddr(device, VDP_FUNC_ID_OUTPUT_SURFACE_GALLIUM, (void**)&f)) + return NULL; + + return f((uintptr_t)vdpSurface); +} + +static struct pipe_resource * +st_vdpau_resource_from_description(struct gl_context *ctx, + const struct VdpSurfaceDMABufDesc *desc) +{ + struct st_context *st = st_context(ctx); + struct pipe_resource templ, *res; + struct winsys_handle whandle; + + if (desc->handle == -1) + return NULL; + + memset(&templ, 0, sizeof(templ)); + templ.target = PIPE_TEXTURE_2D; + templ.last_level = 0; + templ.depth0 = 1; + templ.array_size = 1; + templ.width0 = desc->width; + templ.height0 = desc->height; + templ.format = VdpFormatRGBAToPipe(desc->format); + templ.bind = PIPE_BIND_SAMPLER_VIEW | PIPE_BIND_RENDER_TARGET; + templ.usage = PIPE_USAGE_DEFAULT; + + memset(&whandle, 0, sizeof(whandle)); + whandle.type = DRM_API_HANDLE_TYPE_FD; + whandle.handle = desc->handle; + whandle.offset = desc->offset; + whandle.stride = desc->stride; + + res = st->pipe->screen->resource_from_handle(st->pipe->screen, &templ, &whandle, + PIPE_HANDLE_USAGE_READ_WRITE); + close(desc->handle); + + return res; +} + +static struct pipe_resource * +st_vdpau_output_surface_dma_buf(struct gl_context *ctx, const GLvoid *vdpSurface) +{ + int (*getProcAddr)(uint32_t device, uint32_t id, void **ptr); + uint32_t device = (uintptr_t)ctx->vdpDevice; + + struct VdpSurfaceDMABufDesc desc; + VdpOutputSurfaceDMABuf *f; + + getProcAddr = (void *)ctx->vdpGetProcAddress; + if (getProcAddr(device, VDP_FUNC_ID_OUTPUT_SURFACE_DMA_BUF, (void**)&f)) + return NULL; + + if (f((uintptr_t)vdpSurface, &desc) != VDP_STATUS_OK) + return NULL; + + return st_vdpau_resource_from_description(ctx, &desc); +} + +static struct pipe_resource * +st_vdpau_video_surface_dma_buf(struct gl_context *ctx, const GLvoid *vdpSurface, + GLuint index) +{ + int (*getProcAddr)(uint32_t device, uint32_t id, void **ptr); + uint32_t device = (uintptr_t)ctx->vdpDevice; + + struct VdpSurfaceDMABufDesc desc; + VdpVideoSurfaceDMABuf *f; + + getProcAddr = (void *)ctx->vdpGetProcAddress; + if (getProcAddr(device, VDP_FUNC_ID_VIDEO_SURFACE_DMA_BUF, (void**)&f)) + return NULL; + + if (f((uintptr_t)vdpSurface, index, &desc) != VDP_STATUS_OK) + return NULL; + + return st_vdpau_resource_from_description(ctx, &desc); +} + static void st_vdpau_map_surface(struct gl_context *ctx, GLenum target, GLenum access, GLboolean output, struct gl_texture_object *texObj, struct gl_texture_image *texImage, const GLvoid *vdpSurface, GLuint index) { - int (*getProcAddr)(uint32_t device, uint32_t id, void **ptr); - uint32_t device = (uintptr_t)ctx->vdpDevice; - struct st_context *st = st_context(ctx); struct st_texture_object *stObj = st_texture_object(texObj); struct st_texture_image *stImage = st_texture_image(texImage); - + struct pipe_resource *res; struct pipe_sampler_view templ, **sampler_view; mesa_format texFormat; - getProcAddr = (void *)ctx->vdpGetProcAddress; if (output) { - VdpOutputSurfaceGallium *f; - - if (getProcAddr(device, VDP_FUNC_ID_OUTPUT_SURFACE_GALLIUM, (void**)&f)) { - _mesa_error(ctx, GL_INVALID_OPERATION, "VDPAUMapSurfacesNV"); - return; - } - - res = f((uintptr_t)vdpSurface); + res = st_vdpau_output_surface_dma_buf(ctx, vdpSurface); - if (!res) { - _mesa_error(ctx, GL_INVALID_OPERATION, "VDPAUMapSurfacesNV"); - return; - } + if (!res) + res = st_vdpau_output_surface_gallium(ctx, vdpSurface); } else { - struct pipe_sampler_view *sv; - VdpVideoSurfaceGallium *f; - - struct pipe_video_buffer *buffer; - struct pipe_sampler_view **samplers; - - if (getProcAddr(device, VDP_FUNC_ID_VIDEO_SURFACE_GALLIUM, (void**)&f)) { - _mesa_error(ctx, GL_INVALID_OPERATION, "VDPAUMapSurfacesNV"); - return; - } - - buffer = f((uintptr_t)vdpSurface); - if (!buffer) { - _mesa_error(ctx, GL_INVALID_OPERATION, "VDPAUMapSurfacesNV"); - return; - } - - samplers = buffer->get_sampler_view_planes(buffer); - if (!samplers) { - _mesa_error(ctx, GL_INVALID_OPERATION, "VDPAUMapSurfacesNV"); - return; - } - - sv = samplers[index >> 1]; - if (!sv) { - _mesa_error(ctx, GL_INVALID_OPERATION, "VDPAUMapSurfacesNV"); - return; - } - - res = sv->texture; + res = st_vdpau_video_surface_dma_buf(ctx, vdpSurface, index); + + if (!res) + res = st_vdpau_video_surface_gallium(ctx, vdpSurface, index); } if (!res) { |