검색해서 발견한 것인데 표준 path의 위치에 libEGL과 libGLESv2들의 공유 object가 없어서 아래와 같이 symbolic link로 연결해 보았습니다.
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의 header가 없기때문에, Khronos OpenGL ES Registry(http://www.khronos.org/registry/gles/ )로부터 다운로드 합니다. 다운로드 한 파일들은 바로 프로그램과 같은 장소에 디렉토리 구성이 있는 것처럼 배치했습니다.사용한 프로그램은 이렇습니다.
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include <string.h>
#include <X11/Xlib.h>
#include <X11/Xutil.h>
#include <X11/Xatom.h>
#include "EGL/egl.h"
#include "GLES2/gl2.h"
#include <sys/time.h>
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/AXIGL_VENDOR: NVIDIA CorporationGL_VERSION: OpenGL ES 3.0 19.3EGL_VENDOR : NVIDIAEGL_VERSION: 1.4EGL_CLIENT_APIS : OpenGL_ES OpenGLFPS: 262.60FPS: 177.60FPS: 155.40FPS: 167.00FPS: 169.40FPS: 257.00FPS: 269.20FPS: 177.00
이 버전에서는 이미 OpenGL ES 3.0의 Context로 되어 있는 것 같습니다.GLESv2의 라이브러리를 link해서, 프로그램 중에는 ES 2.0을 지정할 예정이었지만, 좀 이상한 상태입니다.
Congratulations @kimhoe! You received a personal award!
You can view your badges on your Steem Board and compare to others on the Steem Ranking
Do not miss the last post from @steemitboard:
Vote for @Steemitboard as a witness to get one more award and increased upvotes!
Downvoting a post can decrease pending rewards and make it less visible. Common reasons:
Submit
Downvoting a post can decrease pending rewards and make it less visible. Common reasons:
Submit
Downvoting a post can decrease pending rewards and make it less visible. Common reasons:
Submit