]> Pileus Git - ~andy/gtk/commitdiff
broadway: double buffer window updates
authorAlexander Larsson <alexl@redhat.com>
Tue, 15 Mar 2011 08:50:07 +0000 (09:50 +0100)
committerAlexander Larsson <alexl@redhat.com>
Tue, 15 Mar 2011 08:50:07 +0000 (09:50 +0100)
Ensure that we're writing all the updates for a single rendering op
in one go without callbacks inbetween. That way some rendering will
be delayed, but the user will never see partial renderings.

gdk/broadway/broadway.c
gdk/broadway/broadway.h
gdk/broadway/broadway.js
gdk/broadway/gdkwindow-broadway.c

index bc78de1e58feabf91acdc576e35d2690da6b5894..d5e944d382fbf7e5da9aeb3a79a22fae4d649e6a 100644 (file)
@@ -1088,6 +1088,21 @@ broadway_output_put_rgba (BroadwayOutput *output,  int id, int x, int y,
   free (rects);
 }
 
+void
+broadway_output_surface_flush (BroadwayOutput *output,
+                              int             id)
+{
+  char buf[HEADER_LEN + 3];
+  int p;
+
+  p = write_header (output, buf, 'f');
+  append_uint16 (id, buf, &p);
+
+  assert (p == sizeof (buf));
+
+  broadway_output_write (output, buf, sizeof (buf));
+}
+
 #if 0
 static void
 send_image_a (BroadwayOutput *output,  int id, int x, int y,
index c750a2497ba3de5d96b9b3be80409f2b685bb742..635fc918c1682131976c0abe79e9e443805e8f5f 100644 (file)
@@ -49,6 +49,8 @@ void            broadway_output_put_rgba        (BroadwayOutput *output,
                                                 int             h,
                                                 int             byte_stride,
                                                 void           *data);
+void            broadway_output_surface_flush   (BroadwayOutput *output,
+                                                int             id);
 void            broadway_output_copy_rectangles (BroadwayOutput *output,
                                                 int             id,
                                                 BroadwayRect   *rects,
index cd81d095075927613a123d5221a3c208ee99c922..89242e353ab329c2237fb637c8632ea5b174eaf5 100644 (file)
@@ -101,6 +101,7 @@ function initContext(canvas, x, y, id)
   var context = canvas.getContext("2d");
   context.globalCompositeOperation = "source-over";
   document.body.appendChild(canvas);
+  context.drawQueue = [];
 
   return context;
 }
@@ -146,6 +147,63 @@ function getButtonMask (button) {
     return 0;
 }
 
+function flushSurface(surface)
+{
+    var commands = surface.drawQueue;
+    surface.queue = [];
+    var i = 0;
+    for (i = 0; i < commands.length; i++) {
+       var cmd = commands[i];
+       var context = surfaces[cmd.id];
+       switch (cmd.op) {
+      /* put image data surface */
+       case 'i':
+           context.globalCompositeOperation = "source-over";
+           context.drawImage(cmd.img, cmd.x, cmd.y);
+           break;
+
+      /* copy rects */
+       case 'b':
+           context.save();
+           context.beginPath();
+
+           var minx;
+           var miny;
+           var maxx;
+           var maxy;
+           for (var j = 0; j < cmd.rects.length; j++) {
+               var rect = cmd.rects[j];
+               context.rect(rect.x, rect.y, rect.w, rect.h);
+               if (j == 0) {
+                   minx = rect.x;
+                   miny = rect.y;
+                   maxx = rect.x + rect.w;
+                   maxy = rect.y + rect.h;
+               } else {
+                   if (rect.x < minx)
+                       minx = rect.x;
+                   if (rect.y < miny)
+                       miny = rect.y;
+                   if (rect.x + rect.w > maxx)
+                       maxx = rect.x + rect.w;
+                   if (rect.y + rect.h > maxy)
+                       maxy = rect.y + rect.h;
+               }
+           }
+           context.clip();
+           context.globalCompositeOperation = "copy";
+           context.drawImage(context.canvas,
+                             minx - cmd.dx, miny - cmd.dy, maxx - minx, maxy - miny,
+                             minx, miny, maxx - minx, maxy - miny);
+           context.restore();
+           break;
+
+      default:
+           alert("Unknown drawing op " + cmd.op);
+       }
+    }
+}
+
 function handleCommands(cmd_obj)
 {
   var cmd = cmd_obj.data;
@@ -218,30 +276,31 @@ function handleCommands(cmd_obj)
         i = i + 3;
         var h = base64_16(cmd, i);
         i = i + 3;
+       flushSurface(surfaces[id]);
        surfaces[id].canvas.width = w;
        surfaces[id].canvas.height = h;
         break;
 
       /* put image data surface */
       case 'i':
-        var id = base64_16(cmd, i);
+       var q = new Object();
+       q.op = 'i';
+        q.id = base64_16(cmd, i);
         i = i + 3;
-        var x = base64_16(cmd, i);
+        q.x = base64_16(cmd, i);
         i = i + 3;
-        var y = base64_16(cmd, i);
+        q.y = base64_16(cmd, i);
         i = i + 3;
         var size = base64_32(cmd, i);
         i = i + 6;
        var url = cmd.slice(i, i + size);
        i = i + size;
-        var img = new Image();
-       img.src = url;
-       surfaces[id].globalCompositeOperation = "source-over";
-       if (img.complete) {
-          surfaces[id].drawImage(img, x, y);
-       } else {
+        q.img = new Image();
+       q.img.src = url;
+       surfaces[q.id].drawQueue.push(q);
+       if (!q.img.complete) {
          cmd_obj.pos = i;
-         img.onload = function() { surfaces[id].drawImage(img, x, y); handleOutstanding(); };
+         q.img.onload = function() { handleOutstanding(); };
          return false;
        }
 
@@ -249,62 +308,41 @@ function handleCommands(cmd_obj)
 
       /* copy rects */
       case 'b':
-        var id = base64_16(cmd, i);
+       var q = new Object();
+       q.op = 'b';
+        q.id = base64_16(cmd, i);
         i = i + 3;
 
        var nrects = base64_16(cmd, i);
         i = i + 3;
 
-       var context = surfaces[id];
-       context.save();
-       context.beginPath();
-
-       var minx;
-       var miny;
-       var maxx;
-       var maxy;
+       q.rects = [];
        for (var r = 0; r < nrects; r++) {
-         var x = base64_16(cmd, i);
+         var rect = new Object();
+         rect.x = base64_16(cmd, i);
           i = i + 3;
-          var y = base64_16(cmd, i);
+          rect.y = base64_16(cmd, i);
           i = i + 3;
-          var w = base64_16(cmd, i);
+          rect.w = base64_16(cmd, i);
           i = i + 3;
-          var h = base64_16(cmd, i);
+          rect.h = base64_16(cmd, i);
           i = i + 3;
-         context.rect(x, y, w, h);
-
-         if (r == 0) {
-             minx = x;
-             miny = y;
-             maxx = x + w;
-             maxy = y + h;
-         } else {
-             if (x < minx)
-                 minx = x;
-             if (y < miny)
-                 miny = y;
-             if (x + w > maxx)
-                 maxx = x + w;
-             if (y + h > maxy)
-                 maxy = y + h;
-         }
+         q.rects.push (rect);
        }
 
-       context.clip();
-
-        var dx = base64_16s(cmd, i);
+        q.dx = base64_16s(cmd, i);
         i = i + 3;
-        var dy = base64_16s(cmd, i);
+        q.dy = base64_16s(cmd, i);
         i = i + 3;
+       surfaces[q.id].drawQueue.push(q);
+        break;
 
-       context.globalCompositeOperation = "copy";
-        context.drawImage(context.canvas,
-                         minx - dx, miny - dy, maxx - minx, maxy - miny,
-                         minx, miny, maxx - minx, maxy - miny);
+      case 'f': // Flush surface
+        var id = base64_16(cmd, i);
+        i = i + 3;
 
-       context.restore();
-        break;
+       flushSurface(surfaces[id]);
+       break;
 
       case 'q': // Query pointer
         var id = base64_16(cmd, i);
index c42bbf20ddf2d200b95e10df52eac90d9416839f..b986697584193148328f022c307920fdb927c86e 100644 (file)
@@ -153,6 +153,8 @@ window_data_send (BroadwayOutput *output, GdkWindowImplBroadway *impl)
                               cairo_image_surface_get_data (impl->surface));
     }
 
+  broadway_output_surface_flush (output, impl->id);
+
   cr = cairo_create (impl->last_surface);
   cairo_set_source_surface (cr, impl->surface, 0, 0);
   cairo_paint (cr);