1 /*******************************************************************************
2 * vout_x11.c: X11 video output display method
4 *******************************************************************************/
6 /*******************************************************************************
8 *******************************************************************************/
13 #include <sys/types.h>
17 #include <X11/Xutil.h>
18 #include <X11/extensions/XShm.h>
23 #include "vlc_thread.h"
26 #include "video_output.h"
27 #include "video_sys.h"
30 /*******************************************************************************
31 * vout_sys_t: video output X11 method descriptor
32 *******************************************************************************
33 * This structure is part of the video output thread descriptor.
34 * It describes the X11 specific properties of an output thread. X11 video
35 * output is performed through regular resizable windows. Windows can be
36 * dynamically resized to adapt to the size of the streams.
37 *******************************************************************************/
38 typedef struct vout_sys_s
41 boolean_t b_shm; /* shared memory extension flag */
43 /* Internal settings and properties */
44 Display * p_display; /* display pointer */
45 int i_screen; /* screen number */
46 Window root_window; /* root window */
47 Window window; /* window instance handler */
48 GC gc; /* graphic context instance handler */
50 /* Font information */
51 int i_char_bytes_per_line; /* character width (bytes) */
52 int i_char_height; /* character height (lines) */
53 int i_char_interspacing; /* space between centers (pixels) */
54 byte_t * pi_font; /* pointer to font data */
56 /* Display buffers and shared memory information */
57 int i_buffer_index; /* buffer index */
58 XImage * p_ximage[2]; /* XImage pointer */
59 XShmSegmentInfo shm_info[2]; /* shared memory zone information */
62 /*******************************************************************************
64 *******************************************************************************/
65 static int X11OpenDisplay ( vout_thread_t *p_vout, char *psz_display, Window root_window );
66 static void X11CloseDisplay ( vout_thread_t *p_vout );
67 static int X11GetFont ( vout_thread_t *p_vout );
68 static int X11CreateWindow ( vout_thread_t *p_vout );
69 static void X11DestroyWindow ( vout_thread_t *p_vout );
70 static int X11CreateImage ( vout_thread_t *p_vout, XImage **pp_ximage );
71 static void X11DestroyImage ( XImage *p_ximage );
72 static int X11CreateShmImage ( vout_thread_t *p_vout, XImage **pp_ximage,
73 XShmSegmentInfo *p_shm_info );
74 static void X11DestroyShmImage ( vout_thread_t *p_vout, XImage *p_ximage,
75 XShmSegmentInfo *p_shm_info );
78 /*******************************************************************************
79 * vout_SysCreate: allocate X11 video thread output method
80 *******************************************************************************
81 * This function allocate and initialize a X11 vout method. It uses some of the
82 * vout properties to choose the window size, and change them according to the
83 * actual properties of the display.
84 *******************************************************************************/
85 int vout_SysCreate( vout_thread_t *p_vout, char *psz_display, Window root_window )
87 /* Allocate structure */
88 p_vout->p_sys = malloc( sizeof( vout_sys_t ) );
89 if( p_vout->p_sys == NULL )
91 intf_ErrMsg("error: %s\n", strerror(ENOMEM) );
95 /* Open and initialize device. This function issues its own error messages.
96 * Since XLib is usually not thread-safe, we can't use the same display
97 * pointer than the interface or another thread. However, the root window
98 * id is still valid. */
99 if( X11OpenDisplay( p_vout, psz_display, root_window ) )
101 intf_ErrMsg("error: can't initialize X11 display\n" );
102 free( p_vout->p_sys );
109 /*******************************************************************************
110 * vout_SysInit: initialize X11 video thread output method
111 *******************************************************************************
112 * This function create the XImages needed by the output thread. It is called
113 * at the beginning of the thread, but also each time the window is resized.
114 *******************************************************************************/
115 int vout_SysInit( vout_thread_t *p_vout )
119 /* Create XImages using XShm extension - on failure, fall back to regular
120 * way (and destroy the first image if it was created successfully) */
121 if( p_vout->p_sys->b_shm )
123 /* Create first image */
124 i_err = X11CreateShmImage( p_vout, &p_vout->p_sys->p_ximage[0],
125 &p_vout->p_sys->shm_info[0] );
126 if( !i_err ) /* first image has been created */
128 /* Create second image */
129 if( X11CreateShmImage( p_vout, &p_vout->p_sys->p_ximage[1],
130 &p_vout->p_sys->shm_info[1] ) )
131 { /* error creating the second image */
132 X11DestroyShmImage( p_vout, p_vout->p_sys->p_ximage[0],
133 &p_vout->p_sys->shm_info[0] );
137 if( i_err ) /* an error occured */
139 intf_Msg("warning: XShm video extension desactivated\n" );
140 p_vout->p_sys->b_shm = 0;
144 /* Create XImages without XShm extension */
145 if( !p_vout->p_sys->b_shm )
147 if( X11CreateImage( p_vout, &p_vout->p_sys->p_ximage[0] ) )
149 intf_Msg("error: can't create images\n");
150 p_vout->p_sys->p_ximage[0] = NULL;
151 p_vout->p_sys->p_ximage[1] = NULL;
154 if( X11CreateImage( p_vout, &p_vout->p_sys->p_ximage[1] ) )
156 intf_Msg("error: can't create images\n");
157 X11DestroyImage( p_vout->p_sys->p_ximage[0] );
158 p_vout->p_sys->p_ximage[0] = NULL;
159 p_vout->p_sys->p_ximage[1] = NULL;
164 /* Set bytes per line */
165 p_vout->i_bytes_per_line = p_vout->p_sys->p_ximage[0]->bytes_per_line;
167 /* Set buffer index to 0 */
168 p_vout->p_sys->i_buffer_index = 0;
172 /*******************************************************************************
173 * vout_SysEnd: terminate X11 video thread output method
174 *******************************************************************************
175 * Destroy the X11 XImages created by vout_SysInit. It is called at the end of
176 * the thread, but also each time the window is resized.
177 *******************************************************************************/
178 void vout_SysEnd( vout_thread_t *p_vout )
180 if( p_vout->p_sys->b_shm ) /* Shm XImages... */
182 X11DestroyShmImage( p_vout, p_vout->p_sys->p_ximage[0],
183 &p_vout->p_sys->shm_info[0] );
184 X11DestroyShmImage( p_vout, p_vout->p_sys->p_ximage[1],
185 &p_vout->p_sys->shm_info[1] );
187 else /* ...or regular XImages */
189 X11DestroyImage( p_vout->p_sys->p_ximage[0] );
190 X11DestroyImage( p_vout->p_sys->p_ximage[1] );
194 /*******************************************************************************
195 * vout_SysDestroy: destroy X11 video thread output method
196 *******************************************************************************
197 * Terminate an output method created by vout_X11CreateOutputMethod
198 *******************************************************************************/
199 void vout_SysDestroy( vout_thread_t *p_vout )
201 X11CloseDisplay( p_vout );
202 free( p_vout->p_sys );
205 /*******************************************************************************
206 * vout_SysManage: handle X11 events
207 *******************************************************************************
208 * This function should be called regularly by video output thread. It manages
209 * X11 events and allows window resizing. It returns a negative value if
210 * something happened which does not allow the thread to continue, and a
211 * positive one if the thread can go on, but the images have been modified and
212 * therefore it is useless to display them.
213 *******************************************************************************/
214 int vout_SysManage( vout_thread_t *p_vout )
216 if( (p_vout->i_width != p_vout->i_new_width) ||
217 (p_vout->i_height != p_vout->i_new_height) )
220 XResizeWindow( p_vout->p_sys->p_display, p_vout->p_sys->window,
221 p_vout->i_new_width, p_vout->i_new_height );
223 /* Destroy then recreate XImages to change their size */
224 vout_SysEnd( p_vout );
225 p_vout->i_width = p_vout->i_new_width;
226 p_vout->i_height = p_vout->i_new_height;
228 vout_SysInit( p_vout );
230 /* Cancel current display */
237 /*******************************************************************************
238 * vout_SysDisplay: displays previously rendered output
239 *******************************************************************************
240 * This function send the currently rendered image to X11 server, wait until
241 * it is displayed and switch the two rendering buffer, preparing next frame.
242 *******************************************************************************/
243 void vout_SysDisplay( vout_thread_t *p_vout )
245 if( p_vout->p_sys->b_shm) /* XShm is used */
247 /* Display rendered image using shared memory extension */
248 XShmPutImage(p_vout->p_sys->p_display, p_vout->p_sys->window, p_vout->p_sys->gc,
249 p_vout->p_sys->p_ximage[ p_vout->p_sys->i_buffer_index ],
251 p_vout->p_sys->p_ximage[ p_vout->p_sys->i_buffer_index ]->width,
252 p_vout->p_sys->p_ximage[ p_vout->p_sys->i_buffer_index ]->height, True);
254 /* Send the order to the X server */
255 XFlush(p_vout->p_sys->p_display);
257 else /* regular X11 capabilities are used */
259 XPutImage(p_vout->p_sys->p_display, p_vout->p_sys->window, p_vout->p_sys->gc,
260 p_vout->p_sys->p_ximage[ p_vout->p_sys->i_buffer_index ],
262 p_vout->p_sys->p_ximage[ p_vout->p_sys->i_buffer_index ]->width,
263 p_vout->p_sys->p_ximage[ p_vout->p_sys->i_buffer_index ]->height);
265 /* Send the order to the X server */
266 XFlush(p_vout->p_sys->p_display); /* ?? not needed ? */
270 p_vout->p_sys->i_buffer_index = ++p_vout->p_sys->i_buffer_index & 1;
273 /*******************************************************************************
274 * vout_SysGetPicture: get current display buffer informations
275 *******************************************************************************
276 * This function returns the address of the current display buffer.
277 *******************************************************************************/
278 void * vout_SysGetPicture( vout_thread_t *p_vout )
280 return( p_vout->p_sys->p_ximage[ p_vout->p_sys->i_buffer_index ]->data );
283 /*******************************************************************************
284 * vout_SysPrint: print simple text on a picture
285 *******************************************************************************
286 * This function will print a simple text on the picture. It is designed to
287 * print debugging or general informations, not to render subtitles.
288 * Since there is no way to print text on an Ximage directly, this function
289 * copy directly the pixels from a font.
290 *******************************************************************************/
291 void vout_SysPrint( vout_thread_t *p_vout, int i_x, int i_y, int i_halign,
292 int i_valign, unsigned char *psz_text )
294 int i_line; /* line in character matrix */
295 int i_byte; /* byte offset in character line */
296 int i_height; /* character height */
297 int i_char_bytes_per_line; /* total bytes per line */
298 byte_t * pi_pic; /* picture data */
299 byte_t * pi_char; /* character data */
301 /* Update upper left coordinates according to alignment */
304 case 0: /* centered */
305 i_x -= p_vout->p_sys->i_char_interspacing * strlen( psz_text ) / 2;
307 case 1: /* right aligned */
308 i_x -= p_vout->p_sys->i_char_interspacing * strlen( psz_text );
313 case 0: /* centered */
314 i_y -= p_vout->p_sys->i_char_height / 2;
316 case 1: /* bottom aligned */
317 i_y -= p_vout->p_sys->i_char_height;
321 /* Copy used variables to local */
322 i_height = p_vout->p_sys->i_char_height;
323 i_char_bytes_per_line = p_vout->p_sys->i_char_bytes_per_line;
326 for( ; *psz_text != '\0'; psz_text++ )
328 if( (*psz_text >= VOUT_MIN_CHAR) && (*psz_text < VOUT_MAX_CHAR) )
330 /* Select character */
331 pi_char = p_vout->p_sys->pi_font + (*psz_text - VOUT_MIN_CHAR) *
332 i_height * i_char_bytes_per_line;
333 pi_pic = p_vout->p_sys->p_ximage[ p_vout->p_sys->i_buffer_index ]->data +
334 i_y * p_vout->i_bytes_per_line + i_x * p_vout->i_bytes_per_pixel;
337 for( i_line = 0; i_line < i_height; i_line++ )
340 for( i_byte = 0; i_byte < i_char_bytes_per_line; i_byte++ )
342 pi_pic[ i_byte ] = *pi_char++;
345 /* Go to next line */
346 pi_pic += p_vout->i_bytes_per_line;
350 /* Jump to next character */
351 i_x += p_vout->p_sys->i_char_interspacing;
355 /* following functions are local */
357 /*******************************************************************************
358 * X11OpenDisplay: open and initialize X11 device
359 *******************************************************************************
360 * Create a window according to video output given size, and set other
361 * properties according to the display properties.
362 *******************************************************************************/
363 static int X11OpenDisplay( vout_thread_t *p_vout, char *psz_display, Window root_window )
366 p_vout->p_sys->p_display = XOpenDisplay( psz_display );
367 if( p_vout->p_sys->p_display == NULL )
369 intf_ErrMsg("error: can't open display %s\n", psz_display );
373 /* Initialize structure */
374 p_vout->p_sys->root_window = root_window;
375 p_vout->p_sys->b_shm = VOUT_XSHM &&
376 (XShmQueryExtension(p_vout->p_sys->p_display) == True);
377 p_vout->p_sys->i_screen = DefaultScreen( p_vout->p_sys->p_display );
379 /* Get the screen depth */
380 p_vout->i_screen_depth = DefaultDepth( p_vout->p_sys->p_display,
381 p_vout->p_sys->i_screen );
382 switch( p_vout->i_screen_depth )
384 case 15: /* 15 bpp (16bpp with a missing green bit) */
385 case 16: /* 16 bpp (65536 colors) */
386 p_vout->i_bytes_per_pixel = 2;
388 case 24: /* 24 bpp (millions of colors) */
389 p_vout->i_bytes_per_pixel = 3;
391 case 32: /* 32 bpp (millions of colors) */
392 p_vout->i_bytes_per_pixel = 4;
394 default: /* unsupported screen depth */
395 intf_ErrMsg("error: screen depth %d is not supported\n",
396 p_vout->i_screen_depth);
397 XCloseDisplay( p_vout->p_sys->p_display );
402 /* Create a window */
403 if( X11CreateWindow( p_vout ) )
405 intf_ErrMsg("error: can't open a window\n");
406 XCloseDisplay( p_vout->p_sys->p_display );
410 /* Get font information */
411 if( X11GetFont( p_vout ) )
413 intf_ErrMsg("error: can't read default font\n");
414 X11DestroyWindow( p_vout );
415 XCloseDisplay( p_vout->p_sys->p_display );
422 /*******************************************************************************
423 * X11CloseDisplay: close X11 device
424 *******************************************************************************
425 * Returns all resources allocated by X11OpenDisplay and restore the original
426 * state of the display.
427 *******************************************************************************/
428 static void X11CloseDisplay( vout_thread_t *p_vout )
431 free( p_vout->p_sys->pi_font );
433 // Destroy window and close display
434 X11DestroyWindow( p_vout );
435 XCloseDisplay( p_vout->p_sys->p_display );
438 /*******************************************************************************
439 * X11GetFont: get default font bitmap informations
440 *******************************************************************************
441 * This function will convert a font into a bitmap for later use by the
442 * vout_SysPrint function.
443 *******************************************************************************/
444 static int X11GetFont( vout_thread_t *p_vout )
446 XFontStruct * p_font_info; /* font information structure */
447 Pixmap pixmap; /* pixmap used to draw characters */
448 GC gc; /* graphic context */
449 XGCValues gc_values; /* graphic context properties */
450 XImage * p_ximage; /* ximage for character */
451 unsigned char i_char; /* character index */
452 int i_char_width; /* character width (pixels) */
453 int i_char_bytes; /* total character size */
456 p_font_info = XLoadQueryFont( p_vout->p_sys->p_display, "fixed" );
457 if( p_font_info == NULL )
459 intf_ErrMsg("error: can't load 'fixed' font\n");
463 /* Get character size */
464 i_char_width = p_font_info->max_bounds.lbearing +
465 p_font_info->max_bounds.rbearing;
466 p_vout->p_sys->i_char_bytes_per_line = i_char_width * p_vout->i_bytes_per_pixel;
467 p_vout->p_sys->i_char_height = p_font_info->max_bounds.ascent +
468 p_font_info->max_bounds.descent;
469 i_char_bytes = p_vout->p_sys->i_char_bytes_per_line *
470 p_vout->p_sys->i_char_height;
471 p_vout->p_sys->i_char_interspacing = p_font_info->max_bounds.width;
473 /* Allocate font descriptor */
474 p_vout->p_sys->pi_font = malloc( i_char_bytes * ( VOUT_MAX_CHAR - VOUT_MIN_CHAR ) );
475 if( p_vout->p_sys->pi_font == NULL )
477 intf_ErrMsg("error: %s\n", strerror( ENOMEM ) );
478 XFreeFont( p_vout->p_sys->p_display, p_font_info );
482 /* Create drawable and graphic context */
483 gc_values.foreground = XBlackPixel( p_vout->p_sys->p_display,
484 p_vout->p_sys->i_screen );
485 gc_values.background = XBlackPixel( p_vout->p_sys->p_display,
486 p_vout->p_sys->i_screen );
487 gc_values.font = p_font_info->fid;
488 pixmap = XCreatePixmap( p_vout->p_sys->p_display, p_vout->p_sys->window,
490 p_vout->p_sys->i_char_height *(VOUT_MAX_CHAR-VOUT_MIN_CHAR),
491 p_vout->i_screen_depth );
492 gc = XCreateGC( p_vout->p_sys->p_display, pixmap,
493 GCForeground | GCBackground | GCFont, &gc_values );
495 /* Clear pixmap and invert graphic context */
496 XFillRectangle( p_vout->p_sys->p_display, pixmap, gc, 0, 0, i_char_width,
497 p_vout->p_sys->i_char_height*(VOUT_MAX_CHAR-VOUT_MIN_CHAR) );
498 XSetForeground( p_vout->p_sys->p_display, gc,
499 XWhitePixel( p_vout->p_sys->p_display, p_vout->p_sys->i_screen ) );
500 XSetBackground( p_vout->p_sys->p_display, gc,
501 XBlackPixel( p_vout->p_sys->p_display, p_vout->p_sys->i_screen ) );
503 /* Copy characters bitmaps to font descriptor */
504 for( i_char = VOUT_MIN_CHAR; i_char < VOUT_MAX_CHAR; i_char++ )
506 XDrawString( p_vout->p_sys->p_display, pixmap, gc, 0,
507 p_font_info->max_bounds.ascent +
508 (i_char-VOUT_MIN_CHAR) * p_vout->p_sys->i_char_height,
511 p_ximage = XGetImage( p_vout->p_sys->p_display, pixmap, 0, 0, i_char_width,
512 p_vout->p_sys->i_char_height*(VOUT_MAX_CHAR-VOUT_MIN_CHAR),
514 memcpy( p_vout->p_sys->pi_font, p_ximage->data,
515 i_char_bytes*(VOUT_MAX_CHAR-VOUT_MIN_CHAR));
517 /* Free resources, unload font and return */
518 XDestroyImage( p_ximage );
519 XFreeGC( p_vout->p_sys->p_display, gc );
520 XFreePixmap( p_vout->p_sys->p_display, pixmap );
521 XFreeFont( p_vout->p_sys->p_display, p_font_info );
525 /*******************************************************************************
526 * X11CreateWindow: create X11 vout window
527 *******************************************************************************
528 * The video output window will be created. Normally, this window is wether
529 * full screen or part of a parent window. Therefore, it does not need a
530 * title or other hints. Thery are still supplied in case the window would be
531 * spawned as a standalone one by the interface.
532 *******************************************************************************/
533 static int X11CreateWindow( vout_thread_t *p_vout )
535 XSetWindowAttributes xwindow_attributes;
539 boolean_t b_map_notify;
541 /* Prepare window attributes */
542 xwindow_attributes.backing_store = Always; /* save the hidden part */
544 /* Create the window and set hints */
545 p_vout->p_sys->window = XCreateSimpleWindow( p_vout->p_sys->p_display,
546 p_vout->p_sys->root_window,
548 p_vout->i_width, p_vout->i_height,
550 XSelectInput( p_vout->p_sys->p_display, p_vout->p_sys->window,
551 ExposureMask | StructureNotifyMask );
552 XChangeWindowAttributes( p_vout->p_sys->p_display, p_vout->p_sys->window,
553 CWBackingStore, &xwindow_attributes);
555 /* Creation of a graphic context that doesn't generate a GraphicsExpose event
556 when using functions like XCopyArea */
557 xgcvalues.graphics_exposures = False;
558 p_vout->p_sys->gc = XCreateGC( p_vout->p_sys->p_display, p_vout->p_sys->window,
559 GCGraphicsExposures, &xgcvalues);
561 /* Send orders to server, and wait until window is displayed - two events
562 * must be received: a MapNotify event, an Expose event allowing drawing in the
566 XMapWindow( p_vout->p_sys->p_display, p_vout->p_sys->window);
569 XNextEvent( p_vout->p_sys->p_display, &xevent);
570 if( (xevent.type == Expose)
571 && (xevent.xexpose.window == p_vout->p_sys->window) )
575 else if( (xevent.type == MapNotify)
576 && (xevent.xmap.window == p_vout->p_sys->window) )
581 while( !( b_expose && b_map_notify ) );
582 XSelectInput( p_vout->p_sys->p_display, p_vout->p_sys->window, 0 );
584 /* At this stage, the window is openned, displayed, and ready to receive
589 /*******************************************************************************
590 * X11DestroyWindow: destroy X11 window
591 *******************************************************************************
592 * Destroy an X11 window created by vout_X11CreateWindow
593 *******************************************************************************/
594 static void X11DestroyWindow( vout_thread_t *p_vout )
596 XUnmapWindow( p_vout->p_sys->p_display, p_vout->p_sys->window );
597 XFreeGC( p_vout->p_sys->p_display, p_vout->p_sys->gc );
598 XDestroyWindow( p_vout->p_sys->p_display, p_vout->p_sys->window );
601 /*******************************************************************************
602 * X11CreateImage: create an XImage
603 *******************************************************************************
604 * Create a simple XImage used as a buffer.
605 *******************************************************************************/
606 static int X11CreateImage( vout_thread_t *p_vout, XImage **pp_ximage )
608 byte_t * pb_data; /* image data storage zone */
609 int i_quantum; /* XImage quantum (see below) */
611 /* Allocate memory for image */
612 p_vout->i_bytes_per_line = p_vout->i_width * p_vout->i_bytes_per_pixel;
613 pb_data = (byte_t *) malloc( p_vout->i_bytes_per_line * p_vout->i_height );
614 if( !pb_data ) /* error */
616 intf_ErrMsg("error: %s\n", strerror(ENOMEM));
620 /* Optimize the quantum of a scanline regarding its size - the quantum is
621 a diviser of the number of bits between the start of two scanlines. */
622 if( !(( p_vout->i_bytes_per_line ) % 32) )
628 if( !(( p_vout->i_bytes_per_line ) % 16) )
639 *pp_ximage = XCreateImage( p_vout->p_sys->p_display,
640 DefaultVisual(p_vout->p_sys->p_display, p_vout->p_sys->i_screen),
641 p_vout->i_screen_depth, ZPixmap, 0, pb_data,
642 p_vout->i_width, p_vout->i_height, i_quantum, 0);
643 if(! *pp_ximage ) /* error */
645 intf_ErrMsg( "error: XCreateImage() failed\n" );
653 /*******************************************************************************
654 * X11CreateShmImage: create an XImage using shared memory extension
655 *******************************************************************************
656 * Prepare an XImage for DisplayX11ShmImage function.
657 * The order of the operations respects the recommandations of the mit-shm
658 * document by J.Corbet and K.Packard. Most of the parameters were copied from
660 *******************************************************************************/
661 static int X11CreateShmImage( vout_thread_t *p_vout, XImage **pp_ximage,
662 XShmSegmentInfo *p_shm_info)
665 *pp_ximage = XShmCreateImage( p_vout->p_sys->p_display,
666 DefaultVisual(p_vout->p_sys->p_display, p_vout->p_sys->i_screen),
667 p_vout->i_screen_depth, ZPixmap, 0,
668 p_shm_info, p_vout->i_width, p_vout->i_height );
669 if(! *pp_ximage ) /* error */
671 intf_ErrMsg("error: XShmCreateImage() failed\n");
675 /* Allocate shared memory segment - 0777 set the access permission
676 * rights (like umask), they are not yet supported by X servers */
677 p_shm_info->shmid = shmget( IPC_PRIVATE,
678 (*pp_ximage)->bytes_per_line * (*pp_ximage)->height,
680 if( p_shm_info->shmid < 0) /* error */
682 intf_ErrMsg("error: can't allocate shared image data (%s)\n",
684 XDestroyImage( *pp_ximage );
688 /* Attach shared memory segment to process (read/write) */
689 p_shm_info->shmaddr = (*pp_ximage)->data = shmat(p_shm_info->shmid, 0, 0);
690 if(! p_shm_info->shmaddr )
692 intf_ErrMsg("error: can't attach shared memory (%s)\n",
694 shmctl( p_shm_info->shmid, IPC_RMID, 0 ); /* free shared memory */
695 XDestroyImage( *pp_ximage );
699 /* Mark the shm segment to be removed when there will be no more
700 * attachements, so it is automatic on process exit or after shmdt */
701 shmctl( p_shm_info->shmid, IPC_RMID, 0 );
703 /* Attach shared memory segment to X server (read only) */
704 p_shm_info->readOnly = True;
705 if( XShmAttach( p_vout->p_sys->p_display, p_shm_info ) == False ) /* error */
707 intf_ErrMsg("error: can't attach shared memory to X11 server\n");
708 shmdt( p_shm_info->shmaddr ); /* detach shared memory from process
709 * and automatic free */
710 XDestroyImage( *pp_ximage );
714 /* Send image to X server. This instruction is required, since having
715 * built a Shm XImage and not using it causes an error on XCloseDisplay */
716 XFlush( p_vout->p_sys->p_display );
720 /*******************************************************************************
721 * X11DestroyImage: destroy an XImage
722 *******************************************************************************
723 * Destroy XImage AND associated data. If pointer is NULL, the image won't be
724 * destroyed (see vout_X11ManageOutputMethod())
725 *******************************************************************************/
726 static void X11DestroyImage( XImage *p_ximage )
728 if( p_ximage != NULL )
730 XDestroyImage( p_ximage ); /* no free() required */
734 /*******************************************************************************
736 *******************************************************************************
737 * Destroy XImage AND associated data. Detach shared memory segment from
738 * server and process, then free it. If pointer is NULL, the image won't be
739 * destroyed (see vout_X11ManageOutputMethod())
740 *******************************************************************************/
741 static void X11DestroyShmImage( vout_thread_t *p_vout, XImage *p_ximage,
742 XShmSegmentInfo *p_shm_info )
744 /* If pointer is NULL, do nothing */
745 if( p_ximage == NULL )
750 XShmDetach( p_vout->p_sys->p_display, p_shm_info ); /* detach from server */
751 XDestroyImage( p_ximage );
752 if( shmdt( p_shm_info->shmaddr ) ) /* detach shared memory from process */
753 { /* also automatic freeing... */
754 intf_ErrMsg("error: can't detach shared memory (%s)\n",