summaryrefslogtreecommitdiff
path: root/src/mesa/drivers/dri/r300/radeon_vtxfmt_a.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/mesa/drivers/dri/r300/radeon_vtxfmt_a.c')
-rw-r--r--src/mesa/drivers/dri/r300/radeon_vtxfmt_a.c610
1 files changed, 610 insertions, 0 deletions
diff --git a/src/mesa/drivers/dri/r300/radeon_vtxfmt_a.c b/src/mesa/drivers/dri/r300/radeon_vtxfmt_a.c
new file mode 100644
index 0000000000..d1f90abfb2
--- /dev/null
+++ b/src/mesa/drivers/dri/r300/radeon_vtxfmt_a.c
@@ -0,0 +1,610 @@
+#include "context.h"
+#include "r300_context.h"
+#include "r300_cmdbuf.h"
+#include "radeon_mm.h"
+
+#ifdef RADEON_VTXFMT_A
+
+#define CONV(a, b) rmesa->state.VB.AttribPtr[(a)].size = ctx->Array.b.Size, \
+ rmesa->state.VB.AttribPtr[(a)].data = ctx->Array.b.BufferObj->Name ? \
+ ADD_POINTERS(ctx->Array.b.Ptr, ctx->Array.b.BufferObj->Data) : ctx->Array.b.Ptr, \
+ rmesa->state.VB.AttribPtr[(a)].stride = ctx->Array.b.StrideB, \
+ rmesa->state.VB.AttribPtr[(a)].type = ctx->Array.b.Type
+
+static int setup_arrays(r300ContextPtr rmesa, GLint start)
+{
+ int i;
+ struct dt def = { 4, GL_FLOAT, 0, NULL };
+ GLcontext *ctx;
+ GLuint enabled = 0;
+
+ ctx = rmesa->radeon.glCtx;
+
+ memset(rmesa->state.VB.AttribPtr, 0, VERT_ATTRIB_MAX*sizeof(struct dt));
+
+ CONV(VERT_ATTRIB_POS, Vertex);
+ if (ctx->Array.Vertex.Enabled)
+ enabled |= 1 << VERT_ATTRIB_POS;
+
+ CONV(VERT_ATTRIB_NORMAL, Normal);
+ if (ctx->Array.Normal.Enabled)
+ enabled |= 1 << VERT_ATTRIB_NORMAL;
+
+ CONV(VERT_ATTRIB_COLOR0, Color);
+ if (ctx->Array.Color.Enabled)
+ enabled |= 1 << VERT_ATTRIB_COLOR0;
+
+ CONV(VERT_ATTRIB_COLOR1, SecondaryColor);
+ if (ctx->Array.SecondaryColor.Enabled)
+ enabled |= 1 << VERT_ATTRIB_COLOR1;
+
+ CONV(VERT_ATTRIB_FOG, FogCoord);
+ if (ctx->Array.FogCoord.Enabled)
+ enabled |= 1 << VERT_ATTRIB_FOG;
+
+ for (i=0; i < MAX_TEXTURE_COORD_UNITS; i++) {
+ CONV(VERT_ATTRIB_TEX0 + i, TexCoord[i]);
+
+ if(ctx->Array.TexCoord[i].Enabled) {
+ enabled |= 1 << (VERT_ATTRIB_TEX0+i);
+ }
+
+ }
+
+ for (i=0; i < VERT_ATTRIB_MAX; i++) {
+ if (enabled & (1 << i)) {
+ rmesa->state.VB.AttribPtr[i].data += rmesa->state.VB.AttribPtr[i].stride * start;
+ } else {
+ def.data = ctx->Current.Attrib[i];
+ memcpy(&rmesa->state.VB.AttribPtr[i], &def, sizeof(struct dt));
+ }
+
+ /*if(rmesa->state.VB.AttribPtr[i].data == ctx->Current.Attrib[i])
+ fprintf(stderr, "%d is default coord\n", i);*/
+ }
+
+ for(i=0; i < VERT_ATTRIB_MAX; i++){
+ if(rmesa->state.VB.AttribPtr[i].type != GL_UNSIGNED_BYTE &&
+ rmesa->state.VB.AttribPtr[i].type != GL_FLOAT){
+ WARN_ONCE("Unsupported format %d at index %d\n", rmesa->state.VB.AttribPtr[i].type, i);
+ return -1;
+ }
+ if(rmesa->state.VB.AttribPtr[i].type == GL_UNSIGNED_BYTE &&
+ rmesa->state.VB.AttribPtr[i].size != 4){
+ WARN_ONCE("Unsupported component count for ub colors\n");
+ return -1;
+ }
+
+ /*fprintf(stderr, "%d: ", i);
+
+ switch(rmesa->state.VB.AttribPtr[i].type){
+ case GL_BYTE: fprintf(stderr, "byte "); break;
+ case GL_UNSIGNED_BYTE: fprintf(stderr, "u byte "); break;
+ case GL_SHORT: fprintf(stderr, "short "); break;
+ case GL_UNSIGNED_SHORT: fprintf(stderr, "u short "); break;
+ case GL_INT: fprintf(stderr, "int "); break;
+ case GL_UNSIGNED_INT: fprintf(stderr, "u int "); break;
+ case GL_FLOAT: fprintf(stderr, "float "); break;
+ case GL_2_BYTES: fprintf(stderr, "2 bytes "); break;
+ case GL_3_BYTES: fprintf(stderr, "3 bytes "); break;
+ case GL_4_BYTES: fprintf(stderr, "4 bytes "); break;
+ case GL_DOUBLE: fprintf(stderr, "double "); break;
+ default: fprintf(stderr, "unknown "); break;
+ }
+
+ fprintf(stderr, "Size %d ", rmesa->state.VB.AttribPtr[i].size);
+ fprintf(stderr, "Ptr %p ", rmesa->state.VB.AttribPtr[i].data);
+ fprintf(stderr, "Stride %d ", rmesa->state.VB.AttribPtr[i].stride);
+ fprintf(stderr, "\n");*/
+ }
+ return 0;
+}
+
+void radeonDrawElements( GLenum mode, GLsizei count, GLenum type, const GLvoid *indices )
+{
+ GET_CURRENT_CONTEXT(ctx);
+ r300ContextPtr rmesa = R300_CONTEXT(ctx);
+ int elt_size;
+ int i;
+ unsigned int min = ~0, max = 0;
+ struct tnl_prim prim;
+ static void *ptr = NULL;
+ static struct r300_dma_region rvb;
+
+ if (ctx->Array.ElementArrayBufferObj->Name) {
+ /* use indices in the buffer object */
+ if (!ctx->Array.ElementArrayBufferObj->Data) {
+ _mesa_warning(ctx, "DrawRangeElements with empty vertex elements buffer!");
+ return;
+ }
+ /* actual address is the sum of pointers */
+ indices = (const GLvoid *)
+ ADD_POINTERS(ctx->Array.ElementArrayBufferObj->Data, (const GLubyte *) indices);
+ }
+
+ if (!_mesa_validate_DrawElements( ctx, mode, count, type, indices ))
+ return;
+
+ FLUSH_CURRENT( ctx, 0 );
+ /*
+ fprintf(stderr, "dt at %s:\n", __FUNCTION__);
+ for(i=0; i < VERT_ATTRIB_MAX; i++){
+ fprintf(stderr, "dt %d:", i);
+ dump_dt(&rmesa->state.VB.AttribPtr[i], rmesa->state.VB.Count);
+ }*/
+ r300ReleaseDmaRegion(rmesa, &rvb, __FUNCTION__);
+
+ switch (type) {
+ case GL_UNSIGNED_BYTE:
+ elt_size = 2;
+
+ r300AllocDmaRegion(rmesa, &rvb, count * elt_size, elt_size);
+ rvb.aos_offset = GET_START(&rvb);
+ ptr = rvb.address + rvb.start;
+
+ for (i=0; i < count; i++) {
+ if(((unsigned char *)indices)[i] < min)
+ min = ((unsigned char *)indices)[i];
+ if(((unsigned char *)indices)[i] > max)
+ max = ((unsigned char *)indices)[i];
+ }
+
+ for (i=0; i < count; i++)
+ ((unsigned short int *)ptr)[i] = ((unsigned char *)indices)[i] - min;
+ break;
+
+ case GL_UNSIGNED_SHORT:
+ elt_size = 2;
+
+ r300AllocDmaRegion(rmesa, &rvb, count * elt_size, elt_size);
+ rvb.aos_offset = GET_START(&rvb);
+ ptr = rvb.address + rvb.start;
+
+ for (i=0; i < count; i++) {
+ if(((unsigned short int *)indices)[i] < min)
+ min = ((unsigned short int *)indices)[i];
+ if(((unsigned short int *)indices)[i] > max)
+ max = ((unsigned short int *)indices)[i];
+ }
+
+ for (i=0; i < count; i++)
+ ((unsigned short int *)ptr)[i] = ((unsigned short int *)indices)[i] - min;
+ break;
+
+ case GL_UNSIGNED_INT:
+ elt_size = 4;
+
+ r300AllocDmaRegion(rmesa, &rvb, count * elt_size, elt_size);
+ rvb.aos_offset = GET_START(&rvb);
+ ptr = rvb.address + rvb.start;
+
+ for (i=0; i < count; i++) {
+ if(((unsigned int *)indices)[i] < min)
+ min = ((unsigned int *)indices)[i];
+ if(((unsigned int *)indices)[i] > max)
+ max = ((unsigned int *)indices)[i];
+ }
+
+ for (i=0; i < count; i++)
+ ((unsigned int *)ptr)[i] = ((unsigned int *)indices)[i] - min;
+ break;
+
+ default:
+ fprintf(stderr, "Unknown elt type!\n");
+ return;
+
+
+ }
+
+ if (ctx->NewState)
+ _mesa_update_state( ctx );
+
+ r300UpdateShaderStates(rmesa);
+
+ if (rmesa->state.VB.LockCount) {
+ if (rmesa->state.VB.lock_uptodate == GL_FALSE) {
+ if (setup_arrays(rmesa, rmesa->state.VB.LockFirst))
+ return;
+
+ rmesa->state.VB.Count = rmesa->state.VB.LockCount;
+
+ r300ReleaseArrays(ctx);
+ r300EmitArraysVtx(ctx, GL_FALSE);
+
+ rmesa->state.VB.lock_uptodate = GL_TRUE;
+ }
+
+ if (min < rmesa->state.VB.LockFirst) {
+ WARN_ONCE("Out of range min %d vs %d!\n", min, rmesa->state.VB.LockFirst);
+ return;
+ }
+
+ if (max >= rmesa->state.VB.LockFirst + rmesa->state.VB.LockCount) {
+ WARN_ONCE("Out of range max %d vs %d!\n", max, rmesa->state.VB.LockFirst +
+ rmesa->state.VB.LockCount);
+ return;
+ }
+ } else {
+ if (setup_arrays(rmesa, min))
+ return;
+ rmesa->state.VB.Count = max - min + 1;
+ }
+
+ rmesa->state.VB.Primitive = &prim;
+ rmesa->state.VB.PrimitiveCount = 1;
+
+ prim.mode = mode | PRIM_BEGIN | PRIM_END;
+ if (rmesa->state.VB.LockCount)
+ prim.start = min - rmesa->state.VB.LockFirst;
+ else
+ prim.start = 0;
+ prim.count = count;
+
+ rmesa->state.VB.Elts = ptr;
+ rmesa->state.VB.elt_size = elt_size;
+
+ r300_run_vb_render_vtxfmt_a(ctx, NULL);
+
+ if(rvb.buf)
+ radeon_mm_use(rmesa, rvb.buf->id);
+}
+
+void radeonDrawRangeElements(GLenum mode, GLuint start, GLuint end, GLsizei count, GLenum type, const GLvoid *indices)
+{
+ GET_CURRENT_CONTEXT(ctx);
+ r300ContextPtr rmesa = R300_CONTEXT(ctx);
+ struct tnl_prim prim;
+ int elt_size;
+ int i;
+ static void *ptr = NULL;
+ static struct r300_dma_region rvb;
+
+ if (ctx->Array.ElementArrayBufferObj->Name) {
+ /* use indices in the buffer object */
+ if (!ctx->Array.ElementArrayBufferObj->Data) {
+ _mesa_warning(ctx, "DrawRangeElements with empty vertex elements buffer!");
+ return;
+ }
+ /* actual address is the sum of pointers */
+ indices = (const GLvoid *)
+ ADD_POINTERS(ctx->Array.ElementArrayBufferObj->Data, (const GLubyte *) indices);
+ }
+
+ if (!_mesa_validate_DrawRangeElements( ctx, mode, start, end, count, type, indices ))
+ return;
+
+ FLUSH_CURRENT( ctx, 0 );
+#ifdef OPTIMIZE_ELTS
+ start = 0;
+#endif
+ r300ReleaseDmaRegion(rmesa, &rvb, __FUNCTION__);
+
+ switch(type){
+ case GL_UNSIGNED_BYTE:
+ elt_size = 2;
+
+ r300AllocDmaRegion(rmesa, &rvb, count * elt_size, elt_size);
+ rvb.aos_offset = GET_START(&rvb);
+ ptr = rvb.address + rvb.start;
+
+ for(i=0; i < count; i++)
+ ((unsigned short int *)ptr)[i] = ((unsigned char *)indices)[i] - start;
+ break;
+
+ case GL_UNSIGNED_SHORT:
+ elt_size = 2;
+
+#ifdef OPTIMIZE_ELTS
+ if (start == 0 && ctx->Array.ElementArrayBufferObj->Name){
+ ptr = indices;
+ break;
+ }
+#endif
+ r300AllocDmaRegion(rmesa, &rvb, count * elt_size, elt_size);
+ rvb.aos_offset = GET_START(&rvb);
+ ptr = rvb.address + rvb.start;
+
+ for(i=0; i < count; i++)
+ ((unsigned short int *)ptr)[i] = ((unsigned short int *)indices)[i] - start;
+ break;
+
+ case GL_UNSIGNED_INT:
+ elt_size = 4;
+
+ r300AllocDmaRegion(rmesa, &rvb, count * elt_size, elt_size);
+ rvb.aos_offset = GET_START(&rvb);
+ ptr = rvb.address + rvb.start;
+
+ for(i=0; i < count; i++)
+ ((unsigned int *)ptr)[i] = ((unsigned int *)indices)[i] - start;
+ break;
+
+ default:
+ fprintf(stderr, "Unknown elt type!\n");
+ return;
+
+ }
+
+ if(setup_arrays(rmesa, start))
+ return;
+
+ if (ctx->NewState)
+ _mesa_update_state( ctx );
+
+ r300UpdateShaderStates(rmesa);
+
+ rmesa->state.VB.Count = (end - start) + 1;
+ rmesa->state.VB.Primitive = &prim;
+ rmesa->state.VB.PrimitiveCount = 1;
+
+ prim.mode = mode | PRIM_BEGIN | PRIM_END;
+ prim.start = 0;
+ prim.count = count;
+
+ rmesa->state.VB.Elts = ptr;
+ rmesa->state.VB.elt_size = elt_size;
+ rmesa->state.VB.elt_min = start;
+ rmesa->state.VB.elt_max = end;
+
+ r300_run_vb_render_vtxfmt_a(ctx, NULL);
+
+ if(rvb.buf)
+ radeon_mm_use(rmesa, rvb.buf->id);
+}
+
+void radeonDrawArrays( GLenum mode, GLint start, GLsizei count )
+{
+ GET_CURRENT_CONTEXT(ctx);
+ r300ContextPtr rmesa = R300_CONTEXT(ctx);
+ struct tnl_prim prim;
+
+ if (!_mesa_validate_DrawArrays( ctx, mode, start, count ))
+ return;
+
+ FLUSH_CURRENT( ctx, 0 );
+
+ if (ctx->NewState)
+ _mesa_update_state( ctx );
+
+ if (rmesa->state.VB.LockCount == 0)
+ if (setup_arrays(rmesa, start))
+ return;
+
+ r300UpdateShaderStates(rmesa);
+
+ if (rmesa->state.VB.LockCount) {
+ start -= rmesa->state.VB.LockFirst;
+ if (start < 0) { /* Generate error */
+ WARN_ONCE("Out of range!\n");
+ return;
+ }
+ }
+
+ if (rmesa->state.VB.LockCount == 0)
+ rmesa->state.VB.Count = count;
+ rmesa->state.VB.Primitive = &prim;
+ rmesa->state.VB.PrimitiveCount = 1;
+
+ prim.mode = mode | PRIM_BEGIN | PRIM_END;
+ if (ctx->Array.LockCount == 0)
+ prim.start = 0;
+ else
+ prim.start = start;
+
+ prim.count = count;
+
+ rmesa->state.VB.Elts = NULL;
+ rmesa->state.VB.elt_size = 0;
+ rmesa->state.VB.elt_min = 0;
+ rmesa->state.VB.elt_max = 0;
+
+ r300_run_vb_render_vtxfmt_a(ctx, NULL);
+}
+
+void radeon_init_vtxfmt_a(r300ContextPtr rmesa)
+{
+ GLcontext *ctx;
+ GLvertexformat *vfmt;
+
+ ctx = rmesa->radeon.glCtx;
+ vfmt = ctx->TnlModule.Current;
+
+ vfmt->DrawElements = radeonDrawElements;
+ vfmt->DrawArrays = radeonDrawArrays;
+ vfmt->DrawRangeElements = radeonDrawRangeElements;
+
+}
+#endif
+
+#ifdef HW_VBOS
+
+void radeonLockArraysEXT(GLcontext *ctx, GLint first, GLsizei count)
+{
+ r300ContextPtr rmesa = R300_CONTEXT(ctx);
+ int i;
+
+ /* Disabled as array changes arent properly handled yet. */
+ first = 0; count = 0;
+
+ if (first < 0 || count <= 0) {
+ rmesa->state.VB.LockFirst = 0;
+ rmesa->state.VB.LockCount = 0;
+ return ;
+ }
+
+ rmesa->state.VB.LockFirst = first;
+ rmesa->state.VB.LockCount = count;
+ rmesa->state.VB.lock_uptodate = GL_FALSE;
+}
+
+void radeonUnlockArraysEXT(GLcontext *ctx)
+{
+ r300ContextPtr rmesa = R300_CONTEXT(ctx);
+
+ rmesa->state.VB.LockFirst = 0;
+ rmesa->state.VB.LockCount = 0;
+}
+
+struct gl_buffer_object *
+r300NewBufferObject(GLcontext *ctx, GLuint name, GLenum target )
+{
+ struct r300_buffer_object *obj;
+
+ (void) ctx;
+
+ obj = MALLOC_STRUCT(r300_buffer_object);
+ _mesa_initialize_buffer_object(&obj->mesa_obj, name, target);
+ return &obj->mesa_obj;
+}
+
+void r300BufferData(GLcontext *ctx, GLenum target, GLsizeiptrARB size,
+ const GLvoid *data, GLenum usage, struct gl_buffer_object *obj)
+{
+ r300ContextPtr rmesa = R300_CONTEXT(ctx);
+ struct r300_buffer_object *r300_obj = (struct r300_buffer_object *)obj;
+ drm_radeon_mem_alloc_t alloc;
+ int offset, ret;
+
+ /* Free previous buffer */
+ if (obj->OnCard) {
+ radeon_mm_free(rmesa, r300_obj->id);
+ obj->OnCard = GL_FALSE;
+ } else {
+ if (obj->Data)
+ free(obj->Data);
+ }
+#ifdef OPTIMIZE_ELTS
+ if (0) {
+#else
+ if (target == GL_ELEMENT_ARRAY_BUFFER_ARB) {
+#endif
+ obj->Data = malloc(size);
+
+ if (data)
+ memcpy(obj->Data, data, size);
+
+ obj->OnCard = GL_FALSE;
+ } else {
+ r300_obj->id = radeon_mm_alloc(rmesa, 4, size);
+ obj->Data = radeon_mm_map(rmesa, r300_obj->id, RADEON_MM_W);
+
+ if (data)
+ memcpy(obj->Data, data, size);
+
+ radeon_mm_unmap(rmesa, r300_obj->id);
+ obj->OnCard = GL_TRUE;
+ }
+
+ obj->Size = size;
+ obj->Usage = usage;
+}
+
+void r300BufferSubData(GLcontext *ctx, GLenum target, GLintptrARB offset,
+ GLsizeiptrARB size, const GLvoid * data, struct gl_buffer_object * bufObj)
+{
+ r300ContextPtr rmesa = R300_CONTEXT(ctx);
+ struct r300_buffer_object *r300_obj = (struct r300_buffer_object *)bufObj;
+ (void) ctx; (void) target;
+ void *ptr;
+
+ if (bufObj->Data && ((GLuint) (size + offset) <= bufObj->Size)) {
+ if (bufObj->OnCard){
+ ptr = radeon_mm_map(rmesa, r300_obj->id, RADEON_MM_W);
+
+ _mesa_memcpy( (GLubyte *) ptr + offset, data, size );
+
+ radeon_mm_unmap(rmesa, r300_obj->id);
+ } else {
+ _mesa_memcpy( (GLubyte *) bufObj->Data + offset, data, size );
+ }
+ }
+}
+
+void *r300MapBuffer(GLcontext *ctx, GLenum target, GLenum access,
+ struct gl_buffer_object *bufObj)
+{
+ r300ContextPtr rmesa = R300_CONTEXT(ctx);
+ struct r300_buffer_object *r300_obj = (struct r300_buffer_object *)bufObj;
+
+ (void) ctx;
+ (void) target;
+ (void) access;
+ //ASSERT(!bufObj->OnCard);
+ /* Just return a direct pointer to the data */
+ if (bufObj->Pointer) {
+ /* already mapped! */
+ return NULL;
+ }
+
+ if (!bufObj->OnCard) {
+ bufObj->Pointer = bufObj->Data;
+ return bufObj->Pointer;
+ }
+
+ switch (access) {
+ case GL_READ_ONLY:
+ bufObj->Pointer = radeon_mm_map(rmesa, r300_obj->id, RADEON_MM_R);
+ break;
+
+ case GL_WRITE_ONLY:
+ bufObj->Pointer = radeon_mm_map(rmesa, r300_obj->id, RADEON_MM_W);
+ break;
+
+ case GL_READ_WRITE:
+ bufObj->Pointer = radeon_mm_map(rmesa, r300_obj->id, RADEON_MM_RW);
+ break;
+
+ default:
+ WARN_ONCE("Unknown access type\n");
+ bufObj->Pointer = NULL;
+ break;
+ }
+
+ return bufObj->Pointer;
+}
+
+GLboolean r300UnmapBuffer(GLcontext *ctx, GLenum target, struct gl_buffer_object *bufObj)
+{
+ r300ContextPtr rmesa = R300_CONTEXT(ctx);
+ struct r300_buffer_object *r300_obj = (struct r300_buffer_object *)bufObj;
+
+ (void) ctx;
+ (void) target;
+ //ASSERT(!bufObj->OnCard);
+ /* XXX we might assert here that bufObj->Pointer is non-null */
+ if (!bufObj->OnCard) {
+ bufObj->Pointer = NULL;
+ return GL_TRUE;
+ }
+ radeon_mm_unmap(rmesa, r300_obj->id);
+
+ bufObj->Pointer = NULL;
+ return GL_TRUE;
+}
+
+void r300DeleteBuffer(GLcontext *ctx, struct gl_buffer_object *obj)
+{
+ r300ContextPtr rmesa = R300_CONTEXT(ctx);
+ struct r300_buffer_object *r300_obj = (struct r300_buffer_object *)obj;
+
+ if (obj->OnCard) {
+ radeon_mm_free(rmesa, r300_obj->id);
+ obj->Data = NULL;
+ }
+ _mesa_delete_buffer_object(ctx, obj);
+}
+
+void r300_init_vbo_funcs(struct dd_function_table *functions)
+{
+ functions->NewBufferObject = r300NewBufferObject;
+ functions->BufferData = r300BufferData;
+ functions->BufferSubData = r300BufferSubData;
+ functions->MapBuffer = r300MapBuffer;
+ functions->UnmapBuffer = r300UnmapBuffer;
+ functions->DeleteBuffer = r300DeleteBuffer;
+
+ functions->LockArraysEXT = radeonLockArraysEXT;
+ functions->UnlockArraysEXT = radeonUnlockArraysEXT;
+}
+
+#endif