]> git.sesse.net Git - vlc/blob - plugins/glide/vout_glide.c
* Ported Glide and MGA plugins to the new module API. MGA never worked,
[vlc] / plugins / glide / vout_glide.c
1 /*****************************************************************************
2  * vout_glide.c: 3dfx video output display method for 3dfx cards
3  *****************************************************************************
4  * Copyright (C) 2000, 2001 VideoLAN
5  *
6  * Authors: Samuel Hocevar <sam@zoy.org>
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 #define MODULE_NAME glide
24 #include "modules_inner.h"
25
26 /*****************************************************************************
27  * Preamble
28  *****************************************************************************/
29 #include "defs.h"
30
31 #include <errno.h>                                                 /* ENOMEM */
32 #include <stdlib.h>                                                /* free() */
33 #include <string.h>                                            /* strerror() */
34
35 #ifndef __linux__
36 #include <conio.h>                                            /* for glide ? */
37 #endif
38 #include <glide.h>
39 #include <linutil.h>                            /* Glide kbhit() and getch() */
40
41 #include "config.h"
42 #include "common.h"
43 #include "threads.h"
44 #include "mtime.h"
45 #include "tests.h"
46 #include "modules.h"
47
48 #include "video.h"
49 #include "video_output.h"
50
51 #include "intf_msg.h"
52 #include "interface.h"
53
54 #include "main.h"
55
56 #define GLIDE_WIDTH 800
57 #define GLIDE_HEIGHT 600
58 #define GLIDE_BITS_PER_PLANE 16
59 #define GLIDE_BYTES_PER_PIXEL 2
60
61 /*****************************************************************************
62  * vout_sys_t: Glide video output method descriptor
63  *****************************************************************************
64  * This structure is part of the video output thread descriptor.
65  * It describes the Glide specific properties of an output thread.
66  *****************************************************************************/
67 typedef struct vout_sys_s
68 {
69     GrLfbInfo_t                 p_buffer_info;           /* back buffer info */
70
71     /* Dummy video memory */
72     byte_t *                    p_video;                      /* base adress */
73     size_t                      i_page_size;                    /* page size */
74
75 } vout_sys_t;
76
77 /*****************************************************************************
78  * Local prototypes.
79  *****************************************************************************/
80 static int  vout_Probe     ( probedata_t *p_data );
81 static int  vout_Create    ( struct vout_thread_s * );
82 static int  vout_Init      ( struct vout_thread_s * );
83 static void vout_End       ( struct vout_thread_s * );
84 static void vout_Destroy   ( struct vout_thread_s * );
85 static int  vout_Manage    ( struct vout_thread_s * );
86 static void vout_Display   ( struct vout_thread_s * );
87
88 static int  GlideOpenDisplay   ( vout_thread_t *p_vout );
89 static void GlideCloseDisplay  ( vout_thread_t *p_vout );
90
91 /*****************************************************************************
92  * Functions exported as capabilities. They are declared as static so that
93  * we don't pollute the namespace too much.
94  *****************************************************************************/
95 void _M( vout_getfunctions )( function_list_t * p_function_list )
96 {
97     p_function_list->pf_probe = vout_Probe;
98     p_function_list->functions.vout.pf_create     = vout_Create;
99     p_function_list->functions.vout.pf_init       = vout_Init;
100     p_function_list->functions.vout.pf_end        = vout_End;
101     p_function_list->functions.vout.pf_destroy    = vout_Destroy;
102     p_function_list->functions.vout.pf_manage     = vout_Manage;
103     p_function_list->functions.vout.pf_display    = vout_Display;
104     p_function_list->functions.vout.pf_setpalette = NULL;
105 }
106
107 /*****************************************************************************
108  * vout_Probe: probe the video driver and return a score
109  *****************************************************************************
110  * This function tries to initialize SDL and returns a score to the
111  * plugin manager so that it can select the best plugin.
112  *****************************************************************************/
113 static int vout_Probe( probedata_t *p_data )
114 {
115     if( TestMethod( VOUT_METHOD_VAR, "glide" ) )
116     {
117         return( 999 );
118     }
119
120     /* We could do a grSstQueryBoards( GrHwConfiguration *hwConfig ) at
121      * this point, but if the user didn't configure his 3dfx card, we
122      * have great chances to segfault here. So we'd better assume
123      * everything is fine and worry only if we really need to use Glide */
124     return( 20 );
125 }
126
127 /*****************************************************************************
128  * vout_Create: allocates Glide video thread output method
129  *****************************************************************************
130  * This function allocates and initializes a Glide vout method.
131  *****************************************************************************/
132 int vout_Create( vout_thread_t *p_vout )
133 {
134     /* Allocate structure */
135     p_vout->p_sys = malloc( sizeof( vout_sys_t ) );
136     if( p_vout->p_sys == NULL )
137     {
138         intf_ErrMsg("error: %s", strerror(ENOMEM) );
139         return( 1 );
140     }
141
142     /* Open and initialize device */
143     if( GlideOpenDisplay( p_vout ) )
144     {
145         intf_ErrMsg("vout error: can't open display");
146         free( p_vout->p_sys );
147         return( 1 );
148     }
149
150     return( 0 );
151 }
152
153 /*****************************************************************************
154  * vout_Init: initialize Glide video thread output method
155  *****************************************************************************/
156 int vout_Init( vout_thread_t *p_vout )
157 {
158     return( 0 );
159 }
160
161 /*****************************************************************************
162  * vout_End: terminate Glide video thread output method
163  *****************************************************************************/
164 void vout_End( vout_thread_t *p_vout )
165 {
166     ;
167 }
168
169 /*****************************************************************************
170  * vout_Destroy: destroy Glide video thread output method
171  *****************************************************************************
172  * Terminate an output method created by vout_CreateOutputMethod
173  *****************************************************************************/
174 void vout_Destroy( vout_thread_t *p_vout )
175 {
176     GlideCloseDisplay( p_vout );
177     free( p_vout->p_sys );
178 }
179
180 /*****************************************************************************
181  * vout_Manage: handle Glide events
182  *****************************************************************************
183  * This function should be called regularly by video output thread. It manages
184  * console events. It returns a non null value on error.
185  *****************************************************************************/
186 int vout_Manage( vout_thread_t *p_vout )
187 {
188     int buf;
189
190     /* very Linux specific - see tlib.c in Glide for other versions */
191     while( kbhit() )
192     {
193         buf = getch();
194
195         switch( (char)buf )
196         {
197         case 'q':
198             p_main->p_intf->b_die = 1;
199             break;
200
201         default:
202             break;
203         }
204     }
205
206     return 0;
207 }
208
209 /*****************************************************************************
210  * vout_Display: displays previously rendered output
211  *****************************************************************************
212  * This function send the currently rendered image to Glide image, waits until
213  * it is displayed and switch the two rendering buffers, preparing next frame.
214  *****************************************************************************/
215 void vout_Display( vout_thread_t *p_vout )
216 {
217     grLfbUnlock( GR_LFB_WRITE_ONLY, GR_BUFFER_BACKBUFFER );
218
219     grBufferSwap( 0 );
220
221     if ( grLfbLock(GR_LFB_WRITE_ONLY, GR_BUFFER_BACKBUFFER,
222                    GR_LFBWRITEMODE_565, GR_ORIGIN_UPPER_LEFT, FXFALSE,
223                    &p_vout->p_sys->p_buffer_info) == FXFALSE )
224     {
225         intf_ErrMsg( "vout error: can't take 3dfx back buffer lock" );
226     }
227 }
228
229 /* following functions are local */
230
231 /*****************************************************************************
232  * GlideOpenDisplay: open and initialize 3dfx device
233  *****************************************************************************/
234
235 static int GlideOpenDisplay( vout_thread_t *p_vout )
236 {
237     static char version[80];
238     GrHwConfiguration hwconfig;
239     GrScreenResolution_t resolution = GR_RESOLUTION_800x600;
240     GrLfbInfo_t p_front_buffer_info;                    /* front buffer info */
241
242     p_vout->i_width =            GLIDE_WIDTH;
243     p_vout->i_height =           GLIDE_HEIGHT;
244     p_vout->i_screen_depth =     GLIDE_BITS_PER_PLANE;
245     p_vout->i_bytes_per_pixel =  GLIDE_BYTES_PER_PIXEL;
246     /* bytes per line value overriden later */
247     p_vout->i_bytes_per_line =   1024 * GLIDE_BYTES_PER_PIXEL;
248
249     p_vout->p_sys->i_page_size = GLIDE_WIDTH * GLIDE_HEIGHT
250                                   * GLIDE_BYTES_PER_PIXEL;
251
252     p_vout->i_red_mask =   0xf800;
253     p_vout->i_green_mask = 0x07e0;
254     p_vout->i_blue_mask =  0x001f;
255
256     /* Map two framebuffers a the very beginning of the fb */
257     p_vout->p_sys->p_video = malloc( p_vout->p_sys->i_page_size * 2 );
258     if( (int)p_vout->p_sys->p_video == -1 )
259     {
260         intf_ErrMsg( "vout error: can't map video memory (%s)",
261                      strerror(errno) );
262         return( 1 );
263     }
264
265     grGlideGetVersion( version );
266     grGlideInit();
267
268     if( !grSstQueryHardware(&hwconfig) )
269     {
270         intf_ErrMsg( "vout error: can't get 3dfx hardware config" );
271         return( 1 );
272     }
273
274     grSstSelect( 0 );
275     if( !grSstWinOpen(0, resolution, GR_REFRESH_60Hz,
276                         GR_COLORFORMAT_ABGR, GR_ORIGIN_UPPER_LEFT, 2, 1) )
277     {
278         intf_ErrMsg( "vout error: can't open 3dfx screen" );
279         return( 1 );
280     }
281
282     /* disable dithering */
283     //grDitherMode( GR_DITHER_DISABLE );
284
285     /* clear both buffers */
286     grRenderBuffer( GR_BUFFER_BACKBUFFER );
287     grBufferClear( 0, 0, 0 );
288     grRenderBuffer( GR_BUFFER_FRONTBUFFER );
289     grBufferClear( 0, 0, 0 );
290     grRenderBuffer( GR_BUFFER_BACKBUFFER );
291
292     p_vout->p_sys->p_buffer_info.size = sizeof( GrLfbInfo_t );
293     p_front_buffer_info.size          = sizeof( GrLfbInfo_t );
294
295     /* lock the buffers to find their adresses */
296     if ( grLfbLock(GR_LFB_WRITE_ONLY, GR_BUFFER_FRONTBUFFER,
297                    GR_LFBWRITEMODE_565, GR_ORIGIN_UPPER_LEFT, FXFALSE,
298                    &p_front_buffer_info) == FXFALSE )
299     {
300         intf_ErrMsg( "vout error: can't take 3dfx front buffer lock" );
301         grGlideShutdown();
302         return( 1 );
303     }
304     grLfbUnlock( GR_LFB_WRITE_ONLY, GR_BUFFER_FRONTBUFFER );
305
306     if ( grLfbLock(GR_LFB_WRITE_ONLY, GR_BUFFER_BACKBUFFER,
307                    GR_LFBWRITEMODE_565, GR_ORIGIN_UPPER_LEFT, FXFALSE,
308                    &p_vout->p_sys->p_buffer_info) == FXFALSE )
309     {
310         intf_ErrMsg( "vout error: can't take 3dfx back buffer lock" );
311         grGlideShutdown();
312         return( 1 );
313     }
314     grLfbUnlock(GR_LFB_WRITE_ONLY, GR_BUFFER_BACKBUFFER );
315     
316     /* Get the number of bytes per line */
317     p_vout->i_bytes_per_line = p_vout->p_sys->p_buffer_info.strideInBytes;
318
319     grBufferClear( 0, 0, 0 );
320
321     /* Set and initialize buffers */
322     vout_SetBuffers( p_vout, p_vout->p_sys->p_buffer_info.lfbPtr,
323                      p_front_buffer_info.lfbPtr );
324
325     return( 0 );
326 }
327
328 /*****************************************************************************
329  * GlideCloseDisplay: close and reset 3dfx device
330  *****************************************************************************
331  * Returns all resources allocated by GlideOpenDisplay and restore the original
332  * state of the device.
333  *****************************************************************************/
334 static void GlideCloseDisplay( vout_thread_t *p_vout )
335 {
336     /* unlock the hidden buffer */
337     grLfbUnlock( GR_LFB_WRITE_ONLY, GR_BUFFER_BACKBUFFER );
338
339     /* shutdown Glide */
340     grGlideShutdown();
341     free( p_vout->p_sys->p_video );
342 }
343