GLClientState.h revision 57cb41b7ed8c951b1d28fe591c2d2fad97823060
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#include <vector>
36
37// Tracking framebuffer objects:
38// which framebuffer is bound,
39// and which texture names
40// are currently bound to which attachment points.
41struct FboProps {
42    GLenum target;
43    GLuint name;
44    bool previouslyBound;
45    GLuint colorAttachment0_texture;
46    GLuint depthAttachment_texture;
47    GLuint stencilAttachment_texture;
48
49    bool colorAttachment0_hasTexObj;
50    bool depthAttachment_hasTexObj;
51    bool stencilAttachment_hasTexObj;
52
53    GLuint colorAttachment0_rbo;
54    GLuint depthAttachment_rbo;
55    GLuint stencilAttachment_rbo;
56
57    bool colorAttachment0_hasRbo;
58    bool depthAttachment_hasRbo;
59    bool stencilAttachment_hasRbo;
60};
61
62// Same for Rbo's
63struct RboProps {
64    GLenum target;
65    GLuint name;
66    bool previouslyBound;
67};
68
69class GLClientState {
70public:
71    typedef enum {
72        VERTEX_LOCATION = 0,
73        NORMAL_LOCATION = 1,
74        COLOR_LOCATION = 2,
75        POINTSIZE_LOCATION = 3,
76        TEXCOORD0_LOCATION = 4,
77        TEXCOORD1_LOCATION = 5,
78        TEXCOORD2_LOCATION = 6,
79        TEXCOORD3_LOCATION = 7,
80        TEXCOORD4_LOCATION = 8,
81        TEXCOORD5_LOCATION = 9,
82        TEXCOORD6_LOCATION = 10,
83        TEXCOORD7_LOCATION = 11,
84        MATRIXINDEX_LOCATION = 12,
85        WEIGHT_LOCATION = 13,
86        LAST_LOCATION = 14
87    } StateLocation;
88
89    typedef struct {
90        GLint enabled;
91        GLint size;
92        GLenum type;
93        GLsizei stride;
94        void *data;
95        GLuint bufferObject;
96        GLenum glConst;
97        unsigned int elementSize;
98        bool enableDirty;  // true if any enable state has changed since last draw
99        bool normalized;
100    } VertexAttribState;
101
102    typedef struct {
103        int unpack_alignment;
104        int pack_alignment;
105    } PixelStoreState;
106
107    enum {
108        MAX_TEXTURE_UNITS = 32,
109    };
110
111public:
112    GLClientState(int nLocations = CODEC_MAX_VERTEX_ATTRIBUTES);
113    ~GLClientState();
114    int nLocations() { return m_nLocations; }
115    const PixelStoreState *pixelStoreState() { return &m_pixelStore; }
116    int setPixelStore(GLenum param, GLint value);
117    GLuint currentArrayVbo() { return m_currentArrayVbo; }
118    GLuint currentIndexVbo() { return m_currentIndexVbo; }
119    void enable(int location, int state);
120    void setState(int  location, int size, GLenum type, GLboolean normalized, GLsizei stride, const void *data);
121    void setBufferObject(int location, GLuint id);
122    const VertexAttribState  *getState(int location);
123    const VertexAttribState  *getStateAndEnableDirty(int location, bool *enableChanged);
124    int getLocation(GLenum loc);
125    void setActiveTexture(int texUnit) {m_activeTexture = texUnit; };
126    int getActiveTexture() const { return m_activeTexture; }
127    void setMaxVertexAttribs(int val) {
128        m_maxVertexAttribs = val;
129        m_maxVertexAttribsDirty = false;
130    }
131
132    void unBindBuffer(GLuint id)
133    {
134        if (m_currentArrayVbo == id) m_currentArrayVbo = 0;
135        else if (m_currentIndexVbo == id) m_currentIndexVbo = 0;
136    }
137
138    int bindBuffer(GLenum target, GLuint id)
139    {
140        int err = 0;
141        switch(target) {
142        case GL_ARRAY_BUFFER:
143            m_currentArrayVbo = id;
144            break;
145        case GL_ELEMENT_ARRAY_BUFFER:
146            m_currentIndexVbo = id;
147            break;
148        default:
149            err = -1;
150        }
151        return err;
152    }
153
154    int getBuffer(GLenum target)
155    {
156      int ret=0;
157      switch (target) {
158      case GL_ARRAY_BUFFER:
159          ret = m_currentArrayVbo;
160          break;
161      case GL_ELEMENT_ARRAY_BUFFER:
162          ret = m_currentIndexVbo;
163          break;
164      default:
165          ret = -1;
166      }
167      return ret;
168    }
169    size_t pixelDataSize(GLsizei width, GLsizei height, GLenum format, GLenum type, int pack) const;
170
171    void setCurrentProgram(GLint program) { m_currentProgram = program; }
172    GLint currentProgram() const { return m_currentProgram; }
173
174    /* OES_EGL_image_external
175     *
176     * These functions manipulate GL state which interacts with the
177     * OES_EGL_image_external extension, to support client-side emulation on
178     * top of host implementations that don't have it.
179     *
180     * Most of these calls should only be used with TEXTURE_2D or
181     * TEXTURE_EXTERNAL_OES texture targets; TEXTURE_CUBE_MAP or other extension
182     * targets should bypass this. An exception is bindTexture(), which should
183     * see all glBindTexture() calls for any target.
184     */
185
186    // glActiveTexture(GL_TEXTURE0 + i)
187    // Sets the active texture unit. Up to MAX_TEXTURE_UNITS are supported.
188    GLenum setActiveTextureUnit(GLenum texture);
189    GLenum getActiveTextureUnit() const;
190
191    // glEnable(GL_TEXTURE_(2D|EXTERNAL_OES))
192    void enableTextureTarget(GLenum target);
193
194    // glDisable(GL_TEXTURE_(2D|EXTERNAL_OES))
195    void disableTextureTarget(GLenum target);
196
197    // Implements the target priority logic:
198    // * Return GL_TEXTURE_EXTERNAL_OES if enabled, else
199    // * Return GL_TEXTURE_2D if enabled, else
200    // * Return the allDisabled value.
201    // For some cases passing GL_TEXTURE_2D for allDisabled makes callee code
202    // simpler; for other cases passing a recognizable enum like GL_ZERO or
203    // GL_INVALID_ENUM is appropriate.
204    GLenum getPriorityEnabledTarget(GLenum allDisabled) const;
205
206    // glBindTexture(GL_TEXTURE_*, ...)
207    // Set the target binding of the active texture unit to texture. Returns
208    // GL_NO_ERROR on success or GL_INVALID_OPERATION if the texture has
209    // previously been bound to a different target. If firstUse is not NULL,
210    // it is set to indicate whether this is the first use of the texture.
211    // For accurate error detection, bindTexture should be called for *all*
212    // targets, not just 2D and EXTERNAL_OES.
213    GLenum bindTexture(GLenum target, GLuint texture, GLboolean* firstUse);
214
215    // Return the texture currently bound to GL_TEXTURE_(2D|EXTERNAL_OES).
216    GLuint getBoundTexture(GLenum target) const;
217
218    // glDeleteTextures(...)
219    // Remove references to the to-be-deleted textures.
220    void deleteTextures(GLsizei n, const GLuint* textures);
221
222    // Render buffer objects
223    void addRenderbuffers(GLsizei n, GLuint* renderbuffers);
224    void removeRenderbuffers(GLsizei n, const GLuint* renderbuffers);
225    bool usedRenderbufferName(GLuint name) const;
226    void bindRenderbuffer(GLenum target, GLuint name);
227    GLuint boundRenderbuffer() const;
228
229    // Frame buffer objects
230    void addFramebuffers(GLsizei n, GLuint* framebuffers);
231    void removeFramebuffers(GLsizei n, const GLuint* framebuffers);
232    bool usedFramebufferName(GLuint name) const;
233    void bindFramebuffer(GLenum target, GLuint name);
234    GLuint boundFramebuffer() const;
235
236    // Texture object -> FBO
237    void attachTextureObject(GLenum attachment, GLuint texture);
238    GLuint getFboAttachmentTextureId(GLenum attachment) const;
239
240    // RBO -> FBO
241    void attachRbo(GLenum attachment, GLuint renderbuffer);
242    GLuint getFboAttachmentRboId(GLenum attachment) const;
243
244    // FBO attachments in general
245    bool attachmentHasObject(GLenum attachment) const;
246
247    // set eglsurface property on default framebuffer
248    // if coming from eglMakeCurrent
249    void fromMakeCurrent();
250
251private:
252    PixelStoreState m_pixelStore;
253    VertexAttribState *m_states;
254    int m_maxVertexAttribs;
255    bool m_maxVertexAttribsDirty;
256    int m_nLocations;
257    GLuint m_currentArrayVbo;
258    GLuint m_currentIndexVbo;
259    int m_activeTexture;
260    GLint m_currentProgram;
261
262    bool validLocation(int location) { return (location >= 0 && location < m_nLocations); }
263
264    enum TextureTarget {
265        TEXTURE_2D = 0,
266        TEXTURE_EXTERNAL = 1,
267        TEXTURE_TARGET_COUNT
268    };
269    struct TextureUnit {
270        unsigned int enables;
271        GLuint texture[TEXTURE_TARGET_COUNT];
272    };
273    struct TextureRec {
274        GLuint id;
275        GLenum target;
276    };
277    struct TextureState {
278        TextureUnit unit[MAX_TEXTURE_UNITS];
279        TextureUnit* activeUnit;
280        TextureRec* textures;
281        GLuint numTextures;
282        GLuint allocTextures;
283    };
284    TextureState m_tex;
285
286
287    struct RboState {
288        GLuint boundRenderbuffer;
289        size_t boundRenderbufferIndex;
290        std::vector<RboProps> rboData;
291    };
292    RboState mRboState;
293    void addFreshRenderbuffer(GLuint name);
294    void setBoundRenderbufferIndex();
295    size_t getRboIndex(GLuint name) const;
296    RboProps& boundRboProps();
297    const RboProps& boundRboProps_const() const;
298
299    struct FboState {
300        GLuint boundFramebuffer;
301        size_t boundFramebufferIndex;
302        std::vector<FboProps> fboData;
303    };
304    FboState mFboState;
305    void addFreshFramebuffer(GLuint name);
306    void setBoundFramebufferIndex();
307    size_t getFboIndex(GLuint name) const;
308    FboProps& boundFboProps();
309    const FboProps& boundFboProps_const() const;
310
311    static int compareTexId(const void* pid, const void* prec);
312    TextureRec* addTextureRec(GLuint id, GLenum target);
313
314public:
315    void getClientStatePointer(GLenum pname, GLvoid** params);
316
317    template <class T>
318    int getVertexAttribParameter(GLuint index, GLenum param, T *ptr)
319    {
320        bool handled = true;
321        const VertexAttribState *vertexAttrib = getState(index);
322        if (vertexAttrib == NULL) {
323            ERR("getVeterxAttriParameter for non existant index %d\n", index);
324            // set gl error;
325            return handled;
326        }
327
328        switch(param) {
329        case GL_VERTEX_ATTRIB_ARRAY_BUFFER_BINDING:
330            *ptr = (T)(vertexAttrib->bufferObject);
331            break;
332        case GL_VERTEX_ATTRIB_ARRAY_ENABLED:
333            *ptr = (T)(vertexAttrib->enabled);
334            break;
335        case GL_VERTEX_ATTRIB_ARRAY_SIZE:
336            *ptr = (T)(vertexAttrib->size);
337            break;
338        case GL_VERTEX_ATTRIB_ARRAY_STRIDE:
339            *ptr = (T)(vertexAttrib->stride);
340            break;
341        case GL_VERTEX_ATTRIB_ARRAY_TYPE:
342            *ptr = (T)(vertexAttrib->type);
343            break;
344        case GL_VERTEX_ATTRIB_ARRAY_NORMALIZED:
345            *ptr = (T)(vertexAttrib->normalized);
346            break;
347        case GL_CURRENT_VERTEX_ATTRIB:
348            handled = false;
349            break;
350        default:
351            handled = false;
352            ERR("unknown vertex-attrib parameter param %d\n", param);
353        }
354        return handled;
355    }
356
357    template <class T>
358    bool getClientStateParameter(GLenum param, T* ptr)
359    {
360        bool isClientStateParam = false;
361        switch (param) {
362        case GL_CLIENT_ACTIVE_TEXTURE: {
363            GLint tex = getActiveTexture() + GL_TEXTURE0;
364            *ptr = tex;
365            isClientStateParam = true;
366            break;
367            }
368        case GL_VERTEX_ARRAY_SIZE: {
369            const GLClientState::VertexAttribState *state = getState(GLClientState::VERTEX_LOCATION);
370            *ptr = state->size;
371            isClientStateParam = true;
372            break;
373            }
374        case GL_VERTEX_ARRAY_TYPE: {
375            const GLClientState::VertexAttribState *state = getState(GLClientState::VERTEX_LOCATION);
376            *ptr = state->type;
377            isClientStateParam = true;
378            break;
379            }
380        case GL_VERTEX_ARRAY_STRIDE: {
381            const GLClientState::VertexAttribState *state = getState(GLClientState::VERTEX_LOCATION);
382            *ptr = state->stride;
383            isClientStateParam = true;
384            break;
385            }
386        case GL_COLOR_ARRAY_SIZE: {
387            const GLClientState::VertexAttribState *state = getState(GLClientState::COLOR_LOCATION);
388            *ptr = state->size;
389            isClientStateParam = true;
390            break;
391            }
392        case GL_COLOR_ARRAY_TYPE: {
393            const GLClientState::VertexAttribState *state = getState(GLClientState::COLOR_LOCATION);
394            *ptr = state->type;
395            isClientStateParam = true;
396            break;
397            }
398        case GL_COLOR_ARRAY_STRIDE: {
399            const GLClientState::VertexAttribState *state = getState(GLClientState::COLOR_LOCATION);
400            *ptr = state->stride;
401            isClientStateParam = true;
402            break;
403            }
404        case GL_NORMAL_ARRAY_TYPE: {
405            const GLClientState::VertexAttribState *state = getState(GLClientState::NORMAL_LOCATION);
406            *ptr = state->type;
407            isClientStateParam = true;
408            break;
409            }
410        case GL_NORMAL_ARRAY_STRIDE: {
411            const GLClientState::VertexAttribState *state = getState(GLClientState::NORMAL_LOCATION);
412            *ptr = state->stride;
413            isClientStateParam = true;
414            break;
415            }
416        case GL_TEXTURE_COORD_ARRAY_SIZE: {
417            const GLClientState::VertexAttribState *state = getState(getActiveTexture() + GLClientState::TEXCOORD0_LOCATION);
418            *ptr = state->size;
419            isClientStateParam = true;
420            break;
421            }
422        case GL_TEXTURE_COORD_ARRAY_TYPE: {
423            const GLClientState::VertexAttribState *state = getState(getActiveTexture() + GLClientState::TEXCOORD0_LOCATION);
424            *ptr = state->type;
425            isClientStateParam = true;
426            break;
427            }
428        case GL_TEXTURE_COORD_ARRAY_STRIDE: {
429            const GLClientState::VertexAttribState *state = getState(getActiveTexture() + GLClientState::TEXCOORD0_LOCATION);
430            *ptr = state->stride;
431            isClientStateParam = true;
432            break;
433            }
434        case GL_POINT_SIZE_ARRAY_TYPE_OES: {
435            const GLClientState::VertexAttribState *state = getState(GLClientState::POINTSIZE_LOCATION);
436            *ptr = state->type;
437            isClientStateParam = true;
438            break;
439            }
440        case GL_POINT_SIZE_ARRAY_STRIDE_OES: {
441            const GLClientState::VertexAttribState *state = getState(GLClientState::POINTSIZE_LOCATION);
442            *ptr = state->stride;
443            isClientStateParam = true;
444            break;
445            }
446        case GL_MATRIX_INDEX_ARRAY_SIZE_OES: {
447            const GLClientState::VertexAttribState *state = getState(GLClientState::MATRIXINDEX_LOCATION);
448            *ptr = state->size;
449            isClientStateParam = true;
450            break;
451            }
452        case GL_MATRIX_INDEX_ARRAY_TYPE_OES: {
453            const GLClientState::VertexAttribState *state = getState(GLClientState::MATRIXINDEX_LOCATION);
454            *ptr = state->type;
455            isClientStateParam = true;
456            break;
457            }
458        case GL_MATRIX_INDEX_ARRAY_STRIDE_OES: {
459            const GLClientState::VertexAttribState *state = getState(GLClientState::MATRIXINDEX_LOCATION);
460            *ptr = state->stride;
461            isClientStateParam = true;
462            break;
463            }
464        case GL_WEIGHT_ARRAY_SIZE_OES: {
465            const GLClientState::VertexAttribState *state = getState(GLClientState::WEIGHT_LOCATION);
466            *ptr = state->size;
467            isClientStateParam = true;
468            break;
469            }
470        case GL_WEIGHT_ARRAY_TYPE_OES: {
471            const GLClientState::VertexAttribState *state = getState(GLClientState::WEIGHT_LOCATION);
472            *ptr = state->type;
473            isClientStateParam = true;
474            break;
475            }
476        case GL_WEIGHT_ARRAY_STRIDE_OES: {
477            const GLClientState::VertexAttribState *state = getState(GLClientState::WEIGHT_LOCATION);
478            *ptr = state->stride;
479            isClientStateParam = true;
480            break;
481            }
482        case GL_VERTEX_ARRAY_BUFFER_BINDING: {
483            const GLClientState::VertexAttribState *state = getState(GLClientState::VERTEX_LOCATION);
484            *ptr = state->bufferObject;
485            isClientStateParam = true;
486            break;
487            }
488        case GL_NORMAL_ARRAY_BUFFER_BINDING: {
489            const GLClientState::VertexAttribState *state = getState(GLClientState::NORMAL_LOCATION);
490            *ptr = state->bufferObject;
491            isClientStateParam = true;
492            break;
493            }
494        case GL_COLOR_ARRAY_BUFFER_BINDING: {
495            const GLClientState::VertexAttribState *state = getState(GLClientState::COLOR_LOCATION);
496            *ptr = state->bufferObject;
497            isClientStateParam = true;
498            break;
499            }
500        case GL_TEXTURE_COORD_ARRAY_BUFFER_BINDING: {
501            const GLClientState::VertexAttribState *state = getState(getActiveTexture()+GLClientState::TEXCOORD0_LOCATION);
502            *ptr = state->bufferObject;
503            isClientStateParam = true;
504            break;
505            }
506        case GL_POINT_SIZE_ARRAY_BUFFER_BINDING_OES: {
507            const GLClientState::VertexAttribState *state = getState(GLClientState::POINTSIZE_LOCATION);
508            *ptr = state->bufferObject;
509            isClientStateParam = true;
510            break;
511            }
512        case GL_MATRIX_INDEX_ARRAY_BUFFER_BINDING_OES: {
513            const GLClientState::VertexAttribState *state = getState(GLClientState::MATRIXINDEX_LOCATION);
514            *ptr = state->bufferObject;
515            isClientStateParam = true;
516            break;
517            }
518        case GL_WEIGHT_ARRAY_BUFFER_BINDING_OES: {
519            const GLClientState::VertexAttribState *state = getState(GLClientState::WEIGHT_LOCATION);
520            *ptr = state->bufferObject;
521            isClientStateParam = true;
522            break;
523            }
524        case GL_ARRAY_BUFFER_BINDING: {
525            int buffer = getBuffer(GL_ARRAY_BUFFER);
526            *ptr = buffer;
527            isClientStateParam = true;
528            break;
529            }
530        case GL_ELEMENT_ARRAY_BUFFER_BINDING: {
531            int buffer = getBuffer(GL_ELEMENT_ARRAY_BUFFER);
532            *ptr = buffer;
533            isClientStateParam = true;
534            break;
535            }
536        case GL_MAX_VERTEX_ATTRIBS: {
537            if (m_maxVertexAttribsDirty) {
538                isClientStateParam = false;
539            } else {
540                *ptr = m_maxVertexAttribs;
541                isClientStateParam = true;
542            }
543            break;
544            }
545        }
546        return isClientStateParam;
547    }
548
549};
550#endif
551