OpenGL renderer support in melonDS!
This commit is contained in:
parent
acff619034
commit
f71f2fafc6
Binary file not shown.
|
@ -0,0 +1,207 @@
|
|||
#include "GPU.h"
|
||||
#include "OpenGLSupport.h"
|
||||
#include "frontend/FrontendUtil.h"
|
||||
|
||||
#include "BizGLPresenter.h"
|
||||
|
||||
#include <emulibc.h>
|
||||
|
||||
// half of this is taken from melonDS/src/frontend/qt_sdl/main.cpp
|
||||
|
||||
namespace GLPresenter
|
||||
{
|
||||
|
||||
static const char* VertexShader = R"(#version 140
|
||||
|
||||
uniform vec2 uSize;
|
||||
uniform mat2x3 uTransform;
|
||||
|
||||
in vec2 vPosition;
|
||||
in vec2 vTexcoord;
|
||||
|
||||
smooth out vec2 fTexcoord;
|
||||
|
||||
void main()
|
||||
{
|
||||
vec4 fpos;
|
||||
|
||||
fpos.xy = vec3(vPosition, 1.0) * uTransform;
|
||||
|
||||
fpos.xy = ((fpos.xy * 2.0) / uSize) - 1.0;
|
||||
// fpos.y *= -1;
|
||||
fpos.z = 0.0;
|
||||
fpos.w = 1.0;
|
||||
|
||||
gl_Position = fpos;
|
||||
fTexcoord = vTexcoord;
|
||||
}
|
||||
)";
|
||||
|
||||
static const char* FragmentShader = R"(#version 140
|
||||
|
||||
uniform sampler2D Tex;
|
||||
|
||||
smooth in vec2 fTexcoord;
|
||||
|
||||
out vec4 oColor;
|
||||
|
||||
void main()
|
||||
{
|
||||
vec4 pixel = texture(Tex, fTexcoord);
|
||||
|
||||
oColor = vec4(pixel.bgr, 1.0);
|
||||
}
|
||||
)";
|
||||
|
||||
|
||||
ECL_INVISIBLE static GLuint ShaderProgram[3];
|
||||
ECL_INVISIBLE static GLuint ShaderTransformULoc, ShaderSizeULoc;
|
||||
|
||||
ECL_INVISIBLE static GLuint VertexBuffer, VertexArray;
|
||||
|
||||
ECL_INVISIBLE static float TransformMatrix[2 * 6];
|
||||
|
||||
ECL_INVISIBLE static u32 Width, Height;
|
||||
|
||||
ECL_INVISIBLE static GLuint TextureID;
|
||||
ECL_INVISIBLE static GLuint FboID;
|
||||
ECL_INVISIBLE static GLuint PboID;
|
||||
|
||||
void Init(u32 scale)
|
||||
{
|
||||
Width = 256 * scale;
|
||||
Height = 384 * scale;
|
||||
|
||||
OpenGL::BuildShaderProgram(VertexShader, FragmentShader, ShaderProgram, "GLPresenterShader");
|
||||
|
||||
GLuint pid = ShaderProgram[2];
|
||||
glBindAttribLocation(pid, 0, "vPosition");
|
||||
glBindAttribLocation(pid, 1, "vTexcoord");
|
||||
glBindFragDataLocation(pid, 0, "oColor");
|
||||
|
||||
OpenGL::LinkShaderProgram(ShaderProgram);
|
||||
|
||||
glUseProgram(pid);
|
||||
glUniform1i(glGetUniformLocation(pid, "Tex"), 0);
|
||||
|
||||
ShaderSizeULoc = glGetUniformLocation(pid, "uSize");
|
||||
ShaderTransformULoc = glGetUniformLocation(pid, "uTransform");
|
||||
|
||||
constexpr int paddedHeight = 192 * 2 + 2;
|
||||
constexpr float padPixels = 1.f / paddedHeight;
|
||||
|
||||
static const float vertices[] =
|
||||
{
|
||||
0.f, 0.f, 0.f, 0.f,
|
||||
0.f, 192.f, 0.f, 0.5f - padPixels,
|
||||
256.f, 192.f, 1.f, 0.5f - padPixels,
|
||||
0.f, 0.f, 0.f, 0.f,
|
||||
256.f, 192.f, 1.f, 0.5f - padPixels,
|
||||
256.f, 0.f, 1.f, 0.f,
|
||||
|
||||
0.f, 0.f, 0.f, 0.5f + padPixels,
|
||||
0.f, 192.f, 0.f, 1.f,
|
||||
256.f, 192.f, 1.f, 1.f,
|
||||
0.f, 0.f, 0.f, 0.5f + padPixels,
|
||||
256.f, 192.f, 1.f, 1.f,
|
||||
256.f, 0.f, 1.f, 0.5f + padPixels
|
||||
};
|
||||
|
||||
glGenBuffers(1, &VertexBuffer);
|
||||
glBindBuffer(GL_ARRAY_BUFFER, VertexBuffer);
|
||||
glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW);
|
||||
|
||||
glGenVertexArrays(1, &VertexArray);
|
||||
glBindVertexArray(VertexArray);
|
||||
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));
|
||||
|
||||
// TODO: Could we use this instead of all the screen transforming code in the frontend?
|
||||
// see https://github.com/TASEmulators/BizHawk/issues/3772
|
||||
Frontend::SetupScreenLayout(Width, Height, Frontend::screenLayout_Natural, Frontend::screenRot_0Deg, Frontend::screenSizing_Even, 0, true, false, 1, 1);
|
||||
int discard[2];
|
||||
Frontend::GetScreenTransforms(TransformMatrix, discard);
|
||||
|
||||
glGenTextures(1, &TextureID);
|
||||
glActiveTexture(GL_TEXTURE0);
|
||||
glBindTexture(GL_TEXTURE_2D, TextureID);
|
||||
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, Width, Height, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
|
||||
glBindTexture(GL_TEXTURE_2D, 0);
|
||||
|
||||
glGenFramebuffers(1, &FboID);
|
||||
glBindFramebuffer(GL_FRAMEBUFFER, FboID);
|
||||
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, TextureID, 0);
|
||||
glDrawBuffer(GL_COLOR_ATTACHMENT0);
|
||||
|
||||
glGenBuffers(1, &PboID);
|
||||
}
|
||||
|
||||
std::pair<u32, u32> Present(bool filter)
|
||||
{
|
||||
glBindFramebuffer(GL_FRAMEBUFFER, FboID);
|
||||
glDisable(GL_DEPTH_TEST);
|
||||
glDepthMask(false);
|
||||
glDisable(GL_BLEND);
|
||||
glDisable(GL_SCISSOR_TEST);
|
||||
glDisable(GL_STENCIL_TEST);
|
||||
glClear(GL_COLOR_BUFFER_BIT);
|
||||
|
||||
glViewport(0, 0, Width, Height);
|
||||
|
||||
glUseProgram(ShaderProgram[2]);
|
||||
glUniform2f(ShaderSizeULoc, Width, Height);
|
||||
|
||||
glActiveTexture(GL_TEXTURE0);
|
||||
GPU::CurGLCompositor->BindOutputTexture(GPU::FrontBuffer);
|
||||
|
||||
GLint texFilter = filter ? GL_LINEAR : GL_NEAREST;
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, texFilter);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, texFilter);
|
||||
|
||||
glBindBuffer(GL_ARRAY_BUFFER, VertexBuffer);
|
||||
glBindVertexArray(VertexArray);
|
||||
|
||||
glUniformMatrix2x3fv(ShaderTransformULoc, 1, GL_TRUE, &TransformMatrix[0]);
|
||||
glDrawArrays(GL_TRIANGLES, 0, 6);
|
||||
|
||||
glUniformMatrix2x3fv(ShaderTransformULoc, 1, GL_TRUE, &TransformMatrix[6]);
|
||||
glDrawArrays(GL_TRIANGLES, 6, 6);
|
||||
|
||||
glFlush();
|
||||
|
||||
glBindBuffer(GL_PIXEL_PACK_BUFFER, PboID);
|
||||
glBufferData(GL_PIXEL_PACK_BUFFER, Width * Height * sizeof(u32), nullptr, GL_STREAM_READ);
|
||||
glReadPixels(0, 0, Width, Height, GL_BGRA, GL_UNSIGNED_INT_8_8_8_8_REV, static_cast<void*>(0));
|
||||
|
||||
return std::make_pair(Width, Height);
|
||||
}
|
||||
|
||||
ECL_EXPORT u32 GetGLTexture()
|
||||
{
|
||||
return TextureID;
|
||||
}
|
||||
|
||||
ECL_EXPORT void ReadFrameBuffer(u32* buffer)
|
||||
{
|
||||
glBindBuffer(GL_PIXEL_PACK_BUFFER, PboID);
|
||||
const auto p = static_cast<const u32*>(glMapBuffer(GL_PIXEL_PACK_BUFFER, GL_READ_ONLY));
|
||||
if (p) {
|
||||
// FBOs render upside down, so flip vertically to counteract that
|
||||
buffer += Width * (Height - 1);
|
||||
const int w = Width;
|
||||
const int h = Height;
|
||||
for (int i = 0; i < h; i++) {
|
||||
std::memcpy(&buffer[-i * w], &p[i * w], Width * sizeof(u32));
|
||||
}
|
||||
|
||||
glUnmapBuffer(GL_PIXEL_PACK_BUFFER);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,14 @@
|
|||
#ifndef BIZGLPRESENTER_H
|
||||
#define BIZGLPRESENTER_H
|
||||
|
||||
#include "types.h"
|
||||
|
||||
namespace GLPresenter
|
||||
{
|
||||
|
||||
void Init(u32 scale);
|
||||
std::pair<u32, u32> Present(bool filter);
|
||||
|
||||
}
|
||||
|
||||
#endif
|
|
@ -8,7 +8,10 @@
|
|||
#include "BizPlatform/BizConfig.h"
|
||||
#include "BizPlatform/BizFile.h"
|
||||
#include "BizPlatform/BizLog.h"
|
||||
#include "BizPlatform/BizOGL.h"
|
||||
|
||||
#include "BizFileManager.h"
|
||||
#include "BizGLPresenter.h"
|
||||
|
||||
#include <emulibc.h>
|
||||
#include <waterboxcore.h>
|
||||
|
@ -23,6 +26,7 @@ struct InitConfig
|
|||
bool DSi;
|
||||
bool ClearNAND;
|
||||
bool LoadDSiWare;
|
||||
bool IsWinApi;
|
||||
int ThreeDeeRenderer;
|
||||
GPU::RenderSettings RenderSettings;
|
||||
};
|
||||
|
@ -30,7 +34,8 @@ struct InitConfig
|
|||
ECL_EXPORT const char* Init(InitConfig* initConfig,
|
||||
Platform::ConfigCallbackInterface* configCallbackInterface,
|
||||
Platform::FileCallbackInterface* fileCallbackInterface,
|
||||
Platform::LogCallback_t logCallback)
|
||||
Platform::LogCallback_t logCallback,
|
||||
BizOGL::LoadGLProc loadGLProc)
|
||||
{
|
||||
Platform::SetConfigCallbacks(*configCallbackInterface);
|
||||
Platform::SetFileCallbacks(*fileCallbackInterface);
|
||||
|
@ -55,6 +60,27 @@ ECL_EXPORT const char* Init(InitConfig* initConfig,
|
|||
return "Failed to init core!";
|
||||
}
|
||||
|
||||
switch (initConfig->ThreeDeeRenderer)
|
||||
{
|
||||
case 0:
|
||||
break;
|
||||
case 1:
|
||||
BizOGL::LoadGL(loadGLProc, BizOGL::LoadGLVersion::V3_2, initConfig->IsWinApi);
|
||||
break;
|
||||
#if false
|
||||
case 2:
|
||||
BizOGL::LoadGL(loadGLProc, BizOGL::LoadGLVersion::V4_3, initConfig->IsWinApi);
|
||||
break;
|
||||
#endif
|
||||
default:
|
||||
return "Unknown 3DRenderer!";
|
||||
}
|
||||
|
||||
if (initConfig->ThreeDeeRenderer)
|
||||
{
|
||||
GLPresenter::Init(initConfig->RenderSettings.GL_ScaleFactor);
|
||||
}
|
||||
|
||||
GPU::InitRenderer(initConfig->ThreeDeeRenderer);
|
||||
GPU::SetRenderSettings(initConfig->ThreeDeeRenderer, initConfig->RenderSettings);
|
||||
|
||||
|
@ -166,17 +192,22 @@ ECL_EXPORT void FrameAdvance(MyFrameInfo* f)
|
|||
|
||||
NDS::RunFrame();
|
||||
|
||||
if (auto softRenderer = dynamic_cast<GPU3D::SoftRenderer*>(GPU3D::CurrentRenderer.get()))
|
||||
if (GPU3D::CurrentRenderer->Accelerated)
|
||||
{
|
||||
softRenderer->StopRenderThread();
|
||||
std::tie(f->Width, f->Height) = GLPresenter::Present(false);
|
||||
}
|
||||
else
|
||||
{
|
||||
auto softRenderer = reinterpret_cast<GPU3D::SoftRenderer*>(GPU3D::CurrentRenderer.get());
|
||||
softRenderer->StopRenderThread();
|
||||
|
||||
const u32 SingleScreenSize = 256 * 192;
|
||||
memcpy(f->VideoBuffer, GPU::Framebuffer[GPU::FrontBuffer][0], SingleScreenSize * sizeof (u32));
|
||||
memcpy(f->VideoBuffer + SingleScreenSize, GPU::Framebuffer[GPU::FrontBuffer][1], SingleScreenSize * sizeof (u32));
|
||||
constexpr u32 SingleScreenSize = 256 * 192;
|
||||
memcpy(f->VideoBuffer, GPU::Framebuffer[GPU::FrontBuffer][0], SingleScreenSize * sizeof(u32));
|
||||
memcpy(f->VideoBuffer + SingleScreenSize, GPU::Framebuffer[GPU::FrontBuffer][1], SingleScreenSize * sizeof(u32));
|
||||
|
||||
f->Width = 256;
|
||||
f->Height = 384;
|
||||
f->Width = 256;
|
||||
f->Height = 384;
|
||||
}
|
||||
|
||||
f->Samples = SPU::ReadOutput(f->SoundBuffer);
|
||||
if (f->Samples == 0) // hack
|
||||
|
|
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
|
@ -1,7 +1,7 @@
|
|||
CCFLAGS := -Wno-incompatible-pointer-types-discards-qualifiers -Wno-pointer-sign
|
||||
|
||||
CXXFLAGS := -DMELONDS_VERSION="" \
|
||||
-I./melonDS/src -I./melonDS/src/teakra/include \
|
||||
CXXFLAGS := -DMELONDS_VERSION="" -DOGLRENDERER_ENABLED \
|
||||
-I. -I./melonDS/src -I./melonDS/src/teakra/include \
|
||||
-Wall -Wextra -Werror=int-to-pointer-cast \
|
||||
-Wfatal-errors -Wno-unused-parameter -Wno-unused-variable \
|
||||
-Wno-unused-but-set-variable -Wno-unused-function \
|
||||
|
@ -49,6 +49,12 @@ CORE_SRCS = \
|
|||
Wifi.cpp \
|
||||
WifiAP.cpp
|
||||
|
||||
CORE_GL_SRCS = \
|
||||
GPU_OpenGL.cpp \
|
||||
GPU3D_OpenGL.cpp \
|
||||
OpenGLSupport.cpp \
|
||||
frontend/Util_Video.cpp
|
||||
|
||||
TEAKRA_SRCS = \
|
||||
ahbm.cpp \
|
||||
apbp.cpp \
|
||||
|
@ -76,18 +82,21 @@ BIZPLATFORM_SRCS = \
|
|||
BizPlatform/BizConfig.cpp \
|
||||
BizPlatform/BizFile.cpp \
|
||||
BizPlatform/BizLog.cpp \
|
||||
BizPlatform/BizOGL.cpp \
|
||||
BizPlatform/BizPlatformStubs.cpp \
|
||||
BizPlatform/BizSaveManager.cpp \
|
||||
BizPlatform/BizThread.cpp \
|
||||
|
||||
SRCS = \
|
||||
$(addprefix melonDS/src/,$(CORE_SRCS)) \
|
||||
$(addprefix melonDS/src/,$(CORE_GL_SRCS)) \
|
||||
$(addprefix melonDS/src/teakra/src/,$(TEAKRA_SRCS)) \
|
||||
$(addprefix melonDS/src/fatfs/,$(FATFS_SRCS)) \
|
||||
$(addprefix melonDS/src/,$(MISC_SRCS)) \
|
||||
$(BIZPLATFORM_SRCS) \
|
||||
BizDebugging.cpp \
|
||||
BizFileManager.cpp \
|
||||
BizGLPresenter.cpp \
|
||||
BizInterface.cpp \
|
||||
dthumb.c
|
||||
|
||||
|
|
|
@ -1 +1 @@
|
|||
Subproject commit 270f7083caaf477b7ca3456eed9721c3ef239f41
|
||||
Subproject commit b200c5476bce4a0c127c304105b3cb7d54f0cee4
|
Loading…
Reference in New Issue