Files
MobileGL/MobileGL/Defines.h
T
gold 0dad3fcaa1 [Feature] (EGL): MobileGL serves EGL through libglvnd
On a system with libglvnd the libEGL.so.1 an application links is a dispatcher, not an
implementation, and the supported way to be the implementation it talks to is to be a vendor
library it loads and routes to.  On this machine it is also the ONLY way that reaches a caller which
does not link EGL directly: kwin goes through libepoxy, which dlopen()s libEGL.so.1 and dlsyms its
entry points at startup, so a library injected with LD_PRELOAD is invisible to it however loudly it
is named - measured, with the client in kwin's maps and not one call into it.

So this is the vendor half of that ABI: __egl_Main answers glvnd with the entry points by name, the
platforms this implementation serves, and the device it is associated with - the render node of the
machine, because that is what lets a compositor match its own node to the display it is about to
draw into, and because glvnd drops a vendor that does not answer at all.

Two details are the difference between a vendor that is loaded and a vendor that is used.  glvnd
requires setDispatchIndex to exist even when a vendor has nothing to record, which this one has -
its entry points are the implementation, they never re-enter glvnd.  And a vendor must hand over ITS
OWN entry points: with default visibility a reference inside this library resolves against the whole
process, where another libEGL that loaded first wins.  That is what -Bsymbolic-functions is for;
declaring the entry points protected says the same thing but does not compile against the platform
headers, which declare them default.
2026-10-01 12:22:55 -04:00

121 lines
5.6 KiB
C++

// MobileGL - MobileGL/Defines.h
// Copyright (c) 2025-2026 MobileGL-Dev
// Licensed under the GNU Lesser General Public License v3.0:
// https://www.gnu.org/licenses/gpl-3.0.txt
// https://www.gnu.org/licenses/lgpl-3.0.txt
// SPDX-License-Identifier: LGPL-3.0-only
// End of Source File Header
#pragma once
// ============== Platform-specific definitions and macros ============== //
// No __ANDROID_API__ pin here on purpose. The effective API level is owned by
// the build system (gradle minSdk 26 -> -DANDROID_PLATFORM=android-26, enforced
// by the configure-time guard in CMakeLists.txt), not by a macro.
//
// History: this used to `#define __ANDROID_API__ 26` to *raise* the level back
// when the build configured something lower, so that pthread_getname_np (which
// bionic guards with __INTRODUCED_IN(26)) would be declared. Once a later
// change added an `#undef` in front of it, the same line started *lowering* the
// level whenever the build configured higher than 26 - and that is an
// include-order split-brain, not a compatibility knob: a TU that includes any
// libc++ header before Includes.h latches libc++'s feature macros at the
// configure-time level, and only the bionic headers pulled in afterwards see
// the lowered value. The two halves then disagree (e.g. libc++ believes
// pthread_cond_clockwait exists while bionic has since hidden its declaration).
#ifdef _WIN32
#ifndef NOMINMAX
#define NOMINMAX 1 // prevent Windows.h from defining min and max macros
#endif
#endif
// ================== MobileGL definitions and macros =================== //
#ifdef _WIN32
#define MOBILEGL_EXPORT extern "C" __declspec(dllexport)
#else
// Default visibility, which is what the platform's own GL and EGL headers declare their entry
// points with. The one place where that is not enough - a vendor library handing glvnd its own
// entry points, where a reference resolving against the process instead of this library would be a
// call back into the dispatcher - is answered at link time with -Bsymbolic-functions rather than
// here, because a second visibility on the same declaration does not compile.
#define MOBILEGL_EXPORT extern "C" __attribute__((visibility("default")))
#endif
#define MOBILEGL_API MOBILEGL_EXPORT
#define MOBILEGL_GLX_API MOBILEGL_API
#define MOBILEGL_GL_API MOBILEGL_API
#define MOBILEGL_EGL_API MOBILEGL_API
#define MOBILEGL_CGL_API MOBILEGL_API
#define MOBILEGL_NSOPENGL_API MOBILEGL_API
#define MOBILEGL_WGL_API MOBILEGL_API
// ====================== MobileGL configurations ======================= //
// The numeric log levels live here, not only in Log.h: MOBILEGL_ASSERT below compares
// MOBILEGL_LOG_ACTIVE_LEVEL against MOBILEGL_LOG_LEVEL_DEBUG, and in a translation unit
// that includes Defines.h without Log.h both tokens would silently evaluate to 0 in the
// preprocessor conditional - enabling the assert in exactly the INFO-level builds it is
// documented to be compiled out of. Log.h redefines them identically, which is legal.
//
// Severity order, ascending: DEBUG < INFO < WARN < ERROR < FATAL. MOBILEGL_LOG_ACTIVE_LEVEL
// names the lowest severity compiled in, so the production default INFO keeps I/W/E/F and
// drops only D. Any edit here must be mirrored in Log.h.
#ifndef MOBILEGL_LOG_LEVEL_DEBUG
#define MOBILEGL_LOG_LEVEL_DEBUG 0
#define MOBILEGL_LOG_LEVEL_INFO 1
#define MOBILEGL_LOG_LEVEL_WARN 2
#define MOBILEGL_LOG_LEVEL_ERROR 3
#define MOBILEGL_LOG_LEVEL_FATAL 4
#endif
#ifndef MOBILEGL_LOG_ACTIVE_LEVEL
#define MOBILEGL_LOG_ACTIVE_LEVEL MOBILEGL_LOG_LEVEL_INFO
#endif
#define MOBILEGL_LOG_ENABLE_CONSOLE 0
#define MOBILEGL_LOG_ENABLE_FILE 1
#define MOBILEGL_LOG_ENABLE_ANDROID 1
#define MOBILEGL_ENABLE_SCOPE_MARKER 0
// Require C++23
// Clang/Android NDK still doesn't have support for that :(
#if __cplusplus >= 202302L && !__ANDROID__
#define MOBILEGL_LOG_ENABLE_STACKTRACE 0
#endif
#ifdef __ANDROID__
#define MOBILEGL_LOG_FILE_PATH "/sdcard/MG/latest.log"
#else
#define MOBILEGL_LOG_FILE_PATH ""
#endif
#if defined _MSC_VER or defined __MINGW32__ or defined __MINGW64__
#define TRAP assert(false)
#elif __clang__
#define TRAP __builtin_debugtrap()
#else
#include <signal.h>
#define TRAP raise(SIGTRAP)
#endif
// =============================== Utils ================================ //
// Asserts are live in exactly the builds where MGLOG_D is live, i.e. DEBUG builds only;
// an INFO build (the production default) compiles them out. DEBUG is the lowest severity
// in the ordering above, so "ACTIVE <= DEBUG" is true only for ACTIVE == DEBUG - the same
// gate MGLOG_D uses in Log.h. That equivalence is what makes this gate survive the
// 2026-08-13 renumbering unchanged; the contract is and stays
// "INFO builds: asserts OFF; DEBUG builds: asserts ON".
#if MOBILEGL_LOG_ACTIVE_LEVEL <= MOBILEGL_LOG_LEVEL_DEBUG
#define MOBILEGL_ASSERT(condition, ...) \
do { \
if (!(condition)) { \
MGLOG_F("Assertion failed" __VA_OPT__(": ") __VA_ARGS__); \
MGLOG_F(" at %s:%d (%s)", __FILE__, __LINE__, __func__); \
TRAP; \
} \
} while (0)
#else
#define MOBILEGL_ASSERT(condition, ...)
#endif