~ivantis/armagetronad/sty+ct+ivantis

« back to all changes in this revision

Viewing changes to src/render/rSysdep.cpp

  • Committer: ivantis
  • Date: 2008-09-09 21:33:18 UTC
  • Revision ID: ivantis@ivantis.net-20080909213318-k43y6yuq0zd6wbsa
first commit

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
 
 
3
*************************************************************************
 
4
 
 
5
ArmageTron -- Just another Tron Lightcycle Game in 3D.
 
6
Copyright (C) 2000  Manuel Moos (manuel@moosnet.de)
 
7
 
 
8
**************************************************************************
 
9
 
 
10
This program is free software; you can redistribute it and/or
 
11
modify it under the terms of the GNU General Public License
 
12
as published by the Free Software Foundation; either version 2
 
13
of the License, or (at your option) any later version.
 
14
 
 
15
This program is distributed in the hope that it will be useful,
 
16
but WITHOUT ANY WARRANTY; without even the implied warranty of
 
17
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 
18
GNU General Public License for more details.
 
19
 
 
20
You should have received a copy of the GNU General Public License
 
21
along with this program; if not, write to the Free Software
 
22
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
 
23
 
 
24
***************************************************************************
 
25
 
 
26
*/
 
27
 
 
28
 
 
29
#include "defs.h"
 
30
#ifndef DEDICATED
 
31
#include "rSDL.h"
 
32
#endif
 
33
 
 
34
#include "rSysdep.h"
 
35
#include "tInitExit.h"
 
36
#include "tDirectories.h"
 
37
#include "tSysTime.h"
 
38
#include "rConsole.h"
 
39
#include "config.h"
 
40
#include <iostream>
 
41
#include "rScreen.h"
 
42
#include "rGL.h"
 
43
#include "tCommandLine.h"
 
44
#include "tConfiguration.h"
 
45
#include "tRecorder.h"
 
46
 
 
47
#ifndef DEDICATED
 
48
#include "SDL_thread.h"
 
49
#include "SDL_mutex.h"
 
50
 
 
51
#include <png.h>
 
52
#define SCREENSHOT_PNG_BITDEPTH 8
 
53
#define SCREENSHOT_BYTES_PER_PIXEL 3
 
54
#ifndef SDL_OPENGL
 
55
#ifndef DIRTY
 
56
#define DIRTY
 
57
#endif
 
58
#endif
 
59
 
 
60
//#ifndef SDL_OPENGL
 
61
//#error "need SDL 1.1"
 
62
//#endif
 
63
 
 
64
#ifndef DIRTY
 
65
 
 
66
// nothing to be done.
 
67
 
 
68
/*
 
69
//#elif defined(HAVE_FXMESA)
 
70
 #include <GL/gl>
 
71
 #include <GL/fxmesa>
 
72
 
 
73
 static fxMesaContext ctx=NULL;
 
74
*/
 
75
 
 
76
#elif defined(WIN32)
 
77
 
 
78
 #include <windows.h>
 
79
 #include <windef.h>
 
80
 #include "rGL.h"
 
81
static HDC hDC=NULL;
 
82
static HGLRC hRC=NULL;
 
83
 
 
84
#elif defined(unix) || defined(__unix__)
 
85
 
 
86
#include <GL/glx.h>
 
87
static GLXContext cx;
 
88
Display *dpy=NULL;
 
89
Window  win;
 
90
 
 
91
#endif
 
92
 
 
93
#ifdef DIRTY
 
94
#include <SDL_syswm.h>
 
95
 
 
96
// graphics initialisation and cleanup:
 
97
bool  rSysDep::InitGL(){
 
98
    SDL_SysWMinfo system;
 
99
    SDL_VERSION(&system.version);
 
100
    if (!SDL_GetWMInfo(&system)){
 
101
        std::cerr << "Video information not available!\n";
 
102
        return(false);
 
103
    }
 
104
 
 
105
    /*
 
106
    con << "SDL version: " << (int)system.version.major
 
107
         << "." <<  (int)system.version.minor << "." <<  (int)system.version.patch << '\n';
 
108
    */
 
109
 
 
110
    /*
 
111
    //#ifdef HAVE_FXMESA
 
112
    if(!ctx){
 
113
      int x=fxQueryHardware();
 
114
      if(x){
 
115
        std::cerr << "No 3Dfx hardware available.\n" << x << '\n';
 
116
        return(false);
 
117
      }
 
118
 
 
119
      GLint attribs[]={FXMESA_DOUBLEBUFFER,FXMESA_DEPTH_SIZE,16,FXMESA_NONE};
 
120
      ctx=fxMesaCreateBestContext(0,sr_screenWidth,sr_screenHeight,attribs);
 
121
 
 
122
      if (!ctx){
 
123
        std::cerr << "Could not create FX rendering context!\n";
 
124
        return(false);
 
125
      }
 
126
 
 
127
      fxMesaMakeCurrent(ctx);
 
128
    }
 
129
    */
 
130
#ifdef WIN32
 
131
    // windows GL initialisation stolen from
 
132
    // http://www.geocities.com/SiliconValley/Code/1219/opengl32.html
 
133
 
 
134
    if (!hRC){
 
135
        HWND hWnd=system.window;
 
136
 
 
137
        PIXELFORMATDESCRIPTOR pfd;
 
138
        int iFormat;
 
139
 
 
140
        // get the device context (DC)
 
141
        hDC = GetDC( hWnd );
 
142
        if (!hDC) return false;
 
143
 
 
144
        // set the pixel format for the DC
 
145
        ZeroMemory( &pfd, sizeof( pfd ) );
 
146
        pfd.nSize = sizeof( pfd );
 
147
        pfd.nVersion = 1;
 
148
        pfd.dwFlags = PFD_DRAW_TO_WINDOW |
 
149
                      PFD_SUPPORT_OPENGL | PFD_DOUBLEBUFFER;
 
150
        pfd.iPixelType = PFD_TYPE_RGBA;
 
151
        pfd.cColorBits = currentScreensetting.colorDepth ? 24 : 16;
 
152
        pfd.cDepthBits = 16;
 
153
        pfd.iLayerType = PFD_MAIN_PLANE;
 
154
        iFormat = ChoosePixelFormat( hDC, &pfd );
 
155
        SetPixelFormat( hDC, iFormat, &pfd );
 
156
 
 
157
        // create and enable the render context (RC)
 
158
        hRC = wglCreateContext( hDC );
 
159
        if (!hRC || !wglMakeCurrent( hDC, hRC ))
 
160
            return false;
 
161
    }
 
162
 
 
163
#elif defined(unix) || defined(__unix__)
 
164
    if (system.subsystem!=SDL_SYSWM_X11){
 
165
        std::cerr << "System is not X11!\n";
 
166
        std::cerr << (int)system.subsystem << "!=" << (int)SDL_SYSWM_X11 <<'\n';
 
167
        return false;
 
168
    }
 
169
 
 
170
    if(!dpy){
 
171
 
 
172
        dpy=system.info.x11.display;
 
173
        win=system.info.x11.window;
 
174
 
 
175
        int errorbase,tEventbase;
 
176
        if (glXQueryExtension(dpy,&errorbase,&tEventbase) == False){
 
177
            std::cerr << "OpenGL through GLX not supported.\n";
 
178
            return false;
 
179
        }
 
180
 
 
181
        int configuration[]={GLX_DOUBLEBUFFER,GLX_RGBA,GLX_DEPTH_SIZE ,12, GLX_RED_SIZE,1,
 
182
                             GLX_BLUE_SIZE,1,GLX_GREEN_SIZE,1,None};
 
183
 
 
184
        XVisualInfo *vi=glXChooseVisual(dpy,DefaultScreen(dpy),configuration);
 
185
 
 
186
        if(vi== NULL){
 
187
            std::cerr << "Could not initialize Visual.\n";
 
188
            return false;
 
189
        }
 
190
 
 
191
        cx=glXCreateContext(dpy,vi,
 
192
                            NULL,True);
 
193
 
 
194
        if(cx== NULL){
 
195
            std::cerr << "Could not initialize GL context.\n";
 
196
            return false;
 
197
        }
 
198
 
 
199
        if (!glXMakeCurrent(dpy,win,cx)){
 
200
            dpy=0;
 
201
            return false;
 
202
        }
 
203
    }
 
204
 
 
205
#endif
 
206
 
 
207
    return true;
 
208
}
 
209
 
 
210
void  rSysDep::ExitGL(){
 
211
    SDL_SysWMinfo system;
 
212
    SDL_GetWMInfo(&system);
 
213
 
 
214
    /*
 
215
    #ifdef HAVE_FXMESA
 
216
 
 
217
    if(ctx){
 
218
      fxMesaDestroyContext(ctx);
 
219
      ctx=NULL;
 
220
      fxCloseHardware();
 
221
    }
 
222
    */
 
223
 
 
224
#if defined(WIN32)
 
225
    HWND hWnd=system.window;
 
226
 
 
227
    // windows GL cleanup stolen from
 
228
    // http://www.geocities.com/SiliconValley/Code/1219/opengl32.html
 
229
    if(hRC){
 
230
 
 
231
        wglMakeCurrent( NULL, NULL );
 
232
        wglDeleteContext( hRC );
 
233
        ReleaseDC( hWnd, hDC );
 
234
 
 
235
        hRC=NULL;
 
236
        hDC=NULL;
 
237
    }
 
238
#elif defined(unix) || defined(__unix__)
 
239
    if(dpy){
 
240
 
 
241
        //    glXReleaseBuffersMESA( dpy, win );
 
242
        glXMakeCurrent(dpy,None,NULL);
 
243
        glXDestroyContext(dpy, cx );
 
244
        dpy=NULL;
 
245
    }
 
246
#endif
 
247
}
 
248
#endif // DIRTY
 
249
 
 
250
bool sr_screenshotIsPlanned=false;
 
251
 
 
252
static bool png_screenshot=true;
 
253
static tConfItem<bool> pns("PNG_SCREENSHOT",png_screenshot);
 
254
#ifndef DEDICATED
 
255
 
 
256
static void SDL_SavePNG(SDL_Surface *image, tString filename){
 
257
    png_structp png_ptr;
 
258
    png_infop info_ptr;
 
259
    png_byte **row_ptrs;
 
260
    int i;
 
261
    static FILE *fp;
 
262
 
 
263
    if (!(fp = fopen(filename, "wb"))) {
 
264
        fprintf(stderr, "can't open file for writing\n");
 
265
        return;
 
266
    }
 
267
 
 
268
    if (!(png_ptr = png_create_write_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL))) {
 
269
        return;
 
270
    }
 
271
 
 
272
    if (!(info_ptr = png_create_info_struct(png_ptr))) {
 
273
        png_destroy_write_struct(&png_ptr, (png_infopp)NULL);
 
274
        return;
 
275
    }
 
276
 
 
277
    png_init_io(png_ptr, fp);
 
278
 
 
279
    png_set_IHDR(png_ptr, info_ptr, sr_screenWidth, sr_screenHeight,
 
280
                 SCREENSHOT_PNG_BITDEPTH, PNG_COLOR_TYPE_RGB,
 
281
                 PNG_INTERLACE_NONE, PNG_COMPRESSION_TYPE_DEFAULT,
 
282
                 PNG_FILTER_TYPE_DEFAULT);
 
283
    png_write_info(png_ptr, info_ptr);
 
284
 
 
285
    // get pointers
 
286
    if(!(row_ptrs = (png_byte**) malloc(sr_screenHeight * sizeof(png_byte*)))) {
 
287
        png_destroy_write_struct(&png_ptr, &info_ptr);
 
288
        return;
 
289
    }
 
290
 
 
291
    for(i = 0; i < sr_screenHeight; i++) {
 
292
        row_ptrs[i] = (png_byte *)image->pixels + (sr_screenHeight - i - 1)
 
293
                      * SCREENSHOT_BYTES_PER_PIXEL * sr_screenWidth;
 
294
    }
 
295
 
 
296
    png_write_image(png_ptr, row_ptrs);
 
297
    png_write_end(png_ptr, info_ptr);
 
298
    png_destroy_write_struct(&png_ptr, &info_ptr);
 
299
 
 
300
    free(row_ptrs);
 
301
    fclose(fp);
 
302
}
 
303
#endif
 
304
 
 
305
static void make_screenshot(){
 
306
#ifndef DEDICATED
 
307
    // screenshot count
 
308
    static int number=0;
 
309
    number++;
 
310
 
 
311
    SDL_Surface *image;
 
312
    SDL_Surface *temp;
 
313
    int idx;
 
314
    image = SDL_CreateRGBSurface(SDL_SWSURFACE, sr_screenWidth, sr_screenHeight,
 
315
                                 24, 0x0000FF, 0x00FF00, 0xFF0000 ,0);
 
316
    temp = SDL_CreateRGBSurface(SDL_SWSURFACE, sr_screenWidth, sr_screenHeight,
 
317
                                24, 0x0000FF, 0x00FF00, 0xFF0000, 0);
 
318
 
 
319
    // make upside down screenshot
 
320
    glReadPixels(0,0,sr_screenWidth, sr_screenHeight, GL_RGB,
 
321
                 GL_UNSIGNED_BYTE, image->pixels);
 
322
 
 
323
    // turn image around
 
324
    for (idx = 0; idx < sr_screenHeight; idx++)
 
325
    {
 
326
        memcpy(reinterpret_cast<char *>(temp->pixels) + 3 * sr_screenWidth * idx,
 
327
               reinterpret_cast<char *>(image->pixels)+ 3
 
328
               * sr_screenWidth*(sr_screenHeight - idx-1),
 
329
               3*sr_screenWidth);
 
330
    }
 
331
 
 
332
    // save screenshot in unused slot
 
333
    bool done = false;
 
334
    while ( !done )
 
335
    {
 
336
        // generate filename
 
337
        tString fileName("screenshot_");
 
338
        fileName << number;
 
339
        if(png_screenshot)
 
340
            fileName << ".png";
 
341
        else
 
342
            fileName << ".bmp";
 
343
 
 
344
        // test if file exists
 
345
        std::ifstream s;
 
346
        if ( tDirectories::Screenshot().Open( s, fileName ) )
 
347
        {
 
348
            // yes! try next number
 
349
            number++;
 
350
            continue;
 
351
        }
 
352
 
 
353
        // save image
 
354
        if(png_screenshot)
 
355
            SDL_SavePNG(image, tDirectories::Screenshot().GetWritePath( fileName ));
 
356
        else
 
357
            SDL_SaveBMP(temp, tDirectories::Screenshot().GetWritePath( fileName ) );
 
358
        done = true;
 
359
    }
 
360
 
 
361
    // cleanup
 
362
    SDL_FreeSurface(image);
 
363
    SDL_FreeSurface(temp);
 
364
#endif
 
365
}
 
366
 
 
367
class PerformanceCounter
 
368
{
 
369
public:
 
370
    PerformanceCounter(): count_(0){ tRealSysTimeFloat(); }
 
371
    unsigned int Count(){ return count_++; }
 
372
    ~PerformanceCounter()
 
373
    {
 
374
        double time = tRealSysTimeFloat();
 
375
        std::stringstream s;
 
376
        s << count_ << " frames in " << time << " seconds: " << count_ / time << " fps.\n";
 
377
#ifdef WIN32
 
378
        MessageBox (NULL, s.str().c_str() , "Performance", MB_OK);
 
379
#else
 
380
        std::cout << s.str();
 
381
#endif
 
382
    }
 
383
private:
 
384
    unsigned int count_;
 
385
};
 
386
 
 
387
static double s_nextFastForwardFrameRecorded=0; // the next frame to render in recorded time
 
388
static double s_nextFastForwardFrameReal=0;     // the next frame to render in real time
 
389
#endif // DEDICATED
 
390
 
 
391
// settings for fast forward mode
 
392
static REAL sr_FF_Maxstep=1; // maximum step between rendered frames
 
393
static tSettingItem<REAL> c_ff( "FAST_FORWARD_MAXSTEP",
 
394
                                sr_FF_Maxstep );
 
395
 
 
396
static REAL sr_FF_MaxstepReal=.05; // maximum step in real time between rendered frames
 
397
static tSettingItem<REAL> c_ffre( "FAST_FORWARD_MAXSTEP_REAL",
 
398
                                  sr_FF_MaxstepReal );
 
399
 
 
400
static REAL sr_FF_MaxstepRel=1; // maximum step between rendered frames relative to end of FF mode
 
401
static tSettingItem<REAL> c_ffr( "FAST_FORWARD_MAXSTEP_REL",
 
402
                                 sr_FF_MaxstepRel );
 
403
 
 
404
 
 
405
static double s_fastForwardTo=0;
 
406
static bool   s_fastForward =false;
 
407
static bool   s_benchmark   =false;
 
408
 
 
409
class rFastForwardCommandLineAnalyzer: public tCommandLineAnalyzer
 
410
{
 
411
private:
 
412
    virtual bool DoAnalyze( tCommandLineParser & parser )
 
413
    {
 
414
        // get option
 
415
        tString forward;
 
416
        if ( parser.GetOption( forward, "--fastforward" ) )
 
417
        {
 
418
            // set fast forward mode
 
419
            s_fastForward = true;
 
420
 
 
421
            // read time
 
422
            std::stringstream str(static_cast< char const * >( forward ) );
 
423
            str >> s_fastForwardTo;
 
424
 
 
425
            return true;
 
426
        }
 
427
 
 
428
        if ( parser.GetSwitch( "--benchmark" ) )
 
429
        {
 
430
            // set benchmark mode
 
431
            s_benchmark = true;
 
432
            return true;
 
433
        }
 
434
 
 
435
        return false;
 
436
    }
 
437
 
 
438
    virtual void DoHelp( std::ostream & s )
 
439
    {                                      //
 
440
        s << "--fastforward <time>         : lets time run very fast until the given time is reached\n";
 
441
        s << "--benchmark                  : renders frames as they were recorded\n";
 
442
    }
 
443
};
 
444
 
 
445
static rFastForwardCommandLineAnalyzer analyzer;
 
446
 
 
447
// #define MILLION 1000000
 
448
 
 
449
/*
 
450
static double lastFrame = -1;
 
451
static void sr_DelayFrame( int targetFPS )
 
452
{
 
453
    // calculate microseconds per frame
 
454
    int uSecsPerFrame = MILLION/(targetFPS + 10);
 
455
 
 
456
    // calculate microseconds spent rendering
 
457
    double thisFrame = tRealSysTimeFloat();
 
458
 
 
459
    int uSecsPassed = static_cast<int>( MILLION * ( thisFrame - lastFrame ) );
 
460
 
 
461
//    con << uSecsPassed << "\n";
 
462
 
 
463
    // wait
 
464
    int uSecsToWait = uSecsPerFrame - uSecsPassed;
 
465
    if ( uSecsToWait > 0 )
 
466
        tDelay( uSecsToWait );
 
467
 
 
468
    // call glFinish to wait for GPU
 
469
    glFinish();
 
470
}
 
471
*/
 
472
 
 
473
rSysDep::rSwapMode rSysDep::swapMode_ = rSysDep::rSwap_glFlush;
 
474
//rSysDep::rSwapMode rSysDep::swapMode_ = rSysDep::rSwap_60Hz;
 
475
 
 
476
// buffer swap:
 
477
#ifndef DEDICATED
 
478
// for setting breakpoints in optimized mode, too
 
479
static void breakpoint(){}
 
480
 
 
481
static bool sr_netSyncThreadGoOn = true;
 
482
static rSysDep::rNetIdler * sr_netIdler = NULL;
 
483
int sr_NetSyncThread(void *lockVoid)
 
484
{
 
485
    SDL_mutex *lock = (SDL_mutex *)lockVoid;
 
486
 
 
487
    SDL_mutexP(lock);
 
488
 
 
489
    while ( sr_netSyncThreadGoOn )
 
490
    {
 
491
        SDL_mutexV(lock);
 
492
        // wait for network data
 
493
        bool toDo = sr_netIdler->Wait();
 
494
        SDL_mutexP(lock);
 
495
 
 
496
        if ( toDo )
 
497
        {
 
498
            // disable rendering (during auto-scrolling of console, for example)
 
499
            bool glout = sr_glOut;
 
500
            sr_glOut = false;
 
501
 
 
502
            // new network data arrived, handle it
 
503
            sr_netIdler->Do();
 
504
 
 
505
            // enable rendering again
 
506
            sr_glOut = glout;
 
507
        }
 
508
    }
 
509
 
 
510
    SDL_mutexV(lock);
 
511
 
 
512
    return 0;
 
513
}
 
514
 
 
515
static SDL_Thread * sr_netSyncThread = NULL;
 
516
static SDL_mutex * sr_netLock = NULL;
 
517
void rSysDep::StartNetSyncThread( rNetIdler * idler )
 
518
{
 
519
    sr_netIdler = idler;
 
520
 
 
521
    return;
 
522
 
 
523
    // can't use thrading trouble while recording
 
524
    if ( tRecorder::IsRunning() )
 
525
        return;
 
526
 
 
527
    if ( sr_netSyncThread )
 
528
        return;
 
529
 
 
530
    // create lock
 
531
    if ( !sr_netLock )
 
532
        sr_netLock = SDL_CreateMutex();
 
533
 
 
534
    // start thread
 
535
    sr_netSyncThread = SDL_CreateThread( sr_NetSyncThread, sr_netLock );
 
536
    if ( !sr_netSyncThread )
 
537
        return;
 
538
 
 
539
    // lock mutex, the thread should only do work while the main thread is waiting for the refresh
 
540
    SDL_mutexP( sr_netLock );
 
541
}
 
542
 
 
543
void rSysDep::StopNetSyncThread()
 
544
{
 
545
    // stop and delete thread
 
546
    if ( sr_netSyncThread )
 
547
    {
 
548
        SDL_mutexV(  sr_netLock );
 
549
        sr_netSyncThreadGoOn = false;
 
550
        SDL_WaitThread( sr_netSyncThread, NULL );
 
551
        sr_netSyncThread = NULL;
 
552
        sr_netIdler = NULL;
 
553
    }
 
554
 
 
555
    // delete lock
 
556
    if ( sr_netLock )
 
557
    {
 
558
        SDL_DestroyMutex( sr_netLock );
 
559
        sr_netLock = NULL;
 
560
    }
 
561
}
 
562
 
 
563
void rSysDep::SwapGL(){
 
564
    if ( s_benchmark )
 
565
    {
 
566
        static PerformanceCounter counter;
 
567
        counter.Count();
 
568
    }
 
569
 
 
570
    double time = tSysTimeFloat();
 
571
    double realTime = tRealSysTimeFloat();
 
572
 
 
573
    bool next_glOut = sr_glOut;
 
574
 
 
575
    // adapt playback speed to recorded speed
 
576
    if ( !s_benchmark && !s_fastForward && tRecorder::IsPlayingBack() )
 
577
    {
 
578
        static double timeOffset=0;
 
579
        static double lastRendered=0;
 
580
 
 
581
        // calculate how much we're behind the rendering schedule
 
582
        double behind = - time + realTime + timeOffset;
 
583
        // std::cout << behind << " " << sr_glOut << "\n";
 
584
 
 
585
        // large delays can only be caused by breakpoints or map downloads; ignore them
 
586
        if ( behind > .5 || realTime > lastRendered + .2 )
 
587
        {
 
588
            timeOffset -= behind;
 
589
            next_glOut = true;
 
590
        }
 
591
        else
 
592
        {
 
593
            // we're a bit behind, skip the next frame
 
594
            if ( behind > .1 )
 
595
            {
 
596
                next_glOut = false;
 
597
            }
 
598
            else if ( sr_glOut )
 
599
            {
 
600
                lastRendered=realTime;
 
601
                // we're ahead, pause a bit
 
602
                if  ( behind < -.5 )
 
603
                    timeOffset -= behind;
 
604
                else if ( behind < -.1 )
 
605
                {
 
606
                    int delay = int( -( behind + .1 ) * 1000000 );
 
607
                    // std::cout << behind << ":" << delay << "\n";
 
608
                    tDelayForce( delay );
 
609
                }
 
610
            }
 
611
            else
 
612
            {
 
613
                // we're not behind any more. Reactivate rendering.
 
614
                next_glOut = true;
 
615
            }
 
616
        }
 
617
 
 
618
        if ( next_glOut )
 
619
            lastRendered=realTime;
 
620
    }
 
621
 
 
622
    if (!sr_glOut)
 
623
    {
 
624
        // display next frame in fast foward mode
 
625
        if ( s_fastForward && ( time > s_nextFastForwardFrameRecorded || realTime > s_nextFastForwardFrameReal ) || next_glOut )
 
626
        {
 
627
            sr_glOut = true;
 
628
            rSysDep::ClearGL();
 
629
        }
 
630
 
 
631
        // in playback or recording mode, always execute frame tasks, they may be improtant for consistency
 
632
        if ( tRecorder::IsRunning() )
 
633
            rPerFrameTask::DoPerFrameTasks();
 
634
 
 
635
        return;
 
636
    }
 
637
 
 
638
 
 
639
    rPerFrameTask::DoPerFrameTasks();
 
640
 
 
641
    // unlock the mutex while waiting for the swap operation to finish
 
642
    SDL_mutexV(  sr_netLock );
 
643
    sr_LockSDL();
 
644
 
 
645
    switch( swapMode_ )
 
646
    {
 
647
    case rSwap_Fastest:
 
648
        break;
 
649
    case rSwap_glFlush:
 
650
        glFlush();
 
651
        break;
 
652
    case rSwap_glFinish:
 
653
        glFinish();
 
654
        break;
 
655
    }
 
656
 
 
657
#if defined(SDL_OPENGL)
 
658
    if (lastSuccess.useSDL)
 
659
        SDL_GL_SwapBuffers();
 
660
    //#elif defined(HAVE_FXMESA)
 
661
    //fxMesaSwapBuffers();
 
662
#endif
 
663
 
 
664
#ifdef DIRTY
 
665
    if (!lastSuccess.useSDL){
 
666
#if defined(WIN32)
 
667
        SwapBuffers( hDC );
 
668
#elif defined(unix) || defined(__unix__)
 
669
        glXSwapBuffers(dpy,win);
 
670
#endif
 
671
    }
 
672
#endif
 
673
 
 
674
    if (sr_screenshotIsPlanned){
 
675
        make_screenshot();
 
676
        sr_screenshotIsPlanned=false;
 
677
    }
 
678
 
 
679
    sr_UnlockSDL();
 
680
    // lock mutex again
 
681
    SDL_mutexP(  sr_netLock );
 
682
 
 
683
 
 
684
    // disable output in fast forward mode
 
685
    if ( s_fastForward && tRecorder::IsPlayingBack() )
 
686
    {
 
687
        if ( time < s_fastForwardTo )
 
688
        {
 
689
            // next displayed frame should be ten percent closer to the target, but at most 10 seconds
 
690
            s_nextFastForwardFrameRecorded = ( s_fastForwardTo - time ) * sr_FF_MaxstepRel;
 
691
            if ( s_nextFastForwardFrameRecorded > sr_FF_Maxstep )
 
692
                s_nextFastForwardFrameRecorded = sr_FF_Maxstep ;
 
693
            s_nextFastForwardFrameRecorded += time;
 
694
            s_nextFastForwardFrameReal = realTime + sr_FF_MaxstepReal ;
 
695
 
 
696
            next_glOut = false;
 
697
        }
 
698
        else
 
699
        {
 
700
            std::cout << "End of fast forward mode.\n";
 
701
            st_Breakpoint();
 
702
            s_fastForward = false;
 
703
        }
 
704
    }
 
705
 
 
706
    //#ifdef DEBUG
 
707
    if ( !s_fastForward )
 
708
    {
 
709
        breakpoint();
 
710
    }
 
711
    //#endif
 
712
 
 
713
    // store frame time for next frame
 
714
    // lastFrame = tRealSysTimeFloat();
 
715
 
 
716
    sr_glOut = next_glOut;
 
717
}
 
718
#endif // dedicated
 
719
 
 
720
#ifndef DEDICATED
 
721
static SDL_mutex *mut;
 
722
 
 
723
static void stuff_init(){
 
724
    mut=SDL_CreateMutex();
 
725
}
 
726
 
 
727
static tInitExit stuff_ie(&stuff_init);
 
728
#endif
 
729
 
 
730
void sr_LockSDL(){
 
731
    //std::cerr << "locking...";
 
732
#ifndef DEDICATED
 
733
#ifndef WIN32
 
734
    //SDL_mutexP(mut);
 
735
#endif
 
736
#endif
 
737
    //std::cerr << " locked!\n";
 
738
}
 
739
 
 
740
void sr_UnlockSDL(){
 
741
    //std::cerr << "unlocking...";
 
742
#ifndef DEDICATED
 
743
#ifndef WIN32
 
744
    //SDL_mutexV(mut);
 
745
#endif
 
746
#endif
 
747
    //std::cerr << " unlocked!\n";
 
748
}
 
749
 
 
750
#ifndef DEDICATED
 
751
void  rSysDep::ClearGL(){
 
752
    if (sr_glOut){
 
753
 
 
754
        /*
 
755
        if (sr_screenshotIsPlanned){
 
756
          make_screenshot();
 
757
          sr_screenshotIsPlanned=false;
 
758
        }
 
759
        */
 
760
 
 
761
        glClearColor(0.0,0.0,0.0,1.0);
 
762
        glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
 
763
    }
 
764
}
 
765
#endif
 
766
 
 
767