#include "display.h"
#include "list.h"
#include <stdio.h>
+#include <string.h>
#include <assert.h>
#include <stdlib.h>
-#include <xcb/glx.h>
-//#include <GL/glext.h>
-//#include <GL/glxext.h>
-#include <GL/glxtokens.h>
+#include <X11/Xmd.h>
+#include <GL/glxproto.h>
+
#include <GL/gl.h>
+#include <GL/glx.h>
+#include <GL/glxtokens.h>
+#include <GL/glext.h>
+#include <GL/glxext.h>
#define MAX_DEPTH 32
static int plugin_id;
+#define LEFT 0
+#define TOP 1
+#define RIGHT 2
+#define BOTTOM 3
+
+typedef void (*BindEXTFunc)(Display *, GLXDrawable, int, const int *);
+typedef void (*ReleaseEXTFunc)(Display *, GLXDrawable, int);
+typedef int (*SwapIntervalSGIFunc)(int);
+
typedef struct {
void (*screen_paint)(d_screen_t *sc);
void (*screen_root_pixmap_change)(d_screen_t *sc);
void (*window_resize)(d_window_t *w);
void (*window_reshape)(d_window_t *w);
- uint16_t shadowalpha;
+ float shadowalpha;
int xshadowoff;
int yshadowoff;
- uint32_t fbconfig[MAX_DEPTH + 1];
+ GLXFBConfig fbconfig[MAX_DEPTH + 1];
+
+ GLXContext context;
+ GLuint root_texname;
+ GLXPixmap root_glpixmap;
- xcb_glx_context_t context;
- xcb_glx_context_tag_t context_tag;
+ BindEXTFunc bind_func;
+ ReleaseEXTFunc release_func;
} data_t;
typedef struct {
GLuint texname;
- xcb_glx_pixmap_t glpixmap;
+ GLXPixmap glpixmap;
+
+ GLfloat *texcoords;
+ GLint *vertices;
+ int nrects;
+
+ xcb_xfixes_fetch_region_cookie_t ck_region;
+ int waiting_region;
+ int x_region;
+ int y_region;
+ int w_region;
+ int h_region;
+ int bw_region;
} window_data_t;
-static uint32_t glxrender_visual_info(uint32_t *props, int vis, int numprops,
- uint32_t name);
-static gboolean glxrender_check_visual(d_screen_t *sc);
static gboolean glxrender_find_fb_config(d_screen_t *sc, data_t *d);
static void glxrender_paint(d_screen_t *sc);
static void glxrender_root_pixmap_change(d_screen_t *sc);
static void paint_root(d_screen_t *sc, data_t *d);
static void paint_window(d_window_t *window, data_t *d, window_data_t *wd,
- gboolean opaque, int x, int y, int width,
- int height, int bwidth);
-static void paint_shadow(d_window_t *w, data_t *d, window_data_t *wd,
- int x, int y, int width, int height, int bwidth);
+ int x, int y, GLfloat z);
+static void paint_shadow(data_t *d, window_data_t *wd, int x, int y,
+ GLfloat z);
static void glxrender_update_window_pixmap(d_window_t *w, data_t *d,
window_data_t *wd);
-static void glxrender_free_window_pixmap(d_window_t *w, window_data_t *wd);
+static void glxrender_fetch_window_region(d_window_t *w, window_data_t *wd);
+static void glxrender_update_window_region(d_window_t *w, window_data_t *wd);
+static void glxrender_free_window_pixmap(d_window_t *w, data_t *d,
+ window_data_t *wd);
+static void glxrender_free_window_region(window_data_t *wd);
+static void glxrender_free_root_pixmap(d_screen_t *sc, data_t *d);
static void glxrender_update_root_pixmap(d_screen_t *sc, data_t *d);
static void glxrender_window_show(d_window_t *window);
void
glxrender_init(d_screen_t *sc, int id)
{
- xcb_void_cookie_t ck;
- xcb_generic_error_t *err;
- xcb_glx_make_current_cookie_t curck;
- xcb_glx_make_current_reply_t *currep;
+ static int context_visual_config[] = {
+ GLX_DEPTH_SIZE, 1,
+ GLX_DOUBLEBUFFER,
+ GLX_RGBA,
+ XCB_NONE
+ };
+ XVisualInfo *vi;
+ data_t *d;
plugin_id = id;
- data_t *d = malloc(sizeof(data_t));
+ d = malloc(sizeof(data_t));
d->screen_paint = sc->screen_paint;
d->screen_root_pixmap_change = sc->screen_root_pixmap_change;
d->window_show = sc->window_show;
sc->window_resize = glxrender_window_resize;
sc->window_reshape = glxrender_window_reshape;
- d->shadowalpha = 0x3333; /* 20% */
+ d->shadowalpha = 0.2f; /* 20% */
d->xshadowoff = 2;
d->yshadowoff = 2;
- if (!glxrender_check_visual(sc)) {
- printf("unable to use the overlay window for GLX\n");
+ vi = glXChooseVisual(sc->dpy->xlib_dpy, sc->num, context_visual_config);
+ if (!vi) {
+ printf("unable to find a valid double buffered GL context to use\n");
exit(1);
}
exit(1);
}
- d->context = xcb_generate_id(sc->dpy->conn);
- ck = xcb_glx_create_context_checked(sc->dpy->conn, d->context,
- sc->overlay_visual, sc->num,
- XCB_NONE, TRUE);
- if ((err = xcb_request_check(sc->dpy->conn, ck))) {
- printf("context creation failed\n");
- display_error(sc->dpy, err);
- free(err);
- exit(1);
- }
-
- curck = xcb_glx_make_current(sc->dpy->conn,
- sc->overlay, d->context, XCB_NONE);
- currep = xcb_glx_make_current_reply(sc->dpy->conn, curck, &err);
- if (!currep) {
- if (err) {
- display_error(sc->dpy, err);
- free(err);
- }
- printf("make current failed\n");
- exit(1);
- }
- d->context_tag = currep->context_tag;
- free(currep);
+ d->context = glXCreateContext(sc->dpy->xlib_dpy, vi, NULL, GL_TRUE);
+ glXMakeCurrent(sc->dpy->xlib_dpy, sc->overlay, d->context);
- glViewport(0, 0, sc->super.width_in_pixels, sc->super.height_in_pixels);
+ glViewport(0, 0, sc->super->width_in_pixels, sc->super->height_in_pixels);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
- glOrtho(0, sc->super.width_in_pixels, sc->super.height_in_pixels,
- 0.0, -1.0, 100.0);
+ glOrtho(0, sc->super->width_in_pixels, sc->super->height_in_pixels, 0,
+ -100.0, 100.0);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
- glClear(GL_COLOR_BUFFER_BIT);
glEnable(GL_TEXTURE_2D);
- xcb_glx_swap_buffers(sc->dpy->conn, d->context_tag, sc->overlay);
- glClearColor(0.4, 0.4, 0.4, 1.0);
-
-/*
- glBlendFunc(GL_ONE_MINUS_SRC_ALPHA, GL_SRC_ALPHA);
- glEnable(GL_BLEND);
-*/
-}
-
-static uint32_t
-glxrender_visual_info(uint32_t *props, int vis, int numprops, uint32_t name)
-{
- int s;
-
- assert(numprops > 14);
-
- /*
- for (s = vis * numprops; s < vis*numprops + numprops; ++s)
- printf("%x ", props[s]);
- printf("\n");
- */
-
- s = vis * numprops;
- switch (name) {
- case GLX_VISUAL_ID: return props[s+0]; /* id number */
- case GLX_X_VISUAL_TYPE: return props[s+1]; /* XCB_CLASS_TRUE_COLOR etc */
- case GLX_USE_GL: return props[s+2]; /* boolean */
- case GLX_RED_SIZE: return props[s+3]; /* number */
- case GLX_GREEN_SIZE: return props[s+4]; /* number */
- case GLX_BLUE_SIZE: return props[s+5]; /* number */
- case GLX_ALPHA_SIZE: return props[s+6]; /* number */
- case GLX_DOUBLEBUFFER: return props[s+11]; /* boolean */
- case GLX_DEPTH_SIZE: return props[s+14]; /* number */
- case GLX_STENCIL_SIZE: return props[s+15]; /* number */
- default: assert(0);
- }
-}
-
-static gboolean
-glxrender_check_visual(d_screen_t *sc)
-{
- xcb_glx_get_visual_configs_cookie_t ck;
- xcb_glx_get_visual_configs_reply_t *rep;
- gboolean ok = FALSE;
-
- ck = xcb_glx_get_visual_configs_unchecked(sc->dpy->conn, sc->num);
- rep = xcb_glx_get_visual_configs_reply(sc->dpy->conn, ck, NULL);
- if (rep) {
- uint32_t *props;
- unsigned int i, nprops;
-
-/*
- static int config[] = {
- GLX_DEPTH_SIZE, 1,
- GLX_DOUBLEBUFFER,
- GLX_RGBA,
- XCB_NONE
- };
-*/
+ glEnable(GL_DEPTH_TEST);
+ //glEnable(GL_SCISSOR_TEST); ?? what is this, glxcompmgr enables it
+ //glEnable(GL_STENCIL_TEST); ?? what is this, glxcompmgr enables it
- props = xcb_glx_get_visual_configs_property_list(rep);
- nprops = rep->num_properties;
+ glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
+ glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA);
+ glDisable(GL_BLEND);
- for (i = 0; i < rep->num_visuals; ++i) {
- /* look for the overlay's visual */
- if (glxrender_visual_info(props, i, nprops, GLX_VISUAL_ID) !=
- sc->overlay_visual)
- {
- continue;
- }
-
- if (!glxrender_visual_info(props, i, nprops, GLX_USE_GL)) {
- printf("overlay visual does not support GL\n");
- break;
- }
-
- if (!glxrender_visual_info(props, i, nprops, GLX_DOUBLEBUFFER)) {
- printf("overlay visual is not double buffered\n");
- break;
- }
+ glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
+ glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
- ok = TRUE; /* yippa ! */
- }
+ glXSwapBuffers(sc->dpy->xlib_dpy, sc->overlay);
- free(rep);
- }
- return ok;
-}
+ d->bind_func = (BindEXTFunc)
+ glXGetProcAddress((const guchar*)"glXBindTexImageEXT");
+ d->release_func = (ReleaseEXTFunc)
+ glXGetProcAddress((const guchar*)"glXReleaseTexImageEXT");
-static uint32_t
-glxrender_fbconfig_info(uint32_t *props, int con, int numprops, uint32_t name)
-{
- int i;
+ SwapIntervalSGIFunc swap_interval_func = (SwapIntervalSGIFunc)
+ glXGetProcAddress((const guchar*)"glXSwapIntervalSGI");
+ if(swap_interval_func)
+ swap_interval_func(1);
- for (i = 0; i < numprops; ++i) {
- if (props[i*2 + con*numprops*2] == name)
- return props[i*2 + con*numprops*2 + 1];
- }
- return 0;
+ glGenTextures(1, &d->root_texname);
+ d->root_glpixmap = XCB_NONE;
}
static gboolean
glxrender_find_fb_config(d_screen_t *sc, data_t *d)
{
- xcb_glx_get_visual_configs_cookie_t vck;
- xcb_glx_get_visual_configs_reply_t *vrep;
- xcb_glx_get_fb_configs_cookie_t fbck;
- xcb_glx_get_fb_configs_reply_t *fbrep;
- xcb_depth_iterator_t depth_it;
- unsigned int i, nvprops, nfbprops;
- uint32_t *vprops, *fbprops;
- uint32_t db, stencil, depthsize;
-
- vck = xcb_glx_get_visual_configs_unchecked(sc->dpy->conn, sc->num);
- vrep = xcb_glx_get_visual_configs_reply(sc->dpy->conn, vck, NULL);
- if (!vrep) return FALSE;
-
- fbck = xcb_glx_get_fb_configs(sc->dpy->conn, sc->num);
- fbrep = xcb_glx_get_fb_configs_reply(sc->dpy->conn, fbck, NULL);
- if (!fbrep) return FALSE;
-
- vprops = xcb_glx_get_visual_configs_property_list(vrep);
- nvprops = vrep->num_properties;
- fbprops = xcb_glx_get_fb_configs_property_list(fbrep);
- nfbprops = fbrep->num_properties;
-
- for (i = 0; i <= MAX_DEPTH; ++i)
- d->fbconfig[i] = 0;
+ static const int drawable_tfp_attrs[] = {
+ GLX_CONFIG_CAVEAT, GLX_NONE,
+ GLX_DOUBLEBUFFER, FALSE,
+ GLX_DEPTH_SIZE, 0,
+ GLX_RED_SIZE, 1,
+ GLX_GREEN_SIZE, 1,
+ GLX_BLUE_SIZE, 1,
+ GLX_ALPHA_SIZE, 1,
+ GLX_RENDER_TYPE, GLX_RGBA_BIT,
+ GLX_BIND_TO_TEXTURE_RGBA_EXT, TRUE, /* For TextureFromPixmap */
+ XCB_NONE
+ };
+ int db, stencil, depth, numfb, i;
+ GLXFBConfig *fbcons;
+ XVisualInfo tvis, *visinfo;
- db = 32767;
- stencil = 32767;
- depthsize = 32767;
- depth_it = xcb_screen_allowed_depths_iterator(&sc->super);
- for (; depth_it.rem; xcb_depth_next(&depth_it)) {
- uint32_t vid;
- int j;
- unsigned int k;
- xcb_visualtype_t *visuals;
- int nvisuals;
+ fbcons = glXChooseFBConfig(sc->dpy->xlib_dpy, sc->num,
+ drawable_tfp_attrs, &numfb);
+ if (!fbcons) return FALSE;
- vid = 0;
- if (depth_it.data->depth > MAX_DEPTH) continue;
+ for (i = 0; i <= MAX_DEPTH; i++) {
+ int j, count, value;
+ VisualID vid;
- printf("looking for depth %d\n", depth_it.data->depth);
+ vid = 0;
+ d->fbconfig[i] = 0;
+ db = 32767;
+ stencil = 32767;
+ depth = 32767;
- visuals = xcb_depth_visuals(depth_it.data);
- nvisuals = xcb_depth_visuals_length(depth_it.data);
+ //printf("looking for depth %d\n", i);
+ tvis.depth = i;
+ visinfo = XGetVisualInfo(sc->dpy->xlib_dpy, VisualDepthMask,
+ &tvis, &count);
/* pick the nicest visual for the depth */
- for (j = 0; j < nvisuals; ++j) {
- uint32_t val;
-
- /* find the visual's properties */
- for (k = 0; k < vrep->num_visuals; ++k)
- if (glxrender_visual_info(vprops, k, nvprops, GLX_VISUAL_ID)
- == visuals[j].visual_id)
- {
- break;
- }
- if (k == vrep->num_visuals) continue;
-
- val = glxrender_visual_info(vprops, k, nvprops, GLX_USE_GL);
- if (!val) continue;
+ for (j = 0; j < count; j++) {
+ glXGetConfig(sc->dpy->xlib_dpy, &visinfo[j], GLX_USE_GL, &value);
+ if (!value)
+ continue;
- val = glxrender_visual_info(vprops, k, nvprops, GLX_DOUBLEBUFFER);
- if (!val > db) continue;
- db = val;
+ glXGetConfig(sc->dpy->xlib_dpy, &visinfo[j], GLX_DOUBLEBUFFER,
+ &value);
+ if (value > db)
+ continue;
+ db = value;
- val = glxrender_visual_info(vprops, k, nvprops, GLX_STENCIL_SIZE);
- if (!val > stencil) continue;
- stencil = val;
+ glXGetConfig(sc->dpy->xlib_dpy, &visinfo[j], GLX_STENCIL_SIZE,
+ &value);
+ if (value > stencil)
+ continue;
+ stencil = value;
- val = glxrender_visual_info(vprops, k, nvprops, GLX_DEPTH_SIZE);
- if (!val > depthsize) continue;
- depthsize = val;
+ glXGetConfig(sc->dpy->xlib_dpy, &visinfo[j], GLX_DEPTH_SIZE,
+ &value);
+ if (value > depth)
+ continue;
+ depth = value;
/* use this visual */
- vid = visuals[j].visual_id;
+ vid = visinfo[j].visualid;
}
if (!vid) continue;
- printf("found visual for depth %d\n", depth_it.data->depth);
-
- for (k = 0; k < fbrep->num_FB_configs; ++k) {
- uint32_t val;
-
- //printf("root visual 0x%x\n", sc->super.root_visual);
- //printf("overlay visual 0x%x\n", sc->overlay_visual);
-
- val = glxrender_fbconfig_info(fbprops, k, nfbprops,
- GLX_VISUAL_ID);
- //printf("x visual 0x%x\n", val);
- if (val != vid) continue;
-
- val = glxrender_fbconfig_info(fbprops, k, nfbprops,
- GLX_DOUBLEBUFFER);
- //printf("dbl buffer %s\n", val ? "yes" : "no");
- if (db) continue;
-
- val = glxrender_fbconfig_info(fbprops, k, nfbprops,
- GLX_DEPTH_SIZE);
- //printf("depth size %d\n", val);
-
- val = glxrender_fbconfig_info(fbprops, k, nfbprops,
- GLX_RED_SIZE);
- //printf("red size %d\n", val);
- if (!val) continue;
-
- val = glxrender_fbconfig_info(fbprops, k, nfbprops,
- GLX_GREEN_SIZE);
- //printf("green size %d\n", val);
- if (!val) continue;
-
- val = glxrender_fbconfig_info(fbprops, k, nfbprops,
- GLX_BLUE_SIZE);
- //printf("blue size %d\n", val);
- if (!val) continue;
-
- val = glxrender_fbconfig_info(fbprops, k, nfbprops,
- GLX_ALPHA_SIZE);
- //printf("alpha size %d\n", val);
- if (!val) continue;
-
- val = glxrender_fbconfig_info(fbprops, j, nfbprops,
- GLX_RENDER_TYPE);
- //printf("rgba bit %s\n", val & GLX_RGBA_BIT ? "yes" : "no");
- if (!(val & GLX_RGBA_BIT)) continue;
-
- val = glxrender_fbconfig_info(fbprops, j, nfbprops,
- GLX_CONFIG_CAVEAT);
- //printf("caveat 0x%x\n", val);
-
- val = glxrender_fbconfig_info(fbprops, j, nfbprops,
- GLX_BIND_TO_TEXTURE_RGBA_EXT);
- //printf("bind ext %s\n", val ? "yes" : "no");
- if (!val) continue;
-
- d->fbconfig[depth_it.data->depth] =
- glxrender_fbconfig_info(fbprops, i, nfbprops, GLX_FBCONFIG_ID);
- break;
+ /* look for an fbconfig for this visual */
+ for (j = 0; j < numfb; ++j) {
+ glXGetFBConfigAttrib(sc->dpy->xlib_dpy, fbcons[j],
+ GLX_VISUAL_ID, &value);
+ if ((unsigned)value == vid) {
+ d->fbconfig[i] = fbcons[j];
+
+ printf("found visual 0x%x fbconfig 0x%x for depth %d\n",
+ (uint32_t)vid, (uint32_t)fbcons[j], i);
+ break;
+ }
}
}
- free(vrep);
- free(fbrep);
+ XFree(fbcons);
return TRUE;
}
glxrender_free(d_screen_t *sc)
{
data_t *d = screen_find_plugin_data(sc, plugin_id);
- free(d);
+ if (d) {
+ glxrender_free_root_pixmap(sc, d);
+ glXDestroyContext(sc->dpy->xlib_dpy, d->context);
+ free(d);
+ }
screen_remove_plugin_data(sc, plugin_id);
}
}
void
-glxrender_window_free_data(d_window_t *w, window_data_t *wd)
+glxrender_window_free_data(d_window_t *w, data_t *d, window_data_t *wd)
{
- glxrender_free_window_pixmap(w, wd);
+ glxrender_free_window_pixmap(w, d, wd);
+ glxrender_free_window_region(wd);
glDeleteTextures(1, &wd->texname);
free(wd);
}
d->window_show(w);
wd = window_find_plugin_data(w, plugin_id);
- if (wd)
- glxrender_window_free_data(w, wd);
-
+ if (wd) {
+ glxrender_window_free_data(w, d, wd);
+ window_remove_plugin_data(w, plugin_id);
+ }
+
wd = malloc(sizeof(window_data_t));
glGenTextures(1, &wd->texname);
+ wd->glpixmap = XCB_NONE;
+ wd->texcoords = NULL;
+ wd->vertices = NULL;
+ wd->nrects = 0;
+ wd->waiting_region = FALSE;
window_add_plugin_data(w, plugin_id, wd);
+
+ glxrender_fetch_window_region(w, wd);
}
static void
d = screen_find_plugin_data(w->sc, plugin_id);
wd = window_find_plugin_data(w, plugin_id);
if (wd) {
- glxrender_window_free_data(w, wd);
+ glxrender_window_free_data(w, d, wd);
window_remove_plugin_data(w, plugin_id);
}
}
static void
-glxrender_free_window_pixmap(d_window_t *w, window_data_t *wd)
+glxrender_free_window_pixmap(d_window_t *w, data_t *d, window_data_t *wd)
{
/* this might cause an error, oh well */
if (wd->glpixmap) {
glBindTexture(GL_TEXTURE_2D, wd->texname);
+ d->release_func(w->sc->dpy->xlib_dpy,
+ wd->glpixmap, GLX_FRONT_LEFT_EXT);
+ glBindTexture(GL_TEXTURE_2D, 0);
+
+ glXDestroyPixmap(w->sc->dpy->xlib_dpy, wd->glpixmap);
+ wd->glpixmap = XCB_NONE;
+
+ }
+}
- //d->releaseTexImageEXT(obt_display, lw->glpixmap,
- // GLX_FRONT_LEFT_EXT);
+static void
+glxrender_free_window_region(window_data_t *wd)
+{
+ if (wd->nrects) {
+ free(wd->texcoords);
+ free(wd->vertices);
+ wd->texcoords = NULL;
+ wd->vertices = NULL;
+ wd->nrects = 0;
+ }
+}
+static void
+glxrender_free_root_pixmap(d_screen_t *sc, data_t *d)
+{
+ /* this might cause an error, oh well */
+ if (d->root_glpixmap) {
+ glBindTexture(GL_TEXTURE_2D, d->root_texname);
+ d->release_func(sc->dpy->xlib_dpy,
+ d->root_glpixmap, GLX_FRONT_LEFT_EXT);
glBindTexture(GL_TEXTURE_2D, 0);
- xcb_glx_destroy_glx_pixmap(w->sc->dpy->conn, wd->glpixmap);
- wd->glpixmap = XCB_NONE;
+ glXDestroyPixmap(sc->dpy->xlib_dpy, d->root_glpixmap);
+ d->root_glpixmap = XCB_NONE;
}
}
xcb_pixmap_t px;
uint8_t depth;
- static const uint32_t attrs[] = {
+ static int attrs[] = {
GLX_TEXTURE_FORMAT_EXT,
- GLX_TEXTURE_FORMAT_RGBA_EXT
+ XCB_NONE,
+ XCB_NONE
};
px = window_get_pixmap(w);
depth = window_get_depth(w);
- if (px && d->fbconfig[depth]) {
- wd->glpixmap = xcb_generate_id(w->sc->dpy->conn);
- xcb_glx_create_pixmap(w->sc->dpy->conn, w->sc->num, d->fbconfig[depth],
- px, wd->glpixmap, 2, attrs);
- glBindTexture(GL_TEXTURE_2D, wd->texname);
+ if (!px) return;
- {
- unsigned int len = 2 * sizeof(uint32_t);
- uint32_t data[] = {wd->glpixmap, GLX_FRONT_LEFT_EXT};
- xcb_void_cookie_t ck;
- xcb_generic_error_t *err;
-
- ck = xcb_glx_vendor_private(w->sc->dpy->conn,
- GLX_BIND_TO_TEXTURE_RGBA_EXT,
- d->context_tag,
- len, data);
- if ((err = xcb_request_check(w->sc->dpy->conn, ck))) {
- display_error(w->sc->dpy, err);
- free(err);
- }
- }
- //d->bindTexImageEXT(obt_display, lw->glpixmap,
- // GLX_FRONT_LEFT_EXT, NULL);
+ if (!d->fbconfig[depth]) {
+ printf("no GL visual for depth %d\n", depth);
+ return;
+ }
- glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
- glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
+ if (window_is_argb(w))
+ attrs[1] = GLX_TEXTURE_FORMAT_RGBA_EXT;
+ else
+ attrs[1] = GLX_TEXTURE_FORMAT_RGB_EXT;
+
+ wd->glpixmap = glXCreatePixmap(w->sc->dpy->xlib_dpy,
+ d->fbconfig[depth],
+ px, attrs);
+#if 0
+ wd->glpixmap = xcb_generate_id(w->sc->dpy->conn);
+ int v;
+ glXGetFBConfigAttrib(w->sc->dpy->xlib_dpy, d->fbconfig[depth],
+ GLX_FBCONFIG_ID, &v);
+ xcb_void_cookie_t ck =
+ xcb_glx_create_pixmap_checked(w->sc->dpy->conn, w->sc->num,
+ v,
+ px, wd->glpixmap,
+ 2,
+ attrs);
+ xcb_generic_error_t *err = xcb_request_check(w->sc->dpy->conn, ck);
+ if (err) {
+ display_error(w->sc->dpy, err);
+ free(err);
+ wd->glpixmap = XCB_NONE;
+ return;
+ }
+#endif
+
+ glBindTexture(GL_TEXTURE_2D, wd->texname);
+ d->bind_func(w->sc->dpy->xlib_dpy,
+ wd->glpixmap, GLX_FRONT_LEFT_EXT, NULL);
+#if 0
+ {
+ /*
+ BindTexImageEXT
+ 1 CARD8 opcode (X assigned)
+ 1 16 GLX opcode (glXVendorPrivate)
+ 2 6+n request length
+ 4 1330 vendor specific opcode
+ 4 CARD32 context tag
+ 4 GLX_DRAWABLE drawable
+ 4 INT32 buffer
+ 4 CARD32 num_attributes
+ 4*n LISTofATTRIBUTE_PAIR attribute, value pairs.
+ */
+ unsigned int len = 12;
+ uint32_t data[] = {
+ wd->glpixmap,
+ GLX_FRONT_LEFT_EXT,
+ 0,
+ };
+ xcb_glx_vendor_private(w->sc->dpy->conn,
+ X_GLXvop_BindTexImageEXT,
+ 1,
+ len, (uint8_t*)data);
+ }
+#endif
- glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
- glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
- glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
- glBindTexture(GL_TEXTURE_2D, 0);
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
+
+ glBindTexture(GL_TEXTURE_2D, 0);
+}
+
+static void
+glxrender_fetch_window_region(d_window_t *w, window_data_t *wd)
+{
+ window_get_area(w, &wd->x_region, &wd->y_region,
+ &wd->w_region, &wd->h_region, &wd->bw_region);
+
+ wd->ck_region =
+ xcb_xfixes_fetch_region_unchecked(w->sc->dpy->conn,
+ window_get_region(w));
+ wd->waiting_region = TRUE;
+ xcb_flush(w->sc->dpy->conn);
+}
+
+static void
+glxrender_update_window_region(d_window_t *w, window_data_t *wd)
+{
+ xcb_xfixes_fetch_region_reply_t *rep;
+ xcb_rectangle_t area, *rects;
+ int nrects, i, j;
+
+ if (!wd->waiting_region) return;
+
+ area.x = wd->x_region;
+ area.y = wd->y_region;
+ area.width = wd->w_region + wd->bw_region * 2;
+ area.height = wd->h_region + wd->bw_region * 2;
+
+ rep = xcb_xfixes_fetch_region_reply(w->sc->dpy->conn, wd->ck_region, NULL);
+ if (!rep) {
+ rects = &area;
+ nrects = 1;
+ }
+ else {
+ rects = xcb_xfixes_fetch_region_rectangles(rep);
+ nrects = xcb_xfixes_fetch_region_rectangles_length(rep);
}
+
+ wd->texcoords = (GLfloat*)realloc(wd->texcoords,
+ sizeof(GLfloat) * (nrects * 4));
+ wd->vertices = (GLint*)realloc(wd->vertices, sizeof(GLint) * (nrects * 4));
+ wd->nrects = nrects;
+
+ for (i = j = 0; i < nrects * 4; ++j, i += 4) {
+ wd->texcoords[i+LEFT] =
+ (GLfloat)(rects[j].x - area.x) / (GLfloat)area.width;
+ wd->texcoords[i+TOP] =
+ (GLfloat)(rects[j].y - area.y) / (GLfloat)area.height;
+ wd->texcoords[i+RIGHT] =
+ (GLfloat)(rects[j].x - area.x + rects[j].width) /
+ (GLfloat)area.width;
+ wd->texcoords[i+BOTTOM] =
+ (GLfloat)(rects[j].y - area.y + rects[j].height) /
+ (GLfloat)area.height;
+
+ wd->vertices[i+LEFT] = rects[j].x - area.x;
+ wd->vertices[i+TOP] = rects[j].y - area.y;
+ wd->vertices[i+RIGHT] = rects[j].x - area.x + rects[j].width;
+ wd->vertices[i+BOTTOM] = rects[j].y - area.y + rects[j].height;
+ }
+
+ if (rep)
+ free(rep);
+
+ wd->waiting_region = FALSE;
}
static void
glxrender_update_root_pixmap(d_screen_t *sc, data_t *d)
{
xcb_pixmap_t px;
+ static int attrs[] = {
+ GLX_TEXTURE_FORMAT_EXT,
+ GLX_TEXTURE_FORMAT_RGB_EXT,
+ XCB_NONE
+ };
px = screen_get_root_pixmap(sc);
- if (px) {
+ if (!px) return;
+
+ if (!d->fbconfig[sc->super->root_depth]) {
+ printf("no GL visual for depth %d\n", sc->super->root_depth);
+ return;
}
+
+ d->root_glpixmap = glXCreatePixmap(sc->dpy->xlib_dpy,
+ d->fbconfig[sc->super->root_depth],
+ px, attrs);
+
+
+ glBindTexture(GL_TEXTURE_2D, d->root_texname);
+ d->bind_func(sc->dpy->xlib_dpy,
+ d->root_glpixmap, GLX_FRONT_LEFT_EXT, NULL);
+
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
+
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
+
+ glBindTexture(GL_TEXTURE_2D, 0);
}
static void
d->window_resize(w);
assert(wd != NULL);
- glxrender_free_window_pixmap(w, wd);
+ glxrender_free_window_pixmap(w, d, wd);
+ glxrender_fetch_window_region(w, wd);
}
static void
d->window_reshape(w);
assert(wd != NULL);
- glxrender_free_window_pixmap(w, wd);
+ //glxrender_free_window_pixmap(w, d, wd);
+ glxrender_fetch_window_region(w, wd);
}
static void
data_t *d;
d = screen_find_plugin_data(sc, plugin_id);
- int a; /* XXX free things here */
- //if (d->root_picture) {
- // xcb_render_free_picture(sc->dpy->conn, d->root_picture);
- // d->root_picture = XCB_NONE;
- //}
+ glxrender_free_root_pixmap(sc, d);
/* pass it on */
d->screen_root_pixmap_change(sc);
{
data_t *d = screen_find_plugin_data(sc, plugin_id);
d_list_it_t *it;
+ GLfloat z;
+
+ //printf("painting\n");
+
+ glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
+
+ /* add 0.1f to keep everything above the root */
+ z = list_length(sc->stacking) * 0.1f + 0.1f;
+ for (it = list_top(sc->stacking); it; it = it->next) {
+ d_window_t *w = it->data;
+
+ if (!window_is_input_only(w) &&
+ (window_is_mapped(w) || window_is_zombie(w)))
+ {
+ int x, y, width, height, bwidth;
+ gboolean opaque;
+ window_data_t *wd;
- printf("painting\n");
+ window_get_area(w, &x, &y, &width, &height, &bwidth);
+
+ if (!(x < sc->super->width_in_pixels &&
+ y < sc->super->height_in_pixels &&
+ (x + width > 0 || x + width + d->xshadowoff > 0) &&
+ (y + height > 0 || y + height + d->yshadowoff > 0)))
+ {
+ continue;
+ }
+
+ opaque = !window_is_argb(w) && window_get_opacity(w) == 0xffff;
+
+ if (opaque) {
+ wd = window_find_plugin_data(w, plugin_id);
+
+ //glPushMatrix();
+
+ paint_window(w, d, wd, x, y, z - 0.05f);
+
+ //glPopMatrix();
+ }
+
+ z -= 0.1f;
+ }
+ }
paint_root(sc, d);
+ glEnable(GL_BLEND);
+ glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
+
for (it = list_bottom(sc->stacking); it; it = it->prev) {
d_window_t *w = it->data;
int x, y, width, height, bwidth;
gboolean opaque;
window_data_t *wd;
+ uint16_t opac;
+ GLfloat alpha;
window_get_area(w, &x, &y, &width, &height, &bwidth);
- if (!(x < sc->super.width_in_pixels &&
- y < sc->super.height_in_pixels &&
+ if (!(x < sc->super->width_in_pixels &&
+ y < sc->super->height_in_pixels &&
(x + width > 0 || x + width + d->xshadowoff > 0) &&
(y + height > 0 || y + height + d->yshadowoff > 0)))
{
continue;
}
- opaque = !window_is_argb(w) && window_get_opacity(w) == 0xffff;
+ opac = window_get_opacity(w);
+ opaque = !window_is_argb(w) && opac == 0xffff;
wd = window_find_plugin_data(w, plugin_id);
- paint_shadow(w, d, wd, x, y, width, height, bwidth);
- paint_window(w, d, wd, opaque, x, y, width, height, bwidth);
+ /* black shadow */
+ alpha = d->shadowalpha;
+ alpha *= opac;
+ alpha /= 0xffff;
+ if (alpha >= 0.01) {
+ glColor4f(0.0f, 0.0f, 0.0f, alpha);
+ paint_shadow(d, wd, x, y, z);
+ }
+
+ if (!opaque) {
+ glColor4us(opac, opac, opac, opac);
+ paint_window(w, d, wd, x, y, z + 0.05f);
+ }
+
+ z += 0.1f;
}
}
- xcb_glx_swap_buffers(sc->dpy->conn, d->context_tag, sc->overlay);
+ glColor4f(0.0f, 0.0f, 0.0f, 0.0f);
+ glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
+ glDisable(GL_BLEND);
+
+ glXSwapBuffers(sc->dpy->xlib_dpy, sc->overlay);
+
+ glFinish();
/* call the function we replaced in the chain */
d->screen_paint(sc);
static void
paint_root(d_screen_t *sc, data_t *d)
{
- //if (!d->root_picture)
- glxrender_update_root_pixmap(sc, d);
+ if (!d->root_glpixmap)
+ glxrender_update_root_pixmap(sc, d);
- glClear(GL_COLOR_BUFFER_BIT);
+ glBindTexture(GL_TEXTURE_2D, d->root_texname);
+ glBegin(GL_QUADS);
+ glTexCoord2f(0, 0);
+ glVertex3i(0, 0, 0);
+ glTexCoord2f(1, 0);
+ glVertex3i(sc->super->width_in_pixels, 0, 0);
+ glTexCoord2f(1, 1);
+ glVertex3i(sc->super->width_in_pixels, sc->super->height_in_pixels, 0);
+ glTexCoord2f(0, 1);
+ glVertex3i(0, sc->super->height_in_pixels, 0);
+ glEnd();
+
+ glBindTexture(GL_TEXTURE_2D, 0);
}
static void
-paint_window(d_window_t *w, data_t *d, window_data_t *wd, gboolean opaque,
- int x, int y, int width, int height, int bwidth)
+paint_window(d_window_t *w, data_t *d, window_data_t *wd, int x, int y,
+ GLfloat z)
{
+ int i;
+
if (!wd->glpixmap)
glxrender_update_window_pixmap(w, d, wd);
+ if (wd->waiting_region)
+ glxrender_update_window_region(w, wd);
+
+ if (wd->nrects < 1) return;
+
+ glBindTexture(GL_TEXTURE_2D, wd->texname);
glBegin(GL_QUADS);
- glColor3f(1.0, 1.0, 1.0);
- glVertex2i(x, y);
- glTexCoord2f(1, 0);
- glVertex2i(x + width + bwidth, y);
- glTexCoord2f(1, 1);
- glVertex2i(x + width + bwidth,
- y + height + bwidth);
- glTexCoord2f(0, 1);
- glVertex2i(x, y + height + bwidth);
- glTexCoord2f(0, 0);
+ for (i = 0; i < wd->nrects * 4; i += 4) {
+ glTexCoord2f(wd->texcoords[i+LEFT], wd->texcoords[i+TOP]);
+ glVertex3f(x+wd->vertices[i+LEFT], y+wd->vertices[i+TOP], z);
+ glTexCoord2f(wd->texcoords[i+RIGHT], wd->texcoords[i+TOP]);
+ glVertex3f(x+wd->vertices[i+RIGHT], y+wd->vertices[i+TOP], z);
+ glTexCoord2f(wd->texcoords[i+RIGHT], wd->texcoords[i+BOTTOM]);
+ glVertex3f(x+wd->vertices[i+RIGHT], y+wd->vertices[i+BOTTOM], z);
+ glTexCoord2f(wd->texcoords[i+LEFT], wd->texcoords[i+BOTTOM]);
+ glVertex3f(x+wd->vertices[i+LEFT], y+wd->vertices[i+BOTTOM], z);
+ }
glEnd();
+
+ glBindTexture(GL_TEXTURE_2D, 0);
}
static void
-paint_shadow(d_window_t *w, data_t *d, window_data_t *wd,
- int x, int y, int width, int height, int bwidth)
+paint_shadow(data_t *d, window_data_t *wd, int x, int y, GLfloat z)
{
-/*
- xcb_render_composite(w->sc->dpy->conn,
- XCB_RENDER_PICT_OP_OVER,
- wd->shadow_picture,
- wd->picture,
- d->overlay_buffer,
- 0, 0, 0, 0,
- x+d->xshadowoff, y+d->yshadowoff,
- width + bwidth*2, height + bwidth *2);
-*/
+ int i;
+
+ if (wd->nrects < 1) return;
+
+ /* shape the shadow to the window */
+ glBindTexture(GL_TEXTURE_2D, wd->texname);
+
+ x += d->xshadowoff;
+ y += d->yshadowoff;
+
+ glBegin(GL_QUADS);
+ for (i = 0; i < wd->nrects * 4; i += 4) {
+ glTexCoord2f(wd->texcoords[i+LEFT], wd->texcoords[i+TOP]);
+ glVertex3f(x+wd->vertices[i+LEFT], y+wd->vertices[i+TOP], z);
+ glTexCoord2f(wd->texcoords[i+RIGHT], wd->texcoords[i+TOP]);
+ glVertex3f(x+wd->vertices[i+RIGHT], y+wd->vertices[i+TOP], z);
+ glTexCoord2f(wd->texcoords[i+RIGHT], wd->texcoords[i+BOTTOM]);
+ glVertex3f(x+wd->vertices[i+RIGHT], y+wd->vertices[i+BOTTOM], z);
+ glTexCoord2f(wd->texcoords[i+LEFT], wd->texcoords[i+BOTTOM]);
+ glVertex3f(x+wd->vertices[i+LEFT], y+wd->vertices[i+BOTTOM], z);
+ }
+ glEnd();
+
+ glBindTexture(GL_TEXTURE_2D, 0);
}