检查系统支持的OpenGL版本的方法有一下几种方法:
GL_VERSION
GL_SHADING_LANGUAGE_VERSION
此方法适用于创建EGLContext阶段。
要支持GLES3.0 要求EGL版本在1.4以上。
EGL初始化的时候会返回EGL的版本信息,根据此版本选择合适的GLES版本号,具体代码如下:
if (!eglInitialize(m_display, &major, &minor)) {
return XR_EGL_BAD_DISPLAY;
}
LOGI("eglInitialize: major: %d, minor: %d", major, minor);
if (minor >= 4 && s_nGLVersion >= 3) {
nGLRenderType = EGL_OPENGL_ES3_BIT_KHR;
} else {
nGLRenderType = EGL_OPENGL_ES2_BIT;
s_nGLVersion = 2;
}
...
EGLint attribList[]{
EGL_CONTEXT_CLIENT_VERSION, s_nGLVersion,
EGL_NONE
};
m_context = eglCreateContext(m_display, config, sharedContext, attribList);
int clientVersion;
eglQueryContext(m_display, m_context, EGL_CONTEXT_CLIENT_VERSION, &clientVersion);
LOGI("EGLContext created, client version %d\n", clientVersion);
GL_VERSION
此方法必须在EGLContext已经创建好的前提是下才能使用。
const char* versionStr = (const char*)glGetString(GL_VERSION);
return strstr(versionStr, "OpenGL ES 3.") && gl3stubInit();
GL_SHADING_LANGUAGE_VERSION
此方法必须在EGLContext已经创建好的前提是下才能使用。
std::string glslVersion = (const char*)glGetString(GL_SHADING_LANGUAGE_VERSION);
if ( glslVersion.empty())
{
bRet = false;
}
bRet = (strncmp( "OpenGL ES GLSL ES 3", glslVersion.c_str(), 19) == 0) ;
在Android很多机型中,哪怕
EGL_CONTEXT_CLIENT_VERSION申请的是2.0的版本,最终也会创建GLES3.0的环境
如果手机不支持GLES3.0,那么常规的使用方法就需要用宏把GLES 3.0的API包起来,否者就会出现变异问题。采用宏的方式会造成代码混乱,可读性较差。
针对上面的问题,这里提供一种打桩的形式,就是通过eglGetProcAddress
把GLES接口嗅探出来。具体实现如下:
/*
* GL3Stub.h
*/
GLboolean gl3stubInit();
/*-------------------------------------------------------------------------
* Data type definitions
*-----------------------------------------------------------------------*/
/* OpenGL ES 3.0 */
typedef unsigned short GLhalf;
#if __ANDROID_API__ <= 19
typedef khronos_int64_t GLint64;
typedef khronos_uint64_t GLuint64;
typedef struct __GLsync *GLsync;
#endif
/*-------------------------------------------------------------------------
* Token definitions
*-----------------------------------------------------------------------*/
/* OpenGL ES core versions */
#define GL_ES_VERSION_3_0 1
/* OpenGL ES 3.0 */
#define GL_READ_BUFFER 0x0C02
#define GL_UNPACK_ROW_LENGTH 0x0CF2
#define GL_UNPACK_SKIP_ROWS 0x0CF3
#define GL_UNPACK_SKIP_PIXELS 0x0CF4
#define GL_PACK_ROW_LENGTH 0x0D02
#define GL_PACK_SKIP_ROWS 0x0D03
........
/*
* GL3Stub.c
*/
GLboolean gl3stubInit() {
#define FIND_PROC(s) s = (void*)eglGetProcAddress(#s)
FIND_PROC(glReadBuffer);
FIND_PROC(glDrawRangeElements);
FIND_PROC(glTexImage3D);
...
#undef FIND_PROC
if (!glReadBuffer ||
!glDrawRangeElements ||
!glTexImage3D ||
!glTexSubImage3D ||
...
) {
return GL_FALSE;
}
}
/* Function pointer definitions */
GL_APICALL void (* GL_APIENTRY glReadBuffer) (GLenum mode);
GL_APICALL void (* GL_APIENTRY glDrawRangeElements) (GLenum mode, GLuint start, GLuint end, GLsizei count, GLenum type, const GLvoid* indices);
GL_APICALL void (* GL_APIENTRY glTexImage3D) (GLenum target, GLint level, GLint internalformat, GLsizei width, GLsizei height, GLsizei depth, GLint border, GLenum format, GLenum type, const GLvoid* pixels);
GL_APICALL void (* GL_APIENTRY glTexSubImage3D) (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLenum type, const GLvoid* pixels);
GL_APICALL void (* GL_APIENTRY glCopyTexSubImage3D) (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLint x, GLint y, GLsizei width, GLsizei height);
GL_APICALL void (* GL_APIENTRY glCompressedTexImage3D) (GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth, GLint border, GLsizei imageSize, const GLvoid* data);
GL_APICALL void (* GL_APIENTRY glCompressedTexSubImage3D) (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLsizei imageSize, const GLvoid* data);
GL_APICALL void (* GL_APIENTRY glGenQueries) (GLsizei n, GLuint* ids);
...
Android OpenGL ES库有三个:
但是在实际使用中发现:libGLESv2.so中已经支持了GLES3.0.
所以我们只要加载libGLESv2.so就可以了。