HostDisplay: Add an interface for setting software cursor

This commit is contained in:
Connor McLaughlin 2020-06-08 02:53:37 +10:00
parent 56c50c6eeb
commit f98bb033ff
2 changed files with 79 additions and 0 deletions

View file

@ -1,6 +1,7 @@
#include "host_display.h"
#include "common/log.h"
#include "common/string_util.h"
#include "stb_image.h"
#include "stb_image_resize.h"
#include "stb_image_write.h"
#include <cmath>
@ -18,6 +19,50 @@ void HostDisplay::WindowResized(s32 new_window_width, s32 new_window_height)
m_window_height = new_window_height;
}
void HostDisplay::SetSoftwareCursor(std::unique_ptr<HostDisplayTexture> texture, float scale /*= 1.0f*/)
{
m_cursor_texture = std::move(texture);
m_cursor_texture_scale = scale;
}
bool HostDisplay::SetSoftwareCursor(const void* pixels, u32 width, u32 height, u32 stride, float scale /*= 1.0f*/)
{
std::unique_ptr<HostDisplayTexture> tex = CreateTexture(width, height, pixels, stride, false);
if (!tex)
return false;
SetSoftwareCursor(std::move(tex), scale);
return true;
}
bool HostDisplay::SetSoftwareCursor(const char* path, float scale /*= 1.0f*/)
{
int width, height, file_channels;
u8* pixel_data = stbi_load(path, &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<HostDisplayTexture> tex = CreateTexture(static_cast<u32>(width), static_cast<u32>(height), 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 HostDisplay::ClearSoftwareCursor()
{
m_cursor_texture.reset();
m_cursor_texture_scale = 1.0f;
}
void HostDisplay::CalculateDrawRect(s32 window_width, s32 window_height, s32* out_left, s32* out_top, s32* out_width,
s32* out_height, s32* out_left_padding, s32* out_top_padding, float* out_scale,
float* out_y_scale) const
@ -88,6 +133,21 @@ std::tuple<s32, s32, s32, s32> HostDisplay::CalculateDrawRect(s32 window_width,
return std::make_tuple(left + left_padding, top + top_padding + top_margin, width, height);
}
std::tuple<s32, s32, s32, s32> HostDisplay::CalculateSoftwareCursorDrawRect() const
{
const u32 cursor_extents_x =
static_cast<u32>(static_cast<float>(m_cursor_texture->GetWidth()) * m_cursor_texture_scale * 0.5f);
const u32 cursor_extents_y =
static_cast<u32>(static_cast<float>(m_cursor_texture->GetHeight()) * m_cursor_texture_scale * 0.5f);
const s32 out_left = m_mouse_position_x - cursor_extents_x;
const s32 out_top = m_mouse_position_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<s32, s32> HostDisplay::ConvertWindowCoordinatesToDisplayCoordinates(s32 window_x, s32 window_y,
s32 window_width, s32 window_height,
s32 top_margin) const

View file

@ -106,6 +106,18 @@ public:
void SetDisplayTopMargin(s32 height) { m_display_top_margin = height; }
void SetDisplayIntegerScaling(bool enabled) { m_display_integer_scaling = enabled; }
/// Sets the software cursor to the specified texture. Ownership of the texture is transferred.
void SetSoftwareCursor(std::unique_ptr<HostDisplayTexture> texture, float scale = 1.0f);
/// Sets the software cursor to the specified image.
bool SetSoftwareCursor(const void* pixels, u32 width, u32 height, u32 stride, float scale = 1.0f);
/// Sets the software cursor to the specified path (png image).
bool SetSoftwareCursor(const char* path, float scale = 1.0f);
/// Disables the software cursor.
void ClearSoftwareCursor();
/// Helper function for computing the draw rectangle in a larger window.
std::tuple<s32, s32, s32, s32> CalculateDrawRect(s32 window_width, s32 window_height, s32 top_margin) const;
@ -125,10 +137,14 @@ public:
bool clear_alpha = true);
protected:
ALWAYS_INLINE bool HasSoftwareCursor() const { return static_cast<bool>(m_cursor_texture); }
void CalculateDrawRect(s32 window_width, s32 window_height, s32* out_left, s32* out_top, s32* out_width,
s32* out_height, s32* out_left_padding, s32* out_top_padding, float* out_scale,
float* out_y_scale) const;
std::tuple<s32, s32, s32, s32> CalculateSoftwareCursorDrawRect() const;
s32 m_window_width = 0;
s32 m_window_height = 0;
@ -153,6 +169,9 @@ protected:
s32 m_display_top_margin = 0;
std::unique_ptr<HostDisplayTexture> m_cursor_texture;
float m_cursor_texture_scale = 1.0f;
bool m_display_linear_filtering = false;
bool m_display_changed = false;
bool m_display_integer_scaling = false;