mirror of
https://github.com/izzy2lost/dolphin.git
synced 2026-06-19 01:16:48 -07:00
Merge pull request #7450 from stenzek/glcontext
GLInterface refactoring/cleanup and runtime platform selection
This commit is contained in:
@@ -0,0 +1,54 @@
|
||||
# from https://raw.githubusercontent.com/WebKit/webkit/master/Source/cmake/FindEGL.cmake
|
||||
# - Try to Find EGL
|
||||
# Once done, this will define
|
||||
#
|
||||
# EGL_FOUND - system has EGL installed.
|
||||
# EGL_INCLUDE_DIRS - directories which contain the EGL headers.
|
||||
# EGL_LIBRARIES - libraries required to link against EGL.
|
||||
# EGL_DEFINITIONS - Compiler switches required for using EGL.
|
||||
#
|
||||
# Copyright (C) 2012 Intel Corporation. All rights reserved.
|
||||
#
|
||||
# Redistribution and use in source and binary forms, with or without
|
||||
# modification, are permitted provided that the following conditions
|
||||
# are met:
|
||||
# 1. Redistributions of source code must retain the above copyright
|
||||
# notice, this list of conditions and the following disclaimer.
|
||||
# 2. Redistributions in binary form must reproduce the above copyright
|
||||
# notice, this list of conditions and the following disclaimer in the
|
||||
# documentation and/or other materials provided with the distribution.
|
||||
#
|
||||
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER AND ITS CONTRIBUTORS ``AS
|
||||
# IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
|
||||
# THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
# PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR ITS
|
||||
# CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||
# EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||
# PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
|
||||
# OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
|
||||
# WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
|
||||
# OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
|
||||
# ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
|
||||
find_package(PkgConfig)
|
||||
|
||||
pkg_check_modules(PC_EGL egl)
|
||||
|
||||
if (PC_EGL_FOUND)
|
||||
set(EGL_DEFINITIONS ${PC_EGL_CFLAGS_OTHER})
|
||||
endif ()
|
||||
|
||||
find_path(EGL_INCLUDE_DIRS NAMES EGL/egl.h
|
||||
HINTS ${PC_EGL_INCLUDEDIR} ${PC_EGL_INCLUDE_DIRS}
|
||||
)
|
||||
|
||||
set(EGL_NAMES ${EGL_NAMES} egl EGL)
|
||||
find_library(EGL_LIBRARIES NAMES ${EGL_NAMES}
|
||||
HINTS ${PC_EGL_LIBDIR} ${PC_EGL_LIBRARY_DIRS}
|
||||
)
|
||||
|
||||
include(FindPackageHandleStandardArgs)
|
||||
FIND_PACKAGE_HANDLE_STANDARD_ARGS(EGL DEFAULT_MSG EGL_INCLUDE_DIRS EGL_LIBRARIES)
|
||||
|
||||
mark_as_advanced(EGL_INCLUDE_DIRS EGL_LIBRARIES)
|
||||
+26
-50
@@ -16,8 +16,13 @@ project(dolphin-emu)
|
||||
# unique name here.
|
||||
set(DISTRIBUTOR "None" CACHE STRING "Name of the distributor.")
|
||||
|
||||
option(USE_EGL "Enables EGL OpenGL Interface" OFF)
|
||||
option(TRY_X11 "Enables X11 Support" ON)
|
||||
if(UNIX AND NOT APPLE AND NOT ANDROID)
|
||||
option(ENABLE_X11 "Enables X11 Support" ON)
|
||||
endif()
|
||||
if(NOT WIN32 AND NOT APPLE)
|
||||
option(ENABLE_EGL "Enables EGL OpenGL Interface" ON)
|
||||
endif()
|
||||
|
||||
option(USE_SHARED_ENET "Use shared libenet if found rather than Dolphin's soon-to-compatibly-diverge version" OFF)
|
||||
option(USE_UPNP "Enables UPnP port mapping support" ON)
|
||||
option(ENABLE_QT "Enable Qt (Default)" ON)
|
||||
@@ -87,13 +92,8 @@ set_property(GLOBAL PROPERTY USE_FOLDERS ON)
|
||||
|
||||
# Set up paths
|
||||
set(bindir ${CMAKE_INSTALL_PREFIX}/bin CACHE PATH "bindir")
|
||||
if(HAIKU)
|
||||
set(datadir ${CMAKE_INSTALL_PREFIX}/data/dolphin-emu CACHE PATH "datadir")
|
||||
set(mandir ${CMAKE_INSTALL_PREFIX}/documentation/man CACHE PATH "mandir")
|
||||
else()
|
||||
set(datadir ${CMAKE_INSTALL_PREFIX}/share/dolphin-emu CACHE PATH "datadir")
|
||||
set(mandir ${CMAKE_INSTALL_PREFIX}/share/man CACHE PATH "mandir")
|
||||
endif()
|
||||
set(datadir ${CMAKE_INSTALL_PREFIX}/share/dolphin-emu CACHE PATH "datadir")
|
||||
set(mandir ${CMAKE_INSTALL_PREFIX}/share/man CACHE PATH "mandir")
|
||||
add_definitions(-DDATA_DIR="${datadir}/")
|
||||
|
||||
if(CMAKE_SYSROOT)
|
||||
@@ -370,9 +370,7 @@ if(ANDROID)
|
||||
# but not as a shared library. We want an executable.
|
||||
set(ANDROID 0)
|
||||
endif()
|
||||
set(USE_X11 0)
|
||||
set(USE_UPNP 0)
|
||||
set(USE_EGL 1)
|
||||
set(ENABLE_QT 0)
|
||||
set(USE_DISCORD_PRESENCE 0)
|
||||
|
||||
@@ -381,20 +379,10 @@ if(ANDROID)
|
||||
SET(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY)
|
||||
SET(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER)
|
||||
SET(CMAKE_FIND_ROOT_PATH_MODE_PACKAGE ONLY)
|
||||
elseif(HAIKU)
|
||||
set(USE_X11 0)
|
||||
set(USE_UPNP 0)
|
||||
set(USE_EGL 0)
|
||||
endif()
|
||||
|
||||
if(ENABLE_HEADLESS)
|
||||
if(APPLE)
|
||||
message(STATUS "Enabling Headless! Disabling GUI.")
|
||||
else()
|
||||
message(STATUS "Enabling Headless! Disabling GUI, force enabling EGL!")
|
||||
set(USE_EGL 1)
|
||||
endif()
|
||||
set(USE_X11 0)
|
||||
message(STATUS "Enabling Headless! Disabling GUI.")
|
||||
set(ENABLE_QT 0)
|
||||
set(USE_DISCORD_PRESENCE 0)
|
||||
add_definitions(-DUSE_HEADLESS)
|
||||
@@ -425,38 +413,31 @@ if (OPENGL_GL)
|
||||
include_directories(${OPENGL_INCLUDE_DIR})
|
||||
endif()
|
||||
|
||||
set(USE_X11 0)
|
||||
|
||||
if(UNIX AND NOT APPLE AND NOT ANDROID AND NOT HAIKU AND NOT ENABLE_HEADLESS)
|
||||
if(ENABLE_X11)
|
||||
find_package(X11)
|
||||
if(TRY_X11 AND X11_FOUND)
|
||||
set(USE_X11 1)
|
||||
if(X11_FOUND)
|
||||
add_definitions(-DHAVE_X11=1)
|
||||
include_directories(${X11_INCLUDE_DIR})
|
||||
check_lib(XRANDR xrandr Xrandr)
|
||||
if(XRANDR_FOUND)
|
||||
add_definitions(-DHAVE_XRANDR=1)
|
||||
else()
|
||||
add_definitions(-DHAVE_XRANDR=0)
|
||||
endif()
|
||||
pkg_check_modules(X11_INPUT REQUIRED xi>=1.5.0)
|
||||
message(STATUS "X11 support enabled")
|
||||
else()
|
||||
set(USE_X11 0)
|
||||
SET(X11_FOUND "")
|
||||
message(STATUS "X11 support disabled")
|
||||
add_definitions(-DHAVE_X11=0)
|
||||
endif()
|
||||
|
||||
if (NOT USE_X11)
|
||||
message(FATAL_ERROR "\n"
|
||||
"No suitable display platform found\n"
|
||||
"Requires x11 to run")
|
||||
message(WARNING "X11 support enabled but not found. This build will not support X11.")
|
||||
endif()
|
||||
endif()
|
||||
|
||||
if(USE_X11)
|
||||
check_lib(XRANDR xrandr Xrandr)
|
||||
if(XRANDR_FOUND)
|
||||
add_definitions(-DHAVE_XRANDR=1)
|
||||
if(ENABLE_EGL)
|
||||
find_package(EGL)
|
||||
if(EGL_FOUND)
|
||||
add_definitions(-DHAVE_EGL=1)
|
||||
message(STATUS "EGL OpenGL interface enabled")
|
||||
else()
|
||||
add_definitions(-DHAVE_XRANDR=0)
|
||||
message(WARNING "EGL support enabled but not found. This build will not support EGL.")
|
||||
endif()
|
||||
|
||||
pkg_check_modules(X11_INPUT REQUIRED xi>=1.5.0)
|
||||
endif()
|
||||
|
||||
if(ENCODE_FRAMEDUMPS)
|
||||
@@ -482,11 +463,6 @@ if(OPROFILING)
|
||||
endif()
|
||||
endif()
|
||||
|
||||
if(USE_EGL)
|
||||
message(STATUS "EGL OpenGL interface enabled")
|
||||
add_definitions(-DUSE_EGL=1)
|
||||
endif()
|
||||
|
||||
if(ENABLE_EVDEV)
|
||||
find_package(Libudev REQUIRED)
|
||||
find_package(Libevdev REQUIRED)
|
||||
|
||||
@@ -22,10 +22,10 @@
|
||||
#include "Common/CommonTypes.h"
|
||||
#include "Common/Event.h"
|
||||
#include "Common/FileUtil.h"
|
||||
#include "Common/GL/GLInterfaceBase.h"
|
||||
#include "Common/Logging/LogManager.h"
|
||||
#include "Common/MsgHandler.h"
|
||||
#include "Common/Version.h"
|
||||
#include "Common/WindowSystemInfo.h"
|
||||
|
||||
#include "Core/Analytics.h"
|
||||
#include "Core/Boot/Boot.h"
|
||||
@@ -90,11 +90,6 @@ void Host_Message(HostMessageID id)
|
||||
}
|
||||
}
|
||||
|
||||
void* Host_GetRenderHandle()
|
||||
{
|
||||
return s_surf;
|
||||
}
|
||||
|
||||
void Host_UpdateTitle(const std::string& title)
|
||||
{
|
||||
__android_log_write(ANDROID_LOG_INFO, DOLPHIN_TAG, title.c_str());
|
||||
@@ -566,7 +561,8 @@ static void Run(const std::string& path, bool first_open,
|
||||
s_have_wm_user_stop = false;
|
||||
std::unique_ptr<BootParameters> boot = BootParameters::GenerateFromFile(path, savestate_path);
|
||||
boot->delete_savestate = delete_savestate;
|
||||
if (BootManager::BootCore(std::move(boot)))
|
||||
WindowSystemInfo wsi(WindowSystemType::Android, nullptr, s_surf);
|
||||
if (BootManager::BootCore(std::move(boot), wsi))
|
||||
{
|
||||
static constexpr int TIMEOUT = 10000;
|
||||
static constexpr int WAIT_STEP = 25;
|
||||
|
||||
@@ -110,17 +110,18 @@ endif()
|
||||
target_sources(common PRIVATE
|
||||
GL/GLUtil.cpp
|
||||
GL/GLExtensions/GLExtensions.cpp
|
||||
GL/GLInterface/GLInterface.cpp
|
||||
GL/GLContext.cpp
|
||||
)
|
||||
|
||||
if(USE_EGL)
|
||||
if(ENABLE_EGL AND EGL_FOUND)
|
||||
target_sources(common PRIVATE GL/GLInterface/EGL.cpp)
|
||||
if(ANDROID)
|
||||
target_sources(common PRIVATE GL/GLInterface/EGLAndroid.cpp)
|
||||
elseif(USE_X11)
|
||||
elseif(ENABLE_X11 AND X11_FOUND)
|
||||
target_sources(common PRIVATE GL/GLInterface/EGLX11.cpp)
|
||||
endif()
|
||||
target_link_libraries(common PUBLIC EGL)
|
||||
target_include_directories(common PRIVATE ${EGL_INCLUDE_DIRS})
|
||||
target_link_libraries(common PUBLIC ${EGL_LIBRARIES})
|
||||
endif()
|
||||
|
||||
if(WIN32)
|
||||
@@ -130,18 +131,14 @@ if(WIN32)
|
||||
)
|
||||
elseif(APPLE)
|
||||
target_sources(common PRIVATE GL/GLInterface/AGL.mm)
|
||||
elseif(HAIKU)
|
||||
target_sources(common PRIVATE GL/GLInterface/BGL.cpp)
|
||||
target_link_libraries(common PUBLIC be GL)
|
||||
elseif(USE_X11)
|
||||
if (NOT USE_EGL)
|
||||
target_sources(common PRIVATE GL/GLInterface/GLX.cpp)
|
||||
# GLX has a hard dependency on libGL.
|
||||
# Make sure to link to it if using GLX.
|
||||
target_link_libraries(common PUBLIC ${OPENGL_LIBRARIES})
|
||||
endif()
|
||||
target_sources(common PRIVATE GL/GLInterface/X11_Util.cpp)
|
||||
target_link_libraries(common PUBLIC ${XRANDR_LIBRARIES})
|
||||
elseif(ENABLE_X11 AND X11_FOUND)
|
||||
target_sources(common PRIVATE
|
||||
GL/GLX11Window.cpp
|
||||
GL/GLInterface/GLX.cpp)
|
||||
|
||||
# GLX has a hard dependency on libGL.
|
||||
# Make sure to link to it if using GLX.
|
||||
target_link_libraries(common PUBLIC ${OPENGL_LIBRARIES})
|
||||
endif()
|
||||
|
||||
if(CMAKE_SYSTEM_NAME STREQUAL "Linux")
|
||||
@@ -163,9 +160,6 @@ if(UNIX)
|
||||
if(SYSTEMD_FOUND)
|
||||
target_link_libraries(traversal_server PRIVATE ${SYSTEMD_LIBRARIES})
|
||||
endif()
|
||||
if(HAIKU)
|
||||
target_link_libraries(traversal_server PRIVATE network)
|
||||
endif()
|
||||
elseif(WIN32)
|
||||
target_link_libraries(common PRIVATE "-INCLUDE:enableCompatPatches")
|
||||
endif()
|
||||
|
||||
@@ -121,7 +121,7 @@
|
||||
<ClInclude Include="GL\GLExtensions\NV_depth_buffer_float.h" />
|
||||
<ClInclude Include="GL\GLExtensions\NV_occlusion_query_samples.h" />
|
||||
<ClInclude Include="GL\GLExtensions\NV_primitive_restart.h" />
|
||||
<ClInclude Include="GL\GLInterfaceBase.h" />
|
||||
<ClInclude Include="GL\GLContext.h" />
|
||||
<ClInclude Include="GL\GLInterface\WGL.h" />
|
||||
<ClInclude Include="GL\GLUtil.h" />
|
||||
<ClInclude Include="FloatUtils.h" />
|
||||
@@ -189,7 +189,7 @@
|
||||
<ClCompile Include="FloatUtils.cpp" />
|
||||
<ClCompile Include="GekkoDisassembler.cpp" />
|
||||
<ClCompile Include="GL\GLExtensions\GLExtensions.cpp" />
|
||||
<ClCompile Include="GL\GLInterface\GLInterface.cpp" />
|
||||
<ClCompile Include="GL\GLContext.cpp" />
|
||||
<ClCompile Include="GL\GLInterface\WGL.cpp" />
|
||||
<ClCompile Include="GL\GLUtil.cpp" />
|
||||
<ClCompile Include="Hash.cpp" />
|
||||
@@ -255,4 +255,4 @@
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
|
||||
<ImportGroup Label="ExtensionTargets">
|
||||
</ImportGroup>
|
||||
</Project>
|
||||
</Project>
|
||||
@@ -243,9 +243,6 @@
|
||||
<ClInclude Include="GL\GLInterface\WGL.h">
|
||||
<Filter>GL\GLInterface</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="GL\GLInterfaceBase.h">
|
||||
<Filter>GL\GLInterface</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="Assert.h" />
|
||||
<ClInclude Include="Analytics.h" />
|
||||
<ClInclude Include="Semaphore.h" />
|
||||
@@ -275,6 +272,9 @@
|
||||
<ClInclude Include="Debug\MemoryPatches.h">
|
||||
<Filter>Debug</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="GL\GLContext.h">
|
||||
<Filter>GL\GLInterface</Filter>
|
||||
</ClInclude>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClCompile Include="CDUtils.cpp" />
|
||||
@@ -339,9 +339,6 @@
|
||||
<ClCompile Include="GL\GLInterface\WGL.cpp">
|
||||
<Filter>GL\GLInterface</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="GL\GLInterface\GLInterface.cpp">
|
||||
<Filter>GL\GLInterface</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="Analytics.cpp" />
|
||||
<ClCompile Include="MD5.cpp" />
|
||||
<ClCompile Include="File.cpp" />
|
||||
@@ -355,6 +352,9 @@
|
||||
<ClCompile Include="Debug\MemoryPatches.cpp">
|
||||
<Filter>Debug</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="GL\GLContext.cpp">
|
||||
<Filter>GL\GLInterface</Filter>
|
||||
</ClCompile>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Text Include="CMakeLists.txt" />
|
||||
@@ -362,4 +362,4 @@
|
||||
<ItemGroup>
|
||||
<Natvis Include="BitField.natvis" />
|
||||
</ItemGroup>
|
||||
</Project>
|
||||
</Project>
|
||||
@@ -0,0 +1,126 @@
|
||||
// Copyright 2014 Dolphin Emulator Project
|
||||
// Licensed under GPLv2+
|
||||
// Refer to the license.txt file included.
|
||||
|
||||
#include <memory>
|
||||
|
||||
#include "Common/GL/GLContext.h"
|
||||
|
||||
#if defined(__APPLE__)
|
||||
#include "Common/GL/GLInterface/AGL.h"
|
||||
#endif
|
||||
#if defined(WIN32)
|
||||
#include "Common/GL/GLInterface/WGL.h"
|
||||
#endif
|
||||
#if HAVE_X11
|
||||
#include "Common/GL/GLInterface/GLX.h"
|
||||
#endif
|
||||
#if HAVE_EGL
|
||||
#include "Common/GL/GLInterface/EGL.h"
|
||||
#if HAVE_X11
|
||||
#include "Common/GL/GLInterface/EGLX11.h"
|
||||
#endif
|
||||
#if defined(ANDROID)
|
||||
#include "Common/GL/GLInterface/EGLAndroid.h"
|
||||
#endif
|
||||
#endif
|
||||
|
||||
const std::array<std::pair<int, int>, 9> GLContext::s_desktop_opengl_versions = {
|
||||
{{4, 6}, {4, 5}, {4, 4}, {4, 3}, {4, 2}, {4, 1}, {4, 0}, {3, 3}, {3, 2}}};
|
||||
|
||||
GLContext::~GLContext() = default;
|
||||
|
||||
bool GLContext::Initialize(void* display_handle, void* window_handle, bool stereo, bool core)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
bool GLContext::IsHeadless() const
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
std::unique_ptr<GLContext> GLContext::CreateSharedContext()
|
||||
{
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
bool GLContext::MakeCurrent()
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
bool GLContext::ClearCurrent()
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
void GLContext::Update()
|
||||
{
|
||||
}
|
||||
|
||||
void GLContext::UpdateSurface(void* window_handle)
|
||||
{
|
||||
}
|
||||
|
||||
void GLContext::Swap()
|
||||
{
|
||||
}
|
||||
|
||||
void GLContext::SwapInterval(int interval)
|
||||
{
|
||||
}
|
||||
|
||||
void* GLContext::GetFuncAddress(const std::string& name)
|
||||
{
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
std::unique_ptr<GLContext> GLContext::Create(const WindowSystemInfo& wsi, bool stereo, bool core,
|
||||
bool prefer_egl, bool prefer_gles)
|
||||
{
|
||||
std::unique_ptr<GLContext> context;
|
||||
#if defined(__APPLE__)
|
||||
if (wsi.type == WindowSystemType::MacOS || wsi.type == WindowSystemType::Headless)
|
||||
context = std::make_unique<GLContextAGL>();
|
||||
#endif
|
||||
#if defined(_WIN32)
|
||||
if (wsi.type == WindowSystemType::Windows)
|
||||
context = std::make_unique<GLContextWGL>();
|
||||
#endif
|
||||
#if defined(ANDROID)
|
||||
if (wsi.type == WindowSystemType::Android)
|
||||
context = std::make_unique<GLContextEGLAndroid>();
|
||||
#endif
|
||||
#if HAVE_X11
|
||||
if (wsi.type == WindowSystemType::X11)
|
||||
{
|
||||
// GLES 3 is not supported via GLX.
|
||||
const bool use_egl = prefer_egl || prefer_gles;
|
||||
#if defined(HAVE_EGL)
|
||||
if (use_egl)
|
||||
context = std::make_unique<GLContextEGLX11>();
|
||||
else
|
||||
context = std::make_unique<GLContextGLX>();
|
||||
#else
|
||||
context = std::make_unique<GLContextGLX>();
|
||||
#endif
|
||||
}
|
||||
#endif
|
||||
#if HAVE_EGL
|
||||
if (wsi.type == WindowSystemType::Headless)
|
||||
context = std::make_unique<GLContextEGL>();
|
||||
#endif
|
||||
|
||||
if (!context)
|
||||
return nullptr;
|
||||
|
||||
// Option to prefer GLES on desktop platforms, useful for testing.
|
||||
if (prefer_gles)
|
||||
context->m_opengl_mode = Mode::OpenGLES;
|
||||
|
||||
if (!context->Initialize(wsi.display_connection, wsi.render_surface, stereo, core))
|
||||
return nullptr;
|
||||
|
||||
return context;
|
||||
}
|
||||
@@ -0,0 +1,67 @@
|
||||
// Copyright 2008 Dolphin Emulator Project
|
||||
// Licensed under GPLv2+
|
||||
// Refer to the license.txt file included.
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <array>
|
||||
#include <memory>
|
||||
#include <string>
|
||||
#include <utility>
|
||||
|
||||
#include "Common/CommonTypes.h"
|
||||
#include "Common/WindowSystemInfo.h"
|
||||
|
||||
class GLContext
|
||||
{
|
||||
public:
|
||||
enum class Mode
|
||||
{
|
||||
Detect,
|
||||
OpenGL,
|
||||
OpenGLES
|
||||
};
|
||||
|
||||
virtual ~GLContext();
|
||||
|
||||
Mode GetMode() { return m_opengl_mode; }
|
||||
bool IsGLES() const { return m_opengl_mode == Mode::OpenGLES; }
|
||||
|
||||
u32 GetBackBufferWidth() { return m_backbuffer_width; }
|
||||
u32 GetBackBufferHeight() { return m_backbuffer_height; }
|
||||
|
||||
virtual bool IsHeadless() const;
|
||||
|
||||
virtual std::unique_ptr<GLContext> CreateSharedContext();
|
||||
|
||||
virtual bool MakeCurrent();
|
||||
virtual bool ClearCurrent();
|
||||
|
||||
virtual void Update();
|
||||
virtual void UpdateSurface(void* window_handle);
|
||||
|
||||
virtual void Swap();
|
||||
virtual void SwapInterval(int interval);
|
||||
|
||||
virtual void* GetFuncAddress(const std::string& name);
|
||||
|
||||
// Creates an instance of GLContext specific to the platform we are running on.
|
||||
// If successful, the context is made current on the calling thread.
|
||||
static std::unique_ptr<GLContext> Create(const WindowSystemInfo& wsi, bool stereo = false,
|
||||
bool core = true, bool prefer_egl = false,
|
||||
bool prefer_gles = false);
|
||||
|
||||
protected:
|
||||
virtual bool Initialize(void* display_handle, void* window_handle, bool stereo, bool core);
|
||||
|
||||
Mode m_opengl_mode = Mode::Detect;
|
||||
|
||||
// Window dimensions.
|
||||
u32 m_backbuffer_width = 0;
|
||||
u32 m_backbuffer_height = 0;
|
||||
bool m_is_shared = false;
|
||||
|
||||
// A list of desktop OpenGL versions to attempt to create a context for.
|
||||
// (4.6-3.2, geometry shaders is a minimum requirement since we're using core profile).
|
||||
static const std::array<std::pair<int, int>, 9> s_desktop_opengl_versions;
|
||||
};
|
||||
@@ -5,8 +5,8 @@
|
||||
#include <sstream>
|
||||
#include <unordered_map>
|
||||
|
||||
#include "Common/GL/GLContext.h"
|
||||
#include "Common/GL/GLExtensions/GLExtensions.h"
|
||||
#include "Common/GL/GLInterfaceBase.h"
|
||||
#include "Common/Logging/Log.h"
|
||||
|
||||
#if defined(__linux__) || defined(__APPLE__)
|
||||
@@ -2148,12 +2148,11 @@ const GLFunc gl_function_array[] = {
|
||||
namespace GLExtensions
|
||||
{
|
||||
// Private members and functions
|
||||
static bool _isES;
|
||||
static u32 _GLVersion;
|
||||
static std::unordered_map<std::string, bool> m_extension_list;
|
||||
static u32 s_gl_version;
|
||||
static std::unordered_map<std::string, bool> s_extension_list;
|
||||
|
||||
// Private initialization functions
|
||||
bool InitFunctionPointers();
|
||||
bool InitFunctionPointers(GLContext* context);
|
||||
|
||||
// Initializes the extension list the old way
|
||||
static void InitExtensionList21()
|
||||
@@ -2163,28 +2162,28 @@ static void InitExtensionList21()
|
||||
std::istringstream buffer(tmp);
|
||||
|
||||
while (buffer >> tmp)
|
||||
m_extension_list[tmp] = true;
|
||||
s_extension_list[tmp] = true;
|
||||
}
|
||||
|
||||
static void InitExtensionList()
|
||||
static void InitExtensionList(GLContext* context)
|
||||
{
|
||||
m_extension_list.clear();
|
||||
if (_isES)
|
||||
s_extension_list.clear();
|
||||
if (context->IsGLES())
|
||||
{
|
||||
switch (_GLVersion)
|
||||
switch (s_gl_version)
|
||||
{
|
||||
default:
|
||||
case 320:
|
||||
m_extension_list["VERSION_GLES_3_2"] = true;
|
||||
s_extension_list["VERSION_GLES_3_2"] = true;
|
||||
case 310:
|
||||
m_extension_list["VERSION_GLES_3_1"] = true;
|
||||
s_extension_list["VERSION_GLES_3_1"] = true;
|
||||
case 300:
|
||||
m_extension_list["VERSION_GLES_3"] = true;
|
||||
s_extension_list["VERSION_GLES_3"] = true;
|
||||
break;
|
||||
}
|
||||
|
||||
// We always have ES 2.0
|
||||
m_extension_list["VERSION_GLES_2"] = true;
|
||||
s_extension_list["VERSION_GLES_2"] = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -2194,7 +2193,7 @@ static void InitExtensionList()
|
||||
// When an extension got merged in to core, the naming may have changed
|
||||
|
||||
// This has intentional fall through
|
||||
switch (_GLVersion)
|
||||
switch (s_gl_version)
|
||||
{
|
||||
default:
|
||||
case 450:
|
||||
@@ -2213,7 +2212,7 @@ static void InitExtensionList()
|
||||
"VERSION_4_5",
|
||||
};
|
||||
for (auto it : gl450exts)
|
||||
m_extension_list[it] = true;
|
||||
s_extension_list[it] = true;
|
||||
}
|
||||
case 440:
|
||||
{
|
||||
@@ -2229,7 +2228,7 @@ static void InitExtensionList()
|
||||
"VERSION_4_4",
|
||||
};
|
||||
for (auto it : gl440exts)
|
||||
m_extension_list[it] = true;
|
||||
s_extension_list[it] = true;
|
||||
}
|
||||
case 430:
|
||||
{
|
||||
@@ -2257,7 +2256,7 @@ static void InitExtensionList()
|
||||
"VERSION_4_3",
|
||||
};
|
||||
for (auto it : gl430exts)
|
||||
m_extension_list[it] = true;
|
||||
s_extension_list[it] = true;
|
||||
}
|
||||
case 420:
|
||||
{
|
||||
@@ -2277,7 +2276,7 @@ static void InitExtensionList()
|
||||
"VERSION_4_2",
|
||||
};
|
||||
for (auto it : gl420exts)
|
||||
m_extension_list[it] = true;
|
||||
s_extension_list[it] = true;
|
||||
}
|
||||
case 410:
|
||||
{
|
||||
@@ -2291,7 +2290,7 @@ static void InitExtensionList()
|
||||
"VERSION_4_1",
|
||||
};
|
||||
for (auto it : gl410exts)
|
||||
m_extension_list[it] = true;
|
||||
s_extension_list[it] = true;
|
||||
}
|
||||
case 400:
|
||||
{
|
||||
@@ -2311,7 +2310,7 @@ static void InitExtensionList()
|
||||
"VERSION_4_0",
|
||||
};
|
||||
for (auto it : gl400exts)
|
||||
m_extension_list[it] = true;
|
||||
s_extension_list[it] = true;
|
||||
}
|
||||
case 330:
|
||||
{
|
||||
@@ -2329,7 +2328,7 @@ static void InitExtensionList()
|
||||
"VERSION_3_3",
|
||||
};
|
||||
for (auto it : gl330exts)
|
||||
m_extension_list[it] = true;
|
||||
s_extension_list[it] = true;
|
||||
}
|
||||
case 320:
|
||||
{
|
||||
@@ -2346,7 +2345,7 @@ static void InitExtensionList()
|
||||
"VERSION_3_2",
|
||||
};
|
||||
for (auto it : gl320exts)
|
||||
m_extension_list[it] = true;
|
||||
s_extension_list[it] = true;
|
||||
}
|
||||
case 310:
|
||||
{
|
||||
@@ -2361,7 +2360,7 @@ static void InitExtensionList()
|
||||
"VERSION_3_1",
|
||||
};
|
||||
for (auto it : gl310exts)
|
||||
m_extension_list[it] = true;
|
||||
s_extension_list[it] = true;
|
||||
}
|
||||
case 300:
|
||||
{
|
||||
@@ -2392,7 +2391,7 @@ static void InitExtensionList()
|
||||
"VERSION_3_0",
|
||||
};
|
||||
for (auto it : gl300exts)
|
||||
m_extension_list[it] = true;
|
||||
s_extension_list[it] = true;
|
||||
}
|
||||
case 210:
|
||||
case 200:
|
||||
@@ -2406,10 +2405,10 @@ static void InitExtensionList()
|
||||
break;
|
||||
}
|
||||
// So we can easily determine if we are running dekstop GL
|
||||
m_extension_list["VERSION_GL"] = true;
|
||||
s_extension_list["VERSION_GL"] = true;
|
||||
}
|
||||
|
||||
if (_GLVersion < 300)
|
||||
if (s_gl_version < 300)
|
||||
{
|
||||
InitExtensionList21();
|
||||
return;
|
||||
@@ -2417,7 +2416,7 @@ static void InitExtensionList()
|
||||
GLint NumExtension = 0;
|
||||
glGetIntegerv(GL_NUM_EXTENSIONS, &NumExtension);
|
||||
for (GLint i = 0; i < NumExtension; ++i)
|
||||
m_extension_list[std::string((const char*)glGetStringi(GL_EXTENSIONS, i))] = true;
|
||||
s_extension_list[std::string((const char*)glGetStringi(GL_EXTENSIONS, i))] = true;
|
||||
}
|
||||
static void InitVersion()
|
||||
{
|
||||
@@ -2425,14 +2424,14 @@ static void InitVersion()
|
||||
glGetIntegerv(GL_MAJOR_VERSION, &major);
|
||||
glGetIntegerv(GL_MINOR_VERSION, &minor);
|
||||
if (glGetError() == GL_NO_ERROR)
|
||||
_GLVersion = major * 100 + minor * 10;
|
||||
s_gl_version = major * 100 + minor * 10;
|
||||
else
|
||||
_GLVersion = 210;
|
||||
s_gl_version = 210;
|
||||
}
|
||||
|
||||
static void* GetFuncAddress(const std::string& name, void** func)
|
||||
static void* GetFuncAddress(GLContext* context, const std::string& name, void** func)
|
||||
{
|
||||
*func = GLInterface->GetFuncAddress(name);
|
||||
*func = context->GetFuncAddress(name);
|
||||
if (*func == nullptr)
|
||||
{
|
||||
#if defined(__linux__) || defined(__APPLE__)
|
||||
@@ -2448,37 +2447,36 @@ static void* GetFuncAddress(const std::string& name, void** func)
|
||||
// Public members
|
||||
u32 Version()
|
||||
{
|
||||
return _GLVersion;
|
||||
return s_gl_version;
|
||||
}
|
||||
bool Supports(const std::string& name)
|
||||
{
|
||||
return m_extension_list[name];
|
||||
return s_extension_list[name];
|
||||
}
|
||||
|
||||
bool Init()
|
||||
bool Init(GLContext* context)
|
||||
{
|
||||
_isES = GLInterface->GetMode() != GLInterfaceMode::MODE_OPENGL;
|
||||
|
||||
// Grab a few functions for initial checking
|
||||
// We need them to grab the extension list
|
||||
// Also to check if there is an error grabbing the version
|
||||
if (GetFuncAddress("glGetIntegerv", (void**)&glGetIntegerv) == nullptr)
|
||||
if (GetFuncAddress(context, "glGetIntegerv", (void**)&glGetIntegerv) == nullptr)
|
||||
return false;
|
||||
if (GetFuncAddress("glGetString", (void**)&glGetString) == nullptr)
|
||||
if (GetFuncAddress(context, "glGetString", (void**)&glGetString) == nullptr)
|
||||
return false;
|
||||
if (GetFuncAddress("glGetError", (void**)&glGetError) == nullptr)
|
||||
if (GetFuncAddress(context, "glGetError", (void**)&glGetError) == nullptr)
|
||||
return false;
|
||||
|
||||
InitVersion();
|
||||
|
||||
// We need to use glGetStringi to get the extension list
|
||||
// if we are using GLES3 or a GL version greater than 2.1
|
||||
if (_GLVersion > 210 && GetFuncAddress("glGetStringi", (void**)&glGetStringi) == nullptr)
|
||||
if (s_gl_version > 210 &&
|
||||
GetFuncAddress(context, "glGetStringi", (void**)&glGetStringi) == nullptr)
|
||||
return false;
|
||||
|
||||
InitExtensionList();
|
||||
InitExtensionList(context);
|
||||
|
||||
return InitFunctionPointers();
|
||||
return InitFunctionPointers(context);
|
||||
}
|
||||
|
||||
// Private initialization functions
|
||||
@@ -2491,20 +2489,20 @@ static bool HasFeatures(const std::string& extensions)
|
||||
while (buffer >> tmp)
|
||||
{
|
||||
if (tmp[0] == '!')
|
||||
result &= !m_extension_list[tmp.erase(0, 1)];
|
||||
result &= !s_extension_list[tmp.erase(0, 1)];
|
||||
else if (tmp[0] == '|')
|
||||
result |= m_extension_list[tmp.erase(0, 1)];
|
||||
result |= s_extension_list[tmp.erase(0, 1)];
|
||||
else
|
||||
result &= m_extension_list[tmp];
|
||||
result &= s_extension_list[tmp];
|
||||
}
|
||||
return result;
|
||||
}
|
||||
bool InitFunctionPointers()
|
||||
bool InitFunctionPointers(GLContext* context)
|
||||
{
|
||||
bool result = true;
|
||||
for (const auto& it : gl_function_array)
|
||||
if (HasFeatures(it.requirements))
|
||||
result &= !!GetFuncAddress(it.function_name, it.function_ptr);
|
||||
result &= !!GetFuncAddress(context, it.function_name, it.function_ptr);
|
||||
return result;
|
||||
}
|
||||
}
|
||||
} // namespace GLExtensions
|
||||
|
||||
@@ -54,10 +54,12 @@
|
||||
#include "Common/GL/GLExtensions/gl_4_4.h"
|
||||
#include "Common/GL/GLExtensions/gl_4_5.h"
|
||||
|
||||
class GLContext;
|
||||
|
||||
namespace GLExtensions
|
||||
{
|
||||
// Initializes the interface
|
||||
bool Init();
|
||||
bool Init(GLContext* context);
|
||||
|
||||
// Function for checking if the hardware supports an extension
|
||||
// example: if (GLExtensions::Supports("GL_ARB_multi_map"))
|
||||
@@ -65,4 +67,4 @@ bool Supports(const std::string& name);
|
||||
|
||||
// Returns OpenGL version in format 430
|
||||
u32 Version();
|
||||
}
|
||||
} // namespace GLExtensions
|
||||
|
||||
@@ -12,22 +12,28 @@ struct NSOpenGLPixelFormat;
|
||||
struct NSView;
|
||||
#endif
|
||||
|
||||
#include "Common/GL/GLInterfaceBase.h"
|
||||
#include "Common/GL/GLContext.h"
|
||||
|
||||
class cInterfaceAGL : public cInterfaceBase
|
||||
class GLContextAGL final : public GLContext
|
||||
{
|
||||
public:
|
||||
void Swap() override;
|
||||
bool Create(void* window_handle, bool stereo, bool core) override;
|
||||
bool Create(cInterfaceBase* main_context) override;
|
||||
~GLContextAGL() override;
|
||||
|
||||
bool IsHeadless() const override;
|
||||
|
||||
std::unique_ptr<GLContext> CreateSharedContext() override;
|
||||
|
||||
bool MakeCurrent() override;
|
||||
bool ClearCurrent() override;
|
||||
void Shutdown() override;
|
||||
void Update() override;
|
||||
void SwapInterval(int interval) override;
|
||||
std::unique_ptr<cInterfaceBase> CreateSharedContext() override;
|
||||
|
||||
private:
|
||||
void Update() override;
|
||||
|
||||
void Swap() override;
|
||||
void SwapInterval(int interval) override;
|
||||
|
||||
protected:
|
||||
bool Initialize(void* display_handle, void* window_handle, bool stereo, bool core) override;
|
||||
|
||||
NSView* m_view = nullptr;
|
||||
NSOpenGLContext* m_context = nullptr;
|
||||
NSOpenGLPixelFormat* m_pixel_format = nullptr;
|
||||
|
||||
@@ -10,16 +10,15 @@ static bool UpdateCachedDimensions(NSView* view, u32* width, u32* height)
|
||||
NSWindow* window = [view window];
|
||||
NSSize size = [view frame].size;
|
||||
|
||||
float scale = [window backingScaleFactor];
|
||||
size.width *= scale;
|
||||
size.height *= scale;
|
||||
const CGFloat scale = [window backingScaleFactor];
|
||||
u32 new_width = static_cast<u32>(size.width * scale);
|
||||
u32 new_height = static_cast<u32>(size.height * scale);
|
||||
|
||||
if (*width == size.width && *height == size.height)
|
||||
if (*width == new_width && *height == new_height)
|
||||
return false;
|
||||
|
||||
*width = size.width;
|
||||
*height = size.height;
|
||||
|
||||
*width = new_width;
|
||||
*height = new_height;
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -44,14 +43,33 @@ static bool AttachContextToView(NSOpenGLContext* context, NSView* view, u32* wid
|
||||
return true;
|
||||
}
|
||||
|
||||
void cInterfaceAGL::Swap()
|
||||
GLContextAGL::~GLContextAGL()
|
||||
{
|
||||
if ([NSOpenGLContext currentContext] == m_context)
|
||||
[NSOpenGLContext clearCurrentContext];
|
||||
|
||||
if (m_context)
|
||||
{
|
||||
[m_context clearDrawable];
|
||||
[m_context release];
|
||||
}
|
||||
if (m_pixel_format)
|
||||
[m_pixel_format release];
|
||||
}
|
||||
|
||||
bool GLContextAGL::IsHeadless() const
|
||||
{
|
||||
return !m_view;
|
||||
}
|
||||
|
||||
void GLContextAGL::Swap()
|
||||
{
|
||||
[m_context flushBuffer];
|
||||
}
|
||||
|
||||
// Create rendering window.
|
||||
// Call browser: Core.cpp:EmuThread() > main.cpp:Video_Initialize()
|
||||
bool cInterfaceAGL::Create(void* window_handle, bool stereo, bool core)
|
||||
bool GLContextAGL::Initialize(void* display_handle, void* window_handle, bool stereo, bool core)
|
||||
{
|
||||
NSOpenGLPixelFormatAttribute attr[] = {
|
||||
NSOpenGLPFADoubleBuffer,
|
||||
@@ -78,65 +96,54 @@ bool cInterfaceAGL::Create(void* window_handle, bool stereo, bool core)
|
||||
return true;
|
||||
|
||||
m_view = static_cast<NSView*>(window_handle);
|
||||
return AttachContextToView(m_context, m_view, &s_backbuffer_width, &s_backbuffer_height);
|
||||
}
|
||||
|
||||
bool cInterfaceAGL::Create(cInterfaceBase* main_context)
|
||||
{
|
||||
cInterfaceAGL* agl_context = static_cast<cInterfaceAGL*>(main_context);
|
||||
NSOpenGLPixelFormat* pixel_format = agl_context->m_pixel_format;
|
||||
NSOpenGLContext* share_context = agl_context->m_context;
|
||||
|
||||
m_context = [[NSOpenGLContext alloc] initWithFormat:pixel_format shareContext:share_context];
|
||||
if (m_context == nil)
|
||||
{
|
||||
ERROR_LOG(VIDEO, "failed to create shared context");
|
||||
m_opengl_mode = Mode::OpenGL;
|
||||
if (!AttachContextToView(m_context, m_view, &m_backbuffer_width, &m_backbuffer_height))
|
||||
return false;
|
||||
}
|
||||
|
||||
[m_context makeCurrentContext];
|
||||
return true;
|
||||
}
|
||||
|
||||
std::unique_ptr<cInterfaceBase> cInterfaceAGL::CreateSharedContext()
|
||||
std::unique_ptr<GLContext> GLContextAGL::CreateSharedContext()
|
||||
{
|
||||
std::unique_ptr<cInterfaceBase> context = std::make_unique<cInterfaceAGL>();
|
||||
if (!context->Create(this))
|
||||
NSOpenGLContext* new_agl_context =
|
||||
[[NSOpenGLContext alloc] initWithFormat:m_pixel_format shareContext:m_context];
|
||||
if (new_agl_context == nil)
|
||||
{
|
||||
ERROR_LOG(VIDEO, "failed to create shared context");
|
||||
return nullptr;
|
||||
return context;
|
||||
}
|
||||
|
||||
std::unique_ptr<GLContextAGL> new_context = std::make_unique<GLContextAGL>();
|
||||
new_context->m_context = new_agl_context;
|
||||
new_context->m_pixel_format = m_pixel_format;
|
||||
[new_context->m_pixel_format retain];
|
||||
new_context->m_is_shared = true;
|
||||
return new_context;
|
||||
}
|
||||
|
||||
bool cInterfaceAGL::MakeCurrent()
|
||||
bool GLContextAGL::MakeCurrent()
|
||||
{
|
||||
[m_context makeCurrentContext];
|
||||
return true;
|
||||
}
|
||||
|
||||
bool cInterfaceAGL::ClearCurrent()
|
||||
bool GLContextAGL::ClearCurrent()
|
||||
{
|
||||
[NSOpenGLContext clearCurrentContext];
|
||||
return true;
|
||||
}
|
||||
|
||||
// Close backend
|
||||
void cInterfaceAGL::Shutdown()
|
||||
{
|
||||
[m_context clearDrawable];
|
||||
[m_context release];
|
||||
m_context = nil;
|
||||
[m_pixel_format release];
|
||||
m_pixel_format = nil;
|
||||
}
|
||||
|
||||
void cInterfaceAGL::Update()
|
||||
void GLContextAGL::Update()
|
||||
{
|
||||
if (!m_view)
|
||||
return;
|
||||
|
||||
if (UpdateCachedDimensions(m_view, &s_backbuffer_width, &s_backbuffer_height))
|
||||
if (UpdateCachedDimensions(m_view, &m_backbuffer_width, &m_backbuffer_height))
|
||||
[m_context update];
|
||||
}
|
||||
|
||||
void cInterfaceAGL::SwapInterval(int interval)
|
||||
void GLContextAGL::SwapInterval(int interval)
|
||||
{
|
||||
[m_context setValues:static_cast<GLint*>(&interval) forParameter:NSOpenGLCPSwapInterval];
|
||||
}
|
||||
|
||||
@@ -1,70 +0,0 @@
|
||||
// Copyright 2017 Dolphin Emulator Project
|
||||
// Licensed under GPLv2+
|
||||
// Refer to the license.txt file included.
|
||||
|
||||
#include "Common/GL/GLInterface/BGL.h"
|
||||
|
||||
#include <GLView.h>
|
||||
#include <Size.h>
|
||||
#include <Window.h>
|
||||
|
||||
void cInterfaceBGL::Swap()
|
||||
{
|
||||
m_gl->SwapBuffers();
|
||||
}
|
||||
|
||||
bool cInterfaceBGL::Create(void* window_handle, bool stereo, bool core)
|
||||
{
|
||||
m_window = static_cast<BWindow*>(window_handle);
|
||||
|
||||
m_gl = new BGLView(m_window->Bounds(), "cInterfaceBGL", B_FOLLOW_ALL_SIDES, 0,
|
||||
BGL_RGB | BGL_DOUBLE | BGL_ALPHA);
|
||||
m_window->AddChild(m_gl);
|
||||
|
||||
s_opengl_mode = GLInterfaceMode::MODE_OPENGL;
|
||||
|
||||
// Control m_window size and picture scaling
|
||||
BRect size = m_gl->Frame();
|
||||
s_backbuffer_width = size.IntegerWidth();
|
||||
s_backbuffer_height = size.IntegerHeight();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool cInterfaceBGL::MakeCurrent()
|
||||
{
|
||||
m_gl->LockGL();
|
||||
return true;
|
||||
}
|
||||
|
||||
bool cInterfaceBGL::ClearCurrent()
|
||||
{
|
||||
m_gl->UnlockGL();
|
||||
return true;
|
||||
}
|
||||
|
||||
void cInterfaceBGL::Shutdown()
|
||||
{
|
||||
// We don't need to delete m_gl, it's owned by the BWindow.
|
||||
m_gl = nullptr;
|
||||
}
|
||||
|
||||
void cInterfaceBGL::Update()
|
||||
{
|
||||
BRect size = m_gl->Frame();
|
||||
|
||||
if (s_backbuffer_width == size.IntegerWidth() && s_backbuffer_height == size.IntegerHeight())
|
||||
return;
|
||||
|
||||
s_backbuffer_width = size.IntegerWidth();
|
||||
s_backbuffer_height = size.IntegerHeight();
|
||||
}
|
||||
|
||||
void cInterfaceBGL::SwapInterval(int interval)
|
||||
{
|
||||
}
|
||||
|
||||
void* cInterfaceBGL::GetFuncAddress(const std::string& name)
|
||||
{
|
||||
return m_gl->GetGLProcAddress(name.c_str());
|
||||
}
|
||||
@@ -1,27 +0,0 @@
|
||||
// Copyright 2017 Dolphin Emulator Project
|
||||
// Licensed under GPLv2+
|
||||
// Refer to the license.txt file included.
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "Common/GL/GLInterfaceBase.h"
|
||||
|
||||
class BWindow;
|
||||
class BGLView;
|
||||
|
||||
class cInterfaceBGL final : public cInterfaceBase
|
||||
{
|
||||
public:
|
||||
void Swap() override;
|
||||
void* GetFuncAddress(const std::string& name) override;
|
||||
bool Create(void* window_handle, bool stereo, bool core) override;
|
||||
bool MakeCurrent() override;
|
||||
bool ClearCurrent() override;
|
||||
void Shutdown() override;
|
||||
void Update() override;
|
||||
void SwapInterval(int interval) override;
|
||||
|
||||
private:
|
||||
BWindow* m_window;
|
||||
BGLView* m_gl;
|
||||
};
|
||||
@@ -9,7 +9,6 @@
|
||||
|
||||
#include "Common/GL/GLInterface/EGL.h"
|
||||
#include "Common/Logging/Log.h"
|
||||
#include "Core/Config/GraphicsSettings.h"
|
||||
|
||||
#ifndef EGL_KHR_create_context
|
||||
#define EGL_KHR_create_context 1
|
||||
@@ -28,35 +27,37 @@
|
||||
#define EGL_OPENGL_ES3_BIT_KHR 0x00000040
|
||||
#endif /* EGL_KHR_create_context */
|
||||
|
||||
// Show the current FPS
|
||||
void cInterfaceEGL::Swap()
|
||||
GLContextEGL::~GLContextEGL()
|
||||
{
|
||||
if (egl_surf != EGL_NO_SURFACE)
|
||||
eglSwapBuffers(egl_dpy, egl_surf);
|
||||
}
|
||||
void cInterfaceEGL::SwapInterval(int Interval)
|
||||
{
|
||||
eglSwapInterval(egl_dpy, Interval);
|
||||
DestroyWindowSurface();
|
||||
DestroyContext();
|
||||
}
|
||||
|
||||
void* cInterfaceEGL::GetFuncAddress(const std::string& name)
|
||||
bool GLContextEGL::IsHeadless() const
|
||||
{
|
||||
return m_host_window == nullptr;
|
||||
}
|
||||
|
||||
void GLContextEGL::Swap()
|
||||
{
|
||||
if (m_egl_surface != EGL_NO_SURFACE)
|
||||
eglSwapBuffers(m_egl_display, m_egl_surface);
|
||||
}
|
||||
void GLContextEGL::SwapInterval(int interval)
|
||||
{
|
||||
eglSwapInterval(m_egl_display, interval);
|
||||
}
|
||||
|
||||
void* GLContextEGL::GetFuncAddress(const std::string& name)
|
||||
{
|
||||
return (void*)eglGetProcAddress(name.c_str());
|
||||
}
|
||||
|
||||
void cInterfaceEGL::DetectMode()
|
||||
void GLContextEGL::DetectMode(bool has_handle)
|
||||
{
|
||||
if (s_opengl_mode != GLInterfaceMode::MODE_DETECT)
|
||||
return;
|
||||
bool preferGLES = Config::Get(Config::GFX_PREFER_GLES);
|
||||
|
||||
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,
|
||||
}};
|
||||
bool supportsGL = false, supportsGLES3 = false;
|
||||
std::array<int, 3> renderable_types{{EGL_OPENGL_BIT, EGL_OPENGL_ES3_BIT_KHR}};
|
||||
|
||||
for (auto renderable_type : renderable_types)
|
||||
{
|
||||
@@ -71,11 +72,11 @@ void cInterfaceEGL::DetectMode()
|
||||
EGL_RENDERABLE_TYPE,
|
||||
renderable_type,
|
||||
EGL_SURFACE_TYPE,
|
||||
m_has_handle ? EGL_WINDOW_BIT : 0,
|
||||
has_handle ? EGL_WINDOW_BIT : 0,
|
||||
EGL_NONE};
|
||||
|
||||
// Get how many configs there are
|
||||
if (!eglChooseConfig(egl_dpy, attribs, nullptr, 0, &num_configs))
|
||||
if (!eglChooseConfig(m_egl_display, attribs, nullptr, 0, &num_configs))
|
||||
{
|
||||
INFO_LOG(VIDEO, "Error: couldn't get an EGL visual config");
|
||||
continue;
|
||||
@@ -84,7 +85,7 @@ void cInterfaceEGL::DetectMode()
|
||||
EGLConfig* config = new EGLConfig[num_configs];
|
||||
|
||||
// Get all the configurations
|
||||
if (!eglChooseConfig(egl_dpy, attribs, config, num_configs, &num_configs))
|
||||
if (!eglChooseConfig(m_egl_display, attribs, config, num_configs, &num_configs))
|
||||
{
|
||||
INFO_LOG(VIDEO, "Error: couldn't get an EGL visual config");
|
||||
delete[] config;
|
||||
@@ -95,80 +96,68 @@ void cInterfaceEGL::DetectMode()
|
||||
{
|
||||
EGLint attribVal;
|
||||
bool ret;
|
||||
ret = eglGetConfigAttrib(egl_dpy, config[i], EGL_RENDERABLE_TYPE, &attribVal);
|
||||
ret = eglGetConfigAttrib(m_egl_display, config[i], EGL_RENDERABLE_TYPE, &attribVal);
|
||||
if (ret)
|
||||
{
|
||||
if (attribVal & EGL_OPENGL_BIT)
|
||||
supportsGL = true;
|
||||
if (attribVal & (1 << 6)) /* EGL_OPENGL_ES3_BIT_KHR */
|
||||
if (attribVal & EGL_OPENGL_ES3_BIT_KHR)
|
||||
supportsGLES3 = true;
|
||||
if (attribVal & EGL_OPENGL_ES2_BIT)
|
||||
supportsGLES2 = true;
|
||||
}
|
||||
}
|
||||
delete[] config;
|
||||
}
|
||||
|
||||
if (preferGLES)
|
||||
{
|
||||
if (supportsGLES3)
|
||||
s_opengl_mode = GLInterfaceMode::MODE_OPENGLES3;
|
||||
else if (supportsGLES2)
|
||||
s_opengl_mode = GLInterfaceMode::MODE_OPENGLES2;
|
||||
else if (supportsGL)
|
||||
s_opengl_mode = GLInterfaceMode::MODE_OPENGL;
|
||||
}
|
||||
else
|
||||
{
|
||||
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_OPENGL)
|
||||
if (supportsGL)
|
||||
{
|
||||
INFO_LOG(VIDEO, "Using OpenGL");
|
||||
m_opengl_mode = Mode::OpenGL;
|
||||
}
|
||||
else if (s_opengl_mode == GLInterfaceMode::MODE_OPENGLES3)
|
||||
else if (supportsGLES3)
|
||||
{
|
||||
INFO_LOG(VIDEO, "Using OpenGL|ES 3");
|
||||
INFO_LOG(VIDEO, "Using OpenGL|ES");
|
||||
m_opengl_mode = Mode::OpenGLES;
|
||||
}
|
||||
else if (s_opengl_mode == GLInterfaceMode::MODE_OPENGLES2)
|
||||
{
|
||||
INFO_LOG(VIDEO, "Using OpenGL|ES 2");
|
||||
}
|
||||
else if (s_opengl_mode == GLInterfaceMode::MODE_DETECT)
|
||||
else
|
||||
{
|
||||
// Errored before we found a mode
|
||||
ERROR_LOG(VIDEO, "Error: Failed to detect OpenGL flavour, falling back to OpenGL");
|
||||
// This will fail to create a context, as it'll try to use the same attribs we just failed to
|
||||
// find a matching config with
|
||||
s_opengl_mode = GLInterfaceMode::MODE_OPENGL;
|
||||
m_opengl_mode = Mode::OpenGL;
|
||||
}
|
||||
}
|
||||
|
||||
EGLDisplay GLContextEGL::OpenEGLDisplay()
|
||||
{
|
||||
return eglGetDisplay(EGL_DEFAULT_DISPLAY);
|
||||
}
|
||||
|
||||
EGLNativeWindowType GLContextEGL::GetEGLNativeWindow(EGLConfig config)
|
||||
{
|
||||
return reinterpret_cast<EGLNativeWindowType>(EGL_DEFAULT_DISPLAY);
|
||||
}
|
||||
|
||||
// Create rendering window.
|
||||
// Call browser: Core.cpp:EmuThread() > main.cpp:Video_Initialize()
|
||||
bool cInterfaceEGL::Create(void* window_handle, bool stereo, bool core)
|
||||
bool GLContextEGL::Initialize(void* display_handle, void* window_handle, bool stereo, bool core)
|
||||
{
|
||||
const bool has_handle = !!window_handle;
|
||||
|
||||
EGLint egl_major, egl_minor;
|
||||
bool supports_core_profile = false;
|
||||
|
||||
egl_dpy = OpenDisplay();
|
||||
m_host_window = (EGLNativeWindowType)window_handle;
|
||||
m_has_handle = !!window_handle;
|
||||
m_core = core;
|
||||
m_host_display = display_handle;
|
||||
m_host_window = window_handle;
|
||||
m_egl_display = OpenEGLDisplay();
|
||||
|
||||
if (!egl_dpy)
|
||||
if (!m_egl_display)
|
||||
{
|
||||
INFO_LOG(VIDEO, "Error: eglGetDisplay() failed");
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!eglInitialize(egl_dpy, &egl_major, &egl_minor))
|
||||
if (!eglInitialize(m_egl_display, &egl_major, &egl_minor))
|
||||
{
|
||||
INFO_LOG(VIDEO, "Error: eglInitialize() failed");
|
||||
return false;
|
||||
@@ -177,12 +166,13 @@ bool cInterfaceEGL::Create(void* window_handle, bool stereo, bool core)
|
||||
/* Detection code */
|
||||
EGLint num_configs;
|
||||
|
||||
DetectMode();
|
||||
if (m_opengl_mode == Mode::Detect)
|
||||
DetectMode(has_handle);
|
||||
|
||||
// attributes for a visual in RGBA format with at least
|
||||
// 8 bits per color
|
||||
int attribs[] = {EGL_RENDERABLE_TYPE,
|
||||
EGL_OPENGL_ES2_BIT,
|
||||
0,
|
||||
EGL_RED_SIZE,
|
||||
8,
|
||||
EGL_GREEN_SIZE,
|
||||
@@ -190,43 +180,38 @@ bool cInterfaceEGL::Create(void* window_handle, bool stereo, bool core)
|
||||
EGL_BLUE_SIZE,
|
||||
8,
|
||||
EGL_SURFACE_TYPE,
|
||||
m_has_handle ? EGL_WINDOW_BIT : 0,
|
||||
has_handle ? EGL_WINDOW_BIT : 0,
|
||||
EGL_NONE};
|
||||
|
||||
std::vector<EGLint> ctx_attribs;
|
||||
switch (s_opengl_mode)
|
||||
switch (m_opengl_mode)
|
||||
{
|
||||
case GLInterfaceMode::MODE_OPENGL:
|
||||
case Mode::OpenGL:
|
||||
attribs[1] = EGL_OPENGL_BIT;
|
||||
ctx_attribs = {EGL_NONE};
|
||||
break;
|
||||
case GLInterfaceMode::MODE_OPENGLES2:
|
||||
attribs[1] = EGL_OPENGL_ES2_BIT;
|
||||
ctx_attribs = {EGL_CONTEXT_CLIENT_VERSION, 2, EGL_NONE};
|
||||
break;
|
||||
case GLInterfaceMode::MODE_OPENGLES3:
|
||||
attribs[1] = (1 << 6); /* EGL_OPENGL_ES3_BIT_KHR */
|
||||
case Mode::OpenGLES:
|
||||
attribs[1] = EGL_OPENGL_ES3_BIT_KHR;
|
||||
ctx_attribs = {EGL_CONTEXT_CLIENT_VERSION, 3, EGL_NONE};
|
||||
break;
|
||||
default:
|
||||
ERROR_LOG(VIDEO, "Unknown opengl mode set");
|
||||
return false;
|
||||
break;
|
||||
}
|
||||
|
||||
if (!eglChooseConfig(egl_dpy, attribs, &m_config, 1, &num_configs))
|
||||
if (!eglChooseConfig(m_egl_display, attribs, &m_config, 1, &num_configs))
|
||||
{
|
||||
INFO_LOG(VIDEO, "Error: couldn't get an EGL visual config");
|
||||
return false;
|
||||
}
|
||||
|
||||
if (s_opengl_mode == GLInterfaceMode::MODE_OPENGL)
|
||||
if (m_opengl_mode == Mode::OpenGL)
|
||||
eglBindAPI(EGL_OPENGL_API);
|
||||
else
|
||||
eglBindAPI(EGL_OPENGL_ES_API);
|
||||
|
||||
std::string tmp;
|
||||
std::istringstream buffer(eglQueryString(egl_dpy, EGL_EXTENSIONS));
|
||||
std::istringstream buffer(eglQueryString(m_egl_display, EGL_EXTENSIONS));
|
||||
while (buffer >> tmp)
|
||||
{
|
||||
if (tmp == "EGL_KHR_surfaceless_context")
|
||||
@@ -235,19 +220,9 @@ bool cInterfaceEGL::Create(void* window_handle, bool stereo, bool core)
|
||||
supports_core_profile = true;
|
||||
}
|
||||
|
||||
if (supports_core_profile && core && s_opengl_mode == GLInterfaceMode::MODE_OPENGL)
|
||||
if (supports_core_profile && core && m_opengl_mode == Mode::OpenGL)
|
||||
{
|
||||
std::array<std::pair<int, int>, 7> versions_to_try = {{
|
||||
{4, 5},
|
||||
{4, 4},
|
||||
{4, 3},
|
||||
{4, 2},
|
||||
{4, 1},
|
||||
{4, 0},
|
||||
{3, 3},
|
||||
}};
|
||||
|
||||
for (const auto& version : versions_to_try)
|
||||
for (const auto& version : s_desktop_opengl_versions)
|
||||
{
|
||||
std::vector<EGLint> core_attribs = {EGL_CONTEXT_MAJOR_VERSION_KHR,
|
||||
version.first,
|
||||
@@ -259,8 +234,8 @@ bool cInterfaceEGL::Create(void* window_handle, bool stereo, bool core)
|
||||
EGL_CONTEXT_OPENGL_FORWARD_COMPATIBLE_BIT_KHR,
|
||||
EGL_NONE};
|
||||
|
||||
egl_ctx = eglCreateContext(egl_dpy, m_config, EGL_NO_CONTEXT, &core_attribs[0]);
|
||||
if (egl_ctx)
|
||||
m_egl_context = eglCreateContext(m_egl_display, m_config, EGL_NO_CONTEXT, &core_attribs[0]);
|
||||
if (m_egl_context)
|
||||
{
|
||||
m_attribs = std::move(core_attribs);
|
||||
break;
|
||||
@@ -268,14 +243,13 @@ bool cInterfaceEGL::Create(void* window_handle, bool stereo, bool core)
|
||||
}
|
||||
}
|
||||
|
||||
if (!egl_ctx)
|
||||
if (!m_egl_context)
|
||||
{
|
||||
m_core = false;
|
||||
egl_ctx = eglCreateContext(egl_dpy, m_config, EGL_NO_CONTEXT, &ctx_attribs[0]);
|
||||
m_egl_context = eglCreateContext(m_egl_display, m_config, EGL_NO_CONTEXT, &ctx_attribs[0]);
|
||||
m_attribs = std::move(ctx_attribs);
|
||||
}
|
||||
|
||||
if (!egl_ctx)
|
||||
if (!m_egl_context)
|
||||
{
|
||||
INFO_LOG(VIDEO, "Error: eglCreateContext failed");
|
||||
return false;
|
||||
@@ -286,56 +260,45 @@ bool cInterfaceEGL::Create(void* window_handle, bool stereo, bool core)
|
||||
ERROR_LOG(VIDEO, "Error: CreateWindowSurface failed 0x%04x", eglGetError());
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
|
||||
return MakeCurrent();
|
||||
}
|
||||
|
||||
std::unique_ptr<cInterfaceBase> cInterfaceEGL::CreateSharedContext()
|
||||
std::unique_ptr<GLContext> GLContextEGL::CreateSharedContext()
|
||||
{
|
||||
std::unique_ptr<cInterfaceBase> context = std::make_unique<cInterfaceEGL>();
|
||||
if (!context->Create(this))
|
||||
return nullptr;
|
||||
return context;
|
||||
}
|
||||
|
||||
bool cInterfaceEGL::Create(cInterfaceBase* main_context)
|
||||
{
|
||||
cInterfaceEGL* egl_context = static_cast<cInterfaceEGL*>(main_context);
|
||||
|
||||
egl_dpy = egl_context->egl_dpy;
|
||||
m_core = egl_context->m_core;
|
||||
m_config = egl_context->m_config;
|
||||
m_supports_surfaceless = egl_context->m_supports_surfaceless;
|
||||
m_is_shared = true;
|
||||
m_has_handle = false;
|
||||
|
||||
if (egl_context->GetMode() == GLInterfaceMode::MODE_OPENGL)
|
||||
eglBindAPI(EGL_OPENGL_API);
|
||||
else
|
||||
eglBindAPI(EGL_OPENGL_ES_API);
|
||||
|
||||
egl_ctx =
|
||||
eglCreateContext(egl_dpy, m_config, egl_context->egl_ctx, egl_context->m_attribs.data());
|
||||
if (!egl_ctx)
|
||||
eglBindAPI(m_opengl_mode == Mode::OpenGL ? EGL_OPENGL_API : EGL_OPENGL_ES_API);
|
||||
EGLContext new_egl_context =
|
||||
eglCreateContext(m_egl_display, m_config, m_egl_context, m_attribs.data());
|
||||
if (!new_egl_context)
|
||||
{
|
||||
INFO_LOG(VIDEO, "Error: eglCreateContext failed 0x%04x", eglGetError());
|
||||
return false;
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
if (!CreateWindowSurface())
|
||||
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_egl_display = m_egl_display;
|
||||
new_context->m_config = m_config;
|
||||
new_context->m_supports_surfaceless = m_supports_surfaceless;
|
||||
new_context->m_is_shared = true;
|
||||
if (!new_context->CreateWindowSurface())
|
||||
{
|
||||
ERROR_LOG(VIDEO, "Error: CreateWindowSurface failed 0x%04x", eglGetError());
|
||||
return false;
|
||||
return nullptr;
|
||||
}
|
||||
return true;
|
||||
|
||||
return new_context;
|
||||
}
|
||||
|
||||
bool cInterfaceEGL::CreateWindowSurface()
|
||||
bool GLContextEGL::CreateWindowSurface()
|
||||
{
|
||||
if (m_has_handle)
|
||||
if (m_host_window)
|
||||
{
|
||||
EGLNativeWindowType native_window = InitializePlatform(m_host_window, m_config);
|
||||
egl_surf = eglCreateWindowSurface(egl_dpy, m_config, native_window, nullptr);
|
||||
if (!egl_surf)
|
||||
EGLNativeWindowType native_window = GetEGLNativeWindow(m_config);
|
||||
m_egl_surface = eglCreateWindowSurface(m_egl_display, m_config, native_window, nullptr);
|
||||
if (!m_egl_surface)
|
||||
{
|
||||
INFO_LOG(VIDEO, "Error: eglCreateWindowSurface failed");
|
||||
return false;
|
||||
@@ -346,8 +309,8 @@ bool cInterfaceEGL::CreateWindowSurface()
|
||||
EGLint attrib_list[] = {
|
||||
EGL_NONE,
|
||||
};
|
||||
egl_surf = eglCreatePbufferSurface(egl_dpy, m_config, attrib_list);
|
||||
if (!egl_surf)
|
||||
m_egl_surface = eglCreatePbufferSurface(m_egl_display, m_config, attrib_list);
|
||||
if (!m_egl_surface)
|
||||
{
|
||||
INFO_LOG(VIDEO, "Error: eglCreatePbufferSurface failed");
|
||||
return false;
|
||||
@@ -355,56 +318,54 @@ bool cInterfaceEGL::CreateWindowSurface()
|
||||
}
|
||||
else
|
||||
{
|
||||
egl_surf = EGL_NO_SURFACE;
|
||||
m_egl_surface = EGL_NO_SURFACE;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
void cInterfaceEGL::DestroyWindowSurface()
|
||||
void GLContextEGL::DestroyWindowSurface()
|
||||
{
|
||||
if (egl_surf != EGL_NO_SURFACE && !eglDestroySurface(egl_dpy, egl_surf))
|
||||
if (m_egl_surface == EGL_NO_SURFACE)
|
||||
return;
|
||||
|
||||
if (eglGetCurrentSurface(EGL_DRAW) == m_egl_surface)
|
||||
eglMakeCurrent(m_egl_display, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT);
|
||||
if (!eglDestroySurface(m_egl_display, m_egl_surface))
|
||||
NOTICE_LOG(VIDEO, "Could not destroy window surface.");
|
||||
egl_surf = EGL_NO_SURFACE;
|
||||
m_egl_surface = EGL_NO_SURFACE;
|
||||
}
|
||||
|
||||
bool cInterfaceEGL::MakeCurrent()
|
||||
bool GLContextEGL::MakeCurrent()
|
||||
{
|
||||
return eglMakeCurrent(egl_dpy, egl_surf, egl_surf, egl_ctx);
|
||||
return eglMakeCurrent(m_egl_display, m_egl_surface, m_egl_surface, m_egl_context);
|
||||
}
|
||||
|
||||
void cInterfaceEGL::UpdateHandle(void* window_handle)
|
||||
{
|
||||
m_host_window = (EGLNativeWindowType)window_handle;
|
||||
m_has_handle = !!window_handle;
|
||||
}
|
||||
|
||||
void cInterfaceEGL::UpdateSurface()
|
||||
void GLContextEGL::UpdateSurface(void* window_handle)
|
||||
{
|
||||
m_host_window = window_handle;
|
||||
ClearCurrent();
|
||||
DestroyWindowSurface();
|
||||
CreateWindowSurface();
|
||||
MakeCurrent();
|
||||
}
|
||||
|
||||
bool cInterfaceEGL::ClearCurrent()
|
||||
bool GLContextEGL::ClearCurrent()
|
||||
{
|
||||
return eglMakeCurrent(egl_dpy, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT);
|
||||
return eglMakeCurrent(m_egl_display, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT);
|
||||
}
|
||||
|
||||
// Close backend
|
||||
void cInterfaceEGL::Shutdown()
|
||||
void GLContextEGL::DestroyContext()
|
||||
{
|
||||
ShutdownPlatform();
|
||||
if (egl_ctx)
|
||||
{
|
||||
if (!eglMakeCurrent(egl_dpy, egl_surf, egl_surf, egl_ctx))
|
||||
NOTICE_LOG(VIDEO, "Could not release drawing context.");
|
||||
eglMakeCurrent(egl_dpy, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT);
|
||||
if (!eglDestroyContext(egl_dpy, egl_ctx))
|
||||
NOTICE_LOG(VIDEO, "Could not destroy drawing context.");
|
||||
DestroyWindowSurface();
|
||||
if (!m_is_shared && !eglTerminate(egl_dpy))
|
||||
NOTICE_LOG(VIDEO, "Could not destroy display connection.");
|
||||
egl_ctx = nullptr;
|
||||
}
|
||||
if (!m_egl_context)
|
||||
return;
|
||||
|
||||
if (eglGetCurrentContext() == m_egl_context)
|
||||
eglMakeCurrent(m_egl_display, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT);
|
||||
if (!eglDestroyContext(m_egl_display, m_egl_context))
|
||||
NOTICE_LOG(VIDEO, "Could not destroy drawing context.");
|
||||
if (!m_is_shared && !eglTerminate(m_egl_display))
|
||||
NOTICE_LOG(VIDEO, "Could not destroy display connection.");
|
||||
m_egl_context = EGL_NO_CONTEXT;
|
||||
m_egl_display = EGL_NO_DISPLAY;
|
||||
}
|
||||
|
||||
@@ -9,44 +9,46 @@
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
#include "Common/GL/GLInterfaceBase.h"
|
||||
#include "Common/GL/GLContext.h"
|
||||
|
||||
class cInterfaceEGL : public cInterfaceBase
|
||||
class GLContextEGL : public GLContext
|
||||
{
|
||||
private:
|
||||
EGLConfig m_config;
|
||||
bool m_has_handle;
|
||||
EGLNativeWindowType m_host_window;
|
||||
bool m_supports_surfaceless = false;
|
||||
std::vector<int> m_attribs;
|
||||
public:
|
||||
virtual ~GLContextEGL() override;
|
||||
|
||||
bool IsHeadless() const override;
|
||||
|
||||
std::unique_ptr<GLContext> CreateSharedContext() override;
|
||||
|
||||
bool MakeCurrent() override;
|
||||
bool ClearCurrent() override;
|
||||
|
||||
void UpdateSurface(void* window_handle) override;
|
||||
|
||||
void Swap() override;
|
||||
void SwapInterval(int interval) override;
|
||||
|
||||
void* GetFuncAddress(const std::string& name) override;
|
||||
|
||||
protected:
|
||||
virtual EGLDisplay OpenEGLDisplay();
|
||||
virtual EGLNativeWindowType GetEGLNativeWindow(EGLConfig config);
|
||||
|
||||
bool Initialize(void* display_handle, void* window_handle, bool stereo, bool core) override;
|
||||
|
||||
bool CreateWindowSurface();
|
||||
void DestroyWindowSurface();
|
||||
void DetectMode(bool has_handle);
|
||||
void DestroyContext();
|
||||
|
||||
protected:
|
||||
void DetectMode();
|
||||
EGLSurface egl_surf;
|
||||
EGLContext egl_ctx;
|
||||
EGLDisplay egl_dpy;
|
||||
void* m_host_display = nullptr;
|
||||
void* m_host_window = nullptr;
|
||||
|
||||
virtual EGLDisplay OpenDisplay() { return eglGetDisplay(EGL_DEFAULT_DISPLAY); }
|
||||
virtual EGLNativeWindowType InitializePlatform(EGLNativeWindowType host_window, EGLConfig config)
|
||||
{
|
||||
return (EGLNativeWindowType)EGL_DEFAULT_DISPLAY;
|
||||
}
|
||||
virtual void ShutdownPlatform() {}
|
||||
EGLConfig m_config;
|
||||
bool m_supports_surfaceless = false;
|
||||
std::vector<int> m_attribs;
|
||||
|
||||
public:
|
||||
void Swap() override;
|
||||
void SwapInterval(int interval) override;
|
||||
void SetMode(GLInterfaceMode mode) override { s_opengl_mode = mode; }
|
||||
void* GetFuncAddress(const std::string& name) override;
|
||||
bool Create(void* window_handle, bool stereo, bool core) override;
|
||||
bool Create(cInterfaceBase* main_context) override;
|
||||
bool MakeCurrent() override;
|
||||
bool ClearCurrent() override;
|
||||
void Shutdown() override;
|
||||
void UpdateHandle(void* window_handle) override;
|
||||
void UpdateSurface() override;
|
||||
std::unique_ptr<cInterfaceBase> CreateSharedContext() override;
|
||||
EGLSurface m_egl_surface = EGL_NO_SURFACE;
|
||||
EGLContext m_egl_context = EGL_NO_CONTEXT;
|
||||
EGLDisplay m_egl_display = EGL_NO_DISPLAY;
|
||||
};
|
||||
|
||||
@@ -3,26 +3,19 @@
|
||||
// Refer to the license.txt file included.
|
||||
|
||||
#include "Common/GL/GLInterface/EGLAndroid.h"
|
||||
#include <android/native_window.h>
|
||||
|
||||
EGLDisplay cInterfaceEGLAndroid::OpenDisplay()
|
||||
EGLDisplay GLContextEGLAndroid::OpenEGLDisplay()
|
||||
{
|
||||
return eglGetDisplay(EGL_DEFAULT_DISPLAY);
|
||||
}
|
||||
|
||||
EGLNativeWindowType cInterfaceEGLAndroid::InitializePlatform(EGLNativeWindowType host_window,
|
||||
EGLConfig config)
|
||||
EGLNativeWindowType GLContextEGLAndroid::GetEGLNativeWindow(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);
|
||||
GLInterface->SetBackBufferDimensions(width, height);
|
||||
|
||||
return host_window;
|
||||
}
|
||||
|
||||
void cInterfaceEGLAndroid::ShutdownPlatform()
|
||||
{
|
||||
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);
|
||||
}
|
||||
|
||||
@@ -4,14 +4,11 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <android/native_window.h>
|
||||
#include "Common/GL/GLInterface/EGL.h"
|
||||
|
||||
class cInterfaceEGLAndroid : public cInterfaceEGL
|
||||
class GLContextEGLAndroid final : public GLContextEGL
|
||||
{
|
||||
protected:
|
||||
EGLDisplay OpenDisplay() override;
|
||||
EGLNativeWindowType InitializePlatform(EGLNativeWindowType host_window,
|
||||
EGLConfig config) override;
|
||||
void ShutdownPlatform() override;
|
||||
EGLDisplay OpenEGLDisplay() override;
|
||||
EGLNativeWindowType GetEGLNativeWindow(EGLConfig config) override;
|
||||
};
|
||||
|
||||
@@ -1,30 +0,0 @@
|
||||
// Copyright 2017 Dolphin Emulator Project
|
||||
// Licensed under GPLv2+
|
||||
// Refer to the license.txt file included.
|
||||
|
||||
#include "Common/GL/GLInterface/EGLHaiku.h"
|
||||
|
||||
#include <Window.h>
|
||||
|
||||
EGLDisplay cInterfaceEGLHaiku::OpenDisplay()
|
||||
{
|
||||
return eglGetDisplay(EGL_DEFAULT_DISPLAY);
|
||||
}
|
||||
|
||||
EGLNativeWindowType cInterfaceEGLHaiku::InitializePlatform(EGLNativeWindowType host_window,
|
||||
EGLConfig config)
|
||||
{
|
||||
EGLint format;
|
||||
eglGetConfigAttrib(egl_dpy, config, EGL_NATIVE_VISUAL_ID, &format);
|
||||
|
||||
BWindow* window = reinterpret_cast<BWindow*>(host_window);
|
||||
const int width = window->Size().width;
|
||||
const int height = window->Size().height;
|
||||
GLInterface->SetBackBufferDimensions(width, height);
|
||||
|
||||
return host_window;
|
||||
}
|
||||
|
||||
void cInterfaceEGLHaiku::ShutdownPlatform()
|
||||
{
|
||||
}
|
||||
@@ -1,16 +0,0 @@
|
||||
// Copyright 2017 Dolphin Emulator Project
|
||||
// Licensed under GPLv2+
|
||||
// Refer to the license.txt file included.
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "Common/GL/GLInterface/EGL.h"
|
||||
|
||||
class cInterfaceEGLHaiku final : public cInterfaceEGL
|
||||
{
|
||||
protected:
|
||||
EGLDisplay OpenDisplay() override;
|
||||
EGLNativeWindowType InitializePlatform(EGLNativeWindowType host_window,
|
||||
EGLConfig config) override;
|
||||
void ShutdownPlatform() override;
|
||||
};
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user