From afa9d606a36a0148be99887b91397d6f7c73ab75 Mon Sep 17 00:00:00 2001 From: Jesse Talavera-Greenberg Date: Sat, 23 Sep 2023 16:53:18 -0400 Subject: [PATCH] Use the Scaler object --- src/libretro/platform/platform.cpp | 33 +++++++++--------------------- src/libretro/retro/scaler.cpp | 16 +++++++++++++++ src/libretro/retro/scaler.hpp | 2 ++ src/libretro/screenlayout.cpp | 22 +++++++++----------- src/libretro/screenlayout.hpp | 3 ++- 5 files changed, 40 insertions(+), 36 deletions(-) diff --git a/src/libretro/platform/platform.cpp b/src/libretro/platform/platform.cpp index 532c26e8..4318036c 100644 --- a/src/libretro/platform/platform.cpp +++ b/src/libretro/platform/platform.cpp @@ -16,6 +16,8 @@ #include #include +#include +#include #include #include @@ -28,12 +30,13 @@ #include "../memory.hpp" #include "../environment.hpp" #include "../config.hpp" +#include "retro/scaler.hpp" #include "sram.hpp" constexpr unsigned DSI_CAMERA_WIDTH = 640; constexpr unsigned DSI_CAMERA_HEIGHT = 480; static struct retro_camera_callback _camera{}; -static struct scaler_ctx _scaler{}; +static std::unique_ptr scaler{}; // YUV422 framebuffer, two pixels per 32-bit int (see DSi_Camera.h) static std::array _camera_buffer{}; @@ -100,25 +103,13 @@ static void conv_argb8888_yuyv(void *output_, const void *input_, static void CaptureImage(const uint32_t *buffer, unsigned width, unsigned height, size_t pitch) noexcept { - if (_scaler.in_width != static_cast(width) || _scaler.in_height != static_cast(height) || - _scaler.in_stride != static_cast(pitch)) { - // If the camera's dimensions changed behind our back (or haven't been initialized)... - _scaler.in_width = width; - _scaler.in_height = height; - _scaler.in_stride = pitch; - _scaler.out_width = DSI_CAMERA_WIDTH; - _scaler.out_height = DSI_CAMERA_HEIGHT; - _scaler.out_stride = DSI_CAMERA_WIDTH * sizeof(uint32_t) / 2; - _scaler.direct_pixconv = conv_argb8888_yuyv; - _scaler.in_pixconv = nullptr; - _scaler.out_pixconv = conv_argb8888_yuyv; - - if (!scaler_ctx_gen_filter(&_scaler)) { - retro::warn("Failed to initialize camera scaler."); - } + if (!scaler || scaler->InWidth() != width || scaler->InHeight() != height || scaler->InStride() != pitch) { + // If the scaler hasn't been initialized, or if the camera's dimensions changed behind our back... + + scaler = std::make_unique(SCALER_FMT_ARGB8888, SCALER_FMT_RGBA4444, SCALER_TYPE_BILINEAR, width, height, DSI_CAMERA_WIDTH, DSI_CAMERA_HEIGHT); } - scaler_ctx_scale(&_scaler, _camera_buffer.data(), buffer); + scaler->Scale(_camera_buffer.data(), buffer); } void Platform::Init(int, char **) { @@ -136,10 +127,6 @@ void Platform::Init(int, char **) { _camera.width = DSI_CAMERA_WIDTH; _camera.height = DSI_CAMERA_HEIGHT; - _scaler.in_fmt = SCALER_FMT_ARGB8888; - _scaler.out_fmt = SCALER_FMT_YUYV; - _scaler.scaler_type = SCALER_TYPE_BILINEAR; // TODO: Make configurable - if (!retro::environment(RETRO_ENVIRONMENT_GET_CAMERA_INTERFACE, &_camera)) { retro::warn("Camera interface not available."); } else { @@ -157,7 +144,7 @@ void Platform::DeInit() { _camera.start = nullptr; _camera.stop = nullptr; - scaler_ctx_gen_reset(&_scaler); + scaler.reset(); } void Platform::SignalStop(Platform::StopReason reason) { diff --git a/src/libretro/retro/scaler.cpp b/src/libretro/retro/scaler.cpp index 1846da8c..df95d3b4 100644 --- a/src/libretro/retro/scaler.cpp +++ b/src/libretro/retro/scaler.cpp @@ -17,6 +17,7 @@ #include "scaler.hpp" #include +#include constexpr unsigned PixelSize(scaler_pix_fmt fmt) noexcept { switch (fmt) { @@ -56,6 +57,10 @@ const char* PixelFormatName(scaler_pix_fmt fmt) noexcept { } } +retro::Scaler::Scaler() noexcept { + +} + retro::Scaler::Scaler( scaler_pix_fmt in_fmt, scaler_pix_fmt out_fmt, @@ -94,6 +99,17 @@ retro::Scaler::Scaler( } } +retro::Scaler::Scaler(scaler_ctx&& ctx) noexcept { + scaler = ctx; + ctx = {}; + + retro_assert(ctx.input.frame == nullptr); + retro_assert(ctx.scaled.frame == nullptr); + retro_assert(ctx.output.frame == nullptr); + retro_assert(ctx.in_pixconv == nullptr); + retro_assert(ctx.out_pixconv == nullptr); +} + retro::Scaler::~Scaler() noexcept { scaler_ctx_gen_reset(&scaler); } diff --git a/src/libretro/retro/scaler.hpp b/src/libretro/retro/scaler.hpp index dc5c6763..3801ced5 100644 --- a/src/libretro/retro/scaler.hpp +++ b/src/libretro/retro/scaler.hpp @@ -22,7 +22,9 @@ namespace retro { class Scaler { public: + Scaler() noexcept; Scaler(scaler_pix_fmt in_fmt, scaler_pix_fmt out_fmt, scaler_type type, unsigned in_width, unsigned in_height, unsigned out_width, unsigned out_height); + Scaler(scaler_ctx&& ctx) noexcept; ~Scaler() noexcept; Scaler(const Scaler&) = delete; Scaler(Scaler&&) noexcept; diff --git a/src/libretro/screenlayout.cpp b/src/libretro/screenlayout.cpp index 228b3815..45e0080b 100644 --- a/src/libretro/screenlayout.cpp +++ b/src/libretro/screenlayout.cpp @@ -54,7 +54,6 @@ melonds::ScreenLayoutData::ScreenLayoutData() : } melonds::ScreenLayoutData::~ScreenLayoutData() noexcept { - scaler_ctx_gen_reset(&hybridScaler); } void melonds::ScreenLayoutData::CopyScreen(const uint32_t* src, glm::uvec2 destTranslation) noexcept { @@ -120,7 +119,7 @@ void melonds::ScreenLayoutData::CombineScreens(const uint32_t* topBuffer, const retro_assert(hybridBuffer); const uint32_t* primaryBuffer = layout == ScreenLayout::HybridTop ? topBuffer : bottomBuffer; - scaler_ctx_scale(&hybridScaler, hybridBuffer.Buffer(), primaryBuffer); + hybridScaler.Scale(hybridBuffer.Buffer(), primaryBuffer); buffer.CopyRows(hybridBuffer.Buffer(), hybridScreenTranslation, NDS_SCREEN_SIZE * hybridRatio); HybridSideScreenDisplay smallScreenLayout = HybridSmallScreenLayout(); @@ -323,16 +322,15 @@ void melonds::ScreenLayoutData::Update(melonds::Renderer renderer) noexcept { // TODO: Don't recreate this buffer if the hybrid ratio didn't change // TODO: Maintain a separate _hybridDirty flag hybridBuffer = PixelBuffer(NDS_SCREEN_SIZE * hybridRatio); - hybridScaler.in_width = NDS_SCREEN_WIDTH; - hybridScaler.in_height = NDS_SCREEN_HEIGHT; - hybridScaler.in_stride = NDS_SCREEN_WIDTH * sizeof(uint32_t); - hybridScaler.out_width = NDS_SCREEN_WIDTH * hybridRatio; - hybridScaler.out_height = NDS_SCREEN_HEIGHT * hybridRatio; - hybridScaler.out_stride = NDS_SCREEN_WIDTH * hybridRatio * sizeof(uint32_t); - hybridScaler.in_fmt = SCALER_FMT_ARGB8888; - hybridScaler.out_fmt = SCALER_FMT_ARGB8888; - hybridScaler.scaler_type = config::video::ScreenFilter() == ScreenFilter::Nearest ? SCALER_TYPE_POINT : SCALER_TYPE_BILINEAR; - scaler_ctx_gen_filter(&hybridScaler); + hybridScaler = retro::Scaler( + SCALER_FMT_ARGB8888, + SCALER_FMT_ARGB8888, + config::video::ScreenFilter() == ScreenFilter::Nearest ? SCALER_TYPE_POINT : SCALER_TYPE_BILINEAR, + NDS_SCREEN_WIDTH, + NDS_SCREEN_HEIGHT, + NDS_SCREEN_WIDTH * hybridRatio, + NDS_SCREEN_HEIGHT * hybridRatio + ); } else { hybridBuffer = nullptr; } diff --git a/src/libretro/screenlayout.hpp b/src/libretro/screenlayout.hpp index 241e59b2..5ec3c407 100644 --- a/src/libretro/screenlayout.hpp +++ b/src/libretro/screenlayout.hpp @@ -33,6 +33,7 @@ #include "environment.hpp" #include "input.hpp" #include "buffer.hpp" +#include "retro/scaler.hpp" namespace melonds { /// The native width of a single Nintendo DS screen, in pixels @@ -228,7 +229,7 @@ namespace melonds { // Used as a staging area for the hybrid screen to be scaled PixelBuffer hybridBuffer; - struct scaler_ctx hybridScaler; + retro::Scaler hybridScaler; }; constexpr bool LayoutSupportsScreenGap(ScreenLayout layout) noexcept {