add a pure x11 + egl simple demo

This commit is contained in:
uziel 2024-10-24 07:05:42 +00:00
parent 4e271b7943
commit a6e5e145e3
3 changed files with 470 additions and 2 deletions

View File

@ -22,7 +22,7 @@ include_directories(
link_directories( link_directories(
"/usr/lib" "/usr/lib"
"/usr/local/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) add_executable(SimpleEs src/simple-es2.c)
# #

461
src/triangle-es2-x11.c Normal file
View File

@ -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 <stdio.h>
#include <stdlib.h>
#include <fcntl.h>
#include <assert.h>
#include <math.h>
#include <stdbool.h>
#include <threads.h>
#include <unistd.h>
#include <sys/ioctl.h>
#include <sys/time.h>
#include <signal.h>
#include "GLES2/gl2.h"
#include "GLES2/gl2ext.h"
#include "EGL/egl.h"
#include "EGL/eglext.h"
#include <libdrm/drm.h>
#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;
}

View File

@ -26,7 +26,7 @@
#include "EGL/egl.h" #include "EGL/egl.h"
#include "EGL/eglext.h" #include "EGL/eglext.h"
#define XORG_SHOW // #define XORG_SHOW
#include <libdrm/drm.h> #include <libdrm/drm.h>