#include <assert.h>
#include <stdlib.h>
+#include <X11/Xmd.h>
+#include <GL/glxproto.h>
+
#include <GL/gl.h>
#include <GL/glx.h>
#include <GL/glxtokens.h>
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);
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 gboolean glxrender_find_fb_config(d_screen_t *sc, data_t *d);
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);
-static void paint_shadow(d_window_t *w, data_t *d, window_data_t *wd,
- int x, int y);
+ 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_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);
exit(1);
}
- d->context = glXCreateContext(sc->dpy->xlib_dpy, vi, NULL, GL_TRUE);
- glXMakeCurrent(sc->dpy->xlib_dpy, sc->overlay, d->context);
-
-
if (!(glxrender_find_fb_config(sc, d))) {
printf("unable to find FB configs\n");
exit(1);
}
+ 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);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
glEnable(GL_TEXTURE_2D);
+ glEnable(GL_DEPTH_TEST);
+ //glEnable(GL_SCISSOR_TEST); ?? what is this, glxcompmgr enables it
+ //glEnable(GL_STENCIL_TEST); ?? what is this, glxcompmgr enables it
glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA);
glDisable(GL_BLEND);
glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
- glClear(GL_COLOR_BUFFER_BIT);
+ glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
+
glXSwapBuffers(sc->dpy->xlib_dpy, sc->overlay);
d->bind_func = (BindEXTFunc)
d->release_func = (ReleaseEXTFunc)
glXGetProcAddress((const guchar*)"glXReleaseTexImageEXT");
+ SwapIntervalSGIFunc swap_interval_func = (SwapIntervalSGIFunc)
+ glXGetProcAddress((const guchar*)"glXSwapIntervalSGI");
+ if(swap_interval_func)
+ swap_interval_func(1);
+
glGenTextures(1, &d->root_texname);
d->root_glpixmap = XCB_NONE;
}
stencil = 32767;
depth = 32767;
- printf("looking for depth %d\n", i);
+ //printf("looking for depth %d\n", i);
tvis.depth = i;
visinfo = XGetVisualInfo(sc->dpy->xlib_dpy, VisualDepthMask,
glxrender_free(d_screen_t *sc)
{
data_t *d = screen_find_plugin_data(sc, plugin_id);
- glxrender_free_root_pixmap(sc, d);
- 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);
}
glxrender_window_free_data(d_window_t *w, data_t *d, window_data_t *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)
+ 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_update_window_pixmap(w, d, wd);
+ glxrender_fetch_window_region(w, wd);
}
static void
wd->glpixmap, GLX_FRONT_LEFT_EXT);
glBindTexture(GL_TEXTURE_2D, 0);
- //xcb_glx_destroy_pixmap(w->sc->dpy->conn, wd->glpixmap);
glXDestroyPixmap(w->sc->dpy->xlib_dpy, wd->glpixmap);
wd->glpixmap = XCB_NONE;
+ }
+}
+
+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;
}
}
d->root_glpixmap, GLX_FRONT_LEFT_EXT);
glBindTexture(GL_TEXTURE_2D, 0);
- //xcb_glx_destroy_pixmap(w->sc->dpy->conn, wd->glpixmap);
glXDestroyPixmap(sc->dpy->xlib_dpy, d->root_glpixmap);
d->root_glpixmap = XCB_NONE;
}
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_MIN_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
glBindTexture(GL_TEXTURE_2D, 0);
+}
- {
- int x, y, width, height, bwidth;
+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;
- window_get_area(w, &x, &y, &width, &height, &bwidth);
+ if (!wd->waiting_region) return;
- wd->texcoords = (GLfloat*)malloc(sizeof(GLfloat) * 4);
- wd->texcoords[LEFT] = 0.0f;
- wd->texcoords[TOP] = 0.0f;
- wd->texcoords[RIGHT] = 1.0f;
- wd->texcoords[BOTTOM] = 1.0f;
+ 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;
- wd->vertices = (GLint*)malloc(sizeof(GLint) * 4);
- wd->vertices[LEFT] = 0;
- wd->vertices[TOP] = 0;
- wd->vertices[RIGHT] = width + bwidth;
- wd->vertices[BOTTOM] = height + bwidth;
+ 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->nrects = 1;
+ 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
assert(wd != NULL);
glxrender_free_window_pixmap(w, d, wd);
- glxrender_update_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, d, wd);
- glxrender_update_window_pixmap(w, d, wd);
+ //glxrender_free_window_pixmap(w, d, wd);
+ glxrender_fetch_window_region(w, wd);
}
static void
{
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;
+
+ 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);
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);
- glPushMatrix();
-
- glTranslatef(d->xshadowoff, d->yshadowoff, 0.0f);
- paint_shadow(w, d, wd, x, y);
+ /* 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);
+ }
- glTranslatef(-d->xshadowoff, -d->yshadowoff, 0.0f);
- paint_window(w, d, wd, opaque, x, y);
+ if (!opaque) {
+ glColor4us(opac, opac, opac, opac);
+ paint_window(w, d, wd, x, y, z + 0.05f);
+ }
- glPopMatrix();
+ 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);
}
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);
- glVertex2i(0, 0);
+ glVertex3i(0, 0, 0);
glTexCoord2f(1, 0);
- glVertex2i(sc->super->width_in_pixels, 0);
+ glVertex3i(sc->super->width_in_pixels, 0, 0);
glTexCoord2f(1, 1);
- glVertex2i(sc->super->width_in_pixels, sc->super->height_in_pixels);
+ glVertex3i(sc->super->width_in_pixels, sc->super->height_in_pixels, 0);
glTexCoord2f(0, 1);
- glVertex2i(0, sc->super->height_in_pixels);
+ 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)
+paint_window(d_window_t *w, data_t *d, window_data_t *wd, int x, int y,
+ GLfloat z)
{
- uint16_t o = window_get_opacity(w);
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);
- if (!opaque) {
- glEnable(GL_BLEND);
-
- glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
- glColor4us(o, o, o, o);
- }
-
glBegin(GL_QUADS);
for (i = 0; i < wd->nrects * 4; i += 4) {
- // XXX use glVertex3i
glTexCoord2f(wd->texcoords[i+LEFT], wd->texcoords[i+TOP]);
- glVertex2i(x + wd->vertices[i+LEFT], y + wd->vertices[i+TOP]);
+ glVertex3f(x+wd->vertices[i+LEFT], y+wd->vertices[i+TOP], z);
glTexCoord2f(wd->texcoords[i+RIGHT], wd->texcoords[i+TOP]);
- glVertex2i(x + wd->vertices[i+RIGHT], y + wd->vertices[i+TOP]);
+ glVertex3f(x+wd->vertices[i+RIGHT], y+wd->vertices[i+TOP], z);
glTexCoord2f(wd->texcoords[i+RIGHT], wd->texcoords[i+BOTTOM]);
- glVertex2i(x + wd->vertices[i+RIGHT], y + wd->vertices[i+BOTTOM]);
+ glVertex3f(x+wd->vertices[i+RIGHT], y+wd->vertices[i+BOTTOM], z);
glTexCoord2f(wd->texcoords[i+LEFT], wd->texcoords[i+BOTTOM]);
- glVertex2i(x + wd->vertices[i+LEFT], y + wd->vertices[i+BOTTOM]);
+ glVertex3f(x+wd->vertices[i+LEFT], y+wd->vertices[i+BOTTOM], z);
}
glEnd();
glBindTexture(GL_TEXTURE_2D, 0);
-
- if (!opaque) {
- glColor4f(0.0f, 0.0f, 0.0f, 0.0f);
- glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
- glDisable(GL_BLEND);
- }
}
static void
-paint_shadow(d_window_t *w, data_t *d, window_data_t *wd, int x, int y)
+paint_shadow(data_t *d, window_data_t *wd, int x, int y, GLfloat z)
{
- float alpha = d->shadowalpha;
int i;
if (wd->nrects < 1) return;
- alpha *= window_get_opacity(w);
- alpha /= 0xffff;
-
- if (alpha < 0.01) return;
-
- glEnable(GL_BLEND);
- glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
- /* black shadow */
- glColor4f(0.0f, 0.0f, 0.0f, alpha);
-
/* 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]);
- glVertex2i(x + wd->vertices[i+LEFT], y + wd->vertices[i+TOP]);
+ glVertex3f(x+wd->vertices[i+LEFT], y+wd->vertices[i+TOP], z);
glTexCoord2f(wd->texcoords[i+RIGHT], wd->texcoords[i+TOP]);
- glVertex2i(x + wd->vertices[i+RIGHT], y + wd->vertices[i+TOP]);
+ glVertex3f(x+wd->vertices[i+RIGHT], y+wd->vertices[i+TOP], z);
glTexCoord2f(wd->texcoords[i+RIGHT], wd->texcoords[i+BOTTOM]);
- glVertex2i(x + wd->vertices[i+RIGHT], y + wd->vertices[i+BOTTOM]);
+ glVertex3f(x+wd->vertices[i+RIGHT], y+wd->vertices[i+BOTTOM], z);
glTexCoord2f(wd->texcoords[i+LEFT], wd->texcoords[i+BOTTOM]);
- glVertex2i(x + wd->vertices[i+LEFT], y + wd->vertices[i+BOTTOM]);
+ glVertex3f(x+wd->vertices[i+LEFT], y+wd->vertices[i+BOTTOM], z);
}
glEnd();
glBindTexture(GL_TEXTURE_2D, 0);
-
- glColor4f(0.0f, 0.0f, 0.0f, 0.0f);
- glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
- glDisable(GL_BLEND);
}