Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in
Toggle navigation
V
vlc-gpu
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
0
Issues
0
List
Boards
Labels
Milestones
Redmine
Redmine
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Operations
Operations
Metrics
Environments
Analytics
Analytics
CI / CD
Repository
Value Stream
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
videolan
vlc-gpu
Commits
e8534473
Commit
e8534473
authored
Aug 09, 2009
by
Laurent Aimar
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Converted vout xcb to "vout display" API.
parent
c48d9cfc
Changes
5
Hide whitespace changes
Inline
Side-by-side
Showing
5 changed files
with
694 additions
and
590 deletions
+694
-590
modules/video_output/xcb/common.c
modules/video_output/xcb/common.c
+48
-73
modules/video_output/xcb/events.c
modules/video_output/xcb/events.c
+66
-48
modules/video_output/xcb/x11.c
modules/video_output/xcb/x11.c
+219
-158
modules/video_output/xcb/xcb_vlc.h
modules/video_output/xcb/xcb_vlc.h
+19
-11
modules/video_output/xcb/xvideo.c
modules/video_output/xcb/xvideo.c
+342
-300
No files found.
modules/video_output/xcb/common.c
View file @
e8534473
...
@@ -34,11 +34,27 @@
...
@@ -34,11 +34,27 @@
#include <xcb/shm.h>
#include <xcb/shm.h>
#include <vlc_common.h>
#include <vlc_common.h>
#include <vlc_vout.h>
#include <vlc_vout_display.h>
#include <vlc_vout_window.h>
#include "xcb_vlc.h"
#include "xcb_vlc.h"
/**
* Check for an error
*/
int
CheckError
(
vout_display_t
*
vd
,
xcb_connection_t
*
conn
,
const
char
*
str
,
xcb_void_cookie_t
ck
)
{
xcb_generic_error_t
*
err
;
err
=
xcb_request_check
(
conn
,
ck
);
if
(
err
)
{
msg_Err
(
vd
,
"%s: X11 error %d"
,
str
,
err
->
error_code
);
return
VLC_EGENERIC
;
}
return
VLC_SUCCESS
;
}
/**
/**
* Connect to the X server.
* Connect to the X server.
*/
*/
...
@@ -62,7 +78,7 @@ xcb_connection_t *Connect (vlc_object_t *obj)
...
@@ -62,7 +78,7 @@ xcb_connection_t *Connect (vlc_object_t *obj)
* Create a VLC video X window object, find the corresponding X server screen,
* Create a VLC video X window object, find the corresponding X server screen,
* and probe the MIT-SHM extension.
* and probe the MIT-SHM extension.
*/
*/
vout_window_t
*
GetWindow
(
vout_
thread_t
*
obj
,
vout_window_t
*
GetWindow
(
vout_
display_t
*
vd
,
xcb_connection_t
*
conn
,
xcb_connection_t
*
conn
,
const
xcb_screen_t
**
restrict
pscreen
,
const
xcb_screen_t
**
restrict
pscreen
,
bool
*
restrict
pshm
)
bool
*
restrict
pshm
)
...
@@ -73,14 +89,13 @@ vout_window_t *GetWindow (vout_thread_t *obj,
...
@@ -73,14 +89,13 @@ vout_window_t *GetWindow (vout_thread_t *obj,
memset
(
&
wnd_cfg
,
0
,
sizeof
(
wnd_cfg
)
);
memset
(
&
wnd_cfg
,
0
,
sizeof
(
wnd_cfg
)
);
wnd_cfg
.
type
=
VOUT_WINDOW_TYPE_XID
;
wnd_cfg
.
type
=
VOUT_WINDOW_TYPE_XID
;
wnd_cfg
.
width
=
obj
->
i_window_width
;
wnd_cfg
.
width
=
vd
->
cfg
->
display
.
width
;
wnd_cfg
.
height
=
obj
->
i_window_height
;
wnd_cfg
.
height
=
vd
->
cfg
->
display
.
height
;
vout_window_t
*
wnd
=
vout_window_New
(
VLC_OBJECT
(
obj
),
NULL
,
&
wnd_cfg
);
vout_window_t
*
wnd
=
vout_display_NewWindow
(
vd
,
&
wnd_cfg
);
if
(
wnd
==
NULL
)
if
(
wnd
==
NULL
)
{
{
msg_Err
(
obj
,
"parent window not available"
);
msg_Err
(
vd
,
"parent window not available"
);
return
NULL
;
return
NULL
;
}
}
else
else
...
@@ -92,7 +107,7 @@ vout_window_t *GetWindow (vout_thread_t *obj,
...
@@ -92,7 +107,7 @@ vout_window_t *GetWindow (vout_thread_t *obj,
geo
=
xcb_get_geometry_reply
(
conn
,
ck
,
NULL
);
geo
=
xcb_get_geometry_reply
(
conn
,
ck
,
NULL
);
if
(
geo
==
NULL
)
if
(
geo
==
NULL
)
{
{
msg_Err
(
obj
,
"parent window not valid"
);
msg_Err
(
vd
,
"parent window not valid"
);
goto
error
;
goto
error
;
}
}
root
=
geo
->
root
;
root
=
geo
->
root
;
...
@@ -116,13 +131,13 @@ vout_window_t *GetWindow (vout_thread_t *obj,
...
@@ -116,13 +131,13 @@ vout_window_t *GetWindow (vout_thread_t *obj,
if
(
screen
==
NULL
)
if
(
screen
==
NULL
)
{
{
msg_Err
(
obj
,
"parent window screen not found"
);
msg_Err
(
vd
,
"parent window screen not found"
);
goto
error
;
goto
error
;
}
}
msg_Dbg
(
obj
,
"using screen 0x%"
PRIx32
,
root
);
msg_Dbg
(
vd
,
"using screen 0x%"
PRIx32
,
root
);
/* Check MIT-SHM shared memory support */
/* Check MIT-SHM shared memory support */
bool
shm
=
var_CreateGetBool
(
obj
,
"x11-shm"
)
>
0
;
bool
shm
=
var_CreateGetBool
(
vd
,
"x11-shm"
)
>
0
;
if
(
shm
)
if
(
shm
)
{
{
xcb_shm_query_version_cookie_t
ck
;
xcb_shm_query_version_cookie_t
ck
;
...
@@ -132,8 +147,8 @@ vout_window_t *GetWindow (vout_thread_t *obj,
...
@@ -132,8 +147,8 @@ vout_window_t *GetWindow (vout_thread_t *obj,
r
=
xcb_shm_query_version_reply
(
conn
,
ck
,
NULL
);
r
=
xcb_shm_query_version_reply
(
conn
,
ck
,
NULL
);
if
(
!
r
)
if
(
!
r
)
{
{
msg_Err
(
obj
,
"shared memory (MIT-SHM) not available"
);
msg_Err
(
vd
,
"shared memory (MIT-SHM) not available"
);
msg_Warn
(
obj
,
"display will be slow"
);
msg_Warn
(
vd
,
"display will be slow"
);
shm
=
false
;
shm
=
false
;
}
}
free
(
r
);
free
(
r
);
...
@@ -144,7 +159,7 @@ vout_window_t *GetWindow (vout_thread_t *obj,
...
@@ -144,7 +159,7 @@ vout_window_t *GetWindow (vout_thread_t *obj,
return
wnd
;
return
wnd
;
error:
error:
vout_
window_Delete
(
wnd
);
vout_
display_DeleteWindow
(
vd
,
wnd
);
return
NULL
;
return
NULL
;
}
}
...
@@ -168,19 +183,22 @@ int GetWindowSize (struct vout_window_t *wnd, xcb_connection_t *conn,
...
@@ -168,19 +183,22 @@ int GetWindowSize (struct vout_window_t *wnd, xcb_connection_t *conn,
/**
/**
* Initialize a picture buffer as shared memory, according to the video output
* Initialize a picture buffer as shared memory, according to the video output
* format. If a
XCB connection pointer is supplied
, the segment is attached to
* format. If a
attach is true
, the segment is attached to
* the X server (MIT-SHM extension).
* the X server (MIT-SHM extension).
*/
*/
int
Picture
Alloc
(
vout_thread_t
*
vout
,
picture_t
*
pic
,
size_t
size
,
int
Picture
ResourceAlloc
(
vout_display_t
*
vd
,
picture_resource_t
*
res
,
size_t
size
,
xcb_connection_t
*
conn
)
xcb_connection_t
*
conn
,
bool
attach
)
{
{
assert
(
pic
->
i_status
==
FREE_PICTURE
);
res
->
p_sys
=
malloc
(
sizeof
(
*
res
->
p_sys
));
if
(
!
res
->
p_sys
)
return
VLC_EGENERIC
;
/* Allocate shared memory segment */
/* Allocate shared memory segment */
int
id
=
shmget
(
IPC_PRIVATE
,
size
,
IPC_CREAT
|
0700
);
int
id
=
shmget
(
IPC_PRIVATE
,
size
,
IPC_CREAT
|
0700
);
if
(
id
==
-
1
)
if
(
id
==
-
1
)
{
{
msg_Err
(
vout
,
"shared memory allocation error: %m"
);
msg_Err
(
vd
,
"shared memory allocation error: %m"
);
free
(
res
->
p_sys
);
return
VLC_EGENERIC
;
return
VLC_EGENERIC
;
}
}
...
@@ -188,13 +206,14 @@ int PictureAlloc (vout_thread_t *vout, picture_t *pic, size_t size,
...
@@ -188,13 +206,14 @@ int PictureAlloc (vout_thread_t *vout, picture_t *pic, size_t size,
void
*
shm
=
shmat
(
id
,
NULL
,
0
/* read/write */
);
void
*
shm
=
shmat
(
id
,
NULL
,
0
/* read/write */
);
if
(
-
1
==
(
intptr_t
)
shm
)
if
(
-
1
==
(
intptr_t
)
shm
)
{
{
msg_Err
(
v
out
,
"shared memory attachment error: %m"
);
msg_Err
(
v
d
,
"shared memory attachment error: %m"
);
shmctl
(
id
,
IPC_RMID
,
0
);
shmctl
(
id
,
IPC_RMID
,
0
);
free
(
res
->
p_sys
);
return
VLC_EGENERIC
;
return
VLC_EGENERIC
;
}
}
xcb_shm_seg_t
segment
;
xcb_shm_seg_t
segment
;
if
(
conn
!=
NULL
)
if
(
attach
)
{
{
/* Attach the segment to X */
/* Attach the segment to X */
xcb_void_cookie_t
ck
;
xcb_void_cookie_t
ck
;
...
@@ -202,9 +221,9 @@ int PictureAlloc (vout_thread_t *vout, picture_t *pic, size_t size,
...
@@ -202,9 +221,9 @@ int PictureAlloc (vout_thread_t *vout, picture_t *pic, size_t size,
segment
=
xcb_generate_id
(
conn
);
segment
=
xcb_generate_id
(
conn
);
ck
=
xcb_shm_attach_checked
(
conn
,
segment
,
id
,
1
);
ck
=
xcb_shm_attach_checked
(
conn
,
segment
,
id
,
1
);
if
(
CheckError
(
v
out
,
"shared memory server-side error"
,
ck
))
if
(
CheckError
(
v
d
,
conn
,
"shared memory server-side error"
,
ck
))
{
{
msg_Info
(
v
out
,
"using buggy X11 server - SSH proxying?"
);
msg_Info
(
v
d
,
"using buggy X11 server - SSH proxying?"
);
segment
=
0
;
segment
=
0
;
}
}
}
}
...
@@ -212,67 +231,23 @@ int PictureAlloc (vout_thread_t *vout, picture_t *pic, size_t size,
...
@@ -212,67 +231,23 @@ int PictureAlloc (vout_thread_t *vout, picture_t *pic, size_t size,
segment
=
0
;
segment
=
0
;
shmctl
(
id
,
IPC_RMID
,
0
);
shmctl
(
id
,
IPC_RMID
,
0
);
pic
->
p_sys
=
(
void
*
)(
uintptr_t
)
segment
;
res
->
p_sys
->
segment
=
segment
;
pic
->
p
->
p_pixels
=
shm
;
res
->
p
->
p_pixels
=
shm
;
pic
->
i_status
=
DESTROYED_PICTURE
;
pic
->
i_type
=
DIRECT_PICTURE
;
return
VLC_SUCCESS
;
return
VLC_SUCCESS
;
}
}
/**
/**
* Release picture private data: detach the shared memory segment.
* Release picture private data: detach the shared memory segment.
*/
*/
void
Picture
Free
(
picture_t
*
pic
,
xcb_connection_t
*
conn
)
void
Picture
ResourceFree
(
picture_resource_t
*
res
,
xcb_connection_t
*
conn
)
{
{
xcb_shm_seg_t
segment
=
(
uintptr_t
)
pic
->
p_sys
;
xcb_shm_seg_t
segment
=
res
->
p_sys
->
segment
;
if
(
segment
!=
0
)
if
(
segment
!=
0
)
{
{
assert
(
conn
!=
NULL
);
assert
(
conn
!=
NULL
);
xcb_shm_detach
(
conn
,
segment
);
xcb_shm_detach
(
conn
,
segment
);
}
}
shmdt
(
pic
->
p
->
p_pixels
);
shmdt
(
res
->
p
->
p_pixels
);
}
}
/**
* Video output thread management stuff.
* FIXME: Much of this should move to core
*/
void
CommonManage
(
vout_thread_t
*
vout
)
{
if
(
vout
->
i_changes
&
VOUT_SCALE_CHANGE
)
{
vout
->
b_autoscale
=
var_GetBool
(
vout
,
"autoscale"
);
vout
->
i_zoom
=
ZOOM_FP_FACTOR
;
vout
->
i_changes
&=
~
VOUT_SCALE_CHANGE
;
vout
->
i_changes
|=
VOUT_SIZE_CHANGE
;
}
if
(
vout
->
i_changes
&
VOUT_ZOOM_CHANGE
)
{
vout
->
b_autoscale
=
false
;
vout
->
i_zoom
=
var_GetFloat
(
vout
,
"scale"
)
*
ZOOM_FP_FACTOR
;
vout
->
i_changes
&=
~
VOUT_ZOOM_CHANGE
;
vout
->
i_changes
|=
VOUT_SIZE_CHANGE
;
}
if
(
vout
->
i_changes
&
VOUT_CROP_CHANGE
)
{
vout
->
fmt_out
.
i_x_offset
=
vout
->
fmt_in
.
i_x_offset
;
vout
->
fmt_out
.
i_y_offset
=
vout
->
fmt_in
.
i_y_offset
;
vout
->
fmt_out
.
i_visible_width
=
vout
->
fmt_in
.
i_visible_width
;
vout
->
fmt_out
.
i_visible_height
=
vout
->
fmt_in
.
i_visible_height
;
vout
->
i_changes
&=
~
VOUT_CROP_CHANGE
;
vout
->
i_changes
|=
VOUT_SIZE_CHANGE
;
}
if
(
vout
->
i_changes
&
VOUT_ASPECT_CHANGE
)
{
vout
->
fmt_out
.
i_aspect
=
vout
->
fmt_in
.
i_aspect
;
vout
->
fmt_out
.
i_sar_num
=
vout
->
fmt_in
.
i_sar_num
;
vout
->
fmt_out
.
i_sar_den
=
vout
->
fmt_in
.
i_sar_den
;
vout
->
output
.
i_aspect
=
vout
->
fmt_in
.
i_aspect
;
vout
->
i_changes
&=
~
VOUT_ASPECT_CHANGE
;
vout
->
i_changes
|=
VOUT_SIZE_CHANGE
;
}
}
modules/video_output/xcb/events.c
View file @
e8534473
...
@@ -30,7 +30,7 @@
...
@@ -30,7 +30,7 @@
#include <xcb/xcb.h>
#include <xcb/xcb.h>
#include <vlc_common.h>
#include <vlc_common.h>
#include <vlc_vout.h>
#include <vlc_vout
_display
.h>
#include "xcb_vlc.h"
#include "xcb_vlc.h"
...
@@ -39,76 +39,67 @@
...
@@ -39,76 +39,67 @@
* Otherwise, we'd var_OrInteger() and var_NandInteger() functions...
* Otherwise, we'd var_OrInteger() and var_NandInteger() functions...
*/
*/
static
void
HandleButtonPress
(
vout_thread_t
*
vout
,
/* FIXME we assume direct mapping between XCB and VLC */
static
void
HandleButtonPress
(
vout_display_t
*
vd
,
xcb_button_press_event_t
*
ev
)
xcb_button_press_event_t
*
ev
)
{
{
unsigned
buttons
=
var_GetInteger
(
vout
,
"mouse-button-down"
);
vout_display_SendEventMousePressed
(
vd
,
ev
->
detail
-
1
);
buttons
|=
(
1
<<
(
ev
->
detail
-
1
));
var_SetInteger
(
vout
,
"mouse-button-down"
,
buttons
);
}
}
static
void
HandleButtonRelease
(
vout_
thread_t
*
vout
,
static
void
HandleButtonRelease
(
vout_
display_t
*
vd
,
xcb_button_release_event_t
*
ev
)
xcb_button_release_event_t
*
ev
)
{
{
unsigned
buttons
=
var_GetInteger
(
vout
,
"mouse-button-down"
);
vout_display_SendEventMouseReleased
(
vd
,
ev
->
detail
-
1
);
buttons
&=
~
(
1
<<
(
ev
->
detail
-
1
));
var_SetInteger
(
vout
,
"mouse-button-down"
,
buttons
);
switch
(
ev
->
detail
)
{
case
1
:
/* left mouse button */
var_SetBool
(
vout
,
"mouse-clicked"
,
true
);
var_SetBool
(
vout
->
p_libvlc
,
"intf-popupmenu"
,
false
);
break
;
case
3
:
var_SetBool
(
vout
->
p_libvlc
,
"intf-popupmenu"
,
true
);
break
;
}
}
}
static
void
HandleMotionNotify
(
vout_
thread_t
*
vout
,
static
void
HandleMotionNotify
(
vout_
display_t
*
vd
,
xcb_motion_notify_event_t
*
ev
)
xcb_motion_notify_event_t
*
ev
)
{
{
unsigned
x
,
y
,
width
,
height
;
vout_display_place_t
place
;
int
v
;
/* TODO it could be saved */
vout_PlacePicture
(
vout
,
vout
->
output
.
i_width
,
vout
->
output
.
i_height
,
vout_display_PlacePicture
(
&
place
,
&
vd
->
source
,
vd
->
cfg
,
false
);
&
x
,
&
y
,
&
width
,
&
height
);
v
=
vout
->
fmt_in
.
i_x_offset
if
(
place
.
width
<=
0
||
place
.
height
<=
0
)
+
((
ev
->
event_x
-
x
)
*
vout
->
fmt_in
.
i_visible_width
/
width
);
return
;
if
(
v
<
0
)
v
=
0
;
/* to the left of the picture */
const
int
x
=
vd
->
source
.
i_x_offset
+
else
if
((
unsigned
)
v
>
vout
->
fmt_in
.
i_width
)
(
int64_t
)(
ev
->
event_x
-
0
*
place
.
x
)
*
vd
->
source
.
i_visible_width
/
place
.
width
;
v
=
vout
->
fmt_in
.
i_width
;
/* to the right of the picture */
const
int
y
=
vd
->
source
.
i_y_offset
+
var_SetInteger
(
vout
,
"mouse-x"
,
v
);
(
int64_t
)(
ev
->
event_y
-
0
*
place
.
y
)
*
vd
->
source
.
i_visible_height
/
place
.
height
;
v
=
vout
->
fmt_in
.
i_y_offset
/* TODO show the cursor ? */
+
((
ev
->
event_y
-
y
)
*
vout
->
fmt_in
.
i_visible_height
/
height
);
if
(
x
>=
vd
->
source
.
i_x_offset
&&
x
<
vd
->
source
.
i_x_offset
+
vd
->
source
.
i_visible_width
&&
if
(
v
<
0
)
y
>=
vd
->
source
.
i_y_offset
&&
y
<
vd
->
source
.
i_y_offset
+
vd
->
source
.
i_visible_height
)
v
=
0
;
/* above the picture */
vout_display_SendEventMouseMoved
(
vd
,
x
,
y
);
else
if
((
unsigned
)
v
>
vout
->
fmt_in
.
i_height
)
}
v
=
vout
->
fmt_in
.
i_height
;
/* below the picture */
var_SetInteger
(
vout
,
"mouse-y"
,
v
);
static
void
HandleParentStructure
(
vout_display_t
*
vd
,
xcb_configure_notify_event_t
*
ev
)
{
if
(
ev
->
width
!=
vd
->
cfg
->
display
.
width
||
ev
->
height
!=
vd
->
cfg
->
display
.
height
)
vout_display_SendEventDisplaySize
(
vd
,
ev
->
width
,
ev
->
height
);
}
}
/**
/**
* Process an X11 event.
* Process an X11 event.
*/
*/
int
ProcessEvent
(
vout_thread_t
*
vout
,
xcb_connection_t
*
conn
,
static
int
ProcessEvent
(
vout_display_t
*
vd
,
xcb_window_t
window
,
xcb_generic_event_t
*
ev
)
xcb_window_t
window
,
xcb_generic_event_t
*
ev
)
{
{
switch
(
ev
->
response_type
&
0x7f
)
switch
(
ev
->
response_type
&
0x7f
)
{
{
case
XCB_BUTTON_PRESS
:
case
XCB_BUTTON_PRESS
:
HandleButtonPress
(
v
out
,
(
xcb_button_press_event_t
*
)
ev
);
HandleButtonPress
(
v
d
,
(
xcb_button_press_event_t
*
)
ev
);
break
;
break
;
case
XCB_BUTTON_RELEASE
:
case
XCB_BUTTON_RELEASE
:
HandleButtonRelease
(
v
out
,
(
xcb_button_release_event_t
*
)
ev
);
HandleButtonRelease
(
v
d
,
(
xcb_button_release_event_t
*
)
ev
);
break
;
break
;
case
XCB_MOTION_NOTIFY
:
case
XCB_MOTION_NOTIFY
:
HandleMotionNotify
(
v
out
,
(
xcb_motion_notify_event_t
*
)
ev
);
HandleMotionNotify
(
v
d
,
(
xcb_motion_notify_event_t
*
)
ev
);
break
;
break
;
case
XCB_CONFIGURE_NOTIFY
:
case
XCB_CONFIGURE_NOTIFY
:
...
@@ -117,14 +108,41 @@ int ProcessEvent (vout_thread_t *vout, xcb_connection_t *conn,
...
@@ -117,14 +108,41 @@ int ProcessEvent (vout_thread_t *vout, xcb_connection_t *conn,
(
xcb_configure_notify_event_t
*
)
ev
;
(
xcb_configure_notify_event_t
*
)
ev
;
assert
(
cn
->
window
!=
window
);
assert
(
cn
->
window
!=
window
);
HandleParentStructure
(
v
out
,
conn
,
window
,
cn
);
HandleParentStructure
(
v
d
,
cn
);
break
;
break
;
}
}
/* FIXME I am not sure it is the right one */
case
XCB_DESTROY_NOTIFY
:
vout_display_SendEventClose
(
vd
);
break
;
default:
default:
msg_Dbg
(
v
out
,
"unhandled event %"
PRIu8
,
ev
->
response_type
);
msg_Dbg
(
v
d
,
"unhandled event %"
PRIu8
,
ev
->
response_type
);
}
}
free
(
ev
);
free
(
ev
);
return
VLC_SUCCESS
;
return
VLC_SUCCESS
;
}
}
/**
* Process incoming X events.
*/
int
ManageEvent
(
vout_display_t
*
vd
,
xcb_connection_t
*
conn
,
xcb_window_t
window
)
{
xcb_generic_event_t
*
ev
;
while
((
ev
=
xcb_poll_for_event
(
conn
))
!=
NULL
)
ProcessEvent
(
vd
,
window
,
ev
);
if
(
xcb_connection_has_error
(
conn
))
{
msg_Err
(
vd
,
"X server failure"
);
return
VLC_EGENERIC
;
}
return
VLC_SUCCESS
;
}
modules/video_output/xcb/x11.c
View file @
e8534473
...
@@ -32,8 +32,8 @@
...
@@ -32,8 +32,8 @@
#include <vlc_common.h>
#include <vlc_common.h>
#include <vlc_plugin.h>
#include <vlc_plugin.h>
#include <vlc_vout.h>
#include <vlc_vout
_display
.h>
#include <vlc_
vout_window
.h>
#include <vlc_
picture_pool
.h>
#include "xcb_vlc.h"
#include "xcb_vlc.h"
...
@@ -57,7 +57,7 @@ vlc_module_begin ()
...
@@ -57,7 +57,7 @@ vlc_module_begin ()
set_description
(
N_
(
"(Experimental) XCB video output"
))
set_description
(
N_
(
"(Experimental) XCB video output"
))
set_category
(
CAT_VIDEO
)
set_category
(
CAT_VIDEO
)
set_subcategory
(
SUBCAT_VIDEO_VOUT
)
set_subcategory
(
SUBCAT_VIDEO_VOUT
)
set_capability
(
"v
ideo output
"
,
0
)
set_capability
(
"v
out display
"
,
0
)
set_callbacks
(
Open
,
Close
)
set_callbacks
(
Open
,
Close
)
add_string
(
"x11-display"
,
NULL
,
NULL
,
add_string
(
"x11-display"
,
NULL
,
NULL
,
...
@@ -65,7 +65,13 @@ vlc_module_begin ()
...
@@ -65,7 +65,13 @@ vlc_module_begin ()
add_bool
(
"x11-shm"
,
true
,
NULL
,
SHM_TEXT
,
SHM_LONGTEXT
,
true
)
add_bool
(
"x11-shm"
,
true
,
NULL
,
SHM_TEXT
,
SHM_LONGTEXT
,
true
)
vlc_module_end
()
vlc_module_end
()
struct
vout_sys_t
/* It must be large enough to absorb the server display jitter but it is
* useless to used a too large value, direct rendering cannot be used with
* xcb x11
*/
#define MAX_PICTURES (3)
struct
vout_display_sys_t
{
{
xcb_connection_t
*
conn
;
xcb_connection_t
*
conn
;
vout_window_t
*
embed
;
/* VLC window (when windowed) */
vout_window_t
*
embed
;
/* VLC window (when windowed) */
...
@@ -77,40 +83,29 @@ struct vout_sys_t
...
@@ -77,40 +83,29 @@ struct vout_sys_t
uint8_t
pad
;
/* scanline pad */
uint8_t
pad
;
/* scanline pad */
uint8_t
depth
;
/* useful bits per pixel */
uint8_t
depth
;
/* useful bits per pixel */
uint8_t
byte_order
;
/* server byte order */
uint8_t
byte_order
;
/* server byte order */
};
static
int
Init
(
vout_thread_t
*
);
picture_pool_t
*
pool
;
/* picture pool */
static
void
Deinit
(
vout_thread_t
*
);
picture_resource_t
resource
[
MAX_PICTURES
];
static
void
Display
(
vout_thread_t
*
,
picture_t
*
);
};
static
int
Manage
(
vout_thread_t
*
);
static
int
Control
(
vout_thread_t
*
,
int
,
va_list
);
int
CheckError
(
vout_thread_t
*
vout
,
const
char
*
str
,
xcb_void_cookie_t
ck
)
{
xcb_generic_error_t
*
err
;
err
=
xcb_request_check
(
vout
->
p_sys
->
conn
,
ck
);
static
picture_t
*
Get
(
vout_display_t
*
);
if
(
err
)
static
void
Display
(
vout_display_t
*
,
picture_t
*
);
{
static
int
Control
(
vout_display_t
*
,
int
,
va_list
);
msg_Err
(
vout
,
"%s: X11 error %d"
,
str
,
err
->
error_code
);
static
void
Manage
(
vout_display_t
*
);
return
VLC_EGENERIC
;
}
return
VLC_SUCCESS
;
}
#define p_vout vout
static
void
ResetPictures
(
vout_display_t
*
);
/**
/**
* Probe the X server.
* Probe the X server.
*/
*/
static
int
Open
(
vlc_object_t
*
obj
)
static
int
Open
(
vlc_object_t
*
obj
)
{
{
vout_
thread_t
*
vout
=
(
vout_thread
_t
*
)
obj
;
vout_
display_t
*
vd
=
(
vout_display
_t
*
)
obj
;
vout_sys_t
*
p_sys
=
malloc
(
sizeof
(
*
p_sys
));
vout_
display_
sys_t
*
p_sys
=
malloc
(
sizeof
(
*
p_sys
));
if
(
p_sys
==
NULL
)
if
(
p_sys
==
NULL
)
return
VLC_ENOMEM
;
return
VLC_ENOMEM
;
v
out
->
p_
sys
=
p_sys
;
v
d
->
sys
=
p_sys
;
/* Connect to X */
/* Connect to X */
p_sys
->
conn
=
Connect
(
obj
);
p_sys
->
conn
=
Connect
(
obj
);
...
@@ -122,7 +117,7 @@ static int Open (vlc_object_t *obj)
...
@@ -122,7 +117,7 @@ static int Open (vlc_object_t *obj)
/* Get window */
/* Get window */
const
xcb_screen_t
*
scr
;
const
xcb_screen_t
*
scr
;
p_sys
->
embed
=
GetWindow
(
v
out
,
p_sys
->
conn
,
&
scr
,
&
p_sys
->
shm
);
p_sys
->
embed
=
GetWindow
(
v
d
,
p_sys
->
conn
,
&
scr
,
&
p_sys
->
shm
);
if
(
p_sys
->
embed
==
NULL
)
if
(
p_sys
->
embed
==
NULL
)
{
{
xcb_disconnect
(
p_sys
->
conn
);
xcb_disconnect
(
p_sys
->
conn
);
...
@@ -133,6 +128,9 @@ static int Open (vlc_object_t *obj)
...
@@ -133,6 +128,9 @@ static int Open (vlc_object_t *obj)
const
xcb_setup_t
*
setup
=
xcb_get_setup
(
p_sys
->
conn
);
const
xcb_setup_t
*
setup
=
xcb_get_setup
(
p_sys
->
conn
);
p_sys
->
byte_order
=
setup
->
image_byte_order
;
p_sys
->
byte_order
=
setup
->
image_byte_order
;
/* */
video_format_t
fmt_pic
=
vd
->
fmt
;
/* Determine our video format. Normally, this is done in pf_init(), but
/* Determine our video format. Normally, this is done in pf_init(), but
* this plugin always uses the same format for a given X11 screen. */
* this plugin always uses the same format for a given X11 screen. */
xcb_visualid_t
vid
=
0
;
xcb_visualid_t
vid
=
0
;
...
@@ -213,12 +211,12 @@ static int Open (vlc_object_t *obj)
...
@@ -213,12 +211,12 @@ static int Open (vlc_object_t *obj)
if
(
!
vid
)
if
(
!
vid
)
continue
;
/* The screen does not *really* support this depth */
continue
;
/* The screen does not *really* support this depth */
vout
->
fmt_out
.
i_chroma
=
vout
->
output
.
i_chroma
=
chroma
;
fmt_pic
.
i_chroma
=
chroma
;
if
(
!
gray
)
if
(
!
gray
)
{
{
vout
->
fmt_out
.
i_rmask
=
vout
->
output
.
i_rmask
=
vt
->
red_mask
;
fmt_pic
.
i_rmask
=
vt
->
red_mask
;
vout
->
fmt_out
.
i_gmask
=
vout
->
output
.
i_gmask
=
vt
->
green_mask
;
fmt_pic
.
i_gmask
=
vt
->
green_mask
;
vout
->
fmt_out
.
i_bmask
=
vout
->
output
.
i_bmask
=
vt
->
blue_mask
;
fmt_pic
.
i_bmask
=
vt
->
blue_mask
;
}
}
p_sys
->
bpp
=
fmt
->
bits_per_pixel
;
p_sys
->
bpp
=
fmt
->
bits_per_pixel
;
p_sys
->
pad
=
fmt
->
scanline_pad
;
p_sys
->
pad
=
fmt
->
scanline_pad
;
...
@@ -227,12 +225,12 @@ static int Open (vlc_object_t *obj)
...
@@ -227,12 +225,12 @@ static int Open (vlc_object_t *obj)
if
(
depth
==
0
)
if
(
depth
==
0
)
{
{
msg_Err
(
v
out
,
"no supported pixmap formats or visual types"
);
msg_Err
(
v
d
,
"no supported pixmap formats or visual types"
);
goto
error
;
goto
error
;
}
}
msg_Dbg
(
v
out
,
"using X11 visual ID 0x%"
PRIx32
,
vid
);
msg_Dbg
(
v
d
,
"using X11 visual ID 0x%"
PRIx32
,
vid
);
msg_Dbg
(
v
out
,
" %"
PRIu8
" bits per pixels, %"
PRIu8
" bits line pad"
,
msg_Dbg
(
v
d
,
" %"
PRIu8
" bits per pixels, %"
PRIu8
" bits line pad"
,
p_sys
->
bpp
,
p_sys
->
pad
);
p_sys
->
bpp
,
p_sys
->
pad
);
/* Create colormap (needed to select non-default visual) */
/* Create colormap (needed to select non-default visual) */
...
@@ -263,23 +261,41 @@ static int Open (vlc_object_t *obj)
...
@@ -263,23 +261,41 @@ static int Open (vlc_object_t *obj)
p_sys
->
embed
->
handle
.
xid
,
0
,
0
,
1
,
1
,
0
,
p_sys
->
embed
->
handle
.
xid
,
0
,
0
,
1
,
1
,
0
,
XCB_WINDOW_CLASS_INPUT_OUTPUT
,
XCB_WINDOW_CLASS_INPUT_OUTPUT
,
vid
,
mask
,
values
);
vid
,
mask
,
values
);
if
(
CheckError
(
v
out
,
"cannot create X11 window"
,
c
))
if
(
CheckError
(
v
d
,
p_sys
->
conn
,
"cannot create X11 window"
,
c
))
goto
error
;
goto
error
;
p_sys
->
window
=
window
;
p_sys
->
window
=
window
;
msg_Dbg
(
v
out
,
"using X11 window %08"
PRIx32
,
p_sys
->
window
);
msg_Dbg
(
v
d
,
"using X11 window %08"
PRIx32
,
p_sys
->
window
);
xcb_map_window
(
p_sys
->
conn
,
window
);
xcb_map_window
(
p_sys
->
conn
,
window
);
}
}
/* Create graphic context (I wonder why the heck do we need this) */
/* Create graphic context (I wonder why the heck do we need this) */
p_sys
->
gc
=
xcb_generate_id
(
p_sys
->
conn
);
p_sys
->
gc
=
xcb_generate_id
(
p_sys
->
conn
);
xcb_create_gc
(
p_sys
->
conn
,
p_sys
->
gc
,
p_sys
->
window
,
0
,
NULL
);
xcb_create_gc
(
p_sys
->
conn
,
p_sys
->
gc
,
p_sys
->
window
,
0
,
NULL
);
msg_Dbg
(
vout
,
"using X11 graphic context %08"
PRIx32
,
p_sys
->
gc
);
msg_Dbg
(
vd
,
"using X11 graphic context %08"
PRIx32
,
p_sys
->
gc
);
/* */
p_sys
->
pool
=
NULL
;
/* */
vout_display_info_t
info
=
vd
->
info
;
info
.
has_pictures_invalid
=
true
;
/* Setup vout_display_t once everything is fine */
vd
->
fmt
=
fmt_pic
;
vd
->
info
=
info
;
vd
->
get
=
Get
;
vd
->
prepare
=
NULL
;
vd
->
display
=
Display
;
vd
->
control
=
Control
;
vd
->
manage
=
Manage
;
/* */
unsigned
width
,
height
;
if
(
!
GetWindowSize
(
p_sys
->
embed
,
p_sys
->
conn
,
&
width
,
&
height
))
vout_display_SendEventDisplaySize
(
vd
,
width
,
height
);
vout_display_SendEventFullscreen
(
vd
,
false
);
vout
->
pf_init
=
Init
;
vout
->
pf_end
=
Deinit
;
vout
->
pf_display
=
Display
;
vout
->
pf_manage
=
Manage
;
vout
->
pf_control
=
Control
;
return
VLC_SUCCESS
;
return
VLC_SUCCESS
;
error:
error:
...
@@ -293,174 +309,219 @@ error:
...
@@ -293,174 +309,219 @@ error:
*/
*/
static
void
Close
(
vlc_object_t
*
obj
)
static
void
Close
(
vlc_object_t
*
obj
)
{
{
vout_
thread_t
*
vout
=
(
vout_thread
_t
*
)
obj
;
vout_
display_t
*
vd
=
(
vout_display
_t
*
)
obj
;
vout_
sys_t
*
p_sys
=
vout
->
p_
sys
;
vout_
display_sys_t
*
p_sys
=
vd
->
sys
;
vout_window_Delete
(
p_sys
->
embed
);
ResetPictures
(
vd
);
vout_display_DeleteWindow
(
vd
,
p_sys
->
embed
);
/* colormap and window are garbage-collected by X */
/* colormap and window are garbage-collected by X */
xcb_disconnect
(
p_sys
->
conn
);
xcb_disconnect
(
p_sys
->
conn
);
free
(
p_sys
);
free
(
p_sys
);
}
}
/**
/**
*
Allocate drawable window and picture buffers.
*
Return a direct buffer
*/
*/
static
int
Init
(
vout_thread_t
*
vout
)
static
picture_t
*
Get
(
vout_display_t
*
vd
)
{
{
vout_sys_t
*
p_sys
=
vout
->
p_sys
;
vout_display_sys_t
*
p_sys
=
vd
->
sys
;
unsigned
x
,
y
,
width
,
height
;
if
(
GetWindowSize
(
p_sys
->
embed
,
p_sys
->
conn
,
&
width
,
&
height
))
if
(
!
p_sys
->
pool
)
return
VLC_EGENERIC
;
vout_PlacePicture
(
vout
,
width
,
height
,
&
x
,
&
y
,
&
width
,
&
height
);
const
uint32_t
values
[]
=
{
x
,
y
,
width
,
height
,
};
xcb_configure_window
(
p_sys
->
conn
,
p_sys
->
window
,
XCB_CONFIG_WINDOW_X
|
XCB_CONFIG_WINDOW_Y
|
XCB_CONFIG_WINDOW_WIDTH
|
XCB_CONFIG_WINDOW_HEIGHT
,
values
);
/* FIXME: I don't get the subtlety between output and fmt_out here */
vout
->
fmt_out
.
i_visible_width
=
width
;
vout
->
fmt_out
.
i_visible_height
=
height
;
vout
->
fmt_out
.
i_sar_num
=
vout
->
fmt_out
.
i_sar_den
=
1
;
vout
->
output
.
i_width
=
vout
->
fmt_out
.
i_width
=
width
*
vout
->
fmt_in
.
i_width
/
vout
->
fmt_in
.
i_visible_width
;
vout
->
output
.
i_height
=
vout
->
fmt_out
.
i_height
=
height
*
vout
->
fmt_in
.
i_height
/
vout
->
fmt_in
.
i_visible_height
;
vout
->
fmt_out
.
i_x_offset
=
width
*
vout
->
fmt_in
.
i_x_offset
/
vout
->
fmt_in
.
i_visible_width
;
p_vout
->
fmt_out
.
i_y_offset
=
height
*
vout
->
fmt_in
.
i_y_offset
/
vout
->
fmt_in
.
i_visible_height
;
assert
(
height
>
0
);
vout
->
output
.
i_aspect
=
vout
->
fmt_out
.
i_aspect
=
width
*
VOUT_ASPECT_FACTOR
/
height
;
/* Allocate picture buffers */
I_OUTPUTPICTURES
=
0
;
for
(
size_t
index
=
0
;
I_OUTPUTPICTURES
<
2
;
index
++
)
{
{
picture_t
*
pic
=
vout
->
p_picture
+
index
;
vout_display_place_t
place
;
if
(
index
>
sizeof
(
vout
->
p_picture
)
/
sizeof
(
pic
))
vout_display_PlacePicture
(
&
place
,
&
vd
->
source
,
vd
->
cfg
,
false
);
break
;
if
(
pic
->
i_status
!=
FREE_PICTURE
)
continue
;
picture_Setup
(
pic
,
vout
->
output
.
i_chroma
,
/* */
vout
->
output
.
i_width
,
vout
->
output
.
i_height
,
const
uint32_t
values
[]
=
{
place
.
x
,
place
.
y
,
place
.
width
,
place
.
height
};
vout
->
output
.
i_aspect
);
xcb_configure_window
(
p_sys
->
conn
,
p_sys
->
window
,
if
(
PictureAlloc
(
vout
,
pic
,
pic
->
p
->
i_pitch
*
pic
->
p
->
i_lines
,
XCB_CONFIG_WINDOW_X
|
XCB_CONFIG_WINDOW_Y
|
p_sys
->
shm
?
p_sys
->
conn
:
NULL
))
XCB_CONFIG_WINDOW_WIDTH
|
XCB_CONFIG_WINDOW_HEIGHT
,
break
;
values
);
PP_OUTPUTPICTURE
[
I_OUTPUTPICTURES
++
]
=
pic
;
picture_t
*
pic
=
picture_NewFromFormat
(
&
vd
->
fmt
);
if
(
!
pic
)
return
NULL
;
assert
(
pic
->
i_planes
==
1
);
memset
(
p_sys
->
resource
,
0
,
sizeof
(
p_sys
->
resource
));
unsigned
count
;
picture_t
*
pic_array
[
MAX_PICTURES
];
for
(
count
=
0
;
count
<
MAX_PICTURES
;
count
++
)
{
picture_resource_t
*
res
=
&
p_sys
->
resource
[
count
];
res
->
p
->
i_lines
=
pic
->
p
->
i_lines
;
res
->
p
->
i_pitch
=
pic
->
p
->
i_pitch
;
if
(
PictureResourceAlloc
(
vd
,
res
,
res
->
p
->
i_pitch
*
res
->
p
->
i_lines
,
p_sys
->
conn
,
p_sys
->
shm
))
break
;
pic_array
[
count
]
=
picture_NewFromResource
(
&
vd
->
fmt
,
res
);
if
(
!
pic_array
[
count
])
{
PictureResourceFree
(
res
,
p_sys
->
conn
);
memset
(
res
,
0
,
sizeof
(
*
res
));
break
;
}
}
picture_Release
(
pic
);
if
(
count
==
0
)
return
NULL
;
p_sys
->
pool
=
picture_pool_New
(
count
,
pic_array
);
if
(
!
p_sys
->
pool
)
{
/* TODO release picture resources */
return
NULL
;
}
/* FIXME should also do it in case of error ? */
xcb_flush
(
p_sys
->
conn
);
}
}
xcb_flush
(
p_sys
->
conn
);
return
VLC_SUCCESS
;
}
/**
return
picture_pool_Get
(
p_sys
->
pool
);
* Free picture buffers.
*/
static
void
Deinit
(
vout_thread_t
*
vout
)
{
for
(
int
i
=
0
;
i
<
I_OUTPUTPICTURES
;
i
++
)
PictureFree
(
PP_OUTPUTPICTURE
[
i
],
vout
->
p_sys
->
conn
);
}
}
/**
/**
* Sends an image to the X server.
* Sends an image to the X server.
*/
*/
static
void
Display
(
vout_
thread_t
*
vout
,
picture_t
*
pic
)
static
void
Display
(
vout_
display_t
*
vd
,
picture_t
*
pic
)
{
{
vout_
sys_t
*
p_sys
=
vout
->
p_
sys
;
vout_
display_sys_t
*
p_sys
=
vd
->
sys
;
xcb_shm_seg_t
segment
=
(
uintptr_t
)
pic
->
p_sys
;
xcb_shm_seg_t
segment
=
pic
->
p_sys
->
segment
;
if
(
segment
!=
0
)
if
(
segment
!=
0
)
xcb_shm_put_image
(
p_sys
->
conn
,
p_sys
->
window
,
p_sys
->
gc
,
xcb_shm_put_image
(
p_sys
->
conn
,
p_sys
->
window
,
p_sys
->
gc
,
/* real width */
pic
->
p
->
i_pitch
/
pic
->
p
->
i_pixel_pitch
,
/* real width */
pic
->
p
->
i_pitch
/
pic
->
p
->
i_pixel_pitch
,
/* real height */
pic
->
p
->
i_lines
,
/* real height */
pic
->
p
->
i_lines
,
/* x */
v
out
->
fmt_ou
t
.
i_x_offset
,
/* x */
v
d
->
fm
t
.
i_x_offset
,
/* y */
v
out
->
fmt_ou
t
.
i_y_offset
,
/* y */
v
d
->
fm
t
.
i_y_offset
,
/* width */
v
out
->
fmt_ou
t
.
i_visible_width
,
/* width */
v
d
->
fm
t
.
i_visible_width
,
/* height */
v
out
->
fmt_ou
t
.
i_visible_height
,
/* height */
v
d
->
fm
t
.
i_visible_height
,
0
,
0
,
p_sys
->
depth
,
XCB_IMAGE_FORMAT_Z_PIXMAP
,
0
,
0
,
p_sys
->
depth
,
XCB_IMAGE_FORMAT_Z_PIXMAP
,
0
,
segment
,
0
);
0
,
segment
,
0
);
else
else
{
{
const
size_t
offset
=
v
out
->
fmt_ou
t
.
i_y_offset
*
pic
->
p
->
i_pitch
;
const
size_t
offset
=
v
d
->
fm
t
.
i_y_offset
*
pic
->
p
->
i_pitch
;
const
unsigned
lines
=
pic
->
p
->
i_lines
-
v
out
->
fmt_ou
t
.
i_y_offset
;
const
unsigned
lines
=
pic
->
p
->
i_lines
-
v
d
->
fm
t
.
i_y_offset
;
xcb_put_image
(
p_sys
->
conn
,
XCB_IMAGE_FORMAT_Z_PIXMAP
,
xcb_put_image
(
p_sys
->
conn
,
XCB_IMAGE_FORMAT_Z_PIXMAP
,
p_sys
->
window
,
p_sys
->
gc
,
p_sys
->
window
,
p_sys
->
gc
,
pic
->
p
->
i_pitch
/
pic
->
p
->
i_pixel_pitch
,
pic
->
p
->
i_pitch
/
pic
->
p
->
i_pixel_pitch
,
lines
,
-
v
out
->
fmt_ou
t
.
i_x_offset
,
0
,
0
,
p_sys
->
depth
,
lines
,
-
v
d
->
fm
t
.
i_x_offset
,
0
,
0
,
p_sys
->
depth
,
pic
->
p
->
i_pitch
*
lines
,
pic
->
p
->
p_pixels
+
offset
);
pic
->
p
->
i_pitch
*
lines
,
pic
->
p
->
p_pixels
+
offset
);
}
}
xcb_flush
(
p_sys
->
conn
);
xcb_flush
(
p_sys
->
conn
);
/* FIXME might be WAY better to wait in some case (be carefull with
* VOUT_DISPLAY_RESET_PICTURES if done) + does not work with
* vout_display wrapper. */
picture_Release
(
pic
);
}
}
/**
static
int
Control
(
vout_display_t
*
vd
,
int
query
,
va_list
ap
)
* Process incoming X events.
*/
static
int
Manage
(
vout_thread_t
*
vout
)
{
{
vout_sys_t
*
p_sys
=
vout
->
p_sys
;
vout_display_sys_t
*
p_sys
=
vd
->
sys
;
xcb_generic_event_t
*
ev
;
while
((
ev
=
xcb_poll_for_event
(
p_sys
->
conn
))
!=
NULL
)
ProcessEvent
(
vout
,
p_sys
->
conn
,
p_sys
->
window
,
ev
);
if
(
xcb_connection_has_error
(
p_sys
->
conn
)
)
switch
(
query
)
{
{
msg_Err
(
vout
,
"X server failure"
);
case
VOUT_DISPLAY_CHANGE_DISPLAY_SIZE
:
return
VLC_EGENERIC
;
{
}
const
vout_display_cfg_t
*
p_cfg
=
(
const
vout_display_cfg_t
*
)
va_arg
(
ap
,
const
vout_display_cfg_t
*
);
CommonManage
(
vout
);
/* FIXME: <-- move that to core */
if
(
vout_window_SetSize
(
p_sys
->
embed
,
return
VLC_SUCCESS
;
p_cfg
->
display
.
width
,
}
p_cfg
->
display
.
height
))
return
VLC_EGENERIC
;
void
vout_display_place_t
place
;
HandleParentStructure
(
vout_thread_t
*
vout
,
xcb_connection_t
*
conn
,
vout_display_PlacePicture
(
&
place
,
&
vd
->
source
,
p_cfg
,
false
);
xcb_window_t
xid
,
xcb_configure_notify_event_t
*
ev
)
{
unsigned
width
,
height
,
x
,
y
;
vout_PlacePicture
(
vout
,
ev
->
width
,
ev
->
height
,
&
x
,
&
y
,
&
width
,
&
height
);
if
(
place
.
width
!=
vd
->
fmt
.
i_visible_width
||
if
(
width
!=
vout
->
fmt_out
.
i_visible_width
place
.
height
!=
vd
->
fmt
.
i_visible_height
)
||
height
!=
vout
->
fmt_out
.
i_visible_height
)
{
vout_display_SendEventPicturesInvalid
(
vd
);
return
VLC_SUCCESS
;
}
/* Move the picture within the window */
const
uint32_t
values
[]
=
{
place
.
x
,
place
.
y
};
xcb_configure_window
(
p_sys
->
conn
,
p_sys
->
window
,
XCB_CONFIG_WINDOW_X
|
XCB_CONFIG_WINDOW_Y
,
values
);
return
VLC_SUCCESS
;
}
case
VOUT_DISPLAY_CHANGE_ON_TOP
:
{
{
vout
->
i_changes
|=
VOUT_SIZE_CHANGE
;
int
b_on_top
=
(
int
)
va_arg
(
ap
,
int
)
;
return
;
/* vout will be reinitialized */
return
vout_window_SetOnTop
(
p_sys
->
embed
,
b_on_top
);
}
}
/* Move the picture within the window */
case
VOUT_DISPLAY_CHANGE_ZOOM
:
const
uint32_t
values
[]
=
{
x
,
y
,
};
case
VOUT_DISPLAY_CHANGE_DISPLAY_FILLED
:
xcb_configure_window
(
conn
,
xid
,
case
VOUT_DISPLAY_CHANGE_SOURCE_ASPECT
:
XCB_CONFIG_WINDOW_X
|
XCB_CONFIG_WINDOW_Y
,
case
VOUT_DISPLAY_CHANGE_SOURCE_CROP
:
values
);
/* I am not sure it is always necessary, but it is way simpler ... */
}
vout_display_SendEventPicturesInvalid
(
vd
);
return
VLC_SUCCESS
;
static
int
Control
(
vout_thread_t
*
vout
,
int
query
,
va_list
ap
)
case
VOUT_DISPLAY_RESET_PICTURES
:
{
switch
(
query
)
{
{
case
VOUT_SET_SIZE
:
ResetPictures
(
vd
);
{
const
unsigned
width
=
va_arg
(
ap
,
unsigned
);
vout_display_place_t
place
;
const
unsigned
height
=
va_arg
(
ap
,
unsigned
);
vout_display_PlacePicture
(
&
place
,
&
vd
->
source
,
vd
->
cfg
,
false
);
return
vout_window_SetSize
(
vout
->
p_sys
->
embed
,
width
,
height
);
}
vd
->
fmt
.
i_width
=
vd
->
source
.
i_width
*
place
.
width
/
vd
->
source
.
i_visible_width
;
case
VOUT_SET_STAY_ON_TOP
:
vd
->
fmt
.
i_height
=
vd
->
source
.
i_height
*
place
.
height
/
vd
->
source
.
i_visible_height
;
{
const
bool
is_on_top
=
va_arg
(
ap
,
int
);
vd
->
fmt
.
i_visible_width
=
place
.
width
;
return
vout_window_SetOnTop
(
vout
->
p_sys
->
embed
,
is_on_top
);
vd
->
fmt
.
i_visible_height
=
place
.
height
;
vd
->
fmt
.
i_x_offset
=
vd
->
source
.
i_x_offset
*
place
.
width
/
vd
->
source
.
i_visible_width
;
vd
->
fmt
.
i_y_offset
=
vd
->
source
.
i_y_offset
*
place
.
height
/
vd
->
source
.
i_visible_height
;
return
VLC_SUCCESS
;
}
}
/* TODO */
#if 0
/* Hide the mouse. It will be send when
* vout_display_t::info.b_hide_mouse is false */
VOUT_DISPLAY_HIDE_MOUSE,
/* Ask the module to acknowledge/refuse the fullscreen state change after
* being requested (externaly or by VOUT_DISPLAY_EVENT_FULLSCREEN */
VOUT_DISPLAY_CHANGE_FULLSCREEN, /* const vout_display_cfg_t *p_cfg */
#endif
default:
default:
msg_Err
(
vd
,
"Unknown request in XCB vout display"
);
return
VLC_EGENERIC
;
return
VLC_EGENERIC
;
}
}
}
}
static
void
Manage
(
vout_display_t
*
vd
)
{
vout_display_sys_t
*
p_sys
=
vd
->
sys
;
ManageEvent
(
vd
,
p_sys
->
conn
,
p_sys
->
window
);
}
static
void
ResetPictures
(
vout_display_t
*
vd
)
{
vout_display_sys_t
*
p_sys
=
vd
->
sys
;
if
(
!
p_sys
->
pool
)
return
;
for
(
unsigned
i
=
0
;
i
<
MAX_PICTURES
;
i
++
)
{
picture_resource_t
*
res
=
&
p_sys
->
resource
[
i
];
if
(
!
res
->
p
->
p_pixels
)
break
;
PictureResourceFree
(
res
,
p_sys
->
conn
);
}
picture_pool_Delete
(
p_sys
->
pool
);
p_sys
->
pool
=
NULL
;
}
modules/video_output/xcb/xcb_vlc.h
View file @
e8534473
...
@@ -26,12 +26,10 @@
...
@@ -26,12 +26,10 @@
# define ORDER XCB_IMAGE_ORDER_LSB_FIRST
# define ORDER XCB_IMAGE_ORDER_LSB_FIRST
#endif
#endif
int
CheckError
(
vout_thread_t
*
,
const
char
*
str
,
xcb_void_cookie_t
);
#include <vlc_picture.h>
int
ProcessEvent
(
vout_thread_t
*
,
xcb_connection_t
*
,
xcb_window_t
,
#include <vlc_vout_display.h>
xcb_generic_event_t
*
);
void
HandleParentStructure
(
vout_thread_t
*
vout
,
xcb_connection_t
*
conn
,
xcb_window_t
xid
,
xcb_configure_notify_event_t
*
ev
);
int
ManageEvent
(
vout_display_t
*
vd
,
xcb_connection_t
*
conn
,
xcb_window_t
window
);
/* keys.c */
/* keys.c */
typedef
struct
key_handler_t
key_handler_t
;
typedef
struct
key_handler_t
key_handler_t
;
...
@@ -40,15 +38,25 @@ void DestroyKeyHandler (key_handler_t *);
...
@@ -40,15 +38,25 @@ void DestroyKeyHandler (key_handler_t *);
int
ProcessKeyEvent
(
key_handler_t
*
,
xcb_generic_event_t
*
);
int
ProcessKeyEvent
(
key_handler_t
*
,
xcb_generic_event_t
*
);
/* common.c */
/* common.c */
struct
vout_window_t
;
xcb_connection_t
*
Connect
(
vlc_object_t
*
obj
);
xcb_connection_t
*
Connect
(
vlc_object_t
*
obj
);
struct
vout_window_t
*
GetWindow
(
vout_
thread
_t
*
obj
,
struct
vout_window_t
*
GetWindow
(
vout_
display
_t
*
obj
,
xcb_connection_t
*
pconn
,
xcb_connection_t
*
pconn
,
const
xcb_screen_t
**
restrict
pscreen
,
const
xcb_screen_t
**
restrict
pscreen
,
bool
*
restrict
pshm
);
bool
*
restrict
pshm
);
int
GetWindowSize
(
struct
vout_window_t
*
wnd
,
xcb_connection_t
*
conn
,
int
GetWindowSize
(
struct
vout_window_t
*
wnd
,
xcb_connection_t
*
conn
,
unsigned
*
restrict
width
,
unsigned
*
restrict
height
);
unsigned
*
restrict
width
,
unsigned
*
restrict
height
);
int
PictureAlloc
(
vout_thread_t
*
,
picture_t
*
,
size_t
,
xcb_connection_t
*
);
void
PictureFree
(
picture_t
*
pic
,
xcb_connection_t
*
conn
);
int
CheckError
(
vout_display_t
*
,
xcb_connection_t
*
conn
,
void
CommonManage
(
vout_thread_t
*
);
const
char
*
str
,
xcb_void_cookie_t
);
/* FIXME
* maybe it would be better to split this header in 2 */
#include <xcb/shm.h>
struct
picture_sys_t
{
xcb_shm_seg_t
segment
;
};
int
PictureResourceAlloc
(
vout_display_t
*
vd
,
picture_resource_t
*
res
,
size_t
size
,
xcb_connection_t
*
conn
,
bool
attach
);
void
PictureResourceFree
(
picture_resource_t
*
res
,
xcb_connection_t
*
conn
);
modules/video_output/xcb/xvideo.c
View file @
e8534473
...
@@ -33,8 +33,8 @@
...
@@ -33,8 +33,8 @@
#include <vlc_common.h>
#include <vlc_common.h>
#include <vlc_plugin.h>
#include <vlc_plugin.h>
#include <vlc_vout.h>
#include <vlc_vout
_display
.h>
#include <vlc_
vout_window
.h>
#include <vlc_
picture_pool
.h>
#include "xcb_vlc.h"
#include "xcb_vlc.h"
...
@@ -58,7 +58,7 @@ vlc_module_begin ()
...
@@ -58,7 +58,7 @@ vlc_module_begin ()
set_description
(
N_
(
"(Experimental) XVideo output"
))
set_description
(
N_
(
"(Experimental) XVideo output"
))
set_category
(
CAT_VIDEO
)
set_category
(
CAT_VIDEO
)
set_subcategory
(
SUBCAT_VIDEO_VOUT
)
set_subcategory
(
SUBCAT_VIDEO_VOUT
)
set_capability
(
"v
ideo output
"
,
0
)
set_capability
(
"v
out display
"
,
0
)
set_callbacks
(
Open
,
Close
)
set_callbacks
(
Open
,
Close
)
add_string
(
"x11-display"
,
NULL
,
NULL
,
add_string
(
"x11-display"
,
NULL
,
NULL
,
...
@@ -67,7 +67,9 @@ vlc_module_begin ()
...
@@ -67,7 +67,9 @@ vlc_module_begin ()
add_shortcut
(
"xcb-xv"
)
add_shortcut
(
"xcb-xv"
)
vlc_module_end
()
vlc_module_end
()
struct
vout_sys_t
#define MAX_PICTURES (VOUT_MAX_PICTURES)
struct
vout_display_sys_t
{
{
xcb_connection_t
*
conn
;
xcb_connection_t
*
conn
;
xcb_xv_query_adaptors_reply_t
*
adaptors
;
xcb_xv_query_adaptors_reply_t
*
adaptors
;
...
@@ -81,31 +83,21 @@ struct vout_sys_t
...
@@ -81,31 +83,21 @@ struct vout_sys_t
uint16_t
height
;
/* display height */
uint16_t
height
;
/* display height */
uint32_t
data_size
;
/* picture byte size (for non-SHM) */
uint32_t
data_size
;
/* picture byte size (for non-SHM) */
bool
shm
;
/* whether to use MIT-SHM */
bool
shm
;
/* whether to use MIT-SHM */
};
static
int
Init
(
vout_thread_t
*
);
xcb_xv_query_image_attributes_reply_t
*
att
;
static
void
Deinit
(
vout_thread_t
*
);
picture_pool_t
*
pool
;
/* picture pool */
static
void
Display
(
vout_thread_t
*
,
picture_t
*
);
picture_resource_t
resource
[
MAX_PICTURES
];
static
int
Manage
(
vout_thread_t
*
);
};
static
int
Control
(
vout_thread_t
*
,
int
,
va_list
);
int
CheckError
(
vout_thread_t
*
vout
,
const
char
*
str
,
xcb_void_cookie_t
ck
)
{
xcb_generic_error_t
*
err
;
err
=
xcb_request_check
(
vout
->
p_sys
->
conn
,
ck
);
static
picture_t
*
Get
(
vout_display_t
*
);
if
(
err
)
static
void
Display
(
vout_display_t
*
,
picture_t
*
);
{
static
int
Control
(
vout_display_t
*
,
int
,
va_list
);
msg_Err
(
vout
,
"%s: X11 error %d"
,
str
,
err
->
error_code
);
static
void
Manage
(
vout_display_t
*
);
return
VLC_EGENERIC
;
}
return
VLC_SUCCESS
;
}
/**
/**
* Check that the X server supports the XVideo extension.
* Check that the X server supports the XVideo extension.
*/
*/
static
bool
CheckXVideo
(
vout_
thread_t
*
vout
,
xcb_connection_t
*
conn
)
static
bool
CheckXVideo
(
vout_
display_t
*
vd
,
xcb_connection_t
*
conn
)
{
{
xcb_xv_query_extension_reply_t
*
r
;
xcb_xv_query_extension_reply_t
*
r
;
xcb_xv_query_extension_cookie_t
ck
=
xcb_xv_query_extension
(
conn
);
xcb_xv_query_extension_cookie_t
ck
=
xcb_xv_query_extension
(
conn
);
...
@@ -116,129 +108,21 @@ static bool CheckXVideo (vout_thread_t *vout, xcb_connection_t *conn)
...
@@ -116,129 +108,21 @@ static bool CheckXVideo (vout_thread_t *vout, xcb_connection_t *conn)
{
/* We need XVideo 2.2 for PutImage */
{
/* We need XVideo 2.2 for PutImage */
if
((
r
->
major
>
2
)
||
(
r
->
major
==
2
&&
r
->
minor
>=
2
))
if
((
r
->
major
>
2
)
||
(
r
->
major
==
2
&&
r
->
minor
>=
2
))
{
{
msg_Dbg
(
v
out
,
"using XVideo extension v%"
PRIu8
".%"
PRIu8
,
msg_Dbg
(
v
d
,
"using XVideo extension v%"
PRIu8
".%"
PRIu8
,
r
->
major
,
r
->
minor
);
r
->
major
,
r
->
minor
);
ok
=
true
;
ok
=
true
;
}
}
else
else
msg_Dbg
(
v
out
,
"XVideo extension too old (v%"
PRIu8
".%"
PRIu8
,
msg_Dbg
(
v
d
,
"XVideo extension too old (v%"
PRIu8
".%"
PRIu8
,
r
->
major
,
r
->
minor
);
r
->
major
,
r
->
minor
);
free
(
r
);
free
(
r
);
}
}
else
else
msg_Dbg
(
v
out
,
"XVideo extension not available"
);
msg_Dbg
(
v
d
,
"XVideo extension not available"
);
return
ok
;
return
ok
;
}
}
/**
static
vlc_fourcc_t
ParseFormat
(
vout_display_t
*
vd
,
* Get a list of XVideo adaptors for a given window.
*/
static
xcb_xv_query_adaptors_reply_t
*
GetAdaptors
(
vout_window_t
*
wnd
,
xcb_connection_t
*
conn
)
{
xcb_xv_query_adaptors_cookie_t
ck
;
ck
=
xcb_xv_query_adaptors
(
conn
,
wnd
->
handle
.
xid
);
return
xcb_xv_query_adaptors_reply
(
conn
,
ck
,
NULL
);
}
#define p_vout vout
/**
* Probe the X server.
*/
static
int
Open
(
vlc_object_t
*
obj
)
{
vout_thread_t
*
vout
=
(
vout_thread_t
*
)
obj
;
vout_sys_t
*
p_sys
=
malloc
(
sizeof
(
*
p_sys
));
if
(
p_sys
==
NULL
)
return
VLC_ENOMEM
;
vout
->
p_sys
=
p_sys
;
/* Connect to X */
p_sys
->
conn
=
Connect
(
obj
);
if
(
p_sys
->
conn
==
NULL
)
{
free
(
p_sys
);
return
VLC_EGENERIC
;
}
if
(
!
CheckXVideo
(
vout
,
p_sys
->
conn
))
{
msg_Warn
(
vout
,
"Please enable XVideo 2.2 for faster video display"
);
xcb_disconnect
(
p_sys
->
conn
);
free
(
p_sys
);
return
VLC_EGENERIC
;
}
const
xcb_screen_t
*
screen
;
p_sys
->
embed
=
GetWindow
(
vout
,
p_sys
->
conn
,
&
screen
,
&
p_sys
->
shm
);
if
(
p_sys
->
embed
==
NULL
)
{
xcb_disconnect
(
p_sys
->
conn
);
free
(
p_sys
);
return
VLC_EGENERIC
;
}
/* Cache adaptors infos */
p_sys
->
adaptors
=
GetAdaptors
(
p_sys
->
embed
,
p_sys
->
conn
);
if
(
p_sys
->
adaptors
==
NULL
)
goto
error
;
/* Create window */
{
const
uint32_t
mask
=
/* XCB_CW_EVENT_MASK */
XCB_EVENT_MASK_BUTTON_PRESS
|
XCB_EVENT_MASK_BUTTON_RELEASE
|
XCB_EVENT_MASK_POINTER_MOTION
;
xcb_void_cookie_t
c
;
xcb_window_t
window
=
xcb_generate_id
(
p_sys
->
conn
);
c
=
xcb_create_window_checked
(
p_sys
->
conn
,
screen
->
root_depth
,
window
,
p_sys
->
embed
->
handle
.
xid
,
0
,
0
,
1
,
1
,
0
,
XCB_WINDOW_CLASS_INPUT_OUTPUT
,
screen
->
root_visual
,
XCB_CW_EVENT_MASK
,
&
mask
);
if
(
CheckError
(
vout
,
"cannot create X11 window"
,
c
))
goto
error
;
p_sys
->
window
=
window
;
msg_Dbg
(
vout
,
"using X11 window %08"
PRIx32
,
p_sys
->
window
);
xcb_map_window
(
p_sys
->
conn
,
window
);
}
p_sys
->
gc
=
xcb_generate_id
(
p_sys
->
conn
);
xcb_create_gc
(
p_sys
->
conn
,
p_sys
->
gc
,
p_sys
->
window
,
0
,
NULL
);
msg_Dbg
(
vout
,
"using X11 graphic context %08"
PRIx32
,
p_sys
->
gc
);
vout
->
pf_init
=
Init
;
vout
->
pf_end
=
Deinit
;
vout
->
pf_display
=
Display
;
vout
->
pf_manage
=
Manage
;
vout
->
pf_control
=
Control
;
return
VLC_SUCCESS
;
error:
Close
(
obj
);
return
VLC_EGENERIC
;
}
/**
* Disconnect from the X server.
*/
static
void
Close
(
vlc_object_t
*
obj
)
{
vout_thread_t
*
vout
=
(
vout_thread_t
*
)
obj
;
vout_sys_t
*
p_sys
=
vout
->
p_sys
;
free
(
p_sys
->
adaptors
);
vout_window_Delete
(
p_sys
->
embed
);
xcb_disconnect
(
p_sys
->
conn
);
free
(
p_sys
);
}
static
vlc_fourcc_t
ParseFormat
(
vout_thread_t
*
vout
,
const
xcb_xv_image_format_info_t
*
restrict
f
)
const
xcb_xv_image_format_info_t
*
restrict
f
)
{
{
if
(
f
->
byte_order
!=
ORDER
&&
f
->
bpp
!=
8
)
if
(
f
->
byte_order
!=
ORDER
&&
f
->
bpp
!=
8
)
...
@@ -273,9 +157,9 @@ static vlc_fourcc_t ParseFormat (vout_thread_t *vout,
...
@@ -273,9 +157,9 @@ static vlc_fourcc_t ParseFormat (vout_thread_t *vout,
}
}
break
;
break
;
}
}
msg_Err
(
v
out
,
"unknown XVideo RGB format %"
PRIx32
" (%.4s)"
,
msg_Err
(
v
d
,
"unknown XVideo RGB format %"
PRIx32
" (%.4s)"
,
f
->
id
,
f
->
guid
);
f
->
id
,
f
->
guid
);
msg_Dbg
(
v
out
,
" %"
PRIu8
" planes, %"
PRIu8
" bits/pixel, "
msg_Dbg
(
v
d
,
" %"
PRIu8
" planes, %"
PRIu8
" bits/pixel, "
"depth %"
PRIu8
,
f
->
num_planes
,
f
->
bpp
,
f
->
depth
);
"depth %"
PRIu8
,
f
->
num_planes
,
f
->
bpp
,
f
->
depth
);
break
;
break
;
...
@@ -321,16 +205,16 @@ static vlc_fourcc_t ParseFormat (vout_thread_t *vout,
...
@@ -321,16 +205,16 @@ static vlc_fourcc_t ParseFormat (vout_thread_t *vout,
break
;
break
;
}
}
bad:
bad:
msg_Err
(
v
out
,
"unknown XVideo YUV format %"
PRIx32
" (%.4s)"
,
f
->
id
,
msg_Err
(
v
d
,
"unknown XVideo YUV format %"
PRIx32
" (%.4s)"
,
f
->
id
,
f
->
guid
);
f
->
guid
);
msg_Dbg
(
v
out
,
" %"
PRIu8
" planes, %"
PRIu32
" bits/pixel, "
msg_Dbg
(
v
d
,
" %"
PRIu8
" planes, %"
PRIu32
" bits/pixel, "
"%"
PRIu32
"/%"
PRIu32
"/%"
PRIu32
" bits/sample"
,
f
->
num_planes
,
"%"
PRIu32
"/%"
PRIu32
"/%"
PRIu32
" bits/sample"
,
f
->
num_planes
,
f
->
bpp
,
f
->
y_sample_bits
,
f
->
u_sample_bits
,
f
->
v_sample_bits
);
f
->
bpp
,
f
->
y_sample_bits
,
f
->
u_sample_bits
,
f
->
v_sample_bits
);
msg_Dbg
(
v
out
,
" period: %"
PRIu32
"/%"
PRIu32
"/%"
PRIu32
"x"
msg_Dbg
(
v
d
,
" period: %"
PRIu32
"/%"
PRIu32
"/%"
PRIu32
"x"
"%"
PRIu32
"/%"
PRIu32
"/%"
PRIu32
,
"%"
PRIu32
"/%"
PRIu32
"/%"
PRIu32
,
f
->
vhorz_y_period
,
f
->
vhorz_u_period
,
f
->
vhorz_v_period
,
f
->
vhorz_y_period
,
f
->
vhorz_u_period
,
f
->
vhorz_v_period
,
f
->
vvert_y_period
,
f
->
vvert_u_period
,
f
->
vvert_v_period
);
f
->
vvert_y_period
,
f
->
vvert_u_period
,
f
->
vvert_v_period
);
msg_Warn
(
v
out
,
" order: %.32s"
,
f
->
vcomp_order
);
msg_Warn
(
v
d
,
" order: %.32s"
,
f
->
vcomp_order
);
break
;
break
;
}
}
return
0
;
return
0
;
...
@@ -338,11 +222,13 @@ static vlc_fourcc_t ParseFormat (vout_thread_t *vout,
...
@@ -338,11 +222,13 @@ static vlc_fourcc_t ParseFormat (vout_thread_t *vout,
static
const
xcb_xv_image_format_info_t
*
static
const
xcb_xv_image_format_info_t
*
FindFormat
(
vout_thread_t
*
vout
,
vlc_fourcc_t
chroma
,
xcb_xv_port_t
port
,
FindFormat
(
vout_display_t
*
vd
,
vlc_fourcc_t
chroma
,
const
video_format_t
*
fmt
,
xcb_xv_port_t
port
,
const
xcb_xv_list_image_formats_reply_t
*
list
,
const
xcb_xv_list_image_formats_reply_t
*
list
,
xcb_xv_query_image_attributes_reply_t
**
restrict
pa
)
xcb_xv_query_image_attributes_reply_t
**
restrict
pa
)
{
{
xcb_connection_t
*
conn
=
v
out
->
p_
sys
->
conn
;
xcb_connection_t
*
conn
=
v
d
->
sys
->
conn
;
const
xcb_xv_image_format_info_t
*
f
,
*
end
;
const
xcb_xv_image_format_info_t
*
f
,
*
end
;
#ifndef XCB_XV_OLD
#ifndef XCB_XV_OLD
...
@@ -353,21 +239,21 @@ FindFormat (vout_thread_t *vout, vlc_fourcc_t chroma, xcb_xv_port_t port,
...
@@ -353,21 +239,21 @@ FindFormat (vout_thread_t *vout, vlc_fourcc_t chroma, xcb_xv_port_t port,
end
=
f
+
xcb_xv_list_image_formats_format_length
(
list
);
end
=
f
+
xcb_xv_list_image_formats_format_length
(
list
);
for
(;
f
<
end
;
f
++
)
for
(;
f
<
end
;
f
++
)
{
{
if
(
chroma
!=
ParseFormat
(
v
out
,
f
))
if
(
chroma
!=
ParseFormat
(
v
d
,
f
))
continue
;
continue
;
xcb_xv_query_image_attributes_reply_t
*
i
;
xcb_xv_query_image_attributes_reply_t
*
i
;
i
=
xcb_xv_query_image_attributes_reply
(
conn
,
i
=
xcb_xv_query_image_attributes_reply
(
conn
,
xcb_xv_query_image_attributes
(
conn
,
port
,
f
->
id
,
xcb_xv_query_image_attributes
(
conn
,
port
,
f
->
id
,
vout
->
fmt_in
.
i_width
,
vout
->
fmt_in
.
i_height
),
NULL
);
fmt
->
i_width
,
fmt
->
i_height
),
NULL
);
if
(
i
==
NULL
)
if
(
i
==
NULL
)
continue
;
continue
;
if
(
i
->
width
!=
vout
->
fmt_in
.
i_width
if
(
i
->
width
!=
fmt
->
i_width
||
i
->
height
!=
vout
->
fmt_in
.
i_height
)
||
i
->
height
!=
fmt
->
i_height
)
{
{
msg_Warn
(
v
out
,
"incompatible size %ux%u -> %"
PRIu32
"x%"
PRIu32
,
msg_Warn
(
v
d
,
"incompatible size %ux%u -> %"
PRIu32
"x%"
PRIu32
,
vout
->
fmt_in
.
i_width
,
vout
->
fmt_in
.
i_height
,
fmt
->
i_width
,
fmt
->
i_height
,
i
->
width
,
i
->
height
);
i
->
width
,
i
->
height
);
free
(
i
);
free
(
i
);
continue
;
continue
;
...
@@ -378,14 +264,67 @@ FindFormat (vout_thread_t *vout, vlc_fourcc_t chroma, xcb_xv_port_t port,
...
@@ -378,14 +264,67 @@ FindFormat (vout_thread_t *vout, vlc_fourcc_t chroma, xcb_xv_port_t port,
return
NULL
;
return
NULL
;
}
}
/**
/**
*
Allocate drawable window and picture buffers
.
*
Get a list of XVideo adaptors for a given window
.
*/
*/
static
int
Init
(
vout_thread_t
*
vout
)
static
xcb_xv_query_adaptors_reply_t
*
GetAdaptors
(
vout_window_t
*
wnd
,
xcb_connection_t
*
conn
)
{
{
vout_sys_t
*
p_sys
=
vout
->
p_sys
;
xcb_xv_query_adaptors_cookie_t
ck
;
xcb_xv_query_image_attributes_reply_t
*
att
=
NULL
;
bool
swap_planes
=
false
;
/* whether X wants V before U */
ck
=
xcb_xv_query_adaptors
(
conn
,
wnd
->
handle
.
xid
);
return
xcb_xv_query_adaptors_reply
(
conn
,
ck
,
NULL
);
}
/**
* Probe the X server.
*/
static
int
Open
(
vlc_object_t
*
obj
)
{
vout_display_t
*
vd
=
(
vout_display_t
*
)
obj
;
vout_display_sys_t
*
p_sys
=
malloc
(
sizeof
(
*
p_sys
));
if
(
p_sys
==
NULL
)
return
VLC_ENOMEM
;
vd
->
sys
=
p_sys
;
/* Connect to X */
p_sys
->
conn
=
Connect
(
obj
);
if
(
p_sys
->
conn
==
NULL
)
{
free
(
p_sys
);
return
VLC_EGENERIC
;
}
if
(
!
CheckXVideo
(
vd
,
p_sys
->
conn
))
{
msg_Warn
(
vd
,
"Please enable XVideo 2.2 for faster video display"
);
xcb_disconnect
(
p_sys
->
conn
);
free
(
p_sys
);
return
VLC_EGENERIC
;
}
const
xcb_screen_t
*
screen
;
p_sys
->
embed
=
GetWindow
(
vd
,
p_sys
->
conn
,
&
screen
,
&
p_sys
->
shm
);
if
(
p_sys
->
embed
==
NULL
)
{
xcb_disconnect
(
p_sys
->
conn
);
free
(
p_sys
);
return
VLC_EGENERIC
;
}
/* Cache adaptors infos */
p_sys
->
adaptors
=
GetAdaptors
(
p_sys
->
embed
,
p_sys
->
conn
);
if
(
p_sys
->
adaptors
==
NULL
)
goto
error
;
/* */
video_format_t
fmt
=
vd
->
fmt
;
// TODO !
#if 1
p_sys
->
att
=
NULL
;
bool
found_adaptor
=
false
;
/* FIXME: check max image size */
/* FIXME: check max image size */
xcb_xv_adaptor_info_iterator_t
it
;
xcb_xv_adaptor_info_iterator_t
it
;
...
@@ -405,11 +344,11 @@ static int Init (vout_thread_t *vout)
...
@@ -405,11 +344,11 @@ static int Init (vout_thread_t *vout)
if
(
r
==
NULL
)
if
(
r
==
NULL
)
continue
;
continue
;
const
xcb_xv_image_format_info_t
*
fmt
;
const
xcb_xv_image_format_info_t
*
x
fmt
;
/* Video chroma in preference order */
/* Video chroma in preference order */
const
vlc_fourcc_t
chromas
[]
=
{
const
vlc_fourcc_t
chromas
[]
=
{
vout
->
fmt_in
.
i_chroma
,
fmt
.
i_chroma
,
VLC_CODEC_YUYV
,
VLC_CODEC_YUYV
,
VLC_CODEC_RGB24
,
VLC_CODEC_RGB24
,
VLC_CODEC_RGB15
,
VLC_CODEC_RGB15
,
...
@@ -417,10 +356,10 @@ static int Init (vout_thread_t *vout)
...
@@ -417,10 +356,10 @@ static int Init (vout_thread_t *vout)
for
(
size_t
i
=
0
;
i
<
sizeof
(
chromas
)
/
sizeof
(
chromas
[
0
]);
i
++
)
for
(
size_t
i
=
0
;
i
<
sizeof
(
chromas
)
/
sizeof
(
chromas
[
0
]);
i
++
)
{
{
vlc_fourcc_t
chroma
=
chromas
[
i
];
vlc_fourcc_t
chroma
=
chromas
[
i
];
fmt
=
FindFormat
(
vout
,
chroma
,
a
->
base_id
,
r
,
&
att
);
xfmt
=
FindFormat
(
vd
,
chroma
,
&
fmt
,
a
->
base_id
,
r
,
&
p_sys
->
att
);
if
(
fmt
!=
NULL
)
if
(
x
fmt
!=
NULL
)
{
{
vout
->
outpu
t
.
i_chroma
=
chroma
;
fm
t
.
i_chroma
=
chroma
;
goto
found_format
;
goto
found_format
;
}
}
}
}
...
@@ -430,203 +369,306 @@ static int Init (vout_thread_t *vout)
...
@@ -430,203 +369,306 @@ static int Init (vout_thread_t *vout)
found_format:
found_format:
/* TODO: grab port */
/* TODO: grab port */
p_sys
->
port
=
a
->
base_id
;
p_sys
->
port
=
a
->
base_id
;
msg_Dbg
(
v
out
,
"using port %"
PRIu32
,
p_sys
->
port
);
msg_Dbg
(
v
d
,
"using port %"
PRIu32
,
p_sys
->
port
);
p_sys
->
id
=
fmt
->
id
;
p_sys
->
id
=
x
fmt
->
id
;
msg_Dbg
(
v
out
,
"using image format 0x%"
PRIx32
,
p_sys
->
id
);
msg_Dbg
(
v
d
,
"using image format 0x%"
PRIx32
,
p_sys
->
id
);
if
(
fmt
->
type
==
XCB_XV_IMAGE_FORMAT_INFO_TYPE_RGB
)
if
(
x
fmt
->
type
==
XCB_XV_IMAGE_FORMAT_INFO_TYPE_RGB
)
{
{
vout
->
fmt_out
.
i_rmask
=
vout
->
output
.
i_rmask
=
fmt
->
red_mask
;
fmt
.
i_rmask
=
x
fmt
->
red_mask
;
vout
->
fmt_out
.
i_gmask
=
vout
->
output
.
i_gmask
=
fmt
->
green_mask
;
fmt
.
i_gmask
=
x
fmt
->
green_mask
;
vout
->
fmt_out
.
i_bmask
=
vout
->
output
.
i_bmask
=
fmt
->
blue_mask
;
fmt
.
i_bmask
=
x
fmt
->
blue_mask
;
}
}
else
else
if
(
fmt
->
num_planes
==
3
)
if
(
xfmt
->
num_planes
==
3
swap_planes
=
!
strcmp
((
const
char
*
)
fmt
->
vcomp_order
,
"YVU"
);
&&
!
strcmp
((
const
char
*
)
xfmt
->
vcomp_order
,
"YVU"
))
fmt
.
i_chroma
=
VLC_CODEC_YV12
;
free
(
r
);
free
(
r
);
goto
found_adaptor
;
found_adaptor
=
true
;
break
;
}
}
msg_Err
(
vout
,
"no available XVideo adaptor"
);
if
(
!
found_adaptor
)
return
VLC_EGENERIC
;
/* no usable adaptor */
{
msg_Err
(
vd
,
"no available XVideo adaptor"
);
/* Allocate picture buffers */
goto
error
;
const
uint32_t
*
offsets
;
}
found_adaptor:
#endif
offsets
=
xcb_xv_query_image_attributes_offsets
(
att
);
p_sys
->
data_size
=
att
->
data_size
;
I_OUTPUTPICTURES
=
0
;
/* Create window */
for
(
size_t
index
=
0
;
I_OUTPUTPICTURES
<
2
;
index
++
)
{
{
picture_t
*
pic
=
vout
->
p_picture
+
index
;
const
uint32_t
mask
=
/* XCB_CW_EVENT_MASK */
XCB_EVENT_MASK_BUTTON_PRESS
|
XCB_EVENT_MASK_BUTTON_RELEASE
|
XCB_EVENT_MASK_POINTER_MOTION
;
xcb_void_cookie_t
c
;
xcb_window_t
window
=
xcb_generate_id
(
p_sys
->
conn
);
if
(
index
>
sizeof
(
vout
->
p_picture
)
/
sizeof
(
pic
))
c
=
xcb_create_window_checked
(
p_sys
->
conn
,
screen
->
root_depth
,
window
,
break
;
p_sys
->
embed
->
handle
.
xid
,
0
,
0
,
1
,
1
,
0
,
if
(
pic
->
i_status
!=
FREE_PICTURE
)
XCB_WINDOW_CLASS_INPUT_OUTPUT
,
continue
;
screen
->
root_visual
,
XCB_CW_EVENT_MASK
,
&
mask
);
if
(
CheckError
(
vd
,
p_sys
->
conn
,
"cannot create X11 window"
,
c
))
goto
error
;
p_sys
->
window
=
window
;
msg_Dbg
(
vd
,
"using X11 window %08"
PRIx32
,
p_sys
->
window
);
xcb_map_window
(
p_sys
->
conn
,
window
);
picture_Setup
(
pic
,
vout
->
output
.
i_chroma
,
vout_display_place_t
place
;
att
->
width
,
att
->
height
,
vout
->
fmt_in
.
i_aspect
);
vout_display_PlacePicture
(
&
place
,
&
vd
->
source
,
vd
->
cfg
,
false
);
if
(
PictureAlloc
(
vout
,
pic
,
att
->
data_size
,
p_sys
->
width
=
place
.
width
;
p_sys
->
shm
?
p_sys
->
conn
:
NULL
))
p_sys
->
height
=
place
.
height
;
break
;
/*
Allocate further planes as specified by XVideo
*/
/* */
/* We assume that offsets[0] is zero */
const
uint32_t
values
[]
=
{
place
.
x
,
place
.
y
,
place
.
width
,
place
.
height
};
for
(
int
i
=
1
;
i
<
pic
->
i_planes
;
i
++
)
xcb_configure_window
(
p_sys
->
conn
,
p_sys
->
window
,
pic
->
p
[
i
].
p_pixels
=
XCB_CONFIG_WINDOW_X
|
XCB_CONFIG_WINDOW_Y
|
pic
->
p
->
p_pixels
+
offsets
[
swap_planes
?
(
3
-
i
)
:
i
];
XCB_CONFIG_WINDOW_WIDTH
|
XCB_CONFIG_WINDOW_HEIGHT
,
PP_OUTPUTPICTURE
[
I_OUTPUTPICTURES
++
]
=
pic
;
values
)
;
}
}
free
(
att
);
unsigned
x
,
y
,
width
,
height
;
/* Create graphic context */
p_sys
->
gc
=
xcb_generate_id
(
p_sys
->
conn
);
xcb_create_gc
(
p_sys
->
conn
,
p_sys
->
gc
,
p_sys
->
window
,
0
,
NULL
);
msg_Dbg
(
vd
,
"using X11 graphic context %08"
PRIx32
,
p_sys
->
gc
);
if
(
GetWindowSize
(
p_sys
->
embed
,
p_sys
->
conn
,
&
width
,
&
height
))
/* */
return
VLC_EGENERIC
;
p_sys
->
pool
=
NULL
;
vout_PlacePicture
(
vout
,
width
,
height
,
&
x
,
&
y
,
&
width
,
&
height
);
const
uint32_t
values
[]
=
{
x
,
y
,
width
,
height
,
};
/* */
xcb_configure_window
(
p_sys
->
conn
,
p_sys
->
window
,
vout_display_info_t
info
=
vd
->
info
;
XCB_CONFIG_WINDOW_X
|
XCB_CONFIG_WINDOW_Y
|
info
.
has_pictures_invalid
=
false
;
XCB_CONFIG_WINDOW_WIDTH
|
XCB_CONFIG_WINDOW_HEIGHT
,
values
);
xcb_flush
(
p_sys
->
conn
);
p_sys
->
height
=
height
;
p_sys
->
width
=
width
;
vout
->
fmt_out
.
i_chroma
=
vout
->
output
.
i_chroma
;
/* Setup vout_display_t once everything is fine */
vout
->
fmt_out
.
i_visible_width
=
vout
->
fmt_in
.
i_visible_width
;
vd
->
fmt
=
fmt
;
vout
->
fmt_out
.
i_visible_height
=
vout
->
fmt_in
.
i_visible_height
;
vd
->
info
=
info
;
vout
->
fmt_out
.
i_sar_num
=
vout
->
fmt_out
.
i_sar_den
=
1
;
vout
->
output
.
i_width
=
vout
->
fmt_out
.
i_width
=
vout
->
fmt_in
.
i_width
;
vd
->
get
=
Get
;
vout
->
output
.
i_height
=
vout
->
fmt_out
.
i_height
=
vout
->
fmt_in
.
i_height
;
vd
->
prepare
=
NULL
;
vout
->
fmt_out
.
i_x_offset
=
vout
->
fmt_in
.
i_x_offset
;
vd
->
display
=
Display
;
vout
->
fmt_out
.
i_y_offset
=
vout
->
fmt_in
.
i_y_offset
;
vd
->
control
=
Control
;
vd
->
manage
=
Manage
;
assert
(
height
>
0
);
/* */
vout
->
output
.
i_aspect
=
vout
->
fmt_out
.
i_aspect
=
unsigned
width
,
height
;
width
*
VOUT_ASPECT_FACTOR
/
height
;
if
(
!
GetWindowSize
(
p_sys
->
embed
,
p_sys
->
conn
,
&
width
,
&
height
))
vout_display_SendEventDisplaySize
(
vd
,
width
,
height
);
vout_display_SendEventFullscreen
(
vd
,
false
);
return
VLC_SUCCESS
;
return
VLC_SUCCESS
;
error:
Close
(
obj
);
return
VLC_EGENERIC
;
}
/**
* Disconnect from the X server.
*/
static
void
Close
(
vlc_object_t
*
obj
)
{
vout_display_t
*
vd
=
(
vout_display_t
*
)
obj
;
vout_display_sys_t
*
p_sys
=
vd
->
sys
;
if
(
p_sys
->
pool
)
{
for
(
unsigned
i
=
0
;
i
<
MAX_PICTURES
;
i
++
)
{
picture_resource_t
*
res
=
&
p_sys
->
resource
[
i
];
if
(
!
res
->
p
->
p_pixels
)
break
;
PictureResourceFree
(
res
,
p_sys
->
conn
);
}
picture_pool_Delete
(
p_sys
->
pool
);
}
free
(
p_sys
->
att
);
free
(
p_sys
->
adaptors
);
vout_display_DeleteWindow
(
vd
,
p_sys
->
embed
);
xcb_disconnect
(
p_sys
->
conn
);
free
(
p_sys
);
}
}
/**
/**
*
Free picture buffers.
*
Return a direct buffer
*/
*/
static
void
Deinit
(
vout_thread_t
*
vout
)
static
picture_t
*
Get
(
vout_display_t
*
vd
)
{
{
vout_sys_t
*
p_sys
=
vout
->
p_sys
;
vout_display_sys_t
*
p_sys
=
vd
->
sys
;
if
(
!
p_sys
->
pool
)
{
picture_t
*
pic
=
picture_New
(
vd
->
fmt
.
i_chroma
,
p_sys
->
att
->
width
,
p_sys
->
att
->
height
,
0
);
if
(
!
pic
)
return
NULL
;
memset
(
p_sys
->
resource
,
0
,
sizeof
(
p_sys
->
resource
));
const
uint32_t
*
offsets
=
xcb_xv_query_image_attributes_offsets
(
p_sys
->
att
);
p_sys
->
data_size
=
p_sys
->
att
->
data_size
;
unsigned
count
;
picture_t
*
pic_array
[
MAX_PICTURES
];
for
(
count
=
0
;
count
<
MAX_PICTURES
;
count
++
)
{
picture_resource_t
*
res
=
&
p_sys
->
resource
[
count
];
for
(
int
i
=
0
;
i
<
pic
->
i_planes
;
i
++
)
{
res
->
p
[
i
].
i_lines
=
pic
->
p
[
i
].
i_lines
;
/* FIXME seems wrong*/
res
->
p
[
i
].
i_pitch
=
pic
->
p
[
i
].
i_pitch
;
}
if
(
PictureResourceAlloc
(
vd
,
res
,
p_sys
->
att
->
data_size
,
p_sys
->
conn
,
p_sys
->
shm
))
break
;
/* Allocate further planes as specified by XVideo */
/* We assume that offsets[0] is zero */
for
(
int
i
=
1
;
i
<
pic
->
i_planes
;
i
++
)
res
->
p
[
i
].
p_pixels
=
res
->
p
[
0
].
p_pixels
+
offsets
[
i
];
pic_array
[
count
]
=
picture_NewFromResource
(
&
vd
->
fmt
,
res
);
if
(
!
pic_array
[
count
])
{
PictureResourceFree
(
res
,
p_sys
->
conn
);
memset
(
res
,
0
,
sizeof
(
*
res
));
break
;
}
}
picture_Release
(
pic
);
if
(
count
==
0
)
return
NULL
;
p_sys
->
pool
=
picture_pool_New
(
count
,
pic_array
);
if
(
!
p_sys
->
pool
)
{
/* TODO release picture resources */
return
NULL
;
}
/* FIXME should also do it in case of error ? */
xcb_flush
(
p_sys
->
conn
);
}
for
(
int
i
=
0
;
i
<
I_OUTPUTPICTURES
;
i
++
)
return
picture_pool_Get
(
p_sys
->
pool
);
PictureFree
(
PP_OUTPUTPICTURE
[
i
],
p_sys
->
conn
);
}
}
/**
/**
* Sends an image to the X server.
* Sends an image to the X server.
*/
*/
static
void
Display
(
vout_
thread_t
*
vout
,
picture_t
*
pic
)
static
void
Display
(
vout_
display_t
*
vd
,
picture_t
*
pic
)
{
{
vout_
sys_t
*
p_sys
=
vout
->
p_
sys
;
vout_
display_sys_t
*
p_sys
=
vd
->
sys
;
xcb_shm_seg_t
segment
=
(
uintptr_t
)
pic
->
p_sys
;
xcb_shm_seg_t
segment
=
pic
->
p_sys
->
segment
;
if
(
segment
)
if
(
segment
)
xcb_xv_shm_put_image
(
p_sys
->
conn
,
p_sys
->
port
,
p_sys
->
window
,
xcb_xv_shm_put_image
(
p_sys
->
conn
,
p_sys
->
port
,
p_sys
->
window
,
p_sys
->
gc
,
segment
,
p_sys
->
id
,
0
,
p_sys
->
gc
,
segment
,
p_sys
->
id
,
0
,
/* Src: */
vout
->
fmt_out
.
i_x_offset
,
/* Src: */
vd
->
source
.
i_x_offset
,
vout
->
fmt_out
.
i_y_offset
,
vd
->
source
.
i_y_offset
,
vout
->
fmt_out
.
i_visible_width
,
vd
->
source
.
i_visible_width
,
vout
->
fmt_out
.
i_visible_height
,
vd
->
source
.
i_visible_height
,
/* Dst: */
0
,
0
,
p_sys
->
width
,
p_sys
->
height
,
/* Dst: */
0
,
0
,
p_sys
->
width
,
p_sys
->
height
,
/* Memory: */
/* Memory: */
pic
->
p
->
i_pitch
/
pic
->
p
->
i_pixel_pitch
,
pic
->
p
->
i_pitch
/
pic
->
p
->
i_pixel_pitch
,
pic
->
p
->
i_lines
,
false
);
pic
->
p
->
i_lines
,
false
);
else
else
xcb_xv_put_image
(
p_sys
->
conn
,
p_sys
->
port
,
p_sys
->
window
,
xcb_xv_put_image
(
p_sys
->
conn
,
p_sys
->
port
,
p_sys
->
window
,
p_sys
->
gc
,
p_sys
->
id
,
p_sys
->
gc
,
p_sys
->
id
,
vout
->
fmt_out
.
i_x_offset
,
vout
->
fmt_out
.
i_y_offset
,
vd
->
source
.
i_x_offset
,
vout
->
fmt_out
.
i_visible_width
,
vd
->
source
.
i_y_offset
,
vout
->
fmt_out
.
i_visible_height
,
vd
->
source
.
i_visible_width
,
vd
->
source
.
i_visible_height
,
0
,
0
,
p_sys
->
width
,
p_sys
->
height
,
0
,
0
,
p_sys
->
width
,
p_sys
->
height
,
v
out
->
fmt_out
.
i_width
,
vout
->
fmt_out
.
i_height
,
v
d
->
source
.
i_width
,
vd
->
source
.
i_height
,
p_sys
->
data_size
,
pic
->
p
->
p_pixels
);
p_sys
->
data_size
,
pic
->
p
->
p_pixels
);
xcb_flush
(
p_sys
->
conn
);
xcb_flush
(
p_sys
->
conn
);
picture_Release
(
pic
);
}
}
/**
static
int
Control
(
vout_display_t
*
vd
,
int
query
,
va_list
ap
)
* Process incoming X events.
*/
static
int
Manage
(
vout_thread_t
*
vout
)
{
{
vout_sys_t
*
p_sys
=
vout
->
p_sys
;
vout_display_sys_t
*
p_sys
=
vd
->
sys
;
xcb_generic_event_t
*
ev
;
while
((
ev
=
xcb_poll_for_event
(
p_sys
->
conn
))
!=
NULL
)
switch
(
query
)
ProcessEvent
(
vout
,
p_sys
->
conn
,
p_sys
->
window
,
ev
);
if
(
xcb_connection_has_error
(
p_sys
->
conn
))
{
{
msg_Err
(
vout
,
"X server failure"
);
case
VOUT_DISPLAY_CHANGE_DISPLAY_SIZE
:
return
VLC_EGENERIC
;
case
VOUT_DISPLAY_CHANGE_DISPLAY_FILLED
:
}
case
VOUT_DISPLAY_CHANGE_ZOOM
:
case
VOUT_DISPLAY_CHANGE_SOURCE_ASPECT
:
case
VOUT_DISPLAY_CHANGE_SOURCE_CROP
:
{
const
vout_display_cfg_t
*
cfg
;
const
video_format_t
*
source
;
CommonManage
(
vout
);
if
(
query
==
VOUT_DISPLAY_CHANGE_SOURCE_ASPECT
if
(
vout
->
i_changes
&
VOUT_SIZE_CHANGE
)
||
query
==
VOUT_DISPLAY_CHANGE_SOURCE_CROP
)
{
/* TODO: factor this code with XV and X11 Init() */
{
unsigned
x
,
y
,
width
,
height
;
source
=
(
const
video_format_t
*
)
va_arg
(
ap
,
const
video_format_t
*
);
cfg
=
vd
->
cfg
;
}
else
{
source
=
&
vd
->
source
;
cfg
=
(
const
vout_display_cfg_t
*
)
va_arg
(
ap
,
const
vout_display_cfg_t
*
);
}
if
(
GetWindowSize
(
p_sys
->
embed
,
p_sys
->
conn
,
&
width
,
&
height
))
/* */
if
(
query
==
VOUT_DISPLAY_CHANGE_DISPLAY_SIZE
&&
(
cfg
->
display
.
width
!=
vd
->
cfg
->
display
.
width
||
cfg
->
display
.
height
!=
vd
->
cfg
->
display
.
height
)
&&
vout_window_SetSize
(
p_sys
->
embed
,
cfg
->
display
.
width
,
cfg
->
display
.
height
))
return
VLC_EGENERIC
;
return
VLC_EGENERIC
;
vout_PlacePicture
(
vout
,
width
,
height
,
&
x
,
&
y
,
&
width
,
&
height
);
const
uint32_t
values
[]
=
{
x
,
y
,
width
,
height
,
};
xcb_configure_window
(
p_sys
->
conn
,
p_sys
->
window
,
XCB_CONFIG_WINDOW_X
|
XCB_CONFIG_WINDOW_Y
|
XCB_CONFIG_WINDOW_WIDTH
|
XCB_CONFIG_WINDOW_HEIGHT
,
values
);
vout
->
p_sys
->
width
=
width
;
// XXX: <-- this is useless, as the zoom is
vout
->
p_sys
->
height
=
height
;
// handled with VOUT_SET_SIZE anyway.
vout
->
i_changes
&=
~
VOUT_SIZE_CHANGE
;
}
return
VLC_SUCCESS
;
}
void
HandleParentStructure
(
vout_thread_t
*
vout
,
xcb_connection_t
*
conn
,
xcb_window_t
xid
,
xcb_configure_notify_event_t
*
ev
)
{
unsigned
width
,
height
,
x
,
y
;
vout_PlacePicture
(
vout
,
ev
->
width
,
ev
->
height
,
&
x
,
&
y
,
&
width
,
&
height
);
/* Move the picture within the window */
const
uint32_t
values
[]
=
{
x
,
y
,
width
,
height
,
};
xcb_configure_window
(
conn
,
xid
,
XCB_CONFIG_WINDOW_X
|
XCB_CONFIG_WINDOW_Y
|
XCB_CONFIG_WINDOW_WIDTH
|
XCB_CONFIG_WINDOW_HEIGHT
,
values
);
vout
->
p_sys
->
width
=
width
;
vout
->
p_sys
->
height
=
height
;
}
static
int
Control
(
vout_thread_t
*
vout
,
int
query
,
va_list
ap
)
vout_display_place_t
place
;
{
vout_display_PlacePicture
(
&
place
,
source
,
cfg
,
false
);
/* FIXME it can be shared between x11 and xvideo */
p_sys
->
width
=
place
.
width
;
switch
(
query
)
p_sys
->
height
=
place
.
height
;
{
case
VOUT_SET_SIZE
:
/* Move the picture within the window */
{
const
uint32_t
values
[]
=
{
place
.
x
,
place
.
y
,
const
unsigned
width
=
va_arg
(
ap
,
unsigned
);
place
.
width
,
place
.
height
,
};
const
unsigned
height
=
va_arg
(
ap
,
unsigned
);
xcb_configure_window
(
p_sys
->
conn
,
p_sys
->
window
,
return
vout_window_SetSize
(
vout
->
p_sys
->
embed
,
width
,
height
);
XCB_CONFIG_WINDOW_X
|
XCB_CONFIG_WINDOW_Y
|
XCB_CONFIG_WINDOW_WIDTH
|
XCB_CONFIG_WINDOW_HEIGHT
,
values
);
xcb_flush
(
p_sys
->
conn
);
return
VLC_SUCCESS
;
}
}
case
VOUT_
SET_STAY
_ON_TOP
:
case
VOUT_
DISPLAY_CHANGE
_ON_TOP
:
{
{
const
bool
is_on_top
=
va_arg
(
ap
,
int
);
int
on_top
=
(
int
)
va_arg
(
ap
,
int
);
return
vout_window_SetOnTop
(
vout
->
p_sys
->
embed
,
is_
on_top
);
return
vout_window_SetOnTop
(
p_sys
->
embed
,
on_top
);
}
}
/* TODO */
#if 0
/* Hide the mouse. It will be send when
* vout_display_t::info.b_hide_mouse is false */
VOUT_DISPLAY_HIDE_MOUSE,
/* Ask the module to acknowledge/refuse the fullscreen state change after
* being requested (externaly or by VOUT_DISPLAY_EVENT_FULLSCREEN */
VOUT_DISPLAY_CHANGE_FULLSCREEN, /* const vout_display_cfg_t *p_cfg */
#endif
case
VOUT_DISPLAY_RESET_PICTURES
:
assert
(
0
);
default:
default:
msg_Err
(
vd
,
"Unknown request in XCB vout display"
);
return
VLC_EGENERIC
;
return
VLC_EGENERIC
;
}
}
}
static
void
Manage
(
vout_display_t
*
vd
)
{
vout_display_sys_t
*
p_sys
=
vd
->
sys
;
ManageEvent
(
vd
,
p_sys
->
conn
,
p_sys
->
window
);
}
}
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