~x3lectric/xbmc/svn-trunk

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
#pragma once
/*
 *      Copyright (C) 2005-2008 Team XBMC
 *      http://www.xbmc.org
 *
 *  This Program is free software; you can redistribute it and/or modify
 *  it under the terms of the GNU General Public License as published by
 *  the Free Software Foundation; either version 2, or (at your option)
 *  any later version.
 *
 *  This Program is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
 *  GNU General Public License for more details.
 *
 *  You should have received a copy of the GNU General Public License
 *  along with XBMC; see the file COPYING.  If not, write to
 *  the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
 *  http://www.gnu.org/copyleft/gpl.html
 *
 */

#include "system.h" // for HAS_XRANDR, and Win32 types
#include "Thread.h"
#include "utils/CriticalSection.h"

//TODO: get rid of #ifdef hell, abstract implementations in separate classes

#if defined(HAS_GLX) && defined(HAS_XRANDR)
  #include <X11/X.h>
  #include <X11/Xlib.h>
  #include <GL/glx.h>
#elif defined(_WIN32) && defined(HAS_DX)
  #include <d3d9.h>
  #include "D3DResource.h"

class CD3DCallback : public ID3DResource
{
  public:
    void Reset();
    void OnDestroyDevice();
    void OnCreateDevice();
    void Aquire();
    void Release();
    bool IsValid();

  private:
    bool m_devicevalid;
    bool m_deviceused;

    CCriticalSection m_critsection;
    CEvent           m_createevent;
    CEvent           m_releaseevent;
};

#endif

class CVideoReferenceClock : public CThread
{
  public:
    CVideoReferenceClock();

    int64_t GetTime();
    int64_t GetFrequency();
    void    SetSpeed(double Speed);
    double  GetSpeed();
    int     GetRefreshRate();
    int64_t Wait(int64_t Target);
    bool    WaitStarted(int MSecs);
    bool    GetClockInfo(int& MissedVblanks, double& ClockSpeed, int& RefreshRate);

#if defined(__APPLE__)
    void VblankHandler(int64_t nowtime, double fps);
#endif

  private:
    void    Process();
    bool    UpdateRefreshrate(bool Forced = false);
    void    SendVblankSignal();
    void    UpdateClock(int NrVBlanks, bool CheckMissed);
    int64_t TimeOfNextVblank();

    int64_t m_CurrTime;          //the current time of the clock when using vblank as clock source
    int64_t m_AdjustedFrequency; //the frequency of the clock set by dvdplayer
    int64_t m_ClockOffset;       //the difference between the vblank clock and systemclock, set when vblank clock is stopped
    int64_t m_LastRefreshTime;   //last time we updated the refreshrate
    int64_t m_SystemFrequency;   //frequency of the systemclock

    bool    m_UseVblank;         //set to true when vblank is used as clock source
    int64_t m_RefreshRate;       //current refreshrate
    int     m_PrevRefreshRate;   //previous refreshrate, used for log printing and getting refreshrate from nvidia-settings
    int     m_MissedVblanks;     //number of clock updates missed by the vblank clock
    int     m_TotalMissedVblanks;//total number of clock updates missed, used by codec information screen
    int64_t m_VblankTime;        //last time the clock was updated when using vblank as clock

    CEvent  m_Started;            //set when the vblank clock is started
    CEvent  m_VblankEvent;        //set when a vblank happens

    CCriticalSection m_CritSection;

#if defined(HAS_GLX) && defined(HAS_XRANDR)
    bool SetupGLX();
    void RunGLX();
    void CleanupGLX();
    bool ParseNvSettings(int& RefreshRate);
    int  GetRandRRate();

    int  (*m_glXWaitVideoSyncSGI) (int, int, unsigned int*);
    int  (*m_glXGetVideoSyncSGI)  (unsigned int*);

    Display*     m_Dpy;
    XVisualInfo *m_vInfo;
    Window       m_Window;
    GLXContext   m_Context;
    int          m_RREventBase;

    bool         m_UseNvSettings;

#elif defined(_WIN32) && defined(HAS_DX)
    bool   SetupD3D();
    double MeasureRefreshrate(int MSecs);
    void   RunD3D();
    void   CleanupD3D();

    LPDIRECT3DDEVICE9 m_D3dDev;
    CD3DCallback      m_D3dCallback;

    unsigned int  m_Width;
    unsigned int  m_Height;

#elif defined(__APPLE__)
    bool SetupCocoa();
    void RunCocoa();
    void CleanupCocoa();

    int64_t m_LastVBlankTime;  //timestamp of the last vblank, used for calculating how many vblanks happened
                               //not the same as m_VblankTime
#endif
};

extern CVideoReferenceClock g_VideoReferenceClock;