static void gst_gl_window_win32_show (GstGLWindow * window) { GstGLWindowWin32 *window_win32 = GST_GL_WINDOW_WIN32 (window); gint width = window_win32->priv->preferred_width; gint height = window_win32->priv->preferred_height; if (!window_win32->visible) { HWND parent_id = window_win32->parent_win_id; /* if no parent the real size has to be set now because this has not been done * when at window creation */ if (!parent_id) { RECT rect; GetClientRect (window_win32->internal_win_id, &rect); width += 2 * GetSystemMetrics (SM_CXSIZEFRAME); height += 2 * GetSystemMetrics (SM_CYSIZEFRAME) + GetSystemMetrics (SM_CYCAPTION); MoveWindow (window_win32->internal_win_id, rect.left, rect.top, width, height, FALSE); } ShowWindowAsync (window_win32->internal_win_id, SW_SHOW); window_win32->visible = TRUE; } }
/* Thread safe */ static void gst_gl_window_win32_draw (GstGLWindow * window, guint width, guint height) { GstGLWindowWin32 *window_win32 = GST_GL_WINDOW_WIN32 (window); if (!window_win32->visible) { HWND parent_id = window_win32->parent_win_id; /* if no parent the real size has to be set now because this has not been done * when at window creation */ if (!parent_id) { RECT rect; GetClientRect (window_win32->internal_win_id, &rect); width += 2 * GetSystemMetrics (SM_CXSIZEFRAME); height += 2 * GetSystemMetrics (SM_CYSIZEFRAME) + GetSystemMetrics (SM_CYCAPTION); MoveWindow (window_win32->internal_win_id, rect.left, rect.top, width, height, FALSE); } ShowWindowAsync (window_win32->internal_win_id, SW_SHOW); window_win32->visible = TRUE; } RedrawWindow (window_win32->internal_win_id, NULL, NULL, RDW_NOERASE | RDW_INTERNALPAINT | RDW_INVALIDATE); }
/* Thread safe */ static void gst_gl_window_win32_draw (GstGLWindow * window) { GstGLWindowWin32 *window_win32 = GST_GL_WINDOW_WIN32 (window); RedrawWindow (window_win32->internal_win_id, NULL, NULL, RDW_NOERASE | RDW_INTERNALPAINT | RDW_INVALIDATE); }
static void gst_gl_window_win32_set_preferred_size (GstGLWindow * window, gint width, gint height) { GstGLWindowWin32 *window_win32 = GST_GL_WINDOW_WIN32 (window); window_win32->priv->preferred_width = width; window_win32->priv->preferred_height = height; }
static guintptr gst_gl_window_win32_get_display (GstGLWindow * window) { GstGLWindowWin32 *window_win32; window_win32 = GST_GL_WINDOW_WIN32 (window); return (guintptr) window_win32->device; }
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; }
/* Thread safe */ static void gst_gl_window_win32_quit (GstGLWindow * window) { GstGLWindowWin32 *window_win32; window_win32 = GST_GL_WINDOW_WIN32 (window); if (window_win32 && window_win32->internal_win_id) { LRESULT res = PostMessage (window_win32->internal_win_id, WM_GST_GL_WINDOW_QUIT, (WPARAM) 0, (LPARAM) 0); GST_DEBUG ("end loop requested"); g_return_if_fail (SUCCEEDED (res)); } }
gboolean gst_gl_window_win32_open (GstGLWindow * window, GError ** error) { GstGLWindowWin32 *window_win32 = GST_GL_WINDOW_WIN32 (window); if (!GST_GL_WINDOW_CLASS (parent_class)->open (window, error)) return FALSE; window_win32->msg_source = win32_message_source_new (window_win32); g_source_set_callback (window_win32->msg_source, (GSourceFunc) msg_cb, NULL, NULL); g_source_attach (window_win32->msg_source, g_main_context_get_thread_default ()); return TRUE; }
static void gst_gl_window_win32_set_window_handle (GstGLWindow * window, guintptr id) { GstGLWindowWin32 *window_win32; window_win32 = GST_GL_WINDOW_WIN32 (window); if (!window_win32->internal_win_id) { window_win32->parent_win_id = (HWND) id; return; } if (window_win32->visible) { ShowWindow (window_win32->internal_win_id, SW_HIDE); window_win32->visible = FALSE; } release_parent_win_id (window_win32); window_win32->parent_win_id = (HWND) id; set_parent_win_id (window_win32); }
void gst_gl_window_win32_close (GstGLWindow * window) { GstGLWindowWin32 *window_win32 = GST_GL_WINDOW_WIN32 (window); release_parent_win_id (window_win32); if (window_win32->internal_win_id) { RemoveProp (window_win32->internal_win_id, "gl_window"); if (!DestroyWindow (window_win32->internal_win_id)) GST_WARNING ("failed to destroy window %" G_GUINTPTR_FORMAT ", 0x%x", (guintptr) window_win32->internal_win_id, (unsigned int) GetLastError ()); } g_source_destroy (window_win32->msg_source); g_source_unref (window_win32->msg_source); window_win32->msg_source = NULL; GST_GL_WINDOW_CLASS (parent_class)->close (window); }
/* Thread safe */ static void gst_gl_window_win32_send_message_async (GstGLWindow * window, GstGLWindowCB callback, gpointer data, GDestroyNotify destroy) { GstGLWindowWin32 *window_win32; GstGLMessage *message; window_win32 = GST_GL_WINDOW_WIN32 (window); message = g_slice_new (GstGLMessage); if (window_win32) { LRESULT res; message->callback = callback; message->data = data; message->destroy = destroy; res = PostMessage (window_win32->internal_win_id, WM_GST_GL_WINDOW_CUSTOM, (WPARAM) message, (LPARAM) NULL); g_return_if_fail (SUCCEEDED (res)); } }
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; }
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); } }
static void gst_gl_window_win32_set_window_handle (GstGLWindow * window, guintptr id) { GstGLWindowWin32 *window_win32; HWND parent_id; window_win32 = GST_GL_WINDOW_WIN32 (window); if (!window_win32->internal_win_id) { window_win32->parent_win_id = (HWND) id; return; } /* retrieve parent if previously set */ parent_id = window_win32->parent_win_id; if (window_win32->visible) { ShowWindow (window_win32->internal_win_id, SW_HIDE); window_win32->visible = FALSE; } if (parent_id) { WNDPROC parent_proc = GetProp (parent_id, "gl_window_parent_proc"); GST_DEBUG ("release parent %" G_GUINTPTR_FORMAT, (guintptr) parent_id); g_return_if_fail (parent_proc); SetWindowLongPtr (parent_id, GWLP_WNDPROC, (LONG_PTR) parent_proc); SetParent (window_win32->internal_win_id, NULL); RemoveProp (parent_id, "gl_window_parent_proc"); } //not 0 if (id) { WNDPROC window_parent_proc = (WNDPROC) GetWindowLongPtr ((HWND) id, GWLP_WNDPROC); RECT rect; GST_DEBUG ("set parent %" G_GUINTPTR_FORMAT, id); SetProp ((HWND) id, "gl_window_id", window_win32->internal_win_id); SetProp ((HWND) id, "gl_window_parent_proc", (WNDPROC) window_parent_proc); SetWindowLongPtr ((HWND) id, GWLP_WNDPROC, (LONG_PTR) sub_class_proc); SetWindowLongPtr (window_win32->internal_win_id, GWL_STYLE, WS_CHILD | WS_MAXIMIZE); SetParent (window_win32->internal_win_id, (HWND) id); /* take changes into account: SWP_FRAMECHANGED */ GetClientRect ((HWND) id, &rect); SetWindowPos (window_win32->internal_win_id, HWND_TOP, rect.left, rect.top, rect.right, rect.bottom, SWP_ASYNCWINDOWPOS | SWP_NOMOVE | SWP_NOSIZE | SWP_NOZORDER | SWP_FRAMECHANGED | SWP_NOACTIVATE); MoveWindow (window_win32->internal_win_id, rect.left, rect.top, rect.right, rect.bottom, FALSE); } else { /* no parent so the internal window needs borders and system menu */ SetWindowLongPtr (window_win32->internal_win_id, GWL_STYLE, WS_CLIPSIBLINGS | WS_CLIPCHILDREN | WS_OVERLAPPEDWINDOW); } window_win32->parent_win_id = (HWND) id; }