diff --git a/src/mesa/drivers/dri/r300/r300_context.h b/src/mesa/drivers/dri/r300/r300_context.h index 75aeb3eff71..66eaa0f2b22 100644 --- a/src/mesa/drivers/dri/r300/r300_context.h +++ b/src/mesa/drivers/dri/r300/r300_context.h @@ -630,7 +630,12 @@ struct r300_pixel_shader_program { #define MAX_PIXEL_SHADER_PARAMS 32 struct r300_pixel_shader_state { struct r300_pixel_shader_program program; - + + int translated; + int have_sample; + GLuint color_reg; + GLuint src_previous; + /* parameters */ int param_length; /* to limit the number of unnecessary writes */ struct { diff --git a/src/mesa/drivers/dri/r300/r300_reg.h b/src/mesa/drivers/dri/r300/r300_reg.h index a9cb88cf97a..7242cbc892d 100644 --- a/src/mesa/drivers/dri/r300/r300_reg.h +++ b/src/mesa/drivers/dri/r300/r300_reg.h @@ -536,8 +536,8 @@ I am fairly certain that they are correct unless stated otherwise in comments. // the ROUTE_0_COLOR bit is set and ROUTE_0_COLOR_DEST contains the // color register index. */ # define R300_RS_ROUTE_0_COLOR (1 << 14) -# define R300_RS_ROUTE_0_COLOR_DEST_SHIFT (1 << 17) -# define R300_RS_ROUTE_0_COLOR_DEST_MASK (31 << 6) /* GUESS */ +# define R300_RS_ROUTE_0_COLOR_DEST_SHIFT 17 +# define R300_RS_ROUTE_0_COLOR_DEST_MASK (31 << 17) /* GUESS */ /* END */ /* BEGIN: Scissors and cliprects diff --git a/src/mesa/drivers/dri/r300/r300_state.c b/src/mesa/drivers/dri/r300/r300_state.c index c3c01203437..aa9eb5e28bd 100644 --- a/src/mesa/drivers/dri/r300/r300_state.c +++ b/src/mesa/drivers/dri/r300/r300_state.c @@ -61,6 +61,7 @@ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. #include "r300_fixed_pipelines.h" #include "r300_tex.h" #include "r300_maos.h" +#include "r300_texprog.h" static void r300AlphaFunc(GLcontext * ctx, GLenum func, GLfloat ref) { @@ -1380,7 +1381,7 @@ void r300_setup_textures(GLcontext *ctx) max_texture_unit=i; r300->hw.txe.cmd[R300_TXE_ENABLE]|=(1<hw.tex.filter.cmd[R300_TEX_VALUE_0+i]=gen_fixed_filter(t->filter); + r300->hw.tex.filter.cmd[R300_TEX_VALUE_0+i]=gen_fixed_filter(t->filter) | (i << 28); r300->hw.tex.unknown1.cmd[R300_TEX_VALUE_0+i]=0x0; /* No idea why linear filtered textures shake when puting random data */ @@ -1409,14 +1410,57 @@ void r300_setup_textures(GLcontext *ctx) void r300_setup_rs_unit(GLcontext *ctx) { r300ContextPtr r300 = R300_CONTEXT(ctx); - int i; - + int i, cur_reg; + GLuint interp_magic[8] = { + 0x00, + 0x40, + 0x80, + 0xC0, + 0x00, + 0x00, + 0x00, + 0x00 + }; + /* This needs to be rewritten - it is a hack at best */ R300_STATECHANGE(r300, ri); R300_STATECHANGE(r300, rc); R300_STATECHANGE(r300, rr); + +#if 1 + cur_reg = 0; + for (i=0;iConst.MaxTextureUnits;i++) { + r300->hw.ri.cmd[R300_RI_INTERP_0+i] = 0 + | R300_RS_INTERP_USED + | (cur_reg << R300_RS_INTERP_SRC_SHIFT) + | interp_magic[i]; +// fprintf(stderr, "RS_INTERP[%d] = 0x%x\n", i, r300->hw.ri.cmd[R300_RI_INTERP_0+i]); + if (r300->state.render_inputs & (_TNL_BIT_TEX0<hw.rr.cmd[R300_RR_ROUTE_0 + cur_reg] = 0 + | R300_RS_ROUTE_ENABLE + | i /* source INTERP */ + | (cur_reg << R300_RS_ROUTE_DEST_SHIFT); +// fprintf(stderr, "RS_ROUTE[%d] = 0x%x\n", cur_reg, r300->hw.rr.cmd[R300_RR_ROUTE_0 + cur_reg]); + cur_reg++; + } + } + if (r300->state.render_inputs & _TNL_BIT_COLOR0) + r300->hw.rr.cmd[R300_RR_ROUTE_0] |= 0 + | R300_RS_ROUTE_0_COLOR + | (cur_reg << R300_RS_ROUTE_0_COLOR_DEST_SHIFT); + r300->hw.rr.cmd[R300_RR_CMD_0] = cmducs(R300_RS_ROUTE_0, cur_reg); +// fprintf(stderr, "ADJ_RR0 = 0x%x\n", r300->hw.rr.cmd[R300_RR_ROUTE_0]); + +// fprintf(stderr, "rendering with %d texture co-ordinate sets\n", cur_reg); + + r300->hw.rc.cmd[1] = 0 + | (cur_reg /* count */ << R300_RS_CNTL_TC_CNT_SHIFT) + | R300_RS_CNTL_0_UNKNOWN_7 + | R300_RS_CNTL_0_UNKNOWN_18; + r300->hw.rc.cmd[2] = (0xC0 | (cur_reg-1) /* index of highest */ ); +#else for(i = 1; i <= 8; ++i) r300->hw.ri.cmd[i] = 0x00d10000; r300->hw.ri.cmd[R300_RI_INTERP_1] |= R300_RS_INTERP_1_UNKNOWN; @@ -1455,6 +1499,7 @@ void r300_setup_rs_unit(GLcontext *ctx) r300->hw.rr.cmd[R300_RR_ROUTE_0] = 0x4000; } +#endif } #define vpucount(ptr) (((drm_r300_cmd_header_t*)(ptr))->vpu.count) @@ -1815,7 +1860,7 @@ void r300GenerateTexturePixelShader(r300ContextPtr r300) alu_inst++; } - + r300->state.pixel_shader.program.tex.length=tex_inst; r300->state.pixel_shader.program.tex_offset=0; r300->state.pixel_shader.program.tex_end=tex_inst-1; @@ -1839,12 +1884,16 @@ int i,k; /* textures enabled ? */ if(rmesa->state.texture.tc_count>0){ +#if 1 + r300GenerateTextureFragmentShader(rmesa); +#else rmesa->state.pixel_shader=SINGLE_TEXTURE_PIXEL_SHADER; r300GenerateTexturePixelShader(rmesa); +#endif } else { rmesa->state.pixel_shader=FLAT_COLOR_PIXEL_SHADER; } - + R300_STATECHANGE(rmesa, fpt); for(i=0;istate.pixel_shader.program.tex.length;i++) rmesa->hw.fpt.cmd[R300_FPT_INSTR_0+i]=rmesa->state.pixel_shader.program.tex.inst[i]; diff --git a/src/mesa/drivers/dri/r300/r300_texprog.c b/src/mesa/drivers/dri/r300/r300_texprog.c new file mode 100644 index 00000000000..bcc101e8377 --- /dev/null +++ b/src/mesa/drivers/dri/r300/r300_texprog.c @@ -0,0 +1,264 @@ +#include "glheader.h" +#include "state.h" +#include "imports.h" +#include "enums.h" +#include "macros.h" +#include "context.h" +#include "dd.h" +#include "simple_list.h" + +#include "api_arrayelt.h" +#include "swrast/swrast.h" +#include "swrast_setup/swrast_setup.h" +#include "array_cache/acache.h" +#include "tnl/tnl.h" +#include "texformat.h" + +#include "radeon_ioctl.h" +#include "radeon_state.h" +#include "r300_context.h" +#include "r300_ioctl.h" +#include "r300_state.h" +#include "r300_reg.h" +#include "r300_program.h" +#include "r300_emit.h" +#include "r300_fixed_pipelines.h" +#include "r300_tex.h" +#include "pixel_shader.h" +#include "r300_texprog.h" + +/* TODO: we probably should have a better way to emit alu instructions */ +#define INST0 p->alu.inst[p->alu.length].inst0 = +#define INST1 p->alu.inst[p->alu.length].inst1 = +#define INST2 p->alu.inst[p->alu.length].inst2 = +#define INST3 p->alu.inst[p->alu.length].inst3 = +#define EMIT_INST p->alu.length++ + +void emit_tex(struct r300_pixel_shader_program *p, GLuint dest, GLuint unit, GLuint src) +{ + p->tex.inst[p->tex.length++] = 0 + | (src << R300_FPITX_SRC_SHIFT) + | (dest << R300_FPITX_DST_SHIFT) + | (unit << R300_FPITX_IMAGE_SHIFT) + /* I don't know if this is needed, but the hardcoded 0x18000 set it, so I will too */ + | (3 << 15); +// fprintf(stderr, "emit texinst: 0x%x\n", p->tex.inst[p->tex.length-1]); +} + +GLuint get_source(struct r300_pixel_shader_state *ps, GLenum src, GLuint unit, GLuint tc_reg) { + switch (src) { + case GL_TEXTURE: + if (!ps->have_sample) { + emit_tex(&ps->program, tc_reg, unit, tc_reg); + ps->have_sample = 1; + } + return tc_reg; + case GL_CONSTANT: + WARN_ONCE("TODO: Implement envcolor\n"); + return ps->color_reg; + case GL_PRIMARY_COLOR: + return ps->color_reg; + case GL_PREVIOUS: + return ps->src_previous; + default: + WARN_ONCE("Unknown source enum\n"); + return ps->src_previous; + } +} + +GLuint get_temp(struct r300_pixel_shader_program *p) +{ + return p->temp_register_count++; +} + +inline void emit_texenv_color(r300ContextPtr r300, struct r300_pixel_shader_state *ps, + GLuint out, GLenum envmode, GLenum format, GLuint unit, GLuint tc_reg) { + struct r300_pixel_shader_program *p = &ps->program; + + const GLuint Cp = get_source(ps, GL_PREVIOUS, unit, tc_reg); + const GLuint Cs = get_source(ps, GL_TEXTURE, unit, tc_reg); + + switch(envmode) { + case GL_DECAL: /* TODO */ + case GL_BLEND: /* TODO */ + case GL_REPLACE: + INST0 EASY_PFS_INSTR0(MAD, SRC0C_XYZ, ONE, ZERO); + switch (format) { + case GL_ALPHA: + // Cv = Cp + INST1 EASY_PFS_INSTR1(out, Cp, PFS_FLAG_CONST, PFS_FLAG_CONST, ALL, NONE); + break; + default: + // Cv = Cs + INST1 EASY_PFS_INSTR1(out, Cs, PFS_FLAG_CONST, PFS_FLAG_CONST, ALL, NONE); + break; + } + break; + case GL_MODULATE: + switch (format) { + case GL_ALPHA: + // Cv = Cp + INST0 EASY_PFS_INSTR0(MAD, SRC0C_XYZ, ONE, ZERO); + INST1 EASY_PFS_INSTR1(out, Cp, PFS_FLAG_CONST, PFS_FLAG_CONST, ALL, NONE); + break; + default: + // Cv = CpCs + INST0 EASY_PFS_INSTR0(MAD, SRC0C_XYZ, SRC1C_XYZ, ZERO); + INST1 EASY_PFS_INSTR1(out, Cp, Cs, PFS_FLAG_CONST, ALL, NONE); + break; + } + break; + case GL_ADD: + switch (format) { + case GL_ALPHA: + // Cv = Cp + INST0 EASY_PFS_INSTR0(MAD, SRC0C_XYZ, ONE, ZERO); + INST1 EASY_PFS_INSTR1(out, Cp, PFS_FLAG_CONST, PFS_FLAG_CONST, ALL, NONE); + break; + default: + // Cv = Cp + Cs + INST0 EASY_PFS_INSTR0(MAD, SRC0C_XYZ, ONE, SRC1C_XYZ); + INST1 EASY_PFS_INSTR1(out, Cp, Cs, PFS_FLAG_CONST, ALL, NONE); + break; + } + break; + default: + fprintf(stderr, "%s: should never get here!\n", __func__); + break; + } + + return; +} + +inline void emit_texenv_alpha(r300ContextPtr r300, struct r300_pixel_shader_state *ps, + GLuint out, GLenum envmode, GLenum format, GLuint unit, GLuint tc_reg) { + struct r300_pixel_shader_program *p = &ps->program; + + const GLuint Ap = get_source(ps, GL_PREVIOUS, unit, tc_reg); + const GLuint As = get_source(ps, GL_TEXTURE, unit, tc_reg); + + switch(envmode) { + case GL_DECAL: /* TODO */ + case GL_BLEND: /* TODO */ + case GL_REPLACE: + INST2 EASY_PFS_INSTR2(MAD, SRC0A, ONE, ZERO); + switch (format) { + case GL_LUMINANCE: + case GL_RGB: + // Av = Ap + INST3 EASY_PFS_INSTR3(out, Ap, PFS_FLAG_CONST, PFS_FLAG_CONST, REG); + break; + default: + INST3 EASY_PFS_INSTR3(out, As, PFS_FLAG_CONST, PFS_FLAG_CONST, REG); + break; + } + break; + case GL_MODULATE: + case GL_ADD: + switch (format) { + case GL_LUMINANCE: + case GL_RGB: + // Av = Ap + INST2 EASY_PFS_INSTR2(MAD, SRC0A, ONE, ZERO); + INST3 EASY_PFS_INSTR3(out, Ap, PFS_FLAG_CONST, PFS_FLAG_CONST, REG); + break; + default: + // Av = ApAs + INST2 EASY_PFS_INSTR2(MAD, SRC0A, SRC1A, ZERO); + INST3 EASY_PFS_INSTR3(out, Ap, As, PFS_FLAG_CONST, REG); + break; + } + break; + default: + fprintf(stderr, "%s: should never get here!\n", __func__); + break; + } + + return; +} + +GLuint emit_texenv(r300ContextPtr r300, GLuint tc_reg, GLuint unit) +{ + struct r300_pixel_shader_state *ps = &r300->state.pixel_shader; + struct r300_pixel_shader_program *p = &ps->program; + GLcontext *ctx = r300->radeon.glCtx; + struct gl_texture_object *texobj = ctx->Texture.Unit[unit]._Current; + GLenum envmode = ctx->Texture.Unit[unit].EnvMode; + GLenum format = texobj->Image[0][texobj->BaseLevel]->Format; + + const GLuint out = tc_reg; + const GLuint Cf = get_source(ps, GL_PRIMARY_COLOR, unit, tc_reg); + + WARN_ONCE("Texture environments are currently incomplete / wrong! Help me!\n"); +// fprintf(stderr, "EnvMode = %s\n", _mesa_lookup_enum_by_nr(ctx->Texture.Unit[unit].EnvMode)); + + switch (envmode) { + case GL_REPLACE: + case GL_MODULATE: + case GL_DECAL: + case GL_BLEND: + case GL_ADD: + /* Maybe these should be combined? I thought it'd be messy */ + emit_texenv_color(r300, ps, out, envmode, format, unit, tc_reg); + emit_texenv_alpha(r300, ps, out, envmode, format, unit, tc_reg); + EMIT_INST; + return out; + break; + case GL_COMBINE: + WARN_ONCE("EnvMode == GL_COMBINE unsupported! Help Me!!\n"); + return Cf; + break; + default: + WARN_ONCE("Unknown EnvMode == %d, name=%d\n", envmode, + _mesa_lookup_enum_by_nr(envmode)); + return Cf; + break; + } + +} + +void r300GenerateTextureFragmentShader(r300ContextPtr r300) +{ + struct r300_pixel_shader_state *ps = &r300->state.pixel_shader; + struct r300_pixel_shader_program *p = &ps->program; + GLcontext *ctx = r300->radeon.glCtx; + int i, tc_reg; + + p->tex.length = 0; + p->alu.length = 0; + p->active_nodes = 1; + p->first_node_has_tex = 1; + p->temp_register_count = r300->state.texture.tc_count + 1; /* texcoords and colour reg */ + + ps->color_reg = r300->state.texture.tc_count; + ps->src_previous = ps->color_reg; + + tc_reg = 0; + for (i=0;iConst.MaxTextureUnits;i++) { + if (r300->state.render_inputs & (_TNL_BIT_TEX0<have_sample = 0; + ps->src_previous = emit_texenv(r300, tc_reg, i); + tc_reg++; + } + } + +/* Do a MOV from last output, to destination reg.. This won't be needed when we + * have a better way of emitting alu instructions + */ + INST0 EASY_PFS_INSTR0(MAD, SRC0C_XYZ, ONE, ZERO); + INST1 EASY_PFS_INSTR1(0, ps->src_previous, PFS_FLAG_CONST, PFS_FLAG_CONST, NONE, ALL); + INST2 EASY_PFS_INSTR2(MAD, SRC0A, ONE, ZERO); + INST3 EASY_PFS_INSTR3(0, ps->src_previous, PFS_FLAG_CONST, PFS_FLAG_CONST, OUTPUT); + EMIT_INST; + + p->node[3].tex_end = ps->program.tex.length - 1; + p->node[3].tex_offset = 0; + p->node[3].alu_end = ps->program.alu.length - 1; + p->node[3].alu_offset = 0; + + p->tex_end = ps->program.tex.length - 1; + p->tex_offset = 0; + p->alu_end = ps->program.alu.length - 1; + p->alu_offset = 0; +} + diff --git a/src/mesa/drivers/dri/r300/r300_texprog.h b/src/mesa/drivers/dri/r300/r300_texprog.h new file mode 100644 index 00000000000..4e91a11699f --- /dev/null +++ b/src/mesa/drivers/dri/r300/r300_texprog.h @@ -0,0 +1,9 @@ +#ifndef __R300_TEXPROG_H_ +#define __R300_TEXPROG_H_ + +#include "r300_context.h" + +void r300GenerateTextureFragmentShader(r300ContextPtr r300); + +#endif +