split the round trip to fetch a window's region up so that the request can be sent...
authorDana Jansens <danakj@orodu.net>
Sun, 16 Mar 2008 04:13:07 +0000 (00:13 -0400)
committerDana Jansens <danakj@orodu.net>
Sun, 16 Mar 2008 04:13:58 +0000 (00:13 -0400)
glxrender.c

index e0c1cce..6077ccf 100644 (file)
@@ -57,6 +57,9 @@ typedef struct {
     GLfloat *texcoords;
     GLint *vertices;
     int nrects;
+
+    xcb_xfixes_fetch_region_cookie_t ck_region;
+    int waiting_region;
 } window_data_t;
 
 static gboolean glxrender_find_fb_config(d_screen_t *sc, data_t *d);
@@ -70,9 +73,11 @@ 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);
 
@@ -272,6 +277,7 @@ void
 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);
 }
@@ -294,11 +300,14 @@ glxrender_window_show(d_window_t *w)
     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
@@ -333,9 +342,16 @@ glxrender_free_window_pixmap(d_window_t *w, data_t *d, window_data_t *wd)
         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;
     }
 }
@@ -404,16 +420,25 @@ 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)
+{
+    if (wd->waiting_region) return;
+
+    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_region_t reg;
-    xcb_xfixes_fetch_region_cookie_t ck;
     xcb_xfixes_fetch_region_reply_t *rep;
     xcb_rectangle_t area, *rects;
-    int nrects, i, x, y, wid, hei, bwid;
+    int nrects, i, j, x, y, wid, hei, bwid;
 
-    reg = window_get_region(w);
-    ck = xcb_xfixes_fetch_region_unchecked(w->sc->dpy->conn, reg);
+    if (!wd->waiting_region) return;
 
     window_get_area(w, &x, &y, &wid, &hei, &bwid);
     area.x = x;
@@ -421,7 +446,7 @@ glxrender_update_window_region(d_window_t *w, window_data_t *wd)
     area.width = wid + bwid * 2;
     area.height = hei + bwid * 2;
 
-    rep = xcb_xfixes_fetch_region_reply(w->sc->dpy->conn, ck, NULL);
+    rep = xcb_xfixes_fetch_region_reply(w->sc->dpy->conn, wd->ck_region, NULL);
     if (!rep) {
         rects = &area;
         nrects = 1;
@@ -431,30 +456,33 @@ glxrender_update_window_region(d_window_t *w, window_data_t *wd)
         nrects = xcb_xfixes_fetch_region_rectangles_length(rep);
     }
 
-    wd->texcoords = (GLfloat*)malloc(sizeof(GLfloat) * (nrects * 4));
-    wd->vertices = (GLint*)malloc(sizeof(GLint) * (nrects * 4));
+    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 = 0; i < nrects * 4; i += 4) {
+    for (i = j = 0; i < nrects * 4; ++j, i += 4) {
         wd->texcoords[i+LEFT] =
-            (GLfloat)(rects[i].x - area.x) / (GLfloat)area.width;
+            (GLfloat)(rects[j].x - x) / (GLfloat)area.width;
         wd->texcoords[i+TOP] =
-            (GLfloat)(rects[i].y - area.y) / (GLfloat)area.height;
+            (GLfloat)(rects[j].y - y) / (GLfloat)area.height;
         wd->texcoords[i+RIGHT] =
-            (GLfloat)(rects[i].x - area.x + rects[i].width) /
+            (GLfloat)(rects[j].x - x + rects[j].width) /
             (GLfloat)area.width;
         wd->texcoords[i+BOTTOM] =
-            (GLfloat)(rects[i].y - area.y + rects[i].height) /
+            (GLfloat)(rects[j].y - y + rects[j].height) /
             (GLfloat)area.height;
 
-        wd->vertices[i+LEFT] = rects[i].x - x;
-        wd->vertices[i+TOP] = rects[i].y - y;
-        wd->vertices[i+RIGHT] = rects[i].x - x + rects[i].width;
-        wd->vertices[i+BOTTOM] = rects[i].y - y + rects[i].height;
+        wd->vertices[i+LEFT] = rects[j].x - x;
+        wd->vertices[i+TOP] = rects[j].y - y;
+        wd->vertices[i+RIGHT] = rects[j].x - x + rects[j].width;
+        wd->vertices[i+BOTTOM] = rects[j].y - y + rects[j].height;
     }
 
     if (rep)
         free(rep);
+
+    wd->waiting_region = FALSE;
 }
 
 static void
@@ -507,7 +535,9 @@ glxrender_window_resize(d_window_t *w)
 
     assert(wd != NULL);
     glxrender_free_window_pixmap(w, d, wd);
-    glxrender_update_window_pixmap(w, d, wd);
+
+    glxrender_free_window_region(wd);
+    glxrender_fetch_window_region(w, wd);
 }
 
 static void
@@ -524,7 +554,9 @@ glxrender_window_reshape(d_window_t *w)
 
     assert(wd != NULL);
     glxrender_free_window_pixmap(w, d, wd);
-    glxrender_update_window_pixmap(w, d, wd);
+
+    glxrender_free_window_region(wd);
+    glxrender_fetch_window_region(w, wd);
 }
 
 static void