void r300_emit_vertex_stream_state(struct r300_context* r300, unsigned size, void* state) { struct r300_vertex_stream_state *streams = (struct r300_vertex_stream_state*)state; unsigned i; CS_LOCALS(r300); if (DBG_ON(r300, DBG_PSC)) { fprintf(stderr, "r300: PSC emit:\n"); for (i = 0; i < streams->count; i++) { fprintf(stderr, " : prog_stream_cntl%d: 0x%08x\n", i, streams->vap_prog_stream_cntl[i]); } for (i = 0; i < streams->count; i++) { fprintf(stderr, " : prog_stream_cntl_ext%d: 0x%08x\n", i, streams->vap_prog_stream_cntl_ext[i]); } } BEGIN_CS(size); OUT_CS_REG_SEQ(R300_VAP_PROG_STREAM_CNTL_0, streams->count); OUT_CS_TABLE(streams->vap_prog_stream_cntl, streams->count); OUT_CS_REG_SEQ(R300_VAP_PROG_STREAM_CNTL_EXT_0, streams->count); OUT_CS_TABLE(streams->vap_prog_stream_cntl_ext, streams->count); 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_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; }
void r300_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; unsigned j; 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_SEQ(R300_PFS_PARAM_0_X + i * 16, 4); for (j = 0; j < 4; j++) OUT_CS(pack_float24(data[j])); } } END_CS; }
void r300_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; unsigned i, j; CS_LOCALS(r300); if (count == 0) return; BEGIN_CS(size); OUT_CS_REG_SEQ(R300_PFS_PARAM_0_X, count * 4); if (buf->remap_table){ for (i = 0; i < count; i++) { float *data = (float*)&buf->ptr[buf->remap_table[i]*4]; for (j = 0; j < 4; j++) OUT_CS(pack_float24(data[j])); } } else { for (i = 0; i < count; i++) for (j = 0; j < 4; j++) OUT_CS(pack_float24(*(float*)&buf->ptr[i*4+j])); } END_CS; }
void r300_emit_rs_block_state(struct r300_context* r300, unsigned size, void* state) { struct r300_rs_block* rs = (struct r300_rs_block*)state; unsigned i; /* It's the same for both INST and IP tables */ unsigned count = (rs->inst_count & R300_RS_INST_COUNT_MASK) + 1; CS_LOCALS(r300); if (DBG_ON(r300, DBG_RS_BLOCK)) { r500_dump_rs_block(rs); fprintf(stderr, "r300: RS emit:\n"); for (i = 0; i < count; i++) fprintf(stderr, " : ip %d: 0x%08x\n", i, rs->ip[i]); for (i = 0; i < count; i++) fprintf(stderr, " : inst %d: 0x%08x\n", i, rs->inst[i]); fprintf(stderr, " : count: 0x%08x inst_count: 0x%08x\n", rs->count, rs->inst_count); } BEGIN_CS(size); OUT_CS_REG_SEQ(R300_VAP_VTX_STATE_CNTL, 2); OUT_CS(rs->vap_vtx_state_cntl); OUT_CS(rs->vap_vsm_vtx_assm); OUT_CS_REG_SEQ(R300_VAP_OUTPUT_VTX_FMT_0, 2); OUT_CS(rs->vap_out_vtx_fmt[0]); OUT_CS(rs->vap_out_vtx_fmt[1]); OUT_CS_REG_SEQ(R300_GB_ENABLE, 1); OUT_CS(rs->gb_enable); if (r300->screen->caps.is_r500) { OUT_CS_REG_SEQ(R500_RS_IP_0, count); } else { OUT_CS_REG_SEQ(R300_RS_IP_0, count); } OUT_CS_TABLE(rs->ip, count); OUT_CS_REG_SEQ(R300_RS_COUNT, 2); OUT_CS(rs->count); OUT_CS(rs->inst_count); if (r300->screen->caps.is_r500) { OUT_CS_REG_SEQ(R500_RS_INST_0, count); } else { OUT_CS_REG_SEQ(R300_RS_INST_0, count); } OUT_CS_TABLE(rs->inst, count); 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; }
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; }
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; }
void r300_emit_scissor_state(struct r300_context* r300, unsigned size, void* state) { struct pipe_scissor_state* scissor = (struct pipe_scissor_state*)state; CS_LOCALS(r300); BEGIN_CS(size); OUT_CS_REG_SEQ(R300_SC_CLIPRECT_TL_0, 2); if (r300->screen->caps.is_r500) { OUT_CS((scissor->minx << R300_CLIPRECT_X_SHIFT) | (scissor->miny << R300_CLIPRECT_Y_SHIFT)); OUT_CS(((scissor->maxx - 1) << R300_CLIPRECT_X_SHIFT) | ((scissor->maxy - 1) << R300_CLIPRECT_Y_SHIFT)); } else { OUT_CS(((scissor->minx + 1440) << R300_CLIPRECT_X_SHIFT) | ((scissor->miny + 1440) << R300_CLIPRECT_Y_SHIFT)); OUT_CS(((scissor->maxx + 1440-1) << R300_CLIPRECT_X_SHIFT) | ((scissor->maxy + 1440-1) << R300_CLIPRECT_Y_SHIFT)); } 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_gpu_flush(struct r300_context *r300, unsigned size, void *state) { struct r300_gpu_flush *gpuflush = (struct r300_gpu_flush*)state; struct pipe_framebuffer_state* fb = (struct pipe_framebuffer_state*)r300->fb_state.state; uint32_t height = fb->height; uint32_t width = fb->width; CS_LOCALS(r300); if (r300->cbzb_clear) { struct r300_surface *surf = r300_surface(fb->cbufs[0]); height = surf->cbzb_height; width = surf->cbzb_width; } DBG(r300, DBG_SCISSOR, "r300: Scissor width: %i, height: %i, CBZB clear: %s\n", width, height, r300->cbzb_clear ? "YES" : "NO"); BEGIN_CS(size); /* Set up scissors. * By writing to the SC registers, SC & US assert idle. */ OUT_CS_REG_SEQ(R300_SC_SCISSORS_TL, 2); if (r300->screen->caps.is_r500) { OUT_CS(0); OUT_CS(((width - 1) << R300_SCISSORS_X_SHIFT) | ((height - 1) << R300_SCISSORS_Y_SHIFT)); } else { OUT_CS((1440 << R300_SCISSORS_X_SHIFT) | (1440 << R300_SCISSORS_Y_SHIFT)); OUT_CS(((width + 1440-1) << R300_SCISSORS_X_SHIFT) | ((height + 1440-1) << R300_SCISSORS_Y_SHIFT)); } /* Flush CB & ZB caches and wait until the 3D engine is idle and clean. */ OUT_CS_TABLE(gpuflush->cb_flush_clean, 6); END_CS; }
static void r300_flush_and_cleanup(struct r300_context *r300, unsigned flags, struct pipe_fence_handle **fence) { struct r300_atom *atom; r300_emit_hyperz_end(r300); r300_emit_query_end(r300); if (r300->screen->caps.is_r500) r500_emit_index_bias(r300, 0); /* The DDX doesn't set these regs. */ if (r300->screen->info.drm_minor >= 6) { CS_LOCALS(r300); OUT_CS_REG_SEQ(R300_GB_MSPOS0, 2); OUT_CS(0x66666666); OUT_CS(0x6666666); } r300->flush_counter++; r300->rws->cs_flush(r300->cs, flags, fence, 0); r300->dirty_hw = 0; /* New kitchen sink, baby. */ foreach_atom(r300, atom) { if (atom->state || atom->allow_null_state) { r300_mark_atom_dirty(r300, atom); } } r300->vertex_arrays_dirty = TRUE; /* Unmark HWTCL state for SWTCL. */ if (!r300->screen->caps.has_tcl) { r300->vs_state.dirty = FALSE; r300->vs_constants.dirty = FALSE; r300->clip_state.dirty = FALSE; } }
void r300_emit_fb_state_pipelined(struct r300_context *r300, unsigned size, void *state) { struct pipe_framebuffer_state* fb = (struct pipe_framebuffer_state*)r300->fb_state.state; unsigned i, num_cbufs = fb->nr_cbufs; unsigned mspos0, mspos1; CS_LOCALS(r300); /* If we use the multiwrite feature, the colorbuffers 2,3,4 must be * marked as UNUSED in the US block. */ if (r300->fb_multiwrite) { num_cbufs = MIN2(num_cbufs, 1); } BEGIN_CS(size); /* Colorbuffer format in the US block. * (must be written after unpipelined regs) */ OUT_CS_REG_SEQ(R300_US_OUT_FMT_0, 4); for (i = 0; i < num_cbufs; i++) { OUT_CS(r300_surface(fb->cbufs[i])->format); } for (; i < 1; i++) { OUT_CS(R300_US_OUT_FMT_C4_8 | R300_C0_SEL_B | R300_C1_SEL_G | R300_C2_SEL_R | R300_C3_SEL_A); } for (; i < 4; i++) { OUT_CS(R300_US_OUT_FMT_UNUSED); } /* Multisampling. Depends on framebuffer sample count. * These are pipelined regs and as such cannot be moved * to the AA state. */ mspos0 = 0x66666666; mspos1 = 0x6666666; if (fb->nr_cbufs && fb->cbufs[0]->texture->nr_samples > 1) { /* Subsample placement. These may not be optimal. */ switch (fb->cbufs[0]->texture->nr_samples) { case 2: mspos0 = 0x33996633; mspos1 = 0x6666663; break; case 3: mspos0 = 0x33936933; mspos1 = 0x6666663; break; case 4: mspos0 = 0x33939933; mspos1 = 0x3966663; break; case 6: mspos0 = 0x22a2aa22; mspos1 = 0x2a65672; break; default: debug_printf("r300: Bad number of multisamples!\n"); } } OUT_CS_REG_SEQ(R300_GB_MSPOS0, 2); OUT_CS(mspos0); OUT_CS(mspos1); END_CS; }
/* This functions is used to draw a rectangle for the blitter module. * * If we rendered a quad, the pixels on the main diagonal * would be computed and stored twice, which makes the clear/copy codepaths * somewhat inefficient. Instead we use a rectangular point sprite. */ void r300_blitter_draw_rectangle(struct blitter_context *blitter, int x1, int y1, int x2, int y2, float depth, enum blitter_attrib_type type, const union pipe_color_union *attrib) { struct r300_context *r300 = r300_context(util_blitter_get_pipe(blitter)); unsigned last_sprite_coord_enable = r300->sprite_coord_enable; unsigned width = x2 - x1; unsigned height = y2 - y1; unsigned vertex_size = type == UTIL_BLITTER_ATTRIB_COLOR || !r300->draw ? 8 : 4; unsigned dwords = 13 + vertex_size + (type == UTIL_BLITTER_ATTRIB_TEXCOORD ? 7 : 0); static const union pipe_color_union zeros; CS_LOCALS(r300); /* XXX workaround for a lockup in MSAA resolve on SWTCL chipsets, this * function most probably doesn't handle type=NONE correctly */ if (!r300->screen->caps.has_tcl && type == UTIL_BLITTER_ATTRIB_NONE) { util_blitter_draw_rectangle(blitter, x1, y1, x2, y2, depth, type, attrib); return; } if (r300->skip_rendering) return; if (type == UTIL_BLITTER_ATTRIB_TEXCOORD) r300->sprite_coord_enable = 1; r300_update_derived_state(r300); /* Mark some states we don't care about as non-dirty. */ r300->viewport_state.dirty = FALSE; if (!r300_prepare_for_rendering(r300, PREP_EMIT_STATES, NULL, dwords, 0, 0, -1)) goto done; DBG(r300, DBG_DRAW, "r300: draw_rectangle\n"); BEGIN_CS(dwords); /* Set up GA. */ OUT_CS_REG(R300_GA_POINT_SIZE, (height * 6) | ((width * 6) << 16)); if (type == UTIL_BLITTER_ATTRIB_TEXCOORD) { /* Set up the GA to generate texcoords. */ OUT_CS_REG(R300_GB_ENABLE, R300_GB_POINT_STUFF_ENABLE | (R300_GB_TEX_STR << R300_GB_TEX0_SOURCE_SHIFT)); OUT_CS_REG_SEQ(R300_GA_POINT_S0, 4); OUT_CS_32F(attrib->f[0]); OUT_CS_32F(attrib->f[3]); OUT_CS_32F(attrib->f[2]); OUT_CS_32F(attrib->f[1]); } /* Set up VAP controls. */ OUT_CS_REG(R300_VAP_CLIP_CNTL, R300_CLIP_DISABLE); OUT_CS_REG(R300_VAP_VTE_CNTL, R300_VTX_XY_FMT | R300_VTX_Z_FMT); OUT_CS_REG(R300_VAP_VTX_SIZE, vertex_size); OUT_CS_REG_SEQ(R300_VAP_VF_MAX_VTX_INDX, 2); OUT_CS(1); OUT_CS(0); /* Draw. */ OUT_CS_PKT3(R300_PACKET3_3D_DRAW_IMMD_2, vertex_size); OUT_CS(R300_VAP_VF_CNTL__PRIM_WALK_VERTEX_EMBEDDED | (1 << 16) | R300_VAP_VF_CNTL__PRIM_POINTS); OUT_CS_32F(x1 + width * 0.5f); OUT_CS_32F(y1 + height * 0.5f); OUT_CS_32F(depth); OUT_CS_32F(1); if (vertex_size == 8) { if (!attrib) attrib = &zeros; OUT_CS_TABLE(attrib->f, 4); } END_CS; done: /* Restore the state. */ r300_mark_atom_dirty(r300, &r300->rs_state); r300_mark_atom_dirty(r300, &r300->viewport_state); r300->sprite_coord_enable = last_sprite_coord_enable; }
static void r300_emit_draw_elements(struct r300_context *r300, struct pipe_resource* 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); 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; } maxIndex = MIN2(maxIndex, r300->vertex_buffer_max_index); DBG(r300, DBG_DRAW, "r300: Indexbuf of %u indices, min %u max %u\n", count, minIndex, maxIndex); BEGIN_CS(13 + (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(maxIndex); OUT_CS(minIndex); 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)); } /* 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. */ 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_BUF_RELOC(indexBuffer, count_dwords, r300_buffer(indexBuffer)->domain, 0); END_CS; }
static void r300_emit_draw_arrays_immediate(struct r300_context *r300, unsigned mode, unsigned start, unsigned count) { 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 = 9 + 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]; uint32_t* mapelem[PIPE_MAX_ATTRIBS]; struct pipe_transfer* transfer[PIPE_MAX_ATTRIBS] = {0}; CS_LOCALS(r300); if (!r300_prepare_for_rendering(r300, PREP_FIRST_DRAW, NULL, dwords, 0, 0)) 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->hw_format_size[i] / 4; vbi = velem->vertex_buffer_index; vbuf = &r300->vertex_buffer[vbi]; stride[i] = vbuf->stride / 4; /* Map the buffer. */ if (!transfer[vbi]) { map[vbi] = (uint32_t*)pipe_buffer_map(&r300->context, vbuf->buffer, PIPE_TRANSFER_READ, &transfer[vbi]); map[vbi] += (vbuf->buffer_offset / 4) + stride[i] * start; } mapelem[i] = map[vbi] + (velem->src_offset / 4); } BEGIN_CS(dwords); OUT_CS_REG(R300_GA_COLOR_CONTROL, r300_provoking_vertex_fixes(r300, mode)); OUT_CS_REG(R300_VAP_VTX_SIZE, vertex_size); 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_IMMD_2, count * vertex_size); OUT_CS(R300_VAP_VF_CNTL__PRIM_WALK_VERTEX_EMBEDDED | (count << 16) | r300_translate_primitive(mode)); /* Emit vertices. */ for (v = 0; v < count; v++) { for (i = 0; i < vertex_element_count; i++) { OUT_CS_TABLE(&mapelem[i][stride[i] * v], size[i]); } } END_CS; /* Unmap buffers. */ for (i = 0; i < vertex_element_count; i++) { vbi = r300->velems->velem[i].vertex_buffer_index; if (transfer[vbi]) { vbuf = &r300->vertex_buffer[vbi]; pipe_buffer_unmap(&r300->context, vbuf->buffer, transfer[vbi]); transfer[vbi] = NULL; } } }
/* This functions is used to draw a rectangle for the blitter module. * * If we rendered a quad, the pixels on the main diagonal * would be computed and stored twice, which makes the clear/copy codepaths * somewhat inefficient. Instead we use a rectangular point sprite. */ static void r300_blitter_draw_rectangle(struct blitter_context *blitter, unsigned x1, unsigned y1, unsigned x2, unsigned y2, float depth, enum blitter_attrib_type type, const float attrib[4]) { struct r300_context *r300 = r300_context(util_blitter_get_pipe(blitter)); unsigned last_sprite_coord_enable = r300->sprite_coord_enable; unsigned width = x2 - x1; unsigned height = y2 - y1; unsigned vertex_size = type == UTIL_BLITTER_ATTRIB_COLOR || !r300->draw ? 8 : 4; unsigned dwords = 13 + vertex_size + (type == UTIL_BLITTER_ATTRIB_TEXCOORD ? 7 : 0); const float zeros[4] = {0, 0, 0, 0}; CS_LOCALS(r300); if (type == UTIL_BLITTER_ATTRIB_TEXCOORD) r300->sprite_coord_enable = 1; r300_update_derived_state(r300); /* Mark some states we don't care about as non-dirty. */ r300->clip_state.dirty = FALSE; r300->viewport_state.dirty = FALSE; if (!r300_prepare_for_rendering(r300, PREP_FIRST_DRAW, NULL, dwords, 0, 0)) goto done; DBG(r300, DBG_DRAW, "r300: draw_rectangle\n"); BEGIN_CS(dwords); /* Set up GA. */ OUT_CS_REG(R300_GA_POINT_SIZE, (height * 6) | ((width * 6) << 16)); if (type == UTIL_BLITTER_ATTRIB_TEXCOORD) { /* Set up the GA to generate texcoords. */ OUT_CS_REG(R300_GB_ENABLE, R300_GB_POINT_STUFF_ENABLE | (R300_GB_TEX_STR << R300_GB_TEX0_SOURCE_SHIFT)); OUT_CS_REG_SEQ(R300_GA_POINT_S0, 4); OUT_CS_32F(attrib[0]); OUT_CS_32F(attrib[3]); OUT_CS_32F(attrib[2]); OUT_CS_32F(attrib[1]); } /* Set up VAP controls. */ OUT_CS_REG(R300_VAP_CLIP_CNTL, R300_CLIP_DISABLE); OUT_CS_REG(R300_VAP_VTE_CNTL, R300_VTX_XY_FMT | R300_VTX_Z_FMT); OUT_CS_REG(R300_VAP_VTX_SIZE, vertex_size); OUT_CS_REG_SEQ(R300_VAP_VF_MAX_VTX_INDX, 2); OUT_CS(1); OUT_CS(0); /* Draw. */ OUT_CS_PKT3(R300_PACKET3_3D_DRAW_IMMD_2, vertex_size); OUT_CS(R300_VAP_VF_CNTL__PRIM_WALK_VERTEX_EMBEDDED | (1 << 16) | R300_VAP_VF_CNTL__PRIM_POINTS); OUT_CS_32F(x1 + width * 0.5f); OUT_CS_32F(y1 + height * 0.5f); OUT_CS_32F(depth); OUT_CS_32F(1); if (vertex_size == 8) { if (!attrib) attrib = zeros; OUT_CS_TABLE(attrib, 4); } END_CS; done: /* Restore the state. */ r300->clip_state.dirty = TRUE; r300->rs_state.dirty = TRUE; r300->viewport_state.dirty = TRUE; r300->sprite_coord_enable = last_sprite_coord_enable; }
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_pipelined(struct r300_context *r300, unsigned size, void *state) { /* The sample coordinates are in the range [0,11], because * GB_TILE_CONFIG.SUBPIXEL is set to the 1/12 subpixel precision. * * Some sample coordinates reach to neighboring pixels and should not be used. * (e.g. Y=11) * * The unused samples must be set to the positions of other valid samples. */ static unsigned sample_locs_1x[12] = { 6,6, 6,6, 6,6, 6,6, 6,6, 6,6 }; static unsigned sample_locs_2x[12] = { 3,9, 9,3, 9,3, 9,3, 9,3, 9,3 }; static unsigned sample_locs_4x[12] = { 4,4, 8,8, 2,10, 10,2, 10,2, 10,2 }; static unsigned sample_locs_6x[12] = { 3,1, 7,3, 11,5, 1,7, 5,9, 9,10 }; struct pipe_framebuffer_state* fb = (struct pipe_framebuffer_state*)r300->fb_state.state; unsigned i, num_cbufs = fb->nr_cbufs; unsigned mspos0, mspos1; CS_LOCALS(r300); /* If we use the multiwrite feature, the colorbuffers 2,3,4 must be * marked as UNUSED in the US block. */ if (r300->fb_multiwrite) { num_cbufs = MIN2(num_cbufs, 1); } BEGIN_CS(size); /* Colorbuffer format in the US block. * (must be written after unpipelined regs) */ OUT_CS_REG_SEQ(R300_US_OUT_FMT_0, 4); for (i = 0; i < num_cbufs; i++) { OUT_CS(r300_surface(r300_get_nonnull_cb(fb, i))->format); } for (; i < 1; i++) { OUT_CS(R300_US_OUT_FMT_C4_8 | R300_C0_SEL_B | R300_C1_SEL_G | R300_C2_SEL_R | R300_C3_SEL_A); } for (; i < 4; i++) { OUT_CS(R300_US_OUT_FMT_UNUSED); } /* Set sample positions. It depends on the framebuffer sample count. * These are pipelined regs and as such cannot be moved to the AA state. */ switch (r300->num_samples) { default: mspos0 = r300_get_mspos(0, sample_locs_1x); mspos1 = r300_get_mspos(1, sample_locs_1x); break; case 2: mspos0 = r300_get_mspos(0, sample_locs_2x); mspos1 = r300_get_mspos(1, sample_locs_2x); break; case 4: mspos0 = r300_get_mspos(0, sample_locs_4x); mspos1 = r300_get_mspos(1, sample_locs_4x); break; case 6: mspos0 = r300_get_mspos(0, sample_locs_6x); mspos1 = r300_get_mspos(1, sample_locs_6x); break; } OUT_CS_REG_SEQ(R300_GB_MSPOS0, 2); OUT_CS(mspos0); OUT_CS(mspos1); END_CS; }