static void window_resize (GstGLWindowDispmanxEGL * window_egl, guint width, guint height) { GST_DEBUG ("resizing window from %ux%u to %ux%u", window_egl->native.width, window_egl->native.height, width, height); if (window_egl->display) { VC_RECT_T dst_rect; VC_RECT_T src_rect; GstVideoRectangle src, dst, res; DISPMANX_UPDATE_HANDLE_T dispman_update; VC_DISPMANX_ALPHA_T alpha = { DISPMANX_FLAGS_ALPHA_FIXED_ALL_PIXELS, 255, 0 }; /* Center width*height frame inside dp_width*dp_height */ src.w = width; src.h = height; src.x = src.y = 0; dst.w = window_egl->dp_width; dst.h = window_egl->dp_height; dst.x = dst.y = 0; gst_video_sink_center_rect (src, dst, &res, FALSE); dst_rect.x = res.x; dst_rect.y = res.y; dst_rect.width = res.w; dst_rect.height = res.h; src_rect.x = 0; src_rect.y = 0; src_rect.width = width << 16; src_rect.height = height << 16; dispman_update = vc_dispmanx_update_start (0); if (window_egl->native.element) { vc_dispmanx_element_change_attributes (dispman_update, window_egl->native.element, 0x00000110, 0, 0, &dst_rect, &src_rect, 0, 0); } else { window_egl->native.element = vc_dispmanx_element_add (dispman_update, window_egl->display, 0, &dst_rect, 0, &src_rect, DISPMANX_PROTECTION_NONE, &alpha, 0, 0); } vc_dispmanx_update_submit_sync (dispman_update); if (GST_GL_WINDOW (window_egl)->resize) GST_GL_WINDOW (window_egl)-> resize (GST_GL_WINDOW (window_egl)->resize_data, width, height); } window_egl->native.width = width; window_egl->native.height = height; }
/** * gst_gl_window_new: * @display: a #GstGLDisplay * * Returns: (transfer full): a new #GstGLWindow using @display's connection */ GstGLWindow * gst_gl_window_new (GstGLDisplay * display) { GstGLWindow *window = NULL; const gchar *user_choice; static volatile gsize _init = 0; g_return_val_if_fail (display != NULL, NULL); if (g_once_init_enter (&_init)) { GST_DEBUG_CATEGORY_INIT (gst_gl_window_debug, "glwindow", 0, "glwindow element"); g_once_init_leave (&_init, 1); } user_choice = g_getenv ("GST_GL_WINDOW"); GST_INFO ("creating a window, user choice:%s", user_choice); #if GST_GL_HAVE_WINDOW_COCOA if (!window && (!user_choice || g_strstr_len (user_choice, 5, "cocoa"))) window = GST_GL_WINDOW (gst_gl_window_cocoa_new ()); #endif #if GST_GL_HAVE_WINDOW_X11 if (!window && (!user_choice || g_strstr_len (user_choice, 3, "x11"))) window = GST_GL_WINDOW (gst_gl_window_x11_new (display)); #endif #if GST_GL_HAVE_WINDOW_WIN32 if (!window && (!user_choice || g_strstr_len (user_choice, 5, "win32"))) window = GST_GL_WINDOW (gst_gl_window_win32_new ()); #endif #if GST_GL_HAVE_WINDOW_WAYLAND if (!window && (!user_choice || g_strstr_len (user_choice, 7, "wayland"))) window = GST_GL_WINDOW (gst_gl_window_wayland_egl_new ()); #endif #if GST_GL_HAVE_WINDOW_DISPMANX if (!window && (!user_choice || g_strstr_len (user_choice, 8, "dispmanx"))) window = GST_GL_WINDOW (gst_gl_window_dispmanx_egl_new ()); #endif #if GST_GL_HAVE_WINDOW_ANDROID if (!window && (!user_choice || g_strstr_len (user_choice, 7, "android"))) window = GST_GL_WINDOW (gst_gl_window_android_egl_new ()); #endif #if GST_GL_HAVE_WINDOW_EAGL if (!window && (!user_choice || g_strstr_len (user_choice, 4, "eagl"))) window = GST_GL_WINDOW (gst_gl_window_eagl_new ()); #endif if (!window) { /* subclass returned a NULL window */ GST_WARNING ("Could not create window. user specified %s, creating dummy" " window", user_choice ? user_choice : "(null)"); window = GST_GL_WINDOW (gst_gl_dummy_window_new ()); } window->display = gst_object_ref (display); return window; }
static void gst_gl_window_finalize (GObject * object) { GstGLWindow *window = GST_GL_WINDOW (object); GstGLWindowPrivate *priv = window->priv; GST_INFO ("quit navigation loop"); if (window->priv->navigation_loop) { g_main_loop_quit (window->priv->navigation_loop); /* wait until navigation thread finished */ g_thread_join (window->priv->navigation_thread); window->priv->navigation_thread = NULL; } if (priv->loop) g_main_loop_unref (priv->loop); if (priv->main_context) g_main_context_unref (priv->main_context); g_weak_ref_clear (&window->context_ref); g_mutex_clear (&window->lock); g_mutex_clear (&window->priv->nav_lock); g_cond_clear (&window->priv->nav_create_cond); g_mutex_clear (&window->priv->sync_message_lock); g_cond_clear (&window->priv->sync_message_cond); gst_object_unref (window->display); G_OBJECT_CLASS (gst_gl_window_parent_class)->finalize (object); }
static void draw_cb (gpointer data) { GstGLWindowAndroidEGL *window_egl = data; GstGLWindow *window = GST_GL_WINDOW (window_egl); GstGLContext *context = gst_gl_window_get_context (window); GstGLContextEGL *context_egl = GST_GL_CONTEXT_EGL (context); GstGLContextClass *context_class = GST_GL_CONTEXT_GET_CLASS (context); if (context_egl->egl_surface) { gint width, height; if (eglQuerySurface (context_egl->egl_display, context_egl->egl_surface, EGL_WIDTH, &width) && eglQuerySurface (context_egl->egl_display, context_egl->egl_surface, EGL_HEIGHT, &height) && (width != window_egl->window_width || height != window_egl->window_height)) { window_egl->window_width = width; window_egl->window_height = height; if (window->resize) window->resize (window->resize_data, width, height); } } if (window->draw) window->draw (window->draw_data); context_class->swap_buffers (context); gst_object_unref (context); }
static void draw_cb (gpointer data) { GstGLWindowWaylandEGL *window_egl = data; GstGLWindow *window = GST_GL_WINDOW (window_egl); GstGLContext *context = gst_gl_window_get_context (window); GstGLContextClass *context_class = GST_GL_CONTEXT_GET_CLASS (context); create_surfaces (window_egl); if (window_egl->window.subsurface) wl_subsurface_set_desync (window_egl->window.subsurface); if (window->queue_resize) { guint width, height; gst_gl_window_get_surface_dimensions (window, &width, &height); gst_gl_window_resize (window, width, height); } if (window->draw) window->draw (window->draw_data); context_class->swap_buffers (context); if (window_egl->window.subsurface) wl_subsurface_set_desync (window_egl->window.subsurface); gst_object_unref (context); }
static void gst_gl_window_finalize (GObject * object) { GstGLWindow *window = GST_GL_WINDOW (object); g_weak_ref_clear (&window->context_ref); g_mutex_clear (&window->lock); gst_object_unref (window->display); G_OBJECT_CLASS (gst_gl_window_parent_class)->finalize (object); }
static gboolean gst_gl_window_key_event_cb (gpointer data) { KeyEventData *key_data = data; GST_DEBUG ("%s called data struct %p window %p key %s event %s ", __func__, key_data, key_data->window, key_data->key_str, key_data->event_type); gst_gl_window_send_key_event (GST_GL_WINDOW (key_data->window), key_data->event_type, key_data->key_str); return G_SOURCE_REMOVE; }
static void draw_cb (gpointer data) { GstGLWindowWaylandEGL *window_egl = data; GstGLWindow *window = GST_GL_WINDOW (window_egl); GstGLContext *context = gst_gl_window_get_context (window); GstGLContextClass *context_class = GST_GL_CONTEXT_GET_CLASS (context); if (window->draw) window->draw (window->draw_data); context_class->swap_buffers (context); gst_object_unref (context); }
static gboolean gst_gl_window_mouse_event_cb (gpointer data) { MouseEventData *mouse_data = data; GST_DEBUG ("%s called data struct %p mouse event %s button %d at %g, %g", __func__, mouse_data, mouse_data->event_type, mouse_data->button, mouse_data->posx, mouse_data->posy); gst_gl_window_send_mouse_event (GST_GL_WINDOW (mouse_data->window), mouse_data->event_type, mouse_data->button, mouse_data->posx, mouse_data->posy); return G_SOURCE_REMOVE; }
static void draw_cb (gpointer data) { struct draw *draw_data = data; GstGLDummyWindow *dummy = draw_data->window; GstGLWindow *window = GST_GL_WINDOW (dummy); GstGLContext *context = gst_gl_window_get_context (window); GstGLContextClass *context_class = GST_GL_CONTEXT_GET_CLASS (context); if (window->draw) window->draw (window->draw_data); context_class->swap_buffers (context); gst_object_unref (context); }
static void window_resize (GstGLWindowWaylandEGL * window_egl, guint width, guint height) { GstGLWindow *window = GST_GL_WINDOW (window_egl); GST_DEBUG ("resizing window from %ux%u to %ux%u", window_egl->window.window_width, window_egl->window.window_height, width, height); if (window_egl->window.native) { wl_egl_window_resize (window_egl->window.native, width, height, 0, 0); } gst_gl_window_resize (window, width, height); window_egl->window.window_width = width; window_egl->window.window_height = height; }
GstGLContext * gst_gl_context_gpu_process_new (GstGLDisplay * display, GstGLAPI gl_api, GstGLProcAddrFunc proc_addr) { GstGLContext *context = NULL; GstGLContextGPUProcess *gpu_context = NULL; GstGLContextClass *context_class = NULL; GstGLWindow *window = NULL; GError *error = NULL; g_return_val_if_fail ((gst_gl_display_get_gl_api (display) & gl_api) != GST_GL_API_NONE, NULL); gpu_context = g_object_new (GST_GL_TYPE_CONTEXT_GPU_PROCESS, NULL); gpu_context->priv->gl_api = gl_api; context = GST_GL_CONTEXT (gpu_context); context->display = display; gst_gl_display_add_context (display, context); context_class = GST_GL_CONTEXT_GET_CLASS (context); context_class->get_current_context = NULL; context_class->get_proc_address = GST_DEBUG_FUNCPTR (proc_addr); gst_gl_context_activate (context, TRUE); gst_gl_context_fill_info (context, &error); if (error) { GST_ERROR_OBJECT (context, "Failed to create gpu process context: %s", error->message); g_error_free (error); gst_object_unref (context); return NULL; } window = GST_GL_WINDOW (gst_gl_window_gpu_process_new (display)); gst_gl_context_set_window (context, window); GST_GL_WINDOW_GET_CLASS (window)->open (window, NULL); gst_object_unref (window); return context; }
static void gst_gl_window_finalize (GObject * object) { GstGLWindow *window = GST_GL_WINDOW (object); GstGLWindowPrivate *priv = window->priv; if (priv->loop) g_main_loop_unref (priv->loop); if (priv->main_context) g_main_context_unref (priv->main_context); g_weak_ref_clear (&window->context_ref); g_mutex_clear (&window->lock); g_mutex_clear (&window->priv->sync_message_lock); g_cond_clear (&window->priv->sync_message_cond); gst_object_unref (window->display); G_OBJECT_CLASS (gst_gl_window_parent_class)->finalize (object); }
static void gst_gl_window_get_property (GObject * object, guint prop_id, GValue * value, GParamSpec * pspec) { GstGLWindow *window; GstGLWindowPrivate *priv; g_return_if_fail (GST_GL_IS_WINDOW (object)); window = GST_GL_WINDOW (object); priv = window->priv; switch (prop_id) { case ARG_DISPLAY: g_value_set_string (value, priv->display_name); break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); break; } }
static void draw_cb (gpointer data) { GstGLWindow *window = GST_GL_WINDOW (data); GstGLContext *context = gst_gl_window_get_context (window); GstGLContextClass *context_class = GST_GL_CONTEXT_GET_CLASS (context); if (window->queue_resize) { guint width, height; gst_gl_window_get_surface_dimensions (window, &width, &height); gst_gl_window_resize (window, width, height); } if (window->draw) window->draw (window->draw_data); if (context_class->swap_buffers) context_class->swap_buffers (context); gst_object_unref (context); }
static void draw_cb (gpointer data) { GstGLWindowDispmanxEGL *window_egl = data; GstGLWindow *window = GST_GL_WINDOW (window_egl); GstGLContext *context = gst_gl_window_get_context (window); GstGLContextClass *context_class = GST_GL_CONTEXT_GET_CLASS (context); if (window_egl->native.width != window_egl->preferred_width || window_egl->native.height != window_egl->preferred_height) { GST_DEBUG ("dimensions don't match, attempting resize"); window_resize (window_egl, window_egl->preferred_width, window_egl->preferred_height); } if (window->draw) window->draw (window->draw_data); context_class->swap_buffers (context); gst_object_unref (context); }
/** * gst_gl_window_new: * @display: a #GstGLDisplay * * Returns: (transfer full): a new #GstGLWindow using @display's connection * * Since: 1.4 */ GstGLWindow * gst_gl_window_new (GstGLDisplay * display) { GstGLWindow *window = NULL; const gchar *user_choice; g_return_val_if_fail (display != NULL, NULL); _init_debug (); user_choice = g_getenv ("GST_GL_WINDOW"); GST_INFO ("creating a window, user choice:%s", user_choice); #if GST_GL_HAVE_WINDOW_COCOA if (!window && (!user_choice || g_strstr_len (user_choice, 5, "cocoa"))) window = GST_GL_WINDOW (gst_gl_window_cocoa_new (display)); #endif #if GST_GL_HAVE_WINDOW_X11 if (!window && (!user_choice || g_strstr_len (user_choice, 3, "x11"))) window = GST_GL_WINDOW (gst_gl_window_x11_new (display)); #endif #if GST_GL_HAVE_WINDOW_WIN32 if (!window && (!user_choice || g_strstr_len (user_choice, 5, "win32"))) window = GST_GL_WINDOW (gst_gl_window_win32_new (display)); #endif #if GST_GL_HAVE_WINDOW_WAYLAND if (!window && (!user_choice || g_strstr_len (user_choice, 7, "wayland"))) window = GST_GL_WINDOW (gst_gl_window_wayland_egl_new (display)); #endif #if GST_GL_HAVE_WINDOW_DISPMANX if (!window && (!user_choice || g_strstr_len (user_choice, 8, "dispmanx"))) window = GST_GL_WINDOW (gst_gl_window_dispmanx_egl_new (display)); #endif #if GST_GL_HAVE_WINDOW_ANDROID if (!window && (!user_choice || g_strstr_len (user_choice, 7, "android"))) window = GST_GL_WINDOW (gst_gl_window_android_egl_new (display)); #endif #if GST_GL_HAVE_WINDOW_EAGL if (!window && (!user_choice || g_strstr_len (user_choice, 4, "eagl"))) window = GST_GL_WINDOW (gst_gl_window_eagl_new (display)); #endif if (!window) { /* subclass returned a NULL window */ GST_WARNING ("Could not create window. user specified %s, creating dummy" " window", user_choice ? user_choice : "(null)"); window = GST_GL_WINDOW (gst_gl_dummy_window_new ()); } window->display = gst_object_ref (display); g_mutex_lock (&window->priv->nav_lock); window->priv->navigation_thread = g_thread_new ("gstglnavigation", (GThreadFunc) gst_gl_window_navigation_thread, window); while (!window->priv->nav_alive) g_cond_wait (&window->priv->nav_create_cond, &window->priv->nav_lock); g_mutex_unlock (&window->priv->nav_lock); return window; }
static void create_surfaces (GstGLWindowWaylandEGL * window_egl) { GstGLDisplayWayland *display = GST_GL_DISPLAY_WAYLAND (GST_GL_WINDOW (window_egl)->display); gint width, height; if (!window_egl->window.surface) { window_egl->window.surface = wl_compositor_create_surface (display->compositor); if (window_egl->window.queue) wl_proxy_set_queue ((struct wl_proxy *) window_egl->window.surface, window_egl->window.queue); } if (window_egl->window.foreign_surface) { /* (re)parent */ if (!display->subcompositor) { GST_ERROR_OBJECT (window_egl, "Wayland server does not support subsurfaces"); window_egl->window.foreign_surface = NULL; goto shell_window; } if (!window_egl->window.subsurface) { window_egl->window.subsurface = wl_subcompositor_get_subsurface (display->subcompositor, window_egl->window.surface, window_egl->window.foreign_surface); if (window_egl->window.queue) wl_proxy_set_queue ((struct wl_proxy *) window_egl->window.subsurface, window_egl->window.queue); wl_subsurface_set_position (window_egl->window.subsurface, window_egl->window.window_x, window_egl->window.window_y); wl_subsurface_set_desync (window_egl->window.subsurface); } } else { shell_window: if (!window_egl->window.shell_surface) { window_egl->window.shell_surface = wl_shell_get_shell_surface (display->shell, window_egl->window.surface); if (window_egl->window.queue) wl_proxy_set_queue ((struct wl_proxy *) window_egl->window. shell_surface, window_egl->window.queue); wl_shell_surface_add_listener (window_egl->window.shell_surface, &shell_surface_listener, window_egl); wl_shell_surface_set_title (window_egl->window.shell_surface, "OpenGL Renderer"); wl_shell_surface_set_toplevel (window_egl->window.shell_surface); } } if (window_egl->window.window_width > 0) width = window_egl->window.window_width; else width = 320; window_egl->window.window_width = width; if (window_egl->window.window_height > 0) height = window_egl->window.window_height; else height = 240; window_egl->window.window_height = height; if (!window_egl->window.native) { gst_gl_window_resize (GST_GL_WINDOW (window_egl), width, height); window_egl->window.native = wl_egl_window_create (window_egl->window.surface, width, height); if (window_egl->window.queue) wl_proxy_set_queue ((struct wl_proxy *) window_egl->window.native, window_egl->window.queue); } }
/* Must be called in the gl thread */ static void gst_gl_window_finalize (GObject * object) { GstGLWindow *window = GST_GL_WINDOW (object); GstGLWindowPrivate *priv = window->priv; XEvent event; Bool ret = TRUE; g_mutex_lock (priv->x_lock); priv->parent = 0; XUnmapWindow (priv->device, priv->internal_win_id); ret = eglMakeCurrent (priv->device, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT); if (!ret) g_debug ("failed to release opengl context\n"); eglDestroyContext (priv->device, priv->gl_context); eglTerminate (priv->device); XFree (priv->visual_info); XReparentWindow (priv->device, priv->internal_win_id, priv->root, 0, 0); XDestroyWindow (priv->device, priv->internal_win_id); XSync (priv->device, FALSE); while (XPending (priv->device)) XNextEvent (priv->device, &event); XSetCloseDownMode (priv->device, DestroyAll); /*XAddToSaveSet (display, w) Display *display; Window w; */ //FIXME: it seems it causes destroy all created windows, even by other display connection: //This is case in: gst-launch-0.10 videotestsrc ! tee name=t t. ! queue ! glimagesink t. ! queue ! glimagesink //When the first window is closed and so its display is closed by the following line, then the other Window managed by the //other glimagesink, is not useable and so each opengl call causes a segmentation fault. //Maybe the solution is to use: XAddToSaveSet //The following line is commented to avoid the disagreement explained before. //XCloseDisplay (priv->device); g_debug ("display receiver closed\n"); XCloseDisplay (priv->disp_send); g_debug ("display sender closed\n"); if (priv->cond_send_message) { g_cond_free (priv->cond_send_message); priv->cond_send_message = NULL; } g_mutex_unlock (priv->x_lock); if (priv->x_lock) { g_mutex_free (priv->x_lock); priv->x_lock = NULL; } G_OBJECT_CLASS (gst_gl_window_parent_class)->finalize (object); }
LRESULT CALLBACK window_proc (HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam) { GstGLWindowWin32 *window_win32; LRESULT ret = 0; if (uMsg == WM_CREATE) { window_win32 = GST_GL_WINDOW_WIN32 (((LPCREATESTRUCT) lParam)->lpCreateParams); GST_TRACE ("WM_CREATE"); window_win32->device = GetDC (hWnd); /* Do this, otherwise we hang on exit. We can still use it (due to the * CS_OWNDC flag in the WindowClass) after we have Released. */ ReleaseDC (hWnd, window_win32->device); SetProp (hWnd, "gl_window", window_win32); } else if (GetProp (hWnd, "gl_window")) { GstGLWindow *window; GstGLContext *context; GstGLContextClass *context_class; window_win32 = GST_GL_WINDOW_WIN32 (GetProp (hWnd, "gl_window")); window = GST_GL_WINDOW (window_win32); context = gst_gl_window_get_context (window); context_class = GST_GL_CONTEXT_GET_CLASS (context); g_assert (window_win32->internal_win_id == hWnd); switch (uMsg) { case WM_SIZE: { if (window->resize) { window->resize (window->resize_data, LOWORD (lParam), HIWORD (lParam)); } break; } case WM_PAINT: { if (window->draw) { PAINTSTRUCT ps; BeginPaint (hWnd, &ps); window->draw (window->draw_data); context_class->swap_buffers (context); EndPaint (hWnd, &ps); } break; } case WM_CLOSE: { ShowWindowAsync (window_win32->internal_win_id, SW_HIDE); GST_TRACE ("WM_CLOSE"); if (window->close) window->close (window->close_data); break; } case WM_CAPTURECHANGED: { GST_DEBUG ("WM_CAPTURECHANGED"); if (window->draw) window->draw (window->draw_data); break; } case WM_ERASEBKGND: { ret = TRUE; break; } default: { /* transmit messages to the parrent (ex: mouse/keyboard input) */ HWND parent_id = window_win32->parent_win_id; if (parent_id) PostMessage (parent_id, uMsg, wParam, lParam); ret = DefWindowProc (hWnd, uMsg, wParam, lParam); } } gst_object_unref (context); } else { ret = DefWindowProc (hWnd, uMsg, wParam, lParam); } return ret; }
static void window_resize (GstGLWindowDispmanxEGL * window_egl, guint width, guint height, gboolean visible) { GstGLWindow *window = GST_GL_WINDOW (window_egl); GST_DEBUG ("resizing %s window from %ux%u to %ux%u", visible ? "visible" : "invisible", window_egl->native.width, window_egl->native.height, width, height); if (window_egl->display) { VC_RECT_T dst_rect; VC_RECT_T src_rect; GstVideoRectangle src, res; DISPMANX_UPDATE_HANDLE_T dispman_update; uint32_t opacity = visible ? 255 : 0; VC_DISPMANX_ALPHA_T alpha = { DISPMANX_FLAGS_ALPHA_FIXED_ALL_PIXELS, opacity, 0 }; src.w = width; src.h = height; src.x = src.y = 0; /* If there is no render rectangle, center the width*height frame * inside dp_width*dp_height */ if (window_egl->render_rect.w <= 0 || window_egl->render_rect.h <= 0) { GstVideoRectangle dst; dst.w = window_egl->dp_width; dst.h = window_egl->dp_height; dst.x = dst.y = 0; gst_video_sink_center_rect (src, dst, &res, FALSE); } else { gst_video_sink_center_rect (src, window_egl->render_rect, &res, FALSE); } dst_rect.x = res.x; dst_rect.y = res.y; dst_rect.width = res.w; dst_rect.height = res.h; src_rect.x = 0; src_rect.y = 0; src_rect.width = width << 16; src_rect.height = height << 16; dispman_update = vc_dispmanx_update_start (0); if (window_egl->native.element) { uint32_t change_flags = ELEMENT_CHANGE_OPACITY | ELEMENT_CHANGE_DEST_RECT | ELEMENT_CHANGE_SRC_RECT; vc_dispmanx_element_change_attributes (dispman_update, window_egl->native.element, change_flags, 0, opacity, &dst_rect, &src_rect, 0, 0); } else { window_egl->native.element = vc_dispmanx_element_add (dispman_update, window_egl->display, 0, &dst_rect, 0, &src_rect, DISPMANX_PROTECTION_NONE, &alpha, 0, 0); } vc_dispmanx_update_submit_sync (dispman_update); gst_gl_window_resize (window, width, height); } window_egl->native.width = width; window_egl->native.height = height; }
LRESULT CALLBACK window_proc (HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam) { GstGLWindowWin32 *window_win32; if (uMsg == WM_CREATE) { window_win32 = GST_GL_WINDOW_WIN32 (((LPCREATESTRUCT) lParam)->lpCreateParams); GST_TRACE ("WM_CREATE"); window_win32->device = GetDC (hWnd); /* Do this, otherwise we hang on exit. We can still use it (due to the * CS_OWNDC flag in the WindowClass) after we have Released. */ ReleaseDC (hWnd, window_win32->device); SetProp (hWnd, "gl_window", window_win32); return 0; } else if (GetProp (hWnd, "gl_window")) { GstGLWindow *window; GstGLContext *context; GstGLContextClass *context_class; window_win32 = GST_GL_WINDOW_WIN32 (GetProp (hWnd, "gl_window")); window = GST_GL_WINDOW (window_win32); context = gst_gl_window_get_context (window); context_class = GST_GL_CONTEXT_GET_CLASS (context); g_assert (window_win32->internal_win_id == hWnd); switch (uMsg) { case WM_SIZE: { if (window->resize) { window->resize (window->resize_data, LOWORD (lParam), HIWORD (lParam)); } break; } case WM_PAINT: { if (window->draw) { PAINTSTRUCT ps; BeginPaint (hWnd, &ps); window->draw (window->draw_data); context_class->swap_buffers (context); EndPaint (hWnd, &ps); } break; } case WM_CLOSE: { ShowWindowAsync (window_win32->internal_win_id, SW_HIDE); GST_TRACE ("WM_CLOSE"); if (window->close) window->close (window->close_data); break; } case WM_GST_GL_WINDOW_QUIT: { HWND parent_id = 0; GST_TRACE ("WM_GST_GL_WINDOW_QUIT"); parent_id = window_win32->parent_win_id; if (parent_id) { WNDPROC parent_proc = GetProp (parent_id, "gl_window_parent_proc"); g_assert (parent_proc); SetWindowLongPtr (parent_id, GWLP_WNDPROC, (LONG_PTR) parent_proc); SetParent (hWnd, NULL); RemoveProp (parent_id, "gl_window_parent_proc"); } window_win32->is_closed = TRUE; RemoveProp (hWnd, "gl_window"); if (window_win32->internal_win_id) { if (!DestroyWindow (window_win32->internal_win_id)) GST_WARNING ("failed to destroy window %" G_GUINTPTR_FORMAT ", 0x%x", (guintptr) hWnd, (unsigned int) GetLastError ()); } PostQuitMessage (0); break; } case WM_CAPTURECHANGED: { GST_DEBUG ("WM_CAPTURECHANGED"); if (window->draw) window->draw (window->draw_data); break; } case WM_GST_GL_WINDOW_CUSTOM: { if (!window_win32->is_closed) { GstGLMessage *message = (GstGLMessage *) wParam; _run_message (message); } break; } case WM_ERASEBKGND: return TRUE; default: { /* transmit messages to the parrent (ex: mouse/keyboard input) */ HWND parent_id = window_win32->parent_win_id; if (parent_id) PostMessage (parent_id, uMsg, wParam, lParam); return DefWindowProc (hWnd, uMsg, wParam, lParam); } } gst_object_unref (context); return 0; } else { return DefWindowProc (hWnd, uMsg, wParam, lParam); } }