1 /*
2 Copyright (C) 1997-2001 Id Software, Inc.
3
4 This program is free software; you can redistribute it and/or
5 modify it under the terms of the GNU General Public License
6 as published by the Free Software Foundation; either version 2
7 of the License, or (at your option) any later version.
8
9 This program is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
12
13 See the GNU General Public License for more details.
14
15 You should have received a copy of the GNU General Public License
16 along with this program; if not, write to the Free Software
17 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
18
19 */
20
21 // Main windowed and fullscreen graphics interface module. This module
22 // is used for both the software and OpenGL rendering versions of the
23 // Quake refresh engine.
24
25
26 #include "client.h"
27 #include "vid_public.h"
28
29 // Structure containing functions exported from refresh DLL
30 refAPI_t ref;
31
32 // Console variables that we need to access from this module
33 cvar_t *vid_ref; // Name of Refresh DLL loaded
34 cvar_t *vid_autorestart;
35
36 #ifdef REF_HARD_LINKED
37 qboolean Ref_APISetupCallback( api_type_t type, void *api );
38 #else
39 // Global variables used internally by this module
40 static void *reflib_library; // Handle to refresh DLL
41 #endif
42
43 /*
44 ==========================================================================
45
46 LOADING / SHUTDOWN
47
48 ==========================================================================
49 */
50
51 /*
52 ==============
53 CL_FreeRefresh
54 ==============
55 */
CL_FreeRefresh(void)56 static void CL_FreeRefresh( void ) {
57 #ifndef REF_HARD_LINKED
58 Sys_FreeModule( reflib_library );
59 reflib_library = NULL;
60 #endif
61 memset( &ref, 0, sizeof( ref ) );
62 cls.ref_initialized = qfalse;
63 }
64
65 #ifndef REF_HARD_LINKED
66
67 /*
68 ==============
69 CL_RefSetupCallback
70 ==============
71 */
CL_RefSetupCallback(api_type_t type,void * api)72 static qboolean CL_RefSetupCallback( api_type_t type, void *api ) {
73 switch( type ) {
74 case API_CMD:
75 Cmd_FillAPI( ( cmdAPI_t * )api );
76 break;
77 case API_CVAR:
78 Cvar_FillAPI( ( cvarAPI_t * )api );
79 break;
80 case API_FS:
81 FS_FillAPI( ( fsAPI_t * )api );
82 break;
83 case API_COMMON:
84 Com_FillAPI( ( commonAPI_t * )api );
85 break;
86 case API_SYSTEM:
87 Sys_FillAPI( ( sysAPI_t * )api );
88 break;
89 case API_VIDEO_SOFTWARE:
90 Video_FillSWAPI( ( vidSWAPI_t * )api );
91 break;
92 #ifndef _WIN32_WCE
93 case API_VIDEO_OPENGL:
94 Video_FillGLAPI( ( vidGLAPI_t * )api );
95 break;
96 #endif
97 default:
98 Com_Error( ERR_FATAL, "CL_RefSetupCallback: bad api type" );
99 }
100
101 return qtrue;
102 }
103
104 #endif
105
106 /*
107 ==============
108 CL_LoadRefresh
109 ==============
110 */
CL_LoadRefresh(const char * name)111 static qboolean CL_LoadRefresh( const char *name ) {
112 #ifndef REF_HARD_LINKED
113 moduleEntry_t entry;
114 moduleInfo_t info;
115 moduleCapability_t caps;
116 APISetupCallback_t callback;
117 #endif
118
119 if( cls.ref_initialized ) {
120 ref.Shutdown( qtrue );
121 CL_FreeRefresh();
122 }
123
124 Com_Printf( "------- Loading %s -------\n", name );
125
126 #ifdef REF_HARD_LINKED
127 #ifdef SOFTWARE_RENDERER
128 Video_FillSWAPI( &video );
129 #else
130 Video_FillGLAPI( &video );
131 #endif
132
133 Ref_APISetupCallback( API_REFRESH, &ref );
134 #else
135
136 if( ( entry = Sys_LoadModule( name, &reflib_library ) ) == NULL ) {
137 Com_WPrintf( "Couldn't load %s\n", name );
138 return qfalse;
139 }
140
141 entry( MQ_GETINFO, &info );
142 if( info.api_version != MODULES_APIVERSION ) {
143 Com_WPrintf( "%s has incompatible api_version: %i, should be %i\n",
144 name, info.api_version, MODULES_APIVERSION );
145 goto fail;
146 }
147
148 caps = ( moduleCapability_t )entry( MQ_GETCAPS, NULL );
149 if( !( caps & MCP_REFRESH ) ) {
150 Com_WPrintf( "%s doesn't have REFRESH capability\n", name );
151 goto fail;
152 }
153
154 callback = ( APISetupCallback_t )entry( MQ_SETUPAPI, ( void * )CL_RefSetupCallback );
155 if( !callback ) {
156 Com_WPrintf( "%s returned NULL callback\n", name );
157 goto fail;
158 }
159
160 callback( API_REFRESH, &ref );
161 #endif
162
163 cls.ref_initialized = qtrue;
164 if( !ref.Init( qtrue ) ) {
165 goto fail;
166 }
167
168 Com_Printf( "------------------------------------\n" );
169
170 return qtrue;
171
172 fail:
173 CL_FreeRefresh();
174 return qfalse;
175 }
176
177 /*
178 ============
179 CL_PumpEvents
180 ============
181 */
CL_PumpEvents(void)182 void CL_PumpEvents( void ) {
183 if( !cls.ref_initialized ) {
184 return;
185 }
186
187 Video_PumpEvents();
188
189 if( cvar_latchedModified & ( 1 << CVAR_SYSTEM_VIDEO ) ) {
190 if( vid_autorestart->integer ) {
191 Cbuf_AddText( "vid_restart\n" );
192 }
193 cvar_latchedModified &= ~( 1 << CVAR_SYSTEM_VIDEO );
194 }
195
196 }
197
198 #if( defined REF_HARD_LINKED ) && ( defined OPENGL_RENDERER )
199 #define DEFAULT_REFRESH_DRIVER "newgl"
200 #else
201 #define DEFAULT_REFRESH_DRIVER "soft"
202 #endif
203
204 /*
205 ============
206 CL_InitRefresh
207 ============
208 */
CL_InitRefresh(void)209 void CL_InitRefresh( void ) {
210 if( cls.ref_initialized ) {
211 return;
212 }
213
214 /* Create the video variables so we know how to start the graphics drivers */
215 vid_autorestart = Cvar_Get( "vid_autorestart", "0", 0 );
216
217 #ifdef REF_HARD_LINKED
218 vid_ref = Cvar_Get( "vid_ref", DEFAULT_REFRESH_DRIVER, CVAR_ROM );
219 if( !CL_LoadRefresh( "ref_" DEFAULT_REFRESH_DRIVER ) ) {
220 Com_Error( ERR_FATAL, "Couldn't load built-in video driver!" );
221 }
222 #else
223 vid_ref = Cvar_Get( "vid_ref", DEFAULT_REFRESH_DRIVER, CVAR_ARCHIVE|CVAR_LATCHED );
224 vid_ref->subsystem = CVAR_SYSTEM_VIDEO;
225
226 /* Start the graphics mode and load refresh DLL */
227 while( 1 ) {
228 char buffer[MAX_QPATH];
229
230 if( !strcmp( vid_ref->string, "gl" ) ) {
231 /* Temporary hack until I port ref_gl to the new refresh API */
232 strcpy( buffer, "ref_newgl" );
233 } else {
234 Com_sprintf( buffer, sizeof( buffer ), "ref_%s", vid_ref->string );
235 }
236 if( CL_LoadRefresh( buffer ) ) {
237 break;
238 }
239
240 if( !strcmp( vid_ref->string, DEFAULT_REFRESH_DRIVER ) ) {
241 Com_Error( ERR_FATAL, "Couldn't fall back to %s driver!", buffer );
242 }
243
244 Com_Printf( "Falling back to default...\n" );
245 Cvar_Set( "vid_ref", DEFAULT_REFRESH_DRIVER );
246 }
247 #endif
248
249 cvar_latchedModified &= ~( 1 << CVAR_SYSTEM_VIDEO );
250
251 }
252
253 /*
254 ============
255 CL_ShutdownRefresh
256 ============
257 */
CL_ShutdownRefresh(void)258 void CL_ShutdownRefresh( void ) {
259 if( !cls.ref_initialized ) {
260 return;
261 }
262
263 ref.Shutdown( qtrue );
264 CL_FreeRefresh();
265
266 Z_LeakTest( TAG_RENDERER );
267 }
268
269
270
271