#define DISP /* * video_out_x11.c, X11 interface * * * Copyright (C) 1996, MPEG Software Simulation Group. All Rights Reserved. * * Hacked into mpeg2dec by * * Aaron Holtzman * * 15 & 16 bpp support added by Franck Sicard * */ #include #include #include #include "config.h" #include "video_out.h" #include "video_out_internal.h" LIBVO_EXTERN(x11) #include #include #include #include #include "yuv2rgb.h" static vo_info_t vo_info = { "X11 (XImage/Shm)", "x11", "Aaron Holtzman ", "" }; /* private prototypes */ static void Display_Image (XImage * myximage, unsigned char *ImageData); /* since it doesn't seem to be defined on some platforms */ int XShmGetEventBase(Display*); /* local data */ static unsigned char *ImageData; /* X11 related variables */ static Display *mydisplay; static Window mywindow; static GC mygc; static XImage *myximage; static int depth, bpp, mode; static XWindowAttributes attribs; static int X_already_started = 0; #define SH_MEM #ifdef SH_MEM #include #include #include //static int HandleXError _ANSI_ARGS_((Display * dpy, XErrorEvent * event)); static void InstallXErrorHandler (void); static void DeInstallXErrorHandler (void); static int Shmem_Flag; static int Quiet_Flag; static XShmSegmentInfo Shminfo[1]; static int gXErrorFlag; static int CompletionType = -1; static void InstallXErrorHandler() { //XSetErrorHandler(HandleXError); XFlush(mydisplay); } static void DeInstallXErrorHandler() { XSetErrorHandler(NULL); XFlush(mydisplay); } #endif static uint32_t image_width; static uint32_t image_height; static uint32_t image_format; extern void vo_decoration( Display * vo_Display,Window w,int d ); /* connect to server, create and map window, * allocate colors and (shared) memory */ static uint32_t init(uint32_t width, uint32_t height, uint32_t d_width, uint32_t d_height, uint32_t fullscreen, char *title, uint32_t format) { int screen; unsigned int fg, bg; char *hello = (title == NULL) ? "I hate X11" : title; char *name = ":0.0"; XSizeHints hint; XVisualInfo vinfo; XEvent xev; XGCValues xgcv; Colormap theCmap; XSetWindowAttributes xswa; unsigned long xswamask; image_height = height; image_width = width; image_format=format; if (X_already_started) return -1; if(!vo_init()) return 0; // Can't open X11 if(getenv("DISPLAY")) name = getenv("DISPLAY"); mydisplay = XOpenDisplay(name); if (mydisplay == NULL) { fprintf(stderr,"Can not open display\n"); return -1; } screen = DefaultScreen(mydisplay); hint.x = 0; hint.y = 0; hint.width = image_width; hint.height = image_height; hint.flags = PPosition | PSize; /* Get some colors */ bg = WhitePixel(mydisplay, screen); fg = BlackPixel(mydisplay, screen); XGetWindowAttributes(mydisplay, DefaultRootWindow(mydisplay), &attribs); depth = attribs.depth; // depth = vo_depthonscreen; if (depth != 15 && depth != 16 && depth != 24 && 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. */ depth = 24; } //BEGIN HACK //mywindow = XCreateSimpleWindow(mydisplay, DefaultRootWindow(mydisplay), //hint.x, hint.y, hint.width, hint.height, 4, fg, bg); // XMatchVisualInfo(mydisplay, screen, depth, TrueColor, &vinfo); theCmap = XCreateColormap(mydisplay, RootWindow(mydisplay,screen), vinfo.visual, AllocNone); xswa.background_pixel = 0; xswa.border_pixel = 1; xswa.colormap = theCmap; xswamask = CWBackPixel | CWBorderPixel |CWColormap; mywindow = XCreateWindow(mydisplay, RootWindow(mydisplay,screen), hint.x, hint.y, hint.width, hint.height, 4, depth,CopyFromParent,vinfo.visual,xswamask,&xswa); if ( fullscreen ) vo_decoration( mydisplay,mywindow,0 ); XSelectInput(mydisplay, mywindow, StructureNotifyMask); /* Tell other applications about this window */ XSetStandardProperties(mydisplay, mywindow, hello, hello, None, NULL, 0, &hint); /* Map window. */ XMapWindow(mydisplay, mywindow); /* Wait for map. */ do { XNextEvent(mydisplay, &xev); } while (xev.type != MapNotify || xev.xmap.event != mywindow); XSelectInput(mydisplay, mywindow, NoEventMask); XFlush(mydisplay); XSync(mydisplay, False); mygc = XCreateGC(mydisplay, mywindow, 0L, &xgcv); #ifdef SH_MEM if (XShmQueryExtension(mydisplay)) Shmem_Flag = 1; else { Shmem_Flag = 0; if (!Quiet_Flag) fprintf(stderr, "Shared memory not supported\nReverting to normal Xlib\n"); } if (Shmem_Flag) CompletionType = XShmGetEventBase(mydisplay) + ShmCompletion; InstallXErrorHandler(); if (Shmem_Flag) { myximage = XShmCreateImage(mydisplay, vinfo.visual, depth, ZPixmap, NULL, &Shminfo[0], width, image_height); /* If no go, then revert to normal Xlib calls. */ if (myximage == NULL ) { if (myximage != NULL) XDestroyImage(myximage); if (!Quiet_Flag) fprintf(stderr, "Shared memory error, disabling (Ximage error)\n"); goto shmemerror; } /* Success here, continue. */ Shminfo[0].shmid = shmget(IPC_PRIVATE, myximage->bytes_per_line * myximage->height , IPC_CREAT | 0777); if (Shminfo[0].shmid < 0 ) { XDestroyImage(myximage); if (!Quiet_Flag) { printf("%s\n",strerror(errno)); perror(strerror(errno)); fprintf(stderr, "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); if (!Quiet_Flag) fprintf(stderr, "Shared memory error, disabling (address error)\n"); goto shmemerror; } myximage->data = Shminfo[0].shmaddr; ImageData = (unsigned char *) myximage->data; Shminfo[0].readOnly = False; XShmAttach(mydisplay, &Shminfo[0]); XSync(mydisplay, False); if (gXErrorFlag) { /* Ultimate failure here. */ XDestroyImage(myximage); shmdt(Shminfo[0].shmaddr); if (!Quiet_Flag) fprintf(stderr, "Shared memory error, disabling.\n"); gXErrorFlag = 0; goto shmemerror; } else { shmctl(Shminfo[0].shmid, IPC_RMID, 0); } if (!Quiet_Flag) { fprintf(stderr, "Sharing memory.\n"); } } else { shmemerror: Shmem_Flag = 0; #endif myximage = XGetImage(mydisplay, mywindow, 0, 0, width, image_height, AllPlanes, ZPixmap); ImageData = myximage->data; #ifdef SH_MEM } DeInstallXErrorHandler(); #endif bpp = myximage->bits_per_pixel; printf("X11 color mask: R:%X G:%X B:%X\n", myximage->red_mask,myximage->green_mask,myximage->blue_mask); // If we have blue in the lowest bit then obviously RGB mode = ((myximage->blue_mask & 0x01) != 0) ? MODE_RGB : MODE_BGR; // mode = ((myximage->blue_mask & 0x01) == 0) ? MODE_RGB : MODE_BGR; #ifdef WORDS_BIGENDIAN if (myximage->byte_order != MSBFirst) #else if (myximage->byte_order != LSBFirst) #endif { fprintf( stderr, "No support fon non-native XImage byte order!\n" ); return -1; } /* * If 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 depth (2 byte formate assumed). * * FIXME - change yuv2rgb_init to take both depth and bpp * parameters */ if(format==IMGFMT_YV12) yuv2rgb_init((depth == 24) ? bpp : depth, mode); XSelectInput(mydisplay, mywindow, StructureNotifyMask | KeyPressMask ); X_already_started++; return 0; } static const vo_info_t* get_info(void) { return &vo_info; } static void Terminate_Display_Process(void) { getchar(); /* wait for enter to remove window */ #ifdef SH_MEM if (Shmem_Flag) { XShmDetach(mydisplay, &Shminfo[0]); XDestroyImage(myximage); shmdt(Shminfo[0].shmaddr); } #endif XDestroyWindow(mydisplay, mywindow); XCloseDisplay(mydisplay); X_already_started = 0; } static void Display_Image(XImage *myximage, uint8_t *ImageData) { #ifdef DISP #ifdef SH_MEM if (Shmem_Flag) { XShmPutImage(mydisplay, mywindow, mygc, myximage, 0, 0, 0, 0, myximage->width, myximage->height, True); XFlush(mydisplay); } else #endif { XPutImage(mydisplay, mywindow, mygc, myximage, 0, 0, 0, 0, myximage->width, myximage->height); XFlush(mydisplay); } #endif } static void flip_page(void) { int i; XEvent Event; char buf[100]; KeySym keySym; XComposeStatus stat; unsigned long vo_KeyTable[512]; while ( XPending( mydisplay ) ) { XNextEvent( mydisplay,&Event ); switch( Event.type ) { case ConfigureNotify: // windowwidth = Event.xconfigure.width; // windowheight = Event.xconfigure.height; break; case KeyPress: XLookupString( &Event.xkey,buf,sizeof(buf),&keySym,&stat ); vo_keyboard( ( (keySym&0xff00) != 0?( (keySym&0x00ff) + 256 ):( keySym ) ) ); break; } } Display_Image(myximage, ImageData); } static uint32_t draw_slice(uint8_t *src[], uint32_t slice_num) { uint8_t *dst; dst = ImageData + image_width * 16 * (bpp/8) * slice_num; yuv2rgb(dst , src[0], src[1], src[2], image_width, 16, image_width*(bpp/8), image_width, image_width/2 ); return 0; } void rgb15to16_mmx(char* s0,char* d0,int count); #if 1 static uint32_t draw_frame(uint8_t *src[]) { if(image_format==IMGFMT_YV12){ yuv2rgb(ImageData, src[0], src[1], src[2], image_width, image_height, image_width*(bpp/8), image_width, image_width/2 ); } else { int sbpp=((image_format&0xFF)+7)/8; int dbpp=(bpp+7)/8; char *d=ImageData; char *s=src[0]; //printf("sbpp=%d dbpp=%d depth=%d bpp=%d\n",sbpp,dbpp,depth,bpp); #if 0 // flipped BGR int i; // printf("Rendering flipped BGR frame bpp=%d src=%d dst=%d\n",bpp,sbpp,dbpp); s+=sbpp*image_width*image_height; for(i=0;i16bpp #ifdef HAVE_MMX rgb15to16_mmx(s,d,2*image_width*image_height); #else unsigned short *s1=(unsigned short *)s; unsigned short *d1=(unsigned short *)d; unsigned short *e=s1+image_width*image_height; while(s132bpp conversion\n"); while(s