render based on a variable number of vertices per window (for shaped windows in the...
authorDana Jansens <danakj@orodu.net>
Sun, 16 Mar 2008 00:10:59 +0000 (20:10 -0400)
committerDana Jansens <danakj@orodu.net>
Sun, 16 Mar 2008 00:10:59 +0000 (20:10 -0400)
glxrender.c

index 1dc1747..1c5ad24 100644 (file)
 
 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);
 
@@ -48,6 +53,10 @@ typedef struct {
 typedef struct {
     GLuint texname;
     GLXPixmap glpixmap;
+
+    GLfloat *texcoords;
+    GLint *vertices;
+    int nrects;
 } window_data_t;
 
 static gboolean glxrender_find_fb_config(d_screen_t *sc, data_t *d);
@@ -56,10 +65,9 @@ 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);
+                         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 width, int height, int bwidth);
+                         int x, int y);
 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, data_t *d,
@@ -282,8 +290,11 @@ glxrender_window_show(d_window_t *w)
     wd = malloc(sizeof(window_data_t));
     glGenTextures(1, &wd->texname);
     wd->glpixmap = XCB_NONE;
+    wd->nrects = 0;
 
     window_add_plugin_data(w, plugin_id, wd);
+
+    glxrender_update_window_pixmap(w, d, wd);
 }
 
 static void
@@ -316,6 +327,10 @@ glxrender_free_window_pixmap(d_window_t *w, data_t *d, window_data_t *wd)
         //xcb_glx_destroy_pixmap(w->sc->dpy->conn, wd->glpixmap);
         glXDestroyPixmap(w->sc->dpy->xlib_dpy, wd->glpixmap);
         wd->glpixmap = XCB_NONE;
+
+        free(wd->texcoords);
+        free(wd->vertices);
+        wd->nrects = 0;
     }
 }
 
@@ -378,6 +393,26 @@ glxrender_update_window_pixmap(d_window_t *w, data_t *d, window_data_t *wd)
     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
 
     glBindTexture(GL_TEXTURE_2D, 0);
+
+    {
+        int x, y, width, height, bwidth;
+
+        window_get_area(w, &x, &y, &width, &height, &bwidth);
+
+        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;
+
+        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;
+
+        wd->nrects = 1;
+    }
 }
 
 static void
@@ -430,6 +465,7 @@ glxrender_window_resize(d_window_t *w)
 
     assert(wd != NULL);
     glxrender_free_window_pixmap(w, d, wd);
+    glxrender_update_window_pixmap(w, d, wd);
 }
 
 static void
@@ -446,6 +482,7 @@ glxrender_window_reshape(d_window_t *w)
 
     assert(wd != NULL);
     glxrender_free_window_pixmap(w, d, wd);
+    glxrender_update_window_pixmap(w, d, wd);
 }
 
 static void
@@ -495,11 +532,12 @@ glxrender_paint(d_screen_t *sc)
             wd = window_find_plugin_data(w, plugin_id);
 
             glPushMatrix();
-            glTranslatef(x + d->xshadowoff, y + d->yshadowoff, 0.0f);
 
-            paint_shadow(w, d, wd, 0, 0, width, height, bwidth);
+            glTranslatef(d->xshadowoff, d->yshadowoff, 0.0f);
+            paint_shadow(w, d, wd, x, y);
+
             glTranslatef(-d->xshadowoff, -d->yshadowoff, 0.0f);
-            paint_window(w, d, wd, opaque, 0, 0, width, height, bwidth);
+            paint_window(w, d, wd, opaque, x, y);
 
             glPopMatrix();
         }
@@ -522,6 +560,7 @@ paint_root(d_screen_t *sc, data_t *d)
 
     glBindTexture(GL_TEXTURE_2D, d->root_texname);
     glBegin(GL_QUADS);
+    glTexCoord2f(0, 0);
     glVertex2i(0, 0);
     glTexCoord2f(1, 0);
     glVertex2i(sc->super->width_in_pixels, 0);
@@ -529,7 +568,6 @@ paint_root(d_screen_t *sc, data_t *d)
     glVertex2i(sc->super->width_in_pixels, sc->super->height_in_pixels);
     glTexCoord2f(0, 1);
     glVertex2i(0, sc->super->height_in_pixels);
-    glTexCoord2f(0, 0);
     glEnd();
 
     glBindTexture(GL_TEXTURE_2D, 0);
@@ -537,13 +575,16 @@ paint_root(d_screen_t *sc, data_t *d)
 
 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)
+             int x, int y)
 {
     uint16_t o = window_get_opacity(w);
+    int i;
 
     if (!wd->glpixmap)
         glxrender_update_window_pixmap(w, d, wd);
 
+    if (wd->nrects < 1) return;
+
     glBindTexture(GL_TEXTURE_2D, wd->texname);
 
     if (!opaque) {
@@ -554,15 +595,17 @@ paint_window(d_window_t *w, data_t *d, window_data_t *wd, gboolean opaque,
     }
 
     glBegin(GL_QUADS);
-    glTexCoord2f(0, 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);
+    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]);
+        glTexCoord2f(wd->texcoords[i+RIGHT], wd->texcoords[i+TOP]);
+        glVertex2i(x + wd->vertices[i+RIGHT], y + wd->vertices[i+TOP]);
+        glTexCoord2f(wd->texcoords[i+RIGHT], wd->texcoords[i+BOTTOM]);
+        glVertex2i(x + wd->vertices[i+RIGHT], y + wd->vertices[i+BOTTOM]);
+        glTexCoord2f(wd->texcoords[i+LEFT], wd->texcoords[i+BOTTOM]);
+        glVertex2i(x + wd->vertices[i+LEFT], y + wd->vertices[i+BOTTOM]);
+    }
     glEnd();
 
     glBindTexture(GL_TEXTURE_2D, 0);
@@ -575,10 +618,12 @@ paint_window(d_window_t *w, data_t *d, window_data_t *wd, gboolean opaque,
 }
 
 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(d_window_t *w, data_t *d, window_data_t *wd, int x, int y)
 {
     float alpha = d->shadowalpha;
+    int i;
+
+    if (wd->nrects < 1) return;
 
     alpha *= window_get_opacity(w);
     alpha /= 0xffff;
@@ -590,28 +635,23 @@ paint_shadow(d_window_t *w, data_t *d, window_data_t *wd,
     /* black shadow */
     glColor4f(0.0f, 0.0f, 0.0f, alpha);
 
-    if (window_is_argb(w)) {
-        /* shape the shadow to the window's alpha levels */
-        glBindTexture(GL_TEXTURE_2D, wd->texname);
-
-        glBegin(GL_QUADS);
-        glTexCoord2f(0, 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);
-        glEnd();
+    /* shape the shadow to the window */
+    glBindTexture(GL_TEXTURE_2D, wd->texname);
 
-        glBindTexture(GL_TEXTURE_2D, 0);
+    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]);
+        glTexCoord2f(wd->texcoords[i+RIGHT], wd->texcoords[i+TOP]);
+        glVertex2i(x + wd->vertices[i+RIGHT], y + wd->vertices[i+TOP]);
+        glTexCoord2f(wd->texcoords[i+RIGHT], wd->texcoords[i+BOTTOM]);
+        glVertex2i(x + wd->vertices[i+RIGHT], y + wd->vertices[i+BOTTOM]);
+        glTexCoord2f(wd->texcoords[i+LEFT], wd->texcoords[i+BOTTOM]);
+        glVertex2i(x + wd->vertices[i+LEFT], y + wd->vertices[i+BOTTOM]);
     }
-    else
-        /* draw a solid rectangle */
-        glRecti(x, y,
-                x + width + bwidth - 1, y + height + bwidth - 1);
+    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);