Merge branch 'nouveau-import'
[mesa.git] / src / mesa / drivers / dri / r300 / radeon_vtxfmt_a.c
1 /*
2 * Copyright (C) 2005 Aapo Tahkola.
3 *
4 * All Rights Reserved.
5 *
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:
13 *
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.
17 *
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.
25 *
26 */
27
28 /*
29 * Authors:
30 * Aapo Tahkola <aet@rasterburn.org>
31 */
32
33 #include "context.h"
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"
40
41 #include "hash.h"
42 #include "dispatch.h"
43 #include "bufferobj.h"
44 #include "vtxfmt.h"
45 #include "api_validate.h"
46 #include "state.h"
47 #include "image.h"
48
49 #define CONV_VB(a, b) rvb->AttribPtr[(a)].size = vb->b->size, \
50 rvb->AttribPtr[(a)].type = GL_FLOAT, \
51 rvb->AttribPtr[(a)].stride = vb->b->stride, \
52 rvb->AttribPtr[(a)].data = vb->b->data
53
54 void radeon_vb_to_rvb(r300ContextPtr rmesa, struct radeon_vertex_buffer *rvb, struct vertex_buffer *vb)
55 {
56 int i;
57 GLcontext *ctx;
58 ctx = rmesa->radeon.glCtx;
59
60 memset(rvb, 0, sizeof(*rvb));
61
62 rvb->Elts = vb->Elts;
63 rvb->elt_size = 4;
64 rvb->elt_min = 0;
65 rvb->elt_max = vb->Count;
66
67 rvb->Count = vb->Count;
68
69 CONV_VB(VERT_ATTRIB_POS, ObjPtr);
70 CONV_VB(VERT_ATTRIB_NORMAL, NormalPtr);
71 CONV_VB(VERT_ATTRIB_COLOR0, ColorPtr[0]);
72 CONV_VB(VERT_ATTRIB_COLOR1, SecondaryColorPtr[0]);
73 CONV_VB(VERT_ATTRIB_FOG, FogCoordPtr);
74
75 for (i=0; i < ctx->Const.MaxTextureCoordUnits; i++)
76 CONV_VB(VERT_ATTRIB_TEX0 + i, TexCoordPtr[i]);
77
78 for (i=0; i < MAX_VERTEX_PROGRAM_ATTRIBS; i++)
79 CONV_VB(VERT_ATTRIB_GENERIC0 + i, AttribPtr[VERT_ATTRIB_GENERIC0 + i]);
80
81 rvb->Primitive = vb->Primitive;
82 rvb->PrimitiveCount = vb->PrimitiveCount;
83 rvb->LockFirst = rvb->LockCount = 0;
84 rvb->lock_uptodate = GL_FALSE;
85 }
86
87 #ifdef RADEON_VTXFMT_A
88
89 extern void _tnl_array_init( GLcontext *ctx );
90
91 #define CONV(a, b) \
92 do { \
93 if (ctx->Array.ArrayObj->b.Enabled) { \
94 rmesa->state.VB.AttribPtr[(a)].size = ctx->Array.ArrayObj->b.Size; \
95 rmesa->state.VB.AttribPtr[(a)].data = ctx->Array.ArrayObj->b.BufferObj->Name \
96 ? (void *)ADD_POINTERS(ctx->Array.ArrayObj->b.Ptr, ctx->Array.ArrayObj->b.BufferObj->Data) \
97 : (void *)ctx->Array.ArrayObj->b.Ptr; \
98 rmesa->state.VB.AttribPtr[(a)].stride = ctx->Array.ArrayObj->b.StrideB; \
99 rmesa->state.VB.AttribPtr[(a)].type = ctx->Array.ArrayObj->b.Type; \
100 enabled |= 1 << (a); \
101 } \
102 } while (0)
103
104 static int setup_arrays(r300ContextPtr rmesa, GLint start)
105 {
106 int i;
107 struct dt def = { 4, GL_FLOAT, 0, NULL };
108 GLcontext *ctx;
109 GLuint enabled = 0;
110
111 ctx = rmesa->radeon.glCtx;
112 i = r300Fallback(ctx);
113 if (i)
114 return i;
115
116 memset(rmesa->state.VB.AttribPtr, 0, VERT_ATTRIB_MAX*sizeof(struct dt));
117
118 CONV(VERT_ATTRIB_POS, Vertex);
119 CONV(VERT_ATTRIB_NORMAL, Normal);
120 CONV(VERT_ATTRIB_COLOR0, Color);
121 CONV(VERT_ATTRIB_COLOR1, SecondaryColor);
122 CONV(VERT_ATTRIB_FOG, FogCoord);
123
124 for (i=0; i < MAX_TEXTURE_COORD_UNITS; i++)
125 CONV(VERT_ATTRIB_TEX0 + i, TexCoord[i]);
126
127 if (ctx->VertexProgram._Enabled)
128 for (i=0; i < VERT_ATTRIB_MAX; i++)
129 CONV(i, VertexAttrib[i]);
130
131 for (i=0; i < VERT_ATTRIB_MAX; i++) {
132 if (enabled & (1 << i)) {
133 rmesa->state.VB.AttribPtr[i].data += rmesa->state.VB.AttribPtr[i].stride * start;
134 } else {
135 def.data = ctx->Current.Attrib[i];
136 memcpy(&rmesa->state.VB.AttribPtr[i], &def, sizeof(struct dt));
137 }
138
139 /*if(rmesa->state.VB.AttribPtr[i].data == ctx->Current.Attrib[i])
140 fprintf(stderr, "%d is default coord\n", i);*/
141 }
142
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 &&
147 #endif
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;
151 }
152
153 /*fprintf(stderr, "%d: ", i);
154
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;
168 }
169
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");*/
174 }
175 return R300_FALLBACK_NONE;
176 }
177
178 void radeon_init_vtxfmt_a(r300ContextPtr rmesa);
179
180 static void radeonDrawElements( GLenum mode, GLsizei count, GLenum type, const GLvoid *c_indices )
181 {
182 GET_CURRENT_CONTEXT(ctx);
183 r300ContextPtr rmesa = R300_CONTEXT(ctx);
184 int elt_size;
185 int i;
186 unsigned int min = ~0, max = 0;
187 struct tnl_prim prim;
188 static void *ptr = NULL;
189 struct r300_dma_region rvb;
190 const GLvoid *indices = c_indices;
191
192 if (count > 65535) {
193 WARN_ONCE("Too many verts!\n");
194 goto fallback;
195 }
196
197 if (ctx->Array.ElementArrayBufferObj->Name) {
198 /* use indices in the buffer object */
199 if (!ctx->Array.ElementArrayBufferObj->Data) {
200 _mesa_warning(ctx, "DrawRangeElements with empty vertex elements buffer!");
201 return;
202 }
203 /* actual address is the sum of pointers */
204 indices = (GLvoid *)
205 ADD_POINTERS(ctx->Array.ElementArrayBufferObj->Data, (const GLubyte *) c_indices);
206 }
207
208 if (!_mesa_validate_DrawElements( ctx, mode, count, type, indices ))
209 return;
210
211 FLUSH_CURRENT( ctx, 0 );
212
213 memset(&rvb, 0, sizeof(rvb));
214 switch (type) {
215 case GL_UNSIGNED_BYTE:
216 for (i=0; i < count; i++) {
217 if(((unsigned char *)indices)[i] < min)
218 min = ((unsigned char *)indices)[i];
219 if(((unsigned char *)indices)[i] > max)
220 max = ((unsigned char *)indices)[i];
221 }
222
223 #ifdef FORCE_32BITS_ELTS
224 elt_size = 4;
225 #else
226 elt_size = 2;
227 #endif
228 r300AllocDmaRegion(rmesa, &rvb, count * elt_size, elt_size);
229 rvb.aos_offset = GET_START(&rvb);
230 ptr = rvb.address + rvb.start;
231
232 #ifdef FORCE_32BITS_ELTS
233 for (i=0; i < count; i++)
234 ((unsigned int *)ptr)[i] = ((unsigned char *)indices)[i] - min;
235 #else
236 for (i=0; i < count; i++)
237 ((unsigned short int *)ptr)[i] = ((unsigned char *)indices)[i] - min;
238 #endif
239 break;
240
241 case GL_UNSIGNED_SHORT:
242 for (i=0; i < count; i++) {
243 if(((unsigned short int *)indices)[i] < min)
244 min = ((unsigned short int *)indices)[i];
245 if(((unsigned short int *)indices)[i] > max)
246 max = ((unsigned short int *)indices)[i];
247 }
248
249 #ifdef FORCE_32BITS_ELTS
250 elt_size = 4;
251 #else
252 elt_size = 2;
253 #endif
254
255 r300AllocDmaRegion(rmesa, &rvb, count * elt_size, elt_size);
256 rvb.aos_offset = GET_START(&rvb);
257 ptr = rvb.address + rvb.start;
258
259 #ifdef FORCE_32BITS_ELTS
260 for (i=0; i < count; i++)
261 ((unsigned int *)ptr)[i] = ((unsigned short int *)indices)[i] - min;
262 #else
263 for (i=0; i < count; i++)
264 ((unsigned short int *)ptr)[i] = ((unsigned short int *)indices)[i] - min;
265 #endif
266 break;
267
268 case GL_UNSIGNED_INT:
269 for (i=0; i < count; i++) {
270 if(((unsigned int *)indices)[i] < min)
271 min = ((unsigned int *)indices)[i];
272 if(((unsigned int *)indices)[i] > max)
273 max = ((unsigned int *)indices)[i];
274 }
275
276 #ifdef FORCE_32BITS_ELTS
277 elt_size = 4;
278 #else
279 if (max - min <= 65535)
280 elt_size = 2;
281 else
282 elt_size = 4;
283 #endif
284 r300AllocDmaRegion(rmesa, &rvb, count * elt_size, elt_size);
285 rvb.aos_offset = GET_START(&rvb);
286 ptr = rvb.address + rvb.start;
287
288
289 if (elt_size == 2)
290 for (i=0; i < count; i++)
291 ((unsigned short int *)ptr)[i] = ((unsigned int *)indices)[i] - min;
292 else
293 for (i=0; i < count; i++)
294 ((unsigned int *)ptr)[i] = ((unsigned int *)indices)[i] - min;
295 break;
296
297 default:
298 WARN_ONCE("Unknown elt type!\n");
299 goto fallback;
300 }
301
302 if (ctx->NewState)
303 _mesa_update_state( ctx );
304
305 r300UpdateShaders(rmesa);
306
307 if (setup_arrays(rmesa, min) >= R300_FALLBACK_TCL) {
308 r300ReleaseDmaRegion(rmesa, &rvb, __FUNCTION__);
309 goto fallback;
310 }
311
312 rmesa->state.VB.Count = max - min + 1;
313
314 r300UpdateShaderStates(rmesa);
315
316 rmesa->state.VB.Primitive = &prim;
317 rmesa->state.VB.PrimitiveCount = 1;
318
319 prim.mode = mode | PRIM_BEGIN | PRIM_END;
320 if (rmesa->state.VB.LockCount)
321 prim.start = min - rmesa->state.VB.LockFirst;
322 else
323 prim.start = 0;
324 prim.count = count;
325
326 rmesa->state.VB.Elts = ptr;
327 rmesa->state.VB.elt_size = elt_size;
328
329 if (r300_run_vb_render(ctx, NULL)) {
330 r300ReleaseDmaRegion(rmesa, &rvb, __FUNCTION__);
331 goto fallback;
332 }
333
334 if(rvb.buf)
335 radeon_mm_use(rmesa, rvb.buf->id);
336
337 r300ReleaseDmaRegion(rmesa, &rvb, __FUNCTION__);
338 return;
339
340 fallback:
341 _tnl_array_init(ctx);
342 _mesa_install_exec_vtxfmt( ctx, &TNL_CONTEXT(ctx)->exec_vtxfmt );
343 CALL_DrawElements(GET_DISPATCH(), (mode, count, type, c_indices));
344 radeon_init_vtxfmt_a(rmesa);
345 _mesa_install_exec_vtxfmt( ctx, &TNL_CONTEXT(ctx)->exec_vtxfmt );
346 }
347
348 static void radeonDrawRangeElements(GLenum mode, GLuint min, GLuint max, GLsizei count, GLenum type, const GLvoid *c_indices)
349 {
350 GET_CURRENT_CONTEXT(ctx);
351 r300ContextPtr rmesa = R300_CONTEXT(ctx);
352 struct tnl_prim prim;
353 int elt_size;
354 int i;
355 void *ptr = NULL;
356 struct r300_dma_region rvb;
357 const GLvoid *indices = c_indices;
358
359 if (count > 65535) {
360 /* TODO */
361 if (mode == GL_POINTS ||
362 mode == GL_LINES ||
363 mode == GL_QUADS ||
364 mode == GL_TRIANGLES) {
365
366 while (count) {
367 i = r300_get_num_verts(rmesa, MIN2(count, 65535), mode);
368
369 radeonDrawRangeElements(mode, min, max, i, type, indices);
370
371 indices += i * _mesa_sizeof_type(type);
372 count -= i;
373 }
374 return ;
375 }
376 WARN_ONCE("Too many verts!\n");
377 goto fallback;
378 }
379
380 if (ctx->Array.ElementArrayBufferObj->Name) {
381 /* use indices in the buffer object */
382 if (!ctx->Array.ElementArrayBufferObj->Data) {
383 _mesa_warning(ctx, "DrawRangeElements with empty vertex elements buffer!");
384 return;
385 }
386 /* actual address is the sum of pointers */
387 indices = (GLvoid *)
388 ADD_POINTERS(ctx->Array.ElementArrayBufferObj->Data, (const GLubyte *) c_indices);
389 }
390
391 if (!_mesa_validate_DrawRangeElements( ctx, mode, min, max, count, type, indices ))
392 return;
393
394 FLUSH_CURRENT( ctx, 0 );
395 #ifdef OPTIMIZE_ELTS
396 min = 0;
397 #endif
398
399 memset(&rvb, 0, sizeof(rvb));
400 switch (type){
401 case GL_UNSIGNED_BYTE:
402 #ifdef FORCE_32BITS_ELTS
403 elt_size = 4;
404 #else
405 elt_size = 2;
406 #endif
407 r300AllocDmaRegion(rmesa, &rvb, count * elt_size, elt_size);
408 rvb.aos_offset = GET_START(&rvb);
409 ptr = rvb.address + rvb.start;
410
411 #ifdef FORCE_32BITS_ELTS
412 for(i=0; i < count; i++)
413 ((unsigned int *)ptr)[i] = ((unsigned char *)indices)[i] - min;
414 #else
415 for(i=0; i < count; i++)
416 ((unsigned short int *)ptr)[i] = ((unsigned char *)indices)[i] - min;
417 #endif
418 break;
419
420 case GL_UNSIGNED_SHORT:
421 #ifdef FORCE_32BITS_ELTS
422 elt_size = 4;
423 #else
424 elt_size = 2;
425 #endif
426 #ifdef OPTIMIZE_ELTS
427 if (min == 0 && ctx->Array.ElementArrayBufferObj->Name){
428 ptr = indices;
429 break;
430 }
431 #endif
432 r300AllocDmaRegion(rmesa, &rvb, count * elt_size, elt_size);
433 rvb.aos_offset = GET_START(&rvb);
434 ptr = rvb.address + rvb.start;
435
436 #ifdef FORCE_32BITS_ELTS
437 for(i=0; i < count; i++)
438 ((unsigned int *)ptr)[i] = ((unsigned short int *)indices)[i] - min;
439 #else
440 for(i=0; i < count; i++)
441 ((unsigned short int *)ptr)[i] = ((unsigned short int *)indices)[i] - min;
442 #endif
443 break;
444
445 case GL_UNSIGNED_INT:
446 #ifdef FORCE_32BITS_ELTS
447 elt_size = 4;
448 #else
449 if (max - min <= 65535)
450 elt_size = 2;
451 else
452 elt_size = 4;
453 #endif
454 r300AllocDmaRegion(rmesa, &rvb, count * elt_size, elt_size);
455 rvb.aos_offset = GET_START(&rvb);
456 ptr = rvb.address + rvb.start;
457
458 if (elt_size == 2)
459 for (i=0; i < count; i++)
460 ((unsigned short int *)ptr)[i] = ((unsigned int *)indices)[i] - min;
461 else
462 for (i=0; i < count; i++)
463 ((unsigned int *)ptr)[i] = ((unsigned int *)indices)[i] - min;
464 break;
465
466 default:
467 WARN_ONCE("Unknown elt type!\n");
468 goto fallback;
469 }
470
471 /* XXX: setup_arrays before state update? */
472
473 if (ctx->NewState)
474 _mesa_update_state( ctx );
475
476 r300UpdateShaders(rmesa);
477
478 if (setup_arrays(rmesa, min) >= R300_FALLBACK_TCL) {
479 r300ReleaseDmaRegion(rmesa, &rvb, __FUNCTION__);
480 goto fallback;
481 }
482
483 rmesa->state.VB.Count = max - min + 1;
484
485 r300UpdateShaderStates(rmesa);
486
487 rmesa->state.VB.Primitive = &prim;
488 rmesa->state.VB.PrimitiveCount = 1;
489
490 prim.mode = mode | PRIM_BEGIN | PRIM_END;
491 if (rmesa->state.VB.LockCount)
492 prim.start = min - rmesa->state.VB.LockFirst;
493 else
494 prim.start = 0;
495 prim.count = count;
496
497 rmesa->state.VB.Elts = ptr;
498 rmesa->state.VB.elt_size = elt_size;
499 rmesa->state.VB.elt_min = min;
500 rmesa->state.VB.elt_max = max;
501
502 if (r300_run_vb_render(ctx, NULL)) {
503 r300ReleaseDmaRegion(rmesa, &rvb, __FUNCTION__);
504 goto fallback;
505 }
506
507 if(rvb.buf)
508 radeon_mm_use(rmesa, rvb.buf->id);
509
510 r300ReleaseDmaRegion(rmesa, &rvb, __FUNCTION__);
511 return ;
512
513 fallback:
514 _tnl_array_init(ctx);
515 _mesa_install_exec_vtxfmt( ctx, &TNL_CONTEXT(ctx)->exec_vtxfmt );
516 CALL_DrawRangeElements(GET_DISPATCH(), (mode, min, max, count, type, c_indices));
517 radeon_init_vtxfmt_a(rmesa);
518 _mesa_install_exec_vtxfmt( ctx, &TNL_CONTEXT(ctx)->exec_vtxfmt );
519 }
520
521 static void radeonDrawArrays( GLenum mode, GLint start, GLsizei count )
522 {
523 GET_CURRENT_CONTEXT(ctx);
524 r300ContextPtr rmesa = R300_CONTEXT(ctx);
525 struct tnl_prim prim;
526
527 if (count > 65535) {
528 WARN_ONCE("Too many verts!\n");
529 goto fallback;
530 }
531
532 if (!_mesa_validate_DrawArrays( ctx, mode, start, count ))
533 return;
534
535 FLUSH_CURRENT( ctx, 0 );
536
537 if (ctx->NewState)
538 _mesa_update_state( ctx );
539
540 /* XXX: setup_arrays before state update? */
541
542 r300UpdateShaders(rmesa);
543
544 if (setup_arrays(rmesa, start) >= R300_FALLBACK_TCL)
545 goto fallback;
546
547 rmesa->state.VB.Count = count;
548
549 r300UpdateShaderStates(rmesa);
550
551 rmesa->state.VB.Primitive = &prim;
552 rmesa->state.VB.PrimitiveCount = 1;
553
554 prim.mode = mode | PRIM_BEGIN | PRIM_END;
555 if (rmesa->state.VB.LockCount)
556 prim.start = start - rmesa->state.VB.LockFirst;
557 else
558 prim.start = 0;
559 prim.count = count;
560
561 rmesa->state.VB.Elts = NULL;
562 rmesa->state.VB.elt_size = 0;
563 rmesa->state.VB.elt_min = 0;
564 rmesa->state.VB.elt_max = 0;
565
566 if (r300_run_vb_render(ctx, NULL))
567 goto fallback;
568
569 return ;
570
571 fallback:
572 _tnl_array_init(ctx);
573 _mesa_install_exec_vtxfmt( ctx, &TNL_CONTEXT(ctx)->exec_vtxfmt );
574 CALL_DrawArrays(GET_DISPATCH(), (mode, start, count));
575 radeon_init_vtxfmt_a(rmesa);
576 _mesa_install_exec_vtxfmt( ctx, &TNL_CONTEXT(ctx)->exec_vtxfmt );
577 }
578
579 void radeon_init_vtxfmt_a(r300ContextPtr rmesa)
580 {
581 GLcontext *ctx;
582 GLvertexformat *vfmt;
583
584 ctx = rmesa->radeon.glCtx;
585 vfmt = (GLvertexformat *)ctx->TnlModule.Current;
586
587 vfmt->DrawElements = radeonDrawElements;
588 vfmt->DrawArrays = radeonDrawArrays;
589 vfmt->DrawRangeElements = radeonDrawRangeElements;
590
591 }
592 #endif
593
594 #ifdef HW_VBOS
595
596 static struct gl_buffer_object *
597 r300NewBufferObject(GLcontext *ctx, GLuint name, GLenum target )
598 {
599 struct r300_buffer_object *obj;
600
601 (void) ctx;
602
603 obj = MALLOC_STRUCT(r300_buffer_object);
604 _mesa_initialize_buffer_object(&obj->mesa_obj, name, target);
605 return &obj->mesa_obj;
606 }
607
608 static void r300BufferData(GLcontext *ctx, GLenum target, GLsizeiptrARB size,
609 const GLvoid *data, GLenum usage, struct gl_buffer_object *obj)
610 {
611 r300ContextPtr rmesa = R300_CONTEXT(ctx);
612 struct r300_buffer_object *r300_obj = (struct r300_buffer_object *)obj;
613
614 /* Free previous buffer */
615 if (obj->OnCard) {
616 radeon_mm_free(rmesa, r300_obj->id);
617 obj->OnCard = GL_FALSE;
618 } else {
619 if (obj->Data)
620 _mesa_free(obj->Data);
621 }
622 #ifdef OPTIMIZE_ELTS
623 if (0) {
624 #else
625 if (target == GL_ELEMENT_ARRAY_BUFFER_ARB) {
626 #endif
627 fallback:
628 obj->Data = malloc(size);
629
630 if (data)
631 _mesa_memcpy(obj->Data, data, size);
632
633 obj->OnCard = GL_FALSE;
634 } else {
635 r300_obj->id = radeon_mm_alloc(rmesa, 4, size);
636 if (r300_obj->id == 0)
637 goto fallback;
638
639 obj->Data = radeon_mm_map(rmesa, r300_obj->id, RADEON_MM_W);
640
641 if (data)
642 _mesa_memcpy(obj->Data, data, size);
643
644 radeon_mm_unmap(rmesa, r300_obj->id);
645 obj->OnCard = GL_TRUE;
646 }
647
648 obj->Size = size;
649 obj->Usage = usage;
650 }
651
652 static void r300BufferSubData(GLcontext *ctx, GLenum target, GLintptrARB offset,
653 GLsizeiptrARB size, const GLvoid * data, struct gl_buffer_object * bufObj)
654 {
655 r300ContextPtr rmesa = R300_CONTEXT(ctx);
656 struct r300_buffer_object *r300_obj = (struct r300_buffer_object *)bufObj;
657 (void) ctx; (void) target;
658 void *ptr;
659
660 if (bufObj->Data && ((GLuint) (size + offset) <= bufObj->Size)) {
661 if (bufObj->OnCard){
662 ptr = radeon_mm_map(rmesa, r300_obj->id, RADEON_MM_W);
663
664 _mesa_memcpy( (GLubyte *) ptr + offset, data, size );
665
666 radeon_mm_unmap(rmesa, r300_obj->id);
667 } else {
668 _mesa_memcpy( (GLubyte *) bufObj->Data + offset, data, size );
669 }
670 }
671 }
672
673 static void *r300MapBuffer(GLcontext *ctx, GLenum target, GLenum access,
674 struct gl_buffer_object *bufObj)
675 {
676 r300ContextPtr rmesa = R300_CONTEXT(ctx);
677 struct r300_buffer_object *r300_obj = (struct r300_buffer_object *)bufObj;
678
679 (void) ctx;
680 (void) target;
681 (void) access;
682 //ASSERT(!bufObj->OnCard);
683 /* Just return a direct pointer to the data */
684 if (bufObj->Pointer) {
685 /* already mapped! */
686 return NULL;
687 }
688
689 if (!bufObj->OnCard) {
690 bufObj->Pointer = bufObj->Data;
691 return bufObj->Pointer;
692 }
693
694 switch (access) {
695 case GL_READ_ONLY:
696 bufObj->Pointer = radeon_mm_map(rmesa, r300_obj->id, RADEON_MM_R);
697 break;
698
699 case GL_WRITE_ONLY:
700 bufObj->Pointer = radeon_mm_map(rmesa, r300_obj->id, RADEON_MM_W);
701 break;
702
703 case GL_READ_WRITE:
704 bufObj->Pointer = radeon_mm_map(rmesa, r300_obj->id, RADEON_MM_RW);
705 break;
706
707 default:
708 WARN_ONCE("Unknown access type\n");
709 bufObj->Pointer = NULL;
710 break;
711 }
712
713 return bufObj->Pointer;
714 }
715
716 static GLboolean r300UnmapBuffer(GLcontext *ctx, GLenum target, struct gl_buffer_object *bufObj)
717 {
718 r300ContextPtr rmesa = R300_CONTEXT(ctx);
719 struct r300_buffer_object *r300_obj = (struct r300_buffer_object *)bufObj;
720
721 (void) ctx;
722 (void) target;
723 //ASSERT(!bufObj->OnCard);
724 /* XXX we might assert here that bufObj->Pointer is non-null */
725 if (!bufObj->OnCard) {
726 bufObj->Pointer = NULL;
727 return GL_TRUE;
728 }
729 radeon_mm_unmap(rmesa, r300_obj->id);
730
731 bufObj->Pointer = NULL;
732 return GL_TRUE;
733 }
734
735 static void r300DeleteBuffer(GLcontext *ctx, struct gl_buffer_object *obj)
736 {
737 r300ContextPtr rmesa = R300_CONTEXT(ctx);
738 struct r300_buffer_object *r300_obj = (struct r300_buffer_object *)obj;
739
740 if (obj->OnCard) {
741 radeon_mm_free(rmesa, r300_obj->id);
742 obj->Data = NULL;
743 }
744 _mesa_delete_buffer_object(ctx, obj);
745 }
746
747 void r300_evict_vbos(GLcontext *ctx, int amount)
748 {
749 r300ContextPtr rmesa = R300_CONTEXT(ctx);
750 struct _mesa_HashTable *hash = ctx->Shared->BufferObjects;
751 GLuint k = _mesa_HashFirstEntry(hash);
752
753 while (amount > 0 && k) {
754 struct gl_buffer_object *obj = _mesa_lookup_bufferobj(ctx, k);
755 struct r300_buffer_object *r300_obj
756 = (struct r300_buffer_object *) obj;
757
758 if (obj->OnCard && obj->Size) {
759 GLvoid *data;
760 obj->Data = _mesa_malloc(obj->Size);
761
762 data = radeon_mm_map(rmesa, r300_obj->id, RADEON_MM_R);
763 _mesa_memcpy(obj->Data, data, obj->Size);
764 radeon_mm_unmap(rmesa, r300_obj->id);
765
766 radeon_mm_free(rmesa, r300_obj->id);
767 r300_obj->id = 0;
768 obj->OnCard = GL_FALSE;
769
770 amount -= obj->Size;
771 }
772
773 k = _mesa_HashNextEntry(hash, k);
774 }
775
776 }
777
778 void r300_init_vbo_funcs(struct dd_function_table *functions)
779 {
780 functions->NewBufferObject = r300NewBufferObject;
781 functions->BufferData = r300BufferData;
782 functions->BufferSubData = r300BufferSubData;
783 functions->MapBuffer = r300MapBuffer;
784 functions->UnmapBuffer = r300UnmapBuffer;
785 functions->DeleteBuffer = r300DeleteBuffer;
786 }
787
788 #endif