[Feat] (EGL): support Linux X11 + EGL

This commit is contained in:
2026-06-07 08:21:20 +08:00
parent a15a13ca46
commit ff41e59282
12 changed files with 527 additions and 107 deletions
+1
View File
@@ -33,6 +33,7 @@
#include <vector> #include <vector>
#include <cassert> #include <cassert>
#include <climits> #include <climits>
#include <cstdlib>
#include <cstdarg> #include <cstdarg>
#include <cstring> #include <cstring>
#include <numeric> #include <numeric>
+42 -6
View File
@@ -53,7 +53,8 @@ namespace MobileGL::MG_Backend {
return false; return false;
} }
if (m_eglWindowSurfaceInitialized && m_windowHandle.Backend == handle.Backend && m_windowHandle.Handle == handle.Handle) { if (m_eglSurfaceInitialized && m_eglSurfaceKind == SurfaceKind::Window &&
m_windowHandle.Backend == handle.Backend && m_windowHandle.Handle == handle.Handle) {
return true; return true;
} }
@@ -63,7 +64,35 @@ namespace MobileGL::MG_Backend {
return false; return false;
} }
m_eglWindowSurfaceInitialized = true; m_eglSurfaceInitialized = true;
m_eglSurfaceKind = SurfaceKind::Window;
m_eglCurrentThreads.clear();
m_backendCapabilitiesInitialized = false;
return true;
}
Bool BackendObject::CreateEGLPbufferSurface(EGLint width, EGLint height) {
const std::lock_guard<std::recursive_mutex> lock(m_eglStateMutex);
if (!m_eglDisplayInitialized) {
MGLOG_E("CreateEGLPbufferSurface failed: EGL display is not initialized");
return false;
}
if (width <= 0 || height <= 0) {
MGLOG_E("CreateEGLPbufferSurface failed: invalid size %dx%d", width, height);
return false;
}
if (m_eglSurfaceInitialized && m_eglSurfaceKind == SurfaceKind::Pbuffer) {
return true;
}
if (!InitPbufferSurface(width, height)) {
MGLOG_E("CreateEGLPbufferSurface failed: backend InitPbufferSurface failed");
return false;
}
m_eglSurfaceInitialized = true;
m_eglSurfaceKind = SurfaceKind::Pbuffer;
m_eglCurrentThreads.clear(); m_eglCurrentThreads.clear();
m_backendCapabilitiesInitialized = false; m_backendCapabilitiesInitialized = false;
return true; return true;
@@ -81,8 +110,8 @@ namespace MobileGL::MG_Backend {
MGLOG_E("MakeEGLCurrent failed: EGL display mismatch or not initialized"); MGLOG_E("MakeEGLCurrent failed: EGL display mismatch or not initialized");
return false; return false;
} }
if (!m_eglWindowSurfaceInitialized) { if (!m_eglSurfaceInitialized) {
MGLOG_E("MakeEGLCurrent failed: EGL window surface is not initialized"); MGLOG_E("MakeEGLCurrent failed: EGL surface is not initialized");
return false; return false;
} }
if (draw == EGL_NO_SURFACE || read == EGL_NO_SURFACE || ctx == EGL_NO_CONTEXT) { if (draw == EGL_NO_SURFACE || read == EGL_NO_SURFACE || ctx == EGL_NO_CONTEXT) {
@@ -104,8 +133,9 @@ namespace MobileGL::MG_Backend {
void BackendObject::ResetEGLRuntimeState() { void BackendObject::ResetEGLRuntimeState() {
const std::lock_guard<std::recursive_mutex> lock(m_eglStateMutex); const std::lock_guard<std::recursive_mutex> lock(m_eglStateMutex);
m_eglWindowSurfaceInitialized = false; m_eglSurfaceInitialized = false;
m_backendCapabilitiesInitialized = false; m_backendCapabilitiesInitialized = false;
m_eglSurfaceKind = SurfaceKind::None;
m_eglCurrentThreads.clear(); m_eglCurrentThreads.clear();
} }
@@ -119,7 +149,7 @@ namespace MobileGL::MG_Backend {
MGLOG_E("SwapEGLBuffers failed: no current context attached"); MGLOG_E("SwapEGLBuffers failed: no current context attached");
return false; return false;
} }
if (!m_eglWindowSurfaceInitialized || draw == EGL_NO_SURFACE) { if (!m_eglSurfaceInitialized || draw == EGL_NO_SURFACE) {
MGLOG_E("SwapEGLBuffers failed: invalid draw surface"); MGLOG_E("SwapEGLBuffers failed: invalid draw surface");
return false; return false;
} }
@@ -138,4 +168,10 @@ namespace MobileGL::MG_Backend {
const std::lock_guard<std::recursive_mutex> lock(m_eglStateMutex); const std::lock_guard<std::recursive_mutex> lock(m_eglStateMutex);
m_windowHandle = handle; m_windowHandle = handle;
} }
Bool BackendObject::InitPbufferSurface(EGLint width, EGLint height) {
(void)width;
(void)height;
return false;
}
} // namespace MobileGL::MG_Backend } // namespace MobileGL::MG_Backend
+11 -1
View File
@@ -94,6 +94,7 @@ namespace MobileGL {
enum class WindowBackend { enum class WindowBackend {
Android, Android,
X11,
// TODO: X11, Wayland, Windows, macOS, etc. // TODO: X11, Wayland, Windows, macOS, etc.
WindowBackendCount, WindowBackendCount,
Unknown = -1 Unknown = -1
@@ -114,6 +115,7 @@ namespace MobileGL {
virtual Bool InitializeEGLDisplay(EGLDisplay dpy, EGLint* major, EGLint* minor); virtual Bool InitializeEGLDisplay(EGLDisplay dpy, EGLint* major, EGLint* minor);
virtual Bool CreateEGLWindowSurface(const WindowHandle& handle); virtual Bool CreateEGLWindowSurface(const WindowHandle& handle);
virtual Bool CreateEGLPbufferSurface(EGLint width, EGLint height);
virtual Bool MakeEGLCurrent(EGLDisplay dpy, EGLSurface draw, EGLSurface read, EGLContext ctx); virtual Bool MakeEGLCurrent(EGLDisplay dpy, EGLSurface draw, EGLSurface read, EGLContext ctx);
virtual Bool SwapEGLBuffers(EGLDisplay dpy, EGLSurface draw); virtual Bool SwapEGLBuffers(EGLDisplay dpy, EGLSurface draw);
@@ -126,14 +128,22 @@ namespace MobileGL {
virtual BackendType GetBackendType() const = 0; virtual BackendType GetBackendType() const = 0;
protected: protected:
enum class SurfaceKind {
None,
Window,
Pbuffer
};
void ResetEGLRuntimeState(); void ResetEGLRuntimeState();
virtual Bool InitPbufferSurface(EGLint width, EGLint height);
mutable std::recursive_mutex m_eglStateMutex; mutable std::recursive_mutex m_eglStateMutex;
WindowHandle m_windowHandle; WindowHandle m_windowHandle;
EGLDisplay m_eglDisplay = EGL_NO_DISPLAY; EGLDisplay m_eglDisplay = EGL_NO_DISPLAY;
Bool m_eglDisplayInitialized = false; Bool m_eglDisplayInitialized = false;
Bool m_eglWindowSurfaceInitialized = false; Bool m_eglSurfaceInitialized = false;
Bool m_backendCapabilitiesInitialized = false; Bool m_backendCapabilitiesInitialized = false;
SurfaceKind m_eglSurfaceKind = SurfaceKind::None;
UnorderedMap<std::thread::id, Bool> m_eglCurrentThreads; UnorderedMap<std::thread::id, Bool> m_eglCurrentThreads;
}; };
} // namespace MG_Backend } // namespace MG_Backend
@@ -78,18 +78,18 @@ namespace MobileGL::MG_Backend::DirectGLES {
return false; return false;
} }
if (handle.Backend != WindowBackend::Android || !handle.Handle) { if ((handle.Backend != WindowBackend::Android && handle.Backend != WindowBackend::X11) || !handle.Handle) {
MGLOG_E("DirectGLES backend only supports Android native windows"); MGLOG_E("DirectGLES backend only supports Android and X11 native windows");
return false; return false;
} }
const Bool sameHandle = const Bool sameHandle = m_eglSurfaceInitialized && m_eglSurfaceKind == SurfaceKind::Window &&
m_eglWindowSurfaceInitialized && m_windowHandle.Backend == handle.Backend && m_windowHandle.Handle == handle.Handle; m_windowHandle.Backend == handle.Backend && m_windowHandle.Handle == handle.Handle;
if (sameHandle) { if (sameHandle) {
return true; return true;
} }
if (m_eglWindowSurfaceInitialized) { if (m_eglSurfaceInitialized) {
DestroyEGLContext(); DestroyEGLContext();
ResetEGLRuntimeState(); ResetEGLRuntimeState();
} }
@@ -97,6 +97,10 @@ namespace MobileGL::MG_Backend::DirectGLES {
return BackendObject::CreateEGLWindowSurface(handle); return BackendObject::CreateEGLWindowSurface(handle);
} }
Bool BackendObject_DirectGLES::InitPbufferSurface(EGLint width, EGLint height) {
return DirectGLES::InitPbufferSurface(width, height);
}
Bool BackendObject_DirectGLES::MakeEGLCurrent(EGLDisplay dpy, EGLSurface draw, EGLSurface read, EGLContext ctx) { Bool BackendObject_DirectGLES::MakeEGLCurrent(EGLDisplay dpy, EGLSurface draw, EGLSurface read, EGLContext ctx) {
if (IsReleaseCurrentRequest(dpy, draw, read, ctx)) { if (IsReleaseCurrentRequest(dpy, draw, read, ctx)) {
return BackendObject::MakeEGLCurrent(dpy, draw, read, ctx); return BackendObject::MakeEGLCurrent(dpy, draw, read, ctx);
@@ -121,7 +125,8 @@ namespace MobileGL::MG_Backend::DirectGLES {
.Extensions = {V_OpenGL30, V_OpenGL31, V_OpenGL32, // OpenGL Extensions .Extensions = {V_OpenGL30, V_OpenGL31, V_OpenGL32, // OpenGL Extensions
V_OpenGL33, E_GL_ARB_draw_buffers_blend, E_GL_ARB_compute_shader, V_OpenGL33, E_GL_ARB_draw_buffers_blend, E_GL_ARB_compute_shader,
E_GL_ARB_shader_storage_buffer_object, E_GL_ARB_shader_image_load_store, E_GL_ARB_shader_storage_buffer_object, E_GL_ARB_shader_image_load_store,
E_GL_ARB_program_interface_query}, E_GL_ARB_program_interface_query, E_GL_ARB_framebuffer_object,
E_GL_EXT_framebuffer_object},
.IsCompatibilityProfile = false // Is Compatibility Profile .IsCompatibilityProfile = false // Is Compatibility Profile
}, },
.StaticBackendCapability = {.AllowVSOnlyPrograms = false} // Backend Capability .StaticBackendCapability = {.AllowVSOnlyPrograms = false} // Backend Capability
@@ -35,6 +35,7 @@ namespace MobileGL::MG_Backend::DirectGLES {
private: private:
void UpdateDynamicBackendParameters(); void UpdateDynamicBackendParameters();
Bool InitPbufferSurface(EGLint width, EGLint height) override;
Bool m_initialized = false; Bool m_initialized = false;
MG_External::EGLFunctionsTable m_EGLFunctions; MG_External::EGLFunctionsTable m_EGLFunctions;
+139 -30
View File
@@ -134,7 +134,7 @@ namespace MobileGL::MG_Backend::DirectGLES {
const auto start = std::min(range.start, obj->GetSize()); const auto start = std::min(range.start, obj->GetSize());
const auto end = std::min(range.end, obj->GetSize()); const auto end = std::min(range.end, obj->GetSize());
g_GLESFuncs.glBindBufferRange(glTarget, static_cast<GLuint>(i), backendBufferId, g_GLESFuncs.glBindBufferRange(glTarget, static_cast<GLuint>(i), backendBufferId,
static_cast<GLintptr>(start), static_cast<GLsizeiptr>(end - start)); static_cast<GLintptr>(start), static_cast<GLsizeiptr>(end - start));
} }
} }
} }
@@ -1454,8 +1454,8 @@ namespace MobileGL::MG_Backend::DirectGLES {
return g_GLESFuncs.glGetProgramResourceIndex(backendProgramId, programInterface, name); return g_GLESFuncs.glGetProgramResourceIndex(backendProgramId, programInterface, name);
} }
void GetProgramResourceName(GLuint program, GLenum programInterface, GLuint index, GLsizei bufSize, void GetProgramResourceName(GLuint program, GLenum programInterface, GLuint index, GLsizei bufSize, GLsizei* length,
GLsizei* length, GLchar* name) { GLchar* name) {
GLuint backendProgramId = GetBackendProgramId(program); GLuint backendProgramId = GetBackendProgramId(program);
if (!backendProgramId) return; if (!backendProgramId) return;
g_GLESFuncs.glGetProgramResourceName(backendProgramId, programInterface, index, bufSize, length, name); g_GLESFuncs.glGetProgramResourceName(backendProgramId, programInterface, index, bufSize, length, name);
@@ -1465,8 +1465,8 @@ namespace MobileGL::MG_Backend::DirectGLES {
const GLenum* props, GLsizei bufSize, GLsizei* length, GLint* params) { const GLenum* props, GLsizei bufSize, GLsizei* length, GLint* params) {
GLuint backendProgramId = GetBackendProgramId(program); GLuint backendProgramId = GetBackendProgramId(program);
if (!backendProgramId) return; if (!backendProgramId) return;
g_GLESFuncs.glGetProgramResourceiv(backendProgramId, programInterface, index, propCount, props, bufSize, g_GLESFuncs.glGetProgramResourceiv(backendProgramId, programInterface, index, propCount, props, bufSize, length,
length, params); params);
} }
GLint GetProgramResourceLocation(GLuint program, GLenum programInterface, const GLchar* name) { GLint GetProgramResourceLocation(GLuint program, GLenum programInterface, const GLchar* name) {
@@ -1858,9 +1858,117 @@ namespace MobileGL::MG_Backend::DirectGLES {
static EGLContext g_Context = EGL_NO_CONTEXT; static EGLContext g_Context = EGL_NO_CONTEXT;
static EGLSurface g_Surface = EGL_NO_SURFACE; static EGLSurface g_Surface = EGL_NO_SURFACE;
static EGLConfig g_Config = nullptr; static EGLConfig g_Config = nullptr;
Bool InitWindowSurface(NativeWindowType window) {
// TODO: handle custom EGL paramters static EGLint QueryDefaultX11VisualId() {
if (!window) return false; #if defined(__linux__) && !defined(__ANDROID__)
const char* displayName = std::getenv("DISPLAY");
if (!displayName) {
return 0;
}
void* x11Lib = dlopen("libX11.so.6", RTLD_LOCAL | RTLD_NOW);
if (!x11Lib) {
x11Lib = dlopen("libX11.so", RTLD_LOCAL | RTLD_NOW);
}
if (!x11Lib) {
return 0;
}
using XOpenDisplayFn = void* (*)(const char*);
using XDefaultScreenFn = int (*)(void*);
using XDefaultVisualFn = void* (*)(void*, int);
using XVisualIDFromVisualFn = unsigned long (*)(void*);
using XCloseDisplayFn = int (*)(void*);
auto* xOpenDisplay = reinterpret_cast<XOpenDisplayFn>(dlsym(x11Lib, "XOpenDisplay"));
auto* xDefaultScreen = reinterpret_cast<XDefaultScreenFn>(dlsym(x11Lib, "XDefaultScreen"));
auto* xDefaultVisual = reinterpret_cast<XDefaultVisualFn>(dlsym(x11Lib, "XDefaultVisual"));
auto* xVisualIDFromVisual = reinterpret_cast<XVisualIDFromVisualFn>(dlsym(x11Lib, "XVisualIDFromVisual"));
auto* xCloseDisplay = reinterpret_cast<XCloseDisplayFn>(dlsym(x11Lib, "XCloseDisplay"));
if (!xOpenDisplay || !xDefaultScreen || !xDefaultVisual || !xVisualIDFromVisual || !xCloseDisplay) {
dlclose(x11Lib);
return 0;
}
void* display = xOpenDisplay(displayName);
if (!display) {
dlclose(x11Lib);
return 0;
}
const int screen = xDefaultScreen(display);
void* visual = xDefaultVisual(display, screen);
const auto visualId = visual ? static_cast<EGLint>(xVisualIDFromVisual(visual)) : 0;
xCloseDisplay(display);
dlclose(x11Lib);
return visualId;
#else
return 0;
#endif
}
static Bool GetConfigAttrib(EGLConfig config, EGLint attr, EGLint& value) {
return g_EGLFuncs.eglGetConfigAttrib && g_EGLFuncs.eglGetConfigAttrib(g_Display, config, attr, &value);
}
static Bool ConfigSupports(EGLConfig config, EGLint surfaceBit) {
EGLint surfaceType = 0;
EGLint renderableType = 0;
if (!GetConfigAttrib(config, EGL_SURFACE_TYPE, surfaceType)) {
return false;
}
if (!GetConfigAttrib(config, EGL_RENDERABLE_TYPE, renderableType)) {
return false;
}
return (surfaceType & surfaceBit) && (renderableType & EGL_OPENGL_ES3_BIT);
}
static Bool ChooseConfigForSurface(EGLint surfaceBit, EGLConfig& outConfig) {
const EGLint configAttribs[] = {EGL_SURFACE_TYPE, surfaceBit, EGL_RENDERABLE_TYPE, EGL_OPENGL_ES3_BIT,
EGL_RED_SIZE, 8, EGL_GREEN_SIZE, 8,
EGL_BLUE_SIZE, 8, EGL_ALPHA_SIZE, 8,
EGL_DEPTH_SIZE, 24, EGL_STENCIL_SIZE, 8,
EGL_NONE};
EGLint numConfigs = 0;
if (!g_EGLFuncs.eglChooseConfig(g_Display, configAttribs, nullptr, 0, &numConfigs) || numConfigs == 0) {
return false;
}
Vector<EGLConfig> configs(static_cast<SizeT>(numConfigs));
if (!g_EGLFuncs.eglChooseConfig(g_Display, configAttribs, configs.data(), numConfigs, &numConfigs) ||
numConfigs == 0) {
return false;
}
configs.resize(static_cast<SizeT>(numConfigs));
if (surfaceBit == EGL_WINDOW_BIT) {
const EGLint defaultVisualId = QueryDefaultX11VisualId();
if (defaultVisualId != 0) {
for (const auto config : configs) {
EGLint nativeVisualId = 0;
if (ConfigSupports(config, surfaceBit) &&
GetConfigAttrib(config, EGL_NATIVE_VISUAL_ID, nativeVisualId) &&
nativeVisualId == defaultVisualId) {
outConfig = config;
return true;
}
}
}
}
for (const auto config : configs) {
if (ConfigSupports(config, surfaceBit)) {
outConfig = config;
return true;
}
}
outConfig = configs.front();
return true;
}
static Bool InitDisplayAndContext(EGLint surfaceBit) {
DestroyEGLContext();
g_Display = g_EGLFuncs.eglGetDisplay(EGL_DEFAULT_DISPLAY); g_Display = g_EGLFuncs.eglGetDisplay(EGL_DEFAULT_DISPLAY);
if (g_Display == EGL_NO_DISPLAY) return false; if (g_Display == EGL_NO_DISPLAY) return false;
@@ -1868,32 +1976,18 @@ namespace MobileGL::MG_Backend::DirectGLES {
if (!g_EGLFuncs.eglInitialize(g_Display, nullptr, nullptr)) return false; if (!g_EGLFuncs.eglInitialize(g_Display, nullptr, nullptr)) return false;
g_EGLFuncs.eglBindAPI(EGL_OPENGL_ES_API); g_EGLFuncs.eglBindAPI(EGL_OPENGL_ES_API);
const EGLint configAttribs[] = {EGL_SURFACE_TYPE, if (!ChooseConfigForSurface(surfaceBit, g_Config)) return false;
EGL_WINDOW_BIT,
EGL_RENDERABLE_TYPE,
EGL_OPENGL_ES3_BIT,
EGL_RED_SIZE,
8,
EGL_GREEN_SIZE,
8,
EGL_BLUE_SIZE,
8,
EGL_ALPHA_SIZE,
8,
EGL_DEPTH_SIZE,
24,
EGL_STENCIL_SIZE,
8,
EGL_NONE};
EGLint numConfigs = 0;
if (!g_EGLFuncs.eglChooseConfig(g_Display, configAttribs, &g_Config, 1, &numConfigs) || numConfigs == 0)
return false;
const EGLint contextAttribs[] = {EGL_CONTEXT_CLIENT_VERSION, 3, EGL_NONE}; const EGLint contextAttribs[] = {EGL_CONTEXT_CLIENT_VERSION, 3, EGL_NONE};
g_Context = g_EGLFuncs.eglCreateContext(g_Display, g_Config, EGL_NO_CONTEXT, contextAttribs); g_Context = g_EGLFuncs.eglCreateContext(g_Display, g_Config, EGL_NO_CONTEXT, contextAttribs);
if (g_Context == EGL_NO_CONTEXT) return false; return g_Context != EGL_NO_CONTEXT;
}
Bool InitWindowSurface(NativeWindowType window) {
if (!window) return false;
if (!InitDisplayAndContext(EGL_WINDOW_BIT)) return false;
g_Surface = g_EGLFuncs.eglCreateWindowSurface(g_Display, g_Config, window, nullptr); g_Surface = g_EGLFuncs.eglCreateWindowSurface(g_Display, g_Config, window, nullptr);
if (g_Surface == EGL_NO_SURFACE) return false; if (g_Surface == EGL_NO_SURFACE) return false;
@@ -1905,6 +1999,21 @@ namespace MobileGL::MG_Backend::DirectGLES {
return true; return true;
} }
Bool InitPbufferSurface(EGLint width, EGLint height) {
if (width <= 0 || height <= 0) return false;
if (!InitDisplayAndContext(EGL_PBUFFER_BIT)) return false;
const EGLint surfaceAttribs[] = {EGL_WIDTH, width, EGL_HEIGHT, height, EGL_NONE};
g_Surface = g_EGLFuncs.eglCreatePbufferSurface(g_Display, g_Config, surfaceAttribs);
if (g_Surface == EGL_NO_SURFACE) return false;
if (!g_EGLFuncs.eglMakeCurrent(g_Display, g_Surface, g_Surface, g_Context)) return false;
MGLOG_D("EGL pbuffer context created successfully: display=%p, surface=%p, context=%p. size=%dx%d", g_Display,
g_Surface, g_Context, width, height);
return true;
}
void Present() { void Present() {
if (g_Display != EGL_NO_DISPLAY && g_Surface != EGL_NO_SURFACE) { if (g_Display != EGL_NO_DISPLAY && g_Surface != EGL_NO_SURFACE) {
g_EGLFuncs.eglSwapBuffers(g_Display, g_Surface); g_EGLFuncs.eglSwapBuffers(g_Display, g_Surface);
+3 -2
View File
@@ -67,14 +67,15 @@ namespace MobileGL::MG_Backend::DirectGLES {
void GetProgramiv(GLuint program, GLenum pname, GLint* params); void GetProgramiv(GLuint program, GLenum pname, GLint* params);
void GetProgramInterfaceiv(GLuint program, GLenum programInterface, GLenum pname, GLint* params); void GetProgramInterfaceiv(GLuint program, GLenum programInterface, GLenum pname, GLint* params);
GLuint GetProgramResourceIndex(GLuint program, GLenum programInterface, const GLchar* name); GLuint GetProgramResourceIndex(GLuint program, GLenum programInterface, const GLchar* name);
void GetProgramResourceName(GLuint program, GLenum programInterface, GLuint index, GLsizei bufSize, void GetProgramResourceName(GLuint program, GLenum programInterface, GLuint index, GLsizei bufSize, GLsizei* length,
GLsizei* length, GLchar* name); GLchar* name);
void GetProgramResourceiv(GLuint program, GLenum programInterface, GLuint index, GLsizei propCount, void GetProgramResourceiv(GLuint program, GLenum programInterface, GLuint index, GLsizei propCount,
const GLenum* props, GLsizei bufSize, GLsizei* length, GLint* params); const GLenum* props, GLsizei bufSize, GLsizei* length, GLint* params);
GLint GetProgramResourceLocation(GLuint program, GLenum programInterface, const GLchar* name); GLint GetProgramResourceLocation(GLuint program, GLenum programInterface, const GLchar* name);
GLint GetProgramResourceLocationIndex(GLuint program, GLenum programInterface, const GLchar* name); GLint GetProgramResourceLocationIndex(GLuint program, GLenum programInterface, const GLchar* name);
void ShaderStorageBlockBinding(GLuint program, GLuint storageBlockIndex, GLuint storageBlockBinding); void ShaderStorageBlockBinding(GLuint program, GLuint storageBlockIndex, GLuint storageBlockBinding);
Bool InitWindowSurface(NativeWindowType window); Bool InitWindowSurface(NativeWindowType window);
Bool InitPbufferSurface(EGLint width, EGLint height);
void Present(); void Present();
void SetEGLFuncsTable(const MG_External::EGLFunctionsTable& eglFuncs); void SetEGLFuncsTable(const MG_External::EGLFunctionsTable& eglFuncs);
void SetGLESFuncsTable(const MG_External::GLESFunctionsTable& glesFuncs); void SetGLESFuncsTable(const MG_External::GLESFunctionsTable& glesFuncs);
@@ -71,13 +71,13 @@ namespace MobileGL::MG_Backend::DirectVulkan {
return false; return false;
} }
const Bool sameHandle = const Bool sameHandle = m_eglSurfaceInitialized && m_eglSurfaceKind == SurfaceKind::Window &&
m_eglWindowSurfaceInitialized && m_windowHandle.Backend == handle.Backend && m_windowHandle.Handle == handle.Handle; m_windowHandle.Backend == handle.Backend && m_windowHandle.Handle == handle.Handle;
if (sameHandle) { if (sameHandle) {
return true; return true;
} }
if (m_eglWindowSurfaceInitialized || pVulkanRenderer) { if (m_eglSurfaceInitialized || pVulkanRenderer) {
pVulkanRenderer.reset(); pVulkanRenderer.reset();
ResetEGLRuntimeState(); ResetEGLRuntimeState();
} }
@@ -116,10 +116,8 @@ namespace MobileGL::MG_Backend::DirectVulkan {
.TargetGLVersion = {3, 3, 0}, // Target OpenGL Version .TargetGLVersion = {3, 3, 0}, // Target OpenGL Version
.TargetGLSLVersion = {4, 6, 0}, // Target Shading Language Version .TargetGLSLVersion = {4, 6, 0}, // Target Shading Language Version
.Extensions = {V_OpenGL30, V_OpenGL31, V_OpenGL32, // OpenGL Extensions .Extensions = {V_OpenGL30, V_OpenGL31, V_OpenGL32, // OpenGL Extensions
V_OpenGL33, E_GL_ARB_draw_buffers_blend, V_OpenGL33, E_GL_ARB_draw_buffers_blend, E_GL_ARB_compute_shader,
E_GL_ARB_compute_shader, E_GL_ARB_shader_storage_buffer_object, E_GL_ARB_shader_image_load_store,
E_GL_ARB_shader_storage_buffer_object,
E_GL_ARB_shader_image_load_store,
E_GL_ARB_program_interface_query}, E_GL_ARB_program_interface_query},
.IsCompatibilityProfile = false // Is Compatibility Profile .IsCompatibilityProfile = false // Is Compatibility Profile
}, },
+32 -1
View File
@@ -34,11 +34,25 @@ namespace MobileGL::MG_Impl::EGLImpl {
MG_Backend::WindowBackend DetectWindowBackend() { MG_Backend::WindowBackend DetectWindowBackend() {
#if defined(ANDROID) || defined(__ANDROID__) #if defined(ANDROID) || defined(__ANDROID__)
return MG_Backend::WindowBackend::Android; return MG_Backend::WindowBackend::Android;
#elif defined(__linux__)
return MG_Backend::WindowBackend::X11;
#else #else
return MG_Backend::WindowBackend::Unknown; return MG_Backend::WindowBackend::Unknown;
#endif #endif
} }
EGLint GetAttribValue(const EGLint* attribList, EGLint attrib, EGLint defaultValue) {
if (!attribList) {
return defaultValue;
}
for (SizeT i = 0; attribList[i] != EGL_NONE; i += 2) {
if (attribList[i] == attrib) {
return attribList[i + 1];
}
}
return defaultValue;
}
template <typename NativeType> template <typename NativeType>
Bool IsNullNativeHandle(NativeType nativeHandle) { Bool IsNullNativeHandle(NativeType nativeHandle) {
if constexpr (std::is_pointer_v<NativeType>) { if constexpr (std::is_pointer_v<NativeType>) {
@@ -330,7 +344,24 @@ namespace MobileGL::MG_Impl::EGLImpl {
if (!state) { if (!state) {
return EGL_NO_SURFACE; return EGL_NO_SURFACE;
} }
return state->CreatePbufferSurface(dpy, config, attrib_list); const EGLint width = GetAttribValue(attrib_list, EGL_WIDTH, 1);
const EGLint height = GetAttribValue(attrib_list, EGL_HEIGHT, 1);
EGLSurface surface = state->CreatePbufferSurface(dpy, config, attrib_list);
if (surface == EGL_NO_SURFACE) {
return EGL_NO_SURFACE;
}
auto* backendObject = GetBackendObject(state);
if (!backendObject) {
return EGL_NO_SURFACE;
}
if (!backendObject->CreateEGLPbufferSurface(width, height)) {
state->DestroySurface(dpy, surface);
state->SetError(EGL_BAD_ALLOC);
return EGL_NO_SURFACE;
}
return surface;
} }
EGLBoolean BindTexImage(EGLDisplay dpy, EGLSurface surface, EGLint buffer) { EGLBoolean BindTexImage(EGLDisplay dpy, EGLSurface surface, EGLint buffer) {
+104 -43
View File
@@ -17,42 +17,40 @@
#include "../Framebuffer/GL_Framebuffer.h" #include "../Framebuffer/GL_Framebuffer.h"
#include "../VertexArray/GL_VertexArray.h" #include "../VertexArray/GL_VertexArray.h"
#define DECLARE_GL_FUNCTION_STUB_HEAD(type,name,...) \ #define DECLARE_GL_FUNCTION_STUB_HEAD(type, name, ...) MOBILEGL_GL_API type gl##name(__VA_ARGS__) {
MOBILEGL_GL_API type gl##name(__VA_ARGS__) {
#define DECLARE_GL_FUNCTION_STUB_END(type,name,...) \ #define DECLARE_GL_FUNCTION_STUB_END(type, name, ...) \
MGLOG_W("Stub function: %s(...)", __FUNCTION__); \ MGLOG_W("Stub function: %s(...)", __FUNCTION__); \
return (type)1; \ return (type)1; \
} }
#define DECLARE_GL_FUNCTION_STUB_END_NO_RETURN(type,name,...) \ #define DECLARE_GL_FUNCTION_STUB_END_NO_RETURN(type, name, ...) \
MGLOG_W("Stub function: %s(...)", __FUNCTION__); \ MGLOG_W("Stub function: %s(...)", __FUNCTION__); \
} }
#define DECLARE_GL_FUNCTION_HEAD(type,name,...) \ #define DECLARE_GL_FUNCTION_HEAD(type, name, ...) MOBILEGL_GL_API type gl##name(__VA_ARGS__) {
MOBILEGL_GL_API type gl##name(__VA_ARGS__) {
#ifdef TRACY_ENABLE #ifdef TRACY_ENABLE
#define DECLARE_GL_FUNCTION_END(type,name,...) \ #define DECLARE_GL_FUNCTION_END(type, name, ...) \
ZoneScopedC(TRACY_ZONECOLOR_ENTRY); \ ZoneScopedC(TRACY_ZONECOLOR_ENTRY); \
MGLOG_D("Implementing function: %s(...)", __FUNCTION__); \ MGLOG_D("Implementing function: %s(...)", __FUNCTION__); \
return MobileGL::MG_Impl::GLImpl::name(__VA_ARGS__); \ return MobileGL::MG_Impl::GLImpl::name(__VA_ARGS__); \
} }
#define DECLARE_GL_FUNCTION_END_NO_RETURN(type,name,...) \ #define DECLARE_GL_FUNCTION_END_NO_RETURN(type, name, ...) \
ZoneScopedC(TRACY_ZONECOLOR_ENTRY); \ ZoneScopedC(TRACY_ZONECOLOR_ENTRY); \
MGLOG_D("Implementing function: %s(...)", __FUNCTION__); \ MGLOG_D("Implementing function: %s(...)", __FUNCTION__); \
MobileGL::MG_Impl::GLImpl::name(__VA_ARGS__); \ MobileGL::MG_Impl::GLImpl::name(__VA_ARGS__); \
} }
#else #else
#define DECLARE_GL_FUNCTION_END(type,name,...) \ #define DECLARE_GL_FUNCTION_END(type, name, ...) \
MGLOG_D("Implementing function: %s(...)", __FUNCTION__); \ MGLOG_D("Implementing function: %s(...)", __FUNCTION__); \
return MobileGL::MG_Impl::GLImpl::name(__VA_ARGS__); \ return MobileGL::MG_Impl::GLImpl::name(__VA_ARGS__); \
} }
#define DECLARE_GL_FUNCTION_END_NO_RETURN(type,name,...) \ #define DECLARE_GL_FUNCTION_END_NO_RETURN(type, name, ...) \
MGLOG_D("Implementing function: %s(...)", __FUNCTION__); \ MGLOG_D("Implementing function: %s(...)", __FUNCTION__); \
MobileGL::MG_Impl::GLImpl::name(__VA_ARGS__); \ MobileGL::MG_Impl::GLImpl::name(__VA_ARGS__); \
} }
#endif #endif
@@ -2880,6 +2878,69 @@ MOBILEGL_GL_API void glGetFramebufferParameterivEXT(GLenum target, GLenum pname,
glGetFramebufferParameteriv(target, pname, params); glGetFramebufferParameteriv(target, pname, params);
} }
MOBILEGL_GL_API void glBindFramebufferEXT(GLenum target, GLuint framebuffer) {
glBindFramebuffer(target, framebuffer);
}
MOBILEGL_GL_API void glBindRenderbufferEXT(GLenum target, GLuint renderbuffer) {
glBindRenderbuffer(target, renderbuffer);
}
MOBILEGL_GL_API GLenum glCheckFramebufferStatusEXT(GLenum target) {
return glCheckFramebufferStatus(target);
}
MOBILEGL_GL_API void glDeleteFramebuffersEXT(GLsizei n, const GLuint* framebuffers) {
glDeleteFramebuffers(n, framebuffers);
}
MOBILEGL_GL_API void glDeleteRenderbuffersEXT(GLsizei n, const GLuint* renderbuffers) {
glDeleteRenderbuffers(n, renderbuffers);
}
MOBILEGL_GL_API void glFramebufferRenderbufferEXT(GLenum target, GLenum attachment, GLenum renderbuffertarget,
GLuint renderbuffer) {
glFramebufferRenderbuffer(target, attachment, renderbuffertarget, renderbuffer);
}
MOBILEGL_GL_API void glFramebufferTexture2DEXT(GLenum target, GLenum attachment, GLenum textarget, GLuint texture,
GLint level) {
glFramebufferTexture2D(target, attachment, textarget, texture, level);
}
MOBILEGL_GL_API void glGenFramebuffersEXT(GLsizei n, GLuint* framebuffers) {
glGenFramebuffers(n, framebuffers);
}
MOBILEGL_GL_API void glGenRenderbuffersEXT(GLsizei n, GLuint* renderbuffers) {
glGenRenderbuffers(n, renderbuffers);
}
MOBILEGL_GL_API void glGenerateMipmapEXT(GLenum target) {
glGenerateMipmap(target);
}
MOBILEGL_GL_API void glGetFramebufferAttachmentParameterivEXT(GLenum target, GLenum attachment, GLenum pname,
GLint* params) {
glGetFramebufferAttachmentParameteriv(target, attachment, pname, params);
}
MOBILEGL_GL_API void glGetRenderbufferParameterivEXT(GLenum target, GLenum pname, GLint* params) {
glGetRenderbufferParameteriv(target, pname, params);
}
MOBILEGL_GL_API GLboolean glIsFramebufferEXT(GLuint framebuffer) {
return glIsFramebuffer(framebuffer);
}
MOBILEGL_GL_API GLboolean glIsRenderbufferEXT(GLuint renderbuffer) {
return glIsRenderbuffer(renderbuffer);
}
MOBILEGL_GL_API void glRenderbufferStorageEXT(GLenum target, GLenum internalformat, GLsizei width, GLsizei height) {
glRenderbufferStorage(target, internalformat, width, height);
}
MOBILEGL_GL_API GLenum glGetGraphicsResetStatusARB(void) { MOBILEGL_GL_API GLenum glGetGraphicsResetStatusARB(void) {
return glGetGraphicsResetStatus(); return glGetGraphicsResetStatus();
} }
@@ -3025,48 +3086,48 @@ MOBILEGL_GL_API void glProgramUniform4uivEXT(GLuint program, GLint location, GLs
glProgramUniform4uiv(program, location, count, value); glProgramUniform4uiv(program, location, count, value);
} }
MOBILEGL_GL_API void glProgramUniformMatrix2fvEXT(GLuint program, GLint location, GLsizei count, MOBILEGL_GL_API void glProgramUniformMatrix2fvEXT(GLuint program, GLint location, GLsizei count, GLboolean transpose,
GLboolean transpose, const GLfloat* value) { const GLfloat* value) {
glProgramUniformMatrix2fv(program, location, count, transpose, value); glProgramUniformMatrix2fv(program, location, count, transpose, value);
} }
MOBILEGL_GL_API void glProgramUniformMatrix2x3fvEXT(GLuint program, GLint location, GLsizei count, MOBILEGL_GL_API void glProgramUniformMatrix2x3fvEXT(GLuint program, GLint location, GLsizei count, GLboolean transpose,
GLboolean transpose, const GLfloat* value) { const GLfloat* value) {
glProgramUniformMatrix2x3fv(program, location, count, transpose, value); glProgramUniformMatrix2x3fv(program, location, count, transpose, value);
} }
MOBILEGL_GL_API void glProgramUniformMatrix2x4fvEXT(GLuint program, GLint location, GLsizei count, MOBILEGL_GL_API void glProgramUniformMatrix2x4fvEXT(GLuint program, GLint location, GLsizei count, GLboolean transpose,
GLboolean transpose, const GLfloat* value) { const GLfloat* value) {
glProgramUniformMatrix2x4fv(program, location, count, transpose, value); glProgramUniformMatrix2x4fv(program, location, count, transpose, value);
} }
MOBILEGL_GL_API void glProgramUniformMatrix3fvEXT(GLuint program, GLint location, GLsizei count, MOBILEGL_GL_API void glProgramUniformMatrix3fvEXT(GLuint program, GLint location, GLsizei count, GLboolean transpose,
GLboolean transpose, const GLfloat* value) { const GLfloat* value) {
glProgramUniformMatrix3fv(program, location, count, transpose, value); glProgramUniformMatrix3fv(program, location, count, transpose, value);
} }
MOBILEGL_GL_API void glProgramUniformMatrix3x2fvEXT(GLuint program, GLint location, GLsizei count, MOBILEGL_GL_API void glProgramUniformMatrix3x2fvEXT(GLuint program, GLint location, GLsizei count, GLboolean transpose,
GLboolean transpose, const GLfloat* value) { const GLfloat* value) {
glProgramUniformMatrix3x2fv(program, location, count, transpose, value); glProgramUniformMatrix3x2fv(program, location, count, transpose, value);
} }
MOBILEGL_GL_API void glProgramUniformMatrix3x4fvEXT(GLuint program, GLint location, GLsizei count, MOBILEGL_GL_API void glProgramUniformMatrix3x4fvEXT(GLuint program, GLint location, GLsizei count, GLboolean transpose,
GLboolean transpose, const GLfloat* value) { const GLfloat* value) {
glProgramUniformMatrix3x4fv(program, location, count, transpose, value); glProgramUniformMatrix3x4fv(program, location, count, transpose, value);
} }
MOBILEGL_GL_API void glProgramUniformMatrix4fvEXT(GLuint program, GLint location, GLsizei count, MOBILEGL_GL_API void glProgramUniformMatrix4fvEXT(GLuint program, GLint location, GLsizei count, GLboolean transpose,
GLboolean transpose, const GLfloat* value) { const GLfloat* value) {
glProgramUniformMatrix4fv(program, location, count, transpose, value); glProgramUniformMatrix4fv(program, location, count, transpose, value);
} }
MOBILEGL_GL_API void glProgramUniformMatrix4x2fvEXT(GLuint program, GLint location, GLsizei count, MOBILEGL_GL_API void glProgramUniformMatrix4x2fvEXT(GLuint program, GLint location, GLsizei count, GLboolean transpose,
GLboolean transpose, const GLfloat* value) { const GLfloat* value) {
glProgramUniformMatrix4x2fv(program, location, count, transpose, value); glProgramUniformMatrix4x2fv(program, location, count, transpose, value);
} }
MOBILEGL_GL_API void glProgramUniformMatrix4x3fvEXT(GLuint program, GLint location, GLsizei count, MOBILEGL_GL_API void glProgramUniformMatrix4x3fvEXT(GLuint program, GLint location, GLsizei count, GLboolean transpose,
GLboolean transpose, const GLfloat* value) { const GLfloat* value) {
glProgramUniformMatrix4x3fv(program, location, count, transpose, value); glProgramUniformMatrix4x3fv(program, location, count, transpose, value);
} }
+177 -10
View File
@@ -14,6 +14,7 @@ namespace MobileGL {
namespace { namespace {
constexpr EGLint EGL_DISPLAY_MAJOR_VERSION = 1; constexpr EGLint EGL_DISPLAY_MAJOR_VERSION = 1;
constexpr EGLint EGL_DISPLAY_MINOR_VERSION = 5; constexpr EGLint EGL_DISPLAY_MINOR_VERSION = 5;
constexpr EGLint DEFAULT_MAX_PBUFFER_SIZE = 16384;
template <typename AttrType> template <typename AttrType>
Optional<AttrType> ParseAttribValue(const AttrType* attribList, EGLint attrib) { Optional<AttrType> ParseAttribValue(const AttrType* attribList, EGLint attrib) {
@@ -27,6 +28,55 @@ namespace MobileGL {
} }
return Nullopt; return Nullopt;
} }
EGLint QueryDefaultX11VisualId() {
#if defined(__linux__) && !defined(__ANDROID__)
const char* displayName = std::getenv("DISPLAY");
if (!displayName) {
return 0;
}
void* x11Lib = dlopen("libX11.so.6", RTLD_LOCAL | RTLD_NOW);
if (!x11Lib) {
x11Lib = dlopen("libX11.so", RTLD_LOCAL | RTLD_NOW);
}
if (!x11Lib) {
return 0;
}
using XOpenDisplayFn = void* (*)(const char*);
using XDefaultScreenFn = int (*)(void*);
using XDefaultVisualFn = void* (*)(void*, int);
using XVisualIDFromVisualFn = unsigned long (*)(void*);
using XCloseDisplayFn = int (*)(void*);
auto* xOpenDisplay = reinterpret_cast<XOpenDisplayFn>(dlsym(x11Lib, "XOpenDisplay"));
auto* xDefaultScreen = reinterpret_cast<XDefaultScreenFn>(dlsym(x11Lib, "XDefaultScreen"));
auto* xDefaultVisual = reinterpret_cast<XDefaultVisualFn>(dlsym(x11Lib, "XDefaultVisual"));
auto* xVisualIDFromVisual =
reinterpret_cast<XVisualIDFromVisualFn>(dlsym(x11Lib, "XVisualIDFromVisual"));
auto* xCloseDisplay = reinterpret_cast<XCloseDisplayFn>(dlsym(x11Lib, "XCloseDisplay"));
if (!xOpenDisplay || !xDefaultScreen || !xDefaultVisual || !xVisualIDFromVisual || !xCloseDisplay) {
dlclose(x11Lib);
return 0;
}
void* display = xOpenDisplay(displayName);
if (!display) {
dlclose(x11Lib);
return 0;
}
const int screen = xDefaultScreen(display);
void* visual = xDefaultVisual(display, screen);
const auto visualId = visual ? static_cast<EGLint>(xVisualIDFromVisual(visual)) : 0;
xCloseDisplay(display);
dlclose(x11Lib);
return visualId;
#else
return 0;
#endif
}
} // namespace } // namespace
Bool EGLContext::DisplayLookupKey::operator==(const DisplayLookupKey& rhs) const { Bool EGLContext::DisplayLookupKey::operator==(const DisplayLookupKey& rhs) const {
@@ -99,30 +149,31 @@ namespace MobileGL {
.SwapInterval = 1, .SwapInterval = 1,
}; };
const auto config = CreateDefaultConfig(display); displayObject.Configs.push_back(CreateDefaultConfig(display, 1, 0));
displayObject.Configs.push_back(config); displayObject.Configs.push_back(CreateDefaultConfig(display, 2, 8));
m_displays[display] = displayObject; m_displays[display] = displayObject;
m_displayLookup[key] = display; m_displayLookup[key] = display;
return display; return display;
} }
EGLContext::EGLConfigHandle EGLContext::CreateDefaultConfig(EGLDisplayHandle display) { EGLContext::EGLConfigHandle EGLContext::CreateDefaultConfig(EGLDisplayHandle display, EGLint configId,
EGLint stencilSize) {
const auto config = EncodeHandle<EGLConfigHandle>(m_nextConfigHandle++); const auto config = EncodeHandle<EGLConfigHandle>(m_nextConfigHandle++);
ConfigObject cfg = { ConfigObject cfg = {
.Display = display, .Display = display,
.ConfigId = 1, .ConfigId = configId,
.RedSize = 8, .RedSize = 8,
.GreenSize = 8, .GreenSize = 8,
.BlueSize = 8, .BlueSize = 8,
.AlphaSize = 8, .AlphaSize = 8,
.DepthSize = 24, .DepthSize = 24,
.StencilSize = 8, .StencilSize = stencilSize,
.SurfaceType = EGL_WINDOW_BIT | EGL_PBUFFER_BIT | EGL_PIXMAP_BIT, .SurfaceType = EGL_WINDOW_BIT | EGL_PBUFFER_BIT | EGL_PIXMAP_BIT,
.RenderableType = EGL_OPENGL_BIT | EGL_OPENGL_ES2_BIT | EGL_OPENGL_ES3_BIT, .RenderableType = EGL_OPENGL_BIT | EGL_OPENGL_ES2_BIT | EGL_OPENGL_ES3_BIT,
.MinSwapInterval = 0, .MinSwapInterval = 0,
.MaxSwapInterval = 4, .MaxSwapInterval = 4,
.NativeVisualId = 0, .NativeVisualId = QueryDefaultX11VisualId(),
}; };
#if defined(ANDROID) || defined(__ANDROID__) #if defined(ANDROID) || defined(__ANDROID__)
cfg.NativeVisualId = AHARDWAREBUFFER_FORMAT_R8G8B8A8_UNORM; cfg.NativeVisualId = AHARDWAREBUFFER_FORMAT_R8G8B8A8_UNORM;
@@ -294,7 +345,6 @@ namespace MobileGL {
Bool EGLContext::ChooseConfig(EGLDisplayHandle display, const EGLint* attribList, EGLConfigHandle* configs, Bool EGLContext::ChooseConfig(EGLDisplayHandle display, const EGLint* attribList, EGLConfigHandle* configs,
EGLint configSize, EGLint* numConfig) { EGLint configSize, EGLint* numConfig) {
const std::lock_guard<std::recursive_mutex> lock(m_mutex); const std::lock_guard<std::recursive_mutex> lock(m_mutex);
(void)attribList;
auto* displayObject = TryGetDisplay(display); auto* displayObject = TryGetDisplay(display);
if (!displayObject) { if (!displayObject) {
SetError(EGL_BAD_DISPLAY); SetError(EGL_BAD_DISPLAY);
@@ -309,14 +359,84 @@ namespace MobileGL {
return false; return false;
} }
*numConfig = static_cast<EGLint>(displayObject->Configs.size()); Vector<EGLConfigHandle> matchedConfigs;
for (const auto config : displayObject->Configs) {
const auto* cfg = TryGetConfig(config);
if (!cfg) {
continue;
}
Bool matches = true;
if (attribList) {
for (SizeT i = 0; attribList[i] != EGL_NONE; i += 2) {
const EGLint attr = attribList[i];
const EGLint requested = attribList[i + 1];
if (requested == EGL_DONT_CARE) {
continue;
}
switch (attr) {
case EGL_CONFIG_ID:
matches = cfg->ConfigId == requested;
break;
case EGL_RED_SIZE:
matches = cfg->RedSize >= requested;
break;
case EGL_GREEN_SIZE:
matches = cfg->GreenSize >= requested;
break;
case EGL_BLUE_SIZE:
matches = cfg->BlueSize >= requested;
break;
case EGL_ALPHA_SIZE:
matches = cfg->AlphaSize >= requested;
break;
case EGL_BUFFER_SIZE:
matches = (cfg->RedSize + cfg->GreenSize + cfg->BlueSize + cfg->AlphaSize) >= requested;
break;
case EGL_DEPTH_SIZE:
matches = cfg->DepthSize >= requested;
break;
case EGL_STENCIL_SIZE:
matches = cfg->StencilSize >= requested;
break;
case EGL_SURFACE_TYPE:
matches = (cfg->SurfaceType & requested) == requested;
break;
case EGL_RENDERABLE_TYPE:
case EGL_CONFORMANT:
matches = (cfg->RenderableType & requested) == requested;
break;
case EGL_SAMPLE_BUFFERS:
case EGL_SAMPLES:
matches = requested == 0;
break;
case EGL_NATIVE_VISUAL_ID:
matches = cfg->NativeVisualId == requested;
break;
default:
break;
}
if (!matches) {
break;
}
}
}
if (matches) {
matchedConfigs.push_back(config);
}
}
*numConfig = static_cast<EGLint>(matchedConfigs.size());
if (!configs || configSize <= 0) { if (!configs || configSize <= 0) {
return true; return true;
} }
const SizeT copyCount = std::min(static_cast<SizeT>(configSize), displayObject->Configs.size()); const SizeT copyCount = std::min(static_cast<SizeT>(configSize), matchedConfigs.size());
for (SizeT i = 0; i < copyCount; ++i) { for (SizeT i = 0; i < copyCount; ++i) {
configs[i] = displayObject->Configs[i]; configs[i] = matchedConfigs[i];
} }
return true; return true;
} }
@@ -356,9 +476,38 @@ namespace MobileGL {
} }
switch (attribute) { switch (attribute) {
case EGL_BUFFER_SIZE:
*value = cfg->RedSize + cfg->GreenSize + cfg->BlueSize + cfg->AlphaSize;
return true;
case EGL_ALPHA_MASK_SIZE:
*value = 0;
return true;
case EGL_BIND_TO_TEXTURE_RGB:
case EGL_BIND_TO_TEXTURE_RGBA:
*value = EGL_FALSE;
return true;
case EGL_COLOR_BUFFER_TYPE:
*value = EGL_RGB_BUFFER;
return true;
case EGL_CONFIG_CAVEAT:
*value = EGL_NONE;
return true;
case EGL_CONFIG_ID: case EGL_CONFIG_ID:
*value = cfg->ConfigId; *value = cfg->ConfigId;
return true; return true;
case EGL_LEVEL:
*value = 0;
return true;
case EGL_LUMINANCE_SIZE:
*value = 0;
return true;
case EGL_MAX_PBUFFER_WIDTH:
case EGL_MAX_PBUFFER_HEIGHT:
*value = DEFAULT_MAX_PBUFFER_SIZE;
return true;
case EGL_MAX_PBUFFER_PIXELS:
*value = DEFAULT_MAX_PBUFFER_SIZE * DEFAULT_MAX_PBUFFER_SIZE;
return true;
case EGL_RED_SIZE: case EGL_RED_SIZE:
*value = cfg->RedSize; *value = cfg->RedSize;
return true; return true;
@@ -390,9 +539,27 @@ namespace MobileGL {
case EGL_MAX_SWAP_INTERVAL: case EGL_MAX_SWAP_INTERVAL:
*value = cfg->MaxSwapInterval; *value = cfg->MaxSwapInterval;
return true; return true;
case EGL_NATIVE_RENDERABLE:
*value = EGL_TRUE;
return true;
case EGL_NATIVE_VISUAL_ID: case EGL_NATIVE_VISUAL_ID:
*value = cfg->NativeVisualId; *value = cfg->NativeVisualId;
return true; return true;
case EGL_NATIVE_VISUAL_TYPE:
*value = cfg->NativeVisualId;
return true;
case EGL_SAMPLE_BUFFERS:
case EGL_SAMPLES:
*value = 0;
return true;
case EGL_TRANSPARENT_TYPE:
*value = EGL_NONE;
return true;
case EGL_TRANSPARENT_RED_VALUE:
case EGL_TRANSPARENT_GREEN_VALUE:
case EGL_TRANSPARENT_BLUE_VALUE:
*value = 0;
return true;
default: default:
const_cast<EGLContext*>(this)->SetError(EGL_BAD_ATTRIBUTE); const_cast<EGLContext*>(this)->SetError(EGL_BAD_ATTRIBUTE);
return false; return false;
+1 -1
View File
@@ -213,7 +213,7 @@ namespace MobileGL {
static std::thread::id CurrentThreadKey(); static std::thread::id CurrentThreadKey();
EGLDisplayHandle GetOrCreateDisplay(Uint64 nativeDisplayKey, EGLenum platform); EGLDisplayHandle GetOrCreateDisplay(Uint64 nativeDisplayKey, EGLenum platform);
EGLConfigHandle CreateDefaultConfig(EGLDisplayHandle display); EGLConfigHandle CreateDefaultConfig(EGLDisplayHandle display, EGLint configId, EGLint stencilSize);
DisplayObject* TryGetDisplay(EGLDisplayHandle display); DisplayObject* TryGetDisplay(EGLDisplayHandle display);
const DisplayObject* TryGetDisplay(EGLDisplayHandle display) const; const DisplayObject* TryGetDisplay(EGLDisplayHandle display) const;