static gboolean
gst_vaapi_window_egl_create (GstVaapiWindowEGL * window,
    guint * width, guint * height)
{
  GstVaapiDisplayEGL *const display =
      GST_VAAPI_DISPLAY_EGL (GST_VAAPI_OBJECT_DISPLAY (window));
  const GstVaapiDisplayClass *const native_dpy_class =
      GST_VAAPI_DISPLAY_GET_CLASS (display->display);
  CreateObjectsArgs args;

  g_return_val_if_fail (native_dpy_class != NULL, FALSE);

  window->window =
      native_dpy_class->create_window (GST_VAAPI_DISPLAY (display->display),
      GST_VAAPI_ID_INVALID, *width, *height);
  if (!window->window)
    return FALSE;

  gst_vaapi_window_get_size (window->window, width, height);

  args.window = window;
  args.width = *width;
  args.height = *height;
  args.egl_context = GST_VAAPI_DISPLAY_EGL_CONTEXT (display);
  return egl_context_run (args.egl_context,
      (EglContextRunFunc) do_create_objects, &args) && args.success;
}
static gboolean
gst_vaapi_window_glx_ensure_context (GstVaapiWindow * window,
    GLXContext foreign_context)
{
  GstVaapiWindowGLXPrivate *const priv =
      GST_VAAPI_WINDOW_GLX_GET_PRIVATE (window);
  GLContextState old_cs;
  guint width, height;

  if (!_gst_vaapi_window_glx_ensure_context (window, foreign_context))
    return FALSE;

  priv->gl_context->window = GST_VAAPI_WINDOW_ID (window);
  if (!gl_set_current_context (priv->gl_context, &old_cs)) {
    GST_DEBUG ("could not make newly created GLX context current");
    return FALSE;
  }

  glDisable (GL_DEPTH_TEST);
  glDepthMask (GL_FALSE);
  glDisable (GL_CULL_FACE);
  glDrawBuffer (GL_BACK);
  glTexEnvi (GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
  glEnable (GL_BLEND);
  glBlendFunc (GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);

  gst_vaapi_window_get_size (window, &width, &height);
  gl_resize (width, height);

  gl_set_bgcolor (0);
  glClear (GL_COLOR_BUFFER_BIT);
  gl_set_current_context (&old_cs, NULL);
  return TRUE;
}
/**
 * gst_vaapi_window_glx_put_texture:
 * @window: a #GstVaapiWindowGLX
 * @texture: a #GstVaapiTexture
 * @src_rect: the sub-rectangle of the source texture to
 *   extract and process. If %NULL, the entire texture will be used.
 * @dst_rect: the sub-rectangle of the destination
 *   window into which the texture is rendered. If %NULL, the entire
 *   window will be used.
 *
 * Renders the @texture region specified by @src_rect into the @window
 * region specified by @dst_rect.
 *
 * NOTE: only GL_TEXTURE_2D textures are supported at this time.
 *
 * Return value: %TRUE on success
 */
gboolean
gst_vaapi_window_glx_put_texture (GstVaapiWindowGLX * window,
    GstVaapiTexture * texture,
    const GstVaapiRectangle * src_rect, const GstVaapiRectangle * dst_rect)
{
  GstVaapiRectangle tmp_src_rect, tmp_dst_rect;
  GLTextureState ts;
  GLenum tex_target;
  GLuint tex_id;
  guint tex_width, tex_height;
  guint win_width, win_height;

  g_return_val_if_fail (GST_VAAPI_IS_WINDOW_GLX (window), FALSE);
  g_return_val_if_fail (texture != NULL, FALSE);

  gst_vaapi_texture_get_size (texture, &tex_width, &tex_height);
  fill_rect (&tmp_src_rect, src_rect, tex_width, tex_height);
  src_rect = &tmp_src_rect;

  gst_vaapi_window_get_size (GST_VAAPI_WINDOW (window), &win_width,
      &win_height);
  fill_rect (&tmp_dst_rect, dst_rect, win_width, win_height);
  dst_rect = &tmp_dst_rect;

  /* XXX: only GL_TEXTURE_2D textures are supported at this time */
  tex_target = gst_vaapi_texture_get_target (texture);
  if (tex_target != GL_TEXTURE_2D)
    return FALSE;

  tex_id = gst_vaapi_texture_get_id (texture);
  if (!gl_bind_texture (&ts, tex_target, tex_id))
    return FALSE;
  glColor4f (1.0f, 1.0f, 1.0f, 1.0f);
  glPushMatrix ();
  glTranslatef ((GLfloat) dst_rect->x, (GLfloat) dst_rect->y, 0.0f);
  glBegin (GL_QUADS);
  {
    const float tx1 = (float) src_rect->x / tex_width;
    const float tx2 = (float) (src_rect->x + src_rect->width) / tex_width;
    const float ty1 = (float) src_rect->y / tex_height;
    const float ty2 = (float) (src_rect->y + src_rect->height) / tex_height;
    const guint w = dst_rect->width;
    const guint h = dst_rect->height;
    glTexCoord2f (tx1, ty1);
    glVertex2i (0, 0);
    glTexCoord2f (tx1, ty2);
    glVertex2i (0, h);
    glTexCoord2f (tx2, ty2);
    glVertex2i (w, h);
    glTexCoord2f (tx2, ty1);
    glVertex2i (w, 0);
  }
  glEnd ();
  glPopMatrix ();
  gl_unbind_texture (&ts);
  return TRUE;
}
static void
ensure_window_size (App * app, GstVaapiSurface * surface)
{
  guint width, height;

  if (gst_vaapi_window_get_fullscreen (app->window))
    return;

  gst_vaapi_surface_get_size (surface, &width, &height);
  if (app->surface_width == width && app->surface_height == height)
    return;
  app->surface_width = width;
  app->surface_height = height;

  gst_vaapi_window_set_size (app->window, width, height);
  gst_vaapi_window_get_size (app->window,
      &app->window_width, &app->window_height);
}