Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in
Toggle navigation
V
vlc-2-2
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-2-2
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
Hide 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])
VLC_ADD_LDFLAGS([glwin32],[-lopengl32 -lgdi32])
]) ])
])
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