r300g: VBOs WIP
authorMaciej Cencora <m.cencora@gmail.com>
Sun, 25 Oct 2009 12:53:25 +0000 (13:53 +0100)
committerCorbin Simpson <MostAwesomeDude@gmail.com>
Sat, 7 Nov 2009 19:53:13 +0000 (11:53 -0800)
src/gallium/drivers/r300/Makefile
src/gallium/drivers/r300/r300_context.c
src/gallium/drivers/r300/r300_context.h
src/gallium/drivers/r300/r300_emit.c
src/gallium/drivers/r300/r300_emit.h
src/gallium/drivers/r300/r300_render.c
src/gallium/drivers/r300/r300_state.c
src/gallium/drivers/r300/r300_state_derived.c
src/gallium/drivers/r300/r300_vbo.c [new file with mode: 0644]
src/gallium/drivers/r300/r300_vbo.h [new file with mode: 0644]

index f73d80de88237b55c02799f6149bebbb970e59b3..d13bb7a36b1bd742d69c4f73137aacead67a30db 100644 (file)
@@ -17,6 +17,7 @@ C_SOURCES = \
        r300_state.c \
        r300_state_derived.c \
        r300_state_invariant.c \
+       r300_vbo.c \
        r300_vs.c \
        r300_texture.c \
        r300_tgsi_to_rc.c
index f974147ea43eb4b0bcb419328d9e5170e65fbdaf..b520e5929e20a28bad43c6c50eb846ca4cd5fe40 100644 (file)
@@ -104,6 +104,7 @@ struct pipe_context* r300_create_context(struct pipe_screen* screen,
                                          struct r300_winsys* r300_winsys)
 {
     struct r300_context* r300 = CALLOC_STRUCT(r300_context);
+    struct r300_screen* r300screen = r300_screen(screen);
 
     if (!r300)
         return NULL;
@@ -119,9 +120,16 @@ struct pipe_context* r300_create_context(struct pipe_screen* screen,
 
     r300->context.clear = r300_clear;
 
-    r300->context.draw_arrays = r300_draw_arrays;
-    r300->context.draw_elements = r300_draw_elements;
-    r300->context.draw_range_elements = r300_swtcl_draw_range_elements;
+    if (r300screen->caps->has_tcl)
+    {
+        r300->context.draw_arrays = r300_draw_arrays;
+        r300->context.draw_elements = r300_draw_elements;
+        r300->context.draw_range_elements = r300_draw_range_elements;
+    }
+    else
+    {
+        assert(0);
+    }
 
     r300->context.is_texture_referenced = r300_is_texture_referenced;
     r300->context.is_buffer_referenced = r300_is_buffer_referenced;
index 850e5a41c91f5a8abe46f33d2f0bb1e254e83831..a6748852d83a2ae124c48381ed6b9c98f9a4cefc 100644 (file)
@@ -216,18 +216,19 @@ struct r300_texture {
     struct r300_texture_state state;
 };
 
-struct r300_vertex_format {
+struct r300_vertex_info {
     /* Parent class */
     struct vertex_info vinfo;
-    /* R300_VAP_PROG_STREAK_CNTL_[0-7] */
-    uint32_t vap_prog_stream_cntl[8];
-    /* R300_VAP_PROG_STREAK_CNTL_EXT_[0-7] */
-    uint32_t vap_prog_stream_cntl_ext[8];
     /* Map of vertex attributes into PVS memory for HW TCL,
      * or GA memory for SW TCL. */
     int vs_tab[16];
     /* Map of rasterizer attributes from GB through RS to US. */
     int fs_tab[16];
+
+    /* R300_VAP_PROG_STREAK_CNTL_[0-7] */
+    uint32_t vap_prog_stream_cntl[8];
+    /* R300_VAP_PROG_STREAK_CNTL_EXT_[0-7] */
+    uint32_t vap_prog_stream_cntl_ext[8];
 };
 
 extern struct pipe_viewport_state r300_viewport_identity;
@@ -256,7 +257,7 @@ struct r300_context {
      * depends on the combination of both currently loaded shaders. */
     struct util_hash_table* shader_hash_table;
     /* Vertex formatting information. */
-    struct r300_vertex_format* vertex_info;
+    struct r300_vertex_info* vertex_info;
 
     /* Various CSO state objects. */
     /* Blend state. */
@@ -285,12 +286,6 @@ struct r300_context {
     /* Texture states. */
     struct r300_texture* textures[8];
     int texture_count;
-    /* Vertex buffers for Gallium. */
-    struct pipe_vertex_buffer vertex_buffers[PIPE_MAX_ATTRIBS];
-    int vertex_buffer_count;
-    /* Vertex elements for Gallium. */
-    struct pipe_vertex_element vertex_elements[PIPE_MAX_ATTRIBS];
-    int vertex_element_count;
     /* Vertex shader. */
     struct r300_vertex_shader* vs;
     /* Viewport state. */
@@ -298,6 +293,14 @@ struct r300_context {
     /* ZTOP state. */
     struct r300_ztop_state ztop_state;
 
+    /* Vertex buffers for Gallium. */
+    struct pipe_vertex_buffer vertex_buffer[PIPE_MAX_ATTRIBS];
+    int vbuf_count;
+    /* Vertex elements for Gallium. */
+    struct pipe_vertex_element vertex_element[PIPE_MAX_ATTRIBS];
+    int aos_count;
+    unsigned hw_prim;
+
     /* Bitmask of dirty state objects. */
     uint32_t dirty_state;
     /* Flag indicating whether or not the HW is dirty. */
index 69ce5966e8061a383f5c22c46d743e98f5c0d9bb..92e6ec606ca79b4d9ee3d90fbea9289cb3462d5c 100644 (file)
@@ -582,7 +582,48 @@ void r300_emit_texture(struct r300_context* r300,
     END_CS;
 }
 
-void r300_emit_vertex_buffer(struct r300_context* r300)
+void r300_emit_aos(struct r300_context* r300, unsigned offset)
+{
+    struct pipe_vertex_buffer *vbuf = r300->vertex_buffer;
+    struct pipe_vertex_element *velem = r300->vertex_element;
+    CS_LOCALS(r300);
+    int i;
+    unsigned packet_size = (r300->aos_count * 3 + 1) / 2;
+    BEGIN_CS(2 + packet_size + r300->aos_count * 2);
+    OUT_CS_PKT3(R300_PACKET3_3D_LOAD_VBPNTR, packet_size);
+    OUT_CS(r300->aos_count);
+    for (i = 0; i < r300->aos_count - 1; i += 2) {
+        int buf_num1 = velem[i].vertex_buffer_index;
+        int buf_num2 = velem[i+1].vertex_buffer_index;
+        assert(vbuf[buf_num1].stride % 4 == 0 && pf_get_size(velem[i].src_format) % 4 == 0);
+        assert(vbuf[buf_num2].stride % 4 == 0 && pf_get_size(velem[i+1].src_format) % 4 == 0);
+        OUT_CS((pf_get_size(velem[i].src_format) >> 2) | (vbuf[buf_num1].stride << 6) |
+               (pf_get_size(velem[i+1].src_format) << 14) | (vbuf[buf_num2].stride << 22));
+        OUT_CS(vbuf[buf_num1].buffer_offset + velem[i].src_offset +
+               offset * vbuf[buf_num1].stride);
+        OUT_CS(vbuf[buf_num2].buffer_offset + velem[i+1].src_offset +
+               offset * vbuf[buf_num2].stride);
+    }
+    if (r300->aos_count & 1) {
+        int buf_num = velem[i].vertex_buffer_index;
+        assert(vbuf[buf_num].stride % 4 == 0 && pf_get_size(velem[i].src_format) % 4 == 0);
+        OUT_CS((pf_get_size(velem[i].src_format) >> 2) | (vbuf[buf_num].stride << 6));
+        OUT_CS(vbuf[buf_num].buffer_offset + velem[i].src_offset +
+               offset * vbuf[buf_num].stride);
+    }
+
+    for (i = 0; i < r300->aos_count; i++) {
+        cs_winsys->write_cs_reloc(cs_winsys,
+                                  vbuf[velem[i].vertex_buffer_index].buffer,
+                                  RADEON_GEM_DOMAIN_GTT,
+                                  0,
+                                  0);
+        cs_count -= 2;
+    }
+    END_CS;
+}
+#if 0
+void r300_emit_draw_packet(struct r300_context* r300)
 {
     CS_LOCALS(r300);
 
@@ -605,6 +646,65 @@ void r300_emit_vertex_buffer(struct r300_context* r300)
     OUT_CS_RELOC(r300->vbo, 0, RADEON_GEM_DOMAIN_GTT, 0, 0);
     END_CS;
 }
+#endif
+void r300_emit_draw_arrays(struct r300_context *r300,
+                           unsigned count)
+{
+    CS_LOCALS(r300);
+    assert(count < 65536);
+
+    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->hw_prim);
+    END_CS;
+}
+
+void r300_emit_draw_elements(struct r300_context *r300,
+                             struct pipe_buffer* indexBuffer,
+                             unsigned indexSize,
+                             unsigned minIndex,
+                             unsigned maxIndex,
+                             unsigned start,
+                             unsigned count)
+{
+    CS_LOCALS(r300);
+    assert(indexSize == 4 || indexSize == 2);
+    assert(count < 65536);
+    assert((start * indexSize)  % 4 == 0);
+
+    uint32_t size_dwords;
+    uint32_t skip_dwords = indexSize * start / sizeof(uint32_t);
+    assert(skip_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) {
+        size_dwords = count + start;
+        OUT_CS(R300_VAP_VF_CNTL__PRIM_WALK_INDICES | (count << 16) |
+               R300_VAP_VF_CNTL__INDEX_SIZE_32bit | r300->hw_prim);
+    } else {
+        size_dwords = (count + start + 1) / 2;
+        OUT_CS(R300_VAP_VF_CNTL__PRIM_WALK_INDICES |
+               (count << 16) | r300->hw_prim);
+    }
+
+    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(skip_dwords);
+    OUT_CS(size_dwords);
+    cs_winsys->write_cs_reloc(cs_winsys,
+                              indexBuffer,
+                              RADEON_GEM_DOMAIN_GTT,
+                              0,
+                              0);
+    cs_count -= 2;
+
+    END_CS;
+}
 
 void r300_emit_vertex_format_state(struct r300_context* r300)
 {
@@ -771,8 +871,6 @@ void r300_emit_dirty_state(struct r300_context* r300)
         return;
     }
 
-    r300_update_derived_state(r300);
-
     /* Clean out BOs. */
     r300->winsys->reset_bos(r300->winsys);
 
@@ -823,7 +921,7 @@ validate:
             goto validate;
         }
     } else {
-        debug_printf("No VBO while emitting dirty state!\n");
+        // debug_printf("No VBO while emitting dirty state!\n");
     }
     if (!r300->winsys->validate(r300->winsys)) {
         r300->context.flush(&r300->context, 0, NULL);
@@ -951,7 +1049,7 @@ validate:
     */
 
     /* Finally, emit the VBO. */
-    r300_emit_vertex_buffer(r300);
+    //r300_emit_vertex_buffer(r300);
 
     r300->dirty_hw++;
 }
index 6befca72cedd480c8a1ee6330ef0091b6982560d..b4fdfecde019dc012b9971ef46ee8ebcc87bf88f 100644 (file)
@@ -29,6 +29,8 @@
 struct rX00_fragment_program_code;
 struct r300_vertex_program_code;
 
+void r300_emit_aos(struct r300_context* r300, unsigned offset);
+
 void r300_emit_blend_state(struct r300_context* r300,
                            struct r300_blend_state* blend);
 
@@ -38,6 +40,16 @@ void r300_emit_blend_color_state(struct r300_context* r300,
 void r300_emit_clip_state(struct r300_context* r300,
                           struct pipe_clip_state* clip);
 
+void r300_emit_draw_arrays(struct r300_context *r300, unsigned count);
+
+void r300_emit_draw_elements(struct r300_context *r300,
+                             struct pipe_buffer* indexBuffer,
+                             unsigned indexSize,
+                             unsigned minIndex,
+                             unsigned maxIndex,
+                             unsigned start,
+                             unsigned count);
+
 void r300_emit_dsa_state(struct r300_context* r300,
                          struct r300_dsa_state* dsa);
 
index 634c803f2a801d536498e8ff5802f55f46d3991f..86aaf841dd69ee0c5c3181031b7bf896cfdb38e7 100644 (file)
@@ -31,6 +31,7 @@
 #include "util/u_memory.h"
 #include "util/u_prim.h"
 
+#include "r300_vbo.h"
 #include "r300_cs.h"
 #include "r300_context.h"
 #include "r300_emit.h"
@@ -69,98 +70,64 @@ uint32_t r300_translate_primitive(unsigned prim)
     }
 }
 
-/* This is the fast-path drawing & emission for HW TCL. */
-boolean r300_draw_range_elements(struct pipe_context* pipe,
-                                 struct pipe_buffer* indexBuffer,
-                                 unsigned indexSize,
-                                 unsigned minIndex,
-                                 unsigned maxIndex,
-                                 unsigned mode,
-                                 unsigned start,
-                                 unsigned count)
+static boolean setup_vertex_buffers(struct r300_context *r300)
 {
-    struct r300_context* r300 = r300_context(pipe);
-    uint32_t prim = r300_translate_primitive(mode);
-    struct pipe_vertex_buffer* aos = r300->vertex_buffers;
-    unsigned aos_count = r300->vertex_buffer_count;
-    short* indices;
-    unsigned packet_size;
-    unsigned i;
-    bool invalid = FALSE;
-    
-    CS_LOCALS(r300);
-
-    if (!u_trim_pipe_prim(mode, &count)) {
-        return FALSE;
-    }
+    unsigned vbuf_count = r300->aos_count;
+    struct pipe_vertex_buffer *vbuf= r300->vertex_buffer;
+    struct pipe_vertex_element *velem= r300->vertex_element;
+    bool invalid = false;
 
 validate:
-    for (i = 0; i < aos_count; i++) {
-        if (!r300->winsys->add_buffer(r300->winsys, aos[i].buffer,
-                    RADEON_GEM_DOMAIN_GTT, 0)) {
-            pipe->flush(pipe, 0, NULL);
+    for (int i = 0; i < vbuf_count; i++) {
+        if (!r300->winsys->add_buffer(r300->winsys, vbuf[velem[i].vertex_buffer_index].buffer,
+            RADEON_GEM_DOMAIN_GTT, 0)) {
+            r300->context.flush(&r300->context, 0, NULL);
             goto validate;
         }
     }
+
     if (!r300->winsys->validate(r300->winsys)) {
-        pipe->flush(pipe, 0, NULL);
+        r300->context.flush(&r300->context, 0, NULL);
         if (invalid) {
             /* Well, hell. */
             debug_printf("r300: Stuck in validation loop, gonna quit now.");
             exit(1);
         }
-        invalid = TRUE;
+        invalid = true;
         goto validate;
     }
 
-    r300_emit_dirty_state(r300);
+    return invalid;
+}
 
-    packet_size = (aos_count >> 1) * 3 + (aos_count & 1) * 2;
-
-    BEGIN_CS(3 + packet_size + (aos_count * 2));
-    OUT_CS_PKT3(R300_PACKET3_3D_LOAD_VBPNTR, packet_size);
-    OUT_CS(aos_count);
-    for (i = 0; i < aos_count - 1; i += 2) {
-        OUT_CS(aos[i].stride |
-            (aos[i].stride << 8) |
-            (aos[i + 1].stride << 16) |
-            (aos[i + 1].stride << 24));
-        OUT_CS(aos[i].buffer_offset + start * 4 * aos[i].stride);
-        OUT_CS(aos[i + 1].buffer_offset + start * 4 * aos[i + 1].stride);
-    }
-    if (aos_count & 1) {
-        OUT_CS(aos[i].stride | (aos[i].stride << 8));
-        OUT_CS(aos[i].buffer_offset + start * 4 * aos[i].stride);
-    }
-    for (i = 0; i < aos_count; i++) {
-        OUT_CS_RELOC(aos[i].buffer, 0, RADEON_GEM_DOMAIN_GTT, 0, 0);
-    }
-    END_CS;
+/* This is the fast-path drawing & emission for HW TCL. */
+boolean r300_draw_range_elements(struct pipe_context* pipe,
+                                 struct pipe_buffer* indexBuffer,
+                                 unsigned indexSize,
+                                 unsigned minIndex,
+                                 unsigned maxIndex,
+                                 unsigned mode,
+                                 unsigned start,
+                                 unsigned count)
+{
+    struct r300_context* r300 = r300_context(pipe);
 
-    if (indexBuffer) {
-        indices = (short*)pipe_buffer_map(pipe->screen, indexBuffer,
-                                          PIPE_BUFFER_USAGE_CPU_READ);
+    r300_update_derived_state(r300);
 
-        /* Set the starting point. */
-        indices += start;
+    setup_vertex_buffers(r300);
 
-        BEGIN_CS(2 + (count+1)/2);
-        OUT_CS_PKT3(R300_PACKET3_3D_DRAW_INDX_2, (count + 1)/2);
-        OUT_CS(R300_VAP_VF_CNTL__PRIM_WALK_INDICES | (count << 16) | prim);
-        for (i = 0; i < count - 1; i += 2) {
-            OUT_CS(indices[i + 1] << 16 | indices[i]);
-        }
-        if (count % 2) {
-            OUT_CS(indices[count - 1]);
-        }
-        END_CS;
-    } else {
-        BEGIN_CS(2);
-        OUT_CS_PKT3(R300_PACKET3_3D_DRAW_VBUF_2, 0);
-        OUT_CS(R300_VAP_VF_CNTL__PRIM_WALK_VERTEX_LIST | (count << 16) |
-               prim);
-        END_CS;
-    }
+    setup_vertex_attributes(r300);
+
+    setup_index_buffer(r300, indexBuffer, indexSize);
+
+    r300->hw_prim = r300_translate_primitive(mode);
+
+    r300_emit_dirty_state(r300);
+
+    r300_emit_aos(r300, 0);
+
+    r300_emit_draw_elements(r300, indexBuffer, indexSize, minIndex, maxIndex,
+                            start, count);
 
     return TRUE;
 }
@@ -178,7 +145,23 @@ boolean r300_draw_elements(struct pipe_context* pipe,
 boolean r300_draw_arrays(struct pipe_context* pipe, unsigned mode,
                          unsigned start, unsigned count)
 {
-    return pipe->draw_elements(pipe, NULL, 0, mode, start, count);
+    struct r300_context* r300 = r300_context(pipe);
+
+    r300_update_derived_state(r300);
+
+    setup_vertex_buffers(r300);
+
+    setup_vertex_attributes(r300);
+
+    r300->hw_prim = r300_translate_primitive(mode);
+
+    r300_emit_dirty_state(r300);
+
+    r300_emit_aos(r300, start);
+
+    r300_emit_draw_arrays(r300, count);
+
+    return TRUE;
 }
 
 /****************************************************************************
@@ -196,7 +179,9 @@ boolean r300_swtcl_draw_range_elements(struct pipe_context* pipe,
                                        unsigned start,
                                        unsigned count)
 {
+    assert(0);
     struct r300_context* r300 = r300_context(pipe);
+#if 0
     int i;
 
     if (!u_trim_pipe_prim(mode, &count)) {
@@ -236,7 +221,7 @@ boolean r300_swtcl_draw_range_elements(struct pipe_context* pipe,
         draw_set_mapped_element_buffer_range(r300->draw, 0, start,
                                              start + count - 1, NULL);
     }
-
+#endif
     return TRUE;
 }
 
index bed886fad0458e7b7f00e5813813b37a1d738e74..e0b85ab768bd5b857151dce6e21fa7b37899c4fb 100644 (file)
@@ -666,10 +666,9 @@ static void r300_set_vertex_buffers(struct pipe_context* pipe,
 {
     struct r300_context* r300 = r300_context(pipe);
 
-    memcpy(r300->vertex_buffers, buffers,
+    memcpy(r300->vertex_buffer, buffers,
         sizeof(struct pipe_vertex_buffer) * count);
-
-    r300->vertex_buffer_count = count;
+    r300->vbuf_count = count;
 
     if (r300->draw) {
         draw_flush(r300->draw);
@@ -683,10 +682,10 @@ static void r300_set_vertex_elements(struct pipe_context* pipe,
 {
     struct r300_context* r300 = r300_context(pipe);
 
-    memcpy(r300->vertex_elements, elements,
-        sizeof(struct pipe_vertex_element) * count);
-
-    r300->vertex_element_count = count;
+    memcpy(r300->vertex_element,
+           elements,
+           sizeof(struct pipe_vertex_element) * count);
+    r300->aos_count = count;
 
     if (r300->draw) {
         draw_flush(r300->draw);
index 7d000e9e2da97cd218d308d92a03f3389a28ff60..14d7bb094c54a1c13dfaf4a7a284c544ab14e232 100644 (file)
@@ -63,7 +63,7 @@ int r300_shader_key_compare(void* key1, void* key2) {
 
 /* Set up the vs_tab and routes. */
 static void r300_vs_tab_routes(struct r300_context* r300,
-                               struct r300_vertex_format* vformat)
+                               struct r300_vertex_info* vformat)
 {
     struct r300_screen* r300screen = r300_screen(r300->context.screen);
     struct vertex_info* vinfo = &vformat->vinfo;
@@ -219,7 +219,7 @@ static void r300_vs_tab_routes(struct r300_context* r300,
 
 /* Update the PSC tables. */
 static void r300_vertex_psc(struct r300_context* r300,
-                            struct r300_vertex_format* vformat)
+                            struct r300_vertex_info* vformat)
 {
     struct r300_screen* r300screen = r300_screen(r300->context.screen);
     struct vertex_info* vinfo = &vformat->vinfo;
@@ -282,7 +282,7 @@ static void r300_vertex_psc(struct r300_context* r300,
 
 /* Set up the mappings from GB to US, for RS block. */
 static void r300_update_fs_tab(struct r300_context* r300,
-                               struct r300_vertex_format* vformat)
+                               struct r300_vertex_info* vformat)
 {
     struct tgsi_shader_info* info = &r300->fs->info;
     int i, cols = 0, texs = 0, cols_emitted = 0;
@@ -455,13 +455,13 @@ static void r300_update_rs_block(struct r300_context* r300,
 /* Update the vertex format. */
 static void r300_update_derived_shader_state(struct r300_context* r300)
 {
-    struct r300_shader_key* key;
-    struct r300_vertex_format* vformat;
+    struct r300_vertex_info* vformat;
     struct r300_rs_block* rs_block;
-    struct r300_shader_derived_value* value;
     int i;
 
     /*
+    struct r300_shader_key* key;
+    struct r300_shader_derived_value* value;
     key = CALLOC_STRUCT(r300_shader_key);
     key->vs = r300->vs;
     key->fs = r300->fs;
@@ -486,7 +486,7 @@ static void r300_update_derived_shader_state(struct r300_context* r300)
     } */
 
     /* XXX This will be refactored ASAP. */
-    vformat = CALLOC_STRUCT(r300_vertex_format);
+    vformat = CALLOC_STRUCT(r300_vertex_info);
     rs_block = CALLOC_STRUCT(r300_rs_block);
 
     for (i = 0; i < 16; i++) {
diff --git a/src/gallium/drivers/r300/r300_vbo.c b/src/gallium/drivers/r300/r300_vbo.c
new file mode 100644 (file)
index 0000000..e032641
--- /dev/null
@@ -0,0 +1,226 @@
+/*
+ * Copyright 2009 Maciej Cencora <m.cencora@gmail.com>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * on the rights to use, copy, modify, merge, publish, distribute, sub
+ * license, and/or sell copies of the Software, and to permit persons to whom
+ * the Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHOR(S) AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM,
+ * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
+ * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
+ * USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+#include "r300_vbo.h"
+
+#include "pipe/p_format.h"
+
+#include "r300_cs.h"
+#include "r300_context.h"
+#include "r300_reg.h"
+#include "r300_winsys.h"
+
+static void translate_vertex_format(enum pipe_format format,
+                                    unsigned nr_comps,
+                                    unsigned component_size,
+                                    unsigned dst_loc,
+                                    uint32_t *hw_fmt1,
+                                    uint32_t *hw_fmt2)
+{
+    uint32_t fmt1 = 0;
+
+    switch (pf_type(format))
+    {
+        case PIPE_FORMAT_TYPE_FLOAT:
+            assert(component_size == 4);
+            fmt1 = R300_DATA_TYPE_FLOAT_1 + nr_comps - 1;
+            break;
+        case PIPE_FORMAT_TYPE_UNORM:
+        case PIPE_FORMAT_TYPE_SNORM:
+        case PIPE_FORMAT_TYPE_USCALED:
+        case PIPE_FORMAT_TYPE_SSCALED:
+            if (component_size == 1)
+            {
+                assert(nr_comps == 4);
+                fmt1 = R300_DATA_TYPE_BYTE;
+            }
+            else if (component_size == 2)
+            {
+                if (nr_comps == 2)
+                    fmt1 = R300_DATA_TYPE_SHORT_2;
+                else if (nr_comps == 4)
+                    fmt1 = R300_DATA_TYPE_SHORT_4;
+                else
+                    assert(0);
+            }
+            else
+            {
+                assert(0);
+            }
+
+            if (pf_type(format) == PIPE_FORMAT_TYPE_SNORM)
+            {
+                fmt1 |= R300_SIGNED;
+            }
+            else if (pf_type(format) == PIPE_FORMAT_TYPE_SSCALED)
+            {
+                fmt1 |= R300_SIGNED;
+                fmt1 |= R300_NORMALIZE;
+            }
+            else if (pf_type(format) == PIPE_FORMAT_TYPE_USCALED)
+            {
+                fmt1 |= R300_NORMALIZE;
+            }
+            break;
+        default:
+            assert(0);
+            break;
+    }
+
+    *hw_fmt1 = fmt1 | (dst_loc << R300_DST_VEC_LOC_SHIFT);
+    *hw_fmt2 = (pf_swizzle_x(format) << R300_SWIZZLE_SELECT_X_SHIFT) |
+               (pf_swizzle_y(format) << R300_SWIZZLE_SELECT_Y_SHIFT) |
+               (pf_swizzle_z(format) << R300_SWIZZLE_SELECT_Z_SHIFT) |
+               (pf_swizzle_w(format) << R300_SWIZZLE_SELECT_W_SHIFT) |
+               (0xf << R300_WRITE_ENA_SHIFT);
+}
+
+static INLINE void setup_vertex_attribute(struct r300_vertex_info *vinfo,
+                                          struct pipe_vertex_element *vert_elem,
+                                          unsigned attr_num)
+{
+    uint32_t hw_fmt1, hw_fmt2;
+    translate_vertex_format(vert_elem->src_format,
+                            vert_elem->nr_components,
+                            pf_size_x(vert_elem->src_format),
+                            attr_num,
+                            &hw_fmt1,
+                            &hw_fmt2);
+
+    if (attr_num % 2 == 0)
+    {
+        vinfo->vap_prog_stream_cntl[attr_num >> 1] = hw_fmt1;
+        vinfo->vap_prog_stream_cntl_ext[attr_num >> 1] = hw_fmt2;
+    }
+    else
+    {
+        vinfo->vap_prog_stream_cntl[attr_num >> 1] |= hw_fmt1 << 16;
+        vinfo->vap_prog_stream_cntl_ext[attr_num >> 1] |= hw_fmt2 << 16;
+    }
+}
+
+static void finish_vertex_attribs_setup(struct r300_vertex_info *vinfo,
+                                        unsigned attribs_num)
+{
+    uint32_t last_vec_bit = (attribs_num % 2 == 0) ? (R300_LAST_VEC << 16) : R300_LAST_VEC;
+
+    assert(attribs_num > 0 && attribs_num <= 16);
+    vinfo->vap_prog_stream_cntl[(attribs_num - 1) >> 1] |= last_vec_bit;
+}
+
+void setup_vertex_attributes(struct r300_context *r300)
+{
+    for (int i=0; i<r300->aos_count; i++)
+    {
+        struct pipe_vertex_element *vert_elem = &r300->vertex_element[i];
+
+        setup_vertex_attribute(r300->vertex_info, vert_elem, i);
+    }
+
+    finish_vertex_attribs_setup(r300->vertex_info, r300->aos_count);
+}
+
+static void setup_vertex_array(struct r300_context *r300, struct pipe_vertex_element *element)
+{
+}
+
+static void finish_vertex_arrays_setup(struct r300_context *r300)
+{
+}
+
+static bool format_is_supported(enum pipe_format format, int nr_components)
+{
+    if (pf_layout(format) != PIPE_FORMAT_LAYOUT_RGBAZS)
+        return false;
+
+    if ((pf_size_x(format) != pf_size_y(format)) ||
+        (pf_size_x(format) != pf_size_z(format)) ||
+        (pf_size_x(format) != pf_size_w(format)))
+        return false;
+
+    /* Following should be supported as long as stride is 4 bytes aligned */
+    if (pf_size_x(format) != 1 && nr_components != 4)
+        return false;
+
+    if (pf_size_x(format) != 2 && !(nr_components == 2 || nr_components == 4))
+        return false;
+
+    if (pf_size_x(format) == 3 || pf_size_x(format) > 4)
+        return false;
+
+    return true;
+}
+
+static INLINE int get_buffer_offset(struct r300_context *r300,
+                                    unsigned int buf_nr,
+                                    unsigned int elem_offset)
+{
+    return r300->vertex_buffer[buf_nr].buffer_offset + elem_offset;
+}
+
+/**
+ */
+static void setup_vertex_buffers(struct r300_context *r300)
+{
+    for (int i=0; i<r300->aos_count; i++)
+    {
+        struct pipe_vertex_element *vert_elem = &r300->vertex_element[i];
+        if (!format_is_supported(vert_elem->src_format, vert_elem->nr_components))
+        {
+            assert(0);
+            /* use translate module to convert the data */
+            /*
+            struct pipe_buffer *buf;
+            const unsigned int max_index = r300->vertex_buffers[vert_elem->vertex_buffer_index].max_index;
+            buf = pipe_buffer_create(r300->context.screen, 4, usage, vert_elem->nr_components * max_index * sizeof(float));
+            */
+        }
+
+        if (get_buffer_offset(r300, vert_elem->vertex_buffer_index, vert_elem->src_offset) % 4 != 0)
+        {
+            /* need to align buffer */
+            assert(0);
+        }
+        setup_vertex_array(r300, vert_elem);
+    }
+
+    finish_vertex_arrays_setup(r300);
+}
+
+void setup_index_buffer(struct r300_context *r300,
+                        struct pipe_buffer* indexBuffer,
+                        unsigned indexSize)
+{
+    assert(indexSize = 2);
+
+    if (!r300->winsys->add_buffer(r300->winsys, indexBuffer, RADEON_GEM_DOMAIN_GTT, 0))
+    {
+        assert(0);
+    }
+
+    if (!r300->winsys->validate(r300->winsys))
+    {
+        assert(0);
+    }
+}
+
diff --git a/src/gallium/drivers/r300/r300_vbo.h b/src/gallium/drivers/r300/r300_vbo.h
new file mode 100644 (file)
index 0000000..7afa758
--- /dev/null
@@ -0,0 +1,36 @@
+/*
+ * Copyright 2009 Maciej Cencora <m.cencora@gmail.com>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * on the rights to use, copy, modify, merge, publish, distribute, sub
+ * license, and/or sell copies of the Software, and to permit persons to whom
+ * the Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHOR(S) AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM,
+ * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
+ * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
+ * USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+#ifndef R300_VBO_H
+#define R300_VBO_H
+
+struct r300_context;
+struct pipe_buffer;
+
+void setup_vertex_attributes(struct r300_context *r300);
+
+void setup_index_buffer(struct r300_context *r300,
+                        struct pipe_buffer* indexBuffer,
+                        unsigned indexSize);
+
+#endif