new glx: implement fill for monitor-repaint

Refine the API of fill_rectangle and rename it to fill.

Extras:

Keep GL_BLEND enabled; Fixed some texture/fbo leaks

Signed-off-by: Yuxuan Shui <yshuiv7@gmail.com>
This commit is contained in:
Yuxuan Shui 2019-03-10 01:51:21 +00:00
parent 48338a9903
commit 34254ff86e
No known key found for this signature in database
GPG Key ID: 37C999F617EA1A47
7 changed files with 48 additions and 50 deletions

View File

@ -244,10 +244,8 @@ void paint_all_new(session_t *ps, win *const t, bool ignore_damage) {
if (ps->o.monitor_repaint) {
reg_damage = get_damage(ps, false);
auto extent = pixman_region32_extents(&reg_damage);
ps->backend_data->ops->fill_rectangle(
ps->backend_data, 0.5, 0, 0, 0.5, extent->x1, extent->y1,
extent->x2 - extent->x1, extent->y2 - extent->y1, &reg_damage);
ps->backend_data->ops->fill(
ps->backend_data, 0.5, 0, 0, 0.5, &reg_damage);
pixman_region32_fini(&reg_damage);
}

View File

@ -90,8 +90,8 @@ struct backend_operations {
const region_t *reg_paint, const region_t *reg_visible);
/// Fill rectangle of target, mostly for debug purposes, optional.
void (*fill_rectangle)(backend_t *backend_data, double r, double g, double b, double a,
int x, int y, int width, int height, const region_t *clip);
void (*fill)(backend_t *backend_data, double r, double g, double b, double a,
const region_t *clip);
/// Blur a given region on of the target.
bool (*blur)(backend_t *backend_data, double opacity, const region_t *reg_blur,

View File

@ -205,18 +205,6 @@ void gl_compose(backend_t *base, void *image_data, int dst_x, int dst_y,
// It's required by legacy versions of OpenGL to enable texture target
// before specifying environment. Thanks to madsy for telling me.
glEnable(ptex->target);
// Enable blending if needed
if (ptex->opacity < 1.0 || ptex->has_alpha) {
glEnable(GL_BLEND);
// X pixmap is in premultiplied ARGB format, so
// we need to do this to correct it.
// Thanks to derhass for help.
glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA);
glColor4f(ptex->opacity, ptex->opacity, ptex->opacity, ptex->opacity);
}
if (gd->win_shader.prog) {
glUseProgram(gd->win_shader.prog);
if (gd->win_shader.unifm_opacity >= 0)
@ -297,7 +285,6 @@ void gl_compose(backend_t *base, void *image_data, int dst_x, int dst_y,
// Cleanup
glBindTexture(ptex->target, 0);
glColor4f(0.0f, 0.0f, 0.0f, 0.0f);
glDisable(GL_BLEND);
glDisable(GL_COLOR_LOGIC_OP);
glDisable(ptex->target);
@ -317,12 +304,7 @@ void gl_compose(backend_t *base, void *image_data, int dst_x, int dst_y,
bool gl_dim_reg(session_t *ps, int dx, int dy, int width, int height, float z,
GLfloat factor, const region_t *reg_tgt) {
// It's possible to dim in glx_render(), but it would be over-complicated
// considering all those mess in color negation and modulation
glEnable(GL_BLEND);
glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA);
glColor4f(0.0f, 0.0f, 0.0f, factor);
{
P_PAINTREG_START(reg_tgt, crect) {
glVertex3i(crect.x1, crect.y1, z);
@ -334,7 +316,6 @@ bool gl_dim_reg(session_t *ps, int dx, int dy, int width, int height, float z,
}
glColor4f(0.0f, 0.0f, 0.0f, 0.0f);
glDisable(GL_BLEND);
gl_check_err();
@ -523,11 +504,26 @@ void gl_resize(struct gl_data *gd, int width, int height) {
GL_BGRA, GL_UNSIGNED_BYTE, NULL);
if (gd->npasses > 1) {
glBindTexture(gd->blur_texture_target, gd->blur_texture[1]);
glTexImage2D(gd->blur_texture_target, 0, GL_RGBA8, gd->width, gd->height, 0,
GL_BGRA, GL_UNSIGNED_BYTE, NULL);
glTexImage2D(gd->blur_texture_target, 0, GL_RGBA8, gd->width, gd->height,
0, GL_BGRA, GL_UNSIGNED_BYTE, NULL);
}
}
void gl_fill(backend_t *base, double r, double g, double b, double a, const region_t *clip) {
int nrects;
const rect_t *rect = pixman_region32_rectangles((region_t *)clip, &nrects);
struct gl_data *gd = (void *)base;
glColor4f(r, g, b, a);
glBegin(GL_QUADS);
for (int i = 0; i < nrects; i++) {
glVertex2f(rect[i].x1, gd->height - rect[i].y2);
glVertex2f(rect[i].x2, gd->height - rect[i].y2);
glVertex2f(rect[i].x2, gd->height - rect[i].y1);
glVertex2f(rect[i].x1, gd->height - rect[i].y1);
}
glEnd();
}
/**
* Initialize GL blur filters.
*/
@ -536,19 +532,6 @@ static bool gl_init_blur(struct gl_data *gd, conv *const *const kernels) {
return true;
}
// Allocate PBO if more than one blur kernel is present
if (kernels[1]) {
// Try to generate a framebuffer
GLuint fbo = 0;
glGenFramebuffers(1, &fbo);
if (!fbo) {
log_error("Failed to generate Framebuffer. Cannot do "
"multi-pass blur with GL backends.");
return false;
}
glDeleteFramebuffers(1, &fbo);
}
char *lc_numeric_old = strdup(setlocale(LC_NUMERIC, NULL));
// Enforce LC_NUMERIC locale "C" here to make sure decimal point is sane
// Thanks to hiciu for reporting.
@ -645,19 +628,21 @@ static bool gl_init_blur(struct gl_data *gd, conv *const *const kernels) {
if (gd->non_power_of_two_texture) {
gd->blur_texture_target = GL_TEXTURE_2D;
}
// Texture size will be defined by gl_resize
glGenTextures(gd->npasses > 1 ? 2 : 1, gd->blur_texture);
glBindTexture(gd->blur_texture_target, gd->blur_texture[0]);
glTexParameteri(gd->blur_texture_target, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
glTexParameteri(gd->blur_texture_target, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
glTexImage2D(gd->blur_texture_target, 0, GL_RGBA8, gd->width, gd->height, 0,
GL_BGRA, GL_UNSIGNED_BYTE, NULL);
if (gd->npasses > 1) {
glBindTexture(gd->blur_texture_target, gd->blur_texture[1]);
glTexParameteri(gd->blur_texture_target, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
glTexParameteri(gd->blur_texture_target, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
glTexImage2D(gd->blur_texture_target, 0, GL_RGBA8, gd->width, gd->height, 0,
GL_BGRA, GL_UNSIGNED_BYTE, NULL);
glGenFramebuffers(1, &gd->blur_fbo);
if (!gd->blur_fbo) {
log_error("Failed to generate framebuffer object for blur");
return false;
}
}
// Restore LC_NUMERIC
@ -706,7 +691,10 @@ bool gl_init(struct gl_data *gd, session_t *ps) {
glDisable(GL_DEPTH_TEST);
glDepthMask(GL_FALSE);
glDisable(GL_BLEND);
glEnable(GL_BLEND);
// X pixmap is in premultiplied alpha, so we might just as well use it too.
// Thanks to derhass for help.
glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA);
// Initialize stencil buffer
glDisable(GL_STENCIL_TEST);
@ -745,6 +733,11 @@ void gl_deinit(struct gl_data *gd) {
gl_free_prog_main(&gd->win_shader);
glDeleteTextures(gd->npasses > 1 ? 2 : 1, gd->blur_texture);
if (gd->npasses > 1) {
glDeleteFramebuffers(1, &gd->blur_fbo);
}
gl_check_err();
}

View File

@ -109,6 +109,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);
static inline void gl_delete_texture(GLuint texture) {
glDeleteTextures(1, &texture);

View File

@ -468,6 +468,7 @@ struct backend_operations glx_ops = {
.present = glx_present,
.buffer_age = glx_buffer_age,
.render_shadow = default_backend_render_shadow,
.fill = gl_fill,
.max_buffer_age = 5, // Why?
};

View File

@ -105,16 +105,21 @@ static void compose(backend_t *base, void *img_data, int dst_x, int dst_y,
pixman_region32_fini(&reg);
}
static void fill_rectangle(backend_t *base, double r, double g, double b, double a, int x,
int y, int width, int height, const region_t *clip) {
static void
fill(backend_t *base, double r, double g, double b, double a, 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 = r * 0xffff, .green = g * 0xffff, .blue = b * 0xffff, .alpha = a * 0xffff},
1, (xcb_rectangle_t[]){{.x = x, .y = y, .width = width, .height = height}});
1,
(xcb_rectangle_t[]){{.x = extent->x1,
.y = extent->y1,
.width = extent->x2 - extent->x1,
.height = extent->y2 - extent->y1}});
}
static bool blur(backend_t *backend_data, double opacity, const region_t *reg_blur,
@ -561,7 +566,7 @@ struct backend_operations xrender_ops = {
.blur = blur,
.present = present,
.compose = compose,
.fill_rectangle = fill_rectangle,
.fill = fill,
.bind_pixmap = bind_pixmap,
.release_image = release_image,
.render_shadow = default_backend_render_shadow,

View File

@ -2727,7 +2727,7 @@ session_init(int argc, char **argv, Display *dpy, const char *config_file,
}
if (ps->o.experimental_backends) {
if (ps->o.monitor_repaint && !backend_list[ps->o.backend]->fill_rectangle) {
if (ps->o.monitor_repaint && !backend_list[ps->o.backend]->fill) {
log_warn("--monitor-repaint is not supported by the backend, disabling");
ps->o.monitor_repaint = false;
}