#include #include #include #include #include #include #include #include #include #include #include #include using namespace std; using namespace glm; class GlesContext { public: GlesContext( NativeDisplayType aNatDisplay, NativeWindowType aNatWindow, EGLint aVersion = 1 ) { if( ( mDisplay = eglGetDisplay( aNatDisplay ) ) == EGL_NO_DISPLAY ) throw runtime_error( "eglGetDisplay(): no display" ); EGLint maj = 0, min = 0; if( eglInitialize( mDisplay, &maj, &min ) != EGL_TRUE ) throw runtime_error( "eglInitialize():" + eglGetErrorString() ); EGLint rtype = 0; #ifdef EGL_OPENGL_ES_BIT if( 1 == aVersion ) rtype = EGL_OPENGL_ES_BIT; #endif #ifdef EGL_OPENGL_ES2_BIT if( 2 == aVersion ) rtype = EGL_OPENGL_ES2_BIT; #endif const EGLint cfgAttrs[] = { EGL_RED_SIZE, 5, EGL_GREEN_SIZE, 5, EGL_BLUE_SIZE, 5, EGL_DEPTH_SIZE, 16, EGL_RENDERABLE_TYPE, rtype, EGL_NONE }; EGLint numConfigs = 0; if( eglChooseConfig( mDisplay, cfgAttrs, &mConfig, 1, &numConfigs ) != EGL_TRUE ) throw runtime_error( "eglChooseConfig(): " + eglGetErrorString() ); if( numConfigs == 0 ) throw runtime_error( "eglChooseConfig(): no matching config" ); if( ( mSurface = eglCreateWindowSurface( mDisplay, mConfig, aNatWindow, NULL ) ) == EGL_NO_SURFACE ) throw runtime_error( "eglCreateWindowSurface(): " + eglGetErrorString() ); if( eglBindAPI( EGL_OPENGL_ES_API ) != EGL_TRUE ) throw runtime_error( "eglBindAPI(): " + eglGetErrorString() ); EGLint ctxAttrs[] = { EGL_CONTEXT_CLIENT_VERSION, aVersion, EGL_NONE }; if( ( mContext = eglCreateContext( mDisplay, mConfig, EGL_NO_CONTEXT, ctxAttrs ) ) == EGL_NO_CONTEXT ) throw runtime_error( "eglCreateContext(): " + eglGetErrorString() ); if( !MakeCurrent() ) throw runtime_error( "eglMakeCurrent(): " + eglGetErrorString() ); } ~GlesContext() { MakeCurrent( true ); eglDestroySurface( mDisplay, mSurface ); eglDestroyContext( mDisplay, mContext ); eglTerminate( mDisplay ); } bool MakeCurrent( const bool aRelease = false ) { EGLBoolean err = eglMakeCurrent ( mDisplay, ( aRelease ? EGL_NO_SURFACE : mSurface ), ( aRelease ? EGL_NO_SURFACE : mSurface ), ( aRelease ? EGL_NO_CONTEXT : mContext ) ); return ( EGL_TRUE == err ); } bool SwapBuffers() { EGLBoolean err = eglSwapBuffers( mDisplay, mSurface ); return ( EGL_TRUE == err ); } private: static std::string eglGetErrorString() { EGLint err = eglGetError(); if( err == EGL_NOT_INITIALIZED ) return "EGL_NOT_INITIALIZED"; if( err == EGL_BAD_ACCESS ) return "EGL_BAD_ACCESS"; if( err == EGL_BAD_ALLOC ) return "EGL_BAD_ALLOC"; if( err == EGL_BAD_ATTRIBUTE ) return "EGL_BAD_ATTRIBUTE"; if( err == EGL_BAD_CONTEXT ) return "EGL_BAD_CONTEXT"; if( err == EGL_BAD_CONFIG ) return "EGL_BAD_CONFIG"; if( err == EGL_BAD_CURRENT_SURFACE ) return "EGL_BAD_CURRENT_SURFACE"; if( err == EGL_BAD_DISPLAY ) return "EGL_BAD_DISPLAY"; if( err == EGL_BAD_SURFACE ) return "EGL_BAD_SURFACE"; if( err == EGL_BAD_MATCH ) return "EGL_BAD_MATCH"; if( err == EGL_BAD_PARAMETER ) return "EGL_BAD_PARAMETER"; if( err == EGL_BAD_NATIVE_PIXMAP ) return "EGL_BAD_NATIVE_PIXMAP"; if( err == EGL_BAD_NATIVE_WINDOW ) return "EGL_BAD_NATIVE_WINDOW"; if( err == EGL_CONTEXT_LOST ) return "EGL_CONTEXT_LOST"; return ""; } public: EGLDisplay mDisplay; EGLConfig mConfig; EGLSurface mSurface; EGLContext mContext; }; void CheckStatus( GLuint obj ) { GLint status = GL_FALSE; if( glIsShader(obj) ) glGetShaderiv( obj, GL_COMPILE_STATUS, &status ); if( glIsProgram(obj) ) glGetProgramiv( obj, GL_LINK_STATUS, &status ); if( status == GL_TRUE ) return; char log[32768] = { 0 }; if( glIsShader(obj) ) glGetShaderInfoLog( obj, sizeof(log), NULL, log ); if( glIsProgram(obj) ) glGetProgramInfoLog( obj, sizeof(log), NULL, log ); std::cerr << log << std::endl; exit( -1 ); } void AttachShader( GLuint program, GLenum type, const char* src ) { GLuint shader = glCreateShader( type ); glShaderSource( shader, 1, &src, NULL ); glCompileShader( shader ); CheckStatus( shader ); glAttachShader( program, shader ); glDeleteShader( shader ); } GLuint LoadShader( const char* vert, const char* frag ) { GLuint prog = glCreateProgram(); if( vert ) AttachShader( prog, GL_VERTEX_SHADER, vert ); if( frag ) AttachShader( prog, GL_FRAGMENT_SHADER, frag ); glLinkProgram( prog ); CheckStatus( prog ); return prog; } #define GLSL( version, shader ) "#version " #version "\n" #shader const GLchar* vertProg = GLSL ( 100, uniform mat4 uProj; uniform mat4 uView; attribute vec4 aPosn; void main() { gl_Position = uProj * uView * aPosn; } ); const GLchar* fragProg = GLSL ( 100, precision highp float; const float size = 3.0; void main() { float xpos = floor( gl_FragCoord.x / size ); float ypos = floor( gl_FragCoord.y / size ); float col = mod( xpos + mod( ypos, 2.0 ), 2.0 ); gl_FragColor = vec4( col ); } ); int main( int argc, char* argv[] ) { SDL_Init( SDL_INIT_EVERYTHING ); SDL_Surface* display = SDL_SetVideoMode( 640, 480, 32, SDL_SWSURFACE ); // Get the SDL window handle SDL_SysWMinfo sysInfo; SDL_VERSION( &sysInfo.version ); if( SDL_GetWMInfo( &sysInfo ) <= 0 ) return -1; cout << "Creating context..." << endl; GlesContext* ctx = NULL; try { // X11 sysInfo.info.x11.lock_func(); ctx = new GlesContext( sysInfo.info.x11.display, sysInfo.info.x11.window, 2 ); sysInfo.info.x11.unlock_func(); } catch( std::exception& e ) { cerr << "Exception: " << e.what() << endl; return -1; } cout << "Context created!" << endl; cout << "Loading shader..." << endl; GLuint prog = LoadShader( vertProg, fragProg ); cout << "Shader loaded!" << endl; glEnable( GL_DEPTH_TEST ); // create geometry vector< vec2 > verts; verts.push_back( vec2( -4, -4 ) ); verts.push_back( vec2( 4, -4 ) ); verts.push_back( vec2( 4, 4 ) ); verts.push_back( vec2( 4, 4 ) ); verts.push_back( vec2( -4, 4 ) ); verts.push_back( vec2( -4, -4 ) ); bool running = true; while( running ) { // handle all pending events SDL_Event event; while( SDL_PollEvent(&event) ) { switch (event.type) { case SDL_QUIT: running = false; break; default: break; } } glClearColor( 0, 0, 0, 0 ); glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT ); glUseProgram( prog ); glm::mat4 proj = glm::ortho( -2.0f, 2.0f, -2.0f, 2.0f, -1.0f, 1.0f ); GLint u_proj = glGetUniformLocation( prog, "uProj" ); glUniformMatrix4fv( u_proj, 1, GL_FALSE, glm::value_ptr( proj ) ); glm::mat4 view = glm::mat4( 1.0f ); view = glm::rotate( view, (float)SDL_GetTicks() / 10.0f, glm::vec3( 0.0f, 0.0f, 1.0f ) ); GLint uView = glGetUniformLocation( prog, "uView" ); glUniformMatrix4fv( uView, 1, GL_FALSE, glm::value_ptr( view ) ); GLint aPosn = glGetAttribLocation( prog, "aPosn" ); glVertexAttribPointer( aPosn, 2, GL_FLOAT, GL_FALSE, sizeof( vec2 ), &verts[0] ); glEnableVertexAttribArray( aPosn ); glDrawArrays( GL_TRIANGLES, 0, verts.size() ); glDisableVertexAttribArray( aPosn ); ctx->SwapBuffers(); } delete ctx; SDL_Quit(); return 0; }