. nouveaux plugins - ne fonctionnent pas encore tous
[vlc.git] / plugins / ggi / vout_ggi.c
1 /*****************************************************************************
2  * vout_ggi.c: GGI video output display method
3  *****************************************************************************
4  * Copyright (C) 1998, 1999, 2000 VideoLAN
5  *
6  * Authors:
7  *
8  * This program is free software; you can redistribute it and/or modify
9  * it under the terms of the GNU General Public License as published by
10  * the Free Software Foundation; either version 2 of the License, or
11  * (at your option) any later version.
12  * 
13  * This program is distributed in the hope that it will be useful,
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16  * GNU General Public License for more details.
17  *
18  * You should have received a copy of the GNU General Public License
19  * along with this program; if not, write to the Free Software
20  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111, USA.
21  *****************************************************************************/
22
23 /*****************************************************************************
24  * Preamble
25  *****************************************************************************/
26 #include "defs.h"
27
28 #include <errno.h>                                                 /* ENOMEM */
29 #include <stdlib.h>                                                /* free() */
30 #include <string.h>                                            /* strerror() */
31
32 #include <ggi/ggi.h>
33
34 #include "config.h"
35 #include "common.h"
36 #include "threads.h"
37 #include "mtime.h"
38 #include "plugins.h"
39
40 #include "video.h"
41 #include "video_output.h"
42
43 #include "intf_msg.h"
44
45 /*****************************************************************************
46  * vout_sys_t: video output GGI method descriptor
47  *****************************************************************************
48  * This structure is part of the video output thread descriptor.
49  * It describes the GGI specific properties of an output thread.
50  *****************************************************************************/
51 typedef struct vout_sys_s
52 {
53     /* GGI system informations */
54     ggi_visual_t        p_display;                         /* display device */
55
56     /* Buffers informations */
57     ggi_directbuffer *  p_buffer[2];                              /* buffers */
58     boolean_t           b_must_acquire;   /* must be acquired before writing */
59 } vout_sys_t;
60
61 /*****************************************************************************
62  * Local prototypes
63  *****************************************************************************/
64 static int     GGIOpenDisplay   ( vout_thread_t *p_vout, char *psz_display, void *p_data );
65 static void    GGICloseDisplay  ( vout_thread_t *p_vout );
66
67 /*****************************************************************************
68  * vout_SysCreate: allocate GGI video thread output method
69  *****************************************************************************
70  * This function allocate and initialize a GGI vout method. It uses some of the
71  * vout properties to choose the correct mode, and change them according to the
72  * mode actually used.
73  *****************************************************************************/
74 int vout_SysCreate( vout_thread_t *p_vout, char *psz_display, int i_root_window, void *p_data )
75 {
76     /* Allocate structure */
77     p_vout->p_sys = malloc( sizeof( vout_sys_t ) );
78     if( p_vout->p_sys == NULL )
79     {
80         intf_ErrMsg("error: %s\n", strerror(ENOMEM) );
81         return( 1 );
82     }
83
84     /* Open and initialize device */
85     if( GGIOpenDisplay( p_vout, psz_display, p_data ) )
86     {
87         intf_ErrMsg("error: can't initialize GGI display\n");
88         free( p_vout->p_sys );
89         return( 1 );
90     }
91     return( 0 );
92 }
93
94 /*****************************************************************************
95  * vout_SysInit: initialize GGI video thread output method
96  *****************************************************************************
97  * This function initialize the GGI display device.
98  *****************************************************************************/
99 int vout_SysInit( vout_thread_t *p_vout )
100 {
101     /* Acquire first buffer */
102     if( p_vout->p_sys->b_must_acquire )
103     {
104         ggiResourceAcquire( p_vout->p_sys->p_buffer[ p_vout->i_buffer_index ]->resource, GGI_ACTYPE_WRITE );
105     }
106
107     return( 0 );
108 }
109
110 /*****************************************************************************
111  * vout_SysEnd: terminate Sys video thread output method
112  *****************************************************************************
113  * Terminate an output method created by vout_SysCreate
114  *****************************************************************************/
115 void vout_SysEnd( vout_thread_t *p_vout )
116 {
117     /* Release buffer */
118     if( p_vout->p_sys->b_must_acquire )
119     {
120         ggiResourceRelease( p_vout->p_sys->p_buffer[ p_vout->i_buffer_index ]->resource );
121     }
122 }
123
124 /*****************************************************************************
125  * vout_SysDestroy: destroy Sys video thread output method
126  *****************************************************************************
127  * Terminate an output method created by vout_SysCreate
128  *****************************************************************************/
129 void vout_SysDestroy( vout_thread_t *p_vout )
130 {
131     GGICloseDisplay( p_vout );
132     free( p_vout->p_sys );
133 }
134
135 /*****************************************************************************
136  * vout_SysManage: handle Sys events
137  *****************************************************************************
138  * This function should be called regularly by video output thread. It returns
139  * a non null value if an error occured.
140  *****************************************************************************/
141 int vout_SysManage( vout_thread_t *p_vout )
142 {
143     /* FIXME: 8bpp: change palette ?? */
144     return( 0 );
145 }
146
147 /*****************************************************************************
148  * vout_SysDisplay: displays previously rendered output
149  *****************************************************************************
150  * This function send the currently rendered image to the display, wait until
151  * it is displayed and switch the two rendering buffer, preparing next frame.
152  *****************************************************************************/
153 void vout_SysDisplay( vout_thread_t *p_vout )
154 {
155     /* Change display frame */
156     if( p_vout->p_sys->b_must_acquire )
157     {
158         ggiResourceRelease( p_vout->p_sys->p_buffer[ p_vout->i_buffer_index ]->resource );
159     }
160     ggiFlush( p_vout->p_sys->p_display ); /* XXX?? */
161     ggiSetDisplayFrame( p_vout->p_sys->p_display,
162                         p_vout->p_sys->p_buffer[ p_vout->i_buffer_index ]->frame );
163
164     /* Swap buffers and change write frame */
165     if( p_vout->p_sys->b_must_acquire )
166     {
167         ggiResourceAcquire( p_vout->p_sys->p_buffer[ (p_vout->i_buffer_index + 1) & 1]->resource,
168                             GGI_ACTYPE_WRITE );
169     }
170     ggiSetWriteFrame( p_vout->p_sys->p_display,
171                       p_vout->p_sys->p_buffer[ (p_vout->i_buffer_index + 1) & 1]->frame );
172 }
173
174 /* following functions are local */
175
176 /*****************************************************************************
177  * GGIOpenDisplay: open and initialize GGI device
178  *****************************************************************************
179  * Open and initialize display according to preferences specified in the vout
180  * thread fields.
181  *****************************************************************************/
182 static int GGIOpenDisplay( vout_thread_t *p_vout, char *psz_display, void *p_data )
183 {
184     ggi_mode    mode;                                     /* mode descriptor */
185     ggi_color   col_fg;                                  /* foreground color */
186     ggi_color   col_bg;                                  /* background color */
187     int         i_index;                               /* all purposes index */
188
189     /* Initialize library */
190     if( ggiInit() )
191     {
192         intf_ErrMsg("error: can't initialize GGI library\n");
193         return( 1 );
194     }
195
196     /* Open display */
197     p_vout->p_sys->p_display = ggiOpen( psz_display, NULL );
198     if( p_vout->p_sys->p_display == NULL )
199     {
200         intf_ErrMsg("error: can't open GGI default display\n");
201         ggiExit();
202         return( 1 );
203     }
204
205     /* give the data back to the interface */
206     fprintf(stderr, "display is %i\n", p_vout->p_sys->p_display);
207     *(ggi_visual_t *)p_data = p_vout->p_sys->p_display;
208
209     /* Find most appropriate mode */
210     mode.frames =       2;                                      /* 2 buffers */
211     mode.visible.x =    p_vout->i_width;                    /* minimum width */
212     mode.visible.y =    p_vout->i_height;                  /* minimum height */
213     mode.virt.x =       GGI_AUTO;
214     mode.virt.y =       GGI_AUTO;
215     mode.size.x =       GGI_AUTO;
216     mode.size.y =       GGI_AUTO;
217     mode.graphtype =    GT_15BIT;             /* minimum usable screen depth */
218     mode.dpp.x =        GGI_AUTO;
219     mode.dpp.y =        GGI_AUTO;
220     ggiCheckMode( p_vout->p_sys->p_display, &mode );
221
222     /* Check that returned mode has some minimum properties */
223     /* XXX?? */
224
225     /* Set mode */
226     if( ggiSetMode( p_vout->p_sys->p_display, &mode ) )
227     {
228         intf_ErrMsg("error: can't set GGI mode\n");
229         ggiClose( p_vout->p_sys->p_display );
230         ggiExit();
231         return( 1 );
232     }
233
234     /* Check buffers properties */
235     p_vout->p_sys->b_must_acquire = 0;
236     for( i_index = 0; i_index < 2; i_index++ )
237     {
238         /* Get buffer address */
239         p_vout->p_sys->p_buffer[ i_index ] =
240             ggiDBGetBuffer( p_vout->p_sys->p_display, i_index );
241         if( p_vout->p_sys->p_buffer[ i_index ] == NULL )
242         {
243             intf_ErrMsg("error: double buffering is not possible\n");
244             ggiClose( p_vout->p_sys->p_display );
245             ggiExit();
246             return( 1 );
247         }
248
249         /* Check buffer properties */
250         if( ! (p_vout->p_sys->p_buffer[ i_index ]->type & GGI_DB_SIMPLE_PLB) ||
251             (p_vout->p_sys->p_buffer[ i_index ]->page_size != 0) ||
252             (p_vout->p_sys->p_buffer[ i_index ]->write == NULL ) ||
253             (p_vout->p_sys->p_buffer[ i_index ]->noaccess != 0) ||
254             (p_vout->p_sys->p_buffer[ i_index ]->align != 0) )
255         {
256             intf_ErrMsg("error: incorrect video memory type\n");
257             ggiClose( p_vout->p_sys->p_display );
258             ggiExit();
259             return( 1 );
260         }
261
262         /* Check if buffer needs to be acquired before write */
263         if( ggiResourceMustAcquire( p_vout->p_sys->p_buffer[ i_index ]->resource ) )
264         {
265             p_vout->p_sys->b_must_acquire = 1;
266         }
267     }
268 #ifdef DEBUG
269     if( p_vout->p_sys->b_must_acquire )
270     {
271         intf_DbgMsg("buffers must be acquired\n");
272     }
273 #endif
274
275     /* Set graphic context colors */
276     col_fg.r = col_fg.g = col_fg.b = -1;
277     col_bg.r = col_bg.g = col_bg.b = 0;
278     if( ggiSetGCForeground(p_vout->p_sys->p_display,
279                            ggiMapColor(p_vout->p_sys->p_display,&col_fg)) ||
280         ggiSetGCBackground(p_vout->p_sys->p_display,
281                            ggiMapColor(p_vout->p_sys->p_display,&col_bg)) )
282     {
283         intf_ErrMsg("error: can't set colors\n");
284         ggiClose( p_vout->p_sys->p_display );
285         ggiExit();
286         return( 1 );
287     }
288
289     /* Set clipping for text */
290     if( ggiSetGCClipping(p_vout->p_sys->p_display, 0, 0,
291                          mode.visible.x, mode.visible.y ) )
292     {
293         intf_ErrMsg("error: can't set clipping\n");
294         ggiClose( p_vout->p_sys->p_display );
295         ggiExit();
296         return( 1 );
297     }
298
299     /* Set thread information */
300     p_vout->i_width =           mode.visible.x;
301     p_vout->i_height =          mode.visible.y;
302     p_vout->i_bytes_per_line =  p_vout->p_sys->p_buffer[ 0 ]->buffer.plb.stride;
303     p_vout->i_screen_depth =    p_vout->p_sys->p_buffer[ 0 ]->buffer.plb.pixelformat->depth;
304     p_vout->i_bytes_per_pixel = p_vout->p_sys->p_buffer[ 0 ]->buffer.plb.pixelformat->size / 8;
305     p_vout->i_red_mask =        p_vout->p_sys->p_buffer[ 0 ]->buffer.plb.pixelformat->red_mask;
306     p_vout->i_green_mask =      p_vout->p_sys->p_buffer[ 0 ]->buffer.plb.pixelformat->green_mask;
307     p_vout->i_blue_mask =       p_vout->p_sys->p_buffer[ 0 ]->buffer.plb.pixelformat->blue_mask;
308     /* FIXME: palette in 8bpp ?? */
309
310     /* Set and initialize buffers */
311     vout_SetBuffers( p_vout, p_vout->p_sys->p_buffer[ 0 ]->write, p_vout->p_sys->p_buffer[ 1 ]->write );
312
313     return( 0 );
314 }
315
316 /*****************************************************************************
317  * GGICloseDisplay: close and reset GGI device
318  *****************************************************************************
319  * This function returns all resources allocated by GGIOpenDisplay and restore
320  * the original state of the device.
321  *****************************************************************************/
322 static void GGICloseDisplay( vout_thread_t *p_vout )
323 {
324     /* Restore original mode and close display */
325     ggiClose( p_vout->p_sys->p_display );
326
327     /* Exit library */
328     ggiExit();
329 }
330