new backend: glx: implement IMAGE_OP_APPLY_ALPHA

Slight change to the backend_operations::fill interface.

Signed-off-by: Yuxuan Shui <yshuiv7@gmail.com>
This commit is contained in:
Yuxuan Shui 2019-05-10 08:34:58 +01:00
parent 18b1fc95ff
commit 80c7b2f7ec
No known key found for this signature in database
GPG Key ID: 37C999F617EA1A47
6 changed files with 46 additions and 19 deletions

View File

@ -259,7 +259,8 @@ void paint_all_new(session_t *ps, struct managed_win *t, bool ignore_damage) {
if (ps->o.monitor_repaint) {
reg_damage = get_damage(ps, false);
ps->backend_data->ops->fill(ps->backend_data, 0.5, 0, 0, 0.5, &reg_damage);
ps->backend_data->ops->fill(ps->backend_data,
(struct color){0.5, 0, 0, 0.5}, &reg_damage);
pixman_region32_fini(&reg_damage);
}

View File

@ -9,6 +9,7 @@
#include "driver.h"
#include "kernel.h"
#include "region.h"
#include "types.h"
#include "x.h"
typedef struct session session_t;
@ -104,8 +105,7 @@ struct backend_operations {
const region_t *reg_paint, const region_t *reg_visible);
/// Fill rectangle of target, mostly for debug purposes, optional.
void (*fill)(backend_t *backend_data, double r, double g, double b, double a,
const region_t *clip);
void (*fill)(backend_t *backend_data, struct color, const region_t *clip);
/// Blur a given region of the target.
bool (*blur)(backend_t *backend_data, double opacity, const region_t *reg_blur,

View File

@ -367,7 +367,7 @@ bool gl_blur(backend_t *base, double opacity, const region_t *reg_blur,
auto coord = ccalloc(nrects * 16, GLfloat);
auto indices = ccalloc(nrects * 6, GLuint);
x_rect_to_coords(nrects, rects, extent->x1, extent->y2, gd->width, gd->height,
gd->height, false, coord, indices);
gd->height, false, coord, indices);
GLuint vao;
glGenVertexArrays(1, &vao);
@ -575,7 +575,10 @@ static const char fill_vert[] = GLSL(330,
);
// clang-format on
void gl_fill(backend_t *base, double r, double g, double b, double a, const region_t *clip) {
/// Fill a given region in bound framebuffer.
/// @param[in] y_inverted whether the y coordinates in `clip` should be inverted
static void
_gl_fill(backend_t *base, struct color c, const region_t *clip, int height, bool y_inverted) {
int nrects;
const rect_t *rect = pixman_region32_rectangles((region_t *)clip, &nrects);
struct gl_data *gd = (void *)base;
@ -587,7 +590,8 @@ void gl_fill(backend_t *base, double r, double g, double b, double a, const regi
GLuint bo[2];
glGenBuffers(2, bo);
glUseProgram(gd->fill_shader.prog);
glUniform4f(gd->fill_shader.color_loc, (GLfloat)r, (GLfloat)g, (GLfloat)b, (GLfloat)a);
glUniform4f(gd->fill_shader.color_loc, (GLfloat)c.red, (GLfloat)c.green,
(GLfloat)c.blue, (GLfloat)c.alpha);
glEnableVertexAttribArray((GLuint)gd->fill_shader.in_coord_loc);
glBindBuffer(GL_ARRAY_BUFFER, bo[0]);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, bo[1]);
@ -595,11 +599,11 @@ void gl_fill(backend_t *base, double r, double g, double b, double a, const regi
auto coord = ccalloc(nrects * 8, GLint);
auto indices = ccalloc(nrects * 6, GLuint);
for (int i = 0; i < nrects; i++) {
GLint y1 = y_inverted ? height - rect[i].y2 : rect[i].y1,
y2 = y_inverted ? height - rect[i].y1 : rect[i].y2;
memcpy(&coord[i * 8],
(GLint[][2]){{rect[i].x1, gd->height - rect[i].y2},
{rect[i].x2, gd->height - rect[i].y2},
{rect[i].x2, gd->height - rect[i].y1},
{rect[i].x1, gd->height - rect[i].y1}},
(GLint[][2]){
{rect[i].x1, y1}, {rect[i].x2, y1}, {rect[i].x2, y2}, {rect[i].x1, y2}},
sizeof(GLint[2]) * 4);
indices[i * 6 + 0] = (GLuint)i * 4 + 0;
indices[i * 6 + 1] = (GLuint)i * 4 + 1;
@ -624,6 +628,11 @@ void gl_fill(backend_t *base, double r, double g, double b, double a, const regi
glDeleteBuffers(2, bo);
}
void gl_fill(backend_t *base, struct color c, const region_t *clip) {
struct gl_data *gd = (void *)base;
return _gl_fill(base, c, clip, gd->height, true);
}
void gl_release_image(backend_t *base, void *image_data) {
struct gl_image *wd = image_data;
struct gl_data *gl = (void *)base;
@ -967,7 +976,20 @@ static inline void gl_image_decouple(backend_t *base, struct gl_image *img) {
img->opacity = 1;
}
static void gl_image_apply_alpha(struct gl_image *img, const region_t *reg_op, double alpha) {
static void gl_image_apply_alpha(backend_t *base, struct gl_image *img,
const region_t *reg_op, double alpha) {
glBlendFunc(GL_ONE, GL_CONSTANT_COLOR);
glBlendColor(1, 1, 1, (GLclampf)alpha);
GLuint fbo;
glGenFramebuffers(1, &fbo);
glBindFramebuffer(GL_DRAW_FRAMEBUFFER, fbo);
glFramebufferTexture2D(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D,
img->inner->texture, 0);
glDrawBuffer(GL_COLOR_ATTACHMENT0);
_gl_fill(base, (struct color){0, 0, 0, 0}, reg_op, 0, false);
glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA);
glBindFramebuffer(GL_DRAW_FRAMEBUFFER, 0);
glDeleteFramebuffers(1, &fbo);
}
/// stub for backend_operations::image_op
@ -983,8 +1005,8 @@ bool gl_image_op(backend_t *base, enum image_operations op, void *image_data,
case IMAGE_OP_APPLY_ALPHA_ALL: tex->opacity *= *(double *)arg; break;
case IMAGE_OP_APPLY_ALPHA:
gl_image_decouple(base, tex);
gl_image_apply_alpha(tex, reg_op, *(double *)arg);
log_warn("IMAGE_OP_APPLY_ALPHA not implemented yet");
assert(tex->inner->refcount == 1);
gl_image_apply_alpha(base, tex, reg_op, *(double *)arg);
break;
case IMAGE_OP_RESIZE_TILE:
// texture is already set to repeat, so nothing else we need to do

View File

@ -132,7 +132,7 @@ bool gl_blur(backend_t *base, double opacity, const region_t *reg_blur,
const region_t *reg_visible);
bool gl_is_image_transparent(backend_t *base, void *image_data);
void gl_fill(backend_t *base, double r, double g, double b, double a, const region_t *clip);
void gl_fill(backend_t *base, struct color, const region_t *clip);
static inline void gl_delete_texture(GLuint texture) {
glDeleteTextures(1, &texture);

View File

@ -107,17 +107,17 @@ static void compose(backend_t *base, void *img_data, int dst_x, int dst_y,
}
static void
fill(backend_t *base, double r, double g, double b, double a, const region_t *clip) {
fill(backend_t *base, struct color c, const region_t *clip) {
struct _xrender_data *xd = (void *)base;
const rect_t *extent = pixman_region32_extents((region_t *)clip);
x_set_picture_clip_region(base->c, xd->back[xd->curr_back], 0, 0, clip);
// color is in X fixed point representation
xcb_render_fill_rectangles(
base->c, XCB_RENDER_PICT_OP_OVER, xd->back[xd->curr_back],
(xcb_render_color_t){.red = (uint16_t)(r * 0xffff),
.green = (uint16_t)(g * 0xffff),
.blue = (uint16_t)(b * 0xffff),
.alpha = (uint16_t)(a * 0xffff)},
(xcb_render_color_t){.red = (uint16_t)(c.red * 0xffff),
.green = (uint16_t)(c.green * 0xffff),
.blue = (uint16_t)(c.blue * 0xffff),
.alpha = (uint16_t)(c.alpha * 0xffff)},
1,
(xcb_rectangle_t[]){{.x = to_i16_checked(extent->x1),
.y = to_i16_checked(extent->y1),

View File

@ -22,6 +22,10 @@ typedef struct {
int right;
} margin_t;
struct color {
double red, green, blue, alpha;
};
typedef uint32_t opacity_t;
#define MARGIN_INIT \