From ce562f9e3fab769d64b0e5453ec2b4f8710a31ce Mon Sep 17 00:00:00 2001 From: Kyle Brenneman Date: Wed, 4 Jan 2017 11:31:58 -0700 Subject: [PATCH] EGL: Implement the libglvnd interface for EGL (v3) The new interface mostly just sits on top of the existing library. The only change to the existing EGL code is to split the client extension string into platform extensions and everything else. On non-glvnd builds, eglQueryString will just concatenate the two strings. The EGL dispatch stubs are all generated. The script is based on the one used to generate entrypoints in libglvnd itself. v2: [Kyle] - Rebased against master. - Reworked the EGL makefile to use separate libraries - Made the EGL code generation scripts work with Python 2 and 3. - Change gen_egl_dispatch.py to use argparse for the command line arguments. - Assorted formatting and style cleanup in the Python scripts. v3: [Emil Velikov] - Rebase - Remove separate glvnd glx/egl configure toggles Signed-off-by: Emil Velikov --- configure.ac | 12 +- src/egl/Makefile.am | 96 +- src/egl/generate/egl.xml | 2412 ++++++++++++++++++++++++++ src/egl/generate/eglFunctionList.py | 199 +++ src/egl/generate/egl_other.xml | 47 + src/egl/generate/genCommon.py | 223 +++ src/egl/generate/gen_egl_dispatch.py | 250 +++ src/egl/main/50_mesa.json | 6 + src/egl/main/eglapi.c | 6 +- src/egl/main/egldispatchstubs.c | 110 ++ src/egl/main/egldispatchstubs.h | 26 + src/egl/main/eglglobals.c | 47 +- src/egl/main/eglglobals.h | 13 +- src/egl/main/eglglvnd.c | 82 + src/glx/Makefile.am | 2 +- src/glx/glxclient.h | 2 +- 16 files changed, 3501 insertions(+), 32 deletions(-) create mode 100644 src/egl/generate/egl.xml create mode 100644 src/egl/generate/eglFunctionList.py create mode 100644 src/egl/generate/egl_other.xml create mode 100644 src/egl/generate/genCommon.py create mode 100644 src/egl/generate/gen_egl_dispatch.py create mode 100644 src/egl/main/50_mesa.json create mode 100644 src/egl/main/egldispatchstubs.c create mode 100644 src/egl/main/egldispatchstubs.h create mode 100644 src/egl/main/eglglvnd.c diff --git a/configure.ac b/configure.ac index ab33ca03805..ba09cc32535 100644 --- a/configure.ac +++ b/configure.ac @@ -1348,10 +1348,11 @@ dnl Libglvnd configuration dnl AC_ARG_ENABLE([libglvnd], [AS_HELP_STRING([--enable-libglvnd], - [Build for libglvnd @<:@default=disabled@:>@])], + [Build GLX and EGL for libglvnd @<:@default=disabled@:>@])], [enable_libglvnd="$enableval"], [enable_libglvnd=no]) -AM_CONDITIONAL(USE_LIBGLVND_GLX, test "x$enable_libglvnd" = xyes) +AM_CONDITIONAL(USE_LIBGLVND, test "x$enable_libglvnd" = xyes) + if test "x$enable_libglvnd" = xyes ; then dnl XXX: update once we can handle more than libGL/glx. dnl Namely: we should error out if neither of the glvnd enabled libraries @@ -1367,8 +1368,11 @@ if test "x$enable_libglvnd" = xyes ; then ;; esac - PKG_CHECK_MODULES([GLVND], libglvnd >= 0.1.0) - DEFINES="${DEFINES} -DUSE_LIBGLVND_GLX=1" + PKG_CHECK_MODULES([GLVND], libglvnd >= 0.2.0) + PKG_CHECK_VAR(LIBGLVND_DATADIR, libglvnd, datadir) + AC_SUBST([LIBGLVND_DATADIR]) + + DEFINES="${DEFINES} -DUSE_LIBGLVND=1" DEFAULT_GL_LIB_NAME=GLX_mesa fi diff --git a/src/egl/Makefile.am b/src/egl/Makefile.am index 3477f797d77..e607b83fb99 100644 --- a/src/egl/Makefile.am +++ b/src/egl/Makefile.am @@ -32,19 +32,16 @@ AM_CFLAGS = \ $(EGL_CFLAGS) \ -D_EGL_NATIVE_PLATFORM=$(EGL_NATIVE_PLATFORM) -lib_LTLIBRARIES = libEGL.la - -libEGL_la_SOURCES = \ +# Depending on whether libglvnd is enabled, we'll build the EGL library as +# either libEGL.so.1 or libEGL_mesa.so.0. Using an automake substitution +# in the variable names breaks "make dist" target, so use a conenience library +# instead. +noinst_LTLIBRARIES = libEGL_common.la +libEGL_common_la_SOURCES = \ $(LIBEGL_C_FILES) -libEGL_la_LIBADD = \ +libEGL_common_la_LIBADD = \ $(EGL_LIB_DEPS) -libEGL_la_LDFLAGS = \ - -no-undefined \ - -version-number 1:0 \ - $(BSYMBOLIC) \ - $(GC_SECTIONS) \ - $(LD_NO_UNDEFINED) dri2_backend_FILES = dri3_backend_FILES = @@ -52,7 +49,7 @@ dri3_backend_FILES = if HAVE_PLATFORM_X11 AM_CFLAGS += -DHAVE_X11_PLATFORM AM_CFLAGS += $(XCB_DRI2_CFLAGS) -libEGL_la_LIBADD += $(XCB_DRI2_LIBS) +libEGL_common_la_LIBADD += $(XCB_DRI2_LIBS) dri2_backend_FILES += drivers/dri2/platform_x11.c if HAVE_DRI3 @@ -60,22 +57,22 @@ dri3_backend_FILES += \ drivers/dri2/platform_x11_dri3.c \ drivers/dri2/platform_x11_dri3.h -libEGL_la_LIBADD += $(top_builddir)/src/loader/libloader_dri3_helper.la +libEGL_common_la_LIBADD += $(top_builddir)/src/loader/libloader_dri3_helper.la endif endif if HAVE_PLATFORM_WAYLAND AM_CFLAGS += -DHAVE_WAYLAND_PLATFORM AM_CFLAGS += $(WAYLAND_CFLAGS) -libEGL_la_LIBADD += $(WAYLAND_LIBS) -libEGL_la_LIBADD += $(LIBDRM_LIBS) -libEGL_la_LIBADD += $(top_builddir)/src/egl/wayland/wayland-drm/libwayland-drm.la +libEGL_common_la_LIBADD += $(WAYLAND_LIBS) +libEGL_common_la_LIBADD += $(LIBDRM_LIBS) +libEGL_common_la_LIBADD += $(top_builddir)/src/egl/wayland/wayland-drm/libwayland-drm.la dri2_backend_FILES += drivers/dri2/platform_wayland.c endif if HAVE_EGL_PLATFORM_DRM AM_CFLAGS += -DHAVE_DRM_PLATFORM -libEGL_la_LIBADD += $(top_builddir)/src/gbm/libgbm.la +libEGL_common_la_LIBADD += $(top_builddir)/src/gbm/libgbm.la dri2_backend_FILES += drivers/dri2/platform_drm.c endif @@ -87,7 +84,7 @@ endif if HAVE_EGL_PLATFORM_ANDROID AM_CFLAGS += -DHAVE_ANDROID_PLATFORM AM_CFLAGS += $(ANDROID_CFLAGS) -libEGL_la_LIBADD += $(ANDROID_LIBS) +libEGL_common_la_LIBADD += $(ANDROID_LIBS) dri2_backend_FILES += drivers/dri2/platform_android.c endif @@ -101,13 +98,68 @@ AM_CFLAGS += \ -DDEFAULT_DRIVER_DIR=\"$(DRI_DRIVER_SEARCH_DIR)\" \ -D_EGL_BUILT_IN_DRIVER_DRI2 -libEGL_la_SOURCES += \ +libEGL_common_la_SOURCES += \ $(dri2_backend_core_FILES) \ $(dri2_backend_FILES) \ $(dri3_backend_FILES) -libEGL_la_LIBADD += $(top_builddir)/src/loader/libloader.la -libEGL_la_LIBADD += $(DLOPEN_LIBS) $(LIBDRM_LIBS) $(CLOCK_LIB) +libEGL_common_la_LIBADD += $(top_builddir)/src/loader/libloader.la +libEGL_common_la_LIBADD += $(DLOPEN_LIBS) $(LIBDRM_LIBS) $(CLOCK_LIB) + +GLVND_GEN_DEPS = generate/gen_egl_dispatch.py \ + generate/egl.xml generate/eglFunctionList.py generate/genCommon.py \ + generate/egl_other.xml + +PYTHON_GEN = $(AM_V_GEN)$(PYTHON2) $(PYTHON_FLAGS) +g_egldispatchstubs.c: $(GLVND_GEN_DEPS) + $(PYTHON_GEN) $(top_srcdir)/src/egl/generate/gen_egl_dispatch.py source \ + $(top_srcdir)/src/egl/generate/eglFunctionList.py \ + $(top_srcdir)/src/egl/generate/egl.xml \ + $(top_srcdir)/src/egl/generate/egl_other.xml > $@ + +g_egldispatchstubs.h: $(GLVND_GEN_DEPS) + $(PYTHON_GEN) $(top_srcdir)/src/egl/generate/gen_egl_dispatch.py header \ + $(top_srcdir)/src/egl/generate/eglFunctionList.py \ + $(top_srcdir)/src/egl/generate/egl.xml \ + $(top_srcdir)/src/egl/generate/egl_other.xml > $@ + +BUILT_SOURCES = g_egldispatchstubs.c g_egldispatchstubs.h +CLEANFILES = $(BUILT_SOURCES) + +if USE_LIBGLVND +AM_CFLAGS += \ + $(GLVND_CFLAGS) + +vendorjsondir = @LIBGLVND_DATADIR@/glvnd/egl_vendor.d +vendorjson_DATA = main/50_mesa.json + +lib_LTLIBRARIES = libEGL_mesa.la +libEGL_mesa_la_SOURCES = \ + main/eglglvnd.c \ + main/egldispatchstubs.h \ + main/egldispatchstubs.c \ + g_egldispatchstubs.c +libEGL_mesa_la_LIBADD = libEGL_common.la +libEGL_mesa_la_LDFLAGS = \ + -no-undefined \ + -version-number 0 \ + $(BSYMBOLIC) \ + $(GC_SECTIONS) \ + $(LD_NO_UNDEFINED) + +else # USE_LIBGLVND + +lib_LTLIBRARIES = libEGL.la +libEGL_la_SOURCES = +libEGL_la_LIBADD = libEGL_common.la +libEGL_la_LDFLAGS = \ + -no-undefined \ + -version-number 1:0 \ + $(BSYMBOLIC) \ + $(GC_SECTIONS) \ + $(LD_NO_UNDEFINED) + +endif # USE_LIBGLVND include $(top_srcdir)/install-lib-links.mk @@ -134,4 +186,6 @@ EXTRA_DIST = \ SConscript \ drivers/haiku \ main/egl.def \ - main/README.txt + main/README.txt \ + $(GLVND_GEN_DEPS) \ + main/50_mesa.json diff --git a/src/egl/generate/egl.xml b/src/egl/generate/egl.xml new file mode 100644 index 00000000000..f6dbbc0f269 --- /dev/null +++ b/src/egl/generate/egl.xml @@ -0,0 +1,2412 @@ + + + + + + + + + #include <KHR/khrplatform.h> + #include <EGL/eglplatform.h> + + + + + + + + + + + + + + typedef unsigned int EGLBoolean; + typedef unsigned int EGLenum; + typedef intptr_t EGLAttribKHR; + typedef intptr_t EGLAttrib; + typedef void *EGLClientBuffer; + typedef void *EGLConfig; + typedef void *EGLContext; + typedef void *EGLDeviceEXT; + typedef void *EGLDisplay; + typedef void *EGLImage; + typedef void *EGLImageKHR; + typedef void *EGLLabelKHR; + typedef void *EGLObjectKHR; + typedef void *EGLOutputLayerEXT; + typedef void *EGLOutputPortEXT; + typedef void *EGLStreamKHR; + typedef void *EGLSurface; + typedef void *EGLSync; + typedef void *EGLSyncKHR; + typedef void *EGLSyncNV; + typedef void (*__eglMustCastToProperFunctionPointerType)(void); + typedef khronos_utime_nanoseconds_t EGLTimeKHR; + typedef khronos_utime_nanoseconds_t EGLTime; + typedef khronos_utime_nanoseconds_t EGLTimeNV; + typedef khronos_utime_nanoseconds_t EGLuint64NV; + typedef khronos_uint64_t EGLuint64KHR; + typedef int EGLNativeFileDescriptorKHR; + typedef khronos_ssize_t EGLsizeiANDROID; + typedef void (*EGLSetBlobFuncANDROID) (const void *key, EGLsizeiANDROID keySize, const void *value, EGLsizeiANDROID valueSize); + typedef EGLsizeiANDROID (*EGLGetBlobFuncANDROID) (const void *key, EGLsizeiANDROID keySize, void *value, EGLsizeiANDROID valueSize); + struct EGLClientPixmapHI { + void *pData; + EGLint iWidth; + EGLint iHeight; + EGLint iStride; +}; + typedef void ( *EGLDEBUGPROCKHR)(EGLenum error,const char *command,EGLint messageType,EGLLabelKHR threadLabel,EGLLabelKHR objectLabel,const char* message); + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + EGLBoolean eglBindAPI + EGLenum api + + + EGLBoolean eglBindTexImage + EGLDisplay dpy + EGLSurface surface + EGLint buffer + + + EGLBoolean eglChooseConfig + EGLDisplay dpy + const EGLint *attrib_list + EGLConfig *configs + EGLint config_size + EGLint *num_config + + + EGLint eglClientWaitSync + EGLDisplay dpy + EGLSync sync + EGLint flags + EGLTime timeout + + + EGLint eglClientWaitSyncKHR + EGLDisplay dpy + EGLSyncKHR sync + EGLint flags + EGLTimeKHR timeout + + + + EGLint eglClientWaitSyncNV + EGLSyncNV sync + EGLint flags + EGLTimeNV timeout + + + EGLBoolean eglCopyBuffers + EGLDisplay dpy + EGLSurface surface + EGLNativePixmapType target + + + EGLContext eglCreateContext + EGLDisplay dpy + EGLConfig config + EGLContext share_context + const EGLint *attrib_list + + + EGLImageKHR eglCreateDRMImageMESA + EGLDisplay dpy + const EGLint *attrib_list + + + EGLSyncNV eglCreateFenceSyncNV + EGLDisplay dpy + EGLenum condition + const EGLint *attrib_list + + + EGLImage eglCreateImage + EGLDisplay dpy + EGLContext ctx + EGLenum target + EGLClientBuffer buffer + const EGLAttrib *attrib_list + + + EGLImageKHR eglCreateImageKHR + EGLDisplay dpy + EGLContext ctx + EGLenum target + EGLClientBuffer buffer + const EGLint *attrib_list + + + EGLSurface eglCreatePbufferFromClientBuffer + EGLDisplay dpy + EGLenum buftype + EGLClientBuffer buffer + EGLConfig config + const EGLint *attrib_list + + + EGLSurface eglCreatePbufferSurface + EGLDisplay dpy + EGLConfig config + const EGLint *attrib_list + + + EGLSurface eglCreatePixmapSurface + EGLDisplay dpy + EGLConfig config + EGLNativePixmapType pixmap + const EGLint *attrib_list + + + EGLSurface eglCreatePixmapSurfaceHI + EGLDisplay dpy + EGLConfig config + struct EGLClientPixmapHI *pixmap + + + EGLSurface eglCreatePlatformPixmapSurface + EGLDisplay dpy + EGLConfig config + void *native_pixmap + const EGLAttrib *attrib_list + + + EGLSurface eglCreatePlatformPixmapSurfaceEXT + EGLDisplay dpy + EGLConfig config + void *native_pixmap + const EGLint *attrib_list + + + EGLSurface eglCreatePlatformWindowSurface + EGLDisplay dpy + EGLConfig config + void *native_window + const EGLAttrib *attrib_list + + + EGLSurface eglCreatePlatformWindowSurfaceEXT + EGLDisplay dpy + EGLConfig config + void *native_window + const EGLint *attrib_list + + + EGLStreamKHR eglCreateStreamFromFileDescriptorKHR + EGLDisplay dpy + EGLNativeFileDescriptorKHR file_descriptor + + + EGLStreamKHR eglCreateStreamKHR + EGLDisplay dpy + const EGLint *attrib_list + + + EGLSurface eglCreateStreamProducerSurfaceKHR + EGLDisplay dpy + EGLConfig config + EGLStreamKHR stream + const EGLint *attrib_list + + + EGLSyncKHR eglCreateStreamSyncNV + EGLDisplay dpy + EGLStreamKHR stream + EGLenum type + const EGLint *attrib_list + + + EGLSync eglCreateSync + EGLDisplay dpy + EGLenum type + const EGLAttrib *attrib_list + + + EGLSyncKHR eglCreateSyncKHR + EGLDisplay dpy + EGLenum type + const EGLint *attrib_list + + + EGLSyncKHR eglCreateSync64KHR + EGLDisplay dpy + EGLenum type + const EGLAttribKHR *attrib_list + + + + EGLSurface eglCreateWindowSurface + EGLDisplay dpy + EGLConfig config + EGLNativeWindowType win + const EGLint *attrib_list + + + EGLint eglDebugMessageControlKHR + EGLDEBUGPROCKHR callback + const EGLAttrib *attrib_list + + + EGLBoolean eglDestroyContext + EGLDisplay dpy + EGLContext ctx + + + EGLBoolean eglDestroyImage + EGLDisplay dpy + EGLImage image + + + EGLBoolean eglDestroyImageKHR + EGLDisplay dpy + EGLImageKHR image + + + + EGLBoolean eglDestroyStreamKHR + EGLDisplay dpy + EGLStreamKHR stream + + + EGLBoolean eglDestroySurface + EGLDisplay dpy + EGLSurface surface + + + EGLBoolean eglDestroySync + EGLDisplay dpy + EGLSync sync + + + EGLBoolean eglDestroySyncKHR + EGLDisplay dpy + EGLSyncKHR sync + + + + EGLBoolean eglDestroySyncNV + EGLSyncNV sync + + + EGLint eglDupNativeFenceFDANDROID + EGLDisplay dpy + EGLSyncKHR sync + + + EGLBoolean eglExportDMABUFImageMESA + EGLDisplay dpy + EGLImageKHR image + int *fds + EGLint *strides + EGLint *offsets + + + EGLBoolean eglExportDMABUFImageQueryMESA + EGLDisplay dpy + EGLImageKHR image + int *fourcc + int *num_planes + EGLuint64KHR *modifiers + + + EGLBoolean eglExportDRMImageMESA + EGLDisplay dpy + EGLImageKHR image + EGLint *name + EGLint *handle + EGLint *stride + + + EGLBoolean eglFenceNV + EGLSyncNV sync + + + EGLBoolean eglGetConfigAttrib + EGLDisplay dpy + EGLConfig config + EGLint attribute + EGLint *value + + + EGLBoolean eglGetConfigs + EGLDisplay dpy + EGLConfig *configs + EGLint config_size + EGLint *num_config + + + EGLContext eglGetCurrentContext + + + EGLDisplay eglGetCurrentDisplay + + + EGLSurface eglGetCurrentSurface + EGLint readdraw + + + EGLDisplay eglGetDisplay + EGLNativeDisplayType display_id + + + EGLint eglGetError + + + EGLBoolean eglGetOutputLayersEXT + EGLDisplay dpy + const EGLAttrib *attrib_list + EGLOutputLayerEXT *layers + EGLint max_layers + EGLint *num_layers + + + EGLBoolean eglGetOutputPortsEXT + EGLDisplay dpy + const EGLAttrib *attrib_list + EGLOutputPortEXT *ports + EGLint max_ports + EGLint *num_ports + + + EGLDisplay eglGetPlatformDisplay + EGLenum platform + void *native_display + const EGLAttrib *attrib_list + + + EGLDisplay eglGetPlatformDisplayEXT + EGLenum platform + void *native_display + const EGLint *attrib_list + + + __eglMustCastToProperFunctionPointerType eglGetProcAddress + const char *procname + + + EGLNativeFileDescriptorKHR eglGetStreamFileDescriptorKHR + EGLDisplay dpy + EGLStreamKHR stream + + + EGLBoolean eglGetSyncAttrib + EGLDisplay dpy + EGLSync sync + EGLint attribute + EGLAttrib *value + + + EGLBoolean eglGetSyncAttribKHR + EGLDisplay dpy + EGLSyncKHR sync + EGLint attribute + EGLint *value + + + EGLBoolean eglGetSyncAttribNV + EGLSyncNV sync + EGLint attribute + EGLint *value + + + EGLuint64NV eglGetSystemTimeFrequencyNV + + + EGLuint64NV eglGetSystemTimeNV + + + EGLBoolean eglInitialize + EGLDisplay dpy + EGLint *major + EGLint *minor + + + EGLint eglLabelObjectKHR + EGLDisplay display + EGLenum objectType + EGLObjectKHR object + EGLLabelKHR label + + + EGLBoolean eglLockSurfaceKHR + EGLDisplay dpy + EGLSurface surface + const EGLint *attrib_list + + + EGLBoolean eglMakeCurrent + EGLDisplay dpy + EGLSurface draw + EGLSurface read + EGLContext ctx + + + EGLBoolean eglOutputLayerAttribEXT + EGLDisplay dpy + EGLOutputLayerEXT layer + EGLint attribute + EGLAttrib value + + + EGLBoolean eglOutputPortAttribEXT + EGLDisplay dpy + EGLOutputPortEXT port + EGLint attribute + EGLAttrib value + + + EGLBoolean eglPostSubBufferNV + EGLDisplay dpy + EGLSurface surface + EGLint x + EGLint y + EGLint width + EGLint height + + + EGLenum eglQueryAPI + + + EGLBoolean eglQueryContext + EGLDisplay dpy + EGLContext ctx + EGLint attribute + EGLint *value + + + EGLBoolean eglQueryDebugKHR + EGLint attribute + EGLAttrib *value + + + EGLBoolean eglQueryDeviceAttribEXT + EGLDeviceEXT device + EGLint attribute + EGLAttrib *value + + + const char *eglQueryDeviceStringEXT + EGLDeviceEXT device + EGLint name + + + EGLBoolean eglQueryDevicesEXT + EGLint max_devices + EGLDeviceEXT *devices + EGLint *num_devices + + + EGLBoolean eglQueryDisplayAttribEXT + EGLDisplay dpy + EGLint attribute + EGLAttrib *value + + + EGLBoolean eglQueryNativeDisplayNV + EGLDisplay dpy + EGLNativeDisplayType *display_id + + + EGLBoolean eglQueryNativePixmapNV + EGLDisplay dpy + EGLSurface surf + EGLNativePixmapType *pixmap + + + EGLBoolean eglQueryNativeWindowNV + EGLDisplay dpy + EGLSurface surf + EGLNativeWindowType *window + + + EGLBoolean eglQueryOutputLayerAttribEXT + EGLDisplay dpy + EGLOutputLayerEXT layer + EGLint attribute + EGLAttrib *value + + + const char *eglQueryOutputLayerStringEXT + EGLDisplay dpy + EGLOutputLayerEXT layer + EGLint name + + + EGLBoolean eglQueryOutputPortAttribEXT + EGLDisplay dpy + EGLOutputPortEXT port + EGLint attribute + EGLAttrib *value + + + const char *eglQueryOutputPortStringEXT + EGLDisplay dpy + EGLOutputPortEXT port + EGLint name + + + EGLBoolean eglQueryStreamKHR + EGLDisplay dpy + EGLStreamKHR stream + EGLenum attribute + EGLint *value + + + EGLBoolean eglQueryStreamTimeKHR + EGLDisplay dpy + EGLStreamKHR stream + EGLenum attribute + EGLTimeKHR *value + + + EGLBoolean eglQueryStreamu64KHR + EGLDisplay dpy + EGLStreamKHR stream + EGLenum attribute + EGLuint64KHR *value + + + const char *eglQueryString + EGLDisplay dpy + EGLint name + + + EGLBoolean eglQuerySurface + EGLDisplay dpy + EGLSurface surface + EGLint attribute + EGLint *value + + + EGLBoolean eglQuerySurface64KHR + EGLDisplay dpy + EGLSurface surface + EGLint attribute + EGLAttribKHR *value + + + EGLBoolean eglQuerySurfacePointerANGLE + EGLDisplay dpy + EGLSurface surface + EGLint attribute + void **value + + + EGLBoolean eglReleaseTexImage + EGLDisplay dpy + EGLSurface surface + EGLint buffer + + + EGLBoolean eglReleaseThread + + + void eglSetBlobCacheFuncsANDROID + EGLDisplay dpy + EGLSetBlobFuncANDROID set + EGLGetBlobFuncANDROID get + + + EGLBoolean eglSetDamageRegionKHR + EGLDisplay dpy + EGLSurface surface + EGLint *rects + EGLint n_rects + + + EGLBoolean eglSignalSyncKHR + EGLDisplay dpy + EGLSyncKHR sync + EGLenum mode + + + EGLBoolean eglSignalSyncNV + EGLSyncNV sync + EGLenum mode + + + EGLBoolean eglStreamAttribKHR + EGLDisplay dpy + EGLStreamKHR stream + EGLenum attribute + EGLint value + + + EGLBoolean eglStreamConsumerAcquireKHR + EGLDisplay dpy + EGLStreamKHR stream + + + EGLBoolean eglStreamConsumerGLTextureExternalKHR + EGLDisplay dpy + EGLStreamKHR stream + + + EGLBoolean eglStreamConsumerOutputEXT + EGLDisplay dpy + EGLStreamKHR stream + EGLOutputLayerEXT layer + + + EGLBoolean eglStreamConsumerReleaseKHR + EGLDisplay dpy + EGLStreamKHR stream + + + EGLBoolean eglSurfaceAttrib + EGLDisplay dpy + EGLSurface surface + EGLint attribute + EGLint value + + + EGLBoolean eglSwapBuffers + EGLDisplay dpy + EGLSurface surface + + + EGLBoolean eglSwapBuffersWithDamageEXT + EGLDisplay dpy + EGLSurface surface + EGLint *rects + EGLint n_rects + + + EGLBoolean eglSwapBuffersWithDamageKHR + EGLDisplay dpy + EGLSurface surface + EGLint *rects + EGLint n_rects + + + EGLBoolean eglSwapBuffersRegionNOK + EGLDisplay dpy + EGLSurface surface + EGLint numRects + const EGLint *rects + + + EGLBoolean eglSwapBuffersRegion2NOK + EGLDisplay dpy + EGLSurface surface + EGLint numRects + const EGLint *rects + + + EGLBoolean eglSwapInterval + EGLDisplay dpy + EGLint interval + + + EGLBoolean eglTerminate + EGLDisplay dpy + + + EGLBoolean eglUnlockSurfaceKHR + EGLDisplay dpy + EGLSurface surface + + + EGLBoolean eglWaitClient + + + EGLBoolean eglWaitGL + + + EGLBoolean eglWaitNative + EGLint engine + + + EGLBoolean eglWaitSync + EGLDisplay dpy + EGLSync sync + EGLint flags + + + EGLint eglWaitSyncKHR + EGLDisplay dpy + EGLSyncKHR sync + EGLint flags + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/egl/generate/eglFunctionList.py b/src/egl/generate/eglFunctionList.py new file mode 100644 index 00000000000..80cb83437c0 --- /dev/null +++ b/src/egl/generate/eglFunctionList.py @@ -0,0 +1,199 @@ +#!/usr/bin/env python + +""" +Contains a list of EGL functions to generate dispatch functions for. + +This is used from gen_egl_dispatch.py. + +EGL_FUNCTIONS is a sequence of (name, eglData) pairs, where name is the name +of the function, and eglData is a dictionary containing data about that +function. + +The values in the eglData dictionary are: +- method (string): + How to select a vendor library. See "Method values" below. + +- prefix (string): + This string is prepended to the name of the dispatch function. If + unspecified, the default is "" (an empty string). + +- static (boolean) + If True, this function should be declared static. + +- "public" (boolean) + If True, the function should be exported from the library. Vendor libraries + generally should not use this. + +- extension (string): + If specified, this is the name of a macro to check for before defining a + function. Used for checking for extension macros and such. + +- retval (string): + If specified, this is a C expression with the default value to return if we + can't find a function to call. By default, it will try to guess from the + return type: EGL_NO_whatever for the various handle types, NULL for + pointers, and zero for everything else. + +method values: +- "custom" + The dispatch stub will be hand-written instead of generated. + +- "none" + No dispatch function exists at all, but the function should still have an + entry in the index array. This is for other functions that a stub may need + to call that are implemented in libEGL itself. + +- "display" + Select a vendor from an EGLDisplay argument. + +- "device" + Select a vendor from an EGLDeviceEXT argument. + +- "current" + Select the vendor that owns the current context. +""" + +def _eglFunc(name, method, static=None, public=False, inheader=None, prefix="dispatch_", extension=None, retval=None): + """ + A convenience function to define an entry in the EGL function list. + """ + if static is None: + static = (not public and method != "custom") + if inheader is None: + inheader = (not static) + values = { + "method" : method, + "prefix" : prefix, + "extension" : extension, + "retval" : retval, + "static" : static, + "public" : public, + "inheader" : inheader, + } + return (name, values) + +EGL_FUNCTIONS = ( + # EGL_VERSION_1_0 + _eglFunc("eglChooseConfig", "none"), + _eglFunc("eglCopyBuffers", "none"), + _eglFunc("eglCreateContext", "none"), + _eglFunc("eglCreatePbufferSurface", "none"), + _eglFunc("eglCreatePixmapSurface", "none"), + _eglFunc("eglCreateWindowSurface", "none"), + _eglFunc("eglDestroyContext", "none"), + _eglFunc("eglDestroySurface", "none"), + _eglFunc("eglGetConfigAttrib", "none"), + _eglFunc("eglGetConfigs", "none"), + _eglFunc("eglQueryContext", "none"), + _eglFunc("eglQuerySurface", "none"), + _eglFunc("eglSwapBuffers", "none"), + _eglFunc("eglWaitGL", "none"), + _eglFunc("eglWaitNative", "none"), + _eglFunc("eglTerminate", "none"), + _eglFunc("eglInitialize", "none"), + + _eglFunc("eglGetCurrentDisplay", "none"), + _eglFunc("eglGetCurrentSurface", "none"), + _eglFunc("eglGetDisplay", "none"), + _eglFunc("eglGetError", "none"), + _eglFunc("eglGetProcAddress", "none"), + _eglFunc("eglMakeCurrent", "none"), + _eglFunc("eglQueryString", "none"), + + # EGL_VERSION_1_1 + _eglFunc("eglBindTexImage", "none"), + _eglFunc("eglReleaseTexImage", "none"), + _eglFunc("eglSurfaceAttrib", "none"), + _eglFunc("eglSwapInterval", "none"), + + # EGL_VERSION_1_2 + _eglFunc("eglCreatePbufferFromClientBuffer", "none"), + _eglFunc("eglWaitClient", "none"), + _eglFunc("eglBindAPI", "none"), + _eglFunc("eglQueryAPI", "none"), + _eglFunc("eglReleaseThread", "none"), + + # EGL_VERSION_1_4 + _eglFunc("eglGetCurrentContext", "none"), + + # EGL_VERSION_1_5 + _eglFunc("eglCreateSync", "none"), + _eglFunc("eglDestroySync", "none"), + _eglFunc("eglClientWaitSync", "none"), + _eglFunc("eglGetSyncAttrib", "none"), + _eglFunc("eglCreateImage", "none"), + _eglFunc("eglDestroyImage", "none"), + _eglFunc("eglCreatePlatformWindowSurface", "none"), + _eglFunc("eglCreatePlatformPixmapSurface", "none"), + _eglFunc("eglWaitSync", "none"), + _eglFunc("eglGetPlatformDisplay", "none"), + + # EGL_EXT_platform_base + _eglFunc("eglCreatePlatformWindowSurfaceEXT", "display"), + _eglFunc("eglCreatePlatformPixmapSurfaceEXT", "display"), + _eglFunc("eglGetPlatformDisplayEXT", "none"), + + # TODO: Most of these extensions should be provided by the vendor + # libraries, not by libEGL. They're here now to make testing everything + # else easier. + + # EGL_EXT_swap_buffers_with_damage + _eglFunc("eglSwapBuffersWithDamageEXT", "display"), + + # KHR_EXT_swap_buffers_with_damage + _eglFunc("eglSwapBuffersWithDamageKHR", "display"), + + # EGL_KHR_cl_event2 + _eglFunc("eglCreateSync64KHR", "display"), + + # EGL_KHR_fence_sync + _eglFunc("eglCreateSyncKHR", "display"), + _eglFunc("eglDestroySyncKHR", "display"), + _eglFunc("eglClientWaitSyncKHR", "display"), + _eglFunc("eglGetSyncAttribKHR", "display"), + + # EGL_KHR_image + _eglFunc("eglCreateImageKHR", "display"), + _eglFunc("eglDestroyImageKHR", "display"), + + # EGL_KHR_image_base + # eglCreateImageKHR already defined in EGL_KHR_image + # eglDestroyImageKHR already defined in EGL_KHR_image + + # EGL_KHR_reusable_sync + _eglFunc("eglSignalSyncKHR", "display"), + # eglCreateSyncKHR already defined in EGL_KHR_fence_sync + # eglDestroySyncKHR already defined in EGL_KHR_fence_sync + # eglClientWaitSyncKHR already defined in EGL_KHR_fence_sync + # eglGetSyncAttribKHR already defined in EGL_KHR_fence_sync + + # EGL_KHR_wait_sync + _eglFunc("eglWaitSyncKHR", "display"), + + # EGL_MESA_drm_image + _eglFunc("eglCreateDRMImageMESA", "display"), + _eglFunc("eglExportDRMImageMESA", "display"), + + # EGL_MESA_image_dma_buf_export + _eglFunc("eglExportDMABUFImageQueryMESA", "display"), + _eglFunc("eglExportDMABUFImageMESA", "display"), + + # EGL_NOK_swap_region + _eglFunc("eglSwapBuffersRegionNOK", "display"), + + # EGL_NV_post_sub_buffer + _eglFunc("eglPostSubBufferNV", "display"), + + # EGL_WL_bind_wayland_display + _eglFunc("eglCreateWaylandBufferFromImageWL", "display"), + _eglFunc("eglUnbindWaylandDisplayWL", "display"), + _eglFunc("eglQueryWaylandBufferWL", "display"), + _eglFunc("eglBindWaylandDisplayWL", "display"), + + # EGL_CHROMIUM_get_sync_values + _eglFunc("eglGetSyncValuesCHROMIUM", "display"), + + # EGL_ANDROID_native_fence_sync + _eglFunc("eglDupNativeFenceFDANDROID", "display"), +) + diff --git a/src/egl/generate/egl_other.xml b/src/egl/generate/egl_other.xml new file mode 100644 index 00000000000..7fe3a9e2722 --- /dev/null +++ b/src/egl/generate/egl_other.xml @@ -0,0 +1,47 @@ + + + + This file contains any EGL extension functions that are missing from + the normal egl.xml list. + + + + + struct wl_buffer * eglCreateWaylandBufferFromImageWL + EGLDisplay dpy + EGLImage image + + + + EGLBoolean eglUnbindWaylandDisplayWL + EGLDisplay dpy + struct wl_display * display + + + + EGLBoolean eglQueryWaylandBufferWL + EGLDisplay dpy + struct wl_resource * buffer + EGLint attribute + EGLint * value + + + + EGLBoolean eglBindWaylandDisplayWL + EGLDisplay dpy + struct wl_display * display + + + + + EGLBoolean eglGetSyncValuesCHROMIUM + EGLDisplay display + EGLSurface surface + EGLuint64KHR * ust + EGLuint64KHR * msc + EGLuint64KHR * sbc + + + + + diff --git a/src/egl/generate/genCommon.py b/src/egl/generate/genCommon.py new file mode 100644 index 00000000000..d493d7bf29a --- /dev/null +++ b/src/egl/generate/genCommon.py @@ -0,0 +1,223 @@ +#!/usr/bin/env python + +# (C) Copyright 2015, NVIDIA CORPORATION. +# All Rights Reserved. +# +# Permission is hereby granted, free of charge, to any person obtaining a +# copy of this software and associated documentation files (the "Software"), +# to deal in the Software without restriction, including without limitation +# on the rights to use, copy, modify, merge, publish, distribute, sub +# license, and/or sell copies of the Software, and to permit persons to whom +# the Software is furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice (including the next +# paragraph) shall be included in all copies or substantial portions of the +# Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL +# IBM AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +# FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS +# IN THE SOFTWARE. +# +# Authors: +# Kyle Brenneman + +import collections +import re +import sys +import xml.etree.cElementTree as etree + +MAPI_TABLE_NUM_DYNAMIC = 4096 + +_LIBRARY_FEATURE_NAMES = { + # libGL and libGLdiapatch both include every function. + "gl" : None, + "gldispatch" : None, + "opengl" : frozenset(( "GL_VERSION_1_0", "GL_VERSION_1_1", + "GL_VERSION_1_2", "GL_VERSION_1_3", "GL_VERSION_1_4", "GL_VERSION_1_5", + "GL_VERSION_2_0", "GL_VERSION_2_1", "GL_VERSION_3_0", "GL_VERSION_3_1", + "GL_VERSION_3_2", "GL_VERSION_3_3", "GL_VERSION_4_0", "GL_VERSION_4_1", + "GL_VERSION_4_2", "GL_VERSION_4_3", "GL_VERSION_4_4", "GL_VERSION_4_5", + )), + "glesv1" : frozenset(("GL_VERSION_ES_CM_1_0", "GL_OES_point_size_array")), + "glesv2" : frozenset(("GL_ES_VERSION_2_0", "GL_ES_VERSION_3_0", + "GL_ES_VERSION_3_1" "GL_ES_VERSION_3_2", + )), +} + +def getFunctions(xmlFiles): + """ + Reads an XML file and returns all of the functions defined in it. + + xmlFile should be the path to Khronos's gl.xml file. The return value is a + sequence of FunctionDesc objects, ordered by slot number. + """ + roots = [ etree.parse(xmlFile).getroot() for xmlFile in xmlFiles ] + return getFunctionsFromRoots(roots) + +def getFunctionsFromRoots(roots): + functions = {} + for root in roots: + for func in _getFunctionList(root): + functions[func.name] = func + functions = functions.values() + + # Sort the function list by name. + functions = sorted(functions, key=lambda f: f.name) + + # Assign a slot number to each function. This isn't strictly necessary, + # since you can just look at the index in the list, but it makes it easier + # to include the slot when formatting output. + for i in range(len(functions)): + functions[i] = functions[i]._replace(slot=i) + + return functions + +def getExportNamesFromRoots(target, roots): + """ + Goes through the tags from gl.xml and returns a set of OpenGL + functions that a library should export. + + target should be one of "gl", "gldispatch", "opengl", "glesv1", or + "glesv2". + """ + featureNames = _LIBRARY_FEATURE_NAMES[target] + if featureNames is None: + return set(func.name for func in getFunctionsFromRoots(roots)) + + names = set() + for root in roots: + features = [] + for featElem in root.findall("feature"): + if featElem.get("name") in featureNames: + features.append(featElem) + for featElem in root.findall("extensions/extension"): + if featElem.get("name") in featureNames: + features.append(featElem) + for featElem in features: + for commandElem in featElem.findall("require/command"): + names.add(commandElem.get("name")) + return names + +class FunctionArg(collections.namedtuple("FunctionArg", "type name")): + @property + def dec(self): + """ + Returns a "TYPE NAME" string, suitable for a function prototype. + """ + rv = str(self.type) + if not rv.endswith("*"): + rv += " " + rv += self.name + return rv + +class FunctionDesc(collections.namedtuple("FunctionDesc", "name rt args slot")): + def hasReturn(self): + """ + Returns true if the function returns a value. + """ + return (self.rt != "void") + + @property + def decArgs(self): + """ + Returns a string with the types and names of the arguments, as you + would use in a function declaration. + """ + if not self.args: + return "void" + else: + return ", ".join(arg.dec for arg in self.args) + + @property + def callArgs(self): + """ + Returns a string with the names of the arguments, as you would use in a + function call. + """ + return ", ".join(arg.name for arg in self.args) + + @property + def basename(self): + assert self.name.startswith("gl") + return self.name[2:] + +def _getFunctionList(root): + for elem in root.findall("commands/command"): + yield _parseCommandElem(elem) + +def _parseCommandElem(elem): + protoElem = elem.find("proto") + (rt, name) = _parseProtoElem(protoElem) + + args = [] + for ch in elem.findall("param"): + # tags have the same format as a tag. + args.append(FunctionArg(*_parseProtoElem(ch))) + func = FunctionDesc(name, rt, tuple(args), slot=None) + + return func + +def _parseProtoElem(elem): + # If I just remove the tags and string the text together, I'll get valid C code. + text = _flattenText(elem) + text = text.strip() + m = re.match(r"^(.+)\b(\w+)(?:\s*\[\s*(\d*)\s*\])?$", text, re.S) + if m: + typename = _fixupTypeName(m.group(1)) + name = m.group(2) + if m.group(3): + # HACK: glPathGlyphIndexRangeNV defines an argument like this: + # GLuint baseAndCount[2] + # Convert it to a pointer and hope for the best. + typename += "*" + return (typename, name) + else: + raise ValueError("Can't parse element %r -> %r" % (elem, text)) + +def _flattenText(elem): + """ + Returns the text in an element and all child elements, with the tags + removed. + """ + text = "" + if elem.text is not None: + text = elem.text + for ch in elem: + text += _flattenText(ch) + if ch.tail is not None: + text += ch.tail + return text + +def _fixupTypeName(typeName): + """ + Converts a typename into a more consistent format. + """ + + rv = typeName.strip() + + # Replace "GLvoid" with just plain "void". + rv = re.sub(r"\bGLvoid\b", "void", rv) + + # Remove the vendor suffixes from types that have a suffix-less version. + rv = re.sub(r"\b(GLhalf|GLintptr|GLsizeiptr|GLint64|GLuint64)(?:ARB|EXT|NV|ATI)\b", r"\1", rv) + + rv = re.sub(r"\bGLvoid\b", "void", rv) + + # Clear out any leading and trailing whitespace. + rv = rv.strip() + + # Remove any whitespace before a '*' + rv = re.sub(r"\s+\*", r"*", rv) + + # Change "foo*" to "foo *" + rv = re.sub(r"([^\*])\*", r"\1 *", rv) + + # Condense all whitespace into a single space. + rv = re.sub(r"\s+", " ", rv) + + return rv + diff --git a/src/egl/generate/gen_egl_dispatch.py b/src/egl/generate/gen_egl_dispatch.py new file mode 100644 index 00000000000..eeb3f3f9a5a --- /dev/null +++ b/src/egl/generate/gen_egl_dispatch.py @@ -0,0 +1,250 @@ +#!/usr/bin/env python + +# (C) Copyright 2016, NVIDIA CORPORATION. +# All Rights Reserved. +# +# Permission is hereby granted, free of charge, to any person obtaining a +# copy of this software and associated documentation files (the "Software"), +# to deal in the Software without restriction, including without limitation +# on the rights to use, copy, modify, merge, publish, distribute, sub +# license, and/or sell copies of the Software, and to permit persons to whom +# the Software is furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice (including the next +# paragraph) shall be included in all copies or substantial portions of the +# Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL +# IBM AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +# FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS +# IN THE SOFTWARE. +# +# Authors: +# Kyle Brenneman + +""" +Generates dispatch functions for EGL. + +The list of functions and arguments is read from the Khronos's XML files, with +additional information defined in the module eglFunctionList. +""" + +import argparse +import collections +import imp +import sys +import textwrap + +import genCommon + +def main(): + parser = argparse.ArgumentParser() + parser.add_argument("target", choices=("header", "source"), + help="Whether to build the source or header file.") + parser.add_argument("func_list_file", help="The function list .py file.") + parser.add_argument("xml_files", nargs="+", help="The XML files with the EGL function lists.") + + args = parser.parse_args() + + # The function list is a Python module, but it's specified on the command + # line. + eglFunctionList = imp.load_source("eglFunctionList", args.func_list_file) + + xmlFunctions = genCommon.getFunctions(args.xml_files) + xmlByName = dict((f.name, f) for f in xmlFunctions) + functions = [] + for (name, eglFunc) in eglFunctionList.EGL_FUNCTIONS: + func = xmlByName[name] + eglFunc = fixupEglFunc(func, eglFunc) + functions.append((func, eglFunc)) + + # Sort the function list by name. + functions = sorted(functions, key=lambda f: f[0].name) + + if args.target == "header": + text = generateHeader(functions) + elif args.target == "source": + text = generateSource(functions) + sys.stdout.write(text) + +def fixupEglFunc(func, eglFunc): + result = dict(eglFunc) + if result.get("prefix") is None: + result["prefix"] = "" + + if result.get("extension") is not None: + text = "defined(" + result["extension"] + ")" + result["extension"] = text + + if result["method"] in ("none", "custom"): + return result + + if result["method"] not in ("display", "device", "current"): + raise ValueError("Invalid dispatch method %r for function %r" % (result["method"], func.name)) + + if func.hasReturn(): + if result.get("retval") is None: + result["retval"] = getDefaultReturnValue(func.rt) + + return result + +def generateHeader(functions): + text = textwrap.dedent(r""" + #ifndef G_EGLDISPATCH_STUBS_H + #define G_EGLDISPATCH_STUBS_H + + #ifdef __cplusplus + extern "C" { + #endif + + #include + #include + #include "glvnd/libeglabi.h" + + """.lstrip("\n")) + + text += "enum {\n" + for (func, eglFunc) in functions: + text += generateGuardBegin(func, eglFunc) + text += " __EGL_DISPATCH_" + func.name + ",\n" + text += generateGuardEnd(func, eglFunc) + text += " __EGL_DISPATCH_COUNT\n" + text += "};\n" + + for (func, eglFunc) in functions: + if eglFunc["inheader"]: + text += generateGuardBegin(func, eglFunc) + text += "{f.rt} EGLAPIENTRY {ex[prefix]}{f.name}({f.decArgs});\n".format(f=func, ex=eglFunc) + text += generateGuardEnd(func, eglFunc) + + text += textwrap.dedent(r""" + #ifdef __cplusplus + } + #endif + #endif // G_EGLDISPATCH_STUBS_H + """) + return text + +def generateSource(functions): + # First, sort the function list by name. + text = "" + text += '#include "egldispatchstubs.h"\n' + text += '#include "g_egldispatchstubs.h"\n' + text += "\n" + + for (func, eglFunc) in functions: + if eglFunc["method"] not in ("custom", "none"): + text += generateGuardBegin(func, eglFunc) + text += generateDispatchFunc(func, eglFunc) + text += generateGuardEnd(func, eglFunc) + + text += "\n" + text += "const char * const __EGL_DISPATCH_FUNC_NAMES[__EGL_DISPATCH_COUNT + 1] = {\n" + for (func, eglFunc) in functions: + text += generateGuardBegin(func, eglFunc) + text += ' "' + func.name + '",\n' + text += generateGuardEnd(func, eglFunc) + text += " NULL\n" + text += "};\n" + + text += "const __eglMustCastToProperFunctionPointerType __EGL_DISPATCH_FUNCS[__EGL_DISPATCH_COUNT + 1] = {\n" + for (func, eglFunc) in functions: + text += generateGuardBegin(func, eglFunc) + if eglFunc["method"] != "none": + text += " (__eglMustCastToProperFunctionPointerType) " + eglFunc.get("prefix", "") + func.name + ",\n" + else: + text += " NULL, // " + func.name + "\n" + text += generateGuardEnd(func, eglFunc) + text += " NULL\n" + text += "};\n" + + return text + +def generateGuardBegin(func, eglFunc): + ext = eglFunc.get("extension") + if ext is not None: + return "#if " + ext + "\n" + else: + return "" + +def generateGuardEnd(func, eglFunc): + if eglFunc.get("extension") is not None: + return "#endif\n" + else: + return "" + +def generateDispatchFunc(func, eglFunc): + text = "" + + if eglFunc.get("static"): + text += "static " + elif eglFunc.get("public"): + text += "PUBLIC " + text += textwrap.dedent( + r""" + {f.rt} EGLAPIENTRY {ef[prefix]}{f.name}({f.decArgs}) + {{ + typedef {f.rt} EGLAPIENTRY (* _pfn_{f.name})({f.decArgs}); + """).lstrip("\n").format(f=func, ef=eglFunc) + + if func.hasReturn(): + text += " {f.rt} _ret = {ef[retval]};\n".format(f=func, ef=eglFunc) + + text += " _pfn_{f.name} _ptr_{f.name} = (_pfn_{f.name}) ".format(f=func) + if eglFunc["method"] == "current": + text += "__eglDispatchFetchByCurrent(__EGL_DISPATCH_{f.name});\n".format(f=func) + + elif eglFunc["method"] in ("display", "device"): + if eglFunc["method"] == "display": + lookupFunc = "__eglDispatchFetchByDisplay" + lookupType = "EGLDisplay" + else: + assert eglFunc["method"] == "device" + lookupFunc = "__eglDispatchFetchByDevice" + lookupType = "EGLDeviceEXT" + + lookupArg = None + for arg in func.args: + if arg.type == lookupType: + lookupArg = arg.name + break + if lookupArg is None: + raise ValueError("Can't find %s argument for function %s" % (lookupType, func.name,)) + + text += "{lookupFunc}({lookupArg}, __EGL_DISPATCH_{f.name});\n".format( + f=func, lookupFunc=lookupFunc, lookupArg=lookupArg) + else: + raise ValueError("Unknown dispatch method: %r" % (eglFunc["method"],)) + + text += " if(_ptr_{f.name} != NULL) {{\n".format(f=func) + text += " " + if func.hasReturn(): + text += "_ret = " + text += "_ptr_{f.name}({f.callArgs});\n".format(f=func) + text += " }\n" + + if func.hasReturn(): + text += " return _ret;\n" + text += "}\n" + return text + +def getDefaultReturnValue(typename): + if typename.endswith("*"): + return "NULL" + elif typename == "EGLDisplay": + return "EGL_NO_DISPLAY" + elif typename == "EGLContext": + return "EGL_NO_CONTEXT" + elif typename == "EGLSurface": + return "EGL_NO_SURFACE" + elif typename == "EGLBoolean": + return "EGL_FALSE"; + + return "0" + +if __name__ == "__main__": + main() + diff --git a/src/egl/main/50_mesa.json b/src/egl/main/50_mesa.json new file mode 100644 index 00000000000..8aaaa100ffa --- /dev/null +++ b/src/egl/main/50_mesa.json @@ -0,0 +1,6 @@ +{ + "file_format_version" : "1.0.0", + "ICD" : { + "library_path" : "libEGL_mesa.so.0" + } +} diff --git a/src/egl/main/eglapi.c b/src/egl/main/eglapi.c index 5694b5a4ca3..fc243a58e8c 100644 --- a/src/egl/main/eglapi.c +++ b/src/egl/main/eglapi.c @@ -657,7 +657,11 @@ eglQueryString(EGLDisplay dpy, EGLint name) _EGLDriver *drv; if (dpy == EGL_NO_DISPLAY && name == EGL_EXTENSIONS) { - RETURN_EGL_SUCCESS(NULL, _eglGlobal.ClientExtensionString); + const char *ret = _eglGetClientExtensionString(); + if (ret != NULL) + RETURN_EGL_SUCCESS(NULL, ret); + else + RETURN_EGL_ERROR(NULL, EGL_BAD_ALLOC, NULL); } disp = _eglLockDisplay(dpy); diff --git a/src/egl/main/egldispatchstubs.c b/src/egl/main/egldispatchstubs.c new file mode 100644 index 00000000000..e02abd7a9e0 --- /dev/null +++ b/src/egl/main/egldispatchstubs.c @@ -0,0 +1,110 @@ +#include "egldispatchstubs.h" +#include "g_egldispatchstubs.h" + +#include + +#include "eglcurrent.h" + +static const __EGLapiExports *exports; + +const int __EGL_DISPATCH_FUNC_COUNT = __EGL_DISPATCH_COUNT; +int __EGL_DISPATCH_FUNC_INDICES[__EGL_DISPATCH_COUNT + 1]; + +static int FindProcIndex(const char *name) +{ + unsigned first = 0; + unsigned last = __EGL_DISPATCH_COUNT - 1; + + while (first <= last) { + unsigned middle = (first + last) / 2; + int comp = strcmp(name, + __EGL_DISPATCH_FUNC_NAMES[middle]); + + if (comp > 0) + first = middle + 1; + else if (comp < 0) + last = middle - 1; + else + return middle; + } + + /* Just point to the dummy entry at the end of the respective table */ + return __EGL_DISPATCH_COUNT; +} + +void __eglInitDispatchStubs(const __EGLapiExports *exportsTable) +{ + int i; + exports = exportsTable; + for (i=0; i<__EGL_DISPATCH_FUNC_COUNT; i++) { + __EGL_DISPATCH_FUNC_INDICES[i] = -1; + } +} + +void __eglSetDispatchIndex(const char *name, int dispatchIndex) +{ + int index = FindProcIndex(name); + __EGL_DISPATCH_FUNC_INDICES[index] = dispatchIndex; +} + +void *__eglDispatchFindDispatchFunction(const char *name) +{ + int index = FindProcIndex(name); + return (void *) __EGL_DISPATCH_FUNCS[index]; +} + +static __eglMustCastToProperFunctionPointerType FetchVendorFunc(__EGLvendorInfo *vendor, + int index, EGLint errorCode) +{ + __eglMustCastToProperFunctionPointerType func = NULL; + + if (vendor != NULL) { + func = exports->fetchDispatchEntry(vendor, __EGL_DISPATCH_FUNC_INDICES[index]); + } + if (func == NULL) { + if (errorCode != EGL_SUCCESS) { + _eglError(errorCode, __EGL_DISPATCH_FUNC_NAMES[index]); + } + return NULL; + } + + if (!exports->setLastVendor(vendor)) { + // Don't bother trying to set an error code in libglvnd. If + // setLastVendor failed, then setEGLError would also fail. + _eglError(errorCode, __EGL_DISPATCH_FUNC_NAMES[index]); + return NULL; + } + + return func; +} + +__eglMustCastToProperFunctionPointerType __eglDispatchFetchByCurrent(int index) +{ + __EGLvendorInfo *vendor; + + // Note: This is only used for the eglWait* functions. For those, if + // there's no current context, then they're supposed to do nothing but + // return success. + exports->threadInit(); + vendor = exports->getCurrentVendor(); + return FetchVendorFunc(vendor, index, EGL_SUCCESS); +} + +__eglMustCastToProperFunctionPointerType __eglDispatchFetchByDisplay(EGLDisplay dpy, int index) +{ + __EGLvendorInfo *vendor; + + exports->threadInit(); + vendor = exports->getVendorFromDisplay(dpy); + return FetchVendorFunc(vendor, index, EGL_BAD_DISPLAY); +} + +__eglMustCastToProperFunctionPointerType __eglDispatchFetchByDevice(EGLDeviceEXT dev, int index) +{ + __EGLvendorInfo *vendor; + + exports->threadInit(); + vendor = exports->getVendorFromDevice(dev); + return FetchVendorFunc(vendor, index, EGL_BAD_DEVICE_EXT); +} + diff --git a/src/egl/main/egldispatchstubs.h b/src/egl/main/egldispatchstubs.h new file mode 100644 index 00000000000..7861ea5e61a --- /dev/null +++ b/src/egl/main/egldispatchstubs.h @@ -0,0 +1,26 @@ +#ifndef EGLDISPATCHSTUBS_H +#define EGLDISPATCHSTUBS_H + +#include "glvnd/libeglabi.h" + +// These variables are all generated along with the dispatch stubs. +extern const int __EGL_DISPATCH_FUNC_COUNT; +extern const char * const __EGL_DISPATCH_FUNC_NAMES[]; +extern int __EGL_DISPATCH_FUNC_INDICES[]; +extern const __eglMustCastToProperFunctionPointerType __EGL_DISPATCH_FUNCS[]; + +void __eglInitDispatchStubs(const __EGLapiExports *exportsTable); +void __eglSetDispatchIndex(const char *name, int index); + +/** + * Returns the dispatch function for the given name, or \c NULL if the function + * isn't supported. + */ +void *__eglDispatchFindDispatchFunction(const char *name); + +// Helper functions used by the generated stubs. +__eglMustCastToProperFunctionPointerType __eglDispatchFetchByDisplay(EGLDisplay dpy, int index); +__eglMustCastToProperFunctionPointerType __eglDispatchFetchByDevice(EGLDeviceEXT dpy, int index); +__eglMustCastToProperFunctionPointerType __eglDispatchFetchByCurrent(int index); + +#endif // EGLDISPATCHSTUBS_H diff --git a/src/egl/main/eglglobals.c b/src/egl/main/eglglobals.c index cb41063e321..baf96bb1ec5 100644 --- a/src/egl/main/eglglobals.c +++ b/src/egl/main/eglglobals.c @@ -29,6 +29,8 @@ #include +#include +#include #include #include "c11/threads.h" @@ -50,9 +52,13 @@ struct _egl_global _eglGlobal = _eglFiniDisplay }, - /* ClientExtensionString */ + /* ClientOnlyExtensionString */ "EGL_EXT_client_extensions" " EGL_EXT_platform_base" + " EGL_KHR_client_get_all_proc_addresses" + " EGL_KHR_debug", + + /* PlatformExtensionString */ #ifdef HAVE_WAYLAND_PLATFORM " EGL_EXT_platform_wayland" #endif @@ -65,8 +71,9 @@ struct _egl_global _eglGlobal = #ifdef HAVE_SURFACELESS_PLATFORM " EGL_MESA_platform_surfaceless" #endif - " EGL_KHR_client_get_all_proc_addresses" - " EGL_KHR_debug", + "", + + NULL, /* ClientExtensionsString */ NULL, /* debugCallback */ _EGL_DEBUG_BIT_CRITICAL | _EGL_DEBUG_BIT_ERROR, /* debugTypesEnabled */ @@ -101,3 +108,37 @@ _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; +} diff --git a/src/egl/main/eglglobals.h b/src/egl/main/eglglobals.h index ec4f3d04a36..c6ef59d4820 100644 --- a/src/egl/main/eglglobals.h +++ b/src/egl/main/eglglobals.h @@ -57,7 +57,15 @@ struct _egl_global EGLint NumAtExitCalls; void (*AtExitCalls[10])(void); - const char *ClientExtensionString; + /* + * Under libglvnd, the client extension string has to be split into two + * strings, one for platform extensions, and one for everything else. So, + * define separate strings for them. _eglGetClientExtensionString will + * concatenate them together for a non-libglvnd build. + */ + const char *ClientOnlyExtensionString; + const char *PlatformExtensionString; + char *ClientExtensionString; EGLDEBUGPROCKHR debugCallback; unsigned int debugTypesEnabled; @@ -76,4 +84,7 @@ static inline unsigned int DebugBitFromType(EGLenum type) return (1 << (type - EGL_DEBUG_MSG_CRITICAL_KHR)); } +extern const char * +_eglGetClientExtensionString(void); + #endif /* EGLGLOBALS_INCLUDED */ diff --git a/src/egl/main/eglglvnd.c b/src/egl/main/eglglvnd.c new file mode 100644 index 00000000000..6b984ed6c28 --- /dev/null +++ b/src/egl/main/eglglvnd.c @@ -0,0 +1,82 @@ +#include +#include + +#include + +#include "eglcurrent.h" +#include "egldispatchstubs.h" +#include "eglglobals.h" + +static const __EGLapiExports *__eglGLVNDApiExports = NULL; + +static const char * EGLAPIENTRY +__eglGLVNDQueryString(EGLDisplay dpy, EGLenum name) +{ + // For client extensions, return the list of non-platform extensions. The + // platform extensions are returned by __eglGLVNDGetVendorString. + if (dpy == EGL_NO_DISPLAY && name == EGL_EXTENSIONS) + return _eglGlobal.ClientOnlyExtensionString; + + // For everything else, forward to the normal eglQueryString function. + return eglQueryString(dpy, name); +} + +static const char * +__eglGLVNDGetVendorString(int name) +{ + if (name == __EGL_VENDOR_STRING_PLATFORM_EXTENSIONS) { + const char *str = _eglGlobal.PlatformExtensionString; + // The platform extension string may have a leading space. If it does, + // then skip over it. + while (*str == ' ') { + str++; + } + return str; + } + + return NULL; +} + +static EGLDisplay +__eglGLVNDGetPlatformDisplay(EGLenum platform, void *native_display, + const EGLAttrib *attrib_list) +{ + if (platform == EGL_NONE) { + assert(native_display == (void *) EGL_DEFAULT_DISPLAY); + assert(attrib_list == NULL); + return eglGetDisplay((EGLNativeDisplayType) native_display); + } else { + return eglGetPlatformDisplay(platform, native_display, attrib_list); + } +} + +static void * +__eglGLVNDGetProcAddress(const char *procName) +{ + if (strcmp(procName, "eglQueryString") == 0) + return (void *) __eglGLVNDQueryString; + + return (void *) eglGetProcAddress(procName); +} + +EGLAPI EGLBoolean +__egl_Main(uint32_t version, const __EGLapiExports *exports, + __EGLvendorInfo *vendor, __EGLapiImports *imports) +{ + if (EGL_VENDOR_ABI_GET_MAJOR_VERSION(version) != + EGL_VENDOR_ABI_MAJOR_VERSION) + return EGL_FALSE; + + __eglGLVNDApiExports = exports; + __eglInitDispatchStubs(exports); + + imports->getPlatformDisplay = __eglGLVNDGetPlatformDisplay; + imports->getSupportsAPI = _eglIsApiValid; + imports->getVendorString = __eglGLVNDGetVendorString; + imports->getProcAddress = __eglGLVNDGetProcAddress; + imports->getDispatchAddress = __eglDispatchFindDispatchFunction; + imports->setDispatchIndex = __eglSetDispatchIndex; + + return EGL_TRUE; +} + diff --git a/src/glx/Makefile.am b/src/glx/Makefile.am index 5c0376408cc..41e4939a0b7 100644 --- a/src/glx/Makefile.am +++ b/src/glx/Makefile.am @@ -155,7 +155,7 @@ libglx_la_LIBADD += \ $(builddir)/windows/libwindowsglx.la endif -if USE_LIBGLVND_GLX +if USE_LIBGLVND AM_CFLAGS += \ -DGL_LIB_NAME=\"lib@GL_LIB@.so.0\" \ $(GLVND_CFLAGS) diff --git a/src/glx/glxclient.h b/src/glx/glxclient.h index 70733acb23f..0d29e5635e9 100644 --- a/src/glx/glxclient.h +++ b/src/glx/glxclient.h @@ -56,7 +56,7 @@ #include "glxextensions.h" -#if defined(USE_LIBGLVND_GLX) +#if defined(USE_LIBGLVND) #define _GLX_PUBLIC _X_HIDDEN #else #define _GLX_PUBLIC _X_EXPORT -- 2.30.2