Some compiler warnings and eol-style.

git-svn-id: https://dolphin-emu.googlecode.com/svn/trunk@6418 8ced0084-cf51-0410-be5f-012b33b47a6e
This commit is contained in:
Soren Jorvang 2010-11-14 23:56:26 +00:00
parent 0da42fcca7
commit 62a7f101a7
7 changed files with 717 additions and 717 deletions

View File

@ -1,48 +1,48 @@
// Copyright (C) 2003 Dolphin Project.
// 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, version 2.0.
// 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 2.0 for more details.
// A copy of the GPL 2.0 should have been included with the program.
// If not, see http://www.gnu.org/licenses/
// Official SVN repository and contact information can be found at
// http://code.google.com/p/dolphin-emu/
#include "AudioCommon.h"
#include "NullSoundStream.h"
void NullSound::SoundLoop()
{
}
bool NullSound::Start()
{
return true;
}
void NullSound::SetVolume(int volume)
{
}
void NullSound::Update()
{
// This should equal AUDIO_DMA_PERIOD. TODO: Fix after DSP merge
int numBytesToRender = 32000 * 4 / 32;
m_mixer->Mix(realtimeBuffer, numBytesToRender / 4);
}
void NullSound::Clear(bool mute)
{
m_muted = mute;
}
void NullSound::Stop()
{
}
// Copyright (C) 2003 Dolphin Project.
// 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, version 2.0.
// 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 2.0 for more details.
// A copy of the GPL 2.0 should have been included with the program.
// If not, see http://www.gnu.org/licenses/
// Official SVN repository and contact information can be found at
// http://code.google.com/p/dolphin-emu/
#include "AudioCommon.h"
#include "NullSoundStream.h"
void NullSound::SoundLoop()
{
}
bool NullSound::Start()
{
return true;
}
void NullSound::SetVolume(int volume)
{
}
void NullSound::Update()
{
// This should equal AUDIO_DMA_PERIOD. TODO: Fix after DSP merge
int numBytesToRender = 32000 * 4 / 32;
m_mixer->Mix(realtimeBuffer, numBytesToRender / 4);
}
void NullSound::Clear(bool mute)
{
m_muted = mute;
}
void NullSound::Stop()
{
}

View File

@ -1,48 +1,48 @@
// Copyright (C) 2003 Dolphin Project.
// 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, version 2.0.
// 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 2.0 for more details.
// A copy of the GPL 2.0 should have been included with the program.
// If not, see http://www.gnu.org/licenses/
// Official SVN repository and contact information can be found at
// http://code.google.com/p/dolphin-emu/
#ifndef _NULLSOUNDSTREAM_H_
#define _NULLSOUNDSTREAM_H_
#include "SoundStream.h"
#include "Thread.h"
#define BUF_SIZE (48000 * 4 / 32)
class NullSound : public SoundStream
{
// playback position
short realtimeBuffer[BUF_SIZE / sizeof(short)];
public:
NullSound(CMixer *mixer, void *hWnd = NULL)
: SoundStream(mixer)
{}
virtual ~NullSound() {}
virtual bool Start();
virtual void SoundLoop();
virtual void SetVolume(int volume);
virtual void Stop();
virtual void Clear(bool mute);
static bool isValid() { return true; }
virtual bool usesMixer() const { return true; }
virtual void Update();
};
#endif //_NULLSOUNDSTREAM_H_
// Copyright (C) 2003 Dolphin Project.
// 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, version 2.0.
// 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 2.0 for more details.
// A copy of the GPL 2.0 should have been included with the program.
// If not, see http://www.gnu.org/licenses/
// Official SVN repository and contact information can be found at
// http://code.google.com/p/dolphin-emu/
#ifndef _NULLSOUNDSTREAM_H_
#define _NULLSOUNDSTREAM_H_
#include "SoundStream.h"
#include "Thread.h"
#define BUF_SIZE (48000 * 4 / 32)
class NullSound : public SoundStream
{
// playback position
short realtimeBuffer[BUF_SIZE / sizeof(short)];
public:
NullSound(CMixer *mixer, void *hWnd = NULL)
: SoundStream(mixer)
{}
virtual ~NullSound() {}
virtual bool Start();
virtual void SoundLoop();
virtual void SetVolume(int volume);
virtual void Stop();
virtual void Clear(bool mute);
static bool isValid() { return true; }
virtual bool usesMixer() const { return true; }
virtual void Update();
};
#endif //_NULLSOUNDSTREAM_H_

View File

@ -1,211 +1,211 @@
// Copyright (C) 2003 Dolphin Project.
// 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, version 2.0.
// 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 2.0 for more details.
// A copy of the GPL 2.0 should have been included with the program.
// If not, see http://www.gnu.org/licenses/
// Official SVN repository and contact information can be found at
// http://code.google.com/p/dolphin-emu/
#include "AudioCommon.h"
#include "XAudio2Stream.h"
struct StreamingVoiceContext : public IXAudio2VoiceCallback
{
IXAudio2SourceVoice* pSourceVoice;
CMixer *m_mixer;
Common::EventEx *soundSyncEvent;
short *xaBuffer;
StreamingVoiceContext(IXAudio2 *pXAudio2, CMixer *pMixer, Common::EventEx *pSyncEvent)
{
m_mixer = pMixer;
soundSyncEvent = pSyncEvent;
WAVEFORMATEXTENSIBLE wfx;
memset(&wfx, 0, sizeof(WAVEFORMATEXTENSIBLE));
wfx.Format.wFormatTag = WAVE_FORMAT_EXTENSIBLE;
wfx.Format.nSamplesPerSec = m_mixer->GetSampleRate();
wfx.Format.nChannels = 2;
wfx.Format.wBitsPerSample = 16;
wfx.Format.nBlockAlign = wfx.Format.nChannels*wfx.Format.wBitsPerSample/8;
wfx.Format.nAvgBytesPerSec = wfx.Format.nSamplesPerSec * wfx.Format.nBlockAlign;
wfx.Format.cbSize = sizeof(WAVEFORMATEXTENSIBLE)-sizeof(WAVEFORMATEX);
wfx.Samples.wValidBitsPerSample = 16;
wfx.dwChannelMask = SPEAKER_FRONT_LEFT | SPEAKER_FRONT_RIGHT;
wfx.SubFormat = KSDATAFORMAT_SUBTYPE_PCM;
// create source voice
HRESULT hr;
if(FAILED(hr = pXAudio2->CreateSourceVoice(&pSourceVoice, (WAVEFORMATEX*)&wfx, XAUDIO2_VOICE_NOSRC, 1.0f, this)))
PanicAlert("XAudio2 CreateSourceVoice failed: %#X", hr);
pSourceVoice->FlushSourceBuffers();
pSourceVoice->Start();
xaBuffer = new s16[NUM_BUFFERS * BUFFER_SIZE];
memset(xaBuffer, 0, NUM_BUFFERS * BUFFER_SIZE_BYTES);
//start buffers with silence
for(int i=0; i < NUM_BUFFERS; i++)
{
XAUDIO2_BUFFER buf = {0};
buf.AudioBytes = BUFFER_SIZE_BYTES;
buf.pAudioData = (BYTE *) &xaBuffer[i * BUFFER_SIZE];
buf.pContext = (void *) buf.pAudioData;
pSourceVoice->SubmitSourceBuffer(&buf);
}
}
~StreamingVoiceContext()
{
IXAudio2SourceVoice* temp = pSourceVoice;
pSourceVoice = NULL;
temp->FlushSourceBuffers();
temp->DestroyVoice();
safe_delete_array(xaBuffer);
}
void StreamingVoiceContext::Stop() {
if (pSourceVoice)
pSourceVoice->Stop();
}
void StreamingVoiceContext::Play() {
if (pSourceVoice)
pSourceVoice->Start();
}
STDMETHOD_(void, OnVoiceError) (THIS_ void* pBufferContext, HRESULT Error) {}
STDMETHOD_(void, OnVoiceProcessingPassStart) (UINT32) {}
STDMETHOD_(void, OnVoiceProcessingPassEnd) () {}
STDMETHOD_(void, OnBufferStart) (void*) {}
STDMETHOD_(void, OnLoopEnd) (void*) {}
STDMETHOD_(void, OnStreamEnd) () {}
STDMETHOD_(void, OnBufferEnd) (void* context)
{ //
// buffer end callback; gets SAMPLES_PER_BUFFER samples for a new buffer
//
if( !pSourceVoice || !context) return;
//soundSyncEvent->Init();
//soundSyncEvent->Wait(); //sync
//soundSyncEvent->Spin(); //or tight sync
//if (!pSourceVoice) return;
m_mixer->Mix((short *)context, SAMPLES_PER_BUFFER);
XAUDIO2_BUFFER buf = {0};
buf.AudioBytes = BUFFER_SIZE_BYTES;
buf.pAudioData = (byte*)context;
buf.pContext = context;
pSourceVoice->SubmitSourceBuffer(&buf);
}
};
StreamingVoiceContext* pVoiceContext = 0;
bool XAudio2::Start()
{
//soundSyncEvent.Init();
// XAudio2 init
CoInitializeEx(NULL, COINIT_MULTITHREADED);
HRESULT hr;
if(FAILED(hr = XAudio2Create(&pXAudio2, 0, XAUDIO2_ANY_PROCESSOR))) //callback dosent seem to run on a speecific cpu anyways
{
PanicAlert("XAudio2 init failed: %#X", hr);
CoUninitialize();
return false;
}
// XAudio2 master voice
// XAUDIO2_DEFAULT_CHANNELS instead of 2 for expansion?
if(FAILED(hr = pXAudio2->CreateMasteringVoice(&pMasteringVoice, 2, m_mixer->GetSampleRate())))
{
PanicAlert("XAudio2 master voice creation failed: %#X", hr);
safe_release(pXAudio2);
CoUninitialize();
return false;
}
// Volume
if (pMasteringVoice)
pMasteringVoice->SetVolume(m_volume);
if (pXAudio2)
pVoiceContext = new StreamingVoiceContext(pXAudio2, m_mixer, &soundSyncEvent);
return true;
}
void XAudio2::SetVolume(int volume)
{
//linear 1- .01
m_volume = (float)volume / 100.0;
if (pMasteringVoice)
pMasteringVoice->SetVolume(m_volume);
}
//XAUDIO2_PERFORMANCE_DATA perfData;
//int xi = 0;
void XAudio2::Update()
{
//soundSyncEvent.Set();
//xi++;
//if (xi == 100000) {
// xi = 0;
// pXAudio2->GetPerformanceData(&perfData);
// NOTICE_LOG(DSPHLE, "XAudio2 latency (samples): %i",perfData.CurrentLatencyInSamples);
// NOTICE_LOG(DSPHLE, "XAudio2 total glitches: %i",perfData.GlitchesSinceEngineStarted);
//}
}
void XAudio2::Clear(bool mute)
{
m_muted = mute;
if (pVoiceContext)
{
if (m_muted)
pVoiceContext->Stop();
else
pVoiceContext->Play();
}
}
void XAudio2::Stop()
{
//soundSyncEvent.Set();
safe_delete(pVoiceContext);
pVoiceContext = NULL;
if(pMasteringVoice)
pMasteringVoice->DestroyVoice();
safe_release(pXAudio2);
pMasteringVoice = NULL;
CoUninitialize();
//soundSyncEvent.Shutdown();
}
// Copyright (C) 2003 Dolphin Project.
// 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, version 2.0.
// 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 2.0 for more details.
// A copy of the GPL 2.0 should have been included with the program.
// If not, see http://www.gnu.org/licenses/
// Official SVN repository and contact information can be found at
// http://code.google.com/p/dolphin-emu/
#include "AudioCommon.h"
#include "XAudio2Stream.h"
struct StreamingVoiceContext : public IXAudio2VoiceCallback
{
IXAudio2SourceVoice* pSourceVoice;
CMixer *m_mixer;
Common::EventEx *soundSyncEvent;
short *xaBuffer;
StreamingVoiceContext(IXAudio2 *pXAudio2, CMixer *pMixer, Common::EventEx *pSyncEvent)
{
m_mixer = pMixer;
soundSyncEvent = pSyncEvent;
WAVEFORMATEXTENSIBLE wfx;
memset(&wfx, 0, sizeof(WAVEFORMATEXTENSIBLE));
wfx.Format.wFormatTag = WAVE_FORMAT_EXTENSIBLE;
wfx.Format.nSamplesPerSec = m_mixer->GetSampleRate();
wfx.Format.nChannels = 2;
wfx.Format.wBitsPerSample = 16;
wfx.Format.nBlockAlign = wfx.Format.nChannels*wfx.Format.wBitsPerSample/8;
wfx.Format.nAvgBytesPerSec = wfx.Format.nSamplesPerSec * wfx.Format.nBlockAlign;
wfx.Format.cbSize = sizeof(WAVEFORMATEXTENSIBLE)-sizeof(WAVEFORMATEX);
wfx.Samples.wValidBitsPerSample = 16;
wfx.dwChannelMask = SPEAKER_FRONT_LEFT | SPEAKER_FRONT_RIGHT;
wfx.SubFormat = KSDATAFORMAT_SUBTYPE_PCM;
// create source voice
HRESULT hr;
if(FAILED(hr = pXAudio2->CreateSourceVoice(&pSourceVoice, (WAVEFORMATEX*)&wfx, XAUDIO2_VOICE_NOSRC, 1.0f, this)))
PanicAlert("XAudio2 CreateSourceVoice failed: %#X", hr);
pSourceVoice->FlushSourceBuffers();
pSourceVoice->Start();
xaBuffer = new s16[NUM_BUFFERS * BUFFER_SIZE];
memset(xaBuffer, 0, NUM_BUFFERS * BUFFER_SIZE_BYTES);
//start buffers with silence
for(int i=0; i < NUM_BUFFERS; i++)
{
XAUDIO2_BUFFER buf = {0};
buf.AudioBytes = BUFFER_SIZE_BYTES;
buf.pAudioData = (BYTE *) &xaBuffer[i * BUFFER_SIZE];
buf.pContext = (void *) buf.pAudioData;
pSourceVoice->SubmitSourceBuffer(&buf);
}
}
~StreamingVoiceContext()
{
IXAudio2SourceVoice* temp = pSourceVoice;
pSourceVoice = NULL;
temp->FlushSourceBuffers();
temp->DestroyVoice();
safe_delete_array(xaBuffer);
}
void StreamingVoiceContext::Stop() {
if (pSourceVoice)
pSourceVoice->Stop();
}
void StreamingVoiceContext::Play() {
if (pSourceVoice)
pSourceVoice->Start();
}
STDMETHOD_(void, OnVoiceError) (THIS_ void* pBufferContext, HRESULT Error) {}
STDMETHOD_(void, OnVoiceProcessingPassStart) (UINT32) {}
STDMETHOD_(void, OnVoiceProcessingPassEnd) () {}
STDMETHOD_(void, OnBufferStart) (void*) {}
STDMETHOD_(void, OnLoopEnd) (void*) {}
STDMETHOD_(void, OnStreamEnd) () {}
STDMETHOD_(void, OnBufferEnd) (void* context)
{ //
// buffer end callback; gets SAMPLES_PER_BUFFER samples for a new buffer
//
if( !pSourceVoice || !context) return;
//soundSyncEvent->Init();
//soundSyncEvent->Wait(); //sync
//soundSyncEvent->Spin(); //or tight sync
//if (!pSourceVoice) return;
m_mixer->Mix((short *)context, SAMPLES_PER_BUFFER);
XAUDIO2_BUFFER buf = {0};
buf.AudioBytes = BUFFER_SIZE_BYTES;
buf.pAudioData = (byte*)context;
buf.pContext = context;
pSourceVoice->SubmitSourceBuffer(&buf);
}
};
StreamingVoiceContext* pVoiceContext = 0;
bool XAudio2::Start()
{
//soundSyncEvent.Init();
// XAudio2 init
CoInitializeEx(NULL, COINIT_MULTITHREADED);
HRESULT hr;
if(FAILED(hr = XAudio2Create(&pXAudio2, 0, XAUDIO2_ANY_PROCESSOR))) //callback dosent seem to run on a speecific cpu anyways
{
PanicAlert("XAudio2 init failed: %#X", hr);
CoUninitialize();
return false;
}
// XAudio2 master voice
// XAUDIO2_DEFAULT_CHANNELS instead of 2 for expansion?
if(FAILED(hr = pXAudio2->CreateMasteringVoice(&pMasteringVoice, 2, m_mixer->GetSampleRate())))
{
PanicAlert("XAudio2 master voice creation failed: %#X", hr);
safe_release(pXAudio2);
CoUninitialize();
return false;
}
// Volume
if (pMasteringVoice)
pMasteringVoice->SetVolume(m_volume);
if (pXAudio2)
pVoiceContext = new StreamingVoiceContext(pXAudio2, m_mixer, &soundSyncEvent);
return true;
}
void XAudio2::SetVolume(int volume)
{
//linear 1- .01
m_volume = (float)volume / 100.0;
if (pMasteringVoice)
pMasteringVoice->SetVolume(m_volume);
}
//XAUDIO2_PERFORMANCE_DATA perfData;
//int xi = 0;
void XAudio2::Update()
{
//soundSyncEvent.Set();
//xi++;
//if (xi == 100000) {
// xi = 0;
// pXAudio2->GetPerformanceData(&perfData);
// NOTICE_LOG(DSPHLE, "XAudio2 latency (samples): %i",perfData.CurrentLatencyInSamples);
// NOTICE_LOG(DSPHLE, "XAudio2 total glitches: %i",perfData.GlitchesSinceEngineStarted);
//}
}
void XAudio2::Clear(bool mute)
{
m_muted = mute;
if (pVoiceContext)
{
if (m_muted)
pVoiceContext->Stop();
else
pVoiceContext->Play();
}
}
void XAudio2::Stop()
{
//soundSyncEvent.Set();
safe_delete(pVoiceContext);
pVoiceContext = NULL;
if(pMasteringVoice)
pMasteringVoice->DestroyVoice();
safe_release(pXAudio2);
pMasteringVoice = NULL;
CoUninitialize();
//soundSyncEvent.Shutdown();
}

View File

@ -1,86 +1,86 @@
// Copyright (C) 2003 Dolphin Project.
// 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, version 2.0.
// 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 2.0 for more details.
// A copy of the GPL 2.0 should have been included with the program.
// If not, see http://www.gnu.org/licenses/
// Official SVN repository and contact information can be found at
// http://code.google.com/p/dolphin-emu/
#ifndef _XAUDIO2STREAM_H_
#define _XAUDIO2STREAM_H_
#include "SoundStream.h"
#ifdef _WIN32
#include "Thread.h"
#include <xaudio2.h>
const int NUM_BUFFERS = 3;
const int SAMPLES_PER_BUFFER = 96;
const int NUM_CHANNELS = 2;
const int BUFFER_SIZE = SAMPLES_PER_BUFFER * NUM_CHANNELS;
const int BUFFER_SIZE_BYTES = BUFFER_SIZE * sizeof(s16);
#ifndef safe_delete_array
#define safe_delete_array(p) { if(p) { delete[] (p); (p)=NULL; } }
#endif
#ifndef safe_delete
#define safe_delete(a) if( (a) != NULL ) delete (a); (a) = NULL;
#endif
#ifndef safe_release
#define safe_release(p) { if(p) { (p)->Release(); (p)=NULL; } }
#endif
#endif
class XAudio2 : public SoundStream
{
#ifdef _WIN32
IXAudio2 *pXAudio2;
IXAudio2MasteringVoice *pMasteringVoice;
IXAudio2SourceVoice *pSourceVoice;
Common::EventEx soundSyncEvent;
float m_volume;
bool Init();
public:
XAudio2(CMixer *mixer)
: SoundStream(mixer),
pXAudio2(0),
pMasteringVoice(0),
pSourceVoice(0),
m_volume(1.0f) {}
virtual ~XAudio2() {}
virtual bool Start();
virtual void SetVolume(int volume);
virtual void Stop();
virtual void Clear(bool mute);
static bool isValid() { return true; }
virtual bool usesMixer() const { return true; }
virtual void Update();
#else
public:
XAudio2(CMixer *mixer, void *hWnd = NULL)
: SoundStream(mixer)
{}
#endif
};
#endif //_XAUDIO2STREAM_H_
// Copyright (C) 2003 Dolphin Project.
// 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, version 2.0.
// 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 2.0 for more details.
// A copy of the GPL 2.0 should have been included with the program.
// If not, see http://www.gnu.org/licenses/
// Official SVN repository and contact information can be found at
// http://code.google.com/p/dolphin-emu/
#ifndef _XAUDIO2STREAM_H_
#define _XAUDIO2STREAM_H_
#include "SoundStream.h"
#ifdef _WIN32
#include "Thread.h"
#include <xaudio2.h>
const int NUM_BUFFERS = 3;
const int SAMPLES_PER_BUFFER = 96;
const int NUM_CHANNELS = 2;
const int BUFFER_SIZE = SAMPLES_PER_BUFFER * NUM_CHANNELS;
const int BUFFER_SIZE_BYTES = BUFFER_SIZE * sizeof(s16);
#ifndef safe_delete_array
#define safe_delete_array(p) { if(p) { delete[] (p); (p)=NULL; } }
#endif
#ifndef safe_delete
#define safe_delete(a) if( (a) != NULL ) delete (a); (a) = NULL;
#endif
#ifndef safe_release
#define safe_release(p) { if(p) { (p)->Release(); (p)=NULL; } }
#endif
#endif
class XAudio2 : public SoundStream
{
#ifdef _WIN32
IXAudio2 *pXAudio2;
IXAudio2MasteringVoice *pMasteringVoice;
IXAudio2SourceVoice *pSourceVoice;
Common::EventEx soundSyncEvent;
float m_volume;
bool Init();
public:
XAudio2(CMixer *mixer)
: SoundStream(mixer),
pXAudio2(0),
pMasteringVoice(0),
pSourceVoice(0),
m_volume(1.0f) {}
virtual ~XAudio2() {}
virtual bool Start();
virtual void SetVolume(int volume);
virtual void Stop();
virtual void Clear(bool mute);
static bool isValid() { return true; }
virtual bool usesMixer() const { return true; }
virtual void Update();
#else
public:
XAudio2(CMixer *mixer, void *hWnd = NULL)
: SoundStream(mixer)
{}
#endif
};
#endif //_XAUDIO2STREAM_H_

View File

@ -224,23 +224,23 @@ inline u64 CreateMapId(u32 address, u32 size)
inline u64 CreateVMapId(u8 VATUSED)
{
u64 vmat_id = 0;
u64 vmap_id = 0;
for(int i = 0; i < 8 ; i++)
{
if(VATUSED & (1 << i))
{
//vmat_id ^= GetHash64((u8*)(&g_VtxAttr[i].g0.),sizeof(VAT),0);
if(vmat_id != 0)
//vmap_id ^= GetHash64((u8*)(&g_VtxAttr[i].g0.),sizeof(VAT),0);
if(vmap_id != 0)
{
vmat_id ^= (((u64)g_VtxAttr[i].g0.Hex) | (((u64)g_VtxAttr[i].g1.Hex) << 32)) ^ (((u64)g_VtxAttr[i].g2.Hex) << 16);
vmap_id ^= (((u64)g_VtxAttr[i].g0.Hex) | (((u64)g_VtxAttr[i].g1.Hex) << 32)) ^ (((u64)g_VtxAttr[i].g2.Hex) << 16);
}
else
{
vmat_id = (((u64)g_VtxAttr[i].g0.Hex) | (((u64)g_VtxAttr[i].g1.Hex) << 32)) ^ (((u64)g_VtxAttr[i].g2.Hex) << 16);
vmap_id = (((u64)g_VtxAttr[i].g0.Hex) | (((u64)g_VtxAttr[i].g1.Hex) << 32)) ^ (((u64)g_VtxAttr[i].g2.Hex) << 16);
}
}
}
return vmat_id;
return vmap_id;
}
typedef std::map<u64, CachedDisplayList> DLMap;
@ -689,7 +689,6 @@ bool HandleDisplayList(u32 address, u32 size)
if (Parentiter != DLCache::dl_map.end())
{
vhash = DLCache::CreateVMapId(Parentiter->second.VATUsed);
DLCache::VDlist &tvdl = Parentiter->second;
iter = Parentiter->second.dl_map.find(vhash);
childexist = iter != Parentiter->second.dl_map.end();
}

View File

@ -1,225 +1,226 @@
#include "FramebufferManagerBase.h"
#include "Render.h"
#include "VideoConfig.h"
FramebufferManagerBase *g_framebuffer_manager;
XFBSourceBase *FramebufferManagerBase::m_realXFBSource; // Only used in Real XFB mode
FramebufferManagerBase::VirtualXFBListType FramebufferManagerBase::m_virtualXFBList; // Only used in Virtual XFB mode
const XFBSourceBase* FramebufferManagerBase::m_overlappingXFBArray[MAX_VIRTUAL_XFB];
FramebufferManagerBase::FramebufferManagerBase()
{
m_realXFBSource = NULL;
// can't hurt
memset(m_overlappingXFBArray, 0, sizeof(m_overlappingXFBArray));
}
FramebufferManagerBase::~FramebufferManagerBase()
{
VirtualXFBListType::iterator
it = m_virtualXFBList.begin(),
vlend = m_virtualXFBList.end();
for (; it != vlend; ++it)
delete it->xfbSource;
m_virtualXFBList.clear();
delete m_realXFBSource;
}
const XFBSourceBase* const* FramebufferManagerBase::GetXFBSource(u32 xfbAddr, u32 fbWidth, u32 fbHeight, u32 &xfbCount)
{
if (g_ActiveConfig.bUseRealXFB)
return GetRealXFBSource(xfbAddr, fbWidth, fbHeight, xfbCount);
else
return GetVirtualXFBSource(xfbAddr, fbWidth, fbHeight, xfbCount);
}
const XFBSourceBase* const* FramebufferManagerBase::GetRealXFBSource(u32 xfbAddr, u32 fbWidth, u32 fbHeight, u32 &xfbCount)
{
xfbCount = 1;
if (!m_realXFBSource)
m_realXFBSource = g_framebuffer_manager->CreateXFBSource(fbWidth, fbHeight);
m_realXFBSource->srcAddr = xfbAddr;
m_realXFBSource->srcWidth = MAX_XFB_WIDTH;
m_realXFBSource->srcHeight = MAX_XFB_HEIGHT;
m_realXFBSource->texWidth = fbWidth;
m_realXFBSource->texHeight = fbHeight;
// TODO: stuff only used by OGL... :/
// OpenGL texture coordinates originate at the lower left, which is why
// sourceRc.top = fbHeight and sourceRc.bottom = 0.
m_realXFBSource->sourceRc.left = 0;
m_realXFBSource->sourceRc.top = fbHeight;
m_realXFBSource->sourceRc.right = fbWidth;
m_realXFBSource->sourceRc.bottom = 0;
// Decode YUYV data from GameCube RAM
m_realXFBSource->DecodeToTexture(xfbAddr, fbWidth, fbHeight);
m_overlappingXFBArray[0] = m_realXFBSource;
return &m_overlappingXFBArray[0];
}
const XFBSourceBase* const* FramebufferManagerBase::GetVirtualXFBSource(u32 xfbAddr, u32 fbWidth, u32 fbHeight, u32 &xfbCount)
{
xfbCount = 0;
if (m_virtualXFBList.empty()) // no Virtual XFBs available
return NULL;
u32 srcLower = xfbAddr;
u32 srcUpper = xfbAddr + 2 * fbWidth * fbHeight;
VirtualXFBListType::reverse_iterator
it = m_virtualXFBList.rbegin(),
vlend = m_virtualXFBList.rend();
for (; it != vlend; ++it)
{
VirtualXFB* vxfb = &*it;
u32 dstLower = vxfb->xfbAddr;
u32 dstUpper = vxfb->xfbAddr + 2 * vxfb->xfbWidth * vxfb->xfbHeight;
if (addrRangesOverlap(srcLower, srcUpper, dstLower, dstUpper))
{
m_overlappingXFBArray[xfbCount] = vxfb->xfbSource;
++xfbCount;
}
}
return &m_overlappingXFBArray[0];
}
void FramebufferManagerBase::CopyToXFB(u32 xfbAddr, u32 fbWidth, u32 fbHeight, const EFBRectangle& sourceRc)
{
if (g_ActiveConfig.bUseRealXFB)
g_framebuffer_manager->CopyToRealXFB(xfbAddr, fbWidth, fbHeight, sourceRc);
else
CopyToVirtualXFB(xfbAddr, fbWidth, fbHeight, sourceRc);
}
void FramebufferManagerBase::CopyToVirtualXFB(u32 xfbAddr, u32 fbWidth, u32 fbHeight, const EFBRectangle& sourceRc)
{
VirtualXFBListType::iterator vxfb = FindVirtualXFB(xfbAddr, fbWidth, fbHeight);
if (m_virtualXFBList.end() == vxfb)
{
if (m_virtualXFBList.size() < MAX_VIRTUAL_XFB)
{
// create a new Virtual XFB and place it at the front of the list
VirtualXFB v;
m_virtualXFBList.push_front(v);
vxfb = m_virtualXFBList.begin();
}
else
{
// Replace the last virtual XFB
--vxfb;
}
}
//else // replace existing virtual XFB
// move this Virtual XFB to the front of the list.
if (m_virtualXFBList.begin() != vxfb)
m_virtualXFBList.splice(m_virtualXFBList.begin(), m_virtualXFBList, vxfb);
unsigned int target_width, target_height;
g_framebuffer_manager->GetTargetSize(&target_width, &target_height, sourceRc);
// recreate if needed
if (vxfb->xfbSource && (vxfb->xfbSource->texWidth != target_width || vxfb->xfbSource->texHeight != target_height))
{
//delete vxfb->xfbSource;
//vxfb->xfbSource = NULL;
}
if (!vxfb->xfbSource)
{
vxfb->xfbSource = g_framebuffer_manager->CreateXFBSource(target_width, target_height);
vxfb->xfbSource->texWidth = target_width;
vxfb->xfbSource->texHeight = target_height;
}
vxfb->xfbSource->srcAddr = vxfb->xfbAddr = xfbAddr;
vxfb->xfbSource->srcWidth = vxfb->xfbWidth = fbWidth;
vxfb->xfbSource->srcHeight = vxfb->xfbHeight = fbHeight;
vxfb->xfbSource->sourceRc = Renderer::ConvertEFBRectangle(sourceRc);
// keep stale XFB data from being used
ReplaceVirtualXFB();
Renderer::ResetAPIState(); // reset any game specific settings
// Copy EFB data to XFB and restore render target again
vxfb->xfbSource->CopyEFB();
Renderer::RestoreAPIState();
}
FramebufferManagerBase::VirtualXFBListType::iterator FramebufferManagerBase::FindVirtualXFB(u32 xfbAddr, u32 width, u32 height)
{
const u32 srcLower = xfbAddr;
const u32 srcUpper = xfbAddr + 2 * width * height;
VirtualXFBListType::iterator it = m_virtualXFBList.begin();
for (; it != m_virtualXFBList.end(); ++it)
{
const u32 dstLower = it->xfbAddr;
const u32 dstUpper = it->xfbAddr + 2 * it->xfbWidth * it->xfbHeight;
if (dstLower >= srcLower && dstUpper <= srcUpper)
break;
}
return it;
}
void FramebufferManagerBase::ReplaceVirtualXFB()
{
VirtualXFBListType::iterator it = m_virtualXFBList.begin();
const s32 srcLower = it->xfbAddr;
const s32 srcUpper = it->xfbAddr + 2 * it->xfbWidth * it->xfbHeight;
const s32 lineSize = 2 * it->xfbWidth;
++it;
for (; it != m_virtualXFBList.end(); ++it)
{
s32 dstLower = it->xfbAddr;
s32 dstUpper = it->xfbAddr + 2 * it->xfbWidth * it->xfbHeight;
if (dstLower >= srcLower && dstUpper <= srcUpper)
{
// Invalidate the data
it->xfbAddr = 0;
it->xfbHeight = 0;
it->xfbWidth = 0;
}
else if (addrRangesOverlap(srcLower, srcUpper, dstLower, dstUpper))
{
s32 upperOverlap = (srcUpper - dstLower) / lineSize;
s32 lowerOverlap = (dstUpper - srcLower) / lineSize;
if (upperOverlap > 0 && lowerOverlap < 0)
{
it->xfbAddr += lineSize * upperOverlap;
it->xfbHeight -= upperOverlap;
}
else if (lowerOverlap > 0)
{
it->xfbHeight -= lowerOverlap;
}
}
}
}
#include "FramebufferManagerBase.h"
#include "Render.h"
#include "VideoConfig.h"
FramebufferManagerBase *g_framebuffer_manager;
XFBSourceBase *FramebufferManagerBase::m_realXFBSource; // Only used in Real XFB mode
FramebufferManagerBase::VirtualXFBListType FramebufferManagerBase::m_virtualXFBList; // Only used in Virtual XFB mode
const XFBSourceBase* FramebufferManagerBase::m_overlappingXFBArray[MAX_VIRTUAL_XFB];
FramebufferManagerBase::FramebufferManagerBase()
{
m_realXFBSource = NULL;
// can't hurt
memset(m_overlappingXFBArray, 0, sizeof(m_overlappingXFBArray));
}
FramebufferManagerBase::~FramebufferManagerBase()
{
VirtualXFBListType::iterator
it = m_virtualXFBList.begin(),
vlend = m_virtualXFBList.end();
for (; it != vlend; ++it)
delete it->xfbSource;
m_virtualXFBList.clear();
delete m_realXFBSource;
}
const XFBSourceBase* const* FramebufferManagerBase::GetXFBSource(u32 xfbAddr, u32 fbWidth, u32 fbHeight, u32 &xfbCount)
{
if (g_ActiveConfig.bUseRealXFB)
return GetRealXFBSource(xfbAddr, fbWidth, fbHeight, xfbCount);
else
return GetVirtualXFBSource(xfbAddr, fbWidth, fbHeight, xfbCount);
}
const XFBSourceBase* const* FramebufferManagerBase::GetRealXFBSource(u32 xfbAddr, u32 fbWidth, u32 fbHeight, u32 &xfbCount)
{
xfbCount = 1;
if (!m_realXFBSource)
m_realXFBSource = g_framebuffer_manager->CreateXFBSource(fbWidth, fbHeight);
m_realXFBSource->srcAddr = xfbAddr;
m_realXFBSource->srcWidth = MAX_XFB_WIDTH;
m_realXFBSource->srcHeight = MAX_XFB_HEIGHT;
m_realXFBSource->texWidth = fbWidth;
m_realXFBSource->texHeight = fbHeight;
// TODO: stuff only used by OGL... :/
// OpenGL texture coordinates originate at the lower left, which is why
// sourceRc.top = fbHeight and sourceRc.bottom = 0.
m_realXFBSource->sourceRc.left = 0;
m_realXFBSource->sourceRc.top = fbHeight;
m_realXFBSource->sourceRc.right = fbWidth;
m_realXFBSource->sourceRc.bottom = 0;
// Decode YUYV data from GameCube RAM
m_realXFBSource->DecodeToTexture(xfbAddr, fbWidth, fbHeight);
m_overlappingXFBArray[0] = m_realXFBSource;
return &m_overlappingXFBArray[0];
}
const XFBSourceBase* const* FramebufferManagerBase::GetVirtualXFBSource(u32 xfbAddr, u32 fbWidth, u32 fbHeight, u32 &xfbCount)
{
xfbCount = 0;
if (m_virtualXFBList.empty()) // no Virtual XFBs available
return NULL;
u32 srcLower = xfbAddr;
u32 srcUpper = xfbAddr + 2 * fbWidth * fbHeight;
VirtualXFBListType::reverse_iterator
it = m_virtualXFBList.rbegin(),
vlend = m_virtualXFBList.rend();
for (; it != vlend; ++it)
{
VirtualXFB* vxfb = &*it;
u32 dstLower = vxfb->xfbAddr;
u32 dstUpper = vxfb->xfbAddr + 2 * vxfb->xfbWidth * vxfb->xfbHeight;
if (addrRangesOverlap(srcLower, srcUpper, dstLower, dstUpper))
{
m_overlappingXFBArray[xfbCount] = vxfb->xfbSource;
++xfbCount;
}
}
return &m_overlappingXFBArray[0];
}
void FramebufferManagerBase::CopyToXFB(u32 xfbAddr, u32 fbWidth, u32 fbHeight, const EFBRectangle& sourceRc)
{
if (g_ActiveConfig.bUseRealXFB)
g_framebuffer_manager->CopyToRealXFB(xfbAddr, fbWidth, fbHeight, sourceRc);
else
CopyToVirtualXFB(xfbAddr, fbWidth, fbHeight, sourceRc);
}
void FramebufferManagerBase::CopyToVirtualXFB(u32 xfbAddr, u32 fbWidth, u32 fbHeight, const EFBRectangle& sourceRc)
{
VirtualXFBListType::iterator vxfb = FindVirtualXFB(xfbAddr, fbWidth, fbHeight);
if (m_virtualXFBList.end() == vxfb)
{
if (m_virtualXFBList.size() < MAX_VIRTUAL_XFB)
{
// create a new Virtual XFB and place it at the front of the list
VirtualXFB v;
memset(&v, 0, sizeof v);
m_virtualXFBList.push_front(v);
vxfb = m_virtualXFBList.begin();
}
else
{
// Replace the last virtual XFB
--vxfb;
}
}
//else // replace existing virtual XFB
// move this Virtual XFB to the front of the list.
if (m_virtualXFBList.begin() != vxfb)
m_virtualXFBList.splice(m_virtualXFBList.begin(), m_virtualXFBList, vxfb);
unsigned int target_width, target_height;
g_framebuffer_manager->GetTargetSize(&target_width, &target_height, sourceRc);
// recreate if needed
if (vxfb->xfbSource && (vxfb->xfbSource->texWidth != target_width || vxfb->xfbSource->texHeight != target_height))
{
//delete vxfb->xfbSource;
//vxfb->xfbSource = NULL;
}
if (!vxfb->xfbSource)
{
vxfb->xfbSource = g_framebuffer_manager->CreateXFBSource(target_width, target_height);
vxfb->xfbSource->texWidth = target_width;
vxfb->xfbSource->texHeight = target_height;
}
vxfb->xfbSource->srcAddr = vxfb->xfbAddr = xfbAddr;
vxfb->xfbSource->srcWidth = vxfb->xfbWidth = fbWidth;
vxfb->xfbSource->srcHeight = vxfb->xfbHeight = fbHeight;
vxfb->xfbSource->sourceRc = Renderer::ConvertEFBRectangle(sourceRc);
// keep stale XFB data from being used
ReplaceVirtualXFB();
Renderer::ResetAPIState(); // reset any game specific settings
// Copy EFB data to XFB and restore render target again
vxfb->xfbSource->CopyEFB();
Renderer::RestoreAPIState();
}
FramebufferManagerBase::VirtualXFBListType::iterator FramebufferManagerBase::FindVirtualXFB(u32 xfbAddr, u32 width, u32 height)
{
const u32 srcLower = xfbAddr;
const u32 srcUpper = xfbAddr + 2 * width * height;
VirtualXFBListType::iterator it = m_virtualXFBList.begin();
for (; it != m_virtualXFBList.end(); ++it)
{
const u32 dstLower = it->xfbAddr;
const u32 dstUpper = it->xfbAddr + 2 * it->xfbWidth * it->xfbHeight;
if (dstLower >= srcLower && dstUpper <= srcUpper)
break;
}
return it;
}
void FramebufferManagerBase::ReplaceVirtualXFB()
{
VirtualXFBListType::iterator it = m_virtualXFBList.begin();
const s32 srcLower = it->xfbAddr;
const s32 srcUpper = it->xfbAddr + 2 * it->xfbWidth * it->xfbHeight;
const s32 lineSize = 2 * it->xfbWidth;
++it;
for (; it != m_virtualXFBList.end(); ++it)
{
s32 dstLower = it->xfbAddr;
s32 dstUpper = it->xfbAddr + 2 * it->xfbWidth * it->xfbHeight;
if (dstLower >= srcLower && dstUpper <= srcUpper)
{
// Invalidate the data
it->xfbAddr = 0;
it->xfbHeight = 0;
it->xfbWidth = 0;
}
else if (addrRangesOverlap(srcLower, srcUpper, dstLower, dstUpper))
{
s32 upperOverlap = (srcUpper - dstLower) / lineSize;
s32 lowerOverlap = (dstUpper - srcLower) / lineSize;
if (upperOverlap > 0 && lowerOverlap < 0)
{
it->xfbAddr += lineSize * upperOverlap;
it->xfbHeight -= upperOverlap;
}
else if (lowerOverlap > 0)
{
it->xfbHeight -= lowerOverlap;
}
}
}
}

View File

@ -1,92 +1,92 @@
#ifndef _FRAMEBUFFERMANAGER_H
#define _FRAMEBUFFERMANAGER_H
#include <list>
#include "VideoCommon.h"
inline bool addrRangesOverlap(u32 aLower, u32 aUpper, u32 bLower, u32 bUpper)
{
return !((aLower >= bUpper) || (bLower >= aUpper));
}
struct XFBSourceBase
{
virtual ~XFBSourceBase() {}
// TODO: only DX9 uses the width/height params
virtual void Draw(const MathUtil::Rectangle<float> &sourcerc,
const MathUtil::Rectangle<float> &drawrc, int width, int height) const = 0;
virtual void DecodeToTexture(u32 xfbAddr, u32 fbWidth, u32 fbHeight) = 0;
virtual void CopyEFB() = 0;
u32 srcAddr;
u32 srcWidth;
u32 srcHeight;
int texWidth;
int texHeight;
// TODO: only used by OGL
TargetRectangle sourceRc;
};
class FramebufferManagerBase
{
public:
enum
{
// There may be multiple XFBs in GameCube RAM. This is the maximum number to
// virtualize.
MAX_VIRTUAL_XFB = 8
};
FramebufferManagerBase();
virtual ~FramebufferManagerBase();
static void CopyToXFB(u32 xfbAddr, u32 fbWidth, u32 fbHeight, const EFBRectangle& sourceRc);
static const XFBSourceBase* const* GetXFBSource(u32 xfbAddr, u32 fbWidth, u32 fbHeight, u32 &xfbCount);
protected:
struct VirtualXFB
{
VirtualXFB() : xfbSource(NULL) {}
// Address and size in GameCube RAM
u32 xfbAddr;
u32 xfbWidth;
u32 xfbHeight;
XFBSourceBase *xfbSource;
};
typedef std::list<VirtualXFB> VirtualXFBListType;
private:
virtual XFBSourceBase* CreateXFBSource(unsigned int target_width, unsigned int target_height) = 0;
// TODO: figure out why OGL is different for this guy
virtual void GetTargetSize(unsigned int *width, unsigned int *height, const EFBRectangle& sourceRc) = 0;
static VirtualXFBListType::iterator FindVirtualXFB(u32 xfbAddr, u32 width, u32 height);
static void ReplaceVirtualXFB();
// TODO: merge these virtual funcs, they are nearly all the same
virtual void CopyToRealXFB(u32 xfbAddr, u32 fbWidth, u32 fbHeight, const EFBRectangle& sourceRc) = 0;
static void CopyToVirtualXFB(u32 xfbAddr, u32 fbWidth, u32 fbHeight, const EFBRectangle& sourceRc);
static const XFBSourceBase* const* GetRealXFBSource(u32 xfbAddr, u32 fbWidth, u32 fbHeight, u32 &xfbCount);
static const XFBSourceBase* const* GetVirtualXFBSource(u32 xfbAddr, u32 fbWidth, u32 fbHeight, u32 &xfbCount);
static XFBSourceBase *m_realXFBSource; // Only used in Real XFB mode
static VirtualXFBListType m_virtualXFBList; // Only used in Virtual XFB mode
static const XFBSourceBase* m_overlappingXFBArray[MAX_VIRTUAL_XFB];
};
extern FramebufferManagerBase *g_framebuffer_manager;
#endif
#ifndef _FRAMEBUFFERMANAGER_H
#define _FRAMEBUFFERMANAGER_H
#include <list>
#include "VideoCommon.h"
inline bool addrRangesOverlap(u32 aLower, u32 aUpper, u32 bLower, u32 bUpper)
{
return !((aLower >= bUpper) || (bLower >= aUpper));
}
struct XFBSourceBase
{
virtual ~XFBSourceBase() {}
// TODO: only DX9 uses the width/height params
virtual void Draw(const MathUtil::Rectangle<float> &sourcerc,
const MathUtil::Rectangle<float> &drawrc, int width, int height) const = 0;
virtual void DecodeToTexture(u32 xfbAddr, u32 fbWidth, u32 fbHeight) = 0;
virtual void CopyEFB() = 0;
u32 srcAddr;
u32 srcWidth;
u32 srcHeight;
unsigned int texWidth;
unsigned int texHeight;
// TODO: only used by OGL
TargetRectangle sourceRc;
};
class FramebufferManagerBase
{
public:
enum
{
// There may be multiple XFBs in GameCube RAM. This is the maximum number to
// virtualize.
MAX_VIRTUAL_XFB = 8
};
FramebufferManagerBase();
virtual ~FramebufferManagerBase();
static void CopyToXFB(u32 xfbAddr, u32 fbWidth, u32 fbHeight, const EFBRectangle& sourceRc);
static const XFBSourceBase* const* GetXFBSource(u32 xfbAddr, u32 fbWidth, u32 fbHeight, u32 &xfbCount);
protected:
struct VirtualXFB
{
VirtualXFB() : xfbSource(NULL) {}
// Address and size in GameCube RAM
u32 xfbAddr;
u32 xfbWidth;
u32 xfbHeight;
XFBSourceBase *xfbSource;
};
typedef std::list<VirtualXFB> VirtualXFBListType;
private:
virtual XFBSourceBase* CreateXFBSource(unsigned int target_width, unsigned int target_height) = 0;
// TODO: figure out why OGL is different for this guy
virtual void GetTargetSize(unsigned int *width, unsigned int *height, const EFBRectangle& sourceRc) = 0;
static VirtualXFBListType::iterator FindVirtualXFB(u32 xfbAddr, u32 width, u32 height);
static void ReplaceVirtualXFB();
// TODO: merge these virtual funcs, they are nearly all the same
virtual void CopyToRealXFB(u32 xfbAddr, u32 fbWidth, u32 fbHeight, const EFBRectangle& sourceRc) = 0;
static void CopyToVirtualXFB(u32 xfbAddr, u32 fbWidth, u32 fbHeight, const EFBRectangle& sourceRc);
static const XFBSourceBase* const* GetRealXFBSource(u32 xfbAddr, u32 fbWidth, u32 fbHeight, u32 &xfbCount);
static const XFBSourceBase* const* GetVirtualXFBSource(u32 xfbAddr, u32 fbWidth, u32 fbHeight, u32 &xfbCount);
static XFBSourceBase *m_realXFBSource; // Only used in Real XFB mode
static VirtualXFBListType m_virtualXFBList; // Only used in Virtual XFB mode
static const XFBSourceBase* m_overlappingXFBArray[MAX_VIRTUAL_XFB];
};
extern FramebufferManagerBase *g_framebuffer_manager;
#endif