aboutsummaryrefslogtreecommitdiff
path: root/src/frontend/qt_sdl/OSD.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/frontend/qt_sdl/OSD.cpp')
-rw-r--r--src/frontend/qt_sdl/OSD.cpp475
1 files changed, 0 insertions, 475 deletions
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();
-}
-
-}