]> git.sesse.net Git - vlc/blob - plugins/glide/glide.c
* ./include/modules_inner.h: replaced _X with __VLC_SYMBOL because _X was
[vlc] / plugins / glide / glide.c
1 /*****************************************************************************
2  * glide.c : 3dfx Glide plugin for vlc
3  *****************************************************************************
4  * Copyright (C) 2000, 2001 VideoLAN
5  * $Id: glide.c,v 1.11 2002/01/09 02:01:14 sam Exp $
6  *
7  * Authors: Samuel Hocevar <sam@zoy.org>
8  *
9  * This program is free software; you can redistribute it and/or modify
10  * it under the terms of the GNU General Public License as published by
11  * the Free Software Foundation; either version 2 of the License, or
12  * (at your option) any later version.
13  * 
14  * This program is distributed in the hope that it will be useful,
15  * but WITHOUT ANY WARRANTY; without even the implied warranty of
16  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17  * GNU General Public License for more details.
18  *
19  * You should have received a copy of the GNU General Public License
20  * along with this program; if not, write to the Free Software
21  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111, USA.
22  *****************************************************************************/
23
24 /*****************************************************************************
25  * Preamble
26  *****************************************************************************/
27 #include <errno.h>                                                 /* ENOMEM */
28 #include <stdlib.h>                                      /* malloc(), free() */
29 #include <string.h>
30
31 #ifndef __linux__
32 #   include <conio.h>                                         /* for glide ? */
33 #endif
34 #include <glide.h>
35 #include <linutil.h>                            /* Glide kbhit() and getch() */
36
37 #include <videolan/vlc.h>
38
39 #include "video.h"
40 #include "video_output.h"
41
42 #include "interface.h"
43
44 #define GLIDE_WIDTH 800
45 #define GLIDE_HEIGHT 600
46 #define GLIDE_BITS_PER_PLANE 16
47 #define GLIDE_BYTES_PER_PIXEL 2
48
49 /*****************************************************************************
50  * Local prototypes.
51  *****************************************************************************/
52 static void vout_getfunctions( function_list_t * p_function_list );
53
54 static int  vout_Probe     ( probedata_t *p_data );
55 static int  vout_Create    ( vout_thread_t * );
56 static int  vout_Init      ( vout_thread_t * );
57 static void vout_End       ( vout_thread_t * );
58 static void vout_Destroy   ( vout_thread_t * );
59 static int  vout_Manage    ( vout_thread_t * );
60 static void vout_Render    ( vout_thread_t *, picture_t * );
61 static void vout_Display   ( vout_thread_t *, picture_t * );
62
63 static int  OpenDisplay    ( vout_thread_t * );
64 static void CloseDisplay   ( vout_thread_t * );
65
66 /*****************************************************************************
67  * Building configuration tree
68  *****************************************************************************/
69 MODULE_CONFIG_START
70 MODULE_CONFIG_STOP
71
72 MODULE_INIT_START
73     SET_DESCRIPTION( "3dfx Glide module" )
74     ADD_CAPABILITY( VOUT, 20 )
75     ADD_SHORTCUT( "glide" )
76     ADD_SHORTCUT( "3dfx" )
77 MODULE_INIT_STOP
78
79 MODULE_ACTIVATE_START
80     vout_getfunctions( &p_module->p_functions->vout );
81 MODULE_ACTIVATE_STOP
82
83 MODULE_DEACTIVATE_START
84 MODULE_DEACTIVATE_STOP
85
86 /*****************************************************************************
87  * vout_sys_t: Glide video output method descriptor
88  *****************************************************************************
89  * This structure is part of the video output thread descriptor.
90  * It describes the Glide specific properties of an output thread.
91  *****************************************************************************/
92 typedef struct vout_sys_s
93 {
94     GrLfbInfo_t                 p_buffer_info;           /* back buffer info */
95
96     u8* pp_buffer[2];
97     int i_index;
98
99 } vout_sys_t;
100
101 /*****************************************************************************
102  * Functions exported as capabilities. They are declared as static so that
103  * we don't pollute the namespace too much.
104  *****************************************************************************/
105 void _M( vout_getfunctions )( function_list_t * p_function_list )
106 {
107     p_function_list->pf_probe = vout_Probe;
108     p_function_list->functions.vout.pf_create     = vout_Create;
109     p_function_list->functions.vout.pf_init       = vout_Init;
110     p_function_list->functions.vout.pf_end        = vout_End;
111     p_function_list->functions.vout.pf_destroy    = vout_Destroy;
112     p_function_list->functions.vout.pf_manage     = vout_Manage;
113     p_function_list->functions.vout.pf_render     = vout_Render;
114     p_function_list->functions.vout.pf_display    = vout_Display;
115 }
116
117 /*****************************************************************************
118  * vout_Probe: probe the video driver and return a score
119  *****************************************************************************
120  * This function tries to initialize SDL and returns a score to the
121  * plugin manager so that it can select the best plugin.
122  *****************************************************************************/
123 static int vout_Probe( probedata_t *p_data )
124 {
125     /* We could do a grSstQueryBoards( GrHwConfiguration *hwConfig ) at
126      * this point, but if the user didn't configure his 3dfx card, we
127      * have great chances to segfault here. So we'd better assume
128      * everything is fine and worry only if we really need to use Glide */
129     return( 1 );
130 }
131
132 /*****************************************************************************
133  * vout_Create: allocates Glide video thread output method
134  *****************************************************************************
135  * This function allocates and initializes a Glide vout method.
136  *****************************************************************************/
137 int vout_Create( vout_thread_t *p_vout )
138 {
139     /* Allocate structure */
140     p_vout->p_sys = malloc( sizeof( vout_sys_t ) );
141     if( p_vout->p_sys == NULL )
142     {
143         intf_ErrMsg("error: %s", strerror(ENOMEM) );
144         return( 1 );
145     }
146
147     /* Open and initialize device */
148     if( OpenDisplay( p_vout ) )
149     {
150         intf_ErrMsg("vout error: can't open display");
151         free( p_vout->p_sys );
152         return( 1 );
153     }
154
155     return( 0 );
156 }
157
158 /*****************************************************************************
159  * vout_Init: initialize Glide video thread output method
160  *****************************************************************************/
161 int vout_Init( vout_thread_t *p_vout )
162 {
163     int i_index;
164     picture_t *p_pic;
165
166     I_OUTPUTPICTURES = 0;
167
168     p_pic = NULL;
169
170     /* Find an empty picture slot */
171     for( i_index = 0 ; i_index < VOUT_MAX_PICTURES ; i_index++ )
172     {
173         if( p_vout->p_picture[ i_index ].i_status == FREE_PICTURE )
174         {
175             p_pic = p_vout->p_picture + i_index;
176             break;
177         }
178     }
179
180     if( p_pic == NULL )
181     {
182         return -1;
183     }
184
185     /* We know the chroma, allocate a buffer which will be used
186      * directly by the decoder */
187     p_pic->i_planes = 1;
188
189     p_pic->p->p_pixels = p_vout->p_sys->pp_buffer[p_vout->p_sys->i_index];
190     p_pic->p->i_pixel_bytes = GLIDE_BYTES_PER_PIXEL;
191     p_pic->p->i_lines = GLIDE_HEIGHT;
192
193     p_pic->p->b_margin = 1;
194     p_pic->p->b_hidden = 1;
195     p_pic->p->i_visible_bytes = GLIDE_WIDTH * GLIDE_BYTES_PER_PIXEL;
196     p_pic->p->i_pitch = p_vout->p_sys->p_buffer_info.strideInBytes;
197                          /*1024 * GLIDE_BYTES_PER_PIXEL*/
198
199     p_pic->p->i_red_mask =   0xf800;
200     p_pic->p->i_green_mask = 0x07e0;
201     p_pic->p->i_blue_mask =  0x001f;
202
203     p_pic->i_status = DESTROYED_PICTURE;
204     p_pic->i_type   = DIRECT_PICTURE;
205
206     PP_OUTPUTPICTURE[ 0 ] = p_pic;
207
208     I_OUTPUTPICTURES = 1;
209
210     return 0;
211 }
212
213 /*****************************************************************************
214  * vout_End: terminate Glide video thread output method
215  *****************************************************************************/
216 void vout_End( vout_thread_t *p_vout )
217 {
218     ;
219 }
220
221 /*****************************************************************************
222  * vout_Destroy: destroy Glide video thread output method
223  *****************************************************************************
224  * Terminate an output method created by vout_CreateOutputMethod
225  *****************************************************************************/
226 void vout_Destroy( vout_thread_t *p_vout )
227 {
228     CloseDisplay( p_vout );
229     free( p_vout->p_sys );
230 }
231
232 /*****************************************************************************
233  * vout_Manage: handle Glide events
234  *****************************************************************************
235  * This function should be called regularly by video output thread. It manages
236  * console events. It returns a non null value on error.
237  *****************************************************************************/
238 int vout_Manage( vout_thread_t *p_vout )
239 {
240     int buf;
241
242     /* very Linux specific - see tlib.c in Glide for other versions */
243     while( kbhit() )
244     {
245         buf = getch();
246
247         switch( (char)buf )
248         {
249         case 'q':
250             p_main->p_intf->b_die = 1;
251             break;
252
253         default:
254             break;
255         }
256     }
257
258     return 0;
259 }
260
261 /*****************************************************************************
262  * vout_Render: renders previously calculated output
263  *****************************************************************************/
264 void vout_Render( vout_thread_t *p_vout, picture_t *p_pic )
265 {
266     ;
267 }
268         
269 /*****************************************************************************
270  * vout_Display: displays previously rendered output
271  *****************************************************************************/
272 void vout_Display( vout_thread_t *p_vout, picture_t *p_pic )
273
274 {
275     grLfbUnlock( GR_LFB_WRITE_ONLY, GR_BUFFER_BACKBUFFER );
276
277     grBufferSwap( 0 );
278
279     if ( grLfbLock(GR_LFB_WRITE_ONLY, GR_BUFFER_BACKBUFFER,
280                    GR_LFBWRITEMODE_565, GR_ORIGIN_UPPER_LEFT, FXFALSE,
281                    &p_vout->p_sys->p_buffer_info) == FXFALSE )
282     {
283         intf_ErrMsg( "vout error: can't take 3dfx back buffer lock" );
284     }
285 }
286
287 /* following functions are local */
288
289 /*****************************************************************************
290  * OpenDisplay: open and initialize 3dfx device
291  *****************************************************************************/
292
293 static int OpenDisplay( vout_thread_t *p_vout )
294 {
295     static char version[80];
296     GrHwConfiguration hwconfig;
297     GrScreenResolution_t resolution = GR_RESOLUTION_800x600;
298     GrLfbInfo_t p_front_buffer_info;                    /* front buffer info */
299
300     grGlideGetVersion( version );
301     grGlideInit();
302
303     if( !grSstQueryHardware(&hwconfig) )
304     {
305         intf_ErrMsg( "vout error: can't get 3dfx hardware config" );
306         return( 1 );
307     }
308
309     grSstSelect( 0 );
310     if( !grSstWinOpen( 0, resolution, GR_REFRESH_60Hz,
311                        GR_COLORFORMAT_ABGR, GR_ORIGIN_UPPER_LEFT, 2, 1 ) )
312     {
313         intf_ErrMsg( "vout error: can't open 3dfx screen" );
314         return( 1 );
315     }
316
317     /* disable dithering */
318     //grDitherMode( GR_DITHER_DISABLE );
319
320     /* clear both buffers */
321     grRenderBuffer( GR_BUFFER_BACKBUFFER );
322     grBufferClear( 0, 0, 0 );
323     grRenderBuffer( GR_BUFFER_FRONTBUFFER );
324     grBufferClear( 0, 0, 0 );
325     grRenderBuffer( GR_BUFFER_BACKBUFFER );
326
327     p_vout->p_sys->p_buffer_info.size = sizeof( GrLfbInfo_t );
328     p_front_buffer_info.size          = sizeof( GrLfbInfo_t );
329
330     /* lock the buffers to find their adresses */
331     if ( grLfbLock(GR_LFB_WRITE_ONLY, GR_BUFFER_FRONTBUFFER,
332                    GR_LFBWRITEMODE_565, GR_ORIGIN_UPPER_LEFT, FXFALSE,
333                    &p_front_buffer_info) == FXFALSE )
334     {
335         intf_ErrMsg( "vout error: can't take 3dfx front buffer lock" );
336         grGlideShutdown();
337         return( 1 );
338     }
339     grLfbUnlock( GR_LFB_WRITE_ONLY, GR_BUFFER_FRONTBUFFER );
340
341     if ( grLfbLock(GR_LFB_WRITE_ONLY, GR_BUFFER_BACKBUFFER,
342                    GR_LFBWRITEMODE_565, GR_ORIGIN_UPPER_LEFT, FXFALSE,
343                    &p_vout->p_sys->p_buffer_info) == FXFALSE )
344     {
345         intf_ErrMsg( "vout error: can't take 3dfx back buffer lock" );
346         grGlideShutdown();
347         return( 1 );
348     }
349     grLfbUnlock( GR_LFB_WRITE_ONLY, GR_BUFFER_BACKBUFFER );
350     
351     grBufferClear( 0, 0, 0 );
352
353     p_vout->p_sys->pp_buffer[0] = p_vout->p_sys->p_buffer_info.lfbPtr;
354     p_vout->p_sys->pp_buffer[1] = p_front_buffer_info.lfbPtr;
355     p_vout->p_sys->i_index = 0;
356
357     return( 0 );
358 }
359
360 /*****************************************************************************
361  * CloseDisplay: close and reset 3dfx device
362  *****************************************************************************
363  * Returns all resources allocated by OpenDisplay and restore the original
364  * state of the device.
365  *****************************************************************************/
366 static void CloseDisplay( vout_thread_t *p_vout )
367 {
368     /* unlock the hidden buffer */
369     grLfbUnlock( GR_LFB_WRITE_ONLY, GR_BUFFER_BACKBUFFER );
370
371     /* shutdown Glide */
372     grGlideShutdown();
373 }
374