[byzanz] Replace GDK rendering with Cairo
- From: Benjamin Otte <otte src gnome org>
- To: svn-commits-list gnome org
- Cc:
- Subject: [byzanz] Replace GDK rendering with Cairo
- Date: Sat, 15 Aug 2009 22:12:11 +0000 (UTC)
commit 5cfedc0ed00ac5c60d337e2f753a86ca5bf5bcef
Author: Benjamin Otte <otte gnome org>
Date: Sat Aug 15 22:26:34 2009 +0200
Replace GDK rendering with Cairo
src/byzanzrecorder.c | 165 +++++++++++++++++++------------------------------
1 files changed, 64 insertions(+), 101 deletions(-)
---
diff --git a/src/byzanzrecorder.c b/src/byzanzrecorder.c
index 146e758..fa7c5d5 100644
--- a/src/byzanzrecorder.c
+++ b/src/byzanzrecorder.c
@@ -1,5 +1,5 @@
/* desktop session recorder
- * Copyright (C) 2005 Benjamin Otte <otte gnome org
+ * Copyright (C) 2005,2009 Benjamin Otte <otte gnome org>
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Library General Public
@@ -27,6 +27,7 @@
#include <sys/stat.h>
#include <unistd.h>
#include <fcntl.h>
+#include <cairo.h>
#include <glib/gstdio.h>
#include <gtk/gtk.h>
#include <gdk/gdkx.h>
@@ -59,19 +60,18 @@ typedef enum {
RECORDER_JOB_USE_FILE_CACHE,
} RecorderJobType;
-typedef gboolean (* DiterRegionGetDataFunc) (ByzanzRecorder *rec,
+typedef gboolean (* DitherRegionGetDataFunc) (ByzanzRecorder *rec,
gpointer data, GdkRectangle *rect,
- gpointer *data_out, guint *bpp_out, guint *bpl_out);
+ gpointer *data_out, guint *bpl_out);
typedef struct {
RecorderJobType type; /* type of job */
GTimeVal tv; /* time this job was enqueued */
- GdkImage * image; /* image to process */
+ cairo_surface_t * image; /* image to process */
GdkRegion * region; /* relevant region of image */
} RecorderJob;
typedef struct {
- int bpp; /* bpp for image data */
GdkRegion * region; /* the region this image represents */
GTimeVal tv; /* timestamp of image */
int fd; /* file the image is stored in */
@@ -133,10 +133,20 @@ static int fixes_error_base = 0;
/*** JOB FUNCTIONS ***/
+static void
+byzanz_cairo_set_source_window (cairo_t *cr, GdkWindow *window, double x, double y)
+{
+ cairo_t *tmp;
+
+ tmp = gdk_cairo_create (window);
+ cairo_set_source_surface (cr, cairo_get_target (tmp), x, y);
+ cairo_destroy (tmp);
+}
+
static guint
-compute_image_size (GdkImage *image)
+compute_image_size (cairo_surface_t *image)
{
- return image->bpl * image->height;
+ return cairo_image_surface_get_stride (image) * cairo_image_surface_get_height (image);
}
static void
@@ -144,7 +154,7 @@ recorder_job_free (ByzanzRecorder *rec, RecorderJob *job)
{
if (job->image) {
rec->cache_size -= compute_image_size (job->image);
- g_object_unref (job->image);
+ cairo_surface_destroy (job->image);
}
if (job->region)
gdk_region_destroy (job->region);
@@ -177,12 +187,10 @@ recorder_job_new (ByzanzRecorder *rec, RecorderJobType type,
job->type = type;
job->region = region;
if (region != NULL) {
- GdkRectangle *rects;
- gint nrects, i;
+ cairo_t *cr;
if (!job->image) {
if (rec->cache_size <= rec->max_cache_size) {
- job->image = gdk_image_new (GDK_IMAGE_FASTEST,
- gdk_drawable_get_visual (rec->window),
+ job->image = cairo_image_surface_create (CAIRO_FORMAT_RGB24,
rec->area.width, rec->area.height);
rec->cache_size += compute_image_size (job->image);
if (!rec->use_file_cache &&
@@ -209,20 +217,16 @@ recorder_job_new (ByzanzRecorder *rec, RecorderJobType type,
return NULL;
}
}
- gdk_region_get_rectangles (region, &rects, &nrects);
if (type == RECORDER_JOB_ENCODE) {
Display *dpy = gdk_x11_drawable_get_xdisplay (rec->window);
XDamageSubtract (dpy, rec->damage, rec->damaged, rec->damaged);
XFixesSubtractRegion (dpy, rec->damaged, rec->damaged, rec->damaged);
}
- for (i = 0; i < nrects; i++) {
- //g_print ("%d %d %d %d\n", rects[i].x, rects[i].y, rects[i].width, rects[i].height);
- gdk_drawable_copy_to_image (rec->window, job->image,
- rects[i].x, rects[i].y,
- rects[i].x - rec->area.x, rects[i].y - rec->area.y,
- rects[i].width, rects[i].height);
- }
- //g_print ("done\n");
+ cr = cairo_create (job->image);
+ byzanz_cairo_set_source_window (cr, rec->window, rec->area.x, rec->area.y);
+ gdk_cairo_region (cr, region);
+ cairo_paint (cr);
+ cairo_destroy (cr);
gdk_region_offset (region, -rec->area.x, -rec->area.y);
}
return job;
@@ -232,13 +236,13 @@ recorder_job_new (ByzanzRecorder *rec, RecorderJobType type,
static gboolean
byzanz_recorder_dither_region (ByzanzRecorder *rec, GdkRegion *region,
- DiterRegionGetDataFunc func, gpointer data)
+ DitherRegionGetDataFunc func, gpointer data)
{
GdkRectangle *rects;
GdkRegion *rev;
int i, line, nrects;
guint8 transparent;
- guint bpp, bpl;
+ guint bpl;
gpointer mem;
GdkRectangle area;
@@ -248,12 +252,12 @@ byzanz_recorder_dither_region (ByzanzRecorder *rec, GdkRegion *region,
gdk_region_get_rectangles (region, &rects, &nrects);
rev = gdk_region_new ();
for (i = 0; i < nrects; i++) {
- if (!(*func) (rec, data, rects + i, &mem, &bpp, &bpl))
+ if (!(*func) (rec, data, rects + i, &mem, &bpl))
return FALSE;
if (gifenc_dither_rgb_with_full_image (
rec->data + rec->area.width * rects[i].y + rects[i].x, rec->area.width,
rec->data_full + rec->area.width * rects[i].y + rects[i].x, rec->area.width,
- rec->gifenc->palette, mem, rects[i].width, rects[i].height, bpp, bpl, &area)) {
+ rec->gifenc->palette, mem, rects[i].width, rects[i].height, 4, bpl, &area)) {
area.x += rects[i].x;
area.y += rects[i].y;
gdk_region_union_with_rect (rev, &area);
@@ -322,7 +326,7 @@ stored_image_remove_file (ByzanzRecorder *rec, int fd, char *filename)
/* returns FALSE if no more images can be cached */
static gboolean
-stored_image_store (ByzanzRecorder *rec, GdkImage *image, GdkRegion *region, const GTimeVal *tv)
+stored_image_store (ByzanzRecorder *rec, cairo_surface_t *image, GdkRegion *region, const GTimeVal *tv)
{
off_t offset;
StoredImage *store;
@@ -330,6 +334,8 @@ stored_image_store (ByzanzRecorder *rec, GdkImage *image, GdkRegion *region, con
gint i, line, nrects;
gboolean ret = FALSE;
guint cache, val;
+ guint stride;
+ guchar *data;
val = g_atomic_int_get (&rec->max_file_cache);
cache = g_atomic_int_get (&rec->cur_file_cache);
@@ -349,25 +355,25 @@ stored_image_store (ByzanzRecorder *rec, GdkImage *image, GdkRegion *region, con
offset = lseek (rec->cur_cache_fd, 0, SEEK_END);
}
store = g_new (StoredImage, 1);
- store->bpp = image->bpp;
store->region = region;
store->tv = *tv;
store->fd = rec->cur_cache_fd;
store->filename = NULL;
store->offset = offset;
gdk_region_get_rectangles (store->region, &rects, &nrects);
+ stride = cairo_image_surface_get_stride (image);
+ data = cairo_image_surface_get_data (image);
for (i = 0; i < nrects; i++) {
guchar *mem;
- mem = (guchar *) image->mem + rects[i].x * image->bpp + image->bpl * rects[i].y
- + (image->bpp == 4 && image->byte_order == GDK_MSB_FIRST ? 1 : 0);
+ mem = data + rects[i].x * 4 + rects[i].y * stride;
for (line = 0; line < rects[i].height; line++) {
- int amount = rects[i].width * image->bpp;
+ int amount = rects[i].width * 4;
/* This can be made smarter, like retrying and catching EINTR and stuff */
if (write (store->fd, mem, amount) != amount) {
g_print ("couldn't write %d bytes\n", amount);
goto out_err;
}
- mem += image->bpl;
+ mem += stride;
}
}
@@ -397,10 +403,10 @@ out_err:
static gboolean
stored_image_dither_get_data (ByzanzRecorder *rec, gpointer data, GdkRectangle *rect,
- gpointer *data_out, guint *bpp_out, guint *bpl_out)
+ gpointer *data_out, guint *bpl_out)
{
StoredImage *store = data;
- guint required_size = rect->width * rect->height * store->bpp;
+ guint required_size = rect->width * rect->height * 4;
guint8 *ptr;
if (required_size > rec->file_cache_data_size) {
@@ -416,8 +422,7 @@ stored_image_dither_get_data (ByzanzRecorder *rec, gpointer data, GdkRectangle *
ptr += ret;
required_size -= ret;
}
- *bpp_out = store->bpp;
- *bpl_out = store->bpp * rect->width;
+ *bpl_out = 4 * rect->width;
*data_out = rec->file_cache_data;
return TRUE;
}
@@ -449,15 +454,13 @@ stored_image_process (ByzanzRecorder *rec)
}
static void
-byzanz_recorder_quantize (ByzanzRecorder *rec, GdkImage *image)
+byzanz_recorder_quantize (ByzanzRecorder *rec, cairo_surface_t *image)
{
GifencPalette *palette;
- palette = gifenc_quantize_image (
- (guchar *) image->mem + (image->bpp == 4 && image->byte_order == GDK_MSB_FIRST ? 1 : 0),
- rec->area.width, rec->area.height, image->bpp, image->bpl, TRUE,
- (image->byte_order == GDK_MSB_FIRST) ? G_BIG_ENDIAN : G_LITTLE_ENDIAN,
- 255);
+ palette = gifenc_quantize_image (cairo_image_surface_get_data (image),
+ rec->area.width, rec->area.height, 4, cairo_image_surface_get_stride (image), TRUE,
+ G_BYTE_ORDER, 255);
gifenc_set_palette (rec->gifenc, palette);
if (rec->loop)
@@ -466,22 +469,21 @@ byzanz_recorder_quantize (ByzanzRecorder *rec, GdkImage *image)
static gboolean
byzanz_recorder_encode_get_data (ByzanzRecorder *rec, gpointer data, GdkRectangle *rect,
- gpointer *data_out, guint *bpp_out, guint *bpl_out)
+ gpointer *data_out, guint *bpl_out)
{
- GdkImage *image = data;
+ cairo_surface_t *image = data;
- *data_out = (guchar *) image->mem + rect->y * image->bpl + rect->x * image->bpp +
- (image->bpp == 4 && image->byte_order == GDK_MSB_FIRST ? 1 : 0);
- *bpp_out = image->bpp;
- *bpl_out = image->bpl;
+ *data_out = cairo_image_surface_get_data (image)
+ + rect->y * cairo_image_surface_get_stride (image)
+ + rect->x * 4;
+ *bpl_out = cairo_image_surface_get_stride (image);
return TRUE;
}
static void
-byzanz_recorder_encode (ByzanzRecorder *rec, GdkImage *image, GdkRegion *region)
+byzanz_recorder_encode (ByzanzRecorder *rec, cairo_surface_t *image, GdkRegion *region)
{
g_assert (!gdk_region_empty (region));
- g_return_if_fail (image->bpp == 3 || image->bpp == 4);
byzanz_recorder_dither_region (rec, region, byzanz_recorder_encode_get_data,
image);
@@ -586,60 +588,21 @@ loop:
/*** MAIN FUNCTIONS ***/
static void
-render_cursor_to_image (GdkImage *image, XFixesCursorImage *cursor, gint x, gint y)
+render_cursor_to_image (cairo_surface_t *image, XFixesCursorImage *cursor, gint x, gint y)
{
- GdkRectangle rect;
- gint i, j, cursor_x, cursor_y, cursor_rowstride;
- guint8 *cursor_data, *cursor_row, *image_data, *image_row;
-#if G_BYTE_ORDER == G_BIG_ENDIAN
-# define alpha -1
-#elif G_BYTE_ORDER == G_LITTLE_ENDIAN
-# define alpha 3
-#else
-# error "Unknown glib byte order."
-#endif
+ cairo_surface_t *cursor_surface;
+ cairo_t *cr;
- rect.x = x - cursor->xhot;
- rect.width = MIN (cursor->width + MIN (0, rect.x), image->width - rect.x);
- cursor_x = MAX (0, -rect.x);
- rect.x = MAX (rect.x, 0);
-
- rect.y = y - cursor->yhot;
- rect.height = MIN (cursor->height + MIN (0, rect.y), image->height - rect.y);
- cursor_y = MAX (0, -rect.y);
- rect.y = MAX (rect.y, 0);
-
- cursor_rowstride = cursor->width * 4;
- cursor_data = ((guint8 *) cursor->pixels) + 4 * cursor_x +
- cursor_rowstride * cursor_y
-#if G_BYTE_ORDER == G_BIG_ENDIAN
- + 1
-#endif
- ;
- image_data = (guchar *) image->mem + rect.x * image->bpp + image->bpl * rect.y
- + (image->bpp == 4 && image->byte_order == GDK_MSB_FIRST ? 1 : 0);
- for (i = 0; i < rect.height; i++) {
- cursor_row = cursor_data;
- image_row = image_data;
- for (j = 0; j < rect.width; j++) {
- guint8 a = 255 - cursor_row[alpha];
- if ((image->byte_order == GDK_MSB_FIRST && G_BYTE_ORDER == G_BIG_ENDIAN) ||
- (image->byte_order == GDK_LSB_FIRST && G_BYTE_ORDER == G_LITTLE_ENDIAN)) {
- image_row[0] = image_row[0] * a / 255 + cursor_row[0];
- image_row[1] = image_row[1] * a / 255 + cursor_row[1];
- image_row[2] = image_row[2] * a / 255 + cursor_row[2];
- } else {
- image_row[0] = image_row[0] * a / 255 + cursor_row[2];
- image_row[1] = image_row[1] * a / 255 + cursor_row[1];
- image_row[2] = image_row[2] * a / 255 + cursor_row[0];
- }
- cursor_row += 4;
- image_row += image->bpp;
- }
- cursor_data += cursor_rowstride;
- image_data += image->bpl;
- }
-#undef alpha_index
+ cursor_surface = cairo_image_surface_create_for_data ((guchar *) cursor->pixels,
+ CAIRO_FORMAT_ARGB32, cursor->width, cursor->height, cursor->width * 4);
+ cr = cairo_create (image);
+
+ cairo_translate (cr, x, y);
+ cairo_set_source_surface (cr, cursor_surface, -(double) cursor->xhot, -(double) cursor->yhot);
+ cairo_paint (cr);
+
+ cairo_destroy (cr);
+ cairo_surface_destroy (cursor_surface);
}
static guint
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]