summaryrefslogtreecommitdiff
path: root/src/gallium/drivers/r300/r300_render_translate.c
diff options
context:
space:
mode:
authorMarek Olšák <maraeo@gmail.com>2010-06-12 21:16:41 +0200
committerMarek Olšák <maraeo@gmail.com>2010-06-13 17:43:37 +0200
commitaa5422327d6f49d8940c2b933c2342ad8968032c (patch)
tree7a7f6b13f9364deafe5355cce00567113c622dc4 /src/gallium/drivers/r300/r300_render_translate.c
parent028459b0bf2bb778b55493f9b23ab7f2c9b355a0 (diff)
r300g: move index buffer translate functions to their new home
Diffstat (limited to 'src/gallium/drivers/r300/r300_render_translate.c')
-rw-r--r--src/gallium/drivers/r300/r300_render_translate.c140
1 files changed, 137 insertions, 3 deletions
diff --git a/src/gallium/drivers/r300/r300_render_translate.c b/src/gallium/drivers/r300/r300_render_translate.c
index b03582aac3..ea3c9668f7 100644
--- a/src/gallium/drivers/r300/r300_render_translate.c
+++ b/src/gallium/drivers/r300/r300_render_translate.c
@@ -21,9 +21,10 @@
* USE OR OTHER DEALINGS IN THE SOFTWARE. */
/**
- * The functions below translate vertex buffers to the layout compatible
- * with the hardware, so that all vertex fetches are be DWORD-aligned and all
- * used vertex formats are supported.
+ * The functions below translate vertex and index buffers to the layout
+ * compatible with the hardware, so that all vertex and index fetches are
+ * DWORD-aligned and all used vertex and index formats are supported.
+ * For indices, an optional index offset is added to each index.
*/
#include "r300_context.h"
@@ -163,3 +164,136 @@ void r300_end_vertex_translate(struct r300_context *r300)
pipe_resource_reference(&r300->vertex_buffer[r300->tran.vb_slot].buffer,
NULL);
}
+
+static void r300_shorten_ubyte_elts(struct r300_context* r300,
+ struct pipe_resource** elts,
+ int index_bias,
+ unsigned start,
+ unsigned count)
+{
+ struct pipe_context* context = &r300->context;
+ struct pipe_screen* screen = r300->context.screen;
+ struct pipe_resource* new_elts;
+ unsigned char *in_map;
+ unsigned short *out_map;
+ struct pipe_transfer *src_transfer, *dst_transfer;
+ unsigned i;
+
+ new_elts = pipe_buffer_create(screen,
+ PIPE_BIND_INDEX_BUFFER,
+ 2 * count);
+
+ in_map = pipe_buffer_map(context, *elts, PIPE_TRANSFER_READ, &src_transfer);
+ out_map = pipe_buffer_map(context, new_elts, PIPE_TRANSFER_WRITE, &dst_transfer);
+
+ in_map += start;
+
+ for (i = 0; i < count; i++) {
+ *out_map = (unsigned short)(*in_map + index_bias);
+ in_map++;
+ out_map++;
+ }
+
+ pipe_buffer_unmap(context, *elts, src_transfer);
+ pipe_buffer_unmap(context, new_elts, dst_transfer);
+
+ *elts = new_elts;
+}
+
+static void r300_rebuild_ushort_elts(struct r300_context *r300,
+ struct pipe_resource **elts,
+ int index_bias,
+ unsigned start, unsigned count)
+{
+ struct pipe_context *context = &r300->context;
+ struct pipe_transfer *in_transfer = NULL;
+ struct pipe_transfer *out_transfer = NULL;
+ struct pipe_resource *new_elts;
+ unsigned short *in_map;
+ unsigned short *out_map;
+ unsigned i;
+
+ new_elts = pipe_buffer_create(context->screen,
+ PIPE_BIND_INDEX_BUFFER,
+ 2 * count);
+
+ in_map = pipe_buffer_map(context, *elts,
+ PIPE_TRANSFER_READ, &in_transfer);
+ out_map = pipe_buffer_map(context, new_elts,
+ PIPE_TRANSFER_WRITE, &out_transfer);
+
+ in_map += start;
+ for (i = 0; i < count; i++) {
+ *out_map = (unsigned short)(*in_map + index_bias);
+ in_map++;
+ out_map++;
+ }
+
+ pipe_buffer_unmap(context, *elts, in_transfer);
+ pipe_buffer_unmap(context, new_elts, out_transfer);
+
+ *elts = new_elts;
+}
+
+static void r300_rebuild_uint_elts(struct r300_context *r300,
+ struct pipe_resource **elts,
+ int index_bias,
+ unsigned start, unsigned count)
+{
+ struct pipe_context *context = &r300->context;
+ struct pipe_transfer *in_transfer = NULL;
+ struct pipe_transfer *out_transfer = NULL;
+ struct pipe_resource *new_elts;
+ unsigned int *in_map;
+ unsigned int *out_map;
+ unsigned i;
+
+ new_elts = pipe_buffer_create(context->screen,
+ PIPE_BIND_INDEX_BUFFER,
+ 2 * count);
+
+ in_map = pipe_buffer_map(context, *elts,
+ PIPE_TRANSFER_READ, &in_transfer);
+ out_map = pipe_buffer_map(context, new_elts,
+ PIPE_TRANSFER_WRITE, &out_transfer);
+
+ in_map += start;
+ for (i = 0; i < count; i++) {
+ *out_map = (unsigned int)(*in_map + index_bias);
+ in_map++;
+ out_map++;
+ }
+
+ pipe_buffer_unmap(context, *elts, in_transfer);
+ pipe_buffer_unmap(context, new_elts, out_transfer);
+
+ *elts = new_elts;
+}
+
+void r300_translate_index_buffer(struct r300_context *r300,
+ struct pipe_resource **index_buffer,
+ unsigned *index_size, unsigned index_offset,
+ unsigned *start, unsigned count)
+{
+ switch (*index_size) {
+ case 1:
+ r300_shorten_ubyte_elts(r300, index_buffer, index_offset, *start, count);
+ *index_size = 2;
+ *start = 0;
+ break;
+
+ case 2:
+ if (*start % 2 != 0 || index_offset) {
+ r300_rebuild_ushort_elts(r300, index_buffer, index_offset, *start, count);
+ *start = 0;
+ }
+ break;
+
+ case 4:
+ if (index_offset) {
+ r300_rebuild_uint_elts(r300, index_buffer, index_offset, *start, count);
+ *start = 0;
+ }
+ break;
+ }
+}