在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(); }
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 ); } }