~ubuntu-branches/ubuntu/precise/openarena/precise

« back to all changes in this revision

Viewing changes to code/sdl/sdl_glimp.c

  • Committer: Bazaar Package Importer
  • Author(s): Ansgar Burchardt
  • Date: 2008-09-05 21:14:51 UTC
  • mfrom: (1.2.1 upstream) (2.1.5 intrepid)
  • Revision ID: james.westby@ubuntu.com-20080905211451-243bmbl6l6gdav7l
* Remove non-free code/tools/lcc (Closes: #496346)
  + Remove hunk from patch 10_fix_build_and_binary_on_alpha
  + debian/rules: Add BUILD_GAME_QVM=0 to $(MAKE) call
    (thanks to Peter De Wachter)
* Remove code/libs containing binary libraries for Mac OS X and Win32
* debian/copyright: Explain which parts of upstream's sources were removed
* debian/rules: replace ${source:Upstream-Version} by 0.7.7
  because the variable also contains the `+dfsg1' part
* Add -fsigned-char to compiler options (Closes: #487970)
  (thanks to Peter De Wachter)
* Add myself to Uploaders
* debian/control: Remove article from beginning of short description,
  don't start short description with a capital letter
* debian/openarena.6: Escape minus signs
  + fixes lintian warnings: hyphen-used-as-minus-sign

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
===========================================================================
 
3
Copyright (C) 1999-2005 Id Software, Inc.
 
4
 
 
5
This file is part of Quake III Arena source code.
 
6
 
 
7
Quake III Arena source code is free software; you can redistribute it
 
8
and/or modify it under the terms of the GNU General Public License as
 
9
published by the Free Software Foundation; either version 2 of the License,
 
10
or (at your option) any later version.
 
11
 
 
12
Quake III Arena source code is distributed in the hope that it will be
 
13
useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
 
14
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 
15
GNU General Public License for more details.
 
16
 
 
17
You should have received a copy of the GNU General Public License
 
18
along with Quake III Arena source code; if not, write to the Free Software
 
19
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
 
20
===========================================================================
 
21
*/
 
22
 
 
23
#ifdef USE_LOCAL_HEADERS
 
24
#       include "SDL.h"
 
25
#else
 
26
#       include <SDL.h>
 
27
#endif
 
28
 
 
29
#if !SDL_VERSION_ATLEAST(1, 2, 10)
 
30
#define SDL_GL_ACCELERATED_VISUAL 15
 
31
#define SDL_GL_SWAP_CONTROL 16
 
32
#elif MINSDL_PATCH >= 10
 
33
#error Code block no longer necessary, please remove
 
34
#endif
 
35
 
 
36
#ifdef SMP
 
37
#       ifdef USE_LOCAL_HEADERS
 
38
#               include "SDL_thread.h"
 
39
#       else
 
40
#               include <SDL_thread.h>
 
41
#       endif
 
42
#endif
 
43
 
 
44
#include <stdarg.h>
 
45
#include <stdio.h>
 
46
#include <stdlib.h>
 
47
#include <math.h>
 
48
 
 
49
#include "../renderer/tr_local.h"
 
50
#include "../client/client.h"
 
51
#include "../sys/sys_local.h"
 
52
#include "sdl_icon.h"
 
53
 
 
54
/* Just hack it for now. */
 
55
#ifdef MACOS_X
 
56
#include <OpenGL/OpenGL.h>
 
57
typedef CGLContextObj QGLContext;
 
58
#define GLimp_GetCurrentContext() CGLGetCurrentContext()
 
59
#define GLimp_SetCurrentContext(ctx) CGLSetCurrentContext(ctx)
 
60
#else
 
61
typedef void *QGLContext;
 
62
#define GLimp_GetCurrentContext() (NULL)
 
63
#define GLimp_SetCurrentContext(ctx)
 
64
#endif
 
65
 
 
66
static QGLContext opengl_context;
 
67
 
 
68
typedef enum
 
69
{
 
70
        RSERR_OK,
 
71
 
 
72
        RSERR_INVALID_FULLSCREEN,
 
73
        RSERR_INVALID_MODE,
 
74
 
 
75
        RSERR_UNKNOWN
 
76
} rserr_t;
 
77
 
 
78
static SDL_Surface *screen = NULL;
 
79
 
 
80
cvar_t *r_allowSoftwareGL; // Don't abort out if a hardware visual can't be obtained
 
81
 
 
82
void (APIENTRYP qglActiveTextureARB) (GLenum texture);
 
83
void (APIENTRYP qglClientActiveTextureARB) (GLenum texture);
 
84
void (APIENTRYP qglMultiTexCoord2fARB) (GLenum target, GLfloat s, GLfloat t);
 
85
 
 
86
void (APIENTRYP qglLockArraysEXT) (GLint first, GLsizei count);
 
87
void (APIENTRYP qglUnlockArraysEXT) (void);
 
88
 
 
89
/*
 
90
===============
 
91
GLimp_Shutdown
 
92
===============
 
93
*/
 
94
void GLimp_Shutdown( void )
 
95
{
 
96
        IN_Shutdown();
 
97
 
 
98
        SDL_QuitSubSystem( SDL_INIT_VIDEO );
 
99
        screen = NULL;
 
100
 
 
101
        Com_Memset( &glConfig, 0, sizeof( glConfig ) );
 
102
        Com_Memset( &glState, 0, sizeof( glState ) );
 
103
}
 
104
 
 
105
/*
 
106
===============
 
107
GLimp_LogComment
 
108
===============
 
109
*/
 
110
void GLimp_LogComment( char *comment )
 
111
{
 
112
}
 
113
 
 
114
/*
 
115
===============
 
116
GLimp_CompareModes
 
117
===============
 
118
*/
 
119
static int GLimp_CompareModes( const void *a, const void *b )
 
120
{
 
121
        const float ASPECT_EPSILON = 0.001f;
 
122
        SDL_Rect *modeA = *(SDL_Rect **)a;
 
123
        SDL_Rect *modeB = *(SDL_Rect **)b;
 
124
        float aspectDiffA = fabs( ( (float)modeA->w / (float)modeA->h ) - displayAspect );
 
125
        float aspectDiffB = fabs( ( (float)modeB->w / (float)modeB->h ) - displayAspect );
 
126
        float aspectDiffsDiff = aspectDiffA - aspectDiffB;
 
127
 
 
128
        if( aspectDiffsDiff > ASPECT_EPSILON )
 
129
                return 1;
 
130
        else if( aspectDiffsDiff < -ASPECT_EPSILON )
 
131
                return -1;
 
132
        else
 
133
        {
 
134
                if( modeA->w == modeB->w )
 
135
                        return modeA->h - modeB->h;
 
136
                else
 
137
                        return modeA->w - modeB->w;
 
138
        }
 
139
}
 
140
 
 
141
/*
 
142
===============
 
143
GLimp_DetectAvailableModes
 
144
===============
 
145
*/
 
146
static void GLimp_DetectAvailableModes(void)
 
147
{
 
148
        char buf[ MAX_STRING_CHARS ] = { 0 };
 
149
        SDL_Rect **modes;
 
150
        int numModes;
 
151
        int i;
 
152
 
 
153
        modes = SDL_ListModes( NULL, SDL_OPENGL | SDL_FULLSCREEN );
 
154
 
 
155
        if( !modes )
 
156
        {
 
157
                ri.Printf( PRINT_WARNING, "Can't get list of available modes\n" );
 
158
                return;
 
159
        }
 
160
 
 
161
        if( modes == (SDL_Rect **)-1 )
 
162
        {
 
163
                ri.Printf( PRINT_ALL, "Display supports any resolution\n" );
 
164
                return; // can set any resolution
 
165
        }
 
166
 
 
167
        for( numModes = 0; modes[ numModes ]; numModes++ );
 
168
 
 
169
        if(numModes > 1)
 
170
                qsort( modes+1, numModes-1, sizeof( SDL_Rect* ), GLimp_CompareModes );
 
171
 
 
172
        for( i = 0; i < numModes; i++ )
 
173
        {
 
174
                const char *newModeString = va( "%ux%u ", modes[ i ]->w, modes[ i ]->h );
 
175
 
 
176
                if( strlen( newModeString ) < (int)sizeof( buf ) - strlen( buf ) )
 
177
                        Q_strcat( buf, sizeof( buf ), newModeString );
 
178
                else
 
179
                        ri.Printf( PRINT_WARNING, "Skipping mode %ux%x, buffer too small\n", modes[i]->w, modes[i]->h );
 
180
        }
 
181
 
 
182
        if( *buf )
 
183
        {
 
184
                buf[ strlen( buf ) - 1 ] = 0;
 
185
                ri.Printf( PRINT_ALL, "Available modes: '%s'\n", buf );
 
186
                ri.Cvar_Set( "r_availableModes", buf );
 
187
        }
 
188
}
 
189
 
 
190
/*
 
191
===============
 
192
GLimp_SetMode
 
193
===============
 
194
*/
 
195
static int GLimp_SetMode( int mode, qboolean fullscreen )
 
196
{
 
197
        const char*   glstring;
 
198
        int sdlcolorbits;
 
199
        int colorbits, depthbits, stencilbits;
 
200
        int tcolorbits, tdepthbits, tstencilbits;
 
201
        int i = 0;
 
202
        SDL_Surface *vidscreen = NULL;
 
203
        Uint32 flags = SDL_OPENGL;
 
204
        const SDL_VideoInfo *videoInfo;
 
205
 
 
206
        ri.Printf( PRINT_ALL, "Initializing OpenGL display\n");
 
207
 
 
208
        if( displayAspect == 0.0f )
 
209
        {
 
210
#if !SDL_VERSION_ATLEAST(1, 2, 10)
 
211
                // 1.2.10 is needed to get the desktop resolution
 
212
                displayAspect = 4.0f / 3.0f;
 
213
#elif MINSDL_PATCH >= 10
 
214
#       error Ifdeffery no longer necessary, please remove
 
215
#else
 
216
                // Guess the display aspect ratio through the desktop resolution
 
217
                // by assuming (relatively safely) that it is set at or close to
 
218
                // the display's native aspect ratio
 
219
                videoInfo = SDL_GetVideoInfo( );
 
220
                displayAspect = (float)videoInfo->current_w / (float)videoInfo->current_h;
 
221
#endif
 
222
 
 
223
                ri.Printf( PRINT_ALL, "Estimated display aspect: %.3f\n", displayAspect );
 
224
        }
 
225
 
 
226
        ri.Printf (PRINT_ALL, "...setting mode %d:", mode );
 
227
 
 
228
        if ( !R_GetModeInfo( &glConfig.vidWidth, &glConfig.vidHeight, &glConfig.windowAspect, mode ) )
 
229
        {
 
230
                ri.Printf( PRINT_ALL, " invalid mode\n" );
 
231
                return RSERR_INVALID_MODE;
 
232
        }
 
233
        ri.Printf( PRINT_ALL, " %d %d\n", glConfig.vidWidth, glConfig.vidHeight);
 
234
 
 
235
        if (fullscreen)
 
236
        {
 
237
                flags |= SDL_FULLSCREEN;
 
238
                glConfig.isFullscreen = qtrue;
 
239
        }
 
240
        else
 
241
                glConfig.isFullscreen = qfalse;
 
242
 
 
243
        if (!r_colorbits->value)
 
244
                colorbits = 24;
 
245
        else
 
246
                colorbits = r_colorbits->value;
 
247
 
 
248
        if (!r_depthbits->value)
 
249
                depthbits = 24;
 
250
        else
 
251
                depthbits = r_depthbits->value;
 
252
        stencilbits = r_stencilbits->value;
 
253
 
 
254
        for (i = 0; i < 16; i++)
 
255
        {
 
256
                // 0 - default
 
257
                // 1 - minus colorbits
 
258
                // 2 - minus depthbits
 
259
                // 3 - minus stencil
 
260
                if ((i % 4) == 0 && i)
 
261
                {
 
262
                        // one pass, reduce
 
263
                        switch (i / 4)
 
264
                        {
 
265
                                case 2 :
 
266
                                        if (colorbits == 24)
 
267
                                                colorbits = 16;
 
268
                                        break;
 
269
                                case 1 :
 
270
                                        if (depthbits == 24)
 
271
                                                depthbits = 16;
 
272
                                        else if (depthbits == 16)
 
273
                                                depthbits = 8;
 
274
                                case 3 :
 
275
                                        if (stencilbits == 24)
 
276
                                                stencilbits = 16;
 
277
                                        else if (stencilbits == 16)
 
278
                                                stencilbits = 8;
 
279
                        }
 
280
                }
 
281
 
 
282
                tcolorbits = colorbits;
 
283
                tdepthbits = depthbits;
 
284
                tstencilbits = stencilbits;
 
285
 
 
286
                if ((i % 4) == 3)
 
287
                { // reduce colorbits
 
288
                        if (tcolorbits == 24)
 
289
                                tcolorbits = 16;
 
290
                }
 
291
 
 
292
                if ((i % 4) == 2)
 
293
                { // reduce depthbits
 
294
                        if (tdepthbits == 24)
 
295
                                tdepthbits = 16;
 
296
                        else if (tdepthbits == 16)
 
297
                                tdepthbits = 8;
 
298
                }
 
299
 
 
300
                if ((i % 4) == 1)
 
301
                { // reduce stencilbits
 
302
                        if (tstencilbits == 24)
 
303
                                tstencilbits = 16;
 
304
                        else if (tstencilbits == 16)
 
305
                                tstencilbits = 8;
 
306
                        else
 
307
                                tstencilbits = 0;
 
308
                }
 
309
 
 
310
                sdlcolorbits = 4;
 
311
                if (tcolorbits == 24)
 
312
                        sdlcolorbits = 8;
 
313
 
 
314
                SDL_GL_SetAttribute( SDL_GL_RED_SIZE, sdlcolorbits );
 
315
                SDL_GL_SetAttribute( SDL_GL_GREEN_SIZE, sdlcolorbits );
 
316
                SDL_GL_SetAttribute( SDL_GL_BLUE_SIZE, sdlcolorbits );
 
317
                SDL_GL_SetAttribute( SDL_GL_DEPTH_SIZE, tdepthbits );
 
318
                SDL_GL_SetAttribute( SDL_GL_STENCIL_SIZE, tstencilbits );
 
319
 
 
320
                /*Sago: We don't allow stereo view yet
 
321
                if(r_stereoEnabled->integer)
 
322
                {
 
323
                        glConfig.stereoEnabled = qtrue;
 
324
                        SDL_GL_SetAttribute(SDL_GL_STEREO, 1);
 
325
                }
 
326
                else */
 
327
                {
 
328
                        glConfig.stereoEnabled = qfalse;
 
329
                        SDL_GL_SetAttribute(SDL_GL_STEREO, 0);
 
330
                }
 
331
                
 
332
                SDL_GL_SetAttribute( SDL_GL_DOUBLEBUFFER, 1 );
 
333
 
 
334
#if 0 // See http://bugzilla.icculus.org/show_bug.cgi?id=3526
 
335
                // If not allowing software GL, demand accelerated
 
336
                if( !r_allowSoftwareGL->integer )
 
337
                {
 
338
                        if( SDL_GL_SetAttribute( SDL_GL_ACCELERATED_VISUAL, 1 ) < 0 )
 
339
                        {
 
340
                                ri.Printf( PRINT_ALL, "Unable to guarantee accelerated "
 
341
                                                "visual with libSDL < 1.2.10\n" );
 
342
                        }
 
343
                }
 
344
#endif
 
345
 
 
346
                if( SDL_GL_SetAttribute( SDL_GL_SWAP_CONTROL, r_swapInterval->integer ) < 0 )
 
347
                        ri.Printf( PRINT_ALL, "r_swapInterval requires libSDL >= 1.2.10\n" );
 
348
 
 
349
#ifdef USE_ICON
 
350
                {
 
351
                        SDL_Surface *icon = SDL_CreateRGBSurfaceFrom(
 
352
                                        (void *)CLIENT_WINDOW_ICON.pixel_data,
 
353
                                        CLIENT_WINDOW_ICON.width,
 
354
                                        CLIENT_WINDOW_ICON.height,
 
355
                                        CLIENT_WINDOW_ICON.bytes_per_pixel * 8,
 
356
                                        CLIENT_WINDOW_ICON.bytes_per_pixel * CLIENT_WINDOW_ICON.width,
 
357
#ifdef Q3_LITTLE_ENDIAN
 
358
                                        0x000000FF, 0x0000FF00, 0x00FF0000, 0xFF000000
 
359
#else
 
360
                                        0xFF000000, 0x00FF0000, 0x0000FF00, 0x000000FF
 
361
#endif
 
362
                                        );
 
363
 
 
364
                        SDL_WM_SetIcon( icon, NULL );
 
365
                        SDL_FreeSurface( icon );
 
366
                }
 
367
#endif
 
368
 
 
369
                SDL_WM_SetCaption(CLIENT_WINDOW_TITLE, CLIENT_WINDOW_MIN_TITLE);
 
370
                SDL_ShowCursor(0);
 
371
 
 
372
                if (!(vidscreen = SDL_SetVideoMode(glConfig.vidWidth, glConfig.vidHeight, colorbits, flags)))
 
373
                {
 
374
                        ri.Printf( PRINT_DEVELOPER, "SDL_SetVideoMode failed: %s\n", SDL_GetError( ) );
 
375
                        continue;
 
376
                }
 
377
 
 
378
                opengl_context = GLimp_GetCurrentContext();
 
379
 
 
380
                ri.Printf( PRINT_ALL, "Using %d/%d/%d Color bits, %d depth, %d stencil display.\n",
 
381
                                sdlcolorbits, sdlcolorbits, sdlcolorbits, tdepthbits, tstencilbits);
 
382
 
 
383
                glConfig.colorBits = tcolorbits;
 
384
                glConfig.depthBits = tdepthbits;
 
385
                glConfig.stencilBits = tstencilbits;
 
386
                break;
 
387
        }
 
388
 
 
389
        GLimp_DetectAvailableModes();
 
390
 
 
391
        if (!vidscreen)
 
392
        {
 
393
                ri.Printf( PRINT_ALL, "Couldn't get a visual\n" );
 
394
                return RSERR_INVALID_MODE;
 
395
        }
 
396
 
 
397
        screen = vidscreen;
 
398
 
 
399
        glstring = (char *) qglGetString (GL_RENDERER);
 
400
        ri.Printf( PRINT_ALL, "GL_RENDERER: %s\n", glstring );
 
401
 
 
402
        return RSERR_OK;
 
403
}
 
404
 
 
405
/*
 
406
===============
 
407
GLimp_StartDriverAndSetMode
 
408
===============
 
409
*/
 
410
static qboolean GLimp_StartDriverAndSetMode( int mode, qboolean fullscreen )
 
411
{
 
412
        rserr_t err;
 
413
 
 
414
        if (!SDL_WasInit(SDL_INIT_VIDEO))
 
415
        {
 
416
                ri.Printf( PRINT_ALL, "SDL_Init( SDL_INIT_VIDEO )... ");
 
417
                if (SDL_Init(SDL_INIT_VIDEO) == -1)
 
418
                {
 
419
                        ri.Printf( PRINT_ALL, "FAILED (%s)\n", SDL_GetError());
 
420
                        return qfalse;
 
421
                }
 
422
                ri.Printf( PRINT_ALL, "OK\n");
 
423
        }
 
424
 
 
425
        if (fullscreen && Cvar_VariableIntegerValue( "in_nograb" ) )
 
426
        {
 
427
                ri.Printf( PRINT_ALL, "Fullscreen not allowed with in_nograb 1\n");
 
428
                ri.Cvar_Set( "r_fullscreen", "0" );
 
429
                r_fullscreen->modified = qfalse;
 
430
                fullscreen = qfalse;
 
431
        }
 
432
 
 
433
        err = GLimp_SetMode( mode, fullscreen );
 
434
 
 
435
        switch ( err )
 
436
        {
 
437
                case RSERR_INVALID_FULLSCREEN:
 
438
                        ri.Printf( PRINT_ALL, "...WARNING: fullscreen unavailable in this mode\n" );
 
439
                        return qfalse;
 
440
                case RSERR_INVALID_MODE:
 
441
                        ri.Printf( PRINT_ALL, "...WARNING: could not set the given mode (%d)\n", mode );
 
442
                        return qfalse;
 
443
                default:
 
444
                        break;
 
445
        }
 
446
 
 
447
        return qtrue;
 
448
}
 
449
/*
 
450
===============
 
451
GLimp_InitExtensions
 
452
===============
 
453
*/
 
454
static void GLimp_InitExtensions( void )
 
455
{
 
456
        if ( !r_allowExtensions->integer )
 
457
        {
 
458
                ri.Printf( PRINT_ALL, "* IGNORING OPENGL EXTENSIONS *\n" );
 
459
                return;
 
460
        }
 
461
 
 
462
        ri.Printf( PRINT_ALL, "Initializing OpenGL extensions\n" );
 
463
 
 
464
        // GL_S3_s3tc
 
465
        if ( Q_stristr( glConfig.extensions_string, "GL_S3_s3tc" ) )
 
466
        {
 
467
                if ( r_ext_compressed_textures->value )
 
468
                {
 
469
                        glConfig.textureCompression = TC_S3TC;
 
470
                        ri.Printf( PRINT_ALL, "...using GL_S3_s3tc\n" );
 
471
                }
 
472
                else
 
473
                {
 
474
                        glConfig.textureCompression = TC_NONE;
 
475
                        ri.Printf( PRINT_ALL, "...ignoring GL_S3_s3tc\n" );
 
476
                }
 
477
        }
 
478
        else
 
479
        {
 
480
                glConfig.textureCompression = TC_NONE;
 
481
                ri.Printf( PRINT_ALL, "...GL_S3_s3tc not found\n" );
 
482
        }
 
483
 
 
484
        // GL_EXT_texture_env_add
 
485
        glConfig.textureEnvAddAvailable = qfalse;
 
486
        if ( Q_stristr( glConfig.extensions_string, "EXT_texture_env_add" ) )
 
487
        {
 
488
                if ( r_ext_texture_env_add->integer )
 
489
                {
 
490
                        glConfig.textureEnvAddAvailable = qtrue;
 
491
                        ri.Printf( PRINT_ALL, "...using GL_EXT_texture_env_add\n" );
 
492
                }
 
493
                else
 
494
                {
 
495
                        glConfig.textureEnvAddAvailable = qfalse;
 
496
                        ri.Printf( PRINT_ALL, "...ignoring GL_EXT_texture_env_add\n" );
 
497
                }
 
498
        }
 
499
        else
 
500
        {
 
501
                ri.Printf( PRINT_ALL, "...GL_EXT_texture_env_add not found\n" );
 
502
        }
 
503
 
 
504
        // GL_ARB_multitexture
 
505
        qglMultiTexCoord2fARB = NULL;
 
506
        qglActiveTextureARB = NULL;
 
507
        qglClientActiveTextureARB = NULL;
 
508
        if ( Q_stristr( glConfig.extensions_string, "GL_ARB_multitexture" ) )
 
509
        {
 
510
                if ( r_ext_multitexture->value )
 
511
                {
 
512
                        qglMultiTexCoord2fARB = SDL_GL_GetProcAddress( "glMultiTexCoord2fARB" );
 
513
                        qglActiveTextureARB = SDL_GL_GetProcAddress( "glActiveTextureARB" );
 
514
                        qglClientActiveTextureARB = SDL_GL_GetProcAddress( "glClientActiveTextureARB" );
 
515
 
 
516
                        if ( qglActiveTextureARB )
 
517
                        {
 
518
                                GLint glint = 0;
 
519
                                qglGetIntegerv( GL_MAX_TEXTURE_UNITS_ARB, &glint );
 
520
                                glConfig.numTextureUnits = (int) glint;
 
521
                                if ( glConfig.numTextureUnits > 1 )
 
522
                                {
 
523
                                        ri.Printf( PRINT_ALL, "...using GL_ARB_multitexture\n" );
 
524
                                }
 
525
                                else
 
526
                                {
 
527
                                        qglMultiTexCoord2fARB = NULL;
 
528
                                        qglActiveTextureARB = NULL;
 
529
                                        qglClientActiveTextureARB = NULL;
 
530
                                        ri.Printf( PRINT_ALL, "...not using GL_ARB_multitexture, < 2 texture units\n" );
 
531
                                }
 
532
                        }
 
533
                }
 
534
                else
 
535
                {
 
536
                        ri.Printf( PRINT_ALL, "...ignoring GL_ARB_multitexture\n" );
 
537
                }
 
538
        }
 
539
        else
 
540
        {
 
541
                ri.Printf( PRINT_ALL, "...GL_ARB_multitexture not found\n" );
 
542
        }
 
543
 
 
544
        // GL_EXT_compiled_vertex_array
 
545
        if ( Q_stristr( glConfig.extensions_string, "GL_EXT_compiled_vertex_array" ) )
 
546
        {
 
547
                if ( r_ext_compiled_vertex_array->value )
 
548
                {
 
549
                        ri.Printf( PRINT_ALL, "...using GL_EXT_compiled_vertex_array\n" );
 
550
                        qglLockArraysEXT = ( void ( APIENTRY * )( GLint, GLint ) ) SDL_GL_GetProcAddress( "glLockArraysEXT" );
 
551
                        qglUnlockArraysEXT = ( void ( APIENTRY * )( void ) ) SDL_GL_GetProcAddress( "glUnlockArraysEXT" );
 
552
                        if (!qglLockArraysEXT || !qglUnlockArraysEXT)
 
553
                        {
 
554
                                ri.Error (ERR_FATAL, "bad getprocaddress");
 
555
                        }
 
556
                }
 
557
                else
 
558
                {
 
559
                        ri.Printf( PRINT_ALL, "...ignoring GL_EXT_compiled_vertex_array\n" );
 
560
                }
 
561
        }
 
562
        else
 
563
        {
 
564
                ri.Printf( PRINT_ALL, "...GL_EXT_compiled_vertex_array not found\n" );
 
565
        }
 
566
 
 
567
        textureFilterAnisotropic = qfalse;
 
568
        if ( strstr( glConfig.extensions_string, "GL_EXT_texture_filter_anisotropic" ) )
 
569
        {
 
570
                if ( r_ext_texture_filter_anisotropic->integer ) {
 
571
                        qglGetIntegerv( GL_MAX_TEXTURE_MAX_ANISOTROPY_EXT, (GLint *)&maxAnisotropy );
 
572
                        if ( maxAnisotropy <= 0 ) {
 
573
                                ri.Printf( PRINT_ALL, "...GL_EXT_texture_filter_anisotropic not properly supported!\n" );
 
574
                                maxAnisotropy = 0;
 
575
                        }
 
576
                        else
 
577
                        {
 
578
                                ri.Printf( PRINT_ALL, "...using GL_EXT_texture_filter_anisotropic (max: %i)\n", maxAnisotropy );
 
579
                                textureFilterAnisotropic = qtrue;
 
580
                        }
 
581
                }
 
582
                else
 
583
                {
 
584
                        ri.Printf( PRINT_ALL, "...ignoring GL_EXT_texture_filter_anisotropic\n" );
 
585
                }
 
586
        }
 
587
        else
 
588
        {
 
589
                ri.Printf( PRINT_ALL, "...GL_EXT_texture_filter_anisotropic not found\n" );
 
590
        }
 
591
}
 
592
 
 
593
#define R_MODE_FALLBACK 3 // 640 * 480
 
594
 
 
595
/*
 
596
===============
 
597
GLimp_Init
 
598
 
 
599
This routine is responsible for initializing the OS specific portions
 
600
of OpenGL
 
601
===============
 
602
*/
 
603
void GLimp_Init( void )
 
604
{
 
605
        qboolean success = qtrue;
 
606
 
 
607
        r_allowSoftwareGL = ri.Cvar_Get( "r_allowSoftwareGL", "0", CVAR_LATCH );
 
608
 
 
609
        // create the window and set up the context
 
610
        if( !GLimp_StartDriverAndSetMode( r_mode->integer, r_fullscreen->integer ) )
 
611
        {
 
612
                if( r_mode->integer != R_MODE_FALLBACK )
 
613
                {
 
614
                        ri.Printf( PRINT_ALL, "Setting r_mode %d failed, falling back on r_mode %d\n",
 
615
                                        r_mode->integer, R_MODE_FALLBACK );
 
616
                        if( !GLimp_StartDriverAndSetMode( R_MODE_FALLBACK, r_fullscreen->integer ) )
 
617
                                success = qfalse;
 
618
                }
 
619
                else
 
620
                        success = qfalse;
 
621
        }
 
622
 
 
623
        if( !success )
 
624
                ri.Error( ERR_FATAL, "GLimp_Init() - could not load OpenGL subsystem\n" );
 
625
 
 
626
        // This values force the UI to disable driver selection
 
627
        glConfig.driverType = GLDRV_ICD;
 
628
        glConfig.hardwareType = GLHW_GENERIC;
 
629
        glConfig.deviceSupportsGamma = !!( SDL_SetGamma( 1.0f, 1.0f, 1.0f ) >= 0 );
 
630
 
 
631
        // get our config strings
 
632
        Q_strncpyz( glConfig.vendor_string, (char *) qglGetString (GL_VENDOR), sizeof( glConfig.vendor_string ) );
 
633
        Q_strncpyz( glConfig.renderer_string, (char *) qglGetString (GL_RENDERER), sizeof( glConfig.renderer_string ) );
 
634
        if (*glConfig.renderer_string && glConfig.renderer_string[strlen(glConfig.renderer_string) - 1] == '\n')
 
635
                glConfig.renderer_string[strlen(glConfig.renderer_string) - 1] = 0;
 
636
        Q_strncpyz( glConfig.version_string, (char *) qglGetString (GL_VERSION), sizeof( glConfig.version_string ) );
 
637
        Q_strncpyz( glConfig.extensions_string, (char *) qglGetString (GL_EXTENSIONS), sizeof( glConfig.extensions_string ) );
 
638
 
 
639
        // initialize extensions
 
640
        GLimp_InitExtensions( );
 
641
 
 
642
        ri.Cvar_Get( "r_availableModes", "", CVAR_ROM );
 
643
 
 
644
        // This depends on SDL_INIT_VIDEO, hence having it here
 
645
        IN_Init( );
 
646
 
 
647
        return;
 
648
}
 
649
 
 
650
 
 
651
/*
 
652
===============
 
653
GLimp_EndFrame
 
654
 
 
655
Responsible for doing a swapbuffers
 
656
===============
 
657
*/
 
658
void GLimp_EndFrame( void )
 
659
{
 
660
        // don't flip if drawing to front buffer
 
661
        if ( Q_stricmp( r_drawBuffer->string, "GL_FRONT" ) != 0 )
 
662
        {
 
663
                SDL_GL_SwapBuffers();
 
664
        }
 
665
 
 
666
        if( r_fullscreen->modified )
 
667
        {
 
668
                qboolean    fullscreen;
 
669
                qboolean    sdlToggled = qfalse;
 
670
                SDL_Surface *s = SDL_GetVideoSurface( );
 
671
 
 
672
                if( s )
 
673
                {
 
674
                        // Find out the current state
 
675
                        if( s->flags & SDL_FULLSCREEN )
 
676
                                fullscreen = qtrue;
 
677
                        else
 
678
                                fullscreen = qfalse;
 
679
                                
 
680
                        if (r_fullscreen->integer && Cvar_VariableIntegerValue( "in_nograb" ))
 
681
                        {
 
682
                                ri.Printf( PRINT_ALL, "Fullscreen not allowed with in_nograb 1\n");
 
683
                                ri.Cvar_Set( "r_fullscreen", "0" );
 
684
                                r_fullscreen->modified = qfalse;
 
685
                        }
 
686
 
 
687
                        // Is the state we want different from the current state?
 
688
                        if( !!r_fullscreen->integer != fullscreen )
 
689
                                sdlToggled = SDL_WM_ToggleFullScreen( s );
 
690
                        else
 
691
                                sdlToggled = qtrue;
 
692
                }
 
693
 
 
694
                // SDL_WM_ToggleFullScreen didn't work, so do it the slow way
 
695
                if( !sdlToggled )
 
696
                        Cbuf_AddText( "vid_restart" );
 
697
 
 
698
                r_fullscreen->modified = qfalse;
 
699
        }
 
700
}
 
701
 
 
702
 
 
703
 
 
704
#ifdef SMP
 
705
/*
 
706
===========================================================
 
707
 
 
708
SMP acceleration
 
709
 
 
710
===========================================================
 
711
*/
 
712
 
 
713
/*
 
714
 * I have no idea if this will even work...most platforms don't offer
 
715
 * thread-safe OpenGL libraries, and it looks like the original Linux
 
716
 * code counted on each thread claiming the GL context with glXMakeCurrent(),
 
717
 * which you can't currently do in SDL. We'll just have to hope for the best.
 
718
 */
 
719
 
 
720
static SDL_mutex *smpMutex = NULL;
 
721
static SDL_cond *renderCommandsEvent = NULL;
 
722
static SDL_cond *renderCompletedEvent = NULL;
 
723
static void (*glimpRenderThread)( void ) = NULL;
 
724
static SDL_Thread *renderThread = NULL;
 
725
 
 
726
/*
 
727
===============
 
728
GLimp_ShutdownRenderThread
 
729
===============
 
730
*/
 
731
static void GLimp_ShutdownRenderThread(void)
 
732
{
 
733
        if (smpMutex != NULL)
 
734
        {
 
735
                SDL_DestroyMutex(smpMutex);
 
736
                smpMutex = NULL;
 
737
        }
 
738
 
 
739
        if (renderCommandsEvent != NULL)
 
740
        {
 
741
                SDL_DestroyCond(renderCommandsEvent);
 
742
                renderCommandsEvent = NULL;
 
743
        }
 
744
 
 
745
        if (renderCompletedEvent != NULL)
 
746
        {
 
747
                SDL_DestroyCond(renderCompletedEvent);
 
748
                renderCompletedEvent = NULL;
 
749
        }
 
750
 
 
751
        glimpRenderThread = NULL;
 
752
}
 
753
 
 
754
/*
 
755
===============
 
756
GLimp_RenderThreadWrapper
 
757
===============
 
758
*/
 
759
static int GLimp_RenderThreadWrapper( void *arg )
 
760
{
 
761
        Com_Printf( "Render thread starting\n" );
 
762
 
 
763
        glimpRenderThread();
 
764
 
 
765
        GLimp_SetCurrentContext(NULL);
 
766
 
 
767
        Com_Printf( "Render thread terminating\n" );
 
768
 
 
769
        return 0;
 
770
}
 
771
 
 
772
/*
 
773
===============
 
774
GLimp_SpawnRenderThread
 
775
===============
 
776
*/
 
777
qboolean GLimp_SpawnRenderThread( void (*function)( void ) )
 
778
{
 
779
        static qboolean warned = qfalse;
 
780
        if (!warned)
 
781
        {
 
782
                Com_Printf("WARNING: You enable r_smp at your own risk!\n");
 
783
                warned = qtrue;
 
784
        }
 
785
 
 
786
#ifndef MACOS_X
 
787
        return qfalse;  /* better safe than sorry for now. */
 
788
#endif
 
789
 
 
790
        if (renderThread != NULL)  /* hopefully just a zombie at this point... */
 
791
        {
 
792
                Com_Printf("Already a render thread? Trying to clean it up...\n");
 
793
                SDL_WaitThread(renderThread, NULL);
 
794
                renderThread = NULL;
 
795
                GLimp_ShutdownRenderThread();
 
796
        }
 
797
 
 
798
        smpMutex = SDL_CreateMutex();
 
799
        if (smpMutex == NULL)
 
800
        {
 
801
                Com_Printf( "smpMutex creation failed: %s\n", SDL_GetError() );
 
802
                GLimp_ShutdownRenderThread();
 
803
                return qfalse;
 
804
        }
 
805
 
 
806
        renderCommandsEvent = SDL_CreateCond();
 
807
        if (renderCommandsEvent == NULL)
 
808
        {
 
809
                Com_Printf( "renderCommandsEvent creation failed: %s\n", SDL_GetError() );
 
810
                GLimp_ShutdownRenderThread();
 
811
                return qfalse;
 
812
        }
 
813
 
 
814
        renderCompletedEvent = SDL_CreateCond();
 
815
        if (renderCompletedEvent == NULL)
 
816
        {
 
817
                Com_Printf( "renderCompletedEvent creation failed: %s\n", SDL_GetError() );
 
818
                GLimp_ShutdownRenderThread();
 
819
                return qfalse;
 
820
        }
 
821
 
 
822
        glimpRenderThread = function;
 
823
        renderThread = SDL_CreateThread(GLimp_RenderThreadWrapper, NULL);
 
824
        if ( renderThread == NULL )
 
825
        {
 
826
                ri.Printf( PRINT_ALL, "SDL_CreateThread() returned %s", SDL_GetError() );
 
827
                GLimp_ShutdownRenderThread();
 
828
                return qfalse;
 
829
        }
 
830
        else
 
831
        {
 
832
                // tma 01/09/07: don't think this is necessary anyway?
 
833
                //
 
834
                // !!! FIXME: No detach API available in SDL!
 
835
                //ret = pthread_detach( renderThread );
 
836
                //if ( ret ) {
 
837
                //ri.Printf( PRINT_ALL, "pthread_detach returned %d: %s", ret, strerror( ret ) );
 
838
                //}
 
839
        }
 
840
 
 
841
        return qtrue;
 
842
}
 
843
 
 
844
static volatile void    *smpData = NULL;
 
845
static volatile qboolean smpDataReady;
 
846
 
 
847
/*
 
848
===============
 
849
GLimp_RendererSleep
 
850
===============
 
851
*/
 
852
void *GLimp_RendererSleep( void )
 
853
{
 
854
        void  *data = NULL;
 
855
 
 
856
        GLimp_SetCurrentContext(NULL);
 
857
 
 
858
        SDL_LockMutex(smpMutex);
 
859
        {
 
860
                smpData = NULL;
 
861
                smpDataReady = qfalse;
 
862
 
 
863
                // after this, the front end can exit GLimp_FrontEndSleep
 
864
                SDL_CondSignal(renderCompletedEvent);
 
865
 
 
866
                while ( !smpDataReady )
 
867
                        SDL_CondWait(renderCommandsEvent, smpMutex);
 
868
 
 
869
                data = (void *)smpData;
 
870
        }
 
871
        SDL_UnlockMutex(smpMutex);
 
872
 
 
873
        GLimp_SetCurrentContext(opengl_context);
 
874
 
 
875
        return data;
 
876
}
 
877
 
 
878
/*
 
879
===============
 
880
GLimp_FrontEndSleep
 
881
===============
 
882
*/
 
883
void GLimp_FrontEndSleep( void )
 
884
{
 
885
        SDL_LockMutex(smpMutex);
 
886
        {
 
887
                while ( smpData )
 
888
                        SDL_CondWait(renderCompletedEvent, smpMutex);
 
889
        }
 
890
        SDL_UnlockMutex(smpMutex);
 
891
 
 
892
        GLimp_SetCurrentContext(opengl_context);
 
893
}
 
894
 
 
895
/*
 
896
===============
 
897
GLimp_WakeRenderer
 
898
===============
 
899
*/
 
900
void GLimp_WakeRenderer( void *data )
 
901
{
 
902
        GLimp_SetCurrentContext(NULL);
 
903
 
 
904
        SDL_LockMutex(smpMutex);
 
905
        {
 
906
                assert( smpData == NULL );
 
907
                smpData = data;
 
908
                smpDataReady = qtrue;
 
909
 
 
910
                // after this, the renderer can continue through GLimp_RendererSleep
 
911
                SDL_CondSignal(renderCommandsEvent);
 
912
        }
 
913
        SDL_UnlockMutex(smpMutex);
 
914
}
 
915
 
 
916
#else
 
917
 
 
918
// No SMP - stubs
 
919
void GLimp_RenderThreadWrapper( void *arg )
 
920
{
 
921
}
 
922
 
 
923
qboolean GLimp_SpawnRenderThread( void (*function)( void ) )
 
924
{
 
925
        ri.Printf( PRINT_WARNING, "ERROR: SMP support was disabled at compile time\n");
 
926
        return qfalse;
 
927
}
 
928
 
 
929
void *GLimp_RendererSleep( void )
 
930
{
 
931
        return NULL;
 
932
}
 
933
 
 
934
void GLimp_FrontEndSleep( void )
 
935
{
 
936
}
 
937
 
 
938
void GLimp_WakeRenderer( void *data )
 
939
{
 
940
}
 
941
 
 
942
#endif