From b9e0c329d0b561f1e2c779d8faefa289862d4d3a Mon Sep 17 00:00:00 2001 From: Connor McLaughlin Date: Sun, 20 Oct 2019 22:28:19 +1000 Subject: [PATCH] Remove unused common classes --- src/common/CMakeLists.txt | 38 -- src/common/audio.cpp | 372 ------------- src/common/audio.h | 184 ------- src/common/common.vcxproj | 25 - src/common/common.vcxproj.filters | 25 - src/common/display.cpp | 529 ------------------ src/common/display.h | 146 ----- src/common/display_renderer.cpp | 196 ------- src/common/display_renderer.h | 72 --- src/common/display_renderer_d3d.cpp | 340 ------------ src/common/display_renderer_d3d.h | 55 -- src/common/display_renderer_gl.cpp | 367 ------------- src/common/display_renderer_gl.h | 35 -- src/common/display_timing.cpp | 374 ------------- src/common/display_timing.h | 144 ----- src/common/fastjmp.asm | 63 --- src/common/fastjmp.h | 44 -- src/common/hdd_image.cpp | 566 -------------------- src/common/hdd_image.h | 93 ---- src/common/object.cpp | 8 - src/common/object.h | 84 --- src/common/object_type_info.cpp | 129 ----- src/common/object_type_info.h | 129 ----- src/common/property.cpp | 349 ------------ src/common/property.h | 103 ---- src/common/type_registry.h | 110 ---- src/duckstation/CMakeLists.txt | 2 - src/duckstation/duckstation.vcxproj | 2 - src/duckstation/duckstation.vcxproj.filters | 2 - src/duckstation/sdl_audio_mixer.cpp | 129 ----- src/duckstation/sdl_audio_mixer.h | 19 - 31 files changed, 4734 deletions(-) delete mode 100644 src/common/audio.cpp delete mode 100644 src/common/audio.h delete mode 100644 src/common/display.cpp delete mode 100644 src/common/display.h delete mode 100644 src/common/display_renderer.cpp delete mode 100644 src/common/display_renderer.h delete mode 100644 src/common/display_renderer_d3d.cpp delete mode 100644 src/common/display_renderer_d3d.h delete mode 100644 src/common/display_renderer_gl.cpp delete mode 100644 src/common/display_renderer_gl.h delete mode 100644 src/common/display_timing.cpp delete mode 100644 src/common/display_timing.h delete mode 100644 src/common/fastjmp.asm delete mode 100644 src/common/fastjmp.h delete mode 100644 src/common/hdd_image.cpp delete mode 100644 src/common/hdd_image.h delete mode 100644 src/common/object.cpp delete mode 100644 src/common/object.h delete mode 100644 src/common/object_type_info.cpp delete mode 100644 src/common/object_type_info.h delete mode 100644 src/common/property.cpp delete mode 100644 src/common/property.h delete mode 100644 src/common/type_registry.h delete mode 100644 src/duckstation/sdl_audio_mixer.cpp delete mode 100644 src/duckstation/sdl_audio_mixer.h diff --git a/src/common/CMakeLists.txt b/src/common/CMakeLists.txt index 957ad6280..a5974d6b5 100644 --- a/src/common/CMakeLists.txt +++ b/src/common/CMakeLists.txt @@ -1,6 +1,4 @@ set(SRCS - audio.cpp - audio.h audio_stream.cpp audio_stream.h bitfield.h @@ -8,31 +6,15 @@ set(SRCS cd_image.h cd_xa.cpp cd_xa.h - display.cpp - display.h - display_renderer.cpp - display_renderer.h - display_timing.cpp - display_timing.h - fastjmp.h gl_program.cpp gl_program.h gl_texture.cpp gl_texture.h - hdd_image.cpp - hdd_image.h jit_code_buffer.cpp jit_code_buffer.h - object.cpp - object.h - object_type_info.cpp - object_type_info.h - property.cpp - property.h state_wrapper.cpp state_wrapper.h types.h - type_registry.h ) add_library(common ${SRCS}) @@ -40,23 +22,3 @@ add_library(common ${SRCS}) target_include_directories(common PRIVATE "${CMAKE_CURRENT_SOURCE_DIR}/..") target_include_directories(common PUBLIC "${CMAKE_CURRENT_SOURCE_DIR}/..") target_link_libraries(common YBaseLib glad libcue Threads::Threads) - -if(ENABLE_OPENGL) - target_sources(common PRIVATE display_renderer_gl.cpp display_renderer_gl.h) - target_link_libraries(common glad) -endif() - -if(MSVC) - target_sources(common PRIVATE display_renderer_d3d.cpp display_renderer_d3d.h) - target_link_libraries(common d3d11.lib) -endif() - -if(MSVC) - enable_language(ASM_MASM) - if(CMAKE_ASM_MASM_COMPILER_WORKS) - target_sources(common PRIVATE fastjmp.asm) - else() - message(ERROR "MASM assembler does not work") - endif() -endif() - diff --git a/src/common/audio.cpp b/src/common/audio.cpp deleted file mode 100644 index 2c3c1567a..000000000 --- a/src/common/audio.cpp +++ /dev/null @@ -1,372 +0,0 @@ -#include "audio.h" -#include "samplerate.h" -#include -#include - -namespace Audio { - -size_t GetBytesPerSample(SampleFormat format) -{ - switch (format) - { - case SampleFormat::Signed8: - case SampleFormat::Unsigned8: - return sizeof(u8); - - case SampleFormat::Signed16: - case SampleFormat::Unsigned16: - return sizeof(u16); - - case SampleFormat::Signed32: - return sizeof(s32); - - case SampleFormat::Float32: - return sizeof(float); - } - - Panic("Unhandled format"); - return 1; -} - -Mixer::Mixer(float output_sample_rate) : m_output_sample_rate(output_sample_rate) -{ - // Render/mix buffers are allocated on-demand. - m_output_buffer = std::make_unique(size_t(output_sample_rate * OutputBufferLengthInSeconds) * - NumOutputChannels * sizeof(OutputFormatType)); -} - -Mixer::~Mixer() {} - -Channel* Mixer::CreateChannel(const char* name, float sample_rate, SampleFormat format, size_t channels) -{ - Assert(!GetChannelByName(name)); - - std::unique_ptr channel = - std::make_unique(name, m_output_sample_rate, sample_rate, format, channels); - m_channels.push_back(std::move(channel)); - return m_channels.back().get(); -} - -void Mixer::RemoveChannel(Channel* channel) -{ - for (auto iter = m_channels.begin(); iter != m_channels.end(); iter++) - { - if (iter->get() == channel) - { - m_channels.erase(iter); - return; - } - } - - Panic("Removing unknown channel."); -} - -Channel* Mixer::GetChannelByName(const char* name) -{ - for (auto& channel : m_channels) - { - if (channel->GetName().Compare(name)) - return channel.get(); - } - - return nullptr; -} - -void Mixer::ClearBuffers() -{ - for (const auto& channel : m_channels) - channel->ClearBuffer(); -} - -void Mixer::CheckRenderBufferSize(size_t num_samples) -{ - size_t buffer_size = num_samples * NumOutputChannels * sizeof(OutputFormatType); - if (m_render_buffer.size() < buffer_size) - m_render_buffer.resize(buffer_size); -} - -AudioBuffer::AudioBuffer(size_t size) : m_buffer(size) {} - -size_t AudioBuffer::GetBufferUsed() const -{ - return m_used; -} - -size_t AudioBuffer::GetContiguousBufferSpace() const -{ - return m_buffer.size() - m_used; -} - -void AudioBuffer::Clear() -{ - m_used = 0; -} - -bool AudioBuffer::Read(void* dst, size_t len) -{ - if (len > m_used) - return false; - - std::memcpy(dst, m_buffer.data(), len); - m_used -= len; - if (m_used > 0) - std::memmove(m_buffer.data(), m_buffer.data() + len, m_used); - - return true; -} - -bool AudioBuffer::GetWritePointer(void** ptr, size_t* len) -{ - size_t free = GetContiguousBufferSpace(); - if (*len > free) - return false; - - *len = free; - *ptr = m_buffer.data() + m_used; - return true; -} - -void AudioBuffer::MoveWritePointer(size_t len) -{ - DebugAssert(m_used + len <= m_buffer.size()); - m_used += len; -} - -bool AudioBuffer::GetReadPointer(const void** ppReadPointer, size_t* pByteCount) const -{ - if (m_used == 0) - return false; - - *ppReadPointer = m_buffer.data(); - *pByteCount = m_used; - return true; -} - -void AudioBuffer::MoveReadPointer(size_t byteCount) -{ - DebugAssert(byteCount <= m_used); - m_used -= byteCount; - if (m_used > 0) - std::memmove(m_buffer.data(), m_buffer.data() + byteCount, m_used); -} - -Channel::Channel(const char* name, float output_sample_rate, float input_sample_rate, SampleFormat format, - size_t channels) - : m_name(name), m_input_sample_rate(input_sample_rate), m_output_sample_rate(output_sample_rate), m_format(format), - m_channels(channels), m_enabled(true), m_input_sample_size(GetBytesPerSample(format)), - m_input_frame_size(GetBytesPerSample(format) * channels), m_output_frame_size(sizeof(float) * channels), - m_input_buffer(u32(float(InputBufferLengthInSeconds* input_sample_rate)) * channels * m_input_sample_size), - m_output_buffer(u32(float(InputBufferLengthInSeconds* output_sample_rate)) * channels * sizeof(OutputFormatType)), - m_resample_buffer(u32(float(InputBufferLengthInSeconds* output_sample_rate)) * channels), - m_resample_ratio(double(output_sample_rate) / double(input_sample_rate)), - m_resampler_state(src_new(SRC_SINC_FASTEST, int(channels), nullptr)) -{ - Assert(m_resampler_state != nullptr); -} - -Channel::~Channel() -{ - src_delete(reinterpret_cast(m_resampler_state)); -} - -size_t Channel::GetFreeInputSamples() -{ - MutexLock lock(m_lock); - return m_input_buffer.GetContiguousBufferSpace() / m_input_frame_size; -} - -void* Channel::ReserveInputSamples(size_t sample_count) -{ - void* write_ptr; - size_t byte_count = sample_count * m_input_frame_size; - - m_lock.Lock(); - - // When the speed limiter is off, we can easily exceed the audio buffer length. - // In this case, just destroy the oldest samples, wrapping around. - while (!m_input_buffer.GetWritePointer(&write_ptr, &byte_count)) - { - size_t bytes_to_remove = byte_count - m_input_buffer.GetContiguousBufferSpace(); - m_input_buffer.MoveReadPointer(bytes_to_remove); - } - - return write_ptr; -} - -void Channel::CommitInputSamples(size_t sample_count) -{ - size_t byte_count = sample_count * m_input_frame_size; - m_input_buffer.MoveWritePointer(byte_count); - - m_lock.Unlock(); -} - -void Channel::ReadSamples(float* destination, size_t num_samples) -{ - MutexLock lock(m_lock); - - while (num_samples > 0) - { - // Can we use what we have buffered? - size_t currently_buffered = m_output_buffer.GetBufferUsed() / m_output_frame_size; - if (currently_buffered > 0) - { - size_t to_read = std::min(num_samples, currently_buffered); - m_output_buffer.Read(destination, to_read * m_output_frame_size); - destination += to_read; - num_samples -= to_read; - if (num_samples == 0) - break; - } - - // Resample num_samples samples - if (m_input_buffer.GetBufferUsed() > 0) - { - if (ResampleInput(num_samples)) - continue; - } - - // If we hit here, it's because we're out of input data. - std::memset(destination, 0, num_samples * m_output_frame_size); - break; - } -} - -void Channel::ChangeSampleRate(float new_sample_rate) -{ - MutexLock lock(m_lock); - InternalClearBuffer(); - - // Calculate the new ratio. - m_input_sample_rate = new_sample_rate; - m_resample_ratio = double(m_output_sample_rate) / double(new_sample_rate); -} - -void Channel::ClearBuffer() -{ - MutexLock lock(m_lock); - InternalClearBuffer(); -} - -void Channel::InternalClearBuffer() -{ - m_input_buffer.Clear(); - src_reset(reinterpret_cast(m_resampler_state)); - m_output_buffer.Clear(); -} - -bool Channel::ResampleInput(size_t num_output_samples) -{ - const void* in_buf; - size_t in_bufsize; - size_t in_num_frames; - size_t in_num_samples; - if (!m_input_buffer.GetReadPointer(&in_buf, &in_bufsize)) - return false; - - in_num_frames = in_bufsize / m_input_frame_size; - in_num_samples = in_num_frames * m_channels; - if (in_num_frames == 0) - return false; - - // Cap output samples at buffer size. - num_output_samples = std::min(num_output_samples, m_output_buffer.GetContiguousBufferSpace() / m_output_frame_size); - Assert((num_output_samples * m_channels) < m_resample_buffer.size()); - - // Only use as many input samples as needed. - void* out_buf; - size_t out_bufsize = num_output_samples * m_output_frame_size; - if (!m_output_buffer.GetWritePointer(&out_buf, &out_bufsize)) - return false; - - // Set up resampling. - SRC_DATA resample_data; - resample_data.data_out = reinterpret_cast(out_buf); - resample_data.output_frames = static_cast(num_output_samples); - resample_data.input_frames_used = 0; - resample_data.output_frames_gen = 0; - resample_data.end_of_input = 0; - resample_data.src_ratio = m_resample_ratio; - - // Convert from whatever format the input is in to float. - switch (m_format) - { - case SampleFormat::Signed8: - { - const s8* in_samples_typed = reinterpret_cast(in_buf); - for (size_t i = 0; i < in_num_samples; i++) - m_resample_buffer[i] = float(in_samples_typed[i]) / float(0x80); - - resample_data.input_frames = long(in_num_frames); - resample_data.data_in = m_resample_buffer.data(); - } - break; - case SampleFormat::Unsigned8: - { - const s8* in_samples_typed = reinterpret_cast(in_buf); - for (size_t i = 0; i < in_num_samples; i++) - m_resample_buffer[i] = float(int(in_samples_typed[i]) - 128) / float(0x80); - - resample_data.input_frames = long(in_num_frames); - resample_data.data_in = m_resample_buffer.data(); - } - break; - case SampleFormat::Signed16: - src_short_to_float_array(reinterpret_cast(in_buf), m_resample_buffer.data(), int(in_num_samples)); - resample_data.input_frames = long(in_num_frames); - resample_data.data_in = m_resample_buffer.data(); - break; - - case SampleFormat::Unsigned16: - { - const u16* in_samples_typed = reinterpret_cast(in_buf); - for (size_t i = 0; i < in_num_samples; i++) - m_resample_buffer[i] = float(int(in_samples_typed[i]) - 32768) / float(0x8000); - - resample_data.input_frames = long(in_num_frames); - resample_data.data_in = m_resample_buffer.data(); - } - break; - - case SampleFormat::Signed32: - src_int_to_float_array(reinterpret_cast(in_buf), m_resample_buffer.data(), int(in_num_samples)); - resample_data.input_frames = long(in_num_frames); - resample_data.data_in = m_resample_buffer.data(); - break; - - case SampleFormat::Float32: - default: - resample_data.input_frames = long(in_num_frames); - resample_data.data_in = reinterpret_cast(in_buf); - break; - } - - // Actually perform the resampling. - int process_result = src_process(reinterpret_cast(m_resampler_state), &resample_data); - Assert(process_result == 0); - - // Update buffer pointers. - m_input_buffer.MoveReadPointer(size_t(resample_data.input_frames_used) * m_input_frame_size); - m_output_buffer.MoveWritePointer(size_t(resample_data.output_frames_gen) * m_output_frame_size); - return true; -} - -NullMixer::NullMixer() : Mixer(44100) {} - -NullMixer::~NullMixer() {} - -std::unique_ptr NullMixer::Create() -{ - return std::make_unique(); -} - -void NullMixer::RenderSamples(size_t output_samples) -{ - CheckRenderBufferSize(output_samples); - - // Consume everything from the input buffers. - for (auto& channel : m_channels) - channel->ReadSamples(m_render_buffer.data(), output_samples); -} - -} // namespace Audio diff --git a/src/common/audio.h b/src/common/audio.h deleted file mode 100644 index abf759783..000000000 --- a/src/common/audio.h +++ /dev/null @@ -1,184 +0,0 @@ -#pragma once - -#include -#include -#include - -#include "YBaseLib/CircularBuffer.h" -#include "YBaseLib/Mutex.h" -#include "YBaseLib/MutexLock.h" -#include "YBaseLib/String.h" -#include "types.h" - -namespace Audio { - -class Channel; -class Mixer; - -enum class SampleFormat -{ - Signed8, - Unsigned8, - Signed16, - Unsigned16, - Signed32, - Float32 -}; - -// Constants for the maximums we support. -constexpr size_t NumOutputChannels = 2; - -// We buffer one second of data either way. -constexpr float InputBufferLengthInSeconds = 1.0f; -constexpr float OutputBufferLengthInSeconds = 1.0f; - -// Audio render frequency. We render the elapsed simulated time worth of audio at this interval. -// Currently it is every 50ms, or 20hz. For audio channels, it's recommended to render at twice this -// frequency in order to ensure that there is always data ready. This could also be mitigated by buffering. -constexpr u32 MixFrequency = 20; -constexpr SimulationTime MixInterval = SimulationTime(1000000000) / SimulationTime(MixFrequency); - -// We buffer 10ms of input before rendering any samples, that way we don't get buffer underruns. -constexpr SimulationTime ChannelDelayTimeInSimTime = SimulationTime(10000000); - -// Output format type. -constexpr SampleFormat OutputFormat = SampleFormat::Float32; -using OutputFormatType = float; - -// Get the number of bytes for each element of a sample format. -size_t GetBytesPerSample(SampleFormat format); - -// Base audio class, handles mixing/resampling -class Mixer -{ -public: - Mixer(float output_sample_rate); - virtual ~Mixer(); - - // Disable all outputs. - // This prevents any samples being written to the device, but still consumes samples. - bool IsMuted() const { return m_muted; } - void SetMuted(bool muted) { m_muted = muted; } - - // Adds a channel to the audio mixer. - // This pointer is owned by the audio class. - Channel* CreateChannel(const char* name, float sample_rate, SampleFormat format, size_t channels); - - // Drops a channel from the audio mixer. - void RemoveChannel(Channel* channel); - - // Looks up channel by name. Shouldn't really be needed. - Channel* GetChannelByName(const char* name); - - // Clears all buffers. Use when changing speed limiter state, or loading state. - void ClearBuffers(); - -protected: - void CheckRenderBufferSize(size_t num_samples); - - float m_output_sample_rate; - float m_output_sample_carry = 0.0f; - bool m_muted = false; - - // Input channels. - std::vector> m_channels; - - // Output buffer. - std::vector m_render_buffer; - std::unique_ptr m_output_buffer; -}; - -class AudioBuffer -{ -public: - AudioBuffer(size_t size); - - size_t GetBufferUsed() const; - size_t GetContiguousBufferSpace() const; - - void Clear(); - - bool Read(void* dst, size_t len); - - bool GetWritePointer(void** ptr, size_t* len); - - void MoveWritePointer(size_t len); - - bool GetReadPointer(const void** ppReadPointer, size_t* pByteCount) const; - - void MoveReadPointer(size_t byteCount); - -private: - std::vector m_buffer; - size_t m_used = 0; -}; - -// A channel, or source of audio for the mixer. -class Channel -{ -public: - Channel(const char* name, float output_sample_rate, float input_sample_rate, SampleFormat format, size_t channels); - ~Channel(); - - const String& GetName() const { return m_name; } - float GetSampleRate() const { return m_input_sample_rate; } - SampleFormat GetFormat() const { return m_format; } - size_t GetChannels() const { return m_channels; } - - // When the channel is disabled, adding samples will have no effect, and it won't affect the output. - bool IsEnabled() const { return m_enabled; } - void SetEnabled(bool enabled) { m_enabled = enabled; } - - // This sample_count is the number of samples per channel, so two-channel will be half of the total values. - size_t GetFreeInputSamples(); - void* ReserveInputSamples(size_t sample_count); - void CommitInputSamples(size_t sample_count); - - // Resamples at most num_output_samples, the actual number can be lower if there isn't enough input data. - bool ResampleInput(size_t num_output_samples); - - // Render n output samples. If not enough input data is in the buffer, set to zero. - void ReadSamples(float* destination, size_t num_samples); - - // Changes the frequency of the input data. Flushes the resample buffer. - void ChangeSampleRate(float new_sample_rate); - - // Clears the buffer. Use when loading state or changing speed limiter. - void ClearBuffer(); - -private: - void InternalClearBuffer(); - - String m_name; - float m_input_sample_rate; - float m_output_sample_rate; - SampleFormat m_format; - size_t m_channels; - bool m_enabled; - - Mutex m_lock; - // std::unique_ptr m_input_buffer; - size_t m_input_sample_size; - size_t m_input_frame_size; - size_t m_output_frame_size; - AudioBuffer m_input_buffer; - AudioBuffer m_output_buffer; - std::vector m_resample_buffer; - double m_resample_ratio; - void* m_resampler_state; -}; - -// Null audio sink/mixer -class NullMixer : public Mixer -{ -public: - NullMixer(); - virtual ~NullMixer(); - - static std::unique_ptr Create(); - -protected: - void RenderSamples(size_t output_samples); -}; - -} // namespace Audio diff --git a/src/common/common.vcxproj b/src/common/common.vcxproj index 83f3a96a6..784798184 100644 --- a/src/common/common.vcxproj +++ b/src/common/common.vcxproj @@ -35,56 +35,31 @@ - - - - - - - - - - - - - - - - - - - - - - - - - {43540154-9e1e-409c-834f-b84be5621388} diff --git a/src/common/common.vcxproj.filters b/src/common/common.vcxproj.filters index bde502a5b..08cc215ac 100644 --- a/src/common/common.vcxproj.filters +++ b/src/common/common.vcxproj.filters @@ -3,18 +3,6 @@ - - - - - - - - - - - - @@ -25,16 +13,6 @@ - - - - - - - - - - @@ -48,7 +26,4 @@ - - - \ No newline at end of file diff --git a/src/common/display.cpp b/src/common/display.cpp deleted file mode 100644 index 4863005a4..000000000 --- a/src/common/display.cpp +++ /dev/null @@ -1,529 +0,0 @@ -#include "display.h" -#include "YBaseLib/Assert.h" -#include "YBaseLib/Math.h" -#include "display_renderer.h" -#include -#include - -Display::Display(DisplayRenderer* manager, const String& name, Type type, u8 priority) - : m_renderer(manager), m_name(name), m_type(type), m_priority(priority) -{ -} - -Display::~Display() -{ - m_renderer->RemoveDisplay(this); - DestroyFramebuffer(&m_front_buffer); - DestroyFramebuffer(&m_back_buffers[0]); - DestroyFramebuffer(&m_back_buffers[1]); -} - -void Display::SetEnable(bool enabled) -{ - std::lock_guard guard(m_buffer_lock); - if (m_enabled == enabled) - return; - - m_enabled = enabled; - if (enabled) - m_renderer->DisplayEnabled(this); - else - m_renderer->DisplayDisabled(this); -} - -void Display::SetActive(bool active) -{ - m_active = active; -} - -void Display::SetDisplayAspectRatio(u32 numerator, u32 denominator) -{ - if (m_display_aspect_numerator == numerator && m_display_aspect_denominator == denominator) - return; - - m_display_aspect_numerator = numerator; - m_display_aspect_denominator = denominator; - ResizeDisplay(); -} - -void Display::ResizeDisplay(u32 width /*= 0*/, u32 height /*= 0*/) -{ - // If width/height == 0, use aspect ratio to calculate size - if (width == 0 && height == 0) - { - // TODO: Remove floating point math here - // float pixel_aspect_ratio = static_cast(m_framebuffer_width) / static_cast(m_framebuffer_height); - float display_aspect_ratio = - static_cast(m_display_aspect_numerator) / static_cast(m_display_aspect_denominator); - // float ratio = pixel_aspect_ratio / display_aspect_ratio; - m_display_width = std::max(1u, m_framebuffer_width * m_display_scale); - m_display_height = std::max(1u, static_cast(static_cast(m_display_width) / display_aspect_ratio)); - } - else - { - DebugAssert(width > 0 && height > 0); - m_display_width = width * m_display_scale; - m_display_height = height * m_display_scale; - } - - m_renderer->DisplayResized(this); -} - -void Display::ClearFramebuffer() -{ - if (m_back_buffers[0].width > 0 && m_back_buffers[0].height > 0) - std::memset(m_back_buffers[0].data, 0, m_back_buffers[0].stride * m_back_buffers[0].height); - - SwapFramebuffer(); -} - -void Display::SwapFramebuffer() -{ - // Make it visible to the render thread. - { - std::lock_guard guard(m_buffer_lock); - std::swap(m_back_buffers[0].data, m_back_buffers[1].data); - std::swap(m_back_buffers[0].palette, m_back_buffers[1].palette); - std::swap(m_back_buffers[0].width, m_back_buffers[1].width); - std::swap(m_back_buffers[0].height, m_back_buffers[1].height); - std::swap(m_back_buffers[0].stride, m_back_buffers[1].stride); - std::swap(m_back_buffers[0].format, m_back_buffers[1].format); - m_back_buffers[1].dirty = true; - m_renderer->DisplayFramebufferSwapped(this); - } - - // Ensure backbuffer is up to date. - if (m_back_buffers[0].width != m_framebuffer_width || m_back_buffers[0].height != m_framebuffer_height || - m_back_buffers[0].format != m_framebuffer_format) - { - AllocateFramebuffer(&m_back_buffers[0]); - } - - AddFrameRendered(); -} - -bool Display::UpdateFrontbuffer() -{ - std::lock_guard guard(m_buffer_lock); - if (!m_back_buffers[1].dirty) - return false; - - std::swap(m_front_buffer.data, m_back_buffers[1].data); - std::swap(m_front_buffer.palette, m_back_buffers[1].palette); - std::swap(m_front_buffer.width, m_back_buffers[1].width); - std::swap(m_front_buffer.height, m_back_buffers[1].height); - std::swap(m_front_buffer.stride, m_back_buffers[1].stride); - std::swap(m_front_buffer.format, m_back_buffers[1].format); - m_back_buffers[1].dirty = false; - m_front_buffer.dirty = true; - return true; -} - -void Display::AllocateFramebuffer(Framebuffer* fbuf) -{ - DestroyFramebuffer(fbuf); - - fbuf->width = m_framebuffer_width; - fbuf->height = m_framebuffer_height; - fbuf->format = m_framebuffer_format; - fbuf->stride = 0; - - if (m_framebuffer_width > 0 && m_framebuffer_height > 0) - { - switch (m_framebuffer_format) - { - case FramebufferFormat::RGB8: - case FramebufferFormat::BGR8: - fbuf->stride = m_framebuffer_width * 3; - break; - - case FramebufferFormat::RGBX8: - case FramebufferFormat::BGRX8: - fbuf->stride = m_framebuffer_width * 4; - break; - - case FramebufferFormat::RGB565: - case FramebufferFormat::RGB555: - case FramebufferFormat::BGR555: - case FramebufferFormat::BGR565: - fbuf->stride = m_framebuffer_width * 2; - break; - - case FramebufferFormat::C8RGBX8: - fbuf->stride = m_framebuffer_width; - break; - } - - fbuf->data = new byte[fbuf->stride * m_framebuffer_height]; - Y_memzero(fbuf->data, fbuf->stride * m_framebuffer_height); - - if (IsPaletteFormat(m_framebuffer_format)) - { - fbuf->palette = new u32[PALETTE_SIZE]; - Y_memzero(fbuf->palette, sizeof(u32) * PALETTE_SIZE); - } - } -} - -void Display::DestroyFramebuffer(Framebuffer* fbuf) -{ - delete[] fbuf->palette; - fbuf->palette = nullptr; - - delete[] fbuf->data; - fbuf->data = nullptr; - fbuf->width = 0; - fbuf->height = 0; - fbuf->stride = 0; -} - -void Display::ResizeFramebuffer(u32 width, u32 height) -{ - if (m_framebuffer_width == width && m_framebuffer_height == height) - return; - - m_framebuffer_width = width; - m_framebuffer_height = height; - AllocateFramebuffer(&m_back_buffers[0]); -} - -void Display::ChangeFramebufferFormat(FramebufferFormat new_format) -{ - if (m_framebuffer_format == new_format) - return; - - m_framebuffer_format = new_format; - AllocateFramebuffer(&m_back_buffers[0]); -} - -void Display::SetPixel(u32 x, u32 y, u8 r, u8 g, u8 b) -{ - SetPixel(x, y, PackRGBX(r, g, b)); -} - -void Display::SetPixel(u32 x, u32 y, u32 rgb) -{ - DebugAssert(x < m_framebuffer_width && y < m_framebuffer_height); - - // Assumes LE order in rgb and framebuffer. - switch (m_framebuffer_format) - { - case FramebufferFormat::RGB8: - case FramebufferFormat::BGR8: - std::memcpy(&m_back_buffers[0].data[y * m_back_buffers[0].stride + x * 3], &rgb, 3); - break; - - case FramebufferFormat::RGBX8: - case FramebufferFormat::BGRX8: - rgb |= 0xFF000000; - std::memcpy(&m_back_buffers[0].data[y * m_back_buffers[0].stride + x * 4], &rgb, 4); - break; - - case FramebufferFormat::RGB555: - case FramebufferFormat::BGR555: - rgb &= 0x7FFF; - std::memcpy(&m_back_buffers[0].data[y * m_back_buffers[0].stride + x * 2], &rgb, 2); - break; - - case FramebufferFormat::RGB565: - case FramebufferFormat::BGR565: - std::memcpy(&m_back_buffers[0].data[y * m_back_buffers[0].stride + x * 2], &rgb, 2); - break; - - case FramebufferFormat::C8RGBX8: - m_back_buffers[0].data[y * m_back_buffers[0].stride + x] = Truncate8(rgb); - break; - } -} - -void Display::CopyToFramebuffer(const void* pixels, u32 stride) -{ - if (stride == m_back_buffers[0].stride) - { - std::memcpy(m_back_buffers[0].data, pixels, stride * m_framebuffer_height); - return; - } - - const byte* pixels_src = reinterpret_cast(pixels); - byte* pixels_dst = m_back_buffers[0].data; - u32 copy_stride = std::min(m_back_buffers[0].stride, stride); - for (u32 i = 0; i < m_framebuffer_height; i++) - { - std::memcpy(pixels_dst, pixels_src, copy_stride); - pixels_src += stride; - pixels_dst += m_back_buffers[0].stride; - } -} - -void Display::RepeatFrame() -{ - // Don't change the framebuffer. - AddFrameRendered(); -} - -void Display::CopyPalette(u8 start_index, u32 num_entries, const u32* entries) -{ - DebugAssert(IsPaletteFormat(m_framebuffer_format) && (ZeroExtend32(start_index) + num_entries) <= PALETTE_SIZE); - std::copy_n(entries, num_entries, &m_back_buffers[0].palette[start_index]); -} - -void Display::AddFrameRendered() -{ - m_frames_rendered++; - - // Update every 500ms - float dt = float(m_frame_counter_timer.GetTimeSeconds()); - if (dt >= 1.0f) - { - m_fps = float(m_frames_rendered) * (1.0f / dt); - m_frames_rendered = 0; - m_frame_counter_timer.Reset(); - } -} - -inline u32 ConvertRGB555ToRGBX8888(u16 color) -{ - u8 r = Truncate8(color & 31); - u8 g = Truncate8((color >> 5) & 31); - u8 b = Truncate8((color >> 10) & 31); - - // 00012345 -> 1234545 - b = (b << 3) | (b >> 3); - g = (g << 3) | (g >> 3); - r = (r << 3) | (r >> 3); - - return UINT32_C(0xFF000000) | ZeroExtend32(r) | (ZeroExtend32(g) << 8) | (ZeroExtend32(b) << 16); -} - -inline u32 ConvertRGB565ToRGBX8888(u16 color) -{ - u8 r = Truncate8(color & 31); - u8 g = Truncate8((color >> 5) & 63); - u8 b = Truncate8((color >> 11) & 31); - - // 00012345 -> 1234545 / 00123456 -> 12345656 - r = (r << 3) | (r >> 3); - g = (g << 2) | (g >> 4); - b = (b << 3) | (b >> 3); - - return UINT32_C(0xFF000000) | ZeroExtend32(r) | (ZeroExtend32(g) << 8) | (ZeroExtend32(b) << 16); -} - -inline u32 ConvertBGR555ToRGBX8888(u16 color) -{ - u8 b = Truncate8(color & 31); - u8 g = Truncate8((color >> 5) & 31); - u8 r = Truncate8((color >> 10) & 31); - - // 00012345 -> 1234545 - b = (b << 3) | (b >> 3); - g = (g << 3) | (g >> 3); - r = (r << 3) | (r >> 3); - - return UINT32_C(0xFF000000) | ZeroExtend32(r) | (ZeroExtend32(g) << 8) | (ZeroExtend32(b) << 16); -} - -inline u32 ConvertBGR565ToRGBX8888(u16 color) -{ - u8 b = Truncate8(color & 31); - u8 g = Truncate8((color >> 5) & 63); - u8 r = Truncate8((color >> 11) & 31); - - // 00012345 -> 1234545 / 00123456 -> 12345656 - b = (b << 3) | (b >> 3); - g = (g << 2) | (g >> 4); - r = (r << 3) | (r >> 3); - - return UINT32_C(0xFF000000) | ZeroExtend32(r) | (ZeroExtend32(g) << 8) | (ZeroExtend32(b) << 16); -} - -void Display::CopyFramebufferToRGBA8Buffer(const Framebuffer* fbuf, void* dst, u32 dst_stride) -{ - const byte* src_ptr = reinterpret_cast(fbuf->data); - byte* dst_ptr = reinterpret_cast(dst); - - switch (fbuf->format) - { - case FramebufferFormat::RGB8: - { - // yuck.. TODO optimize this, using vectorization? - for (u32 row = 0; row < fbuf->height; row++) - { - const byte* src_row_ptr = src_ptr; - byte* dst_row_ptr = dst_ptr; - for (u32 col = 0; col < fbuf->width; col++) - { - u32 ocol = 0xFF000000; - ocol |= ZeroExtend32(*(src_row_ptr++)); // R - ocol |= ZeroExtend32(*(src_row_ptr++)) << 8; // G - ocol |= ZeroExtend32(*(src_row_ptr++)) << 16; // B - std::memcpy(dst_row_ptr, &ocol, sizeof(ocol)); - dst_row_ptr += sizeof(ocol); - } - - src_ptr += fbuf->stride; - dst_ptr += dst_stride; - } - } - break; - - case FramebufferFormat::RGBX8: - { - const u32 copy_size = std::min(fbuf->stride, dst_stride); - for (u32 row = 0; row < fbuf->height; row++) - { - std::memcpy(dst_ptr, src_ptr, copy_size); - src_ptr += fbuf->stride; - dst_ptr += dst_stride; - } - } - break; - - case FramebufferFormat::BGR8: - { - // yuck.. TODO optimize this, using vectorization? - for (u32 row = 0; row < fbuf->height; row++) - { - const byte* src_row_ptr = src_ptr; - byte* dst_row_ptr = dst_ptr; - for (u32 col = 0; col < fbuf->width; col++) - { - u32 ocol = 0xFF000000; - ocol |= ZeroExtend32(*(src_row_ptr++)) << 16; // B - ocol |= ZeroExtend32(*(src_row_ptr++)) << 8; // G - ocol |= ZeroExtend32(*(src_row_ptr++)); // R - std::memcpy(dst_row_ptr, &ocol, sizeof(ocol)); - dst_row_ptr += sizeof(ocol); - } - - src_ptr += fbuf->stride; - dst_ptr += dst_stride; - } - } - break; - - case FramebufferFormat::BGRX8: - { - for (u32 row = 0; row < fbuf->height; row++) - { - const u32* row_src_ptr = reinterpret_cast(src_ptr); - u32* row_dst_ptr = reinterpret_cast(dst_ptr); - for (u32 col = 0; col < fbuf->width; col++) - { - const u32 pix = *(row_src_ptr++); - *(row_dst_ptr++) = - (pix & UINT32_C(0xFF00FF00)) | ((pix & UINT32_C(0xFF)) << 16) | ((pix >> 16) & UINT32_C(0xFF)); - } - src_ptr += fbuf->stride; - dst_ptr += dst_stride; - } - } - break; - - case FramebufferFormat::RGB555: - { - for (u32 row = 0; row < fbuf->height; row++) - { - const byte* src_row_ptr = src_ptr; - byte* dst_row_ptr = dst_ptr; - for (u32 col = 0; col < fbuf->width; col++) - { - u16 icol; - std::memcpy(&icol, src_row_ptr, sizeof(icol)); - src_row_ptr += sizeof(icol); - u32 ocol = ConvertRGB555ToRGBX8888(icol); - std::memcpy(dst_row_ptr, &ocol, sizeof(ocol)); - dst_row_ptr += sizeof(ocol); - } - - src_ptr += fbuf->stride; - dst_ptr += dst_stride; - } - } - break; - - case FramebufferFormat::RGB565: - { - for (u32 row = 0; row < fbuf->height; row++) - { - const byte* src_row_ptr = src_ptr; - byte* dst_row_ptr = dst_ptr; - for (u32 col = 0; col < fbuf->width; col++) - { - u16 icol; - std::memcpy(&icol, src_row_ptr, sizeof(icol)); - src_row_ptr += sizeof(icol); - u32 ocol = ConvertRGB565ToRGBX8888(icol); - std::memcpy(dst_row_ptr, &ocol, sizeof(ocol)); - dst_row_ptr += sizeof(ocol); - } - - src_ptr += fbuf->stride; - dst_ptr += dst_stride; - } - } - break; - - case FramebufferFormat::BGR555: - { - for (u32 row = 0; row < fbuf->height; row++) - { - const byte* src_row_ptr = src_ptr; - byte* dst_row_ptr = dst_ptr; - for (u32 col = 0; col < fbuf->width; col++) - { - u16 icol; - std::memcpy(&icol, src_row_ptr, sizeof(icol)); - src_row_ptr += sizeof(icol); - u32 ocol = ConvertBGR555ToRGBX8888(icol); - std::memcpy(dst_row_ptr, &ocol, sizeof(ocol)); - dst_row_ptr += sizeof(ocol); - } - - src_ptr += fbuf->stride; - dst_ptr += dst_stride; - } - } - break; - - case FramebufferFormat::BGR565: - { - for (u32 row = 0; row < fbuf->height; row++) - { - const byte* src_row_ptr = src_ptr; - byte* dst_row_ptr = dst_ptr; - for (u32 col = 0; col < fbuf->width; col++) - { - u16 icol; - std::memcpy(&icol, src_row_ptr, sizeof(icol)); - src_row_ptr += sizeof(icol); - u32 ocol = ConvertBGR565ToRGBX8888(icol); - std::memcpy(dst_row_ptr, &ocol, sizeof(ocol)); - dst_row_ptr += sizeof(ocol); - } - - src_ptr += fbuf->stride; - dst_ptr += dst_stride; - } - } - break; - - case FramebufferFormat::C8RGBX8: - { - for (u32 row = 0; row < fbuf->height; row++) - { - const byte* src_row_ptr = src_ptr; - byte* dst_row_ptr = dst_ptr; - for (u32 col = 0; col < fbuf->width; col++) - { - std::memcpy(dst_row_ptr, &fbuf->palette[ZeroExtend32(*src_row_ptr++)], sizeof(u32)); - dst_row_ptr += sizeof(u32); - } - - src_ptr += fbuf->stride; - dst_ptr += dst_stride; - } - } - break; - } -} diff --git a/src/common/display.h b/src/common/display.h deleted file mode 100644 index e0819b076..000000000 --- a/src/common/display.h +++ /dev/null @@ -1,146 +0,0 @@ -#pragma once -#include "YBaseLib/Common.h" -#include "YBaseLib/String.h" -#include "YBaseLib/Timer.h" -#include "types.h" -#include -#include - -class DisplayRenderer; - -class Display -{ -public: - enum : u8 - { - // Priority for primary display. The display with the highest priority will be shown. - DEFAULT_PRIORITY = 1 - }; - enum : u32 - { - // Number of colours in paletted modes. - PALETTE_SIZE = 256 - }; - enum class Type : u8 - { - Primary, - Secondary - }; - enum class FramebufferFormat : u8 - { - RGB8, - RGBX8, - BGR8, - BGRX8, - RGB565, - RGB555, - BGR565, - BGR555, - C8RGBX8, // 8-bit palette, 32-bit colours - }; - - Display(DisplayRenderer* renderer, const String& name, Type type, u8 priority); - virtual ~Display(); - - const String& GetName() const { return m_name; } - Type GetType() const { return m_type; } - u8 GetPriority() const { return m_priority; } - - bool IsEnabled() const { return m_enabled; } - bool IsActive() const { return m_active; } - void SetEnable(bool enabled); - void SetActive(bool active); - - u32 GetFramesRendered() const { return m_frames_rendered; } - float GetFramesPerSecond() const { return m_fps; } - void ResetFramesRendered() { m_frames_rendered = 0; } - - u32 GetDisplayWidth() const { return m_display_width; } - u32 GetDisplayHeight() const { return m_display_height; } - void SetDisplayScale(u32 scale) { m_display_scale = scale; } - void SetDisplayAspectRatio(u32 numerator, u32 denominator); - void ResizeDisplay(u32 width = 0, u32 height = 0); - - u32 GetFramebufferWidth() const { return m_framebuffer_width; } - u32 GetFramebufferHeight() const { return m_framebuffer_height; } - FramebufferFormat GetFramebufferFormat() const { return m_framebuffer_format; } - - void ClearFramebuffer(); - void ResizeFramebuffer(u32 width, u32 height); - void ChangeFramebufferFormat(FramebufferFormat new_format); - void SwapFramebuffer(); - - static constexpr u32 PackRGBX(u8 r, u8 g, u8 b) - { - return (static_cast(r) << 0) | (static_cast(g) << 8) | (static_cast(b) << 16) | - (static_cast(0xFF) << 24); - } - - // Changes pixels in the backbuffer. - byte* GetFramebufferPointer() const { return m_back_buffers[0].data; } - u32 GetFramebufferStride() const { return m_back_buffers[0].stride; } - void SetPixel(u32 x, u32 y, u8 r, u8 g, u8 b); - void SetPixel(u32 x, u32 y, u32 rgb); - void CopyToFramebuffer(const void* pixels, u32 stride); - void RepeatFrame(); - - // Update palette. - const u32* GetPalettePointer() const { return m_back_buffers[0].palette; } - void SetPaletteEntry(u8 index, u32 value) const { m_back_buffers[0].palette[index] = value; } - void CopyPalette(u8 start_index, u32 num_entries, const u32* entries); - - // Returns true if the specified format is a paletted format. - static constexpr bool IsPaletteFormat(FramebufferFormat format) { return (format == FramebufferFormat::C8RGBX8); } - -protected: - static constexpr u32 NUM_BACK_BUFFERS = 2; - - struct Framebuffer - { - byte* data = nullptr; - u32* palette = nullptr; - u32 width = 0; - u32 height = 0; - u32 stride = 0; - FramebufferFormat format = FramebufferFormat::RGBX8; - bool dirty = false; - }; - - void AddFrameRendered(); - void AllocateFramebuffer(Framebuffer* fbuf); - void DestroyFramebuffer(Framebuffer* fbuf); - - // Updates the front buffer. Returns false if the no swap has occurred. - bool UpdateFrontbuffer(); - - // Helper for converting/copying a framebuffer. - static void CopyFramebufferToRGBA8Buffer(const Framebuffer* fbuf, void* dst, u32 dst_stride); - - DisplayRenderer* m_renderer; - String m_name; - - Type m_type; - u8 m_priority; - - u32 m_framebuffer_width = 0; - u32 m_framebuffer_height = 0; - FramebufferFormat m_framebuffer_format = FramebufferFormat::RGBX8; - - Framebuffer m_front_buffer; - Framebuffer m_back_buffers[NUM_BACK_BUFFERS]; - std::mutex m_buffer_lock; - - u32 m_display_width = 640; - u32 m_display_height = 480; - u32 m_display_scale = 1; - u32 m_display_aspect_numerator = 1; - u32 m_display_aspect_denominator = 1; - - static constexpr u32 FRAME_COUNTER_FRAME_COUNT = 100; - Timer m_frame_counter_timer; - u32 m_frames_rendered = 0; - float m_fps = 0.0f; - - bool m_enabled = true; - bool m_active = true; -}; diff --git a/src/common/display_renderer.cpp b/src/common/display_renderer.cpp deleted file mode 100644 index 42ccc73b8..000000000 --- a/src/common/display_renderer.cpp +++ /dev/null @@ -1,196 +0,0 @@ -#include "display_renderer.h" -#include "display_renderer_d3d.h" -#include "display_renderer_gl.h" - -DisplayRenderer::DisplayRenderer(WindowHandleType window_handle, u32 window_width, u32 window_height) - : m_window_handle(window_handle), m_window_width(window_width), m_window_height(window_height) -{ -} - -DisplayRenderer::~DisplayRenderer() -{ - Assert(m_primary_displays.empty()); - Assert(m_secondary_displays.empty()); -} - -float DisplayRenderer::GetPrimaryDisplayFramesPerSecond() -{ - std::lock_guard guard(m_display_lock); - if (m_active_displays.empty()) - return 0.0f; - - return m_active_displays.front()->GetFramesPerSecond(); -} - -bool DisplayRenderer::Initialize() -{ - return true; -} - -void DisplayRenderer::AddDisplay(Display* display) -{ - std::lock_guard guard(m_display_lock); - - if (display->GetType() == Display::Type::Primary) - m_primary_displays.push_back(display); - else - m_secondary_displays.push_back(display); - - UpdateActiveDisplays(); -} - -void DisplayRenderer::RemoveDisplay(Display* display) -{ - std::lock_guard guard(m_display_lock); - - auto& container = (display->GetType() == Display::Type::Primary) ? m_primary_displays : m_secondary_displays; - auto iter = std::find(container.begin(), container.end(), display); - if (iter != container.end()) - container.erase(iter); - - UpdateActiveDisplays(); -} - -void DisplayRenderer::DisplayEnabled(Display* display) -{ - std::lock_guard guard(m_display_lock); - UpdateActiveDisplays(); -} - -void DisplayRenderer::DisplayDisabled(Display* display) -{ - std::lock_guard guard(m_display_lock); - UpdateActiveDisplays(); -} - -void DisplayRenderer::DisplayResized(Display* display) {} - -void DisplayRenderer::DisplayFramebufferSwapped(Display* display) {} - -void DisplayRenderer::WindowResized(u32 window_width, u32 window_height) -{ - m_window_width = window_width; - m_window_height = window_height; -} - -void DisplayRenderer::UpdateActiveDisplays() -{ - m_active_displays.clear(); - - // Find the primary display with the highest priority, and enabled. - Display* primary_display = nullptr; - for (Display* dpy : m_primary_displays) - { - dpy->SetActive(false); - if (dpy->IsEnabled() && (!primary_display || dpy->GetPriority() > primary_display->GetPriority())) - primary_display = dpy; - } - if (primary_display) - { - primary_display->SetActive(true); - m_active_displays.push_back(primary_display); - } - - // Add all enabled secondary displays. - for (Display* dpy : m_secondary_displays) - { - if (dpy->IsEnabled()) - { - dpy->SetActive(true); - m_active_displays.push_back(dpy); - } - else - { - dpy->SetActive(false); - } - } -} - -std::pair DisplayRenderer::GetDisplayRenderSize(const Display* display) -{ - Assert(!m_active_displays.empty()); - const u32 window_width = m_window_width / u32(m_active_displays.size()); - const u32 window_height = u32(std::max(1, int(m_window_height) - int(m_top_padding))); - const float display_ratio = float(display->GetDisplayWidth()) / float(display->GetDisplayHeight()); - const float window_ratio = float(window_width) / float(window_height); - u32 viewport_width; - u32 viewport_height; - if (window_ratio >= display_ratio) - { - viewport_width = u32(float(window_height) * display_ratio); - viewport_height = u32(window_height); - } - else - { - viewport_width = u32(window_width); - viewport_height = u32(float(window_width) / display_ratio); - } - - return std::make_pair(viewport_width, viewport_height); -} - -namespace { -class DisplayRendererNull final : public DisplayRenderer -{ -public: - DisplayRendererNull(WindowHandleType window_handle, u32 window_width, u32 window_height) - : DisplayRenderer(window_handle, window_width, window_height) - { - } - - BackendType GetBackendType() override { return DisplayRenderer::BackendType::Null; } - - virtual std::unique_ptr CreateDisplay(const char* name, Display::Type type, - u8 priority = Display::DEFAULT_PRIORITY) override - { - auto display = std::make_unique(this, name, type, priority); - AddDisplay(display.get()); - return display; - } - - virtual bool BeginFrame() override { return true; } - - virtual void RenderDisplays() override {} - - virtual void EndFrame() override {} -}; -} // namespace - -DisplayRenderer::BackendType DisplayRenderer::GetDefaultBackendType() -{ -#ifdef Y_COMPILER_MSVC - return BackendType::Direct3D; -#else - return BackendType::OpenGL; -#endif -} - -std::unique_ptr DisplayRenderer::Create(BackendType backend, WindowHandleType window_handle, - u32 window_width, u32 window_height) -{ - std::unique_ptr renderer; - switch (backend) - { - case BackendType::Null: - renderer = std::make_unique(window_handle, window_width, window_height); - break; - -#ifdef Y_COMPILER_MSVC - case BackendType::Direct3D: - renderer = std::make_unique(window_handle, window_width, window_height); - break; -#endif - - case BackendType::OpenGL: - renderer = std::make_unique(window_handle, window_width, window_height); - break; - - default: - return nullptr; - } - - if (!renderer->Initialize()) - return nullptr; - - return renderer; -} diff --git a/src/common/display_renderer.h b/src/common/display_renderer.h deleted file mode 100644 index 93fc7fb81..000000000 --- a/src/common/display_renderer.h +++ /dev/null @@ -1,72 +0,0 @@ -#pragma once -#include "display.h" -#include -#include -#include - -class DisplayRenderer; - -class DisplayRenderer -{ -public: - using WindowHandleType = void*; - enum class BackendType - { - Null, - Direct3D, - OpenGL - }; - - DisplayRenderer(WindowHandleType window_handle, u32 window_width, u32 window_height); - virtual ~DisplayRenderer(); - - u32 GetWindowWidth() const { return m_window_width; } - u32 GetWindowHeight() const { return m_window_height; } - - u32 GetTopPadding() const { return m_top_padding; } - void SetTopPadding(u32 padding) { m_top_padding = padding; } - - float GetPrimaryDisplayFramesPerSecond(); - - virtual BackendType GetBackendType() = 0; - - virtual std::unique_ptr CreateDisplay(const char* name, Display::Type type, - u8 priority = Display::DEFAULT_PRIORITY) = 0; - - virtual void RemoveDisplay(Display* display); - - virtual void DisplayEnabled(Display* display); - virtual void DisplayDisabled(Display* display); - virtual void DisplayResized(Display* display); - virtual void DisplayFramebufferSwapped(Display* display); - - virtual void WindowResized(u32 window_width, u32 window_height); - - virtual bool BeginFrame() = 0; - virtual void RenderDisplays() = 0; - virtual void EndFrame() = 0; - - /// Returns the default backend type for the system. - static BackendType GetDefaultBackendType(); - - static std::unique_ptr Create(BackendType backend, WindowHandleType window_handle, u32 window_width, - u32 window_height); - -protected: - virtual bool Initialize(); - - void AddDisplay(Display* display); - void UpdateActiveDisplays(); - - std::pair GetDisplayRenderSize(const Display* display); - - WindowHandleType m_window_handle; - u32 m_window_width; - u32 m_window_height; - u32 m_top_padding = 0; - - std::vector m_primary_displays; - std::vector m_secondary_displays; - std::vector m_active_displays; - std::mutex m_display_lock; -}; diff --git a/src/common/display_renderer_d3d.cpp b/src/common/display_renderer_d3d.cpp deleted file mode 100644 index 5b25138e2..000000000 --- a/src/common/display_renderer_d3d.cpp +++ /dev/null @@ -1,340 +0,0 @@ -#include "display_renderer_d3d.h" -#include "YBaseLib/Assert.h" -#include "YBaseLib/Memory.h" -#include "YBaseLib/String.h" -#include -#include - -#if defined(Y_COMPILER_MSVC) -#pragma comment(lib, "d3d11.lib") - -static constexpr u32 SWAP_CHAIN_BUFFER_COUNT = 2; -static constexpr DXGI_FORMAT SWAP_CHAIN_BUFFER_FORMAT = DXGI_FORMAT_R8G8B8A8_UNORM; - -static constexpr u32 VS_BYTECODE[] = { - 0x43425844, 0x0608a44a, 0xd0e1754a, 0xec57c233, 0x42017a39, 0x00000001, 0x000002a8, 0x00000005, 0x00000034, - 0x00000080, 0x000000b4, 0x0000010c, 0x0000022c, 0x46454452, 0x00000044, 0x00000000, 0x00000000, 0x00000000, - 0x0000001c, 0xfffe0400, 0x00000100, 0x0000001c, 0x7263694d, 0x666f736f, 0x52282074, 0x4c482029, 0x53204c53, - 0x65646168, 0x6f432072, 0x6c69706d, 0x31207265, 0x00312e30, 0x4e475349, 0x0000002c, 0x00000001, 0x00000008, - 0x00000020, 0x00000000, 0x00000006, 0x00000001, 0x00000000, 0x00000101, 0x565f5653, 0x65747265, 0x00444978, - 0x4e47534f, 0x00000050, 0x00000002, 0x00000008, 0x00000038, 0x00000000, 0x00000000, 0x00000003, 0x00000000, - 0x00000c03, 0x00000041, 0x00000000, 0x00000001, 0x00000003, 0x00000001, 0x0000000f, 0x43584554, 0x44524f4f, - 0x5f565300, 0x69736f50, 0x6e6f6974, 0xababab00, 0x52444853, 0x00000118, 0x00010040, 0x00000046, 0x04000060, - 0x00101012, 0x00000000, 0x00000006, 0x03000065, 0x00102032, 0x00000000, 0x04000067, 0x001020f2, 0x00000001, - 0x00000001, 0x02000068, 0x00000001, 0x07000029, 0x00100012, 0x00000000, 0x0010100a, 0x00000000, 0x00004001, - 0x00000001, 0x07000001, 0x00100012, 0x00000000, 0x0010000a, 0x00000000, 0x00004001, 0x00000002, 0x07000001, - 0x00100042, 0x00000000, 0x0010100a, 0x00000000, 0x00004001, 0x00000002, 0x05000056, 0x00100032, 0x00000000, - 0x00100086, 0x00000000, 0x05000036, 0x00102032, 0x00000000, 0x00100046, 0x00000000, 0x0f000032, 0x00102032, - 0x00000001, 0x00100046, 0x00000000, 0x00004002, 0x40000000, 0xc0000000, 0x00000000, 0x00000000, 0x00004002, - 0xbf800000, 0x3f800000, 0x00000000, 0x00000000, 0x08000036, 0x001020c2, 0x00000001, 0x00004002, 0x00000000, - 0x00000000, 0x00000000, 0x3f800000, 0x0100003e, 0x54415453, 0x00000074, 0x00000008, 0x00000001, 0x00000000, - 0x00000003, 0x00000001, 0x00000001, 0x00000002, 0x00000001, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000002, 0x00000000, - 0x00000001, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000}; - -static constexpr u32 PS_BYTECODE[] = { - 0x43425844, 0x76fb5edf, 0x6680f045, 0x1a81341f, 0xac4335f9, 0x00000001, 0x0000021c, 0x00000005, 0x00000034, - 0x000000cc, 0x00000100, 0x00000134, 0x000001a0, 0x46454452, 0x00000090, 0x00000000, 0x00000000, 0x00000002, - 0x0000001c, 0xffff0400, 0x00000100, 0x00000067, 0x0000005c, 0x00000003, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000001, 0x00000000, 0x00000062, 0x00000002, 0x00000005, 0x00000004, 0xffffffff, 0x00000000, - 0x00000001, 0x0000000c, 0x706d6173, 0x65740030, 0x4d003078, 0x6f726369, 0x74666f73, 0x29522820, 0x534c4820, - 0x6853204c, 0x72656461, 0x6d6f4320, 0x656c6970, 0x30312072, 0xab00312e, 0x4e475349, 0x0000002c, 0x00000001, - 0x00000008, 0x00000020, 0x00000000, 0x00000000, 0x00000003, 0x00000000, 0x00000303, 0x43584554, 0x44524f4f, - 0xababab00, 0x4e47534f, 0x0000002c, 0x00000001, 0x00000008, 0x00000020, 0x00000000, 0x00000000, 0x00000003, - 0x00000000, 0x0000000f, 0x545f5653, 0x65677261, 0xabab0074, 0x52444853, 0x00000064, 0x00000040, 0x00000019, - 0x0300005a, 0x00106000, 0x00000000, 0x04001858, 0x00107000, 0x00000000, 0x00005555, 0x03001062, 0x00101032, - 0x00000000, 0x03000065, 0x001020f2, 0x00000000, 0x09000045, 0x001020f2, 0x00000000, 0x00101046, 0x00000000, - 0x00107e46, 0x00000000, 0x00106000, 0x00000000, 0x0100003e, 0x54415453, 0x00000074, 0x00000002, 0x00000000, - 0x00000000, 0x00000002, 0x00000000, 0x00000000, 0x00000000, 0x00000001, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000001, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000}; - -namespace { -class DisplayGL : public Display -{ -public: - DisplayGL(DisplayRenderer* display_manager, const String& name, Type type, u8 priority); - ~DisplayGL(); - - void Render(); - -private: - void UpdateFramebufferTexture(); - void UpdateSamplerState(); - - Microsoft::WRL::ComPtr m_sampler_state = nullptr; - Microsoft::WRL::ComPtr m_framebuffer_texture = nullptr; - Microsoft::WRL::ComPtr m_framebuffer_texture_srv = nullptr; - - u32 m_framebuffer_texture_width = 0; - u32 m_framebuffer_texture_height = 0; -}; - -DisplayGL::DisplayGL(DisplayRenderer* display_manager, const String& name, Type type, u8 priority) - : Display(display_manager, name, type, priority) -{ - // TODO: Customizable sampler states - UpdateSamplerState(); -} - -DisplayGL::~DisplayGL() = default; - -void DisplayGL::Render() -{ - if (UpdateFrontbuffer()) - UpdateFramebufferTexture(); - - if (!m_framebuffer_texture || !m_sampler_state) - return; - - DisplayRendererD3D* dm = static_cast(m_renderer); - ID3D11DeviceContext* d3d_context = dm->GetD3DContext(); - - d3d_context->RSSetState(dm->GetD3DRasterizerState()); - d3d_context->OMSetDepthStencilState(dm->GetD3DDepthState(), 0); - d3d_context->OMSetBlendState(dm->GetD3DBlendState(), nullptr, 0xFFFFFFFF); - - d3d_context->IASetPrimitiveTopology(D3D11_PRIMITIVE_TOPOLOGY_TRIANGLELIST); - d3d_context->VSSetShader(dm->GetD3DVertexShader(), nullptr, 0); - d3d_context->PSSetShader(dm->GetD3DPixelShader(), nullptr, 0); - d3d_context->PSSetShaderResources(0, 1, m_framebuffer_texture_srv.GetAddressOf()); - d3d_context->PSSetSamplers(0, 1, m_sampler_state.GetAddressOf()); - - d3d_context->Draw(3, 0); -} - -void DisplayGL::UpdateFramebufferTexture() -{ - ID3D11Device* d3d_device = static_cast(m_renderer)->GetD3DDevice(); - ID3D11DeviceContext* d3d_context = static_cast(m_renderer)->GetD3DContext(); - - if (m_framebuffer_texture_width != m_front_buffer.width || m_framebuffer_texture_height != m_front_buffer.height) - { - m_framebuffer_texture_width = m_front_buffer.width; - m_framebuffer_texture_height = m_front_buffer.height; - m_framebuffer_texture.Reset(); - m_framebuffer_texture_srv.Reset(); - - if (m_framebuffer_texture_width > 0 && m_framebuffer_texture_height > 0) - { - D3D11_TEXTURE2D_DESC desc = - CD3D11_TEXTURE2D_DESC(DXGI_FORMAT_R8G8B8A8_UNORM, m_framebuffer_texture_width, m_framebuffer_texture_height, 1, - 1, D3D11_BIND_SHADER_RESOURCE, D3D11_USAGE_DYNAMIC, D3D11_CPU_ACCESS_WRITE); - HRESULT hr = d3d_device->CreateTexture2D(&desc, nullptr, m_framebuffer_texture.ReleaseAndGetAddressOf()); - if (FAILED(hr)) - { - Panic("Failed to create framebuffer texture."); - return; - } - - D3D11_SHADER_RESOURCE_VIEW_DESC srv_desc = {}; - srv_desc.Format = DXGI_FORMAT_R8G8B8A8_UNORM; - srv_desc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE2D; - srv_desc.Texture2D.MostDetailedMip = 0; - srv_desc.Texture2D.MipLevels = 1; - hr = d3d_device->CreateShaderResourceView(m_framebuffer_texture.Get(), &srv_desc, - m_framebuffer_texture_srv.ReleaseAndGetAddressOf()); - if (FAILED(hr)) - { - Panic("Failed to create framebuffer texture SRV."); - m_framebuffer_texture.Reset(); - return; - } - } - } - - if (!m_framebuffer_texture) - return; - - D3D11_MAPPED_SUBRESOURCE sr; - HRESULT hr = d3d_context->Map(m_framebuffer_texture.Get(), 0, D3D11_MAP_WRITE_DISCARD, 0, &sr); - if (FAILED(hr)) - { - Panic("Failed to map framebuffer texture."); - return; - } - - CopyFramebufferToRGBA8Buffer(&m_front_buffer, sr.pData, sr.RowPitch); - - d3d_context->Unmap(m_framebuffer_texture.Get(), 0); -} - -void DisplayGL::UpdateSamplerState() -{ - ID3D11Device* d3d_device = static_cast(m_renderer)->GetD3DDevice(); - - m_sampler_state.Reset(); - - D3D11_SAMPLER_DESC ss_desc = CD3D11_SAMPLER_DESC(CD3D11_DEFAULT()); - ss_desc.Filter = D3D11_FILTER_MIN_MAG_MIP_LINEAR; - // ss_desc.Filter = D3D11_FILTER_MIN_MAG_MIP_POINT; - HRESULT hr = d3d_device->CreateSamplerState(&ss_desc, m_sampler_state.GetAddressOf()); - if (FAILED(hr)) - { - Panic("Failed to create sampler state"); - return; - } -} -} // namespace - -DisplayRendererD3D::DisplayRendererD3D(WindowHandleType window_handle, u32 window_width, u32 window_height) - : DisplayRenderer(window_handle, window_width, window_height) -{ -} - -DisplayRendererD3D::~DisplayRendererD3D() = default; - -std::unique_ptr DisplayRendererD3D::CreateDisplay(const char* name, Display::Type type, - u8 priority /*= Display::DEFAULT_PRIORITY*/) -{ - std::unique_ptr display = std::make_unique(this, name, type, priority); - AddDisplay(display.get()); - return display; -} - -bool DisplayRendererD3D::Initialize() -{ - if (!DisplayRenderer::Initialize()) - return false; - - DXGI_SWAP_CHAIN_DESC desc = {}; - desc.BufferDesc.Format = SWAP_CHAIN_BUFFER_FORMAT; - desc.BufferUsage = DXGI_USAGE_BACK_BUFFER | DXGI_USAGE_RENDER_TARGET_OUTPUT; - desc.BufferCount = SWAP_CHAIN_BUFFER_COUNT; - desc.SwapEffect = DXGI_SWAP_EFFECT_DISCARD; - desc.SampleDesc.Count = 1; - desc.SampleDesc.Quality = 0; - desc.Windowed = TRUE; - desc.OutputWindow = static_cast(m_window_handle); - - D3D_FEATURE_LEVEL feature_level; - HRESULT hr = D3D11CreateDeviceAndSwapChain(nullptr, D3D_DRIVER_TYPE_HARDWARE, NULL, 0, nullptr, 0, D3D11_SDK_VERSION, - &desc, m_swap_chain.GetAddressOf(), m_device.GetAddressOf(), - &feature_level, m_context.GetAddressOf()); - if (FAILED(hr) || feature_level < D3D_FEATURE_LEVEL_10_0) - return false; - - // Disable DXGI responding to ALT+ENTER, we need to capture these keystrokes and handle it ourselves. - Microsoft::WRL::ComPtr dxgi_factory; - hr = m_swap_chain->GetParent(IID_PPV_ARGS(dxgi_factory.GetAddressOf())); - if (FAILED(hr)) - return false; - - hr = dxgi_factory->MakeWindowAssociation(desc.OutputWindow, DXGI_MWA_NO_WINDOW_CHANGES | DXGI_MWA_NO_ALT_ENTER | - DXGI_MWA_NO_PRINT_SCREEN); - if (FAILED(hr)) - return false; - - if (!CreateRenderTargetView()) - return false; - - hr = m_device->CreateVertexShader(VS_BYTECODE, sizeof(VS_BYTECODE), nullptr, m_vertex_shader.GetAddressOf()); - if (FAILED(hr)) - return false; - - hr = m_device->CreatePixelShader(PS_BYTECODE, sizeof(PS_BYTECODE), nullptr, m_pixel_shader.GetAddressOf()); - if (FAILED(hr)) - return false; - - D3D11_RASTERIZER_DESC rs_desc = CD3D11_RASTERIZER_DESC(CD3D11_DEFAULT()); - hr = m_device->CreateRasterizerState(&rs_desc, m_rasterizer_state.GetAddressOf()); - if (FAILED(hr)) - return false; - - D3D11_DEPTH_STENCIL_DESC ds_desc = CD3D11_DEPTH_STENCIL_DESC(CD3D11_DEFAULT()); - ds_desc.DepthEnable = FALSE; - ds_desc.DepthWriteMask = D3D11_DEPTH_WRITE_MASK_ZERO; - hr = m_device->CreateDepthStencilState(&ds_desc, m_depth_state.GetAddressOf()); - if (FAILED(hr)) - return false; - - D3D11_BLEND_DESC bs_desc = CD3D11_BLEND_DESC(CD3D11_DEFAULT()); - hr = m_device->CreateBlendState(&bs_desc, m_blend_state.GetAddressOf()); - if (FAILED(hr)) - return false; - - return true; -} - -bool DisplayRendererD3D::BeginFrame() -{ - std::array clear_color = {0.0f, 0.0f, 0.0f, 1.0f}; - m_context->ClearRenderTargetView(m_swap_chain_rtv.Get(), clear_color.data()); - m_context->OMSetRenderTargets(1, m_swap_chain_rtv.GetAddressOf(), nullptr); - return true; -} - -void DisplayRendererD3D::RenderDisplays() -{ - std::lock_guard guard(m_display_lock); - - // How many pixels do we need to render? - u32 total_width = 0; - for (const Display* display : m_active_displays) - { - auto dim = GetDisplayRenderSize(display); - total_width += dim.first; - } - - // Compute the viewport bounds. - const int window_width = int(m_window_width); - const int window_height = std::max(1, int(m_window_height) - int(m_top_padding)); - - int viewport_x = (m_window_width - total_width) / 2; - for (Display* display : m_active_displays) - { - auto dim = GetDisplayRenderSize(display); - const int viewport_width = int(dim.first); - const int viewport_height = int(dim.second); - const int viewport_y = ((window_height - viewport_height) / 2) + m_top_padding; - - D3D11_VIEWPORT vp = { float(viewport_x), float(viewport_y), float(viewport_width), float(viewport_height), 0.0f, 1.0f }; - m_context->RSSetViewports(1, &vp); - - static_cast(display)->Render(); - - viewport_x += dim.first; - } -} - -void DisplayRendererD3D::EndFrame() -{ - m_swap_chain->Present(1, 0); -} - -void DisplayRendererD3D::WindowResized(u32 window_width, u32 window_height) -{ - DisplayRenderer::WindowResized(window_width, window_height); - - m_context->OMSetRenderTargets(0, nullptr, nullptr); - m_swap_chain_rtv.Reset(); - - HRESULT hr = - m_swap_chain->ResizeBuffers(SWAP_CHAIN_BUFFER_COUNT, m_window_width, m_window_height, SWAP_CHAIN_BUFFER_FORMAT, 0); - if (FAILED(hr) || !CreateRenderTargetView()) - Panic("Failed to resize swap chain buffers."); -} - -bool DisplayRendererD3D::CreateRenderTargetView() -{ - D3D11_RENDER_TARGET_VIEW_DESC desc = {}; - desc.ViewDimension = D3D11_RTV_DIMENSION_TEXTURE2D; - desc.Format = SWAP_CHAIN_BUFFER_FORMAT; - desc.Texture2D.MipSlice = 0; - - ID3D11Texture2D* surface; - HRESULT hr = m_swap_chain->GetBuffer(0, IID_PPV_ARGS(&surface)); - if (FAILED(hr)) - return false; - - hr = m_device->CreateRenderTargetView(surface, &desc, m_swap_chain_rtv.GetAddressOf()); - surface->Release(); - return SUCCEEDED(hr); -} - -DisplayRenderer::BackendType DisplayRendererD3D::GetBackendType() -{ - return DisplayRenderer::BackendType::Direct3D; -} - -#endif diff --git a/src/common/display_renderer_d3d.h b/src/common/display_renderer_d3d.h deleted file mode 100644 index 721744a21..000000000 --- a/src/common/display_renderer_d3d.h +++ /dev/null @@ -1,55 +0,0 @@ -#pragma once -#include "YBaseLib/Common.h" - -#if defined(Y_COMPILER_MSVC) - -#include "YBaseLib/Windows/WindowsHeaders.h" -#include "display_renderer.h" -#include -#include -#include -#include - -class DisplayRendererD3D final : public DisplayRenderer -{ -public: - DisplayRendererD3D(WindowHandleType window_handle, u32 window_width, u32 window_height); - ~DisplayRendererD3D(); - - BackendType GetBackendType() override; - - std::unique_ptr CreateDisplay(const char* name, Display::Type type, - u8 priority = Display::DEFAULT_PRIORITY) override; - - void WindowResized(u32 window_width, u32 window_height) override; - - bool BeginFrame() override; - void RenderDisplays() override; - void EndFrame() override; - - ID3D11Device* GetD3DDevice() const { return m_device.Get(); } - ID3D11DeviceContext* GetD3DContext() const { return m_context.Get(); } - ID3D11VertexShader* GetD3DVertexShader() const { return m_vertex_shader.Get(); } - ID3D11PixelShader* GetD3DPixelShader() const { return m_pixel_shader.Get(); } - ID3D11RasterizerState* GetD3DRasterizerState() const { return m_rasterizer_state.Get(); } - ID3D11DepthStencilState* GetD3DDepthState() const { return m_depth_state.Get(); } - ID3D11BlendState* GetD3DBlendState() const { return m_blend_state.Get(); } - -protected: - bool Initialize() override; - -private: - bool CreateRenderTargetView(); - - Microsoft::WRL::ComPtr m_device = nullptr; - Microsoft::WRL::ComPtr m_context = nullptr; - Microsoft::WRL::ComPtr m_swap_chain = nullptr; - Microsoft::WRL::ComPtr m_swap_chain_rtv = nullptr; - Microsoft::WRL::ComPtr m_vertex_shader = nullptr; - Microsoft::WRL::ComPtr m_pixel_shader = nullptr; - Microsoft::WRL::ComPtr m_rasterizer_state = nullptr; - Microsoft::WRL::ComPtr m_depth_state = nullptr; - Microsoft::WRL::ComPtr m_blend_state = nullptr; -}; - -#endif diff --git a/src/common/display_renderer_gl.cpp b/src/common/display_renderer_gl.cpp deleted file mode 100644 index 3b91b4d66..000000000 --- a/src/common/display_renderer_gl.cpp +++ /dev/null @@ -1,367 +0,0 @@ -#include "display_renderer_gl.h" -#include "YBaseLib/Assert.h" -#include "YBaseLib/Memory.h" -#include "YBaseLib/String.h" -#include -#include -#include -#include - -namespace { -class DisplayGL : public Display -{ -public: - DisplayGL(DisplayRenderer* display_manager, const String& name, Type type, u8 priority); - ~DisplayGL(); - - void Render(); - -private: - void UpdateFramebufferTexture(); - - GLuint m_framebuffer_texture_id = 0; - - u32 m_framebuffer_texture_width = 0; - u32 m_framebuffer_texture_height = 0; - - std::vector m_framebuffer_texture_upload_buffer; -}; - -DisplayGL::DisplayGL(DisplayRenderer* display_manager, const String& name, Type type, u8 priority) - : Display(display_manager, name, type, priority) -{ - // TODO: Customizable sampler states -} - -DisplayGL::~DisplayGL() -{ - if (m_framebuffer_texture_id != 0) - glDeleteTextures(1, &m_framebuffer_texture_id); -} - -void DisplayGL::Render() -{ - if (UpdateFrontbuffer()) - UpdateFramebufferTexture(); - - if (m_framebuffer_texture_id == 0) - return; - - // Assumes that everything is already setup/bound. - glBindTexture(GL_TEXTURE_2D, m_framebuffer_texture_id); - glDrawArrays(GL_TRIANGLE_STRIP, 0, 4); -} - -void DisplayGL::UpdateFramebufferTexture() -{ - if (m_framebuffer_texture_width != m_front_buffer.width || m_framebuffer_texture_height != m_front_buffer.height) - { - m_framebuffer_texture_width = m_front_buffer.width; - m_framebuffer_texture_height = m_front_buffer.height; - - if (m_framebuffer_texture_width > 0 && m_framebuffer_texture_height > 0) - { - if (m_framebuffer_texture_id == 0) - glGenTextures(1, &m_framebuffer_texture_id); - - glBindTexture(GL_TEXTURE_2D, m_framebuffer_texture_id); - glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, m_framebuffer_texture_width, m_framebuffer_texture_height, 0, GL_RGBA, - GL_UNSIGNED_BYTE, nullptr); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, 0); - // glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); - // glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); - } - else - { - if (m_framebuffer_texture_id != 0) - { - glDeleteTextures(1, &m_framebuffer_texture_id); - m_framebuffer_texture_id = 0; - } - } - } - - if (m_framebuffer_texture_id == 0) - return; - - const u32 upload_stride = m_framebuffer_texture_width * sizeof(u32); - const size_t required_bytes = size_t(upload_stride) * m_framebuffer_texture_height; - if (m_framebuffer_texture_upload_buffer.size() != required_bytes) - m_framebuffer_texture_upload_buffer.resize(required_bytes); - - CopyFramebufferToRGBA8Buffer(&m_front_buffer, m_framebuffer_texture_upload_buffer.data(), upload_stride); - - glBindTexture(GL_TEXTURE_2D, m_framebuffer_texture_id); - glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, m_framebuffer_texture_width, m_framebuffer_texture_height, GL_RGBA, - GL_UNSIGNED_BYTE, m_framebuffer_texture_upload_buffer.data()); -} - -} // namespace - -DisplayRendererGL::DisplayRendererGL(WindowHandleType window_handle, u32 window_width, u32 window_height) - : DisplayRenderer(window_handle, window_width, window_height) -{ -} - -DisplayRendererGL::~DisplayRendererGL() = default; - -std::unique_ptr DisplayRendererGL::CreateDisplay(const char* name, Display::Type type, - u8 priority /*= Display::DEFAULT_PRIORITY*/) -{ - std::unique_ptr display = std::make_unique(this, name, type, priority); - AddDisplay(display.get()); - return display; -} - -bool DisplayRendererGL::Initialize() -{ - if (!DisplayRenderer::Initialize()) - return false; - - if (!GLAD_GL_VERSION_2_0) - { - Panic("GL version 2.0 not loaded."); - return false; - } - - if (!CreateQuadVAO()) - { - Panic("Failed to create quad VAO"); - return false; - } - - if (!CreateQuadProgram()) - { - Panic("Failed to create quad program"); - return false; - } - - return true; -} - -bool DisplayRendererGL::BeginFrame() -{ - glClearColor(0.0f, 0.0f, 0.0f, 1.0f); - glClear(GL_COLOR_BUFFER_BIT); - return true; -} - -void DisplayRendererGL::RenderDisplays() -{ - std::lock_guard guard(m_display_lock); - - // Setup GL state. - glDisable(GL_SCISSOR_TEST); - glDisable(GL_DEPTH_TEST); - glDisable(GL_BLEND); - glUseProgram(m_quad_program_id); - BindQuadVAO(); - - // How many pixels do we need to render? - u32 total_width = 0; - for (const Display* display : m_active_displays) - { - auto dim = GetDisplayRenderSize(display); - total_width += dim.first; - } - - // Compute the viewport bounds. - const int window_width = int(m_window_width); - const int window_height = std::max(1, int(m_window_height) - int(m_top_padding)); - - int viewport_x = (window_width - total_width) / 2; - for (Display* display : m_active_displays) - { - auto dim = GetDisplayRenderSize(display); - const int viewport_width = int(dim.first); - const int viewport_height = int(dim.second); - const int viewport_y = ((window_height - viewport_height) / 2) + m_top_padding; - glViewport(viewport_x, m_window_height - viewport_height - viewport_y, viewport_width, viewport_height); - static_cast(display)->Render(); - viewport_x += dim.first; - } -} - -void DisplayRendererGL::EndFrame() {} - -void DisplayRendererGL::WindowResized(u32 window_width, u32 window_height) -{ - DisplayRenderer::WindowResized(window_width, window_height); -} - -DisplayRenderer::BackendType DisplayRendererGL::GetBackendType() -{ - return DisplayRenderer::BackendType::OpenGL; -} - -struct QuadVertex -{ - float position[4]; - float texcoord[2]; -}; - -bool DisplayRendererGL::CreateQuadVAO() -{ - static const QuadVertex vertices[4] = {{{1.0f, 1.0f, 0.0f, 1.0f}, {1.0f, 0.0f}}, - {{-1.0f, 1.0f, 0.0f, 1.0f}, {0.0f, 0.0f}}, - {{1.0f, -1.0f, 0.0f, 1.0f}, {1.0f, 1.0f}}, - {{-1.0f, -1.0f, 0.0f, 1.0f}, {0.0f, 1.0f}}}; - - if (GLAD_GL_VERSION_3_0 || GLAD_GL_ES_VERSION_3_0) - { - glGenVertexArrays(1, &m_quad_vao_id); - glBindVertexArray(m_quad_vao_id); - glGenBuffers(1, &m_quad_vbo_id); - glBindBuffer(GL_ARRAY_BUFFER, m_quad_vbo_id); - glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW); - glVertexAttribPointer(0, 4, GL_FLOAT, GL_FALSE, sizeof(QuadVertex), - reinterpret_cast(offsetof(QuadVertex, position[0]))); - glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, sizeof(QuadVertex), - reinterpret_cast(offsetof(QuadVertex, texcoord[0]))); - glEnableVertexAttribArray(0); - glEnableVertexAttribArray(1); - glBindVertexArray(0); - } - else - { - glGenBuffers(1, &m_quad_vbo_id); - glBindBuffer(GL_ARRAY_BUFFER, m_quad_vbo_id); - glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW); - glBindBuffer(GL_ARRAY_BUFFER, 0); - } - - return true; -} - -void DisplayRendererGL::BindQuadVAO() -{ - if (GLAD_GL_VERSION_3_0 || GLAD_GL_ES_VERSION_3_0) - { - glBindVertexArray(m_quad_vao_id); - return; - } - - // old-style - glBindBuffer(GL_ARRAY_BUFFER, m_quad_vbo_id); - glVertexAttribPointer(0, 4, GL_FLOAT, GL_FALSE, sizeof(QuadVertex), - reinterpret_cast(offsetof(QuadVertex, position[0]))); - glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, sizeof(QuadVertex), - reinterpret_cast(offsetof(QuadVertex, texcoord[0]))); - glEnableVertexAttribArray(0); - glEnableVertexAttribArray(1); -} - -static std::string GenerateQuadVertexShader(const bool old_glsl) -{ - std::stringstream ss; - if (old_glsl) - { - ss << "#version 110\n"; - ss << "attribute vec4 a_position;\n"; - ss << "attribute vec2 a_texcoord;\n"; - ss << "varying vec2 v_texcoord;\n"; - } - else - { - ss << "#version 130\n"; - ss << "in vec4 a_position;\n"; - ss << "in vec2 a_texcoord;\n"; - ss << "out vec2 v_texcoord;\n"; - } - - ss << "void main() {\n"; - ss << " gl_Position = a_position;\n"; - ss << " v_texcoord = a_texcoord;\n"; - ss << "}\n"; - - return ss.str(); -} - -static std::string GenerateQuadFragmentShader(const bool old_glsl) -{ - std::stringstream ss; - if (old_glsl) - { - ss << "#version 110\n"; - ss << "varying vec2 v_texcoord;\n"; - ss << "uniform sampler2D samp0;\n"; - } - else - { - ss << "#version 130\n"; - ss << "in vec2 v_texcoord;\n"; - ss << "uniform sampler2D samp0;\n"; - ss << "out vec4 ocol0;\n"; - } - - ss << "void main() {\n"; - if (old_glsl) - ss << " gl_FragColor = texture2D(samp0, v_texcoord);\n"; - else - ss << " ocol0 = texture(samp0, v_texcoord);\n"; - ss << "}\n"; - - return ss.str(); -} - -bool DisplayRendererGL::CreateQuadProgram() -{ - const bool old_glsl = !GLAD_GL_VERSION_3_2 && !GLAD_GL_ES_VERSION_3_0; - const std::string vs_str = GenerateQuadVertexShader(old_glsl); - const std::string fs_str = GenerateQuadFragmentShader(old_glsl); - const char* vs_str_ptr = vs_str.c_str(); - const GLint vs_length = static_cast(vs_str.length()); - const char* fs_str_ptr = fs_str.c_str(); - const GLint fs_length = static_cast(fs_str.length()); - GLint param; - - GLuint vs = glCreateShader(GL_VERTEX_SHADER); - glShaderSource(vs, 1, &vs_str_ptr, &vs_length); - glCompileShader(vs); - glGetShaderiv(vs, GL_COMPILE_STATUS, ¶m); - if (param != GL_TRUE) - { - Panic("Failed to compile vertex shader."); - return false; - } - - GLuint fs = glCreateShader(GL_FRAGMENT_SHADER); - glShaderSource(fs, 1, &fs_str_ptr, &fs_length); - glCompileShader(fs); - glGetShaderiv(fs, GL_COMPILE_STATUS, ¶m); - if (param != GL_TRUE) - { - Panic("Failed to compile fragment shader."); - return false; - } - - m_quad_program_id = glCreateProgram(); - glAttachShader(m_quad_program_id, vs); - glAttachShader(m_quad_program_id, fs); - glBindAttribLocation(m_quad_program_id, 0, "a_position"); - glBindAttribLocation(m_quad_program_id, 1, "a_texcoord"); - if (!old_glsl) - glBindFragDataLocation(m_quad_program_id, 0, "ocol0"); - glLinkProgram(m_quad_program_id); - glGetProgramiv(m_quad_program_id, GL_LINK_STATUS, ¶m); - if (param != GL_TRUE) - { - Panic("Failed to link program."); - return false; - } - - // Bind texture unit zero to the shader. - glUseProgram(m_quad_program_id); - GLint pos = glGetUniformLocation(m_quad_program_id, "samp0"); - if (pos >= 0) - glUniform1i(pos, 0); - - // Shaders are no longer needed after linking. - glDeleteShader(vs); - glDeleteShader(fs); - - glUseProgram(0); - return true; -} diff --git a/src/common/display_renderer_gl.h b/src/common/display_renderer_gl.h deleted file mode 100644 index acbcbb3d5..000000000 --- a/src/common/display_renderer_gl.h +++ /dev/null @@ -1,35 +0,0 @@ -#pragma once -#include "display_renderer.h" -#include -#include - -class DisplayRendererGL final : public DisplayRenderer -{ -public: - DisplayRendererGL(WindowHandleType window_handle, u32 window_width, u32 window_height); - ~DisplayRendererGL(); - - BackendType GetBackendType() override; - - std::unique_ptr CreateDisplay(const char* name, Display::Type type, - u8 priority = Display::DEFAULT_PRIORITY) override; - - void WindowResized(u32 window_width, u32 window_height) override; - - bool BeginFrame() override; - void RenderDisplays() override; - void EndFrame() override; - -protected: - bool Initialize() override; - -private: - bool CreateQuadVAO(); - void BindQuadVAO(); - - bool CreateQuadProgram(); - - u32 m_quad_vbo_id = 0; - u32 m_quad_vao_id = 0; - u32 m_quad_program_id = 0; -}; diff --git a/src/common/display_timing.cpp b/src/common/display_timing.cpp deleted file mode 100644 index d5cd7c39a..000000000 --- a/src/common/display_timing.cpp +++ /dev/null @@ -1,374 +0,0 @@ -#include "display_timing.h" -#include "YBaseLib/String.h" -#include "common/state_wrapper.h" - -DisplayTiming::DisplayTiming() = default; - -void DisplayTiming::ResetClock(SimulationTime start_time) -{ - m_clock_start_time = start_time; -} - -SimulationTime DisplayTiming::GetTime(SimulationTime time) const -{ - return GetSimulationTimeDifference(m_clock_start_time, time); -} - -s32 DisplayTiming::GetTimeInFrame(SimulationTime time) const -{ - return static_cast(GetTime(time) % m_vertical_total_duration); -} - -void DisplayTiming::SetPixelClock(double clock) -{ - m_pixel_clock = clock; - UpdateHorizontalFrequency(); - UpdateVerticalFrequency(); -} - -void DisplayTiming::SetHorizontalVisible(s32 visible) -{ - m_horizontal_visible = visible; - UpdateHorizontalFrequency(); -} - -void DisplayTiming::SetHorizontalSyncRange(s32 start, s32 end) -{ - Assert(start <= end); - m_horizontal_front_porch = start - m_horizontal_visible; - m_horizontal_sync_length = end - start + 1; - UpdateHorizontalFrequency(); -} - -void DisplayTiming::SetHorizontalSyncLength(s32 start, s32 length) -{ - m_horizontal_front_porch = start - m_horizontal_visible; - m_horizontal_sync_length = length; - UpdateHorizontalFrequency(); -} - -void DisplayTiming::SetHorizontalBackPorch(s32 bp) -{ - m_horizontal_back_porch = bp; - UpdateHorizontalFrequency(); -} - -void DisplayTiming::SetHorizontalTotal(s32 total) -{ - m_horizontal_back_porch = total - (m_horizontal_visible + m_horizontal_front_porch + m_horizontal_sync_length); - UpdateHorizontalFrequency(); -} - -void DisplayTiming::SetVerticalVisible(s32 visible) -{ - m_vertical_visible = visible; - UpdateVerticalFrequency(); -} - -void DisplayTiming::SetVerticalSyncRange(s32 start, s32 end) -{ - Assert(start <= end); - m_vertical_front_porch = start - m_vertical_visible; - m_vertical_sync_length = end - start + 1; - UpdateVerticalFrequency(); -} - -void DisplayTiming::SetVerticalSyncLength(s32 start, s32 length) -{ - m_vertical_front_porch = start - m_vertical_visible; - m_vertical_sync_length = length; - UpdateVerticalFrequency(); -} - -void DisplayTiming::SetVerticalBackPorch(s32 bp) -{ - m_vertical_back_porch = bp; - UpdateVerticalFrequency(); -} - -void DisplayTiming::SetVerticalTotal(s32 total) -{ - m_vertical_back_porch = total - (m_vertical_visible + m_vertical_front_porch + m_vertical_sync_length); - UpdateVerticalFrequency(); -} - -DisplayTiming::Snapshot DisplayTiming::GetSnapshot(SimulationTime time) const -{ - Snapshot ss; - if (m_clock_enable && IsValid()) - { - const s32 time_in_frame = GetTimeInFrame(time); - const s32 line_number = time_in_frame / m_horizontal_total_duration; - const s32 time_in_line = time_in_frame % m_horizontal_total_duration; - ss.current_line = static_cast(line_number); - ss.current_pixel = static_cast(time_in_line / m_horizontal_pixel_duration); - ss.in_vertical_blank = (time_in_frame >= m_vertical_active_duration); - ss.in_horizontal_blank = (!ss.in_vertical_blank && (time_in_line >= m_horizontal_sync_start_time && - time_in_line < m_horizontal_sync_end_time)); - ss.vsync_active = (time_in_frame >= m_vertical_sync_start_time && line_number < m_vertical_sync_end_time); - ss.hsync_active = - (!ss.vsync_active && (time_in_line >= m_horizontal_sync_start_time && time_in_line < m_horizontal_sync_end_time)); - ss.display_active = !(ss.in_horizontal_blank | ss.in_vertical_blank); - } - else - { - ss.current_line = 0; - ss.current_pixel = 0; - ss.display_active = false; - ss.in_horizontal_blank = false; - ss.in_vertical_blank = false; - ss.hsync_active = false; - ss.vsync_active = false; - } - return ss; -} - -bool DisplayTiming::IsDisplayActive(SimulationTime time) const -{ - if (!m_clock_enable || !IsValid()) - return false; - - const s32 time_in_frame = GetTimeInFrame(time); - return (time_in_frame < m_vertical_active_duration && - (time_in_frame % m_horizontal_total_duration) < m_horizontal_active_duration); -} - -bool DisplayTiming::InVerticalBlank(SimulationTime time) const -{ - if (!m_clock_enable || !IsValid()) - return false; - - const s32 time_in_frame = GetTimeInFrame(time); - return (time_in_frame >= m_vertical_active_duration); -} - -bool DisplayTiming::InHorizontalSync(SimulationTime time) const -{ - if (!m_clock_enable || !IsValid()) - return false; - - const s32 time_in_frame = GetTimeInFrame(time); - if (time_in_frame >= m_vertical_sync_start_time && time_in_frame < m_vertical_sync_end_time) - { - // In vsync. - return false; - } - - const s32 time_in_line = time_in_frame % m_horizontal_total_duration; - return (time_in_line >= m_horizontal_sync_start_time && time_in_frame < m_horizontal_sync_end_time); -} - -bool DisplayTiming::InVerticalSync(SimulationTime time) const -{ - const s32 time_in_frame = GetTimeInFrame(time); - return (time_in_frame >= m_vertical_sync_start_time && time_in_frame < m_vertical_sync_end_time); -} - -u32 DisplayTiming::GetCurrentLine(SimulationTime time) const -{ - if (!m_clock_enable || !IsValid()) - return 0; - - const s32 time_in_frame = GetTimeInFrame(time); - return static_cast(time_in_frame / m_horizontal_total_duration); -} - -SimulationTime DisplayTiming::GetTimeUntilVSync(SimulationTime time) const -{ - if (!m_clock_enable || !IsValid()) - return 0; - - const s32 time_in_frame = GetTimeInFrame(time); - if (time_in_frame < m_vertical_sync_start_time) - return m_vertical_sync_start_time - time_in_frame; - else - return (m_vertical_total_duration - time_in_frame) + m_vertical_sync_start_time; -} - -SimulationTime DisplayTiming::GetTimeUntilVBlank(SimulationTime time) const -{ - if (!m_clock_enable || !IsValid()) - return 0; - - const s32 time_in_frame = GetTimeInFrame(time); - if (time_in_frame >= m_vertical_active_duration) - return ((m_vertical_total_duration - time_in_frame) + m_vertical_active_duration); - else - return (m_vertical_active_duration - time_in_frame); -} - -void DisplayTiming::ToString(String* str) const -{ - const s32 horizontal_sync_start = m_horizontal_visible + m_horizontal_front_porch; - const s32 vertical_sync_start = m_vertical_visible + m_vertical_front_porch; - str->Format("%dx%d | %.3f KHz, %u Total, %d-%d Sync | %.3fhz, %d Total, %d-%d Sync", m_horizontal_visible, - m_vertical_visible, m_horizontal_frequency / 1000.0, m_horizontal_total, horizontal_sync_start, - horizontal_sync_start + m_horizontal_sync_length, m_vertical_frequency, m_vertical_total, - vertical_sync_start, vertical_sync_start + m_vertical_sync_length); -} - -bool DisplayTiming::FrequenciesMatch(const DisplayTiming& timing) const -{ - return std::tie(m_pixel_clock, m_horizontal_visible, m_horizontal_front_porch, m_horizontal_sync_length, - m_horizontal_back_porch, m_horizontal_frequency, m_vertical_visible, m_vertical_front_porch, - m_vertical_sync_length, m_vertical_back_porch, m_vertical_frequency) == - std::tie(timing.m_pixel_clock, timing.m_horizontal_visible, timing.m_horizontal_front_porch, - timing.m_horizontal_sync_length, timing.m_horizontal_back_porch, timing.m_horizontal_frequency, - timing.m_vertical_visible, timing.m_vertical_front_porch, timing.m_vertical_sync_length, - timing.m_vertical_back_porch, timing.m_vertical_frequency); -} - -bool DisplayTiming::DoState(StateWrapper& sw) -{ - sw.Do(&m_clock_start_time); - sw.Do(&m_horizontal_visible); - sw.Do(&m_horizontal_front_porch); - sw.Do(&m_horizontal_sync_length); - sw.Do(&m_horizontal_back_porch); - sw.Do(&m_vertical_visible); - sw.Do(&m_vertical_front_porch); - sw.Do(&m_vertical_sync_length); - sw.Do(&m_vertical_back_porch); - sw.Do(&m_horizontal_total); - sw.Do(&m_vertical_total); - sw.Do(&m_pixel_clock); - sw.Do(&m_horizontal_frequency); - sw.Do(&m_vertical_frequency); - sw.Do(&m_horizontal_pixel_duration); - sw.Do(&m_horizontal_active_duration); - sw.Do(&m_horizontal_sync_start_time); - sw.Do(&m_horizontal_sync_end_time); - sw.Do(&m_horizontal_total_duration); - sw.Do(&m_vertical_active_duration); - sw.Do(&m_vertical_sync_start_time); - sw.Do(&m_vertical_sync_end_time); - sw.Do(&m_vertical_total_duration); - sw.Do(&m_clock_enable); - sw.Do(&m_valid); - return !sw.HasError(); -} - -void DisplayTiming::Reset() -{ - m_clock_start_time = 0; - - m_horizontal_visible = 0; - m_horizontal_front_porch = 0; - m_horizontal_sync_length = 0; - m_horizontal_back_porch = 0; - m_vertical_visible = 0; - m_vertical_front_porch = 0; - m_vertical_sync_length = 0; - m_vertical_back_porch = 0; - - m_horizontal_total = 0; - m_vertical_total = 0; - - m_pixel_clock = 0.0; - m_horizontal_frequency = 0.0f; - m_vertical_frequency = 0.0f; - - m_horizontal_pixel_duration = 0; - m_horizontal_active_duration = 0; - m_horizontal_sync_start_time = 0; - m_horizontal_sync_end_time = 0; - m_horizontal_total_duration = 0; - m_vertical_active_duration = 0; - m_vertical_sync_start_time = 0; - m_vertical_sync_end_time = 0; - m_vertical_total_duration = 0; - - m_clock_enable = false; - m_valid = false; -} - -DisplayTiming& DisplayTiming::operator=(const DisplayTiming& timing) -{ - m_clock_start_time = timing.m_clock_start_time; - m_horizontal_visible = timing.m_horizontal_visible; - m_horizontal_front_porch = timing.m_horizontal_front_porch; - m_horizontal_sync_length = timing.m_horizontal_sync_length; - m_horizontal_back_porch = timing.m_horizontal_back_porch; - m_vertical_visible = timing.m_vertical_visible; - m_vertical_front_porch = timing.m_vertical_front_porch; - m_vertical_sync_length = timing.m_vertical_sync_length; - m_vertical_back_porch = timing.m_vertical_back_porch; - m_horizontal_total = timing.m_horizontal_total; - m_vertical_total = timing.m_vertical_total; - m_pixel_clock = timing.m_pixel_clock; - m_horizontal_frequency = timing.m_horizontal_frequency; - m_vertical_frequency = timing.m_vertical_frequency; - m_horizontal_pixel_duration = timing.m_horizontal_pixel_duration; - m_horizontal_active_duration = timing.m_horizontal_active_duration; - m_horizontal_sync_start_time = timing.m_horizontal_sync_start_time; - m_horizontal_sync_end_time = timing.m_horizontal_sync_end_time; - m_horizontal_total_duration = timing.m_horizontal_total_duration; - m_vertical_active_duration = timing.m_vertical_active_duration; - m_vertical_sync_start_time = timing.m_vertical_sync_start_time; - m_vertical_sync_end_time = timing.m_vertical_sync_end_time; - m_vertical_total_duration = timing.m_vertical_total_duration; - m_clock_enable = timing.m_clock_enable; - m_valid = timing.m_valid; - return *this; -} - -void DisplayTiming::UpdateHorizontalFrequency() -{ - if (m_pixel_clock == 0.0 || m_horizontal_visible <= 0 || m_horizontal_front_porch < 0 || - m_horizontal_sync_length < 0 || m_horizontal_back_porch < 0) - { - m_horizontal_total = 0; - m_horizontal_frequency = 0.0; - m_horizontal_active_duration = 0; - m_horizontal_sync_start_time = 0; - m_horizontal_sync_end_time = 0; - m_horizontal_total_duration = 0; - UpdateVerticalFrequency(); - return; - } - - m_horizontal_total = - m_horizontal_visible + m_horizontal_front_porch + m_horizontal_sync_length + m_horizontal_back_porch; - - const double pixel_period = 1.0 / m_pixel_clock; - const double active_duration_s = pixel_period * static_cast(m_horizontal_visible); - const double sync_start_time_s = pixel_period * static_cast(m_horizontal_visible + m_horizontal_front_porch); - const double sync_end_time_s = sync_start_time_s + (pixel_period * static_cast(m_horizontal_sync_length)); - const double total_duration_s = pixel_period * static_cast(m_horizontal_total); - - m_horizontal_frequency = m_pixel_clock / static_cast(m_horizontal_total); - m_horizontal_pixel_duration = static_cast(1000000000.0 * pixel_period); - m_horizontal_active_duration = static_cast(1000000000.0 * active_duration_s); - m_horizontal_sync_start_time = static_cast(1000000000.0 * sync_start_time_s); - m_horizontal_sync_end_time = static_cast(1000000000.0 * sync_end_time_s); - m_horizontal_total_duration = static_cast(1000000000.0 * total_duration_s); - UpdateVerticalFrequency(); -} - -void DisplayTiming::UpdateVerticalFrequency() -{ - if (m_vertical_visible <= 0 || m_vertical_front_porch < 0 || m_vertical_sync_length < 0 || m_vertical_back_porch < 0) - { - m_vertical_total = 0; - m_vertical_frequency = 0; - m_vertical_active_duration = 0; - m_vertical_sync_start_time = 0; - m_vertical_sync_end_time = 0; - m_vertical_total_duration = 0; - UpdateValid(); - return; - } - - m_vertical_total = m_vertical_visible + m_vertical_front_porch + m_vertical_sync_length + m_vertical_back_porch; - m_vertical_frequency = m_horizontal_frequency / static_cast(m_vertical_total); - m_vertical_active_duration = m_horizontal_total_duration * m_vertical_visible; - m_vertical_sync_start_time = m_horizontal_total_duration * (m_vertical_visible + m_vertical_front_porch); - m_vertical_sync_end_time = m_vertical_sync_start_time + (m_horizontal_total_duration * m_vertical_sync_length); - m_vertical_total_duration = m_horizontal_total_duration * m_vertical_total; - UpdateValid(); -} - -void DisplayTiming::UpdateValid() -{ - m_valid = (m_horizontal_total_duration > 0 && m_vertical_total_duration > 0); -} diff --git a/src/common/display_timing.h b/src/common/display_timing.h deleted file mode 100644 index 410d7ef85..000000000 --- a/src/common/display_timing.h +++ /dev/null @@ -1,144 +0,0 @@ -#pragma once -#include "types.h" - -class StateWrapper; -class String; - -class DisplayTiming -{ -public: - DisplayTiming(); - - // H/V frequencies are valid? - bool IsValid() const { return m_valid; } - - // Enables the clock at the specified start time. - bool IsClockEnabled() const { return m_clock_enable; } - void SetClockEnable(bool enable) { m_clock_enable = enable; } - void ResetClock(SimulationTime start_time); - - // Returns the number of ticks since the clock was enabled. - SimulationTime GetTime(SimulationTime time) const; - - // Returns the number of ticks elapsed in the current frame. - s32 GetTimeInFrame(SimulationTime time) const; - - // Accessors. - s32 GetHorizontalVisible() const { return m_horizontal_visible; } - s32 GetHorizontalFrontPorch() const { return m_horizontal_front_porch; } - s32 GetHorizontalSyncLength() const { return m_horizontal_sync_length; } - s32 GetHorizontalBackPorch() const { return m_horizontal_back_porch; } - s32 GetHorizontalTotal() const { return m_horizontal_total; } - s32 GetVerticalVisible() const { return m_vertical_visible; } - s32 GetVerticalFrontPorch() const { return m_vertical_front_porch; } - s32 GetVerticalSyncLength() const { return m_vertical_sync_length; } - s32 GetVerticallBackPorch() const { return m_vertical_back_porch; } - s32 GetVerticalTotal() const { return m_vertical_total; } - double GetPixelClock() const { return m_pixel_clock; } - double GetHorizontalFrequency() const { return m_horizontal_frequency; } - double GetVerticalFrequency() const { return m_vertical_frequency; } - s32 GetHorizontalPixelDuration() const { return m_horizontal_pixel_duration; } - s32 GetHorizontalActiveDuration() const { return m_horizontal_active_duration; } - s32 GetHorizontalSyncStartTime() const { return m_horizontal_sync_start_time; } - s32 GetHorizontalSyncEndTime() const { return m_horizontal_sync_end_time; } - s32 GetHorizontalTotalDuration() const { return m_horizontal_total_duration; } - s32 GetHorizontalBlankStartTime() const { return m_horizontal_active_duration; } - s32 GetHorizontalBlankDuration() const { return m_horizontal_total_duration - m_horizontal_active_duration; } - s32 GetVerticalActiveDuration() const { return m_vertical_active_duration; } - s32 GetVerticalSyncStartTime() const { return m_vertical_sync_start_time; } - s32 GetVerticalSyncEndTime() const { return m_vertical_sync_end_time; } - s32 GetVerticalTotalDuration() const { return m_vertical_total_duration; } - s32 GetVerticalBlankStartTime() const { return m_vertical_active_duration; } - s32 GetVerticalBlankDuration() const { return m_vertical_total_duration - m_vertical_active_duration; } - - // Setting horizontal timing based on pixels and clock. - void SetPixelClock(double clock); - void SetHorizontalVisible(s32 visible); - void SetHorizontalSyncRange(s32 start, s32 end); - void SetHorizontalSyncLength(s32 start, s32 length); - void SetHorizontalBackPorch(s32 bp); - void SetHorizontalTotal(s32 total); - void SetVerticalVisible(s32 visible); - void SetVerticalSyncRange(s32 start, s32 end); - void SetVerticalSyncLength(s32 start, s32 length); - void SetVerticalBackPorch(s32 bp); - void SetVerticalTotal(s32 total); - - // Gets the timing state for the specified time point. - struct Snapshot - { - u32 current_line; - u32 current_pixel; - bool display_active; // visible part - bool in_horizontal_blank; - bool in_vertical_blank; - bool hsync_active; - bool vsync_active; - }; - Snapshot GetSnapshot(SimulationTime time) const; - - // Shorter versions of the above. - bool IsDisplayActive(SimulationTime time) const; - bool InVerticalBlank(SimulationTime time) const; - bool InHorizontalSync(SimulationTime time) const; - bool InVerticalSync(SimulationTime time) const; - u32 GetCurrentLine(SimulationTime time) const; - SimulationTime GetTimeUntilVSync(SimulationTime time) const; - - // Returns the amount of time until the next vertical blank starts. - SimulationTime GetTimeUntilVBlank(SimulationTime time) const; - - // Writes frequency information to the log. - void ToString(String* str) const; - - // Tests whether frequencies and dimensions match. - bool FrequenciesMatch(const DisplayTiming& timing) const; - - // Serialization. - bool DoState(StateWrapper& sw); - void Reset(); - - // Copy operator. - DisplayTiming& operator=(const DisplayTiming& timing); - - // TODO: clock update to prevent wrap-around. - -private: - void UpdateHorizontalFrequency(); - void UpdateVerticalFrequency(); - void UpdateValid(); - - SimulationTime m_clock_start_time = 0; - - // Set - s32 m_horizontal_visible = 0; - s32 m_horizontal_front_porch = 0; - s32 m_horizontal_sync_length = 0; - s32 m_horizontal_back_porch = 0; - s32 m_vertical_visible = 0; - s32 m_vertical_front_porch = 0; - s32 m_vertical_sync_length = 0; - s32 m_vertical_back_porch = 0; - - // Computed. End values are exclusive. - s32 m_horizontal_total = 0; - s32 m_vertical_total = 0; - - double m_pixel_clock = 0.0; - double m_horizontal_frequency = 0.0f; - double m_vertical_frequency = 0.0f; - - // TODO: Make these doubles? - s32 m_horizontal_pixel_duration = 0; - s32 m_horizontal_active_duration = 0; - s32 m_horizontal_sync_start_time = 0; - s32 m_horizontal_sync_end_time = 0; - s32 m_horizontal_total_duration = 0; - s32 m_vertical_active_duration = 0; - s32 m_vertical_sync_start_time = 0; - s32 m_vertical_sync_end_time = 0; - s32 m_vertical_total_duration = 0; - - bool m_clock_enable = false; - bool m_valid = false; -}; diff --git a/src/common/fastjmp.asm b/src/common/fastjmp.asm deleted file mode 100644 index f643b56ee..000000000 --- a/src/common/fastjmp.asm +++ /dev/null @@ -1,63 +0,0 @@ -_TEXT SEGMENT - -PUBLIC fastjmp_set -PUBLIC fastjmp_jmp - -; void fastjmp_set(fastjmp_buf*) -fastjmp_set PROC - mov rax, qword ptr [rsp] - mov rdx, rsp ; fixup stack pointer, so it doesn't include the call to fastjmp_set - add rdx, 8 - mov qword ptr [rcx], rax ; actually rip - mov qword ptr [rcx + 8], rbx - mov qword ptr [rcx + 16], rdx ; actually rsp - mov qword ptr [rcx + 24], rbp - mov qword ptr [rcx + 32], rsi - mov qword ptr [rcx + 40], rdi - mov qword ptr [rcx + 48], r12 - mov qword ptr [rcx + 56], r13 - mov qword ptr [rcx + 64], r14 - mov qword ptr [rcx + 72], r15 - movaps xmmword ptr [rcx + 80], xmm6 - movaps xmmword ptr [rcx + 96], xmm7 - movaps xmmword ptr [rcx + 112], xmm8 - add rcx, 112 ; split to two batches to fit displacement in a single byte - movaps xmmword ptr [rcx + 16], xmm9 - movaps xmmword ptr [rcx + 32], xmm10 - movaps xmmword ptr [rcx + 48], xmm11 - movaps xmmword ptr [rcx + 64], xmm12 - movaps xmmword ptr [rcx + 80], xmm13 - movaps xmmword ptr [rcx + 96], xmm14 - movaps xmmword ptr [rcx + 112], xmm15 - ret -fastjmp_set ENDP - -; void fastjmp_jmp(fastjmp_buf*) -fastjmp_jmp PROC - mov rax, qword ptr [rcx + 0] ; actually rip - mov rbx, qword ptr [rcx + 8] - mov rsp, qword ptr [rcx + 16] - mov rbp, qword ptr [rcx + 24] - mov rsi, qword ptr [rcx + 32] - mov rdi, qword ptr [rcx + 40] - mov r12, qword ptr [rcx + 48] - mov r13, qword ptr [rcx + 56] - mov r14, qword ptr [rcx + 64] - mov r15, qword ptr [rcx + 72] - movaps xmm6, xmmword ptr [rcx + 80] - movaps xmm7, xmmword ptr [rcx + 96] - movaps xmm8, xmmword ptr [rcx + 112] - add rcx, 112 ; split to two batches to fit displacement in a single byte - movaps xmm9, xmmword ptr [rcx + 16] - movaps xmm10, xmmword ptr [rcx + 32] - movaps xmm11, xmmword ptr [rcx + 48] - movaps xmm12, xmmword ptr [rcx + 64] - movaps xmm13, xmmword ptr [rcx + 80] - movaps xmm14, xmmword ptr [rcx + 96] - movaps xmm15, xmmword ptr [rcx + 112] - jmp rax -fastjmp_jmp ENDP - -_TEXT ENDS - -END \ No newline at end of file diff --git a/src/common/fastjmp.h b/src/common/fastjmp.h deleted file mode 100644 index 59be2126a..000000000 --- a/src/common/fastjmp.h +++ /dev/null @@ -1,44 +0,0 @@ -#pragma once - -#ifdef _MSC_VER - -__declspec(align(16)) struct fastjmp_buf -{ - unsigned __int64 Rip; - unsigned __int64 Rbx; - unsigned __int64 Rsp; - unsigned __int64 Rbp; - unsigned __int64 Rsi; - unsigned __int64 Rdi; - unsigned __int64 R12; - unsigned __int64 R13; - unsigned __int64 R14; - unsigned __int64 R15; - unsigned __int64 Xmm6[2]; - unsigned __int64 Xmm7[2]; - unsigned __int64 Xmm8[2]; - unsigned __int64 Xmm9[2]; - unsigned __int64 Xmm10[2]; - unsigned __int64 Xmm11[2]; - unsigned __int64 Xmm12[2]; - unsigned __int64 Xmm13[2]; - unsigned __int64 Xmm14[2]; - unsigned __int64 Xmm15[2]; - // unsigned long MxCsr; - // unsigned short FpCsr; - // unsigned short Spare; -}; - -extern "C" { -void fastjmp_set(fastjmp_buf*); -void fastjmp_jmp(fastjmp_buf*); -} - -#else - -#include -#define fastjmp_buf jmp_buf -#define fastjmp_set(buf) setjmp(*(buf)) -#define fastjmp_jmp(buf) longjmp(*(buf), 0) - -#endif diff --git a/src/common/hdd_image.cpp b/src/common/hdd_image.cpp deleted file mode 100644 index 1d20b4e5b..000000000 --- a/src/common/hdd_image.cpp +++ /dev/null @@ -1,566 +0,0 @@ -#include "hdd_image.h" -#include "YBaseLib/FileSystem.h" -#include "YBaseLib/Log.h" -Log_SetChannel(HDDImage); - -#pragma pack(push, 1) -static constexpr u32 LOG_FILE_MAGIC = 0x89374897; -struct LOG_FILE_HEADER -{ - u32 magic; - u32 sector_size; - u64 image_size; - u32 sector_count; - u32 version_number; - u8 padding[12]; -}; -static constexpr u32 STATE_MAGIC = 0x92087348; -struct STATE_HEADER -{ - u32 magic; - u32 sector_size; - u64 image_size; - u32 sector_count; - u32 version_number; - u32 num_sectors_in_state; - u8 padding[8]; -}; -#pragma pack(pop) - -static String GetLogFileName(const char* base_filename) -{ - return String::FromFormat("%s.log", base_filename); -} - -static u64 GetSectorMapOffset(HDDImage::SectorIndex index) -{ - return sizeof(LOG_FILE_HEADER) + (static_cast(index) * sizeof(HDDImage::SectorIndex)); -} - -HDDImage::HDDImage(const std::string filename, ByteStream* base_stream, ByteStream* log_stream, u64 size, - u32 sector_size, u32 sector_count, u32 version_number, LogSectorMap log_sector_map) - : m_filename(std::move(filename)), m_base_stream(base_stream), m_log_stream(log_stream), m_image_size(size), - m_sector_size(sector_size), m_sector_count(sector_count), m_version_number(version_number), - m_log_sector_map(std::move(log_sector_map)) -{ - m_current_sector.data = std::make_unique(sector_size); -} - -HDDImage::~HDDImage() -{ - m_base_stream->Release(); - m_log_stream->Release(); -} - -ByteStream* HDDImage::CreateLogFile(const char* filename, bool truncate_existing, bool atomic_update, u64 image_size, - u32 sector_size, u32& num_sectors, u32 version_number, LogSectorMap& sector_map) -{ - if (sector_size == 0 || !Common::IsPow2(sector_size) || - ((image_size + (sector_size - 1)) / sector_size) >= std::numeric_limits::max()) - { - return nullptr; - } - - // Fill sector map with zeros. - num_sectors = static_cast((image_size + (sector_size - 1)) / sector_size); - sector_map.resize(static_cast(num_sectors)); - std::fill_n(sector_map.begin(), static_cast(num_sectors), InvalidSectorNumber); - - u32 open_flags = BYTESTREAM_OPEN_READ | BYTESTREAM_OPEN_WRITE | BYTESTREAM_OPEN_CREATE | BYTESTREAM_OPEN_SEEKABLE; - if (truncate_existing) - open_flags |= BYTESTREAM_OPEN_TRUNCATE; - if (atomic_update) - open_flags |= BYTESTREAM_OPEN_ATOMIC_UPDATE; - - ByteStream* log_stream = FileSystem::OpenFile(filename, open_flags); - if (!log_stream) - return nullptr; - - LOG_FILE_HEADER header = {}; - header.magic = LOG_FILE_MAGIC; - header.sector_size = sector_size; - header.image_size = image_size; - header.sector_count = static_cast(num_sectors); - header.version_number = version_number; - - // Write header and sector map to the file. - if (!log_stream->Write2(&header, sizeof(header)) || - !log_stream->Write2(sector_map.data(), static_cast(sizeof(SectorIndex) * sector_map.size()))) - { - log_stream->Release(); - FileSystem::DeleteFile(filename); - return nullptr; - } - - // Align the first sector to 4K, so we better utilize the OS's page cache. - u64 pos = log_stream->GetPosition(); - if (!Common::IsAlignedPow2(pos, sector_size)) - { - u64 padding_end = Common::AlignUpPow2(pos, sector_size); - while (pos < padding_end) - { - u64 data = 0; - u64 size = std::min(padding_end - pos, u64(sizeof(data))); - if (!log_stream->Write2(&data, static_cast(size))) - { - log_stream->Release(); - FileSystem::DeleteFile(filename); - return nullptr; - } - - pos += size; - } - } - - if (!log_stream->Flush()) - { - log_stream->Release(); - FileSystem::DeleteFile(filename); - return nullptr; - } - - return log_stream; -} - -ByteStream* HDDImage::OpenLogFile(const char* filename, u64 image_size, u32& sector_size, u32& num_sectors, - u32& version_number, LogSectorMap& sector_map) -{ - ByteStream* log_stream = - FileSystem::OpenFile(filename, BYTESTREAM_OPEN_READ | BYTESTREAM_OPEN_WRITE | BYTESTREAM_OPEN_SEEKABLE); - if (!log_stream) - return nullptr; - - // Read in the image header. - LOG_FILE_HEADER header; - if (!log_stream->Read2(&header, sizeof(header)) || header.magic != LOG_FILE_MAGIC || - header.image_size != image_size || header.sector_size == 0 || !Common::IsPow2(header.sector_size)) - { - Log_ErrorPrintf("Log file '%s': Invalid header", filename); - log_stream->Release(); - return nullptr; - } - - num_sectors = static_cast(image_size / header.sector_size); - if (num_sectors == 0 || header.sector_count != static_cast(num_sectors)) - { - Log_ErrorPrintf("Log file '%s': Corrupted header", filename); - log_stream->Release(); - return nullptr; - } - - // Read in the sector map. - sector_size = header.sector_size; - version_number = header.version_number; - sector_map.resize(num_sectors); - if (!log_stream->Read2(sector_map.data(), static_cast(sizeof(SectorIndex) * num_sectors))) - { - Log_ErrorPrintf("Failed to read sector map from '%s'", filename); - log_stream->Release(); - return nullptr; - } - - return log_stream; -} - -HDDImage::SectorBuffer& HDDImage::GetSector(SectorIndex sector_index) -{ - if (m_current_sector.sector_number == sector_index) - return m_current_sector; - - // Unload current sector and replace it. - ReleaseSector(m_current_sector); - LoadSector(m_current_sector, sector_index); - return m_current_sector; -} - -void HDDImage::LoadSector(SectorBuffer& buf, SectorIndex sector_index) -{ - Assert(sector_index != InvalidSectorNumber && sector_index < m_log_sector_map.size()); - if (m_log_sector_map[sector_index] == InvalidSectorNumber) - LoadSectorFromImage(buf, sector_index); - else - LoadSectorFromLog(buf, sector_index); -} - -std::unique_ptr HDDImage::Create(const char* filename, u64 size_in_bytes, - u32 sector_size /*= DefaultReplaySectorSize*/) -{ - String log_filename = GetLogFileName(filename); - if (FileSystem::FileExists(filename) || FileSystem::FileExists(log_filename)) - return nullptr; - - ByteStream* base_stream = FileSystem::OpenFile(filename, BYTESTREAM_OPEN_READ | BYTESTREAM_OPEN_WRITE | - BYTESTREAM_OPEN_CREATE | BYTESTREAM_OPEN_SEEKABLE); - if (!base_stream) - return nullptr; - - // Write zeros to the image file. - u64 image_size = 0; - while (image_size < size_in_bytes) - { - u64 data = 0; - const u32 to_write = static_cast(std::min(size_in_bytes - image_size, u64(sizeof(data)))); - if (!base_stream->Write2(&data, to_write)) - { - base_stream->Release(); - FileSystem::DeleteFile(filename); - return nullptr; - } - - image_size += to_write; - } - - // Create the log. - u32 sector_count; - LogSectorMap sector_map; - ByteStream* log_stream = - CreateLogFile(log_filename, false, false, image_size, sector_size, sector_count, 0, sector_map); - if (!log_stream) - { - base_stream->Release(); - return nullptr; - } - - return std::unique_ptr( - new HDDImage(filename, base_stream, log_stream, image_size, sector_size, sector_count, 0, std::move(sector_map))); -} - -std::unique_ptr HDDImage::Open(const char* filename, u32 sector_size /* = DefaultReplaySectorSize */) -{ - ByteStream* base_stream = - FileSystem::OpenFile(filename, BYTESTREAM_OPEN_READ | BYTESTREAM_OPEN_WRITE | BYTESTREAM_OPEN_SEEKABLE); - if (!base_stream) - return nullptr; - - u64 image_size = base_stream->GetSize(); - if (image_size == 0) - { - base_stream->Release(); - return nullptr; - } - - String log_filename = GetLogFileName(filename); - u32 sector_count; - u32 version_number = 0; - LogSectorMap sector_map; - ByteStream* log_stream; - if (FileSystem::FileExists(log_filename)) - { - log_stream = OpenLogFile(log_filename, image_size, sector_size, sector_count, version_number, sector_map); - if (!log_stream) - { - Log_ErrorPrintf("Failed to read log file for image '%s'.", filename); - base_stream->Release(); - return nullptr; - } - } - else - { - Log_InfoPrintf("Log file not found for image '%s', creating.", filename); - log_stream = - CreateLogFile(log_filename, false, false, image_size, sector_size, sector_count, version_number, sector_map); - if (!log_stream) - { - Log_ErrorPrintf("Failed to create log file for image '%s'.", filename); - base_stream->Release(); - return nullptr; - } - } - - Log_DevPrintf("Opened image '%s' with log file '%s' (sector size %u)", filename, log_filename.GetCharArray(), - sector_size); - return std::unique_ptr(new HDDImage(filename, base_stream, log_stream, image_size, sector_size, - sector_count, version_number, std::move(sector_map))); -} - -void HDDImage::LoadSectorFromImage(SectorBuffer& buf, SectorIndex sector_index) -{ - if (!m_base_stream->SeekAbsolute(GetFileOffset(sector_index)) || !m_base_stream->Read2(buf.data.get(), m_sector_size)) - Panic("Failed to read from base image."); - - buf.sector_number = sector_index; - buf.dirty = false; - buf.in_log = false; -} - -void HDDImage::LoadSectorFromLog(SectorBuffer& buf, SectorIndex sector_index) -{ - DebugAssert(sector_index < m_sector_count); - - const SectorIndex log_sector_index = m_log_sector_map[sector_index]; - Assert(log_sector_index != InvalidSectorNumber); - if (!m_log_stream->SeekAbsolute(GetFileOffset(log_sector_index)) || - !m_log_stream->Read2(buf.data.get(), m_sector_size)) - { - Panic("Failed to read from log file."); - } - - buf.sector_number = sector_index; - buf.dirty = false; - buf.in_log = true; -} - -void HDDImage::WriteSectorToLog(SectorBuffer& buf) -{ - DebugAssert(buf.dirty && buf.sector_number < m_sector_count); - - // Is the sector currently in the log? - if (!buf.in_log) - { - Assert(m_log_sector_map[buf.sector_number] == InvalidSectorNumber); - - // Need to allocate it in the log file. - if (!m_log_stream->SeekToEnd()) - Panic("Failed to seek to end of log."); - - const u64 sector_offset = m_log_stream->GetPosition(); - const SectorIndex log_sector_number = static_cast(sector_offset / m_sector_size); - Log_DevPrintf("Allocating log sector %u to sector %u", buf.sector_number, log_sector_number); - m_log_sector_map[buf.sector_number] = log_sector_number; - - // Update log sector map in file. - if (!m_log_stream->SeekAbsolute(GetSectorMapOffset(buf.sector_number)) || - !m_log_stream->Write2(&log_sector_number, sizeof(SectorIndex))) - { - Panic("Failed to update sector map in log file."); - } - - buf.in_log = true; - } - - // Write to the log. - const SectorIndex log_sector_index = m_log_sector_map[buf.sector_number]; - Assert(log_sector_index != InvalidSectorNumber); - if (!m_log_stream->SeekAbsolute(GetFileOffset(log_sector_index)) || - !m_log_stream->Write2(buf.data.get(), m_sector_size)) - { - Panic("Failed to write sector to log file."); - } - - buf.dirty = false; -} - -void HDDImage::ReleaseSector(SectorBuffer& buf) -{ - // Write it to the log file if it's changed. - if (m_current_sector.dirty) - WriteSectorToLog(m_current_sector); - - m_current_sector.sector_number = InvalidSectorNumber; -} - -void HDDImage::ReleaseAllSectors() -{ - if (m_current_sector.sector_number == InvalidSectorNumber) - return; - - ReleaseSector(m_current_sector); -} - -void HDDImage::Read(void* buffer, u64 offset, u32 size) -{ - Assert((offset + size) <= m_image_size); - - byte* buf = reinterpret_cast(buffer); - while (size > 0) - { - // Find the sector that this offset lives in. - const SectorIndex sector_index = static_cast(offset / m_sector_size); - const u32 offset_in_sector = static_cast(offset % m_sector_size); - const u32 size_to_read = std::min(size, m_sector_size - offset_in_sector); - - // Load the sector, and read the sub-sector. - const SectorBuffer& sec = GetSector(sector_index); - std::memcpy(buf, &sec.data[offset_in_sector], size_to_read); - buf += size_to_read; - offset += size_to_read; - size -= size_to_read; - } -} - -void HDDImage::Write(const void* buffer, u64 offset, u32 size) -{ - Assert((offset + size) <= m_image_size); - - const byte* buf = reinterpret_cast(buffer); - while (size > 0) - { - // Find the sector that this offset lives in. - const SectorIndex sector_index = static_cast(offset / m_sector_size); - const u32 offset_in_sector = static_cast(offset % m_sector_size); - const u32 size_to_write = std::min(size, m_sector_size - offset_in_sector); - - // Load the sector, and update it. - SectorBuffer& sec = GetSector(sector_index); - std::memcpy(&sec.data[offset_in_sector], buf, size_to_write); - sec.dirty = true; - buf += size_to_write; - offset += size_to_write; - size -= size_to_write; - } -} - -bool HDDImage::LoadState(ByteStream* stream) -{ - ReleaseAllSectors(); - - // Read header in from stream. It may not be valid. - STATE_HEADER header; - if (!stream->Read2(&header, sizeof(header)) || header.magic != STATE_MAGIC || header.image_size != m_image_size || - header.sector_size != m_sector_size || header.sector_count != m_sector_count) - { - Log_ErrorPrintf("Corrupted save state."); - return false; - } - - // The version number could have changed, which means we committed since this state was saved. - if (header.version_number != m_version_number) - { - Log_ErrorPrintf("Incorrect version number in save state (%u, should be %u), it is a stale state", - header.version_number, m_version_number); - return false; - } - - // Okay, everything seems fine. We can now throw away the current log file, and re-write it. - LogSectorMap new_sector_map; - ByteStream* new_log_stream = CreateLogFile(GetLogFileName(m_filename.c_str()), true, true, m_image_size, - m_sector_size, m_sector_count, m_version_number, new_sector_map); - if (!new_log_stream) - return false; - - // Write sectors from log. - for (u32 i = 0; i < header.num_sectors_in_state; i++) - { - const SectorIndex log_sector_index = static_cast(new_log_stream->GetPosition() / m_sector_size); - SectorIndex sector_index; - if (!stream->Read2(§or_index, sizeof(sector_index)) || sector_index >= m_sector_count || - !ByteStream_CopyBytes(stream, m_sector_size, new_log_stream)) - { - Log_ErrorPrintf("Failed to copy new sector from save state."); - new_log_stream->Discard(); - new_log_stream->Release(); - return false; - } - - // Update new sector map. - new_sector_map[sector_index] = log_sector_index; - } - - // Write the new sector map. - if (!new_log_stream->SeekAbsolute(GetSectorMapOffset(0)) || - !new_log_stream->Write2(new_sector_map.data(), sizeof(SectorIndex) * m_sector_count)) - { - Log_ErrorPrintf("Failed to write new sector map from save state."); - new_log_stream->Discard(); - new_log_stream->Release(); - return false; - } - - // Commit the stream, replacing the existing file. Then swap the pointers, since we may as well use the existing one. - m_log_stream->Release(); - new_log_stream->Flush(); - new_log_stream->Commit(); - m_log_stream = new_log_stream; - m_log_sector_map = std::move(new_sector_map); - return true; -} - -bool HDDImage::SaveState(ByteStream* stream) -{ - ReleaseAllSectors(); - - // Precompute how many sectors are committed to the log. - u32 log_sector_count = 0; - for (SectorIndex sector_index = 0; sector_index < m_sector_count; sector_index++) - { - if (IsSectorInLog(sector_index)) - log_sector_count++; - } - - // Construct header. - STATE_HEADER header = {}; - header.magic = STATE_MAGIC; - header.sector_size = m_sector_size; - header.image_size = m_image_size; - header.sector_count = m_sector_count; - header.version_number = m_version_number; - header.num_sectors_in_state = log_sector_count; - if (!stream->Write2(&header, sizeof(header))) - { - Log_ErrorPrintf("Failed to write log header to save state."); - return false; - } - - // Copy each sector from the replay log. - for (SectorIndex sector_index = 0; sector_index < m_sector_count; sector_index++) - { - if (!IsSectorInLog(sector_index)) - continue; - - if (!m_log_stream->SeekAbsolute(GetFileOffset(m_log_sector_map[sector_index])) || - !stream->Write2(§or_index, sizeof(sector_index)) || - !ByteStream_CopyBytes(m_log_stream, m_sector_size, stream)) - { - Log_ErrorPrintf("Failed to write log sector to save state."); - return false; - } - } - - return true; -} - -void HDDImage::Flush() -{ - if (!m_current_sector.dirty) - return; - - WriteSectorToLog(m_current_sector); - - // Ensure the stream isn't buffering. - if (!m_log_stream->Flush()) - Panic("Failed to flush log stream."); -} - -void HDDImage::CommitLog() -{ - Log_InfoPrintf("Committing log for '%s'.", m_filename.c_str()); - ReleaseAllSectors(); - - for (SectorIndex sector_index = 0; sector_index < m_sector_count; sector_index++) - { - if (!IsSectorInLog(sector_index)) - continue; - - // Read log sector to buffer, then write it to the base image. - // No need to update the log map, since we trash it anyway. - if (!m_log_stream->SeekAbsolute(GetFileOffset(m_log_sector_map[sector_index])) || - !m_base_stream->SeekAbsolute(GetFileOffset(sector_index)) || - ByteStream_CopyBytes(m_log_stream, m_sector_size, m_base_stream) != m_sector_size) - { - Panic("Failed to transfer sector from log to base image."); - } - } - - // Increment the version number, to invalidate old save states. - m_version_number++; - - // Truncate the log, and re-create it. - m_log_stream->Release(); - m_log_stream = CreateLogFile(GetLogFileName(m_filename.c_str()), true, false, m_image_size, m_sector_size, - m_sector_count, m_version_number, m_log_sector_map); -} - -void HDDImage::RevertLog() -{ - Log_InfoPrintf("Reverting log for '%s'", m_filename.c_str()); - ReleaseAllSectors(); - - m_log_stream->Release(); - m_log_stream = CreateLogFile(GetLogFileName(m_filename.c_str()), true, false, m_image_size, m_sector_size, - m_sector_count, m_version_number, m_log_sector_map); - if (!m_log_stream) - { - Log_ErrorPrintf("Failed to recreate log file for image '%s'", m_filename.c_str()); - Panic("Failed to recreate log file."); - } -} diff --git a/src/common/hdd_image.h b/src/common/hdd_image.h deleted file mode 100644 index 6f5f84cb3..000000000 --- a/src/common/hdd_image.h +++ /dev/null @@ -1,93 +0,0 @@ -#pragma once -#include "YBaseLib/ByteStream.h" -#include "types.h" -#include -#include -#include - -class HDDImage -{ -public: - using SectorIndex = u32; - - static constexpr u32 InvalidSectorNumber = UINT32_C(0xFFFFFFFF); - static constexpr u32 DefaultSectorSize = 4096; - - static std::unique_ptr Create(const char* filename, u64 size_in_bytes, u32 sector_size = DefaultSectorSize); - static std::unique_ptr Open(const char* filename, u32 sector_size = DefaultSectorSize); - - ~HDDImage(); - - const u64 GetImageSize() const { return m_image_size; } - const u32 GetSectorSize() const { return m_sector_size; } - const u32 GetSectorCount() const { return m_sector_count; } - - void Read(void* buffer, u64 offset, u32 size); - void Write(const void* buffer, u64 offset, u32 size); - - /// Erases the current replay log, and replaces it with the log from the specified stream. - bool LoadState(ByteStream* stream); - - /// Copies the current state of the replay log to the specified stream, so it can be restored later. - bool SaveState(ByteStream* stream); - - /// Flushes any buffered sectors to the backing file/log. - void Flush(); - - /// Commits all changes made in the replay log to the base image. - void CommitLog(); - - /// Erases any changes made in the replay log, restoring the image to its base state. - void RevertLog(); - -private: - using LogSectorMap = std::vector; - struct SectorBuffer - { - std::unique_ptr data; - SectorIndex sector_number = InvalidSectorNumber; - bool in_log = false; - bool dirty = false; - }; - - HDDImage(const std::string filename, ByteStream* base_stream, ByteStream* log_stream, u64 size, u32 sector_size, - u32 sector_count, u32 version_number, LogSectorMap log_sector_map); - - static ByteStream* CreateLogFile(const char* filename, bool truncate_existing, bool atomic_update, u64 image_size, - u32 sector_size, u32& num_sectors, u32 version_number, LogSectorMap& sector_map); - static ByteStream* OpenLogFile(const char* filename, u64 image_size, u32& sector_size, u32& num_sectors, - u32& version_number, LogSectorMap& sector_map); - - // Returns the offset in the image (either log or base) for the specified sector. - u64 GetFileOffset(SectorIndex sector_index) const - { - return static_cast(sector_index) * static_cast(m_sector_size); - } - - // Returns whether the specified sector is in the log (true), or in the base image (false). - bool IsSectorInLog(SectorIndex sector_index) const { return (m_log_sector_map[sector_index] != InvalidSectorNumber); } - - // Currently, we only have one sector open. But we could change this in the future. - SectorBuffer& GetSector(SectorIndex sector_index); - - void LoadSector(SectorBuffer& buf, SectorIndex sector_index); - void LoadSectorFromImage(SectorBuffer& buf, SectorIndex sector_index); - void LoadSectorFromLog(SectorBuffer& buf, SectorIndex sector_index); - void WriteSectorToLog(SectorBuffer& buf); - void ReleaseSector(SectorBuffer& buf); - void ReleaseAllSectors(); - - std::string m_filename; - - ByteStream* m_base_stream; - ByteStream* m_log_stream; - - u64 m_image_size; - u32 m_sector_size; - u32 m_sector_count; - u32 m_version_number; - - LogSectorMap m_log_sector_map; - - SectorBuffer m_current_sector; -}; diff --git a/src/common/object.cpp b/src/common/object.cpp deleted file mode 100644 index 93da107b9..000000000 --- a/src/common/object.cpp +++ /dev/null @@ -1,8 +0,0 @@ -#include "common/object.h" - -// Have to define this manually as Object has no parent class. -ObjectTypeInfo Object::s_type_info("Object", nullptr, nullptr, nullptr); - -Object::Object(const ObjectTypeInfo* pObjectTypeInfo /* = &s_typeInfo */) : m_type_info(pObjectTypeInfo) {} - -Object::~Object() = default; diff --git a/src/common/object.h b/src/common/object.h deleted file mode 100644 index 8816b1550..000000000 --- a/src/common/object.h +++ /dev/null @@ -1,84 +0,0 @@ -#pragma once -#include "object_type_info.h" - -class Object -{ - // OBJECT TYPE STUFF -private: - static ObjectTypeInfo s_type_info; - -public: - typedef Object ThisClass; - static const ObjectTypeInfo* StaticTypeInfo() { return &s_type_info; } - static ObjectTypeInfo* StaticMutableTypeInfo() { return &s_type_info; } - static const PROPERTY_DECLARATION* StaticPropertyMap() { return nullptr; } - static ObjectFactory* StaticFactory() { return nullptr; } - // END OBJECT TYPE STUFF - -public: - Object(const ObjectTypeInfo* type_info = &s_type_info); - virtual ~Object(); - - // Retrieves the type information for this object. - const ObjectTypeInfo* GetTypeInfo() const { return m_type_info; } - - // Cast from one object type to another, unchecked. - template - const T* Cast() const - { - DebugAssert(m_type_info->IsDerived(T::StaticTypeInfo())); - return static_cast(this); - } - template - T* Cast() - { - DebugAssert(m_type_info->IsDerived(T::StaticTypeInfo())); - return static_cast(this); - } - - // Cast from one object type to another, checked. - template - const T* SafeCast() const - { - return (m_type_info->IsDerived(T::StaticTypeInfo())) ? static_cast(this) : nullptr; - } - template - T* SafeCast() - { - return (m_type_info->IsDerived(T::StaticTypeInfo())) ? static_cast(this) : nullptr; - } - - // Test if one object type is derived from another. - template - bool IsDerived() const - { - return (m_type_info->IsDerived(T::StaticTypeInfo())); - } - bool IsDerived(const ObjectTypeInfo* type) const { return (m_type_info->IsDerived(type)); } - -protected: - // Type info pointer. Set by subclasses. - const ObjectTypeInfo* m_type_info; -}; - -// -// GenericObjectFactory -// -template -struct GenericObjectFactory final : public ObjectFactory -{ - Object* CreateObject() override { return new T(); } - Object* CreateObject(const String& identifier) override { return new T(); } - void DeleteObject(Object* object) override { delete object; } -}; - -#define DECLARE_OBJECT_GENERIC_FACTORY(Type) \ - \ -private: \ - static GenericObjectFactory s_GenericFactory; \ - \ -public: \ - static ObjectFactory* StaticFactory() { return &s_GenericFactory; } - -#define DEFINE_OBJECT_GENERIC_FACTORY(Type) \ - GenericObjectFactory Type::s_GenericFactory = GenericObjectFactory(); diff --git a/src/common/object_type_info.cpp b/src/common/object_type_info.cpp deleted file mode 100644 index 72703230a..000000000 --- a/src/common/object_type_info.cpp +++ /dev/null @@ -1,129 +0,0 @@ -#include "common/object_type_info.h" - -static ObjectTypeInfo::RegistryType s_registry; - -ObjectTypeInfo::RegistryType& ObjectTypeInfo::GetRegistry() -{ - return s_registry; -} - -ObjectTypeInfo::ObjectTypeInfo(const char* TypeName, const ObjectTypeInfo* pParentTypeInfo, - const PROPERTY_DECLARATION* pPropertyDeclarations, ObjectFactory* pFactory) - : m_type_index(INVALID_OBJECT_TYPE_INDEX), m_inheritance_depth(0), m_type_name(TypeName), - m_parent_type(pParentTypeInfo), m_factory(pFactory), m_source_property_declarations(pPropertyDeclarations), - m_property_declarations(nullptr), m_num_property_declarations(0) -{ -} - -ObjectTypeInfo::~ObjectTypeInfo() -{ - // DebugAssert(m_iTypeIndex == INVALID_TYPE_INDEX); -} - -bool ObjectTypeInfo::CanCreateInstance() const -{ - return (m_factory != nullptr); -} - -Object* ObjectTypeInfo::CreateInstance() const -{ - DebugAssert(m_factory != nullptr); - return m_factory->CreateObject(); -} - -void ObjectTypeInfo::DestroyInstance(Object* obj) const -{ - DebugAssert(m_factory != nullptr); - m_factory->DeleteObject(obj); -} - -bool ObjectTypeInfo::IsDerived(const ObjectTypeInfo* pTypeInfo) const -{ - const ObjectTypeInfo* current_type = this; - do - { - if (current_type == pTypeInfo) - return true; - - current_type = current_type->m_parent_type; - } while (current_type != nullptr); - - return false; -} - -const PROPERTY_DECLARATION* ObjectTypeInfo::GetPropertyDeclarationByName(const char* PropertyName) const -{ - for (u32 i = 0; i < m_num_property_declarations; i++) - { - if (!Y_stricmp(m_property_declarations[i]->Name, PropertyName)) - return m_property_declarations[i]; - } - - return nullptr; -} - -void ObjectTypeInfo::RegisterType() -{ - if (m_type_index != INVALID_OBJECT_TYPE_INDEX) - return; - - // our stuff - const ObjectTypeInfo* pCurrentTypeInfo; - const PROPERTY_DECLARATION* pPropertyDeclaration; - - // get property count - pCurrentTypeInfo = this; - m_num_property_declarations = 0; - m_inheritance_depth = 0; - while (pCurrentTypeInfo != nullptr) - { - if (pCurrentTypeInfo->m_source_property_declarations != nullptr) - { - pPropertyDeclaration = pCurrentTypeInfo->m_source_property_declarations; - while (pPropertyDeclaration->Name != nullptr) - { - m_num_property_declarations++; - pPropertyDeclaration++; - } - } - - pCurrentTypeInfo = pCurrentTypeInfo->GetParentType(); - m_inheritance_depth++; - } - - if (m_num_property_declarations > 0) - { - m_property_declarations = new const PROPERTY_DECLARATION*[m_num_property_declarations]; - pCurrentTypeInfo = this; - u32 i = 0; - while (pCurrentTypeInfo != nullptr) - { - if (pCurrentTypeInfo->m_source_property_declarations != nullptr) - { - pPropertyDeclaration = pCurrentTypeInfo->m_source_property_declarations; - while (pPropertyDeclaration->Name != nullptr) - { - DebugAssert(i < m_num_property_declarations); - m_property_declarations[i++] = pPropertyDeclaration++; - } - } - - pCurrentTypeInfo = pCurrentTypeInfo->GetParentType(); - } - } - - m_type_index = GetRegistry().RegisterTypeInfo(this, m_type_name, m_inheritance_depth); -} - -void ObjectTypeInfo::UnregisterType() -{ - if (m_type_index == INVALID_OBJECT_TYPE_INDEX) - return; - - delete[] m_property_declarations; - m_property_declarations = nullptr; - m_num_property_declarations = 0; - - m_type_index = INVALID_OBJECT_TYPE_INDEX; - GetRegistry().UnregisterTypeInfo(this); -} diff --git a/src/common/object_type_info.h b/src/common/object_type_info.h deleted file mode 100644 index 438c20b24..000000000 --- a/src/common/object_type_info.h +++ /dev/null @@ -1,129 +0,0 @@ -#pragma once -#include "common/property.h" -#include "common/type_registry.h" -#include "common/types.h" - -// Forward declare the factory type. -class Object; -struct ObjectFactory; - -// -// ObjectTypeInfo -// -class ObjectTypeInfo -{ -public: - // Constants. - static constexpr u32 INVALID_OBJECT_TYPE_INDEX = 0xFFFFFFFF; - using RegistryType = TypeRegistry; - - // constructors - ObjectTypeInfo(const char* TypeName, const ObjectTypeInfo* pParentTypeInfo, - const PROPERTY_DECLARATION* pPropertyDeclarations, ObjectFactory* pFactory); - virtual ~ObjectTypeInfo(); - - // accessors - const u32 GetTypeIndex() const { return m_type_index; } - const u32 GetInheritanceDepth() const { return m_inheritance_depth; } - const char* GetTypeName() const { return m_type_name; } - const ObjectTypeInfo* GetParentType() const { return m_parent_type; } - ObjectFactory* GetFactory() const { return m_factory; } - - // can create? - bool CanCreateInstance() const; - Object* CreateInstance() const; - void DestroyInstance(Object* obj) const; - - // type information - // currently only does single inheritance - bool IsDerived(const ObjectTypeInfo* type) const; - - // properties - const PROPERTY_DECLARATION* GetPropertyDeclarationByName(const char* name) const; - const PROPERTY_DECLARATION* GetPropertyDeclarationByIndex(u32 index) const - { - DebugAssert(index < m_num_property_declarations); - return m_property_declarations[index]; - } - u32 GetPropertyCount() const { return m_num_property_declarations; } - - // only called once. - virtual void RegisterType(); - virtual void UnregisterType(); - -protected: - u32 m_type_index; - u32 m_inheritance_depth; - const char* m_type_name; - const ObjectTypeInfo* m_parent_type; - ObjectFactory* m_factory; - - // properties - const PROPERTY_DECLARATION* m_source_property_declarations; - const PROPERTY_DECLARATION** m_property_declarations; - u32 m_num_property_declarations; - - // TYPE REGISTRY -public: - static RegistryType& GetRegistry(); - // END TYPE REGISTRY -}; - -// -// ObjectFactory -// -struct ObjectFactory -{ - virtual Object* CreateObject() = 0; - virtual Object* CreateObject(const String& identifier) = 0; - virtual void DeleteObject(Object* object) = 0; -}; - -// Macros -#define DECLARE_OBJECT_TYPE_INFO(Type, ParentType) \ - \ -private: \ - static ObjectTypeInfo s_type_info; \ - \ -public: \ - typedef Type ThisClass; \ - typedef ParentType BaseClass; \ - static const ObjectTypeInfo* StaticTypeInfo() { return &s_type_info; } \ - static ObjectTypeInfo* StaticMutableTypeInfo() { return &s_type_info; } - -#define DECLARE_OBJECT_PROPERTY_MAP(Type) \ - \ -private: \ - static const PROPERTY_DECLARATION s_propertyDeclarations[]; \ - static const PROPERTY_DECLARATION* StaticPropertyMap() { return s_propertyDeclarations; } - -#define DECLARE_OBJECT_NO_PROPERTIES(Type) \ - \ -private: \ - static const PROPERTY_DECLARATION* StaticPropertyMap() { return nullptr; } - -#define DEFINE_OBJECT_TYPE_INFO(Type) \ - ObjectTypeInfo Type::s_type_info(#Type, Type::BaseClass::StaticTypeInfo(), Type::StaticPropertyMap(), \ - Type::StaticFactory()) - -#define DEFINE_NAMED_OBJECT_TYPE_INFO(Type, Name) \ - ObjectTypeInfo Type::s_type_info(Name, Type::BaseClass::StaticTypeInfo(), Type::StaticPropertyMap(), \ - Type::StaticFactory()) - -#define DECLARE_OBJECT_NO_FACTORY(Type) \ - \ -public: \ - static ObjectFactory* StaticFactory() { return nullptr; } - -#define BEGIN_OBJECT_PROPERTY_MAP(Type) const PROPERTY_DECLARATION Type::s_propertyDeclarations[] = { - -#define END_OBJECT_PROPERTY_MAP() \ - PROPERTY_TABLE_MEMBER(NULL, PROPERTY_TYPE_COUNT, 0, NULL, NULL, NULL, NULL, NULL, NULL) \ - } \ - ; - -#define OBJECT_TYPEINFO(Type) Type::StaticTypeInfo() -#define OBJECT_TYPEINFO_PTR(Ptr) Ptr->StaticTypeInfo() - -#define OBJECT_MUTABLE_TYPEINFO(Type) Type::StaticMutableTypeInfo() -#define OBJECT_MUTABLE_TYPEINFO_PTR(Type) Type->StaticMutableTypeInfo() diff --git a/src/common/property.cpp b/src/common/property.cpp deleted file mode 100644 index f404b3dd9..000000000 --- a/src/common/property.cpp +++ /dev/null @@ -1,349 +0,0 @@ -#include "common/property.h" -#include "YBaseLib/BinaryReader.h" -#include "YBaseLib/BinaryWriter.h" -#include "YBaseLib/StringConverter.h" - -bool GetPropertyValueAsString(const void* object, const PROPERTY_DECLARATION* property, String& value) -{ - if (!property->GetPropertyCallback) - return false; - - // Strings handled seperately. - if (property->Type == PROPERTY_TYPE_STRING) - { - // We can pass StrValue directly across. - return property->GetPropertyCallback(object, property->pGetPropertyCallbackUserData, &value); - } - else - { - // 32 bytes should be enough for the actual value. (largest is currently transform, which is float3 + quat + float) - byte TempValue[32]; - - // Call the function. - if (!property->GetPropertyCallback(object, property->pGetPropertyCallbackUserData, &TempValue)) - return false; - - // Now stringize it based on type. - switch (property->Type) - { - case PROPERTY_TYPE_BOOL: - StringConverter::BoolToString(value, reinterpret_cast(TempValue)); - break; - - case PROPERTY_TYPE_UINT: - StringConverter::UInt32ToString(value, reinterpret_cast(TempValue)); - break; - - case PROPERTY_TYPE_INT: - StringConverter::Int32ToString(value, reinterpret_cast(TempValue)); - break; - - case PROPERTY_TYPE_FLOAT: - StringConverter::FloatToString(value, reinterpret_cast(TempValue)); - break; - - default: - UnreachableCode(); - break; - } - - return true; - } -} - -bool SetPropertyValueFromString(void* object, const PROPERTY_DECLARATION* property, const char* value) -{ - if (property->SetPropertyCallback == NULL) - return false; - - // Strings handled seperately. - if (property->Type == PROPERTY_TYPE_STRING) - { - // Create a constant string. - StaticString StringRef(value); - if (!property->SetPropertyCallback(object, property->pSetPropertyCallbackUserData, &StringRef)) - return false; - } - else - { - // 32 bytes should be enough for the actual value. (largest is currently transform, which is float3 + quat + float) - byte TempValue[32]; - - // Un-stringize based on type. - switch (property->Type) - { - case PROPERTY_TYPE_BOOL: - reinterpret_cast(TempValue) = StringConverter::StringToBool(value); - break; - - case PROPERTY_TYPE_UINT: - reinterpret_cast(TempValue) = StringConverter::StringToUInt32(value); - break; - - case PROPERTY_TYPE_INT: - reinterpret_cast(TempValue) = StringConverter::StringToInt32(value); - break; - - case PROPERTY_TYPE_FLOAT: - reinterpret_cast(TempValue) = StringConverter::StringToFloat(value); - break; - - default: - UnreachableCode(); - break; - } - - // Call the function. - if (!property->SetPropertyCallback(object, property->pSetPropertyCallbackUserData, TempValue)) - return false; - } - - // Notify updater if needed. - // if (pProperty->PropertyChangedCallback != NULL) - // pProperty->PropertyChangedCallback(pObject, pProperty->pPropertyChangedCallbackUserData); - - return true; -} - -bool WritePropertyValueToBuffer(const void* object, const PROPERTY_DECLARATION* property, BinaryWriter& writer) -{ - if (!property->GetPropertyCallback) - return false; - - // Strings handled seperately. - if (property->Type == PROPERTY_TYPE_STRING) - { - // We can pass StrValue directly across. - SmallString stringValue; - if (!property->GetPropertyCallback(object, property->pGetPropertyCallbackUserData, &stringValue)) - return false; - - writer.WriteUInt32(stringValue.GetLength() + 1); - writer.WriteCString(stringValue); - return true; - } - else - { - // 32 bytes should be enough for the actual value. (largest is currently transform, which is float3 + quat + float) - byte TempValue[32]; - - // Call the function. - if (!property->GetPropertyCallback(object, property->pGetPropertyCallbackUserData, &TempValue)) - return false; - - // Now stringize it based on type. - switch (property->Type) - { - case PROPERTY_TYPE_BOOL: - writer.WriteUInt32(1); - writer.WriteBool(reinterpret_cast(TempValue)); - break; - - case PROPERTY_TYPE_UINT: - writer.WriteUInt32(4); - writer.WriteUInt32(reinterpret_cast(TempValue)); - break; - - case PROPERTY_TYPE_INT: - writer.WriteUInt32(4); - writer.WriteInt32(reinterpret_cast(TempValue)); - break; - - case PROPERTY_TYPE_FLOAT: - writer.WriteUInt32(4); - writer.WriteFloat(reinterpret_cast(TempValue)); - break; - - default: - UnreachableCode(); - break; - } - - return true; - } -} - -bool ReadPropertyValueFromBuffer(void* object, const PROPERTY_DECLARATION* property, BinaryReader& reader) -{ - if (!property->SetPropertyCallback) - return false; - - // Strings handled seperately. - if (property->Type == PROPERTY_TYPE_STRING) - { - u32 stringLength = reader.ReadUInt32(); - - SmallString stringValue; - reader.ReadCString(stringValue); - if (stringValue.GetLength() != (stringLength - 1) || - !property->SetPropertyCallback(object, property->pSetPropertyCallbackUserData, &stringValue)) - return false; - } - else - { - // 32 bytes should be enough for the actual value. (largest is currently transform, which is float3 + quat + float) - byte temp_value[32]; - - // Un-stringize based on type. - switch (property->Type) - { - case PROPERTY_TYPE_BOOL: - if (reader.ReadUInt32() != 1) - { - return false; - } - reinterpret_cast(temp_value) = reader.ReadBool(); - break; - - case PROPERTY_TYPE_UINT: - if (reader.ReadUInt32() != 4) - { - return false; - } - reinterpret_cast(temp_value) = reader.ReadUInt32(); - break; - - case PROPERTY_TYPE_INT: - if (reader.ReadUInt32() != 4) - { - return false; - } - reinterpret_cast(temp_value) = reader.ReadInt32(); - break; - - case PROPERTY_TYPE_FLOAT: - if (reader.ReadUInt32() != 4) - { - return false; - } - reinterpret_cast(temp_value) = reader.ReadFloat(); - break; - - default: - UnreachableCode(); - break; - } - - // Call the function. - if (!property->SetPropertyCallback(object, property->pSetPropertyCallbackUserData, temp_value)) - return false; - } - - // Notify updater if needed. - // if (pProperty->PropertyChangedCallback != NULL) - // pProperty->PropertyChangedCallback(pObject, pProperty->pPropertyChangedCallbackUserData); - - return true; -} - -bool EncodePropertyTypeToBuffer(PROPERTY_TYPE type, const char* value_string, BinaryWriter& writer) -{ - // Strings handled seperately. - if (type == PROPERTY_TYPE_STRING) - { - // We can pass StrValue directly across. - writer.WriteUInt32(Y_strlen(value_string) + 1); - writer.WriteCString(value_string); - return true; - } - else - { - // Now stringize it based on type. - switch (type) - { - case PROPERTY_TYPE_BOOL: - writer.WriteUInt32(1); - writer.WriteBool(StringConverter::StringToBool(value_string)); - break; - - case PROPERTY_TYPE_UINT: - writer.WriteUInt32(4); - writer.WriteUInt32(StringConverter::StringToUInt32(value_string)); - break; - - case PROPERTY_TYPE_INT: - writer.WriteUInt32(4); - writer.WriteInt32(StringConverter::StringToInt32(value_string)); - break; - - case PROPERTY_TYPE_FLOAT: - writer.WriteUInt32(4); - writer.WriteFloat(StringConverter::StringToFloat(value_string)); - break; - - default: - UnreachableCode(); - break; - } - - return true; - } -} - -// default property callbacks -bool DefaultPropertyTableCallbacks::GetBool(const void* pObjectPtr, const void* pUserData, bool* pValuePtr) -{ - *pValuePtr = *((const bool*)((((const byte*)pObjectPtr) + (*(int*)&pUserData)))); - return true; -} - -bool DefaultPropertyTableCallbacks::SetBool(void* pObjectPtr, const void* pUserData, const bool* pValuePtr) -{ - *((bool*)((((byte*)pObjectPtr) + (*(int*)&pUserData)))) = *pValuePtr; - return true; -} - -bool DefaultPropertyTableCallbacks::GetUInt(const void* pObjectPtr, const void* pUserData, u32* pValuePtr) -{ - *pValuePtr = *((const u32*)((((const byte*)pObjectPtr) + (*(u32*)&pUserData)))); - return true; -} - -bool DefaultPropertyTableCallbacks::SetUInt(void* pObjectPtr, const void* pUserData, const u32* pValuePtr) -{ - *((u32*)((((byte*)pObjectPtr) + (*(u32*)&pUserData)))) = *pValuePtr; - return true; -} - -bool DefaultPropertyTableCallbacks::GetInt(const void* pObjectPtr, const void* pUserData, s32* pValuePtr) -{ - *pValuePtr = *((const s32*)((((const byte*)pObjectPtr) + (*(s32*)&pUserData)))); - return true; -} - -bool DefaultPropertyTableCallbacks::SetInt(void* pObjectPtr, const void* pUserData, const s32* pValuePtr) -{ - *((s32*)((((byte*)pObjectPtr) + (*(s32*)&pUserData)))) = *pValuePtr; - return true; -} - -bool DefaultPropertyTableCallbacks::GetFloat(const void* pObjectPtr, const void* pUserData, float* pValuePtr) -{ - *pValuePtr = *((const float*)((((const byte*)pObjectPtr) + (*(int*)&pUserData)))); - return true; -} - -bool DefaultPropertyTableCallbacks::SetFloat(void* pObjectPtr, const void* pUserData, const float* pValuePtr) -{ - *((float*)((((byte*)pObjectPtr) + (*(int*)&pUserData)))) = *pValuePtr; - return true; -} - -bool DefaultPropertyTableCallbacks::SetString(void* pObjectPtr, const void* pUserData, const String* pValuePtr) -{ - ((String*)((((byte*)pObjectPtr) + (*(int*)&pUserData))))->Assign(*pValuePtr); - return true; -} - -bool DefaultPropertyTableCallbacks::GetString(const void* pObjectPtr, const void* pUserData, String* pValuePtr) -{ - pValuePtr->Assign(*((const String*)((((const byte*)pObjectPtr) + (*(int*)&pUserData))))); - return true; -} - -bool DefaultPropertyTableCallbacks::GetConstBool(const void* pObjectPtr, const void* pUserData, bool* pValuePtr) -{ - bool Value = (pUserData != 0) ? true : false; - *pValuePtr = Value; - return true; -} diff --git a/src/common/property.h b/src/common/property.h deleted file mode 100644 index 5ef49dcf4..000000000 --- a/src/common/property.h +++ /dev/null @@ -1,103 +0,0 @@ -#pragma once -#include "common/types.h" - -class BinaryReader; -class BinaryWriter; -class String; - -enum : u32 -{ - MAX_PROPERTY_TABLE_NAME_LENGTH = 128, - MAX_PROPERTY_NAME_LENGTH = 128 -}; - -enum PROPERTY_TYPE -{ - PROPERTY_TYPE_BOOL, - PROPERTY_TYPE_UINT, - PROPERTY_TYPE_INT, - PROPERTY_TYPE_FLOAT, - PROPERTY_TYPE_STRING, - PROPERTY_TYPE_COUNT, -}; - -enum PROPERTY_FLAG -{ - PROPERTY_FLAG_READ_ONLY = (1 << 0), // Property cannot be modified by user. Engine can still modify it, however. - PROPERTY_FLAG_INVOKE_CHANGE_CALLBACK_ON_CREATE = - (1 << 1), // Property change callback will be invoked when the object is being created. By default it is not. -}; - -struct PROPERTY_DECLARATION -{ - typedef bool (*GET_PROPERTY_CALLBACK)(const void* object, const void* userdata, void* value_ptr); - typedef bool (*SET_PROPERTY_CALLBACK)(void* object, const void* userdata, const void* value_ptr); - typedef void (*PROPERTY_CHANGED_CALLBACK)(void* object, const void* userdata); - - const char* Name; - PROPERTY_TYPE Type; - u32 Flags; - - GET_PROPERTY_CALLBACK GetPropertyCallback; - const void* pGetPropertyCallbackUserData; - SET_PROPERTY_CALLBACK SetPropertyCallback; - const void* pSetPropertyCallbackUserData; - PROPERTY_CHANGED_CALLBACK PropertyChangedCallback; - const void* pPropertyChangedCallbackUserData; -}; - -bool GetPropertyValueAsString(const void* object, const PROPERTY_DECLARATION* property, String& value); -bool SetPropertyValueFromString(void* object, const PROPERTY_DECLARATION* property, const char* value); -bool WritePropertyValueToBuffer(const void* object, const PROPERTY_DECLARATION* property, BinaryWriter& writer); -bool ReadPropertyValueFromBuffer(void* object, const PROPERTY_DECLARATION* property, BinaryReader& reader); -bool EncodePropertyTypeToBuffer(PROPERTY_TYPE type, const char* value_string, BinaryWriter& writer); - -namespace DefaultPropertyTableCallbacks { -// builtin functions -bool GetBool(const void* object, const void* userdata, bool* value_ptr); -bool SetBool(void* object, const void* userdata, const bool* value_ptr); -bool GetUInt(const void* object, const void* userdata, u32* value_ptr); -bool SetUInt(void* object, const void* userdata, const u32* value_ptr); -bool GetInt(const void* object, const void* userdata, s32* value_ptr); -bool SetInt(void* object, const void* userdata, const s32* value_ptr); -bool GetFloat(const void* object, const void* userdata, float* value_ptr); -bool SetFloat(void* object, const void* userdata, const float* value_ptr); -bool GetString(const void* object, const void* userdata, String* value_ptr); -bool SetString(void* object, const void* userdata, const String* value_ptr); - -// static bool value -bool GetConstBool(const void* object, const void* userdata, bool* value_ptr); -} // namespace DefaultPropertyTableCallbacks - -#define PROPERTY_TABLE_MEMBER(Name, Type, Flags, GetPropertyCallback, GetPropertyCallbackUserData, \ - SetPropertyCallback, SetPropertyCallbackUserData, PropertyChangedCallback, \ - PropertyChangedCallbackUserData) \ - {Name, \ - Type, \ - Flags, \ - (PROPERTY_DECLARATION::GET_PROPERTY_CALLBACK)(GetPropertyCallback), \ - (const void*)(GetPropertyCallbackUserData), \ - (PROPERTY_DECLARATION::SET_PROPERTY_CALLBACK)(SetPropertyCallback), \ - (const void*)(SetPropertyCallbackUserData), \ - (PROPERTY_DECLARATION::PROPERTY_CHANGED_CALLBACK)(PropertyChangedCallback), \ - (const void*)(PropertyChangedCallbackUserData)}, - -#define PROPERTY_TABLE_MEMBER_BOOL(Name, Flags, Offset, ChangedFunc, ChangedFuncUserData) \ - PROPERTY_TABLE_MEMBER(Name, PROPERTY_TYPE_BOOL, Flags, DefaultPropertyTableCallbacks::GetBool, (Offset), \ - DefaultPropertyTableCallbacks::SetBool, (Offset), ChangedFunc, ChangedFuncUserData) - -#define PROPERTY_TABLE_MEMBER_UINT(Name, Flags, Offset, ChangedFunc, ChangedFuncUserData) \ - PROPERTY_TABLE_MEMBER(Name, PROPERTY_TYPE_INT, Flags, DefaultPropertyTableCallbacks::GetUInt, (Offset), \ - DefaultPropertyTableCallbacks::SetUInt, (Offset), ChangedFunc, ChangedFuncUserData) - -#define PROPERTY_TABLE_MEMBER_INT(Name, Flags, Offset, ChangedFunc, ChangedFuncUserData) \ - PROPERTY_TABLE_MEMBER(Name, PROPERTY_TYPE_INT, Flags, DefaultPropertyTableCallbacks::GetInt, (Offset), \ - DefaultPropertyTableCallbacks::SetInt, (Offset), ChangedFunc, ChangedFuncUserData) - -#define PROPERTY_TABLE_MEMBER_FLOAT(Name, Flags, Offset, ChangedFunc, ChangedFuncUserData) \ - PROPERTY_TABLE_MEMBER(Name, PROPERTY_TYPE_FLOAT, Flags, DefaultPropertyTableCallbacks::GetFloat, (Offset), \ - DefaultPropertyTableCallbacks::SetFloat, (Offset), ChangedFunc, ChangedFuncUserData) - -#define PROPERTY_TABLE_MEMBER_STRING(Name, Flags, Offset, ChangedFunc, ChangedFuncUserData) \ - PROPERTY_TABLE_MEMBER(Name, PROPERTY_TYPE_STRING, Flags, DefaultPropertyTableCallbacks::GetString, (Offset), \ - DefaultPropertyTableCallbacks::SetString, (Offset), ChangedFunc, ChangedFuncUserData) diff --git a/src/common/type_registry.h b/src/common/type_registry.h deleted file mode 100644 index 1aa3b73cf..000000000 --- a/src/common/type_registry.h +++ /dev/null @@ -1,110 +0,0 @@ -#pragma once -#include "YBaseLib/CString.h" -#include "YBaseLib/MemArray.h" -#include "YBaseLib/PODArray.h" -#include "common/types.h" - -#define INVALID_TYPE_INDEX 0xFFFFFFFF - -template -class TypeRegistry -{ -public: - struct RegisteredTypeInfo - { - T* pTypeInfo; - const char* TypeName; - u32 InheritanceDepth; - }; - -public: - TypeRegistry() {} - ~TypeRegistry() {} - - u32 RegisterTypeInfo(T* pTypeInfo, const char* TypeName, u32 InheritanceDepth) - { - u32 Index; - DebugAssert(pTypeInfo != nullptr); - - for (Index = 0; Index < m_arrTypes.GetSize(); Index++) - { - if (m_arrTypes[Index].pTypeInfo == pTypeInfo) - Panic("Attempting to register type multiple times."); - } - - for (Index = 0; Index < m_arrTypes.GetSize(); Index++) - { - if (m_arrTypes[Index].pTypeInfo == nullptr) - { - m_arrTypes[Index].pTypeInfo = pTypeInfo; - m_arrTypes[Index].TypeName = TypeName; - m_arrTypes[Index].InheritanceDepth = InheritanceDepth; - break; - } - } - if (Index == m_arrTypes.GetSize()) - { - RegisteredTypeInfo t; - t.pTypeInfo = pTypeInfo; - t.TypeName = TypeName; - t.InheritanceDepth = InheritanceDepth; - m_arrTypes.Add(t); - } - - CalculateMaxInheritanceDepth(); - return Index; - } - - void UnregisterTypeInfo(T* pTypeInfo) - { - u32 i; - for (i = 0; i < m_arrTypes.GetSize(); i++) - { - if (m_arrTypes[i].pTypeInfo == pTypeInfo) - { - m_arrTypes[i].pTypeInfo = nullptr; - m_arrTypes[i].TypeName = nullptr; - m_arrTypes[i].InheritanceDepth = 0; - break; - } - } - } - - const u32 GetNumTypes() const { return m_arrTypes.GetSize(); } - const u32 GetMaxInheritanceDepth() const { return m_iMaxInheritanceDepth; } - - const RegisteredTypeInfo& GetRegisteredTypeInfoByIndex(u32 TypeIndex) const - { - return m_arrTypes.GetElement(TypeIndex); - } - - const T* GetTypeInfoByIndex(u32 TypeIndex) const { return m_arrTypes.GetElement(TypeIndex).pTypeInfo; } - - const T* GetTypeInfoByName(const char* TypeName) const - { - for (u32 i = 0; i < m_arrTypes.GetSize(); i++) - { - if (m_arrTypes[i].pTypeInfo != nullptr && !Y_stricmp(m_arrTypes[i].TypeName, TypeName)) - return m_arrTypes[i].pTypeInfo; - } - - return nullptr; - } - -private: - typedef MemArray TypeArray; - TypeArray m_arrTypes; - u32 m_iMaxInheritanceDepth; - - void CalculateMaxInheritanceDepth() - { - u32 i; - m_iMaxInheritanceDepth = 0; - - for (i = 0; i < m_arrTypes.GetSize(); i++) - { - if (m_arrTypes[i].pTypeInfo != nullptr) - m_iMaxInheritanceDepth = Max(m_iMaxInheritanceDepth, m_arrTypes[i].InheritanceDepth); - } - } -}; diff --git a/src/duckstation/CMakeLists.txt b/src/duckstation/CMakeLists.txt index f03c63171..a221ad0eb 100644 --- a/src/duckstation/CMakeLists.txt +++ b/src/duckstation/CMakeLists.txt @@ -1,7 +1,5 @@ set(SRCS main.cpp - sdl_audio_mixer.cpp - sdl_audio_mixer.h sdl_audio_stream.cpp sdl_audio_stream.h sdl_interface.cpp diff --git a/src/duckstation/duckstation.vcxproj b/src/duckstation/duckstation.vcxproj index b729d0663..9f17c07da 100644 --- a/src/duckstation/duckstation.vcxproj +++ b/src/duckstation/duckstation.vcxproj @@ -53,14 +53,12 @@ - - diff --git a/src/duckstation/duckstation.vcxproj.filters b/src/duckstation/duckstation.vcxproj.filters index f798dc062..9efb6a869 100644 --- a/src/duckstation/duckstation.vcxproj.filters +++ b/src/duckstation/duckstation.vcxproj.filters @@ -2,13 +2,11 @@ - - diff --git a/src/duckstation/sdl_audio_mixer.cpp b/src/duckstation/sdl_audio_mixer.cpp deleted file mode 100644 index 558cb19b1..000000000 --- a/src/duckstation/sdl_audio_mixer.cpp +++ /dev/null @@ -1,129 +0,0 @@ -#include "sdl_audio_mixer.h" -#include "YBaseLib/Timer.h" -#include - -using namespace Audio; - -inline SDL_AudioFormat GetSDLAudioFormat(SampleFormat format) -{ - switch (format) - { - case SampleFormat::Signed8: - return AUDIO_S8; - - case SampleFormat::Unsigned8: - return AUDIO_U8; - - case SampleFormat::Signed16: - return AUDIO_S16SYS; - - case SampleFormat::Unsigned16: - return AUDIO_U16SYS; - - case SampleFormat::Signed32: - return AUDIO_S32SYS; - - case SampleFormat::Float32: - return AUDIO_F32; - } - - Panic("Unhandled format"); - return AUDIO_U8; -} - -SDLAudioMixer::SDLAudioMixer(SDL_AudioDeviceID device_id, float output_sample_rate) - : Mixer(output_sample_rate), m_device_id(device_id) -{ -} - -SDLAudioMixer::~SDLAudioMixer() -{ - SDL_CloseAudioDevice(m_device_id); -} - -std::unique_ptr SDLAudioMixer::Create() -{ - auto mixer = std::make_unique(0, 44100.0f); - SDL_AudioSpec spec = {44100, AUDIO_F32, static_cast(NumOutputChannels), 0, 4096, 0, 0, - RenderCallback, mixer.get()}; - SDL_AudioSpec obtained_spec; - SDL_AudioDeviceID device_id = SDL_OpenAudioDevice(nullptr, 0, &spec, &obtained_spec, 0); - if (device_id == 0) - return nullptr; - - mixer->m_device_id = device_id; - - SDL_PauseAudioDevice(device_id, SDL_FALSE); - - return mixer; -} - -void SDLAudioMixer::RenderSamples(Audio::OutputFormatType* buf, size_t num_samples) -{ - CheckRenderBufferSize(num_samples); - std::fill_n(buf, num_samples * NumOutputChannels, 0.0f); - - for (auto& channel : m_channels) - { - channel->ReadSamples(m_render_buffer.data(), num_samples); - - // Don't bother mixing it if we're muted. - if (m_muted) - continue; - - // If the format is the same, we can just copy it as-is.. - if (channel->GetChannels() == 1) - { - // Mono -> stereo - for (ssize_t idx = ssize_t(num_samples) - 1; idx >= 0; idx--) - { - float sample = m_render_buffer[idx]; - m_render_buffer[idx * 2 + 0] = sample; - m_render_buffer[idx * 2 + 1] = sample; - } - } - else if (channel->GetChannels() != NumOutputChannels) - { - SDL_AudioCVT cvt; - int err = SDL_BuildAudioCVT(&cvt, AUDIO_F32, Truncate8(channel->GetChannels()), int(m_output_sample_rate), - AUDIO_F32, Truncate8(NumOutputChannels), int(m_output_sample_rate)); - if (err != 1) - Panic("Failed to set up audio conversion"); - - cvt.len = int(channel->GetChannels() * sizeof(float)); - cvt.buf = reinterpret_cast(m_render_buffer.data()); - err = SDL_ConvertAudio(&cvt); - if (err != 0) - Panic("Failed to convert audio"); - } - - // Mix channels together. - const Audio::OutputFormatType* mix_src = reinterpret_cast(m_render_buffer.data()); - Audio::OutputFormatType* mix_dst = buf; - for (size_t i = 0; i < num_samples * NumOutputChannels; i++) - { - // TODO: Saturation/clamping here - *(mix_dst++) += *(mix_src++); - } - } - -#if 0 - static FILE* fp = nullptr; - if (!fp) - fp = fopen("D:\\mixed.raw", "wb"); - if (fp) - { - fwrite(buf, sizeof(float), num_samples * NumOutputChannels, fp); - fflush(fp); - } -#endif -} - -void SDLAudioMixer::RenderCallback(void* userdata, Uint8* stream, int len) -{ - SDLAudioMixer* mixer = static_cast(userdata); - Audio::OutputFormatType* buf = reinterpret_cast(stream); - size_t num_samples = size_t(len) / NumOutputChannels / sizeof(Audio::OutputFormatType); - if (num_samples > 0) - mixer->RenderSamples(buf, num_samples); -} diff --git a/src/duckstation/sdl_audio_mixer.h b/src/duckstation/sdl_audio_mixer.h deleted file mode 100644 index 78c810d06..000000000 --- a/src/duckstation/sdl_audio_mixer.h +++ /dev/null @@ -1,19 +0,0 @@ -#pragma once -#include "common/audio.h" -#include - -class SDLAudioMixer : public Audio::Mixer -{ -public: - SDLAudioMixer(SDL_AudioDeviceID device_id, float output_sample_rate); - virtual ~SDLAudioMixer(); - - static std::unique_ptr Create(); - -protected: - void RenderSamples(Audio::OutputFormatType* buf, size_t num_samples); - static void RenderCallback(void* userdata, Uint8* stream, int len); - -private: - SDL_AudioDeviceID m_device_id; -};