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:
parent
18b1fc95ff
commit
80c7b2f7ec
|
@ -259,7 +259,8 @@ void paint_all_new(session_t *ps, struct managed_win *t, bool ignore_damage) {
|
||||||
|
|
||||||
if (ps->o.monitor_repaint) {
|
if (ps->o.monitor_repaint) {
|
||||||
reg_damage = get_damage(ps, false);
|
reg_damage = get_damage(ps, false);
|
||||||
ps->backend_data->ops->fill(ps->backend_data, 0.5, 0, 0, 0.5, ®_damage);
|
ps->backend_data->ops->fill(ps->backend_data,
|
||||||
|
(struct color){0.5, 0, 0, 0.5}, ®_damage);
|
||||||
pixman_region32_fini(®_damage);
|
pixman_region32_fini(®_damage);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -9,6 +9,7 @@
|
||||||
#include "driver.h"
|
#include "driver.h"
|
||||||
#include "kernel.h"
|
#include "kernel.h"
|
||||||
#include "region.h"
|
#include "region.h"
|
||||||
|
#include "types.h"
|
||||||
#include "x.h"
|
#include "x.h"
|
||||||
|
|
||||||
typedef struct session session_t;
|
typedef struct session session_t;
|
||||||
|
@ -104,8 +105,7 @@ struct backend_operations {
|
||||||
const region_t *reg_paint, const region_t *reg_visible);
|
const region_t *reg_paint, const region_t *reg_visible);
|
||||||
|
|
||||||
/// Fill rectangle of target, mostly for debug purposes, optional.
|
/// Fill rectangle of target, mostly for debug purposes, optional.
|
||||||
void (*fill)(backend_t *backend_data, double r, double g, double b, double a,
|
void (*fill)(backend_t *backend_data, struct color, const region_t *clip);
|
||||||
const region_t *clip);
|
|
||||||
|
|
||||||
/// Blur a given region of the target.
|
/// Blur a given region of the target.
|
||||||
bool (*blur)(backend_t *backend_data, double opacity, const region_t *reg_blur,
|
bool (*blur)(backend_t *backend_data, double opacity, const region_t *reg_blur,
|
||||||
|
|
|
@ -575,7 +575,10 @@ static const char fill_vert[] = GLSL(330,
|
||||||
);
|
);
|
||||||
// clang-format on
|
// 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;
|
int nrects;
|
||||||
const rect_t *rect = pixman_region32_rectangles((region_t *)clip, &nrects);
|
const rect_t *rect = pixman_region32_rectangles((region_t *)clip, &nrects);
|
||||||
struct gl_data *gd = (void *)base;
|
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];
|
GLuint bo[2];
|
||||||
glGenBuffers(2, bo);
|
glGenBuffers(2, bo);
|
||||||
glUseProgram(gd->fill_shader.prog);
|
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);
|
glEnableVertexAttribArray((GLuint)gd->fill_shader.in_coord_loc);
|
||||||
glBindBuffer(GL_ARRAY_BUFFER, bo[0]);
|
glBindBuffer(GL_ARRAY_BUFFER, bo[0]);
|
||||||
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, bo[1]);
|
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 coord = ccalloc(nrects * 8, GLint);
|
||||||
auto indices = ccalloc(nrects * 6, GLuint);
|
auto indices = ccalloc(nrects * 6, GLuint);
|
||||||
for (int i = 0; i < nrects; i++) {
|
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],
|
memcpy(&coord[i * 8],
|
||||||
(GLint[][2]){{rect[i].x1, gd->height - rect[i].y2},
|
(GLint[][2]){
|
||||||
{rect[i].x2, gd->height - rect[i].y2},
|
{rect[i].x1, y1}, {rect[i].x2, y1}, {rect[i].x2, y2}, {rect[i].x1, y2}},
|
||||||
{rect[i].x2, gd->height - rect[i].y1},
|
|
||||||
{rect[i].x1, gd->height - rect[i].y1}},
|
|
||||||
sizeof(GLint[2]) * 4);
|
sizeof(GLint[2]) * 4);
|
||||||
indices[i * 6 + 0] = (GLuint)i * 4 + 0;
|
indices[i * 6 + 0] = (GLuint)i * 4 + 0;
|
||||||
indices[i * 6 + 1] = (GLuint)i * 4 + 1;
|
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);
|
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) {
|
void gl_release_image(backend_t *base, void *image_data) {
|
||||||
struct gl_image *wd = image_data;
|
struct gl_image *wd = image_data;
|
||||||
struct gl_data *gl = (void *)base;
|
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;
|
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
|
/// 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_ALL: tex->opacity *= *(double *)arg; break;
|
||||||
case IMAGE_OP_APPLY_ALPHA:
|
case IMAGE_OP_APPLY_ALPHA:
|
||||||
gl_image_decouple(base, tex);
|
gl_image_decouple(base, tex);
|
||||||
gl_image_apply_alpha(tex, reg_op, *(double *)arg);
|
assert(tex->inner->refcount == 1);
|
||||||
log_warn("IMAGE_OP_APPLY_ALPHA not implemented yet");
|
gl_image_apply_alpha(base, tex, reg_op, *(double *)arg);
|
||||||
break;
|
break;
|
||||||
case IMAGE_OP_RESIZE_TILE:
|
case IMAGE_OP_RESIZE_TILE:
|
||||||
// texture is already set to repeat, so nothing else we need to do
|
// texture is already set to repeat, so nothing else we need to do
|
||||||
|
|
|
@ -132,7 +132,7 @@ bool gl_blur(backend_t *base, double opacity, const region_t *reg_blur,
|
||||||
const region_t *reg_visible);
|
const region_t *reg_visible);
|
||||||
|
|
||||||
bool gl_is_image_transparent(backend_t *base, void *image_data);
|
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) {
|
static inline void gl_delete_texture(GLuint texture) {
|
||||||
glDeleteTextures(1, &texture);
|
glDeleteTextures(1, &texture);
|
||||||
|
|
|
@ -107,17 +107,17 @@ static void compose(backend_t *base, void *img_data, int dst_x, int dst_y,
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
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;
|
struct _xrender_data *xd = (void *)base;
|
||||||
const rect_t *extent = pixman_region32_extents((region_t *)clip);
|
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);
|
x_set_picture_clip_region(base->c, xd->back[xd->curr_back], 0, 0, clip);
|
||||||
// color is in X fixed point representation
|
// color is in X fixed point representation
|
||||||
xcb_render_fill_rectangles(
|
xcb_render_fill_rectangles(
|
||||||
base->c, XCB_RENDER_PICT_OP_OVER, xd->back[xd->curr_back],
|
base->c, XCB_RENDER_PICT_OP_OVER, xd->back[xd->curr_back],
|
||||||
(xcb_render_color_t){.red = (uint16_t)(r * 0xffff),
|
(xcb_render_color_t){.red = (uint16_t)(c.red * 0xffff),
|
||||||
.green = (uint16_t)(g * 0xffff),
|
.green = (uint16_t)(c.green * 0xffff),
|
||||||
.blue = (uint16_t)(b * 0xffff),
|
.blue = (uint16_t)(c.blue * 0xffff),
|
||||||
.alpha = (uint16_t)(a * 0xffff)},
|
.alpha = (uint16_t)(c.alpha * 0xffff)},
|
||||||
1,
|
1,
|
||||||
(xcb_rectangle_t[]){{.x = to_i16_checked(extent->x1),
|
(xcb_rectangle_t[]){{.x = to_i16_checked(extent->x1),
|
||||||
.y = to_i16_checked(extent->y1),
|
.y = to_i16_checked(extent->y1),
|
||||||
|
|
|
@ -22,6 +22,10 @@ typedef struct {
|
||||||
int right;
|
int right;
|
||||||
} margin_t;
|
} margin_t;
|
||||||
|
|
||||||
|
struct color {
|
||||||
|
double red, green, blue, alpha;
|
||||||
|
};
|
||||||
|
|
||||||
typedef uint32_t opacity_t;
|
typedef uint32_t opacity_t;
|
||||||
|
|
||||||
#define MARGIN_INIT \
|
#define MARGIN_INIT \
|
||||||
|
|
Loading…
Reference in New Issue