diff --git a/higan/emulator/emulator.hpp b/higan/emulator/emulator.hpp index f857d9f8..fc230d1e 100644 --- a/higan/emulator/emulator.hpp +++ b/higan/emulator/emulator.hpp @@ -13,7 +13,7 @@ using namespace nall; namespace Emulator { static const string Name = "higan"; - static const string Version = "106.57"; + static const string Version = "106.58"; static const string Author = "byuu"; static const string License = "GPLv3"; static const string Website = "https://byuu.org/"; diff --git a/nall/queue.hpp b/nall/queue.hpp index 0067c69d..062eda77 100644 --- a/nall/queue.hpp +++ b/nall/queue.hpp @@ -12,16 +12,17 @@ struct queue { queue() = default; queue(const queue& source) { operator=(source); } queue(queue&& source) { operator=(move(source)); } + ~queue() { reset(); } auto operator=(const queue& source) -> queue& { if(this == &source) return *this; - reset(); + delete[] _data; + _data = new T[source._capacity]; _capacity = source._capacity; _size = source._size; - _data = new T[_capacity]; - for(uint n : range(_capacity)) _data[n] = source._data[n]; _read = source._read; _write = source._write; + for(uint n : range(_capacity)) _data[n] = source._data[n]; return *this; } @@ -37,10 +38,6 @@ struct queue { return *this; } - ~queue() { - reset(); - } - template auto capacity() const -> uint { return _capacity * sizeof(T) / sizeof(U); } template auto size() const -> uint { return _size * sizeof(T) / sizeof(U); } auto empty() const -> bool { return _size == 0; } @@ -62,9 +59,12 @@ struct queue { } auto resize(uint capacity, const T& value = {}) -> void { - reset(); + delete[] _data; + _data = new T[capacity]; _capacity = capacity; - _data = new T[_capacity]; + _size = 0; + _read = 0; + _write = 0; for(uint n : range(_capacity)) _data[n] = value; } @@ -74,6 +74,13 @@ struct queue { _write = 0; } + auto fill(const T& value = {}) -> void { + _size = 0; + _read = 0; + _write = 0; + for(uint n : range(_capacity)) _data[n] = value; + } + auto read() -> T { T value = _data[_read++]; if(_read >= _capacity) _read = 0; diff --git a/ruby/audio/audio.cpp b/ruby/audio/audio.cpp index 6c060739..c5f4a749 100644 --- a/ruby/audio/audio.cpp +++ b/ruby/audio/audio.cpp @@ -27,7 +27,7 @@ #endif #if defined(AUDIO_PULSEAUDIOSIMPLE) - #include + #include #endif #if defined(AUDIO_WASAPI) @@ -151,7 +151,7 @@ auto Audio::create(string driver) -> bool { #endif #if defined(AUDIO_DIRECTSOUND) - if(driver == "DirectSound") self.instance = new AudioDirectSound(*this); + if(driver == "DirectSound 7.0") self.instance = new AudioDirectSound(*this); #endif #if defined(AUDIO_OPENAL) @@ -167,7 +167,7 @@ auto Audio::create(string driver) -> bool { #endif #if defined(AUDIO_PULSEAUDIOSIMPLE) - if(driver == "PulseAudioSimple") self.instance = new AudioPulseAudioSimple(*this); + if(driver == "PulseAudio Simple") self.instance = new AudioPulseAudioSimple(*this); #endif #if defined(AUDIO_WASAPI) @@ -175,7 +175,7 @@ auto Audio::create(string driver) -> bool { #endif #if defined(AUDIO_XAUDIO2) - if(driver == "XAudio2") self.instance = new AudioXAudio2(*this); + if(driver == "XAudio 2.1") self.instance = new AudioXAudio2(*this); #endif if(!self.instance) self.instance = new AudioDriver(*this); @@ -195,11 +195,11 @@ auto Audio::hasDrivers() -> vector { #endif #if defined(AUDIO_XAUDIO2) - "XAudio2", + "XAudio 2.1", #endif #if defined(AUDIO_DIRECTSOUND) - "DirectSound", + "DirectSound 7.0", #endif #if defined(AUDIO_ALSA) @@ -219,7 +219,7 @@ auto Audio::hasDrivers() -> vector { #endif #if defined(AUDIO_PULSEAUDIOSIMPLE) - "PulseAudioSimple", + "PulseAudio Simple", #endif #if defined(AUDIO_AO) @@ -235,9 +235,9 @@ auto Audio::optimalDriver() -> string { #elif defined(AUDIO_WASAPI) return "WASAPI"; #elif defined(AUDIO_XAUDIO2) - return "XAudio2"; + return "XAudio 2.1"; #elif defined(AUDIO_DIRECTSOUND) - return "DirectSound"; + return "DirectSound 7.0"; #elif defined(AUDIO_ALSA) return "ALSA"; #elif defined(AUDIO_OSS) @@ -247,7 +247,7 @@ auto Audio::optimalDriver() -> string { #elif defined(AUDIO_PULSEAUDIO) return "PulseAudio"; #elif defined(AUDIO_PULSEAUDIOSIMPLE) - return "PulseAudioSimple"; + return "PulseAudio Simple"; #elif defined(AUDIO_AO) return "libao"; #else @@ -257,11 +257,11 @@ auto Audio::optimalDriver() -> string { auto Audio::safestDriver() -> string { #if defined(AUDIO_DIRECTSOUND) - return "DirectSound"; + return "DirectSound 7.0"; #elif defined(AUDIO_WASAPI) return "WASAPI"; #elif defined(AUDIO_XAUDIO2) - return "XAudio2"; + return "XAudio 2.1"; #elif defined(AUDIO_ALSA) return "ALSA"; #elif defined(AUDIO_OSS) @@ -271,7 +271,7 @@ auto Audio::safestDriver() -> string { #elif defined(AUDIO_PULSEAUDIO) return "PulseAudio"; #elif defined(AUDIO_PULSEAUDIOSIMPLE) - return "PulseAudioSimple"; + return "PulseAudio Simple"; #elif defined(AUDIO_AO) return "libao"; #elif defined(AUDIO_ASIO) diff --git a/ruby/audio/audio.hpp b/ruby/audio/audio.hpp index edd4eda1..25d4c88f 100644 --- a/ruby/audio/audio.hpp +++ b/ruby/audio/audio.hpp @@ -1,6 +1,8 @@ struct Audio; struct AudioDriver { + enum class Format : uint { none, int16, int32, float32, float64 }; + AudioDriver(Audio& super) : super(super) {} virtual ~AudioDriver() = default; diff --git a/ruby/audio/directsound.cpp b/ruby/audio/directsound.cpp index ed2f8155..c6ee36a9 100644 --- a/ruby/audio/directsound.cpp +++ b/ruby/audio/directsound.cpp @@ -12,7 +12,7 @@ struct AudioDirectSound : AudioDriver { return initialize(); } - auto driver() -> string override { return "DirectSound"; } + auto driver() -> string override { return "DirectSound 7.0"; } auto ready() -> bool override { return _ready; } auto hasBlocking() -> bool override { return true; } diff --git a/ruby/audio/pulseaudiosimple.cpp b/ruby/audio/pulseaudio-simple.cpp similarity index 97% rename from ruby/audio/pulseaudiosimple.cpp rename to ruby/audio/pulseaudio-simple.cpp index 8cb51fd9..6e6d4fff 100644 --- a/ruby/audio/pulseaudiosimple.cpp +++ b/ruby/audio/pulseaudio-simple.cpp @@ -12,7 +12,7 @@ struct AudioPulseAudioSimple : AudioDriver { return initialize(); } - auto driver() -> string override { return "PulseAudioSimple"; } + auto driver() -> string override { return "PulseAudio Simple"; } auto ready() -> bool override { return _ready; } auto hasFrequencies() -> vector override { diff --git a/ruby/audio/wasapi.cpp b/ruby/audio/wasapi.cpp index e6ed1712..f33c1bd4 100644 --- a/ruby/audio/wasapi.cpp +++ b/ruby/audio/wasapi.cpp @@ -8,19 +8,17 @@ struct AudioWASAPI : AudioDriver { AudioWASAPI& self = *this; - AudioWASAPI(Audio& super) : AudioDriver(super) { enumerate(); } - ~AudioWASAPI() { terminate(); } + AudioWASAPI(Audio& super) : AudioDriver(super) { construct(); } + ~AudioWASAPI() { destruct(); } auto create() -> bool override { - IMMDevice* defaultDevice = nullptr; - if(self.enumerator->GetDefaultAudioEndpoint(eRender, eConsole, &defaultDevice) != S_OK) return false; - for(auto& device : self.devices) { - if(device.device != defaultDevice) continue; - super.setDevice(device.name); - super.setLatency(40); - return initialize(); - } - return false; + super.setExclusive(false); + super.setDevice(hasDevices().first()); + super.setBlocking(false); + super.setChannels(2); + super.setFrequency(48000); + super.setLatency(40); + return initialize(); } auto driver() -> string override { return "WASAPI"; } @@ -77,41 +75,83 @@ struct AudioWASAPI : AudioDriver { } private: - auto enumerate() -> bool { + struct Device { + string id; + string name; + }; + vector devices; + + auto construct() -> bool { if(CoCreateInstance(CLSID_MMDeviceEnumerator, nullptr, CLSCTX_ALL, IID_IMMDeviceEnumerator, (void**)&self.enumerator) != S_OK) return false; + IMMDevice* defaultDeviceContext = nullptr; + if(self.enumerator->GetDefaultAudioEndpoint(eRender, eConsole, &defaultDeviceContext) != S_OK) return false; + + Device defaultDevice; + LPWSTR defaultDeviceString = nullptr; + defaultDeviceContext->GetId(&defaultDeviceString); + defaultDevice.id = (const char*)utf8_t(defaultDeviceString); + CoTaskMemFree(defaultDeviceString); + IMMDeviceCollection* deviceCollection = nullptr; if(self.enumerator->EnumAudioEndpoints(eRender, DEVICE_STATE_ACTIVE, &deviceCollection) != S_OK) return false; + uint deviceCount = 0; if(deviceCollection->GetCount(&deviceCount) != S_OK) return false; + for(uint deviceIndex : range(deviceCount)) { - IMMDevice* device = nullptr; - if(deviceCollection->Item(deviceIndex, &device) != S_OK) continue; + IMMDevice* deviceContext = nullptr; + if(deviceCollection->Item(deviceIndex, &deviceContext) != S_OK) continue; + + Device device; + LPWSTR deviceString = nullptr; + deviceContext->GetId(&deviceString); + device.id = (const char*)utf8_t(deviceString); + CoTaskMemFree(deviceString); + IPropertyStore* propertyStore = nullptr; - device->OpenPropertyStore(STGM_READ, &propertyStore); + deviceContext->OpenPropertyStore(STGM_READ, &propertyStore); PROPVARIANT propVariant; propertyStore->GetValue(PKEY_Device_FriendlyName, &propVariant); - Device item; - item.name = (const char*)utf8_t(propVariant.pwszVal); - item.device = device; - self.devices.append(item); + device.name = (const char*)utf8_t(propVariant.pwszVal); propertyStore->Release(); + + if(device.id == defaultDevice.id) { + self.devices.prepend(device); + } else { + self.devices.append(device); + } } + deviceCollection->Release(); return true; } + auto destruct() -> void { + terminate(); + + if(self.enumerator) { + self.enumerator->Release(); + self.enumerator = nullptr; + } + } + auto initialize() -> bool { terminate(); + + string deviceID; if(auto index = self.devices.find([&](auto& device) { return device.name == self.device; })) { - self.audioDevice = self.devices[*index].device; + deviceID = self.devices[*index].id; } else { return false; } + utf16_t deviceString(deviceID); + if(self.enumerator->GetDevice(deviceString, &self.audioDevice) != S_OK) return false; + if(self.audioDevice->Activate(IID_IAudioClient, CLSCTX_ALL, nullptr, (void**)&self.audioClient) != S_OK) return false; - WAVEFORMATEXTENSIBLE waveFormat = {}; + WAVEFORMATEXTENSIBLE waveFormat{}; if(self.exclusive) { IPropertyStore* propertyStore = nullptr; if(self.audioDevice->OpenPropertyStore(STGM_READ, &propertyStore) != S_OK) return false; @@ -152,9 +192,8 @@ private: self.mode = waveFormat.SubFormat.Data1; self.precision = waveFormat.Format.wBitsPerSample; - self.isReady = true; clear(); - return true; + return self.isReady = true; } auto terminate() -> void { @@ -216,11 +255,6 @@ private: uint mode = 0; uint precision = 0; - struct Device { - string name; - IMMDevice* device; - }; - struct Queue { double samples[65536][8]; uint16_t read; @@ -229,7 +263,6 @@ private: } queue; IMMDeviceEnumerator* enumerator = nullptr; - vector devices; IMMDevice* audioDevice = nullptr; IAudioClient* audioClient = nullptr; IAudioRenderClient* renderClient = nullptr; diff --git a/ruby/audio/xaudio2.cpp b/ruby/audio/xaudio2.cpp index a7a87653..1ccc4186 100644 --- a/ruby/audio/xaudio2.cpp +++ b/ruby/audio/xaudio2.cpp @@ -3,21 +3,31 @@ #undef interface struct AudioXAudio2 : AudioDriver, public IXAudio2VoiceCallback { + enum : uint { Buffers = 32 }; + AudioXAudio2& self = *this; - AudioXAudio2(Audio& super) : AudioDriver(super) {} - ~AudioXAudio2() { terminate(); } + AudioXAudio2(Audio& super) : AudioDriver(super) { construct(); } + ~AudioXAudio2() { destruct(); } auto create() -> bool override { + super.setDevice(hasDevices().first()); super.setChannels(2); super.setFrequency(48000); super.setLatency(40); return initialize(); } - auto driver() -> string override { return "XAudio2"; } + auto driver() -> string override { return "XAudio 2.1"; } auto ready() -> bool override { return self.isReady; } auto hasBlocking() -> bool override { return true; } + auto hasDynamic() -> bool override { return true; } + + auto hasDevices() -> vector override { + vector devices; + for(auto& device : self.devices) devices.append(device.name); + return devices; + } auto hasFrequencies() -> vector override { return {44100, 48000, 96000}; @@ -27,69 +37,120 @@ struct AudioXAudio2 : AudioDriver, public IXAudio2VoiceCallback { return {20, 40, 60, 80, 100}; } + auto setDevice(string device) -> bool override { return initialize(); } auto setBlocking(bool blocking) -> bool override { return true; } auto setFrequency(uint frequency) -> bool override { return initialize(); } auto setLatency(uint latency) -> bool override { return initialize(); } auto clear() -> void override { - if(!self.sourceVoice) return; self.sourceVoice->Stop(0); self.sourceVoice->FlushSourceBuffers(); //calls OnBufferEnd for all currently submitted buffers - self.bufferIndex = 0; - - self.bufferOffset = 0; - if(self.buffer) memory::fill(self.buffer, self.period * self.bufferCount); + self.index = 0; + self.queue = 0; + for(uint n : range(Buffers)) self.buffers[n].fill(); self.sourceVoice->Start(0); } - auto output(const double samples[]) -> void override { - self.buffer[self.bufferIndex * self.period + self.bufferOffset] = (uint16_t)sclamp<16>(samples[0] * 32767.0) << 0; - self.buffer[self.bufferIndex * self.period + self.bufferOffset] |= (uint16_t)sclamp<16>(samples[1] * 32767.0) << 16; - if(++self.bufferOffset < self.period) return; - self.bufferOffset = 0; + auto level() -> double override { + XAUDIO2_VOICE_STATE state{}; + self.sourceVoice->GetState(&state); + uint level = state.BuffersQueued * self.period - state.SamplesPlayed % self.period; + uint limit = Buffers * self.period; + return (double)(limit - level) / limit; + } - if(self.bufferQueue == self.bufferCount - 1) { + auto output(const double samples[]) -> void override { + uint32_t frame = 0; + frame |= (uint16_t)sclamp<16>(samples[0] * 32767.0) << 0; + frame |= (uint16_t)sclamp<16>(samples[1] * 32767.0) << 16; + + auto& buffer = self.buffers[self.index]; + buffer.write(frame); + if(!buffer.full()) return; + + buffer.flush(); + if(self.queue == Buffers - 1) { if(self.blocking) { //wait until there is at least one other free buffer for the next sample - while(self.bufferQueue == self.bufferCount - 1); - } else { //we need one free buffer for the next sample, so ignore the current contents + while(self.queue == Buffers - 1); + } else { + //there is no free buffer for the next block, so ignore the current contents return; } } - pushBuffer(self.period * 4, self.buffer + self.bufferIndex * self.period); - self.bufferIndex = (self.bufferIndex + 1) % self.bufferCount; + write(buffer.data(), buffer.capacity()); + self.index = (self.index + 1) % Buffers; } private: - auto initialize() -> bool { - terminate(); + struct Device { + uint id = 0; + uint channels = 0; + uint frequency = 0; + Format format = Format::none; + string name; + }; + vector devices; - self.bufferCount = 8; - self.period = self.frequency * self.latency / self.bufferCount / 1000.0 + 0.5; - self.buffer = new uint32_t[self.period * self.bufferCount]; - self.bufferOffset = 0; - self.bufferIndex = 0; - self.bufferQueue = 0; - - if(FAILED(XAudio2Create(&self.interface, 0 , XAUDIO2_DEFAULT_PROCESSOR))) return false; + auto construct() -> void { + XAudio2Create(&self.interface, 0 , XAUDIO2_DEFAULT_PROCESSOR); uint deviceCount = 0; self.interface->GetDeviceCount(&deviceCount); - if(deviceCount == 0) return terminate(), false; - - uint deviceID = 0; for(uint deviceIndex : range(deviceCount)) { - XAUDIO2_DEVICE_DETAILS deviceDetails = {}; + XAUDIO2_DEVICE_DETAILS deviceDetails{}; self.interface->GetDeviceDetails(deviceIndex, &deviceDetails); - if(deviceDetails.Role & DefaultGameDevice) deviceID = deviceIndex; + auto format = deviceDetails.OutputFormat.Format.wFormatTag; + auto bits = deviceDetails.OutputFormat.Format.wBitsPerSample; + + Device device; + device.id = deviceIndex; + device.name = (const char*)utf8_t(deviceDetails.DisplayName); + device.channels = deviceDetails.OutputFormat.Format.nChannels; + device.frequency = deviceDetails.OutputFormat.Format.nSamplesPerSec; + if(format == WAVE_FORMAT_PCM) { + if(bits == 16) device.format = Format::int16; + if(bits == 32) device.format = Format::int32; + } else if(format == WAVE_FORMAT_IEEE_FLOAT) { + if(bits == 32) device.format = Format::float32; + } + + //ensure devices.first() is the default device + if(deviceDetails.Role & DefaultGameDevice) { + devices.prepend(device); + } else { + devices.append(device); + } } + } + + auto destruct() -> void { + terminate(); + + if(self.interface) { + self.interface->Release(); + self.interface = nullptr; + } + } + + auto initialize() -> bool { + terminate(); + if(!self.interface) return false; + + self.period = self.frequency * self.latency / Buffers / 1000.0 + 0.5; + for(uint n : range(Buffers)) buffers[n].resize(self.period); + self.index = 0; + self.queue = 0; + + if(!hasDevices().find(self.device)) self.device = hasDevices().first(); + uint deviceID = devices[hasDevices().find(self.device)()].id; if(FAILED(self.interface->CreateMasteringVoice(&self.masterVoice, self.channels, self.frequency, 0, deviceID, nullptr))) return terminate(), false; - WAVEFORMATEX waveFormat; + WAVEFORMATEX waveFormat{}; waveFormat.wFormatTag = WAVE_FORMAT_PCM; waveFormat.nChannels = self.channels; waveFormat.nSamplesPerSec = self.frequency; @@ -117,33 +178,23 @@ private: self.masterVoice->DestroyVoice(); self.masterVoice = nullptr; } - - if(self.interface) { - self.interface->Release(); - self.interface = nullptr; - } - - delete[] self.buffer; - self.buffer = nullptr; } - auto pushBuffer(uint bytes, uint32_t* audioData) -> void { - XAUDIO2_BUFFER buffer = {}; + auto write(const uint32_t* audioData, uint bytes) -> void { + XAUDIO2_BUFFER buffer{}; buffer.AudioBytes = bytes; - buffer.pAudioData = (BYTE*)audioData; - buffer.pContext = 0; - InterlockedIncrement(&self.bufferQueue); + buffer.pAudioData = (const BYTE*)audioData; + buffer.pContext = nullptr; + InterlockedIncrement(&self.queue); self.sourceVoice->SubmitSourceBuffer(&buffer); } bool isReady = false; - uint32_t* buffer = nullptr; - uint period = 0; - uint bufferCount = 0; - uint bufferOffset = 0; - uint bufferIndex = 0; - volatile long bufferQueue = 0; //how many buffers are queued and ready for playback + queue buffers[Buffers]; + uint period = 0; //amount (in 32-bit frames) of samples per buffer + uint index = 0; //current buffer for writing samples to + volatile long queue = 0; //how many buffers are queued and ready for playback IXAudio2* interface = nullptr; IXAudio2MasteringVoice* masterVoice = nullptr; @@ -158,6 +209,6 @@ private: STDMETHODIMP_(void) OnVoiceProcessingPassStart(UINT32 BytesRequired) {} STDMETHODIMP_(void) OnBufferEnd(void* pBufferContext) { - InterlockedDecrement(&self.bufferQueue); + InterlockedDecrement(&self.queue); } }; diff --git a/ruby/video/cgl.cpp b/ruby/video/cgl.cpp index 38773754..4fac7c79 100644 --- a/ruby/video/cgl.cpp +++ b/ruby/video/cgl.cpp @@ -20,7 +20,7 @@ struct VideoCGL : VideoDriver, OpenGL { return initialize(); } - auto driver() -> string override { return "OpenGL"; } + auto driver() -> string override { return "OpenGL 3.2"; } auto ready() -> bool override { return _ready; } auto hasContext() -> bool override { return true; } diff --git a/ruby/video/direct3d.cpp b/ruby/video/direct3d.cpp index e5342016..80011fde 100644 --- a/ruby/video/direct3d.cpp +++ b/ruby/video/direct3d.cpp @@ -16,7 +16,7 @@ struct VideoDirect3D : VideoDriver { return initialize(); } - auto driver() -> string override { return "Direct3D"; } + auto driver() -> string override { return "Direct3D 9.0"; } auto ready() -> bool override { return _ready; } auto hasExclusive() -> bool override { return true; } diff --git a/ruby/video/directdraw.cpp b/ruby/video/directdraw.cpp index b23b9e34..a0a63842 100644 --- a/ruby/video/directdraw.cpp +++ b/ruby/video/directdraw.cpp @@ -10,7 +10,7 @@ struct VideoDirectDraw : VideoDriver { return initialize(); } - auto driver() -> string override { return "DirectDraw"; } + auto driver() -> string override { return "DirectDraw 7.0"; } auto ready() -> bool override { return _ready; } auto hasContext() -> bool override { return true; } diff --git a/ruby/video/glx.cpp b/ruby/video/glx.cpp index cb4bc196..c72474c2 100644 --- a/ruby/video/glx.cpp +++ b/ruby/video/glx.cpp @@ -17,7 +17,7 @@ struct VideoGLX : VideoDriver, OpenGL { return initialize(); } - auto driver() -> string override { return "OpenGL"; } + auto driver() -> string override { return "OpenGL 3.2"; } auto ready() -> bool override { return _ready; } auto hasContext() -> bool override { return true; } diff --git a/ruby/video/glx2.cpp b/ruby/video/glx2.cpp index db70d685..88a4c934 100644 --- a/ruby/video/glx2.cpp +++ b/ruby/video/glx2.cpp @@ -31,7 +31,7 @@ struct VideoGLX2 : VideoDriver { return initialize(); } - auto driver() -> string override { return "OpenGL2"; } + auto driver() -> string override { return "OpenGL 2.0"; } auto ready() -> bool override { return _ready; } auto hasContext() -> bool override { return true; } @@ -64,7 +64,6 @@ struct VideoGLX2 : VideoDriver { } auto clear() -> void override { - if(!ready()) return; memory::fill(_glBuffer, _glWidth * _glHeight); glClearColor(0.0, 0.0, 0.0, 1.0); glClear(GL_COLOR_BUFFER_BIT); diff --git a/ruby/video/video.cpp b/ruby/video/video.cpp index 2de2e124..9ec2ae14 100644 --- a/ruby/video/video.cpp +++ b/ruby/video/video.cpp @@ -124,15 +124,15 @@ auto Video::create(string driver) -> bool { if(!driver) driver = optimalDriver(); #if defined(VIDEO_CGL) - if(driver == "OpenGL") self.instance = new VideoCGL(*this); + if(driver == "OpenGL 3.2") self.instance = new VideoCGL(*this); #endif #if defined(VIDEO_DIRECT3D) - if(driver == "Direct3D") self.instance = new VideoDirect3D(*this); + if(driver == "Direct3D 9.0") self.instance = new VideoDirect3D(*this); #endif #if defined(VIDEO_DIRECTDRAW) - if(driver == "DirectDraw") self.instance = new VideoDirectDraw(*this); + if(driver == "DirectDraw 7.0") self.instance = new VideoDirectDraw(*this); #endif #if defined(VIDEO_GDI) @@ -140,15 +140,15 @@ auto Video::create(string driver) -> bool { #endif #if defined(VIDEO_GLX) - if(driver == "OpenGL") self.instance = new VideoGLX(*this); + if(driver == "OpenGL 3.2") self.instance = new VideoGLX(*this); #endif #if defined(VIDEO_GLX2) - if(driver == "OpenGL2") self.instance = new VideoGLX2(*this); + if(driver == "OpenGL 2.0") self.instance = new VideoGLX2(*this); #endif #if defined(VIDEO_WGL) - if(driver == "OpenGL") self.instance = new VideoWGL(*this); + if(driver == "OpenGL 3.2") self.instance = new VideoWGL(*this); #endif #if defined(VIDEO_XSHM) @@ -168,15 +168,15 @@ auto Video::hasDrivers() -> vector { return { #if defined(VIDEO_WGL) - "OpenGL", + "OpenGL 3.2", #endif #if defined(VIDEO_DIRECT3D) - "Direct3D", + "Direct3D 9.0", #endif #if defined(VIDEO_DIRECTDRAW) - "DirectDraw", + "DirectDraw 7.0", #endif #if defined(VIDEO_GDI) @@ -184,15 +184,15 @@ auto Video::hasDrivers() -> vector { #endif #if defined(VIDEO_CGL) - "OpenGL", + "OpenGL 3.2", #endif #if defined(VIDEO_GLX) - "OpenGL", + "OpenGL 3.2", #endif #if defined(VIDEO_GLX2) - "OpenGL2", + "OpenGL 2.0", #endif #if defined(VIDEO_XVIDEO) @@ -208,19 +208,19 @@ auto Video::hasDrivers() -> vector { auto Video::optimalDriver() -> string { #if defined(VIDEO_WGL) - return "OpenGL"; + return "OpenGL 3.2"; #elif defined(VIDEO_DIRECT3D) - return "Direct3D"; + return "Direct3D 9.0"; #elif defined(VIDEO_DIRECTDRAW) - return "DirectDraw"; + return "DirectDraw 7.0"; #elif defined(VIDEO_GDI) return "GDI"; #elif defined(VIDEO_CGL) - return "OpenGL"; + return "OpenGL 3.2"; #elif defined(VIDEO_GLX) - return "OpenGL"; + return "OpenGL 3.2"; #elif defined(VIDEO_GLX2) - return "OpenGL2"; + return "OpenGL 2.0"; #elif defined(VIDEO_XVIDEO) return "XVideo"; #elif defined(VIDEO_XSHM) @@ -232,23 +232,23 @@ auto Video::optimalDriver() -> string { auto Video::safestDriver() -> string { #if defined(VIDEO_DIRECT3D) - return "Direct3D"; + return "Direct3D 9.0"; #elif defined(VIDEO_WGL) - return "OpenGL"; + return "OpenGL 3.2"; #elif defined(VIDEO_DIRECTDRAW) - return "DirectDraw"; + return "DirectDraw 7.0"; #elif defined(VIDEO_GDI) return "GDI"; #elif defined(VIDEO_CGL) - return "OpenGL"; + return "OpenGL 3.2"; #elif defined(VIDEO_XSHM) return "XShm"; #elif defined(VIDEO_XVIDEO) return "XVideo"; #elif defined(VIDEO_GLX2) - return "OpenGL2"; + return "OpenGL 2.0"; #elif defined(VIDEO_GLX) - return "OpenGL"; + return "OpenGL 3.2"; #else return "None"; #endif diff --git a/ruby/video/wgl.cpp b/ruby/video/wgl.cpp index 3e66b922..78f6799e 100644 --- a/ruby/video/wgl.cpp +++ b/ruby/video/wgl.cpp @@ -12,7 +12,7 @@ struct VideoWGL : VideoDriver, OpenGL { return initialize(); } - auto driver() -> string override { return "OpenGL"; } + auto driver() -> string override { return "OpenGL 3.2"; } auto ready() -> bool override { return _ready; } auto hasContext() -> bool override { return true; }