예제 #1
0
void krad_x11_disable_capture(krad_x11_t *x11) {
  xcb_shm_detach (x11->connection, x11->shminfo.shmseg);
  xcb_image_destroy (x11->img);
  shmdt (x11->shminfo.shmaddr);
  shmctl (x11->shminfo.shmid, IPC_RMID, 0);
  x11->capture_enabled = 0;
}
void
_cairo_xcb_connection_shm_detach (cairo_xcb_connection_t *connection,
				  uint32_t segment)
{
    assert (connection->flags & CAIRO_XCB_HAS_SHM);
    xcb_shm_detach (connection->xcb_connection, segment);
    _cairo_xcb_connection_put_xid (connection, segment);
}
예제 #3
0
void QXcbShmImage::destroy()
{
    Q_XCB_CALL(xcb_shm_detach(xcb_connection(), m_shm_info.shmseg));
    xcb_image_destroy(m_xcb_image);
    shmdt(m_shm_info.shmaddr);
    shmctl(m_shm_info.shmid, IPC_RMID, 0);
    if (m_gc)
        Q_XCB_CALL(xcb_free_gc(xcb_connection(), m_gc));
}
예제 #4
0
/**
 * Release picture private data: detach the shared memory segment.
 */
void PictureResourceFree (picture_resource_t *res, xcb_connection_t *conn)
{
#ifdef HAVE_SYS_SHM_H
    xcb_shm_seg_t segment = res->p_sys->segment;

    if (conn != NULL && segment != 0)
        xcb_shm_detach (conn, segment);
    shmdt (res->p->p_pixels);
#else
    free (res->p->p_pixels);
#endif
}
예제 #5
0
X11BufferSurface::~X11BufferSurface()
{
	if(active_) warning("ny::~X11BufferSurface: there is still an active BufferGuard");
	if(gc_) xcb_free_gc(&xConnection(), gc_);

	if(shmseg_)
	{
		xcb_shm_detach(&xConnection(), shmseg_);
		shmdt(data_);
		shmctl(shmid_, IPC_RMID, 0);
	}
}
예제 #6
0
파일: x11.c 프로젝트: Annovae/vlc
static void ResetPictures (vout_display_t *vd)
{
    vout_display_sys_t *sys = vd->sys;

    if (!sys->pool)
        return;

    if (sys->seg_base != 0)
        for (unsigned i = 0; i < MAX_PICTURES; i++)
            xcb_shm_detach (sys->conn, sys->seg_base + i);

    picture_pool_Delete (sys->pool);
    sys->pool = NULL;
}
예제 #7
0
BufferGuard X11BufferSurface::buffer()
{
	if(active_)
		throw std::logic_error("ny::X11BufferSurface::buffer: there is already a BufferGuard");

	//check if resize is needed
	auto size = windowContext().size();
	auto bpp = imageDataFormatSize(format_); //bytes per pixel (XXX NOT bits!)
	auto newBytes = size.x * size.y * bpp; //the needed size
	if(newBytes > byteSize_)
	{
		//we alloc more than is really needed because this will
		//speed up (especially the shm version) resizes. We don't have to reallocated
		//every time the window is resized and redrawn for the cost of higher memory
		//consumption
		byteSize_ = newBytes * 4;

		if(shm_)
		{
			if(shmseg_)
			{
				xcb_shm_detach(&xConnection(), shmseg_);
				shmdt(data_);
				shmctl(shmid_, IPC_RMID, 0);
			}
			else
			{
				shmseg_ = xcb_generate_id(&xConnection());
			}


			shmid_ = shmget(IPC_PRIVATE, byteSize_, IPC_CREAT | 0777);
			data_ = static_cast<uint8_t*>(shmat(shmid_, 0, 0));
			shmseg_ = xcb_generate_id(&xConnection());
			xcb_shm_attach(&xConnection(), shmseg_, shmid_, 0);
		}
		else
		{
			ownedBuffer_ = std::make_unique<uint8_t[]>(byteSize_);
			data_ = ownedBuffer_.get();
		}
	}

	size_ = size;
	active_ = true;

	return {*this, {data_, {size_.x, size_.y}, format_, size_.x * bpp}};
}
예제 #8
0
void ZLEwlViewWidget::resize(int w, int h) {
	if(w == this->w && h == this->h)
		return;

	this->w = w;
	this->h = h;

	xcb_shm_detach(connection, shminfo.shmseg);
	shmdt(im->data);
	xcb_image_destroy(im);

	xcb_shm_query_version_reply_t *rep_shm;

	rep_shm = xcb_shm_query_version_reply (connection,
			xcb_shm_query_version (connection),
			NULL);
	if(rep_shm) {
		xcb_image_format_t format;
		int shmctl_status;

		if (rep_shm->shared_pixmaps &&
				(rep_shm->major_version > 1 || rep_shm->minor_version > 0))
			format = (xcb_image_format_t)rep_shm->pixmap_format;
		else
			format = (xcb_image_format_t)0;

		uint8_t depth = xcb_aux_get_depth (connection, screen);
		im = xcb_image_create_native (connection, w, h,
				format, depth, NULL, ~0, NULL);
		assert(im);

		shminfo.shmid = shmget (IPC_PRIVATE,
				im->stride*im->height,
				IPC_CREAT | 0777);
		assert(shminfo.shmid != -1);
		shminfo.shmaddr = (uint8_t*)shmat (shminfo.shmid, 0, 0);
		assert(shminfo.shmaddr);
		im->data = shminfo.shmaddr;

		shminfo.shmseg = xcb_generate_id (connection);
		xcb_shm_attach (connection, shminfo.shmseg,
				shminfo.shmid, 0);
		shmctl_status = shmctl(shminfo.shmid, IPC_RMID, 0);
		assert(shmctl_status != -1);
		free (rep_shm);
	}
}
예제 #9
0
void QXcbShmImage::destroy()
{
    const int segmentSize = m_xcb_image ? (m_xcb_image->stride * m_xcb_image->height) : 0;
    if (segmentSize && m_shm_info.shmaddr)
        Q_XCB_CALL(xcb_shm_detach(xcb_connection(), m_shm_info.shmseg));

    xcb_image_destroy(m_xcb_image);

    if (segmentSize) {
        if (m_shm_info.shmaddr) {
            shmdt(m_shm_info.shmaddr);
            shmctl(m_shm_info.shmid, IPC_RMID, 0);
        } else {
            free(m_xcb_image->data);
        }
    }

    if (m_gc)
        Q_XCB_CALL(xcb_free_gc(xcb_connection(), m_gc));
}
예제 #10
0
파일: render.c 프로젝트: mstorsjo/vlc
static void PictureDetach(vout_display_t *vd)
{
    vout_display_sys_t *sys = vd->sys;

    xcb_shm_detach(sys->conn, sys->segment);
}
예제 #11
0
파일: x11.c 프로젝트: Annovae/vlc
/**
 * Return a direct buffer
 */
static picture_pool_t *Pool (vout_display_t *vd, unsigned requested_count)
{
    vout_display_sys_t *sys = vd->sys;
    (void)requested_count;

    if (sys->pool)
        return sys->pool;

    vout_display_place_t place;

    vout_display_PlacePicture (&place, &vd->source, vd->cfg, false);

    /* */
    const uint32_t values[] = { place.x, place.y, place.width, place.height };
    xcb_configure_window (sys->conn, sys->window,
                          XCB_CONFIG_WINDOW_X | XCB_CONFIG_WINDOW_Y |
                          XCB_CONFIG_WINDOW_WIDTH | XCB_CONFIG_WINDOW_HEIGHT,
                          values);

    picture_t *pic = picture_NewFromFormat (&vd->fmt);
    if (!pic)
        return NULL;

    assert (pic->i_planes == 1);

    picture_resource_t res = {
       .p = {
           [0] = {
               .i_lines = pic->p->i_lines,
               .i_pitch = pic->p->i_pitch,
           },
       },
    };
    picture_Release (pic);

    unsigned count;
    picture_t *pic_array[MAX_PICTURES];
    const size_t size = res.p->i_pitch * res.p->i_lines;
    for (count = 0; count < MAX_PICTURES; count++)
    {
        xcb_shm_seg_t seg = (sys->seg_base != 0) ? (sys->seg_base + count) : 0;

        if (XCB_picture_Alloc (vd, &res, size, sys->conn, seg))
            break;
        pic_array[count] = XCB_picture_NewFromResource (&vd->fmt, &res);
        if (unlikely(pic_array[count] == NULL))
        {
            if (seg != 0)
                xcb_shm_detach (sys->conn, seg);
            break;
        }
    }
    xcb_flush (sys->conn);

    if (count == 0)
        return NULL;

    sys->pool = picture_pool_New (count, pic_array);
    if (unlikely(sys->pool == NULL))
        while (count > 0)
            picture_Release(pic_array[--count]);
    return sys->pool;
}
예제 #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);
    }
}