本文主要介绍如何在linux 下 wayland 窗口中,使用 egl + opengles 控制GPU 渲染 gears 并显示,即实现一个wayland 版本的gles-gears
软硬件环境:
硬件:PC
软件:ubuntu18.04 weston3.0 opengles2.0 egl1.4
如下图所示,是在ubuntu 上执行 glxgears 的结果,会出现三个不同颜色的齿轮在不停的旋转,并会打印出帧率。
如果ubuntu 上没有安装 glxgears 程序, 可以通过 sudo apt-get install mesa-utils libgles2-mesa-dev 命令进行安装
参考 Mesa Demos es2gears.c 实现基于 wayland 版本的 gears 总共有三个文件,分别是:egl_wayland_gears.c, matrix.c, matrix.h
使用 wayland (使用wl_shell 接口)+ egl + opengles2.0 实现和 glxgears 同样效果的 egl_wayland_gears.c 代码如下
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include "matrix.h"
#define WIDTH 640
#define HEIGHT 480
static struct timespec start_time;
struct wl_display *display = NULL;
struct wl_compositor *compositor = NULL;
struct wl_shell *shell = NULL;
struct wl_registry *registry = NULL;
struct window {
struct wl_surface *surface;
struct wl_shell_surface *shell_surface;
struct wl_egl_window *egl_window;
};
#define STRIPS_PER_TOOTH 7
#define VERTICES_PER_TOOTH 46
#define GEAR_VERTEX_STRIDE 6
/* Each vertex consist of GEAR_VERTEX_STRIDE GLfloat attributes */
typedef GLfloat GearVertex[GEAR_VERTEX_STRIDE];
/**
* Struct representing a gear.
*/
struct gear {
/** The array of vertices comprising the gear */
GearVertex *vertices;
/** The number of vertices comprising the gear */
int nvertices;
/** The Vertex Buffer Object holding the vertices in the graphics card */
GLuint vbo;
};
/** The view rotation [x, y, z] */
static GLfloat view_rot[3] = {
20.0, 30.0, 0.0 };
/** The gears */
static struct gear *gear1, *gear2, *gear3;
/** The current gear rotation angle */
static GLfloat angle = 0.0;
/** The location of the shader uniforms */
static GLuint ModelViewProjectionMatrix_location,
NormalMatrix_location,
LightSourcePosition_location,
MaterialColor_location;
/** The projection matrix */
static GLfloat ProjectionMatrix[16];
/** The direction of the directional light for the scene */
static const GLfloat LightSourcePosition[4] = {
5.0, 5.0, 10.0, 1.0};
/**
*Fills a gear vertex.
*/
static GearVertex *
vert(GearVertex *v, GLfloat x, GLfloat y, GLfloat z, GLfloat n[3])
{
v[0][0] = x;
v[0][1] = y;
v[0][2] = z;
v[0][3] = n[0];
v[0][4] = n[1];
v[0][5] = n[2];
return v + 1;
}
/**
*Create a gear wheel.
*/
static struct gear *
create_gear(GLfloat inner_radius, GLfloat outer_radius, GLfloat width,
GLint teeth, GLfloat tooth_depth)
{
GLfloat r0, r1, r2;
GLfloat da;
GearVertex *v;
struct gear *gear;
double s[5], c[5];
GLfloat normal[3];
int cur_strip_start = 0;
int i;
/* Allocate memory for the gear */
gear = malloc(sizeof *gear);
if (gear == NULL)
return NULL;
/* Calculate the radii used in the gear */
r0 = inner_radius;
r1 = outer_radius - tooth_depth / 2.0;
r2 = outer_radius + tooth_depth / 2.0;
da = 2.0 * M_PI / teeth / 4.0;
/* the first tooth doesn't need the first strip-restart sequence */
assert(teeth > 0);
gear->nvertices = VERTICES_PER_TOOTH +
(VERTICES_PER_TOOTH + 2) * (teeth - 1);
/* Allocate memory for the vertices */
gear->vertices = calloc(gear->nvertices, sizeof(*gear->vertices));
v = gear->vertices;
for (i = 0; i < teeth; i++) {
/* Calculate needed sin/cos for varius angles */
#if HAVE_SINCOS
sincos(i * 2.0 * M_PI / teeth, &s[0], &c[0]);
sincos(i * 2.0 * M_PI / teeth + da, &s[1], &c[1]);
sincos(i * 2.0 * M_PI / teeth + da * 2, &s[2], &c[2]);
sincos(i * 2.0 * M_PI / teeth + da * 3, &s[3], &c[3]);
sincos(i * 2.0 * M_PI / teeth + da * 4, &s[4], &c[4]);
#else
s[0] = sin(i * 2.0 * M_PI /teeth);
c[0] = cos(i * 2.0 * M_PI /teeth);
s[1] = sin(i * 2.0 * M_PI /teeth + da);
c[1] = cos(i * 2.0 * M_PI /teeth + da);
s[2] = sin(i * 2.0 * M_PI /teeth + da * 2);
c[2] = cos(i * 2.0 * M_PI /teeth + da * 2);
s[3] = sin(i * 2.0 * M_PI /teeth + da * 3);
c[3] = cos(i * 2.0 * M_PI /teeth + da * 3);
s[4] = sin(i * 2.0 * M_PI /teeth + da * 4);
c[4] = cos(i * 2.0 * M_PI /teeth + da * 4);
#endif
/* A set of macros for making the creation of the gears easier */
#define GEAR_POINT(r, da) {
(r) * c[(da)], (r) * s[(da)] }
#define SET_NORMAL(x, y, z) do {
\
normal[0] = (x); normal[1] = (y); normal[2] = (z); \
} while(0)
#define GEAR_VERT(v, point, sign) vert((v), p[(point)].x, p[(point)].y, (sign) * width * 0.5, normal)
#define START_STRIP do {
\
cur_strip_start = (v - gear->vertices); \
if (cur_s