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