r200: Addd missing parameter to debug output.
[mesa.git] / src / xvmc / surface.c
1 #include <assert.h>
2 #include <X11/Xlib.h>
3 #include <X11/extensions/XvMC.h>
4 #include <vl_display.h>
5 #include <vl_screen.h>
6 #include <vl_context.h>
7 #include <vl_surface.h>
8 #include <vl_types.h>
9
10 static enum vlMacroBlockType TypeToVL(int xvmc_mb_type)
11 {
12 if (xvmc_mb_type & XVMC_MB_TYPE_INTRA)
13 return vlMacroBlockTypeIntra;
14 if ((xvmc_mb_type & (XVMC_MB_TYPE_MOTION_FORWARD | XVMC_MB_TYPE_MOTION_BACKWARD)) == XVMC_MB_TYPE_MOTION_FORWARD)
15 return vlMacroBlockTypeFwdPredicted;
16 if ((xvmc_mb_type & (XVMC_MB_TYPE_MOTION_FORWARD | XVMC_MB_TYPE_MOTION_BACKWARD)) == XVMC_MB_TYPE_MOTION_BACKWARD)
17 return vlMacroBlockTypeBkwdPredicted;
18 if ((xvmc_mb_type & (XVMC_MB_TYPE_MOTION_FORWARD | XVMC_MB_TYPE_MOTION_BACKWARD)) == (XVMC_MB_TYPE_MOTION_FORWARD | XVMC_MB_TYPE_MOTION_BACKWARD))
19 return vlMacroBlockTypeBiPredicted;
20
21 assert(0);
22
23 return -1;
24 }
25
26 static enum vlPictureType PictureToVL(int xvmc_pic)
27 {
28 switch (xvmc_pic)
29 {
30 case XVMC_TOP_FIELD:
31 return vlPictureTypeTopField;
32 case XVMC_BOTTOM_FIELD:
33 return vlPictureTypeBottomField;
34 case XVMC_FRAME_PICTURE:
35 return vlPictureTypeFrame;
36 default:
37 assert(0);
38 }
39
40 return -1;
41 }
42
43 static enum vlMotionType MotionToVL(int xvmc_motion_type, int xvmc_dct_type)
44 {
45 switch (xvmc_motion_type)
46 {
47 case XVMC_PREDICTION_FRAME:
48 return xvmc_dct_type == XVMC_DCT_TYPE_FIELD ? vlMotionType16x8 : vlMotionTypeFrame;
49 case XVMC_PREDICTION_FIELD:
50 return vlMotionTypeField;
51 case XVMC_PREDICTION_DUAL_PRIME:
52 return vlMotionTypeDualPrime;
53 default:
54 assert(0);
55 }
56
57 return -1;
58 }
59
60 Status XvMCCreateSurface(Display *display, XvMCContext *context, XvMCSurface *surface)
61 {
62 struct vlContext *vl_ctx;
63 struct vlSurface *vl_sfc;
64
65 assert(display);
66
67 if (!context)
68 return XvMCBadContext;
69 if (!surface)
70 return XvMCBadSurface;
71
72 vl_ctx = context->privData;
73
74 assert(display == vlGetNativeDisplay(vlGetDisplay(vlContextGetScreen(vl_ctx))));
75
76 if (vlCreateSurface(vlContextGetScreen(vl_ctx),
77 context->width, context->height,
78 vlGetPictureFormat(vl_ctx),
79 &vl_sfc))
80 {
81 return BadAlloc;
82 }
83
84 vlBindToContext(vl_sfc, vl_ctx);
85
86 surface->surface_id = XAllocID(display);
87 surface->context_id = context->context_id;
88 surface->surface_type_id = context->surface_type_id;
89 surface->width = context->width;
90 surface->height = context->height;
91 surface->privData = vl_sfc;
92
93 return Success;
94 }
95
96 Status XvMCRenderSurface
97 (
98 Display *display,
99 XvMCContext *context,
100 unsigned int picture_structure,
101 XvMCSurface *target_surface,
102 XvMCSurface *past_surface,
103 XvMCSurface *future_surface,
104 unsigned int flags,
105 unsigned int num_macroblocks,
106 unsigned int first_macroblock,
107 XvMCMacroBlockArray *macroblocks,
108 XvMCBlockArray *blocks
109 )
110 {
111 struct vlContext *vl_ctx;
112 struct vlSurface *target_vl_surface;
113 struct vlSurface *past_vl_surface;
114 struct vlSurface *future_vl_surface;
115 struct vlMpeg2MacroBlockBatch batch;
116 struct vlMpeg2MacroBlock vl_macroblocks[num_macroblocks];
117 unsigned int i;
118
119 assert(display);
120
121 if (!context)
122 return XvMCBadContext;
123 if (!target_surface)
124 return XvMCBadSurface;
125
126 if
127 (
128 picture_structure != XVMC_TOP_FIELD &&
129 picture_structure != XVMC_BOTTOM_FIELD &&
130 picture_structure != XVMC_FRAME_PICTURE
131 )
132 return BadValue;
133 if (future_surface && !past_surface)
134 return BadMatch;
135
136 vl_ctx = context->privData;
137
138 assert(display == vlGetNativeDisplay(vlGetDisplay(vlContextGetScreen(vl_ctx))));
139
140 target_vl_surface = target_surface->privData;
141 past_vl_surface = past_surface ? past_surface->privData : NULL;
142 future_vl_surface = future_surface ? future_surface->privData : NULL;
143
144 assert(context->context_id == target_surface->context_id);
145 assert(!past_surface || context->context_id == past_surface->context_id);
146 assert(!future_surface || context->context_id == future_surface->context_id);
147
148 assert(macroblocks);
149 assert(blocks);
150
151 assert(macroblocks->context_id == context->context_id);
152 assert(blocks->context_id == context->context_id);
153
154 assert(flags == 0 || flags == XVMC_SECOND_FIELD);
155
156 batch.past_surface = past_vl_surface;
157 batch.future_surface = future_vl_surface;
158 batch.picture_type = PictureToVL(picture_structure);
159 batch.field_order = flags & XVMC_SECOND_FIELD ? vlFieldOrderSecond : vlFieldOrderFirst;
160 batch.num_macroblocks = num_macroblocks;
161 batch.macroblocks = vl_macroblocks;
162
163 for (i = 0; i < num_macroblocks; ++i)
164 {
165 unsigned int j = first_macroblock + i;
166
167 unsigned int k, l, m;
168
169 batch.macroblocks[i].mbx = macroblocks->macro_blocks[j].x;
170 batch.macroblocks[i].mby = macroblocks->macro_blocks[j].y;
171 batch.macroblocks[i].mb_type = TypeToVL(macroblocks->macro_blocks[j].macroblock_type);
172 if (batch.macroblocks[i].mb_type != vlMacroBlockTypeIntra)
173 batch.macroblocks[i].mo_type = MotionToVL(macroblocks->macro_blocks[j].motion_type, macroblocks->macro_blocks[j].dct_type);
174 batch.macroblocks[i].dct_type = macroblocks->macro_blocks[j].dct_type == XVMC_DCT_TYPE_FIELD ? vlDCTTypeFieldCoded : vlDCTTypeFrameCoded;
175
176 for (k = 0; k < 2; ++k)
177 for (l = 0; l < 2; ++l)
178 for (m = 0; m < 2; ++m)
179 batch.macroblocks[i].PMV[k][l][m] = macroblocks->macro_blocks[j].PMV[k][l][m];
180
181 batch.macroblocks[i].cbp = macroblocks->macro_blocks[j].coded_block_pattern;
182 batch.macroblocks[i].blocks = blocks->blocks + (macroblocks->macro_blocks[j].index * 64);
183 }
184
185 vlRenderMacroBlocksMpeg2(&batch, target_vl_surface);
186
187 return Success;
188 }
189
190 Status XvMCFlushSurface(Display *display, XvMCSurface *surface)
191 {
192 struct vlSurface *vl_sfc;
193
194 assert(display);
195
196 if (!surface)
197 return XvMCBadSurface;
198
199 vl_sfc = surface->privData;
200
201 assert(display == vlGetNativeDisplay(vlGetDisplay(vlSurfaceGetScreen(vl_sfc))));
202
203 vlSurfaceFlush(vl_sfc);
204
205 return Success;
206 }
207
208 Status XvMCSyncSurface(Display *display, XvMCSurface *surface)
209 {
210 struct vlSurface *vl_sfc;
211
212 assert(display);
213
214 if (!surface)
215 return XvMCBadSurface;
216
217 vl_sfc = surface->privData;
218
219 assert(display == vlGetNativeDisplay(vlGetDisplay(vlSurfaceGetScreen(vl_sfc))));
220
221 vlSurfaceSync(vl_sfc);
222
223 return Success;
224 }
225
226 Status XvMCPutSurface
227 (
228 Display *display,
229 XvMCSurface *surface,
230 Drawable drawable,
231 short srcx,
232 short srcy,
233 unsigned short srcw,
234 unsigned short srch,
235 short destx,
236 short desty,
237 unsigned short destw,
238 unsigned short desth,
239 int flags
240 )
241 {
242 Window root;
243 int x, y;
244 unsigned int width, height;
245 unsigned int border_width;
246 unsigned int depth;
247 struct vlSurface *vl_sfc;
248
249 assert(display);
250
251 if (!surface)
252 return XvMCBadSurface;
253
254 if (XGetGeometry(display, drawable, &root, &x, &y, &width, &height, &border_width, &depth) == BadDrawable)
255 return BadDrawable;
256
257 assert(flags == XVMC_TOP_FIELD || flags == XVMC_BOTTOM_FIELD || flags == XVMC_FRAME_PICTURE);
258
259 /* TODO: Correct for negative srcx,srcy & destx,desty by clipping */
260
261 assert(srcx + srcw - 1 < surface->width);
262 assert(srcy + srch - 1 < surface->height);
263 /* XXX: Some apps (mplayer) hit these asserts because they call
264 * this function after the window has been resized by the WM
265 * but before they've handled the corresponding XEvent and
266 * know about the new dimensions. The output will be clipped
267 * for a few frames until the app updates destw and desth.
268 */
269 /*assert(destx + destw - 1 < width);
270 assert(desty + desth - 1 < height);*/
271
272 vl_sfc = surface->privData;
273
274 vlPutPicture(vl_sfc, drawable, srcx, srcy, srcw, srch, destx, desty, destw, desth, width, height, PictureToVL(flags));
275
276 return Success;
277 }
278
279 Status XvMCGetSurfaceStatus(Display *display, XvMCSurface *surface, int *status)
280 {
281 struct vlSurface *vl_sfc;
282 enum vlResourceStatus res_status;
283
284 assert(display);
285
286 if (!surface)
287 return XvMCBadSurface;
288
289 assert(status);
290
291 vl_sfc = surface->privData;
292
293 assert(display == vlGetNativeDisplay(vlGetDisplay(vlSurfaceGetScreen(vl_sfc))));
294
295 vlSurfaceGetStatus(vl_sfc, &res_status);
296
297 switch (res_status)
298 {
299 case vlResourceStatusFree:
300 {
301 *status = 0;
302 break;
303 }
304 case vlResourceStatusRendering:
305 {
306 *status = XVMC_RENDERING;
307 break;
308 }
309 case vlResourceStatusDisplaying:
310 {
311 *status = XVMC_DISPLAYING;
312 break;
313 }
314 default:
315 assert(0);
316 }
317
318 return Success;
319 }
320
321 Status XvMCDestroySurface(Display *display, XvMCSurface *surface)
322 {
323 struct vlSurface *vl_sfc;
324
325 assert(display);
326
327 if (!surface)
328 return XvMCBadSurface;
329
330 vl_sfc = surface->privData;
331
332 assert(display == vlGetNativeDisplay(vlGetDisplay(vlSurfaceGetScreen(vl_sfc))));
333
334 vlDestroySurface(vl_sfc);
335
336 return Success;
337 }
338
339 Status XvMCHideSurface(Display *display, XvMCSurface *surface)
340 {
341 struct vlSurface *vl_sfc;
342
343 assert(display);
344
345 if (!surface)
346 return XvMCBadSurface;
347
348 vl_sfc = surface->privData;
349
350 assert(display == vlGetNativeDisplay(vlGetDisplay(vlSurfaceGetScreen(vl_sfc))));
351
352 /* No op, only for overlaid rendering */
353
354 return Success;
355 }