/* * Copyright (C) 2010 - 2011 Samsung Electronics Co., Ltd. All rights reserved. * * Contact: * DongKyun Yun * SangJin Kim * HyunGoo Kang * * Permission is hereby granted, free of charge, to any person obtaining a copy of * this software and associated documentation files (the "Software"), to deal in * the Software without restriction, including without limitation the rights to * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies * of the Software, and to permit persons to whom the Software is furnished to do * so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in all * copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE * SOFTWARE. * * Contributors: * - S-Core Co., Ltd * */ #include "gl_imp.h" #include #if defined(PROVIDING_OES_element_index_uint) #define GL_UNSIGNED_INT 0x1405 #endif GL_API void GL_APIENTRY EXTFN(DrawElements)(GLenum mode, GLsizei count, GLenum type, const GLvoid* indices) { int i, j; if (GL_TRIANGLE_FAN < mode) { INTFN(SetError)(GL_INVALID_ENUM); return; } switch (type) { default: INTFN(SetError)(GL_INVALID_ENUM); return; case GL_UNSIGNED_BYTE: case GL_UNSIGNED_SHORT: #if defined(PROVIDING_OES_element_index_uint) case GL_UNSIGNED_INT: #endif break; } if (FNPTR(IsEnabled)(GL_VERTEX_ARRAY) == GL_FALSE) return; if (count < 0) { INTFN(SetError)(GL_INVALID_VALUE); return; } else if (count == 0) { return; } GLint matrixMode; FNPTR(GetIntegerv)(GL_MATRIX_MODE, &matrixMode); #if ALEXGL_INTERNAL_VERSION >= 110 GLint arrayBufferBinding; GLint elementArrayBufferBinding; FNPTR(GetIntegerv)(GL_ARRAY_BUFFER_BINDING, &arrayBufferBinding); FNPTR(GetIntegerv)(GL_ELEMENT_ARRAY_BUFFER_BINDING, &elementArrayBufferBinding); #endif static GLbyte* pBufferArea = NULL; int maxIndex = 0; switch (type) { case GL_UNSIGNED_BYTE: { const GLubyte* ptr = 0; #if ALEXGL_INTERNAL_VERSION >= 110 static GLubyte* pElementArea = NULL; if (elementArrayBufferBinding != 0) { pElementArea = realloc(pElementArea, count * sizeof(GLubyte)); if (pElementArea == NULL) { INTFN(SetError)(GL_OUT_OF_MEMORY); return; } FNPTR(GetBufferSubData)(GL_ELEMENT_ARRAY_BUFFER, (GLintptr)(indices), count * sizeof(GLubyte), pElementArea); ptr = pElementArea; } #endif if (ptr == 0) { ptr = (const GLubyte*)(indices); } for (i = 0; i < count; i++) { if ((int)(ptr[i]) > maxIndex) maxIndex = (int)(ptr[i]); } } break; case GL_UNSIGNED_SHORT: { const GLushort* ptr = 0; #if ALEXGL_INTERNAL_VERSION >= 110 static GLushort* pElementArea = NULL; if (elementArrayBufferBinding != 0) { pElementArea = realloc(pElementArea, count * sizeof(GLushort)); if (pElementArea == NULL) { INTFN(SetError)(GL_OUT_OF_MEMORY); return; } FNPTR(GetBufferSubData)(GL_ELEMENT_ARRAY_BUFFER, (GLintptr)(indices), count * sizeof(GLushort), pElementArea); ptr = pElementArea; } #endif if (ptr == 0) { ptr = (const GLushort*)(indices); } for (i = 0; i < count; i++) { if ((int)(ptr[i]) > maxIndex) maxIndex = (int)(ptr[i]); } } break; #if defined(PROVIDING_OES_element_index_uint) case GL_UNSIGNED_INT: { const GLuint* ptr = 0; #if ALEXGL_INTERNAL_VERSION >= 110 static GLuint* pElementArea = NULL; if (elementArrayBufferBinding != 0) { pElementArea = realloc(pElementArea, count * sizeof(GLuint)); if (pElementArea == NULL) { INTFN(SetError)(GL_OUT_OF_MEMORY); return; } FNPTR(GetBufferSubData)(GL_ELEMENT_ARRAY_BUFFER, (GLintptr)(indices), count * sizeof(GLuint), pElementArea); ptr = pElementArea; } #endif if (ptr == 0) { ptr = (const GLuint*)(indices); } for (i = 0; i < count; i++) { if ((int)(ptr[i]) > maxIndex) maxIndex = (int)(ptr[i]); } } break; #endif } static GLshort* pVertexArea = NULL; GLfloat matrixModelview[16]; if (CCV(vertexArrayType) == GL_BYTE) { pVertexArea = realloc(pVertexArea, (maxIndex + 1) * CCV(vertexArraySize) * sizeof(GLushort)); if (pVertexArea == NULL) { INTFN(SetError)(GL_OUT_OF_MEMORY); return; } GLbyte* srcBase = 0; #if ALEXGL_INTERNAL_VERSION >= 110 if (CCV(vertexArrayBufferBinding) != 0) { pBufferArea = realloc(pBufferArea, (maxIndex + 1) * CCV(vertexArrayStride) * sizeof(GLubyte)); if (pBufferArea == NULL) { INTFN(SetError)(GL_OUT_OF_MEMORY); return; } FNPTR(BindBuffer)(GL_ARRAY_BUFFER, CCV(vertexArrayBufferBinding)); FNPTR(GetBufferSubData)(GL_ARRAY_BUFFER, (GLintptr)((GLbyte*)(CCV(vertexArrayPointer))), (maxIndex + 1) * CCV(vertexArrayStride), pBufferArea); srcBase = pBufferArea; } FNPTR(BindBuffer)(GL_ARRAY_BUFFER, 0); #endif if (srcBase == 0) { srcBase = (GLbyte*)(CCV(vertexArrayPointer)); } for (j = 0; j < maxIndex + 1; j++) { int k = CCV(vertexArraySize); GLshort* dst = &(pVertexArea[j * CCV(vertexArraySize)]); GLbyte* src = srcBase; while (k--) { *dst++ = (GLshort)(*src++); } srcBase += CCV(vertexArrayStride); } FNPTR(VertexPointer)(CCV(vertexArraySize), GL_SHORT, 0, pVertexArea); } else if (CCV(vertexArrayType) == GL_FIXED) { FNPTR(GetFloatv)(GL_MODELVIEW_MATRIX, matrixModelview); FNPTR(MatrixMode)(GL_MODELVIEW); FNPTR(Scalef)(1 / 65536.0F, 1 / 65536.0F, 1 / 65536.0F); } static GLfloat* pNormalArea = NULL; if (FNPTR(IsEnabled)(GL_NORMAL_ARRAY) == GL_TRUE) { if (CCV(normalArrayType) == GL_FIXED) { pNormalArea = realloc(pNormalArea, (maxIndex + 1) * 3 * sizeof(GLfloat)); if (pNormalArea == NULL) { INTFN(SetError)(GL_OUT_OF_MEMORY); return; } GLfixed* srcBase = 0; #if ALEXGL_INTERNAL_VERSION >= 110 if (CCV(normalArrayBufferBinding) != 0) { pBufferArea = realloc(pBufferArea, (maxIndex + 1) * CCV(normalArrayStride) * sizeof(GLubyte)); if (pBufferArea == NULL) { INTFN(SetError)(GL_OUT_OF_MEMORY); return; } FNPTR(BindBuffer)(GL_ARRAY_BUFFER, CCV(normalArrayBufferBinding)); FNPTR(GetBufferSubData)(GL_ARRAY_BUFFER, (GLintptr)((GLbyte*)(CCV(normalArrayPointer))), (maxIndex + 1) * CCV(normalArrayStride), pBufferArea); srcBase = (GLfixed*)(pBufferArea); } FNPTR(BindBuffer)(GL_ARRAY_BUFFER, 0); #endif if (srcBase == 0) { srcBase = (GLfixed*)( (GLbyte*)(CCV(normalArrayPointer))); } for (j = 0; j < maxIndex + 1; j++) { int k = 3; GLfloat* dst = &(pNormalArea[j * 3]); GLfixed* src = srcBase; while (k--) { *dst++ = (*src++) / 65536.0F; } srcBase = (GLfixed*)((GLbyte*)(srcBase) + CCV(normalArrayStride)); } FNPTR(NormalPointer)(GL_FLOAT, 0, pNormalArea); } } static GLfloat* pColorArea = NULL; if (FNPTR(IsEnabled)(GL_COLOR_ARRAY) == GL_TRUE) { if (CCV(colorArrayType) == GL_FIXED) { pColorArea = realloc(pColorArea, (maxIndex + 1) * 4 * sizeof(GLfloat)); GLfixed* srcBase = 0; #if ALEXGL_INTERNAL_VERSION >= 110 if (CCV(colorArrayBufferBinding) != 0) { pBufferArea = realloc(pBufferArea, (maxIndex + 1) * CCV(colorArrayStride) * sizeof(GLubyte)); if (pBufferArea == NULL) { INTFN(SetError)(GL_OUT_OF_MEMORY); return; } FNPTR(BindBuffer)(GL_ARRAY_BUFFER, CCV(colorArrayBufferBinding)); FNPTR(GetBufferSubData)(GL_ARRAY_BUFFER, (GLintptr)((GLbyte*)(CCV(colorArrayPointer))), (maxIndex + 1) * CCV(colorArrayStride), pBufferArea); srcBase = (GLfixed*)(pBufferArea); } FNPTR(BindBuffer)(GL_ARRAY_BUFFER, 0); #endif if (srcBase == 0) { srcBase = (GLfixed*)( (GLbyte*)(CCV(colorArrayPointer))); } for (j = 0; j < maxIndex + 1; j++) { int k = 4; GLfloat* dst = &(pColorArea[j * 4]); GLfixed* src = srcBase; while (k--) { *dst++ = (*src++) / 65536.0F; } srcBase = (GLfixed*)((GLbyte*)(srcBase) + CCV(colorArrayStride)); } FNPTR(ColorPointer)(4, GL_FLOAT, 0, pColorArea); } } static GLshort* pTexCoordArea[ALEXGL_MAX_TEXTURE_UNITS] = { NULL, NULL, NULL, NULL }; GLfloat matrixTexture[ALEXGL_MAX_TEXTURE_UNITS][16]; for (i = 0; i < ALEXGL_MAX_TEXTURE_UNITS; i++) { if (CCV(texture2D[i]) != GL_TRUE || CCV(texCoordArray[i]) != GL_TRUE) continue; if (CCV(texCoordArrayType[i]) == GL_BYTE) { pTexCoordArea[i] = realloc(pTexCoordArea[i], (maxIndex + 1) * CCV(texCoordArraySize[i]) * sizeof(GLshort)); if (pTexCoordArea[i] == NULL) { INTFN(SetError)(GL_OUT_OF_MEMORY); return; } GLbyte* srcBase = 0; #if ALEXGL_INTERNAL_VERSION >= 110 if (CCV(texCoordArrayBufferBinding[i]) != 0) { pBufferArea = realloc(pBufferArea, (maxIndex + 1) * CCV(texCoordArrayStride[i]) * sizeof(GLubyte)); if (pBufferArea == NULL) { INTFN(SetError)(GL_OUT_OF_MEMORY); return; } FNPTR(BindBuffer)(GL_ARRAY_BUFFER, CCV(texCoordArrayBufferBinding[i])); FNPTR(GetBufferSubData)(GL_ARRAY_BUFFER, (GLintptr)( (GLbyte*)(CCV(texCoordArrayPointer[i]))), (maxIndex + 1) * CCV(texCoordArrayStride[i]), pBufferArea); srcBase = pBufferArea; } FNPTR(BindBuffer)(GL_ARRAY_BUFFER, 0); #endif if (srcBase == 0) { srcBase = (GLbyte*)(CCV(texCoordArrayPointer[i])); } for (j = 0; j < maxIndex + 1; j++) { int k = CCV(texCoordArraySize[i]); GLshort* dst = &(pTexCoordArea[i][j * CCV(texCoordArraySize[i])]); GLbyte* src = srcBase; while (k--) { *dst++ = (GLshort)(*src++); } srcBase += CCV(texCoordArrayStride[i]); } FNPTR(ClientActiveTexture)(GL_TEXTURE0 + i); FNPTR(TexCoordPointer)(CCV(texCoordArraySize[i]), GL_SHORT, 0, pTexCoordArea[i]); } else if (CCV(texCoordArrayType[i]) == GL_FIXED) { FNPTR(MatrixMode)(GL_TEXTURE); FNPTR(ActiveTexture)(GL_TEXTURE0 + i); FNPTR(GetFloatv)(GL_TEXTURE_MATRIX, matrixTexture[i]); FNPTR(Scalef)(1 / 65536.0F, 1 / 65536.0F, 1 / 65536.0F); } } if (mode == GL_POINTS && CCV(pointSizeArrayOES) == GL_TRUE) { GLbyte* srcBase = 0; #if ALEXGL_INTERNAL_VERSION >= 110 if (CCV(pointSizeArrayBufferBindingOES) != 0) { pBufferArea = realloc(pBufferArea, (maxIndex + 1) * CCV(pointSizeArrayStrideOES) * sizeof(GLubyte)); if (pBufferArea == NULL) { INTFN(SetError)(GL_OUT_OF_MEMORY); return; } FNPTR(BindBuffer)(GL_ARRAY_BUFFER, CCV(pointSizeArrayBufferBindingOES)); FNPTR(GetBufferSubData)(GL_ARRAY_BUFFER, (GLintptr)((GLbyte*)(CCV(pointSizeArrayPointerOES))), (maxIndex + 1) * CCV(pointSizeArrayStrideOES), pBufferArea); srcBase = pBufferArea; } FNPTR(BindBuffer)(GL_ARRAY_BUFFER, 0); #endif if (srcBase == 0) { srcBase = (GLbyte*)(CCV(pointSizeArrayPointerOES)); } switch (type) { case GL_UNSIGNED_BYTE: { const GLubyte* ptr = (const GLubyte*)(indices); for (i = 0; i < count; i++) { if (CCV(pointSizeArrayTypeOES) == GL_FLOAT) { FNPTR(PointSize)(*((GLfloat*)(srcBase) + ptr[i])); } else { FNPTR(PointSize)(x2f(*((GLfixed*)(srcBase) + ptr[i]))); } FNPTR(DrawElements)(mode, 1, type, (const GLvoid*)(ptr + i)); } } break; case GL_UNSIGNED_SHORT: { const GLushort* ptr = (const GLushort*)(indices); for (i = 0; i < count; i++) { if (CCV(pointSizeArrayTypeOES) == GL_FLOAT) { FNPTR(PointSize)(*((GLfloat*)(srcBase) + ptr[i])); } else { FNPTR(PointSize)(x2f(*((GLfixed*)(srcBase) + ptr[i]))); } FNPTR(DrawElements)(mode, 1, type, (const GLvoid*)(ptr + i)); } } break; #if defined(PROVIDING_OES_element_index_uint) case GL_UNSIGNED_INT: { const GLuint* ptr = (const GLuint*)(indices); for (i = 0; i < count; i++) { if (CCV(pointSizeArrayTypeOES) == GL_FLOAT) { FNPTR(PointSize)(*((GLfloat*)(srcBase) + ptr[i])); } else { FNPTR(PointSize)(x2f(*((GLfixed*)(srcBase) + ptr[i]))); } FNPTR(DrawElements)(mode, 1, type, (const GLvoid*)(ptr + i)); } } break; #endif } } else { FNPTR(DrawElements)(mode, count, type, indices); } if (CCV(vertexArrayType) == GL_FIXED) { FNPTR(MatrixMode)(GL_MODELVIEW); FNPTR(LoadMatrixf)(matrixModelview); } FNPTR(MatrixMode)(GL_TEXTURE); for (i = 0; i < ALEXGL_MAX_TEXTURE_UNITS; i++) { if (CCV(texture2D[i]) != GL_TRUE || CCV(texCoordArray[i]) != GL_TRUE) continue; if (CCV(texCoordArrayType[i]) == GL_FIXED) { FNPTR(ActiveTexture)(GL_TEXTURE0 + i); FNPTR(LoadMatrixf)(matrixTexture[i]); } } FNPTR(MatrixMode)(matrixMode); FNPTR(ActiveTexture)(GL_TEXTURE0 + CCV(activeTexture)); FNPTR(ClientActiveTexture)(GL_TEXTURE0 + CCV(clientActiveTexture)); #if ALEXGL_INTERNAL_VERSION >= 110 FNPTR(BindBuffer)(GL_ARRAY_BUFFER, arrayBufferBinding); FNPTR(BindBuffer)(GL_ELEMENT_ARRAY_BUFFER, elementArrayBufferBinding); #endif }