mirror of
https://github.com/hyprwm/wlroots-hyprland.git
synced 2024-11-04 20:55:58 +01: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…
Reference in a new issue