implemented fullscreen stretch modes
This commit is contained in:
@@ -21,6 +21,8 @@ add_library(ui STATIC
|
|||||||
qt_rendererstack.cpp
|
qt_rendererstack.cpp
|
||||||
qt_rendererstack.hpp
|
qt_rendererstack.hpp
|
||||||
qt_rendererstack.ui
|
qt_rendererstack.ui
|
||||||
|
qt_renderercomon.cpp
|
||||||
|
qt_renderercomon.hpp
|
||||||
qt_softwarerenderer.cpp
|
qt_softwarerenderer.cpp
|
||||||
qt_softwarerenderer.hpp
|
qt_softwarerenderer.hpp
|
||||||
qt_hardwarerenderer.cpp
|
qt_hardwarerenderer.cpp
|
||||||
|
|||||||
@@ -14,14 +14,8 @@ void HardwareRenderer::initializeGL()
|
|||||||
initializeOpenGLFunctions();
|
initializeOpenGLFunctions();
|
||||||
}
|
}
|
||||||
|
|
||||||
void HardwareRenderer::paintGL()
|
void HardwareRenderer::paintGL() {
|
||||||
{
|
onPaint(this);
|
||||||
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::setRenderType(RenderType type) {
|
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) {
|
void HardwareRenderer::onBlit(const QImage& img, int x, int y, int w, int h) {
|
||||||
image = img;
|
image = img;
|
||||||
sx = x;
|
source.setRect(x, y, w, h);
|
||||||
sy = y;
|
|
||||||
sw = w;
|
|
||||||
sh = h;
|
|
||||||
update();
|
update();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void HardwareRenderer::resizeEvent(QResizeEvent *event) {
|
||||||
|
onResize(width(), height());
|
||||||
|
QOpenGLWidget::resizeEvent(event);
|
||||||
|
}
|
||||||
|
|||||||
@@ -10,11 +10,13 @@
|
|||||||
#include <mutex>
|
#include <mutex>
|
||||||
#include <QApplication>
|
#include <QApplication>
|
||||||
|
|
||||||
|
#include "qt_renderercomon.hpp"
|
||||||
|
|
||||||
#ifdef WAYLAND
|
#ifdef WAYLAND
|
||||||
#include "wl_mouse.hpp"
|
#include "wl_mouse.hpp"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
class HardwareRenderer : public QOpenGLWidget, protected QOpenGLFunctions
|
class HardwareRenderer : public QOpenGLWidget, protected QOpenGLFunctions, public RendererCommon
|
||||||
{
|
{
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
|
|
||||||
@@ -49,7 +51,6 @@ public:
|
|||||||
public slots:
|
public slots:
|
||||||
void onBlit(const QImage& img, int, int, int, int);
|
void onBlit(const QImage& img, int, int, int, int);
|
||||||
|
|
||||||
private:
|
protected:
|
||||||
QImage image;
|
void resizeEvent(QResizeEvent *event) override;
|
||||||
int sx, sy, sw, sh;
|
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -139,6 +139,20 @@ MainWindow::MainWindow(QWidget *parent) :
|
|||||||
ui->actionLinear->setChecked(true);
|
ui->actionLinear->setChecked(true);
|
||||||
break;
|
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);
|
setFocusPolicy(Qt::StrongFocus);
|
||||||
ui->gles->setFocusPolicy(Qt::NoFocus);
|
ui->gles->setFocusPolicy(Qt::NoFocus);
|
||||||
@@ -735,6 +749,10 @@ void MainWindow::on_actionFullscreen_triggered() {
|
|||||||
showFullScreen();
|
showFullScreen();
|
||||||
video_fullscreen = 1;
|
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)
|
void MainWindow::setTitle_(const wchar_t *title)
|
||||||
@@ -932,3 +950,40 @@ void MainWindow::on_actionLinear_triggered() {
|
|||||||
video_filter_method = 1;
|
video_filter_method = 1;
|
||||||
ui->actionNearest->setChecked(false);
|
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_action2x_triggered();
|
||||||
void on_actionLinear_triggered();
|
void on_actionLinear_triggered();
|
||||||
void on_actionNearest_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 refreshMediaMenu();
|
||||||
void showMessage_(const QString& header, const QString& message);
|
void showMessage_(const QString& header, const QString& message);
|
||||||
|
|||||||
@@ -111,10 +111,10 @@
|
|||||||
<property name="title">
|
<property name="title">
|
||||||
<string>Fullscreen stretch mode</string>
|
<string>Fullscreen stretch mode</string>
|
||||||
</property>
|
</property>
|
||||||
<addaction name="actionFull_screen_stretch"/>
|
<addaction name="actionFullScreen_stretch"/>
|
||||||
<addaction name="action4_3"/>
|
<addaction name="actionFullScreen_43"/>
|
||||||
<addaction name="actionSquare_pixels_Keep_ratio"/>
|
<addaction name="actionFullScreen_keepRatio"/>
|
||||||
<addaction name="actionInteger_scale"/>
|
<addaction name="actionFullScreen_int"/>
|
||||||
</widget>
|
</widget>
|
||||||
<widget class="QMenu" name="menuEGA_S_VGA_settings">
|
<widget class="QMenu" name="menuEGA_S_VGA_settings">
|
||||||
<property name="title">
|
<property name="title">
|
||||||
@@ -362,7 +362,7 @@
|
|||||||
<string>Linear</string>
|
<string>Linear</string>
|
||||||
</property>
|
</property>
|
||||||
</action>
|
</action>
|
||||||
<action name="actionFull_screen_stretch">
|
<action name="actionFullScreen_stretch">
|
||||||
<property name="checkable">
|
<property name="checkable">
|
||||||
<bool>true</bool>
|
<bool>true</bool>
|
||||||
</property>
|
</property>
|
||||||
@@ -370,7 +370,7 @@
|
|||||||
<string>Full screen stretch</string>
|
<string>Full screen stretch</string>
|
||||||
</property>
|
</property>
|
||||||
</action>
|
</action>
|
||||||
<action name="action4_3">
|
<action name="actionFullScreen_43">
|
||||||
<property name="checkable">
|
<property name="checkable">
|
||||||
<bool>true</bool>
|
<bool>true</bool>
|
||||||
</property>
|
</property>
|
||||||
@@ -378,7 +378,7 @@
|
|||||||
<string>4:3</string>
|
<string>4:3</string>
|
||||||
</property>
|
</property>
|
||||||
</action>
|
</action>
|
||||||
<action name="actionSquare_pixels_Keep_ratio">
|
<action name="actionFullScreen_keepRatio">
|
||||||
<property name="checkable">
|
<property name="checkable">
|
||||||
<bool>true</bool>
|
<bool>true</bool>
|
||||||
</property>
|
</property>
|
||||||
@@ -386,7 +386,7 @@
|
|||||||
<string>Square pixels (Keep ratio)</string>
|
<string>Square pixels (Keep ratio)</string>
|
||||||
</property>
|
</property>
|
||||||
</action>
|
</action>
|
||||||
<action name="actionInteger_scale">
|
<action name="actionFullScreen_int">
|
||||||
<property name="checkable">
|
<property name="checkable">
|
||||||
<bool>true</bool>
|
<bool>true</bool>
|
||||||
</property>
|
</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"
|
#include "qt_softwarerenderer.hpp"
|
||||||
|
|
||||||
extern "C" {
|
|
||||||
#include <86box/86box.h>
|
|
||||||
}
|
|
||||||
#include <QPainter>
|
|
||||||
|
|
||||||
SoftwareRenderer::SoftwareRenderer(QWidget *parent) : QWidget(parent) {}
|
SoftwareRenderer::SoftwareRenderer(QWidget *parent) : QWidget(parent) {}
|
||||||
|
|
||||||
void SoftwareRenderer::paintEvent(QPaintEvent *event) {
|
void SoftwareRenderer::paintEvent(QPaintEvent *event) {
|
||||||
(void) event;
|
(void) event;
|
||||||
|
onPaint(this);
|
||||||
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();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void SoftwareRenderer::onBlit(const QImage& img, int x, int y, int w, int h) {
|
void SoftwareRenderer::onBlit(const QImage& img, int x, int y, int w, int h) {
|
||||||
image = img;
|
image = img;
|
||||||
sx = x;
|
source.setRect(x, y, w, h);
|
||||||
sy = y;
|
|
||||||
sw = w;
|
|
||||||
sh = h;
|
|
||||||
update();
|
update();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void SoftwareRenderer::resizeEvent(QResizeEvent *event) {
|
||||||
|
onResize(width(), height());
|
||||||
|
QWidget::resizeEvent(event);
|
||||||
|
}
|
||||||
|
|||||||
@@ -2,21 +2,20 @@
|
|||||||
#define SOFTWARERENDERER_HPP
|
#define SOFTWARERENDERER_HPP
|
||||||
|
|
||||||
#include <QWidget>
|
#include <QWidget>
|
||||||
|
#include "qt_renderercomon.hpp"
|
||||||
|
|
||||||
class SoftwareRenderer : public QWidget
|
class SoftwareRenderer : public QWidget, public RendererCommon
|
||||||
{
|
{
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
public:
|
public:
|
||||||
explicit SoftwareRenderer(QWidget *parent = nullptr);
|
explicit SoftwareRenderer(QWidget *parent = nullptr);
|
||||||
|
|
||||||
void paintEvent(QPaintEvent *event) override;
|
void paintEvent(QPaintEvent *event) override;
|
||||||
|
|
||||||
public slots:
|
public slots:
|
||||||
void onBlit(const QImage& img, int, int, int, int);
|
void onBlit(const QImage& img, int, int, int, int);
|
||||||
|
|
||||||
private:
|
protected:
|
||||||
QImage image;
|
void resizeEvent(QResizeEvent *event) override;
|
||||||
int sx, sy, sw, sh;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // SOFTWARERENDERER_HPP
|
#endif // SOFTWARERENDERER_HPP
|
||||||
|
|||||||
Reference in New Issue
Block a user