mirror of
https://github.com/RPCS3/rpcs3.git
synced 2026-10-12 02:09:17 +00:00
rsx/lv2: Implement hardware bitmap cursor
This commit is contained in:
@@ -9,6 +9,8 @@
|
||||
#include "Emu/Memory/vm_locking.h"
|
||||
#include "Emu/RSX/Core/RSXEngLock.hpp"
|
||||
#include "Emu/RSX/Core/RSXReservationLock.hpp"
|
||||
#include "Emu/RSX/Overlays/overlay_cursor.h"
|
||||
#include "Emu/RSX/Overlays/overlay_manager.h"
|
||||
#include "Emu/RSX/RSXThread.h"
|
||||
#include "util/asm.hpp"
|
||||
#include "sys_event.h"
|
||||
@@ -36,6 +38,62 @@ void fmt_class_string<sys_rsx_error>::format(std::string& out, u64 arg)
|
||||
});
|
||||
}
|
||||
|
||||
// ---- Hardware cursor ----
|
||||
// The hardware cursor is part of the display circuitry. It is not rendered directly by PGRAPH or any of the other 2D objects.
|
||||
// Emulation is implemented using the overlay system. It has a fixed 64x64 bitmap size.
|
||||
|
||||
rsx::overlays::bitmap_cursor* _sys_rsx_get_cursor()
|
||||
{
|
||||
if (auto manager = g_fxo->try_get<rsx::overlays::display_manager>())
|
||||
{
|
||||
return manager->get<rsx::overlays::bitmap_cursor>().get();
|
||||
}
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
void _sys_rsx_init_cursor_overlay()
|
||||
{
|
||||
if (auto manager = g_fxo->try_get<rsx::overlays::display_manager>())
|
||||
{
|
||||
manager->create<rsx::overlays::bitmap_cursor>();
|
||||
}
|
||||
}
|
||||
|
||||
void _sys_rsx_enable_cursor_overlay()
|
||||
{
|
||||
if (auto cursor = _sys_rsx_get_cursor())
|
||||
{
|
||||
cursor->enable();
|
||||
}
|
||||
}
|
||||
|
||||
void _sys_rsx_disable_cursor_overlay()
|
||||
{
|
||||
if (auto cursor = _sys_rsx_get_cursor())
|
||||
{
|
||||
cursor->disable();
|
||||
}
|
||||
}
|
||||
|
||||
void _sys_rsx_move_cursor_overlay(s32 x, s32 y)
|
||||
{
|
||||
if (auto cursor = _sys_rsx_get_cursor())
|
||||
{
|
||||
cursor->set_pos(x, y);
|
||||
}
|
||||
}
|
||||
|
||||
void _sys_rsx_update_cursor_image(u32 cursor_offset)
|
||||
{
|
||||
if (auto cursor = _sys_rsx_get_cursor())
|
||||
{
|
||||
cursor->set_bitmap(cursor_offset);
|
||||
}
|
||||
}
|
||||
|
||||
// ---- Util ----
|
||||
|
||||
static u64 rsx_timeStamp()
|
||||
{
|
||||
return get_timebased_time();
|
||||
@@ -142,6 +200,8 @@ bool rsx::thread::send_event(u64 data1, u64 event_flags, u64 data3)
|
||||
return true;
|
||||
}
|
||||
|
||||
// ---- Event Queue ----
|
||||
|
||||
void _sys_rsx_drain_event_queue(rsx::thread* rsxthr, u64 event_flags = umax, u64 wait_timeout_ms = 1000ull)
|
||||
{
|
||||
const auto& driverInfo = *vm::_ptr<RsxDriverInfo>(rsxthr->driver_info);
|
||||
@@ -204,6 +264,8 @@ void _sys_rsx_drain_event_queue(rsx::thread* rsxthr, u64 event_flags = umax, u64
|
||||
}
|
||||
}
|
||||
|
||||
// ---- LV2 ----
|
||||
|
||||
error_code sys_rsx_device_open(cpu_thread& cpu)
|
||||
{
|
||||
cpu.state += cpu_flag::wait;
|
||||
@@ -780,11 +842,27 @@ error_code sys_rsx_context_attribute(u32 context_id, u32 package_id, u64 a3, u64
|
||||
case 0x10b:
|
||||
// when a4=3, cellGcmSetCursorPosition(a5=xpos, a6=ypos)
|
||||
// when a4=2, cellGcmSetCursorImageOffset(a5=offset)
|
||||
if (a4 == 3)
|
||||
_sys_rsx_move_cursor_overlay(static_cast<s32>(a5), static_cast<s32>(a6));
|
||||
else if (a4 == 2)
|
||||
_sys_rsx_update_cursor_image(static_cast<u32>(a5));
|
||||
else
|
||||
sys_rsx.error("Unknown subfunction 0x%llx (package=0x10b)", a4);
|
||||
break;
|
||||
case 0x10c:
|
||||
// when a4=1, cellGcmSetCursorEnable()
|
||||
// when a4=2, cellGcmSetCursorDisable()
|
||||
if (a4 == 1)
|
||||
_sys_rsx_enable_cursor_overlay();
|
||||
else if (a4 == 2)
|
||||
_sys_rsx_disable_cursor_overlay();
|
||||
else
|
||||
sys_rsx.error("Unknown subfunction 0x%llx (package=0x10c)", a4);
|
||||
break;
|
||||
case 0x10d:
|
||||
// cellGcmInitCursor(a3=1, a4=1, a5=0, a6=0)
|
||||
ensure(a4 == 1);
|
||||
_sys_rsx_init_cursor_overlay();
|
||||
break;
|
||||
|
||||
case 0x300: // Tiles
|
||||
|
||||
@@ -72,6 +72,26 @@ namespace rsx
|
||||
static std::unique_ptr<image_info> load_icon(const std::string& icon_path, const std::string& archive_path);
|
||||
};
|
||||
|
||||
struct memory_image_info : public image_info_base
|
||||
{
|
||||
public:
|
||||
memory_image_info() = default;
|
||||
|
||||
memory_image_info(u16 w, u16 h, u8 bpp, const u8* data)
|
||||
{
|
||||
this->w = w;
|
||||
this->h = h;
|
||||
this->bpp = bpp;
|
||||
this->m_data_ptr = data;
|
||||
}
|
||||
|
||||
const u8* get_data() const override { return m_data_ptr; }
|
||||
usz size_bytes() const override { return static_cast<usz>(w * h * bpp); }
|
||||
|
||||
private:
|
||||
const u8* m_data_ptr = nullptr;
|
||||
};
|
||||
|
||||
struct resource_config
|
||||
{
|
||||
enum standard_image_resource : u8
|
||||
|
||||
@@ -2,9 +2,13 @@
|
||||
#include "overlay_cursor.h"
|
||||
#include "overlay_manager.h"
|
||||
#include "Emu/Cell/timers.hpp"
|
||||
#include "Emu/Memory/vm.h"
|
||||
#include "Emu/RSX/gcm_enums.h"
|
||||
|
||||
namespace rsx
|
||||
{
|
||||
extern u32 get_address(u32 offset, u32 location, u32 size_to_check = 0, std::source_location src_loc = std::source_location::current());
|
||||
|
||||
namespace overlays
|
||||
{
|
||||
cursor_item::cursor_item()
|
||||
@@ -151,5 +155,56 @@ namespace rsx
|
||||
}
|
||||
}
|
||||
|
||||
void bitmap_cursor::enable()
|
||||
{
|
||||
m_visible = true;
|
||||
}
|
||||
|
||||
void bitmap_cursor::disable()
|
||||
{
|
||||
m_visible = false;
|
||||
}
|
||||
|
||||
void bitmap_cursor::set_pos(s32 x, s32 y)
|
||||
{
|
||||
std::lock_guard lock(m_mutex);
|
||||
|
||||
m_position.x = ::narrow<s16>(x);
|
||||
m_position.y = ::narrow<s16>(y);
|
||||
|
||||
if (m_bitmap)
|
||||
{
|
||||
m_bitmap->set_pos(m_position.x, m_position.y);
|
||||
}
|
||||
}
|
||||
|
||||
void bitmap_cursor::set_bitmap(u32 address)
|
||||
{
|
||||
std::lock_guard lock(m_mutex);
|
||||
|
||||
if (!m_bitmap)
|
||||
{
|
||||
m_bitmap = std::make_unique<image_view>();
|
||||
m_bitmap->set_size(64, 64);
|
||||
m_bitmap->set_pos(m_position.x, m_position.y);
|
||||
}
|
||||
|
||||
auto vm_address = rsx::get_address(address, CELL_GCM_CONTEXT_DMA_MEMORY_FRAME_BUFFER);
|
||||
auto data = vm::get_super_ptr<const u8>(vm_address);
|
||||
m_image_storage = { 64, 64, 4, data };
|
||||
m_bitmap->set_raw_image(&m_image_storage);
|
||||
}
|
||||
|
||||
compiled_resource bitmap_cursor::get_compiled()
|
||||
{
|
||||
std::lock_guard lock(m_mutex);
|
||||
|
||||
if (!m_visible || !m_bitmap)
|
||||
{
|
||||
return {};
|
||||
}
|
||||
|
||||
return m_bitmap->get_compiled();
|
||||
}
|
||||
} // namespace overlays
|
||||
} // namespace rsx
|
||||
|
||||
@@ -50,6 +50,24 @@ namespace rsx
|
||||
std::map<u32, cursor_item> m_cursors;
|
||||
};
|
||||
|
||||
class bitmap_cursor final : public overlay
|
||||
{
|
||||
public:
|
||||
void enable();
|
||||
void disable();
|
||||
void set_pos(s32 x, s32 y);
|
||||
void set_bitmap(u32 address);
|
||||
compiled_resource get_compiled() override;
|
||||
|
||||
private:
|
||||
bool m_visible = false;
|
||||
position2_base<s16> m_position = {};
|
||||
std::unique_ptr<overlays::image_view> m_bitmap;
|
||||
overlays::memory_image_info m_image_storage;
|
||||
|
||||
shared_mutex m_mutex;
|
||||
};
|
||||
|
||||
void set_cursor(u32 id, s16 x, s16 y, const color4f& color, u64 duration_us, bool force_update);
|
||||
|
||||
} // namespace overlays
|
||||
|
||||
Reference in New Issue
Block a user