Merge branch 'mesa_7_6_branch'
[mesa.git] / src / xvmc / context.c
1 #include <assert.h>
2 #include <X11/Xlib.h>
3 #include <X11/extensions/XvMClib.h>
4 #include <X11/Xlibint.h>
5 #include <pipe/p_context.h>
6 #include <vl_display.h>
7 #include <vl_screen.h>
8 #include <vl_context.h>
9 #include <vl_winsys.h>
10
11 static Status Validate
12 (
13 Display *display,
14 XvPortID port,
15 int surface_type_id,
16 unsigned int width,
17 unsigned int height,
18 int flags,
19 int *found_port,
20 int *chroma_format,
21 int *mc_type
22 )
23 {
24 unsigned int found_surface = 0;
25 XvAdaptorInfo *adaptor_info;
26 unsigned int num_adaptors;
27 int num_types;
28 unsigned int max_width, max_height;
29 Status ret;
30 unsigned int i, j, k;
31
32 assert(display && chroma_format);
33
34 *found_port = 0;
35
36 ret = XvQueryAdaptors(display, XDefaultRootWindow(display), &num_adaptors, &adaptor_info);
37 if (ret != Success)
38 return ret;
39
40 /* Scan through all adaptors looking for this port and surface */
41 for (i = 0; i < num_adaptors && !*found_port; ++i)
42 {
43 /* Scan through all ports of this adaptor looking for our port */
44 for (j = 0; j < adaptor_info[i].num_ports && !*found_port; ++j)
45 {
46 /* If this is our port, scan through all its surfaces looking for our surface */
47 if (adaptor_info[i].base_id + j == port)
48 {
49 XvMCSurfaceInfo *surface_info;
50
51 *found_port = 1;
52 surface_info = XvMCListSurfaceTypes(display, adaptor_info[i].base_id, &num_types);
53
54 if (surface_info)
55 {
56 for (k = 0; k < num_types && !found_surface; ++k)
57 {
58 if (surface_info[k].surface_type_id == surface_type_id)
59 {
60 found_surface = 1;
61 max_width = surface_info[k].max_width;
62 max_height = surface_info[k].max_height;
63 *chroma_format = surface_info[k].chroma_format;
64 *mc_type = surface_info[k].mc_type;
65 }
66 }
67
68 XFree(surface_info);
69 }
70 else
71 {
72 XvFreeAdaptorInfo(adaptor_info);
73 return BadAlloc;
74 }
75 }
76 }
77 }
78
79 XvFreeAdaptorInfo(adaptor_info);
80
81 if (!*found_port)
82 return XvBadPort;
83 if (!found_surface)
84 return BadMatch;
85 if (width > max_width || height > max_height)
86 return BadValue;
87 if (flags != XVMC_DIRECT && flags != 0)
88 return BadValue;
89
90 return Success;
91 }
92
93 static enum vlProfile ProfileToVL(int xvmc_profile)
94 {
95 if (xvmc_profile & XVMC_MPEG_1)
96 assert(0);
97 else if (xvmc_profile & XVMC_MPEG_2)
98 return vlProfileMpeg2Main;
99 else if (xvmc_profile & XVMC_H263)
100 assert(0);
101 else if (xvmc_profile & XVMC_MPEG_4)
102 assert(0);
103 else
104 assert(0);
105
106 return -1;
107 }
108
109 static enum vlEntryPoint EntryToVL(int xvmc_entry)
110 {
111 return xvmc_entry & XVMC_IDCT ? vlEntryPointIDCT : vlEntryPointMC;
112 }
113
114 static enum vlFormat FormatToVL(int xvmc_format)
115 {
116 switch (xvmc_format)
117 {
118 case XVMC_CHROMA_FORMAT_420:
119 return vlFormatYCbCr420;
120 case XVMC_CHROMA_FORMAT_422:
121 return vlFormatYCbCr422;
122 case XVMC_CHROMA_FORMAT_444:
123 return vlFormatYCbCr444;
124 default:
125 assert(0);
126 }
127
128 return -1;
129 }
130
131 Status XvMCCreateContext(Display *display, XvPortID port, int surface_type_id, int width, int height, int flags, XvMCContext *context)
132 {
133 int found_port;
134 int chroma_format;
135 int mc_type;
136 Status ret;
137 struct vlDisplay *vl_dpy;
138 struct vlScreen *vl_scrn;
139 struct vlContext *vl_ctx;
140 struct pipe_context *pipe;
141 Display *dpy = display;
142
143 assert(display);
144
145 if (!context)
146 return XvMCBadContext;
147
148 ret = Validate(display, port, surface_type_id, width, height, flags, &found_port, &chroma_format, &mc_type);
149
150 /* XXX: Success and XvBadPort have the same value */
151 if (ret != Success || !found_port)
152 return ret;
153
154 /* XXX: Assumes default screen, should check which screen port is on */
155 pipe = create_pipe_context(display, XDefaultScreen(display));
156
157 assert(pipe);
158
159 vlCreateDisplay(display, &vl_dpy);
160 vlCreateScreen(vl_dpy, XDefaultScreen(display), pipe->screen, &vl_scrn);
161 vlCreateContext
162 (
163 vl_scrn,
164 pipe,
165 width,
166 height,
167 FormatToVL(chroma_format),
168 ProfileToVL(mc_type),
169 EntryToVL(mc_type),
170 &vl_ctx
171 );
172
173 context->context_id = XAllocID(display);
174 context->surface_type_id = surface_type_id;
175 context->width = width;
176 context->height = height;
177 context->flags = flags;
178 context->port = port;
179 context->privData = vl_ctx;
180
181 SyncHandle();
182 return Success;
183 }
184
185 Status XvMCDestroyContext(Display *display, XvMCContext *context)
186 {
187 struct vlContext *vl_ctx;
188 struct vlScreen *vl_screen;
189 struct vlDisplay *vl_dpy;
190 struct pipe_context *pipe;
191
192 assert(display);
193
194 if (!context)
195 return XvMCBadContext;
196
197 vl_ctx = context->privData;
198
199 assert(display == vlGetNativeDisplay(vlGetDisplay(vlContextGetScreen(vl_ctx))));
200
201 pipe = vlGetPipeContext(vl_ctx);
202 vl_screen = vlContextGetScreen(vl_ctx);
203 vl_dpy = vlGetDisplay(vl_screen);
204 vlDestroyContext(vl_ctx);
205 vlDestroyScreen(vl_screen);
206 vlDestroyDisplay(vl_dpy);
207 destroy_pipe_context(pipe);
208
209 return Success;
210 }