/* Not every state tracker calls every driver function before the first draw * call and we must initialize the command buffers somehow. */ static void r300_init_states(struct pipe_context *pipe) { struct r300_context *r300 = r300_context(pipe); struct pipe_blend_color bc = {{0}}; struct pipe_clip_state cs = {{{0}}}; struct pipe_scissor_state ss = {0}; struct r300_gpu_flush *gpuflush = (struct r300_gpu_flush*)r300->gpu_flush.state; struct r300_vap_invariant_state *vap_invariant = (struct r300_vap_invariant_state*)r300->vap_invariant_state.state; struct r300_invariant_state *invariant = (struct r300_invariant_state*)r300->invariant_state.state; CB_LOCALS; pipe->set_blend_color(pipe, &bc); pipe->set_clip_state(pipe, &cs); pipe->set_scissor_states(pipe, 0, 1, &ss); pipe->set_sample_mask(pipe, ~0); /* Initialize the GPU flush. */ { BEGIN_CB(gpuflush->cb_flush_clean, 6); /* Flush and free renderbuffer caches. */ OUT_CB_REG(R300_RB3D_DSTCACHE_CTLSTAT, R300_RB3D_DSTCACHE_CTLSTAT_DC_FREE_FREE_3D_TAGS | R300_RB3D_DSTCACHE_CTLSTAT_DC_FLUSH_FLUSH_DIRTY_3D); OUT_CB_REG(R300_ZB_ZCACHE_CTLSTAT, R300_ZB_ZCACHE_CTLSTAT_ZC_FLUSH_FLUSH_AND_FREE | R300_ZB_ZCACHE_CTLSTAT_ZC_FREE_FREE); /* Wait until the GPU is idle. * This fixes random pixels sometimes appearing probably caused * by incomplete rendering. */ OUT_CB_REG(RADEON_WAIT_UNTIL, RADEON_WAIT_3D_IDLECLEAN); END_CB; } /* Initialize the VAP invariant state. */ { BEGIN_CB(vap_invariant->cb, r300->vap_invariant_state.size); OUT_CB_REG(VAP_PVS_VTX_TIMEOUT_REG, 0xffff); OUT_CB_REG_SEQ(R300_VAP_GB_VERT_CLIP_ADJ, 4); OUT_CB_32F(1.0); OUT_CB_32F(1.0); OUT_CB_32F(1.0); OUT_CB_32F(1.0); OUT_CB_REG(R300_VAP_PSC_SGN_NORM_CNTL, R300_SGN_NORM_NO_ZERO); if (r300->screen->caps.is_r500) { OUT_CB_REG(R500_VAP_TEX_TO_COLOR_CNTL, 0); } END_CB; } /* Initialize the invariant state. */ { BEGIN_CB(invariant->cb, r300->invariant_state.size); OUT_CB_REG(R300_GB_SELECT, 0); OUT_CB_REG(R300_FG_FOG_BLEND, 0); OUT_CB_REG(R300_GA_OFFSET, 0); OUT_CB_REG(R300_SU_TEX_WRAP, 0); OUT_CB_REG(R300_SU_DEPTH_SCALE, 0x4B7FFFFF); OUT_CB_REG(R300_SU_DEPTH_OFFSET, 0); OUT_CB_REG(R300_SC_EDGERULE, 0x2DA49525); if (r300->screen->caps.is_rv350) { OUT_CB_REG(R500_RB3D_DISCARD_SRC_PIXEL_LTE_THRESHOLD, 0x01010101); OUT_CB_REG(R500_RB3D_DISCARD_SRC_PIXEL_GTE_THRESHOLD, 0xFEFEFEFE); } if (r300->screen->caps.is_r500) { OUT_CB_REG(R500_GA_COLOR_CONTROL_PS3, 0); OUT_CB_REG(R500_SU_TEX_WRAP_PS3, 0); } END_CB; } /* Initialize the hyperz state. */ { struct r300_hyperz_state *hyperz = (struct r300_hyperz_state*)r300->hyperz_state.state; BEGIN_CB(&hyperz->cb_flush_begin, r300->hyperz_state.size); OUT_CB_REG(R300_ZB_ZCACHE_CTLSTAT, R300_ZB_ZCACHE_CTLSTAT_ZC_FLUSH_FLUSH_AND_FREE); OUT_CB_REG(R300_ZB_BW_CNTL, 0); OUT_CB_REG(R300_ZB_DEPTHCLEARVALUE, 0); OUT_CB_REG(R300_SC_HYPERZ, R300_SC_HYPERZ_ADJ_2); if (r300->screen->caps.is_r500 || (r300->screen->caps.is_rv350 && r300->screen->info.drm_minor >= 6)) { OUT_CB_REG(R300_GB_Z_PEQ_CONFIG, 0); } END_CB; } }
static void r300_emit_fs_code_to_buffer( struct r300_context *r300, struct r300_fragment_shader_code *shader) { struct rX00_fragment_program_code *generic_code = &shader->code; unsigned imm_count = shader->immediates_count; unsigned imm_first = shader->externals_count; unsigned imm_end = generic_code->constants.Count; struct rc_constant *constants = generic_code->constants.Constants; unsigned i; CB_LOCALS; if (r300->screen->caps.is_r500) { struct r500_fragment_program_code *code = &generic_code->code.r500; shader->cb_code_size = 19 + ((code->inst_end + 1) * 6) + imm_count * 7 + code->int_constant_count * 2; NEW_CB(shader->cb_code, shader->cb_code_size); OUT_CB_REG(R500_US_CONFIG, R500_ZERO_TIMES_ANYTHING_EQUALS_ZERO); OUT_CB_REG(R500_US_PIXSIZE, code->max_temp_idx); OUT_CB_REG(R500_US_FC_CTRL, code->us_fc_ctrl); for(i = 0; i < code->int_constant_count; i++){ OUT_CB_REG(R500_US_FC_INT_CONST_0 + (i * 4), code->int_constants[i]); } OUT_CB_REG(R500_US_CODE_RANGE, R500_US_CODE_RANGE_ADDR(0) | R500_US_CODE_RANGE_SIZE(code->inst_end)); OUT_CB_REG(R500_US_CODE_OFFSET, 0); OUT_CB_REG(R500_US_CODE_ADDR, R500_US_CODE_START_ADDR(0) | R500_US_CODE_END_ADDR(code->inst_end)); OUT_CB_REG(R500_GA_US_VECTOR_INDEX, R500_GA_US_VECTOR_INDEX_TYPE_INSTR); OUT_CB_ONE_REG(R500_GA_US_VECTOR_DATA, (code->inst_end + 1) * 6); for (i = 0; i <= code->inst_end; i++) { OUT_CB(code->inst[i].inst0); OUT_CB(code->inst[i].inst1); OUT_CB(code->inst[i].inst2); OUT_CB(code->inst[i].inst3); OUT_CB(code->inst[i].inst4); OUT_CB(code->inst[i].inst5); } /* Emit immediates. */ if (imm_count) { for(i = imm_first; i < imm_end; ++i) { if (constants[i].Type == RC_CONSTANT_IMMEDIATE) { const float *data = constants[i].u.Immediate; OUT_CB_REG(R500_GA_US_VECTOR_INDEX, R500_GA_US_VECTOR_INDEX_TYPE_CONST | (i & R500_GA_US_VECTOR_INDEX_MASK)); OUT_CB_ONE_REG(R500_GA_US_VECTOR_DATA, 4); OUT_CB_TABLE(data, 4); } } } } else { /* r300 */ struct r300_fragment_program_code *code = &generic_code->code.r300; unsigned int alu_length = code->alu.length; unsigned int alu_iterations = ((alu_length - 1) / 64) + 1; unsigned int tex_length = code->tex.length; unsigned int tex_iterations = tex_length > 0 ? ((tex_length - 1) / 32) + 1 : 0; unsigned int iterations = alu_iterations > tex_iterations ? alu_iterations : tex_iterations; unsigned int bank = 0; shader->cb_code_size = 15 + /* R400_US_CODE_BANK */ (r300->screen->caps.is_r400 ? 2 * (iterations + 1): 0) + /* R400_US_CODE_EXT */ (r300->screen->caps.is_r400 ? 2 : 0) + /* R300_US_ALU_{RGB,ALPHA}_{INST,ADDR}_0, R400_US_ALU_EXT_ADDR_0 */ (code->r390_mode ? (5 * alu_iterations) : 4) + /* R400_US_ALU_EXT_ADDR_[0-63] */ (code->r390_mode ? (code->alu.length) : 0) + /* R300_US_ALU_{RGB,ALPHA}_{INST,ADDR}_0 */ code->alu.length * 4 + /* R300_US_TEX_INST_0, R300_US_TEX_INST_[0-31] */ (code->tex.length > 0 ? code->tex.length + tex_iterations : 0) + imm_count * 5; NEW_CB(shader->cb_code, shader->cb_code_size); OUT_CB_REG(R300_US_CONFIG, code->config); OUT_CB_REG(R300_US_PIXSIZE, code->pixsize); OUT_CB_REG(R300_US_CODE_OFFSET, code->code_offset); if (code->r390_mode) { OUT_CB_REG(R400_US_CODE_EXT, code->r400_code_offset_ext); } else if (r300->screen->caps.is_r400) { /* This register appears to affect shaders even if r390_mode is * disabled, so it needs to be set to 0 for shaders that * don't use r390_mode. */ OUT_CB_REG(R400_US_CODE_EXT, 0); } OUT_CB_REG_SEQ(R300_US_CODE_ADDR_0, 4); OUT_CB_TABLE(code->code_addr, 4); do { unsigned int bank_alu_length = (alu_length < 64 ? alu_length : 64); unsigned int bank_alu_offset = bank * 64; unsigned int bank_tex_length = (tex_length < 32 ? tex_length : 32); unsigned int bank_tex_offset = bank * 32; if (r300->screen->caps.is_r400) { OUT_CB_REG(R400_US_CODE_BANK, code->r390_mode ? (bank << R400_BANK_SHIFT) | R400_R390_MODE_ENABLE : 0);//2 } if (bank_alu_length > 0) { OUT_CB_REG_SEQ(R300_US_ALU_RGB_INST_0, bank_alu_length); for (i = 0; i < bank_alu_length; i++) OUT_CB(code->alu.inst[i + bank_alu_offset].rgb_inst); OUT_CB_REG_SEQ(R300_US_ALU_RGB_ADDR_0, bank_alu_length); for (i = 0; i < bank_alu_length; i++) OUT_CB(code->alu.inst[i + bank_alu_offset].rgb_addr); OUT_CB_REG_SEQ(R300_US_ALU_ALPHA_INST_0, bank_alu_length); for (i = 0; i < bank_alu_length; i++) OUT_CB(code->alu.inst[i + bank_alu_offset].alpha_inst); OUT_CB_REG_SEQ(R300_US_ALU_ALPHA_ADDR_0, bank_alu_length); for (i = 0; i < bank_alu_length; i++) OUT_CB(code->alu.inst[i + bank_alu_offset].alpha_addr); if (code->r390_mode) { OUT_CB_REG_SEQ(R400_US_ALU_EXT_ADDR_0, bank_alu_length); for (i = 0; i < bank_alu_length; i++) OUT_CB(code->alu.inst[i + bank_alu_offset].r400_ext_addr); } } if (bank_tex_length > 0) { OUT_CB_REG_SEQ(R300_US_TEX_INST_0, bank_tex_length); OUT_CB_TABLE(code->tex.inst + bank_tex_offset, bank_tex_length); } alu_length -= bank_alu_length; tex_length -= bank_tex_length; bank++; } while(code->r390_mode && (alu_length > 0 || tex_length > 0)); /* R400_US_CODE_BANK needs to be reset to 0, otherwise some shaders * will be rendered incorrectly. */ if (r300->screen->caps.is_r400) { OUT_CB_REG(R400_US_CODE_BANK, code->r390_mode ? R400_R390_MODE_ENABLE : 0); } /* Emit immediates. */ if (imm_count) { for(i = imm_first; i < imm_end; ++i) { if (constants[i].Type == RC_CONSTANT_IMMEDIATE) { const float *data = constants[i].u.Immediate; OUT_CB_REG_SEQ(R300_PFS_PARAM_0_X + i * 16, 4); OUT_CB(pack_float24(data[0])); OUT_CB(pack_float24(data[1])); OUT_CB(pack_float24(data[2])); OUT_CB(pack_float24(data[3])); } } } } OUT_CB_REG(R300_FG_DEPTH_SRC, shader->fg_depth_src); OUT_CB_REG(R300_US_W_FMT, shader->us_out_w); END_CB; }