wip
This commit is contained in:
parent
cb127b6412
commit
20426d96b0
|
@ -113,15 +113,19 @@ public:
|
||||||
/// Call when the window size changes externally to recreate any resources.
|
/// Call when the window size changes externally to recreate any resources.
|
||||||
virtual void ResizeRenderWindow(s32 new_window_width, s32 new_window_height) = 0;
|
virtual void ResizeRenderWindow(s32 new_window_width, s32 new_window_height) = 0;
|
||||||
|
|
||||||
|
virtual bool SupportsDisplayPixelFormat(HostDisplayPixelFormat format) const = 0;
|
||||||
|
|
||||||
/// Creates an abstracted RGBA8 texture. If dynamic, the texture can be updated with UpdateTexture() below.
|
/// Creates an abstracted RGBA8 texture. If dynamic, the texture can be updated with UpdateTexture() below.
|
||||||
virtual std::unique_ptr<HostDisplayTexture> CreateTexture(u32 width, u32 height, u32 layers, u32 levels, u32 samples,
|
virtual std::unique_ptr<HostDisplayTexture> CreateTexture(u32 width, u32 height, u32 layers, u32 levels, u32 samples,
|
||||||
HostDisplayPixelFormat format, const void* data,
|
HostDisplayPixelFormat format, const void* data,
|
||||||
u32 data_stride, bool dynamic = false) = 0;
|
u32 data_stride, bool dynamic = false) = 0;
|
||||||
virtual void UpdateTexture(HostDisplayTexture* texture, u32 x, u32 y, u32 width, u32 height, const void* data,
|
virtual void UpdateTexture(HostDisplayTexture* texture, u32 x, u32 y, u32 width, u32 height, const void* data,
|
||||||
u32 data_stride) = 0;
|
u32 data_stride) = 0;
|
||||||
|
|
||||||
virtual bool DownloadTexture(const void* texture_handle, HostDisplayPixelFormat texture_format, u32 x, u32 y,
|
virtual bool DownloadTexture(const void* texture_handle, HostDisplayPixelFormat texture_format, u32 x, u32 y,
|
||||||
u32 width, u32 height, void* out_data, u32 out_data_stride) = 0;
|
u32 width, u32 height, void* out_data, u32 out_data_stride) = 0;
|
||||||
|
virtual bool MapTexture(HostDisplayTexture* texture, u32 x, u32 y, u32 width, u32 height, void** out_buffer,
|
||||||
|
u32* out_pitch) = 0;
|
||||||
|
virtual void UnmapTexture(HostDisplayTexture* texture) = 0;
|
||||||
|
|
||||||
/// Returns false if the window was completely occluded.
|
/// Returns false if the window was completely occluded.
|
||||||
virtual bool Render() = 0;
|
virtual bool Render() = 0;
|
||||||
|
@ -137,6 +141,8 @@ public:
|
||||||
virtual void DestroyImGuiContext() = 0;
|
virtual void DestroyImGuiContext() = 0;
|
||||||
virtual bool UpdateImGuiFontTexture() = 0;
|
virtual bool UpdateImGuiFontTexture() = 0;
|
||||||
|
|
||||||
|
virtual bool GetHostRefreshRate(float* refresh_rate);
|
||||||
|
|
||||||
const void* GetDisplayTextureHandle() const { return m_display_texture_handle; }
|
const void* GetDisplayTextureHandle() const { return m_display_texture_handle; }
|
||||||
const s32 GetDisplayTopMargin() const { return m_display_top_margin; }
|
const s32 GetDisplayTopMargin() const { return m_display_top_margin; }
|
||||||
const s32 GetDisplayWidth() const { return m_display_width; }
|
const s32 GetDisplayWidth() const { return m_display_width; }
|
||||||
|
@ -200,15 +206,6 @@ public:
|
||||||
HostDisplayPixelFormat format);
|
HostDisplayPixelFormat format);
|
||||||
static void FlipTextureDataRGBA8(u32 width, u32 height, std::vector<u32>& texture_data, u32 texture_data_stride);
|
static void FlipTextureDataRGBA8(u32 width, u32 height, std::vector<u32>& texture_data, u32 texture_data_stride);
|
||||||
|
|
||||||
virtual bool SupportsDisplayPixelFormat(HostDisplayPixelFormat format) const = 0;
|
|
||||||
|
|
||||||
virtual bool BeginSetDisplayPixels(HostDisplayPixelFormat format, u32 width, u32 height, void** out_buffer,
|
|
||||||
u32* out_pitch) = 0;
|
|
||||||
virtual void EndSetDisplayPixels() = 0;
|
|
||||||
virtual bool SetDisplayPixels(HostDisplayPixelFormat format, u32 width, u32 height, const void* buffer, u32 pitch);
|
|
||||||
|
|
||||||
virtual bool GetHostRefreshRate(float* refresh_rate);
|
|
||||||
|
|
||||||
void SetDisplayLinearFiltering(bool enabled) { m_display_linear_filtering = enabled; }
|
void SetDisplayLinearFiltering(bool enabled) { m_display_linear_filtering = enabled; }
|
||||||
void SetDisplayTopMargin(s32 height) { m_display_top_margin = height; }
|
void SetDisplayTopMargin(s32 height) { m_display_top_margin = height; }
|
||||||
void SetDisplayIntegerScaling(bool enabled) { m_display_integer_scaling = enabled; }
|
void SetDisplayIntegerScaling(bool enabled) { m_display_integer_scaling = enabled; }
|
||||||
|
@ -312,10 +309,10 @@ void ReleaseHostDisplay();
|
||||||
|
|
||||||
/// Returns false if the window was completely occluded. If frame_skip is set, the frame won't be
|
/// Returns false if the window was completely occluded. If frame_skip is set, the frame won't be
|
||||||
/// displayed, but the GPU command queue will still be flushed.
|
/// displayed, but the GPU command queue will still be flushed.
|
||||||
//bool BeginPresentFrame(bool frame_skip);
|
// bool BeginPresentFrame(bool frame_skip);
|
||||||
|
|
||||||
/// Presents the frame to the display, and renders OSD elements.
|
/// Presents the frame to the display, and renders OSD elements.
|
||||||
//void EndPresentFrame();
|
// void EndPresentFrame();
|
||||||
|
|
||||||
/// Provided by the host; renders the display.
|
/// Provided by the host; renders the display.
|
||||||
void RenderDisplay();
|
void RenderDisplay();
|
||||||
|
|
|
@ -182,24 +182,15 @@ bool D3D11HostDisplay::SupportsDisplayPixelFormat(HostDisplayPixelFormat format)
|
||||||
return (SUCCEEDED(m_device->CheckFormatSupport(dfmt, &support)) && ((support & required) == required));
|
return (SUCCEEDED(m_device->CheckFormatSupport(dfmt, &support)) && ((support & required) == required));
|
||||||
}
|
}
|
||||||
|
|
||||||
bool D3D11HostDisplay::BeginSetDisplayPixels(HostDisplayPixelFormat format, u32 width, u32 height, void** out_buffer,
|
bool D3D11HostDisplay::MapTexture(HostDisplayTexture* texture, HostDisplayPixelFormat format, u32 width, u32 height,
|
||||||
u32* out_pitch)
|
void** out_buffer, u32* out_pitch)
|
||||||
{
|
{
|
||||||
ClearDisplayTexture();
|
D3D11HostDisplayTexture* tex = static_cast<D3D11HostDisplayTexture*>(texture);
|
||||||
|
if (!tex->IsDynamic())
|
||||||
const DXGI_FORMAT dxgi_format = s_display_pixel_format_mapping[static_cast<u32>(format)];
|
return false;
|
||||||
if (m_display_pixels_texture.GetWidth() < width || m_display_pixels_texture.GetHeight() < height ||
|
|
||||||
m_display_pixels_texture.GetFormat() != dxgi_format)
|
|
||||||
{
|
|
||||||
if (!m_display_pixels_texture.Create(m_device.Get(), width, height, 1, 1, dxgi_format, D3D11_BIND_SHADER_RESOURCE,
|
|
||||||
nullptr, 0, true))
|
|
||||||
{
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
D3D11_MAPPED_SUBRESOURCE sr;
|
D3D11_MAPPED_SUBRESOURCE sr;
|
||||||
HRESULT hr = m_context->Map(m_display_pixels_texture.GetD3DTexture(), 0, D3D11_MAP_WRITE_DISCARD, 0, &sr);
|
HRESULT hr = m_context->Map(tex->GetD3DTexture(), 0, D3D11_MAP_WRITE_DISCARD, 0, &sr);
|
||||||
if (FAILED(hr))
|
if (FAILED(hr))
|
||||||
{
|
{
|
||||||
Log_ErrorPrintf("Map pixels texture failed: %08X", hr);
|
Log_ErrorPrintf("Map pixels texture failed: %08X", hr);
|
||||||
|
@ -208,15 +199,12 @@ bool D3D11HostDisplay::BeginSetDisplayPixels(HostDisplayPixelFormat format, u32
|
||||||
|
|
||||||
*out_buffer = sr.pData;
|
*out_buffer = sr.pData;
|
||||||
*out_pitch = sr.RowPitch;
|
*out_pitch = sr.RowPitch;
|
||||||
|
|
||||||
SetDisplayTexture(m_display_pixels_texture.GetD3DSRV(), format, m_display_pixels_texture.GetWidth(),
|
|
||||||
m_display_pixels_texture.GetHeight(), 0, 0, static_cast<u32>(width), static_cast<u32>(height));
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void D3D11HostDisplay::EndSetDisplayPixels()
|
void D3D11HostDisplay::UnmapTexture(HostDisplayTexture* texture)
|
||||||
{
|
{
|
||||||
m_context->Unmap(m_display_pixels_texture.GetD3DTexture(), 0);
|
m_context->Unmap(static_cast<D3D11HostDisplayTexture*>(texture)->GetD3DTexture(), 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool D3D11HostDisplay::GetHostRefreshRate(float* refresh_rate)
|
bool D3D11HostDisplay::GetHostRefreshRate(float* refresh_rate)
|
||||||
|
|
|
@ -58,10 +58,10 @@ public:
|
||||||
u32 texture_data_stride) override;
|
u32 texture_data_stride) override;
|
||||||
bool DownloadTexture(const void* texture_handle, HostDisplayPixelFormat texture_format, u32 x, u32 y, u32 width,
|
bool DownloadTexture(const void* texture_handle, HostDisplayPixelFormat texture_format, u32 x, u32 y, u32 width,
|
||||||
u32 height, void* out_data, u32 out_data_stride) override;
|
u32 height, void* out_data, u32 out_data_stride) override;
|
||||||
|
bool MapTexture(HostDisplayTexture* texture, HostDisplayPixelFormat format, u32 width, u32 height, void** out_buffer,
|
||||||
|
u32* out_pitch) override;
|
||||||
|
void UnmapTexture(HostDisplayTexture* texture) override;
|
||||||
bool SupportsDisplayPixelFormat(HostDisplayPixelFormat format) const override;
|
bool SupportsDisplayPixelFormat(HostDisplayPixelFormat format) const override;
|
||||||
bool BeginSetDisplayPixels(HostDisplayPixelFormat format, u32 width, u32 height, void** out_buffer,
|
|
||||||
u32* out_pitch) override;
|
|
||||||
void EndSetDisplayPixels() override;
|
|
||||||
|
|
||||||
bool GetHostRefreshRate(float* refresh_rate) override;
|
bool GetHostRefreshRate(float* refresh_rate) override;
|
||||||
|
|
||||||
|
@ -128,7 +128,6 @@ protected:
|
||||||
ComPtr<ID3D11SamplerState> m_point_sampler;
|
ComPtr<ID3D11SamplerState> m_point_sampler;
|
||||||
ComPtr<ID3D11SamplerState> m_linear_sampler;
|
ComPtr<ID3D11SamplerState> m_linear_sampler;
|
||||||
|
|
||||||
D3D11::Texture m_display_pixels_texture;
|
|
||||||
D3D11::StreamBuffer m_display_uniform_buffer;
|
D3D11::StreamBuffer m_display_uniform_buffer;
|
||||||
D3D11::AutoStagingTexture m_readback_staging_texture;
|
D3D11::AutoStagingTexture m_readback_staging_texture;
|
||||||
|
|
||||||
|
|
|
@ -48,8 +48,25 @@ public:
|
||||||
const D3D12::Texture& GetTexture() const { return m_texture; }
|
const D3D12::Texture& GetTexture() const { return m_texture; }
|
||||||
D3D12::Texture& GetTexture() { return m_texture; }
|
D3D12::Texture& GetTexture() { return m_texture; }
|
||||||
|
|
||||||
|
u32 GetMapX() const { return m_map_x; }
|
||||||
|
u32 GetMapY() const { return m_map_y; }
|
||||||
|
u32 GetMapWidth() const { return m_map_width; }
|
||||||
|
u32 GetMapHeight() const { return m_map_height; }
|
||||||
|
|
||||||
|
void SetMapRect(u32 x, u32 y, u32 width, u32 height)
|
||||||
|
{
|
||||||
|
m_map_x = x;
|
||||||
|
m_map_y = y;
|
||||||
|
m_map_width = width;
|
||||||
|
m_map_height = height;
|
||||||
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
D3D12::Texture m_texture;
|
D3D12::Texture m_texture;
|
||||||
|
u32 m_map_x = 0;
|
||||||
|
u32 m_map_y = 0;
|
||||||
|
u32 m_map_width = 0;
|
||||||
|
u32 m_map_height = 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
D3D12HostDisplay::D3D12HostDisplay() = default;
|
D3D12HostDisplay::D3D12HostDisplay() = default;
|
||||||
|
@ -139,34 +156,21 @@ bool D3D12HostDisplay::SupportsDisplayPixelFormat(HostDisplayPixelFormat format)
|
||||||
return g_d3d12_context->SupportsTextureFormat(dfmt);
|
return g_d3d12_context->SupportsTextureFormat(dfmt);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool D3D12HostDisplay::BeginSetDisplayPixels(HostDisplayPixelFormat format, u32 width, u32 height, void** out_buffer,
|
bool D3D12HostDisplay::MapTexture(HostDisplayTexture* texture, u32 x, u32 y, u32 width, u32 height, void** out_buffer,
|
||||||
u32* out_pitch)
|
u32* out_pitch)
|
||||||
{
|
{
|
||||||
ClearDisplayTexture();
|
D3D12HostDisplayTexture* tex = static_cast<D3D12HostDisplayTexture*>(texture);
|
||||||
|
if (!tex->GetTexture().BeginStreamUpdate(0, 0, width, height, out_buffer, out_pitch))
|
||||||
const DXGI_FORMAT dxgi_format = s_display_pixel_format_mapping[static_cast<u32>(format)];
|
|
||||||
if (m_display_pixels_texture.GetWidth() < width || m_display_pixels_texture.GetHeight() < height ||
|
|
||||||
m_display_pixels_texture.GetFormat() != dxgi_format)
|
|
||||||
{
|
|
||||||
if (!m_display_pixels_texture.Create(width, height, 1, dxgi_format, dxgi_format, DXGI_FORMAT_UNKNOWN,
|
|
||||||
DXGI_FORMAT_UNKNOWN, D3D12_RESOURCE_FLAG_NONE))
|
|
||||||
{
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!m_display_pixels_texture.BeginStreamUpdate(0, 0, width, height, out_buffer, out_pitch))
|
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
SetDisplayTexture(&m_display_pixels_texture, format, m_display_pixels_texture.GetWidth(),
|
tex->SetMapRect(x, y, width, height);
|
||||||
m_display_pixels_texture.GetHeight(), 0, 0, static_cast<u32>(width), static_cast<u32>(height));
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void D3D12HostDisplay::EndSetDisplayPixels()
|
void D3D12HostDisplay::UnmapTexture(HostDisplayTexture* texture)
|
||||||
{
|
{
|
||||||
m_display_pixels_texture.EndStreamUpdate(0, 0, static_cast<u32>(m_display_texture_view_width),
|
D3D12HostDisplayTexture* tex = static_cast<D3D12HostDisplayTexture*>(texture);
|
||||||
static_cast<u32>(m_display_texture_view_height));
|
tex->GetTexture().EndStreamUpdate(tex->GetMapX(), tex->GetMapY(), tex->GetMapWidth(), tex->GetMapHeight());
|
||||||
}
|
}
|
||||||
|
|
||||||
bool D3D12HostDisplay::GetHostRefreshRate(float* refresh_rate)
|
bool D3D12HostDisplay::GetHostRefreshRate(float* refresh_rate)
|
||||||
|
|
|
@ -59,10 +59,10 @@ public:
|
||||||
u32 texture_data_stride) override;
|
u32 texture_data_stride) override;
|
||||||
bool DownloadTexture(const void* texture_handle, HostDisplayPixelFormat texture_format, u32 x, u32 y, u32 width,
|
bool DownloadTexture(const void* texture_handle, HostDisplayPixelFormat texture_format, u32 x, u32 y, u32 width,
|
||||||
u32 height, void* out_data, u32 out_data_stride) override;
|
u32 height, void* out_data, u32 out_data_stride) override;
|
||||||
|
bool MapTexture(HostDisplayTexture* texture, u32 x, u32 y, u32 width, u32 height, void** out_buffer,
|
||||||
|
u32* out_pitch) override;
|
||||||
|
void UnmapTexture(HostDisplayTexture* texture) override;
|
||||||
bool SupportsDisplayPixelFormat(HostDisplayPixelFormat format) const override;
|
bool SupportsDisplayPixelFormat(HostDisplayPixelFormat format) const override;
|
||||||
bool BeginSetDisplayPixels(HostDisplayPixelFormat format, u32 width, u32 height, void** out_buffer,
|
|
||||||
u32* out_pitch) override;
|
|
||||||
void EndSetDisplayPixels() override;
|
|
||||||
|
|
||||||
bool GetHostRefreshRate(float* refresh_rate) override;
|
bool GetHostRefreshRate(float* refresh_rate) override;
|
||||||
|
|
||||||
|
@ -115,7 +115,6 @@ protected:
|
||||||
D3D12::DescriptorHandle m_point_sampler;
|
D3D12::DescriptorHandle m_point_sampler;
|
||||||
D3D12::DescriptorHandle m_linear_sampler;
|
D3D12::DescriptorHandle m_linear_sampler;
|
||||||
|
|
||||||
D3D12::Texture m_display_pixels_texture;
|
|
||||||
D3D12::StreamBuffer m_display_uniform_buffer;
|
D3D12::StreamBuffer m_display_uniform_buffer;
|
||||||
D3D12::StagingTexture m_readback_staging_texture;
|
D3D12::StagingTexture m_readback_staging_texture;
|
||||||
|
|
||||||
|
|
|
@ -32,9 +32,46 @@ public:
|
||||||
|
|
||||||
GLuint GetGLID() const { return m_texture.GetGLId(); }
|
GLuint GetGLID() const { return m_texture.GetGLId(); }
|
||||||
|
|
||||||
|
u32 GetMapX() const { return m_map_x; }
|
||||||
|
u32 GetMapY() const { return m_map_y; }
|
||||||
|
u32 GetMapWidth() const { return m_map_width; }
|
||||||
|
u32 GetMapHeight() const { return m_map_height; }
|
||||||
|
u32 GetMapPBOOffset() const { return m_map_pbo_offset; }
|
||||||
|
u32 GetMapPBOSize() const { return m_map_pbo_size; }
|
||||||
|
|
||||||
|
void SetMapRect(u32 x, u32 y, u32 width, u32 height, u32 pbo_offset, u32 pbo_size)
|
||||||
|
{
|
||||||
|
m_map_x = x;
|
||||||
|
m_map_y = y;
|
||||||
|
m_map_width = width;
|
||||||
|
m_map_height = height;
|
||||||
|
m_map_pbo_offset = pbo_offset;
|
||||||
|
m_map_pbo_size = pbo_size;
|
||||||
|
}
|
||||||
|
|
||||||
|
void BindAndUpdateLinearFilter(bool enabled)
|
||||||
|
{
|
||||||
|
m_texture.Bind();
|
||||||
|
if (m_linear_filter == enabled)
|
||||||
|
return;
|
||||||
|
|
||||||
|
m_linear_filter = enabled;
|
||||||
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, enabled ? GL_LINEAR : GL_NEAREST);
|
||||||
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, enabled ? GL_LINEAR : GL_NEAREST);
|
||||||
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
GL::Texture m_texture;
|
GL::Texture m_texture;
|
||||||
HostDisplayPixelFormat m_format;
|
HostDisplayPixelFormat m_format;
|
||||||
|
|
||||||
|
u32 m_map_x = 0;
|
||||||
|
u32 m_map_y = 0;
|
||||||
|
u32 m_map_width = 0;
|
||||||
|
u32 m_map_height = 0;
|
||||||
|
u32 m_map_pbo_offset = 0;
|
||||||
|
u32 m_map_pbo_size = 0;
|
||||||
|
|
||||||
|
bool m_linear_filter = false;
|
||||||
};
|
};
|
||||||
|
|
||||||
OpenGLHostDisplay::OpenGLHostDisplay() = default;
|
OpenGLHostDisplay::OpenGLHostDisplay() = default;
|
||||||
|
@ -174,45 +211,17 @@ bool OpenGLHostDisplay::DownloadTexture(const void* texture_handle, HostDisplayP
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void OpenGLHostDisplay::BindDisplayPixelsTexture()
|
|
||||||
{
|
|
||||||
if (m_display_pixels_texture_id == 0)
|
|
||||||
{
|
|
||||||
glGenTextures(1, &m_display_pixels_texture_id);
|
|
||||||
glBindTexture(GL_TEXTURE_2D, m_display_pixels_texture_id);
|
|
||||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, m_display_linear_filtering ? GL_LINEAR : GL_NEAREST);
|
|
||||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, m_display_linear_filtering ? GL_LINEAR : GL_NEAREST);
|
|
||||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
|
|
||||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
|
|
||||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, 1);
|
|
||||||
m_display_texture_is_linear_filtered = m_display_linear_filtering;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
glBindTexture(GL_TEXTURE_2D, m_display_pixels_texture_id);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void OpenGLHostDisplay::UpdateDisplayPixelsTextureFilter()
|
|
||||||
{
|
|
||||||
if (m_display_linear_filtering == m_display_texture_is_linear_filtered)
|
|
||||||
return;
|
|
||||||
|
|
||||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, m_display_linear_filtering ? GL_LINEAR : GL_NEAREST);
|
|
||||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, m_display_linear_filtering ? GL_LINEAR : GL_NEAREST);
|
|
||||||
m_display_texture_is_linear_filtered = m_display_linear_filtering;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool OpenGLHostDisplay::SupportsDisplayPixelFormat(HostDisplayPixelFormat format) const
|
bool OpenGLHostDisplay::SupportsDisplayPixelFormat(HostDisplayPixelFormat format) const
|
||||||
{
|
{
|
||||||
const auto [gl_internal_format, gl_format, gl_type] = GetPixelFormatMapping(m_gl_context->IsGLES(), format);
|
const auto [gl_internal_format, gl_format, gl_type] = GetPixelFormatMapping(m_gl_context->IsGLES(), format);
|
||||||
return (gl_internal_format != static_cast<GLenum>(0));
|
return (gl_internal_format != static_cast<GLenum>(0));
|
||||||
}
|
}
|
||||||
|
|
||||||
bool OpenGLHostDisplay::BeginSetDisplayPixels(HostDisplayPixelFormat format, u32 width, u32 height, void** out_buffer,
|
bool OpenGLHostDisplay::MapTexture(HostDisplayTexture* texture, u32 x, u32 y, u32 width, u32 height, void** out_buffer,
|
||||||
u32* out_pitch)
|
u32* out_pitch)
|
||||||
{
|
{
|
||||||
const u32 pixel_size = GetDisplayPixelFormatSize(format);
|
OpenGLHostDisplayTexture* tex = static_cast<OpenGLHostDisplayTexture*>(texture);
|
||||||
|
const u32 pixel_size = GetDisplayPixelFormatSize(tex->GetFormat());
|
||||||
const u32 stride = Common::AlignUpPow2(width * pixel_size, 4);
|
const u32 stride = Common::AlignUpPow2(width * pixel_size, 4);
|
||||||
const u32 size_required = stride * height * pixel_size;
|
const u32 size_required = stride * height * pixel_size;
|
||||||
|
|
||||||
|
@ -227,10 +236,8 @@ bool OpenGLHostDisplay::BeginSetDisplayPixels(HostDisplayPixelFormat format, u32
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
const auto map = m_display_pixels_texture_pbo->Map(GetDisplayPixelFormatSize(format), size_required);
|
const auto map = m_display_pixels_texture_pbo->Map(GetDisplayPixelFormatSize(tex->GetFormat()), size_required);
|
||||||
m_display_texture_format = format;
|
tex->SetMapRect(x, y, width, height, map.buffer_offset, size_required);
|
||||||
m_display_pixels_texture_pbo_map_offset = map.buffer_offset;
|
|
||||||
m_display_pixels_texture_pbo_map_size = size_required;
|
|
||||||
*out_buffer = map.pointer;
|
*out_buffer = map.pointer;
|
||||||
*out_pitch = stride;
|
*out_pitch = stride;
|
||||||
}
|
}
|
||||||
|
@ -239,31 +246,37 @@ bool OpenGLHostDisplay::BeginSetDisplayPixels(HostDisplayPixelFormat format, u32
|
||||||
if (m_gles_pixels_repack_buffer.size() < size_required)
|
if (m_gles_pixels_repack_buffer.size() < size_required)
|
||||||
m_gles_pixels_repack_buffer.resize(size_required);
|
m_gles_pixels_repack_buffer.resize(size_required);
|
||||||
|
|
||||||
|
tex->SetMapRect(x, y, width, height, 0, size_required);
|
||||||
*out_buffer = m_gles_pixels_repack_buffer.data();
|
*out_buffer = m_gles_pixels_repack_buffer.data();
|
||||||
*out_pitch = stride;
|
*out_pitch = stride;
|
||||||
}
|
}
|
||||||
|
|
||||||
BindDisplayPixelsTexture();
|
|
||||||
SetDisplayTexture(reinterpret_cast<void*>(static_cast<uintptr_t>(m_display_pixels_texture_id)), format, width, height,
|
|
||||||
0, 0, width, height);
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void OpenGLHostDisplay::EndSetDisplayPixels()
|
void OpenGLHostDisplay::UnmapTexture(HostDisplayTexture* texture)
|
||||||
{
|
{
|
||||||
const u32 width = static_cast<u32>(m_display_texture_view_width);
|
OpenGLHostDisplayTexture* tex = static_cast<OpenGLHostDisplayTexture*>(texture);
|
||||||
const u32 height = static_cast<u32>(m_display_texture_view_height);
|
|
||||||
|
|
||||||
const auto [gl_internal_format, gl_format, gl_type] =
|
const auto [gl_internal_format, gl_format, gl_type] = GetPixelFormatMapping(m_gl_context->IsGLES(), tex->GetFormat());
|
||||||
GetPixelFormatMapping(m_gl_context->IsGLES(), m_display_texture_format);
|
|
||||||
|
|
||||||
glBindTexture(GL_TEXTURE_2D, m_display_pixels_texture_id);
|
glBindTexture(GL_TEXTURE_2D, tex->GetGLID());
|
||||||
if (m_use_pbo_for_pixels)
|
if (m_use_pbo_for_pixels)
|
||||||
{
|
{
|
||||||
m_display_pixels_texture_pbo->Unmap(m_display_pixels_texture_pbo_map_size);
|
m_display_pixels_texture_pbo->Unmap(m_display_pixels_texture_pbo_map_size);
|
||||||
m_display_pixels_texture_pbo->Bind();
|
m_display_pixels_texture_pbo->Bind();
|
||||||
glTexImage2D(GL_TEXTURE_2D, 0, gl_internal_format, width, height, 0, gl_format, gl_type,
|
if (tex->GetMapX() == 0 && tex->GetMapY() == 0 && tex->GetMapWidth() == tex->GetWidth() &&
|
||||||
reinterpret_cast<void*>(static_cast<uintptr_t>(m_display_pixels_texture_pbo_map_offset)));
|
tex->GetMapHeight() == tex->GetHeight())
|
||||||
|
{
|
||||||
|
glTexImage2D(GL_TEXTURE_2D, 0, gl_internal_format, tex->GetMapWidth(), tex->GetMapHeight(), 0, gl_format, gl_type,
|
||||||
|
reinterpret_cast<void*>(static_cast<uintptr_t>(m_display_pixels_texture_pbo_map_offset)));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
glTexSubImage2D(GL_TEXTURE_2D, 0, tex->GetMapX(), tex->GetMapY(), tex->GetMapWidth(), tex->GetMapHeight(),
|
||||||
|
gl_format, gl_type,
|
||||||
|
reinterpret_cast<void*>(static_cast<uintptr_t>(m_display_pixels_texture_pbo_map_offset)));
|
||||||
|
}
|
||||||
m_display_pixels_texture_pbo->Unbind();
|
m_display_pixels_texture_pbo->Unbind();
|
||||||
|
|
||||||
m_display_pixels_texture_pbo_map_offset = 0;
|
m_display_pixels_texture_pbo_map_offset = 0;
|
||||||
|
@ -272,52 +285,22 @@ void OpenGLHostDisplay::EndSetDisplayPixels()
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
// glTexImage2D should be quicker on Mali...
|
// glTexImage2D should be quicker on Mali...
|
||||||
glTexImage2D(GL_TEXTURE_2D, 0, gl_internal_format, width, height, 0, gl_format, gl_type,
|
if (tex->GetMapX() == 0 && tex->GetMapY() == 0 && tex->GetMapWidth() == tex->GetWidth() &&
|
||||||
m_gles_pixels_repack_buffer.data());
|
tex->GetMapHeight() == tex->GetHeight())
|
||||||
|
{
|
||||||
|
glTexImage2D(GL_TEXTURE_2D, 0, gl_internal_format, tex->GetMapWidth(), tex->GetMapHeight(), 0, gl_format, gl_type,
|
||||||
|
m_gles_pixels_repack_buffer.data());
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
glTexSubImage2D(GL_TEXTURE_2D, 0, tex->GetMapX(), tex->GetMapY(), tex->GetMapWidth(), tex->GetMapHeight(),
|
||||||
|
gl_format, gl_type, m_gles_pixels_repack_buffer.data());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
glBindTexture(GL_TEXTURE_2D, 0);
|
glBindTexture(GL_TEXTURE_2D, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool OpenGLHostDisplay::SetDisplayPixels(HostDisplayPixelFormat format, u32 width, u32 height, const void* buffer,
|
|
||||||
u32 pitch)
|
|
||||||
{
|
|
||||||
BindDisplayPixelsTexture();
|
|
||||||
|
|
||||||
const auto [gl_internal_format, gl_format, gl_type] = GetPixelFormatMapping(m_gl_context->IsGLES(), format);
|
|
||||||
const u32 pixel_size = GetDisplayPixelFormatSize(format);
|
|
||||||
const bool is_packed_tightly = (pitch == (pixel_size * width));
|
|
||||||
|
|
||||||
// If we have GLES3, we can set row_length.
|
|
||||||
if (!m_use_gles2_draw_path || is_packed_tightly)
|
|
||||||
{
|
|
||||||
if (!is_packed_tightly)
|
|
||||||
glPixelStorei(GL_UNPACK_ROW_LENGTH, pitch / pixel_size);
|
|
||||||
|
|
||||||
glTexImage2D(GL_TEXTURE_2D, 0, gl_internal_format, width, height, 0, gl_format, gl_type, buffer);
|
|
||||||
|
|
||||||
if (!is_packed_tightly)
|
|
||||||
glPixelStorei(GL_UNPACK_ROW_LENGTH, 0);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
// Otherwise, we need to repack the image.
|
|
||||||
const u32 packed_pitch = width * pixel_size;
|
|
||||||
const u32 repack_size = packed_pitch * height;
|
|
||||||
if (m_gles_pixels_repack_buffer.size() < repack_size)
|
|
||||||
m_gles_pixels_repack_buffer.resize(repack_size);
|
|
||||||
StringUtil::StrideMemCpy(m_gles_pixels_repack_buffer.data(), packed_pitch, buffer, pitch, packed_pitch, height);
|
|
||||||
glTexImage2D(GL_TEXTURE_2D, 0, gl_internal_format, width, height, 0, gl_format, gl_type,
|
|
||||||
m_gles_pixels_repack_buffer.data());
|
|
||||||
}
|
|
||||||
|
|
||||||
glBindTexture(GL_TEXTURE_2D, 0);
|
|
||||||
|
|
||||||
SetDisplayTexture(reinterpret_cast<void*>(static_cast<uintptr_t>(m_display_pixels_texture_id)), format, width, height,
|
|
||||||
0, 0, width, height);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
void OpenGLHostDisplay::SetVSync(bool enabled)
|
void OpenGLHostDisplay::SetVSync(bool enabled)
|
||||||
{
|
{
|
||||||
if (m_gl_context->GetWindowInfo().type == WindowInfo::Type::Surfaceless)
|
if (m_gl_context->GetWindowInfo().type == WindowInfo::Type::Surfaceless)
|
||||||
|
@ -520,8 +503,7 @@ HostDisplay::AdapterAndModeList OpenGLHostDisplay::GetAdapterAndModeList()
|
||||||
{
|
{
|
||||||
for (const GL::Context::FullscreenModeInfo& fmi : m_gl_context->EnumerateFullscreenModes())
|
for (const GL::Context::FullscreenModeInfo& fmi : m_gl_context->EnumerateFullscreenModes())
|
||||||
{
|
{
|
||||||
aml.fullscreen_modes.push_back(
|
aml.fullscreen_modes.push_back(GetFullscreenModeString(fmi.width, fmi.height, fmi.refresh_rate));
|
||||||
GetFullscreenModeString(fmi.width, fmi.height, fmi.refresh_rate));
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -712,12 +694,6 @@ void OpenGLHostDisplay::DestroyResources()
|
||||||
m_post_processing_ubo.reset();
|
m_post_processing_ubo.reset();
|
||||||
m_post_processing_stages.clear();
|
m_post_processing_stages.clear();
|
||||||
|
|
||||||
if (m_display_pixels_texture_id != 0)
|
|
||||||
{
|
|
||||||
glDeleteTextures(1, &m_display_pixels_texture_id);
|
|
||||||
m_display_pixels_texture_id = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (m_display_vao != 0)
|
if (m_display_vao != 0)
|
||||||
{
|
{
|
||||||
glDeleteVertexArrays(1, &m_display_vao);
|
glDeleteVertexArrays(1, &m_display_vao);
|
||||||
|
@ -886,9 +862,6 @@ void OpenGLHostDisplay::RenderDisplay(s32 left, s32 bottom, s32 width, s32 heigh
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
if (static_cast<GLuint>(reinterpret_cast<uintptr_t>(texture_handle)) == m_display_pixels_texture_id)
|
|
||||||
UpdateDisplayPixelsTextureFilter();
|
|
||||||
|
|
||||||
DrawFullscreenQuadES2(m_display_texture_view_x, m_display_texture_view_y, m_display_texture_view_width,
|
DrawFullscreenQuadES2(m_display_texture_view_x, m_display_texture_view_y, m_display_texture_view_width,
|
||||||
m_display_texture_view_height, m_display_texture_width, m_display_texture_height);
|
m_display_texture_view_height, m_display_texture_width, m_display_texture_height);
|
||||||
}
|
}
|
||||||
|
|
|
@ -50,11 +50,10 @@ public:
|
||||||
u32 texture_data_stride) override;
|
u32 texture_data_stride) override;
|
||||||
bool DownloadTexture(const void* texture_handle, HostDisplayPixelFormat texture_format, u32 x, u32 y, u32 width,
|
bool DownloadTexture(const void* texture_handle, HostDisplayPixelFormat texture_format, u32 x, u32 y, u32 width,
|
||||||
u32 height, void* out_data, u32 out_data_stride) override;
|
u32 height, void* out_data, u32 out_data_stride) override;
|
||||||
|
bool MapTexture(HostDisplayTexture* texture, u32 x, u32 y, u32 width, u32 height, void** out_buffer,
|
||||||
|
u32* out_pitch) override;
|
||||||
|
void UnmapTexture(HostDisplayTexture* texture) override;
|
||||||
bool SupportsDisplayPixelFormat(HostDisplayPixelFormat format) const override;
|
bool SupportsDisplayPixelFormat(HostDisplayPixelFormat format) const override;
|
||||||
bool BeginSetDisplayPixels(HostDisplayPixelFormat format, u32 width, u32 height, void** out_buffer,
|
|
||||||
u32* out_pitch) override;
|
|
||||||
void EndSetDisplayPixels() override;
|
|
||||||
bool SetDisplayPixels(HostDisplayPixelFormat format, u32 width, u32 height, const void* buffer, u32 pitch) override;
|
|
||||||
|
|
||||||
void SetVSync(bool enabled) override;
|
void SetVSync(bool enabled) override;
|
||||||
|
|
||||||
|
@ -73,9 +72,6 @@ protected:
|
||||||
void DestroyImGuiContext() override;
|
void DestroyImGuiContext() override;
|
||||||
bool UpdateImGuiFontTexture() override;
|
bool UpdateImGuiFontTexture() override;
|
||||||
|
|
||||||
void BindDisplayPixelsTexture();
|
|
||||||
void UpdateDisplayPixelsTextureFilter();
|
|
||||||
|
|
||||||
void RenderDisplay();
|
void RenderDisplay();
|
||||||
void RenderImGui();
|
void RenderImGui();
|
||||||
void RenderSoftwareCursor();
|
void RenderSoftwareCursor();
|
||||||
|
@ -107,7 +103,6 @@ protected:
|
||||||
GLuint m_display_linear_sampler = 0;
|
GLuint m_display_linear_sampler = 0;
|
||||||
GLuint m_uniform_buffer_alignment = 1;
|
GLuint m_uniform_buffer_alignment = 1;
|
||||||
|
|
||||||
GLuint m_display_pixels_texture_id = 0;
|
|
||||||
std::unique_ptr<GL::StreamBuffer> m_display_pixels_texture_pbo;
|
std::unique_ptr<GL::StreamBuffer> m_display_pixels_texture_pbo;
|
||||||
u32 m_display_pixels_texture_pbo_map_offset = 0;
|
u32 m_display_pixels_texture_pbo_map_offset = 0;
|
||||||
u32 m_display_pixels_texture_pbo_map_size = 0;
|
u32 m_display_pixels_texture_pbo_map_size = 0;
|
||||||
|
@ -118,7 +113,6 @@ protected:
|
||||||
std::unique_ptr<GL::StreamBuffer> m_post_processing_ubo;
|
std::unique_ptr<GL::StreamBuffer> m_post_processing_ubo;
|
||||||
std::vector<PostProcessingStage> m_post_processing_stages;
|
std::vector<PostProcessingStage> m_post_processing_stages;
|
||||||
|
|
||||||
bool m_display_texture_is_linear_filtered = false;
|
|
||||||
bool m_use_gles2_draw_path = false;
|
bool m_use_gles2_draw_path = false;
|
||||||
bool m_use_pbo_for_pixels = false;
|
bool m_use_pbo_for_pixels = false;
|
||||||
};
|
};
|
||||||
|
|
|
@ -271,8 +271,7 @@ bool VulkanHostDisplay::SupportsDisplayPixelFormat(HostDisplayPixelFormat format
|
||||||
return ((fp.optimalTilingFeatures & required) == required);
|
return ((fp.optimalTilingFeatures & required) == required);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool VulkanHostDisplay::BeginSetDisplayPixels(HostDisplayPixelFormat format, u32 width, u32 height, void** out_buffer,
|
bool VulkanHostDisplay::MapTexture(HostDisplayTexture* texture, u32 x, u32 y, u32 width, u32 height, void** out_buffer, u32* out_pitch)
|
||||||
u32* out_pitch)
|
|
||||||
{
|
{
|
||||||
const VkFormat vk_format = s_display_pixel_format_mapping[static_cast<u32>(format)];
|
const VkFormat vk_format = s_display_pixel_format_mapping[static_cast<u32>(format)];
|
||||||
|
|
||||||
|
|
|
@ -55,11 +55,11 @@ public:
|
||||||
u32 texture_data_stride) override;
|
u32 texture_data_stride) override;
|
||||||
bool DownloadTexture(const void* texture_handle, HostDisplayPixelFormat texture_format, u32 x, u32 y, u32 width,
|
bool DownloadTexture(const void* texture_handle, HostDisplayPixelFormat texture_format, u32 x, u32 y, u32 width,
|
||||||
u32 height, void* out_data, u32 out_data_stride) override;
|
u32 height, void* out_data, u32 out_data_stride) override;
|
||||||
|
bool MapTexture(HostDisplayTexture* texture, u32 x, u32 y, u32 width, u32 height, void** out_buffer,
|
||||||
|
u32* out_pitch) override;
|
||||||
|
void UnmapTexture(HostDisplayTexture* texture) override;
|
||||||
|
|
||||||
bool SupportsDisplayPixelFormat(HostDisplayPixelFormat format) const override;
|
bool SupportsDisplayPixelFormat(HostDisplayPixelFormat format) const override;
|
||||||
bool BeginSetDisplayPixels(HostDisplayPixelFormat format, u32 width, u32 height, void** out_buffer,
|
|
||||||
u32* out_pitch) override;
|
|
||||||
void EndSetDisplayPixels() override;
|
|
||||||
|
|
||||||
void SetVSync(bool enabled) override;
|
void SetVSync(bool enabled) override;
|
||||||
|
|
||||||
|
@ -125,7 +125,6 @@ protected:
|
||||||
VkSampler m_point_sampler = VK_NULL_HANDLE;
|
VkSampler m_point_sampler = VK_NULL_HANDLE;
|
||||||
VkSampler m_linear_sampler = VK_NULL_HANDLE;
|
VkSampler m_linear_sampler = VK_NULL_HANDLE;
|
||||||
|
|
||||||
Vulkan::Texture m_display_pixels_texture;
|
|
||||||
Vulkan::StagingTexture m_upload_staging_texture;
|
Vulkan::StagingTexture m_upload_staging_texture;
|
||||||
Vulkan::StagingTexture m_readback_staging_texture;
|
Vulkan::StagingTexture m_readback_staging_texture;
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue