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
7 changed files with 48 additions and 50 deletions

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?
};