static GstGLAPI gst_gl_context_cocoa_get_gl_api (GstGLContext * context);
static GstGLPlatform gst_gl_context_cocoa_get_gl_platform (GstGLContext * context);
static void gst_gl_context_cocoa_swap_buffers (GstGLContext * context);
+static GstStructure * gst_gl_context_cocoa_get_config (GstGLContext * context);
GST_DEBUG_CATEGORY_STATIC (gst_gl_context_cocoa_debug);
#define GST_CAT_DEFAULT gst_gl_context_cocoa_debug
GST_DEBUG_FUNCPTR (gst_gl_context_cocoa_get_gl_api);
context_class->get_gl_platform =
GST_DEBUG_FUNCPTR (gst_gl_context_cocoa_get_gl_platform);
+ context_class->get_config =
+ GST_DEBUG_FUNCPTR (gst_gl_context_cocoa_get_config);
}
static void
return context->priv->pixel_format;
}
+static GstStructure *
+cgl_pixel_format_to_structure (CGLPixelFormatObj fmt)
+{
+ GstStructure *ret;
+ int val, alpha;
+
+ ret = gst_structure_new (GST_GL_CONFIG_STRUCTURE_NAME,
+ GST_GL_CONFIG_STRUCTURE_SET_ARGS(PLATFORM, GstGLPlatform, GST_GL_PLATFORM_CGL),
+ NULL);
+
+ if (CGLDescribePixelFormat (fmt, 0, kCGLPFAAlphaSize, &alpha) != kCGLNoError)
+ goto failure;
+ gst_structure_set (ret, GST_GL_CONFIG_STRUCTURE_SET_ARGS(ALPHA_SIZE, int, alpha), NULL);
+
+ if (CGLDescribePixelFormat (fmt, 0, kCGLPFADepthSize, &val) != kCGLNoError)
+ goto failure;
+ gst_structure_set (ret, GST_GL_CONFIG_STRUCTURE_SET_ARGS(DEPTH_SIZE, int, val), NULL);
+
+ if (CGLDescribePixelFormat (fmt, 0, kCGLPFAStencilSize, &val) != kCGLNoError)
+ goto failure;
+ gst_structure_set (ret, GST_GL_CONFIG_STRUCTURE_SET_ARGS(STENCIL_SIZE, int, val), NULL);
+
+ if (CGLDescribePixelFormat (fmt, 0, kCGLPFAColorSize, &val) != kCGLNoError)
+ goto failure;
+ val -= alpha;
+ if (val % 3 == 0) {
+ /* XXX: assumes that bits are evenly distributed */
+ gst_structure_set (ret, GST_GL_CONFIG_STRUCTURE_SET_ARGS(RED_SIZE, int, val / 3), NULL);
+ gst_structure_set (ret, GST_GL_CONFIG_STRUCTURE_SET_ARGS(GREEN_SIZE, int, val / 3), NULL);
+ gst_structure_set (ret, GST_GL_CONFIG_STRUCTURE_SET_ARGS(BLUE_SIZE, int, val / 3), NULL);
+ } else {
+ GST_WARNING ("Don't know how to split a color size of %u into R,G,B values",
+ val);
+ goto failure;
+ }
+
+ if (CGLDescribePixelFormat (fmt, 0, kCGLPFASamples, &val) != kCGLNoError)
+ goto failure;
+ gst_structure_set (ret, GST_GL_CONFIG_STRUCTURE_SET_ARGS(SAMPLES, int, val), NULL);
+
+ if (CGLDescribePixelFormat (fmt, 0, kCGLPFASampleBuffers, &val) != kCGLNoError)
+ goto failure;
+ gst_structure_set (ret, GST_GL_CONFIG_STRUCTURE_SET_ARGS(SAMPLE_BUFFERS, int, val), NULL);
+
+ return ret;
+
+failure:
+ gst_structure_free (ret);
+ return NULL;
+}
+
static gboolean
gst_gl_context_cocoa_create_context (GstGLContext *context, GstGLAPI gl_api,
GstGLContext *other_context, GError **error)
{
return (guintptr) CGLGetCurrentContext ();
}
+
+static GstStructure *
+gst_gl_context_cocoa_get_config (GstGLContext * context)
+{
+ GstGLContextCocoa *cocoa = GST_GL_CONTEXT_COCOA (context);
+
+ g_return_val_if_fail (cocoa->priv->pixel_format, NULL);
+
+ return cgl_pixel_format_to_structure (cocoa->priv->pixel_format);
+}
static GstGLAPI gst_gl_context_eagl_get_gl_api (GstGLContext * context);
static GstGLPlatform gst_gl_context_eagl_get_gl_platform (GstGLContext *
context);
+GstStructure *gst_gl_context_eagl_get_config (GstGLContext * context);
struct _GstGLContextEaglPrivate
{
GST_DEBUG_FUNCPTR (gst_gl_context_eagl_get_gl_api);
context_class->get_gl_platform =
GST_DEBUG_FUNCPTR (gst_gl_context_eagl_get_gl_platform);
+ context_class->get_config = GST_DEBUG_FUNCPTR (gst_gl_context_eagl_get_config);
}
static void
return context;
}
+enum EAGLFormat
+{
+ FORMAT_RGBA8 = 1,
+ FORMAT_RGB565,
+};
+
+static GstStructure *
+layer_config_to_structure (GstGLContextEagl *eagl, CAEAGLLayer * layer)
+{
+ GstStructure *ret;
+ NSDictionary *drawableProps = [layer drawableProperties];
+ NSString *color_format;
+ enum EAGLFormat eagl_format = FORMAT_RGBA8;
+
+ ret = gst_structure_new (GST_GL_CONFIG_STRUCTURE_NAME,
+ GST_GL_CONFIG_STRUCTURE_SET_ARGS(PLATFORM, GstGLPlatform, GST_GL_PLATFORM_EAGL),
+ NULL);
+
+ color_format = [drawableProps objectForKey:kEAGLDrawablePropertyColorFormat];
+ if (!color_format)
+ color_format = [layer contentsFormat];
+
+ if (!color_format) {
+ GST_WARNING_OBJECT (eagl, "Could not retrieve color format from layer %p", layer);
+ goto failure;
+ }
+
+ if (color_format == kEAGLColorFormatRGBA8 || color_format == kCAContentsFormatRGBA8Uint) {
+ eagl_format = FORMAT_RGBA8;
+ } else if (color_format == kEAGLColorFormatRGB565) {
+ eagl_format = FORMAT_RGB565;
+ } else {
+ GST_WARNING_OBJECT (eagl, "unknown drawable format: %s", [color_format UTF8String]);
+ goto failure;
+ }
+
+ /* XXX: defaults chosen by _update_layer() */
+ gst_structure_set (ret, GST_GL_CONFIG_STRUCTURE_SET_ARGS(DEPTH_SIZE, int, 16), NULL);
+ gst_structure_set (ret, GST_GL_CONFIG_STRUCTURE_SET_ARGS(STENCIL_SIZE, int, 0), NULL);
+
+ switch (eagl_format) {
+ case FORMAT_RGBA8:
+ gst_structure_set (ret, GST_GL_CONFIG_STRUCTURE_SET_ARGS(RED_SIZE, int, 8), NULL);
+ gst_structure_set (ret, GST_GL_CONFIG_STRUCTURE_SET_ARGS(GREEN_SIZE, int, 8), NULL);
+ gst_structure_set (ret, GST_GL_CONFIG_STRUCTURE_SET_ARGS(BLUE_SIZE, int, 8), NULL);
+ gst_structure_set (ret, GST_GL_CONFIG_STRUCTURE_SET_ARGS(ALPHA_SIZE, int, 8), NULL);
+ break;
+ case FORMAT_RGB565:
+ gst_structure_set (ret, GST_GL_CONFIG_STRUCTURE_SET_ARGS(RED_SIZE, int, 5), NULL);
+ gst_structure_set (ret, GST_GL_CONFIG_STRUCTURE_SET_ARGS(GREEN_SIZE, int, 6), NULL);
+ gst_structure_set (ret, GST_GL_CONFIG_STRUCTURE_SET_ARGS(BLUE_SIZE, int, 5), NULL);
+ gst_structure_set (ret, GST_GL_CONFIG_STRUCTURE_SET_ARGS(ALPHA_SIZE, int, 0), NULL);
+ break;
+ default:
+ GST_WARNING_OBJECT (eagl, "Unhandled format!");
+ goto failure;
+ }
+
+ return ret;
+
+failure:
+ gst_structure_free (ret);
+ return NULL;
+}
+
void
gst_gl_context_eagl_resize (GstGLContextEagl * eagl_context)
{
GstGLContextEagl *context_eagl = GST_GL_CONTEXT_EAGL (context);
GstGLContextEaglPrivate *priv = context_eagl->priv;
GstGLWindow *window = gst_gl_context_get_window (context);
+ GstStructure *fmt;
if (!layer || !gst_gl_window_get_window_handle (window)) {
GST_INFO_OBJECT (context, "window handle not set yet, not updating layer");
priv->color_renderbuffer = color_renderbuffer;
priv->depth_renderbuffer = depth_renderbuffer;
+ fmt = layer_config_to_structure (context_eagl, eagl_layer);
+ if (fmt) {
+ GST_DEBUG_OBJECT (context_eagl, "chosen config %" GST_PTR_FORMAT, fmt);
+ gst_structure_free (fmt);
+ }
+
out:
if (window)
gst_object_unref (window);
{
return (guintptr) [EAGLContext currentContext];
}
+
+GstStructure *
+gst_gl_context_eagl_get_config (GstGLContext * context)
+{
+ GstGLContextEagl *eagl = GST_GL_CONTEXT_EAGL (context);
+
+ if (!eagl->priv->eagl_layer)
+ return NULL;
+
+ return layer_config_to_structure (eagl, (__bridge CAEAGLLayer *) eagl->priv->eagl_layer);
+}
#include "gstglcontext_egl.h"
+#include <gst/gl/gl.h>
#include <gst/gl/gstglcontext_private.h>
-#include <gst/gl/gstglfeature.h>
-#include <gst/gl/gstglwindow.h>
#include "gstegl.h"
#include "../utils/opengl_versions.h"
const gchar * feature);
static void gst_gl_context_egl_get_gl_platform_version (GstGLContext * context,
gint * major, gint * minor);
+static GstStructure *gst_gl_context_egl_get_config (GstGLContext * context);
+static gboolean gst_gl_context_egl_request_config (GstGLContext * context,
+ GstStructure * config);
G_DEFINE_TYPE (GstGLContextEGL, gst_gl_context_egl, GST_TYPE_GL_CONTEXT);
GST_DEBUG_FUNCPTR (gst_gl_context_egl_get_current_context);
context_class->get_gl_platform_version =
GST_DEBUG_FUNCPTR (gst_gl_context_egl_get_gl_platform_version);
+ context_class->get_config = GST_DEBUG_FUNCPTR (gst_gl_context_egl_get_config);
+ context_class->request_config =
+ GST_DEBUG_FUNCPTR (gst_gl_context_egl_request_config);
}
static void
return TRUE;
}
+static GstGLAPI
+egl_conformant_to_gst (int conformant)
+{
+ GstGLAPI ret = GST_GL_API_NONE;
+
+ if (conformant & EGL_OPENGL_BIT)
+ ret |= GST_GL_API_OPENGL | GST_GL_API_OPENGL3;
+ if (conformant & EGL_OPENGL_ES_BIT)
+ ret |= GST_GL_API_GLES1;
+ if (conformant & EGL_OPENGL_ES2_BIT)
+ ret |= GST_GL_API_GLES2;
+#if defined(EGL_KHR_create_context)
+ if (conformant & EGL_OPENGL_ES3_BIT_KHR)
+ /* FIXME: need another gles3 value? */
+ ret |= GST_GL_API_GLES2;
+#endif
+#if 0
+ if (conformant & EGL_OPENVG_BIT)
+ conformant_values[i++] = "OpenVG";
+#endif
+
+ return ret;
+}
+
+static GstGLConfigSurfaceType
+egl_surface_type_to_gst (int surface)
+{
+ GstGLConfigSurfaceType ret = GST_GL_CONFIG_SURFACE_TYPE_NONE;
+
+ if (surface & EGL_WINDOW_BIT)
+ ret |= GST_GL_CONFIG_SURFACE_TYPE_WINDOW;
+ if (surface & EGL_PBUFFER_BIT)
+ ret |= GST_GL_CONFIG_SURFACE_TYPE_PBUFFER;
+#if 0
+ if (surface & EGL_MULTISAMPLE_RESOLVE_BOX_BIT)
+ surface_values[i++] = "multisample-resolve-box";
+ if (surface & EGL_SWAP_BEHAVIOR_PRESERVED_BIT)
+ surface_values[i++] = "swap-behaviour-preserved";
+ if (surface & EGL_VG_ALPHA_FORMAT_PRE_BIT)
+ surface_values[i++] = "vg-alpha-format-pre";
+ if (surface & EGL_VG_COLORSPACE_LINEAR_BIT)
+ surface_values[i++] = "vg-colorspace-linear";
+#endif
+ return ret;
+}
+
+static GstGLConfigCaveat
+egl_caveat_to_gst (int caveat)
+{
+ switch (caveat) {
+ case EGL_NONE:
+ return GST_GL_CONFIG_CAVEAT_NONE;
+ case EGL_SLOW_CONFIG:
+ return GST_GL_CONFIG_CAVEAT_SLOW;
+ case EGL_NON_CONFORMANT_CONFIG:
+ return GST_GL_CONFIG_CAVEAT_NON_CONFORMANT;
+ default:
+ GST_WARNING ("unknown EGL caveat value %u (0x%x)", caveat, caveat);
+ return GST_GL_CONFIG_CAVEAT_NON_CONFORMANT;
+ }
+}
+
+static GstStructure *
+egl_config_to_structure (EGLDisplay egl_display, EGLConfig config)
+{
+ GstStructure *ret;
+ int val;
+ int buffer_type;
+
+ if (!egl_display)
+ return NULL;
+
+ ret = gst_structure_new (GST_GL_CONFIG_STRUCTURE_NAME,
+ GST_GL_CONFIG_STRUCTURE_SET_ARGS (PLATFORM, GstGLPlatform,
+ GST_GL_PLATFORM_EGL), NULL);
+
+ if (!eglGetConfigAttrib (egl_display, config, EGL_CONFIG_ID, &val))
+ goto failure;
+ gst_structure_set (ret, GST_GL_CONFIG_STRUCTURE_SET_ARGS (CONFIG_ID, int,
+ val), NULL);
+
+#if 0
+ {
+ /* Don't know how to translate this value, it's platform and implementation
+ * dependant
+ */
+ int native_visual_type;
+ if (!eglGetConfigAttrib (egl_display, config, EGL_NATIVE_VISUAL_TYPE,
+ &native_visual_type))
+ goto failure;
+ }
+#endif
+
+ if (!eglGetConfigAttrib (egl_display, config, EGL_NATIVE_VISUAL_ID, &val))
+ goto failure;
+ gst_structure_set (ret, GST_GL_CONFIG_STRUCTURE_SET_ARGS (NATIVE_VISUAL_ID,
+ guint, val), NULL);
+
+ if (!eglGetConfigAttrib (egl_display, config, EGL_NATIVE_RENDERABLE, &val))
+ goto failure;
+ gst_structure_set (ret, GST_GL_CONFIG_STRUCTURE_SET_ARGS (NATIVE_RENDERABLE,
+ gboolean, val), NULL);
+
+ if (!eglGetConfigAttrib (egl_display, config, EGL_CONFORMANT, &val))
+ goto failure;
+ gst_structure_set (ret, GST_GL_CONFIG_STRUCTURE_SET_ARGS (CONFORMANT_API,
+ GstGLAPI, egl_conformant_to_gst (val)), NULL);
+
+ if (!eglGetConfigAttrib (egl_display, config, EGL_RENDERABLE_TYPE, &val))
+ goto failure;
+ gst_structure_set (ret, GST_GL_CONFIG_STRUCTURE_SET_ARGS (RENDERABLE_API,
+ GstGLAPI, egl_conformant_to_gst (val)), NULL);
+
+ if (!eglGetConfigAttrib (egl_display, config, EGL_SURFACE_TYPE, &val))
+ goto failure;
+ gst_structure_set (ret, GST_GL_CONFIG_STRUCTURE_SET_ARGS (SURFACE_TYPE,
+ GstGLConfigSurfaceType, egl_surface_type_to_gst (val)), NULL);
+
+ if (!eglGetConfigAttrib (egl_display, config, EGL_CONFIG_CAVEAT, &val))
+ goto failure;
+ gst_structure_set (ret, GST_GL_CONFIG_STRUCTURE_SET_ARGS (CAVEAT,
+ GstGLConfigCaveat, egl_caveat_to_gst (val)), NULL);
+
+ if (!eglGetConfigAttrib (egl_display, config, EGL_LEVEL, &val))
+ goto failure;
+ gst_structure_set (ret, GST_GL_CONFIG_STRUCTURE_SET_ARGS (LEVEL, int, val),
+ NULL);
+
+
+ if (!eglGetConfigAttrib (egl_display, config, EGL_COLOR_BUFFER_TYPE,
+ &buffer_type))
+ goto failure;
+
+ if (buffer_type == EGL_RGB_BUFFER) {
+ if (!eglGetConfigAttrib (egl_display, config, EGL_RED_SIZE, &val))
+ goto failure;
+ gst_structure_set (ret, GST_GL_CONFIG_STRUCTURE_SET_ARGS (RED_SIZE, int,
+ val), NULL);
+
+ if (!eglGetConfigAttrib (egl_display, config, EGL_GREEN_SIZE, &val))
+ goto failure;
+ gst_structure_set (ret, GST_GL_CONFIG_STRUCTURE_SET_ARGS (GREEN_SIZE, int,
+ val), NULL);
+
+ if (!eglGetConfigAttrib (egl_display, config, EGL_BLUE_SIZE, &val))
+ goto failure;
+ gst_structure_set (ret, GST_GL_CONFIG_STRUCTURE_SET_ARGS (BLUE_SIZE, int,
+ val), NULL);
+
+ if (!eglGetConfigAttrib (egl_display, config, EGL_ALPHA_SIZE, &val))
+ goto failure;
+ gst_structure_set (ret, GST_GL_CONFIG_STRUCTURE_SET_ARGS (ALPHA_SIZE, int,
+ val), NULL);
+ } else if (buffer_type == EGL_LUMINANCE_BUFFER) {
+ if (!eglGetConfigAttrib (egl_display, config, EGL_LUMINANCE_SIZE, &val))
+ goto failure;
+ gst_structure_set (ret, GST_GL_CONFIG_STRUCTURE_SET_ARGS (LUMINANCE_SIZE,
+ int, val), NULL);
+
+ if (!eglGetConfigAttrib (egl_display, config, EGL_ALPHA_SIZE, &val))
+ goto failure;
+ gst_structure_set (ret, GST_GL_CONFIG_STRUCTURE_SET_ARGS (ALPHA_SIZE, int,
+ val), NULL);
+ } else {
+ GST_WARNING ("unknown EGL_COLOR_BUFFER_TYPE value %x", buffer_type);
+ goto failure;
+ }
+
+ if (!eglGetConfigAttrib (egl_display, config, EGL_DEPTH_SIZE, &val))
+ goto failure;
+ gst_structure_set (ret, GST_GL_CONFIG_STRUCTURE_SET_ARGS (DEPTH_SIZE, int,
+ val), NULL);
+
+ if (!eglGetConfigAttrib (egl_display, config, EGL_STENCIL_SIZE, &val))
+ goto failure;
+ gst_structure_set (ret, GST_GL_CONFIG_STRUCTURE_SET_ARGS (STENCIL_SIZE, int,
+ val), NULL);
+
+ if (!eglGetConfigAttrib (egl_display, config, EGL_MIN_SWAP_INTERVAL, &val))
+ goto failure;
+ gst_structure_set (ret, GST_GL_CONFIG_STRUCTURE_SET_ARGS (MIN_SWAP_INTERVAL,
+ int, val), NULL);
+
+ if (!eglGetConfigAttrib (egl_display, config, EGL_MAX_SWAP_INTERVAL, &val))
+ goto failure;
+ gst_structure_set (ret, GST_GL_CONFIG_STRUCTURE_SET_ARGS (MAX_SWAP_INTERVAL,
+ int, val), NULL);
+
+ if (!eglGetConfigAttrib (egl_display, config, EGL_MAX_PBUFFER_WIDTH, &val))
+ goto failure;
+ gst_structure_set (ret, GST_GL_CONFIG_STRUCTURE_SET_ARGS (MAX_PBUFFER_WIDTH,
+ int, val), NULL);
+
+ if (!eglGetConfigAttrib (egl_display, config, EGL_MAX_PBUFFER_HEIGHT, &val))
+ goto failure;
+ gst_structure_set (ret, GST_GL_CONFIG_STRUCTURE_SET_ARGS (MAX_PBUFFER_HEIGHT,
+ int, val), NULL);
+
+ if (!eglGetConfigAttrib (egl_display, config, EGL_MAX_PBUFFER_PIXELS, &val))
+ goto failure;
+ gst_structure_set (ret, GST_GL_CONFIG_STRUCTURE_SET_ARGS (MAX_PBUFFER_PIXELS,
+ int, val), NULL);
+
+ if (!eglGetConfigAttrib (egl_display, config, EGL_SAMPLE_BUFFERS, &val))
+ goto failure;
+ gst_structure_set (ret, GST_GL_CONFIG_STRUCTURE_SET_ARGS (SAMPLE_BUFFERS, int,
+ val), NULL);
+
+ if (!eglGetConfigAttrib (egl_display, config, EGL_SAMPLES, &val))
+ goto failure;
+ gst_structure_set (ret, GST_GL_CONFIG_STRUCTURE_SET_ARGS (SAMPLES, int, val),
+ NULL);
+
+ return ret;
+
+failure:
+ gst_structure_free (ret);
+ return NULL;
+}
+
static void
gst_gl_context_egl_dump_config (GstGLContextEGL * egl, EGLConfig config)
{
{
gboolean create_context;
EGLint numConfigs;
- gint i;
+ gint i, n;
EGLint config_attrib[20];
EGLint egl_api = 0;
EGLBoolean ret = EGL_FALSE;
try_again:
i = 0;
+ n = G_N_ELEMENTS (config_attrib);
config_attrib[i++] = EGL_SURFACE_TYPE;
config_attrib[i++] = surface_type;
config_attrib[i++] = EGL_RENDERABLE_TYPE;
config_attrib[i++] = egl_api;
+
+ if (egl->requested_config) {
+#define TRANSFORM_VALUE(GL_CONF_NAME,EGL_ATTR_NAME) \
+ G_STMT_START { \
+ if (gst_structure_has_field_typed (egl->requested_config, \
+ GST_GL_CONFIG_ATTRIB_NAME(GL_CONF_NAME), \
+ GST_GL_CONFIG_ATTRIB_GTYPE(GL_CONF_NAME))) { \
+ int val; \
+ if (gst_structure_get (egl->requested_config, \
+ GST_GL_CONFIG_ATTRIB_NAME(GL_CONF_NAME), \
+ GST_GL_CONFIG_ATTRIB_GTYPE(GL_CONF_NAME), &val, NULL)) { \
+ config_attrib[i++] = EGL_ATTR_NAME; \
+ config_attrib[i++] = (int) val; \
+ g_assert (i <= n); \
+ } \
+ } \
+ } G_STMT_END
+
+ TRANSFORM_VALUE (CONFIG_ID, EGL_CONFIG_ID);
+ TRANSFORM_VALUE (RED_SIZE, EGL_RED_SIZE);
+ TRANSFORM_VALUE (GREEN_SIZE, EGL_GREEN_SIZE);
+ TRANSFORM_VALUE (BLUE_SIZE, EGL_BLUE_SIZE);
+ TRANSFORM_VALUE (ALPHA_SIZE, EGL_ALPHA_SIZE);
+ TRANSFORM_VALUE (DEPTH_SIZE, EGL_DEPTH_SIZE);
+ TRANSFORM_VALUE (STENCIL_SIZE, EGL_STENCIL_SIZE);
+ /* TODO: more values */
+#undef TRANSFORM_VALUE
+ } else {
#if defined(USE_EGL_RPI) && GST_GL_HAVE_WINDOW_WAYLAND
- /* The configurations with a=0 seems to be buggy whereas
- * it works when using dispmanx directly */
- config_attrib[i++] = EGL_ALPHA_SIZE;
- config_attrib[i++] = 1;
+ /* The configurations with a=0 seems to be buggy whereas
+ * it works when using dispmanx directly */
+ config_attrib[i++] = EGL_ALPHA_SIZE;
+ config_attrib[i++] = 1;
#endif
- config_attrib[i++] = EGL_DEPTH_SIZE;
- config_attrib[i++] = 16;
- config_attrib[i++] = EGL_RED_SIZE;
- config_attrib[i++] = 1;
- config_attrib[i++] = EGL_GREEN_SIZE;
- config_attrib[i++] = 1;
- config_attrib[i++] = EGL_BLUE_SIZE;
- config_attrib[i++] = 1;
+ config_attrib[i++] = EGL_DEPTH_SIZE;
+ config_attrib[i++] = 16;
+ config_attrib[i++] = EGL_RED_SIZE;
+ config_attrib[i++] = 1;
+ config_attrib[i++] = EGL_GREEN_SIZE;
+ config_attrib[i++] = 1;
+ config_attrib[i++] = EGL_BLUE_SIZE;
+ config_attrib[i++] = 1;
+ }
+
config_attrib[i++] = EGL_NONE;
+ g_assert (i <= n);
ret = eglChooseConfig (egl->egl_display, config_attrib,
&egl->egl_config, 1, &numConfigs);
gst_object_unref (egl->display_egl);
egl->display_egl = NULL;
}
+
+ if (egl->requested_config)
+ gst_structure_free (egl->requested_config);
+ egl->requested_config = NULL;
}
static gboolean
*major = context_egl->egl_major;
*minor = context_egl->egl_minor;
}
+
+static GstStructure *
+gst_gl_context_egl_get_config (GstGLContext * context)
+{
+ GstGLContextEGL *egl = GST_GL_CONTEXT_EGL (context);
+
+ g_return_val_if_fail (egl->egl_config, NULL);
+
+ return egl_config_to_structure (egl->egl_display, egl->egl_config);
+}
+
+static gboolean
+gst_gl_context_egl_request_config (GstGLContext * context,
+ GstStructure * config)
+{
+ GstGLContextEGL *egl = GST_GL_CONTEXT_EGL (context);
+
+ if (egl->requested_config)
+ gst_structure_free (egl->requested_config);
+ egl->requested_config = config;
+
+ return TRUE;
+}
+
+gboolean
+gst_gl_context_egl_fill_info (GstGLContext * context)
+{
+ EGLContext egl_context = (EGLContext) gst_gl_context_get_gl_context (context);
+ GstGLDisplay *display_egl;
+ GstStructure *config;
+ EGLDisplay *egl_display;
+ EGLConfig egl_config;
+ int config_id, n_configs;
+ int attrs[3];
+
+ if (!egl_context) {
+ GST_ERROR_OBJECT (context, "no GLX context");
+ return FALSE;
+ }
+
+ display_egl =
+ GST_GL_DISPLAY (gst_gl_display_egl_from_gl_display (context->display));
+ egl_display = (EGLDisplay) gst_gl_display_get_handle (display_egl);
+
+ if (EGL_TRUE != eglQueryContext (egl_display, egl_context, EGL_CONFIG_ID,
+ &config_id)) {
+ GST_WARNING_OBJECT (context,
+ "could not retrieve egl config id from egl context: %s",
+ gst_egl_get_error_string (eglGetError ()));
+ goto failure;
+ }
+
+ attrs[0] = EGL_CONFIG_ID;
+ attrs[1] = config_id;
+ attrs[2] = EGL_NONE;
+
+ if (EGL_TRUE != eglChooseConfig (egl_display, attrs, &egl_config, 1,
+ &n_configs) || n_configs <= 0) {
+ GST_WARNING_OBJECT (context,
+ "could not retrieve egl config from its ID 0x%x. "
+ "Wrong EGLDisplay or context?", config_id);
+ goto failure;
+ }
+
+ config = egl_config_to_structure (egl_display, egl_config);
+ if (!config) {
+ GST_WARNING_OBJECT (context, "could not transform config id 0x%x into "
+ "GstStructure", config_id);
+ goto failure;
+ }
+
+ GST_INFO_OBJECT (context, "found config %" GST_PTR_FORMAT, config);
+
+ g_object_set_data_full (G_OBJECT (context),
+ GST_GL_CONTEXT_WRAPPED_GL_CONFIG_NAME, config,
+ (GDestroyNotify) gst_structure_free);
+
+ gst_object_unref (display_egl);
+ return TRUE;
+
+failure:
+ gst_object_unref (display_egl);
+ return FALSE;
+}
/* Cached handle */
guintptr window_handle;
+
+ GstStructure *requested_config;
};
/**
G_GNUC_INTERNAL
gpointer gst_gl_context_egl_get_proc_address (GstGLAPI gl_api, const gchar * name);
+G_GNUC_INTERNAL
+gboolean gst_gl_context_egl_fill_info (GstGLContext * context);
+
G_END_DECLS
#endif /* __GST_GL_CONTEXT_EGL_H__ */
#include <gst/gl/gstglapi.h>
#include <gst/gl/gstglconfig.h>
#include <gst/gl/gstglcontext.h>
+#include <gst/gl/gstglcontextconfig.h>
#include <gst/gl/gstgldebug.h>
#include <gst/gl/gstgldisplay.h>
#include <gst/gl/gstglfeature.h>
* #GstGLContext wraps an OpenGL context object in a uniform API. As a result
* of the limitation on OpenGL context, this object is not thread safe unless
* specified and must only be activated in a single thread.
+ *
+ * Environment variables:
+ * - `GST_GL_API`: select which OpenGL API to create and OpenGL context for.
+ * Depending on the platform, the available values are
+ * 'opengl', 'opengl3' (core profile), and 'gles2'. See the
+ * the #GstGLAPI enumeration for more details.
+ * - `GST_GL_PLATFORM`: select which OpenGL platform to create an OpenGL
+ * context with. Depending on the platform and the
+ * dependencies available build-time, the available values
+ * are, 'glx', 'egl', 'cgl', 'wgl', and 'eagl'
+ * - `GST_GL_CONFIG`: select the configuration used for creating the OpenGL
+ * context and OpenGL surface. Written out as a GstStructure
+ * that has been serialized to string. e.g.
+ * `GST_GL_CONFIG="gst-gl-context-config,red-size=8,green-size=8,blue-size=8,alpha-size=8,depth-size=16"`.
+ * Not all platforms will support the same level of
+ * functionality.
*/
#ifdef HAVE_CONFIG_H
gint gl_minor;
gchar *gl_exts;
+ GstStructure *requested_config;
};
typedef struct
G_DEFINE_ABSTRACT_TYPE_WITH_PRIVATE (GstGLContext, gst_gl_context,
GST_TYPE_OBJECT);
-#define GST_TYPE_GL_WRAPPED_CONTEXT (gst_gl_wrapped_context_get_type())
-static GType gst_gl_wrapped_context_get_type (void);
G_DEFINE_TYPE (GstGLWrappedContext, gst_gl_wrapped_context,
GST_TYPE_GL_CONTEXT);
-#define GST_GL_WRAPPED_CONTEXT(o) (G_TYPE_CHECK_INSTANCE_CAST((o), GST_TYPE_GL_WRAPPED_CONTEXT, GstGLWrappedContext))
-#define GST_GL_WRAPPED_CONTEXT_CLASS(k) (G_TYPE_CHECK_CLASS((k), GST_TYPE_GL_CONTEXT, GstGLContextClass))
-#define GST_IS_GL_WRAPPED_CONTEXT(o) (G_TYPE_CHECK_INSTANCE_TYPE((o), GST_TYPE_GL_WRAPPED_CONTEXT))
-#define GST_IS_GL_WRAPPED_CONTEXT_CLASS(k) (G_TYPE_CHECK_CLASS_TYPE((k), GST_TYPE_GL_WRAPPED_CONTEXT))
-#define GST_GL_WRAPPED_CONTEXT_GET_CLASS(o) (G_TYPE_INSTANCE_GET_CLASS((o), GST_TYPE_GL_WRAPPED_CONTEXT, GstGLWrappedContextClass))
-
/**
* gst_gl_context_error_quark:
*
context->gl_vtable = NULL;
}
+ if (context->priv->requested_config)
+ gst_structure_free (context->priv->requested_config);
+ context->priv->requested_config = NULL;
+
g_mutex_clear (&context->priv->render_lock);
g_cond_clear (&context->priv->create_cond);
* to share shareable OpenGL objects with. See the OpenGL specification for
* what is shared between OpenGL contexts.
*
- * If an error occurs, and @error is not %NULL, then error will contain details
- * of the error and %FALSE will be returned.
+ * Since 1.20, the configuration can be overriden with the environment variable
+ * `GST_GL_CONFIG` which is a stringified #GstStructure as would be returned
+ * from gst_gl_context_get_config(). If `GST_GL_CONFIG` is not set, then the
+ * config will be chosen from @other_context by calling
+ * gst_gl_context_get_config() on @other_context. Otherwise, a default
+ * configuration is used.
+ *
+ * Calling gst_gl_context_request_config()) before calling
+ * gst_gl_context_create() will override the config from @other_context but
+ * will not override the `GST_GL_CONFIG` environment variable.
+ *
+ * If an error occurs, and @error is not %NULL, then @error will contain
+ * details of the error and %FALSE will be returned.
*
* Should only be called once.
*
const gchar *user_choice;
GError **error;
GstGLContext *other_context;
+ GstStructure *config;
g_mutex_lock (&context->priv->render_lock);
goto failure;
}
+ {
+ const gchar *config_str = g_getenv ("GST_GL_CONFIG");
+ if (config_str) {
+ GstStructure *config = gst_structure_from_string (config_str, NULL);
+ if (!config) {
+ g_set_error (error, GST_GL_CONTEXT_ERROR,
+ GST_GL_CONTEXT_ERROR_WRONG_CONFIG,
+ "could not construct OpenGL config from the \'GST_GL_CONFIG\' "
+ "environment variable");
+ g_free (compiled_api_s);
+ g_free (user_api_s);
+ g_free (display_api_s);
+ goto failure;
+ }
+ if (!gst_gl_context_request_config (context, gst_structure_copy (config))) {
+ GST_WARNING_OBJECT (context,
+ "failed to request config %" GST_PTR_FORMAT, config);
+ } else {
+ GST_INFO_OBJECT (context, "requesting config from environment %"
+ GST_PTR_FORMAT, config);
+ }
+ gst_structure_free (config);
+ } else if (other_context && !context->priv->requested_config) {
+ GstStructure *config = gst_gl_context_get_config (other_context);
+ if (config) {
+ if (!gst_gl_context_request_config (context,
+ gst_structure_copy (config))) {
+ GST_WARNING_OBJECT (context,
+ "failed to request config %" GST_PTR_FORMAT, config);
+ } else {
+ GST_INFO_OBJECT (context, "requesting config from other context %"
+ GST_PTR_FORMAT " %" GST_PTR_FORMAT, other_context, config);
+ }
+ gst_structure_free (config);
+ }
+ }
+ }
+
if (context_class->choose_format &&
!context_class->choose_format (context, error)) {
GST_WARNING_OBJECT (context, "Failed to choose format");
api_string = gst_gl_api_to_string (gl_api);
GST_INFO_OBJECT (context, "available GL APIs: %s", api_string);
+ if ((config = gst_gl_context_get_config (context))) {
+ GST_DEBUG_OBJECT (context, "Chosen config %" GST_PTR_FORMAT, config);
+ gst_structure_free (config);
+ }
+
if (((compiled_api & gl_api & display_api) & user_api) == GST_GL_API_NONE) {
g_set_error (error, GST_GL_CONTEXT_ERROR, GST_GL_CONTEXT_ERROR_WRONG_API,
"failed to create context, context "
gl->IsVertexArray = NULL;
}
+ if (GST_IS_GL_WRAPPED_CONTEXT (context)) {
+ /* XXX: vfunc? */
+#if GST_GL_HAVE_PLATFORM_GLX
+ if (gst_gl_context_get_gl_platform (context) == GST_GL_PLATFORM_GLX
+ && !gst_gl_context_glx_fill_info (context))
+ goto failure;
+#endif
+#if GST_GL_HAVE_PLATFORM_EGL
+ if (gst_gl_context_get_gl_platform (context) == GST_GL_PLATFORM_EGL
+ && !gst_gl_context_egl_fill_info (context))
+ goto failure;
+#endif
+ }
+
return TRUE;
failure:
context_class->swap_buffers (context);
}
+/**
+ * gst_gl_context_get_config:
+ * @context: the #GstGLContext
+ *
+ * Retrieve the OpenGL configuration for this context. The context must
+ * have been successfully created for this function to return a valid value.
+ *
+ * Not all implementations currently support retrieving the config and will
+ * return %NULL when not supported.
+ *
+ * Returns: (transfer full) (nullable): the configuration chosen for this OpenGL context.
+ *
+ * Since: 1.20
+ */
+GstStructure *
+gst_gl_context_get_config (GstGLContext * context)
+{
+ GstGLContextClass *context_class;
+
+ g_return_val_if_fail (GST_IS_GL_CONTEXT (context), NULL);
+ context_class = GST_GL_CONTEXT_GET_CLASS (context);
+ if (!context_class->get_config) {
+ GST_FIXME_OBJECT (context, "does not support retrieving a config");
+ return NULL;
+ }
+
+ return context_class->get_config (context);
+}
+
+/**
+ * gst_gl_context_request_config:
+ * @context: the #GstGLContext
+ * @gl_config: (nullable) (transfer full): a configuration structure for
+ * configuring the OpenGL context
+ *
+ * Set the OpenGL configuration for this context. The context must not
+ * have been created for this function to succeed. Setting a %NULL
+ * @config has the affect of removing any specific configuration request.
+ *
+ * Not all implementations currently support retrieving the config and this
+ * function will return FALSE when not supported.
+ *
+ * Note that calling this function may cause a subsequent
+ * gst_gl_context_create() to fail if @config could not be matched with
+ * the platform-specific configuration.
+ *
+ * Note that the actual config used may be differ from the requested values.
+ *
+ * Returns: whether @gl_config could be successfully set on @context
+ *
+ * Since: 1.20
+ */
+gboolean
+gst_gl_context_request_config (GstGLContext * context, GstStructure * gl_config)
+{
+ GstGLContextClass *context_class;
+ gboolean ret;
+
+ g_return_val_if_fail (GST_IS_GL_CONTEXT (context), FALSE);
+ g_return_val_if_fail (context->priv->created == FALSE, FALSE);
+ context_class = GST_GL_CONTEXT_GET_CLASS (context);
+ if (!context_class->request_config) {
+ gst_structure_free (gl_config);
+ GST_FIXME_OBJECT (context, "does not support requesting a config");
+ return FALSE;
+ }
+
+ ret = context_class->request_config (context, gst_structure_copy (gl_config));
+ if (ret) {
+ if (context->priv->requested_config)
+ gst_structure_free (context->priv->requested_config);
+ context->priv->requested_config = gl_config;
+ } else {
+ gst_structure_free (gl_config);
+ }
+
+ return ret;
+}
+
static GstGLAPI
gst_gl_wrapped_context_get_gl_api (GstGLContext * context)
{
return TRUE;
}
+static gpointer
+_structure_copy_if_set (gpointer data, gpointer user_data)
+{
+ GstStructure *ret = NULL;
+
+ if (data)
+ ret = gst_structure_copy (data);
+ return ret;
+}
+
+static GstStructure *
+gst_gl_wrapped_context_get_config (GstGLContext * context)
+{
+ GstStructure *ret;
+
+ ret = g_object_dup_data (G_OBJECT (context),
+ GST_GL_CONTEXT_WRAPPED_GL_CONFIG_NAME,
+ (GDuplicateFunc) _structure_copy_if_set, NULL);
+ if (ret) {
+ GST_DEBUG_OBJECT (context, "wrapped context found config %" GST_PTR_FORMAT,
+ ret);
+ return ret;
+ } else {
+ GST_FIXME_OBJECT (context, "wrapped context could not retrieve config. "
+ "The application may be missing a call to gst_gl_context_fill_info() "
+ "or the specific platform implemention is not implemented for "
+ "retrieving the config from a wrapped OpenGL context.");
+ return NULL;
+ }
+}
+
static void
gst_gl_wrapped_context_class_init (GstGLWrappedContextClass * klass)
{
context_class->get_gl_platform =
GST_DEBUG_FUNCPTR (gst_gl_wrapped_context_get_gl_platform);
context_class->activate = GST_DEBUG_FUNCPTR (gst_gl_wrapped_context_activate);
+ context_class->get_config =
+ GST_DEBUG_FUNCPTR (gst_gl_wrapped_context_get_config);
}
static void
* @destroy_context: destroy the OpenGL context
* @swap_buffers: swap the default framebuffer's front/back buffers
*/
+/**
+ * GstGLContextClass::get_config:
+ * @context: the #GstGLContext
+ *
+ * Retrieve the configuration in use by this context. See also
+ * gst_gl_context_get_config().
+ *
+ * Returns: (transfer full) (nullable): the configuration chosen for this
+ * #GstGLContext
+ *
+ * Since: 1.20
+ */
+/**
+ * GstGLContextClass::request_config:
+ * @context: the #GstGLContext
+ * @gl_config: (nullable) (transfer full): a configuration structure for
+ * configuring on @context
+ *
+ * Request a configuration for this @context to use.
+ *
+ * Unknown fields within @gl_config should be ignored by subclasses.
+ *
+ * See also gst_gl_context_request_config().
+ *
+ * Returns: Whether @gl_config could be successfull set on @context.
+ *
+ * Since: 1.20
+ */
struct _GstGLContextClass {
GstObjectClass parent_class;
void (*swap_buffers) (GstGLContext *context);
gboolean (*check_feature) (GstGLContext *context, const gchar *feature);
void (*get_gl_platform_version) (GstGLContext *context, gint *major, gint *minor);
+ GstStructure *(*get_config) (GstGLContext * context);
+ gboolean (*request_config) (GstGLContext * context, GstStructure * gl_config);
/*< private >*/
- gpointer _reserved[GST_PADDING];
+ gpointer _reserved[GST_PADDING-2];
};
/* methods */
GstGLAPI available_apis);
GST_GL_API
+GstStructure * gst_gl_context_get_config (GstGLContext * context);
+GST_GL_API
+gboolean gst_gl_context_request_config (GstGLContext * context, GstStructure * gl_config);
+
+GST_GL_API
gboolean gst_gl_context_activate (GstGLContext *context, gboolean activate);
GST_GL_API
GThread * gst_gl_context_get_thread (GstGLContext *context);
G_GNUC_INTERNAL
gboolean _gst_gl_context_debug_is_enabled (GstGLContext * context);
+#define GST_GL_CONTEXT_WRAPPED_GL_CONFIG_NAME "gst.gl.context.wrapped.config"
+
+#define GST_TYPE_GL_WRAPPED_CONTEXT (gst_gl_wrapped_context_get_type())
+G_GNUC_INTERNAL
+GType gst_gl_wrapped_context_get_type (void);
+
+#define GST_GL_WRAPPED_CONTEXT(o) (G_TYPE_CHECK_INSTANCE_CAST((o), GST_TYPE_GL_WRAPPED_CONTEXT, GstGLWrappedContext))
+#define GST_GL_WRAPPED_CONTEXT_CLASS(k) (G_TYPE_CHECK_CLASS((k), GST_TYPE_GL_CONTEXT, GstGLContextClass))
+#define GST_IS_GL_WRAPPED_CONTEXT(o) (G_TYPE_CHECK_INSTANCE_TYPE((o), GST_TYPE_GL_WRAPPED_CONTEXT))
+#define GST_IS_GL_WRAPPED_CONTEXT_CLASS(k) (G_TYPE_CHECK_CLASS_TYPE((k), GST_TYPE_GL_WRAPPED_CONTEXT))
+#define GST_GL_WRAPPED_CONTEXT_GET_CLASS(o) (G_TYPE_INSTANCE_GET_CLASS((o), GST_TYPE_GL_WRAPPED_CONTEXT, GstGLWrappedContextClass))
+
G_END_DECLS
#endif /* __GST_GL_CONTEXT_PRIVATE_H__ */
--- /dev/null
+/*
+ * GStreamer
+ * Copyright (C) 2020 Matthew Waters <matthew@centricular.com>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library 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
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ */
+
+/**
+ * SECTION:gstglcontextconfig
+ * @short_description: OpenGL context configuration values
+ * @title: GstGLContext
+ * @see_also: #GstGLContext, #GstGLWindow
+ *
+ * A common list of well-known values for what a config retrievable from or set
+ * on a `GstGLContext` may contain.
+ */
+
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+#include "gstglcontextconfig.h"
+#include <gst/gl/gl.h>
+
+/**
+ * GST_GL_CONFIG_ATTRIB_CONFIG_ID_NAME:
+ *
+ * The platform-specific config-id. This value is not stable across different
+ * machines or even different versions of the same underlying OpenGL
+ * implementation.
+ *
+ * Since: 1.20
+ */
+/**
+ * GST_GL_CONFIG_ATTRIB_CONFIG_ID_GTYPE:
+ *
+ * The #GType of the config-id field.
+ *
+ * Since: 1.20
+ */
+const gchar *GST_GL_CONFIG_ATTRIB_CONFIG_ID_NAME = "config-id";
+/**
+ * GST_GL_CONFIG_ATTRIB_PLATFORM_NAME:
+ *
+ * The #GstGLPlatform this config was made for.
+ *
+ * Since: 1.20
+ */
+/**
+ * GST_GL_CONFIG_ATTRIB_PLATFORM_GTYPE:
+ *
+ * The #GType of the 'platform' field.
+ *
+ * Since: 1.20
+ */
+const gchar *GST_GL_CONFIG_ATTRIB_PLATFORM_NAME = "platform";
+/**
+ * GST_GL_CONFIG_ATTRIB_CAVEAT_NAME:
+ *
+ * Any #GstGLConfigCaveat's applied to this configuration.
+ *
+ * Since: 1.20
+ */
+/**
+ * GST_GL_CONFIG_ATTRIB_CAVEAT_GTYPE:
+ *
+ * The #GType of the 'caveat' field.
+ *
+ * Since: 1.20
+ */
+const gchar *GST_GL_CONFIG_ATTRIB_CAVEAT_NAME = "caveat";
+/**
+ * GST_GL_CONFIG_ATTRIB_SURFACE_TYPE_NAME:
+ *
+ * Flags of #GstGLConfigSurfaceType's that can apply to this configuration.
+ *
+ * Since: 1.20
+ */
+/**
+ * GST_GL_CONFIG_ATTRIB_SURFACE_TYPE_GTYPE:
+ *
+ * The #GType of the 'surface-type' field.
+ *
+ * Since: 1.20
+ */
+const gchar *GST_GL_CONFIG_ATTRIB_SURFACE_TYPE_NAME = "surface-type";
+/**
+ * GST_GL_CONFIG_ATTRIB_CONFORMANT_API_NAME:
+ *
+ * The #GstGLAPI's that this configuration meets the conformance requirements
+ * for.
+ *
+ * Since: 1.20
+ */
+/**
+ * GST_GL_CONFIG_ATTRIB_CONFORMANT_API_GTYPE:
+ *
+ * The #GType of the 'conformant-api' field.
+ *
+ * Since: 1.20
+ */
+const gchar *GST_GL_CONFIG_ATTRIB_CONFORMANT_API_NAME = "conformant-api";
+/**
+ * GST_GL_CONFIG_ATTRIB_RENDERABLE_API_NAME:
+ *
+ * The #GstGLAPI's that this configuration can be rendered with.
+ *
+ * Since: 1.20
+ */
+/**
+ * GST_GL_CONFIG_ATTRIB_RENDERABLE_API_GTYPE:
+ *
+ * The #GType of the 'renderable-api' field.
+ *
+ * Since: 1.20
+ */
+const gchar *GST_GL_CONFIG_ATTRIB_RENDERABLE_API_NAME = "renderable-api";
+/**
+ * GST_GL_CONFIG_ATTRIB_RED_SIZE_NAME:
+ *
+ * The size of the red buffer with a colour backing buffer.
+ *
+ * Since: 1.20
+ */
+/**
+ * GST_GL_CONFIG_ATTRIB_RED_SIZE_GTYPE:
+ *
+ * The #GType of the 'red-size' field.
+ *
+ * Since: 1.20
+ */
+const gchar *GST_GL_CONFIG_ATTRIB_RED_SIZE_NAME = "red-size";
+/**
+ * GST_GL_CONFIG_ATTRIB_GREEN_SIZE_NAME:
+ *
+ * The size of the green buffer with a colour backing buffer.
+ *
+ * Since: 1.20
+ */
+/**
+ * GST_GL_CONFIG_ATTRIB_GREEN_SIZE_GTYPE:
+ *
+ * The #GType of the 'green-size' field.
+ *
+ * Since: 1.20
+ */
+const gchar *GST_GL_CONFIG_ATTRIB_GREEN_SIZE_NAME = "green-size";
+/**
+ * GST_GL_CONFIG_ATTRIB_BLUE_SIZE_NAME:
+ *
+ * The size of the blue buffer with a colour backing buffer.
+ *
+ * Since: 1.20
+ */
+/**
+ * GST_GL_CONFIG_ATTRIB_BLUE_SIZE_GTYPE:
+ *
+ * The #GType of the 'blue-size' field.
+ *
+ * Since: 1.20
+ */
+const gchar *GST_GL_CONFIG_ATTRIB_BLUE_SIZE_NAME = "blue-size";
+/**
+ * GST_GL_CONFIG_ATTRIB_ALPHA_SIZE_NAME:
+ *
+ * The size of the alpha buffer with a colour backing buffer.
+ *
+ * Since: 1.20
+ */
+/**
+ * GST_GL_CONFIG_ATTRIB_ALPHA_SIZE_GTYPE:
+ *
+ * The #GType of the 'alpha-size' field.
+ *
+ * Since: 1.20
+ */
+const gchar *GST_GL_CONFIG_ATTRIB_ALPHA_SIZE_NAME = "alpha-size";
+/**
+ * GST_GL_CONFIG_ATTRIB_LUMINANCE_SIZE_NAME:
+ *
+ * The size of the backing luminance buffer.
+ *
+ * Since: 1.20
+ */
+/**
+ * GST_GL_CONFIG_ATTRIB_LUMINANCE_SIZE_GTYPE:
+ *
+ * The #GType of the 'luminance-size' field.
+ *
+ * Since: 1.20
+ */
+const gchar *GST_GL_CONFIG_ATTRIB_LUMINANCE_SIZE_NAME = "luminance-size";
+/**
+ * GST_GL_CONFIG_ATTRIB_DEPTH_SIZE_NAME:
+ *
+ * The size of the backing depth buffer.
+ *
+ * Since: 1.20
+ */
+/**
+ * GST_GL_CONFIG_ATTRIB_DEPTH_SIZE_GTYPE:
+ *
+ * The #GType of the 'depth-size' field.
+ *
+ * Since: 1.20
+ */
+const gchar *GST_GL_CONFIG_ATTRIB_DEPTH_SIZE_NAME = "depth-size";
+/**
+ * GST_GL_CONFIG_ATTRIB_STENCIL_SIZE_NAME:
+ *
+ * The size of the backing stencil buffer.
+ *
+ * Since: 1.20
+ */
+/**
+ * GST_GL_CONFIG_ATTRIB_STENCIL_SIZE_GTYPE:
+ *
+ * The #GType of the 'stencil-size' field.
+ *
+ * Since: 1.20
+ */
+const gchar *GST_GL_CONFIG_ATTRIB_STENCIL_SIZE_NAME = "stencil-size";
+/**
+ * GST_GL_CONFIG_ATTRIB_MAX_PBUFFER_WIDTH_NAME:
+ *
+ * The maximum width of a pbuffer created with this config.
+ *
+ * Since: 1.20
+ */
+/**
+ * GST_GL_CONFIG_ATTRIB_MAX_PBUFFER_WIDTH_GTYPE:
+ *
+ * The #GType of the 'max-pbuffer-width' field.
+ *
+ * Since: 1.20
+ */
+const gchar *GST_GL_CONFIG_ATTRIB_MAX_PBUFFER_WIDTH_NAME = "max-pbuffer-width";
+/**
+ * GST_GL_CONFIG_ATTRIB_MAX_PBUFFER_HEIGHT_NAME:
+ *
+ * The maximum height of a pbuffer created with this config.
+ *
+ * Since: 1.20
+ */
+/**
+ * GST_GL_CONFIG_ATTRIB_MAX_PBUFFER_HEIGHT_GTYPE:
+ *
+ * The #GType of the 'max-pbuffer-height' field.
+ *
+ * Since: 1.20
+ */
+const gchar *GST_GL_CONFIG_ATTRIB_MAX_PBUFFER_HEIGHT_NAME =
+ "max-pbuffer-height";
+/**
+ * GST_GL_CONFIG_ATTRIB_MAX_PBUFFER_PIXELS_NAME:
+ *
+ * The maximum number of pixels that a pbuffer can be created with this config.
+ *
+ * Since: 1.20
+ */
+/**
+ * GST_GL_CONFIG_ATTRIB_MAX_PBUFFER_PIXELS_GTYPE:
+ *
+ * The #GType of the 'max-pbuffer-pixels' field.
+ *
+ * Since: 1.20
+ */
+const gchar *GST_GL_CONFIG_ATTRIB_MAX_PBUFFER_PIXELS_NAME =
+ "max-pbuffer-pixels";
+/**
+ * GST_GL_CONFIG_ATTRIB_SAMPLE_BUFFERS_NAME:
+ *
+ * The number of sample buffers for this config.
+ *
+ * Since: 1.20
+ */
+/**
+ * GST_GL_CONFIG_ATTRIB_SAMPLE_BUFFERS_GTYPE:
+ *
+ * The #GType of the 'sample-buffers' field.
+ *
+ * Since: 1.20
+ */
+const gchar *GST_GL_CONFIG_ATTRIB_SAMPLE_BUFFERS_NAME = "sample-buffers";
+/**
+ * GST_GL_CONFIG_ATTRIB_SAMPLES_NAME:
+ *
+ * The number of samples per pixel for this config.
+ *
+ * Since: 1.20
+ */
+/**
+ * GST_GL_CONFIG_ATTRIB_SAMPLES_GTYPE:
+ *
+ * The #GType of the 'samples' field.
+ *
+ * Since: 1.20
+ */
+const gchar *GST_GL_CONFIG_ATTRIB_SAMPLES_NAME = "samples";
+/**
+ * GST_GL_CONFIG_ATTRIB_NATIVE_RENDERABLE_NAME:
+ *
+ * Whether this configuration is renderable to by the native drawing API.
+ *
+ * Since: 1.20
+ */
+/**
+ * GST_GL_CONFIG_ATTRIB_NATIVE_RENDERABLE_GTYPE:
+ *
+ * The #GType of the 'native-renderable' field.
+ *
+ * Since: 1.20
+ */
+const gchar *GST_GL_CONFIG_ATTRIB_NATIVE_RENDERABLE_NAME = "native-renderable";
+/**
+ * GST_GL_CONFIG_ATTRIB_NATIVE_VISUAL_ID_NAME:
+ *
+ * The native visual ID of this config. This value may not be consistent
+ * across machines or even dependency versions.
+ *
+ * Since: 1.20
+ */
+/**
+ * GST_GL_CONFIG_ATTRIB_NATIVE_VISUAL_ID_GTYPE:
+ *
+ * The #GType of the 'native-visual-id' field.
+ *
+ * Since: 1.20
+ */
+const gchar *GST_GL_CONFIG_ATTRIB_NATIVE_VISUAL_ID_NAME = "native-visual-id";
+/**
+ * GST_GL_CONFIG_ATTRIB_LEVEL_NAME:
+ *
+ * Level of the under/overlay of this config. Positive values correspond to
+ * overlay, negative values are underlay.
+ *
+ * Since: 1.20
+ */
+/**
+ * GST_GL_CONFIG_ATTRIB_LEVEL_GTYPE:
+ *
+ * The #GType of the 'level' field.
+ *
+ * Since: 1.20
+ */
+const gchar *GST_GL_CONFIG_ATTRIB_LEVEL_NAME = "level";
+/**
+ * GST_GL_CONFIG_ATTRIB_MIN_SWAP_INTERVAL_NAME:
+ *
+ * The minimum value available for vsync synchronisation.
+ *
+ * Since: 1.20
+ */
+/**
+ * GST_GL_CONFIG_ATTRIB_MIN_SWAP_INTERVAL_GTYPE:
+ *
+ * The #GType of the 'min-swap-interval' field.
+ *
+ * Since: 1.20
+ */
+const gchar *GST_GL_CONFIG_ATTRIB_MIN_SWAP_INTERVAL_NAME = "min-swap-interval";
+/**
+ * GST_GL_CONFIG_ATTRIB_MAX_SWAP_INTERVAL_NAME:
+ *
+ * The maximum value available for vsync synchronisation.
+ *
+ * Since: 1.20
+ */
+/**
+ * GST_GL_CONFIG_ATTRIB_MAX_SWAP_INTERVAL_GTYPE:
+ *
+ * The #GType of the 'max-swap-interval' field.
+ *
+ * Since: 1.20
+ */
+const gchar *GST_GL_CONFIG_ATTRIB_MAX_SWAP_INTERVAL_NAME = "max-swap-interval";
+
+static const gchar *
+gst_gl_enum_value_to_const_string (GType type, guint value)
+{
+ GEnumClass *enum_class;
+ GEnumValue *enum_value;
+ const gchar *str = NULL;
+
+ enum_class = g_type_class_ref (type);
+ enum_value = g_enum_get_value (enum_class, value);
+
+ if (enum_value)
+ str = enum_value->value_nick;
+
+ g_type_class_unref (enum_class);
+
+ return str;
+}
+
+/**
+ * gst_gl_config_caveat_to_string:
+ * @caveat: the #GstGLConfigCaveat
+ *
+ * Returns: (nullable): a string version of @caveat or %NULL if @caveat does not
+ * exist.
+ *
+ * Since: 1.20
+ */
+const gchar *
+gst_gl_config_caveat_to_string (GstGLConfigCaveat caveat)
+{
+ return gst_gl_enum_value_to_const_string (GST_TYPE_GL_CONFIG_CAVEAT, caveat);
+}
+
+/**
+ * gst_gl_config_surface_type_to_string:
+ * @surface_type: the #GstGLConfigSurfaceType
+ *
+ * Returns: (nullable): a string version of @caveat or %NULL if @surface_type does not
+ * exist.
+ *
+ * Since: 1.20
+ */
+const gchar *
+gst_gl_config_surface_type_to_string (GstGLConfigSurfaceType surface_type)
+{
+ return gst_gl_enum_value_to_const_string (GST_TYPE_GL_CONFIG_SURFACE_TYPE,
+ surface_type);
+}
--- /dev/null
+/*
+ * GStreamer
+ * Copyright (C) 2020 Matthew Waters <matthew@centricular.com>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library 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
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ */
+
+#ifndef __GST_GL_CONTEXT_CONFIG_H__
+#define __GST_GL_CONTEXT_CONFIG_H__
+
+#include <gst/gst.h>
+
+#include <gst/gl/gstgl_fwd.h>
+
+G_BEGIN_DECLS
+
+/**
+ * GST_GL_CONFIG_STRUCTURE_NAME:
+ *
+ * The canonical name of a #GstStructure that contains a configuration for a
+ * #GstGLContext.
+ *
+ * Since: 1.20
+ */
+#define GST_GL_CONFIG_STRUCTURE_NAME "gst-gl-context-config"
+
+/**
+ * GST_GL_CONFIG_ATTRIB_NAME:
+ *
+ * Get a reference to the variable name of a particular configuration field.
+ *
+ * e.g. for `CONFIG_ID`: `GST_GL_CONFIG_ATTRIB_NAME (CONFIG_ID)`
+ *
+ * Since: 1.20
+ */
+#define GST_GL_CONFIG_ATTRIB_NAME(UPPER_NAME) \
+ G_PASTE(G_PASTE(GST_GL_CONFIG_ATTRIB_,UPPER_NAME),_NAME)
+/**
+ * GST_GL_CONFIG_ATTRIB_GTYPE:
+ *
+ * Get a reference to the #GType of a particular configuration field.
+ *
+ * e.g. for `CONFIG_ID`: `GST_GL_CONFIG_ATTRIB_GTYPE (CONFIG_ID)`
+ *
+ * Since: 1.20
+ */
+#define GST_GL_CONFIG_ATTRIB_GTYPE(UPPER_NAME) \
+ G_PASTE(G_PASTE(GST_GL_CONFIG_ATTRIB_,UPPER_NAME),_GTYPE)
+
+GST_GL_API const char * GST_GL_CONFIG_ATTRIB_CONFIG_ID_NAME;
+#define GST_GL_CONFIG_ATTRIB_CONFIG_ID_GTYPE G_TYPE_UINT
+GST_GL_API const char * GST_GL_CONFIG_ATTRIB_PLATFORM_NAME;
+#define GST_GL_CONFIG_ATTRIB_PLATFORM_GTYPE GST_TYPE_GL_PLATFORM
+GST_GL_API const char * GST_GL_CONFIG_ATTRIB_CAVEAT_NAME;
+#define GST_GL_CONFIG_ATTRIB_CAVEAT_GTYPE GST_TYPE_GL_CONFIG_CAVEAT
+GST_GL_API const char * GST_GL_CONFIG_ATTRIB_SURFACE_TYPE_NAME;
+#define GST_GL_CONFIG_ATTRIB_SURFACE_TYPE_GTYPE GST_TYPE_GL_CONFIG_SURFACE_TYPE
+GST_GL_API const char * GST_GL_CONFIG_ATTRIB_CONFORMANT_API_NAME;
+#define GST_GL_CONFIG_ATTRIB_CONFORMANT_API_GTYPE GST_TYPE_GL_API
+GST_GL_API const char * GST_GL_CONFIG_ATTRIB_RENDERABLE_API_NAME;
+#define GST_GL_CONFIG_ATTRIB_RENDERABLE_API_GTYPE GST_TYPE_GL_API
+GST_GL_API const char * GST_GL_CONFIG_ATTRIB_RED_SIZE_NAME;
+#define GST_GL_CONFIG_ATTRIB_RED_SIZE_GTYPE G_TYPE_INT
+GST_GL_API const char * GST_GL_CONFIG_ATTRIB_GREEN_SIZE_NAME;
+#define GST_GL_CONFIG_ATTRIB_GREEN_SIZE_GTYPE G_TYPE_INT
+GST_GL_API const char * GST_GL_CONFIG_ATTRIB_BLUE_SIZE_NAME;
+#define GST_GL_CONFIG_ATTRIB_BLUE_SIZE_GTYPE G_TYPE_INT
+GST_GL_API const char * GST_GL_CONFIG_ATTRIB_ALPHA_SIZE_NAME;
+#define GST_GL_CONFIG_ATTRIB_ALPHA_SIZE_GTYPE G_TYPE_INT
+GST_GL_API const char * GST_GL_CONFIG_ATTRIB_LUMINANCE_SIZE_NAME;
+#define GST_GL_CONFIG_ATTRIB_LUMINANCE_SIZE_GTYPE G_TYPE_INT
+GST_GL_API const char * GST_GL_CONFIG_ATTRIB_DEPTH_SIZE_NAME;
+#define GST_GL_CONFIG_ATTRIB_DEPTH_SIZE_GTYPE G_TYPE_INT
+GST_GL_API const char * GST_GL_CONFIG_ATTRIB_STENCIL_SIZE_NAME;
+#define GST_GL_CONFIG_ATTRIB_STENCIL_SIZE_GTYPE G_TYPE_INT
+GST_GL_API const char * GST_GL_CONFIG_ATTRIB_MAX_PBUFFER_WIDTH_NAME;
+#define GST_GL_CONFIG_ATTRIB_MAX_PBUFFER_WIDTH_GTYPE G_TYPE_INT
+GST_GL_API const char * GST_GL_CONFIG_ATTRIB_MAX_PBUFFER_HEIGHT_NAME;
+#define GST_GL_CONFIG_ATTRIB_MAX_PBUFFER_HEIGHT_GTYPE G_TYPE_INT
+GST_GL_API const char * GST_GL_CONFIG_ATTRIB_MAX_PBUFFER_PIXELS_NAME;
+#define GST_GL_CONFIG_ATTRIB_MAX_PBUFFER_PIXELS_GTYPE G_TYPE_INT
+GST_GL_API const char * GST_GL_CONFIG_ATTRIB_SAMPLE_BUFFERS_NAME;
+#define GST_GL_CONFIG_ATTRIB_SAMPLE_BUFFERS_GTYPE G_TYPE_INT
+GST_GL_API const char * GST_GL_CONFIG_ATTRIB_SAMPLES_NAME;
+#define GST_GL_CONFIG_ATTRIB_SAMPLES_GTYPE G_TYPE_INT
+GST_GL_API const char * GST_GL_CONFIG_ATTRIB_NATIVE_RENDERABLE_NAME;
+#define GST_GL_CONFIG_ATTRIB_NATIVE_RENDERABLE_GTYPE G_TYPE_BOOLEAN
+GST_GL_API const char * GST_GL_CONFIG_ATTRIB_NATIVE_VISUAL_ID_NAME;
+#define GST_GL_CONFIG_ATTRIB_NATIVE_VISUAL_ID_GTYPE G_TYPE_UINT
+GST_GL_API const char * GST_GL_CONFIG_ATTRIB_LEVEL_NAME;
+#define GST_GL_CONFIG_ATTRIB_LEVEL_GTYPE G_TYPE_INT
+GST_GL_API const char * GST_GL_CONFIG_ATTRIB_MIN_SWAP_INTERVAL_NAME;
+#define GST_GL_CONFIG_ATTRIB_MIN_SWAP_INTERVAL_GTYPE G_TYPE_INT
+GST_GL_API const char * GST_GL_CONFIG_ATTRIB_MAX_SWAP_INTERVAL_NAME;
+#define GST_GL_CONFIG_ATTRIB_MAX_SWAP_INTERVAL_GTYPE G_TYPE_INT
+
+/**
+ * GST_GL_CONFIG_STRUCTURE_SET_ARGS:
+ *
+ * Since: 1.20
+ */
+#define GST_GL_CONFIG_STRUCTURE_SET_ARGS(def_name,ctype,val) \
+ GST_GL_CONFIG_ATTRIB_NAME(def_name), \
+ GST_GL_CONFIG_ATTRIB_GTYPE(def_name), \
+ (ctype) (val)
+
+/**
+ * GstGLConfigCaveat:
+ * @GST_GL_CONFIG_CAVEAT_NONE: none
+ * @GST_GL_CONFIG_CAVEAT_SLOW: slow
+ * @GST_GL_CONFIG_CAVEAT_NON_CONFORMANT: non-conformant
+ *
+ * Since: 1.20
+ */
+typedef enum
+{
+ GST_GL_CONFIG_CAVEAT_NONE,
+ GST_GL_CONFIG_CAVEAT_SLOW,
+ GST_GL_CONFIG_CAVEAT_NON_CONFORMANT,
+} GstGLConfigCaveat;
+
+GST_GL_API
+const gchar * gst_gl_config_caveat_to_string (GstGLConfigCaveat caveat);
+
+/**
+ * GstGLConfigSurfaceType:
+ * @GST_GL_CONFIG_SURFACE_TYPE_NONE: none
+ * @GST_GL_CONFIG_SURFACE_TYPE_WINDOW: window
+ * @GST_GL_CONFIG_SURFACE_TYPE_PBUFFER: pbuffer
+ * @GST_GL_CONFIG_SURFACE_TYPE_PIXMAP: pixmap
+ *
+ * Since: 1.20
+ */
+typedef enum
+{
+ GST_GL_CONFIG_SURFACE_TYPE_NONE = 0,
+ GST_GL_CONFIG_SURFACE_TYPE_WINDOW = (1 << 0),
+ GST_GL_CONFIG_SURFACE_TYPE_PBUFFER = (1 << 1),
+ GST_GL_CONFIG_SURFACE_TYPE_PIXMAP = (1 << 2),
+} GstGLConfigSurfaceType;
+
+GST_GL_API
+const gchar * gst_gl_config_surface_type_to_string (GstGLConfigSurfaceType surface_type);
+
+G_END_DECLS
+
+#endif /* __GST_GL_CONTEXT_CONFIG_H__ */
'gstglbuffer.c',
'gstglbufferpool.c',
'gstglcontext.c',
+ 'gstglcontextconfig.c',
'gstgldebug.c',
'gstgldisplay.c',
'gstglfeature.c',
'gstglbufferpool.h',
'gstglcolorconvert.h',
'gstglcontext.h',
+ 'gstglcontextconfig.h',
'gstgldebug.h',
'gstgldisplay.h',
'gstglfeature.h',
context);
static gboolean gst_gl_context_wgl_check_feature (GstGLContext * context,
const gchar * feature);
+GstStructure *gst_gl_context_wgl_get_config (GstGLContext * context);
static void
gst_gl_context_wgl_class_init (GstGLContextWGLClass * klass)
GST_DEBUG_FUNCPTR (gst_gl_context_wgl_get_gl_platform);
context_class->check_feature =
GST_DEBUG_FUNCPTR (gst_gl_context_wgl_check_feature);
+ context_class->get_config = GST_DEBUG_FUNCPTR (gst_gl_context_wgl_get_config);
}
static void
context_wgl->wgl_context = NULL;
}
+static GstGLConfigSurfaceType
+pfd_flags_to_surface_type (int flags)
+{
+ GstGLConfigSurfaceType ret = GST_GL_CONFIG_SURFACE_TYPE_NONE;
+
+ if (flags & PFD_DRAW_TO_WINDOW)
+ ret |= GST_GL_CONFIG_SURFACE_TYPE_WINDOW;
+ if (flags & PFD_DRAW_TO_BITMAP)
+ ret |= GST_GL_CONFIG_SURFACE_TYPE_PIXMAP;
+
+ return ret;
+}
+
+static GstStructure *
+pixel_format_to_structure (HDC hdc, int pixfmt)
+{
+ GstStructure *ret;
+ PIXELFORMATDESCRIPTOR pfd;
+
+ if (pixfmt == 0)
+ return NULL;
+
+ if (DescribePixelFormat (hdc, pixfmt, sizeof (pfd), &pfd) == 0)
+ return NULL;
+
+ ret = gst_structure_new (GST_GL_CONFIG_STRUCTURE_NAME,
+ GST_GL_CONFIG_STRUCTURE_SET_ARGS (PLATFORM, GstGLPlatform,
+ GST_GL_PLATFORM_WGL), GST_GL_CONFIG_STRUCTURE_SET_ARGS (RED_SIZE, int,
+ pfd.cRedBits), GST_GL_CONFIG_STRUCTURE_SET_ARGS (BLUE_SIZE, int,
+ pfd.cBlueBits), GST_GL_CONFIG_STRUCTURE_SET_ARGS (GREEN_SIZE, int,
+ pfd.cGreenBits), GST_GL_CONFIG_STRUCTURE_SET_ARGS (ALPHA_SIZE, int,
+ pfd.cAlphaBits), GST_GL_CONFIG_STRUCTURE_SET_ARGS (DEPTH_SIZE, int,
+ pfd.cDepthBits), GST_GL_CONFIG_STRUCTURE_SET_ARGS (STENCIL_SIZE, int,
+ pfd.cStencilBits), GST_GL_CONFIG_STRUCTURE_SET_ARGS (NATIVE_VISUAL_ID,
+ guint, pixfmt), GST_GL_CONFIG_STRUCTURE_SET_ARGS (SURFACE_TYPE,
+ GstGLConfigSurfaceType, pfd_flags_to_surface_type (pfd.dwFlags)),
+ NULL);
+
+ return ret;
+}
+
static gboolean
gst_gl_context_wgl_choose_format (GstGLContext * context, GError ** error)
{
gint pixelformat = 0;
gboolean res = FALSE;
HDC device;
+ GstStructure *config;
window = gst_gl_context_get_window (context);
gst_gl_window_win32_create_window (GST_GL_WINDOW_WIN32 (window), error);
return FALSE;
}
+ config = pixel_format_to_structure (device, pixelformat);
+ GST_INFO_OBJECT (context, "chosen config %" GST_PTR_FORMAT, config);
+ gst_structure_free (config);
+
res = SetPixelFormat (device, pixelformat, &pfd);
return res;
{
return (guintptr) wglGetCurrentContext ();
}
+
+GstStructure *
+gst_gl_context_wgl_get_config (GstGLContext * context)
+{
+ GstGLWindow *window;
+ int pixfmt;
+ HDC hdc;
+
+ window = gst_gl_context_get_window (context);
+ hdc = (HDC) gst_gl_window_get_display (window);
+
+ pixfmt = GetPixelFormat (hdc);
+
+ return pixel_format_to_structure (hdc, pixfmt);
+}
context);
static void gst_gl_context_glx_get_gl_platform_version (GstGLContext * context,
gint * major, gint * minor);
+static GstStructure *gst_gl_context_glx_get_config (GstGLContext * context);
+static gboolean gst_gl_context_glx_request_config (GstGLContext * context,
+ GstStructure * config);
struct _GstGLContextGLXPrivate
{
GLXFBConfig *fbconfigs;
GLXContext (*glXCreateContextAttribsARB) (Display *, GLXFBConfig,
GLXContext, Bool, const int *);
+
+ GstStructure *requested_config;
};
#define gst_gl_context_glx_parent_class parent_class
GST_DEBUG_FUNCPTR (gst_gl_context_glx_get_current_context);
context_class->get_gl_platform_version =
GST_DEBUG_FUNCPTR (gst_gl_context_glx_get_gl_platform_version);
+ context_class->get_config = GST_DEBUG_FUNCPTR (gst_gl_context_glx_get_config);
+ context_class->request_config =
+ GST_DEBUG_FUNCPTR (gst_gl_context_glx_request_config);
}
static void
return context;
}
+static GstGLConfigSurfaceType
+glx_drawable_type_to_gst (int drawable_type)
+{
+ GstGLConfigSurfaceType ret = GST_GL_CONFIG_SURFACE_TYPE_NONE;
+
+ if (drawable_type & GLX_WINDOW_BIT)
+ ret |= GST_GL_CONFIG_SURFACE_TYPE_WINDOW;
+ if (drawable_type & GLX_PIXMAP_BIT)
+ ret |= GST_GL_CONFIG_SURFACE_TYPE_PIXMAP;
+ if (drawable_type & GLX_PBUFFER_BIT)
+ ret |= GST_GL_CONFIG_SURFACE_TYPE_PBUFFER;
+
+ return ret;
+}
+
+static GstGLConfigCaveat
+glx_caveat_to_gst (int caveat)
+{
+ switch (caveat) {
+ case GLX_NONE:
+ return GST_GL_CONFIG_CAVEAT_NONE;
+ case GLX_SLOW_CONFIG:
+ return GST_GL_CONFIG_CAVEAT_SLOW;
+ case GLX_NON_CONFORMANT_CONFIG:
+ return GST_GL_CONFIG_CAVEAT_NON_CONFORMANT;
+ default:
+ GST_WARNING ("unknown GLX caveat value %u (0x%x)", caveat, caveat);
+ return GST_GL_CONFIG_CAVEAT_NON_CONFORMANT;
+ }
+}
+
+static GstStructure *
+fb_config_to_structure (GstGLContext * context,
+ Display * dpy, GLXFBConfig fbconfig)
+{
+ GstStructure *ret;
+ int val, render_type;
+
+ ret = gst_structure_new (GST_GL_CONFIG_STRUCTURE_NAME,
+ GST_GL_CONFIG_STRUCTURE_SET_ARGS (PLATFORM, GstGLPlatform,
+ GST_GL_PLATFORM_GLX), "platform-sub-type", G_TYPE_STRING, "fbconfig",
+ NULL);
+
+ if (Success != glXGetFBConfigAttrib (dpy, fbconfig, GLX_FBCONFIG_ID, &val))
+ goto failure;
+ gst_structure_set (ret, GST_GL_CONFIG_STRUCTURE_SET_ARGS (CONFIG_ID, int,
+ val), NULL);
+
+ if (Success != glXGetFBConfigAttrib (dpy, fbconfig, GLX_VISUAL_ID, &val))
+ goto failure;
+ gst_structure_set (ret, GST_GL_CONFIG_STRUCTURE_SET_ARGS (NATIVE_VISUAL_ID,
+ guint, val), NULL);
+
+ if (Success != glXGetFBConfigAttrib (dpy, fbconfig, GLX_CONFIG_CAVEAT, &val))
+ goto failure;
+ gst_structure_set (ret, GST_GL_CONFIG_STRUCTURE_SET_ARGS (CAVEAT,
+ GstGLConfigCaveat, glx_caveat_to_gst (val)), NULL);
+
+ if (Success != glXGetFBConfigAttrib (dpy, fbconfig, GLX_DRAWABLE_TYPE, &val))
+ goto failure;
+ gst_structure_set (ret, GST_GL_CONFIG_STRUCTURE_SET_ARGS (SURFACE_TYPE,
+ GstGLConfigSurfaceType, glx_drawable_type_to_gst (val)), NULL);
+
+ if (Success != glXGetFBConfigAttrib (dpy, fbconfig, GLX_X_RENDERABLE, &val))
+ goto failure;
+ gst_structure_set (ret, GST_GL_CONFIG_STRUCTURE_SET_ARGS (NATIVE_RENDERABLE,
+ gboolean, val), NULL);
+
+ if (Success != glXGetFBConfigAttrib (dpy, fbconfig, GLX_LEVEL, &val))
+ goto failure;
+ gst_structure_set (ret, GST_GL_CONFIG_STRUCTURE_SET_ARGS (LEVEL, int, val),
+ NULL);
+
+ if (Success != glXGetFBConfigAttrib (dpy, fbconfig, GLX_RENDER_TYPE,
+ &render_type))
+ goto failure;
+
+ if (render_type & GLX_RGBA_BIT) {
+ if (Success != glXGetFBConfigAttrib (dpy, fbconfig, GLX_RED_SIZE, &val))
+ goto failure;
+ gst_structure_set (ret, GST_GL_CONFIG_STRUCTURE_SET_ARGS (RED_SIZE, int,
+ val), NULL);
+
+ if (Success != glXGetFBConfigAttrib (dpy, fbconfig, GLX_GREEN_SIZE, &val))
+ goto failure;
+ gst_structure_set (ret, GST_GL_CONFIG_STRUCTURE_SET_ARGS (GREEN_SIZE, int,
+ val), NULL);
+
+ if (Success != glXGetFBConfigAttrib (dpy, fbconfig, GLX_BLUE_SIZE, &val))
+ goto failure;
+ gst_structure_set (ret, GST_GL_CONFIG_STRUCTURE_SET_ARGS (BLUE_SIZE, int,
+ val), NULL);
+
+ if (Success != glXGetFBConfigAttrib (dpy, fbconfig, GLX_ALPHA_SIZE, &val))
+ goto failure;
+ gst_structure_set (ret, GST_GL_CONFIG_STRUCTURE_SET_ARGS (ALPHA_SIZE, int,
+ val), NULL);
+ }
+
+ if (Success != glXGetFBConfigAttrib (dpy, fbconfig, GLX_DEPTH_SIZE, &val))
+ goto failure;
+ gst_structure_set (ret, GST_GL_CONFIG_STRUCTURE_SET_ARGS (DEPTH_SIZE, int,
+ val), NULL);
+
+ if (Success != glXGetFBConfigAttrib (dpy, fbconfig, GLX_STENCIL_SIZE, &val))
+ goto failure;
+ gst_structure_set (ret, GST_GL_CONFIG_STRUCTURE_SET_ARGS (STENCIL_SIZE, int,
+ val), NULL);
+
+ if (Success != glXGetFBConfigAttrib (dpy, fbconfig, GLX_MAX_PBUFFER_WIDTH,
+ &val))
+ goto failure;
+ gst_structure_set (ret, GST_GL_CONFIG_STRUCTURE_SET_ARGS (MAX_PBUFFER_WIDTH,
+ int, val), NULL);
+
+ if (Success != glXGetFBConfigAttrib (dpy, fbconfig, GLX_MAX_PBUFFER_HEIGHT,
+ &val))
+ goto failure;
+ gst_structure_set (ret, GST_GL_CONFIG_STRUCTURE_SET_ARGS (MAX_PBUFFER_HEIGHT,
+ int, val), NULL);
+
+ if (Success != glXGetFBConfigAttrib (dpy, fbconfig, GLX_MAX_PBUFFER_PIXELS,
+ &val))
+ goto failure;
+ gst_structure_set (ret, GST_GL_CONFIG_STRUCTURE_SET_ARGS (MAX_PBUFFER_PIXELS,
+ int, val), NULL);
+
+ return ret;
+
+failure:
+ gst_structure_free (ret);
+ return NULL;
+}
+
static void
gst_gl_context_glx_dump_fb_config (GstGLContextGLX * glx,
Display * dpy, GLXFBConfig fbconfig)
XFree (configs);
}
+static int *
+fb_config_attributes_from_structure (GstStructure * config)
+{
+ guint i = 0, n;
+ int *ret;
+
+ if (!config) {
+ gint attribs[] = {
+ GLX_RENDER_TYPE, GLX_RGBA_BIT,
+ GLX_RED_SIZE, 1,
+ GLX_GREEN_SIZE, 1,
+ GLX_BLUE_SIZE, 1,
+ GLX_DEPTH_SIZE, 16,
+ GLX_DOUBLEBUFFER, True,
+ None
+ };
+
+ return g_memdup (attribs, sizeof (attribs));
+ }
+
+ n = gst_structure_n_fields (config) * 2 + 1;
+ ret = g_new0 (gint, n);
+
+#define TRANSFORM_VALUE(GL_CONF_NAME,GLX_ATTR_NAME) \
+ G_STMT_START { \
+ if (gst_structure_has_field_typed (config, \
+ GST_GL_CONFIG_ATTRIB_NAME(GL_CONF_NAME), \
+ GST_GL_CONFIG_ATTRIB_GTYPE(GL_CONF_NAME))) { \
+ int val; \
+ if (gst_structure_get (config, \
+ GST_GL_CONFIG_ATTRIB_NAME(GL_CONF_NAME), \
+ GST_GL_CONFIG_ATTRIB_GTYPE(GL_CONF_NAME), &val, NULL)) { \
+ ret[i++] = GLX_ATTR_NAME; \
+ ret[i++] = (int) val; \
+ } \
+ } \
+ } G_STMT_END
+
+ TRANSFORM_VALUE (CONFIG_ID, GLX_FBCONFIG_ID);
+ TRANSFORM_VALUE (RED_SIZE, GLX_RED_SIZE);
+ TRANSFORM_VALUE (GREEN_SIZE, GLX_GREEN_SIZE);
+ TRANSFORM_VALUE (BLUE_SIZE, GLX_BLUE_SIZE);
+ TRANSFORM_VALUE (ALPHA_SIZE, GLX_ALPHA_SIZE);
+ TRANSFORM_VALUE (DEPTH_SIZE, GLX_DEPTH_SIZE);
+ TRANSFORM_VALUE (STENCIL_SIZE, GLX_STENCIL_SIZE);
+ /* TODO: more values */
+
+#undef TRANSFORM_VALUE
+
+ ret[i++] = None;
+ g_assert (i <= n);
+ return ret;
+}
+
static GLXContext
_create_context_with_flags (GstGLContextGLX * context_glx, Display * dpy,
GLXFBConfig fbconfig, GLXContext share_context, gint major, gint minor,
context_glx->priv->context_api = GST_GL_API_OPENGL;
}
- if (context_glx->priv->fbconfigs)
- XFree (context_glx->priv->fbconfigs);
-
if (!context_glx->glx_context) {
g_set_error (error, GST_GL_CONTEXT_ERROR,
GST_GL_CONTEXT_ERROR_CREATE_CONTEXT, "Failed to create opengl context");
window = gst_gl_context_get_window (context);
device = (Display *) gst_gl_display_get_handle (window->display);
+ if (context_glx->priv->fbconfigs)
+ XFree (context_glx->priv->fbconfigs);
+ context_glx->priv->fbconfigs = NULL;
+
glXDestroyContext (device, context_glx->glx_context);
context_glx->glx_context = 0;
+ if (context_glx->priv->requested_config)
+ gst_structure_free (context_glx->priv->requested_config);
+ context_glx->priv->requested_config = NULL;
+
gst_object_unref (window);
}
goto failure;
}
} else {
- gint attribs[] = {
- GLX_RENDER_TYPE, GLX_RGBA_BIT,
- GLX_RED_SIZE, 1,
- GLX_GREEN_SIZE, 1,
- GLX_BLUE_SIZE, 1,
- GLX_DEPTH_SIZE, 16,
- GLX_DOUBLEBUFFER, True,
- None
- };
int fbcount;
+ int *attribs;
+
+ attribs =
+ fb_config_attributes_from_structure (context_glx->
+ priv->requested_config);
gst_gl_context_glx_dump_all_fb_configs (context_glx, device,
DefaultScreen (device));
context_glx->priv->fbconfigs = glXChooseFBConfig (device,
DefaultScreen (device), attribs, &fbcount);
+ g_free (attribs);
+
if (!context_glx->priv->fbconfigs) {
g_set_error (error, GST_GL_CONTEXT_ERROR,
GST_GL_CONTEXT_ERROR_WRONG_CONFIG,
*major = context_glx->priv->glx_major;
*minor = context_glx->priv->glx_minor;
}
+
+static GstStructure *
+gst_gl_context_glx_get_config (GstGLContext * context)
+{
+ GstGLContextGLX *glx = GST_GL_CONTEXT_GLX (context);
+ GstGLWindow *window;
+ GstGLWindowX11 *window_x11;
+ Display *device;
+ GstStructure *ret;
+
+ window = gst_gl_context_get_window (context);
+ device = (Display *) gst_gl_display_get_handle (window->display);
+ window_x11 = GST_GL_WINDOW_X11 (window);
+
+ g_return_val_if_fail (glx->priv->fbconfigs || window_x11->visual_info, NULL);
+
+ if (glx->priv->fbconfigs) {
+ ret = fb_config_to_structure (context, device, glx->priv->fbconfigs[0]);
+ } else {
+ /*TODO: XVisualInfo for really old GLX/X11 versions, */
+ ret = NULL;
+ }
+ gst_object_unref (window);
+ return ret;
+}
+
+static gboolean
+gst_gl_context_glx_request_config (GstGLContext * context,
+ GstStructure * config)
+{
+ GstGLContextGLX *glx = GST_GL_CONTEXT_GLX (context);
+
+ if (glx->priv->requested_config)
+ gst_structure_free (glx->priv->requested_config);
+ glx->priv->requested_config = config;
+
+ return TRUE;
+}
+
+gboolean
+gst_gl_context_glx_fill_info (GstGLContext * context)
+{
+ GLXContext glx_context = (GLXContext) gst_gl_context_get_gl_context (context);
+ GstStructure *config;
+ Display *device;
+ GLXFBConfig *fbconfigs;
+ int fbconfig_id, n_fbconfigs;
+ int glx_major, glx_minor;
+ int attrs[3];
+
+ if (!glx_context) {
+ GST_ERROR_OBJECT (context, "no GLX context");
+ return FALSE;
+ }
+
+ device = (Display *) gst_gl_display_get_handle (context->display);
+
+ if (!glXQueryVersion (device, &glx_major, &glx_minor)) {
+ GST_WARNING_OBJECT (context, "could not retrieve GLX version");
+ return FALSE;
+ }
+
+ if (!GST_GL_CHECK_GL_VERSION (glx_major, glx_minor, 1, 4)) {
+ GST_FIXME_OBJECT (context, "No support for retrieving the "
+ "GstGLContextConfig from GLX < 1.4, have %u.%u", glx_major, glx_minor);
+ return TRUE;
+ }
+
+ if (Success != glXQueryContext (device, glx_context, GLX_FBCONFIG_ID,
+ &fbconfig_id)) {
+ GST_WARNING_OBJECT (context,
+ "could not retrieve fbconfig id from glx context");
+ goto failure;
+ }
+
+ attrs[0] = GLX_FBCONFIG_ID;
+ attrs[1] = fbconfig_id;
+ attrs[2] = None;
+
+ fbconfigs = glXChooseFBConfig (device, DefaultScreen (device), attrs,
+ &n_fbconfigs);
+ if (!fbconfigs || n_fbconfigs <= 0) {
+ GST_WARNING_OBJECT (context,
+ "could not retrieve fbconfig from its ID 0x%x. "
+ "Wrong Display or Screen?", fbconfig_id);
+ goto failure;
+ }
+
+ config = fb_config_to_structure (context, device, fbconfigs[0]);
+ if (!config) {
+ GST_WARNING_OBJECT (context, "could not transform fbconfig id 0x%x into "
+ "GstStructure.", fbconfig_id);
+ goto failure;
+ }
+
+ GST_INFO_OBJECT (context, "found config %" GST_PTR_FORMAT, config);
+
+ g_object_set_data_full (G_OBJECT (context),
+ GST_GL_CONTEXT_WRAPPED_GL_CONFIG_NAME, config,
+ (GDestroyNotify) gst_structure_free);
+
+ return TRUE;
+
+failure:
+ return FALSE;
+}
G_GNUC_INTERNAL
gpointer gst_gl_context_glx_get_proc_address (GstGLAPI gl_api, const gchar * name);
+G_GNUC_INTERNAL
+gboolean gst_gl_context_glx_fill_info (GstGLContext * context);
+
G_END_DECLS
#endif /* __GST_GL_CONTEXT_H__ */