1848b8605Smrg/************************************************************************** 2848b8605Smrg * 3848b8605Smrg * Copyright 2009 Younes Manton. 4848b8605Smrg * All Rights Reserved. 5848b8605Smrg * 6848b8605Smrg * Permission is hereby granted, free of charge, to any person obtaining a 7848b8605Smrg * copy of this software and associated documentation files (the 8848b8605Smrg * "Software"), to deal in the Software without restriction, including 9848b8605Smrg * without limitation the rights to use, copy, modify, merge, publish, 10848b8605Smrg * distribute, sub license, and/or sell copies of the Software, and to 11848b8605Smrg * permit persons to whom the Software is furnished to do so, subject to 12848b8605Smrg * the following conditions: 13848b8605Smrg * 14848b8605Smrg * The above copyright notice and this permission notice (including the 15848b8605Smrg * next paragraph) shall be included in all copies or substantial portions 16848b8605Smrg * of the Software. 17848b8605Smrg * 18848b8605Smrg * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 19848b8605Smrg * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 20848b8605Smrg * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. 21848b8605Smrg * IN NO EVENT SHALL VMWARE AND/OR ITS SUPPLIERS BE LIABLE FOR 22848b8605Smrg * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, 23848b8605Smrg * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE 24848b8605Smrg * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 25848b8605Smrg * 26848b8605Smrg **************************************************************************/ 27848b8605Smrg 28848b8605Smrg#include <assert.h> 29848b8605Smrg#include <stdio.h> 30848b8605Smrg 31848b8605Smrg#include <X11/Xlibint.h> 32848b8605Smrg 33848b8605Smrg#include "pipe/p_video_codec.h" 34848b8605Smrg#include "pipe/p_video_state.h" 35848b8605Smrg#include "pipe/p_state.h" 36848b8605Smrg 37b8e80941Smrg#include "util/macros.h" 38848b8605Smrg#include "util/u_inlines.h" 39848b8605Smrg#include "util/u_memory.h" 40848b8605Smrg#include "util/u_math.h" 41848b8605Smrg#include "vl/vl_winsys.h" 42848b8605Smrg 43848b8605Smrg#include "xvmc_private.h" 44848b8605Smrg 45848b8605Smrgstatic void 46848b8605SmrgMacroBlocksToPipe(XvMCContextPrivate *context, 47848b8605Smrg XvMCSurfacePrivate *surface, 48848b8605Smrg unsigned int xvmc_picture_structure, 49848b8605Smrg const XvMCMacroBlock *xvmc_mb, 50848b8605Smrg const XvMCBlockArray *xvmc_blocks, 51848b8605Smrg struct pipe_mpeg12_macroblock *mb, 52848b8605Smrg unsigned int num_macroblocks) 53848b8605Smrg{ 54848b8605Smrg unsigned int i, j, k; 55848b8605Smrg 56848b8605Smrg assert(xvmc_mb); 57848b8605Smrg assert(xvmc_blocks); 58848b8605Smrg assert(num_macroblocks); 59848b8605Smrg 60848b8605Smrg for (; num_macroblocks > 0; --num_macroblocks) { 61848b8605Smrg mb->base.codec = PIPE_VIDEO_FORMAT_MPEG12; 62848b8605Smrg mb->x = xvmc_mb->x; 63848b8605Smrg mb->y = xvmc_mb->y; 64848b8605Smrg mb->macroblock_type = xvmc_mb->macroblock_type; 65848b8605Smrg 66848b8605Smrg switch (xvmc_picture_structure) { 67848b8605Smrg case XVMC_FRAME_PICTURE: 68848b8605Smrg mb->macroblock_modes.bits.frame_motion_type = xvmc_mb->motion_type; 69848b8605Smrg mb->macroblock_modes.bits.field_motion_type = 0; 70848b8605Smrg break; 71848b8605Smrg 72848b8605Smrg case XVMC_TOP_FIELD: 73848b8605Smrg case XVMC_BOTTOM_FIELD: 74848b8605Smrg mb->macroblock_modes.bits.frame_motion_type = 0; 75848b8605Smrg mb->macroblock_modes.bits.field_motion_type = xvmc_mb->motion_type; 76848b8605Smrg break; 77848b8605Smrg 78848b8605Smrg default: 79848b8605Smrg assert(0); 80848b8605Smrg } 81848b8605Smrg 82848b8605Smrg mb->macroblock_modes.bits.dct_type = xvmc_mb->dct_type; 83848b8605Smrg mb->motion_vertical_field_select = xvmc_mb->motion_vertical_field_select; 84848b8605Smrg 85848b8605Smrg for (i = 0; i < 2; ++i) 86848b8605Smrg for (j = 0; j < 2; ++j) 87848b8605Smrg for (k = 0; k < 2; ++k) 88848b8605Smrg mb->PMV[i][j][k] = xvmc_mb->PMV[i][j][k]; 89848b8605Smrg 90848b8605Smrg mb->coded_block_pattern = xvmc_mb->coded_block_pattern; 91848b8605Smrg mb->blocks = xvmc_blocks->blocks + xvmc_mb->index * BLOCK_SIZE_SAMPLES; 92848b8605Smrg mb->num_skipped_macroblocks = 0; 93848b8605Smrg 94848b8605Smrg ++xvmc_mb; 95848b8605Smrg ++mb; 96848b8605Smrg } 97848b8605Smrg} 98848b8605Smrg 99848b8605Smrgstatic void 100848b8605SmrgGetPictureDescription(XvMCSurfacePrivate *surface, struct pipe_mpeg12_picture_desc *desc) 101848b8605Smrg{ 102848b8605Smrg unsigned i, num_refs = 0; 103848b8605Smrg 104848b8605Smrg assert(surface && desc); 105848b8605Smrg 106848b8605Smrg memset(desc, 0, sizeof(*desc)); 107848b8605Smrg desc->base.profile = PIPE_VIDEO_PROFILE_MPEG1; 108848b8605Smrg desc->picture_structure = surface->picture_structure; 109848b8605Smrg for (i = 0; i < 2; ++i) { 110848b8605Smrg if (surface->ref[i]) { 111848b8605Smrg XvMCSurfacePrivate *ref = surface->ref[i]->privData; 112848b8605Smrg 113848b8605Smrg if (ref) 114848b8605Smrg desc->ref[num_refs++] = ref->video_buffer; 115848b8605Smrg } 116848b8605Smrg } 117848b8605Smrg} 118848b8605Smrg 119848b8605Smrgstatic void 120848b8605SmrgRecursiveEndFrame(XvMCSurfacePrivate *surface) 121848b8605Smrg{ 122848b8605Smrg XvMCContextPrivate *context_priv; 123848b8605Smrg unsigned i; 124848b8605Smrg 125848b8605Smrg assert(surface); 126848b8605Smrg 127848b8605Smrg context_priv = surface->context->privData; 128848b8605Smrg 129848b8605Smrg for ( i = 0; i < 2; ++i ) { 130848b8605Smrg if (surface->ref[i]) { 131848b8605Smrg XvMCSurface *ref = surface->ref[i]; 132848b8605Smrg 133848b8605Smrg assert(ref); 134848b8605Smrg 135848b8605Smrg surface->ref[i] = NULL; 136848b8605Smrg RecursiveEndFrame(ref->privData); 137848b8605Smrg surface->ref[i] = ref; 138848b8605Smrg } 139848b8605Smrg } 140848b8605Smrg 141848b8605Smrg if (surface->picture_structure) { 142848b8605Smrg struct pipe_mpeg12_picture_desc desc; 143848b8605Smrg GetPictureDescription(surface, &desc); 144848b8605Smrg surface->picture_structure = 0; 145848b8605Smrg 146848b8605Smrg for (i = 0; i < 2; ++i) 147848b8605Smrg surface->ref[i] = NULL; 148848b8605Smrg 149848b8605Smrg context_priv->decoder->end_frame(context_priv->decoder, surface->video_buffer, &desc.base); 150848b8605Smrg } 151848b8605Smrg} 152848b8605Smrg 153848b8605SmrgPUBLIC 154848b8605SmrgStatus XvMCCreateSurface(Display *dpy, XvMCContext *context, XvMCSurface *surface) 155848b8605Smrg{ 156848b8605Smrg XvMCContextPrivate *context_priv; 157848b8605Smrg struct pipe_context *pipe; 158848b8605Smrg XvMCSurfacePrivate *surface_priv; 159848b8605Smrg struct pipe_video_buffer tmpl; 160848b8605Smrg 161848b8605Smrg XVMC_MSG(XVMC_TRACE, "[XvMC] Creating surface %p.\n", surface); 162848b8605Smrg 163848b8605Smrg assert(dpy); 164848b8605Smrg 165848b8605Smrg if (!context) 166848b8605Smrg return XvMCBadContext; 167848b8605Smrg if (!surface) 168848b8605Smrg return XvMCBadSurface; 169848b8605Smrg 170848b8605Smrg context_priv = context->privData; 171848b8605Smrg pipe = context_priv->pipe; 172848b8605Smrg 173848b8605Smrg surface_priv = CALLOC(1, sizeof(XvMCSurfacePrivate)); 174848b8605Smrg if (!surface_priv) 175848b8605Smrg return BadAlloc; 176848b8605Smrg 177848b8605Smrg memset(&tmpl, 0, sizeof(tmpl)); 178848b8605Smrg tmpl.buffer_format = pipe->screen->get_video_param 179848b8605Smrg ( 180848b8605Smrg pipe->screen, 181848b8605Smrg context_priv->decoder->profile, 182848b8605Smrg context_priv->decoder->entrypoint, 183848b8605Smrg PIPE_VIDEO_CAP_PREFERED_FORMAT 184848b8605Smrg ); 185848b8605Smrg tmpl.chroma_format = context_priv->decoder->chroma_format; 186848b8605Smrg tmpl.width = context_priv->decoder->width; 187848b8605Smrg tmpl.height = context_priv->decoder->height; 188848b8605Smrg tmpl.interlaced = pipe->screen->get_video_param 189848b8605Smrg ( 190848b8605Smrg pipe->screen, 191848b8605Smrg context_priv->decoder->profile, 192848b8605Smrg context_priv->decoder->entrypoint, 193848b8605Smrg PIPE_VIDEO_CAP_PREFERS_INTERLACED 194848b8605Smrg ); 195848b8605Smrg 196848b8605Smrg surface_priv->video_buffer = pipe->create_video_buffer(pipe, &tmpl); 197848b8605Smrg if (!surface_priv->video_buffer) { 198848b8605Smrg FREE(surface_priv); 199848b8605Smrg return BadAlloc; 200848b8605Smrg } 201848b8605Smrg surface_priv->context = context; 202848b8605Smrg 203848b8605Smrg surface->surface_id = XAllocID(dpy); 204848b8605Smrg surface->context_id = context->context_id; 205848b8605Smrg surface->surface_type_id = context->surface_type_id; 206848b8605Smrg surface->width = context->width; 207848b8605Smrg surface->height = context->height; 208848b8605Smrg surface->privData = surface_priv; 209848b8605Smrg 210848b8605Smrg SyncHandle(); 211848b8605Smrg 212848b8605Smrg XVMC_MSG(XVMC_TRACE, "[XvMC] Surface %p created.\n", surface); 213848b8605Smrg 214848b8605Smrg return Success; 215848b8605Smrg} 216848b8605Smrg 217848b8605SmrgPUBLIC 218848b8605SmrgStatus XvMCRenderSurface(Display *dpy, XvMCContext *context, unsigned int picture_structure, 219848b8605Smrg XvMCSurface *target_surface, XvMCSurface *past_surface, XvMCSurface *future_surface, 220848b8605Smrg unsigned int flags, unsigned int num_macroblocks, unsigned int first_macroblock, 221848b8605Smrg XvMCMacroBlockArray *macroblocks, XvMCBlockArray *blocks 222848b8605Smrg) 223848b8605Smrg{ 224848b8605Smrg struct pipe_mpeg12_macroblock mb[num_macroblocks]; 225848b8605Smrg struct pipe_video_codec *decoder; 226848b8605Smrg struct pipe_mpeg12_picture_desc desc; 227848b8605Smrg 228848b8605Smrg XvMCContextPrivate *context_priv; 229848b8605Smrg XvMCSurfacePrivate *target_surface_priv; 230b8e80941Smrg MAYBE_UNUSED XvMCSurfacePrivate *past_surface_priv; 231b8e80941Smrg MAYBE_UNUSED XvMCSurfacePrivate *future_surface_priv; 232848b8605Smrg XvMCMacroBlock *xvmc_mb; 233848b8605Smrg 234848b8605Smrg XVMC_MSG(XVMC_TRACE, "[XvMC] Rendering to surface %p, with past %p and future %p\n", 235848b8605Smrg target_surface, past_surface, future_surface); 236848b8605Smrg 237848b8605Smrg assert(dpy); 238848b8605Smrg 239848b8605Smrg if (!context || !context->privData) 240848b8605Smrg return XvMCBadContext; 241848b8605Smrg if (!target_surface || !target_surface->privData) 242848b8605Smrg return XvMCBadSurface; 243848b8605Smrg 244848b8605Smrg if (picture_structure != XVMC_TOP_FIELD && 245848b8605Smrg picture_structure != XVMC_BOTTOM_FIELD && 246848b8605Smrg picture_structure != XVMC_FRAME_PICTURE) 247848b8605Smrg return BadValue; 248848b8605Smrg /* Bkwd pred equivalent to fwd (past && !future) */ 249848b8605Smrg if (future_surface && !past_surface) 250848b8605Smrg return BadMatch; 251848b8605Smrg 252848b8605Smrg assert(context->context_id == target_surface->context_id); 253848b8605Smrg assert(!past_surface || context->context_id == past_surface->context_id); 254848b8605Smrg assert(!future_surface || context->context_id == future_surface->context_id); 255848b8605Smrg 256848b8605Smrg assert(macroblocks); 257848b8605Smrg assert(blocks); 258848b8605Smrg 259848b8605Smrg assert(macroblocks->context_id == context->context_id); 260848b8605Smrg assert(blocks->context_id == context->context_id); 261848b8605Smrg 262848b8605Smrg assert(flags == 0 || flags == XVMC_SECOND_FIELD); 263848b8605Smrg 264848b8605Smrg context_priv = context->privData; 265848b8605Smrg decoder = context_priv->decoder; 266848b8605Smrg 267848b8605Smrg target_surface_priv = target_surface->privData; 268848b8605Smrg past_surface_priv = past_surface ? past_surface->privData : NULL; 269848b8605Smrg future_surface_priv = future_surface ? future_surface->privData : NULL; 270848b8605Smrg 271848b8605Smrg assert(target_surface_priv->context == context); 272848b8605Smrg assert(!past_surface || past_surface_priv->context == context); 273848b8605Smrg assert(!future_surface || future_surface_priv->context == context); 274848b8605Smrg 275848b8605Smrg // call end frame on all referenced frames 276848b8605Smrg if (past_surface) 277848b8605Smrg RecursiveEndFrame(past_surface->privData); 278848b8605Smrg 279848b8605Smrg if (future_surface) 280848b8605Smrg RecursiveEndFrame(future_surface->privData); 281848b8605Smrg 282848b8605Smrg xvmc_mb = macroblocks->macro_blocks + first_macroblock; 283848b8605Smrg 284848b8605Smrg /* If the surface we're rendering hasn't changed the ref frames shouldn't change. */ 285848b8605Smrg if (target_surface_priv->picture_structure > 0 && ( 286848b8605Smrg target_surface_priv->picture_structure != picture_structure || 287848b8605Smrg target_surface_priv->ref[0] != past_surface || 288848b8605Smrg target_surface_priv->ref[1] != future_surface || 289848b8605Smrg (xvmc_mb->x == 0 && xvmc_mb->y == 0))) { 290848b8605Smrg 291848b8605Smrg // If they change anyway we must assume that the current frame is ended 292848b8605Smrg RecursiveEndFrame(target_surface_priv); 293848b8605Smrg } 294848b8605Smrg 295848b8605Smrg target_surface_priv->ref[0] = past_surface; 296848b8605Smrg target_surface_priv->ref[1] = future_surface; 297848b8605Smrg 298848b8605Smrg if (target_surface_priv->picture_structure) 299848b8605Smrg GetPictureDescription(target_surface_priv, &desc); 300848b8605Smrg else { 301848b8605Smrg target_surface_priv->picture_structure = picture_structure; 302848b8605Smrg GetPictureDescription(target_surface_priv, &desc); 303848b8605Smrg decoder->begin_frame(decoder, target_surface_priv->video_buffer, &desc.base); 304848b8605Smrg } 305848b8605Smrg 306848b8605Smrg MacroBlocksToPipe(context_priv, target_surface_priv, picture_structure, 307848b8605Smrg xvmc_mb, blocks, mb, num_macroblocks); 308848b8605Smrg 309848b8605Smrg context_priv->decoder->decode_macroblock(context_priv->decoder, 310848b8605Smrg target_surface_priv->video_buffer, 311848b8605Smrg &desc.base, 312848b8605Smrg &mb[0].base, num_macroblocks); 313848b8605Smrg 314848b8605Smrg XVMC_MSG(XVMC_TRACE, "[XvMC] Submitted surface %p for rendering.\n", target_surface); 315848b8605Smrg 316848b8605Smrg return Success; 317848b8605Smrg} 318848b8605Smrg 319848b8605SmrgPUBLIC 320848b8605SmrgStatus XvMCFlushSurface(Display *dpy, XvMCSurface *surface) 321848b8605Smrg{ 322848b8605Smrg assert(dpy); 323848b8605Smrg 324848b8605Smrg if (!surface) 325848b8605Smrg return XvMCBadSurface; 326848b8605Smrg 327848b8605Smrg // don't call flush here, because this is usually 328848b8605Smrg // called once for every slice instead of every frame 329848b8605Smrg 330848b8605Smrg XVMC_MSG(XVMC_TRACE, "[XvMC] Flushing surface %p\n", surface); 331848b8605Smrg 332848b8605Smrg return Success; 333848b8605Smrg} 334848b8605Smrg 335848b8605SmrgPUBLIC 336848b8605SmrgStatus XvMCSyncSurface(Display *dpy, XvMCSurface *surface) 337848b8605Smrg{ 338848b8605Smrg assert(dpy); 339848b8605Smrg 340848b8605Smrg if (!surface) 341848b8605Smrg return XvMCBadSurface; 342848b8605Smrg 343848b8605Smrg XVMC_MSG(XVMC_TRACE, "[XvMC] Syncing surface %p\n", surface); 344848b8605Smrg 345848b8605Smrg return Success; 346848b8605Smrg} 347848b8605Smrg 348848b8605SmrgPUBLIC 349848b8605SmrgStatus XvMCPutSurface(Display *dpy, XvMCSurface *surface, Drawable drawable, 350848b8605Smrg short srcx, short srcy, unsigned short srcw, unsigned short srch, 351848b8605Smrg short destx, short desty, unsigned short destw, unsigned short desth, 352848b8605Smrg int flags) 353848b8605Smrg{ 354848b8605Smrg static int dump_window = -1; 355848b8605Smrg 356848b8605Smrg struct pipe_context *pipe; 357848b8605Smrg struct vl_compositor *compositor; 358848b8605Smrg struct vl_compositor_state *cstate; 359b8e80941Smrg struct vl_screen *vscreen; 360848b8605Smrg 361848b8605Smrg XvMCSurfacePrivate *surface_priv; 362848b8605Smrg XvMCContextPrivate *context_priv; 363848b8605Smrg XvMCSubpicturePrivate *subpicture_priv; 364848b8605Smrg XvMCContext *context; 365848b8605Smrg struct u_rect src_rect = {srcx, srcx + srcw, srcy, srcy + srch}; 366848b8605Smrg struct u_rect dst_rect = {destx, destx + destw, desty, desty + desth}; 367848b8605Smrg 368848b8605Smrg struct pipe_resource *tex; 369848b8605Smrg struct pipe_surface surf_templ, *surf; 370848b8605Smrg struct u_rect *dirty_area; 371848b8605Smrg 372848b8605Smrg XVMC_MSG(XVMC_TRACE, "[XvMC] Displaying surface %p.\n", surface); 373848b8605Smrg 374848b8605Smrg assert(dpy); 375848b8605Smrg 376848b8605Smrg if (!surface || !surface->privData) 377848b8605Smrg return XvMCBadSurface; 378848b8605Smrg 379848b8605Smrg surface_priv = surface->privData; 380848b8605Smrg context = surface_priv->context; 381848b8605Smrg context_priv = context->privData; 382848b8605Smrg 383848b8605Smrg assert(flags == XVMC_TOP_FIELD || flags == XVMC_BOTTOM_FIELD || flags == XVMC_FRAME_PICTURE); 384848b8605Smrg assert(srcx + srcw - 1 < surface->width); 385848b8605Smrg assert(srcy + srch - 1 < surface->height); 386848b8605Smrg 387848b8605Smrg subpicture_priv = surface_priv->subpicture ? surface_priv->subpicture->privData : NULL; 388848b8605Smrg pipe = context_priv->pipe; 389848b8605Smrg compositor = &context_priv->compositor; 390848b8605Smrg cstate = &context_priv->cstate; 391b8e80941Smrg vscreen = context_priv->vscreen; 392848b8605Smrg 393b8e80941Smrg tex = vscreen->texture_from_drawable(vscreen, (void *)drawable); 394b8e80941Smrg dirty_area = vscreen->get_dirty_area(vscreen); 395848b8605Smrg 396848b8605Smrg memset(&surf_templ, 0, sizeof(surf_templ)); 397848b8605Smrg surf_templ.format = tex->format; 398848b8605Smrg surf = pipe->create_surface(pipe, tex, &surf_templ); 399848b8605Smrg 400848b8605Smrg if (!surf) 401848b8605Smrg return BadDrawable; 402848b8605Smrg 403848b8605Smrg /* 404848b8605Smrg * Some apps (mplayer) hit these asserts because they call 405848b8605Smrg * this function after the window has been resized by the WM 406848b8605Smrg * but before they've handled the corresponding XEvent and 407848b8605Smrg * know about the new dimensions. The output should be clipped 408848b8605Smrg * until the app updates destw and desth. 409848b8605Smrg */ 410848b8605Smrg /* 411848b8605Smrg assert(destx + destw - 1 < drawable_surface->width); 412848b8605Smrg assert(desty + desth - 1 < drawable_surface->height); 413848b8605Smrg */ 414848b8605Smrg 415848b8605Smrg RecursiveEndFrame(surface_priv); 416848b8605Smrg 417848b8605Smrg context_priv->decoder->flush(context_priv->decoder); 418848b8605Smrg 419848b8605Smrg vl_compositor_clear_layers(cstate); 420848b8605Smrg vl_compositor_set_buffer_layer(cstate, compositor, 0, surface_priv->video_buffer, 421848b8605Smrg &src_rect, NULL, VL_COMPOSITOR_WEAVE); 422848b8605Smrg 423848b8605Smrg if (subpicture_priv) { 424848b8605Smrg XVMC_MSG(XVMC_TRACE, "[XvMC] Surface %p has subpicture %p.\n", surface, surface_priv->subpicture); 425848b8605Smrg 426848b8605Smrg assert(subpicture_priv->surface == surface); 427848b8605Smrg 428848b8605Smrg if (subpicture_priv->palette) 429848b8605Smrg vl_compositor_set_palette_layer(cstate, compositor, 1, subpicture_priv->sampler, subpicture_priv->palette, 430848b8605Smrg &subpicture_priv->src_rect, &subpicture_priv->dst_rect, true); 431848b8605Smrg else 432848b8605Smrg vl_compositor_set_rgba_layer(cstate, compositor, 1, subpicture_priv->sampler, 433848b8605Smrg &subpicture_priv->src_rect, &subpicture_priv->dst_rect, NULL); 434848b8605Smrg 435848b8605Smrg surface_priv->subpicture = NULL; 436848b8605Smrg subpicture_priv->surface = NULL; 437848b8605Smrg } 438848b8605Smrg 439848b8605Smrg // Workaround for r600g, there seems to be a bug in the fence refcounting code 440848b8605Smrg pipe->screen->fence_reference(pipe->screen, &surface_priv->fence, NULL); 441848b8605Smrg 442848b8605Smrg vl_compositor_set_layer_dst_area(cstate, 0, &dst_rect); 443848b8605Smrg vl_compositor_set_layer_dst_area(cstate, 1, &dst_rect); 444848b8605Smrg vl_compositor_render(cstate, compositor, surf, dirty_area, true); 445848b8605Smrg 446848b8605Smrg pipe->flush(pipe, &surface_priv->fence, 0); 447848b8605Smrg 448848b8605Smrg XVMC_MSG(XVMC_TRACE, "[XvMC] Submitted surface %p for display. Pushing to front buffer.\n", surface); 449848b8605Smrg 450b8e80941Smrg pipe->screen->flush_frontbuffer(pipe->screen, tex, 0, 0, 451b8e80941Smrg vscreen->get_private(vscreen), NULL); 452848b8605Smrg 453848b8605Smrg if(dump_window == -1) { 454848b8605Smrg dump_window = debug_get_num_option("XVMC_DUMP", 0); 455848b8605Smrg } 456848b8605Smrg 457848b8605Smrg if(dump_window) { 458848b8605Smrg static unsigned int framenum = 0; 459848b8605Smrg char cmd[256]; 460848b8605Smrg 461848b8605Smrg sprintf(cmd, "xwd -id %d -out xvmc_frame_%08d.xwd", (int)drawable, ++framenum); 462848b8605Smrg if (system(cmd) != 0) 463848b8605Smrg XVMC_MSG(XVMC_ERR, "[XvMC] Dumping surface %p failed.\n", surface); 464848b8605Smrg } 465848b8605Smrg 466848b8605Smrg XVMC_MSG(XVMC_TRACE, "[XvMC] Pushed surface %p to front buffer.\n", surface); 467848b8605Smrg 468848b8605Smrg return Success; 469848b8605Smrg} 470848b8605Smrg 471848b8605SmrgPUBLIC 472848b8605SmrgStatus XvMCGetSurfaceStatus(Display *dpy, XvMCSurface *surface, int *status) 473848b8605Smrg{ 474848b8605Smrg struct pipe_context *pipe; 475848b8605Smrg XvMCSurfacePrivate *surface_priv; 476848b8605Smrg XvMCContextPrivate *context_priv; 477848b8605Smrg 478848b8605Smrg assert(dpy); 479848b8605Smrg 480848b8605Smrg if (!surface) 481848b8605Smrg return XvMCBadSurface; 482848b8605Smrg 483848b8605Smrg assert(status); 484848b8605Smrg 485848b8605Smrg surface_priv = surface->privData; 486848b8605Smrg context_priv = surface_priv->context->privData; 487848b8605Smrg pipe = context_priv->pipe; 488848b8605Smrg 489848b8605Smrg *status = 0; 490848b8605Smrg 491848b8605Smrg if (surface_priv->fence) 492b8e80941Smrg if (!pipe->screen->fence_finish(pipe->screen, NULL, surface_priv->fence, 0)) 493848b8605Smrg *status |= XVMC_RENDERING; 494848b8605Smrg 495848b8605Smrg return Success; 496848b8605Smrg} 497848b8605Smrg 498848b8605SmrgPUBLIC 499848b8605SmrgStatus XvMCDestroySurface(Display *dpy, XvMCSurface *surface) 500848b8605Smrg{ 501848b8605Smrg XvMCSurfacePrivate *surface_priv; 502848b8605Smrg XvMCContextPrivate *context_priv; 503848b8605Smrg 504848b8605Smrg XVMC_MSG(XVMC_TRACE, "[XvMC] Destroying surface %p.\n", surface); 505848b8605Smrg 506848b8605Smrg assert(dpy); 507848b8605Smrg 508848b8605Smrg if (!surface || !surface->privData) 509848b8605Smrg return XvMCBadSurface; 510848b8605Smrg 511848b8605Smrg surface_priv = surface->privData; 512848b8605Smrg context_priv = surface_priv->context->privData; 513848b8605Smrg 514848b8605Smrg if (surface_priv->picture_structure) { 515848b8605Smrg struct pipe_mpeg12_picture_desc desc; 516848b8605Smrg GetPictureDescription(surface_priv, &desc); 517848b8605Smrg context_priv->decoder->end_frame(context_priv->decoder, surface_priv->video_buffer, &desc.base); 518848b8605Smrg } 519848b8605Smrg surface_priv->video_buffer->destroy(surface_priv->video_buffer); 520848b8605Smrg FREE(surface_priv); 521848b8605Smrg surface->privData = NULL; 522848b8605Smrg 523848b8605Smrg XVMC_MSG(XVMC_TRACE, "[XvMC] Surface %p destroyed.\n", surface); 524848b8605Smrg 525848b8605Smrg return Success; 526848b8605Smrg} 527848b8605Smrg 528848b8605SmrgPUBLIC 529848b8605SmrgStatus XvMCHideSurface(Display *dpy, XvMCSurface *surface) 530848b8605Smrg{ 531848b8605Smrg assert(dpy); 532848b8605Smrg 533848b8605Smrg if (!surface || !surface->privData) 534848b8605Smrg return XvMCBadSurface; 535848b8605Smrg 536848b8605Smrg /* No op, only for overlaid rendering */ 537848b8605Smrg 538848b8605Smrg return Success; 539848b8605Smrg} 540