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