diff --git a/src/backends/meta-egl-ext.h b/src/backends/meta-egl-ext.h new file mode 100644 index 000000000..eff850866 --- /dev/null +++ b/src/backends/meta-egl-ext.h @@ -0,0 +1,52 @@ +/* + * Copyright 2008 Tungsten Graphics, Inc., Cedar Park, Texas. + * 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 the rights to use, copy, modify, merge, publish, + * distribute, sublicense, 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 + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * 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. + */ + +#ifndef META_EGL_EXT_H +#define META_EGL_EXT_H + +#include +#include + +/* + * FIXME: Remove both EGL_EXT_stream_acquire_mode and + * EGL_NV_output_drm_flip_event definitions below once both extensions + * get published by Khronos and incorportated into Khronos' header files + */ +#ifndef EGL_EXT_stream_acquire_mode +#define EGL_EXT_stream_acquire_mode 1 +#define EGL_CONSUMER_AUTO_ACQUIRE_EXT 0x332B +typedef EGLBoolean (EGLAPIENTRYP PFNEGLSTREAMCONSUMERACQUIREATTRIBEXTPROC) (EGLDisplay dpy, EGLStreamKHR stream, const EGLAttrib *attrib_list); +#ifdef EGL_EGLEXT_PROTOTYPES +EGLAPI EGLBoolean EGLAPIENTRY eglStreamConsumerAcquireAttribEXT (EGLDisplay dpy, EGLStreamKHR stream, const EGLAttrib *attrib_list); +#endif +#endif /* EGL_EXT_stream_acquire_mode */ + +#ifndef EGL_NV_output_drm_flip_event +#define EGL_NV_output_drm_flip_event 1 +#define EGL_DRM_FLIP_EVENT_DATA_NV 0x333E +#endif /* EGL_NV_output_drm_flip_event */ + +#endif /* META_EGL_EXT_H */ diff --git a/src/backends/meta-egl.c b/src/backends/meta-egl.c index 499b04f35..a1da5d2ad 100644 --- a/src/backends/meta-egl.c +++ b/src/backends/meta-egl.c @@ -26,6 +26,7 @@ #include "backends/meta-backend-private.h" #include "backends/meta-egl.h" +#include "backends/meta-egl-ext.h" #include "meta/util.h" #include @@ -39,6 +40,24 @@ struct _MetaEgl GObject parent; PFNEGLGETPLATFORMDISPLAYEXTPROC eglGetPlatformDisplayEXT; + + PFNEGLQUERYDEVICESEXTPROC eglQueryDevicesEXT; + PFNEGLQUERYDEVICESTRINGEXTPROC eglQueryDeviceStringEXT; + + PFNEGLGETOUTPUTLAYERSEXTPROC eglGetOutputLayersEXT; + PFNEGLQUERYOUTPUTLAYERATTRIBEXTPROC eglQueryOutputLayerAttribEXT; + + PFNEGLCREATESTREAMKHRPROC eglCreateStreamKHR; + PFNEGLDESTROYSTREAMKHRPROC eglDestroyStreamKHR; + PFNEGLQUERYSTREAMKHRPROC eglQueryStreamKHR; + + PFNEGLCREATESTREAMPRODUCERSURFACEKHRPROC eglCreateStreamProducerSurfaceKHR; + + PFNEGLSTREAMCONSUMEROUTPUTEXTPROC eglStreamConsumerOutputEXT; + + PFNEGLSTREAMCONSUMERACQUIREATTRIBEXTPROC eglStreamConsumerAcquireAttribEXT; + + PFNEGLSTREAMCONSUMERGLTEXTUREEXTERNALKHRPROC eglStreamConsumerGLTextureExternalKHR; }; G_DEFINE_TYPE (MetaEgl, meta_egl, G_TYPE_OBJECT) @@ -305,6 +324,266 @@ meta_egl_get_platform_display (MetaEgl *egl, return display; } +gboolean +meta_egl_query_devices (MetaEgl *egl, + EGLint max_devices, + EGLDeviceEXT *devices, + EGLint *num_devices, + GError **error) +{ + if (!is_egl_proc_valid (egl->eglQueryDevicesEXT, error)) + return FALSE; + + if (!egl->eglQueryDevicesEXT (max_devices, + devices, + num_devices)) + { + set_egl_error (error); + return FALSE; + } + + return TRUE; +} + +const char * +meta_egl_query_device_string (MetaEgl *egl, + EGLDeviceEXT device, + EGLint name, + GError **error) +{ + const char *device_string; + + if (!is_egl_proc_valid (egl->eglQueryDeviceStringEXT, error)) + return NULL; + + device_string = egl->eglQueryDeviceStringEXT (device, name); + if (!device_string) + { + set_egl_error (error); + return NULL; + } + + return device_string; +} + +gboolean +meta_egl_egl_device_has_extensions (MetaEgl *egl, + EGLDeviceEXT device, + char ***missing_extensions, + char *first_extension, + ...) +{ + va_list var_args; + const char *extensions_str; + gboolean has_extensions; + GError *error = NULL; + + extensions_str = meta_egl_query_device_string (egl, device, EGL_EXTENSIONS, + &error); + if (!extensions_str) + { + g_warning ("Failed to query device string: %s", error->message); + g_error_free (error); + return FALSE; + } + + va_start (var_args, first_extension); + has_extensions = extensions_string_has_extensions_valist (extensions_str, + missing_extensions, + first_extension, + var_args); + va_end (var_args); + + return has_extensions; +} + +gboolean +meta_egl_get_output_layers (MetaEgl *egl, + EGLDisplay display, + const EGLAttrib *attrib_list, + EGLOutputLayerEXT *layers, + EGLint max_layers, + EGLint *num_layers, + GError **error) +{ + if (!is_egl_proc_valid (egl->eglGetOutputLayersEXT, error)) + return FALSE; + + if (!egl->eglGetOutputLayersEXT (display, + attrib_list, + layers, + max_layers, + num_layers)) + { + set_egl_error (error); + return FALSE; + } + + return TRUE; +} + +gboolean +meta_egl_query_output_layer_attrib (MetaEgl *egl, + EGLDisplay display, + EGLOutputLayerEXT layer, + EGLint attribute, + EGLAttrib *value, + GError **error) +{ + if (!is_egl_proc_valid (egl->eglQueryOutputLayerAttribEXT, error)) + return FALSE; + + if (!egl->eglQueryOutputLayerAttribEXT (display, layer, + attribute, value)) + { + set_egl_error (error); + return FALSE; + } + + return TRUE; +} + +EGLStreamKHR +meta_egl_create_stream (MetaEgl *egl, + EGLDisplay display, + const EGLint *attrib_list, + GError **error) +{ + EGLStreamKHR stream; + + if (!is_egl_proc_valid (egl->eglCreateStreamKHR, error)) + return EGL_NO_STREAM_KHR; + + stream = egl->eglCreateStreamKHR (display, attrib_list); + if (stream == EGL_NO_STREAM_KHR) + { + set_egl_error (error); + return EGL_NO_STREAM_KHR; + } + + return stream; +} + +gboolean +meta_egl_destroy_stream (MetaEgl *egl, + EGLDisplay display, + EGLStreamKHR stream, + GError **error) +{ + if (!is_egl_proc_valid (egl->eglDestroyStreamKHR, error)) + return FALSE; + + if (!egl->eglDestroyStreamKHR (display, stream)) + { + set_egl_error (error); + return FALSE; + } + + return TRUE; +} + +gboolean +meta_egl_query_stream (MetaEgl *egl, + EGLDisplay display, + EGLStreamKHR stream, + EGLenum attribute, + EGLint *value, + GError **error) +{ + if (!is_egl_proc_valid (egl->eglQueryStreamKHR, error)) + return FALSE; + + if (!egl->eglQueryStreamKHR (display, stream, attribute, value)) + { + set_egl_error (error); + return FALSE; + } + + return TRUE; +} + +EGLSurface +meta_egl_create_stream_producer_surface (MetaEgl *egl, + EGLDisplay display, + EGLConfig config, + EGLStreamKHR stream, + const EGLint *attrib_list, + GError **error) +{ + EGLSurface surface; + + if (!is_egl_proc_valid (egl->eglCreateStreamProducerSurfaceKHR, error)) + return EGL_NO_SURFACE; + + surface = egl->eglCreateStreamProducerSurfaceKHR (display, + config, + stream, + attrib_list); + if (surface == EGL_NO_SURFACE) + { + set_egl_error (error); + return EGL_NO_SURFACE; + } + + return surface; +} + +gboolean +meta_egl_stream_consumer_output (MetaEgl *egl, + EGLDisplay display, + EGLStreamKHR stream, + EGLOutputLayerEXT layer, + GError **error) +{ + if (!is_egl_proc_valid (egl->eglStreamConsumerOutputEXT, error)) + return FALSE; + + if (!egl->eglStreamConsumerOutputEXT (display, stream, layer)) + { + set_egl_error (error); + return FALSE; + } + + return TRUE; +} + +gboolean +meta_egl_stream_consumer_acquire_attrib (MetaEgl *egl, + EGLDisplay display, + EGLStreamKHR stream, + EGLAttrib *attrib_list, + GError **error) +{ + if (!is_egl_proc_valid (egl->eglStreamConsumerAcquireAttribEXT, error)) + return FALSE; + + if (!egl->eglStreamConsumerAcquireAttribEXT (display, stream, attrib_list)) + { + set_egl_error (error); + return FALSE; + } + + return TRUE; +} + +gboolean +meta_egl_stream_consumer_gl_texture_external (MetaEgl *egl, + EGLDisplay display, + EGLStreamKHR stream, + GError **error) +{ + if (!is_egl_proc_valid (egl->eglStreamConsumerGLTextureExternalKHR, error)) + return FALSE; + + if (!egl->eglStreamConsumerGLTextureExternalKHR (display, stream)) + { + set_egl_error (error); + return FALSE; + } + + return TRUE; +} + #define GET_EGL_PROC_ADDR(proc) \ egl->proc = (void *) eglGetProcAddress (#proc); @@ -321,6 +600,24 @@ meta_egl_constructed (GObject *object) MetaEgl *egl = META_EGL (object); GET_EGL_PROC_ADDR_REQUIRED (eglGetPlatformDisplayEXT); + + GET_EGL_PROC_ADDR (eglQueryDevicesEXT); + GET_EGL_PROC_ADDR (eglQueryDeviceStringEXT); + + GET_EGL_PROC_ADDR (eglGetOutputLayersEXT); + GET_EGL_PROC_ADDR (eglQueryOutputLayerAttribEXT); + + GET_EGL_PROC_ADDR (eglCreateStreamKHR); + GET_EGL_PROC_ADDR (eglDestroyStreamKHR); + GET_EGL_PROC_ADDR (eglQueryStreamKHR); + + GET_EGL_PROC_ADDR (eglCreateStreamProducerSurfaceKHR); + + GET_EGL_PROC_ADDR (eglStreamConsumerOutputEXT); + + GET_EGL_PROC_ADDR (eglStreamConsumerAcquireAttribEXT); + + GET_EGL_PROC_ADDR (eglStreamConsumerGLTextureExternalKHR); } #undef GET_EGL_PROC_ADDR diff --git a/src/backends/meta-egl.h b/src/backends/meta-egl.h index 40db95052..aa38a5cad 100644 --- a/src/backends/meta-egl.h +++ b/src/backends/meta-egl.h @@ -60,4 +60,77 @@ EGLDisplay meta_egl_get_platform_display (MetaEgl *egl, const EGLint *attrib_list, GError **error); +gboolean meta_egl_query_devices (MetaEgl *egl, + EGLint max_devices, + EGLDeviceEXT *devices, + EGLint *num_devices, + GError **error); + +const char * meta_egl_query_device_string (MetaEgl *egl, + EGLDeviceEXT device, + EGLint name, + GError **error); + +gboolean meta_egl_egl_device_has_extensions (MetaEgl *egl, + EGLDeviceEXT device, + char ***missing_extensions, + char *first_extension, + ...); + +gboolean meta_egl_get_output_layers (MetaEgl *egl, + EGLDisplay display, + const EGLAttrib *attrib_list, + EGLOutputLayerEXT *layers, + EGLint max_layers, + EGLint *num_layers, + GError **error); + +gboolean meta_egl_query_output_layer_attrib (MetaEgl *egl, + EGLDisplay display, + EGLOutputLayerEXT layer, + EGLint attribute, + EGLAttrib *value, + GError **error); + +EGLStreamKHR meta_egl_create_stream (MetaEgl *egl, + EGLDisplay display, + const EGLint *attrib_list, + GError **error); + +gboolean meta_egl_destroy_stream (MetaEgl *egl, + EGLDisplay display, + EGLStreamKHR stream, + GError **error); + +gboolean meta_egl_query_stream (MetaEgl *egl, + EGLDisplay display, + EGLStreamKHR stream, + EGLenum attribute, + EGLint *value, + GError **error); + +EGLSurface meta_egl_create_stream_producer_surface (MetaEgl *egl, + EGLDisplay display, + EGLConfig config, + EGLStreamKHR stream, + const EGLint *attrib_list, + GError **error); + +gboolean meta_egl_stream_consumer_output (MetaEgl *egl, + EGLDisplay display, + EGLStreamKHR stream, + EGLOutputLayerEXT layer, + GError **error); + +gboolean meta_egl_stream_consumer_acquire_attrib (MetaEgl *egl, + EGLDisplay display, + EGLStreamKHR stream, + EGLAttrib *attrib_list, + GError **error); + +gboolean meta_egl_stream_consumer_gl_texture_external (MetaEgl *egl, + EGLDisplay display, + EGLStreamKHR stream, + GError **error); + #endif /* META_EGL_H */