static GLuint get_source( struct i915_fragment_program *p, GLenum src, GLuint unit ) { switch (src) { case GL_TEXTURE: if (p->src_texture == UREG_BAD) { /* TODO: Use D0_CHANNEL_XY where possible. */ GLuint dim = translate_tex_src_bit( p, p->ctx->Texture.Unit[unit]._ReallyEnabled); GLuint sampler = i915_emit_decl(p, REG_TYPE_S, unit, dim); GLuint texcoord = i915_emit_decl(p, REG_TYPE_T, unit, D0_CHANNEL_ALL); GLuint tmp = i915_get_temp( p ); GLuint op = T0_TEXLD; if (p->VB->TexCoordPtr[unit]->size == 4) op = T0_TEXLDP; p->src_texture = i915_emit_texld( p, tmp, A0_DEST_CHANNEL_ALL, sampler, texcoord, op ); } return p->src_texture; /* Crossbar: */ case GL_TEXTURE0: case GL_TEXTURE1: case GL_TEXTURE2: case GL_TEXTURE3: case GL_TEXTURE4: case GL_TEXTURE5: case GL_TEXTURE6: case GL_TEXTURE7: { return UREG_BAD; } case GL_CONSTANT: return i915_emit_const4fv( p, p->ctx->Texture.Unit[unit].EnvColor ); case GL_PRIMARY_COLOR: return i915_emit_decl(p, REG_TYPE_T, T_DIFFUSE, D0_CHANNEL_ALL); case GL_PREVIOUS: default: i915_emit_decl(p, GET_UREG_TYPE(p->src_previous), GET_UREG_NR(p->src_previous), D0_CHANNEL_ALL); return p->src_previous; } }
static void emit_program_fini( struct i915_fragment_program *p ) { int cf = get_source( p, GL_PREVIOUS, 0 ); int out = UREG( REG_TYPE_OC, 0 ); if (p->ctx->_TriangleCaps & DD_SEPARATE_SPECULAR) { /* Emit specular add. */ GLuint s = i915_emit_decl(p, REG_TYPE_T, T_SPECULAR, D0_CHANNEL_ALL); i915_emit_arith( p, A0_ADD, out, A0_DEST_CHANNEL_ALL, 0, cf, swizzle(s, X,Y,Z,ZERO), 0 ); } else if (cf != out) { /* Will wind up in here if no texture enabled or a couple of * other scenarios (GL_REPLACE for instance). */ i915_emit_arith( p, A0_MOV, out, A0_DEST_CHANNEL_ALL, 0, cf, 0, 0 ); } }
/** * Generate texel lookup instruction. */ static void emit_tex(struct i915_fp_compile *p, const struct i915_full_instruction *inst, uint opcode, struct i915_fragment_shader* fs) { uint texture = inst->Texture.Texture; uint unit = inst->Src[1].Register.Index; uint tex = translate_tex_src_target( p, texture ); uint sampler = i915_emit_decl(p, REG_TYPE_S, unit, tex); uint coord = src_vector( p, &inst->Src[0], fs); i915_emit_texld( p, get_result_vector( p, &inst->Dst[0] ), get_result_flags( inst ), sampler, coord, opcode, i915_num_coords(texture) ); }
/** * Retrieve a ureg for the given source register. Will emit * constants, apply swizzling and negation as needed. */ static GLuint src_vector(struct i915_fragment_program *p, const struct prog_src_register *source, const struct gl_fragment_program *program) { GLuint src; switch (source->File) { /* Registers: */ case PROGRAM_TEMPORARY: if (source->Index >= I915_MAX_TEMPORARY) { i915_program_error(p, "Exceeded max temporary reg"); return 0; } src = UREG(REG_TYPE_R, source->Index); break; case PROGRAM_INPUT: switch (source->Index) { case FRAG_ATTRIB_WPOS: src = i915_emit_decl(p, REG_TYPE_T, p->wpos_tex, D0_CHANNEL_ALL); break; case FRAG_ATTRIB_COL0: src = i915_emit_decl(p, REG_TYPE_T, T_DIFFUSE, D0_CHANNEL_ALL); break; case FRAG_ATTRIB_COL1: src = i915_emit_decl(p, REG_TYPE_T, T_SPECULAR, D0_CHANNEL_XYZ); src = swizzle(src, X, Y, Z, ONE); break; case FRAG_ATTRIB_FOGC: src = i915_emit_decl(p, REG_TYPE_T, T_FOG_W, D0_CHANNEL_W); src = swizzle(src, W, ZERO, ZERO, ONE); break; case FRAG_ATTRIB_TEX0: case FRAG_ATTRIB_TEX1: case FRAG_ATTRIB_TEX2: case FRAG_ATTRIB_TEX3: case FRAG_ATTRIB_TEX4: case FRAG_ATTRIB_TEX5: case FRAG_ATTRIB_TEX6: case FRAG_ATTRIB_TEX7: src = i915_emit_decl(p, REG_TYPE_T, T_TEX0 + (source->Index - FRAG_ATTRIB_TEX0), D0_CHANNEL_ALL); break; default: i915_program_error(p, "Bad source->Index"); return 0; } break; /* Various paramters and env values. All emitted to * hardware as program constants. */ case PROGRAM_LOCAL_PARAM: src = i915_emit_param4fv(p, program->Base.LocalParams[source->Index]); break; case PROGRAM_ENV_PARAM: src = i915_emit_param4fv(p, p->ctx->FragmentProgram.Parameters[source-> Index]); break; case PROGRAM_CONSTANT: case PROGRAM_STATE_VAR: case PROGRAM_NAMED_PARAM: src = i915_emit_param4fv(p, program->Base.Parameters->ParameterValues[source-> Index]); break; default: i915_program_error(p, "Bad source->File"); return 0; } src = swizzle(src, GET_SWZ(source->Swizzle, 0), GET_SWZ(source->Swizzle, 1), GET_SWZ(source->Swizzle, 2), GET_SWZ(source->Swizzle, 3)); if (source->NegateBase) src = negate(src, GET_BIT(source->NegateBase, 0), GET_BIT(source->NegateBase, 1), GET_BIT(source->NegateBase, 2), GET_BIT(source->NegateBase, 3)); return src; }
/** * Construct a ureg for the given source register. Will emit * constants, apply swizzling and negation as needed. */ static uint src_vector(struct i915_fp_compile *p, const struct i915_full_src_register *source, struct i915_fragment_shader *fs) { uint index = source->Register.Index; uint src = 0, sem_name, sem_ind; switch (source->Register.File) { case TGSI_FILE_TEMPORARY: if (source->Register.Index >= I915_MAX_TEMPORARY) { i915_program_error(p, "Exceeded max temporary reg"); return 0; } src = UREG(REG_TYPE_R, index); break; case TGSI_FILE_INPUT: /* XXX: Packing COL1, FOGC into a single attribute works for * texenv programs, but will fail for real fragment programs * that use these attributes and expect them to be a full 4 * components wide. Could use a texcoord to pass these * attributes if necessary, but that won't work in the general * case. * * We also use a texture coordinate to pass wpos when possible. */ sem_name = p->shader->info.input_semantic_name[index]; sem_ind = p->shader->info.input_semantic_index[index]; switch (sem_name) { case TGSI_SEMANTIC_POSITION: { /* for fragcoord */ int real_tex_unit = get_mapping(fs, I915_SEMANTIC_POS); src = i915_emit_decl(p, REG_TYPE_T, T_TEX0 + real_tex_unit, D0_CHANNEL_ALL); break; } case TGSI_SEMANTIC_COLOR: if (sem_ind == 0) { src = i915_emit_decl(p, REG_TYPE_T, T_DIFFUSE, D0_CHANNEL_ALL); } else { /* secondary color */ assert(sem_ind == 1); src = i915_emit_decl(p, REG_TYPE_T, T_SPECULAR, D0_CHANNEL_XYZ); src = swizzle(src, X, Y, Z, ONE); } break; case TGSI_SEMANTIC_FOG: src = i915_emit_decl(p, REG_TYPE_T, T_FOG_W, D0_CHANNEL_W); src = swizzle(src, W, W, W, W); break; case TGSI_SEMANTIC_GENERIC: { int real_tex_unit = get_mapping(fs, sem_ind); src = i915_emit_decl(p, REG_TYPE_T, T_TEX0 + real_tex_unit, D0_CHANNEL_ALL); break; } case TGSI_SEMANTIC_FACE: { /* for back/front faces */ int real_tex_unit = get_mapping(fs, I915_SEMANTIC_FACE); src = i915_emit_decl(p, REG_TYPE_T, T_TEX0 + real_tex_unit, D0_CHANNEL_X); break; } default: i915_program_error(p, "Bad source->Index"); return 0; } break; case TGSI_FILE_IMMEDIATE: assert(index < p->num_immediates); index = p->immediates_map[index]; /* fall-through */ case TGSI_FILE_CONSTANT: src = UREG(REG_TYPE_CONST, index); break; default: i915_program_error(p, "Bad source->File"); return 0; } src = swizzle(src, source->Register.SwizzleX, source->Register.SwizzleY, source->Register.SwizzleZ, source->Register.SwizzleW); /* There's both negate-all-components and per-component negation. * Try to handle both here. */ { int n = source->Register.Negate; src = negate(src, n, n, n, n); } /* no abs() */ #if 0 /* XXX assertions disabled to allow arbfplight.c to run */ /* XXX enable these assertions, or fix things */ assert(!source->Register.Absolute); #endif if (source->Register.Absolute) debug_printf("Unhandled absolute value\n"); return src; }