mesa: add gl_client_array::Integer field and related vertex array state code
[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 "macros.h"
35 #include "mtypes.h"
36 #include "varray.h"
37 #include "arrayobj.h"
38 #include "main/dispatch.h"
39
40
41 /**
42 * Set the fields of a vertex array.
43 * Also do an error check for GL_ARB_vertex_array_object: check that
44 * all arrays reside in VBOs when using a vertex array object.
45 *
46 * \param array the array to update
47 * \param dirtyBit which bit to set in ctx->Array.NewState for this array
48 * \param elementSize size of each array element, in bytes
49 * \param size components per element (1, 2, 3 or 4)
50 * \param type datatype of each component (GL_FLOAT, GL_INT, etc)
51 * \param format either GL_RGBA or GL_BGRA
52 * \param stride stride between elements, in elements
53 * \param normalized are integer types converted to floats in [-1, 1]?
54 * \param integer integer-valued values (will not be normalized to [-1,1])
55 * \param ptr the address (or offset inside VBO) of the array data
56 */
57 static void
58 update_array(struct gl_context *ctx, struct gl_client_array *array,
59 GLbitfield dirtyBit, GLsizei elementSize,
60 GLint size, GLenum type, GLenum format,
61 GLsizei stride, GLboolean normalized, GLboolean integer,
62 const GLvoid *ptr)
63 {
64 ASSERT(format == GL_RGBA || format == GL_BGRA);
65
66 if (ctx->Array.ArrayObj->VBOonly &&
67 ctx->Array.ArrayBufferObj->Name == 0) {
68 /* GL_ARB_vertex_array_object requires that all arrays reside in VBOs.
69 * Generate GL_INVALID_OPERATION if that's not true.
70 */
71 _mesa_error(ctx, GL_INVALID_OPERATION,
72 "glVertex/Normal/EtcPointer(non-VBO array)");
73 return;
74 }
75
76 array->Size = size;
77 array->Type = type;
78 array->Format = format;
79 array->Stride = stride;
80 array->StrideB = stride ? stride : elementSize;
81 array->Normalized = normalized;
82 array->Ptr = (const GLubyte *) ptr;
83 array->_ElementSize = elementSize;
84
85 _mesa_reference_buffer_object(ctx, &array->BufferObj,
86 ctx->Array.ArrayBufferObj);
87
88 ctx->NewState |= _NEW_ARRAY;
89 ctx->Array.NewState |= dirtyBit;
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 case GL_HALF_FLOAT:
128 elementSize = size * sizeof(GLhalfARB);
129 break;
130 #if FEATURE_fixedpt
131 case GL_FIXED:
132 elementSize = size * sizeof(GLfixed);
133 break;
134 #endif
135 #if FEATURE_vertex_array_byte
136 case GL_BYTE:
137 elementSize = size * sizeof(GLbyte);
138 break;
139 #endif
140 default:
141 _mesa_error( ctx, GL_INVALID_ENUM, "glVertexPointer(type=%s)",
142 _mesa_lookup_enum_by_nr(type));
143 return;
144 }
145
146 update_array(ctx, &ctx->Array.ArrayObj->Vertex, _NEW_ARRAY_VERTEX,
147 elementSize, size, type, GL_RGBA, stride, GL_FALSE,
148 GL_FALSE, 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 case GL_HALF_FLOAT:
185 elementSize = 3 * sizeof(GLhalfARB);
186 break;
187 #if FEATURE_fixedpt
188 case GL_FIXED:
189 elementSize = 3 * sizeof(GLfixed);
190 break;
191 #endif
192 default:
193 _mesa_error( ctx, GL_INVALID_ENUM, "glNormalPointer(type=%s)",
194 _mesa_lookup_enum_by_nr(type));
195 return;
196 }
197
198 update_array(ctx, &ctx->Array.ArrayObj->Normal, _NEW_ARRAY_NORMAL,
199 elementSize, 3, type, GL_RGBA, stride, GL_TRUE, GL_FALSE, ptr);
200 }
201
202
203 void GLAPIENTRY
204 _mesa_ColorPointer(GLint size, GLenum type, GLsizei stride, const GLvoid *ptr)
205 {
206 GLsizei elementSize;
207 GLenum format;
208 GET_CURRENT_CONTEXT(ctx);
209 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx);
210
211 if (size < 3 || size > 4) {
212 if (!ctx->Extensions.EXT_vertex_array_bgra || size != GL_BGRA) {
213 _mesa_error(ctx, GL_INVALID_VALUE, "glColorPointer(size)");
214 return;
215 }
216 }
217 if (stride < 0) {
218 _mesa_error( ctx, GL_INVALID_VALUE, "glColorPointer(stride)" );
219 return;
220 }
221
222 if (MESA_VERBOSE&(VERBOSE_VARRAY|VERBOSE_API))
223 _mesa_debug(ctx, "glColorPointer( sz %d type %s stride %d )\n", size,
224 _mesa_lookup_enum_by_nr( type ), stride);
225
226 if (size == GL_BGRA) {
227 if (type != GL_UNSIGNED_BYTE) {
228 _mesa_error(ctx, GL_INVALID_VALUE, "glColorPointer(GL_BGRA/GLubyte)");
229 return;
230 }
231 format = GL_BGRA;
232 size = 4;
233 }
234 else {
235 format = GL_RGBA;
236 }
237
238 switch (type) {
239 case GL_BYTE:
240 elementSize = size * sizeof(GLbyte);
241 break;
242 case GL_UNSIGNED_BYTE:
243 elementSize = size * sizeof(GLubyte);
244 break;
245 case GL_SHORT:
246 elementSize = size * sizeof(GLshort);
247 break;
248 case GL_UNSIGNED_SHORT:
249 elementSize = size * sizeof(GLushort);
250 break;
251 case GL_INT:
252 elementSize = size * sizeof(GLint);
253 break;
254 case GL_UNSIGNED_INT:
255 elementSize = size * sizeof(GLuint);
256 break;
257 case GL_FLOAT:
258 elementSize = size * sizeof(GLfloat);
259 break;
260 case GL_DOUBLE:
261 elementSize = size * sizeof(GLdouble);
262 break;
263 case GL_HALF_FLOAT:
264 elementSize = size * sizeof(GLhalfARB);
265 break;
266 #if FEATURE_fixedpt
267 case GL_FIXED:
268 elementSize = size * sizeof(GLfixed);
269 break;
270 #endif
271 default:
272 _mesa_error( ctx, GL_INVALID_ENUM, "glColorPointer(type=%s)",
273 _mesa_lookup_enum_by_nr(type));
274 return;
275 }
276
277 update_array(ctx, &ctx->Array.ArrayObj->Color, _NEW_ARRAY_COLOR0,
278 elementSize, size, type, format, stride, GL_TRUE, GL_FALSE,
279 ptr);
280 }
281
282
283 void GLAPIENTRY
284 _mesa_FogCoordPointerEXT(GLenum type, GLsizei stride, const GLvoid *ptr)
285 {
286 GLint elementSize;
287 GET_CURRENT_CONTEXT(ctx);
288 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx);
289
290 if (stride < 0) {
291 _mesa_error( ctx, GL_INVALID_VALUE, "glFogCoordPointer(stride)" );
292 return;
293 }
294
295 switch (type) {
296 case GL_FLOAT:
297 elementSize = sizeof(GLfloat);
298 break;
299 case GL_DOUBLE:
300 elementSize = sizeof(GLdouble);
301 break;
302 case GL_HALF_FLOAT:
303 elementSize = sizeof(GLhalfARB);
304 break;
305 default:
306 _mesa_error( ctx, GL_INVALID_ENUM, "glFogCoordPointer(type)" );
307 return;
308 }
309
310 update_array(ctx, &ctx->Array.ArrayObj->FogCoord, _NEW_ARRAY_FOGCOORD,
311 elementSize, 1, type, GL_RGBA, stride, GL_FALSE, GL_FALSE,
312 ptr);
313 }
314
315
316 void GLAPIENTRY
317 _mesa_IndexPointer(GLenum type, GLsizei stride, const GLvoid *ptr)
318 {
319 GLsizei elementSize;
320 GET_CURRENT_CONTEXT(ctx);
321 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx);
322
323 if (stride < 0) {
324 _mesa_error( ctx, GL_INVALID_VALUE, "glIndexPointer(stride)" );
325 return;
326 }
327
328 switch (type) {
329 case GL_UNSIGNED_BYTE:
330 elementSize = sizeof(GLubyte);
331 break;
332 case GL_SHORT:
333 elementSize = sizeof(GLshort);
334 break;
335 case GL_INT:
336 elementSize = sizeof(GLint);
337 break;
338 case GL_FLOAT:
339 elementSize = sizeof(GLfloat);
340 break;
341 case GL_DOUBLE:
342 elementSize = sizeof(GLdouble);
343 break;
344 default:
345 _mesa_error( ctx, GL_INVALID_ENUM, "glIndexPointer(type)" );
346 return;
347 }
348
349 update_array(ctx, &ctx->Array.ArrayObj->Index, _NEW_ARRAY_INDEX,
350 elementSize, 1, type, GL_RGBA, stride, GL_FALSE, GL_FALSE,
351 ptr);
352 }
353
354
355 void GLAPIENTRY
356 _mesa_SecondaryColorPointerEXT(GLint size, GLenum type,
357 GLsizei stride, const GLvoid *ptr)
358 {
359 GLsizei elementSize;
360 GLenum format;
361 GET_CURRENT_CONTEXT(ctx);
362 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx);
363
364 if (size != 3 && size != 4) {
365 if (!ctx->Extensions.EXT_vertex_array_bgra || size != GL_BGRA) {
366 _mesa_error(ctx, GL_INVALID_VALUE, "glSecondaryColorPointer(size)");
367 return;
368 }
369 }
370 if (stride < 0) {
371 _mesa_error( ctx, GL_INVALID_VALUE, "glSecondaryColorPointer(stride)" );
372 return;
373 }
374
375 if (MESA_VERBOSE&(VERBOSE_VARRAY|VERBOSE_API))
376 _mesa_debug(ctx, "glSecondaryColorPointer( sz %d type %s stride %d )\n",
377 size, _mesa_lookup_enum_by_nr( type ), stride);
378
379 if (size == GL_BGRA) {
380 if (type != GL_UNSIGNED_BYTE) {
381 _mesa_error(ctx, GL_INVALID_VALUE, "glColorPointer(GL_BGRA/GLubyte)");
382 return;
383 }
384 format = GL_BGRA;
385 size = 4;
386 }
387 else {
388 format = GL_RGBA;
389 }
390
391 switch (type) {
392 case GL_BYTE:
393 elementSize = size * sizeof(GLbyte);
394 break;
395 case GL_UNSIGNED_BYTE:
396 elementSize = size * sizeof(GLubyte);
397 break;
398 case GL_SHORT:
399 elementSize = size * sizeof(GLshort);
400 break;
401 case GL_UNSIGNED_SHORT:
402 elementSize = size * sizeof(GLushort);
403 break;
404 case GL_INT:
405 elementSize = size * sizeof(GLint);
406 break;
407 case GL_UNSIGNED_INT:
408 elementSize = size * sizeof(GLuint);
409 break;
410 case GL_FLOAT:
411 elementSize = size * sizeof(GLfloat);
412 break;
413 case GL_DOUBLE:
414 elementSize = size * sizeof(GLdouble);
415 break;
416 case GL_HALF_FLOAT:
417 elementSize = size * sizeof(GLhalfARB);
418 break;
419 default:
420 _mesa_error( ctx, GL_INVALID_ENUM, "glSecondaryColorPointer(type=%s)",
421 _mesa_lookup_enum_by_nr(type));
422 return;
423 }
424
425 update_array(ctx, &ctx->Array.ArrayObj->SecondaryColor, _NEW_ARRAY_COLOR1,
426 elementSize, size, type, format, stride, GL_TRUE, GL_FALSE,
427 ptr);
428 }
429
430
431 void GLAPIENTRY
432 _mesa_TexCoordPointer(GLint size, GLenum type, GLsizei stride,
433 const GLvoid *ptr)
434 {
435 GLint elementSize;
436 GET_CURRENT_CONTEXT(ctx);
437 const GLuint unit = ctx->Array.ActiveTexture;
438 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx);
439
440 if (size < 1 || size > 4) {
441 _mesa_error( ctx, GL_INVALID_VALUE, "glTexCoordPointer(size)" );
442 return;
443 }
444 if (stride < 0) {
445 _mesa_error( ctx, GL_INVALID_VALUE, "glTexCoordPointer(stride)" );
446 return;
447 }
448
449 if (MESA_VERBOSE&(VERBOSE_VARRAY|VERBOSE_API))
450 _mesa_debug(ctx, "glTexCoordPointer(unit %u sz %d type %s stride %d)\n",
451 unit, size, _mesa_lookup_enum_by_nr( type ), stride);
452
453 /* always need to check that <type> is legal */
454 switch (type) {
455 case GL_SHORT:
456 elementSize = size * sizeof(GLshort);
457 break;
458 case GL_INT:
459 elementSize = size * sizeof(GLint);
460 break;
461 case GL_FLOAT:
462 elementSize = size * sizeof(GLfloat);
463 break;
464 case GL_DOUBLE:
465 elementSize = size * sizeof(GLdouble);
466 break;
467 case GL_HALF_FLOAT:
468 elementSize = size * sizeof(GLhalfARB);
469 break;
470 #if FEATURE_fixedpt
471 case GL_FIXED:
472 elementSize = size * sizeof(GLfixed);
473 break;
474 #endif
475 #if FEATURE_vertex_array_byte
476 case GL_BYTE:
477 elementSize = size * sizeof(GLbyte);
478 break;
479 #endif
480 default:
481 _mesa_error( ctx, GL_INVALID_ENUM, "glTexCoordPointer(type=%s)",
482 _mesa_lookup_enum_by_nr(type));
483 return;
484 }
485
486 ASSERT(unit < Elements(ctx->Array.ArrayObj->TexCoord));
487
488 update_array(ctx, &ctx->Array.ArrayObj->TexCoord[unit],
489 _NEW_ARRAY_TEXCOORD(unit),
490 elementSize, size, type, GL_RGBA, stride, GL_FALSE, GL_FALSE,
491 ptr);
492 }
493
494
495 void GLAPIENTRY
496 _mesa_EdgeFlagPointer(GLsizei stride, const GLvoid *ptr)
497 {
498 /* see table 2.4 edits in GL_EXT_gpu_shader4 spec: */
499 const GLboolean integer = GL_TRUE;
500 GET_CURRENT_CONTEXT(ctx);
501 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx);
502
503 if (stride < 0) {
504 _mesa_error( ctx, GL_INVALID_VALUE, "glEdgeFlagPointer(stride)" );
505 return;
506 }
507
508 update_array(ctx, &ctx->Array.ArrayObj->EdgeFlag, _NEW_ARRAY_EDGEFLAG,
509 sizeof(GLboolean), 1, GL_UNSIGNED_BYTE, GL_RGBA,
510 stride, GL_FALSE, integer, ptr);
511 }
512
513
514 void GLAPIENTRY
515 _mesa_PointSizePointer(GLenum type, GLsizei stride, const GLvoid *ptr)
516 {
517 GLsizei elementSize;
518 GET_CURRENT_CONTEXT(ctx);
519 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx);
520
521 if (stride < 0) {
522 _mesa_error( ctx, GL_INVALID_VALUE, "glPointSizePointer(stride)" );
523 return;
524 }
525
526 switch (type) {
527 case GL_FLOAT:
528 elementSize = sizeof(GLfloat);
529 break;
530 #if FEATURE_fixedpt
531 case GL_FIXED:
532 elementSize = sizeof(GLfixed);
533 break;
534 #endif
535 default:
536 _mesa_error( ctx, GL_INVALID_ENUM, "glPointSizePointer(type)" );
537 return;
538 }
539
540 update_array(ctx, &ctx->Array.ArrayObj->PointSize, _NEW_ARRAY_POINT_SIZE,
541 elementSize, 1, type, GL_RGBA, stride, GL_FALSE, GL_FALSE,
542 ptr);
543 }
544
545
546 #if FEATURE_NV_vertex_program
547 /**
548 * Set a vertex attribute array.
549 * Note that these arrays DO alias the conventional GL vertex arrays
550 * (position, normal, color, fog, texcoord, etc).
551 * The generic attribute slots at #16 and above are not touched.
552 */
553 void GLAPIENTRY
554 _mesa_VertexAttribPointerNV(GLuint index, GLint size, GLenum type,
555 GLsizei stride, const GLvoid *ptr)
556 {
557 GLboolean normalized = GL_FALSE;
558 GLsizei elementSize;
559 GLenum format;
560 GET_CURRENT_CONTEXT(ctx);
561 ASSERT_OUTSIDE_BEGIN_END(ctx);
562
563 if (index >= MAX_NV_VERTEX_PROGRAM_INPUTS) {
564 _mesa_error(ctx, GL_INVALID_VALUE, "glVertexAttribPointerNV(index)");
565 return;
566 }
567
568 if (size < 1 || size > 4) {
569 _mesa_error(ctx, GL_INVALID_VALUE, "glVertexAttribPointerNV(size)");
570 return;
571 }
572
573 if (stride < 0) {
574 _mesa_error(ctx, GL_INVALID_VALUE, "glVertexAttribPointerNV(stride)");
575 return;
576 }
577
578 if (type == GL_UNSIGNED_BYTE && size != 4) {
579 _mesa_error(ctx, GL_INVALID_VALUE, "glVertexAttribPointerNV(size!=4)");
580 return;
581 }
582
583 if (size == GL_BGRA) {
584 if (type != GL_UNSIGNED_BYTE) {
585 _mesa_error(ctx, GL_INVALID_VALUE,
586 "glVertexAttribPointerNV(GL_BGRA/type)");
587 return;
588 }
589
590 format = GL_BGRA;
591 size = 4;
592 normalized = GL_TRUE;
593 }
594 else {
595 format = GL_RGBA;
596 }
597
598 /* check for valid 'type' and compute StrideB right away */
599 switch (type) {
600 case GL_UNSIGNED_BYTE:
601 normalized = GL_TRUE;
602 elementSize = size * sizeof(GLubyte);
603 break;
604 case GL_SHORT:
605 elementSize = size * sizeof(GLshort);
606 break;
607 case GL_FLOAT:
608 elementSize = size * sizeof(GLfloat);
609 break;
610 case GL_DOUBLE:
611 elementSize = size * sizeof(GLdouble);
612 break;
613 default:
614 _mesa_error( ctx, GL_INVALID_ENUM, "glVertexAttribPointerNV(type=%s)",
615 _mesa_lookup_enum_by_nr(type));
616 return;
617 }
618
619 update_array(ctx, &ctx->Array.ArrayObj->VertexAttrib[index],
620 _NEW_ARRAY_ATTRIB(index),
621 elementSize, size, type, format, stride, normalized, GL_FALSE,
622 ptr);
623 }
624 #endif
625
626
627 #if FEATURE_ARB_vertex_program
628 /**
629 * Set a generic vertex attribute array.
630 * Note that these arrays DO NOT alias the conventional GL vertex arrays
631 * (position, normal, color, fog, texcoord, etc).
632 */
633 void GLAPIENTRY
634 _mesa_VertexAttribPointerARB(GLuint index, GLint size, GLenum type,
635 GLboolean normalized,
636 GLsizei stride, const GLvoid *ptr)
637 {
638 GLsizei elementSize;
639 GLenum format;
640 GET_CURRENT_CONTEXT(ctx);
641 ASSERT_OUTSIDE_BEGIN_END(ctx);
642
643 if (index >= ctx->Const.VertexProgram.MaxAttribs) {
644 _mesa_error(ctx, GL_INVALID_VALUE, "glVertexAttribPointerARB(index)");
645 return;
646 }
647
648 if (size < 1 || size > 4) {
649 if (!ctx->Extensions.EXT_vertex_array_bgra || size != GL_BGRA) {
650 _mesa_error(ctx, GL_INVALID_VALUE, "glVertexAttribPointerARB(size)");
651 return;
652 }
653 }
654
655 if (stride < 0) {
656 _mesa_error(ctx, GL_INVALID_VALUE, "glVertexAttribPointerARB(stride)");
657 return;
658 }
659
660 if (size == GL_BGRA) {
661 if (type != GL_UNSIGNED_BYTE) {
662 _mesa_error(ctx, GL_INVALID_VALUE,
663 "glVertexAttribPointerARB(GL_BGRA/type)");
664 return;
665 }
666 if (normalized != GL_TRUE) {
667 _mesa_error(ctx, GL_INVALID_VALUE,
668 "glVertexAttribPointerARB(GL_BGRA/normalized)");
669 return;
670 }
671
672 format = GL_BGRA;
673 size = 4;
674 }
675 else {
676 format = GL_RGBA;
677 }
678
679 /* check for valid 'type' and compute StrideB right away */
680 /* NOTE: more types are supported here than in the NV extension */
681 switch (type) {
682 case GL_BYTE:
683 elementSize = size * sizeof(GLbyte);
684 break;
685 case GL_UNSIGNED_BYTE:
686 elementSize = size * sizeof(GLubyte);
687 break;
688 case GL_SHORT:
689 elementSize = size * sizeof(GLshort);
690 break;
691 case GL_UNSIGNED_SHORT:
692 elementSize = size * sizeof(GLushort);
693 break;
694 case GL_INT:
695 elementSize = size * sizeof(GLint);
696 break;
697 case GL_UNSIGNED_INT:
698 elementSize = size * sizeof(GLuint);
699 break;
700 case GL_FLOAT:
701 elementSize = size * sizeof(GLfloat);
702 break;
703 case GL_DOUBLE:
704 elementSize = size * sizeof(GLdouble);
705 break;
706 case GL_HALF_FLOAT:
707 elementSize = size * sizeof(GLhalfARB);
708 break;
709 #if FEATURE_fixedpt
710 case GL_FIXED:
711 elementSize = size * sizeof(GLfixed);
712 break;
713 #endif
714 default:
715 _mesa_error( ctx, GL_INVALID_ENUM, "glVertexAttribPointerARB(type)" );
716 return;
717 }
718
719 update_array(ctx, &ctx->Array.ArrayObj->VertexAttrib[index],
720 _NEW_ARRAY_ATTRIB(index),
721 elementSize, size, type, format, stride, normalized, GL_FALSE,
722 ptr);
723 }
724 #endif
725
726
727 /**
728 * GL_EXT_gpu_shader4 / GL 3.0.
729 * Set an integer-valued vertex attribute array.
730 * Note that these arrays DO NOT alias the conventional GL vertex arrays
731 * (position, normal, color, fog, texcoord, etc).
732 */
733 void GLAPIENTRY
734 _mesa_VertexAttribIPointer(GLuint index, GLint size, GLenum type,
735 GLsizei stride, const GLvoid *ptr)
736 {
737 const GLboolean normalized = GL_FALSE;
738 const GLboolean integer = GL_TRUE;
739 const GLenum format = GL_RGBA;
740 GLsizei elementSize;
741 GET_CURRENT_CONTEXT(ctx);
742 ASSERT_OUTSIDE_BEGIN_END(ctx);
743
744 if (index >= ctx->Const.VertexProgram.MaxAttribs) {
745 _mesa_error(ctx, GL_INVALID_VALUE, "glVertexAttribIPointer(index)");
746 return;
747 }
748
749 if (size < 1 || size > 4) {
750 if (!ctx->Extensions.EXT_vertex_array_bgra || size != GL_BGRA) {
751 _mesa_error(ctx, GL_INVALID_VALUE, "glVertexAttribIPointer(size)");
752 return;
753 }
754 }
755
756 if (stride < 0) {
757 _mesa_error(ctx, GL_INVALID_VALUE, "glVertexAttribIPointer(stride)");
758 return;
759 }
760
761 /* check for valid 'type' and compute StrideB right away */
762 /* NOTE: more types are supported here than in the NV extension */
763 switch (type) {
764 case GL_BYTE:
765 elementSize = size * sizeof(GLbyte);
766 break;
767 case GL_UNSIGNED_BYTE:
768 elementSize = size * sizeof(GLubyte);
769 break;
770 case GL_SHORT:
771 elementSize = size * sizeof(GLshort);
772 break;
773 case GL_UNSIGNED_SHORT:
774 elementSize = size * sizeof(GLushort);
775 break;
776 case GL_INT:
777 elementSize = size * sizeof(GLint);
778 break;
779 case GL_UNSIGNED_INT:
780 elementSize = size * sizeof(GLuint);
781 break;
782 default:
783 _mesa_error( ctx, GL_INVALID_ENUM, "glVertexAttribIPointer(type)" );
784 return;
785 }
786
787 update_array(ctx, &ctx->Array.ArrayObj->VertexAttrib[index],
788 _NEW_ARRAY_ATTRIB(index),
789 elementSize, size, type, format, stride,
790 normalized, integer, ptr);
791 }
792
793
794
795 void GLAPIENTRY
796 _mesa_EnableVertexAttribArrayARB(GLuint index)
797 {
798 GET_CURRENT_CONTEXT(ctx);
799 ASSERT_OUTSIDE_BEGIN_END(ctx);
800
801 if (index >= ctx->Const.VertexProgram.MaxAttribs) {
802 _mesa_error(ctx, GL_INVALID_VALUE,
803 "glEnableVertexAttribArrayARB(index)");
804 return;
805 }
806
807 ASSERT(index < Elements(ctx->Array.ArrayObj->VertexAttrib));
808
809 FLUSH_VERTICES(ctx, _NEW_ARRAY);
810 ctx->Array.ArrayObj->VertexAttrib[index].Enabled = GL_TRUE;
811 ctx->Array.ArrayObj->_Enabled |= _NEW_ARRAY_ATTRIB(index);
812 ctx->Array.NewState |= _NEW_ARRAY_ATTRIB(index);
813 }
814
815
816 void GLAPIENTRY
817 _mesa_DisableVertexAttribArrayARB(GLuint index)
818 {
819 GET_CURRENT_CONTEXT(ctx);
820 ASSERT_OUTSIDE_BEGIN_END(ctx);
821
822 if (index >= ctx->Const.VertexProgram.MaxAttribs) {
823 _mesa_error(ctx, GL_INVALID_VALUE,
824 "glEnableVertexAttribArrayARB(index)");
825 return;
826 }
827
828 ASSERT(index < Elements(ctx->Array.ArrayObj->VertexAttrib));
829
830 FLUSH_VERTICES(ctx, _NEW_ARRAY);
831 ctx->Array.ArrayObj->VertexAttrib[index].Enabled = GL_FALSE;
832 ctx->Array.ArrayObj->_Enabled &= ~_NEW_ARRAY_ATTRIB(index);
833 ctx->Array.NewState |= _NEW_ARRAY_ATTRIB(index);
834 }
835
836
837 /**
838 * Return info for a vertex attribute array (no alias with legacy
839 * vertex attributes (pos, normal, color, etc)). This function does
840 * not handle the 4-element GL_CURRENT_VERTEX_ATTRIB_ARB query.
841 */
842 static GLuint
843 get_vertex_array_attrib(struct gl_context *ctx, GLuint index, GLenum pname,
844 const char *caller)
845 {
846 const struct gl_client_array *array;
847
848 if (index >= MAX_VERTEX_GENERIC_ATTRIBS) {
849 _mesa_error(ctx, GL_INVALID_VALUE, "%s(index=%u)", caller, index);
850 return 0;
851 }
852
853 ASSERT(index < Elements(ctx->Array.ArrayObj->VertexAttrib));
854
855 array = &ctx->Array.ArrayObj->VertexAttrib[index];
856
857 switch (pname) {
858 case GL_VERTEX_ATTRIB_ARRAY_ENABLED_ARB:
859 return array->Enabled;
860 case GL_VERTEX_ATTRIB_ARRAY_SIZE_ARB:
861 return array->Size;
862 case GL_VERTEX_ATTRIB_ARRAY_STRIDE_ARB:
863 return array->Stride;
864 case GL_VERTEX_ATTRIB_ARRAY_TYPE_ARB:
865 return array->Type;
866 case GL_VERTEX_ATTRIB_ARRAY_NORMALIZED_ARB:
867 return array->Normalized;
868 case GL_VERTEX_ATTRIB_ARRAY_BUFFER_BINDING_ARB:
869 return array->BufferObj->Name;
870 case GL_VERTEX_ATTRIB_ARRAY_INTEGER:
871 if (ctx->Extensions.EXT_gpu_shader4) {
872 return array->Integer;
873 }
874 /* fall-through */
875 default:
876 _mesa_error(ctx, GL_INVALID_ENUM, "%s(pname=0x%x)", caller, pname);
877 return 0;
878 }
879 }
880
881
882 void GLAPIENTRY
883 _mesa_GetVertexAttribfvARB(GLuint index, GLenum pname, GLfloat *params)
884 {
885 GET_CURRENT_CONTEXT(ctx);
886 ASSERT_OUTSIDE_BEGIN_END(ctx);
887
888 if (pname == GL_CURRENT_VERTEX_ATTRIB_ARB) {
889 if (index == 0) {
890 _mesa_error(ctx, GL_INVALID_OPERATION,
891 "glGetVertexAttribfv(index==0)");
892 }
893 else {
894 const GLfloat *v = ctx->Current.Attrib[VERT_ATTRIB_GENERIC0 + index];
895 FLUSH_CURRENT(ctx, 0);
896 COPY_4V(params, v);
897 }
898 }
899 else {
900 params[0] = (GLfloat) get_vertex_array_attrib(ctx, index, pname,
901 "glGetVertexAttribfv");
902 }
903 }
904
905
906 void GLAPIENTRY
907 _mesa_GetVertexAttribdvARB(GLuint index, GLenum pname, GLdouble *params)
908 {
909 GET_CURRENT_CONTEXT(ctx);
910 ASSERT_OUTSIDE_BEGIN_END(ctx);
911
912 if (pname == GL_CURRENT_VERTEX_ATTRIB_ARB) {
913 if (index == 0) {
914 _mesa_error(ctx, GL_INVALID_OPERATION,
915 "glGetVertexAttribdv(index==0)");
916 }
917 else {
918 const GLfloat *v = ctx->Current.Attrib[VERT_ATTRIB_GENERIC0 + index];
919 FLUSH_CURRENT(ctx, 0);
920 params[0] = (GLdouble) v[0];
921 params[1] = (GLdouble) v[1];
922 params[2] = (GLdouble) v[2];
923 params[3] = (GLdouble) v[3];
924 }
925 }
926 else {
927 params[0] = (GLdouble) get_vertex_array_attrib(ctx, index, pname,
928 "glGetVertexAttribdv");
929 }
930 }
931
932
933 void GLAPIENTRY
934 _mesa_GetVertexAttribivARB(GLuint index, GLenum pname, GLint *params)
935 {
936 GET_CURRENT_CONTEXT(ctx);
937 ASSERT_OUTSIDE_BEGIN_END(ctx);
938
939 if (pname == GL_CURRENT_VERTEX_ATTRIB_ARB) {
940 if (index == 0) {
941 _mesa_error(ctx, GL_INVALID_OPERATION,
942 "glGetVertexAttribiv(index==0)");
943 }
944 else {
945 const GLfloat *v = ctx->Current.Attrib[VERT_ATTRIB_GENERIC0 + index];
946 FLUSH_CURRENT(ctx, 0);
947 /* XXX should floats in[0,1] be scaled to full int range? */
948 params[0] = (GLint) v[0];
949 params[1] = (GLint) v[1];
950 params[2] = (GLint) v[2];
951 params[3] = (GLint) v[3];
952 }
953 }
954 else {
955 params[0] = (GLint) get_vertex_array_attrib(ctx, index, pname,
956 "glGetVertexAttribiv");
957 }
958 }
959
960
961 /** GL 3.0 */
962 void GLAPIENTRY
963 _mesa_GetVertexAttribIiv(GLuint index, GLenum pname, GLint *params)
964 {
965 GET_CURRENT_CONTEXT(ctx);
966 ASSERT_OUTSIDE_BEGIN_END(ctx);
967
968 if (pname == GL_CURRENT_VERTEX_ATTRIB_ARB) {
969 if (index == 0) {
970 _mesa_error(ctx, GL_INVALID_OPERATION,
971 "glGetVertexAttribIiv(index==0)");
972 }
973 else {
974 const GLfloat *v = ctx->Current.Attrib[VERT_ATTRIB_GENERIC0 + index];
975 FLUSH_CURRENT(ctx, 0);
976 /* XXX we don't have true integer-valued vertex attribs yet */
977 params[0] = (GLint) v[0];
978 params[1] = (GLint) v[1];
979 params[2] = (GLint) v[2];
980 params[3] = (GLint) v[3];
981 }
982 }
983 else {
984 params[0] = (GLint) get_vertex_array_attrib(ctx, index, pname,
985 "glGetVertexAttribIiv");
986 }
987 }
988
989
990 /** GL 3.0 */
991 void GLAPIENTRY
992 _mesa_GetVertexAttribIuiv(GLuint index, GLenum pname, GLuint *params)
993 {
994 GET_CURRENT_CONTEXT(ctx);
995 ASSERT_OUTSIDE_BEGIN_END(ctx);
996
997 if (pname == GL_CURRENT_VERTEX_ATTRIB_ARB) {
998 if (index == 0) {
999 _mesa_error(ctx, GL_INVALID_OPERATION,
1000 "glGetVertexAttribIuiv(index==0)");
1001 }
1002 else {
1003 const GLfloat *v = ctx->Current.Attrib[VERT_ATTRIB_GENERIC0 + index];
1004 FLUSH_CURRENT(ctx, 0);
1005 /* XXX we don't have true integer-valued vertex attribs yet */
1006 params[0] = (GLuint) v[0];
1007 params[1] = (GLuint) v[1];
1008 params[2] = (GLuint) v[2];
1009 params[3] = (GLuint) v[3];
1010 }
1011 }
1012 else {
1013 params[0] = get_vertex_array_attrib(ctx, index, pname,
1014 "glGetVertexAttribIuiv");
1015 }
1016 }
1017
1018
1019 void GLAPIENTRY
1020 _mesa_GetVertexAttribPointervARB(GLuint index, GLenum pname, GLvoid **pointer)
1021 {
1022 GET_CURRENT_CONTEXT(ctx);
1023 ASSERT_OUTSIDE_BEGIN_END(ctx);
1024
1025 if (index >= ctx->Const.VertexProgram.MaxAttribs) {
1026 _mesa_error(ctx, GL_INVALID_VALUE, "glGetVertexAttribPointerARB(index)");
1027 return;
1028 }
1029
1030 if (pname != GL_VERTEX_ATTRIB_ARRAY_POINTER_ARB) {
1031 _mesa_error(ctx, GL_INVALID_ENUM, "glGetVertexAttribPointerARB(pname)");
1032 return;
1033 }
1034
1035 ASSERT(index < Elements(ctx->Array.ArrayObj->VertexAttrib));
1036
1037 *pointer = (GLvoid *) ctx->Array.ArrayObj->VertexAttrib[index].Ptr;
1038 }
1039
1040
1041 void GLAPIENTRY
1042 _mesa_VertexPointerEXT(GLint size, GLenum type, GLsizei stride,
1043 GLsizei count, const GLvoid *ptr)
1044 {
1045 (void) count;
1046 _mesa_VertexPointer(size, type, stride, ptr);
1047 }
1048
1049
1050 void GLAPIENTRY
1051 _mesa_NormalPointerEXT(GLenum type, GLsizei stride, GLsizei count,
1052 const GLvoid *ptr)
1053 {
1054 (void) count;
1055 _mesa_NormalPointer(type, stride, ptr);
1056 }
1057
1058
1059 void GLAPIENTRY
1060 _mesa_ColorPointerEXT(GLint size, GLenum type, GLsizei stride, GLsizei count,
1061 const GLvoid *ptr)
1062 {
1063 (void) count;
1064 _mesa_ColorPointer(size, type, stride, ptr);
1065 }
1066
1067
1068 void GLAPIENTRY
1069 _mesa_IndexPointerEXT(GLenum type, GLsizei stride, GLsizei count,
1070 const GLvoid *ptr)
1071 {
1072 (void) count;
1073 _mesa_IndexPointer(type, stride, ptr);
1074 }
1075
1076
1077 void GLAPIENTRY
1078 _mesa_TexCoordPointerEXT(GLint size, GLenum type, GLsizei stride,
1079 GLsizei count, const GLvoid *ptr)
1080 {
1081 (void) count;
1082 _mesa_TexCoordPointer(size, type, stride, ptr);
1083 }
1084
1085
1086 void GLAPIENTRY
1087 _mesa_EdgeFlagPointerEXT(GLsizei stride, GLsizei count, const GLboolean *ptr)
1088 {
1089 (void) count;
1090 _mesa_EdgeFlagPointer(stride, ptr);
1091 }
1092
1093
1094 void GLAPIENTRY
1095 _mesa_InterleavedArrays(GLenum format, GLsizei stride, const GLvoid *pointer)
1096 {
1097 GET_CURRENT_CONTEXT(ctx);
1098 GLboolean tflag, cflag, nflag; /* enable/disable flags */
1099 GLint tcomps, ccomps, vcomps; /* components per texcoord, color, vertex */
1100 GLenum ctype = 0; /* color type */
1101 GLint coffset = 0, noffset = 0, voffset;/* color, normal, vertex offsets */
1102 const GLint toffset = 0; /* always zero */
1103 GLint defstride; /* default stride */
1104 GLint c, f;
1105
1106 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx);
1107
1108 f = sizeof(GLfloat);
1109 c = f * ((4 * sizeof(GLubyte) + (f - 1)) / f);
1110
1111 if (stride < 0) {
1112 _mesa_error( ctx, GL_INVALID_VALUE, "glInterleavedArrays(stride)" );
1113 return;
1114 }
1115
1116 switch (format) {
1117 case GL_V2F:
1118 tflag = GL_FALSE; cflag = GL_FALSE; nflag = GL_FALSE;
1119 tcomps = 0; ccomps = 0; vcomps = 2;
1120 voffset = 0;
1121 defstride = 2*f;
1122 break;
1123 case GL_V3F:
1124 tflag = GL_FALSE; cflag = GL_FALSE; nflag = GL_FALSE;
1125 tcomps = 0; ccomps = 0; vcomps = 3;
1126 voffset = 0;
1127 defstride = 3*f;
1128 break;
1129 case GL_C4UB_V2F:
1130 tflag = GL_FALSE; cflag = GL_TRUE; nflag = GL_FALSE;
1131 tcomps = 0; ccomps = 4; vcomps = 2;
1132 ctype = GL_UNSIGNED_BYTE;
1133 coffset = 0;
1134 voffset = c;
1135 defstride = c + 2*f;
1136 break;
1137 case GL_C4UB_V3F:
1138 tflag = GL_FALSE; cflag = GL_TRUE; nflag = GL_FALSE;
1139 tcomps = 0; ccomps = 4; vcomps = 3;
1140 ctype = GL_UNSIGNED_BYTE;
1141 coffset = 0;
1142 voffset = c;
1143 defstride = c + 3*f;
1144 break;
1145 case GL_C3F_V3F:
1146 tflag = GL_FALSE; cflag = GL_TRUE; nflag = GL_FALSE;
1147 tcomps = 0; ccomps = 3; vcomps = 3;
1148 ctype = GL_FLOAT;
1149 coffset = 0;
1150 voffset = 3*f;
1151 defstride = 6*f;
1152 break;
1153 case GL_N3F_V3F:
1154 tflag = GL_FALSE; cflag = GL_FALSE; nflag = GL_TRUE;
1155 tcomps = 0; ccomps = 0; vcomps = 3;
1156 noffset = 0;
1157 voffset = 3*f;
1158 defstride = 6*f;
1159 break;
1160 case GL_C4F_N3F_V3F:
1161 tflag = GL_FALSE; cflag = GL_TRUE; nflag = GL_TRUE;
1162 tcomps = 0; ccomps = 4; vcomps = 3;
1163 ctype = GL_FLOAT;
1164 coffset = 0;
1165 noffset = 4*f;
1166 voffset = 7*f;
1167 defstride = 10*f;
1168 break;
1169 case GL_T2F_V3F:
1170 tflag = GL_TRUE; cflag = GL_FALSE; nflag = GL_FALSE;
1171 tcomps = 2; ccomps = 0; vcomps = 3;
1172 voffset = 2*f;
1173 defstride = 5*f;
1174 break;
1175 case GL_T4F_V4F:
1176 tflag = GL_TRUE; cflag = GL_FALSE; nflag = GL_FALSE;
1177 tcomps = 4; ccomps = 0; vcomps = 4;
1178 voffset = 4*f;
1179 defstride = 8*f;
1180 break;
1181 case GL_T2F_C4UB_V3F:
1182 tflag = GL_TRUE; cflag = GL_TRUE; nflag = GL_FALSE;
1183 tcomps = 2; ccomps = 4; vcomps = 3;
1184 ctype = GL_UNSIGNED_BYTE;
1185 coffset = 2*f;
1186 voffset = c+2*f;
1187 defstride = c+5*f;
1188 break;
1189 case GL_T2F_C3F_V3F:
1190 tflag = GL_TRUE; cflag = GL_TRUE; nflag = GL_FALSE;
1191 tcomps = 2; ccomps = 3; vcomps = 3;
1192 ctype = GL_FLOAT;
1193 coffset = 2*f;
1194 voffset = 5*f;
1195 defstride = 8*f;
1196 break;
1197 case GL_T2F_N3F_V3F:
1198 tflag = GL_TRUE; cflag = GL_FALSE; nflag = GL_TRUE;
1199 tcomps = 2; ccomps = 0; vcomps = 3;
1200 noffset = 2*f;
1201 voffset = 5*f;
1202 defstride = 8*f;
1203 break;
1204 case GL_T2F_C4F_N3F_V3F:
1205 tflag = GL_TRUE; cflag = GL_TRUE; nflag = GL_TRUE;
1206 tcomps = 2; ccomps = 4; vcomps = 3;
1207 ctype = GL_FLOAT;
1208 coffset = 2*f;
1209 noffset = 6*f;
1210 voffset = 9*f;
1211 defstride = 12*f;
1212 break;
1213 case GL_T4F_C4F_N3F_V4F:
1214 tflag = GL_TRUE; cflag = GL_TRUE; nflag = GL_TRUE;
1215 tcomps = 4; ccomps = 4; vcomps = 4;
1216 ctype = GL_FLOAT;
1217 coffset = 4*f;
1218 noffset = 8*f;
1219 voffset = 11*f;
1220 defstride = 15*f;
1221 break;
1222 default:
1223 _mesa_error( ctx, GL_INVALID_ENUM, "glInterleavedArrays(format)" );
1224 return;
1225 }
1226
1227 if (stride==0) {
1228 stride = defstride;
1229 }
1230
1231 _mesa_DisableClientState( GL_EDGE_FLAG_ARRAY );
1232 _mesa_DisableClientState( GL_INDEX_ARRAY );
1233 /* XXX also disable secondary color and generic arrays? */
1234
1235 /* Texcoords */
1236 if (tflag) {
1237 _mesa_EnableClientState( GL_TEXTURE_COORD_ARRAY );
1238 _mesa_TexCoordPointer( tcomps, GL_FLOAT, stride,
1239 (GLubyte *) pointer + toffset );
1240 }
1241 else {
1242 _mesa_DisableClientState( GL_TEXTURE_COORD_ARRAY );
1243 }
1244
1245 /* Color */
1246 if (cflag) {
1247 _mesa_EnableClientState( GL_COLOR_ARRAY );
1248 _mesa_ColorPointer( ccomps, ctype, stride,
1249 (GLubyte *) pointer + coffset );
1250 }
1251 else {
1252 _mesa_DisableClientState( GL_COLOR_ARRAY );
1253 }
1254
1255
1256 /* Normals */
1257 if (nflag) {
1258 _mesa_EnableClientState( GL_NORMAL_ARRAY );
1259 _mesa_NormalPointer( GL_FLOAT, stride, (GLubyte *) pointer + noffset );
1260 }
1261 else {
1262 _mesa_DisableClientState( GL_NORMAL_ARRAY );
1263 }
1264
1265 /* Vertices */
1266 _mesa_EnableClientState( GL_VERTEX_ARRAY );
1267 _mesa_VertexPointer( vcomps, GL_FLOAT, stride,
1268 (GLubyte *) pointer + voffset );
1269 }
1270
1271
1272 void GLAPIENTRY
1273 _mesa_LockArraysEXT(GLint first, GLsizei count)
1274 {
1275 GET_CURRENT_CONTEXT(ctx);
1276 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx);
1277
1278 if (MESA_VERBOSE & VERBOSE_API)
1279 _mesa_debug(ctx, "glLockArrays %d %d\n", first, count);
1280
1281 if (first < 0) {
1282 _mesa_error( ctx, GL_INVALID_VALUE, "glLockArraysEXT(first)" );
1283 return;
1284 }
1285 if (count <= 0) {
1286 _mesa_error( ctx, GL_INVALID_VALUE, "glLockArraysEXT(count)" );
1287 return;
1288 }
1289 if (ctx->Array.LockCount != 0) {
1290 _mesa_error( ctx, GL_INVALID_OPERATION, "glLockArraysEXT(reentry)" );
1291 return;
1292 }
1293
1294 ctx->Array.LockFirst = first;
1295 ctx->Array.LockCount = count;
1296
1297 ctx->NewState |= _NEW_ARRAY;
1298 ctx->Array.NewState |= _NEW_ARRAY_ALL;
1299 }
1300
1301
1302 void GLAPIENTRY
1303 _mesa_UnlockArraysEXT( void )
1304 {
1305 GET_CURRENT_CONTEXT(ctx);
1306 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx);
1307
1308 if (MESA_VERBOSE & VERBOSE_API)
1309 _mesa_debug(ctx, "glUnlockArrays\n");
1310
1311 if (ctx->Array.LockCount == 0) {
1312 _mesa_error( ctx, GL_INVALID_OPERATION, "glUnlockArraysEXT(reexit)" );
1313 return;
1314 }
1315
1316 ctx->Array.LockFirst = 0;
1317 ctx->Array.LockCount = 0;
1318 ctx->NewState |= _NEW_ARRAY;
1319 ctx->Array.NewState |= _NEW_ARRAY_ALL;
1320 }
1321
1322
1323 /* GL_EXT_multi_draw_arrays */
1324 /* Somebody forgot to spec the first and count parameters as const! <sigh> */
1325 void GLAPIENTRY
1326 _mesa_MultiDrawArraysEXT( GLenum mode, const GLint *first,
1327 const GLsizei *count, GLsizei primcount )
1328 {
1329 GET_CURRENT_CONTEXT(ctx);
1330 GLint i;
1331
1332 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx);
1333
1334 for (i = 0; i < primcount; i++) {
1335 if (count[i] > 0) {
1336 CALL_DrawArrays(ctx->Exec, (mode, first[i], count[i]));
1337 }
1338 }
1339 }
1340
1341
1342 /* GL_IBM_multimode_draw_arrays */
1343 void GLAPIENTRY
1344 _mesa_MultiModeDrawArraysIBM( const GLenum * mode, const GLint * first,
1345 const GLsizei * count,
1346 GLsizei primcount, GLint modestride )
1347 {
1348 GET_CURRENT_CONTEXT(ctx);
1349 GLint i;
1350
1351 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx);
1352
1353 for ( i = 0 ; i < primcount ; i++ ) {
1354 if ( count[i] > 0 ) {
1355 GLenum m = *((GLenum *) ((GLubyte *) mode + i * modestride));
1356 CALL_DrawArrays(ctx->Exec, ( m, first[i], count[i] ));
1357 }
1358 }
1359 }
1360
1361
1362 /* GL_IBM_multimode_draw_arrays */
1363 void GLAPIENTRY
1364 _mesa_MultiModeDrawElementsIBM( const GLenum * mode, const GLsizei * count,
1365 GLenum type, const GLvoid * const * indices,
1366 GLsizei primcount, GLint modestride )
1367 {
1368 GET_CURRENT_CONTEXT(ctx);
1369 GLint i;
1370
1371 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx);
1372
1373 /* XXX not sure about ARB_vertex_buffer_object handling here */
1374
1375 for ( i = 0 ; i < primcount ; i++ ) {
1376 if ( count[i] > 0 ) {
1377 GLenum m = *((GLenum *) ((GLubyte *) mode + i * modestride));
1378 CALL_DrawElements(ctx->Exec, ( m, count[i], type, indices[i] ));
1379 }
1380 }
1381 }
1382
1383
1384 /**
1385 * GL_NV_primitive_restart and GL 3.1
1386 */
1387 void GLAPIENTRY
1388 _mesa_PrimitiveRestartIndex(GLuint index)
1389 {
1390 GET_CURRENT_CONTEXT(ctx);
1391
1392 if (!ctx->Extensions.NV_primitive_restart &&
1393 ctx->VersionMajor * 10 + ctx->VersionMinor < 31) {
1394 _mesa_error(ctx, GL_INVALID_OPERATION, "glPrimitiveRestartIndexNV()");
1395 return;
1396 }
1397
1398 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx);
1399
1400 FLUSH_VERTICES(ctx, _NEW_TRANSFORM);
1401
1402 ctx->Array.RestartIndex = index;
1403 }
1404
1405
1406 /**
1407 * Copy one client vertex array to another.
1408 */
1409 void
1410 _mesa_copy_client_array(struct gl_context *ctx,
1411 struct gl_client_array *dst,
1412 struct gl_client_array *src)
1413 {
1414 dst->Size = src->Size;
1415 dst->Type = src->Type;
1416 dst->Format = src->Format;
1417 dst->Stride = src->Stride;
1418 dst->StrideB = src->StrideB;
1419 dst->Ptr = src->Ptr;
1420 dst->Enabled = src->Enabled;
1421 dst->Normalized = src->Normalized;
1422 dst->Integer = src->Integer;
1423 dst->_ElementSize = src->_ElementSize;
1424 _mesa_reference_buffer_object(ctx, &dst->BufferObj, src->BufferObj);
1425 dst->_MaxElement = src->_MaxElement;
1426 }
1427
1428
1429
1430 /**
1431 * Print vertex array's fields.
1432 */
1433 static void
1434 print_array(const char *name, GLint index, const struct gl_client_array *array)
1435 {
1436 if (index >= 0)
1437 printf(" %s[%d]: ", name, index);
1438 else
1439 printf(" %s: ", name);
1440 printf("Ptr=%p, Type=0x%x, Size=%d, ElemSize=%u, Stride=%d, Buffer=%u(Size %lu), MaxElem=%u\n",
1441 array->Ptr, array->Type, array->Size,
1442 array->_ElementSize, array->StrideB,
1443 array->BufferObj->Name, (unsigned long) array->BufferObj->Size,
1444 array->_MaxElement);
1445 }
1446
1447
1448 /**
1449 * Print current vertex object/array info. For debug.
1450 */
1451 void
1452 _mesa_print_arrays(struct gl_context *ctx)
1453 {
1454 struct gl_array_object *arrayObj = ctx->Array.ArrayObj;
1455 GLuint i;
1456
1457 _mesa_update_array_object_max_element(ctx, arrayObj);
1458
1459 printf("Array Object %u\n", arrayObj->Name);
1460 if (arrayObj->Vertex.Enabled)
1461 print_array("Vertex", -1, &arrayObj->Vertex);
1462 if (arrayObj->Normal.Enabled)
1463 print_array("Normal", -1, &arrayObj->Normal);
1464 if (arrayObj->Color.Enabled)
1465 print_array("Color", -1, &arrayObj->Color);
1466 for (i = 0; i < Elements(arrayObj->TexCoord); i++)
1467 if (arrayObj->TexCoord[i].Enabled)
1468 print_array("TexCoord", i, &arrayObj->TexCoord[i]);
1469 for (i = 0; i < Elements(arrayObj->VertexAttrib); i++)
1470 if (arrayObj->VertexAttrib[i].Enabled)
1471 print_array("Attrib", i, &arrayObj->VertexAttrib[i]);
1472 printf(" _MaxElement = %u\n", arrayObj->_MaxElement);
1473 }
1474
1475
1476 /**
1477 * Initialize vertex array state for given context.
1478 */
1479 void
1480 _mesa_init_varray(struct gl_context *ctx)
1481 {
1482 ctx->Array.DefaultArrayObj = _mesa_new_array_object(ctx, 0);
1483 _mesa_reference_array_object(ctx, &ctx->Array.ArrayObj,
1484 ctx->Array.DefaultArrayObj);
1485 ctx->Array.ActiveTexture = 0; /* GL_ARB_multitexture */
1486
1487 ctx->Array.Objects = _mesa_NewHashTable();
1488 }
1489
1490
1491 /**
1492 * Callback for deleting an array object. Called by _mesa_HashDeleteAll().
1493 */
1494 static void
1495 delete_arrayobj_cb(GLuint id, void *data, void *userData)
1496 {
1497 struct gl_array_object *arrayObj = (struct gl_array_object *) data;
1498 struct gl_context *ctx = (struct gl_context *) userData;
1499 _mesa_delete_array_object(ctx, arrayObj);
1500 }
1501
1502
1503 /**
1504 * Free vertex array state for given context.
1505 */
1506 void
1507 _mesa_free_varray_data(struct gl_context *ctx)
1508 {
1509 _mesa_HashDeleteAll(ctx->Array.Objects, delete_arrayobj_cb, ctx);
1510 _mesa_DeleteHashTable(ctx->Array.Objects);
1511 }