Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in
Toggle navigation
V
vlc
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
0
Issues
0
List
Boards
Labels
Milestones
Redmine
Redmine
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Operations
Operations
Metrics
Environments
Analytics
Analytics
CI / CD
Repository
Value Stream
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
videolan
vlc
Commits
599340cf
Commit
599340cf
authored
Jul 20, 2006
by
Damien Fouilleul
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
- direct3d: new video output module using Direct3D 9 APIs
parent
27c3154a
Changes
7
Show whitespace changes
Inline
Side-by-side
Showing
7 changed files
with
1613 additions
and
86 deletions
+1613
-86
configure.ac
configure.ac
+9
-5
modules/video_output/directx/Modules.am
modules/video_output/directx/Modules.am
+6
-0
modules/video_output/directx/direct3d.c
modules/video_output/directx/direct3d.c
+1499
-0
modules/video_output/directx/directx.c
modules/video_output/directx/directx.c
+15
-2
modules/video_output/directx/events.c
modules/video_output/directx/events.c
+42
-28
modules/video_output/directx/glwin32.c
modules/video_output/directx/glwin32.c
+0
-9
modules/video_output/directx/vout.h
modules/video_output/directx/vout.h
+42
-42
No files found.
configure.ac
View file @
599340cf
...
...
@@ -3908,11 +3908,15 @@ then
AC_CHECK_HEADERS(ddraw.h,
[ VLC_ADD_PLUGINS([vout_directx aout_directx])
VLC_ADD_LDFLAGS([vout_directx],[-lgdi32])
dnl to be moved when dependance is removed
AC_CHECK_HEADERS(GL/gl.h, [
VLC_ADD_PLUGINS([glwin32])
])
AC_CHECK_HEADERS(GL/gl.h,
[
VLC_ADD_PLUGINS([glwin32])
VLC_ADD_LDFLAGS([glwin32],[-lopengl32 -lgdi32])
]) ])
])
AC_CHECK_HEADERS(d3d9.h,
[ VLC_ADD_PLUGINS([direct3d])
VLC_ADD_LDFLAGS([direct3d],[-ld3d9 -lgdi32])
])
else
AC_MSG_CHECKING(for directX headers in ${with_directx})
if test -f ${with_directx}/ddraw.h
...
...
modules/video_output/directx/Modules.am
View file @
599340cf
...
...
@@ -4,6 +4,12 @@ SOURCES_vout_directx = \
events.c \
$(NULL)
SOURCES_direct3d = \
direct3d.c \
vout.h \
events.c \
$(NULL)
SOURCES_glwin32 = \
glwin32.c \
vout.h \
...
...
modules/video_output/directx/direct3d.c
0 → 100755
View file @
599340cf
/*****************************************************************************
* vout.c: Windows DirectX video output display method
*****************************************************************************
* Copyright (C) 2001-2006 the VideoLAN team
*
* Authors: 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.
*****************************************************************************/
/*****************************************************************************
* Preamble:
*
* This plugin will use YUV overlay if supported, using overlay will result in
* the best video quality (hardware filering when rescaling the picture)
* and the fastest display as it requires less processing.
*
* If YUV overlay is not supported this plugin will use RGB offscreen video
* surfaces that will be blitted onto the primary surface (display) to
* effectively display the pictures. This fallback method also enables us to
* display video in window mode.
*
*****************************************************************************/
#include <errno.h>
/* ENOMEM */
#include <stdlib.h>
/* free() */
#include <string.h>
/* strerror() */
#include <vlc/vlc.h>
#include <vlc/intf.h>
#include <vlc/vout.h>
#include <windows.h>
#include <d3d9.h>
#include "vout.h"
/*****************************************************************************
* Local prototypes.
*****************************************************************************/
static
int
OpenVideo
(
vlc_object_t
*
);
static
void
CloseVideo
(
vlc_object_t
*
);
static
int
Init
(
vout_thread_t
*
);
static
void
End
(
vout_thread_t
*
);
static
int
Manage
(
vout_thread_t
*
);
static
void
Display
(
vout_thread_t
*
,
picture_t
*
);
static
int
Direct3DVoutCreate
(
vout_thread_t
*
);
static
void
Direct3DVoutRelease
(
vout_thread_t
*
);
static
int
Direct3DVoutOpen
(
vout_thread_t
*
);
static
void
Direct3DVoutClose
(
vout_thread_t
*
);
static
int
Direct3DVoutResetDevice
(
vout_thread_t
*
,
UINT
,
UINT
);
static
int
Direct3DVoutCreatePictures
(
vout_thread_t
*
,
size_t
);
static
void
Direct3DVoutReleasePictures
(
vout_thread_t
*
);
static
int
Direct3DVoutLockSurface
(
vout_thread_t
*
,
picture_t
*
);
static
int
Direct3DVoutUnlockSurface
(
vout_thread_t
*
,
picture_t
*
);
static
void
Direct3DVoutRenderDefault
(
vout_thread_t
*
,
picture_t
*
);
static
int
Direct3DVoutCreateScene
(
vout_thread_t
*
);
static
void
Direct3DVoutReleaseScene
(
vout_thread_t
*
);
static
void
Direct3DVoutRenderScene
(
vout_thread_t
*
,
picture_t
*
);
/*****************************************************************************
* Module descriptor
*****************************************************************************/
vlc_module_begin
();
set_shortname
(
"Direct3D"
);
set_category
(
CAT_VIDEO
);
set_subcategory
(
SUBCAT_VIDEO_VOUT
);
set_description
(
_
(
"DirectX 3D video output"
)
);
set_capability
(
"video output"
,
150
);
add_shortcut
(
"direct3d"
);
set_callbacks
(
OpenVideo
,
CloseVideo
);
/* FIXME: Hack to avoid unregistering our window class */
linked_with_a_crap_library_which_uses_atexit
(
);
vlc_module_end
();
#if 0 /* FIXME */
/* check if we registered a window class because we need to
* unregister it */
WNDCLASS wndclass;
if( GetClassInfo( GetModuleHandle(NULL), "VLC DirectX", &wndclass ) )
UnregisterClass( "VLC DirectX", GetModuleHandle(NULL) );
#endif
/*****************************************************************************
* CUSTOMVERTEX:
*****************************************************************************
*****************************************************************************/
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)
/*****************************************************************************
* OpenVideo: allocate DirectX video thread output method
*****************************************************************************
* This function allocates and initialize the DirectX vout method.
*****************************************************************************/
static
int
OpenVideo
(
vlc_object_t
*
p_this
)
{
vout_thread_t
*
p_vout
=
(
vout_thread_t
*
)
p_this
;
vlc_value_t
val
;
/* Allocate structure */
p_vout
->
p_sys
=
malloc
(
sizeof
(
vout_sys_t
)
);
if
(
p_vout
->
p_sys
==
NULL
)
{
msg_Err
(
p_vout
,
"out of memory"
);
return
VLC_ENOMEM
;
}
memset
(
p_vout
->
p_sys
,
0
,
sizeof
(
vout_sys_t
)
);
if
(
VLC_SUCCESS
!=
Direct3DVoutCreate
(
p_vout
)
)
{
msg_Err
(
p_vout
,
"Direct3D could not be initialized !"
);
goto
error
;
}
/* Initialisations */
p_vout
->
pf_init
=
Init
;
p_vout
->
pf_end
=
End
;
p_vout
->
pf_manage
=
Manage
;
p_vout
->
pf_render
=
Direct3DVoutRenderScene
;
p_vout
->
pf_display
=
Display
;
p_vout
->
p_sys
->
hwnd
=
p_vout
->
p_sys
->
hvideownd
=
NULL
;
p_vout
->
p_sys
->
hparent
=
p_vout
->
p_sys
->
hfswnd
=
NULL
;
p_vout
->
p_sys
->
i_changes
=
0
;
p_vout
->
p_sys
->
b_wallpaper
=
0
;
vlc_mutex_init
(
p_vout
,
&
p_vout
->
p_sys
->
lock
);
SetRectEmpty
(
&
p_vout
->
p_sys
->
rect_display
);
SetRectEmpty
(
&
p_vout
->
p_sys
->
rect_parent
);
p_vout
->
p_sys
->
b_cursor_hidden
=
0
;
p_vout
->
p_sys
->
i_lastmoved
=
mdate
();
/* Set main window's size */
p_vout
->
p_sys
->
i_window_width
=
p_vout
->
i_window_width
;
p_vout
->
p_sys
->
i_window_height
=
p_vout
->
i_window_height
;
/* Create the DirectXEventThread, this thread is created by us to isolate
* the Win32 PeekMessage function calls. We want to do this because
* Windows can stay blocked inside this call for a long time, and when
* this happens it thus blocks vlc's video_output thread.
* DirectXEventThread will take care of the creation of the video
* window (because PeekMessage has to be called from the same thread which
* created the window). */
msg_Dbg
(
p_vout
,
"creating DirectXEventThread"
);
p_vout
->
p_sys
->
p_event
=
vlc_object_create
(
p_vout
,
sizeof
(
event_thread_t
)
);
p_vout
->
p_sys
->
p_event
->
p_vout
=
p_vout
;
if
(
vlc_thread_create
(
p_vout
->
p_sys
->
p_event
,
"DirectX Events Thread"
,
E_
(
DirectXEventThread
),
0
,
1
)
)
{
msg_Err
(
p_vout
,
"cannot create DirectXEventThread"
);
vlc_object_destroy
(
p_vout
->
p_sys
->
p_event
);
p_vout
->
p_sys
->
p_event
=
NULL
;
goto
error
;
}
if
(
p_vout
->
p_sys
->
p_event
->
b_error
)
{
msg_Err
(
p_vout
,
"DirectXEventThread failed"
);
goto
error
;
}
vlc_object_attach
(
p_vout
->
p_sys
->
p_event
,
p_vout
);
msg_Dbg
(
p_vout
,
"DirectXEventThread running"
);
/* Variable to indicate if the window should be on top of others */
/* Trigger a callback right now */
var_Get
(
p_vout
,
"video-on-top"
,
&
val
);
var_Set
(
p_vout
,
"video-on-top"
,
val
);
/* disable screensaver by temporarily changing system settings */
p_vout
->
p_sys
->
i_spi_lowpowertimeout
=
0
;
p_vout
->
p_sys
->
i_spi_powerofftimeout
=
0
;
p_vout
->
p_sys
->
i_spi_screensavetimeout
=
0
;
var_Get
(
p_vout
,
"disable-screensaver"
,
&
val
);
if
(
val
.
b_bool
)
{
msg_Dbg
(
p_vout
,
"disabling screen saver"
);
SystemParametersInfo
(
SPI_GETLOWPOWERTIMEOUT
,
0
,
&
(
p_vout
->
p_sys
->
i_spi_lowpowertimeout
),
0
);
if
(
0
!=
p_vout
->
p_sys
->
i_spi_lowpowertimeout
)
{
SystemParametersInfo
(
SPI_SETLOWPOWERTIMEOUT
,
0
,
NULL
,
0
);
}
SystemParametersInfo
(
SPI_GETPOWEROFFTIMEOUT
,
0
,
&
(
p_vout
->
p_sys
->
i_spi_powerofftimeout
),
0
);
if
(
0
!=
p_vout
->
p_sys
->
i_spi_powerofftimeout
)
{
SystemParametersInfo
(
SPI_SETPOWEROFFTIMEOUT
,
0
,
NULL
,
0
);
}
SystemParametersInfo
(
SPI_GETSCREENSAVETIMEOUT
,
0
,
&
(
p_vout
->
p_sys
->
i_spi_screensavetimeout
),
0
);
if
(
0
!=
p_vout
->
p_sys
->
i_spi_screensavetimeout
)
{
SystemParametersInfo
(
SPI_SETSCREENSAVETIMEOUT
,
0
,
NULL
,
0
);
}
}
return
VLC_SUCCESS
;
error:
CloseVideo
(
VLC_OBJECT
(
p_vout
)
);
return
VLC_EGENERIC
;
}
/*****************************************************************************
* CloseVideo: destroy Sys video thread output method
*****************************************************************************
* Terminate an output method created by Create
*****************************************************************************/
static
void
CloseVideo
(
vlc_object_t
*
p_this
)
{
vout_thread_t
*
p_vout
=
(
vout_thread_t
*
)
p_this
;
Direct3DVoutRelease
(
p_vout
);
if
(
p_vout
->
p_sys
->
p_event
)
{
vlc_object_detach
(
p_vout
->
p_sys
->
p_event
);
/* Kill DirectXEventThread */
p_vout
->
p_sys
->
p_event
->
b_die
=
VLC_TRUE
;
/* we need to be sure DirectXEventThread won't stay stuck in
* GetMessage, so we send a fake message */
if
(
p_vout
->
p_sys
->
hwnd
)
{
PostMessage
(
p_vout
->
p_sys
->
hwnd
,
WM_NULL
,
0
,
0
);
}
vlc_thread_join
(
p_vout
->
p_sys
->
p_event
);
vlc_object_destroy
(
p_vout
->
p_sys
->
p_event
);
}
vlc_mutex_destroy
(
&
p_vout
->
p_sys
->
lock
);
/* restore screensaver system settings */
if
(
0
!=
p_vout
->
p_sys
->
i_spi_lowpowertimeout
)
{
SystemParametersInfo
(
SPI_SETLOWPOWERTIMEOUT
,
p_vout
->
p_sys
->
i_spi_lowpowertimeout
,
NULL
,
0
);
}
if
(
0
!=
p_vout
->
p_sys
->
i_spi_powerofftimeout
)
{
SystemParametersInfo
(
SPI_SETPOWEROFFTIMEOUT
,
p_vout
->
p_sys
->
i_spi_powerofftimeout
,
NULL
,
0
);
}
if
(
0
!=
p_vout
->
p_sys
->
i_spi_screensavetimeout
)
{
SystemParametersInfo
(
SPI_SETSCREENSAVETIMEOUT
,
p_vout
->
p_sys
->
i_spi_screensavetimeout
,
NULL
,
0
);
}
if
(
p_vout
->
p_sys
)
{
free
(
p_vout
->
p_sys
);
p_vout
->
p_sys
=
NULL
;
}
}
/*****************************************************************************
* Init: initialize Direct3D video thread output method
*****************************************************************************/
static
int
Init
(
vout_thread_t
*
p_vout
)
{
int
i_ret
;
/* Initialise Direct3D */
if
(
VLC_SUCCESS
!=
Direct3DVoutOpen
(
p_vout
)
)
{
msg_Err
(
p_vout
,
"cannot initialize Direct3D"
);
return
VLC_EGENERIC
;
}
/* Initialize the output structure.
* Since Direct3D can do rescaling for us, stick to the default
* coordinates and aspect. */
p_vout
->
output
.
i_width
=
p_vout
->
render
.
i_width
;
p_vout
->
output
.
i_height
=
p_vout
->
render
.
i_height
;
p_vout
->
output
.
i_aspect
=
p_vout
->
render
.
i_aspect
;
p_vout
->
fmt_out
=
p_vout
->
fmt_in
;
E_
(
DirectXUpdateRects
)(
p_vout
,
VLC_TRUE
);
/* create picture pool */
i_ret
=
Direct3DVoutCreatePictures
(
p_vout
,
1
);
if
(
VLC_SUCCESS
!=
i_ret
)
{
msg_Err
(
p_vout
,
"Direct3D picture pool initialization failed !"
);
return
i_ret
;
}
/* create scene */
i_ret
=
Direct3DVoutCreateScene
(
p_vout
);
if
(
VLC_SUCCESS
!=
i_ret
)
{
msg_Err
(
p_vout
,
"Direct3D scene initialization failed !"
);
Direct3DVoutReleasePictures
(
p_vout
);
return
i_ret
;
}
p_vout
->
fmt_out
.
i_chroma
=
p_vout
->
output
.
i_chroma
;
return
VLC_SUCCESS
;
}
/*****************************************************************************
* End: terminate Sys video thread output method
*****************************************************************************
* Terminate an output method created by Create.
* It is called at the end of the thread.
*****************************************************************************/
static
void
End
(
vout_thread_t
*
p_vout
)
{
Direct3DVoutReleaseScene
(
p_vout
);
Direct3DVoutReleasePictures
(
p_vout
);
Direct3DVoutClose
(
p_vout
);
}
/*****************************************************************************
* 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
)
{
WINDOWPLACEMENT
window_placement
;
/* If we do not control our window, we check for geometry changes
* ourselves because the parent might not send us its events. */
vlc_mutex_lock
(
&
p_vout
->
p_sys
->
lock
);
if
(
p_vout
->
p_sys
->
hparent
&&
!
p_vout
->
b_fullscreen
)
{
RECT
rect_parent
;
POINT
point
;
vlc_mutex_unlock
(
&
p_vout
->
p_sys
->
lock
);
GetClientRect
(
p_vout
->
p_sys
->
hparent
,
&
rect_parent
);
point
.
x
=
point
.
y
=
0
;
ClientToScreen
(
p_vout
->
p_sys
->
hparent
,
&
point
);
OffsetRect
(
&
rect_parent
,
point
.
x
,
point
.
y
);
if
(
!
EqualRect
(
&
rect_parent
,
&
p_vout
->
p_sys
->
rect_parent
)
)
{
p_vout
->
p_sys
->
rect_parent
=
rect_parent
;
SetWindowPos
(
p_vout
->
p_sys
->
hwnd
,
0
,
0
,
0
,
rect_parent
.
right
-
rect_parent
.
left
,
rect_parent
.
bottom
-
rect_parent
.
top
,
0
);
}
}
else
{
vlc_mutex_unlock
(
&
p_vout
->
p_sys
->
lock
);
}
/*
* Position Change
*/
if
(
p_vout
->
p_sys
->
i_changes
&
DX_POSITION_CHANGE
)
{
#if 0 /* need that when bicubic filter is available */
RECT rect;
UINT width, height;
GetClientRect(p_vout->p_sys->hvideownd, &rect);
width = rect.right-rect.left;
height = rect.bottom-rect.top;
if( (width != p_vout->p_sys->d3dpp.BackBufferWidth)
|| (height != p_vout->p_sys->d3dpp.BackBufferHeight) )
{
msg_Dbg(p_vout, "resizing device back buffers to (%lux%lu)", width, height);
// need to reset D3D device to resize back buffer
if( VLC_SUCCESS != Direct3DVoutResetDevice(p_vout, width, height) )
return VLC_EGENERIC;
}
#endif
p_vout
->
p_sys
->
i_changes
&=
~
DX_POSITION_CHANGE
;
}
/* 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
;
E_
(
DirectXUpdateRects
)(
p_vout
,
VLC_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
)
{
vlc_value_t
val
;
HWND
hwnd
=
(
p_vout
->
p_sys
->
hparent
&&
p_vout
->
p_sys
->
hfswnd
)
?
p_vout
->
p_sys
->
hfswnd
:
p_vout
->
p_sys
->
hwnd
;
p_vout
->
b_fullscreen
=
!
p_vout
->
b_fullscreen
;
/* We need to switch between Maximized and Normal sized window */
window_placement
.
length
=
sizeof
(
WINDOWPLACEMENT
);
GetWindowPlacement
(
hwnd
,
&
window_placement
);
if
(
p_vout
->
b_fullscreen
)
{
/* Change window style, no borders and no title bar */
int
i_style
=
WS_CLIPCHILDREN
|
WS_VISIBLE
;
SetWindowLong
(
hwnd
,
GWL_STYLE
,
i_style
);
if
(
p_vout
->
p_sys
->
hparent
)
{
/* Retrieve current window position so fullscreen will happen
* on the right screen */
POINT
point
=
{
0
,
0
};
RECT
rect
;
ClientToScreen
(
p_vout
->
p_sys
->
hwnd
,
&
point
);
GetClientRect
(
p_vout
->
p_sys
->
hwnd
,
&
rect
);
SetWindowPos
(
hwnd
,
0
,
point
.
x
,
point
.
y
,
rect
.
right
,
rect
.
bottom
,
SWP_NOZORDER
|
SWP_FRAMECHANGED
);
GetWindowPlacement
(
hwnd
,
&
window_placement
);
}
/* Maximize window */
window_placement
.
showCmd
=
SW_SHOWMAXIMIZED
;
SetWindowPlacement
(
hwnd
,
&
window_placement
);
SetWindowPos
(
hwnd
,
0
,
0
,
0
,
0
,
0
,
SWP_NOMOVE
|
SWP_NOSIZE
|
SWP_NOZORDER
|
SWP_FRAMECHANGED
);
if
(
p_vout
->
p_sys
->
hparent
)
{
RECT
rect
;
GetClientRect
(
hwnd
,
&
rect
);
SetParent
(
p_vout
->
p_sys
->
hwnd
,
hwnd
);
SetWindowPos
(
p_vout
->
p_sys
->
hwnd
,
0
,
0
,
0
,
rect
.
right
,
rect
.
bottom
,
SWP_NOZORDER
|
SWP_FRAMECHANGED
);
}
SetForegroundWindow
(
hwnd
);
}
else
{
/* Change window style, no borders and no title bar */
SetWindowLong
(
hwnd
,
GWL_STYLE
,
p_vout
->
p_sys
->
i_window_style
);
/* Normal window */
window_placement
.
showCmd
=
SW_SHOWNORMAL
;
SetWindowPlacement
(
hwnd
,
&
window_placement
);
SetWindowPos
(
hwnd
,
0
,
0
,
0
,
0
,
0
,
SWP_NOMOVE
|
SWP_NOSIZE
|
SWP_NOZORDER
|
SWP_FRAMECHANGED
);
if
(
p_vout
->
p_sys
->
hparent
)
{
RECT
rect
;
GetClientRect
(
p_vout
->
p_sys
->
hparent
,
&
rect
);
SetParent
(
p_vout
->
p_sys
->
hwnd
,
p_vout
->
p_sys
->
hparent
);
SetWindowPos
(
p_vout
->
p_sys
->
hwnd
,
0
,
0
,
0
,
rect
.
right
,
rect
.
bottom
,
SWP_NOZORDER
|
SWP_FRAMECHANGED
);
ShowWindow
(
hwnd
,
SW_HIDE
);
SetForegroundWindow
(
p_vout
->
p_sys
->
hparent
);
}
/* Make sure the mouse cursor is displayed */
PostMessage
(
p_vout
->
p_sys
->
hwnd
,
WM_VLC_SHOW_MOUSE
,
0
,
0
);
}
/* Update the object variable and trigger callback */
val
.
b_bool
=
p_vout
->
b_fullscreen
;
var_Set
(
p_vout
,
"fullscreen"
,
val
);
p_vout
->
i_changes
&=
~
VOUT_FULLSCREEN_CHANGE
;
p_vout
->
p_sys
->
i_changes
&=
~
VOUT_FULLSCREEN_CHANGE
;
}
/*
* Pointer change
*/
if
(
p_vout
->
b_fullscreen
&&
!
p_vout
->
p_sys
->
b_cursor_hidden
&&
(
mdate
()
-
p_vout
->
p_sys
->
i_lastmoved
)
>
5000000
)
{
POINT
point
;
HWND
hwnd
;
/* Hide the cursor only if it is inside our window */
GetCursorPos
(
&
point
);
hwnd
=
WindowFromPoint
(
point
);
if
(
hwnd
==
p_vout
->
p_sys
->
hwnd
||
hwnd
==
p_vout
->
p_sys
->
hvideownd
)
{
PostMessage
(
p_vout
->
p_sys
->
hwnd
,
WM_VLC_HIDE_MOUSE
,
0
,
0
);
}
else
{
p_vout
->
p_sys
->
i_lastmoved
=
mdate
();
}
}
/*
* "Always on top" status change
*/
if
(
p_vout
->
p_sys
->
b_on_top_change
)
{
vlc_value_t
val
;
HMENU
hMenu
=
GetSystemMenu
(
p_vout
->
p_sys
->
hwnd
,
FALSE
);
var_Get
(
p_vout
,
"video-on-top"
,
&
val
);
/* Set the window on top if necessary */
if
(
val
.
b_bool
&&
!
(
GetWindowLong
(
p_vout
->
p_sys
->
hwnd
,
GWL_EXSTYLE
)
&
WS_EX_TOPMOST
)
)
{
CheckMenuItem
(
hMenu
,
IDM_TOGGLE_ON_TOP
,
MF_BYCOMMAND
|
MFS_CHECKED
);
SetWindowPos
(
p_vout
->
p_sys
->
hwnd
,
HWND_TOPMOST
,
0
,
0
,
0
,
0
,
SWP_NOSIZE
|
SWP_NOMOVE
);
}
else
/* The window shouldn't be on top */
if
(
!
val
.
b_bool
&&
(
GetWindowLong
(
p_vout
->
p_sys
->
hwnd
,
GWL_EXSTYLE
)
&
WS_EX_TOPMOST
)
)
{
CheckMenuItem
(
hMenu
,
IDM_TOGGLE_ON_TOP
,
MF_BYCOMMAND
|
MFS_UNCHECKED
);
SetWindowPos
(
p_vout
->
p_sys
->
hwnd
,
HWND_NOTOPMOST
,
0
,
0
,
0
,
0
,
SWP_NOSIZE
|
SWP_NOMOVE
);
}
p_vout
->
p_sys
->
b_on_top_change
=
VLC_FALSE
;
}
/* Check if the event thread is still running */
if
(
p_vout
->
p_sys
->
p_event
->
b_die
)
{
return
VLC_EGENERIC
;
/* exit */
}
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
)
{
LPDIRECT3DDEVICE9
p_d3ddev
=
p_vout
->
p_sys
->
p_d3ddev
;
// Present the backbuffer contents to the display
HRESULT
hr
=
IDirect3DDevice9_Present
(
p_d3ddev
,
NULL
,
NULL
,
NULL
,
NULL
);
if
(
FAILED
(
hr
)
)
msg_Dbg
(
p_vout
,
"%s:%d (hr=0x%0lX)"
,
__FUNCTION__
,
__LINE__
,
hr
);
}
/*****************************************************************************
* DirectD3DVoutCreate: Initialize and instance of Direct3D9
*****************************************************************************
* This function initialize Direct3D and analyze available resources from
* default adapter.
*****************************************************************************/
static
int
Direct3DVoutCreate
(
vout_thread_t
*
p_vout
)
{
HRESULT
hr
;
LPDIRECT3D9
p_d3dobj
;
D3DCAPS9
d3dCaps
;
/* Create the D3D object. */
p_d3dobj
=
Direct3DCreate9
(
D3D_SDK_VERSION
);
if
(
NULL
==
p_d3dobj
)
{
msg_Err
(
p_vout
,
"Could not create Direct3D9 instance."
);
return
VLC_EGENERIC
;
}
p_vout
->
p_sys
->
p_d3dobj
=
p_d3dobj
;
/*
** Get device capabilities
*/
ZeroMemory
(
&
d3dCaps
,
sizeof
(
d3dCaps
));
hr
=
IDirect3D9_GetDeviceCaps
(
p_d3dobj
,
D3DADAPTER_DEFAULT
,
D3DDEVTYPE_HAL
,
&
d3dCaps
);
if
(
FAILED
(
hr
)
)
{
msg_Err
(
p_vout
,
"Could not read adapter capabilities. (hr=0x%lX)"
,
hr
);
return
VLC_EGENERIC
;
}
/* TODO: need to test device capabilities and select the right render function */
return
VLC_SUCCESS
;
}
/*****************************************************************************
* DirectD3DVoutRelease: release an instance of Direct3D9
*****************************************************************************/
static
void
Direct3DVoutRelease
(
vout_thread_t
*
p_vout
)
{
if
(
p_vout
->
p_sys
->
p_d3dobj
)
{
IDirect3D9_Release
(
p_vout
->
p_sys
->
p_d3dobj
);
p_vout
->
p_sys
->
p_d3dobj
=
NULL
;
}
}
/*****************************************************************************
* DirectD3DVoutOpen: Takes care of all the Direct3D9 initialisations
*****************************************************************************
* 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
*****************************************************************************/
static
int
Direct3DVoutOpen
(
vout_thread_t
*
p_vout
)
{
HRESULT
hr
=
S_OK
;
LPDIRECT3D9
p_d3dobj
=
p_vout
->
p_sys
->
p_d3dobj
;;
D3DDISPLAYMODE
d3ddm
;
LPDIRECT3DDEVICE9
p_d3ddev
;
/*
** Get the current desktop display mode, so we can set up a back
** buffer of the same format
*/
hr
=
IDirect3D9_GetAdapterDisplayMode
(
p_d3dobj
,
D3DADAPTER_DEFAULT
,
&
d3ddm
);
if
(
FAILED
(
hr
))
{
msg_Err
(
p_vout
,
"Could not read adapter display mode. (hr=0x%lX)"
,
hr
);
return
VLC_EGENERIC
;
}
/* Set up the structure used to create the D3DDevice. */
ZeroMemory
(
&
p_vout
->
p_sys
->
d3dpp
,
sizeof
(
D3DPRESENT_PARAMETERS
)
);
p_vout
->
p_sys
->
d3dpp
.
Windowed
=
TRUE
;
p_vout
->
p_sys
->
d3dpp
.
hDeviceWindow
=
p_vout
->
p_sys
->
hvideownd
;
p_vout
->
p_sys
->
d3dpp
.
SwapEffect
=
D3DSWAPEFFECT_DISCARD
;
p_vout
->
p_sys
->
d3dpp
.
PresentationInterval
=
D3DPRESENT_INTERVAL_DEFAULT
;
p_vout
->
p_sys
->
d3dpp
.
BackBufferFormat
=
d3ddm
.
Format
;
p_vout
->
p_sys
->
d3dpp
.
BackBufferCount
=
1
;
p_vout
->
p_sys
->
d3dpp
.
EnableAutoDepthStencil
=
TRUE
;
p_vout
->
p_sys
->
d3dpp
.
AutoDepthStencilFormat
=
D3DFMT_D16
;
// Create the D3DDevice
hr
=
IDirect3D9_CreateDevice
(
p_d3dobj
,
D3DADAPTER_DEFAULT
,
D3DDEVTYPE_HAL
,
NULL
,
D3DCREATE_SOFTWARE_VERTEXPROCESSING
,
&
(
p_vout
->
p_sys
->
d3dpp
),
&
p_d3ddev
);
if
(
FAILED
(
hr
)
)
{
msg_Err
(
p_vout
,
"Could not create the D3D device! (hr=0x%lX)"
,
hr
);
return
VLC_EGENERIC
;
}
p_vout
->
p_sys
->
p_d3ddev
=
p_d3ddev
;
msg_Dbg
(
p_vout
,
"Direct3D device adapter successfully initialized"
);
return
VLC_SUCCESS
;
}
/*****************************************************************************
* DirectD3DClose: release the Direct3D9 device
*****************************************************************************/
static
void
Direct3DVoutClose
(
vout_thread_t
*
p_vout
)
{
if
(
p_vout
->
p_sys
->
p_d3ddev
)
{
IDirect3DDevice9_Release
(
p_vout
->
p_sys
->
p_d3ddev
);
p_vout
->
p_sys
->
p_d3ddev
=
NULL
;
}
p_vout
->
p_sys
->
hmonitor
=
NULL
;
}
/*****************************************************************************
* DirectD3DClose: reset the Direct3D9 device
*****************************************************************************
* All resources must be deallocated before the reset occur, they will be
* realllocated once the reset has been performed successfully
*****************************************************************************/
static
int
Direct3DVoutResetDevice
(
vout_thread_t
*
p_vout
,
UINT
i_width
,
UINT
i_height
)
{
LPDIRECT3DDEVICE9
p_d3ddev
=
p_vout
->
p_sys
->
p_d3ddev
;
D3DPRESENT_PARAMETERS
d3dpp
;
HRESULT
hr
;
memcpy
(
&
d3dpp
,
&
(
p_vout
->
p_sys
->
d3dpp
),
sizeof
(
d3dpp
));
if
(
i_width
)
d3dpp
.
BackBufferWidth
=
i_width
;
if
(
i_height
)
d3dpp
.
BackBufferHeight
=
i_height
;
// release all D3D objects
Direct3DVoutReleaseScene
(
p_vout
);
Direct3DVoutReleasePictures
(
p_vout
);
hr
=
IDirect3DDevice9_Reset
(
p_d3ddev
,
&
d3dpp
);
if
(
SUCCEEDED
(
hr
)
)
{
// re-create them
if
(
(
VLC_SUCCESS
==
Direct3DVoutCreatePictures
(
p_vout
,
1
))
&&
(
VLC_SUCCESS
==
Direct3DVoutCreateScene
(
p_vout
))
)
{
p_vout
->
p_sys
->
d3dpp
.
BackBufferWidth
=
i_width
;
p_vout
->
p_sys
->
d3dpp
.
BackBufferHeight
=
i_height
;
return
VLC_SUCCESS
;
}
return
VLC_EGENERIC
;
}
else
{
msg_Err
(
p_vout
,
"%s failed ! (hr=%08lX)"
,
__FUNCTION__
,
hr
);
return
VLC_EGENERIC
;
}
return
VLC_SUCCESS
;
}
static
D3DFORMAT
Direct3DVoutSelectFormat
(
vout_thread_t
*
p_vout
,
D3DFORMAT
target
,
const
D3DFORMAT
*
formats
,
size_t
count
)
{
LPDIRECT3D9
p_d3dobj
=
p_vout
->
p_sys
->
p_d3dobj
;
size_t
c
;
for
(
c
=
0
;
c
<
count
;
++
c
)
{
HRESULT
hr
;
D3DFORMAT
format
=
formats
[
c
];
hr
=
IDirect3D9_CheckDeviceFormatConversion
(
p_d3dobj
,
D3DADAPTER_DEFAULT
,
D3DDEVTYPE_HAL
,
format
,
target
);
if
(
SUCCEEDED
(
hr
)
)
{
// found a compatible format
switch
(
format
)
{
case
D3DFMT_UYVY
:
msg_Dbg
(
p_vout
,
"selected surface pixel format is UYVY"
);
break
;
case
D3DFMT_YUY2
:
msg_Dbg
(
p_vout
,
"selected surface pixel format is YUY2"
);
break
;
case
D3DFMT_X8R8G8B8
:
msg_Dbg
(
p_vout
,
"selected surface pixel format is X8R8G8B8"
);
break
;
case
D3DFMT_A8R8G8B8
:
msg_Dbg
(
p_vout
,
"selected surface pixel format is A8R8G8B8"
);
break
;
case
D3DFMT_R8G8B8
:
msg_Dbg
(
p_vout
,
"selected surface pixel format is R8G8B8"
);
break
;
case
D3DFMT_R5G6B5
:
msg_Dbg
(
p_vout
,
"selected surface pixel format is R5G6B5"
);
break
;
case
D3DFMT_X1R5G5B5
:
msg_Dbg
(
p_vout
,
"selected surface pixel format is X1R5G5B5"
);
break
;
default:
msg_Dbg
(
p_vout
,
"selected surface pixel format is 0x%0X"
,
format
);
break
;
}
return
format
;
}
else
if
(
D3DERR_NOTAVAILABLE
!=
hr
)
{
msg_Err
(
p_vout
,
"Could not query adapter supported formats. (hr=0x%lX)"
,
hr
);
break
;
}
}
return
D3DFMT_UNKNOWN
;
}
D3DFORMAT
Direct3DVoutFindFormat
(
vout_thread_t
*
p_vout
,
int
i_chroma
,
D3DFORMAT
target
)
{
switch
(
i_chroma
)
{
case
VLC_FOURCC
(
'U'
,
'Y'
,
'V'
,
'Y'
):
case
VLC_FOURCC
(
'U'
,
'Y'
,
'N'
,
'V'
):
case
VLC_FOURCC
(
'Y'
,
'4'
,
'2'
,
'2'
):
{
static
const
D3DFORMAT
formats
[]
=
{
D3DFMT_UYVY
,
D3DFMT_YUY2
,
D3DFMT_X8R8G8B8
,
D3DFMT_A8R8G8B8
,
D3DFMT_R5G6B5
,
D3DFMT_X1R5G5B5
};
return
Direct3DVoutSelectFormat
(
p_vout
,
target
,
formats
,
sizeof
(
formats
)
/
sizeof
(
D3DFORMAT
));
}
case
VLC_FOURCC
(
'I'
,
'4'
,
'2'
,
'0'
):
case
VLC_FOURCC
(
'Y'
,
'V'
,
'1'
,
'2'
):
{
/* typically 3D textures don't support planar format
** fallback to packed version and use pixel
** shader or CPU for the conversion
*/
static
const
D3DFORMAT
formats
[]
=
{
D3DFMT_YUY2
,
D3DFMT_UYVY
,
D3DFMT_X8R8G8B8
,
D3DFMT_A8R8G8B8
,
D3DFMT_R5G6B5
,
D3DFMT_X1R5G5B5
};
return
Direct3DVoutSelectFormat
(
p_vout
,
target
,
formats
,
sizeof
(
formats
)
/
sizeof
(
D3DFORMAT
));
}
case
VLC_FOURCC
(
'Y'
,
'U'
,
'Y'
,
'2'
):
case
VLC_FOURCC
(
'Y'
,
'U'
,
'N'
,
'V'
):
{
static
const
D3DFORMAT
formats
[]
=
{
D3DFMT_YUY2
,
D3DFMT_UYVY
,
D3DFMT_X8R8G8B8
,
D3DFMT_A8R8G8B8
,
D3DFMT_R5G6B5
,
D3DFMT_X1R5G5B5
};
return
Direct3DVoutSelectFormat
(
p_vout
,
target
,
formats
,
sizeof
(
formats
)
/
sizeof
(
D3DFORMAT
));
}
case
VLC_FOURCC
(
'R'
,
'V'
,
'1'
,
'5'
):
{
static
const
D3DFORMAT
formats
[]
=
{
D3DFMT_X1R5G5B5
};
return
Direct3DVoutSelectFormat
(
p_vout
,
target
,
formats
,
sizeof
(
formats
)
/
sizeof
(
D3DFORMAT
));
}
case
VLC_FOURCC
(
'R'
,
'V'
,
'1'
,
'6'
):
{
static
const
D3DFORMAT
formats
[]
=
{
D3DFMT_R5G6B5
};
return
Direct3DVoutSelectFormat
(
p_vout
,
target
,
formats
,
sizeof
(
formats
)
/
sizeof
(
D3DFORMAT
));
}
case
VLC_FOURCC
(
'R'
,
'V'
,
'2'
,
'4'
):
{
static
const
D3DFORMAT
formats
[]
=
{
D3DFMT_R8G8B8
,
D3DFMT_X8R8G8B8
,
D3DFMT_A8R8G8B8
};
return
Direct3DVoutSelectFormat
(
p_vout
,
target
,
formats
,
sizeof
(
formats
)
/
sizeof
(
D3DFORMAT
));
}
case
VLC_FOURCC
(
'R'
,
'V'
,
'3'
,
'2'
):
{
static
const
D3DFORMAT
formats
[]
=
{
D3DFMT_A8R8G8B8
,
D3DFMT_X8R8G8B8
};
return
Direct3DVoutSelectFormat
(
p_vout
,
target
,
formats
,
sizeof
(
formats
)
/
sizeof
(
D3DFORMAT
));
}
default:
;
}
return
D3DFMT_UNKNOWN
;
}
static
int
Direct3DVoutSetOuputFormat
(
vout_thread_t
*
p_vout
,
D3DFORMAT
format
)
{
switch
(
format
)
{
case
D3DFMT_YUY2
:
p_vout
->
output
.
i_chroma
=
VLC_FOURCC
(
'Y'
,
'U'
,
'Y'
,
'2'
);
break
;
case
D3DFMT_UYVY
:
p_vout
->
output
.
i_chroma
=
VLC_FOURCC
(
'U'
,
'Y'
,
'V'
,
'Y'
);
break
;
case
D3DFMT_X8R8G8B8
:
case
D3DFMT_A8R8G8B8
:
/*
** FIXME: some custom masks are not handled properly in rgb_yuv converter,
** ARGB do NOT work !
*/
p_vout
->
output
.
i_chroma
=
VLC_FOURCC
(
'R'
,
'V'
,
'3'
,
'2'
);
p_vout
->
output
.
i_rmask
=
0x000000ff
;
p_vout
->
output
.
i_gmask
=
0x0000ff00
;
p_vout
->
output
.
i_bmask
=
0x00ff0000
;
p_vout
->
output
.
i_lrshift
=
8
;
p_vout
->
output
.
i_lgshift
=
16
;
p_vout
->
output
.
i_lbshift
=
24
;
break
;
case
D3DFMT_R5G6B5
:
p_vout
->
output
.
i_chroma
=
VLC_FOURCC
(
'R'
,
'V'
,
'1'
,
'6'
);
# if defined( WORDS_BIGENDIAN )
p_vout
->
output
.
i_rmask
=
(
0x1fL
)
<<
11
;
p_vout
->
output
.
i_gmask
=
(
0x3fL
)
<<
5
;
p_vout
->
output
.
i_bmask
=
(
0x1fL
)
<<
0
;
//p_vout->output.i_rshift = 11;
//p_vout->output.i_gshift = 5;
//p_vout->output.i_bshift = 0;
# else
/*
** FIXME: in little endian mode, following masking is not byte aligned,
** therefore green bits will not be sequentially merged !
*/
p_vout
->
output
.
i_rmask
=
(
0x1fL
)
<<
0
;
p_vout
->
output
.
i_gmask
=
(
0x3fL
)
<<
5
;
p_vout
->
output
.
i_bmask
=
(
0x1fL
)
<<
11
;
//p_vout->output.i_rshift = 0;
//p_vout->output.i_gshift = 5;
//p_vout->output.i_bshift = 11;
# endif
break
;
case
D3DFMT_X1R5G5B5
:
p_vout
->
output
.
i_chroma
=
VLC_FOURCC
(
'R'
,
'V'
,
'1'
,
'5'
);
# if defined( WORDS_BIGENDIAN )
p_vout
->
output
.
i_rmask
=
(
0x1fL
)
<<
10
;
p_vout
->
output
.
i_gmask
=
(
0x1fL
)
<<
5
;
p_vout
->
output
.
i_bmask
=
(
0x1fL
)
<<
0
;
//p_vout->output.i_rshift = 10;
//p_vout->output.i_gshift = 5;
//p_vout->output.i_bshift = 0;
# else
/*
** FIXME: in little endian mode, following masking is not byte aligned,
** therefore green bits will not be sequentially merged !
*/
p_vout
->
output
.
i_rmask
=
(
0x1fL
)
<<
1
;
p_vout
->
output
.
i_gmask
=
(
0x1fL
)
<<
6
;
p_vout
->
output
.
i_bmask
=
(
0x1fL
)
<<
11
;
//p_vout->output.i_rshift = 1;
//p_vout->output.i_gshift = 5;
//p_vout->output.i_bshift = 11;
# endif
break
;
default:
return
VLC_EGENERIC
;
}
return
VLC_SUCCESS
;
}
/*****************************************************************************
* Direct3DVoutCreatePictures: allocate a vector of identical pictures
*****************************************************************************
* Each picture has an associated offscreen surface in video memory
* depending on hardware capabilities the picture chroma will be as close
* as possible to the orginal render chroma to reduce CPU conversion overhead
* and delegate this work to video card GPU
*****************************************************************************/
static
int
Direct3DVoutCreatePictures
(
vout_thread_t
*
p_vout
,
size_t
i_num_pics
)
{
LPDIRECT3DDEVICE9
p_d3ddev
=
p_vout
->
p_sys
->
p_d3ddev
;
D3DFORMAT
format
=
p_vout
->
p_sys
->
d3dpp
.
BackBufferFormat
;
HRESULT
hr
;
size_t
c
;
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
*/
format
=
Direct3DVoutFindFormat
(
p_vout
,
p_vout
->
render
.
i_chroma
,
format
);
if
(
VLC_SUCCESS
!=
Direct3DVoutSetOuputFormat
(
p_vout
,
format
)
)
{
msg_Err
(
p_vout
,
"surface pixel format is not supported."
);
return
VLC_EGENERIC
;
}
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
,
format
,
D3DPOOL_DEFAULT
,
&
p_d3dsurf
,
NULL
);
if
(
FAILED
(
hr
)
)
{
msg_Err
(
p_vout
,
"Failed to create picture surface. (hr=0x%lx)"
,
hr
);
Direct3DVoutReleasePictures
(
p_vout
);
return
VLC_EGENERIC
;
}
/* fill surface with default color */
IDirect3DDevice9_ColorFill
(
p_d3ddev
,
p_d3dsurf
,
NULL
,
D3DCOLOR_ARGB
(
0xFF
,
0
,
0
,
0
)
);
/* assign surface to internal structure */
p_pic
->
p_sys
=
(
void
*
)
p_d3dsurf
;
/* Now that we've got our direct-buffer, we can finish filling in the
* picture_t structures */
switch
(
p_vout
->
output
.
i_chroma
)
{
case
VLC_FOURCC
(
'R'
,
'G'
,
'B'
,
'2'
):
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_FOURCC
(
'R'
,
'V'
,
'1'
,
'5'
):
case
VLC_FOURCC
(
'R'
,
'V'
,
'1'
,
'6'
):
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_FOURCC
(
'R'
,
'V'
,
'2'
,
'4'
):
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_FOURCC
(
'R'
,
'V'
,
'3'
,
'2'
):
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_FOURCC
(
'U'
,
'Y'
,
'V'
,
'Y'
):
case
VLC_FOURCC
(
'Y'
,
'U'
,
'Y'
,
'2'
):
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
;
default:
Direct3DVoutReleasePictures
(
p_vout
);
return
VLC_EGENERIC
;
}
p_pic
->
i_status
=
DESTROYED_PICTURE
;
p_pic
->
i_type
=
DIRECT_PICTURE
;
p_pic
->
b_slow
=
VLC_TRUE
;
p_pic
->
pf_lock
=
Direct3DVoutLockSurface
;
p_pic
->
pf_unlock
=
Direct3DVoutUnlockSurface
;
PP_OUTPUTPICTURE
[
c
]
=
p_pic
;
I_OUTPUTPICTURES
=
++
c
;
}
msg_Dbg
(
p_vout
,
"%u Direct3D pictures created successfully"
,
c
);
return
VLC_SUCCESS
;
}
/*****************************************************************************
* Direct3DVoutReleasePictures: destroy a picture vector
*****************************************************************************
* release all video resources used for pictures
*****************************************************************************/
static
void
Direct3DVoutReleasePictures
(
vout_thread_t
*
p_vout
)
{
size_t
i_num_pics
=
I_OUTPUTPICTURES
;
size_t
c
;
for
(
c
=
0
;
c
<
i_num_pics
;
++
c
)
{
picture_t
*
p_pic
=
p_vout
->
p_picture
+
c
;
if
(
p_pic
->
p_sys
)
{
LPDIRECT3DSURFACE9
p_d3dsurf
=
(
LPDIRECT3DSURFACE9
)
p_pic
->
p_sys
;
p_pic
->
p_sys
=
NULL
;
if
(
p_d3dsurf
)
{
IDirect3DSurface9_Release
(
p_d3dsurf
);
}
}
}
msg_Dbg
(
p_vout
,
"%u Direct3D pictures released."
,
c
);
I_OUTPUTPICTURES
=
0
;
}
/*****************************************************************************
* Direct3DVoutLockSurface: Lock surface and get picture data pointer
*****************************************************************************
* This function locks a surface and get the surface descriptor which amongst
* other things has the pointer to the picture data.
*****************************************************************************/
static
int
Direct3DVoutLockSurface
(
vout_thread_t
*
p_vout
,
picture_t
*
p_pic
)
{
HRESULT
hr
;
D3DLOCKED_RECT
d3drect
;
LPDIRECT3DSURFACE9
p_d3dsurf
=
(
LPDIRECT3DSURFACE9
)
p_pic
->
p_sys
;
if
(
NULL
==
p_d3dsurf
)
return
VLC_EGENERIC
;
/* Lock the surface to get a valid pointer to the picture buffer */
hr
=
IDirect3DSurface9_LockRect
(
p_d3dsurf
,
&
d3drect
,
NULL
,
D3DLOCK_DISCARD
);
if
(
FAILED
(
hr
)
)
{
msg_Dbg
(
p_vout
,
"%s:%d (hr=0x%0lX)"
,
__FUNCTION__
,
__LINE__
,
hr
);
return
VLC_EGENERIC
;
}
/* fill in buffer info in first plane */
p_pic
->
p
->
p_pixels
=
d3drect
.
pBits
;
p_pic
->
p
->
i_pitch
=
d3drect
.
Pitch
;
return
VLC_SUCCESS
;
}
/*****************************************************************************
* Direct3DVoutUnlockSurface: Unlock a surface locked by Direct3DLockSurface().
*****************************************************************************/
static
int
Direct3DVoutUnlockSurface
(
vout_thread_t
*
p_vout
,
picture_t
*
p_pic
)
{
HRESULT
hr
;
LPDIRECT3DSURFACE9
p_d3dsurf
=
(
LPDIRECT3DSURFACE9
)
p_pic
->
p_sys
;
if
(
NULL
==
p_d3dsurf
)
return
VLC_EGENERIC
;
/* Unlock the Surface */
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
;
}
/*****************************************************************************
* Direct3DVoutCreateScene: allocate and initialize a 3D scene
*****************************************************************************
* for advanced blending/filtering a texture needs be used in a 3D scene.
*****************************************************************************/
static
int
Direct3DVoutCreateScene
(
vout_thread_t
*
p_vout
)
{
LPDIRECT3DDEVICE9
p_d3ddev
=
p_vout
->
p_sys
->
p_d3ddev
;
LPDIRECT3DTEXTURE9
p_d3dtex
;
LPDIRECT3DVERTEXBUFFER9
p_d3dvtc
;
HRESULT
hr
;
/*
** Create a texture for use when rendering a scene
** for performance reason, texture format is identical to backbuffer
** which would usually be a RGB format
*/
hr
=
IDirect3DDevice9_CreateTexture
(
p_d3ddev
,
p_vout
->
render
.
i_width
,
p_vout
->
render
.
i_height
,
1
,
D3DUSAGE_RENDERTARGET
,
p_vout
->
p_sys
->
d3dpp
.
BackBufferFormat
,
D3DPOOL_DEFAULT
,
&
p_d3dtex
,
NULL
);
if
(
FAILED
(
hr
))
{
msg_Err
(
p_vout
,
"Failed to create texture. (hr=0x%lx)"
,
hr
);
return
VLC_EGENERIC
;
}
/*
** Create a vertex buffer for use when rendering scene
*/
hr
=
IDirect3DDevice9_CreateVertexBuffer
(
p_d3ddev
,
sizeof
(
CUSTOMVERTEX
)
*
4
,
D3DUSAGE_WRITEONLY
,
D3DFVF_CUSTOMVERTEX
,
D3DPOOL_DEFAULT
,
&
p_d3dvtc
,
NULL
);
if
(
FAILED
(
hr
)
)
{
msg_Err
(
p_vout
,
"Failed to create vertex buffer. (hr=0x%lx)"
,
hr
);
IDirect3DTexture9_Release
(
p_d3dtex
);
return
VLC_EGENERIC
;
}
p_vout
->
p_sys
->
p_d3dtex
=
p_d3dtex
;
p_vout
->
p_sys
->
p_d3dvtc
=
p_d3dvtc
;
// Texture coordinates outside the range [0.0, 1.0] are set
// to the texture color at 0.0 or 1.0, respectively.
IDirect3DDevice9_SetSamplerState
(
p_d3ddev
,
0
,
D3DSAMP_ADDRESSU
,
D3DTADDRESS_CLAMP
);
IDirect3DDevice9_SetSamplerState
(
p_d3ddev
,
0
,
D3DSAMP_ADDRESSV
,
D3DTADDRESS_CLAMP
);
// Set linear filtering quality
IDirect3DDevice9_SetSamplerState
(
p_d3ddev
,
0
,
D3DSAMP_MINFILTER
,
D3DTEXF_LINEAR
);
IDirect3DDevice9_SetSamplerState
(
p_d3ddev
,
0
,
D3DSAMP_MAGFILTER
,
D3DTEXF_LINEAR
);
// set maximum ambient light
IDirect3DDevice9_SetRenderState
(
p_d3ddev
,
D3DRS_AMBIENT
,
D3DCOLOR_XRGB
(
255
,
255
,
255
));
// Turn off culling
IDirect3DDevice9_SetRenderState
(
p_d3ddev
,
D3DRS_CULLMODE
,
D3DCULL_NONE
);
// Turn off the zbuffer
IDirect3DDevice9_SetRenderState
(
p_d3ddev
,
D3DRS_ZENABLE
,
D3DZB_FALSE
);
// Turn off lights
IDirect3DDevice9_SetRenderState
(
p_d3ddev
,
D3DRS_LIGHTING
,
FALSE
);
// Enable dithering
IDirect3DDevice9_SetRenderState
(
p_d3ddev
,
D3DRS_DITHERENABLE
,
TRUE
);
// disable stencil
IDirect3DDevice9_SetRenderState
(
p_d3ddev
,
D3DRS_STENCILENABLE
,
FALSE
);
// manage blending
IDirect3DDevice9_SetRenderState
(
p_d3ddev
,
D3DRS_ALPHABLENDENABLE
,
TRUE
);
IDirect3DDevice9_SetRenderState
(
p_d3ddev
,
D3DRS_SRCBLEND
,
D3DBLEND_SRCALPHA
);
IDirect3DDevice9_SetRenderState
(
p_d3ddev
,
D3DRS_DESTBLEND
,
D3DBLEND_INVSRCALPHA
);
IDirect3DDevice9_SetRenderState
(
p_d3ddev
,
D3DRS_ALPHATESTENABLE
,
TRUE
);
IDirect3DDevice9_SetRenderState
(
p_d3ddev
,
D3DRS_ALPHAREF
,
0x10
);
IDirect3DDevice9_SetRenderState
(
p_d3ddev
,
D3DRS_ALPHAFUNC
,
D3DCMP_GREATER
);
// Set texture states
IDirect3DDevice9_SetTextureStageState
(
p_d3ddev
,
0
,
D3DTSS_COLOROP
,
D3DTOP_MODULATE
);
IDirect3DDevice9_SetTextureStageState
(
p_d3ddev
,
0
,
D3DTSS_COLORARG1
,
D3DTA_TEXTURE
);
IDirect3DDevice9_SetTextureStageState
(
p_d3ddev
,
0
,
D3DTSS_COLORARG2
,
D3DTA_DIFFUSE
);
// turn off alpha operation
IDirect3DDevice9_SetTextureStageState
(
p_d3ddev
,
0
,
D3DTSS_ALPHAOP
,
D3DTOP_DISABLE
);
msg_Dbg
(
p_vout
,
"Direct3D scene created successfully"
);
return
VLC_SUCCESS
;
}
/*****************************************************************************
* Direct3DVoutReleaseScene
*****************************************************************************/
static
void
Direct3DVoutReleaseScene
(
vout_thread_t
*
p_vout
)
{
LPDIRECT3DTEXTURE9
p_d3dtex
=
p_vout
->
p_sys
->
p_d3dtex
;
LPDIRECT3DVERTEXBUFFER9
p_d3dvtc
=
p_vout
->
p_sys
->
p_d3dvtc
;
if
(
p_d3dvtc
)
{
IDirect3DVertexBuffer9_Release
(
p_d3dvtc
);
p_vout
->
p_sys
->
p_d3dvtc
=
NULL
;
}
if
(
p_d3dtex
)
{
IDirect3DTexture9_Release
(
p_d3dtex
);
p_vout
->
p_sys
->
p_d3dtex
=
NULL
;
}
msg_Dbg
(
p_vout
,
"Direct3D scene released successfully"
);
}
/*****************************************************************************
* Direct3DVoutRenderDefault: copy picture surface to display back buffer
*****************************************************************************
* This function is intented for lower end video cards, without pixel shader
* support or low video RAM
*****************************************************************************/
static
void
Direct3DVoutRenderDefault
(
vout_thread_t
*
p_vout
,
picture_t
*
p_pic
)
{
LPDIRECT3DDEVICE9
p_d3ddev
=
p_vout
->
p_sys
->
p_d3ddev
;
LPDIRECT3DSURFACE9
p_d3dsrc
,
p_d3ddest
;
UINT
iSwapChain
,
iSwapChains
;
HRESULT
hr
;
// check if device is still available
hr
=
IDirect3DDevice9_TestCooperativeLevel
(
p_d3ddev
);
if
(
FAILED
(
hr
)
)
{
if
(
(
D3DERR_DEVICENOTRESET
!=
hr
)
||
(
VLC_SUCCESS
!=
Direct3DVoutResetDevice
(
p_vout
,
0
,
0
))
)
{
// device is not usable at present (lost device, out of video mem ?)
return
;
}
}
/* retrieve the number of swap chains */
iSwapChains
=
IDirect3DDevice9_GetNumberOfSwapChains
(
p_d3ddev
);
if
(
0
==
iSwapChains
)
{
msg_Dbg
(
p_vout
,
"no swap chain to render ?"
);
return
;
}
/* retrieve picture surface */
p_d3dsrc
=
(
LPDIRECT3DSURFACE9
)
p_pic
->
p_sys
;
if
(
NULL
==
p_d3dsrc
)
{
msg_Dbg
(
p_vout
,
"no surface to render ?"
);
return
;
}
for
(
iSwapChain
=
0
;
iSwapChain
<
iSwapChains
;
++
iSwapChain
)
{
/* retrieve swap chain back buffer */
hr
=
IDirect3DDevice9_GetBackBuffer
(
p_d3ddev
,
iSwapChain
,
0
,
D3DBACKBUFFER_TYPE_MONO
,
&
p_d3ddest
);
if
(
FAILED
(
hr
)
)
{
msg_Dbg
(
p_vout
,
"%s:%d (hr=0x%0lX)"
,
__FUNCTION__
,
__LINE__
,
hr
);
continue
;
}
/* Copy picture surface into texture surface, color space conversion happens here */
hr
=
IDirect3DDevice9_StretchRect
(
p_d3ddev
,
p_d3dsrc
,
NULL
,
p_d3ddest
,
NULL
,
D3DTEXF_NONE
);
IDirect3DSurface9_Release
(
p_d3ddest
);
if
(
FAILED
(
hr
)
)
{
msg_Dbg
(
p_vout
,
"%s:%d (hr=0x%0lX)"
,
__FUNCTION__
,
__LINE__
,
hr
);
return
;
}
}
}
/*****************************************************************************
* Render: copy picture surface into a texture and render into a scene
*****************************************************************************
* This function is intented for higher end 3D cards, with pixel shader support
* and at least 64 MB of video RAM.
*****************************************************************************/
static
void
Direct3DVoutRenderScene
(
vout_thread_t
*
p_vout
,
picture_t
*
p_pic
)
{
LPDIRECT3DDEVICE9
p_d3ddev
=
p_vout
->
p_sys
->
p_d3ddev
;
LPDIRECT3DTEXTURE9
p_d3dtex
=
p_vout
->
p_sys
->
p_d3dtex
;
LPDIRECT3DVERTEXBUFFER9
p_d3dvtc
=
p_vout
->
p_sys
->
p_d3dvtc
;
LPDIRECT3DSURFACE9
p_d3dsrc
,
p_d3ddest
;
CUSTOMVERTEX
*
p_vertices
;
HRESULT
hr
;
float
f_width
,
f_height
;
// check if device is still available
hr
=
IDirect3DDevice9_TestCooperativeLevel
(
p_d3ddev
);
if
(
FAILED
(
hr
)
)
{
if
(
(
D3DERR_DEVICENOTRESET
!=
hr
)
||
(
VLC_SUCCESS
!=
Direct3DVoutResetDevice
(
p_vout
,
0
,
0
))
)
{
// device is not usable at present (lost device, out of video mem ?)
return
;
}
}
/* Clear the backbuffer and the zbuffer */
hr
=
IDirect3DDevice9_Clear
(
p_d3ddev
,
0
,
NULL
,
D3DCLEAR_TARGET
,
D3DCOLOR_XRGB
(
0
,
255
,
0
),
1
.
0
f
,
0
);
if
(
FAILED
(
hr
)
)
{
msg_Dbg
(
p_vout
,
"%s:%d (hr=0x%0lX)"
,
__FUNCTION__
,
__LINE__
,
hr
);
return
;
}
/* retrieve picture surface */
p_d3dsrc
=
(
LPDIRECT3DSURFACE9
)
p_pic
->
p_sys
;
if
(
NULL
==
p_d3dsrc
)
{
msg_Dbg
(
p_vout
,
"no surface to render ?"
);
return
;
}
/* retrieve texture top-level surface */
hr
=
IDirect3DTexture9_GetSurfaceLevel
(
p_d3dtex
,
0
,
&
p_d3ddest
);
if
(
FAILED
(
hr
)
)
{
msg_Dbg
(
p_vout
,
"%s:%d (hr=0x%0lX)"
,
__FUNCTION__
,
__LINE__
,
hr
);
return
;
}
/* Copy picture surface into texture surface, color space conversion happens here */
hr
=
IDirect3DDevice9_StretchRect
(
p_d3ddev
,
p_d3dsrc
,
NULL
,
p_d3ddest
,
NULL
,
D3DTEXF_NONE
);
IDirect3DSurface9_Release
(
p_d3ddest
);
if
(
FAILED
(
hr
)
)
{
msg_Dbg
(
p_vout
,
"%s:%d (hr=0x%0lX)"
,
__FUNCTION__
,
__LINE__
,
hr
);
return
;
}
/* Update the vertex buffer */
hr
=
IDirect3DVertexBuffer9_Lock
(
p_d3dvtc
,
0
,
0
,
(
VOID
**
)(
&
p_vertices
),
D3DLOCK_DISCARD
);
if
(
FAILED
(
hr
)
)
{
msg_Dbg
(
p_vout
,
"%s:%d (hr=0x%0lX)"
,
__FUNCTION__
,
__LINE__
,
hr
);
return
;
}
/* Setup vertices */
f_width
=
(
float
)(
p_vout
->
p_sys
->
d3dpp
.
BackBufferWidth
);
f_height
=
(
float
)(
p_vout
->
p_sys
->
d3dpp
.
BackBufferHeight
);
p_vertices
[
0
].
x
=
0
.
0
f
;
// left
p_vertices
[
0
].
y
=
0
.
0
f
;
// top
p_vertices
[
0
].
z
=
0
.
0
f
;
p_vertices
[
0
].
diffuse
=
D3DCOLOR_ARGB
(
255
,
255
,
255
,
255
);
p_vertices
[
0
].
rhw
=
1
.
0
f
;
p_vertices
[
0
].
tu
=
0
.
0
f
;
p_vertices
[
0
].
tv
=
0
.
0
f
;
p_vertices
[
1
].
x
=
f_width
;
// right
p_vertices
[
1
].
y
=
0
.
0
f
;
// top
p_vertices
[
1
].
z
=
0
.
0
f
;
p_vertices
[
1
].
diffuse
=
D3DCOLOR_ARGB
(
255
,
255
,
255
,
255
);
p_vertices
[
1
].
rhw
=
1
.
0
f
;
p_vertices
[
1
].
tu
=
1
.
0
f
;
p_vertices
[
1
].
tv
=
0
.
0
f
;
p_vertices
[
2
].
x
=
f_width
;
// right
p_vertices
[
2
].
y
=
f_height
;
// bottom
p_vertices
[
2
].
z
=
0
.
0
f
;
p_vertices
[
2
].
diffuse
=
D3DCOLOR_ARGB
(
255
,
255
,
255
,
255
);
p_vertices
[
2
].
rhw
=
1
.
0
f
;
p_vertices
[
2
].
tu
=
1
.
0
f
;
p_vertices
[
2
].
tv
=
1
.
0
f
;
p_vertices
[
3
].
x
=
0
.
0
f
;
// left
p_vertices
[
3
].
y
=
f_height
;
// bottom
p_vertices
[
3
].
z
=
0
.
0
f
;
p_vertices
[
3
].
diffuse
=
D3DCOLOR_ARGB
(
255
,
255
,
255
,
255
);
p_vertices
[
3
].
rhw
=
1
.
0
f
;
p_vertices
[
3
].
tu
=
0
.
0
f
;
p_vertices
[
3
].
tv
=
1
.
0
f
;
hr
=
IDirect3DVertexBuffer9_Unlock
(
p_d3dvtc
);
if
(
FAILED
(
hr
)
)
{
msg_Dbg
(
p_vout
,
"%s:%d (hr=0x%0lX)"
,
__FUNCTION__
,
__LINE__
,
hr
);
return
;
}
// Begin the scene
hr
=
IDirect3DDevice9_BeginScene
(
p_d3ddev
);
if
(
FAILED
(
hr
)
)
{
msg_Dbg
(
p_vout
,
"%s:%d (hr=0x%0lX)"
,
__FUNCTION__
,
__LINE__
,
hr
);
return
;
}
// Setup our texture. Using textures introduces the texture stage states,
// which govern how textures get blended together (in the case of multiple
// textures) and lighting information. In this case, we are modulating
// (blending) our texture with the diffuse color of the vertices.
hr
=
IDirect3DDevice9_SetTexture
(
p_d3ddev
,
0
,
(
LPDIRECT3DBASETEXTURE9
)
p_d3dtex
);
if
(
FAILED
(
hr
)
)
{
msg_Dbg
(
p_vout
,
"%s:%d (hr=0x%0lX)"
,
__FUNCTION__
,
__LINE__
,
hr
);
IDirect3DDevice9_EndScene
(
p_d3ddev
);
return
;
}
// Render the vertex buffer contents
hr
=
IDirect3DDevice9_SetStreamSource
(
p_d3ddev
,
0
,
p_d3dvtc
,
0
,
sizeof
(
CUSTOMVERTEX
));
if
(
FAILED
(
hr
)
)
{
msg_Dbg
(
p_vout
,
"%s:%d (hr=0x%0lX)"
,
__FUNCTION__
,
__LINE__
,
hr
);
IDirect3DDevice9_EndScene
(
p_d3ddev
);
return
;
}
// we use FVF instead of vertex shader
hr
=
IDirect3DDevice9_SetVertexShader
(
p_d3ddev
,
NULL
);
if
(
FAILED
(
hr
)
)
{
msg_Dbg
(
p_vout
,
"%s:%d (hr=0x%0lX)"
,
__FUNCTION__
,
__LINE__
,
hr
);
IDirect3DDevice9_EndScene
(
p_d3ddev
);
return
;
}
hr
=
IDirect3DDevice9_SetFVF
(
p_d3ddev
,
D3DFVF_CUSTOMVERTEX
);
if
(
FAILED
(
hr
)
)
{
msg_Dbg
(
p_vout
,
"%s:%d (hr=0x%0lX)"
,
__FUNCTION__
,
__LINE__
,
hr
);
IDirect3DDevice9_EndScene
(
p_d3ddev
);
return
;
}
// draw rectangle
hr
=
IDirect3DDevice9_DrawPrimitive
(
p_d3ddev
,
D3DPT_TRIANGLEFAN
,
0
,
2
);
if
(
FAILED
(
hr
)
)
{
msg_Dbg
(
p_vout
,
"%s:%d (hr=0x%0lX)"
,
__FUNCTION__
,
__LINE__
,
hr
);
IDirect3DDevice9_EndScene
(
p_d3ddev
);
return
;
}
// End the scene
hr
=
IDirect3DDevice9_EndScene
(
p_d3ddev
);
if
(
FAILED
(
hr
)
)
{
msg_Dbg
(
p_vout
,
"%s:%d (hr=0x%0lX)"
,
__FUNCTION__
,
__LINE__
,
hr
);
return
;
}
}
modules/video_output/directx/directx.c
View file @
599340cf
...
...
@@ -57,6 +57,19 @@
#include "vout.h"
/*****************************************************************************
* picture_sys_t: direct buffer method descriptor
*****************************************************************************
* This structure is part of the picture descriptor, it describes the
* DirectX specific properties of a direct buffer.
*****************************************************************************/
struct
picture_sys_t
{
LPDIRECTDRAWSURFACE2
p_surface
;
LPDIRECTDRAWSURFACE2
p_front_surface
;
DDSURFACEDESC
ddsd
;
};
/*****************************************************************************
* DirectDraw GUIDs.
* Defining them here allows us to get rid of the dxguid library during
...
...
@@ -908,7 +921,7 @@ BOOL WINAPI DirectXEnumCallback( GUID* p_guid, LPTSTR psz_desc,
rect
.
left
=
monitor_info
.
rcWork
.
left
;
rect
.
top
=
monitor_info
.
rcWork
.
top
;
msg_Dbg
(
p_vout
,
"DirectXEnumCallback: setting window "
"position to %
d,%
d"
,
rect
.
left
,
rect
.
top
);
"position to %
ld,%l
d"
,
rect
.
left
,
rect
.
top
);
SetWindowPos
(
p_vout
->
p_sys
->
hwnd
,
NULL
,
rect
.
left
,
rect
.
top
,
0
,
0
,
SWP_NOSIZE
|
SWP_NOZORDER
|
SWP_NOACTIVATE
);
...
...
@@ -1040,7 +1053,7 @@ static int DirectXInitDDraw( vout_thread_t *p_vout )
p_vout
->
p_sys
->
rect_display
.
bottom
=
GetSystemMetrics
(
SM_CYSCREEN
);
}
msg_Dbg
(
p_vout
,
"screen dimensions (%
ix%i,%ix%
i)"
,
msg_Dbg
(
p_vout
,
"screen dimensions (%
lix%li,%lix%l
i)"
,
p_vout
->
p_sys
->
rect_display
.
left
,
p_vout
->
p_sys
->
rect_display
.
top
,
p_vout
->
p_sys
->
rect_display
.
right
,
...
...
modules/video_output/directx/events.c
View file @
599340cf
...
...
@@ -44,7 +44,15 @@
#include <windowsx.h>
#include <shellapi.h>
#ifdef MODULE_NAME_IS_vout_directx
#include <ddraw.h>
#endif
#ifdef MODULE_NAME_IS_direct3d
#include <d3d9.h>
#endif
#ifdef MODULE_NAME_IS_glwin32
#include <GL/gl.h>
#endif
#include "vlc_keys.h"
#include "vout.h"
...
...
@@ -301,7 +309,11 @@ void E_(DirectXEventThread)( event_thread_t *p_event )
#ifdef MODULE_NAME_IS_glwin32
val
.
psz_string
=
strdup
(
VOUT_TITLE
" (OpenGL output)"
);
#else
#endif
#ifdef MODULE_NAME_IS_direct3d
val
.
psz_string
=
strdup
(
VOUT_TITLE
" (Direct3D output)"
);
#endif
#ifdef MODULE_NAME_IS_directx
if
(
p_event
->
p_vout
->
p_sys
->
b_using_overlay
)
val
.
psz_string
=
strdup
(
VOUT_TITLE
" (hardware YUV overlay DirectX output)"
);
else
if
(
p_event
->
p_vout
->
p_sys
->
b_hw_yuv
)
val
.
psz_string
=
...
...
@@ -481,9 +493,9 @@ static int DirectXCreateWindow( vout_thread_t *p_vout )
_T
(
VOUT_TITLE
)
_T
(
" (DirectX Output)"
),
/* window title */
i_style
,
/* window style */
(
p_vout
->
p_sys
->
i_window_x
<
0
)
?
CW_USEDEFAULT
:
p_vout
->
p_sys
->
i_window_x
,
/* default X coordinate */
(
UINT
)
p_vout
->
p_sys
->
i_window_x
,
/* default X coordinate */
(
p_vout
->
p_sys
->
i_window_y
<
0
)
?
CW_USEDEFAULT
:
p_vout
->
p_sys
->
i_window_y
,
/* default Y coordinate */
(
UINT
)
p_vout
->
p_sys
->
i_window_y
,
/* default Y coordinate */
rect_window
.
right
-
rect_window
.
left
,
/* window width */
rect_window
.
bottom
-
rect_window
.
top
,
/* window height */
p_vout
->
p_sys
->
hparent
,
/* parent window */
...
...
@@ -519,20 +531,33 @@ static int DirectXCreateWindow( vout_thread_t *p_vout )
NULL
,
NULL
,
hInstance
,
NULL
);
}
/* Now display the window */
ShowWindow
(
p_vout
->
p_sys
->
hwnd
,
SW_SHOW
);
/* Create video sub-window. This sub window will always exactly match
* the size of the video, which allows us to use crazy overlay colorkeys
* without having them shown outside of the video area. */
SendMessage
(
p_vout
->
p_sys
->
hwnd
,
WM_VLC_CREATE_VIDEO_WIN
,
0
,
0
);
/* Append a "Always On Top" entry in the system menu */
hMenu
=
GetSystemMenu
(
p_vout
->
p_sys
->
hwnd
,
FALSE
);
AppendMenu
(
hMenu
,
MF_SEPARATOR
,
0
,
_T
(
""
)
);
AppendMenu
(
hMenu
,
MF_STRING
|
MF_UNCHECKED
,
IDM_TOGGLE_ON_TOP
,
_T
(
"Always on &Top"
)
);
/* Create video sub-window. This sub window will always exactly match
* the size of the video, which allows us to use crazy overlay colorkeys
* without having them shown outside of the video area. */
p_vout
->
p_sys
->
hvideownd
=
CreateWindow
(
_T
(
"VLC DirectX video"
),
_T
(
""
),
/* window class */
WS_CHILD
|
WS_VISIBLE
,
/* window style */
0
,
0
,
p_vout
->
render
.
i_width
,
/* default width */
p_vout
->
render
.
i_height
,
/* default height */
p_vout
->
p_sys
->
hwnd
,
/* parent window */
NULL
,
hInstance
,
(
LPVOID
)
p_vout
);
/* send p_vout to WM_CREATE */
if
(
!
p_vout
->
p_sys
->
hvideownd
)
msg_Warn
(
p_vout
,
"can't create video sub-window"
);
else
msg_Dbg
(
p_vout
,
"created video sub-window"
);
/* Now display the window */
ShowWindow
(
p_vout
->
p_sys
->
hwnd
,
SW_SHOW
);
return
VLC_SUCCESS
;
}
...
...
@@ -613,6 +638,7 @@ void E_(DirectXUpdateRects)( vout_thread_t *p_vout, vlc_bool_t b_force )
rect_dest
.
top
=
point
.
y
+
i_y
;
rect_dest
.
bottom
=
rect_dest
.
top
+
i_height
;
#ifdef MODULE_NAME_IS_vout_directx
/* Apply overlay hardware constraints */
if
(
p_vout
->
p_sys
->
b_using_overlay
)
{
...
...
@@ -626,6 +652,7 @@ void E_(DirectXUpdateRects)( vout_thread_t *p_vout, vlc_bool_t b_force )
p_vout
->
p_sys
->
i_align_dest_size
/
2
)
&
~
p_vout
->
p_sys
->
i_align_dest_size
)
+
rect_dest
.
left
;
}
#endif
/* UpdateOverlay directdraw function doesn't automatically clip to the
* display size so we need to do it otherwise it will fail */
...
...
@@ -675,6 +702,7 @@ void E_(DirectXUpdateRects)( vout_thread_t *p_vout, vlc_bool_t b_force )
(
rect_dest
.
bottom
-
rect_dest_clipped
.
bottom
)
*
p_vout
->
fmt_out
.
i_visible_height
/
(
rect_dest
.
bottom
-
rect_dest
.
top
);
#ifdef MODULE_NAME_IS_vout_directx
/* Apply overlay hardware constraints */
if
(
p_vout
->
p_sys
->
b_using_overlay
)
{
...
...
@@ -689,6 +717,7 @@ void E_(DirectXUpdateRects)( vout_thread_t *p_vout, vlc_bool_t b_force )
p_vout
->
p_sys
->
i_align_src_size
/
2
)
&
~
p_vout
->
p_sys
->
i_align_src_size
)
+
rect_src_clipped
.
left
;
}
#endif
#if 0
msg_Dbg( p_vout, "DirectXUpdateRects image_src_clipped"
...
...
@@ -704,8 +733,10 @@ void E_(DirectXUpdateRects)( vout_thread_t *p_vout, vlc_bool_t b_force )
rect_dest_clipped
.
top
-=
p_vout
->
p_sys
->
rect_display
.
top
;
rect_dest_clipped
.
bottom
-=
p_vout
->
p_sys
->
rect_display
.
top
;
#ifdef MODULE_NAME_IS_vout_directx
if
(
p_vout
->
p_sys
->
b_using_overlay
)
E_
(
DirectXUpdateOverlay
)(
p_vout
);
#endif
/* Signal the change in size/position */
p_vout
->
p_sys
->
i_changes
|=
DX_POSITION_CHANGE
;
...
...
@@ -808,23 +839,6 @@ static long FAR PASCAL DirectXEventProc( HWND hwnd, UINT message,
}
break
;
case
WM_VLC_CREATE_VIDEO_WIN
:
/* Create video sub-window */
p_vout
->
p_sys
->
hvideownd
=
CreateWindow
(
_T
(
"VLC DirectX video"
),
_T
(
""
),
/* window class */
WS_CHILD
|
WS_VISIBLE
,
/* window style */
CW_USEDEFAULT
,
CW_USEDEFAULT
,
/* default coordinates */
CW_USEDEFAULT
,
CW_USEDEFAULT
,
hwnd
,
/* parent window */
NULL
,
GetModuleHandle
(
NULL
),
(
LPVOID
)
p_vout
);
/* send p_vout to WM_CREATE */
if
(
!
p_vout
->
p_sys
->
hvideownd
)
msg_Warn
(
p_vout
,
"can't create video sub-window"
);
else
msg_Dbg
(
p_vout
,
"created video sub-window"
);
break
;
case
WM_PAINT
:
case
WM_NCPAINT
:
case
WM_ERASEBKGND
:
...
...
modules/video_output/directx/glwin32.c
View file @
599340cf
...
...
@@ -104,10 +104,6 @@ static int OpenVideo( vlc_object_t *p_this )
p_vout
->
pf_manage
=
Manage
;
p_vout
->
pf_swap
=
GLSwapBuffers
;
p_vout
->
p_sys
->
p_ddobject
=
NULL
;
p_vout
->
p_sys
->
p_display
=
NULL
;
p_vout
->
p_sys
->
p_current_surface
=
NULL
;
p_vout
->
p_sys
->
p_clipper
=
NULL
;
p_vout
->
p_sys
->
hwnd
=
p_vout
->
p_sys
->
hvideownd
=
NULL
;
p_vout
->
p_sys
->
hparent
=
p_vout
->
p_sys
->
hfswnd
=
NULL
;
p_vout
->
p_sys
->
i_changes
=
0
;
...
...
@@ -485,8 +481,3 @@ static void GLSwapBuffers( vout_thread_t *p_vout )
{
SwapBuffers
(
p_vout
->
p_sys
->
hGLDC
);
}
int
E_
(
DirectXUpdateOverlay
)(
vout_thread_t
*
p_vout
)
{
return
1
;
}
modules/video_output/directx/vout.h
View file @
599340cf
...
...
@@ -40,12 +40,6 @@ typedef struct event_thread_t
*****************************************************************************/
struct
vout_sys_t
{
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 */
HWND
hwnd
;
/* Handle of the main window */
HWND
hvideownd
;
/* Handle of the video sub-window */
HWND
hparent
;
/* Handle of the parent window */
...
...
@@ -58,15 +52,13 @@ struct vout_sys_t
HMONITOR
(
WINAPI
*
MonitorFromWindow
)(
HWND
,
DWORD
);
BOOL
(
WINAPI
*
GetMonitorInfo
)(
HMONITOR
,
LPMONITORINFO
);
vlc_bool_t
b_using_overlay
;
/* Are we using an overlay surface */
vlc_bool_t
b_use_sysmem
;
/* Should we use system memory for surfaces */
vlc_bool_t
b_hw_yuv
;
/* Should we use hardware YUV->RGB conversions */
vlc_bool_t
b_3buf_overlay
;
/* Should we use triple buffered overlays */
/* size of the display */
RECT
rect_display
;
int
i_display_depth
;
/* size of the overall window (including black bands) */
RECT
rect_parent
;
/* Window position and size */
int
i_window_x
;
int
i_window_y
;
...
...
@@ -74,65 +66,74 @@ struct vout_sys_t
int
i_window_height
;
int
i_window_style
;
volatile
uint16_t
i_changes
;
/* changes made to the video display */
/* Mouse */
volatile
vlc_bool_t
b_cursor_hidden
;
volatile
mtime_t
i_lastmoved
;
/* Misc */
vlc_bool_t
b_on_top_change
;
vlc_bool_t
b_wallpaper
;
/* screensaver system settings to be restored when vout is closed */
UINT
i_spi_lowpowertimeout
;
UINT
i_spi_powerofftimeout
;
UINT
i_spi_screensavetimeout
;
/* 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
;
RECT
rect_parent
;
#ifdef MODULE_NAME_IS_vout_directx
/* Overlay alignment restrictions */
int
i_align_src_boundary
;
int
i_align_src_size
;
int
i_align_dest_boundary
;
int
i_align_dest_size
;
vlc_bool_t
b_using_overlay
;
/* Are we using an overlay surface */
vlc_bool_t
b_use_sysmem
;
/* Should we use system memory for surfaces */
vlc_bool_t
b_hw_yuv
;
/* Should we use hardware YUV->RGB conversions */
vlc_bool_t
b_3buf_overlay
;
/* Should we use triple buffered overlays */
/* DDraw capabilities */
int
b_caps_overlay_clipping
;
int
i_rgb_colorkey
;
/* colorkey in RGB used by the overlay */
int
i_colorkey
;
/* colorkey used by the overlay */
volatile
uint16_t
i_changes
;
/* changes made to the video display */
/* Mouse */
volatile
vlc_bool_t
b_cursor_hidden
;
volatile
mtime_t
i_lastmoved
;
/* Misc */
vlc_bool_t
b_on_top_change
;
vlc_bool_t
b_wallpaper
;
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 */
#endif
#ifdef MODULE_NAME_IS_glwin32
HDC
hGLDC
;
HGLRC
hGLRC
;
#endif
/* screensaver system settings to be restored when vout is closed */
UINT
i_spi_lowpowertimeout
;
UINT
i_spi_powerofftimeout
;
UINT
i_spi_screensavetimeout
;
#ifdef MODULE_NAME_IS_direct3d
// core objects
LPDIRECT3D9
p_d3dobj
;
LPDIRECT3DDEVICE9
p_d3ddev
;
D3DPRESENT_PARAMETERS
d3dpp
;
// scene objects
LPDIRECT3DTEXTURE9
p_d3dtex
;
LPDIRECT3DVERTEXBUFFER9
p_d3dvtc
;
#endif
event_thread_t
*
p_event
;
vlc_mutex_t
lock
;
};
/*****************************************************************************
* picture_sys_t: direct buffer method descriptor
*****************************************************************************
* This structure is part of the picture descriptor, it describes the
* DirectX specific properties of a direct buffer.
*****************************************************************************/
struct
picture_sys_t
{
LPDIRECTDRAWSURFACE2
p_surface
;
DDSURFACEDESC
ddsd
;
LPDIRECTDRAWSURFACE2
p_front_surface
;
};
/*****************************************************************************
* Prototypes from vout.c
*****************************************************************************/
...
...
@@ -149,8 +150,7 @@ void E_(DirectXUpdateRects) ( vout_thread_t *p_vout, vlc_bool_t b_force );
*****************************************************************************/
#define WM_VLC_HIDE_MOUSE WM_APP
#define WM_VLC_SHOW_MOUSE WM_APP + 1
#define WM_VLC_CREATE_VIDEO_WIN WM_APP + 2
#define WM_VLC_CHANGE_TEXT WM_APP + 3
#define WM_VLC_CHANGE_TEXT WM_APP + 2
#define IDM_TOGGLE_ON_TOP WM_USER + 1
#define DX_POSITION_CHANGE 0x1000
#define DX_WALLPAPER_CHANGE 0x2000
...
...
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