예제 #1
0
static void
swrastGetImage(__DRIdrawable * read,
               int x, int y, int w, int h,
               char *data, void *loaderPrivate)
{
   struct dri2_egl_surface *dri2_surf = loaderPrivate;
   struct dri2_egl_display *dri2_dpy = dri2_egl_display(dri2_surf->base.Resource.Display);

   xcb_get_image_cookie_t cookie;
   xcb_get_image_reply_t *reply;
   xcb_generic_error_t *error;

   cookie = xcb_get_image (dri2_dpy->conn, XCB_IMAGE_FORMAT_Z_PIXMAP,
                           dri2_surf->drawable, x, y, w, h, ~0);
   reply = xcb_get_image_reply (dri2_dpy->conn, cookie, &error);
   if (reply == NULL)
      return;

   if (error != NULL) {
      _eglLog(_EGL_WARNING, "error in xcb_get_image");
      free(error);
   } else {
      uint32_t bytes = xcb_get_image_data_length(reply);
      uint8_t *idata = xcb_get_image_data(reply);
      memcpy(data, idata, bytes);
   }
   free(reply);
}
예제 #2
0
void
_cairo_boilerplate_xcb_synchronize (void *closure)
{
    xcb_target_closure_t *xtc = closure;
    free (xcb_get_image_reply (xtc->c,
		xcb_get_image (xtc->c, XCB_IMAGE_FORMAT_Z_PIXMAP,
		    xtc->pixmap, 0, 0, 1, 1, /* AllPlanes */ ~0UL),
		0));
}
static void
_cairo_boilerplate_xcb_synchronize (void *closure)
{
    xcb_target_closure_t *xtc = closure;
    cairo_status_t status;
    free (xcb_get_image_reply (xtc->c,
		xcb_get_image (xtc->c, XCB_IMAGE_FORMAT_Z_PIXMAP,
		    xtc->drawable, 0, 0, 1, 1, /* AllPlanes */ -1),
		0));

    status = _cairo_boilerplate_xcb_handle_errors (xtc);
    assert (status == CAIRO_STATUS_SUCCESS);
}
예제 #4
0
파일: screen.c 프로젝트: borzunov/remoteink
ExcCode screen_shot(int x, int y, int width, int height,
		Imlib_Image *res) {
	int x1 = x + width;
	int y1 = y + height;
	x = MAX(x, 0);
	y = MAX(y, 0);
	x1 = MIN(x1, screen->width_in_pixels);
	y1 = MIN(y1, screen->height_in_pixels);
	width = x1 - x;
	height = y1 - y;
	
	*res = NULL;
	if (shm_available) {
		xcb_shm_get_image_cookie_t cookie =
				xcb_shm_get_image(display,
				root, x, y, width, height,
				XCB_ALL_PLANES, XCB_IMAGE_FORMAT_Z_PIXMAP,
				shmseg, 0);
		xcb_shm_get_image_reply_t *reply =
				xcb_shm_get_image_reply(display, cookie, NULL);
		if (reply != NULL) {
			*res = imlib_create_image_using_copied_data(width, height,
					(unsigned *) shmaddr);
			free(reply);
		}
	}
	if (*res == NULL) {
		// If shm can't be used due to lack of the libraries or
		// because we connect to X11 on another machine (e.g. via SSH),
		// try to get an image via sockets.

		xcb_get_image_cookie_t cookie = xcb_get_image(display,
				XCB_IMAGE_FORMAT_Z_PIXMAP, root, x, y, width, height,
				XCB_ALL_PLANES);
		xcb_get_image_reply_t *reply =
				xcb_get_image_reply(display, cookie, NULL);
		if (reply == NULL)
			PANIC(ERR_X_REQUEST, "screen_shot (xcb_get_image_reply)");
		*res = imlib_create_image_using_copied_data(width, height,
				(unsigned *) xcb_get_image_data(reply));
		free(reply);
	}
	if (*res == NULL)
		PANIC(ERR_IMAGE);
		
	if (cursor_capturing_enabled && cursor_available)
		screen_cursor_blend(x, y, *res);
	return 0;
}
xcb_get_image_reply_t *
_cairo_xcb_connection_get_image (cairo_xcb_connection_t *connection,
				 xcb_drawable_t src,
				 int16_t src_x,
				 int16_t src_y,
				 uint16_t width,
				 uint16_t height)
{
    return xcb_get_image_reply (connection->xcb_connection,
				xcb_get_image (connection->xcb_connection,
					       XCB_IMAGE_FORMAT_Z_PIXMAP,
					       src,
					       src_x, src_y,
					       width, height,
					       (uint32_t) -1),
				NULL);
}
예제 #6
0
bool Shadow::init(const QVector< uint32_t > &data)
{
    QVector<Xcb::WindowGeometry> pixmapGeometries(ShadowElementsCount);
    QVector<xcb_get_image_cookie_t> getImageCookies(ShadowElementsCount);
    auto *c = connection();
    for (int i = 0; i < ShadowElementsCount; ++i) {
        pixmapGeometries[i] = Xcb::WindowGeometry(data[i]);
    }
    auto discardReplies = [&getImageCookies](int start) {
        for (int i = start; i < getImageCookies.size(); ++i) {
            xcb_discard_reply(connection(), getImageCookies.at(i).sequence);
        }
    };
    for (int i = 0; i < ShadowElementsCount; ++i) {
        auto &geo = pixmapGeometries[i];
        if (geo.isNull()) {
            discardReplies(0);
            return false;
        }
        getImageCookies[i] = xcb_get_image_unchecked(c, XCB_IMAGE_FORMAT_Z_PIXMAP, data[i],
                                                     0, 0, geo->width, geo->height, ~0);
    }
    for (int i = 0; i < ShadowElementsCount; ++i) {
        auto *reply = xcb_get_image_reply(c, getImageCookies.at(i), nullptr);
        if (!reply) {
            discardReplies(i+1);
            return false;
        }
        auto &geo = pixmapGeometries[i];
        QImage image(xcb_get_image_data(reply), geo->width, geo->height, QImage::Format_ARGB32);
        m_shadowElements[i] = QPixmap::fromImage(image);
        free(reply);
    }
    m_topOffset = data[ShadowElementsCount];
    m_rightOffset = data[ShadowElementsCount+1];
    m_bottomOffset = data[ShadowElementsCount+2];
    m_leftOffset = data[ShadowElementsCount+3];
    updateShadowRegion();
    if (!prepareBackend()) {
        return false;
    }
    buildQuads();
    return true;
}
예제 #7
0
ExcCode screen_shot(int x, int y, int width, int height,
		Imlib_Image *res) {
	int x1 = x + width;
	int y1 = y + height;
	x = MAX(x, 0);
	y = MAX(y, 0);
	x1 = MIN(x1, screen->width_in_pixels);
	y1 = MIN(y1, screen->height_in_pixels);
	width = x1 - x;
	height = y1 - y;
	
	if (shm_available) {
		xcb_shm_get_image_cookie_t cookie =
				xcb_shm_get_image(display,
				root, x, y, width, height,
				XCB_ALL_PLANES, XCB_IMAGE_FORMAT_Z_PIXMAP,
				shmseg, 0);
		xcb_shm_get_image_reply_t *reply =
				xcb_shm_get_image_reply(display, cookie, NULL);
		if (reply == NULL)
			PANIC(ERR_X_REQUEST, "screen_shot (xcb_shm_get_image_reply)");
		*res = imlib_create_image_using_copied_data(width, height,
				(unsigned *) shmaddr);
		free(reply);
	} else {
		xcb_get_image_cookie_t cookie = xcb_get_image(display,
				XCB_IMAGE_FORMAT_Z_PIXMAP, root, x, y, width, height,
				XCB_ALL_PLANES);
		xcb_get_image_reply_t *reply =
				xcb_get_image_reply(display, cookie, NULL);
		if (reply == NULL)
			PANIC(ERR_X_REQUEST, "screen_shot (xcb_get_image_reply)");
		*res = imlib_create_image_using_copied_data(width, height,
				(unsigned *) xcb_get_image_data(reply));
		free(reply);
	}
	if (*res == NULL)
		PANIC(ERR_IMAGE);
		
	if (cursor_capturing_enabled && cursor_available)
		screen_cursor_blend(x, y, *res);
	return 0;
}
예제 #8
0
파일: xcb_image.c 프로젝트: RSATom/Qt
xcb_image_t *
xcb_image_get (xcb_connection_t *  conn,
	       xcb_drawable_t      draw,
	       int16_t             x,
	       int16_t             y,
	       uint16_t            width,
	       uint16_t            height,
	       uint32_t            plane_mask,
	       xcb_image_format_t  format)
{
  xcb_get_image_cookie_t   image_cookie;
  xcb_get_image_reply_t *  imrep;
  xcb_image_t *            image = 0;
  uint32_t                 bytes;
  uint8_t *                data;

  image_cookie = xcb_get_image(conn, format, draw, x, y,
			       width, height, plane_mask);
  imrep = xcb_get_image_reply(conn, image_cookie, 0);
  if (!imrep)
      return 0;
  bytes = xcb_get_image_data_length(imrep);
  data = xcb_get_image_data(imrep);
  switch (format) {
  case XCB_IMAGE_FORMAT_XY_PIXMAP:
      plane_mask &= xcb_mask(imrep->depth);
      if (plane_mask != xcb_mask(imrep->depth)) {
	  xcb_image_t *  tmp_image =
	    xcb_image_create_native(conn, width, height, format,
				    imrep->depth, 0, 0, 0);
	  
	  if (!tmp_image) {
	      free(imrep);
	      return 0;
	  }

	  int            i;
	  uint32_t       rpm = plane_mask;
	  uint8_t *      src_plane = image->data;
	  uint8_t *      dst_plane = tmp_image->data;
	  uint32_t       size = image->height * image->stride;

	  if (tmp_image->bit_order == XCB_IMAGE_ORDER_MSB_FIRST)
	      rpm = xcb_bit_reverse(plane_mask, imrep->depth);
	  for (i = 0; i < imrep->depth; i++) {
	      if (rpm & 1) {
		  memcpy(dst_plane, src_plane, size);
		  src_plane += size;
	      } else {
		  memset(dst_plane, 0, size);
	      }
	      dst_plane += size;
	  }
	  tmp_image->plane_mask = plane_mask;
	  image = tmp_image;
	  free(imrep);
	  break;
      }
      /* fall through */
  case XCB_IMAGE_FORMAT_Z_PIXMAP:
      image = xcb_image_create_native(conn, width, height, format,
				      imrep->depth, imrep, bytes, data);
      if (!image) {
	  free(imrep);
	  return 0;
      }
      break;
  default:
      assert(0);
  }
  assert(bytes == image->size);
  return image;
}
예제 #9
0
파일: dri_test.c 프로젝트: wwzbwwzb/truck
void draw_gc(xcb_window_t win)
{
	// the only problem to draw bgr24 it  bps=4 but 3, if depth=24,
	/*
	fmt depth	 bps
	32	  32    4
	bgr24 24    4
	16    16    2
	8      8     1
	0      0      0
		 */
	//draw something in parent window for test
	//w = s->root;
	xcb_gcontext_t       g_solid;
	uint32_t             mask;
	uint32_t             values[2];
	xcb_rectangle_t      r = { 0, 0,  10,10 };
	xcb_rectangle_t      r2 = { 20, 20,  100,100 };
	xcb_connection_t    *c = G.conn;

	if(win==0) {
		win=G.root;
		// atach to root will cause  error=Resource temporary unavailable
	}
	xcb_map_window(c, win); xcb_flush(c);
	g_solid = xcb_generate_id(c);
	mask = XCB_GC_FOREGROUND | XCB_GC_GRAPHICS_EXPOSURES;
	values[0] = G.s->white_pixel;
	values[1] = XCB_EVENT_MASK_EXPOSURE | XCB_EVENT_MASK_KEY_PRESS;
	xcb_create_gc(c, g_solid, win, 0,NULL);
	xcb_change_gc(c, g_solid,  mask, values);
	xcb_poly_fill_rectangle(c, win, g_solid,  1, &r2); xcb_flush(c);
	xcb_free_gc(c,g_solid);

	if(1){
		//getimage 
		xcb_get_image_cookie_t cookie;
		xcb_get_image_reply_t *reply;
		xcb_generic_error_t *error;
		int psize= r.width * r.height * G.s->root_depth/8;
		psize = r.width * r.height * 4; //correct
		static uint8_t *pbuf = NULL;
		xcb_void_cookie_t ck;

		if( pbuf == NULL){
			pbuf = malloc(psize);
			printf("malloc pbuf=0x%x size=%d\n",pbuf, psize);
			memset(pbuf, 0x18, psize);
		}

#if 0
		cookie = xcb_get_image (c, XCB_IMAGE_FORMAT_Z_PIXMAP,
				win, r.x, r.y, r.width, r.height, ~0);
		reply = xcb_get_image_reply (c, cookie, &error);
		if (reply == NULL){
			perror("get_image_replay");
			return;
		}

		if (error != NULL) {
			perror("error in xcb_get_image");
			free(error);
		} else {
			uint32_t bytes = xcb_get_image_data_length(reply);
			uint8_t *idata = xcb_get_image_data(reply);
			printf("get_image size=%d p=%p\n", bytes, idata);
			memcpy(pbuf, idata, bytes);
			printf("root_depth=%d\n", G.s->root_depth);
			psize=bytes;
		}
		free(reply);
#endif

		//draw image with xcb_put_image
		// creat gc and draw to parent window
		xcb_gcontext_t       g;
		g = xcb_generate_id(c);
		xcb_create_gc(c, g, win, 0,NULL);

		memset(pbuf, 0xf8, psize);
		int i=0;
		uint8_t *p2=pbuf;
		//fmt = bgr24
		for( i=0; i<psize; ){
			*(p2+i)= 0;		i++;  //blue
			*(p2+i)= 0xff;		i++; //green
			*(p2+i)= 0;		i++; //red
			*(p2+i)= 0x80;		i++; //??
		}
		ck = xcb_put_image_checked(c, XCB_IMAGE_FORMAT_Z_PIXMAP,
				win, g,
				r.width, r.height, r.x,r.y,
				0, G.s->root_depth,
				psize, pbuf);
		xcb_flush(c);

#if 0
		//BadMatch=8 BadLength=16
		xcb_generic_error_t *err;
		err = xcb_request_check (c, ck);
		if (err)
		{
			int code = err->error_code;
			free (err);
			printf("put image error %d\n", code);
			assert (code != 0);
		}   
		xcb_free_gc(c, g);
#endif
	}

}
예제 #10
0
/**
 * Processing callback
 */
static void Demux (void *data)
{
    demux_t *demux = data;
    demux_sys_t *sys = demux->p_sys;
    xcb_connection_t *conn = sys->conn;

    /* Determine capture region */
    xcb_get_geometry_cookie_t gc;
    xcb_query_pointer_cookie_t qc;

    gc = xcb_get_geometry (conn, sys->window);
    if (sys->follow_mouse)
        qc = xcb_query_pointer (conn, sys->window);

    xcb_get_geometry_reply_t *geo = xcb_get_geometry_reply (conn, gc, NULL);
    if (geo == NULL)
    {
        msg_Err (demux, "bad X11 drawable 0x%08"PRIx32, sys->window);
discard:
        if (sys->follow_mouse)
            xcb_discard_reply (conn, gc.sequence);
        return;
    }

    int w = sys->w;
    int h = sys->h;
    int x, y;

    if (sys->follow_mouse)
    {
        xcb_query_pointer_reply_t *ptr =
            xcb_query_pointer_reply (conn, qc, NULL);
        if (ptr == NULL)
        {
            free (geo);
            return;
        }

        if (w == 0 || w > geo->width)
            w = geo->width;
        x = ptr->win_x;
        if (x < w / 2)
            x = 0;
        else if (x >= (int)geo->width - (w / 2))
            x = geo->width - w;
        else
            x -= w / 2;

        if (h == 0 || h > geo->height)
            h = geo->height;
        y = ptr->win_y;
        if (y < h / 2)
            y = 0;
        else if (y >= (int)geo->height - (h / 2))
            y = geo->height - h;
        else
            y -= h / 2;
    }
    else
    {
        int max;

        x = sys->x;
        max = (int)geo->width - x;
        if (max <= 0)
            goto discard;
        if (w == 0 || w > max)
            w = max;

        y = sys->y;
        max = (int)geo->height - y;
        if (max <= 0)
            goto discard;
        if (h == 0 || h > max)
            h = max;
    }

    /* Update elementary stream format (if needed) */
    if (w != sys->cur_w || h != sys->cur_h)
    {
        if (sys->es != NULL)
            es_out_Del (demux->out, sys->es);

        /* Update composite pixmap */
        if (sys->window != geo->root)
        {
            xcb_free_pixmap (conn, sys->pixmap); /* no-op first time */
            xcb_composite_name_window_pixmap (conn, sys->window, sys->pixmap);
            xcb_create_pixmap (conn, geo->depth, sys->pixmap,
                               geo->root, geo->width, geo->height);
        }

        sys->es = InitES (demux, w, h, geo->depth);
        if (sys->es != NULL)
        {
            sys->cur_w = w;
            sys->cur_h = h;
        }
    }

    /* Capture screen */
    xcb_drawable_t drawable =
        (sys->window != geo->root) ? sys->pixmap : sys->window;
    free (geo);

    xcb_get_image_reply_t *img;
    img = xcb_get_image_reply (conn,
        xcb_get_image (conn, XCB_IMAGE_FORMAT_Z_PIXMAP, drawable,
                       x, y, w, h, ~0), NULL);
    if (img == NULL)
        return;

    block_t *block = block_heap_Alloc (img, xcb_get_image_data (img),
                                       xcb_get_image_data_length (img));
    if (block == NULL)
        return;

    /* Send block - zero copy */
    if (sys->es != NULL)
    {
        if (sys->pts == VLC_TS_INVALID)
            sys->pts = mdate ();
        block->i_pts = block->i_dts = sys->pts;

        es_out_Control (demux->out, ES_OUT_SET_PCR, sys->pts);
        es_out_Send (demux->out, sys->es, block);
        sys->pts += sys->interval;
    }
}
예제 #11
0
파일: xcb.c 프로젝트: FLYKingdom/vlc
/**
 * Processing callback
 */
static void Demux (void *data)
{
    demux_t *demux = data;
    demux_sys_t *p_sys = demux->p_sys;
    xcb_connection_t *conn = p_sys->conn;

    /* Update capture region (if needed) */
    xcb_get_geometry_cookie_t gc = xcb_get_geometry (conn, p_sys->window);
    int16_t x = p_sys->x, y = p_sys->y;
    xcb_translate_coordinates_cookie_t tc;

    if (p_sys->window != p_sys->root)
        tc = xcb_translate_coordinates (conn, p_sys->window, p_sys->root,
                                        x, y);

    xcb_get_geometry_reply_t *geo = xcb_get_geometry_reply (conn, gc, NULL);
    if (geo == NULL)
    {
        msg_Err (demux, "bad X11 drawable 0x%08"PRIx32, p_sys->window);
        return;
    }

    uint16_t w = geo->width - x;
    uint16_t h = geo->height - y;
    free (geo);
    if (p_sys->w > 0 && p_sys->w < w)
        w = p_sys->w;
    if (p_sys->h > 0 && p_sys->h < h)
        h = p_sys->h;

    if (p_sys->window != p_sys->root)
    {
        xcb_translate_coordinates_reply_t *coords =
             xcb_translate_coordinates_reply (conn, tc, NULL);
        if (coords == NULL)
            return;
        x = coords->dst_x;
        y = coords->dst_y;
        free (coords);
    }

    xcb_get_image_reply_t *img;
    img = xcb_get_image_reply (conn,
        xcb_get_image (conn, XCB_IMAGE_FORMAT_Z_PIXMAP, p_sys->root,
                       x, y, w, h, ~0), NULL);
    if (img == NULL)
        return;

    /* Send block - zero copy */
    block_t *block = block_heap_Alloc (img, xcb_get_image_data (img),
                                       xcb_get_image_data_length (img));
    if (block == NULL)
        return;

    vlc_mutex_lock (&p_sys->lock);
    if (w != p_sys->fmt.video.i_visible_width
     || h != p_sys->fmt.video.i_visible_height)
    {
        if (p_sys->es != NULL)
            es_out_Del (demux->out, p_sys->es);
        p_sys->fmt.video.i_visible_width = p_sys->fmt.video.i_width = w;
        p_sys->fmt.video.i_visible_height = p_sys->fmt.video.i_height = h;
        p_sys->es = es_out_Add (demux->out, &p_sys->fmt);
    }

    /* Capture screen */
    if (p_sys->es != NULL)
    {
        if (p_sys->pts == VLC_TS_INVALID)
            p_sys->pts = mdate ();
        block->i_pts = block->i_dts = p_sys->pts;

        es_out_Control (demux->out, ES_OUT_SET_PCR, p_sys->pts);
        es_out_Send (demux->out, p_sys->es, block);
        p_sys->pts += p_sys->interval;
    }
    vlc_mutex_unlock (&p_sys->lock);
}
예제 #12
0
/**
 * Processing callback
 */
static void Demux (void *opaque)
{
    demux_t *demux = opaque;
    demux_sys_t *sys = demux->p_sys;
    xcb_connection_t *conn = sys->conn;

    /* Determine capture region */
    xcb_get_geometry_cookie_t gc;
    xcb_query_pointer_cookie_t qc;

    gc = xcb_get_geometry (conn, sys->window);
    if (sys->follow_mouse)
        qc = xcb_query_pointer (conn, sys->window);

    xcb_get_geometry_reply_t *geo = xcb_get_geometry_reply (conn, gc, NULL);
    if (geo == NULL)
    {
        msg_Err (demux, "bad X11 drawable 0x%08"PRIx32, sys->window);
discard:
        if (sys->follow_mouse)
            xcb_discard_reply (conn, gc.sequence);
        return;
    }

    int w = sys->w;
    int h = sys->h;
    int x, y;

    if (sys->follow_mouse)
    {
        xcb_query_pointer_reply_t *ptr =
            xcb_query_pointer_reply (conn, qc, NULL);
        if (ptr == NULL)
        {
            free (geo);
            return;
        }

        if (w == 0 || w > geo->width)
            w = geo->width;
        x = ptr->win_x;
        if (x < w / 2)
            x = 0;
        else if (x >= (int)geo->width - (w / 2))
            x = geo->width - w;
        else
            x -= w / 2;

        if (h == 0 || h > geo->height)
            h = geo->height;
        y = ptr->win_y;
        if (y < h / 2)
            y = 0;
        else if (y >= (int)geo->height - (h / 2))
            y = geo->height - h;
        else
            y -= h / 2;
    }
    else
    {
        int max;

        x = sys->x;
        max = (int)geo->width - x;
        if (max <= 0)
            goto discard;
        if (w == 0 || w > max)
            w = max;

        y = sys->y;
        max = (int)geo->height - y;
        if (max <= 0)
            goto discard;
        if (h == 0 || h > max)
            h = max;
    }

    /* Update elementary stream format (if needed) */
    if (w != sys->cur_w || h != sys->cur_h)
    {
        if (sys->es != NULL)
            es_out_Del (demux->out, sys->es);

        /* Update composite pixmap */
        if (sys->window != geo->root)
        {
            xcb_free_pixmap (conn, sys->pixmap); /* no-op first time */
            xcb_composite_name_window_pixmap (conn, sys->window, sys->pixmap);
            xcb_create_pixmap (conn, geo->depth, sys->pixmap,
                               geo->root, geo->width, geo->height);
        }

        sys->es = InitES (demux, w, h, geo->depth, &sys->bpp);
        if (sys->es != NULL)
        {
            sys->cur_w = w;
            sys->cur_h = h;
            sys->bpp /= 8; /* bits -> bytes */
        }
    }

    /* Capture screen */
    xcb_drawable_t drawable =
        (sys->window != geo->root) ? sys->pixmap : sys->window;
    free (geo);

    block_t *block = NULL;
#if HAVE_SYS_SHM_H
    if (sys->shm)
    {   /* Capture screen through shared memory */
        size_t size = w * h * sys->bpp;
        int id = shmget (IPC_PRIVATE, size, IPC_CREAT | 0777);
        if (id == -1) /* XXX: fallback */
        {
            msg_Err (demux, "shared memory allocation error: %m");
            goto noshm;
        }

        /* Attach the segment to X and capture */
        xcb_shm_get_image_reply_t *img;
        xcb_shm_get_image_cookie_t ck;

        xcb_shm_attach (conn, sys->segment, id, 0 /* read/write */);
        ck = xcb_shm_get_image (conn, drawable, x, y, w, h, ~0,
                                XCB_IMAGE_FORMAT_Z_PIXMAP, sys->segment, 0);
        xcb_shm_detach (conn, sys->segment);
        img = xcb_shm_get_image_reply (conn, ck, NULL);
        xcb_flush (conn); /* ensure eventual detach */

        if (img == NULL)
        {
            shmctl (id, IPC_RMID, 0);
            goto noshm;
        }
        free (img);

        /* Attach the segment to VLC */
        void *shm = shmat (id, NULL, 0 /* read/write */);
        shmctl (id, IPC_RMID, 0);
        if (-1 == (intptr_t)shm)
        {
            msg_Err (demux, "shared memory attachment error: %m");
            return;
        }

        block = block_shm_Alloc (shm, size);
        if (unlikely(block == NULL))
            shmdt (shm);
    }
noshm:
#endif
    if (block == NULL)
    {   /* Capture screen through socket (fallback) */
        xcb_get_image_reply_t *img;

        img = xcb_get_image_reply (conn,
            xcb_get_image (conn, XCB_IMAGE_FORMAT_Z_PIXMAP, drawable,
                           x, y, w, h, ~0), NULL);
        if (img == NULL)
            return;

        uint8_t *data = xcb_get_image_data (img);
        size_t datalen = xcb_get_image_data_length (img);
        block = block_heap_Alloc (img, data + datalen - (uint8_t *)img);
        if (block == NULL)
            return;
        block->p_buffer = data;
        block->i_buffer = datalen;
    }

    /* Send block - zero copy */
    if (sys->es != NULL)
    {
        block->i_pts = block->i_dts = mdate ();

        es_out_Control (demux->out, ES_OUT_SET_PCR, block->i_pts);
        es_out_Send (demux->out, sys->es, block);
    }
}