Skip to content

Commit

Permalink
GPUDevice: Move software cursor to ImGuiManager
Browse files Browse the repository at this point in the history
  • Loading branch information
stenzek committed Aug 29, 2023
1 parent dd01c75 commit 259193a
Show file tree
Hide file tree
Showing 14 changed files with 201 additions and 185 deletions.
2 changes: 1 addition & 1 deletion src/core/controller.cpp
Expand Up @@ -69,7 +69,7 @@ std::optional<u32> Controller::GetAnalogInputBytes() const

void Controller::LoadSettings(SettingsInterface& si, const char* section) {}

bool Controller::GetSoftwareCursor(const Common::RGBA8Image** image, float* image_scale, bool* relative_mode)
bool Controller::GetSoftwareCursor(std::string* image_path, float* image_scale, bool* relative_mode)
{
return false;
}
Expand Down
2 changes: 1 addition & 1 deletion src/core/controller.h
Expand Up @@ -88,7 +88,7 @@ class Controller
virtual void LoadSettings(SettingsInterface& si, const char* section);

/// Returns the software cursor to use for this controller, if any.
virtual bool GetSoftwareCursor(const Common::RGBA8Image** image, float* image_scale, bool* relative_mode);
virtual bool GetSoftwareCursor(std::string* image_path, float* image_scale, bool* relative_mode);

/// Creates a new controller of the specified type.
static std::unique_ptr<Controller> Create(ControllerType type, u32 index);
Expand Down
30 changes: 10 additions & 20 deletions src/core/guncon.cpp
Expand Up @@ -4,22 +4,24 @@
#include "guncon.h"
#include "gpu.h"
#include "host.h"
#include "resources.h"
#include "system.h"

#include "util/gpu_device.h"
#include "util/state_wrapper.h"

#include "common/assert.h"
#include "common/log.h"
#include "common/path.h"

#include <array>

Log_SetChannel(GunCon);

static constexpr std::array<u8, static_cast<size_t>(GunCon::Button::Count)> s_button_indices = {{13, 3, 14}};

GunCon::GunCon(u32 index) : Controller(index) {}
GunCon::GunCon(u32 index) : Controller(index)
{
}

GunCon::~GunCon() = default;

Expand Down Expand Up @@ -248,35 +250,23 @@ void GunCon::LoadSettings(SettingsInterface& si, const char* section)
{
Controller::LoadSettings(si, section);

std::string path = si.GetStringValue(section, "CrosshairImagePath");
if (path != m_crosshair_image_path)
{
m_crosshair_image_path = std::move(path);
if (m_crosshair_image_path.empty() || !m_crosshair_image.LoadFromFile(m_crosshair_image_path.c_str()))
{
m_crosshair_image.Invalidate();
}
}

m_crosshair_image_path = si.GetStringValue(section, "CrosshairImagePath");
#ifndef __ANDROID__
if (!m_crosshair_image.IsValid())
{
m_crosshair_image.SetPixels(Resources::CROSSHAIR_IMAGE_WIDTH, Resources::CROSSHAIR_IMAGE_HEIGHT,
Resources::CROSSHAIR_IMAGE_DATA.data());
}
if (m_crosshair_image_path.empty())
m_crosshair_image_path = Path::Combine(EmuFolders::Resources, "images/crosshair.png");
#endif

m_crosshair_image_scale = si.GetFloatValue(section, "CrosshairScale", 1.0f);

m_x_scale = si.GetFloatValue(section, "XScale", 1.0f);
}

bool GunCon::GetSoftwareCursor(const Common::RGBA8Image** image, float* image_scale, bool* relative_mode)
bool GunCon::GetSoftwareCursor(std::string* image_path, float* image_scale, bool* relative_mode)
{
if (!m_crosshair_image.IsValid())
if (m_crosshair_image_path.empty())
return false;

*image = &m_crosshair_image;
*image_path = m_crosshair_image_path;
*image_scale = m_crosshair_image_scale;
*relative_mode = false;
return true;
Expand Down
3 changes: 1 addition & 2 deletions src/core/guncon.h
Expand Up @@ -32,7 +32,7 @@ class GunCon final : public Controller
bool DoState(StateWrapper& sw, bool apply_input_state) override;

void LoadSettings(SettingsInterface& si, const char* section) override;
bool GetSoftwareCursor(const Common::RGBA8Image** image, float* image_scale, bool* relative_mode) override;
bool GetSoftwareCursor(std::string* image_path, float* image_scale, bool* relative_mode) override;

float GetBindState(u32 index) const override;
void SetBindState(u32 index, float value) override;
Expand All @@ -56,7 +56,6 @@ class GunCon final : public Controller
YMSB
};

Common::RGBA8Image m_crosshair_image;
std::string m_crosshair_image_path;
float m_crosshair_image_scale = 1.0f;
float m_x_scale = 1.0f;
Expand Down
1 change: 1 addition & 0 deletions src/core/host.cpp
Expand Up @@ -349,6 +349,7 @@ void Host::RenderDisplay(bool skip_present)
FullscreenUI::Render();
ImGuiManager::RenderTextOverlays();
ImGuiManager::RenderOSDMessages();
ImGuiManager::RenderSoftwareCursors();
}

// Debug windows are always rendered, otherwise mouse input breaks on skip.
Expand Down
2 changes: 1 addition & 1 deletion src/core/playstation_mouse.cpp
Expand Up @@ -215,7 +215,7 @@ void PlayStationMouse::LoadSettings(SettingsInterface& si, const char* section)
m_use_relative_mode = si.GetBoolValue(section, "RelativeMouseMode", false);
}

bool PlayStationMouse::GetSoftwareCursor(const Common::RGBA8Image** image, float* image_scale, bool* relative_mode)
bool PlayStationMouse::GetSoftwareCursor(std::string* image_path, float* image_scale, bool* relative_mode)
{
*relative_mode = m_use_relative_mode;
return m_use_relative_mode;
Expand Down
2 changes: 1 addition & 1 deletion src/core/playstation_mouse.h
Expand Up @@ -36,7 +36,7 @@ class PlayStationMouse final : public Controller
bool Transfer(const u8 data_in, u8* data_out) override;

void LoadSettings(SettingsInterface& si, const char* section) override;
bool GetSoftwareCursor(const Common::RGBA8Image** image, float* image_scale, bool* relative_mode) override;
bool GetSoftwareCursor(std::string* image_path, float* image_scale, bool* relative_mode) override;

private:
void UpdatePosition();
Expand Down
17 changes: 6 additions & 11 deletions src/core/system.cpp
Expand Up @@ -4624,19 +4624,19 @@ void System::UpdateSoftwareCursor()
if (!IsValid())
{
Host::SetMouseMode(false, false);
g_gpu_device->ClearSoftwareCursor();
ImGuiManager::ClearSoftwareCursor(0);
return;
}

const Common::RGBA8Image* image = nullptr;
std::string image_path;
float image_scale = 1.0f;
bool relative_mode = false;
bool hide_cursor = false;

for (u32 i = 0; i < NUM_CONTROLLER_AND_CARD_PORTS; i++)
{
Controller* controller = System::GetController(i);
if (controller && controller->GetSoftwareCursor(&image, &image_scale, &relative_mode))
if (controller && controller->GetSoftwareCursor(&image_path, &image_scale, &relative_mode))
{
hide_cursor = true;
break;
Expand All @@ -4645,15 +4645,10 @@ void System::UpdateSoftwareCursor()

Host::SetMouseMode(relative_mode, hide_cursor);

if (image && image->IsValid())
{
g_gpu_device->SetSoftwareCursor(image->GetPixels(), image->GetWidth(), image->GetHeight(), image->GetPitch(),
image_scale);
}
if (!image_path.empty())
ImGuiManager::SetSoftwareCursor(0, std::move(image_path), image_scale);
else
{
g_gpu_device->ClearSoftwareCursor();
}
ImGuiManager::ClearSoftwareCursor(0);
}

void System::RequestDisplaySize(float scale /*= 0.0f*/)
Expand Down
112 changes: 2 additions & 110 deletions src/util/gpu_device.cpp
Expand Up @@ -20,7 +20,6 @@

#include "fmt/format.h"
#include "imgui.h"
#include "stb_image.h"
#include "stb_image_resize.h"
#include "stb_image_write.h"

Expand Down Expand Up @@ -432,26 +431,17 @@ bool GPUDevice::CreateResources()
std::unique_ptr<GPUShader> display_vs = CreateShader(GPUShaderStage::Vertex, shadergen.GenerateDisplayVertexShader());
std::unique_ptr<GPUShader> display_fs =
CreateShader(GPUShaderStage::Fragment, shadergen.GenerateDisplayFragmentShader(true));
std::unique_ptr<GPUShader> cursor_fs =
CreateShader(GPUShaderStage::Fragment, shadergen.GenerateDisplayFragmentShader(false));
if (!display_vs || !display_fs || !cursor_fs)
if (!display_vs || !display_fs)
return false;
GL_OBJECT_NAME(display_vs, "Display Vertex Shader");
GL_OBJECT_NAME(display_fs, "Display Fragment Shader");
GL_OBJECT_NAME(cursor_fs, "Cursor Fragment Shader");

plconfig.vertex_shader = display_vs.get();
plconfig.fragment_shader = display_fs.get();
if (!(m_display_pipeline = CreatePipeline(plconfig)))
return false;
GL_OBJECT_NAME(m_display_pipeline, "Display Pipeline");

plconfig.blend = GPUPipeline::BlendState::GetAlphaBlendingState();
plconfig.fragment_shader = cursor_fs.get();
if (!(m_cursor_pipeline = CreatePipeline(plconfig)))
return false;
GL_OBJECT_NAME(m_cursor_pipeline, "Cursor Pipeline");

std::unique_ptr<GPUShader> imgui_vs = CreateShader(GPUShaderStage::Vertex, shadergen.GenerateImGuiVertexShader());
std::unique_ptr<GPUShader> imgui_fs = CreateShader(GPUShaderStage::Fragment, shadergen.GenerateImGuiFragmentShader());
if (!imgui_vs || !imgui_fs)
Expand All @@ -472,6 +462,7 @@ bool GPUDevice::CreateResources()
plconfig.input_layout.vertex_stride = sizeof(ImDrawVert);
plconfig.vertex_shader = imgui_vs.get();
plconfig.fragment_shader = imgui_fs.get();
plconfig.blend = GPUPipeline::BlendState::GetAlphaBlendingState();

m_imgui_pipeline = CreatePipeline(plconfig);
if (!m_imgui_pipeline)
Expand All @@ -486,12 +477,9 @@ bool GPUDevice::CreateResources()

void GPUDevice::DestroyResources()
{
m_cursor_texture.reset();

m_imgui_font_texture.reset();
m_imgui_pipeline.reset();

m_cursor_pipeline.reset();
m_display_pipeline.reset();
m_imgui_pipeline.reset();

Expand Down Expand Up @@ -862,61 +850,6 @@ float GPUDevice::GetAndResetAccumulatedGPUTime()
return 0.0f;
}

void GPUDevice::SetSoftwareCursor(std::unique_ptr<GPUTexture> texture, float scale /*= 1.0f*/)
{
if (texture)
texture->MakeReadyForSampling();

m_cursor_texture = std::move(texture);
m_cursor_texture_scale = scale;
}

bool GPUDevice::SetSoftwareCursor(const void* pixels, u32 width, u32 height, u32 stride, float scale /*= 1.0f*/)
{
std::unique_ptr<GPUTexture> tex =
CreateTexture(width, height, 1, 1, 1, GPUTexture::Type::Texture, GPUTexture::Format::RGBA8, pixels, stride, false);
if (!tex)
return false;

SetSoftwareCursor(std::move(tex), scale);
return true;
}

bool GPUDevice::SetSoftwareCursor(const char* path, float scale /*= 1.0f*/)
{
auto fp = FileSystem::OpenManagedCFile(path, "rb");
if (!fp)
{
return false;
}

int width, height, file_channels;
u8* pixel_data = stbi_load_from_file(fp.get(), &width, &height, &file_channels, 4);
if (!pixel_data)
{
const char* error_reason = stbi_failure_reason();
Log_ErrorPrintf("Failed to load image from '%s': %s", path, error_reason ? error_reason : "unknown error");
return false;
}

std::unique_ptr<GPUTexture> tex =
CreateTexture(static_cast<u32>(width), static_cast<u32>(height), 1, 1, 1, GPUTexture::Type::Texture,
GPUTexture::Format::RGBA8, pixel_data, sizeof(u32) * static_cast<u32>(width), false);
stbi_image_free(pixel_data);
if (!tex)
return false;

Log_InfoPrintf("Loaded %dx%d image from '%s' for software cursor", width, height, path);
SetSoftwareCursor(std::move(tex), scale);
return true;
}

void GPUDevice::ClearSoftwareCursor()
{
m_cursor_texture.reset();
m_cursor_texture_scale = 1.0f;
}

bool GPUDevice::IsUsingLinearFiltering() const
{
return g_settings.display_linear_filtering;
Expand Down Expand Up @@ -962,7 +895,6 @@ bool GPUDevice::Render(bool skip_present)
SetViewportAndScissor(0, 0, GetWindowWidth(), GetWindowHeight());

RenderImGui();
RenderSoftwareCursor();

EndPresent();
return true;
Expand Down Expand Up @@ -1054,27 +986,6 @@ bool GPUDevice::RenderDisplay(GPUFramebuffer* target, s32 left, s32 top, s32 wid
}
}

void GPUDevice::RenderSoftwareCursor()
{
if (!HasSoftwareCursor())
return;

const auto [left, top, width, height] = CalculateSoftwareCursorDrawRect();
RenderSoftwareCursor(left, top, width, height, m_cursor_texture.get());
}

void GPUDevice::RenderSoftwareCursor(s32 left, s32 top, s32 width, s32 height, GPUTexture* texture)
{
SetPipeline(m_display_pipeline.get());
SetTextureSampler(0, texture, m_linear_sampler.get());

const float uniforms[4] = {0.0f, 0.0f, 1.0f, 1.0f};
PushUniformBuffer(uniforms, sizeof(uniforms));

SetViewportAndScissor(left, top, width, height);
Draw(3, 0);
}

void GPUDevice::CalculateDrawRect(s32 window_width, s32 window_height, float* out_left, float* out_top,
float* out_width, float* out_height, float* out_left_padding, float* out_top_padding,
float* out_scale, float* out_x_scale, bool apply_aspect_ratio /* = true */) const
Expand Down Expand Up @@ -1193,25 +1104,6 @@ std::tuple<s32, s32, s32, s32> GPUDevice::CalculateDrawRect(s32 window_width, s3
static_cast<s32>(width), static_cast<s32>(height));
}

std::tuple<s32, s32, s32, s32> GPUDevice::CalculateSoftwareCursorDrawRect() const
{
return CalculateSoftwareCursorDrawRect(m_mouse_position_x, m_mouse_position_y);
}

std::tuple<s32, s32, s32, s32> GPUDevice::CalculateSoftwareCursorDrawRect(s32 cursor_x, s32 cursor_y) const
{
const float scale = m_window_info.surface_scale * m_cursor_texture_scale;
const u32 cursor_extents_x = static_cast<u32>(static_cast<float>(m_cursor_texture->GetWidth()) * scale * 0.5f);
const u32 cursor_extents_y = static_cast<u32>(static_cast<float>(m_cursor_texture->GetHeight()) * scale * 0.5f);

const s32 out_left = cursor_x - cursor_extents_x;
const s32 out_top = cursor_y - cursor_extents_y;
const s32 out_width = cursor_extents_x * 2u;
const s32 out_height = cursor_extents_y * 2u;

return std::tie(out_left, out_top, out_width, out_height);
}

std::tuple<float, float> GPUDevice::ConvertWindowCoordinatesToDisplayCoordinates(s32 window_x, s32 window_y,
s32 window_width,
s32 window_height) const
Expand Down

0 comments on commit 259193a

Please sign in to comment.