1 /*******************************************************************************
2 * vout_ggi.c: GGI video output display method
4 *******************************************************************************/
6 /*******************************************************************************
8 *******************************************************************************/
17 #include "vlc_thread.h"
20 #include "video_output.h"
21 #include "video_sys.h"
24 /*******************************************************************************
25 * vout_sys_t: video output GGI method descriptor
26 *******************************************************************************
27 * This structure is part of the video output thread descriptor.
28 * It describes the GGI specific properties of an output thread.
29 *******************************************************************************/
30 typedef struct vout_sys_s
32 /* GGI system informations */
33 ggi_visual_t p_display; /* display device */
35 /* Buffers informations */
36 int i_buffer_index; /* buffer index */
37 ggi_directbuffer * p_buffer[2]; /* buffers */
38 boolean_t b_must_acquire; /* must be acquired before writing */
45 /*******************************************************************************
47 *******************************************************************************/
48 static int GGIOpenDisplay ( vout_thread_t *p_vout );
49 static void GGICloseDisplay ( vout_thread_t *p_vout );
51 /*******************************************************************************
52 * vout_SysCreate: allocate GGI video thread output method
53 *******************************************************************************
54 * This function allocate and initialize a GGI vout method. It uses some of the
55 * vout properties to choose the correct mode, and change them according to the
57 *******************************************************************************/
58 int vout_SysCreate( vout_thread_t *p_vout )
60 /* Allocate structure */
61 p_vout->p_sys = malloc( sizeof( vout_sys_t ) );
62 if( p_vout->p_sys == NULL )
64 intf_ErrMsg("error: %s\n", strerror(ENOMEM) );
68 /* Open and initialize device */
69 if( GGIOpenDisplay( p_vout ) )
71 intf_ErrMsg("error: can't initialize GGI display\n");
72 free( p_vout->p_sys );
79 /*******************************************************************************
80 * vout_SysInit: initialize GGI video thread output method
81 *******************************************************************************
82 * This function initialize the GGI display device.
83 *******************************************************************************/
84 int vout_SysInit( vout_thread_t *p_vout )
86 /* Acquire first buffer */
87 p_vout->p_sys->i_buffer_index = 0;
88 if( p_vout->p_sys->b_must_acquire )
90 ggiResourceAcquire( p_vout->p_sys->p_buffer[ 0 ]->resource, GGI_ACTYPE_WRITE );
96 /*******************************************************************************
97 * vout_SysEnd: terminate Sys video thread output method
98 *******************************************************************************
99 * Terminate an output method created by vout_SysCreateOutputMethod
100 *******************************************************************************/
101 void vout_SysEnd( vout_thread_t *p_vout )
104 if( p_vout->p_sys->b_must_acquire )
106 ggiResourceRelease( p_vout->p_sys->p_buffer[ p_vout->p_sys->i_buffer_index ]->resource );
110 /*******************************************************************************
111 * vout_SysDestroy: destroy Sys video thread output method
112 *******************************************************************************
113 * Terminate an output method created by vout_SysCreateOutputMethod
114 *******************************************************************************/
115 void vout_SysDestroy( vout_thread_t *p_vout )
117 GGICloseDisplay( p_vout );
118 free( p_vout->p_sys );
121 /*******************************************************************************
122 * vout_SysManage: handle Sys events
123 *******************************************************************************
124 * This function should be called regularly by video output thread. It returns
125 * a negative value if something happened which does not allow the thread to
126 * continue, and a positive one if the thread can go on, but the images have
127 * been modified and therefore it is useless to display them.
128 *******************************************************************************/
129 int vout_SysManage( vout_thread_t *p_vout )
136 /*******************************************************************************
137 * vout_SysDisplay: displays previously rendered output
138 *******************************************************************************
139 * This function send the currently rendered image to the display, wait until
140 * it is displayed and switch the two rendering buffer, preparing next frame.
141 *******************************************************************************/
142 void vout_SysDisplay( vout_thread_t *p_vout )
144 /* Change display frame */
145 if( p_vout->p_sys->b_must_acquire )
147 ggiResourceRelease( p_vout->p_sys->p_buffer[ p_vout->p_sys->i_buffer_index ]->resource );
149 ggiFlush( p_vout->p_sys->p_display ); // ??
150 ggiSetDisplayFrame( p_vout->p_sys->p_display,
151 p_vout->p_sys->p_buffer[ p_vout->p_sys->i_buffer_index ]->frame );
153 /* Swap buffers and change write frame */
154 p_vout->p_sys->i_buffer_index = ++p_vout->p_sys->i_buffer_index & 1;
155 if( p_vout->p_sys->b_must_acquire )
157 ggiResourceAcquire( p_vout->p_sys->p_buffer[ p_vout->p_sys->i_buffer_index ]->resource,
160 ggiSetWriteFrame( p_vout->p_sys->p_display,
161 p_vout->p_sys->p_buffer[ p_vout->p_sys->i_buffer_index ]->frame );
164 /*******************************************************************************
165 * vout_SysGetPicture: get current display buffer informations
166 *******************************************************************************
167 * This function returns the address of the current display buffer.
168 *******************************************************************************/
169 void * vout_SysGetPicture( vout_thread_t *p_vout )
171 return( p_vout->p_sys->p_buffer[ p_vout->p_sys->i_buffer_index ]->write );
174 /*******************************************************************************
175 * vout_SysPrint: print simple text on a picture
176 *******************************************************************************
177 * This function will print a simple text on the picture. It is designed to
178 * print debugging or general informations, not to render subtitles.
179 *******************************************************************************/
180 void vout_SysPrint( vout_thread_t *p_vout, int i_x, int i_y, int i_halign,
181 int i_valign, unsigned char *psz_text )
183 /* Update upper left coordinates according to alignment */
186 case 0: /* centered */
187 i_x -= p_vout->p_sys->i_char_width * strlen( psz_text ) / 2;
189 case 1: /* right aligned */
190 i_x -= p_vout->p_sys->i_char_width * strlen( psz_text );
195 case 0: /* centered */
196 i_y -= p_vout->p_sys->i_char_height / 2;
198 case 1: /* bottom aligned */
199 i_y -= p_vout->p_sys->i_char_height;
204 ggiPuts( p_vout->p_sys->p_display, i_x, i_y, psz_text );
207 /* following functions are local */
209 /*******************************************************************************
210 * GGIOpenDisplay: open and initialize GGI device
211 *******************************************************************************
212 * Open and initialize display according to preferences specified in the vout
214 *******************************************************************************/
215 static int GGIOpenDisplay( vout_thread_t *p_vout )
217 ggi_mode mode; /* mode descriptor */
218 ggi_color col_fg; /* foreground color */
219 ggi_color col_bg; /* background color */
220 int i_index; /* all purposes index */
222 /* Initialize library */
225 intf_ErrMsg("error: can't initialize GGI library\n");
230 p_vout->p_sys->p_display = ggiOpen( NULL );
231 if( p_vout->p_sys->p_display == NULL )
233 intf_ErrMsg("error: can't open GGI default display\n");
238 /* Find most appropriate mode */
239 mode.frames = 2; /* 2 buffers */
240 mode.visible.x = p_vout->i_width; /* minimum width */
241 mode.visible.y = p_vout->i_height; /* minimum height */
242 mode.virt.x = GGI_AUTO;
243 mode.virt.y = GGI_AUTO;
244 mode.size.x = GGI_AUTO;
245 mode.size.y = GGI_AUTO;
246 mode.graphtype = GT_15BIT; /* minimum usable screen depth */
247 mode.dpp.x = GGI_AUTO;
248 mode.dpp.y = GGI_AUTO;
249 ggiCheckMode( p_vout->p_sys->p_display, &mode );
251 /* Check that returned mode has some minimum properties */
255 if( ggiSetMode( p_vout->p_sys->p_display, &mode ) )
257 intf_ErrMsg("error: can't set GGI mode\n");
258 ggiClose( p_vout->p_sys->p_display );
263 /* Check buffers properties */
264 p_vout->p_sys->b_must_acquire = 0;
265 for( i_index = 0; i_index < 2; i_index++ )
267 /* Get buffer address */
268 p_vout->p_sys->p_buffer[ i_index ] =
269 ggiDBGetBuffer( p_vout->p_sys->p_display, i_index );
270 if( p_vout->p_sys->p_buffer[ i_index ] == NULL )
272 intf_ErrMsg("error: double buffering is not possible\n");
273 ggiClose( p_vout->p_sys->p_display );
278 /* Check buffer properties */
279 if( ! (p_vout->p_sys->p_buffer[ i_index ]->type & GGI_DB_SIMPLE_PLB) ||
280 (p_vout->p_sys->p_buffer[ i_index ]->page_size != 0) ||
281 (p_vout->p_sys->p_buffer[ i_index ]->write == NULL ) ||
282 (p_vout->p_sys->p_buffer[ i_index ]->noaccess != 0) ||
283 (p_vout->p_sys->p_buffer[ i_index ]->align != 0) )
285 intf_ErrMsg("error: incorrect video memory type\n");
286 ggiClose( p_vout->p_sys->p_display );
291 /* Check if buffer needs to be acquired before write */
292 if( ggiResourceMustAcquire( p_vout->p_sys->p_buffer[ i_index ]->resource ) )
294 p_vout->p_sys->b_must_acquire = 1;
298 if( p_vout->p_sys->b_must_acquire )
300 intf_DbgMsg("buffers must be acquired\n");
305 if( ggiGetCharSize( p_vout->p_sys->p_display, &p_vout->p_sys->i_char_width,
306 &p_vout->p_sys->i_char_height ) )
308 intf_ErrMsg("error: can't get font size\n");
309 ggiClose( p_vout->p_sys->p_display );
314 /* Set graphic context colors */
315 col_fg.r = col_fg.g = col_fg.b = -1;
316 col_bg.r = col_bg.g = col_bg.b = 0;
317 if( ggiSetGCForeground(p_vout->p_sys->p_display,
318 ggiMapColor(p_vout->p_sys->p_display,&col_fg)) ||
319 ggiSetGCBackground(p_vout->p_sys->p_display,
320 ggiMapColor(p_vout->p_sys->p_display,&col_bg)) )
322 intf_ErrMsg("error: can't set colors\n");
323 ggiClose( p_vout->p_sys->p_display );
328 /* Set thread information */
329 p_vout->i_width = mode.visible.x;
330 p_vout->i_height = mode.visible.y;
331 p_vout->i_bytes_per_line = p_vout->p_sys->p_buffer[ 0 ]->buffer.plb.stride;
332 switch( mode.graphtype )
335 p_vout->i_screen_depth = 15;
336 p_vout->i_bytes_per_pixel = 2;
339 p_vout->i_screen_depth = 16;
340 p_vout->i_bytes_per_pixel = 2;
343 p_vout->i_screen_depth = 24;
344 p_vout->i_bytes_per_pixel = 3;
347 p_vout->i_screen_depth = 32;
348 p_vout->i_bytes_per_pixel = 4;
351 intf_ErrMsg("error: unsupported screen depth\n");
352 ggiClose( p_vout->p_sys->p_display );
361 /*******************************************************************************
362 * GGICloseDisplay: close and reset GGI device
363 *******************************************************************************
364 * This function returns all resources allocated by GGIOpenDisplay and restore
365 * the original state of the device.
366 *******************************************************************************/
367 static void GGICloseDisplay( vout_thread_t *p_vout )
369 // Restore original mode and close display
370 ggiClose( p_vout->p_sys->p_display );