Skip to content

Commit

Permalink
Merge of GL-AutoChoose.
Browse files Browse the repository at this point in the history
This branch is the final step of fully supporting both OpenGL and OpenGL ES in the same binary.
This of course only applies to EGL and won't work for GLX/AGL/WGL since they don't really support GL ES.
The changes here actually aren't too terrible, basically change every #ifdef USE_GLES to a runtime check.

This adds a DetectMode() function to the EGL context backend.
EGL will iterate through each of the configs and check for GL, GLES3_KHR, and GLES2 bits
After that it'll change the mode from _DETECT to whichever one is the best supported.
After that point we'll just create a context with the mode that was detected
  • Loading branch information
Sonicadvance1 committed Jan 18, 2014
1 parent 0a5bd83 commit 839df31
Show file tree
Hide file tree
Showing 17 changed files with 190 additions and 178 deletions.
32 changes: 5 additions & 27 deletions CMakeLists.txt
Expand Up @@ -7,8 +7,6 @@ option(ANDROID "Enables a build for Android" OFF)
option(USE_EGL "Enables EGL OpenGL Interface" OFF)
option(USE_X11 "Enables X11 Support" ON)
option(USE_WAYLAND "Enables Wayland Support" OFF)
option(USE_GLES "Enables GLES2 And EGL, disables OGL" OFF)
option(USE_GLES3 "Enables GLES3 and EGL" OFF)
option(USE_UPNP "Enables UPnP port mapping support" ON)
option(DISABLE_WX "Disable wxWidgets (use CLI interface)" OFF)
option(ENABLE_PCH "Use PCH to speed up compilation" ON)
Expand Down Expand Up @@ -125,8 +123,6 @@ if(${CMAKE_SYSTEM_PROCESSOR} MATCHES "^arm")
if(${ANDROID_NDK_ABI_NAME} MATCHES "armeabi-v7a")
add_definitions(-marm -march=armv7-a)
endif()
# Set generic options so you don't have to pass anything to cmake to build ARM
set(USE_GLES 1)
endif()

if(${CMAKE_SYSTEM_PROCESSOR} MATCHES "mips")
Expand Down Expand Up @@ -290,27 +286,12 @@ if(ANDROID)
set(USE_X11 0)
set(USE_WAYLAND 0)
set(USE_UPNP 0)
set(USE_GLES3 1)
set(USE_EGL True)
add_definitions(-DUSE_EGL=1)
endif()

include_directories(Externals/GL)

# For now GLES and EGL are tied to each other.
# Enabling GLES also disables the OpenGL plugin.
if(USE_GLES3)
message("GLES3 rendering enabled")
add_definitions(-DUSE_GLES=1 -DUSE_EGL=1 -DUSE_GLES3=1)
include_directories(Externals/GLES3)
set(USE_EGL True)
set(USE_GLES True)
else()
if(USE_GLES)
message("GLES2 rendering enabled. OpenGL disabled")
add_definitions(-DUSE_GLES=1)
add_definitions(-DUSE_EGL=1)
set(USE_EGL True)
endif()
endif()
# For now Wayland and EGL are tied to each other.
# The alternative would be an shm path
if(USE_WAYLAND)
Expand Down Expand Up @@ -352,12 +333,9 @@ endif()

if(NOT ANDROID)

if(NOT USE_GLES3)
include(FindOpenGL)
else()
set(X11_FOUND 1)
endif()

include(FindOpenGL)
include_directories(${OPENGL_INCLUDE_DIR})

include(FindALSA OPTIONAL)
if(ALSA_FOUND)
add_definitions(-DHAVE_ALSA=1)
Expand Down
6 changes: 1 addition & 5 deletions Source/Core/Core/CMakeLists.txt
Expand Up @@ -228,11 +228,7 @@ if(_M_ARM)
)
endif()

set(LIBS bdisasm inputcommon videosoftware sfml-network)

if(NOT USE_GLES OR USE_GLES3)
set(LIBS ${LIBS} videoogl)
endif()
set(LIBS bdisasm inputcommon videoogl videosoftware sfml-network)

if(LIBUSB_FOUND)
# Using shared LibUSB
Expand Down
2 changes: 1 addition & 1 deletion Source/Core/Core/Core.cpp
Expand Up @@ -702,7 +702,7 @@ void UpdateTitle()

// Settings are shown the same for both extended and summary info
std::string SSettings = StringFromFormat("%s %s | %s | %s", cpu_core_base->GetName(), _CoreParameter.bCPUThread ? "DC" : "SC",
g_video_backend->GetName().c_str(), _CoreParameter.bDSPHLE ? "HLE" : "LLE");
g_video_backend->GetDisplayName().c_str(), _CoreParameter.bDSPHLE ? "HLE" : "LLE");

// Use extended or summary information. The summary information does not print the ticks data,
// that's more of a debugging interest, it can always be optional of course if someone is interested.
Expand Down
5 changes: 0 additions & 5 deletions Source/Core/DolphinWX/GLInterface.h
Expand Up @@ -51,11 +51,6 @@ typedef struct {
#endif
} GLWindow;

enum GLInterfaceMode {
MODE_OPENGL = 0,
MODE_OPENGLES2,
MODE_OPENGLES3,
};
extern cInterfaceBase *GLInterface;
extern GLWindow GLWin;

Expand Down
103 changes: 84 additions & 19 deletions Source/Core/DolphinWX/GLInterface/EGL.cpp
Expand Up @@ -40,15 +40,96 @@ void* cInterfaceEGL::GetProcAddress(std::string name)
return (void*)eglGetProcAddress(name.c_str());
}

void cInterfaceEGL::DetectMode()
{
if (s_opengl_mode != MODE_DETECT)
return;

EGLint num_configs;
EGLConfig *config = NULL;
bool supportsGL = false, supportsGLES2 = false, supportsGLES3 = false;

// attributes for a visual in RGBA format with at least
// 8 bits per color
int attribs[] = {
EGL_RED_SIZE, 8,
EGL_GREEN_SIZE, 8,
EGL_BLUE_SIZE, 8,
EGL_NONE };

// Get how many configs there are
if (!eglChooseConfig( GLWin.egl_dpy, attribs, NULL, 0, &num_configs)) {
INFO_LOG(VIDEO, "Error: couldn't get an EGL visual config\n");
goto err_exit;
}

config = new EGLConfig[num_configs];

// Get all the configurations
if (!eglChooseConfig(GLWin.egl_dpy, attribs, config, num_configs, &num_configs))
{
INFO_LOG(VIDEO, "Error: couldn't get an EGL visual config\n");
goto err_exit;
}

for (int i = 0; i < num_configs; ++i)
{
EGLint attribVal;
bool ret;
ret = eglGetConfigAttrib(GLWin.egl_dpy, config[i], EGL_RENDERABLE_TYPE, &attribVal);
if (ret)
{
if (attribVal & EGL_OPENGL_BIT)
supportsGL = true;
if (attribVal & (1 << 6)) /* EGL_OPENGL_ES3_BIT_KHR */
supportsGLES3 = true;
if (attribVal & EGL_OPENGL_ES2_BIT)
supportsGLES2 = true;
}
}
if (supportsGL)

This comment has been minimized.

Copy link
@xsacha

xsacha Aug 5, 2014

Contributor

We have one here that supports OpenGL 2.x and GLES3. Unfortunately it's hitting this and tries the OpenGL instead.
Complains it has GLSL 1.2.0 instead of GLSL1.3.0 and can't compile a shader.

Exynos 5 Octa with Mali-T628

s_opengl_mode = GLInterfaceMode::MODE_OPENGL;
else if (supportsGLES3)
s_opengl_mode = GLInterfaceMode::MODE_OPENGLES3;
else if (supportsGLES2)
s_opengl_mode = GLInterfaceMode::MODE_OPENGLES2;
err_exit:
if (s_opengl_mode == GLInterfaceMode::MODE_DETECT) // Errored before we found a mode
s_opengl_mode = GLInterfaceMode::MODE_OPENGL; // Fall back to OpenGL
if (config)
delete[] config;
}

// Create rendering window.
// Call browser: Core.cpp:EmuThread() > main.cpp:Video_Initialize()
bool cInterfaceEGL::Create(void *&window_handle)
{
const char *s;
EGLint egl_major, egl_minor;

if(!Platform.SelectDisplay())
return false;

GLWin.egl_dpy = Platform.EGLGetDisplay();

if (!GLWin.egl_dpy) {
INFO_LOG(VIDEO, "Error: eglGetDisplay() failed\n");
return false;
}

GLWin.platform = Platform.platform;

if (!eglInitialize(GLWin.egl_dpy, &egl_major, &egl_minor)) {
INFO_LOG(VIDEO, "Error: eglInitialize() failed\n");
return false;
}

/* Detection code */
EGLConfig config;
EGLint num_configs;

DetectMode();

// attributes for a visual in RGBA format with at least
// 8 bits per color
int attribs[] = {
Expand Down Expand Up @@ -82,32 +163,16 @@ bool cInterfaceEGL::Create(void *&window_handle)
break;
}

if(!Platform.SelectDisplay())
return false;

GLWin.egl_dpy = Platform.EGLGetDisplay();

if (!GLWin.egl_dpy) {
INFO_LOG(VIDEO, "Error: eglGetDisplay() failed\n");
return false;
}

GLWin.platform = Platform.platform;

if (!eglInitialize(GLWin.egl_dpy, &egl_major, &egl_minor)) {
INFO_LOG(VIDEO, "Error: eglInitialize() failed\n");
return false;
if (!eglChooseConfig( GLWin.egl_dpy, attribs, &config, 1, &num_configs)) {
INFO_LOG(VIDEO, "Error: couldn't get an EGL visual config\n");
exit(1);
}

if (s_opengl_mode == MODE_OPENGL)
eglBindAPI(EGL_OPENGL_API);
else
eglBindAPI(EGL_OPENGL_ES_API);

if (!eglChooseConfig( GLWin.egl_dpy, attribs, &config, 1, &num_configs)) {
INFO_LOG(VIDEO, "Error: couldn't get an EGL visual config\n");
exit(1);
}

if (!Platform.Init(config))
return false;
Expand Down
2 changes: 2 additions & 0 deletions Source/Core/DolphinWX/GLInterface/EGL.h
Expand Up @@ -26,10 +26,12 @@ class cInterfaceEGL : public cInterfaceBase
{
private:
cPlatform Platform;
void DetectMode();
public:
friend class cPlatform;
void SwapInterval(int Interval);
void Swap();
void SetMode(u32 mode) { s_opengl_mode = GLInterfaceMode::MODE_DETECT; }
void UpdateFPSDisplay(const char *Text);
void* GetProcAddress(std::string name);
bool Create(void *&window_handle);
Expand Down
9 changes: 8 additions & 1 deletion Source/Core/DolphinWX/GLInterface/InterfaceBase.h
Expand Up @@ -4,6 +4,13 @@

#ifndef _GLINTERFACEBASE_H_
#define _GLINTERFACEBASE_H_
enum GLInterfaceMode {
MODE_DETECT = 0,
MODE_OPENGL,
MODE_OPENGLES2,
MODE_OPENGLES3,
};

class cInterfaceBase
{
protected:
Expand All @@ -15,7 +22,7 @@ class cInterfaceBase
public:
virtual void Swap() {}
virtual void UpdateFPSDisplay(const char *Text) {}
virtual void SetMode(u32 mode) { s_opengl_mode = mode; }
virtual void SetMode(u32 mode) { s_opengl_mode = GLInterfaceMode::MODE_OPENGL; }
virtual u32 GetMode() { return s_opengl_mode; }
virtual void* GetProcAddress(std::string name) { return NULL; }
virtual bool Create(void *&window_handle) { return true; }
Expand Down
6 changes: 0 additions & 6 deletions Source/Core/DolphinWX/GLInterface/Platform.h
Expand Up @@ -155,12 +155,6 @@ typedef struct {
#endif
} GLWindow;

enum GLInterfaceMode {
MODE_OPENGL = 0,
MODE_OPENGLES2,
MODE_OPENGLES3,
};

extern cInterfaceBase *GLInterface;
extern GLWindow GLWin;

Expand Down
4 changes: 1 addition & 3 deletions Source/Core/VideoBackends/CMakeLists.txt
@@ -1,5 +1,3 @@
if(NOT USE_GLES OR USE_GLES3)
add_subdirectory(OGL)
endif()
add_subdirectory(OGL)
add_subdirectory(Software)
# TODO: Add other backends here!
19 changes: 1 addition & 18 deletions Source/Core/VideoBackends/OGL/GLUtil.cpp
Expand Up @@ -29,7 +29,7 @@ unsigned int VideoBackend::PeekMessages()
void VideoBackend::UpdateFPSDisplay(const char *text)
{
char temp[100];
snprintf(temp, sizeof temp, "%s | OpenGL | %s", scm_rev_str, text);
snprintf(temp, sizeof temp, "%s | %s | %s", scm_rev_str, GetDisplayName().c_str(), text);
return GLInterface->UpdateFPSDisplay(temp);
}

Expand Down Expand Up @@ -122,21 +122,6 @@ GLuint OpenGL_ReportGLError(const char *function, const char *file, int line)
return err;
}

void OpenGL_ReportARBProgramError()
{
#ifndef USE_GLES
const GLubyte* pstr = glGetString(GL_PROGRAM_ERROR_STRING_ARB);
if (pstr != NULL && pstr[0] != 0)
{
GLint loc = 0;
glGetIntegerv(GL_PROGRAM_ERROR_POSITION_ARB, &loc);
ERROR_LOG(VIDEO, "Program error at %d: ", loc);
ERROR_LOG(VIDEO, "%s", (char*)pstr);
ERROR_LOG(VIDEO, "\n");
}
#endif
}

bool OpenGL_ReportFBOError(const char *function, const char *file, int line)
{
unsigned int fbo_status = glCheckFramebufferStatus(GL_FRAMEBUFFER);
Expand All @@ -151,14 +136,12 @@ bool OpenGL_ReportFBOError(const char *function, const char *file, int line)
case GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT:
error = "INCOMPLETE_MISSING_ATTACHMENT";
break;
#ifndef USE_GLES
case GL_FRAMEBUFFER_INCOMPLETE_DRAW_BUFFER:
error = "INCOMPLETE_DRAW_BUFFER";
break;
case GL_FRAMEBUFFER_INCOMPLETE_READ_BUFFER:
error = "INCOMPLETE_READ_BUFFER";
break;
#endif
case GL_FRAMEBUFFER_UNSUPPORTED:
error = "UNSUPPORTED";
break;
Expand Down
16 changes: 0 additions & 16 deletions Source/Core/VideoBackends/OGL/GLUtil.h
Expand Up @@ -17,19 +17,6 @@
#define GL_TEXTURE_STENCIL_SIZE_EXT 0x88F1
#endif

#ifdef USE_GLES
#define TEX2D GL_TEXTURE_2D
#define PREC "highp"
#define TEXTYPE "sampler2D"
#define TEXFUNC "texture2D"
#else
#define TEX2D GL_TEXTURE_RECTANGLE_ARB
#define PREC
#define TEXTYPE "sampler2DRect"
#define TEXFUNC "texture2DRect"
#endif


#ifndef _WIN32

#include <sys/types.h>
Expand All @@ -41,20 +28,17 @@ void InitInterface();
GLuint OpenGL_CompileProgram(const char *vertexShader, const char *fragmentShader);

// Error reporting - use the convenient macros.
void OpenGL_ReportARBProgramError();
GLuint OpenGL_ReportGLError(const char *function, const char *file, int line);
bool OpenGL_ReportFBOError(const char *function, const char *file, int line);

#if defined(_DEBUG) || defined(DEBUGFAST)
#define GL_REPORT_ERROR() OpenGL_ReportGLError(__FUNCTION__, __FILE__, __LINE__)
#define GL_REPORT_ERRORD() OpenGL_ReportGLError(__FUNCTION__, __FILE__, __LINE__)
#define GL_REPORT_FBO_ERROR() OpenGL_ReportFBOError(__FUNCTION__, __FILE__, __LINE__)
#define GL_REPORT_PROGRAM_ERROR() OpenGL_ReportARBProgramError()
#else
__forceinline GLenum GL_REPORT_ERROR() { return GL_NO_ERROR; }
#define GL_REPORT_ERRORD() (void)GL_NO_ERROR
#define GL_REPORT_FBO_ERROR() (void)true
#define GL_REPORT_PROGRAM_ERROR() (void)0
#endif

// this should be removed in future, but as long as glsl is unstable, we should really read this messages
Expand Down
10 changes: 5 additions & 5 deletions Source/Core/VideoBackends/OGL/main.cpp
Expand Up @@ -98,7 +98,10 @@ std::string VideoBackend::GetName()

std::string VideoBackend::GetDisplayName()
{
return "OpenGL";
if (g_renderer && GLInterface->GetMode() == GLInterfaceMode::MODE_OPENGLES3)
return "OpenGLES";
else
return "OpenGL";
}

void GetShaders(std::vector<std::string> &shaders)
Expand Down Expand Up @@ -179,10 +182,7 @@ bool VideoBackend::Initialize(void *&window_handle)
UpdateActiveConfig();

InitInterface();
GLInterface->SetMode(GLInterfaceMode::MODE_OPENGL);
#ifdef USE_GLES3
GLInterface->SetMode(GLInterfaceMode::MODE_OPENGLES3);
#endif
GLInterface->SetMode(GLInterfaceMode::MODE_DETECT);
if (!GLInterface->Create(window_handle))
return false;

Expand Down

0 comments on commit 839df31

Please sign in to comment.