Пример #1
0
/**
 * gst_gl_context_can_share:
 * @context: a #GstGLContext
 * @other_context: another #GstGLContext
 *
 * Note: This will always fail for two wrapped #GstGLContext's
 *
 * Returns: whether @context and @other_context are able to share OpenGL
 *      resources.
 *
 * Since: 1.6
 */
gboolean
gst_gl_context_can_share (GstGLContext * context, GstGLContext * other_context)
{
  g_return_val_if_fail (GST_IS_GL_CONTEXT (context), FALSE);
  g_return_val_if_fail (GST_IS_GL_CONTEXT (other_context), FALSE);

  /* check if the contexts are descendants or the root nodes are the same */
  return context->priv->sharegroup_id != 0
      && context->priv->sharegroup_id == other_context->priv->sharegroup_id;
}
Пример #2
0
/**
 * gst_gl_allocation_params_init:
 * @params: the #GstGLAllocationParams to initialize
 * @struct_size: the struct size of the implementation
 * @alloc: some alloc flags
 * @copy: a copy function
 * @free: a free function
 * @context: (transfer none): a #GstGLContext
 * @alloc_size: the number of bytes to allocate.
 * @alloc_params: (transfer none) (allow-none): a #GstAllocationParams to apply
 * @wrapped_data: (transfer none) (allow-none): a sysmem data pointer to initialize the allocation with
 * @gl_handle: (transfer none): a GL handle to initialize the allocation with
 * @user_data: (transfer none) (allow-none): user data to call @notify with
 * @notify: (allow-none): a #GDestroyNotify
 *
 * @notify will be called once for each allocated memory using these @params
 * when freeing the memory.
 *
 * Returns: whether the paramaters could be initialized
 */
gboolean
gst_gl_allocation_params_init (GstGLAllocationParams * params,
    gsize struct_size, guint alloc_flags, GstGLAllocationParamsCopyFunc copy,
    GstGLAllocationParamsFreeFunc free, GstGLContext * context,
    gsize alloc_size, GstAllocationParams * alloc_params,
    gpointer wrapped_data, guint gl_handle, gpointer user_data,
    GDestroyNotify notify)
{
  memset (params, 0, sizeof (*params));

  g_return_val_if_fail (struct_size > 0, FALSE);
  g_return_val_if_fail (copy != NULL, FALSE);
  g_return_val_if_fail (free != NULL, FALSE);
  g_return_val_if_fail (GST_IS_GL_CONTEXT (context), FALSE);

  params->struct_size = struct_size;
  params->alloc_size = alloc_size;
  params->copy = copy;
  params->free = free;
  params->alloc_flags = alloc_flags;
  params->context = gst_object_ref (context);
  if (alloc_params)
    params->alloc_params = gst_allocation_params_copy (alloc_params);
  params->notify = notify;
  params->user_data = user_data;
  params->wrapped_data = wrapped_data;
  params->gl_handle = gl_handle;

  return TRUE;
}
Пример #3
0
/**
 * gst_gl_context_activate:
 * @context: a #GstGLContext
 * @activate: %TRUE to activate, %FALSE to deactivate
 *
 * (De)activate the OpenGL context represented by this @context.
 *
 * In OpenGL terms, calls eglMakeCurrent or similar with this context and the
 * currently set window.  See gst_gl_context_set_window() for details.
 *
 * Returns: Whether the activation succeeded
 *
 * Since: 1.4
 */
gboolean
gst_gl_context_activate (GstGLContext * context, gboolean activate)
{
  GstGLContextClass *context_class;
  gboolean result;

  g_return_val_if_fail (GST_IS_GL_CONTEXT (context), FALSE);
  context_class = GST_GL_CONTEXT_GET_CLASS (context);
  g_return_val_if_fail (context_class->activate != NULL, FALSE);

  GST_DEBUG_OBJECT (context, "activate:%d", activate);

  GST_OBJECT_LOCK (context);
  result = context_class->activate (context, activate);

  if (result && activate) {
    context->priv->active_thread = g_thread_self ();
    g_private_set (&current_context_key, context);
  } else {
    context->priv->active_thread = NULL;
    g_private_set (&current_context_key, NULL);
  }
  GST_OBJECT_UNLOCK (context);

  return result;
}
Пример #4
0
gboolean
gst_gl_context_supports_glsl_profile_version (GstGLContext * context,
    GstGLSLVersion version, GstGLSLProfile profile)
{
  g_return_val_if_fail (GST_IS_GL_CONTEXT (context), FALSE);

  if (!_is_valid_version_profile (version, profile))
    return FALSE;

  if (profile != GST_GLSL_PROFILE_NONE) {
    if (gst_gl_context_check_gl_version (context, GST_GL_API_GLES2, 2, 0)) {
      if ((profile & GST_GLSL_PROFILE_ES) == 0)
        return FALSE;
    } else if ((gst_gl_context_get_gl_api (context) & GST_GL_API_OPENGL) != 0) {
      if ((profile & GST_GLSL_PROFILE_COMPATIBILITY) == 0)
        return FALSE;
    } else if ((gst_gl_context_get_gl_api (context) & GST_GL_API_OPENGL3) != 0) {
      /* GL_ARB_es2_compatibility is requried for GL3 contexts */
      if ((profile & (GST_GLSL_PROFILE_CORE | GST_GLSL_PROFILE_ES)) == 0)
        return FALSE;
    } else {
      g_assert_not_reached ();
    }
  }

  if (version != GST_GLSL_VERSION_NONE) {
    GstGLAPI gl_api;
    gint maj, min, glsl_version;

    if (gst_gl_context_check_gl_version (context, GST_GL_API_GLES2, 3, 1)) {
      if (version > GST_GLSL_VERSION_310)
        return FALSE;
    } else if (gst_gl_context_check_gl_version (context, GST_GL_API_GLES2, 3,
            0)) {
      if (version > GST_GLSL_VERSION_300)
        return FALSE;
    } else if (gst_gl_context_check_gl_version (context, GST_GL_API_GLES2, 2,
            0)) {
      if (version > GST_GLSL_VERSION_100)
        return FALSE;
    }

    gl_api = gst_gl_context_get_gl_api (context);
    gst_gl_context_get_gl_version (context, &maj, &min);
    glsl_version = gst_gl_version_to_glsl_version (gl_api, maj, min);
    if (glsl_version > version)
      return FALSE;

    if (gst_gl_context_check_gl_version (context, GST_GL_API_OPENGL3, 1, 0))
      /* GL_ARB_es2_compatibility is requried for GL3 contexts */
      if (version < GST_GLSL_VERSION_150 && version != GST_GLSL_VERSION_100)
        return FALSE;

    if (gst_gl_context_check_gl_version (context, GST_GL_API_OPENGL, 1, 0)
        && version < GST_GLSL_VERSION_110)
      return FALSE;
  }

  return TRUE;
}
Пример #5
0
/**
 * gst_gl_context_thread_add:
 * @context: a #GstGLContext
 * @func: a #GstGLContextThreadFunc
 * @data: (closure): user data to call @func with
 *
 * Execute @func in the OpenGL thread of @context with @data
 *
 * MT-safe
 *
 * Since: 1.4
 */
void
gst_gl_context_thread_add (GstGLContext * context,
    GstGLContextThreadFunc func, gpointer data)
{
  GstGLWindow *window;
  RunGenericData rdata;

  g_return_if_fail (GST_IS_GL_CONTEXT (context));
  g_return_if_fail (func != NULL);

  if (GST_IS_GL_WRAPPED_CONTEXT (context)) {
    g_return_if_fail (context->priv->active_thread == g_thread_self ());
    func (context, data);
    return;
  }

  rdata.context = context;
  rdata.data = data;
  rdata.func = func;

  window = gst_gl_context_get_window (context);

  gst_gl_window_send_message (window,
      GST_GL_WINDOW_CB (_gst_gl_context_thread_run_generic), &rdata);

  gst_object_unref (window);
}
Пример #6
0
/**
 * gst_gl_context_get_display:
 * @context: a #GstGLContext:
 *
 * Returns: the #GstGLDisplay associated with this @context
 *
 * Since: 1.4
 */
GstGLDisplay *
gst_gl_context_get_display (GstGLContext * context)
{
  g_return_val_if_fail (GST_IS_GL_CONTEXT (context), NULL);

  return gst_object_ref (context->display);
}
Пример #7
0
void
gst_gl_query_init (GstGLQuery * query, GstGLContext * context,
    GstGLQueryType query_type)
{
  const GstGLFuncs *gl;

  g_return_if_fail (query != NULL);
  g_return_if_fail (GST_IS_GL_CONTEXT (context));
  gl = context->gl_vtable;

  memset (query, 0, sizeof (*query));

  _init_debug ();

  query->context = gst_object_ref (context);
  query->query_type = _gst_gl_query_type_to_gl (query_type);
  query->supported = _context_supports_query_type (context, query->query_type);

  if (query->supported)
    gl->GenQueries (1, &query->query_id);

  gst_gl_async_debug_init (&query->debug);
  query->debug.callback = _log_time;
  query->debug.user_data = query;
}
/**
 * gst_gl_buffer_allocation_params_new:
 * @context: a #GstGLContext
 * @alloc_size: the size in bytes to allocate
 * @alloc_params: (allow-none): the #GstAllocationParams for @tex_id
 * @gl_target: the OpenGL target to allocate
 * @gl_usage: the OpenGL usage hint to allocate with
 *
 * Returns: a new #GstGLBufferAllocationParams for allocating OpenGL buffer
 *          objects
 *
 * Since: 1.8
 */
GstGLBufferAllocationParams *
gst_gl_buffer_allocation_params_new (GstGLContext * context, gsize alloc_size,
    GstAllocationParams * alloc_params, guint gl_target, guint gl_usage)
{
  GstGLBufferAllocationParams *params;

  g_return_val_if_fail (GST_IS_GL_CONTEXT (context), NULL);
  g_return_val_if_fail (alloc_size > 0, NULL);

  params = g_new0 (GstGLBufferAllocationParams, 1);

  if (!gst_gl_allocation_params_init (&params->parent, sizeof (*params),
          GST_GL_ALLOCATION_PARAMS_ALLOC_FLAG_BUFFER |
          GST_GL_ALLOCATION_PARAMS_ALLOC_FLAG_ALLOC,
          (GstGLAllocationParamsCopyFunc)
          _gst_gl_buffer_allocation_params_copy_data,
          (GstGLAllocationParamsFreeFunc)
          _gst_gl_buffer_allocation_params_free_data, context, alloc_size,
          alloc_params, NULL, 0, NULL, NULL)) {
    g_free (params);
    return NULL;
  }

  params->gl_target = gl_target;
  params->gl_usage = gl_usage;

  return params;
}
Пример #9
0
gchar *
_gst_glsl_mangle_shader (const gchar * str, guint shader_type,
    GstGLTextureTarget from, GstGLTextureTarget to, GstGLContext * context,
    GstGLSLVersion * version, GstGLSLProfile * profile)
{
  gchar *tmp, *tmp2;

  _init_debug ();

  g_return_val_if_fail (GST_IS_GL_CONTEXT (context), NULL);

  _mangle_version_profile_from_gl_api (context, from, to, version, profile);
  tmp2 =
      _mangle_external_image_extension (str, context, from, to, *version,
      *profile);
  tmp = _mangle_texture_access (tmp2, context, from, to, *version, *profile);
  g_free (tmp2);
  tmp2 = _mangle_sampler_type (tmp, from, to);
  g_free (tmp);
  tmp = _mangle_varying_attribute (tmp2, shader_type, *version, *profile);
  g_free (tmp2);
  if (shader_type == GL_FRAGMENT_SHADER) {
    if ((*profile == GST_GLSL_PROFILE_ES && *version >= GST_GLSL_VERSION_300)
        || (*profile == GST_GLSL_PROFILE_CORE
            && *version >= GST_GLSL_VERSION_150)) {
      tmp2 = _mangle_frag_color_data (tmp);
      g_free (tmp);
      tmp = tmp2;
    }
  }
  return tmp;
}
Пример #10
0
Gst3DRenderer *
gst_3d_renderer_new (GstGLContext * context)
{
  g_return_val_if_fail (GST_IS_GL_CONTEXT (context), NULL);
  Gst3DRenderer *renderer = g_object_new (GST_3D_TYPE_RENDERER, NULL);
  renderer->context = gst_object_ref (context);
  return renderer;
}
Пример #11
0
/**
 * gst_gl_context_get_gl_platform:
 * @context: a #GstGLContext:
 *
 * Gets the OpenGL platform that used by @context.
 *
 * Returns: The platform specific backing OpenGL context
 *
 * Since: 1.4
 */
GstGLPlatform
gst_gl_context_get_gl_platform (GstGLContext * context)
{
  GstGLContextClass *context_class;

  g_return_val_if_fail (GST_IS_GL_CONTEXT (context), 0);
  context_class = GST_GL_CONTEXT_GET_CLASS (context);
  g_return_val_if_fail (context_class->get_gl_platform != NULL, 0);

  return context_class->get_gl_platform (context);
}
Пример #12
0
/**
 * gst_gl_context_destroy:
 * @context: a #GstGLContext:
 *
 * Destroys an OpenGL context.
 *
 * Should only be called after gst_gl_context_create() has been successfully
 * called for this context.
 *
 * Since: 1.6
 */
void
gst_gl_context_destroy (GstGLContext * context)
{
  GstGLContextClass *context_class;

  g_return_if_fail (GST_IS_GL_CONTEXT (context));
  context_class = GST_GL_CONTEXT_GET_CLASS (context);
  g_return_if_fail (context_class->destroy_context != NULL);

  context_class->destroy_context (context);
}
Пример #13
0
/**
 * gst_gl_context_get_gl_api:
 * @context: a #GstGLContext
 *
 * Get the currently enabled OpenGL api.
 *
 * The currently available API may be limited by the #GstGLDisplay in use and/or
 * the #GstGLWindow chosen.
 *
 * Returns: the available OpenGL api
 *
 * Since: 1.4
 */
GstGLAPI
gst_gl_context_get_gl_api (GstGLContext * context)
{
  GstGLContextClass *context_class;

  g_return_val_if_fail (GST_IS_GL_CONTEXT (context), GST_GL_API_NONE);
  context_class = GST_GL_CONTEXT_GET_CLASS (context);
  g_return_val_if_fail (context_class->get_gl_api != NULL, GST_GL_API_NONE);

  return context_class->get_gl_api (context);
}
Пример #14
0
/**
 * gst_gl_context_get_gl_version:
 * @context: a #GstGLContext
 * @maj: (out): resulting major version
 * @min: (out): resulting minor version
 *
 * Returns the OpenGL version implemented by @context.  See
 * gst_gl_context_get_gl_api() for retreiving the OpenGL api implemented by
 * @context.
 *
 * Since: 1.4
 */
void
gst_gl_context_get_gl_version (GstGLContext * context, gint * maj, gint * min)
{
  g_return_if_fail (GST_IS_GL_CONTEXT (context));
  g_return_if_fail (maj != NULL && min != NULL);

  if (maj)
    *maj = context->priv->gl_major;

  if (min)
    *min = context->priv->gl_minor;
}
Пример #15
0
/**
 * gst_gl_context_clear_shader:
 * @context: a #GstGLContext
 *
 * Clear's the currently set shader from the GL state machine.
 *
 * Note: must be called in the GL thread.
 */
void
gst_gl_context_clear_shader (GstGLContext * context)
{
  GstGLFuncs *gl;

  g_return_if_fail (GST_IS_GL_CONTEXT (context));

  gl = context->gl_vtable;

  if (gl->CreateProgram)
    gl->UseProgram (0);
  else if (gl->CreateProgramObject)
    gl->UseProgramObject (0);
}
Пример #16
0
/**
 * gst_gl_context_get_gl_context:
 * @context: a #GstGLContext:
 *
 * Gets the backing OpenGL context used by @context.
 *
 * Returns: The platform specific backing OpenGL context
 *
 * Since: 1.4
 */
guintptr
gst_gl_context_get_gl_context (GstGLContext * context)
{
  GstGLContextClass *context_class;
  guintptr result;

  g_return_val_if_fail (GST_IS_GL_CONTEXT (context), 0);
  context_class = GST_GL_CONTEXT_GET_CLASS (context);
  g_return_val_if_fail (context_class->get_gl_context != NULL, 0);

  result = context_class->get_gl_context (context);

  return result;
}
Пример #17
0
/**
 * gst_gl_context_get_window:
 * @context: a #GstGLContext
 *
 * Returns: the currently set window
 *
 * Since: 1.4
 */
GstGLWindow *
gst_gl_context_get_window (GstGLContext * context)
{
  g_return_val_if_fail (GST_IS_GL_CONTEXT (context), NULL);

  if (GST_IS_GL_WRAPPED_CONTEXT (context)) {
    GST_WARNING_OBJECT (context, "context is not toplevel, returning NULL");
    return NULL;
  }

  _ensure_window (context);

  return gst_object_ref (context->window);
}
Пример #18
0
/**
 * gst_gl_context_get_proc_address:
 * @context: a #GstGLContext
 * @name: an opengl function name
 *
 * Get a function pointer to a specified opengl function, @name.  If the the
 * specific function does not exist, NULL is returned instead.
 *
 * Platform specfic functions (names starting 'egl', 'glX', 'wgl', etc) can also
 * be retrieved using this method.
 *
 * Returns: a function pointer or NULL
 *
 * Since: 1.4
 */
gpointer
gst_gl_context_get_proc_address (GstGLContext * context, const gchar * name)
{
  gpointer ret;
  GstGLContextClass *context_class;
  GstGLAPI gl_api;

  g_return_val_if_fail (GST_IS_GL_CONTEXT (context), NULL);
  context_class = GST_GL_CONTEXT_GET_CLASS (context);
  g_return_val_if_fail (context_class->get_proc_address != NULL, NULL);

  gl_api = gst_gl_context_get_gl_api (context);
  ret = context_class->get_proc_address (gl_api, name);

  return ret;
}
Пример #19
0
/**
 * gst_gl_display_add_context:
 * @display: a #GstGLDisplay
 * @context: (transfer none): a #GstGLContext
 *
 * Returns: whether @context was successfully added. %FALSE may be returned
 * if there already exists another context for @context's active thread.
 *
 * Must be called with the object lock held.
 *
 * Since: 1.6
 */
gboolean
gst_gl_display_add_context (GstGLDisplay * display, GstGLContext * context)
{
  GstGLContext *collision = NULL;
  GstGLDisplay *context_display;
  gboolean ret = TRUE;
  GThread *thread;
  GWeakRef *ref;

  g_return_val_if_fail (GST_IS_GL_DISPLAY (display), FALSE);
  g_return_val_if_fail (GST_IS_GL_CONTEXT (context), FALSE);

  context_display = gst_gl_context_get_display (context);
  g_assert (context_display == display);
  gst_object_unref (context_display);

  thread = gst_gl_context_get_thread (context);
  if (thread) {
    collision = _get_gl_context_for_thread_unlocked (display, thread);
    g_thread_unref (thread);

    /* adding the same context is a no-op */
    if (context == collision) {
      ret = TRUE;
      goto out;
    }

    if (_check_collision (context, collision)) {
      ret = FALSE;
      goto out;
    }
  }

  ref = g_new0 (GWeakRef, 1);
  g_weak_ref_init (ref, context);

  display->priv->contexts = g_list_prepend (display->priv->contexts, ref);

out:
  if (collision)
    gst_object_unref (collision);

  GST_DEBUG_OBJECT (display, "%ssuccessfully inserted context %" GST_PTR_FORMAT,
      ret ? "" : "un", context);

  return ret;
}
Пример #20
0
/**
 * gst_gl_context_check_feature:
 * @context: a #GstGLContext
 * @feature: a platform specific feature
 *
 * Some features require that the context be created before it is possible to
 * determine their existence and so will fail if that is not the case.
 *
 * Returns: Whether @feature is supported by @context
 *
 * Since: 1.4
 */
gboolean
gst_gl_context_check_feature (GstGLContext * context, const gchar * feature)
{
  GstGLContextClass *context_class;

  g_return_val_if_fail (GST_IS_GL_CONTEXT (context), FALSE);
  g_return_val_if_fail (feature != NULL, FALSE);

  context_class = GST_GL_CONTEXT_GET_CLASS (context);

  if (g_strstr_len (feature, 3, "GL_"))
    return gst_gl_check_extension (feature, context->priv->gl_exts);

  if (!context_class->check_feature)
    return FALSE;

  return context_class->check_feature (context, feature);
}
/**
 * gst_buffer_add_gl_sync_meta_full:
 * @context: a #GstGLContext
 * @buffer: a #GstBuffer
 * @data: sync data to hold
 *
 * Returns: (transfer none): the #GstGLSyncMeta added to #GstBuffer
 *
 * Since: 1.8
 */
GstGLSyncMeta *
gst_buffer_add_gl_sync_meta_full (GstGLContext * context, GstBuffer * buffer,
    gpointer data)
{
  GstGLSyncMeta *meta;

  g_return_val_if_fail (GST_IS_GL_CONTEXT (context), NULL);

  meta =
      (GstGLSyncMeta *) gst_buffer_add_meta ((buffer), GST_GL_SYNC_META_INFO,
      NULL);

  if (!meta)
    return NULL;

  meta->context = gst_object_ref (context);
  meta->data = data;

  return meta;
}
Пример #22
0
/**
 * gst_gl_context_check_gl_version:
 * @context: a #GstGLContext
 * @api: api type required
 * @maj: major version required
 * @min: minor version required
 *
 * Returns: whether OpenGL context implements the required api and specified
 * version.
 *
 * Since: 1.4
 */
gboolean
gst_gl_context_check_gl_version (GstGLContext * context, GstGLAPI api,
    gint maj, gint min)
{
  g_return_val_if_fail (GST_IS_GL_CONTEXT (context), FALSE);

  if (maj > context->priv->gl_major)
    return FALSE;

  if ((gst_gl_context_get_gl_api (context) & api) == GST_GL_API_NONE)
    return FALSE;

  if (maj < context->priv->gl_major)
    return TRUE;

  if (min > context->priv->gl_minor)
    return FALSE;

  return TRUE;
}
Пример #23
0
static GstGLShader *
_new_with_stages_va_list (GstGLContext * context, GError ** error,
    va_list varargs)
{
  GstGLShader *shader;
  GstGLSLStage *stage;
  gboolean to_unref_and_out = FALSE;

  g_return_val_if_fail (GST_IS_GL_CONTEXT (context), NULL);

  shader = g_object_new (GST_TYPE_GL_SHADER, NULL);
  gst_object_ref_sink (shader);
  shader->context = gst_object_ref (context);

  while ((stage = va_arg (varargs, GstGLSLStage *))) {
    if (to_unref_and_out) {
      gst_object_unref (stage);
      continue;
    }

    if (!gst_glsl_stage_compile (stage, error)) {
      gst_object_unref (stage);
      to_unref_and_out = TRUE;
      continue;
    }
    if (!gst_gl_shader_attach (shader, stage)) {
      g_set_error (error, GST_GLSL_ERROR, GST_GLSL_ERROR_PROGRAM,
          "Failed to attach stage to program");
      to_unref_and_out = TRUE;
      continue;
    }
  }

  if (to_unref_and_out) {
    gst_object_unref (shader);
    return NULL;
  }

  return shader;
}
Пример #24
0
/**
 * gst_gl_context_create:
 * @context: a #GstGLContext:
 * @other_context: (allow-none): a #GstGLContext to share OpenGL objects with
 * @error: (allow-none): a #GError
 *
 * Creates an OpenGL context in the current thread with the specified
 * @other_context as a context to share shareable OpenGL objects with.  See the
 * OpenGL specification for what is shared between contexts.
 *
 * 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.
 *
 * Returns: whether the context could successfully be created
 *
 * Since: 1.4
 */
gboolean
gst_gl_context_create (GstGLContext * context,
    GstGLContext * other_context, GError ** error)
{
  gboolean alive = FALSE;

  g_return_val_if_fail (GST_IS_GL_CONTEXT (context), FALSE);
  g_return_val_if_fail (!GST_IS_GL_WRAPPED_CONTEXT (context), FALSE);

  GST_DEBUG_OBJECT (context, " other_context:%" GST_PTR_FORMAT, other_context);

  _ensure_window (context);

  g_mutex_lock (&context->priv->render_lock);

  if (!context->priv->created) {
    g_weak_ref_set (&context->priv->other_context_ref, other_context);
    context->priv->error = error;
    if (other_context == NULL)
      context->priv->sharegroup_id = _new_sharegroup_id ();
    else
      context->priv->sharegroup_id = other_context->priv->sharegroup_id;

    context->priv->gl_thread = g_thread_new ("gstglcontext",
        (GThreadFunc) gst_gl_context_create_thread, context);

    g_cond_wait (&context->priv->create_cond, &context->priv->render_lock);

    context->priv->created = TRUE;

    GST_INFO_OBJECT (context, "gl thread created");
  }

  alive = context->priv->alive;

  g_mutex_unlock (&context->priv->render_lock);

  return alive;
}
Пример #25
0
/**
 * gst_gl_handle_context_query:
 * @element: a #GstElement
 * @query: a #GstQuery of type %GST_QUERY_CONTEXT
 * @display: (transfer none) (nullable): a #GstGLDisplay
 * @context: (transfer none) (nullable): a #GstGLContext
 * @other_context: (transfer none) (nullable): application provided #GstGLContext
 *
 * Returns: Whether the @query was successfully responded to from the passed
 *          @display, @context, and @other_context.
 */
gboolean
gst_gl_handle_context_query (GstElement * element, GstQuery * query,
    GstGLDisplay * display, GstGLContext * gl_context,
    GstGLContext * other_context)
{
  const gchar *context_type;
  GstContext *context, *old_context;

  g_return_val_if_fail (GST_IS_ELEMENT (element), FALSE);
  g_return_val_if_fail (GST_IS_QUERY (query), FALSE);
  g_return_val_if_fail (display == NULL || GST_IS_GL_DISPLAY (display), FALSE);
  g_return_val_if_fail (gl_context == NULL
      || GST_IS_GL_CONTEXT (gl_context), FALSE);
  g_return_val_if_fail (other_context == NULL
      || GST_IS_GL_CONTEXT (other_context), FALSE);

  GST_LOG_OBJECT (element, "handle context query %" GST_PTR_FORMAT, query);
  gst_query_parse_context_type (query, &context_type);

  if (display && g_strcmp0 (context_type, GST_GL_DISPLAY_CONTEXT_TYPE) == 0) {
    gst_query_parse_context (query, &old_context);

    if (old_context)
      context = gst_context_copy (old_context);
    else
      context = gst_context_new (GST_GL_DISPLAY_CONTEXT_TYPE, TRUE);

    gst_context_set_gl_display (context, display);
    gst_query_set_context (query, context);
    gst_context_unref (context);
    GST_DEBUG_OBJECT (element, "successfully set %" GST_PTR_FORMAT
        " on %" GST_PTR_FORMAT, display, query);

    return TRUE;
  }
#if GST_GL_HAVE_WINDOW_X11
  else if (display && g_strcmp0 (context_type, "gst.x11.display.handle") == 0) {
    GstStructure *s;

    gst_query_parse_context (query, &old_context);

    if (old_context)
      context = gst_context_copy (old_context);
    else
      context = gst_context_new ("gst.x11.display.handle", TRUE);

    if (gst_gl_display_get_handle_type (display) & GST_GL_DISPLAY_TYPE_X11) {
      Display *x11_display = (Display *) gst_gl_display_get_handle (display);

      if (x11_display) {
        s = gst_context_writable_structure (context);
        gst_structure_set (s, "display", G_TYPE_POINTER, x11_display, NULL);

        gst_query_set_context (query, context);
        gst_context_unref (context);

        GST_DEBUG_OBJECT (element, "successfully set x11 display %p (from %"
            GST_PTR_FORMAT ") on %" GST_PTR_FORMAT, x11_display, display,
            query);

        return TRUE;
      }
    }
  }
#endif
#if GST_GL_HAVE_WINDOW_WAYLAND
  else if (display
      && g_strcmp0 (context_type, "GstWaylandDisplayHandleContextType") == 0) {
    GstStructure *s;

    gst_query_parse_context (query, &old_context);

    if (old_context)
      context = gst_context_copy (old_context);
    else
      context = gst_context_new ("GstWaylandDisplayHandleContextType", TRUE);

    if (gst_gl_display_get_handle_type (display) & GST_GL_DISPLAY_TYPE_WAYLAND) {
      struct wl_display *wayland_display =
          (struct wl_display *) gst_gl_display_get_handle (display);

      if (wayland_display) {
        s = gst_context_writable_structure (context);
        gst_structure_set (s, "display", G_TYPE_POINTER, wayland_display, NULL);

        gst_query_set_context (query, context);
        gst_context_unref (context);

        GST_DEBUG_OBJECT (element, "successfully set wayland display %p (from %"
            GST_PTR_FORMAT ") on %" GST_PTR_FORMAT, wayland_display, display,
            query);

        return TRUE;
      }
    }
  }
#endif
  else if (other_context && g_strcmp0 (context_type, "gst.gl.app_context") == 0) {
    GstStructure *s;

    gst_query_parse_context (query, &old_context);

    if (old_context)
      context = gst_context_copy (old_context);
    else
      context = gst_context_new ("gst.gl.app_context", TRUE);

    s = gst_context_writable_structure (context);
    gst_structure_set (s, "context", GST_TYPE_GL_CONTEXT, other_context, NULL);
    gst_query_set_context (query, context);
    gst_context_unref (context);

    GST_DEBUG_OBJECT (element, "successfully set application GL context %"
        GST_PTR_FORMAT " on %" GST_PTR_FORMAT, other_context, query);

    return TRUE;
  } else if (gl_context
      && g_strcmp0 (context_type, "gst.gl.local_context") == 0) {
    GstStructure *s;

    gst_query_parse_context (query, &old_context);

    if (old_context)
      context = gst_context_copy (old_context);
    else
      context = gst_context_new ("gst.gl.local_context", TRUE);

    s = gst_context_writable_structure (context);
    gst_structure_set (s, "context", GST_TYPE_GL_CONTEXT, gl_context, NULL);
    gst_query_set_context (query, context);
    gst_context_unref (context);

    GST_DEBUG_OBJECT (element, "successfully set GL context %"
        GST_PTR_FORMAT " on %" GST_PTR_FORMAT, gl_context, query);

    return TRUE;
  }

  return FALSE;
}
Пример #26
0
/**
 * gst_gl_context_fill_info:
 * @context: a #GstGLContext:
 *
 * Fills @context's info (version, extensions, vtable, etc) from the GL
 * context in the current thread.  Typically used with wrapped contexts to
 * allow wrapped contexts to be used as regular #GstGLContext's.
 *
 * Since: 1.6
 */
gboolean
gst_gl_context_fill_info (GstGLContext * context, GError ** error)
{
  GstGLFuncs *gl;
  GString *ext_g_str = NULL;
  const gchar *ext_const_c_str = NULL;
  GstGLAPI gl_api;
  gboolean ret;

  g_return_val_if_fail (GST_IS_GL_CONTEXT (context), FALSE);
  g_return_val_if_fail (context->priv->active_thread == g_thread_self (),
      FALSE);

  gl = context->gl_vtable;
  gl_api = gst_gl_context_get_gl_api (context);

  gl->GetError = gst_gl_context_get_proc_address (context, "glGetError");
  gl->GetString = gst_gl_context_get_proc_address (context, "glGetString");
  gl->GetStringi = gst_gl_context_get_proc_address (context, "glGetStringi");
  gl->GetIntegerv = gst_gl_context_get_proc_address (context, "glGetIntegerv");

  if (!gl->GetError || !gl->GetString) {
    g_set_error (error, GST_GL_CONTEXT_ERROR, GST_GL_CONTEXT_ERROR_FAILED,
        "could not GetProcAddress core opengl functions");
    goto failure;
  }

  /* gl api specific code */
  ret = _create_context_info (context, gl_api, &context->priv->gl_major,
      &context->priv->gl_minor, error);

  if (!ret) {
    g_assert (error == NULL || *error != NULL);
    goto failure;
  }

  /* GL core contexts and GLES3 */
  if (gl->GetIntegerv && gl->GetStringi && context->priv->gl_major >= 3)
    ext_g_str = _build_extension_string (context);

  if (ext_g_str && ext_g_str->len) {
    GST_DEBUG_OBJECT (context, "GL_EXTENSIONS: %s", ext_g_str->str);
    _gst_gl_feature_check_ext_functions (context, context->priv->gl_major,
        context->priv->gl_minor, ext_g_str->str);

    context->priv->gl_exts = g_string_free (ext_g_str, FALSE);
  } else {
    ext_const_c_str = (const gchar *) gl->GetString (GL_EXTENSIONS);
    if (!ext_const_c_str)
      ext_const_c_str = "";

    GST_DEBUG_OBJECT (context, "GL_EXTENSIONS: %s", ext_const_c_str);
    _gst_gl_feature_check_ext_functions (context, context->priv->gl_major,
        context->priv->gl_minor, ext_const_c_str);

    context->priv->gl_exts = g_strdup (ext_const_c_str);
  }

  if (gl_api & GST_GL_API_OPENGL3
      && !gst_gl_context_check_gl_version (context, GST_GL_API_OPENGL3, 4, 1)
      && !gst_gl_check_extension ("GL_ARB_ES2_compatibility",
          context->priv->gl_exts)) {
    g_set_error (error, GST_GL_CONTEXT_ERROR, GST_GL_CONTEXT_ERROR_FAILED,
        "An opengl3 context created but the required ES2 compatibility was not found");
    goto failure;
  }

  /* Does not implement OES_vertex_array_object properly, see
   * https://bugzilla.gnome.org/show_bug.cgi?id=750185 */
  if (g_strcmp0 ((const gchar *) gl->GetString (GL_VENDOR),
          "Imagination Technologies") == 0
      && g_strcmp0 ((const gchar *) gl->GetString (GL_RENDERER),
          "PowerVR SGX 544MP") == 0) {
    gl->GenVertexArrays = NULL;
    gl->DeleteVertexArrays = NULL;
    gl->BindVertexArray = NULL;
    gl->IsVertexArray = NULL;
  }

  return TRUE;

failure:
  return FALSE;
}