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:
parent
0da42fcca7
commit
62a7f101a7
|
@ -1,48 +1,48 @@
|
||||||
// Copyright (C) 2003 Dolphin Project.
|
// Copyright (C) 2003 Dolphin Project.
|
||||||
|
|
||||||
// This program is free software: you can redistribute it and/or modify
|
// 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
|
// it under the terms of the GNU General Public License as published by
|
||||||
// the Free Software Foundation, version 2.0.
|
// the Free Software Foundation, version 2.0.
|
||||||
|
|
||||||
// This program is distributed in the hope that it will be useful,
|
// This program is distributed in the hope that it will be useful,
|
||||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
// GNU General Public License 2.0 for more details.
|
// GNU General Public License 2.0 for more details.
|
||||||
|
|
||||||
// A copy of the GPL 2.0 should have been included with the program.
|
// A copy of the GPL 2.0 should have been included with the program.
|
||||||
// If not, see http://www.gnu.org/licenses/
|
// If not, see http://www.gnu.org/licenses/
|
||||||
|
|
||||||
// Official SVN repository and contact information can be found at
|
// Official SVN repository and contact information can be found at
|
||||||
// http://code.google.com/p/dolphin-emu/
|
// http://code.google.com/p/dolphin-emu/
|
||||||
|
|
||||||
#include "AudioCommon.h"
|
#include "AudioCommon.h"
|
||||||
#include "NullSoundStream.h"
|
#include "NullSoundStream.h"
|
||||||
|
|
||||||
void NullSound::SoundLoop()
|
void NullSound::SoundLoop()
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
bool NullSound::Start()
|
bool NullSound::Start()
|
||||||
{
|
{
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void NullSound::SetVolume(int volume)
|
void NullSound::SetVolume(int volume)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
void NullSound::Update()
|
void NullSound::Update()
|
||||||
{
|
{
|
||||||
// This should equal AUDIO_DMA_PERIOD. TODO: Fix after DSP merge
|
// This should equal AUDIO_DMA_PERIOD. TODO: Fix after DSP merge
|
||||||
int numBytesToRender = 32000 * 4 / 32;
|
int numBytesToRender = 32000 * 4 / 32;
|
||||||
m_mixer->Mix(realtimeBuffer, numBytesToRender / 4);
|
m_mixer->Mix(realtimeBuffer, numBytesToRender / 4);
|
||||||
}
|
}
|
||||||
|
|
||||||
void NullSound::Clear(bool mute)
|
void NullSound::Clear(bool mute)
|
||||||
{
|
{
|
||||||
m_muted = mute;
|
m_muted = mute;
|
||||||
}
|
}
|
||||||
|
|
||||||
void NullSound::Stop()
|
void NullSound::Stop()
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,48 +1,48 @@
|
||||||
// Copyright (C) 2003 Dolphin Project.
|
// Copyright (C) 2003 Dolphin Project.
|
||||||
|
|
||||||
// This program is free software: you can redistribute it and/or modify
|
// 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
|
// it under the terms of the GNU General Public License as published by
|
||||||
// the Free Software Foundation, version 2.0.
|
// the Free Software Foundation, version 2.0.
|
||||||
|
|
||||||
// This program is distributed in the hope that it will be useful,
|
// This program is distributed in the hope that it will be useful,
|
||||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
// GNU General Public License 2.0 for more details.
|
// GNU General Public License 2.0 for more details.
|
||||||
|
|
||||||
// A copy of the GPL 2.0 should have been included with the program.
|
// A copy of the GPL 2.0 should have been included with the program.
|
||||||
// If not, see http://www.gnu.org/licenses/
|
// If not, see http://www.gnu.org/licenses/
|
||||||
|
|
||||||
// Official SVN repository and contact information can be found at
|
// Official SVN repository and contact information can be found at
|
||||||
// http://code.google.com/p/dolphin-emu/
|
// http://code.google.com/p/dolphin-emu/
|
||||||
|
|
||||||
#ifndef _NULLSOUNDSTREAM_H_
|
#ifndef _NULLSOUNDSTREAM_H_
|
||||||
#define _NULLSOUNDSTREAM_H_
|
#define _NULLSOUNDSTREAM_H_
|
||||||
|
|
||||||
#include "SoundStream.h"
|
#include "SoundStream.h"
|
||||||
#include "Thread.h"
|
#include "Thread.h"
|
||||||
|
|
||||||
#define BUF_SIZE (48000 * 4 / 32)
|
#define BUF_SIZE (48000 * 4 / 32)
|
||||||
|
|
||||||
class NullSound : public SoundStream
|
class NullSound : public SoundStream
|
||||||
{
|
{
|
||||||
// playback position
|
// playback position
|
||||||
short realtimeBuffer[BUF_SIZE / sizeof(short)];
|
short realtimeBuffer[BUF_SIZE / sizeof(short)];
|
||||||
|
|
||||||
public:
|
public:
|
||||||
NullSound(CMixer *mixer, void *hWnd = NULL)
|
NullSound(CMixer *mixer, void *hWnd = NULL)
|
||||||
: SoundStream(mixer)
|
: SoundStream(mixer)
|
||||||
{}
|
{}
|
||||||
|
|
||||||
virtual ~NullSound() {}
|
virtual ~NullSound() {}
|
||||||
|
|
||||||
virtual bool Start();
|
virtual bool Start();
|
||||||
virtual void SoundLoop();
|
virtual void SoundLoop();
|
||||||
virtual void SetVolume(int volume);
|
virtual void SetVolume(int volume);
|
||||||
virtual void Stop();
|
virtual void Stop();
|
||||||
virtual void Clear(bool mute);
|
virtual void Clear(bool mute);
|
||||||
static bool isValid() { return true; }
|
static bool isValid() { return true; }
|
||||||
virtual bool usesMixer() const { return true; }
|
virtual bool usesMixer() const { return true; }
|
||||||
virtual void Update();
|
virtual void Update();
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif //_NULLSOUNDSTREAM_H_
|
#endif //_NULLSOUNDSTREAM_H_
|
||||||
|
|
|
@ -1,211 +1,211 @@
|
||||||
// Copyright (C) 2003 Dolphin Project.
|
// Copyright (C) 2003 Dolphin Project.
|
||||||
|
|
||||||
// This program is free software: you can redistribute it and/or modify
|
// 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
|
// it under the terms of the GNU General Public License as published by
|
||||||
// the Free Software Foundation, version 2.0.
|
// the Free Software Foundation, version 2.0.
|
||||||
|
|
||||||
// This program is distributed in the hope that it will be useful,
|
// This program is distributed in the hope that it will be useful,
|
||||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
// GNU General Public License 2.0 for more details.
|
// GNU General Public License 2.0 for more details.
|
||||||
|
|
||||||
// A copy of the GPL 2.0 should have been included with the program.
|
// A copy of the GPL 2.0 should have been included with the program.
|
||||||
// If not, see http://www.gnu.org/licenses/
|
// If not, see http://www.gnu.org/licenses/
|
||||||
|
|
||||||
// Official SVN repository and contact information can be found at
|
// Official SVN repository and contact information can be found at
|
||||||
// http://code.google.com/p/dolphin-emu/
|
// http://code.google.com/p/dolphin-emu/
|
||||||
|
|
||||||
#include "AudioCommon.h"
|
#include "AudioCommon.h"
|
||||||
#include "XAudio2Stream.h"
|
#include "XAudio2Stream.h"
|
||||||
|
|
||||||
struct StreamingVoiceContext : public IXAudio2VoiceCallback
|
struct StreamingVoiceContext : public IXAudio2VoiceCallback
|
||||||
{
|
{
|
||||||
IXAudio2SourceVoice* pSourceVoice;
|
IXAudio2SourceVoice* pSourceVoice;
|
||||||
CMixer *m_mixer;
|
CMixer *m_mixer;
|
||||||
Common::EventEx *soundSyncEvent;
|
Common::EventEx *soundSyncEvent;
|
||||||
short *xaBuffer;
|
short *xaBuffer;
|
||||||
|
|
||||||
StreamingVoiceContext(IXAudio2 *pXAudio2, CMixer *pMixer, Common::EventEx *pSyncEvent)
|
StreamingVoiceContext(IXAudio2 *pXAudio2, CMixer *pMixer, Common::EventEx *pSyncEvent)
|
||||||
{
|
{
|
||||||
|
|
||||||
m_mixer = pMixer;
|
m_mixer = pMixer;
|
||||||
soundSyncEvent = pSyncEvent;
|
soundSyncEvent = pSyncEvent;
|
||||||
|
|
||||||
WAVEFORMATEXTENSIBLE wfx;
|
WAVEFORMATEXTENSIBLE wfx;
|
||||||
|
|
||||||
memset(&wfx, 0, sizeof(WAVEFORMATEXTENSIBLE));
|
memset(&wfx, 0, sizeof(WAVEFORMATEXTENSIBLE));
|
||||||
wfx.Format.wFormatTag = WAVE_FORMAT_EXTENSIBLE;
|
wfx.Format.wFormatTag = WAVE_FORMAT_EXTENSIBLE;
|
||||||
wfx.Format.nSamplesPerSec = m_mixer->GetSampleRate();
|
wfx.Format.nSamplesPerSec = m_mixer->GetSampleRate();
|
||||||
wfx.Format.nChannels = 2;
|
wfx.Format.nChannels = 2;
|
||||||
wfx.Format.wBitsPerSample = 16;
|
wfx.Format.wBitsPerSample = 16;
|
||||||
wfx.Format.nBlockAlign = wfx.Format.nChannels*wfx.Format.wBitsPerSample/8;
|
wfx.Format.nBlockAlign = wfx.Format.nChannels*wfx.Format.wBitsPerSample/8;
|
||||||
wfx.Format.nAvgBytesPerSec = wfx.Format.nSamplesPerSec * wfx.Format.nBlockAlign;
|
wfx.Format.nAvgBytesPerSec = wfx.Format.nSamplesPerSec * wfx.Format.nBlockAlign;
|
||||||
wfx.Format.cbSize = sizeof(WAVEFORMATEXTENSIBLE)-sizeof(WAVEFORMATEX);
|
wfx.Format.cbSize = sizeof(WAVEFORMATEXTENSIBLE)-sizeof(WAVEFORMATEX);
|
||||||
wfx.Samples.wValidBitsPerSample = 16;
|
wfx.Samples.wValidBitsPerSample = 16;
|
||||||
wfx.dwChannelMask = SPEAKER_FRONT_LEFT | SPEAKER_FRONT_RIGHT;
|
wfx.dwChannelMask = SPEAKER_FRONT_LEFT | SPEAKER_FRONT_RIGHT;
|
||||||
wfx.SubFormat = KSDATAFORMAT_SUBTYPE_PCM;
|
wfx.SubFormat = KSDATAFORMAT_SUBTYPE_PCM;
|
||||||
|
|
||||||
// create source voice
|
// create source voice
|
||||||
HRESULT hr;
|
HRESULT hr;
|
||||||
if(FAILED(hr = pXAudio2->CreateSourceVoice(&pSourceVoice, (WAVEFORMATEX*)&wfx, XAUDIO2_VOICE_NOSRC, 1.0f, this)))
|
if(FAILED(hr = pXAudio2->CreateSourceVoice(&pSourceVoice, (WAVEFORMATEX*)&wfx, XAUDIO2_VOICE_NOSRC, 1.0f, this)))
|
||||||
PanicAlert("XAudio2 CreateSourceVoice failed: %#X", hr);
|
PanicAlert("XAudio2 CreateSourceVoice failed: %#X", hr);
|
||||||
|
|
||||||
pSourceVoice->FlushSourceBuffers();
|
pSourceVoice->FlushSourceBuffers();
|
||||||
pSourceVoice->Start();
|
pSourceVoice->Start();
|
||||||
|
|
||||||
xaBuffer = new s16[NUM_BUFFERS * BUFFER_SIZE];
|
xaBuffer = new s16[NUM_BUFFERS * BUFFER_SIZE];
|
||||||
memset(xaBuffer, 0, NUM_BUFFERS * BUFFER_SIZE_BYTES);
|
memset(xaBuffer, 0, NUM_BUFFERS * BUFFER_SIZE_BYTES);
|
||||||
|
|
||||||
//start buffers with silence
|
//start buffers with silence
|
||||||
for(int i=0; i < NUM_BUFFERS; i++)
|
for(int i=0; i < NUM_BUFFERS; i++)
|
||||||
{
|
{
|
||||||
XAUDIO2_BUFFER buf = {0};
|
XAUDIO2_BUFFER buf = {0};
|
||||||
buf.AudioBytes = BUFFER_SIZE_BYTES;
|
buf.AudioBytes = BUFFER_SIZE_BYTES;
|
||||||
buf.pAudioData = (BYTE *) &xaBuffer[i * BUFFER_SIZE];
|
buf.pAudioData = (BYTE *) &xaBuffer[i * BUFFER_SIZE];
|
||||||
buf.pContext = (void *) buf.pAudioData;
|
buf.pContext = (void *) buf.pAudioData;
|
||||||
|
|
||||||
pSourceVoice->SubmitSourceBuffer(&buf);
|
pSourceVoice->SubmitSourceBuffer(&buf);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
~StreamingVoiceContext()
|
~StreamingVoiceContext()
|
||||||
{
|
{
|
||||||
IXAudio2SourceVoice* temp = pSourceVoice;
|
IXAudio2SourceVoice* temp = pSourceVoice;
|
||||||
pSourceVoice = NULL;
|
pSourceVoice = NULL;
|
||||||
temp->FlushSourceBuffers();
|
temp->FlushSourceBuffers();
|
||||||
temp->DestroyVoice();
|
temp->DestroyVoice();
|
||||||
safe_delete_array(xaBuffer);
|
safe_delete_array(xaBuffer);
|
||||||
}
|
}
|
||||||
|
|
||||||
void StreamingVoiceContext::Stop() {
|
void StreamingVoiceContext::Stop() {
|
||||||
if (pSourceVoice)
|
if (pSourceVoice)
|
||||||
pSourceVoice->Stop();
|
pSourceVoice->Stop();
|
||||||
}
|
}
|
||||||
|
|
||||||
void StreamingVoiceContext::Play() {
|
void StreamingVoiceContext::Play() {
|
||||||
if (pSourceVoice)
|
if (pSourceVoice)
|
||||||
pSourceVoice->Start();
|
pSourceVoice->Start();
|
||||||
}
|
}
|
||||||
|
|
||||||
STDMETHOD_(void, OnVoiceError) (THIS_ void* pBufferContext, HRESULT Error) {}
|
STDMETHOD_(void, OnVoiceError) (THIS_ void* pBufferContext, HRESULT Error) {}
|
||||||
STDMETHOD_(void, OnVoiceProcessingPassStart) (UINT32) {}
|
STDMETHOD_(void, OnVoiceProcessingPassStart) (UINT32) {}
|
||||||
STDMETHOD_(void, OnVoiceProcessingPassEnd) () {}
|
STDMETHOD_(void, OnVoiceProcessingPassEnd) () {}
|
||||||
STDMETHOD_(void, OnBufferStart) (void*) {}
|
STDMETHOD_(void, OnBufferStart) (void*) {}
|
||||||
STDMETHOD_(void, OnLoopEnd) (void*) {}
|
STDMETHOD_(void, OnLoopEnd) (void*) {}
|
||||||
STDMETHOD_(void, OnStreamEnd) () {}
|
STDMETHOD_(void, OnStreamEnd) () {}
|
||||||
STDMETHOD_(void, OnBufferEnd) (void* context)
|
STDMETHOD_(void, OnBufferEnd) (void* context)
|
||||||
{ //
|
{ //
|
||||||
// buffer end callback; gets SAMPLES_PER_BUFFER samples for a new buffer
|
// buffer end callback; gets SAMPLES_PER_BUFFER samples for a new buffer
|
||||||
//
|
//
|
||||||
if( !pSourceVoice || !context) return;
|
if( !pSourceVoice || !context) return;
|
||||||
|
|
||||||
//soundSyncEvent->Init();
|
//soundSyncEvent->Init();
|
||||||
//soundSyncEvent->Wait(); //sync
|
//soundSyncEvent->Wait(); //sync
|
||||||
//soundSyncEvent->Spin(); //or tight sync
|
//soundSyncEvent->Spin(); //or tight sync
|
||||||
|
|
||||||
//if (!pSourceVoice) return;
|
//if (!pSourceVoice) return;
|
||||||
|
|
||||||
m_mixer->Mix((short *)context, SAMPLES_PER_BUFFER);
|
m_mixer->Mix((short *)context, SAMPLES_PER_BUFFER);
|
||||||
|
|
||||||
|
|
||||||
XAUDIO2_BUFFER buf = {0};
|
XAUDIO2_BUFFER buf = {0};
|
||||||
buf.AudioBytes = BUFFER_SIZE_BYTES;
|
buf.AudioBytes = BUFFER_SIZE_BYTES;
|
||||||
buf.pAudioData = (byte*)context;
|
buf.pAudioData = (byte*)context;
|
||||||
buf.pContext = context;
|
buf.pContext = context;
|
||||||
|
|
||||||
pSourceVoice->SubmitSourceBuffer(&buf);
|
pSourceVoice->SubmitSourceBuffer(&buf);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
StreamingVoiceContext* pVoiceContext = 0;
|
StreamingVoiceContext* pVoiceContext = 0;
|
||||||
|
|
||||||
bool XAudio2::Start()
|
bool XAudio2::Start()
|
||||||
{
|
{
|
||||||
//soundSyncEvent.Init();
|
//soundSyncEvent.Init();
|
||||||
|
|
||||||
// XAudio2 init
|
// XAudio2 init
|
||||||
CoInitializeEx(NULL, COINIT_MULTITHREADED);
|
CoInitializeEx(NULL, COINIT_MULTITHREADED);
|
||||||
HRESULT hr;
|
HRESULT hr;
|
||||||
if(FAILED(hr = XAudio2Create(&pXAudio2, 0, XAUDIO2_ANY_PROCESSOR))) //callback dosent seem to run on a speecific cpu anyways
|
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);
|
PanicAlert("XAudio2 init failed: %#X", hr);
|
||||||
CoUninitialize();
|
CoUninitialize();
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
// XAudio2 master voice
|
// XAudio2 master voice
|
||||||
// XAUDIO2_DEFAULT_CHANNELS instead of 2 for expansion?
|
// XAUDIO2_DEFAULT_CHANNELS instead of 2 for expansion?
|
||||||
if(FAILED(hr = pXAudio2->CreateMasteringVoice(&pMasteringVoice, 2, m_mixer->GetSampleRate())))
|
if(FAILED(hr = pXAudio2->CreateMasteringVoice(&pMasteringVoice, 2, m_mixer->GetSampleRate())))
|
||||||
{
|
{
|
||||||
PanicAlert("XAudio2 master voice creation failed: %#X", hr);
|
PanicAlert("XAudio2 master voice creation failed: %#X", hr);
|
||||||
safe_release(pXAudio2);
|
safe_release(pXAudio2);
|
||||||
CoUninitialize();
|
CoUninitialize();
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Volume
|
// Volume
|
||||||
if (pMasteringVoice)
|
if (pMasteringVoice)
|
||||||
pMasteringVoice->SetVolume(m_volume);
|
pMasteringVoice->SetVolume(m_volume);
|
||||||
|
|
||||||
if (pXAudio2)
|
if (pXAudio2)
|
||||||
pVoiceContext = new StreamingVoiceContext(pXAudio2, m_mixer, &soundSyncEvent);
|
pVoiceContext = new StreamingVoiceContext(pXAudio2, m_mixer, &soundSyncEvent);
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void XAudio2::SetVolume(int volume)
|
void XAudio2::SetVolume(int volume)
|
||||||
{
|
{
|
||||||
//linear 1- .01
|
//linear 1- .01
|
||||||
m_volume = (float)volume / 100.0;
|
m_volume = (float)volume / 100.0;
|
||||||
|
|
||||||
if (pMasteringVoice)
|
if (pMasteringVoice)
|
||||||
pMasteringVoice->SetVolume(m_volume);
|
pMasteringVoice->SetVolume(m_volume);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
//XAUDIO2_PERFORMANCE_DATA perfData;
|
//XAUDIO2_PERFORMANCE_DATA perfData;
|
||||||
//int xi = 0;
|
//int xi = 0;
|
||||||
void XAudio2::Update()
|
void XAudio2::Update()
|
||||||
{
|
{
|
||||||
//soundSyncEvent.Set();
|
//soundSyncEvent.Set();
|
||||||
|
|
||||||
//xi++;
|
//xi++;
|
||||||
//if (xi == 100000) {
|
//if (xi == 100000) {
|
||||||
// xi = 0;
|
// xi = 0;
|
||||||
// pXAudio2->GetPerformanceData(&perfData);
|
// pXAudio2->GetPerformanceData(&perfData);
|
||||||
// NOTICE_LOG(DSPHLE, "XAudio2 latency (samples): %i",perfData.CurrentLatencyInSamples);
|
// NOTICE_LOG(DSPHLE, "XAudio2 latency (samples): %i",perfData.CurrentLatencyInSamples);
|
||||||
// NOTICE_LOG(DSPHLE, "XAudio2 total glitches: %i",perfData.GlitchesSinceEngineStarted);
|
// NOTICE_LOG(DSPHLE, "XAudio2 total glitches: %i",perfData.GlitchesSinceEngineStarted);
|
||||||
//}
|
//}
|
||||||
}
|
}
|
||||||
|
|
||||||
void XAudio2::Clear(bool mute)
|
void XAudio2::Clear(bool mute)
|
||||||
{
|
{
|
||||||
m_muted = mute;
|
m_muted = mute;
|
||||||
|
|
||||||
if (pVoiceContext)
|
if (pVoiceContext)
|
||||||
{
|
{
|
||||||
if (m_muted)
|
if (m_muted)
|
||||||
pVoiceContext->Stop();
|
pVoiceContext->Stop();
|
||||||
else
|
else
|
||||||
pVoiceContext->Play();
|
pVoiceContext->Play();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void XAudio2::Stop()
|
void XAudio2::Stop()
|
||||||
{
|
{
|
||||||
//soundSyncEvent.Set();
|
//soundSyncEvent.Set();
|
||||||
|
|
||||||
safe_delete(pVoiceContext);
|
safe_delete(pVoiceContext);
|
||||||
pVoiceContext = NULL;
|
pVoiceContext = NULL;
|
||||||
|
|
||||||
if(pMasteringVoice)
|
if(pMasteringVoice)
|
||||||
pMasteringVoice->DestroyVoice();
|
pMasteringVoice->DestroyVoice();
|
||||||
|
|
||||||
safe_release(pXAudio2);
|
safe_release(pXAudio2);
|
||||||
pMasteringVoice = NULL;
|
pMasteringVoice = NULL;
|
||||||
CoUninitialize();
|
CoUninitialize();
|
||||||
//soundSyncEvent.Shutdown();
|
//soundSyncEvent.Shutdown();
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,86 +1,86 @@
|
||||||
// Copyright (C) 2003 Dolphin Project.
|
// Copyright (C) 2003 Dolphin Project.
|
||||||
|
|
||||||
// This program is free software: you can redistribute it and/or modify
|
// 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
|
// it under the terms of the GNU General Public License as published by
|
||||||
// the Free Software Foundation, version 2.0.
|
// the Free Software Foundation, version 2.0.
|
||||||
|
|
||||||
// This program is distributed in the hope that it will be useful,
|
// This program is distributed in the hope that it will be useful,
|
||||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
// GNU General Public License 2.0 for more details.
|
// GNU General Public License 2.0 for more details.
|
||||||
|
|
||||||
// A copy of the GPL 2.0 should have been included with the program.
|
// A copy of the GPL 2.0 should have been included with the program.
|
||||||
// If not, see http://www.gnu.org/licenses/
|
// If not, see http://www.gnu.org/licenses/
|
||||||
|
|
||||||
// Official SVN repository and contact information can be found at
|
// Official SVN repository and contact information can be found at
|
||||||
// http://code.google.com/p/dolphin-emu/
|
// http://code.google.com/p/dolphin-emu/
|
||||||
|
|
||||||
#ifndef _XAUDIO2STREAM_H_
|
#ifndef _XAUDIO2STREAM_H_
|
||||||
#define _XAUDIO2STREAM_H_
|
#define _XAUDIO2STREAM_H_
|
||||||
|
|
||||||
#include "SoundStream.h"
|
#include "SoundStream.h"
|
||||||
|
|
||||||
#ifdef _WIN32
|
#ifdef _WIN32
|
||||||
#include "Thread.h"
|
#include "Thread.h"
|
||||||
#include <xaudio2.h>
|
#include <xaudio2.h>
|
||||||
|
|
||||||
const int NUM_BUFFERS = 3;
|
const int NUM_BUFFERS = 3;
|
||||||
const int SAMPLES_PER_BUFFER = 96;
|
const int SAMPLES_PER_BUFFER = 96;
|
||||||
|
|
||||||
const int NUM_CHANNELS = 2;
|
const int NUM_CHANNELS = 2;
|
||||||
const int BUFFER_SIZE = SAMPLES_PER_BUFFER * NUM_CHANNELS;
|
const int BUFFER_SIZE = SAMPLES_PER_BUFFER * NUM_CHANNELS;
|
||||||
const int BUFFER_SIZE_BYTES = BUFFER_SIZE * sizeof(s16);
|
const int BUFFER_SIZE_BYTES = BUFFER_SIZE * sizeof(s16);
|
||||||
|
|
||||||
|
|
||||||
#ifndef safe_delete_array
|
#ifndef safe_delete_array
|
||||||
#define safe_delete_array(p) { if(p) { delete[] (p); (p)=NULL; } }
|
#define safe_delete_array(p) { if(p) { delete[] (p); (p)=NULL; } }
|
||||||
#endif
|
#endif
|
||||||
#ifndef safe_delete
|
#ifndef safe_delete
|
||||||
#define safe_delete(a) if( (a) != NULL ) delete (a); (a) = NULL;
|
#define safe_delete(a) if( (a) != NULL ) delete (a); (a) = NULL;
|
||||||
#endif
|
#endif
|
||||||
#ifndef safe_release
|
#ifndef safe_release
|
||||||
#define safe_release(p) { if(p) { (p)->Release(); (p)=NULL; } }
|
#define safe_release(p) { if(p) { (p)->Release(); (p)=NULL; } }
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
class XAudio2 : public SoundStream
|
class XAudio2 : public SoundStream
|
||||||
{
|
{
|
||||||
#ifdef _WIN32
|
#ifdef _WIN32
|
||||||
IXAudio2 *pXAudio2;
|
IXAudio2 *pXAudio2;
|
||||||
IXAudio2MasteringVoice *pMasteringVoice;
|
IXAudio2MasteringVoice *pMasteringVoice;
|
||||||
IXAudio2SourceVoice *pSourceVoice;
|
IXAudio2SourceVoice *pSourceVoice;
|
||||||
|
|
||||||
Common::EventEx soundSyncEvent;
|
Common::EventEx soundSyncEvent;
|
||||||
float m_volume;
|
float m_volume;
|
||||||
|
|
||||||
|
|
||||||
bool Init();
|
bool Init();
|
||||||
public:
|
public:
|
||||||
XAudio2(CMixer *mixer)
|
XAudio2(CMixer *mixer)
|
||||||
: SoundStream(mixer),
|
: SoundStream(mixer),
|
||||||
pXAudio2(0),
|
pXAudio2(0),
|
||||||
pMasteringVoice(0),
|
pMasteringVoice(0),
|
||||||
pSourceVoice(0),
|
pSourceVoice(0),
|
||||||
m_volume(1.0f) {}
|
m_volume(1.0f) {}
|
||||||
|
|
||||||
virtual ~XAudio2() {}
|
virtual ~XAudio2() {}
|
||||||
|
|
||||||
virtual bool Start();
|
virtual bool Start();
|
||||||
virtual void SetVolume(int volume);
|
virtual void SetVolume(int volume);
|
||||||
virtual void Stop();
|
virtual void Stop();
|
||||||
virtual void Clear(bool mute);
|
virtual void Clear(bool mute);
|
||||||
static bool isValid() { return true; }
|
static bool isValid() { return true; }
|
||||||
virtual bool usesMixer() const { return true; }
|
virtual bool usesMixer() const { return true; }
|
||||||
virtual void Update();
|
virtual void Update();
|
||||||
|
|
||||||
#else
|
#else
|
||||||
public:
|
public:
|
||||||
XAudio2(CMixer *mixer, void *hWnd = NULL)
|
XAudio2(CMixer *mixer, void *hWnd = NULL)
|
||||||
: SoundStream(mixer)
|
: SoundStream(mixer)
|
||||||
{}
|
{}
|
||||||
#endif
|
#endif
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif //_XAUDIO2STREAM_H_
|
#endif //_XAUDIO2STREAM_H_
|
||||||
|
|
|
@ -224,23 +224,23 @@ inline u64 CreateMapId(u32 address, u32 size)
|
||||||
|
|
||||||
inline u64 CreateVMapId(u8 VATUSED)
|
inline u64 CreateVMapId(u8 VATUSED)
|
||||||
{
|
{
|
||||||
u64 vmat_id = 0;
|
u64 vmap_id = 0;
|
||||||
for(int i = 0; i < 8 ; i++)
|
for(int i = 0; i < 8 ; i++)
|
||||||
{
|
{
|
||||||
if(VATUSED & (1 << i))
|
if(VATUSED & (1 << i))
|
||||||
{
|
{
|
||||||
//vmat_id ^= GetHash64((u8*)(&g_VtxAttr[i].g0.),sizeof(VAT),0);
|
//vmap_id ^= GetHash64((u8*)(&g_VtxAttr[i].g0.),sizeof(VAT),0);
|
||||||
if(vmat_id != 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
|
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;
|
typedef std::map<u64, CachedDisplayList> DLMap;
|
||||||
|
@ -689,7 +689,6 @@ bool HandleDisplayList(u32 address, u32 size)
|
||||||
if (Parentiter != DLCache::dl_map.end())
|
if (Parentiter != DLCache::dl_map.end())
|
||||||
{
|
{
|
||||||
vhash = DLCache::CreateVMapId(Parentiter->second.VATUsed);
|
vhash = DLCache::CreateVMapId(Parentiter->second.VATUsed);
|
||||||
DLCache::VDlist &tvdl = Parentiter->second;
|
|
||||||
iter = Parentiter->second.dl_map.find(vhash);
|
iter = Parentiter->second.dl_map.find(vhash);
|
||||||
childexist = iter != Parentiter->second.dl_map.end();
|
childexist = iter != Parentiter->second.dl_map.end();
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,225 +1,226 @@
|
||||||
|
|
||||||
#include "FramebufferManagerBase.h"
|
#include "FramebufferManagerBase.h"
|
||||||
|
|
||||||
#include "Render.h"
|
#include "Render.h"
|
||||||
#include "VideoConfig.h"
|
#include "VideoConfig.h"
|
||||||
|
|
||||||
FramebufferManagerBase *g_framebuffer_manager;
|
FramebufferManagerBase *g_framebuffer_manager;
|
||||||
|
|
||||||
XFBSourceBase *FramebufferManagerBase::m_realXFBSource; // Only used in Real XFB mode
|
XFBSourceBase *FramebufferManagerBase::m_realXFBSource; // Only used in Real XFB mode
|
||||||
FramebufferManagerBase::VirtualXFBListType FramebufferManagerBase::m_virtualXFBList; // Only used in Virtual XFB mode
|
FramebufferManagerBase::VirtualXFBListType FramebufferManagerBase::m_virtualXFBList; // Only used in Virtual XFB mode
|
||||||
const XFBSourceBase* FramebufferManagerBase::m_overlappingXFBArray[MAX_VIRTUAL_XFB];
|
const XFBSourceBase* FramebufferManagerBase::m_overlappingXFBArray[MAX_VIRTUAL_XFB];
|
||||||
|
|
||||||
FramebufferManagerBase::FramebufferManagerBase()
|
FramebufferManagerBase::FramebufferManagerBase()
|
||||||
{
|
{
|
||||||
m_realXFBSource = NULL;
|
m_realXFBSource = NULL;
|
||||||
|
|
||||||
// can't hurt
|
// can't hurt
|
||||||
memset(m_overlappingXFBArray, 0, sizeof(m_overlappingXFBArray));
|
memset(m_overlappingXFBArray, 0, sizeof(m_overlappingXFBArray));
|
||||||
}
|
}
|
||||||
|
|
||||||
FramebufferManagerBase::~FramebufferManagerBase()
|
FramebufferManagerBase::~FramebufferManagerBase()
|
||||||
{
|
{
|
||||||
VirtualXFBListType::iterator
|
VirtualXFBListType::iterator
|
||||||
it = m_virtualXFBList.begin(),
|
it = m_virtualXFBList.begin(),
|
||||||
vlend = m_virtualXFBList.end();
|
vlend = m_virtualXFBList.end();
|
||||||
for (; it != vlend; ++it)
|
for (; it != vlend; ++it)
|
||||||
delete it->xfbSource;
|
delete it->xfbSource;
|
||||||
|
|
||||||
m_virtualXFBList.clear();
|
m_virtualXFBList.clear();
|
||||||
|
|
||||||
delete m_realXFBSource;
|
delete m_realXFBSource;
|
||||||
}
|
}
|
||||||
|
|
||||||
const XFBSourceBase* const* FramebufferManagerBase::GetXFBSource(u32 xfbAddr, u32 fbWidth, u32 fbHeight, u32 &xfbCount)
|
const XFBSourceBase* const* FramebufferManagerBase::GetXFBSource(u32 xfbAddr, u32 fbWidth, u32 fbHeight, u32 &xfbCount)
|
||||||
{
|
{
|
||||||
if (g_ActiveConfig.bUseRealXFB)
|
if (g_ActiveConfig.bUseRealXFB)
|
||||||
return GetRealXFBSource(xfbAddr, fbWidth, fbHeight, xfbCount);
|
return GetRealXFBSource(xfbAddr, fbWidth, fbHeight, xfbCount);
|
||||||
else
|
else
|
||||||
return GetVirtualXFBSource(xfbAddr, fbWidth, fbHeight, xfbCount);
|
return GetVirtualXFBSource(xfbAddr, fbWidth, fbHeight, xfbCount);
|
||||||
}
|
}
|
||||||
|
|
||||||
const XFBSourceBase* const* FramebufferManagerBase::GetRealXFBSource(u32 xfbAddr, u32 fbWidth, u32 fbHeight, u32 &xfbCount)
|
const XFBSourceBase* const* FramebufferManagerBase::GetRealXFBSource(u32 xfbAddr, u32 fbWidth, u32 fbHeight, u32 &xfbCount)
|
||||||
{
|
{
|
||||||
xfbCount = 1;
|
xfbCount = 1;
|
||||||
|
|
||||||
if (!m_realXFBSource)
|
if (!m_realXFBSource)
|
||||||
m_realXFBSource = g_framebuffer_manager->CreateXFBSource(fbWidth, fbHeight);
|
m_realXFBSource = g_framebuffer_manager->CreateXFBSource(fbWidth, fbHeight);
|
||||||
|
|
||||||
m_realXFBSource->srcAddr = xfbAddr;
|
m_realXFBSource->srcAddr = xfbAddr;
|
||||||
|
|
||||||
m_realXFBSource->srcWidth = MAX_XFB_WIDTH;
|
m_realXFBSource->srcWidth = MAX_XFB_WIDTH;
|
||||||
m_realXFBSource->srcHeight = MAX_XFB_HEIGHT;
|
m_realXFBSource->srcHeight = MAX_XFB_HEIGHT;
|
||||||
|
|
||||||
m_realXFBSource->texWidth = fbWidth;
|
m_realXFBSource->texWidth = fbWidth;
|
||||||
m_realXFBSource->texHeight = fbHeight;
|
m_realXFBSource->texHeight = fbHeight;
|
||||||
|
|
||||||
// TODO: stuff only used by OGL... :/
|
// TODO: stuff only used by OGL... :/
|
||||||
// OpenGL texture coordinates originate at the lower left, which is why
|
// OpenGL texture coordinates originate at the lower left, which is why
|
||||||
// sourceRc.top = fbHeight and sourceRc.bottom = 0.
|
// sourceRc.top = fbHeight and sourceRc.bottom = 0.
|
||||||
m_realXFBSource->sourceRc.left = 0;
|
m_realXFBSource->sourceRc.left = 0;
|
||||||
m_realXFBSource->sourceRc.top = fbHeight;
|
m_realXFBSource->sourceRc.top = fbHeight;
|
||||||
m_realXFBSource->sourceRc.right = fbWidth;
|
m_realXFBSource->sourceRc.right = fbWidth;
|
||||||
m_realXFBSource->sourceRc.bottom = 0;
|
m_realXFBSource->sourceRc.bottom = 0;
|
||||||
|
|
||||||
// Decode YUYV data from GameCube RAM
|
// Decode YUYV data from GameCube RAM
|
||||||
m_realXFBSource->DecodeToTexture(xfbAddr, fbWidth, fbHeight);
|
m_realXFBSource->DecodeToTexture(xfbAddr, fbWidth, fbHeight);
|
||||||
|
|
||||||
m_overlappingXFBArray[0] = m_realXFBSource;
|
m_overlappingXFBArray[0] = m_realXFBSource;
|
||||||
return &m_overlappingXFBArray[0];
|
return &m_overlappingXFBArray[0];
|
||||||
}
|
}
|
||||||
|
|
||||||
const XFBSourceBase* const* FramebufferManagerBase::GetVirtualXFBSource(u32 xfbAddr, u32 fbWidth, u32 fbHeight, u32 &xfbCount)
|
const XFBSourceBase* const* FramebufferManagerBase::GetVirtualXFBSource(u32 xfbAddr, u32 fbWidth, u32 fbHeight, u32 &xfbCount)
|
||||||
{
|
{
|
||||||
xfbCount = 0;
|
xfbCount = 0;
|
||||||
|
|
||||||
if (m_virtualXFBList.empty()) // no Virtual XFBs available
|
if (m_virtualXFBList.empty()) // no Virtual XFBs available
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
u32 srcLower = xfbAddr;
|
u32 srcLower = xfbAddr;
|
||||||
u32 srcUpper = xfbAddr + 2 * fbWidth * fbHeight;
|
u32 srcUpper = xfbAddr + 2 * fbWidth * fbHeight;
|
||||||
|
|
||||||
VirtualXFBListType::reverse_iterator
|
VirtualXFBListType::reverse_iterator
|
||||||
it = m_virtualXFBList.rbegin(),
|
it = m_virtualXFBList.rbegin(),
|
||||||
vlend = m_virtualXFBList.rend();
|
vlend = m_virtualXFBList.rend();
|
||||||
for (; it != vlend; ++it)
|
for (; it != vlend; ++it)
|
||||||
{
|
{
|
||||||
VirtualXFB* vxfb = &*it;
|
VirtualXFB* vxfb = &*it;
|
||||||
|
|
||||||
u32 dstLower = vxfb->xfbAddr;
|
u32 dstLower = vxfb->xfbAddr;
|
||||||
u32 dstUpper = vxfb->xfbAddr + 2 * vxfb->xfbWidth * vxfb->xfbHeight;
|
u32 dstUpper = vxfb->xfbAddr + 2 * vxfb->xfbWidth * vxfb->xfbHeight;
|
||||||
|
|
||||||
if (addrRangesOverlap(srcLower, srcUpper, dstLower, dstUpper))
|
if (addrRangesOverlap(srcLower, srcUpper, dstLower, dstUpper))
|
||||||
{
|
{
|
||||||
m_overlappingXFBArray[xfbCount] = vxfb->xfbSource;
|
m_overlappingXFBArray[xfbCount] = vxfb->xfbSource;
|
||||||
++xfbCount;
|
++xfbCount;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return &m_overlappingXFBArray[0];
|
return &m_overlappingXFBArray[0];
|
||||||
}
|
}
|
||||||
|
|
||||||
void FramebufferManagerBase::CopyToXFB(u32 xfbAddr, u32 fbWidth, u32 fbHeight, const EFBRectangle& sourceRc)
|
void FramebufferManagerBase::CopyToXFB(u32 xfbAddr, u32 fbWidth, u32 fbHeight, const EFBRectangle& sourceRc)
|
||||||
{
|
{
|
||||||
if (g_ActiveConfig.bUseRealXFB)
|
if (g_ActiveConfig.bUseRealXFB)
|
||||||
g_framebuffer_manager->CopyToRealXFB(xfbAddr, fbWidth, fbHeight, sourceRc);
|
g_framebuffer_manager->CopyToRealXFB(xfbAddr, fbWidth, fbHeight, sourceRc);
|
||||||
else
|
else
|
||||||
CopyToVirtualXFB(xfbAddr, fbWidth, fbHeight, sourceRc);
|
CopyToVirtualXFB(xfbAddr, fbWidth, fbHeight, sourceRc);
|
||||||
}
|
}
|
||||||
|
|
||||||
void FramebufferManagerBase::CopyToVirtualXFB(u32 xfbAddr, u32 fbWidth, u32 fbHeight, const EFBRectangle& sourceRc)
|
void FramebufferManagerBase::CopyToVirtualXFB(u32 xfbAddr, u32 fbWidth, u32 fbHeight, const EFBRectangle& sourceRc)
|
||||||
{
|
{
|
||||||
VirtualXFBListType::iterator vxfb = FindVirtualXFB(xfbAddr, fbWidth, fbHeight);
|
VirtualXFBListType::iterator vxfb = FindVirtualXFB(xfbAddr, fbWidth, fbHeight);
|
||||||
|
|
||||||
if (m_virtualXFBList.end() == vxfb)
|
if (m_virtualXFBList.end() == vxfb)
|
||||||
{
|
{
|
||||||
if (m_virtualXFBList.size() < MAX_VIRTUAL_XFB)
|
if (m_virtualXFBList.size() < MAX_VIRTUAL_XFB)
|
||||||
{
|
{
|
||||||
// create a new Virtual XFB and place it at the front of the list
|
// create a new Virtual XFB and place it at the front of the list
|
||||||
VirtualXFB v;
|
VirtualXFB v;
|
||||||
m_virtualXFBList.push_front(v);
|
memset(&v, 0, sizeof v);
|
||||||
vxfb = m_virtualXFBList.begin();
|
m_virtualXFBList.push_front(v);
|
||||||
}
|
vxfb = m_virtualXFBList.begin();
|
||||||
else
|
}
|
||||||
{
|
else
|
||||||
// Replace the last virtual XFB
|
{
|
||||||
--vxfb;
|
// Replace the last virtual XFB
|
||||||
}
|
--vxfb;
|
||||||
}
|
}
|
||||||
//else // replace existing virtual XFB
|
}
|
||||||
|
//else // replace existing virtual XFB
|
||||||
// move this Virtual XFB to the front of the list.
|
|
||||||
if (m_virtualXFBList.begin() != vxfb)
|
// move this Virtual XFB to the front of the list.
|
||||||
m_virtualXFBList.splice(m_virtualXFBList.begin(), m_virtualXFBList, vxfb);
|
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);
|
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))
|
// recreate if needed
|
||||||
{
|
if (vxfb->xfbSource && (vxfb->xfbSource->texWidth != target_width || vxfb->xfbSource->texHeight != target_height))
|
||||||
//delete vxfb->xfbSource;
|
{
|
||||||
//vxfb->xfbSource = NULL;
|
//delete vxfb->xfbSource;
|
||||||
}
|
//vxfb->xfbSource = NULL;
|
||||||
|
}
|
||||||
if (!vxfb->xfbSource)
|
|
||||||
{
|
if (!vxfb->xfbSource)
|
||||||
vxfb->xfbSource = g_framebuffer_manager->CreateXFBSource(target_width, target_height);
|
{
|
||||||
vxfb->xfbSource->texWidth = target_width;
|
vxfb->xfbSource = g_framebuffer_manager->CreateXFBSource(target_width, target_height);
|
||||||
vxfb->xfbSource->texHeight = 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->srcAddr = vxfb->xfbAddr = xfbAddr;
|
||||||
vxfb->xfbSource->srcHeight = vxfb->xfbHeight = fbHeight;
|
vxfb->xfbSource->srcWidth = vxfb->xfbWidth = fbWidth;
|
||||||
|
vxfb->xfbSource->srcHeight = vxfb->xfbHeight = fbHeight;
|
||||||
vxfb->xfbSource->sourceRc = Renderer::ConvertEFBRectangle(sourceRc);
|
|
||||||
|
vxfb->xfbSource->sourceRc = Renderer::ConvertEFBRectangle(sourceRc);
|
||||||
// keep stale XFB data from being used
|
|
||||||
ReplaceVirtualXFB();
|
// keep stale XFB data from being used
|
||||||
|
ReplaceVirtualXFB();
|
||||||
Renderer::ResetAPIState(); // reset any game specific settings
|
|
||||||
|
Renderer::ResetAPIState(); // reset any game specific settings
|
||||||
// Copy EFB data to XFB and restore render target again
|
|
||||||
vxfb->xfbSource->CopyEFB();
|
// Copy EFB data to XFB and restore render target again
|
||||||
|
vxfb->xfbSource->CopyEFB();
|
||||||
Renderer::RestoreAPIState();
|
|
||||||
}
|
Renderer::RestoreAPIState();
|
||||||
|
}
|
||||||
FramebufferManagerBase::VirtualXFBListType::iterator FramebufferManagerBase::FindVirtualXFB(u32 xfbAddr, u32 width, u32 height)
|
|
||||||
{
|
FramebufferManagerBase::VirtualXFBListType::iterator FramebufferManagerBase::FindVirtualXFB(u32 xfbAddr, u32 width, u32 height)
|
||||||
const u32 srcLower = xfbAddr;
|
{
|
||||||
const u32 srcUpper = xfbAddr + 2 * width * height;
|
const u32 srcLower = xfbAddr;
|
||||||
|
const u32 srcUpper = xfbAddr + 2 * width * height;
|
||||||
VirtualXFBListType::iterator it = m_virtualXFBList.begin();
|
|
||||||
for (; it != m_virtualXFBList.end(); ++it)
|
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;
|
const u32 dstLower = it->xfbAddr;
|
||||||
|
const u32 dstUpper = it->xfbAddr + 2 * it->xfbWidth * it->xfbHeight;
|
||||||
if (dstLower >= srcLower && dstUpper <= srcUpper)
|
|
||||||
break;
|
if (dstLower >= srcLower && dstUpper <= srcUpper)
|
||||||
}
|
break;
|
||||||
|
}
|
||||||
return it;
|
|
||||||
}
|
return it;
|
||||||
|
}
|
||||||
void FramebufferManagerBase::ReplaceVirtualXFB()
|
|
||||||
{
|
void FramebufferManagerBase::ReplaceVirtualXFB()
|
||||||
VirtualXFBListType::iterator it = m_virtualXFBList.begin();
|
{
|
||||||
|
VirtualXFBListType::iterator it = m_virtualXFBList.begin();
|
||||||
const s32 srcLower = it->xfbAddr;
|
|
||||||
const s32 srcUpper = it->xfbAddr + 2 * it->xfbWidth * it->xfbHeight;
|
const s32 srcLower = it->xfbAddr;
|
||||||
const s32 lineSize = 2 * it->xfbWidth;
|
const s32 srcUpper = it->xfbAddr + 2 * it->xfbWidth * it->xfbHeight;
|
||||||
|
const s32 lineSize = 2 * it->xfbWidth;
|
||||||
++it;
|
|
||||||
|
++it;
|
||||||
for (; it != m_virtualXFBList.end(); ++it)
|
|
||||||
{
|
for (; it != m_virtualXFBList.end(); ++it)
|
||||||
s32 dstLower = it->xfbAddr;
|
{
|
||||||
s32 dstUpper = it->xfbAddr + 2 * it->xfbWidth * it->xfbHeight;
|
s32 dstLower = it->xfbAddr;
|
||||||
|
s32 dstUpper = it->xfbAddr + 2 * it->xfbWidth * it->xfbHeight;
|
||||||
if (dstLower >= srcLower && dstUpper <= srcUpper)
|
|
||||||
{
|
if (dstLower >= srcLower && dstUpper <= srcUpper)
|
||||||
// Invalidate the data
|
{
|
||||||
it->xfbAddr = 0;
|
// Invalidate the data
|
||||||
it->xfbHeight = 0;
|
it->xfbAddr = 0;
|
||||||
it->xfbWidth = 0;
|
it->xfbHeight = 0;
|
||||||
}
|
it->xfbWidth = 0;
|
||||||
else if (addrRangesOverlap(srcLower, srcUpper, dstLower, dstUpper))
|
}
|
||||||
{
|
else if (addrRangesOverlap(srcLower, srcUpper, dstLower, dstUpper))
|
||||||
s32 upperOverlap = (srcUpper - dstLower) / lineSize;
|
{
|
||||||
s32 lowerOverlap = (dstUpper - srcLower) / lineSize;
|
s32 upperOverlap = (srcUpper - dstLower) / lineSize;
|
||||||
|
s32 lowerOverlap = (dstUpper - srcLower) / lineSize;
|
||||||
if (upperOverlap > 0 && lowerOverlap < 0)
|
|
||||||
{
|
if (upperOverlap > 0 && lowerOverlap < 0)
|
||||||
it->xfbAddr += lineSize * upperOverlap;
|
{
|
||||||
it->xfbHeight -= upperOverlap;
|
it->xfbAddr += lineSize * upperOverlap;
|
||||||
}
|
it->xfbHeight -= upperOverlap;
|
||||||
else if (lowerOverlap > 0)
|
}
|
||||||
{
|
else if (lowerOverlap > 0)
|
||||||
it->xfbHeight -= lowerOverlap;
|
{
|
||||||
}
|
it->xfbHeight -= lowerOverlap;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -1,92 +1,92 @@
|
||||||
|
|
||||||
#ifndef _FRAMEBUFFERMANAGER_H
|
#ifndef _FRAMEBUFFERMANAGER_H
|
||||||
#define _FRAMEBUFFERMANAGER_H
|
#define _FRAMEBUFFERMANAGER_H
|
||||||
|
|
||||||
#include <list>
|
#include <list>
|
||||||
|
|
||||||
#include "VideoCommon.h"
|
#include "VideoCommon.h"
|
||||||
|
|
||||||
inline bool addrRangesOverlap(u32 aLower, u32 aUpper, u32 bLower, u32 bUpper)
|
inline bool addrRangesOverlap(u32 aLower, u32 aUpper, u32 bLower, u32 bUpper)
|
||||||
{
|
{
|
||||||
return !((aLower >= bUpper) || (bLower >= aUpper));
|
return !((aLower >= bUpper) || (bLower >= aUpper));
|
||||||
}
|
}
|
||||||
|
|
||||||
struct XFBSourceBase
|
struct XFBSourceBase
|
||||||
{
|
{
|
||||||
virtual ~XFBSourceBase() {}
|
virtual ~XFBSourceBase() {}
|
||||||
|
|
||||||
// TODO: only DX9 uses the width/height params
|
// TODO: only DX9 uses the width/height params
|
||||||
virtual void Draw(const MathUtil::Rectangle<float> &sourcerc,
|
virtual void Draw(const MathUtil::Rectangle<float> &sourcerc,
|
||||||
const MathUtil::Rectangle<float> &drawrc, int width, int height) const = 0;
|
const MathUtil::Rectangle<float> &drawrc, int width, int height) const = 0;
|
||||||
|
|
||||||
virtual void DecodeToTexture(u32 xfbAddr, u32 fbWidth, u32 fbHeight) = 0;
|
virtual void DecodeToTexture(u32 xfbAddr, u32 fbWidth, u32 fbHeight) = 0;
|
||||||
|
|
||||||
virtual void CopyEFB() = 0;
|
virtual void CopyEFB() = 0;
|
||||||
|
|
||||||
u32 srcAddr;
|
u32 srcAddr;
|
||||||
u32 srcWidth;
|
u32 srcWidth;
|
||||||
u32 srcHeight;
|
u32 srcHeight;
|
||||||
|
|
||||||
int texWidth;
|
unsigned int texWidth;
|
||||||
int texHeight;
|
unsigned int texHeight;
|
||||||
|
|
||||||
// TODO: only used by OGL
|
// TODO: only used by OGL
|
||||||
TargetRectangle sourceRc;
|
TargetRectangle sourceRc;
|
||||||
};
|
};
|
||||||
|
|
||||||
class FramebufferManagerBase
|
class FramebufferManagerBase
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
enum
|
enum
|
||||||
{
|
{
|
||||||
// There may be multiple XFBs in GameCube RAM. This is the maximum number to
|
// There may be multiple XFBs in GameCube RAM. This is the maximum number to
|
||||||
// virtualize.
|
// virtualize.
|
||||||
MAX_VIRTUAL_XFB = 8
|
MAX_VIRTUAL_XFB = 8
|
||||||
};
|
};
|
||||||
|
|
||||||
FramebufferManagerBase();
|
FramebufferManagerBase();
|
||||||
virtual ~FramebufferManagerBase();
|
virtual ~FramebufferManagerBase();
|
||||||
|
|
||||||
static void CopyToXFB(u32 xfbAddr, u32 fbWidth, u32 fbHeight, const EFBRectangle& sourceRc);
|
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);
|
static const XFBSourceBase* const* GetXFBSource(u32 xfbAddr, u32 fbWidth, u32 fbHeight, u32 &xfbCount);
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
struct VirtualXFB
|
struct VirtualXFB
|
||||||
{
|
{
|
||||||
VirtualXFB() : xfbSource(NULL) {}
|
VirtualXFB() : xfbSource(NULL) {}
|
||||||
|
|
||||||
// Address and size in GameCube RAM
|
// Address and size in GameCube RAM
|
||||||
u32 xfbAddr;
|
u32 xfbAddr;
|
||||||
u32 xfbWidth;
|
u32 xfbWidth;
|
||||||
u32 xfbHeight;
|
u32 xfbHeight;
|
||||||
|
|
||||||
XFBSourceBase *xfbSource;
|
XFBSourceBase *xfbSource;
|
||||||
};
|
};
|
||||||
|
|
||||||
typedef std::list<VirtualXFB> VirtualXFBListType;
|
typedef std::list<VirtualXFB> VirtualXFBListType;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
virtual XFBSourceBase* CreateXFBSource(unsigned int target_width, unsigned int target_height) = 0;
|
virtual XFBSourceBase* CreateXFBSource(unsigned int target_width, unsigned int target_height) = 0;
|
||||||
// TODO: figure out why OGL is different for this guy
|
// TODO: figure out why OGL is different for this guy
|
||||||
virtual void GetTargetSize(unsigned int *width, unsigned int *height, const EFBRectangle& sourceRc) = 0;
|
virtual void GetTargetSize(unsigned int *width, unsigned int *height, const EFBRectangle& sourceRc) = 0;
|
||||||
|
|
||||||
static VirtualXFBListType::iterator FindVirtualXFB(u32 xfbAddr, u32 width, u32 height);
|
static VirtualXFBListType::iterator FindVirtualXFB(u32 xfbAddr, u32 width, u32 height);
|
||||||
|
|
||||||
static void ReplaceVirtualXFB();
|
static void ReplaceVirtualXFB();
|
||||||
|
|
||||||
// TODO: merge these virtual funcs, they are nearly all the same
|
// TODO: merge these virtual funcs, they are nearly all the same
|
||||||
virtual void CopyToRealXFB(u32 xfbAddr, u32 fbWidth, u32 fbHeight, const EFBRectangle& sourceRc) = 0;
|
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 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* GetRealXFBSource(u32 xfbAddr, u32 fbWidth, u32 fbHeight, u32 &xfbCount);
|
||||||
static const XFBSourceBase* const* GetVirtualXFBSource(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 XFBSourceBase *m_realXFBSource; // Only used in Real XFB mode
|
||||||
static VirtualXFBListType m_virtualXFBList; // Only used in Virtual XFB mode
|
static VirtualXFBListType m_virtualXFBList; // Only used in Virtual XFB mode
|
||||||
|
|
||||||
static const XFBSourceBase* m_overlappingXFBArray[MAX_VIRTUAL_XFB];
|
static const XFBSourceBase* m_overlappingXFBArray[MAX_VIRTUAL_XFB];
|
||||||
};
|
};
|
||||||
|
|
||||||
extern FramebufferManagerBase *g_framebuffer_manager;
|
extern FramebufferManagerBase *g_framebuffer_manager;
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
Loading…
Reference in New Issue