VK/GL: honor game's aspect ratio when scaling

This commit is contained in:
Megamouse 2021-11-02 21:57:02 +01:00
parent f16949c292
commit c8d4a0dcdc
7 changed files with 132 additions and 72 deletions

View file

@ -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);
}