mirror of
				https://gitlab.freedesktop.org/wlroots/wlroots.git
				synced 2025-11-03 09:01:40 -05:00 
			
		
		
		
	Support wl_shm pixel formats in gles2 renderer
This commit is contained in:
		
							parent
							
								
									2aafb5dd19
								
							
						
					
					
						commit
						5a2796266f
					
				
					 9 changed files with 101 additions and 38 deletions
				
			
		| 
						 | 
				
			
			@ -204,7 +204,7 @@ int main(int argc, char *argv[]) {
 | 
			
		|||
 | 
			
		||||
	state.renderer = wlr_gles2_renderer_init();
 | 
			
		||||
	state.cat_texture = wlr_render_surface_init(state.renderer);
 | 
			
		||||
	wlr_surface_attach_pixels(state.cat_texture, GL_RGBA,
 | 
			
		||||
	wlr_surface_attach_pixels(state.cat_texture, WL_SHM_FORMAT_ABGR8888,
 | 
			
		||||
		cat_tex.width, cat_tex.height, cat_tex.pixel_data);
 | 
			
		||||
 | 
			
		||||
	compositor_run(&compositor);
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -6,19 +6,38 @@
 | 
			
		|||
#include <GLES2/gl2.h>
 | 
			
		||||
#include <wlr/render.h>
 | 
			
		||||
 | 
			
		||||
struct pixel_format {
 | 
			
		||||
	uint32_t wl_format;
 | 
			
		||||
	GLint gl_format, gl_type;
 | 
			
		||||
	int depth, bpp;
 | 
			
		||||
	GLuint *shader;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
struct wlr_surface_state {
 | 
			
		||||
	struct wlr_surface *wlr_surface;
 | 
			
		||||
	GLuint tex_id;
 | 
			
		||||
	const struct pixel_format *pixel_format;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
struct shaders {
 | 
			
		||||
	bool initialized;
 | 
			
		||||
	GLuint rgba, rgbx;
 | 
			
		||||
	GLuint quad;
 | 
			
		||||
	GLuint ellipse;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
extern struct shaders shaders;
 | 
			
		||||
 | 
			
		||||
const struct pixel_format *gl_format_for_wl_format(enum wl_shm_format fmt);
 | 
			
		||||
 | 
			
		||||
struct wlr_surface *gles2_surface_init();
 | 
			
		||||
 | 
			
		||||
extern const GLchar quad_vertex_src[];
 | 
			
		||||
extern const GLchar quad_fragment_src[];
 | 
			
		||||
extern const GLchar ellipse_fragment_src[];
 | 
			
		||||
extern const GLchar vertex_src[];
 | 
			
		||||
extern const GLchar fragment_src_RGB[];
 | 
			
		||||
extern const GLchar fragment_src_RGBA[];
 | 
			
		||||
extern const GLchar fragment_src_rgba[];
 | 
			
		||||
extern const GLchar fragment_src_rgbx[];
 | 
			
		||||
 | 
			
		||||
bool _gles2_flush_errors(const char *file, int line);
 | 
			
		||||
#define gles2_flush_errors(...) \
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -63,8 +63,9 @@ struct wlr_surface {
 | 
			
		|||
 * Attaches a pixel buffer to this surface. The buffer may be discarded after
 | 
			
		||||
 * calling this function.
 | 
			
		||||
 */
 | 
			
		||||
bool wlr_surface_attach_pixels(struct wlr_surface *surf, uint32_t format,
 | 
			
		||||
		int width, int height, const unsigned char *pixels);
 | 
			
		||||
bool wlr_surface_attach_pixels(struct wlr_surface *surf,
 | 
			
		||||
		enum wl_shm_format format, int width, int height,
 | 
			
		||||
		const unsigned char *pixels);
 | 
			
		||||
/**
 | 
			
		||||
 * Attaches pixels from a wl_shm_buffer to this surface. The shm buffer may be
 | 
			
		||||
 * invalidated after calling this function.
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -32,8 +32,9 @@ struct wlr_renderer *wlr_renderer_init(struct wlr_renderer_state *state,
 | 
			
		|||
		struct wlr_renderer_impl *impl);
 | 
			
		||||
 | 
			
		||||
struct wlr_surface_impl {
 | 
			
		||||
	bool (*attach_pixels)(struct wlr_surface_state *state, uint32_t format,
 | 
			
		||||
		int width, int height, const unsigned char *pixels);
 | 
			
		||||
	bool (*attach_pixels)(struct wlr_surface_state *state,
 | 
			
		||||
		enum wl_shm_format format, int width, int height,
 | 
			
		||||
		const unsigned char *pixels);
 | 
			
		||||
	bool (*attach_shm)(struct wlr_surface_state *state, uint32_t format,
 | 
			
		||||
		struct wl_shm_buffer *shm);
 | 
			
		||||
	// TODO: egl
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -5,5 +5,6 @@ add_library(wlr-render STATIC
 | 
			
		|||
    gles2/shaders.c
 | 
			
		||||
    gles2/renderer.c
 | 
			
		||||
    gles2/surface.c
 | 
			
		||||
    gles2/pixel_format.c
 | 
			
		||||
    gles2/util.c
 | 
			
		||||
)
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
							
								
								
									
										45
									
								
								render/gles2/pixel_format.c
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										45
									
								
								render/gles2/pixel_format.c
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,45 @@
 | 
			
		|||
#include <GLES2/gl2.h>
 | 
			
		||||
#include <GLES2/gl2ext.h>
 | 
			
		||||
#include "render/gles2.h"
 | 
			
		||||
 | 
			
		||||
// Adapted from weston
 | 
			
		||||
struct pixel_format formats[] = {
 | 
			
		||||
	{
 | 
			
		||||
		.wl_format = WL_SHM_FORMAT_ARGB8888,
 | 
			
		||||
		.depth = 32,
 | 
			
		||||
		.bpp = 32,
 | 
			
		||||
		.gl_format = GL_BGRA_EXT,
 | 
			
		||||
		.gl_type = GL_UNSIGNED_BYTE,
 | 
			
		||||
		.shader = &shaders.rgba
 | 
			
		||||
	},
 | 
			
		||||
	{
 | 
			
		||||
		.wl_format = WL_SHM_FORMAT_XRGB8888,
 | 
			
		||||
		.depth = 24,
 | 
			
		||||
		.bpp = 32,
 | 
			
		||||
		.gl_format = GL_BGRA_EXT,
 | 
			
		||||
		.gl_type = GL_UNSIGNED_BYTE,
 | 
			
		||||
		.shader = &shaders.rgbx
 | 
			
		||||
	},
 | 
			
		||||
	{
 | 
			
		||||
		.wl_format = WL_SHM_FORMAT_XBGR8888,
 | 
			
		||||
		.gl_format = GL_RGBA,
 | 
			
		||||
		.gl_type = GL_UNSIGNED_BYTE,
 | 
			
		||||
		.shader = &shaders.rgbx
 | 
			
		||||
	},
 | 
			
		||||
	{
 | 
			
		||||
		.wl_format = WL_SHM_FORMAT_ABGR8888,
 | 
			
		||||
		.gl_format = GL_RGBA,
 | 
			
		||||
		.gl_type = GL_UNSIGNED_BYTE,
 | 
			
		||||
		.shader = &shaders.rgba
 | 
			
		||||
	},
 | 
			
		||||
};
 | 
			
		||||
// TODO: more pixel formats
 | 
			
		||||
 | 
			
		||||
const struct pixel_format *gl_format_for_wl_format(enum wl_shm_format fmt) {
 | 
			
		||||
	for (size_t i = 0; i < sizeof(formats) / sizeof(*formats); ++i) {
 | 
			
		||||
		if (formats[i].wl_format == fmt) {
 | 
			
		||||
			return &formats[i];
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
	return NULL;
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -10,12 +10,7 @@
 | 
			
		|||
#include <wlr/util/log.h>
 | 
			
		||||
#include "render/gles2.h"
 | 
			
		||||
 | 
			
		||||
static struct {
 | 
			
		||||
	bool initialized;
 | 
			
		||||
	GLuint rgb, rgba;
 | 
			
		||||
	GLuint quad;
 | 
			
		||||
	GLuint ellipse;
 | 
			
		||||
} shaders;
 | 
			
		||||
struct shaders shaders;
 | 
			
		||||
 | 
			
		||||
static bool compile_shader(GLuint type, const GLchar *src, GLuint *shader) {
 | 
			
		||||
	*shader = GL_CALL(glCreateShader(type));
 | 
			
		||||
| 
						 | 
				
			
			@ -58,10 +53,10 @@ static void init_default_shaders() {
 | 
			
		|||
	if (shaders.initialized) {
 | 
			
		||||
		return;
 | 
			
		||||
	}
 | 
			
		||||
	if (!compile_program(vertex_src, fragment_src_RGB, &shaders.rgb)) {
 | 
			
		||||
	if (!compile_program(vertex_src, fragment_src_rgba, &shaders.rgba)) {
 | 
			
		||||
		goto error;
 | 
			
		||||
	}
 | 
			
		||||
	if (!compile_program(vertex_src, fragment_src_RGBA, &shaders.rgba)) {
 | 
			
		||||
	if (!compile_program(vertex_src, fragment_src_rgbx, &shaders.rgbx)) {
 | 
			
		||||
		goto error;
 | 
			
		||||
	}
 | 
			
		||||
	if (!compile_program(quad_vertex_src, quad_fragment_src, &shaders.quad)) {
 | 
			
		||||
| 
						 | 
				
			
			@ -129,21 +124,10 @@ static void draw_quad() {
 | 
			
		|||
static bool wlr_gles2_render_surface(struct wlr_renderer_state *state,
 | 
			
		||||
		struct wlr_surface *surface, const float (*matrix)[16]) {
 | 
			
		||||
	assert(surface && surface->valid);
 | 
			
		||||
	// TODO: Convert GL formats to WL_SHM formats
 | 
			
		||||
	switch (surface->format) {
 | 
			
		||||
	case GL_RGB:
 | 
			
		||||
		GL_CALL(glUseProgram(shaders.rgb));
 | 
			
		||||
		break;
 | 
			
		||||
	case GL_RGBA:
 | 
			
		||||
		GL_CALL(glUseProgram(shaders.rgba));
 | 
			
		||||
		break;
 | 
			
		||||
	default:
 | 
			
		||||
		wlr_log(L_ERROR, "No shader for this surface format");
 | 
			
		||||
		return false;
 | 
			
		||||
	}
 | 
			
		||||
	gles2_flush_errors();
 | 
			
		||||
	wlr_surface_bind(surface);
 | 
			
		||||
	GL_CALL(glUniformMatrix4fv(0, 1, GL_FALSE, *matrix));
 | 
			
		||||
	// TODO: source alpha from somewhere else I guess
 | 
			
		||||
	GL_CALL(glUniform1f(2, 1.0f));
 | 
			
		||||
	draw_quad();
 | 
			
		||||
	return true;
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -169,6 +153,8 @@ static const enum wl_shm_format *wlr_gles2_formats(
 | 
			
		|||
	static enum wl_shm_format formats[] = {
 | 
			
		||||
		WL_SHM_FORMAT_ARGB8888,
 | 
			
		||||
		WL_SHM_FORMAT_XRGB8888,
 | 
			
		||||
		WL_SHM_FORMAT_ABGR8888,
 | 
			
		||||
		WL_SHM_FORMAT_XBGR8888,
 | 
			
		||||
	};
 | 
			
		||||
	*len = sizeof(formats) / sizeof(formats[0]);
 | 
			
		||||
	return formats;
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -20,7 +20,6 @@ const GLchar quad_vertex_src[] =
 | 
			
		|||
"                 vec4(i0.z, i1.z, i2.z, i3.z),"
 | 
			
		||||
"                 vec4(i0.w, i1.w, i2.w, i3.w)"
 | 
			
		||||
"                 );"
 | 
			
		||||
""
 | 
			
		||||
"    return outMatrix;"
 | 
			
		||||
"}"
 | 
			
		||||
"void main() {"
 | 
			
		||||
| 
						 | 
				
			
			@ -37,8 +36,7 @@ const GLchar quad_fragment_src[] =
 | 
			
		|||
"  gl_FragColor = v_color;"
 | 
			
		||||
"}";
 | 
			
		||||
 | 
			
		||||
// Colored ellipses (TODO)
 | 
			
		||||
 | 
			
		||||
// Colored ellipses
 | 
			
		||||
const GLchar ellipse_fragment_src[] =
 | 
			
		||||
"precision mediump float;"
 | 
			
		||||
"varying vec4 v_color;"
 | 
			
		||||
| 
						 | 
				
			
			@ -74,18 +72,21 @@ const GLchar vertex_src[] =
 | 
			
		|||
"	v_texcoord = texcoord;"
 | 
			
		||||
"}";
 | 
			
		||||
 | 
			
		||||
const GLchar fragment_src_RGB[] =
 | 
			
		||||
const GLchar fragment_src_rgba[] =
 | 
			
		||||
"precision mediump float;"
 | 
			
		||||
"varying vec2 v_texcoord;"
 | 
			
		||||
"uniform sampler2D tex;"
 | 
			
		||||
"uniform float alpha;"
 | 
			
		||||
"void main() {"
 | 
			
		||||
"	gl_FragColor = vec4(texture2D(tex, v_texcoord).rgb, 1.0);"
 | 
			
		||||
"	gl_FragColor = alpha * texture2D(tex, v_texcoord);"
 | 
			
		||||
"}";
 | 
			
		||||
 | 
			
		||||
const GLchar fragment_src_RGBA[] =
 | 
			
		||||
const GLchar fragment_src_rgbx[] =
 | 
			
		||||
"precision mediump float;"
 | 
			
		||||
"varying vec2 v_texcoord;"
 | 
			
		||||
"uniform sampler2D tex;"
 | 
			
		||||
"uniform float alpha;"
 | 
			
		||||
"void main() {"
 | 
			
		||||
"	gl_FragColor = texture2D(tex, v_texcoord);"
 | 
			
		||||
"   gl_FragColor.rgb = alpha * texture2D(tex, v_texcoord).rgb;"
 | 
			
		||||
"   gl_FragColor.a = alpha;"
 | 
			
		||||
"}";
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -7,18 +7,26 @@
 | 
			
		|||
#include <wlr/render.h>
 | 
			
		||||
#include <wlr/render/interface.h>
 | 
			
		||||
#include <wlr/render/matrix.h>
 | 
			
		||||
#include <wlr/util/log.h>
 | 
			
		||||
#include "render/gles2.h"
 | 
			
		||||
 | 
			
		||||
static bool gles2_surface_attach_pixels(struct wlr_surface_state *surface,
 | 
			
		||||
		uint32_t format, int width, int height, const unsigned char *pixels) {
 | 
			
		||||
		enum wl_shm_format format, int width, int height,
 | 
			
		||||
		const unsigned char *pixels) {
 | 
			
		||||
	assert(surface);
 | 
			
		||||
	const struct pixel_format *fmt = gl_format_for_wl_format(format);
 | 
			
		||||
	if (!fmt || !fmt->gl_format) {
 | 
			
		||||
		wlr_log(L_ERROR, "No supported pixel format for this surface");
 | 
			
		||||
		return false;
 | 
			
		||||
	}
 | 
			
		||||
	surface->wlr_surface->width = width;
 | 
			
		||||
	surface->wlr_surface->height = height;
 | 
			
		||||
	surface->wlr_surface->format = format;
 | 
			
		||||
	surface->pixel_format = fmt;
 | 
			
		||||
	GL_CALL(glGenTextures(1, &surface->tex_id));
 | 
			
		||||
	GL_CALL(glBindTexture(GL_TEXTURE_2D, surface->tex_id));
 | 
			
		||||
	GL_CALL(glTexImage2D(GL_TEXTURE_2D, 0, format, width, height, 0,
 | 
			
		||||
			format, GL_UNSIGNED_BYTE, pixels));
 | 
			
		||||
	GL_CALL(glTexImage2D(GL_TEXTURE_2D, 0, fmt->gl_format, width, height, 0,
 | 
			
		||||
			fmt->gl_format, fmt->gl_type, pixels));
 | 
			
		||||
	surface->wlr_surface->valid = true;
 | 
			
		||||
	return true;
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -40,6 +48,7 @@ static void gles2_surface_bind(struct wlr_surface_state *surface) {
 | 
			
		|||
	GL_CALL(glBindTexture(GL_TEXTURE_2D, surface->tex_id));
 | 
			
		||||
	GL_CALL(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR));
 | 
			
		||||
	GL_CALL(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR));
 | 
			
		||||
	GL_CALL(glUseProgram(*surface->pixel_format->shader));
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void gles2_surface_destroy(struct wlr_surface_state *surface) {
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue