mesa: Make MultiDrawElements submit multiple primitives at once.
[mesa.git] / src / mesa / main / varray.c
1 /*
2 * Mesa 3-D graphics library
3 * Version: 7.6
4 *
5 * Copyright (C) 1999-2008 Brian Paul All Rights Reserved.
6 * Copyright (C) 2009 VMware, Inc. All Rights Reserved.
7 *
8 * Permission is hereby granted, free of charge, to any person obtaining a
9 * copy of this software and associated documentation files (the "Software"),
10 * to deal in the Software without restriction, including without limitation
11 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
12 * and/or sell copies of the Software, and to permit persons to whom the
13 * Software is furnished to do so, subject to the following conditions:
14 *
15 * The above copyright notice and this permission notice shall be included
16 * in all copies or substantial portions of the Software.
17 *
18 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
19 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
20 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
21 * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
22 * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
23 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
24 */
25
26
27 #include "glheader.h"
28 #include "imports.h"
29 #include "bufferobj.h"
30 #include "context.h"
31 #include "enable.h"
32 #include "enums.h"
33 #include "hash.h"
34 #include "mtypes.h"
35 #include "varray.h"
36 #include "arrayobj.h"
37 #include "glapi/dispatch.h"
38
39
40 /**
41 * Set the fields of a vertex array.
42 * Also do an error check for GL_ARB_vertex_array_object: check that
43 * all arrays reside in VBOs when using a vertex array object.
44 *
45 * \param array the array to update
46 * \param dirtyBit which bit to set in ctx->Array.NewState for this array
47 * \param elementSize size of each array element, in bytes
48 * \param size components per element (1, 2, 3 or 4)
49 * \param type datatype of each component (GL_FLOAT, GL_INT, etc)
50 * \param format either GL_RGBA or GL_BGRA
51 * \param stride stride between elements, in elements
52 * \param normalized are integer types converted to floats in [-1, 1]?
53 * \param ptr the address (or offset inside VBO) of the array data
54 * \return GL_TRUE if no error, GL_FALSE if error
55 */
56 static GLboolean
57 update_array(GLcontext *ctx, struct gl_client_array *array,
58 GLbitfield dirtyBit, GLsizei elementSize,
59 GLint size, GLenum type, GLenum format,
60 GLsizei stride, GLboolean normalized, const GLvoid *ptr)
61 {
62 ASSERT(format == GL_RGBA || format == GL_BGRA);
63
64 if (ctx->Array.ArrayObj->VBOonly &&
65 ctx->Array.ArrayBufferObj->Name == 0) {
66 /* GL_ARB_vertex_array_object requires that all arrays reside in VBOs.
67 * Generate GL_INVALID_OPERATION if that's not true.
68 */
69 _mesa_error(ctx, GL_INVALID_OPERATION,
70 "glVertex/Normal/EtcPointer(non-VBO array)");
71 return GL_FALSE;
72 }
73
74 array->Size = size;
75 array->Type = type;
76 array->Format = format;
77 array->Stride = stride;
78 array->StrideB = stride ? stride : elementSize;
79 array->Normalized = normalized;
80 array->Ptr = (const GLubyte *) ptr;
81 array->_ElementSize = elementSize;
82
83 _mesa_reference_buffer_object(ctx, &array->BufferObj,
84 ctx->Array.ArrayBufferObj);
85
86 ctx->NewState |= _NEW_ARRAY;
87 ctx->Array.NewState |= dirtyBit;
88
89 return GL_TRUE;
90 }
91
92
93 void GLAPIENTRY
94 _mesa_VertexPointer(GLint size, GLenum type, GLsizei stride, const GLvoid *ptr)
95 {
96 GLsizei elementSize;
97 GET_CURRENT_CONTEXT(ctx);
98 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx);
99
100 if (size < 2 || size > 4) {
101 _mesa_error( ctx, GL_INVALID_VALUE, "glVertexPointer(size)" );
102 return;
103 }
104 if (stride < 0) {
105 _mesa_error( ctx, GL_INVALID_VALUE, "glVertexPointer(stride)" );
106 return;
107 }
108
109 if (MESA_VERBOSE&(VERBOSE_VARRAY|VERBOSE_API))
110 _mesa_debug(ctx, "glVertexPointer( sz %d type %s stride %d )\n", size,
111 _mesa_lookup_enum_by_nr( type ), stride);
112
113 /* always need to check that <type> is legal */
114 switch (type) {
115 case GL_SHORT:
116 elementSize = size * sizeof(GLshort);
117 break;
118 case GL_INT:
119 elementSize = size * sizeof(GLint);
120 break;
121 case GL_FLOAT:
122 elementSize = size * sizeof(GLfloat);
123 break;
124 case GL_DOUBLE:
125 elementSize = size * sizeof(GLdouble);
126 break;
127 #if FEATURE_fixedpt
128 case GL_FIXED:
129 elementSize = size * sizeof(GLfixed);
130 break;
131 #endif
132 #if FEATURE_vertex_array_byte
133 case GL_BYTE:
134 elementSize = size * sizeof(GLbyte);
135 break;
136 #endif
137 default:
138 _mesa_error( ctx, GL_INVALID_ENUM, "glVertexPointer(type=%s)",
139 _mesa_lookup_enum_by_nr(type));
140 return;
141 }
142
143 if (!update_array(ctx, &ctx->Array.ArrayObj->Vertex, _NEW_ARRAY_VERTEX,
144 elementSize, size, type, GL_RGBA, stride, GL_FALSE, ptr))
145 return;
146
147 if (ctx->Driver.VertexPointer)
148 ctx->Driver.VertexPointer( ctx, size, type, stride, ptr );
149 }
150
151
152 void GLAPIENTRY
153 _mesa_NormalPointer(GLenum type, GLsizei stride, const GLvoid *ptr )
154 {
155 GLsizei elementSize;
156 GET_CURRENT_CONTEXT(ctx);
157 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx);
158
159 if (stride < 0) {
160 _mesa_error( ctx, GL_INVALID_VALUE, "glNormalPointer(stride)" );
161 return;
162 }
163
164 if (MESA_VERBOSE&(VERBOSE_VARRAY|VERBOSE_API))
165 _mesa_debug(ctx, "glNormalPointer( type %s stride %d )\n",
166 _mesa_lookup_enum_by_nr( type ), stride);
167
168 switch (type) {
169 case GL_BYTE:
170 elementSize = 3 * sizeof(GLbyte);
171 break;
172 case GL_SHORT:
173 elementSize = 3 * sizeof(GLshort);
174 break;
175 case GL_INT:
176 elementSize = 3 * sizeof(GLint);
177 break;
178 case GL_FLOAT:
179 elementSize = 3 * sizeof(GLfloat);
180 break;
181 case GL_DOUBLE:
182 elementSize = 3 * sizeof(GLdouble);
183 break;
184 #if FEATURE_fixedpt
185 case GL_FIXED:
186 elementSize = 3 * sizeof(GLfixed);
187 break;
188 #endif
189 default:
190 _mesa_error( ctx, GL_INVALID_ENUM, "glNormalPointer(type=%s)",
191 _mesa_lookup_enum_by_nr(type));
192 return;
193 }
194
195 if (!update_array(ctx, &ctx->Array.ArrayObj->Normal, _NEW_ARRAY_NORMAL,
196 elementSize, 3, type, GL_RGBA, stride, GL_TRUE, ptr))
197 return;
198
199 if (ctx->Driver.NormalPointer)
200 ctx->Driver.NormalPointer( ctx, type, stride, ptr );
201 }
202
203
204 void GLAPIENTRY
205 _mesa_ColorPointer(GLint size, GLenum type, GLsizei stride, const GLvoid *ptr)
206 {
207 GLsizei elementSize;
208 GLenum format;
209 GET_CURRENT_CONTEXT(ctx);
210 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx);
211
212 if (size < 3 || size > 4) {
213 if (!ctx->Extensions.EXT_vertex_array_bgra || size != GL_BGRA) {
214 _mesa_error(ctx, GL_INVALID_VALUE, "glColorPointer(size)");
215 return;
216 }
217 }
218 if (stride < 0) {
219 _mesa_error( ctx, GL_INVALID_VALUE, "glColorPointer(stride)" );
220 return;
221 }
222
223 if (MESA_VERBOSE&(VERBOSE_VARRAY|VERBOSE_API))
224 _mesa_debug(ctx, "glColorPointer( sz %d type %s stride %d )\n", size,
225 _mesa_lookup_enum_by_nr( type ), stride);
226
227 if (size == GL_BGRA) {
228 if (type != GL_UNSIGNED_BYTE) {
229 _mesa_error(ctx, GL_INVALID_VALUE, "glColorPointer(GL_BGRA/GLubyte)");
230 return;
231 }
232 format = GL_BGRA;
233 size = 4;
234 }
235 else {
236 format = GL_RGBA;
237 }
238
239 switch (type) {
240 case GL_BYTE:
241 elementSize = size * sizeof(GLbyte);
242 break;
243 case GL_UNSIGNED_BYTE:
244 elementSize = size * sizeof(GLubyte);
245 break;
246 case GL_SHORT:
247 elementSize = size * sizeof(GLshort);
248 break;
249 case GL_UNSIGNED_SHORT:
250 elementSize = size * sizeof(GLushort);
251 break;
252 case GL_INT:
253 elementSize = size * sizeof(GLint);
254 break;
255 case GL_UNSIGNED_INT:
256 elementSize = size * sizeof(GLuint);
257 break;
258 case GL_FLOAT:
259 elementSize = size * sizeof(GLfloat);
260 break;
261 case GL_DOUBLE:
262 elementSize = size * sizeof(GLdouble);
263 break;
264 #if FEATURE_fixedpt
265 case GL_FIXED:
266 elementSize = size * sizeof(GLfixed);
267 break;
268 #endif
269 default:
270 _mesa_error( ctx, GL_INVALID_ENUM, "glColorPointer(type=%s)",
271 _mesa_lookup_enum_by_nr(type));
272 return;
273 }
274
275 if (!update_array(ctx, &ctx->Array.ArrayObj->Color, _NEW_ARRAY_COLOR0,
276 elementSize, size, type, format, stride, GL_TRUE, ptr))
277 return;
278
279 if (ctx->Driver.ColorPointer)
280 ctx->Driver.ColorPointer( ctx, size, type, stride, ptr );
281 }
282
283
284 void GLAPIENTRY
285 _mesa_FogCoordPointerEXT(GLenum type, GLsizei stride, const GLvoid *ptr)
286 {
287 GLint elementSize;
288 GET_CURRENT_CONTEXT(ctx);
289 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx);
290
291 if (stride < 0) {
292 _mesa_error( ctx, GL_INVALID_VALUE, "glFogCoordPointer(stride)" );
293 return;
294 }
295
296 switch (type) {
297 case GL_FLOAT:
298 elementSize = sizeof(GLfloat);
299 break;
300 case GL_DOUBLE:
301 elementSize = sizeof(GLdouble);
302 break;
303 default:
304 _mesa_error( ctx, GL_INVALID_ENUM, "glFogCoordPointer(type)" );
305 return;
306 }
307
308 if (!update_array(ctx, &ctx->Array.ArrayObj->FogCoord, _NEW_ARRAY_FOGCOORD,
309 elementSize, 1, type, GL_RGBA, stride, GL_FALSE, ptr))
310 return;
311
312 if (ctx->Driver.FogCoordPointer)
313 ctx->Driver.FogCoordPointer( ctx, type, stride, ptr );
314 }
315
316
317 void GLAPIENTRY
318 _mesa_IndexPointer(GLenum type, GLsizei stride, const GLvoid *ptr)
319 {
320 GLsizei elementSize;
321 GET_CURRENT_CONTEXT(ctx);
322 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx);
323
324 if (stride < 0) {
325 _mesa_error( ctx, GL_INVALID_VALUE, "glIndexPointer(stride)" );
326 return;
327 }
328
329 switch (type) {
330 case GL_UNSIGNED_BYTE:
331 elementSize = sizeof(GLubyte);
332 break;
333 case GL_SHORT:
334 elementSize = sizeof(GLshort);
335 break;
336 case GL_INT:
337 elementSize = sizeof(GLint);
338 break;
339 case GL_FLOAT:
340 elementSize = sizeof(GLfloat);
341 break;
342 case GL_DOUBLE:
343 elementSize = sizeof(GLdouble);
344 break;
345 default:
346 _mesa_error( ctx, GL_INVALID_ENUM, "glIndexPointer(type)" );
347 return;
348 }
349
350 if (!update_array(ctx, &ctx->Array.ArrayObj->Index, _NEW_ARRAY_INDEX,
351 elementSize, 1, type, GL_RGBA, stride, GL_FALSE, ptr))
352 return;
353
354 if (ctx->Driver.IndexPointer)
355 ctx->Driver.IndexPointer( ctx, type, stride, ptr );
356 }
357
358
359 void GLAPIENTRY
360 _mesa_SecondaryColorPointerEXT(GLint size, GLenum type,
361 GLsizei stride, const GLvoid *ptr)
362 {
363 GLsizei elementSize;
364 GLenum format;
365 GET_CURRENT_CONTEXT(ctx);
366 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx);
367
368 if (size != 3 && size != 4) {
369 if (!ctx->Extensions.EXT_vertex_array_bgra || size != GL_BGRA) {
370 _mesa_error(ctx, GL_INVALID_VALUE, "glSecondaryColorPointer(size)");
371 return;
372 }
373 }
374 if (stride < 0) {
375 _mesa_error( ctx, GL_INVALID_VALUE, "glSecondaryColorPointer(stride)" );
376 return;
377 }
378
379 if (MESA_VERBOSE&(VERBOSE_VARRAY|VERBOSE_API))
380 _mesa_debug(ctx, "glSecondaryColorPointer( sz %d type %s stride %d )\n",
381 size, _mesa_lookup_enum_by_nr( type ), stride);
382
383 if (size == GL_BGRA) {
384 if (type != GL_UNSIGNED_BYTE) {
385 _mesa_error(ctx, GL_INVALID_VALUE, "glColorPointer(GL_BGRA/GLubyte)");
386 return;
387 }
388 format = GL_BGRA;
389 size = 4;
390 }
391 else {
392 format = GL_RGBA;
393 }
394
395 switch (type) {
396 case GL_BYTE:
397 elementSize = size * sizeof(GLbyte);
398 break;
399 case GL_UNSIGNED_BYTE:
400 elementSize = size * sizeof(GLubyte);
401 break;
402 case GL_SHORT:
403 elementSize = size * sizeof(GLshort);
404 break;
405 case GL_UNSIGNED_SHORT:
406 elementSize = size * sizeof(GLushort);
407 break;
408 case GL_INT:
409 elementSize = size * sizeof(GLint);
410 break;
411 case GL_UNSIGNED_INT:
412 elementSize = size * sizeof(GLuint);
413 break;
414 case GL_FLOAT:
415 elementSize = size * sizeof(GLfloat);
416 break;
417 case GL_DOUBLE:
418 elementSize = size * sizeof(GLdouble);
419 break;
420 default:
421 _mesa_error( ctx, GL_INVALID_ENUM, "glSecondaryColorPointer(type=%s)",
422 _mesa_lookup_enum_by_nr(type));
423 return;
424 }
425
426 if (!update_array(ctx, &ctx->Array.ArrayObj->SecondaryColor,
427 _NEW_ARRAY_COLOR1, elementSize, size, type,
428 format, stride, GL_TRUE, ptr))
429 return;
430
431 if (ctx->Driver.SecondaryColorPointer)
432 ctx->Driver.SecondaryColorPointer( ctx, size, type, stride, ptr );
433 }
434
435
436 void GLAPIENTRY
437 _mesa_TexCoordPointer(GLint size, GLenum type, GLsizei stride,
438 const GLvoid *ptr)
439 {
440 GLint elementSize;
441 GET_CURRENT_CONTEXT(ctx);
442 const GLuint unit = ctx->Array.ActiveTexture;
443 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx);
444
445 if (size < 1 || size > 4) {
446 _mesa_error( ctx, GL_INVALID_VALUE, "glTexCoordPointer(size)" );
447 return;
448 }
449 if (stride < 0) {
450 _mesa_error( ctx, GL_INVALID_VALUE, "glTexCoordPointer(stride)" );
451 return;
452 }
453
454 if (MESA_VERBOSE&(VERBOSE_VARRAY|VERBOSE_API))
455 _mesa_debug(ctx, "glTexCoordPointer(unit %u sz %d type %s stride %d)\n",
456 unit, size, _mesa_lookup_enum_by_nr( type ), stride);
457
458 /* always need to check that <type> is legal */
459 switch (type) {
460 case GL_SHORT:
461 elementSize = size * sizeof(GLshort);
462 break;
463 case GL_INT:
464 elementSize = size * sizeof(GLint);
465 break;
466 case GL_FLOAT:
467 elementSize = size * sizeof(GLfloat);
468 break;
469 case GL_DOUBLE:
470 elementSize = size * sizeof(GLdouble);
471 break;
472 #if FEATURE_fixedpt
473 case GL_FIXED:
474 elementSize = size * sizeof(GLfixed);
475 break;
476 #endif
477 #if FEATURE_vertex_array_byte
478 case GL_BYTE:
479 elementSize = size * sizeof(GLbyte);
480 break;
481 #endif
482 default:
483 _mesa_error( ctx, GL_INVALID_ENUM, "glTexCoordPointer(type=%s)",
484 _mesa_lookup_enum_by_nr(type));
485 return;
486 }
487
488 if (!update_array(ctx, &ctx->Array.ArrayObj->TexCoord[unit],
489 _NEW_ARRAY_TEXCOORD(unit),
490 elementSize, size, type, GL_RGBA, stride, GL_FALSE, ptr))
491 return;
492
493 if (ctx->Driver.TexCoordPointer)
494 ctx->Driver.TexCoordPointer( ctx, size, type, stride, ptr );
495 }
496
497
498 void GLAPIENTRY
499 _mesa_EdgeFlagPointer(GLsizei stride, const GLvoid *ptr)
500 {
501 GET_CURRENT_CONTEXT(ctx);
502 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx);
503
504 if (stride < 0) {
505 _mesa_error( ctx, GL_INVALID_VALUE, "glEdgeFlagPointer(stride)" );
506 return;
507 }
508
509 if (!update_array(ctx, &ctx->Array.ArrayObj->EdgeFlag, _NEW_ARRAY_EDGEFLAG,
510 sizeof(GLboolean), 1, GL_UNSIGNED_BYTE, GL_RGBA,
511 stride, GL_FALSE, ptr))
512 return;
513
514 if (ctx->Driver.EdgeFlagPointer)
515 ctx->Driver.EdgeFlagPointer( ctx, stride, ptr );
516 }
517
518
519 void GLAPIENTRY
520 _mesa_PointSizePointer(GLenum type, GLsizei stride, const GLvoid *ptr)
521 {
522 GLsizei elementSize;
523 GET_CURRENT_CONTEXT(ctx);
524 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx);
525
526 if (stride < 0) {
527 _mesa_error( ctx, GL_INVALID_VALUE, "glPointSizePointer(stride)" );
528 return;
529 }
530
531 switch (type) {
532 case GL_FLOAT:
533 elementSize = sizeof(GLfloat);
534 break;
535 #if FEATURE_fixedpt
536 case GL_FIXED:
537 elementSize = sizeof(GLfixed);
538 break;
539 #endif
540 default:
541 _mesa_error( ctx, GL_INVALID_ENUM, "glPointSizePointer(type)" );
542 return;
543 }
544
545 update_array(ctx, &ctx->Array.ArrayObj->PointSize, _NEW_ARRAY_POINT_SIZE,
546 elementSize, 1, type, GL_RGBA, stride, GL_FALSE, ptr);
547 }
548
549
550 #if FEATURE_NV_vertex_program
551 /**
552 * Set a vertex attribute array.
553 * Note that these arrays DO alias the conventional GL vertex arrays
554 * (position, normal, color, fog, texcoord, etc).
555 * The generic attribute slots at #16 and above are not touched.
556 */
557 void GLAPIENTRY
558 _mesa_VertexAttribPointerNV(GLuint index, GLint size, GLenum type,
559 GLsizei stride, const GLvoid *ptr)
560 {
561 GLboolean normalized = GL_FALSE;
562 GLsizei elementSize;
563 GLenum format;
564 GET_CURRENT_CONTEXT(ctx);
565 ASSERT_OUTSIDE_BEGIN_END(ctx);
566
567 if (index >= MAX_NV_VERTEX_PROGRAM_INPUTS) {
568 _mesa_error(ctx, GL_INVALID_VALUE, "glVertexAttribPointerNV(index)");
569 return;
570 }
571
572 if (size < 1 || size > 4) {
573 _mesa_error(ctx, GL_INVALID_VALUE, "glVertexAttribPointerNV(size)");
574 return;
575 }
576
577 if (stride < 0) {
578 _mesa_error(ctx, GL_INVALID_VALUE, "glVertexAttribPointerNV(stride)");
579 return;
580 }
581
582 if (type == GL_UNSIGNED_BYTE && size != 4) {
583 _mesa_error(ctx, GL_INVALID_VALUE, "glVertexAttribPointerNV(size!=4)");
584 return;
585 }
586
587 if (size == GL_BGRA) {
588 if (type != GL_UNSIGNED_BYTE) {
589 _mesa_error(ctx, GL_INVALID_VALUE,
590 "glVertexAttribPointerNV(GL_BGRA/type)");
591 return;
592 }
593
594 format = GL_BGRA;
595 size = 4;
596 normalized = GL_TRUE;
597 }
598 else {
599 format = GL_RGBA;
600 }
601
602 /* check for valid 'type' and compute StrideB right away */
603 switch (type) {
604 case GL_UNSIGNED_BYTE:
605 normalized = GL_TRUE;
606 elementSize = size * sizeof(GLubyte);
607 break;
608 case GL_SHORT:
609 elementSize = size * sizeof(GLshort);
610 break;
611 case GL_FLOAT:
612 elementSize = size * sizeof(GLfloat);
613 break;
614 case GL_DOUBLE:
615 elementSize = size * sizeof(GLdouble);
616 break;
617 default:
618 _mesa_error( ctx, GL_INVALID_ENUM, "glVertexAttribPointerNV(type=%s)",
619 _mesa_lookup_enum_by_nr(type));
620 return;
621 }
622
623 if (!update_array(ctx, &ctx->Array.ArrayObj->VertexAttrib[index],
624 _NEW_ARRAY_ATTRIB(index),
625 elementSize, size, type, format, stride, normalized, ptr))
626 return;
627
628 if (ctx->Driver.VertexAttribPointer)
629 ctx->Driver.VertexAttribPointer( ctx, index, size, type, stride, ptr );
630 }
631 #endif
632
633
634 #if FEATURE_ARB_vertex_program
635 /**
636 * Set a generic vertex attribute array.
637 * Note that these arrays DO NOT alias the conventional GL vertex arrays
638 * (position, normal, color, fog, texcoord, etc).
639 */
640 void GLAPIENTRY
641 _mesa_VertexAttribPointerARB(GLuint index, GLint size, GLenum type,
642 GLboolean normalized,
643 GLsizei stride, const GLvoid *ptr)
644 {
645 GLsizei elementSize;
646 GLenum format;
647 GET_CURRENT_CONTEXT(ctx);
648 ASSERT_OUTSIDE_BEGIN_END(ctx);
649
650 if (index >= ctx->Const.VertexProgram.MaxAttribs) {
651 _mesa_error(ctx, GL_INVALID_VALUE, "glVertexAttribPointerARB(index)");
652 return;
653 }
654
655 if (size < 1 || size > 4) {
656 if (!ctx->Extensions.EXT_vertex_array_bgra || size != GL_BGRA) {
657 _mesa_error(ctx, GL_INVALID_VALUE, "glVertexAttribPointerARB(size)");
658 return;
659 }
660 }
661
662 if (stride < 0) {
663 _mesa_error(ctx, GL_INVALID_VALUE, "glVertexAttribPointerARB(stride)");
664 return;
665 }
666
667 if (size == GL_BGRA) {
668 if (type != GL_UNSIGNED_BYTE) {
669 _mesa_error(ctx, GL_INVALID_VALUE,
670 "glVertexAttribPointerARB(GL_BGRA/type)");
671 return;
672 }
673 if (normalized != GL_TRUE) {
674 _mesa_error(ctx, GL_INVALID_VALUE,
675 "glVertexAttribPointerARB(GL_BGRA/normalized)");
676 return;
677 }
678
679 format = GL_BGRA;
680 size = 4;
681 }
682 else {
683 format = GL_RGBA;
684 }
685
686 /* check for valid 'type' and compute StrideB right away */
687 /* NOTE: more types are supported here than in the NV extension */
688 switch (type) {
689 case GL_BYTE:
690 elementSize = size * sizeof(GLbyte);
691 break;
692 case GL_UNSIGNED_BYTE:
693 elementSize = size * sizeof(GLubyte);
694 break;
695 case GL_SHORT:
696 elementSize = size * sizeof(GLshort);
697 break;
698 case GL_UNSIGNED_SHORT:
699 elementSize = size * sizeof(GLushort);
700 break;
701 case GL_INT:
702 elementSize = size * sizeof(GLint);
703 break;
704 case GL_UNSIGNED_INT:
705 elementSize = size * sizeof(GLuint);
706 break;
707 case GL_FLOAT:
708 elementSize = size * sizeof(GLfloat);
709 break;
710 case GL_DOUBLE:
711 elementSize = size * sizeof(GLdouble);
712 break;
713 #if FEATURE_fixedpt
714 case GL_FIXED:
715 elementSize = size * sizeof(GLfixed);
716 break;
717 #endif
718 default:
719 _mesa_error( ctx, GL_INVALID_ENUM, "glVertexAttribPointerARB(type)" );
720 return;
721 }
722
723 if (!update_array(ctx, &ctx->Array.ArrayObj->VertexAttrib[index],
724 _NEW_ARRAY_ATTRIB(index),
725 elementSize, size, type, format, stride, normalized, ptr))
726 return;
727
728 if (ctx->Driver.VertexAttribPointer)
729 ctx->Driver.VertexAttribPointer(ctx, index, size, type, stride, ptr);
730 }
731 #endif
732
733
734 void GLAPIENTRY
735 _mesa_VertexPointerEXT(GLint size, GLenum type, GLsizei stride,
736 GLsizei count, const GLvoid *ptr)
737 {
738 (void) count;
739 _mesa_VertexPointer(size, type, stride, ptr);
740 }
741
742
743 void GLAPIENTRY
744 _mesa_NormalPointerEXT(GLenum type, GLsizei stride, GLsizei count,
745 const GLvoid *ptr)
746 {
747 (void) count;
748 _mesa_NormalPointer(type, stride, ptr);
749 }
750
751
752 void GLAPIENTRY
753 _mesa_ColorPointerEXT(GLint size, GLenum type, GLsizei stride, GLsizei count,
754 const GLvoid *ptr)
755 {
756 (void) count;
757 _mesa_ColorPointer(size, type, stride, ptr);
758 }
759
760
761 void GLAPIENTRY
762 _mesa_IndexPointerEXT(GLenum type, GLsizei stride, GLsizei count,
763 const GLvoid *ptr)
764 {
765 (void) count;
766 _mesa_IndexPointer(type, stride, ptr);
767 }
768
769
770 void GLAPIENTRY
771 _mesa_TexCoordPointerEXT(GLint size, GLenum type, GLsizei stride,
772 GLsizei count, const GLvoid *ptr)
773 {
774 (void) count;
775 _mesa_TexCoordPointer(size, type, stride, ptr);
776 }
777
778
779 void GLAPIENTRY
780 _mesa_EdgeFlagPointerEXT(GLsizei stride, GLsizei count, const GLboolean *ptr)
781 {
782 (void) count;
783 _mesa_EdgeFlagPointer(stride, ptr);
784 }
785
786
787 void GLAPIENTRY
788 _mesa_InterleavedArrays(GLenum format, GLsizei stride, const GLvoid *pointer)
789 {
790 GET_CURRENT_CONTEXT(ctx);
791 GLboolean tflag, cflag, nflag; /* enable/disable flags */
792 GLint tcomps, ccomps, vcomps; /* components per texcoord, color, vertex */
793 GLenum ctype = 0; /* color type */
794 GLint coffset = 0, noffset = 0, voffset;/* color, normal, vertex offsets */
795 const GLint toffset = 0; /* always zero */
796 GLint defstride; /* default stride */
797 GLint c, f;
798
799 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx);
800
801 f = sizeof(GLfloat);
802 c = f * ((4 * sizeof(GLubyte) + (f - 1)) / f);
803
804 if (stride < 0) {
805 _mesa_error( ctx, GL_INVALID_VALUE, "glInterleavedArrays(stride)" );
806 return;
807 }
808
809 switch (format) {
810 case GL_V2F:
811 tflag = GL_FALSE; cflag = GL_FALSE; nflag = GL_FALSE;
812 tcomps = 0; ccomps = 0; vcomps = 2;
813 voffset = 0;
814 defstride = 2*f;
815 break;
816 case GL_V3F:
817 tflag = GL_FALSE; cflag = GL_FALSE; nflag = GL_FALSE;
818 tcomps = 0; ccomps = 0; vcomps = 3;
819 voffset = 0;
820 defstride = 3*f;
821 break;
822 case GL_C4UB_V2F:
823 tflag = GL_FALSE; cflag = GL_TRUE; nflag = GL_FALSE;
824 tcomps = 0; ccomps = 4; vcomps = 2;
825 ctype = GL_UNSIGNED_BYTE;
826 coffset = 0;
827 voffset = c;
828 defstride = c + 2*f;
829 break;
830 case GL_C4UB_V3F:
831 tflag = GL_FALSE; cflag = GL_TRUE; nflag = GL_FALSE;
832 tcomps = 0; ccomps = 4; vcomps = 3;
833 ctype = GL_UNSIGNED_BYTE;
834 coffset = 0;
835 voffset = c;
836 defstride = c + 3*f;
837 break;
838 case GL_C3F_V3F:
839 tflag = GL_FALSE; cflag = GL_TRUE; nflag = GL_FALSE;
840 tcomps = 0; ccomps = 3; vcomps = 3;
841 ctype = GL_FLOAT;
842 coffset = 0;
843 voffset = 3*f;
844 defstride = 6*f;
845 break;
846 case GL_N3F_V3F:
847 tflag = GL_FALSE; cflag = GL_FALSE; nflag = GL_TRUE;
848 tcomps = 0; ccomps = 0; vcomps = 3;
849 noffset = 0;
850 voffset = 3*f;
851 defstride = 6*f;
852 break;
853 case GL_C4F_N3F_V3F:
854 tflag = GL_FALSE; cflag = GL_TRUE; nflag = GL_TRUE;
855 tcomps = 0; ccomps = 4; vcomps = 3;
856 ctype = GL_FLOAT;
857 coffset = 0;
858 noffset = 4*f;
859 voffset = 7*f;
860 defstride = 10*f;
861 break;
862 case GL_T2F_V3F:
863 tflag = GL_TRUE; cflag = GL_FALSE; nflag = GL_FALSE;
864 tcomps = 2; ccomps = 0; vcomps = 3;
865 voffset = 2*f;
866 defstride = 5*f;
867 break;
868 case GL_T4F_V4F:
869 tflag = GL_TRUE; cflag = GL_FALSE; nflag = GL_FALSE;
870 tcomps = 4; ccomps = 0; vcomps = 4;
871 voffset = 4*f;
872 defstride = 8*f;
873 break;
874 case GL_T2F_C4UB_V3F:
875 tflag = GL_TRUE; cflag = GL_TRUE; nflag = GL_FALSE;
876 tcomps = 2; ccomps = 4; vcomps = 3;
877 ctype = GL_UNSIGNED_BYTE;
878 coffset = 2*f;
879 voffset = c+2*f;
880 defstride = c+5*f;
881 break;
882 case GL_T2F_C3F_V3F:
883 tflag = GL_TRUE; cflag = GL_TRUE; nflag = GL_FALSE;
884 tcomps = 2; ccomps = 3; vcomps = 3;
885 ctype = GL_FLOAT;
886 coffset = 2*f;
887 voffset = 5*f;
888 defstride = 8*f;
889 break;
890 case GL_T2F_N3F_V3F:
891 tflag = GL_TRUE; cflag = GL_FALSE; nflag = GL_TRUE;
892 tcomps = 2; ccomps = 0; vcomps = 3;
893 noffset = 2*f;
894 voffset = 5*f;
895 defstride = 8*f;
896 break;
897 case GL_T2F_C4F_N3F_V3F:
898 tflag = GL_TRUE; cflag = GL_TRUE; nflag = GL_TRUE;
899 tcomps = 2; ccomps = 4; vcomps = 3;
900 ctype = GL_FLOAT;
901 coffset = 2*f;
902 noffset = 6*f;
903 voffset = 9*f;
904 defstride = 12*f;
905 break;
906 case GL_T4F_C4F_N3F_V4F:
907 tflag = GL_TRUE; cflag = GL_TRUE; nflag = GL_TRUE;
908 tcomps = 4; ccomps = 4; vcomps = 4;
909 ctype = GL_FLOAT;
910 coffset = 4*f;
911 noffset = 8*f;
912 voffset = 11*f;
913 defstride = 15*f;
914 break;
915 default:
916 _mesa_error( ctx, GL_INVALID_ENUM, "glInterleavedArrays(format)" );
917 return;
918 }
919
920 if (stride==0) {
921 stride = defstride;
922 }
923
924 _mesa_DisableClientState( GL_EDGE_FLAG_ARRAY );
925 _mesa_DisableClientState( GL_INDEX_ARRAY );
926 /* XXX also disable secondary color and generic arrays? */
927
928 /* Texcoords */
929 if (tflag) {
930 _mesa_EnableClientState( GL_TEXTURE_COORD_ARRAY );
931 _mesa_TexCoordPointer( tcomps, GL_FLOAT, stride,
932 (GLubyte *) pointer + toffset );
933 }
934 else {
935 _mesa_DisableClientState( GL_TEXTURE_COORD_ARRAY );
936 }
937
938 /* Color */
939 if (cflag) {
940 _mesa_EnableClientState( GL_COLOR_ARRAY );
941 _mesa_ColorPointer( ccomps, ctype, stride,
942 (GLubyte *) pointer + coffset );
943 }
944 else {
945 _mesa_DisableClientState( GL_COLOR_ARRAY );
946 }
947
948
949 /* Normals */
950 if (nflag) {
951 _mesa_EnableClientState( GL_NORMAL_ARRAY );
952 _mesa_NormalPointer( GL_FLOAT, stride, (GLubyte *) pointer + noffset );
953 }
954 else {
955 _mesa_DisableClientState( GL_NORMAL_ARRAY );
956 }
957
958 /* Vertices */
959 _mesa_EnableClientState( GL_VERTEX_ARRAY );
960 _mesa_VertexPointer( vcomps, GL_FLOAT, stride,
961 (GLubyte *) pointer + voffset );
962 }
963
964
965 void GLAPIENTRY
966 _mesa_LockArraysEXT(GLint first, GLsizei count)
967 {
968 GET_CURRENT_CONTEXT(ctx);
969 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx);
970
971 if (MESA_VERBOSE & VERBOSE_API)
972 _mesa_debug(ctx, "glLockArrays %d %d\n", first, count);
973
974 if (first < 0) {
975 _mesa_error( ctx, GL_INVALID_VALUE, "glLockArraysEXT(first)" );
976 return;
977 }
978 if (count <= 0) {
979 _mesa_error( ctx, GL_INVALID_VALUE, "glLockArraysEXT(count)" );
980 return;
981 }
982 if (ctx->Array.LockCount != 0) {
983 _mesa_error( ctx, GL_INVALID_OPERATION, "glLockArraysEXT(reentry)" );
984 return;
985 }
986
987 ctx->Array.LockFirst = first;
988 ctx->Array.LockCount = count;
989
990 ctx->NewState |= _NEW_ARRAY;
991 ctx->Array.NewState |= _NEW_ARRAY_ALL;
992
993 if (ctx->Driver.LockArraysEXT)
994 ctx->Driver.LockArraysEXT( ctx, first, count );
995 }
996
997
998 void GLAPIENTRY
999 _mesa_UnlockArraysEXT( void )
1000 {
1001 GET_CURRENT_CONTEXT(ctx);
1002 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx);
1003
1004 if (MESA_VERBOSE & VERBOSE_API)
1005 _mesa_debug(ctx, "glUnlockArrays\n");
1006
1007 if (ctx->Array.LockCount == 0) {
1008 _mesa_error( ctx, GL_INVALID_OPERATION, "glUnlockArraysEXT(reexit)" );
1009 return;
1010 }
1011
1012 ctx->Array.LockFirst = 0;
1013 ctx->Array.LockCount = 0;
1014 ctx->NewState |= _NEW_ARRAY;
1015 ctx->Array.NewState |= _NEW_ARRAY_ALL;
1016
1017 if (ctx->Driver.UnlockArraysEXT)
1018 ctx->Driver.UnlockArraysEXT( ctx );
1019 }
1020
1021
1022 /* GL_EXT_multi_draw_arrays */
1023 /* Somebody forgot to spec the first and count parameters as const! <sigh> */
1024 void GLAPIENTRY
1025 _mesa_MultiDrawArraysEXT( GLenum mode, GLint *first,
1026 GLsizei *count, GLsizei primcount )
1027 {
1028 GET_CURRENT_CONTEXT(ctx);
1029 GLint i;
1030
1031 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx);
1032
1033 for (i = 0; i < primcount; i++) {
1034 if (count[i] > 0) {
1035 CALL_DrawArrays(ctx->Exec, (mode, first[i], count[i]));
1036 }
1037 }
1038 }
1039
1040
1041 /* GL_IBM_multimode_draw_arrays */
1042 void GLAPIENTRY
1043 _mesa_MultiModeDrawArraysIBM( const GLenum * mode, const GLint * first,
1044 const GLsizei * count,
1045 GLsizei primcount, GLint modestride )
1046 {
1047 GET_CURRENT_CONTEXT(ctx);
1048 GLint i;
1049
1050 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx);
1051
1052 for ( i = 0 ; i < primcount ; i++ ) {
1053 if ( count[i] > 0 ) {
1054 GLenum m = *((GLenum *) ((GLubyte *) mode + i * modestride));
1055 CALL_DrawArrays(ctx->Exec, ( m, first[i], count[i] ));
1056 }
1057 }
1058 }
1059
1060
1061 /* GL_IBM_multimode_draw_arrays */
1062 void GLAPIENTRY
1063 _mesa_MultiModeDrawElementsIBM( const GLenum * mode, const GLsizei * count,
1064 GLenum type, const GLvoid * const * indices,
1065 GLsizei primcount, GLint modestride )
1066 {
1067 GET_CURRENT_CONTEXT(ctx);
1068 GLint i;
1069
1070 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx);
1071
1072 /* XXX not sure about ARB_vertex_buffer_object handling here */
1073
1074 for ( i = 0 ; i < primcount ; i++ ) {
1075 if ( count[i] > 0 ) {
1076 GLenum m = *((GLenum *) ((GLubyte *) mode + i * modestride));
1077 CALL_DrawElements(ctx->Exec, ( m, count[i], type, indices[i] ));
1078 }
1079 }
1080 }
1081
1082
1083 /**
1084 * Copy one client vertex array to another.
1085 */
1086 void
1087 _mesa_copy_client_array(GLcontext *ctx,
1088 struct gl_client_array *dst,
1089 struct gl_client_array *src)
1090 {
1091 dst->Size = src->Size;
1092 dst->Type = src->Type;
1093 dst->Format = src->Format;
1094 dst->Stride = src->Stride;
1095 dst->StrideB = src->StrideB;
1096 dst->Ptr = src->Ptr;
1097 dst->Enabled = src->Enabled;
1098 dst->Normalized = src->Normalized;
1099 dst->_ElementSize = src->_ElementSize;
1100 _mesa_reference_buffer_object(ctx, &dst->BufferObj, src->BufferObj);
1101 dst->_MaxElement = src->_MaxElement;
1102 }
1103
1104
1105
1106 /**
1107 * Print vertex array's fields.
1108 */
1109 static void
1110 print_array(const char *name, GLint index, const struct gl_client_array *array)
1111 {
1112 if (index >= 0)
1113 _mesa_printf(" %s[%d]: ", name, index);
1114 else
1115 _mesa_printf(" %s: ", name);
1116 _mesa_printf("Ptr=%p, Type=0x%x, Size=%d, ElemSize=%u, Stride=%d, Buffer=%u(Size %u), MaxElem=%u\n",
1117 array->Ptr, array->Type, array->Size,
1118 array->_ElementSize, array->StrideB,
1119 array->BufferObj->Name, array->BufferObj->Size,
1120 array->_MaxElement);
1121 }
1122
1123
1124 /**
1125 * Print current vertex object/array info. For debug.
1126 */
1127 void
1128 _mesa_print_arrays(GLcontext *ctx)
1129 {
1130 struct gl_array_object *arrayObj = ctx->Array.ArrayObj;
1131 GLuint i;
1132
1133 _mesa_update_array_object_max_element(ctx, arrayObj);
1134
1135 _mesa_printf("Array Object %u\n", arrayObj->Name);
1136 if (arrayObj->Vertex.Enabled)
1137 print_array("Vertex", -1, &arrayObj->Vertex);
1138 if (arrayObj->Normal.Enabled)
1139 print_array("Normal", -1, &arrayObj->Normal);
1140 if (arrayObj->Color.Enabled)
1141 print_array("Color", -1, &arrayObj->Color);
1142 for (i = 0; i < Elements(arrayObj->TexCoord); i++)
1143 if (arrayObj->TexCoord[i].Enabled)
1144 print_array("TexCoord", i, &arrayObj->TexCoord[i]);
1145 for (i = 0; i < Elements(arrayObj->VertexAttrib); i++)
1146 if (arrayObj->VertexAttrib[i].Enabled)
1147 print_array("Attrib", i, &arrayObj->VertexAttrib[i]);
1148 _mesa_printf(" _MaxElement = %u\n", arrayObj->_MaxElement);
1149 }
1150
1151
1152 /**
1153 * Initialize vertex array state for given context.
1154 */
1155 void
1156 _mesa_init_varray(GLcontext *ctx)
1157 {
1158 ctx->Array.DefaultArrayObj = _mesa_new_array_object(ctx, 0);
1159 _mesa_reference_array_object(ctx, &ctx->Array.ArrayObj,
1160 ctx->Array.DefaultArrayObj);
1161 ctx->Array.ActiveTexture = 0; /* GL_ARB_multitexture */
1162
1163 ctx->Array.Objects = _mesa_NewHashTable();
1164 }
1165
1166
1167 /**
1168 * Callback for deleting an array object. Called by _mesa_HashDeleteAll().
1169 */
1170 static void
1171 delete_arrayobj_cb(GLuint id, void *data, void *userData)
1172 {
1173 struct gl_array_object *arrayObj = (struct gl_array_object *) data;
1174 GLcontext *ctx = (GLcontext *) userData;
1175 _mesa_delete_array_object(ctx, arrayObj);
1176 }
1177
1178
1179 /**
1180 * Free vertex array state for given context.
1181 */
1182 void
1183 _mesa_free_varray_data(GLcontext *ctx)
1184 {
1185 _mesa_HashDeleteAll(ctx->Array.Objects, delete_arrayobj_cb, ctx);
1186 _mesa_DeleteHashTable(ctx->Array.Objects);
1187 }