Minimal port of Android EGL code from Dolphin.

This commit is contained in:
Henrik Rydgard 2015-12-13 18:38:26 +01:00
parent 2083f22dce
commit c2eb6a2fcb
6 changed files with 393 additions and 0 deletions

View File

@ -0,0 +1,228 @@
// Copyright 2012 Dolphin Emulator Project
// Licensed under GPLv2+
// Refer to the license.txt file included.
#include <array>
#include <cstdlib>
#include "Common/GL/GLInterface/EGL.h"
#include "Common/Log.h"
// Show the current FPS
void cInterfaceEGL::Swap()
{
eglSwapBuffers(egl_dpy, egl_surf);
}
void cInterfaceEGL::SwapInterval(int Interval)
{
eglSwapInterval(egl_dpy, Interval);
}
void* cInterfaceEGL::GetFuncAddress(const std::string& name)
{
return (void*)eglGetProcAddress(name.c_str());
}
void cInterfaceEGL::DetectMode()
{
if (s_opengl_mode != MODE_DETECT)
return;
EGLint num_configs;
bool supportsGL = false, supportsGLES2 = false, supportsGLES3 = false;
std::array<int, 3> renderable_types = {
EGL_OPENGL_BIT,
(1 << 6), /* EGL_OPENGL_ES3_BIT_KHR */
EGL_OPENGL_ES2_BIT,
};
for (auto renderable_type : renderable_types)
{
// 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_RENDERABLE_TYPE, renderable_type,
EGL_NONE
};
// Get how many configs there are
if (!eglChooseConfig( egl_dpy, attribs, nullptr, 0, &num_configs))
{
INFO_LOG(G3D, "Error: couldn't get an EGL visual config\n");
continue;
}
EGLConfig* config = new EGLConfig[num_configs];
// Get all the configurations
if (!eglChooseConfig(egl_dpy, attribs, config, num_configs, &num_configs))
{
INFO_LOG(G3D, "Error: couldn't get an EGL visual config\n");
delete[] config;
continue;
}
for (int i = 0; i < num_configs; ++i)
{
EGLint attribVal;
bool ret;
ret = eglGetConfigAttrib(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;
}
}
delete[] config;
}
if (supportsGL)
s_opengl_mode = GLInterfaceMode::MODE_OPENGL;
else if (supportsGLES3)
s_opengl_mode = GLInterfaceMode::MODE_OPENGLES3;
else if (supportsGLES2)
s_opengl_mode = GLInterfaceMode::MODE_OPENGLES2;
if (s_opengl_mode == GLInterfaceMode::MODE_DETECT) // Errored before we found a mode
s_opengl_mode = GLInterfaceMode::MODE_OPENGL; // Fall back to OpenGL
}
// Create rendering window.
// Call browser: Core.cpp:EmuThread() > main.cpp:Video_Initialize()
bool cInterfaceEGL::Create(void *window_handle, bool core)
{
const char *s;
EGLint egl_major, egl_minor;
egl_dpy = OpenDisplay();
if (!egl_dpy)
{
INFO_LOG(G3D, "Error: eglGetDisplay() failed\n");
return false;
}
if (!eglInitialize(egl_dpy, &egl_major, &egl_minor))
{
INFO_LOG(G3D, "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[] = {
EGL_RENDERABLE_TYPE, EGL_OPENGL_ES2_BIT,
EGL_RED_SIZE, 8,
EGL_GREEN_SIZE, 8,
EGL_BLUE_SIZE, 8,
EGL_NONE };
EGLint ctx_attribs[] = {
EGL_CONTEXT_CLIENT_VERSION, 2,
EGL_NONE
};
switch (s_opengl_mode)
{
case MODE_OPENGL:
attribs[1] = EGL_OPENGL_BIT;
ctx_attribs[0] = EGL_NONE;
break;
case MODE_OPENGLES2:
attribs[1] = EGL_OPENGL_ES2_BIT;
ctx_attribs[1] = 2;
break;
case MODE_OPENGLES3:
attribs[1] = (1 << 6); /* EGL_OPENGL_ES3_BIT_KHR */
ctx_attribs[1] = 3;
break;
default:
ERROR_LOG(G3D, "Unknown opengl mode set\n");
return false;
break;
}
if (!eglChooseConfig( egl_dpy, attribs, &config, 1, &num_configs))
{
INFO_LOG(G3D, "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);
EGLNativeWindowType host_window = (EGLNativeWindowType) window_handle;
EGLNativeWindowType native_window = InitializePlatform(host_window, config);
s = eglQueryString(egl_dpy, EGL_VERSION);
INFO_LOG(G3D, "EGL_VERSION = %s\n", s);
s = eglQueryString(egl_dpy, EGL_VENDOR);
INFO_LOG(G3D, "EGL_VENDOR = %s\n", s);
s = eglQueryString(egl_dpy, EGL_EXTENSIONS);
INFO_LOG(G3D, "EGL_EXTENSIONS = %s\n", s);
s = eglQueryString(egl_dpy, EGL_CLIENT_APIS);
INFO_LOG(G3D, "EGL_CLIENT_APIS = %s\n", s);
egl_ctx = eglCreateContext(egl_dpy, config, EGL_NO_CONTEXT, ctx_attribs );
if (!egl_ctx)
{
INFO_LOG(G3D, "Error: eglCreateContext failed\n");
exit(1);
}
egl_surf = eglCreateWindowSurface(egl_dpy, config, native_window, nullptr);
if (!egl_surf)
{
INFO_LOG(G3D, "Error: eglCreateWindowSurface failed\n");
exit(1);
}
return true;
}
bool cInterfaceEGL::MakeCurrent()
{
return eglMakeCurrent(egl_dpy, egl_surf, egl_surf, egl_ctx);
}
bool cInterfaceEGL::ClearCurrent()
{
return eglMakeCurrent(egl_dpy, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT);
}
// Close backend
void cInterfaceEGL::Shutdown()
{
ShutdownPlatform();
if (egl_ctx && !eglMakeCurrent(egl_dpy, egl_surf, egl_surf, egl_ctx))
NOTICE_LOG(G3D, "Could not release drawing context.");
if (egl_ctx)
{
eglMakeCurrent(egl_dpy, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT);
if (!eglDestroyContext(egl_dpy, egl_ctx))
NOTICE_LOG(G3D, "Could not destroy drawing context.");
if (!eglDestroySurface(egl_dpy, egl_surf))
NOTICE_LOG(G3D, "Could not destroy window surface.");
if (!eglTerminate(egl_dpy))
NOTICE_LOG(G3D, "Could not destroy display connection.");
egl_ctx = nullptr;
egl_dpy = nullptr;
}
}

View File

@ -0,0 +1,32 @@
// Copyright 2008 Dolphin Emulator Project
// Licensed under GPLv2+
// Refer to the license.txt file included.
#pragma once
#include <string>
#include <EGL/egl.h>
#include "Common/GL/GLInterfaceBase.h"
class cInterfaceEGL : public cInterfaceBase
{
protected:
void DetectMode();
EGLSurface egl_surf;
EGLContext egl_ctx;
EGLDisplay egl_dpy;
virtual EGLDisplay OpenDisplay() = 0;
virtual EGLNativeWindowType InitializePlatform(EGLNativeWindowType host_window, EGLConfig config) = 0;
virtual void ShutdownPlatform() = 0;
public:
void SwapInterval(int Interval);
void Swap();
void SetMode(u32 mode) { s_opengl_mode = mode; }
void* GetFuncAddress(const std::string& name);
bool Create(void *window_handle, bool core);
bool MakeCurrent();
bool ClearCurrent();
void Shutdown();
};

View File

@ -0,0 +1,28 @@
// Copyright 2014 Dolphin Emulator Project
// Licensed under GPLv2+
// Refer to the license.txt file included.
#include "Common/GL/GLInterface/EGLAndroid.h"
EGLDisplay cInterfaceEGLAndroid::OpenDisplay()
{
return eglGetDisplay(EGL_DEFAULT_DISPLAY);
}
EGLNativeWindowType cInterfaceEGLAndroid::InitializePlatform(EGLNativeWindowType host_window, EGLConfig config)
{
EGLint format;
eglGetConfigAttrib(egl_dpy, config, EGL_NATIVE_VISUAL_ID, &format);
ANativeWindow_setBuffersGeometry(host_window, 0, 0, format);
const int width = ANativeWindow_getWidth(host_window);
const int height = ANativeWindow_getHeight(host_window);
SetBackBufferDimensions(width, height);
return host_window;
}
void cInterfaceEGLAndroid::ShutdownPlatform()
{
}

View File

@ -0,0 +1,15 @@
// Copyright 2014 Dolphin Emulator Project
// Licensed under GPLv2+
// Refer to the license.txt file included.
#pragma once
#include "Common/GL/GLInterface/EGL.h"
class cInterfaceEGLAndroid : public cInterfaceEGL
{
protected:
EGLDisplay OpenDisplay() override;
EGLNativeWindowType InitializePlatform(EGLNativeWindowType host_window, EGLConfig config) override;
void ShutdownPlatform() override;
};

View File

@ -0,0 +1,40 @@
// Copyright 2014 Dolphin Emulator Project
// Licensed under GPLv2+
// Refer to the license.txt file included.
#include "Common/GL/GLInterfaceBase.h"
#ifdef ANDROID
#include "Common/GL/GLInterface/EGLAndroid.h"
#elif defined(__APPLE__)
#include "Common/GL/GLInterface/AGL.h"
#elif defined(_WIN32)
#include "Common/GL/GLInterface/WGL.h"
#elif HAVE_X11
#if defined(USE_EGL) && USE_EGL
#include "Common/GL/GLInterface/EGLX11.h"
#else
#include "Common/GL/GLInterface/GLX.h"
#endif
#else
#error Platform doesnt have a GLInterface
#endif
cInterfaceBase* HostGL_CreateGLInterface()
{
#ifdef ANDROID
return new cInterfaceEGLAndroid;
#elif defined(__APPLE__)
return new cInterfaceAGL;
#elif defined(_WIN32)
return new cInterfaceWGL;
#elif defined(HAVE_X11) && HAVE_X11
#if defined(USE_EGL) && USE_EGL
return new cInterfaceEGLX11;
#else
return new cInterfaceGLX;
#endif
#else
return nullptr;
#endif
}

View File

@ -0,0 +1,50 @@
// Copyright 2008 Dolphin Emulator Project
// Licensed under GPLv2+
// Refer to the license.txt file included.
#pragma once
#include <string>
#include "Common/CommonTypes.h"
enum GLInterfaceMode {
MODE_DETECT = 0,
MODE_OPENGL,
MODE_OPENGLES2,
MODE_OPENGLES3,
};
class cInterfaceBase
{
protected:
// Window dimensions.
u32 s_backbuffer_width;
u32 s_backbuffer_height;
u32 s_opengl_mode;
public:
cInterfaceBase() : s_backbuffer_width(0), s_backbuffer_height(0), s_opengl_mode(MODE_DETECT) {}
virtual ~cInterfaceBase() {}
virtual void Swap() {}
virtual void SetMode(u32 mode) { s_opengl_mode = GLInterfaceMode::MODE_OPENGL; }
virtual u32 GetMode() { return s_opengl_mode; }
virtual void* GetFuncAddress(const std::string& name) { return nullptr; }
virtual bool Create(void *window_handle, bool core = true) { return true; }
virtual bool MakeCurrent() { return true; }
virtual bool ClearCurrent() { return true; }
virtual void Shutdown() {}
virtual void SwapInterval(int Interval) { }
virtual u32 GetBackBufferWidth() { return s_backbuffer_width; }
virtual u32 GetBackBufferHeight() { return s_backbuffer_height; }
virtual void SetBackBufferDimensions(u32 W, u32 H) {s_backbuffer_width = W; s_backbuffer_height = H; }
virtual void Update() { }
virtual bool PeekMessages() { return false; }
};
extern cInterfaceBase *GLInterface;
// This function has to be defined along the Host_ functions from Core/Host.h.
// Current canonical implementation: DolphinWX/GLInterface/GLInterface.cpp.
cInterfaceBase* HostGL_CreateGLInterface();