int video_init(void) { XGCValues gc_values; Display *display; _video_gc = video_get_gc(&gc_values); display = x11ui_get_display_ptr(); x11video_log = log_open("X11Video"); color_init(); #ifdef USE_MITSHM if (!try_mitshm) { use_mitshm = 0; } else { /* This checks if the server has MITSHM extensions available If try_mitshm is true and we are on a different machine, frame_buffer_alloc will fall back to non shared memory calls. */ int major_version, minor_version, pixmap_flag; /* Check whether the server supports the Shared Memory Extension. */ if (!XShmQueryVersion(display, &major_version, &minor_version, &pixmap_flag)) { log_warning(x11video_log, "The MITSHM extension is not supported on this display."); use_mitshm = 0; } else { DEBUG_MITSHM((_("MITSHM extensions version %d.%d detected."), major_version, minor_version)); if (!pixmap_flag) { DEBUG_MITSHM(("The MITSHM extension is supported on this display, but shared pixmaps are not available.")); } use_mitshm = 1; } } #else use_mitshm = 0; #endif return 0; }
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; }