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