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