preliminary, shitty, code for drawing the main window with OpenGL

This commit is contained in:
Arisotura 2019-05-16 00:30:55 +02:00
parent 256b8cb69c
commit f2725791d8
7 changed files with 392 additions and 6 deletions

View File

@ -230,6 +230,7 @@
<Unit filename="src/libui_sdl/libui/windows/winpublic.cpp" />
<Unit filename="src/libui_sdl/libui/windows/winutil.cpp" />
<Unit filename="src/libui_sdl/main.cpp" />
<Unit filename="src/libui_sdl/main_shaders.h" />
<Unit filename="src/pcap/bluetooth.h" />
<Unit filename="src/pcap/bpf.h" />
<Unit filename="src/pcap/can_socketcan.h" />

View File

@ -732,7 +732,8 @@ bool ChunkedRendering = false;
bool InitGLExtensions()
{
if (!OpenGL_Init()) return false;
// TODO move this elsewhere!!
//if (!OpenGL_Init()) return false;
return true;
}
@ -1385,7 +1386,7 @@ void VCount144()
}
void RenderFrame()
{
{return;
ShaderConfig.uScreenSize[0] = ScreenW;
ShaderConfig.uScreenSize[1] = ScreenH;
ShaderConfig.uDispCnt = RenderDispCnt;
@ -1544,7 +1545,7 @@ void RenderFrame()
u32* GetLine(int line)
{
int stride = 256 << (ScaleFactor*2);
return &Framebuffer[stride * line];
if (!ChunkedRendering)
{
if (line == 0)

View File

@ -28,3 +28,88 @@ bool OpenGL_Init()
return true;
}
bool OpenGL_BuildShaderProgram(const char* vs, const char* fs, GLuint* ids, const char* name)
{
int len;
int res;
ids[0] = glCreateShader(GL_VERTEX_SHADER);
len = strlen(vs);
glShaderSource(ids[0], 1, &vs, &len);
glCompileShader(ids[0]);
glGetShaderiv(ids[0], GL_COMPILE_STATUS, &res);
if (res != GL_TRUE)
{
glGetShaderiv(ids[0], GL_INFO_LOG_LENGTH, &res);
if (res < 1) res = 1024;
char* log = new char[res+1];
glGetShaderInfoLog(ids[0], res+1, NULL, log);
printf("OpenGL: failed to compile vertex shader %s: %s\n", name, log);
printf("shader source:\n--\n%s\n--\n", vs);
delete[] log;
glDeleteShader(ids[0]);
return false;
}
ids[1] = glCreateShader(GL_FRAGMENT_SHADER);
len = strlen(fs);
glShaderSource(ids[1], 1, &fs, &len);
glCompileShader(ids[1]);
glGetShaderiv(ids[1], GL_COMPILE_STATUS, &res);
if (res != GL_TRUE)
{
glGetShaderiv(ids[1], GL_INFO_LOG_LENGTH, &res);
if (res < 1) res = 1024;
char* log = new char[res+1];
glGetShaderInfoLog(ids[1], res+1, NULL, log);
printf("OpenGL: failed to compile fragment shader %s: %s\n", name, log);
//printf("shader source:\n--\n%s\n--\n", fs);
delete[] log;
glDeleteShader(ids[0]);
glDeleteShader(ids[1]);
return false;
}
ids[2] = glCreateProgram();
glAttachShader(ids[2], ids[0]);
glAttachShader(ids[2], ids[1]);
glLinkProgram(ids[2]);
glGetProgramiv(ids[2], GL_LINK_STATUS, &res);
if (res != GL_TRUE)
{
glGetProgramiv(ids[2], GL_INFO_LOG_LENGTH, &res);
if (res < 1) res = 1024;
char* log = new char[res+1];
glGetProgramInfoLog(ids[2], res+1, NULL, log);
printf("OpenGL: failed to link program %s: %s\n", name, log);
delete[] log;
glDeleteShader(ids[0]);
glDeleteShader(ids[1]);
glDeleteProgram(ids[2]);
return false;
}
return true;
}
void OpenGL_DeleteShaderProgram(GLuint* ids)
{
glDeleteShader(ids[0]);
glDeleteShader(ids[1]);
glDeleteProgram(ids[2]);
}
void OpenGL_UseShaderProgram(GLuint* ids)
{
glUseProgram(ids[2]);
}

View File

@ -109,4 +109,8 @@ DO_PROCLIST(DECLPROC_EXT);
bool OpenGL_Init();
bool OpenGL_BuildShaderProgram(const char* vs, const char* fs, GLuint* ids, const char* name);
void OpenGL_DeleteShaderProgram(GLuint* ids);
void OpenGL_UseShaderProgram(GLuint* ids);
#endif // OPENGLSUPPORT_H

View File

@ -39,7 +39,7 @@ uiGLContext* uiGLNewContext(uiControl* c, int vermajor, int verminor)
memset(&pfd, 0, sizeof(pfd));
pfd.nSize = sizeof(pfd);
pfd.nVersion = 1;
pfd.dwFlags = PFD_DRAW_TO_WINDOW | PFD_SUPPORT_OPENGL;
pfd.dwFlags = PFD_DRAW_TO_WINDOW | PFD_SUPPORT_OPENGL | PFD_DOUBLEBUFFER;
pfd.iPixelType = PFD_TYPE_RGBA;
pfd.cColorBits = 24;
pfd.cAlphaBits = 8;

View File

@ -24,6 +24,9 @@
#include <SDL2/SDL.h>
#include "libui/ui.h"
#include "../OpenGLSupport.h"
#include "main_shaders.h"
#include "../types.h"
#include "../version.h"
#include "PlatformConfig.h"
@ -97,6 +100,19 @@ bool SavestateLoaded;
bool ScreenDrawInited = false;
uiDrawBitmap* ScreenBitmap[2] = {NULL,NULL};
GLuint GL_ScreenShader[3];
struct
{
float uScreenSize[2];
u32 uFilterMode;
} GL_ShaderConfig;
GLuint GL_ShaderConfigUBO;
GLuint GL_ScreenVertexArrayID, GL_ScreenVertexBufferID;
float GL_ScreenVertices[2 * 3*2 * 4]; // position/texcoord
GLuint GL_ScreenTexture;
bool GL_ScreenSizeDirty;
int ScreenScale[3];
int ScreenScaleMode;
@ -141,6 +157,204 @@ void GetSavestateName(int slot, char* filename, int len);
bool GLDrawing_Init()
{
if (!OpenGL_Init())
return false;
if (!OpenGL_BuildShaderProgram(kScreenVS, kScreenFS, GL_ScreenShader, "ScreenShader"))
return false;
memset(&GL_ShaderConfig, 0, sizeof(GL_ShaderConfig));
glGenBuffers(1, &GL_ShaderConfigUBO);
glBindBuffer(GL_UNIFORM_BUFFER, GL_ShaderConfigUBO);
glBufferData(GL_UNIFORM_BUFFER, sizeof(GL_ShaderConfig), &GL_ShaderConfig, GL_STATIC_DRAW);
glBindBufferBase(GL_UNIFORM_BUFFER, 16, GL_ShaderConfigUBO);
glUniformBlockBinding(GL_ScreenShader[2], 0, 16);
glGenBuffers(1, &GL_ScreenVertexBufferID);
glBindBuffer(GL_ARRAY_BUFFER, GL_ScreenVertexBufferID);
glBufferData(GL_ARRAY_BUFFER, sizeof(GL_ScreenVertices), NULL, GL_STATIC_DRAW);
glGenVertexArrays(1, &GL_ScreenVertexArrayID);
glBindVertexArray(GL_ScreenVertexArrayID);
glEnableVertexAttribArray(0); // position
glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, 4*4, (void*)(0));
glEnableVertexAttribArray(1); // texcoord
glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, 4*4, (void*)(2*4));
glGenTextures(1, &GL_ScreenTexture);
glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D, GL_ScreenTexture);
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_RGBA8UI, 1024, 1536, 0, GL_RGBA_INTEGER, GL_UNSIGNED_BYTE, NULL);
GL_ScreenSizeDirty = true;
return true;
}
void GLDrawing_DeInit()
{
glDeleteTextures(1, &GL_ScreenTexture);
glDeleteVertexArrays(1, &GL_ScreenVertexArrayID);
glDeleteBuffers(1, &GL_ScreenVertexBufferID);
OpenGL_DeleteShaderProgram(GL_ScreenShader);
}
void GLDrawing_DrawScreen()
{
if (GL_ScreenSizeDirty)
{
GL_ScreenSizeDirty = false;
GL_ShaderConfig.uScreenSize[0] = WindowWidth;
GL_ShaderConfig.uScreenSize[1] = WindowHeight;
glBindBuffer(GL_UNIFORM_BUFFER, GL_ShaderConfigUBO);
void* unibuf = glMapBuffer(GL_UNIFORM_BUFFER, GL_WRITE_ONLY);
if (unibuf) memcpy(unibuf, &GL_ShaderConfig, sizeof(GL_ShaderConfig));
glUnmapBuffer(GL_UNIFORM_BUFFER);
float scwidth, scheight;
scwidth = 512;
scheight = 384;
float x0, y0, x1, y1;
float s0, s1, s2, s3;
float t0, t1, t2, t3;
#define SETVERTEX(i, x, y, s, t) \
GL_ScreenVertices[4*(i) + 0] = x; \
GL_ScreenVertices[4*(i) + 1] = y; \
GL_ScreenVertices[4*(i) + 2] = s; \
GL_ScreenVertices[4*(i) + 3] = t;
x0 = TopScreenRect.X;
y0 = TopScreenRect.Y;
x1 = TopScreenRect.X + TopScreenRect.Width;
y1 = TopScreenRect.Y + TopScreenRect.Height;
switch (ScreenRotation)
{
case 0:
s0 = 0; t0 = 0;
s1 = scwidth; t1 = 0;
s2 = 0; t2 = scheight;
s3 = scwidth; t3 = scheight;
break;
case 1:
s0 = 0; t0 = scheight;
s1 = 0; t1 = 0;
s2 = scwidth; t2 = scheight;
s3 = scwidth; t3 = 0;
break;
case 2:
s0 = scwidth; t0 = scheight;
s1 = 0; t1 = scheight;
s2 = scwidth; t2 = 0;
s3 = 0; t3 = 0;
break;
case 3:
s0 = scwidth; t0 = 0;
s1 = scwidth; t1 = scheight;
s2 = 0; t2 = 0;
s3 = 0; t3 = scheight;
break;
}
SETVERTEX(0, x0, y0, s0, t0);
SETVERTEX(1, x1, y1, s3, t3);
SETVERTEX(2, x1, y0, s1, t1);
SETVERTEX(3, x0, y0, s0, t0);
SETVERTEX(4, x0, y1, s2, t2);
SETVERTEX(5, x1, y1, s3, t3);
// TODO: adjust scwidth/scheight
x0 = BottomScreenRect.X;
y0 = BottomScreenRect.Y;
x1 = BottomScreenRect.X + BottomScreenRect.Width;
y1 = BottomScreenRect.Y + BottomScreenRect.Height;
switch (ScreenRotation)
{
case 0:
s0 = 0; t0 = 768;
s1 = scwidth; t1 = 768;
s2 = 0; t2 = 768+scheight;
s3 = scwidth; t3 = 768+scheight;
break;
case 1:
s0 = 0; t0 = 768+scheight;
s1 = 0; t1 = 768;
s2 = scwidth; t2 = 768+scheight;
s3 = scwidth; t3 = 768;
break;
case 2:
s0 = scwidth; t0 = 768+scheight;
s1 = 0; t1 = 768+scheight;
s2 = scwidth; t2 = 768;
s3 = 0; t3 = 768;
break;
case 3:
s0 = scwidth; t0 = 768;
s1 = scwidth; t1 = 768+scheight;
s2 = 0; t2 = 768;
s3 = 0; t3 = 768+scheight;
break;
}
SETVERTEX(6, x0, y0, s0, t0);
SETVERTEX(7, x1, y1, s3, t3);
SETVERTEX(8, x1, y0, s1, t1);
SETVERTEX(9, x0, y0, s0, t0);
SETVERTEX(10, x0, y1, s2, t2);
SETVERTEX(11, x1, y1, s3, t3);
#undef SETVERTEX
glBindBuffer(GL_ARRAY_BUFFER, GL_ScreenVertexBufferID);
glBufferSubData(GL_ARRAY_BUFFER, 0, sizeof(GL_ScreenVertices), GL_ScreenVertices);
}
glDisable(GL_DEPTH_TEST);
glDisable(GL_BLEND);
glViewport(0, 0, WindowWidth, WindowHeight);
OpenGL_UseShaderProgram(GL_ScreenShader);
glBindFramebuffer(GL_DRAW_FRAMEBUFFER, 0);
glClearColor(0, 1, 0, 1);
glClear(GL_COLOR_BUFFER_BIT);
int frontbuf = GPU::FrontBuffer;
glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D, GL_ScreenTexture);
glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 512, 384, GL_RGBA_INTEGER, GL_UNSIGNED_BYTE, GPU::Framebuffer[frontbuf][0]);
glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 768, 512, 384, GL_RGBA_INTEGER, GL_UNSIGNED_BYTE, GPU::Framebuffer[frontbuf][1]);
glBindBuffer(GL_ARRAY_BUFFER, GL_ScreenVertexBufferID);
glBindVertexArray(GL_ScreenVertexArrayID);
glDrawArrays(GL_TRIANGLES, 0, 4*3);
uiGLSwapBuffers(GLContext);
uiAreaQueueRedrawAll(MainDrawArea);
}
void MicLoadWav(char* name)
{
SDL_AudioSpec format;
@ -397,6 +611,8 @@ void FeedMicInput()
int EmuThreadFunc(void* burp)
{
uiGLMakeContextCurrent(GLContext);
GLDrawing_Init();
NDS::Init();
MainScreenPos[0] = 0;
@ -567,7 +783,9 @@ int EmuThreadFunc(void* burp)
if (EmuRunning == 0) break;
uiAreaQueueRedrawAll(MainDrawArea);
GLDrawing_DrawScreen();
//uiAreaQueueRedrawAll(MainDrawArea);
//uiGLSwapBuffers(GLContext);
// framerate limiter based off SDL2_gfx
@ -622,6 +840,7 @@ int EmuThreadFunc(void* burp)
{
//uiAreaQueueRedrawAll(MainDrawArea);
//uiGLSwapBuffers(GLContext);
GLDrawing_DrawScreen();
}
EmuStatus = EmuRunning;
@ -637,6 +856,8 @@ int EmuThreadFunc(void* burp)
NDS::DeInit();
Platform::LAN_DeInit();
GLDrawing_DeInit();
return 44203;
}
@ -1058,6 +1279,8 @@ void SetupScreenRects(int width, int height)
}
break;
}
GL_ScreenSizeDirty = true;
}
void SetMinSize(int w, int h)
@ -2063,7 +2286,7 @@ int main(int argc, char** argv)
areahandler.Resize = OnAreaResize;
ScreenDrawInited = false;
MainDrawArea = uiNewArea(&areahandler, 0);
MainDrawArea = uiNewArea(&areahandler, 1);
uiWindowSetChild(MainWindow, uiControl(MainDrawArea));
uiControlSetMinSize(uiControl(MainDrawArea), 256, 384);
uiAreaSetBackgroundColor(MainDrawArea, 0, 0, 0); // TODO: make configurable?

View File

@ -0,0 +1,72 @@
/*
Copyright 2016-2019 Arisotura
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 MAIN_SHADERS_H
#define MAIN_SHADERS_H
const char* kScreenVS = R"(#version 420
layout(std140, binding=0) uniform uConfig
{
vec2 uScreenSize;
uint uFilterMode;
};
layout(location=0) in vec2 vPosition;
layout(location=1) in vec2 vTexcoord;
smooth out vec2 fTexcoord;
void main()
{
vec4 fpos;
fpos.xy = ((vPosition.xy * 2.0) / uScreenSize) - 1.0;
fpos.y *= -1;
fpos.z = 0.0;
fpos.w = 1.0;
gl_Position = fpos;
fTexcoord = vTexcoord;
}
)";
const char* kScreenFS = R"(#version 420
layout(std140, binding=0) uniform uConfig
{
vec2 uScreenSize;
uint uFilterMode;
};
layout(binding=0) uniform usampler2D ScreenTex;
smooth in vec2 fTexcoord;
layout(location=0) out vec4 oColor;
void main()
{
uvec4 pixel = texelFetch(ScreenTex, ivec2(fTexcoord), 0);
// TODO: filters
oColor = vec4(vec3(pixel.bgr) / 255.0, 1.0);
}
)";
#endif // MAIN_SHADERS_H