aboutsummaryrefslogtreecommitdiff
path: root/nx-X11/extras/Mesa/src/mesa/drivers/dri/r300/r300_texprog.c
diff options
context:
space:
mode:
Diffstat (limited to 'nx-X11/extras/Mesa/src/mesa/drivers/dri/r300/r300_texprog.c')
-rw-r--r--nx-X11/extras/Mesa/src/mesa/drivers/dri/r300/r300_texprog.c270
1 files changed, 270 insertions, 0 deletions
diff --git a/nx-X11/extras/Mesa/src/mesa/drivers/dri/r300/r300_texprog.c b/nx-X11/extras/Mesa/src/mesa/drivers/dri/r300/r300_texprog.c
new file mode 100644
index 000000000..71d28db05
--- /dev/null
+++ b/nx-X11/extras/Mesa/src/mesa/drivers/dri/r300/r300_texprog.c
@@ -0,0 +1,270 @@
+#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"
+#if USE_ARB_F_P == 0
+#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 get_source(ps, GL_TEXTURE, unit, tc_reg);
+ break;
+ default:
+ WARN_ONCE("Unknown EnvMode == %d, name=%s\n", envmode,
+ _mesa_lookup_enum_by_nr(envmode));
+ return get_source(ps, GL_TEXTURE, unit, tc_reg);
+ 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;
+ GLuint OutputsWritten;
+
+ if(hw_tcl_on)
+ OutputsWritten = CURRENT_VERTEX_SHADER(ctx)->OutputsWritten;
+
+ 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 (TMU_ENABLED(ctx, 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;
+}
+#endif // USE_ARB_F_P == 0
+