mirror of
https://gitlab.gnome.org/GNOME/gtk.git
synced 2025-01-01 00:11:29 +00:00
[broadway] Send diffs as bilevel rgba instead of true diff
The true diff only works if the destination keeps perfect 32bit canvas data, which is not always true. So, instead we send only changed pixels, masking the others to 0 via alpha 0.
This commit is contained in:
parent
6fe849d4f1
commit
e6c340519c
@ -5,14 +5,15 @@
|
||||
#include "broadway.h"
|
||||
#include <math.h>
|
||||
#include <unistd.h>
|
||||
#include <stdint.h>
|
||||
#include <cairo.h>
|
||||
|
||||
static void
|
||||
diff_surfaces (cairo_surface_t *surface,
|
||||
cairo_surface_t *old_surface)
|
||||
{
|
||||
unsigned char *data, *old_data;
|
||||
unsigned char *line, *old_line;
|
||||
uint8_t *data, *old_data;
|
||||
uint32_t *line, *old_line;
|
||||
int w, h, stride, old_stride;
|
||||
int x, y;
|
||||
|
||||
@ -27,16 +28,17 @@ diff_surfaces (cairo_surface_t *surface,
|
||||
|
||||
for (y = 0; y < h; y++)
|
||||
{
|
||||
line = data;
|
||||
old_line = old_data;
|
||||
line = (uint32_t *)data;
|
||||
old_line = (uint32_t *)old_data;
|
||||
|
||||
for (x = 0; x < w; x++)
|
||||
{
|
||||
int j;
|
||||
for (j = 0; j < 4; j++)
|
||||
old_line[j] = line[j] - old_line[j];
|
||||
line += 4;
|
||||
old_line += 4;
|
||||
if (*line & 0xffffff == *old_line & 0xffffff)
|
||||
*old_line = 0;
|
||||
else
|
||||
*old_line = *line | 0xff000000;
|
||||
line ++;
|
||||
old_line ++;
|
||||
}
|
||||
|
||||
data += stride;
|
||||
@ -181,8 +183,8 @@ demo2 (BroadwayClient *client)
|
||||
{
|
||||
diff_surfaces (surface,
|
||||
old_surface);
|
||||
broadway_client_put_delta_rgb (client, 0, 0, 0, 800, 600, 800*4,
|
||||
cairo_image_surface_get_data(old_surface));
|
||||
broadway_client_put_rgba (client, 0, 0, 0, 800, 600, 800*4,
|
||||
cairo_image_surface_get_data(old_surface));
|
||||
}
|
||||
broadway_client_move_surface (client, 0, 100 + i, 100 + i);
|
||||
|
||||
|
@ -834,12 +834,12 @@ broadway_client_put_rgb (BroadwayClient *client, int id, int x, int y,
|
||||
}
|
||||
|
||||
static void
|
||||
rgb_autocrop (unsigned char *data,
|
||||
int byte_stride,
|
||||
int *x_arg, int *y_arg,
|
||||
int *w_arg, int *h_arg)
|
||||
rgba_autocrop (unsigned char *data,
|
||||
int byte_stride,
|
||||
int *x_arg, int *y_arg,
|
||||
int *w_arg, int *h_arg)
|
||||
{
|
||||
unsigned char *line;
|
||||
uint32_t *line;
|
||||
int w, h;
|
||||
int x, y, xx, yy;
|
||||
boolean non_zero;
|
||||
@ -851,16 +851,16 @@ rgb_autocrop (unsigned char *data,
|
||||
|
||||
while (h > 0)
|
||||
{
|
||||
line = data + y * byte_stride + x * 4;
|
||||
line = (uint32_t *)(data + y * byte_stride + x * 4);
|
||||
|
||||
non_zero = FALSE;
|
||||
for (xx = 0; xx < w; xx++)
|
||||
{
|
||||
if (line[1] != 0 || line[2] != 0 || line[3] != 0) {
|
||||
if (*line != 0) {
|
||||
non_zero = TRUE;
|
||||
break;
|
||||
}
|
||||
line += 4;
|
||||
line++;
|
||||
}
|
||||
|
||||
if (non_zero)
|
||||
@ -872,16 +872,16 @@ rgb_autocrop (unsigned char *data,
|
||||
|
||||
while (h > 0)
|
||||
{
|
||||
line = data + (y + h - 1) * byte_stride + x * 4;
|
||||
line = (uint32_t *)(data + (y + h - 1) * byte_stride + x * 4);
|
||||
|
||||
non_zero = FALSE;
|
||||
for (xx = 0; xx < w; xx++)
|
||||
{
|
||||
if (line[1] != 0 || line[2] != 0 || line[3] != 0) {
|
||||
if (*line != 0) {
|
||||
non_zero = TRUE;
|
||||
break;
|
||||
}
|
||||
line += 4;
|
||||
line++;
|
||||
}
|
||||
|
||||
if (non_zero)
|
||||
@ -891,16 +891,16 @@ rgb_autocrop (unsigned char *data,
|
||||
|
||||
while (w > 0)
|
||||
{
|
||||
line = data + y * byte_stride + x * 4;
|
||||
line = (uint32_t *)(data + y * byte_stride + x * 4);
|
||||
|
||||
non_zero = FALSE;
|
||||
for (yy = 0; yy < h; yy++)
|
||||
{
|
||||
if (line[1] != 0 || line[2] != 0 || line[3] != 0) {
|
||||
if (*line != 0) {
|
||||
non_zero = TRUE;
|
||||
break;
|
||||
}
|
||||
line += byte_stride;
|
||||
line += byte_stride / 4;
|
||||
}
|
||||
|
||||
if (non_zero)
|
||||
@ -912,16 +912,16 @@ rgb_autocrop (unsigned char *data,
|
||||
|
||||
while (w > 0)
|
||||
{
|
||||
line = data + y * byte_stride + (x + w - 1) * 4;
|
||||
line = (uint32_t *)(data + y * byte_stride + (x + w - 1) * 4);
|
||||
|
||||
non_zero = FALSE;
|
||||
for (yy = 0; yy < h; yy++)
|
||||
{
|
||||
if (line[1] != 0 || line[2] != 0 || line[3] != 0) {
|
||||
if (*line != 0) {
|
||||
non_zero = TRUE;
|
||||
break;
|
||||
}
|
||||
line += byte_stride;
|
||||
line += byte_stride / 4;
|
||||
}
|
||||
|
||||
if (non_zero)
|
||||
@ -935,43 +935,6 @@ rgb_autocrop (unsigned char *data,
|
||||
*h_arg = h;
|
||||
}
|
||||
|
||||
void
|
||||
broadway_client_put_delta_rgb (BroadwayClient *client, int id, int dest_x, int dest_y,
|
||||
int w, int h, int byte_stride, void *data)
|
||||
{
|
||||
char buf[16];
|
||||
size_t len;
|
||||
char *url;
|
||||
int src_x, src_y;
|
||||
|
||||
src_x = 0;
|
||||
src_y = 0;
|
||||
|
||||
rgb_autocrop (data,
|
||||
byte_stride,
|
||||
&src_x, &src_y, &w, &h);
|
||||
|
||||
if (w == 0 || h == 0)
|
||||
return;
|
||||
|
||||
data = (uint8_t *)data + src_x * 4 + src_y * byte_stride;
|
||||
|
||||
buf[0] = 'D';
|
||||
base64_uint16(id, &buf[1]);
|
||||
base64_uint16(dest_x + src_x, &buf[4]);
|
||||
base64_uint16(dest_y + src_y, &buf[7]);
|
||||
|
||||
url = to_png_rgb (w, h, byte_stride, (uint32_t*)data);
|
||||
len = strlen (url);
|
||||
base64_uint32(len, &buf[10]);
|
||||
|
||||
broadway_client_write (client, buf, 16);
|
||||
|
||||
broadway_client_write (client, url, len);
|
||||
|
||||
free (url);
|
||||
}
|
||||
|
||||
void
|
||||
broadway_client_put_rgba (BroadwayClient *client, int id, int x, int y,
|
||||
int w, int h, int byte_stride, void *data)
|
||||
@ -979,11 +942,26 @@ broadway_client_put_rgba (BroadwayClient *client, int id, int x, int y,
|
||||
char buf[16];
|
||||
size_t len;
|
||||
char *url;
|
||||
int crop_x, crop_y;
|
||||
|
||||
crop_x = 0;
|
||||
crop_y = 0;
|
||||
|
||||
printf ("pre crop: %dx%d\n", w, h);
|
||||
rgba_autocrop (data,
|
||||
byte_stride,
|
||||
&crop_x, &crop_y, &w, &h);
|
||||
printf ("post crop: %dx%d %d,%d\n", w, h, crop_x, crop_y);
|
||||
|
||||
if (w == 0 || h == 0)
|
||||
return;
|
||||
|
||||
data = (uint8_t *)data + crop_x * 4 + crop_y * byte_stride;
|
||||
|
||||
buf[0] = 'i';
|
||||
base64_uint16(id, &buf[1]);
|
||||
base64_uint16(x, &buf[4]);
|
||||
base64_uint16(y, &buf[7]);
|
||||
base64_uint16(x + crop_x, &buf[4]);
|
||||
base64_uint16(y + crop_y, &buf[7]);
|
||||
|
||||
url = to_png_rgba (w, h, byte_stride, (uint32_t*)data);
|
||||
len = strlen (url);
|
||||
|
@ -39,14 +39,6 @@ void broadway_client_put_rgba (BroadwayClient *client,
|
||||
int h,
|
||||
int byte_stride,
|
||||
void *data);
|
||||
void broadway_client_put_delta_rgb (BroadwayClient *client,
|
||||
int id,
|
||||
int dest_x,
|
||||
int dest_y,
|
||||
int w,
|
||||
int h,
|
||||
int byte_stride,
|
||||
void *data);
|
||||
void broadway_client_copy_rectangles (BroadwayClient *client,
|
||||
int id,
|
||||
BroadwayRect *rects,
|
||||
|
@ -68,31 +68,6 @@ var surfaces = {};
|
||||
var outstanding_commands = new Array();
|
||||
var input_socket = null;
|
||||
|
||||
function apply_delta(id, img, x, y)
|
||||
{
|
||||
var tmp_surface = document.createElement("canvas");
|
||||
var w = img.width;
|
||||
var h = img.height;
|
||||
tmp_surface.width = w;
|
||||
tmp_surface.height = h;
|
||||
|
||||
tmp_context = tmp_surface.getContext("2d");
|
||||
tmp_context.drawImage(img, 0, 0);
|
||||
|
||||
var data = surfaces[id].getImageData(x, y, w, h);
|
||||
var d = data.data
|
||||
var delta = tmp_context.getImageData(0, 0, w, h).data;
|
||||
var imax = w * h * 4;
|
||||
for (var i = 0; i < imax; i += 4) {
|
||||
d[i ] = (d[i ] + delta[i ]) & 0xff;
|
||||
d[i+1] = (d[i+1] + delta[i+1]) & 0xff;
|
||||
d[i+2] = (d[i+2] + delta[i+2]) & 0xff;
|
||||
d[i+3] = 255;
|
||||
}
|
||||
surfaces[id].putImageData(data, x, y);
|
||||
delete tmp_surface
|
||||
}
|
||||
|
||||
function initContext(canvas, x, y, id)
|
||||
{
|
||||
canvas.surface_id = id;
|
||||
@ -101,7 +76,7 @@ function initContext(canvas, x, y, id)
|
||||
canvas.style["left"] = y + "px"
|
||||
canvas.style["display"] = "none"
|
||||
context = canvas.getContext("2d")
|
||||
context.globalCompositeOperation = "copy"
|
||||
context.globalCompositeOperation = "src-over"
|
||||
context.fillRect(0, 0, canvas.width, canvas.height);
|
||||
document.body.appendChild(canvas)
|
||||
|
||||
@ -194,30 +169,6 @@ function handleCommands(cmd_obj)
|
||||
|
||||
break;
|
||||
|
||||
/* put delta image data surface */
|
||||
case 'D':
|
||||
var id = base64_16(cmd, i);
|
||||
i = i + 3;
|
||||
var x = base64_16(cmd, i);
|
||||
i = i + 3;
|
||||
var 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
|
||||
if (img.complete) {
|
||||
apply_delta(id, img, x, y);
|
||||
} else {
|
||||
cmd_obj.pos = i;
|
||||
img.onload = function() { apply_delta(id, img, x, y); handleOutstanding(); }
|
||||
return false
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
/* copy rects */
|
||||
case 'b':
|
||||
var id = base64_16(cmd, i);
|
||||
|
@ -87,7 +87,7 @@ diff_surfaces (cairo_surface_t *surface,
|
||||
cairo_surface_t *old_surface)
|
||||
{
|
||||
guint8 *data, *old_data;
|
||||
guint8 *line, *old_line;
|
||||
guint32 *line, *old_line;
|
||||
int w, h, stride, old_stride;
|
||||
int x, y;
|
||||
|
||||
@ -102,16 +102,17 @@ diff_surfaces (cairo_surface_t *surface,
|
||||
|
||||
for (y = 0; y < h; y++)
|
||||
{
|
||||
line = data;
|
||||
old_line = old_data;
|
||||
line = (guint32 *)data;
|
||||
old_line = (guint32 *)old_data;
|
||||
|
||||
for (x = 0; x < w; x++)
|
||||
{
|
||||
int j;
|
||||
for (j = 0; j < 4; j++)
|
||||
old_line[j] = line[j] - old_line[j];
|
||||
line += 4;
|
||||
old_line += 4;
|
||||
if ((*line & 0xffffff) == (*old_line & 0xffffff))
|
||||
*old_line = 0;
|
||||
else
|
||||
*old_line = *line | 0xff000000;
|
||||
line ++;
|
||||
old_line ++;
|
||||
}
|
||||
|
||||
data += stride;
|
||||
@ -127,15 +128,18 @@ window_data_send (BroadwayClient *client, GdkWindowImplBroadway *impl)
|
||||
GdkDrawableImplBroadway *drawable_impl = GDK_DRAWABLE_IMPL_BROADWAY (impl);
|
||||
cairo_t *cr;
|
||||
|
||||
if (drawable_impl->surface == NULL)
|
||||
return;
|
||||
|
||||
if (impl->last_synced)
|
||||
{
|
||||
diff_surfaces (drawable_impl->surface,
|
||||
drawable_impl->last_surface);
|
||||
broadway_client_put_delta_rgb (client, impl->id, 0, 0,
|
||||
cairo_image_surface_get_width (drawable_impl->last_surface),
|
||||
cairo_image_surface_get_height (drawable_impl->last_surface),
|
||||
cairo_image_surface_get_stride (drawable_impl->last_surface),
|
||||
cairo_image_surface_get_data (drawable_impl->last_surface));
|
||||
broadway_client_put_rgba (client, impl->id, 0, 0,
|
||||
cairo_image_surface_get_width (drawable_impl->last_surface),
|
||||
cairo_image_surface_get_height (drawable_impl->last_surface),
|
||||
cairo_image_surface_get_stride (drawable_impl->last_surface),
|
||||
cairo_image_surface_get_data (drawable_impl->last_surface));
|
||||
}
|
||||
else
|
||||
{
|
||||
|
Loading…
Reference in New Issue
Block a user