Commit f3138bfb authored by Jeremy White's avatar Jeremy White

Switch to using xcb instead of Xlib.

parent d9b150f4
AC_INIT([x11spice], 1.0)
AM_INIT_AUTOMAKE
PKG_CHECK_MODULES(X11, x11)
PKG_CHECK_MODULES(XTST, xtst)
PKG_CHECK_MODULES(XDAMAGE, xdamage)
PKG_CHECK_MODULES(XEXT, xext)
PKG_CHECK_MODULES(XCB, xcb)
PKG_CHECK_MODULES(DAMAGE, xcb-damage)
PKG_CHECK_MODULES(XTEST, xcb-xtest)
PKG_CHECK_MODULES(SHM, xcb-shm)
PKG_CHECK_MODULES(UTIL, xcb-util)
PKG_CHECK_MODULES(GTK2, gtk+-2.0)
PKG_CHECK_MODULES(SPICE, spice-server)
PKG_CHECK_MODULES(SPICE_PROTOCOL, spice-protocol)
PKG_CHECK_MODULES(GLIB2, glib-2.0)
AC_PROG_CC
......
bin_PROGRAMS = x11spice
AM_CFLAGS = -Wall $(X11_CFLAGS) $(GTK2_CFLAGS) $(SPICE_CFLAGS) $(GLIB2_CFLAGS) $(XDAMAGE_CFLAGS) $(XEXT_CFLAGS) $(XTST_CFLAGS)
x11spice_LDADD = $(X11_LIBS) $(GTK2_LIBS) $(SPICE_LIBS) $(GLIB2_LIBS) $(XDAMAGE_LIBS) $(XEXT_LIBS) $(XTST_LIBS)
ALL_XCB_CFLAGS=$(XCB_CFLAGS) $(DAMAGE_CFLAGS) $(XTEST_CFLAGS) $(SHM_CFLAGS) $(UTIL_CFLAGS)
ALL_XCB_LIBS=$(XCB_LIBS) $(DAMAGE_LIBS) $(XTEST_LIBS) $(SHM_LIBS) $(UTIL_LIBS)
AM_CFLAGS = -Wall $(ALL_XCB_CFLAGS) $(GTK2_CFLAGS) $(SPICE_CFLAGS) $(SPICE_PROTOCOL_CFLAGS) $(GLIB2_CFLAGS)
x11spice_LDADD = $(ALL_XCB_LIBS) $(GTK2_LIBS) $(SPICE_LIBS) $(GLIB2_LIBS)
x11spice_SOURCES = \
display.c \
gui.c \
......
......@@ -21,56 +21,102 @@
#include <stdlib.h>
#include <stdio.h>
#include <X11/Xlib.h>
#include <X11/Xutil.h>
#include <glib.h>
#include <sys/types.h>
#include <sys/shm.h>
#include <string.h>
#include <xcb/xcb.h>
#include <xcb/xcb_aux.h>
#include "x11spice.h"
#include "options.h"
#include "display.h"
static xcb_screen_t *screen_of_display (xcb_connection_t *c, int screen)
{
xcb_screen_iterator_t iter;
iter = xcb_setup_roots_iterator(xcb_get_setup(c));
for (; iter.rem; --screen, xcb_screen_next(&iter))
if (screen == 0)
return iter.data;
return NULL;
}
static int bits_per_pixel(display_t *d)
{
xcb_format_iterator_t fmt;
for (fmt = xcb_setup_pixmap_formats_iterator(xcb_get_setup(d->c));
fmt.rem;
xcb_format_next(&fmt))
if (fmt.data->depth == d->screen->root_depth)
return fmt.data->bits_per_pixel;
return 0;
}
int display_open(display_t *d, options_t *options)
{
static int xinitthreads = 0;
int scr;
xcb_damage_query_version_cookie_t dcookie;
if (!xinitthreads)
xcb_void_cookie_t cookie;
xcb_generic_error_t *error;
d->c = xcb_connect(options->display, &scr);
if (! d->c)
{
if (! XInitThreads())
{
fprintf(stderr, "Error: could not initialize X Threads\n");
return X11SPICE_ERR_NODISPLAY;
}
xinitthreads = 1;
fprintf(stderr, "Error: could not open display %s\n", options->display ? options->display : "");
return X11SPICE_ERR_NODISPLAY;
}
d->xdisplay = XOpenDisplay(options->display);
// FIXME - do we care? - g_x_error_handler = XSetErrorHandler(handle_xerrors);
if (! d->xdisplay)
d->screen = screen_of_display(d->c, scr);
if (!d->screen)
{
fprintf(stderr, "Error: could not open display %s\n", options->display ? options->display : "");
fprintf(stderr, "Error: could not get screen for display %s\n", options->display ? options->display : "");
return X11SPICE_ERR_NODISPLAY;
}
if (! XDamageQueryExtension(d->xdisplay, &d->xd_event_base, &d->xd_error_base))
d->damage_ext = xcb_get_extension_data(d->c, &xcb_damage_id);
if (! d->damage_ext)
{
fprintf(stderr, "Error: XDAMAGE not found on display %s\n", options->display ? options->display : "");
return X11SPICE_ERR_NODAMAGE;
}
if (! XShmQueryExtension(d->xdisplay))
dcookie = xcb_damage_query_version(d->c, XCB_DAMAGE_MAJOR_VERSION, XCB_DAMAGE_MINOR_VERSION);
xcb_damage_query_version_reply(d->c, dcookie, &error);
if (error)
{
fprintf(stderr, "Error: Could not query damage; type %d; code %d; major %d; minor %d\n",
error->response_type, error->error_code, error->major_code, error->minor_code);
return X11SPICE_ERR_NODAMAGE;
}
d->damage = xcb_generate_id(d->c);
cookie = xcb_damage_create_checked(d->c, d->damage, d->screen->root, XCB_DAMAGE_REPORT_LEVEL_RAW_RECTANGLES);
error = xcb_request_check(d->c, cookie);
if (error)
{
fprintf(stderr, "Error: Could not create damage; type %d; code %d; major %d; minor %d\n",
error->response_type, error->error_code, error->major_code, error->minor_code);
return X11SPICE_ERR_NODAMAGE;
}
d->shm_ext = xcb_get_extension_data(d->c, &xcb_shm_id);
if (! d->shm_ext)
{
fprintf(stderr, "Error: XSHM not found on display %s\n", options->display ? options->display : "");
return X11SPICE_ERR_NOSHM;
}
d->xdamage = XDamageCreate(d->xdisplay, DefaultRootWindow(d->xdisplay), XDamageReportRawRectangles);
g_info("Display %s opened", options->display ? options->display : "");
g_message("Display %s opened", options->display ? options->display : "");
return 0;
}
......@@ -78,47 +124,48 @@ int display_open(display_t *d, options_t *options)
shm_image_t * create_shm_image(display_t *d, int w, int h)
{
shm_image_t *shmi;
int scr = DefaultScreen(d->xdisplay);
int imgsize;
xcb_void_cookie_t cookie;
xcb_generic_error_t *error;
shmi = calloc(1, sizeof(*shmi));
if (! shmi)
return shmi;
shmi->img = XShmCreateImage(d->xdisplay,
DefaultVisual(d->xdisplay, scr),
DefaultDepth(d->xdisplay, scr),
ZPixmap /* FIXME - format we want? */, NULL /* data? */,
&shmi->info,
w ? w : DisplayWidth(d->xdisplay, scr),
h ? h : DisplayHeight(d->xdisplay, scr));
if (! shmi->img)
{
free(shmi);
return NULL;
}
shmi->w = w ? w : d->screen->width_in_pixels;
shmi->h = h ? h : d->screen->height_in_pixels;
imgsize = shmi->img->bytes_per_line * shmi->img->height;
shmi->bytes_per_line = (bits_per_pixel(d) / 8) * shmi->w;
imgsize = shmi->bytes_per_line * shmi->h;
shmi->info.shmid = shmget(IPC_PRIVATE, imgsize, IPC_CREAT | 0700);
if (shmi->info.shmid == -1)
shmi->shmid = shmget(IPC_PRIVATE, imgsize, IPC_CREAT | 0700);
if (shmi->shmid != -1)
shmi->shmaddr = shmat(shmi->shmid, 0, 0);
if (shmi->shmid == -1 || shmi->shmaddr == (void *) -1)
{
g_error("Cannot get shared memory of size %d", imgsize);
XDestroyImage(shmi->img);
free(shmi);
return NULL;
}
shmi->info.shmaddr = shmi->img->data = shmat(shmi->info.shmid, 0, 0);
shmi->info.readOnly = False;
shmi->shmseg = xcb_generate_id(d->c);
cookie = xcb_shm_attach_checked(d->c, shmi->shmseg, shmi->shmid, 0);
error = xcb_request_check(d->c, cookie);
if (error)
{
g_error("Could not attach; type %d; code %d; major %d; minor %d\n",
error->response_type, error->error_code, error->major_code, error->minor_code);
return NULL;
}
if (!XShmAttach(d->xdisplay, &shmi->info))
shmi->pid = xcb_generate_id(d->c);
cookie = xcb_shm_create_pixmap_checked(d->c, shmi->pid, d->screen->root,
shmi->w, shmi->h, d->screen->root_depth, shmi->shmseg, 0);
error = xcb_request_check(d->c, cookie);
if (error)
{
g_error("Failed to attach shared memory");
shmdt(shmi->info.shmaddr);
shmctl(shmi->info.shmid, IPC_RMID, NULL);
XDestroyImage(shmi->img);
free(shmi);
g_error("Could not create pixmap; type %d; code %d; major %d; minor %d\n",
error->response_type, error->error_code, error->major_code, error->minor_code);
return NULL;
}
......@@ -127,34 +174,40 @@ shm_image_t * create_shm_image(display_t *d, int w, int h)
int read_shm_image(display_t *d, shm_image_t *shmi, int x, int y)
{
if (!XShmGetImage(d->xdisplay, DefaultRootWindow(d->xdisplay), shmi->img,
x, y, AllPlanes))
xcb_shm_get_image_cookie_t cookie;
xcb_generic_error_t *e;
cookie = xcb_shm_get_image(d->c, d->screen->root, x, y, shmi->w, shmi->h,
~0, XCB_IMAGE_FORMAT_Z_PIXMAP, shmi->shmseg, 0);
xcb_shm_get_image_reply(d->c, cookie, &e);
if (e)
{
g_error("XShmGetImage from %dx%d into size %dx%d failed",
x, y, shmi->img->width, shmi->img->height);
g_error("xcb_shm_get_image from %dx%d into size %dx%d failed", x, y, shmi->w, shmi->h);
return X11SPICE_ERR_NOSHM;
}
return 0;
}
void destroy_shm_image(display_t *d, shm_image_t *shmi)
{
XShmDetach(d->xdisplay, &shmi->info);
shmdt(shmi->info.shmaddr);
shmctl(shmi->info.shmid, IPC_RMID, NULL);
XDestroyImage(shmi->img);
xcb_free_pixmap(d->c, shmi->pid);
xcb_shm_detach(d->c, shmi->shmseg);
shmdt(shmi->shmaddr);
shmctl(shmi->shmid, IPC_RMID, NULL);
if (shmi->drawable_ptr)
free(shmi->drawable_ptr);
}
void display_close(display_t *d)
{
XDamageDestroy(d->xdisplay, d->xdamage);
XCloseDisplay(d->xdisplay);
xcb_damage_destroy(d->c, d->damage);
if (d->fullscreen)
{
destroy_shm_image(d, d->fullscreen);
d->fullscreen = NULL;
}
xcb_disconnect(d->c);
}
......@@ -21,26 +21,35 @@
#ifndef DISPLAY_H_
#define DISPLAY_H_
#include <X11/Xlib.h>
#include <X11/extensions/Xdamage.h>
#include <X11/extensions/XShm.h>
#include <xcb/xcb.h>
#include <xcb/damage.h>
#include <xcb/shm.h>
/*----------------------------------------------------------------------------
** Structure definitions
**--------------------------------------------------------------------------*/
typedef struct
{
XImage *img;
XShmSegmentInfo info;
xcb_pixmap_t pid;
int shmid;
int w;
int h;
int bytes_per_line;
xcb_shm_seg_t shmseg;
void *shmaddr;
void *drawable_ptr;
}shm_image_t;
typedef struct
{
Display *xdisplay;
Damage xdamage;
int xd_event_base;
int xd_error_base;
xcb_connection_t *c;
xcb_screen_t *screen;
const xcb_query_extension_reply_t *damage_ext;
xcb_damage_damage_t damage;
const xcb_query_extension_reply_t *shm_ext;
shm_image_t *fullscreen;
} display_t;
......
This diff is collapsed.
......@@ -183,7 +183,7 @@ static void attach_worker(QXLInstance *qin, QXLWorker *qxl_worker)
if (++count > 1)
{
g_info("Ignoring worker %d", count);
g_message("Ignoring worker %d", count);
return;
}
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment