Implemented naiive update condensing for PNGs in the simplest case. Added queue tail. Now adding to tail of queue.
This commit is contained in:
parent
35fedc1eb6
commit
44a456aece
@ -164,6 +164,11 @@ struct guac_client {
|
|||||||
*/
|
*/
|
||||||
guac_layer* all_layers;
|
guac_layer* all_layers;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Pointer to a pre-allocated default layer (layer 0)
|
||||||
|
*/
|
||||||
|
guac_layer* default_layer;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The time (in milliseconds) of receipt of the last sync message from
|
* The time (in milliseconds) of receipt of the last sync message from
|
||||||
* the client.
|
* the client.
|
||||||
@ -373,6 +378,4 @@ guac_layer* guac_client_alloc_layer(guac_client* client, int index);
|
|||||||
*/
|
*/
|
||||||
void guac_client_free_buffer(guac_client* client, guac_layer* layer);
|
void guac_client_free_buffer(guac_client* client, guac_layer* layer);
|
||||||
|
|
||||||
extern const guac_layer* GUAC_DEFAULT_LAYER;
|
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
@ -245,6 +245,11 @@ struct guac_layer {
|
|||||||
*/
|
*/
|
||||||
guac_layer_update* update_queue_head;
|
guac_layer_update* update_queue_head;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The last element in this layer's update queue.
|
||||||
|
*/
|
||||||
|
guac_layer_update* update_queue_tail;
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -47,15 +47,6 @@
|
|||||||
#include "client.h"
|
#include "client.h"
|
||||||
#include "client-handlers.h"
|
#include "client-handlers.h"
|
||||||
|
|
||||||
guac_layer __GUAC_DEFAULT_LAYER = {
|
|
||||||
.index = 0,
|
|
||||||
.next = NULL,
|
|
||||||
.next_available = NULL
|
|
||||||
};
|
|
||||||
|
|
||||||
const guac_layer* GUAC_DEFAULT_LAYER = &__GUAC_DEFAULT_LAYER;
|
|
||||||
|
|
||||||
|
|
||||||
guac_client* __guac_alloc_client(GUACIO* io) {
|
guac_client* __guac_alloc_client(GUACIO* io) {
|
||||||
|
|
||||||
/* Allocate new client (not handoff) */
|
/* Allocate new client (not handoff) */
|
||||||
@ -72,6 +63,9 @@ guac_client* __guac_alloc_client(GUACIO* io) {
|
|||||||
|
|
||||||
client->next_buffer_index = -1;
|
client->next_buffer_index = -1;
|
||||||
|
|
||||||
|
/* Allocate default layer */
|
||||||
|
client->default_layer = guac_client_alloc_layer(client, 0);
|
||||||
|
|
||||||
return client;
|
return client;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -82,6 +76,7 @@ guac_layer* guac_client_alloc_layer(guac_client* client, int index) {
|
|||||||
/* Init new layer */
|
/* Init new layer */
|
||||||
allocd_layer = malloc(sizeof(guac_layer));
|
allocd_layer = malloc(sizeof(guac_layer));
|
||||||
allocd_layer->update_queue_head = NULL;
|
allocd_layer->update_queue_head = NULL;
|
||||||
|
allocd_layer->update_queue_tail = NULL;
|
||||||
|
|
||||||
/* Add to all_layers list */
|
/* Add to all_layers list */
|
||||||
allocd_layer->next = client->all_layers;
|
allocd_layer->next = client->all_layers;
|
||||||
@ -110,6 +105,7 @@ guac_layer* guac_client_alloc_buffer(guac_client* client) {
|
|||||||
allocd_layer = malloc(sizeof(guac_layer));
|
allocd_layer = malloc(sizeof(guac_layer));
|
||||||
allocd_layer->index = client->next_buffer_index--;
|
allocd_layer->index = client->next_buffer_index--;
|
||||||
allocd_layer->update_queue_head = NULL;
|
allocd_layer->update_queue_head = NULL;
|
||||||
|
allocd_layer->update_queue_tail = NULL;
|
||||||
|
|
||||||
/* Add to all_layers list */
|
/* Add to all_layers list */
|
||||||
allocd_layer->next = client->all_layers;
|
allocd_layer->next = client->all_layers;
|
||||||
@ -139,6 +135,9 @@ void guac_client_free_buffer(guac_client* client, guac_layer* layer) {
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Queue is now empty */
|
||||||
|
layer->update_queue_tail = NULL;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
guac_client* guac_get_client(int client_fd) {
|
guac_client* guac_get_client(int client_fd) {
|
||||||
|
@ -63,6 +63,9 @@
|
|||||||
#include "guacio.h"
|
#include "guacio.h"
|
||||||
#include "protocol.h"
|
#include "protocol.h"
|
||||||
|
|
||||||
|
#define MIN(a, b) (((a) < (b)) ? (a) : (b))
|
||||||
|
#define MAX(a, b) (((a) > (b)) ? (a) : (b))
|
||||||
|
|
||||||
ssize_t __guac_write_length_string(GUACIO* io, const char* str) {
|
ssize_t __guac_write_length_string(GUACIO* io, const char* str) {
|
||||||
|
|
||||||
return
|
return
|
||||||
@ -518,11 +521,17 @@ void guac_sleep(int millis) {
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void _guac_layer_add_update(guac_layer* layer, guac_layer_update* update) {
|
void __guac_layer_add_update(guac_layer* layer, guac_layer_update* update) {
|
||||||
|
|
||||||
/* Add update to queue head */
|
/* Add update to queue tail */
|
||||||
update->next = layer->update_queue_head;
|
if (layer->update_queue_tail != NULL)
|
||||||
layer->update_queue_head = update;
|
layer->update_queue_tail = layer->update_queue_tail->next = update;
|
||||||
|
|
||||||
|
/* Set both head and tail if necessary */
|
||||||
|
else
|
||||||
|
layer->update_queue_tail = layer->update_queue_head = update;
|
||||||
|
|
||||||
|
update->next = NULL;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -539,9 +548,11 @@ void guac_layer_png(guac_layer* layer, guac_composite_mode_t mode,
|
|||||||
update->dst_layer = layer;
|
update->dst_layer = layer;
|
||||||
update->dst_x = x;
|
update->dst_x = x;
|
||||||
update->dst_y = y;
|
update->dst_y = y;
|
||||||
|
update->width = cairo_image_surface_get_width(surface);
|
||||||
|
update->height = cairo_image_surface_get_height(surface);
|
||||||
|
|
||||||
/* Add to layer queue */
|
/* Add to layer queue */
|
||||||
_guac_layer_add_update(layer, update);
|
__guac_layer_add_update(layer, update);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -565,7 +576,7 @@ void guac_layer_copy(guac_layer* layer, guac_composite_mode_t mode,
|
|||||||
update->dst_y = dsty;
|
update->dst_y = dsty;
|
||||||
|
|
||||||
/* Add to layer queue */
|
/* Add to layer queue */
|
||||||
_guac_layer_add_update(layer, update);
|
__guac_layer_add_update(layer, update);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -583,7 +594,7 @@ void guac_layer_clip(guac_layer* layer,
|
|||||||
update->height = height;
|
update->height = height;
|
||||||
|
|
||||||
/* Add to layer queue */
|
/* Add to layer queue */
|
||||||
_guac_layer_add_update(layer, update);
|
__guac_layer_add_update(layer, update);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -607,7 +618,32 @@ void guac_layer_rect(guac_layer* layer, guac_composite_mode_t mode,
|
|||||||
update->height = height;
|
update->height = height;
|
||||||
|
|
||||||
/* Add to layer queue */
|
/* Add to layer queue */
|
||||||
_guac_layer_add_update(layer, update);
|
__guac_layer_add_update(layer, update);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
int __guac_layer_update_intersects(
|
||||||
|
const guac_layer_update* update1, const guac_layer_update* update2) {
|
||||||
|
|
||||||
|
/* If update1 X is within width of update2
|
||||||
|
or update2 X is within width of update1 */
|
||||||
|
if ((update1->dst_x >= update2->dst_x && update1->dst_x < update2->dst_x + update2->width)
|
||||||
|
|| (update2->dst_x >= update1->dst_x && update2->dst_x < update1->dst_x + update2->width)) {
|
||||||
|
|
||||||
|
/* If update1 Y is within height of update2
|
||||||
|
or update2 Y is within height of update1 */
|
||||||
|
if ((update1->dst_y >= update2->dst_y && update1->dst_y < update2->dst_y + update2->height)
|
||||||
|
|| (update2->dst_y >= update1->dst_y && update2->dst_y < update1->dst_y + update2->height)) {
|
||||||
|
|
||||||
|
/* Register instersection */
|
||||||
|
return 1;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Otherwise, no intersection */
|
||||||
|
return 0;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -615,6 +651,9 @@ int guac_layer_flush(guac_layer* layer, GUACIO* io) {
|
|||||||
|
|
||||||
while (layer->update_queue_head != NULL) {
|
while (layer->update_queue_head != NULL) {
|
||||||
|
|
||||||
|
guac_layer_update* later_update;
|
||||||
|
int update_merged = 0;
|
||||||
|
|
||||||
/* Get next update, update queue head. */
|
/* Get next update, update queue head. */
|
||||||
guac_layer_update* update = layer->update_queue_head;
|
guac_layer_update* update = layer->update_queue_head;
|
||||||
layer->update_queue_head = update->next;
|
layer->update_queue_head = update->next;
|
||||||
@ -625,16 +664,114 @@ int guac_layer_flush(guac_layer* layer, GUACIO* io) {
|
|||||||
/* "png" instruction */
|
/* "png" instruction */
|
||||||
case GUAC_LAYER_UPDATE_PNG:
|
case GUAC_LAYER_UPDATE_PNG:
|
||||||
|
|
||||||
if (guac_send_png(io,
|
/* Decide whether or not to send */
|
||||||
update->mode,
|
later_update = update->next;
|
||||||
update->dst_layer,
|
while (later_update != NULL) {
|
||||||
update->dst_x,
|
|
||||||
update->dst_y,
|
/* If destination rectangles intersect */
|
||||||
update->src_image
|
if (__guac_layer_update_intersects(update, later_update)) {
|
||||||
)) {
|
|
||||||
cairo_surface_destroy(update->src_image);
|
cairo_surface_t* merged_surface;
|
||||||
free(update);
|
cairo_t* cairo;
|
||||||
return -1;
|
int merged_x, merged_y, merged_width, merged_height;
|
||||||
|
|
||||||
|
/* Cannot combine anything if intersection with non-PNG */
|
||||||
|
if (later_update->type != GUAC_LAYER_UPDATE_PNG)
|
||||||
|
break;
|
||||||
|
|
||||||
|
/* Cannot combine if modes differ */
|
||||||
|
if (later_update->mode != update->mode)
|
||||||
|
break;
|
||||||
|
|
||||||
|
/* For now, only combine for GUAC_COMP_OVER */
|
||||||
|
if (later_update->mode != GUAC_COMP_OVER)
|
||||||
|
break;
|
||||||
|
|
||||||
|
/* Calculate merged dimensions */
|
||||||
|
merged_x = MIN(update->dst_x, later_update->dst_x);
|
||||||
|
merged_y = MIN(update->dst_y, later_update->dst_y);
|
||||||
|
|
||||||
|
merged_width = MAX(
|
||||||
|
update->dst_x + update->width,
|
||||||
|
later_update->dst_x + later_update->width
|
||||||
|
) - merged_x;
|
||||||
|
|
||||||
|
merged_height = MAX(
|
||||||
|
update->dst_y + update->height,
|
||||||
|
later_update->dst_y + later_update->height
|
||||||
|
) - merged_y;
|
||||||
|
|
||||||
|
/* Create surface for merging */
|
||||||
|
merged_surface = cairo_image_surface_create(
|
||||||
|
CAIRO_FORMAT_ARGB32, merged_width, merged_height);
|
||||||
|
|
||||||
|
/* Get drawing context */
|
||||||
|
cairo = cairo_create(merged_surface);
|
||||||
|
|
||||||
|
/* Draw first update within merged surface */
|
||||||
|
cairo_set_source_surface(cairo,
|
||||||
|
update->src_image,
|
||||||
|
update->dst_x - merged_x,
|
||||||
|
update->dst_y - merged_y);
|
||||||
|
|
||||||
|
cairo_rectangle(cairo,
|
||||||
|
update->dst_x - merged_x,
|
||||||
|
update->dst_y - merged_y,
|
||||||
|
update->width,
|
||||||
|
update->height);
|
||||||
|
|
||||||
|
cairo_fill(cairo);
|
||||||
|
|
||||||
|
/* Draw second update within merged surface */
|
||||||
|
cairo_set_source_surface(cairo,
|
||||||
|
later_update->src_image,
|
||||||
|
later_update->dst_x - merged_x,
|
||||||
|
later_update->dst_y - merged_y);
|
||||||
|
|
||||||
|
cairo_rectangle(cairo,
|
||||||
|
later_update->dst_x - merged_x,
|
||||||
|
later_update->dst_y - merged_y,
|
||||||
|
later_update->width,
|
||||||
|
later_update->height);
|
||||||
|
|
||||||
|
cairo_fill(cairo);
|
||||||
|
|
||||||
|
/* Done drawing */
|
||||||
|
cairo_destroy(cairo);
|
||||||
|
|
||||||
|
/* Alter update dimensions */
|
||||||
|
later_update->dst_x = merged_x;
|
||||||
|
later_update->dst_y = merged_y;
|
||||||
|
later_update->width = merged_width;
|
||||||
|
later_update->height = merged_height;
|
||||||
|
|
||||||
|
/* Alter update to include merged data*/
|
||||||
|
cairo_surface_destroy(later_update->src_image);
|
||||||
|
later_update->src_image = merged_surface;
|
||||||
|
|
||||||
|
update_merged = 1;
|
||||||
|
break;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Get next update */
|
||||||
|
later_update = later_update->next;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Send instruction if update was not merged */
|
||||||
|
if (!update_merged) {
|
||||||
|
if (guac_send_png(io,
|
||||||
|
update->mode,
|
||||||
|
update->dst_layer,
|
||||||
|
update->dst_x,
|
||||||
|
update->dst_y,
|
||||||
|
update->src_image
|
||||||
|
)) {
|
||||||
|
cairo_surface_destroy(update->src_image);
|
||||||
|
free(update);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
cairo_surface_destroy(update->src_image);
|
cairo_surface_destroy(update->src_image);
|
||||||
@ -704,6 +841,9 @@ int guac_layer_flush(guac_layer* layer, GUACIO* io) {
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Queue is now empty */
|
||||||
|
layer->update_queue_tail = NULL;
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
2408
libguac/test
Normal file
2408
libguac/test
Normal file
File diff suppressed because it is too large
Load Diff
Loading…
Reference in New Issue
Block a user