]> git.sesse.net Git - vlc/blob - src/video_output/video_ggi.c
Nettoyage, ajout du gamma, pr�paration de la yuv walken.
[vlc] / src / video_output / video_ggi.c
1 /*******************************************************************************
2  * vout_ggi.c: GGI video output display method
3  * (c)1998 VideoLAN
4  *******************************************************************************/
5
6 /*******************************************************************************
7  * Preamble
8  *******************************************************************************/
9 #include <errno.h>
10 #include <stdlib.h>
11 #include <string.h>
12 #include <ggi/ggi.h>
13
14 #include "config.h"
15 #include "common.h"
16 #include "mtime.h"
17 #include "vlc_thread.h"
18
19 #include "video.h"
20 #include "video_output.h"
21 #include "video_sys.h"
22 #include "intf_msg.h"
23
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
31
32     /* GGI system informations */
33     ggi_visual_t        p_display;                           /* display device */
34
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 */    
39
40     /* Characters size */
41     int                 i_char_width;
42     int                 i_char_height;    
43 } vout_sys_t;
44
45 /*******************************************************************************
46  * Local prototypes
47  *******************************************************************************/
48 static int     GGIOpenDisplay   ( vout_thread_t *p_vout );
49 static void    GGICloseDisplay  ( vout_thread_t *p_vout );
50
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 
56  * mode actually used.
57  *******************************************************************************/
58 int vout_SysCreate( vout_thread_t *p_vout )
59 {    
60     /* Allocate structure */
61     p_vout->p_sys = malloc( sizeof( vout_sys_t ) );    
62     if( p_vout->p_sys == NULL )
63     {
64         intf_ErrMsg("error: %s\n", strerror(ENOMEM) );
65         return( 1 );
66     }
67
68     /* Open and initialize device */
69     if( GGIOpenDisplay( p_vout ) )
70     {
71         intf_ErrMsg("error: can't initialize GGI display\n");        
72         free( p_vout->p_sys );
73         return( 1 );        
74     }
75     
76     return( 0 );
77 }
78
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 )
85 {
86     /* Acquire first buffer */
87     p_vout->p_sys->i_buffer_index = 0;
88     if( p_vout->p_sys->b_must_acquire )
89     {
90         ggiResourceAcquire( p_vout->p_sys->p_buffer[ 0 ]->resource, GGI_ACTYPE_WRITE );        
91     }    
92
93     return( 0 );
94 }
95
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 )
102 {
103     /* Release buffer */
104     if( p_vout->p_sys->b_must_acquire )
105     {
106         ggiResourceRelease( p_vout->p_sys->p_buffer[ p_vout->p_sys->i_buffer_index ]->resource );
107     }
108 }
109
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 )
116 {
117     GGICloseDisplay( p_vout );
118     free( p_vout->p_sys );
119 }
120
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 )
130 {
131     //??
132
133     return( 0 );
134 }
135
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 )
143 {
144     /* Change display frame */
145     if( p_vout->p_sys->b_must_acquire )
146     {            
147         ggiResourceRelease( p_vout->p_sys->p_buffer[ p_vout->p_sys->i_buffer_index ]->resource );
148     }    
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 );      
152         
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 )
156     {            
157         ggiResourceAcquire( p_vout->p_sys->p_buffer[ p_vout->p_sys->i_buffer_index ]->resource, 
158                             GGI_ACTYPE_WRITE );
159     } 
160     ggiSetWriteFrame( p_vout->p_sys->p_display,
161                       p_vout->p_sys->p_buffer[ p_vout->p_sys->i_buffer_index ]->frame );    
162  }
163
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 )
170 {    
171     return( p_vout->p_sys->p_buffer[ p_vout->p_sys->i_buffer_index ]->write );        
172 }
173
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 )
182 {
183     /* Update upper left coordinates according to alignment */
184     switch( i_halign )
185     {
186     case 0:                                                        /* centered */
187         i_x -= p_vout->p_sys->i_char_width * strlen( psz_text ) / 2;
188         break;        
189     case 1:                                                   /* right aligned */
190         i_x -= p_vout->p_sys->i_char_width * strlen( psz_text );
191         break;                
192     }
193     switch( i_valign )
194     {
195     case 0:                                                        /* centered */
196         i_y -= p_vout->p_sys->i_char_height / 2;
197         break;        
198     case 1:                                                   /* bottom aligned */
199         i_y -= p_vout->p_sys->i_char_height;
200         break;                
201     }
202
203     /* Print text */
204     ggiPuts( p_vout->p_sys->p_display, i_x, i_y, psz_text );
205 }
206
207 /* following functions are local */
208
209 /*******************************************************************************
210  * GGIOpenDisplay: open and initialize GGI device 
211  *******************************************************************************
212  * Open and initialize display according to preferences specified in the vout
213  * thread fields.
214  *******************************************************************************/
215 static int GGIOpenDisplay( vout_thread_t *p_vout )
216 {
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 */    
221     
222     /* Initialize library */
223     if( ggiInit() )
224     {
225         intf_ErrMsg("error: can't initialize GGI library\n");
226         return( 1 );        
227     }
228
229     /* Open display */
230     p_vout->p_sys->p_display = ggiOpen( NULL );
231     if( p_vout->p_sys->p_display == NULL )
232     {
233         intf_ErrMsg("error: can't open GGI default display\n");
234         ggiExit();
235         return( 1 );        
236     }
237     
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 );
250
251     /* Check that returned mode has some minimum properties */
252     //??
253     
254     /* Set mode */
255     if( ggiSetMode( p_vout->p_sys->p_display, &mode ) )
256     {
257         intf_ErrMsg("error: can't set GGI mode\n");
258         ggiClose( p_vout->p_sys->p_display );        
259         ggiExit();
260         return( 1 );        
261     }            
262
263     /* Check buffers properties */
264     p_vout->p_sys->b_must_acquire = 0;    
265     for( i_index = 0; i_index < 2; i_index++ )
266     {
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 )
271         {
272             intf_ErrMsg("error: double buffering is not possible\n");
273             ggiClose( p_vout->p_sys->p_display );        
274             ggiExit();
275             return( 1 );            
276         }        
277         
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) )
284         {
285             intf_ErrMsg("error: incorrect video memory type\n");
286             ggiClose( p_vout->p_sys->p_display );        
287             ggiExit();
288             return( 1 ); 
289         } 
290
291         /* Check if buffer needs to be acquired before write */
292         if( ggiResourceMustAcquire( p_vout->p_sys->p_buffer[ i_index ]->resource ) )
293         {
294             p_vout->p_sys->b_must_acquire = 1;            
295         }            
296     } 
297 #ifdef DEBUG
298     if( p_vout->p_sys->b_must_acquire )
299     {
300         intf_DbgMsg("buffers must be acquired\n");        
301     }    
302 #endif
303
304     /* Get font size */
305     if( ggiGetCharSize( p_vout->p_sys->p_display, &p_vout->p_sys->i_char_width,
306                         &p_vout->p_sys->i_char_height ) )
307     {
308         intf_ErrMsg("error: can't get font size\n");
309         ggiClose( p_vout->p_sys->p_display );        
310         ggiExit();
311         return( 1 );   
312     }
313
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)) )
321     {
322         intf_ErrMsg("error: can't set colors\n");
323         ggiClose( p_vout->p_sys->p_display );        
324         ggiExit();
325         return( 1 );  
326     }    
327
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 )
333     {
334     case GT_15BIT:
335         p_vout->i_screen_depth =        15;
336         p_vout->i_bytes_per_pixel =     2;
337         break;        
338     case GT_16BIT:
339         p_vout->i_screen_depth =        16;
340         p_vout->i_bytes_per_pixel =     2;
341         break;        
342     case GT_24BIT:
343         p_vout->i_screen_depth =        24;
344         p_vout->i_bytes_per_pixel =     3;
345         break;        
346     case GT_32BIT:
347         p_vout->i_screen_depth =        32;
348         p_vout->i_bytes_per_pixel =     4;
349        break;        
350     default:
351         intf_ErrMsg("error: unsupported screen depth\n");        
352         ggiClose( p_vout->p_sys->p_display );
353         ggiExit();        
354         return( 1 );        
355         break;        
356     }
357
358     return( 0 );    
359 }
360
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 )
368 {
369     // Restore original mode and close display
370     ggiClose( p_vout->p_sys->p_display );    
371
372     // Exit library
373     ggiExit();    
374 }
375