X-Git-Url: https://git.libre-soc.org/?a=blobdiff_plain;f=src%2Fgallium%2Fdrivers%2Fr300%2Fr300_render.c;h=60700cf30372888d7f726f85854860395194df98;hb=ab130400cf91ab471e265e58193c95f04c7aeeda;hp=cf80692300ad32225dd3dff73a4ae25b4c451349;hpb=f5804e64b41e167bd5578df86e05329dd06c35d6;p=mesa.git diff --git a/src/gallium/drivers/r300/r300_render.c b/src/gallium/drivers/r300/r300_render.c index cf80692300a..60700cf3037 100644 --- a/src/gallium/drivers/r300/r300_render.c +++ b/src/gallium/drivers/r300/r300_render.c @@ -35,7 +35,6 @@ #include "util/u_prim.h" #include "r300_cs.h" -#include "r300_cb.h" #include "r300_context.h" #include "r300_screen_buffer.h" #include "r300_emit.h" @@ -119,13 +118,13 @@ static uint32_t r300_provoking_vertex_fixes(struct r300_context *r300, return color_control; } -static boolean index_bias_supported(struct r300_context *r300) +boolean r500_index_bias_supported(struct r300_context *r300) { return r300->screen->caps.is_r500 && r300->rws->get_value(r300->rws, R300_VID_DRM_2_3_0); } -static void r500_emit_index_bias(struct r300_context *r300, int index_bias) +void r500_emit_index_bias(struct r300_context *r300, int index_bias) { CS_LOCALS(r300); @@ -180,33 +179,21 @@ enum r300_prepare_flags { /** * Check if the requested number of dwords is available in the CS and - * if not, flush. Then validate buffers and emit dirty state. + * if not, flush. * \param r300 The context. * \param flags See r300_prepare_flags. - * \param index_buffer The index buffer to validate. The parameter may be NULL. * \param cs_dwords The number of dwords to reserve in CS. - * \param aos_offset The offset passed to emit_aos. - * \param index_bias The index bias to emit. - * \param end_cs_dwords The number of free dwords which must be available - * at the end of CS after drawing in case the CS space - * management is performed by a draw_* function manually. - * The parameter may be NULL. + * \return TRUE if the CS was flushed */ -static void r300_prepare_for_rendering(struct r300_context *r300, - enum r300_prepare_flags flags, - struct pipe_resource *index_buffer, - unsigned cs_dwords, - int aos_offset, - int index_bias, - unsigned *end_cs_dwords) +static boolean r300_reserve_cs_dwords(struct r300_context *r300, + enum r300_prepare_flags flags, + unsigned cs_dwords) { - unsigned end_dwords = 0; boolean flushed = FALSE; boolean first_draw = flags & PREP_FIRST_DRAW; boolean emit_aos = flags & PREP_EMIT_AOS; boolean emit_aos_swtcl = flags & PREP_EMIT_AOS_SWTCL; - boolean indexed = flags & PREP_INDEXED; - boolean hw_index_bias = index_bias_supported(r300); + boolean hw_index_bias = r500_index_bias_supported(r300); /* Add dirty state, index offset, and AOS. */ if (first_draw) { @@ -222,21 +209,47 @@ static void r300_prepare_for_rendering(struct r300_context *r300, cs_dwords += 7; /* emit_aos_swtcl */ } - /* Emitted in flush. */ - end_dwords += 26; /* emit_query_end */ - end_dwords += r300->hyperz_state.size; /* emit_hyperz_end */ - - cs_dwords += end_dwords; + cs_dwords += r300_get_num_cs_end_dwords(r300); /* Reserve requested CS space. */ - if (!r300_check_cs(r300, cs_dwords)) { + if (cs_dwords > (r300->cs->ndw - r300->cs->cdw)) { r300->context.flush(&r300->context, 0, NULL); flushed = TRUE; } + return flushed; +} + +/** + * Validate buffers and emit dirty state. + * \param r300 The context. + * \param flags See r300_prepare_flags. + * \param index_buffer The index buffer to validate. The parameter may be NULL. + * \param aos_offset The offset passed to emit_aos. + * \param index_bias The index bias to emit. + * \return TRUE if rendering should be skipped + */ +static boolean r300_emit_states(struct r300_context *r300, + enum r300_prepare_flags flags, + struct pipe_resource *index_buffer, + int aos_offset, + int index_bias) +{ + boolean first_draw = flags & PREP_FIRST_DRAW; + boolean emit_aos = flags & PREP_EMIT_AOS; + boolean emit_aos_swtcl = flags & PREP_EMIT_AOS_SWTCL; + boolean indexed = flags & PREP_INDEXED; + boolean hw_index_bias = r500_index_bias_supported(r300); + /* Validate buffers and emit dirty state if needed. */ - if (first_draw || flushed) { - r300_emit_buffer_validate(r300, flags & PREP_VALIDATE_VBOS, index_buffer); + if (first_draw) { + if (!r300_emit_buffer_validate(r300, flags & PREP_VALIDATE_VBOS, + index_buffer)) { + fprintf(stderr, "r300: CS space validation failed. " + "(not enough memory?) Skipping rendering.\n"); + return FALSE; + } + r300_emit_dirty_state(r300); if (hw_index_bias) { if (r300->screen->caps.has_tcl) @@ -252,8 +265,31 @@ static void r300_prepare_for_rendering(struct r300_context *r300, r300_emit_aos_swtcl(r300, indexed); } - if (end_cs_dwords) - *end_cs_dwords = end_dwords; + return TRUE; +} + +/** + * Check if the requested number of dwords is available in the CS and + * if not, flush. Then validate buffers and emit dirty state. + * \param r300 The context. + * \param flags See r300_prepare_flags. + * \param index_buffer The index buffer to validate. The parameter may be NULL. + * \param cs_dwords The number of dwords to reserve in CS. + * \param aos_offset The offset passed to emit_aos. + * \param index_bias The index bias to emit. + * \return TRUE if rendering should be skipped + */ +static boolean r300_prepare_for_rendering(struct r300_context *r300, + enum r300_prepare_flags flags, + struct pipe_resource *index_buffer, + unsigned cs_dwords, + int aos_offset, + int index_bias) +{ + if (r300_reserve_cs_dwords(r300, flags, cs_dwords)) + flags |= PREP_FIRST_DRAW; + + return r300_emit_states(r300, flags, index_buffer, aos_offset, index_bias); } static boolean immd_is_good_idea(struct r300_context *r300, @@ -314,11 +350,14 @@ static void r300_emit_draw_arrays_immediate(struct r300_context *r300, struct pipe_vertex_element* velem; struct pipe_vertex_buffer* vbuf; unsigned vertex_element_count = r300->velems->count; - unsigned i, v, vbi, dwords; + 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]; @@ -331,7 +370,10 @@ static void r300_emit_draw_arrays_immediate(struct r300_context *r300, uint32_t* mapelem[PIPE_MAX_ATTRIBS]; struct pipe_transfer* transfer[PIPE_MAX_ATTRIBS] = {0}; - CB_LOCALS; + 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++) { @@ -352,28 +394,24 @@ static void r300_emit_draw_arrays_immediate(struct r300_context *r300, mapelem[i] = map[vbi] + (velem->src_offset / 4); } - dwords = 9 + count * vertex_size; - - r300_prepare_for_rendering(r300, PREP_FIRST_DRAW, NULL, dwords, 0, 0, NULL); - - BEGIN_CS_AS_CB(r300, dwords); - OUT_CB_REG(R300_GA_COLOR_CONTROL, + BEGIN_CS(dwords); + OUT_CS_REG(R300_GA_COLOR_CONTROL, r300_provoking_vertex_fixes(r300, mode)); - OUT_CB_REG(R300_VAP_VTX_SIZE, vertex_size); - OUT_CB_REG_SEQ(R300_VAP_VF_MAX_VTX_INDX, 2); - OUT_CB(count - 1); - OUT_CB(0); - OUT_CB_PKT3(R300_PACKET3_3D_DRAW_IMMD_2, count * vertex_size); - OUT_CB(R300_VAP_VF_CNTL__PRIM_WALK_VERTEX_EMBEDDED | (count << 16) | + 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_CB_TABLE(&mapelem[i][stride[i] * v], size[i]); + OUT_CS_TABLE(&mapelem[i][stride[i] * v], size[i]); } } - END_CB; + END_CS; /* Unmap buffers. */ for (i = 0; i < vertex_element_count; i++) { @@ -474,7 +512,7 @@ static void r300_emit_draw_elements(struct r300_context *r300, (0 << R300_INDX_BUFFER_SKIP_SHIFT)); OUT_CS(offset_dwords << 2); OUT_CS_BUF_RELOC(indexBuffer, count_dwords, - r300_buffer(indexBuffer)->domain, 0, 0); + r300_buffer(indexBuffer)->domain, 0); END_CS; } @@ -497,29 +535,9 @@ static void r300_draw_range_elements(struct pipe_context* pipe, r300->rws->get_value(r300->rws, R300_VID_DRM_2_3_0); unsigned short_count; int buffer_offset = 0, index_offset = 0; /* for index bias emulation */ - boolean translate = FALSE; - - if (r300->skip_rendering) { - return; - } - - if (!u_trim_pipe_prim(mode, &count)) { - return; - } - - /* Index buffer range checking. */ - if ((start + count) * indexSize > indexBuffer->width0) { - fprintf(stderr, "r300: Invalid index buffer range. Skipping rendering.\n"); - return; - } - - /* Set up fallback for incompatible vertex layout if needed. */ - if (r300->incompatible_vb_layout || r300->velems->incompatible_layout) { - r300_begin_vertex_translate(r300); - translate = TRUE; - } + unsigned new_offset; - if (indexBias && !index_bias_supported(r300)) { + if (indexBias && !r500_index_bias_supported(r300)) { r300_split_index_bias(r300, indexBias, &buffer_offset, &index_offset); } @@ -527,18 +545,19 @@ static void r300_draw_range_elements(struct pipe_context* pipe, &start, count); r300_update_derived_state(r300); - r300_upload_index_buffer(r300, &indexBuffer, indexSize, start, count); + r300_upload_index_buffer(r300, &indexBuffer, indexSize, start, count, &new_offset); - /* 15 dwords for emit_draw_elements */ - r300_prepare_for_rendering(r300, - PREP_FIRST_DRAW | PREP_VALIDATE_VBOS | PREP_EMIT_AOS | PREP_INDEXED, - indexBuffer, 15, buffer_offset, indexBias, NULL); + start = new_offset; + + /* 15 dwords for emit_draw_elements. Give up if the function fails. */ + if (!r300_prepare_for_rendering(r300, + PREP_FIRST_DRAW | PREP_VALIDATE_VBOS | PREP_EMIT_AOS | + PREP_INDEXED, indexBuffer, 15, buffer_offset, indexBias)) + goto done; - u_upload_flush(r300->upload_vb); - u_upload_flush(r300->upload_ib); if (alt_num_verts || count <= 65535) { r300_emit_draw_elements(r300, indexBuffer, indexSize, - minIndex, maxIndex, mode, start, count); + minIndex, maxIndex, mode, start, count); } else { do { short_count = MIN2(count, 65534); @@ -551,33 +570,18 @@ static void r300_draw_range_elements(struct pipe_context* pipe, /* 15 dwords for emit_draw_elements */ if (count) { - r300_prepare_for_rendering(r300, - PREP_VALIDATE_VBOS | PREP_EMIT_AOS | PREP_INDEXED, - indexBuffer, 15, buffer_offset, indexBias, NULL); + if (!r300_prepare_for_rendering(r300, + PREP_VALIDATE_VBOS | PREP_EMIT_AOS | PREP_INDEXED, + indexBuffer, 15, buffer_offset, indexBias)) + goto done; } } while (count); } +done: if (indexBuffer != orgIndexBuffer) { pipe_resource_reference( &indexBuffer, NULL ); } - - if (translate) { - r300_end_vertex_translate(r300); - } -} - -/* Simple helpers for context setup. Should probably be moved to util. */ -static void r300_draw_elements(struct pipe_context* pipe, - struct pipe_resource* indexBuffer, - unsigned indexSize, int indexBias, unsigned mode, - unsigned start, unsigned count) -{ - struct r300_context *r300 = r300_context(pipe); - - pipe->draw_range_elements(pipe, indexBuffer, indexSize, indexBias, - 0, r300->vertex_buffer_max_index, - mode, start, count); } static void r300_draw_arrays(struct pipe_context* pipe, unsigned mode, @@ -588,30 +592,17 @@ static void r300_draw_arrays(struct pipe_context* pipe, unsigned mode, count > 65536 && r300->rws->get_value(r300->rws, R300_VID_DRM_2_3_0); unsigned short_count; - boolean translate = FALSE; - - if (r300->skip_rendering) { - return; - } - - if (!u_trim_pipe_prim(mode, &count)) { - return; - } - - /* Set up fallback for incompatible vertex layout if needed. */ - if (r300->incompatible_vb_layout || r300->velems->incompatible_layout) { - r300_begin_vertex_translate(r300); - translate = TRUE; - } r300_update_derived_state(r300); if (immd_is_good_idea(r300, count)) { r300_emit_draw_arrays_immediate(r300, mode, start, count); } else { - /* 9 spare dwords for emit_draw_arrays. */ - r300_prepare_for_rendering(r300, PREP_FIRST_DRAW | PREP_VALIDATE_VBOS | PREP_EMIT_AOS, - NULL, 9, start, 0, NULL); + /* 9 spare dwords for emit_draw_arrays. Give up if the function fails. */ + if (!r300_prepare_for_rendering(r300, + PREP_FIRST_DRAW | PREP_VALIDATE_VBOS | PREP_EMIT_AOS, + NULL, 9, start, 0)) + return; if (alt_num_verts || count <= 65535) { r300_emit_draw_arrays(r300, mode, count); @@ -623,127 +614,146 @@ static void r300_draw_arrays(struct pipe_context* pipe, unsigned mode, start += short_count; count -= short_count; - /* 9 spare dwords for emit_draw_arrays. */ + /* 9 spare dwords for emit_draw_arrays. Give up if the function fails. */ if (count) { - r300_prepare_for_rendering(r300, - PREP_VALIDATE_VBOS | PREP_EMIT_AOS, NULL, 9, - start, 0, NULL); + if (!r300_prepare_for_rendering(r300, + PREP_VALIDATE_VBOS | PREP_EMIT_AOS, NULL, 9, + start, 0)) + return; } } while (count); } - u_upload_flush(r300->upload_vb); - } - - if (translate) { - r300_end_vertex_translate(r300); } } -/**************************************************************************** - * The rest of this file is for SW TCL rendering only. Please be polite and * - * keep these functions separated so that they are easier to locate. ~C. * - ***************************************************************************/ - -/* SW TCL arrays, using Draw. */ -static void r300_swtcl_draw_arrays(struct pipe_context* pipe, - unsigned mode, - unsigned start, - unsigned count) +static void r300_draw_vbo(struct pipe_context* pipe, + const struct pipe_draw_info *info) { struct r300_context* r300 = r300_context(pipe); - struct pipe_transfer *vb_transfer[PIPE_MAX_ATTRIBS]; - int i; + unsigned count = info->count; + boolean translate = FALSE; + boolean indexed = info->indexed && r300->index_buffer.buffer; + unsigned start_indexed = 0; if (r300->skip_rendering) { return; } - if (!u_trim_pipe_prim(mode, &count)) { + if (!u_trim_pipe_prim(info->mode, &count)) { return; } - r300_update_derived_state(r300); - - for (i = 0; i < r300->vertex_buffer_count; i++) { - void* buf = pipe_buffer_map(pipe, - r300->vertex_buffer[i].buffer, - PIPE_TRANSFER_READ, - &vb_transfer[i]); - draw_set_mapped_vertex_buffer(r300->draw, i, buf); + /* Index buffer range checking. */ + if (indexed) { + assert(r300->index_buffer.offset % r300->index_buffer.index_size == 0); + + /* Compute start for draw_elements, taking the offset into account. */ + start_indexed = + info->start + + (r300->index_buffer.offset / r300->index_buffer.index_size); + + if ((start_indexed + count) * r300->index_buffer.index_size > + r300->index_buffer.buffer->width0) { + fprintf(stderr, "r300: Invalid index buffer range. Skipping rendering.\n"); + return; + } } - draw_set_mapped_element_buffer(r300->draw, 0, 0, NULL); - - draw_arrays(r300->draw, mode, start, count); + /* Set up fallback for incompatible vertex layout if needed. */ + if (r300->incompatible_vb_layout || r300->velems->incompatible_layout) { + r300_begin_vertex_translate(r300); + translate = TRUE; + } - /* XXX Not sure whether this is the best fix. - * It prevents CS from being rejected and weird assertion failures. */ - draw_flush(r300->draw); + if (indexed) { + r300_draw_range_elements(pipe, + r300->index_buffer.buffer, + r300->index_buffer.index_size, + info->index_bias, + info->min_index, + info->max_index, + info->mode, + start_indexed, + count); + } else { + r300_draw_arrays(pipe, + info->mode, + info->start, + count); + } - for (i = 0; i < r300->vertex_buffer_count; i++) { - pipe_buffer_unmap(pipe, r300->vertex_buffer[i].buffer, - vb_transfer[i]); - draw_set_mapped_vertex_buffer(r300->draw, i, NULL); + if (translate) { + r300_end_vertex_translate(r300); } } +/**************************************************************************** + * The rest of this file is for SW TCL rendering only. Please be polite and * + * keep these functions separated so that they are easier to locate. ~C. * + ***************************************************************************/ + /* SW TCL elements, using Draw. */ -static void r300_swtcl_draw_range_elements(struct pipe_context* pipe, - struct pipe_resource* indexBuffer, - unsigned indexSize, - int indexBias, - unsigned minIndex, - unsigned maxIndex, - unsigned mode, - unsigned start, - unsigned count) +static void r300_swtcl_draw_vbo(struct pipe_context* pipe, + const struct pipe_draw_info *info) { struct r300_context* r300 = r300_context(pipe); struct pipe_transfer *vb_transfer[PIPE_MAX_ATTRIBS]; - struct pipe_transfer *ib_transfer; + struct pipe_transfer *ib_transfer = NULL; + unsigned count = info->count; int i; - void* indices; + void *indices = NULL; + boolean indexed = info->indexed && r300->index_buffer.buffer; if (r300->skip_rendering) { return; } - if (!u_trim_pipe_prim(mode, &count)) { + if (!u_trim_pipe_prim(info->mode, &count)) { return; } r300_update_derived_state(r300); + r300_reserve_cs_dwords(r300, + PREP_FIRST_DRAW | PREP_EMIT_AOS_SWTCL | + (indexed ? PREP_INDEXED : 0), + indexed ? 256 : 6); + for (i = 0; i < r300->vertex_buffer_count; i++) { - void* buf = pipe_buffer_map(pipe, - r300->vertex_buffer[i].buffer, - PIPE_TRANSFER_READ, - &vb_transfer[i]); - draw_set_mapped_vertex_buffer(r300->draw, i, buf); + if (r300->vertex_buffer[i].buffer) { + void *buf = pipe_buffer_map(pipe, + r300->vertex_buffer[i].buffer, + PIPE_TRANSFER_READ, + &vb_transfer[i]); + draw_set_mapped_vertex_buffer(r300->draw, i, buf); + } } - indices = pipe_buffer_map(pipe, indexBuffer, - PIPE_TRANSFER_READ, &ib_transfer); - draw_set_mapped_element_buffer_range(r300->draw, indexSize, indexBias, - minIndex, maxIndex, indices); + if (indexed) { + indices = pipe_buffer_map(pipe, r300->index_buffer.buffer, + PIPE_TRANSFER_READ, &ib_transfer); + } - draw_arrays(r300->draw, mode, start, count); + draw_set_mapped_index_buffer(r300->draw, indices); - /* XXX Not sure whether this is the best fix. - * It prevents CS from being rejected and weird assertion failures. */ + r300->draw_vbo_locked = TRUE; + r300->draw_first_emitted = FALSE; + draw_vbo(r300->draw, info); draw_flush(r300->draw); + r300->draw_vbo_locked = FALSE; for (i = 0; i < r300->vertex_buffer_count; i++) { - pipe_buffer_unmap(pipe, r300->vertex_buffer[i].buffer, - vb_transfer[i]); - draw_set_mapped_vertex_buffer(r300->draw, i, NULL); + if (r300->vertex_buffer[i].buffer) { + pipe_buffer_unmap(pipe, r300->vertex_buffer[i].buffer, + vb_transfer[i]); + draw_set_mapped_vertex_buffer(r300->draw, i, NULL); + } } - pipe_buffer_unmap(pipe, indexBuffer, - ib_transfer); - draw_set_mapped_element_buffer_range(r300->draw, 0, 0, - start, start + count - 1, - NULL); + if (indexed) { + pipe_buffer_unmap(pipe, r300->index_buffer.buffer, ib_transfer); + draw_set_mapped_index_buffer(r300->draw, NULL); + } } /* Object for rendering using Draw. */ @@ -760,9 +770,6 @@ struct r300_render { unsigned hwprim; /* VBO */ - struct pipe_resource* vbo; - size_t vbo_size; - size_t vbo_offset; size_t vbo_max_used; void * vbo_ptr; @@ -793,35 +800,40 @@ static boolean r300_render_allocate_vertices(struct vbuf_render* render, struct pipe_screen* screen = r300->context.screen; size_t size = (size_t)vertex_size * (size_t)count; - if (size + r300render->vbo_offset > r300render->vbo_size) + DBG(r300, DBG_DRAW, "r300: render_allocate_vertices (size: %d)\n", size); + + if (size + r300->draw_vbo_offset > r300->draw_vbo_size) { - pipe_resource_reference(&r300->vbo, NULL); - r300render->vbo = pipe_buffer_create(screen, - PIPE_BIND_VERTEX_BUFFER, - R300_MAX_DRAW_VBO_SIZE); - r300render->vbo_offset = 0; - r300render->vbo_size = R300_MAX_DRAW_VBO_SIZE; + pipe_resource_reference(&r300->vbo, NULL); + r300->vbo = pipe_buffer_create(screen, + PIPE_BIND_VERTEX_BUFFER, + R300_MAX_DRAW_VBO_SIZE); + r300->draw_vbo_offset = 0; + r300->draw_vbo_size = R300_MAX_DRAW_VBO_SIZE; } r300render->vertex_size = vertex_size; - r300->vbo = r300render->vbo; - r300->vbo_offset = r300render->vbo_offset; - return (r300render->vbo) ? TRUE : FALSE; + return (r300->vbo) ? TRUE : FALSE; } static void* r300_render_map_vertices(struct vbuf_render* render) { struct r300_render* r300render = r300_render(render); + struct r300_context* r300 = r300render->r300; assert(!r300render->vbo_transfer); + DBG(r300, DBG_DRAW, "r300: render_map_vertices\n"); + r300render->vbo_ptr = pipe_buffer_map(&r300render->r300->context, - r300render->vbo, + r300->vbo, PIPE_TRANSFER_WRITE, &r300render->vbo_transfer); - return ((uint8_t*)r300render->vbo_ptr + r300render->vbo_offset); + assert(r300render->vbo_ptr); + + return ((uint8_t*)r300render->vbo_ptr + r300->draw_vbo_offset); } static void r300_render_unmap_vertices(struct vbuf_render* render, @@ -830,12 +842,15 @@ static void r300_render_unmap_vertices(struct vbuf_render* render, { struct r300_render* r300render = r300_render(render); struct pipe_context* context = &r300render->r300->context; + struct r300_context* r300 = r300render->r300; assert(r300render->vbo_transfer); + DBG(r300, DBG_DRAW, "r300: render_unmap_vertices\n"); + r300render->vbo_max_used = MAX2(r300render->vbo_max_used, r300render->vertex_size * (max + 1)); - pipe_buffer_unmap(context, r300render->vbo, r300render->vbo_transfer); + pipe_buffer_unmap(context, r300->vbo, r300render->vbo_transfer); r300render->vbo_transfer = NULL; } @@ -843,8 +858,11 @@ static void r300_render_unmap_vertices(struct vbuf_render* render, static void r300_render_release_vertices(struct vbuf_render* render) { struct r300_render* r300render = r300_render(render); + struct r300_context* r300 = r300render->r300; + + DBG(r300, DBG_DRAW, "r300: render_release_vertices\n"); - r300render->vbo_offset += r300render->vbo_max_used; + r300->draw_vbo_offset += r300render->vbo_max_used; r300render->vbo_max_used = 0; } @@ -870,13 +888,21 @@ static void r300_render_draw_arrays(struct vbuf_render* render, unsigned dwords = 6; CS_LOCALS(r300); - (void) i; (void) ptr; - r300_prepare_for_rendering(r300, PREP_FIRST_DRAW | PREP_EMIT_AOS_SWTCL, - NULL, dwords, 0, 0, NULL); + DBG(r300, DBG_DRAW, "r300: render_draw_arrays (count: %d)\n", count); - DBG(r300, DBG_DRAW, "r300: Doing vbuf render, 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! @@ -903,6 +929,8 @@ static void r300_render_draw_arrays(struct vbuf_render* render, OUT_CS(R300_VAP_VF_CNTL__PRIM_WALK_VERTEX_LIST | (count << 16) | r300render->hwprim); END_CS; + + r300->draw_first_emitted = TRUE; } static void r300_render_draw_elements(struct vbuf_render* render, @@ -913,23 +941,33 @@ static void r300_render_draw_elements(struct vbuf_render* render, struct r300_context* r300 = r300render->r300; int i; unsigned end_cs_dwords; - unsigned max_index = (r300render->vbo_size - r300render->vbo_offset) / + unsigned max_index = (r300->draw_vbo_size - r300->draw_vbo_offset) / (r300render->r300->vertex_info.size * 4) - 1; unsigned short_count; unsigned free_dwords; CS_LOCALS(r300); + DBG(r300, DBG_DRAW, "r300: render_draw_elements (count: %d)\n", count); - /* Reserve at least 256 dwords. - * - * Below we manage the CS space manually because there may be more + if (r300->draw_first_emitted) { + if (!r300_prepare_for_rendering(r300, + PREP_FIRST_DRAW | PREP_EMIT_AOS_SWTCL | PREP_INDEXED, + NULL, 256, 0, 0)) + return; + } else { + if (!r300_emit_states(r300, + PREP_FIRST_DRAW | PREP_EMIT_AOS_SWTCL | PREP_INDEXED, + NULL, 0, 0)) + return; + } + + /* Below we manage the CS space manually because there may be more * indices than it can fit in CS. */ - r300_prepare_for_rendering(r300, - PREP_FIRST_DRAW | PREP_EMIT_AOS_SWTCL | PREP_INDEXED, - NULL, 256, 0, 0, &end_cs_dwords); + + end_cs_dwords = r300_get_num_cs_end_dwords(r300); while (count) { - free_dwords = r300->rws->get_cs_free_dwords(r300->rws); + free_dwords = r300->cs->ndw - r300->cs->cdw; short_count = MIN2(count, (free_dwords - end_cs_dwords - 6) * 2); @@ -954,11 +992,16 @@ static void r300_render_draw_elements(struct vbuf_render* render, count -= short_count; if (count) { - r300_prepare_for_rendering(r300, - PREP_EMIT_AOS_SWTCL | PREP_INDEXED, - NULL, 256, 0, 0, &end_cs_dwords); + if (!r300_prepare_for_rendering(r300, + PREP_EMIT_AOS_SWTCL | PREP_INDEXED, + NULL, 256, 0, 0)) + return; + + end_cs_dwords = r300_get_num_cs_end_dwords(r300); } } + + r300->draw_first_emitted = TRUE; } static void r300_render_destroy(struct vbuf_render* render) @@ -986,10 +1029,6 @@ static struct vbuf_render* r300_render_create(struct r300_context* r300) r300render->base.release_vertices = r300_render_release_vertices; r300render->base.destroy = r300_render_destroy; - r300render->vbo = NULL; - r300render->vbo_size = 0; - r300render->vbo_offset = 0; - return &r300render->base; } @@ -1016,11 +1055,19 @@ struct draw_stage* r300_draw_stage(struct r300_context* r300) return stage; } +void r300_draw_flush_vbuf(struct r300_context *r300) +{ + pipe_resource_reference(&r300->vbo, NULL); + r300->draw_vbo_size = 0; +} + /**************************************************************************** * End of SW TCL functions * ***************************************************************************/ -/* If we used a quad to draw a rectangle, the pixels on the main diagonal +/* 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, @@ -1039,7 +1086,7 @@ static void r300_blitter_draw_rectangle(struct blitter_context *blitter, unsigned dwords = 13 + vertex_size + (type == UTIL_BLITTER_ATTRIB_TEXCOORD ? 7 : 0); const float zeros[4] = {0, 0, 0, 0}; - CB_LOCALS; + CS_LOCALS(r300); if (type == UTIL_BLITTER_ATTRIB_TEXCOORD) r300->sprite_coord_enable = 1; @@ -1050,48 +1097,52 @@ static void r300_blitter_draw_rectangle(struct blitter_context *blitter, r300->clip_state.dirty = FALSE; r300->viewport_state.dirty = FALSE; - r300_prepare_for_rendering(r300, PREP_FIRST_DRAW, NULL, dwords, 0, 0, NULL); + 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_AS_CB(r300, dwords); + BEGIN_CS(dwords); /* Set up GA. */ - OUT_CB_REG(R300_GA_POINT_SIZE, (height * 6) | ((width * 6) << 16)); + 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_CB_REG(R300_GB_ENABLE, R300_GB_POINT_STUFF_ENABLE | + OUT_CS_REG(R300_GB_ENABLE, R300_GB_POINT_STUFF_ENABLE | (R300_GB_TEX_STR << R300_GB_TEX0_SOURCE_SHIFT)); - OUT_CB_REG_SEQ(R300_GA_POINT_S0, 4); - OUT_CB_32F(attrib[0]); - OUT_CB_32F(attrib[3]); - OUT_CB_32F(attrib[2]); - OUT_CB_32F(attrib[1]); + 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_CB_REG(R300_VAP_CLIP_CNTL, R300_CLIP_DISABLE); - OUT_CB_REG(R300_VAP_VTE_CNTL, R300_VTX_XY_FMT | R300_VTX_Z_FMT); - OUT_CB_REG(R300_VAP_VTX_SIZE, vertex_size); - OUT_CB_REG_SEQ(R300_VAP_VF_MAX_VTX_INDX, 2); - OUT_CB(1); - OUT_CB(0); + 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_CB_PKT3(R300_PACKET3_3D_DRAW_IMMD_2, vertex_size); - OUT_CB(R300_VAP_VF_CNTL__PRIM_WALK_VERTEX_EMBEDDED | (1 << 16) | + 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_CB_32F(x1 + width * 0.5f); - OUT_CB_32F(y1 + height * 0.5f); - OUT_CB_32F(depth); - OUT_CB_32F(1); + 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_CB_TABLE(attrib, 4); + OUT_CS_TABLE(attrib, 4); } - END_CB; + END_CS; +done: /* Restore the state. */ r300->clip_state.dirty = TRUE; r300->rs_state.dirty = TRUE; @@ -1140,16 +1191,11 @@ static void r300_resource_resolve(struct pipe_context* pipe, void r300_init_render_functions(struct r300_context *r300) { - /* Set generic functions. */ - r300->context.draw_elements = r300_draw_elements; - /* Set draw functions based on presence of HW TCL. */ if (r300->screen->caps.has_tcl) { - r300->context.draw_arrays = r300_draw_arrays; - r300->context.draw_range_elements = r300_draw_range_elements; + r300->context.draw_vbo = r300_draw_vbo; } else { - r300->context.draw_arrays = r300_swtcl_draw_arrays; - r300->context.draw_range_elements = r300_swtcl_draw_range_elements; + r300->context.draw_vbo = r300_swtcl_draw_vbo; } r300->context.resource_resolve = r300_resource_resolve;