mesa: refactor: move _mesa_is_color/depth/stencil_format() helpers to image.c
[mesa.git] / src / mesa / main / varray.c
index 0982dc7977ff9b5f1303a6904446277e4ea94f80..be1c03cec2a88ac97e93f4bf628d3c256fe32650 100644 (file)
@@ -30,6 +30,7 @@
 #include "context.h"
 #include "enable.h"
 #include "enums.h"
+#include "hash.h"
 #include "mtypes.h"
 #include "varray.h"
 #include "arrayobj.h"
@@ -38,6 +39,8 @@
 
 /**
  * Set the fields of a vertex array.
+ * Also do an error check for GL_ARB_vertex_array_object: check that
+ * all arrays reside in VBOs when using a vertex array object.
  *
  * \param array  the array to update
  * \param dirtyBit  which bit to set in ctx->Array.NewState for this array
  * \param stride  stride between elements, in elements
  * \param normalized  are integer types converted to floats in [-1, 1]?
  * \param ptr  the address (or offset inside VBO) of the array data
+ * \return GL_TRUE if no error, GL_FALSE if error
  */
-static void
+static GLboolean
 update_array(GLcontext *ctx, struct gl_client_array *array,
              GLbitfield dirtyBit, GLsizei elementSize,
              GLint size, GLenum type, GLenum format,
              GLsizei stride, GLboolean normalized, const GLvoid *ptr)
 {
    ASSERT(format == GL_RGBA || format == GL_BGRA);
+
+   if (ctx->Array.ArrayObj->VBOonly &&
+       ctx->Array.ArrayBufferObj->Name == 0) {
+      /* GL_ARB_vertex_array_object requires that all arrays reside in VBOs.
+       * Generate GL_INVALID_OPERATION if that's not true.
+       */
+      _mesa_error(ctx, GL_INVALID_OPERATION,
+                  "glVertex/Normal/EtcPointer(non-VBO array)");
+      return GL_FALSE;
+   }
+
    array->Size = size;
    array->Type = type;
    array->Format = format;
@@ -70,6 +85,8 @@ update_array(GLcontext *ctx, struct gl_client_array *array,
 
    ctx->NewState |= _NEW_ARRAY;
    ctx->Array.NewState |= dirtyBit;
+
+   return GL_TRUE;
 }
 
 
@@ -118,12 +135,14 @@ _mesa_VertexPointer(GLint size, GLenum type, GLsizei stride, const GLvoid *ptr)
          break;
 #endif
       default:
-         _mesa_error( ctx, GL_INVALID_ENUM, "glVertexPointer(type)" );
+         _mesa_error( ctx, GL_INVALID_ENUM, "glVertexPointer(type=%s)",
+                      _mesa_lookup_enum_by_nr(type));
          return;
    }
 
-   update_array(ctx, &ctx->Array.ArrayObj->Vertex, _NEW_ARRAY_VERTEX,
-                elementSize, size, type, GL_RGBA, stride, GL_FALSE, ptr);
+   if (!update_array(ctx, &ctx->Array.ArrayObj->Vertex, _NEW_ARRAY_VERTEX,
+                     elementSize, size, type, GL_RGBA, stride, GL_FALSE, ptr))
+      return;
 
    if (ctx->Driver.VertexPointer)
       ctx->Driver.VertexPointer( ctx, size, type, stride, ptr );
@@ -168,12 +187,14 @@ _mesa_NormalPointer(GLenum type, GLsizei stride, const GLvoid *ptr )
          break;
 #endif
       default:
-         _mesa_error( ctx, GL_INVALID_ENUM, "glNormalPointer(type)" );
+         _mesa_error( ctx, GL_INVALID_ENUM, "glNormalPointer(type=%s)",
+                      _mesa_lookup_enum_by_nr(type));
          return;
    }
 
-   update_array(ctx, &ctx->Array.ArrayObj->Normal, _NEW_ARRAY_NORMAL,
-                elementSize, 3, type, GL_RGBA, stride, GL_TRUE, ptr);
+   if (!update_array(ctx, &ctx->Array.ArrayObj->Normal, _NEW_ARRAY_NORMAL,
+                     elementSize, 3, type, GL_RGBA, stride, GL_TRUE, ptr))
+      return;
 
    if (ctx->Driver.NormalPointer)
       ctx->Driver.NormalPointer( ctx, type, stride, ptr );
@@ -246,12 +267,14 @@ _mesa_ColorPointer(GLint size, GLenum type, GLsizei stride, const GLvoid *ptr)
          break;
 #endif
       default:
-         _mesa_error( ctx, GL_INVALID_ENUM, "glColorPointer(type)" );
+         _mesa_error( ctx, GL_INVALID_ENUM, "glColorPointer(type=%s)",
+                      _mesa_lookup_enum_by_nr(type));
          return;
    }
 
-   update_array(ctx, &ctx->Array.ArrayObj->Color, _NEW_ARRAY_COLOR0,
-                elementSize, size, type, format, stride, GL_TRUE, ptr);
+   if (!update_array(ctx, &ctx->Array.ArrayObj->Color, _NEW_ARRAY_COLOR0,
+                     elementSize, size, type, format, stride, GL_TRUE, ptr))
+      return;
 
    if (ctx->Driver.ColorPointer)
       ctx->Driver.ColorPointer( ctx, size, type, stride, ptr );
@@ -282,8 +305,9 @@ _mesa_FogCoordPointerEXT(GLenum type, GLsizei stride, const GLvoid *ptr)
          return;
    }
 
-   update_array(ctx, &ctx->Array.ArrayObj->FogCoord, _NEW_ARRAY_FOGCOORD,
-                elementSize, 1, type, GL_RGBA, stride, GL_FALSE, ptr);
+   if (!update_array(ctx, &ctx->Array.ArrayObj->FogCoord, _NEW_ARRAY_FOGCOORD,
+                     elementSize, 1, type, GL_RGBA, stride, GL_FALSE, ptr))
+      return;
 
    if (ctx->Driver.FogCoordPointer)
       ctx->Driver.FogCoordPointer( ctx, type, stride, ptr );
@@ -323,8 +347,9 @@ _mesa_IndexPointer(GLenum type, GLsizei stride, const GLvoid *ptr)
          return;
    }
 
-   update_array(ctx, &ctx->Array.ArrayObj->Index, _NEW_ARRAY_INDEX,
-                elementSize, 1, type, GL_RGBA, stride, GL_FALSE, ptr);
+   if (!update_array(ctx, &ctx->Array.ArrayObj->Index, _NEW_ARRAY_INDEX,
+                     elementSize, 1, type, GL_RGBA, stride, GL_FALSE, ptr))
+      return;
 
    if (ctx->Driver.IndexPointer)
       ctx->Driver.IndexPointer( ctx, type, stride, ptr );
@@ -393,12 +418,15 @@ _mesa_SecondaryColorPointerEXT(GLint size, GLenum type,
          elementSize = size * sizeof(GLdouble);
          break;
       default:
-         _mesa_error( ctx, GL_INVALID_ENUM, "glSecondaryColorPointer(type)" );
+         _mesa_error( ctx, GL_INVALID_ENUM, "glSecondaryColorPointer(type=%s)",
+                      _mesa_lookup_enum_by_nr(type));
          return;
    }
 
-   update_array(ctx, &ctx->Array.ArrayObj->SecondaryColor, _NEW_ARRAY_COLOR1,
-                elementSize, size, type, format, stride, GL_TRUE, ptr);
+   if (!update_array(ctx, &ctx->Array.ArrayObj->SecondaryColor,
+                     _NEW_ARRAY_COLOR1, elementSize, size, type,
+                     format, stride, GL_TRUE, ptr))
+      return;
 
    if (ctx->Driver.SecondaryColorPointer)
       ctx->Driver.SecondaryColorPointer( ctx, size, type, stride, ptr );
@@ -452,13 +480,15 @@ _mesa_TexCoordPointer(GLint size, GLenum type, GLsizei stride,
          break;
 #endif
       default:
-         _mesa_error( ctx, GL_INVALID_ENUM, "glTexCoordPointer(type)" );
+         _mesa_error( ctx, GL_INVALID_ENUM, "glTexCoordPointer(type=%s)",
+                      _mesa_lookup_enum_by_nr(type));
          return;
    }
 
-   update_array(ctx, &ctx->Array.ArrayObj->TexCoord[unit],
-                _NEW_ARRAY_TEXCOORD(unit),
-                elementSize, size, type, GL_RGBA, stride, GL_FALSE, ptr);
+   if (!update_array(ctx, &ctx->Array.ArrayObj->TexCoord[unit],
+                     _NEW_ARRAY_TEXCOORD(unit),
+                     elementSize, size, type, GL_RGBA, stride, GL_FALSE, ptr))
+      return;
 
    if (ctx->Driver.TexCoordPointer)
       ctx->Driver.TexCoordPointer( ctx, size, type, stride, ptr );
@@ -476,9 +506,10 @@ _mesa_EdgeFlagPointer(GLsizei stride, const GLvoid *ptr)
       return;
    }
 
-   update_array(ctx, &ctx->Array.ArrayObj->EdgeFlag, _NEW_ARRAY_EDGEFLAG,
-                sizeof(GLboolean), 1, GL_UNSIGNED_BYTE, GL_RGBA,
-                stride, GL_FALSE, ptr);
+   if (!update_array(ctx, &ctx->Array.ArrayObj->EdgeFlag, _NEW_ARRAY_EDGEFLAG,
+                     sizeof(GLboolean), 1, GL_UNSIGNED_BYTE, GL_RGBA,
+                     stride, GL_FALSE, ptr))
+      return;
 
    if (ctx->Driver.EdgeFlagPointer)
       ctx->Driver.EdgeFlagPointer( ctx, stride, ptr );
@@ -529,6 +560,7 @@ _mesa_VertexAttribPointerNV(GLuint index, GLint size, GLenum type,
 {
    GLboolean normalized = GL_FALSE;
    GLsizei elementSize;
+   GLenum format;
    GET_CURRENT_CONTEXT(ctx);
    ASSERT_OUTSIDE_BEGIN_END(ctx);
 
@@ -552,6 +584,21 @@ _mesa_VertexAttribPointerNV(GLuint index, GLint size, GLenum type,
       return;
    }
 
+   if (size == GL_BGRA) {
+      if (type != GL_UNSIGNED_BYTE) {
+         _mesa_error(ctx, GL_INVALID_VALUE,
+                     "glVertexAttribPointerNV(GL_BGRA/type)");
+         return;
+      }
+
+      format = GL_BGRA;
+      size = 4;
+      normalized = GL_TRUE;
+   }
+   else {
+      format = GL_RGBA;
+   }
+
    /* check for valid 'type' and compute StrideB right away */
    switch (type) {
       case GL_UNSIGNED_BYTE:
@@ -568,13 +615,15 @@ _mesa_VertexAttribPointerNV(GLuint index, GLint size, GLenum type,
          elementSize = size * sizeof(GLdouble);
          break;
       default:
-         _mesa_error( ctx, GL_INVALID_ENUM, "glVertexAttribPointerNV(type)" );
+         _mesa_error( ctx, GL_INVALID_ENUM, "glVertexAttribPointerNV(type=%s)",
+                      _mesa_lookup_enum_by_nr(type));
          return;
    }
 
-   update_array(ctx, &ctx->Array.ArrayObj->VertexAttrib[index],
-                _NEW_ARRAY_ATTRIB(index),
-                elementSize, size, type, GL_RGBA, stride, normalized, ptr);
+   if (!update_array(ctx, &ctx->Array.ArrayObj->VertexAttrib[index],
+                     _NEW_ARRAY_ATTRIB(index),
+                     elementSize, size, type, format, stride, normalized, ptr))
+      return;
 
    if (ctx->Driver.VertexAttribPointer)
       ctx->Driver.VertexAttribPointer( ctx, index, size, type, stride, ptr );
@@ -621,9 +670,14 @@ _mesa_VertexAttribPointerARB(GLuint index, GLint size, GLenum type,
                      "glVertexAttribPointerARB(GL_BGRA/type)");
          return;
       }
+      if (normalized != GL_TRUE) {
+         _mesa_error(ctx, GL_INVALID_VALUE,
+                     "glVertexAttribPointerARB(GL_BGRA/normalized)");
+         return;
+      }
+
       format = GL_BGRA;
       size = 4;
-      normalized = GL_TRUE;
    }
    else {
       format = GL_RGBA;
@@ -666,9 +720,10 @@ _mesa_VertexAttribPointerARB(GLuint index, GLint size, GLenum type,
          return;
    }
 
-   update_array(ctx, &ctx->Array.ArrayObj->VertexAttrib[index],
-                _NEW_ARRAY_ATTRIB(index),
-                elementSize, size, type, GL_RGBA, stride, normalized, ptr);
+   if (!update_array(ctx, &ctx->Array.ArrayObj->VertexAttrib[index],
+                     _NEW_ARRAY_ATTRIB(index),
+                     elementSize, size, type, format, stride, normalized, ptr))
+      return;
 
    if (ctx->Driver.VertexAttribPointer)
       ctx->Driver.VertexAttribPointer(ctx, index, size, type, stride, ptr);
@@ -1043,6 +1098,29 @@ _mesa_MultiModeDrawElementsIBM( const GLenum * mode, const GLsizei * count,
 }
 
 
+/**
+ * Copy one client vertex array to another.
+ */
+void
+_mesa_copy_client_array(GLcontext *ctx,
+                        struct gl_client_array *dst,
+                        struct gl_client_array *src)
+{
+   dst->Size = src->Size;
+   dst->Type = src->Type;
+   dst->Format = src->Format;
+   dst->Stride = src->Stride;
+   dst->StrideB = src->StrideB;
+   dst->Ptr = src->Ptr;
+   dst->Enabled = src->Enabled;
+   dst->Normalized = src->Normalized;
+   dst->_ElementSize = src->_ElementSize;
+   _mesa_reference_buffer_object(ctx, &dst->BufferObj, src->BufferObj);
+   dst->_MaxElement = src->_MaxElement;
+}
+
+
+
 /**
  * Print vertex array's fields.
  */
@@ -1079,10 +1157,10 @@ _mesa_print_arrays(GLcontext *ctx)
       print_array("Normal", -1, &arrayObj->Normal);
    if (arrayObj->Color.Enabled)
       print_array("Color", -1, &arrayObj->Color);
-   for (i = 0; i < MAX_TEXTURE_COORD_UNITS; i++)
+   for (i = 0; i < Elements(arrayObj->TexCoord); i++)
       if (arrayObj->TexCoord[i].Enabled)
          print_array("TexCoord", i, &arrayObj->TexCoord[i]);
-   for (i = 0; i < VERT_ATTRIB_MAX; i++)
+   for (i = 0; i < Elements(arrayObj->VertexAttrib); i++)
       if (arrayObj->VertexAttrib[i].Enabled)
          print_array("Attrib", i, &arrayObj->VertexAttrib[i]);
    _mesa_printf("  _MaxElement = %u\n", arrayObj->_MaxElement);
@@ -1099,4 +1177,29 @@ _mesa_init_varray(GLcontext *ctx)
    _mesa_reference_array_object(ctx, &ctx->Array.ArrayObj,
                                 ctx->Array.DefaultArrayObj);
    ctx->Array.ActiveTexture = 0;   /* GL_ARB_multitexture */
+
+   ctx->Array.Objects = _mesa_NewHashTable();
+}
+
+
+/**
+ * Callback for deleting an array object.  Called by _mesa_HashDeleteAll().
+ */
+static void
+delete_arrayobj_cb(GLuint id, void *data, void *userData)
+{
+   struct gl_array_object *arrayObj = (struct gl_array_object *) data;
+   GLcontext *ctx = (GLcontext *) userData;
+   _mesa_delete_array_object(ctx, arrayObj);
+}
+
+
+/**
+ * Free vertex array state for given context.
+ */
+void 
+_mesa_free_varray_data(GLcontext *ctx)
+{
+   _mesa_HashDeleteAll(ctx->Array.Objects, delete_arrayobj_cb, ctx);
+   _mesa_DeleteHashTable(ctx->Array.Objects);
 }