wayland(wl_shell) + egl + opengles 实例——gears

文章目录

  • 前言
  • 一、ubuntu 上 opengl 版本的 glxgears
  • 二、基于 wayland 窗口协议的 gles-gears
    • 1.egl_wayland_gears.c
    • 2. matrix.c 和 matrix.h
    • 3. 编译
    • 4. 运行
  • 总结
  • 参考资料

前言

本文主要介绍如何在linux 下 wayland 窗口中,使用 egl + opengles 控制GPU 渲染 gears 并显示,即实现一个wayland 版本的gles-gears
软硬件环境:
硬件:PC
软件:ubuntu18.04 weston3.0 opengles2.0 egl1.4


一、ubuntu 上 opengl 版本的 glxgears

如下图所示,是在ubuntu 上执行 glxgears 的结果,会出现三个不同颜色的齿轮在不停的旋转,并会打印出帧率。
如果ubuntu 上没有安装 glxgears 程序, 可以通过 sudo apt-get install mesa-utils libgles2-mesa-dev 命令进行安装
在这里插入图片描述

  • glxgears 是一个简单的 OpenGL 示例程序,用于测试系统中 OpenGL 功能和性能
  • glxgears 只是一个简单的示例程序,并不是一个真正的性能测试工具。它主要用于检查 OpenGL
    驱动是否正确安装和运行,并提供一个简单的可视化效果。如果需要进行更详细的 OpenGL 性能测试,可以考虑使用专业的性能测试工具,例如 glmark2。
  • 运行 glxgears ,需要安装 Mesa 3D 图形库和相关的 OpenGL 开发库;

二、基于 wayland 窗口协议的 gles-gears

参考 Mesa Demos es2gears.c 实现基于 wayland 版本的 gears 总共有三个文件,分别是:egl_wayland_gears.c, matrix.c, matrix.h

1.egl_wayland_gears.c

使用 wayland (使用wl_shell 接口)+ egl + opengles2.0 实现和 glxgears 同样效果的 egl_wayland_gears.c 代码如下

#include <wayland-client.h>
#include <wayland-server.h>
#include <wayland-egl.h>
#include <EGL/egl.h>
#include <GLES2/gl2.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <math.h>
#include <assert.h>
#include <unistd.h>
#include <time.h>
#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