[g3dvl] and finally remove pipe_video_context
[mesa.git] / src / gallium / state_trackers / xorg / xvmc / surface.c
1 /**************************************************************************
2 *
3 * Copyright 2009 Younes Manton.
4 * All Rights Reserved.
5 *
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:
13 *
14 * The above copyright notice and this permission notice (including the
15 * next paragraph) shall be included in all copies or substantial portions
16 * of the Software.
17 *
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.
25 *
26 **************************************************************************/
27
28 #include <assert.h>
29 #include <stdio.h>
30
31 #include <X11/Xlibint.h>
32
33 #include <pipe/p_video_decoder.h>
34 #include <pipe/p_video_state.h>
35 #include <pipe/p_state.h>
36
37 #include <util/u_inlines.h>
38 #include <util/u_memory.h>
39 #include <util/u_math.h>
40
41 #include <vl_winsys.h>
42
43 #include "xvmc_private.h"
44
45 static const unsigned const_empty_block_mask_420[3][2][2] = {
46 { { 0x20, 0x10 }, { 0x08, 0x04 } },
47 { { 0x02, 0x02 }, { 0x02, 0x02 } },
48 { { 0x01, 0x01 }, { 0x01, 0x01 } }
49 };
50
51 static enum pipe_mpeg12_picture_type PictureToPipe(int xvmc_pic)
52 {
53 switch (xvmc_pic) {
54 case XVMC_TOP_FIELD:
55 return PIPE_MPEG12_PICTURE_TYPE_FIELD_TOP;
56 case XVMC_BOTTOM_FIELD:
57 return PIPE_MPEG12_PICTURE_TYPE_FIELD_BOTTOM;
58 case XVMC_FRAME_PICTURE:
59 return PIPE_MPEG12_PICTURE_TYPE_FRAME;
60 default:
61 assert(0);
62 }
63
64 XVMC_MSG(XVMC_ERR, "[XvMC] Unrecognized picture type 0x%08X.\n", xvmc_pic);
65
66 return -1;
67 }
68
69 static inline void
70 MacroBlockTypeToPipeWeights(const XvMCMacroBlock *xvmc_mb, unsigned weights[2])
71 {
72 assert(xvmc_mb);
73
74 switch (xvmc_mb->macroblock_type & (XVMC_MB_TYPE_MOTION_FORWARD | XVMC_MB_TYPE_MOTION_BACKWARD)) {
75 case XVMC_MB_TYPE_MOTION_FORWARD:
76 weights[0] = PIPE_VIDEO_MV_WEIGHT_MAX;
77 weights[1] = PIPE_VIDEO_MV_WEIGHT_MIN;
78 break;
79
80 case (XVMC_MB_TYPE_MOTION_FORWARD | XVMC_MB_TYPE_MOTION_BACKWARD):
81 weights[0] = PIPE_VIDEO_MV_WEIGHT_HALF;
82 weights[1] = PIPE_VIDEO_MV_WEIGHT_HALF;
83 break;
84
85 case XVMC_MB_TYPE_MOTION_BACKWARD:
86 weights[0] = PIPE_VIDEO_MV_WEIGHT_MIN;
87 weights[1] = PIPE_VIDEO_MV_WEIGHT_MAX;
88 break;
89
90 default:
91 /* workaround for xines xxmc video out plugin */
92 if (!(xvmc_mb->macroblock_type & ~XVMC_MB_TYPE_PATTERN)) {
93 weights[0] = PIPE_VIDEO_MV_WEIGHT_MAX;
94 weights[1] = PIPE_VIDEO_MV_WEIGHT_MIN;
95 } else {
96 weights[0] = PIPE_VIDEO_MV_WEIGHT_MIN;
97 weights[1] = PIPE_VIDEO_MV_WEIGHT_MIN;
98 }
99 break;
100 }
101 }
102
103 static inline struct pipe_motionvector
104 MotionVectorToPipe(const XvMCMacroBlock *xvmc_mb, unsigned vector,
105 unsigned field_select_mask, unsigned weight)
106 {
107 struct pipe_motionvector mv;
108
109 assert(xvmc_mb);
110
111 switch (xvmc_mb->motion_type) {
112 case XVMC_PREDICTION_FRAME:
113 mv.top.x = xvmc_mb->PMV[0][vector][0];
114 mv.top.y = xvmc_mb->PMV[0][vector][1];
115 mv.top.field_select = PIPE_VIDEO_FRAME;
116 mv.top.weight = weight;
117
118 mv.bottom.x = xvmc_mb->PMV[0][vector][0];
119 mv.bottom.y = xvmc_mb->PMV[0][vector][1];
120 mv.bottom.weight = weight;
121 mv.bottom.field_select = PIPE_VIDEO_FRAME;
122 break;
123
124 case XVMC_PREDICTION_FIELD:
125 mv.top.x = xvmc_mb->PMV[0][vector][0];
126 mv.top.y = xvmc_mb->PMV[0][vector][1];
127 mv.top.field_select = (xvmc_mb->motion_vertical_field_select & field_select_mask) ?
128 PIPE_VIDEO_BOTTOM_FIELD : PIPE_VIDEO_TOP_FIELD;
129 mv.top.weight = weight;
130
131 mv.bottom.x = xvmc_mb->PMV[1][vector][0];
132 mv.bottom.y = xvmc_mb->PMV[1][vector][1];
133 mv.bottom.field_select = (xvmc_mb->motion_vertical_field_select & (field_select_mask << 2)) ?
134 PIPE_VIDEO_BOTTOM_FIELD : PIPE_VIDEO_TOP_FIELD;
135 mv.bottom.weight = weight;
136 break;
137
138 default: // TODO: Support DUALPRIME and 16x8
139 break;
140 }
141
142 return mv;
143 }
144
145 static inline void
146 UploadYcbcrBlocks(XvMCSurfacePrivate *surface,
147 const XvMCMacroBlock *xvmc_mb,
148 const XvMCBlockArray *xvmc_blocks)
149 {
150 enum pipe_mpeg12_dct_intra intra;
151 enum pipe_mpeg12_dct_type coding;
152
153 unsigned tb, x, y, luma_blocks;
154 short *blocks;
155
156 assert(surface);
157 assert(xvmc_mb);
158
159 if (!xvmc_mb->coded_block_pattern)
160 return;
161
162 intra = xvmc_mb->macroblock_type & XVMC_MB_TYPE_INTRA ?
163 PIPE_MPEG12_DCT_INTRA : PIPE_MPEG12_DCT_DELTA;
164
165 coding = xvmc_mb->dct_type == XVMC_DCT_TYPE_FIELD ?
166 PIPE_MPEG12_DCT_TYPE_FIELD : PIPE_MPEG12_DCT_TYPE_FRAME;
167
168 blocks = xvmc_blocks->blocks + xvmc_mb->index * BLOCK_SIZE_SAMPLES;
169
170 for (y = 0, luma_blocks = 0; y < 2; ++y) {
171 for (x = 0; x < 2; ++x, ++tb) {
172 if (xvmc_mb->coded_block_pattern & const_empty_block_mask_420[0][y][x]) {
173
174 struct pipe_ycbcr_block *stream = surface->ycbcr[0].stream;
175 stream->x = xvmc_mb->x * 2 + x;
176 stream->y = xvmc_mb->y * 2 + y;
177 stream->intra = intra;
178 stream->coding = coding;
179
180 surface->ycbcr[0].num_blocks_added++;
181 surface->ycbcr[0].stream++;
182
183 luma_blocks++;
184 }
185 }
186 }
187
188 if (luma_blocks > 0) {
189 memcpy(surface->ycbcr[0].buffer, blocks, BLOCK_SIZE_BYTES * luma_blocks);
190 surface->ycbcr[0].buffer += BLOCK_SIZE_SAMPLES * luma_blocks;
191 blocks += BLOCK_SIZE_SAMPLES * luma_blocks;
192 }
193
194 /* TODO: Implement 422, 444 */
195 //assert(ctx->base.chroma_format == PIPE_VIDEO_CHROMA_FORMAT_420);
196
197 for (tb = 1; tb < 3; ++tb) {
198 if (xvmc_mb->coded_block_pattern & const_empty_block_mask_420[tb][0][0]) {
199
200 struct pipe_ycbcr_block *stream = surface->ycbcr[tb].stream;
201 stream->x = xvmc_mb->x;
202 stream->y = xvmc_mb->y;
203 stream->intra = intra;
204 stream->coding = PIPE_MPEG12_DCT_TYPE_FRAME;
205
206 memcpy(surface->ycbcr[tb].buffer, blocks, BLOCK_SIZE_BYTES);
207
208 surface->ycbcr[tb].num_blocks_added++;
209 surface->ycbcr[tb].stream++;
210 surface->ycbcr[tb].buffer += BLOCK_SIZE_SAMPLES;
211 blocks += BLOCK_SIZE_SAMPLES;
212 }
213 }
214
215 }
216
217 static void
218 MacroBlocksToPipe(XvMCSurfacePrivate *surface,
219 unsigned int xvmc_picture_structure,
220 const XvMCMacroBlock *xvmc_mb,
221 const XvMCBlockArray *xvmc_blocks,
222 unsigned int num_macroblocks)
223 {
224 unsigned int i, j;
225
226 assert(xvmc_mb);
227 assert(xvmc_blocks);
228 assert(num_macroblocks);
229
230 for (i = 0; i < num_macroblocks; ++i) {
231 unsigned mv_pos = xvmc_mb->x + surface->mv_stride * xvmc_mb->y;
232 unsigned mv_weights[2];
233
234 if (xvmc_mb->macroblock_type & (XVMC_MB_TYPE_PATTERN | XVMC_MB_TYPE_INTRA))
235 UploadYcbcrBlocks(surface, xvmc_mb, xvmc_blocks);
236
237 MacroBlockTypeToPipeWeights(xvmc_mb, mv_weights);
238
239 for (j = 0; j < 2; ++j) {
240 if (!surface->ref[j].mv) continue;
241
242 surface->ref[j].mv[mv_pos] = MotionVectorToPipe
243 (
244 xvmc_mb, j,
245 j ? XVMC_SELECT_FIRST_BACKWARD : XVMC_SELECT_FIRST_FORWARD,
246 mv_weights[j]
247 );
248 }
249
250 ++xvmc_mb;
251 }
252 }
253
254 static void
255 unmap_and_flush_surface(XvMCSurfacePrivate *surface)
256 {
257 struct pipe_video_buffer *ref_frames[2];
258 XvMCContextPrivate *context_priv;
259 unsigned i, num_ycbcr_blocks[3];
260
261 assert(surface);
262
263 context_priv = surface->context->privData;
264
265 for ( i = 0; i < 2; ++i ) {
266 if (surface->ref[i].surface) {
267 XvMCSurfacePrivate *ref = surface->ref[i].surface->privData;
268
269 assert(ref);
270
271 unmap_and_flush_surface(ref);
272 surface->ref[i].surface = NULL;
273 ref_frames[i] = ref->video_buffer;
274 } else {
275 ref_frames[i] = NULL;
276 }
277 }
278
279 if (surface->mapped) {
280 surface->decode_buffer->end_frame(surface->decode_buffer);
281 for (i = 0; i < 3; ++i)
282 num_ycbcr_blocks[i] = surface->ycbcr[i].num_blocks_added;
283 context_priv->decoder->flush_buffer(surface->decode_buffer,
284 num_ycbcr_blocks,
285 ref_frames,
286 surface->video_buffer);
287 surface->mapped = 0;
288 }
289 }
290
291 PUBLIC
292 Status XvMCCreateSurface(Display *dpy, XvMCContext *context, XvMCSurface *surface)
293 {
294 static const uint8_t dummy_quant[64] = {
295 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10,
296 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10,
297 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10,
298 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10,
299 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10,
300 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10,
301 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10,
302 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10
303 };
304
305 XvMCContextPrivate *context_priv;
306 struct pipe_context *pipe;
307 XvMCSurfacePrivate *surface_priv;
308
309 XVMC_MSG(XVMC_TRACE, "[XvMC] Creating surface %p.\n", surface);
310
311 assert(dpy);
312
313 if (!context)
314 return XvMCBadContext;
315 if (!surface)
316 return XvMCBadSurface;
317
318 context_priv = context->privData;
319 pipe = context_priv->vctx->pipe;
320
321 surface_priv = CALLOC(1, sizeof(XvMCSurfacePrivate));
322 if (!surface_priv)
323 return BadAlloc;
324
325 surface_priv->decode_buffer = context_priv->decoder->create_buffer(context_priv->decoder);
326 surface_priv->decode_buffer->set_quant_matrix(surface_priv->decode_buffer, dummy_quant, dummy_quant);
327
328 surface_priv->mv_stride = surface_priv->decode_buffer->get_mv_stream_stride(surface_priv->decode_buffer);
329 surface_priv->video_buffer = pipe->create_video_buffer
330 (
331 pipe, PIPE_FORMAT_NV12, context_priv->decoder->chroma_format,
332 context_priv->decoder->width, context_priv->decoder->height
333 );
334
335 surface_priv->context = context;
336
337 surface->surface_id = XAllocID(dpy);
338 surface->context_id = context->context_id;
339 surface->surface_type_id = context->surface_type_id;
340 surface->width = context->width;
341 surface->height = context->height;
342 surface->privData = surface_priv;
343
344 SyncHandle();
345
346 XVMC_MSG(XVMC_TRACE, "[XvMC] Surface %p created.\n", surface);
347
348 return Success;
349 }
350
351 PUBLIC
352 Status XvMCRenderSurface(Display *dpy, XvMCContext *context, unsigned int picture_structure,
353 XvMCSurface *target_surface, XvMCSurface *past_surface, XvMCSurface *future_surface,
354 unsigned int flags, unsigned int num_macroblocks, unsigned int first_macroblock,
355 XvMCMacroBlockArray *macroblocks, XvMCBlockArray *blocks
356 )
357 {
358 struct pipe_video_decode_buffer *t_buffer;
359
360 XvMCSurfacePrivate *target_surface_priv;
361 XvMCSurfacePrivate *past_surface_priv;
362 XvMCSurfacePrivate *future_surface_priv;
363 XvMCMacroBlock *xvmc_mb;
364
365 unsigned i;
366
367 XVMC_MSG(XVMC_TRACE, "[XvMC] Rendering to surface %p, with past %p and future %p\n",
368 target_surface, past_surface, future_surface);
369
370 assert(dpy);
371
372 if (!context || !context->privData)
373 return XvMCBadContext;
374 if (!target_surface || !target_surface->privData)
375 return XvMCBadSurface;
376
377 if (picture_structure != XVMC_TOP_FIELD &&
378 picture_structure != XVMC_BOTTOM_FIELD &&
379 picture_structure != XVMC_FRAME_PICTURE)
380 return BadValue;
381 /* Bkwd pred equivalent to fwd (past && !future) */
382 if (future_surface && !past_surface)
383 return BadMatch;
384
385 assert(context->context_id == target_surface->context_id);
386 assert(!past_surface || context->context_id == past_surface->context_id);
387 assert(!future_surface || context->context_id == future_surface->context_id);
388
389 assert(macroblocks);
390 assert(blocks);
391
392 assert(macroblocks->context_id == context->context_id);
393 assert(blocks->context_id == context->context_id);
394
395 assert(flags == 0 || flags == XVMC_SECOND_FIELD);
396
397 target_surface_priv = target_surface->privData;
398 past_surface_priv = past_surface ? past_surface->privData : NULL;
399 future_surface_priv = future_surface ? future_surface->privData : NULL;
400
401 assert(target_surface_priv->context == context);
402 assert(!past_surface || past_surface_priv->context == context);
403 assert(!future_surface || future_surface_priv->context == context);
404
405 t_buffer = target_surface_priv->decode_buffer;
406
407 // enshure that all reference frames are flushed
408 // not really nessasary, but speeds ups rendering
409 if (past_surface)
410 unmap_and_flush_surface(past_surface->privData);
411
412 if (future_surface)
413 unmap_and_flush_surface(future_surface->privData);
414
415 xvmc_mb = macroblocks->macro_blocks + first_macroblock;
416
417 /* If the surface we're rendering hasn't changed the ref frames shouldn't change. */
418 if (target_surface_priv->mapped && (
419 target_surface_priv->ref[0].surface != past_surface ||
420 target_surface_priv->ref[1].surface != future_surface ||
421 (xvmc_mb->x == 0 && xvmc_mb->y == 0))) {
422
423 // If they change anyway we need to clear our surface
424 unmap_and_flush_surface(target_surface_priv);
425 }
426
427 if (!target_surface_priv->mapped) {
428 t_buffer->begin_frame(t_buffer);
429
430 for (i = 0; i < 3; ++i) {
431 target_surface_priv->ycbcr[i].num_blocks_added = 0;
432 target_surface_priv->ycbcr[i].stream = t_buffer->get_ycbcr_stream(t_buffer, i);
433 target_surface_priv->ycbcr[i].buffer = t_buffer->get_ycbcr_buffer(t_buffer, i);
434 }
435
436 for (i = 0; i < 2; ++i) {
437 target_surface_priv->ref[i].surface = i == 0 ? past_surface : future_surface;
438
439 if (target_surface_priv->ref[i].surface)
440 target_surface_priv->ref[i].mv = t_buffer->get_mv_stream(t_buffer, i);
441 else
442 target_surface_priv->ref[i].mv = NULL;
443 }
444
445 target_surface_priv->mapped = 1;
446 }
447
448 MacroBlocksToPipe(target_surface_priv, picture_structure, xvmc_mb, blocks, num_macroblocks);
449
450 XVMC_MSG(XVMC_TRACE, "[XvMC] Submitted surface %p for rendering.\n", target_surface);
451
452 return Success;
453 }
454
455 PUBLIC
456 Status XvMCFlushSurface(Display *dpy, XvMCSurface *surface)
457 {
458 assert(dpy);
459
460 if (!surface)
461 return XvMCBadSurface;
462
463 // don't call flush here, because this is usually
464 // called once for every slice instead of every frame
465
466 XVMC_MSG(XVMC_TRACE, "[XvMC] Flushing surface %p\n", surface);
467
468 return Success;
469 }
470
471 PUBLIC
472 Status XvMCSyncSurface(Display *dpy, XvMCSurface *surface)
473 {
474 assert(dpy);
475
476 if (!surface)
477 return XvMCBadSurface;
478
479 XVMC_MSG(XVMC_TRACE, "[XvMC] Syncing surface %p\n", surface);
480
481 return Success;
482 }
483
484 PUBLIC
485 Status XvMCPutSurface(Display *dpy, XvMCSurface *surface, Drawable drawable,
486 short srcx, short srcy, unsigned short srcw, unsigned short srch,
487 short destx, short desty, unsigned short destw, unsigned short desth,
488 int flags)
489 {
490 static int dump_window = -1;
491
492 struct pipe_context *pipe;
493 struct vl_compositor *compositor;
494
495 XvMCSurfacePrivate *surface_priv;
496 XvMCContextPrivate *context_priv;
497 XvMCSubpicturePrivate *subpicture_priv;
498 XvMCContext *context;
499 struct pipe_video_rect src_rect = {srcx, srcy, srcw, srch};
500 struct pipe_video_rect dst_rect = {destx, desty, destw, desth};
501
502 XVMC_MSG(XVMC_TRACE, "[XvMC] Displaying surface %p.\n", surface);
503
504 assert(dpy);
505
506 if (!surface || !surface->privData)
507 return XvMCBadSurface;
508
509 surface_priv = surface->privData;
510 context = surface_priv->context;
511 context_priv = context->privData;
512
513 assert(flags == XVMC_TOP_FIELD || flags == XVMC_BOTTOM_FIELD || flags == XVMC_FRAME_PICTURE);
514 assert(srcx + srcw - 1 < surface->width);
515 assert(srcy + srch - 1 < surface->height);
516
517 subpicture_priv = surface_priv->subpicture ? surface_priv->subpicture->privData : NULL;
518 pipe = context_priv->vctx->pipe;
519 compositor = &context_priv->compositor;
520
521 if (!context_priv->drawable_surface ||
522 context_priv->dst_rect.x != dst_rect.x || context_priv->dst_rect.y != dst_rect.y ||
523 context_priv->dst_rect.w != dst_rect.w || context_priv->dst_rect.h != dst_rect.h) {
524
525 context_priv->drawable_surface = vl_drawable_surface_get(context_priv->vctx, drawable);
526 context_priv->dst_rect = dst_rect;
527 vl_compositor_reset_dirty_area(compositor);
528 }
529
530 if (!context_priv->drawable_surface)
531 return BadDrawable;
532
533 /*
534 * Some apps (mplayer) hit these asserts because they call
535 * this function after the window has been resized by the WM
536 * but before they've handled the corresponding XEvent and
537 * know about the new dimensions. The output should be clipped
538 * until the app updates destw and desth.
539 */
540 /*
541 assert(destx + destw - 1 < drawable_surface->width);
542 assert(desty + desth - 1 < drawable_surface->height);
543 */
544
545 unmap_and_flush_surface(surface_priv);
546
547 vl_compositor_clear_layers(compositor);
548 vl_compositor_set_buffer_layer(compositor, 0, surface_priv->video_buffer, &src_rect, NULL);
549
550 if (subpicture_priv) {
551 XVMC_MSG(XVMC_TRACE, "[XvMC] Surface %p has subpicture %p.\n", surface, surface_priv->subpicture);
552
553 assert(subpicture_priv->surface == surface);
554
555 if (subpicture_priv->palette)
556 vl_compositor_set_palette_layer(compositor, 1, subpicture_priv->sampler, subpicture_priv->palette,
557 &subpicture_priv->src_rect, &subpicture_priv->dst_rect);
558 else
559 vl_compositor_set_rgba_layer(compositor, 1, subpicture_priv->sampler,
560 &subpicture_priv->src_rect, &subpicture_priv->dst_rect);
561
562 surface_priv->subpicture = NULL;
563 subpicture_priv->surface = NULL;
564 }
565
566 // Workaround for r600g, there seems to be a bug in the fence refcounting code
567 pipe->screen->fence_reference(pipe->screen, &surface_priv->fence, NULL);
568
569 vl_compositor_render(compositor, PictureToPipe(flags), context_priv->drawable_surface, &dst_rect, &surface_priv->fence);
570
571 XVMC_MSG(XVMC_TRACE, "[XvMC] Submitted surface %p for display. Pushing to front buffer.\n", surface);
572
573 pipe->screen->flush_frontbuffer
574 (
575 pipe->screen,
576 context_priv->drawable_surface->texture,
577 0, 0,
578 vl_contextprivate_get(context_priv->vctx, context_priv->drawable_surface)
579 );
580
581 if(dump_window == -1) {
582 dump_window = debug_get_num_option("XVMC_DUMP", 0);
583 }
584
585 if(dump_window) {
586 static unsigned int framenum = 0;
587 char cmd[256];
588
589 sprintf(cmd, "xwd -id %d -out xvmc_frame_%08d.xwd", (int)drawable, ++framenum);
590 if (system(cmd) != 0)
591 XVMC_MSG(XVMC_ERR, "[XvMC] Dumping surface %p failed.\n", surface);
592 }
593
594 XVMC_MSG(XVMC_TRACE, "[XvMC] Pushed surface %p to front buffer.\n", surface);
595
596 return Success;
597 }
598
599 PUBLIC
600 Status XvMCGetSurfaceStatus(Display *dpy, XvMCSurface *surface, int *status)
601 {
602 struct pipe_context *pipe;
603 XvMCSurfacePrivate *surface_priv;
604 XvMCContextPrivate *context_priv;
605
606 assert(dpy);
607
608 if (!surface)
609 return XvMCBadSurface;
610
611 assert(status);
612
613 surface_priv = surface->privData;
614 context_priv = surface_priv->context->privData;
615 pipe = context_priv->vctx->pipe;
616
617 *status = 0;
618
619 if (surface_priv->fence)
620 if (!pipe->screen->fence_signalled(pipe->screen, surface_priv->fence))
621 *status |= XVMC_RENDERING;
622
623 return Success;
624 }
625
626 PUBLIC
627 Status XvMCDestroySurface(Display *dpy, XvMCSurface *surface)
628 {
629 XvMCSurfacePrivate *surface_priv;
630
631 XVMC_MSG(XVMC_TRACE, "[XvMC] Destroying surface %p.\n", surface);
632
633 assert(dpy);
634
635 if (!surface || !surface->privData)
636 return XvMCBadSurface;
637
638 surface_priv = surface->privData;
639 surface_priv->decode_buffer->destroy(surface_priv->decode_buffer);
640 surface_priv->video_buffer->destroy(surface_priv->video_buffer);
641 FREE(surface_priv);
642 surface->privData = NULL;
643
644 XVMC_MSG(XVMC_TRACE, "[XvMC] Surface %p destroyed.\n", surface);
645
646 return Success;
647 }
648
649 PUBLIC
650 Status XvMCHideSurface(Display *dpy, XvMCSurface *surface)
651 {
652 assert(dpy);
653
654 if (!surface || !surface->privData)
655 return XvMCBadSurface;
656
657 /* No op, only for overlaid rendering */
658
659 return Success;
660 }