]> git.sesse.net Git - vlc/blob - plugins/ggi/vout_ggi.c
e3cdd9fff3aa857fb0f02195c35723347d9094da
[vlc] / 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     *(ggi_visual_t *)p_data = p_vout->p_sys->p_display;
207
208     /* Find most appropriate mode */
209     mode.frames =       2;                                      /* 2 buffers */
210     mode.visible.x =    p_vout->i_width;                    /* minimum width */
211     mode.visible.y =    p_vout->i_height;                  /* minimum height */
212     mode.virt.x =       GGI_AUTO;
213     mode.virt.y =       GGI_AUTO;
214     mode.size.x =       GGI_AUTO;
215     mode.size.y =       GGI_AUTO;
216     mode.graphtype =    GT_15BIT;             /* minimum usable screen depth */
217     mode.dpp.x =        GGI_AUTO;
218     mode.dpp.y =        GGI_AUTO;
219     ggiCheckMode( p_vout->p_sys->p_display, &mode );
220
221     /* Check that returned mode has some minimum properties */
222     /* XXX?? */
223
224     /* Set mode */
225     if( ggiSetMode( p_vout->p_sys->p_display, &mode ) )
226     {
227         intf_ErrMsg("error: can't set GGI mode\n");
228         ggiClose( p_vout->p_sys->p_display );
229         ggiExit();
230         return( 1 );
231     }
232
233     /* Check buffers properties */
234     p_vout->p_sys->b_must_acquire = 0;
235     for( i_index = 0; i_index < 2; i_index++ )
236     {
237         /* Get buffer address */
238         p_vout->p_sys->p_buffer[ i_index ] =
239             (ggi_directbuffer *)ggiDBGetBuffer( p_vout->p_sys->p_display, i_index );
240         if( p_vout->p_sys->p_buffer[ i_index ] == NULL )
241         {
242             intf_ErrMsg("error: double buffering is not possible\n");
243             ggiClose( p_vout->p_sys->p_display );
244             ggiExit();
245             return( 1 );
246         }
247
248         /* Check buffer properties */
249         if( ! (p_vout->p_sys->p_buffer[ i_index ]->type & GGI_DB_SIMPLE_PLB) ||
250             (p_vout->p_sys->p_buffer[ i_index ]->page_size != 0) ||
251             (p_vout->p_sys->p_buffer[ i_index ]->write == NULL ) ||
252             (p_vout->p_sys->p_buffer[ i_index ]->noaccess != 0) ||
253             (p_vout->p_sys->p_buffer[ i_index ]->align != 0) )
254         {
255             intf_ErrMsg("error: incorrect video memory type\n");
256             ggiClose( p_vout->p_sys->p_display );
257             ggiExit();
258             return( 1 );
259         }
260
261         /* Check if buffer needs to be acquired before write */
262         if( ggiResourceMustAcquire( p_vout->p_sys->p_buffer[ i_index ]->resource ) )
263         {
264             p_vout->p_sys->b_must_acquire = 1;
265         }
266     }
267 #ifdef DEBUG
268     if( p_vout->p_sys->b_must_acquire )
269     {
270         intf_DbgMsg("buffers must be acquired\n");
271     }
272 #endif
273
274     /* Set graphic context colors */
275     col_fg.r = col_fg.g = col_fg.b = -1;
276     col_bg.r = col_bg.g = col_bg.b = 0;
277     if( ggiSetGCForeground(p_vout->p_sys->p_display,
278                            ggiMapColor(p_vout->p_sys->p_display,&col_fg)) ||
279         ggiSetGCBackground(p_vout->p_sys->p_display,
280                            ggiMapColor(p_vout->p_sys->p_display,&col_bg)) )
281     {
282         intf_ErrMsg("error: can't set colors\n");
283         ggiClose( p_vout->p_sys->p_display );
284         ggiExit();
285         return( 1 );
286     }
287
288     /* Set clipping for text */
289     if( ggiSetGCClipping(p_vout->p_sys->p_display, 0, 0,
290                          mode.visible.x, mode.visible.y ) )
291     {
292         intf_ErrMsg("error: can't set clipping\n");
293         ggiClose( p_vout->p_sys->p_display );
294         ggiExit();
295         return( 1 );
296     }
297
298     /* Set thread information */
299     p_vout->i_width =           mode.visible.x;
300     p_vout->i_height =          mode.visible.y;
301     p_vout->i_bytes_per_line =  p_vout->p_sys->p_buffer[ 0 ]->buffer.plb.stride;
302     p_vout->i_screen_depth =    p_vout->p_sys->p_buffer[ 0 ]->buffer.plb.pixelformat->depth;
303     p_vout->i_bytes_per_pixel = p_vout->p_sys->p_buffer[ 0 ]->buffer.plb.pixelformat->size / 8;
304     p_vout->i_red_mask =        p_vout->p_sys->p_buffer[ 0 ]->buffer.plb.pixelformat->red_mask;
305     p_vout->i_green_mask =      p_vout->p_sys->p_buffer[ 0 ]->buffer.plb.pixelformat->green_mask;
306     p_vout->i_blue_mask =       p_vout->p_sys->p_buffer[ 0 ]->buffer.plb.pixelformat->blue_mask;
307     /* FIXME: palette in 8bpp ?? */
308
309     /* Set and initialize buffers */
310     vout_SetBuffers( p_vout, p_vout->p_sys->p_buffer[ 0 ]->write, p_vout->p_sys->p_buffer[ 1 ]->write );
311
312     return( 0 );
313 }
314
315 /*****************************************************************************
316  * GGICloseDisplay: close and reset GGI device
317  *****************************************************************************
318  * This function returns all resources allocated by GGIOpenDisplay and restore
319  * the original state of the device.
320  *****************************************************************************/
321 static void GGICloseDisplay( vout_thread_t *p_vout )
322 {
323     /* Restore original mode and close display */
324     ggiClose( p_vout->p_sys->p_display );
325
326     /* Exit library */
327     ggiExit();
328 }
329