LIBNAME = r300
C_SOURCES = \
+ r3xx_fs.c \
+ r5xx_fs.c \
r300_chipset.c \
r300_clear.c \
r300_context.c \
r300_debug.c \
r300_emit.c \
r300_flush.c \
+ r300_fs.c \
r300_query.c \
r300_render.c \
r300_screen.c \
r300_state.c \
r300_state_derived.c \
r300_state_invariant.c \
- r300_state_shader.c \
- r300_state_tcl.c \
+ r300_vs.c \
r300_surface.c \
r300_texture.c
r300 = env.ConvenienceLibrary(
target = 'r300',
source = [
+ 'r3xx_fs.c',
+ 'r5xx_fs.c',
'r300_chipset.c',
'r300_clear.c',
'r300_context.c',
'r300_debug.c',
'r300_emit.c',
'r300_flush.c',
+ 'r300_fs.c',
'r300_query.c',
'r300_render.c',
'r300_screen.c',
'r300_state.c',
'r300_state_derived.c',
'r300_state_invariant.c',
- 'r300_state_shader.c',
- 'r300_state_tcl.c',
+ 'r300_vs.c',
'r300_surface.c',
'r300_texture.c',
])
unsigned count;
};
-struct r3xx_fragment_shader {
+struct r300_fragment_shader {
/* Parent class */
struct pipe_shader_state state;
struct tgsi_shader_info info;
boolean uses_imms;
};
-struct r300_fragment_shader {
+struct r3xx_fragment_shader {
/* Parent class */
- struct r3xx_fragment_shader shader;
+ struct r300_fragment_shader shader;
/* Number of ALU instructions */
int alu_instruction_count;
} instructions[64]; /* XXX magic num */
};
-struct r500_fragment_shader {
+struct r5xx_fragment_shader {
/* Parent class */
- struct r3xx_fragment_shader shader;
+ struct r300_fragment_shader shader;
/* Number of used instructions */
int instruction_count;
/* Depth, stencil, and alpha state. */
struct r300_dsa_state* dsa_state;
/* Fragment shader. */
- struct r3xx_fragment_shader* fs;
+ struct r300_fragment_shader* fs;
/* Framebuffer state. We currently don't need our own version of this. */
struct pipe_framebuffer_state framebuffer_state;
/* Rasterizer state. */
#include "r300_debug.h"
-static void r300_dump_fs(struct r300_fragment_shader* fs)
+void r3xx_dump_fs(struct r3xx_fragment_shader* fs)
{
int i;
}
}
-void r500_fs_dump(struct r500_fragment_shader* fs)
+void r5xx_fs_dump(struct r5xx_fragment_shader* fs)
{
int i;
uint32_t inst;
inst & R500_INST_NOP ? "NOP" : "",
inst & R500_INST_ALU_WAIT ? "ALU_WAIT" : "");
debug_printf("wmask: %s omask: %s\n",
- r500_fs_mask[(inst >> 11) & 0xf],
- r500_fs_mask[(inst >> 15) & 0xf]);
+ r5xx_fs_mask[(inst >> 11) & 0xf],
+ r5xx_fs_mask[(inst >> 15) & 0xf]);
switch (inst & 0x3) {
case R500_INST_TYPE_ALU:
case R500_INST_TYPE_OUT:
debug_printf(" 3: RGB_INST 0x%08x:", inst);
debug_printf("rgb_A_src:%d %s/%s/%s %d "
"rgb_B_src:%d %s/%s/%s %d\n",
- inst & 0x3, r500_fs_swiz[(inst >> 2) & 0x7],
- r500_fs_swiz[(inst >> 5) & 0x7],
- r500_fs_swiz[(inst >> 8) & 0x7],
+ inst & 0x3, r5xx_fs_swiz[(inst >> 2) & 0x7],
+ r5xx_fs_swiz[(inst >> 5) & 0x7],
+ r5xx_fs_swiz[(inst >> 8) & 0x7],
(inst >> 11) & 0x3, (inst >> 13) & 0x3,
- r500_fs_swiz[(inst >> 15) & 0x7],
- r500_fs_swiz[(inst >> 18) & 0x7],
- r500_fs_swiz[(inst >> 21) & 0x7],
+ r5xx_fs_swiz[(inst >> 15) & 0x7],
+ r5xx_fs_swiz[(inst >> 18) & 0x7],
+ r5xx_fs_swiz[(inst >> 21) & 0x7],
(inst >> 24) & 0x3);
inst = fs->instructions[i].inst4;
debug_printf(" 4: ALPHA_INST 0x%08x:", inst);
debug_printf("%s dest:%d%s alp_A_src:%d %s %d "
"alp_B_src:%d %s %d w:%d\n",
- r500_fs_op_alpha[inst & 0xf], (inst >> 4) & 0x7f,
+ r5xx_fs_op_alpha[inst & 0xf], (inst >> 4) & 0x7f,
inst & (1<<11) ? "(rel)":"", (inst >> 12) & 0x3,
- r500_fs_swiz[(inst >> 14) & 0x7], (inst >> 17) & 0x3,
- (inst >> 19) & 0x3, r500_fs_swiz[(inst >> 21) & 0x7],
+ r5xx_fs_swiz[(inst >> 14) & 0x7], (inst >> 17) & 0x3,
+ (inst >> 19) & 0x3, r5xx_fs_swiz[(inst >> 21) & 0x7],
(inst >> 24) & 0x3, (inst >> 31) & 0x1);
inst = fs->instructions[i].inst5;
debug_printf(" 5: RGBA_INST 0x%08x:", inst);
debug_printf("%s dest:%d%s rgb_C_src:%d %s/%s/%s %d "
"alp_C_src:%d %s %d\n",
- r500_fs_op_rgb[inst & 0xf], (inst >> 4) & 0x7f,
+ r5xx_fs_op_rgb[inst & 0xf], (inst >> 4) & 0x7f,
inst & (1 << 11) ? "(rel)":"", (inst >> 12) & 0x3,
- r500_fs_swiz[(inst >> 14) & 0x7],
- r500_fs_swiz[(inst >> 17) & 0x7],
- r500_fs_swiz[(inst >> 20) & 0x7],
+ r5xx_fs_swiz[(inst >> 14) & 0x7],
+ r5xx_fs_swiz[(inst >> 17) & 0x7],
+ r5xx_fs_swiz[(inst >> 20) & 0x7],
(inst >> 23) & 0x3, (inst >> 25) & 0x3,
- r500_fs_swiz[(inst >> 27) & 0x7], (inst >> 30) & 0x3);
+ r5xx_fs_swiz[(inst >> 27) & 0x7], (inst >> 30) & 0x3);
break;
case R500_INST_TYPE_FC:
/* XXX don't even bother yet */
debug_printf(" 1: TEX_INST 0x%08x: id: %d "
"op:%s, %s, %s %s\n",
inst, (inst >> 16) & 0xf,
- r500_fs_tex[(inst >> 22) & 0x7],
+ r5xx_fs_tex[(inst >> 22) & 0x7],
(inst & (1 << 25)) ? "ACQ" : "",
(inst & (1 << 26)) ? "IGNUNC" : "",
(inst & (1 << 27)) ? "UNSCALED" : "SCALED");
debug_printf(" 2: TEX_ADDR 0x%08x: "
"src: %d%s %s/%s/%s/%s dst: %d%s %s/%s/%s/%s\n",
inst, inst & 0x7f, inst & (1 << 7) ? "(rel)" : "",
- r500_fs_swiz[(inst >> 8) & 0x3],
- r500_fs_swiz[(inst >> 10) & 0x3],
- r500_fs_swiz[(inst >> 12) & 0x3],
- r500_fs_swiz[(inst >> 14) & 0x3],
+ r5xx_fs_swiz[(inst >> 8) & 0x3],
+ r5xx_fs_swiz[(inst >> 10) & 0x3],
+ r5xx_fs_swiz[(inst >> 12) & 0x3],
+ r5xx_fs_swiz[(inst >> 14) & 0x3],
(inst >> 16) & 0x7f, inst & (1 << 23) ? "(rel)" : "",
- r500_fs_swiz[(inst >> 24) & 0x3],
- r500_fs_swiz[(inst >> 26) & 0x3],
- r500_fs_swiz[(inst >> 28) & 0x3],
- r500_fs_swiz[(inst >> 30) & 0x3]);
+ r5xx_fs_swiz[(inst >> 24) & 0x3],
+ r5xx_fs_swiz[(inst >> 26) & 0x3],
+ r5xx_fs_swiz[(inst >> 28) & 0x3],
+ r5xx_fs_swiz[(inst >> 30) & 0x3]);
inst = fs->instructions[i].inst3;
debug_printf(" 3: TEX_DXDY 0x%08x\n", inst);
#define R300_DEBUG_H
#include "r300_reg.h"
-#include "r300_state_shader.h"
-#include "r300_state_tcl.h"
+#include "r300_fs.h"
+#include "r300_vs.h"
-static char* r500_fs_swiz[] = {
+static char* r5xx_fs_swiz[] = {
" R",
" G",
" B",
" U",
};
-static char* r500_fs_op_rgb[] = {
+static char* r5xx_fs_op_rgb[] = {
"MAD",
"DP3",
"DP4",
"MDV",
};
-static char* r500_fs_op_alpha[] = {
+static char* r5xx_fs_op_alpha[] = {
"MAD",
" DP",
"MIN",
"MDV",
};
-static char* r500_fs_mask[] = {
+static char* r5xx_fs_mask[] = {
"NONE",
"R ",
" G ",
"RGBA",
};
-static char* r500_fs_tex[] = {
+static char* r5xx_fs_tex[] = {
" NOP",
" LD",
"TEXKILL",
"U",
};
-void r500_fs_dump(struct r500_fragment_shader* fs);
+void r5xx_fs_dump(struct r5xx_fragment_shader* fs);
+void r3xx_dump_fs(struct r3xx_fragment_shader* fs);
void r300_vs_dump(struct r300_vertex_shader* vs);
}
void r300_emit_fragment_shader(struct r300_context* r300,
- struct r300_fragment_shader* fs)
+ struct r3xx_fragment_shader* fs)
{
int i;
CS_LOCALS(r300);
}
void r500_emit_fragment_shader(struct r300_context* r300,
- struct r500_fragment_shader* fs)
+ struct r5xx_fragment_shader* fs)
{
int i;
struct r300_constant_buffer* constants =
if (r300->dirty_state & R300_NEW_FRAGMENT_SHADER) {
if (r300screen->caps->is_r500) {
r500_emit_fragment_shader(r300,
- (struct r500_fragment_shader*)r300->fs);
+ (struct r5xx_fragment_shader*)r300->fs);
} else {
r300_emit_fragment_shader(r300,
- (struct r300_fragment_shader*)r300->fs);
+ (struct r3xx_fragment_shader*)r300->fs);
}
r300->dirty_state &= ~R300_NEW_FRAGMENT_SHADER;
}
struct r300_dsa_state* dsa);
void r300_emit_fragment_shader(struct r300_context* r300,
- struct r300_fragment_shader* fs);
+ struct r3xx_fragment_shader* fs);
void r500_emit_fragment_shader(struct r300_context* r300,
- struct r500_fragment_shader* fs);
+ struct r5xx_fragment_shader* fs);
void r300_emit_fb_state(struct r300_context* r300,
struct pipe_framebuffer_state* fb);
--- /dev/null
+/*
+ * Copyright 2008 Corbin Simpson <MostAwesomeDude@gmail.com>
+ * Joakim Sindholt <opensource@zhasha.com>
+ *
+ * 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
+ * on the rights to use, copy, modify, merge, publish, distribute, sub
+ * license, 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 (including the next
+ * paragraph) 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 NON-INFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHOR(S) AND/OR THEIR SUPPLIERS 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 "r300_fs.h"
+
+void r300_translate_fragment_shader(struct r300_context* r300,
+ struct r300_fragment_shader* fs)
+{
+ struct tgsi_parse_context parser;
+ int i;
+ boolean is_r500 = r300_screen(r300->context.screen)->caps->is_r500;
+ struct r300_constant_buffer* consts =
+ &r300->shader_constants[PIPE_SHADER_FRAGMENT];
+
+ struct r300_fs_asm* assembler = CALLOC_STRUCT(r300_fs_asm);
+ if (assembler == NULL) {
+ return;
+ }
+ /* Setup starting offset for immediates. */
+ assembler->imm_offset = consts->user_count;
+ /* Enable depth writes, if needed. */
+ assembler->writes_depth = fs->info.writes_z;
+
+ /* Make sure we start at the beginning of the shader. */
+ if (is_r500) {
+ ((struct r5xx_fragment_shader*)fs)->instruction_count = 0;
+ }
+
+ tgsi_parse_init(&parser, fs->state.tokens);
+
+ while (!tgsi_parse_end_of_tokens(&parser)) {
+ tgsi_parse_token(&parser);
+
+ /* This is seriously the lamest way to create fragment programs ever.
+ * I blame TGSI. */
+ switch (parser.FullToken.Token.Type) {
+ case TGSI_TOKEN_TYPE_DECLARATION:
+ /* Allocated registers sitting at the beginning
+ * of the program. */
+ r300_fs_declare(assembler, &parser.FullToken.FullDeclaration);
+ break;
+ case TGSI_TOKEN_TYPE_IMMEDIATE:
+ debug_printf("r300: Emitting immediate to constant buffer, "
+ "position %d\n",
+ assembler->imm_offset + assembler->imm_count);
+ /* I am not amused by the length of these. */
+ for (i = 0; i < 4; i++) {
+ consts->constants[assembler->imm_offset +
+ assembler->imm_count][i] =
+ parser.FullToken.FullImmediate.u.ImmediateFloat32[i]
+ .Float;
+ }
+ assembler->imm_count++;
+ break;
+ case TGSI_TOKEN_TYPE_INSTRUCTION:
+ if (is_r500) {
+ r5xx_fs_instruction((struct r5xx_fragment_shader*)fs,
+ assembler, &parser.FullToken.FullInstruction);
+ } else {
+ r3xx_fs_instruction((struct r3xx_fragment_shader*)fs,
+ assembler, &parser.FullToken.FullInstruction);
+ }
+ break;
+ }
+ }
+
+ debug_printf("r300: fs: %d texs and %d colors, first free reg is %d\n",
+ assembler->tex_count, assembler->color_count,
+ assembler->tex_count + assembler->color_count);
+
+ consts->count = consts->user_count + assembler->imm_count;
+ fs->uses_imms = assembler->imm_count;
+ debug_printf("r300: fs: %d total constants, "
+ "%d from user and %d from immediates\n", consts->count,
+ consts->user_count, assembler->imm_count);
+ r3xx_fs_finalize(fs, assembler);
+ if (is_r500) {
+ r5xx_fs_finalize((struct r5xx_fragment_shader*)fs, assembler);
+ }
+
+ tgsi_dump(fs->state.tokens, 0);
+ /* XXX finish r300 dumper too */
+ if (is_r500) {
+ r5xx_fs_dump((struct r5xx_fragment_shader*)fs);
+ }
+
+ tgsi_parse_free(&parser);
+ FREE(assembler);
+}
--- /dev/null
+/*
+ * Copyright 2008 Corbin Simpson <MostAwesomeDude@gmail.com>
+ * Joakim Sindholt <opensource@zhasha.com>
+ *
+ * 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
+ * on the rights to use, copy, modify, merge, publish, distribute, sub
+ * license, 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 (including the next
+ * paragraph) 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 NON-INFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHOR(S) AND/OR THEIR SUPPLIERS 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 R300_FS_H
+#define R300_FS_H
+
+#include "tgsi/tgsi_dump.h"
+
+#include "r300_context.h"
+#include "r3xx_fs.h"
+#include "r5xx_fs.h"
+
+void r300_translate_fragment_shader(struct r300_context* r300,
+ struct r300_fragment_shader* fs);
+
+ #endif /* R300_FS_H */
--- /dev/null
+/*
+ * Copyright 2008 Corbin Simpson <MostAwesomeDude@gmail.com>
+ * Joakim Sindholt <opensource@zhasha.com>
+ *
+ * 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
+ * on the rights to use, copy, modify, merge, publish, distribute, sub
+ * license, 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 (including the next
+ * paragraph) 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 NON-INFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHOR(S) AND/OR THEIR SUPPLIERS 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 R300_FS_INLINES_H
+#define R300_FS_INLINES_H
+
+#include "tgsi/tgsi_parse.h"
+
+#include "r300_context.h"
+#include "r300_debug.h"
+#include "r300_reg.h"
+#include "r300_screen.h"
+#include "r300_shader_inlines.h"
+
+/* Temporary struct used to hold assembly state while putting together
+ * fragment programs. */
+struct r300_fs_asm {
+ /* Pipe context. */
+ struct r300_context* r300;
+ /* Number of colors. */
+ unsigned color_count;
+ /* Number of texcoords. */
+ unsigned tex_count;
+ /* Offset for temporary registers. Inputs and temporaries have no
+ * distinguishing markings, so inputs start at 0 and the first usable
+ * temporary register is after all inputs. */
+ unsigned temp_offset;
+ /* Number of requested temporary registers. */
+ unsigned temp_count;
+ /* Offset for immediate constants. Neither R300 nor R500 can do four
+ * inline constants per source, so instead we copy immediates into the
+ * constant buffer. */
+ unsigned imm_offset;
+ /* Number of immediate constants. */
+ unsigned imm_count;
+ /* Are depth writes enabled? */
+ boolean writes_depth;
+ /* Depth write offset. This is the TGSI output that corresponds to
+ * depth writes. */
+ unsigned depth_output;
+};
+
+static INLINE void r300_fs_declare(struct r300_fs_asm* assembler,
+ struct tgsi_full_declaration* decl)
+{
+ switch (decl->Declaration.File) {
+ case TGSI_FILE_INPUT:
+ switch (decl->Semantic.SemanticName) {
+ case TGSI_SEMANTIC_COLOR:
+ assembler->color_count++;
+ break;
+ case TGSI_SEMANTIC_FOG:
+ case TGSI_SEMANTIC_GENERIC:
+ assembler->tex_count++;
+ break;
+ default:
+ debug_printf("r300: fs: Bad semantic declaration %d\n",
+ decl->Semantic.SemanticName);
+ break;
+ }
+ break;
+ case TGSI_FILE_OUTPUT:
+ /* Depth write. Mark the position of the output so we can
+ * identify it later. */
+ if (decl->Semantic.SemanticName == TGSI_SEMANTIC_POSITION) {
+ assembler->depth_output = decl->DeclarationRange.First;
+ }
+ break;
+ case TGSI_FILE_CONSTANT:
+ break;
+ case TGSI_FILE_TEMPORARY:
+ assembler->temp_count++;
+ break;
+ default:
+ debug_printf("r300: fs: Bad file %d\n", decl->Declaration.File);
+ break;
+ }
+
+ assembler->temp_offset = assembler->color_count + assembler->tex_count;
+}
+
+static INLINE unsigned r300_fs_src(struct r300_fs_asm* assembler,
+ struct tgsi_src_register* src)
+{
+ switch (src->File) {
+ case TGSI_FILE_NULL:
+ return 0;
+ case TGSI_FILE_INPUT:
+ /* XXX may be wrong */
+ return src->Index;
+ break;
+ case TGSI_FILE_TEMPORARY:
+ return src->Index + assembler->temp_offset;
+ break;
+ case TGSI_FILE_IMMEDIATE:
+ return (src->Index + assembler->imm_offset) | (1 << 8);
+ break;
+ case TGSI_FILE_CONSTANT:
+ /* XXX magic */
+ return src->Index | (1 << 8);
+ break;
+ default:
+ debug_printf("r300: fs: Unimplemented src %d\n", src->File);
+ break;
+ }
+ return 0;
+}
+
+static INLINE unsigned r300_fs_dst(struct r300_fs_asm* assembler,
+ struct tgsi_dst_register* dst)
+{
+ switch (dst->File) {
+ case TGSI_FILE_NULL:
+ /* This happens during KIL instructions. */
+ return 0;
+ break;
+ case TGSI_FILE_OUTPUT:
+ return 0;
+ break;
+ case TGSI_FILE_TEMPORARY:
+ return dst->Index + assembler->temp_offset;
+ break;
+ default:
+ debug_printf("r300: fs: Unimplemented dst %d\n", dst->File);
+ break;
+ }
+ return 0;
+}
+
+static INLINE boolean r300_fs_is_depr(struct r300_fs_asm* assembler,
+ struct tgsi_dst_register* dst)
+{
+ return (assembler->writes_depth &&
+ (dst->File == TGSI_FILE_OUTPUT) &&
+ (dst->Index == assembler->depth_output));
+}
+
+#endif /* R300_FS_INLINES_H */
--- /dev/null
+/*
+ * Copyright 2009 Corbin Simpson <MostAwesomeDude@gmail.com>
+ * Joakim Sindholt <opensource@zhasha.com>
+ *
+ * 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
+ * on the rights to use, copy, modify, merge, publish, distribute, sub
+ * license, 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 (including the next
+ * paragraph) 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 NON-INFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHOR(S) AND/OR THEIR SUPPLIERS 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 R300_SHADER_INLINES_H
+#define R300_SHADER_INLINES_H
+
+/* TGSI constants. TGSI is like XML: If it can't solve your problems, you're
+ * not using enough of it. */
+static const struct tgsi_full_src_register r300_constant_zero = {
+ .SrcRegister.Extended = TRUE,
+ .SrcRegister.File = TGSI_FILE_NULL,
+ .SrcRegisterExtSwz.ExtSwizzleX = TGSI_EXTSWIZZLE_ZERO,
+ .SrcRegisterExtSwz.ExtSwizzleY = TGSI_EXTSWIZZLE_ZERO,
+ .SrcRegisterExtSwz.ExtSwizzleZ = TGSI_EXTSWIZZLE_ZERO,
+ .SrcRegisterExtSwz.ExtSwizzleW = TGSI_EXTSWIZZLE_ZERO,
+};
+
+static const struct tgsi_full_src_register r300_constant_one = {
+ .SrcRegister.Extended = TRUE,
+ .SrcRegister.File = TGSI_FILE_NULL,
+ .SrcRegisterExtSwz.ExtSwizzleX = TGSI_EXTSWIZZLE_ONE,
+ .SrcRegisterExtSwz.ExtSwizzleY = TGSI_EXTSWIZZLE_ONE,
+ .SrcRegisterExtSwz.ExtSwizzleZ = TGSI_EXTSWIZZLE_ONE,
+ .SrcRegisterExtSwz.ExtSwizzleW = TGSI_EXTSWIZZLE_ONE,
+};
+
+#endif /* R300_SHADER_INLINES_H */
#include "r300_context.h"
#include "r300_reg.h"
#include "r300_state_inlines.h"
-#include "r300_state_shader.h"
+#include "r300_fs.h"
/* r300_state: Functions used to intialize state context by translating
* Gallium state objects into semi-native r300 state objects. */
const struct pipe_shader_state* shader)
{
struct r300_context* r300 = r300_context(pipe);
- struct r3xx_fragment_shader* fs = NULL;
+ struct r300_fragment_shader* fs = NULL;
if (r300_screen(r300->context.screen)->caps->is_r500) {
- fs =
- (struct r3xx_fragment_shader*)CALLOC_STRUCT(r500_fragment_shader);
+ fs = (struct r300_fragment_shader*)CALLOC_STRUCT(r5xx_fragment_shader);
} else {
- fs =
- (struct r3xx_fragment_shader*)CALLOC_STRUCT(r300_fragment_shader);
+ fs = (struct r300_fragment_shader*)CALLOC_STRUCT(r3xx_fragment_shader);
}
/* Copy state directly into shader. */
static void r300_bind_fs_state(struct pipe_context* pipe, void* shader)
{
struct r300_context* r300 = r300_context(pipe);
- struct r3xx_fragment_shader* fs = (struct r3xx_fragment_shader*)shader;
+ struct r300_fragment_shader* fs = (struct r300_fragment_shader*)shader;
if (fs == NULL) {
r300->fs = NULL;
/* Delete fragment shader state. */
static void r300_delete_fs_state(struct pipe_context* pipe, void* shader)
{
- struct r3xx_fragment_shader* fs = (struct r3xx_fragment_shader*)shader;
+ struct r300_fragment_shader* fs = (struct r300_fragment_shader*)shader;
FREE(fs->state.tokens);
FREE(shader);
}
+++ /dev/null
-/*
- * Copyright 2008 Corbin Simpson <MostAwesomeDude@gmail.com>
- *
- * 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
- * on the rights to use, copy, modify, merge, publish, distribute, sub
- * license, 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 (including the next
- * paragraph) 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 NON-INFRINGEMENT. IN NO EVENT SHALL
- * THE AUTHOR(S) AND/OR THEIR SUPPLIERS 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 "r300_state_shader.h"
-
-static void r300_fs_declare(struct r300_fs_asm* assembler,
- struct tgsi_full_declaration* decl)
-{
- switch (decl->Declaration.File) {
- case TGSI_FILE_INPUT:
- switch (decl->Semantic.SemanticName) {
- case TGSI_SEMANTIC_COLOR:
- assembler->color_count++;
- break;
- case TGSI_SEMANTIC_FOG:
- case TGSI_SEMANTIC_GENERIC:
- assembler->tex_count++;
- break;
- default:
- debug_printf("r300: fs: Bad semantic declaration %d\n",
- decl->Semantic.SemanticName);
- break;
- }
- break;
- case TGSI_FILE_OUTPUT:
- /* Depth write. Mark the position of the output so we can
- * identify it later. */
- if (decl->Semantic.SemanticName == TGSI_SEMANTIC_POSITION) {
- assembler->depth_output = decl->DeclarationRange.First;
- }
- break;
- case TGSI_FILE_CONSTANT:
- break;
- case TGSI_FILE_TEMPORARY:
- assembler->temp_count++;
- break;
- default:
- debug_printf("r300: fs: Bad file %d\n", decl->Declaration.File);
- break;
- }
-
- assembler->temp_offset = assembler->color_count + assembler->tex_count;
-}
-
-static INLINE unsigned r300_fs_src(struct r300_fs_asm* assembler,
- struct tgsi_src_register* src)
-{
- switch (src->File) {
- case TGSI_FILE_NULL:
- return 0;
- case TGSI_FILE_INPUT:
- /* XXX may be wrong */
- return src->Index;
- break;
- case TGSI_FILE_TEMPORARY:
- return src->Index + assembler->temp_offset;
- break;
- case TGSI_FILE_IMMEDIATE:
- return (src->Index + assembler->imm_offset) | (1 << 8);
- break;
- case TGSI_FILE_CONSTANT:
- /* XXX magic */
- return src->Index | (1 << 8);
- break;
- default:
- debug_printf("r300: fs: Unimplemented src %d\n", src->File);
- break;
- }
- return 0;
-}
-
-static INLINE unsigned r300_fs_dst(struct r300_fs_asm* assembler,
- struct tgsi_dst_register* dst)
-{
- switch (dst->File) {
- case TGSI_FILE_NULL:
- /* This happens during KIL instructions. */
- return 0;
- break;
- case TGSI_FILE_OUTPUT:
- return 0;
- break;
- case TGSI_FILE_TEMPORARY:
- return dst->Index + assembler->temp_offset;
- break;
- default:
- debug_printf("r300: fs: Unimplemented dst %d\n", dst->File);
- break;
- }
- return 0;
-}
-
-static INLINE boolean r300_fs_is_depr(struct r300_fs_asm* assembler,
- struct tgsi_dst_register* dst)
-{
- return (assembler->writes_depth &&
- (dst->File == TGSI_FILE_OUTPUT) &&
- (dst->Index == assembler->depth_output));
-}
-
-static INLINE unsigned r500_fix_swiz(unsigned s)
-{
- /* For historical reasons, the swizzle values x, y, z, w, and 0 are
- * equivalent to the actual machine code, but 1 is not. Thus, we just
- * adjust it a bit... */
- if (s == TGSI_EXTSWIZZLE_ONE) {
- return R500_SWIZZLE_ONE;
- } else {
- return s;
- }
-}
-
-static uint32_t r500_rgba_swiz(struct tgsi_full_src_register* reg)
-{
- if (reg->SrcRegister.Extended) {
- return r500_fix_swiz(reg->SrcRegisterExtSwz.ExtSwizzleX) |
- (r500_fix_swiz(reg->SrcRegisterExtSwz.ExtSwizzleY) << 3) |
- (r500_fix_swiz(reg->SrcRegisterExtSwz.ExtSwizzleZ) << 6) |
- (r500_fix_swiz(reg->SrcRegisterExtSwz.ExtSwizzleW) << 9);
- } else {
- return reg->SrcRegister.SwizzleX |
- (reg->SrcRegister.SwizzleY << 3) |
- (reg->SrcRegister.SwizzleZ << 6) |
- (reg->SrcRegister.SwizzleW << 9);
- }
-}
-
-static uint32_t r500_strq_swiz(struct tgsi_full_src_register* reg)
-{
- return reg->SrcRegister.SwizzleX |
- (reg->SrcRegister.SwizzleY << 2) |
- (reg->SrcRegister.SwizzleZ << 4) |
- (reg->SrcRegister.SwizzleW << 6);
-}
-
-static INLINE uint32_t r500_rgb_swiz(struct tgsi_full_src_register* reg)
-{
- /* Only the first 9 bits... */
- return (r500_rgba_swiz(reg) & 0x1ff) |
- (reg->SrcRegister.Negate ? (1 << 9) : 0) |
- (reg->SrcRegisterExtMod.Absolute ? (1 << 10) : 0);
-}
-
-static INLINE uint32_t r500_alpha_swiz(struct tgsi_full_src_register* reg)
-{
- /* Only the last 3 bits... */
- return (r500_rgba_swiz(reg) >> 9) |
- (reg->SrcRegister.Negate ? (1 << 9) : 0) |
- (reg->SrcRegisterExtMod.Absolute ? (1 << 10) : 0);
-}
-
-static INLINE uint32_t r300_rgb_op(unsigned op)
-{
- switch (op) {
- case TGSI_OPCODE_MOV:
- return R300_ALU_OUTC_CMP;
- default:
- return 0;
- }
-}
-
-static INLINE uint32_t r300_alpha_op(unsigned op)
-{
- switch (op) {
- case TGSI_OPCODE_MOV:
- return R300_ALU_OUTA_CMP;
- default:
- return 0;
- }
-}
-
-static INLINE uint32_t r500_rgba_op(unsigned op)
-{
- switch (op) {
- case TGSI_OPCODE_COS:
- case TGSI_OPCODE_EX2:
- case TGSI_OPCODE_LG2:
- case TGSI_OPCODE_RCP:
- case TGSI_OPCODE_RSQ:
- case TGSI_OPCODE_SIN:
- return R500_ALU_RGBA_OP_SOP;
- case TGSI_OPCODE_DDX:
- return R500_ALU_RGBA_OP_MDH;
- case TGSI_OPCODE_DDY:
- return R500_ALU_RGBA_OP_MDV;
- case TGSI_OPCODE_FRC:
- return R500_ALU_RGBA_OP_FRC;
- case TGSI_OPCODE_DP3:
- return R500_ALU_RGBA_OP_DP3;
- case TGSI_OPCODE_DP4:
- case TGSI_OPCODE_DPH:
- return R500_ALU_RGBA_OP_DP4;
- case TGSI_OPCODE_ABS:
- case TGSI_OPCODE_CMP:
- case TGSI_OPCODE_MOV:
- case TGSI_OPCODE_SWZ:
- return R500_ALU_RGBA_OP_CMP;
- case TGSI_OPCODE_ADD:
- case TGSI_OPCODE_MAD:
- case TGSI_OPCODE_MUL:
- case TGSI_OPCODE_SUB:
- return R500_ALU_RGBA_OP_MAD;
- default:
- return 0;
- }
-}
-
-static INLINE uint32_t r500_alpha_op(unsigned op)
-{
- switch (op) {
- case TGSI_OPCODE_COS:
- return R500_ALPHA_OP_COS;
- case TGSI_OPCODE_EX2:
- return R500_ALPHA_OP_EX2;
- case TGSI_OPCODE_LG2:
- return R500_ALPHA_OP_LN2;
- case TGSI_OPCODE_RCP:
- return R500_ALPHA_OP_RCP;
- case TGSI_OPCODE_RSQ:
- return R500_ALPHA_OP_RSQ;
- case TGSI_OPCODE_FRC:
- return R500_ALPHA_OP_FRC;
- case TGSI_OPCODE_SIN:
- return R500_ALPHA_OP_SIN;
- case TGSI_OPCODE_DDX:
- return R500_ALPHA_OP_MDH;
- case TGSI_OPCODE_DDY:
- return R500_ALPHA_OP_MDV;
- case TGSI_OPCODE_DP3:
- case TGSI_OPCODE_DP4:
- case TGSI_OPCODE_DPH:
- return R500_ALPHA_OP_DP;
- case TGSI_OPCODE_ABS:
- case TGSI_OPCODE_CMP:
- case TGSI_OPCODE_MOV:
- case TGSI_OPCODE_SWZ:
- return R500_ALPHA_OP_CMP;
- case TGSI_OPCODE_ADD:
- case TGSI_OPCODE_MAD:
- case TGSI_OPCODE_MUL:
- case TGSI_OPCODE_SUB:
- return R500_ALPHA_OP_MAD;
- default:
- return 0;
- }
-}
-
-static INLINE uint32_t r500_tex_op(unsigned op)
-{
- switch (op) {
- case TGSI_OPCODE_KIL:
- return R500_TEX_INST_TEXKILL;
- case TGSI_OPCODE_TEX:
- return R500_TEX_INST_LD;
- case TGSI_OPCODE_TXB:
- return R500_TEX_INST_LODBIAS;
- case TGSI_OPCODE_TXP:
- return R500_TEX_INST_PROJ;
- default:
- return 0;
- }
-}
-
-static INLINE void r300_emit_maths(struct r300_fragment_shader* fs,
- struct r300_fs_asm* assembler,
- struct tgsi_full_src_register* src,
- struct tgsi_full_dst_register* dst,
- unsigned op,
- unsigned count)
-{
- int i = fs->alu_instruction_count;
-
- fs->instructions[i].alu_rgb_inst = R300_RGB_SWIZA(R300_ALU_ARGC_SRC0C_XYZ) |
- R300_RGB_SWIZB(R300_ALU_ARGC_SRC0C_XYZ) |
- R300_RGB_SWIZC(R300_ALU_ARGC_ZERO) |
- r300_rgb_op(op);
- fs->instructions[i].alu_rgb_addr = R300_RGB_ADDR0(0) | R300_RGB_ADDR1(0) |
- R300_RGB_ADDR2(0) | R300_ALU_DSTC_OUTPUT_XYZ;
- fs->instructions[i].alu_alpha_inst = R300_ALPHA_SWIZA(R300_ALU_ARGA_SRC0A) |
- R300_ALPHA_SWIZB(R300_ALU_ARGA_SRC0A) |
- R300_ALPHA_SWIZC(R300_ALU_ARGA_ZERO) |
- r300_alpha_op(op);
- fs->instructions[i].alu_alpha_addr = R300_ALPHA_ADDR0(0) |
- R300_ALPHA_ADDR1(0) | R300_ALPHA_ADDR2(0) | R300_ALU_DSTA_OUTPUT;
-
- fs->alu_instruction_count++;
-}
-
-/* Setup an ALU operation. */
-static INLINE void r500_emit_maths(struct r500_fragment_shader* fs,
- struct r300_fs_asm* assembler,
- struct tgsi_full_src_register* src,
- struct tgsi_full_dst_register* dst,
- unsigned op,
- unsigned count)
-{
- int i = fs->instruction_count;
-
- if (dst->DstRegister.File == TGSI_FILE_OUTPUT) {
- fs->instructions[i].inst0 = R500_INST_TYPE_OUT;
- if (r300_fs_is_depr(assembler, dst)) {
- fs->instructions[i].inst4 = R500_W_OMASK;
- } else {
- fs->instructions[i].inst0 |=
- R500_ALU_OMASK(dst->DstRegister.WriteMask);
- }
- } else {
- fs->instructions[i].inst0 = R500_INST_TYPE_ALU |
- R500_ALU_WMASK(dst->DstRegister.WriteMask);
- }
-
- fs->instructions[i].inst0 |= R500_INST_TEX_SEM_WAIT;
-
- fs->instructions[i].inst4 |=
- R500_ALPHA_ADDRD(r300_fs_dst(assembler, &dst->DstRegister));
- fs->instructions[i].inst5 =
- R500_ALU_RGBA_ADDRD(r300_fs_dst(assembler, &dst->DstRegister));
-
- switch (count) {
- case 3:
- fs->instructions[i].inst1 =
- R500_RGB_ADDR2(r300_fs_src(assembler, &src[2].SrcRegister));
- fs->instructions[i].inst2 =
- R500_ALPHA_ADDR2(r300_fs_src(assembler, &src[2].SrcRegister));
- fs->instructions[i].inst5 |=
- R500_ALU_RGBA_SEL_C_SRC2 |
- R500_SWIZ_RGBA_C(r500_rgb_swiz(&src[2])) |
- R500_ALU_RGBA_ALPHA_SEL_C_SRC2 |
- R500_SWIZ_ALPHA_C(r500_alpha_swiz(&src[2]));
- case 2:
- fs->instructions[i].inst1 |=
- R500_RGB_ADDR1(r300_fs_src(assembler, &src[1].SrcRegister));
- fs->instructions[i].inst2 |=
- R500_ALPHA_ADDR1(r300_fs_src(assembler, &src[1].SrcRegister));
- fs->instructions[i].inst3 =
- R500_ALU_RGB_SEL_B_SRC1 |
- R500_SWIZ_RGB_B(r500_rgb_swiz(&src[1]));
- fs->instructions[i].inst4 |=
- R500_ALPHA_SEL_B_SRC1 |
- R500_SWIZ_ALPHA_B(r500_alpha_swiz(&src[1]));
- case 1:
- case 0:
- default:
- fs->instructions[i].inst1 |=
- R500_RGB_ADDR0(r300_fs_src(assembler, &src[0].SrcRegister));
- fs->instructions[i].inst2 |=
- R500_ALPHA_ADDR0(r300_fs_src(assembler, &src[0].SrcRegister));
- fs->instructions[i].inst3 |=
- R500_ALU_RGB_SEL_A_SRC0 |
- R500_SWIZ_RGB_A(r500_rgb_swiz(&src[0]));
- fs->instructions[i].inst4 |=
- R500_ALPHA_SEL_A_SRC0 |
- R500_SWIZ_ALPHA_A(r500_alpha_swiz(&src[0]));
- break;
- }
-
- fs->instructions[i].inst4 |= r500_alpha_op(op);
- fs->instructions[i].inst5 |= r500_rgba_op(op);
-
- fs->instruction_count++;
-}
-
-static INLINE void r500_emit_tex(struct r500_fragment_shader* fs,
- struct r300_fs_asm* assembler,
- struct tgsi_full_src_register* src,
- struct tgsi_full_dst_register* dst,
- uint32_t op)
-{
- int i = fs->instruction_count;
-
- fs->instructions[i].inst0 = R500_INST_TYPE_TEX |
- R500_TEX_WMASK(dst->DstRegister.WriteMask) |
- R500_INST_TEX_SEM_WAIT;
- fs->instructions[i].inst1 = R500_TEX_ID(0) |
- R500_TEX_SEM_ACQUIRE | //R500_TEX_IGNORE_UNCOVERED |
- r500_tex_op(op);
- fs->instructions[i].inst2 =
- R500_TEX_SRC_ADDR(r300_fs_src(assembler, &src->SrcRegister)) |
- R500_SWIZ_TEX_STRQ(r500_strq_swiz(src)) |
- R500_TEX_DST_ADDR(r300_fs_dst(assembler, &dst->DstRegister)) |
- R500_TEX_DST_R_SWIZ_R | R500_TEX_DST_G_SWIZ_G |
- R500_TEX_DST_B_SWIZ_B | R500_TEX_DST_A_SWIZ_A;
-
- if (dst->DstRegister.File == TGSI_FILE_OUTPUT) {
- fs->instructions[i].inst2 |=
- R500_TEX_DST_ADDR(assembler->temp_count +
- assembler->temp_offset);
-
- fs->instruction_count++;
-
- /* Setup and emit a MOV. */
- src[0].SrcRegister.Index = assembler->temp_count;
- src[0].SrcRegister.File = TGSI_FILE_TEMPORARY;
-
- src[1] = src[0];
- src[2] = r500_constant_zero;
- r500_emit_maths(fs, assembler, src, dst, TGSI_OPCODE_MOV, 3);
- } else {
- fs->instruction_count++;
- }
-}
-
-static void r300_fs_instruction(struct r300_fragment_shader* fs,
- struct r300_fs_asm* assembler,
- struct tgsi_full_instruction* inst)
-{
- switch (inst->Instruction.Opcode) {
- case TGSI_OPCODE_MOV:
- /* src0 -> src1 and src2 forced to zero */
- inst->FullSrcRegisters[1] = inst->FullSrcRegisters[0];
- inst->FullSrcRegisters[2] = r500_constant_zero;
- r300_emit_maths(fs, assembler, inst->FullSrcRegisters,
- &inst->FullDstRegisters[0], inst->Instruction.Opcode, 3);
- break;
- case TGSI_OPCODE_END:
- break;
- default:
- debug_printf("r300: fs: Bad opcode %d\n",
- inst->Instruction.Opcode);
- break;
- }
-}
-
-static void r500_fs_instruction(struct r500_fragment_shader* fs,
- struct r300_fs_asm* assembler,
- struct tgsi_full_instruction* inst)
-{
- /* Switch between opcodes. When possible, prefer using the official
- * AMD/ATI names for opcodes, please, as it facilitates using the
- * documentation. */
- switch (inst->Instruction.Opcode) {
- /* XXX trig needs extra prep */
- case TGSI_OPCODE_COS:
- case TGSI_OPCODE_SIN:
- /* The simple scalar ops. */
- case TGSI_OPCODE_EX2:
- case TGSI_OPCODE_LG2:
- case TGSI_OPCODE_RCP:
- case TGSI_OPCODE_RSQ:
- /* Copy red swizzle to alpha for src0 */
- inst->FullSrcRegisters[0].SrcRegisterExtSwz.ExtSwizzleW =
- inst->FullSrcRegisters[0].SrcRegisterExtSwz.ExtSwizzleX;
- inst->FullSrcRegisters[0].SrcRegister.SwizzleW =
- inst->FullSrcRegisters[0].SrcRegister.SwizzleX;
- /* Fall through */
- case TGSI_OPCODE_DDX:
- case TGSI_OPCODE_DDY:
- case TGSI_OPCODE_FRC:
- r500_emit_maths(fs, assembler, inst->FullSrcRegisters,
- &inst->FullDstRegisters[0], inst->Instruction.Opcode, 1);
- break;
-
- /* The dot products. */
- case TGSI_OPCODE_DPH:
- /* Set alpha swizzle to one for src0 */
- if (!inst->FullSrcRegisters[0].SrcRegister.Extended) {
- inst->FullSrcRegisters[0].SrcRegister.Extended = TRUE;
- inst->FullSrcRegisters[0].SrcRegisterExtSwz.ExtSwizzleX =
- inst->FullSrcRegisters[0].SrcRegister.SwizzleX;
- inst->FullSrcRegisters[0].SrcRegisterExtSwz.ExtSwizzleY =
- inst->FullSrcRegisters[0].SrcRegister.SwizzleY;
- inst->FullSrcRegisters[0].SrcRegisterExtSwz.ExtSwizzleZ =
- inst->FullSrcRegisters[0].SrcRegister.SwizzleZ;
- }
- inst->FullSrcRegisters[0].SrcRegisterExtSwz.ExtSwizzleW =
- TGSI_EXTSWIZZLE_ONE;
- /* Fall through */
- case TGSI_OPCODE_DP3:
- case TGSI_OPCODE_DP4:
- r500_emit_maths(fs, assembler, inst->FullSrcRegisters,
- &inst->FullDstRegisters[0], inst->Instruction.Opcode, 2);
- break;
-
- /* Simple three-source operations. */
- case TGSI_OPCODE_CMP:
- /* Swap src0 and src2 */
- inst->FullSrcRegisters[3] = inst->FullSrcRegisters[2];
- inst->FullSrcRegisters[2] = inst->FullSrcRegisters[0];
- inst->FullSrcRegisters[0] = inst->FullSrcRegisters[3];
- r500_emit_maths(fs, assembler, inst->FullSrcRegisters,
- &inst->FullDstRegisters[0], inst->Instruction.Opcode, 3);
- break;
-
- /* The MAD variants. */
- case TGSI_OPCODE_SUB:
- /* Just like ADD, but flip the negation on src1 first */
- inst->FullSrcRegisters[1].SrcRegister.Negate =
- !inst->FullSrcRegisters[1].SrcRegister.Negate;
- /* Fall through */
- case TGSI_OPCODE_ADD:
- /* Force src0 to one, move all registers over */
- inst->FullSrcRegisters[2] = inst->FullSrcRegisters[1];
- inst->FullSrcRegisters[1] = inst->FullSrcRegisters[0];
- inst->FullSrcRegisters[0] = r500_constant_one;
- r500_emit_maths(fs, assembler, inst->FullSrcRegisters,
- &inst->FullDstRegisters[0], inst->Instruction.Opcode, 3);
- break;
- case TGSI_OPCODE_MUL:
- /* Force our src2 to zero */
- inst->FullSrcRegisters[2] = r500_constant_zero;
- r500_emit_maths(fs, assembler, inst->FullSrcRegisters,
- &inst->FullDstRegisters[0], inst->Instruction.Opcode, 3);
- break;
- case TGSI_OPCODE_MAD:
- r500_emit_maths(fs, assembler, inst->FullSrcRegisters,
- &inst->FullDstRegisters[0], inst->Instruction.Opcode, 3);
- break;
-
- /* The MOV variants. */
- case TGSI_OPCODE_ABS:
- /* Set absolute value modifiers. */
- inst->FullSrcRegisters[0].SrcRegisterExtMod.Absolute = TRUE;
- /* Fall through */
- case TGSI_OPCODE_MOV:
- case TGSI_OPCODE_SWZ:
- /* src0 -> src1 and src2 forced to zero */
- inst->FullSrcRegisters[1] = inst->FullSrcRegisters[0];
- inst->FullSrcRegisters[2] = r500_constant_zero;
- r500_emit_maths(fs, assembler, inst->FullSrcRegisters,
- &inst->FullDstRegisters[0], inst->Instruction.Opcode, 3);
- break;
-
- /* The compound and hybrid insts. */
- case TGSI_OPCODE_LRP:
- /* LRP DST A, B, C -> MAD TMP -A, C, C; MAD DST A, B, TMP */
- inst->FullSrcRegisters[3] = inst->FullSrcRegisters[1];
- inst->FullSrcRegisters[1] = inst->FullSrcRegisters[2];
- inst->FullSrcRegisters[0].SrcRegister.Negate =
- !(inst->FullSrcRegisters[0].SrcRegister.Negate);
- inst->FullDstRegisters[1] = inst->FullDstRegisters[0];
- inst->FullDstRegisters[0].DstRegister.Index =
- assembler->temp_count;
- inst->FullDstRegisters[0].DstRegister.File = TGSI_FILE_TEMPORARY;
- r500_emit_maths(fs, assembler, inst->FullSrcRegisters,
- &inst->FullDstRegisters[0], TGSI_OPCODE_MAD, 3);
- inst->FullSrcRegisters[2].SrcRegister.Index =
- assembler->temp_count;
- inst->FullSrcRegisters[2].SrcRegister.File = TGSI_FILE_TEMPORARY;
- inst->FullSrcRegisters[2].SrcRegister.SwizzleX = TGSI_SWIZZLE_X;
- inst->FullSrcRegisters[2].SrcRegister.SwizzleY = TGSI_SWIZZLE_Y;
- inst->FullSrcRegisters[2].SrcRegister.SwizzleZ = TGSI_SWIZZLE_Z;
- inst->FullSrcRegisters[2].SrcRegister.SwizzleW = TGSI_SWIZZLE_W;
- inst->FullSrcRegisters[1] = inst->FullSrcRegisters[3];
- inst->FullSrcRegisters[0].SrcRegister.Negate =
- !(inst->FullSrcRegisters[0].SrcRegister.Negate);
- inst->FullDstRegisters[0] = inst->FullDstRegisters[1];
- r500_emit_maths(fs, assembler, inst->FullSrcRegisters,
- &inst->FullDstRegisters[0], TGSI_OPCODE_MAD, 3);
- break;
- case TGSI_OPCODE_POW:
- /* POW DST A, B -> LG2 TMP A; MUL TMP TMP, B; EX2 DST TMP */
- inst->FullSrcRegisters[0].SrcRegisterExtSwz.ExtSwizzleW =
- inst->FullSrcRegisters[0].SrcRegisterExtSwz.ExtSwizzleX;
- inst->FullSrcRegisters[0].SrcRegister.SwizzleW =
- inst->FullSrcRegisters[0].SrcRegister.SwizzleX;
- inst->FullDstRegisters[1] = inst->FullDstRegisters[0];
- inst->FullDstRegisters[0].DstRegister.Index =
- assembler->temp_count;
- inst->FullDstRegisters[0].DstRegister.File = TGSI_FILE_TEMPORARY;
- r500_emit_maths(fs, assembler, inst->FullSrcRegisters,
- &inst->FullDstRegisters[0], TGSI_OPCODE_LG2, 1);
- inst->FullSrcRegisters[0].SrcRegister.Index =
- assembler->temp_count;
- inst->FullSrcRegisters[0].SrcRegister.File = TGSI_FILE_TEMPORARY;
- inst->FullSrcRegisters[0].SrcRegister.SwizzleX = TGSI_SWIZZLE_X;
- inst->FullSrcRegisters[0].SrcRegister.SwizzleY = TGSI_SWIZZLE_Y;
- inst->FullSrcRegisters[0].SrcRegister.SwizzleZ = TGSI_SWIZZLE_Z;
- inst->FullSrcRegisters[0].SrcRegister.SwizzleW = TGSI_SWIZZLE_W;
- inst->FullSrcRegisters[2] = r500_constant_zero;
- r500_emit_maths(fs, assembler, inst->FullSrcRegisters,
- &inst->FullDstRegisters[0], TGSI_OPCODE_MUL, 3);
- inst->FullDstRegisters[0] = inst->FullDstRegisters[1];
- r500_emit_maths(fs, assembler, inst->FullSrcRegisters,
- &inst->FullDstRegisters[0], TGSI_OPCODE_EX2, 1);
- break;
-
- /* The texture instruction set. */
- case TGSI_OPCODE_KIL:
- case TGSI_OPCODE_TEX:
- case TGSI_OPCODE_TXB:
- case TGSI_OPCODE_TXP:
- r500_emit_tex(fs, assembler, &inst->FullSrcRegisters[0],
- &inst->FullDstRegisters[0], inst->Instruction.Opcode);
- break;
-
- /* This is the end. My only friend, the end. */
- case TGSI_OPCODE_END:
- break;
- default:
- debug_printf("r300: fs: Bad opcode %d\n",
- inst->Instruction.Opcode);
- break;
- }
-
- /* Clamp, if saturation flags are set. */
- if (inst->Instruction.Saturate == TGSI_SAT_ZERO_ONE) {
- fs->instructions[fs->instruction_count - 1].inst0 |=
- R500_INST_RGB_CLAMP | R500_INST_ALPHA_CLAMP;
- }
-}
-
-static void r300_fs_finalize(struct r3xx_fragment_shader* fs,
- struct r300_fs_asm* assembler)
-{
- fs->stack_size = assembler->temp_count + assembler->temp_offset + 1;
-}
-
-static void r500_fs_finalize(struct r500_fragment_shader* fs,
- struct r300_fs_asm* assembler)
-{
- /* XXX should this just go with OPCODE_END? */
- fs->instructions[fs->instruction_count - 1].inst0 |=
- R500_INST_LAST;
-}
-
-void r300_translate_fragment_shader(struct r300_context* r300,
- struct r3xx_fragment_shader* fs)
-{
- struct tgsi_parse_context parser;
- int i;
- boolean is_r500 = r300_screen(r300->context.screen)->caps->is_r500;
- struct r300_constant_buffer* consts =
- &r300->shader_constants[PIPE_SHADER_FRAGMENT];
-
- struct r300_fs_asm* assembler = CALLOC_STRUCT(r300_fs_asm);
- if (assembler == NULL) {
- return;
- }
- /* Setup starting offset for immediates. */
- assembler->imm_offset = consts->user_count;
- /* Enable depth writes, if needed. */
- assembler->writes_depth = fs->info.writes_z;
-
- /* Make sure we start at the beginning of the shader. */
- if (is_r500) {
- ((struct r500_fragment_shader*)fs)->instruction_count = 0;
- }
-
- tgsi_parse_init(&parser, fs->state.tokens);
-
- while (!tgsi_parse_end_of_tokens(&parser)) {
- tgsi_parse_token(&parser);
-
- /* This is seriously the lamest way to create fragment programs ever.
- * I blame TGSI. */
- switch (parser.FullToken.Token.Type) {
- case TGSI_TOKEN_TYPE_DECLARATION:
- /* Allocated registers sitting at the beginning
- * of the program. */
- r300_fs_declare(assembler, &parser.FullToken.FullDeclaration);
- break;
- case TGSI_TOKEN_TYPE_IMMEDIATE:
- debug_printf("r300: Emitting immediate to constant buffer, "
- "position %d\n",
- assembler->imm_offset + assembler->imm_count);
- /* I am not amused by the length of these. */
- for (i = 0; i < 4; i++) {
- consts->constants[assembler->imm_offset +
- assembler->imm_count][i] =
- parser.FullToken.FullImmediate.u.ImmediateFloat32[i]
- .Float;
- }
- assembler->imm_count++;
- break;
- case TGSI_TOKEN_TYPE_INSTRUCTION:
- if (is_r500) {
- r500_fs_instruction((struct r500_fragment_shader*)fs,
- assembler, &parser.FullToken.FullInstruction);
- } else {
- r300_fs_instruction((struct r300_fragment_shader*)fs,
- assembler, &parser.FullToken.FullInstruction);
- }
- break;
- }
- }
-
- debug_printf("r300: fs: %d texs and %d colors, first free reg is %d\n",
- assembler->tex_count, assembler->color_count,
- assembler->tex_count + assembler->color_count);
-
- consts->count = consts->user_count + assembler->imm_count;
- fs->uses_imms = assembler->imm_count;
- debug_printf("r300: fs: %d total constants, "
- "%d from user and %d from immediates\n", consts->count,
- consts->user_count, assembler->imm_count);
- r300_fs_finalize(fs, assembler);
- if (is_r500) {
- r500_fs_finalize((struct r500_fragment_shader*)fs, assembler);
- }
-
- tgsi_dump(fs->state.tokens);
- /* XXX finish r300 dumper too */
- if (is_r500) {
- r500_fs_dump((struct r500_fragment_shader*)fs);
- }
-
- tgsi_parse_free(&parser);
- FREE(assembler);
-}
+++ /dev/null
-/*
- * Copyright 2008 Corbin Simpson <MostAwesomeDude@gmail.com>
- *
- * 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
- * on the rights to use, copy, modify, merge, publish, distribute, sub
- * license, 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 (including the next
- * paragraph) 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 NON-INFRINGEMENT. IN NO EVENT SHALL
- * THE AUTHOR(S) AND/OR THEIR SUPPLIERS 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 R300_STATE_SHADER_H
-#define R300_STATE_SHADER_H
-
-#include "tgsi/tgsi_parse.h"
-
-#include "r300_context.h"
-#include "r300_debug.h"
-#include "r300_reg.h"
-#include "r300_screen.h"
-
-/* XXX this all should find its way back to r300_reg */
-/* Swizzle tools */
-#define R500_SWIZZLE_ZERO 4
-#define R500_SWIZZLE_HALF 5
-#define R500_SWIZZLE_ONE 6
-#define R500_SWIZ_RGB_ZERO ((4 << 0) | (4 << 3) | (4 << 6))
-#define R500_SWIZ_RGB_ONE ((6 << 0) | (6 << 3) | (6 << 6))
-#define R500_SWIZ_RGB_RGB ((0 << 0) | (1 << 3) | (2 << 6))
-#define R500_SWIZ_MOD_NEG 1
-#define R500_SWIZ_MOD_ABS 2
-#define R500_SWIZ_MOD_NEG_ABS 3
-/* Swizzles for inst2 */
-#define R500_SWIZ_TEX_STRQ(x) ((x) << 8)
-#define R500_SWIZ_TEX_RGBA(x) ((x) << 24)
-/* Swizzles for inst3 */
-#define R500_SWIZ_RGB_A(x) ((x) << 2)
-#define R500_SWIZ_RGB_B(x) ((x) << 15)
-/* Swizzles for inst4 */
-#define R500_SWIZ_ALPHA_A(x) ((x) << 14)
-#define R500_SWIZ_ALPHA_B(x) ((x) << 21)
-/* Swizzle for inst5 */
-#define R500_SWIZ_RGBA_C(x) ((x) << 14)
-#define R500_SWIZ_ALPHA_C(x) ((x) << 27)
-/* Writemasks */
-#define R500_TEX_WMASK(x) ((x) << 11)
-#define R500_ALU_WMASK(x) ((x) << 11)
-#define R500_ALU_OMASK(x) ((x) << 15)
-#define R500_W_OMASK (1 << 31)
-
-/* TGSI constants. TGSI is like XML: If it can't solve your problems, you're
- * not using enough of it. */
-static const struct tgsi_full_src_register r500_constant_zero = {
- .SrcRegister.Extended = TRUE,
- .SrcRegister.File = TGSI_FILE_NULL,
- .SrcRegisterExtSwz.ExtSwizzleX = TGSI_EXTSWIZZLE_ZERO,
- .SrcRegisterExtSwz.ExtSwizzleY = TGSI_EXTSWIZZLE_ZERO,
- .SrcRegisterExtSwz.ExtSwizzleZ = TGSI_EXTSWIZZLE_ZERO,
- .SrcRegisterExtSwz.ExtSwizzleW = TGSI_EXTSWIZZLE_ZERO,
-};
-
-static const struct tgsi_full_src_register r500_constant_one = {
- .SrcRegister.Extended = TRUE,
- .SrcRegister.File = TGSI_FILE_NULL,
- .SrcRegisterExtSwz.ExtSwizzleX = TGSI_EXTSWIZZLE_ONE,
- .SrcRegisterExtSwz.ExtSwizzleY = TGSI_EXTSWIZZLE_ONE,
- .SrcRegisterExtSwz.ExtSwizzleZ = TGSI_EXTSWIZZLE_ONE,
- .SrcRegisterExtSwz.ExtSwizzleW = TGSI_EXTSWIZZLE_ONE,
-};
-
-/* Temporary struct used to hold assembly state while putting together
- * fragment programs. */
-struct r300_fs_asm {
- /* Pipe context. */
- struct r300_context* r300;
- /* Number of colors. */
- unsigned color_count;
- /* Number of texcoords. */
- unsigned tex_count;
- /* Offset for temporary registers. Inputs and temporaries have no
- * distinguishing markings, so inputs start at 0 and the first usable
- * temporary register is after all inputs. */
- unsigned temp_offset;
- /* Number of requested temporary registers. */
- unsigned temp_count;
- /* Offset for immediate constants. Neither R300 nor R500 can do four
- * inline constants per source, so instead we copy immediates into the
- * constant buffer. */
- unsigned imm_offset;
- /* Number of immediate constants. */
- unsigned imm_count;
- /* Are depth writes enabled? */
- boolean writes_depth;
- /* Depth write offset. This is the TGSI output that corresponds to
- * depth writes. */
- unsigned depth_output;
-};
-
-void r300_translate_fragment_shader(struct r300_context* r300,
- struct r3xx_fragment_shader* fs);
-
-static struct r300_fragment_shader r300_passthrough_fragment_shader = {
- .alu_instruction_count = 1,
- .tex_instruction_count = 0,
- .indirections = 0,
- .shader.stack_size = 1,
-
- .instructions[0].alu_rgb_inst = R300_RGB_SWIZA(R300_ALU_ARGC_SRC0C_XYZ) |
- R300_RGB_SWIZB(R300_ALU_ARGC_SRC0C_XYZ) |
- R300_RGB_SWIZC(R300_ALU_ARGC_ZERO) |
- R300_ALU_OUTC_CMP,
- .instructions[0].alu_rgb_addr = R300_RGB_ADDR0(0) | R300_RGB_ADDR1(0) |
- R300_RGB_ADDR2(0) | R300_ALU_DSTC_OUTPUT_XYZ,
- .instructions[0].alu_alpha_inst = R300_ALPHA_SWIZA(R300_ALU_ARGA_SRC0A) |
- R300_ALPHA_SWIZB(R300_ALU_ARGA_SRC0A) |
- R300_ALPHA_SWIZC(R300_ALU_ARGA_ZERO) |
- R300_ALU_OUTA_CMP,
- .instructions[0].alu_alpha_addr = R300_ALPHA_ADDR0(0) |
- R300_ALPHA_ADDR1(0) | R300_ALPHA_ADDR2(0) | R300_ALU_DSTA_OUTPUT,
-};
-
-static struct r500_fragment_shader r500_passthrough_fragment_shader = {
- .shader.stack_size = 0,
- .instruction_count = 1,
- .instructions[0].inst0 = R500_INST_TYPE_OUT |
- R500_INST_TEX_SEM_WAIT | R500_INST_LAST |
- R500_INST_RGB_OMASK_RGB | R500_INST_ALPHA_OMASK |
- R500_INST_RGB_CLAMP | R500_INST_ALPHA_CLAMP,
- .instructions[0].inst1 =
- R500_RGB_ADDR0(0) | R500_RGB_ADDR1(0) | R500_RGB_ADDR1_CONST |
- R500_RGB_ADDR2(0) | R500_RGB_ADDR2_CONST,
- .instructions[0].inst2 =
- R500_ALPHA_ADDR0(0) | R500_ALPHA_ADDR1(0) | R500_ALPHA_ADDR1_CONST |
- R500_ALPHA_ADDR2(0) | R500_ALPHA_ADDR2_CONST,
- .instructions[0].inst3 =
- R500_ALU_RGB_SEL_A_SRC0 | R500_ALU_RGB_R_SWIZ_A_R |
- R500_ALU_RGB_G_SWIZ_A_G | R500_ALU_RGB_B_SWIZ_A_B |
- R500_ALU_RGB_SEL_B_SRC0 | R500_ALU_RGB_R_SWIZ_B_R |
- R500_ALU_RGB_B_SWIZ_B_G | R500_ALU_RGB_G_SWIZ_B_B,
- .instructions[0].inst4 =
- R500_ALPHA_OP_CMP | R500_ALPHA_SWIZ_A_A | R500_ALPHA_SWIZ_B_A,
- .instructions[0].inst5 =
- R500_ALU_RGBA_OP_CMP | R500_ALU_RGBA_R_SWIZ_0 |
- R500_ALU_RGBA_G_SWIZ_0 | R500_ALU_RGBA_B_SWIZ_0 |
- R500_ALU_RGBA_A_SWIZ_0,
-};
-
-static struct r300_fragment_shader r300_texture_fragment_shader = {
- .alu_instruction_count = 1,
- .tex_instruction_count = 0,
- .indirections = 0,
- .shader.stack_size = 1,
-
- .instructions[0].alu_rgb_inst = R300_RGB_SWIZA(R300_ALU_ARGC_SRC0C_XYZ) |
- R300_RGB_SWIZB(R300_ALU_ARGC_SRC0C_XYZ) |
- R300_RGB_SWIZC(R300_ALU_ARGC_ZERO) |
- R300_ALU_OUTC_CMP,
- .instructions[0].alu_rgb_addr = R300_RGB_ADDR0(0) | R300_RGB_ADDR1(0) |
- R300_RGB_ADDR2(0) | R300_ALU_DSTC_OUTPUT_XYZ,
- .instructions[0].alu_alpha_inst = R300_ALPHA_SWIZA(R300_ALU_ARGA_SRC0A) |
- R300_ALPHA_SWIZB(R300_ALU_ARGA_SRC0A) |
- R300_ALPHA_SWIZC(R300_ALU_ARGA_ZERO) |
- R300_ALU_OUTA_CMP,
- .instructions[0].alu_alpha_addr = R300_ALPHA_ADDR0(0) |
- R300_ALPHA_ADDR1(0) | R300_ALPHA_ADDR2(0) | R300_ALU_DSTA_OUTPUT,
-};
-
-static struct r500_fragment_shader r500_texture_fragment_shader = {
- .shader.stack_size = 1,
- .instruction_count = 2,
- .instructions[0].inst0 = R500_INST_TYPE_TEX |
- R500_INST_TEX_SEM_WAIT |
- R500_INST_RGB_WMASK_RGB | R500_INST_ALPHA_WMASK |
- R500_INST_RGB_CLAMP | R500_INST_ALPHA_CLAMP,
- .instructions[0].inst1 = R500_TEX_ID(0) | R500_TEX_INST_LD |
- R500_TEX_SEM_ACQUIRE | R500_TEX_IGNORE_UNCOVERED,
- .instructions[0].inst2 = R500_TEX_SRC_ADDR(0) |
- R500_TEX_SRC_S_SWIZ_R | R500_TEX_SRC_T_SWIZ_G |
- R500_TEX_SRC_R_SWIZ_B | R500_TEX_SRC_Q_SWIZ_A |
- R500_TEX_DST_ADDR(0) |
- R500_TEX_DST_R_SWIZ_R | R500_TEX_DST_G_SWIZ_G |
- R500_TEX_DST_B_SWIZ_B | R500_TEX_DST_A_SWIZ_A,
- .instructions[0].inst3 = 0x0,
- .instructions[0].inst4 = 0x0,
- .instructions[0].inst5 = 0x0,
- .instructions[1].inst0 = R500_INST_TYPE_OUT |
- R500_INST_TEX_SEM_WAIT | R500_INST_LAST |
- R500_INST_RGB_OMASK_RGB | R500_INST_ALPHA_OMASK |
- R500_INST_RGB_CLAMP | R500_INST_ALPHA_CLAMP,
- .instructions[1].inst1 =
- R500_RGB_ADDR0(0) | R500_RGB_ADDR1(0) | R500_RGB_ADDR1_CONST |
- R500_RGB_ADDR2(0) | R500_RGB_ADDR2_CONST,
- .instructions[1].inst2 =
- R500_ALPHA_ADDR0(0) | R500_ALPHA_ADDR1(0) | R500_ALPHA_ADDR1_CONST |
- R500_ALPHA_ADDR2(0) | R500_ALPHA_ADDR2_CONST,
- .instructions[1].inst3 =
- R500_ALU_RGB_SEL_A_SRC0 | R500_ALU_RGB_R_SWIZ_A_R |
- R500_ALU_RGB_G_SWIZ_A_G | R500_ALU_RGB_B_SWIZ_A_B |
- R500_ALU_RGB_SEL_B_SRC0 | R500_ALU_RGB_R_SWIZ_B_R |
- R500_ALU_RGB_B_SWIZ_B_G | R500_ALU_RGB_G_SWIZ_B_B,
- .instructions[1].inst4 =
- R500_ALPHA_OP_CMP | R500_ALPHA_SWIZ_A_A | R500_ALPHA_SWIZ_B_A,
- .instructions[1].inst5 =
- R500_ALU_RGBA_OP_CMP | R500_ALU_RGBA_R_SWIZ_0 |
- R500_ALU_RGBA_G_SWIZ_0 | R500_ALU_RGBA_B_SWIZ_0 |
- R500_ALU_RGBA_A_SWIZ_0,
-};
-
-#endif /* R300_STATE_SHADER_H */
+++ /dev/null
-/*
- * Copyright 2009 Corbin Simpson <MostAwesomeDude@gmail.com>
- *
- * 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
- * on the rights to use, copy, modify, merge, publish, distribute, sub
- * license, 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 (including the next
- * paragraph) 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 NON-INFRINGEMENT. IN NO EVENT SHALL
- * THE AUTHOR(S) AND/OR THEIR SUPPLIERS 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 "r300_state_tcl.h"
-
-static void r300_vs_declare(struct r300_vs_asm* assembler,
- struct tgsi_full_declaration* decl)
-{
- switch (decl->Declaration.File) {
- case TGSI_FILE_INPUT:
- break;
- case TGSI_FILE_OUTPUT:
- switch (decl->Semantic.SemanticName) {
- case TGSI_SEMANTIC_POSITION:
- assembler->tab[decl->DeclarationRange.First] = 0;
- break;
- case TGSI_SEMANTIC_COLOR:
- assembler->tab[decl->DeclarationRange.First] =
- (assembler->point_size ? 1 : 0) +
- assembler->out_colors;
- break;
- case TGSI_SEMANTIC_FOG:
- case TGSI_SEMANTIC_GENERIC:
- /* XXX multiple? */
- assembler->tab[decl->DeclarationRange.First] =
- (assembler->point_size ? 1 : 0) +
- assembler->out_colors +
- assembler->out_texcoords;
- break;
- case TGSI_SEMANTIC_PSIZE:
- assembler->tab[decl->DeclarationRange.First] = 1;
- break;
- default:
- debug_printf("r300: vs: Bad semantic declaration %d\n",
- decl->Semantic.SemanticName);
- break;
- }
- break;
- case TGSI_FILE_CONSTANT:
- break;
- case TGSI_FILE_TEMPORARY:
- assembler->temp_count++;
- break;
- default:
- debug_printf("r300: vs: Bad file %d\n", decl->Declaration.File);
- break;
- }
-}
-
-static INLINE unsigned r300_vs_src_type(struct r300_vs_asm* assembler,
- struct tgsi_src_register* src)
-{
- switch (src->File) {
- case TGSI_FILE_NULL:
- case TGSI_FILE_INPUT:
- /* Probably a zero or one swizzle */
- return R300_PVS_SRC_REG_INPUT;
- case TGSI_FILE_TEMPORARY:
- return R300_PVS_SRC_REG_TEMPORARY;
- case TGSI_FILE_CONSTANT:
- case TGSI_FILE_IMMEDIATE:
- return R300_PVS_SRC_REG_CONSTANT;
- default:
- debug_printf("r300: vs: Unimplemented src type %d\n", src->File);
- break;
- }
- return 0;
-}
-
-static INLINE unsigned r300_vs_src(struct r300_vs_asm* assembler,
- struct tgsi_src_register* src)
-{
- switch (src->File) {
- case TGSI_FILE_NULL:
- case TGSI_FILE_INPUT:
- case TGSI_FILE_TEMPORARY:
- case TGSI_FILE_CONSTANT:
- return src->Index;
- case TGSI_FILE_IMMEDIATE:
- return src->Index + assembler->imm_offset;
- default:
- debug_printf("r300: vs: Unimplemented src type %d\n", src->File);
- break;
- }
- return 0;
-}
-
-static INLINE unsigned r300_vs_dst_type(struct r300_vs_asm* assembler,
- struct tgsi_dst_register* dst)
-{
- switch (dst->File) {
- case TGSI_FILE_TEMPORARY:
- return R300_PVS_DST_REG_TEMPORARY;
- case TGSI_FILE_OUTPUT:
- return R300_PVS_DST_REG_OUT;
- default:
- debug_printf("r300: vs: Unimplemented dst type %d\n", dst->File);
- break;
- }
- return 0;
-}
-
-static INLINE unsigned r300_vs_dst(struct r300_vs_asm* assembler,
- struct tgsi_dst_register* dst)
-{
- switch (dst->File) {
- case TGSI_FILE_TEMPORARY:
- return dst->Index;
- case TGSI_FILE_OUTPUT:
- return assembler->tab[dst->Index];
- default:
- debug_printf("r300: vs: Unimplemented dst %d\n", dst->File);
- break;
- }
- return 0;
-}
-
-static uint32_t r300_vs_op(unsigned op)
-{
- switch (op) {
- case TGSI_OPCODE_DP3:
- case TGSI_OPCODE_DP4:
- return R300_VE_DOT_PRODUCT;
- case TGSI_OPCODE_MUL:
- return R300_VE_MULTIPLY;
- case TGSI_OPCODE_ADD:
- case TGSI_OPCODE_MOV:
- case TGSI_OPCODE_SUB:
- case TGSI_OPCODE_SWZ:
- return R300_VE_ADD;
- case TGSI_OPCODE_MAX:
- return R300_VE_MAXIMUM;
- case TGSI_OPCODE_SLT:
- return R300_VE_SET_LESS_THAN;
- case TGSI_OPCODE_RSQ:
- return R300_PVS_DST_MATH_INST | R300_ME_RECIP_DX;
- case TGSI_OPCODE_MAD:
- return R300_PVS_DST_MACRO_INST | R300_PVS_MACRO_OP_2CLK_MADD;
- default:
- break;
- }
- return 0;
-}
-
-static uint32_t r300_vs_swiz(struct tgsi_full_src_register* reg)
-{
- if (reg->SrcRegister.Extended) {
- return (reg->SrcRegister.Negate ? (0xf << 12) : 0) |
- reg->SrcRegisterExtSwz.ExtSwizzleX |
- (reg->SrcRegisterExtSwz.ExtSwizzleY << 3) |
- (reg->SrcRegisterExtSwz.ExtSwizzleZ << 6) |
- (reg->SrcRegisterExtSwz.ExtSwizzleW << 9);
- } else {
- return (reg->SrcRegister.Negate ? (0xf << 12) : 0) |
- reg->SrcRegister.SwizzleX |
- (reg->SrcRegister.SwizzleY << 3) |
- (reg->SrcRegister.SwizzleZ << 6) |
- (reg->SrcRegister.SwizzleW << 9);
- }
-}
-
-/* XXX icky icky icky icky */
-static uint32_t r300_vs_scalar_swiz(struct tgsi_full_src_register* reg)
-{
- if (reg->SrcRegister.Extended) {
- return (reg->SrcRegister.Negate ? (0xf << 12) : 0) |
- reg->SrcRegisterExtSwz.ExtSwizzleX |
- (reg->SrcRegisterExtSwz.ExtSwizzleX << 3) |
- (reg->SrcRegisterExtSwz.ExtSwizzleX << 6) |
- (reg->SrcRegisterExtSwz.ExtSwizzleX << 9);
- } else {
- return (reg->SrcRegister.Negate ? (0xf << 12) : 0) |
- reg->SrcRegister.SwizzleX |
- (reg->SrcRegister.SwizzleX << 3) |
- (reg->SrcRegister.SwizzleX << 6) |
- (reg->SrcRegister.SwizzleX << 9);
- }
-}
-
-/* XXX scalar stupidity */
-static void r300_vs_emit_inst(struct r300_vertex_shader* vs,
- struct r300_vs_asm* assembler,
- struct tgsi_full_src_register* src,
- struct tgsi_full_dst_register* dst,
- unsigned op,
- unsigned count,
- boolean is_scalar)
-{
- int i = vs->instruction_count;
- vs->instructions[i].inst0 = R300_PVS_DST_OPCODE(r300_vs_op(op)) |
- R300_PVS_DST_REG_TYPE(r300_vs_dst_type(assembler, &dst->DstRegister)) |
- R300_PVS_DST_OFFSET(r300_vs_dst(assembler, &dst->DstRegister)) |
- R300_PVS_DST_WE(dst->DstRegister.WriteMask);
- switch (count) {
- case 3:
- vs->instructions[i].inst3 =
- R300_PVS_SRC_REG_TYPE(r300_vs_src_type(assembler,
- &src[2].SrcRegister)) |
- R300_PVS_SRC_OFFSET(r300_vs_src(assembler,
- &src[2].SrcRegister)) |
- R300_PVS_SRC_SWIZZLE(r300_vs_swiz(&src[2]));
- /* Fall through */
- case 2:
- vs->instructions[i].inst2 =
- R300_PVS_SRC_REG_TYPE(r300_vs_src_type(assembler,
- &src[1].SrcRegister)) |
- R300_PVS_SRC_OFFSET(r300_vs_src(assembler,
- &src[1].SrcRegister)) |
- R300_PVS_SRC_SWIZZLE(r300_vs_swiz(&src[1]));
- /* Fall through */
- case 1:
- vs->instructions[i].inst1 =
- R300_PVS_SRC_REG_TYPE(r300_vs_src_type(assembler,
- &src[0].SrcRegister)) |
- R300_PVS_SRC_OFFSET(r300_vs_src(assembler,
- &src[0].SrcRegister)) |
- /* XXX the icky, it burns */
- R300_PVS_SRC_SWIZZLE(is_scalar ? r300_vs_scalar_swiz(&src[0])
- : r300_vs_swiz(&src[0]));
- break;
- }
- vs->instruction_count++;
-}
-
-static void r300_vs_instruction(struct r300_vertex_shader* vs,
- struct r300_vs_asm* assembler,
- struct tgsi_full_instruction* inst)
-{
- switch (inst->Instruction.Opcode) {
- case TGSI_OPCODE_RSQ:
- r300_vs_emit_inst(vs, assembler, inst->FullSrcRegisters,
- &inst->FullDstRegisters[0], inst->Instruction.Opcode,
- 1, TRUE);
- break;
- case TGSI_OPCODE_SUB:
- inst->FullSrcRegisters[1].SrcRegister.Negate =
- !inst->FullSrcRegisters[1].SrcRegister.Negate;
- /* Fall through */
- case TGSI_OPCODE_ADD:
- case TGSI_OPCODE_MUL:
- case TGSI_OPCODE_MAX:
- case TGSI_OPCODE_SLT:
- r300_vs_emit_inst(vs, assembler, inst->FullSrcRegisters,
- &inst->FullDstRegisters[0], inst->Instruction.Opcode,
- 2, FALSE);
- break;
- case TGSI_OPCODE_DP3:
- /* Set alpha swizzle to zero for src0 and src1 */
- if (!inst->FullSrcRegisters[0].SrcRegister.Extended) {
- inst->FullSrcRegisters[0].SrcRegister.Extended = TRUE;
- inst->FullSrcRegisters[0].SrcRegisterExtSwz.ExtSwizzleX =
- inst->FullSrcRegisters[0].SrcRegister.SwizzleX;
- inst->FullSrcRegisters[0].SrcRegisterExtSwz.ExtSwizzleY =
- inst->FullSrcRegisters[0].SrcRegister.SwizzleY;
- inst->FullSrcRegisters[0].SrcRegisterExtSwz.ExtSwizzleZ =
- inst->FullSrcRegisters[0].SrcRegister.SwizzleZ;
- }
- inst->FullSrcRegisters[0].SrcRegisterExtSwz.ExtSwizzleW =
- TGSI_EXTSWIZZLE_ZERO;
- if (!inst->FullSrcRegisters[1].SrcRegister.Extended) {
- inst->FullSrcRegisters[1].SrcRegister.Extended = TRUE;
- inst->FullSrcRegisters[1].SrcRegisterExtSwz.ExtSwizzleX =
- inst->FullSrcRegisters[1].SrcRegister.SwizzleX;
- inst->FullSrcRegisters[1].SrcRegisterExtSwz.ExtSwizzleY =
- inst->FullSrcRegisters[1].SrcRegister.SwizzleY;
- inst->FullSrcRegisters[1].SrcRegisterExtSwz.ExtSwizzleZ =
- inst->FullSrcRegisters[1].SrcRegister.SwizzleZ;
- }
- inst->FullSrcRegisters[1].SrcRegisterExtSwz.ExtSwizzleW =
- TGSI_EXTSWIZZLE_ZERO;
- /* Fall through */
- case TGSI_OPCODE_DP4:
- r300_vs_emit_inst(vs, assembler, inst->FullSrcRegisters,
- &inst->FullDstRegisters[0], inst->Instruction.Opcode,
- 2, FALSE);
- break;
- case TGSI_OPCODE_MOV:
- case TGSI_OPCODE_SWZ:
- inst->FullSrcRegisters[1] = r300_constant_zero;
- r300_vs_emit_inst(vs, assembler, inst->FullSrcRegisters,
- &inst->FullDstRegisters[0], inst->Instruction.Opcode,
- 2, FALSE);
- break;
- case TGSI_OPCODE_MAD:
- r300_vs_emit_inst(vs, assembler, inst->FullSrcRegisters,
- &inst->FullDstRegisters[0], inst->Instruction.Opcode,
- 3, FALSE);
- break;
- case TGSI_OPCODE_END:
- break;
- default:
- debug_printf("r300: vs: Bad opcode %d\n",
- inst->Instruction.Opcode);
- break;
- }
-}
-
-static void r300_vs_init(struct r300_vertex_shader* vs,
- struct r300_vs_asm* assembler)
-{
- struct tgsi_shader_info* info = &vs->info;
- int i;
-
- for (i = 0; i < info->num_outputs; i++) {
- switch (info->output_semantic_name[i]) {
- case TGSI_SEMANTIC_PSIZE:
- assembler->point_size = TRUE;
- break;
- case TGSI_SEMANTIC_COLOR:
- assembler->out_colors++;
- break;
- case TGSI_SEMANTIC_FOG:
- case TGSI_SEMANTIC_GENERIC:
- assembler->out_texcoords++;
- break;
- }
- }
-
- vs->instruction_count = 0;
-}
-
-void r300_translate_vertex_shader(struct r300_context* r300,
- struct r300_vertex_shader* vs)
-{
- struct tgsi_parse_context parser;
- int i;
- struct r300_constant_buffer* consts =
- &r300->shader_constants[PIPE_SHADER_VERTEX];
-
- struct r300_vs_asm* assembler = CALLOC_STRUCT(r300_vs_asm);
- if (assembler == NULL) {
- return;
- }
-
- /* Init assembler. */
- r300_vs_init(vs, assembler);
-
- /* Setup starting offset for immediates. */
- assembler->imm_offset = consts->user_count;
-
- tgsi_parse_init(&parser, vs->state.tokens);
-
- while (!tgsi_parse_end_of_tokens(&parser)) {
- tgsi_parse_token(&parser);
-
- /* This is seriously the lamest way to create fragment programs ever.
- * I blame TGSI. */
- switch (parser.FullToken.Token.Type) {
- case TGSI_TOKEN_TYPE_DECLARATION:
- /* Allocated registers sitting at the beginning
- * of the program. */
- r300_vs_declare(assembler, &parser.FullToken.FullDeclaration);
- break;
- case TGSI_TOKEN_TYPE_IMMEDIATE:
- debug_printf("r300: Emitting immediate to constant buffer, "
- "position %d\n",
- assembler->imm_offset + assembler->imm_count);
- /* I am not amused by the length of these. */
- for (i = 0; i < 4; i++) {
- consts->constants[assembler->imm_offset +
- assembler->imm_count][i] =
- parser.FullToken.FullImmediate.u.ImmediateFloat32[i]
- .Float;
- }
- assembler->imm_count++;
- break;
- case TGSI_TOKEN_TYPE_INSTRUCTION:
- r300_vs_instruction(vs, assembler,
- &parser.FullToken.FullInstruction);
- break;
- }
- }
-
- debug_printf("r300: vs: %d texs and %d colors, first free reg is %d\n",
- assembler->tex_count, assembler->color_count,
- assembler->tex_count + assembler->color_count);
-
- consts->count = consts->user_count + assembler->imm_count;
- vs->uses_imms = assembler->imm_count;
- debug_printf("r300: vs: %d total constants, "
- "%d from user and %d from immediates\n", consts->count,
- consts->user_count, assembler->imm_count);
-
- debug_printf("r300: vs: tab: %d %d %d %d\n", assembler->tab[0],
- assembler->tab[1], assembler->tab[2], assembler->tab[3]);
-
- tgsi_dump(vs->state.tokens);
- /* XXX finish r300 vertex shader dumper */
- r300_vs_dump(vs);
-
- tgsi_parse_free(&parser);
- FREE(assembler);
-}
+++ /dev/null
-/*
- * Copyright 2009 Corbin Simpson <MostAwesomeDude@gmail.com>
- *
- * 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
- * on the rights to use, copy, modify, merge, publish, distribute, sub
- * license, 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 (including the next
- * paragraph) 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 NON-INFRINGEMENT. IN NO EVENT SHALL
- * THE AUTHOR(S) AND/OR THEIR SUPPLIERS 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 R300_STATE_TCL_H
-#define R300_STATE_TCL_H
-
-#include "tgsi/tgsi_parse.h"
-
-#include "r300_context.h"
-#include "r300_debug.h"
-#include "r300_reg.h"
-#include "r300_screen.h"
-
-/* XXX get these to r300_reg */
-#define R300_PVS_DST_OPCODE(x) ((x) << 0)
-# define R300_VE_DOT_PRODUCT 1
-# define R300_VE_MULTIPLY 2
-# define R300_VE_ADD 3
-# define R300_VE_MAXIMUM 7
-# define R300_VE_SET_LESS_THAN 10
-#define R300_PVS_DST_MATH_INST (1 << 6)
-# define R300_ME_RECIP_DX 6
-#define R300_PVS_DST_MACRO_INST (1 << 7)
-# define R300_PVS_MACRO_OP_2CLK_MADD 0
-#define R300_PVS_DST_REG_TYPE(x) ((x) << 8)
-# define R300_PVS_DST_REG_TEMPORARY 0
-# define R300_PVS_DST_REG_A0 1
-# define R300_PVS_DST_REG_OUT 2
-# define R300_PVS_DST_REG_OUT_REPL_X 3
-# define R300_PVS_DST_REG_ALT_TEMPORARY 4
-# define R300_PVS_DST_REG_INPUT 5
-#define R300_PVS_DST_OFFSET(x) ((x) << 13)
-#define R300_PVS_DST_WE(x) ((x) << 20)
-#define R300_PVS_DST_WE_XYZW (0xf << 20)
-
-#define R300_PVS_SRC_REG_TYPE(x) ((x) << 0)
-# define R300_PVS_SRC_REG_TEMPORARY 0
-# define R300_PVS_SRC_REG_INPUT 1
-# define R300_PVS_SRC_REG_CONSTANT 2
-# define R300_PVS_SRC_REG_ALT_TEMPORARY 3
-#define R300_PVS_SRC_OFFSET(x) ((x) << 5)
-#define R300_PVS_SRC_SWIZZLE(x) ((x) << 13)
-# define R300_PVS_SRC_SELECT_X 0
-# define R300_PVS_SRC_SELECT_Y 1
-# define R300_PVS_SRC_SELECT_Z 2
-# define R300_PVS_SRC_SELECT_W 3
-# define R300_PVS_SRC_SELECT_FORCE_0 4
-# define R300_PVS_SRC_SELECT_FORCE_1 5
-# define R300_PVS_SRC_SWIZZLE_XYZW \
- ((R300_PVS_SRC_SELECT_X | (R300_PVS_SRC_SELECT_Y << 3) | \
- (R300_PVS_SRC_SELECT_Z << 6) | (R300_PVS_SRC_SELECT_W << 9)) << 13)
-# define R300_PVS_SRC_SWIZZLE_ZERO \
- ((R300_PVS_SRC_SELECT_FORCE_0 | (R300_PVS_SRC_SELECT_FORCE_0 << 3) | \
- (R300_PVS_SRC_SELECT_FORCE_0 << 6) | \
- (R300_PVS_SRC_SELECT_FORCE_0 << 9)) << 13)
-# define R300_PVS_SRC_SWIZZLE_ONE \
- ((R300_PVS_SRC_SELECT_FORCE_1 | (R300_PVS_SRC_SELECT_FORCE_1 << 3) | \
- (R300_PVS_SRC_SELECT_FORCE_1 << 6) | \
- (R300_PVS_SRC_SELECT_FORCE_1 << 9)) << 13)
-#define R300_PVS_MODIFIER_X (1 << 25)
-#define R300_PVS_MODIFIER_Y (1 << 26)
-#define R300_PVS_MODIFIER_Z (1 << 27)
-#define R300_PVS_MODIFIER_W (1 << 28)
-#define R300_PVS_NEGATE_XYZW \
- (R300_PVS_MODIFIER_X | R300_PVS_MODIFIER_Y | \
- R300_PVS_MODIFIER_Z | R300_PVS_MODIFIER_W)
-
-static const struct tgsi_full_src_register r300_constant_zero = {
- .SrcRegister.Extended = TRUE,
- .SrcRegister.File = TGSI_FILE_NULL,
- .SrcRegisterExtSwz.ExtSwizzleX = TGSI_EXTSWIZZLE_ZERO,
- .SrcRegisterExtSwz.ExtSwizzleY = TGSI_EXTSWIZZLE_ZERO,
- .SrcRegisterExtSwz.ExtSwizzleZ = TGSI_EXTSWIZZLE_ZERO,
- .SrcRegisterExtSwz.ExtSwizzleW = TGSI_EXTSWIZZLE_ZERO,
-};
-
-/* Temporary struct used to hold assembly state while putting together
- * fragment programs. */
-struct r300_vs_asm {
- /* Pipe context. */
- struct r300_context* r300;
- /* Number of colors. */
- unsigned color_count;
- /* Number of texcoords. */
- unsigned tex_count;
- /* Number of requested temporary registers. */
- unsigned temp_count;
- /* Offset for immediate constants. Neither R300 nor R500 can do four
- * inline constants per source, so instead we copy immediates into the
- * constant buffer. */
- unsigned imm_offset;
- /* Number of immediate constants. */
- unsigned imm_count;
- /* Number of colors to write. */
- unsigned out_colors;
- /* Number of texcoords to write. */
- unsigned out_texcoords;
- /* Whether to emit point size. */
- boolean point_size;
- /* Tab of declared outputs to OVM outputs. */
- unsigned tab[16];
-};
-
-static struct r300_vertex_shader r300_passthrough_vertex_shader = {
- /* XXX translate these back into normal instructions */
- .instruction_count = 2,
- .instructions[0].inst0 = R300_PVS_DST_OPCODE(R300_VE_ADD) |
- R300_PVS_DST_REG_TYPE(R300_PVS_DST_REG_OUT) |
- R300_PVS_DST_OFFSET(0) | R300_PVS_DST_WE_XYZW,
- .instructions[0].inst1 = R300_PVS_SRC_REG_TYPE(R300_PVS_SRC_REG_INPUT) |
- R300_PVS_SRC_OFFSET(0) | R300_PVS_SRC_SWIZZLE_XYZW,
- .instructions[0].inst2 = R300_PVS_SRC_SWIZZLE_ZERO,
- .instructions[0].inst3 = 0x0,
- .instructions[1].inst0 = R300_PVS_DST_OPCODE(R300_VE_ADD) |
- R300_PVS_DST_REG_TYPE(R300_PVS_DST_REG_OUT) |
- R300_PVS_DST_OFFSET(1) | R300_PVS_DST_WE_XYZW,
- .instructions[1].inst1 = R300_PVS_SRC_REG_TYPE(R300_PVS_SRC_REG_INPUT) |
- R300_PVS_SRC_OFFSET(1) | R300_PVS_SRC_SWIZZLE_XYZW,
- .instructions[1].inst2 = R300_PVS_SRC_SWIZZLE_ZERO,
- .instructions[1].inst3 = 0x0,
-};
-
-static struct r300_vertex_shader r300_texture_vertex_shader = {
- /* XXX translate these back into normal instructions */
- .instruction_count = 2,
- .instructions[0].inst0 = R300_PVS_DST_OPCODE(R300_VE_ADD) |
- R300_PVS_DST_REG_TYPE(R300_PVS_DST_REG_OUT) |
- R300_PVS_DST_OFFSET(0) | R300_PVS_DST_WE_XYZW,
- .instructions[0].inst1 = R300_PVS_SRC_REG_TYPE(R300_PVS_SRC_REG_INPUT) |
- R300_PVS_SRC_OFFSET(0) | R300_PVS_SRC_SWIZZLE_XYZW,
- .instructions[0].inst2 = R300_PVS_SRC_SWIZZLE_ZERO,
- .instructions[0].inst3 = 0x0,
- .instructions[1].inst0 = R300_PVS_DST_OPCODE(R300_VE_ADD) |
- R300_PVS_DST_REG_TYPE(R300_PVS_DST_REG_OUT) |
- R300_PVS_DST_OFFSET(1) | R300_PVS_DST_WE_XYZW,
- .instructions[1].inst1 = R300_PVS_SRC_REG_TYPE(R300_PVS_SRC_REG_INPUT) |
- R300_PVS_SRC_OFFSET(1) | R300_PVS_SRC_SWIZZLE_XYZW,
- .instructions[1].inst2 = R300_PVS_SRC_SWIZZLE_ZERO,
- .instructions[1].inst3 = 0x0,
-};
-
-void r300_translate_vertex_shader(struct r300_context* r300,
- struct r300_vertex_shader* vs);
-
-#endif /* R300_STATE_TCL_H */
/* Fragment shader setup */
if (caps->is_r500) {
- r500_emit_fragment_shader(r300, &r500_passthrough_fragment_shader);
- r300_emit_rs_block_state(r300, &r500_rs_block_clear_state);
+ r500_emit_fragment_shader(r300, &r5xx_passthrough_fragment_shader);
+ r300_emit_rs_block_state(r300, &r5xx_rs_block_clear_state);
} else {
- r300_emit_fragment_shader(r300, &r300_passthrough_fragment_shader);
- r300_emit_rs_block_state(r300, &r300_rs_block_clear_state);
+ r300_emit_fragment_shader(r300, &r3xx_passthrough_fragment_shader);
+ r300_emit_rs_block_state(r300, &r3xx_rs_block_clear_state);
}
BEGIN_CS(26);
/* Fragment shader setup */
if (caps->is_r500) {
- r500_emit_fragment_shader(r300, &r500_texture_fragment_shader);
- r300_emit_rs_block_state(r300, &r500_rs_block_copy_state);
+ r500_emit_fragment_shader(r300, &r5xx_texture_fragment_shader);
+ r300_emit_rs_block_state(r300, &r5xx_rs_block_copy_state);
} else {
- r300_emit_fragment_shader(r300, &r300_texture_fragment_shader);
- r300_emit_rs_block_state(r300, &r300_rs_block_copy_state);
+ r300_emit_fragment_shader(r300, &r3xx_texture_fragment_shader);
+ r300_emit_rs_block_state(r300, &r3xx_rs_block_copy_state);
}
BEGIN_CS(30);
#include "r300_context.h"
#include "r300_cs.h"
#include "r300_emit.h"
-#include "r300_state_shader.h"
-#include "r300_state_tcl.h"
+#include "r300_fs.h"
+#include "r300_vs.h"
#include "r300_state_inlines.h"
static struct r300_blend_state blend_clear_state = {
.color_control = R300_SHADE_MODEL_FLAT,
};
-static struct r300_rs_block r300_rs_block_clear_state = {
+static struct r300_rs_block r3xx_rs_block_clear_state = {
.ip[0] = R500_RS_SEL_S(R300_RS_SEL_K0) |
R500_RS_SEL_T(R300_RS_SEL_K0) |
R500_RS_SEL_R(R300_RS_SEL_K0) |
.inst_count = 0,
};
-static struct r300_rs_block r500_rs_block_clear_state = {
+static struct r300_rs_block r5xx_rs_block_clear_state = {
.ip[0] = R500_RS_SEL_S(R500_RS_IP_PTR_K0) |
R500_RS_SEL_T(R500_RS_IP_PTR_K0) |
R500_RS_SEL_R(R500_RS_IP_PTR_K0) |
/* The following state is used for surface_copy only. */
-static struct r300_rs_block r300_rs_block_copy_state = {
+static struct r300_rs_block r3xx_rs_block_copy_state = {
.ip[0] = R500_RS_SEL_S(R300_RS_SEL_K0) |
R500_RS_SEL_T(R300_RS_SEL_K0) |
R500_RS_SEL_R(R300_RS_SEL_K0) |
.inst_count = R300_RS_TX_OFFSET(0),
};
-static struct r300_rs_block r500_rs_block_copy_state = {
+static struct r300_rs_block r5xx_rs_block_copy_state = {
.ip[0] = R500_RS_SEL_S(0) |
R500_RS_SEL_T(1) |
R500_RS_SEL_R(R500_RS_IP_PTR_K0) |
--- /dev/null
+/*
+ * Copyright 2009 Corbin Simpson <MostAwesomeDude@gmail.com>
+ *
+ * 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
+ * on the rights to use, copy, modify, merge, publish, distribute, sub
+ * license, 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 (including the next
+ * paragraph) 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 NON-INFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHOR(S) AND/OR THEIR SUPPLIERS 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 "r300_vs.h"
+
+static void r300_vs_declare(struct r300_vs_asm* assembler,
+ struct tgsi_full_declaration* decl)
+{
+ switch (decl->Declaration.File) {
+ case TGSI_FILE_INPUT:
+ break;
+ case TGSI_FILE_OUTPUT:
+ switch (decl->Semantic.SemanticName) {
+ case TGSI_SEMANTIC_POSITION:
+ assembler->tab[decl->DeclarationRange.First] = 0;
+ break;
+ case TGSI_SEMANTIC_COLOR:
+ assembler->tab[decl->DeclarationRange.First] =
+ (assembler->point_size ? 1 : 0) +
+ assembler->out_colors;
+ break;
+ case TGSI_SEMANTIC_FOG:
+ case TGSI_SEMANTIC_GENERIC:
+ /* XXX multiple? */
+ assembler->tab[decl->DeclarationRange.First] =
+ (assembler->point_size ? 1 : 0) +
+ assembler->out_colors +
+ assembler->out_texcoords;
+ break;
+ case TGSI_SEMANTIC_PSIZE:
+ assembler->tab[decl->DeclarationRange.First] = 1;
+ break;
+ default:
+ debug_printf("r300: vs: Bad semantic declaration %d\n",
+ decl->Semantic.SemanticName);
+ break;
+ }
+ break;
+ case TGSI_FILE_CONSTANT:
+ break;
+ case TGSI_FILE_TEMPORARY:
+ assembler->temp_count++;
+ break;
+ default:
+ debug_printf("r300: vs: Bad file %d\n", decl->Declaration.File);
+ break;
+ }
+}
+
+static INLINE unsigned r300_vs_src_type(struct r300_vs_asm* assembler,
+ struct tgsi_src_register* src)
+{
+ switch (src->File) {
+ case TGSI_FILE_NULL:
+ case TGSI_FILE_INPUT:
+ /* Probably a zero or one swizzle */
+ return R300_PVS_SRC_REG_INPUT;
+ case TGSI_FILE_TEMPORARY:
+ return R300_PVS_SRC_REG_TEMPORARY;
+ case TGSI_FILE_CONSTANT:
+ case TGSI_FILE_IMMEDIATE:
+ return R300_PVS_SRC_REG_CONSTANT;
+ default:
+ debug_printf("r300: vs: Unimplemented src type %d\n", src->File);
+ break;
+ }
+ return 0;
+}
+
+static INLINE unsigned r300_vs_src(struct r300_vs_asm* assembler,
+ struct tgsi_src_register* src)
+{
+ switch (src->File) {
+ case TGSI_FILE_NULL:
+ case TGSI_FILE_INPUT:
+ case TGSI_FILE_TEMPORARY:
+ case TGSI_FILE_CONSTANT:
+ return src->Index;
+ case TGSI_FILE_IMMEDIATE:
+ return src->Index + assembler->imm_offset;
+ default:
+ debug_printf("r300: vs: Unimplemented src type %d\n", src->File);
+ break;
+ }
+ return 0;
+}
+
+static INLINE unsigned r300_vs_dst_type(struct r300_vs_asm* assembler,
+ struct tgsi_dst_register* dst)
+{
+ switch (dst->File) {
+ case TGSI_FILE_TEMPORARY:
+ return R300_PVS_DST_REG_TEMPORARY;
+ case TGSI_FILE_OUTPUT:
+ return R300_PVS_DST_REG_OUT;
+ default:
+ debug_printf("r300: vs: Unimplemented dst type %d\n", dst->File);
+ break;
+ }
+ return 0;
+}
+
+static INLINE unsigned r300_vs_dst(struct r300_vs_asm* assembler,
+ struct tgsi_dst_register* dst)
+{
+ switch (dst->File) {
+ case TGSI_FILE_TEMPORARY:
+ return dst->Index;
+ case TGSI_FILE_OUTPUT:
+ return assembler->tab[dst->Index];
+ default:
+ debug_printf("r300: vs: Unimplemented dst %d\n", dst->File);
+ break;
+ }
+ return 0;
+}
+
+static uint32_t r300_vs_op(unsigned op)
+{
+ switch (op) {
+ case TGSI_OPCODE_DP3:
+ case TGSI_OPCODE_DP4:
+ return R300_VE_DOT_PRODUCT;
+ case TGSI_OPCODE_MUL:
+ return R300_VE_MULTIPLY;
+ case TGSI_OPCODE_ADD:
+ case TGSI_OPCODE_MOV:
+ case TGSI_OPCODE_SUB:
+ case TGSI_OPCODE_SWZ:
+ return R300_VE_ADD;
+ case TGSI_OPCODE_MAX:
+ return R300_VE_MAXIMUM;
+ case TGSI_OPCODE_SLT:
+ return R300_VE_SET_LESS_THAN;
+ case TGSI_OPCODE_RSQ:
+ return R300_PVS_DST_MATH_INST | R300_ME_RECIP_DX;
+ case TGSI_OPCODE_MAD:
+ return R300_PVS_DST_MACRO_INST | R300_PVS_MACRO_OP_2CLK_MADD;
+ default:
+ break;
+ }
+ return 0;
+}
+
+static uint32_t r300_vs_swiz(struct tgsi_full_src_register* reg)
+{
+ if (reg->SrcRegister.Extended) {
+ return (reg->SrcRegister.Negate ? (0xf << 12) : 0) |
+ reg->SrcRegisterExtSwz.ExtSwizzleX |
+ (reg->SrcRegisterExtSwz.ExtSwizzleY << 3) |
+ (reg->SrcRegisterExtSwz.ExtSwizzleZ << 6) |
+ (reg->SrcRegisterExtSwz.ExtSwizzleW << 9);
+ } else {
+ return (reg->SrcRegister.Negate ? (0xf << 12) : 0) |
+ reg->SrcRegister.SwizzleX |
+ (reg->SrcRegister.SwizzleY << 3) |
+ (reg->SrcRegister.SwizzleZ << 6) |
+ (reg->SrcRegister.SwizzleW << 9);
+ }
+}
+
+/* XXX icky icky icky icky */
+static uint32_t r300_vs_scalar_swiz(struct tgsi_full_src_register* reg)
+{
+ if (reg->SrcRegister.Extended) {
+ return (reg->SrcRegister.Negate ? (0xf << 12) : 0) |
+ reg->SrcRegisterExtSwz.ExtSwizzleX |
+ (reg->SrcRegisterExtSwz.ExtSwizzleX << 3) |
+ (reg->SrcRegisterExtSwz.ExtSwizzleX << 6) |
+ (reg->SrcRegisterExtSwz.ExtSwizzleX << 9);
+ } else {
+ return (reg->SrcRegister.Negate ? (0xf << 12) : 0) |
+ reg->SrcRegister.SwizzleX |
+ (reg->SrcRegister.SwizzleX << 3) |
+ (reg->SrcRegister.SwizzleX << 6) |
+ (reg->SrcRegister.SwizzleX << 9);
+ }
+}
+
+/* XXX scalar stupidity */
+static void r300_vs_emit_inst(struct r300_vertex_shader* vs,
+ struct r300_vs_asm* assembler,
+ struct tgsi_full_src_register* src,
+ struct tgsi_full_dst_register* dst,
+ unsigned op,
+ unsigned count,
+ boolean is_scalar)
+{
+ int i = vs->instruction_count;
+ vs->instructions[i].inst0 = R300_PVS_DST_OPCODE(r300_vs_op(op)) |
+ R300_PVS_DST_REG_TYPE(r300_vs_dst_type(assembler, &dst->DstRegister)) |
+ R300_PVS_DST_OFFSET(r300_vs_dst(assembler, &dst->DstRegister)) |
+ R300_PVS_DST_WE(dst->DstRegister.WriteMask);
+ switch (count) {
+ case 3:
+ vs->instructions[i].inst3 =
+ R300_PVS_SRC_REG_TYPE(r300_vs_src_type(assembler,
+ &src[2].SrcRegister)) |
+ R300_PVS_SRC_OFFSET(r300_vs_src(assembler,
+ &src[2].SrcRegister)) |
+ R300_PVS_SRC_SWIZZLE(r300_vs_swiz(&src[2]));
+ /* Fall through */
+ case 2:
+ vs->instructions[i].inst2 =
+ R300_PVS_SRC_REG_TYPE(r300_vs_src_type(assembler,
+ &src[1].SrcRegister)) |
+ R300_PVS_SRC_OFFSET(r300_vs_src(assembler,
+ &src[1].SrcRegister)) |
+ R300_PVS_SRC_SWIZZLE(r300_vs_swiz(&src[1]));
+ /* Fall through */
+ case 1:
+ vs->instructions[i].inst1 =
+ R300_PVS_SRC_REG_TYPE(r300_vs_src_type(assembler,
+ &src[0].SrcRegister)) |
+ R300_PVS_SRC_OFFSET(r300_vs_src(assembler,
+ &src[0].SrcRegister)) |
+ /* XXX the icky, it burns */
+ R300_PVS_SRC_SWIZZLE(is_scalar ? r300_vs_scalar_swiz(&src[0])
+ : r300_vs_swiz(&src[0]));
+ break;
+ }
+ vs->instruction_count++;
+}
+
+static void r300_vs_instruction(struct r300_vertex_shader* vs,
+ struct r300_vs_asm* assembler,
+ struct tgsi_full_instruction* inst)
+{
+ switch (inst->Instruction.Opcode) {
+ case TGSI_OPCODE_RSQ:
+ r300_vs_emit_inst(vs, assembler, inst->FullSrcRegisters,
+ &inst->FullDstRegisters[0], inst->Instruction.Opcode,
+ 1, TRUE);
+ break;
+ case TGSI_OPCODE_SUB:
+ inst->FullSrcRegisters[1].SrcRegister.Negate =
+ !inst->FullSrcRegisters[1].SrcRegister.Negate;
+ /* Fall through */
+ case TGSI_OPCODE_ADD:
+ case TGSI_OPCODE_MUL:
+ case TGSI_OPCODE_MAX:
+ case TGSI_OPCODE_SLT:
+ r300_vs_emit_inst(vs, assembler, inst->FullSrcRegisters,
+ &inst->FullDstRegisters[0], inst->Instruction.Opcode,
+ 2, FALSE);
+ break;
+ case TGSI_OPCODE_DP3:
+ /* Set alpha swizzle to zero for src0 and src1 */
+ if (!inst->FullSrcRegisters[0].SrcRegister.Extended) {
+ inst->FullSrcRegisters[0].SrcRegister.Extended = TRUE;
+ inst->FullSrcRegisters[0].SrcRegisterExtSwz.ExtSwizzleX =
+ inst->FullSrcRegisters[0].SrcRegister.SwizzleX;
+ inst->FullSrcRegisters[0].SrcRegisterExtSwz.ExtSwizzleY =
+ inst->FullSrcRegisters[0].SrcRegister.SwizzleY;
+ inst->FullSrcRegisters[0].SrcRegisterExtSwz.ExtSwizzleZ =
+ inst->FullSrcRegisters[0].SrcRegister.SwizzleZ;
+ }
+ inst->FullSrcRegisters[0].SrcRegisterExtSwz.ExtSwizzleW =
+ TGSI_EXTSWIZZLE_ZERO;
+ if (!inst->FullSrcRegisters[1].SrcRegister.Extended) {
+ inst->FullSrcRegisters[1].SrcRegister.Extended = TRUE;
+ inst->FullSrcRegisters[1].SrcRegisterExtSwz.ExtSwizzleX =
+ inst->FullSrcRegisters[1].SrcRegister.SwizzleX;
+ inst->FullSrcRegisters[1].SrcRegisterExtSwz.ExtSwizzleY =
+ inst->FullSrcRegisters[1].SrcRegister.SwizzleY;
+ inst->FullSrcRegisters[1].SrcRegisterExtSwz.ExtSwizzleZ =
+ inst->FullSrcRegisters[1].SrcRegister.SwizzleZ;
+ }
+ inst->FullSrcRegisters[1].SrcRegisterExtSwz.ExtSwizzleW =
+ TGSI_EXTSWIZZLE_ZERO;
+ /* Fall through */
+ case TGSI_OPCODE_DP4:
+ r300_vs_emit_inst(vs, assembler, inst->FullSrcRegisters,
+ &inst->FullDstRegisters[0], inst->Instruction.Opcode,
+ 2, FALSE);
+ break;
+ case TGSI_OPCODE_MOV:
+ case TGSI_OPCODE_SWZ:
+ inst->FullSrcRegisters[1] = r300_constant_zero;
+ r300_vs_emit_inst(vs, assembler, inst->FullSrcRegisters,
+ &inst->FullDstRegisters[0], inst->Instruction.Opcode,
+ 2, FALSE);
+ break;
+ case TGSI_OPCODE_MAD:
+ r300_vs_emit_inst(vs, assembler, inst->FullSrcRegisters,
+ &inst->FullDstRegisters[0], inst->Instruction.Opcode,
+ 3, FALSE);
+ break;
+ case TGSI_OPCODE_END:
+ break;
+ default:
+ debug_printf("r300: vs: Bad opcode %d\n",
+ inst->Instruction.Opcode);
+ break;
+ }
+}
+
+static void r300_vs_init(struct r300_vertex_shader* vs,
+ struct r300_vs_asm* assembler)
+{
+ struct tgsi_shader_info* info = &vs->info;
+ int i;
+
+ for (i = 0; i < info->num_outputs; i++) {
+ switch (info->output_semantic_name[i]) {
+ case TGSI_SEMANTIC_PSIZE:
+ assembler->point_size = TRUE;
+ break;
+ case TGSI_SEMANTIC_COLOR:
+ assembler->out_colors++;
+ break;
+ case TGSI_SEMANTIC_FOG:
+ case TGSI_SEMANTIC_GENERIC:
+ assembler->out_texcoords++;
+ break;
+ }
+ }
+
+ vs->instruction_count = 0;
+}
+
+void r300_translate_vertex_shader(struct r300_context* r300,
+ struct r300_vertex_shader* vs)
+{
+ struct tgsi_parse_context parser;
+ int i;
+ struct r300_constant_buffer* consts =
+ &r300->shader_constants[PIPE_SHADER_VERTEX];
+
+ struct r300_vs_asm* assembler = CALLOC_STRUCT(r300_vs_asm);
+ if (assembler == NULL) {
+ return;
+ }
+
+ /* Init assembler. */
+ r300_vs_init(vs, assembler);
+
+ /* Setup starting offset for immediates. */
+ assembler->imm_offset = consts->user_count;
+
+ tgsi_parse_init(&parser, vs->state.tokens);
+
+ while (!tgsi_parse_end_of_tokens(&parser)) {
+ tgsi_parse_token(&parser);
+
+ /* This is seriously the lamest way to create fragment programs ever.
+ * I blame TGSI. */
+ switch (parser.FullToken.Token.Type) {
+ case TGSI_TOKEN_TYPE_DECLARATION:
+ /* Allocated registers sitting at the beginning
+ * of the program. */
+ r300_vs_declare(assembler, &parser.FullToken.FullDeclaration);
+ break;
+ case TGSI_TOKEN_TYPE_IMMEDIATE:
+ debug_printf("r300: Emitting immediate to constant buffer, "
+ "position %d\n",
+ assembler->imm_offset + assembler->imm_count);
+ /* I am not amused by the length of these. */
+ for (i = 0; i < 4; i++) {
+ consts->constants[assembler->imm_offset +
+ assembler->imm_count][i] =
+ parser.FullToken.FullImmediate.u.ImmediateFloat32[i]
+ .Float;
+ }
+ assembler->imm_count++;
+ break;
+ case TGSI_TOKEN_TYPE_INSTRUCTION:
+ r300_vs_instruction(vs, assembler,
+ &parser.FullToken.FullInstruction);
+ break;
+ }
+ }
+
+ debug_printf("r300: vs: %d texs and %d colors, first free reg is %d\n",
+ assembler->tex_count, assembler->color_count,
+ assembler->tex_count + assembler->color_count);
+
+ consts->count = consts->user_count + assembler->imm_count;
+ vs->uses_imms = assembler->imm_count;
+ debug_printf("r300: vs: %d total constants, "
+ "%d from user and %d from immediates\n", consts->count,
+ consts->user_count, assembler->imm_count);
+
+ debug_printf("r300: vs: tab: %d %d %d %d\n", assembler->tab[0],
+ assembler->tab[1], assembler->tab[2], assembler->tab[3]);
+
+ tgsi_dump(vs->state.tokens, 0);
+ /* XXX finish r300 vertex shader dumper */
+ r300_vs_dump(vs);
+
+ tgsi_parse_free(&parser);
+ FREE(assembler);
+}
--- /dev/null
+/*
+ * Copyright 2009 Corbin Simpson <MostAwesomeDude@gmail.com>
+ *
+ * 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
+ * on the rights to use, copy, modify, merge, publish, distribute, sub
+ * license, 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 (including the next
+ * paragraph) 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 NON-INFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHOR(S) AND/OR THEIR SUPPLIERS 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 R300_VS_H
+#define R300_VS_H
+
+#include "tgsi/tgsi_parse.h"
+#include "tgsi/tgsi_dump.h"
+
+#include "r300_context.h"
+#include "r300_debug.h"
+#include "r300_reg.h"
+#include "r300_screen.h"
+#include "r300_shader_inlines.h"
+
+/* XXX get these to r300_reg */
+#define R300_PVS_DST_OPCODE(x) ((x) << 0)
+# define R300_VE_DOT_PRODUCT 1
+# define R300_VE_MULTIPLY 2
+# define R300_VE_ADD 3
+# define R300_VE_MAXIMUM 7
+# define R300_VE_SET_LESS_THAN 10
+#define R300_PVS_DST_MATH_INST (1 << 6)
+# define R300_ME_RECIP_DX 6
+#define R300_PVS_DST_MACRO_INST (1 << 7)
+# define R300_PVS_MACRO_OP_2CLK_MADD 0
+#define R300_PVS_DST_REG_TYPE(x) ((x) << 8)
+# define R300_PVS_DST_REG_TEMPORARY 0
+# define R300_PVS_DST_REG_A0 1
+# define R300_PVS_DST_REG_OUT 2
+# define R300_PVS_DST_REG_OUT_REPL_X 3
+# define R300_PVS_DST_REG_ALT_TEMPORARY 4
+# define R300_PVS_DST_REG_INPUT 5
+#define R300_PVS_DST_OFFSET(x) ((x) << 13)
+#define R300_PVS_DST_WE(x) ((x) << 20)
+#define R300_PVS_DST_WE_XYZW (0xf << 20)
+
+#define R300_PVS_SRC_REG_TYPE(x) ((x) << 0)
+# define R300_PVS_SRC_REG_TEMPORARY 0
+# define R300_PVS_SRC_REG_INPUT 1
+# define R300_PVS_SRC_REG_CONSTANT 2
+# define R300_PVS_SRC_REG_ALT_TEMPORARY 3
+#define R300_PVS_SRC_OFFSET(x) ((x) << 5)
+#define R300_PVS_SRC_SWIZZLE(x) ((x) << 13)
+# define R300_PVS_SRC_SELECT_X 0
+# define R300_PVS_SRC_SELECT_Y 1
+# define R300_PVS_SRC_SELECT_Z 2
+# define R300_PVS_SRC_SELECT_W 3
+# define R300_PVS_SRC_SELECT_FORCE_0 4
+# define R300_PVS_SRC_SELECT_FORCE_1 5
+# define R300_PVS_SRC_SWIZZLE_XYZW \
+ ((R300_PVS_SRC_SELECT_X | (R300_PVS_SRC_SELECT_Y << 3) | \
+ (R300_PVS_SRC_SELECT_Z << 6) | (R300_PVS_SRC_SELECT_W << 9)) << 13)
+# define R300_PVS_SRC_SWIZZLE_ZERO \
+ ((R300_PVS_SRC_SELECT_FORCE_0 | (R300_PVS_SRC_SELECT_FORCE_0 << 3) | \
+ (R300_PVS_SRC_SELECT_FORCE_0 << 6) | \
+ (R300_PVS_SRC_SELECT_FORCE_0 << 9)) << 13)
+# define R300_PVS_SRC_SWIZZLE_ONE \
+ ((R300_PVS_SRC_SELECT_FORCE_1 | (R300_PVS_SRC_SELECT_FORCE_1 << 3) | \
+ (R300_PVS_SRC_SELECT_FORCE_1 << 6) | \
+ (R300_PVS_SRC_SELECT_FORCE_1 << 9)) << 13)
+#define R300_PVS_MODIFIER_X (1 << 25)
+#define R300_PVS_MODIFIER_Y (1 << 26)
+#define R300_PVS_MODIFIER_Z (1 << 27)
+#define R300_PVS_MODIFIER_W (1 << 28)
+#define R300_PVS_NEGATE_XYZW \
+ (R300_PVS_MODIFIER_X | R300_PVS_MODIFIER_Y | \
+ R300_PVS_MODIFIER_Z | R300_PVS_MODIFIER_W)
+
+/* Temporary struct used to hold assembly state while putting together
+ * fragment programs. */
+struct r300_vs_asm {
+ /* Pipe context. */
+ struct r300_context* r300;
+ /* Number of colors. */
+ unsigned color_count;
+ /* Number of texcoords. */
+ unsigned tex_count;
+ /* Number of requested temporary registers. */
+ unsigned temp_count;
+ /* Offset for immediate constants. Neither R300 nor R500 can do four
+ * inline constants per source, so instead we copy immediates into the
+ * constant buffer. */
+ unsigned imm_offset;
+ /* Number of immediate constants. */
+ unsigned imm_count;
+ /* Number of colors to write. */
+ unsigned out_colors;
+ /* Number of texcoords to write. */
+ unsigned out_texcoords;
+ /* Whether to emit point size. */
+ boolean point_size;
+ /* Tab of declared outputs to OVM outputs. */
+ unsigned tab[16];
+};
+
+static struct r300_vertex_shader r300_passthrough_vertex_shader = {
+ /* XXX translate these back into normal instructions */
+ .instruction_count = 2,
+ .instructions[0].inst0 = R300_PVS_DST_OPCODE(R300_VE_ADD) |
+ R300_PVS_DST_REG_TYPE(R300_PVS_DST_REG_OUT) |
+ R300_PVS_DST_OFFSET(0) | R300_PVS_DST_WE_XYZW,
+ .instructions[0].inst1 = R300_PVS_SRC_REG_TYPE(R300_PVS_SRC_REG_INPUT) |
+ R300_PVS_SRC_OFFSET(0) | R300_PVS_SRC_SWIZZLE_XYZW,
+ .instructions[0].inst2 = R300_PVS_SRC_SWIZZLE_ZERO,
+ .instructions[0].inst3 = 0x0,
+ .instructions[1].inst0 = R300_PVS_DST_OPCODE(R300_VE_ADD) |
+ R300_PVS_DST_REG_TYPE(R300_PVS_DST_REG_OUT) |
+ R300_PVS_DST_OFFSET(1) | R300_PVS_DST_WE_XYZW,
+ .instructions[1].inst1 = R300_PVS_SRC_REG_TYPE(R300_PVS_SRC_REG_INPUT) |
+ R300_PVS_SRC_OFFSET(1) | R300_PVS_SRC_SWIZZLE_XYZW,
+ .instructions[1].inst2 = R300_PVS_SRC_SWIZZLE_ZERO,
+ .instructions[1].inst3 = 0x0,
+};
+
+static struct r300_vertex_shader r300_texture_vertex_shader = {
+ /* XXX translate these back into normal instructions */
+ .instruction_count = 2,
+ .instructions[0].inst0 = R300_PVS_DST_OPCODE(R300_VE_ADD) |
+ R300_PVS_DST_REG_TYPE(R300_PVS_DST_REG_OUT) |
+ R300_PVS_DST_OFFSET(0) | R300_PVS_DST_WE_XYZW,
+ .instructions[0].inst1 = R300_PVS_SRC_REG_TYPE(R300_PVS_SRC_REG_INPUT) |
+ R300_PVS_SRC_OFFSET(0) | R300_PVS_SRC_SWIZZLE_XYZW,
+ .instructions[0].inst2 = R300_PVS_SRC_SWIZZLE_ZERO,
+ .instructions[0].inst3 = 0x0,
+ .instructions[1].inst0 = R300_PVS_DST_OPCODE(R300_VE_ADD) |
+ R300_PVS_DST_REG_TYPE(R300_PVS_DST_REG_OUT) |
+ R300_PVS_DST_OFFSET(1) | R300_PVS_DST_WE_XYZW,
+ .instructions[1].inst1 = R300_PVS_SRC_REG_TYPE(R300_PVS_SRC_REG_INPUT) |
+ R300_PVS_SRC_OFFSET(1) | R300_PVS_SRC_SWIZZLE_XYZW,
+ .instructions[1].inst2 = R300_PVS_SRC_SWIZZLE_ZERO,
+ .instructions[1].inst3 = 0x0,
+};
+
+void r300_translate_vertex_shader(struct r300_context* r300,
+ struct r300_vertex_shader* vs);
+
+#endif /* R300_VS_H */
--- /dev/null
+/*
+ * Copyright 2008 Corbin Simpson <MostAwesomeDude@gmail.com>
+ * Joakim Sindholt <opensource@zhasha.com>
+ *
+ * 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
+ * on the rights to use, copy, modify, merge, publish, distribute, sub
+ * license, 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 (including the next
+ * paragraph) 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 NON-INFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHOR(S) AND/OR THEIR SUPPLIERS 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 "r3xx_fs.h"
+
+static INLINE uint32_t r3xx_rgb_op(unsigned op)
+{
+ switch (op) {
+ case TGSI_OPCODE_MOV:
+ return R300_ALU_OUTC_CMP;
+ default:
+ return 0;
+ }
+}
+
+static INLINE uint32_t r3xx_alpha_op(unsigned op)
+{
+ switch (op) {
+ case TGSI_OPCODE_MOV:
+ return R300_ALU_OUTA_CMP;
+ default:
+ return 0;
+ }
+}
+
+static INLINE void r3xx_emit_maths(struct r3xx_fragment_shader* fs,
+ struct r300_fs_asm* assembler,
+ struct tgsi_full_src_register* src,
+ struct tgsi_full_dst_register* dst,
+ unsigned op,
+ unsigned count)
+{
+ int i = fs->alu_instruction_count;
+
+ fs->instructions[i].alu_rgb_inst = R300_RGB_SWIZA(R300_ALU_ARGC_SRC0C_XYZ) |
+ R300_RGB_SWIZB(R300_ALU_ARGC_SRC0C_XYZ) |
+ R300_RGB_SWIZC(R300_ALU_ARGC_ZERO) |
+ r3xx_rgb_op(op);
+ fs->instructions[i].alu_rgb_addr = R300_RGB_ADDR0(0) | R300_RGB_ADDR1(0) |
+ R300_RGB_ADDR2(0) | R300_ALU_DSTC_OUTPUT_XYZ;
+ fs->instructions[i].alu_alpha_inst = R300_ALPHA_SWIZA(R300_ALU_ARGA_SRC0A) |
+ R300_ALPHA_SWIZB(R300_ALU_ARGA_SRC0A) |
+ R300_ALPHA_SWIZC(R300_ALU_ARGA_ZERO) |
+ r3xx_alpha_op(op);
+ fs->instructions[i].alu_alpha_addr = R300_ALPHA_ADDR0(0) |
+ R300_ALPHA_ADDR1(0) | R300_ALPHA_ADDR2(0) | R300_ALU_DSTA_OUTPUT;
+
+ fs->alu_instruction_count++;
+}
+
+void r3xx_fs_finalize(struct r300_fragment_shader* fs,
+ struct r300_fs_asm* assembler)
+{
+ fs->stack_size = assembler->temp_count + assembler->temp_offset + 1;
+}
+
+void r3xx_fs_instruction(struct r3xx_fragment_shader* fs,
+ struct r300_fs_asm* assembler,
+ struct tgsi_full_instruction* inst)
+{
+ switch (inst->Instruction.Opcode) {
+ case TGSI_OPCODE_MOV:
+ /* src0 -> src1 and src2 forced to zero */
+ inst->FullSrcRegisters[1] = inst->FullSrcRegisters[0];
+ inst->FullSrcRegisters[2] = r300_constant_zero;
+ r3xx_emit_maths(fs, assembler, inst->FullSrcRegisters,
+ &inst->FullDstRegisters[0], inst->Instruction.Opcode, 3);
+ break;
+ case TGSI_OPCODE_END:
+ break;
+ default:
+ debug_printf("r300: fs: Bad opcode %d\n",
+ inst->Instruction.Opcode);
+ break;
+ }
+}
--- /dev/null
+/*
+ * Copyright 2008 Corbin Simpson <MostAwesomeDude@gmail.com>
+ * Joakim Sindholt <opensource@zhasha.com>
+ *
+ * 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
+ * on the rights to use, copy, modify, merge, publish, distribute, sub
+ * license, 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 (including the next
+ * paragraph) 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 NON-INFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHOR(S) AND/OR THEIR SUPPLIERS 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 R3XX_FS_H
+#define R3XX_FS_H
+
+#include "r300_fs_inlines.h"
+
+static struct r3xx_fragment_shader r3xx_passthrough_fragment_shader = {
+ .alu_instruction_count = 1,
+ .tex_instruction_count = 0,
+ .indirections = 0,
+ .shader.stack_size = 1,
+
+ .instructions[0].alu_rgb_inst = R300_RGB_SWIZA(R300_ALU_ARGC_SRC0C_XYZ) |
+ R300_RGB_SWIZB(R300_ALU_ARGC_SRC0C_XYZ) |
+ R300_RGB_SWIZC(R300_ALU_ARGC_ZERO) |
+ R300_ALU_OUTC_CMP,
+ .instructions[0].alu_rgb_addr = R300_RGB_ADDR0(0) | R300_RGB_ADDR1(0) |
+ R300_RGB_ADDR2(0) | R300_ALU_DSTC_OUTPUT_XYZ,
+ .instructions[0].alu_alpha_inst = R300_ALPHA_SWIZA(R300_ALU_ARGA_SRC0A) |
+ R300_ALPHA_SWIZB(R300_ALU_ARGA_SRC0A) |
+ R300_ALPHA_SWIZC(R300_ALU_ARGA_ZERO) |
+ R300_ALU_OUTA_CMP,
+ .instructions[0].alu_alpha_addr = R300_ALPHA_ADDR0(0) |
+ R300_ALPHA_ADDR1(0) | R300_ALPHA_ADDR2(0) | R300_ALU_DSTA_OUTPUT,
+};
+
+static struct r3xx_fragment_shader r3xx_texture_fragment_shader = {
+ .alu_instruction_count = 1,
+ .tex_instruction_count = 0,
+ .indirections = 0,
+ .shader.stack_size = 1,
+
+ .instructions[0].alu_rgb_inst = R300_RGB_SWIZA(R300_ALU_ARGC_SRC0C_XYZ) |
+ R300_RGB_SWIZB(R300_ALU_ARGC_SRC0C_XYZ) |
+ R300_RGB_SWIZC(R300_ALU_ARGC_ZERO) |
+ R300_ALU_OUTC_CMP,
+ .instructions[0].alu_rgb_addr = R300_RGB_ADDR0(0) | R300_RGB_ADDR1(0) |
+ R300_RGB_ADDR2(0) | R300_ALU_DSTC_OUTPUT_XYZ,
+ .instructions[0].alu_alpha_inst = R300_ALPHA_SWIZA(R300_ALU_ARGA_SRC0A) |
+ R300_ALPHA_SWIZB(R300_ALU_ARGA_SRC0A) |
+ R300_ALPHA_SWIZC(R300_ALU_ARGA_ZERO) |
+ R300_ALU_OUTA_CMP,
+ .instructions[0].alu_alpha_addr = R300_ALPHA_ADDR0(0) |
+ R300_ALPHA_ADDR1(0) | R300_ALPHA_ADDR2(0) | R300_ALU_DSTA_OUTPUT,
+};
+
+void r3xx_fs_finalize(struct r300_fragment_shader* fs,
+ struct r300_fs_asm* assembler);
+
+void r3xx_fs_instruction(struct r3xx_fragment_shader* fs,
+ struct r300_fs_asm* assembler,
+ struct tgsi_full_instruction* inst);
+
+#endif /* R3XX_FS_H */
--- /dev/null
+/*
+ * Copyright 2008 Corbin Simpson <MostAwesomeDude@gmail.com>
+ * Joakim Sindholt <opensource@zhasha.com>
+ *
+ * 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
+ * on the rights to use, copy, modify, merge, publish, distribute, sub
+ * license, 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 (including the next
+ * paragraph) 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 NON-INFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHOR(S) AND/OR THEIR SUPPLIERS 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 "r5xx_fs.h"
+
+static INLINE unsigned r5xx_fix_swiz(unsigned s)
+{
+ /* For historical reasons, the swizzle values x, y, z, w, and 0 are
+ * equivalent to the actual machine code, but 1 is not. Thus, we just
+ * adjust it a bit... */
+ if (s == TGSI_EXTSWIZZLE_ONE) {
+ return R500_SWIZZLE_ONE;
+ } else {
+ return s;
+ }
+}
+
+static uint32_t r5xx_rgba_swiz(struct tgsi_full_src_register* reg)
+{
+ if (reg->SrcRegister.Extended) {
+ return r5xx_fix_swiz(reg->SrcRegisterExtSwz.ExtSwizzleX) |
+ (r5xx_fix_swiz(reg->SrcRegisterExtSwz.ExtSwizzleY) << 3) |
+ (r5xx_fix_swiz(reg->SrcRegisterExtSwz.ExtSwizzleZ) << 6) |
+ (r5xx_fix_swiz(reg->SrcRegisterExtSwz.ExtSwizzleW) << 9);
+ } else {
+ return reg->SrcRegister.SwizzleX |
+ (reg->SrcRegister.SwizzleY << 3) |
+ (reg->SrcRegister.SwizzleZ << 6) |
+ (reg->SrcRegister.SwizzleW << 9);
+ }
+}
+
+static uint32_t r5xx_strq_swiz(struct tgsi_full_src_register* reg)
+{
+ return reg->SrcRegister.SwizzleX |
+ (reg->SrcRegister.SwizzleY << 2) |
+ (reg->SrcRegister.SwizzleZ << 4) |
+ (reg->SrcRegister.SwizzleW << 6);
+}
+
+static INLINE uint32_t r5xx_rgb_swiz(struct tgsi_full_src_register* reg)
+{
+ /* Only the first 9 bits... */
+ return (r5xx_rgba_swiz(reg) & 0x1ff) |
+ (reg->SrcRegister.Negate ? (1 << 9) : 0) |
+ (reg->SrcRegisterExtMod.Absolute ? (1 << 10) : 0);
+}
+
+static INLINE uint32_t r5xx_alpha_swiz(struct tgsi_full_src_register* reg)
+{
+ /* Only the last 3 bits... */
+ return (r5xx_rgba_swiz(reg) >> 9) |
+ (reg->SrcRegister.Negate ? (1 << 9) : 0) |
+ (reg->SrcRegisterExtMod.Absolute ? (1 << 10) : 0);
+}
+
+static INLINE uint32_t r5xx_rgba_op(unsigned op)
+{
+ switch (op) {
+ case TGSI_OPCODE_COS:
+ case TGSI_OPCODE_EX2:
+ case TGSI_OPCODE_LG2:
+ case TGSI_OPCODE_RCP:
+ case TGSI_OPCODE_RSQ:
+ case TGSI_OPCODE_SIN:
+ return R500_ALU_RGBA_OP_SOP;
+ case TGSI_OPCODE_DDX:
+ return R500_ALU_RGBA_OP_MDH;
+ case TGSI_OPCODE_DDY:
+ return R500_ALU_RGBA_OP_MDV;
+ case TGSI_OPCODE_FRC:
+ return R500_ALU_RGBA_OP_FRC;
+ case TGSI_OPCODE_DP3:
+ return R500_ALU_RGBA_OP_DP3;
+ case TGSI_OPCODE_DP4:
+ case TGSI_OPCODE_DPH:
+ return R500_ALU_RGBA_OP_DP4;
+ case TGSI_OPCODE_ABS:
+ case TGSI_OPCODE_CMP:
+ case TGSI_OPCODE_MOV:
+ case TGSI_OPCODE_SWZ:
+ return R500_ALU_RGBA_OP_CMP;
+ case TGSI_OPCODE_ADD:
+ case TGSI_OPCODE_MAD:
+ case TGSI_OPCODE_MUL:
+ case TGSI_OPCODE_SUB:
+ return R500_ALU_RGBA_OP_MAD;
+ default:
+ return 0;
+ }
+}
+
+static INLINE uint32_t r5xx_alpha_op(unsigned op)
+{
+ switch (op) {
+ case TGSI_OPCODE_COS:
+ return R500_ALPHA_OP_COS;
+ case TGSI_OPCODE_EX2:
+ return R500_ALPHA_OP_EX2;
+ case TGSI_OPCODE_LG2:
+ return R500_ALPHA_OP_LN2;
+ case TGSI_OPCODE_RCP:
+ return R500_ALPHA_OP_RCP;
+ case TGSI_OPCODE_RSQ:
+ return R500_ALPHA_OP_RSQ;
+ case TGSI_OPCODE_FRC:
+ return R500_ALPHA_OP_FRC;
+ case TGSI_OPCODE_SIN:
+ return R500_ALPHA_OP_SIN;
+ case TGSI_OPCODE_DDX:
+ return R500_ALPHA_OP_MDH;
+ case TGSI_OPCODE_DDY:
+ return R500_ALPHA_OP_MDV;
+ case TGSI_OPCODE_DP3:
+ case TGSI_OPCODE_DP4:
+ case TGSI_OPCODE_DPH:
+ return R500_ALPHA_OP_DP;
+ case TGSI_OPCODE_ABS:
+ case TGSI_OPCODE_CMP:
+ case TGSI_OPCODE_MOV:
+ case TGSI_OPCODE_SWZ:
+ return R500_ALPHA_OP_CMP;
+ case TGSI_OPCODE_ADD:
+ case TGSI_OPCODE_MAD:
+ case TGSI_OPCODE_MUL:
+ case TGSI_OPCODE_SUB:
+ return R500_ALPHA_OP_MAD;
+ default:
+ return 0;
+ }
+}
+
+static INLINE uint32_t r5xx_tex_op(unsigned op)
+{
+ switch (op) {
+ case TGSI_OPCODE_KIL:
+ return R500_TEX_INST_TEXKILL;
+ case TGSI_OPCODE_TEX:
+ return R500_TEX_INST_LD;
+ case TGSI_OPCODE_TXB:
+ return R500_TEX_INST_LODBIAS;
+ case TGSI_OPCODE_TXP:
+ return R500_TEX_INST_PROJ;
+ default:
+ return 0;
+ }
+}
+
+/* Setup an ALU operation. */
+static INLINE void r5xx_emit_maths(struct r5xx_fragment_shader* fs,
+ struct r300_fs_asm* assembler,
+ struct tgsi_full_src_register* src,
+ struct tgsi_full_dst_register* dst,
+ unsigned op,
+ unsigned count)
+{
+ int i = fs->instruction_count;
+
+ if (dst->DstRegister.File == TGSI_FILE_OUTPUT) {
+ fs->instructions[i].inst0 = R500_INST_TYPE_OUT;
+ if (r300_fs_is_depr(assembler, dst)) {
+ fs->instructions[i].inst4 = R500_W_OMASK;
+ } else {
+ fs->instructions[i].inst0 |=
+ R500_ALU_OMASK(dst->DstRegister.WriteMask);
+ }
+ } else {
+ fs->instructions[i].inst0 = R500_INST_TYPE_ALU |
+ R500_ALU_WMASK(dst->DstRegister.WriteMask);
+ }
+
+ fs->instructions[i].inst0 |= R500_INST_TEX_SEM_WAIT;
+
+ fs->instructions[i].inst4 |=
+ R500_ALPHA_ADDRD(r300_fs_dst(assembler, &dst->DstRegister));
+ fs->instructions[i].inst5 =
+ R500_ALU_RGBA_ADDRD(r300_fs_dst(assembler, &dst->DstRegister));
+
+ switch (count) {
+ case 3:
+ fs->instructions[i].inst1 =
+ R500_RGB_ADDR2(r300_fs_src(assembler, &src[2].SrcRegister));
+ fs->instructions[i].inst2 =
+ R500_ALPHA_ADDR2(r300_fs_src(assembler, &src[2].SrcRegister));
+ fs->instructions[i].inst5 |=
+ R500_ALU_RGBA_SEL_C_SRC2 |
+ R500_SWIZ_RGBA_C(r5xx_rgb_swiz(&src[2])) |
+ R500_ALU_RGBA_ALPHA_SEL_C_SRC2 |
+ R500_SWIZ_ALPHA_C(r5xx_alpha_swiz(&src[2]));
+ case 2:
+ fs->instructions[i].inst1 |=
+ R500_RGB_ADDR1(r300_fs_src(assembler, &src[1].SrcRegister));
+ fs->instructions[i].inst2 |=
+ R500_ALPHA_ADDR1(r300_fs_src(assembler, &src[1].SrcRegister));
+ fs->instructions[i].inst3 =
+ R500_ALU_RGB_SEL_B_SRC1 |
+ R500_SWIZ_RGB_B(r5xx_rgb_swiz(&src[1]));
+ fs->instructions[i].inst4 |=
+ R500_ALPHA_SEL_B_SRC1 |
+ R500_SWIZ_ALPHA_B(r5xx_alpha_swiz(&src[1]));
+ case 1:
+ case 0:
+ default:
+ fs->instructions[i].inst1 |=
+ R500_RGB_ADDR0(r300_fs_src(assembler, &src[0].SrcRegister));
+ fs->instructions[i].inst2 |=
+ R500_ALPHA_ADDR0(r300_fs_src(assembler, &src[0].SrcRegister));
+ fs->instructions[i].inst3 |=
+ R500_ALU_RGB_SEL_A_SRC0 |
+ R500_SWIZ_RGB_A(r5xx_rgb_swiz(&src[0]));
+ fs->instructions[i].inst4 |=
+ R500_ALPHA_SEL_A_SRC0 |
+ R500_SWIZ_ALPHA_A(r5xx_alpha_swiz(&src[0]));
+ break;
+ }
+
+ fs->instructions[i].inst4 |= r5xx_alpha_op(op);
+ fs->instructions[i].inst5 |= r5xx_rgba_op(op);
+
+ fs->instruction_count++;
+}
+
+static INLINE void r5xx_emit_tex(struct r5xx_fragment_shader* fs,
+ struct r300_fs_asm* assembler,
+ struct tgsi_full_src_register* src,
+ struct tgsi_full_dst_register* dst,
+ uint32_t op)
+{
+ int i = fs->instruction_count;
+
+ fs->instructions[i].inst0 = R500_INST_TYPE_TEX |
+ R500_TEX_WMASK(dst->DstRegister.WriteMask) |
+ R500_INST_TEX_SEM_WAIT;
+ fs->instructions[i].inst1 = R500_TEX_ID(0) |
+ R500_TEX_SEM_ACQUIRE | //R500_TEX_IGNORE_UNCOVERED |
+ r5xx_tex_op(op);
+ fs->instructions[i].inst2 =
+ R500_TEX_SRC_ADDR(r300_fs_src(assembler, &src->SrcRegister)) |
+ R500_SWIZ_TEX_STRQ(r5xx_strq_swiz(src)) |
+ R500_TEX_DST_ADDR(r300_fs_dst(assembler, &dst->DstRegister)) |
+ R500_TEX_DST_R_SWIZ_R | R500_TEX_DST_G_SWIZ_G |
+ R500_TEX_DST_B_SWIZ_B | R500_TEX_DST_A_SWIZ_A;
+
+ if (dst->DstRegister.File == TGSI_FILE_OUTPUT) {
+ fs->instructions[i].inst2 |=
+ R500_TEX_DST_ADDR(assembler->temp_count +
+ assembler->temp_offset);
+
+ fs->instruction_count++;
+
+ /* Setup and emit a MOV. */
+ src[0].SrcRegister.Index = assembler->temp_count;
+ src[0].SrcRegister.File = TGSI_FILE_TEMPORARY;
+
+ src[1] = src[0];
+ src[2] = r300_constant_zero;
+ r5xx_emit_maths(fs, assembler, src, dst, TGSI_OPCODE_MOV, 3);
+ } else {
+ fs->instruction_count++;
+ }
+}
+
+void r5xx_fs_finalize(struct r5xx_fragment_shader* fs,
+ struct r300_fs_asm* assembler)
+{
+ /* XXX should this just go with OPCODE_END? */
+ fs->instructions[fs->instruction_count - 1].inst0 |=
+ R500_INST_LAST;
+}
+
+void r5xx_fs_instruction(struct r5xx_fragment_shader* fs,
+ struct r300_fs_asm* assembler,
+ struct tgsi_full_instruction* inst)
+{
+ /* Switch between opcodes. When possible, prefer using the official
+ * AMD/ATI names for opcodes, please, as it facilitates using the
+ * documentation. */
+ switch (inst->Instruction.Opcode) {
+ /* XXX trig needs extra prep */
+ case TGSI_OPCODE_COS:
+ case TGSI_OPCODE_SIN:
+ /* The simple scalar ops. */
+ case TGSI_OPCODE_EX2:
+ case TGSI_OPCODE_LG2:
+ case TGSI_OPCODE_RCP:
+ case TGSI_OPCODE_RSQ:
+ /* Copy red swizzle to alpha for src0 */
+ inst->FullSrcRegisters[0].SrcRegisterExtSwz.ExtSwizzleW =
+ inst->FullSrcRegisters[0].SrcRegisterExtSwz.ExtSwizzleX;
+ inst->FullSrcRegisters[0].SrcRegister.SwizzleW =
+ inst->FullSrcRegisters[0].SrcRegister.SwizzleX;
+ /* Fall through */
+ case TGSI_OPCODE_DDX:
+ case TGSI_OPCODE_DDY:
+ case TGSI_OPCODE_FRC:
+ r5xx_emit_maths(fs, assembler, inst->FullSrcRegisters,
+ &inst->FullDstRegisters[0], inst->Instruction.Opcode, 1);
+ break;
+
+ /* The dot products. */
+ case TGSI_OPCODE_DPH:
+ /* Set alpha swizzle to one for src0 */
+ if (!inst->FullSrcRegisters[0].SrcRegister.Extended) {
+ inst->FullSrcRegisters[0].SrcRegister.Extended = TRUE;
+ inst->FullSrcRegisters[0].SrcRegisterExtSwz.ExtSwizzleX =
+ inst->FullSrcRegisters[0].SrcRegister.SwizzleX;
+ inst->FullSrcRegisters[0].SrcRegisterExtSwz.ExtSwizzleY =
+ inst->FullSrcRegisters[0].SrcRegister.SwizzleY;
+ inst->FullSrcRegisters[0].SrcRegisterExtSwz.ExtSwizzleZ =
+ inst->FullSrcRegisters[0].SrcRegister.SwizzleZ;
+ }
+ inst->FullSrcRegisters[0].SrcRegisterExtSwz.ExtSwizzleW =
+ TGSI_EXTSWIZZLE_ONE;
+ /* Fall through */
+ case TGSI_OPCODE_DP3:
+ case TGSI_OPCODE_DP4:
+ r5xx_emit_maths(fs, assembler, inst->FullSrcRegisters,
+ &inst->FullDstRegisters[0], inst->Instruction.Opcode, 2);
+ break;
+
+ /* Simple three-source operations. */
+ case TGSI_OPCODE_CMP:
+ /* Swap src0 and src2 */
+ inst->FullSrcRegisters[3] = inst->FullSrcRegisters[2];
+ inst->FullSrcRegisters[2] = inst->FullSrcRegisters[0];
+ inst->FullSrcRegisters[0] = inst->FullSrcRegisters[3];
+ r5xx_emit_maths(fs, assembler, inst->FullSrcRegisters,
+ &inst->FullDstRegisters[0], inst->Instruction.Opcode, 3);
+ break;
+
+ /* The MAD variants. */
+ case TGSI_OPCODE_SUB:
+ /* Just like ADD, but flip the negation on src1 first */
+ inst->FullSrcRegisters[1].SrcRegister.Negate =
+ !inst->FullSrcRegisters[1].SrcRegister.Negate;
+ /* Fall through */
+ case TGSI_OPCODE_ADD:
+ /* Force src0 to one, move all registers over */
+ inst->FullSrcRegisters[2] = inst->FullSrcRegisters[1];
+ inst->FullSrcRegisters[1] = inst->FullSrcRegisters[0];
+ inst->FullSrcRegisters[0] = r300_constant_one;
+ r5xx_emit_maths(fs, assembler, inst->FullSrcRegisters,
+ &inst->FullDstRegisters[0], inst->Instruction.Opcode, 3);
+ break;
+ case TGSI_OPCODE_MUL:
+ /* Force our src2 to zero */
+ inst->FullSrcRegisters[2] = r300_constant_zero;
+ r5xx_emit_maths(fs, assembler, inst->FullSrcRegisters,
+ &inst->FullDstRegisters[0], inst->Instruction.Opcode, 3);
+ break;
+ case TGSI_OPCODE_MAD:
+ r5xx_emit_maths(fs, assembler, inst->FullSrcRegisters,
+ &inst->FullDstRegisters[0], inst->Instruction.Opcode, 3);
+ break;
+
+ /* The MOV variants. */
+ case TGSI_OPCODE_ABS:
+ /* Set absolute value modifiers. */
+ inst->FullSrcRegisters[0].SrcRegisterExtMod.Absolute = TRUE;
+ /* Fall through */
+ case TGSI_OPCODE_MOV:
+ case TGSI_OPCODE_SWZ:
+ /* src0 -> src1 and src2 forced to zero */
+ inst->FullSrcRegisters[1] = inst->FullSrcRegisters[0];
+ inst->FullSrcRegisters[2] = r300_constant_zero;
+ r5xx_emit_maths(fs, assembler, inst->FullSrcRegisters,
+ &inst->FullDstRegisters[0], inst->Instruction.Opcode, 3);
+ break;
+
+ /* The compound and hybrid insts. */
+ case TGSI_OPCODE_LRP:
+ /* LRP DST A, B, C -> MAD TMP -A, C, C; MAD DST A, B, TMP */
+ inst->FullSrcRegisters[3] = inst->FullSrcRegisters[1];
+ inst->FullSrcRegisters[1] = inst->FullSrcRegisters[2];
+ inst->FullSrcRegisters[0].SrcRegister.Negate =
+ !(inst->FullSrcRegisters[0].SrcRegister.Negate);
+ inst->FullDstRegisters[1] = inst->FullDstRegisters[0];
+ inst->FullDstRegisters[0].DstRegister.Index =
+ assembler->temp_count;
+ inst->FullDstRegisters[0].DstRegister.File = TGSI_FILE_TEMPORARY;
+ r5xx_emit_maths(fs, assembler, inst->FullSrcRegisters,
+ &inst->FullDstRegisters[0], TGSI_OPCODE_MAD, 3);
+ inst->FullSrcRegisters[2].SrcRegister.Index =
+ assembler->temp_count;
+ inst->FullSrcRegisters[2].SrcRegister.File = TGSI_FILE_TEMPORARY;
+ inst->FullSrcRegisters[2].SrcRegister.SwizzleX = TGSI_SWIZZLE_X;
+ inst->FullSrcRegisters[2].SrcRegister.SwizzleY = TGSI_SWIZZLE_Y;
+ inst->FullSrcRegisters[2].SrcRegister.SwizzleZ = TGSI_SWIZZLE_Z;
+ inst->FullSrcRegisters[2].SrcRegister.SwizzleW = TGSI_SWIZZLE_W;
+ inst->FullSrcRegisters[1] = inst->FullSrcRegisters[3];
+ inst->FullSrcRegisters[0].SrcRegister.Negate =
+ !(inst->FullSrcRegisters[0].SrcRegister.Negate);
+ inst->FullDstRegisters[0] = inst->FullDstRegisters[1];
+ r5xx_emit_maths(fs, assembler, inst->FullSrcRegisters,
+ &inst->FullDstRegisters[0], TGSI_OPCODE_MAD, 3);
+ break;
+ case TGSI_OPCODE_POW:
+ /* POW DST A, B -> LG2 TMP A; MUL TMP TMP, B; EX2 DST TMP */
+ inst->FullSrcRegisters[0].SrcRegisterExtSwz.ExtSwizzleW =
+ inst->FullSrcRegisters[0].SrcRegisterExtSwz.ExtSwizzleX;
+ inst->FullSrcRegisters[0].SrcRegister.SwizzleW =
+ inst->FullSrcRegisters[0].SrcRegister.SwizzleX;
+ inst->FullDstRegisters[1] = inst->FullDstRegisters[0];
+ inst->FullDstRegisters[0].DstRegister.Index =
+ assembler->temp_count;
+ inst->FullDstRegisters[0].DstRegister.File = TGSI_FILE_TEMPORARY;
+ r5xx_emit_maths(fs, assembler, inst->FullSrcRegisters,
+ &inst->FullDstRegisters[0], TGSI_OPCODE_LG2, 1);
+ inst->FullSrcRegisters[0].SrcRegister.Index =
+ assembler->temp_count;
+ inst->FullSrcRegisters[0].SrcRegister.File = TGSI_FILE_TEMPORARY;
+ inst->FullSrcRegisters[0].SrcRegister.SwizzleX = TGSI_SWIZZLE_X;
+ inst->FullSrcRegisters[0].SrcRegister.SwizzleY = TGSI_SWIZZLE_Y;
+ inst->FullSrcRegisters[0].SrcRegister.SwizzleZ = TGSI_SWIZZLE_Z;
+ inst->FullSrcRegisters[0].SrcRegister.SwizzleW = TGSI_SWIZZLE_W;
+ inst->FullSrcRegisters[2] = r300_constant_zero;
+ r5xx_emit_maths(fs, assembler, inst->FullSrcRegisters,
+ &inst->FullDstRegisters[0], TGSI_OPCODE_MUL, 3);
+ inst->FullDstRegisters[0] = inst->FullDstRegisters[1];
+ r5xx_emit_maths(fs, assembler, inst->FullSrcRegisters,
+ &inst->FullDstRegisters[0], TGSI_OPCODE_EX2, 1);
+ break;
+
+ /* The texture instruction set. */
+ case TGSI_OPCODE_KIL:
+ case TGSI_OPCODE_TEX:
+ case TGSI_OPCODE_TXB:
+ case TGSI_OPCODE_TXP:
+ r5xx_emit_tex(fs, assembler, &inst->FullSrcRegisters[0],
+ &inst->FullDstRegisters[0], inst->Instruction.Opcode);
+ break;
+
+ /* This is the end. My only friend, the end. */
+ case TGSI_OPCODE_END:
+ break;
+ default:
+ debug_printf("r300: fs: Bad opcode %d\n",
+ inst->Instruction.Opcode);
+ break;
+ }
+
+ /* Clamp, if saturation flags are set. */
+ if (inst->Instruction.Saturate == TGSI_SAT_ZERO_ONE) {
+ fs->instructions[fs->instruction_count - 1].inst0 |=
+ R500_INST_RGB_CLAMP | R500_INST_ALPHA_CLAMP;
+ }
+}
--- /dev/null
+/*
+ * Copyright 2008 Corbin Simpson <MostAwesomeDude@gmail.com>
+ * Joakim Sindholt <opensource@zhasha.com>
+ *
+ * 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
+ * on the rights to use, copy, modify, merge, publish, distribute, sub
+ * license, 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 (including the next
+ * paragraph) 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 NON-INFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHOR(S) AND/OR THEIR SUPPLIERS 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 R5XX_FS_H
+#define R5XX_FS_H
+
+#include "r300_fs_inlines.h"
+
+/* XXX this all should find its way back to r300_reg */
+/* Swizzle tools */
+#define R500_SWIZZLE_ZERO 4
+#define R500_SWIZZLE_HALF 5
+#define R500_SWIZZLE_ONE 6
+#define R500_SWIZ_RGB_ZERO ((4 << 0) | (4 << 3) | (4 << 6))
+#define R500_SWIZ_RGB_ONE ((6 << 0) | (6 << 3) | (6 << 6))
+#define R500_SWIZ_RGB_RGB ((0 << 0) | (1 << 3) | (2 << 6))
+#define R500_SWIZ_MOD_NEG 1
+#define R500_SWIZ_MOD_ABS 2
+#define R500_SWIZ_MOD_NEG_ABS 3
+/* Swizzles for inst2 */
+#define R500_SWIZ_TEX_STRQ(x) ((x) << 8)
+#define R500_SWIZ_TEX_RGBA(x) ((x) << 24)
+/* Swizzles for inst3 */
+#define R500_SWIZ_RGB_A(x) ((x) << 2)
+#define R500_SWIZ_RGB_B(x) ((x) << 15)
+/* Swizzles for inst4 */
+#define R500_SWIZ_ALPHA_A(x) ((x) << 14)
+#define R500_SWIZ_ALPHA_B(x) ((x) << 21)
+/* Swizzle for inst5 */
+#define R500_SWIZ_RGBA_C(x) ((x) << 14)
+#define R500_SWIZ_ALPHA_C(x) ((x) << 27)
+/* Writemasks */
+#define R500_TEX_WMASK(x) ((x) << 11)
+#define R500_ALU_WMASK(x) ((x) << 11)
+#define R500_ALU_OMASK(x) ((x) << 15)
+#define R500_W_OMASK (1 << 31)
+
+static struct r5xx_fragment_shader r5xx_passthrough_fragment_shader = {
+ .shader.stack_size = 0,
+ .instruction_count = 1,
+ .instructions[0].inst0 = R500_INST_TYPE_OUT |
+ R500_INST_TEX_SEM_WAIT | R500_INST_LAST |
+ R500_INST_RGB_OMASK_RGB | R500_INST_ALPHA_OMASK |
+ R500_INST_RGB_CLAMP | R500_INST_ALPHA_CLAMP,
+ .instructions[0].inst1 =
+ R500_RGB_ADDR0(0) | R500_RGB_ADDR1(0) | R500_RGB_ADDR1_CONST |
+ R500_RGB_ADDR2(0) | R500_RGB_ADDR2_CONST,
+ .instructions[0].inst2 =
+ R500_ALPHA_ADDR0(0) | R500_ALPHA_ADDR1(0) | R500_ALPHA_ADDR1_CONST |
+ R500_ALPHA_ADDR2(0) | R500_ALPHA_ADDR2_CONST,
+ .instructions[0].inst3 =
+ R500_ALU_RGB_SEL_A_SRC0 | R500_ALU_RGB_R_SWIZ_A_R |
+ R500_ALU_RGB_G_SWIZ_A_G | R500_ALU_RGB_B_SWIZ_A_B |
+ R500_ALU_RGB_SEL_B_SRC0 | R500_ALU_RGB_R_SWIZ_B_R |
+ R500_ALU_RGB_B_SWIZ_B_G | R500_ALU_RGB_G_SWIZ_B_B,
+ .instructions[0].inst4 =
+ R500_ALPHA_OP_CMP | R500_ALPHA_SWIZ_A_A | R500_ALPHA_SWIZ_B_A,
+ .instructions[0].inst5 =
+ R500_ALU_RGBA_OP_CMP | R500_ALU_RGBA_R_SWIZ_0 |
+ R500_ALU_RGBA_G_SWIZ_0 | R500_ALU_RGBA_B_SWIZ_0 |
+ R500_ALU_RGBA_A_SWIZ_0,
+};
+
+static struct r5xx_fragment_shader r5xx_texture_fragment_shader = {
+ .shader.stack_size = 1,
+ .instruction_count = 2,
+ .instructions[0].inst0 = R500_INST_TYPE_TEX |
+ R500_INST_TEX_SEM_WAIT |
+ R500_INST_RGB_WMASK_RGB | R500_INST_ALPHA_WMASK |
+ R500_INST_RGB_CLAMP | R500_INST_ALPHA_CLAMP,
+ .instructions[0].inst1 = R500_TEX_ID(0) | R500_TEX_INST_LD |
+ R500_TEX_SEM_ACQUIRE | R500_TEX_IGNORE_UNCOVERED,
+ .instructions[0].inst2 = R500_TEX_SRC_ADDR(0) |
+ R500_TEX_SRC_S_SWIZ_R | R500_TEX_SRC_T_SWIZ_G |
+ R500_TEX_SRC_R_SWIZ_B | R500_TEX_SRC_Q_SWIZ_A |
+ R500_TEX_DST_ADDR(0) |
+ R500_TEX_DST_R_SWIZ_R | R500_TEX_DST_G_SWIZ_G |
+ R500_TEX_DST_B_SWIZ_B | R500_TEX_DST_A_SWIZ_A,
+ .instructions[0].inst3 = 0x0,
+ .instructions[0].inst4 = 0x0,
+ .instructions[0].inst5 = 0x0,
+ .instructions[1].inst0 = R500_INST_TYPE_OUT |
+ R500_INST_TEX_SEM_WAIT | R500_INST_LAST |
+ R500_INST_RGB_OMASK_RGB | R500_INST_ALPHA_OMASK |
+ R500_INST_RGB_CLAMP | R500_INST_ALPHA_CLAMP,
+ .instructions[1].inst1 =
+ R500_RGB_ADDR0(0) | R500_RGB_ADDR1(0) | R500_RGB_ADDR1_CONST |
+ R500_RGB_ADDR2(0) | R500_RGB_ADDR2_CONST,
+ .instructions[1].inst2 =
+ R500_ALPHA_ADDR0(0) | R500_ALPHA_ADDR1(0) | R500_ALPHA_ADDR1_CONST |
+ R500_ALPHA_ADDR2(0) | R500_ALPHA_ADDR2_CONST,
+ .instructions[1].inst3 =
+ R500_ALU_RGB_SEL_A_SRC0 | R500_ALU_RGB_R_SWIZ_A_R |
+ R500_ALU_RGB_G_SWIZ_A_G | R500_ALU_RGB_B_SWIZ_A_B |
+ R500_ALU_RGB_SEL_B_SRC0 | R500_ALU_RGB_R_SWIZ_B_R |
+ R500_ALU_RGB_B_SWIZ_B_G | R500_ALU_RGB_G_SWIZ_B_B,
+ .instructions[1].inst4 =
+ R500_ALPHA_OP_CMP | R500_ALPHA_SWIZ_A_A | R500_ALPHA_SWIZ_B_A,
+ .instructions[1].inst5 =
+ R500_ALU_RGBA_OP_CMP | R500_ALU_RGBA_R_SWIZ_0 |
+ R500_ALU_RGBA_G_SWIZ_0 | R500_ALU_RGBA_B_SWIZ_0 |
+ R500_ALU_RGBA_A_SWIZ_0,
+};
+
+void r5xx_fs_finalize(struct r5xx_fragment_shader* fs,
+ struct r300_fs_asm* assembler);
+
+void r5xx_fs_instruction(struct r5xx_fragment_shader* fs,
+ struct r300_fs_asm* assembler,
+ struct tgsi_full_instruction* inst);
+
+#endif /* R5XX_FS_H */