void* icvVideoRender(void* data) { int cameraid = (int)data; CvVideoCamera *const camera = &(cameras[cameraid]); Display* display; int screen_num; GC gc; char* display_name = NULL; Window window = camera->window; XWindowAttributes windowattr; Visual* visual; int windowdepth; XImage* image; XShmSegmentInfo xshmseg; int width = (camera->renderwidth>0)?camera->renderwidth:camera->videopp.width; int height = camera->renderheight?camera->renderheight:camera->videopp.height; int picturedepth = camera->videopp.picture.depth; int pixelsize; XGCValues values; IplImage* iplimage; time_t start, now; int frames = 0; float rate = 0; Status XShm; uchar* imgdata = NULL; uchar* tmpbuff = NULL; pthread_mutex_lock(&(camera->capturestatemutex)); if(camera->capturestate != CAPTURING) { pthread_mutex_unlock(&(camera->capturestatemutex)); pthread_exit( NULL ); } camera->renderstate=1; pthread_cond_signal(&(camera->capturestatecond)); pthread_mutex_unlock(&(camera->capturestatemutex)); XInitThreads(); if ( (display=XOpenDisplay(display_name)) == NULL ) { fprintf( stderr, "cvVideo: cannot connect to X server %s\n", XDisplayName(display_name)); pthread_exit( NULL ); } screen_num = DefaultScreen(display); if (XGetWindowAttributes(display, window, &windowattr) == 0) { fprintf(stderr, "icvVideoRender: failed to get window attributes.\n" ); pthread_exit(NULL); } if(windowattr.map_state == IsUnmapped) { fprintf(stderr, "icvVideoRender: window is not mapped \n" ); pthread_exit(NULL); } windowdepth = windowattr.depth; visual = windowattr.visual; pixelsize = icvVideoWindowPixelsize(windowdepth); XShm = XShmQueryExtension(display); if(XShm) { image = XShmCreateImage(display, visual, windowdepth, ZPixmap, NULL, &xshmseg, width, height ); assert(image); xshmseg.shmid = shmget (IPC_PRIVATE, width*height*pixelsize, IPC_CREAT|0777); assert(xshmseg.shmid != -1); xshmseg.shmaddr = image->data=(char*)shmat (xshmseg.shmid, 0, 0) ; xshmseg.readOnly = False; XShmAttach (display, &xshmseg); } else { imgdata = (uchar*)malloc(width*height*icvVideoWindowPixelsize(windowdepth)) ; image = XCreateImage(display, visual, windowdepth, ZPixmap, 0, (char*)imgdata, width, height, 8, icvVideoWindowPixelsize(windowdepth) *width); assert(image); XInitImage(image); } gc = XCreateGC(display,window,0, &values ); #ifdef RENDER_FRAMERATE start = time(NULL); #endif pthread_mutex_lock(&(camera->capturestatemutex)); while((camera->capturestate == CAPTURING) && (camera->rendered)) { pthread_mutex_unlock(&(camera->capturestatemutex)); pthread_mutex_lock(&(camera->updatedmutex)); while(camera->updated == 0) pthread_cond_wait(&(camera->updatedcond), &(camera->updatedmutex)); camera->updated = 0; pthread_mutex_unlock(&(camera->updatedmutex)); if(cvcamGetProperty(cameraid, "raw_image",&iplimage )) { assert(image->data); if(camera->callback != NULL) camera->callback(iplimage); if((width==camera->videopp.width)&& (height==camera->videopp.height)) { icvvConvert(width, height, width*picturedepth/8, picturedepth, iplimage->imageData, width*pixelsize, pixelsize*8, image->data ); cvReleaseImage(&iplimage); } else { tmpbuff = (uchar*)malloc(camera->videopp.width*camera->videopp.height* pixelsize) ; icvvConvert(camera->videopp.width, camera->videopp.height, camera->videopp.width*picturedepth/8, picturedepth, iplimage->imageData, camera->videopp.width*pixelsize, pixelsize*8, (char*)tmpbuff); cvReleaseImage(&iplimage); icvvResizeImage(camera->videopp.width, camera->videopp.height, (camera->videopp.width)*pixelsize, (char*)tmpbuff, width, height,width*pixelsize, image->data, pixelsize*8); free(tmpbuff); } //fprintf(stdout, "cvVideoRendering:image converted!!!!\n"); if(XShm) { XShmPutImage(display, window, gc, image,0,0,0,0, width, height, False); } else { XPutImage(display, window, gc, image,0,0,0,0, width, height); } XSync(display, False); #ifdef RENDER_FRAMERATE now = time(NULL); frames++; if (now-start) rate = frames/(float)(now-start); if((frames%30) == 0) fprintf(stdout, "camera %d fps = %f\n", cameraid, rate); #endif }//if(cvcamGetProperty(CAMERA, "raw_image",&image )) // stop here if we're paused pthread_mutex_lock(&(camera->pausemutex)); pthread_mutex_unlock(&(camera->pausemutex)); pthread_mutex_lock(&(camera->capturestatemutex)); }//while (camera->state == CAPTURING && camera->rendered) pthread_mutex_unlock(&(camera->capturestatemutex)); pthread_mutex_lock(&(camera->capturestatemutex)); #if 0 if(camera->state != CAPTURING) { // we ended because the camera is not capturing anymore while (camera->capturestate != FINISHED ) { pthread_cond_wait(&(camera->capturestatecond),&(camera->capturestatemutex)); } } #endif camera->renderstate=0; pthread_cond_signal(&(camera->capturestatecond)); pthread_mutex_unlock(&(camera->capturestatemutex)); XShmDetach (display, &xshmseg); XDestroyImage (image); XFreeGC(display,gc); shmdt (xshmseg.shmaddr); shmctl (xshmseg.shmid, IPC_RMID, 0); if(imgdata) free(imgdata); pthread_exit(NULL); }
static int X11_CreateTexture(SDL_Renderer * renderer, SDL_Texture * texture) { X11_RenderData *renderdata = (X11_RenderData *) renderer->driverdata; SDL_Window *window = renderer->window; SDL_VideoDisplay *display = window->display; X11_TextureData *data; int pitch_alignmask = ((renderdata->scanline_pad / 8) - 1); data = (X11_TextureData *) SDL_calloc(1, sizeof(*data)); if (!data) { SDL_OutOfMemory(); return -1; } texture->driverdata = data; if (SDL_ISPIXELFORMAT_FOURCC(texture->format)) { data->yuv = SDL_SW_CreateYUVTexture(texture->format, texture->w, texture->h); if (!data->yuv) { return -1; } data->format = display->current_mode.format; } else { /* The image/pixmap depth must be the same as the window or you get a BadMatch error when trying to putimage or copyarea. */ if (texture->format != display->current_mode.format) { SDL_SetError("Texture format doesn't match window format"); return -1; } data->format = texture->format; } data->pitch = texture->w * SDL_BYTESPERPIXEL(data->format); data->pitch = (data->pitch + pitch_alignmask) & ~pitch_alignmask; if (data->yuv || texture->access == SDL_TEXTUREACCESS_STREAMING) { #ifndef NO_SHARED_MEMORY XShmSegmentInfo *shminfo = &data->shminfo; shm_error = True; if (SDL_X11_HAVE_SHM) { shminfo->shmid = shmget(IPC_PRIVATE, texture->h * data->pitch, IPC_CREAT | 0777); if (shminfo->shmid >= 0) { shminfo->shmaddr = (char *) shmat(shminfo->shmid, 0, 0); shminfo->readOnly = False; if (shminfo->shmaddr != (char *) -1) { shm_error = False; X_handler = XSetErrorHandler(shm_errhandler); XShmAttach(renderdata->display, shminfo); XSync(renderdata->display, False); XSetErrorHandler(X_handler); if (shm_error) { shmdt(shminfo->shmaddr); } } shmctl(shminfo->shmid, IPC_RMID, NULL); } } if (!shm_error) { data->pixels = shminfo->shmaddr; data->image = XShmCreateImage(renderdata->display, renderdata->visual, renderdata->depth, ZPixmap, shminfo->shmaddr, shminfo, texture->w, texture->h); if (!data->image) { XShmDetach(renderdata->display, shminfo); XSync(renderdata->display, False); shmdt(shminfo->shmaddr); shm_error = True; } } if (shm_error) { shminfo->shmaddr = NULL; } if (!data->image) #endif /* not NO_SHARED_MEMORY */ { data->pixels = SDL_malloc(texture->h * data->pitch); if (!data->pixels) { X11_DestroyTexture(renderer, texture); SDL_OutOfMemory(); return -1; } data->image = XCreateImage(renderdata->display, renderdata->visual, renderdata->depth, ZPixmap, 0, data->pixels, texture->w, texture->h, SDL_BYTESPERPIXEL(data->format) * 8, data->pitch); if (!data->image) { X11_DestroyTexture(renderer, texture); SDL_SetError("XCreateImage() failed"); return -1; } } } else { data->pixmap = XCreatePixmap(renderdata->display, renderdata->xwindow, texture->w, texture->h, renderdata->depth); if (data->pixmap == None) { X11_DestroyTexture(renderer, texture); SDL_SetError("XCreatePixmap() failed"); return -1; } data->image = XCreateImage(renderdata->display, renderdata->visual, renderdata->depth, ZPixmap, 0, NULL, texture->w, texture->h, SDL_BYTESPERPIXEL(data->format) * 8, data->pitch); if (!data->image) { X11_DestroyTexture(renderer, texture); SDL_SetError("XCreateImage() failed"); return -1; } } return 0; }
/** * Initialize the x11 grab device demuxer (public device demuxer API). * * @param s1 Context from avformat core * @param ap Parameters from avformat core * @return <ul> * <li>AVERROR(ENOMEM) no memory left</li> * <li>AVERROR(EIO) other failure case</li> * <li>0 success</li> * </ul> */ static int x11grab_read_header(AVFormatContext *s1, AVFormatParameters *ap) { struct x11_grab *x11grab = s1->priv_data; Display *dpy; AVStream *st = NULL; enum PixelFormat input_pixfmt; XImage *image; int x_off = 0; int y_off = 0; int use_shm; char *param, *offset; int ret = 0; AVRational framerate; param = av_strdup(s1->filename); offset = strchr(param, '+'); if (offset) { sscanf(offset, "%d,%d", &x_off, &y_off); x11grab->nomouse= strstr(offset, "nomouse"); *offset= 0; } if ((ret = av_parse_video_size(&x11grab->width, &x11grab->height, x11grab->video_size)) < 0) { av_log(s1, AV_LOG_ERROR, "Couldn't parse video size.\n"); goto out; } if ((ret = av_parse_video_rate(&framerate, x11grab->framerate)) < 0) { av_log(s1, AV_LOG_ERROR, "Could not parse framerate: %s.\n", x11grab->framerate); goto out; } #if FF_API_FORMAT_PARAMETERS if (ap->width > 0) x11grab->width = ap->width; if (ap->height > 0) x11grab->height = ap->height; if (ap->time_base.num) framerate = (AVRational){ap->time_base.den, ap->time_base.num}; #endif av_log(s1, AV_LOG_INFO, "device: %s -> display: %s x: %d y: %d width: %d height: %d\n", s1->filename, param, x_off, y_off, x11grab->width, x11grab->height); dpy = XOpenDisplay(param); if(!dpy) { av_log(s1, AV_LOG_ERROR, "Could not open X display.\n"); ret = AVERROR(EIO); goto out; } st = av_new_stream(s1, 0); if (!st) { ret = AVERROR(ENOMEM); goto out; } av_set_pts_info(st, 64, 1, 1000000); /* 64 bits pts in us */ use_shm = XShmQueryExtension(dpy); av_log(s1, AV_LOG_INFO, "shared memory extension %s found\n", use_shm ? "" : "not"); if(use_shm) { int scr = XDefaultScreen(dpy); image = XShmCreateImage(dpy, DefaultVisual(dpy, scr), DefaultDepth(dpy, scr), ZPixmap, NULL, &x11grab->shminfo, x11grab->width, x11grab->height); x11grab->shminfo.shmid = shmget(IPC_PRIVATE, image->bytes_per_line * image->height, IPC_CREAT|0777); if (x11grab->shminfo.shmid == -1) { av_log(s1, AV_LOG_ERROR, "Fatal: Can't get shared memory!\n"); ret = AVERROR(ENOMEM); goto out; } x11grab->shminfo.shmaddr = image->data = shmat(x11grab->shminfo.shmid, 0, 0); x11grab->shminfo.readOnly = False; if (!XShmAttach(dpy, &x11grab->shminfo)) { av_log(s1, AV_LOG_ERROR, "Fatal: Failed to attach shared memory!\n"); /* needs some better error subroutine :) */ ret = AVERROR(EIO); goto out; } } else { image = XGetImage(dpy, RootWindow(dpy, DefaultScreen(dpy)), x_off,y_off, x11grab->width, x11grab->height, AllPlanes, ZPixmap); } switch (image->bits_per_pixel) { case 8: av_log (s1, AV_LOG_DEBUG, "8 bit palette\n"); input_pixfmt = PIX_FMT_PAL8; break; case 16: if ( image->red_mask == 0xf800 && image->green_mask == 0x07e0 && image->blue_mask == 0x001f ) { av_log (s1, AV_LOG_DEBUG, "16 bit RGB565\n"); input_pixfmt = PIX_FMT_RGB565; } else if (image->red_mask == 0x7c00 && image->green_mask == 0x03e0 && image->blue_mask == 0x001f ) { av_log(s1, AV_LOG_DEBUG, "16 bit RGB555\n"); input_pixfmt = PIX_FMT_RGB555; } else { av_log(s1, AV_LOG_ERROR, "RGB ordering at image depth %i not supported ... aborting\n", image->bits_per_pixel); av_log(s1, AV_LOG_ERROR, "color masks: r 0x%.6lx g 0x%.6lx b 0x%.6lx\n", image->red_mask, image->green_mask, image->blue_mask); ret = AVERROR(EIO); goto out; } break; case 24: if ( image->red_mask == 0xff0000 && image->green_mask == 0x00ff00 && image->blue_mask == 0x0000ff ) { input_pixfmt = PIX_FMT_BGR24; } else if ( image->red_mask == 0x0000ff && image->green_mask == 0x00ff00 && image->blue_mask == 0xff0000 ) { input_pixfmt = PIX_FMT_RGB24; } else { av_log(s1, AV_LOG_ERROR,"rgb ordering at image depth %i not supported ... aborting\n", image->bits_per_pixel); av_log(s1, AV_LOG_ERROR, "color masks: r 0x%.6lx g 0x%.6lx b 0x%.6lx\n", image->red_mask, image->green_mask, image->blue_mask); ret = AVERROR(EIO); goto out; } break; case 32: #if 0 GetColorInfo (image, &c_info); if ( c_info.alpha_mask == 0xff000000 && image->green_mask == 0x0000ff00) { /* byte order is relevant here, not endianness * endianness is handled by avcodec, but atm no such thing * as having ABGR, instead of ARGB in a word. Since we * need this for Solaris/SPARC, but need to do the conversion * for every frame we do it outside of this loop, cf. below * this matches both ARGB32 and ABGR32 */ input_pixfmt = PIX_FMT_ARGB32; } else { av_log(s1, AV_LOG_ERROR,"image depth %i not supported ... aborting\n", image->bits_per_pixel); return AVERROR(EIO); } #endif input_pixfmt = PIX_FMT_RGB32; break; default: av_log(s1, AV_LOG_ERROR, "image depth %i not supported ... aborting\n", image->bits_per_pixel); ret = AVERROR(EINVAL); goto out; } x11grab->frame_size = x11grab->width * x11grab->height * image->bits_per_pixel/8; x11grab->dpy = dpy; x11grab->time_base = (AVRational){framerate.den, framerate.num}; x11grab->time_frame = av_gettime() / av_q2d(x11grab->time_base); x11grab->x_off = x_off; x11grab->y_off = y_off; x11grab->image = image; x11grab->use_shm = use_shm; st->codec->codec_type = AVMEDIA_TYPE_VIDEO; st->codec->codec_id = CODEC_ID_RAWVIDEO; st->codec->width = x11grab->width; st->codec->height = x11grab->height; st->codec->pix_fmt = input_pixfmt; st->codec->time_base = x11grab->time_base; st->codec->bit_rate = x11grab->frame_size * 1/av_q2d(x11grab->time_base) * 8; out: return ret; }
static int x11_reset(struct vidisp_st *st, const struct vidsz *sz) { XWindowAttributes attrs; XGCValues gcv; size_t bufsz, pixsz; int err = 0; if (!XGetWindowAttributes(st->disp, st->win, &attrs)) { warning("x11: cant't get window attributes\n"); return EINVAL; } switch (attrs.depth) { case 24: st->pixfmt = VID_FMT_RGB32; pixsz = 4; break; case 16: st->pixfmt = VID_FMT_RGB565; pixsz = 2; break; case 15: st->pixfmt = VID_FMT_RGB555; pixsz = 2; break; default: warning("x11: colordepth not supported: %d\n", attrs.depth); return ENOSYS; } bufsz = sz->w * sz->h * pixsz; if (st->image) { XDestroyImage(st->image); st->image = NULL; } if (st->xshmat) XShmDetach(st->disp, &st->shm); if (st->shm.shmaddr != (char *)-1) shmdt(st->shm.shmaddr); if (st->shm.shmid >= 0) shmctl(st->shm.shmid, IPC_RMID, NULL); st->shm.shmid = shmget(IPC_PRIVATE, bufsz, IPC_CREAT | 0777); if (st->shm.shmid < 0) { warning("x11: failed to allocate shared memory\n"); return ENOMEM; } st->shm.shmaddr = shmat(st->shm.shmid, NULL, 0); if (st->shm.shmaddr == (char *)-1) { warning("x11: failed to attach to shared memory\n"); return ENOMEM; } st->shm.readOnly = true; x11.shm_error = 0; x11.errorh = XSetErrorHandler(error_handler); if (!XShmAttach(st->disp, &st->shm)) { warning("x11: failed to attach X to shared memory\n"); return ENOMEM; } XSync(st->disp, False); XSetErrorHandler(x11.errorh); if (x11.shm_error) info("x11: shared memory disabled\n"); else st->xshmat = true; gcv.graphics_exposures = false; st->gc = XCreateGC(st->disp, st->win, GCGraphicsExposures, &gcv); if (!st->gc) { warning("x11: failed to create graphics context\n"); return ENOMEM; } if (st->xshmat) { st->image = XShmCreateImage(st->disp, attrs.visual, attrs.depth, ZPixmap, st->shm.shmaddr, &st->shm, sz->w, sz->h); } else { st->image = XCreateImage(st->disp, attrs.visual, attrs.depth, ZPixmap, 0, st->shm.shmaddr, sz->w, sz->h, 32, 0); } if (!st->image) { warning("x11: Failed to create X image\n"); return ENOMEM; } XResizeWindow(st->disp, st->win, sz->w, sz->h); st->size = *sz; return err; }
void *mlx_int_new_xshm_image(t_xvar *xvar,int width,int height,int format) { t_img *img; int (*save_handler)(); if (!(img = malloc(sizeof(*img)))) return ((void *)0); bzero(img,sizeof(*img)); img->data = 0; img->image = XShmCreateImage(xvar->display,xvar->visual,xvar->depth, format,img->data,&(img->shm),width,height); if (!img->image) { free(img); return ((void *)0); } img->width = width; img->height = height; img->size_line = img->image->bytes_per_line; img->bpp = img->image->bits_per_pixel; img->format = format; img->shm.shmid = shmget(IPC_PRIVATE,(width+32)*height*4,IPC_CREAT|0777); if (img->shm.shmid==-1) { XDestroyImage(img->image); free(img); return ((void *)0); } img->data = img->shm.shmaddr = img->image->data = shmat(img->shm.shmid,0,0); if (img->data==(void *)-1) { shmctl(img->shm.shmid,IPC_RMID,0); XDestroyImage(img->image); free(img); return ((void *)0); } img->shm.readOnly = False; mlx_X_error = 0; save_handler = XSetErrorHandler(shm_att_pb); if (!XShmAttach(xvar->display,&(img->shm)) || 0&XSync(xvar->display,False) || mlx_X_error) { XSetErrorHandler(save_handler); shmdt(img->data); shmctl(img->shm.shmid,IPC_RMID,0); XDestroyImage(img->image); free(img); return ((void *)0); } XSetErrorHandler(save_handler); shmctl(img->shm.shmid,IPC_RMID,0); if (xvar->pshm_format==format) { img->pix = XShmCreatePixmap(xvar->display,xvar->root,img->shm.shmaddr, &(img->shm),width,height,xvar->depth); img->type = MLX_TYPE_SHM_PIXMAP; } else { img->pix = XCreatePixmap(xvar->display,xvar->root, width,height,xvar->depth); img->type = MLX_TYPE_SHM; } if (xvar->do_flush) XFlush(xvar->display); return (img); }
RXImage* RCreateXImage(RContext *context, int depth, unsigned width, unsigned height) { RXImage *rximg; Visual *visual = context->visual; rximg = malloc(sizeof(RXImage)); if (!rximg) { RErrorCode = RERR_NOMEMORY; return NULL; } #ifndef XSHM rximg->image = XCreateImage(context->dpy, visual, depth, ZPixmap, 0, NULL, width, height, 8, 0); if (!rximg->image) { free(rximg); RErrorCode = RERR_XERROR; return NULL; } rximg->image->data = malloc(rximg->image->bytes_per_line*height); if (!rximg->image->data) { XDestroyImage(rximg->image); free(rximg); RErrorCode = RERR_NOMEMORY; return NULL; } #else /* XSHM */ if (!context->attribs->use_shared_memory) { retry_without_shm: context->attribs->use_shared_memory = 0; rximg->is_shared = 0; rximg->image = XCreateImage(context->dpy, visual, depth, ZPixmap, 0, NULL, width, height, 8, 0); if (!rximg->image) { free(rximg); RErrorCode = RERR_XERROR; return NULL; } rximg->image->data = malloc(rximg->image->bytes_per_line*height); if (!rximg->image->data) { XDestroyImage(rximg->image); free(rximg); RErrorCode = RERR_NOMEMORY; return NULL; } } else { rximg->is_shared = 1; rximg->info.readOnly = False; rximg->image = XShmCreateImage(context->dpy, visual, depth, ZPixmap, NULL, &rximg->info, width, height); rximg->info.shmid = shmget(IPC_PRIVATE, rximg->image->bytes_per_line*height, IPC_CREAT|0777); if (rximg->info.shmid < 0) { context->attribs->use_shared_memory = 0; perror("wrlib: could not allocate shared memory segment"); XDestroyImage(rximg->image); goto retry_without_shm; } rximg->info.shmaddr = shmat(rximg->info.shmid, 0, 0); if (rximg->info.shmaddr == (void*)-1) { context->attribs->use_shared_memory = 0; if (shmctl(rximg->info.shmid, IPC_RMID, 0) < 0) perror("wrlib: shmctl"); perror("wrlib: could not allocate shared memory"); XDestroyImage(rximg->image); goto retry_without_shm; } shmError = 0; XSync(context->dpy, False); oldErrorHandler = XSetErrorHandler(errorHandler); XShmAttach(context->dpy, &rximg->info); XSync(context->dpy, False); XSetErrorHandler(oldErrorHandler); rximg->image->data = rximg->info.shmaddr; /* rximg->image->obdata = &(rximg->info);*/ if (shmError) { context->attribs->use_shared_memory = 0; XDestroyImage(rximg->image); if (shmdt(rximg->info.shmaddr) < 0) perror("wrlib: shmdt"); if (shmctl(rximg->info.shmid, IPC_RMID, 0) < 0) perror("wrlib: shmctl"); /* printf("wrlib:error attaching shared memory segment to XImage\n"); */ goto retry_without_shm; } } #endif /* XSHM */ return rximg; }
static int makesharedfb(void) { XShmSegmentInfo *shminfo; shminfo = malloc(sizeof(XShmSegmentInfo)); if(shminfo == nil) { fprint(2, "emu: cannot allocate XShmSegmentInfo\n"); cleanexit(0); } /* setup to catch X11 error(s) */ XSync(xdisplay, 0); shm_got_x_error = 0; if(old_handler != shm_ehandler) old_handler = XSetErrorHandler(shm_ehandler); if(old_io_handler != shm_ehandler) old_io_handler = XSetErrorHandler(shm_ehandler); img = XShmCreateImage(xdisplay, xvis, xscreendepth, ZPixmap, NULL, shminfo, Xsize, Ysize); XSync(xdisplay, 0); /* did we get an X11 error? if so then try without shm */ if(shm_got_x_error) { free(shminfo); shminfo = NULL; clean_errhandlers(); return 0; } if(img == nil) { fprint(2, "emu: cannot allocate virtual screen buffer\n"); cleanexit(0); } shminfo->shmid = shmget(IPC_PRIVATE, img->bytes_per_line * img->height, IPC_CREAT|0777); shminfo->shmaddr = img->data = shmat(shminfo->shmid, 0, 0); shminfo->readOnly = True; if(!XShmAttach(xdisplay, shminfo)) { fprint(2, "emu: cannot allocate virtual screen buffer\n"); cleanexit(0); } XSync(xdisplay, 0); /* * Delete the shared segment right now; the segment * won't actually go away until both the client and * server have deleted it. The server will delete it * as soon as the client disconnects, so we might as * well delete our side now as later. */ shmctl(shminfo->shmid, IPC_RMID, 0); /* did we get an X11 error? if so then try without shm */ if(shm_got_x_error) { XDestroyImage(img); XSync(xdisplay, 0); free(shminfo); shminfo = NULL; clean_errhandlers(); return 0; } gscreendata = malloc(Xsize * Ysize * (displaydepth >> 3)); if(gscreendata == nil) { fprint(2, "emu: cannot allocate screen buffer (%dx%dx%d)\n", Xsize, Ysize, displaydepth); cleanexit(0); } xscreendata = (uchar*)img->data; clean_errhandlers(); return 1; }
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)); }
bool video::init_window(int xsize, int ysize) { { //enclose local variables before fail label g_sizex = xsize; g_sizey = ysize; // Open the display if (!dpy) { dpy = XOpenDisplay(display_name); if (!dpy) { fprintf(stderr, "Can't open X11 display %s\n", XDisplayName(display_name)); goto fail; } } int theScreen = DefaultScreen(dpy); scrn = ScreenOfDisplay(dpy, theScreen); dispdepth = DefaultDepth(dpy, theScreen); XVisualInfo vinfo; if (!( (dispdepth >= 15 && dispdepth <= 32 && XMatchVisualInfo(dpy, theScreen, dispdepth, TrueColor, &vinfo) ) || XMatchVisualInfo(dpy, theScreen, 24, TrueColor, &vinfo) || XMatchVisualInfo(dpy, theScreen, 32, TrueColor, &vinfo) || XMatchVisualInfo(dpy, theScreen, 16, TrueColor, &vinfo) || XMatchVisualInfo(dpy, theScreen, 15, TrueColor, &vinfo) )) { fprintf(stderr, "Display has no appropriate True Color visual\n"); goto fail; } vis = vinfo.visual; depth = dispdepth = vinfo.depth; mask2bits(vinfo.red_mask, red_mask, red_shift); mask2bits(vinfo.green_mask, green_mask, green_shift); mask2bits(vinfo.blue_mask, blue_mask, blue_shift); rootW = RootWindow(dpy, theScreen); cmap = XCreateColormap(dpy, rootW, vis, AllocNone); XSetWindowAttributes attrs; attrs.backing_store = Always; attrs.colormap = cmap; attrs.event_mask = StructureNotifyMask|KeyPressMask|ButtonPressMask|ButtonReleaseMask; attrs.background_pixel = BlackPixelOfScreen(scrn); attrs.border_pixel = WhitePixelOfScreen(scrn); win = XCreateWindow(dpy, rootW, 0, 0, xsize, ysize, 2, dispdepth, InputOutput, vis, CWBackingStore | CWColormap | CWEventMask | CWBackPixel | CWBorderPixel, &attrs); if(!win) { fprintf(stderr, "Can't create the window\n"); goto fail; } XSizeHints sh; sh.flags = PSize | PMinSize | PMaxSize; sh.width = sh.min_width = sh.max_width = xsize; sh.height = sh.min_height = sh.max_height = ysize; XSetStandardProperties( dpy, win, g_video->title, g_video->title, None, NULL, 0, &sh ); _XA_WM_DELETE_WINDOW = XInternAtom(dpy, "WM_DELETE_WINDOW", false); XSetWMProtocols(dpy, win, &_XA_WM_DELETE_WINDOW, 1); gc = XCreateGC(dpy, win, 0L, &xgcv); XMapRaised(dpy, win); XFlush(dpy); #ifdef X_FULLSYNC XSynchronize(dpy, true); #endif XSetErrorHandler(xerr_handler); int imgbytes = xsize*ysize*(dispdepth<=16?2:4); const char *vidstr; #ifndef X_NOSHMEM int major, minor, pixmaps; if(XShmQueryExtension(dpy) && XShmQueryVersion(dpy, &major, &minor, &pixmaps)) { // Shared memory if(NULL!=getenv(NOSHMEM_env_var_name) && 0!=strcmp("0",getenv(NOSHMEM_env_var_name))) { goto generic; } shmseginfo.shmid = shmget(IPC_PRIVATE, imgbytes, IPC_CREAT|0777); if(shmseginfo.shmid < 0) { fprintf(stderr, "Warning: Can't get shared memory: %s\n", strerror(errno)); goto generic; } g_pImg = (unsigned int*)(shmseginfo.shmaddr = (char*)shmat(shmseginfo.shmid, 0, 0)); if(g_pImg == (unsigned int*)-1) { fprintf(stderr, "Warning: Can't attach to shared memory: %s\n", strerror(errno)); shmctl(shmseginfo.shmid, IPC_RMID, NULL); goto generic; } shmseginfo.readOnly = false; if(!XShmAttach(dpy, &shmseginfo) || x_error) { char err[256]; XGetErrorText(dpy, x_error, err, 255); fprintf(stderr, "Warning: Can't attach shared memory to display: %s (%d)\n", err, x_error); shmdt(shmseginfo.shmaddr); shmctl(shmseginfo.shmid, IPC_RMID, NULL); goto generic; } already_called_X_ShmAttach = true; #ifndef X_NOSHMPIX if(pixmaps && XShmPixmapFormat(dpy) == ZPixmap) { // Pixmaps vidtype = 2; vidstr = "X11 shared memory pixmap"; pixmap = XShmCreatePixmap(dpy, win, (char*)g_pImg, &shmseginfo, xsize, ysize, dispdepth); XSetWindowBackgroundPixmap(dpy, win, pixmap); } else #endif//!X_NOSHMPIX { // Standard vidtype = 1; vidstr = "X11 shared memory"; ximage = XShmCreateImage(dpy, vis, dispdepth, ZPixmap, 0, &shmseginfo, xsize, ysize); if(!ximage) { fprintf(stderr, "Can't create the shared image\n"); goto fail; } assert(ximage->bytes_per_line == xsize*(dispdepth<=16?2:4)); ximage->data = shmseginfo.shmaddr; } } else #endif { #ifndef X_NOSHMEM generic: #endif vidtype = 0; vidstr = "generic X11"; g_pImg = new unsigned int[imgbytes/sizeof(int)]; ximage = XCreateImage(dpy, vis, dispdepth, ZPixmap, 0, (char*)g_pImg, xsize, ysize, 32, imgbytes/ysize); if(!ximage) { fprintf(stderr, "Can't create the image\n"); goto fail; } } // Note: It may be more efficient to adopt the server's byte order // and swap once per get_color() call instead of once per pixel. const uint32_t probe = 0x03020100; const bool big_endian = (((const char*)(&probe))[0]==0x03); ximage->byte_order = big_endian ? MSBFirst : LSBFirst; printf("Note: using %s with %s visual for %d-bit color depth\n", vidstr, vis==DefaultVisual(dpy, theScreen)?"default":"non-default", dispdepth); running = true; return true; } // end of enclosing local variables fail: terminate(); init_console(); return false; }
int x11_shadow_xshm_init(x11ShadowSubsystem* subsystem) { Bool pixmaps; int major, minor; XGCValues values; if (!XShmQueryExtension(subsystem->display)) return -1; if (!XShmQueryVersion(subsystem->display, &major, &minor, &pixmaps)) return -1; if (!pixmaps) return -1; subsystem->fb_shm_info.shmid = -1; subsystem->fb_shm_info.shmaddr = (char*) -1; subsystem->fb_shm_info.readOnly = False; subsystem->fb_image = XShmCreateImage(subsystem->display, subsystem->visual, subsystem->depth, ZPixmap, NULL, &(subsystem->fb_shm_info), subsystem->width, subsystem->height); if (!subsystem->fb_image) { WLog_ERR(TAG, "XShmCreateImage failed"); return -1; } subsystem->fb_shm_info.shmid = shmget(IPC_PRIVATE, subsystem->fb_image->bytes_per_line * subsystem->fb_image->height, IPC_CREAT | 0600); if (subsystem->fb_shm_info.shmid == -1) { WLog_ERR(TAG, "shmget failed"); return -1; } subsystem->fb_shm_info.shmaddr = shmat(subsystem->fb_shm_info.shmid, 0, 0); subsystem->fb_image->data = subsystem->fb_shm_info.shmaddr; if (subsystem->fb_shm_info.shmaddr == ((char*) -1)) { WLog_ERR(TAG, "shmat failed"); return -1; } if (!XShmAttach(subsystem->display, &(subsystem->fb_shm_info))) return -1; XSync(subsystem->display, False); shmctl(subsystem->fb_shm_info.shmid, IPC_RMID, 0); subsystem->fb_pixmap = XShmCreatePixmap(subsystem->display, subsystem->root_window, subsystem->fb_image->data, &(subsystem->fb_shm_info), subsystem->fb_image->width, subsystem->fb_image->height, subsystem->fb_image->depth); XSync(subsystem->display, False); if (!subsystem->fb_pixmap) return -1; values.subwindow_mode = IncludeInferiors; values.graphics_exposures = False; subsystem->xshm_gc = XCreateGC(subsystem->display, subsystem->root_window, GCSubwindowMode | GCGraphicsExposures, &values); XSetFunction(subsystem->display, subsystem->xshm_gc, GXcopy); XSync(subsystem->display, False); return 1; }
/* Tries to allocate enough shared mem to handle a full size * update size of the X Pixmap. */ static void try_alloc_shm (CoglTexturePixmapX11 *tex_pixmap) { CoglTexture *tex = COGL_TEXTURE (tex_pixmap); XImage *dummy_image; Display *display; _COGL_GET_CONTEXT (ctx, NO_RETVAL); display = cogl_xlib_renderer_get_display (ctx->display->renderer); if (!XShmQueryExtension (display)) return; /* We are creating a dummy_image so we can have Xlib calculate * image->bytes_per_line - including any magic padding it may * want - for the largest possible ximage we might need to use * when handling updates to the texture. * * Note: we pass a NULL shminfo here, but that has no bearing * on the setup of the XImage, except that ximage->obdata will * == NULL. */ dummy_image = XShmCreateImage (display, tex_pixmap->visual, tex_pixmap->depth, ZPixmap, NULL, NULL, /* shminfo, */ tex->width, tex->height); if (!dummy_image) goto failed_image_create; tex_pixmap->shm_info.shmid = shmget (IPC_PRIVATE, dummy_image->bytes_per_line * dummy_image->height, IPC_CREAT | 0777); if (tex_pixmap->shm_info.shmid == -1) goto failed_shmget; tex_pixmap->shm_info.shmaddr = shmat (tex_pixmap->shm_info.shmid, 0, 0); if (tex_pixmap->shm_info.shmaddr == (void *) -1) goto failed_shmat; tex_pixmap->shm_info.readOnly = False; if (XShmAttach (display, &tex_pixmap->shm_info) == 0) goto failed_xshmattach; XDestroyImage (dummy_image); return; failed_xshmattach: g_warning ("XShmAttach failed"); shmdt (tex_pixmap->shm_info.shmaddr); failed_shmat: g_warning ("shmat failed"); shmctl (tex_pixmap->shm_info.shmid, IPC_RMID, 0); failed_shmget: g_warning ("shmget failed"); XDestroyImage (dummy_image); failed_image_create: tex_pixmap->shm_info.shmid = -1; }
QNativeImage::QNativeImage(int width, int height, QImage::Format format,bool /* isTextBuffer */, QWidget *widget) : xshmimg(0), xshmpm(0) { QX11Info info = widget->x11Info(); int dd = info.depth(); Visual *vis = (Visual*) info.visual(); if (!X11->use_mitshm || format != QImage::Format_RGB16 && X11->bppForDepth.value(dd) != 32) { image = QImage(width, height, format); // follow good coding practice and set xshminfo attributes, though values not used in this case xshminfo.readOnly = true; xshminfo.shmaddr = 0; xshminfo.shmid = 0; xshminfo.shmseg = 0; return; } xshmimg = XShmCreateImage(X11->display, vis, dd, ZPixmap, 0, &xshminfo, width, height); if (!xshmimg) { qWarning("QNativeImage: Unable to create shared XImage."); return; } bool ok; xshminfo.shmid = shmget(IPC_PRIVATE, xshmimg->bytes_per_line * xshmimg->height, IPC_CREAT | 0700); ok = xshminfo.shmid != -1; if (ok) { xshmimg->data = (char*)shmat(xshminfo.shmid, 0, 0); xshminfo.shmaddr = xshmimg->data; ok = (xshminfo.shmaddr != (char*)-1); if (ok) image = QImage((uchar *)xshmimg->data, width, height, format); } xshminfo.readOnly = false; if (ok) { ok = XShmAttach(X11->display, &xshminfo); XSync(X11->display, False); if (shmctl(xshminfo.shmid, IPC_RMID, 0) == -1) qWarning() << "Error while marking the shared memory segment to be destroyed"; } if (!ok) { qWarning() << "QNativeImage: Unable to attach to shared memory segment."; if (xshmimg->data) { free(xshmimg->data); xshmimg->data = 0; } XDestroyImage(xshmimg); xshmimg = 0; if (xshminfo.shmaddr) shmdt(xshminfo.shmaddr); if (xshminfo.shmid != -1) shmctl(xshminfo.shmid, IPC_RMID, 0); return; } if (X11->use_mitshm_pixmaps) { xshmpm = XShmCreatePixmap(X11->display, DefaultRootWindow(X11->display), xshmimg->data, &xshminfo, width, height, dd); if (!xshmpm) { qWarning() << "QNativeImage: Unable to create shared Pixmap."; } } }
int main (void) { int i; int allocateOK; ximg = NULL; d = XOpenDisplay (NULL); if (!d) fputs ("Couldn't open display\n", stderr), exit (1); screen = DefaultScreen (d); gc = DefaultGC (d, screen); /* Find a visual */ vis.screen = screen; vlist = XGetVisualInfo (d, VisualScreenMask, &vis, &match); if (!vlist) fputs ("No matched visuals\n", stderr), exit (1); vis = vlist[0]; XFree (vlist); // That's not a fair comparison colormap_size is depth in bits! // if (vis.colormap_size < COLORS) // printf("Colormap is too small: %i.\n",vis.colormap_size); // , exit (1); printf("Colour depth: %i\n",vis.colormap_size); win = XCreateSimpleWindow (d, DefaultRootWindow (d), 0, 0, WIN_W, WIN_H, 0, WhitePixel (d, screen), BlackPixel (d, screen)); int xclass=get_xvisinfo_class(vis); // printf("class = %i\n",xclass); stylee = ( vis.depth > 8 ? styleeTrueColor : styleePrivate ); // printf("stylee=%i\n",stylee); if ( get_xvisinfo_class(vis) % 2 == 1) { /* The odd numbers can redefine colors */ // printf("%i\n",get_xvisinfo_class(vis)); colormap = DefaultColormap (d, screen); Visual *defaultVisual=DefaultVisual(d,screen); /* Allocate cells */ allocateOK = (XAllocColorCells (d, colormap, 1, NULL, 0, color, COLORS) != 0); // printf("Allocated OK? %i\n",allocateOK); if (allocateOK) { // printf("Allocated OK\n"); // This doesn't work for installed colormap! /* Modify the colorcells */ for (i = 0; i < COLORS; i++) xrgb[i].pixel = color[i]; XStoreColors (d, colormap, xrgb, COLORS); } else { colormap = XCreateColormap(d,win,defaultVisual,AllocNone); // redocolors(); } // black = XBlackPixel(d,screen); // white = XWhitePixel(d,screen); } else if ( get_xvisinfo_class(vis) == TrueColor) { colormap = DefaultColormap (d, screen); // printf("TrueColor %i = %i\n",xclass,TrueColor); /* This will lookup the color and sets the xrgb[i].pixel value */ // for (i = 0; i < COLORS; i++) // XAllocColor (d, colormap, &xrgb[i]); } else fprintf (stderr, "Not content with visual class %d.\n", get_xvisinfo_class(vis) ), exit (1); /* Find out if MITSHM is supported and useable */ printf ("MITSHM: "); if (XShmQueryVersion (d, &mitshm_major_code, &mitshm_minor_code, &shared_pixmaps)) { int (*handler) (Display *, XErrorEvent *); ximg = XShmCreateImage (d, vis.visual, vis.depth, XShmPixmapFormat (d), NULL, &shminfo, WIN_W, WIN_H); shminfo.shmid = shmget (IPC_PRIVATE, ximg->bytes_per_line * ximg->height, IPC_CREAT | 0777); shminfo.shmaddr = (char *)shmat (shminfo.shmid, 0, 0); ximg->data = (char *)shminfo.shmaddr; handler = XSetErrorHandler (mitshm_handler); XShmAttach (d, &shminfo); /* Tell the server to attach */ XSync (d, 0); XSetErrorHandler (handler); shmctl (shminfo.shmid, IPC_RMID, 0); /* Mark this shm segment for deletion at once. The segment will * automatically become released when both the server and this * client have detached from it. * (Process termination automagically detach shm segments) */ if (!can_use_mitshm) { shmdt (shminfo.shmaddr); ximg = NULL; } } if (ximg == NULL) { can_use_mitshm = 0; /* XInitImage(ximg); */ ximg = XCreateImage (d, vis.visual, vis.depth, ZPixmap, 0, (char *)malloc (WIN_W * WIN_H), WIN_W, WIN_H, 8, 0); } if (can_use_mitshm) printf ("YES!\n"); else printf ("NO, using fallback instead.\n"); // DrawFractal (ximg,xrgb); XSelectInput (d, win, ButtonPressMask | ExposureMask); XMapWindow (d, win); real_main(); // XNextEvent (d, &ev); // switch (ev.type) { // case ButtonPress: // should_quit = 1; // break; // case Expose: // if (can_use_mitshm) // XShmPutImage (d, win, gc, img, 0, 0, 0, 0, WIN_W, WIN_H, True); // else // XPutImage (d, win, gc, img, 0, 0, 0, 0, WIN_W, WIN_H); // break; // default: // break; // } if (get_xvisinfo_class(vis) % 2 == 1 || get_xvisinfo_class(vis) == TrueColor) { unsigned long color[COLORS]; if (allocateOK) { for (i = 0; i < COLORS; i++) color[i] = xrgb[i].pixel; XFreeColors (d, colormap, color, COLORS, 0); } /* Allocated colors freed */ } else { XUninstallColormap (d, colormap); } if (can_use_mitshm) { XShmDetach (d, &shminfo); /* Server detached */ XDestroyImage (ximg); /* Image struct freed */ shmdt (shminfo.shmaddr); /* We're detached */ } else XDestroyImage (ximg); /* Image struct freed */ XDestroyWindow (d, win); /* Window removed */ XCloseDisplay (d); /* Display disconnected */ /* So you can see how your computer compares to your friend's */ getrusage (RUSAGE_SELF, &resource_utilization); float seconds=(float)resource_utilization.ru_utime.tv_sec +(float)resource_utilization.ru_utime.tv_usec*0.000000001; printf("CPU seconds per frame: %f\n",seconds/(float)frameno); // printf ("CPU seconds consumed: %ds and %dµs\n", // (int) resource_utilization.ru_utime.tv_sec, // (int) resource_utilization.ru_utime.tv_usec); return 0; }
/* This name doesn't really cover this function, since it also sets up mouse and keyboard. This is done over here, since on most display targets the mouse and keyboard can't be setup before the display has. */ int x11_window_open_display(int reopen) { int needed_width, needed_height; /* set aspect_ratio, do this early since this can change yarbsize */ mode_set_aspect_ratio((double)screen->width/screen->height); needed_width = sysdep_display_params.width * sysdep_display_params.widthscale; needed_height = sysdep_display_params.yarbsize? sysdep_display_params.yarbsize: sysdep_display_params.height * sysdep_display_params.heightscale; if(!reopen) { XGCValues xgcv; /* setup the sysdep_display_properties struct */ sysdep_display_properties.max_width = -1; sysdep_display_properties.max_height = -1; if (x11_init_palette_info()) return 1; /* create a window */ if (x11_create_window(&window_width, &window_height, X11_FIXED)) return 1; if ((needed_width > window_width) || (needed_height > window_height)) { fprintf (stderr, "OSD ERROR: Window is to small: %dx%d, needed %dx%d\n", needed_width, needed_height, window_width, window_height); return 1; } startx = ((window_width - needed_width) / 2) & ~3; starty = ((window_height - window_height) / 2) & ~3; /* create gc */ gc = XCreateGC (display, window, 0, &xgcv); /* open xinput */ xinput_open(0, ExposureMask); } else { sysdep_display_effect_close(); if ( (needed_width > image->width) || (needed_height > image->height) ) x11_window_destroy_image(); x11_resize_window(&window_width, &window_height, X11_FIXED); } /* create and setup the image */ if (!image) { char *scaled_buffer_ptr; int image_width = sysdep_display_params.widthscale * sysdep_display_params.max_width; int image_height = sysdep_display_params.yarbsize? sysdep_display_params.yarbsize: sysdep_display_params.max_height * sysdep_display_params.heightscale; #ifdef USE_MITSHM if (mit_shm_available && use_mit_shm) x11_window_update_method = X11_MITSHM; else #endif x11_window_update_method = X11_NORMAL; switch (x11_window_update_method) { #ifdef USE_MITSHM case X11_MITSHM: /* Create a MITSHM image. */ fprintf (stderr, "MIT-SHM Extension Available. trying to use... "); x11_mit_shm_error = 0; XSetErrorHandler (x11_test_mit_shm); image = XShmCreateImage (display, screen->root_visual, screen->root_depth, ZPixmap, NULL, &shm_info, image_width, image_height); if (image) { shm_info.readOnly = False; shm_info.shmid = shmget (IPC_PRIVATE, image->bytes_per_line * image->height, (IPC_CREAT | 0777)); if (shm_info.shmid < 0) { fprintf (stderr, "\nError: failed to create MITSHM block.\n"); return 1; } /* And allocate the bitmap buffer. */ image->data = shm_info.shmaddr = (char *) shmat (shm_info.shmid, 0, 0); if (!image->data) { fprintf (stderr, "\nError: failed to allocate MITSHM bitmap buffer.\n"); return 1; } /* Attach the MITSHM block. this will cause an exception if */ /* MIT-SHM is not available. so trap it and process */ if (!XShmAttach (display, &shm_info)) { fprintf (stderr, "\nError: failed to attach MITSHM block.\n"); return 1; } XSync (display, False); /* be sure to get request processed */ /* sleep (2); enought time to notify error if any */ /* Mark segment as deletable after we attach. When all processes detach from the segment (progam exits), it will be deleted. This way it won't be left in memory if we crash or something. Grr, have todo this after X attaches too since slowlaris doesn't like it otherwise */ shmctl(shm_info.shmid, IPC_RMID, NULL); if (!x11_mit_shm_error) { fprintf (stderr, "Success.\nUsing Shared Memory Features to speed up\n"); XSetErrorHandler (None); /* Restore error handler to default */ mit_shm_attached = 1; break; } /* else we have failed clean up before retrying without MITSHM */ shmdt (shm_info.shmaddr); shm_info.shmaddr = NULL; XDestroyImage (image); image = NULL; } XSetErrorHandler (None); /* Restore error handler to default */ fprintf (stderr, "Failed\nReverting to normal XPutImage() mode\n"); x11_window_update_method = X11_NORMAL; #endif case X11_NORMAL: scaled_buffer_ptr=malloc(((screen->root_depth <= 16)? 2:4) * image_width * image_height); if (!scaled_buffer_ptr) { fprintf (stderr, "Error: failed to allocate bitmap buffer.\n"); return 1; } image = XCreateImage (display, screen->root_visual, screen->root_depth, ZPixmap, 0, scaled_buffer_ptr, image_width, image_height, 32, /* image_width always is a multiple of 4 */ 0); if (!image) { free (scaled_buffer_ptr); fprintf (stderr, "OSD ERROR: could not create image.\n"); return 1; } break; default: fprintf (stderr, "Error unknown X11 update method, this shouldn't happen\n"); return 1; } sysdep_display_properties.palette_info.bpp = image->bits_per_pixel; } /* get a blit function */ return !(x11_window_update_display_func=sysdep_display_effect_open()); }
XImage * create_xshm_image (Display *dpy, Visual *visual, unsigned int depth, int format, XShmSegmentInfo *shm_info, unsigned int width, unsigned int height) { #ifndef HAVE_XSHM_EXTENSION return create_fallback (dpy, visual, depth, format, shm_info, width, height); #else /* HAVE_XSHM_EXTENSION */ Status status; XImage *image = 0; if (!get_boolean_resource(dpy, "useSHM", "Boolean") || !XShmQueryExtension (dpy)) { return create_fallback (dpy, visual, depth, format, shm_info, width, height); } CATCH_X_ERROR(dpy); image = XShmCreateImage(dpy, visual, depth, format, NULL, shm_info, width, height); UNCATCH_X_ERROR(dpy); if (shm_got_x_error) return create_fallback (dpy, visual, depth, format, shm_info, width, height); #ifdef DEBUG fprintf(stderr, "\n%s: XShmCreateImage(... %d, %d)\n", progname, width, height); #endif shm_info->shmid = shmget(IPC_PRIVATE, image->bytes_per_line * image->height, IPC_CREAT | 0777); #ifdef DEBUG fprintf(stderr, "%s: shmget(IPC_PRIVATE, %d, IPC_CREAT | 0777) ==> %d\n", progname, image->bytes_per_line * image->height, shm_info->shmid); #endif if (shm_info->shmid == -1) { char buf[1024]; sprintf (buf, "%s: shmget failed", progname); perror(buf); XDestroyImage (image); image = 0; XSync(dpy, False); } else { shm_info->readOnly = False; image->data = shm_info->shmaddr = shmat(shm_info->shmid, 0, 0); #ifdef DEBUG fprintf(stderr, "%s: shmat(%d, 0, 0) ==> %d\n", progname, shm_info->shmid, (int) image->data); #endif CATCH_X_ERROR(dpy); status = XShmAttach(dpy, shm_info); UNCATCH_X_ERROR(dpy); if (shm_got_x_error) status = False; if (!status) { fprintf (stderr, "%s: XShmAttach failed!\n", progname); XDestroyImage (image); XSync(dpy, False); shmdt (shm_info->shmaddr); image = 0; } #ifdef DEBUG else fprintf(stderr, "%s: XShmAttach(dpy, shm_info) ==> True\n", progname); #endif XSync(dpy, False); /* Delete the shared segment right now; the segment won't actually go away until both the client and server have deleted it. The server will delete it as soon as the client disconnects, so we should delete our side early in case of abnormal termination. (And note that, in the context of xscreensaver, abnormal termination is the rule rather than the exception, so this would leak like a sieve if we didn't do this...) #### Are we leaking anyway? Perhaps because of the window of opportunity between here and the XShmAttach call above, during which we might be killed? Do we need to establish a signal handler for this case? */ shmctl (shm_info->shmid, IPC_RMID, 0); #ifdef DEBUG fprintf(stderr, "%s: shmctl(%d, IPC_RMID, 0)\n\n", progname, shm_info->shmid); #endif } if (!image) { return create_fallback (dpy, visual, depth, format, shm_info, width, height); } return image; #endif /* HAVE_XSHM_EXTENSION */ }
/* * create XImage */ void fastViewer::createImage(const image& img) { int screen; display_info_s& di = display_info; XWindowAttributes win_attributes; bool resizeWin = false; if ((di.height != img.rows()) || (di.width != img.columns())) { resizeWin = true; } di.height = img.rows(); di.width = img.columns(); if (di.win == 0) { createWindow(); } if (resizeWin) { XResizeWindow(di.display,di.win,di.width,di.height); } screen = DefaultScreen(di.display); XGetWindowAttributes(di.display, di.win, &win_attributes); di.depth = win_attributes.depth; // TODO: maybe screen->root_depth is more precise than win_attr.depth // We should try it. // check if the X-Server has a 32 bit interface if (di.depth < 24) { throw exception("Error: Fast Viewer works only with 32 bit depth!"); } if (useShareMemory) { // // Shared Memory Setup // di.shmimage = XShmCreateImage(di.display, DefaultVisual(di.display, screen), di.depth, ZPixmap, NULL, &shminfo, di.width, di.height); if(isNull(di.shmimage)) { throw exception("fastViewer::shmimage == NULL:"); } int sharedMemSize = di.shmimage->bytes_per_line * di.shmimage->height; shminfo.shmid = shmget(IPC_PRIVATE, sharedMemSize, IPC_CREAT | 0777); if(shminfo.shmid < 0) { std::string str; str = "fastViewer::shmget failed:"; str += strerror(errno); throw exception(str); } shminfo.shmaddr = (char *) shmat(shminfo.shmid, (void *) 0, 0); if (shminfo.shmaddr == 0) { std::string str; str = "fastViewer::shmmat failed:"; str += std::strerror(errno); throw exception(str); } di.shmimage->data = shminfo.shmaddr; XShmAttach(di.display, &shminfo); data.useExternData(di.height,di.width,(rgbPixel*)di.shmimage->data); data.fill(img); } else { // // without shared memory // const int blockSize = img.rows()*img.columns()*4; remoteData = new char[blockSize]; data.useExternData(di.height,di.width,(rgbPixel*)remoteData); data.fill(img); di.shmimage = XCreateImage(di.display, DefaultVisual(di.display, screen), di.depth, ZPixmap, 0, remoteData, di.width, di.height,8,0); if(isNull(di.shmimage)) { throw exception("fastViewer::shmimage == NULL:"); } } }
static int video_arch_frame_buffer_alloc(video_canvas_t *canvas, unsigned int width, unsigned int height) { int sizeofpixel = sizeof(BYTE); Display *display; #ifdef USE_MITSHM int (*olderrorhandler)(Display *, XErrorEvent *); int dummy; #endif #ifdef USE_MITSHM canvas->using_mitshm = use_mitshm; #endif display = x11ui_get_display_ptr(); /* sizeof(PIXEL) is not always what we are using. I guess this should be checked from the XImage but I'm lazy... */ if (canvas->depth > 8) { sizeofpixel *= 2; } if (canvas->depth > 16) { sizeofpixel *= 2; } #ifdef HAVE_XVIDEO canvas->xv_image = NULL; if (canvas->videoconfig->hwscale) { #if defined(__QNX__) || defined(MINIX_SUPPORT) XShmSegmentInfo* shminfo = NULL; #else XShmSegmentInfo* shminfo = use_mitshm ? &canvas->xshm_info : NULL; #endif canvas->xv_image = create_yuv_image(display, canvas->xv_port, canvas->xv_format, width, height, shminfo); if (!(canvas->xv_image)) { return -1; } /* Copy data for architecture independent rendering. */ canvas->yuv_image.width = canvas->xv_image->width; canvas->yuv_image.height = canvas->xv_image->height; canvas->yuv_image.data_size = canvas->xv_image->data_size; canvas->yuv_image.num_planes = canvas->xv_image->num_planes; canvas->yuv_image.pitches = canvas->xv_image->pitches; canvas->yuv_image.offsets = canvas->xv_image->offsets; canvas->yuv_image.data = (unsigned char *)canvas->xv_image->data; log_message(x11video_log, "Successfully initialized using XVideo (%dx%d %.4s).", width, height, canvas->xv_format.label); return 0; } #endif /* HAVE_XVIDEO */ /* Round up to 32-bit boundary (used in XCreateImage). */ width = (width + 3) & ~0x3; #ifdef USE_MITSHM tryagain: if (canvas->using_mitshm) { DEBUG_MITSHM(("frame_buffer_alloc(): allocating XImage with MITSHM, %d x %d pixels...", width, height)); canvas->x_image = XShmCreateImage(display, visual, canvas->depth, ZPixmap, NULL, &(canvas->xshm_info), width, height); if (!canvas->x_image) { log_warning(x11video_log, "Cannot allocate XImage with XShm; falling back to non MITSHM extension mode."); canvas->using_mitshm = 0; goto tryagain; } DEBUG_MITSHM(("Done.")); DEBUG_MITSHM(("frame_buffer_alloc(): shmgetting %ld bytes...", (long)canvas->x_image->bytes_per_line * canvas->x_image->height)); canvas->xshm_info.shmid = shmget(IPC_PRIVATE, canvas->x_image->bytes_per_line * canvas->x_image->height, IPC_CREAT | 0604); if (canvas->xshm_info.shmid == -1) { log_warning(x11video_log, "Cannot get shared memory; falling back to non MITSHM extension mode."); XDestroyImage(canvas->x_image); canvas->using_mitshm = 0; goto tryagain; } DEBUG_MITSHM(("Done, id = 0x%x.", i->xshm_info.shmid)); DEBUG_MITSHM(("frame_buffer_alloc(): getting address... ")); canvas->xshm_info.shmaddr = shmat(canvas->xshm_info.shmid, 0, 0); canvas->x_image->data = canvas->xshm_info.shmaddr; if (canvas->xshm_info.shmaddr == (char *)-1) { log_warning(x11video_log, "Cannot get shared memory address; falling back to non MITSHM extension mode."); shmctl(canvas->xshm_info.shmid,IPC_RMID,0); XDestroyImage(canvas->x_image); canvas->using_mitshm = 0; goto tryagain; } DEBUG_MITSHM(("0x%lx OK.", (unsigned long) i->xshm_info.shmaddr)); canvas->xshm_info.readOnly = True; mitshm_failed = 0; XQueryExtension(display,"MIT-SHM",&shmmajor,&dummy,&dummy); olderrorhandler = XSetErrorHandler(shmhandler); if (!XShmAttach(display, &(canvas->xshm_info))) { log_warning(x11video_log, "Cannot attach shared memory; falling back to non MITSHM extension mode."); shmdt(canvas->xshm_info.shmaddr); shmctl(canvas->xshm_info.shmid,IPC_RMID,0); XDestroyImage(canvas->x_image); canvas->using_mitshm = 0; goto tryagain; } /* Wait for XShmAttach to fail or to succede. */ XSync(display,False); XSetErrorHandler(olderrorhandler); /* Mark memory segment for automatic deletion. */ shmctl(canvas->xshm_info.shmid, IPC_RMID, 0); if (mitshm_failed) { log_warning(x11video_log, "Cannot attach shared memory; falling back to non MITSHM extension mode."); shmdt(canvas->xshm_info.shmaddr); XDestroyImage(canvas->x_image); canvas->using_mitshm = 0; goto tryagain; } DEBUG_MITSHM((_("MITSHM initialization succeed.\n"))); video_refresh_func((void (*)(void))XShmPutImage); } else #endif { /* !i->using_mitshm */ char *data; data = lib_malloc(width * height * sizeofpixel); if (data == NULL) { return -1; } canvas->x_image = XCreateImage(display, visual, canvas->depth, ZPixmap, 0, data, width, height, 32, 0); if (!canvas->x_image) { return -1; } video_refresh_func((void (*)(void))XPutImage); } #ifdef USE_MITSHM log_message(x11video_log, "Successfully initialized%s shared memory.", (canvas->using_mitshm) ? ", using" : " without"); if (!(canvas->using_mitshm)) { log_warning(x11video_log, "Performance will be poor."); } #else log_message(x11video_log, "Successfully initialized without shared memory."); #endif return 0; }
/** * Initialize the x11 grab device demuxer (public device demuxer API). * * @param s1 Context from avformat core * @return <ul> * <li>AVERROR(ENOMEM) no memory left</li> * <li>AVERROR(EIO) other failure case</li> * <li>0 success</li> * </ul> */ static int x11grab_read_header(AVFormatContext *s1) { struct x11_grab *x11grab = s1->priv_data; Display *dpy; AVStream *st = NULL; enum PixelFormat input_pixfmt; XImage *image; int x_off = 0; int y_off = 0; int screen; int use_shm; char *dpyname, *offset; int ret = 0; AVRational framerate; dpyname = av_strdup(s1->filename); if (!dpyname) goto out; offset = strchr(dpyname, '+'); if (offset) { sscanf(offset, "%d,%d", &x_off, &y_off); x11grab->draw_mouse = !strstr(offset, "nomouse"); *offset= 0; } if ((ret = av_parse_video_size(&x11grab->width, &x11grab->height, x11grab->video_size)) < 0) { av_log(s1, AV_LOG_ERROR, "Couldn't parse video size.\n"); goto out; } if ((ret = av_parse_video_rate(&framerate, x11grab->framerate)) < 0) { av_log(s1, AV_LOG_ERROR, "Could not parse framerate: %s.\n", x11grab->framerate); goto out; } av_log(s1, AV_LOG_INFO, "device: %s -> display: %s x: %d y: %d width: %d height: %d\n", s1->filename, dpyname, x_off, y_off, x11grab->width, x11grab->height); dpy = XOpenDisplay(dpyname); av_freep(&dpyname); if(!dpy) { av_log(s1, AV_LOG_ERROR, "Could not open X display.\n"); ret = AVERROR(EIO); goto out; } st = avformat_new_stream(s1, NULL); if (!st) { ret = AVERROR(ENOMEM); goto out; } avpriv_set_pts_info(st, 64, 1, 1000000); /* 64 bits pts in us */ screen = DefaultScreen(dpy); if (x11grab->follow_mouse) { int screen_w, screen_h; Window w; screen_w = DisplayWidth(dpy, screen); screen_h = DisplayHeight(dpy, screen); XQueryPointer(dpy, RootWindow(dpy, screen), &w, &w, &x_off, &y_off, &ret, &ret, &ret); x_off -= x11grab->width / 2; y_off -= x11grab->height / 2; x_off = FFMIN(FFMAX(x_off, 0), screen_w - x11grab->width); y_off = FFMIN(FFMAX(y_off, 0), screen_h - x11grab->height); av_log(s1, AV_LOG_INFO, "followmouse is enabled, resetting grabbing region to x: %d y: %d\n", x_off, y_off); } use_shm = XShmQueryExtension(dpy); av_log(s1, AV_LOG_INFO, "shared memory extension%s found\n", use_shm ? "" : " not"); if(use_shm) { int scr = XDefaultScreen(dpy); image = XShmCreateImage(dpy, DefaultVisual(dpy, scr), DefaultDepth(dpy, scr), ZPixmap, NULL, &x11grab->shminfo, x11grab->width, x11grab->height); x11grab->shminfo.shmid = shmget(IPC_PRIVATE, image->bytes_per_line * image->height, IPC_CREAT|0777); if (x11grab->shminfo.shmid == -1) { av_log(s1, AV_LOG_ERROR, "Fatal: Can't get shared memory!\n"); ret = AVERROR(ENOMEM); goto out; } x11grab->shminfo.shmaddr = image->data = shmat(x11grab->shminfo.shmid, 0, 0); x11grab->shminfo.readOnly = False; if (!XShmAttach(dpy, &x11grab->shminfo)) { av_log(s1, AV_LOG_ERROR, "Fatal: Failed to attach shared memory!\n"); /* needs some better error subroutine :) */ ret = AVERROR(EIO); goto out; } } else { image = XGetImage(dpy, RootWindow(dpy, screen), x_off,y_off, x11grab->width, x11grab->height, AllPlanes, ZPixmap); } switch (image->bits_per_pixel) { case 8: av_log (s1, AV_LOG_DEBUG, "8 bit palette\n"); input_pixfmt = PIX_FMT_PAL8; break; case 16: if ( image->red_mask == 0xf800 && image->green_mask == 0x07e0 && image->blue_mask == 0x001f ) { av_log (s1, AV_LOG_DEBUG, "16 bit RGB565\n"); input_pixfmt = PIX_FMT_RGB565; } else if (image->red_mask == 0x7c00 && image->green_mask == 0x03e0 && image->blue_mask == 0x001f ) { av_log(s1, AV_LOG_DEBUG, "16 bit RGB555\n"); input_pixfmt = PIX_FMT_RGB555; } else { av_log(s1, AV_LOG_ERROR, "RGB ordering at image depth %i not supported ... aborting\n", image->bits_per_pixel); av_log(s1, AV_LOG_ERROR, "color masks: r 0x%.6lx g 0x%.6lx b 0x%.6lx\n", image->red_mask, image->green_mask, image->blue_mask); ret = AVERROR(EIO); goto out; } break; case 24: if ( image->red_mask == 0xff0000 && image->green_mask == 0x00ff00 && image->blue_mask == 0x0000ff ) { input_pixfmt = PIX_FMT_BGR24; } else if ( image->red_mask == 0x0000ff && image->green_mask == 0x00ff00 && image->blue_mask == 0xff0000 ) { input_pixfmt = PIX_FMT_RGB24; } else { av_log(s1, AV_LOG_ERROR,"rgb ordering at image depth %i not supported ... aborting\n", image->bits_per_pixel); av_log(s1, AV_LOG_ERROR, "color masks: r 0x%.6lx g 0x%.6lx b 0x%.6lx\n", image->red_mask, image->green_mask, image->blue_mask); ret = AVERROR(EIO); goto out; } break; case 32: input_pixfmt = PIX_FMT_0RGB32; break; default: av_log(s1, AV_LOG_ERROR, "image depth %i not supported ... aborting\n", image->bits_per_pixel); ret = AVERROR(EINVAL); goto out; } x11grab->frame_size = x11grab->width * x11grab->height * image->bits_per_pixel/8; x11grab->dpy = dpy; x11grab->time_base = (AVRational){framerate.den, framerate.num}; x11grab->time_frame = av_gettime() / av_q2d(x11grab->time_base); x11grab->x_off = x_off; x11grab->y_off = y_off; x11grab->image = image; x11grab->use_shm = use_shm; st->codec->codec_type = AVMEDIA_TYPE_VIDEO; st->codec->codec_id = CODEC_ID_RAWVIDEO; st->codec->width = x11grab->width; st->codec->height = x11grab->height; st->codec->pix_fmt = input_pixfmt; st->codec->time_base = x11grab->time_base; st->codec->bit_rate = x11grab->frame_size * 1/av_q2d(x11grab->time_base) * 8; out: av_free(dpyname); return ret; }
DFBResult dfb_x11_image_init_handler( DFBX11 *x11, x11Image *image ) { Visual *visual; XImage *ximage; D_MAGIC_ASSERT( image, x11Image ); if (!x11->use_shm) return DFB_UNSUPPORTED; /* Lookup visual. */ visual = x11->visuals[DFB_PIXELFORMAT_INDEX(image->format)]; if (!visual) return DFB_UNSUPPORTED; image->visual = visual; XLockDisplay( x11->display ); ximage = XShmCreateImage( x11->display, image->visual, image->depth, ZPixmap, NULL, &image->seginfo, image->width, image->height ); if (!ximage) { D_ERROR( "X11/ShmImage: Error creating shared image (XShmCreateImage)!\n"); XUnlockDisplay( x11->display ); return DFB_FAILURE; } /* we firstly create our shared memory segment with the size we need, and correct permissions for the owner, the group and the world --> 0777 */ image->seginfo.shmid = shmget( IPC_PRIVATE, ximage->bytes_per_line * ximage->height, IPC_CREAT | 0777 ); if (image->seginfo.shmid < 0) goto error; /* Then, we have to attach the segment to our process, and we let the function search the correct memory place --> NULL. It's safest ! */ image->seginfo.shmaddr = shmat( image->seginfo.shmid, NULL, 0 ); if (!image->seginfo.shmaddr) goto error_shmat; ximage->data = image->seginfo.shmaddr; /* We set the buffer in Read and Write mode */ image->seginfo.readOnly = False; if (!XShmAttach( x11->display, &image->seginfo )) goto error_xshmattach; image->ximage = ximage; image->pitch = ximage->bytes_per_line; image->pixmap = XShmCreatePixmap( x11->display, DefaultRootWindow(x11->display), ximage->data, &image->seginfo, image->width, image->height, image->depth ); image->gc = XCreateGC( x11->display, image->pixmap, 0, NULL ); XUnlockDisplay( x11->display ); return DFB_OK; error_xshmattach: shmdt( image->seginfo.shmaddr ); error_shmat: shmctl( image->seginfo.shmid, IPC_RMID, NULL ); error: XDestroyImage( ximage ); XUnlockDisplay( x11->display ); return DFB_FAILURE; }
static inline int up_x11mapsharedmem(int depth, unsigned int fblen) { #ifndef CONFIG_SIM_X11NOSHM Status result; #endif atexit(up_x11uninitX); g_shmcheckpoint = 1; b_useshm = 0; #ifndef CONFIG_SIM_X11NOSHM if (XShmQueryExtension(g_display)) { b_useshm = 1; printf("Using shared memory.\n"); up_x11traperrors(); g_image = XShmCreateImage(g_display, DefaultVisual(g_display, g_screen), depth, ZPixmap, NULL, &g_xshminfo, g_fbpixelwidth, g_fbpixelheight); if (up_x11untraperrors()) { up_x11uninitialize(); goto shmerror; } if (!g_image) { fprintf(stderr,"Unable to create g_image."); return -1; } g_shmcheckpoint++; g_xshminfo.shmid = shmget(IPC_PRIVATE, g_image->bytes_per_line * g_image->height, IPC_CREAT | 0777); if (g_xshminfo.shmid < 0) { up_x11uninitialize(); goto shmerror; } g_shmcheckpoint++; g_image->data = (char *) shmat(g_xshminfo.shmid, 0, 0); if (g_image->data == ((char *) -1)) { up_x11uninitialize(); goto shmerror; } g_shmcheckpoint++; g_xshminfo.shmaddr = g_image->data; g_xshminfo.readOnly = 0; up_x11traperrors(); result = XShmAttach(g_display, &g_xshminfo); if (up_x11untraperrors() || !result) { up_x11uninitialize(); goto shmerror; } g_shmcheckpoint++; } else #endif if (!b_useshm) { #ifndef CONFIG_SIM_X11NOSHM shmerror: #endif b_useshm = 0; g_framebuffer = (unsigned char*)malloc(fblen); g_image = XCreateImage(g_display, DefaultVisual(g_display,g_screen), depth, ZPixmap, 0, (char*)g_framebuffer, g_fbpixelwidth, g_fbpixelheight, 8, 0); if (g_image == NULL) { fprintf(stderr, "Unable to create g_image\n"); return -1; } g_shmcheckpoint++; } return 0; }
static void getMyXImage(void) { #ifdef HAVE_SHM if (mLocalDisplay && XShmQueryExtension(mDisplay)) Shmem_Flag = 1; else { Shmem_Flag = 0; mp_msg(MSGT_VO, MSGL_WARN, "Shared memory not supported\nReverting to normal Xlib\n"); } if (Shmem_Flag) CompletionType = XShmGetEventBase(mDisplay) + ShmCompletion; if (Shmem_Flag) { myximage = XShmCreateImage(mDisplay, vinfo.visual, depth, ZPixmap, NULL, &Shminfo[0], image_width, image_height); if (myximage == NULL) { mp_msg(MSGT_VO, MSGL_WARN, "Shared memory error,disabling ( Ximage error )\n"); goto shmemerror; } Shminfo[0].shmid = shmget(IPC_PRIVATE, myximage->bytes_per_line * myximage->height, IPC_CREAT | 0777); if (Shminfo[0].shmid < 0) { XDestroyImage(myximage); mp_msg(MSGT_VO, MSGL_V, "%s\n", strerror(errno)); //perror( strerror( errno ) ); mp_msg(MSGT_VO, MSGL_WARN, "Shared memory error,disabling ( seg id error )\n"); goto shmemerror; } Shminfo[0].shmaddr = (char *) shmat(Shminfo[0].shmid, 0, 0); if (Shminfo[0].shmaddr == ((char *) -1)) { XDestroyImage(myximage); if (Shminfo[0].shmaddr != ((char *) -1)) shmdt(Shminfo[0].shmaddr); mp_msg(MSGT_VO, MSGL_WARN, "Shared memory error,disabling ( address error )\n"); goto shmemerror; } myximage->data = Shminfo[0].shmaddr; ImageData = (unsigned char *) myximage->data; Shminfo[0].readOnly = False; XShmAttach(mDisplay, &Shminfo[0]); XSync(mDisplay, False); if (gXErrorFlag) { XDestroyImage(myximage); shmdt(Shminfo[0].shmaddr); mp_msg(MSGT_VO, MSGL_WARN, "Shared memory error,disabling.\n"); gXErrorFlag = 0; goto shmemerror; } else shmctl(Shminfo[0].shmid, IPC_RMID, 0); { static int firstTime = 1; if (firstTime) { mp_msg(MSGT_VO, MSGL_V, "Sharing memory.\n"); firstTime = 0; } } } else { shmemerror: Shmem_Flag = 0; #endif myximage = XCreateImage(mDisplay, vinfo.visual, depth, ZPixmap, 0, NULL, image_width, image_height, 8, 0); ImageDataOrig = malloc(myximage->bytes_per_line * image_height + 32); myximage->data = ImageDataOrig + 16 - ((long)ImageDataOrig & 15); memset(myximage->data, 0, myximage->bytes_per_line * image_height); ImageData = myximage->data; #ifdef HAVE_SHM } #endif }
/** * Allocate a shared memory XImage back buffer for the given XMesaBuffer. * Return: GL_TRUE if success, GL_FALSE if error */ static GLboolean alloc_back_shm_ximage(XMesaBuffer b, GLuint width, GLuint height) { /* * We have to do a _lot_ of error checking here to be sure we can * really use the XSHM extension. It seems different servers trigger * errors at different points if the extension won't work. Therefore * we have to be very careful... */ GC gc; int (*old_handler)(XMesaDisplay *, XErrorEvent *); if (width == 0 || height == 0) { /* this will be true the first time we're called on 'b' */ return GL_FALSE; } b->backxrb->ximage = XShmCreateImage(b->xm_visual->display, b->xm_visual->visinfo->visual, b->xm_visual->visinfo->depth, ZPixmap, NULL, &b->shminfo, width, height); if (b->backxrb->ximage == NULL) { _mesa_warning(NULL, "alloc_back_buffer: Shared memory error (XShmCreateImage), disabling.\n"); b->shm = 0; return GL_FALSE; } b->shminfo.shmid = shmget(IPC_PRIVATE, b->backxrb->ximage->bytes_per_line * b->backxrb->ximage->height, IPC_CREAT|0777); if (b->shminfo.shmid < 0) { _mesa_warning(NULL, "shmget failed while allocating back buffer.\n"); XDestroyImage(b->backxrb->ximage); b->backxrb->ximage = NULL; _mesa_warning(NULL, "alloc_back_buffer: Shared memory error (shmget), disabling.\n"); b->shm = 0; return GL_FALSE; } b->shminfo.shmaddr = b->backxrb->ximage->data = (char*)shmat(b->shminfo.shmid, 0, 0); if (b->shminfo.shmaddr == (char *) -1) { _mesa_warning(NULL, "shmat() failed while allocating back buffer.\n"); XDestroyImage(b->backxrb->ximage); shmctl(b->shminfo.shmid, IPC_RMID, 0); b->backxrb->ximage = NULL; _mesa_warning(NULL, "alloc_back_buffer: Shared memory error (shmat), disabling.\n"); b->shm = 0; return GL_FALSE; } b->shminfo.readOnly = False; mesaXErrorFlag = 0; old_handler = XSetErrorHandler(mesaHandleXError); /* This may trigger the X protocol error we're ready to catch: */ XShmAttach(b->xm_visual->display, &b->shminfo); XSync(b->xm_visual->display, False); if (mesaXErrorFlag) { /* we are on a remote display, this error is normal, don't print it */ XFlush(b->xm_visual->display); mesaXErrorFlag = 0; XDestroyImage(b->backxrb->ximage); shmdt(b->shminfo.shmaddr); shmctl(b->shminfo.shmid, IPC_RMID, 0); b->backxrb->ximage = NULL; b->shm = 0; (void) XSetErrorHandler(old_handler); return GL_FALSE; } shmctl(b->shminfo.shmid, IPC_RMID, 0); /* nobody else needs it */ /* Finally, try an XShmPutImage to be really sure the extension works */ gc = XCreateGC(b->xm_visual->display, b->frontxrb->drawable, 0, NULL); XShmPutImage(b->xm_visual->display, b->frontxrb->drawable, gc, b->backxrb->ximage, 0, 0, 0, 0, 1, 1 /*one pixel*/, False); XSync(b->xm_visual->display, False); XFreeGC(b->xm_visual->display, gc); (void) XSetErrorHandler(old_handler); if (mesaXErrorFlag) { XFlush(b->xm_visual->display); mesaXErrorFlag = 0; XDestroyImage(b->backxrb->ximage); shmdt(b->shminfo.shmaddr); shmctl(b->shminfo.shmid, IPC_RMID, 0); b->backxrb->ximage = NULL; b->shm = 0; return GL_FALSE; } return GL_TRUE; }
Bool dfb_x11_open_window( DFBX11 *x11, XWindow** ppXW, int iXPos, int iYPos, int iWidth, int iHeight, DFBSurfacePixelFormat format ) { XWindow *xw; XSetWindowAttributes attr = { .background_pixmap = 0 }; void *old_error_handler = 0; unsigned int cw_mask = CWEventMask; D_DEBUG_AT( X11_Window, "Creating %4dx%4d %s window...\n", iWidth, iHeight, dfb_pixelformat_name(format) ); xw = D_CALLOC( 1, sizeof(XWindow) ); if (!xw) return D_OOM(); /* We set the structure as needed for our window */ xw->width = iWidth; xw->height = iHeight; xw->display = x11->display; xw->screenptr = DefaultScreenOfDisplay(xw->display); xw->screennum = DefaultScreen(xw->display); xw->depth = DefaultDepthOfScreen(xw->screenptr); xw->visual = DefaultVisualOfScreen(xw->screenptr); attr.event_mask = ButtonPressMask | ButtonReleaseMask | PointerMotionMask | KeyPressMask | KeyReleaseMask | ExposureMask | StructureNotifyMask; if (dfb_config->x11_borderless) { attr.override_redirect = True; cw_mask |= CWOverrideRedirect; } XLockDisplay( x11->display ); old_error_handler = XSetErrorHandler( error_handler ); error_code = 0; xw->window = XCreateWindow( xw->display, RootWindowOfScreen(xw->screenptr), iXPos, iYPos, iWidth, iHeight, 0, xw->depth, InputOutput, xw->visual, cw_mask, &attr ); XSync( xw->display, False ); if (!xw->window || error_code) { D_FREE( xw ); XUnlockDisplay( x11->display ); return False; } XSizeHints Hints; /* * Here we inform the function of what we are going to change for the * window (there's also PPosition but it's obsolete) */ Hints.flags = PSize | PMinSize | PMaxSize; /* * Now we set the structure to the values we need for width & height. * For esthetic reasons we set Width=MinWidth=MaxWidth. * The same goes for Height. You can try whith differents values, or * let's use Hints.flags=Psize; and resize your window.. */ Hints.min_width = Hints.max_width = Hints.base_width = xw->width; Hints.min_height = Hints.max_height = Hints.base_height = xw->height; /* Now we can set the size hints for the specified window */ XSetWMNormalHints(xw->display,xw->window,&Hints); /* We change the title of the window (default:Untitled) */ XStoreName(xw->display,xw->window,"DFB X11 system window"); xw->gc = XCreateGC(xw->display, xw->window, 0, NULL); #if 0 // Create a null cursor Pixmap pixmp1; Pixmap pixmp2; XColor fore; XColor back; char zero = 0; pixmp1 = XCreateBitmapFromData( xw->display, xw->window, &zero, 1, 1 ); pixmp2 = XCreateBitmapFromData( xw->display, xw->window, &zero, 1, 1 ); xw->NullCursor = XCreatePixmapCursor( xw->display, pixmp1, pixmp2, &fore, &back, 0, 0 ); XFreePixmap ( xw->display, pixmp1 ); XFreePixmap ( xw->display, pixmp2 ); XDefineCursor( xw->display, xw->window, xw->NullCursor ); #endif /* maps the window and raises it to the top of the stack */ XMapRaised( xw->display, xw->window ); if (x11->use_shm) { // Shared memory xw->shmseginfo=(XShmSegmentInfo *)D_CALLOC(1, sizeof(XShmSegmentInfo)); if (!xw->shmseginfo) { x11->use_shm = false; goto no_shm; } xw->ximage=XShmCreateImage(xw->display, xw->visual, xw->depth, ZPixmap, NULL,xw->shmseginfo, xw->width, xw->height * 2); XSync( xw->display, False ); if (!xw->ximage || error_code) { D_ERROR("X11: Error creating shared image (XShmCreateImage) \n"); x11->use_shm = false; D_FREE(xw->shmseginfo); error_code = 0; goto no_shm; } xw->bpp = (xw->ximage->bits_per_pixel + 7) / 8; /* we firstly create our shared memory segment with the size we need, and correct permissions for the owner, the group and the world --> 0777 */ xw->shmseginfo->shmid=shmget(IPC_PRIVATE, xw->ximage->bytes_per_line * xw->ximage->height * 2, IPC_CREAT|0777); if (xw->shmseginfo->shmid<0) { x11->use_shm = false; XDestroyImage(xw->ximage); D_FREE(xw->shmseginfo); goto no_shm; } /* Then, we have to attach the segment to our process, and we let the function search the correct memory place --> NULL. It's safest ! */ xw->shmseginfo->shmaddr = shmat( xw->shmseginfo->shmid, NULL, 0 ); if (!xw->shmseginfo->shmaddr) { x11->use_shm = false; shmctl(xw->shmseginfo->shmid,IPC_RMID,NULL); XDestroyImage(xw->ximage); D_FREE(xw->shmseginfo); goto no_shm; } /* We set the buffer in Read and Write mode */ xw->shmseginfo->readOnly=False; xw->virtualscreen= xw->ximage->data = xw->shmseginfo->shmaddr; XSetErrorHandler( error_handler_shm ); XShmAttach(x11->display,xw->shmseginfo); XShmPutImage(x11->display, xw->window, xw->gc, xw->ximage, 0, 0, 0, 0, 1, 1, False); XSync(x11->display, False); XSetErrorHandler( error_handler ); if (!x11->use_shm) { shmdt(xw->shmseginfo->shmaddr); shmctl(xw->shmseginfo->shmid,IPC_RMID,NULL); XDestroyImage(xw->ximage); D_FREE(xw->shmseginfo); } } no_shm: if (!x11->use_shm) { int pitch; xw->bpp = (xw->depth > 16) ? 4 : (xw->depth > 8) ? 2 : 1; pitch = (xw->bpp * xw->width + 3) & ~3; /* Use malloc(), not D_MALLOC() here, because XCreateImage() * will call free() on this data. */ xw->virtualscreen = malloc ( 2 * xw->height * pitch ); xw->ximage = XCreateImage( xw->display, xw->visual, xw->depth, ZPixmap, 0, xw->virtualscreen, xw->width, xw->height * 2, 32, pitch ); XSync( xw->display, False ); if (!xw->ximage || error_code) { D_ERROR( "X11/Window: XCreateImage( Visual %02lu, depth %d, size %dx%d, buffer %p [%d] ) failed!\n", xw->visual->visualid, xw->depth, xw->width, xw->height * 2, xw->virtualscreen, pitch ); XFreeGC(xw->display,xw->gc); XDestroyWindow(xw->display,xw->window); XSetErrorHandler( old_error_handler ); XUnlockDisplay( x11->display ); D_FREE( xw ); return False; } } XSetErrorHandler( old_error_handler ); XUnlockDisplay( x11->display ); D_INFO( "X11/Display: %ssing XShm.\n", x11->use_shm ? "U" : "Not u" ); (*ppXW) = xw; return True; } void dfb_x11_close_window( DFBX11 *x11, XWindow* xw ) { if (x11->use_shm) { XShmDetach( xw->display, xw->shmseginfo ); shmdt( xw->shmseginfo->shmaddr ); shmctl( xw->shmseginfo->shmid, IPC_RMID, NULL ); D_FREE( xw->shmseginfo ); } XDestroyImage( xw->ximage ); XFreeGC( xw->display, xw->gc ); XDestroyWindow( xw->display, xw->window ); #if 0 XFreeCursor( xw->display, xw->NullCursor ); #endif D_FREE( xw ); }
static bool getMyXImage(struct priv *p, int foo) { struct vo *vo = p->vo; #if HAVE_SHM && HAVE_XEXT if (vo->x11->display_is_local && XShmQueryExtension(vo->x11->display)) { p->Shmem_Flag = 1; vo->x11->ShmCompletionEvent = XShmGetEventBase(vo->x11->display) + ShmCompletion; } else { p->Shmem_Flag = 0; MP_WARN(vo, "Shared memory not supported\nReverting to normal Xlib\n"); } if (p->Shmem_Flag) { p->myximage[foo] = XShmCreateImage(vo->x11->display, p->vinfo.visual, p->depth, ZPixmap, NULL, &p->Shminfo[foo], p->image_width, p->image_height); if (p->myximage[foo] == NULL) { MP_WARN(vo, "Shared memory error,disabling ( Ximage error )\n"); goto shmemerror; } p->Shminfo[foo].shmid = shmget(IPC_PRIVATE, p->myximage[foo]->bytes_per_line * p->myximage[foo]->height, IPC_CREAT | 0777); if (p->Shminfo[foo].shmid < 0) { XDestroyImage(p->myximage[foo]); MP_WARN(vo, "Shared memory error,disabling ( seg id error )\n"); goto shmemerror; } p->Shminfo[foo].shmaddr = (char *) shmat(p->Shminfo[foo].shmid, 0, 0); if (p->Shminfo[foo].shmaddr == ((char *) -1)) { XDestroyImage(p->myximage[foo]); MP_WARN(vo, "Shared memory error,disabling ( address error )\n"); goto shmemerror; } p->myximage[foo]->data = p->Shminfo[foo].shmaddr; p->Shminfo[foo].readOnly = False; XShmAttach(vo->x11->display, &p->Shminfo[foo]); XSync(vo->x11->display, False); shmctl(p->Shminfo[foo].shmid, IPC_RMID, 0); } else { shmemerror: p->Shmem_Flag = 0; #endif MP_VERBOSE(vo, "Not using SHM.\n"); p->myximage[foo] = XCreateImage(vo->x11->display, p->vinfo.visual, p->depth, ZPixmap, 0, NULL, p->image_width, p->image_height, 8, 0); if (!p->myximage[foo]) { MP_WARN(vo, "could not allocate image"); return false; } p->myximage[foo]->data = calloc(1, p->myximage[foo]->bytes_per_line * p->image_height + 32); #if HAVE_SHM && HAVE_XEXT } #endif return true; }
static void SetupImage (void) { TakedownImage(); #ifdef MITSHM GUI.use_shared_memory = TRUE; int major, minor; Bool shared; if (!XShmQueryVersion(GUI.display, &major, &minor, &shared) || !shared) GUI.image = NULL; else GUI.image = XShmCreateImage(GUI.display, GUI.visual, GUI.depth, ZPixmap, NULL, &GUI.sm_info, SNES_WIDTH * 2, SNES_HEIGHT_EXTENDED * 2); if (!GUI.image) GUI.use_shared_memory = FALSE; else { GUI.sm_info.shmid = shmget(IPC_PRIVATE, GUI.image->bytes_per_line * GUI.image->height, IPC_CREAT | 0777); if (GUI.sm_info.shmid < 0) { XDestroyImage(GUI.image); GUI.use_shared_memory = FALSE; } else { GUI.image->data = GUI.sm_info.shmaddr = (char *) shmat(GUI.sm_info.shmid, 0, 0); if (!GUI.image->data) { XDestroyImage(GUI.image); shmctl(GUI.sm_info.shmid, IPC_RMID, 0); GUI.use_shared_memory = FALSE; } else { GUI.sm_info.readOnly = False; XSetErrorHandler(ErrorHandler); XShmAttach(GUI.display, &GUI.sm_info); XSync(GUI.display, False); // X Error handler might clear GUI.use_shared_memory if XShmAttach failed. if (!GUI.use_shared_memory) { XDestroyImage(GUI.image); shmdt(GUI.sm_info.shmaddr); shmctl(GUI.sm_info.shmid, IPC_RMID, 0); } } } } if (!GUI.use_shared_memory) { fprintf(stderr, "use_shared_memory failed, switching to XPutImage.\n"); #endif GUI.image = XCreateImage(GUI.display, GUI.visual, GUI.depth, ZPixmap, 0, NULL, SNES_WIDTH * 2, SNES_HEIGHT_EXTENDED * 2, BitmapUnit(GUI.display), 0); GUI.image->data = (char *) malloc(GUI.image->bytes_per_line * GUI.image->height); if (!GUI.image || !GUI.image->data) FatalError("XCreateImage failed."); #ifdef MITSHM } #endif #ifdef LSB_FIRST GUI.image->byte_order = LSBFirst; #else GUI.image->byte_order = MSBFirst; #endif GFX.Pitch = SNES_WIDTH * 2 * 2; GUI.snes_buffer = (uint8 *) calloc(GFX.Pitch * ((SNES_HEIGHT_EXTENDED + 4) * 2), 1); if (!GUI.snes_buffer) FatalError("Failed to allocate GUI.snes_buffer."); GFX.Screen = (uint16 *) (GUI.snes_buffer + (GFX.Pitch * 2 * 2)); GUI.filter_buffer = (uint8 *) calloc((SNES_WIDTH * 2) * 2 * (SNES_HEIGHT_EXTENDED * 2), 1); if (!GUI.filter_buffer) FatalError("Failed to allocate GUI.filter_buffer."); if (GUI.depth == 15 || GUI.depth == 16) { GUI.blit_screen_pitch = GUI.image->bytes_per_line; GUI.blit_screen = (uint8 *) GUI.image->data; GUI.need_convert = FALSE; } else { GUI.blit_screen_pitch = (SNES_WIDTH * 2) * 2; GUI.blit_screen = GUI.filter_buffer; GUI.need_convert = TRUE; } S9xGraphicsInit(); }
uint32_t *GetX11(uint16_t x, uint16_t y, uint16_t *w, uint16_t *h){ xGetImageReply rep; xGetImageReq *req; long nbytes; if(!image){ return 0; } XGetWindowAttributes(dpy, CaptureWin, &gwa); if(image->width != gwa.width || image->height != gwa.height){ printf("X11 Window: Changed W/H\n"); *w = gwa.width; *h = gwa.height; XFree(image); #ifdef X11_USE_XSHM_ if(use_shm) { int scr = XDefaultScreen(dpy); image = XShmCreateImage(dpy, DefaultVisual(dpy, scr), DefaultDepth(dpy, scr), ZPixmap, NULL, &shminfo, w, h); shminfo.shmid = shmget( IPC_PRIVATE, image->bytes_per_line * image->height, IPC_CREAT|0777); if(shminfo.shmid == -1){ printf("shminfo.shmid == -1\n"); return 0; } shminfo.shmaddr = image->data = (char*) shmat(shminfo.shmid, 0, 0); shminfo.readOnly = False; if(!XShmAttach(dpy, &shminfo)){ printf("!XShmAttach(dpy, &shminfo)\n"); return 0; } } else{ #endif /*X11_USE_XSHM_*/ image = XGetImage(dpy, CaptureWin, x,y, gwa.width,gwa.height, AllPlanes, ZPixmap); #ifdef X11_USE_XSHM_ } #endif /*X11_USE_XSHM_*/ } /* Here i should add a check to be sure that the window is still open */ LockDisplay(dpy); GetReq(GetImage, req); req->drawable = CaptureWin; req->x = x; req->y = y; req->width = gwa.width; req->height = gwa.height; req->planeMask = (unsigned int)AllPlanes; req->format = ZPixmap; if (!_XReply(dpy, (xReply *)&rep, 0, xFalse) || !rep.length) { UnlockDisplay(dpy); SyncHandle(); return 0; } nbytes = (long)rep.length << 2; _XReadPad(dpy, image->data, nbytes); UnlockDisplay(dpy); SyncHandle(); return (uint32_t*) image->data; }
void *vs_open (int v_width, int v_height) { Ctx *ctx = malloc(sizeof(Ctx)); ctx->v_width = v_width; ctx->v_height = v_height; // window ctx->display = XOpenDisplay(0); if (!ctx->display) { fprintf(stderr, "%s: XOpenDisplay err\n", __func__); exit(-1); } ctx->window = XCreateSimpleWindow(ctx->display, RootWindow(ctx->display, 0), 100, 100, v_width, v_height, 0, BlackPixel(ctx->display, 0), WhitePixel(ctx->display, 0)); ctx->screen = 0; ctx->gc = XCreateGC(ctx->display, ctx->window, 0, 0); XMapWindow(ctx->display, ctx->window); // current screen pix fmt Window root; unsigned int cx, cy, border, depth; int x, y; XGetGeometry(ctx->display, ctx->window, &root, &x, &y, &cx, &cy, &border, &depth); // visual info XMatchVisualInfo(ctx->display, ctx->screen, depth, DirectColor, &ctx->vinfo); // image ctx->image = XShmCreateImage(ctx->display, ctx->vinfo.visual, depth, ZPixmap, 0, &ctx->segment, cx, cy); if (!ctx->image) { fprintf(stderr, "%s: can't XShmCreateImage !\n", __func__); exit(-1); } ctx->segment.shmid = shmget(IPC_PRIVATE, ctx->image->bytes_per_line * ctx->image->height, IPC_CREAT | 0777); if (ctx->segment.shmid < 0) { fprintf(stderr, "%s: shmget err\n", __func__); exit(-1); } ctx->segment.shmaddr = (char*)shmat(ctx->segment.shmid, 0, 0); if (ctx->segment.shmaddr == (char*)-1) { fprintf(stderr, "%s: shmat err\n", __func__); exit(-1); } ctx->image->data = ctx->segment.shmaddr; ctx->segment.readOnly = 0; XShmAttach(ctx->display, &ctx->segment); PixelFormat target_pix_fmt = PIX_FMT_NONE; switch (ctx->image->bits_per_pixel) { case 32: target_pix_fmt = PIX_FMT_RGB32; break; case 24: target_pix_fmt = PIX_FMT_RGB24; break; default: break; } if (target_pix_fmt == PIX_FMT_NONE) { fprintf(stderr, "%s: screen depth format err\n", __func__); free(ctx); return 0; } // sws ctx->target_pixfmt = target_pix_fmt; ctx->curr_width = cx; ctx->curr_height = cy; ctx->sws = sws_getContext(v_width, v_height, PIX_FMT_YUV420P, cx, cy, target_pix_fmt, SWS_FAST_BILINEAR, 0, 0, 0); avpicture_alloc(&ctx->pic_target, target_pix_fmt, cx, cy); XFlush(ctx->display); return ctx; }
int image_create( IMAGE_CONTEXT *img_ctx, int width, int height ) { XGCValues gcValues; ulong gcValuesMask; XWindowAttributes windowAttributes; /*if ( img_ctx->xImage != NULL ) image_destroy( img_ctx );*/ g_width = width; g_height = height; gcValues.function = GXcopy; gcValuesMask = GCFunction; // Creating a graphics context img_ctx->gc = XCreateGC( img_ctx->display, img_ctx->window, gcValuesMask, &gcValues ); XGetWindowAttributes( img_ctx->display, img_ctx->window, &windowAttributes ); img_ctx->visual = windowAttributes.visual; img_ctx->depth = windowAttributes.depth; if( XShmQueryExtension( img_ctx->display ) ) img_ctx->isShared = 1; else { img_ctx->isShared = 0; printf("Error. isShared = FALSE\n"); } errno = 0; img_ctx->xImage = NULL; img_ctx->sharedPixmap = None; img_ctx->shmInfo.shmid = -1; img_ctx->shmInfo.shmaddr = NULL; if( ( img_ctx->xImage = XShmCreateImage( img_ctx->display, img_ctx->visual, img_ctx->depth, ZPixmap, NULL, &( img_ctx->shmInfo ), g_width, g_height ) ) == NULL ) { printf("Error. Failed to create image.\n"); return -1; } if( ( img_ctx->shmInfo.shmid = shmget( IPC_PRIVATE, img_ctx->xImage->bytes_per_line * img_ctx->xImage->height, IPC_CREAT | 0777 ) ) < 0 ) { printf("Error. Failed to create a segment.\n"); return -1; } if( ( img_ctx->shmInfo.shmaddr = (char *) shmat(img_ctx->shmInfo.shmid, 0, 0 ) ) < 0 ) { img_ctx->shmInfo.shmaddr = NULL; return -1; } img_ctx->xImage->data = img_ctx->shmInfo.shmaddr; img_ctx->shmInfo.readOnly = false; if ( !XShmAttach( img_ctx->display, &( img_ctx->shmInfo ) ) ) { printf("Error. Attach failed.\n"); return -1; } return 0; }
int fbx_init(fbx_struct *fb, fbx_wh wh, int width_, int height_, int useShm) { int width, height; int rmask, gmask, bmask, ps, i; #ifdef _WIN32 BMINFO bminfo; HBITMAP hmembmp=0; RECT rect; HDC hdc=NULL; #else XWindowAttributes xwa; int shmok=1, alphaFirst, pixmap=0; #endif if(!fb) _throw("Invalid argument"); #ifdef _WIN32 if(!wh) _throw("Invalid argument"); _w32(GetClientRect(wh, &rect)); if(width_>0) width=width_; else { width=rect.right-rect.left; if(width<=0) width=MINWIDTH; } if(height_>0) height=height_; else { height=rect.bottom-rect.top; if(height<=0) height=MINHEIGHT; } if(fb->wh==wh) { if(width==fb->width && height==fb->height && fb->hmdc && fb->hdib && fb->bits) return 0; else if(fbx_term(fb)==-1) return -1; } memset(fb, 0, sizeof(fbx_struct)); fb->wh=wh; _w32(hdc=GetDC(fb->wh)); _w32(fb->hmdc=CreateCompatibleDC(hdc)); _w32(hmembmp=CreateCompatibleBitmap(hdc, width, height)); _w32(GetDeviceCaps(hdc, RASTERCAPS)&RC_BITBLT); _w32(GetDeviceCaps(fb->hmdc, RASTERCAPS)&RC_DI_BITMAP); bminfo.bmi.bmiHeader.biSize=sizeof(BITMAPINFOHEADER); bminfo.bmi.bmiHeader.biBitCount=0; _w32(GetDIBits(fb->hmdc, hmembmp, 0, 1, NULL, &bminfo.bmi, DIB_RGB_COLORS)); _w32(GetDIBits(fb->hmdc, hmembmp, 0, 1, NULL, &bminfo.bmi, DIB_RGB_COLORS)); _w32(DeleteObject(hmembmp)); hmembmp=0; /* (we only needed it to get the screen properties) */ ps=bminfo.bmi.bmiHeader.biBitCount/8; if(width>0) bminfo.bmi.bmiHeader.biWidth=width; if(height>0) bminfo.bmi.bmiHeader.biHeight=height; fb->width=bminfo.bmi.bmiHeader.biWidth; fb->height=bminfo.bmi.bmiHeader.biHeight; if(ps<3) { /* Make the buffer BGRA */ bminfo.bmi.bmiHeader.biCompression=BI_BITFIELDS; bminfo.bmi.bmiHeader.biBitCount=32; ps=4; (*(DWORD *)&bminfo.bmi.bmiColors[0])=0xFF0000; (*(DWORD *)&bminfo.bmi.bmiColors[1])=0xFF00; (*(DWORD *)&bminfo.bmi.bmiColors[2])=0xFF; } fb->pitch=BMPPAD(fb->width*ps); /* Windoze bitmaps are always padded */ if(bminfo.bmi.bmiHeader.biCompression==BI_BITFIELDS) { rmask=(*(DWORD *)&bminfo.bmi.bmiColors[0]); gmask=(*(DWORD *)&bminfo.bmi.bmiColors[1]); bmask=(*(DWORD *)&bminfo.bmi.bmiColors[2]); } else { rmask=0xFF0000; gmask=0xFF00; bmask=0xFF; } fb->format=-1; for(i=0; i<FBX_FORMATS; i++) if(rmask==fbx_rmask[i] && gmask==fbx_gmask[i] && bmask==fbx_bmask[i] && ps==fbx_ps[i] && fbx_alphafirst[i]==0) fb->format=i; if(fb->format==-1) _throw("Display has unsupported pixel format"); bminfo.bmi.bmiHeader.biHeight=-bminfo.bmi.bmiHeader.biHeight; /* (our convention is top-down) */ _w32(fb->hdib=CreateDIBSection(hdc, &bminfo.bmi, DIB_RGB_COLORS, (void **)&fb->bits, NULL, 0)); _w32(SelectObject(fb->hmdc, fb->hdib)); ReleaseDC(fb->wh, hdc); return 0; finally: if(hmembmp) DeleteObject(hmembmp); if(hdc) ReleaseDC(fb->wh, hdc); #else if(!wh.dpy || !wh.d) _throw("Invalid argument"); if(wh.v) { _x11(XGetGeometry(wh.dpy, wh.d, &xwa.root, &xwa.x, &xwa.y, (unsigned int *)&xwa.width, (unsigned int *)&xwa.height, (unsigned int *)&xwa.border_width, (unsigned int *)&xwa.depth)); xwa.visual=wh.v; useShm=0; pixmap=1; } else { _x11(XGetWindowAttributes(wh.dpy, wh.d, &xwa)); } if(width_>0) width=width_; else width=xwa.width; if(height_>0) height=height_; else height=xwa.height; if(fb->wh.dpy==wh.dpy && fb->wh.d==wh.d) { if(width==fb->width && height==fb->height && fb->xi && fb->xgc && fb->bits) return 0; else if(fbx_term(fb)==-1) return -1; } memset(fb, 0, sizeof(fbx_struct)); fb->wh.dpy=wh.dpy; fb->wh.d=wh.d; #ifdef USESHM if(!useShm) { static int alreadyWarned=0; if(!alreadyWarned && warningFile) { fprintf(warningFile, "[FBX] Disabling shared memory blitting\n"); alreadyWarned=1; } } if(useShm && XShmQueryExtension(fb->wh.dpy)) { static int alreadyWarned=0; fb->shminfo.shmid=-1; if(!(fb->xi=XShmCreateImage(fb->wh.dpy, xwa.visual, xwa.depth, ZPixmap, NULL, &fb->shminfo, width, height))) { useShm=0; goto noshm; } if((fb->shminfo.shmid=shmget(IPC_PRIVATE, fb->xi->bytes_per_line*fb->xi->height+1, IPC_CREAT|0777))==-1) { useShm=0; XDestroyImage(fb->xi); goto noshm; } if((fb->shminfo.shmaddr=fb->xi->data =(char *)shmat(fb->shminfo.shmid, 0, 0))==(char *)-1) { useShm=0; XDestroyImage(fb->xi); shmctl(fb->shminfo.shmid, IPC_RMID, 0); goto noshm; } fb->shminfo.readOnly=False; XLockDisplay(fb->wh.dpy); XSync(fb->wh.dpy, False); prevHandler=XSetErrorHandler(xhandler); extok=1; serial=NextRequest(fb->wh.dpy); XShmAttach(fb->wh.dpy, &fb->shminfo); XSync(fb->wh.dpy, False); XSetErrorHandler(prevHandler); shmok=extok; if(!alreadyWarned && !shmok && warningFile) { fprintf(warningFile, "[FBX] WARNING: MIT-SHM extension failed to initialize (this is normal on a\n"); fprintf(warningFile, "[FBX] remote connection.) Will use X Pixmap drawing instead.\n"); alreadyWarned=1; } XUnlockDisplay(fb->wh.dpy); if(shmok) { char *env=getenv("FBX_USESHMPIXMAPS"); if(env && !strcmp(env, "1")) { static int alreadyWarned=0; if(!alreadyWarned && warningFile) { fprintf(warningFile, "[FBX] Using MIT-SHM pixmaps\n"); alreadyWarned=1; } fb->pm=XShmCreatePixmap(fb->wh.dpy, fb->wh.d, fb->shminfo.shmaddr, &fb->shminfo, width, height, xwa.depth); if(!fb->pm) shmok=0; } } shmctl(fb->shminfo.shmid, IPC_RMID, 0); if(!shmok) { useShm=0; XDestroyImage(fb->xi); shmdt(fb->shminfo.shmaddr); shmctl(fb->shminfo.shmid, IPC_RMID, 0); goto noshm; } fb->xattach=1; fb->shm=1; } else if(useShm) { static int alreadyWarned=0; if(!alreadyWarned && warningFile) { fprintf(warningFile, "[FBX] WARNING: MIT-SHM extension not available. Will use X pixmap\n"); fprintf(warningFile, "[FBX] drawing instead.\n"); alreadyWarned=1; } useShm=0; } noshm: if(!useShm) #endif { if(!pixmap) _x11(fb->pm=XCreatePixmap(fb->wh.dpy, fb->wh.d, width, height, xwa.depth)); _x11(fb->xi=XCreateImage(fb->wh.dpy, xwa.visual, xwa.depth, ZPixmap, 0, NULL, width, height, 8, 0)); if((fb->xi->data=(char *)malloc(fb->xi->bytes_per_line*fb->xi->height+1)) ==NULL) _throw("Memory allocation error"); } ps=fb->xi->bits_per_pixel/8; fb->width=fb->xi->width; fb->height=fb->xi->height; fb->pitch=fb->xi->bytes_per_line; if(fb->width!=width || fb->height!=height) _throw("Bitmap returned does not match requested size"); rmask=fb->xi->red_mask; gmask=fb->xi->green_mask; bmask=fb->xi->blue_mask; alphaFirst=0; if(fb->xi->byte_order==MSBFirst) { if(ps<4) { rmask=fb->xi->blue_mask; gmask=fb->xi->green_mask; bmask=fb->xi->red_mask; } else alphaFirst=1; } fb->format=-1; for(i=0; i<FBX_FORMATS; i++) if(rmask==fbx_rmask[i] && gmask==fbx_gmask[i] && bmask==fbx_bmask[i] && ps==fbx_ps[i] && fbx_alphafirst[i]==alphaFirst) fb->format=i; if(fb->format==-1) _throw("Display has unsupported pixel format"); fb->bits=fb->xi->data; fb->pixmap=pixmap; _x11(fb->xgc=XCreateGC(fb->wh.dpy, fb->pm? fb->pm:fb->wh.d, 0, NULL)); return 0; finally: #endif fbx_term(fb); return -1; }
int xf_xshm_init(xfInfo* xfi) { Bool pixmaps; int major, minor; if (XShmQueryExtension(xfi->display) != False) { XShmQueryVersion(xfi->display, &major, &minor, &pixmaps); if (pixmaps != True) { fprintf(stderr, "XShmQueryVersion failed\n"); return -1; } } else { fprintf(stderr, "XShmQueryExtension failed\n"); return -1; } xfi->fb_shm_info.shmid = -1; xfi->fb_shm_info.shmaddr = (char*) -1; xfi->fb_image = XShmCreateImage(xfi->display, xfi->visual, xfi->depth, ZPixmap, NULL, &(xfi->fb_shm_info), xfi->width, xfi->height); if (!xfi->fb_image) { fprintf(stderr, "XShmCreateImage failed\n"); return -1; } xfi->fb_shm_info.shmid = shmget(IPC_PRIVATE, xfi->fb_image->bytes_per_line * xfi->fb_image->height, IPC_CREAT | 0600); if (xfi->fb_shm_info.shmid == -1) { fprintf(stderr, "shmget failed\n"); return -1; } xfi->fb_shm_info.readOnly = False; xfi->fb_shm_info.shmaddr = shmat(xfi->fb_shm_info.shmid, 0, 0); xfi->fb_image->data = xfi->fb_shm_info.shmaddr; if (xfi->fb_shm_info.shmaddr == ((char*) -1)) { fprintf(stderr, "shmat failed\n"); return -1; } XShmAttach(xfi->display, &(xfi->fb_shm_info)); XSync(xfi->display, False); shmctl(xfi->fb_shm_info.shmid, IPC_RMID, 0); fprintf(stderr, "display: %p root_window: %p width: %d height: %d depth: %d\n", xfi->display, (void*) xfi->root_window, xfi->fb_image->width, xfi->fb_image->height, xfi->fb_image->depth); xfi->fb_pixmap = XShmCreatePixmap(xfi->display, xfi->root_window, xfi->fb_image->data, &(xfi->fb_shm_info), xfi->fb_image->width, xfi->fb_image->height, xfi->fb_image->depth); return 0; }