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:
parent
48338a9903
commit
34254ff86e
|
@ -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(®_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, ®_damage);
|
||||
ps->backend_data->ops->fill(
|
||||
ps->backend_data, 0.5, 0, 0, 0.5, ®_damage);
|
||||
pixman_region32_fini(®_damage);
|
||||
}
|
||||
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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();
|
||||
}
|
||||
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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?
|
||||
};
|
||||
|
||||
|
|
|
@ -105,16 +105,21 @@ static void compose(backend_t *base, void *img_data, int dst_x, int dst_y,
|
|||
pixman_region32_fini(®);
|
||||
}
|
||||
|
||||
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,
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue