[gtk+/broadway: 242/246] broadway: double buffer window updates



commit e3a2176a1fe5363560fc646d4ae2d4690fbd4c8f
Author: Alexander Larsson <alexl redhat com>
Date:   Tue Mar 15 09:50:07 2011 +0100

    broadway: double buffer window updates
    
    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           |   15 ++++
 gdk/broadway/broadway.h           |    2 +
 gdk/broadway/broadway.js          |  138 +++++++++++++++++++++++-------------
 gdk/broadway/gdkwindow-broadway.c |    2 +
 4 files changed, 107 insertions(+), 50 deletions(-)
---
diff --git a/gdk/broadway/broadway.c b/gdk/broadway/broadway.c
index bc78de1..d5e944d 100644
--- a/gdk/broadway/broadway.c
+++ b/gdk/broadway/broadway.c
@@ -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,
diff --git a/gdk/broadway/broadway.h b/gdk/broadway/broadway.h
index c750a24..635fc91 100644
--- a/gdk/broadway/broadway.h
+++ b/gdk/broadway/broadway.h
@@ -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,
diff --git a/gdk/broadway/broadway.js b/gdk/broadway/broadway.js
index cd81d09..89242e3 100644
--- a/gdk/broadway/broadway.js
+++ b/gdk/broadway/broadway.js
@@ -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);
diff --git a/gdk/broadway/gdkwindow-broadway.c b/gdk/broadway/gdkwindow-broadway.c
index c42bbf2..b986697 100644
--- a/gdk/broadway/gdkwindow-broadway.c
+++ b/gdk/broadway/gdkwindow-broadway.c
@@ -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);



[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]