2 #include <X11/Xlibint.h>
3 #include <X11/extensions/XvMClib.h>
4 #include <pipe/p_screen.h>
5 #include <pipe/p_video_context.h>
6 #include <pipe/p_video_state.h>
7 #include <pipe/p_state.h>
9 #include <util/u_memory.h>
10 #include <util/u_debug.h>
11 #include "xvmc_private.h"
13 static Status
Validate(Display
*dpy
, XvPortID port
, int surface_type_id
,
14 unsigned int width
, unsigned int height
, int flags
,
15 bool *found_port
, int *screen
, int *chroma_format
,
16 int *mc_type
, int *surface_flags
)
18 bool found_surface
= false;
19 XvAdaptorInfo
*adaptor_info
;
20 unsigned int num_adaptors
;
22 unsigned int max_width
, max_height
;
28 assert(chroma_format
);
30 assert(surface_flags
);
34 for (unsigned int i
= 0; i
< XScreenCount(dpy
); ++i
) {
35 ret
= XvQueryAdaptors(dpy
, XRootWindow(dpy
, i
), &num_adaptors
, &adaptor_info
);
39 for (unsigned int j
= 0; j
< num_adaptors
&& !*found_port
; ++j
) {
40 for (unsigned int k
= 0; k
< adaptor_info
[j
].num_ports
&& !*found_port
; ++k
) {
41 XvMCSurfaceInfo
*surface_info
;
43 if (adaptor_info
[j
].base_id
+ k
!= port
)
48 surface_info
= XvMCListSurfaceTypes(dpy
, adaptor_info
[j
].base_id
, &num_types
);
50 XvFreeAdaptorInfo(adaptor_info
);
54 for (unsigned int l
= 0; l
< num_types
&& !found_surface
; ++l
) {
55 if (surface_info
[l
].surface_type_id
!= surface_type_id
)
59 max_width
= surface_info
[l
].max_width
;
60 max_height
= surface_info
[l
].max_height
;
61 *chroma_format
= surface_info
[l
].chroma_format
;
62 *mc_type
= surface_info
[l
].mc_type
;
63 *surface_flags
= surface_info
[l
].flags
;
71 XvFreeAdaptorInfo(adaptor_info
);
78 if (width
> max_width
|| height
> max_height
)
80 if (flags
!= XVMC_DIRECT
&& flags
!= 0)
86 static enum pipe_video_profile
ProfileToPipe(int xvmc_profile
)
88 if (xvmc_profile
& XVMC_MPEG_1
)
90 if (xvmc_profile
& XVMC_MPEG_2
)
91 return PIPE_VIDEO_PROFILE_MPEG2_MAIN
;
92 if (xvmc_profile
& XVMC_H263
)
94 if (xvmc_profile
& XVMC_MPEG_4
)
102 static enum pipe_video_chroma_format
FormatToPipe(int xvmc_format
)
104 switch (xvmc_format
) {
105 case XVMC_CHROMA_FORMAT_420
:
106 return PIPE_VIDEO_CHROMA_FORMAT_420
;
107 case XVMC_CHROMA_FORMAT_422
:
108 return PIPE_VIDEO_CHROMA_FORMAT_422
;
109 case XVMC_CHROMA_FORMAT_444
:
110 return PIPE_VIDEO_CHROMA_FORMAT_444
;
118 Status
XvMCCreateContext(Display
*dpy
, XvPortID port
, int surface_type_id
,
119 int width
, int height
, int flags
, XvMCContext
*context
)
127 struct pipe_screen
*screen
;
128 struct pipe_video_context
*vpipe
;
129 XvMCContextPrivate
*context_priv
;
134 return XvMCBadContext
;
136 ret
= Validate(dpy
, port
, surface_type_id
, width
, height
, flags
,
137 &found_port
, &scrn
, &chroma_format
, &mc_type
, &surface_flags
);
139 /* Success and XvBadPort have the same value */
140 if (ret
!= Success
|| !found_port
)
143 /* XXX: Current limits */
144 if (chroma_format
!= XVMC_CHROMA_FORMAT_420
) {
145 debug_printf("[XvMCg3dvl] Cannot decode requested surface type. Unsupported chroma format.\n");
146 return BadImplementation
;
148 if (mc_type
!= (XVMC_MOCOMP
| XVMC_MPEG_2
)) {
149 debug_printf("[XvMCg3dvl] Cannot decode requested surface type. Non-MPEG2/Mocomp acceleration unsupported.\n");
150 return BadImplementation
;
152 if (!(surface_flags
& XVMC_INTRA_UNSIGNED
)) {
153 debug_printf("[XvMCg3dvl] Cannot decode requested surface type. Signed intra unsupported.\n");
154 return BadImplementation
;
157 context_priv
= CALLOC(1, sizeof(XvMCContextPrivate
));
161 /* TODO: Reuse screen if process creates another context */
162 screen
= vl_screen_create(dpy
, scrn
);
169 vpipe
= vl_video_create(screen
, ProfileToPipe(mc_type
),
170 FormatToPipe(chroma_format
), width
, height
);
173 screen
->destroy(screen
);
178 context_priv
->vpipe
= vpipe
;
180 context
->context_id
= XAllocID(dpy
);
181 context
->surface_type_id
= surface_type_id
;
182 context
->width
= width
;
183 context
->height
= height
;
184 context
->flags
= flags
;
185 context
->port
= port
;
186 context
->privData
= context_priv
;
193 Status
XvMCDestroyContext(Display
*dpy
, XvMCContext
*context
)
195 struct pipe_screen
*screen
;
196 struct pipe_video_context
*vpipe
;
197 XvMCContextPrivate
*context_priv
;
201 if (!context
|| !context
->privData
)
202 return XvMCBadContext
;
204 context_priv
= context
->privData
;
205 vpipe
= context_priv
->vpipe
;
206 pipe_surface_reference(&context_priv
->backbuffer
, NULL
);
207 screen
= vpipe
->screen
;
208 vpipe
->destroy(vpipe
);
209 screen
->destroy(screen
);
211 context
->privData
= NULL
;