aboutsummaryrefslogtreecommitdiff
path: root/src/frontend
diff options
context:
space:
mode:
authorArisotura <thetotalworm@gmail.com>2023-12-28 14:40:37 +0100
committerArisotura <thetotalworm@gmail.com>2023-12-28 14:40:37 +0100
commit345b7439e41e57d159befc8fc2546f184dc10fc0 (patch)
treebf8ce9c54445880fde6a0ba5f05b21c0b871155e /src/frontend
parentfa835ecf68910baa9bc355be4c4eb1dc66e65b0f (diff)
integrate OSD into ScreenPanel and make it nicer
Diffstat (limited to 'src/frontend')
-rw-r--r--src/frontend/qt_sdl/CMakeLists.txt1
-rw-r--r--src/frontend/qt_sdl/EmuThread.cpp15
-rw-r--r--src/frontend/qt_sdl/OSD.cpp475
-rw-r--r--src/frontend/qt_sdl/OSD.h39
-rw-r--r--src/frontend/qt_sdl/Platform.cpp11
-rw-r--r--src/frontend/qt_sdl/Screen.cpp566
-rw-r--r--src/frontend/qt_sdl/Screen.h112
-rw-r--r--src/frontend/qt_sdl/Window.cpp23
-rw-r--r--src/frontend/qt_sdl/Window.h6
-rw-r--r--src/frontend/qt_sdl/main.cpp1
10 files changed, 540 insertions, 709 deletions
diff --git a/src/frontend/qt_sdl/CMakeLists.txt b/src/frontend/qt_sdl/CMakeLists.txt
index 9281021..8eeb44a 100644
--- a/src/frontend/qt_sdl/CMakeLists.txt
+++ b/src/frontend/qt_sdl/CMakeLists.txt
@@ -32,7 +32,6 @@ set(SOURCES_QT_SDL
LAN_PCap.cpp
LAN_Socket.cpp
LocalMP.cpp
- OSD.cpp
OSD_shaders.h
font.h
Platform.cpp
diff --git a/src/frontend/qt_sdl/EmuThread.cpp b/src/frontend/qt_sdl/EmuThread.cpp
index f86d30b..4a75387 100644
--- a/src/frontend/qt_sdl/EmuThread.cpp
+++ b/src/frontend/qt_sdl/EmuThread.cpp
@@ -36,7 +36,6 @@
#include "version.h"
#include "FrontendUtil.h"
-#include "OSD.h"
#include "Args.h"
#include "NDS.h"
@@ -80,7 +79,7 @@ EmuThread::EmuThread(QObject* parent) : QThread(parent)
EmuPauseStack = EmuPauseStackRunning;
RunningSomething = false;
- connect(this, SIGNAL(windowUpdate()), mainWindow->panelWidget, SLOT(repaint()));
+ connect(this, SIGNAL(windowUpdate()), mainWindow->panel, SLOT(repaint()));
connect(this, SIGNAL(windowTitleChange(QString)), mainWindow, SLOT(onTitleUpdate(QString)));
connect(this, SIGNAL(windowEmuStart()), mainWindow, SLOT(onEmuStart()));
connect(this, SIGNAL(windowEmuStop()), mainWindow, SLOT(onEmuStop()));
@@ -88,7 +87,7 @@ EmuThread::EmuThread(QObject* parent) : QThread(parent)
connect(this, SIGNAL(windowEmuReset()), mainWindow->actReset, SLOT(trigger()));
connect(this, SIGNAL(windowEmuFrameStep()), mainWindow->actFrameStep, SLOT(trigger()));
connect(this, SIGNAL(windowLimitFPSChange()), mainWindow->actLimitFramerate, SLOT(trigger()));
- connect(this, SIGNAL(screenLayoutChange()), mainWindow->panelWidget, SLOT(onScreenLayoutChanged()));
+ connect(this, SIGNAL(screenLayoutChange()), mainWindow->panel, SLOT(onScreenLayoutChanged()));
connect(this, SIGNAL(windowFullscreenToggle()), mainWindow, SLOT(onFullscreenToggled()));
connect(this, SIGNAL(swapScreensToggle()), mainWindow->actScreenSwap, SLOT(trigger()));
connect(this, SIGNAL(screenEmphasisToggle()), mainWindow, SLOT(onScreenEmphasisToggled()));
@@ -386,9 +385,7 @@ void EmuThread::run()
int level = NDS->GBACartSlot.SetInput(GBACart::Input_SolarSensorDown, true);
if (level != -1)
{
- char msg[64];
- sprintf(msg, "Solar sensor level: %d", level);
- OSD::AddMessage(0, msg);
+ mainWindow->osdAddMessage(0, "Solar sensor level: %d", level);
}
}
if (Input::HotkeyPressed(HK_SolarSensorIncrease))
@@ -396,9 +393,7 @@ void EmuThread::run()
int level = NDS->GBACartSlot.SetInput(GBACart::Input_SolarSensorUp, true);
if (level != -1)
{
- char msg[64];
- sprintf(msg, "Solar sensor level: %d", level);
- OSD::AddMessage(0, msg);
+ mainWindow->osdAddMessage(0, "Solar sensor level: %d", level);
}
}
@@ -480,7 +475,7 @@ void EmuThread::run()
{
bool lid = !NDS->IsLidClosed();
NDS->SetLidClosed(lid);
- OSD::AddMessage(0, lid ? "Lid closed" : "Lid opened");
+ mainWindow->osdAddMessage(0, lid ? "Lid closed" : "Lid opened");
}
// microphone input
diff --git a/src/frontend/qt_sdl/OSD.cpp b/src/frontend/qt_sdl/OSD.cpp
deleted file mode 100644
index 3734b76..0000000
--- a/src/frontend/qt_sdl/OSD.cpp
+++ /dev/null
@@ -1,475 +0,0 @@
-/*
- Copyright 2016-2023 melonDS team
-
- This file is part of melonDS.
-
- melonDS is free software: you can redistribute it and/or modify it under
- the terms of the GNU General Public License as published by the Free
- Software Foundation, either version 3 of the License, or (at your option)
- any later version.
-
- melonDS is distributed in the hope that it will be useful, but WITHOUT ANY
- WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
- FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
-
- You should have received a copy of the GNU General Public License along
- with melonDS. If not, see http://www.gnu.org/licenses/.
-*/
-
-#include <stdio.h>
-#include <string.h>
-#include <deque>
-#include <SDL2/SDL.h>
-#include "../types.h"
-
-#include "main.h"
-#include "OpenGLSupport.h"
-#include <QPainter>
-
-#include "OSD.h"
-#include "OSD_shaders.h"
-#include "font.h"
-
-#include "Config.h"
-
-using namespace melonDS;
-
-extern MainWindow* mainWindow;
-
-namespace OSD
-{
-
-const u32 kOSDMargin = 6;
-
-struct Item
-{
- Uint32 Timestamp;
- char Text[256];
- u32 Color;
-
- u32 Width, Height;
- u32* Bitmap;
-
- bool NativeBitmapLoaded;
- QImage NativeBitmap;
-
- bool GLTextureLoaded;
- GLuint GLTexture;
-};
-
-std::deque<Item> ItemQueue;
-
-GLuint Shader[3];
-GLint uScreenSize, uOSDPos, uOSDSize;
-GLfloat uScaleFactor;
-GLuint OSDVertexArray;
-GLuint OSDVertexBuffer;
-
-QMutex Rendering;
-
-
-bool Init(bool openGL)
-{
- if (openGL)
- {
- OpenGL::BuildShaderProgram(kScreenVS_OSD, kScreenFS_OSD, Shader, "OSDShader");
-
- GLuint pid = Shader[2];
- glBindAttribLocation(pid, 0, "vPosition");
- glBindFragDataLocation(pid, 0, "oColor");
-
- OpenGL::LinkShaderProgram(Shader);
- glUseProgram(pid);
- glUniform1i(glGetUniformLocation(pid, "OSDTex"), 0);
-
- uScreenSize = glGetUniformLocation(pid, "uScreenSize");
- uOSDPos = glGetUniformLocation(pid, "uOSDPos");
- uOSDSize = glGetUniformLocation(pid, "uOSDSize");
- uScaleFactor = glGetUniformLocation(pid, "uScaleFactor");
-
- float vertices[6*2] =
- {
- 0, 0,
- 1, 1,
- 1, 0,
- 0, 0,
- 0, 1,
- 1, 1
- };
-
- glGenBuffers(1, &OSDVertexBuffer);
- glBindBuffer(GL_ARRAY_BUFFER, OSDVertexBuffer);
- glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW);
-
- glGenVertexArrays(1, &OSDVertexArray);
- glBindVertexArray(OSDVertexArray);
- glEnableVertexAttribArray(0); // position
- glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, 0, (void*)(0));
- }
-
- return true;
-}
-
-void DeInit()
-{
- for (auto it = ItemQueue.begin(); it != ItemQueue.end(); )
- {
- Item& item = *it;
-
- if (item.GLTextureLoaded) glDeleteTextures(1, &item.GLTexture);
- if (item.Bitmap) delete[] item.Bitmap;
-
- it = ItemQueue.erase(it);
- }
-}
-
-
-int FindBreakPoint(const char* text, int i)
-{
- // i = character that went out of bounds
-
- for (int j = i; j >= 0; j--)
- {
- if (text[j] == ' ')
- return j;
- }
-
- return i;
-}
-
-void LayoutText(const char* text, u32* width, u32* height, int* breaks)
-{
- u32 w = 0;
- u32 h = 14;
- u32 totalw = 0;
- u32 maxw = mainWindow->panelWidget->width() - (kOSDMargin*2);
- int lastbreak = -1;
- int numbrk = 0;
- u16* ptr;
-
- memset(breaks, 0, sizeof(int)*64);
-
- for (int i = 0; text[i] != '\0'; )
- {
- int glyphsize;
- if (text[i] == ' ')
- {
- glyphsize = 6;
- }
- else
- {
- u32 ch = text[i];
- if (ch < 0x10 || ch > 0x7E) ch = 0x7F;
-
- ptr = &font[(ch-0x10) << 4];
- glyphsize = ptr[0];
- if (!glyphsize) glyphsize = 6;
- else glyphsize += 2; // space around the character
- }
-
- w += glyphsize;
- if (w > maxw)
- {
- // wrap shit as needed
- if (text[i] == ' ')
- {
- if (numbrk >= 64) break;
- breaks[numbrk++] = i;
- i++;
- }
- else
- {
- int brk = FindBreakPoint(text, i);
- if (brk != lastbreak) i = brk;
-
- if (numbrk >= 64) break;
- breaks[numbrk++] = i;
-
- lastbreak = brk;
- }
-
- w = 0;
- h += 14;
- }
- else
- i++;
-
- if (w > totalw) totalw = w;
- }
-
- *width = totalw;
- *height = h;
-}
-
-u32 RainbowColor(u32 inc)
-{
- // inspired from Acmlmboard
-
- if (inc < 100) return 0xFFFF9B9B + (inc << 8);
- else if (inc < 200) return 0xFFFFFF9B - ((inc-100) << 16);
- else if (inc < 300) return 0xFF9BFF9B + (inc-200);
- else if (inc < 400) return 0xFF9BFFFF - ((inc-300) << 8);
- else if (inc < 500) return 0xFF9B9BFF + ((inc-400) << 16);
- else return 0xFFFF9BFF - (inc-500);
-}
-
-void RenderText(u32 color, const char* text, Item* item)
-{
- u32 w, h;
- int breaks[64];
-
- bool rainbow = (color == 0);
- u32 rainbowinc = ((text[0] * 17) + (SDL_GetTicks() * 13)) % 600;
-
- color |= 0xFF000000;
- const u32 shadow = 0xE0000000;
-
- LayoutText(text, &w, &h, breaks);
-
- item->Width = w;
- item->Height = h;
- item->Bitmap = new u32[w*h];
- memset(item->Bitmap, 0, w*h*sizeof(u32));
-
- u32 x = 0, y = 1;
- u32 maxw = mainWindow->panelWidget->width() - (kOSDMargin*2);
- int curline = 0;
- u16* ptr;
-
- for (int i = 0; text[i] != '\0'; )
- {
- int glyphsize;
- if (text[i] == ' ')
- {
- x += 6;
- }
- else
- {
- u32 ch = text[i];
- if (ch < 0x10 || ch > 0x7E) ch = 0x7F;
-
- ptr = &font[(ch-0x10) << 4];
- int glyphsize = ptr[0];
- if (!glyphsize) x += 6;
- else
- {
- x++;
-
- if (rainbow)
- {
- color = RainbowColor(rainbowinc);
- rainbowinc = (rainbowinc + 30) % 600;
- }
-
- // draw character
- for (int cy = 0; cy < 12; cy++)
- {
- u16 val = ptr[4+cy];
-
- for (int cx = 0; cx < glyphsize; cx++)
- {
- if (val & (1<<cx))
- item->Bitmap[((y+cy) * w) + x+cx] = color;
- }
- }
-
- x += glyphsize;
- x++;
- }
- }
-
- i++;
- if (breaks[curline] && i >= breaks[curline])
- {
- i = breaks[curline++];
- if (text[i] == ' ') i++;
-
- x = 0;
- y += 14;
- }
- }
-
- // shadow
- for (y = 0; y < h; y++)
- {
- for (x = 0; x < w; x++)
- {
- u32 val;
-
- val = item->Bitmap[(y * w) + x];
- if ((val >> 24) == 0xFF) continue;
-
- if (x > 0) val = item->Bitmap[(y * w) + x-1];
- if (x < w-1) val |= item->Bitmap[(y * w) + x+1];
- if (y > 0)
- {
- if (x > 0) val |= item->Bitmap[((y-1) * w) + x-1];
- val |= item->Bitmap[((y-1) * w) + x];
- if (x < w-1) val |= item->Bitmap[((y-1) * w) + x+1];
- }
- if (y < h-1)
- {
- if (x > 0) val |= item->Bitmap[((y+1) * w) + x-1];
- val |= item->Bitmap[((y+1) * w) + x];
- if (x < w-1) val |= item->Bitmap[((y+1) * w) + x+1];
- }
-
- if ((val >> 24) == 0xFF)
- item->Bitmap[(y * w) + x] = shadow;
- }
- }
-}
-
-
-void AddMessage(u32 color, const char* text)
-{
- if (!Config::ShowOSD) return;
-
- Rendering.lock();
-
- Item item;
-
- item.Timestamp = SDL_GetTicks();
- strncpy(item.Text, text, 255); item.Text[255] = '\0';
- item.Color = color;
- item.Bitmap = nullptr;
-
- item.NativeBitmapLoaded = false;
- item.GLTextureLoaded = false;
-
- ItemQueue.push_back(item);
-
- Rendering.unlock();
-}
-
-void Update()
-{
- if (!Config::ShowOSD)
- {
- Rendering.lock();
- for (auto it = ItemQueue.begin(); it != ItemQueue.end(); )
- {
- Item& item = *it;
-
- if (item.GLTextureLoaded) glDeleteTextures(1, &item.GLTexture);
- if (item.Bitmap) delete[] item.Bitmap;
-
- it = ItemQueue.erase(it);
- }
- Rendering.unlock();
- return;
- }
-
- Rendering.lock();
-
- Uint32 tick_now = SDL_GetTicks();
- Uint32 tick_min = tick_now - 2500;
-
- for (auto it = ItemQueue.begin(); it != ItemQueue.end(); )
- {
- Item& item = *it;
-
- if (item.Timestamp < tick_min)
- {
- if (item.GLTextureLoaded) glDeleteTextures(1, &item.GLTexture);
- if (item.Bitmap) delete[] item.Bitmap;
-
- it = ItemQueue.erase(it);
- continue;
- }
-
- if (!item.Bitmap)
- {
- RenderText(item.Color, item.Text, &item);
- }
-
- it++;
- }
-
- Rendering.unlock();
-}
-
-void DrawNative(QPainter& painter)
-{
- if (!Config::ShowOSD) return;
-
- Rendering.lock();
-
- u32 y = kOSDMargin;
-
- painter.resetTransform();
-
- for (auto it = ItemQueue.begin(); it != ItemQueue.end(); )
- {
- Item& item = *it;
-
- if (!item.NativeBitmapLoaded)
- {
- item.NativeBitmap = QImage((const uchar*)item.Bitmap, item.Width, item.Height, QImage::Format_ARGB32_Premultiplied);
- item.NativeBitmapLoaded = true;
- }
-
- painter.drawImage(kOSDMargin, y, item.NativeBitmap);
-
- y += item.Height;
- it++;
- }
-
- Rendering.unlock();
-}
-
-void DrawGL(float w, float h, float factor)
-{
- if (!Config::ShowOSD) return;
- if (!mainWindow || !mainWindow->panel) return;
-
- Rendering.lock();
-
- u32 y = kOSDMargin;
-
- glUseProgram(Shader[2]);
-
- glUniform2f(uScreenSize, w, h);
- glUniform1f(uScaleFactor, factor);
-
- glBindBuffer(GL_ARRAY_BUFFER, OSDVertexBuffer);
- glBindVertexArray(OSDVertexArray);
-
- glActiveTexture(GL_TEXTURE0);
-
- glEnable(GL_BLEND);
- glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA);
-
- for (auto it = ItemQueue.begin(); it != ItemQueue.end(); )
- {
- Item& item = *it;
-
- if (!item.GLTextureLoaded)
- {
- glGenTextures(1, &item.GLTexture);
- glBindTexture(GL_TEXTURE_2D, item.GLTexture);
- glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
- glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
- glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
- glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
- glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, item.Width, item.Height, 0, GL_RGBA, GL_UNSIGNED_BYTE, item.Bitmap);
-
- item.GLTextureLoaded = true;
- }
-
- glBindTexture(GL_TEXTURE_2D, item.GLTexture);
- glUniform2i(uOSDPos, kOSDMargin, y);
- glUniform2i(uOSDSize, item.Width, item.Height);
- glDrawArrays(GL_TRIANGLES, 0, 2*3);
-
- y += item.Height;
- it++;
- }
-
- glDisable(GL_BLEND);
- glUseProgram(0);
-
- Rendering.unlock();
-}
-
-}
diff --git a/src/frontend/qt_sdl/OSD.h b/src/frontend/qt_sdl/OSD.h
deleted file mode 100644
index c907a0b..0000000
--- a/src/frontend/qt_sdl/OSD.h
+++ /dev/null
@@ -1,39 +0,0 @@
-/*
- Copyright 2016-2023 melonDS team
-
- This file is part of melonDS.
-
- melonDS is free software: you can redistribute it and/or modify it under
- the terms of the GNU General Public License as published by the Free
- Software Foundation, either version 3 of the License, or (at your option)
- any later version.
-
- melonDS is distributed in the hope that it will be useful, but WITHOUT ANY
- WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
- FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
-
- You should have received a copy of the GNU General Public License along
- with melonDS. If not, see http://www.gnu.org/licenses/.
-*/
-
-#ifndef OSD_H
-#define OSD_H
-
-#include "types.h"
-
-namespace OSD
-{
-
-using namespace melonDS;
-bool Init(bool openGL);
-void DeInit();
-
-void AddMessage(u32 color, const char* text);
-
-void Update();
-void DrawNative(QPainter& painter);
-void DrawGL(float w, float h, float factor);
-
-}
-
-#endif // OSD_H
diff --git a/src/frontend/qt_sdl/Platform.cpp b/src/frontend/qt_sdl/Platform.cpp
index 6fe87ac..efd3340 100644
--- a/src/frontend/qt_sdl/Platform.cpp
+++ b/src/frontend/qt_sdl/Platform.cpp
@@ -39,7 +39,6 @@
#include "LAN_Socket.h"
#include "LAN_PCap.h"
#include "LocalMP.h"
-#include "OSD.h"
#include "SPI_Firmware.h"
#ifdef __WIN32__
@@ -53,6 +52,10 @@ extern CameraManager* camManager[2];
void emuStop();
+// TEMP
+//#include "main.h"
+//extern MainWindow* mainWindow;
+
namespace melonDS::Platform
{
@@ -177,14 +180,14 @@ void SignalStop(StopReason reason)
{
case StopReason::GBAModeNotSupported:
Log(LogLevel::Error, "!! GBA MODE NOT SUPPORTED\n");
- OSD::AddMessage(0xFFA0A0, "GBA mode not supported.");
+ //mainWindow->osdAddMessage(0xFFA0A0, "GBA mode not supported.");
break;
case StopReason::BadExceptionRegion:
- OSD::AddMessage(0xFFA0A0, "Internal error.");
+ //mainWindow->osdAddMessage(0xFFA0A0, "Internal error.");
break;
case StopReason::PowerOff:
case StopReason::External:
- OSD::AddMessage(0xFFC040, "Shutdown");
+ //mainWindow->osdAddMessage(0xFFC040, "Shutdown");
default:
break;
}
diff --git a/src/frontend/qt_sdl/Screen.cpp b/src/frontend/qt_sdl/Screen.cpp
index d8af662..cfcbeed 100644
--- a/src/frontend/qt_sdl/Screen.cpp
+++ b/src/frontend/qt_sdl/Screen.cpp
@@ -35,6 +35,7 @@
#include <qpa/qplatformnativeinterface.h>
#endif
#endif
+#include <QDateTime>
#include "OpenGLSupport.h"
#include "duckstation/gl/context.h"
@@ -49,8 +50,8 @@
#include "Config.h"
#include "main_shaders.h"
-
-#include "OSD.h"
+#include "OSD_shaders.h"
+#include "font.h"
using namespace melonDS;
@@ -64,23 +65,31 @@ extern int autoScreenSizing;
extern int videoRenderer;
extern bool videoSettingsDirty;
+const u32 kOSDMargin = 6;
+
-ScreenHandler::ScreenHandler(QWidget* widget)
+ScreenPanel::ScreenPanel(QWidget* parent) : QWidget(parent)
{
- widget->setMouseTracking(true);
- widget->setAttribute(Qt::WA_AcceptTouchEvents);
+ setMouseTracking(true);
+ setAttribute(Qt::WA_AcceptTouchEvents);
QTimer* mouseTimer = setupMouseTimer();
- widget->connect(mouseTimer, &QTimer::timeout, [=] { if (Config::MouseHide) widget->setCursor(Qt::BlankCursor);});
+ connect(mouseTimer, &QTimer::timeout, [=] { if (Config::MouseHide) setCursor(Qt::BlankCursor);});
+
+ osdEnabled = false;
+ osdID = 1;
}
-ScreenHandler::~ScreenHandler()
+ScreenPanel::~ScreenPanel()
{
mouseTimer->stop();
delete mouseTimer;
}
-void ScreenHandler::screenSetupLayout(int w, int h)
+void ScreenPanel::setupScreenLayout()
{
+ int w = width();
+ int h = height();
+
int sizing = Config::ScreenSizing;
if (sizing == 3) sizing = autoScreenSizing;
@@ -113,7 +122,7 @@ void ScreenHandler::screenSetupLayout(int w, int h)
numScreens = Frontend::GetScreenTransforms(screenMatrix[0], screenKind);
}
-QSize ScreenHandler::screenGetMinSize(int factor = 1)
+QSize ScreenPanel::screenGetMinSize(int factor = 1)
{
bool isHori = (Config::ScreenRotation == Frontend::screenRot_90Deg
|| Config::ScreenRotation == Frontend::screenRot_270Deg);
@@ -158,7 +167,19 @@ QSize ScreenHandler::screenGetMinSize(int factor = 1)
}
}
-void ScreenHandler::screenOnMousePress(QMouseEvent* event)
+void ScreenPanel::onScreenLayoutChanged()
+{
+ setMinimumSize(screenGetMinSize());
+ setupScreenLayout();
+}
+
+void ScreenPanel::resizeEvent(QResizeEvent* event)
+{
+ setupScreenLayout();
+ QWidget::resizeEvent(event);
+}
+
+void ScreenPanel::mousePressEvent(QMouseEvent* event)
{
event->accept();
if (event->button() != Qt::LeftButton) return;
@@ -174,7 +195,7 @@ void ScreenHandler::screenOnMousePress(QMouseEvent* event)
}
}
-void ScreenHandler::screenOnMouseRelease(QMouseEvent* event)
+void ScreenPanel::mouseReleaseEvent(QMouseEvent* event)
{
event->accept();
if (event->button() != Qt::LeftButton) return;
@@ -187,7 +208,7 @@ void ScreenHandler::screenOnMouseRelease(QMouseEvent* event)
}
}
-void ScreenHandler::screenOnMouseMove(QMouseEvent* event)
+void ScreenPanel::mouseMoveEvent(QMouseEvent* event)
{
event->accept();
@@ -206,7 +227,7 @@ void ScreenHandler::screenOnMouseMove(QMouseEvent* event)
}
}
-void ScreenHandler::screenHandleTablet(QTabletEvent* event)
+void ScreenPanel::tabletEvent(QTabletEvent* event)
{
event->accept();
@@ -239,7 +260,7 @@ void ScreenHandler::screenHandleTablet(QTabletEvent* event)
}
}
-void ScreenHandler::screenHandleTouch(QTouchEvent* event)
+void ScreenPanel::touchEvent(QTouchEvent* event)
{
event->accept();
@@ -274,13 +295,26 @@ void ScreenHandler::screenHandleTouch(QTouchEvent* event)
}
}
-void ScreenHandler::showCursor()
+bool ScreenPanel::event(QEvent* event)
+{
+ if (event->type() == QEvent::TouchBegin
+ || event->type() == QEvent::TouchEnd
+ || event->type() == QEvent::TouchUpdate)
+ {
+ touchEvent((QTouchEvent*)event);
+ return true;
+ }
+
+ return QWidget::event(event);
+}
+
+void ScreenPanel::showCursor()
{
- mainWindow->panelWidget->setCursor(Qt::ArrowCursor);
+ mainWindow->panel->setCursor(Qt::ArrowCursor);
mouseTimer->start();
}
-QTimer* ScreenHandler::setupMouseTimer()
+QTimer* ScreenPanel::setupMouseTimer()
{
mouseTimer = new QTimer();
mouseTimer->setSingleShot(true);
@@ -290,35 +324,290 @@ QTimer* ScreenHandler::setupMouseTimer()
return mouseTimer;
}
-ScreenPanelNative::ScreenPanelNative(QWidget* parent) : QWidget(parent), ScreenHandler(this)
+int ScreenPanel::osdFindBreakPoint(const char* text, int i)
+{
+ // i = character that went out of bounds
+
+ for (int j = i; j >= 0; j--)
+ {
+ if (text[j] == ' ')
+ return j;
+ }
+
+ return i;
+}
+
+void ScreenPanel::osdLayoutText(const char* text, int* width, int* height, int* breaks)
+{
+ int w = 0;
+ int h = 14;
+ int totalw = 0;
+ int maxw = ((QWidget*)this)->width() - (kOSDMargin*2);
+ int lastbreak = -1;
+ int numbrk = 0;
+ u16* ptr;
+
+ memset(breaks, 0, sizeof(int)*64);
+
+ for (int i = 0; text[i] != '\0'; )
+ {
+ int glyphsize;
+ if (text[i] == ' ')
+ {
+ glyphsize = 6;
+ }
+ else
+ {
+ u32 ch = text[i];
+ if (ch < 0x10 || ch > 0x7E) ch = 0x7F;
+
+ ptr = &::font[(ch-0x10) << 4];
+ glyphsize = ptr[0];
+ if (!glyphsize) glyphsize = 6;
+ else glyphsize += 2; // space around the character
+ }
+
+ w += glyphsize;
+ if (w > maxw)
+ {
+ // wrap shit as needed
+ if (text[i] == ' ')
+ {
+ if (numbrk >= 64) break;
+ breaks[numbrk++] = i;
+ i++;
+ }
+ else
+ {
+ int brk = osdFindBreakPoint(text, i);
+ if (brk != lastbreak) i = brk;
+
+ if (numbrk >= 64) break;
+ breaks[numbrk++] = i;
+
+ lastbreak = brk;
+ }
+
+ w = 0;
+ h += 14;
+ }
+ else
+ i++;
+
+ if (w > totalw) totalw = w;
+ }
+
+ *width = totalw;
+ *height = h;
+}
+
+unsigned int ScreenPanel::osdRainbowColor(int inc)
+{
+ // inspired from Acmlmboard
+
+ if (inc < 100) return 0xFFFF9B9B + (inc << 8);
+ else if (inc < 200) return 0xFFFFFF9B - ((inc-100) << 16);
+ else if (inc < 300) return 0xFF9BFF9B + (inc-200);
+ else if (inc < 400) return 0xFF9BFFFF - ((inc-300) << 8);
+ else if (inc < 500) return 0xFF9B9BFF + ((inc-400) << 16);
+ else return 0xFFFF9BFF - (inc-500);
+}
+
+void ScreenPanel::osdRenderItem(OSDItem* item)
+{
+ int w, h;
+ int breaks[64];
+
+ char* text = item->text;
+ u32 color = item->color;
+
+ bool rainbow = (color == 0);
+ u32 ticks = (u32)QDateTime::currentMSecsSinceEpoch();
+ u32 rainbowinc = ((text[0] * 17) + (ticks * 13)) % 600;
+
+ color |= 0xFF000000;
+ const u32 shadow = 0xE0000000;
+
+ osdLayoutText(text, &w, &h, breaks);
+
+ item->bitmap = QImage(w, h, QImage::Format_ARGB32_Premultiplied);
+ u32* bitmap = (u32*)item->bitmap.bits();
+ memset(bitmap, 0, w*h*sizeof(u32));
+
+ int x = 0, y = 1;
+ u32 maxw = ((QWidget*)this)->width() - (kOSDMargin*2);
+ int curline = 0;
+ u16* ptr;
+
+ for (int i = 0; text[i] != '\0'; )
+ {
+ int glyphsize;
+ if (text[i] == ' ')
+ {
+ x += 6;
+ }
+ else
+ {
+ u32 ch = text[i];
+ if (ch < 0x10 || ch > 0x7E) ch = 0x7F;
+
+ ptr = &::font[(ch-0x10) << 4];
+ int glyphsize = ptr[0];
+ if (!glyphsize) x += 6;
+ else
+ {
+ x++;
+
+ if (rainbow)
+ {
+ color = osdRainbowColor(rainbowinc);
+ rainbowinc = (rainbowinc + 30) % 600;
+ }
+
+ // draw character
+ for (int cy = 0; cy < 12; cy++)
+ {
+ u16 val = ptr[4+cy];
+
+ for (int cx = 0; cx < glyphsize; cx++)
+ {
+ if (val & (1<<cx))
+ bitmap[((y+cy) * w) + x+cx] = color;
+ }
+ }
+
+ x += glyphsize;
+ x++;
+ }
+ }
+
+ i++;
+ if (breaks[curline] && i >= breaks[curline])
+ {
+ i = breaks[curline++];
+ if (text[i] == ' ') i++;
+
+ x = 0;
+ y += 14;
+ }
+ }
+
+ // shadow
+ for (y = 0; y < h; y++)
+ {
+ for (x = 0; x < w; x++)
+ {
+ u32 val;
+
+ val = bitmap[(y * w) + x];
+ if ((val >> 24) == 0xFF) continue;
+
+ if (x > 0) val = bitmap[(y * w) + x-1];
+ if (x < w-1) val |= bitmap[(y * w) + x+1];
+ if (y > 0)
+ {
+ if (x > 0) val |= bitmap[((y-1) * w) + x-1];
+ val |= bitmap[((y-1) * w) + x];
+ if (x < w-1) val |= bitmap[((y-1) * w) + x+1];
+ }
+ if (y < h-1)
+ {
+ if (x > 0) val |= bitmap[((y+1) * w) + x-1];
+ val |= bitmap[((y+1) * w) + x];
+ if (x < w-1) val |= bitmap[((y+1) * w) + x+1];
+ }
+
+ if ((val >> 24) == 0xFF)
+ bitmap[(y * w) + x] = shadow;
+ }
+ }
+}
+
+void ScreenPanel::osdDeleteItem(OSDItem* item)
+{
+}
+
+void ScreenPanel::osdSetEnabled(bool enabled)
+{
+ osdMutex.lock();
+ osdEnabled = enabled;
+ osdMutex.unlock();
+}
+
+void ScreenPanel::osdAddMessage(unsigned int color, const char* text)
+{
+ if (!osdEnabled) return;
+
+ osdMutex.lock();
+
+ OSDItem item;
+
+ item.id = osdID++;
+ item.timestamp = QDateTime::currentMSecsSinceEpoch();
+ strncpy(item.text, text, 255); item.text[255] = '\0';
+ item.color = color;
+ item.rendered = false;
+
+ osdItems.push_back(item);
+
+ osdMutex.unlock();
+}
+
+void ScreenPanel::osdUpdate()
+{
+ osdMutex.lock();
+
+ qint64 tick_now = QDateTime::currentMSecsSinceEpoch();
+ qint64 tick_min = tick_now - 2500;
+
+ for (auto it = osdItems.begin(); it != osdItems.end(); )
+ {
+ OSDItem& item = *it;
+
+ if ((!osdEnabled) || (item.timestamp < tick_min))
+ {
+ osdDeleteItem(&item);
+ it = osdItems.erase(it);
+ continue;
+ }
+
+ if (!item.rendered)
+ {
+ osdRenderItem(&item);
+ item.rendered = true;
+ }
+
+ it++;
+ }
+
+ osdMutex.unlock();
+}
+
+
+
+ScreenPanelNative::ScreenPanelNative(QWidget* parent) : ScreenPanel(parent)
{
screen[0] = QImage(256, 192, QImage::Format_RGB32);
screen[1] = QImage(256, 192, QImage::Format_RGB32);
screenTrans[0].reset();
screenTrans[1].reset();
-
- OSD::Init(false);
}
ScreenPanelNative::~ScreenPanelNative()
{
- OSD::DeInit();
}
void ScreenPanelNative::setupScreenLayout()
{
- int w = width();
- int h = height();
-
- screenSetupLayout(w, h);
+ ScreenPanel::setupScreenLayout();
for (int i = 0; i < numScreens; i++)
{
float* mtx = screenMatrix[i];
screenTrans[i].setMatrix(mtx[0], mtx[1], 0.f,
- mtx[2], mtx[3], 0.f,
- mtx[4], mtx[5], 1.f);
+ mtx[2], mtx[3], 0.f,
+ mtx[4], mtx[5], 1.f);
}
}
@@ -353,55 +642,32 @@ void ScreenPanelNative::paintEvent(QPaintEvent* event)
}
}
- OSD::Update();
- OSD::DrawNative(painter);
-}
+ osdUpdate();
+ if (osdEnabled)
+ {
+ osdMutex.lock();
-void ScreenPanelNative::resizeEvent(QResizeEvent* event)
-{
- setupScreenLayout();
-}
+ u32 y = kOSDMargin;
-void ScreenPanelNative::mousePressEvent(QMouseEvent* event)
-{
- screenOnMousePress(event);
-}
+ painter.resetTransform();
-void ScreenPanelNative::mouseReleaseEvent(QMouseEvent* event)
-{
- screenOnMouseRelease(event);
-}
+ for (auto it = osdItems.begin(); it != osdItems.end(); )
+ {
+ OSDItem& item = *it;
-void ScreenPanelNative::mouseMoveEvent(QMouseEvent* event)
-{
- screenOnMouseMove(event);
-}
+ painter.drawImage(kOSDMargin, y, item.bitmap);
-void ScreenPanelNative::tabletEvent(QTabletEvent* event)
-{
- screenHandleTablet(event);
-}
+ y += item.bitmap.height();
+ it++;
+ }
-bool ScreenPanelNative::event(QEvent* event)
-{
- if (event->type() == QEvent::TouchBegin
- || event->type() == QEvent::TouchEnd
- || event->type() == QEvent::TouchUpdate)
- {
- screenHandleTouch((QTouchEvent*)event);
- return true;
+ osdMutex.unlock();
}
- return QWidget::event(event);
}
-void ScreenPanelNative::onScreenLayoutChanged()
-{
- setMinimumSize(screenGetMinSize());
- setupScreenLayout();
-}
-ScreenPanelGL::ScreenPanelGL(QWidget* parent) : QWidget(parent), ScreenHandler(this)
+ScreenPanelGL::ScreenPanelGL(QWidget* parent) : ScreenPanel(parent)
{
setAutoFillBackground(false);
setAttribute(Qt::WA_NativeWindow, true);
@@ -503,7 +769,41 @@ void ScreenPanelGL::initOpenGL()
memset(zeroData, 0, sizeof(zeroData));
glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 192, 256, 2, GL_RGBA, GL_UNSIGNED_BYTE, zeroData);
- OSD::Init(true);
+
+ OpenGL::BuildShaderProgram(kScreenVS_OSD, kScreenFS_OSD, osdShader, "OSDShader");
+
+ pid = osdShader[2];
+ glBindAttribLocation(pid, 0, "vPosition");
+ glBindFragDataLocation(pid, 0, "oColor");
+
+ OpenGL::LinkShaderProgram(osdShader);
+ glUseProgram(pid);
+ glUniform1i(glGetUniformLocation(pid, "OSDTex"), 0);
+
+ osdScreenSizeULoc = glGetUniformLocation(pid, "uScreenSize");
+ osdPosULoc = glGetUniformLocation(pid, "uOSDPos");
+ osdSizeULoc = glGetUniformLocation(pid, "uOSDSize");
+ osdScaleFactorULoc = glGetUniformLocation(pid, "uScaleFactor");
+
+ const float osdvertices[6*2] =
+ {
+ 0, 0,
+ 1, 1,
+ 1, 0,
+ 0, 0,
+ 0, 1,
+ 1, 1
+ };
+
+ glGenBuffers(1, &osdVertexBuffer);
+ glBindBuffer(GL_ARRAY_BUFFER, osdVertexBuffer);
+ glBufferData(GL_ARRAY_BUFFER, sizeof(osdvertices), osdvertices, GL_STATIC_DRAW);
+
+ glGenVertexArrays(1, &osdVertexArray);
+ glBindVertexArray(osdVertexArray);
+ glEnableVertexAttribArray(0); // position
+ glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, 0, (void*)(0));
+
glContext->SetSwapInterval(Config::ScreenVSync ? Config::ScreenVSyncInterval : 0);
transferLayout();
@@ -520,13 +820,52 @@ void ScreenPanelGL::deinitOpenGL()
OpenGL::DeleteShaderProgram(screenShaderProgram);
- OSD::DeInit();
+
+ for (const auto& [key, tex] : osdTextures)
+ {
+ glDeleteTextures(1, &tex);
+ }
+ osdTextures.clear();
+
+ glDeleteVertexArrays(1, &osdVertexArray);
+ glDeleteBuffers(1, &osdVertexBuffer);
+
+ OpenGL::DeleteShaderProgram(osdShader);
+
glContext->DoneCurrent();
lastScreenWidth = lastScreenHeight = -1;
}
+void ScreenPanelGL::osdRenderItem(OSDItem* item)
+{
+ ScreenPanel::osdRenderItem(item);
+
+ GLuint tex;
+ glGenTextures(1, &tex);
+ glBindTexture(GL_TEXTURE_2D, tex);
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
+ glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, item->bitmap.width(), item->bitmap.height(), 0, GL_RGBA, GL_UNSIGNED_BYTE, item->bitmap.bits());
+
+ osdTextures[item->id] = tex;
+}
+
+void ScreenPanelGL::osdDeleteItem(OSDItem* item)
+{
+ if (osdTextures.count(item->id))
+ {
+ GLuint tex = osdTextures[item->id];
+ glDeleteTextures(1, &tex);
+ osdTextures.erase(item->id);
+ }
+
+ ScreenPanel::osdDeleteItem(item);
+}
+
void ScreenPanelGL::drawScreenGL()
{
if (!glContext) return;
@@ -590,8 +929,47 @@ void ScreenPanelGL::drawScreenGL()
screenSettingsLock.unlock();
- OSD::Update();
- OSD::DrawGL(w, h, factor);
+ osdUpdate();
+ if (osdEnabled)
+ {
+ osdMutex.lock();
+
+ u32 y = kOSDMargin;
+
+ glUseProgram(osdShader[2]);
+
+ glUniform2f(osdScreenSizeULoc, w, h);
+ glUniform1f(osdScaleFactorULoc, factor);
+
+ glBindBuffer(GL_ARRAY_BUFFER, osdVertexBuffer);
+ glBindVertexArray(osdVertexArray);
+
+ glActiveTexture(GL_TEXTURE0);
+
+ glEnable(GL_BLEND);
+ glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA);
+
+ for (auto it = osdItems.begin(); it != osdItems.end(); )
+ {
+ OSDItem& item = *it;
+
+ if (!osdTextures.count(item.id))
+ continue;
+
+ glBindTexture(GL_TEXTURE_2D, osdTextures[item.id]);
+ glUniform2i(osdPosULoc, kOSDMargin, y);
+ glUniform2i(osdSizeULoc, item.bitmap.width(), item.bitmap.height());
+ glDrawArrays(GL_TRIANGLES, 0, 2*3);
+
+ y += item.bitmap.height();
+ it++;
+ }
+
+ glDisable(GL_BLEND);
+ glUseProgram(0);
+
+ osdMutex.unlock();
+ }
glContext->SwapBuffers();
}
@@ -667,52 +1045,10 @@ QPaintEngine* ScreenPanelGL::paintEngine() const
void ScreenPanelGL::setupScreenLayout()
{
- int w = width();
- int h = height();
-
- screenSetupLayout(w, h);
+ ScreenPanel::setupScreenLayout();
transferLayout();
}
-void ScreenPanelGL::resizeEvent(QResizeEvent* event)
-{
- setupScreenLayout();
-
- QWidget::resizeEvent(event);
-}
-
-void ScreenPanelGL::mousePressEvent(QMouseEvent* event)
-{
- screenOnMousePress(event);
-}
-
-void ScreenPanelGL::mouseReleaseEvent(QMouseEvent* event)
-{
- screenOnMouseRelease(event);
-}
-
-void ScreenPanelGL::mouseMoveEvent(QMouseEvent* event)
-{
- screenOnMouseMove(event);
-}
-
-void ScreenPanelGL::tabletEvent(QTabletEvent* event)
-{
- screenHandleTablet(event);
-}
-
-bool ScreenPanelGL::event(QEvent* event)
-{
- if (event->type() == QEvent::TouchBegin
- || event->type() == QEvent::TouchEnd
- || event->type() == QEvent::TouchUpdate)
- {
- screenHandleTouch((QTouchEvent*)event);
- return true;
- }
- return QWidget::event(event);
-}
-
void ScreenPanelGL::transferLayout()
{
std::optional<WindowInfo> windowInfo = getWindowInfo();
@@ -734,9 +1070,3 @@ void ScreenPanelGL::transferLayout()
screenSettingsLock.unlock();
}
}
-
-void ScreenPanelGL::onScreenLayoutChanged()
-{
- setMinimumSize(screenGetMinSize());
- setupScreenLayout();
-}
diff --git a/src/frontend/qt_sdl/Screen.h b/src/frontend/qt_sdl/Screen.h
index 4c031e6..c2f7fda 100644
--- a/src/frontend/qt_sdl/Screen.h
+++ b/src/frontend/qt_sdl/Screen.h
@@ -20,20 +20,19 @@
#define SCREEN_H
#include <optional>
-
-#include "glad/glad.h"
-#include "FrontendUtil.h"
-#include "duckstation/gl/context.h"
+#include <deque>
+#include <map>
#include <QWidget>
-#include <QWindow>
-#include <QMainWindow>
#include <QImage>
-#include <QActionGroup>
-#include <QTimer>
#include <QMutex>
#include <QScreen>
#include <QCloseEvent>
+#include <QTimer>
+
+#include "glad/glad.h"
+#include "FrontendUtil.h"
+#include "duckstation/gl/context.h"
class EmuThread;
@@ -50,27 +49,54 @@ const struct { int id; float ratio; const char* label; } aspectRatios[] =
constexpr int AspectRatiosNum = sizeof(aspectRatios) / sizeof(aspectRatios[0]);
-class ScreenHandler
+class ScreenPanel : public QWidget
{
- Q_GADGET
+ Q_OBJECT
public:
- ScreenHandler(QWidget* widget);
- virtual ~ScreenHandler();
+ explicit ScreenPanel(QWidget* parent);
+ virtual ~ScreenPanel();
+
QTimer* setupMouseTimer();
void updateMouseTimer();
QTimer* mouseTimer;
QSize screenGetMinSize(int factor);
+ void osdSetEnabled(bool enabled);
+ void osdAddMessage(unsigned int color, const char* msg);
+
+private slots:
+ void onScreenLayoutChanged();
+
protected:
- void screenSetupLayout(int w, int h);
+ struct OSDItem
+ {
+ unsigned int id;
+ qint64 timestamp;
+
+ char text[256];
+ unsigned int color;
+
+ bool rendered;
+ QImage bitmap;
+ };
+
+ QMutex osdMutex;
+ bool osdEnabled;
+ unsigned int osdID;
+ std::deque<OSDItem> osdItems;
+
+ virtual void setupScreenLayout();
+
+ void resizeEvent(QResizeEvent* event) override;
- void screenOnMousePress(QMouseEvent* event);
- void screenOnMouseRelease(QMouseEvent* event);
- void screenOnMouseMove(QMouseEvent* event);
+ void mousePressEvent(QMouseEvent* event) override;
+ void mouseReleaseEvent(QMouseEvent* event) override;
+ void mouseMoveEvent(QMouseEvent* event) override;
- void screenHandleTablet(QTabletEvent* event);
- void screenHandleTouch(QTouchEvent* event);
+ void tabletEvent(QTabletEvent* event) override;
+ void touchEvent(QTouchEvent* event);
+ bool event(QEvent* event) override;
float screenMatrix[Frontend::MaxScreenTransforms][6];
int screenKind[Frontend::MaxScreenTransforms];
@@ -79,10 +105,19 @@ protected:
bool touching = false;
void showCursor();
+
+ int osdFindBreakPoint(const char* text, int i);
+ void osdLayoutText(const char* text, int* width, int* height, int* breaks);
+ unsigned int osdRainbowColor(int inc);
+
+ virtual void osdRenderItem(OSDItem* item);
+ virtual void osdDeleteItem(OSDItem* item);
+
+ void osdUpdate();
};
-class ScreenPanelNative : public QWidget, public ScreenHandler
+class ScreenPanelNative : public ScreenPanel
{
Q_OBJECT
@@ -93,26 +128,15 @@ public:
protected:
void paintEvent(QPaintEvent* event) override;
- void resizeEvent(QResizeEvent* event) override;
-
- void mousePressEvent(QMouseEvent* event) override;
- void mouseReleaseEvent(QMouseEvent* event) override;
- void mouseMoveEvent(QMouseEvent* event) override;
-
- void tabletEvent(QTabletEvent* event) override;
- bool event(QEvent* event) override;
-private slots:
- void onScreenLayoutChanged();
-
private:
- void setupScreenLayout();
+ void setupScreenLayout() override;
QImage screen[2];
QTransform screenTrans[Frontend::MaxScreenTransforms];
};
-class ScreenPanelGL : public QWidget, public ScreenHandler
+class ScreenPanelGL : public ScreenPanel
{
Q_OBJECT
@@ -141,20 +165,8 @@ protected:
QPaintEngine* paintEngine() const override;
- void resizeEvent(QResizeEvent* event) override;
-
- void mousePressEvent(QMouseEvent* event) override;
- void mouseReleaseEvent(QMouseEvent* event) override;
- void mouseMoveEvent(QMouseEvent* event) override;
-
- void tabletEvent(QTabletEvent* event) override;
- bool event(QEvent* event) override;
-
-private slots:
- void onScreenLayoutChanged();
-
private:
- void setupScreenLayout();
+ void setupScreenLayout() override;
std::unique_ptr<GL::Context> glContext;
@@ -168,6 +180,16 @@ private:
bool filter;
int lastScreenWidth = -1, lastScreenHeight = -1;
+
+ GLuint osdShader[3];
+ GLint osdScreenSizeULoc, osdPosULoc, osdSizeULoc;
+ GLfloat osdScaleFactorULoc;
+ GLuint osdVertexArray;
+ GLuint osdVertexBuffer;
+ std::map<unsigned int, GLuint> osdTextures;
+
+ void osdRenderItem(OSDItem* item) override;
+ void osdDeleteItem(OSDItem* item) override;
};
#endif // SCREEN_H
diff --git a/src/frontend/qt_sdl/Window.cpp b/src/frontend/qt_sdl/Window.cpp
index 7b67ec5..962fb76 100644
--- a/src/frontend/qt_sdl/Window.cpp
+++ b/src/frontend/qt_sdl/Window.cpp
@@ -81,8 +81,6 @@
#include "ArchiveUtil.h"
#include "CameraManager.h"
-#include "OSD.h"
-
using namespace melonDS;
// TEMP
@@ -689,13 +687,13 @@ void MainWindow::osdAddMessage(unsigned int color, const char* fmt, ...)
if (fmt == nullptr)
return;
- char msg[1024];
+ char msg[256];
va_list args;
va_start(args, fmt);
- vsnprintf(msg, 1024, fmt, args);
+ vsnprintf(msg, 256, fmt, args);
va_end(args);
- OSD::AddMessage(color, msg);
+ panel->osdAddMessage(color, msg);
}
void MainWindow::closeEvent(QCloseEvent* event)
@@ -720,7 +718,6 @@ void MainWindow::createScreenPanel()
panelGL->show();
panel = panelGL;
- panelWidget = panelGL;
panelGL->createContext();
}
@@ -729,14 +726,14 @@ void MainWindow::createScreenPanel()
{
ScreenPanelNative* panelNative = new ScreenPanelNative(this);
panel = panelNative;
- panelWidget = panelNative;
- panelWidget->show();
+ panel->show();
}
- setCentralWidget(panelWidget);
+ setCentralWidget(panel);
actScreenFiltering->setEnabled(hasOGL);
+ panel->osdSetEnabled(Config::ShowOSD);
- connect(this, SIGNAL(screenLayoutChange()), panelWidget, SLOT(onScreenLayoutChanged()));
+ connect(this, SIGNAL(screenLayoutChange()), panel, SLOT(onScreenLayoutChanged()));
emit screenLayoutChange();
}
@@ -1866,7 +1863,7 @@ void MainWindow::onChangeSavestateSRAMReloc(bool checked)
void MainWindow::onChangeScreenSize()
{
int factor = ((QAction*)sender())->data().toInt();
- QSize diff = size() - panelWidget->size();
+ QSize diff = size() - panel->size();
resize(panel->screenGetMinSize(factor) + diff);
}
@@ -1959,7 +1956,9 @@ void MainWindow::onChangeScreenFiltering(bool checked)
void MainWindow::onChangeShowOSD(bool checked)
{
Config::ShowOSD = checked?1:0;
+ panel->osdSetEnabled(Config::ShowOSD);
}
+
void MainWindow::onChangeLimitFramerate(bool checked)
{
Config::LimitFPS = checked?1:0;
@@ -2065,7 +2064,7 @@ void MainWindow::onUpdateVideoSettings(bool glchange)
delete panel;
createScreenPanel();
- connect(emuThread, SIGNAL(windowUpdate()), panelWidget, SLOT(repaint()));
+ connect(emuThread, SIGNAL(windowUpdate()), panel, SLOT(repaint()));
}
videoSettingsDirty = true;
diff --git a/src/frontend/qt_sdl/Window.h b/src/frontend/qt_sdl/Window.h
index f0f66c2..bc20748 100644
--- a/src/frontend/qt_sdl/Window.h
+++ b/src/frontend/qt_sdl/Window.h
@@ -92,8 +92,7 @@ private:
bool oldMax;
public:
- ScreenHandler* panel;
- QWidget* panelWidget;
+ ScreenPanel* panel;
};*/
class MainWindow : public QMainWindow
@@ -230,8 +229,7 @@ private:
bool oldMax;
public:
- ScreenHandler* panel;
- QWidget* panelWidget;
+ ScreenPanel* panel;
QAction* actOpenROM;
QAction* actBootFirmware;
diff --git a/src/frontend/qt_sdl/main.cpp b/src/frontend/qt_sdl/main.cpp
index 2f08c37..38c0ab1 100644
--- a/src/frontend/qt_sdl/main.cpp
+++ b/src/frontend/qt_sdl/main.cpp
@@ -79,7 +79,6 @@
#include "version.h"
#include "FrontendUtil.h"
-#include "OSD.h"
#include "Args.h"
#include "NDS.h"