From a6e5e145e37b9ae6cbf9e3da996f01a4542e3835 Mon Sep 17 00:00:00 2001 From: uziel Date: Thu, 24 Oct 2024 07:05:42 +0000 Subject: [PATCH] add a pure x11 + egl simple demo --- CMakeLists.txt | 9 +- src/triangle-es2-x11.c | 461 +++++++++++++++++++++++++++++++++++++++++ src/triangle-es2.c | 2 +- 3 files changed, 470 insertions(+), 2 deletions(-) create mode 100644 src/triangle-es2-x11.c diff --git a/CMakeLists.txt b/CMakeLists.txt index 689768e..a407f11 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -22,7 +22,7 @@ include_directories( link_directories( "/usr/lib" "/usr/local/lib" - "/usr/lib/mali-g5x/" + /lib/aarch64-linux-gnu/mali ) @@ -70,6 +70,13 @@ target_link_libraries(TriangleEsDemo ) +add_executable(TriangleEsX11Demo src/triangle-es2-x11.c) +target_link_libraries(TriangleEsX11Demo + ${DEP_LIBS} + X11 + ) + + add_executable(SimpleEs src/simple-es2.c) # 查找对应的第三方库 diff --git a/src/triangle-es2-x11.c b/src/triangle-es2-x11.c new file mode 100644 index 0000000..24b9c7b --- /dev/null +++ b/src/triangle-es2-x11.c @@ -0,0 +1,461 @@ +/* + * This code was created by Jeff Molofee '99 + * (ported to Linux by Ti Leggett '01) + * (ported to i.mx51, i.mx31 and x11 by Freescale '10) + * If you've found this code useful, please let him know. + * + * Visit Jeff at http://nehe.gamedev.net/ + * + */ +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +#include "GLES2/gl2.h" +#include "GLES2/gl2ext.h" + +#include "EGL/egl.h" +#include "EGL/eglext.h" + +#include +#include "X11/X.h" +#include "X11/Xatom.h" + +Display *x_display; +Window win; + + +int g_stop; + +#define USE_FORMAT 0x34325258 + +EGLDisplay egldisplay; +EGLConfig eglconfig; +EGLSurface eglsurface; +EGLContext eglcontext; + + +GLuint g_hShaderProgram = 0; +GLuint g_hModelViewMatrixLoc = 0; +GLuint g_hProjMatrixLoc = 0; +GLuint g_hVertexLoc = 0; +GLuint g_hColorLoc = 1; +GLuint g_hVColor = 0; + +#define ASSERT_EQ(exp1, exp2) do { auto e1 = (exp1);auto e2 = (exp2);\ + if((e1) != (e2)) { \ + printf("assert value: %p, %p\n", e1, e2); \ + __assert_fail (#exp1 "==" #exp2, __FILE__, __LINE__, __ASSERT_FUNCTION); \ +}}while(0) + + +//-------------------------------------------------------------------------------------- +// Name: g_strVertexShader / g_strFragmentShader +// Desc: The vertex and fragment shader programs +//-------------------------------------------------------------------------------------- +const char* g_strVertexShader = +"uniform mat4 g_matModelView; \n" +"uniform mat4 g_matProj; \n" +" \n" +"attribute vec4 g_vPosition; \n" +"attribute vec3 g_vColor; \n" +" \n" +"varying vec3 g_vVSColor; \n" +" \n" +"void main() \n" +"{ \n" +" vec4 vPositionES = g_matModelView * g_vPosition; \n" +" gl_Position = g_matProj * vPositionES; \n" +" g_vVSColor = g_vColor; \n" +"} \n"; + + +const char* g_strFragmentShader = +"#ifdef GL_FRAGMENT_PRECISION_HIGH \n" +" precision highp float; \n" +"#else \n" +" precision mediump float; \n" +"#endif \n" +" \n" +"varying vec3 g_vVSColor; \n" +" \n" +"void main() \n" +"{ \n" +" gl_FragColor = vec4( g_vVSColor, 1.0 ); \n" +"} \n"; + + +float matModelView[16] = {0}; +float matProj[16] = {0}; +float color[4] = {0, 0, 0, 0}; + +// Define vertice for a 4-sided pyramid +float VertexPositions[] = +{ + 0.0f,1.0f, 0.0f, + -1.0f,-1.0f, 0.0f, + +1.0f,-1.0f, 0.0f, + 1.0f, 1.0f, 0.0f, + -1.0f,1.0f, 0.0f, + 1.0f, -1.0, 0.0f +}; + +void render(float w, float h, unsigned int framenum) +{ + + // Clear the colorbuffer and depth-buffer + glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT ); + glViewport(0, 0, w, h); +#if 1 + // Build a perspective projection matrix + matProj[ 0] = cosf( 0.5f ) / sinf( 0.5f ); + matProj[ 5] = matProj[0] * (w/h) ; + matProj[10] = -( 10.0f ) / ( 9.0f ); + matProj[11] = -1.0f; + matProj[14] = -( 10.0f ) / ( 9.0f ); + + glViewport(0, 0, w, h); + + float zTransDelta = sinf((framenum%200) /200.0 * M_PI); + + // Rotate and translate the model view matrix + matModelView[ 0] = 1.0f; + matModelView[ 2] = 0.1f; + matModelView[ 5] = 1.0f; + matModelView[ 8] = 0.0f; + matModelView[10] = 0.0f; + matModelView[14] = -5.0f + zTransDelta;//translation Z + matModelView[15] = 1.0f; + + color[0] = sinf(((framenum%400) /400.0) * M_PI); + // color[1] = sinf(((framenum%300) /300.0) * M_PI); + // color[2] = sinf(((framenum%200) /200.0) * M_PI); + // color[3] = sinf((framenum%500) /500.0 * M_PI); + + glUniformMatrix4fv( g_hModelViewMatrixLoc, 1, 0, matModelView ); + glUniformMatrix4fv( g_hProjMatrixLoc, 1, 0, matProj ); + glVertexAttrib4fv(g_hVColor, color); + + // Bind the vertex attributes + glVertexAttribPointer( g_hVertexLoc, 3, GL_FLOAT, 0, 0, VertexPositions ); + glEnableVertexAttribArray( g_hVertexLoc ); + + glDrawArrays( GL_TRIANGLES, 0, 3 ); + + // Cleanup + glDisableVertexAttribArray( g_hVertexLoc ); +#endif +} + + +void print_glinfo() { + printf("OpenGL information:\n"); + printf(" version: \"%s\"\n", glGetString(GL_VERSION)); + printf(" shading language version: \"%s\"\n", glGetString(GL_SHADING_LANGUAGE_VERSION)); + printf(" vendor: \"%s\"\n", glGetString(GL_VENDOR)); + printf(" renderer: \"%s\"\n", glGetString(GL_RENDERER)); + // printf(" extensions: \"%s\"\n", glGetString(GL_EXTENSIONS)); + printf("===================================\n"); +} + +#define PRINT_CONFIG(display, config, type) \ +{ int _tmp; eglGetConfigAttrib(display, config, type, &_tmp); printf("config val " #type ":0x%x\n", _tmp);} + + +static int matchConfigToVisual(EGLDisplay display, EGLint visualId, EGLConfig* configs, int count) +{ + EGLint id = 0; + EGLint suf_type; + int retId = -1; + for (int i = 0; i < count; ++i) + { + + if (!eglGetConfigAttrib(display, configs[i], EGL_NATIVE_VISUAL_ID, &id)) + continue; + + // PRINT_CONFIG(display, configs[i], EGL_SURFACE_TYPE); + // PRINT_CONFIG(display, configs[i], EGL_MAX_SWAP_INTERVAL); + // PRINT_CONFIG(display, configs[i], EGL_MIN_SWAP_INTERVAL); + // printf("visualid: 0x%x, str:%.*s\n=====================\n", id, 4, &id); + if (id == visualId) { + retId = i; + break; + } + + } + return retId; +} + +int init(void) +{ + EGLint count = 0; + EGLint numConfigs = 0; + + x_display = XOpenDisplay (NULL); + if (!x_display) { + printf("XOpenDisplay failed!\n"); + return 1; + } + Window root = DefaultRootWindow( x_display ); + + XSetWindowAttributes swa; + swa.event_mask = ExposureMask | PointerMotionMask | KeyPressMask | StructureNotifyMask; + swa.override_redirect = True; + + // 创建窗口 + win = XCreateWindow ( // create a window with the provided parameters + x_display, root, + 0, 0, 1000, 1000, 0, + CopyFromParent, InputOutput, + CopyFromParent, + CWEventMask | CWOverrideRedirect, + &swa ); + + XMapWindow ( x_display , win); // make the window visible on the screen + XStoreName ( x_display , win , "GL test"); // give the window a name + + XSelectInput(x_display, win, StructureNotifyMask); + egldisplay = eglGetDisplay((EGLNativeDisplayType)x_display); + + int majo, mino; + eglInitialize(egldisplay, &majo, &mino); + printf("egl ver: %d.%d\n", majo, mino); + ASSERT_EQ(eglGetError(), EGL_SUCCESS); + eglBindAPI(EGL_OPENGL_ES_API); + + + static const EGLint s_configAttribs[] = + { + EGL_GREEN_SIZE, 8, + EGL_BLUE_SIZE, 8, + EGL_RED_SIZE, 8, + EGL_RENDERABLE_TYPE, EGL_OPENGL_ES3_BIT, + EGL_SURFACE_TYPE, EGL_WINDOW_BIT, + EGL_NONE + }; + + eglGetConfigs(egldisplay, NULL, 0, &count); + EGLConfig* configs = malloc(count * sizeof(EGLConfig)); + + eglChooseConfig(egldisplay, s_configAttribs, configs, count, &numConfigs); + ASSERT_EQ(eglGetError(), EGL_SUCCESS); + printf("configs num: %d\n", numConfigs); + + int indexCfg = matchConfigToVisual(egldisplay, USE_FORMAT, configs, numConfigs); + printf("configs indexCfg: %d\n", indexCfg); + if (indexCfg < 0) { + indexCfg = 1; + } + + eglconfig = configs[indexCfg]; + + EGLint ContextAttribList[] = { EGL_CONTEXT_CLIENT_VERSION, 3, EGL_NONE }; + eglcontext = eglCreateContext( egldisplay, eglconfig, EGL_NO_CONTEXT, ContextAttribList ); + ASSERT_EQ(eglGetError(), EGL_SUCCESS); + + + EGLint win_attrlist[] = { + EGL_NONE, + }; + // 使用窗口区域创建绘制平面 + eglsurface = eglCreateWindowSurface(egldisplay, eglconfig, (EGLNativeWindowType)(win), win_attrlist); + + ASSERT_EQ(eglGetError(), EGL_SUCCESS); + if (eglsurface == EGL_NO_SURFACE) { + int e = eglGetError(); + printf("EGL_NO_SURFACE ! error_num: %p\n", e); + return -1; + } + + eglMakeCurrent(egldisplay, eglsurface, eglsurface, eglcontext); + ASSERT_EQ(eglGetError(), EGL_SUCCESS); + + // disable refresh rate limit + if (!eglSwapInterval || !eglSwapInterval(egldisplay, 0)) { + printf("Failed to set swap interval. Results may be bounded above by refresh rate.\n"); + } + + print_glinfo(); + + { + // Compile the shaders + GLuint hVertexShader = glCreateShader( GL_VERTEX_SHADER ); + glShaderSource( hVertexShader, 1, &g_strVertexShader, NULL ); + glCompileShader( hVertexShader ); + + // Check for compile success + GLint nCompileResult = 0; + glGetShaderiv( hVertexShader, GL_COMPILE_STATUS, &nCompileResult ); + if( 0 == nCompileResult ) + { + char strLog[1024]; + GLint nLength; + glGetShaderInfoLog( hVertexShader, 1024, &nLength, strLog ); + return 0; + } + + GLuint hFragmentShader = glCreateShader( GL_FRAGMENT_SHADER ); + glShaderSource( hFragmentShader, 1, &g_strFragmentShader, NULL ); + glCompileShader( hFragmentShader ); + + // Check for compile success + glGetShaderiv( hFragmentShader, GL_COMPILE_STATUS, &nCompileResult ); + if( 0 == nCompileResult ) + { + char strLog[1024]; + GLint nLength; + glGetShaderInfoLog( hFragmentShader, 1024, &nLength, strLog ); + return 0; + } + + // Attach the individual shaders to the common shader program + g_hShaderProgram = glCreateProgram(); + glAttachShader( g_hShaderProgram, hVertexShader ); + glAttachShader( g_hShaderProgram, hFragmentShader ); + + // Init attributes BEFORE linking + glBindAttribLocation( g_hShaderProgram, g_hVertexLoc, "g_vPosition" ); + + // Link the vertex shader and fragment shader together + glLinkProgram( g_hShaderProgram ); + + // Check for link success + GLint nLinkResult = 0; + glGetProgramiv( g_hShaderProgram, GL_LINK_STATUS, &nLinkResult ); + if( 0 == nLinkResult ) + { + char strLog[1024]; + GLint nLength; + glGetProgramInfoLog( g_hShaderProgram, 1024, &nLength, strLog ); + return 0; + } + + // Get uniform locations + g_hModelViewMatrixLoc = glGetUniformLocation( g_hShaderProgram, "g_matModelView" ); + g_hProjMatrixLoc = glGetUniformLocation( g_hShaderProgram, "g_matProj" ); + g_hVColor = glGetAttribLocation( g_hShaderProgram, "g_vColor" ); + + + glDeleteShader( hVertexShader ); + glDeleteShader( hFragmentShader ); + + // Set the shader program + glUseProgram( g_hShaderProgram ); + + // Clear the colorbuffer and depth-buffer + glClearColor( 0.0f, 0.0f, 0.5f, 1.0f ); + + // Set some state + glEnable( GL_DEPTH_TEST ); + + } + + return 0; +} + +void resize(int w, int h) +{ + // Build a perspective projection matrix + matProj[ 0] = cosf( 0.5f ) / sinf( 0.5f ); + matProj[ 5] = matProj[0] * (w/h) ; + matProj[10] = -( 10.0f ) / ( 9.0f ); + matProj[11] = -1.0f; + matProj[14] = -( 10.0f ) / ( 9.0f ); + + glViewport(0, 0, w, h); +} + +void deinit(void) +{ + printf("Cleaning up...\n"); + eglMakeCurrent(egldisplay, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT); + assert(eglGetError() == EGL_SUCCESS); + eglDestroyContext(egldisplay, eglcontext); + eglDestroySurface(egldisplay, eglsurface); + eglTerminate(egldisplay); + assert(eglGetError() == EGL_SUCCESS); + eglReleaseThread(); +} + +int event_handle(void* arg) { + printf("start event loop\n"); + while (1) { + XEvent xevent; + // XWindowEvent(x_display, win, StructureNotifyMask, &xevent); + XNextEvent(x_display, &xevent); + if (xevent.type == DestroyNotify) { + printf("DestroyNotify \n"); + break; + } + } + return 0; +} + +void handle_sig(int sig) { + printf("recieve sig: %d\n", sig); + g_stop = 1; +} + +void init_signal() { + signal(SIGABRT, handle_sig); + signal(SIGHUP, handle_sig); + signal(SIGINT, handle_sig); +} + +long GetNowMillis() { + struct timeval t; + gettimeofday(&t, NULL); + return t.tv_sec*1000 + t.tv_usec/1000; +} + +int main (void) +{ + EGLint width = 600; + EGLint height = 600; + int ret; + ret = init(); + if (ret) { + return ret; + } + init_signal(); + + eglQuerySurface(egldisplay, eglsurface, EGL_WIDTH, &width); + eglQuerySurface(egldisplay, eglsurface, EGL_HEIGHT, &height); + + printf("w=%d h=%d\n",width,height); + + thrd_t thr; + thrd_create(&thr, event_handle, NULL); + + long lastTime = GetNowMillis(); + unsigned int framenum = 0; + while (!g_stop) { + render(width, height, framenum); + eglSwapBuffers(egldisplay, eglsurface); + + //usleep(1*1000); + framenum++; + + if (!(framenum%100)) { + long now = GetNowMillis(); + printf("frame num:%d, fps: %.1f\n", framenum, 100/((now-lastTime)/1000.0)); + lastTime = now; + } + if (framenum > 100000) { + break; + } + } + + deinit(); + + return 0; +} diff --git a/src/triangle-es2.c b/src/triangle-es2.c index 6e97481..ad81f5c 100644 --- a/src/triangle-es2.c +++ b/src/triangle-es2.c @@ -26,7 +26,7 @@ #include "EGL/egl.h" #include "EGL/eglext.h" -#define XORG_SHOW +// #define XORG_SHOW #include