surface.c revision d645dc65b6c5e7d46538e98208a703f0f7a5d20b
1dff7e11c2000d6745261de046d76b1500a05ece9reed@google.com/************************************************************************** 2dff7e11c2000d6745261de046d76b1500a05ece9reed@google.com * 3dff7e11c2000d6745261de046d76b1500a05ece9reed@google.com * Copyright 2009 Younes Manton. 4dff7e11c2000d6745261de046d76b1500a05ece9reed@google.com * All Rights Reserved. 5dff7e11c2000d6745261de046d76b1500a05ece9reed@google.com * 6dff7e11c2000d6745261de046d76b1500a05ece9reed@google.com * Permission is hereby granted, free of charge, to any person obtaining a 7dff7e11c2000d6745261de046d76b1500a05ece9reed@google.com * copy of this software and associated documentation files (the 8dff7e11c2000d6745261de046d76b1500a05ece9reed@google.com * "Software"), to deal in the Software without restriction, including 974ce6f046c8c8990172cebcfa830c8e5f5e42a1ereed@google.com * without limitation the rights to use, copy, modify, merge, publish, 10dff7e11c2000d6745261de046d76b1500a05ece9reed@google.com * distribute, sub license, and/or sell copies of the Software, and to 11dff7e11c2000d6745261de046d76b1500a05ece9reed@google.com * permit persons to whom the Software is furnished to do so, subject to 12dff7e11c2000d6745261de046d76b1500a05ece9reed@google.com * the following conditions: 13f02fe3d4fec9120da009c941d14af66980911a4emike@reedtribe.org * 14dff7e11c2000d6745261de046d76b1500a05ece9reed@google.com * The above copyright notice and this permission notice (including the 15dff7e11c2000d6745261de046d76b1500a05ece9reed@google.com * next paragraph) shall be included in all copies or substantial portions 1674ce6f046c8c8990172cebcfa830c8e5f5e42a1ereed@google.com * of the Software. 171c5a94f5e01d0851bfeceb7d17ad7d693bdc899emike@reedtribe.org * 1874ce6f046c8c8990172cebcfa830c8e5f5e42a1ereed@google.com * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 191c5a94f5e01d0851bfeceb7d17ad7d693bdc899emike@reedtribe.org * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 201c5a94f5e01d0851bfeceb7d17ad7d693bdc899emike@reedtribe.org * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. 211c5a94f5e01d0851bfeceb7d17ad7d693bdc899emike@reedtribe.org * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR 221c5a94f5e01d0851bfeceb7d17ad7d693bdc899emike@reedtribe.org * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, 231c5a94f5e01d0851bfeceb7d17ad7d693bdc899emike@reedtribe.org * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE 24539f364e80a1e8ee35845b93fd6547e855380cadskia.committer@gmail.com * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 251c5a94f5e01d0851bfeceb7d17ad7d693bdc899emike@reedtribe.org * 2674ce6f046c8c8990172cebcfa830c8e5f5e42a1ereed@google.com **************************************************************************/ 27dff7e11c2000d6745261de046d76b1500a05ece9reed@google.com 28dff7e11c2000d6745261de046d76b1500a05ece9reed@google.com#include <assert.h> 291c5a94f5e01d0851bfeceb7d17ad7d693bdc899emike@reedtribe.org#include <stdio.h> 303597b73bc6e3e169f1d360de80d77e6e0ab65e96reed@google.com 3174ce6f046c8c8990172cebcfa830c8e5f5e42a1ereed@google.com#include <X11/Xlibint.h> 3274ce6f046c8c8990172cebcfa830c8e5f5e42a1ereed@google.com 331c5a94f5e01d0851bfeceb7d17ad7d693bdc899emike@reedtribe.org#include "pipe/p_video_decoder.h" 3474ce6f046c8c8990172cebcfa830c8e5f5e42a1ereed@google.com#include "pipe/p_video_state.h" 35dff7e11c2000d6745261de046d76b1500a05ece9reed@google.com#include "pipe/p_state.h" 361c5a94f5e01d0851bfeceb7d17ad7d693bdc899emike@reedtribe.org 37e3823fd901674e22269637a669ac2b3e2667dc9creed@google.com#include "util/u_inlines.h" 38e3823fd901674e22269637a669ac2b3e2667dc9creed@google.com#include "util/u_memory.h" 391c5a94f5e01d0851bfeceb7d17ad7d693bdc899emike@reedtribe.org#include "util/u_math.h" 4074ce6f046c8c8990172cebcfa830c8e5f5e42a1ereed@google.com 419a73104c1b2238aa816de4d1beea3b4f570cfea0reed@google.com#include "vl_winsys.h" 429a73104c1b2238aa816de4d1beea3b4f570cfea0reed@google.com 4374ce6f046c8c8990172cebcfa830c8e5f5e42a1ereed@google.com#include "xvmc_private.h" 449a73104c1b2238aa816de4d1beea3b4f570cfea0reed@google.com 45e3823fd901674e22269637a669ac2b3e2667dc9creed@google.comstatic void 46e3823fd901674e22269637a669ac2b3e2667dc9creed@google.comMacroBlocksToPipe(XvMCContextPrivate *context, 47e3823fd901674e22269637a669ac2b3e2667dc9creed@google.com XvMCSurfacePrivate *surface, 48e3823fd901674e22269637a669ac2b3e2667dc9creed@google.com unsigned int xvmc_picture_structure, 49e3823fd901674e22269637a669ac2b3e2667dc9creed@google.com const XvMCMacroBlock *xvmc_mb, 50e3823fd901674e22269637a669ac2b3e2667dc9creed@google.com const XvMCBlockArray *xvmc_blocks, 51e3823fd901674e22269637a669ac2b3e2667dc9creed@google.com struct pipe_mpeg12_macroblock *mb, 52e3823fd901674e22269637a669ac2b3e2667dc9creed@google.com unsigned int num_macroblocks) 53e3823fd901674e22269637a669ac2b3e2667dc9creed@google.com{ 54e3823fd901674e22269637a669ac2b3e2667dc9creed@google.com unsigned int i, j, k; 55e3823fd901674e22269637a669ac2b3e2667dc9creed@google.com 56e3823fd901674e22269637a669ac2b3e2667dc9creed@google.com assert(xvmc_mb); 57e3823fd901674e22269637a669ac2b3e2667dc9creed@google.com assert(xvmc_blocks); 58e3823fd901674e22269637a669ac2b3e2667dc9creed@google.com assert(num_macroblocks); 59e3823fd901674e22269637a669ac2b3e2667dc9creed@google.com 607fa2a65c0cfc714364490cb715171461143024e0reed@google.com for (; num_macroblocks > 0; --num_macroblocks) { 617fa2a65c0cfc714364490cb715171461143024e0reed@google.com mb->base.codec = PIPE_VIDEO_CODEC_MPEG12; 62e3823fd901674e22269637a669ac2b3e2667dc9creed@google.com mb->x = xvmc_mb->x; 63e3823fd901674e22269637a669ac2b3e2667dc9creed@google.com mb->y = xvmc_mb->y; 64e3823fd901674e22269637a669ac2b3e2667dc9creed@google.com mb->macroblock_type = xvmc_mb->macroblock_type; 65e3823fd901674e22269637a669ac2b3e2667dc9creed@google.com 66e3823fd901674e22269637a669ac2b3e2667dc9creed@google.com switch (xvmc_picture_structure) { 67e3823fd901674e22269637a669ac2b3e2667dc9creed@google.com case XVMC_FRAME_PICTURE: 689a73104c1b2238aa816de4d1beea3b4f570cfea0reed@google.com mb->macroblock_modes.bits.frame_motion_type = xvmc_mb->motion_type; 699a73104c1b2238aa816de4d1beea3b4f570cfea0reed@google.com mb->macroblock_modes.bits.field_motion_type = 0; 70f02fe3d4fec9120da009c941d14af66980911a4emike@reedtribe.org break; 7174ce6f046c8c8990172cebcfa830c8e5f5e42a1ereed@google.com 72f02fe3d4fec9120da009c941d14af66980911a4emike@reedtribe.org case XVMC_TOP_FIELD: 73f02fe3d4fec9120da009c941d14af66980911a4emike@reedtribe.org case XVMC_BOTTOM_FIELD: 74f02fe3d4fec9120da009c941d14af66980911a4emike@reedtribe.org mb->macroblock_modes.bits.frame_motion_type = 0; 75f02fe3d4fec9120da009c941d14af66980911a4emike@reedtribe.org mb->macroblock_modes.bits.field_motion_type = xvmc_mb->motion_type; 76dff7e11c2000d6745261de046d76b1500a05ece9reed@google.com break; 77e254310a55d55a710309714c48f7fbbe7a6126f7commit-bot@chromium.org 78dff7e11c2000d6745261de046d76b1500a05ece9reed@google.com default: 79dff7e11c2000d6745261de046d76b1500a05ece9reed@google.com assert(0); 80dff7e11c2000d6745261de046d76b1500a05ece9reed@google.com } 81dff7e11c2000d6745261de046d76b1500a05ece9reed@google.com 82dff7e11c2000d6745261de046d76b1500a05ece9reed@google.com mb->macroblock_modes.bits.dct_type = xvmc_mb->dct_type; 83dff7e11c2000d6745261de046d76b1500a05ece9reed@google.com mb->motion_vertical_field_select = xvmc_mb->motion_vertical_field_select; 84e54a23fcfa42b2fc9d320650de72bcb2d9566b2dcommit-bot@chromium.org 851c5a94f5e01d0851bfeceb7d17ad7d693bdc899emike@reedtribe.org for (i = 0; i < 2; ++i) 86e54a23fcfa42b2fc9d320650de72bcb2d9566b2dcommit-bot@chromium.org for (j = 0; j < 2; ++j) 87dff7e11c2000d6745261de046d76b1500a05ece9reed@google.com for (k = 0; k < 2; ++k) 88dff7e11c2000d6745261de046d76b1500a05ece9reed@google.com mb->PMV[i][j][k] = xvmc_mb->PMV[i][j][k]; 89e54a23fcfa42b2fc9d320650de72bcb2d9566b2dcommit-bot@chromium.org 90e54a23fcfa42b2fc9d320650de72bcb2d9566b2dcommit-bot@chromium.org mb->coded_block_pattern = xvmc_mb->coded_block_pattern; 911c5a94f5e01d0851bfeceb7d17ad7d693bdc899emike@reedtribe.org mb->blocks = xvmc_blocks->blocks + xvmc_mb->index * BLOCK_SIZE_SAMPLES; 921c5a94f5e01d0851bfeceb7d17ad7d693bdc899emike@reedtribe.org mb->num_skipped_macroblocks = 0; 9374ce6f046c8c8990172cebcfa830c8e5f5e42a1ereed@google.com 941c5a94f5e01d0851bfeceb7d17ad7d693bdc899emike@reedtribe.org ++xvmc_mb; 951c5a94f5e01d0851bfeceb7d17ad7d693bdc899emike@reedtribe.org ++mb; 9674ce6f046c8c8990172cebcfa830c8e5f5e42a1ereed@google.com } 971c5a94f5e01d0851bfeceb7d17ad7d693bdc899emike@reedtribe.org} 98e54a23fcfa42b2fc9d320650de72bcb2d9566b2dcommit-bot@chromium.org 99e54a23fcfa42b2fc9d320650de72bcb2d9566b2dcommit-bot@chromium.orgstatic void 100e54a23fcfa42b2fc9d320650de72bcb2d9566b2dcommit-bot@chromium.orgGetPictureDescription(XvMCSurfacePrivate *surface, struct pipe_mpeg12_picture_desc *desc) 101e54a23fcfa42b2fc9d320650de72bcb2d9566b2dcommit-bot@chromium.org{ 102dff7e11c2000d6745261de046d76b1500a05ece9reed@google.com unsigned i, num_refs = 0; 103dff7e11c2000d6745261de046d76b1500a05ece9reed@google.com 104e54a23fcfa42b2fc9d320650de72bcb2d9566b2dcommit-bot@chromium.org assert(surface && desc); 1051c5a94f5e01d0851bfeceb7d17ad7d693bdc899emike@reedtribe.org 106e54a23fcfa42b2fc9d320650de72bcb2d9566b2dcommit-bot@chromium.org memset(desc, 0, sizeof(*desc)); 107dff7e11c2000d6745261de046d76b1500a05ece9reed@google.com desc->base.profile = PIPE_VIDEO_PROFILE_MPEG1; 108dff7e11c2000d6745261de046d76b1500a05ece9reed@google.com desc->picture_structure = surface->picture_structure; 10944c48d062f7996b5b46917e1b312a32ad101f326commit-bot@chromium.org for (i = 0; i < 2; ++i) { 110d9ea09e1f29b303e6fa36079e99729d2951925b9commit-bot@chromium.org if (surface->ref[i]) { 111d9ea09e1f29b303e6fa36079e99729d2951925b9commit-bot@chromium.org XvMCSurfacePrivate *ref = surface->ref[i]->privData; 112d9ea09e1f29b303e6fa36079e99729d2951925b9commit-bot@chromium.org 113d9ea09e1f29b303e6fa36079e99729d2951925b9commit-bot@chromium.org if (ref) 114d9ea09e1f29b303e6fa36079e99729d2951925b9commit-bot@chromium.org desc->ref[num_refs++] = ref->video_buffer; 115d9ea09e1f29b303e6fa36079e99729d2951925b9commit-bot@chromium.org } 116d9ea09e1f29b303e6fa36079e99729d2951925b9commit-bot@chromium.org } 117d9ea09e1f29b303e6fa36079e99729d2951925b9commit-bot@chromium.org} 118d9ea09e1f29b303e6fa36079e99729d2951925b9commit-bot@chromium.org 119d9ea09e1f29b303e6fa36079e99729d2951925b9commit-bot@chromium.orgstatic void 120d9ea09e1f29b303e6fa36079e99729d2951925b9commit-bot@chromium.orgRecursiveEndFrame(XvMCSurfacePrivate *surface) 121d9ea09e1f29b303e6fa36079e99729d2951925b9commit-bot@chromium.org{ 122d9ea09e1f29b303e6fa36079e99729d2951925b9commit-bot@chromium.org XvMCContextPrivate *context_priv; 123d9ea09e1f29b303e6fa36079e99729d2951925b9commit-bot@chromium.org unsigned i; 124d9ea09e1f29b303e6fa36079e99729d2951925b9commit-bot@chromium.org 125ab885be21bfc389450e6194d0562493c658b3c36commit-bot@chromium.org assert(surface); 126ab885be21bfc389450e6194d0562493c658b3c36commit-bot@chromium.org 127ab885be21bfc389450e6194d0562493c658b3c36commit-bot@chromium.org context_priv = surface->context->privData; 128d9ea09e1f29b303e6fa36079e99729d2951925b9commit-bot@chromium.org 129d9ea09e1f29b303e6fa36079e99729d2951925b9commit-bot@chromium.org for ( i = 0; i < 2; ++i ) { 130d9ea09e1f29b303e6fa36079e99729d2951925b9commit-bot@chromium.org if (surface->ref[i]) { 131d9ea09e1f29b303e6fa36079e99729d2951925b9commit-bot@chromium.org XvMCSurface *ref = surface->ref[i]; 13244c48d062f7996b5b46917e1b312a32ad101f326commit-bot@chromium.org 133dff7e11c2000d6745261de046d76b1500a05ece9reed@google.com assert(ref); 134dff7e11c2000d6745261de046d76b1500a05ece9reed@google.com 13544c48d062f7996b5b46917e1b312a32ad101f326commit-bot@chromium.org surface->ref[i] = NULL; 13644c48d062f7996b5b46917e1b312a32ad101f326commit-bot@chromium.org RecursiveEndFrame(ref->privData); 137dff7e11c2000d6745261de046d76b1500a05ece9reed@google.com surface->ref[i] = ref; 138dff7e11c2000d6745261de046d76b1500a05ece9reed@google.com } 1398f90a892c5130d4d26b5588e1ff151d01a40688arobertphillips@google.com } 1401c5a94f5e01d0851bfeceb7d17ad7d693bdc899emike@reedtribe.org 14174ce6f046c8c8990172cebcfa830c8e5f5e42a1ereed@google.com if (surface->picture_structure) { 1428f90a892c5130d4d26b5588e1ff151d01a40688arobertphillips@google.com struct pipe_mpeg12_picture_desc desc; 1438f90a892c5130d4d26b5588e1ff151d01a40688arobertphillips@google.com GetPictureDescription(surface, &desc); 144dff7e11c2000d6745261de046d76b1500a05ece9reed@google.com surface->picture_structure = 0; 145dff7e11c2000d6745261de046d76b1500a05ece9reed@google.com 1468f90a892c5130d4d26b5588e1ff151d01a40688arobertphillips@google.com for (i = 0; i < 2; ++i) 1471c5a94f5e01d0851bfeceb7d17ad7d693bdc899emike@reedtribe.org surface->ref[i] = NULL; 14874ce6f046c8c8990172cebcfa830c8e5f5e42a1ereed@google.com 1498f90a892c5130d4d26b5588e1ff151d01a40688arobertphillips@google.com context_priv->decoder->end_frame(context_priv->decoder, surface->video_buffer, &desc.base); 1508f90a892c5130d4d26b5588e1ff151d01a40688arobertphillips@google.com } 151dff7e11c2000d6745261de046d76b1500a05ece9reed@google.com} 152dff7e11c2000d6745261de046d76b1500a05ece9reed@google.com 1538f90a892c5130d4d26b5588e1ff151d01a40688arobertphillips@google.comPUBLIC 1541c5a94f5e01d0851bfeceb7d17ad7d693bdc899emike@reedtribe.orgStatus XvMCCreateSurface(Display *dpy, XvMCContext *context, XvMCSurface *surface) 15574ce6f046c8c8990172cebcfa830c8e5f5e42a1ereed@google.com{ 1568f90a892c5130d4d26b5588e1ff151d01a40688arobertphillips@google.com XvMCContextPrivate *context_priv; 1578f90a892c5130d4d26b5588e1ff151d01a40688arobertphillips@google.com struct pipe_context *pipe; 158dff7e11c2000d6745261de046d76b1500a05ece9reed@google.com XvMCSurfacePrivate *surface_priv; 159dff7e11c2000d6745261de046d76b1500a05ece9reed@google.com struct pipe_video_buffer tmpl; 1608f90a892c5130d4d26b5588e1ff151d01a40688arobertphillips@google.com 1611c5a94f5e01d0851bfeceb7d17ad7d693bdc899emike@reedtribe.org XVMC_MSG(XVMC_TRACE, "[XvMC] Creating surface %p.\n", surface); 1628f90a892c5130d4d26b5588e1ff151d01a40688arobertphillips@google.com 163dff7e11c2000d6745261de046d76b1500a05ece9reed@google.com assert(dpy); 164dff7e11c2000d6745261de046d76b1500a05ece9reed@google.com 165dff7e11c2000d6745261de046d76b1500a05ece9reed@google.com if (!context) 1661c5a94f5e01d0851bfeceb7d17ad7d693bdc899emike@reedtribe.org return XvMCBadContext; 16774ce6f046c8c8990172cebcfa830c8e5f5e42a1ereed@google.com if (!surface) 168dff7e11c2000d6745261de046d76b1500a05ece9reed@google.com return XvMCBadSurface; 169dff7e11c2000d6745261de046d76b1500a05ece9reed@google.com 170dff7e11c2000d6745261de046d76b1500a05ece9reed@google.com context_priv = context->privData; 171dff7e11c2000d6745261de046d76b1500a05ece9reed@google.com pipe = context_priv->pipe; 1721c5a94f5e01d0851bfeceb7d17ad7d693bdc899emike@reedtribe.org 1732cfa3200fda29279eba1240170c7e873d12f9d48commit-bot@chromium.org surface_priv = CALLOC(1, sizeof(XvMCSurfacePrivate)); 17474ce6f046c8c8990172cebcfa830c8e5f5e42a1ereed@google.com if (!surface_priv) 175dff7e11c2000d6745261de046d76b1500a05ece9reed@google.com return BadAlloc; 176dff7e11c2000d6745261de046d76b1500a05ece9reed@google.com 177dff7e11c2000d6745261de046d76b1500a05ece9reed@google.com memset(&tmpl, 0, sizeof(tmpl)); 1781c5a94f5e01d0851bfeceb7d17ad7d693bdc899emike@reedtribe.org tmpl.buffer_format = pipe->screen->get_video_param 17974ce6f046c8c8990172cebcfa830c8e5f5e42a1ereed@google.com ( 18074ce6f046c8c8990172cebcfa830c8e5f5e42a1ereed@google.com pipe->screen, 181dff7e11c2000d6745261de046d76b1500a05ece9reed@google.com PIPE_VIDEO_PROFILE_MPEG2_MAIN, 182dff7e11c2000d6745261de046d76b1500a05ece9reed@google.com PIPE_VIDEO_CAP_PREFERED_FORMAT 1837ce564cccb246ec56427085872b2e1458fe74bd1bsalomon@google.com ); 1841c5a94f5e01d0851bfeceb7d17ad7d693bdc899emike@reedtribe.org tmpl.chroma_format = context_priv->decoder->chroma_format; 18574ce6f046c8c8990172cebcfa830c8e5f5e42a1ereed@google.com tmpl.width = context_priv->decoder->width; 18674ce6f046c8c8990172cebcfa830c8e5f5e42a1ereed@google.com tmpl.height = context_priv->decoder->height; 187dff7e11c2000d6745261de046d76b1500a05ece9reed@google.com tmpl.interlaced = pipe->screen->get_video_param 188dff7e11c2000d6745261de046d76b1500a05ece9reed@google.com ( 189dff7e11c2000d6745261de046d76b1500a05ece9reed@google.com pipe->screen, 1901c5a94f5e01d0851bfeceb7d17ad7d693bdc899emike@reedtribe.org PIPE_VIDEO_PROFILE_MPEG2_MAIN, 19174ce6f046c8c8990172cebcfa830c8e5f5e42a1ereed@google.com PIPE_VIDEO_CAP_PREFERS_INTERLACED 19274ce6f046c8c8990172cebcfa830c8e5f5e42a1ereed@google.com ); 193dff7e11c2000d6745261de046d76b1500a05ece9reed@google.com 194dff7e11c2000d6745261de046d76b1500a05ece9reed@google.com surface_priv->video_buffer = pipe->create_video_buffer(pipe, &tmpl); 195ab5827354e2c23624acc3fc1fe4a83788bc99e96commit-bot@chromium.org surface_priv->context = context; 196ab5827354e2c23624acc3fc1fe4a83788bc99e96commit-bot@chromium.org 197ab5827354e2c23624acc3fc1fe4a83788bc99e96commit-bot@chromium.org surface->surface_id = XAllocID(dpy); 198ab5827354e2c23624acc3fc1fe4a83788bc99e96commit-bot@chromium.org surface->context_id = context->context_id; 199ab5827354e2c23624acc3fc1fe4a83788bc99e96commit-bot@chromium.org surface->surface_type_id = context->surface_type_id; 200ab5827354e2c23624acc3fc1fe4a83788bc99e96commit-bot@chromium.org surface->width = context->width; 201ab5827354e2c23624acc3fc1fe4a83788bc99e96commit-bot@chromium.org surface->height = context->height; 202ab5827354e2c23624acc3fc1fe4a83788bc99e96commit-bot@chromium.org surface->privData = surface_priv; 2037ce564cccb246ec56427085872b2e1458fe74bd1bsalomon@google.com 2041c5a94f5e01d0851bfeceb7d17ad7d693bdc899emike@reedtribe.org SyncHandle(); 20574ce6f046c8c8990172cebcfa830c8e5f5e42a1ereed@google.com 20674ce6f046c8c8990172cebcfa830c8e5f5e42a1ereed@google.com XVMC_MSG(XVMC_TRACE, "[XvMC] Surface %p created.\n", surface); 207dff7e11c2000d6745261de046d76b1500a05ece9reed@google.com 208dff7e11c2000d6745261de046d76b1500a05ece9reed@google.com return Success; 209dff7e11c2000d6745261de046d76b1500a05ece9reed@google.com} 210eed779d866e1e239bfb9ebc6a225b7345a41adf9commit-bot@chromium.org 2111c5a94f5e01d0851bfeceb7d17ad7d693bdc899emike@reedtribe.orgPUBLIC 2121c5a94f5e01d0851bfeceb7d17ad7d693bdc899emike@reedtribe.orgStatus XvMCRenderSurface(Display *dpy, XvMCContext *context, unsigned int picture_structure, 21374ce6f046c8c8990172cebcfa830c8e5f5e42a1ereed@google.com XvMCSurface *target_surface, XvMCSurface *past_surface, XvMCSurface *future_surface, 2141c5a94f5e01d0851bfeceb7d17ad7d693bdc899emike@reedtribe.org unsigned int flags, unsigned int num_macroblocks, unsigned int first_macroblock, 215dff7e11c2000d6745261de046d76b1500a05ece9reed@google.com XvMCMacroBlockArray *macroblocks, XvMCBlockArray *blocks 216dff7e11c2000d6745261de046d76b1500a05ece9reed@google.com) 217dff7e11c2000d6745261de046d76b1500a05ece9reed@google.com{ 218eed779d866e1e239bfb9ebc6a225b7345a41adf9commit-bot@chromium.org struct pipe_mpeg12_macroblock mb[num_macroblocks]; 219eed779d866e1e239bfb9ebc6a225b7345a41adf9commit-bot@chromium.org struct pipe_video_decoder *decoder; 2201c5a94f5e01d0851bfeceb7d17ad7d693bdc899emike@reedtribe.org struct pipe_mpeg12_picture_desc desc; 2211c5a94f5e01d0851bfeceb7d17ad7d693bdc899emike@reedtribe.org 22274ce6f046c8c8990172cebcfa830c8e5f5e42a1ereed@google.com XvMCContextPrivate *context_priv; 2231c5a94f5e01d0851bfeceb7d17ad7d693bdc899emike@reedtribe.org XvMCSurfacePrivate *target_surface_priv; 224dff7e11c2000d6745261de046d76b1500a05ece9reed@google.com XvMCSurfacePrivate *past_surface_priv; 225dff7e11c2000d6745261de046d76b1500a05ece9reed@google.com XvMCSurfacePrivate *future_surface_priv; 226dff7e11c2000d6745261de046d76b1500a05ece9reed@google.com XvMCMacroBlock *xvmc_mb; 227eed779d866e1e239bfb9ebc6a225b7345a41adf9commit-bot@chromium.org 2281c5a94f5e01d0851bfeceb7d17ad7d693bdc899emike@reedtribe.org XVMC_MSG(XVMC_TRACE, "[XvMC] Rendering to surface %p, with past %p and future %p\n", 2291c5a94f5e01d0851bfeceb7d17ad7d693bdc899emike@reedtribe.org target_surface, past_surface, future_surface); 23074ce6f046c8c8990172cebcfa830c8e5f5e42a1ereed@google.com 2311c5a94f5e01d0851bfeceb7d17ad7d693bdc899emike@reedtribe.org assert(dpy); 232dff7e11c2000d6745261de046d76b1500a05ece9reed@google.com 233dff7e11c2000d6745261de046d76b1500a05ece9reed@google.com if (!context || !context->privData) 234dff7e11c2000d6745261de046d76b1500a05ece9reed@google.com return XvMCBadContext; 235dff7e11c2000d6745261de046d76b1500a05ece9reed@google.com if (!target_surface || !target_surface->privData) 2361c5a94f5e01d0851bfeceb7d17ad7d693bdc899emike@reedtribe.org return XvMCBadSurface; 2371c5a94f5e01d0851bfeceb7d17ad7d693bdc899emike@reedtribe.org 23874ce6f046c8c8990172cebcfa830c8e5f5e42a1ereed@google.com if (picture_structure != XVMC_TOP_FIELD && 2391c5a94f5e01d0851bfeceb7d17ad7d693bdc899emike@reedtribe.org picture_structure != XVMC_BOTTOM_FIELD && 240dff7e11c2000d6745261de046d76b1500a05ece9reed@google.com picture_structure != XVMC_FRAME_PICTURE) 241dff7e11c2000d6745261de046d76b1500a05ece9reed@google.com return BadValue; 242e0d9ce890e67d02727ac2811bb456ddb64f827d4reed@google.com /* Bkwd pred equivalent to fwd (past && !future) */ 243e0d9ce890e67d02727ac2811bb456ddb64f827d4reed@google.com if (future_surface && !past_surface) 2441c5a94f5e01d0851bfeceb7d17ad7d693bdc899emike@reedtribe.org return BadMatch; 245e3823fd901674e22269637a669ac2b3e2667dc9creed@google.com 24674ce6f046c8c8990172cebcfa830c8e5f5e42a1ereed@google.com assert(context->context_id == target_surface->context_id); 247dff7e11c2000d6745261de046d76b1500a05ece9reed@google.com assert(!past_surface || context->context_id == past_surface->context_id); 248dff7e11c2000d6745261de046d76b1500a05ece9reed@google.com assert(!future_surface || context->context_id == future_surface->context_id); 249e0d9ce890e67d02727ac2811bb456ddb64f827d4reed@google.com 250e0d9ce890e67d02727ac2811bb456ddb64f827d4reed@google.com assert(macroblocks); 2511c5a94f5e01d0851bfeceb7d17ad7d693bdc899emike@reedtribe.org assert(blocks); 252e3823fd901674e22269637a669ac2b3e2667dc9creed@google.com 25374ce6f046c8c8990172cebcfa830c8e5f5e42a1ereed@google.com assert(macroblocks->context_id == context->context_id); 254dff7e11c2000d6745261de046d76b1500a05ece9reed@google.com assert(blocks->context_id == context->context_id); 255dff7e11c2000d6745261de046d76b1500a05ece9reed@google.com 256e0d9ce890e67d02727ac2811bb456ddb64f827d4reed@google.com assert(flags == 0 || flags == XVMC_SECOND_FIELD); 257e0d9ce890e67d02727ac2811bb456ddb64f827d4reed@google.com 2581c5a94f5e01d0851bfeceb7d17ad7d693bdc899emike@reedtribe.org context_priv = context->privData; 259e3823fd901674e22269637a669ac2b3e2667dc9creed@google.com decoder = context_priv->decoder; 26074ce6f046c8c8990172cebcfa830c8e5f5e42a1ereed@google.com 261dff7e11c2000d6745261de046d76b1500a05ece9reed@google.com target_surface_priv = target_surface->privData; 262dff7e11c2000d6745261de046d76b1500a05ece9reed@google.com past_surface_priv = past_surface ? past_surface->privData : NULL; 263e0d9ce890e67d02727ac2811bb456ddb64f827d4reed@google.com future_surface_priv = future_surface ? future_surface->privData : NULL; 264e0d9ce890e67d02727ac2811bb456ddb64f827d4reed@google.com 2651c5a94f5e01d0851bfeceb7d17ad7d693bdc899emike@reedtribe.org assert(target_surface_priv->context == context); 26674ce6f046c8c8990172cebcfa830c8e5f5e42a1ereed@google.com assert(!past_surface || past_surface_priv->context == context); 267e3823fd901674e22269637a669ac2b3e2667dc9creed@google.com assert(!future_surface || future_surface_priv->context == context); 26874ce6f046c8c8990172cebcfa830c8e5f5e42a1ereed@google.com 269dff7e11c2000d6745261de046d76b1500a05ece9reed@google.com // call end frame on all referenced frames 270dff7e11c2000d6745261de046d76b1500a05ece9reed@google.com if (past_surface) 2719b14f26d0f3a974f3dd626c8354e1db1cfcd322frobertphillips RecursiveEndFrame(past_surface->privData); 2721c5a94f5e01d0851bfeceb7d17ad7d693bdc899emike@reedtribe.org 273dff7e11c2000d6745261de046d76b1500a05ece9reed@google.com if (future_surface) 2749b14f26d0f3a974f3dd626c8354e1db1cfcd322frobertphillips RecursiveEndFrame(future_surface->privData); 275dff7e11c2000d6745261de046d76b1500a05ece9reed@google.com 276dff7e11c2000d6745261de046d76b1500a05ece9reed@google.com xvmc_mb = macroblocks->macro_blocks + first_macroblock; 277dff7e11c2000d6745261de046d76b1500a05ece9reed@google.com 278dff7e11c2000d6745261de046d76b1500a05ece9reed@google.com /* If the surface we're rendering hasn't changed the ref frames shouldn't change. */ 279dff7e11c2000d6745261de046d76b1500a05ece9reed@google.com if (target_surface_priv->picture_structure > 0 && ( 280dff7e11c2000d6745261de046d76b1500a05ece9reed@google.com target_surface_priv->picture_structure != picture_structure || 281dff7e11c2000d6745261de046d76b1500a05ece9reed@google.com target_surface_priv->ref[0] != past_surface || 2821c5a94f5e01d0851bfeceb7d17ad7d693bdc899emike@reedtribe.org target_surface_priv->ref[1] != future_surface || 28374ce6f046c8c8990172cebcfa830c8e5f5e42a1ereed@google.com (xvmc_mb->x == 0 && xvmc_mb->y == 0))) { 284dff7e11c2000d6745261de046d76b1500a05ece9reed@google.com 285dff7e11c2000d6745261de046d76b1500a05ece9reed@google.com // If they change anyway we must assume that the current frame is ended 286dff7e11c2000d6745261de046d76b1500a05ece9reed@google.com RecursiveEndFrame(target_surface_priv); 2871c5a94f5e01d0851bfeceb7d17ad7d693bdc899emike@reedtribe.org } 288dff7e11c2000d6745261de046d76b1500a05ece9reed@google.com 289 target_surface_priv->ref[0] = past_surface; 290 target_surface_priv->ref[1] = future_surface; 291 292 if (target_surface_priv->picture_structure) 293 GetPictureDescription(target_surface_priv, &desc); 294 else { 295 target_surface_priv->picture_structure = picture_structure; 296 GetPictureDescription(target_surface_priv, &desc); 297 decoder->begin_frame(decoder, target_surface_priv->video_buffer, &desc.base); 298 } 299 300 MacroBlocksToPipe(context_priv, target_surface_priv, picture_structure, 301 xvmc_mb, blocks, mb, num_macroblocks); 302 303 context_priv->decoder->decode_macroblock(context_priv->decoder, 304 target_surface_priv->video_buffer, 305 &desc.base, 306 &mb[0].base, num_macroblocks); 307 308 XVMC_MSG(XVMC_TRACE, "[XvMC] Submitted surface %p for rendering.\n", target_surface); 309 310 return Success; 311} 312 313PUBLIC 314Status XvMCFlushSurface(Display *dpy, XvMCSurface *surface) 315{ 316 assert(dpy); 317 318 if (!surface) 319 return XvMCBadSurface; 320 321 // don't call flush here, because this is usually 322 // called once for every slice instead of every frame 323 324 XVMC_MSG(XVMC_TRACE, "[XvMC] Flushing surface %p\n", surface); 325 326 return Success; 327} 328 329PUBLIC 330Status XvMCSyncSurface(Display *dpy, XvMCSurface *surface) 331{ 332 assert(dpy); 333 334 if (!surface) 335 return XvMCBadSurface; 336 337 XVMC_MSG(XVMC_TRACE, "[XvMC] Syncing surface %p\n", surface); 338 339 return Success; 340} 341 342PUBLIC 343Status XvMCPutSurface(Display *dpy, XvMCSurface *surface, Drawable drawable, 344 short srcx, short srcy, unsigned short srcw, unsigned short srch, 345 short destx, short desty, unsigned short destw, unsigned short desth, 346 int flags) 347{ 348 static int dump_window = -1; 349 350 struct pipe_context *pipe; 351 struct vl_compositor *compositor; 352 struct vl_compositor_state *cstate; 353 354 XvMCSurfacePrivate *surface_priv; 355 XvMCContextPrivate *context_priv; 356 XvMCSubpicturePrivate *subpicture_priv; 357 XvMCContext *context; 358 struct u_rect src_rect = {srcx, srcx + srcw, srcy, srcy + srch}; 359 struct u_rect dst_rect = {destx, destx + destw, desty, desty + desth}; 360 361 struct pipe_resource *tex; 362 struct pipe_surface surf_templ, *surf; 363 struct u_rect *dirty_area; 364 365 XVMC_MSG(XVMC_TRACE, "[XvMC] Displaying surface %p.\n", surface); 366 367 assert(dpy); 368 369 if (!surface || !surface->privData) 370 return XvMCBadSurface; 371 372 surface_priv = surface->privData; 373 context = surface_priv->context; 374 context_priv = context->privData; 375 376 assert(flags == XVMC_TOP_FIELD || flags == XVMC_BOTTOM_FIELD || flags == XVMC_FRAME_PICTURE); 377 assert(srcx + srcw - 1 < surface->width); 378 assert(srcy + srch - 1 < surface->height); 379 380 subpicture_priv = surface_priv->subpicture ? surface_priv->subpicture->privData : NULL; 381 pipe = context_priv->pipe; 382 compositor = &context_priv->compositor; 383 cstate = &context_priv->cstate; 384 385 tex = vl_screen_texture_from_drawable(context_priv->vscreen, drawable); 386 dirty_area = vl_screen_get_dirty_area(context_priv->vscreen); 387 388 memset(&surf_templ, 0, sizeof(surf_templ)); 389 surf_templ.format = tex->format; 390 surf_templ.usage = PIPE_BIND_RENDER_TARGET; 391 surf = pipe->create_surface(pipe, tex, &surf_templ); 392 393 if (!surf) 394 return BadDrawable; 395 396 /* 397 * Some apps (mplayer) hit these asserts because they call 398 * this function after the window has been resized by the WM 399 * but before they've handled the corresponding XEvent and 400 * know about the new dimensions. The output should be clipped 401 * until the app updates destw and desth. 402 */ 403 /* 404 assert(destx + destw - 1 < drawable_surface->width); 405 assert(desty + desth - 1 < drawable_surface->height); 406 */ 407 408 RecursiveEndFrame(surface_priv); 409 410 context_priv->decoder->flush(context_priv->decoder); 411 412 vl_compositor_clear_layers(cstate); 413 vl_compositor_set_buffer_layer(cstate, compositor, 0, surface_priv->video_buffer, 414 &src_rect, NULL, VL_COMPOSITOR_WEAVE); 415 416 if (subpicture_priv) { 417 XVMC_MSG(XVMC_TRACE, "[XvMC] Surface %p has subpicture %p.\n", surface, surface_priv->subpicture); 418 419 assert(subpicture_priv->surface == surface); 420 421 if (subpicture_priv->palette) 422 vl_compositor_set_palette_layer(cstate, compositor, 1, subpicture_priv->sampler, subpicture_priv->palette, 423 &subpicture_priv->src_rect, &subpicture_priv->dst_rect, true); 424 else 425 vl_compositor_set_rgba_layer(cstate, compositor, 1, subpicture_priv->sampler, 426 &subpicture_priv->src_rect, &subpicture_priv->dst_rect); 427 428 surface_priv->subpicture = NULL; 429 subpicture_priv->surface = NULL; 430 } 431 432 // Workaround for r600g, there seems to be a bug in the fence refcounting code 433 pipe->screen->fence_reference(pipe->screen, &surface_priv->fence, NULL); 434 435 vl_compositor_set_dst_area(cstate, &dst_rect); 436 vl_compositor_render(cstate, compositor, surf, dirty_area); 437 438 pipe->flush(pipe, &surface_priv->fence); 439 440 XVMC_MSG(XVMC_TRACE, "[XvMC] Submitted surface %p for display. Pushing to front buffer.\n", surface); 441 442 pipe->screen->flush_frontbuffer 443 ( 444 pipe->screen, tex, 0, 0, 445 vl_screen_get_private(context_priv->vscreen) 446 ); 447 448 if(dump_window == -1) { 449 dump_window = debug_get_num_option("XVMC_DUMP", 0); 450 } 451 452 if(dump_window) { 453 static unsigned int framenum = 0; 454 char cmd[256]; 455 456 sprintf(cmd, "xwd -id %d -out xvmc_frame_%08d.xwd", (int)drawable, ++framenum); 457 if (system(cmd) != 0) 458 XVMC_MSG(XVMC_ERR, "[XvMC] Dumping surface %p failed.\n", surface); 459 } 460 461 XVMC_MSG(XVMC_TRACE, "[XvMC] Pushed surface %p to front buffer.\n", surface); 462 463 return Success; 464} 465 466PUBLIC 467Status XvMCGetSurfaceStatus(Display *dpy, XvMCSurface *surface, int *status) 468{ 469 struct pipe_context *pipe; 470 XvMCSurfacePrivate *surface_priv; 471 XvMCContextPrivate *context_priv; 472 473 assert(dpy); 474 475 if (!surface) 476 return XvMCBadSurface; 477 478 assert(status); 479 480 surface_priv = surface->privData; 481 context_priv = surface_priv->context->privData; 482 pipe = context_priv->pipe; 483 484 *status = 0; 485 486 if (surface_priv->fence) 487 if (!pipe->screen->fence_signalled(pipe->screen, surface_priv->fence)) 488 *status |= XVMC_RENDERING; 489 490 return Success; 491} 492 493PUBLIC 494Status XvMCDestroySurface(Display *dpy, XvMCSurface *surface) 495{ 496 XvMCSurfacePrivate *surface_priv; 497 XvMCContextPrivate *context_priv; 498 499 XVMC_MSG(XVMC_TRACE, "[XvMC] Destroying surface %p.\n", surface); 500 501 assert(dpy); 502 503 if (!surface || !surface->privData) 504 return XvMCBadSurface; 505 506 surface_priv = surface->privData; 507 context_priv = surface_priv->context->privData; 508 509 if (surface_priv->picture_structure) { 510 struct pipe_mpeg12_picture_desc desc; 511 GetPictureDescription(surface_priv, &desc); 512 context_priv->decoder->end_frame(context_priv->decoder, surface_priv->video_buffer, &desc.base); 513 } 514 surface_priv->video_buffer->destroy(surface_priv->video_buffer); 515 FREE(surface_priv); 516 surface->privData = NULL; 517 518 XVMC_MSG(XVMC_TRACE, "[XvMC] Surface %p destroyed.\n", surface); 519 520 return Success; 521} 522 523PUBLIC 524Status XvMCHideSurface(Display *dpy, XvMCSurface *surface) 525{ 526 assert(dpy); 527 528 if (!surface || !surface->privData) 529 return XvMCBadSurface; 530 531 /* No op, only for overlaid rendering */ 532 533 return Success; 534} 535