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 } 35 m_initialized = true; 36 } 37 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 47 void GLEScmContext::setActiveTexture(GLenum tex) { 48 m_activeTexture = tex - GL_TEXTURE0; 49 } 50 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 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 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 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 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 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 205 void GLEScmContext::drawPointsArrs(GLESConversionArrays& arrs,GLint first,GLsizei count) { 206 drawPointsData(arrs,first,count,0,NULL,false); 207 } 208 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 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 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 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 291 int GLEScmContext::getMaxTexUnits() { 292 return getCaps()->maxTexUnits; 293 } 294 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 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 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 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