This commit is contained in:
Uziel 2024-09-29 09:19:42 +00:00
commit 81b612465e
8 changed files with 1592 additions and 0 deletions

2
.gitignore vendored Normal file
View File

@ -0,0 +1,2 @@
.vscode/
build/

111
CMakeLists.txt Normal file
View File

@ -0,0 +1,111 @@
SET_PROPERTY(GLOBAL PROPERTY USE_FOLDERS ON)
CMAKE_MINIMUM_REQUIRED(VERSION 2.6)
#
PROJECT(Triangle-ES2)
#dubug -----------------------it's very import for Debug
set(CMAKE_BUILD_TYPE "Debug")
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -std=gnu99 -fPIC -pipe -g -O0 -Wall -W -D_REENTRANT -D__VXWORKS__")
#
#ADD_DEFINITIONS(-D_MWV207_OS_=106)
#ADD_DEFINITIONS(-DXORG_SHOW=1)
#
include_directories(
"/usr/local/include"
)
# LINUX
link_directories(
"/usr/lib"
"/usr/local/lib"
#"/usr/lib/mali-g5x/"
)
#
#include_directories( "/usr/lib/gcc/aarch64-linux-gnu/9/include" )
# *.h,
#file(GLOB_RECURSE JPG_Include "./jpgLib_prj/src/*.h")
# *.c,
#file(GLOB_RECURSE JPG_SRC "./jpgLib_prj/src/*.c")
# ,
set(Triangle_SRC src/triangle-es2.c)
#
source_group("src" FILES ${Triangle_SRC})
#
set(EXECUTABLE_OUTPUT_PATH ${PROJECT_SOURCE_DIR}/build/bin)
add_executable(TriangleEsDemo ${Triangle_SRC})
#
#find_library(OPENGL_LIBRARY GL "OpenGL library")
#find_library(GLU_LIBRARY GLU "GLU library" )
set(DEP_LIBS
dl
gbm
m
pthread
EGL
GLESv2
GL
OpenGL
#X11
)
#
target_link_libraries(TriangleEsDemo
${DEP_LIBS}
)
add_executable(SimpleEs src/simple-es2.c)
#
#find_library(OPENGL_LIBRARY GL "OpenGL library")
#find_library(GLU_LIBRARY GLU "GLU library" )
#
target_link_libraries(SimpleEs
${DEP_LIBS}
)
add_executable(color_test src/color_test.c)
target_link_libraries(color_test
dl
)
# # demo
# add_executable(demo src/demo.cpp)
# #
# target_link_libraries(demo
# -Wl,--start-group
# #stdc++
# glut
# dl
# m
# pthread
# X11
# EGL
# GLESv2
# OpenGL
# GL
# -Wl,--end-group)

10
Makefile Normal file
View File

@ -0,0 +1,10 @@
compile: build
cmake --build build
build:
mkdir build
cmake -B build
t: compile
sudo ./build/bin/SimpleEs

13
README.md Normal file
View File

@ -0,0 +1,13 @@
使用gbm实现opengles在drm上画图。
| Syntax | Description |
| ----------- | ----------- |
| color_test.c | 直接刷写fb的像素值 |
| simple-es2.c | 使用GBM + pbuffer离屏渲染并写入文件 |
| triangle-es2.c | 使用GBM + surface渲染opengles到屏幕 |
依赖
libgbm-dev, libopengles-dev

88
src/color_test.c Normal file
View File

@ -0,0 +1,88 @@
#include <stdio.h>
#include <unistd.h>
#include <linux/fb.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <sys/mman.h>
#include <sys/ioctl.h>
typedef unsigned int color_t; /* 根据实际情况修改此处为unsigned short是565的屏 */
static struct fb_var_screeninfo __g_vinfo; /* 显示信息 */
static void *__gp_frame; /* 虚拟屏幕首地址 */
int framebuffer_init(void) {
int fd = 0;
fd = open("/dev/fb0", O_RDWR);
if (fd == -1) {
perror("fail to open /dev/fb0\n");
return -1;
}
ioctl(fd, FBIOGET_VSCREENINFO, &__g_vinfo); /* 获取显示信息 */
printf("bits_per_pixel = %d\n", __g_vinfo.bits_per_pixel); /* 一个像素点对应的位数如果值为16则为565格式输出如果值为32则为888格式输出 */
printf("xres_virtual = %d\n", __g_vinfo.xres_virtual); /* 虚拟x轴像素点数 */
printf("yres_virtual = %d\n", __g_vinfo.yres_virtual); /* 虚拟y轴像素点数 */
printf("xres = %d\n", __g_vinfo.xres); /* x轴像素点数 */
printf("yres = %d\n", __g_vinfo.yres); /* y轴像素点数 */
__gp_frame = mmap(NULL, /* 映射区的开始地址为NULL表示由系统决定映射区的起始地址 */
__g_vinfo.xres_virtual * __g_vinfo.yres_virtual
* __g_vinfo.bits_per_pixel / 8, /* 映射区大小 */
PROT_WRITE | PROT_READ, /* 内存保护标志(可读可写) */
MAP_SHARED, /* 映射对象类型(与其他进程共享) */
fd, /* 有效的文件描述符 */
0); /* 被映射内容的偏移量 */
if (__gp_frame == NULL) {
perror("fail to mmap\n");
return -1;
}
return 0;
}
#define BYTE(data, loc) (((data)>> (loc*8))&0xFF)
void full_screen(color_t color) {
printf("test write fb: 0x%08x\n", color);
int i;
int bpp = __g_vinfo.bits_per_pixel / 8;
unsigned char *p = __gp_frame;
for (i = 0; i < __g_vinfo.xres_virtual * __g_vinfo.yres_virtual; i++) {
for (size_t j = 0; j < bpp; j++)
{
p[j] = BYTE(color, j);
}
p += bpp;
}
}
int main() {
if (framebuffer_init()) {
return -1;
}
while (1) {
// full_screen(0x001F);
// sleep(2);
// full_screen(0x07E0);
// sleep(2);
// full_screen(0xF800);
// sleep(2);
full_screen(0x0000FF);
sleep(2);
full_screen(0x00FF00);
sleep(2);
full_screen(0xFF0000);
sleep(2);
full_screen(0x00);
sleep(2);
full_screen(0xFFFFFF);
sleep(2);
}
return 0;
}

175
src/demo.cpp Normal file
View File

@ -0,0 +1,175 @@
#include <EGL/egl.h>
#include <EGL/eglext.h>
#include <GLES2/gl2.h>
#include <stdio.h>
#include <stdlib.h>
// Shader sources
const GLchar* vertexSource =
"attribute vec4 position; \n"
"void main() \n"
"{ \n"
" gl_Position = position; \n"
"} \n";
const GLchar* fragmentSource =
"void main() \n"
"{ \n"
" gl_FragColor = vec4(1.0, 0.0, 0.0, 1.0); \n"
"} \n";
void checkGLError(const char* stmt, const char* fname, int line) {
GLenum err = glGetError();
if (err != GL_NO_ERROR) {
fprintf(stderr, "OpenGL error %08x, at %s:%i - for %s\n", err, fname, line, stmt);
exit(1);
}
}
#define GL_CHECK(stmt) do { \
stmt; \
checkGLError(#stmt, __FILE__, __LINE__); \
} while (0)
typedef EGLDisplay (*PFNEGLGETPLATFORMDISPLAYEXTPROC)(EGLenum, void*, const EGLint*);
int main() {
// 1. Initialize EGL
EGLDisplay display;
EGLConfig config;
EGLContext context;
EGLint numConfigs;
EGLint configAttribs[] = {
EGL_SURFACE_TYPE, EGL_PBUFFER_BIT,
EGL_BLUE_SIZE, 8,
EGL_GREEN_SIZE, 8,
EGL_RED_SIZE, 8,
EGL_DEPTH_SIZE, 8,
EGL_RENDERABLE_TYPE, EGL_OPENGL_ES2_BIT,
EGL_NONE
};
// Get function pointer to eglGetPlatformDisplayEXT
PFNEGLGETPLATFORMDISPLAYEXTPROC eglGetPlatformDisplayEXT =
(PFNEGLGETPLATFORMDISPLAYEXTPROC) eglGetProcAddress("eglGetPlatformDisplayEXT");
if (!eglGetPlatformDisplayEXT) {
fprintf(stderr, "Error: eglGetPlatformDisplayEXT() not found.\n");
return 1;
}
// Use surfaceless platform
display = eglGetPlatformDisplayEXT(EGL_PLATFORM_SURFACELESS_MESA, EGL_DEFAULT_DISPLAY, NULL);
if (display == EGL_NO_DISPLAY) {
fprintf(stderr, "Error: eglGetPlatformDisplayEXT() failed.\n");
return 1;
}
if (!eglInitialize(display, NULL, NULL)) {
fprintf(stderr, "Error: eglInitialize() failed.\n");
return 1;
}
if (!eglChooseConfig(display, configAttribs, &config, 1, &numConfigs)) {
fprintf(stderr, "Error: eglChooseConfig() failed.\n");
return 1;
}
EGLint contextAttribs[] = {
EGL_CONTEXT_CLIENT_VERSION, 2,
EGL_NONE
};
context = eglCreateContext(display, config, EGL_NO_CONTEXT, contextAttribs);
if (context == EGL_NO_CONTEXT) {
fprintf(stderr, "Error: eglCreateContext() failed.\n");
return 1;
}
if (!eglMakeCurrent(display, EGL_NO_SURFACE, EGL_NO_SURFACE, context)) {
fprintf(stderr, "Error: eglMakeCurrent() failed.\n");
return 1;
}
// 2. Create and compile shaders
GLuint vertexShader = glCreateShader(GL_VERTEX_SHADER);
GL_CHECK(glShaderSource(vertexShader, 1, &vertexSource, NULL));
GL_CHECK(glCompileShader(vertexShader));
GLuint fragmentShader = glCreateShader(GL_FRAGMENT_SHADER);
GL_CHECK(glShaderSource(fragmentShader, 1, &fragmentSource, NULL));
GL_CHECK(glCompileShader(fragmentShader));
// 3. Link shaders to create a program
GLuint shaderProgram = glCreateProgram();
GL_CHECK(glAttachShader(shaderProgram, vertexShader));
GL_CHECK(glAttachShader(shaderProgram, fragmentShader));
GL_CHECK(glLinkProgram(shaderProgram));
GL_CHECK(glUseProgram(shaderProgram));
// 4. Define vertices for a triangle
GLfloat vertices[] = {
0.0f, 0.5f,
-0.5f, -0.5f,
0.5f, -0.5f,
};
GLuint VBO;
GL_CHECK(glGenBuffers(1, &VBO));
GL_CHECK(glBindBuffer(GL_ARRAY_BUFFER, VBO));
GL_CHECK(glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW));
GLint posAttrib = glGetAttribLocation(shaderProgram, "position");
GL_CHECK(glEnableVertexAttribArray(posAttrib));
GL_CHECK(glVertexAttribPointer(posAttrib, 2, GL_FLOAT, GL_FALSE, 2 * sizeof(GLfloat), 0));
// 5. Create FBO
GLuint fbo, texture;
GL_CHECK(glGenFramebuffers(1, &fbo));
GL_CHECK(glBindFramebuffer(GL_FRAMEBUFFER, fbo));
GL_CHECK(glGenTextures(1, &texture));
GL_CHECK(glBindTexture(GL_TEXTURE_2D, texture));
GL_CHECK(glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, 800, 600, 0, GL_RGB, GL_UNSIGNED_BYTE, NULL));
GL_CHECK(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST));
GL_CHECK(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST));
GL_CHECK(glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texture, 0));
if (glCheckFramebufferStatus(GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE) {
fprintf(stderr, "Error: Framebuffer is not complete.\n");
return 1;
}
// 6. Render to the FBO
GL_CHECK(glViewport(0, 0, 800, 600));
GL_CHECK(glClearColor(0.0, 0.0, 1.0, 1.0));
GL_CHECK(glClear(GL_COLOR_BUFFER_BIT));
GL_CHECK(glDrawArrays(GL_TRIANGLES, 0, 3));
// 7. Read pixels from the FBO
GLubyte *pixels = (GLubyte *)malloc(800 * 600 * 3);
GL_CHECK(glReadPixels(0, 0, 800, 600, GL_RGB, GL_UNSIGNED_BYTE, pixels));
// 8. Clean up
GL_CHECK(glDeleteFramebuffers(1, &fbo));
GL_CHECK(glDeleteTextures(1, &texture));
GL_CHECK(glDeleteProgram(shaderProgram));
GL_CHECK(glDeleteShader(vertexShader));
GL_CHECK(glDeleteShader(fragmentShader));
GL_CHECK(glDeleteBuffers(1, &VBO));
eglDestroyContext(display, context);
eglTerminate(display);
// Use `pixels` as needed
// For example, save it to a file, process it, etc.
// Don't forget to free the memory once done
free(pixels);
printf("Rendering completed successfully.\n");
return 0;
}

519
src/simple-es2.c Normal file
View File

@ -0,0 +1,519 @@
/*
* 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 <unistd.h>
#include <stdio.h>
#include <stdlib.h>
#include <fcntl.h>
#include <assert.h>
#include <math.h>
#include <stdbool.h>
#include <threads.h>
#include <signal.h>
#include "GLES2/gl2.h"
#include "GLES2/gl2ext.h"
#include "GL/gl.h"
#include "EGL/egl.h"
#include <EGL/eglext.h>
// #include <xf86dri.h>
// #include <xf86drmMode.h>
#include <gbm.h>
int device;
struct gbm_device *gbmDevice;
struct gbm_surface *gbmSurface;
EGLDisplay egldisplay;
EGLConfig eglconfig;
EGLSurface eglsurface;
EGLContext eglcontext;
GLuint framebuffer;
GLuint renderbuffer;
// 定义纹理对象的标识符
GLuint texId;
GLuint g_hShaderProgram = 0;
GLuint g_hModelViewMatrixLoc = 0;
GLuint g_hProjMatrixLoc = 0;
GLuint g_hVertexLoc = 0;
GLuint g_hColorLoc = 1;
#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)
#define CHECK_NULL(exp1) do { auto e1 = (exp1);\
if(!(e1)) { \
printf("check " #exp1 " is %p\n", e1); \
}}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};
// 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)
{
// 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);
// Rotate and translate the model view matrix
matModelView[ 0] = 1.0;
matModelView[ 2] = 0.0f;
matModelView[ 5] = 1.0f;
matModelView[ 8] = 0.0f;
matModelView[10] = 0.0f;
matModelView[14] = -4.0f;//translation Z
matModelView[15] = 1.0f;
glUniformMatrix4fv( g_hModelViewMatrixLoc, 1, 0, matModelView );
glUniformMatrix4fv( g_hProjMatrixLoc, 1, 0, matProj );
// 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
}
static int matchConfigToVisual(EGLDisplay display, EGLint visualId, EGLConfig* configs, int count)
{
EGLint id;
EGLint suf_type;
for (int i = 0; i < count; ++i)
{
eglGetConfigAttrib(display, configs[i], EGL_SURFACE_TYPE, &suf_type);
printf("suf_type: 0x%x\n", suf_type);
if (!eglGetConfigAttrib(display, configs[i], EGL_NATIVE_VISUAL_ID, &id))
continue;
if (id == visualId)
return i;
}
return -1;
}
EGLDisplay gbm_init(const char* devicePath) {
device = open(devicePath, O_RDWR | O_CLOEXEC);
gbmDevice = gbm_create_device(device);
CHECK_NULL(gbmDevice);
// gbmSurface = gbm_surface_create(gbmDevice, 600, 800, GBM_FORMAT_XRGB8888, GBM_BO_USE_SCANOUT | GBM_BO_USE_RENDERING);
// CHECK_NULL(gbmSurface);
return eglGetDisplay(gbmDevice);
}
void fbo_test() {
int width = 800;
int height = 600;
// 创建并绑定帧缓冲对象
glGenFramebuffers(1, &framebuffer);
glBindFramebuffer(GL_FRAMEBUFFER, framebuffer);
// 创建并绑定渲染缓冲对象用于深度和模板信息
glGenRenderbuffers(1, &renderbuffer);
glBindRenderbuffer(GL_RENDERBUFFER, renderbuffer);
// 分配存储空间
glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_COMPONENT, width, height);
// 将渲染缓冲对象附着到帧缓冲的深度和模板附着点
glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, renderbuffer);
// 创建并绑定纹理对象用于颜色附着点
glGenTextures(1, &texId);
glBindTexture(GL_TEXTURE_2D, texId);
// 分配存储空间
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL);
// 设置纹理参数
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_2D, GL_GENERATE_MIPMAP, GL_TRUE); // automatic mipmap generation included in OpenGL v1.4
// 将纹理对象附着到帧缓冲的颜色附着点
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texId, 0);
// 检查 FBO 完整性
GLenum status = glCheckFramebufferStatus(GL_FRAMEBUFFER);
if (status != GL_FRAMEBUFFER_COMPLETE) {
// 处理错误
printf("glCheckFramebufferStatus2 error : 0x%x\n", status);
}
// glBindFramebuffer(GL_FRAMEBUFFER, framebuffer);
}
int init(void)
{
// if ((egldisplay = eglGetDisplay(EGL_DEFAULT_DISPLAY)) == EGL_NO_DISPLAY)
// {
// fprintf(stderr, "Failed to get EGL display! \n");
// // return EXIT_FAILURE;
// }
egldisplay = gbm_init("/dev/dri/card0");
int major=-1, minor=-1;
eglInitialize(egldisplay, &major, &minor);
printf("Initialized EGL version: %d.%d\n", major, minor);
ASSERT_EQ(eglGetError(), EGL_SUCCESS);
eglBindAPI(EGL_OPENGL_ES_API);
EGLint count = 0;
EGLint numConfigs = 0;
eglGetConfigs(egldisplay, NULL, 0, &count);
EGLConfig* configs = malloc(count * sizeof(configs));
static const EGLint configAttribs[] = {
EGL_RED_SIZE, 8,
EGL_GREEN_SIZE, 8,
EGL_BLUE_SIZE, 8,
EGL_RENDERABLE_TYPE, EGL_OPENGL_ES3_BIT,
// EGL_SURFACE_TYPE, EGL_PBUFFER_BIT,
EGL_NONE
};
if (!eglChooseConfig(egldisplay, configAttribs, configs, count, &numConfigs))
{
fprintf(stderr, "Failed to get EGL configs! Error: 0x%x\n", eglGetError());
eglTerminate(egldisplay);
return EXIT_FAILURE;
}
int configIndex = matchConfigToVisual(egldisplay, GBM_FORMAT_XRGB8888, configs, numConfigs);
if (configIndex < 0)
{
fprintf(stderr, "Failed to find matching EGL config! Error: 0x%x\n", eglGetError());
eglTerminate(egldisplay);
gbm_device_destroy(gbmDevice);
return EXIT_FAILURE;
}
printf("configIndex: %d, numConfigs: %d\n", configIndex, numConfigs);
static const EGLint contextAttribs[] = {
EGL_CONTEXT_CLIENT_VERSION, 3,
EGL_NONE };
EGLContext context = eglCreateContext(egldisplay, configs[configIndex], EGL_NO_CONTEXT, contextAttribs);
if (context == EGL_NO_CONTEXT)
{
fprintf(stderr, "Failed to create EGL context! Error: 0x%x\n", eglGetError());
eglTerminate(egldisplay);
gbm_device_destroy(gbmDevice);
return EXIT_FAILURE;
}
// No rendering, no surface, just compute
// static EGLint attribList[] = {
// EGL_RENDER_BUFFER, EGL_BACK_BUFFER,
// EGL_WIDTH, 300,
// EGL_HEIGHT, 300,
// EGL_NONE};
// eglsurface = eglCreateWindowSurface(egldisplay, configs[configIndex], (EGLNativeWindowType)(0), NULL);
// auto ret = eglGetError();
// printf("eglCreateWindowSurface: result: 0x%x\n", ret);
// if(eglsurface == EGL_NO_SURFACE)
// {
// switch(ret)
// {
// case EGL_BAD_ALLOC:
// // Not enough resources available. Handle and recover
// printf("BgRender::CreateGlesEnv Not enough resources available\n");
// break;
// case EGL_BAD_CONFIG:
// // Verify that provided EGLConfig is valid
// printf("BgRender::CreateGlesEnv provided EGLConfig is invalid\n");
// break;
// case EGL_BAD_PARAMETER:
// // Verify that the EGL_WIDTH and EGL_HEIGHT are
// // non-negative values
// printf("BgRender::CreateGlesEnv provided EGL_WIDTH and EGL_HEIGHT is invalid\n");
// break;
// case EGL_BAD_MATCH:
// // Check window and EGLConfig attributes to determine
// // compatibility and pbuffer-texture parameters
// printf("BgRender::CreateGlesEnv Check window and EGLConfig attributes\n");
// break;
// }
// }
// free(configs);
eglsurface = EGL_NO_SURFACE;
eglMakeCurrent(egldisplay, eglsurface, eglsurface, context);
{
//1、查看显卡、GLSL和OpenGL的信息
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");
// 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 );
printf("compile opengl shader result: %d\n", nCompileResult);
if( 0 == nCompileResult )
{
char strLog[1024] = {0};
GLint nLength;
glGetShaderInfoLog( hVertexShader, 1024, &nLength, strLog );
printf("compile opengl shader failed: %s\n", 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" );
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 Cleanup()
{
}
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);
}
void init_signal() {
signal(SIGUSR1, handle_sig);
signal(SIGUSR2, handle_sig);
signal(37, handle_sig);
}
void writeToFile(const char* filename, unsigned char* data, long dataLen) {
FILE* file = fopen(filename, "wb");
if (file) {
fwrite(data, 1, dataLen, file);
fclose(file);
}
}
int main (void)
{
EGLint width = 800;
EGLint height = 600;
// init_signal();
init();
// 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);
unsigned char* buffer = (unsigned char*)malloc(width * height * 4);
fbo_test();
while (1) {
glBindTexture(GL_TEXTURE_2D, texId);
glGenerateMipmap(GL_TEXTURE_2D);
glBindTexture(GL_TEXTURE_2D, 0);
// glBindFramebuffer(GL_FRAMEBUFFER, framebuffer);
render(width,height);
// glBindFramebuffer(GL_FRAMEBUFFER, 0);
printf("glReadPixels start \n");
glBindFramebuffer(GL_READ_FRAMEBUFFER, framebuffer);
glReadPixels( 0, 0, width, height, GL_RGBA, GL_UNSIGNED_BYTE, buffer );
glBindFramebuffer(GL_READ_FRAMEBUFFER, 0);
printf("glReadPixels end \n");
writeToFile("image.rgba", buffer, width * height * 4);
// eglSwapBuffers(egldisplay, eglsurface);
sleep(1);
}
free(buffer);
deinit();
return 0;
}

674
src/triangle-es2.c Normal file
View File

@ -0,0 +1,674 @@
/*
* 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 <signal.h>
#include "GLES2/gl2.h"
#include "GLES2/gl2ext.h"
#include "EGL/egl.h"
// #define XORG_SHOW
#include <libdrm/drm.h>
#ifdef XORG_SHOW
#include "X11/X.h"
#include "X11/Xatom.h"
#else
#include <gbm.h>
#endif
Display *x_display;
Window win;
int device;
struct gbm_device *gbmDevice;
struct gbm_surface *gbmSurface;
struct gbm_bo * gbmBo;
int fb_id;
int dumb_handle;
int g_stop;
#ifdef XORG_SHOW
#define USE_FORMAT 0x34325258
#else
#define USE_GBM_FORMAT GBM_FORMAT_XRGB8888
#define USE_FORMAT USE_GBM_FORMAT
#endif
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
}
#ifndef XORG_SHOW
#define drm_ioctl(fd, _IOCTL_NAME, ...) \
{ int __ret; \
__ret=ioctl(fd, _IOCTL_NAME, __VA_ARGS__);\
if (__ret) { \
printf( "ioctl:" #_IOCTL_NAME " failed:%d\n", __ret); \
return __ret;\
}}
#define memzero(_p) (memset((_p), 0, sizeof(*(_p))))
static int mode_get_cap(int fd, int cap) {
struct drm_get_cap get_cap;
get_cap.capability = cap;
drm_ioctl(fd, DRM_IOCTL_GET_CAP, &get_cap);
return get_cap.value;
}
int modeset_import_fd(int dumb, int fd) {
struct drm_prime_handle prime_handle;
memzero(&prime_handle);
prime_handle.handle = dumb_handle;
// prime_handle.fd = fd;
prime_handle.flags = DRM_RDWR;
drm_ioctl(fd, DRM_IOCTL_PRIME_HANDLE_TO_FD, &prime_handle);
printf("prime_handle : %d, newfd:%d flags:%x\n", prime_handle.fd, prime_handle.handle, prime_handle.flags);
return prime_handle.fd;
}
int modeset_fd(int fd) {
int width = 1280;
int height = 1024;
int bpp = 32;
int buffer_v = mode_get_cap(fd, DRM_CAP_DUMB_BUFFER);
printf("buffer_v :0x%x\n", buffer_v);
int prime_v = mode_get_cap(fd, DRM_CAP_PRIME);
printf("prime_v :0x%x\n", prime_v);
// struct drm_mode_create_dumb create_dumb;
// memzero(&create_dumb);
// create_dumb.width = width;
// create_dumb.height = height;
// create_dumb.bpp = bpp;
// create_dumb.pitch = width * bpp/8;
// create_dumb.size = create_dumb.pitch * height;
// drm_ioctl(fd, DRM_IOCTL_MODE_CREATE_DUMB, &create_dumb);
// dumb_handle = create_dumb.handle;
// printf("create_dumb handle:0x%x\n", dumb_handle);
// struct drm_mode_map_dumb map_dumb;
// map_dumb.handle = dumb_handle;
// drm_ioctl(fd, DRM_IOCTL_MODE_MAP_DUMB, &map_dumb);
return 0;
}
int modeset_clean(int fd) {
// struct drm_mode_destroy_dumb destroy_dumb;
// destroy_dumb.handle = dumb_handle;
ioctl(fd, DRM_IOCTL_MODE_RMFB, fb_id);
// drm_ioctl(fd, DRM_IOCTL_MODE_DESTROY_DUMB, &destroy_dumb);
ioctl(fd, DRM_IOCTL_DROP_MASTER);
return 0;
}
int gbm_mode_set() {
if (gbmBo) {
return 0;
}
gbmBo = gbm_surface_lock_front_buffer(gbmSurface);
union gbm_bo_handle bo_handle = gbm_bo_get_handle(gbmBo);
printf("gbm bo handle: %d\n", bo_handle);
dumb_handle = bo_handle.u32;
gbm_surface_release_buffer(gbmSurface, gbmBo);
int fd = device;
int width = gbm_bo_get_width(gbmBo);
int height = gbm_bo_get_height(gbmBo);
int bpp = gbm_bo_get_bpp(gbmBo);
int i;
struct drm_mode_fb_cmd fb_cmd;
memzero(&fb_cmd);
fb_cmd.width = width;
fb_cmd.height = height;
fb_cmd.bpp = bpp;
fb_cmd.depth = 24;
fb_cmd.pitch = width * bpp/8;
fb_cmd.handle = dumb_handle;
drm_ioctl(fd, DRM_IOCTL_MODE_ADDFB, &fb_cmd);
fb_id = fb_cmd.fb_id;
printf("add_fb fb_id: %d\n", fb_id);
struct drm_mode_card_res drm_mode_card_res;
memzero(&drm_mode_card_res);
drm_ioctl(fd, DRM_IOCTL_MODE_GETRESOURCES, &drm_mode_card_res);
drm_mode_card_res.connector_id_ptr = calloc(1, sizeof(uint32_t));
drm_mode_card_res.crtc_id_ptr = calloc(1, sizeof(uint32_t));
drm_mode_card_res.fb_id_ptr = calloc(1, sizeof(uint32_t));
drm_mode_card_res.count_encoders = 0;
// drm_mode_card_res.encoder_id_ptr = calloc(1, sizeof(uint32_t));
drm_ioctl(fd, DRM_IOCTL_MODE_GETRESOURCES, &drm_mode_card_res);
printf("res count_connectors:%d, count_crtcs:%d, count_fbs:%d, crtc_ptr:0x%x\n",
drm_mode_card_res.count_connectors, drm_mode_card_res.count_crtcs, drm_mode_card_res.count_fbs, drm_mode_card_res.crtc_id_ptr);
printf("crtc data:[ %d]\n", ((uint32_t*)drm_mode_card_res.crtc_id_ptr)[0]);
uint32_t crtc_id = ((uint32_t*)drm_mode_card_res.crtc_id_ptr)[0];
uint32_t conn_id = ((uint32_t*)drm_mode_card_res.connector_id_ptr)[0];
struct drm_mode_get_connector get_connector;
memzero(&get_connector);
get_connector.connector_id = conn_id;
drm_ioctl(fd, DRM_IOCTL_MODE_GETCONNECTOR, &get_connector);
printf("get_connector modes count: %d\n", get_connector.count_modes);
get_connector.connector_id = conn_id;
get_connector.count_encoders = 0;
get_connector.count_props = 0;
struct drm_mode_modeinfo *modes = calloc(get_connector.count_modes, sizeof(struct drm_mode_modeinfo));
get_connector.modes_ptr = modes;
drm_ioctl(fd, DRM_IOCTL_MODE_GETCONNECTOR, &get_connector);
for (i = 0; i < get_connector.count_modes; i++) {
printf("get_connector mode[%d] : '%s' -> (%d, %d, %d)\n", i, modes[i].name, modes[i].hdisplay, modes[i].vdisplay, modes[i].vrefresh);
if (modes[i].hdisplay == width && modes[i].vdisplay == height) {
printf("match gbm size (%d, %d)\n", width, height);
break;
}
}
if (i == get_connector.count_modes) {
printf("nothing match gbm size (%d, %d)\n", width, height);
return -1;
}
ioctl(fd, DRM_IOCTL_SET_MASTER);
struct drm_mode_crtc mode_crtc;
memzero(&mode_crtc);
mode_crtc.count_connectors = drm_mode_card_res.count_connectors;
mode_crtc.set_connectors_ptr = drm_mode_card_res.connector_id_ptr;
mode_crtc.crtc_id = crtc_id;
mode_crtc.fb_id = fb_id;
mode_crtc.mode_valid = 1;
memcpy(&mode_crtc.mode, modes+i, sizeof(struct drm_mode_modeinfo));
drm_ioctl(fd, DRM_IOCTL_MODE_SETCRTC, &mode_crtc);
return 0;
}
EGLDisplay gbm_init(const char* devicePath) {
device = open(devicePath, O_RDWR | O_CLOEXEC);
modeset_fd(device);
gbmDevice = gbm_create_device(device);
if (!gbmDevice) {
printf("gbm device is null!\n");
}
// int gbm_fd = gbm_device_get_fd(gbmDevice);
// printf("gbm_fd: %d, card0 fd:%d\n", gbm_fd, device);
gbmSurface = gbm_surface_create(gbmDevice, 1280, 1024, USE_GBM_FORMAT, GBM_BO_USE_SCANOUT | GBM_BO_USE_RENDERING);
if (!gbmSurface) {
printf("gbm surface is null!\n");
}
return eglGetDisplay(gbmDevice);
}
EGLDisplay gbm_uninit() {
if (gbmSurface)
gbm_surface_destroy(gbmSurface);
// if (gbmBo)
// gbm_bo_destroy(gbmBo);
gbm_device_destroy(gbmDevice);
modeset_clean(device);
return 0;
}
#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");
}
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)
{
// eglGetConfigAttrib(display, configs[i], EGL_SURFACE_TYPE, &suf_type);
// printf("suf_type: 0x%x\n", suf_type);
// eglGetConfigAttrib(display, configs[i], EGL_NATIVE_VISUAL_TYPE, &suf_type);
// printf("native_visual_type: 0x%x\n", suf_type);
if (!eglGetConfigAttrib(display, configs[i], EGL_NATIVE_VISUAL_ID, &id))
continue;
// printf("visualid: 0x%x, str:%.*s\n", id, 4, &id);
if (id == visualId) {
retId = i;
break;
}
}
return retId;
}
int init(void)
{
#ifdef XORG_SHOW
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;
win = XCreateWindow ( // create a window with the provided parameters
x_display, root,
0, 0, 1000, 1000, 0,
CopyFromParent, InputOutput,
CopyFromParent, CWEventMask,
&swa );
XSetWindowAttributes xattr;
xattr.override_redirect = False;
XChangeWindowAttributes( x_display, win, CWOverrideRedirect, &xattr );
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);
#else
egldisplay = gbm_init("/dev/dri/card0");
#endif
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
};
EGLint count = 0;
EGLint numConfigs = 0;
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);
#ifdef XORG_SHOW
EGLint win_attrlist[] = {
EGL_NONE,
};
eglsurface = eglCreateWindowSurface(egldisplay, eglconfig, (EGLNativeWindowType)(win), win_attrlist);
#else
EGLint win_attrlist[] = {
EGL_NONE
};
eglsurface = eglCreateWindowSurface(egldisplay, eglconfig, (EGLNativeWindowType)(gbmSurface), win_attrlist);
#endif
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);
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();
#ifndef XORG_SHOW
gbm_uninit();
#endif
}
int event_handle(void* arg) {
printf("start event loop\n");
#ifdef XORG_SHOW
while (1) {
XEvent xevent;
// XWindowEvent(x_display, win, StructureNotifyMask, &xevent);
XNextEvent(x_display, &xevent);
if (xevent.type == DestroyNotify) {
printf("DestroyNotify \n");
break;
}
}
#endif
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);
}
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);
unsigned int framenum = 0;
while (!g_stop) {
render(width, height, framenum);
eglSwapBuffers(egldisplay, eglsurface);
#ifndef XORG_SHOW
gbm_mode_set();
#endif
usleep(1*1000);
framenum++;
if (!(framenum%100)) {
printf("frame num:%d\n", framenum);
}
if (framenum > 100000) {
break;
}
}
deinit();
return 0;
}