2 * Copyright (C) 2005 Aapo Tahkola.
6 * Permission is hereby granted, free of charge, to any person obtaining
7 * a copy of this software and associated documentation files (the
8 * "Software"), to deal in the Software without restriction, including
9 * without limitation the rights to use, copy, modify, merge, publish,
10 * distribute, sublicense, and/or sell copies of the Software, and to
11 * permit persons to whom the Software is furnished to do so, subject to
12 * the following conditions:
14 * The above copyright notice and this permission notice (including the
15 * next paragraph) shall be included in all copies or substantial
16 * portions of the Software.
18 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
19 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
20 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
21 * IN NO EVENT SHALL THE COPYRIGHT OWNER(S) AND/OR ITS SUPPLIERS BE
22 * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
23 * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
24 * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
30 * Aapo Tahkola <aet@rasterburn.org>
34 #include "r300_context.h"
35 #include "r300_cmdbuf.h"
36 #include "r300_ioctl.h"
37 #include "r300_maos.h"
38 #include "r300_state.h"
39 #include "radeon_mm.h"
43 #include "bufferobj.h"
45 #include "api_validate.h"
49 #include "vbo/vbo_context.h"
51 #define CONV_VB(a, b) rvb->AttribPtr[(a)].size = vb->b->size, \
52 rvb->AttribPtr[(a)].type = GL_FLOAT, \
53 rvb->AttribPtr[(a)].stride = vb->b->stride, \
54 rvb->AttribPtr[(a)].data = vb->b->data
56 void radeon_vb_to_rvb(r300ContextPtr rmesa
, struct radeon_vertex_buffer
*rvb
, struct vertex_buffer
*vb
)
60 ctx
= rmesa
->radeon
.glCtx
;
62 memset(rvb
, 0, sizeof(*rvb
));
67 rvb
->elt_max
= vb
->Count
;
69 rvb
->Count
= vb
->Count
;
72 CONV_VB(VERT_ATTRIB_POS
, ObjPtr
);
75 CONV_VB(VERT_ATTRIB_POS
, ClipPtr
);
78 CONV_VB(VERT_ATTRIB_NORMAL
, NormalPtr
);
79 CONV_VB(VERT_ATTRIB_COLOR0
, ColorPtr
[0]);
80 CONV_VB(VERT_ATTRIB_COLOR1
, SecondaryColorPtr
[0]);
81 CONV_VB(VERT_ATTRIB_FOG
, FogCoordPtr
);
83 for (i
=0; i
< ctx
->Const
.MaxTextureCoordUnits
; i
++)
84 CONV_VB(VERT_ATTRIB_TEX0
+ i
, TexCoordPtr
[i
]);
86 for (i
=0; i
< MAX_VERTEX_PROGRAM_ATTRIBS
; i
++)
87 CONV_VB(VERT_ATTRIB_GENERIC0
+ i
, AttribPtr
[VERT_ATTRIB_GENERIC0
+ i
]);
89 rvb
->Primitive
= vb
->Primitive
;
90 rvb
->PrimitiveCount
= vb
->PrimitiveCount
;
91 rvb
->LockFirst
= rvb
->LockCount
= 0;
92 rvb
->lock_uptodate
= GL_FALSE
;
95 #ifdef RADEON_VTXFMT_A
97 extern void _tnl_array_init( GLcontext
*ctx
);
101 if (ctx->Array.ArrayObj->b.Enabled) { \
102 rmesa->state.VB.AttribPtr[(a)].size = ctx->Array.ArrayObj->b.Size; \
103 rmesa->state.VB.AttribPtr[(a)].data = ctx->Array.ArrayObj->b.BufferObj->Name \
104 ? (void *)ADD_POINTERS(ctx->Array.ArrayObj->b.Ptr, ctx->Array.ArrayObj->b.BufferObj->Data) \
105 : (void *)ctx->Array.ArrayObj->b.Ptr; \
106 rmesa->state.VB.AttribPtr[(a)].stride = ctx->Array.ArrayObj->b.StrideB; \
107 rmesa->state.VB.AttribPtr[(a)].type = ctx->Array.ArrayObj->b.Type; \
108 enabled |= 1 << (a); \
112 static int setup_arrays(r300ContextPtr rmesa
, GLint start
)
115 struct dt def
= { 4, GL_FLOAT
, 0, NULL
};
119 ctx
= rmesa
->radeon
.glCtx
;
120 i
= r300Fallback(ctx
);
124 memset(rmesa
->state
.VB
.AttribPtr
, 0, VERT_ATTRIB_MAX
*sizeof(struct dt
));
126 CONV(VERT_ATTRIB_POS
, Vertex
);
127 CONV(VERT_ATTRIB_NORMAL
, Normal
);
128 CONV(VERT_ATTRIB_COLOR0
, Color
);
129 CONV(VERT_ATTRIB_COLOR1
, SecondaryColor
);
130 CONV(VERT_ATTRIB_FOG
, FogCoord
);
132 for (i
=0; i
< MAX_TEXTURE_COORD_UNITS
; i
++)
133 CONV(VERT_ATTRIB_TEX0
+ i
, TexCoord
[i
]);
135 if (ctx
->VertexProgram
._Enabled
)
136 for (i
=0; i
< VERT_ATTRIB_MAX
; i
++)
137 CONV(i
, VertexAttrib
[i
]);
139 for (i
=0; i
< VERT_ATTRIB_MAX
; i
++) {
140 rmesa
->state
.VB
.AttribPtr
[i
].data
+= rmesa
->state
.VB
.AttribPtr
[i
].stride
* start
;
143 for(i
=0; i
< VERT_ATTRIB_MAX
; i
++){
144 if(rmesa
->state
.VB
.AttribPtr
[i
].type
!= GL_UNSIGNED_BYTE
&&
145 #if MESA_LITTLE_ENDIAN
146 rmesa
->state
.VB
.AttribPtr
[i
].type
!= GL_SHORT
&&
148 rmesa
->state
.VB
.AttribPtr
[i
].type
!= GL_FLOAT
){
149 WARN_ONCE("Unsupported format %d at index %d\n", rmesa
->state
.VB
.AttribPtr
[i
].type
, i
);
150 return R300_FALLBACK_TCL
;
153 /*fprintf(stderr, "%d: ", i);
155 switch(rmesa->state.VB.AttribPtr[i].type){
156 case GL_BYTE: fprintf(stderr, "byte "); break;
157 case GL_UNSIGNED_BYTE: fprintf(stderr, "u byte "); break;
158 case GL_SHORT: fprintf(stderr, "short "); break;
159 case GL_UNSIGNED_SHORT: fprintf(stderr, "u short "); break;
160 case GL_INT: fprintf(stderr, "int "); break;
161 case GL_UNSIGNED_INT: fprintf(stderr, "u int "); break;
162 case GL_FLOAT: fprintf(stderr, "float "); break;
163 case GL_2_BYTES: fprintf(stderr, "2 bytes "); break;
164 case GL_3_BYTES: fprintf(stderr, "3 bytes "); break;
165 case GL_4_BYTES: fprintf(stderr, "4 bytes "); break;
166 case GL_DOUBLE: fprintf(stderr, "double "); break;
167 default: fprintf(stderr, "unknown "); break;
170 fprintf(stderr, "Size %d ", rmesa->state.VB.AttribPtr[i].size);
171 fprintf(stderr, "Ptr %p ", rmesa->state.VB.AttribPtr[i].data);
172 fprintf(stderr, "Stride %d ", rmesa->state.VB.AttribPtr[i].stride);
173 fprintf(stderr, "\n");*/
175 return R300_FALLBACK_NONE
;
178 void radeon_init_vtxfmt_a(r300ContextPtr rmesa
);
181 static void radeonDrawRangeElements(GLcontext
*ctx
,
187 const GLvoid
*c_indices
)
192 r300ContextPtr rmesa
= R300_CONTEXT(ctx
);
193 struct tnl_prim prim
;
197 struct r300_dma_region rvb
;
198 const GLvoid
*indices
= c_indices
;
202 if (mode
== GL_POINTS
||
205 mode
== GL_TRIANGLES
) {
208 i
= r300_get_num_verts(rmesa
, MIN2(count
, 65535), mode
);
210 radeonDrawRangeElements(mode
, min
, max
, i
, type
, indices
);
212 indices
+= i
* _mesa_sizeof_type(type
);
217 WARN_ONCE("Too many verts!\n");
221 if (ctx
->Array
.ElementArrayBufferObj
->Name
) {
222 /* use indices in the buffer object */
223 if (!ctx
->Array
.ElementArrayBufferObj
->Data
) {
224 _mesa_warning(ctx
, "DrawRangeElements with empty vertex elements buffer!");
227 /* actual address is the sum of pointers */
229 ADD_POINTERS(ctx
->Array
.ElementArrayBufferObj
->Data
, (const GLubyte
*) c_indices
);
232 FLUSH_CURRENT( ctx
, 0 );
237 memset(&rvb
, 0, sizeof(rvb
));
239 case GL_UNSIGNED_BYTE
:
240 #ifdef FORCE_32BITS_ELTS
245 r300AllocDmaRegion(rmesa
, &rvb
, count
* elt_size
, elt_size
);
246 rvb
.aos_offset
= GET_START(&rvb
);
247 ptr
= rvb
.address
+ rvb
.start
;
249 #ifdef FORCE_32BITS_ELTS
250 for(i
=0; i
< count
; i
++)
251 ((unsigned int *)ptr
)[i
] = ((unsigned char *)indices
)[i
] - min
;
253 for(i
=0; i
< count
; i
++)
254 ((unsigned short int *)ptr
)[i
] = ((unsigned char *)indices
)[i
] - min
;
258 case GL_UNSIGNED_SHORT
:
259 #ifdef FORCE_32BITS_ELTS
265 if (min
== 0 && ctx
->Array
.ElementArrayBufferObj
->Name
){
270 r300AllocDmaRegion(rmesa
, &rvb
, count
* elt_size
, elt_size
);
271 rvb
.aos_offset
= GET_START(&rvb
);
272 ptr
= rvb
.address
+ rvb
.start
;
274 #ifdef FORCE_32BITS_ELTS
275 for(i
=0; i
< count
; i
++)
276 ((unsigned int *)ptr
)[i
] = ((unsigned short int *)indices
)[i
] - min
;
278 for(i
=0; i
< count
; i
++)
279 ((unsigned short int *)ptr
)[i
] = ((unsigned short int *)indices
)[i
] - min
;
283 case GL_UNSIGNED_INT
:
284 #ifdef FORCE_32BITS_ELTS
287 if (max
- min
<= 65535)
292 r300AllocDmaRegion(rmesa
, &rvb
, count
* elt_size
, elt_size
);
293 rvb
.aos_offset
= GET_START(&rvb
);
294 ptr
= rvb
.address
+ rvb
.start
;
297 for (i
=0; i
< count
; i
++)
298 ((unsigned short int *)ptr
)[i
] = ((unsigned int *)indices
)[i
] - min
;
300 for (i
=0; i
< count
; i
++)
301 ((unsigned int *)ptr
)[i
] = ((unsigned int *)indices
)[i
] - min
;
305 WARN_ONCE("Unknown elt type!\n");
309 /* XXX: setup_arrays before state update? */
312 _mesa_update_state( ctx
);
314 r300UpdateShaders(rmesa
);
316 if (setup_arrays(rmesa
, min
) >= R300_FALLBACK_TCL
) {
317 r300ReleaseDmaRegion(rmesa
, &rvb
, __FUNCTION__
);
321 rmesa
->state
.VB
.Count
= max
- min
+ 1;
323 r300UpdateShaderStates(rmesa
);
325 rmesa
->state
.VB
.Primitive
= &prim
;
326 rmesa
->state
.VB
.PrimitiveCount
= 1;
328 prim
.mode
= mode
| PRIM_BEGIN
| PRIM_END
;
329 if (rmesa
->state
.VB
.LockCount
)
330 prim
.start
= min
- rmesa
->state
.VB
.LockFirst
;
335 rmesa
->state
.VB
.Elts
= ptr
;
336 rmesa
->state
.VB
.elt_size
= elt_size
;
337 rmesa
->state
.VB
.elt_min
= min
;
338 rmesa
->state
.VB
.elt_max
= max
;
340 if (r300_run_vb_render(ctx
, NULL
)) {
341 r300ReleaseDmaRegion(rmesa
, &rvb
, __FUNCTION__
);
346 radeon_mm_use(rmesa
, rvb
.buf
->id
);
348 r300ReleaseDmaRegion(rmesa
, &rvb
, __FUNCTION__
);
353 static GLboolean
radeonDrawArrays( GLcontext
*ctx
,
354 GLenum mode
, GLint start
, GLsizei count
)
359 GET_CURRENT_CONTEXT(ctx
);
360 r300ContextPtr rmesa
= R300_CONTEXT(ctx
);
361 struct tnl_prim prim
;
364 /* TODO: split into multiple draws.
366 WARN_ONCE("Too many verts!\n");
370 FLUSH_CURRENT( ctx
, 0 );
373 _mesa_update_state( ctx
);
375 /* XXX: setup_arrays before state update? */
377 r300UpdateShaders(rmesa
);
379 if (setup_arrays(rmesa
, start
) >= R300_FALLBACK_TCL
)
382 rmesa
->state
.VB
.Count
= count
;
384 r300UpdateShaderStates(rmesa
);
386 rmesa
->state
.VB
.Primitive
= &prim
;
387 rmesa
->state
.VB
.PrimitiveCount
= 1;
389 prim
.mode
= mode
| PRIM_BEGIN
| PRIM_END
;
390 if (rmesa
->state
.VB
.LockCount
)
391 prim
.start
= start
- rmesa
->state
.VB
.LockFirst
;
396 rmesa
->state
.VB
.Elts
= NULL
;
397 rmesa
->state
.VB
.elt_size
= 0;
398 rmesa
->state
.VB
.elt_min
= 0;
399 rmesa
->state
.VB
.elt_max
= 0;
401 if (r300_run_vb_render(ctx
, NULL
))
408 static void radeon_draw_prims( GLcontext
*ctx
,
409 const struct gl_client_array
*arrays
[],
410 const struct _mesa_prim
*prim
,
412 const struct _mesa_index_buffer
*ib
,
417 for (i
= 0; i
< nr_prims
; i
++) {
418 if (!radeonDrawArrays(ctx
,
435 for (i
= 0; i
< nr_prims
; i
++) {
436 if (!radeonDrawRangeElements(ctx
,
458 void radeon_init_vtxfmt_a(r300ContextPtr rmesa
)
461 struct vbo_context
*vbo
= vbo_context(ctx
);
463 vbo
->draw_prims
= radeon_draw_prims
;
470 static struct gl_buffer_object
*
471 r300NewBufferObject(GLcontext
*ctx
, GLuint name
, GLenum target
)
473 struct r300_buffer_object
*obj
;
477 obj
= MALLOC_STRUCT(r300_buffer_object
);
478 _mesa_initialize_buffer_object(&obj
->mesa_obj
, name
, target
);
479 return &obj
->mesa_obj
;
482 static void r300BufferData(GLcontext
*ctx
, GLenum target
, GLsizeiptrARB size
,
483 const GLvoid
*data
, GLenum usage
, struct gl_buffer_object
*obj
)
485 r300ContextPtr rmesa
= R300_CONTEXT(ctx
);
486 struct r300_buffer_object
*r300_obj
= (struct r300_buffer_object
*)obj
;
488 /* Free previous buffer */
490 radeon_mm_free(rmesa
, r300_obj
->id
);
491 obj
->OnCard
= GL_FALSE
;
494 _mesa_free(obj
->Data
);
499 if (target
== GL_ELEMENT_ARRAY_BUFFER_ARB
) {
502 obj
->Data
= malloc(size
);
505 _mesa_memcpy(obj
->Data
, data
, size
);
507 obj
->OnCard
= GL_FALSE
;
509 r300_obj
->id
= radeon_mm_alloc(rmesa
, 4, size
);
510 if (r300_obj
->id
== 0)
513 obj
->Data
= radeon_mm_map(rmesa
, r300_obj
->id
, RADEON_MM_W
);
516 _mesa_memcpy(obj
->Data
, data
, size
);
518 radeon_mm_unmap(rmesa
, r300_obj
->id
);
519 obj
->OnCard
= GL_TRUE
;
526 static void r300BufferSubData(GLcontext
*ctx
, GLenum target
, GLintptrARB offset
,
527 GLsizeiptrARB size
, const GLvoid
* data
, struct gl_buffer_object
* bufObj
)
529 r300ContextPtr rmesa
= R300_CONTEXT(ctx
);
530 struct r300_buffer_object
*r300_obj
= (struct r300_buffer_object
*)bufObj
;
531 (void) ctx
; (void) target
;
534 if (bufObj
->Data
&& ((GLuint
) (size
+ offset
) <= bufObj
->Size
)) {
536 ptr
= radeon_mm_map(rmesa
, r300_obj
->id
, RADEON_MM_W
);
538 _mesa_memcpy( (GLubyte
*) ptr
+ offset
, data
, size
);
540 radeon_mm_unmap(rmesa
, r300_obj
->id
);
542 _mesa_memcpy( (GLubyte
*) bufObj
->Data
+ offset
, data
, size
);
547 static void *r300MapBuffer(GLcontext
*ctx
, GLenum target
, GLenum access
,
548 struct gl_buffer_object
*bufObj
)
550 r300ContextPtr rmesa
= R300_CONTEXT(ctx
);
551 struct r300_buffer_object
*r300_obj
= (struct r300_buffer_object
*)bufObj
;
556 //ASSERT(!bufObj->OnCard);
557 /* Just return a direct pointer to the data */
558 if (bufObj
->Pointer
) {
559 /* already mapped! */
563 if (!bufObj
->OnCard
) {
564 bufObj
->Pointer
= bufObj
->Data
;
565 return bufObj
->Pointer
;
570 bufObj
->Pointer
= radeon_mm_map(rmesa
, r300_obj
->id
, RADEON_MM_R
);
574 bufObj
->Pointer
= radeon_mm_map(rmesa
, r300_obj
->id
, RADEON_MM_W
);
578 bufObj
->Pointer
= radeon_mm_map(rmesa
, r300_obj
->id
, RADEON_MM_RW
);
582 WARN_ONCE("Unknown access type\n");
583 bufObj
->Pointer
= NULL
;
587 return bufObj
->Pointer
;
590 static GLboolean
r300UnmapBuffer(GLcontext
*ctx
, GLenum target
, struct gl_buffer_object
*bufObj
)
592 r300ContextPtr rmesa
= R300_CONTEXT(ctx
);
593 struct r300_buffer_object
*r300_obj
= (struct r300_buffer_object
*)bufObj
;
597 //ASSERT(!bufObj->OnCard);
598 /* XXX we might assert here that bufObj->Pointer is non-null */
599 if (!bufObj
->OnCard
) {
600 bufObj
->Pointer
= NULL
;
603 radeon_mm_unmap(rmesa
, r300_obj
->id
);
605 bufObj
->Pointer
= NULL
;
609 static void r300DeleteBuffer(GLcontext
*ctx
, struct gl_buffer_object
*obj
)
611 r300ContextPtr rmesa
= R300_CONTEXT(ctx
);
612 struct r300_buffer_object
*r300_obj
= (struct r300_buffer_object
*)obj
;
615 radeon_mm_free(rmesa
, r300_obj
->id
);
618 _mesa_delete_buffer_object(ctx
, obj
);
621 void r300EvictVBOs(GLcontext
*ctx
, int amount
)
623 r300ContextPtr rmesa
= R300_CONTEXT(ctx
);
624 struct _mesa_HashTable
*hash
= ctx
->Shared
->BufferObjects
;
625 GLuint k
= _mesa_HashFirstEntry(hash
);
627 while (amount
> 0 && k
) {
628 struct gl_buffer_object
*obj
= _mesa_lookup_bufferobj(ctx
, k
);
629 struct r300_buffer_object
*r300_obj
630 = (struct r300_buffer_object
*) obj
;
632 if (obj
->OnCard
&& obj
->Size
) {
634 obj
->Data
= _mesa_malloc(obj
->Size
);
636 data
= radeon_mm_map(rmesa
, r300_obj
->id
, RADEON_MM_R
);
637 _mesa_memcpy(obj
->Data
, data
, obj
->Size
);
638 radeon_mm_unmap(rmesa
, r300_obj
->id
);
640 radeon_mm_free(rmesa
, r300_obj
->id
);
642 obj
->OnCard
= GL_FALSE
;
647 k
= _mesa_HashNextEntry(hash
, k
);
652 void r300InitVBOFuncs(struct dd_function_table
*functions
)
654 functions
->NewBufferObject
= r300NewBufferObject
;
655 functions
->BufferData
= r300BufferData
;
656 functions
->BufferSubData
= r300BufferSubData
;
657 functions
->MapBuffer
= r300MapBuffer
;
658 functions
->UnmapBuffer
= r300UnmapBuffer
;
659 functions
->DeleteBuffer
= r300DeleteBuffer
;