wayland(xdg_wm_base) + egl + opengles2.0 绘制四边形实例(二)

文章目录

  • 前言
  • 一、opengles 绘制四边形的步骤
    • 1. 术语介绍
    • 2. opengles 绘制四边形的主要步骤
  • 二、代码实例
    • 1. 没有使用 VBO 的版本
      • 1.1 基于opengles2.0 接口的 egl_wayland_demo2_1.c
      • 1.2 基于opengles3.0 接口的 egl_wayland_demo3_1.c
    • 2. 使用 VBO 的版本
      • 2.1 基于opengles2.0 接口的 egl_wayland_demo2_1.c
      • 2.2 基于opengles3.0 接口的 egl_wayland_demo3_1.c
    • 3. xdg-shell-client-protocol.h 和 xdg-shell-protocol.c
    • 3. 编译
    • 4. 运行结果
  • 总结


前言

本文主要介绍在使用wayland 协议作为窗口系统的Linux系统中,如何使用 egl + opengles 绘制一个最简单的四边形,在阅读本篇文章之前,建议先读一下之前的文章 《wayland(xdg_wm_base) + egl + opengles 最简实例(一)》
软硬件环境:
硬件:PC
软件:ubuntu22.04 egl1.4 opengles2.0/3.0 weston9.0


一、opengles 绘制四边形的步骤

1. 术语介绍

  • VBO(Vertex Buffer Object)是一个顶点缓冲区对象,它用来存储顶点数据。VBO可以通过glGenBuffers函数创建,并通过glBindBuffer函数绑定到OpenGLES上下文中。然后,我们可以使用glBufferData函数将顶点数据存储到VBO中,或使用glMapBuffer函数将VBO映射到内存中进行读写操作。

2. opengles 绘制四边形的主要步骤

使用opengles 绘制一个四边形需要有如下步骤:
其中对 VBO 的操作是可选的(即不使用VBO时 ,也能绘制四边形,但是效率比使用 VBO 时要低)

  1. 定义四个顶点的坐标
// Define the vertex positions of the quad
const GLfloat vertices[] = {
   
    // x     y     z
    -1.0f, -1.0f, 0.0f,   // Bottom-left
     1.0f, -1.0f, 0.0f,  // Bottom-right
    -1.0f, 1.0f, 0.0f,   // Top-left
     1.0f, 1.0f, 0.0f    // Top-right
};
  1. 创建并绑定VBO:生成一个顶点缓冲对象(VBO),并将其绑定到GL_ARRAY_BUFFER目标上
// Generate a vertex buffer object (VBO)
GLuint vbo;
glGenBuffers(1, &vbo);

// Bind the VBO to GL_ARRAY_BUFFER target
glBindBuffer(GL_ARRAY_BUFFER, vbo);

  1. 存储顶点数据:使用glBufferData函数将顶点数据存储到VBO中
// Store vertex data in the VBO
glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW);
  1. 设置顶点属性指针:启用顶点属性数组,并设置顶点属性指针指向VBO中的顶点数据
// Enable vertex attribute array
glEnableVertexAttribArray(0);

// Set vertex attribute pointer
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0, NULL);
  1. 绘制四边形:使用glDrawArrays函数绘制四边形
// Draw the quad using glDrawArrays
glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
  1. 清理工作:在绘制完成后,禁用顶点属性数组,并解绑并删除VBO
// Disable the vertex attribute array
glDisableVertexAttribArray(0);

// Unbind the VBO
glBindBuffer(GL_ARRAY_BUFFER, 0);

// Delete the VBO
glDeleteBuffers(1, &vbo);

二、代码实例

如下图所示,是实现绘制一个 640x480 的四边形,并且颜色由纯红色所填充(窗口大小是800x600, 窗口背景颜色是淡蓝色)的代码实例

1. 没有使用 VBO 的版本

1.1 基于opengles2.0 接口的 egl_wayland_demo2_1.c

#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 

#include 
#include 
#include 
#include 
#include "xdg-shell-client-protocol.h"

#define WIDTH 800
#define HEIGHT 600

struct wl_display *display = NULL;
struct wl_compositor *compositor = NULL;
struct xdg_wm_base *wm_base = NULL;
struct wl_registry *registry = NULL;

struct window {
   
	struct wl_surface *surface;
	struct xdg_surface *xdg_surface;
	struct xdg_toplevel *xdg_toplevel;
	struct wl_egl_window *egl_window;
};

// Index to bind the attributes to vertex shaders
const unsigned int VertexArray = 0;

static void
xdg_wm_base_ping(void *data, struct xdg_wm_base *shell, uint32_t serial)
{
   
		xdg_wm_base_pong(shell, serial);
}

/*for xdg_wm_base listener*/
static const struct xdg_wm_base_listener wm_base_listener = {
   
		xdg_wm_base_ping,
};

/*for registry listener*/
static void registry_add_object(void *data, struct wl_registry *registry, uint32_t name, const char *interface, uint32_t version) 
{
   
	if (!strcmp(interface, "wl_compositor")) {
   
		compositor = wl_registry_bind(registry, name, &wl_compositor_interface, 1);
	} else if (strcmp(interface, "xdg_wm_base") == 0) {
   
		wm_base = wl_registry_bind(registry, name,
			&xdg_wm_base_interface, 1);
		xdg_wm_base_add_listener(wm_base, &wm_base_listener, NULL);
	}
}


void registry_remove_object(void *data, struct wl_registry *registry, uint32_t name) 
{
   

}

static struct wl_registry_listener registry_listener = {
   registry_add_object, registry_remove_object};


static void
handle_surface_configure(void *data, struct xdg_surface *surface,
	uint32_t serial)
{
   
	xdg_surface_ack_configure(surface, serial);
}


static const struct xdg_surface_listener xdg_surface_listener = {
   
		handle_surface_configure
};

static void
handle_toplevel_configure(void *data, struct xdg_toplevel *toplevel,
				  int32_t width, int32_t height,
							  struct wl_array *states)
{
   
}

static void
handle_toplevel_close(void *data, struct xdg_toplevel *xdg_toplevel)
{
   
}

static const struct xdg_toplevel_listener xdg_toplevel_listener = {
   
	handle_toplevel_configure,
	handle_toplevel_close,
};

bool initWaylandConnection()
{
   	
	if ((display = wl_display_connect(NULL)) == NULL)
	{
   
		printf("Failed to connect to Wayland display!\n");
		return false;
	}

	if ((registry = wl_display_get_registry(display)) == NULL)
	{
   
		printf("Faield to get Wayland registry!\n");
		return false;
	}

	wl_registry_add_listener(registry, &registry_listener, NULL);
	wl_display_dispatch(display);

	if (!compositor)
	{
   
		printf("Could not bind Wayland protocols!\n");
		return false;
	}

	return true;
}

bool initializeWindow(struct window *window)
{
   
	initWaylandConnection();
	window->surface = wl_compositor_create_surface (compositor);
	window->xdg_surface = xdg_wm_base_get_xdg_surface(wm_base, window->surface);
	if (window->xdg_surface == NULL)
	{
   
		printf("Failed to get Wayland xdg surface\n");
		return false;
	} else {
   
		xdg_surface_add_listener(window->xdg_surface, &xdg_surface_listener, window);
		window->xdg_toplevel =
			xdg_surface_get_toplevel(window->xdg_surface);
		xdg_toplevel_add_listener(window->xdg_toplevel,
			&xdg_toplevel_listener, window);
		xdg_toplevel_set_title(window->xdg_toplevel, "egl_wayland_texture");
	}

	return true;

}

void releaseWaylandConnection(struct window *window)
{
   
	if(window->xdg_toplevel)
		xdg_toplevel_destroy(window->xdg_toplevel);
	if(window->xdg_surface)
		xdg_surface_destroy(window->xdg_surface);
	wl_surface_destroy(window->surface);
	xdg_wm_base_destroy(wm_base);
	wl_compositor_destroy(compositor);
	wl_registry_destroy(registry);
	wl_display_disconnect(display);
}

bool createEGLSurface(EGLDisplay eglDisplay, EGLConfig eglConfig, EGLSurface *eglSurface, struct window *window)
{
   

	window->egl_window = wl_egl_window_create(window->surface, WIDTH, HEIGHT);
	if (window->egl_window == EGL_NO_SURFACE) {
    
		printf("Can't create egl window\n"); 
		return false;
	} else {
   
		printf("Created wl egl window\n");
	}

	*eglSurface = eglCreateWindowSurface(eglDisplay, eglConfig, window->egl_window, NULL);
	
	return true;
}


bool opengles_init(GLuint *shaderProgram)
{
   
	GLuint fragmentShader = 0;
	GLuint vertexShader = 0;
	char msg[1000];
	GLsizei len;


	const char* const fragmentShaderSource = 
		"precision mediump float;\n"
		"void main()\n"
		"{\n"
		"   gl_FragColor = vec4(1.0, 0.0, 0.0, 1.0);\n"
		"}\n";


	// Create a fragment shader object
	fragmentShader = glCreateShader(GL_FRAGMENT_SHADER);

	// Load the source code into it
	glShaderSource(fragmentShader, 1, (const char**)&fragmentShaderSource, NULL);
	
	// Compile the source code
	glCompileShader(fragmentShader);

	// Check that the shader compiled
	GLint isShaderCompiled;
	glGetShaderiv(fragmentShader, GL_COMPILE_STATUS, &isShaderCompiled);
	if (!isShaderCompiled)
	{
   
		// If an error happened, first retrieve the length of the log message

		glGetShaderInfoLog(fragmentShader, sizeof msg, &len, msg);
		//glGetShaderiv(fragmentShader, GL_INFO_LOG_LENGTH, &infoLogLength);

		// Allocate enough space for the message and retrieve it
		//std::vector infoLog;
		//infoLog.resize(infoLogLength);
		//glGetShaderInfoLog(fragmentShader, infoLogLength, &charactersWritten, infoLog.data());
		fprintf(stderr, "Error: compiling %s: %.*s\n", "fragment", len, msg);
		return false;
	}

	// Vertex shader code
	const char* const vertexShaderSource =		
		"attribute vec4 vPosition; \n"
		"void main()\n"
		"{\n"
		"   gl_Position = vPosition;\n"
		"}\n";

	// Create a vertex shader object
	vertexShader = glCreateShader(GL_VERTEX_SHADER);

	// Load the source code into the shader
	glShaderSource(vertexShader, 1, (const char**)&vertexShaderSource, NULL);

	// Compile the shader
	glCompileShader(vertexShader);

	// Check the shader has compiled
	glGetShaderiv(vertexShader, GL_COMPILE_STATUS, &isShaderCompiled);
	if (!isShaderCompiled)
	{
   
		// If an error happened, first retrieve the length of the log message
		//int infoLogLength, charactersWritten;
		//glGetShaderiv(vertexShader, GL_INFO_LOG_LENGTH, &infoLogLength);

		glGetShaderInfoLog(vertexShader, sizeof msg, &len, msg);

		// Allocate enough space for the message and retrieve it
		//std::vector infoLog;
		//infoLog.resize(infoLogLength);
		//glGetShaderInfoLog(vertexShader, infoLogLength, &charactersWritten, infoLog.data());
		return false;
	}

	// Create the shader program
	*shaderProgram = glCreateProgram();

	// Attach the fragment and vertex shaders to it
	glAttachShader(*shaderProgram, fragmentShader);
	glAttachShader(*shaderProgram, vertexShader);

	// Bind the vertex attribute "vPosition" to location VertexArray (0)
	glBindAttribLocation(*shaderProgram, 0, "vPosition");

	// Link the program
	glLinkProgram(*shaderProgram);


	// After linking the program, shaders are no longer necessary
	glDeleteShader(vertexShader);
	glDeleteShader(fragmentShader);

	// Check if linking succeeded in the same way we checked for compilation success
	GLint isLinked;
	glGetProgramiv(*shaderProgram, GL_LINK_STATUS, &isLinked);

	if (!isLinked)
	{
   
		// If an error happened, first retrieve the length of the log message
		//nt infoLogLength, charactersWritten;
		//glGetProgramiv(*shaderProgram, GL_INFO_LOG_LENGTH, &infoLogLength);

		// Allocate enough space for the message and retrieve it
		//std::vector infoLog;
		//infoLog.resize(infoLogLength);
		//glGetShaderInfoLog(shaderProgram, infoLogLength, &charactersWritten, infoLog.data());
		glGetProgramInfoLog(*shaderProgram, sizeof msg, &len, msg);
		fprintf(stderr, "Error: compiling %s: %.*s\n", "linkprogram", len, msg);

		return false;
	}

	//	Use the Program
	glUseProgram(*shaderProgram);


	return true;
}
bool renderScene(GLuint shaderProgram, EGLDisplay eglDisplay, EGLSurface eglSurface)
{
   
	GLfloat vVertices[] = {
   
		//vertex pointer
        //x     y   z
		-0.8f,0.8f,0.0f,	//top left
		0.8f,0.8f,0.0f,		//top right
		-0.8f,-0.8f,0.0f,	//bottom left
		0.8f,-0.8f,0.0f,	//bottom right
		};

	glViewport(0, 0, WIDTH, HEIGHT);			//set the view port
	glClearColor(0.00f, 0.70f, 0.67f, 1.0f);		//set rgba value for backgroud 
	glClear(GL_COLOR_BUFFER_BIT);

	glEnableVertexAttribArray(0);
	glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0, vVertices);

	glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);			//draw a quadrilateral

	if (!eglSwapBuffers(eglDisplay, eglSurface))
	{
   
		return false;
	}

	return true;

}

bool render(GLuint shade

你可能感兴趣的:(EGL/OpenGL,ES,weston/wayland,opengles,egl,wayland)