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