diff options
-rw-r--r-- | src/gallium/drivers/r300/r300_fs.c | 55 | ||||
-rw-r--r-- | src/mesa/drivers/dri/r300/compiler/radeon_code.h | 16 | ||||
-rw-r--r-- | src/mesa/drivers/dri/r300/compiler/radeon_program_tex.c | 265 |
3 files changed, 156 insertions, 180 deletions
diff --git a/src/gallium/drivers/r300/r300_fs.c b/src/gallium/drivers/r300/r300_fs.c index b8dab88ef09..3f89987897d 100644 --- a/src/gallium/drivers/r300/r300_fs.c +++ b/src/gallium/drivers/r300/r300_fs.c @@ -150,12 +150,16 @@ static void get_external_state( unsigned char *swizzle; for (i = 0; i < texstate->sampler_state_count; i++) { - struct r300_sampler_state* s = texstate->sampler_states[i]; + struct r300_sampler_state *s = texstate->sampler_states[i]; + struct r300_sampler_view *v = texstate->sampler_views[i]; + struct r300_texture *t; - if (!s) { + if (!s || !v) { continue; } + t = r300_texture(texstate->sampler_views[i]->base.texture); + if (s->state.compare_mode == PIPE_TEX_COMPARE_R_TO_TEXTURE) { state->unit[i].compare_mode_enabled = 1; @@ -176,34 +180,25 @@ static void get_external_state( state->unit[i].non_normalized_coords = !s->state.normalized_coords; - if (texstate->sampler_views[i]) { - struct r300_texture *t; - t = (struct r300_texture*)texstate->sampler_views[i]->base.texture; - - /* XXX this should probably take into account STR, not just S. */ - if (t->desc.is_npot) { - switch (s->state.wrap_s) { - case PIPE_TEX_WRAP_REPEAT: - state->unit[i].wrap_mode = RC_WRAP_REPEAT; - state->unit[i].fake_npot = TRUE; - break; - - case PIPE_TEX_WRAP_MIRROR_REPEAT: - state->unit[i].wrap_mode = RC_WRAP_MIRRORED_REPEAT; - state->unit[i].fake_npot = TRUE; - break; - - case PIPE_TEX_WRAP_MIRROR_CLAMP: - case PIPE_TEX_WRAP_MIRROR_CLAMP_TO_EDGE: - case PIPE_TEX_WRAP_MIRROR_CLAMP_TO_BORDER: - state->unit[i].wrap_mode = RC_WRAP_MIRRORED_CLAMP; - state->unit[i].fake_npot = TRUE; - break; - - default: - state->unit[i].wrap_mode = RC_WRAP_NONE; - break; - } + /* XXX this should probably take into account STR, not just S. */ + if (t->desc.is_npot) { + switch (s->state.wrap_s) { + case PIPE_TEX_WRAP_REPEAT: + state->unit[i].wrap_mode = RC_WRAP_REPEAT; + break; + + case PIPE_TEX_WRAP_MIRROR_REPEAT: + state->unit[i].wrap_mode = RC_WRAP_MIRRORED_REPEAT; + break; + + case PIPE_TEX_WRAP_MIRROR_CLAMP: + case PIPE_TEX_WRAP_MIRROR_CLAMP_TO_EDGE: + case PIPE_TEX_WRAP_MIRROR_CLAMP_TO_BORDER: + state->unit[i].wrap_mode = RC_WRAP_MIRRORED_CLAMP; + break; + + default: + state->unit[i].wrap_mode = RC_WRAP_NONE; } } } diff --git a/src/mesa/drivers/dri/r300/compiler/radeon_code.h b/src/mesa/drivers/dri/r300/compiler/radeon_code.h index f76676fae8e..53cc1bd77e9 100644 --- a/src/mesa/drivers/dri/r300/compiler/radeon_code.h +++ b/src/mesa/drivers/dri/r300/compiler/radeon_code.h @@ -126,11 +126,7 @@ struct r300_fragment_program_external_state { struct { /** * If the sampler is used as a shadow sampler, - * this field is: - * 0 - GL_LUMINANCE - * 1 - GL_INTENSITY - * 2 - GL_ALPHA - * depending on the depth texture mode. + * this field contains swizzle depending on the depth texture mode. */ unsigned depth_texture_swizzle:12; @@ -150,13 +146,9 @@ struct r300_fragment_program_external_state { unsigned compare_mode_enabled : 1; /** - * If the sampler needs to fake NPOT, this field is set. - */ - unsigned fake_npot : 1; - - /** - * If the sampler will recieve non-normalized coords, - * this field is set. + * If the sampler will receive non-normalized coords, + * this field is set. The scaling factor is given by + * RC_STATE_R300_TEXRECT_FACTOR. */ unsigned non_normalized_coords : 1; diff --git a/src/mesa/drivers/dri/r300/compiler/radeon_program_tex.c b/src/mesa/drivers/dri/r300/compiler/radeon_program_tex.c index ddce590ee66..7ce5fb8639f 100644 --- a/src/mesa/drivers/dri/r300/compiler/radeon_program_tex.c +++ b/src/mesa/drivers/dri/r300/compiler/radeon_program_tex.c @@ -1,5 +1,6 @@ /* * Copyright (C) 2010 Corbin Simpson + * Copyright (C) 2010 Marek Olšák <[email protected]> * * All Rights Reserved. * @@ -46,31 +47,28 @@ static struct rc_src_register shadow_ambient(struct r300_fragment_program_compil return reg; } -static void lower_texture_rect(struct r300_fragment_program_compiler *compiler, - struct rc_instruction *inst) +static void scale_texcoords(struct r300_fragment_program_compiler *compiler, + struct rc_instruction *inst, + unsigned state_constant) { - struct rc_instruction *inst_rect; - unsigned temp = rc_find_free_temporary(&compiler->Base); + struct rc_instruction *inst_mov; - if (inst->U.I.TexSrcTarget == RC_TEXTURE_RECT || - compiler->state.unit[inst->U.I.TexSrcUnit].non_normalized_coords) { - inst_rect = rc_insert_new_instruction(&compiler->Base, inst->Prev); + unsigned temp = rc_find_free_temporary(&compiler->Base); - inst_rect->U.I.Opcode = RC_OPCODE_MUL; - inst_rect->U.I.DstReg.File = RC_FILE_TEMPORARY; - inst_rect->U.I.DstReg.Index = temp; - inst_rect->U.I.SrcReg[0] = inst->U.I.SrcReg[0]; - inst_rect->U.I.SrcReg[1].File = RC_FILE_CONSTANT; - inst_rect->U.I.SrcReg[1].Index = - rc_constants_add_state(&compiler->Base.Program.Constants, - RC_STATE_R300_TEXRECT_FACTOR, inst->U.I.TexSrcUnit); + inst_mov = rc_insert_new_instruction(&compiler->Base, inst->Prev); - reset_srcreg(&inst->U.I.SrcReg[0]); - inst->U.I.SrcReg[0].File = RC_FILE_TEMPORARY; - inst->U.I.SrcReg[0].Index = temp; + inst_mov->U.I.Opcode = RC_OPCODE_MUL; + inst_mov->U.I.DstReg.File = RC_FILE_TEMPORARY; + inst_mov->U.I.DstReg.Index = temp; + inst_mov->U.I.SrcReg[0] = inst->U.I.SrcReg[0]; + inst_mov->U.I.SrcReg[1].File = RC_FILE_CONSTANT; + inst_mov->U.I.SrcReg[1].Index = + rc_constants_add_state(&compiler->Base.Program.Constants, + state_constant, inst->U.I.TexSrcUnit); - inst->U.I.TexSrcTarget = RC_TEXTURE_2D; - } + reset_srcreg(&inst->U.I.SrcReg[0]); + inst->U.I.SrcReg[0].File = RC_FILE_TEMPORARY; + inst->U.I.SrcReg[0].Index = temp; } /** @@ -88,6 +86,9 @@ int radeonTransformTEX( { struct r300_fragment_program_compiler *compiler = (struct r300_fragment_program_compiler*)data; + rc_wrap_mode wrapmode = compiler->state.unit[inst->U.I.TexSrcUnit].wrap_mode; + int is_rect = inst->U.I.TexSrcTarget == RC_TEXTURE_RECT || + compiler->state.unit[inst->U.I.TexSrcUnit].non_normalized_coords; if (inst->U.I.Opcode != RC_OPCODE_TEX && inst->U.I.Opcode != RC_OPCODE_TXB && @@ -141,6 +142,7 @@ int radeonTransformTEX( inst_rcp->U.I.DstReg.Index = tmp_recip_w; inst_rcp->U.I.DstReg.WriteMask = RC_MASK_W; inst_rcp->U.I.SrcReg[0] = inst->U.I.SrcReg[0]; + /* XXX do not take W, instead, see which channel is mapped to W. */ inst_rcp->U.I.SrcReg[0].Swizzle = RC_SWIZZLE_WWWW; } @@ -206,11 +208,15 @@ int radeonTransformTEX( } } - /* Texture wrap modes don't work on NPOT textures or texrects. - * - * The game plan is simple. We have two flags, fake_npot and - * non_normalized_coords, as well as a tex target. The RECT tex target - * will make the emitted code use non-scaled texcoords. + /* R300 cannot sample from rectangles and the wrap mode fallback needs + * normalized coordinates anyway. */ + if (inst->U.I.Opcode != RC_OPCODE_KIL && + is_rect && (!c->is_r500 || wrapmode != RC_WRAP_NONE)) { + scale_texcoords(compiler, inst, RC_STATE_R300_TEXRECT_FACTOR); + inst->U.I.TexSrcTarget = RC_TEXTURE_2D; + } + + /* Texture wrap modes don't work on NPOT textures. * * Non-wrapped/clamped texcoords with NPOT are free in HW. Repeat and * mirroring are not. If we need to repeat, we do: @@ -235,128 +241,111 @@ int radeonTransformTEX( * ~ C & M. ;) */ if (inst->U.I.Opcode != RC_OPCODE_KIL && - (inst->U.I.TexSrcTarget == RC_TEXTURE_RECT || - compiler->state.unit[inst->U.I.TexSrcUnit].fake_npot || - compiler->state.unit[inst->U.I.TexSrcUnit].non_normalized_coords)) { - rc_wrap_mode wrapmode = compiler->state.unit[inst->U.I.TexSrcUnit].wrap_mode; - - /* R300 cannot sample from rectangles. */ - if (!c->is_r500) { - lower_texture_rect(compiler, inst); - } - - if (compiler->state.unit[inst->U.I.TexSrcUnit].fake_npot && - wrapmode != RC_WRAP_NONE) { + wrapmode != RC_WRAP_NONE) { + struct rc_instruction *inst_mov; + unsigned temp = rc_find_free_temporary(c); + + if (wrapmode == RC_WRAP_REPEAT) { + /* Both instructions will be paired up. */ + struct rc_instruction *inst_frc = rc_insert_new_instruction(c, inst->Prev); + + inst_frc->U.I.Opcode = RC_OPCODE_FRC; + inst_frc->U.I.DstReg.File = RC_FILE_TEMPORARY; + inst_frc->U.I.DstReg.Index = temp; + inst_frc->U.I.DstReg.WriteMask = RC_MASK_XYZ; + inst_frc->U.I.SrcReg[0] = inst->U.I.SrcReg[0]; + } else if (wrapmode == RC_WRAP_MIRRORED_REPEAT) { + /* + * Function: + * f(v) = 1 - abs(frac(v * 0.5) * 2 - 1) + * + * Code: + * MUL temp, src0, 0.5 + * FRC temp, temp + * MAD temp, temp, 2, -1 + * ADD temp, 1, -abs(temp) + */ + + struct rc_instruction *inst_mul, *inst_frc, *inst_mad, *inst_add; + unsigned two, two_swizzle; + + inst_mul = rc_insert_new_instruction(c, inst->Prev); + + inst_mul->U.I.Opcode = RC_OPCODE_MUL; + inst_mul->U.I.DstReg.File = RC_FILE_TEMPORARY; + inst_mul->U.I.DstReg.Index = temp; + inst_mul->U.I.DstReg.WriteMask = RC_MASK_XYZ; + inst_mul->U.I.SrcReg[0] = inst->U.I.SrcReg[0]; + inst_mul->U.I.SrcReg[1].Swizzle = RC_SWIZZLE_HHHH; + + inst_frc = rc_insert_new_instruction(c, inst->Prev); + + inst_frc->U.I.Opcode = RC_OPCODE_FRC; + inst_frc->U.I.DstReg.File = RC_FILE_TEMPORARY; + inst_frc->U.I.DstReg.Index = temp; + inst_frc->U.I.DstReg.WriteMask = RC_MASK_XYZ; + inst_frc->U.I.SrcReg[0].File = RC_FILE_TEMPORARY; + inst_frc->U.I.SrcReg[0].Index = temp; + inst_frc->U.I.SrcReg[0].Swizzle = RC_SWIZZLE_XYZ0; + + two = rc_constants_add_immediate_scalar(&c->Program.Constants, 2, &two_swizzle); + inst_mad = rc_insert_new_instruction(c, inst->Prev); + + inst_mad->U.I.Opcode = RC_OPCODE_MAD; + inst_mad->U.I.DstReg.File = RC_FILE_TEMPORARY; + inst_mad->U.I.DstReg.Index = temp; + inst_mad->U.I.DstReg.WriteMask = RC_MASK_XYZ; + inst_mad->U.I.SrcReg[0].File = RC_FILE_TEMPORARY; + inst_mad->U.I.SrcReg[0].Index = temp; + inst_mad->U.I.SrcReg[0].Swizzle = RC_SWIZZLE_XYZ0; + inst_mad->U.I.SrcReg[1].File = RC_FILE_CONSTANT; + inst_mad->U.I.SrcReg[1].Index = two; + inst_mad->U.I.SrcReg[1].Swizzle = two_swizzle; + inst_mad->U.I.SrcReg[2].Swizzle = RC_SWIZZLE_1111; + inst_mad->U.I.SrcReg[2].Negate = RC_MASK_XYZ; + + inst_add = rc_insert_new_instruction(c, inst->Prev); + + inst_add->U.I.Opcode = RC_OPCODE_ADD; + inst_add->U.I.DstReg.File = RC_FILE_TEMPORARY; + inst_add->U.I.DstReg.Index = temp; + inst_add->U.I.DstReg.WriteMask = RC_MASK_XYZ; + inst_add->U.I.SrcReg[0].Swizzle = RC_SWIZZLE_1111; + inst_add->U.I.SrcReg[1].File = RC_FILE_TEMPORARY; + inst_add->U.I.SrcReg[1].Index = temp; + inst_add->U.I.SrcReg[1].Swizzle = RC_SWIZZLE_XYZ0; + inst_add->U.I.SrcReg[1].Abs = 1; + inst_add->U.I.SrcReg[1].Negate = RC_MASK_XYZ; + } else if (wrapmode == RC_WRAP_MIRRORED_CLAMP) { + /* + * Mirrored clamp modes are bloody simple, we just use abs + * to mirror [0, 1] into [-1, 0]. This works for + * all modes i.e. CLAMP, CLAMP_TO_EDGE, and CLAMP_TO_BORDER. + */ struct rc_instruction *inst_mov; - unsigned temp = rc_find_free_temporary(c); - /* For NPOT fallback, we need normalized coordinates anyway. */ - if (c->is_r500) { - lower_texture_rect(compiler, inst); - } - - if (wrapmode == RC_WRAP_REPEAT) { - /* Both instructions will be paired up. */ - struct rc_instruction *inst_frc = rc_insert_new_instruction(c, inst->Prev); - - inst_frc->U.I.Opcode = RC_OPCODE_FRC; - inst_frc->U.I.DstReg.File = RC_FILE_TEMPORARY; - inst_frc->U.I.DstReg.Index = temp; - inst_frc->U.I.DstReg.WriteMask = RC_MASK_XYZ; - inst_frc->U.I.SrcReg[0] = inst->U.I.SrcReg[0]; - } else if (wrapmode == RC_WRAP_MIRRORED_REPEAT) { - /* - * Function: - * f(v) = 1 - abs(frac(v * 0.5) * 2 - 1) - * - * Code: - * MUL temp, src0, 0.5 - * FRC temp, temp - * MAD temp, temp, 2, -1 - * ADD temp, 1, -abs(temp) - */ - - struct rc_instruction *inst_mul, *inst_frc, *inst_mad, *inst_add; - unsigned two, two_swizzle; - - inst_mul = rc_insert_new_instruction(c, inst->Prev); - - inst_mul->U.I.Opcode = RC_OPCODE_MUL; - inst_mul->U.I.DstReg.File = RC_FILE_TEMPORARY; - inst_mul->U.I.DstReg.Index = temp; - inst_mul->U.I.DstReg.WriteMask = RC_MASK_XYZ; - inst_mul->U.I.SrcReg[0] = inst->U.I.SrcReg[0]; - inst_mul->U.I.SrcReg[1].Swizzle = RC_SWIZZLE_HHHH; - - inst_frc = rc_insert_new_instruction(c, inst->Prev); - - inst_frc->U.I.Opcode = RC_OPCODE_FRC; - inst_frc->U.I.DstReg.File = RC_FILE_TEMPORARY; - inst_frc->U.I.DstReg.Index = temp; - inst_frc->U.I.DstReg.WriteMask = RC_MASK_XYZ; - inst_frc->U.I.SrcReg[0].File = RC_FILE_TEMPORARY; - inst_frc->U.I.SrcReg[0].Index = temp; - inst_frc->U.I.SrcReg[0].Swizzle = RC_SWIZZLE_XYZ0; - - two = rc_constants_add_immediate_scalar(&c->Program.Constants, 2, &two_swizzle); - inst_mad = rc_insert_new_instruction(c, inst->Prev); - - inst_mad->U.I.Opcode = RC_OPCODE_MAD; - inst_mad->U.I.DstReg.File = RC_FILE_TEMPORARY; - inst_mad->U.I.DstReg.Index = temp; - inst_mad->U.I.DstReg.WriteMask = RC_MASK_XYZ; - inst_mad->U.I.SrcReg[0].File = RC_FILE_TEMPORARY; - inst_mad->U.I.SrcReg[0].Index = temp; - inst_mad->U.I.SrcReg[0].Swizzle = RC_SWIZZLE_XYZ0; - inst_mad->U.I.SrcReg[1].File = RC_FILE_CONSTANT; - inst_mad->U.I.SrcReg[1].Index = two; - inst_mad->U.I.SrcReg[1].Swizzle = two_swizzle; - inst_mad->U.I.SrcReg[2].Swizzle = RC_SWIZZLE_1111; - inst_mad->U.I.SrcReg[2].Negate = RC_MASK_XYZ; - - inst_add = rc_insert_new_instruction(c, inst->Prev); - - inst_add->U.I.Opcode = RC_OPCODE_ADD; - inst_add->U.I.DstReg.File = RC_FILE_TEMPORARY; - inst_add->U.I.DstReg.Index = temp; - inst_add->U.I.DstReg.WriteMask = RC_MASK_XYZ; - inst_add->U.I.SrcReg[0].Swizzle = RC_SWIZZLE_1111; - inst_add->U.I.SrcReg[1].File = RC_FILE_TEMPORARY; - inst_add->U.I.SrcReg[1].Index = temp; - inst_add->U.I.SrcReg[1].Swizzle = RC_SWIZZLE_XYZ0; - inst_add->U.I.SrcReg[1].Abs = 1; - inst_add->U.I.SrcReg[1].Negate = RC_MASK_XYZ; - } else if (wrapmode == RC_WRAP_MIRRORED_CLAMP) { - /* - * Mirrored clamp modes are bloody simple, we just use abs - * to mirror [0, 1] into [-1, 0]. This works for - * all modes i.e. CLAMP, CLAMP_TO_EDGE, and CLAMP_TO_BORDER. - */ - struct rc_instruction *inst_mov; - - inst_mov = rc_insert_new_instruction(c, inst->Prev); - - inst_mov->U.I.Opcode = RC_OPCODE_MOV; - inst_mov->U.I.DstReg.File = RC_FILE_TEMPORARY; - inst_mov->U.I.DstReg.Index = temp; - inst_mov->U.I.DstReg.WriteMask = RC_MASK_XYZ; - inst_mov->U.I.SrcReg[0] = inst->U.I.SrcReg[0]; - inst_mov->U.I.SrcReg[0].Abs = 1; - } - - /* Preserve W for TXP/TXB. */ inst_mov = rc_insert_new_instruction(c, inst->Prev); inst_mov->U.I.Opcode = RC_OPCODE_MOV; inst_mov->U.I.DstReg.File = RC_FILE_TEMPORARY; inst_mov->U.I.DstReg.Index = temp; - inst_mov->U.I.DstReg.WriteMask = RC_MASK_W; + inst_mov->U.I.DstReg.WriteMask = RC_MASK_XYZ; inst_mov->U.I.SrcReg[0] = inst->U.I.SrcReg[0]; - - reset_srcreg(&inst->U.I.SrcReg[0]); - inst->U.I.SrcReg[0].File = RC_FILE_TEMPORARY; - inst->U.I.SrcReg[0].Index = temp; + inst_mov->U.I.SrcReg[0].Abs = 1; } + + /* Preserve W for TXP/TXB. */ + inst_mov = rc_insert_new_instruction(c, inst->Prev); + + inst_mov->U.I.Opcode = RC_OPCODE_MOV; + inst_mov->U.I.DstReg.File = RC_FILE_TEMPORARY; + inst_mov->U.I.DstReg.Index = temp; + inst_mov->U.I.DstReg.WriteMask = RC_MASK_W; + inst_mov->U.I.SrcReg[0] = inst->U.I.SrcReg[0]; + + reset_srcreg(&inst->U.I.SrcReg[0]); + inst->U.I.SrcReg[0].File = RC_FILE_TEMPORARY; + inst->U.I.SrcReg[0].Index = temp; } /* Cannot write texture to output registers (all chips) or with masks (non-r500) */ |