OSDN Git Service

66b72d709dce06308b5315aa256827dbeac636b1
[android-x86/device-generic-goldfish-opengl.git] / system / GLESv1_enc / GLEncoder.cpp
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
26 static GLubyte *gVendorString= (GLubyte *) "Android";
27 static GLubyte *gRendererString= (GLubyte *) "Android HW-GLES 1.0";
28 static GLubyte *gVersionString= (GLubyte *) "OpenGL ES-CM 1.0";
29 static GLubyte *gExtensionsString= (GLubyte *) "GL_OES_EGL_image_external ";
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
44 GLenum 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
57 GLint * 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
71 void 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
109 void 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
148 void 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
187 void 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
222 void 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
229 void GLEncoder::s_glFlush(void *self)
230 {
231     GLEncoder *ctx = (GLEncoder *)self;
232     ctx->m_glFlush_enc(self);
233     ctx->m_stream->flush();
234 }
235
236 const GLubyte *GLEncoder::s_glGetString(void *self, GLenum name)
237 {
238     (void)self;
239
240     GLubyte *retval =  (GLubyte *) "";
241     switch(name) {
242     case GL_VENDOR:
243         retval = gVendorString;
244         break;
245     case GL_RENDERER:
246         retval = gRendererString;
247         break;
248     case GL_VERSION:
249         retval = gVersionString;
250         break;
251     case GL_EXTENSIONS:
252         retval = gExtensionsString;
253         break;
254     }
255     return retval;
256 }
257
258 void GLEncoder::s_glPixelStorei(void *self, GLenum param, GLint value)
259 {
260     GLEncoder *ctx = (GLEncoder *)self;
261     ctx->m_glPixelStorei_enc(ctx, param, value);
262     ALOG_ASSERT(ctx->m_state, "GLEncoder::s_glPixelStorei");
263     ctx->m_state->setPixelStore(param, value);
264 }
265
266 void GLEncoder::s_glVertexPointer(void *self, int size, GLenum type, GLsizei stride, const void *data)
267 {
268     GLEncoder *ctx = (GLEncoder *)self;
269     assert(ctx->m_state != NULL);
270     ctx->m_state->setState(GLClientState::VERTEX_LOCATION, size, type, false, stride, data);
271 }
272
273 void GLEncoder::s_glNormalPointer(void *self, GLenum type, GLsizei stride, const void *data)
274 {
275     GLEncoder *ctx = (GLEncoder *)self;
276     assert(ctx->m_state != NULL);
277     ctx->m_state->setState(GLClientState::NORMAL_LOCATION, 3, type, false, stride, data);
278 }
279
280 void GLEncoder::s_glColorPointer(void *self, int size, GLenum type, GLsizei stride, const void *data)
281 {
282     GLEncoder *ctx = (GLEncoder *)self;
283     assert(ctx->m_state != NULL);
284     ctx->m_state->setState(GLClientState::COLOR_LOCATION, size, type, false, stride, data);
285 }
286
287 void GLEncoder::s_glPointSizePointerOES(void *self, GLenum type, GLsizei stride, const void *data)
288 {
289     GLEncoder *ctx = (GLEncoder *)self;
290     assert(ctx->m_state != NULL);
291     ctx->m_state->setState(GLClientState::POINTSIZE_LOCATION, 1, type, false, stride, data);
292 }
293
294 void GLEncoder::s_glClientActiveTexture(void *self, GLenum texture)
295 {
296     GLEncoder *ctx = (GLEncoder *)self;
297     assert(ctx->m_state != NULL);
298     ctx->m_state->setActiveTexture(texture - GL_TEXTURE0);
299 }
300
301 void GLEncoder::s_glTexCoordPointer(void *self, int size, GLenum type, GLsizei stride, const void *data)
302 {
303     GLEncoder *ctx = (GLEncoder *)self;
304     assert(ctx->m_state != NULL);
305     int loc = ctx->m_state->getLocation(GL_TEXTURE_COORD_ARRAY);
306     ctx->m_state->setState(loc, size, type, false, stride, data);
307 }
308
309 void GLEncoder::s_glMatrixIndexPointerOES(void *self, int size, GLenum type, GLsizei stride, const void * data)
310 {
311     GLEncoder *ctx = (GLEncoder *)self;
312     assert(ctx->m_state != NULL);
313     int loc = ctx->m_state->getLocation(GL_MATRIX_INDEX_ARRAY_OES);
314     ctx->m_state->setState(loc, size, type, false, stride, data);
315 }
316
317 void GLEncoder::s_glWeightPointerOES(void * self, int size, GLenum type, GLsizei stride, const void * data)
318 {
319     GLEncoder *ctx = (GLEncoder *)self;
320     assert(ctx->m_state != NULL);
321     int loc = ctx->m_state->getLocation(GL_WEIGHT_ARRAY_OES);
322     ctx->m_state->setState(loc, size, type, false, stride, data);
323 }
324
325 void GLEncoder::s_glEnableClientState(void *self, GLenum state)
326 {
327     GLEncoder *ctx = (GLEncoder *) self;
328     assert(ctx->m_state != NULL);
329     int loc = ctx->m_state->getLocation(state);
330     ctx->m_state->enable(loc, 1);
331 }
332
333 void GLEncoder::s_glDisableClientState(void *self, GLenum state)
334 {
335     GLEncoder *ctx = (GLEncoder *) self;
336     assert(ctx->m_state != NULL);
337     int loc = ctx->m_state->getLocation(state);
338     ctx->m_state->enable(loc, 0);
339 }
340
341 GLboolean GLEncoder::s_glIsEnabled(void *self, GLenum cap)
342 {
343     GLEncoder *ctx = (GLEncoder *) self;
344     assert(ctx->m_state != NULL);
345     int loc = ctx->m_state->getLocation(cap);
346     const GLClientState::VertexAttribState *state = ctx->m_state->getState(loc);
347
348     if (state!=NULL)
349       return state->enabled;
350
351     return ctx->m_glIsEnabled_enc(self,cap);
352 }
353
354 void GLEncoder::s_glBindBuffer(void *self, GLenum target, GLuint id)
355 {
356     GLEncoder *ctx = (GLEncoder *) self;
357     assert(ctx->m_state != NULL);
358     ctx->m_state->bindBuffer(target, id);
359     // TODO set error state if needed;
360     ctx->m_glBindBuffer_enc(self, target, id);
361 }
362
363 void GLEncoder::s_glBufferData(void * self, GLenum target, GLsizeiptr size, const GLvoid * data, GLenum usage)
364 {
365     GLEncoder *ctx = (GLEncoder *) self;
366     GLuint bufferId = ctx->m_state->getBuffer(target);
367     SET_ERROR_IF(bufferId==0, GL_INVALID_OPERATION);
368     SET_ERROR_IF(size<0, GL_INVALID_VALUE);
369
370     ctx->m_shared->updateBufferData(bufferId, size, (void*)data);
371     ctx->m_glBufferData_enc(self, target, size, data, usage);
372 }
373
374 void GLEncoder::s_glBufferSubData(void * self, GLenum target, GLintptr offset, GLsizeiptr size, const GLvoid * data)
375 {
376     GLEncoder *ctx = (GLEncoder *) self;
377     GLuint bufferId = ctx->m_state->getBuffer(target);
378     SET_ERROR_IF(bufferId==0, GL_INVALID_OPERATION);
379
380     GLenum res = ctx->m_shared->subUpdateBufferData(bufferId, offset, size, (void*)data);
381     SET_ERROR_IF(res, res);
382
383     ctx->m_glBufferSubData_enc(self, target, offset, size, data);
384 }
385
386 void GLEncoder::s_glDeleteBuffers(void * self, GLsizei n, const GLuint * buffers)
387 {
388     GLEncoder *ctx = (GLEncoder *) self;
389     SET_ERROR_IF(n<0, GL_INVALID_VALUE);
390     for (int i=0; i<n; i++) {
391         ctx->m_shared->deleteBufferData(buffers[i]);
392         ctx->m_glDeleteBuffers_enc(self,1,&buffers[i]);
393     }
394 }
395
396 void GLEncoder::sendVertexData(unsigned int first, unsigned int count)
397 {
398     assert(m_state != NULL);
399     GLenum prevActiveTexUnit = m_state->getActiveTextureUnit();
400     for (int i = 0; i < GLClientState::LAST_LOCATION; i++) {
401         bool enableDirty;
402         const GLClientState::VertexAttribState *state = m_state->getStateAndEnableDirty(i, &enableDirty);
403
404         // do not process if state not valid
405         if (!state) continue;
406
407         // do not send disable state if state was already disabled
408         if (!enableDirty && !state->enabled) continue;
409
410         if ( i >= GLClientState::TEXCOORD0_LOCATION &&
411             i <= GLClientState::TEXCOORD7_LOCATION ) {
412             m_glClientActiveTexture_enc(this, GL_TEXTURE0 + i - GLClientState::TEXCOORD0_LOCATION);
413         }
414
415         if (state->enabled) {
416             if (enableDirty)
417                 m_glEnableClientState_enc(this, state->glConst);
418
419             unsigned int datalen = state->elementSize * count;
420             int stride = state->stride;
421             if (stride == 0) stride = state->elementSize;
422             int firstIndex = stride * first;
423
424             this->m_glBindBuffer_enc(this, GL_ARRAY_BUFFER, state->bufferObject);
425             if (state->bufferObject == 0) {
426
427                 switch(i) {
428                 case GLClientState::VERTEX_LOCATION:
429                     this->glVertexPointerData(this, state->size, state->type, state->stride,
430                                               (unsigned char *)state->data + firstIndex, datalen);
431                     break;
432                 case GLClientState::NORMAL_LOCATION:
433                     this->glNormalPointerData(this, state->type, state->stride,
434                                               (unsigned char *)state->data + firstIndex, datalen);
435                     break;
436                 case GLClientState::COLOR_LOCATION:
437                     this->glColorPointerData(this, state->size, state->type, state->stride,
438                                              (unsigned char *)state->data + firstIndex, datalen);
439                     break;
440                 case GLClientState::TEXCOORD0_LOCATION:
441                 case GLClientState::TEXCOORD1_LOCATION:
442                 case GLClientState::TEXCOORD2_LOCATION:
443                 case GLClientState::TEXCOORD3_LOCATION:
444                 case GLClientState::TEXCOORD4_LOCATION:
445                 case GLClientState::TEXCOORD5_LOCATION:
446                 case GLClientState::TEXCOORD6_LOCATION:
447                 case GLClientState::TEXCOORD7_LOCATION:
448                     m_state->setActiveTextureUnit(i - GLClientState::TEXCOORD0_LOCATION + GL_TEXTURE0);
449                     if (m_state->getPriorityEnabledTarget(GL_INVALID_ENUM) != GL_INVALID_ENUM) {
450                         this->glTexCoordPointerData(this, i - GLClientState::TEXCOORD0_LOCATION, state->size, state->type, state->stride,
451                                                 (unsigned char *)state->data + firstIndex, datalen);
452                     }
453                     break;
454                 case GLClientState::POINTSIZE_LOCATION:
455                     this->glPointSizePointerData(this, state->type, state->stride,
456                                                  (unsigned char *) state->data + firstIndex, datalen);
457                     break;
458                 case GLClientState::WEIGHT_LOCATION:
459                     this->glWeightPointerData(this, state->size, state->type, state->stride,
460                                               (unsigned char * ) state->data + firstIndex, datalen);
461                     break;
462                 case GLClientState::MATRIXINDEX_LOCATION:
463                     this->glMatrixIndexPointerData(this, state->size, state->type, state->stride,
464                                                   (unsigned char *)state->data + firstIndex, datalen);
465                     break;
466                 }
467             } else {
468
469                 switch(i) {
470                 case GLClientState::VERTEX_LOCATION:
471                     this->glVertexPointerOffset(this, state->size, state->type, state->stride,
472                                                 (uintptr_t)state->data + firstIndex);
473                     break;
474                 case GLClientState::NORMAL_LOCATION:
475                     this->glNormalPointerOffset(this, state->type, state->stride,
476                                                 (uintptr_t)state->data + firstIndex);
477                     break;
478                 case GLClientState::POINTSIZE_LOCATION:
479                     this->glPointSizePointerOffset(this, state->type, state->stride,
480                                                    (uintptr_t)state->data + firstIndex);
481                     break;
482                 case GLClientState::COLOR_LOCATION:
483                     this->glColorPointerOffset(this, state->size, state->type, state->stride,
484                                                (uintptr_t)state->data + firstIndex);
485                     break;
486                 case GLClientState::TEXCOORD0_LOCATION:
487                 case GLClientState::TEXCOORD1_LOCATION:
488                 case GLClientState::TEXCOORD2_LOCATION:
489                 case GLClientState::TEXCOORD3_LOCATION:
490                 case GLClientState::TEXCOORD4_LOCATION:
491                 case GLClientState::TEXCOORD5_LOCATION:
492                 case GLClientState::TEXCOORD6_LOCATION:
493                 case GLClientState::TEXCOORD7_LOCATION:
494                     this->glTexCoordPointerOffset(this, state->size, state->type, state->stride,
495                                                   (uintptr_t)state->data + firstIndex);
496                     break;
497                 case GLClientState::WEIGHT_LOCATION:
498                     this->glWeightPointerOffset(this,state->size,state->type,state->stride,
499                                                 (uintptr_t)state->data+firstIndex);
500                     break;
501                 case GLClientState::MATRIXINDEX_LOCATION:
502                     this->glMatrixIndexPointerOffset(this,state->size,state->type,state->stride,
503                                               (uintptr_t)state->data+firstIndex);
504                     break;
505                 }
506             }
507             this->m_glBindBuffer_enc(this, GL_ARRAY_BUFFER, m_state->currentArrayVbo());
508         } else {
509             this->m_glDisableClientState_enc(this, state->glConst);
510         }
511     }
512     m_state->setActiveTextureUnit(prevActiveTexUnit);
513 }
514
515 void GLEncoder::s_glDrawArrays(void *self, GLenum mode, GLint first, GLsizei count)
516 {
517     GLEncoder *ctx = (GLEncoder *)self;
518
519     bool has_arrays = false;
520     for (int i = 0; i < GLClientState::LAST_LOCATION; i++) {
521         const GLClientState::VertexAttribState *state = ctx->m_state->getState(i);
522         if (state->enabled) {
523             if (state->bufferObject || state->data) {
524                 has_arrays = true;
525             } else {
526                 ALOGE("glDrawArrays: a vertex attribute array is enabled with no data bound\n");
527                 ctx->setError(GL_INVALID_OPERATION);
528                 return;
529             }
530         }
531     }
532     if (!has_arrays) {
533         ALOGE("glDrawArrays: no data bound to the command - ignoring\n");
534         return;
535     }
536
537     ctx->sendVertexData(first, count);
538     ctx->m_glDrawArrays_enc(ctx, mode, /*first*/ 0, count);
539     ctx->m_stream->flush();
540 }
541
542 void GLEncoder::s_glDrawElements(void *self, GLenum mode, GLsizei count, GLenum type, const void *indices)
543 {
544
545     GLEncoder *ctx = (GLEncoder *)self;
546     assert(ctx->m_state != NULL);
547     SET_ERROR_IF(count<0, GL_INVALID_VALUE);
548
549     bool has_immediate_arrays = false;
550     bool has_indirect_arrays = false;
551
552     for (int i = 0; i < GLClientState::LAST_LOCATION; i++) {
553         const GLClientState::VertexAttribState *state = ctx->m_state->getState(i);
554         if (state->enabled) {
555             if (state->bufferObject != 0) {
556                 has_indirect_arrays = true;
557             } else if (state->data) {
558                 has_immediate_arrays = true;
559             } else {
560                 ALOGE("glDrawElements: a vertex attribute array is enabled with no data bound\n");
561                 ctx->setError(GL_INVALID_OPERATION);
562                 return;
563             }
564         }
565     }
566
567     if (!has_immediate_arrays && !has_indirect_arrays) {
568         ALOGE("glDrawElements: no data bound to the command - ignoring\n");
569         return;
570     }
571
572     bool adjustIndices = true;
573     if (ctx->m_state->currentIndexVbo() != 0) {
574         if (!has_immediate_arrays) {
575             ctx->sendVertexData(0, count);
576             ctx->m_glBindBuffer_enc(self, GL_ELEMENT_ARRAY_BUFFER, ctx->m_state->currentIndexVbo());
577             ctx->glDrawElementsOffset(ctx, mode, count, type, (uintptr_t)indices);
578             ctx->m_stream->flush();
579             adjustIndices = false;
580         } else {
581             BufferData * buf = ctx->m_shared->getBufferData(ctx->m_state->currentIndexVbo());
582             ctx->m_glBindBuffer_enc(self, GL_ELEMENT_ARRAY_BUFFER, 0);
583             indices = (void*)((GLintptr)buf->m_fixedBuffer.ptr() + (GLintptr)indices);
584         }
585     }
586     if (adjustIndices) {
587         void *adjustedIndices = (void*)indices;
588         int minIndex = 0, maxIndex = 0;
589
590         switch(type) {
591         case GL_BYTE:
592         case GL_UNSIGNED_BYTE:
593             GLUtils::minmax<unsigned char>((unsigned char *)indices, count, &minIndex, &maxIndex);
594             if (minIndex != 0) {
595                 adjustedIndices =  ctx->m_fixedBuffer.alloc(glSizeof(type) * count);
596                 GLUtils::shiftIndices<unsigned char>((unsigned char *)indices,
597                                                  (unsigned char *)adjustedIndices,
598                                                  count, -minIndex);
599             }
600             break;
601         case GL_SHORT:
602         case GL_UNSIGNED_SHORT:
603             GLUtils::minmax<unsigned short>((unsigned short *)indices, count, &minIndex, &maxIndex);
604             if (minIndex != 0) {
605                 adjustedIndices = ctx->m_fixedBuffer.alloc(glSizeof(type) * count);
606                 GLUtils::shiftIndices<unsigned short>((unsigned short *)indices,
607                                                  (unsigned short *)adjustedIndices,
608                                                  count, -minIndex);
609             }
610             break;
611         case GL_INT:
612         case GL_UNSIGNED_INT:
613             GLUtils::minmax<unsigned int>((unsigned int *)indices, count, &minIndex, &maxIndex);
614             if (minIndex != 0) {
615                 adjustedIndices = ctx->m_fixedBuffer.alloc(glSizeof(type) * count);
616                 GLUtils::shiftIndices<unsigned int>((unsigned int *)indices,
617                                                  (unsigned int *)adjustedIndices,
618                                                  count, -minIndex);
619             }
620             break;
621         default:
622             ALOGE("unsupported index buffer type %d\n", type);
623         }
624         if (has_indirect_arrays || 1) {
625             ctx->sendVertexData(minIndex, maxIndex - minIndex + 1);
626             ctx->glDrawElementsData(ctx, mode, count, type, adjustedIndices,
627                                       count * glSizeof(type));
628             ctx->m_stream->flush();
629             // XXX - OPTIMIZATION (see the other else branch) should be implemented
630             if(!has_indirect_arrays) {
631                 //ALOGD("unoptimized drawelements !!!\n");
632             }
633         } else {
634             // we are all direct arrays and immidate mode index array -
635             // rebuild the arrays and the index array;
636             ALOGE("glDrawElements: direct index & direct buffer data - will be implemented in later versions;\n");
637         }
638     }
639 }
640
641 void GLEncoder::s_glActiveTexture(void* self, GLenum texture)
642 {
643     GLEncoder* ctx = (GLEncoder*)self;
644     GLClientState* state = ctx->m_state;
645     GLenum err;
646
647     if ((err = state->setActiveTextureUnit(texture)) != GL_NO_ERROR) {
648         ALOGE("%s:%s:%d GL error %#x\n", __FILE__, __FUNCTION__, __LINE__, err);
649         ctx->setError(err);
650         return;
651     }
652
653     ctx->m_glActiveTexture_enc(ctx, texture);
654 }
655
656 void GLEncoder::s_glBindTexture(void* self, GLenum target, GLuint texture)
657 {
658     GLEncoder* ctx = (GLEncoder*)self;
659     GLClientState* state = ctx->m_state;
660     GLenum err;
661
662     GLboolean firstUse;
663     if ((err = state->bindTexture(target, texture, &firstUse)) != GL_NO_ERROR) {
664         ALOGE("%s:%s:%d GL error %#x\n", __FILE__, __FUNCTION__, __LINE__, err);
665         ctx->setError(err);
666         return;
667     }
668
669     if (target != GL_TEXTURE_2D && target != GL_TEXTURE_EXTERNAL_OES) {
670         ctx->m_glBindTexture_enc(ctx, target, texture);
671         return;
672     }
673
674     GLenum priorityTarget = state->getPriorityEnabledTarget(GL_TEXTURE_2D);
675
676     if (target == GL_TEXTURE_EXTERNAL_OES && firstUse) {
677         // set TEXTURE_EXTERNAL_OES default states which differ from TEXTURE_2D
678         ctx->m_glBindTexture_enc(ctx, GL_TEXTURE_2D, texture);
679         ctx->m_glTexParameteri_enc(ctx, GL_TEXTURE_2D,
680                 GL_TEXTURE_MIN_FILTER, GL_LINEAR);
681         ctx->m_glTexParameteri_enc(ctx, GL_TEXTURE_2D,
682                 GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
683         ctx->m_glTexParameteri_enc(ctx, GL_TEXTURE_2D,
684                 GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
685
686         if (target != priorityTarget) {
687             ctx->m_glBindTexture_enc(ctx, GL_TEXTURE_2D,
688                     state->getBoundTexture(GL_TEXTURE_2D));
689         }
690     }
691
692     if (target == priorityTarget) {
693         ctx->m_glBindTexture_enc(ctx, GL_TEXTURE_2D, texture);
694     }
695 }
696
697 void GLEncoder::s_glDeleteTextures(void* self, GLsizei n, const GLuint* textures)
698 {
699     GLEncoder* ctx = (GLEncoder*)self;
700     GLClientState* state = ctx->m_state;
701
702     state->deleteTextures(n, textures);
703     ctx->m_glDeleteTextures_enc(ctx, n, textures);
704 }
705
706 void GLEncoder::s_glDisable(void* self, GLenum cap)
707 {
708     GLEncoder* ctx = (GLEncoder*)self;
709     GLClientState* state = ctx->m_state;
710
711     if (cap == GL_TEXTURE_2D || cap == GL_TEXTURE_EXTERNAL_OES) {
712         GLenum prevTarget = state->getPriorityEnabledTarget(GL_INVALID_ENUM);
713         state->disableTextureTarget(cap);
714         GLenum currTarget = state->getPriorityEnabledTarget(GL_INVALID_ENUM);
715
716         if (prevTarget != currTarget) {
717             if (currTarget == GL_INVALID_ENUM) {
718                 ctx->m_glDisable_enc(ctx, GL_TEXTURE_2D);
719                 currTarget = GL_TEXTURE_2D;
720             }
721             // maintain the invariant that when TEXTURE_EXTERNAL_OES is
722             // disabled, the TEXTURE_2D binding is active, even if
723             // TEXTURE_2D is also disabled.
724             ctx->m_glBindTexture_enc(ctx, GL_TEXTURE_2D,
725                     state->getBoundTexture(currTarget));
726         }
727
728     } else {
729         ctx->m_glDisable_enc(ctx, cap);
730     }
731 }
732
733 void GLEncoder::s_glEnable(void* self, GLenum cap)
734 {
735     GLEncoder* ctx = (GLEncoder*)self;
736     GLClientState* state = ctx->m_state;
737
738     if (cap == GL_TEXTURE_2D || cap == GL_TEXTURE_EXTERNAL_OES) {
739         GLenum prevTarget = state->getPriorityEnabledTarget(GL_INVALID_ENUM);
740         state->enableTextureTarget(cap);
741         GLenum currTarget = state->getPriorityEnabledTarget(GL_INVALID_ENUM);
742
743         if (prevTarget != currTarget) {
744             if (prevTarget == GL_INVALID_ENUM) {
745                 ctx->m_glEnable_enc(ctx, GL_TEXTURE_2D);
746             }
747             if (currTarget == GL_TEXTURE_EXTERNAL_OES) {
748                 ctx->m_glBindTexture_enc(ctx, GL_TEXTURE_2D,
749                         state->getBoundTexture(currTarget));
750             }
751         }
752
753     } else {
754         ctx->m_glEnable_enc(ctx, cap);
755     }
756 }
757
758 void GLEncoder::s_glGetTexParameterfv(void* self,
759         GLenum target, GLenum pname, GLfloat* params)
760 {
761     GLEncoder* ctx = (GLEncoder*)self;
762     const GLClientState* state = ctx->m_state;
763
764     if (target == GL_TEXTURE_2D || target == GL_TEXTURE_EXTERNAL_OES) {
765         ctx->override2DTextureTarget(target);
766         ctx->m_glGetTexParameterfv_enc(ctx, GL_TEXTURE_2D, pname, params);
767         ctx->restore2DTextureTarget();
768     } else {
769         ctx->m_glGetTexParameterfv_enc(ctx, target, pname, params);
770     }
771 }
772
773 void GLEncoder::s_glGetTexParameteriv(void* self,
774         GLenum target, GLenum pname, GLint* params)
775 {
776     GLEncoder* ctx = (GLEncoder*)self;
777     const GLClientState* state = ctx->m_state;
778
779     switch (pname) {
780     case GL_REQUIRED_TEXTURE_IMAGE_UNITS_OES:
781         *params = 1;
782         break;
783
784     default:
785         if (target == GL_TEXTURE_2D || target == GL_TEXTURE_EXTERNAL_OES) {
786             ctx->override2DTextureTarget(target);
787             ctx->m_glGetTexParameteriv_enc(ctx, GL_TEXTURE_2D, pname, params);
788             ctx->restore2DTextureTarget();
789         } else {
790             ctx->m_glGetTexParameteriv_enc(ctx, target, pname, params);
791         }
792         break;
793     }
794 }
795
796 void GLEncoder::s_glGetTexParameterxv(void* self,
797         GLenum target, GLenum pname, GLfixed* params)
798 {
799     GLEncoder* ctx = (GLEncoder*)self;
800     const GLClientState* state = ctx->m_state;
801
802     if (target == GL_TEXTURE_2D || target == GL_TEXTURE_EXTERNAL_OES) {
803         ctx->override2DTextureTarget(target);
804         ctx->m_glGetTexParameterxv_enc(ctx, GL_TEXTURE_2D, pname, params);
805         ctx->restore2DTextureTarget();
806     } else {
807         ctx->m_glGetTexParameterxv_enc(ctx, target, pname, params);
808     }
809 }
810
811 static bool isValidTextureExternalParam(GLenum pname, GLenum param)
812 {
813     switch (pname) {
814     case GL_TEXTURE_MIN_FILTER:
815     case GL_TEXTURE_MAG_FILTER:
816         return param == GL_NEAREST || param == GL_LINEAR;
817
818     case GL_TEXTURE_WRAP_S:
819     case GL_TEXTURE_WRAP_T:
820         return param == GL_CLAMP_TO_EDGE;
821
822     case GL_GENERATE_MIPMAP:
823         return param == GL_FALSE;
824
825     default:
826         return true;
827     }
828 }
829
830 void GLEncoder::s_glTexParameterf(void* self,
831         GLenum target, GLenum pname, GLfloat param)
832 {
833     GLEncoder* ctx = (GLEncoder*)self;
834     const GLClientState* state = ctx->m_state;
835
836     SET_ERROR_IF((target == GL_TEXTURE_EXTERNAL_OES &&
837             !isValidTextureExternalParam(pname, (GLenum)param)),
838             GL_INVALID_ENUM);
839
840     if (target == GL_TEXTURE_2D || target == GL_TEXTURE_EXTERNAL_OES) {
841         ctx->override2DTextureTarget(target);
842         ctx->m_glTexParameterf_enc(ctx, GL_TEXTURE_2D, pname, param);
843         ctx->restore2DTextureTarget();
844     } else {
845         ctx->m_glTexParameterf_enc(ctx, target, pname, param);
846     }
847 }
848
849 void GLEncoder::s_glTexParameterfv(void* self,
850         GLenum target, GLenum pname, const GLfloat* params)
851 {
852     GLEncoder* ctx = (GLEncoder*)self;
853     const GLClientState* state = ctx->m_state;
854
855     SET_ERROR_IF((target == GL_TEXTURE_EXTERNAL_OES &&
856             !isValidTextureExternalParam(pname, (GLenum)params[0])),
857             GL_INVALID_ENUM);
858
859     if (target == GL_TEXTURE_2D || target == GL_TEXTURE_EXTERNAL_OES) {
860         ctx->override2DTextureTarget(target);
861         ctx->m_glTexParameterfv_enc(ctx, GL_TEXTURE_2D, pname, params);
862         ctx->restore2DTextureTarget();
863     } else {
864         ctx->m_glTexParameterfv_enc(ctx, target, pname, params);
865     }
866 }
867
868 void GLEncoder::s_glTexParameteri(void* self,
869         GLenum target, GLenum pname, GLint param)
870 {
871     GLEncoder* ctx = (GLEncoder*)self;
872     const GLClientState* state = ctx->m_state;
873
874     SET_ERROR_IF((target == GL_TEXTURE_EXTERNAL_OES &&
875             !isValidTextureExternalParam(pname, (GLenum)param)),
876             GL_INVALID_ENUM);
877
878     if (target == GL_TEXTURE_2D || target == GL_TEXTURE_EXTERNAL_OES) {
879         ctx->override2DTextureTarget(target);
880         ctx->m_glTexParameteri_enc(ctx, GL_TEXTURE_2D, pname, param);
881         ctx->restore2DTextureTarget();
882     } else {
883         ctx->m_glTexParameteri_enc(ctx, target, pname, param);
884     }
885 }
886
887 void GLEncoder::s_glTexParameterx(void* self,
888         GLenum target, GLenum pname, GLfixed param)
889 {
890     GLEncoder* ctx = (GLEncoder*)self;
891     const GLClientState* state = ctx->m_state;
892
893     SET_ERROR_IF((target == GL_TEXTURE_EXTERNAL_OES &&
894             !isValidTextureExternalParam(pname, (GLenum)param)),
895             GL_INVALID_ENUM);
896
897     if (target == GL_TEXTURE_2D || target == GL_TEXTURE_EXTERNAL_OES) {
898         ctx->override2DTextureTarget(target);
899         ctx->m_glTexParameterx_enc(ctx, GL_TEXTURE_2D, pname, param);
900         ctx->restore2DTextureTarget();
901     } else {
902         ctx->m_glTexParameterx_enc(ctx, target, pname, param);
903     }
904 }
905
906 void GLEncoder::s_glTexParameteriv(void* self,
907         GLenum target, GLenum pname, const GLint* params)
908 {
909     GLEncoder* ctx = (GLEncoder*)self;
910     const GLClientState* state = ctx->m_state;
911
912     SET_ERROR_IF((target == GL_TEXTURE_EXTERNAL_OES &&
913             !isValidTextureExternalParam(pname, (GLenum)params[0])),
914             GL_INVALID_ENUM);
915
916     if (target == GL_TEXTURE_2D || target == GL_TEXTURE_EXTERNAL_OES) {
917         ctx->override2DTextureTarget(target);
918         ctx->m_glTexParameteriv_enc(ctx, GL_TEXTURE_2D, pname, params);
919         ctx->restore2DTextureTarget();
920     } else {
921         ctx->m_glTexParameteriv_enc(ctx, target, pname, params);
922     }
923 }
924
925 void GLEncoder::s_glTexParameterxv(void* self,
926         GLenum target, GLenum pname, const GLfixed* params)
927 {
928     GLEncoder* ctx = (GLEncoder*)self;
929     const GLClientState* state = ctx->m_state;
930
931     SET_ERROR_IF((target == GL_TEXTURE_EXTERNAL_OES &&
932             !isValidTextureExternalParam(pname, (GLenum)params[0])),
933             GL_INVALID_ENUM);
934
935     if (target == GL_TEXTURE_2D || target == GL_TEXTURE_EXTERNAL_OES) {
936         ctx->override2DTextureTarget(target);
937         ctx->m_glTexParameterxv_enc(ctx, GL_TEXTURE_2D, pname, params);
938         ctx->restore2DTextureTarget();
939     } else {
940         ctx->m_glTexParameterxv_enc(ctx, target, pname, params);
941     }
942 }
943
944 void GLEncoder::override2DTextureTarget(GLenum target)
945 {
946     if ((target == GL_TEXTURE_2D || target == GL_TEXTURE_EXTERNAL_OES) &&
947         target != m_state->getPriorityEnabledTarget(GL_TEXTURE_2D)) {
948             m_glBindTexture_enc(this, GL_TEXTURE_2D,
949                     m_state->getBoundTexture(target));
950     }
951 }
952
953 void GLEncoder::restore2DTextureTarget()
954 {
955     GLenum priorityTarget = m_state->getPriorityEnabledTarget(GL_TEXTURE_2D);
956     m_glBindTexture_enc(this, GL_TEXTURE_2D,
957             m_state->getBoundTexture(priorityTarget));
958 }
959
960 void GLEncoder::s_glGenFramebuffersOES(void* self,
961         GLsizei n, GLuint* framebuffers) {
962     GLEncoder* ctx = (GLEncoder*)self;
963     GLClientState* state = ctx->m_state;
964
965     SET_ERROR_IF(n < 0, GL_INVALID_VALUE);
966
967     ctx->m_glGenFramebuffersOES_enc(self, n, framebuffers);
968     state->addFramebuffers(n, framebuffers);
969 }
970
971 void GLEncoder::s_glDeleteFramebuffersOES(void* self,
972         GLsizei n, const GLuint* framebuffers) {
973     GLEncoder* ctx = (GLEncoder*)self;
974     GLClientState* state = ctx->m_state;
975
976     SET_ERROR_IF(n < 0, GL_INVALID_VALUE);
977
978     ctx->m_glDeleteFramebuffersOES_enc(self, n, framebuffers);
979     state->removeFramebuffers(n, framebuffers);
980 }
981
982 void GLEncoder::s_glBindFramebufferOES(void* self,
983         GLenum target, GLuint framebuffer) {
984     GLEncoder* ctx = (GLEncoder*)self;
985     GLClientState* state = ctx->m_state;
986
987     SET_ERROR_IF((target != GL_FRAMEBUFFER),
988                  GL_INVALID_ENUM);
989
990     state->bindFramebuffer(target, framebuffer);
991
992     ctx->m_glBindFramebufferOES_enc(self, target, framebuffer);
993 }
994
995 void GLEncoder::s_glFramebufferTexture2DOES(void*self,
996         GLenum target, GLenum attachment,
997         GLenum textarget, GLuint texture, GLint level) {
998     GLEncoder* ctx = (GLEncoder*)self;
999     GLClientState* state = ctx->m_state;
1000
1001     state->attachTextureObject(attachment, texture);
1002
1003     ctx->m_glFramebufferTexture2DOES_enc(self, target, attachment, textarget, texture, level);
1004 }
1005
1006 void GLEncoder::s_glFramebufferTexture2DMultisampleIMG(void* self,
1007         GLenum target, GLenum attachment,
1008         GLenum textarget, GLuint texture, GLint level, GLsizei samples) {
1009     GLEncoder* ctx = (GLEncoder*)self;
1010     GLClientState* state = ctx->m_state;
1011
1012     state->attachTextureObject(attachment, texture);
1013
1014     ctx->m_glFramebufferTexture2DMultisampleIMG_enc(self, target, attachment, textarget, texture, level, samples);
1015 }
1016
1017 void GLEncoder::s_glGetFramebufferAttachmentParameterivOES(void* self,
1018         GLenum target, GLenum attachment, GLenum pname, GLint* params)
1019 {
1020     GLEncoder* ctx = (GLEncoder*)self;
1021     const GLClientState* state = ctx->m_state;
1022
1023     SET_ERROR_IF(state->boundFramebuffer() == 0,
1024                  GL_INVALID_OPERATION);
1025     SET_ERROR_IF((pname != GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE) &&
1026                  (!state->attachmentHasObject(attachment)),
1027                  GL_INVALID_ENUM);
1028
1029     ctx->m_glGetFramebufferAttachmentParameterivOES_enc(self, target, attachment, pname, params);
1030 }
1031
1032 GLEncoder::GLEncoder(IOStream *stream, ChecksumCalculator *protocol)
1033         : gl_encoder_context_t(stream, protocol)
1034 {
1035     m_initialized = false;
1036     m_state = NULL;
1037     m_error = GL_NO_ERROR;
1038     m_num_compressedTextureFormats = 0;
1039     m_compressedTextureFormats = NULL;
1040
1041     // overrides;
1042 #define OVERRIDE(name)  m_##name##_enc = this-> name ; this-> name = &s_##name
1043
1044     OVERRIDE(glFlush);
1045     OVERRIDE(glPixelStorei);
1046     OVERRIDE(glVertexPointer);
1047     OVERRIDE(glNormalPointer);
1048     OVERRIDE(glColorPointer);
1049     OVERRIDE(glPointSizePointerOES);
1050     OVERRIDE(glClientActiveTexture);
1051     OVERRIDE(glTexCoordPointer);
1052     OVERRIDE(glMatrixIndexPointerOES);
1053     OVERRIDE(glWeightPointerOES);
1054
1055     OVERRIDE(glGetIntegerv);
1056     OVERRIDE(glGetFloatv);
1057     OVERRIDE(glGetBooleanv);
1058     OVERRIDE(glGetFixedv);
1059     OVERRIDE(glGetPointerv);
1060
1061     OVERRIDE(glBindBuffer);
1062     OVERRIDE(glBufferData);
1063     OVERRIDE(glBufferSubData);
1064     OVERRIDE(glDeleteBuffers);
1065
1066     OVERRIDE(glEnableClientState);
1067     OVERRIDE(glDisableClientState);
1068     OVERRIDE(glIsEnabled);
1069     OVERRIDE(glDrawArrays);
1070     OVERRIDE(glDrawElements);
1071
1072     this->glGetString = s_glGetString;
1073     this->glFinish = s_glFinish;
1074
1075     OVERRIDE(glGetError);
1076
1077     OVERRIDE(glActiveTexture);
1078     OVERRIDE(glBindTexture);
1079     OVERRIDE(glDeleteTextures);
1080     OVERRIDE(glDisable);
1081     OVERRIDE(glEnable);
1082     OVERRIDE(glGetTexParameterfv);
1083     OVERRIDE(glGetTexParameteriv);
1084     OVERRIDE(glGetTexParameterxv);
1085     OVERRIDE(glTexParameterf);
1086     OVERRIDE(glTexParameterfv);
1087     OVERRIDE(glTexParameteri);
1088     OVERRIDE(glTexParameterx);
1089     OVERRIDE(glTexParameteriv);
1090     OVERRIDE(glTexParameterxv);
1091
1092     OVERRIDE(glGenFramebuffersOES);
1093     OVERRIDE(glDeleteFramebuffersOES);
1094     OVERRIDE(glBindFramebufferOES);
1095     OVERRIDE(glFramebufferTexture2DOES);
1096     OVERRIDE(glFramebufferTexture2DMultisampleIMG);
1097     OVERRIDE(glGetFramebufferAttachmentParameterivOES);
1098 }
1099
1100 GLEncoder::~GLEncoder()
1101 {
1102     delete [] m_compressedTextureFormats;
1103 }
1104
1105 size_t GLEncoder::pixelDataSize(GLsizei width, GLsizei height, GLenum format, GLenum type, int pack)
1106 {
1107     assert(m_state != NULL);
1108     return m_state->pixelDataSize(width, height, format, type, pack);
1109 }
1110
1111 void GLEncoder::s_glFinish(void *self)
1112 {
1113     GLEncoder *ctx = (GLEncoder *)self;
1114     ctx->glFinishRoundTrip(self);
1115 }