wayland(xdg_wm_base) + egl + opengles 最简实例

文章目录

  • 前言
  • 一、ubuntu 下相关环境准备
    • 1. 获取 xdg_wm_base 依赖的相关文件
    • 2. 查看 ubuntu 上安装的opengles 版本
    • 3. 查看 weston 所支持的 窗口shell 接口种类
  • 二、xdg_wm_base 介绍
  • 三、egl_wayland_demo
    • 1.egl_wayland_demo2_0.c
    • 2.egl_wayland_demo3_0.c
    • 3. xdg-shell-protocol.c和 xdg-shell-client-protocol.h
    • 4. 编译和运行
      • 4.1 编译
      • 4.2 运行
  • 总结
  • 参考资料


前言

`本文主要介绍如何在linux 下,基于xdg_wm_base 接口的 wayland client 中 使用 egl + opengles 渲染一个最基本的三角形
软硬件环境:
硬件:PC
软件:
ubuntu22.04
EGL1.4
openGL ES3.1
weston9.0


一、ubuntu 下相关环境准备

1. 获取 xdg_wm_base 依赖的相关文件

之前的文章 weston 源码下载及编译 介绍了如何在ubuntu 22.04 下面编译 weston9.0 ,在编译结束后,在build 目录下会生成 xdg-shell-protocol.cxdg-shell-client-protocol.h 这两个文件,如下图所示
在这里插入图片描述
xdg-shell-protocol.cxdg-shell-client-protocol.h 这两个文件就是使用 xdg_wm_base 时所依赖的,这里就直接从weston9.0的目录下获取了,当然也可以使用wayland 相关的命令(wayland-scanner)去操作对应的.xml 文件来生成它们。

(wayland-scanner)是一个用于生成Wayland协议代码的工具。它是Wayland项目的一部分,用于根据XML描述文件生成C语言代码,以便在应用程序中使用Wayland协议。
Wayland-Scanner工具的用途是将Wayland协议的XML描述文件转换为可供应用程序使用的C语言代码。这些代码包括客户端和服务器端的接口定义、消息处理函数、数据结构等。通过使用Wayland-Scanner,开发人员可以根据自定义的Wayland协议描述文件生成所需的代码,从而实现与Wayland服务器的通信

2. 查看 ubuntu 上安装的opengles 版本

使用 glxinfo | grep “OpenGL ES” 可以查看 ubuntu 上所安装的opengles 的版本,如下图所示,代表当前 ubuntu (ubuntu22.04)上安装的是opengles版本是 opengles3.1
在这里插入图片描述

3. 查看 weston 所支持的 窗口shell 接口种类

直接执行 weston-info(后面会被wayland-info 命令取代) 命令,如下图所示,可以看到,当前ubuntu(ubuntu22.04)上所支持的窗口 shell 接口种类,其中就有 xdg_wm_base, zxdg_shell_v6 等,但是没有 wl_shell , 所以从这可以看出,wl_shell 确实已经在ubuntu22.04 上废弃使用了。
在这里插入图片描述

二、xdg_wm_base 介绍

  • xdg_wm_base是由XDG组织定义的Wayland协议接口之一,它提供了一种标准化的方法,使得窗口管理器和应用程序能够进行互动;
  • xdg_wm_base定义了与窗口管理器交互的基本功能,如创建新窗口、设置窗口标题、最大化和最小化窗口等;
  • 它鼓励窗口管理器使用更加灵活和自由的方式来处理窗口管理任务;
  • xdg_wm_base和 wl_shell 都是Wayland协议的一部分,用于定义窗口管理器(Window Manager)与应用程序之间的通信接口。它们之间的区别在于设计理念和功能,xdg_wm_base提供了更加灵活和标准化的窗口管理器接口,窗口管理器可以根据需要实现更多的功能;

三、egl_wayland_demo

1.egl_wayland_demo2_0.c

使用 opengles2.x 接口的 egl_wayland_demo2_0.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 "xdg-shell-client-protocol.h"

#define WIDTH 640
#define HEIGHT 480

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);
}

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};



/*for shell surface listener*/

static void shell_surface_ping (void *data, struct wl_shell_surface *shell_surface, uint32_t serial) 
{
   
	wl_shell_surface_pong (shell_surface, serial);
}
static void shell_surface_configure (void *data, struct wl_shell_surface *shell_surface, uint32_t edges, int32_t width, int32_t height) {
   
	struct window *window = data;
	wl_egl_window_resize (window->egl_window, width, height, 0, 0);
}
static void shell_surface_popup_done (void *data, struct wl_shell_surface *shell_surface) 
{
   

}

static struct wl_shell_surface_listener shell_surface_listener = {
   &shell_surface_ping, &shell_surface_configure, &shell_surface_popup_done};

static void create_window (struct window *window, int32_t width, int32_t height)
{
   

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

	xdg_surface_ack_configure(surface, serial);

	//window->wait_for_configure = false;
}

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_demo");
    }
	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<char> 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<char> infoLog;
		//infoLog.resize(infoLogLength);
		//glGetShaderInfoLog(vertexShader, infoLogLength, &charactersWritten, infoLog.data());
		fprintf(stderr, "Error: compiling %s: %.*s\n", "vertex", len, msg);
		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 "myVertex" to location VertexArray (0)
	glBindAttribLocation(*shaderProgram, VertexArray, "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<char> 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(EGLDisplay eglDisplay, EGLSurface eglSurface)
{
   
	GLfloat vVertices[] = {
   0.0f,0.5f,0.0f,			//vertex pointer
		-0.5f,-0.5f,0.0f,
		0.5f,-0.5f,0.0f};

	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(VertexArray);
	glVertexAttribPointer(VertexArray, 3, GL_FLOAT, GL_FALSE, 0, vVertices);
	glDrawArrays(GL_TRIANGLES, 0, 3);			//draw a triangle

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

	return true;

}

bool render(GLuint shaderProgram, EGLDisplay eglDisplay, EGLSurface eglSurface)
{
   
	// Renders a triangle for 800 frames using the state setup in the previous function
	for (int i = 0; i < 800; ++i)
	{
   
		wl_display_dispatch_pending(display);
		if (!renderScene(eglDisplay, eglSurface)) {
    return false; }
	}
	return true;
}

void deInitializeGLState(GLuint shaderProgram)
{
   
	// Frees the OpenGL handles for the program
	glDeleteProgram(shaderProgram);
}

void releaseEGLState(EGLDisplay eglDisplay)
{
   
	if (eglDisplay != NULL)
	{
   
		// To release the resources in the context, first the context has to be released from its binding with the current thread.
		eglMakeCurrent(eglDisplay, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT);

		// Terminate the display, and any resources associated with it (including the EGLContext)
		eglTerminate(eglDisplay);
	}
}



int main()
{
   
	/* EGL variables*/
	EGLDisplay eglDisplay;
	EGLConfig eglConfig;
	EGLSurface eglSurface;
	EGLContext context;
	struct window window;

	//wayland client init
	if(!initializeWindow(&window))
	{
   
		printf("initializeWindow failed\n");
		return -1;
	}

	//egl init	
	eglDisplay = eglGetDisplay(display);
	if (eglDisplay == EGL_NO_DISPLAY)
	{
   
		printf("Failed to get an EGLDisplay\n");
		return -1;
	}

	EGLint eglMajorVersion = 0;
	EGLint eglMinorVersion = 0;
    if (!eglInitialize(eglDisplay, &eglMajorVersion, &eglMinorVersion))
    {
   
        printf("Failed to initialize the EGLDisplay\n");
        return -1;
    } else {
   
        printf(" EGL%d.%d\n", eglMajorVersion, eglMinorVersion);
        printf(" EGL_CLIENT_APIS: %s\n", eglQueryString(eglDisplay, EGL_CLIENT_APIS));
        printf(" EGL_VENDOR: %s\n", eglQueryString(eglDisplay,  EGL_VENDOR));
        printf(" EGL_VERSION: %s\n", eglQueryString(eglDisplay,  EGL_VERSION));
        printf(" EGL_EXTENSIONS: %s\n", eglQueryString(eglDisplay,  EGL_EXTENSIONS));
    }

    int result = EGL_FALSE;
    result = eglBindAPI(EGL_OPENGL_ES_API);
    if (result != EGL_TRUE) {
    
        printf("eglBindAPI failed\n");
        return -1; 
    }
 
	const EGLint configurationAttributes[] = {
    EGL_SURFACE_TYPE, EGL_WINDOW_BIT, EGL_RENDERABLE_TYPE, EGL_OPENGL_ES2_BIT, EGL_NONE };
	EGLint configsReturned;
	if (!eglChooseConfig(eglDisplay, configurationAttributes, &eglConfig, 1, &configsReturned) || (configsReturned != 1))
	{
   
		printf("Failed to choose a suitable config\n");
		return -1;
	}

	EGLint contextAttributes[] = {
    EGL_CONTEXT_CLIENT_VERSION, 2, EGL_NONE };
	context = eglCreateContext(eglDisplay, eglConfig, NULL, contextAttributes);

	if(!createEGLSurface(eglDisplay, eglConfig, &eglSurface, &window))
	{
   
		printf("Failed to create EGLSurface\n");
		return -1;
	}

	eglMakeCurrent(eglDisplay, eglSurface, eglSurface, context);
 
    const GLubyte* version = glGetString(GL_VERSION);
    if (version != NULL) {
   
        printf("OpenGL ES version: %s\n", version);
    } else {
   
        printf("Failed to get OpenGL ES version\n");
    }

	// opengles init
	GLuint shaderProgram = 0;
	opengles_init(&shaderProgram);

	//render
	if(!render(shaderProgram, eglDisplay, eglSurface)) {
   
		printf("=========render failed\n");
	}

	//clean up
	deInitializeGLState(shaderProgram);

	// Release the EGL State
	releaseEGLState(eglDisplay);

	// Release the Wayland connection
	releaseWaylandConnection(&window);

	return 0;
}

2.egl_wayland_demo3_0.c

使用 opengles3.x 接口的 egl_wayland_demo3_0.c 代码如下

#include <wayland-client.h>
#include <wayland-server.h>
#include <wayland-egl.h>
#include <EGL/egl.h>
#include <GLES3/gl3.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "xdg-shell-client-protocol.h"

#define WIDTH 640
#define HEIGHT 480

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

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mfbz.cn/a/339216.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

Node开发基础

1. 概述 1.1 为什么要学习服务器端开发基础 能够和后端程序员更加紧密的配合 网站业务逻辑前置&#xff0c;学习前端技术需要后端技术支撑 扩宽知识视野&#xff0c;能够站在更高的角度审视整个项目 1.2 服务器端开发要做的事情 实现网站的业务逻辑 ---网站登录部分&#…

[pytorch入门] 2. tensorboard

tensorboard简介 TensorBoard 是一组用于数据可视化的工具。它包含在流行的开源机器学习库 Tensorflow 中.但是也可以独立安装&#xff0c;服务Pytorch等其他的框架 可以常常用来观察训练过程中每一阶段如何输出的 安装pip install tensorboard启动tensorboard --logdir<d…

LeetCode面试题05.06

美好的一天&#xff0c;从力扣开始 王子公主请看题 整数转换。编写一个函数&#xff0c;确定需要改变几个位才能将整数A转成整数B。 示例1: 输入&#xff1a;A 29 &#xff08;或者0b11101&#xff09;, B 15&#xff08;或者0b01111&#xff09;输出&#xff1a;2示例2: 输…

深度求索开源国内首个 MoE 大模型 | DeepSeekMoE:在专家混合语言模型中实现终极专家专业化

文章目录 一、前言二、主要内容三、总结 &#x1f349; CSDN 叶庭云&#xff1a;https://yetingyun.blog.csdn.net/ 一、前言 在大语言模型时代&#xff0c;混合专家模型&#xff08;MoE&#xff09;是一种很有前途的架构&#xff0c;用于在扩展模型参数时管理计算成本。然而&a…

【算法专栏学习】成贤学院,程序员的福利站到了,判断子序列,经典算法实战。

&#x1f3c6;作者简介&#xff0c;普修罗双战士&#xff0c;一直追求不断学习和成长&#xff0c;在技术的道路上持续探索和实践。 &#x1f3c6;多年互联网行业从业经验&#xff0c;历任核心研发工程师&#xff0c;项目技术负责人。 &#x1f389;欢迎 &#x1f44d;点赞✍评论…

使用宝塔面板安装wiki.js详细教程

因为在安装过程中遇到了一些问题&#xff0c;花费了很长时间在解决问题上。根据这篇教程可以少踩很多坑。点赞加关注吧。 准备运行环境 Nodejs 在宝塔面板的软件商店中找到nodejs版本管理器并安装。 点击设置&#xff0c;选择一个稳定版安装。 PostgreSQL 官方推荐的数据库是…

Nginx之负载均衡、静态代理与动态代理配置

Nginx之负载均衡配置 文章目录 Nginx之负载均衡配置1. 负载均衡基本配置1. 配置upstream2. 配置location3. 访问 2. Nginx常用负载均衡策略1. 轮询(默认)2. 权重3. ip_hash策略4. 最少连接策略5. 负载均衡其他几个配置 3. 静态代理1. 基于静态在一文件后缀的匹配2. 基于静态资源…

Python - 深夜数据结构与算法之 高级字符串

目录 一.引言 二.经典算法实战 1.Longest-Common-Sub-Seq [1143] 2.Edit-Distance [72] 3.Longest-Palindromic-Str [5] 4.Distinct-Sub-Seq [115] 5.Regular-Exp-Match [10] 三.总结 一.引言 上一节介绍了字符串的基本操作&#xff0c;本文介绍字符串更复杂的一些操作…

YOLOv8改进 | 主干篇 | 低照度图像增强网络SCINet改进黑暗目标检测(全网独家首发)

一、本文介绍 本文给大家带来的改进机制是低照度图像增强网络SCINet,SCINet(自校正照明网络)是一种专为低光照图像增强设计的框架。它通过级联照明学习过程和权重共享机制来处理图像,优化了照明部分以提升图像质量。我将该网络集成在YOLOv8的主干上针对于图像的输入进行增…

BurpSuite Pro 2023.12.1.2下载与破解-最新版BurpSuite Pro

本文在我的博客地址是&#xff1a;https://h4cker.zip/post/f05ae2e66da503f6383dffe48cdf5bac 上一次BurpSuite的分享还是在2020年 由于CSDN有防盗链&#xff0c;我自己的博客都无法访问这篇博文的图片了 至于为什么再写一次&#xff0c;是因为我看到群里这张图&#xff1a;…

高效能方法 - 任务清单优先级

任务清单是有优先级的&#xff0c;首先要尽所能保证A级别的事项完成&#xff0c;或许不能估计B级或者C级&#xff0c;那这结果也是不错的。 博恩崔西在《吃掉那只青蛙》一书中指出&#xff1a;在你决定要做什么&#xff0c;并对其进行排序的时候&#xff0c;你首要解决那些最难…

腾讯云服务器价格查询,2024更新

腾讯云服务器租用优惠价格表&#xff1a;轻量应用服务器2核2G3M价格62元一年、2核2G4M价格118元一年&#xff0c;540元三年、2核4G5M带宽218元一年&#xff0c;2核4G5M带宽756元三年、轻量4核8G12M服务器646元15个月&#xff1b;云服务器CVM S5实例2核2G配置280.8元一年、2核4G…

x-cmd pkg | yq - 命令行 YAML处理工具

目录 简介首次用户支持格式转换友好的显示和操作语法与 jq 类似竞品和相关作品进一步阅读 简介 yq (YAML Query) 是一个轻量级的 YAML、JSON、XML 处理器&#xff0c;主要用于查询和提取 YAML 数据。 本 yq 的包来自 mikefarah/yq 项目&#xff0c;语法类似于 jq 。相比 kisly…

《WebKit 技术内幕》之八(2):硬件加速机制

2 Chromium的硬件加速机制 2.1 GraphicsLayer的支持 GraphicsLayer对象是对一个渲染后端存储中某一层的抽象&#xff0c;同众多其他WebKit所定义的抽象类一样&#xff0c;在WebKit移植中&#xff0c;它还需要具体的实现类来支持该类所要提供的功能。为了完成这一功能&#x…

python if条件判断的基础及应用

当前版本&#xff1a; Python 3.8.4 简介 if 语句是一种用于根据一个或多个条件的结果来执行不同代码块的控制流结构&#xff0c;它会检查给定的条件是否为真。如果条件为真&#xff0c;则执行与之关联的代码块&#xff1b;如果条件为假&#xff0c;则执行与之关联的其他代码块…

工作小计- RGB相关算子实现

项目中的模型一直都是直接操作NV12的yuv格式数据&#xff0c;这次的模型只支持RGB格式的输入&#xff0c;正好来自己实现对应的算子。 这里记录一下对应算子的实现过程&#xff0c;主要涉及到NV12到RGB的变换&#xff0c;RGB的crop/resize操作&#xff0c;对于数据的Norm/ToFlo…

python 正则表达式学习(1)

正则表达式是一个特殊的字符序列&#xff0c;它能帮助你方便的检查一个字符串是否与某种模式匹配。 1. 特殊符号 1.1 符号含义 模式描述^匹配字符串的开头$匹配字符串的末尾.匹配任意字符&#xff0c;除了换行符&#xff0c;当re.DOTALL标记被指定时&#xff0c;则可以匹配包…

芯片工程系列(1)封装基础知识、分来、步骤与方法.md

英文缩写 环氧树脂模塑料&#xff08;Epoxy Molding Compound&#xff0c;EMC&#xff09;引线框架封装&#xff08;Leadframe&#xff09;&#xff0c;基板封装&#xff08;Substrate&#xff09;&#xff0c;Substrate 基板晶圆片级芯片规模封装&#xff08;Wafer Level Chi…

ESP32-UDP通信 (Arduino)

ESP32配置UDP通信 介绍 用户数据报协议UDP UDP&#xff08;User Datagram Protocol&#xff09;是一种在计算机网络中常用的传输层协议&#xff0c;它与TCP&#xff08;Transmission Control Protocol&#xff09;一样属于传输层协议的一种。UDP主要用于在网络中传输数据&…

小程序学习-20

建议每次构建npm之前都先删除miniprogram_npm
最新文章