implemented fullscreen stretch modes
This commit is contained in:
@@ -21,6 +21,8 @@ add_library(ui STATIC
|
||||
qt_rendererstack.cpp
|
||||
qt_rendererstack.hpp
|
||||
qt_rendererstack.ui
|
||||
qt_renderercomon.cpp
|
||||
qt_renderercomon.hpp
|
||||
qt_softwarerenderer.cpp
|
||||
qt_softwarerenderer.hpp
|
||||
qt_hardwarerenderer.cpp
|
||||
|
@@ -14,14 +14,8 @@ void HardwareRenderer::initializeGL()
|
||||
initializeOpenGLFunctions();
|
||||
}
|
||||
|
||||
void HardwareRenderer::paintGL()
|
||||
{
|
||||
QPainter painter(this);
|
||||
painter.setRenderHint(QPainter::SmoothPixmapTransform, video_filter_method > 0 ? true : false);
|
||||
painter.drawImage(QRect(0, 0, width(), height()), image, QRect(sx, sy, sw, sh));
|
||||
// "release" image, reducing it's refcount, so renderstack::blit()
|
||||
// won't have to reallocate
|
||||
image = QImage();
|
||||
void HardwareRenderer::paintGL() {
|
||||
onPaint(this);
|
||||
}
|
||||
|
||||
void HardwareRenderer::setRenderType(RenderType type) {
|
||||
@@ -41,9 +35,11 @@ void HardwareRenderer::setRenderType(RenderType type) {
|
||||
|
||||
void HardwareRenderer::onBlit(const QImage& img, int x, int y, int w, int h) {
|
||||
image = img;
|
||||
sx = x;
|
||||
sy = y;
|
||||
sw = w;
|
||||
sh = h;
|
||||
source.setRect(x, y, w, h);
|
||||
update();
|
||||
}
|
||||
|
||||
void HardwareRenderer::resizeEvent(QResizeEvent *event) {
|
||||
onResize(width(), height());
|
||||
QOpenGLWidget::resizeEvent(event);
|
||||
}
|
||||
|
@@ -10,11 +10,13 @@
|
||||
#include <mutex>
|
||||
#include <QApplication>
|
||||
|
||||
#include "qt_renderercomon.hpp"
|
||||
|
||||
#ifdef WAYLAND
|
||||
#include "wl_mouse.hpp"
|
||||
#endif
|
||||
|
||||
class HardwareRenderer : public QOpenGLWidget, protected QOpenGLFunctions
|
||||
class HardwareRenderer : public QOpenGLWidget, protected QOpenGLFunctions, public RendererCommon
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
@@ -49,7 +51,6 @@ public:
|
||||
public slots:
|
||||
void onBlit(const QImage& img, int, int, int, int);
|
||||
|
||||
private:
|
||||
QImage image;
|
||||
int sx, sy, sw, sh;
|
||||
protected:
|
||||
void resizeEvent(QResizeEvent *event) override;
|
||||
};
|
||||
|
@@ -139,6 +139,20 @@ MainWindow::MainWindow(QWidget *parent) :
|
||||
ui->actionLinear->setChecked(true);
|
||||
break;
|
||||
}
|
||||
switch (video_fullscreen_scale) {
|
||||
case FULLSCR_SCALE_FULL:
|
||||
ui->actionFullScreen_stretch->setChecked(true);
|
||||
break;
|
||||
case FULLSCR_SCALE_43:
|
||||
ui->actionFullScreen_43->setChecked(true);
|
||||
break;
|
||||
case FULLSCR_SCALE_KEEPRATIO:
|
||||
ui->actionFullScreen_keepRatio->setChecked(true);
|
||||
break;
|
||||
case FULLSCR_SCALE_INT:
|
||||
ui->actionFullScreen_int->setChecked(true);
|
||||
break;
|
||||
}
|
||||
|
||||
setFocusPolicy(Qt::StrongFocus);
|
||||
ui->gles->setFocusPolicy(Qt::NoFocus);
|
||||
@@ -735,6 +749,10 @@ void MainWindow::on_actionFullscreen_triggered() {
|
||||
showFullScreen();
|
||||
video_fullscreen = 1;
|
||||
}
|
||||
|
||||
auto widget = ui->stackedWidget->currentWidget();
|
||||
auto rc = dynamic_cast<RendererCommon*>(widget);
|
||||
rc->onResize(widget->width(), widget->height());
|
||||
}
|
||||
|
||||
void MainWindow::setTitle_(const wchar_t *title)
|
||||
@@ -932,3 +950,40 @@ void MainWindow::on_actionLinear_triggered() {
|
||||
video_filter_method = 1;
|
||||
ui->actionNearest->setChecked(false);
|
||||
}
|
||||
|
||||
static void update_fullscreen_scale_checkboxes(Ui::MainWindow* ui, QAction* selected) {
|
||||
ui->actionFullScreen_stretch->setChecked(ui->actionFullScreen_stretch == selected);
|
||||
ui->actionFullScreen_43->setChecked(ui->actionFullScreen_43 == selected);
|
||||
ui->actionFullScreen_keepRatio->setChecked(ui->actionFullScreen_keepRatio == selected);
|
||||
ui->actionFullScreen_int->setChecked(ui->actionFullScreen_int == selected);
|
||||
|
||||
if (video_fullscreen > 0) {
|
||||
auto widget = ui->stackedWidget->currentWidget();
|
||||
auto rc = dynamic_cast<RendererCommon*>(widget);
|
||||
rc->onResize(widget->width(), widget->height());
|
||||
}
|
||||
|
||||
device_force_redraw();
|
||||
config_save();
|
||||
}
|
||||
|
||||
void MainWindow::on_actionFullScreen_stretch_triggered() {
|
||||
video_fullscreen_scale = FULLSCR_SCALE_FULL;
|
||||
update_fullscreen_scale_checkboxes(ui, ui->actionFullScreen_stretch);
|
||||
}
|
||||
|
||||
void MainWindow::on_actionFullScreen_43_triggered() {
|
||||
video_fullscreen_scale = FULLSCR_SCALE_43;
|
||||
update_fullscreen_scale_checkboxes(ui, ui->actionFullScreen_43);
|
||||
}
|
||||
|
||||
void MainWindow::on_actionFullScreen_keepRatio_triggered() {
|
||||
video_fullscreen_scale = FULLSCR_SCALE_KEEPRATIO;
|
||||
update_fullscreen_scale_checkboxes(ui, ui->actionFullScreen_keepRatio);
|
||||
}
|
||||
|
||||
void MainWindow::on_actionFullScreen_int_triggered() {
|
||||
video_fullscreen_scale = FULLSCR_SCALE_INT;
|
||||
update_fullscreen_scale_checkboxes(ui, ui->actionFullScreen_int);
|
||||
}
|
||||
|
||||
|
@@ -64,6 +64,10 @@ private slots:
|
||||
void on_action2x_triggered();
|
||||
void on_actionLinear_triggered();
|
||||
void on_actionNearest_triggered();
|
||||
void on_actionFullScreen_int_triggered();
|
||||
void on_actionFullScreen_keepRatio_triggered();
|
||||
void on_actionFullScreen_43_triggered();
|
||||
void on_actionFullScreen_stretch_triggered();
|
||||
|
||||
void refreshMediaMenu();
|
||||
void showMessage_(const QString& header, const QString& message);
|
||||
|
@@ -111,10 +111,10 @@
|
||||
<property name="title">
|
||||
<string>Fullscreen stretch mode</string>
|
||||
</property>
|
||||
<addaction name="actionFull_screen_stretch"/>
|
||||
<addaction name="action4_3"/>
|
||||
<addaction name="actionSquare_pixels_Keep_ratio"/>
|
||||
<addaction name="actionInteger_scale"/>
|
||||
<addaction name="actionFullScreen_stretch"/>
|
||||
<addaction name="actionFullScreen_43"/>
|
||||
<addaction name="actionFullScreen_keepRatio"/>
|
||||
<addaction name="actionFullScreen_int"/>
|
||||
</widget>
|
||||
<widget class="QMenu" name="menuEGA_S_VGA_settings">
|
||||
<property name="title">
|
||||
@@ -362,7 +362,7 @@
|
||||
<string>Linear</string>
|
||||
</property>
|
||||
</action>
|
||||
<action name="actionFull_screen_stretch">
|
||||
<action name="actionFullScreen_stretch">
|
||||
<property name="checkable">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
@@ -370,7 +370,7 @@
|
||||
<string>Full screen stretch</string>
|
||||
</property>
|
||||
</action>
|
||||
<action name="action4_3">
|
||||
<action name="actionFullScreen_43">
|
||||
<property name="checkable">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
@@ -378,7 +378,7 @@
|
||||
<string>4:3</string>
|
||||
</property>
|
||||
</action>
|
||||
<action name="actionSquare_pixels_Keep_ratio">
|
||||
<action name="actionFullScreen_keepRatio">
|
||||
<property name="checkable">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
@@ -386,7 +386,7 @@
|
||||
<string>Square pixels (Keep ratio)</string>
|
||||
</property>
|
||||
</action>
|
||||
<action name="actionInteger_scale">
|
||||
<action name="actionFullScreen_int">
|
||||
<property name="checkable">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
|
89
src/qt/qt_renderercomon.cpp
Normal file
89
src/qt/qt_renderercomon.cpp
Normal file
@@ -0,0 +1,89 @@
|
||||
#include "qt_renderercomon.hpp"
|
||||
|
||||
#include <QPainter>
|
||||
#include <QWidget>
|
||||
|
||||
#include <cmath>
|
||||
|
||||
extern "C" {
|
||||
#include <86box/86box.h>
|
||||
#include <86box/video.h>
|
||||
}
|
||||
|
||||
RendererCommon::RendererCommon() = default;
|
||||
|
||||
void RendererCommon::onPaint(QPaintDevice* device) {
|
||||
QPainter painter(device);
|
||||
painter.setRenderHint(QPainter::SmoothPixmapTransform, video_filter_method > 0 ? true : false);
|
||||
painter.drawImage(destination, image, source);
|
||||
// "release" image, reducing it's refcount, so renderstack::blit()
|
||||
// won't have to reallocate
|
||||
image = QImage();
|
||||
}
|
||||
|
||||
static void integer_scale(double *d, double *g) {
|
||||
double ratio;
|
||||
|
||||
if (*d > *g) {
|
||||
ratio = std::floor(*d / *g);
|
||||
*d = *g * ratio;
|
||||
} else {
|
||||
ratio = std::ceil(*d / *g);
|
||||
*d = *g / ratio;
|
||||
}
|
||||
}
|
||||
|
||||
void RendererCommon::onResize(int width, int height) {
|
||||
if (video_fullscreen == 0) {
|
||||
destination.setRect(0, 0, width, height);
|
||||
return;
|
||||
}
|
||||
double dx, dy, dw, dh, gsr;
|
||||
|
||||
double hw = width;
|
||||
double hh = height;
|
||||
double gw = source.width();
|
||||
double gh = source.height();
|
||||
double hsr = hw / hh;
|
||||
|
||||
switch (video_fullscreen_scale) {
|
||||
case FULLSCR_SCALE_INT:
|
||||
gsr = gw / gh;
|
||||
if (gsr <= hsr) {
|
||||
dw = hh * gsr;
|
||||
dh = hh;
|
||||
} else {
|
||||
dw = hw;
|
||||
dh = hw / gsr;
|
||||
}
|
||||
integer_scale(&dw, &gw);
|
||||
integer_scale(&dh, &gh);
|
||||
dx = (hw - dw) / 2.0;
|
||||
dy = (hh - dh) / 2.0;
|
||||
destination.setRect(dx, dy, dw, dh);
|
||||
break;
|
||||
case FULLSCR_SCALE_43:
|
||||
case FULLSCR_SCALE_KEEPRATIO:
|
||||
if (video_fullscreen_scale == FULLSCR_SCALE_43) {
|
||||
gsr = 4.0 / 3.0;
|
||||
} else {
|
||||
gsr = gw / gh;
|
||||
}
|
||||
|
||||
if (gsr <= hsr) {
|
||||
dw = hh * gsr;
|
||||
dh = hh;
|
||||
} else {
|
||||
dw = hw;
|
||||
dh = hw / gsr;
|
||||
}
|
||||
dx = (hw - dw) / 2.0;
|
||||
dy = (hh - dh) / 2.0;
|
||||
destination.setRect(dx, dy, dw, dh);
|
||||
break;
|
||||
case FULLSCR_SCALE_FULL:
|
||||
default:
|
||||
destination.setRect(0, 0, hw, hh);
|
||||
break;
|
||||
}
|
||||
}
|
19
src/qt/qt_renderercomon.hpp
Normal file
19
src/qt/qt_renderercomon.hpp
Normal file
@@ -0,0 +1,19 @@
|
||||
#pragma once
|
||||
|
||||
#include <QRect>
|
||||
#include <QImage>
|
||||
|
||||
class QWidget;
|
||||
|
||||
class RendererCommon
|
||||
{
|
||||
public:
|
||||
RendererCommon();
|
||||
|
||||
void onResize(int width, int height);
|
||||
protected:
|
||||
void onPaint(QPaintDevice* device);
|
||||
|
||||
QImage image;
|
||||
QRect source, destination;
|
||||
};
|
@@ -1,26 +1,19 @@
|
||||
#include "qt_softwarerenderer.hpp"
|
||||
|
||||
extern "C" {
|
||||
#include <86box/86box.h>
|
||||
}
|
||||
#include <QPainter>
|
||||
|
||||
SoftwareRenderer::SoftwareRenderer(QWidget *parent) : QWidget(parent) {}
|
||||
|
||||
void SoftwareRenderer::paintEvent(QPaintEvent *event) {
|
||||
(void) event;
|
||||
|
||||
QPainter painter(this);
|
||||
painter.setRenderHint(QPainter::SmoothPixmapTransform, video_filter_method > 0 ? true : false);
|
||||
painter.drawImage(QRect(0, 0, width(), height()), image, QRect(sx, sy, sw, sh));
|
||||
image = QImage();
|
||||
onPaint(this);
|
||||
}
|
||||
|
||||
void SoftwareRenderer::onBlit(const QImage& img, int x, int y, int w, int h) {
|
||||
image = img;
|
||||
sx = x;
|
||||
sy = y;
|
||||
sw = w;
|
||||
sh = h;
|
||||
source.setRect(x, y, w, h);
|
||||
update();
|
||||
}
|
||||
|
||||
void SoftwareRenderer::resizeEvent(QResizeEvent *event) {
|
||||
onResize(width(), height());
|
||||
QWidget::resizeEvent(event);
|
||||
}
|
||||
|
@@ -2,21 +2,20 @@
|
||||
#define SOFTWARERENDERER_HPP
|
||||
|
||||
#include <QWidget>
|
||||
#include "qt_renderercomon.hpp"
|
||||
|
||||
class SoftwareRenderer : public QWidget
|
||||
class SoftwareRenderer : public QWidget, public RendererCommon
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
explicit SoftwareRenderer(QWidget *parent = nullptr);
|
||||
|
||||
void paintEvent(QPaintEvent *event) override;
|
||||
|
||||
public slots:
|
||||
void onBlit(const QImage& img, int, int, int, int);
|
||||
|
||||
private:
|
||||
QImage image;
|
||||
int sx, sy, sw, sh;
|
||||
protected:
|
||||
void resizeEvent(QResizeEvent *event) override;
|
||||
};
|
||||
|
||||
#endif // SOFTWARERENDERER_HPP
|
||||
|
Reference in New Issue
Block a user