Signed-off-by: Tiago Vignatti <tiago.vigna...@nokia.com> --- This patch is a WIP to remove gdk-pixbuf dependency and use libpng instead. It is unfinished though and only compositor with simple-client works.
In principle, gdk-pixbuf is a bit bloated and brings a big package dependency in some platforms which makes harder to try Wayland. On the other hand, gdk-pixbuf has several modules to convert a bunch of image formats in pixel data, whereas libpng has only one, obviously. This is the drawback on using lipng. However, I guess compositor and clients could live happy with libpng only given they are made for demonstration purposes (well, at least at the moment). I won't be playing with this on the next days, but I'd love to help anyone with this work in the case I got a positive feedback here. Then, the short TODO on my mind: - fix command line parsing in compositor.c - apply analogue changes for other clients and screenshooter Thanks! Tiago clients/dnd.c | 2 + clients/image.c | 6 +++ clients/window.c | 6 +++ compositor/compositor.c | 92 +++++++++++++++++++++++++++++++++----------- compositor/screenshooter.c | 8 ++++ configure.ac | 4 +- 6 files changed, 93 insertions(+), 25 deletions(-) diff --git a/clients/dnd.c b/clients/dnd.c index 1625ffd..48d8dc0 100644 --- a/clients/dnd.c +++ b/clients/dnd.c @@ -30,7 +30,9 @@ #include <sys/time.h> #include <cairo.h> #include <glib.h> +#ifdef GDK_STUFF #include <gdk-pixbuf/gdk-pixbuf.h> +#endif #include "wayland-client.h" #include "wayland-glib.h" diff --git a/clients/image.c b/clients/image.c index 3eada1e..ca144e4 100644 --- a/clients/image.c +++ b/clients/image.c @@ -31,7 +31,9 @@ #include <time.h> #include <cairo.h> #include <glib.h> +#ifdef GDK_STUFF #include <gdk-pixbuf/gdk-pixbuf.h> +#endif #include "wayland-client.h" #include "wayland-glib.h" @@ -45,6 +47,7 @@ struct image { gchar *filename; }; +#ifdef GDK_STUFF static void set_source_pixbuf(cairo_t *cr, const GdkPixbuf *pixbuf, @@ -133,10 +136,12 @@ set_source_pixbuf(cairo_t *cr, src_y + .5 * (src_height - height)); cairo_surface_destroy(surface); } +#endif static void image_draw(struct image *image) { +#ifdef GDK_STUFF struct rectangle allocation; GdkPixbuf *pb; cairo_t *cr; @@ -179,6 +184,7 @@ image_draw(struct image *image) window_flush(image->window); cairo_surface_destroy(surface); +#endif } static void diff --git a/clients/window.c b/clients/window.c index b802518..9fa523e 100644 --- a/clients/window.c +++ b/clients/window.c @@ -33,7 +33,9 @@ #include <cairo.h> #include <glib.h> #include <glib-object.h> +#ifdef GDK_STUFF #include <gdk-pixbuf/gdk-pixbuf.h> +#endif #include <sys/mman.h> #define EGL_EGLEXT_PROTOTYPES 1 @@ -281,6 +283,7 @@ display_create_egl_image_surface_from_file(struct display *display, const char *filename, struct rectangle *rect) { +#ifdef GDK_STUFF cairo_surface_t *surface; GdkPixbuf *pixbuf; GError *error = NULL; @@ -335,6 +338,7 @@ display_create_egl_image_surface_from_file(struct display *display, g_object_unref(pixbuf); return surface; +#endif } #endif @@ -429,6 +433,7 @@ display_create_shm_surface_from_file(struct display *display, const char *filename, struct rectangle *rect) { +#ifdef GDK_STUFF cairo_surface_t *surface; GdkPixbuf *pixbuf; GError *error = NULL; @@ -481,6 +486,7 @@ display_create_shm_surface_from_file(struct display *display, g_object_unref(pixbuf); return surface; +#endif } static int diff --git a/compositor/compositor.c b/compositor/compositor.c index 535b3f1..8bbe387 100644 --- a/compositor/compositor.c +++ b/compositor/compositor.c @@ -28,7 +28,8 @@ #include <sys/ioctl.h> #include <fcntl.h> #include <unistd.h> -#include <gdk-pixbuf/gdk-pixbuf.h> +#include <png.h> +#include <signal.h> /* SIGTERM and SIGINT */ #include <math.h> #include <linux/input.h> @@ -45,10 +46,11 @@ struct wlsc_switcher { * advertise that through a service on the session dbus. */ static const char *option_socket_name = NULL; -static const char *option_background = "background.jpg"; +static const char *option_background = "background.png"; static const char *option_geometry = "1024x640"; static int option_connector = 0; +#ifdef GDK_STUFF static const GOptionEntry option_entries[] = { { "background", 'b', 0, G_OPTION_ARG_STRING, &option_background, "Background image" }, @@ -60,6 +62,7 @@ static const GOptionEntry option_entries[] = { &option_socket_name, "Socket Name" }, { NULL } }; +#endif static void wlsc_matrix_init(struct wlsc_matrix *matrix) @@ -198,33 +201,76 @@ destroy_surface(struct wl_resource *resource, struct wl_client *client) uint32_t * wlsc_load_image(const char *filename, int width, int height) { - GdkPixbuf *pixbuf; - GError *error = NULL; int stride, i, n_channels; - unsigned char *pixels, *end, *argb_pixels, *s, *d; - - pixbuf = gdk_pixbuf_new_from_file_at_scale(filename, - width, height, - FALSE, &error); - if (error != NULL) { - fprintf(stderr, "failed to load image: %s\n", error->message); - g_error_free(error); + unsigned char *end, *argb_pixels, *s, *d; + + int y; + png_byte bit_depth; + png_structp png_ptr; + png_infop info_ptr; + int number_of_passes; + png_bytep * row_pointers; + + char header[8]; // 8 is the maximum size that can be checked + + /* open file and test for it being a png */ + FILE *fp = fopen(filename, "rb"); + if (!fp) + fprintf(stderr, "file %s could not be opened for reading", filename); + + fread(header, 1, 8, fp); + + if (png_sig_cmp((png_bytep) header, 0, 8)) { + fprintf(stderr, "file %s is not recognized as a PNG file", filename); return NULL; } - stride = gdk_pixbuf_get_rowstride(pixbuf); - pixels = gdk_pixbuf_get_pixels(pixbuf); - n_channels = gdk_pixbuf_get_n_channels(pixbuf); + /* initialize stuff */ + png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL); + if (!png_ptr) + fprintf(stderr, "png_create_read_struct failed"); - argb_pixels = malloc (height * width * 4); - if (argb_pixels == NULL) { - g_object_unref(pixbuf); + info_ptr = png_create_info_struct(png_ptr); + if (!info_ptr) + fprintf(stderr, "png_create_info_struct failed"); + + if (setjmp(png_jmpbuf(png_ptr))) { + fprintf(stderr, "error during init_io"); return NULL; } + png_init_io(png_ptr, fp); + png_set_sig_bytes(png_ptr, 8); + png_set_swap_alpha(png_ptr); + png_read_info(png_ptr, info_ptr); + + bit_depth = png_get_bit_depth(png_ptr, info_ptr); + n_channels = png_get_channels(png_ptr, info_ptr); + stride = width * bit_depth * n_channels / 8; + + number_of_passes = png_set_interlace_handling(png_ptr); + png_read_update_info(png_ptr, info_ptr); + + /* read file */ + if (setjmp(png_jmpbuf(png_ptr))) + fprintf(stderr, "error during read_image"); + + row_pointers = (png_bytep*) malloc(sizeof(png_bytep) * height); + for (y=0; y < height; y++) + row_pointers[y] = malloc(png_get_rowbytes(png_ptr, info_ptr)); + + png_read_image(png_ptr, row_pointers); + fclose(fp); + + /* TODO: implement color type checking */ + + argb_pixels = malloc (height * width * 4); + if (argb_pixels == NULL) + return NULL; + if (n_channels == 4) { for (i = 0; i < height; i++) { - s = pixels + i * stride; + s = (unsigned char *)row_pointers[i]; end = s + width * 4; d = argb_pixels + i * width * 4; while (s < end) { @@ -243,7 +289,7 @@ wlsc_load_image(const char *filename, int width, int height) } } else if (n_channels == 3) { for (i = 0; i < height; i++) { - s = pixels + i * stride; + s = (unsigned char *)row_pointers[i]; end = s + width * 3; d = argb_pixels + i * width * 4; while (s < end) { @@ -257,8 +303,6 @@ wlsc_load_image(const char *filename, int width, int height) } } - g_object_unref(pixbuf); - return (uint32_t *) argb_pixels; } @@ -1283,9 +1327,10 @@ int main(int argc, char *argv[]) struct wl_display *display; struct wlsc_compositor *ec; struct wl_event_loop *loop; + int width, height; +#ifdef GDK_STUFF GError *error = NULL; GOptionContext *context; - int width, height; g_type_init(); /* GdkPixbuf needs this, it seems. */ @@ -1295,6 +1340,7 @@ int main(int argc, char *argv[]) fprintf(stderr, "option parsing failed: %s\n", error->message); exit(EXIT_FAILURE); } +#endif if (sscanf(option_geometry, "%dx%d", &width, &height) != 2) { fprintf(stderr, "invalid geometry option: %s \n", option_geometry); diff --git a/compositor/screenshooter.c b/compositor/screenshooter.c index 53ed931..a5cece3 100644 --- a/compositor/screenshooter.c +++ b/compositor/screenshooter.c @@ -18,7 +18,11 @@ #include <stdlib.h> #include <GLES2/gl2.h> +#ifdef GDK_STUFF #include <gdk-pixbuf/gdk-pixbuf.h> +#else +#include <stdio.h> +#endif #include "compositor.h" #include "screenshooter-server-protocol.h" @@ -34,8 +38,10 @@ screenshooter_shoot(struct wl_client *client, struct wl_screenshooter *shooter) struct wlsc_compositor *ec = shooter->ec; struct wlsc_output *output; char buffer[256]; +#ifdef GDK_STUFF GdkPixbuf *pixbuf; GError *error = NULL; +#endif unsigned char *data; int i, j; @@ -56,11 +62,13 @@ screenshooter_shoot(struct wl_client *client, struct wl_screenshooter *shooter) for (j = 3; j < output->width * output->height * 4; j += 4) data[j] = 0xff; +#ifdef GDK_STUFF pixbuf = gdk_pixbuf_new_from_data(data, GDK_COLORSPACE_RGB, TRUE, 8, output->width, output->height, output->width * 4, NULL, NULL); gdk_pixbuf_save(pixbuf, buffer, "png", &error, NULL); g_object_unref(pixbuf); +#endif free(data); } } diff --git a/configure.ac b/configure.ac index 868ebb8..38e4ab5 100644 --- a/configure.ac +++ b/configure.ac @@ -23,9 +23,9 @@ PKG_PROG_PKG_CONFIG() PKG_CHECK_MODULES(FFI, [libffi]) PKG_CHECK_MODULES(COMPOSITOR, - [egl >= 7.10 glesv2 gdk-pixbuf-2.0 libudev >= 136 libdrm >= 2.4.23] xcb-dri2 xcb-xfixes) + [egl >= 7.10 glesv2 libudev >= 136 libdrm >= 2.4.23] libpng xcb-dri2 xcb-xfixes) PKG_CHECK_MODULES(GLES2, [egl >= 7.10 glesv2 libdrm >= 2.4.23]) -PKG_CHECK_MODULES(CLIENT, [egl >= 7.10 gl cairo >= 1.10.0 gdk-pixbuf-2.0 glib-2.0 gobject-2.0 xkbcommon libdrm >= 2.4.23]) +PKG_CHECK_MODULES(CLIENT, [egl >= 7.10 gl cairo >= 1.10.0 libpng glib-2.0 gobject-2.0 xkbcommon libdrm >= 2.4.23]) PKG_CHECK_MODULES(POPPLER, [poppler-glib gdk-2.0 gio-2.0], [have_poppler=yes], [have_poppler=no]) AM_CONDITIONAL(HAVE_POPPLER, test "x$have_poppler" = "xyes") -- 1.7.1 _______________________________________________ wayland-devel mailing list wayland-devel@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/wayland-devel