qt: add Direct3D 9 renderer
This commit is contained in:
@@ -179,7 +179,8 @@ if(WIN32)
|
|||||||
enable_language(RC)
|
enable_language(RC)
|
||||||
target_sources(86Box PUBLIC ../win/86Box-qt.rc)
|
target_sources(86Box PUBLIC ../win/86Box-qt.rc)
|
||||||
target_sources(plat PRIVATE win_joystick_rawinput.c)
|
target_sources(plat PRIVATE win_joystick_rawinput.c)
|
||||||
target_link_libraries(86Box hid)
|
target_sources(ui PRIVATE qt_d3d9renderer.hpp qt_d3d9renderer.cpp)
|
||||||
|
target_link_libraries(86Box hid d3d9)
|
||||||
|
|
||||||
# CMake 3.22 messed this up for clang/clang++
|
# CMake 3.22 messed this up for clang/clang++
|
||||||
# See https://gitlab.kitware.com/cmake/cmake/-/issues/22611
|
# See https://gitlab.kitware.com/cmake/cmake/-/issues/22611
|
||||||
|
@@ -49,6 +49,8 @@ plat_vidapi(char* api) {
|
|||||||
return 3;
|
return 3;
|
||||||
} else if (!strcasecmp(api, "qt_vulkan")) {
|
} else if (!strcasecmp(api, "qt_vulkan")) {
|
||||||
return 4;
|
return 4;
|
||||||
|
} else if (!strcasecmp(api, "qt_d3d9")) {
|
||||||
|
return 5;
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
@@ -73,6 +75,9 @@ char* plat_vidapi_name(int api) {
|
|||||||
case 4:
|
case 4:
|
||||||
name = "qt_vulkan";
|
name = "qt_vulkan";
|
||||||
break;
|
break;
|
||||||
|
case 5:
|
||||||
|
name = "qt_d3d9";
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
fatal("Unknown renderer: %i\n", api);
|
fatal("Unknown renderer: %i\n", api);
|
||||||
break;
|
break;
|
||||||
|
167
src/qt/qt_d3d9renderer.cpp
Normal file
167
src/qt/qt_d3d9renderer.cpp
Normal file
@@ -0,0 +1,167 @@
|
|||||||
|
#include "qt_d3d9renderer.hpp"
|
||||||
|
#include <QResizeEvent>
|
||||||
|
#include <QTimer>
|
||||||
|
|
||||||
|
extern "C"
|
||||||
|
{
|
||||||
|
#include <86box/86box.h>
|
||||||
|
#include <86box/video.h>
|
||||||
|
}
|
||||||
|
|
||||||
|
D3D9Renderer::D3D9Renderer(QWidget *parent)
|
||||||
|
: QWidget{parent}, RendererCommon()
|
||||||
|
{
|
||||||
|
QPalette pal = palette();
|
||||||
|
pal.setColor(QPalette::Window, Qt::black);
|
||||||
|
setAutoFillBackground(true);
|
||||||
|
setPalette(pal);
|
||||||
|
|
||||||
|
setAttribute(Qt::WA_NativeWindow);
|
||||||
|
setAttribute(Qt::WA_PaintOnScreen);
|
||||||
|
setAttribute(Qt::WA_NoSystemBackground);
|
||||||
|
setAttribute(Qt::WA_OpaquePaintEvent);
|
||||||
|
|
||||||
|
windowHandle = (HWND)winId();
|
||||||
|
surfaceInUse = true;
|
||||||
|
|
||||||
|
RendererCommon::parentWidget = parent;
|
||||||
|
|
||||||
|
this->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);
|
||||||
|
}
|
||||||
|
|
||||||
|
D3D9Renderer::~D3D9Renderer()
|
||||||
|
{
|
||||||
|
finalize();
|
||||||
|
}
|
||||||
|
|
||||||
|
void D3D9Renderer::finalize()
|
||||||
|
{
|
||||||
|
if (!finalized) {
|
||||||
|
while (surfaceInUse) {}
|
||||||
|
finalized = true;
|
||||||
|
}
|
||||||
|
surfaceInUse = true;
|
||||||
|
if (d3d9surface) { d3d9surface->Release(); d3d9surface = nullptr;}
|
||||||
|
if (d3d9dev) { d3d9dev->Release(); d3d9dev = nullptr; }
|
||||||
|
if (d3d9) { d3d9->Release(); d3d9 = nullptr; };
|
||||||
|
}
|
||||||
|
|
||||||
|
void D3D9Renderer::hideEvent(QHideEvent *event)
|
||||||
|
{
|
||||||
|
finalize();
|
||||||
|
}
|
||||||
|
|
||||||
|
void D3D9Renderer::showEvent(QShowEvent *event)
|
||||||
|
{
|
||||||
|
params = {};
|
||||||
|
|
||||||
|
if (FAILED(Direct3DCreate9Ex(D3D_SDK_VERSION, &d3d9))) {
|
||||||
|
return error("Failed to create Direct3D 9 context");
|
||||||
|
}
|
||||||
|
|
||||||
|
params.Windowed = true;
|
||||||
|
params.SwapEffect = D3DSWAPEFFECT_FLIPEX;
|
||||||
|
params.BackBufferWidth = width();
|
||||||
|
params.BackBufferHeight = height();
|
||||||
|
params.BackBufferCount = 1;
|
||||||
|
params.FullScreen_RefreshRateInHz = D3DPRESENT_RATE_DEFAULT;
|
||||||
|
params.PresentationInterval = D3DPRESENT_INTERVAL_IMMEDIATE;
|
||||||
|
params.hDeviceWindow = windowHandle;
|
||||||
|
|
||||||
|
HRESULT result = d3d9->CreateDeviceEx(D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, windowHandle, D3DCREATE_MULTITHREADED | D3DCREATE_HARDWARE_VERTEXPROCESSING, ¶ms, nullptr, &d3d9dev);
|
||||||
|
if (FAILED(result)) result = d3d9->CreateDeviceEx(D3DADAPTER_DEFAULT, D3DDEVTYPE_REF, windowHandle, D3DCREATE_MULTITHREADED | D3DCREATE_SOFTWARE_VERTEXPROCESSING, ¶ms, nullptr, &d3d9dev);
|
||||||
|
if (FAILED(result)) {
|
||||||
|
return error("Failed to create Direct3D 9 device");
|
||||||
|
}
|
||||||
|
|
||||||
|
result = d3d9dev->CreateOffscreenPlainSurface(2048, 2048, D3DFMT_A8R8G8B8, D3DPOOL_DEFAULT, &d3d9surface, nullptr);
|
||||||
|
if (FAILED(result)) result = d3d9dev->CreateOffscreenPlainSurface(1024, 1024, D3DFMT_A8R8G8B8, D3DPOOL_DEFAULT, &d3d9surface, nullptr);
|
||||||
|
if (FAILED(result)) {
|
||||||
|
return error("Failed to create Direct3D 9 surface");
|
||||||
|
}
|
||||||
|
if (!alreadyInitialized) {
|
||||||
|
emit initialized();
|
||||||
|
alreadyInitialized = true;
|
||||||
|
}
|
||||||
|
surfaceInUse = false;
|
||||||
|
finalized = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
void D3D9Renderer::paintEvent(QPaintEvent *event)
|
||||||
|
{
|
||||||
|
IDirect3DSurface9* backbuffer = nullptr;
|
||||||
|
RECT srcRect, dstRect;
|
||||||
|
HRESULT result = d3d9dev->GetBackBuffer(0, 0, D3DBACKBUFFER_TYPE_MONO, &backbuffer);
|
||||||
|
|
||||||
|
if (FAILED(result)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
srcRect.top = source.top();
|
||||||
|
srcRect.bottom = source.bottom();
|
||||||
|
srcRect.left = source.left();
|
||||||
|
srcRect.right = source.right();
|
||||||
|
dstRect.top = destination.top();
|
||||||
|
dstRect.bottom = destination.bottom();
|
||||||
|
dstRect.left = destination.left();
|
||||||
|
dstRect.right = destination.right();
|
||||||
|
d3d9dev->BeginScene();
|
||||||
|
while (surfaceInUse) {}
|
||||||
|
surfaceInUse = true;
|
||||||
|
d3d9dev->StretchRect(d3d9surface, &srcRect, backbuffer, &dstRect, video_filter_method == 0 ? D3DTEXF_POINT : D3DTEXF_LINEAR);
|
||||||
|
result = d3d9dev->EndScene();
|
||||||
|
surfaceInUse = false;
|
||||||
|
if (SUCCEEDED(result)) {
|
||||||
|
if (FAILED(d3d9dev->PresentEx(nullptr, nullptr, 0, nullptr, D3DPRESENT_FORCEIMMEDIATE))) {
|
||||||
|
finalize();
|
||||||
|
showEvent(nullptr);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool D3D9Renderer::event(QEvent *event)
|
||||||
|
{
|
||||||
|
bool res = false;
|
||||||
|
if (!eventDelegate(event, res)) return QWidget::event(event);
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
|
void D3D9Renderer::resizeEvent(QResizeEvent *event)
|
||||||
|
{
|
||||||
|
onResize(width(), height());
|
||||||
|
|
||||||
|
params.BackBufferWidth = event->size().width();
|
||||||
|
params.BackBufferHeight = event->size().height();
|
||||||
|
if (d3d9dev) d3d9dev->Reset(¶ms);
|
||||||
|
QWidget::resizeEvent(event);
|
||||||
|
}
|
||||||
|
|
||||||
|
void D3D9Renderer::blit(int x, int y, int w, int h)
|
||||||
|
{
|
||||||
|
if ((x < 0) || (y < 0) || (w <= 0) || (h <= 0) || (w > 2048) || (h > 2048) || (buffer32 == NULL) || surfaceInUse) {
|
||||||
|
video_blit_complete();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
source.setRect(x, y, w, h);
|
||||||
|
RECT srcRect;
|
||||||
|
D3DLOCKED_RECT lockRect;
|
||||||
|
srcRect.top = source.top();
|
||||||
|
srcRect.bottom = source.bottom();
|
||||||
|
srcRect.left = source.left();
|
||||||
|
srcRect.right = source.right();
|
||||||
|
|
||||||
|
surfaceInUse = true;
|
||||||
|
if (screenshots) {
|
||||||
|
video_screenshot((uint32_t *) &(buffer32->line[y][x]), 0, 0, 2048);
|
||||||
|
}
|
||||||
|
if (SUCCEEDED(d3d9surface->LockRect(&lockRect, &srcRect, 0))) {
|
||||||
|
for (int y1 = 0; y1 < h; y1++) {
|
||||||
|
video_copy(((uint8_t*)lockRect.pBits) + (y1 * lockRect.Pitch), &(buffer32->line[y + y1][x]), w * 4);
|
||||||
|
}
|
||||||
|
video_blit_complete();
|
||||||
|
d3d9surface->UnlockRect();
|
||||||
|
}
|
||||||
|
else video_blit_complete();
|
||||||
|
surfaceInUse = false;
|
||||||
|
QTimer::singleShot(0, this, [this] { this->update(); });
|
||||||
|
}
|
44
src/qt/qt_d3d9renderer.hpp
Normal file
44
src/qt/qt_d3d9renderer.hpp
Normal file
@@ -0,0 +1,44 @@
|
|||||||
|
#ifndef D3D9RENDERER_HPP
|
||||||
|
#define D3D9RENDERER_HPP
|
||||||
|
|
||||||
|
#include <QWidget>
|
||||||
|
#include "qt_renderercommon.hpp"
|
||||||
|
|
||||||
|
#include <windows.h>
|
||||||
|
#include <d3d9.h>
|
||||||
|
#include <atomic>
|
||||||
|
|
||||||
|
class D3D9Renderer : public QWidget, public RendererCommon
|
||||||
|
{
|
||||||
|
Q_OBJECT
|
||||||
|
public:
|
||||||
|
explicit D3D9Renderer(QWidget *parent = nullptr);
|
||||||
|
~D3D9Renderer();
|
||||||
|
bool hasBlitFunc() override { return true; }
|
||||||
|
void blit(int x, int y, int w, int h) override;
|
||||||
|
void finalize() override;
|
||||||
|
|
||||||
|
protected:
|
||||||
|
void showEvent(QShowEvent* event) override;
|
||||||
|
void hideEvent(QHideEvent *event) override;
|
||||||
|
void resizeEvent(QResizeEvent *event) override;
|
||||||
|
void paintEvent(QPaintEvent *event) override;
|
||||||
|
bool event(QEvent* event) override;
|
||||||
|
QPaintEngine* paintEngine() const override { return nullptr; }
|
||||||
|
|
||||||
|
signals:
|
||||||
|
void initialized();
|
||||||
|
void error(QString);
|
||||||
|
|
||||||
|
private:
|
||||||
|
HWND windowHandle = 0;
|
||||||
|
D3DPRESENT_PARAMETERS params{};
|
||||||
|
IDirect3D9Ex* d3d9 = nullptr;
|
||||||
|
IDirect3DDevice9Ex* d3d9dev = nullptr;
|
||||||
|
IDirect3DSurface9* d3d9surface = nullptr;
|
||||||
|
|
||||||
|
std::atomic<bool> surfaceInUse{false}, finalized{false};
|
||||||
|
bool alreadyInitialized = false;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // D3D9RENDERER_HPP
|
@@ -281,6 +281,10 @@ MainWindow::MainWindow(QWidget *parent) :
|
|||||||
ui->actionVulkan->setVisible(false);
|
ui->actionVulkan->setVisible(false);
|
||||||
ui->actionOpenGL_3_0_Core->setVisible(false);
|
ui->actionOpenGL_3_0_Core->setVisible(false);
|
||||||
}
|
}
|
||||||
|
#if !defined Q_OS_WINDOWS
|
||||||
|
ui->actionDirect3D_9->setVisible(false);
|
||||||
|
if (vid_api == 5) vid_api = 0;
|
||||||
|
#endif
|
||||||
|
|
||||||
#if !QT_CONFIG(vulkan)
|
#if !QT_CONFIG(vulkan)
|
||||||
if (vid_api == 4) vid_api = 0;
|
if (vid_api == 4) vid_api = 0;
|
||||||
@@ -295,6 +299,7 @@ MainWindow::MainWindow(QWidget *parent) :
|
|||||||
actGroup->addAction(ui->actionHardware_Renderer_OpenGL_ES);
|
actGroup->addAction(ui->actionHardware_Renderer_OpenGL_ES);
|
||||||
actGroup->addAction(ui->actionOpenGL_3_0_Core);
|
actGroup->addAction(ui->actionOpenGL_3_0_Core);
|
||||||
actGroup->addAction(ui->actionVulkan);
|
actGroup->addAction(ui->actionVulkan);
|
||||||
|
actGroup->addAction(ui->actionDirect3D_9);
|
||||||
actGroup->setExclusive(true);
|
actGroup->setExclusive(true);
|
||||||
|
|
||||||
connect(actGroup, &QActionGroup::triggered, [this](QAction* action) {
|
connect(actGroup, &QActionGroup::triggered, [this](QAction* action) {
|
||||||
@@ -316,6 +321,9 @@ MainWindow::MainWindow(QWidget *parent) :
|
|||||||
case 4:
|
case 4:
|
||||||
ui->stackedWidget->switchRenderer(RendererStack::Renderer::Vulkan);
|
ui->stackedWidget->switchRenderer(RendererStack::Renderer::Vulkan);
|
||||||
break;
|
break;
|
||||||
|
case 5:
|
||||||
|
ui->stackedWidget->switchRenderer(RendererStack::Renderer::Direct3D9);
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -1341,6 +1349,7 @@ void MainWindow::processMacKeyboardInput(bool down, const QKeyEvent* event) {
|
|||||||
void MainWindow::on_actionFullscreen_triggered() {
|
void MainWindow::on_actionFullscreen_triggered() {
|
||||||
if (video_fullscreen > 0) {
|
if (video_fullscreen > 0) {
|
||||||
showNormal();
|
showNormal();
|
||||||
|
if (vid_api == 5) ui->stackedWidget->switchRenderer(RendererStack::Renderer::Direct3D9);
|
||||||
ui->menubar->show();
|
ui->menubar->show();
|
||||||
if (!hide_status_bar) ui->statusbar->show();
|
if (!hide_status_bar) ui->statusbar->show();
|
||||||
if (!hide_tool_bar) ui->toolBar->show();
|
if (!hide_tool_bar) ui->toolBar->show();
|
||||||
|
@@ -54,7 +54,7 @@
|
|||||||
<x>0</x>
|
<x>0</x>
|
||||||
<y>0</y>
|
<y>0</y>
|
||||||
<width>724</width>
|
<width>724</width>
|
||||||
<height>23</height>
|
<height>21</height>
|
||||||
</rect>
|
</rect>
|
||||||
</property>
|
</property>
|
||||||
<widget class="QMenu" name="menuAction">
|
<widget class="QMenu" name="menuAction">
|
||||||
@@ -105,6 +105,7 @@
|
|||||||
<addaction name="actionHardware_Renderer_OpenGL_ES"/>
|
<addaction name="actionHardware_Renderer_OpenGL_ES"/>
|
||||||
<addaction name="actionOpenGL_3_0_Core"/>
|
<addaction name="actionOpenGL_3_0_Core"/>
|
||||||
<addaction name="actionVulkan"/>
|
<addaction name="actionVulkan"/>
|
||||||
|
<addaction name="actionDirect3D_9"/>
|
||||||
</widget>
|
</widget>
|
||||||
<widget class="QMenu" name="menuWindow_scale_factor">
|
<widget class="QMenu" name="menuWindow_scale_factor">
|
||||||
<property name="title">
|
<property name="title">
|
||||||
@@ -745,6 +746,17 @@
|
|||||||
<string>MCA devices...</string>
|
<string>MCA devices...</string>
|
||||||
</property>
|
</property>
|
||||||
</action>
|
</action>
|
||||||
|
<action name="actionDirect3D_9">
|
||||||
|
<property name="checkable">
|
||||||
|
<bool>true</bool>
|
||||||
|
</property>
|
||||||
|
<property name="text">
|
||||||
|
<string>Direct3D 9</string>
|
||||||
|
</property>
|
||||||
|
<property name="vid_api" stdset="0">
|
||||||
|
<number>5</number>
|
||||||
|
</property>
|
||||||
|
</action>
|
||||||
</widget>
|
</widget>
|
||||||
<customwidgets>
|
<customwidgets>
|
||||||
<customwidget>
|
<customwidget>
|
||||||
|
@@ -22,13 +22,16 @@ public:
|
|||||||
|
|
||||||
virtual uint32_t getBytesPerRow() { return 2048 * 4; }
|
virtual uint32_t getBytesPerRow() { return 2048 * 4; }
|
||||||
|
|
||||||
virtual std::vector<std::tuple<uint8_t *, std::atomic_flag *>> getBuffers() = 0;
|
virtual std::vector<std::tuple<uint8_t *, std::atomic_flag *>> getBuffers() { std::vector<std::tuple<uint8_t*, std::atomic_flag*>> buffers; return buffers; }
|
||||||
|
|
||||||
/* Does renderer implement options dialog */
|
/* Does renderer implement options dialog */
|
||||||
virtual bool hasOptions() const { return false; }
|
virtual bool hasOptions() const { return false; }
|
||||||
/* Returns options dialog for renderer */
|
/* Returns options dialog for renderer */
|
||||||
virtual QDialog *getOptions(QWidget *parent) { return nullptr; }
|
virtual QDialog *getOptions(QWidget *parent) { return nullptr; }
|
||||||
|
|
||||||
|
virtual bool hasBlitFunc() { return false; }
|
||||||
|
virtual void blit(int x, int y, int w, int h) {}
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
bool eventDelegate(QEvent *event, bool &result);
|
bool eventDelegate(QEvent *event, bool &result);
|
||||||
|
|
||||||
|
@@ -25,6 +25,9 @@
|
|||||||
#include "qt_openglrenderer.hpp"
|
#include "qt_openglrenderer.hpp"
|
||||||
#include "qt_softwarerenderer.hpp"
|
#include "qt_softwarerenderer.hpp"
|
||||||
#include "qt_vulkanwindowrenderer.hpp"
|
#include "qt_vulkanwindowrenderer.hpp"
|
||||||
|
#ifdef Q_OS_WIN
|
||||||
|
#include "qt_d3d9renderer.hpp"
|
||||||
|
#endif
|
||||||
|
|
||||||
#include "qt_mainwindow.hpp"
|
#include "qt_mainwindow.hpp"
|
||||||
#include "qt_util.hpp"
|
#include "qt_util.hpp"
|
||||||
@@ -223,12 +226,18 @@ RendererStack::switchRenderer(Renderer renderer)
|
|||||||
{
|
{
|
||||||
startblit();
|
startblit();
|
||||||
if (current) {
|
if (current) {
|
||||||
|
if (rendererWindow->hasBlitFunc()) {
|
||||||
|
while (directBlitting) {}
|
||||||
|
disconnect(this, &RendererStack::blit, this, &RendererStack::blitRenderer);
|
||||||
|
video_blit_complete();
|
||||||
|
}
|
||||||
rendererWindow->finalize();
|
rendererWindow->finalize();
|
||||||
|
|
||||||
removeWidget(current.get());
|
removeWidget(current.get());
|
||||||
disconnect(this, &RendererStack::blitToRenderer, nullptr, nullptr);
|
disconnect(this, &RendererStack::blitToRenderer, nullptr, nullptr);
|
||||||
|
|
||||||
/* Create new renderer only after previous is destroyed! */
|
/* Create new renderer only after previous is destroyed! */
|
||||||
connect(current.get(), &QObject::destroyed, [this, renderer](QObject *) { createRenderer(renderer); });
|
connect(current.get(), &QObject::destroyed, [this, renderer](QObject *) { video_blit_complete(); createRenderer(renderer); video_blit_complete(); });
|
||||||
|
|
||||||
current.release()->deleteLater();
|
current.release()->deleteLater();
|
||||||
} else {
|
} else {
|
||||||
@@ -292,6 +301,31 @@ RendererStack::createRenderer(Renderer renderer)
|
|||||||
current.reset(this->createWindowContainer(hw, this));
|
current.reset(this->createWindowContainer(hw, this));
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
#ifdef Q_OS_WIN
|
||||||
|
case Renderer::Direct3D9:
|
||||||
|
{
|
||||||
|
this->createWinId();
|
||||||
|
auto hw = new D3D9Renderer(this);
|
||||||
|
rendererWindow = hw;
|
||||||
|
connect(hw, &D3D9Renderer::error, this, [this](QString str)
|
||||||
|
{
|
||||||
|
auto msgBox = new QMessageBox(QMessageBox::Critical, "86Box", QString("Failed to initialize D3D9 renderer. Falling back to software rendering.\n\n") + str, QMessageBox::Ok);
|
||||||
|
msgBox->setAttribute(Qt::WA_DeleteOnClose);
|
||||||
|
msgBox->show();
|
||||||
|
imagebufs = {};
|
||||||
|
endblit();
|
||||||
|
QTimer::singleShot(0, this, [this]() { switchRenderer(Renderer::Software); });
|
||||||
|
});
|
||||||
|
connect(hw, &D3D9Renderer::initialized, this, [this]()
|
||||||
|
{
|
||||||
|
qDebug() << "initialized";
|
||||||
|
endblit();
|
||||||
|
emit rendererChanged();
|
||||||
|
});
|
||||||
|
current.reset(hw);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
#if QT_CONFIG(vulkan)
|
#if QT_CONFIG(vulkan)
|
||||||
case Renderer::Vulkan:
|
case Renderer::Vulkan:
|
||||||
{
|
{
|
||||||
@@ -340,16 +374,31 @@ RendererStack::createRenderer(Renderer renderer)
|
|||||||
|
|
||||||
currentBuf = 0;
|
currentBuf = 0;
|
||||||
|
|
||||||
if (renderer != Renderer::OpenGL3 && renderer != Renderer::Vulkan) {
|
if (rendererWindow->hasBlitFunc()) {
|
||||||
|
connect(this, &RendererStack::blit, this, &RendererStack::blitRenderer, Qt::DirectConnection);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
connect(this, &RendererStack::blit, this, &RendererStack::blitCommon, Qt::DirectConnection);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (renderer != Renderer::OpenGL3 && renderer != Renderer::Vulkan && renderer != Renderer::Direct3D9) {
|
||||||
imagebufs = rendererWindow->getBuffers();
|
imagebufs = rendererWindow->getBuffers();
|
||||||
endblit();
|
endblit();
|
||||||
emit rendererChanged();
|
emit rendererChanged();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
RendererStack::blitRenderer(int x, int y, int w, int h)
|
||||||
|
{
|
||||||
|
directBlitting = true;
|
||||||
|
rendererWindow->blit(x, y, w, h);
|
||||||
|
directBlitting = false;
|
||||||
|
}
|
||||||
|
|
||||||
// called from blitter thread
|
// called from blitter thread
|
||||||
void
|
void
|
||||||
RendererStack::blit(int x, int y, int w, int h)
|
RendererStack::blitCommon(int x, int y, int w, int h)
|
||||||
{
|
{
|
||||||
if ((x < 0) || (y < 0) || (w <= 0) || (h <= 0) || (w > 2048) || (h > 2048) || (buffer32 == NULL) || imagebufs.empty() || std::get<std::atomic_flag *>(imagebufs[currentBuf])->test_and_set()) {
|
if ((x < 0) || (y < 0) || (w <= 0) || (h <= 0) || (w > 2048) || (h > 2048) || (buffer32 == NULL) || imagebufs.empty() || std::get<std::atomic_flag *>(imagebufs[currentBuf])->test_and_set()) {
|
||||||
video_blit_complete();
|
video_blit_complete();
|
||||||
|
@@ -45,7 +45,8 @@ public:
|
|||||||
OpenGL,
|
OpenGL,
|
||||||
OpenGLES,
|
OpenGLES,
|
||||||
OpenGL3,
|
OpenGL3,
|
||||||
Vulkan
|
Vulkan,
|
||||||
|
Direct3D9
|
||||||
};
|
};
|
||||||
void switchRenderer(Renderer renderer);
|
void switchRenderer(Renderer renderer);
|
||||||
|
|
||||||
@@ -72,10 +73,12 @@ public:
|
|||||||
|
|
||||||
signals:
|
signals:
|
||||||
void blitToRenderer(int buf_idx, int x, int y, int w, int h);
|
void blitToRenderer(int buf_idx, int x, int y, int w, int h);
|
||||||
|
void blit(int x, int y, int w, int h);
|
||||||
void rendererChanged();
|
void rendererChanged();
|
||||||
|
|
||||||
public slots:
|
public slots:
|
||||||
void blit(int x, int y, int w, int h);
|
void blitCommon(int x, int y, int w, int h);
|
||||||
|
void blitRenderer(int x, int y, int w, int h);
|
||||||
void mousePoll();
|
void mousePoll();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
@@ -98,6 +101,7 @@ private:
|
|||||||
|
|
||||||
RendererCommon *rendererWindow { nullptr };
|
RendererCommon *rendererWindow { nullptr };
|
||||||
std::unique_ptr<QWidget> current;
|
std::unique_ptr<QWidget> current;
|
||||||
|
std::atomic<bool> directBlitting{false};
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // QT_RENDERERCONTAINER_HPP
|
#endif // QT_RENDERERCONTAINER_HPP
|
||||||
|
Reference in New Issue
Block a user