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 rv530_emit_query_end_double_z(struct r300_context *r300, struct r300_query *query) { CS_LOCALS(r300); BEGIN_CS(14); OUT_CS_REG(RV530_FG_ZBREG_DEST, RV530_FG_ZBREG_DEST_PIPE_SELECT_0); OUT_CS_REG(R300_ZB_ZPASS_ADDR, (query->num_results + 0) * 4); OUT_CS_RELOC(r300->query_current); OUT_CS_REG(RV530_FG_ZBREG_DEST, RV530_FG_ZBREG_DEST_PIPE_SELECT_1); OUT_CS_REG(R300_ZB_ZPASS_ADDR, (query->num_results + 1) * 4); OUT_CS_RELOC(r300->query_current); OUT_CS_REG(RV530_FG_ZBREG_DEST, RV530_FG_ZBREG_DEST_PIPE_SELECT_ALL); END_CS; }
static void r300_end_query(struct pipe_context* pipe, struct pipe_query* query) { struct r300_context* r300 = r300_context(pipe); struct r300_query* q = (struct r300_query*)query; CS_LOCALS(r300); BEGIN_CS(4); OUT_CS_REG_SEQ(R300_ZB_ZPASS_ADDR, 1); OUT_CS_RELOC(q->buf, 0, 0, RADEON_GEM_DOMAIN_GTT, 0); END_CS; }
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_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_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; }
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_vertex_arrays_swtcl(struct r300_context *r300, boolean indexed) { CS_LOCALS(r300); DBG(r300, DBG_SWTCL, "r300: Preparing vertex buffer %p for render, " "vertex size %d\n", r300->vbo, r300->vertex_info.size); /* Set the pointer to our vertex buffer. The emitted values are this: * PACKET3 [3D_LOAD_VBPNTR] * COUNT [1] * FORMAT [size | stride << 8] * OFFSET [offset into BO] * VBPNTR [relocated BO] */ BEGIN_CS(7); OUT_CS_PKT3(R300_PACKET3_3D_LOAD_VBPNTR, 3); OUT_CS(1 | (!indexed ? R300_VC_FORCE_PREFETCH : 0)); OUT_CS(r300->vertex_info.size | (r300->vertex_info.size << 8)); OUT_CS(r300->draw_vbo_offset); OUT_CS(0); OUT_CS_RELOC(r300_resource(r300->vbo)); 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; }
void r300_emit_vertex_arrays(struct r300_context* r300, int offset, boolean indexed, int instance_id) { struct pipe_vertex_buffer *vbuf = r300->vertex_buffer; struct pipe_vertex_element *velem = r300->velems->velem; struct r300_resource *buf; int i; unsigned vertex_array_count = r300->velems->count; unsigned packet_size = (vertex_array_count * 3 + 1) / 2; struct pipe_vertex_buffer *vb1, *vb2; unsigned *hw_format_size = r300->velems->format_size; unsigned size1, size2, offset1, offset2, stride1, stride2; CS_LOCALS(r300); BEGIN_CS(2 + packet_size + vertex_array_count * 2); OUT_CS_PKT3(R300_PACKET3_3D_LOAD_VBPNTR, packet_size); OUT_CS(vertex_array_count | (!indexed ? R300_VC_FORCE_PREFETCH : 0)); if (instance_id == -1) { /* Non-instanced arrays. This ignores instance_divisor and instance_id. */ for (i = 0; i < vertex_array_count - 1; i += 2) { vb1 = &vbuf[velem[i].vertex_buffer_index]; vb2 = &vbuf[velem[i+1].vertex_buffer_index]; size1 = hw_format_size[i]; size2 = hw_format_size[i+1]; OUT_CS(R300_VBPNTR_SIZE0(size1) | R300_VBPNTR_STRIDE0(vb1->stride) | R300_VBPNTR_SIZE1(size2) | R300_VBPNTR_STRIDE1(vb2->stride)); OUT_CS(vb1->buffer_offset + velem[i].src_offset + offset * vb1->stride); OUT_CS(vb2->buffer_offset + velem[i+1].src_offset + offset * vb2->stride); } if (vertex_array_count & 1) { vb1 = &vbuf[velem[i].vertex_buffer_index]; size1 = hw_format_size[i]; OUT_CS(R300_VBPNTR_SIZE0(size1) | R300_VBPNTR_STRIDE0(vb1->stride)); OUT_CS(vb1->buffer_offset + velem[i].src_offset + offset * vb1->stride); } for (i = 0; i < vertex_array_count; i++) { buf = r300_resource(vbuf[velem[i].vertex_buffer_index].buffer); OUT_CS_RELOC(buf); } } else { /* Instanced arrays. */ for (i = 0; i < vertex_array_count - 1; i += 2) { vb1 = &vbuf[velem[i].vertex_buffer_index]; vb2 = &vbuf[velem[i+1].vertex_buffer_index]; size1 = hw_format_size[i]; size2 = hw_format_size[i+1]; if (velem[i].instance_divisor) { stride1 = 0; offset1 = vb1->buffer_offset + velem[i].src_offset + (instance_id / velem[i].instance_divisor) * vb1->stride; } else { stride1 = vb1->stride; offset1 = vb1->buffer_offset + velem[i].src_offset + offset * vb1->stride; } if (velem[i+1].instance_divisor) { stride2 = 0; offset2 = vb2->buffer_offset + velem[i+1].src_offset + (instance_id / velem[i+1].instance_divisor) * vb2->stride; } else { stride2 = vb2->stride; offset2 = vb2->buffer_offset + velem[i+1].src_offset + offset * vb2->stride; } OUT_CS(R300_VBPNTR_SIZE0(size1) | R300_VBPNTR_STRIDE0(stride1) | R300_VBPNTR_SIZE1(size2) | R300_VBPNTR_STRIDE1(stride2)); OUT_CS(offset1); OUT_CS(offset2); } if (vertex_array_count & 1) { vb1 = &vbuf[velem[i].vertex_buffer_index]; size1 = hw_format_size[i]; if (velem[i].instance_divisor) { stride1 = 0; offset1 = vb1->buffer_offset + velem[i].src_offset + (instance_id / velem[i].instance_divisor) * vb1->stride; } else { stride1 = vb1->stride; offset1 = vb1->buffer_offset + velem[i].src_offset + offset * vb1->stride; } OUT_CS(R300_VBPNTR_SIZE0(size1) | R300_VBPNTR_STRIDE0(stride1)); OUT_CS(offset1); } for (i = 0; i < vertex_array_count; i++) { buf = r300_resource(vbuf[velem[i].vertex_buffer_index].buffer); OUT_CS_RELOC(buf); } } END_CS; }
void r300_emit_fb_state(struct r300_context* r300, unsigned size, void* state) { struct pipe_framebuffer_state* fb = (struct pipe_framebuffer_state*)state; struct r300_surface* surf; unsigned i; uint32_t rb3d_cctl = 0; CS_LOCALS(r300); BEGIN_CS(size); if (r300->screen->caps.is_r500) { rb3d_cctl = R300_RB3D_CCTL_INDEPENDENT_COLORFORMAT_ENABLE_ENABLE; } /* NUM_MULTIWRITES replicates COLOR[0] to all colorbuffers. */ if (fb->nr_cbufs && r300->fb_multiwrite) { rb3d_cctl |= R300_RB3D_CCTL_NUM_MULTIWRITES(fb->nr_cbufs); } if (r300->cmask_in_use) { rb3d_cctl |= R300_RB3D_CCTL_AA_COMPRESSION_ENABLE | R300_RB3D_CCTL_CMASK_ENABLE; } OUT_CS_REG(R300_RB3D_CCTL, rb3d_cctl); /* Set up colorbuffers. */ for (i = 0; i < fb->nr_cbufs; i++) { surf = r300_surface(r300_get_nonnull_cb(fb, i)); OUT_CS_REG(R300_RB3D_COLOROFFSET0 + (4 * i), surf->offset); OUT_CS_RELOC(surf); OUT_CS_REG(R300_RB3D_COLORPITCH0 + (4 * i), surf->pitch); OUT_CS_RELOC(surf); if (r300->cmask_in_use && i == 0) { OUT_CS_REG(R300_RB3D_CMASK_OFFSET0, 0); OUT_CS_REG(R300_RB3D_CMASK_PITCH0, surf->pitch_cmask); OUT_CS_REG(R300_RB3D_COLOR_CLEAR_VALUE, r300->color_clear_value); if (r300->screen->caps.is_r500 && r300->screen->info.drm_minor >= 29) { OUT_CS_REG_SEQ(R500_RB3D_COLOR_CLEAR_VALUE_AR, 2); OUT_CS(r300->color_clear_value_ar); OUT_CS(r300->color_clear_value_gb); } } } /* Set up the ZB part of the CBZB clear. */ if (r300->cbzb_clear) { surf = r300_surface(fb->cbufs[0]); OUT_CS_REG(R300_ZB_FORMAT, surf->cbzb_format); OUT_CS_REG(R300_ZB_DEPTHOFFSET, surf->cbzb_midpoint_offset); OUT_CS_RELOC(surf); OUT_CS_REG(R300_ZB_DEPTHPITCH, surf->cbzb_pitch); OUT_CS_RELOC(surf); DBG(r300, DBG_CBZB, "CBZB clearing cbuf %08x %08x\n", surf->cbzb_format, surf->cbzb_pitch); } /* Set up a zbuffer. */ else if (fb->zsbuf) { surf = r300_surface(fb->zsbuf); OUT_CS_REG(R300_ZB_FORMAT, surf->format); OUT_CS_REG(R300_ZB_DEPTHOFFSET, surf->offset); OUT_CS_RELOC(surf); OUT_CS_REG(R300_ZB_DEPTHPITCH, surf->pitch); OUT_CS_RELOC(surf); if (r300->hyperz_enabled) { /* HiZ RAM. */ OUT_CS_REG(R300_ZB_HIZ_OFFSET, 0); OUT_CS_REG(R300_ZB_HIZ_PITCH, surf->pitch_hiz); /* Z Mask RAM. (compressed zbuffer) */ OUT_CS_REG(R300_ZB_ZMASK_OFFSET, 0); OUT_CS_REG(R300_ZB_ZMASK_PITCH, surf->pitch_zmask); } } END_CS; }
void r300_emit_fb_state(struct r300_context* r300, unsigned size, void* state) { struct pipe_framebuffer_state* fb = (struct pipe_framebuffer_state*)state; struct r300_surface* surf; unsigned i; uint32_t rb3d_cctl = 0; CS_LOCALS(r300); BEGIN_CS(size); /* NUM_MULTIWRITES replicates COLOR[0] to all colorbuffers, which is not * what we usually want. */ if (r300->screen->caps.is_r500) { rb3d_cctl = R300_RB3D_CCTL_INDEPENDENT_COLORFORMAT_ENABLE_ENABLE; } if (fb->nr_cbufs && r300->fb_multiwrite) { rb3d_cctl |= R300_RB3D_CCTL_NUM_MULTIWRITES(fb->nr_cbufs); } OUT_CS_REG(R300_RB3D_CCTL, rb3d_cctl); /* Set up colorbuffers. */ for (i = 0; i < fb->nr_cbufs; i++) { surf = r300_surface(fb->cbufs[i]); OUT_CS_REG(R300_RB3D_COLOROFFSET0 + (4 * i), surf->offset); OUT_CS_RELOC(surf); OUT_CS_REG(R300_RB3D_COLORPITCH0 + (4 * i), surf->pitch); OUT_CS_RELOC(surf); } /* Set up the ZB part of the CBZB clear. */ if (r300->cbzb_clear) { surf = r300_surface(fb->cbufs[0]); OUT_CS_REG(R300_ZB_FORMAT, surf->cbzb_format); OUT_CS_REG(R300_ZB_DEPTHOFFSET, surf->cbzb_midpoint_offset); OUT_CS_RELOC(surf); OUT_CS_REG(R300_ZB_DEPTHPITCH, surf->cbzb_pitch); OUT_CS_RELOC(surf); DBG(r300, DBG_CBZB, "CBZB clearing cbuf %08x %08x\n", surf->cbzb_format, surf->cbzb_pitch); } /* Set up a zbuffer. */ else if (fb->zsbuf) { surf = r300_surface(fb->zsbuf); OUT_CS_REG(R300_ZB_FORMAT, surf->format); OUT_CS_REG(R300_ZB_DEPTHOFFSET, surf->offset); OUT_CS_RELOC(surf); OUT_CS_REG(R300_ZB_DEPTHPITCH, surf->pitch); OUT_CS_RELOC(surf); if (r300->hyperz_enabled) { /* HiZ RAM. */ OUT_CS_REG(R300_ZB_HIZ_OFFSET, 0); OUT_CS_REG(R300_ZB_HIZ_PITCH, surf->pitch_hiz); /* Z Mask RAM. (compressed zbuffer) */ OUT_CS_REG(R300_ZB_ZMASK_OFFSET, 0); OUT_CS_REG(R300_ZB_ZMASK_PITCH, surf->pitch_zmask); } } END_CS; }