Skip to content
Permalink
Browse files

Merge pull request #8343 from stenzek/fbdev

DolphinNoGUI: Add a FBDev platform
  • Loading branch information...
stenzek committed Nov 8, 2019
2 parents 2ebea1b + 0a75e71 commit a89fdb628c349ae112d6b9749b9ba7fba1e46b04
@@ -30,7 +30,7 @@ const std::array<std::pair<int, int>, 9> GLContext::s_desktop_opengl_versions =

GLContext::~GLContext() = default;

bool GLContext::Initialize(void* display_handle, void* window_handle, bool stereo, bool core)
bool GLContext::Initialize(const WindowSystemInfo& wsi, bool stereo, bool core)
{
return false;
}
@@ -108,7 +108,7 @@ std::unique_ptr<GLContext> GLContext::Create(const WindowSystemInfo& wsi, bool s
}
#endif
#if HAVE_EGL
if (wsi.type == WindowSystemType::Headless)
if (wsi.type == WindowSystemType::Headless || wsi.type == WindowSystemType::FBDev)
context = std::make_unique<GLContextEGL>();
#endif

@@ -119,7 +119,7 @@ std::unique_ptr<GLContext> GLContext::Create(const WindowSystemInfo& wsi, bool s
if (prefer_gles)
context->m_opengl_mode = Mode::OpenGLES;

if (!context->Initialize(wsi.display_connection, wsi.render_surface, stereo, core))
if (!context->Initialize(wsi, stereo, core))
return nullptr;

return context;
@@ -52,7 +52,7 @@ class GLContext
bool prefer_gles = false);

protected:
virtual bool Initialize(void* display_handle, void* window_handle, bool stereo, bool core);
virtual bool Initialize(const WindowSystemInfo& wsi, bool stereo, bool core);

Mode m_opengl_mode = Mode::Detect;

@@ -32,7 +32,7 @@ class GLContextAGL final : public GLContext
void SwapInterval(int interval) override;

protected:
bool Initialize(void* display_handle, void* window_handle, bool stereo, bool core) override;
bool Initialize(const WindowSystemInfo& wsi, bool stereo, bool core) override;

NSView* m_view = nullptr;
NSOpenGLContext* m_context = nullptr;
@@ -69,7 +69,7 @@ static bool AttachContextToView(NSOpenGLContext* context, NSView* view, u32* wid

// Create rendering window.
// Call browser: Core.cpp:EmuThread() > main.cpp:Video_Initialize()
bool GLContextAGL::Initialize(void* display_handle, void* window_handle, bool stereo, bool core)
bool GLContextAGL::Initialize(const WindowSystemInfo& wsi, bool stereo, bool core)
{
NSOpenGLPixelFormatAttribute attr[] = {
NSOpenGLPFADoubleBuffer,
@@ -92,10 +92,10 @@ static bool AttachContextToView(NSOpenGLContext* context, NSView* view, u32* wid
return false;
}

if (!window_handle)
if (!wsi.render_surface)
return true;

m_view = static_cast<NSView*>(window_handle);
m_view = static_cast<NSView*>(wsi.render_surface);
m_opengl_mode = Mode::OpenGL;
if (!AttachContextToView(m_context, m_view, &m_backbuffer_width, &m_backbuffer_height))
return false;
@@ -35,7 +35,7 @@ GLContextEGL::~GLContextEGL()

bool GLContextEGL::IsHeadless() const
{
return m_host_window == nullptr;
return m_wsi.type == WindowSystemType::Headless;
}

void GLContextEGL::Swap()
@@ -53,7 +53,7 @@ void* GLContextEGL::GetFuncAddress(const std::string& name)
return (void*)eglGetProcAddress(name.c_str());
}

void GLContextEGL::DetectMode(bool has_handle)
void GLContextEGL::DetectMode()
{
EGLint num_configs;
bool supportsGL = false, supportsGLES3 = false;
@@ -72,7 +72,7 @@ void GLContextEGL::DetectMode(bool has_handle)
EGL_RENDERABLE_TYPE,
renderable_type,
EGL_SURFACE_TYPE,
has_handle ? EGL_WINDOW_BIT : 0,
IsHeadless() ? 0 : EGL_WINDOW_BIT,
EGL_NONE};

// Get how many configs there are
@@ -130,27 +130,23 @@ void GLContextEGL::DetectMode(bool has_handle)

EGLDisplay GLContextEGL::OpenEGLDisplay()
{
return eglGetDisplay(EGL_DEFAULT_DISPLAY);
return eglGetDisplay(static_cast<EGLNativeDisplayType>(m_wsi.render_surface));
}

EGLNativeWindowType GLContextEGL::GetEGLNativeWindow(EGLConfig config)
{
return reinterpret_cast<EGLNativeWindowType>(EGL_DEFAULT_DISPLAY);
return reinterpret_cast<EGLNativeWindowType>(m_wsi.display_connection);
}

// Create rendering window.
// Call browser: Core.cpp:EmuThread() > main.cpp:Video_Initialize()
bool GLContextEGL::Initialize(void* display_handle, void* window_handle, bool stereo, bool core)
bool GLContextEGL::Initialize(const WindowSystemInfo& wsi, bool stereo, bool core)
{
const bool has_handle = !!window_handle;

EGLint egl_major, egl_minor;
bool supports_core_profile = false;

m_host_display = display_handle;
m_host_window = window_handle;
m_wsi = wsi;
m_egl_display = OpenEGLDisplay();

if (!m_egl_display)
{
INFO_LOG(VIDEO, "Error: eglGetDisplay() failed");
@@ -167,7 +163,7 @@ bool GLContextEGL::Initialize(void* display_handle, void* window_handle, bool st
EGLint num_configs;

if (m_opengl_mode == Mode::Detect)
DetectMode(has_handle);
DetectMode();

// attributes for a visual in RGBA format with at least
// 8 bits per color
@@ -180,7 +176,7 @@ bool GLContextEGL::Initialize(void* display_handle, void* window_handle, bool st
EGL_BLUE_SIZE,
8,
EGL_SURFACE_TYPE,
has_handle ? EGL_WINDOW_BIT : 0,
IsHeadless() ? 0 : EGL_WINDOW_BIT,
EGL_NONE};

std::vector<EGLint> ctx_attribs;
@@ -278,7 +274,7 @@ std::unique_ptr<GLContext> GLContextEGL::CreateSharedContext()
std::unique_ptr<GLContextEGL> new_context = std::make_unique<GLContextEGL>();
new_context->m_opengl_mode = m_opengl_mode;
new_context->m_egl_context = new_egl_context;
new_context->m_host_display = m_host_display;
new_context->m_wsi.display_connection = m_wsi.display_connection;
new_context->m_egl_display = m_egl_display;
new_context->m_config = m_config;
new_context->m_supports_surfaceless = m_supports_surfaceless;
@@ -294,7 +290,7 @@ std::unique_ptr<GLContext> GLContextEGL::CreateSharedContext()

bool GLContextEGL::CreateWindowSurface()
{
if (m_host_window)
if (!IsHeadless())
{
EGLNativeWindowType native_window = GetEGLNativeWindow(m_config);
m_egl_surface = eglCreateWindowSurface(m_egl_display, m_config, native_window, nullptr);
@@ -303,6 +299,17 @@ bool GLContextEGL::CreateWindowSurface()
INFO_LOG(VIDEO, "Error: eglCreateWindowSurface failed");
return false;
}

// Get dimensions from the surface.
EGLint surface_width = 1, surface_height = 1;
if (!eglQuerySurface(m_egl_display, m_egl_surface, EGL_WIDTH, &surface_width) ||
!eglQuerySurface(m_egl_display, m_egl_surface, EGL_HEIGHT, &surface_height))
{
WARN_LOG(VIDEO,
"Failed to get surface dimensions via eglQuerySurface. Size may be incorrect.");
}
m_backbuffer_width = static_cast<int>(surface_width);
m_backbuffer_height = static_cast<int>(surface_height);
}
else if (!m_supports_surfaceless)
{
@@ -342,7 +349,7 @@ bool GLContextEGL::MakeCurrent()

void GLContextEGL::UpdateSurface(void* window_handle)
{
m_host_window = window_handle;
m_wsi.render_surface = window_handle;
ClearCurrent();
DestroyWindowSurface();
CreateWindowSurface();
@@ -34,15 +34,14 @@ class GLContextEGL : public GLContext
virtual EGLDisplay OpenEGLDisplay();
virtual EGLNativeWindowType GetEGLNativeWindow(EGLConfig config);

bool Initialize(void* display_handle, void* window_handle, bool stereo, bool core) override;
bool Initialize(const WindowSystemInfo& wsi, bool stereo, bool core) override;

bool CreateWindowSurface();
void DestroyWindowSurface();
void DetectMode(bool has_handle);
void DetectMode();
void DestroyContext();

void* m_host_display = nullptr;
void* m_host_window = nullptr;
WindowSystemInfo m_wsi = {};

EGLConfig m_config;
bool m_supports_surfaceless = false;
@@ -14,8 +14,8 @@ EGLNativeWindowType GLContextEGLAndroid::GetEGLNativeWindow(EGLConfig config)
{
EGLint format;
eglGetConfigAttrib(m_egl_display, config, EGL_NATIVE_VISUAL_ID, &format);
ANativeWindow_setBuffersGeometry(static_cast<ANativeWindow*>(m_host_window), 0, 0, format);
m_backbuffer_width = ANativeWindow_getWidth(static_cast<ANativeWindow*>(m_host_window));
m_backbuffer_height = ANativeWindow_getHeight(static_cast<ANativeWindow*>(m_host_window));
return static_cast<EGLNativeWindowType>(m_host_window);
ANativeWindow_setBuffersGeometry(static_cast<ANativeWindow*>(m_wsi.render_surface), 0, 0, format);
m_backbuffer_width = ANativeWindow_getWidth(static_cast<ANativeWindow*>(m_wsi.render_surface));
m_backbuffer_height = ANativeWindow_getHeight(static_cast<ANativeWindow*>(m_wsi.render_surface));
return static_cast<EGLNativeWindowType>(m_wsi.render_surface);
}
@@ -21,7 +21,7 @@ void GLContextEGLX11::Update()

EGLDisplay GLContextEGLX11::OpenEGLDisplay()
{
return eglGetDisplay(static_cast<Display*>(m_host_display));
return eglGetDisplay(static_cast<Display*>(m_wsi.display_connection));
}

EGLNativeWindowType GLContextEGLX11::GetEGLNativeWindow(EGLConfig config)
@@ -33,14 +33,14 @@ EGLNativeWindowType GLContextEGLX11::GetEGLNativeWindow(EGLConfig config)
visTemplate.visualid = vid;

int nVisuals;
XVisualInfo* vi =
XGetVisualInfo(static_cast<Display*>(m_host_display), VisualIDMask, &visTemplate, &nVisuals);
XVisualInfo* vi = XGetVisualInfo(static_cast<Display*>(m_wsi.display_connection), VisualIDMask,
&visTemplate, &nVisuals);

if (m_render_window)
m_render_window.reset();

m_render_window = GLX11Window::Create(static_cast<Display*>(m_host_display),
reinterpret_cast<Window>(m_host_window), vi);
m_render_window = GLX11Window::Create(static_cast<Display*>(m_wsi.display_connection),
reinterpret_cast<Window>(m_wsi.render_surface), vi);
m_backbuffer_width = m_render_window->GetWidth();
m_backbuffer_height = m_render_window->GetHeight();

@@ -73,9 +73,9 @@ void GLContextGLX::Swap()

// Create rendering window.
// Call browser: Core.cpp:EmuThread() > main.cpp:Video_Initialize()
bool GLContextGLX::Initialize(void* display_handle, void* window_handle, bool stereo, bool core)
bool GLContextGLX::Initialize(const WindowSystemInfo& wsi, bool stereo, bool core)
{
m_display = static_cast<Display*>(display_handle);
m_display = static_cast<Display*>(wsi.display_connection);
int screen = DefaultScreen(m_display);

// checking glx version
@@ -204,7 +204,7 @@ bool GLContextGLX::Initialize(void* display_handle, void* window_handle, bool st
}
}

if (!CreateWindowSurface(reinterpret_cast<Window>(window_handle)))
if (!CreateWindowSurface(reinterpret_cast<Window>(wsi.render_surface)))
{
ERROR_LOG(VIDEO, "Error: CreateWindowSurface failed\n");
XSetErrorHandler(oldHandler);
@@ -33,7 +33,7 @@ class GLContextGLX final : public GLContext
void* GetFuncAddress(const std::string& name) override;

protected:
bool Initialize(void* display_handle, void* window_handle, bool stereo, bool core) override;
bool Initialize(const WindowSystemInfo& wsi, bool stereo, bool core) override;

Display* m_display = nullptr;
std::unique_ptr<GLX11Window> m_render_window;
@@ -223,13 +223,13 @@ void* GLContextWGL::GetFuncAddress(const std::string& name)

// Create rendering window.
// Call browser: Core.cpp:EmuThread() > main.cpp:Video_Initialize()
bool GLContextWGL::Initialize(void* display_handle, void* window_handle, bool stereo, bool core)
bool GLContextWGL::Initialize(const WindowSystemInfo& wsi, bool stereo, bool core)
{
if (!window_handle)
if (!wsi.render_surface)
return false;

RECT window_rect = {};
m_window_handle = reinterpret_cast<HWND>(window_handle);
m_window_handle = reinterpret_cast<HWND>(wsi.render_surface);
if (!GetClientRect(m_window_handle, &window_rect))
return false;

@@ -28,7 +28,7 @@ class GLContextWGL final : public GLContext
void* GetFuncAddress(const std::string& name) override;

protected:
bool Initialize(void* display_handle, void* window_handle, bool stereo, bool core) override;
bool Initialize(const WindowSystemInfo& wsi, bool stereo, bool core) override;

static HGLRC CreateCoreContext(HDC dc, HGLRC share_context);
static bool CreatePBuffer(HDC onscreen_dc, int width, int height, HANDLE* pbuffer_handle,
@@ -11,7 +11,8 @@ enum class WindowSystemType
MacOS,
Android,
X11,
Wayland
Wayland,
FBDev,
};

struct WindowSystemInfo
@@ -9,6 +9,10 @@ if(ENABLE_X11 AND X11_FOUND)
target_sources(dolphin-nogui PRIVATE PlatformX11.cpp)
endif()

if(${CMAKE_SYSTEM_NAME} STREQUAL "Linux")
target_sources(dolphin-nogui PRIVATE PlatformFBDev.cpp)
endif()

set_target_properties(dolphin-nogui PROPERTIES OUTPUT_NAME dolphin-emu-nogui)

target_link_libraries(dolphin-nogui
@@ -121,6 +121,11 @@ static std::unique_ptr<Platform> GetPlatform(const optparse::Values& options)
return Platform::CreateX11Platform();
#endif

#ifdef __linux__
if (platform_name == "fbdev" || platform_name.empty())
return Platform::CreateFBDevPlatform();
#endif

if (platform_name == "headless" || platform_name.empty())
return Platform::CreateHeadlessPlatform();

@@ -135,6 +140,10 @@ int main(int argc, char* argv[])
.help("Window platform to use [%choices]")
.choices({
"headless"
#ifdef __linux__
,
"fbdev"
#endif
#if HAVE_X11
,
"x11"
@@ -35,6 +35,9 @@ class Platform
#ifdef HAVE_X11
static std::unique_ptr<Platform> CreateX11Platform();
#endif
#ifdef __linux__
static std::unique_ptr<Platform> CreateFBDevPlatform();
#endif

protected:
void UpdateRunningFlag();

0 comments on commit a89fdb6

Please sign in to comment.
You can’t perform that action at this time.