コード例 #1
0
static gboolean
gst_gl_context_egl_choose_format (GstGLContext * context, GError ** error)
{
#if GST_GL_HAVE_WINDOW_X11
  if (GST_GL_IS_WINDOW_X11 (context->window)) {
    GstGLWindow *window = gst_gl_context_get_window (context);
    GstGLWindowX11 *window_x11 = GST_GL_WINDOW_X11 (window);
    gint ret;

    window_x11->visual_info = g_new0 (XVisualInfo, 1);
    ret = XMatchVisualInfo (window_x11->device, window_x11->screen_num,
        window_x11->depth, TrueColor, window_x11->visual_info);

    gst_object_unref (window);

    if (ret == 0) {
      g_set_error (error, GST_GL_CONTEXT_ERROR,
          GST_GL_CONTEXT_ERROR_WRONG_CONFIG, "Failed to match XVisualInfo");
      return FALSE;
    }
  }
#endif

  return TRUE;
}
コード例 #2
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);
}
static gboolean
gst_glimage_sink_redisplay (GstGLImageSink * gl_sink)
{
  GstGLWindow *window;
  gboolean alive;

  window = gst_gl_context_get_window (gl_sink->context);

  if (window && gst_gl_window_is_running (window)) {

#if GST_GL_HAVE_GLES2
    if (USING_GLES2 (gl_sink->context)) {
      if (!gl_sink->redisplay_shader) {
        gst_gl_window_send_message (window,
            GST_GL_WINDOW_CB (gst_glimage_sink_thread_init_redisplay), gl_sink);
      }
    }
#endif

    /* Drawing is asynchrone: gst_gl_window_draw is not blocking
     * It means that it does not wait for stuff being executed in other threads
     */
    gst_gl_window_draw (window, GST_VIDEO_SINK_WIDTH (gl_sink),
        GST_VIDEO_SINK_HEIGHT (gl_sink));
  }
  alive = gst_gl_window_is_running (window);
  gst_object_unref (window);

  return alive;
}
コード例 #4
0
static gboolean
gst_gl_context_egl_activate (GstGLContext * context, gboolean activate)
{
  GstGLContextEGL *egl;
  gboolean result;

  egl = GST_GL_CONTEXT_EGL (context);

  if (activate) {
    GstGLWindow *window = gst_gl_context_get_window (context);
    EGLNativeWindowType handle = 0;
    /* Check if the backing handle changed */
    if (window) {
      handle = (EGLNativeWindowType) gst_gl_window_get_window_handle (window);
      gst_object_unref (window);
    }
    if (handle && handle != egl->window_handle) {
      GST_DEBUG_OBJECT (context,
          "Handle changed (have:%p, now:%p), switching surface",
          (void *) egl->window_handle, (void *) handle);
      if (egl->egl_surface) {
        result = eglDestroySurface (egl->egl_display, egl->egl_surface);
        egl->egl_surface = EGL_NO_SURFACE;
        if (!result) {
          GST_ERROR_OBJECT (context, "Failed to destroy old window surface: %s",
              gst_egl_get_error_string (eglGetError ()));
          goto done;
        }
      }
      egl->egl_surface =
          eglCreateWindowSurface (egl->egl_display, egl->egl_config, handle,
          NULL);
      egl->window_handle = handle;

      if (egl->egl_surface == EGL_NO_SURFACE) {
        GST_ERROR_OBJECT (context, "Failed to create window surface: %s",
            gst_egl_get_error_string (eglGetError ()));
        result = FALSE;
        goto done;
      }
    }
    result = eglMakeCurrent (egl->egl_display, egl->egl_surface,
        egl->egl_surface, egl->egl_context);
  } else {
    result = eglMakeCurrent (egl->egl_display, EGL_NO_SURFACE,
        EGL_NO_SURFACE, EGL_NO_CONTEXT);
  }

  if (!result) {
    GST_ERROR_OBJECT (context,
        "Failed to bind context to the current rendering thread: %s",
        gst_egl_get_error_string (eglGetError ()));
  }

done:
  return result;
}
コード例 #5
0
static gboolean
gst_gl_context_wgl_create_context (GstGLContext * context,
    GstGLAPI gl_api, GstGLContext * other_context, GError ** error)
{
  GstGLWindow *window;
  GstGLContextWGL *context_wgl;
  GstGLContextWGL *other_wgl = NULL;
  HDC device;

  context_wgl = GST_GL_CONTEXT_WGL (context);
  window = gst_gl_context_get_window (context);
  device = (HDC) gst_gl_window_get_display (window);

  if (other_context) {
    if (!GST_GL_IS_CONTEXT_WGL (other_context)) {
      g_set_error (error, GST_GL_CONTEXT_ERROR,
          GST_GL_CONTEXT_ERROR_WRONG_CONFIG,
          "Cannot share context with a non-WGL context");
      goto failure;
    }
    other_wgl = (GstGLContextWGL *) other_context;
  }

  context_wgl->wgl_context = wglCreateContext (device);
  if (context_wgl->wgl_context)
    GST_DEBUG ("gl context created: %" G_GUINTPTR_FORMAT,
        (guintptr) context_wgl->wgl_context);
  else {
    g_set_error (error, GST_GL_CONTEXT_ERROR,
        GST_GL_CONTEXT_ERROR_CREATE_CONTEXT, "failed to create glcontext:0x%x",
        (unsigned int) GetLastError ());
    goto failure;
  }
  g_assert (context_wgl->wgl_context);

  GST_LOG ("gl context id: %" G_GUINTPTR_FORMAT,
      (guintptr) context_wgl->wgl_context);

  if (other_wgl) {
    if (!wglShareLists (other_wgl->wgl_context, context_wgl->wgl_context)) {
      g_set_error (error, GST_GL_CONTEXT_ERROR,
          GST_GL_CONTEXT_ERROR_CREATE_CONTEXT, "failed to share contexts 0x%x",
          (unsigned int) GetLastError ());
      goto failure;
    }
  }

  gst_object_unref (window);

  return TRUE;

failure:
  gst_object_unref (window);

  return FALSE;
}
コード例 #6
0
static void
gst_gl_context_wgl_swap_buffers (GstGLContext * context)
{
  GstGLWindow *window = gst_gl_context_get_window (context);
  HDC device = (HDC) gst_gl_window_get_display (window);

  SwapBuffers (device);

  gst_object_unref (window);
}
コード例 #7
0
static gboolean
gst_gl_context_wgl_choose_format (GstGLContext * context, GError ** error)
{
  GstGLWindow *window;
  PIXELFORMATDESCRIPTOR pfd;
  gint pixelformat = 0;
  gboolean res = FALSE;
  HDC device;

  window = gst_gl_context_get_window (context);
  gst_gl_window_win32_create_window (GST_GL_WINDOW_WIN32 (window), error);
  device = (HDC) gst_gl_window_get_display (window);
  gst_object_unref (window);

  pfd.nSize = sizeof (PIXELFORMATDESCRIPTOR);
  pfd.nVersion = 1;
  pfd.dwFlags = PFD_DRAW_TO_WINDOW | PFD_SUPPORT_OPENGL | PFD_DOUBLEBUFFER;
  pfd.iPixelType = PFD_TYPE_RGBA;
  pfd.cColorBits = 24;
  pfd.cRedBits = 8;
  pfd.cRedShift = 0;
  pfd.cGreenBits = 8;
  pfd.cGreenShift = 0;
  pfd.cBlueBits = 8;
  pfd.cBlueShift = 0;
  pfd.cAlphaBits = 0;
  pfd.cAlphaShift = 0;
  pfd.cAccumBits = 0;
  pfd.cAccumRedBits = 0;
  pfd.cAccumGreenBits = 0;
  pfd.cAccumBlueBits = 0;
  pfd.cAccumAlphaBits = 0;
  pfd.cDepthBits = 24;
  pfd.cStencilBits = 8;
  pfd.cAuxBuffers = 0;
  pfd.iLayerType = PFD_MAIN_PLANE;
  pfd.bReserved = 0;
  pfd.dwLayerMask = 0;
  pfd.dwVisibleMask = 0;
  pfd.dwDamageMask = 0;

  pfd.cColorBits = (BYTE) GetDeviceCaps (device, BITSPIXEL);

  pixelformat = ChoosePixelFormat (device, &pfd);

  if (!pixelformat) {
    g_set_error (error, GST_GL_CONTEXT_ERROR, GST_GL_CONTEXT_ERROR_FAILED,
        "Failed to choose a pixel format");
    return FALSE;
  }

  res = SetPixelFormat (device, pixelformat, &pfd);

  return res;
}
コード例 #8
0
static void
gst_gl_context_glx_swap_buffers (GstGLContext * context)
{
  GstGLWindow *window = gst_gl_context_get_window (context);
  Display *device = (Display *) gst_gl_display_get_handle (window->display);
  Window window_handle = (Window) gst_gl_window_get_window_handle (window);

  glXSwapBuffers (device, window_handle);

  gst_object_unref (window);
}
コード例 #9
0
static void
gst_glimage_sink_on_close (GstGLImageSink * gl_sink)
{
  GstGLWindow *window;

  gst_gl_context_set_error (gl_sink->context, "Output window was closed");

  window = gst_gl_context_get_window (gl_sink->context);

  g_signal_handler_disconnect (window, gl_sink->key_sig_id);
  g_signal_handler_disconnect (window, gl_sink->mouse_sig_id);

  g_atomic_int_set (&gl_sink->to_quit, 1);

  gst_object_unref (window);
}
コード例 #10
0
static void
setup (void)
{
  GError *error = NULL;

  display = gst_gl_display_new ();
  context = gst_gl_context_new (display);

  gst_gl_context_create (context, 0, &error);
  window = gst_gl_context_get_window (context);

  fail_if (error != NULL, "Error creating context: %s\n",
      error ? error->message : "Unknown Error");

  upload = gst_gl_upload_new (context);
}
コード例 #11
0
static GstVaapiDisplay *
gst_vaapi_create_display_from_gl_context (GstObject * gl_context_object)
{
#if USE_GST_GL_HELPERS
  GstGLContext *const gl_context = GST_GL_CONTEXT (gl_context_object);
  GstGLDisplay *const gl_display = gst_gl_context_get_display (gl_context);
  GstGLDisplayType gl_display_type;
  GstGLPlatform gl_platform;
  gpointer native_display;
  GstVaapiDisplay *display = NULL;
  GstVaapiDisplayType display_type;

  /* Get display type and the native hanler */
  gl_display_type = gst_gl_display_get_handle_type (gl_display);
  gl_platform = gst_gl_context_get_gl_platform (gl_context);
  display_type =
      gst_vaapi_get_display_type_from_gl (gl_display_type, gl_platform);

  native_display = GSIZE_TO_POINTER (gst_gl_display_get_handle (gl_display));

  if (display_type == GST_VAAPI_DISPLAY_TYPE_ANY) {
    /* derive type and native_display from the active window */
    GstGLWindow *const gl_window = gst_gl_context_get_window (gl_context);
    if (gl_window)
      native_display = GSIZE_TO_POINTER (gst_gl_window_get_display (gl_window));
    display_type = gst_vaapi_get_display_type_from_gl_env ();
  }

  if (gl_platform == GST_GL_PLATFORM_EGL) {
    display = gst_vaapi_create_display_from_egl (gl_display, gl_context,
        display_type, native_display);
  }

  /* Non-EGL and fallback */
  if (!display) {
    display =
        gst_vaapi_create_display_from_handle (display_type, native_display);
  }

  gst_object_unref (gl_display);

  return display;
#endif
  GST_ERROR ("No GstGL support");
  return NULL;
}
コード例 #12
0
static void
gst_gl_context_glx_destroy_context (GstGLContext * context)
{
  GstGLWindow *window;
  GstGLContextGLX *context_glx;
  Display *device;

  context_glx = GST_GL_CONTEXT_GLX (context);
  window = gst_gl_context_get_window (context);
  device = (Display *) gst_gl_display_get_handle (window->display);

  glXDestroyContext (device, context_glx->glx_context);

  context_glx->glx_context = 0;

  gst_object_unref (window);
}
コード例 #13
0
static gboolean
gst_gl_context_glx_activate (GstGLContext * context, gboolean activate)
{
  GstGLWindow *window = gst_gl_context_get_window (context);
  Display *device = (Display *) gst_gl_display_get_handle (window->display);
  Window window_handle = (Window) gst_gl_window_get_window_handle (window);
  gboolean result;

  if (activate) {
    result = glXMakeCurrent (device, window_handle,
        GST_GL_CONTEXT_GLX (context)->glx_context);
  } else {
    result = glXMakeCurrent (device, None, NULL);
  }

  gst_object_unref (window);

  return result;
}
static void
gst_glimage_sink_expose (GstVideoOverlay * overlay)
{
  GstGLImageSink *glimage_sink = GST_GLIMAGE_SINK (overlay);

  /* redisplay opengl scene */
  if (glimage_sink->display && glimage_sink->window_id) {

    if (glimage_sink->window_id != glimage_sink->new_window_id) {
      GstGLWindow *window = gst_gl_context_get_window (glimage_sink->context);

      glimage_sink->window_id = glimage_sink->new_window_id;
      gst_gl_window_set_window_handle (window, glimage_sink->window_id);

      gst_object_unref (window);
    }

    gst_glimage_sink_redisplay (glimage_sink);
  }
}
コード例 #15
0
static void
gst_glimage_sink_navigation_send_event (GstNavigation * navigation, GstStructure
    * structure)
{
  GstGLImageSink *sink = GST_GLIMAGE_SINK (navigation);
  GstEvent *event = NULL;
  GstPad *pad = NULL;
  GstGLWindow *window = gst_gl_context_get_window (sink->context);
  guint width, height;
  gdouble x, y, xscale, yscale;

  g_return_if_fail (GST_GL_IS_WINDOW (window));

  width = GST_VIDEO_SINK_WIDTH (sink);
  height = GST_VIDEO_SINK_HEIGHT (sink);
  gst_gl_window_get_surface_dimensions (window, &width, &height);

  event = gst_event_new_navigation (structure);

  pad = gst_pad_get_peer (GST_VIDEO_SINK_PAD (sink));
  /* Converting pointer coordinates to the non scaled geometry */
  if (width != GST_VIDEO_SINK_WIDTH (sink) &&
      width != 0 && gst_structure_get_double (structure, "pointer_x", &x)) {
    xscale = (gdouble) GST_VIDEO_SINK_WIDTH (sink) / width;
    gst_structure_set (structure, "pointer_x", G_TYPE_DOUBLE,
        (gdouble) x * xscale, NULL);
  }
  if (height != GST_VIDEO_SINK_HEIGHT (sink) &&
      height != 0 && gst_structure_get_double (structure, "pointer_y", &y)) {
    yscale = (gdouble) GST_VIDEO_SINK_HEIGHT (sink) / height;
    gst_structure_set (structure, "pointer_y", G_TYPE_DOUBLE,
        (gdouble) y * yscale, NULL);
  }


  if (GST_IS_PAD (pad) && GST_IS_EVENT (event))
    gst_pad_send_event (pad, event);

  gst_object_unref (pad);
  gst_object_unref (window);
}
コード例 #16
0
static GstFlowReturn
gst_glimage_sink_prepare (GstBaseSink * bsink, GstBuffer * buf)
{
  GstGLImageSink *glimage_sink;

  glimage_sink = GST_GLIMAGE_SINK (bsink);

  GST_TRACE ("preparing buffer:%p", buf);

  if (GST_VIDEO_SINK_WIDTH (glimage_sink) < 1 ||
      GST_VIDEO_SINK_HEIGHT (glimage_sink) < 1) {
    return GST_FLOW_NOT_NEGOTIATED;
  }

  if (!_ensure_gl_setup (glimage_sink))
    return GST_FLOW_NOT_NEGOTIATED;

  if (!gst_gl_upload_perform_with_buffer (glimage_sink->upload, buf,
          &glimage_sink->next_tex))
    goto upload_failed;

  if (glimage_sink->window_id != glimage_sink->new_window_id) {
    GstGLWindow *window = gst_gl_context_get_window (glimage_sink->context);

    glimage_sink->window_id = glimage_sink->new_window_id;
    gst_gl_window_set_window_handle (window, glimage_sink->window_id);

    gst_object_unref (window);
  }

  return GST_FLOW_OK;

upload_failed:
  {
    GST_ELEMENT_ERROR (glimage_sink, RESOURCE, NOT_FOUND,
        ("%s", "Failed to upload buffer"), (NULL));
    return GST_FLOW_ERROR;
  }
}
コード例 #17
0
static gboolean
gst_gl_context_wgl_activate (GstGLContext * context, gboolean activate)
{
  GstGLWindow *window;
  GstGLContextWGL *context_wgl;
  HDC device;
  gboolean result;

  window = gst_gl_context_get_window (context);
  context_wgl = GST_GL_CONTEXT_WGL (context);
  device = (HDC) gst_gl_window_get_display (window);

  if (activate) {
    result = wglMakeCurrent (device, context_wgl->wgl_context);
  } else {
    result = wglMakeCurrent (NULL, NULL);
  }

  gst_object_unref (window);

  return result;
}
コード例 #18
0
static gboolean
gst_glimage_sink_redisplay (GstGLImageSink * gl_sink)
{
  GstGLWindow *window;
  gboolean alive;

  window = gst_gl_context_get_window (gl_sink->context);
  if (!window)
    return FALSE;

  if (gst_gl_window_is_running (window)) {

#if GST_GL_HAVE_GLES2
    if (USING_GLES2 (gl_sink->context)) {
      if (G_UNLIKELY (!gl_sink->redisplay_shader)) {
        gst_gl_window_send_message (window,
            GST_GL_WINDOW_CB (gst_glimage_sink_thread_init_redisplay), gl_sink);

        /* if the shader is still null it means it failed to be useable */
        if (G_UNLIKELY (!gl_sink->redisplay_shader)) {
          gst_object_unref (window);
          return FALSE;
        }
      }
    }
#endif

    /* Drawing is asynchronous: gst_gl_window_draw is not blocking
     * It means that it does not wait for stuff to be executed in other threads
     */
    gst_gl_window_draw (window, GST_VIDEO_SINK_WIDTH (gl_sink),
        GST_VIDEO_SINK_HEIGHT (gl_sink));
  }
  alive = gst_gl_window_is_running (window);
  gst_object_unref (window);

  return alive;
}
static void
gst_glimage_sink_on_draw (const GstGLImageSink * gl_sink)
{
  /* Here gl_sink members (ex:gl_sink->info) have a life time of set_caps.
   * It means that they cannot not change between two set_caps as well as
   * for the redisplay_texture size.
   * Whereas redisplay_texture id changes every sink_render
   */

  const GstGLFuncs *gl = NULL;
  GstGLWindow *window = NULL;

  g_return_if_fail (GST_IS_GLIMAGE_SINK (gl_sink));

  gl = gl_sink->context->gl_vtable;

  GST_GLIMAGE_SINK_LOCK (gl_sink);

  /* check if texture is ready for being drawn */
  if (!gl_sink->redisplay_texture) {
    GST_GLIMAGE_SINK_UNLOCK (gl_sink);
    return;
  }

  window = gst_gl_context_get_window (gl_sink->context);
  window->is_drawing = TRUE;

  /* opengl scene */
  GST_TRACE ("redrawing texture:%u", gl_sink->redisplay_texture);

  /* make sure that the environnement is clean */
  gst_gl_context_clear_shader (gl_sink->context);

#if GST_GL_HAVE_OPENGL
  if (USING_OPENGL (gl_sink->context))
    gl->Disable (GL_TEXTURE_2D);
#endif

  gl->BindTexture (GL_TEXTURE_2D, 0);

  /* check if a client draw callback is registered */
  if (gl_sink->clientDrawCallback) {

    gboolean doRedisplay =
        gl_sink->clientDrawCallback (gl_sink->redisplay_texture,
        GST_VIDEO_INFO_WIDTH (&gl_sink->info),
        GST_VIDEO_INFO_HEIGHT (&gl_sink->info),
        gl_sink->client_data);

    if (doRedisplay)
      gst_gl_window_draw_unlocked (window,
          GST_VIDEO_INFO_WIDTH (&gl_sink->info),
          GST_VIDEO_INFO_HEIGHT (&gl_sink->info));
  }
  /* default opengl scene */
  else {
#if GST_GL_HAVE_OPENGL
    if (USING_OPENGL (gl_sink->context)) {
      GLfloat verts[8] = { 1.0f, 1.0f,
        -1.0f, 1.0f,
        -1.0f, -1.0f,
        1.0f, -1.0f
      };
      GLfloat texcoords[8] = { 1.0f, 0.0f,
        0.0f, 0.0f,
        0.0f, 1.0f,
        1.0f, 1.0f
      };
      gl->Clear (GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

      gl->MatrixMode (GL_PROJECTION);
      gl->LoadIdentity ();

      gl->Enable (GL_TEXTURE_2D);
      gl->BindTexture (GL_TEXTURE_2D, gl_sink->redisplay_texture);

      gl->EnableClientState (GL_VERTEX_ARRAY);
      gl->EnableClientState (GL_TEXTURE_COORD_ARRAY);
      gl->VertexPointer (2, GL_FLOAT, 0, &verts);
      gl->TexCoordPointer (2, GL_FLOAT, 0, &texcoords);

      gl->DrawArrays (GL_TRIANGLE_FAN, 0, 4);

      gl->DisableClientState (GL_VERTEX_ARRAY);
      gl->DisableClientState (GL_TEXTURE_COORD_ARRAY);

      gl->Disable (GL_TEXTURE_2D);
    }
#endif
#if GST_GL_HAVE_GLES2
    if (USING_GLES2 (gl_sink->context)) {
      const GLfloat vVertices[] = { 1.0f, 1.0f, 0.0f,
        1.0f, 0.0f,
        -1.0f, 1.0f, 0.0f,
        0.0f, 0.0f,
        -1.0f, -1.0f, 0.0f,
        0.0f, 1.0f,
        1.0f, -1.0f, 0.0f,
        1.0f, 1.0f
      };

      GLushort indices[] = { 0, 1, 2, 0, 2, 3 };

      gl->Clear (GL_COLOR_BUFFER_BIT);

      gst_gl_shader_use (gl_sink->redisplay_shader);

      /* Load the vertex position */
      gl->VertexAttribPointer (gl_sink->redisplay_attr_position_loc, 3,
          GL_FLOAT, GL_FALSE, 5 * sizeof (GLfloat), vVertices);

      /* Load the texture coordinate */
      gl->VertexAttribPointer (gl_sink->redisplay_attr_texture_loc, 2,
          GL_FLOAT, GL_FALSE, 5 * sizeof (GLfloat), &vVertices[3]);

      gl->EnableVertexAttribArray (gl_sink->redisplay_attr_position_loc);
      gl->EnableVertexAttribArray (gl_sink->redisplay_attr_texture_loc);

      gl->ActiveTexture (GL_TEXTURE0);
      gl->BindTexture (GL_TEXTURE_2D, gl_sink->redisplay_texture);
      gst_gl_shader_set_uniform_1i (gl_sink->redisplay_shader, "s_texture", 0);

      gl->DrawElements (GL_TRIANGLES, 6, GL_UNSIGNED_SHORT, indices);
    }
#endif
  }                             /* end default opengl scene */

  window->is_drawing = FALSE;
  gst_object_unref (window);

  GST_GLIMAGE_SINK_UNLOCK (gl_sink);
}
コード例 #20
0
static gboolean
gst_gl_context_glx_choose_format (GstGLContext * context, GError ** error)
{
  GstGLContextGLX *context_glx;
  GstGLWindow *window;
  GstGLWindowX11 *window_x11;
  gint error_base;
  gint event_base;
  Display *device;

  context_glx = GST_GL_CONTEXT_GLX (context);
  window = gst_gl_context_get_window (context);
  window_x11 = GST_GL_WINDOW_X11 (window);
  device = (Display *) gst_gl_display_get_handle (window->display);

  if (!glXQueryExtension (device, &error_base, &event_base)) {
    g_set_error (error, GST_GL_CONTEXT_ERROR,
        GST_GL_CONTEXT_ERROR_RESOURCE_UNAVAILABLE, "No GLX extension");
    goto failure;
  }

  if (!glXQueryVersion (device, &context_glx->priv->glx_major,
          &context_glx->priv->glx_minor)) {
    g_set_error (error, GST_GL_CONTEXT_ERROR,
        GST_GL_CONTEXT_ERROR_CREATE_CONTEXT,
        "Failed to query GLX version (glXQueryVersion failed)");
    goto failure;
  }

  GST_INFO ("GLX Version: %d.%d", context_glx->priv->glx_major,
      context_glx->priv->glx_minor);

  /* legacy case */
  if (context_glx->priv->glx_major < 1 || (context_glx->priv->glx_major == 1
          && context_glx->priv->glx_minor < 3)) {
    gint attribs[] = {
      GLX_RGBA,
      GLX_RED_SIZE, 1,
      GLX_GREEN_SIZE, 1,
      GLX_BLUE_SIZE, 1,
      GLX_DEPTH_SIZE, 16,
      GLX_DOUBLEBUFFER,
      None
    };

    window_x11->visual_info = glXChooseVisual (device,
        window_x11->screen_num, attribs);

    if (!window_x11->visual_info) {
      g_set_error (error, GST_GL_CONTEXT_ERROR,
          GST_GL_CONTEXT_ERROR_WRONG_CONFIG,
          "Bad attributes in glXChooseVisual");
      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;

    context_glx->priv->fbconfigs = glXChooseFBConfig (device,
        DefaultScreen (device), attribs, &fbcount);

    if (!context_glx->priv->fbconfigs) {
      g_set_error (error, GST_GL_CONTEXT_ERROR,
          GST_GL_CONTEXT_ERROR_WRONG_CONFIG,
          "Could not find any FBConfig's to use (check attributes?)");
      goto failure;
    }

    _describe_fbconfig (device, context_glx->priv->fbconfigs[0]);

    window_x11->visual_info = glXGetVisualFromFBConfig (device,
        context_glx->priv->fbconfigs[0]);

    if (!window_x11->visual_info) {
      g_set_error (error, GST_GL_CONTEXT_ERROR,
          GST_GL_CONTEXT_ERROR_WRONG_CONFIG, "Bad attributes in FBConfig");
      goto failure;
    }
  }

  gst_gl_window_x11_create_window ((GstGLWindowX11 *) window);

  gst_object_unref (window);

  return TRUE;

failure:
  if (window)
    gst_object_unref (window);

  return FALSE;
}
コード例 #21
0
static gboolean
gst_gl_context_egl_create_context (GstGLContext * context,
    GstGLAPI gl_api, GstGLContext * other_context, GError ** error)
{
  GstGLContextEGL *egl;
  GstGLWindow *window = NULL;
  EGLNativeWindowType window_handle;
  gint i = 0;
  EGLint context_attrib[3];
  EGLint majorVersion;
  EGLint minorVersion;
  const gchar *egl_exts;
  gboolean need_surface = TRUE;
  guintptr external_gl_context = 0;

  egl = GST_GL_CONTEXT_EGL (context);
  window = gst_gl_context_get_window (context);

  if (other_context) {
    if (!GST_GL_IS_CONTEXT_EGL (other_context)) {
      g_set_error (error, GST_GL_CONTEXT_ERROR,
          GST_GL_CONTEXT_ERROR_WRONG_CONFIG,
          "Cannot share context with non-EGL context");
      goto failure;
    }
    external_gl_context = gst_gl_context_get_gl_context (other_context);
  }

  if ((gl_api & (GST_GL_API_OPENGL | GST_GL_API_GLES2)) == GST_GL_API_NONE) {
    g_set_error (error, GST_GL_CONTEXT_ERROR, GST_GL_CONTEXT_ERROR_WRONG_API,
        "EGL supports opengl or gles2");
    goto failure;
  }

  if (other_context) {
    GstGLContextEGL *other_egl = (GstGLContextEGL *) other_context;
    egl->egl_display = other_egl->egl_display;
  } else {
    egl->egl_display = eglGetDisplay ((EGLNativeDisplayType)
        gst_gl_window_get_display (window));
  }

  if (eglInitialize (egl->egl_display, &majorVersion, &minorVersion)) {
    GST_INFO ("egl initialized, version: %d.%d", majorVersion, minorVersion);
  } else {
    g_set_error (error, GST_GL_CONTEXT_ERROR,
        GST_GL_CONTEXT_ERROR_RESOURCE_UNAVAILABLE,
        "Failed to initialize egl: %s", gst_gl_context_egl_get_error_string ());
    goto failure;
  }

  if (gl_api & GST_GL_API_OPENGL) {
    /* egl + opengl only available with EGL 1.4+ */
    if (majorVersion == 1 && minorVersion <= 3) {
      if ((gl_api & ~GST_GL_API_OPENGL) == GST_GL_API_NONE) {
        g_set_error (error, GST_GL_CONTEXT_ERROR, GST_GL_CONTEXT_ERROR_OLD_LIBS,
            "EGL version (%i.%i) too old for OpenGL support, (needed at least 1.4)",
            majorVersion, minorVersion);
        goto failure;
      } else {
        GST_WARNING
            ("EGL version (%i.%i) too old for OpenGL support, (needed at least 1.4)",
            majorVersion, minorVersion);
        if (gl_api & GST_GL_API_GLES2) {
          goto try_gles2;
        } else {
          g_set_error (error, GST_GL_CONTEXT_ERROR,
              GST_GL_CONTEXT_ERROR_WRONG_CONFIG,
              "Failed to choose a suitable OpenGL API");
          goto failure;
        }
      }
    }

    if (!eglBindAPI (EGL_OPENGL_API)) {
      g_set_error (error, GST_GL_CONTEXT_ERROR, GST_GL_CONTEXT_ERROR_FAILED,
          "Failed to bind OpenGL API: %s",
          gst_gl_context_egl_get_error_string ());
      goto failure;
    }

    GST_INFO ("Using OpenGL");
    egl->gl_api = GST_GL_API_OPENGL;
  } else if (gl_api & GST_GL_API_GLES2) {
  try_gles2:
    if (!eglBindAPI (EGL_OPENGL_ES_API)) {
      g_set_error (error, GST_GL_CONTEXT_ERROR, GST_GL_CONTEXT_ERROR_FAILED,
          "Failed to bind OpenGL|ES API: %s",
          gst_gl_context_egl_get_error_string ());
      goto failure;
    }

    GST_INFO ("Using OpenGL|ES 2.0");
    egl->gl_api = GST_GL_API_GLES2;
  }

  if (!gst_gl_context_egl_choose_config (egl, other_context, error)) {
    g_assert (error == NULL || *error != NULL);
    goto failure;
  }

  GST_DEBUG ("about to create gl context\n");

  if (egl->gl_api & GST_GL_API_GLES2) {
    context_attrib[i++] = EGL_CONTEXT_CLIENT_VERSION;
    context_attrib[i++] = 2;
  }
  context_attrib[i++] = EGL_NONE;

  egl->egl_context =
      eglCreateContext (egl->egl_display, egl->egl_config,
      (EGLContext) external_gl_context, context_attrib);

  if (egl->egl_context != EGL_NO_CONTEXT) {
    GST_INFO ("gl context created: %" G_GUINTPTR_FORMAT,
        (guintptr) egl->egl_context);
  } else {
    g_set_error (error, GST_GL_CONTEXT_ERROR,
        GST_GL_CONTEXT_ERROR_CREATE_CONTEXT,
        "Failed to create a OpenGL context: %s",
        gst_gl_context_egl_get_error_string ());
    goto failure;
  }

  egl_exts = eglQueryString (egl->egl_display, EGL_EXTENSIONS);

  if (other_context == NULL) {
    /* FIXME do we want a window vfunc ? */
#if GST_GL_HAVE_WINDOW_X11
    if (GST_GL_IS_WINDOW_X11 (context->window)) {
      gst_gl_window_x11_create_window ((GstGLWindowX11 *) context->window);
    }
#endif
#if GST_GL_HAVE_WINDOW_WIN32
    if (GST_GL_IS_WINDOW_WIN32 (context->window)) {
      gst_gl_window_win32_create_window ((GstGLWindowWin32 *) context->window);
    }
#endif
  }

  window_handle =
      (EGLNativeWindowType) gst_gl_window_get_window_handle (window);

  if (window_handle) {
    egl->egl_surface =
        eglCreateWindowSurface (egl->egl_display, egl->egl_config,
        window_handle, NULL);
  } else if (!gst_gl_check_extension ("EGL_KHR_surfaceless_context", egl_exts)) {
    EGLint surface_attrib[7];
    gint j = 0;

    /* FIXME: Width/height doesn't seem to matter but we can't leave them
     * at 0, otherwise X11 complains about BadValue */
    surface_attrib[j++] = EGL_WIDTH;
    surface_attrib[j++] = 1;
    surface_attrib[j++] = EGL_HEIGHT;
    surface_attrib[j++] = 1;
    surface_attrib[j++] = EGL_LARGEST_PBUFFER;
    surface_attrib[j++] = EGL_TRUE;
    surface_attrib[j++] = EGL_NONE;

    egl->egl_surface =
        eglCreatePbufferSurface (egl->egl_display, egl->egl_config,
        surface_attrib);
  } else {
    egl->egl_surface = EGL_NO_SURFACE;
    need_surface = FALSE;
  }

  if (need_surface) {
    if (egl->egl_surface != EGL_NO_SURFACE) {
      GST_INFO ("surface created");
    } else {
      g_set_error (error, GST_GL_CONTEXT_ERROR, GST_GL_CONTEXT_ERROR_FAILED,
          "Failed to create window surface: %s",
          gst_gl_context_egl_get_error_string ());
      goto failure;
    }
  }

  gst_object_unref (window);

  return TRUE;

failure:
  if (window)
    gst_object_unref (window);

  return FALSE;
}
static GstFlowReturn
gst_glimage_sink_render (GstBaseSink * bsink, GstBuffer * buf)
{
  GstGLImageSink *glimage_sink;
  guint tex_id;

  GST_TRACE ("rendering buffer:%p", buf);

  glimage_sink = GST_GLIMAGE_SINK (bsink);

  if (GST_VIDEO_SINK_WIDTH (glimage_sink) < 1 ||
      GST_VIDEO_SINK_HEIGHT (glimage_sink) < 1) {
    return GST_FLOW_NOT_NEGOTIATED;
  }

  if (!_ensure_gl_setup (glimage_sink))
    return GST_FLOW_NOT_NEGOTIATED;

  if (!gst_gl_upload_perform_with_buffer (glimage_sink->upload, buf, &tex_id))
    goto upload_failed;

  if (glimage_sink->window_id != glimage_sink->new_window_id) {
    GstGLWindow *window = gst_gl_context_get_window (glimage_sink->context);

    glimage_sink->window_id = glimage_sink->new_window_id;
    gst_gl_window_set_window_handle (window, glimage_sink->window_id);

    gst_object_unref (window);
  }

  GST_TRACE ("redisplay texture:%u of size:%ux%u, window size:%ux%u", tex_id,
      GST_VIDEO_INFO_WIDTH (&glimage_sink->info),
      GST_VIDEO_INFO_HEIGHT (&glimage_sink->info),
      GST_VIDEO_SINK_WIDTH (glimage_sink),
      GST_VIDEO_SINK_HEIGHT (glimage_sink));

  /* Avoid to release the texture while drawing */
  GST_GLIMAGE_SINK_LOCK (glimage_sink);
  glimage_sink->redisplay_texture = tex_id;
  GST_GLIMAGE_SINK_UNLOCK (glimage_sink);

  /* Ask the underlying window to redraw its content */
  if (!gst_glimage_sink_redisplay (glimage_sink))
    goto redisplay_failed;

  GST_TRACE ("post redisplay");

  if (g_atomic_int_get (&glimage_sink->to_quit) != 0) {
    GST_ELEMENT_ERROR (glimage_sink, RESOURCE, NOT_FOUND,
        ("%s", gst_gl_context_get_error ()), (NULL));
    gst_gl_upload_release_buffer (glimage_sink->upload);
    return GST_FLOW_ERROR;
  }

  gst_gl_upload_release_buffer (glimage_sink->upload);
  return GST_FLOW_OK;

/* ERRORS */
redisplay_failed:
  {
    gst_gl_upload_release_buffer (glimage_sink->upload);
    GST_ELEMENT_ERROR (glimage_sink, RESOURCE, NOT_FOUND,
        ("%s", gst_gl_context_get_error ()), (NULL));
    return GST_FLOW_ERROR;
  }

upload_failed:
  {
    GST_ELEMENT_ERROR (glimage_sink, RESOURCE, NOT_FOUND,
        ("%s", "Failed to upload format"), (NULL));
    return FALSE;
  }
}
コード例 #23
0
static GstStateChangeReturn
gst_glimage_sink_change_state (GstElement * element, GstStateChange transition)
{
  GstGLImageSink *glimage_sink;
  GstStateChangeReturn ret = GST_STATE_CHANGE_SUCCESS;

  GST_DEBUG ("changing state: %s => %s",
      gst_element_state_get_name (GST_STATE_TRANSITION_CURRENT (transition)),
      gst_element_state_get_name (GST_STATE_TRANSITION_NEXT (transition)));

  glimage_sink = GST_GLIMAGE_SINK (element);

  switch (transition) {
    case GST_STATE_CHANGE_NULL_TO_READY:
      break;
    case GST_STATE_CHANGE_READY_TO_PAUSED:
      g_atomic_int_set (&glimage_sink->to_quit, 0);
      if (!glimage_sink->display) {
        if (!gst_gl_ensure_display (glimage_sink, &glimage_sink->display))
          return GST_STATE_CHANGE_FAILURE;
      }
      break;
    case GST_STATE_CHANGE_PAUSED_TO_PLAYING:
      break;
    default:
      break;
  }

  ret = GST_ELEMENT_CLASS (parent_class)->change_state (element, transition);
  if (ret == GST_STATE_CHANGE_FAILURE)
    return ret;

  switch (transition) {
    case GST_STATE_CHANGE_PLAYING_TO_PAUSED:
      break;
    case GST_STATE_CHANGE_PAUSED_TO_READY:
    {
      /* mark the redisplay_texture as unavailable (=0)
       * to avoid drawing
       */
      GST_GLIMAGE_SINK_LOCK (glimage_sink);
      glimage_sink->redisplay_texture = 0;
      if (glimage_sink->stored_buffer) {
        gst_buffer_unref (glimage_sink->stored_buffer);
        glimage_sink->stored_buffer = NULL;
      }
      GST_GLIMAGE_SINK_UNLOCK (glimage_sink);

      if (glimage_sink->upload) {
        gst_object_unref (glimage_sink->upload);
        glimage_sink->upload = NULL;
      }

      glimage_sink->window_id = 0;
      //but do not reset glimage_sink->new_window_id

      if (glimage_sink->pool) {
        gst_buffer_pool_set_active (glimage_sink->pool, FALSE);
        gst_object_unref (glimage_sink->pool);
        glimage_sink->pool = NULL;
      }

      GST_VIDEO_SINK_WIDTH (glimage_sink) = 1;
      GST_VIDEO_SINK_HEIGHT (glimage_sink) = 1;
      if (glimage_sink->context) {
        GstGLWindow *window = gst_gl_context_get_window (glimage_sink->context);

        gst_gl_window_send_message (window,
            GST_GL_WINDOW_CB (gst_glimage_sink_cleanup_glthread), glimage_sink);

        gst_gl_window_set_resize_callback (window, NULL, NULL, NULL);
        gst_gl_window_set_draw_callback (window, NULL, NULL, NULL);
        gst_gl_window_set_close_callback (window, NULL, NULL, NULL);

        gst_object_unref (window);
        gst_object_unref (glimage_sink->context);
        glimage_sink->context = NULL;
      }

      if (glimage_sink->display) {
        gst_object_unref (glimage_sink->display);
        glimage_sink->display = NULL;
      }
      break;
    }
    case GST_STATE_CHANGE_READY_TO_NULL:
      break;
    default:
      break;
  }

  return ret;
}
コード例 #24
0
static gboolean
gst_gl_context_egl_create_context (GstGLContext * context,
    GstGLAPI gl_api, GstGLContext * other_context, GError ** error)
{
  GstGLContextEGL *egl;
  GstGLWindow *window = NULL;
  EGLNativeWindowType window_handle = (EGLNativeWindowType) 0;
  EGLint egl_major;
  EGLint egl_minor;
  gboolean need_surface = TRUE;
  guintptr external_gl_context = 0;
  guintptr egl_display;

  egl = GST_GL_CONTEXT_EGL (context);
  window = gst_gl_context_get_window (context);

  GST_DEBUG_OBJECT (context, "Creating EGL context");

  if (other_context) {
    if (gst_gl_context_get_gl_platform (other_context) != GST_GL_PLATFORM_EGL) {
      g_set_error (error, GST_GL_CONTEXT_ERROR,
          GST_GL_CONTEXT_ERROR_WRONG_CONFIG,
          "Cannot share context with non-EGL context");
      goto failure;
    }
    external_gl_context = gst_gl_context_get_gl_context (other_context);
  }

  if ((gl_api & (GST_GL_API_OPENGL | GST_GL_API_OPENGL3 | GST_GL_API_GLES2)) ==
      GST_GL_API_NONE) {
    g_set_error (error, GST_GL_CONTEXT_ERROR, GST_GL_CONTEXT_ERROR_WRONG_API,
        "EGL supports opengl or gles2");
    goto failure;
  }

  if (!egl->display_egl) {
    GstGLDisplay *display = gst_gl_context_get_display (context);

    egl->display_egl = gst_gl_display_egl_from_gl_display (display);
    if (!egl->display_egl) {
      g_set_error (error, GST_GL_CONTEXT_ERROR,
          GST_GL_CONTEXT_ERROR_RESOURCE_UNAVAILABLE,
          "Failed to create EGLDisplay from native display");
      goto failure;
    }

    gst_object_unref (display);
  }

  egl_display = gst_gl_display_get_handle (GST_GL_DISPLAY (egl->display_egl));
  egl->egl_display = (EGLDisplay) egl_display;

  if (eglInitialize (egl->egl_display, &egl_major, &egl_minor)) {
    GST_INFO ("egl initialized, version: %d.%d", egl_major, egl_minor);
  } else {
    g_set_error (error, GST_GL_CONTEXT_ERROR,
        GST_GL_CONTEXT_ERROR_RESOURCE_UNAVAILABLE,
        "Failed to initialize egl: %s",
        gst_egl_get_error_string (eglGetError ()));
    goto failure;
  }

  egl->egl_exts = eglQueryString (egl->egl_display, EGL_EXTENSIONS);

  if (gl_api & (GST_GL_API_OPENGL | GST_GL_API_OPENGL3)) {
    GstGLAPI chosen_gl_api = 0;
    gint i;

    /* egl + opengl only available with EGL 1.4+ */
    if (egl_major == 1 && egl_minor <= 3) {
      if ((gl_api & ~GST_GL_API_OPENGL) == GST_GL_API_NONE) {
        g_set_error (error, GST_GL_CONTEXT_ERROR, GST_GL_CONTEXT_ERROR_OLD_LIBS,
            "EGL version (%i.%i) too old for OpenGL support, (needed at least 1.4)",
            egl_major, egl_minor);
        goto failure;
      } else {
        GST_WARNING
            ("EGL version (%i.%i) too old for OpenGL support, (needed at least 1.4)",
            egl_major, egl_minor);
        if (gl_api & GST_GL_API_GLES2) {
          goto try_gles2;
        } else {
          g_set_error (error, GST_GL_CONTEXT_ERROR,
              GST_GL_CONTEXT_ERROR_WRONG_CONFIG,
              "Failed to choose a suitable OpenGL API");
          goto failure;
        }
      }
    }

    if (!eglBindAPI (EGL_OPENGL_API)) {
      g_set_error (error, GST_GL_CONTEXT_ERROR, GST_GL_CONTEXT_ERROR_FAILED,
          "Failed to bind OpenGL API: %s",
          gst_egl_get_error_string (eglGetError ()));
      goto failure;
    }

    GST_INFO ("Bound OpenGL");

    /* api, version only matters for gles */
    if (!gst_gl_context_egl_choose_config (egl, GST_GL_API_OPENGL, 0, error)) {
      g_assert (error == NULL || *error != NULL);
      goto failure;
    }

    for (i = 0; i < G_N_ELEMENTS (opengl_versions); i++) {
      gint profileMask = 0;
      gint contextFlags = 0;

      if (GST_GL_CHECK_GL_VERSION (opengl_versions[i].major,
              opengl_versions[i].minor, 3, 2)) {
        /* skip gl3 contexts if requested */
        if ((gl_api & GST_GL_API_OPENGL3) == 0)
          continue;

        chosen_gl_api = GST_GL_API_OPENGL3;
#if defined(EGL_KHR_create_context)
        profileMask |= EGL_CONTEXT_OPENGL_CORE_PROFILE_BIT_KHR;
        contextFlags |= EGL_CONTEXT_OPENGL_DEBUG_BIT_KHR;
#endif
      } else if (opengl_versions[i].major == 3 && opengl_versions[i].minor == 1) {
        /* skip 3.1, the implementation is free to give us either a core or a
         * compatibility context (we have no say) */
        continue;
      } else {
        /* skip legacy contexts if requested */
        if ((gl_api & GST_GL_API_OPENGL) == 0)
          continue;

        chosen_gl_api = GST_GL_API_OPENGL;
      }

      egl->egl_context =
          _create_context_with_flags (egl, (EGLContext) external_gl_context,
          chosen_gl_api, opengl_versions[i].major,
          opengl_versions[i].minor, contextFlags, profileMask);

      if (egl->egl_context)
        break;

#if defined(EGL_KHR_create_context)
      profileMask &= ~EGL_CONTEXT_OPENGL_DEBUG_BIT_KHR;

      egl->egl_context =
          _create_context_with_flags (egl, (EGLContext) external_gl_context,
          chosen_gl_api, opengl_versions[i].major,
          opengl_versions[i].minor, contextFlags, profileMask);

      if (egl->egl_context)
        break;
#endif
    }

    egl->gl_api = chosen_gl_api;
  } else if (gl_api & GST_GL_API_GLES2) {
    gint i;

  try_gles2:
    if (!eglBindAPI (EGL_OPENGL_ES_API)) {
      g_set_error (error, GST_GL_CONTEXT_ERROR, GST_GL_CONTEXT_ERROR_FAILED,
          "Failed to bind OpenGL|ES API: %s",
          gst_egl_get_error_string (eglGetError ()));
      goto failure;
    }

    GST_INFO ("Bound OpenGL|ES");

    for (i = 0; i < G_N_ELEMENTS (gles2_versions); i++) {
      gint profileMask = 0;
      gint contextFlags = 0;

      if (!gst_gl_context_egl_choose_config (egl, GST_GL_API_GLES2,
              gles2_versions[i].major, error)) {
        continue;
      }
#if defined(EGL_KHR_create_context)
      /* try a debug context */
      contextFlags |= EGL_CONTEXT_OPENGL_DEBUG_BIT_KHR;

      egl->egl_context =
          _create_context_with_flags (egl, (EGLContext) external_gl_context,
          GST_GL_API_GLES2, gles2_versions[i].major,
          gles2_versions[i].minor, contextFlags, profileMask);

      if (egl->egl_context)
        break;

      /* try without a debug context */
      contextFlags &= ~EGL_CONTEXT_OPENGL_DEBUG_BIT_KHR;
#endif

      egl->egl_context =
          _create_context_with_flags (egl, (EGLContext) external_gl_context,
          GST_GL_API_GLES2, gles2_versions[i].major,
          gles2_versions[i].minor, contextFlags, profileMask);

      if (egl->egl_context)
        break;
    }
    egl->gl_api = GST_GL_API_GLES2;
  }

  if (egl->egl_context != EGL_NO_CONTEXT) {
    GST_INFO ("gl context created: %" G_GUINTPTR_FORMAT,
        (guintptr) egl->egl_context);
  } else {
    g_set_error (error, GST_GL_CONTEXT_ERROR,
        GST_GL_CONTEXT_ERROR_CREATE_CONTEXT,
        "Failed to create a OpenGL context: %s",
        gst_egl_get_error_string (eglGetError ()));
    goto failure;
  }
  /* FIXME do we want a window vfunc ? */
#if GST_GL_HAVE_WINDOW_X11
  if (GST_IS_GL_WINDOW_X11 (context->window)) {
    gst_gl_window_x11_create_window ((GstGLWindowX11 *) context->window);
  }
#endif

  if (other_context == NULL) {
    /* FIXME: fails to show two outputs at all.  We need a property/option for
     * glimagesink to say its a visible context */
#if GST_GL_HAVE_WINDOW_WAYLAND
    if (GST_IS_GL_WINDOW_WAYLAND_EGL (context->window)) {
      gst_gl_window_wayland_egl_create_window ((GstGLWindowWaylandEGL *)
          context->window);
    }
#endif
#if GST_GL_HAVE_WINDOW_WIN32
    if (GST_IS_GL_WINDOW_WIN32 (context->window)) {
      gst_gl_window_win32_create_window ((GstGLWindowWin32 *) context->window);
    }
#endif
#if GST_GL_HAVE_WINDOW_DISPMANX
    if (GST_IS_GL_WINDOW_DISPMANX_EGL (context->window)) {
      gst_gl_window_dispmanx_egl_create_window ((GstGLWindowDispmanxEGL *)
          context->window);
    }
#endif
  }

  if (window)
    window_handle =
        (EGLNativeWindowType) gst_gl_window_get_window_handle (window);

  if (window_handle) {
    GST_DEBUG ("Creating EGLSurface from window_handle %p",
        (void *) window_handle);
    egl->egl_surface =
        eglCreateWindowSurface (egl->egl_display, egl->egl_config,
        window_handle, NULL);
    /* Store window handle for later comparision */
    egl->window_handle = window_handle;
  } else if (!gst_gl_check_extension ("EGL_KHR_surfaceless_context",
          egl->egl_exts)) {
    EGLint surface_attrib[7];
    gint j = 0;

    GST_DEBUG ("Surfaceless context, creating PBufferSurface");
    /* FIXME: Width/height doesn't seem to matter but we can't leave them
     * at 0, otherwise X11 complains about BadValue */
    surface_attrib[j++] = EGL_WIDTH;
    surface_attrib[j++] = 1;
    surface_attrib[j++] = EGL_HEIGHT;
    surface_attrib[j++] = 1;
    surface_attrib[j++] = EGL_LARGEST_PBUFFER;
    surface_attrib[j++] = EGL_TRUE;
    surface_attrib[j++] = EGL_NONE;

    egl->egl_surface =
        eglCreatePbufferSurface (egl->egl_display, egl->egl_config,
        surface_attrib);
  } else {
    GST_DEBUG ("No surface/handle !");
    egl->egl_surface = EGL_NO_SURFACE;
    need_surface = FALSE;
  }

  if (need_surface) {
    if (egl->egl_surface != EGL_NO_SURFACE) {
      GST_INFO ("surface created");
    } else {
      g_set_error (error, GST_GL_CONTEXT_ERROR, GST_GL_CONTEXT_ERROR_FAILED,
          "Failed to create window surface: %s",
          gst_egl_get_error_string (eglGetError ()));
      goto failure;
    }
  }
  egl->egl_major = egl_major;
  egl->egl_minor = egl_minor;

  if (window)
    gst_object_unref (window);

  return TRUE;

failure:
  if (window)
    gst_object_unref (window);

  return FALSE;
}
コード例 #25
0
static GstVaapiDisplay *
gst_vaapi_create_display_from_gl_context (GstObject * gl_context_object)
{
#if USE_GST_GL_HELPERS
  GstGLContext *const gl_context = GST_GL_CONTEXT (gl_context_object);
  GstGLDisplay *const gl_display = gst_gl_context_get_display (gl_context);
  gpointer native_display =
      GSIZE_TO_POINTER (gst_gl_display_get_handle (gl_display));
  GstVaapiDisplay *display, *out_display;
  GstVaapiDisplayType display_type;

  switch (gst_gl_display_get_handle_type (gl_display)) {
#if USE_X11
    case GST_GL_DISPLAY_TYPE_X11:
      display_type = GST_VAAPI_DISPLAY_TYPE_X11;
      break;
#endif
#if USE_WAYLAND
    case GST_GL_DISPLAY_TYPE_WAYLAND:
      display_type = GST_VAAPI_DISPLAY_TYPE_WAYLAND;
      break;
#endif
    case GST_GL_DISPLAY_TYPE_ANY:{
      /* Derive from the active window */
      GstGLWindow *const gl_window = gst_gl_context_get_window (gl_context);
      const gchar *const gl_window_type = g_getenv ("GST_GL_WINDOW");

      display_type = GST_VAAPI_DISPLAY_TYPE_ANY;
      if (!gl_window)
        break;
      native_display = GSIZE_TO_POINTER (gst_gl_window_get_display (gl_window));

      if (gl_window_type) {
#if USE_X11
        if (!display_type && g_strcmp0 (gl_window_type, "x11") == 0)
          display_type = GST_VAAPI_DISPLAY_TYPE_X11;
#endif
#if USE_WAYLAND
        if (!display_type && g_strcmp0 (gl_window_type, "wayland") == 0)
          display_type = GST_VAAPI_DISPLAY_TYPE_WAYLAND;
#endif
      } else {
#if USE_X11
        if (!display_type && GST_GL_HAVE_WINDOW_X11)
          display_type = GST_VAAPI_DISPLAY_TYPE_X11;
#endif
#if USE_WAYLAND
        if (!display_type && GST_GL_HAVE_WINDOW_WAYLAND)
          display_type = GST_VAAPI_DISPLAY_TYPE_WAYLAND;
#endif
      }
      break;
    }
    default:
      display_type = GST_VAAPI_DISPLAY_TYPE_ANY;
      break;
  }
  if (!display_type)
    return NULL;

  display = gst_vaapi_create_display_from_handle (display_type, native_display);
  if (!display)
    return NULL;

  switch (gst_gl_context_get_gl_platform (gl_context)) {
#if USE_EGL
    case GST_GL_PLATFORM_EGL:{
      guint gles_version;

      switch (gst_gl_context_get_gl_api (gl_context)) {
        case GST_GL_API_GLES1:
          gles_version = 1;
          goto create_egl_display;
        case GST_GL_API_GLES2:
          gles_version = 2;
          goto create_egl_display;
        case GST_GL_API_OPENGL:
        case GST_GL_API_OPENGL3:
          gles_version = 0;
        create_egl_display:
          out_display = gst_vaapi_display_egl_new (display, gles_version);
          break;
        default:
          out_display = NULL;
          break;
      }
      if (!out_display)
        return NULL;
      gst_vaapi_display_egl_set_gl_context (GST_VAAPI_DISPLAY_EGL (out_display),
          GSIZE_TO_POINTER (gst_gl_context_get_gl_context (gl_context)));
      break;
    }
#endif
    default:
      out_display = gst_vaapi_display_ref (display);
      break;
  }
  gst_vaapi_display_unref (display);
  return out_display;
#endif
  GST_ERROR ("unsupported GStreamer version %s", GST_API_VERSION_S);
  return NULL;
}
コード例 #26
0
static gboolean
gst_gl_context_glx_create_context (GstGLContext * context,
    GstGLAPI gl_api, GstGLContext * other_context, GError ** error)
{
  GstGLContextGLX *context_glx;
  GstGLWindow *window;
  GstGLWindowX11 *window_x11;
  GstGLDisplay *display = NULL;
  gboolean create_context;
  const char *glx_exts;
  Display *device;
  guintptr external_gl_context = 0;

  context_glx = GST_GL_CONTEXT_GLX (context);
  window = gst_gl_context_get_window (context);

  if (!GST_IS_GL_WINDOW_X11 (window)) {
    g_set_error (error, GST_GL_CONTEXT_ERROR,
        GST_GL_CONTEXT_ERROR_WRONG_CONFIG,
        "Cannot create an GLX context from a non-X11 window");
    goto failure;
  }

  window_x11 = GST_GL_WINDOW_X11 (window);
  display = gst_gl_context_get_display (context);

  if (other_context) {
    if (gst_gl_context_get_gl_platform (other_context) != GST_GL_PLATFORM_GLX) {
      g_set_error (error, GST_GL_CONTEXT_ERROR,
          GST_GL_CONTEXT_ERROR_WRONG_CONFIG,
          "Cannot share context with non-GLX context");
      goto failure;
    }

    external_gl_context = gst_gl_context_get_gl_context (other_context);
  }

  device = (Display *) gst_gl_display_get_handle (display);
  if (!device) {
    g_set_error (error, GST_GL_CONTEXT_ERROR,
        GST_GL_CONTEXT_ERROR_RESOURCE_UNAVAILABLE, "Invalid Display handle");
    goto failure;
  }

  glx_exts = glXQueryExtensionsString (device, DefaultScreen (device));

  create_context = gst_gl_check_extension ("GLX_ARB_create_context", glx_exts);
  context_glx->priv->glXCreateContextAttribsARB =
      (gpointer) glXGetProcAddressARB ((const GLubyte *)
      "glXCreateContextAttribsARB");

  if (!context_glx->glx_context && gl_api & GST_GL_API_OPENGL3 && create_context
      && context_glx->priv->glXCreateContextAttribsARB) {
    gint i;

    for (i = 0; i < G_N_ELEMENTS (opengl_versions); i++) {
      gint profileMask = 0;
      gint contextFlags = 0;

      if ((opengl_versions[i].major > 3
              || (opengl_versions[i].major == 3
                  && opengl_versions[i].minor >= 2))) {
        profileMask |= GLX_CONTEXT_CORE_PROFILE_BIT_ARB;
        contextFlags |= GLX_CONTEXT_DEBUG_BIT_ARB;
      } else {
        break;
      }

      GST_DEBUG_OBJECT (context, "trying to create a GL %d.%d context",
          opengl_versions[i].major, opengl_versions[i].minor);

      context_glx->glx_context = _create_context_with_flags (context_glx,
          device, context_glx->priv->fbconfigs[0],
          (GLXContext) external_gl_context, opengl_versions[i].major,
          opengl_versions[i].minor, contextFlags, profileMask);

      if (context_glx->glx_context) {
        context_glx->priv->context_api = GST_GL_API_OPENGL3;
        break;
      }
    }
  }
  if (!context_glx->glx_context && gl_api & GST_GL_API_OPENGL) {
    context_glx->glx_context =
        glXCreateContext (device, window_x11->visual_info,
        (GLXContext) external_gl_context, TRUE);
    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");
    goto failure;
  }

  GST_LOG ("gl context id: %ld", (gulong) context_glx->glx_context);

  gst_object_unref (window);
  gst_object_unref (display);

  return TRUE;

failure:
  if (window)
    gst_object_unref (window);
  if (display)
    gst_object_unref (display);

  return FALSE;
}
static GstStateChangeReturn
gst_glimage_sink_change_state (GstElement * element, GstStateChange transition)
{
  GstGLImageSink *glimage_sink;
  GstStateChangeReturn ret = GST_STATE_CHANGE_SUCCESS;

  GST_DEBUG ("change state");

  glimage_sink = GST_GLIMAGE_SINK (element);

  switch (transition) {
    case GST_STATE_CHANGE_NULL_TO_READY:
      break;
    case GST_STATE_CHANGE_READY_TO_PAUSED:
      g_atomic_int_set (&glimage_sink->to_quit, 0);
      if (!glimage_sink->display) {
        GstGLWindow *window;
        GError *error = NULL;

        if (!gst_gl_ensure_display (glimage_sink, &glimage_sink->display))
          return GST_STATE_CHANGE_FAILURE;

        glimage_sink->context = gst_gl_context_new (glimage_sink->display);
        window = gst_gl_context_get_window (glimage_sink->context);

        if (!glimage_sink->window_id && !glimage_sink->new_window_id)
          gst_video_overlay_prepare_window_handle (GST_VIDEO_OVERLAY
              (glimage_sink));

        if (glimage_sink->window_id != glimage_sink->new_window_id) {
          glimage_sink->window_id = glimage_sink->new_window_id;
          gst_gl_window_set_window_handle (window, glimage_sink->window_id);
        }

        if (!gst_gl_context_create (glimage_sink->context,
                glimage_sink->other_context, &error)) {
          GST_ELEMENT_ERROR (glimage_sink, RESOURCE, NOT_FOUND, ("%s",
                  error->message), (NULL));

          if (glimage_sink->display) {
            gst_object_unref (glimage_sink->display);
            glimage_sink->display = NULL;
          }
          gst_object_unref (glimage_sink->context);
          gst_object_unref (window);

          return GST_STATE_CHANGE_FAILURE;
        }

        /* setup callbacks */
        gst_gl_window_set_resize_callback (window,
            GST_GL_WINDOW_RESIZE_CB (gst_glimage_sink_on_resize),
            gst_object_ref (glimage_sink), (GDestroyNotify) gst_object_unref);
        gst_gl_window_set_draw_callback (window,
            GST_GL_WINDOW_CB (gst_glimage_sink_on_draw),
            gst_object_ref (glimage_sink), (GDestroyNotify) gst_object_unref);
        gst_gl_window_set_close_callback (window,
            GST_GL_WINDOW_CB (gst_glimage_sink_on_close),
            gst_object_ref (glimage_sink), (GDestroyNotify) gst_object_unref);

        gst_object_unref (window);
      }
      break;
    case GST_STATE_CHANGE_PAUSED_TO_PLAYING:
      break;
    default:
      break;
  }

  ret = GST_ELEMENT_CLASS (parent_class)->change_state (element, transition);
  if (ret == GST_STATE_CHANGE_FAILURE)
    return ret;

  switch (transition) {
    case GST_STATE_CHANGE_PLAYING_TO_PAUSED:
      break;
    case GST_STATE_CHANGE_PAUSED_TO_READY:
    {
      /* mark the redisplay_texture as unavailable (=0)
       * to avoid drawing
       */
      GST_GLIMAGE_SINK_LOCK (glimage_sink);
      glimage_sink->redisplay_texture = 0;
      GST_GLIMAGE_SINK_UNLOCK (glimage_sink);

      if (glimage_sink->upload) {
        gst_object_unref (glimage_sink->upload);
        glimage_sink->upload = NULL;
      }

      glimage_sink->window_id = 0;
      //but do not reset glimage_sink->new_window_id

      if (glimage_sink->pool) {
        gst_buffer_pool_set_active (glimage_sink->pool, FALSE);
        gst_object_unref (glimage_sink->pool);
        glimage_sink->pool = NULL;
      }

      GST_VIDEO_SINK_WIDTH (glimage_sink) = 1;
      GST_VIDEO_SINK_HEIGHT (glimage_sink) = 1;
      if (glimage_sink->context) {
        GstGLWindow *window = gst_gl_context_get_window (glimage_sink->context);

        gst_gl_window_send_message (window,
            GST_GL_WINDOW_CB (gst_glimage_sink_cleanup_glthread), glimage_sink);

        gst_gl_window_set_resize_callback (window, NULL, NULL, NULL);
        gst_gl_window_set_draw_callback (window, NULL, NULL, NULL);
        gst_gl_window_set_close_callback (window, NULL, NULL, NULL);

        gst_object_unref (window);
        gst_object_unref (glimage_sink->context);
        glimage_sink->context = NULL;
        gst_object_unref (glimage_sink->display);
        glimage_sink->display = NULL;
      }
      break;
    }
    case GST_STATE_CHANGE_READY_TO_NULL:
      break;
    default:
      break;
  }

  return ret;
}
コード例 #28
0
static gboolean
gst_gl_context_egl_create_context (GstGLContext * context,
    GstGLAPI gl_api, GstGLContext * other_context, GError ** error)
{
  GstGLContextEGL *egl;
  GstGLWindow *window = NULL;
  EGLNativeWindowType window_handle = (EGLNativeWindowType) 0;
  gint i = 0;
  EGLint context_attrib[5];
  EGLint majorVersion;
  EGLint minorVersion;
  const gchar *egl_exts;
  gboolean need_surface = TRUE;
  guintptr external_gl_context = 0;
  GstGLDisplay *display;

  egl = GST_GL_CONTEXT_EGL (context);
  window = gst_gl_context_get_window (context);

  if (other_context) {
    if (gst_gl_context_get_gl_platform (other_context) != GST_GL_PLATFORM_EGL) {
      g_set_error (error, GST_GL_CONTEXT_ERROR,
          GST_GL_CONTEXT_ERROR_WRONG_CONFIG,
          "Cannot share context with non-EGL context");
      goto failure;
    }
    external_gl_context = gst_gl_context_get_gl_context (other_context);
  }

  if ((gl_api & (GST_GL_API_OPENGL | GST_GL_API_GLES2)) == GST_GL_API_NONE) {
    g_set_error (error, GST_GL_CONTEXT_ERROR, GST_GL_CONTEXT_ERROR_WRONG_API,
        "EGL supports opengl or gles2");
    goto failure;
  }

  display = gst_gl_context_get_display (context);

  if (display->type == GST_GL_DISPLAY_TYPE_EGL) {
    egl->egl_display = (EGLDisplay) gst_gl_display_get_handle (display);
  } else {
    guintptr native_display = gst_gl_display_get_handle (display);

    if (!native_display) {
      GstGLWindow *window = NULL;
      GST_WARNING ("Failed to get a global display handle, falling back to "
          "per-window display handles.  Context sharing may not work");

      if (other_context)
        window = gst_gl_context_get_window (other_context);
      if (!window)
        window = gst_gl_context_get_window (context);
      if (window) {
        native_display = gst_gl_window_get_display (window);
        gst_object_unref (window);
      }
    }

    egl->egl_display = eglGetDisplay ((EGLNativeDisplayType) native_display);
  }
  gst_object_unref (display);

  if (eglInitialize (egl->egl_display, &majorVersion, &minorVersion)) {
    GST_INFO ("egl initialized, version: %d.%d", majorVersion, minorVersion);
  } else {
    g_set_error (error, GST_GL_CONTEXT_ERROR,
        GST_GL_CONTEXT_ERROR_RESOURCE_UNAVAILABLE,
        "Failed to initialize egl: %s", gst_gl_context_egl_get_error_string ());
    goto failure;
  }

  if (gl_api & GST_GL_API_OPENGL) {
    /* egl + opengl only available with EGL 1.4+ */
    if (majorVersion == 1 && minorVersion <= 3) {
      if ((gl_api & ~GST_GL_API_OPENGL) == GST_GL_API_NONE) {
        g_set_error (error, GST_GL_CONTEXT_ERROR, GST_GL_CONTEXT_ERROR_OLD_LIBS,
            "EGL version (%i.%i) too old for OpenGL support, (needed at least 1.4)",
            majorVersion, minorVersion);
        goto failure;
      } else {
        GST_WARNING
            ("EGL version (%i.%i) too old for OpenGL support, (needed at least 1.4)",
            majorVersion, minorVersion);
        if (gl_api & GST_GL_API_GLES2) {
          goto try_gles2;
        } else {
          g_set_error (error, GST_GL_CONTEXT_ERROR,
              GST_GL_CONTEXT_ERROR_WRONG_CONFIG,
              "Failed to choose a suitable OpenGL API");
          goto failure;
        }
      }
    }

    if (!eglBindAPI (EGL_OPENGL_API)) {
      g_set_error (error, GST_GL_CONTEXT_ERROR, GST_GL_CONTEXT_ERROR_FAILED,
          "Failed to bind OpenGL API: %s",
          gst_gl_context_egl_get_error_string ());
      goto failure;
    }

    GST_INFO ("Using OpenGL");
    egl->gl_api = GST_GL_API_OPENGL;
  } else if (gl_api & GST_GL_API_GLES2) {
  try_gles2:
    if (!eglBindAPI (EGL_OPENGL_ES_API)) {
      g_set_error (error, GST_GL_CONTEXT_ERROR, GST_GL_CONTEXT_ERROR_FAILED,
          "Failed to bind OpenGL|ES API: %s",
          gst_gl_context_egl_get_error_string ());
      goto failure;
    }

    GST_INFO ("Using OpenGL|ES 2.0");
    egl->gl_api = GST_GL_API_GLES2;
  }

  if (!gst_gl_context_egl_choose_config (egl, other_context, error)) {
    g_assert (error == NULL || *error != NULL);
    goto failure;
  }

  egl_exts = eglQueryString (egl->egl_display, EGL_EXTENSIONS);

  GST_DEBUG ("about to create gl context\n");

  if (egl->gl_api & GST_GL_API_GLES2) {
    context_attrib[i++] = EGL_CONTEXT_CLIENT_VERSION;
    context_attrib[i++] = 2;
  }
#if !defined(GST_DISABLE_GST_DEBUG) && defined(EGL_KHR_create_context)
  if (gst_gl_check_extension ("EGL_KHR_create_context", egl_exts)) {
    context_attrib[i++] = EGL_CONTEXT_FLAGS_KHR;
    context_attrib[i++] = EGL_CONTEXT_OPENGL_DEBUG_BIT_KHR;
  }
#endif
  context_attrib[i++] = EGL_NONE;

  egl->egl_context =
      eglCreateContext (egl->egl_display, egl->egl_config,
      (EGLContext) external_gl_context, context_attrib);

#ifdef EGL_KHR_create_context
  if (egl->egl_context == EGL_NO_CONTEXT && egl->gl_api & GST_GL_API_GLES2
      && eglGetError () != EGL_SUCCESS) {
    /* try without EGL_CONTEXT_FLAGS flags as it was added to
     * EGL_KHR_create_context for gles contexts */
    int i;
    for (i = 0; i < G_N_ELEMENTS (context_attrib); i++) {
      if (context_attrib[i] == EGL_CONTEXT_FLAGS_KHR ||
          context_attrib[i] == EGL_CONTEXT_OPENGL_DEBUG_BIT_KHR)
        context_attrib[i] = EGL_NONE;
    }
    egl->egl_context =
        eglCreateContext (egl->egl_display, egl->egl_config,
        (EGLContext) external_gl_context, context_attrib);
  }
#endif

  if (egl->egl_context != EGL_NO_CONTEXT) {
    GST_INFO ("gl context created: %" G_GUINTPTR_FORMAT,
        (guintptr) egl->egl_context);
  } else {
    g_set_error (error, GST_GL_CONTEXT_ERROR,
        GST_GL_CONTEXT_ERROR_CREATE_CONTEXT,
        "Failed to create a OpenGL context: %s",
        gst_gl_context_egl_get_error_string ());
    goto failure;
  }

  if (other_context == NULL) {
    /* FIXME do we want a window vfunc ? */
#if GST_GL_HAVE_WINDOW_X11
    if (GST_GL_IS_WINDOW_X11 (context->window)) {
      gst_gl_window_x11_create_window ((GstGLWindowX11 *) context->window);
    }
#endif
#if GST_GL_HAVE_WINDOW_WIN32
    if (GST_GL_IS_WINDOW_WIN32 (context->window)) {
      gst_gl_window_win32_create_window ((GstGLWindowWin32 *) context->window);
    }
#endif
  }

  if (window)
    window_handle =
        (EGLNativeWindowType) gst_gl_window_get_window_handle (window);

  if (window_handle) {
    egl->egl_surface =
        eglCreateWindowSurface (egl->egl_display, egl->egl_config,
        window_handle, NULL);
  } else if (!gst_gl_check_extension ("EGL_KHR_surfaceless_context", egl_exts)) {
    EGLint surface_attrib[7];
    gint j = 0;

    /* FIXME: Width/height doesn't seem to matter but we can't leave them
     * at 0, otherwise X11 complains about BadValue */
    surface_attrib[j++] = EGL_WIDTH;
    surface_attrib[j++] = 1;
    surface_attrib[j++] = EGL_HEIGHT;
    surface_attrib[j++] = 1;
    surface_attrib[j++] = EGL_LARGEST_PBUFFER;
    surface_attrib[j++] = EGL_TRUE;
    surface_attrib[j++] = EGL_NONE;

    egl->egl_surface =
        eglCreatePbufferSurface (egl->egl_display, egl->egl_config,
        surface_attrib);
  } else {
    egl->egl_surface = EGL_NO_SURFACE;
    need_surface = FALSE;
  }

  if (need_surface) {
    if (egl->egl_surface != EGL_NO_SURFACE) {
      GST_INFO ("surface created");
    } else {
      g_set_error (error, GST_GL_CONTEXT_ERROR, GST_GL_CONTEXT_ERROR_FAILED,
          "Failed to create window surface: %s",
          gst_gl_context_egl_get_error_string ());
      goto failure;
    }
  }

  /* EGLImage functions */
  if (GST_GL_CHECK_GL_VERSION (majorVersion, minorVersion, 1, 5)) {
    egl->eglCreateImage = gst_gl_context_get_proc_address (context,
        "eglCreateImage");
    egl->eglDestroyImage = gst_gl_context_get_proc_address (context,
        "eglDestroyImage");
  } else if (gst_gl_check_extension ("EGL_KHR_image_base", egl_exts)) {
    egl->eglCreateImage = gst_gl_context_get_proc_address (context,
        "eglCreateImageKHR");
    egl->eglDestroyImage = gst_gl_context_get_proc_address (context,
        "eglDestroyImageKHR");
  }
  if (egl->eglCreateImage == NULL || egl->eglDestroyImage == NULL) {
    egl->eglCreateImage = NULL;
    egl->eglDestroyImage = NULL;
  }

  if (window)
    gst_object_unref (window);

  return TRUE;

failure:
  if (window)
    gst_object_unref (window);

  return FALSE;
}
コード例 #29
0
static gboolean
gst_gl_context_glx_create_context (GstGLContext * context,
    GstGLAPI gl_api, GstGLContext * other_context, GError ** error)
{
  GstGLContextGLX *context_glx;
  GstGLWindow *window;
  GstGLWindowX11 *window_x11;
  GstGLDisplay *display;
  gboolean create_context;
  const char *glx_exts;
  int x_error;
  Display *device;
  guintptr external_gl_context = 0;

  context_glx = GST_GL_CONTEXT_GLX (context);
  window = gst_gl_context_get_window (context);
  window_x11 = GST_GL_WINDOW_X11 (window);
  display = gst_gl_context_get_display (context);

  if (other_context) {
    if (gst_gl_context_get_gl_platform (other_context) != GST_GL_PLATFORM_GLX) {
      g_set_error (error, GST_GL_CONTEXT_ERROR,
          GST_GL_CONTEXT_ERROR_WRONG_CONFIG,
          "Cannot share context with non-GLX context");
      goto failure;
    }

    external_gl_context = gst_gl_context_get_gl_context (other_context);
  }

  device = (Display *) gst_gl_display_get_handle (display);
  glx_exts = glXQueryExtensionsString (device, DefaultScreen (device));

  create_context = gst_gl_check_extension ("GLX_ARB_create_context", glx_exts);
  context_glx->priv->glXCreateContextAttribsARB =
      (gpointer) glXGetProcAddressARB ((const GLubyte *)
      "glXCreateContextAttribsARB");

  if (create_context && context_glx->priv->glXCreateContextAttribsARB) {
    int context_attribs_3[] = {
      GLX_CONTEXT_MAJOR_VERSION_ARB, 3,
      GLX_CONTEXT_MINOR_VERSION_ARB, 0,
      //GLX_CONTEXT_FLAGS_ARB        , GLX_CONTEXT_FORWARD_COMPATIBLE_BIT_ARB,
#if !defined(GST_DISABLE_GST_DEBUG)
      GLX_CONTEXT_FLAGS_ARB, GLX_CONTEXT_DEBUG_BIT_ARB,
#endif
      None
    };

    int context_attribs_pre_3[] = {
      GLX_CONTEXT_MAJOR_VERSION_ARB, 1,
      GLX_CONTEXT_MINOR_VERSION_ARB, 4,
      None
    };

    gst_gl_window_x11_trap_x_errors ();
    context_glx->glx_context =
        context_glx->priv->glXCreateContextAttribsARB (device,
        context_glx->priv->fbconfigs[0], (GLXContext) external_gl_context, True,
        context_attribs_3);

    x_error = gst_gl_window_x11_untrap_x_errors ();
    context_glx->priv->context_api = GST_GL_API_OPENGL;

    if (!context_glx->glx_context || x_error != 0) {
      GST_DEBUG ("Failed to create an Opengl 3 context. trying a legacy one");

      gst_gl_window_x11_trap_x_errors ();
      context_glx->glx_context =
          context_glx->priv->glXCreateContextAttribsARB (device,
          context_glx->priv->fbconfigs[0], (GLXContext) external_gl_context,
          True, context_attribs_pre_3);

      x_error = gst_gl_window_x11_untrap_x_errors ();

      if (x_error != 0)
        context_glx->glx_context = NULL;
      context_glx->priv->context_api = GST_GL_API_OPENGL;
    }

  } else {
    context_glx->glx_context =
        glXCreateContext (device, window_x11->visual_info,
        (GLXContext) external_gl_context, TRUE);
    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");
    goto failure;
  }

  GST_LOG ("gl context id: %ld", (gulong) context_glx->glx_context);

  gst_object_unref (window);
  gst_object_unref (display);

  return TRUE;

failure:
  if (window)
    gst_object_unref (window);
  gst_object_unref (display);

  return FALSE;
}
コード例 #30
0
static gboolean
gst_gl_context_wgl_create_context (GstGLContext * context,
    GstGLAPI gl_api, GstGLContext * other_context, GError ** error)
{
  GstGLWindow *window;
  GstGLContextWGL *context_wgl;
  HGLRC external_gl_context = NULL;
  HGLRC trampoline;
  HDC device;

  context_wgl = GST_GL_CONTEXT_WGL (context);
  window = gst_gl_context_get_window (context);
  device = (HDC) gst_gl_window_get_display (window);

  if (other_context) {
    if (gst_gl_context_get_gl_platform (other_context) != GST_GL_PLATFORM_WGL) {
      g_set_error (error, GST_GL_CONTEXT_ERROR,
          GST_GL_CONTEXT_ERROR_WRONG_CONFIG,
          "Cannot share context with a non-WGL context");
      goto failure;
    }
    external_gl_context = (HGLRC) gst_gl_context_get_gl_context (other_context);
  }

  trampoline = wglCreateContext (device);
  if (trampoline)
    GST_DEBUG ("gl context created: %" G_GUINTPTR_FORMAT,
        (guintptr) trampoline);
  else {
    g_set_error (error, GST_GL_CONTEXT_ERROR,
        GST_GL_CONTEXT_ERROR_CREATE_CONTEXT, "failed to create glcontext:0x%x",
        (unsigned int) GetLastError ());
    goto failure;
  }
  g_assert (trampoline);

  /* get extension functions */
  wglMakeCurrent (device, trampoline);

  context_wgl->priv->wglCreateContextAttribsARB =
      (PFNWGLCREATECONTEXTATTRIBSARBPROC)
      wglGetProcAddress ("wglCreateContextAttribsARB");

  wglMakeCurrent (device, 0);
  wglDeleteContext (trampoline);
  trampoline = NULL;

  if (context_wgl->priv->wglCreateContextAttribsARB != NULL
      && gl_api & GST_GL_API_OPENGL3) {
    gint i;

    for (i = 0; i < G_N_ELEMENTS (opengl_versions); i++) {
      gint profileMask = 0;
      gint contextFlags = 0;

      if ((opengl_versions[i].major > 3
              || (opengl_versions[i].major == 3
                  && opengl_versions[i].minor >= 2))) {
        profileMask |= WGL_CONTEXT_CORE_PROFILE_BIT_ARB;
        contextFlags |= WGL_CONTEXT_DEBUG_BIT_ARB;
      } else {
        break;
      }

      GST_DEBUG_OBJECT (context, "trying to create a GL %d.%d context",
          opengl_versions[i].major, opengl_versions[i].minor);

      context_wgl->wgl_context = _create_context_with_flags (context_wgl,
          device, external_gl_context, opengl_versions[i].major,
          opengl_versions[i].minor, contextFlags, profileMask);

      if (context_wgl->wgl_context) {
        context_wgl->priv->context_api = GST_GL_API_OPENGL3;
        break;
      }
    }
  }

  if (!context_wgl->wgl_context) {

    if (context_wgl->priv->wglCreateContextAttribsARB && external_gl_context) {
      context_wgl->wgl_context =
          context_wgl->priv->wglCreateContextAttribsARB (device,
          external_gl_context, 0);
    }


    if (!context_wgl->wgl_context) {

      context_wgl->wgl_context = wglCreateContext (device);

      if (!context_wgl->wgl_context) {
        g_set_error (error, GST_GL_CONTEXT_ERROR,
            GST_GL_CONTEXT_ERROR_CREATE_CONTEXT,
            "Failed to create WGL context 0x%x",
            (unsigned int) GetLastError ());
        goto failure;
      }

      if (external_gl_context) {
        if (!wglShareLists (external_gl_context, context_wgl->wgl_context)) {
          g_set_error (error, GST_GL_CONTEXT_ERROR,
              GST_GL_CONTEXT_ERROR_CREATE_CONTEXT,
              "failed to share contexts through wglShareLists 0x%x",
              (unsigned int) GetLastError ());
          goto failure;
        }
      }
    }

    context_wgl->priv->context_api = GST_GL_API_OPENGL;
  }

  GST_LOG ("gl context id: %" G_GUINTPTR_FORMAT,
      (guintptr) context_wgl->wgl_context);

  gst_object_unref (window);

  return TRUE;

failure:
  gst_object_unref (window);

  return FALSE;
}