1 /*
2 * Copyright (C) 2011 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16 #ifndef _GL_CLIENT_STATE_H_
17 #define _GL_CLIENT_STATE_H_
18 
19 #define GL_API
20 #ifndef ANDROID
21 #define GL_APIENTRY
22 #define GL_APIENTRYP
23 #endif
24 
25 #include "TextureSharedData.h"
26 
27 #include <GLES/gl.h>
28 #include <GLES/glext.h>
29 #include <GLES2/gl2.h>
30 #include <GLES2/gl2ext.h>
31 
32 #include <stdio.h>
33 #include <stdlib.h>
34 #include "ErrorLog.h"
35 #include "codec_defs.h"
36 
37 #include <vector>
38 #include <map>
39 #include <set>
40 
41 // Tracking framebuffer objects:
42 // which framebuffer is bound,
43 // and which texture names
44 // are currently bound to which attachment points.
45 struct FboProps {
46     GLuint name;
47     bool previouslyBound;
48     std::vector<GLuint> colorAttachmenti_textures;
49     GLuint depthAttachment_texture;
50     GLuint stencilAttachment_texture;
51     GLuint depthstencilAttachment_texture;
52 
53     std::vector<bool> colorAttachmenti_hasTex;
54     bool depthAttachment_hasTexObj;
55     bool stencilAttachment_hasTexObj;
56     bool depthstencilAttachment_hasTexObj;
57 
58     std::vector<GLuint> colorAttachmenti_rbos;
59     GLuint depthAttachment_rbo;
60     GLuint stencilAttachment_rbo;
61     GLuint depthstencilAttachment_rbo;
62 
63     std::vector<bool> colorAttachmenti_hasRbo;
64     bool depthAttachment_hasRbo;
65     bool stencilAttachment_hasRbo;
66     bool depthstencilAttachment_hasRbo;
67 };
68 
69 // Same for Rbo's
70 struct RboProps {
71     GLenum target;
72     GLuint name;
73     GLenum format;
74     GLsizei multisamples;
75     bool previouslyBound;
76 };
77 
78 // Enum for describing whether a framebuffer attachment
79 // is a texture or renderbuffer.
80 enum FboAttachmentType {
81     FBO_ATTACHMENT_RENDERBUFFER = 0,
82     FBO_ATTACHMENT_TEXTURE = 1,
83     FBO_ATTACHMENT_NONE = 2
84 };
85 
86 // Tracking FBO format
87 struct FboFormatInfo {
88     FboAttachmentType type;
89     GLenum rb_format;
90     GLsizei rb_multisamples;
91 
92     GLint tex_internalformat;
93     GLenum tex_format;
94     GLenum tex_type;
95     GLsizei tex_multisamples;
96 };
97 
98 class GLClientState {
99 public:
100     typedef enum {
101         VERTEX_LOCATION = 0,
102         NORMAL_LOCATION = 1,
103         COLOR_LOCATION = 2,
104         POINTSIZE_LOCATION = 3,
105         TEXCOORD0_LOCATION = 4,
106         TEXCOORD1_LOCATION = 5,
107         TEXCOORD2_LOCATION = 6,
108         TEXCOORD3_LOCATION = 7,
109         TEXCOORD4_LOCATION = 8,
110         TEXCOORD5_LOCATION = 9,
111         TEXCOORD6_LOCATION = 10,
112         TEXCOORD7_LOCATION = 11,
113         MATRIXINDEX_LOCATION = 12,
114         WEIGHT_LOCATION = 13,
115         LAST_LOCATION = 14
116     } StateLocation;
117 
118     typedef struct {
119         GLint enabled;
120         GLint size;
121         GLenum type;
122         GLsizei stride;
123         void *data;
124         GLuint reloffset;
125         GLuint bufferObject;
126         GLenum glConst;
127         unsigned int elementSize;
128         bool enableDirty;  // true if any enable state has changed since last draw
129         bool normalized;
130         GLuint divisor;
131         bool isInt;
132         int bindingindex;
133     } VertexAttribState;
134 
135     struct BufferBinding {
136         GLintptr offset;
137         GLintptr stride;
138         GLintptr effectiveStride;
139         GLsizeiptr size;
140         GLuint buffer;
141         GLuint divisor;
142     };
143 
144     typedef std::vector<VertexAttribState> VertexAttribStateVector;
145     typedef std::vector<BufferBinding> VertexAttribBindingVector;
146 
147     struct VAOState {
VAOStateVAOState148         VAOState(GLuint ibo, int nLoc, int nBindings) :
149             element_array_buffer_binding(ibo),
150             attribState(nLoc),
151             bindingState(nBindings) { }
152         VertexAttribStateVector attribState;
153         VertexAttribBindingVector bindingState;
154         GLuint element_array_buffer_binding;
155     };
156 
157     typedef std::map<GLuint, VAOState> VAOStateMap;
158     struct VAOStateRef {
VAOStateRefVAOStateRef159         VAOStateRef() { }
VAOStateRefVAOStateRef160         VAOStateRef(
161                 VAOStateMap::iterator iter) : it(iter) { }
162         VertexAttribState& operator[](size_t k) { return it->second.attribState[k]; }
bufferBindingVAOStateRef163         BufferBinding& bufferBinding(size_t k) { return it->second.bindingState[k]; }
bufferBindingsVAOStateRef164         VertexAttribBindingVector& bufferBindings() { return it->second.bindingState; }
bufferBindings_constVAOStateRef165         const VertexAttribBindingVector& bufferBindings_const() const { return it->second.bindingState; }
vaoIdVAOStateRef166         GLuint vaoId() const { return it->first; }
iboIdVAOStateRef167         GLuint& iboId() { return it->second.element_array_buffer_binding; }
168         VAOStateMap::iterator it;
169     };
170 
171     typedef struct {
172         int unpack_alignment;
173 
174         int unpack_row_length;
175         int unpack_image_height;
176         int unpack_skip_pixels;
177         int unpack_skip_rows;
178         int unpack_skip_images;
179 
180         int pack_alignment;
181 
182         int pack_row_length;
183         int pack_skip_pixels;
184         int pack_skip_rows;
185     } PixelStoreState;
186 
187     enum {
188         MAX_TEXTURE_UNITS = 256,
189     };
190 
191 public:
192     GLClientState();
193     GLClientState(int majorVersion, int minorVersion);
194     ~GLClientState();
nLocations()195     int nLocations() { return m_nLocations; }
pixelStoreState()196     const PixelStoreState *pixelStoreState() { return &m_pixelStore; }
197     int setPixelStore(GLenum param, GLint value);
currentVertexArrayObject()198     GLuint currentVertexArrayObject() const { return m_currVaoState.vaoId(); }
currentVertexBufferBindings()199     const VertexAttribBindingVector& currentVertexBufferBindings() const {
200         return m_currVaoState.bufferBindings_const();
201     }
202 
currentArrayVbo()203     GLuint currentArrayVbo() { return m_arrayBuffer; }
currentIndexVbo()204     GLuint currentIndexVbo() { return m_currVaoState.iboId(); }
205     void enable(int location, int state);
206     // Vertex array objects and vertex attributes
207     void addVertexArrayObjects(GLsizei n, GLuint* arrays);
208     void removeVertexArrayObjects(GLsizei n, const GLuint* arrays);
209     void addVertexArrayObject(GLuint name);
210     void removeVertexArrayObject(GLuint name);
211     void setVertexArrayObject(GLuint vao);
212     bool isVertexArrayObject(GLuint vao) const;
213     void setVertexAttribState(int  location, int size, GLenum type, GLboolean normalized, GLsizei stride, const void *data, bool isInt = false);
214     void setVertexBindingDivisor(int bindingindex, GLuint divisor);
215     const BufferBinding& getCurrAttributeBindingInfo(int attribindex);
216     void setVertexAttribBinding(int attribindex, int bindingindex);
217     void setVertexAttribFormat(int location, int size, GLenum type, GLboolean normalized, GLuint reloffset, bool isInt = false);
218     const VertexAttribState& getState(int location);
219     const VertexAttribState& getStateAndEnableDirty(int location, bool *enableChanged);
220     int getLocation(GLenum loc);
setActiveTexture(int texUnit)221     void setActiveTexture(int texUnit) {m_activeTexture = texUnit; };
getActiveTexture()222     int getActiveTexture() const { return m_activeTexture; }
setMaxVertexAttribs(int val)223     void setMaxVertexAttribs(int val) {
224         m_maxVertexAttribs = val;
225         m_maxVertexAttribsDirty = false;
226     }
227 
228     void addBuffer(GLuint id);
229     void removeBuffer(GLuint id);
230     bool bufferIdExists(GLuint id) const;
231     void unBindBuffer(GLuint id);
232 
233     int bindBuffer(GLenum target, GLuint id);
234     void bindIndexedBuffer(GLenum target, GLuint index, GLuint buffer, GLintptr offset, GLsizeiptr size, GLintptr stride, GLintptr effectiveStride);
235     int getMaxIndexedBufferBindings(GLenum target) const;
236 
237     int getBuffer(GLenum target);
238 
239     size_t pixelDataSize(GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLenum type, int pack) const;
240     size_t pboNeededDataSize(GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLenum type, int pack) const;
241     size_t clearBufferNumElts(GLenum buffer) const;
242 
setCurrentProgram(GLint program)243     void setCurrentProgram(GLint program) { m_currentProgram = program; }
setCurrentShaderProgram(GLint program)244     void setCurrentShaderProgram(GLint program) { m_currentShaderProgram = program; }
currentProgram()245     GLint currentProgram() const { return m_currentProgram; }
currentShaderProgram()246     GLint currentShaderProgram() const { return m_currentShaderProgram; }
247 
248     struct UniformBlockInfoKey {
249         GLuint program;
250         GLuint uniformBlockIndex;
251     };
252     struct UniformBlockInfoKeyCompare {
operatorUniformBlockInfoKeyCompare253         bool operator() (const UniformBlockInfoKey& a,
254                          const UniformBlockInfoKey& b) const {
255             if (a.program != b.program) return a.program < b.program;
256             if (a.uniformBlockIndex != b.uniformBlockIndex) return a.uniformBlockIndex < b.uniformBlockIndex;
257             return false;
258         }
259     };
260     struct UniformBlockUniformInfo {
261         size_t numActiveUniforms;
262     };
263 
264     typedef std::map<UniformBlockInfoKey, UniformBlockUniformInfo, UniformBlockInfoKeyCompare> UniformBlockInfoMap;
265     UniformBlockInfoMap m_uniformBlockInfoMap;
266 
267     void setNumActiveUniformsInUniformBlock(GLuint program, GLuint uniformBlockIndex, GLint numActiveUniforms);
268     size_t numActiveUniformsInUniformBlock(GLuint program, GLuint uniformBlockIndex) const;
269 
270     typedef std::map<GLuint, GLuint> ProgramPipelineMap;
271     typedef ProgramPipelineMap::iterator ProgramPipelineIterator;
272     void associateProgramWithPipeline(GLuint program, GLuint pipeline);
273     ProgramPipelineIterator programPipelineBegin();
274     ProgramPipelineIterator programPipelineEnd();
275 
276     /* OES_EGL_image_external
277      *
278      * These functions manipulate GL state which interacts with the
279      * OES_EGL_image_external extension, to support client-side emulation on
280      * top of host implementations that don't have it.
281      *
282      * Most of these calls should only be used with TEXTURE_2D or
283      * TEXTURE_EXTERNAL_OES texture targets; TEXTURE_CUBE_MAP or other extension
284      * targets should bypass this. An exception is bindTexture(), which should
285      * see all glBindTexture() calls for any target.
286      */
287 
288     // glActiveTexture(GL_TEXTURE0 + i)
289     // Sets the active texture unit. Up to MAX_TEXTURE_UNITS are supported.
290     GLenum setActiveTextureUnit(GLenum texture);
291     GLenum getActiveTextureUnit() const;
292 
293     // glEnable(GL_TEXTURE_(2D|EXTERNAL_OES))
294     void enableTextureTarget(GLenum target);
295 
296     // glDisable(GL_TEXTURE_(2D|EXTERNAL_OES))
297     void disableTextureTarget(GLenum target);
298 
299     // Implements the target priority logic:
300     // * Return GL_TEXTURE_EXTERNAL_OES if enabled, else
301     // * Return GL_TEXTURE_2D if enabled, else
302     // * Return the allDisabled value.
303     // For some cases passing GL_TEXTURE_2D for allDisabled makes callee code
304     // simpler; for other cases passing a recognizable enum like GL_ZERO or
305     // GL_INVALID_ENUM is appropriate.
306     GLenum getPriorityEnabledTarget(GLenum allDisabled) const;
307 
308     // glBindTexture(GL_TEXTURE_*, ...)
309     // Set the target binding of the active texture unit to texture. Returns
310     // GL_NO_ERROR on success or GL_INVALID_OPERATION if the texture has
311     // previously been bound to a different target. If firstUse is not NULL,
312     // it is set to indicate whether this is the first use of the texture.
313     // For accurate error detection, bindTexture should be called for *all*
314     // targets, not just 2D and EXTERNAL_OES.
315     GLenum bindTexture(GLenum target, GLuint texture, GLboolean* firstUse);
316     void setBoundEGLImage(GLenum target, GLeglImageOES image);
317 
318     // Return the texture currently bound to GL_TEXTURE_(2D|EXTERNAL_OES).
319     GLuint getBoundTexture(GLenum target) const;
320     // Other publicly-visible texture queries
321     GLenum queryTexLastBoundTarget(GLuint name) const;
322     GLenum queryTexFormat(GLuint name) const;
323     GLint queryTexInternalFormat(GLuint name) const;
324     GLsizei queryTexWidth(GLsizei level, GLuint name) const;
325     GLsizei queryTexHeight(GLsizei level, GLuint name) const;
326     GLsizei queryTexDepth(GLsizei level, GLuint name) const;
327     bool queryTexEGLImageBacked(GLuint name) const;
328 
329     // For AMD GPUs, it is easy for the emulator to segfault
330     // (esp. in dEQP) when a cube map is defined using glCopyTexImage2D
331     // and uses GL_LUMINANCE as internal format.
332     // In particular, the segfault happens when negative components of
333     // cube maps are defined before positive ones,
334     // This procedure checks internal state to see if we have defined
335     // the positive component of a cube map already. If not, it returns
336     // which positive component needs to be defined first.
337     // If there is no need for the extra definition, 0 is returned.
338     GLenum copyTexImageLuminanceCubeMapAMDWorkaround(GLenum target, GLint level,
339                                                      GLenum internalformat);
340 
341     // Tracks the format of the currently bound texture.
342     // This is to pass dEQP tests for fbo completeness.
343     void setBoundTextureInternalFormat(GLenum target, GLint format);
344     void setBoundTextureFormat(GLenum target, GLenum format);
345     void setBoundTextureType(GLenum target, GLenum type);
346     void setBoundTextureDims(GLenum target, GLsizei level, GLsizei width, GLsizei height, GLsizei depth);
347     void setBoundTextureSamples(GLenum target, GLsizei samples);
348 
349     // glTexStorage2D disallows any change in texture format after it is set for a particular texture.
350     void setBoundTextureImmutableFormat(GLenum target);
351     bool isBoundTextureImmutableFormat(GLenum target) const;
352 
353     // glDeleteTextures(...)
354     // Remove references to the to-be-deleted textures.
355     void deleteTextures(GLsizei n, const GLuint* textures);
356 
357     // Render buffer objects
358     void addRenderbuffers(GLsizei n, GLuint* renderbuffers);
359     void removeRenderbuffers(GLsizei n, const GLuint* renderbuffers);
360     bool usedRenderbufferName(GLuint name) const;
361     void bindRenderbuffer(GLenum target, GLuint name);
362     GLuint boundRenderbuffer() const;
363     void setBoundRenderbufferFormat(GLenum format);
364     void setBoundRenderbufferSamples(GLsizei samples);
365 
366     // Frame buffer objects
367     void addFramebuffers(GLsizei n, GLuint* framebuffers);
368     void removeFramebuffers(GLsizei n, const GLuint* framebuffers);
369     bool usedFramebufferName(GLuint name) const;
370     void bindFramebuffer(GLenum target, GLuint name);
371     void setCheckFramebufferStatus(GLenum target, GLenum status);
372     GLenum getCheckFramebufferStatus(GLenum target) const;
373     GLuint boundFramebuffer(GLenum target) const;
374 
375     // Texture object -> FBO
376     void attachTextureObject(GLenum target, GLenum attachment, GLuint texture);
377     GLuint getFboAttachmentTextureId(GLenum target, GLenum attachment) const;
378 
379     // RBO -> FBO
380     void detachRbo(GLuint renderbuffer);
381     void detachRboFromFbo(GLenum target, GLenum attachment, GLuint renderbuffer);
382     void attachRbo(GLenum target, GLenum attachment, GLuint renderbuffer);
383     GLuint getFboAttachmentRboId(GLenum target, GLenum attachment) const;
384 
385     // FBO attachments in general
386     bool attachmentHasObject(GLenum target, GLenum attachment) const;
387     GLuint objectOfAttachment(GLenum target, GLenum attachment) const;
388 
389     // Transform feedback state
390     void setTransformFeedbackActiveUnpaused(bool activeUnpaused);
391     bool getTransformFeedbackActiveUnpaused() const;
392 
393     void setTextureData(SharedTextureDataMap* sharedTexData);
394     // set eglsurface property on default framebuffer
395     // if coming from eglMakeCurrent
396     void fromMakeCurrent();
397     // set indexed buffer state.
398     // We need to query the underlying OpenGL to get
399     // accurate values for indexed buffers
400     // and # render targets.
401     void initFromCaps(
402         int max_transform_feedback_separate_attribs,
403         int max_uniform_buffer_bindings,
404         int max_atomic_counter_buffer_bindings,
405         int max_shader_storage_buffer_bindings,
406         int max_vertex_attrib_bindings,
407         int max_color_attachments,
408         int max_draw_buffers);
409     bool needsInitFromCaps() const;
410 
411     // Queries the format backing the current framebuffer.
412     // Type differs depending on whether the attachment
413     // is a texture or renderbuffer.
414     void getBoundFramebufferFormat(
415             GLenum target,
416             GLenum attachment,
417             FboFormatInfo* res_info) const;
418     FboAttachmentType getBoundFramebufferAttachmentType(
419             GLenum target,
420             GLenum attachment) const;
421     int getMaxColorAttachments() const;
422     int getMaxDrawBuffers() const;
423 private:
424     void init();
425     bool m_initialized;
426     PixelStoreState m_pixelStore;
427 
428     std::set<GLuint> mBufferIds;
429 
430     // GL_ARRAY_BUFFER_BINDING is separate from VAO state
431     GLuint m_arrayBuffer;
432     VAOStateMap m_vaoMap;
433     VAOStateRef m_currVaoState;
434 
435     // Other buffer id's, other targets
436     GLuint m_copyReadBuffer;
437     GLuint m_copyWriteBuffer;
438 
439     GLuint m_pixelPackBuffer;
440     GLuint m_pixelUnpackBuffer;
441 
442     GLuint m_transformFeedbackBuffer;
443     GLuint m_uniformBuffer;
444 
445     GLuint m_atomicCounterBuffer;
446     GLuint m_dispatchIndirectBuffer;
447     GLuint m_drawIndirectBuffer;
448     GLuint m_shaderStorageBuffer;
449 
450     bool m_transformFeedbackActiveUnpaused;
451 
452     int m_max_transform_feedback_separate_attribs;
453     int m_max_uniform_buffer_bindings;
454     int m_max_atomic_counter_buffer_bindings;
455     int m_max_shader_storage_buffer_bindings;
456     int m_max_vertex_attrib_bindings;
457     std::vector<BufferBinding> m_indexedTransformFeedbackBuffers;
458     std::vector<BufferBinding> m_indexedUniformBuffers;
459     std::vector<BufferBinding> m_indexedAtomicCounterBuffers;
460     std::vector<BufferBinding> m_indexedShaderStorageBuffers;
461 
462     int m_glesMajorVersion;
463     int m_glesMinorVersion;
464     int m_maxVertexAttribs;
465     bool m_maxVertexAttribsDirty;
466     int m_nLocations;
467     int m_activeTexture;
468     GLint m_currentProgram;
469     GLint m_currentShaderProgram;
470     ProgramPipelineMap m_programPipelines;
471 
472     enum TextureTarget {
473         TEXTURE_2D = 0,
474         TEXTURE_EXTERNAL = 1,
475         TEXTURE_CUBE_MAP = 2,
476         TEXTURE_2D_ARRAY = 3,
477         TEXTURE_3D = 4,
478         TEXTURE_2D_MULTISAMPLE = 5,
479         TEXTURE_TARGET_COUNT
480     };
481     struct TextureUnit {
482         unsigned int enables;
483         GLuint texture[TEXTURE_TARGET_COUNT];
484     };
485     struct TextureState {
486         TextureUnit unit[MAX_TEXTURE_UNITS];
487         TextureUnit* activeUnit;
488         // Initialized from shared group.
489         SharedTextureDataMap* textureRecs;
490     };
491     TextureState m_tex;
492 
493     // State tracking of cube map definitions.
494     // Currently used only for driver workarounds
495     // when using GL_LUMINANCE and defining cube maps with
496     // glCopyTexImage2D.
497     struct CubeMapDef {
498         GLuint id;
499         GLenum target;
500         GLint level;
501         GLenum internalformat;
502     };
503     struct CubeMapDefCompare {
operatorCubeMapDefCompare504         bool operator() (const CubeMapDef& a,
505                          const CubeMapDef& b) const {
506             if (a.id != b.id) return a.id < b.id;
507             if (a.target != b.target) return a.target < b.target;
508             if (a.level != b.level) return a.level < b.level;
509             if (a.internalformat != b.internalformat)
510                 return a.internalformat < b.internalformat;
511             return false;
512         }
513     };
514     std::set<CubeMapDef, CubeMapDefCompare> m_cubeMapDefs;
515     void writeCopyTexImageState(GLenum target, GLint level,
516                                 GLenum internalformat);
517     GLenum copyTexImageNeededTarget(GLenum target, GLint level,
518                                     GLenum internalformat);
519 
520     int m_max_color_attachments;
521     int m_max_draw_buffers;
522     struct RboState {
523         GLuint boundRenderbuffer;
524         size_t boundRenderbufferIndex;
525         std::vector<RboProps> rboData;
526     };
527     RboState mRboState;
528     void addFreshRenderbuffer(GLuint name);
529     void setBoundRenderbufferIndex();
530     size_t getRboIndex(GLuint name) const;
531     RboProps& boundRboProps();
532     const RboProps& boundRboProps_const() const;
533 
534     struct FboState {
535         GLuint boundDrawFramebuffer;
536         GLuint boundReadFramebuffer;
537         size_t boundFramebufferIndex;
538         std::map<GLuint, FboProps> fboData;
539         GLenum drawFboCheckStatus;
540         GLenum readFboCheckStatus;
541     };
542     FboState mFboState;
543     void addFreshFramebuffer(GLuint name);
544     FboProps& boundFboProps(GLenum target);
545     const FboProps& boundFboProps_const(GLenum target) const;
546 
547     // Querying framebuffer format
548     GLenum queryRboFormat(GLuint name) const;
549     GLsizei queryRboSamples(GLuint name) const;
550     GLenum queryTexType(GLuint name) const;
551     GLsizei queryTexSamples(GLuint name) const;
552 
553     static int compareTexId(const void* pid, const void* prec);
554     TextureRec* addTextureRec(GLuint id, GLenum target);
555     TextureRec* getTextureRec(GLuint id) const;
556 
557 public:
558     void getClientStatePointer(GLenum pname, GLvoid** params);
559 
560     template <class T>
getVertexAttribParameter(GLuint index,GLenum param,T * ptr)561     int getVertexAttribParameter(GLuint index, GLenum param, T *ptr)
562     {
563         bool handled = true;
564         const VertexAttribState& vertexAttrib = getState(index);
565         const BufferBinding& vertexAttribBufferBinding =
566             m_currVaoState.bufferBindings_const()[vertexAttrib.bindingindex];
567 
568         switch(param) {
569 #define GL_VERTEX_ATTRIB_BINDING 0x82D4
570         case GL_VERTEX_ATTRIB_BINDING:
571             *ptr = (T)vertexAttrib.bindingindex;
572             break;
573 #define GL_VERTEX_ATTRIB_RELATIVE_OFFSET 0x82D5
574         case GL_VERTEX_ATTRIB_RELATIVE_OFFSET:
575             *ptr = (T)vertexAttrib.reloffset;
576             break;
577         case GL_VERTEX_ATTRIB_ARRAY_BUFFER_BINDING:
578             *ptr = (T)(vertexAttribBufferBinding.buffer);
579             break;
580         case GL_VERTEX_ATTRIB_ARRAY_ENABLED:
581             *ptr = (T)(vertexAttrib.enabled);
582             break;
583 #define GL_VERTEX_ATTRIB_ARRAY_INTEGER 0x88FD
584         case GL_VERTEX_ATTRIB_ARRAY_INTEGER:
585             *ptr = (T)(vertexAttrib.isInt);
586             break;
587         case GL_VERTEX_ATTRIB_ARRAY_SIZE:
588             *ptr = (T)(vertexAttrib.size);
589             break;
590         case GL_VERTEX_ATTRIB_ARRAY_STRIDE:
591             *ptr = (T)(vertexAttribBufferBinding.stride);
592             break;
593         case GL_VERTEX_ATTRIB_ARRAY_TYPE:
594             *ptr = (T)(vertexAttrib.type);
595             break;
596         case GL_VERTEX_ATTRIB_ARRAY_NORMALIZED:
597             *ptr = (T)(vertexAttrib.normalized);
598             break;
599         case GL_CURRENT_VERTEX_ATTRIB:
600             handled = false;
601             break;
602         default:
603             handled = false;
604             ERR("unknown vertex-attrib parameter param %d\n", param);
605         }
606         return handled;
607     }
608 
609     template <class T>
getClientStateParameter(GLenum param,T * out)610     bool getClientStateParameter(GLenum param, T* out)
611     {
612         bool isClientStateParam = false;
613         switch (param) {
614         case GL_CLIENT_ACTIVE_TEXTURE: {
615             GLint tex = getActiveTexture() + GL_TEXTURE0;
616             *out = tex;
617             isClientStateParam = true;
618             break;
619             }
620         case GL_VERTEX_ARRAY_SIZE: {
621             const GLClientState::VertexAttribState& state = getState(GLClientState::VERTEX_LOCATION);
622             *out = state.size;
623             isClientStateParam = true;
624             break;
625             }
626         case GL_VERTEX_ARRAY_TYPE: {
627             const GLClientState::VertexAttribState& state = getState(GLClientState::VERTEX_LOCATION);
628             *out = state.type;
629             isClientStateParam = true;
630             break;
631             }
632         case GL_VERTEX_ARRAY_STRIDE: {
633             const GLClientState::VertexAttribState& state = getState(GLClientState::VERTEX_LOCATION);
634             *out = state.stride;
635             isClientStateParam = true;
636             break;
637             }
638         case GL_COLOR_ARRAY_SIZE: {
639             const GLClientState::VertexAttribState& state = getState(GLClientState::COLOR_LOCATION);
640             *out = state.size;
641             isClientStateParam = true;
642             break;
643             }
644         case GL_COLOR_ARRAY_TYPE: {
645             const GLClientState::VertexAttribState& state = getState(GLClientState::COLOR_LOCATION);
646             *out = state.type;
647             isClientStateParam = true;
648             break;
649             }
650         case GL_COLOR_ARRAY_STRIDE: {
651             const GLClientState::VertexAttribState& state = getState(GLClientState::COLOR_LOCATION);
652             *out = state.stride;
653             isClientStateParam = true;
654             break;
655             }
656         case GL_NORMAL_ARRAY_TYPE: {
657             const GLClientState::VertexAttribState& state = getState(GLClientState::NORMAL_LOCATION);
658             *out = state.type;
659             isClientStateParam = true;
660             break;
661             }
662         case GL_NORMAL_ARRAY_STRIDE: {
663             const GLClientState::VertexAttribState& state = getState(GLClientState::NORMAL_LOCATION);
664             *out = state.stride;
665             isClientStateParam = true;
666             break;
667             }
668         case GL_TEXTURE_COORD_ARRAY_SIZE: {
669             const GLClientState::VertexAttribState& state = getState(getActiveTexture() + GLClientState::TEXCOORD0_LOCATION);
670             *out = state.size;
671             isClientStateParam = true;
672             break;
673             }
674         case GL_TEXTURE_COORD_ARRAY_TYPE: {
675             const GLClientState::VertexAttribState& state = getState(getActiveTexture() + GLClientState::TEXCOORD0_LOCATION);
676             *out = state.type;
677             isClientStateParam = true;
678             break;
679             }
680         case GL_TEXTURE_COORD_ARRAY_STRIDE: {
681             const GLClientState::VertexAttribState& state = getState(getActiveTexture() + GLClientState::TEXCOORD0_LOCATION);
682             *out = state.stride;
683             isClientStateParam = true;
684             break;
685             }
686         case GL_POINT_SIZE_ARRAY_TYPE_OES: {
687             const GLClientState::VertexAttribState& state = getState(GLClientState::POINTSIZE_LOCATION);
688             *out = state.type;
689             isClientStateParam = true;
690             break;
691             }
692         case GL_POINT_SIZE_ARRAY_STRIDE_OES: {
693             const GLClientState::VertexAttribState& state = getState(GLClientState::POINTSIZE_LOCATION);
694             *out = state.stride;
695             isClientStateParam = true;
696             break;
697             }
698         case GL_MATRIX_INDEX_ARRAY_SIZE_OES: {
699             const GLClientState::VertexAttribState& state = getState(GLClientState::MATRIXINDEX_LOCATION);
700             *out = state.size;
701             isClientStateParam = true;
702             break;
703             }
704         case GL_MATRIX_INDEX_ARRAY_TYPE_OES: {
705             const GLClientState::VertexAttribState& state = getState(GLClientState::MATRIXINDEX_LOCATION);
706             *out = state.type;
707             isClientStateParam = true;
708             break;
709             }
710         case GL_MATRIX_INDEX_ARRAY_STRIDE_OES: {
711             const GLClientState::VertexAttribState& state = getState(GLClientState::MATRIXINDEX_LOCATION);
712             *out = state.stride;
713             isClientStateParam = true;
714             break;
715             }
716         case GL_WEIGHT_ARRAY_SIZE_OES: {
717             const GLClientState::VertexAttribState& state = getState(GLClientState::WEIGHT_LOCATION);
718             *out = state.size;
719             isClientStateParam = true;
720             break;
721             }
722         case GL_WEIGHT_ARRAY_TYPE_OES: {
723             const GLClientState::VertexAttribState& state = getState(GLClientState::WEIGHT_LOCATION);
724             *out = state.type;
725             isClientStateParam = true;
726             break;
727             }
728         case GL_WEIGHT_ARRAY_STRIDE_OES: {
729             const GLClientState::VertexAttribState& state = getState(GLClientState::WEIGHT_LOCATION);
730             *out = state.stride;
731             isClientStateParam = true;
732             break;
733             }
734         case GL_VERTEX_ARRAY_BUFFER_BINDING: {
735             const GLClientState::VertexAttribState& state = getState(GLClientState::VERTEX_LOCATION);
736             *out = state.bufferObject;
737             isClientStateParam = true;
738             break;
739             }
740         case GL_NORMAL_ARRAY_BUFFER_BINDING: {
741             const GLClientState::VertexAttribState& state = getState(GLClientState::NORMAL_LOCATION);
742             *out = state.bufferObject;
743             isClientStateParam = true;
744             break;
745             }
746         case GL_COLOR_ARRAY_BUFFER_BINDING: {
747             const GLClientState::VertexAttribState& state = getState(GLClientState::COLOR_LOCATION);
748             *out = state.bufferObject;
749             isClientStateParam = true;
750             break;
751             }
752         case GL_TEXTURE_COORD_ARRAY_BUFFER_BINDING: {
753             const GLClientState::VertexAttribState& state = getState(getActiveTexture()+GLClientState::TEXCOORD0_LOCATION);
754             *out = state.bufferObject;
755             isClientStateParam = true;
756             break;
757             }
758         case GL_POINT_SIZE_ARRAY_BUFFER_BINDING_OES: {
759             const GLClientState::VertexAttribState& state = getState(GLClientState::POINTSIZE_LOCATION);
760             *out = state.bufferObject;
761             isClientStateParam = true;
762             break;
763             }
764         case GL_MATRIX_INDEX_ARRAY_BUFFER_BINDING_OES: {
765             const GLClientState::VertexAttribState& state = getState(GLClientState::MATRIXINDEX_LOCATION);
766             *out = state.bufferObject;
767             isClientStateParam = true;
768             break;
769             }
770         case GL_WEIGHT_ARRAY_BUFFER_BINDING_OES: {
771             const GLClientState::VertexAttribState& state = getState(GLClientState::WEIGHT_LOCATION);
772             *out = state.bufferObject;
773             isClientStateParam = true;
774             break;
775             }
776         case GL_ARRAY_BUFFER_BINDING: {
777             int buffer = getBuffer(GL_ARRAY_BUFFER);
778             *out = buffer;
779             isClientStateParam = true;
780             break;
781             }
782         case GL_ELEMENT_ARRAY_BUFFER_BINDING: {
783             int buffer = getBuffer(GL_ELEMENT_ARRAY_BUFFER);
784             *out = buffer;
785             isClientStateParam = true;
786             break;
787             }
788         case GL_MAX_VERTEX_ATTRIBS: {
789             if (m_maxVertexAttribsDirty) {
790                 isClientStateParam = false;
791             } else {
792                 *out = m_maxVertexAttribs;
793                 isClientStateParam = true;
794             }
795             break;
796         }
797         }
798         return isClientStateParam;
799     }
800 
801 };
802 #endif
803