From: Alexander Larsson Date: Tue, 15 Mar 2011 08:50:07 +0000 (+0100) Subject: broadway: double buffer window updates X-Git-Url: http://pileus.org/git/?a=commitdiff_plain;h=e3a2176a1fe5363560fc646d4ae2d4690fbd4c8f;p=~andy%2Fgtk 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. --- diff --git a/gdk/broadway/broadway.c b/gdk/broadway/broadway.c index bc78de1e5..d5e944d38 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 c750a2497..635fc918c 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 cd81d0950..89242e353 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 c42bbf20d..b98669758 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);