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