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#include "GLEncoder.h"
17#include "glUtils.h"
18#include "FixedBuffer.h"
19#include <cutils/log.h>
20#include <assert.h>
21
22#ifndef MIN
23#define MIN(a, b) ((a) < (b) ? (a) : (b))
24#endif
25
26static GLubyte *gVendorString= (GLubyte *) "Android";
27static GLubyte *gRendererString= (GLubyte *) "Android HW-GLES 1.0";
28static GLubyte *gVersionString= (GLubyte *) "OpenGL ES-CM 1.0";
29static GLubyte *gExtensionsString= (GLubyte *) ""; // no extensions at this point;
30
31#define SET_ERROR_IF(condition,err) if((condition)) {                            \
32        ALOGE("%s:%s:%d GL error 0x%x\n", __FILE__, __FUNCTION__, __LINE__, err); \
33        ctx->setError(err);                                    \
34        return;                                                  \
35    }
36
37
38#define RET_AND_SET_ERROR_IF(condition,err,ret) if((condition)) {                \
39        ALOGE("%s:%s:%d GL error 0x%x\n", __FILE__, __FUNCTION__, __LINE__, err); \
40        ctx->setError(err);                                    \
41        return ret;                                              \
42    }
43
44GLenum GLEncoder::s_glGetError(void * self)
45{
46    GLEncoder *ctx = (GLEncoder *)self;
47    GLenum err = ctx->getError();
48    if(err != GL_NO_ERROR) {
49        ctx->setError(GL_NO_ERROR);
50        return err;
51    }
52
53    return ctx->m_glGetError_enc(self);
54
55}
56
57GLint * GLEncoder::getCompressedTextureFormats()
58{
59    if (m_compressedTextureFormats == NULL) {
60        this->glGetIntegerv(this, GL_NUM_COMPRESSED_TEXTURE_FORMATS,
61                            &m_num_compressedTextureFormats);
62        if (m_num_compressedTextureFormats > 0) {
63            // get number of texture formats;
64            m_compressedTextureFormats = new GLint[m_num_compressedTextureFormats];
65            this->glGetCompressedTextureFormats(this, m_num_compressedTextureFormats, m_compressedTextureFormats);
66        }
67    }
68    return m_compressedTextureFormats;
69}
70
71void GLEncoder::s_glGetIntegerv(void *self, GLenum param, GLint *ptr)
72{
73    GLEncoder *ctx = (GLEncoder *)self;
74    assert(ctx->m_state != NULL);
75    GLClientState* state = ctx->m_state;
76
77    switch (param) {
78    case GL_COMPRESSED_TEXTURE_FORMATS: {
79        GLint * compressedTextureFormats = ctx->getCompressedTextureFormats();
80        if (ctx->m_num_compressedTextureFormats > 0 &&
81                compressedTextureFormats != NULL) {
82            memcpy(ptr, compressedTextureFormats,
83                   ctx->m_num_compressedTextureFormats * sizeof(GLint));
84        }
85        break;
86    }
87
88    case GL_MAX_TEXTURE_UNITS:
89        ctx->m_glGetIntegerv_enc(self, param, ptr);
90        *ptr = MIN(*ptr, GLClientState::MAX_TEXTURE_UNITS);
91        break;
92
93    case GL_TEXTURE_BINDING_2D:
94        *ptr = state->getBoundTexture(GL_TEXTURE_2D);
95        break;
96
97    case GL_TEXTURE_BINDING_EXTERNAL_OES:
98        *ptr = state->getBoundTexture(GL_TEXTURE_EXTERNAL_OES);
99        break;
100
101    default:
102        if (!state->getClientStateParameter<GLint>(param,ptr)) {
103            ctx->m_glGetIntegerv_enc(self, param, ptr);
104        }
105        break;
106    }
107}
108
109void GLEncoder::s_glGetFloatv(void *self, GLenum param, GLfloat *ptr)
110{
111    GLEncoder *ctx = (GLEncoder *)self;
112    assert(ctx->m_state != NULL);
113    GLClientState* state = ctx->m_state;
114
115    switch (param) {
116    case GL_COMPRESSED_TEXTURE_FORMATS: {
117        GLint * compressedTextureFormats = ctx->getCompressedTextureFormats();
118        if (ctx->m_num_compressedTextureFormats > 0 &&
119                compressedTextureFormats != NULL) {
120            for (int i = 0; i < ctx->m_num_compressedTextureFormats; i++) {
121                ptr[i] = (GLfloat) compressedTextureFormats[i];
122            }
123        }
124        break;
125    }
126
127    case GL_MAX_TEXTURE_UNITS:
128        ctx->m_glGetFloatv_enc(self, param, ptr);
129        *ptr = MIN(*ptr, (GLfloat)GLClientState::MAX_TEXTURE_UNITS);
130        break;
131
132    case GL_TEXTURE_BINDING_2D:
133        *ptr = (GLfloat)state->getBoundTexture(GL_TEXTURE_2D);
134        break;
135
136    case GL_TEXTURE_BINDING_EXTERNAL_OES:
137        *ptr = (GLfloat)state->getBoundTexture(GL_TEXTURE_EXTERNAL_OES);
138        break;
139
140    default:
141        if (!state->getClientStateParameter<GLfloat>(param,ptr)) {
142            ctx->m_glGetFloatv_enc(self, param, ptr);
143        }
144        break;
145    }
146}
147
148void GLEncoder::s_glGetFixedv(void *self, GLenum param, GLfixed *ptr)
149{
150    GLEncoder *ctx = (GLEncoder *)self;
151    assert(ctx->m_state != NULL);
152    GLClientState* state = ctx->m_state;
153
154    switch (param) {
155    case GL_COMPRESSED_TEXTURE_FORMATS: {
156        GLint * compressedTextureFormats = ctx->getCompressedTextureFormats();
157        if (ctx->m_num_compressedTextureFormats > 0 &&
158                compressedTextureFormats != NULL) {
159            for (int i = 0; i < ctx->m_num_compressedTextureFormats; i++) {
160                ptr[i] =  compressedTextureFormats[i] << 16;
161            }
162        }
163        break;
164    }
165
166    case GL_MAX_TEXTURE_UNITS:
167        ctx->m_glGetFixedv_enc(self, param, ptr);
168        *ptr = MIN(*ptr, GLClientState::MAX_TEXTURE_UNITS << 16);
169        break;
170
171    case GL_TEXTURE_BINDING_2D:
172        *ptr = state->getBoundTexture(GL_TEXTURE_2D) << 16;
173        break;
174
175    case GL_TEXTURE_BINDING_EXTERNAL_OES:
176        *ptr = state->getBoundTexture(GL_TEXTURE_EXTERNAL_OES) << 16;
177        break;
178
179    default:
180        if (!state->getClientStateParameter<GLfixed>(param,ptr)) {
181            ctx->m_glGetFixedv_enc(self, param, ptr);
182        }
183        break;
184    }
185}
186
187void GLEncoder::s_glGetBooleanv(void *self, GLenum param, GLboolean *ptr)
188{
189    GLEncoder *ctx = (GLEncoder *)self;
190    assert(ctx->m_state != NULL);
191    GLClientState* state = ctx->m_state;
192
193    switch (param) {
194    case GL_COMPRESSED_TEXTURE_FORMATS: {
195        GLint* compressedTextureFormats = ctx->getCompressedTextureFormats();
196        if (ctx->m_num_compressedTextureFormats > 0 &&
197                compressedTextureFormats != NULL) {
198            for (int i = 0; i < ctx->m_num_compressedTextureFormats; i++) {
199                ptr[i] = compressedTextureFormats[i] != 0 ? GL_TRUE : GL_FALSE;
200            }
201        }
202        break;
203    }
204
205    case GL_TEXTURE_BINDING_2D:
206        *ptr = state->getBoundTexture(GL_TEXTURE_2D) != 0 ? GL_TRUE : GL_FALSE;
207        break;
208
209    case GL_TEXTURE_BINDING_EXTERNAL_OES:
210        *ptr = state->getBoundTexture(GL_TEXTURE_EXTERNAL_OES) != 0
211                ? GL_TRUE : GL_FALSE;
212        break;
213
214    default:
215        if (!state->getClientStateParameter<GLboolean>(param,ptr)) {
216            ctx->m_glGetBooleanv_enc(self, param, ptr);
217        }
218        break;
219    }
220}
221
222void GLEncoder::s_glGetPointerv(void * self, GLenum param, GLvoid **params)
223{
224    GLEncoder * ctx = (GLEncoder *) self;
225    assert(ctx->m_state != NULL);
226    ctx->m_state->getClientStatePointer(param,params);
227}
228
229void GLEncoder::s_glFlush(void *self)
230{
231    GLEncoder *ctx = (GLEncoder *)self;
232    ctx->m_glFlush_enc(self);
233    ctx->m_stream->flush();
234}
235
236const GLubyte *GLEncoder::s_glGetString(void *self, GLenum name)
237{
238    GLubyte *retval =  (GLubyte *) "";
239    switch(name) {
240    case GL_VENDOR:
241        retval = gVendorString;
242        break;
243    case GL_RENDERER:
244        retval = gRendererString;
245        break;
246    case GL_VERSION:
247        retval = gVersionString;
248        break;
249    case GL_EXTENSIONS:
250        retval = gExtensionsString;
251        break;
252    }
253    return retval;
254}
255
256void GLEncoder::s_glPixelStorei(void *self, GLenum param, GLint value)
257{
258    GLEncoder *ctx = (GLEncoder *)self;
259    ctx->m_glPixelStorei_enc(ctx, param, value);
260    ALOG_ASSERT(ctx->m_state, "GLEncoder::s_glPixelStorei");
261    ctx->m_state->setPixelStore(param, value);
262}
263
264void GLEncoder::s_glVertexPointer(void *self, int size, GLenum type, GLsizei stride, const void *data)
265{
266    GLEncoder *ctx = (GLEncoder *)self;
267    assert(ctx->m_state != NULL);
268    ctx->m_state->setState(GLClientState::VERTEX_LOCATION, size, type, false, stride, data);
269}
270
271void GLEncoder::s_glNormalPointer(void *self, GLenum type, GLsizei stride, const void *data)
272{
273    GLEncoder *ctx = (GLEncoder *)self;
274    assert(ctx->m_state != NULL);
275    ctx->m_state->setState(GLClientState::NORMAL_LOCATION, 3, type, false, stride, data);
276}
277
278void GLEncoder::s_glColorPointer(void *self, int size, GLenum type, GLsizei stride, const void *data)
279{
280    GLEncoder *ctx = (GLEncoder *)self;
281    assert(ctx->m_state != NULL);
282    ctx->m_state->setState(GLClientState::COLOR_LOCATION, size, type, false, stride, data);
283}
284
285void GLEncoder::s_glPointsizePointer(void *self, GLenum type, GLsizei stride, const void *data)
286{
287    GLEncoder *ctx = (GLEncoder *)self;
288    assert(ctx->m_state != NULL);
289    ctx->m_state->setState(GLClientState::POINTSIZE_LOCATION, 1, type, false, stride, data);
290}
291
292void GLEncoder::s_glClientActiveTexture(void *self, GLenum texture)
293{
294    GLEncoder *ctx = (GLEncoder *)self;
295    assert(ctx->m_state != NULL);
296    ctx->m_state->setActiveTexture(texture - GL_TEXTURE0);
297}
298
299void GLEncoder::s_glTexcoordPointer(void *self, int size, GLenum type, GLsizei stride, const void *data)
300{
301    GLEncoder *ctx = (GLEncoder *)self;
302    assert(ctx->m_state != NULL);
303    int loc = ctx->m_state->getLocation(GL_TEXTURE_COORD_ARRAY);
304    ctx->m_state->setState(loc, size, type, false, stride, data);
305}
306
307void GLEncoder::s_glMatrixIndexPointerOES(void *self, int size, GLenum type, GLsizei stride, const void * data)
308{
309    GLEncoder *ctx = (GLEncoder *)self;
310    assert(ctx->m_state != NULL);
311    int loc = ctx->m_state->getLocation(GL_MATRIX_INDEX_ARRAY_OES);
312    ctx->m_state->setState(loc, size, type, false, stride, data);
313}
314
315void GLEncoder::s_glWeightPointerOES(void * self, int size, GLenum type, GLsizei stride, const void * data)
316{
317    GLEncoder *ctx = (GLEncoder *)self;
318    assert(ctx->m_state != NULL);
319    int loc = ctx->m_state->getLocation(GL_WEIGHT_ARRAY_OES);
320    ctx->m_state->setState(loc, size, type, false, stride, data);
321}
322
323void GLEncoder::s_glEnableClientState(void *self, GLenum state)
324{
325    GLEncoder *ctx = (GLEncoder *) self;
326    assert(ctx->m_state != NULL);
327    int loc = ctx->m_state->getLocation(state);
328    ctx->m_state->enable(loc, 1);
329}
330
331void GLEncoder::s_glDisableClientState(void *self, GLenum state)
332{
333    GLEncoder *ctx = (GLEncoder *) self;
334    assert(ctx->m_state != NULL);
335    int loc = ctx->m_state->getLocation(state);
336    ctx->m_state->enable(loc, 0);
337}
338
339GLboolean GLEncoder::s_glIsEnabled(void *self, GLenum cap)
340{
341    GLEncoder *ctx = (GLEncoder *) self;
342    assert(ctx->m_state != NULL);
343    int loc = ctx->m_state->getLocation(cap);
344    const GLClientState::VertexAttribState *state = ctx->m_state->getState(loc);
345
346    if (state!=NULL)
347      return state->enabled;
348
349    return ctx->m_glIsEnabled_enc(self,cap);
350}
351
352void GLEncoder::s_glBindBuffer(void *self, GLenum target, GLuint id)
353{
354    GLEncoder *ctx = (GLEncoder *) self;
355    assert(ctx->m_state != NULL);
356    ctx->m_state->bindBuffer(target, id);
357    // TODO set error state if needed;
358    ctx->m_glBindBuffer_enc(self, target, id);
359}
360
361void GLEncoder::s_glBufferData(void * self, GLenum target, GLsizeiptr size, const GLvoid * data, GLenum usage)
362{
363    GLEncoder *ctx = (GLEncoder *) self;
364    GLuint bufferId = ctx->m_state->getBuffer(target);
365    SET_ERROR_IF(bufferId==0, GL_INVALID_OPERATION);
366    SET_ERROR_IF(size<0, GL_INVALID_VALUE);
367
368    ctx->m_shared->updateBufferData(bufferId, size, (void*)data);
369    ctx->m_glBufferData_enc(self, target, size, data, usage);
370}
371
372void GLEncoder::s_glBufferSubData(void * self, GLenum target, GLintptr offset, GLsizeiptr size, const GLvoid * data)
373{
374    GLEncoder *ctx = (GLEncoder *) self;
375    GLuint bufferId = ctx->m_state->getBuffer(target);
376    SET_ERROR_IF(bufferId==0, GL_INVALID_OPERATION);
377
378    GLenum res = ctx->m_shared->subUpdateBufferData(bufferId, offset, size, (void*)data);
379    SET_ERROR_IF(res, res);
380
381    ctx->m_glBufferSubData_enc(self, target, offset, size, data);
382}
383
384void GLEncoder::s_glDeleteBuffers(void * self, GLsizei n, const GLuint * buffers)
385{
386    GLEncoder *ctx = (GLEncoder *) self;
387    SET_ERROR_IF(n<0, GL_INVALID_VALUE);
388    for (int i=0; i<n; i++) {
389        ctx->m_shared->deleteBufferData(buffers[i]);
390        ctx->m_glDeleteBuffers_enc(self,1,&buffers[i]);
391    }
392}
393
394void GLEncoder::sendVertexData(unsigned int first, unsigned int count)
395{
396    assert(m_state != NULL);
397    for (int i = 0; i < GLClientState::LAST_LOCATION; i++) {
398        bool enableDirty;
399        const GLClientState::VertexAttribState *state = m_state->getStateAndEnableDirty(i, &enableDirty);
400
401        // do not process if state not valid
402        if (!state) continue;
403
404        // do not send disable state if state was already disabled
405        if (!enableDirty && !state->enabled) continue;
406
407        if ( i >= GLClientState::TEXCOORD0_LOCATION &&
408            i <= GLClientState::TEXCOORD7_LOCATION ) {
409            m_glClientActiveTexture_enc(this, GL_TEXTURE0 + i - GLClientState::TEXCOORD0_LOCATION);
410        }
411
412        if (state->enabled) {
413
414            if (enableDirty)
415                m_glEnableClientState_enc(this, state->glConst);
416
417            unsigned int datalen = state->elementSize * count;
418            int stride = state->stride;
419            if (stride == 0) stride = state->elementSize;
420            int firstIndex = stride * first;
421
422            if (state->bufferObject == 0) {
423
424                switch(i) {
425                case GLClientState::VERTEX_LOCATION:
426                    this->glVertexPointerData(this, state->size, state->type, state->stride,
427                                              (unsigned char *)state->data + firstIndex, datalen);
428                    break;
429                case GLClientState::NORMAL_LOCATION:
430                    this->glNormalPointerData(this, state->type, state->stride,
431                                              (unsigned char *)state->data + firstIndex, datalen);
432                    break;
433                case GLClientState::COLOR_LOCATION:
434                    this->glColorPointerData(this, state->size, state->type, state->stride,
435                                             (unsigned char *)state->data + firstIndex, datalen);
436                    break;
437                case GLClientState::TEXCOORD0_LOCATION:
438                case GLClientState::TEXCOORD1_LOCATION:
439                case GLClientState::TEXCOORD2_LOCATION:
440                case GLClientState::TEXCOORD3_LOCATION:
441                case GLClientState::TEXCOORD4_LOCATION:
442                case GLClientState::TEXCOORD5_LOCATION:
443                case GLClientState::TEXCOORD6_LOCATION:
444                case GLClientState::TEXCOORD7_LOCATION:
445                    this->glTexCoordPointerData(this, i - GLClientState::TEXCOORD0_LOCATION, state->size, state->type, state->stride,
446                                                (unsigned char *)state->data + firstIndex, datalen);
447                    break;
448                case GLClientState::POINTSIZE_LOCATION:
449                    this->glPointSizePointerData(this, state->type, state->stride,
450                                                 (unsigned char *) state->data + firstIndex, datalen);
451                    break;
452                case GLClientState::WEIGHT_LOCATION:
453                    this->glWeightPointerData(this, state->size, state->type, state->stride,
454                                              (unsigned char * ) state->data + firstIndex, datalen);
455                    break;
456                case GLClientState::MATRIXINDEX_LOCATION:
457                    this->glMatrixIndexPointerData(this, state->size, state->type, state->stride,
458                                                  (unsigned char *)state->data + firstIndex, datalen);
459                    break;
460                }
461            } else {
462                this->m_glBindBuffer_enc(this, GL_ARRAY_BUFFER, state->bufferObject);
463
464                switch(i) {
465                case GLClientState::VERTEX_LOCATION:
466                    this->glVertexPointerOffset(this, state->size, state->type, state->stride,
467                                                (GLuint)state->data + firstIndex);
468                    break;
469                case GLClientState::NORMAL_LOCATION:
470                    this->glNormalPointerOffset(this, state->type, state->stride,
471                                                (GLuint) state->data + firstIndex);
472                    break;
473                case GLClientState::POINTSIZE_LOCATION:
474                    this->glPointSizePointerOffset(this, state->type, state->stride,
475                                                   (GLuint) state->data + firstIndex);
476                    break;
477                case GLClientState::COLOR_LOCATION:
478                    this->glColorPointerOffset(this, state->size, state->type, state->stride,
479                                               (GLuint) state->data + firstIndex);
480                    break;
481                case GLClientState::TEXCOORD0_LOCATION:
482                case GLClientState::TEXCOORD1_LOCATION:
483                case GLClientState::TEXCOORD2_LOCATION:
484                case GLClientState::TEXCOORD3_LOCATION:
485                case GLClientState::TEXCOORD4_LOCATION:
486                case GLClientState::TEXCOORD5_LOCATION:
487                case GLClientState::TEXCOORD6_LOCATION:
488                case GLClientState::TEXCOORD7_LOCATION:
489                    this->glTexCoordPointerOffset(this, state->size, state->type, state->stride,
490                                                  (GLuint) state->data + firstIndex);
491                    break;
492                case GLClientState::WEIGHT_LOCATION:
493                    this->glWeightPointerOffset(this,state->size,state->type,state->stride,
494                                                (GLuint)state->data+firstIndex);
495                    break;
496                case GLClientState::MATRIXINDEX_LOCATION:
497                    this->glMatrixIndexPointerOffset(this,state->size,state->type,state->stride,
498                                              (GLuint)state->data+firstIndex);
499                    break;
500                }
501                this->m_glBindBuffer_enc(this, GL_ARRAY_BUFFER, m_state->currentArrayVbo());
502            }
503        } else {
504            this->m_glDisableClientState_enc(this, state->glConst);
505        }
506    }
507}
508
509void GLEncoder::s_glDrawArrays(void *self, GLenum mode, GLint first, GLsizei count)
510{
511    GLEncoder *ctx = (GLEncoder *)self;
512
513    ctx->sendVertexData(first, count);
514    ctx->m_glDrawArrays_enc(ctx, mode, /*first*/ 0, count);
515}
516
517void GLEncoder::s_glDrawElements(void *self, GLenum mode, GLsizei count, GLenum type, const void *indices)
518{
519
520    GLEncoder *ctx = (GLEncoder *)self;
521    assert(ctx->m_state != NULL);
522    SET_ERROR_IF(count<0, GL_INVALID_VALUE);
523
524    bool has_immediate_arrays = false;
525    bool has_indirect_arrays = false;
526
527    for (int i = 0; i < GLClientState::LAST_LOCATION; i++) {
528        const GLClientState::VertexAttribState *state = ctx->m_state->getState(i);
529        if (state->enabled) {
530            if (state->bufferObject != 0) {
531                has_indirect_arrays = true;
532            } else {
533                has_immediate_arrays = true;
534            }
535        }
536    }
537
538    if (!has_immediate_arrays && !has_indirect_arrays) {
539        ALOGE("glDrawElements: no data bound to the command - ignoring\n");
540        return;
541    }
542
543    bool adjustIndices = true;
544    if (ctx->m_state->currentIndexVbo() != 0) {
545        if (!has_immediate_arrays) {
546            ctx->sendVertexData(0, count);
547            ctx->m_glBindBuffer_enc(self, GL_ELEMENT_ARRAY_BUFFER, ctx->m_state->currentIndexVbo());
548            ctx->glDrawElementsOffset(ctx, mode, count, type, (GLuint)indices);
549            adjustIndices = false;
550        } else {
551            BufferData * buf = ctx->m_shared->getBufferData(ctx->m_state->currentIndexVbo());
552            ctx->m_glBindBuffer_enc(self, GL_ELEMENT_ARRAY_BUFFER, 0);
553            indices = (void*)((GLintptr)buf->m_fixedBuffer.ptr() + (GLintptr)indices);
554        }
555    }
556    if (adjustIndices) {
557        void *adjustedIndices = (void*)indices;
558        int minIndex = 0, maxIndex = 0;
559
560        switch(type) {
561        case GL_BYTE:
562        case GL_UNSIGNED_BYTE:
563            GLUtils::minmax<unsigned char>((unsigned char *)indices, count, &minIndex, &maxIndex);
564            if (minIndex != 0) {
565                adjustedIndices =  ctx->m_fixedBuffer.alloc(glSizeof(type) * count);
566                GLUtils::shiftIndices<unsigned char>((unsigned char *)indices,
567                                                 (unsigned char *)adjustedIndices,
568                                                 count, -minIndex);
569            }
570            break;
571        case GL_SHORT:
572        case GL_UNSIGNED_SHORT:
573            GLUtils::minmax<unsigned short>((unsigned short *)indices, count, &minIndex, &maxIndex);
574            if (minIndex != 0) {
575                adjustedIndices = ctx->m_fixedBuffer.alloc(glSizeof(type) * count);
576                GLUtils::shiftIndices<unsigned short>((unsigned short *)indices,
577                                                 (unsigned short *)adjustedIndices,
578                                                 count, -minIndex);
579            }
580            break;
581        default:
582            ALOGE("unsupported index buffer type %d\n", type);
583        }
584        if (has_indirect_arrays || 1) {
585            ctx->sendVertexData(minIndex, maxIndex - minIndex + 1);
586            ctx->glDrawElementsData(ctx, mode, count, type, adjustedIndices,
587                                      count * glSizeof(type));
588            // XXX - OPTIMIZATION (see the other else branch) should be implemented
589            if(!has_indirect_arrays) {
590                //ALOGD("unoptimized drawelements !!!\n");
591            }
592        } else {
593            // we are all direct arrays and immidate mode index array -
594            // rebuild the arrays and the index array;
595            ALOGE("glDrawElements: direct index & direct buffer data - will be implemented in later versions;\n");
596        }
597    }
598}
599
600void GLEncoder::s_glActiveTexture(void* self, GLenum texture)
601{
602    GLEncoder* ctx = (GLEncoder*)self;
603    GLClientState* state = ctx->m_state;
604    GLenum err;
605
606    if ((err = state->setActiveTextureUnit(texture)) != GL_NO_ERROR) {
607        ALOGE("%s:%s:%d GL error %#x\n", __FILE__, __FUNCTION__, __LINE__, err);
608        ctx->setError(err);
609        return;
610    }
611
612    ctx->m_glActiveTexture_enc(ctx, texture);
613}
614
615void GLEncoder::s_glBindTexture(void* self, GLenum target, GLuint texture)
616{
617    GLEncoder* ctx = (GLEncoder*)self;
618    GLClientState* state = ctx->m_state;
619    GLenum err;
620
621    GLboolean firstUse;
622    if ((err = state->bindTexture(target, texture, &firstUse)) != GL_NO_ERROR) {
623        ALOGE("%s:%s:%d GL error %#x\n", __FILE__, __FUNCTION__, __LINE__, err);
624        ctx->setError(err);
625        return;
626    }
627
628    if (target != GL_TEXTURE_2D && target != GL_TEXTURE_EXTERNAL_OES) {
629        ctx->m_glBindTexture_enc(ctx, target, texture);
630        return;
631    }
632
633    GLenum priorityTarget = state->getPriorityEnabledTarget(GL_TEXTURE_2D);
634
635    if (target == GL_TEXTURE_EXTERNAL_OES && firstUse) {
636        // set TEXTURE_EXTERNAL_OES default states which differ from TEXTURE_2D
637        ctx->m_glBindTexture_enc(ctx, GL_TEXTURE_2D, texture);
638        ctx->m_glTexParameteri_enc(ctx, GL_TEXTURE_2D,
639                GL_TEXTURE_MIN_FILTER, GL_LINEAR);
640        ctx->m_glTexParameteri_enc(ctx, GL_TEXTURE_2D,
641                GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
642        ctx->m_glTexParameteri_enc(ctx, GL_TEXTURE_2D,
643                GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
644
645        if (target != priorityTarget) {
646            ctx->m_glBindTexture_enc(ctx, GL_TEXTURE_2D,
647                    state->getBoundTexture(GL_TEXTURE_2D));
648        }
649    }
650
651    if (target == priorityTarget) {
652        ctx->m_glBindTexture_enc(ctx, GL_TEXTURE_2D, texture);
653    }
654}
655
656void GLEncoder::s_glDeleteTextures(void* self, GLsizei n, const GLuint* textures)
657{
658    GLEncoder* ctx = (GLEncoder*)self;
659    GLClientState* state = ctx->m_state;
660
661    state->deleteTextures(n, textures);
662    ctx->m_glDeleteTextures_enc(ctx, n, textures);
663}
664
665void GLEncoder::s_glDisable(void* self, GLenum cap)
666{
667    GLEncoder* ctx = (GLEncoder*)self;
668    GLClientState* state = ctx->m_state;
669
670    if (cap == GL_TEXTURE_2D || cap == GL_TEXTURE_EXTERNAL_OES) {
671        GLenum prevTarget = state->getPriorityEnabledTarget(GL_INVALID_ENUM);
672        state->disableTextureTarget(cap);
673        GLenum currTarget = state->getPriorityEnabledTarget(GL_INVALID_ENUM);
674
675        if (prevTarget != currTarget) {
676            if (currTarget == GL_INVALID_ENUM) {
677                ctx->m_glDisable_enc(ctx, GL_TEXTURE_2D);
678                currTarget = GL_TEXTURE_2D;
679            }
680            // maintain the invariant that when TEXTURE_EXTERNAL_OES is
681            // disabled, the TEXTURE_2D binding is active, even if
682            // TEXTURE_2D is also disabled.
683            ctx->m_glBindTexture_enc(ctx, GL_TEXTURE_2D,
684                    state->getBoundTexture(currTarget));
685        }
686
687    } else {
688        ctx->m_glDisable_enc(ctx, cap);
689    }
690}
691
692void GLEncoder::s_glEnable(void* self, GLenum cap)
693{
694    GLEncoder* ctx = (GLEncoder*)self;
695    GLClientState* state = ctx->m_state;
696
697    if (cap == GL_TEXTURE_2D || cap == GL_TEXTURE_EXTERNAL_OES) {
698        GLenum prevTarget = state->getPriorityEnabledTarget(GL_INVALID_ENUM);
699        state->enableTextureTarget(cap);
700        GLenum currTarget = state->getPriorityEnabledTarget(GL_INVALID_ENUM);
701
702        if (prevTarget != currTarget) {
703            if (prevTarget == GL_INVALID_ENUM) {
704                ctx->m_glEnable_enc(ctx, GL_TEXTURE_2D);
705            }
706            if (currTarget == GL_TEXTURE_EXTERNAL_OES) {
707                ctx->m_glBindTexture_enc(ctx, GL_TEXTURE_2D,
708                        state->getBoundTexture(currTarget));
709            }
710        }
711
712    } else {
713        ctx->m_glEnable_enc(ctx, cap);
714    }
715}
716
717void GLEncoder::s_glGetTexParameterfv(void* self,
718        GLenum target, GLenum pname, GLfloat* params)
719{
720    GLEncoder* ctx = (GLEncoder*)self;
721    const GLClientState* state = ctx->m_state;
722
723    if (target == GL_TEXTURE_2D || target == GL_TEXTURE_EXTERNAL_OES) {
724        ctx->override2DTextureTarget(target);
725        ctx->m_glGetTexParameterfv_enc(ctx, GL_TEXTURE_2D, pname, params);
726        ctx->restore2DTextureTarget();
727    } else {
728        ctx->m_glGetTexParameterfv_enc(ctx, target, pname, params);
729    }
730}
731
732void GLEncoder::s_glGetTexParameteriv(void* self,
733        GLenum target, GLenum pname, GLint* params)
734{
735    GLEncoder* ctx = (GLEncoder*)self;
736    const GLClientState* state = ctx->m_state;
737
738    switch (pname) {
739    case GL_REQUIRED_TEXTURE_IMAGE_UNITS_OES:
740        *params = 1;
741        break;
742
743    default:
744        if (target == GL_TEXTURE_2D || target == GL_TEXTURE_EXTERNAL_OES) {
745            ctx->override2DTextureTarget(target);
746            ctx->m_glGetTexParameteriv_enc(ctx, GL_TEXTURE_2D, pname, params);
747            ctx->restore2DTextureTarget();
748        } else {
749            ctx->m_glGetTexParameteriv_enc(ctx, target, pname, params);
750        }
751        break;
752    }
753}
754
755void GLEncoder::s_glGetTexParameterxv(void* self,
756        GLenum target, GLenum pname, GLfixed* params)
757{
758    GLEncoder* ctx = (GLEncoder*)self;
759    const GLClientState* state = ctx->m_state;
760
761    if (target == GL_TEXTURE_2D || target == GL_TEXTURE_EXTERNAL_OES) {
762        ctx->override2DTextureTarget(target);
763        ctx->m_glGetTexParameterxv_enc(ctx, GL_TEXTURE_2D, pname, params);
764        ctx->restore2DTextureTarget();
765    } else {
766        ctx->m_glGetTexParameterxv_enc(ctx, target, pname, params);
767    }
768}
769
770static bool isValidTextureExternalParam(GLenum pname, GLenum param)
771{
772    switch (pname) {
773    case GL_TEXTURE_MIN_FILTER:
774    case GL_TEXTURE_MAG_FILTER:
775        return param == GL_NEAREST || param == GL_LINEAR;
776
777    case GL_TEXTURE_WRAP_S:
778    case GL_TEXTURE_WRAP_T:
779        return param == GL_CLAMP_TO_EDGE;
780
781    case GL_GENERATE_MIPMAP:
782        return param == GL_FALSE;
783
784    default:
785        return true;
786    }
787}
788
789void GLEncoder::s_glTexParameterf(void* self,
790        GLenum target, GLenum pname, GLfloat param)
791{
792    GLEncoder* ctx = (GLEncoder*)self;
793    const GLClientState* state = ctx->m_state;
794
795    SET_ERROR_IF((target == GL_TEXTURE_EXTERNAL_OES &&
796            !isValidTextureExternalParam(pname, (GLenum)param)),
797            GL_INVALID_ENUM);
798
799    if (target == GL_TEXTURE_2D || target == GL_TEXTURE_EXTERNAL_OES) {
800        ctx->override2DTextureTarget(target);
801        ctx->m_glTexParameterf_enc(ctx, GL_TEXTURE_2D, pname, param);
802        ctx->restore2DTextureTarget();
803    } else {
804        ctx->m_glTexParameterf_enc(ctx, target, pname, param);
805    }
806}
807
808void GLEncoder::s_glTexParameterfv(void* self,
809        GLenum target, GLenum pname, const GLfloat* params)
810{
811    GLEncoder* ctx = (GLEncoder*)self;
812    const GLClientState* state = ctx->m_state;
813
814    SET_ERROR_IF((target == GL_TEXTURE_EXTERNAL_OES &&
815            !isValidTextureExternalParam(pname, (GLenum)params[0])),
816            GL_INVALID_ENUM);
817
818    if (target == GL_TEXTURE_2D || target == GL_TEXTURE_EXTERNAL_OES) {
819        ctx->override2DTextureTarget(target);
820        ctx->m_glTexParameterfv_enc(ctx, GL_TEXTURE_2D, pname, params);
821        ctx->restore2DTextureTarget();
822    } else {
823        ctx->m_glTexParameterfv_enc(ctx, target, pname, params);
824    }
825}
826
827void GLEncoder::s_glTexParameteri(void* self,
828        GLenum target, GLenum pname, GLint param)
829{
830    GLEncoder* ctx = (GLEncoder*)self;
831    const GLClientState* state = ctx->m_state;
832
833    SET_ERROR_IF((target == GL_TEXTURE_EXTERNAL_OES &&
834            !isValidTextureExternalParam(pname, (GLenum)param)),
835            GL_INVALID_ENUM);
836
837    if (target == GL_TEXTURE_2D || target == GL_TEXTURE_EXTERNAL_OES) {
838        ctx->override2DTextureTarget(target);
839        ctx->m_glTexParameteri_enc(ctx, GL_TEXTURE_2D, pname, param);
840        ctx->restore2DTextureTarget();
841    } else {
842        ctx->m_glTexParameteri_enc(ctx, target, pname, param);
843    }
844}
845
846void GLEncoder::s_glTexParameterx(void* self,
847        GLenum target, GLenum pname, GLfixed param)
848{
849    GLEncoder* ctx = (GLEncoder*)self;
850    const GLClientState* state = ctx->m_state;
851
852    SET_ERROR_IF((target == GL_TEXTURE_EXTERNAL_OES &&
853            !isValidTextureExternalParam(pname, (GLenum)param)),
854            GL_INVALID_ENUM);
855
856    if (target == GL_TEXTURE_2D || target == GL_TEXTURE_EXTERNAL_OES) {
857        ctx->override2DTextureTarget(target);
858        ctx->m_glTexParameterx_enc(ctx, GL_TEXTURE_2D, pname, param);
859        ctx->restore2DTextureTarget();
860    } else {
861        ctx->m_glTexParameterx_enc(ctx, target, pname, param);
862    }
863}
864
865void GLEncoder::s_glTexParameteriv(void* self,
866        GLenum target, GLenum pname, const GLint* params)
867{
868    GLEncoder* ctx = (GLEncoder*)self;
869    const GLClientState* state = ctx->m_state;
870
871    SET_ERROR_IF((target == GL_TEXTURE_EXTERNAL_OES &&
872            !isValidTextureExternalParam(pname, (GLenum)params[0])),
873            GL_INVALID_ENUM);
874
875    if (target == GL_TEXTURE_2D || target == GL_TEXTURE_EXTERNAL_OES) {
876        ctx->override2DTextureTarget(target);
877        ctx->m_glTexParameteriv_enc(ctx, GL_TEXTURE_2D, pname, params);
878        ctx->restore2DTextureTarget();
879    } else {
880        ctx->m_glTexParameteriv_enc(ctx, target, pname, params);
881    }
882}
883
884void GLEncoder::s_glTexParameterxv(void* self,
885        GLenum target, GLenum pname, const GLfixed* params)
886{
887    GLEncoder* ctx = (GLEncoder*)self;
888    const GLClientState* state = ctx->m_state;
889
890    SET_ERROR_IF((target == GL_TEXTURE_EXTERNAL_OES &&
891            !isValidTextureExternalParam(pname, (GLenum)params[0])),
892            GL_INVALID_ENUM);
893
894    if (target == GL_TEXTURE_2D || target == GL_TEXTURE_EXTERNAL_OES) {
895        ctx->override2DTextureTarget(target);
896        ctx->m_glTexParameterxv_enc(ctx, GL_TEXTURE_2D, pname, params);
897        ctx->restore2DTextureTarget();
898    } else {
899        ctx->m_glTexParameterxv_enc(ctx, target, pname, params);
900    }
901}
902
903void GLEncoder::override2DTextureTarget(GLenum target)
904{
905    if ((target == GL_TEXTURE_2D || target == GL_TEXTURE_EXTERNAL_OES) &&
906        target != m_state->getPriorityEnabledTarget(GL_TEXTURE_2D)) {
907            m_glBindTexture_enc(this, GL_TEXTURE_2D,
908                    m_state->getBoundTexture(target));
909    }
910}
911
912void GLEncoder::restore2DTextureTarget()
913{
914    GLenum priorityTarget = m_state->getPriorityEnabledTarget(GL_TEXTURE_2D);
915    m_glBindTexture_enc(this, GL_TEXTURE_2D,
916            m_state->getBoundTexture(priorityTarget));
917}
918
919GLEncoder::GLEncoder(IOStream *stream) : gl_encoder_context_t(stream)
920{
921    m_initialized = false;
922    m_state = NULL;
923    m_error = GL_NO_ERROR;
924    m_num_compressedTextureFormats = 0;
925    m_compressedTextureFormats = NULL;
926    // overrides;
927    m_glFlush_enc = set_glFlush(s_glFlush);
928    m_glPixelStorei_enc = set_glPixelStorei(s_glPixelStorei);
929    m_glVertexPointer_enc = set_glVertexPointer(s_glVertexPointer);
930    m_glNormalPointer_enc = set_glNormalPointer(s_glNormalPointer);
931    m_glColorPointer_enc = set_glColorPointer(s_glColorPointer);
932    m_glPointSizePointerOES_enc = set_glPointSizePointerOES(s_glPointsizePointer);
933    m_glClientActiveTexture_enc = set_glClientActiveTexture(s_glClientActiveTexture);
934    m_glTexCoordPointer_enc = set_glTexCoordPointer(s_glTexcoordPointer);
935    m_glMatrixIndexPointerOES_enc = set_glMatrixIndexPointerOES(s_glMatrixIndexPointerOES);
936    m_glWeightPointerOES_enc = set_glWeightPointerOES(s_glWeightPointerOES);
937
938    m_glGetIntegerv_enc = set_glGetIntegerv(s_glGetIntegerv);
939    m_glGetFloatv_enc = set_glGetFloatv(s_glGetFloatv);
940    m_glGetBooleanv_enc = set_glGetBooleanv(s_glGetBooleanv);
941    m_glGetFixedv_enc = set_glGetFixedv(s_glGetFixedv);
942    m_glGetPointerv_enc = set_glGetPointerv(s_glGetPointerv);
943
944    m_glBindBuffer_enc = set_glBindBuffer(s_glBindBuffer);
945    m_glBufferData_enc = set_glBufferData(s_glBufferData);
946    m_glBufferSubData_enc = set_glBufferSubData(s_glBufferSubData);
947    m_glDeleteBuffers_enc = set_glDeleteBuffers(s_glDeleteBuffers);
948
949    m_glEnableClientState_enc = set_glEnableClientState(s_glEnableClientState);
950    m_glDisableClientState_enc = set_glDisableClientState(s_glDisableClientState);
951    m_glIsEnabled_enc = set_glIsEnabled(s_glIsEnabled);
952    m_glDrawArrays_enc = set_glDrawArrays(s_glDrawArrays);
953    m_glDrawElements_enc = set_glDrawElements(s_glDrawElements);
954    set_glGetString(s_glGetString);
955    set_glFinish(s_glFinish);
956    m_glGetError_enc = set_glGetError(s_glGetError);
957
958    m_glActiveTexture_enc = set_glActiveTexture(s_glActiveTexture);
959    m_glBindTexture_enc = set_glBindTexture(s_glBindTexture);
960    m_glDeleteTextures_enc = set_glDeleteTextures(s_glDeleteTextures);
961    m_glDisable_enc = set_glDisable(s_glDisable);
962    m_glEnable_enc = set_glEnable(s_glEnable);
963    m_glGetTexParameterfv_enc = set_glGetTexParameterfv(s_glGetTexParameterfv);
964    m_glGetTexParameteriv_enc = set_glGetTexParameteriv(s_glGetTexParameteriv);
965    m_glGetTexParameterxv_enc = set_glGetTexParameterxv(s_glGetTexParameterxv);
966    m_glTexParameterf_enc = set_glTexParameterf(s_glTexParameterf);
967    m_glTexParameterfv_enc = set_glTexParameterfv(s_glTexParameterfv);
968    m_glTexParameteri_enc = set_glTexParameteri(s_glTexParameteri);
969    m_glTexParameterx_enc = set_glTexParameterx(s_glTexParameterx);
970    m_glTexParameteriv_enc = set_glTexParameteriv(s_glTexParameteriv);
971    m_glTexParameterxv_enc = set_glTexParameterxv(s_glTexParameterxv);
972}
973
974GLEncoder::~GLEncoder()
975{
976    delete [] m_compressedTextureFormats;
977}
978
979size_t GLEncoder::pixelDataSize(GLsizei width, GLsizei height, GLenum format, GLenum type, int pack)
980{
981    assert(m_state != NULL);
982    return m_state->pixelDataSize(width, height, format, type, pack);
983}
984
985void GLEncoder::s_glFinish(void *self)
986{
987    GLEncoder *ctx = (GLEncoder *)self;
988    ctx->glFinishRoundTrip(self);
989}
990