uint32_t _cairo_xcb_connection_shm_attach (cairo_xcb_connection_t *connection, uint32_t id, cairo_bool_t readonly) { uint32_t segment = _cairo_xcb_connection_get_xid (connection); assert (connection->flags & CAIRO_XCB_HAS_SHM); xcb_shm_attach (connection->xcb_connection, segment, id, readonly); return segment; }
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); } }
ZLEwlViewWidget::ZLEwlViewWidget(ZLApplication *application, ZLView::Angle initialAngle) : ZLViewWidget(initialAngle) { myApplication = application; w = 600; h = 800; xcb_screen_iterator_t screen_iter; const xcb_setup_t *setup; xcb_generic_event_t *e; xcb_generic_error_t *error; xcb_void_cookie_t cookie_window; xcb_void_cookie_t cookie_map; uint32_t mask; uint32_t values[2]; int screen_number; uint8_t is_hand = 0; xcb_rectangle_t rect_coord = { 0, 0, 600, 800}; /* getting the connection */ connection = xcb_connect (NULL, &screen_number); if (xcb_connection_has_error(connection)) { fprintf (stderr, "ERROR: can't connect to an X server\n"); exit(-1); } screen = xcb_aux_get_screen (connection, screen_number); gc = xcb_generate_id (connection); mask = XCB_GC_FOREGROUND | XCB_GC_GRAPHICS_EXPOSURES; values[0] = screen->black_pixel; values[1] = 0; /* no graphics exposures */ xcb_create_gc (connection, gc, screen->root, mask, values); bgcolor = xcb_generate_id (connection); mask = XCB_GC_FOREGROUND | XCB_GC_GRAPHICS_EXPOSURES; values[0] = screen->white_pixel; values[1] = 0; /* no graphics exposures */ xcb_create_gc (connection, bgcolor, screen->root, mask, values); /* creating the window */ window = xcb_generate_id(connection); mask = XCB_CW_BACK_PIXEL | XCB_CW_EVENT_MASK; values[0] = screen->white_pixel; values[1] = XCB_EVENT_MASK_KEY_PRESS | XCB_EVENT_MASK_KEY_RELEASE | XCB_EVENT_MASK_BUTTON_PRESS | XCB_EVENT_MASK_EXPOSURE | XCB_EVENT_MASK_POINTER_MOTION | XCB_EVENT_MASK_VISIBILITY_CHANGE | XCB_EVENT_MASK_STRUCTURE_NOTIFY | XCB_EVENT_MASK_FOCUS_CHANGE | XCB_EVENT_MASK_PROPERTY_CHANGE; uint8_t depth = xcb_aux_get_depth (connection, screen); xcb_create_window(connection, depth, window, screen->root, 0, 0, 600, 800, 0, XCB_WINDOW_CLASS_INPUT_OUTPUT, screen->root_visual, mask, values); rect = xcb_generate_id (connection); xcb_create_pixmap (connection, depth, rect, window, 600, 800); xcb_map_window(connection, window); xcb_colormap_t colormap; colormap = screen->default_colormap; xcb_alloc_color_reply_t *rep; rep = xcb_alloc_color_reply (connection, xcb_alloc_color (connection, colormap, 0, 0, 0), NULL); pal_[0] = rep->pixel; free(rep); rep = xcb_alloc_color_reply (connection, xcb_alloc_color (connection, colormap, 0x55<<8, 0x55<<8, 0x55<<8), NULL); pal_[1] = rep->pixel; free(rep); rep = xcb_alloc_color_reply (connection, xcb_alloc_color (connection, colormap, 0xaa<<8, 0xaa<<8, 0xaa<<8), NULL); pal_[2] = rep->pixel; free(rep); rep = xcb_alloc_color_reply (connection, xcb_alloc_color (connection, colormap, 0xff<<8, 0xff<<8, 0xff<<8), NULL); pal_[3] = rep->pixel; free(rep); pal = pal_; 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; im = xcb_image_create_native (connection, 600, 800, 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); } xcb_flush(connection); }
void krad_x11_enable_capture (krad_x11_t *x11, uint32_t window_id) { xcb_get_geometry_reply_t *geo; xcb_query_tree_reply_t *tree; xcb_translate_coordinates_cookie_t translateCookie; xcb_translate_coordinates_reply_t *trans; geo = xcb_get_geometry_reply (x11->connection, xcb_get_geometry (x11->connection, window_id), NULL); if (geo == NULL) { window_id = 0; } else { tree = xcb_query_tree_reply (x11->connection, xcb_query_tree (x11->connection, window_id), NULL); if (tree == NULL) { window_id = 0; free (geo); } else { translateCookie = xcb_translate_coordinates (x11->connection, window_id, x11->screen->root, geo->x, geo->y); trans = xcb_translate_coordinates_reply (x11->connection, translateCookie, NULL); if (trans == NULL) { window_id = 0; free (tree); free (geo); } else { x11->width = geo->width; x11->height = geo->height; x11->x = trans->dst_x - geo->x; x11->y = trans->dst_y - geo->y; free (trans); free (tree); free (geo); } } } if (window_id == 0) { x11->width = x11->screen_width; x11->height = x11->screen_height; x11->window = x11->screen->root; } //printf ("capture width %d height %d x %d y %d\n", // x11->width, x11->height, x11->x, x11->y); x11->img = xcb_image_create_native (x11->connection, x11->width, x11->height, XCB_IMAGE_FORMAT_Z_PIXMAP, x11->screen_bit_depth, 0, ~0, 0); if (!x11->img) { exit (15); } x11->stride = x11->img->stride; x11->shminfo.shmid = shmget (IPC_PRIVATE, x11->img->stride * x11->img->height, (IPC_CREAT | 0666)); if (x11->shminfo.shmid == (uint32_t)-1) { xcb_image_destroy (x11->img); failfast ("shminfo fail"); } x11->shminfo.shmaddr = shmat (x11->shminfo.shmid, 0, 0); x11->img->data = x11->shminfo.shmaddr; if (x11->img->data == (uint8_t *)-1) { xcb_image_destroy (x11->img); failfast ("xcb image fail"); } x11->shminfo.shmseg = xcb_generate_id (x11->connection); xcb_shm_attach (x11->connection, x11->shminfo.shmseg, x11->shminfo.shmid, 0); x11->capture_enabled = 1; }
/** * 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); } }