summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMaciej Cencora <[email protected]>2009-10-25 13:53:25 +0100
committerCorbin Simpson <[email protected]>2009-11-07 11:53:13 -0800
commit3445f476977ae403cef9ca15661fa0f96ff50eca (patch)
treea57c0972c23b3471920300f42f33a2998551a799
parentd8592d1724d8c8fd0b36eb21f4007b52f809e062 (diff)
r300g: VBOs WIP
-rw-r--r--src/gallium/drivers/r300/Makefile1
-rw-r--r--src/gallium/drivers/r300/r300_context.c14
-rw-r--r--src/gallium/drivers/r300/r300_context.h27
-rw-r--r--src/gallium/drivers/r300/r300_emit.c108
-rw-r--r--src/gallium/drivers/r300/r300_emit.h12
-rw-r--r--src/gallium/drivers/r300/r300_render.c135
-rw-r--r--src/gallium/drivers/r300/r300_state.c13
-rw-r--r--src/gallium/drivers/r300/r300_state_derived.c14
-rw-r--r--src/gallium/drivers/r300/r300_vbo.c226
-rw-r--r--src/gallium/drivers/r300/r300_vbo.h36
10 files changed, 477 insertions, 109 deletions
diff --git a/src/gallium/drivers/r300/Makefile b/src/gallium/drivers/r300/Makefile
index f73d80de882..d13bb7a36b1 100644
--- a/src/gallium/drivers/r300/Makefile
+++ b/src/gallium/drivers/r300/Makefile
@@ -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
diff --git a/src/gallium/drivers/r300/r300_context.c b/src/gallium/drivers/r300/r300_context.c
index f974147ea43..b520e5929e2 100644
--- a/src/gallium/drivers/r300/r300_context.c
+++ b/src/gallium/drivers/r300/r300_context.c
@@ -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;
diff --git a/src/gallium/drivers/r300/r300_context.h b/src/gallium/drivers/r300/r300_context.h
index 850e5a41c91..a6748852d83 100644
--- a/src/gallium/drivers/r300/r300_context.h
+++ b/src/gallium/drivers/r300/r300_context.h
@@ -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. */
diff --git a/src/gallium/drivers/r300/r300_emit.c b/src/gallium/drivers/r300/r300_emit.c
index 69ce5966e80..92e6ec606ca 100644
--- a/src/gallium/drivers/r300/r300_emit.c
+++ b/src/gallium/drivers/r300/r300_emit.c
@@ -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++;
}
diff --git a/src/gallium/drivers/r300/r300_emit.h b/src/gallium/drivers/r300/r300_emit.h
index 6befca72ced..b4fdfecde01 100644
--- a/src/gallium/drivers/r300/r300_emit.h
+++ b/src/gallium/drivers/r300/r300_emit.h
@@ -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);
diff --git a/src/gallium/drivers/r300/r300_render.c b/src/gallium/drivers/r300/r300_render.c
index 634c803f2a8..86aaf841dd6 100644
--- a/src/gallium/drivers/r300/r300_render.c
+++ b/src/gallium/drivers/r300/r300_render.c
@@ -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;
}
diff --git a/src/gallium/drivers/r300/r300_state.c b/src/gallium/drivers/r300/r300_state.c
index bed886fad04..e0b85ab768b 100644
--- a/src/gallium/drivers/r300/r300_state.c
+++ b/src/gallium/drivers/r300/r300_state.c
@@ -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);
diff --git a/src/gallium/drivers/r300/r300_state_derived.c b/src/gallium/drivers/r300/r300_state_derived.c
index 7d000e9e2da..14d7bb094c5 100644
--- a/src/gallium/drivers/r300/r300_state_derived.c
+++ b/src/gallium/drivers/r300/r300_state_derived.c
@@ -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
index 00000000000..e0326412865
--- /dev/null
+++ b/src/gallium/drivers/r300/r300_vbo.c
@@ -0,0 +1,226 @@
+/*
+ * Copyright 2009 Maciej Cencora <[email protected]>
+ *
+ * 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
index 00000000000..7afa75899cf
--- /dev/null
+++ b/src/gallium/drivers/r300/r300_vbo.h
@@ -0,0 +1,36 @@
+/*
+ * Copyright 2009 Maciej Cencora <[email protected]>
+ *
+ * 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