GUAC-675: Optimize copy.

This commit is contained in:
Michael Jumper 2014-05-12 02:01:09 -07:00
parent 573f524dee
commit 07f6712591

View File

@ -235,7 +235,9 @@ void guac_common_surface_flush_deferred(guac_common_surface* surface) {
* @param src The source of the uint32_t value. * @param src The source of the uint32_t value.
* @param dst THe destination which will hold the result of the transfer. * @param dst THe destination which will hold the result of the transfer.
*/ */
static void __guac_common_surface_transfer_int(guac_transfer_function op, uint32_t* src, uint32_t* dst) { static int __guac_common_surface_transfer_int(guac_transfer_function op, uint32_t* src, uint32_t* dst) {
uint32_t orig = *dst;
switch (op) { switch (op) {
@ -304,6 +306,9 @@ static void __guac_common_surface_transfer_int(guac_transfer_function op, uint32
break; break;
} }
return *dst != orig;
} }
/** /**
@ -542,6 +547,11 @@ static void __guac_common_surface_transfer(guac_common_surface* src, int sx, int
int src_stride, dst_stride; int src_stride, dst_stride;
int step = 1; int step = 1;
int min_x = rect->width - 1;
int min_y = rect->height - 1;
int max_x = 0;
int max_y = 0;
/* Copy forwards only if destination is in a different surface or is before source */ /* Copy forwards only if destination is in a different surface or is before source */
if (src != dst || rect->y < sy || (rect->y == sy && rect->x < sx)) { if (src != dst || rect->y < sy || (rect->y == sy && rect->x < sx)) {
src_buffer += src->stride*sy + 4*sx; src_buffer += src->stride*sy + 4*sx;
@ -568,7 +578,14 @@ static void __guac_common_surface_transfer(guac_common_surface* src, int sx, int
/* Transfer each pixel in row */ /* Transfer each pixel in row */
for (x=0; x < rect->width; x++) { for (x=0; x < rect->width; x++) {
__guac_common_surface_transfer_int(op, src_current, dst_current);
if (__guac_common_surface_transfer_int(op, src_current, dst_current)) {
if (x < min_x) min_x = x;
if (y < min_y) min_y = y;
if (x > max_x) max_x = x;
if (y > max_y) max_y = y;
}
src_current += step; src_current += step;
dst_current += step; dst_current += step;
} }
@ -579,6 +596,26 @@ static void __guac_common_surface_transfer(guac_common_surface* src, int sx, int
} }
/* Translate coordinate space of min_* and max_* if moving backwards */
if (step < 0) {
min_x = rect->width - 1 - min_x;
max_x = rect->width - 1 - max_x;
min_y = rect->height - 1 - min_y;
max_y = rect->height - 1 - max_y;
}
/* Restrict destination rect to only updated pixels */
if (max_x >= min_x && max_y >= min_y) {
rect->x += min_x;
rect->y += min_y;
rect->width = max_x - min_x + 1;
rect->height = max_y - min_y + 1;
}
else {
rect->width = 0;
rect->height = 0;
}
} }
guac_common_surface* guac_common_surface_alloc(guac_socket* socket, const guac_layer* layer, int w, int h) { guac_common_surface* guac_common_surface_alloc(guac_socket* socket, const guac_layer* layer, int w, int h) {
@ -756,6 +793,8 @@ void guac_common_surface_copy(guac_common_surface* src, int sx, int sy, int w, i
/* Update backing surface */ /* Update backing surface */
__guac_common_surface_transfer(src, sx, sy, GUAC_TRANSFER_BINARY_SRC, dst, &rect); __guac_common_surface_transfer(src, sx, sy, GUAC_TRANSFER_BINARY_SRC, dst, &rect);
if (rect.width <= 0 || rect.height <= 0)
return;
/* Defer if combining */ /* Defer if combining */
if (__guac_common_should_combine(dst, &rect, 1)) if (__guac_common_should_combine(dst, &rect, 1))
@ -789,6 +828,8 @@ void guac_common_surface_transfer(guac_common_surface* src, int sx, int sy, int
/* Update backing surface */ /* Update backing surface */
__guac_common_surface_transfer(src, sx, sy, op, dst, &rect); __guac_common_surface_transfer(src, sx, sy, op, dst, &rect);
if (rect.width <= 0 || rect.height <= 0)
return;
/* Defer if combining */ /* Defer if combining */
if (__guac_common_should_combine(dst, &rect, 1)) if (__guac_common_should_combine(dst, &rect, 1))