static gboolean
gst_gl_window_dispmanx_egl_open (GstGLWindow * window, GError ** error)
{
  GstGLWindowDispmanxEGL *window_egl = GST_GL_WINDOW_DISPMANX_EGL (window);
  gint ret = graphics_get_display_size (0, &window_egl->dp_width,
      &window_egl->dp_height);
  if (ret < 0) {
    GST_ERROR ("Can't open display");
    return FALSE;
  }
  GST_DEBUG ("Got display size: %dx%d\n", window_egl->dp_width,
      window_egl->dp_height);

  window_egl->native.width = 0;
  window_egl->native.height = 0;
  window_egl->display = vc_dispmanx_display_open (0);
  window_egl->native.element = 0;

  window_egl->main_context = g_main_context_new ();
  window_egl->loop = g_main_loop_new (window_egl->main_context, FALSE);

  window_resize (window_egl, 16, 16);

  return TRUE;
}
static void
gst_gl_window_dispmanx_set_preferred_size (GstGLWindow * window)
{
  GstGLWindowDispmanxEGL *window_egl = GST_GL_WINDOW_DISPMANX_EGL (window);

  window_egl->preferred_width = width;
  window_egl->preferred_height = height;
}
static guintptr
gst_gl_window_dispmanx_egl_get_display (GstGLWindow * window)
{
  GstGLWindowDispmanxEGL *window_egl;

  window_egl = GST_GL_WINDOW_DISPMANX_EGL (window);

  return (guintptr) window_egl->egldisplay;
}
static guintptr
gst_gl_window_dispmanx_egl_get_window_handle (GstGLWindow * window)
{
  GstGLWindowDispmanxEGL *window_egl;
  window_egl = GST_GL_WINDOW_DISPMANX_EGL (window);
  if (window_egl->native.element)
    return (guintptr) & window_egl->native;
  return 0;
}
static void
gst_gl_window_dispmanx_egl_set_preferred_size (GstGLWindow * window, gint width,
    gint height)
{
  GstGLWindowDispmanxEGL *window_egl = GST_GL_WINDOW_DISPMANX_EGL (window);

  GST_DEBUG_OBJECT (window, "set preferred size to %dx%d", width, height);
  window_egl->preferred_width = width;
  window_egl->preferred_height = height;
}
static void
gst_gl_window_dispmanx_egl_run (GstGLWindow * window)
{
  GstGLWindowDispmanxEGL *window_egl;

  window_egl = GST_GL_WINDOW_DISPMANX_EGL (window);

  GST_LOG ("starting main loop");
  g_main_loop_run (window_egl->loop);
  GST_LOG ("exiting main loop");
}
static void
gst_gl_window_dispmanx_egl_show (GstGLWindow * window)
{
  GstGLWindowDispmanxEGL *window_egl = GST_GL_WINDOW_DISPMANX_EGL (window);

  if (!window_egl->visible) {
    window_resize (window_egl, window_egl->preferred_width,
        window_egl->preferred_height, TRUE);
    window_egl->visible = TRUE;
  }
}
static void
gst_gl_window_dispmanx_egl_quit (GstGLWindow * window)
{
  GstGLWindowDispmanxEGL *window_egl;

  window_egl = GST_GL_WINDOW_DISPMANX_EGL (window);

  GST_LOG ("sending quit");

  g_main_loop_quit (window_egl->loop);

  GST_LOG ("quit sent");
}
static gboolean
gst_gl_window_dispmanx_egl_set_render_rectangle (GstGLWindow * window,
    gint x, gint y, gint width, gint height)
{
  GstGLWindowDispmanxEGL *window_egl = GST_GL_WINDOW_DISPMANX_EGL (window);
  window_egl->render_rect.x = x;
  window_egl->render_rect.y = y;
  window_egl->render_rect.w = width;
  window_egl->render_rect.h = height;

  window_resize (window_egl, window_egl->render_rect.w,
      window_egl->render_rect.h, TRUE);
  return TRUE;
}
static void
gst_gl_window_dispmanx_egl_close (GstGLWindow * window)
{
  GstGLWindowDispmanxEGL *window_egl;
  DISPMANX_UPDATE_HANDLE_T dispman_update;

  window_egl = GST_GL_WINDOW_DISPMANX_EGL (window);

  if (window_egl->native.element && window_egl->native.element != window_egl->foreign.element) {
    dispman_update = vc_dispmanx_update_start (0);
    vc_dispmanx_element_remove (dispman_update, window_egl->native.element);
    vc_dispmanx_update_submit_sync (dispman_update);
  }
  vc_dispmanx_display_close (window_egl->display);

  GST_GL_WINDOW_CLASS (parent_class)->close (window);
}
static void
gst_gl_window_dispmanx_egl_send_message_async (GstGLWindow * window,
    GstGLWindowCB callback, gpointer data, GDestroyNotify destroy)
{
  GstGLWindowDispmanxEGL *window_egl;
  GstGLMessage *message;

  window_egl = GST_GL_WINDOW_DISPMANX_EGL (window);
  message = g_slice_new (GstGLMessage);

  message->callback = callback;
  message->data = data;
  message->destroy = destroy;

  g_main_context_invoke (window_egl->main_context, (GSourceFunc) _run_message,
      message);
}
static gboolean
gst_gl_window_dispmanx_egl_open (GstGLWindow * window, GError ** error)
{
  GstGLWindowDispmanxEGL *window_egl = GST_GL_WINDOW_DISPMANX_EGL (window);
  gint ret = graphics_get_display_size (0, &window_egl->dp_width,
      &window_egl->dp_height);
  if (ret < 0) {
    g_set_error (error, GST_GL_WINDOW_ERROR,
        GST_GL_WINDOW_ERROR_RESOURCE_UNAVAILABLE, "Can't open display");
    return FALSE;
  }
  GST_DEBUG ("Got display size: %dx%d\n", window_egl->dp_width,
      window_egl->dp_height);

  window_egl->native.element = 0;

  return GST_GL_WINDOW_CLASS (parent_class)->open (window, error);
}
static void
gst_gl_window_dispmanx_egl_set_window_handle (GstGLWindow * window,
    guintptr handle)
{
  GstGLWindowDispmanxEGL *window_egl = GST_GL_WINDOW_DISPMANX_EGL (window);
  EGL_DISPMANX_WINDOW_T *foreign_window = (EGL_DISPMANX_WINDOW_T *)handle;
  DISPMANX_UPDATE_HANDLE_T dispman_update;

  GST_DEBUG_OBJECT (window, "set window handle with size %dx%d", foreign_window->width, foreign_window->height);

  if (window_egl->native.element) {
    dispman_update = vc_dispmanx_update_start (0);
    vc_dispmanx_element_remove (dispman_update, window_egl->native.element);
    vc_dispmanx_update_submit_sync (dispman_update);
  }

  window_egl->native.element = window_egl->foreign.element = foreign_window->element;
  window_egl->native.width =  window_egl->foreign.width = foreign_window->width;
  window_egl->native.height =  window_egl->foreign.height = foreign_window->height;
}
static void
gst_gl_window_dispmanx_egl_close (GstGLWindow * window)
{
  GstGLWindowDispmanxEGL *window_egl;
  DISPMANX_UPDATE_HANDLE_T dispman_update;

  window_egl = GST_GL_WINDOW_DISPMANX_EGL (window);

  if (window_egl->native.element) {
    dispman_update = vc_dispmanx_update_start (0);
    vc_dispmanx_element_remove (dispman_update, window_egl->native.element);
    vc_dispmanx_update_submit_sync (dispman_update);
  }
  vc_dispmanx_display_close (window_egl->display);

  g_main_loop_unref (window_egl->loop);
  window_egl->loop = NULL;
  g_main_context_unref (window_egl->main_context);
  window_egl->main_context = NULL;
}
static guintptr
gst_gl_window_dispmanx_egl_get_window_handle (GstGLWindow * window)
{
  return (guintptr) & GST_GL_WINDOW_DISPMANX_EGL (window)->native;
}