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 2701e04c3fSmrg#include <stdio.h> 28af69d88dSmrg#include <inttypes.h> /* for PRId64 macro */ 29af69d88dSmrg 307117f1b4Smrg#include "glheader.h" 317ec681f3Smrg 327117f1b4Smrg#include "bufferobj.h" 337117f1b4Smrg#include "context.h" 347117f1b4Smrg#include "enable.h" 357117f1b4Smrg#include "enums.h" 36b9abf16eSmaya#include "glformats.h" 374a49301eSmrg#include "hash.h" 383464ebd5Sriastradh#include "image.h" 393464ebd5Sriastradh#include "macros.h" 407117f1b4Smrg#include "mtypes.h" 417117f1b4Smrg#include "varray.h" 427117f1b4Smrg#include "arrayobj.h" 437ec681f3Smrg#include "get.h" 44cdc920a0Smrg#include "main/dispatch.h" 457117f1b4Smrg 467117f1b4Smrg 473464ebd5Sriastradh/** Used to do error checking for GL_EXT_vertex_array_bgra */ 483464ebd5Sriastradh#define BGRA_OR_4 5 493464ebd5Sriastradh 503464ebd5Sriastradh 513464ebd5Sriastradh/** Used to indicate which GL datatypes are accepted by each of the 523464ebd5Sriastradh * glVertex/Color/Attrib/EtcPointer() functions. 533464ebd5Sriastradh */ 54af69d88dSmrg#define BOOL_BIT (1 << 0) 55af69d88dSmrg#define BYTE_BIT (1 << 1) 56af69d88dSmrg#define UNSIGNED_BYTE_BIT (1 << 2) 57af69d88dSmrg#define SHORT_BIT (1 << 3) 58af69d88dSmrg#define UNSIGNED_SHORT_BIT (1 << 4) 59af69d88dSmrg#define INT_BIT (1 << 5) 60af69d88dSmrg#define UNSIGNED_INT_BIT (1 << 6) 61af69d88dSmrg#define HALF_BIT (1 << 7) 62af69d88dSmrg#define FLOAT_BIT (1 << 8) 63af69d88dSmrg#define DOUBLE_BIT (1 << 9) 64af69d88dSmrg#define FIXED_ES_BIT (1 << 10) 65af69d88dSmrg#define FIXED_GL_BIT (1 << 11) 66af69d88dSmrg#define UNSIGNED_INT_2_10_10_10_REV_BIT (1 << 12) 67af69d88dSmrg#define INT_2_10_10_10_REV_BIT (1 << 13) 68af69d88dSmrg#define UNSIGNED_INT_10F_11F_11F_REV_BIT (1 << 14) 69af69d88dSmrg#define ALL_TYPE_BITS ((1 << 15) - 1) 703464ebd5Sriastradh 7101e04c3fSmrg#define ATTRIB_FORMAT_TYPES_MASK (BYTE_BIT | UNSIGNED_BYTE_BIT | \ 7201e04c3fSmrg SHORT_BIT | UNSIGNED_SHORT_BIT | \ 7301e04c3fSmrg INT_BIT | UNSIGNED_INT_BIT | \ 7401e04c3fSmrg HALF_BIT | FLOAT_BIT | DOUBLE_BIT | \ 7501e04c3fSmrg FIXED_GL_BIT | \ 7601e04c3fSmrg UNSIGNED_INT_2_10_10_10_REV_BIT | \ 7701e04c3fSmrg INT_2_10_10_10_REV_BIT | \ 7801e04c3fSmrg UNSIGNED_INT_10F_11F_11F_REV_BIT) 7901e04c3fSmrg 8001e04c3fSmrg#define ATTRIB_IFORMAT_TYPES_MASK (BYTE_BIT | UNSIGNED_BYTE_BIT | \ 8101e04c3fSmrg SHORT_BIT | UNSIGNED_SHORT_BIT | \ 8201e04c3fSmrg INT_BIT | UNSIGNED_INT_BIT) 8301e04c3fSmrg 8401e04c3fSmrg#define ATTRIB_LFORMAT_TYPES_MASK DOUBLE_BIT 8501e04c3fSmrg 863464ebd5Sriastradh 873464ebd5Sriastradh/** Convert GL datatype enum into a <type>_BIT value seen above */ 883464ebd5Sriastradhstatic GLbitfield 893464ebd5Sriastradhtype_to_bit(const struct gl_context *ctx, GLenum type) 903464ebd5Sriastradh{ 913464ebd5Sriastradh switch (type) { 923464ebd5Sriastradh case GL_BOOL: 933464ebd5Sriastradh return BOOL_BIT; 943464ebd5Sriastradh case GL_BYTE: 953464ebd5Sriastradh return BYTE_BIT; 963464ebd5Sriastradh case GL_UNSIGNED_BYTE: 973464ebd5Sriastradh return UNSIGNED_BYTE_BIT; 983464ebd5Sriastradh case GL_SHORT: 993464ebd5Sriastradh return SHORT_BIT; 1003464ebd5Sriastradh case GL_UNSIGNED_SHORT: 1013464ebd5Sriastradh return UNSIGNED_SHORT_BIT; 1023464ebd5Sriastradh case GL_INT: 1033464ebd5Sriastradh return INT_BIT; 1043464ebd5Sriastradh case GL_UNSIGNED_INT: 1053464ebd5Sriastradh return UNSIGNED_INT_BIT; 1063464ebd5Sriastradh case GL_HALF_FLOAT: 10701e04c3fSmrg case GL_HALF_FLOAT_OES: 1083464ebd5Sriastradh if (ctx->Extensions.ARB_half_float_vertex) 1093464ebd5Sriastradh return HALF_BIT; 1103464ebd5Sriastradh else 1113464ebd5Sriastradh return 0x0; 1123464ebd5Sriastradh case GL_FLOAT: 1133464ebd5Sriastradh return FLOAT_BIT; 1143464ebd5Sriastradh case GL_DOUBLE: 1153464ebd5Sriastradh return DOUBLE_BIT; 1163464ebd5Sriastradh case GL_FIXED: 117af69d88dSmrg return _mesa_is_desktop_gl(ctx) ? FIXED_GL_BIT : FIXED_ES_BIT; 118af69d88dSmrg case GL_UNSIGNED_INT_2_10_10_10_REV: 119af69d88dSmrg return UNSIGNED_INT_2_10_10_10_REV_BIT; 120af69d88dSmrg case GL_INT_2_10_10_10_REV: 121af69d88dSmrg return INT_2_10_10_10_REV_BIT; 122af69d88dSmrg case GL_UNSIGNED_INT_10F_11F_11F_REV: 123af69d88dSmrg return UNSIGNED_INT_10F_11F_11F_REV_BIT; 1243464ebd5Sriastradh default: 1253464ebd5Sriastradh return 0; 1263464ebd5Sriastradh } 1273464ebd5Sriastradh} 1283464ebd5Sriastradh 1293464ebd5Sriastradh 1307117f1b4Smrg/** 13101e04c3fSmrg * Depending on the position and generic0 attributes enable flags select 13201e04c3fSmrg * the one that is used for both attributes. 13301e04c3fSmrg * The generic0 attribute takes precedence. 1347117f1b4Smrg */ 13501e04c3fSmrgstatic inline void 13601e04c3fSmrgupdate_attribute_map_mode(const struct gl_context *ctx, 13701e04c3fSmrg struct gl_vertex_array_object *vao) 138af69d88dSmrg{ 13901e04c3fSmrg /* 14001e04c3fSmrg * There is no need to change the mapping away from the 14101e04c3fSmrg * identity mapping if we are not in compat mode. 14201e04c3fSmrg */ 14301e04c3fSmrg if (ctx->API != API_OPENGL_COMPAT) 14401e04c3fSmrg return; 14501e04c3fSmrg /* The generic0 attribute superseeds the position attribute */ 146b9abf16eSmaya const GLbitfield enabled = vao->Enabled; 14701e04c3fSmrg if (enabled & VERT_BIT_GENERIC0) 14801e04c3fSmrg vao->_AttributeMapMode = ATTRIBUTE_MAP_MODE_GENERIC0; 14901e04c3fSmrg else if (enabled & VERT_BIT_POS) 15001e04c3fSmrg vao->_AttributeMapMode = ATTRIBUTE_MAP_MODE_POSITION; 15101e04c3fSmrg else 15201e04c3fSmrg vao->_AttributeMapMode = ATTRIBUTE_MAP_MODE_IDENTITY; 15301e04c3fSmrg} 15401e04c3fSmrg 155af69d88dSmrg 15601e04c3fSmrg/** 15701e04c3fSmrg * Sets the BufferBindingIndex field for the vertex attribute given by 15801e04c3fSmrg * attribIndex. 15901e04c3fSmrg */ 16001e04c3fSmrgvoid 16101e04c3fSmrg_mesa_vertex_attrib_binding(struct gl_context *ctx, 16201e04c3fSmrg struct gl_vertex_array_object *vao, 16301e04c3fSmrg gl_vert_attrib attribIndex, 16401e04c3fSmrg GLuint bindingIndex) 16501e04c3fSmrg{ 16601e04c3fSmrg struct gl_array_attributes *array = &vao->VertexAttrib[attribIndex]; 16701e04c3fSmrg assert(!vao->SharedAndImmutable); 168af69d88dSmrg 16901e04c3fSmrg if (array->BufferBindingIndex != bindingIndex) { 17001e04c3fSmrg const GLbitfield array_bit = VERT_BIT(attribIndex); 171af69d88dSmrg 1727ec681f3Smrg if (vao->BufferBinding[bindingIndex].BufferObj) 17301e04c3fSmrg vao->VertexAttribBufferMask |= array_bit; 17401e04c3fSmrg else 17501e04c3fSmrg vao->VertexAttribBufferMask &= ~array_bit; 176af69d88dSmrg 1777ec681f3Smrg if (vao->BufferBinding[bindingIndex].InstanceDivisor) 1787ec681f3Smrg vao->NonZeroDivisorMask |= array_bit; 1797ec681f3Smrg else 1807ec681f3Smrg vao->NonZeroDivisorMask &= ~array_bit; 1817ec681f3Smrg 18201e04c3fSmrg vao->BufferBinding[array->BufferBindingIndex]._BoundArrays &= ~array_bit; 18301e04c3fSmrg vao->BufferBinding[bindingIndex]._BoundArrays |= array_bit; 184af69d88dSmrg 18501e04c3fSmrg array->BufferBindingIndex = bindingIndex; 18601e04c3fSmrg 187b9abf16eSmaya vao->NewArrays |= vao->Enabled & array_bit; 1887ec681f3Smrg vao->NonDefaultStateMask |= array_bit | BITFIELD_BIT(bindingIndex); 189af69d88dSmrg } 190af69d88dSmrg} 191af69d88dSmrg 192af69d88dSmrg 193af69d88dSmrg/** 194af69d88dSmrg * Binds a buffer object to the vertex buffer binding point given by index, 195af69d88dSmrg * and sets the Offset and Stride fields. 196af69d88dSmrg */ 19701e04c3fSmrgvoid 19801e04c3fSmrg_mesa_bind_vertex_buffer(struct gl_context *ctx, 19901e04c3fSmrg struct gl_vertex_array_object *vao, 20001e04c3fSmrg GLuint index, 20101e04c3fSmrg struct gl_buffer_object *vbo, 2027ec681f3Smrg GLintptr offset, GLsizei stride, 2037ec681f3Smrg bool offset_is_int32, bool take_vbo_ownership) 204af69d88dSmrg{ 20501e04c3fSmrg assert(index < ARRAY_SIZE(vao->BufferBinding)); 20601e04c3fSmrg assert(!vao->SharedAndImmutable); 20701e04c3fSmrg struct gl_vertex_buffer_binding *binding = &vao->BufferBinding[index]; 208af69d88dSmrg 2097ec681f3Smrg if (ctx->Const.VertexBufferOffsetIsInt32 && (int)offset < 0 && 2107ec681f3Smrg !offset_is_int32 && vbo) { 2117ec681f3Smrg /* The offset will be interpreted as a signed int, so make sure 2127ec681f3Smrg * the user supplied offset is not negative (driver limitation). 2137ec681f3Smrg */ 2147ec681f3Smrg _mesa_warning(ctx, "Received negative int32 vertex buffer offset. " 2157ec681f3Smrg "(driver limitation)\n"); 2167ec681f3Smrg 2177ec681f3Smrg /* We can't disable this binding, so use a non-negative offset value 2187ec681f3Smrg * instead. 2197ec681f3Smrg */ 2207ec681f3Smrg offset = 0; 2217ec681f3Smrg } 2227ec681f3Smrg 223af69d88dSmrg if (binding->BufferObj != vbo || 224af69d88dSmrg binding->Offset != offset || 225af69d88dSmrg binding->Stride != stride) { 226af69d88dSmrg 2277ec681f3Smrg if (take_vbo_ownership) { 2287ec681f3Smrg _mesa_reference_buffer_object(ctx, &binding->BufferObj, NULL); 2297ec681f3Smrg binding->BufferObj = vbo; 2307ec681f3Smrg } else { 2317ec681f3Smrg _mesa_reference_buffer_object(ctx, &binding->BufferObj, vbo); 2327ec681f3Smrg } 233af69d88dSmrg 234af69d88dSmrg binding->Offset = offset; 235af69d88dSmrg binding->Stride = stride; 236af69d88dSmrg 2377ec681f3Smrg if (!vbo) { 23801e04c3fSmrg vao->VertexAttribBufferMask &= ~binding->_BoundArrays; 239b9abf16eSmaya } else { 24001e04c3fSmrg vao->VertexAttribBufferMask |= binding->_BoundArrays; 241b9abf16eSmaya vbo->UsageHistory |= USAGE_ARRAY_BUFFER; 242b9abf16eSmaya } 24301e04c3fSmrg 244b9abf16eSmaya vao->NewArrays |= vao->Enabled & binding->_BoundArrays; 2457ec681f3Smrg vao->NonDefaultStateMask |= BITFIELD_BIT(index); 246af69d88dSmrg } 247af69d88dSmrg} 248af69d88dSmrg 249af69d88dSmrg 250af69d88dSmrg/** 251af69d88dSmrg * Sets the InstanceDivisor field in the vertex buffer binding point 252af69d88dSmrg * given by bindingIndex. 253af69d88dSmrg */ 254af69d88dSmrgstatic void 25501e04c3fSmrgvertex_binding_divisor(struct gl_context *ctx, 25601e04c3fSmrg struct gl_vertex_array_object *vao, 25701e04c3fSmrg GLuint bindingIndex, 258af69d88dSmrg GLuint divisor) 259af69d88dSmrg{ 260af69d88dSmrg struct gl_vertex_buffer_binding *binding = 26101e04c3fSmrg &vao->BufferBinding[bindingIndex]; 26201e04c3fSmrg assert(!vao->SharedAndImmutable); 263af69d88dSmrg 264af69d88dSmrg if (binding->InstanceDivisor != divisor) { 265af69d88dSmrg binding->InstanceDivisor = divisor; 2667ec681f3Smrg 2677ec681f3Smrg if (divisor) 2687ec681f3Smrg vao->NonZeroDivisorMask |= binding->_BoundArrays; 2697ec681f3Smrg else 2707ec681f3Smrg vao->NonZeroDivisorMask &= ~binding->_BoundArrays; 2717ec681f3Smrg 272b9abf16eSmaya vao->NewArrays |= vao->Enabled & binding->_BoundArrays; 2737ec681f3Smrg vao->NonDefaultStateMask |= BITFIELD_BIT(bindingIndex); 274af69d88dSmrg } 275af69d88dSmrg} 276af69d88dSmrg 2777ec681f3Smrg/* vertex_formats[gltype - GL_BYTE][integer*2 + normalized][size - 1] */ 2787ec681f3Smrgstatic const uint16_t vertex_formats[][4][4] = { 2797ec681f3Smrg { /* GL_BYTE */ 2807ec681f3Smrg { 2817ec681f3Smrg PIPE_FORMAT_R8_SSCALED, 2827ec681f3Smrg PIPE_FORMAT_R8G8_SSCALED, 2837ec681f3Smrg PIPE_FORMAT_R8G8B8_SSCALED, 2847ec681f3Smrg PIPE_FORMAT_R8G8B8A8_SSCALED 2857ec681f3Smrg }, 2867ec681f3Smrg { 2877ec681f3Smrg PIPE_FORMAT_R8_SNORM, 2887ec681f3Smrg PIPE_FORMAT_R8G8_SNORM, 2897ec681f3Smrg PIPE_FORMAT_R8G8B8_SNORM, 2907ec681f3Smrg PIPE_FORMAT_R8G8B8A8_SNORM 2917ec681f3Smrg }, 2927ec681f3Smrg { 2937ec681f3Smrg PIPE_FORMAT_R8_SINT, 2947ec681f3Smrg PIPE_FORMAT_R8G8_SINT, 2957ec681f3Smrg PIPE_FORMAT_R8G8B8_SINT, 2967ec681f3Smrg PIPE_FORMAT_R8G8B8A8_SINT 2977ec681f3Smrg }, 2987ec681f3Smrg }, 2997ec681f3Smrg { /* GL_UNSIGNED_BYTE */ 3007ec681f3Smrg { 3017ec681f3Smrg PIPE_FORMAT_R8_USCALED, 3027ec681f3Smrg PIPE_FORMAT_R8G8_USCALED, 3037ec681f3Smrg PIPE_FORMAT_R8G8B8_USCALED, 3047ec681f3Smrg PIPE_FORMAT_R8G8B8A8_USCALED 3057ec681f3Smrg }, 3067ec681f3Smrg { 3077ec681f3Smrg PIPE_FORMAT_R8_UNORM, 3087ec681f3Smrg PIPE_FORMAT_R8G8_UNORM, 3097ec681f3Smrg PIPE_FORMAT_R8G8B8_UNORM, 3107ec681f3Smrg PIPE_FORMAT_R8G8B8A8_UNORM 3117ec681f3Smrg }, 3127ec681f3Smrg { 3137ec681f3Smrg PIPE_FORMAT_R8_UINT, 3147ec681f3Smrg PIPE_FORMAT_R8G8_UINT, 3157ec681f3Smrg PIPE_FORMAT_R8G8B8_UINT, 3167ec681f3Smrg PIPE_FORMAT_R8G8B8A8_UINT 3177ec681f3Smrg }, 3187ec681f3Smrg }, 3197ec681f3Smrg { /* GL_SHORT */ 3207ec681f3Smrg { 3217ec681f3Smrg PIPE_FORMAT_R16_SSCALED, 3227ec681f3Smrg PIPE_FORMAT_R16G16_SSCALED, 3237ec681f3Smrg PIPE_FORMAT_R16G16B16_SSCALED, 3247ec681f3Smrg PIPE_FORMAT_R16G16B16A16_SSCALED 3257ec681f3Smrg }, 3267ec681f3Smrg { 3277ec681f3Smrg PIPE_FORMAT_R16_SNORM, 3287ec681f3Smrg PIPE_FORMAT_R16G16_SNORM, 3297ec681f3Smrg PIPE_FORMAT_R16G16B16_SNORM, 3307ec681f3Smrg PIPE_FORMAT_R16G16B16A16_SNORM 3317ec681f3Smrg }, 3327ec681f3Smrg { 3337ec681f3Smrg PIPE_FORMAT_R16_SINT, 3347ec681f3Smrg PIPE_FORMAT_R16G16_SINT, 3357ec681f3Smrg PIPE_FORMAT_R16G16B16_SINT, 3367ec681f3Smrg PIPE_FORMAT_R16G16B16A16_SINT 3377ec681f3Smrg }, 3387ec681f3Smrg }, 3397ec681f3Smrg { /* GL_UNSIGNED_SHORT */ 3407ec681f3Smrg { 3417ec681f3Smrg PIPE_FORMAT_R16_USCALED, 3427ec681f3Smrg PIPE_FORMAT_R16G16_USCALED, 3437ec681f3Smrg PIPE_FORMAT_R16G16B16_USCALED, 3447ec681f3Smrg PIPE_FORMAT_R16G16B16A16_USCALED 3457ec681f3Smrg }, 3467ec681f3Smrg { 3477ec681f3Smrg PIPE_FORMAT_R16_UNORM, 3487ec681f3Smrg PIPE_FORMAT_R16G16_UNORM, 3497ec681f3Smrg PIPE_FORMAT_R16G16B16_UNORM, 3507ec681f3Smrg PIPE_FORMAT_R16G16B16A16_UNORM 3517ec681f3Smrg }, 3527ec681f3Smrg { 3537ec681f3Smrg PIPE_FORMAT_R16_UINT, 3547ec681f3Smrg PIPE_FORMAT_R16G16_UINT, 3557ec681f3Smrg PIPE_FORMAT_R16G16B16_UINT, 3567ec681f3Smrg PIPE_FORMAT_R16G16B16A16_UINT 3577ec681f3Smrg }, 3587ec681f3Smrg }, 3597ec681f3Smrg { /* GL_INT */ 3607ec681f3Smrg { 3617ec681f3Smrg PIPE_FORMAT_R32_SSCALED, 3627ec681f3Smrg PIPE_FORMAT_R32G32_SSCALED, 3637ec681f3Smrg PIPE_FORMAT_R32G32B32_SSCALED, 3647ec681f3Smrg PIPE_FORMAT_R32G32B32A32_SSCALED 3657ec681f3Smrg }, 3667ec681f3Smrg { 3677ec681f3Smrg PIPE_FORMAT_R32_SNORM, 3687ec681f3Smrg PIPE_FORMAT_R32G32_SNORM, 3697ec681f3Smrg PIPE_FORMAT_R32G32B32_SNORM, 3707ec681f3Smrg PIPE_FORMAT_R32G32B32A32_SNORM 3717ec681f3Smrg }, 3727ec681f3Smrg { 3737ec681f3Smrg PIPE_FORMAT_R32_SINT, 3747ec681f3Smrg PIPE_FORMAT_R32G32_SINT, 3757ec681f3Smrg PIPE_FORMAT_R32G32B32_SINT, 3767ec681f3Smrg PIPE_FORMAT_R32G32B32A32_SINT 3777ec681f3Smrg }, 3787ec681f3Smrg }, 3797ec681f3Smrg { /* GL_UNSIGNED_INT */ 3807ec681f3Smrg { 3817ec681f3Smrg PIPE_FORMAT_R32_USCALED, 3827ec681f3Smrg PIPE_FORMAT_R32G32_USCALED, 3837ec681f3Smrg PIPE_FORMAT_R32G32B32_USCALED, 3847ec681f3Smrg PIPE_FORMAT_R32G32B32A32_USCALED 3857ec681f3Smrg }, 3867ec681f3Smrg { 3877ec681f3Smrg PIPE_FORMAT_R32_UNORM, 3887ec681f3Smrg PIPE_FORMAT_R32G32_UNORM, 3897ec681f3Smrg PIPE_FORMAT_R32G32B32_UNORM, 3907ec681f3Smrg PIPE_FORMAT_R32G32B32A32_UNORM 3917ec681f3Smrg }, 3927ec681f3Smrg { 3937ec681f3Smrg PIPE_FORMAT_R32_UINT, 3947ec681f3Smrg PIPE_FORMAT_R32G32_UINT, 3957ec681f3Smrg PIPE_FORMAT_R32G32B32_UINT, 3967ec681f3Smrg PIPE_FORMAT_R32G32B32A32_UINT 3977ec681f3Smrg }, 3987ec681f3Smrg }, 3997ec681f3Smrg { /* GL_FLOAT */ 4007ec681f3Smrg { 4017ec681f3Smrg PIPE_FORMAT_R32_FLOAT, 4027ec681f3Smrg PIPE_FORMAT_R32G32_FLOAT, 4037ec681f3Smrg PIPE_FORMAT_R32G32B32_FLOAT, 4047ec681f3Smrg PIPE_FORMAT_R32G32B32A32_FLOAT 4057ec681f3Smrg }, 4067ec681f3Smrg { 4077ec681f3Smrg PIPE_FORMAT_R32_FLOAT, 4087ec681f3Smrg PIPE_FORMAT_R32G32_FLOAT, 4097ec681f3Smrg PIPE_FORMAT_R32G32B32_FLOAT, 4107ec681f3Smrg PIPE_FORMAT_R32G32B32A32_FLOAT 4117ec681f3Smrg }, 4127ec681f3Smrg }, 4137ec681f3Smrg {{0}}, /* GL_2_BYTES */ 4147ec681f3Smrg {{0}}, /* GL_3_BYTES */ 4157ec681f3Smrg {{0}}, /* GL_4_BYTES */ 4167ec681f3Smrg { /* GL_DOUBLE */ 4177ec681f3Smrg { 4187ec681f3Smrg PIPE_FORMAT_R64_FLOAT, 4197ec681f3Smrg PIPE_FORMAT_R64G64_FLOAT, 4207ec681f3Smrg PIPE_FORMAT_R64G64B64_FLOAT, 4217ec681f3Smrg PIPE_FORMAT_R64G64B64A64_FLOAT 4227ec681f3Smrg }, 4237ec681f3Smrg { 4247ec681f3Smrg PIPE_FORMAT_R64_FLOAT, 4257ec681f3Smrg PIPE_FORMAT_R64G64_FLOAT, 4267ec681f3Smrg PIPE_FORMAT_R64G64B64_FLOAT, 4277ec681f3Smrg PIPE_FORMAT_R64G64B64A64_FLOAT 4287ec681f3Smrg }, 4297ec681f3Smrg }, 4307ec681f3Smrg { /* GL_HALF_FLOAT */ 4317ec681f3Smrg { 4327ec681f3Smrg PIPE_FORMAT_R16_FLOAT, 4337ec681f3Smrg PIPE_FORMAT_R16G16_FLOAT, 4347ec681f3Smrg PIPE_FORMAT_R16G16B16_FLOAT, 4357ec681f3Smrg PIPE_FORMAT_R16G16B16A16_FLOAT 4367ec681f3Smrg }, 4377ec681f3Smrg { 4387ec681f3Smrg PIPE_FORMAT_R16_FLOAT, 4397ec681f3Smrg PIPE_FORMAT_R16G16_FLOAT, 4407ec681f3Smrg PIPE_FORMAT_R16G16B16_FLOAT, 4417ec681f3Smrg PIPE_FORMAT_R16G16B16A16_FLOAT 4427ec681f3Smrg }, 4437ec681f3Smrg }, 4447ec681f3Smrg { /* GL_FIXED */ 4457ec681f3Smrg { 4467ec681f3Smrg PIPE_FORMAT_R32_FIXED, 4477ec681f3Smrg PIPE_FORMAT_R32G32_FIXED, 4487ec681f3Smrg PIPE_FORMAT_R32G32B32_FIXED, 4497ec681f3Smrg PIPE_FORMAT_R32G32B32A32_FIXED 4507ec681f3Smrg }, 4517ec681f3Smrg { 4527ec681f3Smrg PIPE_FORMAT_R32_FIXED, 4537ec681f3Smrg PIPE_FORMAT_R32G32_FIXED, 4547ec681f3Smrg PIPE_FORMAT_R32G32B32_FIXED, 4557ec681f3Smrg PIPE_FORMAT_R32G32B32A32_FIXED 4567ec681f3Smrg }, 4577ec681f3Smrg }, 4587ec681f3Smrg}; 4597ec681f3Smrg 4607ec681f3Smrg/** 4617ec681f3Smrg * Return a PIPE_FORMAT_x for the given GL datatype and size. 4627ec681f3Smrg */ 4637ec681f3Smrgstatic enum pipe_format 4647ec681f3Smrgvertex_format_to_pipe_format(GLubyte size, GLenum16 type, GLenum16 format, 4657ec681f3Smrg bool normalized, bool integer, bool doubles) 4667ec681f3Smrg{ 4677ec681f3Smrg assert(size >= 1 && size <= 4); 4687ec681f3Smrg assert(format == GL_RGBA || format == GL_BGRA); 4697ec681f3Smrg 4707ec681f3Smrg /* Raw doubles use 64_UINT. */ 4717ec681f3Smrg if (doubles) 4727ec681f3Smrg return PIPE_FORMAT_R64_UINT + size - 1; 4737ec681f3Smrg 4747ec681f3Smrg switch (type) { 4757ec681f3Smrg case GL_HALF_FLOAT_OES: 4767ec681f3Smrg type = GL_HALF_FLOAT; 4777ec681f3Smrg break; 4787ec681f3Smrg 4797ec681f3Smrg case GL_INT_2_10_10_10_REV: 4807ec681f3Smrg assert(size == 4 && !integer); 4817ec681f3Smrg 4827ec681f3Smrg if (format == GL_BGRA) { 4837ec681f3Smrg if (normalized) 4847ec681f3Smrg return PIPE_FORMAT_B10G10R10A2_SNORM; 4857ec681f3Smrg else 4867ec681f3Smrg return PIPE_FORMAT_B10G10R10A2_SSCALED; 4877ec681f3Smrg } else { 4887ec681f3Smrg if (normalized) 4897ec681f3Smrg return PIPE_FORMAT_R10G10B10A2_SNORM; 4907ec681f3Smrg else 4917ec681f3Smrg return PIPE_FORMAT_R10G10B10A2_SSCALED; 4927ec681f3Smrg } 4937ec681f3Smrg break; 4947ec681f3Smrg 4957ec681f3Smrg case GL_UNSIGNED_INT_2_10_10_10_REV: 4967ec681f3Smrg assert(size == 4 && !integer); 4977ec681f3Smrg 4987ec681f3Smrg if (format == GL_BGRA) { 4997ec681f3Smrg if (normalized) 5007ec681f3Smrg return PIPE_FORMAT_B10G10R10A2_UNORM; 5017ec681f3Smrg else 5027ec681f3Smrg return PIPE_FORMAT_B10G10R10A2_USCALED; 5037ec681f3Smrg } else { 5047ec681f3Smrg if (normalized) 5057ec681f3Smrg return PIPE_FORMAT_R10G10B10A2_UNORM; 5067ec681f3Smrg else 5077ec681f3Smrg return PIPE_FORMAT_R10G10B10A2_USCALED; 5087ec681f3Smrg } 5097ec681f3Smrg break; 5107ec681f3Smrg 5117ec681f3Smrg case GL_UNSIGNED_INT_10F_11F_11F_REV: 5127ec681f3Smrg assert(size == 3 && !integer && format == GL_RGBA); 5137ec681f3Smrg return PIPE_FORMAT_R11G11B10_FLOAT; 5147ec681f3Smrg 5157ec681f3Smrg case GL_UNSIGNED_BYTE: 5167ec681f3Smrg if (format == GL_BGRA) { 5177ec681f3Smrg /* this is an odd-ball case */ 5187ec681f3Smrg assert(normalized); 5197ec681f3Smrg return PIPE_FORMAT_B8G8R8A8_UNORM; 5207ec681f3Smrg } 5217ec681f3Smrg break; 5227ec681f3Smrg } 5237ec681f3Smrg 5247ec681f3Smrg unsigned index = integer*2 + normalized; 5257ec681f3Smrg assert(index <= 2); 5267ec681f3Smrg assert(type >= GL_BYTE && type <= GL_FIXED); 5277ec681f3Smrg return vertex_formats[type - GL_BYTE][index][size-1]; 5287ec681f3Smrg} 529af69d88dSmrg 530b9abf16eSmayavoid 531b9abf16eSmaya_mesa_set_vertex_format(struct gl_vertex_format *vertex_format, 532b9abf16eSmaya GLubyte size, GLenum16 type, GLenum16 format, 533b9abf16eSmaya GLboolean normalized, GLboolean integer, 534b9abf16eSmaya GLboolean doubles) 535b9abf16eSmaya{ 536b9abf16eSmaya assert(size <= 4); 537b9abf16eSmaya vertex_format->Type = type; 538b9abf16eSmaya vertex_format->Format = format; 539b9abf16eSmaya vertex_format->Size = size; 540b9abf16eSmaya vertex_format->Normalized = normalized; 541b9abf16eSmaya vertex_format->Integer = integer; 542b9abf16eSmaya vertex_format->Doubles = doubles; 543b9abf16eSmaya vertex_format->_ElementSize = _mesa_bytes_per_vertex_attrib(size, type); 544b9abf16eSmaya assert(vertex_format->_ElementSize <= 4*sizeof(double)); 5457ec681f3Smrg vertex_format->_PipeFormat = 5467ec681f3Smrg vertex_format_to_pipe_format(size, type, format, normalized, integer, 5477ec681f3Smrg doubles); 5487ec681f3Smrg /* pipe_vertex_element::src_format has only 8 bits, assuming a signed enum */ 5497ec681f3Smrg assert(vertex_format->_PipeFormat <= 255); 550b9abf16eSmaya} 551b9abf16eSmaya 552b9abf16eSmaya 553af69d88dSmrg/** 554af69d88dSmrg * Examine the API profile and extensions to determine which types are legal 555af69d88dSmrg * for vertex arrays. This is called once from update_array_format(). 556af69d88dSmrg */ 557af69d88dSmrgstatic GLbitfield 558af69d88dSmrgget_legal_types_mask(const struct gl_context *ctx) 559af69d88dSmrg{ 560af69d88dSmrg GLbitfield legalTypesMask = ALL_TYPE_BITS; 561af69d88dSmrg 562af69d88dSmrg if (_mesa_is_gles(ctx)) { 563af69d88dSmrg legalTypesMask &= ~(FIXED_GL_BIT | 564af69d88dSmrg DOUBLE_BIT | 565af69d88dSmrg UNSIGNED_INT_10F_11F_11F_REV_BIT); 566af69d88dSmrg 567af69d88dSmrg /* GL_INT and GL_UNSIGNED_INT data is not allowed in OpenGL ES until 568af69d88dSmrg * 3.0. The 2_10_10_10 types are added in OpenGL ES 3.0 or 569af69d88dSmrg * GL_OES_vertex_type_10_10_10_2. GL_HALF_FLOAT data is not allowed 570af69d88dSmrg * until 3.0 or with the GL_OES_vertex_half float extension, which isn't 571af69d88dSmrg * quite as trivial as we'd like because it uses a different enum value 572af69d88dSmrg * for GL_HALF_FLOAT_OES. 573af69d88dSmrg */ 574af69d88dSmrg if (ctx->Version < 30) { 575af69d88dSmrg legalTypesMask &= ~(UNSIGNED_INT_BIT | 576af69d88dSmrg INT_BIT | 577af69d88dSmrg UNSIGNED_INT_2_10_10_10_REV_BIT | 57801e04c3fSmrg INT_2_10_10_10_REV_BIT); 57901e04c3fSmrg 58001e04c3fSmrg if (!_mesa_has_OES_vertex_half_float(ctx)) 58101e04c3fSmrg legalTypesMask &= ~HALF_BIT; 582af69d88dSmrg } 583af69d88dSmrg } 584af69d88dSmrg else { 585af69d88dSmrg legalTypesMask &= ~FIXED_ES_BIT; 586af69d88dSmrg 587af69d88dSmrg if (!ctx->Extensions.ARB_ES2_compatibility) 588af69d88dSmrg legalTypesMask &= ~FIXED_GL_BIT; 589af69d88dSmrg 590af69d88dSmrg if (!ctx->Extensions.ARB_vertex_type_2_10_10_10_rev) 591af69d88dSmrg legalTypesMask &= ~(UNSIGNED_INT_2_10_10_10_REV_BIT | 592af69d88dSmrg INT_2_10_10_10_REV_BIT); 593af69d88dSmrg 594af69d88dSmrg if (!ctx->Extensions.ARB_vertex_type_10f_11f_11f_rev) 595af69d88dSmrg legalTypesMask &= ~UNSIGNED_INT_10F_11F_11F_REV_BIT; 596af69d88dSmrg } 597af69d88dSmrg 598af69d88dSmrg return legalTypesMask; 599af69d88dSmrg} 600af69d88dSmrg 60101e04c3fSmrgstatic GLenum 60201e04c3fSmrgget_array_format(const struct gl_context *ctx, GLint sizeMax, GLint *size) 60301e04c3fSmrg{ 60401e04c3fSmrg GLenum format = GL_RGBA; 60501e04c3fSmrg 60601e04c3fSmrg /* Do size parameter checking. 60701e04c3fSmrg * If sizeMax = BGRA_OR_4 it means that size = GL_BGRA is legal and 60801e04c3fSmrg * must be handled specially. 60901e04c3fSmrg */ 61001e04c3fSmrg if (ctx->Extensions.EXT_vertex_array_bgra && sizeMax == BGRA_OR_4 && 61101e04c3fSmrg *size == GL_BGRA) { 61201e04c3fSmrg format = GL_BGRA; 61301e04c3fSmrg *size = 4; 61401e04c3fSmrg } 61501e04c3fSmrg 61601e04c3fSmrg return format; 61701e04c3fSmrg} 61801e04c3fSmrg 61901e04c3fSmrg 62001e04c3fSmrg/** 62101e04c3fSmrg * \param attrib The index of the attribute array 62201e04c3fSmrg * \param size Components per element (1, 2, 3 or 4) 62301e04c3fSmrg * \param type Datatype of each component (GL_FLOAT, GL_INT, etc) 62401e04c3fSmrg * \param format Either GL_RGBA or GL_BGRA. 62501e04c3fSmrg * \param normalized Whether integer types are converted to floats in [-1, 1] 62601e04c3fSmrg * \param integer Integer-valued values (will not be normalized to [-1, 1]) 62701e04c3fSmrg * \param doubles Double values not reduced to floats 62801e04c3fSmrg * \param relativeOffset Offset of the first element relative to the binding 62901e04c3fSmrg * offset. 63001e04c3fSmrg */ 63101e04c3fSmrgvoid 63201e04c3fSmrg_mesa_update_array_format(struct gl_context *ctx, 63301e04c3fSmrg struct gl_vertex_array_object *vao, 63401e04c3fSmrg gl_vert_attrib attrib, GLint size, GLenum type, 63501e04c3fSmrg GLenum format, GLboolean normalized, 63601e04c3fSmrg GLboolean integer, GLboolean doubles, 63701e04c3fSmrg GLuint relativeOffset) 63801e04c3fSmrg{ 63901e04c3fSmrg struct gl_array_attributes *const array = &vao->VertexAttrib[attrib]; 6407ec681f3Smrg struct gl_vertex_format new_format; 64101e04c3fSmrg 64201e04c3fSmrg assert(!vao->SharedAndImmutable); 64301e04c3fSmrg assert(size <= 4); 64401e04c3fSmrg 6457ec681f3Smrg _mesa_set_vertex_format(&new_format, size, type, format, 646b9abf16eSmaya normalized, integer, doubles); 64701e04c3fSmrg 6487ec681f3Smrg if ((array->RelativeOffset == relativeOffset) && 6497ec681f3Smrg !memcmp(&new_format, &array->Format, sizeof(new_format))) 6507ec681f3Smrg return; 6517ec681f3Smrg 6527ec681f3Smrg array->RelativeOffset = relativeOffset; 6537ec681f3Smrg array->Format = new_format; 6547ec681f3Smrg 655b9abf16eSmaya vao->NewArrays |= vao->Enabled & VERT_BIT(attrib); 6567ec681f3Smrg vao->NonDefaultStateMask |= BITFIELD_BIT(attrib); 65701e04c3fSmrg} 658af69d88dSmrg 659af69d88dSmrg/** 66001e04c3fSmrg * Does error checking of the format in an attrib array. 661af69d88dSmrg * 66201e04c3fSmrg * Called by *Pointer() and VertexAttrib*Format(). 663af69d88dSmrg * 664af69d88dSmrg * \param func Name of calling function used for error reporting 665af69d88dSmrg * \param attrib The index of the attribute array 666af69d88dSmrg * \param legalTypes Bitmask of *_BIT above indicating legal datatypes 667af69d88dSmrg * \param sizeMin Min allowable size value 668af69d88dSmrg * \param sizeMax Max allowable size value (may also be BGRA_OR_4) 669af69d88dSmrg * \param size Components per element (1, 2, 3 or 4) 670af69d88dSmrg * \param type Datatype of each component (GL_FLOAT, GL_INT, etc) 671af69d88dSmrg * \param normalized Whether integer types are converted to floats in [-1, 1] 672af69d88dSmrg * \param integer Integer-valued values (will not be normalized to [-1, 1]) 67301e04c3fSmrg * \param doubles Double values not reduced to floats 674af69d88dSmrg * \param relativeOffset Offset of the first element relative to the binding offset. 67501e04c3fSmrg * \return bool True if validation is successful, False otherwise. 676af69d88dSmrg */ 677af69d88dSmrgstatic bool 67801e04c3fSmrgvalidate_array_format(struct gl_context *ctx, const char *func, 67901e04c3fSmrg struct gl_vertex_array_object *vao, 68001e04c3fSmrg GLuint attrib, GLbitfield legalTypesMask, 68101e04c3fSmrg GLint sizeMin, GLint sizeMax, 6827ec681f3Smrg GLint size, GLenum type, bool normalized, 6837ec681f3Smrg bool integer, bool doubles, 68401e04c3fSmrg GLuint relativeOffset, GLenum format) 68501e04c3fSmrg{ 6863464ebd5Sriastradh GLbitfield typeBit; 6873464ebd5Sriastradh 68801e04c3fSmrg /* at most, one of these bools can be true */ 68901e04c3fSmrg assert((int) normalized + (int) integer + (int) doubles <= 1); 69001e04c3fSmrg 69101e04c3fSmrg if (ctx->Array.LegalTypesMask == 0 || ctx->Array.LegalTypesMaskAPI != ctx->API) { 69201e04c3fSmrg /* Compute the LegalTypesMask only once, unless the context API has 69301e04c3fSmrg * changed, in which case we want to compute it again. We can't do this 69401e04c3fSmrg * in _mesa_init_varrays() below because extensions are not yet enabled 69501e04c3fSmrg * at that point. 696af69d88dSmrg */ 697af69d88dSmrg ctx->Array.LegalTypesMask = get_legal_types_mask(ctx); 69801e04c3fSmrg ctx->Array.LegalTypesMaskAPI = ctx->API; 6993464ebd5Sriastradh } 700af69d88dSmrg 701af69d88dSmrg legalTypesMask &= ctx->Array.LegalTypesMask; 702af69d88dSmrg 703af69d88dSmrg if (_mesa_is_gles(ctx) && sizeMax == BGRA_OR_4) { 704af69d88dSmrg /* BGRA ordering is not supported in ES contexts. 705af69d88dSmrg */ 706af69d88dSmrg sizeMax = 4; 7073464ebd5Sriastradh } 7083464ebd5Sriastradh 7093464ebd5Sriastradh typeBit = type_to_bit(ctx, type); 7103464ebd5Sriastradh if (typeBit == 0x0 || (typeBit & legalTypesMask) == 0x0) { 7113464ebd5Sriastradh _mesa_error(ctx, GL_INVALID_ENUM, "%s(type = %s)", 71201e04c3fSmrg func, _mesa_enum_to_string(type)); 713af69d88dSmrg return false; 7143464ebd5Sriastradh } 7153464ebd5Sriastradh 71601e04c3fSmrg if (format == GL_BGRA) { 717af69d88dSmrg /* Page 298 of the PDF of the OpenGL 4.3 (Core Profile) spec says: 718af69d88dSmrg * 719af69d88dSmrg * "An INVALID_OPERATION error is generated under any of the following 720af69d88dSmrg * conditions: 721af69d88dSmrg * ... 722af69d88dSmrg * • size is BGRA and type is not UNSIGNED_BYTE, INT_2_10_10_10_REV 723af69d88dSmrg * or UNSIGNED_INT_2_10_10_10_REV; 724af69d88dSmrg * ... 725af69d88dSmrg * • size is BGRA and normalized is FALSE;" 726af69d88dSmrg */ 727af69d88dSmrg bool bgra_error = false; 728af69d88dSmrg 729af69d88dSmrg if (ctx->Extensions.ARB_vertex_type_2_10_10_10_rev) { 730af69d88dSmrg if (type != GL_UNSIGNED_INT_2_10_10_10_REV && 731af69d88dSmrg type != GL_INT_2_10_10_10_REV && 732af69d88dSmrg type != GL_UNSIGNED_BYTE) 733af69d88dSmrg bgra_error = true; 734af69d88dSmrg } else if (type != GL_UNSIGNED_BYTE) 735af69d88dSmrg bgra_error = true; 736af69d88dSmrg 737af69d88dSmrg if (bgra_error) { 738af69d88dSmrg _mesa_error(ctx, GL_INVALID_OPERATION, "%s(size=GL_BGRA and type=%s)", 73901e04c3fSmrg func, _mesa_enum_to_string(type)); 740af69d88dSmrg return false; 741af69d88dSmrg } 742af69d88dSmrg 743af69d88dSmrg if (!normalized) { 744af69d88dSmrg _mesa_error(ctx, GL_INVALID_OPERATION, 745af69d88dSmrg "%s(size=GL_BGRA and normalized=GL_FALSE)", func); 746af69d88dSmrg return false; 7473464ebd5Sriastradh } 7483464ebd5Sriastradh } 7493464ebd5Sriastradh else if (size < sizeMin || size > sizeMax || size > 4) { 7503464ebd5Sriastradh _mesa_error(ctx, GL_INVALID_VALUE, "%s(size=%d)", func, size); 751af69d88dSmrg return false; 752af69d88dSmrg } 753af69d88dSmrg 754af69d88dSmrg if (ctx->Extensions.ARB_vertex_type_2_10_10_10_rev && 755af69d88dSmrg (type == GL_UNSIGNED_INT_2_10_10_10_REV || 756af69d88dSmrg type == GL_INT_2_10_10_10_REV) && size != 4) { 757af69d88dSmrg _mesa_error(ctx, GL_INVALID_OPERATION, "%s(size=%d)", func, size); 758af69d88dSmrg return false; 759af69d88dSmrg } 760af69d88dSmrg 761af69d88dSmrg /* The ARB_vertex_attrib_binding_spec says: 762af69d88dSmrg * 763af69d88dSmrg * An INVALID_VALUE error is generated if <relativeoffset> is larger than 764af69d88dSmrg * the value of MAX_VERTEX_ATTRIB_RELATIVE_OFFSET. 765af69d88dSmrg */ 766af69d88dSmrg if (relativeOffset > ctx->Const.MaxVertexAttribRelativeOffset) { 767af69d88dSmrg _mesa_error(ctx, GL_INVALID_VALUE, 768af69d88dSmrg "%s(relativeOffset=%d > " 769af69d88dSmrg "GL_MAX_VERTEX_ATTRIB_RELATIVE_OFFSET)", 770af69d88dSmrg func, relativeOffset); 771af69d88dSmrg return false; 772af69d88dSmrg } 773af69d88dSmrg 774af69d88dSmrg if (ctx->Extensions.ARB_vertex_type_10f_11f_11f_rev && 775af69d88dSmrg type == GL_UNSIGNED_INT_10F_11F_11F_REV && size != 3) { 776af69d88dSmrg _mesa_error(ctx, GL_INVALID_OPERATION, "%s(size=%d)", func, size); 777af69d88dSmrg return false; 7783464ebd5Sriastradh } 7793464ebd5Sriastradh 780af69d88dSmrg return true; 781af69d88dSmrg} 782af69d88dSmrg 783af69d88dSmrg/** 78401e04c3fSmrg * Do error checking for glVertex/Color/TexCoord/...Pointer functions. 785af69d88dSmrg * 786af69d88dSmrg * \param func name of calling function used for error reporting 7877ec681f3Smrg * \param vao the vao to update 7887ec681f3Smrg * \param obj the bound buffer object 789af69d88dSmrg * \param attrib the attribute array index to update 790af69d88dSmrg * \param legalTypes bitmask of *_BIT above indicating legal datatypes 791af69d88dSmrg * \param sizeMin min allowable size value 792af69d88dSmrg * \param sizeMax max allowable size value (may also be BGRA_OR_4) 793af69d88dSmrg * \param size components per element (1, 2, 3 or 4) 794af69d88dSmrg * \param type datatype of each component (GL_FLOAT, GL_INT, etc) 795af69d88dSmrg * \param stride stride between elements, in elements 796af69d88dSmrg * \param normalized are integer types converted to floats in [-1, 1]? 797af69d88dSmrg * \param integer integer-valued values (will not be normalized to [-1,1]) 79801e04c3fSmrg * \param doubles Double values not reduced to floats 799af69d88dSmrg * \param ptr the address (or offset inside VBO) of the array data 800af69d88dSmrg */ 801af69d88dSmrgstatic void 80201e04c3fSmrgvalidate_array(struct gl_context *ctx, const char *func, 8037ec681f3Smrg struct gl_vertex_array_object *vao, 8047ec681f3Smrg struct gl_buffer_object *obj, 80501e04c3fSmrg GLuint attrib, GLbitfield legalTypesMask, 80601e04c3fSmrg GLint sizeMin, GLint sizeMax, 80701e04c3fSmrg GLint size, GLenum type, GLsizei stride, 80801e04c3fSmrg GLboolean normalized, GLboolean integer, GLboolean doubles, 80901e04c3fSmrg const GLvoid *ptr) 810af69d88dSmrg{ 811af69d88dSmrg /* Page 407 (page 423 of the PDF) of the OpenGL 3.0 spec says: 812af69d88dSmrg * 813af69d88dSmrg * "Client vertex arrays - all vertex array attribute pointers must 814af69d88dSmrg * refer to buffer objects (section 2.9.2). The default vertex array 815af69d88dSmrg * object (the name zero) is also deprecated. Calling 816af69d88dSmrg * VertexAttribPointer when no buffer object or no vertex array object 817af69d88dSmrg * is bound will generate an INVALID_OPERATION error..." 818af69d88dSmrg * 819af69d88dSmrg * The check for VBOs is handled below. 820af69d88dSmrg */ 82101e04c3fSmrg if (ctx->API == API_OPENGL_CORE && (vao == ctx->Array.DefaultVAO)) { 822af69d88dSmrg _mesa_error(ctx, GL_INVALID_OPERATION, "%s(no array object bound)", 823af69d88dSmrg func); 824af69d88dSmrg return; 825af69d88dSmrg } 826af69d88dSmrg 8273464ebd5Sriastradh if (stride < 0) { 8283464ebd5Sriastradh _mesa_error( ctx, GL_INVALID_VALUE, "%s(stride=%d)", func, stride ); 8293464ebd5Sriastradh return; 8303464ebd5Sriastradh } 8314a49301eSmrg 83201e04c3fSmrg if (_mesa_is_desktop_gl(ctx) && ctx->Version >= 44 && 83301e04c3fSmrg stride > ctx->Const.MaxVertexAttribStride) { 83401e04c3fSmrg _mesa_error(ctx, GL_INVALID_VALUE, "%s(stride=%d > " 83501e04c3fSmrg "GL_MAX_VERTEX_ATTRIB_STRIDE)", func, stride); 83601e04c3fSmrg return; 83701e04c3fSmrg } 83801e04c3fSmrg 839af69d88dSmrg /* Page 29 (page 44 of the PDF) of the OpenGL 3.3 spec says: 840af69d88dSmrg * 841af69d88dSmrg * "An INVALID_OPERATION error is generated under any of the following 842af69d88dSmrg * conditions: 843af69d88dSmrg * 844af69d88dSmrg * ... 845af69d88dSmrg * 846af69d88dSmrg * * any of the *Pointer commands specifying the location and 847af69d88dSmrg * organization of vertex array data are called while zero is bound 848af69d88dSmrg * to the ARRAY_BUFFER buffer object binding point (see section 849af69d88dSmrg * 2.9.6), and the pointer argument is not NULL." 850af69d88dSmrg */ 85101e04c3fSmrg if (ptr != NULL && vao != ctx->Array.DefaultVAO && 8527ec681f3Smrg !obj) { 8533464ebd5Sriastradh _mesa_error(ctx, GL_INVALID_OPERATION, "%s(non-VBO array)", func); 8544a49301eSmrg return; 8554a49301eSmrg } 85601e04c3fSmrg} 8574a49301eSmrg 85801e04c3fSmrg 85901e04c3fSmrgstatic bool 86001e04c3fSmrgvalidate_array_and_format(struct gl_context *ctx, const char *func, 8617ec681f3Smrg struct gl_vertex_array_object *vao, 8627ec681f3Smrg struct gl_buffer_object *obj, 86301e04c3fSmrg GLuint attrib, GLbitfield legalTypes, 86401e04c3fSmrg GLint sizeMin, GLint sizeMax, 86501e04c3fSmrg GLint size, GLenum type, GLsizei stride, 86601e04c3fSmrg GLboolean normalized, GLboolean integer, 8677ec681f3Smrg GLboolean doubles, GLenum format, const GLvoid *ptr) 86801e04c3fSmrg{ 8697ec681f3Smrg validate_array(ctx, func, vao, obj, attrib, legalTypes, sizeMin, sizeMax, 8707ec681f3Smrg size, type, stride, normalized, integer, doubles, ptr); 87101e04c3fSmrg 87201e04c3fSmrg return validate_array_format(ctx, func, vao, attrib, legalTypes, sizeMin, 87301e04c3fSmrg sizeMax, size, type, normalized, integer, 87401e04c3fSmrg doubles, 0, format); 87501e04c3fSmrg} 87601e04c3fSmrg 87701e04c3fSmrg 87801e04c3fSmrg/** 87901e04c3fSmrg * Update state for glVertex/Color/TexCoord/...Pointer functions. 88001e04c3fSmrg * 8817ec681f3Smrg * \param vao the vao to update 8827ec681f3Smrg * \param obj the bound buffer object 88301e04c3fSmrg * \param attrib the attribute array index to update 88401e04c3fSmrg * \param format Either GL_RGBA or GL_BGRA. 88501e04c3fSmrg * \param sizeMax max allowable size value (may also be BGRA_OR_4) 88601e04c3fSmrg * \param size components per element (1, 2, 3 or 4) 88701e04c3fSmrg * \param type datatype of each component (GL_FLOAT, GL_INT, etc) 88801e04c3fSmrg * \param stride stride between elements, in elements 88901e04c3fSmrg * \param normalized are integer types converted to floats in [-1, 1]? 89001e04c3fSmrg * \param integer integer-valued values (will not be normalized to [-1,1]) 89101e04c3fSmrg * \param doubles Double values not reduced to floats 89201e04c3fSmrg * \param ptr the address (or offset inside VBO) of the array data 89301e04c3fSmrg */ 89401e04c3fSmrgstatic void 89501e04c3fSmrgupdate_array(struct gl_context *ctx, 8967ec681f3Smrg struct gl_vertex_array_object *vao, 8977ec681f3Smrg struct gl_buffer_object *obj, 89801e04c3fSmrg GLuint attrib, GLenum format, 89901e04c3fSmrg GLint sizeMax, 90001e04c3fSmrg GLint size, GLenum type, GLsizei stride, 90101e04c3fSmrg GLboolean normalized, GLboolean integer, GLboolean doubles, 90201e04c3fSmrg const GLvoid *ptr) 90301e04c3fSmrg{ 90401e04c3fSmrg _mesa_update_array_format(ctx, vao, attrib, size, type, format, 90501e04c3fSmrg normalized, integer, doubles, 0); 9063464ebd5Sriastradh 907af69d88dSmrg /* Reset the vertex attrib binding */ 90801e04c3fSmrg _mesa_vertex_attrib_binding(ctx, vao, attrib, attrib); 9094a49301eSmrg 910af69d88dSmrg /* The Stride and Ptr fields are not set by update_array_format() */ 91101e04c3fSmrg struct gl_array_attributes *array = &vao->VertexAttrib[attrib]; 9127ec681f3Smrg if ((array->Stride != stride) || (array->Ptr != ptr)) { 9137ec681f3Smrg array->Stride = stride; 9147ec681f3Smrg array->Ptr = ptr; 9157ec681f3Smrg vao->NewArrays |= vao->Enabled & VERT_BIT(attrib); 9167ec681f3Smrg vao->NonDefaultStateMask |= BITFIELD_BIT(attrib); 9177ec681f3Smrg } 918c1f859d4Smrg 919af69d88dSmrg /* Update the vertex buffer binding */ 920b9abf16eSmaya GLsizei effectiveStride = stride != 0 ? 921b9abf16eSmaya stride : array->Format._ElementSize; 92201e04c3fSmrg _mesa_bind_vertex_buffer(ctx, vao, attrib, 9237ec681f3Smrg obj, (GLintptr) ptr, 9247ec681f3Smrg effectiveStride, false, false); 92501e04c3fSmrg} 92601e04c3fSmrg 9277ec681f3Smrg 9287ec681f3Smrg/* Helper function for all EXT_direct_state_access glVertexArray* functions */ 9297ec681f3Smrgstatic bool 9307ec681f3Smrg_lookup_vao_and_vbo_dsa(struct gl_context *ctx, 9317ec681f3Smrg GLuint vaobj, GLuint buffer, 9327ec681f3Smrg GLintptr offset, 9337ec681f3Smrg struct gl_vertex_array_object** vao, 9347ec681f3Smrg struct gl_buffer_object** vbo, 9357ec681f3Smrg const char* caller) 9367ec681f3Smrg{ 9377ec681f3Smrg *vao = _mesa_lookup_vao_err(ctx, vaobj, true, caller); 9387ec681f3Smrg if (!(*vao)) 9397ec681f3Smrg return false; 9407ec681f3Smrg 9417ec681f3Smrg if (buffer != 0) { 9427ec681f3Smrg *vbo = _mesa_lookup_bufferobj(ctx, buffer); 9437ec681f3Smrg if (!_mesa_handle_bind_buffer_gen(ctx, buffer, vbo, caller)) 9447ec681f3Smrg return false; 9457ec681f3Smrg 9467ec681f3Smrg if (offset < 0) { 9477ec681f3Smrg _mesa_error(ctx, GL_INVALID_VALUE, 9487ec681f3Smrg "%s(negative offset with non-0 buffer)", caller); 9497ec681f3Smrg return false; 9507ec681f3Smrg } 9517ec681f3Smrg } else { 9527ec681f3Smrg *vbo = NULL; 9537ec681f3Smrg } 9547ec681f3Smrg 9557ec681f3Smrg return true; 9567ec681f3Smrg} 9577ec681f3Smrg 9587ec681f3Smrg 95901e04c3fSmrgvoid GLAPIENTRY 96001e04c3fSmrg_mesa_VertexPointer_no_error(GLint size, GLenum type, GLsizei stride, 96101e04c3fSmrg const GLvoid *ptr) 96201e04c3fSmrg{ 96301e04c3fSmrg GET_CURRENT_CONTEXT(ctx); 96401e04c3fSmrg 9657ec681f3Smrg update_array(ctx, ctx->Array.VAO, ctx->Array.ArrayBufferObj, 9667ec681f3Smrg VERT_ATTRIB_POS, GL_RGBA, 4, size, type, stride, 96701e04c3fSmrg GL_FALSE, GL_FALSE, GL_FALSE, ptr); 9687117f1b4Smrg} 9697117f1b4Smrg 9707117f1b4Smrg 9717117f1b4Smrgvoid GLAPIENTRY 9727117f1b4Smrg_mesa_VertexPointer(GLint size, GLenum type, GLsizei stride, const GLvoid *ptr) 9737117f1b4Smrg{ 9747117f1b4Smrg GET_CURRENT_CONTEXT(ctx); 97501e04c3fSmrg 97601e04c3fSmrg GLenum format = GL_RGBA; 977af69d88dSmrg GLbitfield legalTypes = (ctx->API == API_OPENGLES) 978af69d88dSmrg ? (BYTE_BIT | SHORT_BIT | FLOAT_BIT | FIXED_ES_BIT) 979af69d88dSmrg : (SHORT_BIT | INT_BIT | FLOAT_BIT | 980af69d88dSmrg DOUBLE_BIT | HALF_BIT | 981af69d88dSmrg UNSIGNED_INT_2_10_10_10_REV_BIT | 982af69d88dSmrg INT_2_10_10_10_REV_BIT); 9837117f1b4Smrg 9847ec681f3Smrg if (!validate_array_and_format(ctx, "glVertexPointer", 9857ec681f3Smrg ctx->Array.VAO, ctx->Array.ArrayBufferObj, 9867ec681f3Smrg VERT_ATTRIB_POS, legalTypes, 2, 4, size, 9877ec681f3Smrg type, stride, GL_FALSE, GL_FALSE, GL_FALSE, 9887ec681f3Smrg format, ptr)) 98901e04c3fSmrg return; 99001e04c3fSmrg 9917ec681f3Smrg update_array(ctx, ctx->Array.VAO, ctx->Array.ArrayBufferObj, 9927ec681f3Smrg VERT_ATTRIB_POS, format, 4, size, type, stride, 99301e04c3fSmrg GL_FALSE, GL_FALSE, GL_FALSE, ptr); 99401e04c3fSmrg} 99501e04c3fSmrg 99601e04c3fSmrg 9977ec681f3Smrgvoid GLAPIENTRY 9987ec681f3Smrg_mesa_VertexArrayVertexOffsetEXT(GLuint vaobj, GLuint buffer, GLint size, 9997ec681f3Smrg GLenum type, GLsizei stride, GLintptr offset) 10007ec681f3Smrg{ 10017ec681f3Smrg GET_CURRENT_CONTEXT(ctx); 10027ec681f3Smrg 10037ec681f3Smrg GLenum format = GL_RGBA; 10047ec681f3Smrg GLbitfield legalTypes = (ctx->API == API_OPENGLES) 10057ec681f3Smrg ? (BYTE_BIT | SHORT_BIT | FLOAT_BIT | FIXED_ES_BIT) 10067ec681f3Smrg : (SHORT_BIT | INT_BIT | FLOAT_BIT | 10077ec681f3Smrg DOUBLE_BIT | HALF_BIT | 10087ec681f3Smrg UNSIGNED_INT_2_10_10_10_REV_BIT | 10097ec681f3Smrg INT_2_10_10_10_REV_BIT); 10107ec681f3Smrg 10117ec681f3Smrg struct gl_vertex_array_object* vao; 10127ec681f3Smrg struct gl_buffer_object* vbo; 10137ec681f3Smrg 10147ec681f3Smrg if (!_lookup_vao_and_vbo_dsa(ctx, vaobj, buffer, offset, 10157ec681f3Smrg &vao, &vbo, 10167ec681f3Smrg "glVertexArrayVertexOffsetEXT")) 10177ec681f3Smrg return; 10187ec681f3Smrg 10197ec681f3Smrg if (!validate_array_and_format(ctx, "glVertexArrayVertexOffsetEXT", 10207ec681f3Smrg vao, vbo, 10217ec681f3Smrg VERT_ATTRIB_POS, legalTypes, 2, 4, size, 10227ec681f3Smrg type, stride, GL_FALSE, GL_FALSE, GL_FALSE, 10237ec681f3Smrg format, (void*) offset)) 10247ec681f3Smrg return; 10257ec681f3Smrg 10267ec681f3Smrg update_array(ctx, vao, vbo, 10277ec681f3Smrg VERT_ATTRIB_POS, format, 4, size, type, stride, 10287ec681f3Smrg GL_FALSE, GL_FALSE, GL_FALSE, (void*) offset); 10297ec681f3Smrg} 10307ec681f3Smrg 10317ec681f3Smrg 103201e04c3fSmrgvoid GLAPIENTRY 103301e04c3fSmrg_mesa_NormalPointer_no_error(GLenum type, GLsizei stride, const GLvoid *ptr ) 103401e04c3fSmrg{ 103501e04c3fSmrg GET_CURRENT_CONTEXT(ctx); 10367117f1b4Smrg 10377ec681f3Smrg update_array(ctx, ctx->Array.VAO, ctx->Array.ArrayBufferObj, 10387ec681f3Smrg VERT_ATTRIB_NORMAL, GL_RGBA, 3, 3, type, stride, GL_TRUE, 103901e04c3fSmrg GL_FALSE, GL_FALSE, ptr); 10407117f1b4Smrg} 10417117f1b4Smrg 10427117f1b4Smrg 10437117f1b4Smrgvoid GLAPIENTRY 10447117f1b4Smrg_mesa_NormalPointer(GLenum type, GLsizei stride, const GLvoid *ptr ) 10457117f1b4Smrg{ 10467117f1b4Smrg GET_CURRENT_CONTEXT(ctx); 104701e04c3fSmrg 104801e04c3fSmrg GLenum format = GL_RGBA; 1049af69d88dSmrg const GLbitfield legalTypes = (ctx->API == API_OPENGLES) 1050af69d88dSmrg ? (BYTE_BIT | SHORT_BIT | FLOAT_BIT | FIXED_ES_BIT) 1051af69d88dSmrg : (BYTE_BIT | SHORT_BIT | INT_BIT | 1052af69d88dSmrg HALF_BIT | FLOAT_BIT | DOUBLE_BIT | 1053af69d88dSmrg UNSIGNED_INT_2_10_10_10_REV_BIT | 1054af69d88dSmrg INT_2_10_10_10_REV_BIT); 1055af69d88dSmrg 105601e04c3fSmrg if (!validate_array_and_format(ctx, "glNormalPointer", 10577ec681f3Smrg ctx->Array.VAO, ctx->Array.ArrayBufferObj, 105801e04c3fSmrg VERT_ATTRIB_NORMAL, legalTypes, 3, 3, 3, 105901e04c3fSmrg type, stride, GL_TRUE, GL_FALSE, 10607ec681f3Smrg GL_FALSE, format, ptr)) 106101e04c3fSmrg return; 106201e04c3fSmrg 10637ec681f3Smrg update_array(ctx, ctx->Array.VAO, ctx->Array.ArrayBufferObj, 10647ec681f3Smrg VERT_ATTRIB_NORMAL, format, 3, 3, type, stride, GL_TRUE, 106501e04c3fSmrg GL_FALSE, GL_FALSE, ptr); 106601e04c3fSmrg} 106701e04c3fSmrg 106801e04c3fSmrg 10697ec681f3Smrgvoid GLAPIENTRY 10707ec681f3Smrg_mesa_VertexArrayNormalOffsetEXT(GLuint vaobj, GLuint buffer, GLenum type, 10717ec681f3Smrg GLsizei stride, GLintptr offset) 10727ec681f3Smrg{ 10737ec681f3Smrg GET_CURRENT_CONTEXT(ctx); 10747ec681f3Smrg 10757ec681f3Smrg GLenum format = GL_RGBA; 10767ec681f3Smrg const GLbitfield legalTypes = (ctx->API == API_OPENGLES) 10777ec681f3Smrg ? (BYTE_BIT | SHORT_BIT | FLOAT_BIT | FIXED_ES_BIT) 10787ec681f3Smrg : (BYTE_BIT | SHORT_BIT | INT_BIT | 10797ec681f3Smrg HALF_BIT | FLOAT_BIT | DOUBLE_BIT | 10807ec681f3Smrg UNSIGNED_INT_2_10_10_10_REV_BIT | 10817ec681f3Smrg INT_2_10_10_10_REV_BIT); 10827ec681f3Smrg 10837ec681f3Smrg struct gl_vertex_array_object* vao; 10847ec681f3Smrg struct gl_buffer_object* vbo; 10857ec681f3Smrg 10867ec681f3Smrg if (!_lookup_vao_and_vbo_dsa(ctx, vaobj, buffer, offset, 10877ec681f3Smrg &vao, &vbo, 10887ec681f3Smrg "glNormalPointer")) 10897ec681f3Smrg return; 10907ec681f3Smrg 10917ec681f3Smrg if (!validate_array_and_format(ctx, "glNormalPointer", 10927ec681f3Smrg vao, vbo, 10937ec681f3Smrg VERT_ATTRIB_NORMAL, legalTypes, 3, 3, 3, 10947ec681f3Smrg type, stride, GL_TRUE, GL_FALSE, 10957ec681f3Smrg GL_FALSE, format, (void*) offset)) 10967ec681f3Smrg return; 10977ec681f3Smrg 10987ec681f3Smrg update_array(ctx, vao, vbo, 10997ec681f3Smrg VERT_ATTRIB_NORMAL, format, 3, 3, type, stride, GL_TRUE, 11007ec681f3Smrg GL_FALSE, GL_FALSE, (void*) offset); 11017ec681f3Smrg} 11027ec681f3Smrg 11037ec681f3Smrg 110401e04c3fSmrgvoid GLAPIENTRY 110501e04c3fSmrg_mesa_ColorPointer_no_error(GLint size, GLenum type, GLsizei stride, 110601e04c3fSmrg const GLvoid *ptr) 110701e04c3fSmrg{ 110801e04c3fSmrg GET_CURRENT_CONTEXT(ctx); 11097117f1b4Smrg 111001e04c3fSmrg GLenum format = get_array_format(ctx, BGRA_OR_4, &size); 11117ec681f3Smrg update_array(ctx, ctx->Array.VAO, ctx->Array.ArrayBufferObj, 11127ec681f3Smrg VERT_ATTRIB_COLOR0, format, BGRA_OR_4, size, 111301e04c3fSmrg type, stride, GL_TRUE, GL_FALSE, GL_FALSE, ptr); 11147117f1b4Smrg} 11157117f1b4Smrg 11167117f1b4Smrg 11177117f1b4Smrgvoid GLAPIENTRY 11187117f1b4Smrg_mesa_ColorPointer(GLint size, GLenum type, GLsizei stride, const GLvoid *ptr) 11197117f1b4Smrg{ 11207117f1b4Smrg GET_CURRENT_CONTEXT(ctx); 112101e04c3fSmrg const GLint sizeMin = (ctx->API == API_OPENGLES) ? 4 : 3; 112201e04c3fSmrg 112301e04c3fSmrg GLenum format = get_array_format(ctx, BGRA_OR_4, &size); 1124af69d88dSmrg const GLbitfield legalTypes = (ctx->API == API_OPENGLES) 1125af69d88dSmrg ? (UNSIGNED_BYTE_BIT | HALF_BIT | FLOAT_BIT | FIXED_ES_BIT) 1126af69d88dSmrg : (BYTE_BIT | UNSIGNED_BYTE_BIT | 1127af69d88dSmrg SHORT_BIT | UNSIGNED_SHORT_BIT | 1128af69d88dSmrg INT_BIT | UNSIGNED_INT_BIT | 1129af69d88dSmrg HALF_BIT | FLOAT_BIT | DOUBLE_BIT | 1130af69d88dSmrg UNSIGNED_INT_2_10_10_10_REV_BIT | 1131af69d88dSmrg INT_2_10_10_10_REV_BIT); 1132af69d88dSmrg 113301e04c3fSmrg if (!validate_array_and_format(ctx, "glColorPointer", 11347ec681f3Smrg ctx->Array.VAO, ctx->Array.ArrayBufferObj, 113501e04c3fSmrg VERT_ATTRIB_COLOR0, legalTypes, sizeMin, 113601e04c3fSmrg BGRA_OR_4, size, type, stride, GL_TRUE, 11377ec681f3Smrg GL_FALSE, GL_FALSE, format, ptr)) 113801e04c3fSmrg return; 113901e04c3fSmrg 11407ec681f3Smrg update_array(ctx, ctx->Array.VAO, ctx->Array.ArrayBufferObj, 11417ec681f3Smrg VERT_ATTRIB_COLOR0, format, BGRA_OR_4, size, 114201e04c3fSmrg type, stride, GL_TRUE, GL_FALSE, GL_FALSE, ptr); 114301e04c3fSmrg} 114401e04c3fSmrg 114501e04c3fSmrg 11467ec681f3Smrgvoid GLAPIENTRY 11477ec681f3Smrg_mesa_VertexArrayColorOffsetEXT(GLuint vaobj, GLuint buffer, GLint size, 11487ec681f3Smrg GLenum type, GLsizei stride, GLintptr offset) 11497ec681f3Smrg{ 11507ec681f3Smrg GET_CURRENT_CONTEXT(ctx); 11517ec681f3Smrg const GLint sizeMin = (ctx->API == API_OPENGLES) ? 4 : 3; 11527ec681f3Smrg 11537ec681f3Smrg GLenum format = get_array_format(ctx, BGRA_OR_4, &size); 11547ec681f3Smrg const GLbitfield legalTypes = (ctx->API == API_OPENGLES) 11557ec681f3Smrg ? (UNSIGNED_BYTE_BIT | HALF_BIT | FLOAT_BIT | FIXED_ES_BIT) 11567ec681f3Smrg : (BYTE_BIT | UNSIGNED_BYTE_BIT | 11577ec681f3Smrg SHORT_BIT | UNSIGNED_SHORT_BIT | 11587ec681f3Smrg INT_BIT | UNSIGNED_INT_BIT | 11597ec681f3Smrg HALF_BIT | FLOAT_BIT | DOUBLE_BIT | 11607ec681f3Smrg UNSIGNED_INT_2_10_10_10_REV_BIT | 11617ec681f3Smrg INT_2_10_10_10_REV_BIT); 11627ec681f3Smrg 11637ec681f3Smrg struct gl_vertex_array_object* vao; 11647ec681f3Smrg struct gl_buffer_object* vbo; 11657ec681f3Smrg 11667ec681f3Smrg if (!_lookup_vao_and_vbo_dsa(ctx, vaobj, buffer, offset, 11677ec681f3Smrg &vao, &vbo, 11687ec681f3Smrg "glVertexArrayColorOffsetEXT")) 11697ec681f3Smrg return; 11707ec681f3Smrg 11717ec681f3Smrg if (!validate_array_and_format(ctx, "glVertexArrayColorOffsetEXT", 11727ec681f3Smrg vao, vbo, 11737ec681f3Smrg VERT_ATTRIB_COLOR0, legalTypes, sizeMin, 11747ec681f3Smrg BGRA_OR_4, size, type, stride, GL_TRUE, 11757ec681f3Smrg GL_FALSE, GL_FALSE, format, (void*) offset)) 11767ec681f3Smrg return; 11777ec681f3Smrg 11787ec681f3Smrg update_array(ctx, vao, vbo, 11797ec681f3Smrg VERT_ATTRIB_COLOR0, format, BGRA_OR_4, size, 11807ec681f3Smrg type, stride, GL_TRUE, GL_FALSE, GL_FALSE, (void*) offset); 11817ec681f3Smrg} 11827ec681f3Smrg 11837ec681f3Smrg 118401e04c3fSmrgvoid GLAPIENTRY 118501e04c3fSmrg_mesa_FogCoordPointer_no_error(GLenum type, GLsizei stride, const GLvoid *ptr) 118601e04c3fSmrg{ 118701e04c3fSmrg GET_CURRENT_CONTEXT(ctx); 1188af69d88dSmrg 11897ec681f3Smrg update_array(ctx, ctx->Array.VAO, ctx->Array.ArrayBufferObj, 11907ec681f3Smrg VERT_ATTRIB_FOG, GL_RGBA, 1, 1, type, stride, GL_FALSE, 119101e04c3fSmrg GL_FALSE, GL_FALSE, ptr); 11927117f1b4Smrg} 11937117f1b4Smrg 11947117f1b4Smrg 11957117f1b4Smrgvoid GLAPIENTRY 1196af69d88dSmrg_mesa_FogCoordPointer(GLenum type, GLsizei stride, const GLvoid *ptr) 11977117f1b4Smrg{ 11987117f1b4Smrg GET_CURRENT_CONTEXT(ctx); 11997117f1b4Smrg 120001e04c3fSmrg GLenum format = GL_RGBA; 120101e04c3fSmrg const GLbitfield legalTypes = (HALF_BIT | FLOAT_BIT | DOUBLE_BIT); 120201e04c3fSmrg 120301e04c3fSmrg if (!validate_array_and_format(ctx, "glFogCoordPointer", 12047ec681f3Smrg ctx->Array.VAO, ctx->Array.ArrayBufferObj, 120501e04c3fSmrg VERT_ATTRIB_FOG, legalTypes, 1, 1, 1, 120601e04c3fSmrg type, stride, GL_FALSE, GL_FALSE, 12077ec681f3Smrg GL_FALSE, format, ptr)) 120801e04c3fSmrg return; 120901e04c3fSmrg 12107ec681f3Smrg update_array(ctx, ctx->Array.VAO, ctx->Array.ArrayBufferObj, 12117ec681f3Smrg VERT_ATTRIB_FOG, format, 1, 1, type, stride, GL_FALSE, 121201e04c3fSmrg GL_FALSE, GL_FALSE, ptr); 121301e04c3fSmrg} 121401e04c3fSmrg 121501e04c3fSmrg 12167ec681f3Smrgvoid GLAPIENTRY 12177ec681f3Smrg_mesa_VertexArrayFogCoordOffsetEXT(GLuint vaobj, GLuint buffer, GLenum type, 12187ec681f3Smrg GLsizei stride, GLintptr offset) 12197ec681f3Smrg{ 12207ec681f3Smrg GET_CURRENT_CONTEXT(ctx); 12217ec681f3Smrg 12227ec681f3Smrg GLenum format = GL_RGBA; 12237ec681f3Smrg const GLbitfield legalTypes = (HALF_BIT | FLOAT_BIT | DOUBLE_BIT); 12247ec681f3Smrg 12257ec681f3Smrg struct gl_vertex_array_object* vao; 12267ec681f3Smrg struct gl_buffer_object* vbo; 12277ec681f3Smrg 12287ec681f3Smrg if (!_lookup_vao_and_vbo_dsa(ctx, vaobj, buffer, offset, 12297ec681f3Smrg &vao, &vbo, 12307ec681f3Smrg "glVertexArrayFogCoordOffsetEXT")) 12317ec681f3Smrg return; 12327ec681f3Smrg 12337ec681f3Smrg if (!validate_array_and_format(ctx, "glVertexArrayFogCoordOffsetEXT", 12347ec681f3Smrg vao, vbo, 12357ec681f3Smrg VERT_ATTRIB_FOG, legalTypes, 1, 1, 1, 12367ec681f3Smrg type, stride, GL_FALSE, GL_FALSE, 12377ec681f3Smrg GL_FALSE, format, (void*) offset)) 12387ec681f3Smrg return; 12397ec681f3Smrg 12407ec681f3Smrg update_array(ctx, vao, vbo, 12417ec681f3Smrg VERT_ATTRIB_FOG, format, 1, 1, type, stride, GL_FALSE, 12427ec681f3Smrg GL_FALSE, GL_FALSE, (void*) offset); 12437ec681f3Smrg} 12447ec681f3Smrg 12457ec681f3Smrg 124601e04c3fSmrgvoid GLAPIENTRY 124701e04c3fSmrg_mesa_IndexPointer_no_error(GLenum type, GLsizei stride, const GLvoid *ptr) 124801e04c3fSmrg{ 124901e04c3fSmrg GET_CURRENT_CONTEXT(ctx); 1250af69d88dSmrg 12517ec681f3Smrg update_array(ctx, ctx->Array.VAO, ctx->Array.ArrayBufferObj, 12527ec681f3Smrg VERT_ATTRIB_COLOR_INDEX, GL_RGBA, 1, 1, type, stride, 125301e04c3fSmrg GL_FALSE, GL_FALSE, GL_FALSE, ptr); 12547117f1b4Smrg} 12557117f1b4Smrg 12567117f1b4Smrg 12577117f1b4Smrgvoid GLAPIENTRY 12587117f1b4Smrg_mesa_IndexPointer(GLenum type, GLsizei stride, const GLvoid *ptr) 12597117f1b4Smrg{ 12607117f1b4Smrg GET_CURRENT_CONTEXT(ctx); 12617117f1b4Smrg 126201e04c3fSmrg GLenum format = GL_RGBA; 126301e04c3fSmrg const GLbitfield legalTypes = (UNSIGNED_BYTE_BIT | SHORT_BIT | INT_BIT | 126401e04c3fSmrg FLOAT_BIT | DOUBLE_BIT); 126501e04c3fSmrg 126601e04c3fSmrg if (!validate_array_and_format(ctx, "glIndexPointer", 12677ec681f3Smrg ctx->Array.VAO, ctx->Array.ArrayBufferObj, 126801e04c3fSmrg VERT_ATTRIB_COLOR_INDEX, 126901e04c3fSmrg legalTypes, 1, 1, 1, type, stride, 12707ec681f3Smrg GL_FALSE, GL_FALSE, GL_FALSE, format, ptr)) 127101e04c3fSmrg return; 127201e04c3fSmrg 12737ec681f3Smrg update_array(ctx, ctx->Array.VAO, ctx->Array.ArrayBufferObj, 12747ec681f3Smrg VERT_ATTRIB_COLOR_INDEX, format, 1, 1, type, stride, 127501e04c3fSmrg GL_FALSE, GL_FALSE, GL_FALSE, ptr); 127601e04c3fSmrg} 127701e04c3fSmrg 127801e04c3fSmrg 12797ec681f3Smrgvoid GLAPIENTRY 12807ec681f3Smrg_mesa_VertexArrayIndexOffsetEXT(GLuint vaobj, GLuint buffer, GLenum type, 12817ec681f3Smrg GLsizei stride, GLintptr offset) 12827ec681f3Smrg{ 12837ec681f3Smrg GET_CURRENT_CONTEXT(ctx); 12847ec681f3Smrg 12857ec681f3Smrg GLenum format = GL_RGBA; 12867ec681f3Smrg const GLbitfield legalTypes = (UNSIGNED_BYTE_BIT | SHORT_BIT | INT_BIT | 12877ec681f3Smrg FLOAT_BIT | DOUBLE_BIT); 12887ec681f3Smrg 12897ec681f3Smrg struct gl_vertex_array_object* vao; 12907ec681f3Smrg struct gl_buffer_object* vbo; 12917ec681f3Smrg 12927ec681f3Smrg if (!_lookup_vao_and_vbo_dsa(ctx, vaobj, buffer, offset, 12937ec681f3Smrg &vao, &vbo, 12947ec681f3Smrg "glVertexArrayIndexOffsetEXT")) 12957ec681f3Smrg return; 12967ec681f3Smrg 12977ec681f3Smrg if (!validate_array_and_format(ctx, "glVertexArrayIndexOffsetEXT", 12987ec681f3Smrg vao, vbo, 12997ec681f3Smrg VERT_ATTRIB_COLOR_INDEX, 13007ec681f3Smrg legalTypes, 1, 1, 1, type, stride, 13017ec681f3Smrg GL_FALSE, GL_FALSE, GL_FALSE, format, (void*) offset)) 13027ec681f3Smrg return; 13037ec681f3Smrg 13047ec681f3Smrg update_array(ctx, vao, vbo, 13057ec681f3Smrg VERT_ATTRIB_COLOR_INDEX, format, 1, 1, type, stride, 13067ec681f3Smrg GL_FALSE, GL_FALSE, GL_FALSE, (void*) offset); 13077ec681f3Smrg} 13087ec681f3Smrg 13097ec681f3Smrg 131001e04c3fSmrgvoid GLAPIENTRY 131101e04c3fSmrg_mesa_SecondaryColorPointer_no_error(GLint size, GLenum type, 131201e04c3fSmrg GLsizei stride, const GLvoid *ptr) 131301e04c3fSmrg{ 131401e04c3fSmrg GET_CURRENT_CONTEXT(ctx); 1315af69d88dSmrg 131601e04c3fSmrg GLenum format = get_array_format(ctx, BGRA_OR_4, &size); 13177ec681f3Smrg update_array(ctx, ctx->Array.VAO, ctx->Array.ArrayBufferObj, 13187ec681f3Smrg VERT_ATTRIB_COLOR1, format, BGRA_OR_4, size, type, 131901e04c3fSmrg stride, GL_TRUE, GL_FALSE, GL_FALSE, ptr); 13207117f1b4Smrg} 13217117f1b4Smrg 13227117f1b4Smrg 13237117f1b4Smrgvoid GLAPIENTRY 1324af69d88dSmrg_mesa_SecondaryColorPointer(GLint size, GLenum type, 13257117f1b4Smrg GLsizei stride, const GLvoid *ptr) 13267117f1b4Smrg{ 132701e04c3fSmrg GET_CURRENT_CONTEXT(ctx); 132801e04c3fSmrg 132901e04c3fSmrg GLenum format = get_array_format(ctx, BGRA_OR_4, &size); 13303464ebd5Sriastradh const GLbitfield legalTypes = (BYTE_BIT | UNSIGNED_BYTE_BIT | 13313464ebd5Sriastradh SHORT_BIT | UNSIGNED_SHORT_BIT | 13323464ebd5Sriastradh INT_BIT | UNSIGNED_INT_BIT | 1333af69d88dSmrg HALF_BIT | FLOAT_BIT | DOUBLE_BIT | 1334af69d88dSmrg UNSIGNED_INT_2_10_10_10_REV_BIT | 1335af69d88dSmrg INT_2_10_10_10_REV_BIT); 13367117f1b4Smrg 133701e04c3fSmrg if (!validate_array_and_format(ctx, "glSecondaryColorPointer", 13387ec681f3Smrg ctx->Array.VAO, ctx->Array.ArrayBufferObj, 133901e04c3fSmrg VERT_ATTRIB_COLOR1, legalTypes, 3, 134001e04c3fSmrg BGRA_OR_4, size, type, stride, 13417ec681f3Smrg GL_TRUE, GL_FALSE, GL_FALSE, format, ptr)) 134201e04c3fSmrg return; 134301e04c3fSmrg 13447ec681f3Smrg update_array(ctx, ctx->Array.VAO, ctx->Array.ArrayBufferObj, 13457ec681f3Smrg VERT_ATTRIB_COLOR1, format, BGRA_OR_4, size, type, 134601e04c3fSmrg stride, GL_TRUE, GL_FALSE, GL_FALSE, ptr); 134701e04c3fSmrg} 134801e04c3fSmrg 134901e04c3fSmrg 13507ec681f3Smrgvoid GLAPIENTRY 13517ec681f3Smrg_mesa_VertexArraySecondaryColorOffsetEXT(GLuint vaobj, GLuint buffer, GLint size, 13527ec681f3Smrg GLenum type, GLsizei stride, GLintptr offset) 13537ec681f3Smrg{ 13547ec681f3Smrg GET_CURRENT_CONTEXT(ctx); 13557ec681f3Smrg 13567ec681f3Smrg GLenum format = get_array_format(ctx, BGRA_OR_4, &size); 13577ec681f3Smrg const GLbitfield legalTypes = (BYTE_BIT | UNSIGNED_BYTE_BIT | 13587ec681f3Smrg SHORT_BIT | UNSIGNED_SHORT_BIT | 13597ec681f3Smrg INT_BIT | UNSIGNED_INT_BIT | 13607ec681f3Smrg HALF_BIT | FLOAT_BIT | DOUBLE_BIT | 13617ec681f3Smrg UNSIGNED_INT_2_10_10_10_REV_BIT | 13627ec681f3Smrg INT_2_10_10_10_REV_BIT); 13637ec681f3Smrg 13647ec681f3Smrg struct gl_vertex_array_object* vao; 13657ec681f3Smrg struct gl_buffer_object* vbo; 13667ec681f3Smrg 13677ec681f3Smrg if (!_lookup_vao_and_vbo_dsa(ctx, vaobj, buffer, offset, 13687ec681f3Smrg &vao, &vbo, 13697ec681f3Smrg "glVertexArraySecondaryColorOffsetEXT")) 13707ec681f3Smrg return; 13717ec681f3Smrg 13727ec681f3Smrg if (!validate_array_and_format(ctx, "glVertexArraySecondaryColorOffsetEXT", 13737ec681f3Smrg vao, vbo, 13747ec681f3Smrg VERT_ATTRIB_COLOR1, legalTypes, 3, 13757ec681f3Smrg BGRA_OR_4, size, type, stride, 13767ec681f3Smrg GL_TRUE, GL_FALSE, GL_FALSE, format, (void*) offset)) 13777ec681f3Smrg return; 13787ec681f3Smrg 13797ec681f3Smrg update_array(ctx, vao, vbo, 13807ec681f3Smrg VERT_ATTRIB_COLOR1, format, BGRA_OR_4, size, type, 13817ec681f3Smrg stride, GL_TRUE, GL_FALSE, GL_FALSE, (void*) offset); 13827ec681f3Smrg} 13837ec681f3Smrg 13847ec681f3Smrg 138501e04c3fSmrgvoid GLAPIENTRY 138601e04c3fSmrg_mesa_TexCoordPointer_no_error(GLint size, GLenum type, GLsizei stride, 138701e04c3fSmrg const GLvoid *ptr) 138801e04c3fSmrg{ 138901e04c3fSmrg GET_CURRENT_CONTEXT(ctx); 139001e04c3fSmrg const GLuint unit = ctx->Array.ActiveTexture; 1391af69d88dSmrg 13927ec681f3Smrg update_array(ctx, ctx->Array.VAO, ctx->Array.ArrayBufferObj, 13937ec681f3Smrg VERT_ATTRIB_TEX(unit), GL_RGBA, 4, size, type, 139401e04c3fSmrg stride, GL_FALSE, GL_FALSE, GL_FALSE, ptr); 13957117f1b4Smrg} 13967117f1b4Smrg 13977117f1b4Smrg 13987117f1b4Smrgvoid GLAPIENTRY 13997117f1b4Smrg_mesa_TexCoordPointer(GLint size, GLenum type, GLsizei stride, 14007117f1b4Smrg const GLvoid *ptr) 14017117f1b4Smrg{ 14027117f1b4Smrg GET_CURRENT_CONTEXT(ctx); 140301e04c3fSmrg const GLint sizeMin = (ctx->API == API_OPENGLES) ? 2 : 1; 140401e04c3fSmrg const GLuint unit = ctx->Array.ActiveTexture; 140501e04c3fSmrg 140601e04c3fSmrg GLenum format = GL_RGBA; 140701e04c3fSmrg const GLbitfield legalTypes = (ctx->API == API_OPENGLES) 1408af69d88dSmrg ? (BYTE_BIT | SHORT_BIT | FLOAT_BIT | FIXED_ES_BIT) 1409af69d88dSmrg : (SHORT_BIT | INT_BIT | 1410af69d88dSmrg HALF_BIT | FLOAT_BIT | DOUBLE_BIT | 1411af69d88dSmrg UNSIGNED_INT_2_10_10_10_REV_BIT | 1412af69d88dSmrg INT_2_10_10_10_REV_BIT); 14137117f1b4Smrg 141401e04c3fSmrg if (!validate_array_and_format(ctx, "glTexCoordPointer", 14157ec681f3Smrg ctx->Array.VAO, ctx->Array.ArrayBufferObj, 141601e04c3fSmrg VERT_ATTRIB_TEX(unit), legalTypes, 141701e04c3fSmrg sizeMin, 4, size, type, stride, 14187ec681f3Smrg GL_FALSE, GL_FALSE, GL_FALSE, format, ptr)) 141901e04c3fSmrg return; 142001e04c3fSmrg 14217ec681f3Smrg update_array(ctx, ctx->Array.VAO, ctx->Array.ArrayBufferObj, 14227ec681f3Smrg VERT_ATTRIB_TEX(unit), format, 4, size, type, 142301e04c3fSmrg stride, GL_FALSE, GL_FALSE, GL_FALSE, ptr); 142401e04c3fSmrg} 142501e04c3fSmrg 142601e04c3fSmrg 14277ec681f3Smrgvoid GLAPIENTRY 14287ec681f3Smrg_mesa_VertexArrayTexCoordOffsetEXT(GLuint vaobj, GLuint buffer, GLint size, 14297ec681f3Smrg GLenum type, GLsizei stride, GLintptr offset) 14307ec681f3Smrg{ 14317ec681f3Smrg GET_CURRENT_CONTEXT(ctx); 14327ec681f3Smrg const GLint sizeMin = (ctx->API == API_OPENGLES) ? 2 : 1; 14337ec681f3Smrg const GLuint unit = ctx->Array.ActiveTexture; 14347ec681f3Smrg 14357ec681f3Smrg GLenum format = GL_RGBA; 14367ec681f3Smrg const GLbitfield legalTypes = (ctx->API == API_OPENGLES) 14377ec681f3Smrg ? (BYTE_BIT | SHORT_BIT | FLOAT_BIT | FIXED_ES_BIT) 14387ec681f3Smrg : (SHORT_BIT | INT_BIT | 14397ec681f3Smrg HALF_BIT | FLOAT_BIT | DOUBLE_BIT | 14407ec681f3Smrg UNSIGNED_INT_2_10_10_10_REV_BIT | 14417ec681f3Smrg INT_2_10_10_10_REV_BIT); 14427ec681f3Smrg 14437ec681f3Smrg struct gl_vertex_array_object* vao; 14447ec681f3Smrg struct gl_buffer_object* vbo; 14457ec681f3Smrg 14467ec681f3Smrg if (!_lookup_vao_and_vbo_dsa(ctx, vaobj, buffer, offset, 14477ec681f3Smrg &vao, &vbo, 14487ec681f3Smrg "glVertexArrayTexCoordOffsetEXT")) 14497ec681f3Smrg return; 14507ec681f3Smrg 14517ec681f3Smrg if (!validate_array_and_format(ctx, "glVertexArrayTexCoordOffsetEXT", 14527ec681f3Smrg vao, vbo, 14537ec681f3Smrg VERT_ATTRIB_TEX(unit), legalTypes, 14547ec681f3Smrg sizeMin, 4, size, type, stride, 14557ec681f3Smrg GL_FALSE, GL_FALSE, GL_FALSE, format, (void*) offset)) 14567ec681f3Smrg return; 14577ec681f3Smrg 14587ec681f3Smrg update_array(ctx, vao, vbo, 14597ec681f3Smrg VERT_ATTRIB_TEX(unit), format, 4, size, type, 14607ec681f3Smrg stride, GL_FALSE, GL_FALSE, GL_FALSE, (void*) offset); 14617ec681f3Smrg} 14627ec681f3Smrg 14637ec681f3Smrg 14647ec681f3Smrgvoid GLAPIENTRY 14657ec681f3Smrg_mesa_VertexArrayMultiTexCoordOffsetEXT(GLuint vaobj, GLuint buffer, GLenum texunit, 14667ec681f3Smrg GLint size, GLenum type, GLsizei stride, 14677ec681f3Smrg GLintptr offset) 14687ec681f3Smrg{ 14697ec681f3Smrg GET_CURRENT_CONTEXT(ctx); 14707ec681f3Smrg const GLint sizeMin = (ctx->API == API_OPENGLES) ? 2 : 1; 14717ec681f3Smrg const GLuint unit = texunit - GL_TEXTURE0; 14727ec681f3Smrg 14737ec681f3Smrg GLenum format = GL_RGBA; 14747ec681f3Smrg const GLbitfield legalTypes = (ctx->API == API_OPENGLES) 14757ec681f3Smrg ? (BYTE_BIT | SHORT_BIT | FLOAT_BIT | FIXED_ES_BIT) 14767ec681f3Smrg : (SHORT_BIT | INT_BIT | 14777ec681f3Smrg HALF_BIT | FLOAT_BIT | DOUBLE_BIT | 14787ec681f3Smrg UNSIGNED_INT_2_10_10_10_REV_BIT | 14797ec681f3Smrg INT_2_10_10_10_REV_BIT); 14807ec681f3Smrg 14817ec681f3Smrg struct gl_vertex_array_object* vao; 14827ec681f3Smrg struct gl_buffer_object* vbo; 14837ec681f3Smrg 14847ec681f3Smrg if (!_lookup_vao_and_vbo_dsa(ctx, vaobj, buffer, offset, 14857ec681f3Smrg &vao, &vbo, 14867ec681f3Smrg "glVertexArrayMultiTexCoordOffsetEXT")) 14877ec681f3Smrg return; 14887ec681f3Smrg 14897ec681f3Smrg if (unit >= ctx->Const.MaxCombinedTextureImageUnits) { 14907ec681f3Smrg _mesa_error(ctx, GL_INVALID_OPERATION, "glVertexArrayMultiTexCoordOffsetEXT(texunit=%d)", 14917ec681f3Smrg texunit); 14927ec681f3Smrg return; 14937ec681f3Smrg } 14947ec681f3Smrg 14957ec681f3Smrg if (!validate_array_and_format(ctx, "glVertexArrayMultiTexCoordOffsetEXT", 14967ec681f3Smrg vao, vbo, 14977ec681f3Smrg VERT_ATTRIB_TEX(unit), legalTypes, 14987ec681f3Smrg sizeMin, 4, size, type, stride, 14997ec681f3Smrg GL_FALSE, GL_FALSE, GL_FALSE, format, (void*) offset)) 15007ec681f3Smrg return; 15017ec681f3Smrg 15027ec681f3Smrg update_array(ctx, vao, vbo, 15037ec681f3Smrg VERT_ATTRIB_TEX(unit), format, 4, size, type, 15047ec681f3Smrg stride, GL_FALSE, GL_FALSE, GL_FALSE, (void*) offset); 15057ec681f3Smrg} 15067ec681f3Smrg 15077ec681f3Smrg 150801e04c3fSmrgvoid GLAPIENTRY 150901e04c3fSmrg_mesa_EdgeFlagPointer_no_error(GLsizei stride, const GLvoid *ptr) 151001e04c3fSmrg{ 151101e04c3fSmrg /* this is the same type that glEdgeFlag uses */ 151201e04c3fSmrg const GLboolean integer = GL_FALSE; 151301e04c3fSmrg GET_CURRENT_CONTEXT(ctx); 1514cdc920a0Smrg 15157ec681f3Smrg update_array(ctx, ctx->Array.VAO, ctx->Array.ArrayBufferObj, 15167ec681f3Smrg VERT_ATTRIB_EDGEFLAG, GL_RGBA, 1, 1, GL_UNSIGNED_BYTE, 151701e04c3fSmrg stride, GL_FALSE, integer, GL_FALSE, ptr); 15187117f1b4Smrg} 15197117f1b4Smrg 15207117f1b4Smrg 15217117f1b4Smrgvoid GLAPIENTRY 15227117f1b4Smrg_mesa_EdgeFlagPointer(GLsizei stride, const GLvoid *ptr) 15237117f1b4Smrg{ 1524af69d88dSmrg /* this is the same type that glEdgeFlag uses */ 1525af69d88dSmrg const GLboolean integer = GL_FALSE; 15267117f1b4Smrg GET_CURRENT_CONTEXT(ctx); 15277117f1b4Smrg 152801e04c3fSmrg GLenum format = GL_RGBA; 152901e04c3fSmrg const GLbitfield legalTypes = UNSIGNED_BYTE_BIT; 153001e04c3fSmrg 153101e04c3fSmrg if (!validate_array_and_format(ctx, "glEdgeFlagPointer", 15327ec681f3Smrg ctx->Array.VAO, ctx->Array.ArrayBufferObj, 153301e04c3fSmrg VERT_ATTRIB_EDGEFLAG, legalTypes, 153401e04c3fSmrg 1, 1, 1, GL_UNSIGNED_BYTE, stride, 15357ec681f3Smrg GL_FALSE, integer, GL_FALSE, format, ptr)) 153601e04c3fSmrg return; 1537af69d88dSmrg 15387ec681f3Smrg update_array(ctx, ctx->Array.VAO, ctx->Array.ArrayBufferObj, 15397ec681f3Smrg VERT_ATTRIB_EDGEFLAG, format, 1, 1, GL_UNSIGNED_BYTE, 154001e04c3fSmrg stride, GL_FALSE, integer, GL_FALSE, ptr); 15417117f1b4Smrg} 15427117f1b4Smrg 15437117f1b4Smrg 15447ec681f3Smrgvoid GLAPIENTRY 15457ec681f3Smrg_mesa_VertexArrayEdgeFlagOffsetEXT(GLuint vaobj, GLuint buffer, GLsizei stride, 15467ec681f3Smrg GLintptr offset) 15477ec681f3Smrg{ 15487ec681f3Smrg /* this is the same type that glEdgeFlag uses */ 15497ec681f3Smrg const GLboolean integer = GL_FALSE; 15507ec681f3Smrg GET_CURRENT_CONTEXT(ctx); 15517ec681f3Smrg 15527ec681f3Smrg GLenum format = GL_RGBA; 15537ec681f3Smrg const GLbitfield legalTypes = UNSIGNED_BYTE_BIT; 15547ec681f3Smrg 15557ec681f3Smrg struct gl_vertex_array_object* vao; 15567ec681f3Smrg struct gl_buffer_object* vbo; 15577ec681f3Smrg 15587ec681f3Smrg if (!_lookup_vao_and_vbo_dsa(ctx, vaobj, buffer, offset, 15597ec681f3Smrg &vao, &vbo, 15607ec681f3Smrg "glVertexArrayEdgeFlagOffsetEXT")) 15617ec681f3Smrg return; 15627ec681f3Smrg 15637ec681f3Smrg if (!validate_array_and_format(ctx, "glVertexArrayEdgeFlagOffsetEXT", 15647ec681f3Smrg vao, vbo, 15657ec681f3Smrg VERT_ATTRIB_EDGEFLAG, legalTypes, 15667ec681f3Smrg 1, 1, 1, GL_UNSIGNED_BYTE, stride, 15677ec681f3Smrg GL_FALSE, integer, GL_FALSE, format, (void*) offset)) 15687ec681f3Smrg return; 15697ec681f3Smrg 15707ec681f3Smrg update_array(ctx, vao, vbo, 15717ec681f3Smrg VERT_ATTRIB_EDGEFLAG, format, 1, 1, GL_UNSIGNED_BYTE, 15727ec681f3Smrg stride, GL_FALSE, integer, GL_FALSE, (void*) offset); 15737ec681f3Smrg} 15747ec681f3Smrg 15757ec681f3Smrg 1576c1f859d4Smrgvoid GLAPIENTRY 157701e04c3fSmrg_mesa_PointSizePointerOES_no_error(GLenum type, GLsizei stride, 157801e04c3fSmrg const GLvoid *ptr) 1579c1f859d4Smrg{ 1580c1f859d4Smrg GET_CURRENT_CONTEXT(ctx); 1581af69d88dSmrg 15827ec681f3Smrg update_array(ctx, ctx->Array.VAO, ctx->Array.ArrayBufferObj, 15837ec681f3Smrg VERT_ATTRIB_POINT_SIZE, GL_RGBA, 1, 1, type, stride, 158401e04c3fSmrg GL_FALSE, GL_FALSE, GL_FALSE, ptr); 158501e04c3fSmrg} 158601e04c3fSmrg 158701e04c3fSmrg 158801e04c3fSmrgvoid GLAPIENTRY 158901e04c3fSmrg_mesa_PointSizePointerOES(GLenum type, GLsizei stride, const GLvoid *ptr) 159001e04c3fSmrg{ 159101e04c3fSmrg GET_CURRENT_CONTEXT(ctx); 1592c1f859d4Smrg 159301e04c3fSmrg GLenum format = GL_RGBA; 15943464ebd5Sriastradh if (ctx->API != API_OPENGLES) { 15953464ebd5Sriastradh _mesa_error(ctx, GL_INVALID_OPERATION, 15963464ebd5Sriastradh "glPointSizePointer(ES 1.x only)"); 1597c1f859d4Smrg return; 1598c1f859d4Smrg } 159901e04c3fSmrg 160001e04c3fSmrg const GLbitfield legalTypes = (FLOAT_BIT | FIXED_ES_BIT); 160101e04c3fSmrg 160201e04c3fSmrg if (!validate_array_and_format(ctx, "glPointSizePointer", 16037ec681f3Smrg ctx->Array.VAO, ctx->Array.ArrayBufferObj, 160401e04c3fSmrg VERT_ATTRIB_POINT_SIZE, legalTypes, 160501e04c3fSmrg 1, 1, 1, type, stride, GL_FALSE, GL_FALSE, 16067ec681f3Smrg GL_FALSE, format, ptr)) 160701e04c3fSmrg return; 160801e04c3fSmrg 16097ec681f3Smrg update_array(ctx, ctx->Array.VAO, ctx->Array.ArrayBufferObj, 16107ec681f3Smrg VERT_ATTRIB_POINT_SIZE, format, 1, 1, type, stride, 161101e04c3fSmrg GL_FALSE, GL_FALSE, GL_FALSE, ptr); 161201e04c3fSmrg} 161301e04c3fSmrg 161401e04c3fSmrg 161501e04c3fSmrgvoid GLAPIENTRY 161601e04c3fSmrg_mesa_VertexAttribPointer_no_error(GLuint index, GLint size, GLenum type, 161701e04c3fSmrg GLboolean normalized, 161801e04c3fSmrg GLsizei stride, const GLvoid *ptr) 161901e04c3fSmrg{ 162001e04c3fSmrg GET_CURRENT_CONTEXT(ctx); 162101e04c3fSmrg 162201e04c3fSmrg GLenum format = get_array_format(ctx, BGRA_OR_4, &size); 16237ec681f3Smrg update_array(ctx, ctx->Array.VAO, ctx->Array.ArrayBufferObj, 16247ec681f3Smrg VERT_ATTRIB_GENERIC(index), format, BGRA_OR_4, 162501e04c3fSmrg size, type, stride, normalized, GL_FALSE, GL_FALSE, ptr); 1626c1f859d4Smrg} 1627c1f859d4Smrg 1628c1f859d4Smrg 16294a49301eSmrg/** 16304a49301eSmrg * Set a generic vertex attribute array. 16314a49301eSmrg * Note that these arrays DO NOT alias the conventional GL vertex arrays 16324a49301eSmrg * (position, normal, color, fog, texcoord, etc). 16334a49301eSmrg */ 16347117f1b4Smrgvoid GLAPIENTRY 1635af69d88dSmrg_mesa_VertexAttribPointer(GLuint index, GLint size, GLenum type, 16367117f1b4Smrg GLboolean normalized, 16377117f1b4Smrg GLsizei stride, const GLvoid *ptr) 16387117f1b4Smrg{ 163901e04c3fSmrg GET_CURRENT_CONTEXT(ctx); 164001e04c3fSmrg 164101e04c3fSmrg GLenum format = get_array_format(ctx, BGRA_OR_4, &size); 164201e04c3fSmrg if (index >= ctx->Const.Program[MESA_SHADER_VERTEX].MaxAttribs) { 164301e04c3fSmrg _mesa_error(ctx, GL_INVALID_VALUE, "glVertexAttribPointerARB(idx)"); 164401e04c3fSmrg return; 164501e04c3fSmrg } 164601e04c3fSmrg 16473464ebd5Sriastradh const GLbitfield legalTypes = (BYTE_BIT | UNSIGNED_BYTE_BIT | 16483464ebd5Sriastradh SHORT_BIT | UNSIGNED_SHORT_BIT | 16493464ebd5Sriastradh INT_BIT | UNSIGNED_INT_BIT | 16503464ebd5Sriastradh HALF_BIT | FLOAT_BIT | DOUBLE_BIT | 1651af69d88dSmrg FIXED_ES_BIT | FIXED_GL_BIT | 1652af69d88dSmrg UNSIGNED_INT_2_10_10_10_REV_BIT | 1653af69d88dSmrg INT_2_10_10_10_REV_BIT | 1654af69d88dSmrg UNSIGNED_INT_10F_11F_11F_REV_BIT); 16557117f1b4Smrg 165601e04c3fSmrg if (!validate_array_and_format(ctx, "glVertexAttribPointer", 16577ec681f3Smrg ctx->Array.VAO, ctx->Array.ArrayBufferObj, 165801e04c3fSmrg VERT_ATTRIB_GENERIC(index), legalTypes, 165901e04c3fSmrg 1, BGRA_OR_4, size, type, stride, 16607ec681f3Smrg normalized, GL_FALSE, GL_FALSE, format, ptr)) 16617117f1b4Smrg return; 16627117f1b4Smrg 16637ec681f3Smrg update_array(ctx, ctx->Array.VAO, ctx->Array.ArrayBufferObj, 16647ec681f3Smrg VERT_ATTRIB_GENERIC(index), format, BGRA_OR_4, 166501e04c3fSmrg size, type, stride, normalized, GL_FALSE, GL_FALSE, ptr); 166601e04c3fSmrg} 166701e04c3fSmrg 166801e04c3fSmrg 16697ec681f3Smrgvoid GLAPIENTRY 16707ec681f3Smrg_mesa_VertexArrayVertexAttribOffsetEXT(GLuint vaobj, GLuint buffer, GLuint index, GLint size, 16717ec681f3Smrg GLenum type, GLboolean normalized, 16727ec681f3Smrg GLsizei stride, GLintptr offset) 16737ec681f3Smrg{ 16747ec681f3Smrg GET_CURRENT_CONTEXT(ctx); 16757ec681f3Smrg GLenum format = get_array_format(ctx, BGRA_OR_4, &size); 16767ec681f3Smrg struct gl_vertex_array_object* vao; 16777ec681f3Smrg struct gl_buffer_object* vbo; 16787ec681f3Smrg 16797ec681f3Smrg if (!_lookup_vao_and_vbo_dsa(ctx, vaobj, buffer, offset, 16807ec681f3Smrg &vao, &vbo, 16817ec681f3Smrg "glVertexArrayVertexAttribOffsetEXT")) 16827ec681f3Smrg return; 16837ec681f3Smrg 16847ec681f3Smrg if (index >= ctx->Const.Program[MESA_SHADER_VERTEX].MaxAttribs) { 16857ec681f3Smrg _mesa_error(ctx, GL_INVALID_VALUE, "glVertexArrayVertexAttribOffsetEXT(idx)"); 16867ec681f3Smrg return; 16877ec681f3Smrg } 16887ec681f3Smrg 16897ec681f3Smrg const GLbitfield legalTypes = (BYTE_BIT | UNSIGNED_BYTE_BIT | 16907ec681f3Smrg SHORT_BIT | UNSIGNED_SHORT_BIT | 16917ec681f3Smrg INT_BIT | UNSIGNED_INT_BIT | 16927ec681f3Smrg HALF_BIT | FLOAT_BIT | DOUBLE_BIT | 16937ec681f3Smrg FIXED_ES_BIT | FIXED_GL_BIT | 16947ec681f3Smrg UNSIGNED_INT_2_10_10_10_REV_BIT | 16957ec681f3Smrg INT_2_10_10_10_REV_BIT | 16967ec681f3Smrg UNSIGNED_INT_10F_11F_11F_REV_BIT); 16977ec681f3Smrg 16987ec681f3Smrg if (!validate_array_and_format(ctx, "glVertexArrayVertexAttribOffsetEXT", 16997ec681f3Smrg vao, vbo, 17007ec681f3Smrg VERT_ATTRIB_GENERIC(index), legalTypes, 17017ec681f3Smrg 1, BGRA_OR_4, size, type, stride, 17027ec681f3Smrg normalized, GL_FALSE, GL_FALSE, format, (void*) offset)) 17037ec681f3Smrg return; 17047ec681f3Smrg 17057ec681f3Smrg update_array(ctx, vao, vbo, 17067ec681f3Smrg VERT_ATTRIB_GENERIC(index), format, BGRA_OR_4, 17077ec681f3Smrg size, type, stride, normalized, GL_FALSE, GL_FALSE, (void*) offset); 17087ec681f3Smrg} 17097ec681f3Smrg 17107ec681f3Smrg 17117ec681f3Smrgvoid GLAPIENTRY 17127ec681f3Smrg_mesa_VertexArrayVertexAttribLOffsetEXT(GLuint vaobj, GLuint buffer, GLuint index, GLint size, 17137ec681f3Smrg GLenum type, GLsizei stride, GLintptr offset) 17147ec681f3Smrg{ 17157ec681f3Smrg GET_CURRENT_CONTEXT(ctx); 17167ec681f3Smrg GLenum format = GL_RGBA; 17177ec681f3Smrg struct gl_vertex_array_object* vao; 17187ec681f3Smrg struct gl_buffer_object* vbo; 17197ec681f3Smrg 17207ec681f3Smrg if (!_lookup_vao_and_vbo_dsa(ctx, vaobj, buffer, offset, 17217ec681f3Smrg &vao, &vbo, 17227ec681f3Smrg "glVertexArrayVertexAttribLOffsetEXT")) 17237ec681f3Smrg return; 17247ec681f3Smrg 17257ec681f3Smrg if (index >= ctx->Const.Program[MESA_SHADER_VERTEX].MaxAttribs) { 17267ec681f3Smrg _mesa_error(ctx, GL_INVALID_VALUE, "glVertexArrayVertexAttribLOffsetEXT(idx)"); 17277ec681f3Smrg return; 17287ec681f3Smrg } 17297ec681f3Smrg 17307ec681f3Smrg const GLbitfield legalTypes = DOUBLE_BIT; 17317ec681f3Smrg 17327ec681f3Smrg if (!validate_array_and_format(ctx, "glVertexArrayVertexAttribLOffsetEXT", 17337ec681f3Smrg vao, vbo, 17347ec681f3Smrg VERT_ATTRIB_GENERIC(index), legalTypes, 17357ec681f3Smrg 1, 4, size, type, stride, 17367ec681f3Smrg GL_FALSE, GL_FALSE, GL_TRUE, format, (void*) offset)) 17377ec681f3Smrg return; 17387ec681f3Smrg 17397ec681f3Smrg update_array(ctx, vao, vbo, 17407ec681f3Smrg VERT_ATTRIB_GENERIC(index), format, 4, 17417ec681f3Smrg size, type, stride, GL_FALSE, GL_FALSE, GL_TRUE, (void*) offset); 17427ec681f3Smrg} 17437ec681f3Smrg 17447ec681f3Smrg 174501e04c3fSmrgvoid GLAPIENTRY 174601e04c3fSmrg_mesa_VertexAttribIPointer_no_error(GLuint index, GLint size, GLenum type, 174701e04c3fSmrg GLsizei stride, const GLvoid *ptr) 174801e04c3fSmrg{ 174901e04c3fSmrg const GLboolean normalized = GL_FALSE; 175001e04c3fSmrg const GLboolean integer = GL_TRUE; 175101e04c3fSmrg GET_CURRENT_CONTEXT(ctx); 175201e04c3fSmrg 17537ec681f3Smrg update_array(ctx, ctx->Array.VAO, ctx->Array.ArrayBufferObj, 17547ec681f3Smrg VERT_ATTRIB_GENERIC(index), GL_RGBA, 4, size, type, 175501e04c3fSmrg stride, normalized, integer, GL_FALSE, ptr); 17563464ebd5Sriastradh} 17573464ebd5Sriastradh 17583464ebd5Sriastradh 17593464ebd5Sriastradh/** 17603464ebd5Sriastradh * GL_EXT_gpu_shader4 / GL 3.0. 17613464ebd5Sriastradh * Set an integer-valued vertex attribute array. 17623464ebd5Sriastradh * Note that these arrays DO NOT alias the conventional GL vertex arrays 17633464ebd5Sriastradh * (position, normal, color, fog, texcoord, etc). 17643464ebd5Sriastradh */ 17653464ebd5Sriastradhvoid GLAPIENTRY 17663464ebd5Sriastradh_mesa_VertexAttribIPointer(GLuint index, GLint size, GLenum type, 17673464ebd5Sriastradh GLsizei stride, const GLvoid *ptr) 17683464ebd5Sriastradh{ 17693464ebd5Sriastradh const GLboolean normalized = GL_FALSE; 17703464ebd5Sriastradh const GLboolean integer = GL_TRUE; 17713464ebd5Sriastradh GET_CURRENT_CONTEXT(ctx); 17723464ebd5Sriastradh 177301e04c3fSmrg GLenum format = GL_RGBA; 1774af69d88dSmrg if (index >= ctx->Const.Program[MESA_SHADER_VERTEX].MaxAttribs) { 17753464ebd5Sriastradh _mesa_error(ctx, GL_INVALID_VALUE, "glVertexAttribIPointer(index)"); 17763464ebd5Sriastradh return; 17777117f1b4Smrg } 17787117f1b4Smrg 177901e04c3fSmrg const GLbitfield legalTypes = (BYTE_BIT | UNSIGNED_BYTE_BIT | 178001e04c3fSmrg SHORT_BIT | UNSIGNED_SHORT_BIT | 178101e04c3fSmrg INT_BIT | UNSIGNED_INT_BIT); 178201e04c3fSmrg 178301e04c3fSmrg if (!validate_array_and_format(ctx, "glVertexAttribIPointer", 17847ec681f3Smrg ctx->Array.VAO, ctx->Array.ArrayBufferObj, 178501e04c3fSmrg VERT_ATTRIB_GENERIC(index), legalTypes, 178601e04c3fSmrg 1, 4, size, type, stride, 17877ec681f3Smrg normalized, integer, GL_FALSE, format, ptr)) 178801e04c3fSmrg return; 178901e04c3fSmrg 17907ec681f3Smrg update_array(ctx, ctx->Array.VAO, ctx->Array.ArrayBufferObj, 17917ec681f3Smrg VERT_ATTRIB_GENERIC(index), format, 4, size, type, 179201e04c3fSmrg stride, normalized, integer, GL_FALSE, ptr); 17933464ebd5Sriastradh} 17943464ebd5Sriastradh 17953464ebd5Sriastradh 179601e04c3fSmrgvoid GLAPIENTRY 179701e04c3fSmrg_mesa_VertexAttribLPointer_no_error(GLuint index, GLint size, GLenum type, 179801e04c3fSmrg GLsizei stride, const GLvoid *ptr) 179901e04c3fSmrg{ 180001e04c3fSmrg GET_CURRENT_CONTEXT(ctx); 180101e04c3fSmrg 18027ec681f3Smrg update_array(ctx, ctx->Array.VAO, ctx->Array.ArrayBufferObj, 18037ec681f3Smrg VERT_ATTRIB_GENERIC(index), GL_RGBA, 4, size, type, 180401e04c3fSmrg stride, GL_FALSE, GL_FALSE, GL_TRUE, ptr); 180501e04c3fSmrg} 180601e04c3fSmrg 18073464ebd5Sriastradh 18087ec681f3Smrgvoid GLAPIENTRY 18097ec681f3Smrg_mesa_VertexArrayVertexAttribIOffsetEXT(GLuint vaobj, GLuint buffer, GLuint index, GLint size, 18107ec681f3Smrg GLenum type, GLsizei stride, GLintptr offset) 18117ec681f3Smrg{ 18127ec681f3Smrg const GLboolean normalized = GL_FALSE; 18137ec681f3Smrg const GLboolean integer = GL_TRUE; 18147ec681f3Smrg GET_CURRENT_CONTEXT(ctx); 18157ec681f3Smrg GLenum format = GL_RGBA; 18167ec681f3Smrg 18177ec681f3Smrg struct gl_vertex_array_object* vao; 18187ec681f3Smrg struct gl_buffer_object* vbo; 18197ec681f3Smrg 18207ec681f3Smrg if (!_lookup_vao_and_vbo_dsa(ctx, vaobj, buffer, offset, 18217ec681f3Smrg &vao, &vbo, 18227ec681f3Smrg "glVertexArrayVertexAttribIOffsetEXT")) 18237ec681f3Smrg return; 18247ec681f3Smrg 18257ec681f3Smrg if (index >= ctx->Const.Program[MESA_SHADER_VERTEX].MaxAttribs) { 18267ec681f3Smrg _mesa_error(ctx, GL_INVALID_VALUE, "glVertexArrayVertexAttribIOffsetEXT(index)"); 18277ec681f3Smrg return; 18287ec681f3Smrg } 18297ec681f3Smrg 18307ec681f3Smrg const GLbitfield legalTypes = (BYTE_BIT | UNSIGNED_BYTE_BIT | 18317ec681f3Smrg SHORT_BIT | UNSIGNED_SHORT_BIT | 18327ec681f3Smrg INT_BIT | UNSIGNED_INT_BIT); 18337ec681f3Smrg 18347ec681f3Smrg if (!validate_array_and_format(ctx, "glVertexArrayVertexAttribIOffsetEXT", 18357ec681f3Smrg vao, vbo, 18367ec681f3Smrg VERT_ATTRIB_GENERIC(index), legalTypes, 18377ec681f3Smrg 1, 4, size, type, stride, 18387ec681f3Smrg normalized, integer, GL_FALSE, format, (void*) offset)) 18397ec681f3Smrg return; 18407ec681f3Smrg 18417ec681f3Smrg update_array(ctx, vao, vbo, 18427ec681f3Smrg VERT_ATTRIB_GENERIC(index), format, 4, size, type, 18437ec681f3Smrg stride, normalized, integer, GL_FALSE, (void*) offset); 18447ec681f3Smrg} 18457ec681f3Smrg 18467ec681f3Smrg 18473464ebd5Sriastradhvoid GLAPIENTRY 184801e04c3fSmrg_mesa_VertexAttribLPointer(GLuint index, GLint size, GLenum type, 184901e04c3fSmrg GLsizei stride, const GLvoid *ptr) 18503464ebd5Sriastradh{ 18513464ebd5Sriastradh GET_CURRENT_CONTEXT(ctx); 18523464ebd5Sriastradh 185301e04c3fSmrg GLenum format = GL_RGBA; 1854af69d88dSmrg if (index >= ctx->Const.Program[MESA_SHADER_VERTEX].MaxAttribs) { 185501e04c3fSmrg _mesa_error(ctx, GL_INVALID_VALUE, "glVertexAttribLPointer(index)"); 18567117f1b4Smrg return; 18577117f1b4Smrg } 18587117f1b4Smrg 185901e04c3fSmrg const GLbitfield legalTypes = DOUBLE_BIT; 186001e04c3fSmrg 186101e04c3fSmrg if (!validate_array_and_format(ctx, "glVertexAttribLPointer", 18627ec681f3Smrg ctx->Array.VAO, ctx->Array.ArrayBufferObj, 186301e04c3fSmrg VERT_ATTRIB_GENERIC(index), legalTypes, 186401e04c3fSmrg 1, 4, size, type, stride, 18657ec681f3Smrg GL_FALSE, GL_FALSE, GL_TRUE, format, ptr)) 186601e04c3fSmrg return; 186701e04c3fSmrg 18687ec681f3Smrg update_array(ctx, ctx->Array.VAO, ctx->Array.ArrayBufferObj, 18697ec681f3Smrg VERT_ATTRIB_GENERIC(index), format, 4, size, type, 187001e04c3fSmrg stride, GL_FALSE, GL_FALSE, GL_TRUE, ptr); 187101e04c3fSmrg} 187201e04c3fSmrg 1873af69d88dSmrg 187401e04c3fSmrgvoid 1875b9abf16eSmaya_mesa_enable_vertex_array_attribs(struct gl_context *ctx, 1876b9abf16eSmaya struct gl_vertex_array_object *vao, 1877b9abf16eSmaya GLbitfield attrib_bits) 187801e04c3fSmrg{ 1879b9abf16eSmaya assert((attrib_bits & ~VERT_BIT_ALL) == 0); 188001e04c3fSmrg assert(!vao->SharedAndImmutable); 18813464ebd5Sriastradh 1882b9abf16eSmaya /* Only work on bits that are disabled */ 1883b9abf16eSmaya attrib_bits &= ~vao->Enabled; 1884b9abf16eSmaya if (attrib_bits) { 1885af69d88dSmrg /* was disabled, now being enabled */ 1886b9abf16eSmaya vao->Enabled |= attrib_bits; 1887b9abf16eSmaya vao->NewArrays |= attrib_bits; 18887ec681f3Smrg vao->NonDefaultStateMask |= attrib_bits; 188901e04c3fSmrg 189001e04c3fSmrg /* Update the map mode if needed */ 1891b9abf16eSmaya if (attrib_bits & (VERT_BIT_POS|VERT_BIT_GENERIC0)) 189201e04c3fSmrg update_attribute_map_mode(ctx, vao); 18937ec681f3Smrg 18947ec681f3Smrg vao->_EnabledWithMapMode = 18957ec681f3Smrg _mesa_vao_enable_to_vp_inputs(vao->_AttributeMapMode, vao->Enabled); 189601e04c3fSmrg } 189701e04c3fSmrg} 189801e04c3fSmrg 189901e04c3fSmrgstatic void 190001e04c3fSmrgenable_vertex_array_attrib(struct gl_context *ctx, 190101e04c3fSmrg struct gl_vertex_array_object *vao, 190201e04c3fSmrg GLuint index, 190301e04c3fSmrg const char *func) 190401e04c3fSmrg{ 190501e04c3fSmrg if (index >= ctx->Const.Program[MESA_SHADER_VERTEX].MaxAttribs) { 190601e04c3fSmrg _mesa_error(ctx, GL_INVALID_VALUE, "%s(index)", func); 190701e04c3fSmrg return; 1908af69d88dSmrg } 190901e04c3fSmrg 191001e04c3fSmrg _mesa_enable_vertex_array_attrib(ctx, vao, VERT_ATTRIB_GENERIC(index)); 19113464ebd5Sriastradh} 19123464ebd5Sriastradh 19133464ebd5Sriastradh 19143464ebd5Sriastradhvoid GLAPIENTRY 191501e04c3fSmrg_mesa_EnableVertexAttribArray(GLuint index) 191601e04c3fSmrg{ 191701e04c3fSmrg GET_CURRENT_CONTEXT(ctx); 191801e04c3fSmrg enable_vertex_array_attrib(ctx, ctx->Array.VAO, index, 191901e04c3fSmrg "glEnableVertexAttribArray"); 192001e04c3fSmrg} 192101e04c3fSmrg 192201e04c3fSmrg 192301e04c3fSmrgvoid GLAPIENTRY 192401e04c3fSmrg_mesa_EnableVertexAttribArray_no_error(GLuint index) 192501e04c3fSmrg{ 192601e04c3fSmrg GET_CURRENT_CONTEXT(ctx); 192701e04c3fSmrg _mesa_enable_vertex_array_attrib(ctx, ctx->Array.VAO, 192801e04c3fSmrg VERT_ATTRIB_GENERIC(index)); 192901e04c3fSmrg} 193001e04c3fSmrg 193101e04c3fSmrg 193201e04c3fSmrgvoid GLAPIENTRY 193301e04c3fSmrg_mesa_EnableVertexArrayAttrib(GLuint vaobj, GLuint index) 19343464ebd5Sriastradh{ 193501e04c3fSmrg GET_CURRENT_CONTEXT(ctx); 1936af69d88dSmrg struct gl_vertex_array_object *vao; 193701e04c3fSmrg 193801e04c3fSmrg /* The ARB_direct_state_access specification says: 193901e04c3fSmrg * 194001e04c3fSmrg * "An INVALID_OPERATION error is generated by EnableVertexArrayAttrib 194101e04c3fSmrg * and DisableVertexArrayAttrib if <vaobj> is not 194201e04c3fSmrg * [compatibility profile: zero or] the name of an existing vertex 194301e04c3fSmrg * array object." 194401e04c3fSmrg */ 19457ec681f3Smrg vao = _mesa_lookup_vao_err(ctx, vaobj, false, "glEnableVertexArrayAttrib"); 194601e04c3fSmrg if (!vao) 194701e04c3fSmrg return; 194801e04c3fSmrg 194901e04c3fSmrg enable_vertex_array_attrib(ctx, vao, index, "glEnableVertexArrayAttrib"); 195001e04c3fSmrg} 195101e04c3fSmrg 19527ec681f3Smrgvoid GLAPIENTRY 19537ec681f3Smrg_mesa_EnableVertexArrayAttribEXT(GLuint vaobj, GLuint index) 19547ec681f3Smrg{ 19557ec681f3Smrg GET_CURRENT_CONTEXT(ctx); 19567ec681f3Smrg struct gl_vertex_array_object* vao = _mesa_lookup_vao_err(ctx, vaobj, 19577ec681f3Smrg true, 19587ec681f3Smrg "glEnableVertexArrayAttribEXT"); 19597ec681f3Smrg if (!vao) 19607ec681f3Smrg return; 19617ec681f3Smrg 19627ec681f3Smrg enable_vertex_array_attrib(ctx, vao, index, "glEnableVertexArrayAttribEXT"); 19637ec681f3Smrg} 19647ec681f3Smrg 196501e04c3fSmrg 196601e04c3fSmrgvoid GLAPIENTRY 196701e04c3fSmrg_mesa_EnableVertexArrayAttrib_no_error(GLuint vaobj, GLuint index) 196801e04c3fSmrg{ 196901e04c3fSmrg GET_CURRENT_CONTEXT(ctx); 197001e04c3fSmrg struct gl_vertex_array_object *vao = _mesa_lookup_vao(ctx, vaobj); 197101e04c3fSmrg _mesa_enable_vertex_array_attrib(ctx, vao, VERT_ATTRIB_GENERIC(index)); 197201e04c3fSmrg} 197301e04c3fSmrg 197401e04c3fSmrg 197501e04c3fSmrgvoid 1976b9abf16eSmaya_mesa_disable_vertex_array_attribs(struct gl_context *ctx, 1977b9abf16eSmaya struct gl_vertex_array_object *vao, 1978b9abf16eSmaya GLbitfield attrib_bits) 197901e04c3fSmrg{ 1980b9abf16eSmaya assert((attrib_bits & ~VERT_BIT_ALL) == 0); 198101e04c3fSmrg assert(!vao->SharedAndImmutable); 198201e04c3fSmrg 1983b9abf16eSmaya /* Only work on bits that are enabled */ 1984b9abf16eSmaya attrib_bits &= vao->Enabled; 1985b9abf16eSmaya if (attrib_bits) { 198601e04c3fSmrg /* was enabled, now being disabled */ 1987b9abf16eSmaya vao->Enabled &= ~attrib_bits; 1988b9abf16eSmaya vao->NewArrays |= attrib_bits; 198901e04c3fSmrg 199001e04c3fSmrg /* Update the map mode if needed */ 1991b9abf16eSmaya if (attrib_bits & (VERT_BIT_POS|VERT_BIT_GENERIC0)) 199201e04c3fSmrg update_attribute_map_mode(ctx, vao); 19937ec681f3Smrg 19947ec681f3Smrg vao->_EnabledWithMapMode = 19957ec681f3Smrg _mesa_vao_enable_to_vp_inputs(vao->_AttributeMapMode, vao->Enabled); 199601e04c3fSmrg } 199701e04c3fSmrg} 199801e04c3fSmrg 199901e04c3fSmrg 200001e04c3fSmrgvoid GLAPIENTRY 200101e04c3fSmrg_mesa_DisableVertexAttribArray(GLuint index) 200201e04c3fSmrg{ 20033464ebd5Sriastradh GET_CURRENT_CONTEXT(ctx); 20043464ebd5Sriastradh 2005af69d88dSmrg if (index >= ctx->Const.Program[MESA_SHADER_VERTEX].MaxAttribs) { 200601e04c3fSmrg _mesa_error(ctx, GL_INVALID_VALUE, "glDisableVertexAttribArray(index)"); 20073464ebd5Sriastradh return; 20083464ebd5Sriastradh } 20093464ebd5Sriastradh 201001e04c3fSmrg const gl_vert_attrib attrib = VERT_ATTRIB_GENERIC(index); 201101e04c3fSmrg _mesa_disable_vertex_array_attrib(ctx, ctx->Array.VAO, attrib); 201201e04c3fSmrg} 20133464ebd5Sriastradh 2014af69d88dSmrg 201501e04c3fSmrgvoid GLAPIENTRY 201601e04c3fSmrg_mesa_DisableVertexAttribArray_no_error(GLuint index) 201701e04c3fSmrg{ 201801e04c3fSmrg GET_CURRENT_CONTEXT(ctx); 201901e04c3fSmrg const gl_vert_attrib attrib = VERT_ATTRIB_GENERIC(index); 202001e04c3fSmrg _mesa_disable_vertex_array_attrib(ctx, ctx->Array.VAO, attrib); 202101e04c3fSmrg} 202201e04c3fSmrg 202301e04c3fSmrg 202401e04c3fSmrgvoid GLAPIENTRY 202501e04c3fSmrg_mesa_DisableVertexArrayAttrib(GLuint vaobj, GLuint index) 202601e04c3fSmrg{ 202701e04c3fSmrg GET_CURRENT_CONTEXT(ctx); 202801e04c3fSmrg struct gl_vertex_array_object *vao; 202901e04c3fSmrg 203001e04c3fSmrg /* The ARB_direct_state_access specification says: 203101e04c3fSmrg * 203201e04c3fSmrg * "An INVALID_OPERATION error is generated by EnableVertexArrayAttrib 203301e04c3fSmrg * and DisableVertexArrayAttrib if <vaobj> is not 203401e04c3fSmrg * [compatibility profile: zero or] the name of an existing vertex 203501e04c3fSmrg * array object." 203601e04c3fSmrg */ 20377ec681f3Smrg vao = _mesa_lookup_vao_err(ctx, vaobj, false, "glDisableVertexArrayAttrib"); 20387ec681f3Smrg if (!vao) 20397ec681f3Smrg return; 20407ec681f3Smrg 20417ec681f3Smrg if (index >= ctx->Const.Program[MESA_SHADER_VERTEX].MaxAttribs) { 20427ec681f3Smrg _mesa_error(ctx, GL_INVALID_VALUE, "glDisableVertexArrayAttrib(index)"); 20437ec681f3Smrg return; 20447ec681f3Smrg } 20457ec681f3Smrg 20467ec681f3Smrg const gl_vert_attrib attrib = VERT_ATTRIB_GENERIC(index); 20477ec681f3Smrg _mesa_disable_vertex_array_attrib(ctx, vao, attrib); 20487ec681f3Smrg} 20497ec681f3Smrg 20507ec681f3Smrgvoid GLAPIENTRY 20517ec681f3Smrg_mesa_DisableVertexArrayAttribEXT(GLuint vaobj, GLuint index) 20527ec681f3Smrg{ 20537ec681f3Smrg GET_CURRENT_CONTEXT(ctx); 20547ec681f3Smrg struct gl_vertex_array_object* vao = _mesa_lookup_vao_err(ctx, vaobj, 20557ec681f3Smrg true, 20567ec681f3Smrg "glEnableVertexArrayAttribEXT"); 205701e04c3fSmrg if (!vao) 205801e04c3fSmrg return; 205901e04c3fSmrg 206001e04c3fSmrg if (index >= ctx->Const.Program[MESA_SHADER_VERTEX].MaxAttribs) { 206101e04c3fSmrg _mesa_error(ctx, GL_INVALID_VALUE, "glDisableVertexArrayAttrib(index)"); 206201e04c3fSmrg return; 2063af69d88dSmrg } 206401e04c3fSmrg 206501e04c3fSmrg const gl_vert_attrib attrib = VERT_ATTRIB_GENERIC(index); 206601e04c3fSmrg _mesa_disable_vertex_array_attrib(ctx, vao, attrib); 206701e04c3fSmrg} 206801e04c3fSmrg 206901e04c3fSmrg 207001e04c3fSmrgvoid GLAPIENTRY 207101e04c3fSmrg_mesa_DisableVertexArrayAttrib_no_error(GLuint vaobj, GLuint index) 207201e04c3fSmrg{ 207301e04c3fSmrg GET_CURRENT_CONTEXT(ctx); 207401e04c3fSmrg struct gl_vertex_array_object *vao = _mesa_lookup_vao(ctx, vaobj); 207501e04c3fSmrg const gl_vert_attrib attrib = VERT_ATTRIB_GENERIC(index); 207601e04c3fSmrg _mesa_disable_vertex_array_attrib(ctx, vao, attrib); 20773464ebd5Sriastradh} 20783464ebd5Sriastradh 20793464ebd5Sriastradh 20803464ebd5Sriastradh/** 20813464ebd5Sriastradh * Return info for a vertex attribute array (no alias with legacy 20823464ebd5Sriastradh * vertex attributes (pos, normal, color, etc)). This function does 20833464ebd5Sriastradh * not handle the 4-element GL_CURRENT_VERTEX_ATTRIB_ARB query. 20843464ebd5Sriastradh */ 20853464ebd5Sriastradhstatic GLuint 208601e04c3fSmrgget_vertex_array_attrib(struct gl_context *ctx, 208701e04c3fSmrg const struct gl_vertex_array_object *vao, 208801e04c3fSmrg GLuint index, GLenum pname, 208901e04c3fSmrg const char *caller) 20903464ebd5Sriastradh{ 209101e04c3fSmrg const struct gl_array_attributes *array; 20927ec681f3Smrg struct gl_buffer_object *buf; 20933464ebd5Sriastradh 2094af69d88dSmrg if (index >= ctx->Const.Program[MESA_SHADER_VERTEX].MaxAttribs) { 20953464ebd5Sriastradh _mesa_error(ctx, GL_INVALID_VALUE, "%s(index=%u)", caller, index); 20963464ebd5Sriastradh return 0; 20973464ebd5Sriastradh } 20983464ebd5Sriastradh 209901e04c3fSmrg assert(VERT_ATTRIB_GENERIC(index) < ARRAY_SIZE(vao->VertexAttrib)); 21003464ebd5Sriastradh 2101af69d88dSmrg array = &vao->VertexAttrib[VERT_ATTRIB_GENERIC(index)]; 21023464ebd5Sriastradh 21033464ebd5Sriastradh switch (pname) { 21043464ebd5Sriastradh case GL_VERTEX_ATTRIB_ARRAY_ENABLED_ARB: 2105b9abf16eSmaya return !!(vao->Enabled & VERT_BIT_GENERIC(index)); 21063464ebd5Sriastradh case GL_VERTEX_ATTRIB_ARRAY_SIZE_ARB: 2107b9abf16eSmaya return (array->Format.Format == GL_BGRA) ? GL_BGRA : array->Format.Size; 21083464ebd5Sriastradh case GL_VERTEX_ATTRIB_ARRAY_STRIDE_ARB: 21093464ebd5Sriastradh return array->Stride; 21103464ebd5Sriastradh case GL_VERTEX_ATTRIB_ARRAY_TYPE_ARB: 2111b9abf16eSmaya return array->Format.Type; 21123464ebd5Sriastradh case GL_VERTEX_ATTRIB_ARRAY_NORMALIZED_ARB: 2113b9abf16eSmaya return array->Format.Normalized; 21143464ebd5Sriastradh case GL_VERTEX_ATTRIB_ARRAY_BUFFER_BINDING_ARB: 21157ec681f3Smrg buf = vao->BufferBinding[array->BufferBindingIndex].BufferObj; 21167ec681f3Smrg return buf ? buf->Name : 0; 21173464ebd5Sriastradh case GL_VERTEX_ATTRIB_ARRAY_INTEGER: 2118af69d88dSmrg if ((_mesa_is_desktop_gl(ctx) 2119af69d88dSmrg && (ctx->Version >= 30 || ctx->Extensions.EXT_gpu_shader4)) 2120af69d88dSmrg || _mesa_is_gles3(ctx)) { 2121b9abf16eSmaya return array->Format.Integer; 21224a49301eSmrg } 21233464ebd5Sriastradh goto error; 212401e04c3fSmrg case GL_VERTEX_ATTRIB_ARRAY_LONG: 212501e04c3fSmrg if (_mesa_is_desktop_gl(ctx)) { 2126b9abf16eSmaya return array->Format.Doubles; 212701e04c3fSmrg } 212801e04c3fSmrg goto error; 21293464ebd5Sriastradh case GL_VERTEX_ATTRIB_ARRAY_DIVISOR_ARB: 2130af69d88dSmrg if ((_mesa_is_desktop_gl(ctx) && ctx->Extensions.ARB_instanced_arrays) 2131af69d88dSmrg || _mesa_is_gles3(ctx)) { 213201e04c3fSmrg return vao->BufferBinding[array->BufferBindingIndex].InstanceDivisor; 2133af69d88dSmrg } 2134af69d88dSmrg goto error; 2135af69d88dSmrg case GL_VERTEX_ATTRIB_BINDING: 213601e04c3fSmrg if (_mesa_is_desktop_gl(ctx) || _mesa_is_gles31(ctx)) { 213701e04c3fSmrg return array->BufferBindingIndex - VERT_ATTRIB_GENERIC0; 2138af69d88dSmrg } 2139af69d88dSmrg goto error; 2140af69d88dSmrg case GL_VERTEX_ATTRIB_RELATIVE_OFFSET: 214101e04c3fSmrg if (_mesa_is_desktop_gl(ctx) || _mesa_is_gles31(ctx)) { 2142af69d88dSmrg return array->RelativeOffset; 21434a49301eSmrg } 21443464ebd5Sriastradh goto error; 21453464ebd5Sriastradh default: 21463464ebd5Sriastradh ; /* fall-through */ 21473464ebd5Sriastradh } 21484a49301eSmrg 21493464ebd5Sriastradherror: 21503464ebd5Sriastradh _mesa_error(ctx, GL_INVALID_ENUM, "%s(pname=0x%x)", caller, pname); 21513464ebd5Sriastradh return 0; 21523464ebd5Sriastradh} 21533464ebd5Sriastradh 21543464ebd5Sriastradh 21553464ebd5Sriastradhstatic const GLfloat * 21563464ebd5Sriastradhget_current_attrib(struct gl_context *ctx, GLuint index, const char *function) 21573464ebd5Sriastradh{ 21583464ebd5Sriastradh if (index == 0) { 2159af69d88dSmrg if (_mesa_attr_zero_aliases_vertex(ctx)) { 21603464ebd5Sriastradh _mesa_error(ctx, GL_INVALID_OPERATION, "%s(index==0)", function); 21613464ebd5Sriastradh return NULL; 21623464ebd5Sriastradh } 21633464ebd5Sriastradh } 2164af69d88dSmrg else if (index >= ctx->Const.Program[MESA_SHADER_VERTEX].MaxAttribs) { 21653464ebd5Sriastradh _mesa_error(ctx, GL_INVALID_VALUE, 21663464ebd5Sriastradh "%s(index>=GL_MAX_VERTEX_ATTRIBS)", function); 21673464ebd5Sriastradh return NULL; 21683464ebd5Sriastradh } 21693464ebd5Sriastradh 217001e04c3fSmrg assert(VERT_ATTRIB_GENERIC(index) < 217101e04c3fSmrg ARRAY_SIZE(ctx->Array.VAO->VertexAttrib)); 2172af69d88dSmrg 21733464ebd5Sriastradh FLUSH_CURRENT(ctx, 0); 2174af69d88dSmrg return ctx->Current.Attrib[VERT_ATTRIB_GENERIC(index)]; 21753464ebd5Sriastradh} 21763464ebd5Sriastradh 21773464ebd5Sriastradhvoid GLAPIENTRY 2178af69d88dSmrg_mesa_GetVertexAttribfv(GLuint index, GLenum pname, GLfloat *params) 21793464ebd5Sriastradh{ 21803464ebd5Sriastradh GET_CURRENT_CONTEXT(ctx); 21813464ebd5Sriastradh 21823464ebd5Sriastradh if (pname == GL_CURRENT_VERTEX_ATTRIB_ARB) { 21833464ebd5Sriastradh const GLfloat *v = get_current_attrib(ctx, index, "glGetVertexAttribfv"); 21843464ebd5Sriastradh if (v != NULL) { 21853464ebd5Sriastradh COPY_4V(params, v); 21863464ebd5Sriastradh } 21874a49301eSmrg } 21884a49301eSmrg else { 218901e04c3fSmrg params[0] = (GLfloat) get_vertex_array_attrib(ctx, ctx->Array.VAO, 219001e04c3fSmrg index, pname, 21913464ebd5Sriastradh "glGetVertexAttribfv"); 21924a49301eSmrg } 21933464ebd5Sriastradh} 21944a49301eSmrg 21953464ebd5Sriastradh 21963464ebd5Sriastradhvoid GLAPIENTRY 2197af69d88dSmrg_mesa_GetVertexAttribdv(GLuint index, GLenum pname, GLdouble *params) 21983464ebd5Sriastradh{ 21993464ebd5Sriastradh GET_CURRENT_CONTEXT(ctx); 22003464ebd5Sriastradh 22013464ebd5Sriastradh if (pname == GL_CURRENT_VERTEX_ATTRIB_ARB) { 22023464ebd5Sriastradh const GLfloat *v = get_current_attrib(ctx, index, "glGetVertexAttribdv"); 22033464ebd5Sriastradh if (v != NULL) { 22043464ebd5Sriastradh params[0] = (GLdouble) v[0]; 22053464ebd5Sriastradh params[1] = (GLdouble) v[1]; 22063464ebd5Sriastradh params[2] = (GLdouble) v[2]; 22073464ebd5Sriastradh params[3] = (GLdouble) v[3]; 22083464ebd5Sriastradh } 22093464ebd5Sriastradh } 22103464ebd5Sriastradh else { 221101e04c3fSmrg params[0] = (GLdouble) get_vertex_array_attrib(ctx, ctx->Array.VAO, 221201e04c3fSmrg index, pname, 22133464ebd5Sriastradh "glGetVertexAttribdv"); 22147117f1b4Smrg } 22153464ebd5Sriastradh} 22167117f1b4Smrg 221701e04c3fSmrgvoid GLAPIENTRY 221801e04c3fSmrg_mesa_GetVertexAttribLdv(GLuint index, GLenum pname, GLdouble *params) 221901e04c3fSmrg{ 222001e04c3fSmrg GET_CURRENT_CONTEXT(ctx); 222101e04c3fSmrg 222201e04c3fSmrg if (pname == GL_CURRENT_VERTEX_ATTRIB_ARB) { 222301e04c3fSmrg const GLdouble *v = 222401e04c3fSmrg (const GLdouble *)get_current_attrib(ctx, index, 222501e04c3fSmrg "glGetVertexAttribLdv"); 222601e04c3fSmrg if (v != NULL) { 222701e04c3fSmrg params[0] = v[0]; 222801e04c3fSmrg params[1] = v[1]; 222901e04c3fSmrg params[2] = v[2]; 223001e04c3fSmrg params[3] = v[3]; 223101e04c3fSmrg } 223201e04c3fSmrg } 223301e04c3fSmrg else { 223401e04c3fSmrg params[0] = (GLdouble) get_vertex_array_attrib(ctx, ctx->Array.VAO, 223501e04c3fSmrg index, pname, 223601e04c3fSmrg "glGetVertexAttribLdv"); 223701e04c3fSmrg } 223801e04c3fSmrg} 22393464ebd5Sriastradh 22403464ebd5Sriastradhvoid GLAPIENTRY 2241af69d88dSmrg_mesa_GetVertexAttribiv(GLuint index, GLenum pname, GLint *params) 22423464ebd5Sriastradh{ 22433464ebd5Sriastradh GET_CURRENT_CONTEXT(ctx); 22443464ebd5Sriastradh 22453464ebd5Sriastradh if (pname == GL_CURRENT_VERTEX_ATTRIB_ARB) { 22463464ebd5Sriastradh const GLfloat *v = get_current_attrib(ctx, index, "glGetVertexAttribiv"); 22473464ebd5Sriastradh if (v != NULL) { 22483464ebd5Sriastradh /* XXX should floats in[0,1] be scaled to full int range? */ 22493464ebd5Sriastradh params[0] = (GLint) v[0]; 22503464ebd5Sriastradh params[1] = (GLint) v[1]; 22513464ebd5Sriastradh params[2] = (GLint) v[2]; 22523464ebd5Sriastradh params[3] = (GLint) v[3]; 22533464ebd5Sriastradh } 22543464ebd5Sriastradh } 22553464ebd5Sriastradh else { 225601e04c3fSmrg params[0] = (GLint) get_vertex_array_attrib(ctx, ctx->Array.VAO, 225701e04c3fSmrg index, pname, 22583464ebd5Sriastradh "glGetVertexAttribiv"); 22593464ebd5Sriastradh } 22603464ebd5Sriastradh} 22613464ebd5Sriastradh 226201e04c3fSmrgvoid GLAPIENTRY 226301e04c3fSmrg_mesa_GetVertexAttribLui64vARB(GLuint index, GLenum pname, GLuint64EXT *params) 226401e04c3fSmrg{ 226501e04c3fSmrg GET_CURRENT_CONTEXT(ctx); 226601e04c3fSmrg 226701e04c3fSmrg if (pname == GL_CURRENT_VERTEX_ATTRIB_ARB) { 226801e04c3fSmrg const GLuint64 *v = 226901e04c3fSmrg (const GLuint64 *)get_current_attrib(ctx, index, 227001e04c3fSmrg "glGetVertexAttribLui64vARB"); 227101e04c3fSmrg if (v != NULL) { 227201e04c3fSmrg params[0] = v[0]; 227301e04c3fSmrg params[1] = v[1]; 227401e04c3fSmrg params[2] = v[2]; 227501e04c3fSmrg params[3] = v[3]; 227601e04c3fSmrg } 227701e04c3fSmrg } 227801e04c3fSmrg else { 227901e04c3fSmrg params[0] = (GLuint64) get_vertex_array_attrib(ctx, ctx->Array.VAO, 228001e04c3fSmrg index, pname, 228101e04c3fSmrg "glGetVertexAttribLui64vARB"); 228201e04c3fSmrg } 228301e04c3fSmrg} 228401e04c3fSmrg 22853464ebd5Sriastradh 22863464ebd5Sriastradh/** GL 3.0 */ 22873464ebd5Sriastradhvoid GLAPIENTRY 22883464ebd5Sriastradh_mesa_GetVertexAttribIiv(GLuint index, GLenum pname, GLint *params) 22893464ebd5Sriastradh{ 22903464ebd5Sriastradh GET_CURRENT_CONTEXT(ctx); 22913464ebd5Sriastradh 22923464ebd5Sriastradh if (pname == GL_CURRENT_VERTEX_ATTRIB_ARB) { 2293af69d88dSmrg const GLint *v = (const GLint *) 22943464ebd5Sriastradh get_current_attrib(ctx, index, "glGetVertexAttribIiv"); 22953464ebd5Sriastradh if (v != NULL) { 2296af69d88dSmrg COPY_4V(params, v); 22973464ebd5Sriastradh } 22983464ebd5Sriastradh } 22993464ebd5Sriastradh else { 230001e04c3fSmrg params[0] = (GLint) get_vertex_array_attrib(ctx, ctx->Array.VAO, 230101e04c3fSmrg index, pname, 23023464ebd5Sriastradh "glGetVertexAttribIiv"); 23033464ebd5Sriastradh } 23043464ebd5Sriastradh} 23053464ebd5Sriastradh 23063464ebd5Sriastradh 23073464ebd5Sriastradh/** GL 3.0 */ 23083464ebd5Sriastradhvoid GLAPIENTRY 23093464ebd5Sriastradh_mesa_GetVertexAttribIuiv(GLuint index, GLenum pname, GLuint *params) 23103464ebd5Sriastradh{ 23113464ebd5Sriastradh GET_CURRENT_CONTEXT(ctx); 23123464ebd5Sriastradh 23133464ebd5Sriastradh if (pname == GL_CURRENT_VERTEX_ATTRIB_ARB) { 2314af69d88dSmrg const GLuint *v = (const GLuint *) 23153464ebd5Sriastradh get_current_attrib(ctx, index, "glGetVertexAttribIuiv"); 23163464ebd5Sriastradh if (v != NULL) { 2317af69d88dSmrg COPY_4V(params, v); 23183464ebd5Sriastradh } 23193464ebd5Sriastradh } 23203464ebd5Sriastradh else { 232101e04c3fSmrg params[0] = get_vertex_array_attrib(ctx, ctx->Array.VAO, 232201e04c3fSmrg index, pname, 23233464ebd5Sriastradh "glGetVertexAttribIuiv"); 23243464ebd5Sriastradh } 23253464ebd5Sriastradh} 23263464ebd5Sriastradh 23273464ebd5Sriastradh 23283464ebd5Sriastradhvoid GLAPIENTRY 2329af69d88dSmrg_mesa_GetVertexAttribPointerv(GLuint index, GLenum pname, GLvoid **pointer) 23303464ebd5Sriastradh{ 23313464ebd5Sriastradh GET_CURRENT_CONTEXT(ctx); 23323464ebd5Sriastradh 2333af69d88dSmrg if (index >= ctx->Const.Program[MESA_SHADER_VERTEX].MaxAttribs) { 23343464ebd5Sriastradh _mesa_error(ctx, GL_INVALID_VALUE, "glGetVertexAttribPointerARB(index)"); 23353464ebd5Sriastradh return; 23363464ebd5Sriastradh } 23373464ebd5Sriastradh 23383464ebd5Sriastradh if (pname != GL_VERTEX_ATTRIB_ARRAY_POINTER_ARB) { 23393464ebd5Sriastradh _mesa_error(ctx, GL_INVALID_ENUM, "glGetVertexAttribPointerARB(pname)"); 23403464ebd5Sriastradh return; 23413464ebd5Sriastradh } 23423464ebd5Sriastradh 234301e04c3fSmrg assert(VERT_ATTRIB_GENERIC(index) < 234401e04c3fSmrg ARRAY_SIZE(ctx->Array.VAO->VertexAttrib)); 234501e04c3fSmrg 234601e04c3fSmrg *pointer = (GLvoid *) 234701e04c3fSmrg ctx->Array.VAO->VertexAttrib[VERT_ATTRIB_GENERIC(index)].Ptr; 234801e04c3fSmrg} 234901e04c3fSmrg 235001e04c3fSmrg 235101e04c3fSmrg/** ARB_direct_state_access */ 235201e04c3fSmrgvoid GLAPIENTRY 235301e04c3fSmrg_mesa_GetVertexArrayIndexediv(GLuint vaobj, GLuint index, 235401e04c3fSmrg GLenum pname, GLint *params) 235501e04c3fSmrg{ 235601e04c3fSmrg GET_CURRENT_CONTEXT(ctx); 235701e04c3fSmrg struct gl_vertex_array_object *vao; 23587ec681f3Smrg struct gl_buffer_object *buf; 235901e04c3fSmrg 236001e04c3fSmrg /* The ARB_direct_state_access specification says: 236101e04c3fSmrg * 236201e04c3fSmrg * "An INVALID_OPERATION error is generated if <vaobj> is not 236301e04c3fSmrg * [compatibility profile: zero or] the name of an existing 236401e04c3fSmrg * vertex array object." 236501e04c3fSmrg */ 23667ec681f3Smrg vao = _mesa_lookup_vao_err(ctx, vaobj, false, "glGetVertexArrayIndexediv"); 236701e04c3fSmrg if (!vao) 236801e04c3fSmrg return; 236901e04c3fSmrg 237001e04c3fSmrg /* The ARB_direct_state_access specification says: 237101e04c3fSmrg * 237201e04c3fSmrg * "For GetVertexArrayIndexediv, <pname> must be one of 237301e04c3fSmrg * VERTEX_ATTRIB_ARRAY_ENABLED, VERTEX_ATTRIB_ARRAY_SIZE, 237401e04c3fSmrg * VERTEX_ATTRIB_ARRAY_STRIDE, VERTEX_ATTRIB_ARRAY_TYPE, 237501e04c3fSmrg * VERTEX_ATTRIB_ARRAY_NORMALIZED, VERTEX_ATTRIB_ARRAY_INTEGER, 237601e04c3fSmrg * VERTEX_ATTRIB_ARRAY_LONG, VERTEX_ATTRIB_ARRAY_DIVISOR, or 237701e04c3fSmrg * VERTEX_ATTRIB_RELATIVE_OFFSET." 237801e04c3fSmrg * 237901e04c3fSmrg * and: 238001e04c3fSmrg * 238101e04c3fSmrg * "Add GetVertexArrayIndexediv in 'Get Command' for 238201e04c3fSmrg * VERTEX_ATTRIB_ARRAY_BUFFER_BINDING 238301e04c3fSmrg * VERTEX_ATTRIB_BINDING, 238401e04c3fSmrg * VERTEX_ATTRIB_RELATIVE_OFFSET, 238501e04c3fSmrg * VERTEX_BINDING_OFFSET, and 238601e04c3fSmrg * VERTEX_BINDING_STRIDE states" 238701e04c3fSmrg * 238801e04c3fSmrg * The only parameter name common to both lists is 238901e04c3fSmrg * VERTEX_ATTRIB_RELATIVE_OFFSET. Also note that VERTEX_BINDING_BUFFER 239001e04c3fSmrg * and VERTEX_BINDING_DIVISOR are missing from both lists. It seems 239101e04c3fSmrg * pretty clear however that the intent is that it should be possible 239201e04c3fSmrg * to query all vertex attrib and binding states that can be set with 239301e04c3fSmrg * a DSA function. 239401e04c3fSmrg */ 239501e04c3fSmrg switch (pname) { 239601e04c3fSmrg case GL_VERTEX_BINDING_OFFSET: 239701e04c3fSmrg params[0] = vao->BufferBinding[VERT_ATTRIB_GENERIC(index)].Offset; 239801e04c3fSmrg break; 239901e04c3fSmrg case GL_VERTEX_BINDING_STRIDE: 240001e04c3fSmrg params[0] = vao->BufferBinding[VERT_ATTRIB_GENERIC(index)].Stride; 240101e04c3fSmrg break; 240201e04c3fSmrg case GL_VERTEX_BINDING_DIVISOR: 240301e04c3fSmrg params[0] = vao->BufferBinding[VERT_ATTRIB_GENERIC(index)].InstanceDivisor; 240401e04c3fSmrg break; 240501e04c3fSmrg case GL_VERTEX_BINDING_BUFFER: 24067ec681f3Smrg buf = vao->BufferBinding[VERT_ATTRIB_GENERIC(index)].BufferObj; 24077ec681f3Smrg params[0] = buf ? buf->Name : 0; 240801e04c3fSmrg break; 240901e04c3fSmrg default: 241001e04c3fSmrg params[0] = get_vertex_array_attrib(ctx, vao, index, pname, 241101e04c3fSmrg "glGetVertexArrayIndexediv"); 241201e04c3fSmrg break; 241301e04c3fSmrg } 241401e04c3fSmrg} 241501e04c3fSmrg 241601e04c3fSmrg 241701e04c3fSmrgvoid GLAPIENTRY 241801e04c3fSmrg_mesa_GetVertexArrayIndexed64iv(GLuint vaobj, GLuint index, 241901e04c3fSmrg GLenum pname, GLint64 *params) 242001e04c3fSmrg{ 242101e04c3fSmrg GET_CURRENT_CONTEXT(ctx); 242201e04c3fSmrg struct gl_vertex_array_object *vao; 242301e04c3fSmrg 242401e04c3fSmrg /* The ARB_direct_state_access specification says: 242501e04c3fSmrg * 242601e04c3fSmrg * "An INVALID_OPERATION error is generated if <vaobj> is not 242701e04c3fSmrg * [compatibility profile: zero or] the name of an existing 242801e04c3fSmrg * vertex array object." 242901e04c3fSmrg */ 24307ec681f3Smrg vao = _mesa_lookup_vao_err(ctx, vaobj, false, "glGetVertexArrayIndexed64iv"); 243101e04c3fSmrg if (!vao) 243201e04c3fSmrg return; 243301e04c3fSmrg 243401e04c3fSmrg /* The ARB_direct_state_access specification says: 243501e04c3fSmrg * 243601e04c3fSmrg * "For GetVertexArrayIndexed64iv, <pname> must be 243701e04c3fSmrg * VERTEX_BINDING_OFFSET." 243801e04c3fSmrg * 243901e04c3fSmrg * and: 244001e04c3fSmrg * 244101e04c3fSmrg * "An INVALID_ENUM error is generated if <pname> is not one of 244201e04c3fSmrg * the valid values listed above for the corresponding command." 244301e04c3fSmrg */ 244401e04c3fSmrg if (pname != GL_VERTEX_BINDING_OFFSET) { 244501e04c3fSmrg _mesa_error(ctx, GL_INVALID_ENUM, "glGetVertexArrayIndexed64iv(" 244601e04c3fSmrg "pname != GL_VERTEX_BINDING_OFFSET)"); 244701e04c3fSmrg return; 244801e04c3fSmrg } 244901e04c3fSmrg 245001e04c3fSmrg /* The ARB_direct_state_access specification says: 245101e04c3fSmrg * 245201e04c3fSmrg * "An INVALID_VALUE error is generated if <index> is greater than 245301e04c3fSmrg * or equal to the value of MAX_VERTEX_ATTRIBS." 245401e04c3fSmrg * 245501e04c3fSmrg * Since the index refers to a buffer binding in this case, the intended 245601e04c3fSmrg * limit must be MAX_VERTEX_ATTRIB_BINDINGS. Both limits are currently 245701e04c3fSmrg * required to be the same, so in practice this doesn't matter. 245801e04c3fSmrg */ 245901e04c3fSmrg if (index >= ctx->Const.MaxVertexAttribBindings) { 246001e04c3fSmrg _mesa_error(ctx, GL_INVALID_VALUE, "glGetVertexArrayIndexed64iv(index" 246101e04c3fSmrg "%d >= the value of GL_MAX_VERTEX_ATTRIB_BINDINGS (%d))", 246201e04c3fSmrg index, ctx->Const.MaxVertexAttribBindings); 246301e04c3fSmrg return; 246401e04c3fSmrg } 24653464ebd5Sriastradh 246601e04c3fSmrg params[0] = vao->BufferBinding[VERT_ATTRIB_GENERIC(index)].Offset; 24677117f1b4Smrg} 24687117f1b4Smrg 24697117f1b4Smrg 24707117f1b4Smrgvoid GLAPIENTRY 24717117f1b4Smrg_mesa_VertexPointerEXT(GLint size, GLenum type, GLsizei stride, 24727117f1b4Smrg GLsizei count, const GLvoid *ptr) 24737117f1b4Smrg{ 24747117f1b4Smrg (void) count; 24757117f1b4Smrg _mesa_VertexPointer(size, type, stride, ptr); 24767117f1b4Smrg} 24777117f1b4Smrg 24787117f1b4Smrg 24797117f1b4Smrgvoid GLAPIENTRY 24807117f1b4Smrg_mesa_NormalPointerEXT(GLenum type, GLsizei stride, GLsizei count, 24817117f1b4Smrg const GLvoid *ptr) 24827117f1b4Smrg{ 24837117f1b4Smrg (void) count; 24847117f1b4Smrg _mesa_NormalPointer(type, stride, ptr); 24857117f1b4Smrg} 24867117f1b4Smrg 24877117f1b4Smrg 24887117f1b4Smrgvoid GLAPIENTRY 24897117f1b4Smrg_mesa_ColorPointerEXT(GLint size, GLenum type, GLsizei stride, GLsizei count, 24907117f1b4Smrg const GLvoid *ptr) 24917117f1b4Smrg{ 24927117f1b4Smrg (void) count; 24937117f1b4Smrg _mesa_ColorPointer(size, type, stride, ptr); 24947117f1b4Smrg} 24957117f1b4Smrg 24967117f1b4Smrg 24977117f1b4Smrgvoid GLAPIENTRY 24987117f1b4Smrg_mesa_IndexPointerEXT(GLenum type, GLsizei stride, GLsizei count, 24997117f1b4Smrg const GLvoid *ptr) 25007117f1b4Smrg{ 25017117f1b4Smrg (void) count; 25027117f1b4Smrg _mesa_IndexPointer(type, stride, ptr); 25037117f1b4Smrg} 25047117f1b4Smrg 25057117f1b4Smrg 25067117f1b4Smrgvoid GLAPIENTRY 25077117f1b4Smrg_mesa_TexCoordPointerEXT(GLint size, GLenum type, GLsizei stride, 25087117f1b4Smrg GLsizei count, const GLvoid *ptr) 25097117f1b4Smrg{ 25107117f1b4Smrg (void) count; 25117117f1b4Smrg _mesa_TexCoordPointer(size, type, stride, ptr); 25127117f1b4Smrg} 25137117f1b4Smrg 25147117f1b4Smrg 25157ec681f3Smrgvoid GLAPIENTRY 25167ec681f3Smrg_mesa_MultiTexCoordPointerEXT(GLenum texunit, GLint size, GLenum type, 25177ec681f3Smrg GLsizei stride, const GLvoid *ptr) 25187ec681f3Smrg{ 25197ec681f3Smrg GET_CURRENT_CONTEXT(ctx); 25207ec681f3Smrg const GLint sizeMin = 1; 25217ec681f3Smrg const GLuint unit = texunit - GL_TEXTURE0; 25227ec681f3Smrg 25237ec681f3Smrg GLenum format = GL_RGBA; 25247ec681f3Smrg const GLbitfield legalTypes = (SHORT_BIT | INT_BIT | 25257ec681f3Smrg HALF_BIT | FLOAT_BIT | DOUBLE_BIT | 25267ec681f3Smrg UNSIGNED_INT_2_10_10_10_REV_BIT | 25277ec681f3Smrg INT_2_10_10_10_REV_BIT); 25287ec681f3Smrg 25297ec681f3Smrg if (!validate_array_and_format(ctx, "glMultiTexCoordPointerEXT", 25307ec681f3Smrg ctx->Array.VAO, ctx->Array.ArrayBufferObj, 25317ec681f3Smrg VERT_ATTRIB_TEX(unit), legalTypes, 25327ec681f3Smrg sizeMin, 4, size, type, stride, 25337ec681f3Smrg GL_FALSE, GL_FALSE, GL_FALSE, format, ptr)) 25347ec681f3Smrg return; 25357ec681f3Smrg 25367ec681f3Smrg update_array(ctx, ctx->Array.VAO, ctx->Array.ArrayBufferObj, 25377ec681f3Smrg VERT_ATTRIB_TEX(unit), format, 4, size, type, 25387ec681f3Smrg stride, GL_FALSE, GL_FALSE, GL_FALSE, ptr); 25397ec681f3Smrg} 25407ec681f3Smrg 25417ec681f3Smrg 25427117f1b4Smrgvoid GLAPIENTRY 25437117f1b4Smrg_mesa_EdgeFlagPointerEXT(GLsizei stride, GLsizei count, const GLboolean *ptr) 25447117f1b4Smrg{ 25457117f1b4Smrg (void) count; 25467117f1b4Smrg _mesa_EdgeFlagPointer(stride, ptr); 25477117f1b4Smrg} 25487117f1b4Smrg 25497117f1b4Smrg 25507ec681f3Smrgbool 25517ec681f3Smrg_mesa_get_interleaved_layout(GLenum format, 25527ec681f3Smrg struct gl_interleaved_layout *layout) 25537117f1b4Smrg{ 25547ec681f3Smrg int f = sizeof(GLfloat); 25557ec681f3Smrg int c = f * ((4 * sizeof(GLubyte) + (f - 1)) / f); 25567117f1b4Smrg 25577ec681f3Smrg memset(layout, 0, sizeof(*layout)); 25587117f1b4Smrg 25597117f1b4Smrg switch (format) { 25607117f1b4Smrg case GL_V2F: 25617ec681f3Smrg layout->vcomps = 2; 25627ec681f3Smrg layout->defstride = 2 * f; 25637117f1b4Smrg break; 25647117f1b4Smrg case GL_V3F: 25657ec681f3Smrg layout->vcomps = 3; 25667ec681f3Smrg layout->defstride = 3 * f; 25677117f1b4Smrg break; 25687117f1b4Smrg case GL_C4UB_V2F: 25697ec681f3Smrg layout->cflag = true; 25707ec681f3Smrg layout->ccomps = 4; layout->vcomps = 2; 25717ec681f3Smrg layout->ctype = GL_UNSIGNED_BYTE; 25727ec681f3Smrg layout->voffset = c; 25737ec681f3Smrg layout->defstride = c + 2 * f; 25747117f1b4Smrg break; 25757117f1b4Smrg case GL_C4UB_V3F: 25767ec681f3Smrg layout->cflag = true; 25777ec681f3Smrg layout->ccomps = 4; layout->vcomps = 3; 25787ec681f3Smrg layout->ctype = GL_UNSIGNED_BYTE; 25797ec681f3Smrg layout->voffset = c; 25807ec681f3Smrg layout->defstride = c + 3 * f; 25817117f1b4Smrg break; 25827117f1b4Smrg case GL_C3F_V3F: 25837ec681f3Smrg layout->cflag = true; 25847ec681f3Smrg layout->ccomps = 3; layout->vcomps = 3; 25857ec681f3Smrg layout->ctype = GL_FLOAT; 25867ec681f3Smrg layout->voffset = 3 * f; 25877ec681f3Smrg layout->defstride = 6 * f; 25887117f1b4Smrg break; 25897117f1b4Smrg case GL_N3F_V3F: 25907ec681f3Smrg layout->nflag = true; 25917ec681f3Smrg layout->vcomps = 3; 25927ec681f3Smrg layout->voffset = 3 * f; 25937ec681f3Smrg layout->defstride = 6 * f; 25947117f1b4Smrg break; 25957117f1b4Smrg case GL_C4F_N3F_V3F: 25967ec681f3Smrg layout->cflag = true; layout->nflag = true; 25977ec681f3Smrg layout->ccomps = 4; layout->vcomps = 3; 25987ec681f3Smrg layout->ctype = GL_FLOAT; 25997ec681f3Smrg layout->noffset = 4 * f; 26007ec681f3Smrg layout->voffset = 7 * f; 26017ec681f3Smrg layout->defstride = 10 * f; 26027117f1b4Smrg break; 26037117f1b4Smrg case GL_T2F_V3F: 26047ec681f3Smrg layout->tflag = true; 26057ec681f3Smrg layout->tcomps = 2; layout->vcomps = 3; 26067ec681f3Smrg layout->voffset = 2 * f; 26077ec681f3Smrg layout->defstride = 5 * f; 26087117f1b4Smrg break; 26097117f1b4Smrg case GL_T4F_V4F: 26107ec681f3Smrg layout->tflag = true; 26117ec681f3Smrg layout->tcomps = 4; layout->vcomps = 4; 26127ec681f3Smrg layout->voffset = 4 * f; 26137ec681f3Smrg layout->defstride = 8 * f; 26147117f1b4Smrg break; 26157117f1b4Smrg case GL_T2F_C4UB_V3F: 26167ec681f3Smrg layout->tflag = true; layout->cflag = true; 26177ec681f3Smrg layout->tcomps = 2; layout->ccomps = 4; layout->vcomps = 3; 26187ec681f3Smrg layout->ctype = GL_UNSIGNED_BYTE; 26197ec681f3Smrg layout->coffset = 2 * f; 26207ec681f3Smrg layout->voffset = c + 2 * f; 26217ec681f3Smrg layout->defstride = c + 5 * f; 26227117f1b4Smrg break; 26237117f1b4Smrg case GL_T2F_C3F_V3F: 26247ec681f3Smrg layout->tflag = true; layout->cflag = true; 26257ec681f3Smrg layout->tcomps = 2; layout->ccomps = 3; layout->vcomps = 3; 26267ec681f3Smrg layout->ctype = GL_FLOAT; 26277ec681f3Smrg layout->coffset = 2 * f; 26287ec681f3Smrg layout->voffset = 5 * f; 26297ec681f3Smrg layout->defstride = 8 * f; 26307117f1b4Smrg break; 26317117f1b4Smrg case GL_T2F_N3F_V3F: 26327ec681f3Smrg layout->tflag = true; layout->nflag = true; 26337ec681f3Smrg layout->tcomps = 2; layout->vcomps = 3; 26347ec681f3Smrg layout->noffset = 2 * f; 26357ec681f3Smrg layout->voffset = 5 * f; 26367ec681f3Smrg layout->defstride = 8 * f; 26377117f1b4Smrg break; 26387117f1b4Smrg case GL_T2F_C4F_N3F_V3F: 26397ec681f3Smrg layout->tflag = true; layout->cflag = true; layout->nflag = true; 26407ec681f3Smrg layout->tcomps = 2; layout->ccomps = 4; layout->vcomps = 3; 26417ec681f3Smrg layout->ctype = GL_FLOAT; 26427ec681f3Smrg layout->coffset = 2 * f; 26437ec681f3Smrg layout->noffset = 6 * f; 26447ec681f3Smrg layout->voffset = 9 * f; 26457ec681f3Smrg layout->defstride = 12 * f; 26467117f1b4Smrg break; 26477117f1b4Smrg case GL_T4F_C4F_N3F_V4F: 26487ec681f3Smrg layout->tflag = true; layout->cflag = true; layout->nflag = true; 26497ec681f3Smrg layout->tcomps = 4; layout->ccomps = 4; layout->vcomps = 4; 26507ec681f3Smrg layout->ctype = GL_FLOAT; 26517ec681f3Smrg layout->coffset = 4 * f; 26527ec681f3Smrg layout->noffset = 8 * f; 26537ec681f3Smrg layout->voffset = 11 * f; 26547ec681f3Smrg layout->defstride = 15 * f; 26557117f1b4Smrg break; 26567117f1b4Smrg default: 26577ec681f3Smrg return false; 26587ec681f3Smrg } 26597ec681f3Smrg return true; 26607ec681f3Smrg} 26617ec681f3Smrg 26627ec681f3Smrgvoid GLAPIENTRY 26637ec681f3Smrg_mesa_InterleavedArrays(GLenum format, GLsizei stride, const GLvoid *pointer) 26647ec681f3Smrg{ 26657ec681f3Smrg GET_CURRENT_CONTEXT(ctx); 26667ec681f3Smrg struct gl_interleaved_layout layout; 26677ec681f3Smrg 26687ec681f3Smrg if (stride < 0) { 26697ec681f3Smrg _mesa_error( ctx, GL_INVALID_VALUE, "glInterleavedArrays(stride)" ); 26707ec681f3Smrg return; 26717ec681f3Smrg } 26727ec681f3Smrg 26737ec681f3Smrg if (!_mesa_get_interleaved_layout(format, &layout)) { 26747ec681f3Smrg _mesa_error( ctx, GL_INVALID_ENUM, "glInterleavedArrays(format)" ); 26757ec681f3Smrg return; 26767117f1b4Smrg } 26777117f1b4Smrg 26787117f1b4Smrg if (stride==0) { 26797ec681f3Smrg stride = layout.defstride; 26807117f1b4Smrg } 26817117f1b4Smrg 26827117f1b4Smrg _mesa_DisableClientState( GL_EDGE_FLAG_ARRAY ); 26837117f1b4Smrg _mesa_DisableClientState( GL_INDEX_ARRAY ); 26847117f1b4Smrg /* XXX also disable secondary color and generic arrays? */ 26857117f1b4Smrg 26867117f1b4Smrg /* Texcoords */ 26877ec681f3Smrg if (layout.tflag) { 26887117f1b4Smrg _mesa_EnableClientState( GL_TEXTURE_COORD_ARRAY ); 26897ec681f3Smrg _mesa_TexCoordPointer( layout.tcomps, GL_FLOAT, stride, 26907ec681f3Smrg (GLubyte *) pointer + layout.toffset ); 26917117f1b4Smrg } 26927117f1b4Smrg else { 26937117f1b4Smrg _mesa_DisableClientState( GL_TEXTURE_COORD_ARRAY ); 26947117f1b4Smrg } 26957117f1b4Smrg 26967117f1b4Smrg /* Color */ 26977ec681f3Smrg if (layout.cflag) { 26987117f1b4Smrg _mesa_EnableClientState( GL_COLOR_ARRAY ); 26997ec681f3Smrg _mesa_ColorPointer( layout.ccomps, layout.ctype, stride, 27007ec681f3Smrg (GLubyte *) pointer + layout.coffset ); 27017117f1b4Smrg } 27027117f1b4Smrg else { 27037117f1b4Smrg _mesa_DisableClientState( GL_COLOR_ARRAY ); 27047117f1b4Smrg } 27057117f1b4Smrg 27067117f1b4Smrg 27077117f1b4Smrg /* Normals */ 27087ec681f3Smrg if (layout.nflag) { 27097117f1b4Smrg _mesa_EnableClientState( GL_NORMAL_ARRAY ); 27107ec681f3Smrg _mesa_NormalPointer( GL_FLOAT, stride, (GLubyte *) pointer + layout.noffset ); 27117117f1b4Smrg } 27127117f1b4Smrg else { 27137117f1b4Smrg _mesa_DisableClientState( GL_NORMAL_ARRAY ); 27147117f1b4Smrg } 27157117f1b4Smrg 27167117f1b4Smrg /* Vertices */ 27177117f1b4Smrg _mesa_EnableClientState( GL_VERTEX_ARRAY ); 27187ec681f3Smrg _mesa_VertexPointer( layout.vcomps, GL_FLOAT, stride, 27197ec681f3Smrg (GLubyte *) pointer + layout.voffset ); 27207117f1b4Smrg} 27217117f1b4Smrg 27227117f1b4Smrg 27237117f1b4Smrgvoid GLAPIENTRY 27247117f1b4Smrg_mesa_LockArraysEXT(GLint first, GLsizei count) 27257117f1b4Smrg{ 27267117f1b4Smrg GET_CURRENT_CONTEXT(ctx); 2727af69d88dSmrg 27287117f1b4Smrg if (MESA_VERBOSE & VERBOSE_API) 27297117f1b4Smrg _mesa_debug(ctx, "glLockArrays %d %d\n", first, count); 27307117f1b4Smrg 2731c1f859d4Smrg if (first < 0) { 2732c1f859d4Smrg _mesa_error( ctx, GL_INVALID_VALUE, "glLockArraysEXT(first)" ); 2733c1f859d4Smrg return; 27347117f1b4Smrg } 2735c1f859d4Smrg if (count <= 0) { 2736c1f859d4Smrg _mesa_error( ctx, GL_INVALID_VALUE, "glLockArraysEXT(count)" ); 2737c1f859d4Smrg return; 2738c1f859d4Smrg } 2739c1f859d4Smrg if (ctx->Array.LockCount != 0) { 2740c1f859d4Smrg _mesa_error( ctx, GL_INVALID_OPERATION, "glLockArraysEXT(reentry)" ); 2741c1f859d4Smrg return; 27427117f1b4Smrg } 27437117f1b4Smrg 2744c1f859d4Smrg ctx->Array.LockFirst = first; 2745c1f859d4Smrg ctx->Array.LockCount = count; 27467117f1b4Smrg} 27477117f1b4Smrg 27487117f1b4Smrg 27497117f1b4Smrgvoid GLAPIENTRY 27507117f1b4Smrg_mesa_UnlockArraysEXT( void ) 27517117f1b4Smrg{ 27527117f1b4Smrg GET_CURRENT_CONTEXT(ctx); 2753af69d88dSmrg 27547117f1b4Smrg if (MESA_VERBOSE & VERBOSE_API) 27557117f1b4Smrg _mesa_debug(ctx, "glUnlockArrays\n"); 27567117f1b4Smrg 2757c1f859d4Smrg if (ctx->Array.LockCount == 0) { 2758c1f859d4Smrg _mesa_error( ctx, GL_INVALID_OPERATION, "glUnlockArraysEXT(reexit)" ); 2759c1f859d4Smrg return; 2760c1f859d4Smrg } 2761c1f859d4Smrg 27627117f1b4Smrg ctx->Array.LockFirst = 0; 27637117f1b4Smrg ctx->Array.LockCount = 0; 27647117f1b4Smrg} 27657117f1b4Smrg 27667117f1b4Smrg 276701e04c3fSmrgstatic void 276801e04c3fSmrgprimitive_restart_index(struct gl_context *ctx, GLuint index) 27697117f1b4Smrg{ 277001e04c3fSmrg ctx->Array.RestartIndex = index; 27717ec681f3Smrg _mesa_update_derived_primitive_restart_state(ctx); 27727117f1b4Smrg} 27737117f1b4Smrg 27747117f1b4Smrg 277501e04c3fSmrg/** 277601e04c3fSmrg * GL_NV_primitive_restart and GL 3.1 277701e04c3fSmrg */ 27787117f1b4Smrgvoid GLAPIENTRY 277901e04c3fSmrg_mesa_PrimitiveRestartIndex_no_error(GLuint index) 27807117f1b4Smrg{ 27817117f1b4Smrg GET_CURRENT_CONTEXT(ctx); 278201e04c3fSmrg primitive_restart_index(ctx, index); 27837117f1b4Smrg} 27847117f1b4Smrg 27857117f1b4Smrg 27867117f1b4Smrgvoid GLAPIENTRY 278701e04c3fSmrg_mesa_PrimitiveRestartIndex(GLuint index) 27887117f1b4Smrg{ 27897117f1b4Smrg GET_CURRENT_CONTEXT(ctx); 27907117f1b4Smrg 279101e04c3fSmrg if (!ctx->Extensions.NV_primitive_restart && ctx->Version < 31) { 279201e04c3fSmrg _mesa_error(ctx, GL_INVALID_OPERATION, "glPrimitiveRestartIndexNV()"); 279301e04c3fSmrg return; 27947117f1b4Smrg } 279501e04c3fSmrg 279601e04c3fSmrg primitive_restart_index(ctx, index); 27977117f1b4Smrg} 27987117f1b4Smrg 27997117f1b4Smrg 28003464ebd5Sriastradhvoid GLAPIENTRY 28017ec681f3Smrg_mesa_VertexAttribDivisor_no_error(GLuint index, GLuint divisor) 28027ec681f3Smrg{ 28037ec681f3Smrg GET_CURRENT_CONTEXT(ctx); 28047ec681f3Smrg 28057ec681f3Smrg const gl_vert_attrib genericIndex = VERT_ATTRIB_GENERIC(index); 28067ec681f3Smrg struct gl_vertex_array_object * const vao = ctx->Array.VAO; 28077ec681f3Smrg 28087ec681f3Smrg assert(genericIndex < ARRAY_SIZE(vao->VertexAttrib)); 28097ec681f3Smrg 28107ec681f3Smrg /* The ARB_vertex_attrib_binding spec says: 28117ec681f3Smrg * 28127ec681f3Smrg * "The command 28137ec681f3Smrg * 28147ec681f3Smrg * void VertexAttribDivisor(uint index, uint divisor); 28157ec681f3Smrg * 28167ec681f3Smrg * is equivalent to (assuming no errors are generated): 28177ec681f3Smrg * 28187ec681f3Smrg * VertexAttribBinding(index, index); 28197ec681f3Smrg * VertexBindingDivisor(index, divisor);" 28207ec681f3Smrg */ 28217ec681f3Smrg _mesa_vertex_attrib_binding(ctx, vao, genericIndex, genericIndex); 28227ec681f3Smrg vertex_binding_divisor(ctx, vao, genericIndex, divisor); 28237ec681f3Smrg} 28247ec681f3Smrg 28257ec681f3Smrg 28267ec681f3Smrg/** 28277ec681f3Smrg * See GL_ARB_instanced_arrays. 28287ec681f3Smrg * Note that the instance divisor only applies to generic arrays, not 28297ec681f3Smrg * the legacy vertex arrays. 28307ec681f3Smrg */ 28317ec681f3Smrgvoid GLAPIENTRY 28327ec681f3Smrg_mesa_VertexAttribDivisor(GLuint index, GLuint divisor) 28333464ebd5Sriastradh{ 28343464ebd5Sriastradh GET_CURRENT_CONTEXT(ctx); 28353464ebd5Sriastradh 283601e04c3fSmrg const gl_vert_attrib genericIndex = VERT_ATTRIB_GENERIC(index); 283701e04c3fSmrg struct gl_vertex_array_object * const vao = ctx->Array.VAO; 28383464ebd5Sriastradh 28397ec681f3Smrg if (!ctx->Extensions.ARB_instanced_arrays) { 28407ec681f3Smrg _mesa_error(ctx, GL_INVALID_OPERATION, "glVertexAttribDivisor()"); 28417ec681f3Smrg return; 28427ec681f3Smrg } 28437ec681f3Smrg 28447ec681f3Smrg if (index >= ctx->Const.Program[MESA_SHADER_VERTEX].MaxAttribs) { 28457ec681f3Smrg _mesa_error(ctx, GL_INVALID_VALUE, 28467ec681f3Smrg "glVertexAttribDivisor(index = %u)", index); 28477ec681f3Smrg return; 28487ec681f3Smrg } 28497ec681f3Smrg 285001e04c3fSmrg assert(genericIndex < ARRAY_SIZE(vao->VertexAttrib)); 285101e04c3fSmrg 285201e04c3fSmrg /* The ARB_vertex_attrib_binding spec says: 285301e04c3fSmrg * 285401e04c3fSmrg * "The command 285501e04c3fSmrg * 285601e04c3fSmrg * void VertexAttribDivisor(uint index, uint divisor); 285701e04c3fSmrg * 285801e04c3fSmrg * is equivalent to (assuming no errors are generated): 285901e04c3fSmrg * 286001e04c3fSmrg * VertexAttribBinding(index, index); 286101e04c3fSmrg * VertexBindingDivisor(index, divisor);" 286201e04c3fSmrg */ 286301e04c3fSmrg _mesa_vertex_attrib_binding(ctx, vao, genericIndex, genericIndex); 286401e04c3fSmrg vertex_binding_divisor(ctx, vao, genericIndex, divisor); 28653464ebd5Sriastradh} 28663464ebd5Sriastradh 28673464ebd5Sriastradh 28683464ebd5Sriastradhvoid GLAPIENTRY 28697ec681f3Smrg_mesa_VertexArrayVertexAttribDivisorEXT(GLuint vaobj, GLuint index, GLuint divisor) 28703464ebd5Sriastradh{ 28713464ebd5Sriastradh GET_CURRENT_CONTEXT(ctx); 2872af69d88dSmrg 287301e04c3fSmrg const gl_vert_attrib genericIndex = VERT_ATTRIB_GENERIC(index); 28747ec681f3Smrg struct gl_vertex_array_object * vao; 28757ec681f3Smrg /* The ARB_instanced_arrays spec says: 28767ec681f3Smrg * 28777ec681f3Smrg * "The vertex array object named by vaobj must 28787ec681f3Smrg * be generated by GenVertexArrays (and not since deleted); 28797ec681f3Smrg * otherwise an INVALID_OPERATION error is generated." 28807ec681f3Smrg */ 28817ec681f3Smrg vao = _mesa_lookup_vao_err(ctx, vaobj, 28827ec681f3Smrg false, 28837ec681f3Smrg "glVertexArrayVertexAttribDivisorEXT"); 28847ec681f3Smrg if (!vao) 28857ec681f3Smrg return; 28863464ebd5Sriastradh 28873464ebd5Sriastradh if (!ctx->Extensions.ARB_instanced_arrays) { 28887ec681f3Smrg _mesa_error(ctx, GL_INVALID_OPERATION, "glVertexArrayVertexAttribDivisorEXT()"); 28893464ebd5Sriastradh return; 28903464ebd5Sriastradh } 28913464ebd5Sriastradh 2892af69d88dSmrg if (index >= ctx->Const.Program[MESA_SHADER_VERTEX].MaxAttribs) { 289301e04c3fSmrg _mesa_error(ctx, GL_INVALID_VALUE, 28947ec681f3Smrg "glVertexArrayVertexAttribDivisorEXT(index = %u)", index); 28953464ebd5Sriastradh return; 28963464ebd5Sriastradh } 28973464ebd5Sriastradh 289801e04c3fSmrg assert(genericIndex < ARRAY_SIZE(vao->VertexAttrib)); 2899af69d88dSmrg 2900af69d88dSmrg /* The ARB_vertex_attrib_binding spec says: 2901af69d88dSmrg * 2902af69d88dSmrg * "The command 2903af69d88dSmrg * 2904af69d88dSmrg * void VertexAttribDivisor(uint index, uint divisor); 2905af69d88dSmrg * 2906af69d88dSmrg * is equivalent to (assuming no errors are generated): 2907af69d88dSmrg * 2908af69d88dSmrg * VertexAttribBinding(index, index); 2909af69d88dSmrg * VertexBindingDivisor(index, divisor);" 2910af69d88dSmrg */ 291101e04c3fSmrg _mesa_vertex_attrib_binding(ctx, vao, genericIndex, genericIndex); 291201e04c3fSmrg vertex_binding_divisor(ctx, vao, genericIndex, divisor); 2913af69d88dSmrg} 2914af69d88dSmrg 2915af69d88dSmrg 29167ec681f3Smrg 291701e04c3fSmrgstatic ALWAYS_INLINE void 291801e04c3fSmrgvertex_array_vertex_buffer(struct gl_context *ctx, 291901e04c3fSmrg struct gl_vertex_array_object *vao, 292001e04c3fSmrg GLuint bindingIndex, GLuint buffer, GLintptr offset, 292101e04c3fSmrg GLsizei stride, bool no_error, const char *func) 2922af69d88dSmrg{ 2923af69d88dSmrg struct gl_buffer_object *vbo; 29247ec681f3Smrg struct gl_buffer_object *current_buf = 29257ec681f3Smrg vao->BufferBinding[VERT_ATTRIB_GENERIC(bindingIndex)].BufferObj; 29267ec681f3Smrg 29277ec681f3Smrg if (current_buf && buffer == current_buf->Name) { 29287ec681f3Smrg vbo = current_buf; 292901e04c3fSmrg } else if (buffer != 0) { 293001e04c3fSmrg vbo = _mesa_lookup_bufferobj(ctx, buffer); 2931af69d88dSmrg 293201e04c3fSmrg if (!no_error && !vbo && _mesa_is_gles31(ctx)) { 293301e04c3fSmrg _mesa_error(ctx, GL_INVALID_OPERATION, "%s(non-gen name)", func); 293401e04c3fSmrg return; 293501e04c3fSmrg } 293601e04c3fSmrg /* From the GL_ARB_vertex_attrib_array spec: 293701e04c3fSmrg * 293801e04c3fSmrg * "[Core profile only:] 293901e04c3fSmrg * An INVALID_OPERATION error is generated if buffer is not zero or a 294001e04c3fSmrg * name returned from a previous call to GenBuffers, or if such a name 294101e04c3fSmrg * has since been deleted with DeleteBuffers. 294201e04c3fSmrg * 294301e04c3fSmrg * Otherwise, we fall back to the same compat profile behavior as other 294401e04c3fSmrg * object references (automatically gen it). 294501e04c3fSmrg */ 294601e04c3fSmrg if (!_mesa_handle_bind_buffer_gen(ctx, buffer, &vbo, func)) 294701e04c3fSmrg return; 294801e04c3fSmrg } else { 294901e04c3fSmrg /* The ARB_vertex_attrib_binding spec says: 295001e04c3fSmrg * 295101e04c3fSmrg * "If <buffer> is zero, any buffer object attached to this 295201e04c3fSmrg * bindpoint is detached." 295301e04c3fSmrg */ 29547ec681f3Smrg vbo = NULL; 2955af69d88dSmrg } 2956af69d88dSmrg 295701e04c3fSmrg _mesa_bind_vertex_buffer(ctx, vao, VERT_ATTRIB_GENERIC(bindingIndex), 29587ec681f3Smrg vbo, offset, stride, false, false); 295901e04c3fSmrg} 296001e04c3fSmrg 296101e04c3fSmrg 296201e04c3fSmrg/** 296301e04c3fSmrg * GL_ARB_vertex_attrib_binding 296401e04c3fSmrg */ 296501e04c3fSmrgstatic void 296601e04c3fSmrgvertex_array_vertex_buffer_err(struct gl_context *ctx, 296701e04c3fSmrg struct gl_vertex_array_object *vao, 296801e04c3fSmrg GLuint bindingIndex, GLuint buffer, 296901e04c3fSmrg GLintptr offset, GLsizei stride, 297001e04c3fSmrg const char *func) 297101e04c3fSmrg{ 297201e04c3fSmrg ASSERT_OUTSIDE_BEGIN_END(ctx); 297301e04c3fSmrg 2974af69d88dSmrg /* The ARB_vertex_attrib_binding spec says: 2975af69d88dSmrg * 2976af69d88dSmrg * "An INVALID_VALUE error is generated if <bindingindex> is greater than 2977af69d88dSmrg * the value of MAX_VERTEX_ATTRIB_BINDINGS." 2978af69d88dSmrg */ 2979af69d88dSmrg if (bindingIndex >= ctx->Const.MaxVertexAttribBindings) { 2980af69d88dSmrg _mesa_error(ctx, GL_INVALID_VALUE, 298101e04c3fSmrg "%s(bindingindex=%u > " 2982af69d88dSmrg "GL_MAX_VERTEX_ATTRIB_BINDINGS)", 298301e04c3fSmrg func, bindingIndex); 2984af69d88dSmrg return; 2985af69d88dSmrg } 2986af69d88dSmrg 2987af69d88dSmrg /* The ARB_vertex_attrib_binding spec says: 2988af69d88dSmrg * 2989af69d88dSmrg * "The error INVALID_VALUE is generated if <stride> or <offset> 2990af69d88dSmrg * are negative." 2991af69d88dSmrg */ 2992af69d88dSmrg if (offset < 0) { 2993af69d88dSmrg _mesa_error(ctx, GL_INVALID_VALUE, 299401e04c3fSmrg "%s(offset=%" PRId64 " < 0)", 299501e04c3fSmrg func, (int64_t) offset); 2996af69d88dSmrg return; 2997af69d88dSmrg } 2998af69d88dSmrg 2999af69d88dSmrg if (stride < 0) { 3000af69d88dSmrg _mesa_error(ctx, GL_INVALID_VALUE, 300101e04c3fSmrg "%s(stride=%d < 0)", func, stride); 3002af69d88dSmrg return; 3003af69d88dSmrg } 3004af69d88dSmrg 300501e04c3fSmrg if (((_mesa_is_desktop_gl(ctx) && ctx->Version >= 44) || _mesa_is_gles31(ctx)) && 300601e04c3fSmrg stride > ctx->Const.MaxVertexAttribStride) { 300701e04c3fSmrg _mesa_error(ctx, GL_INVALID_VALUE, "%s(stride=%d > " 300801e04c3fSmrg "GL_MAX_VERTEX_ATTRIB_STRIDE)", func, stride); 300901e04c3fSmrg return; 3010af69d88dSmrg } 3011af69d88dSmrg 301201e04c3fSmrg vertex_array_vertex_buffer(ctx, vao, bindingIndex, buffer, offset, 301301e04c3fSmrg stride, false, func); 3014af69d88dSmrg} 3015af69d88dSmrg 3016af69d88dSmrg 3017af69d88dSmrgvoid GLAPIENTRY 301801e04c3fSmrg_mesa_BindVertexBuffer_no_error(GLuint bindingIndex, GLuint buffer, 301901e04c3fSmrg GLintptr offset, GLsizei stride) 3020af69d88dSmrg{ 3021af69d88dSmrg GET_CURRENT_CONTEXT(ctx); 302201e04c3fSmrg vertex_array_vertex_buffer(ctx, ctx->Array.VAO, bindingIndex, 302301e04c3fSmrg buffer, offset, stride, true, 302401e04c3fSmrg "glBindVertexBuffer"); 302501e04c3fSmrg} 3026af69d88dSmrg 302701e04c3fSmrg 302801e04c3fSmrgvoid GLAPIENTRY 302901e04c3fSmrg_mesa_BindVertexBuffer(GLuint bindingIndex, GLuint buffer, GLintptr offset, 303001e04c3fSmrg GLsizei stride) 303101e04c3fSmrg{ 303201e04c3fSmrg GET_CURRENT_CONTEXT(ctx); 3033af69d88dSmrg 3034af69d88dSmrg /* The ARB_vertex_attrib_binding spec says: 3035af69d88dSmrg * 303601e04c3fSmrg * "An INVALID_OPERATION error is generated if no vertex array object 303701e04c3fSmrg * is bound." 3038af69d88dSmrg */ 303901e04c3fSmrg if ((ctx->API == API_OPENGL_CORE || _mesa_is_gles31(ctx)) && 3040af69d88dSmrg ctx->Array.VAO == ctx->Array.DefaultVAO) { 3041af69d88dSmrg _mesa_error(ctx, GL_INVALID_OPERATION, 304201e04c3fSmrg "glBindVertexBuffer(No array object bound)"); 3043af69d88dSmrg return; 3044af69d88dSmrg } 3045af69d88dSmrg 304601e04c3fSmrg vertex_array_vertex_buffer_err(ctx, ctx->Array.VAO, bindingIndex, 304701e04c3fSmrg buffer, offset, stride, 304801e04c3fSmrg "glBindVertexBuffer"); 304901e04c3fSmrg} 305001e04c3fSmrg 305101e04c3fSmrg 305201e04c3fSmrgvoid GLAPIENTRY 305301e04c3fSmrg_mesa_VertexArrayVertexBuffer_no_error(GLuint vaobj, GLuint bindingIndex, 305401e04c3fSmrg GLuint buffer, GLintptr offset, 305501e04c3fSmrg GLsizei stride) 305601e04c3fSmrg{ 305701e04c3fSmrg GET_CURRENT_CONTEXT(ctx); 305801e04c3fSmrg 305901e04c3fSmrg struct gl_vertex_array_object *vao = _mesa_lookup_vao(ctx, vaobj); 306001e04c3fSmrg vertex_array_vertex_buffer(ctx, vao, bindingIndex, buffer, offset, 306101e04c3fSmrg stride, true, "glVertexArrayVertexBuffer"); 306201e04c3fSmrg} 306301e04c3fSmrg 306401e04c3fSmrg 306501e04c3fSmrgvoid GLAPIENTRY 306601e04c3fSmrg_mesa_VertexArrayVertexBuffer(GLuint vaobj, GLuint bindingIndex, GLuint buffer, 306701e04c3fSmrg GLintptr offset, GLsizei stride) 306801e04c3fSmrg{ 306901e04c3fSmrg GET_CURRENT_CONTEXT(ctx); 307001e04c3fSmrg struct gl_vertex_array_object *vao; 307101e04c3fSmrg 307201e04c3fSmrg /* The ARB_direct_state_access specification says: 3073af69d88dSmrg * 307401e04c3fSmrg * "An INVALID_OPERATION error is generated by VertexArrayVertexBuffer 307501e04c3fSmrg * if <vaobj> is not [compatibility profile: zero or] the name of an 307601e04c3fSmrg * existing vertex array object." 3077af69d88dSmrg */ 30787ec681f3Smrg vao = _mesa_lookup_vao_err(ctx, vaobj, false, "glVertexArrayVertexBuffer"); 307901e04c3fSmrg if (!vao) 3080af69d88dSmrg return; 308101e04c3fSmrg 308201e04c3fSmrg vertex_array_vertex_buffer_err(ctx, vao, bindingIndex, buffer, offset, 308301e04c3fSmrg stride, "glVertexArrayVertexBuffer"); 308401e04c3fSmrg} 308501e04c3fSmrg 308601e04c3fSmrg 30877ec681f3Smrgvoid GLAPIENTRY 30887ec681f3Smrg_mesa_VertexArrayBindVertexBufferEXT(GLuint vaobj, GLuint bindingIndex, GLuint buffer, 30897ec681f3Smrg GLintptr offset, GLsizei stride) 30907ec681f3Smrg{ 30917ec681f3Smrg GET_CURRENT_CONTEXT(ctx); 30927ec681f3Smrg struct gl_vertex_array_object *vao; 30937ec681f3Smrg vao = _mesa_lookup_vao_err(ctx, vaobj, true, "glVertexArrayBindVertexBufferEXT"); 30947ec681f3Smrg if (!vao) 30957ec681f3Smrg return; 30967ec681f3Smrg 30977ec681f3Smrg vertex_array_vertex_buffer_err(ctx, vao, bindingIndex, buffer, offset, 30987ec681f3Smrg stride, "glVertexArrayBindVertexBufferEXT"); 30997ec681f3Smrg} 31007ec681f3Smrg 31017ec681f3Smrg 310201e04c3fSmrgstatic ALWAYS_INLINE void 310301e04c3fSmrgvertex_array_vertex_buffers(struct gl_context *ctx, 310401e04c3fSmrg struct gl_vertex_array_object *vao, 310501e04c3fSmrg GLuint first, GLsizei count, const GLuint *buffers, 310601e04c3fSmrg const GLintptr *offsets, const GLsizei *strides, 310701e04c3fSmrg bool no_error, const char *func) 310801e04c3fSmrg{ 310901e04c3fSmrg GLint i; 3110af69d88dSmrg 3111af69d88dSmrg if (!buffers) { 3112af69d88dSmrg /** 3113af69d88dSmrg * The ARB_multi_bind spec says: 3114af69d88dSmrg * 3115af69d88dSmrg * "If <buffers> is NULL, each affected vertex buffer binding point 3116af69d88dSmrg * from <first> through <first>+<count>-1 will be reset to have no 3117af69d88dSmrg * bound buffer object. In this case, the offsets and strides 3118af69d88dSmrg * associated with the binding points are set to default values, 3119af69d88dSmrg * ignoring <offsets> and <strides>." 3120af69d88dSmrg */ 3121af69d88dSmrg for (i = 0; i < count; i++) 312201e04c3fSmrg _mesa_bind_vertex_buffer(ctx, vao, VERT_ATTRIB_GENERIC(first + i), 31237ec681f3Smrg NULL, 0, 16, false, false); 3124af69d88dSmrg 3125af69d88dSmrg return; 3126af69d88dSmrg } 3127af69d88dSmrg 3128af69d88dSmrg /* Note that the error semantics for multi-bind commands differ from 3129af69d88dSmrg * those of other GL commands. 3130af69d88dSmrg * 3131af69d88dSmrg * The Issues section in the ARB_multi_bind spec says: 3132af69d88dSmrg * 3133af69d88dSmrg * "(11) Typically, OpenGL specifies that if an error is generated by 3134af69d88dSmrg * a command, that command has no effect. This is somewhat 3135af69d88dSmrg * unfortunate for multi-bind commands, because it would require 3136af69d88dSmrg * a first pass to scan the entire list of bound objects for 3137af69d88dSmrg * errors and then a second pass to actually perform the 3138af69d88dSmrg * bindings. Should we have different error semantics? 3139af69d88dSmrg * 3140af69d88dSmrg * RESOLVED: Yes. In this specification, when the parameters for 3141af69d88dSmrg * one of the <count> binding points are invalid, that binding 3142af69d88dSmrg * point is not updated and an error will be generated. However, 3143af69d88dSmrg * other binding points in the same command will be updated if 3144af69d88dSmrg * their parameters are valid and no other error occurs." 3145af69d88dSmrg */ 3146af69d88dSmrg 31477ec681f3Smrg _mesa_HashLockMaybeLocked(ctx->Shared->BufferObjects, 31487ec681f3Smrg ctx->BufferObjectsLocked); 3149af69d88dSmrg 3150af69d88dSmrg for (i = 0; i < count; i++) { 3151af69d88dSmrg struct gl_buffer_object *vbo; 3152af69d88dSmrg 315301e04c3fSmrg if (!no_error) { 315401e04c3fSmrg /* The ARB_multi_bind spec says: 315501e04c3fSmrg * 315601e04c3fSmrg * "An INVALID_VALUE error is generated if any value in 315701e04c3fSmrg * <offsets> or <strides> is negative (per binding)." 315801e04c3fSmrg */ 315901e04c3fSmrg if (offsets[i] < 0) { 316001e04c3fSmrg _mesa_error(ctx, GL_INVALID_VALUE, 316101e04c3fSmrg "%s(offsets[%u]=%" PRId64 " < 0)", 316201e04c3fSmrg func, i, (int64_t) offsets[i]); 316301e04c3fSmrg continue; 316401e04c3fSmrg } 3165af69d88dSmrg 316601e04c3fSmrg if (strides[i] < 0) { 316701e04c3fSmrg _mesa_error(ctx, GL_INVALID_VALUE, 316801e04c3fSmrg "%s(strides[%u]=%d < 0)", 316901e04c3fSmrg func, i, strides[i]); 317001e04c3fSmrg continue; 317101e04c3fSmrg } 317201e04c3fSmrg 317301e04c3fSmrg if (_mesa_is_desktop_gl(ctx) && ctx->Version >= 44 && 317401e04c3fSmrg strides[i] > ctx->Const.MaxVertexAttribStride) { 317501e04c3fSmrg _mesa_error(ctx, GL_INVALID_VALUE, 317601e04c3fSmrg "%s(strides[%u]=%d > " 317701e04c3fSmrg "GL_MAX_VERTEX_ATTRIB_STRIDE)", func, i, strides[i]); 317801e04c3fSmrg continue; 317901e04c3fSmrg } 3180af69d88dSmrg } 3181af69d88dSmrg 3182af69d88dSmrg if (buffers[i]) { 3183af69d88dSmrg struct gl_vertex_buffer_binding *binding = 318401e04c3fSmrg &vao->BufferBinding[VERT_ATTRIB_GENERIC(first + i)]; 3185af69d88dSmrg 31867ec681f3Smrg if (buffers[i] == 0) 31877ec681f3Smrg vbo = NULL; 31887ec681f3Smrg else if (binding->BufferObj && binding->BufferObj->Name == buffers[i]) 3189af69d88dSmrg vbo = binding->BufferObj; 31907ec681f3Smrg else { 31917ec681f3Smrg bool error; 31927ec681f3Smrg vbo = _mesa_multi_bind_lookup_bufferobj(ctx, buffers, i, func, 31937ec681f3Smrg &error); 31947ec681f3Smrg if (error) 31957ec681f3Smrg continue; 31967ec681f3Smrg } 3197af69d88dSmrg } else { 31987ec681f3Smrg vbo = NULL; 3199af69d88dSmrg } 3200af69d88dSmrg 320101e04c3fSmrg _mesa_bind_vertex_buffer(ctx, vao, VERT_ATTRIB_GENERIC(first + i), 32027ec681f3Smrg vbo, offsets[i], strides[i], false, false); 3203af69d88dSmrg } 3204af69d88dSmrg 32057ec681f3Smrg _mesa_HashUnlockMaybeLocked(ctx->Shared->BufferObjects, 32067ec681f3Smrg ctx->BufferObjectsLocked); 3207af69d88dSmrg} 3208af69d88dSmrg 3209af69d88dSmrg 321001e04c3fSmrgstatic void 321101e04c3fSmrgvertex_array_vertex_buffers_err(struct gl_context *ctx, 321201e04c3fSmrg struct gl_vertex_array_object *vao, 321301e04c3fSmrg GLuint first, GLsizei count, 321401e04c3fSmrg const GLuint *buffers, const GLintptr *offsets, 321501e04c3fSmrg const GLsizei *strides, const char *func) 3216af69d88dSmrg{ 3217af69d88dSmrg ASSERT_OUTSIDE_BEGIN_END(ctx); 3218af69d88dSmrg 321901e04c3fSmrg /* The ARB_multi_bind spec says: 3220af69d88dSmrg * 322101e04c3fSmrg * "An INVALID_OPERATION error is generated if <first> + <count> 322201e04c3fSmrg * is greater than the value of MAX_VERTEX_ATTRIB_BINDINGS." 3223af69d88dSmrg */ 322401e04c3fSmrg if (first + count > ctx->Const.MaxVertexAttribBindings) { 3225af69d88dSmrg _mesa_error(ctx, GL_INVALID_OPERATION, 322601e04c3fSmrg "%s(first=%u + count=%d > the value of " 322701e04c3fSmrg "GL_MAX_VERTEX_ATTRIB_BINDINGS=%u)", 322801e04c3fSmrg func, first, count, ctx->Const.MaxVertexAttribBindings); 3229af69d88dSmrg return; 3230af69d88dSmrg } 3231af69d88dSmrg 323201e04c3fSmrg vertex_array_vertex_buffers(ctx, vao, first, count, buffers, offsets, 323301e04c3fSmrg strides, false, func); 323401e04c3fSmrg} 323501e04c3fSmrg 3236af69d88dSmrg 323701e04c3fSmrgvoid GLAPIENTRY 323801e04c3fSmrg_mesa_BindVertexBuffers_no_error(GLuint first, GLsizei count, 323901e04c3fSmrg const GLuint *buffers, const GLintptr *offsets, 324001e04c3fSmrg const GLsizei *strides) 324101e04c3fSmrg{ 324201e04c3fSmrg GET_CURRENT_CONTEXT(ctx); 3243af69d88dSmrg 324401e04c3fSmrg vertex_array_vertex_buffers(ctx, ctx->Array.VAO, first, count, 324501e04c3fSmrg buffers, offsets, strides, true, 324601e04c3fSmrg "glBindVertexBuffers"); 3247af69d88dSmrg} 3248af69d88dSmrg 3249af69d88dSmrg 3250af69d88dSmrgvoid GLAPIENTRY 325101e04c3fSmrg_mesa_BindVertexBuffers(GLuint first, GLsizei count, const GLuint *buffers, 325201e04c3fSmrg const GLintptr *offsets, const GLsizei *strides) 3253af69d88dSmrg{ 3254af69d88dSmrg GET_CURRENT_CONTEXT(ctx); 3255af69d88dSmrg 3256af69d88dSmrg /* The ARB_vertex_attrib_binding spec says: 3257af69d88dSmrg * 325801e04c3fSmrg * "An INVALID_OPERATION error is generated if no 325901e04c3fSmrg * vertex array object is bound." 3260af69d88dSmrg */ 3261af69d88dSmrg if (ctx->API == API_OPENGL_CORE && 3262af69d88dSmrg ctx->Array.VAO == ctx->Array.DefaultVAO) { 3263af69d88dSmrg _mesa_error(ctx, GL_INVALID_OPERATION, 326401e04c3fSmrg "glBindVertexBuffers(No array object bound)"); 3265af69d88dSmrg return; 3266af69d88dSmrg } 3267af69d88dSmrg 326801e04c3fSmrg vertex_array_vertex_buffers_err(ctx, ctx->Array.VAO, first, count, 326901e04c3fSmrg buffers, offsets, strides, 327001e04c3fSmrg "glBindVertexBuffers"); 327101e04c3fSmrg} 327201e04c3fSmrg 327301e04c3fSmrg 32747ec681f3Smrgvoid 32757ec681f3Smrg_mesa_InternalBindVertexBuffers(struct gl_context *ctx, 32767ec681f3Smrg const struct glthread_attrib_binding *buffers, 32777ec681f3Smrg GLbitfield buffer_mask, 32787ec681f3Smrg GLboolean restore_pointers) 32797ec681f3Smrg{ 32807ec681f3Smrg struct gl_vertex_array_object *vao = ctx->Array.VAO; 32817ec681f3Smrg unsigned param_index = 0; 32827ec681f3Smrg 32837ec681f3Smrg if (restore_pointers) { 32847ec681f3Smrg while (buffer_mask) { 32857ec681f3Smrg unsigned i = u_bit_scan(&buffer_mask); 32867ec681f3Smrg 32877ec681f3Smrg _mesa_bind_vertex_buffer(ctx, vao, i, NULL, 32887ec681f3Smrg (GLintptr)buffers[param_index].original_pointer, 32897ec681f3Smrg vao->BufferBinding[i].Stride, false, false); 32907ec681f3Smrg param_index++; 32917ec681f3Smrg } 32927ec681f3Smrg return; 32937ec681f3Smrg } 32947ec681f3Smrg 32957ec681f3Smrg while (buffer_mask) { 32967ec681f3Smrg unsigned i = u_bit_scan(&buffer_mask); 32977ec681f3Smrg struct gl_buffer_object *buf = buffers[param_index].buffer; 32987ec681f3Smrg 32997ec681f3Smrg /* The buffer reference is passed to _mesa_bind_vertex_buffer. */ 33007ec681f3Smrg _mesa_bind_vertex_buffer(ctx, vao, i, buf, buffers[param_index].offset, 33017ec681f3Smrg vao->BufferBinding[i].Stride, true, true); 33027ec681f3Smrg param_index++; 33037ec681f3Smrg } 33047ec681f3Smrg} 33057ec681f3Smrg 33067ec681f3Smrg 330701e04c3fSmrgvoid GLAPIENTRY 330801e04c3fSmrg_mesa_VertexArrayVertexBuffers_no_error(GLuint vaobj, GLuint first, 330901e04c3fSmrg GLsizei count, const GLuint *buffers, 331001e04c3fSmrg const GLintptr *offsets, 331101e04c3fSmrg const GLsizei *strides) 331201e04c3fSmrg{ 331301e04c3fSmrg GET_CURRENT_CONTEXT(ctx); 331401e04c3fSmrg 331501e04c3fSmrg struct gl_vertex_array_object *vao = _mesa_lookup_vao(ctx, vaobj); 331601e04c3fSmrg vertex_array_vertex_buffers(ctx, vao, first, count, 331701e04c3fSmrg buffers, offsets, strides, true, 331801e04c3fSmrg "glVertexArrayVertexBuffers"); 331901e04c3fSmrg} 332001e04c3fSmrg 332101e04c3fSmrg 332201e04c3fSmrgvoid GLAPIENTRY 332301e04c3fSmrg_mesa_VertexArrayVertexBuffers(GLuint vaobj, GLuint first, GLsizei count, 332401e04c3fSmrg const GLuint *buffers, 332501e04c3fSmrg const GLintptr *offsets, const GLsizei *strides) 332601e04c3fSmrg{ 332701e04c3fSmrg GET_CURRENT_CONTEXT(ctx); 332801e04c3fSmrg struct gl_vertex_array_object *vao; 332901e04c3fSmrg 333001e04c3fSmrg /* The ARB_direct_state_access specification says: 3331af69d88dSmrg * 333201e04c3fSmrg * "An INVALID_OPERATION error is generated by VertexArrayVertexBuffer 333301e04c3fSmrg * if <vaobj> is not [compatibility profile: zero or] the name of an 333401e04c3fSmrg * existing vertex array object." 3335af69d88dSmrg */ 33367ec681f3Smrg vao = _mesa_lookup_vao_err(ctx, vaobj, false, "glVertexArrayVertexBuffers"); 333701e04c3fSmrg if (!vao) 3338af69d88dSmrg return; 333901e04c3fSmrg 334001e04c3fSmrg vertex_array_vertex_buffers_err(ctx, vao, first, count, 334101e04c3fSmrg buffers, offsets, strides, 334201e04c3fSmrg "glVertexArrayVertexBuffers"); 334301e04c3fSmrg} 334401e04c3fSmrg 334501e04c3fSmrg 334601e04c3fSmrgstatic void 334701e04c3fSmrgvertex_attrib_format(GLuint attribIndex, GLint size, GLenum type, 334801e04c3fSmrg GLboolean normalized, GLboolean integer, 334901e04c3fSmrg GLboolean doubles, GLbitfield legalTypes, 335001e04c3fSmrg GLsizei sizeMax, GLuint relativeOffset, 335101e04c3fSmrg const char *func) 335201e04c3fSmrg{ 335301e04c3fSmrg GET_CURRENT_CONTEXT(ctx); 335401e04c3fSmrg ASSERT_OUTSIDE_BEGIN_END(ctx); 335501e04c3fSmrg 335601e04c3fSmrg GLenum format = get_array_format(ctx, sizeMax, &size); 335701e04c3fSmrg 335801e04c3fSmrg if (!_mesa_is_no_error_enabled(ctx)) { 335901e04c3fSmrg /* The ARB_vertex_attrib_binding spec says: 336001e04c3fSmrg * 336101e04c3fSmrg * "An INVALID_OPERATION error is generated under any of the 336201e04c3fSmrg * following conditions: 336301e04c3fSmrg * - if no vertex array object is currently bound (see section 336401e04c3fSmrg * 2.10); 336501e04c3fSmrg * - ..." 336601e04c3fSmrg * 336701e04c3fSmrg * This error condition only applies to VertexAttribFormat and 336801e04c3fSmrg * VertexAttribIFormat in the extension spec, but we assume that this 336901e04c3fSmrg * is an oversight. In the OpenGL 4.3 (Core Profile) spec, it applies 337001e04c3fSmrg * to all three functions. 337101e04c3fSmrg */ 337201e04c3fSmrg if ((ctx->API == API_OPENGL_CORE || _mesa_is_gles31(ctx)) && 337301e04c3fSmrg ctx->Array.VAO == ctx->Array.DefaultVAO) { 337401e04c3fSmrg _mesa_error(ctx, GL_INVALID_OPERATION, 337501e04c3fSmrg "%s(No array object bound)", func); 337601e04c3fSmrg return; 337701e04c3fSmrg } 337801e04c3fSmrg 337901e04c3fSmrg /* The ARB_vertex_attrib_binding spec says: 338001e04c3fSmrg * 338101e04c3fSmrg * "The error INVALID_VALUE is generated if index is greater than or 338201e04c3fSmrg * equal to the value of MAX_VERTEX_ATTRIBS." 338301e04c3fSmrg */ 338401e04c3fSmrg if (attribIndex >= ctx->Const.Program[MESA_SHADER_VERTEX].MaxAttribs) { 338501e04c3fSmrg _mesa_error(ctx, GL_INVALID_VALUE, 338601e04c3fSmrg "%s(attribindex=%u > " 338701e04c3fSmrg "GL_MAX_VERTEX_ATTRIBS)", 338801e04c3fSmrg func, attribIndex); 338901e04c3fSmrg return; 339001e04c3fSmrg } 339101e04c3fSmrg 339201e04c3fSmrg if (!validate_array_format(ctx, func, ctx->Array.VAO, 339301e04c3fSmrg VERT_ATTRIB_GENERIC(attribIndex), 339401e04c3fSmrg legalTypes, 1, sizeMax, size, type, 339501e04c3fSmrg normalized, integer, doubles, relativeOffset, 339601e04c3fSmrg format)) { 339701e04c3fSmrg return; 339801e04c3fSmrg } 3399af69d88dSmrg } 3400af69d88dSmrg 340101e04c3fSmrg _mesa_update_array_format(ctx, ctx->Array.VAO, 340201e04c3fSmrg VERT_ATTRIB_GENERIC(attribIndex), size, type, 340301e04c3fSmrg format, normalized, integer, doubles, 340401e04c3fSmrg relativeOffset); 340501e04c3fSmrg} 340601e04c3fSmrg 340701e04c3fSmrg 340801e04c3fSmrgvoid GLAPIENTRY 340901e04c3fSmrg_mesa_VertexAttribFormat(GLuint attribIndex, GLint size, GLenum type, 341001e04c3fSmrg GLboolean normalized, GLuint relativeOffset) 341101e04c3fSmrg{ 341201e04c3fSmrg vertex_attrib_format(attribIndex, size, type, normalized, 341301e04c3fSmrg GL_FALSE, GL_FALSE, ATTRIB_FORMAT_TYPES_MASK, 341401e04c3fSmrg BGRA_OR_4, relativeOffset, 341501e04c3fSmrg "glVertexAttribFormat"); 341601e04c3fSmrg} 341701e04c3fSmrg 3418af69d88dSmrg 341901e04c3fSmrgvoid GLAPIENTRY 342001e04c3fSmrg_mesa_VertexAttribIFormat(GLuint attribIndex, GLint size, GLenum type, 342101e04c3fSmrg GLuint relativeOffset) 342201e04c3fSmrg{ 342301e04c3fSmrg vertex_attrib_format(attribIndex, size, type, GL_FALSE, 342401e04c3fSmrg GL_TRUE, GL_FALSE, ATTRIB_IFORMAT_TYPES_MASK, 4, 342501e04c3fSmrg relativeOffset, "glVertexAttribIFormat"); 3426af69d88dSmrg} 3427af69d88dSmrg 3428af69d88dSmrg 3429af69d88dSmrgvoid GLAPIENTRY 3430af69d88dSmrg_mesa_VertexAttribLFormat(GLuint attribIndex, GLint size, GLenum type, 3431af69d88dSmrg GLuint relativeOffset) 3432af69d88dSmrg{ 343301e04c3fSmrg vertex_attrib_format(attribIndex, size, type, GL_FALSE, GL_FALSE, 343401e04c3fSmrg GL_TRUE, ATTRIB_LFORMAT_TYPES_MASK, 4, 343501e04c3fSmrg relativeOffset, "glVertexAttribLFormat"); 343601e04c3fSmrg} 343701e04c3fSmrg 3438af69d88dSmrg 343901e04c3fSmrgstatic void 34407ec681f3Smrgvertex_array_attrib_format(GLuint vaobj, bool isExtDsa, GLuint attribIndex, 34417ec681f3Smrg GLint size, GLenum type, GLboolean normalized, 344201e04c3fSmrg GLboolean integer, GLboolean doubles, 344301e04c3fSmrg GLbitfield legalTypes, GLsizei sizeMax, 344401e04c3fSmrg GLuint relativeOffset, const char *func) 344501e04c3fSmrg{ 3446af69d88dSmrg GET_CURRENT_CONTEXT(ctx); 344701e04c3fSmrg struct gl_vertex_array_object *vao; 344801e04c3fSmrg 3449af69d88dSmrg ASSERT_OUTSIDE_BEGIN_END(ctx); 3450af69d88dSmrg 345101e04c3fSmrg GLenum format = get_array_format(ctx, sizeMax, &size); 345201e04c3fSmrg 345301e04c3fSmrg if (_mesa_is_no_error_enabled(ctx)) { 345401e04c3fSmrg vao = _mesa_lookup_vao(ctx, vaobj); 345501e04c3fSmrg if (!vao) 345601e04c3fSmrg return; 345701e04c3fSmrg } else { 34587ec681f3Smrg vao = _mesa_lookup_vao_err(ctx, vaobj, isExtDsa, func); 345901e04c3fSmrg if (!vao) 346001e04c3fSmrg return; 346101e04c3fSmrg 346201e04c3fSmrg /* The ARB_vertex_attrib_binding spec says: 346301e04c3fSmrg * 346401e04c3fSmrg * "The error INVALID_VALUE is generated if index is greater than or 346501e04c3fSmrg * equal to the value of MAX_VERTEX_ATTRIBS." 346601e04c3fSmrg */ 346701e04c3fSmrg if (attribIndex >= ctx->Const.Program[MESA_SHADER_VERTEX].MaxAttribs) { 346801e04c3fSmrg _mesa_error(ctx, GL_INVALID_VALUE, 346901e04c3fSmrg "%s(attribindex=%u > GL_MAX_VERTEX_ATTRIBS)", 347001e04c3fSmrg func, attribIndex); 347101e04c3fSmrg return; 347201e04c3fSmrg } 347301e04c3fSmrg 347401e04c3fSmrg if (!validate_array_format(ctx, func, vao, 347501e04c3fSmrg VERT_ATTRIB_GENERIC(attribIndex), 347601e04c3fSmrg legalTypes, 1, sizeMax, size, type, 347701e04c3fSmrg normalized, integer, doubles, relativeOffset, 347801e04c3fSmrg format)) { 347901e04c3fSmrg return; 348001e04c3fSmrg } 3481af69d88dSmrg } 3482af69d88dSmrg 348301e04c3fSmrg _mesa_update_array_format(ctx, vao, VERT_ATTRIB_GENERIC(attribIndex), size, 348401e04c3fSmrg type, format, normalized, integer, doubles, 348501e04c3fSmrg relativeOffset); 348601e04c3fSmrg} 348701e04c3fSmrg 348801e04c3fSmrg 348901e04c3fSmrgvoid GLAPIENTRY 349001e04c3fSmrg_mesa_VertexArrayAttribFormat(GLuint vaobj, GLuint attribIndex, GLint size, 349101e04c3fSmrg GLenum type, GLboolean normalized, 349201e04c3fSmrg GLuint relativeOffset) 349301e04c3fSmrg{ 34947ec681f3Smrg vertex_array_attrib_format(vaobj, false, attribIndex, size, type, normalized, 349501e04c3fSmrg GL_FALSE, GL_FALSE, ATTRIB_FORMAT_TYPES_MASK, 349601e04c3fSmrg BGRA_OR_4, relativeOffset, 349701e04c3fSmrg "glVertexArrayAttribFormat"); 349801e04c3fSmrg} 349901e04c3fSmrg 350001e04c3fSmrg 35017ec681f3Smrgvoid GLAPIENTRY 35027ec681f3Smrg_mesa_VertexArrayVertexAttribFormatEXT(GLuint vaobj, GLuint attribIndex, GLint size, 35037ec681f3Smrg GLenum type, GLboolean normalized, 35047ec681f3Smrg GLuint relativeOffset) 35057ec681f3Smrg{ 35067ec681f3Smrg vertex_array_attrib_format(vaobj, true, attribIndex, size, type, normalized, 35077ec681f3Smrg GL_FALSE, GL_FALSE, ATTRIB_FORMAT_TYPES_MASK, 35087ec681f3Smrg BGRA_OR_4, relativeOffset, 35097ec681f3Smrg "glVertexArrayVertexAttribFormatEXT"); 35107ec681f3Smrg} 35117ec681f3Smrg 35127ec681f3Smrg 351301e04c3fSmrgvoid GLAPIENTRY 351401e04c3fSmrg_mesa_VertexArrayAttribIFormat(GLuint vaobj, GLuint attribIndex, 351501e04c3fSmrg GLint size, GLenum type, 351601e04c3fSmrg GLuint relativeOffset) 351701e04c3fSmrg{ 35187ec681f3Smrg vertex_array_attrib_format(vaobj, false, attribIndex, size, type, GL_FALSE, 351901e04c3fSmrg GL_TRUE, GL_FALSE, ATTRIB_IFORMAT_TYPES_MASK, 352001e04c3fSmrg 4, relativeOffset, 352101e04c3fSmrg "glVertexArrayAttribIFormat"); 352201e04c3fSmrg} 352301e04c3fSmrg 352401e04c3fSmrg 35257ec681f3Smrgvoid GLAPIENTRY 35267ec681f3Smrg_mesa_VertexArrayVertexAttribIFormatEXT(GLuint vaobj, GLuint attribIndex, 35277ec681f3Smrg GLint size, GLenum type, 35287ec681f3Smrg GLuint relativeOffset) 35297ec681f3Smrg{ 35307ec681f3Smrg vertex_array_attrib_format(vaobj, true, attribIndex, size, type, GL_FALSE, 35317ec681f3Smrg GL_TRUE, GL_FALSE, ATTRIB_IFORMAT_TYPES_MASK, 35327ec681f3Smrg 4, relativeOffset, 35337ec681f3Smrg "glVertexArrayVertexAttribIFormatEXT"); 35347ec681f3Smrg} 35357ec681f3Smrg 35367ec681f3Smrg 353701e04c3fSmrgvoid GLAPIENTRY 353801e04c3fSmrg_mesa_VertexArrayAttribLFormat(GLuint vaobj, GLuint attribIndex, 353901e04c3fSmrg GLint size, GLenum type, 354001e04c3fSmrg GLuint relativeOffset) 354101e04c3fSmrg{ 35427ec681f3Smrg vertex_array_attrib_format(vaobj, false, attribIndex, size, type, GL_FALSE, 354301e04c3fSmrg GL_FALSE, GL_TRUE, ATTRIB_LFORMAT_TYPES_MASK, 354401e04c3fSmrg 4, relativeOffset, 354501e04c3fSmrg "glVertexArrayAttribLFormat"); 354601e04c3fSmrg} 354701e04c3fSmrg 354801e04c3fSmrg 35497ec681f3Smrgvoid GLAPIENTRY 35507ec681f3Smrg_mesa_VertexArrayVertexAttribLFormatEXT(GLuint vaobj, GLuint attribIndex, 35517ec681f3Smrg GLint size, GLenum type, 35527ec681f3Smrg GLuint relativeOffset) 35537ec681f3Smrg{ 35547ec681f3Smrg vertex_array_attrib_format(vaobj, true, attribIndex, size, type, GL_FALSE, 35557ec681f3Smrg GL_FALSE, GL_TRUE, ATTRIB_LFORMAT_TYPES_MASK, 35567ec681f3Smrg 4, relativeOffset, 35577ec681f3Smrg "glVertexArrayVertexAttribLFormatEXT"); 35587ec681f3Smrg} 35597ec681f3Smrg 35607ec681f3Smrg 356101e04c3fSmrgstatic void 356201e04c3fSmrgvertex_array_attrib_binding(struct gl_context *ctx, 356301e04c3fSmrg struct gl_vertex_array_object *vao, 356401e04c3fSmrg GLuint attribIndex, GLuint bindingIndex, 356501e04c3fSmrg const char *func) 356601e04c3fSmrg{ 356701e04c3fSmrg ASSERT_OUTSIDE_BEGIN_END(ctx); 356801e04c3fSmrg 3569af69d88dSmrg /* The ARB_vertex_attrib_binding spec says: 3570af69d88dSmrg * 357101e04c3fSmrg * "<attribindex> must be less than the value of MAX_VERTEX_ATTRIBS and 357201e04c3fSmrg * <bindingindex> must be less than the value of 357301e04c3fSmrg * MAX_VERTEX_ATTRIB_BINDINGS, otherwise the error INVALID_VALUE 357401e04c3fSmrg * is generated." 3575af69d88dSmrg */ 3576af69d88dSmrg if (attribIndex >= ctx->Const.Program[MESA_SHADER_VERTEX].MaxAttribs) { 3577af69d88dSmrg _mesa_error(ctx, GL_INVALID_VALUE, 357801e04c3fSmrg "%s(attribindex=%u >= " 3579af69d88dSmrg "GL_MAX_VERTEX_ATTRIBS)", 358001e04c3fSmrg func, attribIndex); 358101e04c3fSmrg return; 358201e04c3fSmrg } 358301e04c3fSmrg 358401e04c3fSmrg if (bindingIndex >= ctx->Const.MaxVertexAttribBindings) { 358501e04c3fSmrg _mesa_error(ctx, GL_INVALID_VALUE, 358601e04c3fSmrg "%s(bindingindex=%u >= " 358701e04c3fSmrg "GL_MAX_VERTEX_ATTRIB_BINDINGS)", 358801e04c3fSmrg func, bindingIndex); 3589af69d88dSmrg return; 3590af69d88dSmrg } 3591af69d88dSmrg 359201e04c3fSmrg assert(VERT_ATTRIB_GENERIC(attribIndex) < ARRAY_SIZE(vao->VertexAttrib)); 359301e04c3fSmrg 359401e04c3fSmrg _mesa_vertex_attrib_binding(ctx, vao, 359501e04c3fSmrg VERT_ATTRIB_GENERIC(attribIndex), 359601e04c3fSmrg VERT_ATTRIB_GENERIC(bindingIndex)); 359701e04c3fSmrg} 359801e04c3fSmrg 3599af69d88dSmrg 360001e04c3fSmrgvoid GLAPIENTRY 360101e04c3fSmrg_mesa_VertexAttribBinding_no_error(GLuint attribIndex, GLuint bindingIndex) 360201e04c3fSmrg{ 360301e04c3fSmrg GET_CURRENT_CONTEXT(ctx); 360401e04c3fSmrg _mesa_vertex_attrib_binding(ctx, ctx->Array.VAO, 360501e04c3fSmrg VERT_ATTRIB_GENERIC(attribIndex), 360601e04c3fSmrg VERT_ATTRIB_GENERIC(bindingIndex)); 3607af69d88dSmrg} 3608af69d88dSmrg 3609af69d88dSmrg 3610af69d88dSmrgvoid GLAPIENTRY 3611af69d88dSmrg_mesa_VertexAttribBinding(GLuint attribIndex, GLuint bindingIndex) 3612af69d88dSmrg{ 3613af69d88dSmrg GET_CURRENT_CONTEXT(ctx); 3614af69d88dSmrg 3615af69d88dSmrg /* The ARB_vertex_attrib_binding spec says: 3616af69d88dSmrg * 3617af69d88dSmrg * "An INVALID_OPERATION error is generated if no vertex array object 3618af69d88dSmrg * is bound." 3619af69d88dSmrg */ 362001e04c3fSmrg if ((ctx->API == API_OPENGL_CORE || _mesa_is_gles31(ctx)) && 3621af69d88dSmrg ctx->Array.VAO == ctx->Array.DefaultVAO) { 3622af69d88dSmrg _mesa_error(ctx, GL_INVALID_OPERATION, 3623af69d88dSmrg "glVertexAttribBinding(No array object bound)"); 3624af69d88dSmrg return; 3625af69d88dSmrg } 3626af69d88dSmrg 362701e04c3fSmrg vertex_array_attrib_binding(ctx, ctx->Array.VAO, 362801e04c3fSmrg attribIndex, bindingIndex, 362901e04c3fSmrg "glVertexAttribBinding"); 363001e04c3fSmrg} 363101e04c3fSmrg 363201e04c3fSmrg 363301e04c3fSmrgvoid GLAPIENTRY 363401e04c3fSmrg_mesa_VertexArrayAttribBinding_no_error(GLuint vaobj, GLuint attribIndex, 363501e04c3fSmrg GLuint bindingIndex) 363601e04c3fSmrg{ 363701e04c3fSmrg GET_CURRENT_CONTEXT(ctx); 363801e04c3fSmrg 363901e04c3fSmrg struct gl_vertex_array_object *vao = _mesa_lookup_vao(ctx, vaobj); 364001e04c3fSmrg _mesa_vertex_attrib_binding(ctx, vao, 364101e04c3fSmrg VERT_ATTRIB_GENERIC(attribIndex), 364201e04c3fSmrg VERT_ATTRIB_GENERIC(bindingIndex)); 364301e04c3fSmrg} 364401e04c3fSmrg 364501e04c3fSmrg 364601e04c3fSmrgvoid GLAPIENTRY 364701e04c3fSmrg_mesa_VertexArrayAttribBinding(GLuint vaobj, GLuint attribIndex, GLuint bindingIndex) 364801e04c3fSmrg{ 364901e04c3fSmrg GET_CURRENT_CONTEXT(ctx); 365001e04c3fSmrg struct gl_vertex_array_object *vao; 365101e04c3fSmrg 365201e04c3fSmrg /* The ARB_direct_state_access specification says: 3653af69d88dSmrg * 365401e04c3fSmrg * "An INVALID_OPERATION error is generated by VertexArrayAttribBinding 365501e04c3fSmrg * if <vaobj> is not [compatibility profile: zero or] the name of an 365601e04c3fSmrg * existing vertex array object." 3657af69d88dSmrg */ 36587ec681f3Smrg vao = _mesa_lookup_vao_err(ctx, vaobj, false, "glVertexArrayAttribBinding"); 365901e04c3fSmrg if (!vao) 366001e04c3fSmrg return; 366101e04c3fSmrg 366201e04c3fSmrg vertex_array_attrib_binding(ctx, vao, attribIndex, bindingIndex, 366301e04c3fSmrg "glVertexArrayAttribBinding"); 366401e04c3fSmrg} 366501e04c3fSmrg 366601e04c3fSmrg 36677ec681f3Smrgvoid GLAPIENTRY 36687ec681f3Smrg_mesa_VertexArrayVertexAttribBindingEXT(GLuint vaobj, GLuint attribIndex, GLuint bindingIndex) 36697ec681f3Smrg{ 36707ec681f3Smrg GET_CURRENT_CONTEXT(ctx); 36717ec681f3Smrg struct gl_vertex_array_object *vao; 36727ec681f3Smrg vao = _mesa_lookup_vao_err(ctx, vaobj, true, "glVertexArrayVertexAttribBindingEXT"); 36737ec681f3Smrg if (!vao) 36747ec681f3Smrg return; 36757ec681f3Smrg 36767ec681f3Smrg vertex_array_attrib_binding(ctx, vao, attribIndex, bindingIndex, 36777ec681f3Smrg "glVertexArrayVertexAttribBindingEXT"); 36787ec681f3Smrg} 36797ec681f3Smrg 36807ec681f3Smrg 368101e04c3fSmrgstatic void 368201e04c3fSmrgvertex_array_binding_divisor(struct gl_context *ctx, 368301e04c3fSmrg struct gl_vertex_array_object *vao, 368401e04c3fSmrg GLuint bindingIndex, GLuint divisor, 368501e04c3fSmrg const char *func) 368601e04c3fSmrg{ 368701e04c3fSmrg ASSERT_OUTSIDE_BEGIN_END(ctx); 368801e04c3fSmrg 368901e04c3fSmrg if (!ctx->Extensions.ARB_instanced_arrays) { 369001e04c3fSmrg _mesa_error(ctx, GL_INVALID_OPERATION, "%s()", func); 3691af69d88dSmrg return; 3692af69d88dSmrg } 3693af69d88dSmrg 369401e04c3fSmrg /* The ARB_vertex_attrib_binding spec says: 369501e04c3fSmrg * 369601e04c3fSmrg * "An INVALID_VALUE error is generated if <bindingindex> is greater 369701e04c3fSmrg * than or equal to the value of MAX_VERTEX_ATTRIB_BINDINGS." 369801e04c3fSmrg */ 3699af69d88dSmrg if (bindingIndex >= ctx->Const.MaxVertexAttribBindings) { 3700af69d88dSmrg _mesa_error(ctx, GL_INVALID_VALUE, 370101e04c3fSmrg "%s(bindingindex=%u > " 3702af69d88dSmrg "GL_MAX_VERTEX_ATTRIB_BINDINGS)", 370301e04c3fSmrg func, bindingIndex); 3704af69d88dSmrg return; 3705af69d88dSmrg } 3706af69d88dSmrg 370701e04c3fSmrg vertex_binding_divisor(ctx, vao, VERT_ATTRIB_GENERIC(bindingIndex), divisor); 370801e04c3fSmrg} 370901e04c3fSmrg 3710af69d88dSmrg 371101e04c3fSmrgvoid GLAPIENTRY 371201e04c3fSmrg_mesa_VertexBindingDivisor_no_error(GLuint bindingIndex, GLuint divisor) 371301e04c3fSmrg{ 371401e04c3fSmrg GET_CURRENT_CONTEXT(ctx); 371501e04c3fSmrg vertex_binding_divisor(ctx, ctx->Array.VAO, 371601e04c3fSmrg VERT_ATTRIB_GENERIC(bindingIndex), divisor); 3717af69d88dSmrg} 3718af69d88dSmrg 3719af69d88dSmrg 3720af69d88dSmrgvoid GLAPIENTRY 3721af69d88dSmrg_mesa_VertexBindingDivisor(GLuint bindingIndex, GLuint divisor) 3722af69d88dSmrg{ 3723af69d88dSmrg GET_CURRENT_CONTEXT(ctx); 3724af69d88dSmrg 3725af69d88dSmrg /* The ARB_vertex_attrib_binding spec says: 3726af69d88dSmrg * 3727af69d88dSmrg * "An INVALID_OPERATION error is generated if no vertex array object 3728af69d88dSmrg * is bound." 3729af69d88dSmrg */ 373001e04c3fSmrg if ((ctx->API == API_OPENGL_CORE || _mesa_is_gles31(ctx)) && 3731af69d88dSmrg ctx->Array.VAO == ctx->Array.DefaultVAO) { 3732af69d88dSmrg _mesa_error(ctx, GL_INVALID_OPERATION, 3733af69d88dSmrg "glVertexBindingDivisor(No array object bound)"); 3734af69d88dSmrg return; 3735af69d88dSmrg } 3736af69d88dSmrg 373701e04c3fSmrg vertex_array_binding_divisor(ctx, ctx->Array.VAO, 373801e04c3fSmrg bindingIndex, divisor, 373901e04c3fSmrg "glVertexBindingDivisor"); 374001e04c3fSmrg} 374101e04c3fSmrg 374201e04c3fSmrg 374301e04c3fSmrgvoid GLAPIENTRY 374401e04c3fSmrg_mesa_VertexArrayBindingDivisor_no_error(GLuint vaobj, GLuint bindingIndex, 374501e04c3fSmrg GLuint divisor) 374601e04c3fSmrg{ 374701e04c3fSmrg GET_CURRENT_CONTEXT(ctx); 3748af69d88dSmrg 374901e04c3fSmrg struct gl_vertex_array_object *vao = _mesa_lookup_vao(ctx, vaobj); 375001e04c3fSmrg vertex_binding_divisor(ctx, vao, VERT_ATTRIB_GENERIC(bindingIndex), divisor); 3751af69d88dSmrg} 3752af69d88dSmrg 37533464ebd5Sriastradh 375401e04c3fSmrgvoid GLAPIENTRY 375501e04c3fSmrg_mesa_VertexArrayBindingDivisor(GLuint vaobj, GLuint bindingIndex, 375601e04c3fSmrg GLuint divisor) 375701e04c3fSmrg{ 375801e04c3fSmrg struct gl_vertex_array_object *vao; 375901e04c3fSmrg GET_CURRENT_CONTEXT(ctx); 376001e04c3fSmrg 376101e04c3fSmrg /* The ARB_direct_state_access specification says: 376201e04c3fSmrg * 376301e04c3fSmrg * "An INVALID_OPERATION error is generated by VertexArrayBindingDivisor 376401e04c3fSmrg * if <vaobj> is not [compatibility profile: zero or] the name of an 376501e04c3fSmrg * existing vertex array object." 376601e04c3fSmrg */ 37677ec681f3Smrg vao = _mesa_lookup_vao_err(ctx, vaobj, false, "glVertexArrayBindingDivisor"); 376801e04c3fSmrg if (!vao) 376901e04c3fSmrg return; 377001e04c3fSmrg 377101e04c3fSmrg vertex_array_binding_divisor(ctx, vao, bindingIndex, divisor, 377201e04c3fSmrg "glVertexArrayBindingDivisor"); 37734a49301eSmrg} 37744a49301eSmrg 377501e04c3fSmrg 37767ec681f3Smrgvoid GLAPIENTRY 37777ec681f3Smrg_mesa_VertexArrayVertexBindingDivisorEXT(GLuint vaobj, GLuint bindingIndex, 37787ec681f3Smrg GLuint divisor) 3779af69d88dSmrg{ 37807ec681f3Smrg struct gl_vertex_array_object *vao; 37817ec681f3Smrg GET_CURRENT_CONTEXT(ctx); 3782af69d88dSmrg 37837ec681f3Smrg /* The ARB_direct_state_access specification says: 37847ec681f3Smrg * 37857ec681f3Smrg * "An INVALID_OPERATION error is generated by VertexArrayBindingDivisor 37867ec681f3Smrg * if <vaobj> is not [compatibility profile: zero or] the name of an 37877ec681f3Smrg * existing vertex array object." 37887ec681f3Smrg */ 37897ec681f3Smrg vao = _mesa_lookup_vao_err(ctx, vaobj, true, "glVertexArrayVertexBindingDivisorEXT"); 37907ec681f3Smrg if (!vao) 37917ec681f3Smrg return; 37924a49301eSmrg 37937ec681f3Smrg vertex_array_binding_divisor(ctx, vao, bindingIndex, divisor, 37947ec681f3Smrg "glVertexArrayVertexBindingDivisorEXT"); 3795af69d88dSmrg} 37964a49301eSmrg 37974a49301eSmrg/** 37984a49301eSmrg * Print current vertex object/array info. For debug. 37994a49301eSmrg */ 38004a49301eSmrgvoid 38013464ebd5Sriastradh_mesa_print_arrays(struct gl_context *ctx) 38024a49301eSmrg{ 380301e04c3fSmrg const struct gl_vertex_array_object *vao = ctx->Array.VAO; 38044a49301eSmrg 380501e04c3fSmrg fprintf(stderr, "Array Object %u\n", vao->Name); 3806af69d88dSmrg 3807b9abf16eSmaya GLbitfield mask = vao->Enabled; 3808b9abf16eSmaya while (mask) { 3809b9abf16eSmaya const gl_vert_attrib i = u_bit_scan(&mask); 381001e04c3fSmrg const struct gl_array_attributes *array = &vao->VertexAttrib[i]; 381101e04c3fSmrg 381201e04c3fSmrg const struct gl_vertex_buffer_binding *binding = 381301e04c3fSmrg &vao->BufferBinding[array->BufferBindingIndex]; 381401e04c3fSmrg const struct gl_buffer_object *bo = binding->BufferObj; 381501e04c3fSmrg 381601e04c3fSmrg fprintf(stderr, " %s: Ptr=%p, Type=%s, Size=%d, ElemSize=%u, " 381701e04c3fSmrg "Stride=%d, Buffer=%u(Size %lu)\n", 381801e04c3fSmrg gl_vert_attrib_name((gl_vert_attrib)i), 3819b9abf16eSmaya array->Ptr, _mesa_enum_to_string(array->Format.Type), 3820b9abf16eSmaya array->Format.Size, 38217ec681f3Smrg array->Format._ElementSize, binding->Stride, bo ? bo->Name : 0, 38227ec681f3Smrg (unsigned long)(bo ? bo->Size : 0)); 382301e04c3fSmrg } 38244a49301eSmrg} 38254a49301eSmrg 38267ec681f3Smrg/** 38277ec681f3Smrg * Initialize attributes of a vertex array within a vertex array object. 38287ec681f3Smrg * \param vao the container vertex array object 38297ec681f3Smrg * \param index which array in the VAO to initialize 38307ec681f3Smrg * \param size number of components (1, 2, 3 or 4) per attribute 38317ec681f3Smrg * \param type datatype of the attribute (GL_FLOAT, GL_INT, etc). 38327ec681f3Smrg */ 38337ec681f3Smrgstatic void 38347ec681f3Smrginit_array(struct gl_context *ctx, 38357ec681f3Smrg struct gl_vertex_array_object *vao, 38367ec681f3Smrg gl_vert_attrib index, GLint size, GLint type) 38377ec681f3Smrg{ 38387ec681f3Smrg assert(index < ARRAY_SIZE(vao->VertexAttrib)); 38397ec681f3Smrg struct gl_array_attributes *array = &vao->VertexAttrib[index]; 38407ec681f3Smrg assert(index < ARRAY_SIZE(vao->BufferBinding)); 38417ec681f3Smrg struct gl_vertex_buffer_binding *binding = &vao->BufferBinding[index]; 38427ec681f3Smrg 38437ec681f3Smrg _mesa_set_vertex_format(&array->Format, size, type, GL_RGBA, 38447ec681f3Smrg GL_FALSE, GL_FALSE, GL_FALSE); 38457ec681f3Smrg array->Stride = 0; 38467ec681f3Smrg array->Ptr = NULL; 38477ec681f3Smrg array->RelativeOffset = 0; 38487ec681f3Smrg ASSERT_BITFIELD_SIZE(struct gl_array_attributes, BufferBindingIndex, 38497ec681f3Smrg VERT_ATTRIB_MAX - 1); 38507ec681f3Smrg array->BufferBindingIndex = index; 38517ec681f3Smrg 38527ec681f3Smrg binding->Offset = 0; 38537ec681f3Smrg binding->Stride = array->Format._ElementSize; 38547ec681f3Smrg binding->BufferObj = NULL; 38557ec681f3Smrg binding->_BoundArrays = BITFIELD_BIT(index); 38567ec681f3Smrg} 38577ec681f3Smrg 38587ec681f3Smrgstatic void 38597ec681f3Smrginit_default_vao_state(struct gl_context *ctx) 38607ec681f3Smrg{ 38617ec681f3Smrg struct gl_vertex_array_object *vao = &ctx->Array.DefaultVAOState; 38627ec681f3Smrg 38637ec681f3Smrg vao->RefCount = 1; 38647ec681f3Smrg vao->SharedAndImmutable = false; 38657ec681f3Smrg 38667ec681f3Smrg /* Init the individual arrays */ 38677ec681f3Smrg for (unsigned i = 0; i < ARRAY_SIZE(vao->VertexAttrib); i++) { 38687ec681f3Smrg switch (i) { 38697ec681f3Smrg case VERT_ATTRIB_NORMAL: 38707ec681f3Smrg init_array(ctx, vao, VERT_ATTRIB_NORMAL, 3, GL_FLOAT); 38717ec681f3Smrg break; 38727ec681f3Smrg case VERT_ATTRIB_COLOR1: 38737ec681f3Smrg init_array(ctx, vao, VERT_ATTRIB_COLOR1, 3, GL_FLOAT); 38747ec681f3Smrg break; 38757ec681f3Smrg case VERT_ATTRIB_FOG: 38767ec681f3Smrg init_array(ctx, vao, VERT_ATTRIB_FOG, 1, GL_FLOAT); 38777ec681f3Smrg break; 38787ec681f3Smrg case VERT_ATTRIB_COLOR_INDEX: 38797ec681f3Smrg init_array(ctx, vao, VERT_ATTRIB_COLOR_INDEX, 1, GL_FLOAT); 38807ec681f3Smrg break; 38817ec681f3Smrg case VERT_ATTRIB_EDGEFLAG: 38827ec681f3Smrg init_array(ctx, vao, VERT_ATTRIB_EDGEFLAG, 1, GL_UNSIGNED_BYTE); 38837ec681f3Smrg break; 38847ec681f3Smrg case VERT_ATTRIB_POINT_SIZE: 38857ec681f3Smrg init_array(ctx, vao, VERT_ATTRIB_POINT_SIZE, 1, GL_FLOAT); 38867ec681f3Smrg break; 38877ec681f3Smrg default: 38887ec681f3Smrg init_array(ctx, vao, i, 4, GL_FLOAT); 38897ec681f3Smrg break; 38907ec681f3Smrg } 38917ec681f3Smrg } 38927ec681f3Smrg 38937ec681f3Smrg vao->_AttributeMapMode = ATTRIBUTE_MAP_MODE_IDENTITY; 38947ec681f3Smrg} 38954a49301eSmrg 38967117f1b4Smrg/** 38977117f1b4Smrg * Initialize vertex array state for given context. 38987117f1b4Smrg */ 389901e04c3fSmrgvoid 39003464ebd5Sriastradh_mesa_init_varray(struct gl_context *ctx) 39017117f1b4Smrg{ 39027ec681f3Smrg init_default_vao_state(ctx); 39037ec681f3Smrg 390401e04c3fSmrg ctx->Array.DefaultVAO = _mesa_new_vao(ctx, 0); 3905af69d88dSmrg _mesa_reference_vao(ctx, &ctx->Array.VAO, ctx->Array.DefaultVAO); 390601e04c3fSmrg ctx->Array._EmptyVAO = _mesa_new_vao(ctx, ~0u); 390701e04c3fSmrg _mesa_reference_vao(ctx, &ctx->Array._DrawVAO, ctx->Array._EmptyVAO); 39087117f1b4Smrg ctx->Array.ActiveTexture = 0; /* GL_ARB_multitexture */ 39094a49301eSmrg 39104a49301eSmrg ctx->Array.Objects = _mesa_NewHashTable(); 39114a49301eSmrg} 39124a49301eSmrg 39134a49301eSmrg 39144a49301eSmrg/** 39154a49301eSmrg * Callback for deleting an array object. Called by _mesa_HashDeleteAll(). 39164a49301eSmrg */ 39174a49301eSmrgstatic void 39187ec681f3Smrgdelete_arrayobj_cb(void *data, void *userData) 39194a49301eSmrg{ 3920af69d88dSmrg struct gl_vertex_array_object *vao = (struct gl_vertex_array_object *) data; 39213464ebd5Sriastradh struct gl_context *ctx = (struct gl_context *) userData; 3922af69d88dSmrg _mesa_delete_vao(ctx, vao); 39234a49301eSmrg} 39244a49301eSmrg 39254a49301eSmrg 39264a49301eSmrg/** 39274a49301eSmrg * Free vertex array state for given context. 39284a49301eSmrg */ 392901e04c3fSmrgvoid 39303464ebd5Sriastradh_mesa_free_varray_data(struct gl_context *ctx) 39314a49301eSmrg{ 39324a49301eSmrg _mesa_HashDeleteAll(ctx->Array.Objects, delete_arrayobj_cb, ctx); 39334a49301eSmrg _mesa_DeleteHashTable(ctx->Array.Objects); 39347117f1b4Smrg} 39357ec681f3Smrg 39367ec681f3Smrgvoid GLAPIENTRY 39377ec681f3Smrg_mesa_GetVertexArrayIntegervEXT(GLuint vaobj, GLenum pname, GLint *param) 39387ec681f3Smrg{ 39397ec681f3Smrg GET_CURRENT_CONTEXT(ctx); 39407ec681f3Smrg struct gl_vertex_array_object* vao; 39417ec681f3Smrg struct gl_buffer_object *buf; 39427ec681f3Smrg void* ptr; 39437ec681f3Smrg 39447ec681f3Smrg vao = _mesa_lookup_vao_err(ctx, vaobj, true, 39457ec681f3Smrg "glGetVertexArrayIntegervEXT"); 39467ec681f3Smrg if (!vao) 39477ec681f3Smrg return; 39487ec681f3Smrg 39497ec681f3Smrg /* The EXT_direct_state_access spec says: 39507ec681f3Smrg * 39517ec681f3Smrg * "For GetVertexArrayIntegervEXT, pname must be one of the "Get value" tokens 39527ec681f3Smrg * in tables 6.6, 6.7, 6.8, and 6.9 that use GetIntegerv, IsEnabled, or 39537ec681f3Smrg * GetPointerv for their "Get command" (so excluding the VERTEX_ATTRIB_* 39547ec681f3Smrg * tokens)." 39557ec681f3Smrg */ 39567ec681f3Smrg switch (pname) { 39577ec681f3Smrg /* Tokens using GetIntegerv */ 39587ec681f3Smrg case GL_CLIENT_ACTIVE_TEXTURE: 39597ec681f3Smrg *param = GL_TEXTURE0_ARB + ctx->Array.ActiveTexture; 39607ec681f3Smrg break; 39617ec681f3Smrg case GL_VERTEX_ARRAY_SIZE: 39627ec681f3Smrg *param = vao->VertexAttrib[VERT_ATTRIB_POS].Format.Size; 39637ec681f3Smrg break; 39647ec681f3Smrg case GL_VERTEX_ARRAY_TYPE: 39657ec681f3Smrg *param = vao->VertexAttrib[VERT_ATTRIB_POS].Format.Type; 39667ec681f3Smrg break; 39677ec681f3Smrg case GL_VERTEX_ARRAY_STRIDE: 39687ec681f3Smrg *param = vao->VertexAttrib[VERT_ATTRIB_POS].Stride; 39697ec681f3Smrg break; 39707ec681f3Smrg case GL_VERTEX_ARRAY_BUFFER_BINDING: 39717ec681f3Smrg buf = vao->BufferBinding[VERT_ATTRIB_POS].BufferObj; 39727ec681f3Smrg *param = buf ? buf->Name : 0; 39737ec681f3Smrg break; 39747ec681f3Smrg case GL_COLOR_ARRAY_SIZE: 39757ec681f3Smrg *param = vao->VertexAttrib[VERT_ATTRIB_COLOR0].Format.Size; 39767ec681f3Smrg break; 39777ec681f3Smrg case GL_COLOR_ARRAY_TYPE: 39787ec681f3Smrg *param = vao->VertexAttrib[VERT_ATTRIB_COLOR0].Format.Type; 39797ec681f3Smrg break; 39807ec681f3Smrg case GL_COLOR_ARRAY_STRIDE: 39817ec681f3Smrg *param = vao->VertexAttrib[VERT_ATTRIB_COLOR0].Stride; 39827ec681f3Smrg break; 39837ec681f3Smrg case GL_COLOR_ARRAY_BUFFER_BINDING: 39847ec681f3Smrg buf = vao->BufferBinding[VERT_ATTRIB_COLOR0].BufferObj; 39857ec681f3Smrg *param = buf ? buf->Name : 0; 39867ec681f3Smrg break; 39877ec681f3Smrg case GL_EDGE_FLAG_ARRAY_STRIDE: 39887ec681f3Smrg *param = vao->VertexAttrib[VERT_ATTRIB_EDGEFLAG].Stride; 39897ec681f3Smrg break; 39907ec681f3Smrg case GL_EDGE_FLAG_ARRAY_BUFFER_BINDING: 39917ec681f3Smrg buf = vao->BufferBinding[VERT_ATTRIB_EDGEFLAG].BufferObj; 39927ec681f3Smrg *param = buf ? buf->Name : 0; 39937ec681f3Smrg break; 39947ec681f3Smrg case GL_INDEX_ARRAY_TYPE: 39957ec681f3Smrg *param = vao->VertexAttrib[VERT_ATTRIB_COLOR_INDEX].Format.Type; 39967ec681f3Smrg break; 39977ec681f3Smrg case GL_INDEX_ARRAY_STRIDE: 39987ec681f3Smrg *param = vao->VertexAttrib[VERT_ATTRIB_COLOR_INDEX].Stride; 39997ec681f3Smrg break; 40007ec681f3Smrg case GL_INDEX_ARRAY_BUFFER_BINDING: 40017ec681f3Smrg buf = vao->BufferBinding[VERT_ATTRIB_COLOR_INDEX].BufferObj; 40027ec681f3Smrg *param = buf ? buf->Name : 0; 40037ec681f3Smrg break; 40047ec681f3Smrg case GL_NORMAL_ARRAY_TYPE: 40057ec681f3Smrg *param = vao->VertexAttrib[VERT_ATTRIB_NORMAL].Format.Type; 40067ec681f3Smrg break; 40077ec681f3Smrg case GL_NORMAL_ARRAY_STRIDE: 40087ec681f3Smrg *param = vao->VertexAttrib[VERT_ATTRIB_NORMAL].Stride; 40097ec681f3Smrg break; 40107ec681f3Smrg case GL_NORMAL_ARRAY_BUFFER_BINDING: 40117ec681f3Smrg buf = vao->BufferBinding[VERT_ATTRIB_NORMAL].BufferObj; 40127ec681f3Smrg *param = buf ? buf->Name : 0; 40137ec681f3Smrg break; 40147ec681f3Smrg case GL_TEXTURE_COORD_ARRAY_SIZE: 40157ec681f3Smrg *param = vao->VertexAttrib[VERT_ATTRIB_TEX(ctx->Array.ActiveTexture)].Format.Size; 40167ec681f3Smrg break; 40177ec681f3Smrg case GL_TEXTURE_COORD_ARRAY_TYPE: 40187ec681f3Smrg *param = vao->VertexAttrib[VERT_ATTRIB_TEX(ctx->Array.ActiveTexture)].Format.Type; 40197ec681f3Smrg break; 40207ec681f3Smrg case GL_TEXTURE_COORD_ARRAY_STRIDE: 40217ec681f3Smrg *param = vao->VertexAttrib[VERT_ATTRIB_TEX(ctx->Array.ActiveTexture)].Stride; 40227ec681f3Smrg break; 40237ec681f3Smrg case GL_TEXTURE_COORD_ARRAY_BUFFER_BINDING: 40247ec681f3Smrg buf = vao->BufferBinding[VERT_ATTRIB_TEX(ctx->Array.ActiveTexture)].BufferObj; 40257ec681f3Smrg *param = buf ? buf->Name : 0; 40267ec681f3Smrg break; 40277ec681f3Smrg case GL_FOG_COORD_ARRAY_TYPE: 40287ec681f3Smrg *param = vao->VertexAttrib[VERT_ATTRIB_FOG].Format.Type; 40297ec681f3Smrg break; 40307ec681f3Smrg case GL_FOG_COORD_ARRAY_STRIDE: 40317ec681f3Smrg *param = vao->VertexAttrib[VERT_ATTRIB_FOG].Stride; 40327ec681f3Smrg break; 40337ec681f3Smrg case GL_FOG_COORD_ARRAY_BUFFER_BINDING: 40347ec681f3Smrg buf = vao->BufferBinding[VERT_ATTRIB_FOG].BufferObj; 40357ec681f3Smrg *param = buf ? buf->Name : 0; 40367ec681f3Smrg break; 40377ec681f3Smrg case GL_SECONDARY_COLOR_ARRAY_SIZE: 40387ec681f3Smrg *param = vao->VertexAttrib[VERT_ATTRIB_COLOR1].Format.Size; 40397ec681f3Smrg break; 40407ec681f3Smrg case GL_SECONDARY_COLOR_ARRAY_TYPE: 40417ec681f3Smrg *param = vao->VertexAttrib[VERT_ATTRIB_COLOR1].Format.Type; 40427ec681f3Smrg break; 40437ec681f3Smrg case GL_SECONDARY_COLOR_ARRAY_STRIDE: 40447ec681f3Smrg *param = vao->VertexAttrib[VERT_ATTRIB_COLOR1].Stride; 40457ec681f3Smrg break; 40467ec681f3Smrg case GL_SECONDARY_COLOR_ARRAY_BUFFER_BINDING: 40477ec681f3Smrg buf = vao->BufferBinding[VERT_ATTRIB_COLOR1].BufferObj; 40487ec681f3Smrg *param = buf ? buf->Name : 0; 40497ec681f3Smrg break; 40507ec681f3Smrg 40517ec681f3Smrg /* Tokens using IsEnabled */ 40527ec681f3Smrg case GL_VERTEX_ARRAY: 40537ec681f3Smrg *param = !!(vao->Enabled & VERT_BIT_POS); 40547ec681f3Smrg break; 40557ec681f3Smrg case GL_COLOR_ARRAY: 40567ec681f3Smrg *param = !!(vao->Enabled & VERT_BIT_COLOR0); 40577ec681f3Smrg break; 40587ec681f3Smrg case GL_EDGE_FLAG_ARRAY: 40597ec681f3Smrg *param = !!(vao->Enabled & VERT_BIT_EDGEFLAG); 40607ec681f3Smrg break; 40617ec681f3Smrg case GL_INDEX_ARRAY: 40627ec681f3Smrg *param = !!(vao->Enabled & VERT_BIT_COLOR_INDEX); 40637ec681f3Smrg break; 40647ec681f3Smrg case GL_NORMAL_ARRAY: 40657ec681f3Smrg *param = !!(vao->Enabled & VERT_BIT_NORMAL); 40667ec681f3Smrg break; 40677ec681f3Smrg case GL_TEXTURE_COORD_ARRAY: 40687ec681f3Smrg *param = !!(vao->Enabled & VERT_BIT_TEX(ctx->Array.ActiveTexture)); 40697ec681f3Smrg break; 40707ec681f3Smrg case GL_FOG_COORD_ARRAY: 40717ec681f3Smrg *param = !!(vao->Enabled & VERT_BIT_FOG); 40727ec681f3Smrg break; 40737ec681f3Smrg case GL_SECONDARY_COLOR_ARRAY: 40747ec681f3Smrg *param = !!(vao->Enabled & VERT_BIT_COLOR1); 40757ec681f3Smrg break; 40767ec681f3Smrg 40777ec681f3Smrg /* Tokens using GetPointerv */ 40787ec681f3Smrg case GL_VERTEX_ARRAY_POINTER: 40797ec681f3Smrg case GL_COLOR_ARRAY_POINTER: 40807ec681f3Smrg case GL_EDGE_FLAG_ARRAY_POINTER: 40817ec681f3Smrg case GL_INDEX_ARRAY_POINTER: 40827ec681f3Smrg case GL_NORMAL_ARRAY_POINTER: 40837ec681f3Smrg case GL_TEXTURE_COORD_ARRAY_POINTER: 40847ec681f3Smrg case GL_FOG_COORD_ARRAY_POINTER: 40857ec681f3Smrg case GL_SECONDARY_COLOR_ARRAY_POINTER: 40867ec681f3Smrg _get_vao_pointerv(pname, vao, &ptr, "glGetVertexArrayIntegervEXT"); 40877ec681f3Smrg *param = (int) ((intptr_t) ptr & 0xFFFFFFFF); 40887ec681f3Smrg break; 40897ec681f3Smrg 40907ec681f3Smrg default: 40917ec681f3Smrg _mesa_error(ctx, GL_INVALID_ENUM, "glGetVertexArrayIntegervEXT(pname)"); 40927ec681f3Smrg } 40937ec681f3Smrg} 40947ec681f3Smrg 40957ec681f3Smrgvoid GLAPIENTRY 40967ec681f3Smrg_mesa_GetVertexArrayPointervEXT(GLuint vaobj, GLenum pname, GLvoid** param) 40977ec681f3Smrg{ 40987ec681f3Smrg GET_CURRENT_CONTEXT(ctx); 40997ec681f3Smrg struct gl_vertex_array_object* vao; 41007ec681f3Smrg 41017ec681f3Smrg vao = _mesa_lookup_vao_err(ctx, vaobj, true, 41027ec681f3Smrg "glGetVertexArrayPointervEXT"); 41037ec681f3Smrg if (!vao) 41047ec681f3Smrg return; 41057ec681f3Smrg 41067ec681f3Smrg /* The EXT_direct_state_access spec says: 41077ec681f3Smrg * 41087ec681f3Smrg * "For GetVertexArrayPointervEXT, pname must be a *_ARRAY_POINTER token from 41097ec681f3Smrg * tables 6.6, 6.7, and 6.8 excluding VERTEX_ATTRIB_ARRAY_POINT." 41107ec681f3Smrg */ 41117ec681f3Smrg switch (pname) { 41127ec681f3Smrg case GL_VERTEX_ARRAY_POINTER: 41137ec681f3Smrg case GL_COLOR_ARRAY_POINTER: 41147ec681f3Smrg case GL_EDGE_FLAG_ARRAY_POINTER: 41157ec681f3Smrg case GL_INDEX_ARRAY_POINTER: 41167ec681f3Smrg case GL_NORMAL_ARRAY_POINTER: 41177ec681f3Smrg case GL_TEXTURE_COORD_ARRAY_POINTER: 41187ec681f3Smrg case GL_FOG_COORD_ARRAY_POINTER: 41197ec681f3Smrg case GL_SECONDARY_COLOR_ARRAY_POINTER: 41207ec681f3Smrg break; 41217ec681f3Smrg 41227ec681f3Smrg default: 41237ec681f3Smrg _mesa_error(ctx, GL_INVALID_ENUM, "glGetVertexArrayPointervEXT(pname)"); 41247ec681f3Smrg return; 41257ec681f3Smrg } 41267ec681f3Smrg 41277ec681f3Smrg /* pname has been validated, we can now use the helper function */ 41287ec681f3Smrg _get_vao_pointerv(pname, vao, param, "glGetVertexArrayPointervEXT"); 41297ec681f3Smrg} 41307ec681f3Smrg 41317ec681f3Smrgvoid GLAPIENTRY 41327ec681f3Smrg_mesa_GetVertexArrayIntegeri_vEXT(GLuint vaobj, GLuint index, GLenum pname, GLint *param) 41337ec681f3Smrg{ 41347ec681f3Smrg GET_CURRENT_CONTEXT(ctx); 41357ec681f3Smrg struct gl_vertex_array_object* vao; 41367ec681f3Smrg struct gl_buffer_object *buf; 41377ec681f3Smrg 41387ec681f3Smrg vao = _mesa_lookup_vao_err(ctx, vaobj, true, 41397ec681f3Smrg "glGetVertexArrayIntegeri_vEXT"); 41407ec681f3Smrg if (!vao) 41417ec681f3Smrg return; 41427ec681f3Smrg 41437ec681f3Smrg 41447ec681f3Smrg /* The EXT_direct_state_access spec says: 41457ec681f3Smrg * 41467ec681f3Smrg * "For GetVertexArrayIntegeri_vEXT, pname must be one of the 41477ec681f3Smrg * "Get value" tokens in tables 6.8 and 6.9 that use GetVertexAttribiv 41487ec681f3Smrg * or GetVertexAttribPointerv (so allowing only the VERTEX_ATTRIB_* 41497ec681f3Smrg * tokens) or a token of the form TEXTURE_COORD_ARRAY (the enable) or 41507ec681f3Smrg * TEXTURE_COORD_ARRAY_*; index identifies the vertex attribute 41517ec681f3Smrg * array to query or texture coordinate set index respectively." 41527ec681f3Smrg */ 41537ec681f3Smrg 41547ec681f3Smrg switch (pname) { 41557ec681f3Smrg case GL_TEXTURE_COORD_ARRAY: 41567ec681f3Smrg *param = !!(vao->Enabled & VERT_BIT_TEX(index)); 41577ec681f3Smrg break; 41587ec681f3Smrg case GL_TEXTURE_COORD_ARRAY_SIZE: 41597ec681f3Smrg *param = vao->VertexAttrib[VERT_ATTRIB_TEX(index)].Format.Size; 41607ec681f3Smrg break; 41617ec681f3Smrg case GL_TEXTURE_COORD_ARRAY_TYPE: 41627ec681f3Smrg *param = vao->VertexAttrib[VERT_ATTRIB_TEX(index)].Format.Type; 41637ec681f3Smrg break; 41647ec681f3Smrg case GL_TEXTURE_COORD_ARRAY_STRIDE: 41657ec681f3Smrg *param = vao->VertexAttrib[VERT_ATTRIB_TEX(index)].Stride; 41667ec681f3Smrg break; 41677ec681f3Smrg case GL_TEXTURE_COORD_ARRAY_BUFFER_BINDING: 41687ec681f3Smrg buf = vao->BufferBinding[VERT_ATTRIB_TEX(index)].BufferObj; 41697ec681f3Smrg *param = buf ? buf->Name : 0; 41707ec681f3Smrg break; 41717ec681f3Smrg default: 41727ec681f3Smrg *param = get_vertex_array_attrib(ctx, vao, index, pname, "glGetVertexArrayIntegeri_vEXT"); 41737ec681f3Smrg } 41747ec681f3Smrg} 41757ec681f3Smrg 41767ec681f3Smrgvoid GLAPIENTRY 41777ec681f3Smrg_mesa_GetVertexArrayPointeri_vEXT(GLuint vaobj, GLuint index, GLenum pname, GLvoid** param) 41787ec681f3Smrg{ 41797ec681f3Smrg GET_CURRENT_CONTEXT(ctx); 41807ec681f3Smrg struct gl_vertex_array_object* vao; 41817ec681f3Smrg 41827ec681f3Smrg vao = _mesa_lookup_vao_err(ctx, vaobj, true, 41837ec681f3Smrg "glGetVertexArrayPointeri_vEXT"); 41847ec681f3Smrg if (!vao) 41857ec681f3Smrg return; 41867ec681f3Smrg 41877ec681f3Smrg if (index >= ctx->Const.Program[MESA_SHADER_VERTEX].MaxAttribs) { 41887ec681f3Smrg _mesa_error(ctx, GL_INVALID_VALUE, "glGetVertexArrayPointeri_vEXT(index)"); 41897ec681f3Smrg return; 41907ec681f3Smrg } 41917ec681f3Smrg 41927ec681f3Smrg /* The EXT_direct_state_access spec says: 41937ec681f3Smrg * 41947ec681f3Smrg * "For GetVertexArrayPointeri_vEXT, pname must be VERTEX_ATTRIB_ARRAY_POINTER 41957ec681f3Smrg * or TEXTURE_COORD_ARRAY_POINTER with the index parameter indicating the vertex 41967ec681f3Smrg * attribute or texture coordindate set index." 41977ec681f3Smrg */ 41987ec681f3Smrg switch(pname) { 41997ec681f3Smrg case GL_VERTEX_ATTRIB_ARRAY_POINTER: 42007ec681f3Smrg *param = (GLvoid *) vao->VertexAttrib[VERT_ATTRIB_GENERIC(index)].Ptr; 42017ec681f3Smrg break; 42027ec681f3Smrg case GL_TEXTURE_COORD_ARRAY_POINTER: 42037ec681f3Smrg *param = (GLvoid *) vao->VertexAttrib[VERT_ATTRIB_TEX(index)].Ptr; 42047ec681f3Smrg break; 42057ec681f3Smrg default: 42067ec681f3Smrg _mesa_error(ctx, GL_INVALID_ENUM, "glGetVertexArrayPointeri_vEXT(pname)"); 42077ec681f3Smrg } 42087ec681f3Smrg} 4209