From 2b3ca2089f7420bb938c6bdda67ed0f8c04e51d5 Mon Sep 17 00:00:00 2001 From: Arisotura Date: Mon, 3 Jun 2019 16:45:55 +0200 Subject: [PATCH] take the OSD shito somewhere --- src/OpenGLSupport.h | 1 + src/libui_sdl/OSD.cpp | 136 +++++++++++++++++++++++++---------- src/libui_sdl/main.cpp | 45 ++++++++++-- src/libui_sdl/main_shaders.h | 51 ++++++++++++- 4 files changed, 190 insertions(+), 43 deletions(-) diff --git a/src/OpenGLSupport.h b/src/OpenGLSupport.h index 6130c8ef..fbc100cd 100644 --- a/src/OpenGLSupport.h +++ b/src/OpenGLSupport.h @@ -106,6 +106,7 @@ \ func(GLUNIFORM1I, glUniform1i); \ func(GLUNIFORM1UI, glUniform1ui); \ + func(GLUNIFORM2I, glUniform2i); \ func(GLUNIFORM4UI, glUniform4ui); \ func(GLUNIFORMBLOCKBINDING, glUniformBlockBinding); \ func(GLGETUNIFORMLOCATION, glGetUniformLocation); \ diff --git a/src/libui_sdl/OSD.cpp b/src/libui_sdl/OSD.cpp index a13ff449..851f9c54 100644 --- a/src/libui_sdl/OSD.cpp +++ b/src/libui_sdl/OSD.cpp @@ -35,7 +35,7 @@ namespace OSD const u32 kOSDMargin = 6; -typedef struct +struct Item { Uint32 Timestamp; char Text[256]; @@ -50,13 +50,45 @@ typedef struct bool GLTextureLoaded; GLuint GLTexture; -} Item; +}; -std::deque ItemQueue; +std::deque ItemQueue; + +GLint uOSDPos, uOSDSize; +GLuint OSDVertexArray; +GLuint OSDVertexBuffer; + +volatile bool Rendering; bool Init(bool opengl) { + if (opengl) + { + GLuint prog; glGetIntegerv(GL_CURRENT_PROGRAM, (GLint*)&prog); + uOSDPos = glGetUniformLocation(prog, "uOSDPos"); + uOSDSize = glGetUniformLocation(prog, "uOSDSize"); + + 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; } @@ -64,15 +96,13 @@ void DeInit(bool opengl) { for (auto it = ItemQueue.begin(); it != ItemQueue.end(); ) { - Item* item = *it; + Item& item = *it; - if (item->DrawBitmapLoaded && item->DrawBitmap) uiDrawFreeBitmap(item->DrawBitmap); - if (item->GLTextureLoaded && opengl) glDeleteTextures(1, &item->GLTexture); - if (item->Bitmap) delete[] item->Bitmap; + if (item.DrawBitmapLoaded && item.DrawBitmap) uiDrawFreeBitmap(item.DrawBitmap); + if (item.GLTextureLoaded && opengl) glDeleteTextures(1, &item.GLTexture); + if (item.Bitmap) delete[] item.Bitmap; - delete item; - - ItemQueue.erase(it); + it = ItemQueue.erase(it); } } @@ -276,15 +306,17 @@ void RenderText(u32 color, const char* text, Item* item) void AddMessage(u32 color, const char* text) { - Item* item = new Item; + while (Rendering); - item->Timestamp = SDL_GetTicks(); - strncpy(item->Text, text, 255); item->Text[255] = '\0'; - item->Color = color; - item->Bitmap = NULL; + Item item; - item->DrawBitmapLoaded = false; - item->GLTextureLoaded = false; + item.Timestamp = SDL_GetTicks(); + strncpy(item.Text, text, 255); item.Text[255] = '\0'; + item.Color = color; + item.Bitmap = NULL; + + item.DrawBitmapLoaded = false; + item.GLTextureLoaded = false; ItemQueue.push_back(item); } @@ -293,7 +325,7 @@ void WindowResized(bool opengl) { /*for (auto it = ItemQueue.begin(); it != ItemQueue.end(); ) { - Item* item = *it; + Item& item = *it; if (item->DrawBitmapLoaded && item->DrawBitmap) uiDrawFreeBitmap(item->DrawBitmap); //if (item->GLTextureLoaded && opengl) glDeleteTextures(1, &item->GLTexture); @@ -309,53 +341,83 @@ void WindowResized(bool opengl) void Update(bool opengl, uiAreaDrawParams* params) { + Rendering = true; + Uint32 tick_now = SDL_GetTicks(); Uint32 tick_min = tick_now - 2500; u32 y = kOSDMargin; + if (opengl) + { + 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; + Item& item = *it; - if (item->Timestamp < tick_min) + if (item.Timestamp < tick_min) { - if (item->DrawBitmapLoaded && item->DrawBitmap) uiDrawFreeBitmap(item->DrawBitmap); - if (item->GLTextureLoaded && opengl) glDeleteTextures(1, &item->GLTexture); - if (item->Bitmap) delete[] item->Bitmap; + if (item.DrawBitmapLoaded && item.DrawBitmap) uiDrawFreeBitmap(item.DrawBitmap); + if (item.GLTextureLoaded && opengl) glDeleteTextures(1, &item.GLTexture); + if (item.Bitmap) delete[] item.Bitmap; - delete item; - - ItemQueue.erase(it); + it = ItemQueue.erase(it); continue; } - if (!item->Bitmap) + if (!item.Bitmap) { - RenderText(item->Color, item->Text, item); + RenderText(item.Color, item.Text, &item); } if (opengl) { - // + 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); } else { - if (!item->DrawBitmapLoaded) + if (!item.DrawBitmapLoaded) { - item->DrawBitmap = uiDrawNewBitmap(params->Context, item->Width, item->Height, 1); - uiDrawBitmapUpdate(item->DrawBitmap, item->Bitmap); - item->DrawBitmapLoaded = true; + item.DrawBitmap = uiDrawNewBitmap(params->Context, item.Width, item.Height, 1); + uiDrawBitmapUpdate(item.DrawBitmap, item.Bitmap); + + item.DrawBitmapLoaded = true; } - uiRect rc_src = {0, 0, item->Width, item->Height}; - uiRect rc_dst = {kOSDMargin, y, item->Width, item->Height}; + uiRect rc_src = {0, 0, item.Width, item.Height}; + uiRect rc_dst = {kOSDMargin, y, item.Width, item.Height}; - uiDrawBitmapDraw(params->Context, item->DrawBitmap, &rc_src, &rc_dst, 0); + uiDrawBitmapDraw(params->Context, item.DrawBitmap, &rc_src, &rc_dst, 0); } - y += item->Height; + y += item.Height; it++; } + + Rendering = false; } } diff --git a/src/libui_sdl/main.cpp b/src/libui_sdl/main.cpp index 54074038..073c8acd 100644 --- a/src/libui_sdl/main.cpp +++ b/src/libui_sdl/main.cpp @@ -112,6 +112,7 @@ uiDrawBitmap* ScreenBitmap[2] = {NULL,NULL}; GLuint GL_ScreenShader[3]; GLuint GL_ScreenShaderAccel[3]; +GLuint GL_ScreenShaderOSD[3]; struct { float uScreenSize[2]; @@ -198,6 +199,29 @@ bool GLScreen_InitShader(GLuint* shader, const char* fs) return true; } +bool GLScreen_InitOSDShader(GLuint* shader) +{ + if (!OpenGL_BuildShaderProgram(kScreenVS_OSD, kScreenFS_OSD, shader, "ScreenShaderOSD")) + return false; + + glBindAttribLocation(shader[2], 0, "vPosition"); + glBindFragDataLocation(shader[2], 0, "oColor"); + + if (!OpenGL_LinkShaderProgram(shader)) + return false; + + GLuint uni_id; + + uni_id = glGetUniformBlockIndex(shader[2], "uConfig"); + glUniformBlockBinding(shader[2], uni_id, 16); + + glUseProgram(shader[2]); + uni_id = glGetUniformLocation(shader[2], "OSDTex"); + glUniform1i(uni_id, 0); + + return true; +} + bool GLScreen_Init() { // TODO: consider using epoxy? @@ -213,6 +237,8 @@ bool GLScreen_Init() return false; if (!GLScreen_InitShader(GL_ScreenShaderAccel, kScreenFS_Accel)) return false; + if (!GLScreen_InitOSDShader(GL_ScreenShaderOSD)) + return false; memset(&GL_ShaderConfig, 0, sizeof(GL_ShaderConfig)); @@ -255,6 +281,7 @@ void GLScreen_DeInit() OpenGL_DeleteShaderProgram(GL_ScreenShader); OpenGL_DeleteShaderProgram(GL_ScreenShaderAccel); + OpenGL_DeleteShaderProgram(GL_ScreenShaderOSD); } void GLScreen_DrawScreen() @@ -396,7 +423,7 @@ void GLScreen_DrawScreen() else OpenGL_UseShaderProgram(GL_ScreenShaderAccel); - glBindFramebuffer(GL_DRAW_FRAMEBUFFER, uiGLGetFramebuffer(GLContext)); + glBindFramebuffer(GL_FRAMEBUFFER, uiGLGetFramebuffer(GLContext)); glClearColor(0, 0, 0, 1); glClear(GL_COLOR_BUFFER_BIT); @@ -434,6 +461,7 @@ void GLScreen_DrawScreen() glDrawArrays(GL_TRIANGLES, 0, 4*3); } + OpenGL_UseShaderProgram(GL_ScreenShaderOSD); OSD::Update(true, NULL); glFlush(); @@ -947,19 +975,21 @@ int EmuThreadFunc(void* burp) if (joybuttons) delete[] joybuttons; + if (Screen_UseGL) uiGLMakeContextCurrent(GLContext); + NDS::DeInit(); Platform::LAN_DeInit(); if (Screen_UseGL) { - uiGLMakeContextCurrent(GLContext); OSD::DeInit(true); GLScreen_DeInit(); - uiGLMakeContextCurrent(NULL); } else OSD::DeInit(false); + if (Screen_UseGL) uiGLMakeContextCurrent(NULL); + return 44203; } @@ -1128,7 +1158,7 @@ int OnAreaKeyEvent(uiAreaHandler* handler, uiArea* area, uiAreaKeyEvent* evt) MicCommand |= 1; if (evt->Scancode == 0x57) // F11 - OSD::AddMessage(0, "OSD test"); + OSD::AddMessage(0x00FFFF, "OSD test"); //NDS::debug(0); } @@ -2302,6 +2332,11 @@ void CreateMainWindow(bool opengl) { uiGLMakeContextCurrent(GLContext); if (!GLScreen_Init()) opengl_good = false; + if (opengl_good) + { + OpenGL_UseShaderProgram(GL_ScreenShaderOSD); + OSD::Init(true); + } uiGLMakeContextCurrent(NULL); } @@ -2312,7 +2347,7 @@ void CreateMainWindow(bool opengl) Screen_UseGL = false; } - OSD::Init(opengl); + if (!opengl) OSD::Init(false); } void DestroyMainWindow() diff --git a/src/libui_sdl/main_shaders.h b/src/libui_sdl/main_shaders.h index f03931c1..6504520f 100644 --- a/src/libui_sdl/main_shaders.h +++ b/src/libui_sdl/main_shaders.h @@ -36,7 +36,7 @@ smooth out vec2 fTexcoord; void main() { vec4 fpos; - fpos.xy = ((vPosition.xy * 2.0) / uScreenSize) - 1.0; + fpos.xy = ((vPosition * 2.0) / uScreenSize) - 1.0; fpos.y *= -1; fpos.z = 0.0; fpos.w = 1.0; @@ -198,4 +198,53 @@ void main() } )"; + +const char* kScreenVS_OSD = R"(#version 140 + +layout(std140) uniform uConfig +{ + vec2 uScreenSize; + uint u3DScale; + uint uFilterMode; +}; + +uniform ivec2 uOSDPos; +uniform ivec2 uOSDSize; + +in vec2 vPosition; + +smooth out vec2 fTexcoord; + +void main() +{ + vec4 fpos; + + vec2 osdpos = (vPosition * vec2(uOSDSize)); + fTexcoord = osdpos; + osdpos += uOSDPos; + + fpos.xy = ((osdpos * 2.0) / uScreenSize) - 1.0; + fpos.y *= -1; + fpos.z = 0.0; + fpos.w = 1.0; + + gl_Position = fpos; +} +)"; + +const char* kScreenFS_OSD = R"(#version 140 + +uniform sampler2D OSDTex; + +smooth in vec2 fTexcoord; + +out vec4 oColor; + +void main() +{ + vec4 pixel = texelFetch(OSDTex, ivec2(fTexcoord), 0); + oColor = pixel.bgra; +} +)"; + #endif // MAIN_SHADERS_H