1 /**************************************************************************
3 * Copyright 2009 Younes Manton.
6 * Permission is hereby granted, free of charge, to any person obtaining a
7 * copy of this software and associated documentation files (the
8 * "Software"), to deal in the Software without restriction, including
9 * without limitation the rights to use, copy, modify, merge, publish,
10 * distribute, sub license, and/or sell copies of the Software, and to
11 * permit persons to whom the Software is furnished to do so, subject to
12 * the following conditions:
14 * The above copyright notice and this permission notice (including the
15 * next paragraph) shall be included in all copies or substantial portions
18 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
19 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
20 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
21 * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
22 * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
23 * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
24 * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
26 **************************************************************************/
29 #include <X11/Xlibint.h>
30 #include <X11/extensions/XvMClib.h>
31 #include <pipe/p_screen.h>
32 #include <pipe/p_video_context.h>
33 #include <pipe/p_video_state.h>
34 #include <pipe/p_state.h>
35 #include <vl_winsys.h>
36 #include <util/u_memory.h>
37 #include <util/u_debug.h>
38 #include <vl/vl_csc.h>
39 #include "xvmc_private.h"
41 static Status
Validate(Display
*dpy
, XvPortID port
, int surface_type_id
,
42 unsigned int width
, unsigned int height
, int flags
,
43 bool *found_port
, int *screen
, int *chroma_format
,
44 int *mc_type
, int *surface_flags
)
46 bool found_surface
= false;
47 XvAdaptorInfo
*adaptor_info
;
48 unsigned int num_adaptors
;
50 unsigned int max_width
, max_height
;
56 assert(chroma_format
);
58 assert(surface_flags
);
62 for (unsigned int i
= 0; i
< XScreenCount(dpy
); ++i
) {
63 ret
= XvQueryAdaptors(dpy
, XRootWindow(dpy
, i
), &num_adaptors
, &adaptor_info
);
67 for (unsigned int j
= 0; j
< num_adaptors
&& !*found_port
; ++j
) {
68 for (unsigned int k
= 0; k
< adaptor_info
[j
].num_ports
&& !*found_port
; ++k
) {
69 XvMCSurfaceInfo
*surface_info
;
71 if (adaptor_info
[j
].base_id
+ k
!= port
)
76 surface_info
= XvMCListSurfaceTypes(dpy
, adaptor_info
[j
].base_id
, &num_types
);
78 XvFreeAdaptorInfo(adaptor_info
);
82 for (unsigned int l
= 0; l
< num_types
&& !found_surface
; ++l
) {
83 if (surface_info
[l
].surface_type_id
!= surface_type_id
)
87 max_width
= surface_info
[l
].max_width
;
88 max_height
= surface_info
[l
].max_height
;
89 *chroma_format
= surface_info
[l
].chroma_format
;
90 *mc_type
= surface_info
[l
].mc_type
;
91 *surface_flags
= surface_info
[l
].flags
;
99 XvFreeAdaptorInfo(adaptor_info
);
106 if (width
> max_width
|| height
> max_height
)
108 if (flags
!= XVMC_DIRECT
&& flags
!= 0)
114 static enum pipe_video_profile
ProfileToPipe(int xvmc_profile
)
116 if (xvmc_profile
& XVMC_MPEG_1
)
118 if (xvmc_profile
& XVMC_MPEG_2
)
119 return PIPE_VIDEO_PROFILE_MPEG2_MAIN
;
120 if (xvmc_profile
& XVMC_H263
)
122 if (xvmc_profile
& XVMC_MPEG_4
)
130 static enum pipe_video_chroma_format
FormatToPipe(int xvmc_format
)
132 switch (xvmc_format
) {
133 case XVMC_CHROMA_FORMAT_420
:
134 return PIPE_VIDEO_CHROMA_FORMAT_420
;
135 case XVMC_CHROMA_FORMAT_422
:
136 return PIPE_VIDEO_CHROMA_FORMAT_422
;
137 case XVMC_CHROMA_FORMAT_444
:
138 return PIPE_VIDEO_CHROMA_FORMAT_444
;
146 Status
XvMCCreateContext(Display
*dpy
, XvPortID port
, int surface_type_id
,
147 int width
, int height
, int flags
, XvMCContext
*context
)
155 struct pipe_screen
*screen
;
156 struct pipe_video_context
*vpipe
;
157 XvMCContextPrivate
*context_priv
;
163 return XvMCBadContext
;
165 ret
= Validate(dpy
, port
, surface_type_id
, width
, height
, flags
,
166 &found_port
, &scrn
, &chroma_format
, &mc_type
, &surface_flags
);
168 /* Success and XvBadPort have the same value */
169 if (ret
!= Success
|| !found_port
)
172 /* XXX: Current limits */
173 if (chroma_format
!= XVMC_CHROMA_FORMAT_420
) {
174 debug_printf("[XvMCg3dvl] Cannot decode requested surface type. Unsupported chroma format.\n");
175 return BadImplementation
;
177 if (mc_type
!= (XVMC_MOCOMP
| XVMC_MPEG_2
)) {
178 debug_printf("[XvMCg3dvl] Cannot decode requested surface type. Non-MPEG2/Mocomp acceleration unsupported.\n");
179 return BadImplementation
;
181 if (!(surface_flags
& XVMC_INTRA_UNSIGNED
)) {
182 debug_printf("[XvMCg3dvl] Cannot decode requested surface type. Signed intra unsupported.\n");
183 return BadImplementation
;
186 context_priv
= CALLOC(1, sizeof(XvMCContextPrivate
));
190 /* TODO: Reuse screen if process creates another context */
191 screen
= vl_screen_create(dpy
, scrn
);
198 vpipe
= vl_video_create(screen
, ProfileToPipe(mc_type
),
199 FormatToPipe(chroma_format
), width
, height
);
202 screen
->destroy(screen
);
207 /* TODO: Define some Xv attribs to allow users to specify color standard, procamp */
210 debug_get_bool_option("G3DVL_NO_CSC", FALSE
) ?
211 VL_CSC_COLOR_STANDARD_IDENTITY
: VL_CSC_COLOR_STANDARD_BT_601
,
214 vpipe
->set_csc_matrix(vpipe
, csc
);
216 context_priv
->vpipe
= vpipe
;
218 context
->context_id
= XAllocID(dpy
);
219 context
->surface_type_id
= surface_type_id
;
220 context
->width
= width
;
221 context
->height
= height
;
222 context
->flags
= flags
;
223 context
->port
= port
;
224 context
->privData
= context_priv
;
231 Status
XvMCDestroyContext(Display
*dpy
, XvMCContext
*context
)
233 struct pipe_screen
*screen
;
234 struct pipe_video_context
*vpipe
;
235 XvMCContextPrivate
*context_priv
;
239 if (!context
|| !context
->privData
)
240 return XvMCBadContext
;
242 context_priv
= context
->privData
;
243 vpipe
= context_priv
->vpipe
;
244 pipe_surface_reference(&context_priv
->backbuffer
, NULL
);
245 screen
= vpipe
->screen
;
246 vpipe
->destroy(vpipe
);
247 screen
->destroy(screen
);
249 context
->privData
= NULL
;