static void r300_emit_draw_arrays(struct r300_context *r300, unsigned mode, unsigned count) { boolean alt_num_verts = count > 65535; CS_LOCALS(r300); if (count >= (1 << 24)) { fprintf(stderr, "r300: Got a huge number of vertices: %i, " "refusing to render.\n", count); return; } BEGIN_CS(7 + (alt_num_verts ? 2 : 0)); if (alt_num_verts) { OUT_CS_REG(R500_VAP_ALT_NUM_VERTICES, count); } OUT_CS_REG(R300_GA_COLOR_CONTROL, r300_provoking_vertex_fixes(r300, mode)); OUT_CS_REG_SEQ(R300_VAP_VF_MAX_VTX_INDX, 2); OUT_CS(count - 1); OUT_CS(0); OUT_CS_PKT3(R300_PACKET3_3D_DRAW_VBUF_2, 0); OUT_CS(R300_VAP_VF_CNTL__PRIM_WALK_VERTEX_LIST | (count << 16) | r300_translate_primitive(mode) | (alt_num_verts ? R500_VAP_VF_CNTL__USE_ALT_NUM_VERTS : 0)); END_CS; }
static void r300_render_draw_arrays(struct vbuf_render* render, unsigned start, unsigned count) { struct r300_render* r300render = r300_render(render); struct r300_context* r300 = r300render->r300; uint8_t* ptr; unsigned i; unsigned dwords = 6; CS_LOCALS(r300); (void) i; (void) ptr; assert(start == 0); assert(count < (1 << 16)); DBG(r300, DBG_DRAW, "r300: render_draw_arrays (count: %d)\n", count); if (!r300_prepare_for_rendering(r300, PREP_EMIT_STATES | PREP_EMIT_VARRAYS_SWTCL, NULL, dwords, 0, 0, -1)) { return; } BEGIN_CS(dwords); OUT_CS_REG(R300_GA_COLOR_CONTROL, r300_provoking_vertex_fixes(r300, r300render->prim)); OUT_CS_REG(R300_VAP_VF_MAX_VTX_INDX, count - 1); OUT_CS_PKT3(R300_PACKET3_3D_DRAW_VBUF_2, 0); OUT_CS(R300_VAP_VF_CNTL__PRIM_WALK_VERTEX_LIST | (count << 16) | r300render->hwprim); END_CS; }
void r300_emit_vs_state(struct r300_context* r300, unsigned size, void* state) { struct r300_vertex_shader* vs = (struct r300_vertex_shader*)state; struct r300_vertex_program_code* code = &vs->code; struct r300_screen* r300screen = r300->screen; unsigned instruction_count = code->length / 4; unsigned vtx_mem_size = r300screen->caps.is_r500 ? 128 : 72; unsigned input_count = MAX2(util_bitcount(code->InputsRead), 1); unsigned output_count = MAX2(util_bitcount(code->OutputsWritten), 1); unsigned temp_count = MAX2(code->num_temporaries, 1); unsigned pvs_num_slots = MIN3(vtx_mem_size / input_count, vtx_mem_size / output_count, 10); unsigned pvs_num_controllers = MIN2(vtx_mem_size / temp_count, 5); CS_LOCALS(r300); BEGIN_CS(size); /* R300_VAP_PVS_CODE_CNTL_0 * R300_VAP_PVS_CONST_CNTL * R300_VAP_PVS_CODE_CNTL_1 * See the r5xx docs for instructions on how to use these. */ OUT_CS_REG(R300_VAP_PVS_CODE_CNTL_0, R300_PVS_FIRST_INST(0) | R300_PVS_XYZW_VALID_INST(instruction_count - 1) | R300_PVS_LAST_INST(instruction_count - 1)); OUT_CS_REG(R300_VAP_PVS_CODE_CNTL_1, instruction_count - 1); OUT_CS_REG(R300_VAP_PVS_VECTOR_INDX_REG, 0); OUT_CS_ONE_REG(R300_VAP_PVS_UPLOAD_DATA, code->length); OUT_CS_TABLE(code->body.d, code->length); OUT_CS_REG(R300_VAP_CNTL, R300_PVS_NUM_SLOTS(pvs_num_slots) | R300_PVS_NUM_CNTLRS(pvs_num_controllers) | R300_PVS_NUM_FPUS(r300screen->caps.num_vert_fpus) | R300_PVS_VF_MAX_VTX_NUM(12) | (r300->clip_halfz ? R300_DX_CLIP_SPACE_DEF : 0) | (r300screen->caps.is_r500 ? R500_TCL_STATE_OPTIMIZATION : 0)); /* Emit flow control instructions. Even if there are no fc instructions, * we still need to write the registers to make sure they are cleared. */ OUT_CS_REG(R300_VAP_PVS_FLOW_CNTL_OPC, code->fc_ops); if (r300screen->caps.is_r500) { OUT_CS_REG_SEQ(R500_VAP_PVS_FLOW_CNTL_ADDRS_LW_0, R300_VS_MAX_FC_OPS * 2); OUT_CS_TABLE(code->fc_op_addrs.r500, R300_VS_MAX_FC_OPS * 2); } else { OUT_CS_REG_SEQ(R300_VAP_PVS_FLOW_CNTL_ADDRS_0, R300_VS_MAX_FC_OPS); OUT_CS_TABLE(code->fc_op_addrs.r300, R300_VS_MAX_FC_OPS); } OUT_CS_REG_SEQ(R300_VAP_PVS_FLOW_CNTL_LOOP_INDEX_0, R300_VS_MAX_FC_OPS); OUT_CS_TABLE(code->fc_loop_index, R300_VS_MAX_FC_OPS); END_CS; }
static void r300_render_draw_arrays(struct vbuf_render* render, unsigned start, unsigned count) { struct r300_render* r300render = r300_render(render); struct r300_context* r300 = r300render->r300; uint8_t* ptr; unsigned i; unsigned dwords = 6; CS_LOCALS(r300); (void) i; (void) ptr; DBG(r300, DBG_DRAW, "r300: render_draw_arrays (count: %d)\n", count); if (r300->draw_first_emitted) { if (!r300_prepare_for_rendering(r300, PREP_FIRST_DRAW | PREP_EMIT_AOS_SWTCL, NULL, 6, 0, 0)) return; } else { if (!r300_emit_states(r300, PREP_FIRST_DRAW | PREP_EMIT_AOS_SWTCL, NULL, 0, 0)) return; } /* Uncomment to dump all VBOs rendered through this interface. * Slow and noisy! ptr = pipe_buffer_map(&r300render->r300->context, r300render->vbo, PIPE_TRANSFER_READ, &r300render->vbo_transfer); for (i = 0; i < count; i++) { printf("r300: Vertex %d\n", i); draw_dump_emitted_vertex(&r300->vertex_info, ptr); ptr += r300->vertex_info.size * 4; printf("\n"); } pipe_buffer_unmap(&r300render->r300->context, r300render->vbo, r300render->vbo_transfer); */ BEGIN_CS(dwords); OUT_CS_REG(R300_GA_COLOR_CONTROL, r300_provoking_vertex_fixes(r300, r300render->prim)); OUT_CS_REG(R300_VAP_VF_MAX_VTX_INDX, count - 1); OUT_CS_PKT3(R300_PACKET3_3D_DRAW_VBUF_2, 0); OUT_CS(R300_VAP_VF_CNTL__PRIM_WALK_VERTEX_LIST | (count << 16) | r300render->hwprim); END_CS; r300->draw_first_emitted = TRUE; }
static void rv530_emit_query_end_single_z(struct r300_context *r300, struct r300_query *query) { CS_LOCALS(r300); BEGIN_CS(8); OUT_CS_REG(RV530_FG_ZBREG_DEST, RV530_FG_ZBREG_DEST_PIPE_SELECT_0); OUT_CS_REG(R300_ZB_ZPASS_ADDR, query->num_results * 4); OUT_CS_RELOC(r300->query_current); OUT_CS_REG(RV530_FG_ZBREG_DEST, RV530_FG_ZBREG_DEST_PIPE_SELECT_ALL); END_CS; }
void r300_emit_dsa_state(struct r300_context* r300, unsigned size, void* state) { struct r300_dsa_state* dsa = (struct r300_dsa_state*)state; struct pipe_framebuffer_state* fb = (struct pipe_framebuffer_state*)r300->fb_state.state; boolean is_r500 = r300->screen->caps.is_r500; CS_LOCALS(r300); uint32_t alpha_func = dsa->alpha_function; /* Choose the alpha ref value between 8-bit (FG_ALPHA_FUNC.AM_VAL) and * 16-bit (FG_ALPHA_VALUE). */ if (is_r500 && (alpha_func & R300_FG_ALPHA_FUNC_ENABLE)) { struct pipe_surface *cb = fb->nr_cbufs ? r300_get_nonnull_cb(fb, 0) : NULL; if (cb && (cb->format == PIPE_FORMAT_R16G16B16A16_FLOAT || cb->format == PIPE_FORMAT_R16G16B16X16_FLOAT)) { alpha_func |= R500_FG_ALPHA_FUNC_FP16_ENABLE; } else { alpha_func |= R500_FG_ALPHA_FUNC_8BIT; } } /* Setup alpha-to-coverage. */ if (r300->alpha_to_coverage && r300->msaa_enable) { /* Always set 3/6, it improves precision even for 2x and 4x MSAA. */ alpha_func |= R300_FG_ALPHA_FUNC_MASK_ENABLE | R300_FG_ALPHA_FUNC_CFG_3_OF_6; } BEGIN_CS(size); OUT_CS_REG(R300_FG_ALPHA_FUNC, alpha_func); OUT_CS_TABLE(fb->zsbuf ? &dsa->cb_begin : dsa->cb_zb_no_readwrite, size-2); END_CS; }
void r500_emit_fs_rc_constant_state(struct r300_context* r300, unsigned size, void *state) { struct r300_fragment_shader *fs = r300_fs(r300); struct rc_constant_list *constants = &fs->shader->code.constants; unsigned i; unsigned count = fs->shader->rc_state_count; unsigned first = fs->shader->externals_count; unsigned end = constants->Count; CS_LOCALS(r300); if (count == 0) return; BEGIN_CS(size); for(i = first; i < end; ++i) { if (constants->Constants[i].Type == RC_CONSTANT_STATE) { float data[4]; get_rc_constant_state(data, r300, &constants->Constants[i]); OUT_CS_REG(R500_GA_US_VECTOR_INDEX, R500_GA_US_VECTOR_INDEX_TYPE_CONST | (i & R500_GA_US_VECTOR_INDEX_MASK)); OUT_CS_ONE_REG(R500_GA_US_VECTOR_DATA, 4); OUT_CS_TABLE(data, 4); } } END_CS; }
static void r300_emit_query_end_frag_pipes(struct r300_context *r300, struct r300_query *query) { struct r300_capabilities* caps = &r300->screen->caps; uint32_t gb_pipes = r300->screen->info.r300_num_gb_pipes; CS_LOCALS(r300); assert(gb_pipes); BEGIN_CS(6 * gb_pipes + 2); /* I'm not so sure I like this switch, but it's hard to be elegant * when there's so many special cases... * * So here's the basic idea. For each pipe, enable writes to it only, * then put out the relocation for ZPASS_ADDR, taking into account a * 4-byte offset for each pipe. RV380 and older are special; they have * only two pipes, and the second pipe's enable is on bit 3, not bit 1, * so there's a chipset cap for that. */ switch (gb_pipes) { case 4: /* pipe 3 only */ OUT_CS_REG(R300_SU_REG_DEST, 1 << 3); OUT_CS_REG(R300_ZB_ZPASS_ADDR, (query->num_results + 3) * 4); OUT_CS_RELOC(r300->query_current); case 3: /* pipe 2 only */ OUT_CS_REG(R300_SU_REG_DEST, 1 << 2); OUT_CS_REG(R300_ZB_ZPASS_ADDR, (query->num_results + 2) * 4); OUT_CS_RELOC(r300->query_current); case 2: /* pipe 1 only */ /* As mentioned above, accommodate RV380 and older. */ OUT_CS_REG(R300_SU_REG_DEST, 1 << (caps->high_second_pipe ? 3 : 1)); OUT_CS_REG(R300_ZB_ZPASS_ADDR, (query->num_results + 1) * 4); OUT_CS_RELOC(r300->query_current); case 1: /* pipe 0 only */ OUT_CS_REG(R300_SU_REG_DEST, 1 << 0); OUT_CS_REG(R300_ZB_ZPASS_ADDR, (query->num_results + 0) * 4); OUT_CS_RELOC(r300->query_current); break; default: fprintf(stderr, "r300: Implementation error: Chipset reports %d" " pixel pipes!\n", gb_pipes); abort(); } /* And, finally, reset it to normal... */ OUT_CS_REG(R300_SU_REG_DEST, 0xF); END_CS; }
static void r300_render_draw_elements(struct vbuf_render* render, const ushort* indices, uint count) { struct r300_render* r300render = r300_render(render); struct r300_context* r300 = r300render->r300; unsigned max_index = (r300->vbo->size - r300->draw_vbo_offset) / (r300render->r300->vertex_info.size * 4) - 1; struct pipe_resource *index_buffer = NULL; unsigned index_buffer_offset; CS_LOCALS(r300); DBG(r300, DBG_DRAW, "r300: render_draw_elements (count: %d)\n", count); u_upload_data(r300->uploader, 0, count * 2, indices, &index_buffer_offset, &index_buffer); if (!index_buffer) { return; } if (!r300_prepare_for_rendering(r300, PREP_EMIT_STATES | PREP_EMIT_VARRAYS_SWTCL | PREP_INDEXED, index_buffer, 12, 0, 0, -1)) { pipe_resource_reference(&index_buffer, NULL); return; } BEGIN_CS(12); OUT_CS_REG(R300_GA_COLOR_CONTROL, r300_provoking_vertex_fixes(r300, r300render->prim)); OUT_CS_REG(R300_VAP_VF_MAX_VTX_INDX, max_index); OUT_CS_PKT3(R300_PACKET3_3D_DRAW_INDX_2, 0); OUT_CS(R300_VAP_VF_CNTL__PRIM_WALK_INDICES | (count << 16) | r300render->hwprim); OUT_CS_PKT3(R300_PACKET3_INDX_BUFFER, 2); OUT_CS(R300_INDX_BUFFER_ONE_REG_WR | (R300_VAP_PORT_IDX0 >> 2)); OUT_CS(index_buffer_offset); OUT_CS((count + 1) / 2); OUT_CS_RELOC(r300_resource(index_buffer)); END_CS; pipe_resource_reference(&index_buffer, NULL); }
void r300_emit_aa_state(struct r300_context *r300, unsigned size, void *state) { struct r300_aa_state *aa = (struct r300_aa_state*)state; CS_LOCALS(r300); BEGIN_CS(size); OUT_CS_REG(R300_GB_AA_CONFIG, aa->aa_config); if (aa->dest) { OUT_CS_REG(R300_RB3D_AARESOLVE_OFFSET, aa->dest->offset); OUT_CS_RELOC(aa->dest); OUT_CS_REG(R300_RB3D_AARESOLVE_PITCH, aa->dest->pitch); } OUT_CS_REG(R300_RB3D_AARESOLVE_CTL, aa->aaresolve_ctl); END_CS; }
void r300_emit_texture_cache_inval(struct r300_context* r300, unsigned size, void* state) { CS_LOCALS(r300); BEGIN_CS(size); OUT_CS_REG(R300_TX_INVALTAGS, 0); END_CS; }
void r300_emit_vs_constants(struct r300_context* r300, unsigned size, void *state) { unsigned count = ((struct r300_vertex_shader*)r300->vs_state.state)->externals_count; struct r300_constant_buffer *buf = (struct r300_constant_buffer*)state; struct r300_vertex_shader *vs = (struct r300_vertex_shader*)r300->vs_state.state; unsigned i; int imm_first = vs->externals_count; int imm_end = vs->code.constants.Count; int imm_count = vs->immediates_count; CS_LOCALS(r300); BEGIN_CS(size); OUT_CS_REG(R300_VAP_PVS_CONST_CNTL, R300_PVS_CONST_BASE_OFFSET(buf->buffer_base) | R300_PVS_MAX_CONST_ADDR(MAX2(imm_end - 1, 0))); if (vs->externals_count) { OUT_CS_REG(R300_VAP_PVS_VECTOR_INDX_REG, (r300->screen->caps.is_r500 ? R500_PVS_CONST_START : R300_PVS_CONST_START) + buf->buffer_base); OUT_CS_ONE_REG(R300_VAP_PVS_UPLOAD_DATA, count * 4); if (buf->remap_table){ for (i = 0; i < count; i++) { uint32_t *data = &buf->ptr[buf->remap_table[i]*4]; OUT_CS_TABLE(data, 4); } } else { OUT_CS_TABLE(buf->ptr, count * 4); } } /* Emit immediates. */ if (imm_count) { OUT_CS_REG(R300_VAP_PVS_VECTOR_INDX_REG, (r300->screen->caps.is_r500 ? R500_PVS_CONST_START : R300_PVS_CONST_START) + buf->buffer_base + imm_first); OUT_CS_ONE_REG(R300_VAP_PVS_UPLOAD_DATA, imm_count * 4); for (i = imm_first; i < imm_end; i++) { const float *data = vs->code.constants.Constants[i].u.Immediate; OUT_CS_TABLE(data, 4); } } END_CS; }
void r300_emit_pvs_flush(struct r300_context* r300, unsigned size, void* state) { CS_LOCALS(r300); BEGIN_CS(size); OUT_CS_REG(R300_VAP_PVS_STATE_FLUSH_REG, 0x0); END_CS; }
void r300_emit_query_start(struct r300_context *r300, unsigned size, void*state) { struct r300_query *query = r300->query_current; CS_LOCALS(r300); if (!query) return; BEGIN_CS(size); if (r300->screen->caps.family == CHIP_RV530) { OUT_CS_REG(RV530_FG_ZBREG_DEST, RV530_FG_ZBREG_DEST_PIPE_SELECT_ALL); } else { OUT_CS_REG(R300_SU_REG_DEST, R300_RASTER_PIPE_SELECT_ALL); } OUT_CS_REG(R300_ZB_ZPASS_DATA, 0); END_CS; query->begin_emitted = TRUE; }
void r500_emit_index_bias(struct r300_context *r300, int index_bias) { CS_LOCALS(r300); BEGIN_CS(2); OUT_CS_REG(R500_VAP_INDEX_OFFSET, (index_bias & 0xFFFFFF) | (index_bias < 0 ? 1<<24 : 0)); END_CS; }
void r300_flush(struct pipe_context *pipe, unsigned flags, struct pipe_fence_handle **fence) { struct r300_context *r300 = r300_context(pipe); if (r300->screen->info.drm_minor >= 12) { flags |= RADEON_FLUSH_KEEP_TILING_FLAGS; } if (r300->dirty_hw) { r300_flush_and_cleanup(r300, flags, fence); } else { if (fence) { /* We have to create a fence object, but the command stream is empty * and we cannot emit an empty CS. Let's write to some reg. */ CS_LOCALS(r300); OUT_CS_REG(RB3D_COLOR_CHANNEL_MASK, 0); r300->rws->cs_flush(r300->cs, flags, fence, 0); } else { /* Even if hw is not dirty, we should at least reset the CS in case * the space checking failed for the first draw operation. */ r300->rws->cs_flush(r300->cs, flags, NULL, 0); } } /* Update Hyper-Z status. */ if (r300->hyperz_enabled) { /* If there was a Z clear, keep Hyper-Z access. */ if (r300->num_z_clears) { r300->hyperz_time_of_last_flush = os_time_get(); r300->num_z_clears = 0; } else if (r300->hyperz_time_of_last_flush - os_time_get() > 2000000) { /* If there hasn't been a Z clear for 2 seconds, revoke Hyper-Z access. */ r300->hiz_in_use = FALSE; /* Decompress the Z buffer. */ if (r300->zmask_in_use) { if (r300->locked_zbuffer) { r300_decompress_zmask_locked(r300); } else { r300_decompress_zmask(r300); } if (fence && *fence) r300->rws->fence_reference(fence, NULL); r300_flush_and_cleanup(r300, flags, fence); } /* Revoke Hyper-Z access, so that some other process can take it. */ r300->rws->cs_request_feature(r300->cs, RADEON_FID_R300_HYPERZ_ACCESS, FALSE); r300->hyperz_enabled = FALSE; } } }
void r300_emit_ztop_state(struct r300_context* r300, unsigned size, void* state) { struct r300_ztop_state* ztop = (struct r300_ztop_state*)state; CS_LOCALS(r300); BEGIN_CS(size); OUT_CS_REG(R300_ZB_ZTOP, ztop->z_buffer_top); END_CS; }
void r300_emit_sample_mask(struct r300_context *r300, unsigned size, void *state) { unsigned mask = (*(unsigned*)state) & ((1 << 6)-1); CS_LOCALS(r300); BEGIN_CS(size); OUT_CS_REG(R300_SC_SCREENDOOR, mask | (mask << 6) | (mask << 12) | (mask << 18)); END_CS; }
void r300_emit_viewport_state(struct r300_context* r300, unsigned size, void* state) { struct r300_viewport_state* viewport = (struct r300_viewport_state*)state; CS_LOCALS(r300); BEGIN_CS(size); OUT_CS_REG_SEQ(R300_SE_VPORT_XSCALE, 6); OUT_CS_TABLE(&viewport->xscale, 6); OUT_CS_REG(R300_VAP_VTE_CNTL, viewport->vte_control); END_CS; }
void r300_emit_aa_state(struct r300_context *r300, unsigned size, void *state) { struct r300_aa_state *aa = (struct r300_aa_state*)state; CS_LOCALS(r300); BEGIN_CS(size); OUT_CS_REG(R300_GB_AA_CONFIG, aa->aa_config); if (aa->dest) { OUT_CS_REG_SEQ(R300_RB3D_AARESOLVE_OFFSET, 3); OUT_CS(aa->dest->offset); OUT_CS(aa->dest->pitch & R300_RB3D_AARESOLVE_PITCH_MASK); OUT_CS(R300_RB3D_AARESOLVE_CTL_AARESOLVE_MODE_RESOLVE | R300_RB3D_AARESOLVE_CTL_AARESOLVE_ALPHA_AVERAGE); OUT_CS_RELOC(aa->dest); } else { OUT_CS_REG(R300_RB3D_AARESOLVE_CTL, 0); } END_CS; }
static void r300_emit_draw_arrays(struct r300_context *r300, unsigned mode, unsigned count) { CS_LOCALS(r300); BEGIN_CS(4); OUT_CS_REG(R300_VAP_VF_MAX_VTX_INDX, count); OUT_CS_PKT3(R300_PACKET3_3D_DRAW_VBUF_2, 0); OUT_CS(R300_VAP_VF_CNTL__PRIM_WALK_VERTEX_LIST | (count << 16) | r300_translate_primitive(mode)); END_CS; }
static void r300_emit_draw_init(struct r300_context *r300, unsigned mode, unsigned max_index) { CS_LOCALS(r300); assert(max_index < (1 << 24)); BEGIN_CS(5); OUT_CS_REG(R300_GA_COLOR_CONTROL, r300_provoking_vertex_fixes(r300, mode)); OUT_CS_REG_SEQ(R300_VAP_VF_MAX_VTX_INDX, 2); OUT_CS(max_index); OUT_CS(0); END_CS; }
static void r300_render_unmap_vertices(struct vbuf_render* render, ushort min, ushort max) { struct r300_render* r300render = r300_render(render); struct pipe_screen* screen = r300render->r300->context.screen; CS_LOCALS(r300render->r300); BEGIN_CS(2); OUT_CS_REG(R300_VAP_VF_MAX_VTX_INDX, max); END_CS; r300render->vbo_max_used = MAX2(r300render->vbo_max_used, r300render->vertex_size * (max + 1)); pipe_buffer_unmap(screen, r300render->vbo); }
static void r300_emit_draw_elements(struct r300_context *r300, struct pipe_buffer* indexBuffer, unsigned indexSize, unsigned minIndex, unsigned maxIndex, unsigned mode, unsigned start, unsigned count) { uint32_t count_dwords; uint32_t offset_dwords = indexSize * start / sizeof(uint32_t); CS_LOCALS(r300); /* XXX most of these are stupid */ assert(indexSize == 4 || indexSize == 2); assert((start * indexSize) % 4 == 0); assert(offset_dwords == 0); BEGIN_CS(10); OUT_CS_REG(R300_VAP_VF_MAX_VTX_INDX, maxIndex); OUT_CS_PKT3(R300_PACKET3_3D_DRAW_INDX_2, 0); if (indexSize == 4) { count_dwords = count + start; OUT_CS(R300_VAP_VF_CNTL__PRIM_WALK_INDICES | (count << 16) | R300_VAP_VF_CNTL__INDEX_SIZE_32bit | r300_translate_primitive(mode)); } else { count_dwords = (count + start + 1) / 2; OUT_CS(R300_VAP_VF_CNTL__PRIM_WALK_INDICES | (count << 16) | r300_translate_primitive(mode)); } /* INDX_BUFFER is a truly special packet3. * Unlike most other packet3, where the offset is after the count, * the order is reversed, so the relocation ends up carrying the * size of the indexbuf instead of the offset. * * XXX Fix offset */ OUT_CS_PKT3(R300_PACKET3_INDX_BUFFER, 2); OUT_CS(R300_INDX_BUFFER_ONE_REG_WR | (R300_VAP_PORT_IDX0 >> 2) | (0 << R300_INDX_BUFFER_SKIP_SHIFT)); OUT_CS(offset_dwords); OUT_CS_RELOC(indexBuffer, count_dwords, RADEON_GEM_DOMAIN_GTT, 0, 0); END_CS; }
static void r300_begin_query(struct pipe_context* pipe, struct pipe_query* query) { uint32_t* map; struct r300_context* r300 = r300_context(pipe); struct r300_query* q = (struct r300_query*)query; CS_LOCALS(r300); map = pipe_buffer_map(pipe->screen, q->buf, PIPE_BUFFER_USAGE_CPU_WRITE); *map = ~0; pipe_buffer_unmap(pipe->screen, q->buf); BEGIN_CS(2); OUT_CS_REG(R300_ZB_ZPASS_DATA, 0); END_CS; }
void r300_emit_textures_state(struct r300_context *r300, unsigned size, void *state) { struct r300_textures_state *allstate = (struct r300_textures_state*)state; struct r300_texture_sampler_state *texstate; struct r300_resource *tex; unsigned i; boolean has_us_format = r300->screen->caps.has_us_format; CS_LOCALS(r300); BEGIN_CS(size); OUT_CS_REG(R300_TX_ENABLE, allstate->tx_enable); for (i = 0; i < allstate->count; i++) { if ((1 << i) & allstate->tx_enable) { texstate = &allstate->regs[i]; tex = r300_resource(allstate->sampler_views[i]->base.texture); OUT_CS_REG(R300_TX_FILTER0_0 + (i * 4), texstate->filter0); OUT_CS_REG(R300_TX_FILTER1_0 + (i * 4), texstate->filter1); OUT_CS_REG(R300_TX_BORDER_COLOR_0 + (i * 4), texstate->border_color); OUT_CS_REG(R300_TX_FORMAT0_0 + (i * 4), texstate->format.format0); OUT_CS_REG(R300_TX_FORMAT1_0 + (i * 4), texstate->format.format1); OUT_CS_REG(R300_TX_FORMAT2_0 + (i * 4), texstate->format.format2); OUT_CS_REG(R300_TX_OFFSET_0 + (i * 4), texstate->format.tile_config); OUT_CS_RELOC(tex); if (has_us_format) { OUT_CS_REG(R500_US_FORMAT0_0 + (i * 4), texstate->format.us_format0); } } } END_CS; }
void r300_emit_zmask_clear(struct r300_context *r300, unsigned size, void *state) { struct pipe_framebuffer_state *fb = (struct pipe_framebuffer_state*)r300->fb_state.state; struct r300_resource *tex; CS_LOCALS(r300); tex = r300_resource(fb->zsbuf->texture); BEGIN_CS(size); OUT_CS_REG(R300_ZB_ZCACHE_CTLSTAT, R300_ZB_ZCACHE_CTLSTAT_ZC_FLUSH_FLUSH_AND_FREE | R300_ZB_ZCACHE_CTLSTAT_ZC_FREE_FREE); OUT_CS_PKT3(R300_PACKET3_3D_CLEAR_ZMASK, 2); OUT_CS(0); OUT_CS(tex->tex.zmask_dwords[fb->zsbuf->u.tex.level]); OUT_CS(0); END_CS; /* Mark the current zbuffer's zmask as in use. */ r300->zmask_in_use = TRUE; r300_mark_atom_dirty(r300, &r300->hyperz_state); }
void r500_emit_fs_constants(struct r300_context* r300, unsigned size, void *state) { struct r300_fragment_shader *fs = r300_fs(r300); struct r300_constant_buffer *buf = (struct r300_constant_buffer*)state; unsigned count = fs->shader->externals_count; CS_LOCALS(r300); if (count == 0) return; BEGIN_CS(size); OUT_CS_REG(R500_GA_US_VECTOR_INDEX, R500_GA_US_VECTOR_INDEX_TYPE_CONST); OUT_CS_ONE_REG(R500_GA_US_VECTOR_DATA, count * 4); if (buf->remap_table){ for (unsigned i = 0; i < count; i++) { uint32_t *data = &buf->ptr[buf->remap_table[i]*4]; OUT_CS_TABLE(data, 4); } } else { OUT_CS_TABLE(buf->ptr, count * 4); } END_CS; }
static void r300_emit_draw_elements(struct r300_context *r300, struct pipe_resource* indexBuffer, unsigned indexSize, unsigned max_index, unsigned mode, unsigned start, unsigned count, uint16_t *imm_indices3) { uint32_t count_dwords, offset_dwords; boolean alt_num_verts = count > 65535; CS_LOCALS(r300); if (count >= (1 << 24)) { fprintf(stderr, "r300: Got a huge number of vertices: %i, " "refusing to render (max_index: %i).\n", count, max_index); return; } DBG(r300, DBG_DRAW, "r300: Indexbuf of %u indices, max %u\n", count, max_index); r300_emit_draw_init(r300, mode, max_index); /* If start is odd, render the first triangle with indices embedded * in the command stream. This will increase start by 3 and make it * even. We can then proceed without a fallback. */ if (indexSize == 2 && (start & 1) && mode == PIPE_PRIM_TRIANGLES) { BEGIN_CS(4); OUT_CS_PKT3(R300_PACKET3_3D_DRAW_INDX_2, 2); OUT_CS(R300_VAP_VF_CNTL__PRIM_WALK_INDICES | (3 << 16) | R300_VAP_VF_CNTL__PRIM_TRIANGLES); OUT_CS(imm_indices3[1] << 16 | imm_indices3[0]); OUT_CS(imm_indices3[2]); END_CS; start += 3; count -= 3; if (!count) return; } offset_dwords = indexSize * start / sizeof(uint32_t); BEGIN_CS(8 + (alt_num_verts ? 2 : 0)); if (alt_num_verts) { OUT_CS_REG(R500_VAP_ALT_NUM_VERTICES, count); } OUT_CS_PKT3(R300_PACKET3_3D_DRAW_INDX_2, 0); if (indexSize == 4) { count_dwords = count; OUT_CS(R300_VAP_VF_CNTL__PRIM_WALK_INDICES | (count << 16) | R300_VAP_VF_CNTL__INDEX_SIZE_32bit | r300_translate_primitive(mode) | (alt_num_verts ? R500_VAP_VF_CNTL__USE_ALT_NUM_VERTS : 0)); } else { count_dwords = (count + 1) / 2; OUT_CS(R300_VAP_VF_CNTL__PRIM_WALK_INDICES | (count << 16) | r300_translate_primitive(mode) | (alt_num_verts ? R500_VAP_VF_CNTL__USE_ALT_NUM_VERTS : 0)); } OUT_CS_PKT3(R300_PACKET3_INDX_BUFFER, 2); OUT_CS(R300_INDX_BUFFER_ONE_REG_WR | (R300_VAP_PORT_IDX0 >> 2) | (0 << R300_INDX_BUFFER_SKIP_SHIFT)); OUT_CS(offset_dwords << 2); OUT_CS(count_dwords); OUT_CS_RELOC(r300_resource(indexBuffer)); END_CS; }
static void r300_draw_arrays_immediate(struct r300_context *r300, const struct pipe_draw_info *info) { struct pipe_vertex_element* velem; struct pipe_vertex_buffer* vbuf; unsigned vertex_element_count = r300->velems->count; unsigned i, v, vbi; /* Size of the vertex, in dwords. */ unsigned vertex_size = r300->velems->vertex_size_dwords; /* The number of dwords for this draw operation. */ unsigned dwords = 4 + info->count * vertex_size; /* Size of the vertex element, in dwords. */ unsigned size[PIPE_MAX_ATTRIBS]; /* Stride to the same attrib in the next vertex in the vertex buffer, * in dwords. */ unsigned stride[PIPE_MAX_ATTRIBS]; /* Mapped vertex buffers. */ uint32_t* map[PIPE_MAX_ATTRIBS] = {0}; uint32_t* mapelem[PIPE_MAX_ATTRIBS]; CS_LOCALS(r300); if (!r300_prepare_for_rendering(r300, PREP_EMIT_STATES, NULL, dwords, 0, 0, -1)) return; /* Calculate the vertex size, offsets, strides etc. and map the buffers. */ for (i = 0; i < vertex_element_count; i++) { velem = &r300->velems->velem[i]; size[i] = r300->velems->format_size[i] / 4; vbi = velem->vertex_buffer_index; vbuf = &r300->vertex_buffer[vbi]; stride[i] = vbuf->stride / 4; /* Map the buffer. */ if (!map[vbi]) { map[vbi] = (uint32_t*)r300->rws->buffer_map( r300_resource(vbuf->buffer)->cs_buf, r300->cs, PIPE_TRANSFER_READ | PIPE_TRANSFER_UNSYNCHRONIZED); map[vbi] += (vbuf->buffer_offset / 4) + stride[i] * info->start; } mapelem[i] = map[vbi] + (velem->src_offset / 4); } r300_emit_draw_init(r300, info->mode, info->count-1); BEGIN_CS(dwords); OUT_CS_REG(R300_VAP_VTX_SIZE, vertex_size); OUT_CS_PKT3(R300_PACKET3_3D_DRAW_IMMD_2, info->count * vertex_size); OUT_CS(R300_VAP_VF_CNTL__PRIM_WALK_VERTEX_EMBEDDED | (info->count << 16) | r300_translate_primitive(info->mode)); /* Emit vertices. */ for (v = 0; v < info->count; v++) { for (i = 0; i < vertex_element_count; i++) { OUT_CS_TABLE(&mapelem[i][stride[i] * v], size[i]); } } END_CS; }