GL2Encoder.cpp revision 318ffd3798500fe100e0a16166cc0fa9e3790ca3
1#include "GL2Encoder.h"
2#include <assert.h>
3
4
5static GLubyte *gVendorString= (GLubyte *) "Android";
6static GLubyte *gRendererString= (GLubyte *) "Android HW-GLES 2.0";
7static GLubyte *gVersionString= (GLubyte *) "OpenGL ES 2.0";
8static GLubyte *gExtensionsString= (GLubyte *) ""; // no extensions at this point;
9
10GL2Encoder::GL2Encoder(IOStream *stream) : gl2_encoder_context_t(stream)
11{
12    m_state = NULL;
13    m_glFlush_enc = set_glFlush(s_glFlush);
14    m_glPixelStorei_enc = set_glPixelStorei(s_glPixelStorei);
15    m_glGetString_enc = set_glGetString(s_glGetString);
16    m_glBindBuffer_enc = set_glBindBuffer(s_glBindBuffer);
17    m_glDrawArrays_enc = set_glDrawArrays(s_glDrawArrays);
18    m_glDrawElements_enc = set_glDrawElements(s_glDrawElements);
19    m_glGetIntegerv_enc = set_glGetIntegerv(s_glGetIntegerv);
20    m_glGetFloatv_enc = set_glGetFloatv(s_glGetFloatv);
21    m_glGetBooleanv_enc = set_glGetBooleanv(s_glGetBooleanv);
22    m_glVertexAttribPointer_enc = set_glVertexAttribPointer(s_glVertexAtrribPointer);
23    m_glEnableVertexAttribArray_enc = set_glEnableVertexAttribArray(s_glEnableVertexAttribArray);
24    m_glDisableVertexAttribArray_enc = set_glDisableVertexAttribArray(s_glDisableVertexAttribArray);
25    m_glGetVertexAttribiv_enc = set_glGetVertexAttribiv(s_glGetVertexAttribiv);
26    m_glGetVertexAttribfv_enc = set_glGetVertexAttribfv(s_glGetVertexAttribfv);
27    m_glGetVertexAttribPointerv = set_glGetVertexAttribPointerv(s_glGetVertexAttribPointerv);
28}
29
30GL2Encoder::~GL2Encoder()
31{
32    delete m_compressedTextureFormats;
33}
34
35void GL2Encoder::s_glFlush(void *self)
36{
37    GL2Encoder *ctx = (GL2Encoder *) self;
38    ctx->m_glFlush_enc(self);
39    ctx->m_stream->flush();
40}
41
42GLubyte *GL2Encoder::s_glGetString(void *self, GLenum name)
43{
44    GLubyte *retval =  (GLubyte *) "";
45    switch(name) {
46    case GL_VENDOR:
47        retval = gVendorString;
48        break;
49    case GL_RENDERER:
50        retval = gRendererString;
51        break;
52    case GL_VERSION:
53        retval = gVersionString;
54        break;
55    case GL_EXTENSIONS:
56        retval = gExtensionsString;
57        break;
58    }
59    return retval;
60}
61
62void GL2Encoder::s_glPixelStorei(void *self, GLenum param, GLint value)
63{
64    GL2Encoder *ctx = (GL2Encoder *)self;
65    ctx->m_glPixelStorei_enc(ctx, param, value);
66    assert(ctx->m_state != NULL);
67    ctx->m_state->setPixelStore(param, value);
68}
69
70
71void GL2Encoder::s_glBindBuffer(void *self, GLenum target, GLuint id)
72{
73    GL2Encoder *ctx = (GL2Encoder *) self;
74    assert(ctx->m_state != NULL);
75    ctx->m_state->bindBuffer(target, id);
76    // TODO set error state if needed;
77    ctx->m_glBindBuffer_enc(self, target, id);
78}
79
80void GL2Encoder::s_glVertexAtrribPointer(void *self, GLuint indx, GLint size, GLenum type, GLboolean normalized, GLsizei stride, GLvoid * ptr)
81{
82    GL2Encoder *ctx = (GL2Encoder *)self;
83    assert(ctx->m_state != NULL);
84    ctx->m_state->setState(indx, size, type, normalized, stride, ptr);
85}
86
87void GL2Encoder::s_glGetIntegerv(void *self, GLenum param, GLint *params)
88{
89    GL2Encoder *ctx = (GL2Encoder *) self;
90    assert(ctx->m_state != NULL);
91    if (param == GL_NUM_SHADER_BINARY_FORMATS) {
92        *params = 0;
93    } else if (param == GL_SHADER_BINARY_FORMATS) {
94        // do nothing
95    } else  if (param == GL_COMPRESSED_TEXTURE_FORMATS) {
96        GLint *compressedTextureFormats = ctx->getCompressedTextureFormats();
97        if (ctx->m_num_compressedTextureFormats > 0 && compressedTextureFormats != NULL) {
98            memcpy(params, compressedTextureFormats, ctx->m_num_compressedTextureFormats * sizeof(GLint));
99        }
100    } else if (!ctx->m_state->getClientStateParameter<GLint>(param, params)) {
101        ctx->m_glGetIntegerv_enc(self, param, params);
102    }
103}
104
105
106void GL2Encoder::s_glGetFloatv(void *self, GLenum param, GLfloat *ptr)
107{
108    GL2Encoder *ctx = (GL2Encoder *)self;
109    assert(ctx->m_state != NULL);
110    if (param == GL_NUM_SHADER_BINARY_FORMATS) {
111        *ptr = 0;
112    } else if (param == GL_SHADER_BINARY_FORMATS) {
113        // do nothing;
114    } else  if (param == GL_COMPRESSED_TEXTURE_FORMATS) {
115        GLint * compressedTextureFormats = ctx->getCompressedTextureFormats();
116        if (ctx->m_num_compressedTextureFormats > 0 && compressedTextureFormats != NULL) {
117            for (int i = 0; i < ctx->m_num_compressedTextureFormats; i++) {
118                ptr[i] = (GLfloat) compressedTextureFormats[i];
119            }
120        }
121    }
122    else if (!ctx->m_state->getClientStateParameter<GLfloat>(param,ptr)) {
123        ctx->m_glGetFloatv_enc(self, param, ptr);
124    }
125}
126
127
128void GL2Encoder::s_glGetBooleanv(void *self, GLenum param, GLboolean *ptr)
129{
130    GL2Encoder *ctx = (GL2Encoder *)self;
131    assert(ctx->m_state != NULL);
132    if (param == GL_COMPRESSED_TEXTURE_FORMATS) {
133        // ignore the command, although we should have generated a GLerror;
134    }
135    else if (!ctx->m_state->getClientStateParameter<GLboolean>(param,ptr)) {
136        ctx->m_glGetBooleanv_enc(self, param, ptr);
137    }
138}
139
140
141void GL2Encoder::s_glEnableVertexAttribArray(void *self, GLuint index)
142{
143    GL2Encoder *ctx = (GL2Encoder *)self;
144    assert(ctx->m_state);
145    ctx->m_state->enable(index, 1);
146}
147
148void GL2Encoder::s_glDisableVertexAttribArray(void *self, GLuint index)
149{
150    GL2Encoder *ctx = (GL2Encoder *)self;
151    assert(ctx->m_state);
152    ctx->m_state->enable(index, 0);
153}
154
155
156void GL2Encoder::s_glGetVertexAttribiv(void *self, GLuint index, GLenum pname, GLint *params)
157{
158    GL2Encoder *ctx = (GL2Encoder *)self;
159    assert(ctx->m_state);
160
161    if (!ctx->m_state->getVertexAttribParameter<GLint>(index, pname, params)) {
162        ctx->m_glGetVertexAttribiv_enc(self, index, pname, params);
163    }
164}
165
166void GL2Encoder::s_glGetVertexAttribfv(void *self, GLuint index, GLenum pname, GLfloat *params)
167{
168    GL2Encoder *ctx = (GL2Encoder *)self;
169    assert(ctx->m_state);
170
171    if (!ctx->m_state->getVertexAttribParameter<GLfloat>(index, pname, params)) {
172        ctx->m_glGetVertexAttribfv_enc(self, index, pname, params);
173    }
174}
175
176void GL2Encoder::s_glGetVertexAttribPointerv(void *self, GLuint index, GLenum pname, GLvoid **pointer)
177{
178    GL2Encoder *ctx = (GL2Encoder *)self;
179    if (ctx->m_state == NULL) return;
180
181    const GLClientState::VertexAttribState *va_state = ctx->m_state->getState(index);
182    if (va_state != NULL) {
183        *pointer = va_state->data;
184    }
185}
186
187
188void GL2Encoder::sendVertexAttributes(GLint first, GLsizei count)
189{
190    assert(m_state);
191
192    for (int i = 0; i < m_state->nLocations(); i++) {
193        bool enableDirty;
194        const GLClientState::VertexAttribState *state = m_state->getStateAndEnableDirty(i, &enableDirty);
195
196        if (!state) {
197            continue;
198        }
199
200        if (!enableDirty && !state->enabled) {
201            continue;
202        }
203
204
205        if (state->enabled) {
206            m_glEnableVertexAttribArray_enc(this, i);
207
208            unsigned int datalen = state->elementSize * count;
209            int stride = state->stride == 0 ? state->elementSize : state->stride;
210            int firstIndex = stride * first;
211
212            if (state->bufferObject == 0) {
213                this->glVertexAttribPointerData(this, i, state->size, state->type, state->normalized, state->stride,
214                                                (unsigned char *)state->data + firstIndex, datalen);
215            } else {
216                this->glBindBuffer(this, GL_ARRAY_BUFFER, state->bufferObject);
217                this->glVertexAttribPointerOffset(this, i, state->size, state->type, state->normalized, state->stride,
218                                                  (GLuint) state->data + firstIndex);
219            }
220        } else {
221            this->m_glDisableVertexAttribArray_enc(this, i);
222        }
223    }
224}
225
226void GL2Encoder::s_glDrawArrays(void *self, GLenum mode, GLint first, GLsizei count)
227{
228    GL2Encoder *ctx = (GL2Encoder *)self;
229    ctx->sendVertexAttributes(first, count);
230    ctx->m_glDrawArrays_enc(ctx, mode, 0, count);
231}
232
233
234void GL2Encoder::s_glDrawElements(void *self, GLenum mode, GLsizei count, GLenum type, void *indices)
235{
236
237    GL2Encoder *ctx = (GL2Encoder *)self;
238    assert(ctx->m_state != NULL);
239
240    bool has_immediate_arrays = false;
241    bool has_indirect_arrays = false;
242    int nLocations = ctx->m_state->nLocations();
243
244    for (int i = 0; i < nLocations; i++) {
245        const GLClientState::VertexAttribState *state = ctx->m_state->getState(i);
246        if (state->enabled) {
247            if (state->bufferObject != 0) {
248                has_indirect_arrays = true;
249            } else {
250                has_immediate_arrays = true;
251            }
252        }
253    }
254
255    if (!has_immediate_arrays && !has_indirect_arrays) {
256        LOGE("glDrawElements: no data bound to the command - ignoring\n");
257        return;
258    }
259
260    if (ctx->m_state->currentIndexVbo() != 0) {
261        if (!has_immediate_arrays) {
262            ctx->sendVertexAttributes(0, count);
263            ctx->glDrawElementsOffset(ctx, mode, count, type, (GLuint)indices);
264        } else {
265            LOGE("glDrawElements: indirect index arrays, with immidate-mode data array is not supported\n");
266        }
267    } else {
268        void *adjustedIndices = indices;
269        int minIndex = 0, maxIndex = 0;
270
271        switch(type) {
272        case GL_BYTE:
273        case GL_UNSIGNED_BYTE:
274            GLUtils::minmax<unsigned char>((unsigned char *)indices, count, &minIndex, &maxIndex);
275            if (minIndex != 0) {
276                adjustedIndices =  ctx->m_fixedBuffer.alloc(glSizeof(type) * count);
277                GLUtils::shiftIndices<unsigned char>((unsigned char *)indices,
278                                                 (unsigned char *)adjustedIndices,
279                                                 count, -minIndex);
280            }
281            break;
282        case GL_SHORT:
283        case GL_UNSIGNED_SHORT:
284            GLUtils::minmax<unsigned short>((unsigned short *)indices, count, &minIndex, &maxIndex);
285            if (minIndex != 0) {
286                adjustedIndices = ctx->m_fixedBuffer.alloc(glSizeof(type) * count);
287                GLUtils::shiftIndices<unsigned short>((unsigned short *)indices,
288                                                  (unsigned short *)adjustedIndices,
289                                                  count, -minIndex);
290            }
291            break;
292        default:
293            LOGE("unsupported index buffer type %d\n", type);
294        }
295        if (has_indirect_arrays || 1) {
296            ctx->sendVertexAttributes(minIndex, maxIndex - minIndex + 1);
297            ctx->glDrawElementsData(ctx, mode, count, type, adjustedIndices,
298                                    count * glSizeof(type));
299            // XXX - OPTIMIZATION (see the other else branch) should be implemented
300            if(!has_indirect_arrays) {
301                LOGD("unoptimized drawelements !!!\n");
302            }
303        } else {
304            // we are all direct arrays and immidate mode index array -
305            // rebuild the arrays and the index array;
306            LOGE("glDrawElements: direct index & direct buffer data - will be implemented in later versions;\n");
307        }
308    }
309}
310
311
312GLint * GL2Encoder::getCompressedTextureFormats()
313{
314    if (m_compressedTextureFormats == NULL) {
315        this->glGetIntegerv(this, GL_NUM_COMPRESSED_TEXTURE_FORMATS,
316                            &m_num_compressedTextureFormats);
317        if (m_num_compressedTextureFormats > 0) {
318            // get number of texture formats;
319            m_compressedTextureFormats = new GLint[m_num_compressedTextureFormats];
320            this->glGetCompressedTextureFormats(this, m_num_compressedTextureFormats, m_compressedTextureFormats);
321        }
322    }
323    return m_compressedTextureFormats;
324}
325