1/*
2* Copyright 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
17#include <GLcommon/GLEScontext.h>
18#include <GLcommon/GLconversion_macros.h>
19#include <GLcommon/GLESmacros.h>
20#include <GLES/gl.h>
21#include <GLES/glext.h>
22#include <GLcommon/GLESvalidate.h>
23#include <GLcommon/TextureUtils.h>
24#include <GLcommon/FramebufferData.h>
25#include <strings.h>
26#include <string.h>
27
28//decleration
29static void convertFixedDirectLoop(const char* dataIn,unsigned int strideIn,void* dataOut,unsigned int nBytes,unsigned int strideOut,int attribSize);
30static void convertFixedIndirectLoop(const char* dataIn,unsigned int strideIn,void* dataOut,GLsizei count,GLenum indices_type,const GLvoid* indices,unsigned int strideOut,int attribSize);
31static void convertByteDirectLoop(const char* dataIn,unsigned int strideIn,void* dataOut,unsigned int nBytes,unsigned int strideOut,int attribSize);
32static void convertByteIndirectLoop(const char* dataIn,unsigned int strideIn,void* dataOut,GLsizei count,GLenum indices_type,const GLvoid* indices,unsigned int strideOut,int attribSize);
33
34GLESConversionArrays::~GLESConversionArrays() {
35    for(std::map<GLenum,ArrayData>::iterator it = m_arrays.begin(); it != m_arrays.end();it++) {
36        if((*it).second.allocated){
37            if((*it).second.type == GL_FLOAT){
38                GLfloat* p = (GLfloat *)((*it).second.data);
39                if(p) delete[] p;
40            } else if((*it).second.type == GL_SHORT){
41                GLshort* p = (GLshort *)((*it).second.data);
42                if(p) delete[] p;
43            }
44        }
45    }
46}
47
48void GLESConversionArrays::allocArr(unsigned int size,GLenum type){
49    if(type == GL_FIXED){
50        m_arrays[m_current].data = new GLfloat[size];
51        m_arrays[m_current].type = GL_FLOAT;
52    } else if(type == GL_BYTE){
53        m_arrays[m_current].data = new GLshort[size];
54        m_arrays[m_current].type = GL_SHORT;
55    }
56    m_arrays[m_current].stride = 0;
57    m_arrays[m_current].allocated = true;
58}
59
60void GLESConversionArrays::setArr(void* data,unsigned int stride,GLenum type){
61   m_arrays[m_current].type = type;
62   m_arrays[m_current].data = data;
63   m_arrays[m_current].stride = stride;
64   m_arrays[m_current].allocated = false;
65}
66
67void* GLESConversionArrays::getCurrentData(){
68    return m_arrays[m_current].data;
69}
70
71ArrayData& GLESConversionArrays::getCurrentArray(){
72    return m_arrays[m_current];
73}
74
75unsigned int GLESConversionArrays::getCurrentIndex(){
76    return m_current;
77}
78
79ArrayData& GLESConversionArrays::operator[](int i){
80    return m_arrays[i];
81}
82
83void GLESConversionArrays::operator++(){
84    m_current++;
85}
86
87GLDispatch     GLEScontext::s_glDispatch;
88emugl::Mutex   GLEScontext::s_lock;
89std::string*   GLEScontext::s_glExtensions= NULL;
90std::string    GLEScontext::s_glVendor;
91std::string    GLEScontext::s_glRenderer;
92std::string    GLEScontext::s_glVersion;
93GLSupport      GLEScontext::s_glSupport;
94
95Version::Version():m_major(0),
96                   m_minor(0),
97                   m_release(0){};
98
99Version::Version(int major,int minor,int release):m_major(major),
100                                                  m_minor(minor),
101                                                  m_release(release){};
102
103Version::Version(const Version& ver):m_major(ver.m_major),
104                                     m_minor(ver.m_minor),
105                                     m_release(ver.m_release){}
106
107Version::Version(const char* versionString){
108    m_release = 0;
109    if((!versionString) ||
110      ((!(sscanf(versionString,"%d.%d"   ,&m_major,&m_minor) == 2)) &&
111       (!(sscanf(versionString,"%d.%d.%d",&m_major,&m_minor,&m_release) == 3)))){
112        m_major = m_minor = 0; // the version is not in the right format
113    }
114}
115
116Version& Version::operator=(const Version& ver){
117    m_major   = ver.m_major;
118    m_minor   = ver.m_minor;
119    m_release = ver.m_release;
120    return *this;
121}
122
123bool Version::operator<(const Version& ver) const{
124    if(m_major < ver.m_major) return true;
125    if(m_major == ver.m_major){
126        if(m_minor < ver.m_minor) return true;
127        if(m_minor == ver.m_minor){
128           return m_release < ver.m_release;
129        }
130    }
131    return false;
132}
133
134void GLEScontext::init() {
135
136    if (!s_glExtensions) {
137        initCapsLocked(s_glDispatch.glGetString(GL_EXTENSIONS));
138        s_glExtensions = new std::string("");
139    }
140
141    if (!m_initialized) {
142        initExtensionString();
143
144        int maxTexUnits = getMaxTexUnits();
145        m_texState = new textureUnitState[maxTexUnits];
146        for (int i=0;i<maxTexUnits;++i) {
147            for (int j=0;j<NUM_TEXTURE_TARGETS;++j)
148            {
149                m_texState[i][j].texture = 0;
150                m_texState[i][j].enabled = GL_FALSE;
151            }
152        }
153    }
154}
155
156GLEScontext::GLEScontext():
157                           m_initialized(false)    ,
158                           m_activeTexture(0)      ,
159                           m_unpackAlignment(4)    ,
160                           m_glError(GL_NO_ERROR)  ,
161                           m_texState(0)          ,
162                           m_arrayBuffer(0)        ,
163                           m_elementBuffer(0),
164                           m_renderbuffer(0),
165                           m_framebuffer(0)
166{
167};
168
169GLenum GLEScontext::getGLerror() {
170    return m_glError;
171}
172
173void GLEScontext::setGLerror(GLenum err) {
174    m_glError = err;
175}
176
177void GLEScontext::setActiveTexture(GLenum tex) {
178   m_activeTexture = tex - GL_TEXTURE0;
179}
180
181GLEScontext::~GLEScontext() {
182    for(ArraysMap::iterator it = m_map.begin(); it != m_map.end();it++) {
183        GLESpointer* p = (*it).second;
184        if(p) {
185            delete p;
186        }
187    }
188    delete[] m_texState;
189    m_texState = NULL;
190}
191
192const GLvoid* GLEScontext::setPointer(GLenum arrType,GLint size,GLenum type,GLsizei stride,const GLvoid* data,bool normalize) {
193    GLuint bufferName = m_arrayBuffer;
194    if(bufferName) {
195        unsigned int offset = SafeUIntFromPointer(data);
196        GLESbuffer* vbo = static_cast<GLESbuffer*>(m_shareGroup->getObjectData(VERTEXBUFFER,bufferName).Ptr());
197        m_map[arrType]->setBuffer(size,type,stride,vbo,bufferName,offset,normalize);
198        return  static_cast<const unsigned char*>(vbo->getData()) +  offset;
199    }
200    m_map[arrType]->setArray(size,type,stride,data,normalize);
201    return data;
202}
203
204void GLEScontext::enableArr(GLenum arr,bool enable) {
205    m_map[arr]->enable(enable);
206}
207
208bool GLEScontext::isArrEnabled(GLenum arr) {
209    return m_map[arr]->isEnable();
210}
211
212const GLESpointer* GLEScontext::getPointer(GLenum arrType) {
213    if (m_map.find(arrType) != m_map.end()) return m_map[arrType];
214    return NULL;
215}
216
217static void convertFixedDirectLoop(const char* dataIn,unsigned int strideIn,void* dataOut,unsigned int nBytes,unsigned int strideOut,int attribSize) {
218
219    for(unsigned int i = 0; i < nBytes;i+=strideOut) {
220        const GLfixed* fixed_data = (const GLfixed *)dataIn;
221        //filling attrib
222        for(int j=0;j<attribSize;j++) {
223            reinterpret_cast<GLfloat*>(&static_cast<unsigned char*>(dataOut)[i])[j] = X2F(fixed_data[j]);
224        }
225        dataIn += strideIn;
226    }
227}
228
229static void convertFixedIndirectLoop(const char* dataIn,unsigned int strideIn,void* dataOut,GLsizei count,GLenum indices_type,const GLvoid* indices,unsigned int strideOut,int attribSize) {
230    for(int i = 0 ;i < count ;i++) {
231        unsigned short index = indices_type == GL_UNSIGNED_BYTE? ((GLubyte *)indices)[i]:
232                                                             ((GLushort *)indices)[i];
233        const GLfixed* fixed_data = (GLfixed *)(dataIn  + index*strideIn);
234        GLfloat* float_data = reinterpret_cast<GLfloat*>(static_cast<unsigned char*>(dataOut) + index*strideOut);
235
236        for(int j=0;j<attribSize;j++) {
237            float_data[j] = X2F(fixed_data[j]);
238         }
239    }
240}
241
242static void convertByteDirectLoop(const char* dataIn,unsigned int strideIn,void* dataOut,unsigned int nBytes,unsigned int strideOut,int attribSize) {
243
244    for(unsigned int i = 0; i < nBytes;i+=strideOut) {
245        const GLbyte* byte_data = (const GLbyte *)dataIn;
246        //filling attrib
247        for(int j=0;j<attribSize;j++) {
248            reinterpret_cast<GLshort*>(&static_cast<unsigned char*>(dataOut)[i])[j] = B2S(byte_data[j]);
249        }
250        dataIn += strideIn;
251    }
252}
253
254static void convertByteIndirectLoop(const char* dataIn,unsigned int strideIn,void* dataOut,GLsizei count,GLenum indices_type,const GLvoid* indices,unsigned int strideOut,int attribSize) {
255    for(int i = 0 ;i < count ;i++) {
256        unsigned short index = indices_type == GL_UNSIGNED_BYTE? ((GLubyte *)indices)[i]:
257                                                             ((GLushort *)indices)[i];
258        const GLbyte* bytes_data = (GLbyte *)(dataIn  + index*strideIn);
259        GLshort* short_data = reinterpret_cast<GLshort*>(static_cast<unsigned char*>(dataOut) + index*strideOut);
260
261        for(int j=0;j<attribSize;j++) {
262            short_data[j] = B2S(bytes_data[j]);
263         }
264    }
265}
266static void directToBytesRanges(GLint first,GLsizei count,GLESpointer* p,RangeList& list) {
267
268    int attribSize = p->getSize()*4; //4 is the sizeof GLfixed or GLfloat in bytes
269    int stride = p->getStride()?p->getStride():attribSize;
270    int start  = p->getBufferOffset()+first*attribSize;
271    if(!p->getStride()) {
272        list.addRange(Range(start,count*attribSize));
273    } else {
274        for(int i = 0 ;i < count; i++,start+=stride) {
275            list.addRange(Range(start,attribSize));
276        }
277    }
278}
279
280static void indirectToBytesRanges(const GLvoid* indices,GLenum indices_type,GLsizei count,GLESpointer* p,RangeList& list) {
281
282    int attribSize = p->getSize() * 4; //4 is the sizeof GLfixed or GLfloat in bytes
283    int stride = p->getStride()?p->getStride():attribSize;
284    int start  = p->getBufferOffset();
285    for(int i=0 ; i < count; i++) {
286        GLushort index = (indices_type == GL_UNSIGNED_SHORT?
287                         static_cast<const GLushort*>(indices)[i]:
288                         static_cast<const GLubyte*>(indices)[i]);
289        list.addRange(Range(start+index*stride,attribSize));
290
291    }
292}
293
294int bytesRangesToIndices(RangeList& ranges,GLESpointer* p,GLushort* indices) {
295
296    int attribSize = p->getSize() * 4; //4 is the sizeof GLfixed or GLfloat in bytes
297    int stride = p->getStride()?p->getStride():attribSize;
298    int offset = p->getBufferOffset();
299
300    int n = 0;
301    for(int i=0;i<ranges.size();i++) {
302        int startIndex = (ranges[i].getStart() - offset) / stride;
303        int nElements = ranges[i].getSize()/attribSize;
304        for(int j=0;j<nElements;j++) {
305            indices[n++] = startIndex+j;
306        }
307    }
308    return n;
309}
310
311void GLEScontext::convertDirect(GLESConversionArrays& cArrs,GLint first,GLsizei count,GLenum array_id,GLESpointer* p) {
312
313    GLenum type    = p->getType();
314    int attribSize = p->getSize();
315    unsigned int size = attribSize*count + first;
316    unsigned int bytes = type == GL_FIXED ? sizeof(GLfixed):sizeof(GLbyte);
317    cArrs.allocArr(size,type);
318    int stride = p->getStride()?p->getStride():bytes*attribSize;
319    const char* data = (const char*)p->getArrayData() + (first*stride);
320
321    if(type == GL_FIXED) {
322        convertFixedDirectLoop(data,stride,cArrs.getCurrentData(),size*sizeof(GLfloat),attribSize*sizeof(GLfloat),attribSize);
323    } else if(type == GL_BYTE) {
324        convertByteDirectLoop(data,stride,cArrs.getCurrentData(),size*sizeof(GLshort),attribSize*sizeof(GLshort),attribSize);
325    }
326}
327
328void GLEScontext::convertDirectVBO(GLESConversionArrays& cArrs,GLint first,GLsizei count,GLenum array_id,GLESpointer* p) {
329
330    RangeList ranges;
331    RangeList conversions;
332    GLushort* indices = NULL;
333    int attribSize = p->getSize();
334    int stride = p->getStride()?p->getStride():sizeof(GLfixed)*attribSize;
335    char* data = (char*)p->getBufferData() + (first*stride);
336
337    if(p->bufferNeedConversion()) {
338        directToBytesRanges(first,count,p,ranges); //converting indices range to buffer bytes ranges by offset
339        p->getBufferConversions(ranges,conversions); // getting from the buffer the relevant ranges that still needs to be converted
340
341        if(conversions.size()) { // there are some elements to convert
342           indices = new GLushort[count];
343           int nIndices = bytesRangesToIndices(conversions,p,indices); //converting bytes ranges by offset to indices in this array
344           convertFixedIndirectLoop(data,stride,data,nIndices,GL_UNSIGNED_SHORT,indices,stride,attribSize);
345        }
346    }
347    if(indices) delete[] indices;
348    cArrs.setArr(data,p->getStride(),GL_FLOAT);
349}
350
351int GLEScontext::findMaxIndex(GLsizei count,GLenum type,const GLvoid* indices) {
352    //finding max index
353    int max = 0;
354    if(type == GL_UNSIGNED_BYTE) {
355        GLubyte*  b_indices  =(GLubyte *)indices;
356        for(int i=0;i<count;i++) {
357            if(b_indices[i] > max) max = b_indices[i];
358        }
359    } else {
360        GLushort* us_indices =(GLushort *)indices;
361        for(int i=0;i<count;i++) {
362            if(us_indices[i] > max) max = us_indices[i];
363        }
364    }
365    return max;
366}
367
368void GLEScontext::convertIndirect(GLESConversionArrays& cArrs,GLsizei count,GLenum indices_type,const GLvoid* indices,GLenum array_id,GLESpointer* p) {
369    GLenum type    = p->getType();
370    int maxElements = findMaxIndex(count,type,indices) + 1;
371
372    int attribSize = p->getSize();
373    int size = attribSize * maxElements;
374    unsigned int bytes = type == GL_FIXED ? sizeof(GLfixed):sizeof(GLbyte);
375    cArrs.allocArr(size,type);
376    int stride = p->getStride()?p->getStride():bytes*attribSize;
377
378    const char* data = (const char*)p->getArrayData();
379    if(type == GL_FIXED) {
380        convertFixedIndirectLoop(data,stride,cArrs.getCurrentData(),count,indices_type,indices,attribSize*sizeof(GLfloat),attribSize);
381    } else if(type == GL_BYTE){
382        convertByteIndirectLoop(data,stride,cArrs.getCurrentData(),count,indices_type,indices,attribSize*sizeof(GLshort),attribSize);
383    }
384}
385
386void GLEScontext::convertIndirectVBO(GLESConversionArrays& cArrs,GLsizei count,GLenum indices_type,const GLvoid* indices,GLenum array_id,GLESpointer* p) {
387    RangeList ranges;
388    RangeList conversions;
389    GLushort* conversionIndices = NULL;
390    int attribSize = p->getSize();
391    int stride = p->getStride()?p->getStride():sizeof(GLfixed)*attribSize;
392    char* data = static_cast<char*>(p->getBufferData());
393    if(p->bufferNeedConversion()) {
394        indirectToBytesRanges(indices,indices_type,count,p,ranges); //converting indices range to buffer bytes ranges by offset
395        p->getBufferConversions(ranges,conversions); // getting from the buffer the relevant ranges that still needs to be converted
396        if(conversions.size()) { // there are some elements to convert
397            conversionIndices = new GLushort[count];
398            int nIndices = bytesRangesToIndices(conversions,p,conversionIndices); //converting bytes ranges by offset to indices in this array
399            convertFixedIndirectLoop(data,stride,data,nIndices,GL_UNSIGNED_SHORT,conversionIndices,stride,attribSize);
400        }
401    }
402    if(conversionIndices) delete[] conversionIndices;
403    cArrs.setArr(data,p->getStride(),GL_FLOAT);
404}
405
406
407
408void GLEScontext::bindBuffer(GLenum target,GLuint buffer) {
409    if(target == GL_ARRAY_BUFFER) {
410        m_arrayBuffer = buffer;
411    } else {
412       m_elementBuffer = buffer;
413    }
414}
415
416void GLEScontext::unbindBuffer(GLuint buffer) {
417    if(m_arrayBuffer == buffer)
418    {
419        m_arrayBuffer = 0;
420    }
421    if(m_elementBuffer == buffer)
422    {
423        m_elementBuffer = 0;
424    }
425}
426
427//checks if any buffer is binded to target
428bool GLEScontext::isBindedBuffer(GLenum target) {
429    if(target == GL_ARRAY_BUFFER) {
430        return m_arrayBuffer != 0;
431    } else {
432        return m_elementBuffer != 0;
433    }
434}
435
436GLuint GLEScontext::getBuffer(GLenum target) {
437    return target == GL_ARRAY_BUFFER ? m_arrayBuffer:m_elementBuffer;
438}
439
440GLvoid* GLEScontext::getBindedBuffer(GLenum target) {
441    GLuint bufferName = getBuffer(target);
442    if(!bufferName) return NULL;
443
444    GLESbuffer* vbo = static_cast<GLESbuffer*>(m_shareGroup->getObjectData(VERTEXBUFFER,bufferName).Ptr());
445    return vbo->getData();
446}
447
448void GLEScontext::getBufferSize(GLenum target,GLint* param) {
449    GLuint bufferName = getBuffer(target);
450    GLESbuffer* vbo = static_cast<GLESbuffer*>(m_shareGroup->getObjectData(VERTEXBUFFER,bufferName).Ptr());
451    *param = vbo->getSize();
452}
453
454void GLEScontext::getBufferUsage(GLenum target,GLint* param) {
455    GLuint bufferName = getBuffer(target);
456    GLESbuffer* vbo = static_cast<GLESbuffer*>(m_shareGroup->getObjectData(VERTEXBUFFER,bufferName).Ptr());
457    *param = vbo->getUsage();
458}
459
460bool GLEScontext::setBufferData(GLenum target,GLsizeiptr size,const GLvoid* data,GLenum usage) {
461    GLuint bufferName = getBuffer(target);
462    if(!bufferName) return false;
463    GLESbuffer* vbo = static_cast<GLESbuffer*>(m_shareGroup->getObjectData(VERTEXBUFFER,bufferName).Ptr());
464    return vbo->setBuffer(size,usage,data);
465}
466
467bool GLEScontext::setBufferSubData(GLenum target,GLintptr offset,GLsizeiptr size,const GLvoid* data) {
468
469    GLuint bufferName = getBuffer(target);
470    if(!bufferName) return false;
471    GLESbuffer* vbo = static_cast<GLESbuffer*>(m_shareGroup->getObjectData(VERTEXBUFFER,bufferName).Ptr());
472    return vbo->setSubBuffer(offset,size,data);
473}
474
475const char * GLEScontext::getExtensionString() {
476    const char * ret;
477    s_lock.lock();
478    if (s_glExtensions)
479        ret = s_glExtensions->c_str();
480    else
481        ret="";
482    s_lock.unlock();
483    return ret;
484}
485
486const char * GLEScontext::getVendorString() const {
487    return s_glVendor.c_str();
488}
489
490const char * GLEScontext::getRendererString() const {
491    return s_glRenderer.c_str();
492}
493
494const char * GLEScontext::getVersionString() const {
495    return s_glVersion.c_str();
496}
497
498void GLEScontext::getGlobalLock() {
499    s_lock.lock();
500}
501
502void GLEScontext::releaseGlobalLock() {
503    s_lock.unlock();
504}
505
506
507void GLEScontext::initCapsLocked(const GLubyte * extensionString)
508{
509    const char* cstring = (const char*)extensionString;
510
511    s_glDispatch.glGetIntegerv(GL_MAX_VERTEX_ATTRIBS,&s_glSupport.maxVertexAttribs);
512    s_glDispatch.glGetIntegerv(GL_MAX_CLIP_PLANES,&s_glSupport.maxClipPlane);
513    s_glDispatch.glGetIntegerv(GL_MAX_LIGHTS,&s_glSupport.maxLights);
514    s_glDispatch.glGetIntegerv(GL_MAX_TEXTURE_SIZE,&s_glSupport.maxTexSize);
515    s_glDispatch.glGetIntegerv(GL_MAX_TEXTURE_UNITS,&s_glSupport.maxTexUnits);
516    s_glDispatch.glGetIntegerv(GL_MAX_TEXTURE_IMAGE_UNITS,&s_glSupport.maxTexImageUnits);
517    const GLubyte* glslVersion = s_glDispatch.glGetString(GL_SHADING_LANGUAGE_VERSION);
518    s_glSupport.glslVersion = Version((const  char*)(glslVersion));
519
520    if (strstr(cstring,"GL_EXT_bgra ")!=NULL)
521        s_glSupport.GL_EXT_TEXTURE_FORMAT_BGRA8888 = true;
522
523    if (strstr(cstring,"GL_EXT_framebuffer_object ")!=NULL)
524        s_glSupport.GL_EXT_FRAMEBUFFER_OBJECT = true;
525
526    if (strstr(cstring,"GL_ARB_vertex_blend ")!=NULL)
527        s_glSupport.GL_ARB_VERTEX_BLEND = true;
528
529    if (strstr(cstring,"GL_ARB_matrix_palette ")!=NULL)
530        s_glSupport.GL_ARB_MATRIX_PALETTE = true;
531
532    if (strstr(cstring,"GL_EXT_packed_depth_stencil ")!=NULL )
533        s_glSupport.GL_EXT_PACKED_DEPTH_STENCIL = true;
534
535    if (strstr(cstring,"GL_OES_read_format ")!=NULL)
536        s_glSupport.GL_OES_READ_FORMAT = true;
537
538    if (strstr(cstring,"GL_ARB_half_float_pixel ")!=NULL)
539        s_glSupport.GL_ARB_HALF_FLOAT_PIXEL = true;
540
541    if (strstr(cstring,"GL_NV_half_float ")!=NULL)
542        s_glSupport.GL_NV_HALF_FLOAT = true;
543
544    if (strstr(cstring,"GL_ARB_half_float_vertex ")!=NULL)
545        s_glSupport.GL_ARB_HALF_FLOAT_VERTEX = true;
546
547    if (strstr(cstring,"GL_SGIS_generate_mipmap ")!=NULL)
548        s_glSupport.GL_SGIS_GENERATE_MIPMAP = true;
549
550    if (strstr(cstring,"GL_ARB_ES2_compatibility ")!=NULL)
551        s_glSupport.GL_ARB_ES2_COMPATIBILITY = true;
552
553    if (strstr(cstring,"GL_OES_standard_derivatives ")!=NULL)
554        s_glSupport.GL_OES_STANDARD_DERIVATIVES = true;
555
556}
557
558void GLEScontext::buildStrings(const char* baseVendor,
559        const char* baseRenderer, const char* baseVersion, const char* version)
560{
561    static const char VENDOR[]   = {"Google ("};
562    static const char RENDERER[] = {"Android Emulator OpenGL ES Translator ("};
563    const size_t VENDOR_LEN   = sizeof(VENDOR) - 1;
564    const size_t RENDERER_LEN = sizeof(RENDERER) - 1;
565
566    size_t baseVendorLen = strlen(baseVendor);
567    s_glVendor.clear();
568    s_glVendor.reserve(baseVendorLen + VENDOR_LEN + 1);
569    s_glVendor.append(VENDOR, VENDOR_LEN);
570    s_glVendor.append(baseVendor, baseVendorLen);
571    s_glVendor.append(")", 1);
572
573    size_t baseRendererLen = strlen(baseRenderer);
574    s_glRenderer.clear();
575    s_glRenderer.reserve(baseRendererLen + RENDERER_LEN + 1);
576    s_glRenderer.append(RENDERER, RENDERER_LEN);
577    s_glRenderer.append(baseRenderer, baseRendererLen);
578    s_glRenderer.append(")", 1);
579
580    size_t baseVersionLen = strlen(baseVersion);
581    size_t versionLen = strlen(version);
582    s_glVersion.clear();
583    s_glVersion.reserve(baseVersionLen + versionLen + 3);
584    s_glVersion.append(version, versionLen);
585    s_glVersion.append(" (", 2);
586    s_glVersion.append(baseVersion, baseVersionLen);
587    s_glVersion.append(")", 1);
588}
589
590bool GLEScontext::isTextureUnitEnabled(GLenum unit) {
591    for (int i=0;i<NUM_TEXTURE_TARGETS;++i) {
592        if (m_texState[unit-GL_TEXTURE0][i].enabled)
593            return true;
594    }
595    return false;
596}
597
598bool GLEScontext::glGetBooleanv(GLenum pname, GLboolean *params)
599{
600    GLint iParam;
601
602    if(glGetIntegerv(pname, &iParam))
603    {
604        *params = (iParam != 0);
605        return true;
606    }
607
608    return false;
609}
610
611bool GLEScontext::glGetFixedv(GLenum pname, GLfixed *params)
612{
613    bool result = false;
614    GLint numParams = 1;
615
616    GLint* iParams = new GLint[numParams];
617    if (numParams>0 && glGetIntegerv(pname,iParams)) {
618        while(numParams >= 0)
619        {
620            params[numParams] = I2X(iParams[numParams]);
621            numParams--;
622        }
623        result = true;
624    }
625    delete [] iParams;
626
627    return result;
628}
629
630bool GLEScontext::glGetFloatv(GLenum pname, GLfloat *params)
631{
632    bool result = false;
633    GLint numParams = 1;
634
635    GLint* iParams = new GLint[numParams];
636    if (numParams>0 && glGetIntegerv(pname,iParams)) {
637        while(numParams >= 0)
638        {
639            params[numParams] = (GLfloat)iParams[numParams];
640            numParams--;
641        }
642        result = true;
643    }
644    delete [] iParams;
645
646    return result;
647}
648
649bool GLEScontext::glGetIntegerv(GLenum pname, GLint *params)
650{
651    switch(pname)
652    {
653        case GL_ARRAY_BUFFER_BINDING:
654            *params = m_arrayBuffer;
655            break;
656
657        case GL_ELEMENT_ARRAY_BUFFER_BINDING:
658            *params = m_elementBuffer;
659            break;
660
661        case GL_TEXTURE_BINDING_CUBE_MAP:
662            *params = m_texState[m_activeTexture][TEXTURE_CUBE_MAP].texture;
663            break;
664
665        case GL_TEXTURE_BINDING_2D:
666            *params = m_texState[m_activeTexture][TEXTURE_2D].texture;
667            break;
668
669        case GL_ACTIVE_TEXTURE:
670            *params = m_activeTexture+GL_TEXTURE0;
671            break;
672
673        case GL_IMPLEMENTATION_COLOR_READ_TYPE_OES:
674            *params = GL_UNSIGNED_BYTE;
675            break;
676
677        case GL_IMPLEMENTATION_COLOR_READ_FORMAT_OES:
678            *params = GL_RGBA;
679            break;
680
681        case GL_MAX_TEXTURE_SIZE:
682            *params = getMaxTexSize();
683            break;
684        default:
685            return false;
686    }
687
688    return true;
689}
690
691TextureTarget GLEScontext::GLTextureTargetToLocal(GLenum target) {
692    TextureTarget value=TEXTURE_2D;
693    switch (target) {
694    case GL_TEXTURE_CUBE_MAP:
695    case GL_TEXTURE_CUBE_MAP_POSITIVE_X:
696    case GL_TEXTURE_CUBE_MAP_POSITIVE_Y:
697    case GL_TEXTURE_CUBE_MAP_POSITIVE_Z:
698    case GL_TEXTURE_CUBE_MAP_NEGATIVE_X:
699    case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y:
700    case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z:
701        value = TEXTURE_CUBE_MAP;
702        break;
703    case GL_TEXTURE_2D:
704        value = TEXTURE_2D;
705        break;
706    }
707    return value;
708}
709
710unsigned int GLEScontext::getBindedTexture(GLenum target) {
711    TextureTarget pos = GLTextureTargetToLocal(target);
712    return m_texState[m_activeTexture][pos].texture;
713}
714
715unsigned int GLEScontext::getBindedTexture(GLenum unit, GLenum target) {
716    TextureTarget pos = GLTextureTargetToLocal(target);
717    return m_texState[unit-GL_TEXTURE0][pos].texture;
718}
719
720void GLEScontext::setBindedTexture(GLenum target, unsigned int tex) {
721    TextureTarget pos = GLTextureTargetToLocal(target);
722    m_texState[m_activeTexture][pos].texture = tex;
723}
724
725void GLEScontext::setTextureEnabled(GLenum target, GLenum enable) {
726    TextureTarget pos = GLTextureTargetToLocal(target);
727    m_texState[m_activeTexture][pos].enabled = enable;
728}
729
730#define INTERNAL_NAME(x) (x +0x100000000ll);
731
732ObjectLocalName GLEScontext::getDefaultTextureName(GLenum target) {
733    ObjectLocalName name = 0;
734    switch (GLTextureTargetToLocal(target)) {
735    case TEXTURE_2D:
736        name = INTERNAL_NAME(0);
737        break;
738    case TEXTURE_CUBE_MAP:
739        name = INTERNAL_NAME(1);
740        break;
741    default:
742        name = 0;
743        break;
744    }
745    return name;
746}
747
748void GLEScontext::drawValidate(void)
749{
750    if(m_framebuffer == 0)
751        return;
752
753    ObjectDataPtr fbObj = m_shareGroup->getObjectData(FRAMEBUFFER,m_framebuffer);
754    if (fbObj.Ptr() == NULL)
755        return;
756
757    FramebufferData *fbData = (FramebufferData *)fbObj.Ptr();
758
759    fbData->validate(this);
760}
761