Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in
Toggle navigation
V
vlc-gpu
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-gpu
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
Show 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. */
/*
* Fullscreen change
*/
if
(
p_vout
->
i_changes
&
VOUT_FULLSCREEN_CHANGE
||
p_vout
->
p_sys
->
i_changes
&
VOUT_FULLSCREEN_CHANGE
)
{
Win32ToggleFullscreen
(
p_vout
);
p_vout
->
i_changes
&=
~
VOUT_FULLSCREEN_CHANGE
;
/* Pointer change */
p_vout
->
p_sys
->
i_changes
&=
~
VOUT_FULLSCREEN_CHANGE
;
EventThreadMouseAutoHide
(
sys
->
event
);
}
/*
* 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
,
&
p_taskbl
)
)
&
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
;
return
VLC_SUCCESS
;
default:
return
VLC_EGENERIC
;
}
}
/* Internal wrapper over GetWindowPlacement */
#ifdef MODULE_NAME_IS_direct3d
static
WINDOWPLACEMENT
getWindowState
(
HWND
hwnd
)
if
(
sys
->
use_desktop
&&
is_fullscreen
)
{
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
;
}
int
CommonControl
(
vout_display_t
*
vd
,
int
query
,
va_list
args
)
{
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
);
}
}
/* Update the object variable and trigger callback */
case
VOUT_DISPLAY_RESET_PICTURES
:
var_SetBool
(
p_vout
,
"fullscreen"
,
p_vout
->
b_fullscreen
);
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
);
Direct3DClose
(
vd
);
CommonClean
(
p_vout
);
CommonClean
(
vd
);
Direct3D
Release
(
p_vout
);
Direct3D
Destroy
(
vd
);
free
(
p_vout
->
p_
sys
);
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
);
}
if
(
sys
->
is_first_display
)
{
/* Video window is initially hidden, show it now since we got a
* picture to show.
*/
SetWindowPos
(
vd
->
sys
->
hvideownd
,
0
,
0
,
0
,
0
,
0
,
SWP_ASYNCWINDOWPOS
|
SWP_FRAMECHANGED
|
SWP_SHOWWINDOW
|
SWP_NOMOVE
|
SWP_NOSIZE
|
SWP_NOZORDER
);
sys
->
is_first_display
=
false
;
}
}
/* Initialize the output structure.
#if 0
* Since Direct3D can do rescaling for us, stick to the default
VLC_UNUSED(picture);
* coordinates and aspect. */
#else
p_vout
->
output
.
i_width
=
p_vout
->
render
.
i_width
;
/* XXX See Prepare() */
p_vout
->
output
.
i_height
=
p_vout
->
render
.
i_height
;
picture_Release
(
picture
);
p_vout
->
output
.
i_aspect
=
p_vout
->
render
.
i_aspect
;
#endif
p_vout
->
fmt_out
=
p_vout
->
fmt_in
;
}
UpdateRects
(
p_vout
,
true
);
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
;
/* create picture pool */
WINDOWPLACEMENT
wp
=
{
.
length
=
sizeof
(
wp
),
};
p_vout
->
output
.
i_chroma
=
0
;
GetWindowPlacement
(
sys
->
hparent
?
sys
->
hparent
:
sys
->
hwnd
,
&
wp
);
i_ret
=
Direct3DCreatePictures
(
p_vout
,
1
);
sys
->
desktop_save
.
win
=
wp
.
rcNormalPosition
;
if
(
i_ret
)
{
msg_Err
(
p_vout
,
"Direct3D picture pool initialization failed !"
);
return
i_ret
;
}
}
/* create scene */
/* */
i_ret
=
Direct3DCreateScene
(
p_vout
);
Direct3DClose
(
vd
);
if
(
i_ret
)
{
EventThreadStop
(
sys
->
event
);
msg_Err
(
p_vout
,
"Direct3D scene initialization failed !"
);
Direct3DReleasePictures
(
p_vout
);
/* */
return
i_ret
;
vlc_mutex_lock
(
&
sys
->
lock
);
sys
->
use_desktop
=
sys
->
desktop_requested
;
sys
->
ch_desktop
=
false
;
vlc_mutex_unlock
(
&
sys
->
lock
);
/* */
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
;
}
}
/* Change the window title bar text */
event_hwnd_t
hwnd
;
EventThreadUpdateTitle
(
p_sys
->
p_event
,
VOUT_TITLE
" (Direct3D output)"
);
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
);
p_vout
->
fmt_out
.
i_chroma
=
p_vout
->
output
.
i_chroma
;
/* */
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
(
p_vout
);
CommonManage
(
vd
);
/* 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;
}
}
#endif
/*
* 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
;
}
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
* It initializes an instance of Direct3D9
** 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
,
static
int
Direct3DCreate
(
vout_display_t
*
vd
)
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
*****************************************************************************
* This function initialize Direct3D and analyze available resources from
* 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
,
D3DDEVTYPE_HAL
,
sys
->
hvideownd
,
D3DCREATE_SOFTWARE_VERTEXPROCESSING
|
D3DCREATE_SOFTWARE_VERTEXPROCESSING
|
D3DCREATE_MULTITHREADED
,
D3DCREATE_MULTITHREADED
,
&
p_sys
->
d3dpp
,
&
p_
d3ddev
);
&
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
;
return
VLC_EGENERIC
;
}
}
// re-create them
if
(
Direct3DCreatePictures
(
p_vout
,
1
)
||
Direct3DCreateScene
(
p_vout
))
{
UpdateRects
(
vd
,
NULL
,
NULL
,
true
);
msg_Dbg
(
p_vout
,
"%s failed !"
,
__FUNCTION__
);
/* re-create them */
if
(
Direct3DCreateResources
(
vd
,
&
vd
->
fmt
))
{
msg_Dbg
(
vd
,
"%s failed !"
,
__FUNCTION__
);
return
VLC_EGENERIC
;
return
VLC_EGENERIC
;
}
}
return
VLC_SUCCESS
;
return
VLC_SUCCESS
;
}
}
static
int
Direct3DCheckFormat
(
vout_thread_t
*
p_vout
,
/* */
D3DFORMAT
target
,
D3DFORMAT
format
)
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
)
{
{
vout_sys_t
*
p_sys
=
p_vout
->
p_sys
;
if
(
Direct3DCreatePool
(
vd
,
fmt
))
{
LPDIRECT3D9
p_d3dobj
=
p_sys
->
p_d3dobj
;
msg_Err
(
vd
,
"Direct3D picture pool initialization failed"
);
return
VLC_EGENERIC
;
}
if
(
Direct3DCreateScene
(
vd
))
{
msg_Err
(
vd
,
"Direct3D scene initialization failed !"
);
return
VLC_EGENERIC
;
}
return
VLC_SUCCESS
;
}
/**
* It destroys the picture and scene resources.
*/
static
void
Direct3DDestroyResources
(
vout_display_t
*
vd
)
{
Direct3DDestroyScene
(
vd
);
Direct3DDestroyPool
(
vd
);
}
/**
* It tests if the conversion from src to dst is supported.
*/
static
int
Direct3DCheckConversion
(
vout_display_t
*
vd
,
D3DFORMAT
src
,
D3DFORMAT
dst
)
{
vout_display_sys_t
*
sys
=
vd
->
sys
;
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
* 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
);
static
int
Direct3DLockSurface
(
picture_t
*
picture
)
if
(
!
p_format
)
{
{
msg_Err
(
p_vout
,
"surface pixel format is not supported."
);
/* Lock the surface to get a valid pointer to the picture buffer */
return
VLC_EGENERIC
;
D3DLOCKED_RECT
d3drect
;
}
HRESULT
hr
=
IDirect3DSurface9_LockRect
(
picture
->
p_sys
->
surface
,
&
d3drect
,
NULL
,
0
);
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
))
{
if
(
FAILED
(
hr
))
{
msg_Err
(
p_vout
,
"Failed to create picture surface. (hr=0x%lx)"
,
hr
);
//msg_Dbg(vd, "%s:%d (hr=0x%0lX)", __FUNCTION__, __LINE__, hr);
Direct3DReleasePictures
(
p_vout
);
return
VLC_EGENERIC
;
return
VLC_EGENERIC
;
}
}
/* fill surface with black color */
/* fill in buffer info in first plane */
IDirect3DDevice9_ColorFill
(
p_d3ddev
,
p_d3dsurf
,
NULL
,
D3DCOLOR_ARGB
(
0xFF
,
0
,
0
,
0
));
picture
->
p
->
p_pixels
=
d3drect
.
pBits
;
picture
->
p
->
i_pitch
=
d3drect
.
Pitch
;
/* */
/* Fill chroma planes for planar YUV */
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
);
if
(
picture
->
format
.
i_chroma
==
VLC_CODEC_I420
||
picture
->
format
.
i_chroma
==
VLC_CODEC_J420
||
/* assign surface to internal structure */
picture
->
format
.
i_chroma
==
VLC_CODEC_YV12
)
{
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
;
for
(
int
n
=
1
;
n
<
picture
->
i_planes
;
n
++
)
{
p
->
i_lines
=
const
plane_t
*
o
=
&
picture
->
p
[
n
-
1
];
p
->
i_visible_lines
=
p_vout
->
output
.
i_height
/
d
;
plane_t
*
p
=
&
picture
->
p
[
n
];
p
->
i_visible_pitch
=
p_vout
->
output
.
i_width
/
d
;
p
->
p_pixels
=
o
->
p_pixels
+
o
->
i_lines
*
o
->
i_pitch
;
p
->
i_pitch
=
d3drect
.
Pitch
/
2
;
}
}
break
;
/* The d3d buffer is always allocated as YV12 */
default:
if
(
vlc_fourcc_AreUVPlanesSwapped
(
picture
->
format
.
i_chroma
,
VLC_CODEC_YV12
))
{
Direct3DReleasePictures
(
p_vout
);
uint8_t
*
p_tmp
=
picture
->
p
[
1
].
p_pixels
;
return
VLC_EGENERIC
;
picture
->
p
[
1
].
p_pixels
=
picture
->
p
[
2
].
p_pixels
;
picture
->
p
[
2
].
p_pixels
=
p_tmp
;
}
}
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
;
return
VLC_SUCCESS
;
}
}
/**
/*****************************************************************************
* It unlocks the surface associated to the picture.
* Direct3DReleasePictures: destroy a picture vector
*/
*****************************************************************************
static
void
Direct3DUnlockSurface
(
picture_t
*
picture
)
* release all video resources used for pictures
*****************************************************************************/
static
void
Direct3DReleasePictures
(
vout_thread_t
*
p_vout
)
{
{
size_t
i_num_pics
=
I_OUTPUTPICTURES
;
/* Unlock the Surface */
size_t
c
;
HRESULT
hr
=
IDirect3DSurface9_UnlockRect
(
picture
->
p_sys
->
surface
);
for
(
c
=
0
;
c
<
i_num_pics
;
c
++
)
{
if
(
FAILED
(
hr
))
{
picture_t
*
p_pic
=
&
p_vout
->
p_picture
[
c
];
//msg_Dbg(vd, "%s:%d (hr=0x%0lX)", __FUNCTION__, __LINE__, hr);
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
* It creates the pool of picture (only 1).
*****************************************************************************
*
* This function locks a surface and get the surface descriptor which amongst
* Each picture has an associated offscreen surface in video memory
* other things has the pointer to the picture data.
* 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
(
vout_thread_t
*
p_vout
,
picture_t
*
p_pic
)
* 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
;
}
/* Lock the surface to get a valid pointer to the picture buffer */
fmt
->
i_chroma
=
d3dfmt
->
fourcc
;
D3DLOCKED_RECT
d3drect
;
fmt
->
i_rmask
=
d3dfmt
->
rmask
;
HRESULT
hr
=
IDirect3DSurface9_LockRect
(
p_d3dsurf
,
&
d3drect
,
NULL
,
0
);
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
));
/* fill in buffer info in first plane */
/* Create the associated picture */
p_pic
->
p
->
p_pixels
=
d3drect
.
pBits
;
picture_resource_t
*
rsc
=
&
sys
->
resource
;
p_pic
->
p
->
i_pitch
=
d3drect
.
Pitch
;
rsc
->
p_sys
=
malloc
(
sizeof
(
*
rsc
->
p_sys
));
if
(
!
rsc
->
p_sys
)
{
/* Fill chroma planes for planar YUV */
IDirect3DSurface9_Release
(
surface
);
if
(
p_pic
->
format
.
i_chroma
==
VLC_CODEC_I420
||
return
VLC_ENOMEM
;
p_pic
->
format
.
i_chroma
==
VLC_CODEC_J420
||
p_pic
->
format
.
i_chroma
==
VLC_CODEC_YV12
)
{
for
(
int
n
=
1
;
n
<
p_pic
->
i_planes
;
n
++
)
{
const
plane_t
*
o
=
&
p_pic
->
p
[
n
-
1
];
plane_t
*
p
=
&
p_pic
->
p
[
n
];
p
->
p_pixels
=
o
->
p_pixels
+
o
->
i_lines
*
o
->
i_pitch
;
p
->
i_pitch
=
d3drect
.
Pitch
/
2
;
}
}
/* The d3d buffer is always allocated as YV12 */
rsc
->
p_sys
->
surface
=
surface
;
if
(
vlc_fourcc_AreUVPlanesSwapped
(
p_pic
->
format
.
i_chroma
,
VLC_CODEC_YV12
)
)
{
for
(
int
i
=
0
;
i
<
PICTURE_PLANE_MAX
;
i
++
)
{
uint8_t
*
p_tmp
=
p_pic
->
p
[
1
].
p_pixels
;
rsc
->
p
[
i
].
p_pixels
=
NULL
;
p_pic
->
p
[
1
].
p_pixels
=
p_pic
->
p
[
2
].
p_pixels
;
rsc
->
p
[
i
].
i_pitch
=
0
;
p_pic
->
p
[
2
].
p_pixels
=
p_tmp
;
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.
* Direct3DUnlockSurface: Unlock a surface locked by Direct3DLockSurface().
*/
*****************************************************************************/
static
void
Direct3DDestroyPool
(
vout_display_t
*
vd
)
static
int
Direct3DUnlockSurface
(
vout_thread_t
*
p_vout
,
picture_t
*
p_pic
)
{
{
LPDIRECT3DSURFACE9
p_d3dsurf
=
(
LPDIRECT3DSURFACE9
)
p_pic
->
p_
sys
;
vout_display_sys_t
*
sys
=
vd
->
sys
;
if
(
!
p_d3dsurf
)
if
(
sys
->
pool
)
{
return
VLC_EGENERIC
;
picture_resource_t
*
rsc
=
&
sys
->
resource
;
IDirect3DSurface9_Release
(
rsc
->
p_sys
->
surface
);
/* Unlock the Surface */
picture_pool_Delete
(
sys
->
pool
);
HRESULT
hr
=
IDirect3DSurface9_UnlockRect
(
p_d3dsurf
);
if
(
FAILED
(
hr
))
{
msg_Dbg
(
p_vout
,
"%s:%d (hr=0x%0lX)"
,
__FUNCTION__
,
__LINE__
,
hr
);
return
VLC_EGENERIC
;
}
}
return
VLC_SUCCESS
;
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
(
place
.
width
>
0
&&
place
.
height
>
0
)
{
if
(
msg
.
hwnd
==
p_event
->
hvideownd
)
if
(
msg
.
hwnd
==
p_event
->
hvideownd
)
{
{
/* Child window */
/* Child window */
i_x
=
i_y
=
0
;
place
.
x
=
0
;
place
.
y
=
0
;
}
}
const
int
x
=
source
.
i_x_offset
+
if
(
i_width
&&
i_height
)
(
int64_t
)(
GET_X_LPARAM
(
msg
.
lParam
)
-
place
.
x
)
*
source
.
i_width
/
place
.
width
;
{
const
int
y
=
source
.
i_y_offset
+
val
.
i_int
=
(
GET_X_LPARAM
(
msg
.
lParam
)
-
i_x
)
*
(
int64_t
)(
GET_Y_LPARAM
(
msg
.
lParam
)
-
place
.
y
)
*
source
.
i_height
/
place
.
height
;
p_event
->
p_vout
->
fmt_in
.
i_visible_width
/
i_width
+
vout_display_SendEventMouseMoved
(
vd
,
x
,
y
);
p_event
->
p_vout
->
fmt_in
.
i_x_offset
;
var_Set
(
p_event
->
p_vout
,
"mouse-x"
,
val
);
val
.
i_int
=
(
GET_Y_LPARAM
(
msg
.
lParam
)
-
i_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
;
...
@@ -778,12 +747,13 @@ static long FAR PASCAL DirectXEventProc( HWND hwnd, UINT message,
...
@@ -778,12 +747,13 @@ static long FAR PASCAL DirectXEventProc( HWND hwnd, UINT message,
{
{
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,21 +977,22 @@ event_thread_t *EventThreadCreate( vout_thread_t *p_vout, const vout_window_cfg_
...
@@ -1002,21 +977,22 @@ 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