varray.c revision 3464ebd5
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 "image.h"
35#include "macros.h"
36#include "mfeatures.h"
37#include "mtypes.h"
38#include "varray.h"
39#include "arrayobj.h"
40#include "main/dispatch.h"
41
42
43/** Used to do error checking for GL_EXT_vertex_array_bgra */
44#define BGRA_OR_4  5
45
46
47/** Used to indicate which GL datatypes are accepted by each of the
48 * glVertex/Color/Attrib/EtcPointer() functions.
49 */
50#define BOOL_BIT             0x1
51#define BYTE_BIT             0x2
52#define UNSIGNED_BYTE_BIT    0x4
53#define SHORT_BIT            0x8
54#define UNSIGNED_SHORT_BIT   0x10
55#define INT_BIT              0x20
56#define UNSIGNED_INT_BIT     0x40
57#define HALF_BIT             0x80
58#define FLOAT_BIT            0x100
59#define DOUBLE_BIT           0x200
60#define FIXED_ES_BIT         0x400
61#define FIXED_GL_BIT         0x800
62
63
64/** Convert GL datatype enum into a <type>_BIT value seen above */
65static GLbitfield
66type_to_bit(const struct gl_context *ctx, GLenum type)
67{
68   switch (type) {
69   case GL_BOOL:
70      return BOOL_BIT;
71   case GL_BYTE:
72      return BYTE_BIT;
73   case GL_UNSIGNED_BYTE:
74      return UNSIGNED_BYTE_BIT;
75   case GL_SHORT:
76      return SHORT_BIT;
77   case GL_UNSIGNED_SHORT:
78      return UNSIGNED_SHORT_BIT;
79   case GL_INT:
80      return INT_BIT;
81   case GL_UNSIGNED_INT:
82      return UNSIGNED_INT_BIT;
83   case GL_HALF_FLOAT:
84      if (ctx->Extensions.ARB_half_float_vertex)
85         return HALF_BIT;
86      else
87         return 0x0;
88   case GL_FLOAT:
89      return FLOAT_BIT;
90   case GL_DOUBLE:
91      return DOUBLE_BIT;
92   case GL_FIXED:
93      return ctx->API == API_OPENGL ? FIXED_GL_BIT : FIXED_ES_BIT;
94   default:
95      return 0;
96   }
97}
98
99
100/**
101 * Do error checking and update state for glVertex/Color/TexCoord/...Pointer
102 * functions.
103 *
104 * \param func  name of calling function used for error reporting
105 * \param array  the array to update
106 * \param dirtyBit  which bit to set in ctx->Array.NewState for this array
107 * \param legalTypes  bitmask of *_BIT above indicating legal datatypes
108 * \param sizeMin  min allowable size value
109 * \param sizeMax  max allowable size value (may also be BGRA_OR_4)
110 * \param size  components per element (1, 2, 3 or 4)
111 * \param type  datatype of each component (GL_FLOAT, GL_INT, etc)
112 * \param stride  stride between elements, in elements
113 * \param normalized  are integer types converted to floats in [-1, 1]?
114 * \param integer  integer-valued values (will not be normalized to [-1,1])
115 * \param ptr  the address (or offset inside VBO) of the array data
116 */
117static void
118update_array(struct gl_context *ctx,
119             const char *func,
120             struct gl_client_array *array,
121             GLbitfield dirtyBit, GLbitfield legalTypesMask,
122             GLint sizeMin, GLint sizeMax,
123             GLint size, GLenum type, GLsizei stride,
124             GLboolean normalized, GLboolean integer,
125             const GLvoid *ptr)
126{
127   GLbitfield typeBit;
128   GLsizei elementSize;
129   GLenum format = GL_RGBA;
130
131   if (ctx->API != API_OPENGLES && ctx->API != API_OPENGLES2) {
132      /* fixed point arrays / data is only allowed with OpenGL ES 1.x/2.0 */
133      legalTypesMask &= ~FIXED_ES_BIT;
134   }
135   if (!ctx->Extensions.ARB_ES2_compatibility) {
136      legalTypesMask &= ~FIXED_GL_BIT;
137   }
138
139   typeBit = type_to_bit(ctx, type);
140   if (typeBit == 0x0 || (typeBit & legalTypesMask) == 0x0) {
141      _mesa_error(ctx, GL_INVALID_ENUM, "%s(type = %s)",
142                  func, _mesa_lookup_enum_by_nr(type));
143      return;
144   }
145
146   /* Do size parameter checking.
147    * If sizeMax = BGRA_OR_4 it means that size = GL_BGRA is legal and
148    * must be handled specially.
149    */
150   if (ctx->Extensions.EXT_vertex_array_bgra &&
151       sizeMax == BGRA_OR_4 &&
152       size == GL_BGRA) {
153      if (type != GL_UNSIGNED_BYTE) {
154         _mesa_error(ctx, GL_INVALID_VALUE, "%s(GL_BGRA/GLubyte)", func);
155         return;
156      }
157      format = GL_BGRA;
158      size = 4;
159   }
160   else if (size < sizeMin || size > sizeMax || size > 4) {
161      _mesa_error(ctx, GL_INVALID_VALUE, "%s(size=%d)", func, size);
162      return;
163   }
164
165   ASSERT(size <= 4);
166
167   if (stride < 0) {
168      _mesa_error( ctx, GL_INVALID_VALUE, "%s(stride=%d)", func, stride );
169      return;
170   }
171
172   if (ctx->Array.ArrayObj->VBOonly &&
173       ctx->Array.ArrayBufferObj->Name == 0) {
174      /* GL_ARB_vertex_array_object requires that all arrays reside in VBOs.
175       * Generate GL_INVALID_OPERATION if that's not true.
176       */
177      _mesa_error(ctx, GL_INVALID_OPERATION, "%s(non-VBO array)", func);
178      return;
179   }
180
181   elementSize = _mesa_sizeof_type(type) * size;
182
183   array->Size = size;
184   array->Type = type;
185   array->Format = format;
186   array->Stride = stride;
187   array->StrideB = stride ? stride : elementSize;
188   array->Normalized = normalized;
189   array->Ptr = (const GLubyte *) ptr;
190   array->_ElementSize = elementSize;
191
192   _mesa_reference_buffer_object(ctx, &array->BufferObj,
193                                 ctx->Array.ArrayBufferObj);
194
195   ctx->NewState |= _NEW_ARRAY;
196   ctx->Array.NewState |= dirtyBit;
197}
198
199
200void GLAPIENTRY
201_mesa_VertexPointer(GLint size, GLenum type, GLsizei stride, const GLvoid *ptr)
202{
203   GLbitfield legalTypes = (SHORT_BIT | INT_BIT | FLOAT_BIT |
204                            DOUBLE_BIT | HALF_BIT | FIXED_ES_BIT);
205   GET_CURRENT_CONTEXT(ctx);
206   ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx);
207
208   if (ctx->API == API_OPENGLES)
209      legalTypes |= BYTE_BIT;
210
211   update_array(ctx, "glVertexPointer",
212                &ctx->Array.ArrayObj->Vertex, _NEW_ARRAY_VERTEX,
213                legalTypes, 2, 4,
214                size, type, stride, GL_FALSE, GL_FALSE, ptr);
215}
216
217
218void GLAPIENTRY
219_mesa_NormalPointer(GLenum type, GLsizei stride, const GLvoid *ptr )
220{
221   const GLbitfield legalTypes = (BYTE_BIT | SHORT_BIT | INT_BIT |
222                                  HALF_BIT | FLOAT_BIT | DOUBLE_BIT |
223                                  FIXED_ES_BIT);
224   GET_CURRENT_CONTEXT(ctx);
225   ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx);
226
227   update_array(ctx, "glNormalPointer",
228                &ctx->Array.ArrayObj->Normal, _NEW_ARRAY_NORMAL,
229                legalTypes, 3, 3,
230                3, type, stride, GL_TRUE, GL_FALSE, ptr);
231}
232
233
234void GLAPIENTRY
235_mesa_ColorPointer(GLint size, GLenum type, GLsizei stride, const GLvoid *ptr)
236{
237   const GLbitfield legalTypes = (BYTE_BIT | UNSIGNED_BYTE_BIT |
238                                  SHORT_BIT | UNSIGNED_SHORT_BIT |
239                                  INT_BIT | UNSIGNED_INT_BIT |
240                                  HALF_BIT | FLOAT_BIT | DOUBLE_BIT |
241                                  FIXED_ES_BIT);
242   GET_CURRENT_CONTEXT(ctx);
243   ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx);
244
245   update_array(ctx, "glColorPointer",
246                &ctx->Array.ArrayObj->Color, _NEW_ARRAY_COLOR0,
247                legalTypes, 3, BGRA_OR_4,
248                size, type, stride, GL_TRUE, GL_FALSE, ptr);
249}
250
251
252void GLAPIENTRY
253_mesa_FogCoordPointerEXT(GLenum type, GLsizei stride, const GLvoid *ptr)
254{
255   const GLbitfield legalTypes = (HALF_BIT | FLOAT_BIT | DOUBLE_BIT);
256   GET_CURRENT_CONTEXT(ctx);
257   ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx);
258
259   update_array(ctx, "glFogCoordPointer",
260                &ctx->Array.ArrayObj->FogCoord, _NEW_ARRAY_FOGCOORD,
261                legalTypes, 1, 1,
262                1, type, stride, GL_FALSE, GL_FALSE, ptr);
263}
264
265
266void GLAPIENTRY
267_mesa_IndexPointer(GLenum type, GLsizei stride, const GLvoid *ptr)
268{
269   const GLbitfield legalTypes = (UNSIGNED_BYTE_BIT | SHORT_BIT | INT_BIT |
270                                  FLOAT_BIT | DOUBLE_BIT);
271   GET_CURRENT_CONTEXT(ctx);
272   ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx);
273
274   update_array(ctx, "glIndexPointer",
275                &ctx->Array.ArrayObj->Index, _NEW_ARRAY_INDEX,
276                legalTypes, 1, 1,
277                1, type, stride, GL_FALSE, GL_FALSE, ptr);
278}
279
280
281void GLAPIENTRY
282_mesa_SecondaryColorPointerEXT(GLint size, GLenum type,
283			       GLsizei stride, const GLvoid *ptr)
284{
285   const GLbitfield legalTypes = (BYTE_BIT | UNSIGNED_BYTE_BIT |
286                                  SHORT_BIT | UNSIGNED_SHORT_BIT |
287                                  INT_BIT | UNSIGNED_INT_BIT |
288                                  HALF_BIT | FLOAT_BIT | DOUBLE_BIT);
289   GET_CURRENT_CONTEXT(ctx);
290   ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx);
291
292   update_array(ctx, "glSecondaryColorPointer",
293                &ctx->Array.ArrayObj->SecondaryColor, _NEW_ARRAY_COLOR1,
294                legalTypes, 3, BGRA_OR_4,
295                size, type, stride, GL_TRUE, GL_FALSE, ptr);
296}
297
298
299void GLAPIENTRY
300_mesa_TexCoordPointer(GLint size, GLenum type, GLsizei stride,
301                      const GLvoid *ptr)
302{
303   GLbitfield legalTypes = (SHORT_BIT | INT_BIT |
304                            HALF_BIT | FLOAT_BIT | DOUBLE_BIT |
305                            FIXED_ES_BIT);
306   GET_CURRENT_CONTEXT(ctx);
307   const GLuint unit = ctx->Array.ActiveTexture;
308   ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx);
309
310   if (ctx->API == API_OPENGLES)
311      legalTypes |= BYTE_BIT;
312
313   ASSERT(unit < Elements(ctx->Array.ArrayObj->TexCoord));
314
315   update_array(ctx, "glTexCoordPointer",
316                &ctx->Array.ArrayObj->TexCoord[unit],
317                _NEW_ARRAY_TEXCOORD(unit),
318                legalTypes, 1, 4,
319                size, type, stride, GL_FALSE, GL_FALSE,
320                ptr);
321}
322
323
324void GLAPIENTRY
325_mesa_EdgeFlagPointer(GLsizei stride, const GLvoid *ptr)
326{
327   const GLbitfield legalTypes = UNSIGNED_BYTE_BIT;
328   /* see table 2.4 edits in GL_EXT_gpu_shader4 spec: */
329   const GLboolean integer = GL_TRUE;
330   GET_CURRENT_CONTEXT(ctx);
331   ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx);
332
333   update_array(ctx, "glEdgeFlagPointer",
334                &ctx->Array.ArrayObj->EdgeFlag, _NEW_ARRAY_EDGEFLAG,
335                legalTypes, 1, 1,
336                1, GL_UNSIGNED_BYTE, stride, GL_FALSE, integer, ptr);
337}
338
339
340void GLAPIENTRY
341_mesa_PointSizePointer(GLenum type, GLsizei stride, const GLvoid *ptr)
342{
343   const GLbitfield legalTypes = (FLOAT_BIT | FIXED_ES_BIT);
344   GET_CURRENT_CONTEXT(ctx);
345   ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx);
346
347   if (ctx->API != API_OPENGLES) {
348      _mesa_error(ctx, GL_INVALID_OPERATION,
349                  "glPointSizePointer(ES 1.x only)");
350      return;
351   }
352
353   update_array(ctx, "glPointSizePointer",
354                &ctx->Array.ArrayObj->PointSize, _NEW_ARRAY_POINT_SIZE,
355                legalTypes, 1, 1,
356                1, type, stride, GL_FALSE, GL_FALSE, ptr);
357}
358
359
360#if FEATURE_NV_vertex_program
361/**
362 * Set a vertex attribute array.
363 * Note that these arrays DO alias the conventional GL vertex arrays
364 * (position, normal, color, fog, texcoord, etc).
365 * The generic attribute slots at #16 and above are not touched.
366 */
367void GLAPIENTRY
368_mesa_VertexAttribPointerNV(GLuint index, GLint size, GLenum type,
369                            GLsizei stride, const GLvoid *ptr)
370{
371   const GLbitfield legalTypes = (UNSIGNED_BYTE_BIT | SHORT_BIT |
372                                  FLOAT_BIT | DOUBLE_BIT);
373   GLboolean normalized = GL_FALSE;
374   GET_CURRENT_CONTEXT(ctx);
375   ASSERT_OUTSIDE_BEGIN_END(ctx);
376
377   if (index >= MAX_NV_VERTEX_PROGRAM_INPUTS) {
378      _mesa_error(ctx, GL_INVALID_VALUE, "glVertexAttribPointerNV(index)");
379      return;
380   }
381
382   if (type == GL_UNSIGNED_BYTE && size != 4) {
383      _mesa_error(ctx, GL_INVALID_VALUE, "glVertexAttribPointerNV(size!=4)");
384      return;
385   }
386
387   update_array(ctx, "glVertexAttribPointerNV",
388                &ctx->Array.ArrayObj->VertexAttrib[index],
389                _NEW_ARRAY_ATTRIB(index),
390                legalTypes, 1, BGRA_OR_4,
391                size, type, stride, normalized, GL_FALSE, ptr);
392}
393#endif
394
395
396#if FEATURE_ARB_vertex_program
397/**
398 * Set a generic vertex attribute array.
399 * Note that these arrays DO NOT alias the conventional GL vertex arrays
400 * (position, normal, color, fog, texcoord, etc).
401 */
402void GLAPIENTRY
403_mesa_VertexAttribPointerARB(GLuint index, GLint size, GLenum type,
404                             GLboolean normalized,
405                             GLsizei stride, const GLvoid *ptr)
406{
407   const GLbitfield legalTypes = (BYTE_BIT | UNSIGNED_BYTE_BIT |
408                                  SHORT_BIT | UNSIGNED_SHORT_BIT |
409                                  INT_BIT | UNSIGNED_INT_BIT |
410                                  HALF_BIT | FLOAT_BIT | DOUBLE_BIT |
411                                  FIXED_ES_BIT | FIXED_GL_BIT);
412   GET_CURRENT_CONTEXT(ctx);
413   ASSERT_OUTSIDE_BEGIN_END(ctx);
414
415   if (index >= ctx->Const.VertexProgram.MaxAttribs) {
416      _mesa_error(ctx, GL_INVALID_VALUE, "glVertexAttribPointerARB(index)");
417      return;
418   }
419
420   update_array(ctx, "glVertexAttribPointer",
421                &ctx->Array.ArrayObj->VertexAttrib[index],
422                _NEW_ARRAY_ATTRIB(index),
423                legalTypes, 1, BGRA_OR_4,
424                size, type, stride, normalized, GL_FALSE, ptr);
425}
426#endif
427
428
429/**
430 * GL_EXT_gpu_shader4 / GL 3.0.
431 * Set an integer-valued vertex attribute array.
432 * Note that these arrays DO NOT alias the conventional GL vertex arrays
433 * (position, normal, color, fog, texcoord, etc).
434 */
435void GLAPIENTRY
436_mesa_VertexAttribIPointer(GLuint index, GLint size, GLenum type,
437                           GLsizei stride, const GLvoid *ptr)
438{
439   const GLbitfield legalTypes = (BYTE_BIT | UNSIGNED_BYTE_BIT |
440                                  SHORT_BIT | UNSIGNED_SHORT_BIT |
441                                  INT_BIT | UNSIGNED_INT_BIT);
442   const GLboolean normalized = GL_FALSE;
443   const GLboolean integer = GL_TRUE;
444   GET_CURRENT_CONTEXT(ctx);
445   ASSERT_OUTSIDE_BEGIN_END(ctx);
446
447   if (index >= ctx->Const.VertexProgram.MaxAttribs) {
448      _mesa_error(ctx, GL_INVALID_VALUE, "glVertexAttribIPointer(index)");
449      return;
450   }
451
452   update_array(ctx, "glVertexAttribIPointer",
453                &ctx->Array.ArrayObj->VertexAttrib[index],
454                _NEW_ARRAY_ATTRIB(index),
455                legalTypes, 1, 4,
456                size, type, stride, normalized, integer, ptr);
457}
458
459
460
461void GLAPIENTRY
462_mesa_EnableVertexAttribArrayARB(GLuint index)
463{
464   GET_CURRENT_CONTEXT(ctx);
465   ASSERT_OUTSIDE_BEGIN_END(ctx);
466
467   if (index >= ctx->Const.VertexProgram.MaxAttribs) {
468      _mesa_error(ctx, GL_INVALID_VALUE,
469                  "glEnableVertexAttribArrayARB(index)");
470      return;
471   }
472
473   ASSERT(index < Elements(ctx->Array.ArrayObj->VertexAttrib));
474
475   FLUSH_VERTICES(ctx, _NEW_ARRAY);
476   ctx->Array.ArrayObj->VertexAttrib[index].Enabled = GL_TRUE;
477   ctx->Array.ArrayObj->_Enabled |= _NEW_ARRAY_ATTRIB(index);
478   ctx->Array.NewState |= _NEW_ARRAY_ATTRIB(index);
479}
480
481
482void GLAPIENTRY
483_mesa_DisableVertexAttribArrayARB(GLuint index)
484{
485   GET_CURRENT_CONTEXT(ctx);
486   ASSERT_OUTSIDE_BEGIN_END(ctx);
487
488   if (index >= ctx->Const.VertexProgram.MaxAttribs) {
489      _mesa_error(ctx, GL_INVALID_VALUE,
490                  "glDisableVertexAttribArrayARB(index)");
491      return;
492   }
493
494   ASSERT(index < Elements(ctx->Array.ArrayObj->VertexAttrib));
495
496   FLUSH_VERTICES(ctx, _NEW_ARRAY);
497   ctx->Array.ArrayObj->VertexAttrib[index].Enabled = GL_FALSE;
498   ctx->Array.ArrayObj->_Enabled &= ~_NEW_ARRAY_ATTRIB(index);
499   ctx->Array.NewState |= _NEW_ARRAY_ATTRIB(index);
500}
501
502
503/**
504 * Return info for a vertex attribute array (no alias with legacy
505 * vertex attributes (pos, normal, color, etc)).  This function does
506 * not handle the 4-element GL_CURRENT_VERTEX_ATTRIB_ARB query.
507 */
508static GLuint
509get_vertex_array_attrib(struct gl_context *ctx, GLuint index, GLenum pname,
510                  const char *caller)
511{
512   const struct gl_client_array *array;
513
514   if (index >= ctx->Const.VertexProgram.MaxAttribs) {
515      _mesa_error(ctx, GL_INVALID_VALUE, "%s(index=%u)", caller, index);
516      return 0;
517   }
518
519   ASSERT(index < Elements(ctx->Array.ArrayObj->VertexAttrib));
520
521   array = &ctx->Array.ArrayObj->VertexAttrib[index];
522
523   switch (pname) {
524   case GL_VERTEX_ATTRIB_ARRAY_ENABLED_ARB:
525      return array->Enabled;
526   case GL_VERTEX_ATTRIB_ARRAY_SIZE_ARB:
527      return array->Size;
528   case GL_VERTEX_ATTRIB_ARRAY_STRIDE_ARB:
529      return array->Stride;
530   case GL_VERTEX_ATTRIB_ARRAY_TYPE_ARB:
531      return array->Type;
532   case GL_VERTEX_ATTRIB_ARRAY_NORMALIZED_ARB:
533      return array->Normalized;
534   case GL_VERTEX_ATTRIB_ARRAY_BUFFER_BINDING_ARB:
535      return array->BufferObj->Name;
536   case GL_VERTEX_ATTRIB_ARRAY_INTEGER:
537      if (ctx->Extensions.EXT_gpu_shader4) {
538         return array->Integer;
539      }
540      goto error;
541   case GL_VERTEX_ATTRIB_ARRAY_DIVISOR_ARB:
542      if (ctx->Extensions.ARB_instanced_arrays) {
543         return array->InstanceDivisor;
544      }
545      goto error;
546   default:
547      ; /* fall-through */
548   }
549
550error:
551   _mesa_error(ctx, GL_INVALID_ENUM, "%s(pname=0x%x)", caller, pname);
552   return 0;
553}
554
555
556static const GLfloat *
557get_current_attrib(struct gl_context *ctx, GLuint index, const char *function)
558{
559   if (index == 0) {
560      if (ctx->API != API_OPENGLES2) {
561	 _mesa_error(ctx, GL_INVALID_OPERATION, "%s(index==0)", function);
562	 return NULL;
563      }
564   }
565   else if (index >= ctx->Const.VertexProgram.MaxAttribs) {
566      _mesa_error(ctx, GL_INVALID_VALUE,
567		  "%s(index>=GL_MAX_VERTEX_ATTRIBS)", function);
568      return NULL;
569   }
570
571   FLUSH_CURRENT(ctx, 0);
572   return ctx->Current.Attrib[VERT_ATTRIB_GENERIC0 + index];
573}
574
575void GLAPIENTRY
576_mesa_GetVertexAttribfvARB(GLuint index, GLenum pname, GLfloat *params)
577{
578   GET_CURRENT_CONTEXT(ctx);
579   ASSERT_OUTSIDE_BEGIN_END(ctx);
580
581   if (pname == GL_CURRENT_VERTEX_ATTRIB_ARB) {
582      const GLfloat *v = get_current_attrib(ctx, index, "glGetVertexAttribfv");
583      if (v != NULL) {
584         COPY_4V(params, v);
585      }
586   }
587   else {
588      params[0] = (GLfloat) get_vertex_array_attrib(ctx, index, pname,
589                                                    "glGetVertexAttribfv");
590   }
591}
592
593
594void GLAPIENTRY
595_mesa_GetVertexAttribdvARB(GLuint index, GLenum pname, GLdouble *params)
596{
597   GET_CURRENT_CONTEXT(ctx);
598   ASSERT_OUTSIDE_BEGIN_END(ctx);
599
600   if (pname == GL_CURRENT_VERTEX_ATTRIB_ARB) {
601      const GLfloat *v = get_current_attrib(ctx, index, "glGetVertexAttribdv");
602      if (v != NULL) {
603         params[0] = (GLdouble) v[0];
604         params[1] = (GLdouble) v[1];
605         params[2] = (GLdouble) v[2];
606         params[3] = (GLdouble) v[3];
607      }
608   }
609   else {
610      params[0] = (GLdouble) get_vertex_array_attrib(ctx, index, pname,
611                                                     "glGetVertexAttribdv");
612   }
613}
614
615
616void GLAPIENTRY
617_mesa_GetVertexAttribivARB(GLuint index, GLenum pname, GLint *params)
618{
619   GET_CURRENT_CONTEXT(ctx);
620   ASSERT_OUTSIDE_BEGIN_END(ctx);
621
622   if (pname == GL_CURRENT_VERTEX_ATTRIB_ARB) {
623      const GLfloat *v = get_current_attrib(ctx, index, "glGetVertexAttribiv");
624      if (v != NULL) {
625         /* XXX should floats in[0,1] be scaled to full int range? */
626         params[0] = (GLint) v[0];
627         params[1] = (GLint) v[1];
628         params[2] = (GLint) v[2];
629         params[3] = (GLint) v[3];
630      }
631   }
632   else {
633      params[0] = (GLint) get_vertex_array_attrib(ctx, index, pname,
634                                                  "glGetVertexAttribiv");
635   }
636}
637
638
639/** GL 3.0 */
640void GLAPIENTRY
641_mesa_GetVertexAttribIiv(GLuint index, GLenum pname, GLint *params)
642{
643   GET_CURRENT_CONTEXT(ctx);
644   ASSERT_OUTSIDE_BEGIN_END(ctx);
645
646   if (pname == GL_CURRENT_VERTEX_ATTRIB_ARB) {
647      const GLfloat *v =
648	 get_current_attrib(ctx, index, "glGetVertexAttribIiv");
649      if (v != NULL) {
650         /* XXX we don't have true integer-valued vertex attribs yet */
651         params[0] = (GLint) v[0];
652         params[1] = (GLint) v[1];
653         params[2] = (GLint) v[2];
654         params[3] = (GLint) v[3];
655      }
656   }
657   else {
658      params[0] = (GLint) get_vertex_array_attrib(ctx, index, pname,
659                                                  "glGetVertexAttribIiv");
660   }
661}
662
663
664/** GL 3.0 */
665void GLAPIENTRY
666_mesa_GetVertexAttribIuiv(GLuint index, GLenum pname, GLuint *params)
667{
668   GET_CURRENT_CONTEXT(ctx);
669   ASSERT_OUTSIDE_BEGIN_END(ctx);
670
671   if (pname == GL_CURRENT_VERTEX_ATTRIB_ARB) {
672      const GLfloat *v =
673	 get_current_attrib(ctx, index, "glGetVertexAttribIuiv");
674      if (v != NULL) {
675         /* XXX we don't have true integer-valued vertex attribs yet */
676         params[0] = (GLuint) v[0];
677         params[1] = (GLuint) v[1];
678         params[2] = (GLuint) v[2];
679         params[3] = (GLuint) v[3];
680      }
681   }
682   else {
683      params[0] = get_vertex_array_attrib(ctx, index, pname,
684                                          "glGetVertexAttribIuiv");
685   }
686}
687
688
689void GLAPIENTRY
690_mesa_GetVertexAttribPointervARB(GLuint index, GLenum pname, GLvoid **pointer)
691{
692   GET_CURRENT_CONTEXT(ctx);
693   ASSERT_OUTSIDE_BEGIN_END(ctx);
694
695   if (index >= ctx->Const.VertexProgram.MaxAttribs) {
696      _mesa_error(ctx, GL_INVALID_VALUE, "glGetVertexAttribPointerARB(index)");
697      return;
698   }
699
700   if (pname != GL_VERTEX_ATTRIB_ARRAY_POINTER_ARB) {
701      _mesa_error(ctx, GL_INVALID_ENUM, "glGetVertexAttribPointerARB(pname)");
702      return;
703   }
704
705   ASSERT(index < Elements(ctx->Array.ArrayObj->VertexAttrib));
706
707   *pointer = (GLvoid *) ctx->Array.ArrayObj->VertexAttrib[index].Ptr;
708}
709
710
711void GLAPIENTRY
712_mesa_VertexPointerEXT(GLint size, GLenum type, GLsizei stride,
713                       GLsizei count, const GLvoid *ptr)
714{
715   (void) count;
716   _mesa_VertexPointer(size, type, stride, ptr);
717}
718
719
720void GLAPIENTRY
721_mesa_NormalPointerEXT(GLenum type, GLsizei stride, GLsizei count,
722                       const GLvoid *ptr)
723{
724   (void) count;
725   _mesa_NormalPointer(type, stride, ptr);
726}
727
728
729void GLAPIENTRY
730_mesa_ColorPointerEXT(GLint size, GLenum type, GLsizei stride, GLsizei count,
731                      const GLvoid *ptr)
732{
733   (void) count;
734   _mesa_ColorPointer(size, type, stride, ptr);
735}
736
737
738void GLAPIENTRY
739_mesa_IndexPointerEXT(GLenum type, GLsizei stride, GLsizei count,
740                      const GLvoid *ptr)
741{
742   (void) count;
743   _mesa_IndexPointer(type, stride, ptr);
744}
745
746
747void GLAPIENTRY
748_mesa_TexCoordPointerEXT(GLint size, GLenum type, GLsizei stride,
749                         GLsizei count, const GLvoid *ptr)
750{
751   (void) count;
752   _mesa_TexCoordPointer(size, type, stride, ptr);
753}
754
755
756void GLAPIENTRY
757_mesa_EdgeFlagPointerEXT(GLsizei stride, GLsizei count, const GLboolean *ptr)
758{
759   (void) count;
760   _mesa_EdgeFlagPointer(stride, ptr);
761}
762
763
764void GLAPIENTRY
765_mesa_InterleavedArrays(GLenum format, GLsizei stride, const GLvoid *pointer)
766{
767   GET_CURRENT_CONTEXT(ctx);
768   GLboolean tflag, cflag, nflag;  /* enable/disable flags */
769   GLint tcomps, ccomps, vcomps;   /* components per texcoord, color, vertex */
770   GLenum ctype = 0;               /* color type */
771   GLint coffset = 0, noffset = 0, voffset;/* color, normal, vertex offsets */
772   const GLint toffset = 0;        /* always zero */
773   GLint defstride;                /* default stride */
774   GLint c, f;
775
776   ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx);
777
778   f = sizeof(GLfloat);
779   c = f * ((4 * sizeof(GLubyte) + (f - 1)) / f);
780
781   if (stride < 0) {
782      _mesa_error( ctx, GL_INVALID_VALUE, "glInterleavedArrays(stride)" );
783      return;
784   }
785
786   switch (format) {
787      case GL_V2F:
788         tflag = GL_FALSE;  cflag = GL_FALSE;  nflag = GL_FALSE;
789         tcomps = 0;  ccomps = 0;  vcomps = 2;
790         voffset = 0;
791         defstride = 2*f;
792         break;
793      case GL_V3F:
794         tflag = GL_FALSE;  cflag = GL_FALSE;  nflag = GL_FALSE;
795         tcomps = 0;  ccomps = 0;  vcomps = 3;
796         voffset = 0;
797         defstride = 3*f;
798         break;
799      case GL_C4UB_V2F:
800         tflag = GL_FALSE;  cflag = GL_TRUE;  nflag = GL_FALSE;
801         tcomps = 0;  ccomps = 4;  vcomps = 2;
802         ctype = GL_UNSIGNED_BYTE;
803         coffset = 0;
804         voffset = c;
805         defstride = c + 2*f;
806         break;
807      case GL_C4UB_V3F:
808         tflag = GL_FALSE;  cflag = GL_TRUE;  nflag = GL_FALSE;
809         tcomps = 0;  ccomps = 4;  vcomps = 3;
810         ctype = GL_UNSIGNED_BYTE;
811         coffset = 0;
812         voffset = c;
813         defstride = c + 3*f;
814         break;
815      case GL_C3F_V3F:
816         tflag = GL_FALSE;  cflag = GL_TRUE;  nflag = GL_FALSE;
817         tcomps = 0;  ccomps = 3;  vcomps = 3;
818         ctype = GL_FLOAT;
819         coffset = 0;
820         voffset = 3*f;
821         defstride = 6*f;
822         break;
823      case GL_N3F_V3F:
824         tflag = GL_FALSE;  cflag = GL_FALSE;  nflag = GL_TRUE;
825         tcomps = 0;  ccomps = 0;  vcomps = 3;
826         noffset = 0;
827         voffset = 3*f;
828         defstride = 6*f;
829         break;
830      case GL_C4F_N3F_V3F:
831         tflag = GL_FALSE;  cflag = GL_TRUE;  nflag = GL_TRUE;
832         tcomps = 0;  ccomps = 4;  vcomps = 3;
833         ctype = GL_FLOAT;
834         coffset = 0;
835         noffset = 4*f;
836         voffset = 7*f;
837         defstride = 10*f;
838         break;
839      case GL_T2F_V3F:
840         tflag = GL_TRUE;  cflag = GL_FALSE;  nflag = GL_FALSE;
841         tcomps = 2;  ccomps = 0;  vcomps = 3;
842         voffset = 2*f;
843         defstride = 5*f;
844         break;
845      case GL_T4F_V4F:
846         tflag = GL_TRUE;  cflag = GL_FALSE;  nflag = GL_FALSE;
847         tcomps = 4;  ccomps = 0;  vcomps = 4;
848         voffset = 4*f;
849         defstride = 8*f;
850         break;
851      case GL_T2F_C4UB_V3F:
852         tflag = GL_TRUE;  cflag = GL_TRUE;  nflag = GL_FALSE;
853         tcomps = 2;  ccomps = 4;  vcomps = 3;
854         ctype = GL_UNSIGNED_BYTE;
855         coffset = 2*f;
856         voffset = c+2*f;
857         defstride = c+5*f;
858         break;
859      case GL_T2F_C3F_V3F:
860         tflag = GL_TRUE;  cflag = GL_TRUE;  nflag = GL_FALSE;
861         tcomps = 2;  ccomps = 3;  vcomps = 3;
862         ctype = GL_FLOAT;
863         coffset = 2*f;
864         voffset = 5*f;
865         defstride = 8*f;
866         break;
867      case GL_T2F_N3F_V3F:
868         tflag = GL_TRUE;  cflag = GL_FALSE;  nflag = GL_TRUE;
869         tcomps = 2;  ccomps = 0;  vcomps = 3;
870         noffset = 2*f;
871         voffset = 5*f;
872         defstride = 8*f;
873         break;
874      case GL_T2F_C4F_N3F_V3F:
875         tflag = GL_TRUE;  cflag = GL_TRUE;  nflag = GL_TRUE;
876         tcomps = 2;  ccomps = 4;  vcomps = 3;
877         ctype = GL_FLOAT;
878         coffset = 2*f;
879         noffset = 6*f;
880         voffset = 9*f;
881         defstride = 12*f;
882         break;
883      case GL_T4F_C4F_N3F_V4F:
884         tflag = GL_TRUE;  cflag = GL_TRUE;  nflag = GL_TRUE;
885         tcomps = 4;  ccomps = 4;  vcomps = 4;
886         ctype = GL_FLOAT;
887         coffset = 4*f;
888         noffset = 8*f;
889         voffset = 11*f;
890         defstride = 15*f;
891         break;
892      default:
893         _mesa_error( ctx, GL_INVALID_ENUM, "glInterleavedArrays(format)" );
894         return;
895   }
896
897   if (stride==0) {
898      stride = defstride;
899   }
900
901   _mesa_DisableClientState( GL_EDGE_FLAG_ARRAY );
902   _mesa_DisableClientState( GL_INDEX_ARRAY );
903   /* XXX also disable secondary color and generic arrays? */
904
905   /* Texcoords */
906   if (tflag) {
907      _mesa_EnableClientState( GL_TEXTURE_COORD_ARRAY );
908      _mesa_TexCoordPointer( tcomps, GL_FLOAT, stride,
909                             (GLubyte *) pointer + toffset );
910   }
911   else {
912      _mesa_DisableClientState( GL_TEXTURE_COORD_ARRAY );
913   }
914
915   /* Color */
916   if (cflag) {
917      _mesa_EnableClientState( GL_COLOR_ARRAY );
918      _mesa_ColorPointer( ccomps, ctype, stride,
919			  (GLubyte *) pointer + coffset );
920   }
921   else {
922      _mesa_DisableClientState( GL_COLOR_ARRAY );
923   }
924
925
926   /* Normals */
927   if (nflag) {
928      _mesa_EnableClientState( GL_NORMAL_ARRAY );
929      _mesa_NormalPointer( GL_FLOAT, stride, (GLubyte *) pointer + noffset );
930   }
931   else {
932      _mesa_DisableClientState( GL_NORMAL_ARRAY );
933   }
934
935   /* Vertices */
936   _mesa_EnableClientState( GL_VERTEX_ARRAY );
937   _mesa_VertexPointer( vcomps, GL_FLOAT, stride,
938			(GLubyte *) pointer + voffset );
939}
940
941
942void GLAPIENTRY
943_mesa_LockArraysEXT(GLint first, GLsizei count)
944{
945   GET_CURRENT_CONTEXT(ctx);
946   ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx);
947
948   if (MESA_VERBOSE & VERBOSE_API)
949      _mesa_debug(ctx, "glLockArrays %d %d\n", first, count);
950
951   if (first < 0) {
952      _mesa_error( ctx, GL_INVALID_VALUE, "glLockArraysEXT(first)" );
953      return;
954   }
955   if (count <= 0) {
956      _mesa_error( ctx, GL_INVALID_VALUE, "glLockArraysEXT(count)" );
957      return;
958   }
959   if (ctx->Array.LockCount != 0) {
960      _mesa_error( ctx, GL_INVALID_OPERATION, "glLockArraysEXT(reentry)" );
961      return;
962   }
963
964   ctx->Array.LockFirst = first;
965   ctx->Array.LockCount = count;
966
967   ctx->NewState |= _NEW_ARRAY;
968   ctx->Array.NewState |= _NEW_ARRAY_ALL;
969}
970
971
972void GLAPIENTRY
973_mesa_UnlockArraysEXT( void )
974{
975   GET_CURRENT_CONTEXT(ctx);
976   ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx);
977
978   if (MESA_VERBOSE & VERBOSE_API)
979      _mesa_debug(ctx, "glUnlockArrays\n");
980
981   if (ctx->Array.LockCount == 0) {
982      _mesa_error( ctx, GL_INVALID_OPERATION, "glUnlockArraysEXT(reexit)" );
983      return;
984   }
985
986   ctx->Array.LockFirst = 0;
987   ctx->Array.LockCount = 0;
988   ctx->NewState |= _NEW_ARRAY;
989   ctx->Array.NewState |= _NEW_ARRAY_ALL;
990}
991
992
993/* GL_EXT_multi_draw_arrays */
994void GLAPIENTRY
995_mesa_MultiDrawArraysEXT( GLenum mode, const GLint *first,
996                          const GLsizei *count, GLsizei primcount )
997{
998   GET_CURRENT_CONTEXT(ctx);
999   GLint i;
1000
1001   ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx);
1002
1003   for (i = 0; i < primcount; i++) {
1004      if (count[i] > 0) {
1005         CALL_DrawArrays(ctx->Exec, (mode, first[i], count[i]));
1006      }
1007   }
1008}
1009
1010
1011/* GL_IBM_multimode_draw_arrays */
1012void GLAPIENTRY
1013_mesa_MultiModeDrawArraysIBM( const GLenum * mode, const GLint * first,
1014			      const GLsizei * count,
1015			      GLsizei primcount, GLint modestride )
1016{
1017   GET_CURRENT_CONTEXT(ctx);
1018   GLint i;
1019
1020   ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx);
1021
1022   for ( i = 0 ; i < primcount ; i++ ) {
1023      if ( count[i] > 0 ) {
1024         GLenum m = *((GLenum *) ((GLubyte *) mode + i * modestride));
1025	 CALL_DrawArrays(ctx->Exec, ( m, first[i], count[i] ));
1026      }
1027   }
1028}
1029
1030
1031/* GL_IBM_multimode_draw_arrays */
1032void GLAPIENTRY
1033_mesa_MultiModeDrawElementsIBM( const GLenum * mode, const GLsizei * count,
1034				GLenum type, const GLvoid * const * indices,
1035				GLsizei primcount, GLint modestride )
1036{
1037   GET_CURRENT_CONTEXT(ctx);
1038   GLint i;
1039
1040   ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx);
1041
1042   /* XXX not sure about ARB_vertex_buffer_object handling here */
1043
1044   for ( i = 0 ; i < primcount ; i++ ) {
1045      if ( count[i] > 0 ) {
1046         GLenum m = *((GLenum *) ((GLubyte *) mode + i * modestride));
1047	 CALL_DrawElements(ctx->Exec, ( m, count[i], type, indices[i] ));
1048      }
1049   }
1050}
1051
1052
1053/**
1054 * GL_NV_primitive_restart and GL 3.1
1055 */
1056void GLAPIENTRY
1057_mesa_PrimitiveRestartIndex(GLuint index)
1058{
1059   GET_CURRENT_CONTEXT(ctx);
1060
1061   if (!ctx->Extensions.NV_primitive_restart &&
1062       ctx->VersionMajor * 10 + ctx->VersionMinor < 31) {
1063      _mesa_error(ctx, GL_INVALID_OPERATION, "glPrimitiveRestartIndexNV()");
1064      return;
1065   }
1066
1067   ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx);
1068
1069   FLUSH_VERTICES(ctx, _NEW_TRANSFORM);
1070
1071   ctx->Array.RestartIndex = index;
1072}
1073
1074
1075/**
1076 * See GL_ARB_instanced_arrays.
1077 * Note that the instance divisor only applies to generic arrays, not
1078 * the legacy vertex arrays.
1079 */
1080void GLAPIENTRY
1081_mesa_VertexAttribDivisor(GLuint index, GLuint divisor)
1082{
1083   GET_CURRENT_CONTEXT(ctx);
1084   ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx);
1085
1086   if (!ctx->Extensions.ARB_instanced_arrays) {
1087      _mesa_error(ctx, GL_INVALID_OPERATION, "glVertexAttribDivisor()");
1088      return;
1089   }
1090
1091   if (index >= ctx->Const.VertexProgram.MaxAttribs) {
1092      _mesa_error(ctx, GL_INVALID_ENUM, "glVertexAttribDivisor(index = %u)",
1093                  index);
1094      return;
1095   }
1096
1097   ctx->Array.ArrayObj->VertexAttrib[index].InstanceDivisor = divisor;
1098}
1099
1100
1101
1102/**
1103 * Copy one client vertex array to another.
1104 */
1105void
1106_mesa_copy_client_array(struct gl_context *ctx,
1107                        struct gl_client_array *dst,
1108                        struct gl_client_array *src)
1109{
1110   dst->Size = src->Size;
1111   dst->Type = src->Type;
1112   dst->Format = src->Format;
1113   dst->Stride = src->Stride;
1114   dst->StrideB = src->StrideB;
1115   dst->Ptr = src->Ptr;
1116   dst->Enabled = src->Enabled;
1117   dst->Normalized = src->Normalized;
1118   dst->Integer = src->Integer;
1119   dst->InstanceDivisor = src->InstanceDivisor;
1120   dst->_ElementSize = src->_ElementSize;
1121   _mesa_reference_buffer_object(ctx, &dst->BufferObj, src->BufferObj);
1122   dst->_MaxElement = src->_MaxElement;
1123}
1124
1125
1126
1127/**
1128 * Print vertex array's fields.
1129 */
1130static void
1131print_array(const char *name, GLint index, const struct gl_client_array *array)
1132{
1133   if (index >= 0)
1134      printf("  %s[%d]: ", name, index);
1135   else
1136      printf("  %s: ", name);
1137   printf("Ptr=%p, Type=0x%x, Size=%d, ElemSize=%u, Stride=%d, Buffer=%u(Size %lu), MaxElem=%u\n",
1138	  array->Ptr, array->Type, array->Size,
1139	  array->_ElementSize, array->StrideB,
1140	  array->BufferObj->Name, (unsigned long) array->BufferObj->Size,
1141	  array->_MaxElement);
1142}
1143
1144
1145/**
1146 * Print current vertex object/array info.  For debug.
1147 */
1148void
1149_mesa_print_arrays(struct gl_context *ctx)
1150{
1151   struct gl_array_object *arrayObj = ctx->Array.ArrayObj;
1152   GLuint i;
1153
1154   _mesa_update_array_object_max_element(ctx, arrayObj);
1155
1156   printf("Array Object %u\n", arrayObj->Name);
1157   if (arrayObj->Vertex.Enabled)
1158      print_array("Vertex", -1, &arrayObj->Vertex);
1159   if (arrayObj->Normal.Enabled)
1160      print_array("Normal", -1, &arrayObj->Normal);
1161   if (arrayObj->Color.Enabled)
1162      print_array("Color", -1, &arrayObj->Color);
1163   for (i = 0; i < Elements(arrayObj->TexCoord); i++)
1164      if (arrayObj->TexCoord[i].Enabled)
1165         print_array("TexCoord", i, &arrayObj->TexCoord[i]);
1166   for (i = 0; i < Elements(arrayObj->VertexAttrib); i++)
1167      if (arrayObj->VertexAttrib[i].Enabled)
1168         print_array("Attrib", i, &arrayObj->VertexAttrib[i]);
1169   printf("  _MaxElement = %u\n", arrayObj->_MaxElement);
1170}
1171
1172
1173/**
1174 * Initialize vertex array state for given context.
1175 */
1176void
1177_mesa_init_varray(struct gl_context *ctx)
1178{
1179   ctx->Array.DefaultArrayObj = _mesa_new_array_object(ctx, 0);
1180   _mesa_reference_array_object(ctx, &ctx->Array.ArrayObj,
1181                                ctx->Array.DefaultArrayObj);
1182   ctx->Array.ActiveTexture = 0;   /* GL_ARB_multitexture */
1183
1184   ctx->Array.Objects = _mesa_NewHashTable();
1185}
1186
1187
1188/**
1189 * Callback for deleting an array object.  Called by _mesa_HashDeleteAll().
1190 */
1191static void
1192delete_arrayobj_cb(GLuint id, void *data, void *userData)
1193{
1194   struct gl_array_object *arrayObj = (struct gl_array_object *) data;
1195   struct gl_context *ctx = (struct gl_context *) userData;
1196   _mesa_delete_array_object(ctx, arrayObj);
1197}
1198
1199
1200/**
1201 * Free vertex array state for given context.
1202 */
1203void
1204_mesa_free_varray_data(struct gl_context *ctx)
1205{
1206   _mesa_HashDeleteAll(ctx->Array.Objects, delete_arrayobj_cb, ctx);
1207   _mesa_DeleteHashTable(ctx->Array.Objects);
1208}
1209