X-Git-Url: https://git.libre-soc.org/?p=mesa.git;a=blobdiff_plain;f=src%2Fegl%2Fmain%2Feglglobals.c;h=8a8c03c924fd0f036f52901ce2ceee5fbdc8257c;hp=884cff0c36b8bb5bda3fbe21e6797635dfa3392d;hb=7d7d1da1ac4b02c92da1624d3eb16004268dabac;hpb=3a83adeb7c6340104e9417beefc086f7d33183bc diff --git a/src/egl/main/eglglobals.c b/src/egl/main/eglglobals.c index 884cff0c36b..8a8c03c924f 100644 --- a/src/egl/main/eglglobals.c +++ b/src/egl/main/eglglobals.c @@ -29,34 +29,68 @@ #include +#include +#include #include #include "c11/threads.h" #include "eglglobals.h" +#include "egldevice.h" #include "egldisplay.h" #include "egldriver.h" +#include "util/macros.h" + +#ifdef HAVE_MINCORE +#include +#include +#endif + static mtx_t _eglGlobalMutex = _MTX_INITIALIZER_NP; struct _egl_global _eglGlobal = { - &_eglGlobalMutex, /* Mutex */ - NULL, /* DisplayList */ - 2, /* NumAtExitCalls */ - { + .Mutex = &_eglGlobalMutex, + .DisplayList = NULL, + .DeviceList = &_eglSoftwareDevice, + .NumAtExitCalls = 3, + .AtExitCalls = { /* default AtExitCalls, called in reverse order */ - _eglUnloadDrivers, /* always called last */ - _eglFiniDisplay + _eglFiniDevice, /* always called last */ + _eglUnloadDrivers, + _eglFiniDisplay, }, - /* ClientExtensionsString */ + .ClientOnlyExtensionString = "EGL_EXT_client_extensions" + " EGL_EXT_device_base" + " EGL_EXT_device_enumeration" + " EGL_EXT_device_query" " EGL_EXT_platform_base" - " EGL_EXT_platform_x11" + " EGL_KHR_client_get_all_proc_addresses" + " EGL_KHR_debug", + + .PlatformExtensionString = +#ifdef HAVE_WAYLAND_PLATFORM " EGL_EXT_platform_wayland" +#endif +#ifdef HAVE_X11_PLATFORM + " EGL_EXT_platform_x11" +#endif +#ifdef HAVE_DRM_PLATFORM " EGL_MESA_platform_gbm" - " EGL_KHR_client_get_all_proc_addresses" +#endif +#ifdef HAVE_SURFACELESS_PLATFORM + " EGL_MESA_platform_surfaceless" +#endif + " EGL_EXT_platform_device" + "", + + .ClientExtensionString = NULL, + + .debugCallback = NULL, + .debugTypesEnabled = _EGL_DEBUG_BIT_CRITICAL | _EGL_DEBUG_BIT_ERROR, }; @@ -88,3 +122,73 @@ _eglAddAtExitCall(void (*func)(void)) mtx_unlock(_eglGlobal.Mutex); } } + +const char * +_eglGetClientExtensionString(void) +{ + const char *ret; + + mtx_lock(_eglGlobal.Mutex); + + if (_eglGlobal.ClientExtensionString == NULL) { + size_t clientLen = strlen(_eglGlobal.ClientOnlyExtensionString); + size_t platformLen = strlen(_eglGlobal.PlatformExtensionString); + + _eglGlobal.ClientExtensionString = (char *) malloc(clientLen + platformLen + 1); + if (_eglGlobal.ClientExtensionString != NULL) { + char *ptr = _eglGlobal.ClientExtensionString; + + memcpy(ptr, _eglGlobal.ClientOnlyExtensionString, clientLen); + ptr += clientLen; + + if (platformLen > 0) { + // Note that if PlatformExtensionString is not empty, then it will + // already have a leading space. + assert(_eglGlobal.PlatformExtensionString[0] == ' '); + memcpy(ptr, _eglGlobal.PlatformExtensionString, platformLen); + ptr += platformLen; + } + *ptr = '\0'; + } + } + ret = _eglGlobal.ClientExtensionString; + + mtx_unlock(_eglGlobal.Mutex); + return ret; +} + +EGLBoolean +_eglPointerIsDereferencable(void *p) +{ + uintptr_t addr = (uintptr_t) p; + const long page_size = getpagesize(); +#ifdef HAVE_MINCORE + unsigned char valid = 0; + + if (p == NULL) + return EGL_FALSE; + + /* align addr to page_size */ + addr &= ~(page_size - 1); + + if (mincore((void *) addr, page_size, &valid) < 0) { + return EGL_FALSE; + } + + /* mincore() returns 0 on success, and -1 on failure. The last parameter + * is a vector of bytes with one entry for each page queried. mincore + * returns page residency information in the first bit of each byte in the + * vector. + * + * Residency doesn't actually matter when determining whether a pointer is + * dereferenceable, so the output vector can be ignored. What matters is + * whether mincore succeeds. See: + * + * http://man7.org/linux/man-pages/man2/mincore.2.html + */ + return EGL_TRUE; +#else + // Without mincore(), we just assume that the first page is unmapped. + return addr >= page_size; +#endif +}