mirror of
https://github.com/yshui/picom.git
synced 2024-11-11 13:51:02 -05:00
Move glx_init_blur to gl_common.c
Signed-off-by: Yuxuan Shui <yshuiv7@gmail.com>
This commit is contained in:
parent
8629fee78f
commit
a2022661e6
3 changed files with 154 additions and 152 deletions
|
@ -1,9 +1,11 @@
|
||||||
#include <GL/gl.h>
|
#include <GL/gl.h>
|
||||||
#include <GL/glext.h>
|
#include <GL/glext.h>
|
||||||
#include <stdbool.h>
|
#include <stdbool.h>
|
||||||
|
#include <locale.h>
|
||||||
|
|
||||||
#include "common.h"
|
#include "common.h"
|
||||||
#include "log.h"
|
#include "log.h"
|
||||||
|
#include "string_utils.h"
|
||||||
|
|
||||||
#include "backend/gl/gl_common.h"
|
#include "backend/gl/gl_common.h"
|
||||||
|
|
||||||
|
@ -589,3 +591,143 @@ static void attr_unused gl_destroy_win_shader(session_t *ps, gl_win_shader_t *sh
|
||||||
shader->unifm_invert_color = -1;
|
shader->unifm_invert_color = -1;
|
||||||
shader->unifm_tex = -1;
|
shader->unifm_tex = -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Initialize GL blur filters.
|
||||||
|
*
|
||||||
|
* Fill `passes` with blur filters, won't create more than MAX_BLUR_FILTER number of filters
|
||||||
|
*/
|
||||||
|
bool gl_create_blur_filters(session_t *ps, gl_blur_shader_t *passes, const gl_cap_t *cap) {
|
||||||
|
assert(ps->o.blur_kerns[0]);
|
||||||
|
|
||||||
|
// Allocate PBO if more than one blur kernel is present
|
||||||
|
if (ps->o.blur_kerns[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.
|
||||||
|
setlocale(LC_NUMERIC, "C");
|
||||||
|
|
||||||
|
static const char *FRAG_SHADER_BLUR_PREFIX = "#version 110\n"
|
||||||
|
"%s"
|
||||||
|
"uniform float offset_x;\n"
|
||||||
|
"uniform float offset_y;\n"
|
||||||
|
"uniform float factor_center;\n"
|
||||||
|
"uniform %s tex_scr;\n\n"
|
||||||
|
"void main() {\n"
|
||||||
|
" vec4 sum = vec4(0.0, 0.0, 0.0, "
|
||||||
|
"0.0);\n";
|
||||||
|
static const char *FRAG_SHADER_BLUR_ADD =
|
||||||
|
" sum += float(%.7g) * %s(tex_scr, vec2(gl_TexCoord[0].x + offset_x "
|
||||||
|
"* float(%d), gl_TexCoord[0].y + offset_y * float(%d)));\n";
|
||||||
|
static const char *FRAG_SHADER_BLUR_ADD_GPUSHADER4 =
|
||||||
|
" sum += float(%.7g) * %sOffset(tex_scr, vec2(gl_TexCoord[0].x, "
|
||||||
|
"gl_TexCoord[0].y), ivec2(%d, %d));\n";
|
||||||
|
static const char *FRAG_SHADER_BLUR_SUFFIX =
|
||||||
|
" sum += %s(tex_scr, vec2(gl_TexCoord[0].x, gl_TexCoord[0].y)) * "
|
||||||
|
"factor_center;\n"
|
||||||
|
" gl_FragColor = sum / (factor_center + float(%.7g));\n"
|
||||||
|
"}\n";
|
||||||
|
|
||||||
|
const bool use_texture_rect = !cap->non_power_of_two_texture;
|
||||||
|
const char *sampler_type = (use_texture_rect ? "sampler2DRect" : "sampler2D");
|
||||||
|
const char *texture_func = (use_texture_rect ? "texture2DRect" : "texture2D");
|
||||||
|
const char *shader_add = FRAG_SHADER_BLUR_ADD;
|
||||||
|
char *extension = strdup("");
|
||||||
|
if (use_texture_rect)
|
||||||
|
mstrextend(&extension, "#extension GL_ARB_texture_rectangle : "
|
||||||
|
"require\n");
|
||||||
|
if (ps->o.glx_use_gpushader4) {
|
||||||
|
mstrextend(&extension, "#extension GL_EXT_gpu_shader4 : "
|
||||||
|
"require\n");
|
||||||
|
shader_add = FRAG_SHADER_BLUR_ADD_GPUSHADER4;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (int i = 0; i < MAX_BLUR_PASS && ps->o.blur_kerns[i]; ++i) {
|
||||||
|
xcb_render_fixed_t *kern = ps->o.blur_kerns[i];
|
||||||
|
if (!kern)
|
||||||
|
break;
|
||||||
|
|
||||||
|
// Build shader
|
||||||
|
int wid = XFIXED_TO_DOUBLE(kern[0]), hei = XFIXED_TO_DOUBLE(kern[1]);
|
||||||
|
int nele = wid * hei - 1;
|
||||||
|
unsigned int len =
|
||||||
|
strlen(FRAG_SHADER_BLUR_PREFIX) + strlen(sampler_type) +
|
||||||
|
strlen(extension) +
|
||||||
|
(strlen(shader_add) + strlen(texture_func) + 42) * nele +
|
||||||
|
strlen(FRAG_SHADER_BLUR_SUFFIX) + strlen(texture_func) + 12 + 1;
|
||||||
|
char *shader_str = ccalloc(len, char);
|
||||||
|
char *pc = shader_str;
|
||||||
|
sprintf(pc, FRAG_SHADER_BLUR_PREFIX, extension, sampler_type);
|
||||||
|
pc += strlen(pc);
|
||||||
|
assert(strlen(shader_str) < len);
|
||||||
|
|
||||||
|
double sum = 0.0;
|
||||||
|
for (int j = 0; j < hei; ++j) {
|
||||||
|
for (int k = 0; k < wid; ++k) {
|
||||||
|
if (hei / 2 == j && wid / 2 == k)
|
||||||
|
continue;
|
||||||
|
double val = XFIXED_TO_DOUBLE(kern[2 + j * wid + k]);
|
||||||
|
if (0.0 == val)
|
||||||
|
continue;
|
||||||
|
sum += val;
|
||||||
|
sprintf(pc, shader_add, val, texture_func, k - wid / 2,
|
||||||
|
j - hei / 2);
|
||||||
|
pc += strlen(pc);
|
||||||
|
assert(strlen(shader_str) < len);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
auto pass = passes + i;
|
||||||
|
sprintf(pc, FRAG_SHADER_BLUR_SUFFIX, texture_func, sum);
|
||||||
|
assert(strlen(shader_str) < len);
|
||||||
|
pass->frag_shader = gl_create_shader(GL_FRAGMENT_SHADER, shader_str);
|
||||||
|
free(shader_str);
|
||||||
|
|
||||||
|
if (!pass->frag_shader) {
|
||||||
|
log_error("Failed to create fragment shader %d.", i);
|
||||||
|
goto err;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Build program
|
||||||
|
pass->prog = gl_create_program(&pass->frag_shader, 1);
|
||||||
|
if (!pass->prog) {
|
||||||
|
log_error("Failed to create GLSL program.");
|
||||||
|
goto err;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get uniform addresses
|
||||||
|
pass->unifm_factor_center =
|
||||||
|
glGetUniformLocationChecked(pass->prog, "factor_center");
|
||||||
|
if (!ps->o.glx_use_gpushader4) {
|
||||||
|
pass->unifm_offset_x =
|
||||||
|
glGetUniformLocationChecked(pass->prog, "offset_x");
|
||||||
|
pass->unifm_offset_y =
|
||||||
|
glGetUniformLocationChecked(pass->prog, "offset_y");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
free(extension);
|
||||||
|
|
||||||
|
// Restore LC_NUMERIC
|
||||||
|
setlocale(LC_NUMERIC, lc_numeric_old);
|
||||||
|
free(lc_numeric_old);
|
||||||
|
|
||||||
|
gl_check_err();
|
||||||
|
|
||||||
|
return true;
|
||||||
|
err:
|
||||||
|
free(extension);
|
||||||
|
setlocale(LC_NUMERIC, lc_numeric_old);
|
||||||
|
free(lc_numeric_old);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
|
@ -70,6 +70,7 @@ void gl_free_prog_main(session_t *ps, gl_win_shader_t *prog);
|
||||||
|
|
||||||
unsigned char *gl_take_screenshot(session_t *ps, int *out_length);
|
unsigned char *gl_take_screenshot(session_t *ps, int *out_length);
|
||||||
void gl_resize(int width, int height);
|
void gl_resize(int width, int height);
|
||||||
|
bool gl_create_blur_filters(session_t *ps, gl_blur_shader_t *passes, const gl_cap_t *cap);
|
||||||
|
|
||||||
GLuint glGetUniformLocationChecked(GLuint p, const char *name);
|
GLuint glGetUniformLocationChecked(GLuint p, const char *name);
|
||||||
|
|
||||||
|
|
|
@ -10,7 +10,6 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include <GL/glx.h>
|
#include <GL/glx.h>
|
||||||
#include <locale.h>
|
|
||||||
#include "backend/backend.h"
|
#include "backend/backend.h"
|
||||||
#include "backend/gl/gl_common.h"
|
#include "backend/gl/gl_common.h"
|
||||||
#include "string_utils.h"
|
#include "string_utils.h"
|
||||||
|
@ -469,10 +468,14 @@ static void *glx_init(session_t *ps) {
|
||||||
// glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
|
// glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
|
||||||
// glXSwapBuffers(ps->dpy, get_tgt_window(ps));
|
// glXSwapBuffers(ps->dpy, get_tgt_window(ps));
|
||||||
|
|
||||||
|
// Initialize blur filters
|
||||||
|
gl_create_blur_filters(ps, gd->blur_shader, &gd->cap);
|
||||||
|
|
||||||
success = true;
|
success = true;
|
||||||
|
|
||||||
end:
|
end:
|
||||||
cxfree(pvis);
|
if (pvis)
|
||||||
|
XFree(pvis);
|
||||||
|
|
||||||
if (!success) {
|
if (!success) {
|
||||||
glx_deinit(gd, ps);
|
glx_deinit(gd, ps);
|
||||||
|
@ -482,146 +485,6 @@ end:
|
||||||
return gd;
|
return gd;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Initialize GLX blur filter.
|
|
||||||
*/
|
|
||||||
static bool attr_unused glx_init_blur(session_t *ps) {
|
|
||||||
struct _glx_data *gd = ps->backend_data;
|
|
||||||
assert(ps->o.blur_kerns[0]);
|
|
||||||
|
|
||||||
// Allocate PBO if more than one blur kernel is present
|
|
||||||
if (ps->o.blur_kerns[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 GLX backend.");
|
|
||||||
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.
|
|
||||||
setlocale(LC_NUMERIC, "C");
|
|
||||||
|
|
||||||
static const char *FRAG_SHADER_BLUR_PREFIX = "#version 110\n"
|
|
||||||
"%s"
|
|
||||||
"uniform float offset_x;\n"
|
|
||||||
"uniform float offset_y;\n"
|
|
||||||
"uniform float factor_center;\n"
|
|
||||||
"uniform %s tex_scr;\n\n"
|
|
||||||
"void main() {\n"
|
|
||||||
" vec4 sum = vec4(0.0, 0.0, 0.0, "
|
|
||||||
"0.0);\n";
|
|
||||||
static const char *FRAG_SHADER_BLUR_ADD =
|
|
||||||
" sum += float(%.7g) * %s(tex_scr, vec2(gl_TexCoord[0].x + offset_x "
|
|
||||||
"* float(%d), gl_TexCoord[0].y + offset_y * float(%d)));\n";
|
|
||||||
static const char *FRAG_SHADER_BLUR_ADD_GPUSHADER4 =
|
|
||||||
" sum += float(%.7g) * %sOffset(tex_scr, vec2(gl_TexCoord[0].x, "
|
|
||||||
"gl_TexCoord[0].y), ivec2(%d, %d));\n";
|
|
||||||
static const char *FRAG_SHADER_BLUR_SUFFIX =
|
|
||||||
" sum += %s(tex_scr, vec2(gl_TexCoord[0].x, gl_TexCoord[0].y)) * "
|
|
||||||
"factor_center;\n"
|
|
||||||
" gl_FragColor = sum / (factor_center + float(%.7g));\n"
|
|
||||||
"}\n";
|
|
||||||
|
|
||||||
const bool use_texture_rect = !gd->cap.non_power_of_two_texture;
|
|
||||||
const char *sampler_type = (use_texture_rect ? "sampler2DRect" : "sampler2D");
|
|
||||||
const char *texture_func = (use_texture_rect ? "texture2DRect" : "texture2D");
|
|
||||||
const char *shader_add = FRAG_SHADER_BLUR_ADD;
|
|
||||||
char *extension = strdup("");
|
|
||||||
if (use_texture_rect)
|
|
||||||
mstrextend(&extension, "#extension GL_ARB_texture_rectangle : "
|
|
||||||
"require\n");
|
|
||||||
if (ps->o.glx_use_gpushader4) {
|
|
||||||
mstrextend(&extension, "#extension GL_EXT_gpu_shader4 : "
|
|
||||||
"require\n");
|
|
||||||
shader_add = FRAG_SHADER_BLUR_ADD_GPUSHADER4;
|
|
||||||
}
|
|
||||||
|
|
||||||
for (int i = 0; i < MAX_BLUR_PASS && ps->o.blur_kerns[i]; ++i) {
|
|
||||||
xcb_render_fixed_t *kern = ps->o.blur_kerns[i];
|
|
||||||
if (!kern)
|
|
||||||
break;
|
|
||||||
|
|
||||||
glx_blur_pass_t *ppass = &ps->psglx->blur_passes[i];
|
|
||||||
|
|
||||||
// Build shader
|
|
||||||
int wid = XFIXED_TO_DOUBLE(kern[0]), hei = XFIXED_TO_DOUBLE(kern[1]);
|
|
||||||
int nele = wid * hei - 1;
|
|
||||||
unsigned int len =
|
|
||||||
strlen(FRAG_SHADER_BLUR_PREFIX) + strlen(sampler_type) +
|
|
||||||
strlen(extension) +
|
|
||||||
(strlen(shader_add) + strlen(texture_func) + 42) * nele +
|
|
||||||
strlen(FRAG_SHADER_BLUR_SUFFIX) + strlen(texture_func) + 12 + 1;
|
|
||||||
char *shader_str = ccalloc(len, char);
|
|
||||||
char *pc = shader_str;
|
|
||||||
sprintf(pc, FRAG_SHADER_BLUR_PREFIX, extension, sampler_type);
|
|
||||||
pc += strlen(pc);
|
|
||||||
assert(strlen(shader_str) < len);
|
|
||||||
|
|
||||||
double sum = 0.0;
|
|
||||||
for (int j = 0; j < hei; ++j) {
|
|
||||||
for (int k = 0; k < wid; ++k) {
|
|
||||||
if (hei / 2 == j && wid / 2 == k)
|
|
||||||
continue;
|
|
||||||
double val = XFIXED_TO_DOUBLE(kern[2 + j * wid + k]);
|
|
||||||
if (0.0 == val)
|
|
||||||
continue;
|
|
||||||
sum += val;
|
|
||||||
sprintf(pc, shader_add, val, texture_func, k - wid / 2,
|
|
||||||
j - hei / 2);
|
|
||||||
pc += strlen(pc);
|
|
||||||
assert(strlen(shader_str) < len);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
sprintf(pc, FRAG_SHADER_BLUR_SUFFIX, texture_func, sum);
|
|
||||||
assert(strlen(shader_str) < len);
|
|
||||||
ppass->frag_shader = gl_create_shader(GL_FRAGMENT_SHADER, shader_str);
|
|
||||||
free(shader_str);
|
|
||||||
|
|
||||||
if (!ppass->frag_shader) {
|
|
||||||
log_error("Failed to create fragment shader %d.", i);
|
|
||||||
goto err;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Build program
|
|
||||||
ppass->prog = gl_create_program(&ppass->frag_shader, 1);
|
|
||||||
if (!ppass->prog) {
|
|
||||||
log_error("Failed to create GLSL program.");
|
|
||||||
goto err;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Get uniform addresses
|
|
||||||
ppass->unifm_factor_center =
|
|
||||||
glGetUniformLocationChecked(ppass->prog, "factor_center");
|
|
||||||
if (!ps->o.glx_use_gpushader4) {
|
|
||||||
ppass->unifm_offset_x =
|
|
||||||
glGetUniformLocationChecked(ppass->prog, "offset_x");
|
|
||||||
ppass->unifm_offset_y =
|
|
||||||
glGetUniformLocationChecked(ppass->prog, "offset_y");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
free(extension);
|
|
||||||
|
|
||||||
// Restore LC_NUMERIC
|
|
||||||
setlocale(LC_NUMERIC, lc_numeric_old);
|
|
||||||
free(lc_numeric_old);
|
|
||||||
|
|
||||||
gl_check_err();
|
|
||||||
|
|
||||||
return true;
|
|
||||||
err:
|
|
||||||
free(extension);
|
|
||||||
setlocale(LC_NUMERIC, lc_numeric_old);
|
|
||||||
free(lc_numeric_old);
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
void *glx_prepare_win(void *backend_data, session_t *ps, win *w) {
|
void *glx_prepare_win(void *backend_data, session_t *ps, win *w) {
|
||||||
struct _glx_data *gd = backend_data;
|
struct _glx_data *gd = backend_data;
|
||||||
// Retrieve pixmap parameters, if they aren't provided
|
// Retrieve pixmap parameters, if they aren't provided
|
||||||
|
@ -713,12 +576,10 @@ err:
|
||||||
/**
|
/**
|
||||||
* Bind a X pixmap to an OpenGL texture.
|
* Bind a X pixmap to an OpenGL texture.
|
||||||
*/
|
*/
|
||||||
bool glx_render_win(void *backend_data, session_t *ps, win *w, void *win_data,
|
void glx_render_win(void *backend_data, session_t *ps, win *w, void *win_data,
|
||||||
const region_t *reg_paint) {
|
const region_t *reg_paint) {
|
||||||
struct _glx_data *gd = backend_data;
|
struct _glx_data *gd = backend_data;
|
||||||
struct _glx_win_data *wd = win_data;
|
struct _glx_win_data *wd = win_data;
|
||||||
if (ps->o.backend != BKEND_GLX && ps->o.backend != BKEND_XR_GLX_HYBRID)
|
|
||||||
return true;
|
|
||||||
|
|
||||||
assert(wd->pixmap);
|
assert(wd->pixmap);
|
||||||
assert(wd->glpixmap);
|
assert(wd->glpixmap);
|
||||||
|
@ -729,15 +590,12 @@ bool glx_render_win(void *backend_data, session_t *ps, win *w, void *win_data,
|
||||||
glBindTexture(wd->texture.target, 0);
|
glBindTexture(wd->texture.target, 0);
|
||||||
|
|
||||||
gl_check_err();
|
gl_check_err();
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#if 0
|
|
||||||
/**
|
/**
|
||||||
* Preprocess function before start painting.
|
* Preprocess function before start painting.
|
||||||
*/
|
*/
|
||||||
void
|
static void attr_unused
|
||||||
glx_paint_pre(session_t *ps, region_t *preg) {
|
glx_paint_pre(session_t *ps, region_t *preg) {
|
||||||
ps->psglx->z = 0.0;
|
ps->psglx->z = 0.0;
|
||||||
// glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
|
// glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
|
||||||
|
@ -785,7 +643,7 @@ glx_paint_pre(session_t *ps, region_t *preg) {
|
||||||
ps->all_damage_last[0] = newdamage;
|
ps->all_damage_last[0] = newdamage;
|
||||||
}
|
}
|
||||||
|
|
||||||
glx_set_clip(ps, preg);
|
//gl_set_clip(ps, preg);
|
||||||
|
|
||||||
#ifdef DEBUG_GLX_PAINTREG
|
#ifdef DEBUG_GLX_PAINTREG
|
||||||
glx_render_color(ps, 0, 0, ps->root_width, ps->root_height, 0, *preg, NULL);
|
glx_render_color(ps, 0, 0, ps->root_width, ps->root_height, 0, *preg, NULL);
|
||||||
|
@ -793,9 +651,10 @@ glx_paint_pre(session_t *ps, region_t *preg) {
|
||||||
|
|
||||||
gl_check_err();
|
gl_check_err();
|
||||||
}
|
}
|
||||||
#endif
|
|
||||||
|
|
||||||
backend_info_t glx_backend = {
|
backend_info_t glx_backend = {
|
||||||
.init = glx_init,
|
.init = glx_init,
|
||||||
|
.deinit = glx_deinit,
|
||||||
|
.prepare_win = glx_prepare_win,
|
||||||
|
.render_win = glx_render_win,
|
||||||
};
|
};
|
||||||
|
|
Loading…
Reference in a new issue