g3dvl: Fix field coded block copy.
[mesa.git] / src / libXvMC / 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 vlCreateSurface
77 (
78 vlContextGetScreen(vl_ctx),
79 context->width,
80 context->height,
81 vlGetPictureFormat(vl_ctx),
82 &vl_sfc
83 );
84
85 vlBindToContext(vl_sfc, vl_ctx);
86
87 surface->surface_id = XAllocID(display);
88 surface->context_id = context->context_id;
89 surface->surface_type_id = context->surface_type_id;
90 surface->width = context->width;
91 surface->height = context->height;
92 surface->privData = vl_sfc;
93
94 return Success;
95 }
96
97 Status XvMCRenderSurface
98 (
99 Display *display,
100 XvMCContext *context,
101 unsigned int picture_structure,
102 XvMCSurface *target_surface,
103 XvMCSurface *past_surface,
104 XvMCSurface *future_surface,
105 unsigned int flags,
106 unsigned int num_macroblocks,
107 unsigned int first_macroblock,
108 XvMCMacroBlockArray *macroblocks,
109 XvMCBlockArray *blocks
110 )
111 {
112 struct vlContext *vl_ctx;
113 struct vlSurface *target_vl_surface;
114 struct vlSurface *past_vl_surface;
115 struct vlSurface *future_vl_surface;
116 struct vlMpeg2MacroBlockBatch batch;
117 struct vlMpeg2MacroBlock vl_macroblocks[num_macroblocks];
118 unsigned int i;
119
120 assert(display);
121
122 if (!context)
123 return XvMCBadContext;
124 if (!target_surface)
125 return XvMCBadSurface;
126
127 if
128 (
129 picture_structure != XVMC_TOP_FIELD &&
130 picture_structure != XVMC_BOTTOM_FIELD &&
131 picture_structure != XVMC_FRAME_PICTURE
132 )
133 return BadValue;
134 if (future_surface && !past_surface)
135 return BadMatch;
136
137 vl_ctx = context->privData;
138
139 assert(display == vlGetNativeDisplay(vlGetDisplay(vlContextGetScreen(vl_ctx))));
140
141 target_vl_surface = target_surface->privData;
142 past_vl_surface = past_surface ? past_surface->privData : NULL;
143 future_vl_surface = future_surface ? future_surface->privData : NULL;
144
145 assert(context->context_id == target_surface->context_id);
146 assert(!past_surface || context->context_id == past_surface->context_id);
147 assert(!future_surface || context->context_id == future_surface->context_id);
148
149 assert(macroblocks);
150 assert(blocks);
151
152 assert(macroblocks->context_id == context->context_id);
153 assert(blocks->context_id == context->context_id);
154
155 assert(flags == 0 || flags == XVMC_SECOND_FIELD);
156
157 batch.past_surface = past_vl_surface;
158 batch.future_surface = future_vl_surface;
159 batch.picture_type = PictureToVL(picture_structure);
160 batch.field_order = flags & XVMC_SECOND_FIELD ? vlFieldOrderSecond : vlFieldOrderFirst;
161 batch.num_macroblocks = num_macroblocks;
162 batch.macroblocks = vl_macroblocks;
163
164 for (i = 0; i < num_macroblocks; ++i)
165 {
166 unsigned int j = first_macroblock + i;
167
168 unsigned int k, l, m;
169
170 batch.macroblocks[i].mbx = macroblocks->macro_blocks[j].x;
171 batch.macroblocks[i].mby = macroblocks->macro_blocks[j].y;
172 batch.macroblocks[i].mb_type = TypeToVL(macroblocks->macro_blocks[j].macroblock_type);
173 if (batch.macroblocks[i].mb_type != vlMacroBlockTypeIntra)
174 batch.macroblocks[i].mo_type = MotionToVL(macroblocks->macro_blocks[j].motion_type, macroblocks->macro_blocks[j].dct_type);
175 batch.macroblocks[i].dct_type = macroblocks->macro_blocks[j].dct_type == XVMC_DCT_TYPE_FIELD ? vlDCTTypeFieldCoded : vlDCTTypeFrameCoded;
176
177 for (k = 0; k < 2; ++k)
178 for (l = 0; l < 2; ++l)
179 for (m = 0; m < 2; ++m)
180 batch.macroblocks[i].PMV[k][l][m] = macroblocks->macro_blocks[j].PMV[k][l][m];
181
182 batch.macroblocks[i].cbp = macroblocks->macro_blocks[j].coded_block_pattern;
183 batch.macroblocks[i].blocks = blocks->blocks + (macroblocks->macro_blocks[j].index * 64);
184 }
185
186 vlRenderMacroBlocksMpeg2(&batch, target_vl_surface);
187
188 return Success;
189 }
190
191 Status XvMCFlushSurface(Display *display, XvMCSurface *surface)
192 {
193 struct vlSurface *vl_sfc;
194
195 assert(display);
196
197 if (!surface)
198 return XvMCBadSurface;
199
200 vl_sfc = surface->privData;
201
202 assert(display == vlGetNativeDisplay(vlGetDisplay(vlSurfaceGetScreen(vl_sfc))));
203
204 vlSurfaceFlush(vl_sfc);
205
206 return Success;
207 }
208
209 Status XvMCSyncSurface(Display *display, XvMCSurface *surface)
210 {
211 struct vlSurface *vl_sfc;
212
213 assert(display);
214
215 if (!surface)
216 return XvMCBadSurface;
217
218 vl_sfc = surface->privData;
219
220 assert(display == vlGetNativeDisplay(vlGetDisplay(vlSurfaceGetScreen(vl_sfc))));
221
222 vlSurfaceSync(vl_sfc);
223
224 return Success;
225 }
226
227 Status XvMCPutSurface
228 (
229 Display *display,
230 XvMCSurface *surface,
231 Drawable drawable,
232 short srcx,
233 short srcy,
234 unsigned short srcw,
235 unsigned short srch,
236 short destx,
237 short desty,
238 unsigned short destw,
239 unsigned short desth,
240 int flags
241 )
242 {
243 Window root;
244 int x, y;
245 unsigned int width, height;
246 unsigned int border_width;
247 unsigned int depth;
248 struct vlSurface *vl_sfc;
249
250 assert(display);
251
252 if (!surface)
253 return XvMCBadSurface;
254
255 if (XGetGeometry(display, drawable, &root, &x, &y, &width, &height, &border_width, &depth) == BadDrawable)
256 return BadDrawable;
257
258 assert(flags == XVMC_TOP_FIELD || flags == XVMC_BOTTOM_FIELD || flags == XVMC_FRAME_PICTURE);
259
260 /* TODO: Correct for negative srcx,srcy & destx,desty by clipping */
261
262 assert(srcx + srcw - 1 < surface->width);
263 assert(srcy + srch - 1 < surface->height);
264 assert(destx + destw - 1 < width);
265 assert(desty + desth - 1 < height);
266
267 vl_sfc = surface->privData;
268
269 vlPutPicture(vl_sfc, drawable, srcx, srcy, srcw, srch, destx, desty, destw, desth, width, height, PictureToVL(flags));
270
271 return Success;
272 }
273
274 Status XvMCGetSurfaceStatus(Display *display, XvMCSurface *surface, int *status)
275 {
276 struct vlSurface *vl_sfc;
277 enum vlResourceStatus res_status;
278
279 assert(display);
280
281 if (!surface)
282 return XvMCBadSurface;
283
284 assert(status);
285
286 vl_sfc = surface->privData;
287
288 assert(display == vlGetNativeDisplay(vlGetDisplay(vlSurfaceGetScreen(vl_sfc))));
289
290 vlSurfaceGetStatus(vl_sfc, &res_status);
291
292 switch (res_status)
293 {
294 case vlResourceStatusFree:
295 {
296 *status = 0;
297 break;
298 }
299 case vlResourceStatusRendering:
300 {
301 *status = XVMC_RENDERING;
302 break;
303 }
304 case vlResourceStatusDisplaying:
305 {
306 *status = XVMC_DISPLAYING;
307 break;
308 }
309 default:
310 assert(0);
311 }
312
313 return Success;
314 }
315
316 Status XvMCDestroySurface(Display *display, XvMCSurface *surface)
317 {
318 struct vlSurface *vl_sfc;
319
320 assert(display);
321
322 if (!surface)
323 return XvMCBadSurface;
324
325 vl_sfc = surface->privData;
326
327 assert(display == vlGetNativeDisplay(vlGetDisplay(vlSurfaceGetScreen(vl_sfc))));
328
329 vlDestroySurface(vl_sfc);
330
331 return Success;
332 }
333
334 Status XvMCHideSurface(Display *display, XvMCSurface *surface)
335 {
336 struct vlSurface *vl_sfc;
337
338 assert(display);
339
340 if (!surface)
341 return XvMCBadSurface;
342
343 vl_sfc = surface->privData;
344
345 assert(display == vlGetNativeDisplay(vlGetDisplay(vlSurfaceGetScreen(vl_sfc))));
346
347 /* No op, only for overlaid rendering */
348
349 return Success;
350 }