Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in
Toggle navigation
V
vlc
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
0
Issues
0
List
Boards
Labels
Milestones
Redmine
Redmine
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Operations
Operations
Metrics
Environments
Analytics
Analytics
CI / CD
Repository
Value Stream
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
videolan
vlc
Commits
f6d06e15
Commit
f6d06e15
authored
Oct 24, 2009
by
Laurent Aimar
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Converted direct3d to vout display.
It also fixes a few remaining race conditions.
parent
4a1df8f1
Changes
6
Hide whitespace changes
Inline
Side-by-side
Showing
6 changed files
with
1555 additions
and
1306 deletions
+1555
-1306
modules/video_output/msw/Modules.am
modules/video_output/msw/Modules.am
+4
-4
modules/video_output/msw/common.c
modules/video_output/msw/common.c
+363
-447
modules/video_output/msw/common.h
modules/video_output/msw/common.h
+322
-0
modules/video_output/msw/direct3d.c
modules/video_output/msw/direct3d.c
+718
-688
modules/video_output/msw/events.c
modules/video_output/msw/events.c
+140
-165
modules/video_output/msw/events.h
modules/video_output/msw/events.h
+8
-2
No files found.
modules/video_output/msw/Modules.am
View file @
f6d06e15
...
@@ -8,10 +8,10 @@ SOURCES_directx = \
...
@@ -8,10 +8,10 @@ SOURCES_directx = \
SOURCES_direct3d = \
SOURCES_direct3d = \
direct3d.c \
direct3d.c \
vout
.h \
common
.h \
events
_vo
.h \
events.h \
events
_vo
.c \
events.c \
common
_vo
.c \
common.c \
$(NULL)
$(NULL)
SOURCES_glwin32 = \
SOURCES_glwin32 = \
...
...
modules/video_output/msw/common.c
View file @
f6d06e15
...
@@ -29,9 +29,10 @@
...
@@ -29,9 +29,10 @@
#ifdef HAVE_CONFIG_H
#ifdef HAVE_CONFIG_H
# include "config.h"
# include "config.h"
#endif
#endif
#include <assert.h>
#include <vlc_common.h>
#include <vlc_common.h>
#include <vlc_vout.h>
#include <vlc_vout
_display
.h>
#include <vlc_vout_window.h>
#include <vlc_vout_window.h>
#include <windows.h>
#include <windows.h>
...
@@ -48,7 +49,7 @@
...
@@ -48,7 +49,7 @@
#include <GL/gl.h>
#include <GL/gl.h>
#endif
#endif
#include "
vout
.h"
#include "
common
.h"
#ifndef UNDER_CE
#ifndef UNDER_CE
#include <vlc_windows_interfaces.h>
#include <vlc_windows_interfaces.h>
...
@@ -59,230 +60,151 @@
...
@@ -59,230 +60,151 @@
//WINSHELLAPI BOOL WINAPI SHFullScreen(HWND hwndRequester, DWORD dwState);
//WINSHELLAPI BOOL WINAPI SHFullScreen(HWND hwndRequester, DWORD dwState);
#endif
#endif
static
int
vaControlParentWindow
(
vout_thread_t
*
,
int
,
va_list
);
static
int
CommonControlSetFullscreen
(
vout_display_t
*
,
bool
is_fullscreen
);
static
void
DisableScreensaver
(
vout_display_t
*
);
static
void
RestoreScreensaver
(
vout_display_t
*
);
/* */
/* */
int
CommonInit
(
vout_thread_t
*
p_vout
)
int
CommonInit
(
vout_display_t
*
vd
)
{
{
vout_sys_t
*
p_sys
=
p_vout
->
p_sys
;
vout_display_sys_t
*
sys
=
vd
->
sys
;
p_sys
->
hwnd
=
NULL
;
sys
->
hwnd
=
NULL
;
p_sys
->
hvideownd
=
NULL
;
sys
->
hvideownd
=
NULL
;
p_sys
->
hparent
=
NULL
;
sys
->
hparent
=
NULL
;
p_sys
->
hfswnd
=
NULL
;
sys
->
hfswnd
=
NULL
;
p_sys
->
i_changes
=
0
;
sys
->
changes
=
0
;
SetRectEmpty
(
&
p_sys
->
rect_display
);
SetRectEmpty
(
&
sys
->
rect_display
);
SetRectEmpty
(
&
p_sys
->
rect_parent
);
SetRectEmpty
(
&
sys
->
rect_parent
);
sys
->
is_first_display
=
true
;
var_Create
(
p_vout
,
"video-title"
,
VLC_VAR_STRING
|
VLC_VAR_DOINHERIT
);
sys
->
is_on_top
=
false
;
/* Set main window's size */
var_Create
(
vd
,
"video-title"
,
VLC_VAR_STRING
|
VLC_VAR_DOINHERIT
);
vout_window_cfg_t
wnd_cfg
;
var_Create
(
vd
,
"video-deco"
,
VLC_VAR_BOOL
|
VLC_VAR_DOINHERIT
);
memset
(
&
wnd_cfg
,
0
,
sizeof
(
wnd_cfg
)
);
/* FIXME remove mouse hide from msw */
wnd_cfg
.
type
=
VOUT_WINDOW_TYPE_HWND
;
var_Create
(
vd
,
"mouse-hide-timeout"
,
VLC_VAR_INTEGER
|
VLC_VAR_DOINHERIT
);
wnd_cfg
.
x
=
0
;
wnd_cfg
.
y
=
0
;
/* */
wnd_cfg
.
width
=
p_vout
->
i_window_width
;
sys
->
event
=
EventThreadCreate
(
vd
);
wnd_cfg
.
height
=
p_vout
->
i_window_height
;
if
(
!
sys
->
event
)
p_sys
->
p_event
=
EventThreadCreate
(
p_vout
,
&
wnd_cfg
);
if
(
!
p_sys
->
p_event
)
return
VLC_EGENERIC
;
return
VLC_EGENERIC
;
event_cfg_t
cfg
;
event_cfg_t
cfg
;
memset
(
&
cfg
,
0
,
sizeof
(
cfg
));
memset
(
&
cfg
,
0
,
sizeof
(
cfg
));
#ifdef MODULE_NAME_IS_direct3d
#ifdef MODULE_NAME_IS_direct3d
cfg
.
use_desktop
=
p_vout
->
p_sys
->
b
_desktop
;
cfg
.
use_desktop
=
sys
->
use
_desktop
;
#endif
#endif
#ifdef MODULE_NAME_IS_directx
#ifdef MODULE_NAME_IS_directx
cfg
.
use_overlay
=
p_vout
->
p_
sys
->
b_using_overlay
;
cfg
.
use_overlay
=
sys
->
b_using_overlay
;
#endif
#endif
cfg
.
win
.
type
=
VOUT_WINDOW_TYPE_HWND
;
cfg
.
win
.
x
=
0
;
cfg
.
win
.
y
=
0
;
cfg
.
win
.
width
=
vd
->
cfg
->
display
.
width
;
cfg
.
win
.
height
=
vd
->
cfg
->
display
.
height
;
event_hwnd_t
hwnd
;
event_hwnd_t
hwnd
;
if
(
EventThreadStart
(
p_sys
->
p_event
,
&
hwnd
,
&
cfg
)
)
if
(
EventThreadStart
(
sys
->
event
,
&
hwnd
,
&
cfg
)
)
return
VLC_EGENERIC
;
return
VLC_EGENERIC
;
p_
sys
->
parent_window
=
hwnd
.
parent_window
;
sys
->
parent_window
=
hwnd
.
parent_window
;
p_
sys
->
hparent
=
hwnd
.
hparent
;
sys
->
hparent
=
hwnd
.
hparent
;
p_
sys
->
hwnd
=
hwnd
.
hwnd
;
sys
->
hwnd
=
hwnd
.
hwnd
;
p_
sys
->
hvideownd
=
hwnd
.
hvideownd
;
sys
->
hvideownd
=
hwnd
.
hvideownd
;
p_
sys
->
hfswnd
=
hwnd
.
hfswnd
;
sys
->
hfswnd
=
hwnd
.
hfswnd
;
/* Variable to indicate if the window should be on top of others */
if
(
vd
->
cfg
->
is_fullscreen
)
{
/* Trigger a callback right now */
if
(
CommonControlSetFullscreen
(
vd
,
true
))
var_TriggerCallback
(
p_vout
,
"video-on-top"
);
vout_display_SendEventFullscreen
(
vd
,
false
);
}
/* Why not with glwin32 */
/* Why not with glwin32 */
#if !defined(UNDER_CE) && !defined(MODULE_NAME_IS_glwin32)
#if !defined(UNDER_CE) && !defined(MODULE_NAME_IS_glwin32)
var_Create
(
p_vout
,
"disable-screensaver"
,
VLC_VAR_BOOL
|
VLC_VAR_DOINHERIT
);
var_Create
(
vd
,
"disable-screensaver"
,
VLC_VAR_BOOL
|
VLC_VAR_DOINHERIT
);
DisableScreensaver
(
p_vout
);
DisableScreensaver
(
vd
);
#endif
#endif
return
VLC_SUCCESS
;
return
VLC_SUCCESS
;
}
}
/* */
/* */
void
CommonClean
(
vout_thread_t
*
p_vout
)
void
CommonClean
(
vout_display_t
*
vd
)
{
{
vout_
sys_t
*
p_sys
=
p_vout
->
p_
sys
;
vout_
display_sys_t
*
sys
=
vd
->
sys
;
ExitFullscreen
(
p_vout
);
if
(
sys
->
event
)
{
if
(
p_sys
->
p_event
)
EventThreadStop
(
sys
->
event
);
{
EventThreadDestroy
(
sys
->
event
);
EventThreadStop
(
p_sys
->
p_event
);
EventThreadDestroy
(
p_sys
->
p_event
);
}
}
#if !defined(UNDER_CE) && !defined(MODULE_NAME_IS_glwin32)
#if !defined(UNDER_CE) && !defined(MODULE_NAME_IS_glwin32)
RestoreScreensaver
(
p_vout
);
RestoreScreensaver
(
vd
);
#endif
#endif
}
}
void
CommonManage
(
vout_thread_t
*
p_vout
)
void
CommonManage
(
vout_display_t
*
vd
)
{
{
vout_display_sys_t
*
sys
=
vd
->
sys
;
/* 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. */
/* If we do not control our window, we check for geometry changes
/* If we do not control our window, we check for geometry changes
* ourselves because the parent might not send us its events. */
* ourselves because the parent might not send us its events. */
if
(
p_vout
->
p_sys
->
hparent
&&
!
p_vout
->
b_fullscreen
)
if
(
sys
->
hparent
&&
!
vd
->
cfg
->
is_fullscreen
)
{
{
RECT
rect_parent
;
RECT
rect_parent
;
POINT
point
;
POINT
point
;
GetClientRect
(
p_vout
->
p_sys
->
hparent
,
&
rect_parent
);
GetClientRect
(
sys
->
hparent
,
&
rect_parent
);
point
.
x
=
point
.
y
=
0
;
point
.
x
=
point
.
y
=
0
;
ClientToScreen
(
p_vout
->
p_sys
->
hparent
,
&
point
);
ClientToScreen
(
sys
->
hparent
,
&
point
);
OffsetRect
(
&
rect_parent
,
point
.
x
,
point
.
y
);
OffsetRect
(
&
rect_parent
,
point
.
x
,
point
.
y
);
if
(
!
EqualRect
(
&
rect_parent
,
&
p_vout
->
p_sys
->
rect_parent
)
)
if
(
!
EqualRect
(
&
rect_parent
,
&
sys
->
rect_parent
))
{
{
sys
->
rect_parent
=
rect_parent
;
p_vout
->
p_sys
->
rect_parent
=
rect_parent
;
/* FIXME I find such #ifdef quite weirds. Are they really needed ? */
/* FIXME I find such #ifdef quite weirds. Are they really needed ? */
#if defined(MODULE_NAME_IS_direct3d)
#if defined(MODULE_NAME_IS_direct3d)
SetWindowPos
(
p_vout
->
p_
sys
->
hwnd
,
0
,
0
,
0
,
SetWindowPos
(
sys
->
hwnd
,
0
,
0
,
0
,
rect_parent
.
right
-
rect_parent
.
left
,
rect_parent
.
right
-
rect_parent
.
left
,
rect_parent
.
bottom
-
rect_parent
.
top
,
rect_parent
.
bottom
-
rect_parent
.
top
,
SWP_NOZORDER
);
SWP_NOZORDER
);
UpdateRects
(
p_vout
,
true
);
UpdateRects
(
vd
,
NULL
,
NULL
,
true
);
#else
#else
/* This one is to force the update even if only
/* This one is to force the update even if only
* the position has changed */
* the position has changed */
SetWindowPos
(
p_vout
->
p_
sys
->
hwnd
,
0
,
1
,
1
,
SetWindowPos
(
sys
->
hwnd
,
0
,
1
,
1
,
rect_parent
.
right
-
rect_parent
.
left
,
rect_parent
.
right
-
rect_parent
.
left
,
rect_parent
.
bottom
-
rect_parent
.
top
,
0
);
rect_parent
.
bottom
-
rect_parent
.
top
,
0
);
SetWindowPos
(
p_vout
->
p_
sys
->
hwnd
,
0
,
0
,
0
,
SetWindowPos
(
sys
->
hwnd
,
0
,
0
,
0
,
rect_parent
.
right
-
rect_parent
.
left
,
rect_parent
.
right
-
rect_parent
.
left
,
rect_parent
.
bottom
-
rect_parent
.
top
,
0
);
rect_parent
.
bottom
-
rect_parent
.
top
,
0
);
#if defined(MODULE_NAME_IS_wingdi) || defined(MODULE_NAME_IS_wingapi)
#if defined(MODULE_NAME_IS_wingdi) || defined(MODULE_NAME_IS_wingapi)
unsigned
int
i_x
,
i_y
,
i_width
,
i_height
;
unsigned
int
i_x
,
i_y
,
i_width
,
i_height
;
vout_PlacePicture
(
p_vout
,
rect_parent
.
right
-
rect_parent
.
left
,
vout_PlacePicture
(
vd
,
rect_parent
.
right
-
rect_parent
.
left
,
rect_parent
.
bottom
-
rect_parent
.
top
,
rect_parent
.
bottom
-
rect_parent
.
top
,
&
i_x
,
&
i_y
,
&
i_width
,
&
i_height
);
&
i_x
,
&
i_y
,
&
i_width
,
&
i_height
);
SetWindowPos
(
p_vout
->
p_
sys
->
hvideownd
,
HWND_TOP
,
SetWindowPos
(
sys
->
hvideownd
,
HWND_TOP
,
i_x
,
i_y
,
i_width
,
i_height
,
0
);
i_x
,
i_y
,
i_width
,
i_height
,
0
);
#endif
#endif
#endif
#endif
}
}
}
}
/* */
/* */
p_vout
->
p_sys
->
i_changes
|=
EventThreadRetreiveChanges
(
p_vout
->
p_sys
->
p_event
);
if
(
EventThreadGetAndResetHasMoved
(
sys
->
event
))
UpdateRects
(
vd
,
NULL
,
NULL
,
false
);
/* autoscale toggle */
if
(
p_vout
->
i_changes
&
VOUT_SCALE_CHANGE
)
{
p_vout
->
i_changes
&=
~
VOUT_SCALE_CHANGE
;
p_vout
->
b_autoscale
=
var_GetBool
(
p_vout
,
"autoscale"
);
p_vout
->
i_zoom
=
(
int
)
ZOOM_FP_FACTOR
;
UpdateRects
(
p_vout
,
true
);
}
/* scaling factor */
if
(
p_vout
->
i_changes
&
VOUT_ZOOM_CHANGE
)
{
p_vout
->
i_changes
&=
~
VOUT_ZOOM_CHANGE
;
p_vout
->
b_autoscale
=
false
;
p_vout
->
i_zoom
=
(
int
)(
ZOOM_FP_FACTOR
*
var_GetFloat
(
p_vout
,
"scale"
)
);
UpdateRects
(
p_vout
,
true
);
}
/* 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
);
}
/* 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. */
/*
/* Pointer change */
* Fullscreen change
EventThreadMouseAutoHide
(
sys
->
event
);
*/
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
;
}
/*
* Pointer change
*/
EventThreadMouseAutoHide
(
p_vout
->
p_sys
->
p_event
);
/*
* "Always on top" status change
*/
if
(
p_vout
->
p_sys
->
b_on_top_change
)
{
HMENU
hMenu
=
GetSystemMenu
(
p_vout
->
p_sys
->
hwnd
,
FALSE
);
bool
b
=
var_GetBool
(
p_vout
,
"video-on-top"
);
/* Set the window on top if necessary */
if
(
b
&&
!
(
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
(
!
b
&&
(
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
;
}
}
}
/*****************************************************************************
/*****************************************************************************
...
@@ -292,67 +214,81 @@ void CommonManage( vout_thread_t *p_vout )
...
@@ -292,67 +214,81 @@ void CommonManage( vout_thread_t *p_vout )
* its job is to update the source and destination RECTs used to display the
* its job is to update the source and destination RECTs used to display the
* picture.
* picture.
*****************************************************************************/
*****************************************************************************/
void
UpdateRects
(
vout_thread_t
*
p_vout
,
bool
b_force
)
void
UpdateRects
(
vout_display_t
*
vd
,
const
vout_display_cfg_t
*
cfg
,
const
video_format_t
*
source
,
bool
is_forced
)
{
{
#define rect_src p_vout->p_sys->rect_src
vout_display_sys_t
*
sys
=
vd
->
sys
;
#define rect_src_clipped p_vout->p_sys->rect_src_clipped
#define rect_src sys->rect_src
#define rect_dest p_vout->p_sys->rect_dest
#define rect_src_clipped sys->rect_src_clipped
#define rect_dest_clipped p_vout->p_sys->rect_dest_clipped
#define rect_dest sys->rect_dest
#define rect_dest_clipped sys->rect_dest_clipped
unsigned
int
i_width
,
i_height
,
i_x
,
i_y
;
RECT
rect
;
RECT
rect
;
POINT
point
;
POINT
point
;
/* Retrieve the window size */
/* Retrieve the window size */
GetClientRect
(
p_vout
->
p_sys
->
hwnd
,
&
rect
);
GetClientRect
(
sys
->
hwnd
,
&
rect
);
/* Retrieve the window position */
/* Retrieve the window position */
point
.
x
=
point
.
y
=
0
;
point
.
x
=
point
.
y
=
0
;
ClientToScreen
(
p_vout
->
p_sys
->
hwnd
,
&
point
);
ClientToScreen
(
sys
->
hwnd
,
&
point
);
/* If nothing changed, we can return */
/* If nothing changed, we can return */
bool
b
_changed
;
bool
has
_changed
;
EventThreadUpdateWindowPosition
(
p_vout
->
p_sys
->
p_event
,
&
b
_changed
,
EventThreadUpdateWindowPosition
(
sys
->
event
,
&
has
_changed
,
point
.
x
,
point
.
y
,
point
.
x
,
point
.
y
,
rect
.
right
,
rect
.
bottom
);
rect
.
right
,
rect
.
bottom
);
if
(
!
b_force
&&
!
b_changed
)
if
(
!
is_forced
&&
!
has_changed
)
return
;
return
;
/* */
if
(
!
cfg
)
cfg
=
vd
->
cfg
;
if
(
!
source
)
source
=
&
vd
->
source
;
/* Update the window position and size */
/* Update the window position and size */
vout_PlacePicture
(
p_vout
,
rect
.
right
,
rect
.
bottom
,
vout_display_cfg_t
place_cfg
=
*
cfg
;
&
i_x
,
&
i_y
,
&
i_width
,
&
i_height
);
place_cfg
.
display
.
width
=
rect
.
right
;
place_cfg
.
display
.
height
=
rect
.
bottom
;
vout_display_place_t
place
;
vout_display_PlacePicture
(
&
place
,
source
,
&
place_cfg
,
true
);
if
(
p_vout
->
p_sys
->
hvideownd
)
EventThreadUpdateSourceAndPlace
(
sys
->
event
,
source
,
&
place
);
SetWindowPos
(
p_vout
->
p_sys
->
hvideownd
,
0
,
i_x
,
i_y
,
i_width
,
i_height
,
if
(
sys
->
hvideownd
)
SWP_NOCOPYBITS
|
SWP_NOZORDER
|
SWP_ASYNCWINDOWPOS
);
SetWindowPos
(
sys
->
hvideownd
,
0
,
place
.
x
,
place
.
y
,
place
.
width
,
place
.
height
,
SWP_NOCOPYBITS
|
SWP_NOZORDER
|
SWP_ASYNCWINDOWPOS
);
/* Destination image position and dimensions */
/* Destination image position and dimensions */
#if defined(MODULE_NAME_IS_direct3d)
#if defined(MODULE_NAME_IS_direct3d)
rect_dest
.
left
=
0
;
rect_dest
.
left
=
0
;
rect_dest
.
right
=
i_
width
;
rect_dest
.
right
=
place
.
width
;
rect_dest
.
top
=
0
;
rect_dest
.
top
=
0
;
rect_dest
.
bottom
=
i_
height
;
rect_dest
.
bottom
=
place
.
height
;
#else
#else
rect_dest
.
left
=
point
.
x
+
i_
x
;
rect_dest
.
left
=
point
.
x
+
place
.
x
;
rect_dest
.
right
=
rect_dest
.
left
+
i_
width
;
rect_dest
.
right
=
rect_dest
.
left
+
place
.
width
;
rect_dest
.
top
=
point
.
y
+
i_
y
;
rect_dest
.
top
=
point
.
y
+
place
.
y
;
rect_dest
.
bottom
=
rect_dest
.
top
+
i_
height
;
rect_dest
.
bottom
=
rect_dest
.
top
+
place
.
height
;
#ifdef MODULE_NAME_IS_directx
#ifdef MODULE_NAME_IS_directx
/* Apply overlay hardware constraints */
/* Apply overlay hardware constraints */
if
(
p_vout
->
p_sys
->
b_using_overlay
)
if
(
sys
->
b_using_overlay
)
{
{
if
(
sys
->
i_align_dest_boundary
)
if
(
p_vout
->
p_sys
->
i_align_dest_boundary
)
rect_dest
.
left
=
(
rect_dest
.
left
+
rect_dest
.
left
=
(
rect_dest
.
left
+
sys
->
i_align_dest_boundary
/
2
)
&
p_vout
->
p_sys
->
i_align_dest_boundary
/
2
)
&
~
sys
->
i_align_dest_boundary
;
~
p_vout
->
p_sys
->
i_align_dest_boundary
;
if
(
sys
->
i_align_dest_size
)
if
(
p_vout
->
p_sys
->
i_align_dest_size
)
rect_dest
.
right
=
((
rect_dest
.
right
-
rect_dest
.
right
=
((
rect_dest
.
right
-
rect_dest
.
left
+
rect_dest
.
left
+
p_vout
->
p_sys
->
i_align_dest_size
/
2
)
&
sys
->
i_align_dest_size
/
2
)
&
~
p_vout
->
p_
sys
->
i_align_dest_size
)
+
rect_dest
.
left
;
~
sys
->
i_align_dest_size
)
+
rect_dest
.
left
;
}
}
#endif
#endif
...
@@ -364,18 +300,17 @@ void UpdateRects( vout_thread_t *p_vout, bool b_force )
...
@@ -364,18 +300,17 @@ void UpdateRects( vout_thread_t *p_vout, bool b_force )
* It is also needed for d3d to avoid exceding our surface size */
* It is also needed for d3d to avoid exceding our surface size */
/* Clip the destination window */
/* Clip the destination window */
if
(
!
IntersectRect
(
&
rect_dest_clipped
,
&
rect_dest
,
if
(
!
IntersectRect
(
&
rect_dest_clipped
,
&
rect_dest
,
&
p_vout
->
p_sys
->
rect_display
)
)
&
sys
->
rect_display
))
{
{
SetRectEmpty
(
&
rect_src_clipped
);
SetRectEmpty
(
&
rect_src_clipped
);
return
;
return
;
}
}
#ifndef NDEBUG
#ifndef NDEBUG
msg_Dbg
(
p_vout
,
"DirectXUpdateRects image_dst_clipped coords:"
msg_Dbg
(
vd
,
"DirectXUpdateRects image_dst_clipped coords:"
" %li,%li,%li,%li"
,
" %li,%li,%li,%li"
,
rect_dest_clipped
.
left
,
rect_dest_clipped
.
top
,
rect_dest_clipped
.
left
,
rect_dest_clipped
.
top
,
rect_dest_clipped
.
right
,
rect_dest_clipped
.
bottom
);
rect_dest_clipped
.
right
,
rect_dest_clipped
.
bottom
);
#endif
#endif
#else
#else
...
@@ -386,49 +321,48 @@ void UpdateRects( vout_thread_t *p_vout, bool b_force )
...
@@ -386,49 +321,48 @@ void UpdateRects( vout_thread_t *p_vout, bool b_force )
#endif
#endif
/* the 2 following lines are to fix a bug when clicking on the desktop */
/* the 2 following lines are to fix a bug when clicking on the desktop */
if
(
(
rect_dest_clipped
.
right
-
rect_dest_clipped
.
left
)
==
0
||
if
((
rect_dest_clipped
.
right
-
rect_dest_clipped
.
left
)
==
0
||
(
rect_dest_clipped
.
bottom
-
rect_dest_clipped
.
top
)
==
0
)
(
rect_dest_clipped
.
bottom
-
rect_dest_clipped
.
top
)
==
0
)
{
{
SetRectEmpty
(
&
rect_src_clipped
);
SetRectEmpty
(
&
rect_src_clipped
);
return
;
return
;
}
}
/* src image dimensions */
/* src image dimensions */
rect_src
.
left
=
0
;
rect_src
.
left
=
0
;
rect_src
.
top
=
0
;
rect_src
.
top
=
0
;
rect_src
.
right
=
p_vout
->
render
.
i_width
;
rect_src
.
right
=
source
->
i_width
;
rect_src
.
bottom
=
p_vout
->
render
.
i_height
;
rect_src
.
bottom
=
source
->
i_height
;
/* Clip the source image */
/* Clip the source image */
rect_src_clipped
.
left
=
p_vout
->
fmt_out
.
i_x_offset
+
rect_src_clipped
.
left
=
source
->
i_x_offset
+
(
rect_dest_clipped
.
left
-
rect_dest
.
left
)
*
(
rect_dest_clipped
.
left
-
rect_dest
.
left
)
*
p_vout
->
fmt_out
.
i_visible_width
/
(
rect_dest
.
right
-
rect_dest
.
left
);
source
->
i_visible_width
/
(
rect_dest
.
right
-
rect_dest
.
left
);
rect_src_clipped
.
right
=
p_vout
->
fmt_out
.
i_x_offset
+
rect_src_clipped
.
right
=
source
->
i_x_offset
+
p_vout
->
fmt_out
.
i_visible_width
-
source
->
i_visible_width
-
(
rect_dest
.
right
-
rect_dest_clipped
.
right
)
*
(
rect_dest
.
right
-
rect_dest_clipped
.
right
)
*
p_vout
->
fmt_out
.
i_visible_width
/
(
rect_dest
.
right
-
rect_dest
.
left
);
source
->
i_visible_width
/
(
rect_dest
.
right
-
rect_dest
.
left
);
rect_src_clipped
.
top
=
p_vout
->
fmt_out
.
i_y_offset
+
rect_src_clipped
.
top
=
source
->
i_y_offset
+
(
rect_dest_clipped
.
top
-
rect_dest
.
top
)
*
(
rect_dest_clipped
.
top
-
rect_dest
.
top
)
*
p_vout
->
fmt_out
.
i_visible_height
/
(
rect_dest
.
bottom
-
rect_dest
.
top
);
source
->
i_visible_height
/
(
rect_dest
.
bottom
-
rect_dest
.
top
);
rect_src_clipped
.
bottom
=
p_vout
->
fmt_out
.
i_y_offset
+
rect_src_clipped
.
bottom
=
source
->
i_y_offset
+
p_vout
->
fmt_out
.
i_visible_height
-
source
->
i_visible_height
-
(
rect_dest
.
bottom
-
rect_dest_clipped
.
bottom
)
*
(
rect_dest
.
bottom
-
rect_dest_clipped
.
bottom
)
*
p_vout
->
fmt_out
.
i_visible_height
/
(
rect_dest
.
bottom
-
rect_dest
.
top
);
source
->
i_visible_height
/
(
rect_dest
.
bottom
-
rect_dest
.
top
);
#ifdef MODULE_NAME_IS_directx
#ifdef MODULE_NAME_IS_directx
/* Apply overlay hardware constraints */
/* Apply overlay hardware constraints */
if
(
p_vout
->
p_sys
->
b_using_overlay
)
if
(
sys
->
b_using_overlay
)
{
{
if
(
sys
->
i_align_src_boundary
)
if
(
p_vout
->
p_sys
->
i_align_src_boundary
)
rect_src_clipped
.
left
=
rect_src_clipped
.
left
=
(
rect_src_clipped
.
left
+
(
rect_src_clipped
.
left
+
p_vout
->
p_sys
->
i_align_src_boundary
/
2
)
&
sys
->
i_align_src_boundary
/
2
)
&
~
p_vout
->
p_
sys
->
i_align_src_boundary
;
~
sys
->
i_align_src_boundary
;
if
(
p_vout
->
p_sys
->
i_align_src_size
)
if
(
sys
->
i_align_src_size
)
rect_src_clipped
.
right
=
((
rect_src_clipped
.
right
-
rect_src_clipped
.
right
=
rect_src_clipped
.
left
+
((
rect_src_clipped
.
right
-
rect_src_clipped
.
left
+
p_vout
->
p_sys
->
i_align_src_size
/
2
)
&
sys
->
i_align_src_size
/
2
)
&
~
p_vout
->
p_
sys
->
i_align_src_size
)
+
rect_src_clipped
.
left
;
~
sys
->
i_align_src_size
)
+
rect_src_clipped
.
left
;
}
}
#elif defined(MODULE_NAME_IS_direct3d)
#elif defined(MODULE_NAME_IS_direct3d)
/* Needed at least with YUV content */
/* Needed at least with YUV content */
...
@@ -439,59 +373,57 @@ void UpdateRects( vout_thread_t *p_vout, bool b_force )
...
@@ -439,59 +373,57 @@ void UpdateRects( vout_thread_t *p_vout, bool b_force )
#endif
#endif
#ifndef NDEBUG
#ifndef NDEBUG
msg_Dbg
(
p_vout
,
"DirectXUpdateRects image_src_clipped"
msg_Dbg
(
vd
,
"DirectXUpdateRects image_src_clipped"
" coords: %li,%li,%li,%li"
,
" coords: %li,%li,%li,%li"
,
rect_src_clipped
.
left
,
rect_src_clipped
.
top
,
rect_src_clipped
.
left
,
rect_src_clipped
.
top
,
rect_src_clipped
.
right
,
rect_src_clipped
.
bottom
);
rect_src_clipped
.
right
,
rect_src_clipped
.
bottom
);
#endif
#endif
#ifdef MODULE_NAME_IS_directx
#ifdef MODULE_NAME_IS_directx
/* The destination coordinates need to be relative to the current
/* The destination coordinates need to be relative to the current
* directdraw primary surface (display) */
* directdraw primary surface (display) */
rect_dest_clipped
.
left
-=
p_vout
->
p_
sys
->
rect_display
.
left
;
rect_dest_clipped
.
left
-=
sys
->
rect_display
.
left
;
rect_dest_clipped
.
right
-=
p_vout
->
p_
sys
->
rect_display
.
left
;
rect_dest_clipped
.
right
-=
sys
->
rect_display
.
left
;
rect_dest_clipped
.
top
-=
p_vout
->
p_
sys
->
rect_display
.
top
;
rect_dest_clipped
.
top
-=
sys
->
rect_display
.
top
;
rect_dest_clipped
.
bottom
-=
p_vout
->
p_
sys
->
rect_display
.
top
;
rect_dest_clipped
.
bottom
-=
sys
->
rect_display
.
top
;
if
(
p_vout
->
p_sys
->
b_using_overlay
)
if
(
sys
->
b_using_overlay
)
DirectDrawUpdateOverlay
(
p_vout
);
DirectDrawUpdateOverlay
(
vd
);
#endif
#endif
#ifndef UNDER_CE
#ifndef UNDER_CE
/* Windows 7 taskbar thumbnail code */
/* Windows 7 taskbar thumbnail code */
LPTASKBARLIST3
p_
taskbl
;
LPTASKBARLIST3
taskbl
;
OSVERSIONINFO
winVer
;
OSVERSIONINFO
winVer
;
winVer
.
dwOSVersionInfoSize
=
sizeof
(
OSVERSIONINFO
);
winVer
.
dwOSVersionInfoSize
=
sizeof
(
OSVERSIONINFO
);
if
(
GetVersionEx
(
&
winVer
)
&&
winVer
.
dwMajorVersion
>
5
)
if
(
GetVersionEx
(
&
winVer
)
&&
winVer
.
dwMajorVersion
>
5
)
{
{
CoInitialize
(
0
);
CoInitialize
(
0
);
if
(
S_OK
==
CoCreateInstance
(
&
clsid_ITaskbarList
,
if
(
S_OK
==
CoCreateInstance
(
&
clsid_ITaskbarList
,
NULL
,
CLSCTX_INPROC_SERVER
,
NULL
,
CLSCTX_INPROC_SERVER
,
&
IID_ITaskbarList3
,
&
IID_ITaskbarList3
,
&
taskbl
))
{
&
p_taskbl
)
)
{
RECT
rect_video
,
rect_parent
,
rect_relative
;
RECT
rect_video
,
rect_parent
,
rect_relative
;
HWND
hroot
=
GetAncestor
(
p_vout
->
p_
sys
->
hwnd
,
GA_ROOT
);
HWND
hroot
=
GetAncestor
(
sys
->
hwnd
,
GA_ROOT
);
p_taskbl
->
vt
->
HrInit
(
p_
taskbl
);
taskbl
->
vt
->
HrInit
(
taskbl
);
GetWindowRect
(
p_vout
->
p_
sys
->
hvideownd
,
&
rect_video
);
GetWindowRect
(
sys
->
hvideownd
,
&
rect_video
);
GetWindowRect
(
hroot
,
&
rect_parent
);
GetWindowRect
(
hroot
,
&
rect_parent
);
rect_relative
.
left
=
rect_video
.
left
-
rect_parent
.
left
-
8
;
rect_relative
.
left
=
rect_video
.
left
-
rect_parent
.
left
-
8
;
rect_relative
.
right
=
rect_video
.
right
-
rect_video
.
left
+
rect_relative
.
left
;
rect_relative
.
right
=
rect_video
.
right
-
rect_video
.
left
+
rect_relative
.
left
;
rect_relative
.
top
=
rect_video
.
top
-
rect_parent
.
top
-
10
;
rect_relative
.
top
=
rect_video
.
top
-
rect_parent
.
top
-
10
;
rect_relative
.
bottom
=
rect_video
.
bottom
-
rect_video
.
top
+
rect_relative
.
top
-
25
;
rect_relative
.
bottom
=
rect_video
.
bottom
-
rect_video
.
top
+
rect_relative
.
top
-
25
;
if
(
S_OK
!=
p_taskbl
->
vt
->
SetThumbnailClip
(
p_
taskbl
,
hroot
,
&
rect_relative
))
if
(
S_OK
!=
taskbl
->
vt
->
SetThumbnailClip
(
taskbl
,
hroot
,
&
rect_relative
))
msg_Err
(
p_vout
,
"SetThumbNailClip failed"
);
msg_Err
(
vd
,
"SetThumbNailClip failed"
);
p_taskbl
->
vt
->
Release
(
p_
taskbl
);
taskbl
->
vt
->
Release
(
taskbl
);
}
}
CoUninitialize
();
CoUninitialize
();
}
}
#endif
#endif
/* Signal the change in size/position */
/* Signal the change in size/position */
p_vout
->
p_sys
->
i_
changes
|=
DX_POSITION_CHANGE
;
sys
->
changes
|=
DX_POSITION_CHANGE
;
#undef rect_src
#undef rect_src
#undef rect_src_clipped
#undef rect_src_clipped
...
@@ -499,254 +431,238 @@ void UpdateRects( vout_thread_t *p_vout, bool b_force )
...
@@ -499,254 +431,238 @@ void UpdateRects( vout_thread_t *p_vout, bool b_force )
#undef rect_dest_clipped
#undef rect_dest_clipped
}
}
/*****************************************************************************
static
int
CommonControlSetFullscreen
(
vout_display_t
*
vd
,
bool
is_fullscreen
)
* Control: control facility for the vout
*****************************************************************************/
int
Control
(
vout_thread_t
*
p_vout
,
int
i_query
,
va_list
args
)
{
{
RECT
rect_window
;
vout_display_sys_t
*
sys
=
vd
->
sys
;
switch
(
i_query
)
{
case
VOUT_SET_SIZE
:
if
(
p_vout
->
p_sys
->
parent_window
)
return
vaControlParentWindow
(
p_vout
,
i_query
,
args
);
/* Update dimensions */
rect_window
.
top
=
rect_window
.
left
=
0
;
rect_window
.
right
=
va_arg
(
args
,
unsigned
int
);
rect_window
.
bottom
=
va_arg
(
args
,
unsigned
int
);
if
(
!
rect_window
.
right
)
rect_window
.
right
=
p_vout
->
i_window_width
;
if
(
!
rect_window
.
bottom
)
rect_window
.
bottom
=
p_vout
->
i_window_height
;
AdjustWindowRect
(
&
rect_window
,
EventThreadGetWindowStyle
(
p_vout
->
p_sys
->
p_event
),
0
);
SetWindowPos
(
p_vout
->
p_sys
->
hwnd
,
0
,
0
,
0
,
rect_window
.
right
-
rect_window
.
left
,
rect_window
.
bottom
-
rect_window
.
top
,
SWP_NOMOVE
);
return
VLC_SUCCESS
;
case
VOUT_SET_STAY_ON_TOP
:
if
(
p_vout
->
p_sys
->
hparent
&&
!
var_GetBool
(
p_vout
,
"fullscreen"
)
)
return
vaControlParentWindow
(
p_vout
,
i_query
,
args
);
p_vout
->
p_sys
->
b_on_top_change
=
true
;
#ifdef MODULE_NAME_IS_direct3d
return
VLC_SUCCESS
;
if
(
sys
->
use_desktop
&&
is_fullscreen
)
default:
return
VLC_EGENERIC
;
}
}
/* Internal wrapper over GetWindowPlacement */
static
WINDOWPLACEMENT
getWindowState
(
HWND
hwnd
)
{
WINDOWPLACEMENT
window_placement
;
window_placement
.
length
=
sizeof
(
WINDOWPLACEMENT
);
GetWindowPlacement
(
hwnd
,
&
window_placement
);
return
window_placement
;
}
/* Internal wrapper to call vout_ControlWindow for hparent */
static
int
vaControlParentWindow
(
vout_thread_t
*
p_vout
,
int
i_query
,
va_list
args
)
{
switch
(
i_query
)
{
case
VOUT_SET_SIZE
:
{
const
unsigned
i_width
=
va_arg
(
args
,
unsigned
);
const
unsigned
i_height
=
va_arg
(
args
,
unsigned
);
return
vout_window_SetSize
(
p_vout
->
p_sys
->
parent_window
,
i_width
,
i_height
);
}
case
VOUT_SET_STAY_ON_TOP
:
{
const
bool
is_on_top
=
va_arg
(
args
,
int
);
return
vout_window_SetOnTop
(
p_vout
->
p_sys
->
parent_window
,
is_on_top
);
}
default:
return
VLC_EGENERIC
;
return
VLC_EGENERIC
;
}
}
#if 0
static int ControlParentWindow( vout_thread_t *p_vout, int i_query, ... )
{
va_list args;
int ret;
va_start( args, i_query );
ret = vaControlParentWindow( p_vout, i_query, args );
va_end( args );
return ret;
}
#endif
#endif
void
ExitFullscreen
(
vout_thread_t
*
p_vout
)
/* */
{
if
(
sys
->
parent_window
)
if
(
p_vout
->
b_fullscreen
)
return
vout_window_SetFullScreen
(
sys
->
parent_window
,
is_fullscreen
);
{
msg_Dbg
(
p_vout
,
"Quitting fullscreen"
);
Win32ToggleFullscreen
(
p_vout
);
/* Force fullscreen in the core for the next video */
var_SetBool
(
p_vout
,
"fullscreen"
,
true
);
}
}
void
Win32ToggleFullscreen
(
vout_thread_t
*
p_vout
)
/* */
{
HWND
hwnd
=
sys
->
hparent
&&
sys
->
hfswnd
?
sys
->
hfswnd
:
sys
->
hwnd
;
HWND
hwnd
=
(
p_vout
->
p_sys
->
hparent
&&
p_vout
->
p_sys
->
hfswnd
)
?
p_vout
->
p_sys
->
hfswnd
:
p_vout
->
p_sys
->
hwnd
;
/* Save the current windows placement/placement to restore
/* Save the current windows placement/placement to restore
when fullscreen is over */
when fullscreen is over */
WINDOWPLACEMENT
window_placement
=
getWindowState
(
hwnd
)
;
WINDOWPLACEMENT
window_placement
;
window_placement
.
length
=
sizeof
(
WINDOWPLACEMENT
);
p_vout
->
b_fullscreen
=
!
p_vout
->
b_fullscreen
;
GetWindowPlacement
(
hwnd
,
&
window_placement
)
;
/* We want to go to Fullscreen */
if
(
is_fullscreen
)
{
if
(
p_vout
->
b_fullscreen
)
msg_Dbg
(
vd
,
"entering fullscreen mode"
);
{
msg_Dbg
(
p_vout
,
"entering fullscreen mode"
);
/* Change window style, no borders and no title bar */
/* Change window style, no borders and no title bar */
int
i_style
=
WS_CLIPCHILDREN
|
WS_VISIBLE
;
SetWindowLong
(
hwnd
,
GWL_STYLE
,
WS_CLIPCHILDREN
|
WS_VISIBLE
);
SetWindowLong
(
hwnd
,
GWL_STYLE
,
i_style
);
if
(
p_vout
->
p_sys
->
hparent
)
if
(
sys
->
hparent
)
{
{
#ifdef UNDER_CE
#ifdef UNDER_CE
POINT
point
=
{
0
,
0
};
POINT
point
=
{
0
,
0
};
RECT
rect
;
RECT
rect
;
ClientToScreen
(
p_vout
->
p_sys
->
hwnd
,
&
point
);
ClientToScreen
(
sys
->
hwnd
,
&
point
);
GetClientRect
(
p_vout
->
p_sys
->
hwnd
,
&
rect
);
GetClientRect
(
sys
->
hwnd
,
&
rect
);
SetWindowPos
(
hwnd
,
0
,
point
.
x
,
point
.
y
,
SetWindowPos
(
hwnd
,
0
,
point
.
x
,
point
.
y
,
rect
.
right
,
rect
.
bottom
,
rect
.
right
,
rect
.
bottom
,
SWP_NOZORDER
|
SWP_FRAMECHANGED
);
SWP_NOZORDER
|
SWP_FRAMECHANGED
);
#else
#else
/* Retrieve current window position so fullscreen will happen
/* Retrieve current window position so fullscreen will happen
*on the right screen */
*on the right screen */
HMONITOR
hmon
=
MonitorFromWindow
(
p_vout
->
p_
sys
->
hparent
,
HMONITOR
hmon
=
MonitorFromWindow
(
sys
->
hparent
,
MONITOR_DEFAULTTONEAREST
);
MONITOR_DEFAULTTONEAREST
);
MONITORINFO
mi
;
MONITORINFO
mi
;
mi
.
cbSize
=
sizeof
(
MONITORINFO
);
mi
.
cbSize
=
sizeof
(
MONITORINFO
);
if
(
GetMonitorInfo
(
hmon
,
&
mi
))
if
(
GetMonitorInfo
(
hmon
,
&
mi
))
SetWindowPos
(
hwnd
,
0
,
SetWindowPos
(
hwnd
,
0
,
mi
.
rcMonitor
.
left
,
mi
.
rcMonitor
.
left
,
mi
.
rcMonitor
.
top
,
mi
.
rcMonitor
.
top
,
mi
.
rcMonitor
.
right
-
mi
.
rcMonitor
.
left
,
mi
.
rcMonitor
.
right
-
mi
.
rcMonitor
.
left
,
mi
.
rcMonitor
.
bottom
-
mi
.
rcMonitor
.
top
,
mi
.
rcMonitor
.
bottom
-
mi
.
rcMonitor
.
top
,
SWP_NOZORDER
|
SWP_FRAMECHANGED
);
SWP_NOZORDER
|
SWP_FRAMECHANGED
);
#endif
#endif
}
}
else
{
else
{
/* Maximize non embedded window */
/* Maximize non embedded window */
ShowWindow
(
hwnd
,
SW_SHOWMAXIMIZED
);
ShowWindow
(
hwnd
,
SW_SHOWMAXIMIZED
);
}
}
if
(
p_vout
->
p_sys
->
hparent
)
if
(
sys
->
hparent
)
{
{
/* Hide the previous window */
/* Hide the previous window */
RECT
rect
;
RECT
rect
;
GetClientRect
(
hwnd
,
&
rect
);
GetClientRect
(
hwnd
,
&
rect
);
SetParent
(
p_vout
->
p_sys
->
hwnd
,
hwnd
);
SetParent
(
sys
->
hwnd
,
hwnd
);
SetWindowPos
(
p_vout
->
p_
sys
->
hwnd
,
0
,
0
,
0
,
SetWindowPos
(
sys
->
hwnd
,
0
,
0
,
0
,
rect
.
right
,
rect
.
bottom
,
rect
.
right
,
rect
.
bottom
,
SWP_NOZORDER
|
SWP_FRAMECHANGED
);
SWP_NOZORDER
|
SWP_FRAMECHANGED
);
#ifdef UNDER_CE
#ifdef UNDER_CE
HWND
topLevelParent
=
GetParent
(
p_vout
->
p_sys
->
hparent
);
HWND
topLevelParent
=
GetParent
(
sys
->
hparent
);
#else
#else
HWND
topLevelParent
=
GetAncestor
(
p_vout
->
p_sys
->
hparent
,
GA_ROOT
);
HWND
topLevelParent
=
GetAncestor
(
sys
->
hparent
,
GA_ROOT
);
#endif
#endif
ShowWindow
(
topLevelParent
,
SW_HIDE
);
ShowWindow
(
topLevelParent
,
SW_HIDE
);
}
}
SetForegroundWindow
(
hwnd
);
}
else
{
msg_Dbg
(
vd
,
"leaving fullscreen mode"
);
SetForegroundWindow
(
hwnd
);
}
else
{
msg_Dbg
(
p_vout
,
"leaving fullscreen mode"
);
/* Change window style, no borders and no title bar */
/* Change window style, no borders and no title bar */
SetWindowLong
(
hwnd
,
GWL_STYLE
,
EventThreadGetWindowStyle
(
p_vout
->
p_sys
->
p_event
)
);
SetWindowLong
(
hwnd
,
GWL_STYLE
,
EventThreadGetWindowStyle
(
sys
->
event
)
);
if
(
p_vout
->
p_sys
->
hparent
)
if
(
sys
->
hparent
)
{
{
RECT
rect
;
RECT
rect
;
GetClientRect
(
p_vout
->
p_sys
->
hparent
,
&
rect
);
GetClientRect
(
sys
->
hparent
,
&
rect
);
SetParent
(
p_vout
->
p_sys
->
hwnd
,
p_vout
->
p_sys
->
hparent
);
SetParent
(
sys
->
hwnd
,
sys
->
hparent
);
SetWindowPos
(
p_vout
->
p_
sys
->
hwnd
,
0
,
0
,
0
,
SetWindowPos
(
sys
->
hwnd
,
0
,
0
,
0
,
rect
.
right
,
rect
.
bottom
,
rect
.
right
,
rect
.
bottom
,
SWP_NOZORDER
|
SWP_FRAMECHANGED
);
SWP_NOZORDER
|
SWP_FRAMECHANGED
);
#ifdef UNDER_CE
#ifdef UNDER_CE
HWND
topLevelParent
=
GetParent
(
p_vout
->
p_sys
->
hparent
);
HWND
topLevelParent
=
GetParent
(
sys
->
hparent
);
#else
#else
HWND
topLevelParent
=
GetAncestor
(
p_vout
->
p_sys
->
hparent
,
GA_ROOT
);
HWND
topLevelParent
=
GetAncestor
(
sys
->
hparent
,
GA_ROOT
);
#endif
#endif
ShowWindow
(
topLevelParent
,
SW_SHOW
);
ShowWindow
(
topLevelParent
,
SW_SHOW
);
SetForegroundWindow
(
p_vout
->
p_sys
->
hparent
);
SetForegroundWindow
(
sys
->
hparent
);
ShowWindow
(
hwnd
,
SW_HIDE
);
ShowWindow
(
hwnd
,
SW_HIDE
);
}
}
else
{
else
{
/* return to normal window for non embedded vout */
/* return to normal window for non embedded vout */
SetWindowPlacement
(
hwnd
,
&
window_placement
);
SetWindowPlacement
(
hwnd
,
&
window_placement
);
ShowWindow
(
hwnd
,
SW_SHOWNORMAL
);
ShowWindow
(
hwnd
,
SW_SHOWNORMAL
);
}
}
/* Make sure the mouse cursor is displayed */
/* Make sure the mouse cursor is displayed */
EventThreadMouseShow
(
p_vout
->
p_sys
->
p_event
);
EventThreadMouseShow
(
sys
->
event
);
}
}
return
VLC_SUCCESS
;
}
/* Update the object variable and trigger callback */
int
CommonControl
(
vout_display_t
*
vd
,
int
query
,
va_list
args
)
var_SetBool
(
p_vout
,
"fullscreen"
,
p_vout
->
b_fullscreen
);
{
vout_display_sys_t
*
sys
=
vd
->
sys
;
switch
(
query
)
{
case
VOUT_DISPLAY_CHANGE_DISPLAY_SIZE
:
/* const vout_display_cfg_t *p_cfg, int is_forced */
case
VOUT_DISPLAY_CHANGE_DISPLAY_FILLED
:
/* const vout_display_cfg_t *p_cfg */
case
VOUT_DISPLAY_CHANGE_ZOOM
:
/* const vout_display_cfg_t *p_cfg */
case
VOUT_DISPLAY_CHANGE_SOURCE_ASPECT
:
/* const video_format_t *p_source */
case
VOUT_DISPLAY_CHANGE_SOURCE_CROP
:
{
/* const video_format_t *p_source */
const
vout_display_cfg_t
*
cfg
;
const
video_format_t
*
source
;
bool
is_forced
=
true
;
if
(
query
==
VOUT_DISPLAY_CHANGE_SOURCE_CROP
||
query
==
VOUT_DISPLAY_CHANGE_SOURCE_ASPECT
)
{
cfg
=
vd
->
cfg
;
source
=
va_arg
(
args
,
const
video_format_t
*
);
}
else
{
cfg
=
va_arg
(
args
,
const
vout_display_cfg_t
*
);
source
=
&
vd
->
source
;
if
(
query
==
VOUT_DISPLAY_CHANGE_DISPLAY_SIZE
)
is_forced
=
va_arg
(
args
,
int
);
}
if
(
query
==
VOUT_DISPLAY_CHANGE_DISPLAY_SIZE
&&
is_forced
)
{
/* Update dimensions */
if
(
sys
->
parent_window
)
{
vout_window_SetSize
(
sys
->
parent_window
,
cfg
->
display
.
width
,
cfg
->
display
.
height
);
}
else
{
RECT
rect_window
;
rect_window
.
top
=
0
;
rect_window
.
left
=
0
;
rect_window
.
right
=
cfg
->
display
.
width
;
rect_window
.
bottom
=
cfg
->
display
.
height
;
AdjustWindowRect
(
&
rect_window
,
EventThreadGetWindowStyle
(
sys
->
event
),
0
);
SetWindowPos
(
sys
->
hwnd
,
0
,
0
,
0
,
rect_window
.
right
-
rect_window
.
left
,
rect_window
.
bottom
-
rect_window
.
top
,
SWP_NOMOVE
);
}
}
UpdateRects
(
vd
,
cfg
,
source
,
is_forced
);
return
VLC_SUCCESS
;
}
case
VOUT_DISPLAY_CHANGE_ON_TOP
:
{
/* int b_on_top */
const
bool
is_on_top
=
va_arg
(
args
,
int
);
#ifdef MODULE_NAME_IS_direct3d
if
(
sys
->
use_desktop
&&
is_on_top
)
return
VLC_EGENERIC
;
#endif
if
(
sys
->
parent_window
)
{
if
(
vout_window_SetOnTop
(
sys
->
parent_window
,
is_on_top
))
return
VLC_EGENERIC
;
}
else
{
HMENU
hMenu
=
GetSystemMenu
(
sys
->
hwnd
,
FALSE
);
if
(
is_on_top
&&
!
(
GetWindowLong
(
sys
->
hwnd
,
GWL_EXSTYLE
)
&
WS_EX_TOPMOST
))
{
CheckMenuItem
(
hMenu
,
IDM_TOGGLE_ON_TOP
,
MF_BYCOMMAND
|
MFS_CHECKED
);
SetWindowPos
(
sys
->
hwnd
,
HWND_TOPMOST
,
0
,
0
,
0
,
0
,
SWP_NOSIZE
|
SWP_NOMOVE
);
}
else
if
(
!
is_on_top
&&
(
GetWindowLong
(
sys
->
hwnd
,
GWL_EXSTYLE
)
&
WS_EX_TOPMOST
))
{
CheckMenuItem
(
hMenu
,
IDM_TOGGLE_ON_TOP
,
MF_BYCOMMAND
|
MFS_UNCHECKED
);
SetWindowPos
(
sys
->
hwnd
,
HWND_NOTOPMOST
,
0
,
0
,
0
,
0
,
SWP_NOSIZE
|
SWP_NOMOVE
);
}
}
sys
->
is_on_top
=
is_on_top
;
return
VLC_SUCCESS
;
}
case
VOUT_DISPLAY_CHANGE_FULLSCREEN
:
{
/* const vout_display_cfg_t *p_cfg */
const
vout_display_cfg_t
*
cfg
=
va_arg
(
args
,
const
vout_display_cfg_t
*
);
return
CommonControlSetFullscreen
(
vd
,
cfg
->
is_fullscreen
);
}
case
VOUT_DISPLAY_RESET_PICTURES
:
case
VOUT_DISPLAY_HIDE_MOUSE
:
assert
(
0
);
default:
return
VLC_EGENERIC
;
}
}
}
#ifndef UNDER_CE
#ifndef UNDER_CE
void
DisableScreensaver
(
vout_thread_t
*
p_vout
)
static
void
DisableScreensaver
(
vout_display_t
*
vd
)
{
{
vout_display_sys_t
*
sys
=
vd
->
sys
;
/* disable screensaver by temporarily changing system settings */
/* disable screensaver by temporarily changing system settings */
p_vout
->
p_sys
->
i_spi_lowpowertimeout
=
0
;
sys
->
i_spi_lowpowertimeout
=
0
;
p_vout
->
p_sys
->
i_spi_powerofftimeout
=
0
;
sys
->
i_spi_powerofftimeout
=
0
;
p_vout
->
p_sys
->
i_spi_screensavetimeout
=
0
;
sys
->
i_spi_screensavetimeout
=
0
;
if
(
var_GetBool
(
p_vout
,
"disable-screensaver"
)
)
if
(
var_GetBool
(
vd
,
"disable-screensaver"
))
{
{
msg_Dbg
(
vd
,
"disabling screen saver"
);
msg_Dbg
(
p_vout
,
"disabling screen saver"
);
SystemParametersInfo
(
SPI_GETLOWPOWERTIMEOUT
,
0
,
SystemParametersInfo
(
SPI_GETLOWPOWERTIMEOUT
,
&
sys
->
i_spi_lowpowertimeout
,
0
);
0
,
&
(
p_vout
->
p_sys
->
i_spi_lowpowertimeout
),
0
);
if
(
0
!=
sys
->
i_spi_lowpowertimeout
)
{
if
(
0
!=
p_vout
->
p_sys
->
i_spi_lowpowertimeout
)
{
SystemParametersInfo
(
SPI_SETLOWPOWERTIMEOUT
,
0
,
NULL
,
0
);
SystemParametersInfo
(
SPI_SETLOWPOWERTIMEOUT
,
0
,
NULL
,
0
);
}
}
SystemParametersInfo
(
SPI_GETPOWEROFFTIMEOUT
,
0
,
SystemParametersInfo
(
SPI_GETPOWEROFFTIMEOUT
,
0
,
&
(
p_vout
->
p_sys
->
i_spi_powerofftimeout
)
,
0
);
&
sys
->
i_spi_powerofftimeout
,
0
);
if
(
0
!=
p_vout
->
p_sys
->
i_spi_powerofftimeout
)
{
if
(
0
!=
sys
->
i_spi_powerofftimeout
)
{
SystemParametersInfo
(
SPI_SETPOWEROFFTIMEOUT
,
0
,
NULL
,
0
);
SystemParametersInfo
(
SPI_SETPOWEROFFTIMEOUT
,
0
,
NULL
,
0
);
}
}
SystemParametersInfo
(
SPI_GETSCREENSAVETIMEOUT
,
0
,
SystemParametersInfo
(
SPI_GETSCREENSAVETIMEOUT
,
0
,
&
(
p_vout
->
p_sys
->
i_spi_screensavetimeout
)
,
0
);
&
sys
->
i_spi_screensavetimeout
,
0
);
if
(
0
!=
p_vout
->
p_sys
->
i_spi_screensavetimeout
)
{
if
(
0
!=
sys
->
i_spi_screensavetimeout
)
{
SystemParametersInfo
(
SPI_SETSCREENSAVETIMEOUT
,
0
,
NULL
,
0
);
SystemParametersInfo
(
SPI_SETSCREENSAVETIMEOUT
,
0
,
NULL
,
0
);
}
}
}
}
}
}
void
RestoreScreensaver
(
vout_thread_t
*
p_vout
)
static
void
RestoreScreensaver
(
vout_display_t
*
vd
)
{
{
vout_display_sys_t
*
sys
=
vd
->
sys
;
/* restore screensaver system settings */
/* restore screensaver system settings */
if
(
0
!=
p_vout
->
p_sys
->
i_spi_lowpowertimeout
)
{
if
(
0
!=
sys
->
i_spi_lowpowertimeout
)
{
SystemParametersInfo
(
SPI_SETLOWPOWERTIMEOUT
,
SystemParametersInfo
(
SPI_SETLOWPOWERTIMEOUT
,
p_vout
->
p_
sys
->
i_spi_lowpowertimeout
,
NULL
,
0
);
sys
->
i_spi_lowpowertimeout
,
NULL
,
0
);
}
}
if
(
0
!=
p_vout
->
p_sys
->
i_spi_powerofftimeout
)
{
if
(
0
!=
sys
->
i_spi_powerofftimeout
)
{
SystemParametersInfo
(
SPI_SETPOWEROFFTIMEOUT
,
SystemParametersInfo
(
SPI_SETPOWEROFFTIMEOUT
,
p_vout
->
p_
sys
->
i_spi_powerofftimeout
,
NULL
,
0
);
sys
->
i_spi_powerofftimeout
,
NULL
,
0
);
}
}
if
(
0
!=
p_vout
->
p_sys
->
i_spi_screensavetimeout
)
{
if
(
0
!=
sys
->
i_spi_screensavetimeout
)
{
SystemParametersInfo
(
SPI_SETSCREENSAVETIMEOUT
,
SystemParametersInfo
(
SPI_SETSCREENSAVETIMEOUT
,
p_vout
->
p_
sys
->
i_spi_screensavetimeout
,
NULL
,
0
);
sys
->
i_spi_screensavetimeout
,
NULL
,
0
);
}
}
}
}
#endif
#endif
...
...
modules/video_output/msw/common.h
0 → 100644
View file @
f6d06e15
/*****************************************************************************
* common.h: Windows video output header file
*****************************************************************************
* Copyright (C) 2001-2009 the VideoLAN team
* $Id$
*
* Authors: Gildas Bazin <gbazin@videolan.org>
* Damien Fouilleul <damienf@videolan.org>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
*****************************************************************************/
/*****************************************************************************
* event_thread_t: event thread
*****************************************************************************/
#include <vlc_picture_pool.h>
#include "events.h"
#ifdef MODULE_NAME_IS_wingapi
typedef
struct
GXDisplayProperties
{
DWORD
cxWidth
;
DWORD
cyHeight
;
long
cbxPitch
;
long
cbyPitch
;
long
cBPP
;
DWORD
ffFormat
;
}
GXDisplayProperties
;
typedef
struct
GXScreenRect
{
DWORD
dwTop
;
DWORD
dwLeft
;
DWORD
dwWidth
;
DWORD
dwHeight
;
}
GXScreenRect
;
# define GX_FULLSCREEN 0x01
# define GX_NORMALKEYS 0x02
# define GX_LANDSCAPEKEYS 0x03
# ifndef kfLandscape
# define kfLandscape 0x8
# define kfPalette 0x10
# define kfDirect 0x20
# define kfDirect555 0x40
# define kfDirect565 0x80
# define kfDirect888 0x100
# define kfDirect444 0x200
# define kfDirectInverted 0x400
# endif
#endif
/*****************************************************************************
* vout_sys_t: video output method descriptor
*****************************************************************************
* This structure is part of the video output thread descriptor.
* It describes the module specific properties of an output thread.
*****************************************************************************/
struct
vout_display_sys_t
{
/* */
event_thread_t
*
event
;
/* */
HWND
hwnd
;
/* Handle of the main window */
HWND
hvideownd
;
/* Handle of the video sub-window */
struct
vout_window_t
*
parent_window
;
/* Parent window VLC object */
HWND
hparent
;
/* Handle of the parent window */
HWND
hfswnd
;
/* Handle of the fullscreen window */
/* Multi-monitor support */
HMONITOR
hmonitor
;
/* handle of the current monitor */
GUID
*
p_display_driver
;
HMONITOR
(
WINAPI
*
MonitorFromWindow
)(
HWND
,
DWORD
);
BOOL
(
WINAPI
*
GetMonitorInfo
)(
HMONITOR
,
LPMONITORINFO
);
/* size of the display */
RECT
rect_display
;
int
display_depth
;
/* size of the overall window (including black bands) */
RECT
rect_parent
;
unsigned
changes
;
/* changes made to the video display */
/* Misc */
bool
is_first_display
;
bool
is_on_top
;
#ifndef UNDER_CE
/* screensaver system settings to be restored when vout is closed */
UINT
i_spi_lowpowertimeout
;
UINT
i_spi_powerofftimeout
;
UINT
i_spi_screensavetimeout
;
#endif
/* Coordinates of src and dest images (used when blitting to display) */
RECT
rect_src
;
RECT
rect_src_clipped
;
RECT
rect_dest
;
RECT
rect_dest_clipped
;
bool
allow_hw_yuv
;
/* Should we use hardware YUV->RGB conversions */
#ifdef MODULE_NAME_IS_directx
/* Overlay alignment restrictions */
int
i_align_src_boundary
;
int
i_align_src_size
;
int
i_align_dest_boundary
;
int
i_align_dest_size
;
bool
b_wallpaper
;
/* show as desktop wallpaper ? */
bool
b_using_overlay
;
/* Are we using an overlay surface */
bool
b_use_sysmem
;
/* Should we use system memory for surfaces */
bool
b_3buf_overlay
;
/* Should we use triple buffered overlays */
/* DDraw capabilities */
int
b_caps_overlay_clipping
;
unsigned
int
i_rgb_colorkey
;
/* colorkey in RGB used by the overlay */
unsigned
int
i_colorkey
;
/* colorkey used by the overlay */
COLORREF
color_bkg
;
COLORREF
color_bkgtxt
;
LPDIRECTDRAW2
p_ddobject
;
/* DirectDraw object */
LPDIRECTDRAWSURFACE2
p_display
;
/* Display device */
LPDIRECTDRAWSURFACE2
p_current_surface
;
/* surface currently displayed */
LPDIRECTDRAWCLIPPER
p_clipper
;
/* clipper used for blitting */
HINSTANCE
hddraw_dll
;
/* handle of the opened ddraw dll */
vlc_mutex_t
lock
;
#endif
#ifdef MODULE_NAME_IS_glwin32
HDC
hGLDC
;
HGLRC
hGLRC
;
#endif
#ifdef MODULE_NAME_IS_direct3d
/* show video on desktop window ? */
bool
use_desktop
;
struct
{
bool
is_fullscreen
;
bool
is_on_top
;
RECT
win
;
}
desktop_save
;
vout_display_cfg_t
cfg_saved
;
/* configuration used before going into desktop mode */
// core objects
HINSTANCE
hd3d9_dll
;
/* handle of the opened d3d9 dll */
LPDIRECT3D9
d3dobj
;
LPDIRECT3DDEVICE9
d3ddev
;
D3DPRESENT_PARAMETERS
d3dpp
;
// scene objects
LPDIRECT3DTEXTURE9
d3dtex
;
LPDIRECT3DVERTEXBUFFER9
d3dvtc
;
picture_resource_t
resource
;
picture_pool_t
*
pool
;
/* */
bool
reset_device
;
bool
reopen_device
;
/* It protects the following variables */
vlc_mutex_t
lock
;
bool
ch_desktop
;
bool
desktop_requested
;
#endif
#ifdef MODULE_NAME_IS_wingdi
int
i_depth
;
/* Our offscreen bitmap and its framebuffer */
HDC
off_dc
;
HBITMAP
off_bitmap
;
uint8_t
*
p_pic_buffer
;
int
i_pic_pitch
;
int
i_pic_pixel_pitch
;
BITMAPINFO
bitmapinfo
;
RGBQUAD
red
;
RGBQUAD
green
;
RGBQUAD
blue
;
#endif
#ifdef MODULE_NAME_IS_wingapi
int
i_depth
;
int
render_width
;
int
render_height
;
/* Our offscreen bitmap and its framebuffer */
HDC
off_dc
;
HBITMAP
off_bitmap
;
uint8_t
*
p_pic_buffer
;
int
i_pic_pitch
;
int
i_pic_pixel_pitch
;
BITMAPINFO
bitmapinfo
;
RGBQUAD
red
;
RGBQUAD
green
;
RGBQUAD
blue
;
HINSTANCE
gapi_dll
;
/* handle of the opened gapi dll */
/* GAPI functions */
int
(
*
GXOpenDisplay
)(
HWND
hWnd
,
DWORD
dwFlags
);
int
(
*
GXCloseDisplay
)();
void
*
(
*
GXBeginDraw
)();
int
(
*
GXEndDraw
)();
GXDisplayProperties
(
*
GXGetDisplayProperties
)();
int
(
*
GXSuspend
)();
int
(
*
GXResume
)();
#endif
};
#ifdef MODULE_NAME_IS_wingapi
# define GXOpenDisplay p_vout->p_sys->GXOpenDisplay
# define GXCloseDisplay p_vout->p_sys->GXCloseDisplay
# define GXBeginDraw p_vout->p_sys->GXBeginDraw
# define GXEndDraw p_vout->p_sys->GXEndDraw
# define GXGetDisplayProperties p_vout->p_sys->GXGetDisplayProperties
# define GXSuspend p_vout->p_sys->GXSuspend
# define GXResume p_vout->p_sys->GXResume
#endif
/*****************************************************************************
* Prototypes from directx.c
*****************************************************************************/
int
DirectDrawUpdateOverlay
(
vout_display_t
*
);
/*****************************************************************************
* Prototypes from common.c
*****************************************************************************/
int
CommonInit
(
vout_display_t
*
);
void
CommonClean
(
vout_display_t
*
);
void
CommonManage
(
vout_display_t
*
);
int
CommonControl
(
vout_display_t
*
,
int
,
va_list
);
void
UpdateRects
(
vout_display_t
*
,
const
vout_display_cfg_t
*
,
const
video_format_t
*
,
bool
is_forced
);
/*****************************************************************************
* Constants
*****************************************************************************/
#define IDM_TOGGLE_ON_TOP WM_USER + 1
#define DX_POSITION_CHANGE 0x1000
#define DX_WALLPAPER_CHANGE 0x2000
#define DX_DESKTOP_CHANGE 0x4000
/*****************************************************************************
* WinCE helpers
*****************************************************************************/
#ifdef UNDER_CE
#define AdjustWindowRect(a,b,c)
#ifndef GCL_HBRBACKGROUND
# define GCL_HBRBACKGROUND (-10)
#endif
//#define FindWindowEx(a,b,c,d) 0
#define GetWindowPlacement(a,b)
#define SetWindowPlacement(a,b)
/*typedef struct _WINDOWPLACEMENT {
UINT length;
UINT flags;
UINT showCmd;
POINT ptMinPosition;
POINT ptMaxPosition;
RECT rcNormalPosition;
} WINDOWPLACEMENT;*/
#ifndef WM_NCMOUSEMOVE
# define WM_NCMOUSEMOVE 160
#endif
#ifndef CS_OWNDC
# define CS_OWNDC 32
#endif
#ifndef SC_SCREENSAVE
# define SC_SCREENSAVE 0xF140
#endif
#ifndef SC_MONITORPOWER
# define SC_MONITORPOWER 0xF170
#endif
#ifndef WM_NCPAINT
# define WM_NCPAINT 133
#endif
#ifndef WS_OVERLAPPEDWINDOW
# define WS_OVERLAPPEDWINDOW 0xcf0000
#endif
#ifndef WS_EX_NOPARENTNOTIFY
# define WS_EX_NOPARENTNOTIFY 4
#endif
#ifndef WS_EX_APPWINDOW
#define WS_EX_APPWINDOW 0x40000
#endif
//#define SetWindowLongPtr SetWindowLong
//#define GetWindowLongPtr GetWindowLong
//#define GWLP_USERDATA GWL_USERDATA
#endif //UNDER_CE
modules/video_output/msw/direct3d.c
View file @
f6d06e15
...
@@ -40,7 +40,7 @@
...
@@ -40,7 +40,7 @@
#include <vlc_common.h>
#include <vlc_common.h>
#include <vlc_plugin.h>
#include <vlc_plugin.h>
#include <vlc_playlist.h>
#include <vlc_playlist.h>
#include <vlc_vout.h>
#include <vlc_vout
_display
.h>
#include <windows.h>
#include <windows.h>
#include <d3d9.h>
#include <d3d9.h>
...
@@ -63,20 +63,19 @@ vlc_module_begin ()
...
@@ -63,20 +63,19 @@ vlc_module_begin ()
set_category
(
CAT_VIDEO
)
set_category
(
CAT_VIDEO
)
set_subcategory
(
SUBCAT_VIDEO_VOUT
)
set_subcategory
(
SUBCAT_VIDEO_VOUT
)
add_bool
(
"direct3d-desktop"
,
false
,
NULL
,
DESKTOP_TEXT
,
DESKTOP_LONGTEXT
,
add_bool
(
"direct3d-desktop"
,
false
,
NULL
,
DESKTOP_TEXT
,
DESKTOP_LONGTEXT
,
true
)
true
)
set_description
(
N_
(
"DirectX 3D video output"
))
set_description
(
N_
(
"DirectX 3D video output"
))
set_capability
(
"v
ideo output
"
,
50
)
set_capability
(
"v
out display
"
,
50
)
add_shortcut
(
"direct3d"
)
add_shortcut
(
"direct3d
_xp
"
)
set_callbacks
(
OpenVideoXP
,
Close
)
set_callbacks
(
OpenVideoXP
,
Close
)
/* FIXME: Hack to avoid unregistering our window class */
/* FIXME: Hack to avoid unregistering our window class */
linked_with_a_crap_library_which_uses_atexit
()
linked_with_a_crap_library_which_uses_atexit
()
add_submodule
()
add_submodule
()
set_capability
(
"video output"
,
150
)
set_capability
(
"video output"
,
150
)
add_shortcut
(
"direct3d"
)
add_shortcut
(
"direct3d
_vista
"
)
set_callbacks
(
OpenVideoVista
,
Close
)
set_callbacks
(
OpenVideoVista
,
Close
)
vlc_module_end
()
vlc_module_end
()
...
@@ -91,92 +90,106 @@ vlc_module_end ()
...
@@ -91,92 +90,106 @@ vlc_module_end ()
/*****************************************************************************
/*****************************************************************************
* Local prototypes.
* Local prototypes.
*****************************************************************************/
*****************************************************************************/
static
int
Open
(
vlc_object_t
*
);
struct
picture_sys_t
{
static
int
Init
(
vout_thread_t
*
);
LPDIRECT3DSURFACE9
surface
;
static
void
End
(
vout_thread_t
*
);
};
static
int
Manage
(
vout_thread_t
*
);
static
void
Display
(
vout_thread_t
*
,
picture_t
*
);
static
void
FirstDisplay
(
vout_thread_t
*
,
picture_t
*
);
static
int
Direct3DCreate
(
vout_thread_t
*
);
static
void
Direct3DRelease
(
vout_thread_t
*
);
static
int
Direct3DOpen
(
vout_thread_t
*
);
static
int
Open
(
vlc_object_t
*
);
static
void
Direct3DClose
(
vout_thread_t
*
);
static
int
Direct3DResetDevice
(
vout_thread_t
*
);
static
picture_t
*
Get
(
vout_display_t
*
);
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
int
Direct3DCreatePictures
(
vout_thread_t
*
,
size_t
);
static
int
Direct3DCreate
(
vout_display_t
*
);
static
void
Direct3DReleasePictures
(
vout_thread_t
*
);
static
int
Direct3DReset
(
vout_display_t
*
);
static
void
Direct3DDestroy
(
vout_display_t
*
);
static
int
Direct3DLockSurface
(
vout_thread_t
*
,
picture
_t
*
);
static
int
Direct3DOpen
(
vout_display_t
*
,
video_format
_t
*
);
static
int
Direct3DUnlockSurface
(
vout_thread_t
*
,
picture
_t
*
);
static
void
Direct3DClose
(
vout_display
_t
*
);
static
int
Direct3DCreateScene
(
vout_thread_t
*
);
static
void
Direct3DRenderScene
(
vout_display_t
*
vd
,
LPDIRECT3DSURFACE9
surface
);
static
void
Direct3DReleaseScene
(
vout_thread_t
*
);
static
void
Direct3DRenderScene
(
vout_thread_t
*
,
picture_t
*
);
/* */
static
int
DesktopCallback
(
vlc_object_t
*
,
char
const
*
,
vlc_value_t
,
vlc_value_t
,
void
*
);
static
int
DesktopCallback
(
vlc_object_t
*
,
char
const
*
,
vlc_value_t
,
vlc_value_t
,
void
*
);
typedef
struct
{
FLOAT
x
,
y
,
z
;
// vertex untransformed position
FLOAT
rhw
;
// eye distance
D3DCOLOR
diffuse
;
// diffuse color
FLOAT
tu
,
tv
;
// texture relative coordinates
}
CUSTOMVERTEX
;
#define D3DFVF_CUSTOMVERTEX (D3DFVF_XYZRHW|D3DFVF_DIFFUSE|D3DFVF_TEX1)
/**
/**
* It creates a Direct3D vout display.
* It creates a Direct3D vout display.
*/
*/
static
int
Open
(
vlc_object_t
*
object
)
static
int
Open
(
vlc_object_t
*
object
)
{
{
vout_
thread_t
*
p_vout
=
(
vout_thread
_t
*
)
object
;
vout_
display_t
*
vd
=
(
vout_display
_t
*
)
object
;
vout_
sys_t
*
p_
sys
;
vout_
display_sys_t
*
sys
;
/* Allocate structure */
/* Allocate structure */
p_vout
->
p_sys
=
p_sys
=
calloc
(
1
,
sizeof
(
vout
_sys_t
));
vd
->
sys
=
sys
=
calloc
(
1
,
sizeof
(
vout_display
_sys_t
));
if
(
!
p_
sys
)
if
(
!
sys
)
return
VLC_ENOMEM
;
return
VLC_ENOMEM
;
if
(
VLC_SUCCESS
!=
Direct3DCreate
(
p_vout
))
{
if
(
Direct3DCreate
(
vd
))
{
msg_Err
(
p_vout
,
"Direct3D could not be initialized !
"
);
msg_Err
(
vd
,
"Direct3D could not be initialized
"
);
Direct3D
Release
(
p_vout
);
Direct3D
Destroy
(
vd
);
free
(
p_
sys
);
free
(
sys
);
return
VLC_EGENERIC
;
return
VLC_EGENERIC
;
}
}
p_sys
->
b_desktop
=
false
;
sys
->
use_desktop
=
var_CreateGetBool
(
vd
,
"direct3d-desktop"
);
sys
->
reset_device
=
false
;
/* Initialisations */
sys
->
reset_device
=
false
;
p_vout
->
pf_init
=
Init
;
sys
->
allow_hw_yuv
=
var_CreateGetBool
(
vd
,
"directx-hw-yuv"
);
p_vout
->
pf_end
=
End
;
sys
->
desktop_save
.
is_fullscreen
=
vd
->
cfg
->
is_fullscreen
;
p_vout
->
pf_manage
=
Manage
;
sys
->
desktop_save
.
is_on_top
=
false
;
p_vout
->
pf_render
=
Direct3DRenderScene
;
sys
->
desktop_save
.
win
.
left
=
0
;
p_vout
->
pf_display
=
FirstDisplay
;
sys
->
desktop_save
.
win
.
right
=
vd
->
cfg
->
display
.
width
;
p_vout
->
pf_control
=
Control
;
sys
->
desktop_save
.
win
.
top
=
0
;
sys
->
desktop_save
.
win
.
bottom
=
vd
->
cfg
->
display
.
height
;
if
(
CommonInit
(
vd
))
goto
error
;
if
(
CommonInit
(
p_vout
))
/* */
video_format_t
fmt
;
if
(
Direct3DOpen
(
vd
,
&
fmt
))
{
msg_Err
(
vd
,
"Direct3D could not be opened"
);
goto
error
;
goto
error
;
}
var_Create
(
p_vout
,
"directx-hw-yuv"
,
VLC_VAR_BOOL
|
VLC_VAR_DOINHERIT
);
/* */
var_Create
(
p_vout
,
"directx-device"
,
VLC_VAR_STRING
|
VLC_VAR_DOINHERIT
);
vout_display_info_t
info
=
vd
->
info
;
info
.
is_slow
=
true
;
info
.
has_double_click
=
true
;
info
.
has_hide_mouse
=
true
;
info
.
has_pictures_invalid
=
true
;
/* Interaction */
vlc_mutex_init
(
&
sys
->
lock
);
sys
->
ch_desktop
=
false
;
sys
->
desktop_requested
=
sys
->
use_desktop
;
/* Trigger a callback right now */
var_Create
(
p_vout
,
"direct3d-desktop"
,
VLC_VAR_BOOL
|
VLC_VAR_DOINHERIT
);
vlc_value_t
val
;
vlc_value_t
val
;
val
.
psz_string
=
_
(
"Desktop"
);
val
.
psz_string
=
_
(
"Desktop"
);
var_Change
(
p_vout
,
"direct3d-desktop"
,
VLC_VAR_SETTEXT
,
&
val
,
NULL
);
var_Change
(
vd
,
"direct3d-desktop"
,
VLC_VAR_SETTEXT
,
&
val
,
NULL
);
var_AddCallback
(
p_vout
,
"direct3d-desktop"
,
DesktopCallback
,
NULL
);
var_AddCallback
(
vd
,
"direct3d-desktop"
,
DesktopCallback
,
NULL
);
var_TriggerCallback
(
p_vout
,
"direct3d-desktop"
);
return
VLC_SUCCESS
;
/* Setup vout_display now that everything is fine */
vd
->
fmt
=
fmt
;
vd
->
info
=
info
;
vd
->
get
=
Get
;
vd
->
prepare
=
Prepare
;
vd
->
display
=
Display
;
vd
->
control
=
Control
;
vd
->
manage
=
Manage
;
/* Fix state in case of desktop mode */
if
(
sys
->
use_desktop
&&
vd
->
cfg
->
is_fullscreen
)
vout_display_SendEventFullscreen
(
vd
,
false
);
return
VLC_SUCCESS
;
error:
error:
Close
(
VLC_OBJECT
(
p_vout
));
Close
(
VLC_OBJECT
(
vd
));
return
VLC_EGENERIC
;
return
VLC_EGENERIC
;
}
}
...
@@ -204,92 +217,212 @@ static int OpenVideoVista(vlc_object_t *obj)
...
@@ -204,92 +217,212 @@ static int OpenVideoVista(vlc_object_t *obj)
*/
*/
static
void
Close
(
vlc_object_t
*
object
)
static
void
Close
(
vlc_object_t
*
object
)
{
{
vout_thread_t
*
p_vout
=
(
vout_thread_t
*
)
object
;
vout_display_t
*
vd
=
(
vout_display_t
*
)
object
;
var_DelCallback
(
vd
,
"direct3d-desktop"
,
DesktopCallback
,
NULL
);
CommonClean
(
p_vout
);
Direct3DClose
(
vd
);
Direct3DRelease
(
p_vout
);
CommonClean
(
vd
);
free
(
p_vout
->
p_sys
);
Direct3DDestroy
(
vd
);
free
(
vd
->
sys
);
}
}
/*****************************************************************************
/* */
* Init: initialize Direct3D video thread output method
static
picture_t
*
Get
(
vout_display_t
*
vd
)
*****************************************************************************/
static
int
Init
(
vout_thread_t
*
p_vout
)
{
{
vout_sys_t
*
p_sys
=
p_vout
->
p_sys
;
vout_display_sys_t
*
sys
=
vd
->
sys
;
int
i_ret
;
p_sys
->
b_hw_yuv
=
var_GetBool
(
p_vout
,
"directx-hw-yuv"
);
if
(
!
sys
->
pool
)
return
NULL
;
return
picture_pool_Get
(
sys
->
pool
);
}
/* Initialise Direct3D */
static
int
Direct3DLockSurface
(
picture_t
*
);
if
(
Direct3DOpen
(
p_vout
))
{
static
void
Direct3DUnlockSurface
(
picture_t
*
);
msg_Err
(
p_vout
,
"cannot initialize Direct3D"
);
return
VLC_EGENERIC
;
static
void
Prepare
(
vout_display_t
*
vd
,
picture_t
*
picture
)
{
LPDIRECT3DSURFACE9
surface
=
picture
->
p_sys
->
surface
;
#if 0
picture_Release(picture);
Direct3DRenderScene(vd, surface);
#else
/* FIXME it is a bit ugly, we need the surface to be unlocked for
* rendering.
* The clean way would be to release the picture (and ensure that
* the vout doesn't keep a reference). But because of the vout
* wrapper, we can't */
Direct3DUnlockSurface
(
picture
);
Direct3DRenderScene
(
vd
,
surface
);
Direct3DLockSurface
(
picture
);
#endif
}
static
void
Display
(
vout_display_t
*
vd
,
picture_t
*
picture
)
{
vout_display_sys_t
*
sys
=
vd
->
sys
;
LPDIRECT3DDEVICE9
d3ddev
=
sys
->
d3ddev
;
// Present the back buffer contents to the display
// No stretching should happen here !
const
RECT
src
=
sys
->
rect_dest_clipped
;
const
RECT
dst
=
sys
->
rect_dest_clipped
;
HRESULT
hr
=
IDirect3DDevice9_Present
(
d3ddev
,
&
src
,
&
dst
,
NULL
,
NULL
);
if
(
FAILED
(
hr
))
{
msg_Dbg
(
vd
,
"%s:%d (hr=0x%0lX)"
,
__FUNCTION__
,
__LINE__
,
hr
);
}
}
/* Initialize the output structure.
if
(
sys
->
is_first_display
)
{
* Since Direct3D can do rescaling for us, stick to the default
/* Video window is initially hidden, show it now since we got a
* coordinates and aspect. */
* picture to show.
p_vout
->
output
.
i_width
=
p_vout
->
render
.
i_width
;
*/
p_vout
->
output
.
i_height
=
p_vout
->
render
.
i_height
;
SetWindowPos
(
vd
->
sys
->
hvideownd
,
0
,
0
,
0
,
0
,
0
,
p_vout
->
output
.
i_aspect
=
p_vout
->
render
.
i_aspect
;
SWP_ASYNCWINDOWPOS
|
p_vout
->
fmt_out
=
p_vout
->
fmt_in
;
SWP_FRAMECHANGED
|
UpdateRects
(
p_vout
,
true
);
SWP_SHOWWINDOW
|
SWP_NOMOVE
|
/* create picture pool */
SWP_NOSIZE
|
p_vout
->
output
.
i_chroma
=
0
;
SWP_NOZORDER
);
i_ret
=
Direct3DCreatePictures
(
p_vout
,
1
);
sys
->
is_first_display
=
false
;
if
(
i_ret
)
{
msg_Err
(
p_vout
,
"Direct3D picture pool initialization failed !"
);
return
i_ret
;
}
}
/* create scene */
#if 0
i_ret
=
Direct3DCreateScene
(
p_vout
);
VLC_UNUSED(picture);
if
(
i_ret
)
{
#else
msg_Err
(
p_vout
,
"Direct3D scene initialization failed !"
);
/* XXX See Prepare() */
Direct3DReleasePictures
(
p_vout
);
picture_Release
(
picture
);
return
i_ret
;
#endif
}
static
int
ControlResetDevice
(
vout_display_t
*
vd
)
{
return
Direct3DReset
(
vd
);
}
static
int
ControlReopenDevice
(
vout_display_t
*
vd
)
{
vout_display_sys_t
*
sys
=
vd
->
sys
;
if
(
!
sys
->
use_desktop
)
{
/* Save non-desktop state */
sys
->
desktop_save
.
is_fullscreen
=
vd
->
cfg
->
is_fullscreen
;
sys
->
desktop_save
.
is_on_top
=
sys
->
is_on_top
;
WINDOWPLACEMENT
wp
=
{
.
length
=
sizeof
(
wp
),
};
GetWindowPlacement
(
sys
->
hparent
?
sys
->
hparent
:
sys
->
hwnd
,
&
wp
);
sys
->
desktop_save
.
win
=
wp
.
rcNormalPosition
;
}
}
/* Change the window title bar text */
/* */
EventThreadUpdateTitle
(
p_sys
->
p_event
,
VOUT_TITLE
" (Direct3D output)"
);
Direct3DClose
(
vd
);
EventThreadStop
(
sys
->
event
);
/* */
vlc_mutex_lock
(
&
sys
->
lock
);
sys
->
use_desktop
=
sys
->
desktop_requested
;
sys
->
ch_desktop
=
false
;
vlc_mutex_unlock
(
&
sys
->
lock
);
p_vout
->
fmt_out
.
i_chroma
=
p_vout
->
output
.
i_chroma
;
/* */
event_cfg_t
cfg
;
memset
(
&
cfg
,
0
,
sizeof
(
cfg
));
cfg
.
use_desktop
=
sys
->
use_desktop
;
if
(
!
sys
->
use_desktop
)
{
cfg
.
win
.
type
=
VOUT_WINDOW_TYPE_HWND
;
cfg
.
win
.
x
=
sys
->
desktop_save
.
win
.
left
;
cfg
.
win
.
y
=
sys
->
desktop_save
.
win
.
top
;
cfg
.
win
.
width
=
sys
->
desktop_save
.
win
.
right
-
sys
->
desktop_save
.
win
.
left
;
cfg
.
win
.
height
=
sys
->
desktop_save
.
win
.
bottom
-
sys
->
desktop_save
.
win
.
top
;
}
event_hwnd_t
hwnd
;
if
(
EventThreadStart
(
sys
->
event
,
&
hwnd
,
&
cfg
))
{
msg_Err
(
vd
,
"Failed to restart event thread"
);
return
VLC_EGENERIC
;
}
sys
->
parent_window
=
hwnd
.
parent_window
;
sys
->
hparent
=
hwnd
.
hparent
;
sys
->
hwnd
=
hwnd
.
hwnd
;
sys
->
hvideownd
=
hwnd
.
hvideownd
;
sys
->
hfswnd
=
hwnd
.
hfswnd
;
SetRectEmpty
(
&
sys
->
rect_parent
);
/* */
video_format_t
fmt
;
if
(
Direct3DOpen
(
vd
,
&
fmt
))
{
CommonClean
(
vd
);
msg_Err
(
vd
,
"Failed to reopen device"
);
return
VLC_EGENERIC
;
}
vd
->
fmt
=
fmt
;
sys
->
is_first_display
=
true
;
if
(
sys
->
use_desktop
)
{
/* Disable fullscreen/on_top while using desktop */
if
(
sys
->
desktop_save
.
is_fullscreen
)
vout_display_SendEventFullscreen
(
vd
,
false
);
if
(
sys
->
desktop_save
.
is_on_top
)
vout_display_SendEventOnTop
(
vd
,
false
);
}
else
{
/* Restore fullscreen/on_top */
if
(
sys
->
desktop_save
.
is_fullscreen
)
vout_display_SendEventFullscreen
(
vd
,
true
);
if
(
sys
->
desktop_save
.
is_on_top
)
vout_display_SendEventOnTop
(
vd
,
true
);
}
return
VLC_SUCCESS
;
return
VLC_SUCCESS
;
}
}
static
int
Control
(
vout_display_t
*
vd
,
int
query
,
va_list
args
)
/*****************************************************************************
* 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
)
{
{
Direct3DReleaseScene
(
p_vout
);
vout_display_sys_t
*
sys
=
vd
->
sys
;
Direct3DReleasePictures
(
p_vout
);
Direct3DClose
(
p_vout
);
switch
(
query
)
{
case
VOUT_DISPLAY_RESET_PICTURES
:
/* FIXME what to do here in case of failure */
if
(
sys
->
reset_device
)
{
if
(
ControlResetDevice
(
vd
))
{
msg_Err
(
vd
,
"Failed to reset device"
);
return
VLC_EGENERIC
;
}
sys
->
reset_device
=
false
;
}
else
if
(
sys
->
reopen_device
)
{
if
(
ControlReopenDevice
(
vd
))
{
msg_Err
(
vd
,
"Failed to reopen device"
);
return
VLC_EGENERIC
;
}
sys
->
reopen_device
=
false
;
}
return
VLC_SUCCESS
;
default:
return
CommonControl
(
vd
,
query
,
args
);
}
}
}
static
void
Manage
(
vout_display_t
*
vd
)
/*****************************************************************************
* 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
)
{
{
vout_sys_t
*
p_sys
=
p_vout
->
p_sys
;
vout_display_sys_t
*
sys
=
vd
->
sys
;
CommonManage
(
vd
);
CommonManage
(
p_vout
);
/* Desktop mode change */
vlc_mutex_lock
(
&
sys
->
lock
);
const
bool
ch_desktop
=
sys
->
ch_desktop
;
sys
->
ch_desktop
=
false
;
vlc_mutex_unlock
(
&
sys
->
lock
);
if
(
ch_desktop
)
{
sys
->
reopen_device
=
true
;
vout_display_SendEventPicturesInvalid
(
vd
);
}
#if 0
/*
/*
* Position Change
* Position Change
*/
*/
if
(
p_sys
->
i_
changes
&
DX_POSITION_CHANGE
)
{
if (
sys->
changes & DX_POSITION_CHANGE) {
#if 0 /* need that when bicubic filter is available */
#if 0 /* need that when bicubic filter is available */
RECT rect;
RECT rect;
UINT width, height;
UINT width, height;
...
@@ -300,139 +433,54 @@ static int Manage(vout_thread_t *p_vout)
...
@@ -300,139 +433,54 @@ static int Manage(vout_thread_t *p_vout)
if (width != p_sys->d3dpp.BackBufferWidth || height != p_sys->d3dpp.BackBufferHeight)
if (width != p_sys->d3dpp.BackBufferWidth || height != p_sys->d3dpp.BackBufferHeight)
{
{
msg_Dbg(
p_vout
, "resizing device back buffers to (%lux%lu)", width, height);
msg_Dbg(
vd
, "resizing device back buffers to (%lux%lu)", width, height);
// need to reset D3D device to resize back buffer
// need to reset D3D device to resize back buffer
if (VLC_SUCCESS != Direct3DResetDevice(
p_vout
, width, height))
if (VLC_SUCCESS != Direct3DResetDevice(
vd
, width, height))
return VLC_EGENERIC;
return VLC_EGENERIC;
}
}
#endif
#endif
p_sys
->
i_changes
&=
~
DX_POSITION_CHANGE
;
sys->changes &= ~DX_POSITION_CHANGE;
}
/*
* Desktop mode change
*/
if
(
p_sys
->
i_changes
&
DX_DESKTOP_CHANGE
)
{
/* Close the direct3d instance attached to the current output window. */
End
(
p_vout
);
ExitFullscreen
(
p_vout
);
EventThreadStop
(
p_sys
->
p_event
);
/* Open the direct3d output and attaches it to the new window */
p_sys
->
b_desktop
=
!
p_sys
->
b_desktop
;
p_vout
->
pf_display
=
FirstDisplay
;
event_cfg_t
cfg
;
memset
(
&
cfg
,
0
,
sizeof
(
cfg
));
cfg
.
use_desktop
=
p_sys
->
b_desktop
;
event_hwnd_t
hwnd
;
EventThreadStart
(
p_sys
->
p_event
,
&
hwnd
,
&
cfg
);
p_sys
->
parent_window
=
hwnd
.
parent_window
;
p_sys
->
hparent
=
hwnd
.
hparent
;
p_sys
->
hwnd
=
hwnd
.
hwnd
;
p_sys
->
hvideownd
=
hwnd
.
hvideownd
;
p_sys
->
hfswnd
=
hwnd
.
hfswnd
;
Init
(
p_vout
);
/* Reset the flag */
p_sys
->
i_changes
&=
~
DX_DESKTOP_CHANGE
;
}
}
#endif
return
VLC_SUCCESS
;
}
/*****************************************************************************
* Display: displays previously rendered output
*****************************************************************************
* This function sends the currently rendered image to the display, wait until
* it is displayed and switch the two rendering buffers, preparing next frame.
*****************************************************************************/
static
void
Display
(
vout_thread_t
*
p_vout
,
picture_t
*
p_pic
)
{
vout_sys_t
*
p_sys
=
p_vout
->
p_sys
;
LPDIRECT3DDEVICE9
p_d3ddev
=
p_sys
->
p_d3ddev
;
VLC_UNUSED
(
p_pic
);
// Present the back buffer contents to the display
// No stretching should happen here !
RECT
src
=
p_sys
->
rect_dest_clipped
;
RECT
dst
=
p_sys
->
rect_dest_clipped
;
HRESULT
hr
=
IDirect3DDevice9_Present
(
p_d3ddev
,
&
src
,
&
dst
,
NULL
,
NULL
);
if
(
FAILED
(
hr
))
msg_Dbg
(
p_vout
,
"%s:%d (hr=0x%0lX)"
,
__FUNCTION__
,
__LINE__
,
hr
);
}
/*
** this function is only used once when the first picture is received
** this function will show the video window once a picture is ready
*/
static
void
FirstDisplay
(
vout_thread_t
*
p_vout
,
picture_t
*
p_pic
)
{
/* get initial picture presented through D3D */
Display
(
p_vout
,
p_pic
);
/*
** Video window is initially hidden, show it now since we got a
** picture to show.
*/
SetWindowPos
(
p_vout
->
p_sys
->
hvideownd
,
0
,
0
,
0
,
0
,
0
,
SWP_ASYNCWINDOWPOS
|
SWP_FRAMECHANGED
|
SWP_SHOWWINDOW
|
SWP_NOMOVE
|
SWP_NOSIZE
|
SWP_NOZORDER
);
/* use and restores proper display function for further pictures */
p_vout
->
pf_display
=
Display
;
}
}
/*****************************************************************************
/**
* DirectD3DVoutCreate: Initialize and instance of Direct3D9
* It initializes an instance of Direct3D9
*****************************************************************************
*/
* This function initialize Direct3D and analyze available resources from
static
int
Direct3DCreate
(
vout_display_t
*
vd
)
* default adapter.
*****************************************************************************/
static
int
Direct3DCreate
(
vout_thread_t
*
p_vout
)
{
{
vout_
sys_t
*
p_sys
=
p_vout
->
p_
sys
;
vout_
display_sys_t
*
sys
=
vd
->
sys
;
p_
sys
->
hd3d9_dll
=
LoadLibrary
(
TEXT
(
"D3D9.DLL"
));
sys
->
hd3d9_dll
=
LoadLibrary
(
TEXT
(
"D3D9.DLL"
));
if
(
!
p_
sys
->
hd3d9_dll
)
{
if
(
!
sys
->
hd3d9_dll
)
{
msg_Warn
(
p_vout
,
"cannot load d3d9.dll, aborting"
);
msg_Warn
(
vd
,
"cannot load d3d9.dll, aborting"
);
return
VLC_EGENERIC
;
return
VLC_EGENERIC
;
}
}
LPDIRECT3D9
(
WINAPI
*
OurDirect3DCreate9
)(
UINT
SDKVersion
);
LPDIRECT3D9
(
WINAPI
*
OurDirect3DCreate9
)(
UINT
SDKVersion
);
OurDirect3DCreate9
=
OurDirect3DCreate9
=
(
void
*
)
GetProcAddress
(
p_
sys
->
hd3d9_dll
,
TEXT
(
"Direct3DCreate9"
));
(
void
*
)
GetProcAddress
(
sys
->
hd3d9_dll
,
TEXT
(
"Direct3DCreate9"
));
if
(
!
OurDirect3DCreate9
)
{
if
(
!
OurDirect3DCreate9
)
{
msg_Err
(
p_vout
,
"Cannot locate reference to Direct3DCreate9 ABI in DLL"
);
msg_Err
(
vd
,
"Cannot locate reference to Direct3DCreate9 ABI in DLL"
);
return
VLC_EGENERIC
;
return
VLC_EGENERIC
;
}
}
/* Create the D3D object. */
/* Create the D3D object. */
LPDIRECT3D9
p_
d3dobj
=
OurDirect3DCreate9
(
D3D_SDK_VERSION
);
LPDIRECT3D9
d3dobj
=
OurDirect3DCreate9
(
D3D_SDK_VERSION
);
if
(
!
p_
d3dobj
)
{
if
(
!
d3dobj
)
{
msg_Err
(
p_vout
,
"Could not create Direct3D9 instance."
);
msg_Err
(
vd
,
"Could not create Direct3D9 instance."
);
return
VLC_EGENERIC
;
return
VLC_EGENERIC
;
}
}
p_sys
->
p_d3dobj
=
p_
d3dobj
;
sys
->
d3dobj
=
d3dobj
;
/*
/*
** Get device capabilities
** Get device capabilities
*/
*/
D3DCAPS9
d3dCaps
;
D3DCAPS9
d3dCaps
;
ZeroMemory
(
&
d3dCaps
,
sizeof
(
d3dCaps
));
ZeroMemory
(
&
d3dCaps
,
sizeof
(
d3dCaps
));
HRESULT
hr
=
IDirect3D9_GetDeviceCaps
(
p_
d3dobj
,
D3DADAPTER_DEFAULT
,
D3DDEVTYPE_HAL
,
&
d3dCaps
);
HRESULT
hr
=
IDirect3D9_GetDeviceCaps
(
d3dobj
,
D3DADAPTER_DEFAULT
,
D3DDEVTYPE_HAL
,
&
d3dCaps
);
if
(
FAILED
(
hr
))
{
if
(
FAILED
(
hr
))
{
msg_Err
(
p_vout
,
"Could not read adapter capabilities. (hr=0x%lX)"
,
hr
);
msg_Err
(
vd
,
"Could not read adapter capabilities. (hr=0x%lX)"
,
hr
);
return
VLC_EGENERIC
;
return
VLC_EGENERIC
;
}
}
/* TODO: need to test device capabilities and select the right render function */
/* TODO: need to test device capabilities and select the right render function */
...
@@ -440,45 +488,49 @@ static int Direct3DCreate(vout_thread_t *p_vout)
...
@@ -440,45 +488,49 @@ static int Direct3DCreate(vout_thread_t *p_vout)
return
VLC_SUCCESS
;
return
VLC_SUCCESS
;
}
}
/**
***************************************************************************
/**
*
DirectD3DVoutRelease: release
an instance of Direct3D9
*
It releases
an instance of Direct3D9
*
****************************************************************************
/
*/
static
void
Direct3D
Release
(
vout_thread_t
*
p_vout
)
static
void
Direct3D
Destroy
(
vout_display_t
*
vd
)
{
{
vout_
sys_t
*
p_sys
=
p_vout
->
p_
sys
;
vout_
display_sys_t
*
sys
=
vd
->
sys
;
if
(
p_sys
->
p_
d3dobj
)
if
(
sys
->
d3dobj
)
IDirect3D9_Release
(
p_sys
->
p_
d3dobj
);
IDirect3D9_Release
(
sys
->
d3dobj
);
if
(
p_
sys
->
hd3d9_dll
)
if
(
sys
->
hd3d9_dll
)
FreeLibrary
(
p_
sys
->
hd3d9_dll
);
FreeLibrary
(
sys
->
hd3d9_dll
);
p_sys
->
p_
d3dobj
=
NULL
;
sys
->
d3dobj
=
NULL
;
p_
sys
->
hd3d9_dll
=
NULL
;
sys
->
hd3d9_dll
=
NULL
;
}
}
static
int
Direct3DFillPresentationParameters
(
vout_thread_t
*
p_vout
)
/**
* It setup vout_display_sys_t::d3dpp and vout_display_sys_t::rect_display
* from the default adapter.
*/
static
int
Direct3DFillPresentationParameters
(
vout_display_t
*
vd
)
{
{
vout_sys_t
*
p_sys
=
p_vout
->
p_sys
;
vout_display_sys_t
*
sys
=
vd
->
sys
;
LPDIRECT3D9
p_d3dobj
=
p_sys
->
p_d3dobj
;
D3DDISPLAYMODE
d3ddm
;
HRESULT
hr
;
/*
/*
** Get the current desktop display mode, so we can set up a back
** Get the current desktop display mode, so we can set up a back
** buffer of the same format
** buffer of the same format
*/
*/
hr
=
IDirect3D9_GetAdapterDisplayMode
(
p_d3dobj
,
D3DADAPTER_DEFAULT
,
&
d3ddm
);
D3DDISPLAYMODE
d3ddm
;
HRESULT
hr
=
IDirect3D9_GetAdapterDisplayMode
(
sys
->
d3dobj
,
D3DADAPTER_DEFAULT
,
&
d3ddm
);
if
(
FAILED
(
hr
))
{
if
(
FAILED
(
hr
))
{
msg_Err
(
p_vout
,
"Could not read adapter display mode. (hr=0x%lX)"
,
hr
);
msg_Err
(
vd
,
"Could not read adapter display mode. (hr=0x%lX)"
,
hr
);
return
VLC_EGENERIC
;
return
VLC_EGENERIC
;
}
}
/* Set up the structure used to create the D3DDevice. */
/* Set up the structure used to create the D3DDevice. */
D3DPRESENT_PARAMETERS
*
d3dpp
=
&
p_vout
->
p_
sys
->
d3dpp
;
D3DPRESENT_PARAMETERS
*
d3dpp
=
&
vd
->
sys
->
d3dpp
;
ZeroMemory
(
d3dpp
,
sizeof
(
D3DPRESENT_PARAMETERS
));
ZeroMemory
(
d3dpp
,
sizeof
(
D3DPRESENT_PARAMETERS
));
d3dpp
->
Flags
=
D3DPRESENTFLAG_VIDEO
;
d3dpp
->
Flags
=
D3DPRESENTFLAG_VIDEO
;
d3dpp
->
Windowed
=
TRUE
;
d3dpp
->
Windowed
=
TRUE
;
d3dpp
->
hDeviceWindow
=
p_vout
->
p_
sys
->
hvideownd
;
d3dpp
->
hDeviceWindow
=
vd
->
sys
->
hvideownd
;
d3dpp
->
BackBufferWidth
=
d3ddm
.
Width
;
d3dpp
->
BackBufferWidth
=
d3ddm
.
Width
;
d3dpp
->
BackBufferHeight
=
d3ddm
.
Height
;
d3dpp
->
BackBufferHeight
=
d3ddm
.
Height
;
d3dpp
->
SwapEffect
=
D3DSWAPEFFECT_COPY
;
d3dpp
->
SwapEffect
=
D3DSWAPEFFECT_COPY
;
...
@@ -488,17 +540,17 @@ static int Direct3DFillPresentationParameters(vout_thread_t *p_vout)
...
@@ -488,17 +540,17 @@ static int Direct3DFillPresentationParameters(vout_thread_t *p_vout)
d3dpp
->
BackBufferCount
=
1
;
d3dpp
->
BackBufferCount
=
1
;
d3dpp
->
EnableAutoDepthStencil
=
FALSE
;
d3dpp
->
EnableAutoDepthStencil
=
FALSE
;
const
unsigned
i_adapter_count
=
IDirect3D9_GetAdapterCount
(
p_d3dobj
);
const
unsigned
adapter_count
=
IDirect3D9_GetAdapterCount
(
sys
->
d3dobj
);
for
(
unsigned
i
=
1
;
i
<
i_adapter_count
;
i
++
)
for
(
unsigned
i
=
1
;
i
<
adapter_count
;
i
++
)
{
{
hr
=
IDirect3D9_GetAdapterDisplayMode
(
sys
->
d3dobj
,
i
,
&
d3ddm
);
hr
=
IDirect3D9_GetAdapterDisplayMode
(
p_d3dobj
,
i
,
&
d3ddm
);
if
(
FAILED
(
hr
))
if
(
FAILED
(
hr
)
)
continue
;
continue
;
d3dpp
->
BackBufferWidth
=
__MAX
(
d3dpp
->
BackBufferWidth
,
d3ddm
.
Width
);
d3dpp
->
BackBufferWidth
=
__MAX
(
d3dpp
->
BackBufferWidth
,
d3ddm
.
Width
);
d3dpp
->
BackBufferHeight
=
__MAX
(
d3dpp
->
BackBufferHeight
,
d3ddm
.
Height
);
d3dpp
->
BackBufferHeight
=
__MAX
(
d3dpp
->
BackBufferHeight
,
d3ddm
.
Height
);
}
}
RECT
*
display
=
&
p_vout
->
p_sys
->
rect_display
;
/* */
RECT
*
display
=
&
vd
->
sys
->
rect_display
;
display
->
left
=
0
;
display
->
left
=
0
;
display
->
top
=
0
;
display
->
top
=
0
;
display
->
right
=
d3dpp
->
BackBufferWidth
;
display
->
right
=
d3dpp
->
BackBufferWidth
;
...
@@ -507,108 +559,152 @@ static int Direct3DFillPresentationParameters(vout_thread_t *p_vout)
...
@@ -507,108 +559,152 @@ static int Direct3DFillPresentationParameters(vout_thread_t *p_vout)
return
VLC_SUCCESS
;
return
VLC_SUCCESS
;
}
}
/*
****************************************************************************
/*
*/
* DirectD3DVoutOpen: Takes care of all the Direct3D9 initialisations
static
int
Direct3DCreateResources
(
vout_display_t
*
,
video_format_t
*
);
*****************************************************************************
static
void
Direct3DDestroyResources
(
vout_display_t
*
);
* This function creates Direct3D device
* this must be called from the vout thread for performance reason, as
/**
*
all Direct3D Device APIs are used in a non multithread safe environment
*
It creates a Direct3D device and the associated resources.
*
****************************************************************************
/
*/
static
int
Direct3DOpen
(
vout_
thread_t
*
p_vou
t
)
static
int
Direct3DOpen
(
vout_
display_t
*
vd
,
video_format_t
*
fm
t
)
{
{
vout_sys_t
*
p_sys
=
p_vout
->
p_sys
;
vout_display_sys_t
*
sys
=
vd
->
sys
;
LPDIRECT3D9
p_d3dobj
=
p_sys
->
p_d3dobj
;
LPDIRECT3D9
d3dobj
=
sys
->
d3dobj
;
LPDIRECT3DDEVICE9
p_d3ddev
;
HRESULT
hr
;
if
(
Direct3DFillPresentationParameters
(
p_vout
))
if
(
Direct3DFillPresentationParameters
(
vd
))
return
VLC_EGENERIC
;
return
VLC_EGENERIC
;
// Create the D3DDevice
// Create the D3DDevice
hr
=
IDirect3D9_CreateDevice
(
p_d3dobj
,
D3DADAPTER_DEFAULT
,
LPDIRECT3DDEVICE9
d3ddev
;
D3DDEVTYPE_HAL
,
p_sys
->
hvideownd
,
HRESULT
hr
=
IDirect3D9_CreateDevice
(
d3dobj
,
D3DADAPTER_DEFAULT
,
D3DCREATE_SOFTWARE_VERTEXPROCESSING
|
D3DDEVTYPE_HAL
,
sys
->
hvideownd
,
D3DCREATE_MULTITHREADED
,
D3DCREATE_SOFTWARE_VERTEXPROCESSING
|
&
p_sys
->
d3dpp
,
&
p_d3ddev
);
D3DCREATE_MULTITHREADED
,
&
sys
->
d3dpp
,
&
d3ddev
);
if
(
FAILED
(
hr
))
{
if
(
FAILED
(
hr
))
{
msg_Err
(
p_vout
,
"Could not create the D3D device! (hr=0x%lX)"
,
hr
);
msg_Err
(
vd
,
"Could not create the D3D device! (hr=0x%lX)"
,
hr
);
return
VLC_EGENERIC
;
return
VLC_EGENERIC
;
}
}
p_sys
->
p_d3ddev
=
p_d3ddev
;
sys
->
d3ddev
=
d3ddev
;
UpdateRects
(
vd
,
NULL
,
NULL
,
true
);
msg_Dbg
(
p_vout
,
"Direct3D device adapter successfully initialized"
);
if
(
Direct3DCreateResources
(
vd
,
fmt
))
{
msg_Err
(
vd
,
"Failed to allocate resources"
);
return
VLC_EGENERIC
;
}
/* Change the window title bar text */
EventThreadUpdateTitle
(
sys
->
event
,
VOUT_TITLE
" (Direct3D output)"
);
msg_Dbg
(
vd
,
"Direct3D device adapter successfully initialized"
);
return
VLC_SUCCESS
;
return
VLC_SUCCESS
;
}
}
/**
***************************************************************************
/**
*
DirectD3DClose: release the Direct3D9 device
*
It releases the Direct3D9 device and its resources.
*
****************************************************************************
/
*/
static
void
Direct3DClose
(
vout_
thread_t
*
p_vout
)
static
void
Direct3DClose
(
vout_
display_t
*
vd
)
{
{
vout_sys_t
*
p_sys
=
p_vout
->
p_sys
;
vout_display_sys_t
*
sys
=
vd
->
sys
;
Direct3DDestroyResources
(
vd
);
if
(
p_sys
->
p_
d3ddev
)
if
(
sys
->
d3ddev
)
IDirect3DDevice9_Release
(
p_sys
->
p_
d3ddev
);
IDirect3DDevice9_Release
(
sys
->
d3ddev
);
p_sys
->
p_
d3ddev
=
NULL
;
sys
->
d3ddev
=
NULL
;
p_
sys
->
hmonitor
=
NULL
;
sys
->
hmonitor
=
NULL
;
}
}
/*****************************************************************************
/**
* DirectD3DClose: reset the Direct3D9 device
* It reset the Direct3D9 device and its resources.
*****************************************************************************
*/
* All resources must be deallocated before the reset occur, they will be
static
int
Direct3DReset
(
vout_display_t
*
vd
)
* realllocated once the reset has been performed successfully
*****************************************************************************/
static
int
Direct3DResetDevice
(
vout_thread_t
*
p_vout
)
{
{
vout_sys_t
*
p_sys
=
p_vout
->
p_sys
;
vout_display_sys_t
*
sys
=
vd
->
sys
;
LPDIRECT3DDEVICE9
p_d3ddev
=
p_sys
->
p_d3ddev
;
LPDIRECT3DDEVICE9
d3ddev
=
sys
->
d3ddev
;
HRESULT
hr
;
if
(
Direct3DFillPresentationParameters
(
p_vout
))
if
(
Direct3DFillPresentationParameters
(
vd
))
return
VLC_EGENERIC
;
return
VLC_EGENERIC
;
// release all D3D objects
/* release all D3D objects */
Direct3DReleaseScene
(
p_vout
);
Direct3DDestroyResources
(
vd
);
Direct3DReleasePictures
(
p_vout
);
hr
=
IDirect3DDevice9_Reset
(
p_d3ddev
,
&
p_sys
->
d3dpp
);
/* */
HRESULT
hr
=
IDirect3DDevice9_Reset
(
d3ddev
,
&
sys
->
d3dpp
);
if
(
FAILED
(
hr
))
{
if
(
FAILED
(
hr
))
{
msg_Err
(
p_vout
,
"%s failed ! (hr=%08lX)"
,
__FUNCTION__
,
hr
);
msg_Err
(
vd
,
"%s failed ! (hr=%08lX)"
,
__FUNCTION__
,
hr
);
return
VLC_EGENERIC
;
}
UpdateRects
(
vd
,
NULL
,
NULL
,
true
);
/* re-create them */
if
(
Direct3DCreateResources
(
vd
,
&
vd
->
fmt
))
{
msg_Dbg
(
vd
,
"%s failed !"
,
__FUNCTION__
);
return
VLC_EGENERIC
;
}
return
VLC_SUCCESS
;
}
/* */
static
int
Direct3DCreatePool
(
vout_display_t
*
vd
,
video_format_t
*
fmt
);
static
void
Direct3DDestroyPool
(
vout_display_t
*
vd
);
static
int
Direct3DCreateScene
(
vout_display_t
*
vd
);
static
void
Direct3DDestroyScene
(
vout_display_t
*
vd
);
/**
* It creates the picture and scene resources.
*/
static
int
Direct3DCreateResources
(
vout_display_t
*
vd
,
video_format_t
*
fmt
)
{
if
(
Direct3DCreatePool
(
vd
,
fmt
))
{
msg_Err
(
vd
,
"Direct3D picture pool initialization failed"
);
return
VLC_EGENERIC
;
return
VLC_EGENERIC
;
}
}
// re-create them
if
(
Direct3DCreateScene
(
vd
))
{
if
(
Direct3DCreatePictures
(
p_vout
,
1
)
||
Direct3DCreateScene
(
p_vout
))
{
msg_Err
(
vd
,
"Direct3D scene initialization failed !"
);
msg_Dbg
(
p_vout
,
"%s failed !"
,
__FUNCTION__
);
return
VLC_EGENERIC
;
return
VLC_EGENERIC
;
}
}
return
VLC_SUCCESS
;
return
VLC_SUCCESS
;
}
}
/**
* It destroys the picture and scene resources.
*/
static
void
Direct3DDestroyResources
(
vout_display_t
*
vd
)
{
Direct3DDestroyScene
(
vd
);
Direct3DDestroyPool
(
vd
);
}
static
int
Direct3DCheckFormat
(
vout_thread_t
*
p_vout
,
/**
D3DFORMAT
target
,
D3DFORMAT
format
)
* It tests if the conversion from src to dst is supported.
*/
static
int
Direct3DCheckConversion
(
vout_display_t
*
vd
,
D3DFORMAT
src
,
D3DFORMAT
dst
)
{
{
vout_
sys_t
*
p_sys
=
p_vout
->
p_
sys
;
vout_
display_sys_t
*
sys
=
vd
->
sys
;
LPDIRECT3D9
p_d3dobj
=
p_sys
->
p_
d3dobj
;
LPDIRECT3D9
d3dobj
=
sys
->
d3dobj
;
HRESULT
hr
;
HRESULT
hr
;
/* test whether device can create a surface of that format */
/* test whether device can create a surface of that format */
hr
=
IDirect3D9_CheckDeviceFormat
(
p_
d3dobj
,
D3DADAPTER_DEFAULT
,
hr
=
IDirect3D9_CheckDeviceFormat
(
d3dobj
,
D3DADAPTER_DEFAULT
,
D3DDEVTYPE_HAL
,
targe
t
,
0
,
D3DDEVTYPE_HAL
,
ds
t
,
0
,
D3DRTYPE_SURFACE
,
format
);
D3DRTYPE_SURFACE
,
src
);
if
(
SUCCEEDED
(
hr
))
{
if
(
SUCCEEDED
(
hr
))
{
/* test whether device can perform color-conversion
/* test whether device can perform color-conversion
** from that format to target format
** from that format to target format
*/
*/
hr
=
IDirect3D9_CheckDeviceFormatConversion
(
p_
d3dobj
,
hr
=
IDirect3D9_CheckDeviceFormatConversion
(
d3dobj
,
D3DADAPTER_DEFAULT
,
D3DADAPTER_DEFAULT
,
D3DDEVTYPE_HAL
,
D3DDEVTYPE_HAL
,
format
,
targe
t
);
src
,
ds
t
);
}
}
if
(
!
SUCCEEDED
(
hr
))
{
if
(
!
SUCCEEDED
(
hr
))
{
if
(
D3DERR_NOTAVAILABLE
!=
hr
)
if
(
D3DERR_NOTAVAILABLE
!=
hr
)
msg_Err
(
p_vout
,
"Could not query adapter supported formats. (hr=0x%lX)"
,
hr
);
msg_Err
(
vd
,
"Could not query adapter supported formats. (hr=0x%lX)"
,
hr
);
return
VLC_EGENERIC
;
return
VLC_EGENERIC
;
}
}
return
VLC_SUCCESS
;
return
VLC_SUCCESS
;
...
@@ -617,14 +713,14 @@ static int Direct3DCheckFormat(vout_thread_t *p_vout,
...
@@ -617,14 +713,14 @@ static int Direct3DCheckFormat(vout_thread_t *p_vout,
typedef
struct
typedef
struct
{
{
const
char
*
name
;
const
char
*
name
;
D3DFORMAT
format
;
D3DFORMAT
format
;
/* D3D format */
vlc_fourcc_t
fourcc
;
vlc_fourcc_t
fourcc
;
/* VLC fourcc */
uint32_t
rmask
;
uint32_t
rmask
;
uint32_t
gmask
;
uint32_t
gmask
;
uint32_t
bmask
;
uint32_t
bmask
;
}
d3d_format_t
;
}
d3d_format_t
;
static
const
d3d_format_t
p_
d3d_formats
[]
=
{
static
const
d3d_format_t
d3d_formats
[]
=
{
/* YV12 is always used for planar 420, the planes are then swapped in Lock() */
/* YV12 is always used for planar 420, the planes are then swapped in Lock() */
{
"YV12"
,
MAKEFOURCC
(
'Y'
,
'V'
,
'1'
,
'2'
),
VLC_CODEC_YV12
,
0
,
0
,
0
},
{
"YV12"
,
MAKEFOURCC
(
'Y'
,
'V'
,
'1'
,
'2'
),
VLC_CODEC_YV12
,
0
,
0
,
0
},
{
"YV12"
,
MAKEFOURCC
(
'Y'
,
'V'
,
'1'
,
'2'
),
VLC_CODEC_I420
,
0
,
0
,
0
},
{
"YV12"
,
MAKEFOURCC
(
'Y'
,
'V'
,
'1'
,
'2'
),
VLC_CODEC_I420
,
0
,
0
,
0
},
...
@@ -640,33 +736,35 @@ static const d3d_format_t p_d3d_formats[] = {
...
@@ -640,33 +736,35 @@ static const d3d_format_t p_d3d_formats[] = {
{
NULL
,
0
,
0
,
0
,
0
,
0
}
{
NULL
,
0
,
0
,
0
,
0
,
0
}
};
};
static
const
d3d_format_t
*
Direct3DFindFormat
(
vout_thread_t
*
p_vout
,
vlc_fourcc_t
i_chroma
,
D3DFORMAT
target
)
/**
* It returns the format (closest to chroma) that can be converted to target */
static
const
d3d_format_t
*
Direct3DFindFormat
(
vout_display_t
*
vd
,
vlc_fourcc_t
chroma
,
D3DFORMAT
target
)
{
{
vout_
sys_t
*
p_sys
=
p_vout
->
p_
sys
;
vout_
display_sys_t
*
sys
=
vd
->
sys
;
for
(
unsigned
pass
=
0
;
pass
<
2
;
pass
++
)
{
for
(
unsigned
pass
=
0
;
pass
<
2
;
pass
++
)
{
const
vlc_fourcc_t
*
p_chromas
;
const
vlc_fourcc_t
*
list
;
if
(
pass
==
0
&&
p_sys
->
b_hw_yuv
&&
vlc_fourcc_IsYUV
(
i_
chroma
))
if
(
pass
==
0
&&
sys
->
allow_hw_yuv
&&
vlc_fourcc_IsYUV
(
chroma
))
p_chromas
=
vlc_fourcc_GetYUVFallback
(
i_
chroma
);
list
=
vlc_fourcc_GetYUVFallback
(
chroma
);
else
if
(
pass
==
1
)
else
if
(
pass
==
1
)
p_chromas
=
vlc_fourcc_GetRGBFallback
(
i_
chroma
);
list
=
vlc_fourcc_GetRGBFallback
(
chroma
);
else
else
continue
;
continue
;
for
(
unsigned
i
=
0
;
p_chromas
[
i
]
!=
0
;
i
++
)
{
for
(
unsigned
i
=
0
;
list
[
i
]
!=
0
;
i
++
)
{
for
(
unsigned
j
=
0
;
p_
d3d_formats
[
j
].
name
;
j
++
)
{
for
(
unsigned
j
=
0
;
d3d_formats
[
j
].
name
;
j
++
)
{
const
d3d_format_t
*
p_format
=
&
p_
d3d_formats
[
j
];
const
d3d_format_t
*
format
=
&
d3d_formats
[
j
];
if
(
p_format
->
fourcc
!=
p_chromas
[
i
])
if
(
format
->
fourcc
!=
list
[
i
])
continue
;
continue
;
msg_Warn
(
p_vout
,
"trying surface pixel format: %s"
,
msg_Warn
(
vd
,
"trying surface pixel format: %s"
,
p_
format
->
name
);
format
->
name
);
if
(
!
Direct3DCheck
Format
(
p_vout
,
target
,
p_format
->
forma
t
))
{
if
(
!
Direct3DCheck
Conversion
(
vd
,
format
->
format
,
targe
t
))
{
msg_Dbg
(
p_vout
,
"selected surface pixel format is %s"
,
msg_Dbg
(
vd
,
"selected surface pixel format is %s"
,
p_
format
->
name
);
format
->
name
);
return
p_
format
;
return
format
;
}
}
}
}
}
}
...
@@ -674,474 +772,402 @@ static const d3d_format_t *Direct3DFindFormat(vout_thread_t *p_vout, vlc_fourcc_
...
@@ -674,474 +772,402 @@ static const d3d_format_t *Direct3DFindFormat(vout_thread_t *p_vout, vlc_fourcc_
return
NULL
;
return
NULL
;
}
}
/*****************************************************************************
/**
* Direct3DCreatePictures: allocate a vector of identical pictures
* It locks the surface associated to the picture and get the surface
*****************************************************************************
* descriptor which amongst other things has the pointer to the picture
* Each picture has an associated offscreen surface in video memory
* data and its pitch.
* depending on hardware capabilities the picture chroma will be as close
*/
* as possible to the orginal render chroma to reduce CPU conversion overhead
static
int
Direct3DLockSurface
(
picture_t
*
picture
)
* and delegate this work to video card GPU
*****************************************************************************/
static
int
Direct3DCreatePictures
(
vout_thread_t
*
p_vout
,
size_t
i_num_pics
)
{
vout_sys_t
*
p_sys
=
p_vout
->
p_sys
;
LPDIRECT3DDEVICE9
p_d3ddev
=
p_sys
->
p_d3ddev
;
HRESULT
hr
;
size_t
c
;
// if vout is already running, use current chroma, otherwise choose from upstream
vlc_fourcc_t
i_chroma
=
p_vout
->
output
.
i_chroma
?
p_vout
->
output
.
i_chroma
:
p_vout
->
render
.
i_chroma
;
I_OUTPUTPICTURES
=
0
;
/*
** find the appropriate D3DFORMAT for the render chroma, the format will be the closest to
** the requested chroma which is usable by the hardware in an offscreen surface, as they
** typically support more formats than textures
*/
const
d3d_format_t
*
p_format
=
Direct3DFindFormat
(
p_vout
,
i_chroma
,
p_sys
->
d3dpp
.
BackBufferFormat
);
if
(
!
p_format
)
{
msg_Err
(
p_vout
,
"surface pixel format is not supported."
);
return
VLC_EGENERIC
;
}
p_vout
->
output
.
i_chroma
=
p_format
->
fourcc
;
p_vout
->
output
.
i_rmask
=
p_format
->
rmask
;
p_vout
->
output
.
i_gmask
=
p_format
->
gmask
;
p_vout
->
output
.
i_bmask
=
p_format
->
bmask
;
/* */
for
(
c
=
0
;
c
<
i_num_pics
;)
{
LPDIRECT3DSURFACE9
p_d3dsurf
;
picture_t
*
p_pic
=
p_vout
->
p_picture
+
c
;
hr
=
IDirect3DDevice9_CreateOffscreenPlainSurface
(
p_d3ddev
,
p_vout
->
render
.
i_width
,
p_vout
->
render
.
i_height
,
p_format
->
format
,
D3DPOOL_DEFAULT
,
&
p_d3dsurf
,
NULL
);
if
(
FAILED
(
hr
))
{
msg_Err
(
p_vout
,
"Failed to create picture surface. (hr=0x%lx)"
,
hr
);
Direct3DReleasePictures
(
p_vout
);
return
VLC_EGENERIC
;
}
/* fill surface with black color */
IDirect3DDevice9_ColorFill
(
p_d3ddev
,
p_d3dsurf
,
NULL
,
D3DCOLOR_ARGB
(
0xFF
,
0
,
0
,
0
));
/* */
video_format_Setup
(
&
p_pic
->
format
,
p_vout
->
output
.
i_chroma
,
p_vout
->
output
.
i_width
,
p_vout
->
output
.
i_height
,
p_vout
->
output
.
i_aspect
);
/* assign surface to internal structure */
p_pic
->
p_sys
=
(
void
*
)
p_d3dsurf
;
/* Now that we've got our direct-buffer, we can finish filling in the
* picture_t structures */
switch
(
p_vout
->
output
.
i_chroma
)
{
case
VLC_CODEC_RGB8
:
p_pic
->
p
->
i_lines
=
p_vout
->
output
.
i_height
;
p_pic
->
p
->
i_visible_lines
=
p_vout
->
output
.
i_height
;
p_pic
->
p
->
i_pixel_pitch
=
1
;
p_pic
->
p
->
i_visible_pitch
=
p_vout
->
output
.
i_width
*
p_pic
->
p
->
i_pixel_pitch
;
p_pic
->
i_planes
=
1
;
break
;
case
VLC_CODEC_RGB15
:
case
VLC_CODEC_RGB16
:
p_pic
->
p
->
i_lines
=
p_vout
->
output
.
i_height
;
p_pic
->
p
->
i_visible_lines
=
p_vout
->
output
.
i_height
;
p_pic
->
p
->
i_pixel_pitch
=
2
;
p_pic
->
p
->
i_visible_pitch
=
p_vout
->
output
.
i_width
*
p_pic
->
p
->
i_pixel_pitch
;
p_pic
->
i_planes
=
1
;
break
;
case
VLC_CODEC_RGB24
:
p_pic
->
p
->
i_lines
=
p_vout
->
output
.
i_height
;
p_pic
->
p
->
i_visible_lines
=
p_vout
->
output
.
i_height
;
p_pic
->
p
->
i_pixel_pitch
=
3
;
p_pic
->
p
->
i_visible_pitch
=
p_vout
->
output
.
i_width
*
p_pic
->
p
->
i_pixel_pitch
;
p_pic
->
i_planes
=
1
;
break
;
case
VLC_CODEC_RGB32
:
p_pic
->
p
->
i_lines
=
p_vout
->
output
.
i_height
;
p_pic
->
p
->
i_visible_lines
=
p_vout
->
output
.
i_height
;
p_pic
->
p
->
i_pixel_pitch
=
4
;
p_pic
->
p
->
i_visible_pitch
=
p_vout
->
output
.
i_width
*
p_pic
->
p
->
i_pixel_pitch
;
p_pic
->
i_planes
=
1
;
break
;
case
VLC_CODEC_UYVY
:
case
VLC_CODEC_YUYV
:
p_pic
->
p
->
i_lines
=
p_vout
->
output
.
i_height
;
p_pic
->
p
->
i_visible_lines
=
p_vout
->
output
.
i_height
;
p_pic
->
p
->
i_pixel_pitch
=
2
;
p_pic
->
p
->
i_visible_pitch
=
p_vout
->
output
.
i_width
*
p_pic
->
p
->
i_pixel_pitch
;
p_pic
->
i_planes
=
1
;
break
;
case
VLC_CODEC_I420
:
case
VLC_CODEC_J420
:
case
VLC_CODEC_YV12
:
p_pic
->
i_planes
=
3
;
for
(
int
n
=
0
;
n
<
p_pic
->
i_planes
;
n
++
)
{
const
unsigned
d
=
1
+
(
n
>
0
);
plane_t
*
p
=
&
p_pic
->
p
[
n
];
p
->
i_pixel_pitch
=
1
;
p
->
i_lines
=
p
->
i_visible_lines
=
p_vout
->
output
.
i_height
/
d
;
p
->
i_visible_pitch
=
p_vout
->
output
.
i_width
/
d
;
}
break
;
default:
Direct3DReleasePictures
(
p_vout
);
return
VLC_EGENERIC
;
}
p_pic
->
i_status
=
DESTROYED_PICTURE
;
p_pic
->
i_type
=
DIRECT_PICTURE
;
p_pic
->
b_slow
=
true
;
p_pic
->
pf_lock
=
Direct3DLockSurface
;
p_pic
->
pf_unlock
=
Direct3DUnlockSurface
;
PP_OUTPUTPICTURE
[
c
]
=
p_pic
;
I_OUTPUTPICTURES
=
++
c
;
}
msg_Dbg
(
p_vout
,
"%u Direct3D pictures created successfully"
,
c
);
return
VLC_SUCCESS
;
}
/*****************************************************************************
* Direct3DReleasePictures: destroy a picture vector
*****************************************************************************
* release all video resources used for pictures
*****************************************************************************/
static
void
Direct3DReleasePictures
(
vout_thread_t
*
p_vout
)
{
size_t
i_num_pics
=
I_OUTPUTPICTURES
;
size_t
c
;
for
(
c
=
0
;
c
<
i_num_pics
;
c
++
)
{
picture_t
*
p_pic
=
&
p_vout
->
p_picture
[
c
];
if
(
!
p_pic
->
p_sys
)
continue
;
LPDIRECT3DSURFACE9
p_d3dsurf
=
(
LPDIRECT3DSURFACE9
)
p_pic
->
p_sys
;
if
(
p_d3dsurf
)
IDirect3DSurface9_Release
(
p_d3dsurf
);
p_pic
->
p_sys
=
NULL
;
}
msg_Dbg
(
p_vout
,
"%u Direct3D pictures released."
,
c
);
I_OUTPUTPICTURES
=
0
;
}
/*****************************************************************************
* Direct3DLockSurface: Lock surface and get picture data pointer
*****************************************************************************
* This function locks a surface and get the surface descriptor which amongst
* other things has the pointer to the picture data.
*****************************************************************************/
static
int
Direct3DLockSurface
(
vout_thread_t
*
p_vout
,
picture_t
*
p_pic
)
{
{
LPDIRECT3DSURFACE9
p_d3dsurf
=
(
LPDIRECT3DSURFACE9
)
p_pic
->
p_sys
;
if
(
!
p_d3dsurf
)
return
VLC_EGENERIC
;
/* Lock the surface to get a valid pointer to the picture buffer */
/* Lock the surface to get a valid pointer to the picture buffer */
D3DLOCKED_RECT
d3drect
;
D3DLOCKED_RECT
d3drect
;
HRESULT
hr
=
IDirect3DSurface9_LockRect
(
p
_d3dsurf
,
&
d3drect
,
NULL
,
0
);
HRESULT
hr
=
IDirect3DSurface9_LockRect
(
p
icture
->
p_sys
->
surface
,
&
d3drect
,
NULL
,
0
);
if
(
FAILED
(
hr
))
{
if
(
FAILED
(
hr
))
{
msg_Dbg
(
p_vout
,
"%s:%d (hr=0x%0lX)"
,
__FUNCTION__
,
__LINE__
,
hr
);
//msg_Dbg(vd
, "%s:%d (hr=0x%0lX)", __FUNCTION__, __LINE__, hr);
return
VLC_EGENERIC
;
return
VLC_EGENERIC
;
}
}
/* fill in buffer info in first plane */
/* fill in buffer info in first plane */
p
_pic
->
p
->
p_pixels
=
d3drect
.
pBits
;
p
icture
->
p
->
p_pixels
=
d3drect
.
pBits
;
p
_pic
->
p
->
i_pitch
=
d3drect
.
Pitch
;
p
icture
->
p
->
i_pitch
=
d3drect
.
Pitch
;
/* Fill chroma planes for planar YUV */
/* Fill chroma planes for planar YUV */
if
(
p
_pic
->
format
.
i_chroma
==
VLC_CODEC_I420
||
if
(
p
icture
->
format
.
i_chroma
==
VLC_CODEC_I420
||
p
_pic
->
format
.
i_chroma
==
VLC_CODEC_J420
||
p
icture
->
format
.
i_chroma
==
VLC_CODEC_J420
||
p
_pic
->
format
.
i_chroma
==
VLC_CODEC_YV12
)
{
p
icture
->
format
.
i_chroma
==
VLC_CODEC_YV12
)
{
for
(
int
n
=
1
;
n
<
p
_pic
->
i_planes
;
n
++
)
{
for
(
int
n
=
1
;
n
<
p
icture
->
i_planes
;
n
++
)
{
const
plane_t
*
o
=
&
p
_pic
->
p
[
n
-
1
];
const
plane_t
*
o
=
&
p
icture
->
p
[
n
-
1
];
plane_t
*
p
=
&
p
_pic
->
p
[
n
];
plane_t
*
p
=
&
p
icture
->
p
[
n
];
p
->
p_pixels
=
o
->
p_pixels
+
o
->
i_lines
*
o
->
i_pitch
;
p
->
p_pixels
=
o
->
p_pixels
+
o
->
i_lines
*
o
->
i_pitch
;
p
->
i_pitch
=
d3drect
.
Pitch
/
2
;
p
->
i_pitch
=
d3drect
.
Pitch
/
2
;
}
}
/* The d3d buffer is always allocated as YV12 */
/* The d3d buffer is always allocated as YV12 */
if
(
vlc_fourcc_AreUVPlanesSwapped
(
p
_pic
->
format
.
i_chroma
,
VLC_CODEC_YV12
))
{
if
(
vlc_fourcc_AreUVPlanesSwapped
(
p
icture
->
format
.
i_chroma
,
VLC_CODEC_YV12
))
{
uint8_t
*
p_tmp
=
p
_pic
->
p
[
1
].
p_pixels
;
uint8_t
*
p_tmp
=
p
icture
->
p
[
1
].
p_pixels
;
p
_pic
->
p
[
1
].
p_pixels
=
p_pic
->
p
[
2
].
p_pixels
;
p
icture
->
p
[
1
].
p_pixels
=
picture
->
p
[
2
].
p_pixels
;
p
_pic
->
p
[
2
].
p_pixels
=
p_tmp
;
p
icture
->
p
[
2
].
p_pixels
=
p_tmp
;
}
}
}
}
return
VLC_SUCCESS
;
return
VLC_SUCCESS
;
}
}
/**
* It unlocks the surface associated to the picture.
*/
static
void
Direct3DUnlockSurface
(
picture_t
*
picture
)
{
/* Unlock the Surface */
HRESULT
hr
=
IDirect3DSurface9_UnlockRect
(
picture
->
p_sys
->
surface
);
if
(
FAILED
(
hr
))
{
//msg_Dbg(vd, "%s:%d (hr=0x%0lX)", __FUNCTION__, __LINE__, hr);
}
}
/*****************************************************************************
/**
* Direct3DUnlockSurface: Unlock a surface locked by Direct3DLockSurface().
* It creates the pool of picture (only 1).
*****************************************************************************/
*
static
int
Direct3DUnlockSurface
(
vout_thread_t
*
p_vout
,
picture_t
*
p_pic
)
* Each picture has an associated offscreen surface in video memory
* depending on hardware capabilities the picture chroma will be as close
* as possible to the orginal render chroma to reduce CPU conversion overhead
* and delegate this work to video card GPU
*/
static
int
Direct3DCreatePool
(
vout_display_t
*
vd
,
video_format_t
*
fmt
)
{
{
LPDIRECT3DSURFACE9
p_d3dsurf
=
(
LPDIRECT3DSURFACE9
)
p_pic
->
p_sys
;
vout_display_sys_t
*
sys
=
vd
->
sys
;
LPDIRECT3DDEVICE9
d3ddev
=
sys
->
d3ddev
;
if
(
!
p_d3dsurf
)
/* */
*
fmt
=
vd
->
source
;
/* Find the appropriate D3DFORMAT for the render chroma, the format will be the closest to
* the requested chroma which is usable by the hardware in an offscreen surface, as they
* typically support more formats than textures */
const
d3d_format_t
*
d3dfmt
=
Direct3DFindFormat
(
vd
,
fmt
->
i_chroma
,
sys
->
d3dpp
.
BackBufferFormat
);
if
(
!
d3dfmt
)
{
msg_Err
(
vd
,
"surface pixel format is not supported."
);
return
VLC_EGENERIC
;
return
VLC_EGENERIC
;
}
/* Unlock the Surface */
fmt
->
i_chroma
=
d3dfmt
->
fourcc
;
HRESULT
hr
=
IDirect3DSurface9_UnlockRect
(
p_d3dsurf
);
fmt
->
i_rmask
=
d3dfmt
->
rmask
;
fmt
->
i_gmask
=
d3dfmt
->
gmask
;
fmt
->
i_bmask
=
d3dfmt
->
bmask
;
/* We create one picture.
* It is useless to create more as we can't be used for direct rendering */
/* Create a surface */
LPDIRECT3DSURFACE9
surface
;
HRESULT
hr
=
IDirect3DDevice9_CreateOffscreenPlainSurface
(
d3ddev
,
fmt
->
i_width
,
fmt
->
i_height
,
d3dfmt
->
format
,
D3DPOOL_DEFAULT
,
&
surface
,
NULL
);
if
(
FAILED
(
hr
))
{
if
(
FAILED
(
hr
))
{
msg_
Dbg
(
p_vout
,
"%s:%d (hr=0x%0lX)"
,
__FUNCTION__
,
__LINE__
,
hr
);
msg_
Err
(
vd
,
"Failed to create picture surface. (hr=0x%lx)"
,
hr
);
return
VLC_EGENERIC
;
return
VLC_EGENERIC
;
}
}
/* fill surface with black color */
IDirect3DDevice9_ColorFill
(
d3ddev
,
surface
,
NULL
,
D3DCOLOR_ARGB
(
0xFF
,
0
,
0
,
0
));
/* Create the associated picture */
picture_resource_t
*
rsc
=
&
sys
->
resource
;
rsc
->
p_sys
=
malloc
(
sizeof
(
*
rsc
->
p_sys
));
if
(
!
rsc
->
p_sys
)
{
IDirect3DSurface9_Release
(
surface
);
return
VLC_ENOMEM
;
}
rsc
->
p_sys
->
surface
=
surface
;
for
(
int
i
=
0
;
i
<
PICTURE_PLANE_MAX
;
i
++
)
{
rsc
->
p
[
i
].
p_pixels
=
NULL
;
rsc
->
p
[
i
].
i_pitch
=
0
;
rsc
->
p
[
i
].
i_lines
=
fmt
->
i_height
/
(
i
>
0
?
2
:
1
);
}
picture_t
*
picture
=
picture_NewFromResource
(
fmt
,
rsc
);
if
(
!
picture
)
{
IDirect3DSurface9_Release
(
surface
);
free
(
rsc
->
p_sys
);
return
VLC_ENOMEM
;
}
/* Wrap it into a picture pool */
picture_pool_configuration_t
pool_cfg
;
memset
(
&
pool_cfg
,
0
,
sizeof
(
pool_cfg
));
pool_cfg
.
picture_count
=
1
;
pool_cfg
.
picture
=
&
picture
;
pool_cfg
.
lock
=
Direct3DLockSurface
;
pool_cfg
.
unlock
=
Direct3DUnlockSurface
;
sys
->
pool
=
picture_pool_NewExtended
(
&
pool_cfg
);
if
(
!
sys
->
pool
)
{
picture_Release
(
picture
);
IDirect3DSurface9_Release
(
surface
);
return
VLC_ENOMEM
;
}
return
VLC_SUCCESS
;
return
VLC_SUCCESS
;
}
}
/**
* It destroys the pool of picture and its resources.
*/
static
void
Direct3DDestroyPool
(
vout_display_t
*
vd
)
{
vout_display_sys_t
*
sys
=
vd
->
sys
;
if
(
sys
->
pool
)
{
picture_resource_t
*
rsc
=
&
sys
->
resource
;
IDirect3DSurface9_Release
(
rsc
->
p_sys
->
surface
);
picture_pool_Delete
(
sys
->
pool
);
}
sys
->
pool
=
NULL
;
}
/*****************************************************************************
/* */
* Direct3DCreateScene: allocate and initialize a 3D scene
typedef
struct
*****************************************************************************
* for advanced blending/filtering a texture needs be used in a 3D scene.
*****************************************************************************/
static
int
Direct3DCreateScene
(
vout_thread_t
*
p_vout
)
{
{
vout_sys_t
*
p_sys
=
p_vout
->
p_sys
;
FLOAT
x
,
y
,
z
;
// vertex untransformed position
LPDIRECT3DDEVICE9
p_d3ddev
=
p_sys
->
p_d3ddev
;
FLOAT
rhw
;
// eye distance
LPDIRECT3DTEXTURE9
p_d3dtex
;
D3DCOLOR
diffuse
;
// diffuse color
LPDIRECT3DVERTEXBUFFER9
p_d3dvtc
;
FLOAT
tu
,
tv
;
// texture relative coordinates
}
CUSTOMVERTEX
;
#define D3DFVF_CUSTOMVERTEX (D3DFVF_XYZRHW|D3DFVF_DIFFUSE|D3DFVF_TEX1)
/**
* It allocates and initializes the resources needed to render the scene.
*/
static
int
Direct3DCreateScene
(
vout_display_t
*
vd
)
{
vout_display_sys_t
*
sys
=
vd
->
sys
;
LPDIRECT3DDEVICE9
d3ddev
=
sys
->
d3ddev
;
HRESULT
hr
;
HRESULT
hr
;
/*
/*
** Create a texture for use when rendering a scene
* Create a texture for use when rendering a scene
** for performance reason, texture format is identical to backbuffer
* for performance reason, texture format is identical to backbuffer
** which would usually be a RGB format
* which would usually be a RGB format
*/
*/
hr
=
IDirect3DDevice9_CreateTexture
(
p_d3ddev
,
LPDIRECT3DTEXTURE9
d3dtex
;
p_sys
->
d3dpp
.
BackBufferWidth
,
hr
=
IDirect3DDevice9_CreateTexture
(
d3ddev
,
p_sys
->
d3dpp
.
BackBufferHeight
,
sys
->
d3dpp
.
BackBufferWidth
,
sys
->
d3dpp
.
BackBufferHeight
,
1
,
1
,
D3DUSAGE_RENDERTARGET
,
D3DUSAGE_RENDERTARGET
,
p_
sys
->
d3dpp
.
BackBufferFormat
,
sys
->
d3dpp
.
BackBufferFormat
,
D3DPOOL_DEFAULT
,
D3DPOOL_DEFAULT
,
&
p_
d3dtex
,
&
d3dtex
,
NULL
);
NULL
);
if
(
FAILED
(
hr
))
{
if
(
FAILED
(
hr
))
{
msg_Err
(
p_vout
,
"Failed to create texture. (hr=0x%lx)"
,
hr
);
msg_Err
(
vd
,
"Failed to create texture. (hr=0x%lx)"
,
hr
);
return
VLC_EGENERIC
;
return
VLC_EGENERIC
;
}
}
/*
/*
** Create a vertex buffer for use when rendering scene
** Create a vertex buffer for use when rendering scene
*/
*/
hr
=
IDirect3DDevice9_CreateVertexBuffer
(
p_d3ddev
,
LPDIRECT3DVERTEXBUFFER9
d3dvtc
;
hr
=
IDirect3DDevice9_CreateVertexBuffer
(
d3ddev
,
sizeof
(
CUSTOMVERTEX
)
*
4
,
sizeof
(
CUSTOMVERTEX
)
*
4
,
D3DUSAGE_DYNAMIC
|
D3DUSAGE_WRITEONLY
,
D3DUSAGE_DYNAMIC
|
D3DUSAGE_WRITEONLY
,
D3DFVF_CUSTOMVERTEX
,
D3DFVF_CUSTOMVERTEX
,
D3DPOOL_DEFAULT
,
D3DPOOL_DEFAULT
,
&
p_
d3dvtc
,
&
d3dvtc
,
NULL
);
NULL
);
if
(
FAILED
(
hr
))
{
if
(
FAILED
(
hr
))
{
msg_Err
(
p_vout
,
"Failed to create vertex buffer. (hr=0x%lx)"
,
hr
);
msg_Err
(
vd
,
"Failed to create vertex buffer. (hr=0x%lx)"
,
hr
);
IDirect3DTexture9_Release
(
p_
d3dtex
);
IDirect3DTexture9_Release
(
d3dtex
);
return
VLC_EGENERIC
;
return
VLC_EGENERIC
;
}
}
p_sys
->
p_d3dtex
=
p_d3dtex
;
/* */
p_sys
->
p_d3dvtc
=
p_d3dvtc
;
sys
->
d3dtex
=
d3dtex
;
sys
->
d3dvtc
=
d3dvtc
;
// Texture coordinates outside the range [0.0, 1.0] are set
// Texture coordinates outside the range [0.0, 1.0] are set
// to the texture color at 0.0 or 1.0, respectively.
// to the texture color at 0.0 or 1.0, respectively.
IDirect3DDevice9_SetSamplerState
(
p_
d3ddev
,
0
,
D3DSAMP_ADDRESSU
,
D3DTADDRESS_CLAMP
);
IDirect3DDevice9_SetSamplerState
(
d3ddev
,
0
,
D3DSAMP_ADDRESSU
,
D3DTADDRESS_CLAMP
);
IDirect3DDevice9_SetSamplerState
(
p_
d3ddev
,
0
,
D3DSAMP_ADDRESSV
,
D3DTADDRESS_CLAMP
);
IDirect3DDevice9_SetSamplerState
(
d3ddev
,
0
,
D3DSAMP_ADDRESSV
,
D3DTADDRESS_CLAMP
);
// Set linear filtering quality
// Set linear filtering quality
IDirect3DDevice9_SetSamplerState
(
p_
d3ddev
,
0
,
D3DSAMP_MINFILTER
,
D3DTEXF_LINEAR
);
IDirect3DDevice9_SetSamplerState
(
d3ddev
,
0
,
D3DSAMP_MINFILTER
,
D3DTEXF_LINEAR
);
IDirect3DDevice9_SetSamplerState
(
p_
d3ddev
,
0
,
D3DSAMP_MAGFILTER
,
D3DTEXF_LINEAR
);
IDirect3DDevice9_SetSamplerState
(
d3ddev
,
0
,
D3DSAMP_MAGFILTER
,
D3DTEXF_LINEAR
);
// set maximum ambient light
// set maximum ambient light
IDirect3DDevice9_SetRenderState
(
p_
d3ddev
,
D3DRS_AMBIENT
,
D3DCOLOR_XRGB
(
255
,
255
,
255
));
IDirect3DDevice9_SetRenderState
(
d3ddev
,
D3DRS_AMBIENT
,
D3DCOLOR_XRGB
(
255
,
255
,
255
));
// Turn off culling
// Turn off culling
IDirect3DDevice9_SetRenderState
(
p_
d3ddev
,
D3DRS_CULLMODE
,
D3DCULL_NONE
);
IDirect3DDevice9_SetRenderState
(
d3ddev
,
D3DRS_CULLMODE
,
D3DCULL_NONE
);
// Turn off the zbuffer
// Turn off the zbuffer
IDirect3DDevice9_SetRenderState
(
p_
d3ddev
,
D3DRS_ZENABLE
,
D3DZB_FALSE
);
IDirect3DDevice9_SetRenderState
(
d3ddev
,
D3DRS_ZENABLE
,
D3DZB_FALSE
);
// Turn off lights
// Turn off lights
IDirect3DDevice9_SetRenderState
(
p_
d3ddev
,
D3DRS_LIGHTING
,
FALSE
);
IDirect3DDevice9_SetRenderState
(
d3ddev
,
D3DRS_LIGHTING
,
FALSE
);
// Enable dithering
// Enable dithering
IDirect3DDevice9_SetRenderState
(
p_
d3ddev
,
D3DRS_DITHERENABLE
,
TRUE
);
IDirect3DDevice9_SetRenderState
(
d3ddev
,
D3DRS_DITHERENABLE
,
TRUE
);
// disable stencil
// disable stencil
IDirect3DDevice9_SetRenderState
(
p_
d3ddev
,
D3DRS_STENCILENABLE
,
FALSE
);
IDirect3DDevice9_SetRenderState
(
d3ddev
,
D3DRS_STENCILENABLE
,
FALSE
);
// manage blending
// manage blending
IDirect3DDevice9_SetRenderState
(
p_
d3ddev
,
D3DRS_ALPHABLENDENABLE
,
TRUE
);
IDirect3DDevice9_SetRenderState
(
d3ddev
,
D3DRS_ALPHABLENDENABLE
,
TRUE
);
IDirect3DDevice9_SetRenderState
(
p_
d3ddev
,
D3DRS_SRCBLEND
,
D3DBLEND_SRCALPHA
);
IDirect3DDevice9_SetRenderState
(
d3ddev
,
D3DRS_SRCBLEND
,
D3DBLEND_SRCALPHA
);
IDirect3DDevice9_SetRenderState
(
p_
d3ddev
,
D3DRS_DESTBLEND
,
D3DBLEND_INVSRCALPHA
);
IDirect3DDevice9_SetRenderState
(
d3ddev
,
D3DRS_DESTBLEND
,
D3DBLEND_INVSRCALPHA
);
IDirect3DDevice9_SetRenderState
(
p_
d3ddev
,
D3DRS_ALPHATESTENABLE
,
TRUE
);
IDirect3DDevice9_SetRenderState
(
d3ddev
,
D3DRS_ALPHATESTENABLE
,
TRUE
);
IDirect3DDevice9_SetRenderState
(
p_
d3ddev
,
D3DRS_ALPHAREF
,
0x10
);
IDirect3DDevice9_SetRenderState
(
d3ddev
,
D3DRS_ALPHAREF
,
0x10
);
IDirect3DDevice9_SetRenderState
(
p_
d3ddev
,
D3DRS_ALPHAFUNC
,
D3DCMP_GREATER
);
IDirect3DDevice9_SetRenderState
(
d3ddev
,
D3DRS_ALPHAFUNC
,
D3DCMP_GREATER
);
// Set texture states
// Set texture states
IDirect3DDevice9_SetTextureStageState
(
p_
d3ddev
,
0
,
D3DTSS_COLOROP
,
D3DTOP_MODULATE
);
IDirect3DDevice9_SetTextureStageState
(
d3ddev
,
0
,
D3DTSS_COLOROP
,
D3DTOP_MODULATE
);
IDirect3DDevice9_SetTextureStageState
(
p_
d3ddev
,
0
,
D3DTSS_COLORARG1
,
D3DTA_TEXTURE
);
IDirect3DDevice9_SetTextureStageState
(
d3ddev
,
0
,
D3DTSS_COLORARG1
,
D3DTA_TEXTURE
);
IDirect3DDevice9_SetTextureStageState
(
p_
d3ddev
,
0
,
D3DTSS_COLORARG2
,
D3DTA_DIFFUSE
);
IDirect3DDevice9_SetTextureStageState
(
d3ddev
,
0
,
D3DTSS_COLORARG2
,
D3DTA_DIFFUSE
);
// turn off alpha operation
// turn off alpha operation
IDirect3DDevice9_SetTextureStageState
(
p_
d3ddev
,
0
,
D3DTSS_ALPHAOP
,
D3DTOP_DISABLE
);
IDirect3DDevice9_SetTextureStageState
(
d3ddev
,
0
,
D3DTSS_ALPHAOP
,
D3DTOP_DISABLE
);
msg_Dbg
(
p_vout
,
"Direct3D scene created successfully"
);
msg_Dbg
(
vd
,
"Direct3D scene created successfully"
);
return
VLC_SUCCESS
;
return
VLC_SUCCESS
;
}
}
/**
***************************************************************************
/**
*
Direct3DReleaseScene
*
It releases the scene resources.
*
****************************************************************************
/
*/
static
void
Direct3D
ReleaseScene
(
vout_thread_t
*
p_vout
)
static
void
Direct3D
DestroyScene
(
vout_display_t
*
vd
)
{
{
vout_
sys_t
*
p_sys
=
p_vout
->
p_
sys
;
vout_
display_sys_t
*
sys
=
vd
->
sys
;
LPDIRECT3DVERTEXBUFFER9
p_d3dvtc
=
p_sys
->
p_
d3dvtc
;
LPDIRECT3DVERTEXBUFFER9
d3dvtc
=
sys
->
d3dvtc
;
if
(
p_
d3dvtc
)
if
(
d3dvtc
)
IDirect3DVertexBuffer9_Release
(
p_
d3dvtc
);
IDirect3DVertexBuffer9_Release
(
d3dvtc
);
LPDIRECT3DTEXTURE9
p_d3dtex
=
p_sys
->
p_
d3dtex
;
LPDIRECT3DTEXTURE9
d3dtex
=
sys
->
d3dtex
;
if
(
p_
d3dtex
)
if
(
d3dtex
)
IDirect3DTexture9_Release
(
p_
d3dtex
);
IDirect3DTexture9_Release
(
d3dtex
);
p_sys
->
p_
d3dvtc
=
NULL
;
sys
->
d3dvtc
=
NULL
;
p_sys
->
p_
d3dtex
=
NULL
;
sys
->
d3dtex
=
NULL
;
msg_Dbg
(
p_vout
,
"Direct3D scene released successfully"
);
msg_Dbg
(
vd
,
"Direct3D scene released successfully"
);
}
}
/**
***************************************************************************
/**
*
Render: copy picture surface into a texture and render into a scene
*
It copies picture surface into a texture and renders into a scene.
*
****************************************************************************
*
* This function is intented for higher end 3D cards, with pixel shader support
* This function is intented for higher end 3D cards, with pixel shader support
* and at least 64 MB of video RAM.
* and at least 64 MB of video RAM.
*
****************************************************************************
/
*/
static
void
Direct3DRenderScene
(
vout_
thread_t
*
p_vout
,
picture_t
*
p_pic
)
static
void
Direct3DRenderScene
(
vout_
display_t
*
vd
,
LPDIRECT3DSURFACE9
surface
)
{
{
vout_
sys_t
*
p_sys
=
p_vout
->
p_
sys
;
vout_
display_sys_t
*
sys
=
vd
->
sys
;
LPDIRECT3DDEVICE9
p_d3ddev
=
p_sys
->
p_
d3ddev
;
LPDIRECT3DDEVICE9
d3ddev
=
sys
->
d3ddev
;
HRESULT
hr
;
HRESULT
hr
;
// check if device is still available
// check if device is still available
hr
=
IDirect3DDevice9_TestCooperativeLevel
(
p_
d3ddev
);
hr
=
IDirect3DDevice9_TestCooperativeLevel
(
d3ddev
);
if
(
FAILED
(
hr
))
{
if
(
FAILED
(
hr
))
{
if
(
hr
!=
D3DERR_DEVICENOTRESET
||
Direct3DResetDevice
(
p_vout
)
)
{
if
(
hr
==
D3DERR_DEVICENOTRESET
&&
!
sys
->
reset_device
)
{
// device is not usable at present (lost device, out of video mem ?)
vout_display_SendEventPicturesInvalid
(
vd
);
return
;
sys
->
reset_device
=
true
;
}
}
return
;
}
}
/* */
/* */
LPDIRECT3DTEXTURE9
p_d3dtex
=
p_sys
->
p_
d3dtex
;
LPDIRECT3DTEXTURE9
d3dtex
=
sys
->
d3dtex
;
LPDIRECT3DVERTEXBUFFER9
p_d3dvtc
=
p_sys
->
p_
d3dvtc
;
LPDIRECT3DVERTEXBUFFER9
d3dvtc
=
sys
->
d3dvtc
;
/* Clear the backbuffer and the zbuffer */
/* Clear the backbuffer and the zbuffer */
hr
=
IDirect3DDevice9_Clear
(
p_
d3ddev
,
0
,
NULL
,
D3DCLEAR_TARGET
,
hr
=
IDirect3DDevice9_Clear
(
d3ddev
,
0
,
NULL
,
D3DCLEAR_TARGET
,
D3DCOLOR_XRGB
(
0
,
0
,
0
),
1
.
0
f
,
0
);
D3DCOLOR_XRGB
(
0
,
0
,
0
),
1
.
0
f
,
0
);
if
(
FAILED
(
hr
))
{
if
(
FAILED
(
hr
))
{
msg_Dbg
(
p_vout
,
"%s:%d (hr=0x%0lX)"
,
__FUNCTION__
,
__LINE__
,
hr
);
msg_Dbg
(
vd
,
"%s:%d (hr=0x%0lX)"
,
__FUNCTION__
,
__LINE__
,
hr
);
return
;
return
;
}
}
/* retrieve picture surface */
/* retrieve picture surface */
LPDIRECT3DSURFACE9
p_d3dsrc
=
(
LPDIRECT3DSURFACE9
)
p_pic
->
p_sys
;
LPDIRECT3DSURFACE9
d3dsrc
=
surface
;
if
(
!
p_
d3dsrc
)
{
if
(
!
d3dsrc
)
{
msg_Dbg
(
p_vout
,
"no surface to render ?"
);
msg_Dbg
(
vd
,
"no surface to render ?"
);
return
;
return
;
}
}
/* retrieve texture top-level surface */
/* retrieve texture top-level surface */
LPDIRECT3DSURFACE9
p_
d3ddest
;
LPDIRECT3DSURFACE9
d3ddest
;
hr
=
IDirect3DTexture9_GetSurfaceLevel
(
p_d3dtex
,
0
,
&
p_
d3ddest
);
hr
=
IDirect3DTexture9_GetSurfaceLevel
(
d3dtex
,
0
,
&
d3ddest
);
if
(
FAILED
(
hr
))
{
if
(
FAILED
(
hr
))
{
msg_Dbg
(
p_vout
,
"%s:%d (hr=0x%0lX)"
,
__FUNCTION__
,
__LINE__
,
hr
);
msg_Dbg
(
vd
,
"%s:%d (hr=0x%0lX)"
,
__FUNCTION__
,
__LINE__
,
hr
);
return
;
return
;
}
}
/* Copy picture surface into texture surface
/* Copy picture surface into texture surface
* color space conversion and scaling happen here */
* color space conversion and scaling happen here */
RECT
src
=
p_vout
->
p_
sys
->
rect_src_clipped
;
RECT
src
=
vd
->
sys
->
rect_src_clipped
;
RECT
dst
=
p_vout
->
p_
sys
->
rect_dest_clipped
;
RECT
dst
=
vd
->
sys
->
rect_dest_clipped
;
hr
=
IDirect3DDevice9_StretchRect
(
p_d3ddev
,
p_d3dsrc
,
&
src
,
p_
d3ddest
,
&
dst
,
D3DTEXF_LINEAR
);
hr
=
IDirect3DDevice9_StretchRect
(
d3ddev
,
d3dsrc
,
&
src
,
d3ddest
,
&
dst
,
D3DTEXF_LINEAR
);
IDirect3DSurface9_Release
(
p_
d3ddest
);
IDirect3DSurface9_Release
(
d3ddest
);
if
(
FAILED
(
hr
))
{
if
(
FAILED
(
hr
))
{
msg_Dbg
(
p_vout
,
"%s:%d (hr=0x%0lX)"
,
__FUNCTION__
,
__LINE__
,
hr
);
msg_Dbg
(
vd
,
"%s:%d (hr=0x%0lX)"
,
__FUNCTION__
,
__LINE__
,
hr
);
return
;
return
;
}
}
/* Update the vertex buffer */
/* Update the vertex buffer */
CUSTOMVERTEX
*
p_
vertices
;
CUSTOMVERTEX
*
vertices
;
hr
=
IDirect3DVertexBuffer9_Lock
(
p_d3dvtc
,
0
,
0
,
(
&
p_vertices
)
,
D3DLOCK_DISCARD
);
hr
=
IDirect3DVertexBuffer9_Lock
(
d3dvtc
,
0
,
0
,
&
vertices
,
D3DLOCK_DISCARD
);
if
(
FAILED
(
hr
))
{
if
(
FAILED
(
hr
))
{
msg_Dbg
(
p_vout
,
"%s:%d (hr=0x%0lX)"
,
__FUNCTION__
,
__LINE__
,
hr
);
msg_Dbg
(
vd
,
"%s:%d (hr=0x%0lX)"
,
__FUNCTION__
,
__LINE__
,
hr
);
return
;
return
;
}
}
/* Setup vertices */
/* Setup vertices */
float
f_width
=
(
float
)
p_vout
->
p_
sys
->
d3dpp
.
BackBufferWidth
;
const
float
f_width
=
vd
->
sys
->
d3dpp
.
BackBufferWidth
;
float
f_height
=
(
float
)
p_vout
->
p_
sys
->
d3dpp
.
BackBufferHeight
;
const
float
f_height
=
vd
->
sys
->
d3dpp
.
BackBufferHeight
;
/* -0.5f is a "feature" of DirectX and it seems to apply to Direct3d also */
/* -0.5f is a "feature" of DirectX and it seems to apply to Direct3d also */
/* http://www.sjbrown.co.uk/2003/05/01/fix-directx-rasterisation/ */
/* http://www.sjbrown.co.uk/2003/05/01/fix-directx-rasterisation/ */
p_
vertices
[
0
].
x
=
-
0
.
5
f
;
// left
vertices
[
0
].
x
=
-
0
.
5
f
;
// left
p_
vertices
[
0
].
y
=
-
0
.
5
f
;
// top
vertices
[
0
].
y
=
-
0
.
5
f
;
// top
p_
vertices
[
0
].
z
=
0
.
0
f
;
vertices
[
0
].
z
=
0
.
0
f
;
p_
vertices
[
0
].
diffuse
=
D3DCOLOR_ARGB
(
255
,
255
,
255
,
255
);
vertices
[
0
].
diffuse
=
D3DCOLOR_ARGB
(
255
,
255
,
255
,
255
);
p_
vertices
[
0
].
rhw
=
1
.
0
f
;
vertices
[
0
].
rhw
=
1
.
0
f
;
p_
vertices
[
0
].
tu
=
0
.
0
f
;
vertices
[
0
].
tu
=
0
.
0
f
;
p_
vertices
[
0
].
tv
=
0
.
0
f
;
vertices
[
0
].
tv
=
0
.
0
f
;
p_
vertices
[
1
].
x
=
f_width
-
0
.
5
f
;
// right
vertices
[
1
].
x
=
f_width
-
0
.
5
f
;
// right
p_
vertices
[
1
].
y
=
-
0
.
5
f
;
// top
vertices
[
1
].
y
=
-
0
.
5
f
;
// top
p_
vertices
[
1
].
z
=
0
.
0
f
;
vertices
[
1
].
z
=
0
.
0
f
;
p_
vertices
[
1
].
diffuse
=
D3DCOLOR_ARGB
(
255
,
255
,
255
,
255
);
vertices
[
1
].
diffuse
=
D3DCOLOR_ARGB
(
255
,
255
,
255
,
255
);
p_
vertices
[
1
].
rhw
=
1
.
0
f
;
vertices
[
1
].
rhw
=
1
.
0
f
;
p_
vertices
[
1
].
tu
=
1
.
0
f
;
vertices
[
1
].
tu
=
1
.
0
f
;
p_
vertices
[
1
].
tv
=
0
.
0
f
;
vertices
[
1
].
tv
=
0
.
0
f
;
p_
vertices
[
2
].
x
=
f_width
-
0
.
5
f
;
// right
vertices
[
2
].
x
=
f_width
-
0
.
5
f
;
// right
p_
vertices
[
2
].
y
=
f_height
-
0
.
5
f
;
// bottom
vertices
[
2
].
y
=
f_height
-
0
.
5
f
;
// bottom
p_
vertices
[
2
].
z
=
0
.
0
f
;
vertices
[
2
].
z
=
0
.
0
f
;
p_
vertices
[
2
].
diffuse
=
D3DCOLOR_ARGB
(
255
,
255
,
255
,
255
);
vertices
[
2
].
diffuse
=
D3DCOLOR_ARGB
(
255
,
255
,
255
,
255
);
p_
vertices
[
2
].
rhw
=
1
.
0
f
;
vertices
[
2
].
rhw
=
1
.
0
f
;
p_
vertices
[
2
].
tu
=
1
.
0
f
;
vertices
[
2
].
tu
=
1
.
0
f
;
p_
vertices
[
2
].
tv
=
1
.
0
f
;
vertices
[
2
].
tv
=
1
.
0
f
;
p_
vertices
[
3
].
x
=
-
0
.
5
f
;
// left
vertices
[
3
].
x
=
-
0
.
5
f
;
// left
p_
vertices
[
3
].
y
=
f_height
-
0
.
5
f
;
// bottom
vertices
[
3
].
y
=
f_height
-
0
.
5
f
;
// bottom
p_
vertices
[
3
].
z
=
0
.
0
f
;
vertices
[
3
].
z
=
0
.
0
f
;
p_
vertices
[
3
].
diffuse
=
D3DCOLOR_ARGB
(
255
,
255
,
255
,
255
);
vertices
[
3
].
diffuse
=
D3DCOLOR_ARGB
(
255
,
255
,
255
,
255
);
p_
vertices
[
3
].
rhw
=
1
.
0
f
;
vertices
[
3
].
rhw
=
1
.
0
f
;
p_
vertices
[
3
].
tu
=
0
.
0
f
;
vertices
[
3
].
tu
=
0
.
0
f
;
p_
vertices
[
3
].
tv
=
1
.
0
f
;
vertices
[
3
].
tv
=
1
.
0
f
;
hr
=
IDirect3DVertexBuffer9_Unlock
(
p_
d3dvtc
);
hr
=
IDirect3DVertexBuffer9_Unlock
(
d3dvtc
);
if
(
FAILED
(
hr
))
{
if
(
FAILED
(
hr
))
{
msg_Dbg
(
p_vout
,
"%s:%d (hr=0x%0lX)"
,
__FUNCTION__
,
__LINE__
,
hr
);
msg_Dbg
(
vd
,
"%s:%d (hr=0x%0lX)"
,
__FUNCTION__
,
__LINE__
,
hr
);
return
;
return
;
}
}
// Begin the scene
// Begin the scene
hr
=
IDirect3DDevice9_BeginScene
(
p_
d3ddev
);
hr
=
IDirect3DDevice9_BeginScene
(
d3ddev
);
if
(
FAILED
(
hr
))
{
if
(
FAILED
(
hr
))
{
msg_Dbg
(
p_vout
,
"%s:%d (hr=0x%0lX)"
,
__FUNCTION__
,
__LINE__
,
hr
);
msg_Dbg
(
vd
,
"%s:%d (hr=0x%0lX)"
,
__FUNCTION__
,
__LINE__
,
hr
);
return
;
return
;
}
}
...
@@ -1149,41 +1175,41 @@ static void Direct3DRenderScene(vout_thread_t *p_vout, picture_t *p_pic)
...
@@ -1149,41 +1175,41 @@ static void Direct3DRenderScene(vout_thread_t *p_vout, picture_t *p_pic)
// which govern how textures get blended together (in the case of multiple
// which govern how textures get blended together (in the case of multiple
// textures) and lighting information. In this case, we are modulating
// textures) and lighting information. In this case, we are modulating
// (blending) our texture with the diffuse color of the vertices.
// (blending) our texture with the diffuse color of the vertices.
hr
=
IDirect3DDevice9_SetTexture
(
p_d3ddev
,
0
,
(
LPDIRECT3DBASETEXTURE9
)
p_
d3dtex
);
hr
=
IDirect3DDevice9_SetTexture
(
d3ddev
,
0
,
(
LPDIRECT3DBASETEXTURE9
)
d3dtex
);
if
(
FAILED
(
hr
))
{
if
(
FAILED
(
hr
))
{
msg_Dbg
(
p_vout
,
"%s:%d (hr=0x%0lX)"
,
__FUNCTION__
,
__LINE__
,
hr
);
msg_Dbg
(
vd
,
"%s:%d (hr=0x%0lX)"
,
__FUNCTION__
,
__LINE__
,
hr
);
IDirect3DDevice9_EndScene
(
p_
d3ddev
);
IDirect3DDevice9_EndScene
(
d3ddev
);
return
;
return
;
}
}
// Render the vertex buffer contents
// Render the vertex buffer contents
hr
=
IDirect3DDevice9_SetStreamSource
(
p_d3ddev
,
0
,
p_
d3dvtc
,
0
,
sizeof
(
CUSTOMVERTEX
));
hr
=
IDirect3DDevice9_SetStreamSource
(
d3ddev
,
0
,
d3dvtc
,
0
,
sizeof
(
CUSTOMVERTEX
));
if
(
FAILED
(
hr
))
{
if
(
FAILED
(
hr
))
{
msg_Dbg
(
p_vout
,
"%s:%d (hr=0x%0lX)"
,
__FUNCTION__
,
__LINE__
,
hr
);
msg_Dbg
(
vd
,
"%s:%d (hr=0x%0lX)"
,
__FUNCTION__
,
__LINE__
,
hr
);
IDirect3DDevice9_EndScene
(
p_
d3ddev
);
IDirect3DDevice9_EndScene
(
d3ddev
);
return
;
return
;
}
}
// we use FVF instead of vertex shader
// we use FVF instead of vertex shader
hr
=
IDirect3DDevice9_SetFVF
(
p_
d3ddev
,
D3DFVF_CUSTOMVERTEX
);
hr
=
IDirect3DDevice9_SetFVF
(
d3ddev
,
D3DFVF_CUSTOMVERTEX
);
if
(
FAILED
(
hr
))
{
if
(
FAILED
(
hr
))
{
msg_Dbg
(
p_vout
,
"%s:%d (hr=0x%0lX)"
,
__FUNCTION__
,
__LINE__
,
hr
);
msg_Dbg
(
vd
,
"%s:%d (hr=0x%0lX)"
,
__FUNCTION__
,
__LINE__
,
hr
);
IDirect3DDevice9_EndScene
(
p_
d3ddev
);
IDirect3DDevice9_EndScene
(
d3ddev
);
return
;
return
;
}
}
// draw rectangle
// draw rectangle
hr
=
IDirect3DDevice9_DrawPrimitive
(
p_
d3ddev
,
D3DPT_TRIANGLEFAN
,
0
,
2
);
hr
=
IDirect3DDevice9_DrawPrimitive
(
d3ddev
,
D3DPT_TRIANGLEFAN
,
0
,
2
);
if
(
FAILED
(
hr
))
{
if
(
FAILED
(
hr
))
{
msg_Dbg
(
p_vout
,
"%s:%d (hr=0x%0lX)"
,
__FUNCTION__
,
__LINE__
,
hr
);
msg_Dbg
(
vd
,
"%s:%d (hr=0x%0lX)"
,
__FUNCTION__
,
__LINE__
,
hr
);
IDirect3DDevice9_EndScene
(
p_
d3ddev
);
IDirect3DDevice9_EndScene
(
d3ddev
);
return
;
return
;
}
}
// End the scene
// End the scene
hr
=
IDirect3DDevice9_EndScene
(
p_
d3ddev
);
hr
=
IDirect3DDevice9_EndScene
(
d3ddev
);
if
(
FAILED
(
hr
))
{
if
(
FAILED
(
hr
))
{
msg_Dbg
(
p_vout
,
"%s:%d (hr=0x%0lX)"
,
__FUNCTION__
,
__LINE__
,
hr
);
msg_Dbg
(
vd
,
"%s:%d (hr=0x%0lX)"
,
__FUNCTION__
,
__LINE__
,
hr
);
return
;
return
;
}
}
}
}
...
@@ -1195,24 +1221,28 @@ static int DesktopCallback(vlc_object_t *object, char const *psz_cmd,
...
@@ -1195,24 +1221,28 @@ static int DesktopCallback(vlc_object_t *object, char const *psz_cmd,
vlc_value_t
oldval
,
vlc_value_t
newval
,
vlc_value_t
oldval
,
vlc_value_t
newval
,
void
*
p_data
)
void
*
p_data
)
{
{
vout_display_t
*
vd
=
(
vout_display_t
*
)
object
;
vout_display_sys_t
*
sys
=
vd
->
sys
;
VLC_UNUSED
(
psz_cmd
);
VLC_UNUSED
(
psz_cmd
);
VLC_UNUSED
(
oldval
);
VLC_UNUSED
(
oldval
);
VLC_UNUSED
(
p_data
);
VLC_UNUSED
(
p_data
);
vout_thread_t
*
p_vout
=
(
vout_thread_t
*
)
object
;
vlc_mutex_lock
(
&
sys
->
lock
);
const
bool
ch_desktop
=
!
sys
->
desktop_requested
!=
!
newval
.
b_bool
;
if
((
newval
.
b_bool
&&
!
p_vout
->
p_sys
->
b_desktop
)
||
sys
->
ch_desktop
|=
ch_desktop
;
(
!
newval
.
b_bool
&&
p_vout
->
p_sys
->
b_desktop
))
{
sys
->
desktop_requested
=
newval
.
b_bool
;
vlc_mutex_unlock
(
&
sys
->
lock
);
playlist_t
*
p_playlist
=
pl_Hold
(
p_vout
);
/* FIXME we should have a way to export variable to be saved */
if
(
ch_desktop
)
{
playlist_t
*
p_playlist
=
pl_Hold
(
vd
);
if
(
p_playlist
)
{
if
(
p_playlist
)
{
/* Modify playlist as well because the vout might have to be
/* Modify playlist as well because the vout might have to be
* restarted */
* restarted */
var_Create
(
p_playlist
,
"direct3d-desktop"
,
VLC_VAR_BOOL
);
var_Create
(
p_playlist
,
"direct3d-desktop"
,
VLC_VAR_BOOL
);
var_Set
(
p_playlist
,
"direct3d-desktop"
,
newva
l
);
var_Set
Bool
(
p_playlist
,
"direct3d-desktop"
,
newval
.
b_boo
l
);
pl_Release
(
p_vout
);
pl_Release
(
vd
);
}
}
p_vout
->
p_sys
->
i_changes
|=
DX_DESKTOP_CHANGE
;
}
}
return
VLC_SUCCESS
;
return
VLC_SUCCESS
;
}
}
modules/video_output/msw/events.c
View file @
f6d06e15
...
@@ -31,8 +31,7 @@
...
@@ -31,8 +31,7 @@
#endif
#endif
#include <vlc_common.h>
#include <vlc_common.h>
#include <vlc_playlist.h>
#include <vlc_vout_display.h>
#include <vlc_vout.h>
#include <vlc_vout_window.h>
#include <vlc_vout_window.h>
#include <windows.h>
#include <windows.h>
...
@@ -52,7 +51,7 @@
...
@@ -52,7 +51,7 @@
#endif
#endif
#include <vlc_keys.h>
#include <vlc_keys.h>
#include "
vout
.h"
#include "
common
.h"
#ifdef UNDER_CE
#ifdef UNDER_CE
#include <aygshell.h>
#include <aygshell.h>
...
@@ -75,7 +74,7 @@
...
@@ -75,7 +74,7 @@
struct
event_thread_t
struct
event_thread_t
{
{
vout_
thread_t
*
p_vout
;
vout_
display_t
*
vd
;
/* */
/* */
vlc_thread_t
thread
;
vlc_thread_t
thread
;
...
@@ -100,26 +99,22 @@ struct event_thread_t
...
@@ -100,26 +99,22 @@ struct event_thread_t
int
i_window_style
;
int
i_window_style
;
vout_window_cfg_t
wnd_cfg
;
vout_window_cfg_t
wnd_cfg
;
/* */
unsigned
i_changes
;
/* */
/* */
vout_window_t
*
parent_window
;
vout_window_t
*
parent_window
;
HWND
hparent
;
HWND
hparent
;
HWND
hwnd
;
HWND
hwnd
;
HWND
hvideownd
;
HWND
hvideownd
;
HWND
hfswnd
;
HWND
hfswnd
;
video_format_t
source
;
vout_display_place_t
place
;
bool
has_moved
;
};
};
static
int
DirectXCreateWindow
(
event_thread_t
*
);
static
int
DirectXCreateWindow
(
event_thread_t
*
);
static
void
DirectXCloseWindow
(
event_thread_t
*
);
static
void
DirectXCloseWindow
(
event_thread_t
*
);
static
long
FAR
PASCAL
DirectXEventProc
(
HWND
,
UINT
,
WPARAM
,
LPARAM
);
static
long
FAR
PASCAL
DirectXEventProc
(
HWND
,
UINT
,
WPARAM
,
LPARAM
);
static
void
DirectXPopupMenu
(
event_thread_t
*
p_event
,
bool
b_open
)
{
var_SetBool
(
p_event
->
p_vout
->
p_libvlc
,
"intf-popupmenu"
,
b_open
);
}
static
int
DirectXConvertKey
(
int
i_key
);
static
int
DirectXConvertKey
(
int
i_key
);
/*****************************************************************************
/*****************************************************************************
...
@@ -133,11 +128,9 @@ static int DirectXConvertKey( int i_key );
...
@@ -133,11 +128,9 @@ static int DirectXConvertKey( int i_key );
static
void
*
EventThread
(
void
*
p_this
)
static
void
*
EventThread
(
void
*
p_this
)
{
{
event_thread_t
*
p_event
=
(
event_thread_t
*
)
p_this
;
event_thread_t
*
p_event
=
(
event_thread_t
*
)
p_this
;
vout_
thread_t
*
p_vout
=
p_event
->
p_vout
;
vout_
display_t
*
vd
=
p_event
->
vd
;
MSG
msg
;
MSG
msg
;
POINT
old_mouse_pos
=
{
0
,
0
},
mouse_pos
;
POINT
old_mouse_pos
=
{
0
,
0
},
mouse_pos
;
vlc_value_t
val
;
unsigned
int
i_width
,
i_height
,
i_x
,
i_y
;
HMODULE
hkernel32
;
HMODULE
hkernel32
;
int
canc
=
vlc_savecancel
();
int
canc
=
vlc_savecancel
();
...
@@ -173,7 +166,7 @@ static void *EventThread( void *p_this )
...
@@ -173,7 +166,7 @@ static void *EventThread( void *p_this )
/* Prevent monitor from powering off */
/* Prevent monitor from powering off */
OurSetThreadExecutionState
(
ES_DISPLAY_REQUIRED
|
ES_CONTINUOUS
);
OurSetThreadExecutionState
(
ES_DISPLAY_REQUIRED
|
ES_CONTINUOUS
);
else
else
msg_Dbg
(
p_vout
,
"no support for SetThreadExecutionState()"
);
msg_Dbg
(
vd
,
"no support for SetThreadExecutionState()"
);
}
}
#endif
#endif
...
@@ -181,6 +174,9 @@ static void *EventThread( void *p_this )
...
@@ -181,6 +174,9 @@ static void *EventThread( void *p_this )
/* GetMessage will sleep if there's no message in the queue */
/* GetMessage will sleep if there's no message in the queue */
for
(
;;
)
for
(
;;
)
{
{
vout_display_place_t
place
;
video_format_t
source
;
if
(
!
GetMessage
(
&
msg
,
0
,
0
,
0
)
)
if
(
!
GetMessage
(
&
msg
,
0
,
0
,
0
)
)
{
{
vlc_mutex_lock
(
&
p_event
->
lock
);
vlc_mutex_lock
(
&
p_event
->
lock
);
...
@@ -199,37 +195,30 @@ static void *EventThread( void *p_this )
...
@@ -199,37 +195,30 @@ static void *EventThread( void *p_this )
/* */
/* */
switch
(
msg
.
message
)
switch
(
msg
.
message
)
{
{
case
WM_MOUSEMOVE
:
case
WM_MOUSEMOVE
:
vlc_mutex_lock
(
&
p_event
->
lock
);
vlc_mutex_lock
(
&
p_event
->
lock
);
vout_PlacePicture
(
p_event
->
p_vout
,
place
=
p_event
->
place
;
p_event
->
wnd_cfg
.
width
,
source
=
p_event
->
source
;
p_event
->
wnd_cfg
.
height
,
&
i_x
,
&
i_y
,
&
i_width
,
&
i_height
);
vlc_mutex_unlock
(
&
p_event
->
lock
);
vlc_mutex_unlock
(
&
p_event
->
lock
);
if
(
msg
.
hwnd
==
p_event
->
hvideownd
)
if
(
place
.
width
>
0
&&
place
.
height
>
0
)
{
{
/* Child window */
if
(
msg
.
hwnd
==
p_event
->
hvideownd
)
i_x
=
i_y
=
0
;
{
}
/* Child window */
place
.
x
=
0
;
if
(
i_width
&&
i_height
)
place
.
y
=
0
;
{
}
val
.
i_int
=
(
GET_X_LPARAM
(
msg
.
lParam
)
-
i_x
)
*
const
int
x
=
source
.
i_x_offset
+
p_event
->
p_vout
->
fmt_in
.
i_visible_width
/
i_width
+
(
int64_t
)(
GET_X_LPARAM
(
msg
.
lParam
)
-
place
.
x
)
*
source
.
i_width
/
place
.
width
;
p_event
->
p_vout
->
fmt_in
.
i_x_offset
;
const
int
y
=
source
.
i_y_offset
+
var_Set
(
p_event
->
p_vout
,
"mouse-x"
,
val
);
(
int64_t
)(
GET_Y_LPARAM
(
msg
.
lParam
)
-
place
.
y
)
*
source
.
i_height
/
place
.
height
;
val
.
i_int
=
(
GET_Y_LPARAM
(
msg
.
lParam
)
-
i_y
)
*
vout_display_SendEventMouseMoved
(
vd
,
x
,
y
);
p_event
->
p_vout
->
fmt_in
.
i_visible_height
/
i_height
+
p_event
->
p_vout
->
fmt_in
.
i_y_offset
;
var_Set
(
p_event
->
p_vout
,
"mouse-y"
,
val
);
var_SetBool
(
p_event
->
p_vout
,
"mouse-moved"
,
true
);
}
}
/* Fall through */
case
WM_NCMOUSEMOVE
:
case
WM_NCMOUSEMOVE
:
GetCursorPos
(
&
mouse_pos
);
GetCursorPos
(
&
mouse_pos
);
/* FIXME, why this >2 limits ? */
if
(
(
abs
(
mouse_pos
.
x
-
old_mouse_pos
.
x
)
>
2
||
if
(
(
abs
(
mouse_pos
.
x
-
old_mouse_pos
.
x
)
>
2
||
(
abs
(
mouse_pos
.
y
-
old_mouse_pos
.
y
))
>
2
)
)
(
abs
(
mouse_pos
.
y
-
old_mouse_pos
.
y
))
>
2
)
)
{
{
...
@@ -238,132 +227,114 @@ static void *EventThread( void *p_this )
...
@@ -238,132 +227,114 @@ static void *EventThread( void *p_this )
if
(
p_event
->
b_cursor_hidden
)
if
(
p_event
->
b_cursor_hidden
)
{
{
p_event
->
b_cursor_hidden
=
0
;
p_event
->
b_cursor_hidden
=
false
;
ShowCursor
(
TRUE
);
ShowCursor
(
TRUE
);
}
}
}
}
break
;
break
;
case
WM_VLC_HIDE_MOUSE
:
case
WM_VLC_HIDE_MOUSE
:
if
(
p_event
->
b_cursor_hidden
)
break
;
if
(
p_event
->
b_cursor_hidden
)
break
;
p_event
->
b_cursor_hidden
=
true
;
p_event
->
b_cursor_hidden
=
true
;
GetCursorPos
(
&
old_mouse_pos
);
GetCursorPos
(
&
old_mouse_pos
);
ShowCursor
(
FALSE
);
ShowCursor
(
FALSE
);
break
;
break
;
case
WM_VLC_SHOW_MOUSE
:
case
WM_VLC_SHOW_MOUSE
:
if
(
!
p_event
->
b_cursor_hidden
)
break
;
if
(
!
p_event
->
b_cursor_hidden
)
break
;
p_event
->
b_cursor_hidden
=
false
;
p_event
->
b_cursor_hidden
=
false
;
GetCursorPos
(
&
old_mouse_pos
);
GetCursorPos
(
&
old_mouse_pos
);
ShowCursor
(
TRUE
);
ShowCursor
(
TRUE
);
break
;
break
;
case
WM_LBUTTONDOWN
:
case
WM_LBUTTONDOWN
:
var_Get
(
p_event
->
p_vout
,
"mouse-button-down"
,
&
val
);
vout_display_SendEventMousePressed
(
vd
,
MOUSE_BUTTON_LEFT
);
val
.
i_int
|=
1
;
var_Set
(
p_event
->
p_vout
,
"mouse-button-down"
,
val
);
DirectXPopupMenu
(
p_event
,
false
);
break
;
break
;
case
WM_LBUTTONUP
:
case
WM_LBUTTONUP
:
var_Get
(
p_event
->
p_vout
,
"mouse-button-down"
,
&
val
);
vout_display_SendEventMouseReleased
(
vd
,
MOUSE_BUTTON_LEFT
);
val
.
i_int
&=
~
1
;
var_Set
(
p_event
->
p_vout
,
"mouse-button-down"
,
val
);
var_SetBool
(
p_event
->
p_vout
,
"mouse-clicked"
,
true
);
break
;
break
;
case
WM_LBUTTONDBLCLK
:
case
WM_LBUTTONDBLCLK
:
vlc_mutex_lock
(
&
p_event
->
lock
);
vout_display_SendEventMouseDoubleClick
(
vd
);
p_event
->
i_changes
|=
VOUT_FULLSCREEN_CHANGE
;
vlc_mutex_unlock
(
&
p_event
->
lock
);
break
;
break
;
case
WM_MBUTTONDOWN
:
case
WM_MBUTTONDOWN
:
var_Get
(
p_event
->
p_vout
,
"mouse-button-down"
,
&
val
);
vout_display_SendEventMousePressed
(
vd
,
MOUSE_BUTTON_CENTER
);
val
.
i_int
|=
2
;
var_Set
(
p_event
->
p_vout
,
"mouse-button-down"
,
val
);
DirectXPopupMenu
(
p_event
,
false
);
break
;
break
;
case
WM_MBUTTONUP
:
case
WM_MBUTTONUP
:
var_Get
(
p_event
->
p_vout
,
"mouse-button-down"
,
&
val
);
vout_display_SendEventMouseReleased
(
vd
,
MOUSE_BUTTON_CENTER
);
val
.
i_int
&=
~
2
;
var_Set
(
p_event
->
p_vout
,
"mouse-button-down"
,
val
);
break
;
break
;
case
WM_RBUTTONDOWN
:
case
WM_RBUTTONDOWN
:
var_Get
(
p_event
->
p_vout
,
"mouse-button-down"
,
&
val
);
vout_display_SendEventMousePressed
(
vd
,
MOUSE_BUTTON_RIGHT
);
val
.
i_int
|=
4
;
var_Set
(
p_event
->
p_vout
,
"mouse-button-down"
,
val
);
DirectXPopupMenu
(
p_event
,
false
);
break
;
break
;
case
WM_RBUTTONUP
:
case
WM_RBUTTONUP
:
var_Get
(
p_event
->
p_vout
,
"mouse-button-down"
,
&
val
);
vout_display_SendEventMouseReleased
(
vd
,
MOUSE_BUTTON_RIGHT
);
val
.
i_int
&=
~
4
;
var_Set
(
p_event
->
p_vout
,
"mouse-button-down"
,
val
);
DirectXPopupMenu
(
p_event
,
true
);
break
;
break
;
case
WM_KEYDOWN
:
case
WM_KEYDOWN
:
case
WM_SYSKEYDOWN
:
case
WM_SYSKEYDOWN
:
{
/* The key events are first processed here and not translated
/* The key events are first processed here and not translated
* into WM_CHAR events because we need to know the status of the
* into WM_CHAR events because we need to know the status of the
* modifier keys. */
* modifier keys. */
val
.
i_int
=
DirectXConvertKey
(
msg
.
wParam
);
int
i_key
=
DirectXConvertKey
(
msg
.
wParam
);
if
(
!
val
.
i_int
)
if
(
!
i_key
)
{
{
/* This appears to be a "normal" (ascii) key */
/* This appears to be a "normal" (ascii) key */
val
.
i_int
=
tolower
(
MapVirtualKey
(
msg
.
wParam
,
2
)
);
i_key
=
tolower
(
MapVirtualKey
(
msg
.
wParam
,
2
)
);
}
}
if
(
val
.
i_int
)
if
(
i_key
)
{
{
if
(
GetKeyState
(
VK_CONTROL
)
&
0x8000
)
if
(
GetKeyState
(
VK_CONTROL
)
&
0x8000
)
{
{
val
.
i_int
|=
KEY_MODIFIER_CTRL
;
i_key
|=
KEY_MODIFIER_CTRL
;
}
}
if
(
GetKeyState
(
VK_SHIFT
)
&
0x8000
)
if
(
GetKeyState
(
VK_SHIFT
)
&
0x8000
)
{
{
val
.
i_int
|=
KEY_MODIFIER_SHIFT
;
i_key
|=
KEY_MODIFIER_SHIFT
;
}
}
if
(
GetKeyState
(
VK_MENU
)
&
0x8000
)
if
(
GetKeyState
(
VK_MENU
)
&
0x8000
)
{
{
val
.
i_int
|=
KEY_MODIFIER_ALT
;
i_key
|=
KEY_MODIFIER_ALT
;
}
}
v
ar_Set
(
p_vout
->
p_libvlc
,
"key-pressed"
,
val
);
v
out_display_SendEventKey
(
vd
,
i_key
);
}
}
break
;
break
;
}
case
WM_MOUSEWHEEL
:
case
WM_MOUSEWHEEL
:
{
int
i_key
;
if
(
GET_WHEEL_DELTA_WPARAM
(
msg
.
wParam
)
>
0
)
if
(
GET_WHEEL_DELTA_WPARAM
(
msg
.
wParam
)
>
0
)
{
{
val
.
i_int
=
KEY_MOUSEWHEELUP
;
i_key
=
KEY_MOUSEWHEELUP
;
}
}
else
else
{
{
val
.
i_int
=
KEY_MOUSEWHEELDOWN
;
i_key
=
KEY_MOUSEWHEELDOWN
;
}
}
if
(
val
.
i_int
)
if
(
i_key
)
{
{
if
(
GetKeyState
(
VK_CONTROL
)
&
0x8000
)
if
(
GetKeyState
(
VK_CONTROL
)
&
0x8000
)
{
{
val
.
i_int
|=
KEY_MODIFIER_CTRL
;
i_key
|=
KEY_MODIFIER_CTRL
;
}
}
if
(
GetKeyState
(
VK_SHIFT
)
&
0x8000
)
if
(
GetKeyState
(
VK_SHIFT
)
&
0x8000
)
{
{
val
.
i_int
|=
KEY_MODIFIER_SHIFT
;
i_key
|=
KEY_MODIFIER_SHIFT
;
}
}
if
(
GetKeyState
(
VK_MENU
)
&
0x8000
)
if
(
GetKeyState
(
VK_MENU
)
&
0x8000
)
{
{
val
.
i_int
|=
KEY_MODIFIER_ALT
;
i_key
|=
KEY_MODIFIER_ALT
;
}
}
vout_display_SendEventKey
(
vd
,
i_key
);
var_Set
(
p_vout
->
p_libvlc
,
"key-pressed"
,
val
);
}
}
break
;
break
;
}
case
WM_VLC_CHANGE_TEXT
:
case
WM_VLC_CHANGE_TEXT
:
{
{
...
@@ -405,11 +376,11 @@ static void *EventThread( void *p_this )
...
@@ -405,11 +376,11 @@ static void *EventThread( void *p_this )
/* Check for WM_QUIT if we created the window */
/* Check for WM_QUIT if we created the window */
if
(
!
p_event
->
hparent
&&
msg
.
message
==
WM_QUIT
)
if
(
!
p_event
->
hparent
&&
msg
.
message
==
WM_QUIT
)
{
{
msg_Warn
(
p_vout
,
"WM_QUIT... should not happen!!"
);
msg_Warn
(
vd
,
"WM_QUIT... should not happen!!"
);
p_event
->
hwnd
=
NULL
;
/* Window already destroyed */
p_event
->
hwnd
=
NULL
;
/* Window already destroyed */
}
}
msg_Dbg
(
p_vout
,
"DirectXEventThread terminating"
);
msg_Dbg
(
vd
,
"DirectXEventThread terminating"
);
DirectXCloseWindow
(
p_event
);
DirectXCloseWindow
(
p_event
);
vlc_restorecancel
(
canc
);
vlc_restorecancel
(
canc
);
...
@@ -428,7 +399,7 @@ static void *EventThread( void *p_this )
...
@@ -428,7 +399,7 @@ static void *EventThread( void *p_this )
*****************************************************************************/
*****************************************************************************/
static
int
DirectXCreateWindow
(
event_thread_t
*
p_event
)
static
int
DirectXCreateWindow
(
event_thread_t
*
p_event
)
{
{
vout_
thread_t
*
p_vout
=
p_event
->
p_vout
;
vout_
display_t
*
vd
=
p_event
->
vd
;
HINSTANCE
hInstance
;
HINSTANCE
hInstance
;
HMENU
hMenu
;
HMENU
hMenu
;
RECT
rect_window
;
RECT
rect_window
;
...
@@ -437,7 +408,7 @@ static int DirectXCreateWindow( event_thread_t *p_event )
...
@@ -437,7 +408,7 @@ static int DirectXCreateWindow( event_thread_t *p_event )
char
vlc_path
[
MAX_PATH
+
1
];
char
vlc_path
[
MAX_PATH
+
1
];
int
i_style
,
i_stylex
;
int
i_style
,
i_stylex
;
msg_Dbg
(
p_vout
,
"DirectXCreateWindow"
);
msg_Dbg
(
vd
,
"DirectXCreateWindow"
);
/* Get this module's instance */
/* Get this module's instance */
hInstance
=
GetModuleHandle
(
NULL
);
hInstance
=
GetModuleHandle
(
NULL
);
...
@@ -447,7 +418,7 @@ static int DirectXCreateWindow( event_thread_t *p_event )
...
@@ -447,7 +418,7 @@ static int DirectXCreateWindow( event_thread_t *p_event )
{
{
#endif
#endif
/* If an external window was specified, we'll draw in it. */
/* If an external window was specified, we'll draw in it. */
p_event
->
parent_window
=
vout_
window_New
(
VLC_OBJECT
(
p_vout
),
NULL
,
&
p_event
->
wnd_cfg
);
p_event
->
parent_window
=
vout_
display_NewWindow
(
vd
,
&
p_event
->
wnd_cfg
);
if
(
p_event
->
parent_window
)
if
(
p_event
->
parent_window
)
p_event
->
hparent
=
p_event
->
parent_window
->
handle
.
hwnd
;
p_event
->
hparent
=
p_event
->
parent_window
->
handle
.
hwnd
;
else
else
...
@@ -461,7 +432,8 @@ static int DirectXCreateWindow( event_thread_t *p_event )
...
@@ -461,7 +432,8 @@ static int DirectXCreateWindow( event_thread_t *p_event )
if
(
hwnd
)
hwnd
=
FindWindowEx
(
hwnd
,
NULL
,
_T
(
"SHELLDLL_DefView"
),
NULL
);
if
(
hwnd
)
hwnd
=
FindWindowEx
(
hwnd
,
NULL
,
_T
(
"SHELLDLL_DefView"
),
NULL
);
if
(
hwnd
)
hwnd
=
FindWindowEx
(
hwnd
,
NULL
,
_T
(
"SysListView32"
),
NULL
);
if
(
hwnd
)
hwnd
=
FindWindowEx
(
hwnd
,
NULL
,
_T
(
"SysListView32"
),
NULL
);
if
(
!
hwnd
)
if
(
!
hwnd
)
msg_Err
(
p_vout
,
"Couldn't find desktop icon window. Desktop mode can't be established."
);
msg_Err
(
vd
,
"Couldn't find desktop icon window. Desktop mode can't be established."
);
p_event
->
parent_window
=
NULL
;
p_event
->
hparent
=
hwnd
;
p_event
->
hparent
=
hwnd
;
}
}
#endif
#endif
...
@@ -498,7 +470,7 @@ static int DirectXCreateWindow( event_thread_t *p_event )
...
@@ -498,7 +470,7 @@ static int DirectXCreateWindow( event_thread_t *p_event )
* then fine, otherwise return with an error. */
* then fine, otherwise return with an error. */
if
(
!
GetClassInfo
(
hInstance
,
_T
(
"VLC DirectX"
),
&
wndclass
)
)
if
(
!
GetClassInfo
(
hInstance
,
_T
(
"VLC DirectX"
),
&
wndclass
)
)
{
{
msg_Err
(
p_vout
,
"DirectXCreateWindow RegisterClass FAILED (err=%lu)"
,
GetLastError
()
);
msg_Err
(
vd
,
"DirectXCreateWindow RegisterClass FAILED (err=%lu)"
,
GetLastError
()
);
return
VLC_EGENERIC
;
return
VLC_EGENERIC
;
}
}
}
}
...
@@ -514,7 +486,7 @@ static int DirectXCreateWindow( event_thread_t *p_event )
...
@@ -514,7 +486,7 @@ static int DirectXCreateWindow( event_thread_t *p_event )
* then fine, otherwise return with an error. */
* then fine, otherwise return with an error. */
if
(
!
GetClassInfo
(
hInstance
,
_T
(
"VLC DirectX video"
),
&
wndclass
)
)
if
(
!
GetClassInfo
(
hInstance
,
_T
(
"VLC DirectX video"
),
&
wndclass
)
)
{
{
msg_Err
(
p_vout
,
"DirectXCreateWindow RegisterClass FAILED (err=%lu)"
,
GetLastError
()
);
msg_Err
(
vd
,
"DirectXCreateWindow RegisterClass FAILED (err=%lu)"
,
GetLastError
()
);
return
VLC_EGENERIC
;
return
VLC_EGENERIC
;
}
}
}
}
...
@@ -528,7 +500,7 @@ static int DirectXCreateWindow( event_thread_t *p_event )
...
@@ -528,7 +500,7 @@ static int DirectXCreateWindow( event_thread_t *p_event )
rect_window
.
right
=
rect_window
.
left
+
p_event
->
wnd_cfg
.
width
;
rect_window
.
right
=
rect_window
.
left
+
p_event
->
wnd_cfg
.
width
;
rect_window
.
bottom
=
rect_window
.
top
+
p_event
->
wnd_cfg
.
height
;
rect_window
.
bottom
=
rect_window
.
top
+
p_event
->
wnd_cfg
.
height
;
if
(
var_GetBool
(
p_vout
,
"video-deco"
)
)
if
(
var_GetBool
(
vd
,
"video-deco"
)
)
{
{
/* Open with window decoration */
/* Open with window decoration */
AdjustWindowRect
(
&
rect_window
,
WS_OVERLAPPEDWINDOW
|
WS_SIZEBOX
,
0
);
AdjustWindowRect
(
&
rect_window
,
WS_OVERLAPPEDWINDOW
|
WS_SIZEBOX
,
0
);
...
@@ -567,11 +539,11 @@ static int DirectXCreateWindow( event_thread_t *p_event )
...
@@ -567,11 +539,11 @@ static int DirectXCreateWindow( event_thread_t *p_event )
p_event
->
hparent
,
/* parent window */
p_event
->
hparent
,
/* parent window */
NULL
,
/* no menu in this window */
NULL
,
/* no menu in this window */
hInstance
,
/* handle of this program instance */
hInstance
,
/* handle of this program instance */
(
LPVOID
)
p_event
);
/* send
p_vout
to WM_CREATE */
(
LPVOID
)
p_event
);
/* send
vd
to WM_CREATE */
if
(
!
p_event
->
hwnd
)
if
(
!
p_event
->
hwnd
)
{
{
msg_Warn
(
p_vout
,
"DirectXCreateWindow create window FAILED (err=%lu)"
,
GetLastError
()
);
msg_Warn
(
vd
,
"DirectXCreateWindow create window FAILED (err=%lu)"
,
GetLastError
()
);
return
VLC_EGENERIC
;
return
VLC_EGENERIC
;
}
}
...
@@ -610,20 +582,21 @@ static int DirectXCreateWindow( event_thread_t *p_event )
...
@@ -610,20 +582,21 @@ static int DirectXCreateWindow( event_thread_t *p_event )
/* Create video sub-window. This sub window will always exactly match
/* Create video sub-window. This sub window will always exactly match
* the size of the video, which allows us to use crazy overlay colorkeys
* the size of the video, which allows us to use crazy overlay colorkeys
* without having them shown outside of the video area. */
* without having them shown outside of the video area. */
/* FIXME vd->source.i_width/i_height seems wrong */
p_event
->
hvideownd
=
p_event
->
hvideownd
=
CreateWindow
(
_T
(
"VLC DirectX video"
),
_T
(
""
),
/* window class */
CreateWindow
(
_T
(
"VLC DirectX video"
),
_T
(
""
),
/* window class */
WS_CHILD
,
/* window style, not visible initially */
WS_CHILD
,
/* window style, not visible initially */
0
,
0
,
0
,
0
,
p_vout
->
render
.
i_width
,
/* default width */
vd
->
source
.
i_width
,
/* default width */
p_vout
->
render
.
i_height
,
/* default height */
vd
->
source
.
i_height
,
/* default height */
p_event
->
hwnd
,
/* parent window */
p_event
->
hwnd
,
/* parent window */
NULL
,
hInstance
,
NULL
,
hInstance
,
(
LPVOID
)
p_event
);
/* send
p_vout
to WM_CREATE */
(
LPVOID
)
p_event
);
/* send
vd
to WM_CREATE */
if
(
!
p_event
->
hvideownd
)
if
(
!
p_event
->
hvideownd
)
msg_Warn
(
p_vout
,
"can't create video sub-window"
);
msg_Warn
(
vd
,
"can't create video sub-window"
);
else
else
msg_Dbg
(
p_vout
,
"created video sub-window"
);
msg_Dbg
(
vd
,
"created video sub-window"
);
/* Now display the window */
/* Now display the window */
ShowWindow
(
p_event
->
hwnd
,
SW_SHOW
);
ShowWindow
(
p_event
->
hwnd
,
SW_SHOW
);
...
@@ -638,16 +611,17 @@ static int DirectXCreateWindow( event_thread_t *p_event )
...
@@ -638,16 +611,17 @@ static int DirectXCreateWindow( event_thread_t *p_event )
*****************************************************************************/
*****************************************************************************/
static
void
DirectXCloseWindow
(
event_thread_t
*
p_event
)
static
void
DirectXCloseWindow
(
event_thread_t
*
p_event
)
{
{
vout_
thread_t
*
p_vout
=
p_event
->
p_vout
;
vout_
display_t
*
vd
=
p_event
->
vd
;
msg_Dbg
(
p_vout
,
"DirectXCloseWindow"
);
msg_Dbg
(
vd
,
"DirectXCloseWindow"
);
DestroyWindow
(
p_event
->
hwnd
);
DestroyWindow
(
p_event
->
hwnd
);
if
(
p_event
->
hfswnd
)
DestroyWindow
(
p_event
->
hfswnd
);
if
(
p_event
->
hfswnd
)
DestroyWindow
(
p_event
->
hfswnd
);
#ifdef MODULE_NAME_IS_direct3d
#ifdef MODULE_NAME_IS_direct3d
if
(
!
p_event
->
use_desktop
)
if
(
!
p_event
->
use_desktop
)
#endif
#endif
vout_
window_Delete
(
p_event
->
parent_window
);
vout_
display_DeleteWindow
(
vd
,
p_event
->
parent_window
);
p_event
->
hwnd
=
NULL
;
p_event
->
hwnd
=
NULL
;
/* We don't unregister the Window Class because it could lead to race
/* We don't unregister the Window Class because it could lead to race
...
@@ -673,7 +647,7 @@ static long FAR PASCAL DirectXEventProc( HWND hwnd, UINT message,
...
@@ -673,7 +647,7 @@ static long FAR PASCAL DirectXEventProc( HWND hwnd, UINT message,
if
(
message
==
WM_CREATE
)
if
(
message
==
WM_CREATE
)
{
{
/* Store
p_vout
for future use */
/* Store
vd
for future use */
p_event
=
(
event_thread_t
*
)((
CREATESTRUCT
*
)
lParam
)
->
lpCreateParams
;
p_event
=
(
event_thread_t
*
)((
CREATESTRUCT
*
)
lParam
)
->
lpCreateParams
;
SetWindowLongPtr
(
hwnd
,
GWLP_USERDATA
,
(
LONG_PTR
)
p_event
);
SetWindowLongPtr
(
hwnd
,
GWLP_USERDATA
,
(
LONG_PTR
)
p_event
);
return
TRUE
;
return
TRUE
;
...
@@ -689,14 +663,14 @@ static long FAR PASCAL DirectXEventProc( HWND hwnd, UINT message,
...
@@ -689,14 +663,14 @@ static long FAR PASCAL DirectXEventProc( HWND hwnd, UINT message,
return
DefWindowProc
(
hwnd
,
message
,
wParam
,
lParam
);
return
DefWindowProc
(
hwnd
,
message
,
wParam
,
lParam
);
}
}
}
}
vout_
thread_t
*
p_vout
=
p_event
->
p_vout
;
vout_
display_t
*
vd
=
p_event
->
vd
;
#ifndef UNDER_CE
#ifndef UNDER_CE
/* Catch the screensaver and the monitor turn-off */
/* Catch the screensaver and the monitor turn-off */
if
(
message
==
WM_SYSCOMMAND
&&
if
(
message
==
WM_SYSCOMMAND
&&
(
(
wParam
&
0xFFF0
)
==
SC_SCREENSAVE
||
(
wParam
&
0xFFF0
)
==
SC_MONITORPOWER
)
)
(
(
wParam
&
0xFFF0
)
==
SC_SCREENSAVE
||
(
wParam
&
0xFFF0
)
==
SC_MONITORPOWER
)
)
{
{
//if(
p_vout ) msg_Dbg( p_vout
, "WinProc WM_SYSCOMMAND screensaver" );
//if(
vd ) msg_Dbg( vd
, "WinProc WM_SYSCOMMAND screensaver" );
return
0
;
/* this stops them from happening */
return
0
;
/* this stops them from happening */
}
}
#endif
#endif
...
@@ -751,24 +725,19 @@ static long FAR PASCAL DirectXEventProc( HWND hwnd, UINT message,
...
@@ -751,24 +725,19 @@ static long FAR PASCAL DirectXEventProc( HWND hwnd, UINT message,
{
{
case
WM_WINDOWPOSCHANGED
:
case
WM_WINDOWPOSCHANGED
:
UpdateRects
(
p_vout
,
true
);
vlc_mutex_lock
(
&
p_event
->
lock
);
p_event
->
has_moved
=
true
;
vlc_mutex_unlock
(
&
p_event
->
lock
);
return
0
;
return
0
;
/* the user wants to close the window */
/* the user wants to close the window */
case
WM_CLOSE
:
case
WM_CLOSE
:
{
vout_display_SendEventClose
(
vd
);
playlist_t
*
p_playlist
=
pl_Hold
(
p_vout
);
if
(
p_playlist
)
{
playlist_Stop
(
p_playlist
);
pl_Release
(
p_vout
);
}
return
0
;
return
0
;
}
/* the window has been closed so shut down everything now */
/* the window has been closed so shut down everything now */
case
WM_DESTROY
:
case
WM_DESTROY
:
msg_Dbg
(
p_vout
,
"WinProc WM_DESTROY"
);
msg_Dbg
(
vd
,
"WinProc WM_DESTROY"
);
/* just destroy the window */
/* just destroy the window */
PostQuitMessage
(
0
);
PostQuitMessage
(
0
);
return
0
;
return
0
;
...
@@ -776,14 +745,15 @@ static long FAR PASCAL DirectXEventProc( HWND hwnd, UINT message,
...
@@ -776,14 +745,15 @@ static long FAR PASCAL DirectXEventProc( HWND hwnd, UINT message,
case
WM_SYSCOMMAND
:
case
WM_SYSCOMMAND
:
switch
(
wParam
)
switch
(
wParam
)
{
{
case
IDM_TOGGLE_ON_TOP
:
/* toggle the "on top" status */
case
IDM_TOGGLE_ON_TOP
:
/* toggle the "on top" status */
{
{
msg_Dbg
(
p_vout
,
"WinProc WM_SYSCOMMAND: IDM_TOGGLE_ON_TOP"
);
msg_Dbg
(
vd
,
"WinProc WM_SYSCOMMAND: IDM_TOGGLE_ON_TOP"
);
HMENU
hMenu
=
GetSystemMenu
(
vd
->
sys
->
hwnd
,
FALSE
);
/* Change the current value */
vout_display_SendEventOnTop
(
vd
,
(
GetMenuState
(
hMenu
,
IDM_TOGGLE_ON_TOP
,
MF_BYCOMMAND
)
&
MF_CHECKED
)
==
0
);
var_ToggleBool
(
p_vout
,
"video-on-top"
);
return
0
;
return
0
;
}
}
default:
break
;
}
}
break
;
break
;
...
@@ -816,13 +786,11 @@ static long FAR PASCAL DirectXEventProc( HWND hwnd, UINT message,
...
@@ -816,13 +786,11 @@ static long FAR PASCAL DirectXEventProc( HWND hwnd, UINT message,
GXResume
();
GXResume
();
#endif
#endif
#ifdef UNDER_CE
#ifdef UNDER_CE
/* FIXME vd->cfg is not lock[ed/able] */
#warning "FIXME: race condition"
if
(
p_event
->
hparent
&&
if
(
p_event
->
hparent
&&
hwnd
!=
p_event
->
hfswnd
&&
p_vout
->
b_fullscreen
)
hwnd
!=
p_event
->
hfswnd
&&
vd
->
cfg
->
is_fullscreen
)
{
vout_display_SendEventFullscreen
(
vd
,
false
);
vlc_mutex_lock
(
&
p_event
->
lock
);
p_event
->
i_changes
|=
VOUT_FULLSCREEN_CHANGE
;
vlc_mutex_unlock
(
&
p_event
->
lock
);
}
if
(
hwnd
==
p_event
->
hfswnd
)
if
(
hwnd
==
p_event
->
hfswnd
)
{
{
...
@@ -839,7 +807,7 @@ static long FAR PASCAL DirectXEventProc( HWND hwnd, UINT message,
...
@@ -839,7 +807,7 @@ static long FAR PASCAL DirectXEventProc( HWND hwnd, UINT message,
return
0
;
return
0
;
default:
default:
//msg_Dbg(
p_vout
, "WinProc WM Default %i", message );
//msg_Dbg(
vd
, "WinProc WM Default %i", message );
break
;
break
;
}
}
...
@@ -915,10 +883,7 @@ static int DirectXConvertKey( int i_key )
...
@@ -915,10 +883,7 @@ static int DirectXConvertKey( int i_key )
void
EventThreadMouseAutoHide
(
event_thread_t
*
p_event
)
void
EventThreadMouseAutoHide
(
event_thread_t
*
p_event
)
{
{
vout_thread_t
*
p_vout
=
p_event
->
p_vout
;
if
(
!
p_event
->
b_cursor_hidden
&&
if
(
p_vout
->
b_fullscreen
&&
!
p_event
->
b_cursor_hidden
&&
(
mdate
()
-
p_event
->
i_lastmoved
)
>
p_event
->
i_mouse_hide_timeout
)
(
mdate
()
-
p_event
->
i_lastmoved
)
>
p_event
->
i_mouse_hide_timeout
)
{
{
/* Hide the cursor only if it is inside our window */
/* Hide the cursor only if it is inside our window */
...
@@ -942,7 +907,7 @@ void EventThreadMouseShow( event_thread_t *p_event )
...
@@ -942,7 +907,7 @@ void EventThreadMouseShow( event_thread_t *p_event )
}
}
void
EventThreadUpdateTitle
(
event_thread_t
*
p_event
,
const
char
*
psz_fallback
)
void
EventThreadUpdateTitle
(
event_thread_t
*
p_event
,
const
char
*
psz_fallback
)
{
{
char
*
psz_title
=
var_GetNonEmptyString
(
p_event
->
p_vout
,
"video-title"
);
char
*
psz_title
=
var_GetNonEmptyString
(
p_event
->
vd
,
"video-title"
);
if
(
!
psz_title
)
if
(
!
psz_title
)
psz_title
=
strdup
(
psz_fallback
);
psz_title
=
strdup
(
psz_fallback
);
if
(
!
psz_title
)
if
(
!
psz_title
)
...
@@ -955,15 +920,6 @@ void EventThreadUpdateTitle( event_thread_t *p_event, const char *psz_fallback )
...
@@ -955,15 +920,6 @@ void EventThreadUpdateTitle( event_thread_t *p_event, const char *psz_fallback )
PostMessage
(
p_event
->
hwnd
,
WM_VLC_CHANGE_TEXT
,
0
,
0
);
PostMessage
(
p_event
->
hwnd
,
WM_VLC_CHANGE_TEXT
,
0
,
0
);
}
}
unsigned
EventThreadRetreiveChanges
(
event_thread_t
*
p_event
)
{
vlc_mutex_lock
(
&
p_event
->
lock
);
unsigned
i_changes
=
p_event
->
i_changes
;
p_event
->
i_changes
=
0
;
vlc_mutex_unlock
(
&
p_event
->
lock
);
return
i_changes
;
}
int
EventThreadGetWindowStyle
(
event_thread_t
*
p_event
)
int
EventThreadGetWindowStyle
(
event_thread_t
*
p_event
)
{
{
/* No need to lock, it is serialized by EventThreadStart */
/* No need to lock, it is serialized by EventThreadStart */
...
@@ -986,14 +942,33 @@ void EventThreadUpdateWindowPosition( event_thread_t *p_event, bool *pb_changed,
...
@@ -986,14 +942,33 @@ void EventThreadUpdateWindowPosition( event_thread_t *p_event, bool *pb_changed,
vlc_mutex_unlock
(
&
p_event
->
lock
);
vlc_mutex_unlock
(
&
p_event
->
lock
);
}
}
void
EventThreadUpdateSourceAndPlace
(
event_thread_t
*
p_event
,
const
video_format_t
*
p_source
,
const
vout_display_place_t
*
p_place
)
{
vlc_mutex_lock
(
&
p_event
->
lock
);
p_event
->
source
=
*
p_source
;
p_event
->
place
=
*
p_place
;
vlc_mutex_unlock
(
&
p_event
->
lock
);
}
void
EventThreadUseOverlay
(
event_thread_t
*
p_event
,
bool
b_used
)
void
EventThreadUseOverlay
(
event_thread_t
*
p_event
,
bool
b_used
)
{
{
vlc_mutex_lock
(
&
p_event
->
lock
);
vlc_mutex_lock
(
&
p_event
->
lock
);
p_event
->
use_overlay
=
b_used
;
p_event
->
use_overlay
=
b_used
;
vlc_mutex_unlock
(
&
p_event
->
lock
);
vlc_mutex_unlock
(
&
p_event
->
lock
);
}
}
bool
EventThreadGetAndResetHasMoved
(
event_thread_t
*
p_event
)
{
vlc_mutex_lock
(
&
p_event
->
lock
);
const
bool
has_moved
=
p_event
->
has_moved
;
p_event
->
has_moved
=
false
;
vlc_mutex_unlock
(
&
p_event
->
lock
);
return
has_moved
;
}
event_thread_t
*
EventThreadCreate
(
vout_
thread_t
*
p_vout
,
const
vout_window_cfg_t
*
p_wnd_cfg
)
event_thread_t
*
EventThreadCreate
(
vout_
display_t
*
vd
)
{
{
/* Create the Vout EventThread, this thread is created by us to isolate
/* Create the Vout EventThread, this thread is created by us to isolate
* the Win32 PeekMessage function calls. We want to do this because
* the Win32 PeekMessage function calls. We want to do this because
...
@@ -1002,22 +977,23 @@ event_thread_t *EventThreadCreate( vout_thread_t *p_vout, const vout_window_cfg_
...
@@ -1002,22 +977,23 @@ event_thread_t *EventThreadCreate( vout_thread_t *p_vout, const vout_window_cfg_
* Vout EventThread will take care of the creation of the video
* Vout EventThread will take care of the creation of the video
* window (because PeekMessage has to be called from the same thread which
* window (because PeekMessage has to be called from the same thread which
* created the window). */
* created the window). */
msg_Dbg
(
p_vout
,
"creating Vout EventThread"
);
msg_Dbg
(
vd
,
"creating Vout EventThread"
);
event_thread_t
*
p_event
=
malloc
(
sizeof
(
*
p_event
)
);
event_thread_t
*
p_event
=
malloc
(
sizeof
(
*
p_event
)
);
if
(
!
p_event
)
if
(
!
p_event
)
return
NULL
;
return
NULL
;
p_event
->
p_vout
=
p_vout
;
p_event
->
vd
=
vd
;
vlc_mutex_init
(
&
p_event
->
lock
);
vlc_mutex_init
(
&
p_event
->
lock
);
vlc_cond_init
(
&
p_event
->
wait
);
vlc_cond_init
(
&
p_event
->
wait
);
p_event
->
b_cursor_hidden
=
false
;
p_event
->
b_cursor_hidden
=
false
;
p_event
->
i_lastmoved
=
mdate
();
p_event
->
i_lastmoved
=
mdate
();
p_event
->
i_mouse_hide_timeout
=
p_event
->
i_mouse_hide_timeout
=
var_GetInteger
(
p_vout
,
"mouse-hide-timeout"
)
*
1000
;
var_GetInteger
(
vd
,
"mouse-hide-timeout"
)
*
1000
;
p_event
->
psz_title
=
NULL
;
p_event
->
psz_title
=
NULL
;
p_event
->
wnd_cfg
=
*
p_wnd_cfg
;
p_event
->
source
=
vd
->
source
;
vout_display_PlacePicture
(
&
p_event
->
place
,
&
vd
->
source
,
vd
->
cfg
,
true
);
return
p_event
;
return
p_event
;
}
}
...
@@ -1033,8 +1009,9 @@ int EventThreadStart( event_thread_t *p_event, event_hwnd_t *p_hwnd, const event
...
@@ -1033,8 +1009,9 @@ int EventThreadStart( event_thread_t *p_event, event_hwnd_t *p_hwnd, const event
{
{
p_event
->
use_desktop
=
p_cfg
->
use_desktop
;
p_event
->
use_desktop
=
p_cfg
->
use_desktop
;
p_event
->
use_overlay
=
p_cfg
->
use_overlay
;
p_event
->
use_overlay
=
p_cfg
->
use_overlay
;
p_event
->
wnd_cfg
=
p_cfg
->
win
;
p_event
->
i_changes
=
0
;
p_event
->
has_moved
=
false
;
p_event
->
b_ready
=
false
;
p_event
->
b_ready
=
false
;
p_event
->
b_done
=
false
;
p_event
->
b_done
=
false
;
...
@@ -1043,7 +1020,7 @@ int EventThreadStart( event_thread_t *p_event, event_hwnd_t *p_hwnd, const event
...
@@ -1043,7 +1020,7 @@ int EventThreadStart( event_thread_t *p_event, event_hwnd_t *p_hwnd, const event
if
(
vlc_clone
(
&
p_event
->
thread
,
EventThread
,
p_event
,
if
(
vlc_clone
(
&
p_event
->
thread
,
EventThread
,
p_event
,
VLC_THREAD_PRIORITY_LOW
)
)
VLC_THREAD_PRIORITY_LOW
)
)
{
{
msg_Err
(
p_event
->
p_vout
,
"cannot create Vout EventThread"
);
msg_Err
(
p_event
->
vd
,
"cannot create Vout EventThread"
);
return
VLC_EGENERIC
;
return
VLC_EGENERIC
;
}
}
...
@@ -1059,12 +1036,10 @@ int EventThreadStart( event_thread_t *p_event, event_hwnd_t *p_hwnd, const event
...
@@ -1059,12 +1036,10 @@ int EventThreadStart( event_thread_t *p_event, event_hwnd_t *p_hwnd, const event
p_event
->
b_ready
=
false
;
p_event
->
b_ready
=
false
;
return
VLC_EGENERIC
;
return
VLC_EGENERIC
;
}
}
msg_Dbg
(
p_event
->
p_vout
,
"Vout EventThread running"
);
msg_Dbg
(
p_event
->
vd
,
"Vout EventThread running"
);
if
(
!
p_event
->
use_desktop
)
/* */
p_hwnd
->
parent_window
=
p_event
->
parent_window
;
p_hwnd
->
parent_window
=
p_event
->
parent_window
;
else
p_hwnd
->
parent_window
=
NULL
;
p_hwnd
->
hparent
=
p_event
->
hparent
;
p_hwnd
->
hparent
=
p_event
->
hparent
;
p_hwnd
->
hwnd
=
p_event
->
hwnd
;
p_hwnd
->
hwnd
=
p_event
->
hwnd
;
p_hwnd
->
hvideownd
=
p_event
->
hvideownd
;
p_hwnd
->
hvideownd
=
p_event
->
hvideownd
;
...
...
modules/video_output/msw/events.h
View file @
f6d06e15
...
@@ -32,6 +32,8 @@ typedef struct event_thread_t event_thread_t;
...
@@ -32,6 +32,8 @@ typedef struct event_thread_t event_thread_t;
typedef
struct
{
typedef
struct
{
bool
use_desktop
;
/* direct3d */
bool
use_desktop
;
/* direct3d */
bool
use_overlay
;
/* directx */
bool
use_overlay
;
/* directx */
vout_window_cfg_t
win
;
}
event_cfg_t
;
}
event_cfg_t
;
typedef
struct
{
typedef
struct
{
...
@@ -42,7 +44,7 @@ typedef struct {
...
@@ -42,7 +44,7 @@ typedef struct {
HWND
hfswnd
;
HWND
hfswnd
;
}
event_hwnd_t
;
}
event_hwnd_t
;
event_thread_t
*
EventThreadCreate
(
vout_
thread_t
*
,
const
vout_window_cfg_t
*
);
event_thread_t
*
EventThreadCreate
(
vout_
display_t
*
);
void
EventThreadDestroy
(
event_thread_t
*
);
void
EventThreadDestroy
(
event_thread_t
*
);
int
EventThreadStart
(
event_thread_t
*
,
event_hwnd_t
*
,
const
event_cfg_t
*
);
int
EventThreadStart
(
event_thread_t
*
,
event_hwnd_t
*
,
const
event_cfg_t
*
);
void
EventThreadStop
(
event_thread_t
*
);
void
EventThreadStop
(
event_thread_t
*
);
...
@@ -50,8 +52,12 @@ void EventThreadStop( event_thread_t * );
...
@@ -50,8 +52,12 @@ void EventThreadStop( event_thread_t * );
void
EventThreadMouseAutoHide
(
event_thread_t
*
);
void
EventThreadMouseAutoHide
(
event_thread_t
*
);
void
EventThreadMouseShow
(
event_thread_t
*
);
void
EventThreadMouseShow
(
event_thread_t
*
);
void
EventThreadUpdateTitle
(
event_thread_t
*
,
const
char
*
psz_fallback
);
void
EventThreadUpdateTitle
(
event_thread_t
*
,
const
char
*
psz_fallback
);
unsigned
EventThreadRetreiveChanges
(
event_thread_t
*
);
int
EventThreadGetWindowStyle
(
event_thread_t
*
);
int
EventThreadGetWindowStyle
(
event_thread_t
*
);
void
EventThreadUpdateWindowPosition
(
event_thread_t
*
,
bool
*
pb_changed
,
void
EventThreadUpdateWindowPosition
(
event_thread_t
*
,
bool
*
pb_changed
,
int
x
,
int
y
,
int
w
,
int
h
);
int
x
,
int
y
,
int
w
,
int
h
);
void
EventThreadUpdateSourceAndPlace
(
event_thread_t
*
p_event
,
const
video_format_t
*
p_source
,
const
vout_display_place_t
*
p_place
);
void
EventThreadUseOverlay
(
event_thread_t
*
,
bool
b_used
);
void
EventThreadUseOverlay
(
event_thread_t
*
,
bool
b_used
);
bool
EventThreadGetAndResetHasMoved
(
event_thread_t
*
);
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment