static void swrastGetImageShm(__DRIdrawable * read, int x, int y, int w, int h, int shmid, void *loaderPrivate) { struct drisw_drawable *prp = loaderPrivate; __GLXDRIdrawable *pread = &(prp->base); Display *dpy = pread->psc->dpy; Drawable readable; XImage *ximage; if (!prp->ximage || shmid != prp->shminfo.shmid) { if (!XCreateDrawable(prp, shmid, dpy)) return; } readable = pread->xDrawable; ximage = prp->ximage; ximage->data = prp->shminfo.shmaddr; /* no offset */ ximage->width = w; ximage->height = h; ximage->bytes_per_line = bytes_per_line(w * ximage->bits_per_pixel, 32); XShmGetImage(dpy, readable, ximage, x, y, ~0L); }
static void pixel_tests(struct test *t, int reps, int sets, enum target target) { struct test_target tt; XImage image; uint32_t *cells = malloc(t->real.width*t->real.height*4); struct { uint16_t x, y; } *pixels = malloc(reps*sizeof(*pixels)); int r, s; test_target_create_render(&t->real, target, &tt); printf("Testing setting of single pixels (%s): ", test_target_name(target)); fflush(stdout); for (s = 0; s < sets; s++) { for (r = 0; r < reps; r++) { int x = rand() % (tt.width - 1); int y = rand() % (tt.height - 1); uint32_t fg = rand(); fill_rect(&t->real, tt.draw, GXcopy, x, y, 1, 1, fg); pixels[r].x = x; pixels[r].y = y; cells[y*tt.width+x] = fg; } test_init_image(&image, &t->real.shm, tt.format, 1, 1); for (r = 0; r < reps; r++) { uint32_t x = pixels[r].x; uint32_t y = pixels[r].y; uint32_t result; XShmGetImage(t->real.dpy, tt.draw, &image, x, y, AllPlanes); result = *(uint32_t *)image.data; if (!pixel_equal(image.depth, result, cells[y*tt.width+x])) { uint32_t mask = depth_mask(image.depth); die("failed to set pixel (%d,%d) to %08x [%08x], found %08x [%08x] instead\n", x, y, cells[y*tt.width+x] & mask, cells[y*tt.width+x], result & mask, result); } } } printf("passed [%d iterations x %d]\n", reps, sets); test_target_destroy_render(&t->real, &tt); free(pixels); free(cells); }
static int tc_x11source_acquire_image_shm(TCX11Source *handle, uint8_t *data, int maxdata) { int size = -1; Status ret; /* but draw such areas if windows are opaque */ ret = XShmGetImage(handle->dpy, handle->pix, handle->image, 0, 0, AllPlanes); if (!ret || handle->image == NULL || handle->image->data == NULL) { tc_log_error(__FILE__, "cannot get X image (using SHM)"); } else { size = (int)tc_video_frame_size(handle->image->width, handle->image->height, handle->out_fmt); if (size <= maxdata) { tcv_convert(handle->tcvhandle, handle->image->data, data, handle->image->width, handle->image->height, IMG_BGRA32, handle->conv_fmt); } else { size = 0; } } return size; }
// the bitmap must be wholly contained in the source during a GetImage int BC_Bitmap::read_drawable(Drawable &pixmap, int source_x, int source_y) { if(use_shm) XShmGetImage(top_level->display, pixmap, ximage[current_ringbuffer], source_x, source_y, 0xffffffff); else XGetSubImage(top_level->display, pixmap, source_x, source_y, w, h, 0xffffffff, ZPixmap, ximage[current_ringbuffer], 0, 0); return 0; }
static char* captureScreenShotX(int* pwidth, int* pheight, screenshot_data* sdata) { Window root; // Atom atom_rotation; sdata->dpy = XOpenDisplay(NULL); if(unlikely(sdata->dpy == NULL)) { // XOpenDisplay failed! return NULL; } *pwidth = DisplayWidth(sdata->dpy, DefaultScreen(sdata->dpy)); *pheight = DisplayHeight(sdata->dpy, DefaultScreen(sdata->dpy)); root = RootWindow(sdata->dpy, DefaultScreen(sdata->dpy)); sdata->ximage = XShmCreateImage(sdata->dpy, DefaultVisualOfScreen (DefaultScreenOfDisplay (sdata->dpy)), 24, ZPixmap, NULL, &sdata->x_shm_info, (unsigned int)*pwidth, (unsigned int)*pheight); if(sdata->ximage != NULL) { sdata->x_shm_info.shmid = shmget(IPC_PRIVATE, sdata->ximage->bytes_per_line * sdata->ximage->height, IPC_CREAT | 0777); sdata->x_shm_info.shmaddr = sdata->ximage->data = shmat(sdata->x_shm_info.shmid, 0, 0); sdata->x_shm_info.readOnly = False; if(XShmAttach(sdata->dpy, &sdata->x_shm_info)) { if(XShmGetImage(sdata->dpy, root, sdata->ximage, 0, 0, AllPlanes)) { XSync (sdata->dpy, False); return sdata->ximage->data; } else { ; // XShmGetImage failed ! } XShmDetach (sdata->dpy, &sdata->x_shm_info); } else { ; // XShmAttach failed ! } shmdt (sdata->x_shm_info.shmaddr); shmctl (sdata->x_shm_info.shmid, IPC_RMID, NULL); XDestroyImage(sdata->ximage); sdata->ximage = NULL; } else { ; // XShmCreateImage failed! } return NULL; }
Image<ColorRgb> & X11Grabber::grab() { updateScreenDimensions(); if (_XRenderAvailable && !_useXGetImage) { XRenderComposite( _x11Display, // *dpy, PictOpSrc, // op, _srcPicture, // src None, // mask _dstPicture, // dst _cropLeft, // src_x _cropTop, // src_y 0, // mask_x 0, // mask_y 0, // dst_x 0, // dst_y _croppedWidth, // width _croppedHeight); // height XSync(_x11Display, False); if (_XShmAvailable) { XShmGetImage(_x11Display, _pixmap, _xImage, 0, 0, AllPlanes); } else { _xImage = XGetImage(_x11Display, _pixmap, 0, 0, _croppedWidth, _croppedHeight, AllPlanes, ZPixmap); } } else { if (_XShmAvailable && !_useXGetImage) { XShmGetImage(_x11Display, _window, _xImage, _cropLeft, _cropTop, AllPlanes); } else { _xImage = XGetImage(_x11Display, _window, _cropLeft, _cropTop, _croppedWidth, _croppedHeight, AllPlanes, ZPixmap); } } if (_xImage == nullptr) { std::cerr << "X11GRABBER ERROR: Grab failed" << std::endl; return _image; } _imageResampler.processImage(reinterpret_cast<const uint8_t *>(_xImage->data), _xImage->width, _xImage->height, _xImage->bytes_per_line, PIXELFORMAT_BGR32, _image); return _image; }
int refresh_image(Display *d, int x, int y, int radius) { /* if we are near the border, we capture more than just the area around the cursor */ int w = DisplayWidth(d, DefaultScreen(d)); int h = DisplayHeight(d, DefaultScreen(d)); img_offset.x = VAL_BETWEEN(radius, w-1-2*radius, x); img_offset.y = VAL_BETWEEN(radius, h-1-2*radius, y); int ret = XShmGetImage(d, RootWindow(d, DefaultScreen (d)), img, img_offset.x, img_offset.y, AllPlanes); return ret; }
/** * Grab a frame from x11 (public device demuxer API). * * @param s1 Context from avformat core * @param pkt Packet holding the brabbed frame * @return frame size in bytes */ static int x11grab_read_packet(AVFormatContext *s1, AVPacket *pkt) { struct x11_grab *s = s1->priv_data; Display *dpy = s->dpy; XImage *image = s->image; int x_off = s->x_off; int y_off = s->y_off; int64_t curtime, delay; struct timespec ts; /* Calculate the time of the next frame */ s->time_frame += INT64_C(1000000); /* wait based on the frame rate */ for(;;) { curtime = av_gettime(); delay = s->time_frame * av_q2d(s->time_base) - curtime; if (delay <= 0) { if (delay < INT64_C(-1000000) * av_q2d(s->time_base)) { s->time_frame += INT64_C(1000000); } break; } ts.tv_sec = delay / 1000000; ts.tv_nsec = (delay % 1000000) * 1000; nanosleep(&ts, NULL); } if (av_new_packet(pkt, s->frame_size) < 0) { return AVERROR(EIO); } pkt->pts = curtime; if(s->use_shm) { if (!XShmGetImage(dpy, RootWindow(dpy, DefaultScreen(dpy)), image, x_off, y_off, AllPlanes)) { av_log (s1, AV_LOG_INFO, "XShmGetImage() failed\n"); } } else { if (!xget_zpixmap(dpy, RootWindow(dpy, DefaultScreen(dpy)), image, x_off, y_off)) { av_log (s1, AV_LOG_INFO, "XGetZPixmap() failed\n"); } } if(!s->nomouse){ paint_mouse_pointer(image, s); } /* XXX: avoid memcpy */ memcpy(pkt->data, image->data, s->frame_size); return s->frame_size; }
void DoShmGetImage(XParms xp, Parms p, int reps) { int i, size; XSegment *sa, *sb; size = p->special; shm_image.width = size; shm_image.height = size; for (sa = segsa, sb = segsb, i = 0; i != reps; i++, sa++, sb++) { /* compute offsets into image data? */ XShmGetImage(xp->d, xp->w, &shm_image, sa->x1, sa->y1, xp->planemask); XShmGetImage(xp->d, xp->w, &shm_image, sa->x2, sa->y2, xp->planemask); XShmGetImage(xp->d, xp->w, &shm_image, sb->x2, sb->y2, xp->planemask); XShmGetImage(xp->d, xp->w, &shm_image, sb->x1, sb->y1, xp->planemask); CheckAbort (); } }
Bool get_xshm_image (Display *dpy, Drawable d, XImage *image, int x, int y, unsigned long plane_mask, XShmSegmentInfo *shm_info) { #ifdef HAVE_XSHM_EXTENSION if (shm_info->shmid != -1) { return XShmGetImage (dpy, d, image, x, y, plane_mask); } #endif /* HAVE_XSHM_EXTENSION */ return XGetSubImage (dpy, d, x, y, image->width, image->height, plane_mask, image->format, image, 0, 0) != NULL; }
// gcc -Wall x11shot2.c -o x11shot2 -lX11 -lX11ext -lpng;./x11shot2 <wid> >/tmp/screenshot.png int main(int argc,char* argv[]){ if(argc<2){ fprintf(stderr, "usage:x11shot2 <wid> >/tmp/screenshot.png\n"); exit(1); } int wid=(int)strtol(argv[1], NULL, 0); sscanf(argv[1], "%x", &wid); XShmSegmentInfo shminfo; int x_off=0,y_off=0; Display *dpy=XOpenDisplay(getenv("DISPLAY")); XImage *image; XWindowAttributes wattr; if (dpy == NULL) { fprintf(stderr, "Cannot open display\n"); exit(1); } XGetWindowAttributes(dpy,wid,&wattr); fprintf(stderr,"wid:0x%x wattr x:%d y:%d w:%d h:%d begin capture\n" ,wid ,wattr.x,wattr.y ,wattr.width,wattr.height); if(!XShmQueryExtension(dpy)){ fprintf(stderr, "can't not use shm!\n"); exit(1); } int scr = XDefaultScreen(dpy); image = XShmCreateImage(dpy, DefaultVisual(dpy, scr), DefaultDepth(dpy, scr), ZPixmap, NULL, &shminfo, wattr.width,wattr.height); shminfo.shmid = shmget(IPC_PRIVATE, image->bytes_per_line * image->height, IPC_CREAT|0777); shminfo.shmaddr = image->data = shmat(shminfo.shmid, 0, 0); shminfo.readOnly = False; if (!XShmAttach(dpy, &shminfo)) { fprintf(stderr, "Fatal: Failed to attach shared memory!\n"); exit(1); } if(!XShmGetImage(dpy,wid,image,x_off,y_off,AllPlanes)) { die("Can't get image"); } pngstdout(image); XDestroyImage(image); return 0; };
void glDispyWidget::paintGL() { //http://stackoverflow.com/questions/6512543/obtaining-full-desktop-screenshot-from-the-gpu //http://forum.openframeworks.cc/index.php?topic=3017.0 if(useShm) { XShmGetImage(xDisplay, rootWindow, img, 0, 0, AllPlanes); } else { //XImage *img = XGetImage(display,root,0,0,400,400,XAllPlanes(),ZPixmap); img = XGetImage(xDisplay,rootWindow,0,0,xDisplayWidth,xDisplayHeight,XAllPlanes(),ZPixmap); } if (img == NULL) { qDebug() << "error getting display data"; return; } qDebug() << img->width; /*glClear(GL_COLOR_BUFFER_BIT); glColor3f(1,0,0); glBegin(GL_POLYGON); glVertex2f(0,0); glVertex2f(100,500); glVertex2f(500,100); glEnd(); */ //see http://www.opengl.org/wiki/Programming_OpenGL_in_Linux:_Creating_a_texture_from_a_Pixmap //generate a texture from the Ximage glBindTexture(GL_TEXTURE_2D, texture); /*GL_EXT extension test glXBindTexImageEXT (display, glxpixmap, GLX_FRONT_LEFT_EXT, NULL); */ /*working code */ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, xDisplayWidth,xDisplayHeight, 0, GL_BGRA, GL_UNSIGNED_BYTE, (void*)(&(img->data[0]))); glEnable(GL_TEXTURE_2D); //glEnable(GL_MULTISAMPLE); //glEnable(GL_CULL_FACE); glColor4f(1.0f, 1.0f, 1.0f, 1.0f); glBegin(GL_QUADS); glTexCoord2f(0.0f, 0.0f); glVertex3f(0.f, 0.f, 0.f); glTexCoord2f(1.0f, 0.0f); glVertex3f(width(), 0.f, 0.f); glTexCoord2f(1.0f, 1.0f); glVertex3f(width(), height()-2, 0); glTexCoord2f(0.0f, 1.0f); glVertex3f(0.f, height(), 0.f); glEnd(); //render_fbo->toImage().save("test.png"); }
int fbx_read(fbx_struct *fb, int x_, int y_) { int x, y; #ifdef _WIN32 fbx_gc gc; #endif if(!fb) _throw("Invalid argument"); x=x_>=0? x_:0; y=y_>=0? y_:0; #ifdef _WIN32 if(!fb->hmdc || fb->width<=0 || fb->height<=0 || !fb->bits || !fb->wh) _throw("Not initialized"); _w32(gc=GetDC(fb->wh)); _w32(BitBlt(fb->hmdc, 0, 0, fb->width, fb->height, gc, x, y, SRCCOPY)); _w32(ReleaseDC(fb->wh, gc)); return 0; #else if(!fb->wh.dpy || !fb->wh.d || !fb->xi || !fb->bits) _throw("Not initialized"); #ifdef USESHM if(!fb->xattach && fb->shm) { _x11(XShmAttach(fb->wh.dpy, &fb->shminfo)); fb->xattach=1; } #endif #ifdef USESHM if(fb->shm) { _x11(XShmGetImage(fb->wh.dpy, fb->wh.d, fb->xi, x, y, AllPlanes)); } else #endif { _x11(XGetSubImage(fb->wh.dpy, fb->wh.d, x, y, fb->width, fb->height, AllPlanes, ZPixmap, fb->xi, 0, 0)); } return 0; #endif finally: return -1; }
RXImage* RGetXImage(RContext *context, Drawable d, int x, int y, unsigned width, unsigned height) { RXImage *ximg = NULL; #ifdef XSHM if (context->attribs->use_shared_memory && 0) { ximg = RCreateXImage(context, getDepth(context->dpy, d), width, height); if (ximg && !ximg->is_shared) { RDestroyXImage(context, ximg); ximg = NULL; } if (ximg) { XShmGetImage(context->dpy, d, ximg->image, x, y, AllPlanes); } } if (!ximg) { ximg = malloc(sizeof(RXImage)); if (!ximg) { RErrorCode = RERR_NOMEMORY; return NULL; } ximg->is_shared = 0; ximg->image = XGetImage(context->dpy, d, x, y, width, height, AllPlanes, ZPixmap); } return ximg; #else /* !XSHM */ ximg = malloc(sizeof(RXImage)); if (!ximg) { RErrorCode = RERR_NOMEMORY; return NULL; } ximg->image = XGetImage(context->dpy, d, x, y, width, height, AllPlanes, ZPixmap); return ximg; #endif /* !XSHM */ }
/** * Prepare the capture data */ static void xshm_video_tick(void *vptr, float seconds) { UNUSED_PARAMETER(seconds); XSHM_DATA(vptr); if (!data->xshm) return; obs_enter_graphics(); XShmGetImage(data->dpy, XRootWindowOfScreen(data->screen), data->xshm->image, data->x_org, data->y_org, AllPlanes); gs_texture_set_image(data->texture, (void *) data->xshm->image->data, data->width * 4, false); xcursor_tick(data->cursor); obs_leave_graphics(); }
int video_getframe(uint8_t *y, uint8_t *u, uint8_t *v, uint16_t width, uint16_t height) { if(utox_v4l_fd == -1) { static uint64_t lasttime; uint64_t t = get_time(); if(t - lasttime >= (uint64_t)1000 * 1000 * 1000 / 24) { XShmGetImage(deskdisplay,RootWindow(deskdisplay, deskscreen), screen_image, video_x, video_y, AllPlanes); if (width != video_width || height != video_height) { debug("uTox:\twidth/height mismatch %u %u != %u %u\n", width, height, screen_image->width, screen_image->height); return 0; } bgrxtoyuv420(y, u, v, (uint8_t*)screen_image->data, screen_image->width, screen_image->height); lasttime = t; return 1; } return 0; } return v4l_getframe(y, u, v, width, height); }
int BC_Capture::capture_frame(VFrame *frame, int &x1, int &y1) { if(!display) return 1; if(x1 < 0) x1 = 0; if(y1 < 0) y1 = 0; if(x1 > get_top_w() - w) x1 = get_top_w() - w; if(y1 > get_top_h() - h) y1 = get_top_h() - h; // Read the raw data if(use_shm) XShmGetImage(display, rootwin, ximage, x1, y1, 0xffffffff); else XGetSubImage(display, rootwin, x1, y1, w, h, 0xffffffff, ZPixmap, ximage, 0, 0); BC_WindowBase::get_cmodels()->transfer(frame->get_rows(), row_data, frame->get_y(), frame->get_u(), frame->get_v(), 0, 0, 0, 0, 0, w, h, 0, 0, frame->get_w(), frame->get_h(), bitmap_color_model, frame->get_color_model(), 0, frame->get_w(), w); return 0; }
void ga_xwin_capture(char *buf, int buflen, struct gaRect *rect) { if(XShmGetImage(display, rootWindow, image, 0, 0, XAllPlanes()) == 0) { ga_error("FATAL: XShmGetImage failed.\n"); exit(-1); } if(rect == NULL) { bcopy(image->data, buf, buflen); } else { int i; char *src, *dst; src = ((char *) image->data); src += image->bytes_per_line * rect->top; src += RGBA_SIZE * rect->left; dst = (char*) buf; // for(i = 0; i < rect->height; i++) { bcopy(src, dst, rect->linesize); src += image->bytes_per_line; dst += rect->linesize; } } return; }
/** * Grab a frame from x11 (public device demuxer API). * * @param s1 Context from avformat core * @param pkt Packet holding the brabbed frame * @return frame size in bytes */ static int x11grab_read_packet(AVFormatContext *s1, AVPacket *pkt) { struct x11_grab *s = s1->priv_data; Display *dpy = s->dpy; XImage *image = s->image; int x_off = s->x_off; int y_off = s->y_off; int screen; Window root; int follow_mouse = s->follow_mouse; int64_t curtime, delay; struct timespec ts; /* Calculate the time of the next frame */ s->time_frame += INT64_C(1000000); /* wait based on the frame rate */ for(;;) { curtime = av_gettime(); delay = s->time_frame * av_q2d(s->time_base) - curtime; if (delay <= 0) { if (delay < INT64_C(-1000000) * av_q2d(s->time_base)) { s->time_frame += INT64_C(1000000); } break; } ts.tv_sec = delay / 1000000; ts.tv_nsec = (delay % 1000000) * 1000; nanosleep(&ts, NULL); } av_init_packet(pkt); pkt->data = image->data; pkt->size = s->frame_size; pkt->pts = curtime; screen = DefaultScreen(dpy); root = RootWindow(dpy, screen); if (follow_mouse) { int screen_w, screen_h; int pointer_x, pointer_y, _; Window w; screen_w = DisplayWidth(dpy, screen); screen_h = DisplayHeight(dpy, screen); XQueryPointer(dpy, root, &w, &w, &pointer_x, &pointer_y, &_, &_, &_); if (follow_mouse == -1) { // follow the mouse, put it at center of grabbing region x_off += pointer_x - s->width / 2 - x_off; y_off += pointer_y - s->height / 2 - y_off; } else { // follow the mouse, but only move the grabbing region when mouse // reaches within certain pixels to the edge. if (pointer_x > x_off + s->width - follow_mouse) { x_off += pointer_x - (x_off + s->width - follow_mouse); } else if (pointer_x < x_off + follow_mouse) x_off -= (x_off + follow_mouse) - pointer_x; if (pointer_y > y_off + s->height - follow_mouse) { y_off += pointer_y - (y_off + s->height - follow_mouse); } else if (pointer_y < y_off + follow_mouse) y_off -= (y_off + follow_mouse) - pointer_y; } // adjust grabbing region position if it goes out of screen. s->x_off = x_off = FFMIN(FFMAX(x_off, 0), screen_w - s->width); s->y_off = y_off = FFMIN(FFMAX(y_off, 0), screen_h - s->height); if (s->show_region && s->region_win) XMoveWindow(dpy, s->region_win, s->x_off - REGION_WIN_BORDER, s->y_off - REGION_WIN_BORDER); } if (s->show_region) { if (s->region_win) { XEvent evt; // clean up the events, and do the initinal draw or redraw. for (evt.type = NoEventMask; XCheckMaskEvent(dpy, ExposureMask | StructureNotifyMask, &evt); ); if (evt.type) x11grab_draw_region_win(s); } else { x11grab_region_win_init(s); } } if(s->use_shm) { if (!XShmGetImage(dpy, root, image, x_off, y_off, AllPlanes)) { av_log (s1, AV_LOG_INFO, "XShmGetImage() failed\n"); } } else { if (!xget_zpixmap(dpy, root, image, x_off, y_off)) { av_log (s1, AV_LOG_INFO, "XGetZPixmap() failed\n"); } } if (s->draw_mouse) { paint_mouse_pointer(image, s); } return s->frame_size; }
int BC_XShmImage::read_drawable(Drawable &pixmap, int source_x, int source_y) { XShmGetImage(top_level->display, pixmap, ximage, source_x, source_y, 0xffffffff); return 0; }
int X11Grabber::grabFrame(Image<ColorRgb> & image) { if (_XRenderAvailable && !_useXGetImage) { double scale_x = static_cast<double>(_windowAttr.width / _horizontalDecimation) / static_cast<double>(_windowAttr.width); double scale_y = static_cast<double>(_windowAttr.height / _verticalDecimation) / static_cast<double>(_windowAttr.height); double scale = std::min(scale_y, scale_x); _transform = { { { XDoubleToFixed(1), XDoubleToFixed(0), XDoubleToFixed(0) }, { XDoubleToFixed(0), XDoubleToFixed(1), XDoubleToFixed(0) }, { XDoubleToFixed(0), XDoubleToFixed(0), XDoubleToFixed(scale) } } }; XRenderSetPictureTransform (_x11Display, _srcPicture, &_transform); XRenderComposite( _x11Display, // dpy PictOpSrc, // op _srcPicture, // src None, // mask _dstPicture, // dst _cropLeft / _horizontalDecimation, // src_x _cropLeft _cropTop / _verticalDecimation, // src_y _cropTop 0, // mask_x 0, // mask_y 0, // dst_x 0, // dst_y _croppedWidth, // width _croppedHeight); // height XSync(_x11Display, False); if (_XShmAvailable) { XShmGetImage(_x11Display, _pixmap, _xImage, 0, 0, AllPlanes); } else { _xImage = XGetImage(_x11Display, _pixmap, 0, 0, _croppedWidth, _croppedHeight, AllPlanes, ZPixmap); } } else { if (_XShmAvailable && !_useXGetImage) { XShmGetImage(_x11Display, _window, _xImage, _cropLeft, _cropTop, AllPlanes); } else { _xImage = XGetImage(_x11Display, _window, _cropLeft, _cropTop, _croppedWidth, _croppedHeight, AllPlanes, ZPixmap); } } if (_xImage == nullptr) { Error(_log, "Grab Failed!"); return -1; } _imageResampler.processImage(reinterpret_cast<const uint8_t *>(_xImage->data), _xImage->width, _xImage->height, _xImage->bytes_per_line, PIXELFORMAT_BGR32, image); return 0; }
static void area_tests(struct test *t, int reps, int sets, enum target target) { struct test_target tt; XImage image; uint32_t *cells = calloc(sizeof(uint32_t), t->real.width*t->real.height); int r, s, x, y; printf("Testing area sets (%s): ", test_target_name(target)); fflush(stdout); test_target_create_render(&t->real, target, &tt); clear(&t->real, &tt); test_init_image(&image, &t->real.shm, tt.format, tt.width, tt.height); for (s = 0; s < sets; s++) { for (r = 0; r < reps; r++) { int w = rand() % tt.width; int h = rand() % tt.height; int red = rand() % 0xff; int green = rand() % 0xff; int blue = rand() % 0xff; int alpha = rand() % 0xff; x = rand() % (2*tt.width) - tt.width; y = rand() % (2*tt.height) - tt.height; fill_rect(&t->real, tt.picture, PictOpSrc, x, y, w, h, red, green, blue, alpha); if (x < 0) w += x, x = 0; if (y < 0) h += y, y = 0; if (x >= tt.width || y >= tt.height) continue; if (x + w > tt.width) w = tt.width - x; if (y + h > tt.height) h = tt.height - y; if (w <= 0 || h <= 0) continue; pixman_fill(cells, tt.width, 32, x, y, w, h, color(red, green, blue, alpha)); } XShmGetImage(t->real.dpy, tt.draw, &image, 0, 0, AllPlanes); for (y = 0; y < tt.height; y++) { for (x = 0; x < tt.width; x++) { uint32_t result = *(uint32_t *)(image.data + y*image.bytes_per_line + image.bits_per_pixel*x/8); if (!pixel_equal(image.depth, result, cells[y*tt.width+x])) { uint32_t mask; if (image.depth == 32) mask = 0xffffffff; else mask = (1 << image.depth) - 1; die("failed to set pixel (%d,%d) to %08x[%08x], found %08x instead\n", x, y, cells[y*tt.width+x] & mask, cells[y*tt.width+x], result & mask); } } } } printf("passed [%d iterations x %d]\n", reps, sets); test_target_destroy_render(&t->real, &tt); free(cells); }
static void clutter_x11_texture_pixmap_update_area_real (ClutterX11TexturePixmap *texture, gint x, gint y, gint width, gint height) { ClutterX11TexturePixmapPrivate *priv; Display *dpy; XImage *image; char *first_pixel; GError *error = NULL; guint bytes_per_line; char *data; int err_code; char pixel_bpp; gboolean pixel_has_alpha; #if 0 clock_t start_t = clock(); #endif if (!CLUTTER_ACTOR_IS_REALIZED (texture)) return; priv = texture->priv; dpy = clutter_x11_get_default_display(); if (!priv->pixmap) return; if (priv->shminfo.shmid == -1) try_alloc_shm (texture); clutter_x11_trap_x_errors (); if (priv->have_shm) { image = XShmCreateImage(dpy, DefaultVisual(dpy, clutter_x11_get_default_screen()), priv->depth, ZPixmap, NULL, &priv->shminfo, width, height); image->data = priv->shminfo.shmaddr; XShmGetImage (dpy, priv->pixmap, image, x, y, AllPlanes); first_pixel = image->data; } else { if (!priv->image) { priv->image = XGetImage (dpy, priv->pixmap, 0, 0, priv->pixmap_width, priv->pixmap_height, AllPlanes, ZPixmap); if (priv->image) first_pixel = priv->image->data + priv->image->bytes_per_line * y + x * priv->image->bits_per_pixel/8; else { g_warning ("%s: XGetImage() failed", __FUNCTION__); return; } } else { XGetSubImage (dpy, priv->pixmap, x, y, width, height, AllPlanes, ZPixmap, priv->image, x, y); first_pixel = priv->image->data + priv->image->bytes_per_line * y + x * priv->image->bits_per_pixel/8; } image = priv->image; } XSync (dpy, FALSE); if ((err_code = clutter_x11_untrap_x_errors ())) { g_warning ("Failed to get XImage of pixmap: %lx, removing", priv->pixmap); /* safe to assume pixmap has gone away? - therefor reset */ clutter_x11_texture_pixmap_set_pixmap (texture, None); goto free_image_and_return; } if (priv->depth == 24) { bytes_per_line = image->bytes_per_line; data = first_pixel; pixel_bpp = 3; pixel_has_alpha = FALSE; } else if (priv->depth == 16) { bytes_per_line = image->bytes_per_line; data = first_pixel; pixel_bpp = 2; pixel_has_alpha = FALSE; } else if (priv->depth == 32) { bytes_per_line = image->bytes_per_line; data = first_pixel; pixel_bpp = 4; pixel_has_alpha = TRUE; } else goto free_image_and_return; if (!priv->allow_alpha) pixel_has_alpha = FALSE; /* For debugging purposes, un comment to simply generate dummy * pixmap data. (A Green background and Blue cross) */ #if 0 { guint xpos, ypos; if (data_allocated) g_free (data); data_allocated = TRUE; data = g_malloc (width*height*4); bytes_per_line = width *4; for (ypos=0; ypos<height; ypos++) for (xpos=0; xpos<width; xpos++) { char *p = data + width*4*ypos + xpos * 4; guint32 *pixel = (guint32 *)p; if ((xpos > width/2 && xpos <= (width/2) + width/4) || (ypos > height/2 && ypos <= (height/2) + height/4)) *pixel=0xff0000ff; else *pixel=0xff00ff00; } } #endif if (x != 0 || y != 0 || width != priv->pixmap_width || height != priv->pixmap_height) clutter_texture_set_area_from_rgb_data (CLUTTER_TEXTURE (texture), (guint8 *)data, pixel_has_alpha, x, y, width, height, bytes_per_line, pixel_bpp, CLUTTER_TEXTURE_RGB_FLAG_BGR, &error); else clutter_texture_set_from_rgb_data (CLUTTER_TEXTURE (texture), (guint8 *)data, pixel_has_alpha, width, height, bytes_per_line, pixel_bpp, CLUTTER_TEXTURE_RGB_FLAG_BGR, &error); if (error) { g_warning ("Error when uploading from pixbuf: %s", error->message); g_error_free (error); } free_image_and_return: if (priv->have_shm) XFree (image); #if 0 clock_t end_t = clock(); int time = (int)((double)(end_t - start_t) * (1000.0 / CLOCKS_PER_SEC)); g_print("clutter-x11-update-area-real(%d,%d,%d,%d) %d bits - %d ms\n",x,y,width,height,priv->depth,time); #endif }
static void _cogl_texture_pixmap_x11_update_image_texture (CoglTexturePixmapX11 *tex_pixmap) { CoglTexture *tex = COGL_TEXTURE (tex_pixmap); Display *display; Visual *visual; CoglPixelFormat image_format; XImage *image; int src_x, src_y; int x, y, width, height; int bpp; int offset; CoglError *ignore = NULL; _COGL_GET_CONTEXT (ctx, NO_RETVAL); display = cogl_xlib_renderer_get_display (ctx->display->renderer); visual = tex_pixmap->visual; /* If the damage region is empty then there's nothing to do */ if (tex_pixmap->damage_rect.x2 == tex_pixmap->damage_rect.x1) return; x = tex_pixmap->damage_rect.x1; y = tex_pixmap->damage_rect.y1; width = tex_pixmap->damage_rect.x2 - x; height = tex_pixmap->damage_rect.y2 - y; /* We lazily create the texture the first time it is needed in case this texture can be entirely handled using the GLX texture instead */ if (tex_pixmap->tex == NULL) { CoglPixelFormat texture_format; texture_format = (tex_pixmap->depth >= 32 ? COGL_PIXEL_FORMAT_RGBA_8888_PRE : COGL_PIXEL_FORMAT_RGB_888); tex_pixmap->tex = create_fallback_texture (ctx, tex->width, tex->height, texture_format); } if (tex_pixmap->image == NULL) { /* If we also haven't got a shm segment then this must be the first time we've tried to update, so lets try allocating shm first */ if (tex_pixmap->shm_info.shmid == -1) try_alloc_shm (tex_pixmap); if (tex_pixmap->shm_info.shmid == -1) { COGL_NOTE (TEXTURE_PIXMAP, "Updating %p using XGetImage", tex_pixmap); /* We'll fallback to using a regular XImage. We'll download the entire area instead of a sub region because presumably if this is the first update then the entire pixmap is needed anyway and it saves trying to manually allocate an XImage at the right size */ tex_pixmap->image = XGetImage (display, tex_pixmap->pixmap, 0, 0, tex->width, tex->height, AllPlanes, ZPixmap); image = tex_pixmap->image; src_x = x; src_y = y; } else { COGL_NOTE (TEXTURE_PIXMAP, "Updating %p using XShmGetImage", tex_pixmap); /* Create a temporary image using the beginning of the shared memory segment and the right size for the region we want to update. We need to reallocate the XImage every time because there is no XShmGetSubImage. */ image = XShmCreateImage (display, tex_pixmap->visual, tex_pixmap->depth, ZPixmap, NULL, &tex_pixmap->shm_info, width, height); image->data = tex_pixmap->shm_info.shmaddr; src_x = 0; src_y = 0; XShmGetImage (display, tex_pixmap->pixmap, image, x, y, AllPlanes); } } else { COGL_NOTE (TEXTURE_PIXMAP, "Updating %p using XGetSubImage", tex_pixmap); image = tex_pixmap->image; src_x = x; src_y = y; XGetSubImage (display, tex_pixmap->pixmap, x, y, width, height, AllPlanes, ZPixmap, image, x, y); } image_format = _cogl_util_pixel_format_from_masks (visual->red_mask, visual->green_mask, visual->blue_mask, image->depth, image->bits_per_pixel, image->byte_order == LSBFirst); bpp = _cogl_pixel_format_get_bytes_per_pixel (image_format); offset = image->bytes_per_line * src_y + bpp * src_x; _cogl_texture_set_region (tex_pixmap->tex, width, height, image_format, image->bytes_per_line, ((const uint8_t *) image->data) + offset, x, y, 0, /* level */ &ignore); /* If we have a shared memory segment then the XImage would be a temporary one with no data allocated so we can just XFree it */ if (tex_pixmap->shm_info.shmid != -1) XFree (image); memset (&tex_pixmap->damage_rect, 0, sizeof (CoglDamageRectangle)); }
/* Finds NaCl/Chromium shm memory using external handler. * Reply must be in the form PID:file */ struct cache_entry* find_shm(uint64_t paddr, uint64_t sig, size_t length) { struct cache_entry* entry = NULL; /* Find entry in cache */ if (cache[0].paddr == paddr) { entry = &cache[0]; } else if (cache[1].paddr == paddr) { entry = &cache[1]; } else { /* Not found: erase an existing entry. */ entry = &cache[next_entry]; next_entry = (next_entry + 1) % 2; close_mmap(entry); } int try; for (try = 0; try < 2; try++) { /* Check signature */ if (entry->map) { if (*((uint64_t*)entry->map) == sig) return entry; log(1, "Invalid signature, fetching new shm!"); close_mmap(entry); } /* Setup parameters and run command */ char arg1[32], arg2[32]; int c; c = snprintf(arg1, sizeof(arg1), "%08lx", (long)paddr & 0xffffffff); trueorabort(c > 0, "snprintf"); int i, p = 0; for (i = 0; i < 8; i++) { c = snprintf(arg2 + p, sizeof(arg2) - p, "%02x", ((uint8_t*)&sig)[i]); trueorabort(c > 0, "snprintf"); p += c; } char* cmd = "croutonfindnacl"; char* args[] = {cmd, arg1, arg2, NULL}; char buffer[256]; log(2, "Running %s %s %s", cmd, arg1, arg2); c = popen2(cmd, args, NULL, 0, buffer, sizeof(buffer)); if (c <= 0) { error("Error running helper."); return NULL; } buffer[c < sizeof(buffer) ? c : (sizeof(buffer)-1)] = 0; log(2, "Result: %s", buffer); /* Parse PID:file output */ char* cut = strchr(buffer, ':'); if (!cut) { error("No ':' in helper reply: %s.", cut); return NULL; } *cut = 0; char* endptr; long pid = strtol(buffer, &endptr, 10); if(buffer == endptr || *endptr != '\0') { error("Invalid pid: %s", buffer); return NULL; } char* file = cut+1; log(2, "PID:%ld, FILE:%s", pid, file); entry->paddr = paddr; entry->fd = open(file, O_RDWR); if (entry->fd < 0) { error("Cannot open file %s\n", file); return NULL; } entry->length = length; entry->map = mmap(NULL, length, PROT_READ|PROT_WRITE, MAP_SHARED, entry->fd, 0); if (!entry->map) { error("Cannot mmap %s\n", file); close(entry->fd); return NULL; } log(2, "mmap ok %p %zu %d", entry->map, entry->length, entry->fd); } error("Cannot find shm."); return NULL; } /* WebSocket functions */ XImage* img = NULL; XShmSegmentInfo shminfo; /* Writes framebuffer image to websocket/shm */ int write_image(const struct screen* screen) { char reply_raw[FRAMEMAXHEADERSIZE + sizeof(struct screen_reply)]; struct screen_reply* reply = (struct screen_reply*)(reply_raw + FRAMEMAXHEADERSIZE); int refresh = 0; memset(reply_raw, 0, sizeof(reply_raw)); reply->type = 'S'; reply->width = screen->width; reply->height = screen->height; /* Allocate XShmImage */ if (!img || img->width != screen->width || img->height != screen->height) { if (img) { XDestroyImage(img); shmdt(shminfo.shmaddr); shmctl(shminfo.shmid, IPC_RMID, 0); } /* FIXME: Some error checking should happen here... */ img = XShmCreateImage(dpy, DefaultVisual(dpy, 0), 24, ZPixmap, NULL, &shminfo, screen->width, screen->height); trueorabort(img, "XShmCreateImage"); shminfo.shmid = shmget(IPC_PRIVATE, img->bytes_per_line*img->height, IPC_CREAT|0777); trueorabort(shminfo.shmid != -1, "shmget"); shminfo.shmaddr = img->data = shmat(shminfo.shmid, 0, 0); trueorabort(shminfo.shmaddr != (void*)-1, "shmat"); shminfo.readOnly = False; int ret = XShmAttach(dpy, &shminfo); trueorabort(ret, "XShmAttach"); /* Force refresh */ refresh = 1; } if (screen->refresh) { log(1, "Force refresh from client."); /* refresh forced by the client */ refresh = 1; } XEvent ev; /* Register damage on new windows */ while (XCheckTypedEvent(dpy, MapNotify, &ev)) { register_damage(dpy, ev.xcreatewindow.window); refresh = 1; } /* Check for damage */ while (XCheckTypedEvent(dpy, damageEvent + XDamageNotify, &ev)) { refresh = 1; } /* Check for cursor events */ reply->cursor_updated = 0; while (XCheckTypedEvent(dpy, fixesEvent + XFixesCursorNotify, &ev)) { XFixesCursorNotifyEvent* curev = (XFixesCursorNotifyEvent*)&ev; if (verbose >= 2) { char* name = XGetAtomName(dpy, curev->cursor_name); log(2, "cursor! %ld %s", curev->cursor_serial, name); XFree(name); } reply->cursor_updated = 1; reply->cursor_serial = curev->cursor_serial; } /* No update */ if (!refresh) { reply->shm = 0; reply->updated = 0; socket_client_write_frame(reply_raw, sizeof(*reply), WS_OPCODE_BINARY, 1); return 0; } /* Get new image from framebuffer */ XShmGetImage(dpy, DefaultRootWindow(dpy), img, 0, 0, AllPlanes); int size = img->bytes_per_line * img->height; trueorabort(size == screen->width*screen->height*4, "Invalid screen byte count"); trueorabort(screen->shm, "Non-SHM rendering is not supported"); struct cache_entry* entry = find_shm(screen->paddr, screen->sig, size); reply->shm = 1; reply->updated = 1; reply->shmfailed = 0; if (entry && entry->map) { if (size == entry->length) { memcpy(entry->map, img->data, size); msync(entry->map, size, MS_SYNC); } else { /* This should never happen (it means the client passed an * outdated buffer to us). */ error("Invalid shm entry length (client bug!)."); reply->shmfailed = 1; } } else { /* Keep the flow going, even if we cannot find the shm. Next time * the NaCl client reallocates the buffer, we are likely to be able * to find it. */ error("Cannot find shm, moving on..."); reply->shmfailed = 1; } /* Confirm write is done */ socket_client_write_frame(reply_raw, sizeof(*reply), WS_OPCODE_BINARY, 1); return 0; } /* Writes cursor image to websocket */ int write_cursor() { XFixesCursorImage *img = XFixesGetCursorImage(dpy); if (!img) { error("XFixesGetCursorImage returned NULL"); return -1; } int size = img->width*img->height; const int replylength = sizeof(struct cursor_reply) + size*sizeof(uint32_t); char reply_raw[FRAMEMAXHEADERSIZE + replylength]; struct cursor_reply* reply = (struct cursor_reply*)(reply_raw + FRAMEMAXHEADERSIZE); memset(reply_raw, 0, sizeof(*reply_raw)); reply->type = 'P'; reply->width = img->width; reply->height = img->height; reply->xhot = img->xhot; reply->yhot = img->yhot; reply->cursor_serial = img->cursor_serial; /* This casts long[] to uint32_t[] */ int i; for (i = 0; i < size; i++) reply->pixels[i] = img->pixels[i]; socket_client_write_frame(reply_raw, replylength, WS_OPCODE_BINARY, 1); XFree(img); return 0; }
static void area_tests(struct test *t, int reps, int sets, enum target target) { struct test_target tt; XImage image; uint32_t *cells = calloc(sizeof(uint32_t), t->real.width*t->real.height); int r, s, x, y; printf("Testing area sets (%s): ", test_target_name(target)); fflush(stdout); test_target_create_render(&t->real, target, &tt); clear(&t->real, &tt); test_init_image(&image, &t->real.shm, tt.format, tt.width, tt.height); for (s = 0; s < sets; s++) { for (r = 0; r < reps; r++) { int w = rand() % tt.width; int h = rand() % tt.height; uint32_t fg = rand(); x = rand() % (2*tt.width) - tt.width; y = rand() % (2*tt.height) - tt.height; fill_rect(&t->real, tt.draw, GXcopy, x, y, w, h, fg); if (x < 0) w += x, x = 0; if (y < 0) h += y, y = 0; if (x >= tt.width || y >= tt.height) continue; if (x + w > tt.width) w = tt.width - x; if (y + h > tt.height) h = tt.height - y; if (w <= 0 || h <= 0) continue; pixman_fill(cells, tt.width, 32, x, y, w, h, fg); } XShmGetImage(t->real.dpy, tt.draw, &image, 0, 0, AllPlanes); for (y = 0; y < tt.height; y++) { for (x = 0; x < tt.width; x++) { uint32_t result = *(uint32_t *) (image.data + y*image.bytes_per_line + x*image.bits_per_pixel/8); if (!pixel_equal(image.depth, result, cells[y*tt.width+x])) { char buf[600]; uint32_t mask = depth_mask(image.depth); show_cells(buf, (uint32_t*)image.data, cells, x, y, tt.width, tt.height); die("failed to set pixel (%d,%d) to %08x [%08x], found %08x [%08x] instead\n%s", x, y, cells[y*tt.width+x] & mask, cells[y*tt.width+x], result & mask, result, buf); } } } } printf("passed [%d iterations x %d]\n", reps, sets); test_target_destroy_render(&t->real, &tt); free(cells); }
static void area_tests(struct test *t, int reps, int sets, enum target target, int use_shm) { struct test_target tt; XImage image; uint32_t *cells = calloc(sizeof(uint32_t), t->real.width*t->real.height); int r, s, x, y; printf("Testing area sets (%s %s shm): ", test_target_name(target), use_shm ? "with" : "without" ); fflush(stdout); test_target_create_render(&t->real, target, &tt); clear(&t->real, &tt); test_init_image(&image, &t->real.shm, tt.format, tt.width, tt.height); for (s = 0; s < sets; s++) { for (r = 0; r < reps; r++) { int red = rand() % 0xff; int green = rand() % 0xff; int blue = rand() % 0xff; int alpha = rand() % 0xff; uint32_t fg = color(red, green, blue, alpha); int w, h; x = rand() % tt.width; y = rand() % tt.height; w = rand() % (tt.width - x); h = rand() % (tt.height - y); fill_rect(&t->real, tt.draw, tt.format, use_shm, GXcopy, x, y, w, h, fg); pixman_fill(cells, tt.width, 32, x, y, w, h, fg); } XShmGetImage(t->real.dpy, tt.draw, &image, 0, 0, AllPlanes); for (y = 0; y < tt.height; y++) { for (x = 0; x < tt.width; x++) { uint32_t result = *(uint32_t *)(image.data + y*image.bytes_per_line + image.bits_per_pixel*x/8); if (!pixel_equal(image.depth, result, cells[y*tt.width+x])) { uint32_t mask = depth_mask(image.depth); char buf[600]; show_cells(buf, (uint32_t*)image.data, cells, x, y, tt.width, tt.height); die("failed to set pixel (%d,%d) to %08x[%08x], found %08x [%08x] instead\n%s", x, y, cells[y*tt.width+x] & mask, cells[y*tt.width+x], result & mask, result, buf); } } } } printf("passed [%d iterations x %d]\n", reps, sets); test_target_destroy_render(&t->real, &tt); free(cells); }
// ###################################################################### Image<PixRGB<byte> > AutomateXWin::getImage() { DeleteImage(); #ifdef USE_SHM if(!itsImage) { itsImage = XShmCreateImage(itsDisplay, itsVInfo.visual, itsDepth, ZPixmap, NULL, &itsShminfo, itsWidth, itsHeight); if(!itsImage) { LERROR("XShmCreateImage"); return Image<PixRGB<byte> >(); } itsShminfo.shmid = shmget(IPC_PRIVATE, itsImage->bytes_per_line * itsImage->height, IPC_CREAT | 0777); if(itsShminfo.shmid < 0) { LERROR("shmget"); XDestroyImage(itsImage); itsImage=NULL; return Image<PixRGB<byte> >(); } itsShminfo.shmaddr = (char *) shmat(itsShminfo.shmid, 0, 0); if(itsShminfo.shmaddr == (char *)-1) { LERROR("shmat"); XDestroyImage(itsImage); return Image<PixRGB<byte> >(); } shmctl(itsShminfo.shmid, IPC_RMID, 0), itsImage->data = itsShminfo.shmaddr; itsShminfo.readOnly = False; XShmAttach(itsDisplay, &itsShminfo); XSync(itsDisplay, False); } #endif /* If SHM failed or was disabled, try non-SHM way */ if(!itsImage) { itsImage = XGetImage(itsDisplay, itsWindow, 0, 0, itsWidth, itsHeight, AllPlanes, XYPixmap); if(!itsImage) LERROR("XGetImage\n"); } #ifdef USE_SHM if(!XShmGetImage(itsDisplay, itsWindow, itsImage, 0, 0, AllPlanes)) LERROR("XSHMGetImage"); #endif Image<PixRGB<byte> > img(itsWidth,itsHeight,NO_INIT); int rshift = 7 - getHighBitIndex (itsImage->red_mask); int gshift = 7 - getHighBitIndex (itsImage->green_mask); int bshift = 7 - getHighBitIndex (itsImage->blue_mask); for (int y=0; y<itsImage->height; y++) { for (int x=0; x<itsImage->width; x++) { unsigned long pixel = XGetPixel (itsImage,x,y); PixRGB<byte> pixVal( SHIFTL(pixel & itsImage->red_mask,rshift), SHIFTL(pixel & itsImage->green_mask,gshift), SHIFTL(pixel & itsImage->blue_mask,bshift) ); img.setVal(x,y, pixVal); } } return img; }
main(int argc, char * argv []) { Display * sdpy = XOpenDisplay(argv[1]); Display * tdpy = XOpenDisplay(argv[2]); int sscr = XDefaultScreen(sdpy); int tscr = XDefaultScreen(tdpy); GC tgc = DefaultGC(tdpy,tscr); Window swin=RootWindow (sdpy,sscr); int width, height, dummy; XGetGeometry(sdpy, swin, (Window *)&dummy, &dummy, &dummy, &width, &height, &dummy, &dummy); Window twin=CreateWindow(tdpy,tscr,width,height); XSelectInput(sdpy, swin, PointerMotionMask); XImage * image; XImage * simage; XImage * timage; int use_shm=1; XShmSegmentInfo xshm_sinfo; XShmSegmentInfo xshm_tinfo; if(use_shm) createShmImage(width,height,&xshm_sinfo,&xshm_tinfo,sdpy,tdpy,sscr,tscr,&simage,&timage); int frame=0; for(;;) { XEvent e; XNextEvent(tdpy, &e); if (e.type == MapNotify) break; } int emulate_events=0; int xmouse, ymouse; while(1) { { XEvent e; //long mask=ButtonPressMask|ButtonReleaseMask|MotionNotifyMask; //while(XCheckWindowEvent(tdpy, twin, mask, &e)!=False) while(XCheckTypedWindowEvent(tdpy, twin, ButtonPress, &e)!=False || XCheckTypedWindowEvent(tdpy, twin, ButtonRelease, &e)!=False) { printf("button event\n"); if(emulate_events) { e.xbutton.display=sdpy; e.xbutton.window=swin; e.xbutton.root=swin; e.xbutton.window=swin; e.xbutton.x_root=e.xbutton.x; e.xbutton.y_root=e.xbutton.y; //XSendEvent( sdpy, swin, True, mask, &e ); XPutBackEvent( sdpy, &e ); //XTestFakeMotionEvent(sdpy,sscr,e.xbutton.x,e.xbutton.y,0); XTestFakeButtonEvent(sdpy,e.xbutton.button,e.xbutton.type==ButtonPress,0); } } while(XCheckTypedWindowEvent(sdpy, swin, MotionNotify, &e)!=False) { //printf("motion event\n"); xmouse=e.xbutton.x_root; ymouse=e.xbutton.y_root; } } //printf("frame %d\n", frame++); usleep(60000); if(!use_shm) { image=CaptRoot(sdpy,sscr); DrawImage(tdpy,twin,image); XDestroyImage(image); } else { // XShmAttach(sdpy, &xshm_sinfo); XShmGetImage (sdpy, swin, simage, 0, 0, AllPlanes); // XShmAttach(sdpy, &xshm_tinfo); //printf("simage: w:%d h:%d d:%d\n",simage->width, simage->height, simage->depth); //printf("timage: w:%d h:%d d:%d\n",timage->width, timage->height, timage->depth); if(!emulate_events) { Window rwin,cwin; int xmouse,ymouse,x,y,mask; XQueryPointer(sdpy,swin,&rwin,&cwin,&xmouse,&ymouse,&x,&y,&mask); drawMouse(timage, xmouse, ymouse); } XShmPutImage (tdpy, twin, tgc, timage, 0, 0, 0, 0, timage->width, timage->height, False); //XPutImage (tdpy, twin, tgc, timage, 0, 0, 0, 0, timage->width, timage->height); } //XFlush(sdpy); XFlush(tdpy); // getchar(); } }
static void _cogl_texture_pixmap_x11_update_image_texture (CoglTexturePixmapX11 *tex_pixmap) { Display *display; CoglPixelFormat image_format; XImage *image; int src_x, src_y; int x, y, width, height; display = cogl_xlib_get_display (); /* If the damage region is empty then there's nothing to do */ if (tex_pixmap->damage_rect.x2 == tex_pixmap->damage_rect.x1) return; x = tex_pixmap->damage_rect.x1; y = tex_pixmap->damage_rect.y1; width = tex_pixmap->damage_rect.x2 - x; height = tex_pixmap->damage_rect.y2 - y; /* We lazily create the texture the first time it is needed in case this texture can be entirely handled using the GLX texture instead */ if (tex_pixmap->tex == COGL_INVALID_HANDLE) { CoglPixelFormat texture_format; texture_format = (tex_pixmap->depth >= 32 ? COGL_PIXEL_FORMAT_RGBA_8888_PRE : COGL_PIXEL_FORMAT_RGB_888); tex_pixmap->tex = cogl_texture_new_with_size (tex_pixmap->width, tex_pixmap->height, COGL_TEXTURE_NONE, texture_format); } if (tex_pixmap->image == NULL) { /* If we also haven't got a shm segment then this must be the first time we've tried to update, so lets try allocating shm first */ if (tex_pixmap->shm_info.shmid == -1) try_alloc_shm (tex_pixmap); if (tex_pixmap->shm_info.shmid == -1) { COGL_NOTE (TEXTURE_PIXMAP, "Updating %p using XGetImage", tex_pixmap); /* We'll fallback to using a regular XImage. We'll download the entire area instead of a sub region because presumably if this is the first update then the entire pixmap is needed anyway and it saves trying to manually allocate an XImage at the right size */ tex_pixmap->image = XGetImage (display, tex_pixmap->pixmap, 0, 0, tex_pixmap->width, tex_pixmap->height, AllPlanes, ZPixmap); image = tex_pixmap->image; src_x = x; src_y = y; } else { COGL_NOTE (TEXTURE_PIXMAP, "Updating %p using XShmGetImage", tex_pixmap); /* Create a temporary image using the beginning of the shared memory segment and the right size for the region we want to update. We need to reallocate the XImage every time because there is no XShmGetSubImage. */ image = XShmCreateImage (display, tex_pixmap->visual, tex_pixmap->depth, ZPixmap, NULL, &tex_pixmap->shm_info, width, height); image->data = tex_pixmap->shm_info.shmaddr; src_x = 0; src_y = 0; XShmGetImage (display, tex_pixmap->pixmap, image, x, y, AllPlanes); } } else { COGL_NOTE (TEXTURE_PIXMAP, "Updating %p using XGetSubImage", tex_pixmap); image = tex_pixmap->image; src_x = x; src_y = y; XGetSubImage (display, tex_pixmap->pixmap, x, y, width, height, AllPlanes, ZPixmap, image, x, y); } /* xlib doesn't appear to fill in image->{red,green,blue}_mask so this just assumes that the image is stored as ARGB from most significant byte to to least significant. If the format is little endian that means the order will be BGRA in memory */ switch (image->bits_per_pixel) { default: case 32: { /* If the pixmap is actually non-packed-pixel RGB format then the texture would have been created in RGB_888 format so Cogl will ignore the alpha channel and effectively pack it for us */ image_format = COGL_PIXEL_FORMAT_RGBA_8888_PRE; /* If the format is actually big endian then the alpha component will come first */ if (image->byte_order == MSBFirst) image_format |= COGL_AFIRST_BIT; } break; case 24: image_format = COGL_PIXEL_FORMAT_RGB_888; break; case 16: /* FIXME: this should probably swap the orders around if the endianness does not match */ image_format = COGL_PIXEL_FORMAT_RGB_565; break; } if (image->bits_per_pixel != 16) { /* If the image is in little-endian then the order in memory is reversed */ if (image->byte_order == LSBFirst) image_format |= COGL_BGR_BIT; } cogl_texture_set_region (tex_pixmap->tex, src_x, src_y, x, y, width, height, image->width, image->height, image_format, image->bytes_per_line, (const guint8 *) image->data); /* If we have a shared memory segment then the XImage would be a temporary one with no data allocated so we can just XFree it */ if (tex_pixmap->shm_info.shmid != -1) XFree (image); memset (&tex_pixmap->damage_rect, 0, sizeof (CoglDamageRectangle)); }