mirror of
https://github.com/wheremyfoodat/Panda3DS.git
synced 2025-06-09 04:21:38 +12:00
Support GLES on desktop
This commit is contained in:
parent
80ccede765
commit
cb8b13e129
15 changed files with 125 additions and 59 deletions
|
@ -56,10 +56,6 @@ void RendererGL::reset() {
|
|||
void RendererGL::initGraphicsContextInternal() {
|
||||
gl.reset();
|
||||
|
||||
#if defined(USING_GLES) || defined(__ANDROID__)
|
||||
driverInfo.usingGLES = true;
|
||||
#endif
|
||||
|
||||
auto gl_resources = cmrc::RendererGL::get_filesystem();
|
||||
auto vertexShaderSource = gl_resources.open("opengl_vertex_shader.vert");
|
||||
auto fragmentShaderSource = gl_resources.open("opengl_fragment_shader.frag");
|
||||
|
@ -69,16 +65,7 @@ void RendererGL::initGraphicsContextInternal() {
|
|||
triangleProgram.create({vert, frag});
|
||||
initUbershader(triangleProgram);
|
||||
|
||||
auto displayVertexShaderSource = gl_resources.open("opengl_display.vert");
|
||||
auto displayFragmentShaderSource = gl_resources.open("opengl_display.frag");
|
||||
|
||||
OpenGL::Shader vertDisplay({displayVertexShaderSource.begin(), displayVertexShaderSource.size()}, OpenGL::Vertex);
|
||||
OpenGL::Shader fragDisplay({displayFragmentShaderSource.begin(), displayFragmentShaderSource.size()}, OpenGL::Fragment);
|
||||
displayProgram.create({vertDisplay, fragDisplay});
|
||||
|
||||
gl.useProgram(displayProgram);
|
||||
glUniform1i(OpenGL::uniformLocation(displayProgram, "u_texture"), 0); // Init sampler object
|
||||
|
||||
compileDisplayShader();
|
||||
// Create stream buffers for vertex, index and uniform buffers
|
||||
static constexpr usize hwIndexBufferSize = 2_MB;
|
||||
static constexpr usize hwVertexBufferSize = 16_MB;
|
||||
|
@ -1156,6 +1143,19 @@ void RendererGL::initUbershader(OpenGL::Program& program) {
|
|||
glUniform1i(OpenGL::uniformLocation(program, "u_tex_luts"), 3);
|
||||
}
|
||||
|
||||
void RendererGL::compileDisplayShader() {
|
||||
auto gl_resources = cmrc::RendererGL::get_filesystem();
|
||||
auto displayVertexShaderSource = driverInfo.usingGLES ? gl_resources.open("opengl_es_display.vert") : gl_resources.open("opengl_display.vert");
|
||||
auto displayFragmentShaderSource = driverInfo.usingGLES ? gl_resources.open("opengl_es_display.frag") : gl_resources.open("opengl_display.frag");
|
||||
|
||||
OpenGL::Shader vertDisplay({displayVertexShaderSource.begin(), displayVertexShaderSource.size()}, OpenGL::Vertex);
|
||||
OpenGL::Shader fragDisplay({displayFragmentShaderSource.begin(), displayFragmentShaderSource.size()}, OpenGL::Fragment);
|
||||
displayProgram.create({vertDisplay, fragDisplay});
|
||||
|
||||
gl.useProgram(displayProgram);
|
||||
glUniform1i(OpenGL::uniformLocation(displayProgram, "u_texture"), 0); // Init sampler object
|
||||
}
|
||||
|
||||
void RendererGL::accelerateVertexUpload(ShaderUnit& shaderUnit, PICA::DrawAcceleration* accel) {
|
||||
u32 buffer = 0; // Vertex buffer index for non-fixed attributes
|
||||
u32 attrCount = 0;
|
||||
|
@ -1250,4 +1250,18 @@ void RendererGL::accelerateVertexUpload(ShaderUnit& shaderUnit, PICA::DrawAccele
|
|||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void RendererGL::setupGLES() {
|
||||
driverInfo.usingGLES = true;
|
||||
|
||||
// OpenGL ES hardware is typically way too slow to use the ubershader (eg RPi, mobile phones, handhelds) or has other issues with it.
|
||||
// So, display a warning and turn them off on OpenGL ES.
|
||||
if (emulatorConfig->useUbershaders) {
|
||||
emulatorConfig->useUbershaders = false;
|
||||
Helpers::warn("Ubershaders enabled on OpenGL ES. This usually results in a worse experience, turning it off...");
|
||||
}
|
||||
|
||||
// Stub out logic operations so that calling them doesn't crash the emulator
|
||||
glLogicOp = [](GLenum) {};
|
||||
}
|
|
@ -117,7 +117,6 @@ std::filesystem::path Emulator::getConfigPath() {
|
|||
#endif
|
||||
|
||||
void Emulator::step() {}
|
||||
void Emulator::render() {}
|
||||
|
||||
// Only resume if a ROM is properly loaded
|
||||
void Emulator::resume() {
|
||||
|
|
10
src/host_shaders/opengl_es_display.frag
Normal file
10
src/host_shaders/opengl_es_display.frag
Normal file
|
@ -0,0 +1,10 @@
|
|||
#version 310 es
|
||||
precision mediump float;
|
||||
|
||||
in vec2 UV;
|
||||
out vec4 FragColor;
|
||||
|
||||
uniform sampler2D u_texture;
|
||||
void main() {
|
||||
FragColor = texture(u_texture, UV);
|
||||
}
|
25
src/host_shaders/opengl_es_display.vert
Normal file
25
src/host_shaders/opengl_es_display.vert
Normal file
|
@ -0,0 +1,25 @@
|
|||
#version 310 es
|
||||
precision mediump float;
|
||||
|
||||
out vec2 UV;
|
||||
|
||||
void main() {
|
||||
const vec4 positions[4] = vec4[](
|
||||
vec4(-1.0, 1.0, 1.0, 1.0), // Top-left
|
||||
vec4(1.0, 1.0, 1.0, 1.0), // Top-right
|
||||
vec4(-1.0, -1.0, 1.0, 1.0), // Bottom-left
|
||||
vec4(1.0, -1.0, 1.0, 1.0) // Bottom-right
|
||||
);
|
||||
|
||||
// The 3DS displays both screens' framebuffer rotated 90 deg counter clockwise
|
||||
// So we adjust our texcoords accordingly
|
||||
const vec2 texcoords[4] = vec2[](
|
||||
vec2(1.0, 1.0), // Top-right
|
||||
vec2(1.0, 0.0), // Bottom-right
|
||||
vec2(0.0, 1.0), // Top-left
|
||||
vec2(0.0, 0.0) // Bottom-left
|
||||
);
|
||||
|
||||
gl_Position = positions[gl_VertexID];
|
||||
UV = texcoords[gl_VertexID];
|
||||
}
|
|
@ -118,6 +118,7 @@ void HydraCore::resetContext() {
|
|||
if (!gladLoadGLES2Loader(reinterpret_cast<GLADloadproc>(getProcAddress))) {
|
||||
Helpers::panic("OpenGL ES init failed");
|
||||
}
|
||||
emulator->getRenderer()->setupGLES();
|
||||
#else
|
||||
if (!gladLoadGLLoader(reinterpret_cast<GLADloadproc>(getProcAddress))) {
|
||||
Helpers::panic("OpenGL init failed");
|
||||
|
|
|
@ -78,6 +78,7 @@ AlberFunction(void, Initialize)(JNIEnv* env, jobject obj) {
|
|||
}
|
||||
|
||||
__android_log_print(ANDROID_LOG_INFO, "AlberDriver", "OpenGL ES %d.%d", GLVersion.major, GLVersion.minor);
|
||||
emulator->getRenderer()->setupGLES();
|
||||
emulator->initGraphicsContext(nullptr);
|
||||
}
|
||||
|
||||
|
@ -153,7 +154,6 @@ int AndroidUtils::openDocument(const char* path, const char* perms) {
|
|||
|
||||
jstring uri = env->NewStringUTF(path);
|
||||
jstring jmode = env->NewStringUTF(perms);
|
||||
|
||||
jint result = env->CallStaticIntMethod(alberClass, alberClassOpenDocument, uri, jmode);
|
||||
|
||||
env->DeleteLocalRef(uri);
|
||||
|
|
|
@ -17,7 +17,8 @@ static retro_input_state_t inputStateCallback;
|
|||
static retro_hw_render_callback hwRender;
|
||||
static std::filesystem::path savePath;
|
||||
|
||||
static bool screenTouched;
|
||||
static bool screenTouched = false;
|
||||
static bool usingGLES = false;
|
||||
|
||||
std::unique_ptr<Emulator> emulator;
|
||||
RendererGL* renderer;
|
||||
|
@ -35,15 +36,19 @@ static void* getGLProcAddress(const char* name) {
|
|||
}
|
||||
|
||||
static void videoResetContext() {
|
||||
#ifdef USING_GLES
|
||||
if (!gladLoadGLES2Loader(reinterpret_cast<GLADloadproc>(getGLProcAddress))) {
|
||||
Helpers::panic("OpenGL ES init failed");
|
||||
if (usingGLES) {
|
||||
if (!gladLoadGLES2Loader(reinterpret_cast<GLADloadproc>(getGLProcAddress))) {
|
||||
Helpers::panic("OpenGL ES init failed");
|
||||
}
|
||||
|
||||
emulator->getRenderer()->setupGLES();
|
||||
}
|
||||
#else
|
||||
if (!gladLoadGLLoader(reinterpret_cast<GLADloadproc>(getGLProcAddress))) {
|
||||
Helpers::panic("OpenGL init failed");
|
||||
|
||||
else {
|
||||
if (!gladLoadGLLoader(reinterpret_cast<GLADloadproc>(getGLProcAddress))) {
|
||||
Helpers::panic("OpenGL init failed");
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
emulator->initGraphicsContext(nullptr);
|
||||
}
|
||||
|
@ -73,6 +78,7 @@ static bool setHWRender(retro_hw_context_type type) {
|
|||
hwRender.version_minor = 1;
|
||||
|
||||
if (envCallback(RETRO_ENVIRONMENT_SET_HW_RENDER, &hwRender)) {
|
||||
usingGLES = true;
|
||||
return true;
|
||||
}
|
||||
break;
|
||||
|
|
|
@ -140,6 +140,10 @@ MainWindow::MainWindow(QApplication* app, QWidget* parent) : QMainWindow(parent)
|
|||
glContext->MakeCurrent();
|
||||
glContext->SetSwapInterval(emu->getConfig().vsyncEnabled ? 1 : 0);
|
||||
|
||||
if (glContext->IsGLES()) {
|
||||
emu->getRenderer()->setupGLES();
|
||||
}
|
||||
|
||||
emu->initGraphicsContext(glContext);
|
||||
} else if (usingVk) {
|
||||
Helpers::panic("Vulkan on Qt is currently WIP, try the SDL frontend instead!");
|
||||
|
|
|
@ -60,11 +60,12 @@ void ScreenWidget::resizeSurface(u32 width, u32 height) {
|
|||
}
|
||||
|
||||
bool ScreenWidget::createGLContext() {
|
||||
// List of GL context versions we will try. Anything 4.1+ is good
|
||||
static constexpr std::array<GL::Context::Version, 6> versionsToTry = {
|
||||
// List of GL context versions we will try. Anything 4.1+ is good for desktop OpenGL, and 3.1+ for OpenGL ES
|
||||
static constexpr std::array<GL::Context::Version, 8> versionsToTry = {
|
||||
GL::Context::Version{GL::Context::Profile::Core, 4, 6}, GL::Context::Version{GL::Context::Profile::Core, 4, 5},
|
||||
GL::Context::Version{GL::Context::Profile::Core, 4, 4}, GL::Context::Version{GL::Context::Profile::Core, 4, 3},
|
||||
GL::Context::Version{GL::Context::Profile::Core, 4, 2}, GL::Context::Version{GL::Context::Profile::Core, 4, 1},
|
||||
GL::Context::Version{GL::Context::Profile::ES, 3, 2}, GL::Context::Version{GL::Context::Profile::ES, 3, 1},
|
||||
};
|
||||
|
||||
std::optional<WindowInfo> windowInfo = getWindowInfo();
|
||||
|
@ -72,6 +73,10 @@ bool ScreenWidget::createGLContext() {
|
|||
this->windowInfo = *windowInfo;
|
||||
|
||||
glContext = GL::Context::Create(*getWindowInfo(), versionsToTry);
|
||||
if (glContext == nullptr) {
|
||||
return false;
|
||||
}
|
||||
|
||||
glContext->DoneCurrent();
|
||||
}
|
||||
|
||||
|
|
|
@ -71,11 +71,27 @@ FrontendSDL::FrontendSDL() : keyboardMappings(InputMappings::defaultKeyboardMapp
|
|||
|
||||
glContext = SDL_GL_CreateContext(window);
|
||||
if (glContext == nullptr) {
|
||||
Helpers::panic("OpenGL context creation failed: %s", SDL_GetError());
|
||||
}
|
||||
Helpers::warn("OpenGL context creation failed: %s\nTrying again with OpenGL ES.", SDL_GetError());
|
||||
|
||||
if (!gladLoadGLLoader(reinterpret_cast<GLADloadproc>(SDL_GL_GetProcAddress))) {
|
||||
Helpers::panic("OpenGL init failed");
|
||||
// Some low end devices (eg RPi, emulation handhelds) don't support desktop GL, but only OpenGL ES, so fall back to that if GL context
|
||||
// creation failed
|
||||
SDL_GL_SetAttribute(SDL_GL_CONTEXT_PROFILE_MASK, SDL_GL_CONTEXT_PROFILE_ES);
|
||||
SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, 3);
|
||||
SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, 1);
|
||||
glContext = SDL_GL_CreateContext(window);
|
||||
if (glContext == nullptr) {
|
||||
Helpers::panic("OpenGL context creation failed: %s", SDL_GetError());
|
||||
}
|
||||
|
||||
if (!gladLoadGLES2Loader(reinterpret_cast<GLADloadproc>(SDL_GL_GetProcAddress))) {
|
||||
Helpers::panic("OpenGL init failed");
|
||||
}
|
||||
|
||||
emu.getRenderer()->setupGLES();
|
||||
} else {
|
||||
if (!gladLoadGLLoader(reinterpret_cast<GLADloadproc>(SDL_GL_GetProcAddress))) {
|
||||
Helpers::panic("OpenGL init failed");
|
||||
}
|
||||
}
|
||||
|
||||
SDL_GL_SetSwapInterval(config.vsyncEnabled ? 1 : 0);
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue