st/xvmc: Set default CSC matrix to BT.601, no ProcAmp, full range RGB.
[mesa.git] / src / gallium / state_trackers / xorg / xvmc / context.c
1 #include <assert.h>
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>
8 #include <vl_winsys.h>
9 #include <util/u_memory.h>
10 #include <util/u_debug.h>
11 #include <vl/vl_csc.h>
12 #include "xvmc_private.h"
13
14 static Status Validate(Display *dpy, XvPortID port, int surface_type_id,
15 unsigned int width, unsigned int height, int flags,
16 bool *found_port, int *screen, int *chroma_format,
17 int *mc_type, int *surface_flags)
18 {
19 bool found_surface = false;
20 XvAdaptorInfo *adaptor_info;
21 unsigned int num_adaptors;
22 int num_types;
23 unsigned int max_width, max_height;
24 Status ret;
25
26 assert(dpy);
27 assert(found_port);
28 assert(screen);
29 assert(chroma_format);
30 assert(mc_type);
31 assert(surface_flags);
32
33 *found_port = false;
34
35 for (unsigned int i = 0; i < XScreenCount(dpy); ++i) {
36 ret = XvQueryAdaptors(dpy, XRootWindow(dpy, i), &num_adaptors, &adaptor_info);
37 if (ret != Success)
38 return ret;
39
40 for (unsigned int j = 0; j < num_adaptors && !*found_port; ++j) {
41 for (unsigned int k = 0; k < adaptor_info[j].num_ports && !*found_port; ++k) {
42 XvMCSurfaceInfo *surface_info;
43
44 if (adaptor_info[j].base_id + k != port)
45 continue;
46
47 *found_port = true;
48
49 surface_info = XvMCListSurfaceTypes(dpy, adaptor_info[j].base_id, &num_types);
50 if (!surface_info) {
51 XvFreeAdaptorInfo(adaptor_info);
52 return BadAlloc;
53 }
54
55 for (unsigned int l = 0; l < num_types && !found_surface; ++l) {
56 if (surface_info[l].surface_type_id != surface_type_id)
57 continue;
58
59 found_surface = true;
60 max_width = surface_info[l].max_width;
61 max_height = surface_info[l].max_height;
62 *chroma_format = surface_info[l].chroma_format;
63 *mc_type = surface_info[l].mc_type;
64 *surface_flags = surface_info[l].flags;
65 *screen = i;
66 }
67
68 XFree(surface_info);
69 }
70 }
71
72 XvFreeAdaptorInfo(adaptor_info);
73 }
74
75 if (!*found_port)
76 return XvBadPort;
77 if (!found_surface)
78 return BadMatch;
79 if (width > max_width || height > max_height)
80 return BadValue;
81 if (flags != XVMC_DIRECT && flags != 0)
82 return BadValue;
83
84 return Success;
85 }
86
87 static enum pipe_video_profile ProfileToPipe(int xvmc_profile)
88 {
89 if (xvmc_profile & XVMC_MPEG_1)
90 assert(0);
91 if (xvmc_profile & XVMC_MPEG_2)
92 return PIPE_VIDEO_PROFILE_MPEG2_MAIN;
93 if (xvmc_profile & XVMC_H263)
94 assert(0);
95 if (xvmc_profile & XVMC_MPEG_4)
96 assert(0);
97
98 assert(0);
99
100 return -1;
101 }
102
103 static enum pipe_video_chroma_format FormatToPipe(int xvmc_format)
104 {
105 switch (xvmc_format) {
106 case XVMC_CHROMA_FORMAT_420:
107 return PIPE_VIDEO_CHROMA_FORMAT_420;
108 case XVMC_CHROMA_FORMAT_422:
109 return PIPE_VIDEO_CHROMA_FORMAT_422;
110 case XVMC_CHROMA_FORMAT_444:
111 return PIPE_VIDEO_CHROMA_FORMAT_444;
112 default:
113 assert(0);
114 }
115
116 return -1;
117 }
118
119 Status XvMCCreateContext(Display *dpy, XvPortID port, int surface_type_id,
120 int width, int height, int flags, XvMCContext *context)
121 {
122 bool found_port;
123 int scrn;
124 int chroma_format;
125 int mc_type;
126 int surface_flags;
127 Status ret;
128 struct pipe_screen *screen;
129 struct pipe_video_context *vpipe;
130 XvMCContextPrivate *context_priv;
131 float csc[16];
132
133 assert(dpy);
134
135 if (!context)
136 return XvMCBadContext;
137
138 ret = Validate(dpy, port, surface_type_id, width, height, flags,
139 &found_port, &scrn, &chroma_format, &mc_type, &surface_flags);
140
141 /* Success and XvBadPort have the same value */
142 if (ret != Success || !found_port)
143 return ret;
144
145 /* XXX: Current limits */
146 if (chroma_format != XVMC_CHROMA_FORMAT_420) {
147 debug_printf("[XvMCg3dvl] Cannot decode requested surface type. Unsupported chroma format.\n");
148 return BadImplementation;
149 }
150 if (mc_type != (XVMC_MOCOMP | XVMC_MPEG_2)) {
151 debug_printf("[XvMCg3dvl] Cannot decode requested surface type. Non-MPEG2/Mocomp acceleration unsupported.\n");
152 return BadImplementation;
153 }
154 if (!(surface_flags & XVMC_INTRA_UNSIGNED)) {
155 debug_printf("[XvMCg3dvl] Cannot decode requested surface type. Signed intra unsupported.\n");
156 return BadImplementation;
157 }
158
159 context_priv = CALLOC(1, sizeof(XvMCContextPrivate));
160 if (!context_priv)
161 return BadAlloc;
162
163 /* TODO: Reuse screen if process creates another context */
164 screen = vl_screen_create(dpy, scrn);
165
166 if (!screen) {
167 FREE(context_priv);
168 return BadAlloc;
169 }
170
171 vpipe = vl_video_create(screen, ProfileToPipe(mc_type),
172 FormatToPipe(chroma_format), width, height);
173
174 if (!vpipe) {
175 screen->destroy(screen);
176 FREE(context_priv);
177 return BadAlloc;
178 }
179
180 /* TODO: Define some Xv attribs to allow users to specify color standard, procamp */
181 vl_csc_get_matrix
182 (
183 debug_get_bool_option("G3DVL_NO_CSC", FALSE) ?
184 VL_CSC_COLOR_STANDARD_IDENTITY : VL_CSC_COLOR_STANDARD_BT_601,
185 NULL, true, csc
186 );
187 vpipe->set_csc_matrix(vpipe, csc);
188
189 context_priv->vpipe = vpipe;
190
191 context->context_id = XAllocID(dpy);
192 context->surface_type_id = surface_type_id;
193 context->width = width;
194 context->height = height;
195 context->flags = flags;
196 context->port = port;
197 context->privData = context_priv;
198
199 SyncHandle();
200
201 return Success;
202 }
203
204 Status XvMCDestroyContext(Display *dpy, XvMCContext *context)
205 {
206 struct pipe_screen *screen;
207 struct pipe_video_context *vpipe;
208 XvMCContextPrivate *context_priv;
209
210 assert(dpy);
211
212 if (!context || !context->privData)
213 return XvMCBadContext;
214
215 context_priv = context->privData;
216 vpipe = context_priv->vpipe;
217 pipe_surface_reference(&context_priv->backbuffer, NULL);
218 screen = vpipe->screen;
219 vpipe->destroy(vpipe);
220 screen->destroy(screen);
221 FREE(context_priv);
222 context->privData = NULL;
223
224 return Success;
225 }