検索でライブラリは見つかるものの標準パスの位置にlibEGLやlibGLESv2らの共有オブジェクトがなかったので、下記のようにしてシンボリックリンクを張ってみました。
cd /usr/lib/arm-linux-gnueabihf sudo ln -s tegra-egl/libEGL.so.1 libEGL.so sudo ln -s tegra-egl/libGLESv2.so.2 libGLESv2.so
標準では EGLやGLES2のヘッダがないために、Khronos OpenGL ES Registry からダウンロードしてきます。ダウンロードしたファイルらはとりあえずプログラムと同じ場所にディレクトリ構成があうようにして配置しました。
使用したプログラムはこのようなものです。
#include#include #include #include #include #include #include #include "EGL/egl.h" #include "GLES2/gl2.h" #include static Display* xdisp; static Window window; EGLDisplay eglDisplay; EGLContext eglContext; EGLSurface eglSurface; static GLuint shaderProgram; void initializeEGL(); void terminateEGL(); void mainloop(); GLuint createShaderProgram(); int main() { xdisp = XOpenDisplay( NULL ); if( xdisp == NULL ) { return -1; } Window rootWin = DefaultRootWindow( xdisp ); int screen = DefaultScreen( xdisp ); unsigned long white = WhitePixel( xdisp, screen ); unsigned long black = BlackPixel( xdisp, screen ); window = XCreateSimpleWindow( xdisp, rootWin, 100, 100, 640, 480, 2, black, white ); XSelectInput( xdisp, window, KeyPressMask|ButtonPressMask|UnmapNotify ); Atom atom, atom2; atom = XInternAtom( xdisp, "WM_DELETE_WINDOW", False ); XSetWMProtocols( xdisp, window, &atom, 1 ); atom2 = XInternAtom( xdisp, "WM_PROTOCOLS", False ); XMapWindow( xdisp, window ); XFlush( xdisp ); initializeEGL(); shaderProgram = createShaderProgram(); XEvent evt; bool isFinish = false; int frameCount = 0; timeval t0, t1; gettimeofday( &t0, NULL ); const int countSecond = 5; do { while( XPending( xdisp ) ) { XNextEvent( xdisp, &evt ); switch( evt.type ) { case ClientMessage: if( evt.xclient.message_type == atom2 && evt.xclient.data.l[0] == atom ) { XFlush( xdisp ); isFinish = true; } break; case KeyPress: isFinish = true; break; } } mainloop(); frameCount++; gettimeofday( &t1, NULL ); if( t1.tv_sec * 1000000 + t1.tv_usec - t0.tv_sec * 1000000 - t0.tv_usec > countSecond * 1000000 ) { printf( "FPS: %.2f\n", frameCount / (float)countSecond ); gettimeofday( &t0, NULL ); frameCount = 0; } } while( !isFinish ); glDeleteProgram( shaderProgram ); terminateEGL(); XDestroyWindow( xdisp, window ); XCloseDisplay( xdisp ); return 0; } void initializeEGL() { eglDisplay = eglGetDisplay( (EGLNativeDisplayType) xdisp ); if( eglDisplay == EGL_NO_DISPLAY ) { fprintf( stderr, "NO EGL DISPLAY\n" ); return; } if( !eglInitialize( eglDisplay, NULL, NULL ) ) { fprintf( stderr, "Unable to initialize EGL\n" ); return; } EGLint attr[] = { EGL_RED_SIZE, 8, EGL_GREEN_SIZE, 8, EGL_BLUE_SIZE, 8, EGL_ALPHA_SIZE, 8, EGL_SURFACE_TYPE, EGL_WINDOW_BIT, EGL_RENDERABLE_TYPE, EGL_OPENGL_ES2_BIT, EGL_NONE, }; EGLConfig cfg; EGLint numConfigs = 0; if( !eglChooseConfig( eglDisplay, attr, &cfg, 1, &numConfigs )) { fprintf( stderr, "Failed to choose config.\n" ); return; } eglSurface =eglCreateWindowSurface( eglDisplay, cfg, window, NULL ); if( eglSurface == EGL_NO_SURFACE ) { return; } EGLint ctxAttr[] = { EGL_CONTEXT_CLIENT_VERSION, 2, EGL_NONE, }; eglContext = eglCreateContext( eglDisplay, cfg, EGL_NO_CONTEXT, ctxAttr ); if( eglContext == EGL_NO_CONTEXT ) { fprintf( stderr, "Unable to create EGL context. (%d).\n", eglGetError() ); return; } eglMakeCurrent( eglDisplay, eglSurface, eglSurface, eglContext ); printf( "GL_RENDERER: %s\n", (char*)glGetString( GL_RENDERER ) ); printf( "GL_VENDOR: %s\n", (char*)glGetString( GL_VENDOR ) ); printf( "GL_VERSION: %s\n", (char*)glGetString( GL_VERSION ) ); printf( "EGL_VENDOR : %s\n", eglQueryString( eglDisplay, EGL_VENDOR ) ); printf( "EGL_VERSION: %s\n", eglQueryString( eglDisplay, EGL_VERSION ) ); printf( "EGL_CLIENT_APIS : %s\n", eglQueryString( eglDisplay, EGL_CLIENT_APIS ) ); eglSwapInterval( eglDisplay, 0 ); } void terminateEGL() { eglDestroyContext( eglDisplay, eglContext ); eglDestroySurface( eglDisplay, eglSurface ); eglTerminate( eglDisplay ); } static GLchar srcVertexShader[] = "attribute vec4 position0;\n" "attribute vec4 color0;\n" "varying vec4 vsout_color0;\n" "uniform float theta;\n" "void main() {\n" " gl_Position = position0;\n" " gl_Position.x = position0.x * cos(theta) - position0.y * sin(theta);\n" " gl_Position.y = position0.x * sin(theta) + position0.y * cos(theta);\n" " vsout_color0 = color0;\n" "}"; static GLchar srcFragmentShader[] = "precision mediump float;\n" "varying vec4 vsout_color0;\n" "void main() {\n" " gl_FragColor = vsout_color0;\n" "}"; void checkCompiled( GLuint shader ) { GLint status; glGetShaderiv( shader, GL_COMPILE_STATUS, &status ); if( status != GL_TRUE ) { GLint length; glGetShaderiv( shader, GL_INFO_LOG_LENGTH, &length ); if( length ) { char* buf = (char*)malloc( length ); glGetShaderInfoLog( shader, length, NULL, buf ); fprintf( stderr, "CompiledLog: %s\n", buf ); free( buf ); } exit( EXIT_FAILURE ); } } GLuint createShaderProgram() { GLuint shaderVS = glCreateShader( GL_VERTEX_SHADER ); GLuint shaderFS = glCreateShader( GL_FRAGMENT_SHADER ); GLsizei length; GLchar* vsSources[] = { srcVertexShader, }; GLchar* fsSources[] = { srcFragmentShader, }; glShaderSource( shaderVS, 1, (GLchar**) &vsSources, NULL ); glCompileShader( shaderVS ); checkCompiled( shaderVS ); glShaderSource( shaderFS, 1, (GLchar**) &fsSources, NULL ); glCompileShader( shaderFS ); checkCompiled( shaderFS ); GLuint program; program = glCreateProgram(); glAttachShader( program, shaderVS ); glAttachShader( program, shaderFS ); glLinkProgram( program ); return program; } void mainloop() { static unsigned int count = 0; float v = sinf( count * 0.001f ) + 1; v *= 0.5f; glClearColor( 0.25f, 0.25f, v, 0.0f ); glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT ); glUseProgram( shaderProgram ); GLint locPos = glGetAttribLocation( shaderProgram, "position0" ); GLint locColor = glGetAttribLocation( shaderProgram, "color0" ); float vertices[] = { 0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, 1.0f, 1.0f, 0.0f, 0.0f, 1.0f, 0.0f, 1.0f, 1.0f, 0.5f, 0.5f, 0.0f, 1.0f, 1.0f, 0.0f, 1.0f, }; GLint stride = sizeof(float)*7; glVertexAttribPointer( locPos, 3, GL_FLOAT, false, stride, &vertices[0] ); glVertexAttribPointer( locColor, 4, GL_FLOAT, false, stride, &vertices[3] ); glEnableVertexAttribArray( locPos ); glEnableVertexAttribArray( locColor ); glUniform1f( glGetUniformLocation( shaderProgram, "theta" ), count*0.001f ); glDrawArrays( GL_TRIANGLES, 0, 3 ); eglSwapBuffers( eglDisplay, eglSurface ); count++; }
GL_RENDERER: GK20A/AXI GL_VENDOR: NVIDIA Corporation GL_VERSION: OpenGL ES 3.0 19.3 EGL_VENDOR : NVIDIA EGL_VERSION: 1.4 EGL_CLIENT_APIS : OpenGL_ES OpenGL FPS: 262.60 FPS: 177.60 FPS: 155.40 FPS: 167.00 FPS: 169.40 FPS: 257.00 FPS: 269.20 FPS: 177.00
このバージョンでは既にOpenGL ES 3.0 のコンテキストとなっているようです。
GLESv2のライブラリをリンクして、プログラム中では ES 2.0 を指定しているつもりでしたが、ちょっと奇妙な状態です。