mirror of
https://github.com/RPCS3/rpcs3.git
synced 2025-07-10 08:51:28 +12:00
VK/GL: honor game's aspect ratio when scaling
This commit is contained in:
parent
f16949c292
commit
c8d4a0dcdc
7 changed files with 132 additions and 72 deletions
|
@ -10,6 +10,7 @@
|
|||
#include "Emu/system_progress.hpp"
|
||||
#include "Emu/IdManager.h"
|
||||
#include "Emu/Cell/Modules/cellScreenshot.h"
|
||||
#include "Emu/Cell/Modules/cellVideoOut.h"
|
||||
#include "Emu/RSX/rsx_utils.h"
|
||||
|
||||
#include <QApplication>
|
||||
|
@ -618,16 +619,32 @@ void gs_frame::take_screenshot(std::vector<u8> data, const u32 sshot_width, cons
|
|||
text[num_text].key = const_cast<char*>("Comment");
|
||||
text[num_text].text = const_cast<char*>(game_comment.c_str());
|
||||
|
||||
std::vector<u8*> rows(sshot_height);
|
||||
for (usz y = 0; y < sshot_height; y++)
|
||||
rows[y] = sshot_data_alpha.data() + y * sshot_width * 4;
|
||||
// Create image from data
|
||||
QImage img(sshot_data_alpha.data(), sshot_width, sshot_height, sshot_width * 4, QImage::Format_RGBA8888);
|
||||
|
||||
// Scale image if necessary
|
||||
int new_width = img.width();
|
||||
int new_height = img.height();
|
||||
auto& avconf = g_fxo->get<rsx::avconf>();
|
||||
avconf.upscale_to_aspect_ratio(new_width, new_height);
|
||||
|
||||
if (new_width != img.width() || new_height != img.height())
|
||||
{
|
||||
img = img.scaled(QSize(new_width, new_height), Qt::AspectRatioMode::IgnoreAspectRatio, Qt::TransformationMode::SmoothTransformation);
|
||||
img.convertTo(QImage::Format_RGBA8888); // The current Qt version changes the image format during smooth scaling, so we have to change it back.
|
||||
}
|
||||
|
||||
// Create row pointers for libpng
|
||||
std::vector<u8*> rows(img.height());
|
||||
for (int y = 0; y < img.height(); y++)
|
||||
rows[y] = img.scanLine(y);
|
||||
|
||||
std::vector<u8> encoded_png;
|
||||
|
||||
const auto write_png = [&]()
|
||||
{
|
||||
const scoped_png_ptrs ptrs;
|
||||
png_set_IHDR(ptrs.write_ptr, ptrs.info_ptr, sshot_width, sshot_height, 8, PNG_COLOR_TYPE_RGBA, PNG_INTERLACE_NONE, PNG_COMPRESSION_TYPE_DEFAULT, PNG_FILTER_TYPE_DEFAULT);
|
||||
png_set_IHDR(ptrs.write_ptr, ptrs.info_ptr, img.width(), img.height(), 8, PNG_COLOR_TYPE_RGBA, PNG_INTERLACE_NONE, PNG_COMPRESSION_TYPE_DEFAULT, PNG_FILTER_TYPE_DEFAULT);
|
||||
png_set_text(ptrs.write_ptr, ptrs.info_ptr, text, 6);
|
||||
png_set_rows(ptrs.write_ptr, ptrs.info_ptr, &rows[0]);
|
||||
png_set_write_fn(ptrs.write_ptr, &encoded_png, [](png_structp png_ptr, png_bytep data, png_size_t length)
|
||||
|
@ -660,10 +677,13 @@ void gs_frame::take_screenshot(std::vector<u8> data, const u32 sshot_width, cons
|
|||
|
||||
// Games choose the overlay file and the offset based on the current video resolution.
|
||||
// We need to scale the overlay if our resolution scaling causes the image to have a different size.
|
||||
auto& avconf = g_fxo->get<rsx::avconf>();
|
||||
|
||||
// TODO: handle wacky PS3 resolutions (without resolution scaling)
|
||||
if (avconf.resolution_x != sshot_width || avconf.resolution_y != sshot_height)
|
||||
// Scale the resolution first (as seen before with the image)
|
||||
new_width = avconf.resolution_x;
|
||||
new_height = avconf.resolution_y;
|
||||
avconf.upscale_to_aspect_ratio(new_width, new_height);
|
||||
|
||||
if (new_width != img.width() || new_height != img.height())
|
||||
{
|
||||
const int scale = rsx::get_resolution_scale_percent();
|
||||
const int x = (scale * manager.overlay_offset_x) / 100;
|
||||
|
@ -679,16 +699,16 @@ void gs_frame::take_screenshot(std::vector<u8> data, const u32 sshot_width, cons
|
|||
overlay_img = overlay_img.scaled(QSize(width, height), Qt::AspectRatioMode::IgnoreAspectRatio, Qt::TransformationMode::SmoothTransformation);
|
||||
}
|
||||
|
||||
if (manager.overlay_offset_x < static_cast<s64>(sshot_width) &&
|
||||
manager.overlay_offset_y < static_cast<s64>(sshot_height) &&
|
||||
if (manager.overlay_offset_x < static_cast<s64>(img.width()) &&
|
||||
manager.overlay_offset_y < static_cast<s64>(img.height()) &&
|
||||
manager.overlay_offset_x + overlay_img.width() > 0 &&
|
||||
manager.overlay_offset_y + overlay_img.height() > 0)
|
||||
{
|
||||
QImage screenshot_img(rows[0], sshot_width, sshot_height, QImage::Format_RGBA8888);
|
||||
QImage screenshot_img(rows[0], img.width(), img.height(), QImage::Format_RGBA8888);
|
||||
QPainter painter(&screenshot_img);
|
||||
painter.drawImage(manager.overlay_offset_x, manager.overlay_offset_y, overlay_img);
|
||||
|
||||
std::memcpy(rows[0], screenshot_img.constBits(), static_cast<usz>(sshot_height) * screenshot_img.bytesPerLine());
|
||||
std::memcpy(rows[0], screenshot_img.constBits(), screenshot_img.sizeInBytes());
|
||||
|
||||
screenshot_log.success("Applied screenshot overlay '%s'", cell_sshot_overlay_path);
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue