From 1fba2b78a8414802a20fac4c40f79a1ba1d570d7 Mon Sep 17 00:00:00 2001 From: Jason Francis Date: Thu, 1 Aug 2019 11:07:00 -0400 Subject: [PATCH] swap RGB -> BGR when necessary --- src/main.c | 2 ++ src/outputs.c | 9 ++++++++- src/render.c | 20 +++++++++++++++++++- src/wdisplays.h | 2 ++ 4 files changed, 31 insertions(+), 2 deletions(-) diff --git a/src/main.c b/src/main.c index c71c6dc..35a9198 100644 --- a/src/main.c +++ b/src/main.c @@ -824,6 +824,7 @@ static void canvas_render(GtkGLArea *area, GdkGLContext *context, gpointer data) render->preview = true; render->updated_at = tick; render->y_invert = frame->y_invert; + render->swap_rgb = frame->swap_rgb; } } else if (render->preview || render->pixels == NULL || size_changed(render)) { @@ -839,6 +840,7 @@ static void canvas_render(GtkGLArea *area, GdkGLContext *context, gpointer data) render->tex_stride = cairo_image_surface_get_stride(head->surface); render->updated_at = tick; render->y_invert = false; + render->swap_rgb = false; } } } diff --git a/src/outputs.c b/src/outputs.c index 02aa7c7..ea3b549 100644 --- a/src/outputs.c +++ b/src/outputs.c @@ -174,8 +174,13 @@ static void capture_buffer(void *data, struct zwlr_screencopy_frame_v1 *copy_frame, uint32_t format, uint32_t width, uint32_t height, uint32_t stride) { struct wd_frame *frame = data; - char *shm_name = NULL; + + if (format != WL_SHM_FORMAT_ARGB8888 && format != WL_SHM_FORMAT_XRGB8888 && + format != WL_SHM_FORMAT_ABGR8888 && format != WL_SHM_FORMAT_XBGR8888) { + goto err; + } + if (asprintf(&shm_name, "/wd-%s", frame->output->name) == -1) { fprintf(stderr, "asprintf: %s\n", strerror(errno)); shm_name = NULL; @@ -199,6 +204,8 @@ static void capture_buffer(void *data, frame->stride = stride; frame->width = width; frame->height = height; + frame->swap_rgb = format == WL_SHM_FORMAT_ABGR8888 + || format == WL_SHM_FORMAT_XBGR8888; return; err: diff --git a/src/render.c b/src/render.c index dee1efb..eb333bb 100644 --- a/src/render.c +++ b/src/render.c @@ -53,6 +53,7 @@ struct wd_gl_data { GLuint texture_uv_attribute; GLuint texture_screen_size_uniform; GLuint texture_texture_uniform; + GLuint texture_color_transform_uniform; GLuint buffers[2]; @@ -93,8 +94,9 @@ void main(void) {\n\ static const char *texture_fragment_shader_src = "\ varying vec2 uv_out;\n\ uniform sampler2D texture;\n\ +uniform mat4 color_transform;\n\ void main(void) {\n\ - gl_FragColor = texture2D(texture, uv_out);\n\ + gl_FragColor = texture2D(texture, uv_out) * color_transform;\n\ }"; static GLuint gl_make_shader(GLenum type, const char *src) { @@ -182,6 +184,8 @@ struct wd_gl_data *wd_gl_setup(void) { "screen_size"); res->texture_texture_uniform = glGetUniformLocation(res->texture_program, "texture"); + res->texture_color_transform_uniform = glGetUniformLocation( + res->texture_program, "color_transform"); glGenBuffers(2, res->buffers); glBindBuffer(GL_ARRAY_BUFFER, res->buffers[0]); @@ -195,6 +199,18 @@ struct wd_gl_data *wd_gl_setup(void) { return res; } +static const GLfloat TRANSFORM_RGB[16] = { + 1, 0, 0, 0, + 0, 1, 0, 0, + 0, 0, 1, 0, + 0, 0, 0, 1}; + +static const GLfloat TRANSFORM_BGR[16] = { + 0, 0, 1, 0, + 0, 1, 0, 0, + 1, 0, 0, 0, + 0, 0, 0, 1}; + #define PUSH_POINT(_start, _a, _b) \ *((_start)++) = (_a);\ *((_start)++) = (_b); @@ -278,6 +294,8 @@ void wd_gl_render(struct wd_gl_data *res, struct wd_render_data *info, 0, GL_RGBA, GL_UNSIGNED_BYTE, head->pixels); glPixelStorei(GL_UNPACK_ROW_LENGTH_EXT, 0); } + glUniformMatrix4fv(res->texture_color_transform_uniform, 1, GL_FALSE, + head->swap_rgb ? TRANSFORM_RGB : TRANSFORM_BGR); glDrawArrays(GL_TRIANGLES, i * 6, 6); } } diff --git a/src/wdisplays.h b/src/wdisplays.h index 3131a64..896d578 100644 --- a/src/wdisplays.h +++ b/src/wdisplays.h @@ -90,6 +90,7 @@ struct wd_frame { uint8_t *pixels; uint64_t tick; bool y_invert; + bool swap_rgb; }; struct wd_head_config { @@ -154,6 +155,7 @@ struct wd_render_head_data { unsigned tex_height; bool preview; bool y_invert; + bool swap_rgb; uint64_t updated_at; bool hovered;