commit
6a5ad609ba
|
@ -4,7 +4,6 @@
|
|||
#include <GL/gl.h>
|
||||
#include <GL/glext.h>
|
||||
|
||||
#include "common.h"
|
||||
#include "region.h"
|
||||
#include "log.h"
|
||||
|
||||
|
@ -62,6 +61,8 @@ typedef struct {
|
|||
int height;
|
||||
} gl_blur_cache_t;
|
||||
|
||||
typedef struct session session_t;
|
||||
|
||||
#define GL_PROG_MAIN_INIT \
|
||||
{ .prog = 0, .unifm_opacity = -1, .unifm_invert_color = -1, .unifm_tex = -1, }
|
||||
|
||||
|
|
|
@ -10,6 +10,7 @@
|
|||
*/
|
||||
|
||||
#include <GL/glx.h>
|
||||
#include <X11/Xlib-xcb.h>
|
||||
#include <assert.h>
|
||||
#include <pixman.h>
|
||||
#include <stdbool.h>
|
||||
|
@ -20,6 +21,7 @@
|
|||
|
||||
#include "backend/backend.h"
|
||||
#include "backend/gl/gl_common.h"
|
||||
#include "backend/gl/glx.h"
|
||||
#include "common.h"
|
||||
#include "compiler.h"
|
||||
#include "config.h"
|
||||
|
@ -27,14 +29,7 @@
|
|||
#include "region.h"
|
||||
#include "utils.h"
|
||||
#include "win.h"
|
||||
|
||||
/// @brief Wrapper of a GLX FBConfig.
|
||||
typedef struct glx_fbconfig {
|
||||
GLXFBConfig cfg;
|
||||
GLint texture_fmt;
|
||||
GLint texture_tgts;
|
||||
bool y_inverted;
|
||||
} glx_fbconfig_t;
|
||||
#include "x.h"
|
||||
|
||||
struct _glx_win_data {
|
||||
gl_texture_t texture;
|
||||
|
@ -49,13 +44,117 @@ struct _glx_data {
|
|||
gl_cap_t cap;
|
||||
gl_win_shader_t win_shader;
|
||||
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,
|
||||
const int *attrib_list);
|
||||
void (*glXReleaseTexImage)(Display *display, GLXDrawable drawable, int buffer);
|
||||
};
|
||||
|
||||
struct glx_fbconfig_info *
|
||||
glx_find_fbconfig(Display *dpy, int screen, xcb_render_pictforminfo_t *pictfmt, int depth) {
|
||||
// Alright, this might not be right, but it might just be enough to just match
|
||||
// visual against GLX_VISUAL_ID, and use the one that matches
|
||||
assert(pictfmt);
|
||||
|
||||
if (pictfmt->type != XCB_RENDER_PICT_TYPE_DIRECT) {
|
||||
log_error("compton cannot handle non-DirectColor visuals. Report an "
|
||||
"issue if you see this error message.");
|
||||
return NULL;
|
||||
}
|
||||
int red_size = popcountl(pictfmt->direct.red_mask),
|
||||
blue_size = popcountl(pictfmt->direct.blue_mask),
|
||||
green_size = popcountl(pictfmt->direct.green_mask),
|
||||
alpha_size = popcountl(pictfmt->direct.alpha_mask);
|
||||
log_debug("Looking for FBConfig for RGBA%d%d%d%d, depth %d", red_size, blue_size,
|
||||
green_size, alpha_size, depth);
|
||||
|
||||
int ncfg;
|
||||
// clang-format off
|
||||
GLXFBConfig *cfg =
|
||||
glXChooseFBConfig(dpy, screen, (int[]){
|
||||
GLX_RENDER_TYPE, GLX_RGBA_BIT,
|
||||
GLX_DRAWABLE_TYPE, GLX_PIXMAP_BIT,
|
||||
GLX_X_VISUAL_TYPE, GLX_TRUE_COLOR,
|
||||
GLX_X_RENDERABLE, true,
|
||||
GLX_FRAMEBUFFER_SRGB_CAPABLE_EXT, GLX_DONT_CARE,
|
||||
GLX_BUFFER_SIZE, red_size + green_size + blue_size + alpha_size,
|
||||
GLX_RED_SIZE, red_size,
|
||||
GLX_BLUE_SIZE, blue_size,
|
||||
GLX_GREEN_SIZE, green_size,
|
||||
GLX_ALPHA_SIZE, alpha_size,
|
||||
GLX_STENCIL_SIZE, 0,
|
||||
GLX_DEPTH_SIZE, 0,
|
||||
0
|
||||
}, &ncfg);
|
||||
// clang-format on
|
||||
|
||||
#define glXGetFBConfigAttribChecked(a, b, attr, c) \
|
||||
do { \
|
||||
if (glXGetFBConfigAttrib(a, b, attr, c)) { \
|
||||
log_info("Cannot get FBConfig attribute " #attr); \
|
||||
continue; \
|
||||
} \
|
||||
} while (0)
|
||||
int texture_tgts, y_inverted, texture_fmt;
|
||||
bool found = false;
|
||||
GLXFBConfig ret;
|
||||
for (int i = 0; i < ncfg; i++) {
|
||||
int red, green, blue;
|
||||
glXGetFBConfigAttribChecked(dpy, cfg[i], GLX_RED_SIZE, &red);
|
||||
glXGetFBConfigAttribChecked(dpy, cfg[i], GLX_BLUE_SIZE, &blue);
|
||||
glXGetFBConfigAttribChecked(dpy, cfg[i], GLX_GREEN_SIZE, &green);
|
||||
if (red != red_size || green != green_size || blue != blue_size) {
|
||||
// Color size doesn't match, this cannot work
|
||||
continue;
|
||||
}
|
||||
|
||||
int rgb, rgba;
|
||||
glXGetFBConfigAttribChecked(dpy, cfg[i], GLX_BIND_TO_TEXTURE_RGB_EXT, &rgb);
|
||||
glXGetFBConfigAttribChecked(dpy, cfg[i], GLX_BIND_TO_TEXTURE_RGBA_EXT, &rgba);
|
||||
if (!rgb && !rgba) {
|
||||
log_info("FBConfig is neither RGBA nor RGB, compton cannot "
|
||||
"handle this setup.");
|
||||
continue;
|
||||
}
|
||||
|
||||
int visual;
|
||||
glXGetFBConfigAttribChecked(dpy, cfg[i], GLX_VISUAL_ID, &visual);
|
||||
if (depth != -1 && x_get_visual_depth(XGetXCBConnection(dpy), visual) != depth) {
|
||||
// Some driver might attach fbconfig to a GLX visual with a
|
||||
// different depth. (That totally makes sense. - NVIDIA
|
||||
// developers)
|
||||
continue;
|
||||
}
|
||||
|
||||
// All check passed, we are using this one.
|
||||
found = true;
|
||||
ret = cfg[i];
|
||||
glXGetFBConfigAttribChecked(dpy, cfg[i], GLX_BIND_TO_TEXTURE_TARGETS_EXT, &texture_tgts);
|
||||
glXGetFBConfigAttribChecked(dpy, cfg[i], GLX_Y_INVERTED_EXT, &y_inverted);
|
||||
|
||||
// Prefer the texture format with matching alpha, with the other one as
|
||||
// fallback
|
||||
if (alpha_size) {
|
||||
texture_fmt = rgba ? GLX_TEXTURE_FORMAT_RGBA_EXT : GLX_TEXTURE_FORMAT_RGB_EXT;
|
||||
} else {
|
||||
texture_fmt = rgb ? GLX_TEXTURE_FORMAT_RGB_EXT : GLX_TEXTURE_FORMAT_RGBA_EXT;
|
||||
}
|
||||
break;
|
||||
}
|
||||
#undef glXGetFBConfigAttribChecked
|
||||
free(cfg);
|
||||
if (!found) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
auto info = cmalloc(struct glx_fbconfig_info);
|
||||
info->cfg = ret;
|
||||
info->texture_tgts = texture_tgts;
|
||||
info->texture_fmt = texture_fmt;
|
||||
info->y_inverted = y_inverted;
|
||||
return info;
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if a GLX extension exists.
|
||||
*/
|
||||
|
@ -120,199 +219,10 @@ static inline void free_win_res_glx(session_t *ps, win *w) {
|
|||
/*free_glx_bc(ps, &w->glx_blur_cache);*/
|
||||
}
|
||||
|
||||
static inline int glx_cmp_fbconfig_cmpattr(session_t *ps, const glx_fbconfig_t *pfbc_a,
|
||||
const glx_fbconfig_t *pfbc_b, int attr) {
|
||||
int attr_a = 0, attr_b = 0;
|
||||
|
||||
// TODO: Error checking
|
||||
glXGetFBConfigAttrib(ps->dpy, pfbc_a->cfg, attr, &attr_a);
|
||||
glXGetFBConfigAttrib(ps->dpy, pfbc_b->cfg, attr, &attr_b);
|
||||
|
||||
return attr_a - attr_b;
|
||||
}
|
||||
|
||||
/**
|
||||
* Compare two GLX FBConfig's to find the preferred one.
|
||||
*/
|
||||
static int
|
||||
glx_cmp_fbconfig(session_t *ps, const glx_fbconfig_t *pfbc_a, const glx_fbconfig_t *pfbc_b) {
|
||||
int result = 0;
|
||||
|
||||
if (!pfbc_a)
|
||||
return -1;
|
||||
if (!pfbc_b)
|
||||
return 1;
|
||||
int tmpattr;
|
||||
|
||||
// Avoid 10-bit colors
|
||||
glXGetFBConfigAttrib(ps->dpy, pfbc_a->cfg, GLX_RED_SIZE, &tmpattr);
|
||||
if (tmpattr != 8)
|
||||
return -1;
|
||||
|
||||
glXGetFBConfigAttrib(ps->dpy, pfbc_b->cfg, GLX_RED_SIZE, &tmpattr);
|
||||
if (tmpattr != 8)
|
||||
return 1;
|
||||
|
||||
#define P_CMPATTR_LT(attr) \
|
||||
{ \
|
||||
if ((result = glx_cmp_fbconfig_cmpattr(ps, pfbc_a, pfbc_b, (attr)))) \
|
||||
return -result; \
|
||||
}
|
||||
#define P_CMPATTR_GT(attr) \
|
||||
{ \
|
||||
if ((result = glx_cmp_fbconfig_cmpattr(ps, pfbc_a, pfbc_b, (attr)))) \
|
||||
return result; \
|
||||
}
|
||||
|
||||
P_CMPATTR_LT(GLX_BIND_TO_TEXTURE_RGBA_EXT);
|
||||
P_CMPATTR_LT(GLX_DOUBLEBUFFER);
|
||||
P_CMPATTR_LT(GLX_STENCIL_SIZE);
|
||||
P_CMPATTR_LT(GLX_DEPTH_SIZE);
|
||||
P_CMPATTR_GT(GLX_BIND_TO_MIPMAP_TEXTURE_EXT);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Update the FBConfig of given depth.
|
||||
*/
|
||||
static inline void glx_update_fbconfig_bydepth(session_t *ps, struct _glx_data *gd,
|
||||
int depth, glx_fbconfig_t *pfbcfg) {
|
||||
// Make sure the depth is sane
|
||||
if (depth < 0 || depth > OPENGL_MAX_DEPTH)
|
||||
return;
|
||||
|
||||
// Compare new FBConfig with current one
|
||||
if (glx_cmp_fbconfig(ps, gd->fbconfigs[depth], pfbcfg) < 0) {
|
||||
log_debug("(depth %d): %p overrides %p, target %#x.\n", depth, pfbcfg->cfg,
|
||||
gd->fbconfigs[depth] ? gd->fbconfigs[depth]->cfg : 0, pfbcfg->texture_tgts);
|
||||
if (!gd->fbconfigs[depth]) {
|
||||
gd->fbconfigs[depth] = cmalloc(glx_fbconfig_t);
|
||||
}
|
||||
(*gd->fbconfigs[depth]) = *pfbcfg;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get GLX FBConfigs for all depths.
|
||||
*/
|
||||
static bool glx_update_fbconfig(struct _glx_data *gd, session_t *ps) {
|
||||
// Acquire all FBConfigs and loop through them
|
||||
int nele = 0;
|
||||
GLXFBConfig *pfbcfgs = glXGetFBConfigs(ps->dpy, ps->scr, &nele);
|
||||
|
||||
for (GLXFBConfig *pcur = pfbcfgs; pcur < pfbcfgs + nele; pcur++) {
|
||||
glx_fbconfig_t fbinfo = {
|
||||
.cfg = *pcur,
|
||||
.texture_fmt = 0,
|
||||
.texture_tgts = 0,
|
||||
.y_inverted = false,
|
||||
};
|
||||
int id = (int)(pcur - pfbcfgs);
|
||||
int depth = 0, depth_alpha = 0, val = 0;
|
||||
|
||||
// Skip over multi-sampled visuals
|
||||
// http://people.freedesktop.org/~glisse/0001-glx-do-not-use-multisample-visual-config-for-front-o.patch
|
||||
#ifdef GLX_SAMPLES
|
||||
if (Success == glXGetFBConfigAttrib(ps->dpy, *pcur, GLX_SAMPLES, &val) && val > 1)
|
||||
continue;
|
||||
#endif
|
||||
|
||||
if (Success != glXGetFBConfigAttrib(ps->dpy, *pcur, GLX_BUFFER_SIZE, &depth) ||
|
||||
Success != glXGetFBConfigAttrib(ps->dpy, *pcur, GLX_ALPHA_SIZE, &depth_alpha)) {
|
||||
log_error("Failed to retrieve buffer size and alpha size of "
|
||||
"FBConfig %d.",
|
||||
id);
|
||||
continue;
|
||||
}
|
||||
if (Success != glXGetFBConfigAttrib(ps->dpy, *pcur, GLX_BIND_TO_TEXTURE_TARGETS_EXT,
|
||||
&fbinfo.texture_tgts)) {
|
||||
log_error("Failed to retrieve BIND_TO_TEXTURE_TARGETS_EXT of "
|
||||
"FBConfig %d.",
|
||||
id);
|
||||
continue;
|
||||
}
|
||||
|
||||
int visualdepth = 0;
|
||||
{
|
||||
XVisualInfo *pvi = glXGetVisualFromFBConfig(ps->dpy, *pcur);
|
||||
if (!pvi) {
|
||||
// On nvidia-drivers-325.08 this happens slightly too often...
|
||||
// log_error("Failed to retrieve X Visual of FBConfig %d.", id);
|
||||
continue;
|
||||
}
|
||||
visualdepth = pvi->depth;
|
||||
cxfree(pvi);
|
||||
}
|
||||
|
||||
bool rgb = false;
|
||||
bool rgba = false;
|
||||
|
||||
if (depth >= 32 && depth_alpha &&
|
||||
Success == glXGetFBConfigAttrib(ps->dpy, *pcur, GLX_BIND_TO_TEXTURE_RGBA_EXT, &val) && val)
|
||||
rgba = true;
|
||||
|
||||
if (Success == glXGetFBConfigAttrib(ps->dpy, *pcur, GLX_BIND_TO_TEXTURE_RGB_EXT, &val) && val)
|
||||
rgb = true;
|
||||
|
||||
if (Success == glXGetFBConfigAttrib(ps->dpy, *pcur, GLX_Y_INVERTED_EXT, &val))
|
||||
fbinfo.y_inverted = val;
|
||||
|
||||
{
|
||||
int tgtdpt = depth - depth_alpha;
|
||||
if (tgtdpt == visualdepth && tgtdpt < 32 && rgb) {
|
||||
fbinfo.texture_fmt = GLX_TEXTURE_FORMAT_RGB_EXT;
|
||||
glx_update_fbconfig_bydepth(ps, gd, tgtdpt, &fbinfo);
|
||||
}
|
||||
}
|
||||
|
||||
if (depth == visualdepth && rgba) {
|
||||
fbinfo.texture_fmt = GLX_TEXTURE_FORMAT_RGBA_EXT;
|
||||
glx_update_fbconfig_bydepth(ps, gd, depth, &fbinfo);
|
||||
}
|
||||
}
|
||||
|
||||
cxfree(pfbcfgs);
|
||||
|
||||
// Sanity checks
|
||||
if (!gd->fbconfigs[ps->depth]) {
|
||||
log_error("No FBConfig found for default depth %d.", ps->depth);
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!gd->fbconfigs[32]) {
|
||||
log_error("No FBConfig found for depth 32. compton may not work "
|
||||
"correctly");
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
#ifdef DEBUG_GLX_DEBUG_CONTEXT
|
||||
static inline GLXFBConfig get_fbconfig_from_visualinfo(session_t *ps, const XVisualInfo *visualinfo) {
|
||||
int nelements = 0;
|
||||
GLXFBConfig *fbconfigs = glXGetFBConfigs(ps->dpy, visualinfo->screen, &nelements);
|
||||
for (int i = 0; i < nelements; ++i) {
|
||||
int visual_id = 0;
|
||||
if (Success == glXGetFBConfigAttrib(ps->dpy, fbconfigs[i], GLX_VISUAL_ID, &visual_id) &&
|
||||
visual_id == visualinfo->visualid)
|
||||
return fbconfigs[i];
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static void glx_debug_msg_callback(GLenum source, GLenum type, GLuint id, GLenum severity,
|
||||
GLsizei length, const GLchar *message, GLvoid *userParam) {
|
||||
log_trace("(): source 0x%04X, type 0x%04X, id %u, severity 0x%0X, \"%s\"", source,
|
||||
type, id, severity, message);
|
||||
}
|
||||
#endif
|
||||
|
||||
/**
|
||||
* Destroy GLX related resources.
|
||||
*/
|
||||
void glx_deinit(void *backend_data, session_t *ps) {
|
||||
static void glx_deinit(void *backend_data, session_t *ps) {
|
||||
struct _glx_data *gd = backend_data;
|
||||
|
||||
// Free all GLX resources of windows
|
||||
|
@ -328,12 +238,6 @@ void glx_deinit(void *backend_data, session_t *ps) {
|
|||
|
||||
gl_check_err();
|
||||
|
||||
// Free FBConfigs
|
||||
for (int i = 0; i <= OPENGL_MAX_DEPTH; ++i) {
|
||||
free(gd->fbconfigs[i]);
|
||||
gd->fbconfigs[i] = NULL;
|
||||
}
|
||||
|
||||
// Destroy GLX context
|
||||
if (gd->ctx) {
|
||||
glXDestroyContext(ps->dpy, gd->ctx);
|
||||
|
@ -448,10 +352,6 @@ static void *glx_init(session_t *ps) {
|
|||
goto end;
|
||||
}
|
||||
|
||||
// Acquire FBConfigs
|
||||
if (!glx_update_fbconfig(gd, ps))
|
||||
goto end;
|
||||
|
||||
// Render preparations
|
||||
gl_resize(ps->root_width, ps->root_height);
|
||||
|
||||
|
@ -490,7 +390,7 @@ end:
|
|||
return gd;
|
||||
}
|
||||
|
||||
void *glx_prepare_win(void *backend_data, session_t *ps, win *w) {
|
||||
static void *glx_prepare_win(void *backend_data, session_t *ps, win *w) {
|
||||
struct _glx_data *gd = backend_data;
|
||||
// Retrieve pixmap parameters, if they aren't provided
|
||||
if (w->g.depth > OPENGL_MAX_DEPTH) {
|
||||
|
@ -499,36 +399,7 @@ void *glx_prepare_win(void *backend_data, session_t *ps, win *w) {
|
|||
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 && gd->cap.non_power_of_two_texture)
|
||||
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,
|
||||
};
|
||||
|
||||
auto wd = ccalloc(1, struct _glx_win_data);
|
||||
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);
|
||||
|
@ -540,7 +411,48 @@ void *glx_prepare_win(void *backend_data, session_t *ps, win *w) {
|
|||
goto err;
|
||||
}
|
||||
|
||||
wd->glpixmap = glXCreatePixmap(ps->dpy, pcfg->cfg, wd->pixmap, attrs);
|
||||
auto pictfmt = x_get_pictform_for_visual(ps->c, w->a.visual);
|
||||
if (!pictfmt) {
|
||||
log_error("Window %#010x has invalid visual %#x", w->id, w->a.visual);
|
||||
goto err;
|
||||
}
|
||||
int depth = x_get_visual_depth(ps->c, w->a.visual);
|
||||
auto fbcfg = glx_find_fbconfig(ps->dpy, ps->scr, pictfmt, depth);
|
||||
if (!fbcfg) {
|
||||
log_error("Couldn't find FBConfig with requested visual %x", w->a.visual);
|
||||
goto err;
|
||||
}
|
||||
|
||||
// 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 & fbcfg->texture_tgts && gd->cap.non_power_of_two_texture)
|
||||
tex_tgt = GLX_TEXTURE_2D_EXT;
|
||||
else if (GLX_TEXTURE_RECTANGLE_BIT_EXT & fbcfg->texture_tgts)
|
||||
tex_tgt = GLX_TEXTURE_RECTANGLE_EXT;
|
||||
else if (!(GLX_TEXTURE_2D_BIT_EXT & fbcfg->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 == fbcfg->texture_fmt));
|
||||
|
||||
GLint attrs[] = {
|
||||
GLX_TEXTURE_FORMAT_EXT,
|
||||
fbcfg->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 = fbcfg->y_inverted;
|
||||
|
||||
wd->glpixmap = glXCreatePixmap(ps->dpy, fbcfg->cfg, wd->pixmap, attrs);
|
||||
free(fbcfg);
|
||||
|
||||
if (!wd->glpixmap) {
|
||||
log_error("Failed to create glpixmap for window %#010x", w->id);
|
||||
goto err;
|
||||
|
@ -581,7 +493,8 @@ err:
|
|||
/**
|
||||
* Bind a X pixmap to an OpenGL texture.
|
||||
*/
|
||||
void glx_render_win(void *backend_data, session_t *ps, win *w, void *win_data, const region_t *reg_paint) {
|
||||
static void glx_render_win(void *backend_data, session_t *ps, win *w, void *win_data,
|
||||
const region_t *reg_paint) {
|
||||
struct _glx_data *gd = backend_data;
|
||||
struct _glx_win_data *wd = win_data;
|
||||
|
||||
|
|
|
@ -0,0 +1,15 @@
|
|||
#pragma once
|
||||
#include <GL/glx.h>
|
||||
#include <X11/Xlib.h>
|
||||
#include <xcb/render.h>
|
||||
#include <xcb/xcb.h>
|
||||
|
||||
struct glx_fbconfig_info {
|
||||
GLXFBConfig cfg;
|
||||
int texture_tgts;
|
||||
int texture_fmt;
|
||||
int y_inverted;
|
||||
};
|
||||
|
||||
struct glx_fbconfig_info *
|
||||
glx_find_fbconfig(Display *, int screen, xcb_render_pictforminfo_t *, int depth);
|
|
@ -2,13 +2,9 @@
|
|||
srcs += [ files('backend_common.c') ]
|
||||
if get_option('new_backends')
|
||||
srcs += [ files('xrender.c', 'backend.c') ]
|
||||
|
||||
# enable opengl
|
||||
if get_option('opengl')
|
||||
srcs += [ files('gl/gl_common.c', 'gl/glx.c') ]
|
||||
endif
|
||||
endif
|
||||
|
||||
# enable opengl
|
||||
if get_option('opengl')
|
||||
srcs += [ files('gl/gl_common.c') ]
|
||||
srcs += [ files('gl/gl_common.c', 'gl/glx.c') ]
|
||||
endif
|
||||
|
|
|
@ -221,7 +221,6 @@ struct _glx_texture {
|
|||
GLenum target;
|
||||
unsigned width;
|
||||
unsigned height;
|
||||
unsigned depth;
|
||||
bool y_inverted;
|
||||
};
|
||||
|
||||
|
@ -310,8 +309,6 @@ typedef struct {
|
|||
f_ImportSyncEXT glImportSyncEXT;
|
||||
/// Current GLX Z value.
|
||||
int z;
|
||||
/// FBConfig-s for GLX pixmap of different depths.
|
||||
glx_fbconfig_t *fbconfigs[OPENGL_MAX_DEPTH + 1];
|
||||
#ifdef CONFIG_OPENGL
|
||||
glx_blur_pass_t blur_passes[MAX_BLUR_PASS];
|
||||
#endif
|
||||
|
|
|
@ -68,6 +68,9 @@ module backend {
|
|||
module gl_common {
|
||||
header "backend/gl/gl_common.h"
|
||||
}
|
||||
module glx {
|
||||
header "backend/gl/glx.h"
|
||||
}
|
||||
}
|
||||
module backend {
|
||||
header "backend/backend.h"
|
||||
|
|
230
src/opengl.c
230
src/opengl.c
|
@ -25,173 +25,10 @@
|
|||
#include "win.h"
|
||||
#include "region.h"
|
||||
#include "backend/gl/gl_common.h"
|
||||
#include "backend/gl/glx.h"
|
||||
|
||||
#include "opengl.h"
|
||||
|
||||
static inline int
|
||||
glx_cmp_fbconfig_cmpattr(session_t *ps,
|
||||
const glx_fbconfig_t *pfbc_a, const glx_fbconfig_t *pfbc_b,
|
||||
int attr) {
|
||||
int attr_a = 0, attr_b = 0;
|
||||
|
||||
// TODO: Error checking
|
||||
glXGetFBConfigAttrib(ps->dpy, pfbc_a->cfg, attr, &attr_a);
|
||||
glXGetFBConfigAttrib(ps->dpy, pfbc_b->cfg, attr, &attr_b);
|
||||
|
||||
return attr_a - attr_b;
|
||||
}
|
||||
|
||||
/**
|
||||
* Compare two GLX FBConfig's to find the preferred one.
|
||||
*/
|
||||
static int
|
||||
glx_cmp_fbconfig(session_t *ps,
|
||||
const glx_fbconfig_t *pfbc_a, const glx_fbconfig_t *pfbc_b) {
|
||||
int result = 0;
|
||||
|
||||
if (!pfbc_a)
|
||||
return -1;
|
||||
if (!pfbc_b)
|
||||
return 1;
|
||||
int tmpattr;
|
||||
|
||||
// Avoid 10-bit colors
|
||||
glXGetFBConfigAttrib(ps->dpy, pfbc_a->cfg, GLX_RED_SIZE, &tmpattr);
|
||||
if (tmpattr != 8)
|
||||
return -1;
|
||||
|
||||
glXGetFBConfigAttrib(ps->dpy, pfbc_b->cfg, GLX_RED_SIZE, &tmpattr);
|
||||
if (tmpattr != 8)
|
||||
return 1;
|
||||
|
||||
#define P_CMPATTR_LT(attr) { if ((result = glx_cmp_fbconfig_cmpattr(ps, pfbc_a, pfbc_b, (attr)))) return -result; }
|
||||
#define P_CMPATTR_GT(attr) { if ((result = glx_cmp_fbconfig_cmpattr(ps, pfbc_a, pfbc_b, (attr)))) return result; }
|
||||
|
||||
P_CMPATTR_LT(GLX_BIND_TO_TEXTURE_RGBA_EXT);
|
||||
P_CMPATTR_LT(GLX_DOUBLEBUFFER);
|
||||
P_CMPATTR_LT(GLX_STENCIL_SIZE);
|
||||
P_CMPATTR_LT(GLX_DEPTH_SIZE);
|
||||
P_CMPATTR_GT(GLX_BIND_TO_MIPMAP_TEXTURE_EXT);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Update the FBConfig of given depth.
|
||||
*/
|
||||
static inline void
|
||||
glx_update_fbconfig_bydepth(session_t *ps, int depth, glx_fbconfig_t *pfbcfg) {
|
||||
// Make sure the depth is sane
|
||||
if (depth < 0 || depth > OPENGL_MAX_DEPTH)
|
||||
return;
|
||||
|
||||
// Compare new FBConfig with current one
|
||||
if (glx_cmp_fbconfig(ps, ps->psglx->fbconfigs[depth], pfbcfg) < 0) {
|
||||
log_trace("(depth %d): %p overrides %p, target %#x.", depth,
|
||||
pfbcfg->cfg,
|
||||
ps->psglx->fbconfigs[depth] ? ps->psglx->fbconfigs[depth]->cfg:
|
||||
0,
|
||||
pfbcfg->texture_tgts);
|
||||
if (!ps->psglx->fbconfigs[depth]) {
|
||||
ps->psglx->fbconfigs[depth] = cmalloc(glx_fbconfig_t);
|
||||
}
|
||||
(*ps->psglx->fbconfigs[depth]) = *pfbcfg;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get GLX FBConfigs for all depths.
|
||||
*/
|
||||
static bool
|
||||
glx_update_fbconfig(session_t *ps) {
|
||||
// Acquire all FBConfigs and loop through them
|
||||
int nele = 0;
|
||||
GLXFBConfig* pfbcfgs = glXGetFBConfigs(ps->dpy, ps->scr, &nele);
|
||||
|
||||
for (GLXFBConfig *pcur = pfbcfgs; pcur < pfbcfgs + nele; pcur++) {
|
||||
glx_fbconfig_t fbinfo = {
|
||||
.cfg = *pcur,
|
||||
.texture_fmt = 0,
|
||||
.texture_tgts = 0,
|
||||
.y_inverted = false,
|
||||
};
|
||||
int id = (int) (pcur - pfbcfgs);
|
||||
int depth = 0, depth_alpha = 0, val = 0;
|
||||
|
||||
// Skip over multi-sampled visuals
|
||||
// http://people.freedesktop.org/~glisse/0001-glx-do-not-use-multisample-visual-config-for-front-o.patch
|
||||
#ifdef GLX_SAMPLES
|
||||
if (Success == glXGetFBConfigAttrib(ps->dpy, *pcur, GLX_SAMPLES, &val)
|
||||
&& val > 1)
|
||||
continue;
|
||||
#endif
|
||||
|
||||
if (Success != glXGetFBConfigAttrib(ps->dpy, *pcur, GLX_BUFFER_SIZE, &depth)
|
||||
|| Success != glXGetFBConfigAttrib(ps->dpy, *pcur, GLX_ALPHA_SIZE, &depth_alpha)) {
|
||||
log_error("Failed to retrieve buffer size and alpha size of FBConfig %d.", id);
|
||||
continue;
|
||||
}
|
||||
if (Success != glXGetFBConfigAttrib(ps->dpy, *pcur, GLX_BIND_TO_TEXTURE_TARGETS_EXT, &fbinfo.texture_tgts)) {
|
||||
log_error("Failed to retrieve BIND_TO_TEXTURE_TARGETS_EXT of FBConfig %d.", id);
|
||||
continue;
|
||||
}
|
||||
|
||||
int visualdepth = 0;
|
||||
{
|
||||
XVisualInfo *pvi = glXGetVisualFromFBConfig(ps->dpy, *pcur);
|
||||
if (!pvi) {
|
||||
// On nvidia-drivers-325.08 this happens slightly too often...
|
||||
// log_error("Failed to retrieve X Visual of FBConfig %d.", id);
|
||||
continue;
|
||||
}
|
||||
visualdepth = pvi->depth;
|
||||
cxfree(pvi);
|
||||
}
|
||||
|
||||
bool rgb = false;
|
||||
bool rgba = false;
|
||||
|
||||
if (depth >= 32 && depth_alpha && Success == glXGetFBConfigAttrib(ps->dpy, *pcur, GLX_BIND_TO_TEXTURE_RGBA_EXT, &val) && val)
|
||||
rgba = true;
|
||||
|
||||
if (Success == glXGetFBConfigAttrib(ps->dpy, *pcur, GLX_BIND_TO_TEXTURE_RGB_EXT, &val) && val)
|
||||
rgb = true;
|
||||
|
||||
if (Success == glXGetFBConfigAttrib(ps->dpy, *pcur, GLX_Y_INVERTED_EXT, &val))
|
||||
fbinfo.y_inverted = val;
|
||||
|
||||
{
|
||||
int tgtdpt = depth - depth_alpha;
|
||||
if (tgtdpt == visualdepth && tgtdpt < 32 && rgb) {
|
||||
fbinfo.texture_fmt = GLX_TEXTURE_FORMAT_RGB_EXT;
|
||||
glx_update_fbconfig_bydepth(ps, tgtdpt, &fbinfo);
|
||||
}
|
||||
}
|
||||
|
||||
if (depth == visualdepth && rgba) {
|
||||
fbinfo.texture_fmt = GLX_TEXTURE_FORMAT_RGBA_EXT;
|
||||
glx_update_fbconfig_bydepth(ps, depth, &fbinfo);
|
||||
}
|
||||
}
|
||||
|
||||
cxfree(pfbcfgs);
|
||||
|
||||
// Sanity checks
|
||||
if (!ps->psglx->fbconfigs[ps->depth]) {
|
||||
log_error("No FBConfig found for default depth %d.", ps->depth);
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!ps->psglx->fbconfigs[32]) {
|
||||
log_error("No FBConfig found for depth 32. compton will try to continue.");
|
||||
} else {
|
||||
log_trace("%d-bit: %p, 32-bit: %p", ps->depth,
|
||||
ps->psglx->fbconfigs[ps->depth]->cfg, ps->psglx->fbconfigs[32]->cfg);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static inline XVisualInfo *
|
||||
get_visualinfo_from_visual(session_t *ps, xcb_visualid_t visual) {
|
||||
XVisualInfo vreq = { .visualid = visual };
|
||||
|
@ -200,31 +37,6 @@ get_visualinfo_from_visual(session_t *ps, xcb_visualid_t visual) {
|
|||
return XGetVisualInfo(ps->dpy, VisualIDMask, &vreq, &nitems);
|
||||
}
|
||||
|
||||
#ifdef DEBUG_GLX_DEBUG_CONTEXT
|
||||
static inline GLXFBConfig
|
||||
get_fbconfig_from_visualinfo(session_t *ps, const XVisualInfo *visualinfo) {
|
||||
int nelements = 0;
|
||||
GLXFBConfig *fbconfigs = glXGetFBConfigs(ps->dpy, visualinfo->screen,
|
||||
&nelements);
|
||||
for (int i = 0; i < nelements; ++i) {
|
||||
int visual_id = 0;
|
||||
if (Success == glXGetFBConfigAttrib(ps->dpy, fbconfigs[i], GLX_VISUAL_ID, &visual_id)
|
||||
&& visual_id == visualinfo->visualid)
|
||||
return fbconfigs[i];
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static void
|
||||
glx_debug_msg_callback(GLenum source, GLenum type,
|
||||
GLuint id, GLenum severity, GLsizei length, const GLchar *message,
|
||||
GLvoid *userParam) {
|
||||
log_trace("source 0x%04X, type 0x%04X, id %u, severity 0x%0X, \"%s\"",
|
||||
source, type, id, severity, message);
|
||||
}
|
||||
#endif
|
||||
|
||||
/**
|
||||
* Initialize OpenGL.
|
||||
*/
|
||||
|
@ -375,10 +187,6 @@ glx_init(session_t *ps, bool need_render) {
|
|||
}
|
||||
}
|
||||
|
||||
// Acquire FBConfigs
|
||||
if (need_render && !glx_update_fbconfig(ps))
|
||||
goto glx_init_end;
|
||||
|
||||
// Render preparations
|
||||
if (need_render) {
|
||||
glx_on_root_change(ps);
|
||||
|
@ -451,12 +259,6 @@ glx_destroy(session_t *ps) {
|
|||
|
||||
gl_check_err();
|
||||
|
||||
// Free FBConfigs
|
||||
for (int i = 0; i <= OPENGL_MAX_DEPTH; ++i) {
|
||||
free(ps->psglx->fbconfigs[i]);
|
||||
ps->psglx->fbconfigs[i] = NULL;
|
||||
}
|
||||
|
||||
// Destroy GLX context
|
||||
if (ps->psglx->context) {
|
||||
glXDestroyContext(ps->dpy, ps->psglx->context);
|
||||
|
@ -694,7 +496,7 @@ glx_load_prog_main(session_t *ps,
|
|||
*/
|
||||
bool
|
||||
glx_bind_pixmap(session_t *ps, glx_texture_t **pptex, xcb_pixmap_t pixmap,
|
||||
unsigned width, unsigned height, unsigned depth) {
|
||||
unsigned width, unsigned height, const struct glx_fbconfig_info *fbcfg) {
|
||||
if (ps->o.backend != BKEND_GLX && ps->o.backend != BKEND_XR_GLX_HYBRID)
|
||||
return true;
|
||||
|
||||
|
@ -703,6 +505,7 @@ glx_bind_pixmap(session_t *ps, glx_texture_t **pptex, xcb_pixmap_t pixmap,
|
|||
return false;
|
||||
}
|
||||
|
||||
assert(fbcfg);
|
||||
glx_texture_t *ptex = *pptex;
|
||||
bool need_release = true;
|
||||
|
||||
|
@ -715,7 +518,6 @@ glx_bind_pixmap(session_t *ps, glx_texture_t **pptex, xcb_pixmap_t pixmap,
|
|||
.target = 0,
|
||||
.width = 0,
|
||||
.height = 0,
|
||||
.depth = 0,
|
||||
.y_inverted = false,
|
||||
};
|
||||
|
||||
|
@ -731,11 +533,12 @@ glx_bind_pixmap(session_t *ps, glx_texture_t **pptex, xcb_pixmap_t pixmap,
|
|||
}
|
||||
|
||||
// Create GLX pixmap
|
||||
unsigned depth;
|
||||
if (!ptex->glpixmap) {
|
||||
need_release = false;
|
||||
|
||||
// Retrieve pixmap parameters, if they aren't provided
|
||||
if (!(width && height && depth)) {
|
||||
if (!(width && height)) {
|
||||
Window rroot = None;
|
||||
int rx = 0, ry = 0;
|
||||
unsigned rbdwid = 0;
|
||||
|
@ -751,45 +554,38 @@ glx_bind_pixmap(session_t *ps, glx_texture_t **pptex, xcb_pixmap_t pixmap,
|
|||
}
|
||||
}
|
||||
|
||||
const glx_fbconfig_t *pcfg = ps->psglx->fbconfigs[depth];
|
||||
if (!pcfg) {
|
||||
log_error("Couldn't find FBConfig with requested depth %d.", depth);
|
||||
return false;
|
||||
}
|
||||
|
||||
// Determine texture target, copied from compiz
|
||||
// The assumption we made here is the target never changes based on any
|
||||
// pixmap-specific parameters, and this may change in the future
|
||||
GLenum tex_tgt = 0;
|
||||
if (GLX_TEXTURE_2D_BIT_EXT & pcfg->texture_tgts
|
||||
if (GLX_TEXTURE_2D_BIT_EXT & fbcfg->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)
|
||||
else if (GLX_TEXTURE_RECTANGLE_BIT_EXT & fbcfg->texture_tgts)
|
||||
tex_tgt = GLX_TEXTURE_RECTANGLE_EXT;
|
||||
else if (!(GLX_TEXTURE_2D_BIT_EXT & pcfg->texture_tgts))
|
||||
else if (!(GLX_TEXTURE_2D_BIT_EXT & fbcfg->texture_tgts))
|
||||
tex_tgt = GLX_TEXTURE_RECTANGLE_EXT;
|
||||
else
|
||||
tex_tgt = GLX_TEXTURE_2D_EXT;
|
||||
|
||||
log_debug("depth %d, tgt %#x, rgba %d", depth, tex_tgt,
|
||||
(GLX_TEXTURE_FORMAT_RGBA_EXT == pcfg->texture_fmt));
|
||||
(GLX_TEXTURE_FORMAT_RGBA_EXT == fbcfg->texture_fmt));
|
||||
|
||||
GLint attrs[] = {
|
||||
GLX_TEXTURE_FORMAT_EXT,
|
||||
pcfg->texture_fmt,
|
||||
fbcfg->texture_fmt,
|
||||
GLX_TEXTURE_TARGET_EXT,
|
||||
tex_tgt,
|
||||
0,
|
||||
};
|
||||
|
||||
ptex->glpixmap = glXCreatePixmap(ps->dpy, pcfg->cfg, pixmap, attrs);
|
||||
ptex->glpixmap = glXCreatePixmap(ps->dpy, fbcfg->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;
|
||||
ptex->y_inverted = fbcfg->y_inverted;
|
||||
}
|
||||
if (!ptex->glpixmap) {
|
||||
log_error("Failed to allocate GLX pixmap.");
|
||||
|
@ -1186,8 +982,6 @@ glx_render(session_t *ps, const glx_texture_t *ptex,
|
|||
return false;
|
||||
}
|
||||
|
||||
argb = argb || (GLX_TEXTURE_FORMAT_RGBA_EXT ==
|
||||
ps->psglx->fbconfigs[ptex->depth]->texture_fmt);
|
||||
const bool has_prog = pprogram && pprogram->prog;
|
||||
bool dual_texture = false;
|
||||
|
||||
|
|
12
src/opengl.h
12
src/opengl.h
|
@ -19,20 +19,13 @@
|
|||
#include "log.h"
|
||||
|
||||
#include <xcb/xcb.h>
|
||||
#include <xcb/render.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <ctype.h>
|
||||
#include <locale.h>
|
||||
#include <GL/glx.h>
|
||||
|
||||
/// @brief Wrapper of a GLX FBConfig.
|
||||
typedef struct glx_fbconfig {
|
||||
GLXFBConfig cfg;
|
||||
GLint texture_fmt;
|
||||
GLint texture_tgts;
|
||||
bool y_inverted;
|
||||
} glx_fbconfig_t;
|
||||
|
||||
/**
|
||||
* Check if a word is in string.
|
||||
*/
|
||||
|
@ -108,7 +101,7 @@ glx_load_prog_main(session_t *ps,
|
|||
|
||||
bool
|
||||
glx_bind_pixmap(session_t *ps, glx_texture_t **pptex, xcb_pixmap_t pixmap,
|
||||
unsigned width, unsigned height, unsigned depth);
|
||||
unsigned width, unsigned height, const struct glx_fbconfig_info *);
|
||||
|
||||
void
|
||||
glx_release_pixmap(session_t *ps, glx_texture_t *ptex);
|
||||
|
@ -249,5 +242,6 @@ free_win_res_glx(session_t *ps, win *w) {
|
|||
free_paint_glx(ps, &w->shadow_paint);
|
||||
#ifdef CONFIG_OPENGL
|
||||
free_glx_bc(ps, &w->glx_blur_cache);
|
||||
free(w->paint.fbcfg);
|
||||
#endif
|
||||
}
|
||||
|
|
114
src/render.c
114
src/render.c
|
@ -3,10 +3,10 @@
|
|||
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <xcb/xcb_image.h>
|
||||
#include <xcb/composite.h>
|
||||
#include <xcb/sync.h>
|
||||
#include <xcb/render.h>
|
||||
#include <xcb/sync.h>
|
||||
#include <xcb/xcb_image.h>
|
||||
#include <xcb/xcb_renderutil.h>
|
||||
|
||||
#include "common.h"
|
||||
|
@ -17,40 +17,78 @@
|
|||
#include "opengl.h"
|
||||
#endif
|
||||
|
||||
#include "vsync.h"
|
||||
#include "win.h"
|
||||
#include "kernel.h"
|
||||
#include "compiler.h"
|
||||
#include "x.h"
|
||||
#include "config.h"
|
||||
#include "region.h"
|
||||
#include "kernel.h"
|
||||
#include "log.h"
|
||||
#include "region.h"
|
||||
#include "types.h"
|
||||
#include "utils.h"
|
||||
#include "vsync.h"
|
||||
#include "win.h"
|
||||
#include "x.h"
|
||||
|
||||
#include "backend/backend_common.h"
|
||||
#include "backend/gl/glx.h"
|
||||
#include "render.h"
|
||||
|
||||
#ifdef CONFIG_OPENGL
|
||||
/**
|
||||
* Bind texture in paint_t if we are using GLX backend.
|
||||
*/
|
||||
static inline bool paint_bind_tex(session_t *ps, paint_t *ppaint, unsigned wid,
|
||||
unsigned hei, unsigned depth, bool force) {
|
||||
static inline bool paint_bind_tex(session_t *ps, paint_t *ppaint, unsigned wid, unsigned hei,
|
||||
unsigned depth, xcb_visualid_t visual, bool force) {
|
||||
#ifdef CONFIG_OPENGL
|
||||
// XXX This is a mess. But this will go away after the backend refactor.
|
||||
static thread_local struct glx_fbconfig_info *argb_fbconfig = NULL;
|
||||
if (!ppaint->pixmap)
|
||||
return false;
|
||||
|
||||
if (force || !glx_tex_binded(ppaint->ptex, ppaint->pixmap))
|
||||
return glx_bind_pixmap(ps, &ppaint->ptex, ppaint->pixmap, wid, hei, depth);
|
||||
struct glx_fbconfig_info *fbcfg;
|
||||
if (!visual) {
|
||||
assert(depth == 32);
|
||||
if (!argb_fbconfig) {
|
||||
xcb_render_pictforminfo_t tmp_pictfmt = {
|
||||
.direct =
|
||||
{
|
||||
.red_mask = 255,
|
||||
.blue_mask = 255,
|
||||
.green_mask = 255,
|
||||
.alpha_mask = 255,
|
||||
},
|
||||
.type = XCB_RENDER_PICT_TYPE_DIRECT};
|
||||
argb_fbconfig = glx_find_fbconfig(ps->dpy, ps->scr, &tmp_pictfmt, 32);
|
||||
}
|
||||
if (!argb_fbconfig) {
|
||||
log_error("Failed to find appropriate FBConfig for 32 bit depth");
|
||||
return false;
|
||||
}
|
||||
fbcfg = argb_fbconfig;
|
||||
} else {
|
||||
xcb_render_pictforminfo_t *pictfmt = x_get_pictform_for_visual(ps->c, visual);
|
||||
if (!depth) {
|
||||
assert(visual);
|
||||
depth = x_get_visual_depth(ps->c, visual);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
#else
|
||||
static inline bool paint_bind_tex(session_t *ps, paint_t *ppaint, unsigned wid,
|
||||
unsigned hei, unsigned depth, bool force) {
|
||||
return true;
|
||||
}
|
||||
if (!pictfmt) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!ppaint->fbcfg) {
|
||||
ppaint->fbcfg = glx_find_fbconfig(ps->dpy, ps->scr, pictfmt, depth);
|
||||
}
|
||||
if (!ppaint->fbcfg) {
|
||||
log_error("Failed to find appropriate FBConfig for X pixmap");
|
||||
return false;
|
||||
}
|
||||
fbcfg = ppaint->fbcfg;
|
||||
}
|
||||
|
||||
if (force || !glx_tex_binded(ppaint->ptex, ppaint->pixmap))
|
||||
return glx_bind_pixmap(ps, &ppaint->ptex, ppaint->pixmap, wid, hei, fbcfg);
|
||||
#endif
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if current backend uses XRender for rendering.
|
||||
|
@ -219,7 +257,8 @@ void paint_one(session_t *ps, win *w, const region_t *reg_paint) {
|
|||
// Let glx_bind_pixmap() determine pixmap size, because if the user
|
||||
// is resizing windows, the width and height we get may not be up-to-date,
|
||||
// causing the jittering issue M4he reported in #7.
|
||||
if (!paint_bind_tex(ps, &w->paint, 0, 0, 0, (!ps->o.glx_no_rebind_pixmap && w->pixmap_damaged))) {
|
||||
if (!paint_bind_tex(ps, &w->paint, 0, 0, 0, w->a.visual,
|
||||
(!ps->o.glx_no_rebind_pixmap && w->pixmap_damaged))) {
|
||||
log_error("Failed to bind texture for window %#010x.", w->id);
|
||||
}
|
||||
w->pixmap_damaged = false;
|
||||
|
@ -445,8 +484,7 @@ static bool get_root_tile(session_t *ps) {
|
|||
ps->root_tile_paint.pixmap = pixmap;
|
||||
#ifdef CONFIG_OPENGL
|
||||
if (BKEND_GLX == ps->o.backend)
|
||||
return glx_bind_pixmap(ps, &ps->root_tile_paint.ptex,
|
||||
ps->root_tile_paint.pixmap, 0, 0, 0);
|
||||
return paint_bind_tex(ps, &ps->root_tile_paint, 0, 0, 0, ps->vis, false);
|
||||
#endif
|
||||
|
||||
return true;
|
||||
|
@ -484,7 +522,8 @@ static bool win_build_shadow(session_t *ps, win *w, double opacity) {
|
|||
return XCB_NONE;
|
||||
}
|
||||
|
||||
shadow_pixmap = x_create_pixmap(ps->c, 8, ps->root, shadow_image->width, shadow_image->height);
|
||||
shadow_pixmap =
|
||||
x_create_pixmap(ps->c, 8, ps->root, shadow_image->width, shadow_image->height);
|
||||
shadow_pixmap_argb =
|
||||
x_create_pixmap(ps->c, 32, ps->root, shadow_image->width, shadow_image->height);
|
||||
|
||||
|
@ -542,7 +581,7 @@ shadow_picture_err:
|
|||
*/
|
||||
static inline void win_paint_shadow(session_t *ps, win *w, region_t *reg_paint) {
|
||||
// Bind shadow pixmap to GLX texture if needed
|
||||
paint_bind_tex(ps, &w->shadow_paint, 0, 0, 32, false);
|
||||
paint_bind_tex(ps, &w->shadow_paint, 0, 0, 32, 0, false);
|
||||
|
||||
if (!paint_isvalid(ps, &w->shadow_paint)) {
|
||||
log_error("Window %#010x is missing shadow data.", w->id);
|
||||
|
@ -942,12 +981,14 @@ void paint_all(session_t *ps, win *const t, bool ignore_damage) {
|
|||
switch (ps->o.backend) {
|
||||
case BKEND_XRENDER:
|
||||
if (ps->o.monitor_repaint) {
|
||||
// Copy the screen content to a new picture, and highlight
|
||||
// the paint region. This is not very efficient, but since
|
||||
// it's for debug only, we don't really care
|
||||
// Copy the screen content to a new picture, and highlight the
|
||||
// paint region. This is not very efficient, but since it's for
|
||||
// debug only, we don't really care
|
||||
|
||||
// First we create a new picture, and copy content from the buffer to it
|
||||
xcb_render_pictforminfo_t *pictfmt = x_get_pictform_for_visual(ps->c, ps->vis);
|
||||
// First we create a new picture, and copy content from the buffer
|
||||
// to it
|
||||
xcb_render_pictforminfo_t *pictfmt =
|
||||
x_get_pictform_for_visual(ps->c, ps->vis);
|
||||
xcb_render_picture_t new_pict = x_create_picture_with_pictfmt(
|
||||
ps, ps->root_width, ps->root_height, pictfmt, 0, NULL);
|
||||
xcb_render_composite(ps->c, XCB_RENDER_PICT_OP_SRC,
|
||||
|
@ -983,7 +1024,7 @@ void paint_all(session_t *ps, win *const t, bool ignore_damage) {
|
|||
glXWaitX();
|
||||
assert(ps->tgt_buffer.pixmap);
|
||||
paint_bind_tex(ps, &ps->tgt_buffer, ps->root_width, ps->root_height,
|
||||
ps->depth, !ps->o.glx_no_rebind_pixmap);
|
||||
ps->depth, ps->vis, !ps->o.glx_no_rebind_pixmap);
|
||||
if (ps->o.vsync_use_glfinish)
|
||||
glFinish();
|
||||
else
|
||||
|
@ -1200,14 +1241,15 @@ void deinit_render(session_t *ps) {
|
|||
// Free other X resources
|
||||
free_root_tile(ps);
|
||||
|
||||
// Free the damage ring
|
||||
for (int i = 0; i < ps->ndamage; ++i)
|
||||
pixman_region32_fini(&ps->damage_ring[i]);
|
||||
ps->ndamage = 0;
|
||||
free(ps->damage_ring);
|
||||
ps->damage_ring = ps->damage = NULL;
|
||||
// Free the damage ring
|
||||
for (int i = 0; i < ps->ndamage; ++i)
|
||||
pixman_region32_fini(&ps->damage_ring[i]);
|
||||
ps->ndamage = 0;
|
||||
free(ps->damage_ring);
|
||||
ps->damage_ring = ps->damage = NULL;
|
||||
|
||||
#ifdef CONFIG_OPENGL
|
||||
free(ps->root_tile_paint.fbcfg);
|
||||
glx_destroy(ps);
|
||||
#endif
|
||||
}
|
||||
|
|
|
@ -5,6 +5,10 @@
|
|||
#include <xcb/xcb.h>
|
||||
#include <xcb/render.h>
|
||||
#include <stdbool.h>
|
||||
#ifdef CONFIG_OPENGL
|
||||
#include <GL/glx.h>
|
||||
#include "backend/gl/glx.h"
|
||||
#endif
|
||||
#include "region.h"
|
||||
|
||||
typedef struct _glx_texture glx_texture_t;
|
||||
|
@ -16,6 +20,9 @@ typedef struct paint {
|
|||
xcb_pixmap_t pixmap;
|
||||
xcb_render_picture_t pict;
|
||||
glx_texture_t *ptex;
|
||||
#ifdef CONFIG_OPENGL
|
||||
struct glx_fbconfig_info *fbcfg;
|
||||
#endif
|
||||
} paint_t;
|
||||
|
||||
void
|
||||
|
|
|
@ -73,6 +73,10 @@ static inline long attr_const min_l(long a, long b) {
|
|||
return (a > b ? b : a);
|
||||
}
|
||||
|
||||
static inline int attr_const popcountl(unsigned long a) {
|
||||
return __builtin_popcountl(a);
|
||||
}
|
||||
|
||||
/**
|
||||
* Normalize a double value to a specific range.
|
||||
*
|
||||
|
|
1
src/x.h
1
src/x.h
|
@ -94,6 +94,7 @@ xcb_window_t wid_get_prop_window(session_t *ps, xcb_window_t wid, xcb_atom_t apr
|
|||
bool wid_get_text_prop(session_t *ps, xcb_window_t wid, xcb_atom_t prop, char ***pstrlst, int *pnstr);
|
||||
|
||||
xcb_render_pictforminfo_t *x_get_pictform_for_visual(xcb_connection_t *, xcb_visualid_t);
|
||||
int x_get_visual_depth(xcb_connection_t *, xcb_visualid_t);
|
||||
|
||||
xcb_render_picture_t
|
||||
x_create_picture_with_pictfmt_and_pixmap(xcb_connection_t *, xcb_render_pictforminfo_t *pictfmt,
|
||||
|
|
Loading…
Reference in New Issue