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
17 #include "GLEScmContext.h"
18 #include "GLEScmUtils.h"
19 #include <GLcommon/GLutils.h>
20 #include <GLcommon/GLconversion_macros.h>
21 #include <string.h>
22 #include <GLES/gl.h>
23 #include <GLES/glext.h>
24
init()25 void GLEScmContext::init() {
26 android::Mutex::Autolock mutex(s_lock);
27 if(!m_initialized) {
28 s_glDispatch.dispatchFuncs(GLES_1_1);
29 GLEScontext::init();
30
31 m_texCoords = new GLESpointer[s_glSupport.maxTexUnits];
32 m_map[GL_TEXTURE_COORD_ARRAY] = &m_texCoords[m_clientActiveTexture];
33
34 buildStrings((const char*)dispatcher().glGetString(GL_VENDOR),
35 (const char*)dispatcher().glGetString(GL_RENDERER),
36 (const char*)dispatcher().glGetString(GL_VERSION),
37 "OpenGL ES-CM 1.1");
38 }
39 m_initialized = true;
40 }
41
GLEScmContext()42 GLEScmContext::GLEScmContext():GLEScontext(),m_texCoords(NULL),m_pointsIndex(-1), m_clientActiveTexture(0) {
43
44 m_map[GL_COLOR_ARRAY] = new GLESpointer();
45 m_map[GL_NORMAL_ARRAY] = new GLESpointer();
46 m_map[GL_VERTEX_ARRAY] = new GLESpointer();
47 m_map[GL_POINT_SIZE_ARRAY_OES] = new GLESpointer();
48 }
49
50
setActiveTexture(GLenum tex)51 void GLEScmContext::setActiveTexture(GLenum tex) {
52 m_activeTexture = tex - GL_TEXTURE0;
53 }
54
setClientActiveTexture(GLenum tex)55 void GLEScmContext::setClientActiveTexture(GLenum tex) {
56 m_clientActiveTexture = tex - GL_TEXTURE0;
57 m_map[GL_TEXTURE_COORD_ARRAY] = &m_texCoords[m_clientActiveTexture];
58 }
59
~GLEScmContext()60 GLEScmContext::~GLEScmContext(){
61 if(m_texCoords){
62 delete[] m_texCoords;
63 m_texCoords = NULL;
64 }
65 m_map[GL_TEXTURE_COORD_ARRAY] = NULL;
66 }
67
68
69 //setting client side arr
setupArr(const GLvoid * arr,GLenum arrayType,GLenum dataType,GLint size,GLsizei stride,GLboolean normalized,int index)70 void GLEScmContext::setupArr(const GLvoid* arr,GLenum arrayType,GLenum dataType,GLint size,GLsizei stride,GLboolean normalized, int index){
71 if( arr == NULL) return;
72 switch(arrayType) {
73 case GL_VERTEX_ARRAY:
74 s_glDispatch.glVertexPointer(size,dataType,stride,arr);
75 break;
76 case GL_NORMAL_ARRAY:
77 s_glDispatch.glNormalPointer(dataType,stride,arr);
78 break;
79 case GL_TEXTURE_COORD_ARRAY:
80 s_glDispatch.glTexCoordPointer(size,dataType,stride,arr);
81 break;
82 case GL_COLOR_ARRAY:
83 s_glDispatch.glColorPointer(size,dataType,stride,arr);
84 break;
85 case GL_POINT_SIZE_ARRAY_OES:
86 m_pointsIndex = index;
87 break;
88 }
89 }
90
91
setupArrayPointerHelper(GLESConversionArrays & cArrs,GLint first,GLsizei count,GLenum type,const GLvoid * indices,bool direct,GLenum array_id,GLESpointer * p)92 void GLEScmContext::setupArrayPointerHelper(GLESConversionArrays& cArrs,GLint first,GLsizei count,GLenum type,const GLvoid* indices,bool direct,GLenum array_id,GLESpointer* p){
93 unsigned int size = p->getSize();
94 GLenum dataType = p->getType();
95
96 if(needConvert(cArrs,first,count,type,indices,direct,p,array_id)){
97 //conversion has occured
98 ArrayData currentArr = cArrs.getCurrentArray();
99 setupArr(currentArr.data,array_id,currentArr.type,size,currentArr.stride,GL_FALSE, cArrs.getCurrentIndex());
100 ++cArrs;
101 } else {
102 setupArr(p->getData(),array_id,dataType,size,p->getStride(), GL_FALSE);
103 }
104 }
105
setupArraysPointers(GLESConversionArrays & cArrs,GLint first,GLsizei count,GLenum type,const GLvoid * indices,bool direct)106 void GLEScmContext::setupArraysPointers(GLESConversionArrays& cArrs,GLint first,GLsizei count,GLenum type,const GLvoid* indices,bool direct) {
107 ArraysMap::iterator it;
108 m_pointsIndex = -1;
109
110 //going over all clients arrays Pointers
111 for ( it=m_map.begin() ; it != m_map.end(); it++ ) {
112
113 GLenum array_id = (*it).first;
114 GLESpointer* p = (*it).second;
115 if(!isArrEnabled(array_id)) continue;
116 if(array_id == GL_TEXTURE_COORD_ARRAY) continue; //handling textures later
117 setupArrayPointerHelper(cArrs,first,count,type,indices,direct,array_id,p);
118 }
119
120 unsigned int activeTexture = m_clientActiveTexture + GL_TEXTURE0;
121
122 s_lock.lock();
123 int maxTexUnits = s_glSupport.maxTexUnits;
124 s_lock.unlock();
125
126 //converting all texture coords arrays
127 for(int i=0; i< maxTexUnits;i++) {
128
129 unsigned int tex = GL_TEXTURE0+i;
130 setClientActiveTexture(tex);
131 s_glDispatch.glClientActiveTexture(tex);
132
133 GLenum array_id = GL_TEXTURE_COORD_ARRAY;
134 GLESpointer* p = m_map[array_id];
135 if(!isArrEnabled(array_id)) continue;
136 setupArrayPointerHelper(cArrs,first,count,type,indices,direct,array_id,p);
137 }
138
139 setClientActiveTexture(activeTexture);
140 s_glDispatch.glClientActiveTexture(activeTexture);
141 }
142
drawPointsData(GLESConversionArrays & cArrs,GLint first,GLsizei count,GLenum type,const GLvoid * indices_in,bool isElemsDraw)143 void GLEScmContext::drawPointsData(GLESConversionArrays& cArrs,GLint first,GLsizei count,GLenum type,const GLvoid* indices_in,bool isElemsDraw) {
144 const char *pointsArr = NULL;
145 int stride = 0;
146 GLESpointer* p = m_map[GL_POINT_SIZE_ARRAY_OES];
147
148 //choosing the right points sizes array source
149 if(m_pointsIndex >= 0) { //point size array was converted
150 pointsArr = (const char*)(cArrs[m_pointsIndex].data);
151 stride = cArrs[m_pointsIndex].stride;
152 } else {
153 pointsArr = static_cast<const char*>(p->getData());
154 stride = p->getStride();
155 }
156
157 if(stride == 0){
158 stride = sizeof(GLfloat);
159 }
160
161
162 if(isElemsDraw) {
163 int tSize = type == GL_UNSIGNED_SHORT ? 2 : 1;
164
165 int i = 0;
166 while(i<count)
167 {
168 int sStart = i;
169 int sCount = 1;
170
171 #define INDEX \
172 (type == GL_UNSIGNED_SHORT ? \
173 static_cast<const GLushort*>(indices_in)[i]: \
174 static_cast<const GLubyte*>(indices_in)[i])
175
176 GLfloat pSize = *((GLfloat*)(pointsArr+(INDEX*stride)));
177 i++;
178
179 while(i < count && pSize == *((GLfloat*)(pointsArr+(INDEX*stride))))
180 {
181 sCount++;
182 i++;
183 }
184
185 s_glDispatch.glPointSize(pSize);
186 s_glDispatch.glDrawElements(GL_POINTS, sCount, type, (char*)indices_in+sStart*tSize);
187 }
188 } else {
189 int i = 0;
190 while(i<count)
191 {
192 int sStart = i;
193 int sCount = 1;
194 GLfloat pSize = *((GLfloat*)(pointsArr+((first+i)*stride)));
195 i++;
196
197 while(i < count && pSize == *((GLfloat*)(pointsArr+((first+i)*stride))))
198 {
199 sCount++;
200 i++;
201 }
202
203 s_glDispatch.glPointSize(pSize);
204 s_glDispatch.glDrawArrays(GL_POINTS, first+sStart, sCount);
205 }
206 }
207 }
208
drawPointsArrs(GLESConversionArrays & arrs,GLint first,GLsizei count)209 void GLEScmContext::drawPointsArrs(GLESConversionArrays& arrs,GLint first,GLsizei count) {
210 drawPointsData(arrs,first,count,0,NULL,false);
211 }
212
drawPointsElems(GLESConversionArrays & arrs,GLsizei count,GLenum type,const GLvoid * indices_in)213 void GLEScmContext::drawPointsElems(GLESConversionArrays& arrs,GLsizei count,GLenum type,const GLvoid* indices_in) {
214 drawPointsData(arrs,0,count,type,indices_in,true);
215 }
216
needConvert(GLESConversionArrays & cArrs,GLint first,GLsizei count,GLenum type,const GLvoid * indices,bool direct,GLESpointer * p,GLenum array_id)217 bool GLEScmContext::needConvert(GLESConversionArrays& cArrs,GLint first,GLsizei count,GLenum type,const GLvoid* indices,bool direct,GLESpointer* p,GLenum array_id) {
218
219 bool usingVBO = p->isVBO();
220 GLenum arrType = p->getType();
221 /*
222 conversion is not necessary in the following cases:
223 (*) array type is byte but it is not vertex or texture array
224 (*) array type is not fixed
225 */
226 if((arrType != GL_FIXED) && (arrType != GL_BYTE)) return false;
227 if((arrType == GL_BYTE && (array_id != GL_VERTEX_ARRAY)) &&
228 (arrType == GL_BYTE && (array_id != GL_TEXTURE_COORD_ARRAY)) ) return false;
229
230
231 bool byteVBO = (arrType == GL_BYTE) && usingVBO;
232 if(byteVBO){
233 p->redirectPointerData();
234 }
235
236 if(!usingVBO || byteVBO) {
237 if (direct) {
238 convertDirect(cArrs,first,count,array_id,p);
239 } else {
240 convertIndirect(cArrs,count,type,indices,array_id,p);
241 }
242 } else {
243 if (direct) {
244 convertDirectVBO(cArrs,first,count,array_id,p) ;
245 } else {
246 convertIndirectVBO(cArrs,count,type,indices,array_id,p);
247 }
248 }
249 return true;
250 }
251
getPointer(GLenum arrType)252 const GLESpointer* GLEScmContext::getPointer(GLenum arrType) {
253 GLenum type =
254 arrType == GL_VERTEX_ARRAY_POINTER ? GL_VERTEX_ARRAY :
255 arrType == GL_NORMAL_ARRAY_POINTER ? GL_NORMAL_ARRAY :
256 arrType == GL_TEXTURE_COORD_ARRAY_POINTER ? GL_TEXTURE_COORD_ARRAY :
257 arrType == GL_COLOR_ARRAY_POINTER ? GL_COLOR_ARRAY :
258 arrType == GL_POINT_SIZE_ARRAY_POINTER_OES ? GL_POINT_SIZE_ARRAY_OES :
259 0;
260 if(type != 0)
261 {
262 return GLEScontext::getPointer(type);
263 }
264 return NULL;
265 }
266
initExtensionString()267 void GLEScmContext::initExtensionString() {
268 *s_glExtensions = "GL_OES_blend_func_separate GL_OES_blend_equation_separate GL_OES_blend_subtract "
269 "GL_OES_byte_coordinates GL_OES_compressed_paletted_texture GL_OES_point_size_array "
270 "GL_OES_point_sprite GL_OES_single_precision GL_OES_stencil_wrap GL_OES_texture_env_crossbar "
271 "GL_OES_texture_mirored_repeat GL_OES_EGL_image GL_OES_element_index_uint GL_OES_draw_texture "
272 "GL_OES_texture_cube_map GL_OES_draw_texture ";
273 if (s_glSupport.GL_OES_READ_FORMAT)
274 *s_glExtensions+="GL_OES_read_format ";
275 if (s_glSupport.GL_EXT_FRAMEBUFFER_OBJECT) {
276 *s_glExtensions+="GL_OES_framebuffer_object GL_OES_depth24 GL_OES_depth32 GL_OES_fbo_render_mipmap "
277 "GL_OES_rgb8_rgba8 GL_OES_stencil1 GL_OES_stencil4 GL_OES_stencil8 ";
278 }
279 if (s_glSupport.GL_EXT_PACKED_DEPTH_STENCIL)
280 *s_glExtensions+="GL_OES_packed_depth_stencil ";
281 if (s_glSupport.GL_EXT_TEXTURE_FORMAT_BGRA8888)
282 *s_glExtensions+="GL_EXT_texture_format_BGRA8888 GL_APPLE_texture_format_BGRA8888 ";
283 if (s_glSupport.GL_ARB_MATRIX_PALETTE && s_glSupport.GL_ARB_VERTEX_BLEND) {
284 *s_glExtensions+="GL_OES_matrix_palette ";
285 GLint max_palette_matrices=0;
286 GLint max_vertex_units=0;
287 dispatcher().glGetIntegerv(GL_MAX_PALETTE_MATRICES_OES,&max_palette_matrices);
288 dispatcher().glGetIntegerv(GL_MAX_VERTEX_UNITS_OES,&max_vertex_units);
289 if (max_palette_matrices>=32 && max_vertex_units>=4)
290 *s_glExtensions+="GL_OES_extended_matrix_palette ";
291 }
292 *s_glExtensions+="GL_OES_compressed_ETC1_RGB8_texture ";
293 }
294
getMaxTexUnits()295 int GLEScmContext::getMaxTexUnits() {
296 return getCaps()->maxTexUnits;
297 }
298
glGetBooleanv(GLenum pname,GLboolean * params)299 bool GLEScmContext::glGetBooleanv(GLenum pname, GLboolean *params)
300 {
301 GLint iParam;
302
303 if(glGetIntegerv(pname, &iParam))
304 {
305 *params = (iParam != 0);
306 return true;
307 }
308
309 return false;
310 }
311
glGetFixedv(GLenum pname,GLfixed * params)312 bool GLEScmContext::glGetFixedv(GLenum pname, GLfixed *params)
313 {
314 GLint iParam;
315
316 if(glGetIntegerv(pname, &iParam))
317 {
318 *params = I2X(iParam);
319 return true;
320 }
321
322 return false;
323 }
324
glGetFloatv(GLenum pname,GLfloat * params)325 bool GLEScmContext::glGetFloatv(GLenum pname, GLfloat *params)
326 {
327 GLint iParam;
328
329 if(glGetIntegerv(pname, &iParam))
330 {
331 *params = (GLfloat)iParam;
332 return true;
333 }
334
335 return false;
336 }
337
glGetIntegerv(GLenum pname,GLint * params)338 bool GLEScmContext::glGetIntegerv(GLenum pname, GLint *params)
339 {
340 if(GLEScontext::glGetIntegerv(pname, params))
341 return true;
342
343 const GLESpointer* ptr = NULL;
344
345 switch(pname){
346 case GL_VERTEX_ARRAY_BUFFER_BINDING:
347 case GL_VERTEX_ARRAY_SIZE:
348 case GL_VERTEX_ARRAY_STRIDE:
349 case GL_VERTEX_ARRAY_TYPE:
350 ptr = getPointer(GL_VERTEX_ARRAY_POINTER);
351 break;
352
353 case GL_NORMAL_ARRAY_BUFFER_BINDING:
354 case GL_NORMAL_ARRAY_STRIDE:
355 case GL_NORMAL_ARRAY_TYPE:
356 ptr = getPointer(GL_NORMAL_ARRAY_POINTER);
357 break;
358
359 case GL_COLOR_ARRAY_BUFFER_BINDING:
360 case GL_COLOR_ARRAY_SIZE:
361 case GL_COLOR_ARRAY_STRIDE:
362 case GL_COLOR_ARRAY_TYPE:
363 ptr = getPointer(GL_COLOR_ARRAY_POINTER);
364 break;
365
366 case GL_TEXTURE_COORD_ARRAY_BUFFER_BINDING:
367 case GL_TEXTURE_COORD_ARRAY_SIZE:
368 case GL_TEXTURE_COORD_ARRAY_STRIDE:
369 case GL_TEXTURE_COORD_ARRAY_TYPE:
370 ptr = getPointer(GL_TEXTURE_COORD_ARRAY_POINTER);
371 break;
372
373 case GL_POINT_SIZE_ARRAY_BUFFER_BINDING_OES:
374 case GL_POINT_SIZE_ARRAY_STRIDE_OES:
375 case GL_POINT_SIZE_ARRAY_TYPE_OES:
376 ptr = getPointer(GL_POINT_SIZE_ARRAY_POINTER_OES);
377 break;
378
379 default:
380 return false;
381 }
382
383 switch(pname)
384 {
385 case GL_VERTEX_ARRAY_BUFFER_BINDING:
386 case GL_NORMAL_ARRAY_BUFFER_BINDING:
387 case GL_COLOR_ARRAY_BUFFER_BINDING:
388 case GL_TEXTURE_COORD_ARRAY_BUFFER_BINDING:
389 case GL_POINT_SIZE_ARRAY_BUFFER_BINDING_OES:
390 *params = ptr ? ptr->getBufferName() : 0;
391 break;
392
393 case GL_VERTEX_ARRAY_STRIDE:
394 case GL_NORMAL_ARRAY_STRIDE:
395 case GL_COLOR_ARRAY_STRIDE:
396 case GL_TEXTURE_COORD_ARRAY_STRIDE:
397 case GL_POINT_SIZE_ARRAY_STRIDE_OES:
398 *params = ptr ? ptr->getStride() : 0;
399 break;
400
401 case GL_VERTEX_ARRAY_SIZE:
402 case GL_COLOR_ARRAY_SIZE:
403 case GL_TEXTURE_COORD_ARRAY_SIZE:
404 *params = ptr ? ptr->getSize() : 0;
405 break;
406
407 case GL_VERTEX_ARRAY_TYPE:
408 case GL_NORMAL_ARRAY_TYPE:
409 case GL_COLOR_ARRAY_TYPE:
410 case GL_TEXTURE_COORD_ARRAY_TYPE:
411 case GL_POINT_SIZE_ARRAY_TYPE_OES:
412 *params = ptr ? ptr->getType() : 0;
413 break;
414 }
415
416 return true;
417 }
418