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