GUAC-667: Remove unnecessary use of Cairo surface within common - just update buffer.
This commit is contained in:
parent
dbec5a5957
commit
b2d74c92a2
@ -62,6 +62,11 @@
|
|||||||
*/
|
*/
|
||||||
#define GUAC_SURFACE_NEGLIGIBLE_INCREASE 4
|
#define GUAC_SURFACE_NEGLIGIBLE_INCREASE 4
|
||||||
|
|
||||||
|
/* Define cairo_format_stride_for_width() if missing */
|
||||||
|
#ifndef HAVE_CAIRO_FORMAT_STRIDE_FOR_WIDTH
|
||||||
|
#define cairo_format_stride_for_width(format, width) (width*4)
|
||||||
|
#endif
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns whether the given rectangle should be combined into the existing
|
* Returns whether the given rectangle should be combined into the existing
|
||||||
* dirty rectangle, to be eventually flushed as a "png" instruction.
|
* dirty rectangle, to be eventually flushed as a "png" instruction.
|
||||||
@ -249,6 +254,71 @@ static void __guac_common_surface_transfer_int(guac_transfer_function op, uint32
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void __guac_common_surface_rect(guac_common_surface* dst, int dx, int dy, int w, int h,
|
||||||
|
int red, int green, int blue) {
|
||||||
|
|
||||||
|
int dst_stride = dst->stride;
|
||||||
|
unsigned char* dst_buffer = dst->buffer + dst_stride*dy + 4*dx;
|
||||||
|
|
||||||
|
int x, y;
|
||||||
|
|
||||||
|
uint32_t color = 0xFF000000 | (red << 16) | (green << 8) | blue;
|
||||||
|
|
||||||
|
/* For each row */
|
||||||
|
for (y=0; y<h; y++) {
|
||||||
|
|
||||||
|
uint32_t* dst_current = (uint32_t*) dst_buffer;
|
||||||
|
|
||||||
|
/* Set row */
|
||||||
|
for (x=0; x<w; x++) {
|
||||||
|
*dst_current = color;
|
||||||
|
dst_current++;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Next row */
|
||||||
|
dst_buffer += dst_stride;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
static void __guac_common_surface_put(unsigned char* src_buffer, int src_stride,
|
||||||
|
int sx, int sy, int w, int h,
|
||||||
|
guac_common_surface* dst, int dx, int dy,
|
||||||
|
int opaque) {
|
||||||
|
|
||||||
|
unsigned char* dst_buffer = dst->buffer;
|
||||||
|
int dst_stride = dst->stride;
|
||||||
|
|
||||||
|
int x, y;
|
||||||
|
|
||||||
|
src_buffer += src_stride*sy + 4*sx;
|
||||||
|
dst_buffer += dst_stride*dy + 4*dx;
|
||||||
|
|
||||||
|
/* For each row */
|
||||||
|
for (y=0; y<h; y++) {
|
||||||
|
|
||||||
|
uint32_t* src_current = (uint32_t*) src_buffer;
|
||||||
|
uint32_t* dst_current = (uint32_t*) dst_buffer;
|
||||||
|
|
||||||
|
/* Copy row */
|
||||||
|
for (x=0; x<w; x++) {
|
||||||
|
|
||||||
|
if (opaque || (*src_current & 0xFF000000))
|
||||||
|
*dst_current = *src_current;
|
||||||
|
|
||||||
|
src_current++;
|
||||||
|
dst_current++;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Next row */
|
||||||
|
src_buffer += src_stride;
|
||||||
|
dst_buffer += dst_stride;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
static void __guac_common_surface_transfer(guac_common_surface* src, int sx, int sy, int w, int h,
|
static void __guac_common_surface_transfer(guac_common_surface* src, int sx, int sy, int w, int h,
|
||||||
guac_transfer_function op, guac_common_surface* dst, int dx, int dy) {
|
guac_transfer_function op, guac_common_surface* dst, int dx, int dy) {
|
||||||
|
|
||||||
@ -311,13 +381,9 @@ guac_common_surface* guac_common_surface_alloc(guac_socket* socket, const guac_l
|
|||||||
/* Create corresponding Cairo surface */
|
/* Create corresponding Cairo surface */
|
||||||
surface->stride = cairo_format_stride_for_width(CAIRO_FORMAT_RGB24, w);
|
surface->stride = cairo_format_stride_for_width(CAIRO_FORMAT_RGB24, w);
|
||||||
surface->buffer = malloc(surface->stride * h);
|
surface->buffer = malloc(surface->stride * h);
|
||||||
surface->surface = cairo_image_surface_create_for_data(surface->buffer, CAIRO_FORMAT_RGB24,
|
|
||||||
w, h, surface->stride);
|
|
||||||
surface->cairo = cairo_create(surface->surface);
|
|
||||||
|
|
||||||
/* Init with black */
|
/* Init with black */
|
||||||
cairo_set_source_rgb(surface->cairo, 0, 0, 0);
|
__guac_common_surface_rect(surface, 0, 0, w, h, 0x00, 0x00, 0x00);
|
||||||
cairo_paint(surface->cairo);
|
|
||||||
|
|
||||||
/* Layers must initially exist */
|
/* Layers must initially exist */
|
||||||
if (layer->index >= 0) {
|
if (layer->index >= 0) {
|
||||||
@ -338,8 +404,6 @@ void guac_common_surface_free(guac_common_surface* surface) {
|
|||||||
if (surface->realized)
|
if (surface->realized)
|
||||||
guac_protocol_send_dispose(surface->socket, surface->layer);
|
guac_protocol_send_dispose(surface->socket, surface->layer);
|
||||||
|
|
||||||
cairo_surface_destroy(surface->surface);
|
|
||||||
cairo_destroy(surface->cairo);
|
|
||||||
free(surface->buffer);
|
free(surface->buffer);
|
||||||
free(surface);
|
free(surface);
|
||||||
|
|
||||||
@ -350,31 +414,28 @@ void guac_common_surface_resize(guac_common_surface* surface, int w, int h) {
|
|||||||
guac_socket* socket = surface->socket;
|
guac_socket* socket = surface->socket;
|
||||||
const guac_layer* layer = surface->layer;
|
const guac_layer* layer = surface->layer;
|
||||||
|
|
||||||
|
/* Copy old surface data */
|
||||||
|
unsigned char* old_buffer = surface->buffer;
|
||||||
|
int old_stride = surface->stride;
|
||||||
|
int old_width = surface->width;
|
||||||
|
int old_height = surface->height;
|
||||||
|
|
||||||
/* Create new buffer */
|
/* Create new buffer */
|
||||||
int stride = cairo_format_stride_for_width(CAIRO_FORMAT_RGB24, w);
|
int stride = cairo_format_stride_for_width(CAIRO_FORMAT_RGB24, w);
|
||||||
unsigned char* buffer = malloc(stride * h);
|
unsigned char* buffer = malloc(stride * h);
|
||||||
|
|
||||||
/* Create corresponding cairo objects */
|
|
||||||
cairo_surface_t* cairo_surface = cairo_image_surface_create_for_data(buffer, CAIRO_FORMAT_RGB24, w, h, stride);
|
|
||||||
cairo_t* cairo = cairo_create(cairo_surface);
|
|
||||||
|
|
||||||
/* Init with old data */
|
|
||||||
cairo_set_source_surface(cairo, surface->surface, 0, 0);
|
|
||||||
cairo_rectangle(cairo, 0, 0, surface->width, surface->height);
|
|
||||||
cairo_paint(cairo);
|
|
||||||
|
|
||||||
/* Destroy old data */
|
|
||||||
cairo_surface_destroy(surface->surface);
|
|
||||||
cairo_destroy(surface->cairo);
|
|
||||||
free(surface->buffer);
|
|
||||||
|
|
||||||
/* Assign new data */
|
/* Assign new data */
|
||||||
surface->width = w;
|
surface->width = w;
|
||||||
surface->height = h;
|
surface->height = h;
|
||||||
surface->stride = stride;
|
surface->stride = stride;
|
||||||
surface->buffer = buffer;
|
surface->buffer = buffer;
|
||||||
surface->surface = cairo_surface;
|
|
||||||
surface->cairo = cairo;
|
/* Init with old data */
|
||||||
|
__guac_common_surface_put(old_buffer, old_stride, 0, 0, old_width, old_height,
|
||||||
|
surface, 0, 0, 1);
|
||||||
|
|
||||||
|
/* Free old data */
|
||||||
|
free(old_buffer);
|
||||||
|
|
||||||
/* Clip dirty rect */
|
/* Clip dirty rect */
|
||||||
if (surface->dirty) {
|
if (surface->dirty) {
|
||||||
@ -403,13 +464,16 @@ void guac_common_surface_resize(guac_common_surface* surface, int w, int h) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* Update Guacamole layer */
|
/* Update Guacamole layer */
|
||||||
|
if (surface->realized)
|
||||||
guac_protocol_send_size(socket, layer, w, h);
|
guac_protocol_send_size(socket, layer, w, h);
|
||||||
surface->realized = 1;
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void guac_common_surface_draw(guac_common_surface* surface, int x, int y, cairo_surface_t* src) {
|
void guac_common_surface_draw(guac_common_surface* surface, int x, int y, cairo_surface_t* src) {
|
||||||
|
|
||||||
|
unsigned char* buffer = cairo_image_surface_get_data(src);
|
||||||
|
cairo_format_t format = cairo_image_surface_get_format(src);
|
||||||
|
int stride = cairo_image_surface_get_stride(src);
|
||||||
int w = cairo_image_surface_get_width(src);
|
int w = cairo_image_surface_get_width(src);
|
||||||
int h = cairo_image_surface_get_height(src);
|
int h = cairo_image_surface_get_height(src);
|
||||||
|
|
||||||
@ -421,11 +485,7 @@ void guac_common_surface_draw(guac_common_surface* surface, int x, int y, cairo_
|
|||||||
__guac_common_mark_dirty(surface, x, y, w, h);
|
__guac_common_mark_dirty(surface, x, y, w, h);
|
||||||
|
|
||||||
/* Update backing surface */
|
/* Update backing surface */
|
||||||
cairo_save(surface->cairo);
|
__guac_common_surface_put(buffer, stride, 0, 0, w, h, surface, x, y, format != CAIRO_FORMAT_ARGB32);
|
||||||
cairo_set_source_surface(surface->cairo, src, x, y);
|
|
||||||
cairo_rectangle(surface->cairo, x, y, w, h);
|
|
||||||
cairo_fill(surface->cairo);
|
|
||||||
cairo_restore(surface->cairo);
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -449,8 +509,6 @@ void guac_common_surface_copy(guac_common_surface* src, int sx, int sy, int w, i
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* Update backing surface */
|
/* Update backing surface */
|
||||||
cairo_surface_flush(src->surface);
|
|
||||||
cairo_surface_flush(dst->surface);
|
|
||||||
__guac_common_surface_transfer(src, sx, sy, w, h, GUAC_TRANSFER_BINARY_SRC, dst, dx, dy);
|
__guac_common_surface_transfer(src, sx, sy, w, h, GUAC_TRANSFER_BINARY_SRC, dst, dx, dy);
|
||||||
|
|
||||||
}
|
}
|
||||||
@ -475,8 +533,6 @@ void guac_common_surface_transfer(guac_common_surface* src, int sx, int sy, int
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* Update backing surface */
|
/* Update backing surface */
|
||||||
cairo_surface_flush(src->surface);
|
|
||||||
cairo_surface_flush(dst->surface);
|
|
||||||
__guac_common_surface_transfer(src, sx, sy, w, h, op, dst, dx, dy);
|
__guac_common_surface_transfer(src, sx, sy, w, h, op, dst, dx, dy);
|
||||||
|
|
||||||
}
|
}
|
||||||
@ -501,11 +557,7 @@ void guac_common_surface_rect(guac_common_surface* surface,
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* Update backing surface */
|
/* Update backing surface */
|
||||||
cairo_save(surface->cairo);
|
__guac_common_surface_rect(surface, x, y, w, h, red, green, blue);
|
||||||
cairo_set_source_rgb(surface->cairo, red, green, blue);
|
|
||||||
cairo_rectangle(surface->cairo, x, y, w, h);
|
|
||||||
cairo_fill(surface->cairo);
|
|
||||||
cairo_restore(surface->cairo);
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -515,12 +567,13 @@ void guac_common_surface_flush(guac_common_surface* surface) {
|
|||||||
|
|
||||||
guac_socket* socket = surface->socket;
|
guac_socket* socket = surface->socket;
|
||||||
const guac_layer* layer = surface->layer;
|
const guac_layer* layer = surface->layer;
|
||||||
cairo_surface_t* rect;
|
unsigned char* buffer = surface->buffer + surface->dirty_y * surface->stride + surface->dirty_x * 4;
|
||||||
|
|
||||||
|
cairo_surface_t* rect = cairo_image_surface_create_for_data(buffer, CAIRO_FORMAT_RGB24,
|
||||||
|
surface->dirty_width, surface->dirty_height,
|
||||||
|
surface->stride);
|
||||||
|
|
||||||
/* Send PNG for dirty rect */
|
/* Send PNG for dirty rect */
|
||||||
rect = cairo_surface_create_for_rectangle(surface->surface,
|
|
||||||
surface->dirty_x, surface->dirty_y,
|
|
||||||
surface->dirty_width, surface->dirty_height);
|
|
||||||
guac_protocol_send_png(socket, GUAC_COMP_OVER, layer, surface->dirty_x, surface->dirty_y, rect);
|
guac_protocol_send_png(socket, GUAC_COMP_OVER, layer, surface->dirty_x, surface->dirty_y, rect);
|
||||||
cairo_surface_destroy(rect);
|
cairo_surface_destroy(rect);
|
||||||
|
|
||||||
|
@ -66,17 +66,6 @@ typedef struct guac_common_surface {
|
|||||||
*/
|
*/
|
||||||
unsigned char* buffer;
|
unsigned char* buffer;
|
||||||
|
|
||||||
/**
|
|
||||||
* The Cairo surface containing this Guacamole surface's current
|
|
||||||
* graphical state.
|
|
||||||
*/
|
|
||||||
cairo_surface_t* surface;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Cairo object for the underlying surface.
|
|
||||||
*/
|
|
||||||
cairo_t* cairo;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Non-zero if this surface is dirty and needs to be flushed, 0 otherwise.
|
* Non-zero if this surface is dirty and needs to be flushed, 0 otherwise.
|
||||||
*/
|
*/
|
||||||
|
Loading…
Reference in New Issue
Block a user