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, int i_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, i_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("Video: XShm 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_ErrMsg("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_ErrMsg("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 non null value on
211 *******************************************************************************/
212 int vout_SysManage( vout_thread_t *p_vout )
214 if( p_vout->i_changes & VOUT_SIZE_CHANGE )
216 intf_DbgMsg("resizing window\n");
217 p_vout->i_changes &= ~VOUT_SIZE_CHANGE;
220 XResizeWindow( p_vout->p_sys->p_display, p_vout->p_sys->window,
221 p_vout->i_width, p_vout->i_height );
223 /* Destroy XImages to change their size */
224 vout_SysEnd( p_vout );
226 /* Recreate XImages. If SysInit failed, the thread can't go on. */
227 if( vout_SysInit( p_vout ) )
229 intf_ErrMsg("error: can't resize display\n");
232 intf_Msg("Video: display resized to %dx%d\n", p_vout->i_width, p_vout->i_height);
238 /*******************************************************************************
239 * vout_SysDisplay: displays previously rendered output
240 *******************************************************************************
241 * This function send the currently rendered image to X11 server, wait until
242 * it is displayed and switch the two rendering buffer, preparing next frame.
243 *******************************************************************************/
244 void vout_SysDisplay( vout_thread_t *p_vout )
246 if( p_vout->p_sys->b_shm) /* XShm is used */
248 /* Display rendered image using shared memory extension */
249 XShmPutImage(p_vout->p_sys->p_display, p_vout->p_sys->window, p_vout->p_sys->gc,
250 p_vout->p_sys->p_ximage[ p_vout->p_sys->i_buffer_index ],
252 p_vout->p_sys->p_ximage[ p_vout->p_sys->i_buffer_index ]->width,
253 p_vout->p_sys->p_ximage[ p_vout->p_sys->i_buffer_index ]->height, True);
255 /* Send the order to the X server */
256 XFlush(p_vout->p_sys->p_display);
258 else /* regular X11 capabilities are used */
260 XPutImage(p_vout->p_sys->p_display, p_vout->p_sys->window, p_vout->p_sys->gc,
261 p_vout->p_sys->p_ximage[ p_vout->p_sys->i_buffer_index ],
263 p_vout->p_sys->p_ximage[ p_vout->p_sys->i_buffer_index ]->width,
264 p_vout->p_sys->p_ximage[ p_vout->p_sys->i_buffer_index ]->height);
266 /* Send the order to the X server */
267 XFlush(p_vout->p_sys->p_display);
271 p_vout->p_sys->i_buffer_index = ++p_vout->p_sys->i_buffer_index & 1;
274 /*******************************************************************************
275 * vout_SysGetPicture: get current display buffer informations
276 *******************************************************************************
277 * This function returns the address of the current display buffer.
278 *******************************************************************************/
279 void * vout_SysGetPicture( vout_thread_t *p_vout )
281 return( p_vout->p_sys->p_ximage[ p_vout->p_sys->i_buffer_index ]->data );
284 /*******************************************************************************
285 * vout_SysPrint: print simple text on a picture
286 *******************************************************************************
287 * This function will print a simple text on the picture. It is designed to
288 * print debugging or general informations, not to render subtitles.
289 * Since there is no way to print text on an Ximage directly, this function
290 * copy directly the pixels from a font.
291 *******************************************************************************/
292 void vout_SysPrint( vout_thread_t *p_vout, int i_x, int i_y, int i_halign,
293 int i_valign, unsigned char *psz_text )
295 int i_line; /* line in character matrix */
296 int i_byte; /* byte offset in character line */
297 int i_height; /* character height */
298 int i_char_bytes_per_line; /* total bytes per line */
299 int i_text_width; /* total text width */
300 byte_t * pi_pic; /* picture data */
301 byte_t * pi_char; /* character data */
303 /* Update upper left coordinates according to alignment */
304 i_text_width = p_vout->p_sys->i_char_interspacing * strlen( psz_text );
307 case 0: /* centered */
308 i_x -= i_text_width / 2;
310 case 1: /* right aligned */
316 case 0: /* centered */
317 i_y -= p_vout->p_sys->i_char_height / 2;
319 case 1: /* bottom aligned */
320 i_y -= p_vout->p_sys->i_char_height;
324 /* Copy used variables to local */
325 i_height = p_vout->p_sys->i_char_height;
326 i_char_bytes_per_line = p_vout->p_sys->i_char_bytes_per_line;
328 /* Check that the text is in the screen vertically and horizontally */
329 if( (i_y < 0) || (i_y + i_height > p_vout->i_height) || (i_x < 0) ||
330 (i_x + i_text_width > p_vout->i_width) )
332 intf_DbgMsg("text '%s' would print outside the screen\n", psz_text);
337 for( ; *psz_text != '\0'; psz_text++ )
339 /* Check that the character is valid and in the screen horizontally */
340 if( (*psz_text >= VOUT_MIN_CHAR) && (*psz_text < VOUT_MAX_CHAR) )
342 /* Select character */
343 pi_char = p_vout->p_sys->pi_font + (*psz_text - VOUT_MIN_CHAR) *
344 i_height * i_char_bytes_per_line;
345 pi_pic = p_vout->p_sys->p_ximage[ p_vout->p_sys->i_buffer_index ]->data +
346 i_y * p_vout->i_bytes_per_line + i_x * p_vout->i_bytes_per_pixel;
349 for( i_line = 0; i_line < i_height; i_line++ )
352 for( i_byte = 0; i_byte < i_char_bytes_per_line; i_byte++ )
354 pi_pic[ i_byte ] = *pi_char++;
357 /* Go to next line */
358 pi_pic += p_vout->i_bytes_per_line;
362 /* Jump to next character */
363 i_x += p_vout->p_sys->i_char_interspacing;
367 /* following functions are local */
369 /*******************************************************************************
370 * X11OpenDisplay: open and initialize X11 device
371 *******************************************************************************
372 * Create a window according to video output given size, and set other
373 * properties according to the display properties.
374 *******************************************************************************/
375 static int X11OpenDisplay( vout_thread_t *p_vout, char *psz_display, Window root_window )
378 p_vout->p_sys->p_display = XOpenDisplay( psz_display );
379 if( p_vout->p_sys->p_display == NULL )
381 intf_ErrMsg("error: can't open display %s\n", psz_display );
385 /* Initialize structure */
386 p_vout->p_sys->root_window = root_window;
387 p_vout->p_sys->b_shm = (XShmQueryExtension(p_vout->p_sys->p_display) == True);
388 p_vout->p_sys->i_screen = DefaultScreen( p_vout->p_sys->p_display );
389 if( !p_vout->p_sys->b_shm )
391 intf_Msg("Video: XShm extension is not available\n");
394 /* Get the screen depth */
395 p_vout->i_screen_depth = DefaultDepth( p_vout->p_sys->p_display,
396 p_vout->p_sys->i_screen );
397 switch( p_vout->i_screen_depth )
399 case 15: /* 15 bpp (16bpp with a missing green bit) */
400 case 16: /* 16 bpp (65536 colors) */
401 p_vout->i_bytes_per_pixel = 2;
403 case 24: /* 24 bpp (millions of colors) */
404 p_vout->i_bytes_per_pixel = 3;
406 case 32: /* 32 bpp (millions of colors) */
407 p_vout->i_bytes_per_pixel = 4;
409 default: /* unsupported screen depth */
410 intf_ErrMsg("error: screen depth %d is not supported\n",
411 p_vout->i_screen_depth);
412 XCloseDisplay( p_vout->p_sys->p_display );
417 /* Create a window */
418 if( X11CreateWindow( p_vout ) )
420 intf_ErrMsg("error: can't open a window\n");
421 XCloseDisplay( p_vout->p_sys->p_display );
425 /* Get font information */
426 if( X11GetFont( p_vout ) )
428 intf_ErrMsg("error: can't read default font\n");
429 X11DestroyWindow( p_vout );
430 XCloseDisplay( p_vout->p_sys->p_display );
437 /*******************************************************************************
438 * X11CloseDisplay: close X11 device
439 *******************************************************************************
440 * Returns all resources allocated by X11OpenDisplay and restore the original
441 * state of the display.
442 *******************************************************************************/
443 static void X11CloseDisplay( vout_thread_t *p_vout )
446 free( p_vout->p_sys->pi_font );
448 // Destroy window and close display
449 X11DestroyWindow( p_vout );
450 XCloseDisplay( p_vout->p_sys->p_display );
453 /*******************************************************************************
454 * X11GetFont: get default font bitmap informations
455 *******************************************************************************
456 * This function will convert a font into a bitmap for later use by the
457 * vout_SysPrint function.
458 *******************************************************************************/
459 static int X11GetFont( vout_thread_t *p_vout )
461 XFontStruct * p_font_info; /* font information structure */
462 Pixmap pixmap; /* pixmap used to draw characters */
463 GC gc; /* graphic context */
464 XGCValues gc_values; /* graphic context properties */
465 XImage * p_ximage; /* ximage for character */
466 unsigned char i_char; /* character index */
467 int i_char_width; /* character width (pixels) */
468 int i_char_bytes; /* total character size */
471 p_font_info = XLoadQueryFont( p_vout->p_sys->p_display, "fixed" );
472 if( p_font_info == NULL )
474 intf_ErrMsg("error: can't load 'fixed' font\n");
478 /* Get character size */
479 i_char_width = p_font_info->max_bounds.lbearing +
480 p_font_info->max_bounds.rbearing;
481 p_vout->p_sys->i_char_bytes_per_line = i_char_width * p_vout->i_bytes_per_pixel;
482 p_vout->p_sys->i_char_height = p_font_info->max_bounds.ascent +
483 p_font_info->max_bounds.descent;
484 i_char_bytes = p_vout->p_sys->i_char_bytes_per_line *
485 p_vout->p_sys->i_char_height;
486 p_vout->p_sys->i_char_interspacing = p_font_info->max_bounds.width;
488 /* Allocate font descriptor */
489 p_vout->p_sys->pi_font = malloc( i_char_bytes * ( VOUT_MAX_CHAR - VOUT_MIN_CHAR ) );
490 if( p_vout->p_sys->pi_font == NULL )
492 intf_ErrMsg("error: %s\n", strerror( ENOMEM ) );
493 XFreeFont( p_vout->p_sys->p_display, p_font_info );
497 /* Create drawable and graphic context */
498 gc_values.foreground = XBlackPixel( p_vout->p_sys->p_display,
499 p_vout->p_sys->i_screen );
500 gc_values.background = XBlackPixel( p_vout->p_sys->p_display,
501 p_vout->p_sys->i_screen );
502 gc_values.font = p_font_info->fid;
503 pixmap = XCreatePixmap( p_vout->p_sys->p_display, p_vout->p_sys->window,
505 p_vout->p_sys->i_char_height *(VOUT_MAX_CHAR-VOUT_MIN_CHAR),
506 p_vout->i_screen_depth );
507 gc = XCreateGC( p_vout->p_sys->p_display, pixmap,
508 GCForeground | GCBackground | GCFont, &gc_values );
510 /* Clear pixmap and invert graphic context */
511 XFillRectangle( p_vout->p_sys->p_display, pixmap, gc, 0, 0, i_char_width,
512 p_vout->p_sys->i_char_height*(VOUT_MAX_CHAR-VOUT_MIN_CHAR) );
513 XSetForeground( p_vout->p_sys->p_display, gc,
514 XWhitePixel( p_vout->p_sys->p_display, p_vout->p_sys->i_screen ) );
515 XSetBackground( p_vout->p_sys->p_display, gc,
516 XBlackPixel( p_vout->p_sys->p_display, p_vout->p_sys->i_screen ) );
518 /* Copy characters bitmaps to font descriptor */
519 for( i_char = VOUT_MIN_CHAR; i_char < VOUT_MAX_CHAR; i_char++ )
521 XDrawString( p_vout->p_sys->p_display, pixmap, gc, 0,
522 p_font_info->max_bounds.ascent +
523 (i_char-VOUT_MIN_CHAR) * p_vout->p_sys->i_char_height,
526 p_ximage = XGetImage( p_vout->p_sys->p_display, pixmap, 0, 0, i_char_width,
527 p_vout->p_sys->i_char_height*(VOUT_MAX_CHAR-VOUT_MIN_CHAR),
529 memcpy( p_vout->p_sys->pi_font, p_ximage->data,
530 i_char_bytes*(VOUT_MAX_CHAR-VOUT_MIN_CHAR));
532 /* Free resources, unload font and return */
533 XDestroyImage( p_ximage );
534 XFreeGC( p_vout->p_sys->p_display, gc );
535 XFreePixmap( p_vout->p_sys->p_display, pixmap );
536 XFreeFont( p_vout->p_sys->p_display, p_font_info );
540 /*******************************************************************************
541 * X11CreateWindow: create X11 vout window
542 *******************************************************************************
543 * The video output window will be created. Normally, this window is wether
544 * full screen or part of a parent window. Therefore, it does not need a
545 * title or other hints. Thery are still supplied in case the window would be
546 * spawned as a standalone one by the interface.
547 *******************************************************************************/
548 static int X11CreateWindow( vout_thread_t *p_vout )
550 XSetWindowAttributes xwindow_attributes;
554 boolean_t b_map_notify;
556 /* Prepare window attributes */
557 xwindow_attributes.backing_store = Always; /* save the hidden part */
559 /* Create the window and set hints */
560 p_vout->p_sys->window = XCreateSimpleWindow( p_vout->p_sys->p_display,
561 p_vout->p_sys->root_window,
563 p_vout->i_width, p_vout->i_height,
565 XSelectInput( p_vout->p_sys->p_display, p_vout->p_sys->window,
566 ExposureMask | StructureNotifyMask );
567 XChangeWindowAttributes( p_vout->p_sys->p_display, p_vout->p_sys->window,
568 CWBackingStore, &xwindow_attributes);
570 /* Creation of a graphic context that doesn't generate a GraphicsExpose event
571 when using functions like XCopyArea */
572 xgcvalues.graphics_exposures = False;
573 p_vout->p_sys->gc = XCreateGC( p_vout->p_sys->p_display, p_vout->p_sys->window,
574 GCGraphicsExposures, &xgcvalues);
576 /* Send orders to server, and wait until window is displayed - two events
577 * must be received: a MapNotify event, an Expose event allowing drawing in the
581 XMapWindow( p_vout->p_sys->p_display, p_vout->p_sys->window);
584 XNextEvent( p_vout->p_sys->p_display, &xevent);
585 if( (xevent.type == Expose)
586 && (xevent.xexpose.window == p_vout->p_sys->window) )
590 else if( (xevent.type == MapNotify)
591 && (xevent.xmap.window == p_vout->p_sys->window) )
596 while( !( b_expose && b_map_notify ) );
597 XSelectInput( p_vout->p_sys->p_display, p_vout->p_sys->window, 0 );
599 /* At this stage, the window is openned, displayed, and ready to receive
604 /*******************************************************************************
605 * X11DestroyWindow: destroy X11 window
606 *******************************************************************************
607 * Destroy an X11 window created by vout_X11CreateWindow
608 *******************************************************************************/
609 static void X11DestroyWindow( vout_thread_t *p_vout )
611 XUnmapWindow( p_vout->p_sys->p_display, p_vout->p_sys->window );
612 XFreeGC( p_vout->p_sys->p_display, p_vout->p_sys->gc );
613 XDestroyWindow( p_vout->p_sys->p_display, p_vout->p_sys->window );
616 /*******************************************************************************
617 * X11CreateImage: create an XImage
618 *******************************************************************************
619 * Create a simple XImage used as a buffer.
620 *******************************************************************************/
621 static int X11CreateImage( vout_thread_t *p_vout, XImage **pp_ximage )
623 byte_t * pb_data; /* image data storage zone */
624 int i_quantum; /* XImage quantum (see below) */
626 /* Allocate memory for image */
627 p_vout->i_bytes_per_line = p_vout->i_width * p_vout->i_bytes_per_pixel;
628 pb_data = (byte_t *) malloc( p_vout->i_bytes_per_line * p_vout->i_height );
629 if( !pb_data ) /* error */
631 intf_ErrMsg("error: %s\n", strerror(ENOMEM));
635 /* Optimize the quantum of a scanline regarding its size - the quantum is
636 a diviser of the number of bits between the start of two scanlines. */
637 if( !(( p_vout->i_bytes_per_line ) % 32) )
643 if( !(( p_vout->i_bytes_per_line ) % 16) )
654 *pp_ximage = XCreateImage( p_vout->p_sys->p_display,
655 DefaultVisual(p_vout->p_sys->p_display, p_vout->p_sys->i_screen),
656 p_vout->i_screen_depth, ZPixmap, 0, pb_data,
657 p_vout->i_width, p_vout->i_height, i_quantum, 0);
658 if(! *pp_ximage ) /* error */
660 intf_ErrMsg( "error: XCreateImage() failed\n" );
668 /*******************************************************************************
669 * X11CreateShmImage: create an XImage using shared memory extension
670 *******************************************************************************
671 * Prepare an XImage for DisplayX11ShmImage function.
672 * The order of the operations respects the recommandations of the mit-shm
673 * document by J.Corbet and K.Packard. Most of the parameters were copied from
675 *******************************************************************************/
676 static int X11CreateShmImage( vout_thread_t *p_vout, XImage **pp_ximage,
677 XShmSegmentInfo *p_shm_info)
680 *pp_ximage = XShmCreateImage( p_vout->p_sys->p_display,
681 DefaultVisual(p_vout->p_sys->p_display, p_vout->p_sys->i_screen),
682 p_vout->i_screen_depth, ZPixmap, 0,
683 p_shm_info, p_vout->i_width, p_vout->i_height );
684 if(! *pp_ximage ) /* error */
686 intf_ErrMsg("error: XShmCreateImage() failed\n");
690 /* Allocate shared memory segment - 0777 set the access permission
691 * rights (like umask), they are not yet supported by X servers */
692 p_shm_info->shmid = shmget( IPC_PRIVATE,
693 (*pp_ximage)->bytes_per_line * (*pp_ximage)->height,
695 if( p_shm_info->shmid < 0) /* error */
697 intf_ErrMsg("error: can't allocate shared image data (%s)\n",
699 XDestroyImage( *pp_ximage );
703 /* Attach shared memory segment to process (read/write) */
704 p_shm_info->shmaddr = (*pp_ximage)->data = shmat(p_shm_info->shmid, 0, 0);
705 if(! p_shm_info->shmaddr )
707 intf_ErrMsg("error: can't attach shared memory (%s)\n",
709 shmctl( p_shm_info->shmid, IPC_RMID, 0 ); /* free shared memory */
710 XDestroyImage( *pp_ximage );
714 /* Mark the shm segment to be removed when there will be no more
715 * attachements, so it is automatic on process exit or after shmdt */
716 shmctl( p_shm_info->shmid, IPC_RMID, 0 );
718 /* Attach shared memory segment to X server (read only) */
719 p_shm_info->readOnly = True;
720 if( XShmAttach( p_vout->p_sys->p_display, p_shm_info ) == False ) /* error */
722 intf_ErrMsg("error: can't attach shared memory to X11 server\n");
723 shmdt( p_shm_info->shmaddr ); /* detach shared memory from process
724 * and automatic free */
725 XDestroyImage( *pp_ximage );
729 /* Send image to X server. This instruction is required, since having
730 * built a Shm XImage and not using it causes an error on XCloseDisplay */
731 XFlush( p_vout->p_sys->p_display );
735 /*******************************************************************************
736 * X11DestroyImage: destroy an XImage
737 *******************************************************************************
738 * Destroy XImage AND associated data. If pointer is NULL, the image won't be
739 * destroyed (see vout_X11ManageOutputMethod())
740 *******************************************************************************/
741 static void X11DestroyImage( XImage *p_ximage )
743 if( p_ximage != NULL )
745 XDestroyImage( p_ximage ); /* no free() required */
749 /*******************************************************************************
751 *******************************************************************************
752 * Destroy XImage AND associated data. Detach shared memory segment from
753 * server and process, then free it. If pointer is NULL, the image won't be
754 * destroyed (see vout_X11ManageOutputMethod())
755 *******************************************************************************/
756 static void X11DestroyShmImage( vout_thread_t *p_vout, XImage *p_ximage,
757 XShmSegmentInfo *p_shm_info )
759 /* If pointer is NULL, do nothing */
760 if( p_ximage == NULL )
765 XShmDetach( p_vout->p_sys->p_display, p_shm_info ); /* detach from server */
766 XDestroyImage( p_ximage );
767 if( shmdt( p_shm_info->shmaddr ) ) /* detach shared memory from process */
768 { /* also automatic freeing... */
769 intf_ErrMsg("error: can't detach shared memory (%s)\n",