Initial multitexturing support. Old behaviour can be re-enabled by changing ifdefs...
authorBen Skeggs <darktama@iinet.net.au>
Tue, 15 Mar 2005 17:00:44 +0000 (17:00 +0000)
committerBen Skeggs <darktama@iinet.net.au>
Tue, 15 Mar 2005 17:00:44 +0000 (17:00 +0000)
src/mesa/drivers/dri/r300/r300_context.h
src/mesa/drivers/dri/r300/r300_reg.h
src/mesa/drivers/dri/r300/r300_state.c
src/mesa/drivers/dri/r300/r300_texprog.c [new file with mode: 0644]
src/mesa/drivers/dri/r300/r300_texprog.h [new file with mode: 0644]

index 75aeb3eff71e1f8d3a06f70ed860db2abf6fac66..66eaa0f2b22c0cac20a3af75c7ab8deaa5471207 100644 (file)
@@ -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 {
index a9cb88cf97ac7c809bb721eedc0634446f4d5736..7242cbc892dfcd414f33a1d603d9a309ddb92c4b 100644 (file)
@@ -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
index c3c0120343737936aad5b84fc61bb8114097860a..aa9eb5e28bdc25ce49d0c79160030dd13bdcbd9f 100644 (file)
@@ -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<<i);
                        
-                       r300->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;i<ctx->Const.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<<i)) {
+                       r300->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;i<rmesa->state.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 (file)
index 0000000..bcc101e
--- /dev/null
@@ -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;i<ctx->Const.MaxTextureUnits;i++) {
+               if (r300->state.render_inputs & (_TNL_BIT_TEX0<<i)) {
+                       ps->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 (file)
index 0000000..4e91a11
--- /dev/null
@@ -0,0 +1,9 @@
+#ifndef __R300_TEXPROG_H_
+#define __R300_TEXPROG_H_
+
+#include "r300_context.h"
+
+void r300GenerateTextureFragmentShader(r300ContextPtr r300);
+
+#endif
+