mirror of
https://github.com/MobileGL-Dev/MobileGL
synced 2026-09-08 04:08:32 +09:00
[Feat] (EGL): support Linux X11 + EGL
This commit is contained in:
@@ -33,6 +33,7 @@
|
||||
#include <vector>
|
||||
#include <cassert>
|
||||
#include <climits>
|
||||
#include <cstdlib>
|
||||
#include <cstdarg>
|
||||
#include <cstring>
|
||||
#include <numeric>
|
||||
|
||||
@@ -53,7 +53,8 @@ namespace MobileGL::MG_Backend {
|
||||
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;
|
||||
}
|
||||
|
||||
@@ -63,7 +64,35 @@ namespace MobileGL::MG_Backend {
|
||||
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_backendCapabilitiesInitialized = false;
|
||||
return true;
|
||||
@@ -81,8 +110,8 @@ namespace MobileGL::MG_Backend {
|
||||
MGLOG_E("MakeEGLCurrent failed: EGL display mismatch or not initialized");
|
||||
return false;
|
||||
}
|
||||
if (!m_eglWindowSurfaceInitialized) {
|
||||
MGLOG_E("MakeEGLCurrent failed: EGL window surface is not initialized");
|
||||
if (!m_eglSurfaceInitialized) {
|
||||
MGLOG_E("MakeEGLCurrent failed: EGL surface is not initialized");
|
||||
return false;
|
||||
}
|
||||
if (draw == EGL_NO_SURFACE || read == EGL_NO_SURFACE || ctx == EGL_NO_CONTEXT) {
|
||||
@@ -104,8 +133,9 @@ namespace MobileGL::MG_Backend {
|
||||
|
||||
void BackendObject::ResetEGLRuntimeState() {
|
||||
const std::lock_guard<std::recursive_mutex> lock(m_eglStateMutex);
|
||||
m_eglWindowSurfaceInitialized = false;
|
||||
m_eglSurfaceInitialized = false;
|
||||
m_backendCapabilitiesInitialized = false;
|
||||
m_eglSurfaceKind = SurfaceKind::None;
|
||||
m_eglCurrentThreads.clear();
|
||||
}
|
||||
|
||||
@@ -119,7 +149,7 @@ namespace MobileGL::MG_Backend {
|
||||
MGLOG_E("SwapEGLBuffers failed: no current context attached");
|
||||
return false;
|
||||
}
|
||||
if (!m_eglWindowSurfaceInitialized || draw == EGL_NO_SURFACE) {
|
||||
if (!m_eglSurfaceInitialized || draw == EGL_NO_SURFACE) {
|
||||
MGLOG_E("SwapEGLBuffers failed: invalid draw surface");
|
||||
return false;
|
||||
}
|
||||
@@ -138,4 +168,10 @@ namespace MobileGL::MG_Backend {
|
||||
const std::lock_guard<std::recursive_mutex> lock(m_eglStateMutex);
|
||||
m_windowHandle = handle;
|
||||
}
|
||||
|
||||
Bool BackendObject::InitPbufferSurface(EGLint width, EGLint height) {
|
||||
(void)width;
|
||||
(void)height;
|
||||
return false;
|
||||
}
|
||||
} // namespace MobileGL::MG_Backend
|
||||
|
||||
@@ -94,6 +94,7 @@ namespace MobileGL {
|
||||
|
||||
enum class WindowBackend {
|
||||
Android,
|
||||
X11,
|
||||
// TODO: X11, Wayland, Windows, macOS, etc.
|
||||
WindowBackendCount,
|
||||
Unknown = -1
|
||||
@@ -114,6 +115,7 @@ namespace MobileGL {
|
||||
|
||||
virtual Bool InitializeEGLDisplay(EGLDisplay dpy, EGLint* major, EGLint* minor);
|
||||
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 SwapEGLBuffers(EGLDisplay dpy, EGLSurface draw);
|
||||
|
||||
@@ -126,14 +128,22 @@ namespace MobileGL {
|
||||
virtual BackendType GetBackendType() const = 0;
|
||||
|
||||
protected:
|
||||
enum class SurfaceKind {
|
||||
None,
|
||||
Window,
|
||||
Pbuffer
|
||||
};
|
||||
|
||||
void ResetEGLRuntimeState();
|
||||
virtual Bool InitPbufferSurface(EGLint width, EGLint height);
|
||||
|
||||
mutable std::recursive_mutex m_eglStateMutex;
|
||||
WindowHandle m_windowHandle;
|
||||
EGLDisplay m_eglDisplay = EGL_NO_DISPLAY;
|
||||
Bool m_eglDisplayInitialized = false;
|
||||
Bool m_eglWindowSurfaceInitialized = false;
|
||||
Bool m_eglSurfaceInitialized = false;
|
||||
Bool m_backendCapabilitiesInitialized = false;
|
||||
SurfaceKind m_eglSurfaceKind = SurfaceKind::None;
|
||||
UnorderedMap<std::thread::id, Bool> m_eglCurrentThreads;
|
||||
};
|
||||
} // namespace MG_Backend
|
||||
|
||||
@@ -78,18 +78,18 @@ namespace MobileGL::MG_Backend::DirectGLES {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (handle.Backend != WindowBackend::Android || !handle.Handle) {
|
||||
MGLOG_E("DirectGLES backend only supports Android native windows");
|
||||
if ((handle.Backend != WindowBackend::Android && handle.Backend != WindowBackend::X11) || !handle.Handle) {
|
||||
MGLOG_E("DirectGLES backend only supports Android and X11 native windows");
|
||||
return false;
|
||||
}
|
||||
|
||||
const Bool sameHandle =
|
||||
m_eglWindowSurfaceInitialized && m_windowHandle.Backend == handle.Backend && m_windowHandle.Handle == handle.Handle;
|
||||
const Bool sameHandle = m_eglSurfaceInitialized && m_eglSurfaceKind == SurfaceKind::Window &&
|
||||
m_windowHandle.Backend == handle.Backend && m_windowHandle.Handle == handle.Handle;
|
||||
if (sameHandle) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (m_eglWindowSurfaceInitialized) {
|
||||
if (m_eglSurfaceInitialized) {
|
||||
DestroyEGLContext();
|
||||
ResetEGLRuntimeState();
|
||||
}
|
||||
@@ -97,6 +97,10 @@ namespace MobileGL::MG_Backend::DirectGLES {
|
||||
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) {
|
||||
if (IsReleaseCurrentRequest(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
|
||||
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_program_interface_query},
|
||||
E_GL_ARB_program_interface_query, E_GL_ARB_framebuffer_object,
|
||||
E_GL_EXT_framebuffer_object},
|
||||
.IsCompatibilityProfile = false // Is Compatibility Profile
|
||||
},
|
||||
.StaticBackendCapability = {.AllowVSOnlyPrograms = false} // Backend Capability
|
||||
|
||||
@@ -35,6 +35,7 @@ namespace MobileGL::MG_Backend::DirectGLES {
|
||||
|
||||
private:
|
||||
void UpdateDynamicBackendParameters();
|
||||
Bool InitPbufferSurface(EGLint width, EGLint height) override;
|
||||
|
||||
Bool m_initialized = false;
|
||||
MG_External::EGLFunctionsTable m_EGLFunctions;
|
||||
|
||||
@@ -134,7 +134,7 @@ namespace MobileGL::MG_Backend::DirectGLES {
|
||||
const auto start = std::min(range.start, obj->GetSize());
|
||||
const auto end = std::min(range.end, obj->GetSize());
|
||||
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);
|
||||
}
|
||||
|
||||
void GetProgramResourceName(GLuint program, GLenum programInterface, GLuint index, GLsizei bufSize,
|
||||
GLsizei* length, GLchar* name) {
|
||||
void GetProgramResourceName(GLuint program, GLenum programInterface, GLuint index, GLsizei bufSize, GLsizei* length,
|
||||
GLchar* name) {
|
||||
GLuint backendProgramId = GetBackendProgramId(program);
|
||||
if (!backendProgramId) return;
|
||||
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) {
|
||||
GLuint backendProgramId = GetBackendProgramId(program);
|
||||
if (!backendProgramId) return;
|
||||
g_GLESFuncs.glGetProgramResourceiv(backendProgramId, programInterface, index, propCount, props, bufSize,
|
||||
length, params);
|
||||
g_GLESFuncs.glGetProgramResourceiv(backendProgramId, programInterface, index, propCount, props, bufSize, length,
|
||||
params);
|
||||
}
|
||||
|
||||
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 EGLSurface g_Surface = EGL_NO_SURFACE;
|
||||
static EGLConfig g_Config = nullptr;
|
||||
Bool InitWindowSurface(NativeWindowType window) {
|
||||
// TODO: handle custom EGL paramters
|
||||
if (!window) return false;
|
||||
|
||||
static 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
|
||||
}
|
||||
|
||||
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);
|
||||
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;
|
||||
g_EGLFuncs.eglBindAPI(EGL_OPENGL_ES_API);
|
||||
|
||||
const EGLint configAttribs[] = {EGL_SURFACE_TYPE,
|
||||
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;
|
||||
if (!ChooseConfigForSurface(surfaceBit, g_Config)) return false;
|
||||
|
||||
const EGLint contextAttribs[] = {EGL_CONTEXT_CLIENT_VERSION, 3, EGL_NONE};
|
||||
|
||||
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);
|
||||
if (g_Surface == EGL_NO_SURFACE) return false;
|
||||
@@ -1905,6 +1999,21 @@ namespace MobileGL::MG_Backend::DirectGLES {
|
||||
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() {
|
||||
if (g_Display != EGL_NO_DISPLAY && g_Surface != EGL_NO_SURFACE) {
|
||||
g_EGLFuncs.eglSwapBuffers(g_Display, g_Surface);
|
||||
|
||||
@@ -67,14 +67,15 @@ namespace MobileGL::MG_Backend::DirectGLES {
|
||||
void GetProgramiv(GLuint program, GLenum pname, GLint* params);
|
||||
void GetProgramInterfaceiv(GLuint program, GLenum programInterface, GLenum pname, GLint* params);
|
||||
GLuint GetProgramResourceIndex(GLuint program, GLenum programInterface, const GLchar* name);
|
||||
void GetProgramResourceName(GLuint program, GLenum programInterface, GLuint index, GLsizei bufSize,
|
||||
GLsizei* length, GLchar* name);
|
||||
void GetProgramResourceName(GLuint program, GLenum programInterface, GLuint index, GLsizei bufSize, GLsizei* length,
|
||||
GLchar* name);
|
||||
void GetProgramResourceiv(GLuint program, GLenum programInterface, GLuint index, GLsizei propCount,
|
||||
const GLenum* props, GLsizei bufSize, GLsizei* length, GLint* params);
|
||||
GLint GetProgramResourceLocation(GLuint program, GLenum programInterface, const GLchar* name);
|
||||
GLint GetProgramResourceLocationIndex(GLuint program, GLenum programInterface, const GLchar* name);
|
||||
void ShaderStorageBlockBinding(GLuint program, GLuint storageBlockIndex, GLuint storageBlockBinding);
|
||||
Bool InitWindowSurface(NativeWindowType window);
|
||||
Bool InitPbufferSurface(EGLint width, EGLint height);
|
||||
void Present();
|
||||
void SetEGLFuncsTable(const MG_External::EGLFunctionsTable& eglFuncs);
|
||||
void SetGLESFuncsTable(const MG_External::GLESFunctionsTable& glesFuncs);
|
||||
|
||||
@@ -71,13 +71,13 @@ namespace MobileGL::MG_Backend::DirectVulkan {
|
||||
return false;
|
||||
}
|
||||
|
||||
const Bool sameHandle =
|
||||
m_eglWindowSurfaceInitialized && m_windowHandle.Backend == handle.Backend && m_windowHandle.Handle == handle.Handle;
|
||||
const Bool sameHandle = m_eglSurfaceInitialized && m_eglSurfaceKind == SurfaceKind::Window &&
|
||||
m_windowHandle.Backend == handle.Backend && m_windowHandle.Handle == handle.Handle;
|
||||
if (sameHandle) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (m_eglWindowSurfaceInitialized || pVulkanRenderer) {
|
||||
if (m_eglSurfaceInitialized || pVulkanRenderer) {
|
||||
pVulkanRenderer.reset();
|
||||
ResetEGLRuntimeState();
|
||||
}
|
||||
@@ -116,10 +116,8 @@ namespace MobileGL::MG_Backend::DirectVulkan {
|
||||
.TargetGLVersion = {3, 3, 0}, // Target OpenGL Version
|
||||
.TargetGLSLVersion = {4, 6, 0}, // Target Shading Language Version
|
||||
.Extensions = {V_OpenGL30, V_OpenGL31, V_OpenGL32, // OpenGL Extensions
|
||||
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,
|
||||
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_program_interface_query},
|
||||
.IsCompatibilityProfile = false // Is Compatibility Profile
|
||||
},
|
||||
|
||||
@@ -34,11 +34,25 @@ namespace MobileGL::MG_Impl::EGLImpl {
|
||||
MG_Backend::WindowBackend DetectWindowBackend() {
|
||||
#if defined(ANDROID) || defined(__ANDROID__)
|
||||
return MG_Backend::WindowBackend::Android;
|
||||
#elif defined(__linux__)
|
||||
return MG_Backend::WindowBackend::X11;
|
||||
#else
|
||||
return MG_Backend::WindowBackend::Unknown;
|
||||
#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>
|
||||
Bool IsNullNativeHandle(NativeType nativeHandle) {
|
||||
if constexpr (std::is_pointer_v<NativeType>) {
|
||||
@@ -330,7 +344,24 @@ namespace MobileGL::MG_Impl::EGLImpl {
|
||||
if (!state) {
|
||||
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) {
|
||||
|
||||
@@ -17,42 +17,40 @@
|
||||
#include "../Framebuffer/GL_Framebuffer.h"
|
||||
#include "../VertexArray/GL_VertexArray.h"
|
||||
|
||||
#define DECLARE_GL_FUNCTION_STUB_HEAD(type,name,...) \
|
||||
MOBILEGL_GL_API type gl##name(__VA_ARGS__) {
|
||||
#define DECLARE_GL_FUNCTION_STUB_HEAD(type, name, ...) MOBILEGL_GL_API type gl##name(__VA_ARGS__) {
|
||||
|
||||
#define DECLARE_GL_FUNCTION_STUB_END(type,name,...) \
|
||||
MGLOG_W("Stub function: %s(...)", __FUNCTION__); \
|
||||
return (type)1; \
|
||||
}
|
||||
#define DECLARE_GL_FUNCTION_STUB_END(type, name, ...) \
|
||||
MGLOG_W("Stub function: %s(...)", __FUNCTION__); \
|
||||
return (type)1; \
|
||||
}
|
||||
|
||||
#define DECLARE_GL_FUNCTION_STUB_END_NO_RETURN(type,name,...) \
|
||||
MGLOG_W("Stub function: %s(...)", __FUNCTION__); \
|
||||
}
|
||||
#define DECLARE_GL_FUNCTION_STUB_END_NO_RETURN(type, name, ...) \
|
||||
MGLOG_W("Stub function: %s(...)", __FUNCTION__); \
|
||||
}
|
||||
|
||||
#define DECLARE_GL_FUNCTION_HEAD(type,name,...) \
|
||||
MOBILEGL_GL_API type gl##name(__VA_ARGS__) {
|
||||
#define DECLARE_GL_FUNCTION_HEAD(type, name, ...) MOBILEGL_GL_API type gl##name(__VA_ARGS__) {
|
||||
|
||||
#ifdef TRACY_ENABLE
|
||||
#define DECLARE_GL_FUNCTION_END(type,name,...) \
|
||||
ZoneScopedC(TRACY_ZONECOLOR_ENTRY); \
|
||||
MGLOG_D("Implementing function: %s(...)", __FUNCTION__); \
|
||||
return MobileGL::MG_Impl::GLImpl::name(__VA_ARGS__); \
|
||||
#define DECLARE_GL_FUNCTION_END(type, name, ...) \
|
||||
ZoneScopedC(TRACY_ZONECOLOR_ENTRY); \
|
||||
MGLOG_D("Implementing function: %s(...)", __FUNCTION__); \
|
||||
return MobileGL::MG_Impl::GLImpl::name(__VA_ARGS__); \
|
||||
}
|
||||
|
||||
#define DECLARE_GL_FUNCTION_END_NO_RETURN(type,name,...) \
|
||||
ZoneScopedC(TRACY_ZONECOLOR_ENTRY); \
|
||||
MGLOG_D("Implementing function: %s(...)", __FUNCTION__); \
|
||||
MobileGL::MG_Impl::GLImpl::name(__VA_ARGS__); \
|
||||
#define DECLARE_GL_FUNCTION_END_NO_RETURN(type, name, ...) \
|
||||
ZoneScopedC(TRACY_ZONECOLOR_ENTRY); \
|
||||
MGLOG_D("Implementing function: %s(...)", __FUNCTION__); \
|
||||
MobileGL::MG_Impl::GLImpl::name(__VA_ARGS__); \
|
||||
}
|
||||
#else
|
||||
#define DECLARE_GL_FUNCTION_END(type,name,...) \
|
||||
MGLOG_D("Implementing function: %s(...)", __FUNCTION__); \
|
||||
return MobileGL::MG_Impl::GLImpl::name(__VA_ARGS__); \
|
||||
#define DECLARE_GL_FUNCTION_END(type, name, ...) \
|
||||
MGLOG_D("Implementing function: %s(...)", __FUNCTION__); \
|
||||
return MobileGL::MG_Impl::GLImpl::name(__VA_ARGS__); \
|
||||
}
|
||||
|
||||
#define DECLARE_GL_FUNCTION_END_NO_RETURN(type,name,...) \
|
||||
MGLOG_D("Implementing function: %s(...)", __FUNCTION__); \
|
||||
MobileGL::MG_Impl::GLImpl::name(__VA_ARGS__); \
|
||||
#define DECLARE_GL_FUNCTION_END_NO_RETURN(type, name, ...) \
|
||||
MGLOG_D("Implementing function: %s(...)", __FUNCTION__); \
|
||||
MobileGL::MG_Impl::GLImpl::name(__VA_ARGS__); \
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -2880,6 +2878,69 @@ MOBILEGL_GL_API void glGetFramebufferParameterivEXT(GLenum target, GLenum pname,
|
||||
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) {
|
||||
return glGetGraphicsResetStatus();
|
||||
}
|
||||
@@ -3025,48 +3086,48 @@ MOBILEGL_GL_API void glProgramUniform4uivEXT(GLuint program, GLint location, GLs
|
||||
glProgramUniform4uiv(program, location, count, value);
|
||||
}
|
||||
|
||||
MOBILEGL_GL_API void glProgramUniformMatrix2fvEXT(GLuint program, GLint location, GLsizei count,
|
||||
GLboolean transpose, const GLfloat* value) {
|
||||
MOBILEGL_GL_API void glProgramUniformMatrix2fvEXT(GLuint program, GLint location, GLsizei count, GLboolean transpose,
|
||||
const GLfloat* value) {
|
||||
glProgramUniformMatrix2fv(program, location, count, transpose, value);
|
||||
}
|
||||
|
||||
MOBILEGL_GL_API void glProgramUniformMatrix2x3fvEXT(GLuint program, GLint location, GLsizei count,
|
||||
GLboolean transpose, const GLfloat* value) {
|
||||
MOBILEGL_GL_API void glProgramUniformMatrix2x3fvEXT(GLuint program, GLint location, GLsizei count, GLboolean transpose,
|
||||
const GLfloat* value) {
|
||||
glProgramUniformMatrix2x3fv(program, location, count, transpose, value);
|
||||
}
|
||||
|
||||
MOBILEGL_GL_API void glProgramUniformMatrix2x4fvEXT(GLuint program, GLint location, GLsizei count,
|
||||
GLboolean transpose, const GLfloat* value) {
|
||||
MOBILEGL_GL_API void glProgramUniformMatrix2x4fvEXT(GLuint program, GLint location, GLsizei count, GLboolean transpose,
|
||||
const GLfloat* value) {
|
||||
glProgramUniformMatrix2x4fv(program, location, count, transpose, value);
|
||||
}
|
||||
|
||||
MOBILEGL_GL_API void glProgramUniformMatrix3fvEXT(GLuint program, GLint location, GLsizei count,
|
||||
GLboolean transpose, const GLfloat* value) {
|
||||
MOBILEGL_GL_API void glProgramUniformMatrix3fvEXT(GLuint program, GLint location, GLsizei count, GLboolean transpose,
|
||||
const GLfloat* value) {
|
||||
glProgramUniformMatrix3fv(program, location, count, transpose, value);
|
||||
}
|
||||
|
||||
MOBILEGL_GL_API void glProgramUniformMatrix3x2fvEXT(GLuint program, GLint location, GLsizei count,
|
||||
GLboolean transpose, const GLfloat* value) {
|
||||
MOBILEGL_GL_API void glProgramUniformMatrix3x2fvEXT(GLuint program, GLint location, GLsizei count, GLboolean transpose,
|
||||
const GLfloat* value) {
|
||||
glProgramUniformMatrix3x2fv(program, location, count, transpose, value);
|
||||
}
|
||||
|
||||
MOBILEGL_GL_API void glProgramUniformMatrix3x4fvEXT(GLuint program, GLint location, GLsizei count,
|
||||
GLboolean transpose, const GLfloat* value) {
|
||||
MOBILEGL_GL_API void glProgramUniformMatrix3x4fvEXT(GLuint program, GLint location, GLsizei count, GLboolean transpose,
|
||||
const GLfloat* value) {
|
||||
glProgramUniformMatrix3x4fv(program, location, count, transpose, value);
|
||||
}
|
||||
|
||||
MOBILEGL_GL_API void glProgramUniformMatrix4fvEXT(GLuint program, GLint location, GLsizei count,
|
||||
GLboolean transpose, const GLfloat* value) {
|
||||
MOBILEGL_GL_API void glProgramUniformMatrix4fvEXT(GLuint program, GLint location, GLsizei count, GLboolean transpose,
|
||||
const GLfloat* value) {
|
||||
glProgramUniformMatrix4fv(program, location, count, transpose, value);
|
||||
}
|
||||
|
||||
MOBILEGL_GL_API void glProgramUniformMatrix4x2fvEXT(GLuint program, GLint location, GLsizei count,
|
||||
GLboolean transpose, const GLfloat* value) {
|
||||
MOBILEGL_GL_API void glProgramUniformMatrix4x2fvEXT(GLuint program, GLint location, GLsizei count, GLboolean transpose,
|
||||
const GLfloat* value) {
|
||||
glProgramUniformMatrix4x2fv(program, location, count, transpose, value);
|
||||
}
|
||||
|
||||
MOBILEGL_GL_API void glProgramUniformMatrix4x3fvEXT(GLuint program, GLint location, GLsizei count,
|
||||
GLboolean transpose, const GLfloat* value) {
|
||||
MOBILEGL_GL_API void glProgramUniformMatrix4x3fvEXT(GLuint program, GLint location, GLsizei count, GLboolean transpose,
|
||||
const GLfloat* value) {
|
||||
glProgramUniformMatrix4x3fv(program, location, count, transpose, value);
|
||||
}
|
||||
|
||||
|
||||
@@ -14,6 +14,7 @@ namespace MobileGL {
|
||||
namespace {
|
||||
constexpr EGLint EGL_DISPLAY_MAJOR_VERSION = 1;
|
||||
constexpr EGLint EGL_DISPLAY_MINOR_VERSION = 5;
|
||||
constexpr EGLint DEFAULT_MAX_PBUFFER_SIZE = 16384;
|
||||
|
||||
template <typename AttrType>
|
||||
Optional<AttrType> ParseAttribValue(const AttrType* attribList, EGLint attrib) {
|
||||
@@ -27,6 +28,55 @@ namespace MobileGL {
|
||||
}
|
||||
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
|
||||
|
||||
Bool EGLContext::DisplayLookupKey::operator==(const DisplayLookupKey& rhs) const {
|
||||
@@ -99,30 +149,31 @@ namespace MobileGL {
|
||||
.SwapInterval = 1,
|
||||
};
|
||||
|
||||
const auto config = CreateDefaultConfig(display);
|
||||
displayObject.Configs.push_back(config);
|
||||
displayObject.Configs.push_back(CreateDefaultConfig(display, 1, 0));
|
||||
displayObject.Configs.push_back(CreateDefaultConfig(display, 2, 8));
|
||||
|
||||
m_displays[display] = displayObject;
|
||||
m_displayLookup[key] = 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++);
|
||||
ConfigObject cfg = {
|
||||
.Display = display,
|
||||
.ConfigId = 1,
|
||||
.ConfigId = configId,
|
||||
.RedSize = 8,
|
||||
.GreenSize = 8,
|
||||
.BlueSize = 8,
|
||||
.AlphaSize = 8,
|
||||
.DepthSize = 24,
|
||||
.StencilSize = 8,
|
||||
.StencilSize = stencilSize,
|
||||
.SurfaceType = EGL_WINDOW_BIT | EGL_PBUFFER_BIT | EGL_PIXMAP_BIT,
|
||||
.RenderableType = EGL_OPENGL_BIT | EGL_OPENGL_ES2_BIT | EGL_OPENGL_ES3_BIT,
|
||||
.MinSwapInterval = 0,
|
||||
.MaxSwapInterval = 4,
|
||||
.NativeVisualId = 0,
|
||||
.NativeVisualId = QueryDefaultX11VisualId(),
|
||||
};
|
||||
#if defined(ANDROID) || defined(__ANDROID__)
|
||||
cfg.NativeVisualId = AHARDWAREBUFFER_FORMAT_R8G8B8A8_UNORM;
|
||||
@@ -294,7 +345,6 @@ namespace MobileGL {
|
||||
Bool EGLContext::ChooseConfig(EGLDisplayHandle display, const EGLint* attribList, EGLConfigHandle* configs,
|
||||
EGLint configSize, EGLint* numConfig) {
|
||||
const std::lock_guard<std::recursive_mutex> lock(m_mutex);
|
||||
(void)attribList;
|
||||
auto* displayObject = TryGetDisplay(display);
|
||||
if (!displayObject) {
|
||||
SetError(EGL_BAD_DISPLAY);
|
||||
@@ -309,14 +359,84 @@ namespace MobileGL {
|
||||
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) {
|
||||
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) {
|
||||
configs[i] = displayObject->Configs[i];
|
||||
configs[i] = matchedConfigs[i];
|
||||
}
|
||||
return true;
|
||||
}
|
||||
@@ -356,9 +476,38 @@ namespace MobileGL {
|
||||
}
|
||||
|
||||
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:
|
||||
*value = cfg->ConfigId;
|
||||
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:
|
||||
*value = cfg->RedSize;
|
||||
return true;
|
||||
@@ -390,9 +539,27 @@ namespace MobileGL {
|
||||
case EGL_MAX_SWAP_INTERVAL:
|
||||
*value = cfg->MaxSwapInterval;
|
||||
return true;
|
||||
case EGL_NATIVE_RENDERABLE:
|
||||
*value = EGL_TRUE;
|
||||
return true;
|
||||
case EGL_NATIVE_VISUAL_ID:
|
||||
*value = cfg->NativeVisualId;
|
||||
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:
|
||||
const_cast<EGLContext*>(this)->SetError(EGL_BAD_ATTRIBUTE);
|
||||
return false;
|
||||
|
||||
@@ -213,7 +213,7 @@ namespace MobileGL {
|
||||
static std::thread::id CurrentThreadKey();
|
||||
|
||||
EGLDisplayHandle GetOrCreateDisplay(Uint64 nativeDisplayKey, EGLenum platform);
|
||||
EGLConfigHandle CreateDefaultConfig(EGLDisplayHandle display);
|
||||
EGLConfigHandle CreateDefaultConfig(EGLDisplayHandle display, EGLint configId, EGLint stencilSize);
|
||||
|
||||
DisplayObject* TryGetDisplay(EGLDisplayHandle display);
|
||||
const DisplayObject* TryGetDisplay(EGLDisplayHandle display) const;
|
||||
|
||||
Reference in New Issue
Block a user