X-Git-Url: https://git.sesse.net/?a=blobdiff_plain;f=modules%2Fvideo_output%2Fmsw%2Fglwin32.c;h=c6173b8c3176a6cb4940ebb81f2336f4b7eea9f2;hb=c60652e38ac6afd74bd8225e9dae5406f13aaa4f;hp=38a7b19b20374c2ef77902f4be8b753083aea527;hpb=ad77d955a5dc051976d94d6e08ee0f717ec3a938;p=vlc diff --git a/modules/video_output/msw/glwin32.c b/modules/video_output/msw/glwin32.c index 38a7b19b20..c6173b8c31 100644 --- a/modules/video_output/msw/glwin32.c +++ b/modules/video_output/msw/glwin32.c @@ -20,17 +20,13 @@ * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA. *****************************************************************************/ - -#include /* ENOMEM */ - #ifdef HAVE_CONFIG_H # include "config.h" #endif #include #include -#include -#include +#include #include #include @@ -43,361 +39,188 @@ # define MONITOR_DEFAULTTONEAREST 2 #endif -#include - -#include "vout.h" - -/***************************************************************************** - * Local prototypes. - *****************************************************************************/ -static int OpenVideo ( vlc_object_t * ); -static void CloseVideo ( vlc_object_t * ); - -static int Init ( vout_thread_t * ); -static void End ( vout_thread_t * ); -static int Manage ( vout_thread_t * ); -static void GLSwapBuffers( vout_thread_t * ); -static void FirstSwap( vout_thread_t * ); +#include "../opengl.h" +#include "common.h" /***************************************************************************** * Module descriptor *****************************************************************************/ -vlc_module_begin () - set_category( CAT_VIDEO ) - set_subcategory( SUBCAT_VIDEO_VOUT ) - set_shortname( "OpenGL" ) - set_description( N_("OpenGL video output") ) - set_capability( "opengl provider", 100 ) - add_shortcut( "glwin32" ) - set_callbacks( OpenVideo, CloseVideo ) - - /* FIXME: Hack to avoid unregistering our window class */ - linked_with_a_crap_library_which_uses_atexit () -vlc_module_end () - -#if 0 /* FIXME */ - /* check if we registered a window class because we need to - * unregister it */ - WNDCLASS wndclass; - if( GetClassInfo( GetModuleHandle(NULL), "VLC DirectX", &wndclass ) ) - UnregisterClass( "VLC DirectX", GetModuleHandle(NULL) ); -#endif +static int Open (vlc_object_t *); +static void Close(vlc_object_t *); + +vlc_module_begin() + set_category(CAT_VIDEO) + set_subcategory(SUBCAT_VIDEO_VOUT) + set_shortname("OpenGL") + set_description(N_("OpenGL video output")) + set_capability("vout display", 20) + add_shortcut("glwin32", "opengl") + set_callbacks(Open, Close) +vlc_module_end() /***************************************************************************** - * OpenVideo: allocate OpenGL provider - ***************************************************************************** - * This function creates and initializes a video window. + * Local prototypes. *****************************************************************************/ -static int OpenVideo( vlc_object_t *p_this ) +static picture_pool_t *Pool (vout_display_t *, unsigned); +static void Prepare(vout_display_t *, picture_t *); +static void Display(vout_display_t *, picture_t *); +static int Control(vout_display_t *, int, va_list); +static void Manage (vout_display_t *); + +static void Swap (vout_opengl_t *); + +/** + * It creates an OpenGL vout display. + */ +static int Open(vlc_object_t *object) { - vout_thread_t * p_vout = (vout_thread_t *)p_this; + vout_display_t *vd = (vout_display_t *)object; + vout_display_sys_t *sys; /* Allocate structure */ - p_vout->p_sys = calloc( 1, sizeof( vout_sys_t ) ); - if( p_vout->p_sys == NULL ) + vd->sys = sys = calloc(1, sizeof(*sys)); + if (!sys) return VLC_ENOMEM; - /* Initialisations */ - p_vout->pf_init = Init; - p_vout->pf_end = End; - p_vout->pf_manage = Manage; - p_vout->pf_swap = FirstSwap; - - p_vout->p_sys->hwnd = p_vout->p_sys->hvideownd = NULL; - p_vout->p_sys->hparent = p_vout->p_sys->hfswnd = NULL; - p_vout->p_sys->i_changes = 0; - vlc_mutex_init( &p_vout->p_sys->lock ); - SetRectEmpty( &p_vout->p_sys->rect_display ); - SetRectEmpty( &p_vout->p_sys->rect_parent ); - - var_Create( p_vout, "video-title", VLC_VAR_STRING | VLC_VAR_DOINHERIT ); + /* */ + if (CommonInit(vd)) + goto error; - p_vout->p_sys->b_cursor_hidden = 0; - p_vout->p_sys->i_lastmoved = mdate(); - p_vout->p_sys->i_mouse_hide_timeout = - var_GetInteger(p_vout, "mouse-hide-timeout") * 1000; + EventThreadUpdateTitle(sys->event, VOUT_TITLE " (OpenGL output)"); - /* Set main window's size */ - p_vout->p_sys->i_window_width = p_vout->i_window_width; - p_vout->p_sys->i_window_height = p_vout->i_window_height; - - if ( CreateEventThread( p_vout ) ) - { - /* Variable to indicate if the window should be on top of others */ - /* Trigger a callback right now */ - var_TriggerCallback( p_vout, "video-on-top" ); - - return VLC_SUCCESS; - } - else - { - CloseVideo( VLC_OBJECT(p_vout) ); - return VLC_EGENERIC; - } -} - -/***************************************************************************** - * Init: initialize video thread output method - *****************************************************************************/ -static int Init( vout_thread_t *p_vout ) -{ - PIXELFORMATDESCRIPTOR pfd; - int iFormat; - - /* Change the window title bar text */ - PostMessage( p_vout->p_sys->hwnd, WM_VLC_CHANGE_TEXT, 0, 0 ); - - p_vout->p_sys->hGLDC = GetDC( p_vout->p_sys->hvideownd ); + /* */ + sys->hGLDC = GetDC(sys->hvideownd); /* Set the pixel format for the DC */ - memset( &pfd, 0, sizeof( pfd ) ); - pfd.nSize = sizeof( pfd ); + PIXELFORMATDESCRIPTOR pfd; + memset(&pfd, 0, sizeof(pfd)); + pfd.nSize = sizeof(pfd); pfd.nVersion = 1; pfd.dwFlags = PFD_DRAW_TO_WINDOW | PFD_SUPPORT_OPENGL | PFD_DOUBLEBUFFER; pfd.iPixelType = PFD_TYPE_RGBA; pfd.cColorBits = 24; pfd.cDepthBits = 16; pfd.iLayerType = PFD_MAIN_PLANE; - iFormat = ChoosePixelFormat( p_vout->p_sys->hGLDC, &pfd ); - SetPixelFormat( p_vout->p_sys->hGLDC, iFormat, &pfd ); + SetPixelFormat(sys->hGLDC, + ChoosePixelFormat(sys->hGLDC, &pfd), &pfd); /* Create and enable the render context */ - p_vout->p_sys->hGLRC = wglCreateContext( p_vout->p_sys->hGLDC ); - wglMakeCurrent( p_vout->p_sys->hGLDC, p_vout->p_sys->hGLRC ); + sys->hGLRC = wglCreateContext(sys->hGLDC); + wglMakeCurrent(sys->hGLDC, sys->hGLRC); + + /* */ + sys->gl.lock = NULL; + sys->gl.unlock = NULL; + sys->gl.swap = Swap; + sys->gl.sys = vd; + + video_format_t fmt = vd->fmt; + if (vout_display_opengl_Init(&sys->vgl, &fmt, &sys->gl)) + goto error; + + vout_display_info_t info = vd->info; + info.has_double_click = true; + info.has_hide_mouse = false; + info.has_pictures_invalid = true; + info.has_event_thread = true; + + /* Setup vout_display now that everything is fine */ + vd->fmt = fmt; + vd->info = info; + + vd->pool = Pool; + vd->prepare = Prepare; + vd->display = Display; + vd->control = Control; + vd->manage = Manage; return VLC_SUCCESS; -} -/***************************************************************************** - * End: terminate Sys video thread output method - ***************************************************************************** - * Terminate an output method created by Create. - * It is called at the end of the thread. - *****************************************************************************/ -static void End( vout_thread_t *p_vout ) -{ - wglMakeCurrent( NULL, NULL ); - wglDeleteContext( p_vout->p_sys->hGLRC ); - ReleaseDC( p_vout->p_sys->hvideownd, p_vout->p_sys->hGLDC ); - return; +error: + Close(object); + return VLC_EGENERIC; } -/***************************************************************************** - * CloseVideo: destroy Sys video thread output method - ***************************************************************************** - * Terminate an output method created by Create - *****************************************************************************/ -static void CloseVideo( vlc_object_t *p_this ) +/** + * It destroys an OpenGL vout display. + */ +static void Close(vlc_object_t *object) { - vout_thread_t * p_vout = (vout_thread_t *)p_this; + vout_display_t *vd = (vout_display_t *)object; + vout_display_sys_t *sys = vd->sys; + + if (sys->vgl.gl) + vout_display_opengl_Clean(&sys->vgl); + + if (sys->hGLDC && sys->hGLRC) + wglMakeCurrent(NULL, NULL); + if (sys->hGLRC) + wglDeleteContext(sys->hGLRC); + if (sys->hGLDC) + ReleaseDC(sys->hvideownd, sys->hGLDC); - StopEventThread( p_vout ); + CommonClean(vd); - free( p_vout->p_sys ); - p_vout->p_sys = NULL; + free(sys); } -/***************************************************************************** - * Manage: handle Sys events - ***************************************************************************** - * This function should be called regularly by the video output thread. - * It returns a non null value if an error occurred. - *****************************************************************************/ -static int Manage( vout_thread_t *p_vout ) +/* */ +static picture_pool_t *Pool(vout_display_t *vd, unsigned count) { - int i_width = p_vout->p_sys->rect_dest.right - - p_vout->p_sys->rect_dest.left; - int i_height = p_vout->p_sys->rect_dest.bottom - - p_vout->p_sys->rect_dest.top; - glViewport( 0, 0, i_width, i_height ); - - /* If we do not control our window, we check for geometry changes - * ourselves because the parent might not send us its events. */ - vlc_mutex_lock( &p_vout->p_sys->lock ); - if( p_vout->p_sys->hparent && !p_vout->b_fullscreen ) - { - RECT rect_parent; - POINT point; - - vlc_mutex_unlock( &p_vout->p_sys->lock ); - - GetClientRect( p_vout->p_sys->hparent, &rect_parent ); - point.x = point.y = 0; - ClientToScreen( p_vout->p_sys->hparent, &point ); - OffsetRect( &rect_parent, point.x, point.y ); - - if( !EqualRect( &rect_parent, &p_vout->p_sys->rect_parent ) ) - { - p_vout->p_sys->rect_parent = rect_parent; - - /* This one is to force the update even if only - * the position has changed */ - SetWindowPos( p_vout->p_sys->hwnd, 0, 1, 1, - rect_parent.right - rect_parent.left, - rect_parent.bottom - rect_parent.top, 0 ); - - SetWindowPos( p_vout->p_sys->hwnd, 0, 0, 0, - rect_parent.right - rect_parent.left, - rect_parent.bottom - rect_parent.top, 0 ); - } - } - else - { - vlc_mutex_unlock( &p_vout->p_sys->lock ); - } - - /* autoscale toggle */ - if( p_vout->i_changes & VOUT_SCALE_CHANGE ) - { - p_vout->i_changes &= ~VOUT_SCALE_CHANGE; + vout_display_sys_t *sys = vd->sys; + VLC_UNUSED(count); - p_vout->b_autoscale = var_GetBool( p_vout, "autoscale" ); - p_vout->i_zoom = (int) ZOOM_FP_FACTOR; + if (!sys->pool) + sys->pool = vout_display_opengl_GetPool(&sys->vgl); + return sys->pool; +} - UpdateRects( p_vout, true ); - } +static void Prepare(vout_display_t *vd, picture_t *picture) +{ + vout_display_sys_t *sys = vd->sys; - /* scaling factor */ - if( p_vout->i_changes & VOUT_ZOOM_CHANGE ) - { - p_vout->i_changes &= ~VOUT_ZOOM_CHANGE; + vout_display_opengl_Prepare(&sys->vgl, picture); +} - p_vout->b_autoscale = false; - p_vout->i_zoom = - (int)( ZOOM_FP_FACTOR * var_GetFloat( p_vout, "scale" ) ); - UpdateRects( p_vout, true ); - } +static void Display(vout_display_t *vd, picture_t *picture) +{ + vout_display_sys_t *sys = vd->sys; - /* Check for cropping / aspect changes */ - if( p_vout->i_changes & VOUT_CROP_CHANGE || - p_vout->i_changes & VOUT_ASPECT_CHANGE ) - { - p_vout->i_changes &= ~VOUT_CROP_CHANGE; - p_vout->i_changes &= ~VOUT_ASPECT_CHANGE; - - p_vout->fmt_out.i_x_offset = p_vout->fmt_in.i_x_offset; - p_vout->fmt_out.i_y_offset = p_vout->fmt_in.i_y_offset; - p_vout->fmt_out.i_visible_width = p_vout->fmt_in.i_visible_width; - p_vout->fmt_out.i_visible_height = p_vout->fmt_in.i_visible_height; - p_vout->fmt_out.i_aspect = p_vout->fmt_in.i_aspect; - p_vout->fmt_out.i_sar_num = p_vout->fmt_in.i_sar_num; - p_vout->fmt_out.i_sar_den = p_vout->fmt_in.i_sar_den; - p_vout->output.i_aspect = p_vout->fmt_in.i_aspect; - UpdateRects( p_vout, true ); - } + vout_display_opengl_Display(&sys->vgl, &vd->source); - /* We used to call the Win32 PeekMessage function here to read the window - * messages. But since window can stay blocked into this function for a - * long time (for example when you move your window on the screen), I - * decided to isolate PeekMessage in another thread. */ - - /* - * Fullscreen change - */ - if( p_vout->i_changes & VOUT_FULLSCREEN_CHANGE - || p_vout->p_sys->i_changes & VOUT_FULLSCREEN_CHANGE ) - { - Win32ToggleFullscreen( p_vout ); - - p_vout->i_changes &= ~VOUT_FULLSCREEN_CHANGE; - p_vout->p_sys->i_changes &= ~VOUT_FULLSCREEN_CHANGE; - } + picture_Release(picture); - /* - * Pointer change - */ - if( p_vout->b_fullscreen && !p_vout->p_sys->b_cursor_hidden && - (mdate() - p_vout->p_sys->i_lastmoved) > - p_vout->p_sys->i_mouse_hide_timeout ) - { - POINT point; - HWND hwnd; - - /* Hide the cursor only if it is inside our window */ - GetCursorPos( &point ); - hwnd = WindowFromPoint(point); - if( hwnd == p_vout->p_sys->hwnd || hwnd == p_vout->p_sys->hvideownd ) - { - PostMessage( p_vout->p_sys->hwnd, WM_VLC_HIDE_MOUSE, 0, 0 ); - } - else - { - p_vout->p_sys->i_lastmoved = mdate(); - } - } + CommonDisplay(vd); +} - /* - * "Always on top" status change - */ - if( p_vout->p_sys->b_on_top_change ) - { - vlc_value_t val; - HMENU hMenu = GetSystemMenu( p_vout->p_sys->hwnd, FALSE ); - - var_Get( p_vout, "video-on-top", &val ); - - /* Set the window on top if necessary */ - if( val.b_bool && !( GetWindowLong( p_vout->p_sys->hwnd, GWL_EXSTYLE ) - & WS_EX_TOPMOST ) ) - { - CheckMenuItem( hMenu, IDM_TOGGLE_ON_TOP, - MF_BYCOMMAND | MFS_CHECKED ); - SetWindowPos( p_vout->p_sys->hwnd, HWND_TOPMOST, 0, 0, 0, 0, - SWP_NOSIZE | SWP_NOMOVE ); - } - else - /* The window shouldn't be on top */ - if( !val.b_bool && ( GetWindowLong( p_vout->p_sys->hwnd, GWL_EXSTYLE ) - & WS_EX_TOPMOST ) ) - { - CheckMenuItem( hMenu, IDM_TOGGLE_ON_TOP, - MF_BYCOMMAND | MFS_UNCHECKED ); - SetWindowPos( p_vout->p_sys->hwnd, HWND_NOTOPMOST, 0, 0, 0, 0, - SWP_NOSIZE | SWP_NOMOVE ); - } - - p_vout->p_sys->b_on_top_change = false; +static int Control(vout_display_t *vd, int query, va_list args) +{ + switch (query) { + case VOUT_DISPLAY_GET_OPENGL: { + vout_opengl_t **gl = va_arg(args, vout_opengl_t **); + *gl = &vd->sys->gl; + return VLC_SUCCESS; } - - /* Check if the event thread is still running */ - if( !vlc_object_alive (p_vout->p_sys->p_event) ) - { - return VLC_EGENERIC; /* exit */ + default: + return CommonControl(vd, query, args); } - - return VLC_SUCCESS; } -/***************************************************************************** - * GLSwapBuffers: swap front/back buffers - *****************************************************************************/ -static void GLSwapBuffers( vout_thread_t *p_vout ) +static void Manage (vout_display_t *vd) { - SwapBuffers( p_vout->p_sys->hGLDC ); -} + vout_display_sys_t *sys = vd->sys; -/* -** this function is only used once when the first picture is received -** this function will show the video window once a picture is ready -*/ + CommonManage(vd); -static void FirstSwap( vout_thread_t *p_vout ) + const int width = sys->rect_dest.right - sys->rect_dest.left; + const int height = sys->rect_dest.bottom - sys->rect_dest.top; + glViewport(0, 0, width, height); +} + +static void Swap(vout_opengl_t *gl) { - /* get initial picture buffer swapped to front buffer */ - GLSwapBuffers( p_vout ); - - /* - ** Video window is initially hidden, show it now since we got a - ** picture to show. - */ - SetWindowPos( p_vout->p_sys->hvideownd, NULL, 0, 0, 0, 0, - SWP_ASYNCWINDOWPOS| - SWP_FRAMECHANGED| - SWP_SHOWWINDOW| - SWP_NOMOVE| - SWP_NOSIZE| - SWP_NOZORDER ); - - /* use and restores proper swap function for further pictures */ - p_vout->pf_swap = GLSwapBuffers; + vout_display_t *vd = gl->sys; + + SwapBuffers(vd->sys->hGLDC); } +