Support wl_shm pixel formats in gles2 renderer

This commit is contained in:
Drew DeVault 2017-06-23 14:25:55 -04:00
parent 2aafb5dd19
commit 5a2796266f
9 changed files with 101 additions and 38 deletions

View file

@ -204,7 +204,7 @@ int main(int argc, char *argv[]) {
state.renderer = wlr_gles2_renderer_init(); state.renderer = wlr_gles2_renderer_init();
state.cat_texture = wlr_render_surface_init(state.renderer); 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); cat_tex.width, cat_tex.height, cat_tex.pixel_data);
compositor_run(&compositor); compositor_run(&compositor);

View file

@ -6,19 +6,38 @@
#include <GLES2/gl2.h> #include <GLES2/gl2.h>
#include <wlr/render.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_state {
struct wlr_surface *wlr_surface; struct wlr_surface *wlr_surface;
GLuint tex_id; 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(); struct wlr_surface *gles2_surface_init();
extern const GLchar quad_vertex_src[]; extern const GLchar quad_vertex_src[];
extern const GLchar quad_fragment_src[]; extern const GLchar quad_fragment_src[];
extern const GLchar ellipse_fragment_src[]; extern const GLchar ellipse_fragment_src[];
extern const GLchar vertex_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); bool _gles2_flush_errors(const char *file, int line);
#define gles2_flush_errors(...) \ #define gles2_flush_errors(...) \

View file

@ -63,8 +63,9 @@ struct wlr_surface {
* Attaches a pixel buffer to this surface. The buffer may be discarded after * Attaches a pixel buffer to this surface. The buffer may be discarded after
* calling this function. * calling this function.
*/ */
bool wlr_surface_attach_pixels(struct wlr_surface *surf, uint32_t format, bool wlr_surface_attach_pixels(struct wlr_surface *surf,
int width, int height, const unsigned char *pixels); 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 * Attaches pixels from a wl_shm_buffer to this surface. The shm buffer may be
* invalidated after calling this function. * invalidated after calling this function.

View file

@ -32,8 +32,9 @@ struct wlr_renderer *wlr_renderer_init(struct wlr_renderer_state *state,
struct wlr_renderer_impl *impl); struct wlr_renderer_impl *impl);
struct wlr_surface_impl { struct wlr_surface_impl {
bool (*attach_pixels)(struct wlr_surface_state *state, uint32_t format, bool (*attach_pixels)(struct wlr_surface_state *state,
int width, int height, const unsigned char *pixels); enum wl_shm_format format, int width, int height,
const unsigned char *pixels);
bool (*attach_shm)(struct wlr_surface_state *state, uint32_t format, bool (*attach_shm)(struct wlr_surface_state *state, uint32_t format,
struct wl_shm_buffer *shm); struct wl_shm_buffer *shm);
// TODO: egl // TODO: egl

View file

@ -5,5 +5,6 @@ add_library(wlr-render STATIC
gles2/shaders.c gles2/shaders.c
gles2/renderer.c gles2/renderer.c
gles2/surface.c gles2/surface.c
gles2/pixel_format.c
gles2/util.c gles2/util.c
) )

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

View file

@ -10,12 +10,7 @@
#include <wlr/util/log.h> #include <wlr/util/log.h>
#include "render/gles2.h" #include "render/gles2.h"
static struct { struct shaders shaders;
bool initialized;
GLuint rgb, rgba;
GLuint quad;
GLuint ellipse;
} shaders;
static bool compile_shader(GLuint type, const GLchar *src, GLuint *shader) { static bool compile_shader(GLuint type, const GLchar *src, GLuint *shader) {
*shader = GL_CALL(glCreateShader(type)); *shader = GL_CALL(glCreateShader(type));
@ -58,10 +53,10 @@ static void init_default_shaders() {
if (shaders.initialized) { if (shaders.initialized) {
return; return;
} }
if (!compile_program(vertex_src, fragment_src_RGB, &shaders.rgb)) { if (!compile_program(vertex_src, fragment_src_rgba, &shaders.rgba)) {
goto error; goto error;
} }
if (!compile_program(vertex_src, fragment_src_RGBA, &shaders.rgba)) { if (!compile_program(vertex_src, fragment_src_rgbx, &shaders.rgbx)) {
goto error; goto error;
} }
if (!compile_program(quad_vertex_src, quad_fragment_src, &shaders.quad)) { 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, static bool wlr_gles2_render_surface(struct wlr_renderer_state *state,
struct wlr_surface *surface, const float (*matrix)[16]) { struct wlr_surface *surface, const float (*matrix)[16]) {
assert(surface && surface->valid); 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); wlr_surface_bind(surface);
GL_CALL(glUniformMatrix4fv(0, 1, GL_FALSE, *matrix)); GL_CALL(glUniformMatrix4fv(0, 1, GL_FALSE, *matrix));
// TODO: source alpha from somewhere else I guess
GL_CALL(glUniform1f(2, 1.0f));
draw_quad(); draw_quad();
return true; return true;
} }
@ -169,6 +153,8 @@ static const enum wl_shm_format *wlr_gles2_formats(
static enum wl_shm_format formats[] = { static enum wl_shm_format formats[] = {
WL_SHM_FORMAT_ARGB8888, WL_SHM_FORMAT_ARGB8888,
WL_SHM_FORMAT_XRGB8888, WL_SHM_FORMAT_XRGB8888,
WL_SHM_FORMAT_ABGR8888,
WL_SHM_FORMAT_XBGR8888,
}; };
*len = sizeof(formats) / sizeof(formats[0]); *len = sizeof(formats) / sizeof(formats[0]);
return formats; return formats;

View file

@ -20,7 +20,6 @@ const GLchar quad_vertex_src[] =
" vec4(i0.z, i1.z, i2.z, i3.z)," " vec4(i0.z, i1.z, i2.z, i3.z),"
" vec4(i0.w, i1.w, i2.w, i3.w)" " vec4(i0.w, i1.w, i2.w, i3.w)"
" );" " );"
""
" return outMatrix;" " return outMatrix;"
"}" "}"
"void main() {" "void main() {"
@ -37,8 +36,7 @@ const GLchar quad_fragment_src[] =
" gl_FragColor = v_color;" " gl_FragColor = v_color;"
"}"; "}";
// Colored ellipses (TODO) // Colored ellipses
const GLchar ellipse_fragment_src[] = const GLchar ellipse_fragment_src[] =
"precision mediump float;" "precision mediump float;"
"varying vec4 v_color;" "varying vec4 v_color;"
@ -74,18 +72,21 @@ const GLchar vertex_src[] =
" v_texcoord = texcoord;" " v_texcoord = texcoord;"
"}"; "}";
const GLchar fragment_src_RGB[] = const GLchar fragment_src_rgba[] =
"precision mediump float;" "precision mediump float;"
"varying vec2 v_texcoord;" "varying vec2 v_texcoord;"
"uniform sampler2D tex;" "uniform sampler2D tex;"
"uniform float alpha;"
"void main() {" "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;" "precision mediump float;"
"varying vec2 v_texcoord;" "varying vec2 v_texcoord;"
"uniform sampler2D tex;" "uniform sampler2D tex;"
"uniform float alpha;"
"void main() {" "void main() {"
" gl_FragColor = texture2D(tex, v_texcoord);" " gl_FragColor.rgb = alpha * texture2D(tex, v_texcoord).rgb;"
" gl_FragColor.a = alpha;"
"}"; "}";

View file

@ -7,18 +7,26 @@
#include <wlr/render.h> #include <wlr/render.h>
#include <wlr/render/interface.h> #include <wlr/render/interface.h>
#include <wlr/render/matrix.h> #include <wlr/render/matrix.h>
#include <wlr/util/log.h>
#include "render/gles2.h" #include "render/gles2.h"
static bool gles2_surface_attach_pixels(struct wlr_surface_state *surface, 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); 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->width = width;
surface->wlr_surface->height = height; surface->wlr_surface->height = height;
surface->wlr_surface->format = format; surface->wlr_surface->format = format;
surface->pixel_format = fmt;
GL_CALL(glGenTextures(1, &surface->tex_id)); GL_CALL(glGenTextures(1, &surface->tex_id));
GL_CALL(glBindTexture(GL_TEXTURE_2D, surface->tex_id)); GL_CALL(glBindTexture(GL_TEXTURE_2D, surface->tex_id));
GL_CALL(glTexImage2D(GL_TEXTURE_2D, 0, format, width, height, 0, GL_CALL(glTexImage2D(GL_TEXTURE_2D, 0, fmt->gl_format, width, height, 0,
format, GL_UNSIGNED_BYTE, pixels)); fmt->gl_format, fmt->gl_type, pixels));
surface->wlr_surface->valid = true; surface->wlr_surface->valid = true;
return 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(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_MIN_FILTER, GL_LINEAR));
GL_CALL(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_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) { static void gles2_surface_destroy(struct wlr_surface_state *surface) {