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