在android中,java层需要创建surface,
class MobileViewGLES extends GLSurfaceView implements Callback
{
public void surfaceCreated(SurfaceHolder holder)
{
Log.e("MobileViewGLES", "surfaceCreated");
//new Thread(this).start();
initRenderGLES( getHolder().getSurface() );
}
public void surfaceChanged(SurfaceHolder holder, int format, int width, int height)
{
Log.e("MobileViewGLES", "surfaceChanged");
}
public void surfaceDestroyed(SurfaceHolder holder)
{
Log.e("MobileViewGLES", "surfaceDestroyed");
termRenderGLES();
}
public native void initRenderGLES( Surface surface );
public native void termRenderGLES();
}
initRenderGLES是Native函数,在c++层实现,该函数主要创建gles环境,绘制的surface和display,实现函数如下:
static void MobileViewGLES_InitRenderGLES( JNIEnv *env, jobject thiz, jobject surface )
{
gANativeWindow = ANativeWindow_fromSurface( env, surface );
GlesInitDisplay();
CreateGlesEnv();
GlesEnvChanged( gWidth, gHeight );
SetDrawOffScreen( false );
//GlesDrawFrame();
//GlesTermDisplay();
return;
}
GlesInitDisplay()如下:
int GlesInitDisplay()
{
const EGLint attribs[] =
{
EGL_SURFACE_TYPE,
EGL_WINDOW_BIT,
EGL_BLUE_SIZE, 8,
EGL_GREEN_SIZE, 8,
EGL_RED_SIZE, 8,
EGL_NONE
};
EGLConfig config;
EGLint numConfigs;
EGLint format;
EGLint width;
EGLint height;
EGLint contextAtt[] = { EGL_CONTEXT_CLIENT_VERSION, 2, EGL_NONE, EGL_NONE };
gDisplay = eglGetDisplay( EGL_DEFAULT_DISPLAY );
eglInitialize( gDisplay, 0, 0 );
eglChooseConfig( gDisplay, attribs, &config, 1, &numConfigs );
eglGetConfigAttrib( gDisplay, config, EGL_NATIVE_VISUAL_ID, &format );
ANativeWindow_setBuffersGeometry( gANativeWindow, 0, 0, format);
gSurface = eglCreateWindowSurface( gDisplay, config, gANativeWindow, NULL);
gContext = eglCreateContext( gDisplay, config, EGL_NO_CONTEXT, contextAtt);
if (eglMakeCurrent( gDisplay, gSurface, gSurface, gContext) == EGL_FALSE)
{
LOGE("Unable to eglMakeCurrent");
return -1;
}
eglQuerySurface( gDisplay, gSurface, EGL_WIDTH, &width );
eglQuerySurface( gDisplay, gSurface, EGL_HEIGHT, &height );
return 0;
}
GLint CreateGlesEnv( )
{
static char vShaderStr[] =
"uniform mat4 u_TransMatrix; \n"
"attribute vec4 a_position; \n"
"attribute vec2 a_texCoord; \n"
"varying vec2 v_texCoord; \n"
"void main() \n"
"{ \n"
" gl_Position = u_TransMatrix * a_position; \n"
" v_texCoord = a_texCoord; \n"
"} \n";
static char fShaderStr[] =
"precision mediump float; \n"
"varying vec2 v_texCoord; \n"
"uniform sampler2D s_ImgTexture; \n"
"uniform int specColorFlag; \n"
"uniform vec4 specColor; \n"
"void main() \n"
"{ \n"
//" gl_FragColor = texture2D( s_ImgTexture, v_texCoord );\n"
" if (specColorFlag == 0) \n"
" {gl_FragColor = texture2D( s_ImgTexture, v_texCoord );} \n"
" else {gl_FragColor = specColor;} \n"
"} \n";
//esOrtho(&gOrthographic, -100, 100, -100, 100, 5.0f, -5.0f );
GLuint vertexShader;
GLuint fragmentShader;
GLuint programObject;
GLint linked;
// Load the vertex/fragment shaders
vertexShader = esLoadShader ( GL_VERTEX_SHADER, vShaderStr );
if ( vertexShader == 0 )
return 0;
fragmentShader = esLoadShader ( GL_FRAGMENT_SHADER, fShaderStr );
if ( fragmentShader == 0 )
{
glDeleteShader( vertexShader );
return 0;
}
gProObject = glCreateProgram ( );
glAttachShader ( gProObject, vertexShader );
glAttachShader ( gProObject, fragmentShader );
// Link the program
glLinkProgram ( gProObject );
// Check the link status
glGetProgramiv ( gProObject, GL_LINK_STATUS, &linked );
if ( !linked )
{
GLint infoLen = 0;
glGetProgramiv ( gProObject, GL_INFO_LOG_LENGTH, &infoLen );
if ( infoLen > 1 )
{
char* infoLog = (char *)malloc (sizeof(char) * infoLen );
glGetProgramInfoLog ( gProObject, infoLen, NULL, infoLog );
free ( infoLog );
}
glDeleteProgram ( gProObject );
return 0;
}
// Free up no longer needed shader resources
glDeleteShader ( vertexShader );
glDeleteShader ( fragmentShader );
gShaderPosition = glGetAttribLocation ( gProObject, "a_position" );
gShaderTexCoord = glGetAttribLocation ( gProObject, "a_texCoord" );
gvpMatrix = glGetUniformLocation( gProObject, "u_TransMatrix" );
gShaderImgTexture = glGetUniformLocation ( gProObject, "s_ImgTexture" );
gColorFlag = glGetUniformLocation( gProObject, "specColorFlag" );
gColorLoc = glGetUniformLocation( gProObject, "specColor" );
//glEnable (GL_BLEND);
//glBlendFunc (GL_SRC_ALPHA, GL_ONE_MINUS_SRC_COLOR);
glGenTextures(1, &gMainTexture );
glGenTextures(1, &gTextureTmp);
GlesBindOffScreen();
glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
glBindTexture(GL_TEXTURE_2D, gTextureTmp);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE );
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE );
glTexImage2D(GL_TEXTURE_2D,
0,
GL_RGBA,
gWidth,
gHeight,
0,
GL_RGBA,
GL_UNSIGNED_BYTE,
NULL );
return gProObject;
}
void GlesEnvChanged( int width, int height )
{
gWidthd2 = width / 2;
gHeightd2 = height / 2;
esMatrixLoadIdentity( &gOrthographic );
//esOrtho(&gOrthographic, 0, mWidth, -mHeight, 0, 5.0f, -5.0f );
esOrtho(&gOrthographic, -gWidthd2, gWidthd2, -gHeightd2, gHeightd2, 5.0f, -5.0f );
ESMatrix modelview;
esMatrixLoadIdentity( &gMatrix );
esMatrixLoadIdentity( &modelview );
esMatrixMultiply( &gMatrix, &modelview, &gOrthographic );
glViewport(0, 0, width, height);
}
void SetDrawOffScreen(bool bOffScreen )
{
if ( bOffScreen )
{
glBindFramebuffer(GL_FRAMEBUFFER, gFrameBuffer);
}
else
{
glBindFramebuffer(GL_FRAMEBUFFER, 0);
}
}
通过上面步骤,gles环境创建完成,下面就是绘制
case XWM_REPAINT:
{
if( eglMakeCurrent( gDisplay, gSurface, gSurface, gContext) == EGL_FALSE )
{
LOGWHEREMSG("MakeCurrent Error");
break;
}
LOGWHEREMSG( "XWM_REPAINT" );
XRect clip(m_clip);
glClearColor( 0.0f, 0.0f, 0.0f, 1.0f );
glBindFramebuffer(GL_FRAMEBUFFER, gFrameBuffer);
bool b = Paint(m_draw);
if( b )
{
glClearColor( 0.0f, 0.0f, 0.0f, 1.0f );
glBindFramebuffer(GL_FRAMEBUFFER, 0);
GlesPaint( gMainTexture );
FlushBuffer();
LOGWHEREMSG( "XWM_REPAINT" );
}
else
{
InvalidateRect(clip);
}
break;
}
绘制过程中,glBindFramebuffer(GL_FRAMEBUFFER, gFrameBuffer)设置绘制在离屏缓存区上, 而glBindFramebuffer(GL_FRAMEBUFFER, 0)则绘制在屏幕上
最后,在结束时通过调用termRenderGLES()函数,销毁surface,函数实现如下:
int GlesTermDisplay()
{
if( gDisplay != EGL_NO_DISPLAY )
{
eglMakeCurrent( gDisplay, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT );
if( gContext != EGL_NO_CONTEXT )
{
eglDestroyContext( gDisplay, gContext );
}
if( gSurface != EGL_NO_SURFACE )
{
eglDestroySurface( gDisplay, gDisplay );
}
eglTerminate( gDisplay );
}
}