comparison libvo/vo_x11.c @ 1:3b5f5d1c5041

Initial revision
author arpi_esp
date Sat, 24 Feb 2001 20:28:24 +0000
parents
children 1fc618eba830
comparison
equal deleted inserted replaced
0:c1bb2c071d63 1:3b5f5d1c5041
1 #define DISP
2
3 /*
4 * video_out_x11.c,X11 interface
5 *
6 *
7 * Copyright ( C ) 1996,MPEG Software Simulation Group. All Rights Reserved.
8 *
9 * Hacked into mpeg2dec by
10 *
11 * Aaron Holtzman <aholtzma@ess.engr.uvic.ca>
12 *
13 * 15 & 16 bpp support added by Franck Sicard <Franck.Sicard@solsoft.fr>
14 *
15 */
16
17 #include <stdio.h>
18 #include <stdlib.h>
19 #include <string.h>
20 #include <signal.h>
21
22 #include "config.h"
23 #include "video_out.h"
24 #include "video_out_internal.h"
25
26 LIBVO_EXTERN( x11 )
27
28 #include <X11/Xlib.h>
29 #include <X11/Xutil.h>
30 #include <X11/extensions/XShm.h>
31 #include <errno.h>
32 #include "yuv2rgb.h"
33
34 static vo_info_t vo_info =
35 {
36 "X11 ( XImage/Shm )",
37 "x11",
38 "Aaron Holtzman <aholtzma@ess.engr.uvic.ca>",
39 ""
40 };
41
42 /* private prototypes */
43 static void Display_Image ( XImage * myximage,unsigned char *ImageData );
44
45 /* since it doesn't seem to be defined on some platforms */
46 int XShmGetEventBase( Display* );
47
48 /* local data */
49 static unsigned char *ImageData;
50
51 /* X11 related variables */
52 static Display *mDisplay;
53 static Window mywindow;
54 static GC mygc;
55 static XImage *myximage;
56 static int depth,bpp,mode;
57 static XWindowAttributes attribs;
58 static int X_already_started=0;
59
60 static int windowwidth,windowheight;
61
62 #define SH_MEM
63
64 #ifdef SH_MEM
65
66 #include <sys/ipc.h>
67 #include <sys/shm.h>
68 #include <X11/extensions/XShm.h>
69
70 //static int HandleXError _ANSI_ARGS_( ( Display * dpy,XErrorEvent * event ) );
71 static void InstallXErrorHandler ( void );
72 static void DeInstallXErrorHandler ( void );
73
74 static int Shmem_Flag;
75 static int Quiet_Flag;
76 static XShmSegmentInfo Shminfo[1];
77 static int gXErrorFlag;
78 static int CompletionType=-1;
79
80 static void InstallXErrorHandler()
81 {
82 //XSetErrorHandler( HandleXError );
83 XFlush( mDisplay );
84 }
85
86 static void DeInstallXErrorHandler()
87 {
88 XSetErrorHandler( NULL );
89 XFlush( mDisplay );
90 }
91
92 #endif
93
94 static uint32_t image_width;
95 static uint32_t image_height;
96 static uint32_t image_format;
97
98 extern void vo_decoration( Display * vo_Display,Window w,int d );
99
100 static Bool mEvents( Display * display,XEvent * Event,XPointer arg )
101 {
102 int i;
103 char buf[100];
104 KeySym keySym;
105 XComposeStatus stat;
106 unsigned long vo_KeyTable[512];
107
108 switch( Event->type )
109 {
110 case ConfigureNotify:
111 windowwidth=Event->xconfigure.width;
112 windowheight=Event->xconfigure.height;
113 break;
114 case KeyPress:
115 XLookupString( &Event->xkey,buf,sizeof(buf),&keySym,&stat );
116 vo_keyboard( ( (keySym&0xff00) != 0?( (keySym&0x00ff) + 256 ):( keySym ) ) );
117 break;
118 }
119 return 0;
120 }
121
122 static XEvent mEvent;
123
124 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 )
125 {
126 int screen;
127 unsigned int fg,bg;
128 char *hello=( title == NULL ) ? "X11 render" : title;
129 char *name=":0.0";
130 XSizeHints hint;
131 XVisualInfo vinfo;
132 XEvent xev;
133 XGCValues xgcv;
134 Colormap theCmap;
135 XSetWindowAttributes xswa;
136 unsigned long xswamask;
137
138 image_height=height;
139 image_width=width;
140 image_format=format;
141
142 if ( X_already_started ) return -1;
143 if( !vo_init() ) return 0; // Can't open X11
144
145 if( getenv( "DISPLAY" ) ) name=getenv( "DISPLAY" );
146
147 mDisplay=XOpenDisplay( name );
148
149 if ( mDisplay == NULL )
150 {
151 fprintf( stderr,"Can not open display\n" );
152 return -1;
153 }
154
155 screen=DefaultScreen( mDisplay );
156
157 hint.x=0;
158 hint.y=0;
159 hint.width=image_width;
160 hint.height=image_height;
161 if ( fullscreen )
162 {
163 hint.width=vo_screenwidth;
164 hint.height=vo_screenheight;
165 }
166 windowwidth=hint.width;
167 windowheight=hint.height;
168 hint.flags=PPosition | PSize;
169
170 bg=WhitePixel( mDisplay,screen );
171 fg=BlackPixel( mDisplay,screen );
172
173 XGetWindowAttributes( mDisplay,DefaultRootWindow( mDisplay ),&attribs );
174 depth=attribs.depth;
175
176 if ( depth != 15 && depth != 16 && depth != 24 && depth != 32 ) depth=24;
177 XMatchVisualInfo( mDisplay,screen,depth,TrueColor,&vinfo );
178
179 theCmap =XCreateColormap( mDisplay,RootWindow( mDisplay,screen ),
180 vinfo.visual,AllocNone );
181
182 xswa.background_pixel=0;
183 xswa.border_pixel=1;
184 xswa.colormap=theCmap;
185 xswamask=CWBackPixel | CWBorderPixel |CWColormap;
186
187 mywindow=XCreateWindow( mDisplay,RootWindow( mDisplay,screen ),
188 hint.x,hint.y,
189 hint.width,hint.height,
190 xswa.border_pixel,depth,CopyFromParent,vinfo.visual,xswamask,&xswa );
191
192 if ( fullscreen ) vo_decoration( mDisplay,mywindow,0 );
193 XSelectInput( mDisplay,mywindow,StructureNotifyMask );
194 XSetStandardProperties( mDisplay,mywindow,hello,hello,None,NULL,0,&hint );
195 XMapWindow( mDisplay,mywindow );
196 do { XNextEvent( mDisplay,&xev ); } while ( xev.type != MapNotify || xev.xmap.event != mywindow );
197
198 XSelectInput( mDisplay,mywindow,NoEventMask );
199
200 XFlush( mDisplay );
201 XSync( mDisplay,False );
202
203 mygc=XCreateGC( mDisplay,mywindow,0L,&xgcv );
204
205 #ifdef SH_MEM
206 if ( XShmQueryExtension( mDisplay ) ) Shmem_Flag=1;
207 else
208 {
209 Shmem_Flag=0;
210 if ( !Quiet_Flag ) fprintf( stderr,"Shared memory not supported\nReverting to normal Xlib\n" );
211 }
212 if ( Shmem_Flag ) CompletionType=XShmGetEventBase( mDisplay ) + ShmCompletion;
213
214 InstallXErrorHandler();
215
216 if ( Shmem_Flag )
217 {
218 myximage=XShmCreateImage( mDisplay,vinfo.visual,depth,ZPixmap,NULL,&Shminfo[0],width,image_height );
219 if ( myximage == NULL )
220 {
221 if ( myximage != NULL ) XDestroyImage( myximage );
222 if ( !Quiet_Flag ) fprintf( stderr,"Shared memory error,disabling ( Ximage error )\n" );
223 goto shmemerror;
224 }
225 Shminfo[0].shmid=shmget( IPC_PRIVATE,
226 myximage->bytes_per_line * myximage->height ,
227 IPC_CREAT | 0777 );
228 if ( Shminfo[0].shmid < 0 )
229 {
230 XDestroyImage( myximage );
231 if ( !Quiet_Flag )
232 {
233 printf( "%s\n",strerror( errno ) );
234 perror( strerror( errno ) );
235 fprintf( stderr,"Shared memory error,disabling ( seg id error )\n" );
236 }
237 goto shmemerror;
238 }
239 Shminfo[0].shmaddr=( char * ) shmat( Shminfo[0].shmid,0,0 );
240
241 if ( Shminfo[0].shmaddr == ( ( char * ) -1 ) )
242 {
243 XDestroyImage( myximage );
244 if ( Shminfo[0].shmaddr != ( ( char * ) -1 ) ) shmdt( Shminfo[0].shmaddr );
245 if ( !Quiet_Flag ) fprintf( stderr,"Shared memory error,disabling ( address error )\n" );
246 goto shmemerror;
247 }
248 myximage->data=Shminfo[0].shmaddr;
249 ImageData=( unsigned char * ) myximage->data;
250 Shminfo[0].readOnly=False;
251 XShmAttach( mDisplay,&Shminfo[0] );
252
253 XSync( mDisplay,False );
254
255 if ( gXErrorFlag )
256 {
257 XDestroyImage( myximage );
258 shmdt( Shminfo[0].shmaddr );
259 if ( !Quiet_Flag ) fprintf( stderr,"Shared memory error,disabling.\n" );
260 gXErrorFlag=0;
261 goto shmemerror;
262 }
263 else
264 shmctl( Shminfo[0].shmid,IPC_RMID,0 );
265
266 if ( !Quiet_Flag ) fprintf( stderr,"Sharing memory.\n" );
267 }
268 else
269 {
270 shmemerror:
271 Shmem_Flag=0;
272 #endif
273 myximage=XGetImage( mDisplay,mywindow,0,0,
274 width,image_height,AllPlanes,ZPixmap );
275 ImageData=myximage->data;
276 #ifdef SH_MEM
277 }
278
279 DeInstallXErrorHandler();
280 #endif
281
282 bpp=myximage->bits_per_pixel;
283
284 fprintf( stderr,"X11 color mask: R:%X G:%X B:%X\n",myximage->red_mask,myximage->green_mask,myximage->blue_mask );
285
286 // If we have blue in the lowest bit then obviously RGB
287 mode=( ( myximage->blue_mask & 0x01 ) != 0 ) ? MODE_RGB : MODE_BGR;
288 #ifdef WORDS_BIGENDIAN
289 if ( myximage->byte_order != MSBFirst )
290 #else
291 if ( myximage->byte_order != LSBFirst )
292 #endif
293 {
294 fprintf( stderr,"No support fon non-native XImage byte order!\n" );
295 return -1;
296 }
297
298 if( format==IMGFMT_YV12 ) yuv2rgb_init( ( depth == 24 ) ? bpp : depth,mode );
299
300 XSelectInput( mDisplay,mywindow,StructureNotifyMask | KeyPressMask );
301 X_already_started++;
302
303 // vo_initthread( mThread );
304
305 if((vo_eventhandler_pid=fork())==0){
306 XIfEvent( mDisplay,&mEvent,mEvents,NULL );
307 exit(0);
308 }
309
310 return 0;
311 }
312
313 static const vo_info_t* get_info( void )
314 { return &vo_info; }
315
316 static void Terminate_Display_Process( void )
317 {
318 getchar(); /* wait for enter to remove window */
319 #ifdef SH_MEM
320 if ( Shmem_Flag )
321 {
322 XShmDetach( mDisplay,&Shminfo[0] );
323 XDestroyImage( myximage );
324 shmdt( Shminfo[0].shmaddr );
325 }
326 #endif
327 XDestroyWindow( mDisplay,mywindow );
328 XCloseDisplay( mDisplay );
329 X_already_started=0;
330 }
331
332 static void Display_Image( XImage *myximage,uint8_t *ImageData )
333 {
334 #ifdef DISP
335 #ifdef SH_MEM
336 if ( Shmem_Flag )
337 {
338 XShmPutImage( mDisplay,mywindow,mygc,myximage,
339 0,0,
340 ( windowwidth - myximage->width ) / 2,( windowheight - myximage->height ) / 2,
341 myximage->width,myximage->height,True );
342 XFlush( mDisplay );
343 }
344 else
345 #endif
346 {
347 XPutImage( mDisplay,mywindow,mygc,myximage,
348 0,0,
349 ( windowwidth - myximage->width ) / 2,( windowheight - myximage->height ) / 2,
350 myximage->width,myximage->height );
351 XFlush( mDisplay );
352 }
353 #endif
354 }
355
356 static void flip_page( void )
357 { Display_Image( myximage,ImageData ); }
358
359 static uint32_t draw_slice( uint8_t *src[],int stride[],int w,int h,int x,int y )
360 {
361 uint8_t *dst;
362
363 dst=ImageData + ( image_width * y + x ) * ( bpp/8 );
364 yuv2rgb( dst,src[0],src[1],src[2],w,h,image_width*( bpp/8 ),stride[0],stride[1] );
365 return 0;
366 }
367
368 void rgb15to16_mmx( char* s0,char* d0,int count );
369
370 #if 1
371 static uint32_t draw_frame( uint8_t *src[] )
372 {
373 if( image_format==IMGFMT_YV12 )
374 {
375 yuv2rgb( ImageData,src[0],src[1],src[2],image_width,image_height,image_width*( bpp/8 ),image_width,image_width/2 );
376 }
377 else
378 {
379 int sbpp=( ( image_format&0xFF )+7 )/8;
380 int dbpp=( bpp+7 )/8;
381 char *d=ImageData;
382 char *s=src[0];
383 //printf( "sbpp=%d dbpp=%d depth=%d bpp=%d\n",sbpp,dbpp,depth,bpp );
384 #if 0
385 // flipped BGR
386 int i;
387 //printf( "Rendering flipped BGR frame bpp=%d src=%d dst=%d\n",bpp,sbpp,dbpp );
388 s+=sbpp*image_width*image_height;
389 for( i=0;i<image_height;i++ )
390 {
391 s-=sbpp*image_width;
392 if( sbpp==dbpp ) memcpy( d,s,sbpp*image_width );
393 else
394 {
395 char *s2=s;
396 char *d2=d;
397 char *e=s2+sbpp*image_width;
398 while( s2<e )
399 {
400 d2[0]=s2[0];
401 d2[1]=s2[1];
402 d2[2]=s2[2];
403 s2+=sbpp;d2+=dbpp;
404 }
405 }
406 d+=dbpp*image_width;
407 }
408 #else
409 // memcpy( ImageData,src[0],image_width*image_height*bpp );
410 if( sbpp==dbpp )
411 {
412 //Display_Image( myximage,s );return 0;
413 #if 1
414 if( depth==16 && image_format==( IMGFMT_BGR|15 ) ){
415 // do 15bpp->16bpp
416 #ifdef HAVE_MMX
417 rgb15to16_mmx( s,d,2*image_width*image_height );
418 #else
419 unsigned short *s1=( unsigned short * )s;
420 unsigned short *d1=( unsigned short * )d;
421 unsigned short *e=s1+image_width*image_height;
422 while( s1<e )
423 {
424 register int x=*( s1++ );
425 // rrrrrggggggbbbbb
426 // 0rrrrrgggggbbbbb
427 // 0111 1111 1110 0000=0x7FE0
428 // 00000000000001 1111=0x001F
429 *( d1++ )=( x&0x001F )|( ( x&0x7FE0 )<<1 );
430 }
431 #endif
432 }
433 else
434 #endif
435 { memcpy( d,s,sbpp*image_width*image_height ); }
436 }
437 else
438 {
439 char *e=s+sbpp*image_width*image_height;
440 //printf( "libvo: using C 24->32bpp conversion\n" );
441 while( s<e )
442 {
443 d[0]=s[0];
444 d[1]=s[1];
445 d[2]=s[2];
446 s+=sbpp;d+=dbpp;
447 }
448 }
449 #endif
450 }
451 //Display_Image( myximage,ImageData );
452 return 0;
453 }
454 #endif
455
456 static uint32_t query_format( uint32_t format )
457 {
458 if( !vo_init() ) return 0; // Can't open X11
459 if( ( format&IMGFMT_BGR_MASK )==IMGFMT_BGR && ( format&0xFF )==vo_depthonscreen ) return 1;
460 switch( format )
461 {
462 case IMGFMT_YV12: return 1;
463 }
464 return 0;
465 }
466
467
468 static void
469 uninit(void)
470 {
471 printf("vo: uninit!\n");
472 vo_kill_eventhandler();
473 }
474
475
476