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 <GLES/gl.h>
26#include <GLES/glext.h>
27#include <GLES2/gl2.h>
28#include <GLES2/gl2ext.h>
29
30#include <stdio.h>
31#include <stdlib.h>
32#include "ErrorLog.h"
33#include "codec_defs.h"
34
35class GLClientState {
36public:
37    typedef enum {
38        VERTEX_LOCATION = 0,
39        NORMAL_LOCATION = 1,
40        COLOR_LOCATION = 2,
41        POINTSIZE_LOCATION = 3,
42        TEXCOORD0_LOCATION = 4,
43        TEXCOORD1_LOCATION = 5,
44        TEXCOORD2_LOCATION = 6,
45        TEXCOORD3_LOCATION = 7,
46        TEXCOORD4_LOCATION = 8,
47        TEXCOORD5_LOCATION = 9,
48        TEXCOORD6_LOCATION = 10,
49        TEXCOORD7_LOCATION = 11,
50        MATRIXINDEX_LOCATION = 12,
51        WEIGHT_LOCATION = 13,
52        LAST_LOCATION = 14
53    } StateLocation;
54
55    typedef struct {
56        GLint enabled;
57        GLint size;
58        GLenum type;
59        GLsizei stride;
60        void *data;
61        GLuint bufferObject;
62        GLenum glConst;
63        unsigned int elementSize;
64        bool enableDirty;  // true if any enable state has changed since last draw
65        bool normalized;
66    } VertexAttribState;
67
68    typedef struct {
69        int unpack_alignment;
70        int pack_alignment;
71    } PixelStoreState;
72
73    enum {
74        MAX_TEXTURE_UNITS = 32,
75    };
76
77public:
78    GLClientState(int nLocations = CODEC_MAX_VERTEX_ATTRIBUTES);
79    ~GLClientState();
80    int nLocations() { return m_nLocations; }
81    const PixelStoreState *pixelStoreState() { return &m_pixelStore; }
82    int setPixelStore(GLenum param, GLint value);
83    GLuint currentArrayVbo() { return m_currentArrayVbo; }
84    GLuint currentIndexVbo() { return m_currentIndexVbo; }
85    void enable(int location, int state);
86    void setState(int  location, int size, GLenum type, GLboolean normalized, GLsizei stride, const void *data);
87    void setBufferObject(int location, GLuint id);
88    const VertexAttribState  *getState(int location);
89    const VertexAttribState  *getStateAndEnableDirty(int location, bool *enableChanged);
90    int getLocation(GLenum loc);
91    void setActiveTexture(int texUnit) {m_activeTexture = texUnit; };
92    int getActiveTexture() const { return m_activeTexture; }
93
94    int bindBuffer(GLenum target, GLuint id)
95    {
96        int err = 0;
97        switch(target) {
98        case GL_ARRAY_BUFFER:
99            m_currentArrayVbo = id;
100            break;
101        case GL_ELEMENT_ARRAY_BUFFER:
102            m_currentIndexVbo = id;
103            break;
104        default:
105            err = -1;
106        }
107        return err;
108    }
109
110    int getBuffer(GLenum target)
111    {
112      int ret=0;
113      switch (target) {
114      case GL_ARRAY_BUFFER:
115          ret = m_currentArrayVbo;
116          break;
117      case GL_ELEMENT_ARRAY_BUFFER:
118          ret = m_currentIndexVbo;
119          break;
120      default:
121          ret = -1;
122      }
123      return ret;
124    }
125    size_t pixelDataSize(GLsizei width, GLsizei height, GLenum format, GLenum type, int pack) const;
126
127    void setCurrentProgram(GLint program) { m_currentProgram = program; }
128    GLint currentProgram() const { return m_currentProgram; }
129
130    /* OES_EGL_image_external
131     *
132     * These functions manipulate GL state which interacts with the
133     * OES_EGL_image_external extension, to support client-side emulation on
134     * top of host implementations that don't have it.
135     *
136     * Most of these calls should only be used with TEXTURE_2D or
137     * TEXTURE_EXTERNAL_OES texture targets; TEXTURE_CUBE_MAP or other extension
138     * targets should bypass this. An exception is bindTexture(), which should
139     * see all glBindTexture() calls for any target.
140     */
141
142    // glActiveTexture(GL_TEXTURE0 + i)
143    // Sets the active texture unit. Up to MAX_TEXTURE_UNITS are supported.
144    GLenum setActiveTextureUnit(GLenum texture);
145    GLenum getActiveTextureUnit() const;
146
147    // glEnable(GL_TEXTURE_(2D|EXTERNAL_OES))
148    void enableTextureTarget(GLenum target);
149
150    // glDisable(GL_TEXTURE_(2D|EXTERNAL_OES))
151    void disableTextureTarget(GLenum target);
152
153    // Implements the target priority logic:
154    // * Return GL_TEXTURE_EXTERNAL_OES if enabled, else
155    // * Return GL_TEXTURE_2D if enabled, else
156    // * Return the allDisabled value.
157    // For some cases passing GL_TEXTURE_2D for allDisabled makes callee code
158    // simpler; for other cases passing a recognizable enum like GL_ZERO or
159    // GL_INVALID_ENUM is appropriate.
160    GLenum getPriorityEnabledTarget(GLenum allDisabled) const;
161
162    // glBindTexture(GL_TEXTURE_*, ...)
163    // Set the target binding of the active texture unit to texture. Returns
164    // GL_NO_ERROR on success or GL_INVALID_OPERATION if the texture has
165    // previously been bound to a different target. If firstUse is not NULL,
166    // it is set to indicate whether this is the first use of the texture.
167    // For accurate error detection, bindTexture should be called for *all*
168    // targets, not just 2D and EXTERNAL_OES.
169    GLenum bindTexture(GLenum target, GLuint texture, GLboolean* firstUse);
170
171    // Return the texture currently bound to GL_TEXTURE_(2D|EXTERNAL_OES).
172    GLuint getBoundTexture(GLenum target) const;
173
174    // glDeleteTextures(...)
175    // Remove references to the to-be-deleted textures.
176    void deleteTextures(GLsizei n, const GLuint* textures);
177
178private:
179    PixelStoreState m_pixelStore;
180    VertexAttribState *m_states;
181    int m_nLocations;
182    GLuint m_currentArrayVbo;
183    GLuint m_currentIndexVbo;
184    int m_activeTexture;
185    GLint m_currentProgram;
186
187    bool validLocation(int location) { return (location >= 0 && location < m_nLocations); }
188
189    enum TextureTarget {
190        TEXTURE_2D = 0,
191        TEXTURE_EXTERNAL = 1,
192        TEXTURE_TARGET_COUNT
193    };
194    struct TextureUnit {
195        unsigned int enables;
196        GLuint texture[TEXTURE_TARGET_COUNT];
197    };
198    struct TextureRec {
199        GLuint id;
200        GLenum target;
201    };
202    struct TextureState {
203        TextureUnit unit[MAX_TEXTURE_UNITS];
204        TextureUnit* activeUnit;
205        TextureRec* textures;
206        GLuint numTextures;
207        GLuint allocTextures;
208    };
209    TextureState m_tex;
210
211    static int compareTexId(const void* pid, const void* prec);
212    TextureRec* addTextureRec(GLuint id, GLenum target);
213
214public:
215    void getClientStatePointer(GLenum pname, GLvoid** params);
216
217    template <class T>
218    int getVertexAttribParameter(GLuint index, GLenum param, T *ptr)
219    {
220        bool handled = true;
221        const VertexAttribState *vertexAttrib = getState(index);
222        if (vertexAttrib == NULL) {
223            ERR("getVeterxAttriParameter for non existant index %d\n", index);
224            // set gl error;
225            return handled;
226        }
227
228        switch(param) {
229        case GL_VERTEX_ATTRIB_ARRAY_BUFFER_BINDING:
230            *ptr = (T)(vertexAttrib->bufferObject);
231            break;
232        case GL_VERTEX_ATTRIB_ARRAY_ENABLED:
233            *ptr = (T)(vertexAttrib->enabled);
234            break;
235        case GL_VERTEX_ATTRIB_ARRAY_SIZE:
236            *ptr = (T)(vertexAttrib->size);
237            break;
238        case GL_VERTEX_ATTRIB_ARRAY_STRIDE:
239            *ptr = (T)(vertexAttrib->stride);
240            break;
241        case GL_VERTEX_ATTRIB_ARRAY_TYPE:
242            *ptr = (T)(vertexAttrib->type);
243            break;
244        case GL_VERTEX_ATTRIB_ARRAY_NORMALIZED:
245            *ptr = (T)(vertexAttrib->normalized);
246            break;
247        case GL_CURRENT_VERTEX_ATTRIB:
248            handled = false;
249            break;
250        default:
251            handled = false;
252            ERR("unknown vertex-attrib parameter param %d\n", param);
253        }
254        return handled;
255    }
256
257    template <class T>
258    bool getClientStateParameter(GLenum param, T* ptr)
259    {
260        bool isClientStateParam = false;
261        switch (param) {
262        case GL_CLIENT_ACTIVE_TEXTURE: {
263            GLint tex = getActiveTexture() + GL_TEXTURE0;
264            *ptr = tex;
265            isClientStateParam = true;
266            break;
267            }
268        case GL_VERTEX_ARRAY_SIZE: {
269            const GLClientState::VertexAttribState *state = getState(GLClientState::VERTEX_LOCATION);
270            *ptr = state->size;
271            isClientStateParam = true;
272            break;
273            }
274        case GL_VERTEX_ARRAY_TYPE: {
275            const GLClientState::VertexAttribState *state = getState(GLClientState::VERTEX_LOCATION);
276            *ptr = state->type;
277            isClientStateParam = true;
278            break;
279            }
280        case GL_VERTEX_ARRAY_STRIDE: {
281            const GLClientState::VertexAttribState *state = getState(GLClientState::VERTEX_LOCATION);
282            *ptr = state->stride;
283            isClientStateParam = true;
284            break;
285            }
286        case GL_COLOR_ARRAY_SIZE: {
287            const GLClientState::VertexAttribState *state = getState(GLClientState::COLOR_LOCATION);
288            *ptr = state->size;
289            isClientStateParam = true;
290            break;
291            }
292        case GL_COLOR_ARRAY_TYPE: {
293            const GLClientState::VertexAttribState *state = getState(GLClientState::COLOR_LOCATION);
294            *ptr = state->type;
295            isClientStateParam = true;
296            break;
297            }
298        case GL_COLOR_ARRAY_STRIDE: {
299            const GLClientState::VertexAttribState *state = getState(GLClientState::COLOR_LOCATION);
300            *ptr = state->stride;
301            isClientStateParam = true;
302            break;
303            }
304        case GL_NORMAL_ARRAY_TYPE: {
305            const GLClientState::VertexAttribState *state = getState(GLClientState::NORMAL_LOCATION);
306            *ptr = state->type;
307            isClientStateParam = true;
308            break;
309            }
310        case GL_NORMAL_ARRAY_STRIDE: {
311            const GLClientState::VertexAttribState *state = getState(GLClientState::NORMAL_LOCATION);
312            *ptr = state->stride;
313            isClientStateParam = true;
314            break;
315            }
316        case GL_TEXTURE_COORD_ARRAY_SIZE: {
317            const GLClientState::VertexAttribState *state = getState(getActiveTexture() + GLClientState::TEXCOORD0_LOCATION);
318            *ptr = state->size;
319            isClientStateParam = true;
320            break;
321            }
322        case GL_TEXTURE_COORD_ARRAY_TYPE: {
323            const GLClientState::VertexAttribState *state = getState(getActiveTexture() + GLClientState::TEXCOORD0_LOCATION);
324            *ptr = state->type;
325            isClientStateParam = true;
326            break;
327            }
328        case GL_TEXTURE_COORD_ARRAY_STRIDE: {
329            const GLClientState::VertexAttribState *state = getState(getActiveTexture() + GLClientState::TEXCOORD0_LOCATION);
330            *ptr = state->stride;
331            isClientStateParam = true;
332            break;
333            }
334        case GL_POINT_SIZE_ARRAY_TYPE_OES: {
335            const GLClientState::VertexAttribState *state = getState(GLClientState::POINTSIZE_LOCATION);
336            *ptr = state->type;
337            isClientStateParam = true;
338            break;
339            }
340        case GL_POINT_SIZE_ARRAY_STRIDE_OES: {
341            const GLClientState::VertexAttribState *state = getState(GLClientState::POINTSIZE_LOCATION);
342            *ptr = state->stride;
343            isClientStateParam = true;
344            break;
345            }
346        case GL_MATRIX_INDEX_ARRAY_SIZE_OES: {
347            const GLClientState::VertexAttribState *state = getState(GLClientState::MATRIXINDEX_LOCATION);
348            *ptr = state->size;
349            isClientStateParam = true;
350            break;
351            }
352        case GL_MATRIX_INDEX_ARRAY_TYPE_OES: {
353            const GLClientState::VertexAttribState *state = getState(GLClientState::MATRIXINDEX_LOCATION);
354            *ptr = state->type;
355            isClientStateParam = true;
356            break;
357            }
358        case GL_MATRIX_INDEX_ARRAY_STRIDE_OES: {
359            const GLClientState::VertexAttribState *state = getState(GLClientState::MATRIXINDEX_LOCATION);
360            *ptr = state->stride;
361            isClientStateParam = true;
362            break;
363            }
364        case GL_WEIGHT_ARRAY_SIZE_OES: {
365            const GLClientState::VertexAttribState *state = getState(GLClientState::WEIGHT_LOCATION);
366            *ptr = state->size;
367            isClientStateParam = true;
368            break;
369            }
370        case GL_WEIGHT_ARRAY_TYPE_OES: {
371            const GLClientState::VertexAttribState *state = getState(GLClientState::WEIGHT_LOCATION);
372            *ptr = state->type;
373            isClientStateParam = true;
374            break;
375            }
376        case GL_WEIGHT_ARRAY_STRIDE_OES: {
377            const GLClientState::VertexAttribState *state = getState(GLClientState::WEIGHT_LOCATION);
378            *ptr = state->stride;
379            isClientStateParam = true;
380            break;
381            }
382        case GL_VERTEX_ARRAY_BUFFER_BINDING: {
383            const GLClientState::VertexAttribState *state = getState(GLClientState::VERTEX_LOCATION);
384            *ptr = state->bufferObject;
385            isClientStateParam = true;
386            break;
387            }
388        case GL_NORMAL_ARRAY_BUFFER_BINDING: {
389            const GLClientState::VertexAttribState *state = getState(GLClientState::NORMAL_LOCATION);
390            *ptr = state->bufferObject;
391            isClientStateParam = true;
392            break;
393            }
394        case GL_COLOR_ARRAY_BUFFER_BINDING: {
395            const GLClientState::VertexAttribState *state = getState(GLClientState::COLOR_LOCATION);
396            *ptr = state->bufferObject;
397            isClientStateParam = true;
398            break;
399            }
400        case GL_TEXTURE_COORD_ARRAY_BUFFER_BINDING: {
401            const GLClientState::VertexAttribState *state = getState(getActiveTexture()+GLClientState::TEXCOORD0_LOCATION);
402            *ptr = state->bufferObject;
403            isClientStateParam = true;
404            break;
405            }
406        case GL_POINT_SIZE_ARRAY_BUFFER_BINDING_OES: {
407            const GLClientState::VertexAttribState *state = getState(GLClientState::POINTSIZE_LOCATION);
408            *ptr = state->bufferObject;
409            isClientStateParam = true;
410            break;
411            }
412        case GL_MATRIX_INDEX_ARRAY_BUFFER_BINDING_OES: {
413            const GLClientState::VertexAttribState *state = getState(GLClientState::MATRIXINDEX_LOCATION);
414            *ptr = state->bufferObject;
415            isClientStateParam = true;
416            break;
417            }
418        case GL_WEIGHT_ARRAY_BUFFER_BINDING_OES: {
419            const GLClientState::VertexAttribState *state = getState(GLClientState::WEIGHT_LOCATION);
420            *ptr = state->bufferObject;
421            isClientStateParam = true;
422            break;
423            }
424        case GL_ARRAY_BUFFER_BINDING: {
425            int buffer = getBuffer(GL_ARRAY_BUFFER);
426            *ptr = buffer;
427            isClientStateParam = true;
428            break;
429            }
430        case GL_ELEMENT_ARRAY_BUFFER_BINDING: {
431            int buffer = getBuffer(GL_ELEMENT_ARRAY_BUFFER);
432            *ptr = buffer;
433            isClientStateParam = true;
434            break;
435            }
436        }
437        return isClientStateParam;
438    }
439
440};
441#endif
442