diff options
Diffstat (limited to 'src/video_out/video_out_xshm.c')
-rw-r--r-- | src/video_out/video_out_xshm.c | 968 |
1 files changed, 968 insertions, 0 deletions
diff --git a/src/video_out/video_out_xshm.c b/src/video_out/video_out_xshm.c new file mode 100644 index 000000000..61531225f --- /dev/null +++ b/src/video_out/video_out_xshm.c @@ -0,0 +1,968 @@ +/* + * Copyright (C) 2000 the xine project + * + * This file is part of xine, a unix video player. + * + * xine is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * xine is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + * + * $Id: video_out_xshm.c,v 1.1 2001/04/24 20:53:00 f1rmb Exp $ + * + * video_out_xshm.c, X11 shared memory extension interface for xine + * + * based on mpeg2dec code from + * Aaron Holtzman <aholtzma@ess.engr.uvic.ca> + * + * xine-specific code by Guenter Bartsch <bartscgr@studbox.uni-stuttgart.de> + * + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include <stdio.h> +#include <stdlib.h> +#include <string.h> + +#include "video_out.h" + +#include <X11/Xlib.h> +#include <X11/Xutil.h> +#include <X11/cursorfont.h> +#include <errno.h> + +#include <X11/extensions/XShm.h> +#include <sys/ipc.h> +#include <sys/shm.h> +#include <sys/time.h> + +#include <Imlib.h> +#include <pthread.h> + +#include "xine_internal.h" +#include "monitor.h" +#include "libmpeg2/mpeg2.h" +#include "yuv2rgb.h" +#warning "FIXME" +#include "../gui/gui_dnd.h" +#include "../gui/gui_main.h" + +extern uint32_t xine_debug; + +extern int XShmGetEventBase(Display *); + +extern Display *gDisplay; +extern pthread_mutex_t gXLock; +extern Window gVideoWin; +extern ImlibImage *gXineLogoImg; +extern ImlibData *gImlib_data; +extern Pixmap gXineLogo; +extern int gXineLogoWidth, gXineLogoHeight; + +typedef struct xshm_image_info_s { + vo_image_buffer_t mImageBuffer; + XImage *mImage; + XShmSegmentInfo mShminfo; +} xshm_image_buffer_t; + +typedef struct _xshm_globals { + int screen; + Window window; + XVisualInfo vinfo; + int depth,bpp; + int bFullscreen; + int bIsFullscreen; + GC gc; + uint32_t image_width; + uint32_t image_height; + uint32_t image_xoff; + uint32_t image_yoff; + uint32_t dest_width; + uint32_t dest_height; + uint32_t ratio; + int user_ratio, user_ratio_changed; + int bYuvInitialized; + int bytes_per_pixel; + int hstride_rgb, hstride_y, hstride_uv; + int anamorphic; + + + xshm_image_buffer_t *cur_image; + + /* + * misc (read: fun ;)) + */ + int bLogoMode; + +#define HIDE_CURSOR 0 +#define SHOW_CURSOR 1 + Cursor mcursor[2]; + int current_cursor; + + int bFail; + int bUseShm; + DND_struct_t *xdnd; +} xshm_globals; + + +xshm_globals gXshm ; + +int HandleXError (Display *gDisplay, XErrorEvent *xevent) { + + xprintf (VERBOSE|VIDEO, "\n\n*** X ERROR *** \n\n\n"); + + gXshm.bFail = 1; + return 0; + +} + +static void x11_InstallXErrorHandler () +{ + XSetErrorHandler (HandleXError); + XFlush (gDisplay); +} + +static void x11_DeInstallXErrorHandler () +{ + XSetErrorHandler (NULL); + XFlush (gDisplay); +} + +static int get_capabilities_xshm () { + return VO_CAP_COPIES_IMAGE | VO_CAP_YV12; +} + +static unsigned char bm_no_data[] = { 0,0,0,0, 0,0,0,0 }; + +static void create_cursor_xshm (Colormap colormap) { + Pixmap bm_no; + XColor black, dummy; + + /* + * create empty cursor + */ + + bm_no = XCreateBitmapFromData(gDisplay, gXshm.window, + bm_no_data, 8, 8); + + XAllocNamedColor(gDisplay,colormap,"black",&black,&dummy); + gXshm.mcursor[0] = XCreatePixmapCursor(gDisplay, bm_no, bm_no, + &black, &black, + 0, 0); + gXshm.mcursor[1]= XCreateFontCursor(gDisplay, XC_left_ptr); + +} + +static void display_cursor_xshm(int state) { + + XDefineCursor(gDisplay, gXshm.window, gXshm.mcursor[state]); + gXshm.current_cursor = state; +} + +static void setup_window_xshm () { + char *hello = "xine video output"; + Colormap theCmap = 0; + XSizeHints hint; + XWMHints *wm_hint; + XEvent xev; + XGCValues xgcv; + XColor background, ignored; + XSetWindowAttributes attr; + int ww, wh; + float aspect; + Atom WM_DELETE_WINDOW; + XClassHint *xshm_xclasshint; + + XLOCK (); + + + if((xshm_xclasshint = XAllocClassHint()) != NULL) { + xshm_xclasshint->res_name = "Xine Xshm Video"; + xshm_xclasshint->res_class = "Xine"; + } + + if (gXshm.bFullscreen) { + + ww = DisplayWidth (gDisplay, gXshm.screen); + wh = DisplayHeight (gDisplay, gXshm.screen); + + /* + * zoom to fullscreen + */ + + if (gXshm.dest_width < ww) { + aspect = (float) gXshm.dest_width / (float) gXshm.dest_height ; + + gXshm.dest_width = ww; + gXshm.dest_height = ww / aspect; + } + + gXshm.image_xoff = ( ww - gXshm.dest_width) / 2; + gXshm.image_yoff = ( wh - gXshm.dest_height) / 2; + + + if (gXshm.window) { + + if (gXshm.bIsFullscreen) { + XUNLOCK (); + return; + } + + XDestroyWindow(gDisplay, gXshm.window); + gXshm.window = 0; + + } + + gXshm.bIsFullscreen = 1; + + /* + * open fullscreen window + */ + + if (XAllocNamedColor (gDisplay, DefaultColormap (gDisplay, gXshm.screen), + "black", + &background, &ignored) == 0) { + fprintf (stderr, "Cannot allocate color black\n"); + exit(1); + } + + attr.background_pixel = background.pixel; + attr.override_redirect = True; + + gXshm.window = + XCreateWindow (gDisplay, RootWindow (gDisplay, gXshm.screen), 0, 0, + ww, wh, 0, gXshm.depth, + CopyFromParent, DefaultVisual (gDisplay, gXshm.screen), + CWBackPixel|CWOverrideRedirect, &attr); + + if(xshm_xclasshint != NULL) + XSetClassHint(gDisplay, gXshm.window, xshm_xclasshint); + + gVideoWin = gXshm.window; + + } else { + + if (gXshm.window) { + + if (gXshm.bIsFullscreen) { + XDestroyWindow(gDisplay, gXshm.window); + gXshm.window = 0; + } else { + + XResizeWindow (gDisplay, gXshm.window, gXshm.dest_width, + gXshm.dest_height); + + XFlush(gDisplay); + XSync(gDisplay, False); + XUNLOCK (); + return; + + } + } + + gXshm.bIsFullscreen = 0; + + + hint.x = 0; + hint.y = 0; + hint.width = gXshm.dest_width; + hint.height = gXshm.dest_height; + hint.flags = PPosition | PSize; + + theCmap = XCreateColormap(gDisplay, RootWindow(gDisplay,gXshm.screen), + gXshm.vinfo.visual, AllocNone); + + attr.background_pixel = 0; + attr.border_pixel = 1; + attr.colormap = theCmap; + + gXshm.window = XCreateWindow(gDisplay, RootWindow(gDisplay, gXshm.screen), + hint.x, hint.y, hint.width, hint.height, 4, + gXshm.depth,CopyFromParent,gXshm.vinfo.visual, + CWBackPixel | CWBorderPixel |CWColormap,&attr); + + if(xshm_xclasshint != NULL) + XSetClassHint(gDisplay, gXshm.window, xshm_xclasshint); + + gVideoWin = gXshm.window; + + /* Tell other applications about this window */ + + XSetStandardProperties(gDisplay, gXshm.window, hello, hello, + None, NULL, 0, &hint); + + gXshm.image_xoff = 0; + gXshm.image_yoff = 0; + } + + XSelectInput(gDisplay, gXshm.window, StructureNotifyMask | ExposureMask | KeyPressMask | ButtonPressMask | StructureNotifyMask); + + wm_hint = XAllocWMHints(); + if (wm_hint != NULL) { + wm_hint->input = True; + wm_hint->initial_state = NormalState; + wm_hint->flags = InputHint | StateHint; + XSetWMHints(gDisplay, gXshm.window, wm_hint); + XFree(wm_hint); + } + + WM_DELETE_WINDOW = XInternAtom(gDisplay, "WM_DELETE_WINDOW", False); + XSetWMProtocols(gDisplay, gXshm.window, &WM_DELETE_WINDOW, 1); + + /* Map window. */ + + XMapWindow(gDisplay, gXshm.window); + + /* Wait for map. */ + do { + XMaskEvent(gDisplay, + StructureNotifyMask, + &xev) ; + } while (xev.type != MapNotify || xev.xmap.event != gXshm.window); + + XFlush(gDisplay); + XSync(gDisplay, False); + + gXshm.gc = XCreateGC(gDisplay, gXshm.window, 0L, &xgcv); + + if (gXshm.bFullscreen) + XSetInputFocus (gDisplay, gXshm.window, RevertToNone, CurrentTime); + + if (gXshm.bFullscreen) { + if (!gXshm.mcursor[0]) { + create_cursor_xshm (theCmap); + } + + //display_cursor_xshm(HIDE_CURSOR); + } + /* drag and drop */ + + XUNLOCK (); + + if(!gXshm.xdnd) + gXshm.xdnd = (DND_struct_t *) malloc(sizeof(DND_struct_t)); + + gui_init_dnd(gXshm.xdnd); + gui_dnd_set_callback (gXshm.xdnd, gui_dndcallback); + gui_make_window_dnd_aware (gXshm.xdnd, gXshm.window); + +} + +/* allocates ximages if necessary */ +static int set_image_format_xshm (uint32_t width, uint32_t height, uint32_t ratio, int format) { + + /* FIXME: handle format argument */ + + if ( (gXshm.image_width == width) + && (gXshm.image_height == height) + && (gXshm.ratio == ratio) + && (gXshm.bFullscreen == gXshm.bIsFullscreen) + && !gXshm.user_ratio_changed ) + return 0; + + gXshm.image_width = width; + gXshm.image_height = height; + gXshm.hstride_rgb = gXshm.dest_width * gXshm.bytes_per_pixel; + gXshm.hstride_y = gXshm.image_width; + gXshm.hstride_uv = gXshm.image_width / 2; + gXshm.ratio = ratio; + gXshm.user_ratio_changed = 0; + + /* + * calculate dest size from ratio + */ + + /* + * Mpeg-2: + */ + + if (gXshm.user_ratio == ASPECT_AUTO) { + switch (gXshm.ratio) { + case 0: /* forbidden */ + fprintf (stderr, "invalid ratio\n"); + exit (1); + break; + case 1: /* square */ + gXshm.dest_width = width; + gXshm.dest_height = height; + gXshm.anamorphic = 0; + break; + case 2: /* 4:3 */ + gXshm.dest_width = width ; + gXshm.dest_height = height; + gXshm.anamorphic = 0; + break; + case 3: /* 16:9 */ + gXshm.dest_width = width * 5/4; + gXshm.dest_height = height; + gXshm.anamorphic = 1; + break; + default: + gXshm.dest_width = width; + gXshm.dest_height = height; + xprintf (VERBOSE|VIDEO, "invalid ratio\n"); + /*exit (1); */ + break; + } + } else if (gXshm.user_ratio == ASPECT_ANAMORPHIC) { + gXshm.dest_width = width *5/4 ; + gXshm.dest_height = height; + gXshm.anamorphic = 1; + } else { + gXshm.dest_width = width; + gXshm.dest_height = height; + gXshm.anamorphic = 0; + } + + + xprintf (VERBOSE|VIDEO, "picture size : %d x %d (Ratio: %d)\n", + width, height, ratio); + + setup_window_xshm () ; + + return 1; +} + +static void dispose_image_buffer_xshm (vo_image_buffer_t *vo_img) { + + xshm_image_buffer_t *img = (xshm_image_buffer_t *) vo_img; + + XLOCK (); + + if (gXshm.bUseShm) { + + XShmDetach(gDisplay, &img->mShminfo); + XDestroyImage(img->mImage); + shmdt(img->mShminfo.shmaddr); + shmctl (img->mShminfo.shmid, IPC_RMID,NULL); + + } else { + + XDestroyImage(img->mImage); + + } + + free (img); + + XUNLOCK (); +} + + +static vo_image_buffer_t *alloc_image_buffer_xshm () { + + uint32_t image_size; + xshm_image_buffer_t *img ; + + XLOCK (); + + img = (xshm_image_buffer_t *) malloc (sizeof (xshm_image_buffer_t)); + + if (img==NULL) { + printf ("out of memory while allocating image buffer\n"); + exit (1); + } + + if (gXshm.bUseShm) { + img->mImage = XShmCreateImage(gDisplay, + gXshm.vinfo.visual, + gXshm.vinfo.depth, + ZPixmap, NULL, + &img->mShminfo, + gXshm.dest_width, + gXshm.dest_height); + + if (img->mImage == NULL ) { + fprintf(stderr, "Shared memory error when allocating image => exit (Ximage error)\n"); + exit (1); + } + + gXshm.bpp = img->mImage->bits_per_pixel; + gXshm.bytes_per_pixel = gXshm.bpp / 8; + gXshm.hstride_rgb = gXshm.dest_width * gXshm.bytes_per_pixel; + img->mShminfo.shmid=shmget(IPC_PRIVATE, + img->mImage->bytes_per_line * img->mImage->height, + IPC_CREAT | 0777); + + if (img->mShminfo.shmid < 0 ) { + printf("%s: allocating image \n",strerror(errno)); + exit (1); + } + + img->mShminfo.shmaddr = (char *) shmat(img->mShminfo.shmid, 0, 0); + + if (img->mShminfo.shmaddr == ((char *) -1)) { + fprintf(stderr, "Shared memory error (address error) when allocating image \n"); + exit (1); + } + + img->mShminfo.readOnly = False; + img->mImage->data = img->mShminfo.shmaddr; + + XShmAttach(gDisplay, &img->mShminfo); + + XSync(gDisplay, False); + /* shmctl(img->mShminfo.shmid, IPC_RMID, 0);*/ + } else { /* no shm */ + + /* + XResizeWindow (gDisplay, gXshm.window, gXshm.dest_width, + gXshm.dest_height); + + XSync(gDisplay, False); + */ + img->mImage = XGetImage (gDisplay, gXshm.window, 0, 0, + gXshm.dest_width, gXshm.dest_height, + AllPlanes, ZPixmap); + XSync(gDisplay, False); + } + + + image_size = gXshm.image_width * gXshm.image_height; + img->mImageBuffer.mem[0] = malloc(image_size); + img->mImageBuffer.mem[1] = malloc(image_size/4); + img->mImageBuffer.mem[2] = malloc(image_size/4); + + if (!gXshm.bYuvInitialized) { + int mode = ((img->mImage->blue_mask & 0x01)) ? MODE_RGB : MODE_BGR; + yuv2rgb_init((gXshm.depth == 24) ? gXshm.bpp : gXshm.depth, mode); + gXshm.bYuvInitialized = 1; + } + + XUNLOCK (); + + pthread_mutex_init (&img->mImageBuffer.mutex, NULL); + + return (vo_image_buffer_t *) img; +} + +static void process_macroblock_xshm (vo_image_buffer_t *img, + uint8_t *py, uint8_t *pu, uint8_t *pv, + int slice_num, + int subslice_num) { + + uint8_t *dst; + int subslice_offset; + xshm_image_buffer_t *xshm_img = (xshm_image_buffer_t *) img; + int slice_offset; + + slice_offset = slice_num * 16 * gXshm.dest_width ; + if (gXshm.anamorphic) + subslice_offset = subslice_num *20 ; + else + subslice_offset = subslice_num *16 ; + + dst = xshm_img->mImage->data + (slice_offset + subslice_offset) * gXshm.bytes_per_pixel ; + + if (gXshm.anamorphic) + yuv2rgb_anamorphic(dst, + py, pu, pv, + gXshm.hstride_rgb, + gXshm.hstride_y, + gXshm.hstride_uv); + else + yuv2rgb(dst, + py, pu, pv, + gXshm.hstride_rgb, + gXshm.hstride_y, + gXshm.hstride_uv); +} + +static int is_fullscreen_xshm () { + return gXshm.bFullscreen; +} + +static void set_fullscreen_xshm (int bFullscreen) { + + xprintf(VERBOSE|VIDEO, "(!)Fullscreen not implemented for xshm.\n"); + + return ; /* FIXME - not implemented for xshm */ + + gXshm.bFullscreen = bFullscreen; + + set_image_format_xshm (gXshm.image_width, gXshm.image_height, gXshm.ratio, IMGFMT_YV12); +} + +static void display_frame_xshm (vo_image_buffer_t *vo_img) { + + xshm_image_buffer_t *img = (xshm_image_buffer_t *) vo_img; + + XLOCK (); + + if (gXshm.bUseShm) { + + XShmPutImage(gDisplay, gXshm.window, gXshm.gc, img->mImage, + 0, 0, 0, 0, + img->mImage->width, img->mImage->height, True); + } else { + + xprintf (VERBOSE|VIDEO, "display frame\n"); + + XPutImage(gDisplay, gXshm.window, gXshm.gc, img->mImage, + 0, 0, 0, 0, + img->mImage->width, img->mImage->height); + } + + XFlush(gDisplay); + + if (gXshm.cur_image) { + vo_image_drawn ( (vo_image_buffer_t *) gXshm.cur_image); + } + + gXshm.cur_image = img; + + XUNLOCK (); +} + +static void draw_logo_xshm () { + ImlibImage *resized_image; + int xwin, ywin, tmp; + unsigned int wwin, hwin, bwin, dwin; + double ratio = 1; + Window rootwin; + + XLOCK ();; + + XClearWindow (gDisplay, gXshm.window); + + if(XGetGeometry(gDisplay, gXshm.window, &rootwin, + &xwin, &ywin, &wwin, &hwin, &bwin, &dwin) != BadDrawable) { + + tmp = (wwin / 100) * 86; + ratio = (tmp < gXineLogoWidth && tmp >= 1) ? + (ratio = (double)tmp / (double)gXineLogoWidth) : 1; + } + + resized_image = Imlib_clone_image(gImlib_data, gXineLogoImg); + Imlib_render (gImlib_data, resized_image, + (int)gXineLogoWidth * ratio, + (int)gXineLogoHeight * ratio); + + XCopyArea (gDisplay, resized_image->pixmap, gXshm.window, gXshm.gc, 0, 0, + resized_image->width, resized_image->height, + (wwin - resized_image->width) / 2, + (hwin - resized_image->height) / 2); + + XFlush(gDisplay); + + Imlib_destroy_image(gImlib_data, resized_image); + + XUNLOCK ();; +} + +static void handle_event_xshm (XEvent *event) { + + switch (event->type) { + case Expose: + if (event->xexpose.window == gXshm.window) { + if (gXshm.bLogoMode) { + draw_logo_xshm (); + } else { + XLOCK (); + XClearWindow (gDisplay, gXshm.window); + if (gXshm.cur_image) + XShmPutImage(gDisplay, gXshm.window, gXshm.gc, + gXshm.cur_image->mImage, + 0, 0, 0, 0, + gXshm.cur_image->mImage->width, + gXshm.cur_image->mImage->height, True); + XUNLOCK (); + } + } + break; + + case ClientMessage: + if(event->xany.window == gXshm.window) + gui_dnd_process_client_message (gXshm.xdnd, event); + break; + } +} + +static void set_logo_mode_xshm (int bLogoMode) { + gXshm.bLogoMode = bLogoMode; + + if (bLogoMode) + draw_logo_xshm (); +} + +static void reset_xshm () { + + if (gXshm.cur_image) { + vo_image_drawn ( (vo_image_buffer_t *) gXshm.cur_image); + gXshm.cur_image = NULL; + } + +} + +void set_aspect_xshm (int ratio) { + + ratio %= 3; /* DVB unsupported */ + + if (ratio != gXshm.user_ratio) { + gXshm.user_ratio = ratio; + gXshm.user_ratio_changed = 1; + + set_image_format_xshm (gXshm.image_width, gXshm.image_height, gXshm.ratio, IMGFMT_YV12); + } + + printf ("set_aspect done\n"); +} + +int get_aspect_xshm () { + return gXshm.user_ratio; +} + +void exit_xshm () { +} + +static int get_noop(void) { + return 0; +} + +static int set_noop(int v) { + return v; +} + +static vo_driver_t vo_xshm = { + get_capabilities_xshm, + set_image_format_xshm, + alloc_image_buffer_xshm, + dispose_image_buffer_xshm, + process_macroblock_xshm, + display_frame_xshm, + set_fullscreen_xshm, + is_fullscreen_xshm, + handle_event_xshm, + set_logo_mode_xshm, + reset_xshm, + display_cursor_xshm, + set_aspect_xshm, + get_aspect_xshm, + exit_xshm, + + get_noop, + get_noop, + set_noop, + get_noop, + + get_noop, + get_noop, + set_noop, + get_noop, + + get_noop, + get_noop, + set_noop, + get_noop, + + get_noop, + get_noop, + set_noop, + get_noop, + + get_noop, + get_noop, + set_noop, + + NULL, + NULL +}; + +/* + * connect to server, create and map window, + * allocate colors and (shared) memory + */ + +vo_driver_t *init_video_out_xshm () { + + int completionType = -1; + XWindowAttributes attribs; + int minor, major; + Bool bPixmaps; + XImage *myimage; + XShmSegmentInfo myshminfo; + + /* XLOCK (); */ + + gXshm.image_width=720; + gXshm.image_height=576; + + /* + * ok, X11, prepare for some video! + */ + + gXshm.screen = DefaultScreen(gDisplay); + + XGetWindowAttributes(gDisplay, DefaultRootWindow(gDisplay), &attribs); + + /* + * + * depth in X11 terminology land is the number of bits used to + * actually represent the colour. + * + * bpp in X11 land means how many bits in the frame buffer per + * pixel. + * + * ex. 15 bit color is 15 bit depth and 16 bpp. Also 24 bit + * color is 24 bit depth, but can be 24 bpp or 32 bpp. + */ + + gXshm.depth = attribs.depth; + + if (gXshm.depth != 15 && gXshm.depth != 16 && gXshm.depth != 24 && gXshm.depth != 32) { + /* The root window may be 8bit but there might still be + * visuals with other bit depths. For example this is the + * case on Sun/Solaris machines. + */ + gXshm.depth = 24; + } + + XMatchVisualInfo(gDisplay, gXshm.screen, gXshm.depth, TrueColor, &gXshm.vinfo); + + gXshm.bUseShm = 1; + + /* + * check for X shared memory support + */ + + if (!XShmQueryExtension(gDisplay)) { + xprintf(VERBOSE|VIDEO, "Shared memory not supported\n\n"); + gXshm.bUseShm = 0; + goto finishShmTesting; + } + + if (!XShmQueryVersion (gDisplay, &major, &minor, &bPixmaps)){ + xprintf(VERBOSE|VIDEO, "Shared memory not supported\n\n"); + gXshm.bUseShm = 0; + goto finishShmTesting; + } + + xprintf (VERBOSE|VIDEO, "pixmaps : %d ?= %d\n", bPixmaps, True); + + if (!bPixmaps) { + xprintf(VERBOSE|VIDEO, "creation of shared pixmaps not possible\n\n"); + gXshm.bUseShm = 0; + goto finishShmTesting; + } + + + completionType = XShmGetEventBase(gDisplay) + ShmCompletion; + + /* try to create shared image */ + gXshm.bFail = 0; + x11_InstallXErrorHandler (); + + myimage = XShmCreateImage(gDisplay, + gXshm.vinfo.visual, + gXshm.vinfo.depth, + ZPixmap, NULL, + &myshminfo, + 100, + 100); + + if (myimage == NULL ) { + xprintf(VERBOSE|VIDEO, "Shared memory error when allocating image => exit (Ximage error)\n"); + gXshm.bUseShm = 0; + x11_DeInstallXErrorHandler(); + goto finishShmTesting; + } + + gXshm.bpp = myimage->bits_per_pixel; + gXshm.bytes_per_pixel = gXshm.bpp / 8; + + myshminfo.shmid=shmget(IPC_PRIVATE, + myimage->bytes_per_line * myimage->height, + IPC_CREAT | 0777); + + if (myshminfo.shmid < 0 ) { + xprintf(VERBOSE|VIDEO, "%s: allocating image \n",strerror(errno)); + gXshm.bUseShm = 0; + x11_DeInstallXErrorHandler(); + goto finishShmTesting; + } + + myshminfo.shmaddr = (char *) shmat(myshminfo.shmid, 0, 0); + + if (myshminfo.shmaddr == ((char *) -1)) { + xprintf(VERBOSE|VIDEO, "Shared memory error (address error) when allocating image \n"); + gXshm.bUseShm = 0; + x11_DeInstallXErrorHandler(); + goto finishShmTesting; + } + + myshminfo.readOnly = False; + myimage->data = myshminfo.shmaddr; + + XShmAttach(gDisplay, &myshminfo); + + XSync(gDisplay, False); + + if (gXshm.bFail) { + xprintf (VERBOSE|VIDEO, "Couldn't create shared memory image\n"); + gXshm.bUseShm = 0; + x11_DeInstallXErrorHandler(); + goto finishShmTesting; + } + + XShmDetach (gDisplay, &myshminfo); + XDestroyImage (myimage); + shmdt (myshminfo.shmaddr); + shmctl (myshminfo.shmid, IPC_RMID, 0); + + x11_DeInstallXErrorHandler(); + + finishShmTesting: + + if (!gXshm.bUseShm) { + printf ("\n\n!!! failed to initialize X shared memory extension. Fall back to plain X11 functions. This is very slow and mostly untested. Are you sure you're using a local graphics device for output? Remote playing via network is not supported by xine!!!\n\n"); + } + + + /* + * init global variables + */ + + gXshm.bFullscreen = 0; + gXshm.bIsFullscreen = 0; + gXshm.ratio = 0; + gXshm.user_ratio = ASPECT_AUTO; + gXshm.user_ratio_changed = 0 ; + gXshm.bLogoMode = 1; + gXshm.bYuvInitialized = 0; + gXshm.cur_image = NULL; + + set_image_format_xshm (720,576,1,IMGFMT_YV12); + + create_cursor_xshm(DefaultColormap(gDisplay, 0)); + gXshm.current_cursor = SHOW_CURSOR; + + /* + * If gVo.depth is 24 then it may either be a 3 or 4 byte per pixel + * format. We can't use bpp because then we would lose the + * distinction between 15/16bit gVo.depth (2 byte formate assumed). + * + * FIXME - change yuv2rgb_init to take both gVo.depth and bpp + * parameters + */ + + if (gXshm.depth>16) + printf ("\n\nWARNING: current display depth is %d. For better performance\na depth of 16 bpp is recommended!\n\n", + gXshm.depth); + + /* yuv2rgb_init((gXshm.depth == 24) ? gXshm.bpp : gXshm.depth,MODE_RGB); */ + + /* XUNLOCK (); */ + + return &vo_xshm; +} |