varray.c revision af69d88d
17117f1b4Smrg/* 27117f1b4Smrg * Mesa 3-D graphics library 37117f1b4Smrg * 4c1f859d4Smrg * Copyright (C) 1999-2008 Brian Paul All Rights Reserved. 54a49301eSmrg * Copyright (C) 2009 VMware, Inc. All Rights Reserved. 67117f1b4Smrg * 77117f1b4Smrg * Permission is hereby granted, free of charge, to any person obtaining a 87117f1b4Smrg * copy of this software and associated documentation files (the "Software"), 97117f1b4Smrg * to deal in the Software without restriction, including without limitation 107117f1b4Smrg * the rights to use, copy, modify, merge, publish, distribute, sublicense, 117117f1b4Smrg * and/or sell copies of the Software, and to permit persons to whom the 127117f1b4Smrg * Software is furnished to do so, subject to the following conditions: 137117f1b4Smrg * 147117f1b4Smrg * The above copyright notice and this permission notice shall be included 157117f1b4Smrg * in all copies or substantial portions of the Software. 167117f1b4Smrg * 177117f1b4Smrg * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 187117f1b4Smrg * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 197117f1b4Smrg * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 20af69d88dSmrg * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR 21af69d88dSmrg * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, 22af69d88dSmrg * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 23af69d88dSmrg * OTHER DEALINGS IN THE SOFTWARE. 247117f1b4Smrg */ 257117f1b4Smrg 267117f1b4Smrg 27af69d88dSmrg#include <inttypes.h> /* for PRId64 macro */ 28af69d88dSmrg 297117f1b4Smrg#include "glheader.h" 307117f1b4Smrg#include "imports.h" 317117f1b4Smrg#include "bufferobj.h" 327117f1b4Smrg#include "context.h" 337117f1b4Smrg#include "enable.h" 347117f1b4Smrg#include "enums.h" 354a49301eSmrg#include "hash.h" 363464ebd5Sriastradh#include "image.h" 373464ebd5Sriastradh#include "macros.h" 387117f1b4Smrg#include "mtypes.h" 397117f1b4Smrg#include "varray.h" 407117f1b4Smrg#include "arrayobj.h" 41cdc920a0Smrg#include "main/dispatch.h" 427117f1b4Smrg 437117f1b4Smrg 443464ebd5Sriastradh/** Used to do error checking for GL_EXT_vertex_array_bgra */ 453464ebd5Sriastradh#define BGRA_OR_4 5 463464ebd5Sriastradh 473464ebd5Sriastradh 483464ebd5Sriastradh/** Used to indicate which GL datatypes are accepted by each of the 493464ebd5Sriastradh * glVertex/Color/Attrib/EtcPointer() functions. 503464ebd5Sriastradh */ 51af69d88dSmrg#define BOOL_BIT (1 << 0) 52af69d88dSmrg#define BYTE_BIT (1 << 1) 53af69d88dSmrg#define UNSIGNED_BYTE_BIT (1 << 2) 54af69d88dSmrg#define SHORT_BIT (1 << 3) 55af69d88dSmrg#define UNSIGNED_SHORT_BIT (1 << 4) 56af69d88dSmrg#define INT_BIT (1 << 5) 57af69d88dSmrg#define UNSIGNED_INT_BIT (1 << 6) 58af69d88dSmrg#define HALF_BIT (1 << 7) 59af69d88dSmrg#define FLOAT_BIT (1 << 8) 60af69d88dSmrg#define DOUBLE_BIT (1 << 9) 61af69d88dSmrg#define FIXED_ES_BIT (1 << 10) 62af69d88dSmrg#define FIXED_GL_BIT (1 << 11) 63af69d88dSmrg#define UNSIGNED_INT_2_10_10_10_REV_BIT (1 << 12) 64af69d88dSmrg#define INT_2_10_10_10_REV_BIT (1 << 13) 65af69d88dSmrg#define UNSIGNED_INT_10F_11F_11F_REV_BIT (1 << 14) 66af69d88dSmrg#define ALL_TYPE_BITS ((1 << 15) - 1) 673464ebd5Sriastradh 683464ebd5Sriastradh 693464ebd5Sriastradh/** Convert GL datatype enum into a <type>_BIT value seen above */ 703464ebd5Sriastradhstatic GLbitfield 713464ebd5Sriastradhtype_to_bit(const struct gl_context *ctx, GLenum type) 723464ebd5Sriastradh{ 733464ebd5Sriastradh switch (type) { 743464ebd5Sriastradh case GL_BOOL: 753464ebd5Sriastradh return BOOL_BIT; 763464ebd5Sriastradh case GL_BYTE: 773464ebd5Sriastradh return BYTE_BIT; 783464ebd5Sriastradh case GL_UNSIGNED_BYTE: 793464ebd5Sriastradh return UNSIGNED_BYTE_BIT; 803464ebd5Sriastradh case GL_SHORT: 813464ebd5Sriastradh return SHORT_BIT; 823464ebd5Sriastradh case GL_UNSIGNED_SHORT: 833464ebd5Sriastradh return UNSIGNED_SHORT_BIT; 843464ebd5Sriastradh case GL_INT: 853464ebd5Sriastradh return INT_BIT; 863464ebd5Sriastradh case GL_UNSIGNED_INT: 873464ebd5Sriastradh return UNSIGNED_INT_BIT; 883464ebd5Sriastradh case GL_HALF_FLOAT: 893464ebd5Sriastradh if (ctx->Extensions.ARB_half_float_vertex) 903464ebd5Sriastradh return HALF_BIT; 913464ebd5Sriastradh else 923464ebd5Sriastradh return 0x0; 933464ebd5Sriastradh case GL_FLOAT: 943464ebd5Sriastradh return FLOAT_BIT; 953464ebd5Sriastradh case GL_DOUBLE: 963464ebd5Sriastradh return DOUBLE_BIT; 973464ebd5Sriastradh case GL_FIXED: 98af69d88dSmrg return _mesa_is_desktop_gl(ctx) ? FIXED_GL_BIT : FIXED_ES_BIT; 99af69d88dSmrg case GL_UNSIGNED_INT_2_10_10_10_REV: 100af69d88dSmrg return UNSIGNED_INT_2_10_10_10_REV_BIT; 101af69d88dSmrg case GL_INT_2_10_10_10_REV: 102af69d88dSmrg return INT_2_10_10_10_REV_BIT; 103af69d88dSmrg case GL_UNSIGNED_INT_10F_11F_11F_REV: 104af69d88dSmrg return UNSIGNED_INT_10F_11F_11F_REV_BIT; 1053464ebd5Sriastradh default: 1063464ebd5Sriastradh return 0; 1073464ebd5Sriastradh } 1083464ebd5Sriastradh} 1093464ebd5Sriastradh 1103464ebd5Sriastradh 1117117f1b4Smrg/** 112af69d88dSmrg * Sets the VertexBinding field in the vertex attribute given by attribIndex. 1137117f1b4Smrg */ 1147117f1b4Smrgstatic void 115af69d88dSmrgvertex_attrib_binding(struct gl_context *ctx, GLuint attribIndex, 116af69d88dSmrg GLuint bindingIndex) 117af69d88dSmrg{ 118af69d88dSmrg struct gl_vertex_array_object *vao = ctx->Array.VAO; 119af69d88dSmrg struct gl_vertex_attrib_array *array = &vao->VertexAttrib[attribIndex]; 120af69d88dSmrg 121af69d88dSmrg if (array->VertexBinding != bindingIndex) { 122af69d88dSmrg const GLbitfield64 array_bit = VERT_BIT(attribIndex); 123af69d88dSmrg 124af69d88dSmrg FLUSH_VERTICES(ctx, _NEW_ARRAY); 125af69d88dSmrg 126af69d88dSmrg vao->VertexBinding[array->VertexBinding]._BoundArrays &= ~array_bit; 127af69d88dSmrg vao->VertexBinding[bindingIndex]._BoundArrays |= array_bit; 128af69d88dSmrg 129af69d88dSmrg array->VertexBinding = bindingIndex; 130af69d88dSmrg 131af69d88dSmrg vao->NewArrays |= array_bit; 132af69d88dSmrg } 133af69d88dSmrg} 134af69d88dSmrg 135af69d88dSmrg 136af69d88dSmrg/** 137af69d88dSmrg * Binds a buffer object to the vertex buffer binding point given by index, 138af69d88dSmrg * and sets the Offset and Stride fields. 139af69d88dSmrg */ 140af69d88dSmrgstatic void 141af69d88dSmrgbind_vertex_buffer(struct gl_context *ctx, GLuint index, 142af69d88dSmrg struct gl_buffer_object *vbo, 143af69d88dSmrg GLintptr offset, GLsizei stride) 144af69d88dSmrg{ 145af69d88dSmrg struct gl_vertex_array_object *vao = ctx->Array.VAO; 146af69d88dSmrg struct gl_vertex_buffer_binding *binding = &vao->VertexBinding[index]; 147af69d88dSmrg 148af69d88dSmrg if (binding->BufferObj != vbo || 149af69d88dSmrg binding->Offset != offset || 150af69d88dSmrg binding->Stride != stride) { 151af69d88dSmrg 152af69d88dSmrg FLUSH_VERTICES(ctx, _NEW_ARRAY); 153af69d88dSmrg 154af69d88dSmrg _mesa_reference_buffer_object(ctx, &binding->BufferObj, vbo); 155af69d88dSmrg 156af69d88dSmrg binding->Offset = offset; 157af69d88dSmrg binding->Stride = stride; 158af69d88dSmrg 159af69d88dSmrg vao->NewArrays |= binding->_BoundArrays; 160af69d88dSmrg } 161af69d88dSmrg} 162af69d88dSmrg 163af69d88dSmrg 164af69d88dSmrg/** 165af69d88dSmrg * Sets the InstanceDivisor field in the vertex buffer binding point 166af69d88dSmrg * given by bindingIndex. 167af69d88dSmrg */ 168af69d88dSmrgstatic void 169af69d88dSmrgvertex_binding_divisor(struct gl_context *ctx, GLuint bindingIndex, 170af69d88dSmrg GLuint divisor) 171af69d88dSmrg{ 172af69d88dSmrg struct gl_vertex_array_object *vao = ctx->Array.VAO; 173af69d88dSmrg struct gl_vertex_buffer_binding *binding = 174af69d88dSmrg &vao->VertexBinding[bindingIndex]; 175af69d88dSmrg 176af69d88dSmrg if (binding->InstanceDivisor != divisor) { 177af69d88dSmrg FLUSH_VERTICES(ctx, _NEW_ARRAY); 178af69d88dSmrg binding->InstanceDivisor = divisor; 179af69d88dSmrg vao->NewArrays |= binding->_BoundArrays; 180af69d88dSmrg } 181af69d88dSmrg} 182af69d88dSmrg 183af69d88dSmrg 184af69d88dSmrg/** 185af69d88dSmrg * Examine the API profile and extensions to determine which types are legal 186af69d88dSmrg * for vertex arrays. This is called once from update_array_format(). 187af69d88dSmrg */ 188af69d88dSmrgstatic GLbitfield 189af69d88dSmrgget_legal_types_mask(const struct gl_context *ctx) 190af69d88dSmrg{ 191af69d88dSmrg GLbitfield legalTypesMask = ALL_TYPE_BITS; 192af69d88dSmrg 193af69d88dSmrg if (_mesa_is_gles(ctx)) { 194af69d88dSmrg legalTypesMask &= ~(FIXED_GL_BIT | 195af69d88dSmrg DOUBLE_BIT | 196af69d88dSmrg UNSIGNED_INT_10F_11F_11F_REV_BIT); 197af69d88dSmrg 198af69d88dSmrg /* GL_INT and GL_UNSIGNED_INT data is not allowed in OpenGL ES until 199af69d88dSmrg * 3.0. The 2_10_10_10 types are added in OpenGL ES 3.0 or 200af69d88dSmrg * GL_OES_vertex_type_10_10_10_2. GL_HALF_FLOAT data is not allowed 201af69d88dSmrg * until 3.0 or with the GL_OES_vertex_half float extension, which isn't 202af69d88dSmrg * quite as trivial as we'd like because it uses a different enum value 203af69d88dSmrg * for GL_HALF_FLOAT_OES. 204af69d88dSmrg */ 205af69d88dSmrg if (ctx->Version < 30) { 206af69d88dSmrg legalTypesMask &= ~(UNSIGNED_INT_BIT | 207af69d88dSmrg INT_BIT | 208af69d88dSmrg UNSIGNED_INT_2_10_10_10_REV_BIT | 209af69d88dSmrg INT_2_10_10_10_REV_BIT | 210af69d88dSmrg HALF_BIT); 211af69d88dSmrg } 212af69d88dSmrg } 213af69d88dSmrg else { 214af69d88dSmrg legalTypesMask &= ~FIXED_ES_BIT; 215af69d88dSmrg 216af69d88dSmrg if (!ctx->Extensions.ARB_ES2_compatibility) 217af69d88dSmrg legalTypesMask &= ~FIXED_GL_BIT; 218af69d88dSmrg 219af69d88dSmrg if (!ctx->Extensions.ARB_vertex_type_2_10_10_10_rev) 220af69d88dSmrg legalTypesMask &= ~(UNSIGNED_INT_2_10_10_10_REV_BIT | 221af69d88dSmrg INT_2_10_10_10_REV_BIT); 222af69d88dSmrg 223af69d88dSmrg if (!ctx->Extensions.ARB_vertex_type_10f_11f_11f_rev) 224af69d88dSmrg legalTypesMask &= ~UNSIGNED_INT_10F_11F_11F_REV_BIT; 225af69d88dSmrg } 226af69d88dSmrg 227af69d88dSmrg return legalTypesMask; 228af69d88dSmrg} 229af69d88dSmrg 230af69d88dSmrg 231af69d88dSmrg/** 232af69d88dSmrg * Does error checking and updates the format in an attrib array. 233af69d88dSmrg * 234af69d88dSmrg * Called by update_array() and VertexAttrib*Format(). 235af69d88dSmrg * 236af69d88dSmrg * \param func Name of calling function used for error reporting 237af69d88dSmrg * \param attrib The index of the attribute array 238af69d88dSmrg * \param legalTypes Bitmask of *_BIT above indicating legal datatypes 239af69d88dSmrg * \param sizeMin Min allowable size value 240af69d88dSmrg * \param sizeMax Max allowable size value (may also be BGRA_OR_4) 241af69d88dSmrg * \param size Components per element (1, 2, 3 or 4) 242af69d88dSmrg * \param type Datatype of each component (GL_FLOAT, GL_INT, etc) 243af69d88dSmrg * \param normalized Whether integer types are converted to floats in [-1, 1] 244af69d88dSmrg * \param integer Integer-valued values (will not be normalized to [-1, 1]) 245af69d88dSmrg * \param relativeOffset Offset of the first element relative to the binding offset. 246af69d88dSmrg */ 247af69d88dSmrgstatic bool 248af69d88dSmrgupdate_array_format(struct gl_context *ctx, 249af69d88dSmrg const char *func, 250af69d88dSmrg GLuint attrib, GLbitfield legalTypesMask, 251af69d88dSmrg GLint sizeMin, GLint sizeMax, 252af69d88dSmrg GLint size, GLenum type, 253af69d88dSmrg GLboolean normalized, GLboolean integer, 254af69d88dSmrg GLuint relativeOffset) 2557117f1b4Smrg{ 256af69d88dSmrg struct gl_vertex_attrib_array *array; 2573464ebd5Sriastradh GLbitfield typeBit; 258af69d88dSmrg GLuint elementSize; 2593464ebd5Sriastradh GLenum format = GL_RGBA; 2603464ebd5Sriastradh 261af69d88dSmrg if (ctx->Array.LegalTypesMask == 0) { 262af69d88dSmrg /* One-time initialization. We can't do this in _mesa_init_varrays() 263af69d88dSmrg * below because extensions are not yet enabled at that point. 264af69d88dSmrg */ 265af69d88dSmrg ctx->Array.LegalTypesMask = get_legal_types_mask(ctx); 2663464ebd5Sriastradh } 267af69d88dSmrg 268af69d88dSmrg legalTypesMask &= ctx->Array.LegalTypesMask; 269af69d88dSmrg 270af69d88dSmrg if (_mesa_is_gles(ctx) && sizeMax == BGRA_OR_4) { 271af69d88dSmrg /* BGRA ordering is not supported in ES contexts. 272af69d88dSmrg */ 273af69d88dSmrg sizeMax = 4; 2743464ebd5Sriastradh } 2753464ebd5Sriastradh 2763464ebd5Sriastradh typeBit = type_to_bit(ctx, type); 2773464ebd5Sriastradh if (typeBit == 0x0 || (typeBit & legalTypesMask) == 0x0) { 2783464ebd5Sriastradh _mesa_error(ctx, GL_INVALID_ENUM, "%s(type = %s)", 2793464ebd5Sriastradh func, _mesa_lookup_enum_by_nr(type)); 280af69d88dSmrg return false; 2813464ebd5Sriastradh } 2823464ebd5Sriastradh 2833464ebd5Sriastradh /* Do size parameter checking. 2843464ebd5Sriastradh * If sizeMax = BGRA_OR_4 it means that size = GL_BGRA is legal and 2853464ebd5Sriastradh * must be handled specially. 2863464ebd5Sriastradh */ 2873464ebd5Sriastradh if (ctx->Extensions.EXT_vertex_array_bgra && 2883464ebd5Sriastradh sizeMax == BGRA_OR_4 && 2893464ebd5Sriastradh size == GL_BGRA) { 290af69d88dSmrg /* Page 298 of the PDF of the OpenGL 4.3 (Core Profile) spec says: 291af69d88dSmrg * 292af69d88dSmrg * "An INVALID_OPERATION error is generated under any of the following 293af69d88dSmrg * conditions: 294af69d88dSmrg * ... 295af69d88dSmrg * • size is BGRA and type is not UNSIGNED_BYTE, INT_2_10_10_10_REV 296af69d88dSmrg * or UNSIGNED_INT_2_10_10_10_REV; 297af69d88dSmrg * ... 298af69d88dSmrg * • size is BGRA and normalized is FALSE;" 299af69d88dSmrg */ 300af69d88dSmrg bool bgra_error = false; 301af69d88dSmrg 302af69d88dSmrg if (ctx->Extensions.ARB_vertex_type_2_10_10_10_rev) { 303af69d88dSmrg if (type != GL_UNSIGNED_INT_2_10_10_10_REV && 304af69d88dSmrg type != GL_INT_2_10_10_10_REV && 305af69d88dSmrg type != GL_UNSIGNED_BYTE) 306af69d88dSmrg bgra_error = true; 307af69d88dSmrg } else if (type != GL_UNSIGNED_BYTE) 308af69d88dSmrg bgra_error = true; 309af69d88dSmrg 310af69d88dSmrg if (bgra_error) { 311af69d88dSmrg _mesa_error(ctx, GL_INVALID_OPERATION, "%s(size=GL_BGRA and type=%s)", 312af69d88dSmrg func, _mesa_lookup_enum_by_nr(type)); 313af69d88dSmrg return false; 314af69d88dSmrg } 315af69d88dSmrg 316af69d88dSmrg if (!normalized) { 317af69d88dSmrg _mesa_error(ctx, GL_INVALID_OPERATION, 318af69d88dSmrg "%s(size=GL_BGRA and normalized=GL_FALSE)", func); 319af69d88dSmrg return false; 3203464ebd5Sriastradh } 321af69d88dSmrg 3223464ebd5Sriastradh format = GL_BGRA; 3233464ebd5Sriastradh size = 4; 3243464ebd5Sriastradh } 3253464ebd5Sriastradh else if (size < sizeMin || size > sizeMax || size > 4) { 3263464ebd5Sriastradh _mesa_error(ctx, GL_INVALID_VALUE, "%s(size=%d)", func, size); 327af69d88dSmrg return false; 328af69d88dSmrg } 329af69d88dSmrg 330af69d88dSmrg if (ctx->Extensions.ARB_vertex_type_2_10_10_10_rev && 331af69d88dSmrg (type == GL_UNSIGNED_INT_2_10_10_10_REV || 332af69d88dSmrg type == GL_INT_2_10_10_10_REV) && size != 4) { 333af69d88dSmrg _mesa_error(ctx, GL_INVALID_OPERATION, "%s(size=%d)", func, size); 334af69d88dSmrg return false; 335af69d88dSmrg } 336af69d88dSmrg 337af69d88dSmrg /* The ARB_vertex_attrib_binding_spec says: 338af69d88dSmrg * 339af69d88dSmrg * An INVALID_VALUE error is generated if <relativeoffset> is larger than 340af69d88dSmrg * the value of MAX_VERTEX_ATTRIB_RELATIVE_OFFSET. 341af69d88dSmrg */ 342af69d88dSmrg if (relativeOffset > ctx->Const.MaxVertexAttribRelativeOffset) { 343af69d88dSmrg _mesa_error(ctx, GL_INVALID_VALUE, 344af69d88dSmrg "%s(relativeOffset=%d > " 345af69d88dSmrg "GL_MAX_VERTEX_ATTRIB_RELATIVE_OFFSET)", 346af69d88dSmrg func, relativeOffset); 347af69d88dSmrg return false; 348af69d88dSmrg } 349af69d88dSmrg 350af69d88dSmrg if (ctx->Extensions.ARB_vertex_type_10f_11f_11f_rev && 351af69d88dSmrg type == GL_UNSIGNED_INT_10F_11F_11F_REV && size != 3) { 352af69d88dSmrg _mesa_error(ctx, GL_INVALID_OPERATION, "%s(size=%d)", func, size); 353af69d88dSmrg return false; 3543464ebd5Sriastradh } 3553464ebd5Sriastradh 3563464ebd5Sriastradh ASSERT(size <= 4); 3573464ebd5Sriastradh 358af69d88dSmrg elementSize = _mesa_bytes_per_vertex_attrib(size, type); 359af69d88dSmrg assert(elementSize != -1); 360af69d88dSmrg 361af69d88dSmrg array = &ctx->Array.VAO->VertexAttrib[attrib]; 362af69d88dSmrg array->Size = size; 363af69d88dSmrg array->Type = type; 364af69d88dSmrg array->Format = format; 365af69d88dSmrg array->Normalized = normalized; 366af69d88dSmrg array->Integer = integer; 367af69d88dSmrg array->RelativeOffset = relativeOffset; 368af69d88dSmrg array->_ElementSize = elementSize; 369af69d88dSmrg 370af69d88dSmrg ctx->Array.VAO->NewArrays |= VERT_BIT(attrib); 371af69d88dSmrg ctx->NewState |= _NEW_ARRAY; 372af69d88dSmrg 373af69d88dSmrg return true; 374af69d88dSmrg} 375af69d88dSmrg 376af69d88dSmrg 377af69d88dSmrg/** 378af69d88dSmrg * Do error checking and update state for glVertex/Color/TexCoord/...Pointer 379af69d88dSmrg * functions. 380af69d88dSmrg * 381af69d88dSmrg * \param func name of calling function used for error reporting 382af69d88dSmrg * \param attrib the attribute array index to update 383af69d88dSmrg * \param legalTypes bitmask of *_BIT above indicating legal datatypes 384af69d88dSmrg * \param sizeMin min allowable size value 385af69d88dSmrg * \param sizeMax max allowable size value (may also be BGRA_OR_4) 386af69d88dSmrg * \param size components per element (1, 2, 3 or 4) 387af69d88dSmrg * \param type datatype of each component (GL_FLOAT, GL_INT, etc) 388af69d88dSmrg * \param stride stride between elements, in elements 389af69d88dSmrg * \param normalized are integer types converted to floats in [-1, 1]? 390af69d88dSmrg * \param integer integer-valued values (will not be normalized to [-1,1]) 391af69d88dSmrg * \param ptr the address (or offset inside VBO) of the array data 392af69d88dSmrg */ 393af69d88dSmrgstatic void 394af69d88dSmrgupdate_array(struct gl_context *ctx, 395af69d88dSmrg const char *func, 396af69d88dSmrg GLuint attrib, GLbitfield legalTypesMask, 397af69d88dSmrg GLint sizeMin, GLint sizeMax, 398af69d88dSmrg GLint size, GLenum type, GLsizei stride, 399af69d88dSmrg GLboolean normalized, GLboolean integer, 400af69d88dSmrg const GLvoid *ptr) 401af69d88dSmrg{ 402af69d88dSmrg struct gl_vertex_attrib_array *array; 403af69d88dSmrg GLsizei effectiveStride; 404af69d88dSmrg 405af69d88dSmrg /* Page 407 (page 423 of the PDF) of the OpenGL 3.0 spec says: 406af69d88dSmrg * 407af69d88dSmrg * "Client vertex arrays - all vertex array attribute pointers must 408af69d88dSmrg * refer to buffer objects (section 2.9.2). The default vertex array 409af69d88dSmrg * object (the name zero) is also deprecated. Calling 410af69d88dSmrg * VertexAttribPointer when no buffer object or no vertex array object 411af69d88dSmrg * is bound will generate an INVALID_OPERATION error..." 412af69d88dSmrg * 413af69d88dSmrg * The check for VBOs is handled below. 414af69d88dSmrg */ 415af69d88dSmrg if (ctx->API == API_OPENGL_CORE 416af69d88dSmrg && (ctx->Array.VAO == ctx->Array.DefaultVAO)) { 417af69d88dSmrg _mesa_error(ctx, GL_INVALID_OPERATION, "%s(no array object bound)", 418af69d88dSmrg func); 419af69d88dSmrg return; 420af69d88dSmrg } 421af69d88dSmrg 4223464ebd5Sriastradh if (stride < 0) { 4233464ebd5Sriastradh _mesa_error( ctx, GL_INVALID_VALUE, "%s(stride=%d)", func, stride ); 4243464ebd5Sriastradh return; 4253464ebd5Sriastradh } 4264a49301eSmrg 427af69d88dSmrg /* Page 29 (page 44 of the PDF) of the OpenGL 3.3 spec says: 428af69d88dSmrg * 429af69d88dSmrg * "An INVALID_OPERATION error is generated under any of the following 430af69d88dSmrg * conditions: 431af69d88dSmrg * 432af69d88dSmrg * ... 433af69d88dSmrg * 434af69d88dSmrg * * any of the *Pointer commands specifying the location and 435af69d88dSmrg * organization of vertex array data are called while zero is bound 436af69d88dSmrg * to the ARRAY_BUFFER buffer object binding point (see section 437af69d88dSmrg * 2.9.6), and the pointer argument is not NULL." 438af69d88dSmrg */ 439af69d88dSmrg if (ptr != NULL && ctx->Array.VAO->ARBsemantics && 440af69d88dSmrg !_mesa_is_bufferobj(ctx->Array.ArrayBufferObj)) { 4413464ebd5Sriastradh _mesa_error(ctx, GL_INVALID_OPERATION, "%s(non-VBO array)", func); 4424a49301eSmrg return; 4434a49301eSmrg } 4444a49301eSmrg 445af69d88dSmrg if (!update_array_format(ctx, func, attrib, legalTypesMask, sizeMin, 446af69d88dSmrg sizeMax, size, type, normalized, integer, 0)) { 447af69d88dSmrg return; 448af69d88dSmrg } 4493464ebd5Sriastradh 450af69d88dSmrg /* Reset the vertex attrib binding */ 451af69d88dSmrg vertex_attrib_binding(ctx, attrib, attrib); 4524a49301eSmrg 453af69d88dSmrg /* The Stride and Ptr fields are not set by update_array_format() */ 454af69d88dSmrg array = &ctx->Array.VAO->VertexAttrib[attrib]; 455af69d88dSmrg array->Stride = stride; 456af69d88dSmrg array->Ptr = (const GLvoid *) ptr; 457c1f859d4Smrg 458af69d88dSmrg /* Update the vertex buffer binding */ 459af69d88dSmrg effectiveStride = stride != 0 ? stride : array->_ElementSize; 460af69d88dSmrg bind_vertex_buffer(ctx, attrib, ctx->Array.ArrayBufferObj, 461af69d88dSmrg (GLintptr) ptr, effectiveStride); 4627117f1b4Smrg} 4637117f1b4Smrg 4647117f1b4Smrg 4657117f1b4Smrgvoid GLAPIENTRY 4667117f1b4Smrg_mesa_VertexPointer(GLint size, GLenum type, GLsizei stride, const GLvoid *ptr) 4677117f1b4Smrg{ 4687117f1b4Smrg GET_CURRENT_CONTEXT(ctx); 469af69d88dSmrg GLbitfield legalTypes = (ctx->API == API_OPENGLES) 470af69d88dSmrg ? (BYTE_BIT | SHORT_BIT | FLOAT_BIT | FIXED_ES_BIT) 471af69d88dSmrg : (SHORT_BIT | INT_BIT | FLOAT_BIT | 472af69d88dSmrg DOUBLE_BIT | HALF_BIT | 473af69d88dSmrg UNSIGNED_INT_2_10_10_10_REV_BIT | 474af69d88dSmrg INT_2_10_10_10_REV_BIT); 4757117f1b4Smrg 476af69d88dSmrg FLUSH_VERTICES(ctx, 0); 4777117f1b4Smrg 478af69d88dSmrg update_array(ctx, "glVertexPointer", VERT_ATTRIB_POS, 4793464ebd5Sriastradh legalTypes, 2, 4, 4803464ebd5Sriastradh size, type, stride, GL_FALSE, GL_FALSE, ptr); 4817117f1b4Smrg} 4827117f1b4Smrg 4837117f1b4Smrg 4847117f1b4Smrgvoid GLAPIENTRY 4857117f1b4Smrg_mesa_NormalPointer(GLenum type, GLsizei stride, const GLvoid *ptr ) 4867117f1b4Smrg{ 4877117f1b4Smrg GET_CURRENT_CONTEXT(ctx); 488af69d88dSmrg const GLbitfield legalTypes = (ctx->API == API_OPENGLES) 489af69d88dSmrg ? (BYTE_BIT | SHORT_BIT | FLOAT_BIT | FIXED_ES_BIT) 490af69d88dSmrg : (BYTE_BIT | SHORT_BIT | INT_BIT | 491af69d88dSmrg HALF_BIT | FLOAT_BIT | DOUBLE_BIT | 492af69d88dSmrg UNSIGNED_INT_2_10_10_10_REV_BIT | 493af69d88dSmrg INT_2_10_10_10_REV_BIT); 494af69d88dSmrg 495af69d88dSmrg FLUSH_VERTICES(ctx, 0); 4967117f1b4Smrg 497af69d88dSmrg update_array(ctx, "glNormalPointer", VERT_ATTRIB_NORMAL, 4983464ebd5Sriastradh legalTypes, 3, 3, 4993464ebd5Sriastradh 3, type, stride, GL_TRUE, GL_FALSE, ptr); 5007117f1b4Smrg} 5017117f1b4Smrg 5027117f1b4Smrg 5037117f1b4Smrgvoid GLAPIENTRY 5047117f1b4Smrg_mesa_ColorPointer(GLint size, GLenum type, GLsizei stride, const GLvoid *ptr) 5057117f1b4Smrg{ 5067117f1b4Smrg GET_CURRENT_CONTEXT(ctx); 507af69d88dSmrg const GLbitfield legalTypes = (ctx->API == API_OPENGLES) 508af69d88dSmrg ? (UNSIGNED_BYTE_BIT | HALF_BIT | FLOAT_BIT | FIXED_ES_BIT) 509af69d88dSmrg : (BYTE_BIT | UNSIGNED_BYTE_BIT | 510af69d88dSmrg SHORT_BIT | UNSIGNED_SHORT_BIT | 511af69d88dSmrg INT_BIT | UNSIGNED_INT_BIT | 512af69d88dSmrg HALF_BIT | FLOAT_BIT | DOUBLE_BIT | 513af69d88dSmrg UNSIGNED_INT_2_10_10_10_REV_BIT | 514af69d88dSmrg INT_2_10_10_10_REV_BIT); 515af69d88dSmrg const GLint sizeMin = (ctx->API == API_OPENGLES) ? 4 : 3; 516af69d88dSmrg 517af69d88dSmrg FLUSH_VERTICES(ctx, 0); 518af69d88dSmrg 519af69d88dSmrg update_array(ctx, "glColorPointer", VERT_ATTRIB_COLOR0, 520af69d88dSmrg legalTypes, sizeMin, BGRA_OR_4, 5213464ebd5Sriastradh size, type, stride, GL_TRUE, GL_FALSE, ptr); 5227117f1b4Smrg} 5237117f1b4Smrg 5247117f1b4Smrg 5257117f1b4Smrgvoid GLAPIENTRY 526af69d88dSmrg_mesa_FogCoordPointer(GLenum type, GLsizei stride, const GLvoid *ptr) 5277117f1b4Smrg{ 5283464ebd5Sriastradh const GLbitfield legalTypes = (HALF_BIT | FLOAT_BIT | DOUBLE_BIT); 5297117f1b4Smrg GET_CURRENT_CONTEXT(ctx); 5307117f1b4Smrg 531af69d88dSmrg FLUSH_VERTICES(ctx, 0); 532af69d88dSmrg 533af69d88dSmrg update_array(ctx, "glFogCoordPointer", VERT_ATTRIB_FOG, 5343464ebd5Sriastradh legalTypes, 1, 1, 5353464ebd5Sriastradh 1, type, stride, GL_FALSE, GL_FALSE, ptr); 5367117f1b4Smrg} 5377117f1b4Smrg 5387117f1b4Smrg 5397117f1b4Smrgvoid GLAPIENTRY 5407117f1b4Smrg_mesa_IndexPointer(GLenum type, GLsizei stride, const GLvoid *ptr) 5417117f1b4Smrg{ 5423464ebd5Sriastradh const GLbitfield legalTypes = (UNSIGNED_BYTE_BIT | SHORT_BIT | INT_BIT | 5433464ebd5Sriastradh FLOAT_BIT | DOUBLE_BIT); 5447117f1b4Smrg GET_CURRENT_CONTEXT(ctx); 5457117f1b4Smrg 546af69d88dSmrg FLUSH_VERTICES(ctx, 0); 547af69d88dSmrg 548af69d88dSmrg update_array(ctx, "glIndexPointer", VERT_ATTRIB_COLOR_INDEX, 5493464ebd5Sriastradh legalTypes, 1, 1, 5503464ebd5Sriastradh 1, type, stride, GL_FALSE, GL_FALSE, ptr); 5517117f1b4Smrg} 5527117f1b4Smrg 5537117f1b4Smrg 5547117f1b4Smrgvoid GLAPIENTRY 555af69d88dSmrg_mesa_SecondaryColorPointer(GLint size, GLenum type, 5567117f1b4Smrg GLsizei stride, const GLvoid *ptr) 5577117f1b4Smrg{ 5583464ebd5Sriastradh const GLbitfield legalTypes = (BYTE_BIT | UNSIGNED_BYTE_BIT | 5593464ebd5Sriastradh SHORT_BIT | UNSIGNED_SHORT_BIT | 5603464ebd5Sriastradh INT_BIT | UNSIGNED_INT_BIT | 561af69d88dSmrg HALF_BIT | FLOAT_BIT | DOUBLE_BIT | 562af69d88dSmrg UNSIGNED_INT_2_10_10_10_REV_BIT | 563af69d88dSmrg INT_2_10_10_10_REV_BIT); 5647117f1b4Smrg GET_CURRENT_CONTEXT(ctx); 5657117f1b4Smrg 566af69d88dSmrg FLUSH_VERTICES(ctx, 0); 567af69d88dSmrg 568af69d88dSmrg update_array(ctx, "glSecondaryColorPointer", VERT_ATTRIB_COLOR1, 5693464ebd5Sriastradh legalTypes, 3, BGRA_OR_4, 5703464ebd5Sriastradh size, type, stride, GL_TRUE, GL_FALSE, ptr); 5717117f1b4Smrg} 5727117f1b4Smrg 5737117f1b4Smrg 5747117f1b4Smrgvoid GLAPIENTRY 5757117f1b4Smrg_mesa_TexCoordPointer(GLint size, GLenum type, GLsizei stride, 5767117f1b4Smrg const GLvoid *ptr) 5777117f1b4Smrg{ 5787117f1b4Smrg GET_CURRENT_CONTEXT(ctx); 579af69d88dSmrg GLbitfield legalTypes = (ctx->API == API_OPENGLES) 580af69d88dSmrg ? (BYTE_BIT | SHORT_BIT | FLOAT_BIT | FIXED_ES_BIT) 581af69d88dSmrg : (SHORT_BIT | INT_BIT | 582af69d88dSmrg HALF_BIT | FLOAT_BIT | DOUBLE_BIT | 583af69d88dSmrg UNSIGNED_INT_2_10_10_10_REV_BIT | 584af69d88dSmrg INT_2_10_10_10_REV_BIT); 585af69d88dSmrg const GLint sizeMin = (ctx->API == API_OPENGLES) ? 2 : 1; 5867117f1b4Smrg const GLuint unit = ctx->Array.ActiveTexture; 5877117f1b4Smrg 588af69d88dSmrg FLUSH_VERTICES(ctx, 0); 589cdc920a0Smrg 590af69d88dSmrg update_array(ctx, "glTexCoordPointer", VERT_ATTRIB_TEX(unit), 591af69d88dSmrg legalTypes, sizeMin, 4, 5923464ebd5Sriastradh size, type, stride, GL_FALSE, GL_FALSE, 5933464ebd5Sriastradh ptr); 5947117f1b4Smrg} 5957117f1b4Smrg 5967117f1b4Smrg 5977117f1b4Smrgvoid GLAPIENTRY 5987117f1b4Smrg_mesa_EdgeFlagPointer(GLsizei stride, const GLvoid *ptr) 5997117f1b4Smrg{ 6003464ebd5Sriastradh const GLbitfield legalTypes = UNSIGNED_BYTE_BIT; 601af69d88dSmrg /* this is the same type that glEdgeFlag uses */ 602af69d88dSmrg const GLboolean integer = GL_FALSE; 6037117f1b4Smrg GET_CURRENT_CONTEXT(ctx); 6047117f1b4Smrg 605af69d88dSmrg FLUSH_VERTICES(ctx, 0); 606af69d88dSmrg 607af69d88dSmrg update_array(ctx, "glEdgeFlagPointer", VERT_ATTRIB_EDGEFLAG, 6083464ebd5Sriastradh legalTypes, 1, 1, 6093464ebd5Sriastradh 1, GL_UNSIGNED_BYTE, stride, GL_FALSE, integer, ptr); 6107117f1b4Smrg} 6117117f1b4Smrg 6127117f1b4Smrg 613c1f859d4Smrgvoid GLAPIENTRY 614af69d88dSmrg_mesa_PointSizePointerOES(GLenum type, GLsizei stride, const GLvoid *ptr) 615c1f859d4Smrg{ 6163464ebd5Sriastradh const GLbitfield legalTypes = (FLOAT_BIT | FIXED_ES_BIT); 617c1f859d4Smrg GET_CURRENT_CONTEXT(ctx); 618af69d88dSmrg 619af69d88dSmrg FLUSH_VERTICES(ctx, 0); 620c1f859d4Smrg 6213464ebd5Sriastradh if (ctx->API != API_OPENGLES) { 6223464ebd5Sriastradh _mesa_error(ctx, GL_INVALID_OPERATION, 6233464ebd5Sriastradh "glPointSizePointer(ES 1.x only)"); 624c1f859d4Smrg return; 625c1f859d4Smrg } 6263464ebd5Sriastradh 627af69d88dSmrg update_array(ctx, "glPointSizePointer", VERT_ATTRIB_POINT_SIZE, 6283464ebd5Sriastradh legalTypes, 1, 1, 6293464ebd5Sriastradh 1, type, stride, GL_FALSE, GL_FALSE, ptr); 630c1f859d4Smrg} 631c1f859d4Smrg 632c1f859d4Smrg 6334a49301eSmrg/** 6344a49301eSmrg * Set a generic vertex attribute array. 6354a49301eSmrg * Note that these arrays DO NOT alias the conventional GL vertex arrays 6364a49301eSmrg * (position, normal, color, fog, texcoord, etc). 6374a49301eSmrg */ 6387117f1b4Smrgvoid GLAPIENTRY 639af69d88dSmrg_mesa_VertexAttribPointer(GLuint index, GLint size, GLenum type, 6407117f1b4Smrg GLboolean normalized, 6417117f1b4Smrg GLsizei stride, const GLvoid *ptr) 6427117f1b4Smrg{ 6433464ebd5Sriastradh const GLbitfield legalTypes = (BYTE_BIT | UNSIGNED_BYTE_BIT | 6443464ebd5Sriastradh SHORT_BIT | UNSIGNED_SHORT_BIT | 6453464ebd5Sriastradh INT_BIT | UNSIGNED_INT_BIT | 6463464ebd5Sriastradh HALF_BIT | FLOAT_BIT | DOUBLE_BIT | 647af69d88dSmrg FIXED_ES_BIT | FIXED_GL_BIT | 648af69d88dSmrg UNSIGNED_INT_2_10_10_10_REV_BIT | 649af69d88dSmrg INT_2_10_10_10_REV_BIT | 650af69d88dSmrg UNSIGNED_INT_10F_11F_11F_REV_BIT); 6517117f1b4Smrg GET_CURRENT_CONTEXT(ctx); 6527117f1b4Smrg 653af69d88dSmrg if (index >= ctx->Const.Program[MESA_SHADER_VERTEX].MaxAttribs) { 6547117f1b4Smrg _mesa_error(ctx, GL_INVALID_VALUE, "glVertexAttribPointerARB(index)"); 6557117f1b4Smrg return; 6567117f1b4Smrg } 6577117f1b4Smrg 658af69d88dSmrg update_array(ctx, "glVertexAttribPointer", VERT_ATTRIB_GENERIC(index), 6593464ebd5Sriastradh legalTypes, 1, BGRA_OR_4, 6603464ebd5Sriastradh size, type, stride, normalized, GL_FALSE, ptr); 6613464ebd5Sriastradh} 6623464ebd5Sriastradh 6633464ebd5Sriastradh 6643464ebd5Sriastradh/** 6653464ebd5Sriastradh * GL_EXT_gpu_shader4 / GL 3.0. 6663464ebd5Sriastradh * Set an integer-valued vertex attribute array. 6673464ebd5Sriastradh * Note that these arrays DO NOT alias the conventional GL vertex arrays 6683464ebd5Sriastradh * (position, normal, color, fog, texcoord, etc). 6693464ebd5Sriastradh */ 6703464ebd5Sriastradhvoid GLAPIENTRY 6713464ebd5Sriastradh_mesa_VertexAttribIPointer(GLuint index, GLint size, GLenum type, 6723464ebd5Sriastradh GLsizei stride, const GLvoid *ptr) 6733464ebd5Sriastradh{ 6743464ebd5Sriastradh const GLbitfield legalTypes = (BYTE_BIT | UNSIGNED_BYTE_BIT | 6753464ebd5Sriastradh SHORT_BIT | UNSIGNED_SHORT_BIT | 6763464ebd5Sriastradh INT_BIT | UNSIGNED_INT_BIT); 6773464ebd5Sriastradh const GLboolean normalized = GL_FALSE; 6783464ebd5Sriastradh const GLboolean integer = GL_TRUE; 6793464ebd5Sriastradh GET_CURRENT_CONTEXT(ctx); 6803464ebd5Sriastradh 681af69d88dSmrg if (index >= ctx->Const.Program[MESA_SHADER_VERTEX].MaxAttribs) { 6823464ebd5Sriastradh _mesa_error(ctx, GL_INVALID_VALUE, "glVertexAttribIPointer(index)"); 6833464ebd5Sriastradh return; 6847117f1b4Smrg } 6857117f1b4Smrg 686af69d88dSmrg update_array(ctx, "glVertexAttribIPointer", VERT_ATTRIB_GENERIC(index), 6873464ebd5Sriastradh legalTypes, 1, 4, 6883464ebd5Sriastradh size, type, stride, normalized, integer, ptr); 6893464ebd5Sriastradh} 6903464ebd5Sriastradh 6913464ebd5Sriastradh 6923464ebd5Sriastradh 6933464ebd5Sriastradhvoid GLAPIENTRY 694af69d88dSmrg_mesa_EnableVertexAttribArray(GLuint index) 6953464ebd5Sriastradh{ 696af69d88dSmrg struct gl_vertex_array_object *vao; 6973464ebd5Sriastradh GET_CURRENT_CONTEXT(ctx); 6983464ebd5Sriastradh 699af69d88dSmrg if (index >= ctx->Const.Program[MESA_SHADER_VERTEX].MaxAttribs) { 7003464ebd5Sriastradh _mesa_error(ctx, GL_INVALID_VALUE, 7013464ebd5Sriastradh "glEnableVertexAttribArrayARB(index)"); 7027117f1b4Smrg return; 7037117f1b4Smrg } 7047117f1b4Smrg 705af69d88dSmrg vao = ctx->Array.VAO; 706af69d88dSmrg 707af69d88dSmrg ASSERT(VERT_ATTRIB_GENERIC(index) < Elements(vao->_VertexAttrib)); 7083464ebd5Sriastradh 709af69d88dSmrg if (!vao->VertexAttrib[VERT_ATTRIB_GENERIC(index)].Enabled) { 710af69d88dSmrg /* was disabled, now being enabled */ 711af69d88dSmrg FLUSH_VERTICES(ctx, _NEW_ARRAY); 712af69d88dSmrg vao->VertexAttrib[VERT_ATTRIB_GENERIC(index)].Enabled = GL_TRUE; 713af69d88dSmrg vao->_Enabled |= VERT_BIT_GENERIC(index); 714af69d88dSmrg vao->NewArrays |= VERT_BIT_GENERIC(index); 715af69d88dSmrg } 7163464ebd5Sriastradh} 7173464ebd5Sriastradh 7183464ebd5Sriastradh 7193464ebd5Sriastradhvoid GLAPIENTRY 720af69d88dSmrg_mesa_DisableVertexAttribArray(GLuint index) 7213464ebd5Sriastradh{ 722af69d88dSmrg struct gl_vertex_array_object *vao; 7233464ebd5Sriastradh GET_CURRENT_CONTEXT(ctx); 7243464ebd5Sriastradh 725af69d88dSmrg if (index >= ctx->Const.Program[MESA_SHADER_VERTEX].MaxAttribs) { 7263464ebd5Sriastradh _mesa_error(ctx, GL_INVALID_VALUE, 7273464ebd5Sriastradh "glDisableVertexAttribArrayARB(index)"); 7283464ebd5Sriastradh return; 7293464ebd5Sriastradh } 7303464ebd5Sriastradh 731af69d88dSmrg vao = ctx->Array.VAO; 7323464ebd5Sriastradh 733af69d88dSmrg ASSERT(VERT_ATTRIB_GENERIC(index) < Elements(vao->_VertexAttrib)); 734af69d88dSmrg 735af69d88dSmrg if (vao->VertexAttrib[VERT_ATTRIB_GENERIC(index)].Enabled) { 736af69d88dSmrg /* was enabled, now being disabled */ 737af69d88dSmrg FLUSH_VERTICES(ctx, _NEW_ARRAY); 738af69d88dSmrg vao->VertexAttrib[VERT_ATTRIB_GENERIC(index)].Enabled = GL_FALSE; 739af69d88dSmrg vao->_Enabled &= ~VERT_BIT_GENERIC(index); 740af69d88dSmrg vao->NewArrays |= VERT_BIT_GENERIC(index); 741af69d88dSmrg } 7423464ebd5Sriastradh} 7433464ebd5Sriastradh 7443464ebd5Sriastradh 7453464ebd5Sriastradh/** 7463464ebd5Sriastradh * Return info for a vertex attribute array (no alias with legacy 7473464ebd5Sriastradh * vertex attributes (pos, normal, color, etc)). This function does 7483464ebd5Sriastradh * not handle the 4-element GL_CURRENT_VERTEX_ATTRIB_ARB query. 7493464ebd5Sriastradh */ 7503464ebd5Sriastradhstatic GLuint 7513464ebd5Sriastradhget_vertex_array_attrib(struct gl_context *ctx, GLuint index, GLenum pname, 7523464ebd5Sriastradh const char *caller) 7533464ebd5Sriastradh{ 754af69d88dSmrg const struct gl_vertex_array_object *vao = ctx->Array.VAO; 755af69d88dSmrg const struct gl_vertex_attrib_array *array; 7563464ebd5Sriastradh 757af69d88dSmrg if (index >= ctx->Const.Program[MESA_SHADER_VERTEX].MaxAttribs) { 7583464ebd5Sriastradh _mesa_error(ctx, GL_INVALID_VALUE, "%s(index=%u)", caller, index); 7593464ebd5Sriastradh return 0; 7603464ebd5Sriastradh } 7613464ebd5Sriastradh 762af69d88dSmrg ASSERT(VERT_ATTRIB_GENERIC(index) < Elements(vao->VertexAttrib)); 7633464ebd5Sriastradh 764af69d88dSmrg array = &vao->VertexAttrib[VERT_ATTRIB_GENERIC(index)]; 7653464ebd5Sriastradh 7663464ebd5Sriastradh switch (pname) { 7673464ebd5Sriastradh case GL_VERTEX_ATTRIB_ARRAY_ENABLED_ARB: 7683464ebd5Sriastradh return array->Enabled; 7693464ebd5Sriastradh case GL_VERTEX_ATTRIB_ARRAY_SIZE_ARB: 770af69d88dSmrg return (array->Format == GL_BGRA) ? GL_BGRA : array->Size; 7713464ebd5Sriastradh case GL_VERTEX_ATTRIB_ARRAY_STRIDE_ARB: 7723464ebd5Sriastradh return array->Stride; 7733464ebd5Sriastradh case GL_VERTEX_ATTRIB_ARRAY_TYPE_ARB: 7743464ebd5Sriastradh return array->Type; 7753464ebd5Sriastradh case GL_VERTEX_ATTRIB_ARRAY_NORMALIZED_ARB: 7763464ebd5Sriastradh return array->Normalized; 7773464ebd5Sriastradh case GL_VERTEX_ATTRIB_ARRAY_BUFFER_BINDING_ARB: 778af69d88dSmrg return vao->VertexBinding[array->VertexBinding].BufferObj->Name; 7793464ebd5Sriastradh case GL_VERTEX_ATTRIB_ARRAY_INTEGER: 780af69d88dSmrg if ((_mesa_is_desktop_gl(ctx) 781af69d88dSmrg && (ctx->Version >= 30 || ctx->Extensions.EXT_gpu_shader4)) 782af69d88dSmrg || _mesa_is_gles3(ctx)) { 7833464ebd5Sriastradh return array->Integer; 7844a49301eSmrg } 7853464ebd5Sriastradh goto error; 7863464ebd5Sriastradh case GL_VERTEX_ATTRIB_ARRAY_DIVISOR_ARB: 787af69d88dSmrg if ((_mesa_is_desktop_gl(ctx) && ctx->Extensions.ARB_instanced_arrays) 788af69d88dSmrg || _mesa_is_gles3(ctx)) { 789af69d88dSmrg return vao->VertexBinding[array->VertexBinding].InstanceDivisor; 790af69d88dSmrg } 791af69d88dSmrg goto error; 792af69d88dSmrg case GL_VERTEX_ATTRIB_BINDING: 793af69d88dSmrg if (_mesa_is_desktop_gl(ctx)) { 794af69d88dSmrg return array->VertexBinding - VERT_ATTRIB_GENERIC0; 795af69d88dSmrg } 796af69d88dSmrg goto error; 797af69d88dSmrg case GL_VERTEX_ATTRIB_RELATIVE_OFFSET: 798af69d88dSmrg if (_mesa_is_desktop_gl(ctx)) { 799af69d88dSmrg return array->RelativeOffset; 8004a49301eSmrg } 8013464ebd5Sriastradh goto error; 8023464ebd5Sriastradh default: 8033464ebd5Sriastradh ; /* fall-through */ 8043464ebd5Sriastradh } 8054a49301eSmrg 8063464ebd5Sriastradherror: 8073464ebd5Sriastradh _mesa_error(ctx, GL_INVALID_ENUM, "%s(pname=0x%x)", caller, pname); 8083464ebd5Sriastradh return 0; 8093464ebd5Sriastradh} 8103464ebd5Sriastradh 8113464ebd5Sriastradh 8123464ebd5Sriastradhstatic const GLfloat * 8133464ebd5Sriastradhget_current_attrib(struct gl_context *ctx, GLuint index, const char *function) 8143464ebd5Sriastradh{ 8153464ebd5Sriastradh if (index == 0) { 816af69d88dSmrg if (_mesa_attr_zero_aliases_vertex(ctx)) { 8173464ebd5Sriastradh _mesa_error(ctx, GL_INVALID_OPERATION, "%s(index==0)", function); 8183464ebd5Sriastradh return NULL; 8193464ebd5Sriastradh } 8203464ebd5Sriastradh } 821af69d88dSmrg else if (index >= ctx->Const.Program[MESA_SHADER_VERTEX].MaxAttribs) { 8223464ebd5Sriastradh _mesa_error(ctx, GL_INVALID_VALUE, 8233464ebd5Sriastradh "%s(index>=GL_MAX_VERTEX_ATTRIBS)", function); 8243464ebd5Sriastradh return NULL; 8253464ebd5Sriastradh } 8263464ebd5Sriastradh 827af69d88dSmrg ASSERT(VERT_ATTRIB_GENERIC(index) < Elements(ctx->Array.VAO->_VertexAttrib)); 828af69d88dSmrg 8293464ebd5Sriastradh FLUSH_CURRENT(ctx, 0); 830af69d88dSmrg return ctx->Current.Attrib[VERT_ATTRIB_GENERIC(index)]; 8313464ebd5Sriastradh} 8323464ebd5Sriastradh 8333464ebd5Sriastradhvoid GLAPIENTRY 834af69d88dSmrg_mesa_GetVertexAttribfv(GLuint index, GLenum pname, GLfloat *params) 8353464ebd5Sriastradh{ 8363464ebd5Sriastradh GET_CURRENT_CONTEXT(ctx); 8373464ebd5Sriastradh 8383464ebd5Sriastradh if (pname == GL_CURRENT_VERTEX_ATTRIB_ARB) { 8393464ebd5Sriastradh const GLfloat *v = get_current_attrib(ctx, index, "glGetVertexAttribfv"); 8403464ebd5Sriastradh if (v != NULL) { 8413464ebd5Sriastradh COPY_4V(params, v); 8423464ebd5Sriastradh } 8434a49301eSmrg } 8444a49301eSmrg else { 8453464ebd5Sriastradh params[0] = (GLfloat) get_vertex_array_attrib(ctx, index, pname, 8463464ebd5Sriastradh "glGetVertexAttribfv"); 8474a49301eSmrg } 8483464ebd5Sriastradh} 8494a49301eSmrg 8503464ebd5Sriastradh 8513464ebd5Sriastradhvoid GLAPIENTRY 852af69d88dSmrg_mesa_GetVertexAttribdv(GLuint index, GLenum pname, GLdouble *params) 8533464ebd5Sriastradh{ 8543464ebd5Sriastradh GET_CURRENT_CONTEXT(ctx); 8553464ebd5Sriastradh 8563464ebd5Sriastradh if (pname == GL_CURRENT_VERTEX_ATTRIB_ARB) { 8573464ebd5Sriastradh const GLfloat *v = get_current_attrib(ctx, index, "glGetVertexAttribdv"); 8583464ebd5Sriastradh if (v != NULL) { 8593464ebd5Sriastradh params[0] = (GLdouble) v[0]; 8603464ebd5Sriastradh params[1] = (GLdouble) v[1]; 8613464ebd5Sriastradh params[2] = (GLdouble) v[2]; 8623464ebd5Sriastradh params[3] = (GLdouble) v[3]; 8633464ebd5Sriastradh } 8643464ebd5Sriastradh } 8653464ebd5Sriastradh else { 8663464ebd5Sriastradh params[0] = (GLdouble) get_vertex_array_attrib(ctx, index, pname, 8673464ebd5Sriastradh "glGetVertexAttribdv"); 8687117f1b4Smrg } 8693464ebd5Sriastradh} 8707117f1b4Smrg 8713464ebd5Sriastradh 8723464ebd5Sriastradhvoid GLAPIENTRY 873af69d88dSmrg_mesa_GetVertexAttribiv(GLuint index, GLenum pname, GLint *params) 8743464ebd5Sriastradh{ 8753464ebd5Sriastradh GET_CURRENT_CONTEXT(ctx); 8763464ebd5Sriastradh 8773464ebd5Sriastradh if (pname == GL_CURRENT_VERTEX_ATTRIB_ARB) { 8783464ebd5Sriastradh const GLfloat *v = get_current_attrib(ctx, index, "glGetVertexAttribiv"); 8793464ebd5Sriastradh if (v != NULL) { 8803464ebd5Sriastradh /* XXX should floats in[0,1] be scaled to full int range? */ 8813464ebd5Sriastradh params[0] = (GLint) v[0]; 8823464ebd5Sriastradh params[1] = (GLint) v[1]; 8833464ebd5Sriastradh params[2] = (GLint) v[2]; 8843464ebd5Sriastradh params[3] = (GLint) v[3]; 8853464ebd5Sriastradh } 8863464ebd5Sriastradh } 8873464ebd5Sriastradh else { 8883464ebd5Sriastradh params[0] = (GLint) get_vertex_array_attrib(ctx, index, pname, 8893464ebd5Sriastradh "glGetVertexAttribiv"); 8903464ebd5Sriastradh } 8913464ebd5Sriastradh} 8923464ebd5Sriastradh 8933464ebd5Sriastradh 8943464ebd5Sriastradh/** GL 3.0 */ 8953464ebd5Sriastradhvoid GLAPIENTRY 8963464ebd5Sriastradh_mesa_GetVertexAttribIiv(GLuint index, GLenum pname, GLint *params) 8973464ebd5Sriastradh{ 8983464ebd5Sriastradh GET_CURRENT_CONTEXT(ctx); 8993464ebd5Sriastradh 9003464ebd5Sriastradh if (pname == GL_CURRENT_VERTEX_ATTRIB_ARB) { 901af69d88dSmrg const GLint *v = (const GLint *) 9023464ebd5Sriastradh get_current_attrib(ctx, index, "glGetVertexAttribIiv"); 9033464ebd5Sriastradh if (v != NULL) { 904af69d88dSmrg COPY_4V(params, v); 9053464ebd5Sriastradh } 9063464ebd5Sriastradh } 9073464ebd5Sriastradh else { 9083464ebd5Sriastradh params[0] = (GLint) get_vertex_array_attrib(ctx, index, pname, 9093464ebd5Sriastradh "glGetVertexAttribIiv"); 9103464ebd5Sriastradh } 9113464ebd5Sriastradh} 9123464ebd5Sriastradh 9133464ebd5Sriastradh 9143464ebd5Sriastradh/** GL 3.0 */ 9153464ebd5Sriastradhvoid GLAPIENTRY 9163464ebd5Sriastradh_mesa_GetVertexAttribIuiv(GLuint index, GLenum pname, GLuint *params) 9173464ebd5Sriastradh{ 9183464ebd5Sriastradh GET_CURRENT_CONTEXT(ctx); 9193464ebd5Sriastradh 9203464ebd5Sriastradh if (pname == GL_CURRENT_VERTEX_ATTRIB_ARB) { 921af69d88dSmrg const GLuint *v = (const GLuint *) 9223464ebd5Sriastradh get_current_attrib(ctx, index, "glGetVertexAttribIuiv"); 9233464ebd5Sriastradh if (v != NULL) { 924af69d88dSmrg COPY_4V(params, v); 9253464ebd5Sriastradh } 9263464ebd5Sriastradh } 9273464ebd5Sriastradh else { 9283464ebd5Sriastradh params[0] = get_vertex_array_attrib(ctx, index, pname, 9293464ebd5Sriastradh "glGetVertexAttribIuiv"); 9303464ebd5Sriastradh } 9313464ebd5Sriastradh} 9323464ebd5Sriastradh 9333464ebd5Sriastradh 9343464ebd5Sriastradhvoid GLAPIENTRY 935af69d88dSmrg_mesa_GetVertexAttribPointerv(GLuint index, GLenum pname, GLvoid **pointer) 9363464ebd5Sriastradh{ 9373464ebd5Sriastradh GET_CURRENT_CONTEXT(ctx); 9383464ebd5Sriastradh 939af69d88dSmrg if (index >= ctx->Const.Program[MESA_SHADER_VERTEX].MaxAttribs) { 9403464ebd5Sriastradh _mesa_error(ctx, GL_INVALID_VALUE, "glGetVertexAttribPointerARB(index)"); 9413464ebd5Sriastradh return; 9423464ebd5Sriastradh } 9433464ebd5Sriastradh 9443464ebd5Sriastradh if (pname != GL_VERTEX_ATTRIB_ARRAY_POINTER_ARB) { 9453464ebd5Sriastradh _mesa_error(ctx, GL_INVALID_ENUM, "glGetVertexAttribPointerARB(pname)"); 9463464ebd5Sriastradh return; 9473464ebd5Sriastradh } 9483464ebd5Sriastradh 949af69d88dSmrg ASSERT(VERT_ATTRIB_GENERIC(index) < Elements(ctx->Array.VAO->_VertexAttrib)); 9503464ebd5Sriastradh 951af69d88dSmrg *pointer = (GLvoid *) ctx->Array.VAO->VertexAttrib[VERT_ATTRIB_GENERIC(index)].Ptr; 9527117f1b4Smrg} 9537117f1b4Smrg 9547117f1b4Smrg 9557117f1b4Smrgvoid GLAPIENTRY 9567117f1b4Smrg_mesa_VertexPointerEXT(GLint size, GLenum type, GLsizei stride, 9577117f1b4Smrg GLsizei count, const GLvoid *ptr) 9587117f1b4Smrg{ 9597117f1b4Smrg (void) count; 9607117f1b4Smrg _mesa_VertexPointer(size, type, stride, ptr); 9617117f1b4Smrg} 9627117f1b4Smrg 9637117f1b4Smrg 9647117f1b4Smrgvoid GLAPIENTRY 9657117f1b4Smrg_mesa_NormalPointerEXT(GLenum type, GLsizei stride, GLsizei count, 9667117f1b4Smrg const GLvoid *ptr) 9677117f1b4Smrg{ 9687117f1b4Smrg (void) count; 9697117f1b4Smrg _mesa_NormalPointer(type, stride, ptr); 9707117f1b4Smrg} 9717117f1b4Smrg 9727117f1b4Smrg 9737117f1b4Smrgvoid GLAPIENTRY 9747117f1b4Smrg_mesa_ColorPointerEXT(GLint size, GLenum type, GLsizei stride, GLsizei count, 9757117f1b4Smrg const GLvoid *ptr) 9767117f1b4Smrg{ 9777117f1b4Smrg (void) count; 9787117f1b4Smrg _mesa_ColorPointer(size, type, stride, ptr); 9797117f1b4Smrg} 9807117f1b4Smrg 9817117f1b4Smrg 9827117f1b4Smrgvoid GLAPIENTRY 9837117f1b4Smrg_mesa_IndexPointerEXT(GLenum type, GLsizei stride, GLsizei count, 9847117f1b4Smrg const GLvoid *ptr) 9857117f1b4Smrg{ 9867117f1b4Smrg (void) count; 9877117f1b4Smrg _mesa_IndexPointer(type, stride, ptr); 9887117f1b4Smrg} 9897117f1b4Smrg 9907117f1b4Smrg 9917117f1b4Smrgvoid GLAPIENTRY 9927117f1b4Smrg_mesa_TexCoordPointerEXT(GLint size, GLenum type, GLsizei stride, 9937117f1b4Smrg GLsizei count, const GLvoid *ptr) 9947117f1b4Smrg{ 9957117f1b4Smrg (void) count; 9967117f1b4Smrg _mesa_TexCoordPointer(size, type, stride, ptr); 9977117f1b4Smrg} 9987117f1b4Smrg 9997117f1b4Smrg 10007117f1b4Smrgvoid GLAPIENTRY 10017117f1b4Smrg_mesa_EdgeFlagPointerEXT(GLsizei stride, GLsizei count, const GLboolean *ptr) 10027117f1b4Smrg{ 10037117f1b4Smrg (void) count; 10047117f1b4Smrg _mesa_EdgeFlagPointer(stride, ptr); 10057117f1b4Smrg} 10067117f1b4Smrg 10077117f1b4Smrg 10087117f1b4Smrgvoid GLAPIENTRY 10097117f1b4Smrg_mesa_InterleavedArrays(GLenum format, GLsizei stride, const GLvoid *pointer) 10107117f1b4Smrg{ 10117117f1b4Smrg GET_CURRENT_CONTEXT(ctx); 10127117f1b4Smrg GLboolean tflag, cflag, nflag; /* enable/disable flags */ 10137117f1b4Smrg GLint tcomps, ccomps, vcomps; /* components per texcoord, color, vertex */ 10147117f1b4Smrg GLenum ctype = 0; /* color type */ 10157117f1b4Smrg GLint coffset = 0, noffset = 0, voffset;/* color, normal, vertex offsets */ 10167117f1b4Smrg const GLint toffset = 0; /* always zero */ 10177117f1b4Smrg GLint defstride; /* default stride */ 10187117f1b4Smrg GLint c, f; 10197117f1b4Smrg 1020af69d88dSmrg FLUSH_VERTICES(ctx, 0); 10217117f1b4Smrg 10227117f1b4Smrg f = sizeof(GLfloat); 10237117f1b4Smrg c = f * ((4 * sizeof(GLubyte) + (f - 1)) / f); 10247117f1b4Smrg 10257117f1b4Smrg if (stride < 0) { 10267117f1b4Smrg _mesa_error( ctx, GL_INVALID_VALUE, "glInterleavedArrays(stride)" ); 10277117f1b4Smrg return; 10287117f1b4Smrg } 10297117f1b4Smrg 10307117f1b4Smrg switch (format) { 10317117f1b4Smrg case GL_V2F: 10327117f1b4Smrg tflag = GL_FALSE; cflag = GL_FALSE; nflag = GL_FALSE; 10337117f1b4Smrg tcomps = 0; ccomps = 0; vcomps = 2; 10347117f1b4Smrg voffset = 0; 10357117f1b4Smrg defstride = 2*f; 10367117f1b4Smrg break; 10377117f1b4Smrg case GL_V3F: 10387117f1b4Smrg tflag = GL_FALSE; cflag = GL_FALSE; nflag = GL_FALSE; 10397117f1b4Smrg tcomps = 0; ccomps = 0; vcomps = 3; 10407117f1b4Smrg voffset = 0; 10417117f1b4Smrg defstride = 3*f; 10427117f1b4Smrg break; 10437117f1b4Smrg case GL_C4UB_V2F: 10447117f1b4Smrg tflag = GL_FALSE; cflag = GL_TRUE; nflag = GL_FALSE; 10457117f1b4Smrg tcomps = 0; ccomps = 4; vcomps = 2; 10467117f1b4Smrg ctype = GL_UNSIGNED_BYTE; 10477117f1b4Smrg coffset = 0; 10487117f1b4Smrg voffset = c; 10497117f1b4Smrg defstride = c + 2*f; 10507117f1b4Smrg break; 10517117f1b4Smrg case GL_C4UB_V3F: 10527117f1b4Smrg tflag = GL_FALSE; cflag = GL_TRUE; nflag = GL_FALSE; 10537117f1b4Smrg tcomps = 0; ccomps = 4; vcomps = 3; 10547117f1b4Smrg ctype = GL_UNSIGNED_BYTE; 10557117f1b4Smrg coffset = 0; 10567117f1b4Smrg voffset = c; 10577117f1b4Smrg defstride = c + 3*f; 10587117f1b4Smrg break; 10597117f1b4Smrg case GL_C3F_V3F: 10607117f1b4Smrg tflag = GL_FALSE; cflag = GL_TRUE; nflag = GL_FALSE; 10617117f1b4Smrg tcomps = 0; ccomps = 3; vcomps = 3; 10627117f1b4Smrg ctype = GL_FLOAT; 10637117f1b4Smrg coffset = 0; 10647117f1b4Smrg voffset = 3*f; 10657117f1b4Smrg defstride = 6*f; 10667117f1b4Smrg break; 10677117f1b4Smrg case GL_N3F_V3F: 10687117f1b4Smrg tflag = GL_FALSE; cflag = GL_FALSE; nflag = GL_TRUE; 10697117f1b4Smrg tcomps = 0; ccomps = 0; vcomps = 3; 10707117f1b4Smrg noffset = 0; 10717117f1b4Smrg voffset = 3*f; 10727117f1b4Smrg defstride = 6*f; 10737117f1b4Smrg break; 10747117f1b4Smrg case GL_C4F_N3F_V3F: 10757117f1b4Smrg tflag = GL_FALSE; cflag = GL_TRUE; nflag = GL_TRUE; 10767117f1b4Smrg tcomps = 0; ccomps = 4; vcomps = 3; 10777117f1b4Smrg ctype = GL_FLOAT; 10787117f1b4Smrg coffset = 0; 10797117f1b4Smrg noffset = 4*f; 10807117f1b4Smrg voffset = 7*f; 10817117f1b4Smrg defstride = 10*f; 10827117f1b4Smrg break; 10837117f1b4Smrg case GL_T2F_V3F: 10847117f1b4Smrg tflag = GL_TRUE; cflag = GL_FALSE; nflag = GL_FALSE; 10857117f1b4Smrg tcomps = 2; ccomps = 0; vcomps = 3; 10867117f1b4Smrg voffset = 2*f; 10877117f1b4Smrg defstride = 5*f; 10887117f1b4Smrg break; 10897117f1b4Smrg case GL_T4F_V4F: 10907117f1b4Smrg tflag = GL_TRUE; cflag = GL_FALSE; nflag = GL_FALSE; 10917117f1b4Smrg tcomps = 4; ccomps = 0; vcomps = 4; 10927117f1b4Smrg voffset = 4*f; 10937117f1b4Smrg defstride = 8*f; 10947117f1b4Smrg break; 10957117f1b4Smrg case GL_T2F_C4UB_V3F: 10967117f1b4Smrg tflag = GL_TRUE; cflag = GL_TRUE; nflag = GL_FALSE; 10977117f1b4Smrg tcomps = 2; ccomps = 4; vcomps = 3; 10987117f1b4Smrg ctype = GL_UNSIGNED_BYTE; 10997117f1b4Smrg coffset = 2*f; 11007117f1b4Smrg voffset = c+2*f; 11017117f1b4Smrg defstride = c+5*f; 11027117f1b4Smrg break; 11037117f1b4Smrg case GL_T2F_C3F_V3F: 11047117f1b4Smrg tflag = GL_TRUE; cflag = GL_TRUE; nflag = GL_FALSE; 11057117f1b4Smrg tcomps = 2; ccomps = 3; vcomps = 3; 11067117f1b4Smrg ctype = GL_FLOAT; 11077117f1b4Smrg coffset = 2*f; 11087117f1b4Smrg voffset = 5*f; 11097117f1b4Smrg defstride = 8*f; 11107117f1b4Smrg break; 11117117f1b4Smrg case GL_T2F_N3F_V3F: 11127117f1b4Smrg tflag = GL_TRUE; cflag = GL_FALSE; nflag = GL_TRUE; 11137117f1b4Smrg tcomps = 2; ccomps = 0; vcomps = 3; 11147117f1b4Smrg noffset = 2*f; 11157117f1b4Smrg voffset = 5*f; 11167117f1b4Smrg defstride = 8*f; 11177117f1b4Smrg break; 11187117f1b4Smrg case GL_T2F_C4F_N3F_V3F: 11197117f1b4Smrg tflag = GL_TRUE; cflag = GL_TRUE; nflag = GL_TRUE; 11207117f1b4Smrg tcomps = 2; ccomps = 4; vcomps = 3; 11217117f1b4Smrg ctype = GL_FLOAT; 11227117f1b4Smrg coffset = 2*f; 11237117f1b4Smrg noffset = 6*f; 11247117f1b4Smrg voffset = 9*f; 11257117f1b4Smrg defstride = 12*f; 11267117f1b4Smrg break; 11277117f1b4Smrg case GL_T4F_C4F_N3F_V4F: 11287117f1b4Smrg tflag = GL_TRUE; cflag = GL_TRUE; nflag = GL_TRUE; 11297117f1b4Smrg tcomps = 4; ccomps = 4; vcomps = 4; 11307117f1b4Smrg ctype = GL_FLOAT; 11317117f1b4Smrg coffset = 4*f; 11327117f1b4Smrg noffset = 8*f; 11337117f1b4Smrg voffset = 11*f; 11347117f1b4Smrg defstride = 15*f; 11357117f1b4Smrg break; 11367117f1b4Smrg default: 11377117f1b4Smrg _mesa_error( ctx, GL_INVALID_ENUM, "glInterleavedArrays(format)" ); 11387117f1b4Smrg return; 11397117f1b4Smrg } 11407117f1b4Smrg 11417117f1b4Smrg if (stride==0) { 11427117f1b4Smrg stride = defstride; 11437117f1b4Smrg } 11447117f1b4Smrg 11457117f1b4Smrg _mesa_DisableClientState( GL_EDGE_FLAG_ARRAY ); 11467117f1b4Smrg _mesa_DisableClientState( GL_INDEX_ARRAY ); 11477117f1b4Smrg /* XXX also disable secondary color and generic arrays? */ 11487117f1b4Smrg 11497117f1b4Smrg /* Texcoords */ 11507117f1b4Smrg if (tflag) { 11517117f1b4Smrg _mesa_EnableClientState( GL_TEXTURE_COORD_ARRAY ); 11527117f1b4Smrg _mesa_TexCoordPointer( tcomps, GL_FLOAT, stride, 11537117f1b4Smrg (GLubyte *) pointer + toffset ); 11547117f1b4Smrg } 11557117f1b4Smrg else { 11567117f1b4Smrg _mesa_DisableClientState( GL_TEXTURE_COORD_ARRAY ); 11577117f1b4Smrg } 11587117f1b4Smrg 11597117f1b4Smrg /* Color */ 11607117f1b4Smrg if (cflag) { 11617117f1b4Smrg _mesa_EnableClientState( GL_COLOR_ARRAY ); 11627117f1b4Smrg _mesa_ColorPointer( ccomps, ctype, stride, 11637117f1b4Smrg (GLubyte *) pointer + coffset ); 11647117f1b4Smrg } 11657117f1b4Smrg else { 11667117f1b4Smrg _mesa_DisableClientState( GL_COLOR_ARRAY ); 11677117f1b4Smrg } 11687117f1b4Smrg 11697117f1b4Smrg 11707117f1b4Smrg /* Normals */ 11717117f1b4Smrg if (nflag) { 11727117f1b4Smrg _mesa_EnableClientState( GL_NORMAL_ARRAY ); 11737117f1b4Smrg _mesa_NormalPointer( GL_FLOAT, stride, (GLubyte *) pointer + noffset ); 11747117f1b4Smrg } 11757117f1b4Smrg else { 11767117f1b4Smrg _mesa_DisableClientState( GL_NORMAL_ARRAY ); 11777117f1b4Smrg } 11787117f1b4Smrg 11797117f1b4Smrg /* Vertices */ 11807117f1b4Smrg _mesa_EnableClientState( GL_VERTEX_ARRAY ); 11817117f1b4Smrg _mesa_VertexPointer( vcomps, GL_FLOAT, stride, 11827117f1b4Smrg (GLubyte *) pointer + voffset ); 11837117f1b4Smrg} 11847117f1b4Smrg 11857117f1b4Smrg 11867117f1b4Smrgvoid GLAPIENTRY 11877117f1b4Smrg_mesa_LockArraysEXT(GLint first, GLsizei count) 11887117f1b4Smrg{ 11897117f1b4Smrg GET_CURRENT_CONTEXT(ctx); 1190af69d88dSmrg 1191af69d88dSmrg FLUSH_VERTICES(ctx, 0); 11927117f1b4Smrg 11937117f1b4Smrg if (MESA_VERBOSE & VERBOSE_API) 11947117f1b4Smrg _mesa_debug(ctx, "glLockArrays %d %d\n", first, count); 11957117f1b4Smrg 1196c1f859d4Smrg if (first < 0) { 1197c1f859d4Smrg _mesa_error( ctx, GL_INVALID_VALUE, "glLockArraysEXT(first)" ); 1198c1f859d4Smrg return; 11997117f1b4Smrg } 1200c1f859d4Smrg if (count <= 0) { 1201c1f859d4Smrg _mesa_error( ctx, GL_INVALID_VALUE, "glLockArraysEXT(count)" ); 1202c1f859d4Smrg return; 1203c1f859d4Smrg } 1204c1f859d4Smrg if (ctx->Array.LockCount != 0) { 1205c1f859d4Smrg _mesa_error( ctx, GL_INVALID_OPERATION, "glLockArraysEXT(reentry)" ); 1206c1f859d4Smrg return; 12077117f1b4Smrg } 12087117f1b4Smrg 1209c1f859d4Smrg ctx->Array.LockFirst = first; 1210c1f859d4Smrg ctx->Array.LockCount = count; 1211c1f859d4Smrg 12127117f1b4Smrg ctx->NewState |= _NEW_ARRAY; 12137117f1b4Smrg} 12147117f1b4Smrg 12157117f1b4Smrg 12167117f1b4Smrgvoid GLAPIENTRY 12177117f1b4Smrg_mesa_UnlockArraysEXT( void ) 12187117f1b4Smrg{ 12197117f1b4Smrg GET_CURRENT_CONTEXT(ctx); 1220af69d88dSmrg 1221af69d88dSmrg FLUSH_VERTICES(ctx, 0); 12227117f1b4Smrg 12237117f1b4Smrg if (MESA_VERBOSE & VERBOSE_API) 12247117f1b4Smrg _mesa_debug(ctx, "glUnlockArrays\n"); 12257117f1b4Smrg 1226c1f859d4Smrg if (ctx->Array.LockCount == 0) { 1227c1f859d4Smrg _mesa_error( ctx, GL_INVALID_OPERATION, "glUnlockArraysEXT(reexit)" ); 1228c1f859d4Smrg return; 1229c1f859d4Smrg } 1230c1f859d4Smrg 12317117f1b4Smrg ctx->Array.LockFirst = 0; 12327117f1b4Smrg ctx->Array.LockCount = 0; 12337117f1b4Smrg ctx->NewState |= _NEW_ARRAY; 12347117f1b4Smrg} 12357117f1b4Smrg 12367117f1b4Smrg 12377117f1b4Smrg/* GL_EXT_multi_draw_arrays */ 12387117f1b4Smrgvoid GLAPIENTRY 1239af69d88dSmrg_mesa_MultiDrawArrays( GLenum mode, const GLint *first, 12403464ebd5Sriastradh const GLsizei *count, GLsizei primcount ) 12417117f1b4Smrg{ 12427117f1b4Smrg GET_CURRENT_CONTEXT(ctx); 12437117f1b4Smrg GLint i; 12447117f1b4Smrg 1245af69d88dSmrg FLUSH_VERTICES(ctx, 0); 12467117f1b4Smrg 12477117f1b4Smrg for (i = 0; i < primcount; i++) { 12487117f1b4Smrg if (count[i] > 0) { 1249af69d88dSmrg CALL_DrawArrays(ctx->CurrentDispatch, (mode, first[i], count[i])); 12507117f1b4Smrg } 12517117f1b4Smrg } 12527117f1b4Smrg} 12537117f1b4Smrg 12547117f1b4Smrg 12557117f1b4Smrg/* GL_IBM_multimode_draw_arrays */ 12567117f1b4Smrgvoid GLAPIENTRY 12577117f1b4Smrg_mesa_MultiModeDrawArraysIBM( const GLenum * mode, const GLint * first, 12587117f1b4Smrg const GLsizei * count, 12597117f1b4Smrg GLsizei primcount, GLint modestride ) 12607117f1b4Smrg{ 12617117f1b4Smrg GET_CURRENT_CONTEXT(ctx); 12627117f1b4Smrg GLint i; 12637117f1b4Smrg 1264af69d88dSmrg FLUSH_VERTICES(ctx, 0); 12657117f1b4Smrg 12667117f1b4Smrg for ( i = 0 ; i < primcount ; i++ ) { 12677117f1b4Smrg if ( count[i] > 0 ) { 12687117f1b4Smrg GLenum m = *((GLenum *) ((GLubyte *) mode + i * modestride)); 1269af69d88dSmrg CALL_DrawArrays(ctx->CurrentDispatch, ( m, first[i], count[i] )); 12707117f1b4Smrg } 12717117f1b4Smrg } 12727117f1b4Smrg} 12737117f1b4Smrg 12747117f1b4Smrg 12757117f1b4Smrg/* GL_IBM_multimode_draw_arrays */ 12767117f1b4Smrgvoid GLAPIENTRY 12777117f1b4Smrg_mesa_MultiModeDrawElementsIBM( const GLenum * mode, const GLsizei * count, 12787117f1b4Smrg GLenum type, const GLvoid * const * indices, 12797117f1b4Smrg GLsizei primcount, GLint modestride ) 12807117f1b4Smrg{ 12817117f1b4Smrg GET_CURRENT_CONTEXT(ctx); 12827117f1b4Smrg GLint i; 12837117f1b4Smrg 1284af69d88dSmrg FLUSH_VERTICES(ctx, 0); 12857117f1b4Smrg 12867117f1b4Smrg /* XXX not sure about ARB_vertex_buffer_object handling here */ 12877117f1b4Smrg 12887117f1b4Smrg for ( i = 0 ; i < primcount ; i++ ) { 12897117f1b4Smrg if ( count[i] > 0 ) { 12907117f1b4Smrg GLenum m = *((GLenum *) ((GLubyte *) mode + i * modestride)); 1291af69d88dSmrg CALL_DrawElements(ctx->CurrentDispatch, ( m, count[i], type, 1292af69d88dSmrg indices[i] )); 12937117f1b4Smrg } 12947117f1b4Smrg } 12957117f1b4Smrg} 12967117f1b4Smrg 12977117f1b4Smrg 12983464ebd5Sriastradh/** 12993464ebd5Sriastradh * GL_NV_primitive_restart and GL 3.1 13003464ebd5Sriastradh */ 13013464ebd5Sriastradhvoid GLAPIENTRY 13023464ebd5Sriastradh_mesa_PrimitiveRestartIndex(GLuint index) 13033464ebd5Sriastradh{ 13043464ebd5Sriastradh GET_CURRENT_CONTEXT(ctx); 13053464ebd5Sriastradh 1306af69d88dSmrg if (!ctx->Extensions.NV_primitive_restart && ctx->Version < 31) { 13073464ebd5Sriastradh _mesa_error(ctx, GL_INVALID_OPERATION, "glPrimitiveRestartIndexNV()"); 13083464ebd5Sriastradh return; 13093464ebd5Sriastradh } 13103464ebd5Sriastradh 1311af69d88dSmrg if (ctx->Array.RestartIndex != index) { 1312af69d88dSmrg FLUSH_VERTICES(ctx, _NEW_TRANSFORM); 1313af69d88dSmrg ctx->Array.RestartIndex = index; 1314af69d88dSmrg } 13153464ebd5Sriastradh} 13163464ebd5Sriastradh 13173464ebd5Sriastradh 13183464ebd5Sriastradh/** 13193464ebd5Sriastradh * See GL_ARB_instanced_arrays. 13203464ebd5Sriastradh * Note that the instance divisor only applies to generic arrays, not 13213464ebd5Sriastradh * the legacy vertex arrays. 13223464ebd5Sriastradh */ 13233464ebd5Sriastradhvoid GLAPIENTRY 13243464ebd5Sriastradh_mesa_VertexAttribDivisor(GLuint index, GLuint divisor) 13253464ebd5Sriastradh{ 13263464ebd5Sriastradh GET_CURRENT_CONTEXT(ctx); 1327af69d88dSmrg 1328af69d88dSmrg const GLuint genericIndex = VERT_ATTRIB_GENERIC(index); 13293464ebd5Sriastradh 13303464ebd5Sriastradh if (!ctx->Extensions.ARB_instanced_arrays) { 13313464ebd5Sriastradh _mesa_error(ctx, GL_INVALID_OPERATION, "glVertexAttribDivisor()"); 13323464ebd5Sriastradh return; 13333464ebd5Sriastradh } 13343464ebd5Sriastradh 1335af69d88dSmrg if (index >= ctx->Const.Program[MESA_SHADER_VERTEX].MaxAttribs) { 1336af69d88dSmrg _mesa_error(ctx, GL_INVALID_VALUE, "glVertexAttribDivisor(index = %u)", 13373464ebd5Sriastradh index); 13383464ebd5Sriastradh return; 13393464ebd5Sriastradh } 13403464ebd5Sriastradh 1341af69d88dSmrg ASSERT(genericIndex < Elements(ctx->Array.VAO->VertexAttrib)); 1342af69d88dSmrg 1343af69d88dSmrg /* The ARB_vertex_attrib_binding spec says: 1344af69d88dSmrg * 1345af69d88dSmrg * "The command 1346af69d88dSmrg * 1347af69d88dSmrg * void VertexAttribDivisor(uint index, uint divisor); 1348af69d88dSmrg * 1349af69d88dSmrg * is equivalent to (assuming no errors are generated): 1350af69d88dSmrg * 1351af69d88dSmrg * VertexAttribBinding(index, index); 1352af69d88dSmrg * VertexBindingDivisor(index, divisor);" 1353af69d88dSmrg */ 1354af69d88dSmrg vertex_attrib_binding(ctx, genericIndex, genericIndex); 1355af69d88dSmrg vertex_binding_divisor(ctx, genericIndex, divisor); 13563464ebd5Sriastradh} 13573464ebd5Sriastradh 13583464ebd5Sriastradh 1359af69d88dSmrgunsigned 1360af69d88dSmrg_mesa_primitive_restart_index(const struct gl_context *ctx, GLenum ib_type) 1361af69d88dSmrg{ 1362af69d88dSmrg /* From the OpenGL 4.3 core specification, page 302: 1363af69d88dSmrg * "If both PRIMITIVE_RESTART and PRIMITIVE_RESTART_FIXED_INDEX are 1364af69d88dSmrg * enabled, the index value determined by PRIMITIVE_RESTART_FIXED_INDEX 1365af69d88dSmrg * is used." 1366af69d88dSmrg */ 1367af69d88dSmrg if (ctx->Array.PrimitiveRestartFixedIndex) { 1368af69d88dSmrg switch (ib_type) { 1369af69d88dSmrg case GL_UNSIGNED_BYTE: 1370af69d88dSmrg return 0xff; 1371af69d88dSmrg case GL_UNSIGNED_SHORT: 1372af69d88dSmrg return 0xffff; 1373af69d88dSmrg case GL_UNSIGNED_INT: 1374af69d88dSmrg return 0xffffffff; 1375af69d88dSmrg default: 1376af69d88dSmrg assert(!"_mesa_primitive_restart_index: Invalid index buffer type."); 1377af69d88dSmrg } 1378af69d88dSmrg } 1379af69d88dSmrg 1380af69d88dSmrg return ctx->Array.RestartIndex; 1381af69d88dSmrg} 1382af69d88dSmrg 1383af69d88dSmrg 1384af69d88dSmrg/** 1385af69d88dSmrg * GL_ARB_vertex_attrib_binding 1386af69d88dSmrg */ 1387af69d88dSmrgvoid GLAPIENTRY 1388af69d88dSmrg_mesa_BindVertexBuffer(GLuint bindingIndex, GLuint buffer, GLintptr offset, 1389af69d88dSmrg GLsizei stride) 1390af69d88dSmrg{ 1391af69d88dSmrg GET_CURRENT_CONTEXT(ctx); 1392af69d88dSmrg const struct gl_vertex_array_object *vao = ctx->Array.VAO; 1393af69d88dSmrg struct gl_buffer_object *vbo; 1394af69d88dSmrg 1395af69d88dSmrg ASSERT_OUTSIDE_BEGIN_END(ctx); 1396af69d88dSmrg 1397af69d88dSmrg /* The ARB_vertex_attrib_binding spec says: 1398af69d88dSmrg * 1399af69d88dSmrg * "An INVALID_OPERATION error is generated if no vertex array object 1400af69d88dSmrg * is bound." 1401af69d88dSmrg */ 1402af69d88dSmrg if (ctx->API == API_OPENGL_CORE && 1403af69d88dSmrg ctx->Array.VAO == ctx->Array.DefaultVAO) { 1404af69d88dSmrg _mesa_error(ctx, GL_INVALID_OPERATION, 1405af69d88dSmrg "glBindVertexBuffer(No array object bound)"); 1406af69d88dSmrg return; 1407af69d88dSmrg } 1408af69d88dSmrg 1409af69d88dSmrg /* The ARB_vertex_attrib_binding spec says: 1410af69d88dSmrg * 1411af69d88dSmrg * "An INVALID_VALUE error is generated if <bindingindex> is greater than 1412af69d88dSmrg * the value of MAX_VERTEX_ATTRIB_BINDINGS." 1413af69d88dSmrg */ 1414af69d88dSmrg if (bindingIndex >= ctx->Const.MaxVertexAttribBindings) { 1415af69d88dSmrg _mesa_error(ctx, GL_INVALID_VALUE, 1416af69d88dSmrg "glBindVertexBuffer(bindingindex=%u > " 1417af69d88dSmrg "GL_MAX_VERTEX_ATTRIB_BINDINGS)", 1418af69d88dSmrg bindingIndex); 1419af69d88dSmrg return; 1420af69d88dSmrg } 1421af69d88dSmrg 1422af69d88dSmrg /* The ARB_vertex_attrib_binding spec says: 1423af69d88dSmrg * 1424af69d88dSmrg * "The error INVALID_VALUE is generated if <stride> or <offset> 1425af69d88dSmrg * are negative." 1426af69d88dSmrg */ 1427af69d88dSmrg if (offset < 0) { 1428af69d88dSmrg _mesa_error(ctx, GL_INVALID_VALUE, 1429af69d88dSmrg "glBindVertexBuffer(offset=%" PRId64 " < 0)", 1430af69d88dSmrg (int64_t) offset); 1431af69d88dSmrg return; 1432af69d88dSmrg } 1433af69d88dSmrg 1434af69d88dSmrg if (stride < 0) { 1435af69d88dSmrg _mesa_error(ctx, GL_INVALID_VALUE, 1436af69d88dSmrg "glBindVertexBuffer(stride=%d < 0)", stride); 1437af69d88dSmrg return; 1438af69d88dSmrg } 1439af69d88dSmrg 1440af69d88dSmrg if (buffer == vao->VertexBinding[VERT_ATTRIB_GENERIC(bindingIndex)].BufferObj->Name) { 1441af69d88dSmrg vbo = vao->VertexBinding[VERT_ATTRIB_GENERIC(bindingIndex)].BufferObj; 1442af69d88dSmrg } else if (buffer != 0) { 1443af69d88dSmrg vbo = _mesa_lookup_bufferobj(ctx, buffer); 1444af69d88dSmrg 1445af69d88dSmrg /* From the GL_ARB_vertex_attrib_array spec: 1446af69d88dSmrg * 1447af69d88dSmrg * "[Core profile only:] 1448af69d88dSmrg * An INVALID_OPERATION error is generated if buffer is not zero or a 1449af69d88dSmrg * name returned from a previous call to GenBuffers, or if such a name 1450af69d88dSmrg * has since been deleted with DeleteBuffers. 1451af69d88dSmrg * 1452af69d88dSmrg * Otherwise, we fall back to the same compat profile behavior as other 1453af69d88dSmrg * object references (automatically gen it). 1454af69d88dSmrg */ 1455af69d88dSmrg if (!_mesa_handle_bind_buffer_gen(ctx, GL_ARRAY_BUFFER, buffer, 1456af69d88dSmrg &vbo, "glBindVertexBuffer")) 1457af69d88dSmrg return; 1458af69d88dSmrg } else { 1459af69d88dSmrg /* The ARB_vertex_attrib_binding spec says: 1460af69d88dSmrg * 1461af69d88dSmrg * "If <buffer> is zero, any buffer object attached to this 1462af69d88dSmrg * bindpoint is detached." 1463af69d88dSmrg */ 1464af69d88dSmrg vbo = ctx->Shared->NullBufferObj; 1465af69d88dSmrg } 1466af69d88dSmrg 1467af69d88dSmrg bind_vertex_buffer(ctx, VERT_ATTRIB_GENERIC(bindingIndex), 1468af69d88dSmrg vbo, offset, stride); 1469af69d88dSmrg} 1470af69d88dSmrg 1471af69d88dSmrg 1472af69d88dSmrgvoid GLAPIENTRY 1473af69d88dSmrg_mesa_BindVertexBuffers(GLuint first, GLsizei count, const GLuint *buffers, 1474af69d88dSmrg const GLintptr *offsets, const GLsizei *strides) 1475af69d88dSmrg{ 1476af69d88dSmrg GET_CURRENT_CONTEXT(ctx); 1477af69d88dSmrg struct gl_vertex_array_object * const vao = ctx->Array.VAO; 1478af69d88dSmrg GLuint i; 1479af69d88dSmrg 1480af69d88dSmrg ASSERT_OUTSIDE_BEGIN_END(ctx); 1481af69d88dSmrg 1482af69d88dSmrg /* The ARB_vertex_attrib_binding spec says: 1483af69d88dSmrg * 1484af69d88dSmrg * "An INVALID_OPERATION error is generated if no 1485af69d88dSmrg * vertex array object is bound." 1486af69d88dSmrg */ 1487af69d88dSmrg if (ctx->API == API_OPENGL_CORE && 1488af69d88dSmrg ctx->Array.VAO == ctx->Array.DefaultVAO) { 1489af69d88dSmrg _mesa_error(ctx, GL_INVALID_OPERATION, 1490af69d88dSmrg "glBindVertexBuffers(No array object bound)"); 1491af69d88dSmrg return; 1492af69d88dSmrg } 1493af69d88dSmrg 1494af69d88dSmrg /* The ARB_multi_bind spec says: 1495af69d88dSmrg * 1496af69d88dSmrg * "An INVALID_OPERATION error is generated if <first> + <count> 1497af69d88dSmrg * is greater than the value of MAX_VERTEX_ATTRIB_BINDINGS." 1498af69d88dSmrg */ 1499af69d88dSmrg if (first + count > ctx->Const.MaxVertexAttribBindings) { 1500af69d88dSmrg _mesa_error(ctx, GL_INVALID_OPERATION, 1501af69d88dSmrg "glBindVertexBuffers(first=%u + count=%d > the value of " 1502af69d88dSmrg "GL_MAX_VERTEX_ATTRIB_BINDINGS=%u)", 1503af69d88dSmrg first, count, ctx->Const.MaxVertexAttribBindings); 1504af69d88dSmrg return; 1505af69d88dSmrg } 1506af69d88dSmrg 1507af69d88dSmrg if (!buffers) { 1508af69d88dSmrg /** 1509af69d88dSmrg * The ARB_multi_bind spec says: 1510af69d88dSmrg * 1511af69d88dSmrg * "If <buffers> is NULL, each affected vertex buffer binding point 1512af69d88dSmrg * from <first> through <first>+<count>-1 will be reset to have no 1513af69d88dSmrg * bound buffer object. In this case, the offsets and strides 1514af69d88dSmrg * associated with the binding points are set to default values, 1515af69d88dSmrg * ignoring <offsets> and <strides>." 1516af69d88dSmrg */ 1517af69d88dSmrg struct gl_buffer_object *vbo = ctx->Shared->NullBufferObj; 1518af69d88dSmrg 1519af69d88dSmrg for (i = 0; i < count; i++) 1520af69d88dSmrg bind_vertex_buffer(ctx, VERT_ATTRIB_GENERIC(first + i), vbo, 0, 16); 1521af69d88dSmrg 1522af69d88dSmrg return; 1523af69d88dSmrg } 1524af69d88dSmrg 1525af69d88dSmrg /* Note that the error semantics for multi-bind commands differ from 1526af69d88dSmrg * those of other GL commands. 1527af69d88dSmrg * 1528af69d88dSmrg * The Issues section in the ARB_multi_bind spec says: 1529af69d88dSmrg * 1530af69d88dSmrg * "(11) Typically, OpenGL specifies that if an error is generated by 1531af69d88dSmrg * a command, that command has no effect. This is somewhat 1532af69d88dSmrg * unfortunate for multi-bind commands, because it would require 1533af69d88dSmrg * a first pass to scan the entire list of bound objects for 1534af69d88dSmrg * errors and then a second pass to actually perform the 1535af69d88dSmrg * bindings. Should we have different error semantics? 1536af69d88dSmrg * 1537af69d88dSmrg * RESOLVED: Yes. In this specification, when the parameters for 1538af69d88dSmrg * one of the <count> binding points are invalid, that binding 1539af69d88dSmrg * point is not updated and an error will be generated. However, 1540af69d88dSmrg * other binding points in the same command will be updated if 1541af69d88dSmrg * their parameters are valid and no other error occurs." 1542af69d88dSmrg */ 1543af69d88dSmrg 1544af69d88dSmrg _mesa_begin_bufferobj_lookups(ctx); 1545af69d88dSmrg 1546af69d88dSmrg for (i = 0; i < count; i++) { 1547af69d88dSmrg struct gl_buffer_object *vbo; 1548af69d88dSmrg 1549af69d88dSmrg /* The ARB_multi_bind spec says: 1550af69d88dSmrg * 1551af69d88dSmrg * "An INVALID_VALUE error is generated if any value in 1552af69d88dSmrg * <offsets> or <strides> is negative (per binding)." 1553af69d88dSmrg */ 1554af69d88dSmrg if (offsets[i] < 0) { 1555af69d88dSmrg _mesa_error(ctx, GL_INVALID_VALUE, 1556af69d88dSmrg "glBindVertexBuffers(offsets[%u]=%" PRId64 " < 0)", 1557af69d88dSmrg i, (int64_t) offsets[i]); 1558af69d88dSmrg continue; 1559af69d88dSmrg } 1560af69d88dSmrg 1561af69d88dSmrg if (strides[i] < 0) { 1562af69d88dSmrg _mesa_error(ctx, GL_INVALID_VALUE, 1563af69d88dSmrg "glBindVertexBuffers(strides[%u]=%d < 0)", 1564af69d88dSmrg i, strides[i]); 1565af69d88dSmrg continue; 1566af69d88dSmrg } 1567af69d88dSmrg 1568af69d88dSmrg if (buffers[i]) { 1569af69d88dSmrg struct gl_vertex_buffer_binding *binding = 1570af69d88dSmrg &vao->VertexBinding[VERT_ATTRIB_GENERIC(first + i)]; 1571af69d88dSmrg 1572af69d88dSmrg if (buffers[i] == binding->BufferObj->Name) 1573af69d88dSmrg vbo = binding->BufferObj; 1574af69d88dSmrg else 1575af69d88dSmrg vbo = _mesa_multi_bind_lookup_bufferobj(ctx, buffers, i, 1576af69d88dSmrg "glBindVertexBuffers"); 1577af69d88dSmrg 1578af69d88dSmrg if (!vbo) 1579af69d88dSmrg continue; 1580af69d88dSmrg } else { 1581af69d88dSmrg vbo = ctx->Shared->NullBufferObj; 1582af69d88dSmrg } 1583af69d88dSmrg 1584af69d88dSmrg bind_vertex_buffer(ctx, VERT_ATTRIB_GENERIC(first + i), vbo, 1585af69d88dSmrg offsets[i], strides[i]); 1586af69d88dSmrg } 1587af69d88dSmrg 1588af69d88dSmrg _mesa_end_bufferobj_lookups(ctx); 1589af69d88dSmrg} 1590af69d88dSmrg 1591af69d88dSmrg 1592af69d88dSmrgvoid GLAPIENTRY 1593af69d88dSmrg_mesa_VertexAttribFormat(GLuint attribIndex, GLint size, GLenum type, 1594af69d88dSmrg GLboolean normalized, GLuint relativeOffset) 1595af69d88dSmrg{ 1596af69d88dSmrg const GLbitfield legalTypes = (BYTE_BIT | UNSIGNED_BYTE_BIT | 1597af69d88dSmrg SHORT_BIT | UNSIGNED_SHORT_BIT | 1598af69d88dSmrg INT_BIT | UNSIGNED_INT_BIT | 1599af69d88dSmrg HALF_BIT | FLOAT_BIT | DOUBLE_BIT | 1600af69d88dSmrg FIXED_GL_BIT | 1601af69d88dSmrg UNSIGNED_INT_2_10_10_10_REV_BIT | 1602af69d88dSmrg INT_2_10_10_10_REV_BIT | 1603af69d88dSmrg UNSIGNED_INT_10F_11F_11F_REV_BIT); 1604af69d88dSmrg 1605af69d88dSmrg GET_CURRENT_CONTEXT(ctx); 1606af69d88dSmrg ASSERT_OUTSIDE_BEGIN_END(ctx); 1607af69d88dSmrg 1608af69d88dSmrg /* The ARB_vertex_attrib_binding spec says: 1609af69d88dSmrg * 1610af69d88dSmrg * "An INVALID_OPERATION error is generated under any of the following 1611af69d88dSmrg * conditions: 1612af69d88dSmrg * - if no vertex array object is currently bound (see section 2.10); 1613af69d88dSmrg * - ..." 1614af69d88dSmrg */ 1615af69d88dSmrg if (ctx->API == API_OPENGL_CORE && 1616af69d88dSmrg ctx->Array.VAO == ctx->Array.DefaultVAO) { 1617af69d88dSmrg _mesa_error(ctx, GL_INVALID_OPERATION, 1618af69d88dSmrg "glVertexAttribFormat(No array object bound)"); 1619af69d88dSmrg return; 1620af69d88dSmrg } 1621af69d88dSmrg 1622af69d88dSmrg /* The ARB_vertex_attrib_binding spec says: 1623af69d88dSmrg * 1624af69d88dSmrg * "The error INVALID_VALUE is generated if index is greater than or equal 1625af69d88dSmrg * to the value of MAX_VERTEX_ATTRIBS." 1626af69d88dSmrg */ 1627af69d88dSmrg if (attribIndex >= ctx->Const.Program[MESA_SHADER_VERTEX].MaxAttribs) { 1628af69d88dSmrg _mesa_error(ctx, GL_INVALID_VALUE, 1629af69d88dSmrg "glVertexAttribFormat(attribindex=%u > " 1630af69d88dSmrg "GL_MAX_VERTEX_ATTRIBS)", 1631af69d88dSmrg attribIndex); 1632af69d88dSmrg return; 1633af69d88dSmrg } 1634af69d88dSmrg 1635af69d88dSmrg FLUSH_VERTICES(ctx, 0); 1636af69d88dSmrg 1637af69d88dSmrg update_array_format(ctx, "glVertexAttribFormat", 1638af69d88dSmrg VERT_ATTRIB_GENERIC(attribIndex), 1639af69d88dSmrg legalTypes, 1, BGRA_OR_4, size, type, normalized, 1640af69d88dSmrg GL_FALSE, relativeOffset); 1641af69d88dSmrg} 1642af69d88dSmrg 1643af69d88dSmrg 1644af69d88dSmrgvoid GLAPIENTRY 1645af69d88dSmrg_mesa_VertexAttribIFormat(GLuint attribIndex, GLint size, GLenum type, 1646af69d88dSmrg GLuint relativeOffset) 1647af69d88dSmrg{ 1648af69d88dSmrg const GLbitfield legalTypes = (BYTE_BIT | UNSIGNED_BYTE_BIT | 1649af69d88dSmrg SHORT_BIT | UNSIGNED_SHORT_BIT | 1650af69d88dSmrg INT_BIT | UNSIGNED_INT_BIT); 1651af69d88dSmrg 1652af69d88dSmrg GET_CURRENT_CONTEXT(ctx); 1653af69d88dSmrg ASSERT_OUTSIDE_BEGIN_END(ctx); 1654af69d88dSmrg 1655af69d88dSmrg /* The ARB_vertex_attrib_binding spec says: 1656af69d88dSmrg * 1657af69d88dSmrg * "An INVALID_OPERATION error is generated under any of the following 1658af69d88dSmrg * conditions: 1659af69d88dSmrg * - if no vertex array object is currently bound (see section 2.10); 1660af69d88dSmrg * - ..." 1661af69d88dSmrg */ 1662af69d88dSmrg if (ctx->API == API_OPENGL_CORE && 1663af69d88dSmrg ctx->Array.VAO == ctx->Array.DefaultVAO) { 1664af69d88dSmrg _mesa_error(ctx, GL_INVALID_OPERATION, 1665af69d88dSmrg "glVertexAttribIFormat(No array object bound)"); 1666af69d88dSmrg return; 1667af69d88dSmrg } 1668af69d88dSmrg 1669af69d88dSmrg /* The ARB_vertex_attrib_binding spec says: 1670af69d88dSmrg * 1671af69d88dSmrg * "The error INVALID_VALUE is generated if index is greater than 1672af69d88dSmrg * or equal to the value of MAX_VERTEX_ATTRIBS." 1673af69d88dSmrg */ 1674af69d88dSmrg if (attribIndex >= ctx->Const.Program[MESA_SHADER_VERTEX].MaxAttribs) { 1675af69d88dSmrg _mesa_error(ctx, GL_INVALID_VALUE, 1676af69d88dSmrg "glVertexAttribIFormat(attribindex=%u > " 1677af69d88dSmrg "GL_MAX_VERTEX_ATTRIBS)", 1678af69d88dSmrg attribIndex); 1679af69d88dSmrg return; 1680af69d88dSmrg } 1681af69d88dSmrg 1682af69d88dSmrg FLUSH_VERTICES(ctx, 0); 1683af69d88dSmrg 1684af69d88dSmrg update_array_format(ctx, "glVertexAttribIFormat", 1685af69d88dSmrg VERT_ATTRIB_GENERIC(attribIndex), 1686af69d88dSmrg legalTypes, 1, 4, size, type, GL_FALSE, GL_TRUE, 1687af69d88dSmrg relativeOffset); 1688af69d88dSmrg} 1689af69d88dSmrg 1690af69d88dSmrg 1691af69d88dSmrgvoid GLAPIENTRY 1692af69d88dSmrg_mesa_VertexAttribLFormat(GLuint attribIndex, GLint size, GLenum type, 1693af69d88dSmrg GLuint relativeOffset) 1694af69d88dSmrg{ 1695af69d88dSmrg const GLbitfield legalTypes = DOUBLE_BIT; 1696af69d88dSmrg 1697af69d88dSmrg GET_CURRENT_CONTEXT(ctx); 1698af69d88dSmrg ASSERT_OUTSIDE_BEGIN_END(ctx); 1699af69d88dSmrg 1700af69d88dSmrg /* Page 298 of the PDF of the OpenGL 4.3 (Core Profile) spec says: 1701af69d88dSmrg * 1702af69d88dSmrg * "An INVALID_OPERATION error is generated under any of the following 1703af69d88dSmrg * conditions: 1704af69d88dSmrg * • if no vertex array object is currently bound (see section 10.4); 1705af69d88dSmrg * • ..." 1706af69d88dSmrg * 1707af69d88dSmrg * This language is missing from the extension spec, but we assume 1708af69d88dSmrg * that this is an oversight. 1709af69d88dSmrg */ 1710af69d88dSmrg if (ctx->API == API_OPENGL_CORE && 1711af69d88dSmrg ctx->Array.VAO == ctx->Array.DefaultVAO) { 1712af69d88dSmrg _mesa_error(ctx, GL_INVALID_OPERATION, 1713af69d88dSmrg "glVertexAttribLFormat(No array object bound)"); 1714af69d88dSmrg return; 1715af69d88dSmrg } 1716af69d88dSmrg 1717af69d88dSmrg /* The ARB_vertex_attrib_binding spec says: 1718af69d88dSmrg * 1719af69d88dSmrg * "The error INVALID_VALUE is generated if <attribindex> is greater than 1720af69d88dSmrg * or equal to the value of MAX_VERTEX_ATTRIBS." 1721af69d88dSmrg */ 1722af69d88dSmrg if (attribIndex >= ctx->Const.Program[MESA_SHADER_VERTEX].MaxAttribs) { 1723af69d88dSmrg _mesa_error(ctx, GL_INVALID_VALUE, 1724af69d88dSmrg "glVertexAttribLFormat(attribindex=%u > " 1725af69d88dSmrg "GL_MAX_VERTEX_ATTRIBS)", 1726af69d88dSmrg attribIndex); 1727af69d88dSmrg return; 1728af69d88dSmrg } 1729af69d88dSmrg 1730af69d88dSmrg FLUSH_VERTICES(ctx, 0); 1731af69d88dSmrg 1732af69d88dSmrg update_array_format(ctx, "glVertexAttribLFormat", 1733af69d88dSmrg VERT_ATTRIB_GENERIC(attribIndex), 1734af69d88dSmrg legalTypes, 1, 4, size, type, GL_FALSE, GL_FALSE, 1735af69d88dSmrg relativeOffset); 1736af69d88dSmrg} 1737af69d88dSmrg 1738af69d88dSmrg 1739af69d88dSmrgvoid GLAPIENTRY 1740af69d88dSmrg_mesa_VertexAttribBinding(GLuint attribIndex, GLuint bindingIndex) 1741af69d88dSmrg{ 1742af69d88dSmrg GET_CURRENT_CONTEXT(ctx); 1743af69d88dSmrg ASSERT_OUTSIDE_BEGIN_END(ctx); 1744af69d88dSmrg 1745af69d88dSmrg /* The ARB_vertex_attrib_binding spec says: 1746af69d88dSmrg * 1747af69d88dSmrg * "An INVALID_OPERATION error is generated if no vertex array object 1748af69d88dSmrg * is bound." 1749af69d88dSmrg */ 1750af69d88dSmrg if (ctx->API == API_OPENGL_CORE && 1751af69d88dSmrg ctx->Array.VAO == ctx->Array.DefaultVAO) { 1752af69d88dSmrg _mesa_error(ctx, GL_INVALID_OPERATION, 1753af69d88dSmrg "glVertexAttribBinding(No array object bound)"); 1754af69d88dSmrg return; 1755af69d88dSmrg } 1756af69d88dSmrg 1757af69d88dSmrg /* The ARB_vertex_attrib_binding spec says: 1758af69d88dSmrg * 1759af69d88dSmrg * "<attribindex> must be less than the value of MAX_VERTEX_ATTRIBS and 1760af69d88dSmrg * <bindingindex> must be less than the value of 1761af69d88dSmrg * MAX_VERTEX_ATTRIB_BINDINGS, otherwise the error INVALID_VALUE 1762af69d88dSmrg * is generated." 1763af69d88dSmrg */ 1764af69d88dSmrg if (attribIndex >= ctx->Const.Program[MESA_SHADER_VERTEX].MaxAttribs) { 1765af69d88dSmrg _mesa_error(ctx, GL_INVALID_VALUE, 1766af69d88dSmrg "glVertexAttribBinding(attribindex=%u >= " 1767af69d88dSmrg "GL_MAX_VERTEX_ATTRIBS)", 1768af69d88dSmrg attribIndex); 1769af69d88dSmrg return; 1770af69d88dSmrg } 1771af69d88dSmrg 1772af69d88dSmrg if (bindingIndex >= ctx->Const.MaxVertexAttribBindings) { 1773af69d88dSmrg _mesa_error(ctx, GL_INVALID_VALUE, 1774af69d88dSmrg "glVertexAttribBinding(bindingindex=%u >= " 1775af69d88dSmrg "GL_MAX_VERTEX_ATTRIB_BINDINGS)", 1776af69d88dSmrg bindingIndex); 1777af69d88dSmrg return; 1778af69d88dSmrg } 1779af69d88dSmrg 1780af69d88dSmrg ASSERT(VERT_ATTRIB_GENERIC(attribIndex) < 1781af69d88dSmrg Elements(ctx->Array.VAO->VertexAttrib)); 1782af69d88dSmrg 1783af69d88dSmrg vertex_attrib_binding(ctx, VERT_ATTRIB_GENERIC(attribIndex), 1784af69d88dSmrg VERT_ATTRIB_GENERIC(bindingIndex)); 1785af69d88dSmrg} 1786af69d88dSmrg 1787af69d88dSmrg 1788af69d88dSmrgvoid GLAPIENTRY 1789af69d88dSmrg_mesa_VertexBindingDivisor(GLuint bindingIndex, GLuint divisor) 1790af69d88dSmrg{ 1791af69d88dSmrg GET_CURRENT_CONTEXT(ctx); 1792af69d88dSmrg ASSERT_OUTSIDE_BEGIN_END(ctx); 1793af69d88dSmrg 1794af69d88dSmrg if (!ctx->Extensions.ARB_instanced_arrays) { 1795af69d88dSmrg _mesa_error(ctx, GL_INVALID_OPERATION, "glVertexBindingDivisor()"); 1796af69d88dSmrg return; 1797af69d88dSmrg } 1798af69d88dSmrg 1799af69d88dSmrg /* The ARB_vertex_attrib_binding spec says: 1800af69d88dSmrg * 1801af69d88dSmrg * "An INVALID_OPERATION error is generated if no vertex array object 1802af69d88dSmrg * is bound." 1803af69d88dSmrg */ 1804af69d88dSmrg if (ctx->API == API_OPENGL_CORE && 1805af69d88dSmrg ctx->Array.VAO == ctx->Array.DefaultVAO) { 1806af69d88dSmrg _mesa_error(ctx, GL_INVALID_OPERATION, 1807af69d88dSmrg "glVertexBindingDivisor(No array object bound)"); 1808af69d88dSmrg return; 1809af69d88dSmrg } 1810af69d88dSmrg 1811af69d88dSmrg /* The ARB_vertex_attrib_binding spec says: 1812af69d88dSmrg * 1813af69d88dSmrg * "An INVALID_VALUE error is generated if <bindingindex> is greater 1814af69d88dSmrg * than or equal to the value of MAX_VERTEX_ATTRIB_BINDINGS." 1815af69d88dSmrg */ 1816af69d88dSmrg if (bindingIndex >= ctx->Const.MaxVertexAttribBindings) { 1817af69d88dSmrg _mesa_error(ctx, GL_INVALID_VALUE, 1818af69d88dSmrg "glVertexBindingDivisor(bindingindex=%u > " 1819af69d88dSmrg "GL_MAX_VERTEX_ATTRIB_BINDINGS)", 1820af69d88dSmrg bindingIndex); 1821af69d88dSmrg return; 1822af69d88dSmrg } 1823af69d88dSmrg 1824af69d88dSmrg vertex_binding_divisor(ctx, VERT_ATTRIB_GENERIC(bindingIndex), divisor); 1825af69d88dSmrg} 1826af69d88dSmrg 18273464ebd5Sriastradh 18284a49301eSmrg/** 18294a49301eSmrg * Copy one client vertex array to another. 18304a49301eSmrg */ 18314a49301eSmrgvoid 18323464ebd5Sriastradh_mesa_copy_client_array(struct gl_context *ctx, 18334a49301eSmrg struct gl_client_array *dst, 18344a49301eSmrg struct gl_client_array *src) 18354a49301eSmrg{ 18364a49301eSmrg dst->Size = src->Size; 18374a49301eSmrg dst->Type = src->Type; 18384a49301eSmrg dst->Format = src->Format; 18394a49301eSmrg dst->Stride = src->Stride; 18404a49301eSmrg dst->StrideB = src->StrideB; 18414a49301eSmrg dst->Ptr = src->Ptr; 18424a49301eSmrg dst->Enabled = src->Enabled; 18434a49301eSmrg dst->Normalized = src->Normalized; 18443464ebd5Sriastradh dst->Integer = src->Integer; 18453464ebd5Sriastradh dst->InstanceDivisor = src->InstanceDivisor; 18464a49301eSmrg dst->_ElementSize = src->_ElementSize; 18474a49301eSmrg _mesa_reference_buffer_object(ctx, &dst->BufferObj, src->BufferObj); 18484a49301eSmrg dst->_MaxElement = src->_MaxElement; 18494a49301eSmrg} 18504a49301eSmrg 1851af69d88dSmrgvoid 1852af69d88dSmrg_mesa_copy_vertex_attrib_array(struct gl_context *ctx, 1853af69d88dSmrg struct gl_vertex_attrib_array *dst, 1854af69d88dSmrg const struct gl_vertex_attrib_array *src) 1855af69d88dSmrg{ 1856af69d88dSmrg dst->Size = src->Size; 1857af69d88dSmrg dst->Type = src->Type; 1858af69d88dSmrg dst->Format = src->Format; 1859af69d88dSmrg dst->VertexBinding = src->VertexBinding; 1860af69d88dSmrg dst->RelativeOffset = src->RelativeOffset; 1861af69d88dSmrg dst->Format = src->Format; 1862af69d88dSmrg dst->Integer = src->Integer; 1863af69d88dSmrg dst->Normalized = src->Normalized; 1864af69d88dSmrg dst->Ptr = src->Ptr; 1865af69d88dSmrg dst->Enabled = src->Enabled; 1866af69d88dSmrg dst->_ElementSize = src->_ElementSize; 1867af69d88dSmrg} 1868af69d88dSmrg 1869af69d88dSmrgvoid 1870af69d88dSmrg_mesa_copy_vertex_buffer_binding(struct gl_context *ctx, 1871af69d88dSmrg struct gl_vertex_buffer_binding *dst, 1872af69d88dSmrg const struct gl_vertex_buffer_binding *src) 1873af69d88dSmrg{ 1874af69d88dSmrg dst->Offset = src->Offset; 1875af69d88dSmrg dst->Stride = src->Stride; 1876af69d88dSmrg dst->InstanceDivisor = src->InstanceDivisor; 1877af69d88dSmrg dst->_BoundArrays = src->_BoundArrays; 18784a49301eSmrg 1879af69d88dSmrg _mesa_reference_buffer_object(ctx, &dst->BufferObj, src->BufferObj); 1880af69d88dSmrg} 18814a49301eSmrg 18824a49301eSmrg/** 18834a49301eSmrg * Print vertex array's fields. 18844a49301eSmrg */ 18854a49301eSmrgstatic void 18864a49301eSmrgprint_array(const char *name, GLint index, const struct gl_client_array *array) 18874a49301eSmrg{ 18884a49301eSmrg if (index >= 0) 1889cdc920a0Smrg printf(" %s[%d]: ", name, index); 18904a49301eSmrg else 1891cdc920a0Smrg printf(" %s: ", name); 18923464ebd5Sriastradh printf("Ptr=%p, Type=0x%x, Size=%d, ElemSize=%u, Stride=%d, Buffer=%u(Size %lu), MaxElem=%u\n", 1893cdc920a0Smrg array->Ptr, array->Type, array->Size, 1894cdc920a0Smrg array->_ElementSize, array->StrideB, 18953464ebd5Sriastradh array->BufferObj->Name, (unsigned long) array->BufferObj->Size, 1896cdc920a0Smrg array->_MaxElement); 18974a49301eSmrg} 18984a49301eSmrg 18994a49301eSmrg 19004a49301eSmrg/** 19014a49301eSmrg * Print current vertex object/array info. For debug. 19024a49301eSmrg */ 19034a49301eSmrgvoid 19043464ebd5Sriastradh_mesa_print_arrays(struct gl_context *ctx) 19054a49301eSmrg{ 1906af69d88dSmrg struct gl_vertex_array_object *vao = ctx->Array.VAO; 19074a49301eSmrg GLuint i; 19084a49301eSmrg 1909af69d88dSmrg _mesa_update_vao_max_element(ctx, vao); 1910af69d88dSmrg 1911af69d88dSmrg printf("Array Object %u\n", vao->Name); 1912af69d88dSmrg if (vao->_VertexAttrib[VERT_ATTRIB_POS].Enabled) 1913af69d88dSmrg print_array("Vertex", -1, &vao->_VertexAttrib[VERT_ATTRIB_POS]); 1914af69d88dSmrg if (vao->_VertexAttrib[VERT_ATTRIB_NORMAL].Enabled) 1915af69d88dSmrg print_array("Normal", -1, &vao->_VertexAttrib[VERT_ATTRIB_NORMAL]); 1916af69d88dSmrg if (vao->_VertexAttrib[VERT_ATTRIB_COLOR0].Enabled) 1917af69d88dSmrg print_array("Color", -1, &vao->_VertexAttrib[VERT_ATTRIB_COLOR0]); 1918af69d88dSmrg for (i = 0; i < ctx->Const.MaxTextureCoordUnits; i++) 1919af69d88dSmrg if (vao->_VertexAttrib[VERT_ATTRIB_TEX(i)].Enabled) 1920af69d88dSmrg print_array("TexCoord", i, &vao->_VertexAttrib[VERT_ATTRIB_TEX(i)]); 1921af69d88dSmrg for (i = 0; i < VERT_ATTRIB_GENERIC_MAX; i++) 1922af69d88dSmrg if (vao->_VertexAttrib[VERT_ATTRIB_GENERIC(i)].Enabled) 1923af69d88dSmrg print_array("Attrib", i, &vao->_VertexAttrib[VERT_ATTRIB_GENERIC(i)]); 1924af69d88dSmrg printf(" _MaxElement = %u\n", vao->_MaxElement); 19254a49301eSmrg} 19264a49301eSmrg 19274a49301eSmrg 19287117f1b4Smrg/** 19297117f1b4Smrg * Initialize vertex array state for given context. 19307117f1b4Smrg */ 19317117f1b4Smrgvoid 19323464ebd5Sriastradh_mesa_init_varray(struct gl_context *ctx) 19337117f1b4Smrg{ 1934af69d88dSmrg ctx->Array.DefaultVAO = ctx->Driver.NewArrayObject(ctx, 0); 1935af69d88dSmrg _mesa_reference_vao(ctx, &ctx->Array.VAO, ctx->Array.DefaultVAO); 19367117f1b4Smrg ctx->Array.ActiveTexture = 0; /* GL_ARB_multitexture */ 19374a49301eSmrg 19384a49301eSmrg ctx->Array.Objects = _mesa_NewHashTable(); 19394a49301eSmrg} 19404a49301eSmrg 19414a49301eSmrg 19424a49301eSmrg/** 19434a49301eSmrg * Callback for deleting an array object. Called by _mesa_HashDeleteAll(). 19444a49301eSmrg */ 19454a49301eSmrgstatic void 19464a49301eSmrgdelete_arrayobj_cb(GLuint id, void *data, void *userData) 19474a49301eSmrg{ 1948af69d88dSmrg struct gl_vertex_array_object *vao = (struct gl_vertex_array_object *) data; 19493464ebd5Sriastradh struct gl_context *ctx = (struct gl_context *) userData; 1950af69d88dSmrg _mesa_delete_vao(ctx, vao); 19514a49301eSmrg} 19524a49301eSmrg 19534a49301eSmrg 19544a49301eSmrg/** 19554a49301eSmrg * Free vertex array state for given context. 19564a49301eSmrg */ 19574a49301eSmrgvoid 19583464ebd5Sriastradh_mesa_free_varray_data(struct gl_context *ctx) 19594a49301eSmrg{ 19604a49301eSmrg _mesa_HashDeleteAll(ctx->Array.Objects, delete_arrayobj_cb, ctx); 19614a49301eSmrg _mesa_DeleteHashTable(ctx->Array.Objects); 19627117f1b4Smrg} 1963