Add backend/gl/glx.c to build
Still a long way to go for the glx backend. Signed-off-by: Yuxuan Shui <yshuiv7@gmail.com>
This commit is contained in:
parent
3e7b7bd608
commit
61f55f69a6
|
@ -7,6 +7,8 @@
|
||||||
|
|
||||||
#include "backend/gl/gl_common.h"
|
#include "backend/gl/gl_common.h"
|
||||||
|
|
||||||
|
struct gl_data {};
|
||||||
|
|
||||||
GLuint gl_create_shader(GLenum shader_type, const char *shader_str) {
|
GLuint gl_create_shader(GLenum shader_type, const char *shader_str) {
|
||||||
log_trace("===\n%s\n===", shader_str);
|
log_trace("===\n%s\n===", shader_str);
|
||||||
|
|
||||||
|
@ -92,8 +94,7 @@ end:
|
||||||
/**
|
/**
|
||||||
* @brief Create a program from vertex and fragment shader strings.
|
* @brief Create a program from vertex and fragment shader strings.
|
||||||
*/
|
*/
|
||||||
GLuint
|
GLuint gl_create_program_from_str(const char *vert_shader_str, const char *frag_shader_str) {
|
||||||
gl_create_program_from_str(const char *vert_shader_str, const char *frag_shader_str) {
|
|
||||||
GLuint vert_shader = 0;
|
GLuint vert_shader = 0;
|
||||||
GLuint frag_shader = 0;
|
GLuint frag_shader = 0;
|
||||||
GLuint prog = 0;
|
GLuint prog = 0;
|
||||||
|
@ -123,6 +124,18 @@ gl_create_program_from_str(const char *vert_shader_str, const char *frag_shader_
|
||||||
return prog;
|
return prog;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void gl_free_prog_main(session_t *ps, gl_win_shader_t *pprogram) {
|
||||||
|
if (!pprogram)
|
||||||
|
return;
|
||||||
|
if (pprogram->prog) {
|
||||||
|
glDeleteProgram(pprogram->prog);
|
||||||
|
pprogram->prog = 0;
|
||||||
|
}
|
||||||
|
pprogram->unifm_opacity = -1;
|
||||||
|
pprogram->unifm_invert_color = -1;
|
||||||
|
pprogram->unifm_tex = -1;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Get tightly packed RGB888 data from GL front buffer.
|
* @brief Get tightly packed RGB888 data from GL front buffer.
|
||||||
*
|
*
|
||||||
|
@ -521,11 +534,14 @@ void gl_set_clip(const region_t *reg) {
|
||||||
gl_check_err();
|
gl_check_err();
|
||||||
}
|
}
|
||||||
|
|
||||||
static GLint glGetUniformLocationChecked(GLint prog, const char *name) {
|
GLuint glGetUniformLocationChecked(GLuint p, const char *name) {
|
||||||
GLint ret = glGetUniformLocation(prog, name);
|
auto ret = glGetUniformLocation(p, name);
|
||||||
if (ret < 0)
|
if (ret < 0) {
|
||||||
log_error("Failed to get location of uniform '%s'. Might be troublesome.",
|
log_error("Failed to get location of uniform '%s'. compton might not "
|
||||||
|
"work correctly.",
|
||||||
name);
|
name);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -66,10 +66,13 @@ gl_create_program_from_str(const char *vert_shader_str, const char *frag_shader_
|
||||||
|
|
||||||
bool gl_load_prog_main(session_t *ps, const char *vshader_str, const char *fshader_str,
|
bool gl_load_prog_main(session_t *ps, const char *vshader_str, const char *fshader_str,
|
||||||
gl_win_shader_t *pprogram);
|
gl_win_shader_t *pprogram);
|
||||||
|
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);
|
||||||
|
|
||||||
|
GLuint glGetUniformLocationChecked(GLuint p, const char *name);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get a textual representation of an OpenGL error.
|
* Get a textual representation of an OpenGL error.
|
||||||
*/
|
*/
|
||||||
|
|
|
@ -9,13 +9,14 @@
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include <GL/glx.h>
|
|
||||||
#include "backend/gl/glx.h"
|
#include "backend/gl/glx.h"
|
||||||
|
#include <GL/glx.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"
|
||||||
|
|
||||||
/// @brief Wrapper of a GLX FBConfig.
|
/// @brief Wrapper of a GLX FBConfig.
|
||||||
typedef struct {
|
typedef struct glx_fbconfig {
|
||||||
GLXFBConfig cfg;
|
GLXFBConfig cfg;
|
||||||
GLint texture_fmt;
|
GLint texture_fmt;
|
||||||
GLint texture_tgts;
|
GLint texture_tgts;
|
||||||
|
@ -33,7 +34,9 @@ struct _glx_data {
|
||||||
int glx_error;
|
int glx_error;
|
||||||
GLXContext ctx;
|
GLXContext ctx;
|
||||||
gl_cap_t cap;
|
gl_cap_t cap;
|
||||||
|
gl_win_shader_t win_shader;
|
||||||
gl_blur_shader_t blur_shader[MAX_BLUR_PASS];
|
gl_blur_shader_t blur_shader[MAX_BLUR_PASS];
|
||||||
|
glx_fbconfig_t *fbconfigs[OPENGL_MAX_DEPTH + 1];
|
||||||
|
|
||||||
void (*glXBindTexImage)(Display *display, GLXDrawable drawable, int buffer,
|
void (*glXBindTexImage)(Display *display, GLXDrawable drawable, int buffer,
|
||||||
const int *attrib_list);
|
const int *attrib_list);
|
||||||
|
@ -63,7 +66,7 @@ static inline bool glx_has_extension(session_t *ps, const char *ext) {
|
||||||
/**
|
/**
|
||||||
* @brief Release binding of a texture.
|
* @brief Release binding of a texture.
|
||||||
*/
|
*/
|
||||||
void glx_release_pixmap(struct _glx_data *gd, Display *dpy, struct _glx_win_data *wd) {
|
static void glx_release_pixmap(struct _glx_data *gd, Display *dpy, struct _glx_win_data *wd) {
|
||||||
// Release binding
|
// Release binding
|
||||||
if (wd->glpixmap && wd->texture.texture) {
|
if (wd->glpixmap && wd->texture.texture) {
|
||||||
glBindTexture(wd->texture.target, wd->texture.texture);
|
glBindTexture(wd->texture.target, wd->texture.texture);
|
||||||
|
@ -83,12 +86,12 @@ void glx_release_pixmap(struct _glx_data *gd, Display *dpy, struct _glx_win_data
|
||||||
/**
|
/**
|
||||||
* Free a glx_texture_t.
|
* Free a glx_texture_t.
|
||||||
*/
|
*/
|
||||||
static void glx_release_win(struct _glx_data *gd, Display *dpy, gl_texture_t *ptex) {
|
static void attr_unused glx_release_win(struct _glx_data *gd, Display *dpy, struct _glx_win_data *wd) {
|
||||||
glx_release_pixmap(gd, dpy, ptex);
|
glx_release_pixmap(gd, dpy, wd);
|
||||||
glDeleteTextures(1, &ptex->texture);
|
glDeleteTextures(1, &wd->texture.texture);
|
||||||
|
|
||||||
// Free structure itself
|
// Free structure itself
|
||||||
free(ptex);
|
free(wd);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -99,7 +102,6 @@ static inline void free_win_res_glx(session_t *ps, win *w) {
|
||||||
/*free_paint_glx(ps, &w->shadow_paint);*/
|
/*free_paint_glx(ps, &w->shadow_paint);*/
|
||||||
/*free_glx_bc(ps, &w->glx_blur_cache);*/
|
/*free_glx_bc(ps, &w->glx_blur_cache);*/
|
||||||
}
|
}
|
||||||
>>>>>>> 4bc5ef8... wip glx backend:src/backend/gl/glx.c
|
|
||||||
|
|
||||||
static inline int glx_cmp_fbconfig_cmpattr(session_t *ps, const glx_fbconfig_t *pfbc_a,
|
static inline int glx_cmp_fbconfig_cmpattr(session_t *ps, const glx_fbconfig_t *pfbc_a,
|
||||||
const glx_fbconfig_t *pfbc_b, int attr) {
|
const glx_fbconfig_t *pfbc_b, int attr) {
|
||||||
|
@ -115,8 +117,8 @@ static inline int glx_cmp_fbconfig_cmpattr(session_t *ps, const glx_fbconfig_t *
|
||||||
/**
|
/**
|
||||||
* Compare two GLX FBConfig's to find the preferred one.
|
* Compare two GLX FBConfig's to find the preferred one.
|
||||||
*/
|
*/
|
||||||
static int glx_cmp_fbconfig(session_t *ps, const glx_fbconfig_t *pfbc_a,
|
static int
|
||||||
const glx_fbconfig_t *pfbc_b) {
|
glx_cmp_fbconfig(session_t *ps, const glx_fbconfig_t *pfbc_a, const glx_fbconfig_t *pfbc_b) {
|
||||||
int result = 0;
|
int result = 0;
|
||||||
|
|
||||||
if (!pfbc_a)
|
if (!pfbc_a)
|
||||||
|
@ -165,10 +167,9 @@ glx_update_fbconfig_bydepth(session_t *ps, int depth, glx_fbconfig_t *pfbcfg) {
|
||||||
|
|
||||||
// Compare new FBConfig with current one
|
// Compare new FBConfig with current one
|
||||||
if (glx_cmp_fbconfig(ps, ps->psglx->fbconfigs[depth], pfbcfg) < 0) {
|
if (glx_cmp_fbconfig(ps, ps->psglx->fbconfigs[depth], pfbcfg) < 0) {
|
||||||
log_debug(
|
log_debug("(depth %d): %p overrides %p, target %#x.\n", depth, pfbcfg->cfg,
|
||||||
"(depth %d): %p overrides %p, target %#x.\n", depth, pfbcfg->cfg,
|
ps->psglx->fbconfigs[depth] ? ps->psglx->fbconfigs[depth]->cfg : 0,
|
||||||
ps->psglx->fbconfigs[depth] ? ps->psglx->fbconfigs[depth]->cfg : 0,
|
pfbcfg->texture_tgts);
|
||||||
pfbcfg->texture_tgts);
|
|
||||||
if (!ps->psglx->fbconfigs[depth]) {
|
if (!ps->psglx->fbconfigs[depth]) {
|
||||||
ps->psglx->fbconfigs[depth] = cmalloc(glx_fbconfig_t);
|
ps->psglx->fbconfigs[depth] = cmalloc(glx_fbconfig_t);
|
||||||
}
|
}
|
||||||
|
@ -179,7 +180,7 @@ glx_update_fbconfig_bydepth(session_t *ps, int depth, glx_fbconfig_t *pfbcfg) {
|
||||||
/**
|
/**
|
||||||
* Get GLX FBConfigs for all depths.
|
* Get GLX FBConfigs for all depths.
|
||||||
*/
|
*/
|
||||||
static bool glx_update_fbconfig(session_t *ps) {
|
static bool glx_update_fbconfig(struct _glx_data *gd, session_t *ps) {
|
||||||
// Acquire all FBConfigs and loop through them
|
// Acquire all FBConfigs and loop through them
|
||||||
int nele = 0;
|
int nele = 0;
|
||||||
GLXFBConfig *pfbcfgs = glXGetFBConfigs(ps->dpy, ps->scr, &nele);
|
GLXFBConfig *pfbcfgs = glXGetFBConfigs(ps->dpy, ps->scr, &nele);
|
||||||
|
@ -202,8 +203,7 @@ static bool glx_update_fbconfig(session_t *ps) {
|
||||||
continue;
|
continue;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
if (Success !=
|
if (Success != glXGetFBConfigAttrib(ps->dpy, *pcur, GLX_BUFFER_SIZE, &depth) ||
|
||||||
glXGetFBConfigAttrib(ps->dpy, *pcur, GLX_BUFFER_SIZE, &depth) ||
|
|
||||||
Success != glXGetFBConfigAttrib(ps->dpy, *pcur, GLX_ALPHA_SIZE,
|
Success != glXGetFBConfigAttrib(ps->dpy, *pcur, GLX_ALPHA_SIZE,
|
||||||
&depth_alpha)) {
|
&depth_alpha)) {
|
||||||
log_error("Failed to retrieve buffer size and alpha size of "
|
log_error("Failed to retrieve buffer size and alpha size of "
|
||||||
|
@ -246,8 +246,7 @@ static bool glx_update_fbconfig(session_t *ps) {
|
||||||
val)
|
val)
|
||||||
rgb = true;
|
rgb = true;
|
||||||
|
|
||||||
if (Success ==
|
if (Success == glXGetFBConfigAttrib(ps->dpy, *pcur, GLX_Y_INVERTED_EXT, &val))
|
||||||
glXGetFBConfigAttrib(ps->dpy, *pcur, GLX_Y_INVERTED_EXT, &val))
|
|
||||||
fbinfo.y_inverted = val;
|
fbinfo.y_inverted = val;
|
||||||
|
|
||||||
{
|
{
|
||||||
|
@ -267,17 +266,18 @@ static bool glx_update_fbconfig(session_t *ps) {
|
||||||
cxfree(pfbcfgs);
|
cxfree(pfbcfgs);
|
||||||
|
|
||||||
// Sanity checks
|
// Sanity checks
|
||||||
if (!ps->psglx->fbconfigs[ps->depth]) {
|
if (!gd->fbconfigs[ps->depth]) {
|
||||||
log_error("No FBConfig found for default depth %d.", ps->depth);
|
log_error("No FBConfig found for default depth %d.", ps->depth);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!ps->psglx->fbconfigs[32]) {
|
if (!gd->fbconfigs[32]) {
|
||||||
log_error("No FBConfig found for depth 32. Expect crazy things.");
|
log_error("No FBConfig found for depth 32. compton may not work "
|
||||||
|
"correctly");
|
||||||
}
|
}
|
||||||
|
|
||||||
log_trace("%d-bit: %p, 32-bit: %p", ps->depth,
|
log_trace("%d-bit: %p, 32-bit: %p", ps->depth, gd->fbconfigs[ps->depth]->cfg,
|
||||||
ps->psglx->fbconfigs[ps->depth]->cfg, ps->psglx->fbconfigs[32]->cfg);
|
gd->fbconfigs[32]->cfg);
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
@ -298,9 +298,8 @@ get_fbconfig_from_visualinfo(session_t *ps, const XVisualInfo *visualinfo) {
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void glx_debug_msg_callback(GLenum source, GLenum type, GLuint id, GLenum severity,
|
||||||
glx_debug_msg_callback(GLenum source, GLenum type, GLuint id, GLenum severity,
|
GLsizei length, const GLchar *message, GLvoid *userParam) {
|
||||||
GLsizei length, const GLchar *message, GLvoid *userParam) {
|
|
||||||
log_trace("(): source 0x%04X, type 0x%04X, id %u, severity 0x%0X, \"%s\"", source,
|
log_trace("(): source 0x%04X, type 0x%04X, id %u, severity 0x%0X, \"%s\"", source,
|
||||||
type, id, severity, message);
|
type, id, severity, message);
|
||||||
}
|
}
|
||||||
|
@ -321,7 +320,7 @@ void glx_deinit(void *backend_data, session_t *ps) {
|
||||||
gl_free_blur_shader(&gd->blur_shader[i]);
|
gl_free_blur_shader(&gd->blur_shader[i]);
|
||||||
}
|
}
|
||||||
|
|
||||||
glx_free_prog_main(ps, &ps->o.glx_prog_win);
|
gl_free_prog_main(ps, &gd->win_shader);
|
||||||
|
|
||||||
gl_check_err();
|
gl_check_err();
|
||||||
|
|
||||||
|
@ -343,7 +342,7 @@ void glx_deinit(void *backend_data, session_t *ps) {
|
||||||
/**
|
/**
|
||||||
* Initialize OpenGL.
|
* Initialize OpenGL.
|
||||||
*/
|
*/
|
||||||
void *glx_init(session_t *ps) {
|
static void *glx_init(session_t *ps) {
|
||||||
bool success = false;
|
bool success = false;
|
||||||
auto gd = ccalloc(1, struct _glx_data);
|
auto gd = ccalloc(1, struct _glx_data);
|
||||||
XVisualInfo *pvis = NULL;
|
XVisualInfo *pvis = NULL;
|
||||||
|
@ -434,14 +433,6 @@ void *glx_init(session_t *ps) {
|
||||||
gd->cap.non_power_of_two_texture = gl_has_extension(ps, "GL_ARB_texture_non_"
|
gd->cap.non_power_of_two_texture = gl_has_extension(ps, "GL_ARB_texture_non_"
|
||||||
"power_of_two");
|
"power_of_two");
|
||||||
|
|
||||||
// Acquire function addresses
|
|
||||||
#if 0
|
|
||||||
psglx->glStringMarkerGREMEDY = (f_StringMarkerGREMEDY)
|
|
||||||
glXGetProcAddress((const GLubyte *) "glStringMarkerGREMEDY");
|
|
||||||
psglx->glFrameTerminatorGREMEDY = (f_FrameTerminatorGREMEDY)
|
|
||||||
glXGetProcAddress((const GLubyte *) "glFrameTerminatorGREMEDY");
|
|
||||||
#endif
|
|
||||||
|
|
||||||
gd->glXBindTexImage = (void *)glXGetProcAddress((const GLubyte *)"glXBindTexImage"
|
gd->glXBindTexImage = (void *)glXGetProcAddress((const GLubyte *)"glXBindTexImage"
|
||||||
"EXT");
|
"EXT");
|
||||||
gd->glXReleaseTexImage = (void *)glXGetProcAddress((const GLubyte *)"glXReleaseTe"
|
gd->glXReleaseTexImage = (void *)glXGetProcAddress((const GLubyte *)"glXReleaseTe"
|
||||||
|
@ -454,7 +445,7 @@ void *glx_init(session_t *ps) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Acquire FBConfigs
|
// Acquire FBConfigs
|
||||||
if (!glx_update_fbconfig(ps))
|
if (!glx_update_fbconfig(gd, ps))
|
||||||
goto end;
|
goto end;
|
||||||
|
|
||||||
// Render preparations
|
// Render preparations
|
||||||
|
@ -494,7 +485,8 @@ end:
|
||||||
/**
|
/**
|
||||||
* Initialize GLX blur filter.
|
* Initialize GLX blur filter.
|
||||||
*/
|
*/
|
||||||
bool glx_init_blur(session_t *ps) {
|
static bool attr_unused glx_init_blur(session_t *ps) {
|
||||||
|
struct _glx_data *gd = ps->backend_data;
|
||||||
assert(ps->o.blur_kerns[0]);
|
assert(ps->o.blur_kerns[0]);
|
||||||
|
|
||||||
// Allocate PBO if more than one blur kernel is present
|
// Allocate PBO if more than one blur kernel is present
|
||||||
|
@ -516,40 +508,28 @@ bool glx_init_blur(session_t *ps) {
|
||||||
// Thanks to hiciu for reporting.
|
// Thanks to hiciu for reporting.
|
||||||
setlocale(LC_NUMERIC, "C");
|
setlocale(LC_NUMERIC, "C");
|
||||||
|
|
||||||
static const char *FRAG_SHADER_BLUR_PREFIX = "#version 110\n"
|
static const char *FRAG_SHADER_BLUR_PREFIX =
|
||||||
"%s"
|
"#version 110\n"
|
||||||
"uniform float offset_x;\n"
|
"%s"
|
||||||
"uniform float offset_y;\n"
|
"uniform float offset_x;\n"
|
||||||
"uniform float "
|
"uniform float offset_y;\n"
|
||||||
"factor_center;\n"
|
"uniform float factor_center;\n"
|
||||||
"uniform %s tex_scr;\n"
|
"uniform %s tex_scr;\n\n"
|
||||||
"\n"
|
"void main() {\n"
|
||||||
"void main() {\n"
|
" vec4 sum = vec4(0.0, 0.0, 0.0, 0.0);\n";
|
||||||
" vec4 sum = vec4(0.0, "
|
static const char *FRAG_SHADER_BLUR_ADD =
|
||||||
"0.0, 0.0, 0.0);\n";
|
" sum += float(%.7g) * %s(tex_scr, vec2(gl_TexCoord[0].x + offset_x "
|
||||||
static const char *FRAG_SHADER_BLUR_ADD = " sum += float(%.7g) * "
|
"* float(%d), gl_TexCoord[0].y + offset_y * float(%d)));\n";
|
||||||
"%s(tex_scr, "
|
static const char *FRAG_SHADER_BLUR_ADD_GPUSHADER4 =
|
||||||
"vec2(gl_TexCoord[0].x + "
|
" sum += float(%.7g) * %sOffset(tex_scr, vec2(gl_TexCoord[0].x, "
|
||||||
"offset_x * float(%d), "
|
"gl_TexCoord[0].y), ivec2(%d, %d));\n";
|
||||||
"gl_TexCoord[0].y + offset_y * "
|
static const char *FRAG_SHADER_BLUR_SUFFIX =
|
||||||
"float(%d)));\n";
|
" sum += %s(tex_scr, vec2(gl_TexCoord[0].x, gl_TexCoord[0].y)) * "
|
||||||
static const char *FRAG_SHADER_BLUR_ADD_GPUSHADER4 = " sum += "
|
"factor_center;\n"
|
||||||
"float(%.7g) * "
|
" gl_FragColor = sum / (factor_center + float(%.7g));\n"
|
||||||
"%sOffset(tex_scr, "
|
"}\n";
|
||||||
"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 = !ps->psglx->has_texture_non_power_of_two;
|
const bool use_texture_rect = !gd->cap.non_power_of_two_texture;
|
||||||
const char *sampler_type =
|
const char *sampler_type =
|
||||||
(use_texture_rect ? "sampler2DRect" : "sampler2D");
|
(use_texture_rect ? "sampler2DRect" : "sampler2D");
|
||||||
const char *texture_func =
|
const char *texture_func =
|
||||||
|
@ -573,85 +553,62 @@ bool glx_init_blur(session_t *ps) {
|
||||||
glx_blur_pass_t *ppass = &ps->psglx->blur_passes[i];
|
glx_blur_pass_t *ppass = &ps->psglx->blur_passes[i];
|
||||||
|
|
||||||
// Build shader
|
// Build shader
|
||||||
{
|
int wid = XFIXED_TO_DOUBLE(kern[0]), hei = XFIXED_TO_DOUBLE(kern[1]);
|
||||||
int wid = XFIXED_TO_DOUBLE(kern[0]),
|
int nele = wid * hei - 1;
|
||||||
hei = XFIXED_TO_DOUBLE(kern[1]);
|
unsigned int len =
|
||||||
int nele = wid * hei - 1;
|
strlen(FRAG_SHADER_BLUR_PREFIX) + strlen(sampler_type) +
|
||||||
unsigned int len =
|
strlen(extension) +
|
||||||
strlen(FRAG_SHADER_BLUR_PREFIX) +
|
(strlen(shader_add) + strlen(texture_func) + 42) * nele +
|
||||||
strlen(sampler_type) + strlen(extension) +
|
strlen(FRAG_SHADER_BLUR_SUFFIX) + strlen(texture_func) + 12 + 1;
|
||||||
(strlen(shader_add) + strlen(texture_func) + 42) *
|
char *shader_str = ccalloc(len, char);
|
||||||
nele +
|
char *pc = shader_str;
|
||||||
strlen(FRAG_SHADER_BLUR_SUFFIX) +
|
sprintf(pc, FRAG_SHADER_BLUR_PREFIX, extension, sampler_type);
|
||||||
strlen(texture_func) + 12 + 1;
|
pc += strlen(pc);
|
||||||
char *shader_str = ccalloc(len, char);
|
assert(strlen(shader_str) < len);
|
||||||
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;
|
double sum = 0.0;
|
||||||
for (int j = 0; j < hei; ++j) {
|
for (int j = 0; j < hei; ++j) {
|
||||||
for (int k = 0; k < wid; ++k) {
|
for (int k = 0; k < wid; ++k) {
|
||||||
if (hei / 2 == j && wid / 2 == k)
|
if (hei / 2 == j && wid / 2 == k)
|
||||||
continue;
|
continue;
|
||||||
double val = XFIXED_TO_DOUBLE(
|
double val = XFIXED_TO_DOUBLE(kern[2 + j * wid + k]);
|
||||||
kern[2 + j * wid + k]);
|
if (0.0 == val)
|
||||||
if (0.0 == val)
|
continue;
|
||||||
continue;
|
sum += val;
|
||||||
sum += val;
|
sprintf(pc, shader_add, val, texture_func,
|
||||||
sprintf(pc, shader_add, val, texture_func,
|
k - wid / 2, j - hei / 2);
|
||||||
k - wid / 2, j - hei / 2);
|
pc += strlen(pc);
|
||||||
pc += strlen(pc);
|
assert(strlen(shader_str) < len);
|
||||||
assert(strlen(shader_str) < len);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
sprintf(pc, FRAG_SHADER_BLUR_SUFFIX, texture_func, sum);
|
|
||||||
assert(strlen(shader_str) < len);
|
|
||||||
ppass->frag_shader =
|
|
||||||
glx_create_shader(GL_FRAGMENT_SHADER, shader_str);
|
|
||||||
free(shader_str);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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) {
|
if (!ppass->frag_shader) {
|
||||||
log_error("Failed to create fragment shader %d.", i);
|
log_error("Failed to create fragment shader %d.", i);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Build program
|
// Build program
|
||||||
ppass->prog = glx_create_program(&ppass->frag_shader, 1);
|
ppass->prog = gl_create_program(&ppass->frag_shader, 1);
|
||||||
if (!ppass->prog) {
|
if (!ppass->prog) {
|
||||||
log_error("Failed to create GLSL program.");
|
log_error("Failed to create GLSL program.");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Get uniform addresses
|
// Get uniform addresses
|
||||||
#define P_GET_UNIFM_LOC(name, target) \
|
ppass->unifm_factor_center =
|
||||||
{ \
|
glGetUniformLocationChecked(ppass->prog, "factor_center");
|
||||||
ppass->target = glGetUniformLocation(ppass->prog, name); \
|
|
||||||
if (ppass->target < 0) { \
|
|
||||||
log_error("Failed to get location of %d-th uniform '" name "'. " \
|
|
||||||
"Mig" \
|
|
||||||
"ht " \
|
|
||||||
"be " \
|
|
||||||
"tro" \
|
|
||||||
"ubl" \
|
|
||||||
"eso" \
|
|
||||||
"me" \
|
|
||||||
".", \
|
|
||||||
i); \
|
|
||||||
} \
|
|
||||||
}
|
|
||||||
|
|
||||||
P_GET_UNIFM_LOC("factor_center", unifm_factor_center);
|
|
||||||
if (!ps->o.glx_use_gpushader4) {
|
if (!ps->o.glx_use_gpushader4) {
|
||||||
P_GET_UNIFM_LOC("offset_x", unifm_offset_x);
|
ppass->unifm_offset_x =
|
||||||
P_GET_UNIFM_LOC("offset_y", unifm_offset_y);
|
glGetUniformLocationChecked(ppass->prog, "offset_x");
|
||||||
|
ppass->unifm_offset_y =
|
||||||
|
glGetUniformLocationChecked(ppass->prog, "offset_y");
|
||||||
}
|
}
|
||||||
|
|
||||||
#undef P_GET_UNIFM_LOC
|
|
||||||
}
|
}
|
||||||
free(extension);
|
free(extension);
|
||||||
|
|
||||||
|
@ -660,156 +617,118 @@ bool glx_init_blur(session_t *ps) {
|
||||||
free(lc_numeric_old);
|
free(lc_numeric_old);
|
||||||
}
|
}
|
||||||
|
|
||||||
glx_check_err(ps);
|
gl_check_err();
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void *glx_prepare_win(void *backend_data, session_t *ps, win *w) {
|
||||||
|
struct _glx_data *gd = backend_data;
|
||||||
|
auto wd = ccalloc(1, struct _glx_win_data);
|
||||||
|
// Retrieve pixmap parameters, if they aren't provided
|
||||||
|
if (w->g.depth > OPENGL_MAX_DEPTH) {
|
||||||
|
log_error("Requested depth %d higher than max possible depth %d.",
|
||||||
|
w->g.depth, OPENGL_MAX_DEPTH);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
const glx_fbconfig_t *pcfg = gd->fbconfigs[w->g.depth];
|
||||||
|
if (!pcfg) {
|
||||||
|
log_error("Couldn't find FBConfig with requested depth %d", w->g.depth);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Choose a suitable texture target for our pixmap.
|
||||||
|
// Refer to GLX_EXT_texture_om_pixmap spec to see what are the mean
|
||||||
|
// of the bits in texture_tgts
|
||||||
|
GLenum tex_tgt = 0;
|
||||||
|
if (GLX_TEXTURE_2D_BIT_EXT & pcfg->texture_tgts &&
|
||||||
|
ps->psglx->has_texture_non_power_of_two)
|
||||||
|
tex_tgt = GLX_TEXTURE_2D_EXT;
|
||||||
|
else if (GLX_TEXTURE_RECTANGLE_BIT_EXT & pcfg->texture_tgts)
|
||||||
|
tex_tgt = GLX_TEXTURE_RECTANGLE_EXT;
|
||||||
|
else if (!(GLX_TEXTURE_2D_BIT_EXT & pcfg->texture_tgts))
|
||||||
|
tex_tgt = GLX_TEXTURE_RECTANGLE_EXT;
|
||||||
|
else
|
||||||
|
tex_tgt = GLX_TEXTURE_2D_EXT;
|
||||||
|
|
||||||
|
log_debug("depth %d, tgt %#x, rgba %d\n", w->g.depth, tex_tgt,
|
||||||
|
(GLX_TEXTURE_FORMAT_RGBA_EXT == pcfg->texture_fmt));
|
||||||
|
|
||||||
|
GLint attrs[] = {
|
||||||
|
GLX_TEXTURE_FORMAT_EXT, pcfg->texture_fmt, GLX_TEXTURE_TARGET_EXT, tex_tgt, 0,
|
||||||
|
};
|
||||||
|
|
||||||
|
wd->texture.target =
|
||||||
|
(GLX_TEXTURE_2D_EXT == tex_tgt ? GL_TEXTURE_2D : GL_TEXTURE_RECTANGLE);
|
||||||
|
wd->texture.y_inverted = pcfg->y_inverted;
|
||||||
|
|
||||||
|
if (ps->has_name_pixmap) {
|
||||||
|
wd->pixmap = xcb_generate_id(ps->c);
|
||||||
|
xcb_composite_name_window_pixmap(ps->c, w->id, wd->pixmap);
|
||||||
|
} else {
|
||||||
|
wd->pixmap = w->id;
|
||||||
|
}
|
||||||
|
if (!wd->pixmap) {
|
||||||
|
log_error("Failed to get pixmap for window %#010x", w->id);
|
||||||
|
goto err;
|
||||||
|
}
|
||||||
|
|
||||||
|
wd->glpixmap = glXCreatePixmap(ps->dpy, pcfg->cfg, wd->pixmap, attrs);
|
||||||
|
if (!wd->glpixmap) {
|
||||||
|
log_error("Failed to create glpixmap for window %#010x", w->id);
|
||||||
|
goto err;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Create texture
|
||||||
|
|
||||||
|
GLuint texture = 0;
|
||||||
|
GLuint target = wd->texture.target;
|
||||||
|
glGenTextures(1, &texture);
|
||||||
|
if (!texture) {
|
||||||
|
log_error("Failed to generate texture for window %#010x", w->id);
|
||||||
|
goto err;
|
||||||
|
}
|
||||||
|
|
||||||
|
glBindTexture(target, texture);
|
||||||
|
glTexParameteri(target, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
|
||||||
|
glTexParameteri(target, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
|
||||||
|
glTexParameteri(target, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
|
||||||
|
glTexParameteri(target, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
|
||||||
|
glBindTexture(target, 0);
|
||||||
|
|
||||||
|
wd->texture.texture = texture;
|
||||||
|
return wd;
|
||||||
|
err:
|
||||||
|
if (wd->pixmap && wd->pixmap != w->id) {
|
||||||
|
xcb_free_pixmap(ps->c, wd->pixmap);
|
||||||
|
}
|
||||||
|
if (wd->glpixmap) {
|
||||||
|
glXDestroyPixmap(ps->dpy, wd->glpixmap);
|
||||||
|
}
|
||||||
|
free(wd);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Bind a X pixmap to an OpenGL texture.
|
* Bind a X pixmap to an OpenGL texture.
|
||||||
*/
|
*/
|
||||||
bool glx_render_win(session_t *ps, glx_texture_t **pptex, xcb_pixmap_t pixmap,
|
bool glx_render_win(void *backend_data, session_t *ps, win *w, void *win_data,
|
||||||
unsigned width, unsigned height, unsigned depth) {
|
const region_t *reg_paint) {
|
||||||
|
struct _glx_data *gd = backend_data;
|
||||||
|
struct _glx_win_data *wd = win_data;
|
||||||
if (ps->o.backend != BKEND_GLX && ps->o.backend != BKEND_XR_GLX_HYBRID)
|
if (ps->o.backend != BKEND_GLX && ps->o.backend != BKEND_XR_GLX_HYBRID)
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
if (!pixmap) {
|
assert(wd->pixmap);
|
||||||
log_error("Binding to an empty pixmap %#010x. This can't work.", pixmap);
|
assert(wd->glpixmap);
|
||||||
return false;
|
assert(wd->texture.texture);
|
||||||
}
|
|
||||||
|
|
||||||
glx_texture_t *ptex = *pptex;
|
glBindTexture(wd->texture.target, wd->texture.texture);
|
||||||
bool need_release = true;
|
gd->glXBindTexImage(ps->dpy, wd->glpixmap, GLX_FRONT_LEFT_EXT, NULL);
|
||||||
|
glBindTexture(wd->texture.target, 0);
|
||||||
|
|
||||||
// Allocate structure
|
gl_check_err();
|
||||||
if (!ptex) {
|
|
||||||
static const glx_texture_t GLX_TEX_DEF = {
|
|
||||||
.texture = 0,
|
|
||||||
.glpixmap = 0,
|
|
||||||
.pixmap = 0,
|
|
||||||
.target = 0,
|
|
||||||
.width = 0,
|
|
||||||
.height = 0,
|
|
||||||
.depth = 0,
|
|
||||||
.y_inverted = false,
|
|
||||||
};
|
|
||||||
|
|
||||||
ptex = cmalloc(glx_texture_t);
|
|
||||||
memcpy(ptex, &GLX_TEX_DEF, sizeof(glx_texture_t));
|
|
||||||
*pptex = ptex;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Release pixmap if parameters are inconsistent
|
|
||||||
if (ptex->texture && ptex->pixmap != pixmap) {
|
|
||||||
glx_release_pixmap(ps, ptex);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Create GLX pixmap
|
|
||||||
if (!ptex->glpixmap) {
|
|
||||||
need_release = false;
|
|
||||||
|
|
||||||
// Retrieve pixmap parameters, if they aren't provided
|
|
||||||
if (!(width && height && depth)) {
|
|
||||||
Window rroot = None;
|
|
||||||
int rx = 0, ry = 0;
|
|
||||||
unsigned rbdwid = 0;
|
|
||||||
if (!XGetGeometry(ps->dpy, pixmap, &rroot, &rx, &ry, &width,
|
|
||||||
&height, &rbdwid, &depth)) {
|
|
||||||
log_error("Failed to query info of pixmap %#010x.", pixmap);
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
if (depth > OPENGL_MAX_DEPTH) {
|
|
||||||
log_error("Requested depth %d higher than max possible "
|
|
||||||
"depth %d.",
|
|
||||||
depth, OPENGL_MAX_DEPTH);
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
const glx_fbconfig_t *pcfg = ps->psglx->fbconfigs[depth];
|
|
||||||
if (!pcfg) {
|
|
||||||
log_error("Couldn't find FBConfig with requested depth %d", depth);
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Choose a suitable texture target for our pixmap.
|
|
||||||
// Refer to GLX_EXT_texture_om_pixmap spec to see what are the mean
|
|
||||||
// of the bits in texture_tgts
|
|
||||||
GLenum tex_tgt = 0;
|
|
||||||
if (GLX_TEXTURE_2D_BIT_EXT & pcfg->texture_tgts &&
|
|
||||||
ps->psglx->has_texture_non_power_of_two)
|
|
||||||
tex_tgt = GLX_TEXTURE_2D_EXT;
|
|
||||||
else if (GLX_TEXTURE_RECTANGLE_BIT_EXT & pcfg->texture_tgts)
|
|
||||||
tex_tgt = GLX_TEXTURE_RECTANGLE_EXT;
|
|
||||||
else if (!(GLX_TEXTURE_2D_BIT_EXT & pcfg->texture_tgts))
|
|
||||||
tex_tgt = GLX_TEXTURE_RECTANGLE_EXT;
|
|
||||||
else
|
|
||||||
tex_tgt = GLX_TEXTURE_2D_EXT;
|
|
||||||
|
|
||||||
log_debug("depth %d, tgt %#x, rgba %d\n", depth, tex_tgt,
|
|
||||||
(GLX_TEXTURE_FORMAT_RGBA_EXT == pcfg->texture_fmt));
|
|
||||||
|
|
||||||
GLint attrs[] = {
|
|
||||||
GLX_TEXTURE_FORMAT_EXT,
|
|
||||||
pcfg->texture_fmt,
|
|
||||||
GLX_TEXTURE_TARGET_EXT,
|
|
||||||
tex_tgt,
|
|
||||||
0,
|
|
||||||
};
|
|
||||||
|
|
||||||
ptex->glpixmap = glXCreatePixmap(ps->dpy, pcfg->cfg, pixmap, attrs);
|
|
||||||
ptex->pixmap = pixmap;
|
|
||||||
ptex->target =
|
|
||||||
(GLX_TEXTURE_2D_EXT == tex_tgt ? GL_TEXTURE_2D : GL_TEXTURE_RECTANGLE);
|
|
||||||
ptex->width = width;
|
|
||||||
ptex->height = height;
|
|
||||||
ptex->depth = depth;
|
|
||||||
ptex->y_inverted = pcfg->y_inverted;
|
|
||||||
}
|
|
||||||
if (!ptex->glpixmap) {
|
|
||||||
log_error("Failed to allocate GLX pixmap.");
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
glEnable(ptex->target);
|
|
||||||
|
|
||||||
// Create texture
|
|
||||||
if (!ptex->texture) {
|
|
||||||
need_release = false;
|
|
||||||
|
|
||||||
GLuint texture = 0;
|
|
||||||
glGenTextures(1, &texture);
|
|
||||||
glBindTexture(ptex->target, texture);
|
|
||||||
|
|
||||||
glTexParameteri(ptex->target, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
|
|
||||||
glTexParameteri(ptex->target, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
|
|
||||||
glTexParameteri(ptex->target, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
|
|
||||||
glTexParameteri(ptex->target, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
|
|
||||||
|
|
||||||
glBindTexture(ptex->target, 0);
|
|
||||||
|
|
||||||
ptex->texture = texture;
|
|
||||||
}
|
|
||||||
if (!ptex->texture) {
|
|
||||||
log_error("Failed to allocate texture.");
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
glBindTexture(ptex->target, ptex->texture);
|
|
||||||
|
|
||||||
// The specification requires rebinding whenever the content changes...
|
|
||||||
// We can't follow this, too slow.
|
|
||||||
if (need_release)
|
|
||||||
ps->psglx->glXReleaseTexImageProc(ps->dpy, ptex->glpixmap,
|
|
||||||
GLX_FRONT_LEFT_EXT);
|
|
||||||
|
|
||||||
ps->psglx->glXBindTexImageProc(ps->dpy, ptex->glpixmap, GLX_FRONT_LEFT_EXT, NULL);
|
|
||||||
|
|
||||||
// Cleanup
|
|
||||||
glBindTexture(ptex->target, 0);
|
|
||||||
glDisable(ptex->target);
|
|
||||||
|
|
||||||
glx_check_err(ps);
|
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
@ -872,7 +791,7 @@ glx_paint_pre(session_t *ps, region_t *preg) {
|
||||||
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);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
glx_check_err(ps);
|
gl_check_err();
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
|
@ -20,6 +20,10 @@
|
||||||
|
|
||||||
#include "common.h"
|
#include "common.h"
|
||||||
|
|
||||||
|
#if 0
|
||||||
|
struct _glx_data;
|
||||||
|
struct _glx_win_data;
|
||||||
|
|
||||||
void
|
void
|
||||||
glx_destroy(session_t *ps);
|
glx_destroy(session_t *ps);
|
||||||
|
|
||||||
|
@ -34,7 +38,7 @@ glx_bind_pixmap(session_t *ps, glx_texture_t **pptex, xcb_pixmap_t pixmap,
|
||||||
unsigned width, unsigned height, unsigned depth);
|
unsigned width, unsigned height, unsigned depth);
|
||||||
|
|
||||||
void
|
void
|
||||||
glx_release_pixmap(session_t *ps, glx_texture_t *ptex);
|
glx_release_pixmap(struct _glx_data *, Display *, struct _glx_win_data *);
|
||||||
|
|
||||||
void glx_paint_pre(session_t *ps, region_t *preg)
|
void glx_paint_pre(session_t *ps, region_t *preg)
|
||||||
__attribute__((nonnull(1, 2)));
|
__attribute__((nonnull(1, 2)));
|
||||||
|
@ -47,4 +51,4 @@ glx_tex_binded(const glx_texture_t *ptex, xcb_pixmap_t pixmap) {
|
||||||
return ptex && ptex->glpixmap && ptex->texture
|
return ptex && ptex->glpixmap && ptex->texture
|
||||||
&& (!pixmap || pixmap == ptex->pixmap);
|
&& (!pixmap || pixmap == ptex->pixmap);
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
|
|
@ -5,7 +5,7 @@ if get_option('new_backends')
|
||||||
|
|
||||||
# enable opengl
|
# enable opengl
|
||||||
if get_option('opengl')
|
if get_option('opengl')
|
||||||
srcs += [ files('gl/gl_common.c') ]
|
srcs += [ files('gl/gl_common.c', 'gl/glx.c') ]
|
||||||
deps += [ dependency('gl', required: true) ]
|
deps += [ dependency('gl', required: true) ]
|
||||||
cflags += [ '-DGL_GLEXT_PROTOTYPES' ]
|
cflags += [ '-DGL_GLEXT_PROTOTYPES' ]
|
||||||
endif
|
endif
|
||||||
|
|
Loading…
Reference in New Issue