/* * Copyright (c) 2020, Rockchip Electronics Co., Ltd * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. */ #ifndef _GNU_SOURCE #define _GNU_SOURCE 1 #endif #include #include #include #include #include #include #include #include #include #ifdef HAS_GBM #include #endif #ifdef HAS_EGL #include #include #endif #ifdef HAS_X11 #include #include #include #endif #ifndef ARRAY_SIZE #define ARRAY_SIZE(x) (sizeof(x)/sizeof(x[0])) #endif #ifndef DRM_FORMAT_MOD_LINEAR #define DRM_FORMAT_MOD_LINEAR 0 #endif #ifndef DRM_FORMAT_MOD_INVALID #define DRM_FORMAT_MOD_INVALID ((1ULL<<56) - 1) #endif /* A stub symbol to ensure that the hook library would not be removed as unused */ int mali_injected = 0; /* Override libmali symbols */ #ifdef HAS_GBM #ifndef HAS_gbm_bo_map static int (* _gbm_device_get_fd)(struct gbm_device *gbm) = NULL; #endif static struct gbm_surface * (* _gbm_surface_create)(struct gbm_device *, uint32_t, uint32_t, uint32_t, uint32_t) = NULL; #ifdef HAS_gbm_surface_create_with_modifiers static struct gbm_surface *(* _gbm_surface_create_with_modifiers) (struct gbm_device *gbm, uint32_t width, uint32_t height, uint32_t format, const uint64_t *modifiers, const unsigned int count); #endif static struct gbm_bo * (* _gbm_bo_create)(struct gbm_device *, uint32_t, uint32_t, uint32_t, uint32_t) = NULL; #ifdef HAS_gbm_bo_create_with_modifiers static struct gbm_bo * (* _gbm_bo_create_with_modifiers)(struct gbm_device *gbm, uint32_t width, uint32_t height, uint32_t format, const uint64_t *modifiers, const unsigned int count) = NULL; #endif #ifdef HAS_gbm_bo_get_modifier static uint64_t (* _gbm_bo_get_modifier)(struct gbm_bo *bo) = NULL; #endif #ifndef HAS_gbm_bo_map static uint32_t (* _gbm_bo_get_width)(struct gbm_bo *bo) = NULL; #endif #if !defined(HAS_gbm_bo_map) || !defined(HAS_gbm_bo_unmap) static uint32_t (* _gbm_bo_get_height)(struct gbm_bo *bo) = NULL; #endif #if !defined(HAS_gbm_bo_map) || !defined(HAS_gbm_bo_unmap) || \ !defined(HAS_gbm_bo_get_stride_for_plane) static uint32_t (* _gbm_bo_get_stride)(struct gbm_bo *bo) = NULL; #endif #ifndef HAS_gbm_bo_get_bpp static uint32_t (* _gbm_bo_get_format)(struct gbm_bo *bo) = NULL; #endif #ifndef HAS_gbm_bo_map static uint32_t (* _gbm_bo_get_bpp)(struct gbm_bo *bo) = NULL; static struct gbm_device * (* _gbm_bo_get_device)(struct gbm_bo *bo) = NULL; #endif #if !defined(HAS_gbm_bo_map) || !defined(HAS_gbm_bo_get_handle_for_plane) static union gbm_bo_handle (* _gbm_bo_get_handle)(struct gbm_bo *bo) = NULL; #endif #ifndef HAS_gbm_bo_get_fd_for_plane static int (* _gbm_bo_get_fd)(struct gbm_bo *bo) = NULL; #endif #endif #ifdef HAS_EGL static PFNEGLGETCURRENTSURFACEPROC _eglGetCurrentSurface = NULL; static PFNEGLGETDISPLAYPROC _eglGetDisplay = NULL; static PFNEGLGETPROCADDRESSPROC _eglGetProcAddress = NULL; static PFNEGLGETPLATFORMDISPLAYPROC _eglGetPlatformDisplay = NULL; static PFNEGLCHOOSECONFIGPROC _eglChooseConfig = NULL; static PFNEGLGETPLATFORMDISPLAYEXTPROC _eglGetPlatformDisplayEXT = NULL; static PFNEGLCREATEPIXMAPSURFACEPROC _eglCreatePixmapSurface = NULL; static PFNEGLCREATEWINDOWSURFACEPROC _eglCreateWindowSurface = NULL; static EGLBoolean (* _eglDestroySurface)(EGLDisplay dpy, EGLSurface surface) = NULL; static PFNEGLMAKECURRENTPROC _eglMakeCurrent = NULL; #endif #define MALI_SYMBOL(func) { #func, (void **)(&_ ## func), } static struct { const char *func; void **symbol; } mali_symbols[] = { #ifdef HAS_GBM #ifndef HAS_gbm_bo_map MALI_SYMBOL(gbm_device_get_fd), #endif MALI_SYMBOL(gbm_surface_create), #ifdef HAS_gbm_surface_create_with_modifiers MALI_SYMBOL(gbm_surface_create_with_modifiers), #endif MALI_SYMBOL(gbm_bo_create), #ifdef HAS_gbm_bo_create_with_modifiers MALI_SYMBOL(gbm_bo_create_with_modifiers), #endif #ifdef HAS_gbm_bo_get_modifier MALI_SYMBOL(gbm_bo_get_modifier), #endif #ifndef HAS_gbm_bo_map MALI_SYMBOL(gbm_bo_get_width), #endif #if !defined(HAS_gbm_bo_map) || !defined(HAS_gbm_bo_unmap) MALI_SYMBOL(gbm_bo_get_height), #endif #if !defined(HAS_gbm_bo_map) || !defined(HAS_gbm_bo_unmap) || \ !defined(HAS_gbm_bo_get_stride_for_plane) MALI_SYMBOL(gbm_bo_get_stride), #endif #ifndef HAS_gbm_bo_get_bpp MALI_SYMBOL(gbm_bo_get_format), #endif #ifndef HAS_gbm_bo_map MALI_SYMBOL(gbm_bo_get_bpp), MALI_SYMBOL(gbm_bo_get_device), #endif #if !defined(HAS_gbm_bo_map) || !defined(HAS_gbm_bo_get_handle_for_plane) MALI_SYMBOL(gbm_bo_get_handle), #endif #ifndef HAS_gbm_bo_get_fd_for_plane MALI_SYMBOL(gbm_bo_get_fd), #endif #endif #ifdef HAS_EGL MALI_SYMBOL(eglGetCurrentSurface), MALI_SYMBOL(eglGetDisplay), MALI_SYMBOL(eglGetProcAddress), MALI_SYMBOL(eglChooseConfig), MALI_SYMBOL(eglCreatePixmapSurface), MALI_SYMBOL(eglCreateWindowSurface), MALI_SYMBOL(eglDestroySurface), MALI_SYMBOL(eglMakeCurrent), #endif }; __attribute__((constructor)) static void load_mali_symbols(void) { void *handle, *symbol; int i; /* The libmali should be already loaded */ handle = dlopen(LIBMALI_SO, RTLD_LAZY | RTLD_NOLOAD); if (!handle) { /* Should not reach here */ fprintf(stderr, "[MALI-HOOK] FATAL: dlopen(" LIBMALI_SO ") failed(%s)\n", dlerror()); exit(-1); } for (i = 0; i < ARRAY_SIZE(mali_symbols); i++) { const char *func = mali_symbols[i].func; /* Clear error */ dlerror(); symbol = dlsym(handle, func); if (!symbol) { /* Should not reach here */ fprintf(stderr, "[MALI-HOOK] FATAL: " LIBMALI_SO " dlsym(%s) failed(%s)\n", func, dlerror()); exit(-1); } *mali_symbols[i].symbol = symbol; } dlclose(handle); #ifdef HAS_EGL _eglGetPlatformDisplay = (PFNEGLGETPLATFORMDISPLAYPROC)_eglGetProcAddress("eglGetPlatformDisplay"); _eglGetPlatformDisplayEXT = (PFNEGLGETPLATFORMDISPLAYEXTPROC)_eglGetProcAddress("eglGetPlatformDisplayEXT"); #endif } #ifdef HAS_GBM /* Implement new GBM APIs */ __attribute__((unused)) static inline bool can_ignore_modifiers(const uint64_t *modifiers, const unsigned int count) { for (int i = 0; i < count; i++) { if (modifiers[i] == DRM_FORMAT_MOD_LINEAR || modifiers[i] == DRM_FORMAT_MOD_INVALID) { return true; } } return !count; } #ifndef HAS_gbm_bo_get_offset uint32_t gbm_bo_get_offset(struct gbm_bo *bo, int plane) { return 0; } #endif #ifndef HAS_gbm_bo_get_plane_count int gbm_bo_get_plane_count(struct gbm_bo *bo) { return 1; } #endif #ifndef HAS_gbm_bo_get_stride_for_plane uint32_t gbm_bo_get_stride_for_plane(struct gbm_bo *bo, int plane) { if (plane) return 0; return _gbm_bo_get_stride(bo); } #endif #ifndef HAS_gbm_bo_get_fd_for_plane int gbm_bo_get_fd_for_plane(struct gbm_bo *bo, int plane) { if (plane) return -1; return _gbm_bo_get_fd(bo); } #endif #ifndef HAS_gbm_bo_get_handle_for_plane union gbm_bo_handle gbm_bo_get_handle_for_plane(struct gbm_bo *bo, int plane) { union gbm_bo_handle ret; ret.s32 = -1; if (plane) return ret; return _gbm_bo_get_handle(bo); } #endif #ifndef HAS_gbm_device_get_format_modifier_plane_count int gbm_device_get_format_modifier_plane_count(struct gbm_device *gbm, uint32_t format, uint64_t modifier) { return can_ignore_modifiers(&modifier, 1) ? 1 : 0; } #endif #ifndef HAS_gbm_bo_create_with_modifiers2 struct gbm_bo * gbm_bo_create_with_modifiers2(struct gbm_device *gbm, uint32_t width, uint32_t height, uint32_t format, const uint64_t *modifiers, const unsigned int count, uint32_t flags) { #ifdef HAS_gbm_bo_create_with_modifiers /* flags ignored */ return _gbm_bo_create_with_modifiers(gbm, width, height, format, modifiers, count); #else if (!can_ignore_modifiers(modifiers, count)) return NULL; return gbm_bo_create(gbm, width, height, format, flags); #endif } #endif #ifndef HAS_gbm_bo_create_with_modifiers struct gbm_bo * gbm_bo_create_with_modifiers(struct gbm_device *gbm, uint32_t width, uint32_t height, uint32_t format, const uint64_t *modifiers, const unsigned int count) { return gbm_bo_create_with_modifiers2(gbm, width, height, format, modifiers, count, GBM_BO_USE_SCANOUT); } #endif #ifndef HAS_gbm_surface_create_with_modifiers2 struct gbm_surface * gbm_surface_create_with_modifiers2(struct gbm_device *gbm, uint32_t width, uint32_t height, uint32_t format, const uint64_t *modifiers, const unsigned int count, uint32_t flags) { #ifdef HAS_gbm_surface_create_with_modifiers /* flags ignored */ return _gbm_surface_create_with_modifiers(gbm, width, height, format, modifiers, count); #else if (!can_ignore_modifiers(modifiers, count)) return NULL; return gbm_surface_create(gbm, width, height, format, 0); #endif } #endif #ifndef HAS_gbm_surface_create_with_modifiers struct gbm_surface * gbm_surface_create_with_modifiers(struct gbm_device *gbm, uint32_t width, uint32_t height, uint32_t format, const uint64_t *modifiers, const unsigned int count) { return gbm_surface_create_with_modifiers2(gbm, width, height, format, modifiers, count, GBM_BO_USE_SCANOUT); } #endif #ifndef HAS_gbm_bo_map void * gbm_bo_map(struct gbm_bo *bo, uint32_t x, uint32_t y, uint32_t width, uint32_t height, uint32_t flags, uint32_t *stride, void **map_data) { struct drm_mode_map_dumb arg; struct gbm_device *gbm_dev; void *map; int fd, ret; if (!bo || !map_data || width <= 0 || width > _gbm_bo_get_width(bo) || height <= 0 || height > _gbm_bo_get_height(bo)) { errno = EINVAL; return MAP_FAILED; } gbm_dev = _gbm_bo_get_device(bo); if (!gbm_dev) return MAP_FAILED; fd = _gbm_device_get_fd(gbm_dev); if (fd < 0) return MAP_FAILED; memset(&arg, 0, sizeof(arg)); arg.handle = _gbm_bo_get_handle(bo).u32; ret = drmIoctl(fd, DRM_IOCTL_MODE_MAP_DUMB, &arg); if (ret) return MAP_FAILED; map = mmap(NULL, _gbm_bo_get_stride(bo) * _gbm_bo_get_height(bo), PROT_READ | PROT_WRITE, MAP_SHARED, fd, arg.offset); if (map == MAP_FAILED) return map; *map_data = map; if (stride) *stride = _gbm_bo_get_stride(bo); return map + y * _gbm_bo_get_stride(bo) + x * (_gbm_bo_get_bpp(bo) >> 3); } #endif #ifndef HAS_gbm_bo_unmap void gbm_bo_unmap(struct gbm_bo *bo, void *map_data) { if (map_data) munmap(map_data, _gbm_bo_get_stride(bo) * _gbm_bo_get_height(bo)); } #endif /* From mesa3d mesa-23.1.3-1 : src/gbm/main/gbm.c */ #ifndef HAS_gbm_bo_get_bpp uint32_t gbm_bo_get_bpp(struct gbm_bo *bo) { switch (_gbm_bo_get_format(bo)) { default: return 0; case GBM_FORMAT_C8: case GBM_FORMAT_R8: case GBM_FORMAT_RGB332: case GBM_FORMAT_BGR233: return 8; case GBM_FORMAT_R16: case GBM_FORMAT_GR88: case GBM_FORMAT_XRGB4444: case GBM_FORMAT_XBGR4444: case GBM_FORMAT_RGBX4444: case GBM_FORMAT_BGRX4444: case GBM_FORMAT_ARGB4444: case GBM_FORMAT_ABGR4444: case GBM_FORMAT_RGBA4444: case GBM_FORMAT_BGRA4444: case GBM_FORMAT_XRGB1555: case GBM_FORMAT_XBGR1555: case GBM_FORMAT_RGBX5551: case GBM_FORMAT_BGRX5551: case GBM_FORMAT_ARGB1555: case GBM_FORMAT_ABGR1555: case GBM_FORMAT_RGBA5551: case GBM_FORMAT_BGRA5551: case GBM_FORMAT_RGB565: case GBM_FORMAT_BGR565: return 16; case GBM_FORMAT_RGB888: case GBM_FORMAT_BGR888: return 24; case GBM_FORMAT_RG1616: case GBM_FORMAT_GR1616: case GBM_FORMAT_XRGB8888: case GBM_FORMAT_XBGR8888: case GBM_FORMAT_RGBX8888: case GBM_FORMAT_BGRX8888: case GBM_FORMAT_ARGB8888: case GBM_FORMAT_ABGR8888: case GBM_FORMAT_RGBA8888: case GBM_FORMAT_BGRA8888: case GBM_FORMAT_XRGB2101010: case GBM_FORMAT_XBGR2101010: case GBM_FORMAT_RGBX1010102: case GBM_FORMAT_BGRX1010102: case GBM_FORMAT_ARGB2101010: case GBM_FORMAT_ABGR2101010: case GBM_FORMAT_RGBA1010102: case GBM_FORMAT_BGRA1010102: return 32; case GBM_FORMAT_XBGR16161616: case GBM_FORMAT_ABGR16161616: case GBM_FORMAT_XBGR16161616F: case GBM_FORMAT_ABGR16161616F: return 64; } } #endif /* From mesa3d mesa-23.1.3-1 : src/gbm/main/gbm.c */ #ifndef HAS_gbm_format_get_name static uint32_t gbm_format_canonicalize(uint32_t gbm_format) { switch (gbm_format) { case GBM_BO_FORMAT_XRGB8888: return GBM_FORMAT_XRGB8888; case GBM_BO_FORMAT_ARGB8888: return GBM_FORMAT_ARGB8888; default: return gbm_format; } } char * gbm_format_get_name(uint32_t gbm_format, struct gbm_format_name_desc *desc) { gbm_format = gbm_format_canonicalize(gbm_format); desc->name[0] = gbm_format; desc->name[1] = gbm_format >> 8; desc->name[2] = gbm_format >> 16; desc->name[3] = gbm_format >> 24; desc->name[4] = 0; return desc->name; } #endif /* Wrappers for invalid modifier */ uint64_t gbm_bo_get_modifier(struct gbm_bo *bo) { #ifdef HAS_gbm_bo_get_modifier uint64_t modifier = _gbm_bo_get_modifier(bo); if (modifier != DRM_FORMAT_MOD_INVALID) return modifier; #endif return DRM_FORMAT_MOD_LINEAR; } /* Wrappers for unsupported flags */ struct gbm_surface * gbm_surface_create(struct gbm_device *gbm, uint32_t width, uint32_t height, uint32_t format, uint32_t flags) { struct gbm_surface *surface; surface = _gbm_surface_create(gbm, width, height, format, flags); if (surface) return surface; flags &= GBM_BO_USE_SCANOUT | GBM_BO_USE_RENDERING; return _gbm_surface_create(gbm, width, height, format, flags); } struct gbm_bo * gbm_bo_create(struct gbm_device *gbm, uint32_t width, uint32_t height, uint32_t format, uint32_t flags) { struct gbm_bo *bo; bo = _gbm_bo_create(gbm, width, height, format, flags); if (bo) return bo; flags &= GBM_BO_USE_SCANOUT | GBM_BO_USE_RENDERING | GBM_BO_USE_WRITE | GBM_BO_USE_CURSOR_64X64; return _gbm_bo_create(gbm, width, height, format, flags); } #endif // HAS_GBM #ifdef HAS_EGL #ifdef HAS_X11 /* Hacked displays (should not be much) */ #define MAX_X11_DISPLAY 32 static Display *_x11_displays[MAX_X11_DISPLAY] = { NULL, }; static pthread_mutex_t _x11_mutex = PTHREAD_MUTEX_INITIALIZER; static inline int force_x11_threads(void) { return !getenv("MALI_X11_NO_FORCE_THREADS"); } __attribute__((constructor)) static void init_x11_threads(void) { if (force_x11_threads()) XInitThreads(); } __attribute__((destructor)) static void cleanup_x11_display(void) { int i; for (i = 0; i < MAX_X11_DISPLAY; i++) { Display *display = _x11_displays[i]; if (display) XCloseDisplay(display); } } static Display * fixup_x11_display(Display *display) { int i; if (!force_x11_threads()) return display; if (!display || display->lock_fns) return display; pthread_mutex_lock(&_x11_mutex); /* Create a new threaded display */ display = XOpenDisplay(DisplayString(display)); for (i = 0; i < MAX_X11_DISPLAY; i++) { if (!_x11_displays[i]) { _x11_displays[i] = display; break; } } pthread_mutex_unlock(&_x11_mutex); return display; } #endif // HAS_X11 /* Override EGL symbols */ #ifdef HAS_X11 EGLAPI EGLDisplay EGLAPIENTRY eglGetPlatformDisplayEXT (EGLenum platform, void *native_display, const EGLint *attrib_list) { if (!_eglGetPlatformDisplayEXT) return EGL_NO_DISPLAY; if (platform == EGL_PLATFORM_X11_KHR && native_display) { native_display = (void *)fixup_x11_display(native_display); if (!native_display) return EGL_NO_DISPLAY; } return _eglGetPlatformDisplayEXT(platform, native_display, attrib_list); } #endif // HAS_X11 EGLAPI EGLDisplay EGLAPIENTRY eglGetDisplay (EGLNativeDisplayType display_id) { const char *type = getenv("MALI_DEFAULT_WINSYS"); // HACK: For chromium angle with in-process-gpu. if (getenv("MALI_FORCE_DEFAULT_DISPLAY") && display_id != EGL_DEFAULT_DISPLAY) { fprintf(stderr, "[MALI-HOOK] WARN: Native display(%p) ignored!\n", display_id); display_id = EGL_DEFAULT_DISPLAY; } #ifdef HAS_GBM if (type && !strcmp(type, "gbm")) return eglGetPlatformDisplay(EGL_PLATFORM_GBM_KHR, display_id, NULL); #endif #ifdef HAS_WAYLAND if (type && !strcmp(type, "wayland")) return eglGetPlatformDisplay(EGL_PLATFORM_WAYLAND_EXT, display_id, NULL); #endif #ifdef HAS_X11 /* Use X11 by default when avaiable */ return eglGetPlatformDisplay(EGL_PLATFORM_X11_KHR, display_id, NULL); #else return _eglGetDisplay(display_id); #endif } /* Export for EGL 1.5 */ #define GET_PROC_ADDR(v, n) v = (typeof(v))_eglGetProcAddress(n) /* From mesa3d mesa-23.1.3-1 : src/egl/main/egldisplay.h */ static inline size_t _eglNumAttribs(const EGLAttrib *attribs) { size_t len = 0; if (attribs) { while (attribs[len] != EGL_NONE) len += 2; len++; } return len; } /* From mesa3d mesa-23.1.3-1 : src/egl/main/eglapi.c */ static EGLint * _eglConvertAttribsToInt(const EGLAttrib *attr_list) { size_t size = _eglNumAttribs(attr_list); EGLint *int_attribs = NULL; /* Convert attributes from EGLAttrib[] to EGLint[] */ if (size) { int_attribs = calloc(size, sizeof(int_attribs[0])); if (!int_attribs) return NULL; for (size_t i = 0; i < size; i++) int_attribs[i] = attr_list[i]; } return int_attribs; } EGLAPI EGLDisplay EGLAPIENTRY eglGetPlatformDisplay(EGLenum platform, void *native_display, const EGLAttrib *attrib_list) { if (_eglGetPlatformDisplayEXT) { EGLint *int_attribs = _eglConvertAttribsToInt(attrib_list); if (!int_attribs == !attrib_list) { EGLDisplay display = _eglGetPlatformDisplayEXT(platform, native_display, int_attribs); free(int_attribs); return display; } } if (!_eglGetPlatformDisplay) return EGL_NO_DISPLAY; #ifdef HAS_X11 if (platform == EGL_PLATFORM_X11_KHR && native_display) { native_display = (void *)fixup_x11_display(native_display); if (!native_display) return EGL_NO_DISPLAY; } #endif return _eglGetPlatformDisplay(platform, native_display, attrib_list); } EGLAPI EGLSurface EGLAPIENTRY eglCreatePlatformWindowSurface(EGLDisplay dpy, EGLConfig config, void *native_window, const EGLAttrib *attrib_list) { PFNEGLCREATEPLATFORMWINDOWSURFACEPROC create_platform_window_surface; GET_PROC_ADDR(create_platform_window_surface, "eglCreatePlatformWindowSurface"); if (!create_platform_window_surface) { EGLint *int_attribs = _eglConvertAttribsToInt(attrib_list); if (!int_attribs == !attrib_list) { EGLSurface surface = _eglCreateWindowSurface(dpy, config, native_window, int_attribs); free(int_attribs); return surface; } } return create_platform_window_surface(dpy, config, native_window, attrib_list); } EGLAPI EGLSurface EGLAPIENTRY eglCreatePlatformPixmapSurface(EGLDisplay dpy, EGLConfig config, void *native_pixmap, const EGLAttrib *attrib_list) { PFNEGLCREATEPLATFORMPIXMAPSURFACEPROC create_platform_pixmap_surface; GET_PROC_ADDR(create_platform_pixmap_surface, "eglCreatePlatformPixmapSurface"); if (!create_platform_pixmap_surface) { EGLint *int_attribs = _eglConvertAttribsToInt(attrib_list); if (!int_attribs == !attrib_list) { EGLSurface surface = _eglCreatePixmapSurface(dpy, config, native_pixmap, int_attribs); free(int_attribs); return surface; } } return create_platform_pixmap_surface(dpy, config, native_pixmap, attrib_list); } /* HACK: Unset current surface before destroying it */ EGLBoolean eglDestroySurface(EGLDisplay dpy, EGLSurface surface) { if (_eglGetCurrentSurface(EGL_DRAW) == surface || _eglGetCurrentSurface(EGL_READ) == surface) _eglMakeCurrent(dpy, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT); return _eglDestroySurface(dpy, surface); } /* HACK: Fixup EGL_OPENGL_BIT */ EGLBoolean eglChooseConfig (EGLDisplay dpy, const EGLint *attrib_list, EGLConfig *configs, EGLint config_size, EGLint *num_config) { #define MAX_EGL_ATTRS 1024 EGLint list[MAX_EGL_ATTRS]; int i = 0; if (!attrib_list) return _eglChooseConfig(dpy, attrib_list, configs, config_size, num_config); while (attrib_list[i] != EGL_NONE) { if (i > MAX_EGL_ATTRS - 2) return EGL_FALSE; list[i] = attrib_list[i]; list[i + 1] = attrib_list[i + 1]; if (list[i] == EGL_RENDERABLE_TYPE && list[i + 1] == EGL_OPENGL_BIT) list[i + 1] = EGL_OPENGL_ES_BIT; i += 2; } list[i] = EGL_NONE; return _eglChooseConfig(dpy, list, configs, config_size, num_config); } /* Override proc addesses */ EGLAPI __eglMustCastToProperFunctionPointerType EGLAPIENTRY eglGetProcAddress(const char *procname) { if (!procname) return NULL; if (!strcmp(procname, __func__)) return (__eglMustCastToProperFunctionPointerType)eglGetProcAddress; if (!strcmp(procname, "eglGetDisplay")) return (__eglMustCastToProperFunctionPointerType)eglGetDisplay; if (!strcmp(procname, "eglGetPlatformDisplay")) { if (!_eglGetPlatformDisplay && !_eglGetPlatformDisplayEXT) return NULL; return (__eglMustCastToProperFunctionPointerType)eglGetPlatformDisplay; } #ifdef HAS_X11 if (!strcmp(procname, "eglGetPlatformDisplayEXT")) { if (!_eglGetPlatformDisplayEXT) return NULL; return (__eglMustCastToProperFunctionPointerType)eglGetPlatformDisplayEXT; } #endif if (!strcmp(procname, "eglChooseConfig")) return (__eglMustCastToProperFunctionPointerType)eglChooseConfig; if (!strcmp(procname, "eglCreatePlatformWindowSurface")) return (__eglMustCastToProperFunctionPointerType)eglCreatePlatformWindowSurface; if (!strcmp(procname, "eglCreatePlatformPixmapSurface")) return (__eglMustCastToProperFunctionPointerType)eglCreatePlatformPixmapSurface; if (!strcmp(procname, "eglDestroySurface")) return (__eglMustCastToProperFunctionPointerType)eglDestroySurface; return _eglGetProcAddress(procname); } #endif // HAS_EGL