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); }
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)); }
/** * 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 }
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); } }
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; }
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}}; }
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); } }
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)); }
static void PictureDetach(vout_display_t *vd) { vout_display_sys_t *sys = vd->sys; xcb_shm_detach(sys->conn, sys->segment); }
/** * 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; }
/** * 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); } }