r300: Renamed the VBO functions to the R300 name format.
[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 #include "vbo/vbo_context.h"
50
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
55
56 void radeon_vb_to_rvb(r300ContextPtr rmesa, struct radeon_vertex_buffer *rvb, struct vertex_buffer *vb)
57 {
58 int i;
59 GLcontext *ctx;
60 ctx = rmesa->radeon.glCtx;
61
62 memset(rvb, 0, sizeof(*rvb));
63
64 rvb->Elts = vb->Elts;
65 rvb->elt_size = 4;
66 rvb->elt_min = 0;
67 rvb->elt_max = vb->Count;
68
69 rvb->Count = vb->Count;
70
71 if (hw_tcl_on) {
72 CONV_VB(VERT_ATTRIB_POS, ObjPtr);
73 } else {
74 assert(vb->ClipPtr);
75 CONV_VB(VERT_ATTRIB_POS, ClipPtr);
76 }
77
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);
82
83 for (i=0; i < ctx->Const.MaxTextureCoordUnits; i++)
84 CONV_VB(VERT_ATTRIB_TEX0 + i, TexCoordPtr[i]);
85
86 for (i=0; i < MAX_VERTEX_PROGRAM_ATTRIBS; i++)
87 CONV_VB(VERT_ATTRIB_GENERIC0 + i, AttribPtr[VERT_ATTRIB_GENERIC0 + i]);
88
89 rvb->Primitive = vb->Primitive;
90 rvb->PrimitiveCount = vb->PrimitiveCount;
91 rvb->LockFirst = rvb->LockCount = 0;
92 rvb->lock_uptodate = GL_FALSE;
93 }
94
95 #ifdef RADEON_VTXFMT_A
96
97 extern void _tnl_array_init( GLcontext *ctx );
98
99 #define CONV(a, b) \
100 do { \
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); \
109 } \
110 } while (0)
111
112 static int setup_arrays(r300ContextPtr rmesa, GLint start)
113 {
114 int i;
115 struct dt def = { 4, GL_FLOAT, 0, NULL };
116 GLcontext *ctx;
117 GLuint enabled = 0;
118
119 ctx = rmesa->radeon.glCtx;
120 i = r300Fallback(ctx);
121 if (i)
122 return i;
123
124 memset(rmesa->state.VB.AttribPtr, 0, VERT_ATTRIB_MAX*sizeof(struct dt));
125
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);
131
132 for (i=0; i < MAX_TEXTURE_COORD_UNITS; i++)
133 CONV(VERT_ATTRIB_TEX0 + i, TexCoord[i]);
134
135 if (ctx->VertexProgram._Enabled)
136 for (i=0; i < VERT_ATTRIB_MAX; i++)
137 CONV(i, VertexAttrib[i]);
138
139 for (i=0; i < VERT_ATTRIB_MAX; i++) {
140 rmesa->state.VB.AttribPtr[i].data += rmesa->state.VB.AttribPtr[i].stride * start;
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
181 static void radeonDrawRangeElements(GLcontext *ctx,
182 GLenum mode,
183 GLuint min,
184 GLuint max,
185 GLsizei count,
186 GLenum type,
187 const GLvoid *c_indices)
188 {
189 #if 1
190 return GL_FALSE;
191 #else
192 r300ContextPtr rmesa = R300_CONTEXT(ctx);
193 struct tnl_prim prim;
194 int elt_size;
195 int i;
196 void *ptr = NULL;
197 struct r300_dma_region rvb;
198 const GLvoid *indices = c_indices;
199
200 if (count > 65535) {
201 /* TODO */
202 if (mode == GL_POINTS ||
203 mode == GL_LINES ||
204 mode == GL_QUADS ||
205 mode == GL_TRIANGLES) {
206
207 while (count) {
208 i = r300_get_num_verts(rmesa, MIN2(count, 65535), mode);
209
210 radeonDrawRangeElements(mode, min, max, i, type, indices);
211
212 indices += i * _mesa_sizeof_type(type);
213 count -= i;
214 }
215 return GL_TRUE;
216 }
217 WARN_ONCE("Too many verts!\n");
218 return GL_FALSE;
219 }
220
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!");
225 return GL_TRUE;
226 }
227 /* actual address is the sum of pointers */
228 indices = (GLvoid *)
229 ADD_POINTERS(ctx->Array.ElementArrayBufferObj->Data, (const GLubyte *) c_indices);
230 }
231
232 FLUSH_CURRENT( ctx, 0 );
233 #ifdef OPTIMIZE_ELTS
234 min = 0;
235 #endif
236
237 memset(&rvb, 0, sizeof(rvb));
238 switch (type){
239 case GL_UNSIGNED_BYTE:
240 #ifdef FORCE_32BITS_ELTS
241 elt_size = 4;
242 #else
243 elt_size = 2;
244 #endif
245 r300AllocDmaRegion(rmesa, &rvb, count * elt_size, elt_size);
246 rvb.aos_offset = GET_START(&rvb);
247 ptr = rvb.address + rvb.start;
248
249 #ifdef FORCE_32BITS_ELTS
250 for(i=0; i < count; i++)
251 ((unsigned int *)ptr)[i] = ((unsigned char *)indices)[i] - min;
252 #else
253 for(i=0; i < count; i++)
254 ((unsigned short int *)ptr)[i] = ((unsigned char *)indices)[i] - min;
255 #endif
256 break;
257
258 case GL_UNSIGNED_SHORT:
259 #ifdef FORCE_32BITS_ELTS
260 elt_size = 4;
261 #else
262 elt_size = 2;
263 #endif
264 #ifdef OPTIMIZE_ELTS
265 if (min == 0 && ctx->Array.ElementArrayBufferObj->Name){
266 ptr = indices;
267 break;
268 }
269 #endif
270 r300AllocDmaRegion(rmesa, &rvb, count * elt_size, elt_size);
271 rvb.aos_offset = GET_START(&rvb);
272 ptr = rvb.address + rvb.start;
273
274 #ifdef FORCE_32BITS_ELTS
275 for(i=0; i < count; i++)
276 ((unsigned int *)ptr)[i] = ((unsigned short int *)indices)[i] - min;
277 #else
278 for(i=0; i < count; i++)
279 ((unsigned short int *)ptr)[i] = ((unsigned short int *)indices)[i] - min;
280 #endif
281 break;
282
283 case GL_UNSIGNED_INT:
284 #ifdef FORCE_32BITS_ELTS
285 elt_size = 4;
286 #else
287 if (max - min <= 65535)
288 elt_size = 2;
289 else
290 elt_size = 4;
291 #endif
292 r300AllocDmaRegion(rmesa, &rvb, count * elt_size, elt_size);
293 rvb.aos_offset = GET_START(&rvb);
294 ptr = rvb.address + rvb.start;
295
296 if (elt_size == 2)
297 for (i=0; i < count; i++)
298 ((unsigned short int *)ptr)[i] = ((unsigned int *)indices)[i] - min;
299 else
300 for (i=0; i < count; i++)
301 ((unsigned int *)ptr)[i] = ((unsigned int *)indices)[i] - min;
302 break;
303
304 default:
305 WARN_ONCE("Unknown elt type!\n");
306 return GL_FALSE;
307 }
308
309 /* XXX: setup_arrays before state update? */
310
311 if (ctx->NewState)
312 _mesa_update_state( ctx );
313
314 r300UpdateShaders(rmesa);
315
316 if (setup_arrays(rmesa, min) >= R300_FALLBACK_TCL) {
317 r300ReleaseDmaRegion(rmesa, &rvb, __FUNCTION__);
318 return GL_FALSE;
319 }
320
321 rmesa->state.VB.Count = max - min + 1;
322
323 r300UpdateShaderStates(rmesa);
324
325 rmesa->state.VB.Primitive = &prim;
326 rmesa->state.VB.PrimitiveCount = 1;
327
328 prim.mode = mode | PRIM_BEGIN | PRIM_END;
329 if (rmesa->state.VB.LockCount)
330 prim.start = min - rmesa->state.VB.LockFirst;
331 else
332 prim.start = 0;
333 prim.count = count;
334
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;
339
340 if (r300_run_vb_render(ctx, NULL)) {
341 r300ReleaseDmaRegion(rmesa, &rvb, __FUNCTION__);
342 return GL_FALSE;
343 }
344
345 if(rvb.buf)
346 radeon_mm_use(rmesa, rvb.buf->id);
347
348 r300ReleaseDmaRegion(rmesa, &rvb, __FUNCTION__);
349 return GL_TRUE;
350 #endif
351 }
352
353 static GLboolean radeonDrawArrays( GLcontext *ctx,
354 GLenum mode, GLint start, GLsizei count )
355 {
356 #if 1
357 return GL_FALSE;
358 #else
359 GET_CURRENT_CONTEXT(ctx);
360 r300ContextPtr rmesa = R300_CONTEXT(ctx);
361 struct tnl_prim prim;
362
363 if (count > 65535) {
364 /* TODO: split into multiple draws.
365 */
366 WARN_ONCE("Too many verts!\n");
367 return GL_FALSE;
368 }
369
370 FLUSH_CURRENT( ctx, 0 );
371
372 if (ctx->NewState)
373 _mesa_update_state( ctx );
374
375 /* XXX: setup_arrays before state update? */
376
377 r300UpdateShaders(rmesa);
378
379 if (setup_arrays(rmesa, start) >= R300_FALLBACK_TCL)
380 return GL_FALSE;
381
382 rmesa->state.VB.Count = count;
383
384 r300UpdateShaderStates(rmesa);
385
386 rmesa->state.VB.Primitive = &prim;
387 rmesa->state.VB.PrimitiveCount = 1;
388
389 prim.mode = mode | PRIM_BEGIN | PRIM_END;
390 if (rmesa->state.VB.LockCount)
391 prim.start = start - rmesa->state.VB.LockFirst;
392 else
393 prim.start = 0;
394 prim.count = count;
395
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;
400
401 if (r300_run_vb_render(ctx, NULL))
402 return GL_FALSE;
403
404 return GL_TRUE;
405 #endif
406 }
407
408 static void radeon_draw_prims( GLcontext *ctx,
409 const struct gl_client_array *arrays[],
410 const struct _mesa_prim *prim,
411 GLuint nr_prims,
412 const struct _mesa_index_buffer *ib,
413 GLuint min_index,
414 GLuint max_index)
415 {
416 if (ib == NULL) {
417 for (i = 0; i < nr_prims; i++) {
418 if (!radeonDrawArrays(ctx,
419 prim->mode,
420 prim->start,
421 prim->count)) {
422 /* Fallback
423 */
424 _tnl_draw_prims(ctx,
425 arrays,
426 prim + i,
427 nr_prims - i,
428 ib,
429 min_index,
430 max_index);
431 return;
432 }
433 }
434 } else {
435 for (i = 0; i < nr_prims; i++) {
436 if (!radeonDrawRangeElements(ctx,
437 prim->mode,
438 min_index,
439 max_index,
440 prim->count,
441 ib->types,
442 ib->ptr)) {
443 /* Fallback
444 */
445 _tnl_draw_prims(ctx,
446 arrays,
447 prim + i,
448 nr_prims - i,
449 ib,
450 min_index,
451 max_index);
452 return;
453 }
454 }
455 }
456 }
457
458 void radeon_init_vtxfmt_a(r300ContextPtr rmesa)
459 {
460 GLcontext *ctx;
461 struct vbo_context *vbo = vbo_context(ctx);
462
463 vbo->draw_prims = radeon_draw_prims;
464 }
465
466 #endif
467
468 #ifdef HW_VBOS
469
470 static struct gl_buffer_object *
471 r300NewBufferObject(GLcontext *ctx, GLuint name, GLenum target )
472 {
473 struct r300_buffer_object *obj;
474
475 (void) ctx;
476
477 obj = MALLOC_STRUCT(r300_buffer_object);
478 _mesa_initialize_buffer_object(&obj->mesa_obj, name, target);
479 return &obj->mesa_obj;
480 }
481
482 static void r300BufferData(GLcontext *ctx, GLenum target, GLsizeiptrARB size,
483 const GLvoid *data, GLenum usage, struct gl_buffer_object *obj)
484 {
485 r300ContextPtr rmesa = R300_CONTEXT(ctx);
486 struct r300_buffer_object *r300_obj = (struct r300_buffer_object *)obj;
487
488 /* Free previous buffer */
489 if (obj->OnCard) {
490 radeon_mm_free(rmesa, r300_obj->id);
491 obj->OnCard = GL_FALSE;
492 } else {
493 if (obj->Data)
494 _mesa_free(obj->Data);
495 }
496 #ifdef OPTIMIZE_ELTS
497 if (0) {
498 #else
499 if (target == GL_ELEMENT_ARRAY_BUFFER_ARB) {
500 #endif
501 fallback:
502 obj->Data = malloc(size);
503
504 if (data)
505 _mesa_memcpy(obj->Data, data, size);
506
507 obj->OnCard = GL_FALSE;
508 } else {
509 r300_obj->id = radeon_mm_alloc(rmesa, 4, size);
510 if (r300_obj->id == 0)
511 goto fallback;
512
513 obj->Data = radeon_mm_map(rmesa, r300_obj->id, RADEON_MM_W);
514
515 if (data)
516 _mesa_memcpy(obj->Data, data, size);
517
518 radeon_mm_unmap(rmesa, r300_obj->id);
519 obj->OnCard = GL_TRUE;
520 }
521
522 obj->Size = size;
523 obj->Usage = usage;
524 }
525
526 static void r300BufferSubData(GLcontext *ctx, GLenum target, GLintptrARB offset,
527 GLsizeiptrARB size, const GLvoid * data, struct gl_buffer_object * bufObj)
528 {
529 r300ContextPtr rmesa = R300_CONTEXT(ctx);
530 struct r300_buffer_object *r300_obj = (struct r300_buffer_object *)bufObj;
531 (void) ctx; (void) target;
532 void *ptr;
533
534 if (bufObj->Data && ((GLuint) (size + offset) <= bufObj->Size)) {
535 if (bufObj->OnCard){
536 ptr = radeon_mm_map(rmesa, r300_obj->id, RADEON_MM_W);
537
538 _mesa_memcpy( (GLubyte *) ptr + offset, data, size );
539
540 radeon_mm_unmap(rmesa, r300_obj->id);
541 } else {
542 _mesa_memcpy( (GLubyte *) bufObj->Data + offset, data, size );
543 }
544 }
545 }
546
547 static void *r300MapBuffer(GLcontext *ctx, GLenum target, GLenum access,
548 struct gl_buffer_object *bufObj)
549 {
550 r300ContextPtr rmesa = R300_CONTEXT(ctx);
551 struct r300_buffer_object *r300_obj = (struct r300_buffer_object *)bufObj;
552
553 (void) ctx;
554 (void) target;
555 (void) access;
556 //ASSERT(!bufObj->OnCard);
557 /* Just return a direct pointer to the data */
558 if (bufObj->Pointer) {
559 /* already mapped! */
560 return NULL;
561 }
562
563 if (!bufObj->OnCard) {
564 bufObj->Pointer = bufObj->Data;
565 return bufObj->Pointer;
566 }
567
568 switch (access) {
569 case GL_READ_ONLY:
570 bufObj->Pointer = radeon_mm_map(rmesa, r300_obj->id, RADEON_MM_R);
571 break;
572
573 case GL_WRITE_ONLY:
574 bufObj->Pointer = radeon_mm_map(rmesa, r300_obj->id, RADEON_MM_W);
575 break;
576
577 case GL_READ_WRITE:
578 bufObj->Pointer = radeon_mm_map(rmesa, r300_obj->id, RADEON_MM_RW);
579 break;
580
581 default:
582 WARN_ONCE("Unknown access type\n");
583 bufObj->Pointer = NULL;
584 break;
585 }
586
587 return bufObj->Pointer;
588 }
589
590 static GLboolean r300UnmapBuffer(GLcontext *ctx, GLenum target, struct gl_buffer_object *bufObj)
591 {
592 r300ContextPtr rmesa = R300_CONTEXT(ctx);
593 struct r300_buffer_object *r300_obj = (struct r300_buffer_object *)bufObj;
594
595 (void) ctx;
596 (void) target;
597 //ASSERT(!bufObj->OnCard);
598 /* XXX we might assert here that bufObj->Pointer is non-null */
599 if (!bufObj->OnCard) {
600 bufObj->Pointer = NULL;
601 return GL_TRUE;
602 }
603 radeon_mm_unmap(rmesa, r300_obj->id);
604
605 bufObj->Pointer = NULL;
606 return GL_TRUE;
607 }
608
609 static void r300DeleteBuffer(GLcontext *ctx, 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 if (obj->OnCard) {
615 radeon_mm_free(rmesa, r300_obj->id);
616 obj->Data = NULL;
617 }
618 _mesa_delete_buffer_object(ctx, obj);
619 }
620
621 void r300EvictVBOs(GLcontext *ctx, int amount)
622 {
623 r300ContextPtr rmesa = R300_CONTEXT(ctx);
624 struct _mesa_HashTable *hash = ctx->Shared->BufferObjects;
625 GLuint k = _mesa_HashFirstEntry(hash);
626
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;
631
632 if (obj->OnCard && obj->Size) {
633 GLvoid *data;
634 obj->Data = _mesa_malloc(obj->Size);
635
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);
639
640 radeon_mm_free(rmesa, r300_obj->id);
641 r300_obj->id = 0;
642 obj->OnCard = GL_FALSE;
643
644 amount -= obj->Size;
645 }
646
647 k = _mesa_HashNextEntry(hash, k);
648 }
649
650 }
651
652 void r300InitVBOFuncs(struct dd_function_table *functions)
653 {
654 functions->NewBufferObject = r300NewBufferObject;
655 functions->BufferData = r300BufferData;
656 functions->BufferSubData = r300BufferSubData;
657 functions->MapBuffer = r300MapBuffer;
658 functions->UnmapBuffer = r300UnmapBuffer;
659 functions->DeleteBuffer = r300DeleteBuffer;
660 }
661
662 #endif