aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDrew DeVault <sir@cmpwn.com>2017-06-23 14:25:55 -0400
committerDrew DeVault <sir@cmpwn.com>2017-06-23 14:25:55 -0400
commit5a2796266f6f88464396a9cd255dd9d0dedba749 (patch)
tree27b1036ed11709332c2fb359f02eade319790cf9
parent2aafb5dd19f8a3e3436f8843071fa2076a6d2716 (diff)
Support wl_shm pixel formats in gles2 renderer
-rw-r--r--example/rotation.c2
-rw-r--r--include/render/gles2.h23
-rw-r--r--include/wlr/render.h5
-rw-r--r--include/wlr/render/interface.h5
-rw-r--r--render/CMakeLists.txt1
-rw-r--r--render/gles2/pixel_format.c45
-rw-r--r--render/gles2/renderer.c28
-rw-r--r--render/gles2/shaders.c15
-rw-r--r--render/gles2/surface.c15
9 files changed, 101 insertions, 38 deletions
diff --git a/example/rotation.c b/example/rotation.c
index b8c43d4c..84137078 100644
--- a/example/rotation.c
+++ b/example/rotation.c
@@ -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);
diff --git a/include/render/gles2.h b/include/render/gles2.h
index bd0106b3..7b835209 100644
--- a/include/render/gles2.h
+++ b/include/render/gles2.h
@@ -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(...) \
diff --git a/include/wlr/render.h b/include/wlr/render.h
index 496e3638..bb333723 100644
--- a/include/wlr/render.h
+++ b/include/wlr/render.h
@@ -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.
diff --git a/include/wlr/render/interface.h b/include/wlr/render/interface.h
index c7fa54d6..f2168dcd 100644
--- a/include/wlr/render/interface.h
+++ b/include/wlr/render/interface.h
@@ -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
diff --git a/render/CMakeLists.txt b/render/CMakeLists.txt
index 70ebced2..63412b61 100644
--- a/render/CMakeLists.txt
+++ b/render/CMakeLists.txt
@@ -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
)
diff --git a/render/gles2/pixel_format.c b/render/gles2/pixel_format.c
new file mode 100644
index 00000000..a0b9d09f
--- /dev/null
+++ b/render/gles2/pixel_format.c
@@ -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;
+}
diff --git a/render/gles2/renderer.c b/render/gles2/renderer.c
index f3906125..897dc3b8 100644
--- a/render/gles2/renderer.c
+++ b/render/gles2/renderer.c
@@ -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;
diff --git a/render/gles2/shaders.c b/render/gles2/shaders.c
index 62712230..f5e61dd6 100644
--- a/render/gles2/shaders.c
+++ b/render/gles2/shaders.c
@@ -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;"
"}";
diff --git a/render/gles2/surface.c b/render/gles2/surface.c
index 278b3dc3..8c2f459f 100644
--- a/render/gles2/surface.c
+++ b/render/gles2/surface.c
@@ -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) {