#include <assert.h>
#include <X11/Xlibint.h>
+#include <vl_winsys.h>
#include <pipe/p_video_context.h>
#include <pipe/p_video_state.h>
#include <pipe/p_state.h>
+#include <util/u_inlines.h>
#include <util/u_memory.h>
+#include <util/u_math.h>
#include "xvmc_private.h"
static enum pipe_mpeg12_macroblock_type TypeToPipe(int xvmc_mb_type)
assert(0);
+ XVMC_MSG(XVMC_ERR, "[XvMC] Unrecognized mb type 0x%08X.\n", xvmc_mb_type);
+
return -1;
}
assert(0);
}
+ XVMC_MSG(XVMC_ERR, "[XvMC] Unrecognized picture type 0x%08X.\n", xvmc_pic);
+
return -1;
}
-static enum pipe_mpeg12_motion_type MotionToPipe(int xvmc_motion_type, int xvmc_dct_type)
+static enum pipe_mpeg12_motion_type MotionToPipe(int xvmc_motion_type, unsigned int xvmc_picture_structure)
{
switch (xvmc_motion_type) {
case XVMC_PREDICTION_FRAME:
- return xvmc_dct_type == XVMC_DCT_TYPE_FIELD ?
- PIPE_MPEG12_MOTION_TYPE_16x8 : PIPE_MPEG12_MOTION_TYPE_FRAME;
+ if (xvmc_picture_structure == XVMC_FRAME_PICTURE)
+ return PIPE_MPEG12_MOTION_TYPE_FRAME;
+ else
+ return PIPE_MPEG12_MOTION_TYPE_16x8;
+ break;
case XVMC_PREDICTION_FIELD:
return PIPE_MPEG12_MOTION_TYPE_FIELD;
case XVMC_PREDICTION_DUAL_PRIME:
assert(0);
}
+ XVMC_MSG(XVMC_ERR, "[XvMC] Unrecognized motion type 0x%08X (with picture structure 0x%08X).\n", xvmc_motion_type, xvmc_picture_structure);
+
return -1;
}
+#if 0
static bool
-CreateOrResizeBackBuffer(struct pipe_video_context *vpipe, unsigned int width, unsigned int height,
+CreateOrResizeBackBuffer(struct vl_context *vctx, unsigned int width, unsigned int height,
struct pipe_surface **backbuffer)
{
- struct pipe_texture template;
- struct pipe_texture *tex;
+ struct pipe_video_context *vpipe;
+ struct pipe_resource template;
+ struct pipe_resource *tex;
+
+ assert(vctx);
- assert(vpipe);
+ vpipe = vctx->vpipe;
if (*backbuffer) {
if ((*backbuffer)->width != width || (*backbuffer)->height != height)
return true;
}
- memset(&template, 0, sizeof(struct pipe_texture));
+ memset(&template, 0, sizeof(struct pipe_resource));
template.target = PIPE_TEXTURE_2D;
- /* XXX: Needs to match the drawable's format? */
- template.format = PIPE_FORMAT_X8R8G8B8_UNORM;
+ template.format = vctx->vscreen->format;
template.last_level = 0;
template.width0 = width;
template.height0 = height;
template.depth0 = 1;
- template.tex_usage = PIPE_TEXTURE_USAGE_DISPLAY_TARGET;
+ template.usage = PIPE_USAGE_DEFAULT;
+ template.bind = PIPE_BIND_RENDER_TARGET | PIPE_BIND_DISPLAY_TARGET | PIPE_BIND_BLIT_SOURCE;
+ template.flags = 0;
- tex = vpipe->screen->texture_create(vpipe->screen, &template);
+ tex = vpipe->screen->resource_create(vpipe->screen, &template);
if (!tex)
return false;
*backbuffer = vpipe->screen->get_tex_surface(vpipe->screen, tex, 0, 0, 0,
- PIPE_BUFFER_USAGE_GPU_READ |
- PIPE_BUFFER_USAGE_GPU_WRITE);
- pipe_texture_reference(&tex, NULL);
+ template.bind);
+ pipe_resource_reference(&tex, NULL);
if (!*backbuffer)
return false;
/* Clear the backbuffer in case the video doesn't cover the whole window */
/* FIXME: Need to clear every time a frame moves and leaves dirty rects */
- vpipe->clear_surface(vpipe, 0, 0, width, height, 0, *backbuffer);
+ vpipe->surface_fill(vpipe, *backbuffer, 0, 0, width, height, 0);
return true;
}
+#endif
static void
-MacroBlocksToPipe(const XvMCMacroBlockArray *xvmc_macroblocks,
+MacroBlocksToPipe(struct pipe_screen *screen,
+ unsigned int xvmc_picture_structure,
+ const XvMCMacroBlockArray *xvmc_macroblocks,
const XvMCBlockArray *xvmc_blocks,
unsigned int first_macroblock,
unsigned int num_macroblocks,
pipe_macroblocks->mby = xvmc_mb->y;
pipe_macroblocks->mb_type = TypeToPipe(xvmc_mb->macroblock_type);
if (pipe_macroblocks->mb_type != PIPE_MPEG12_MACROBLOCK_TYPE_INTRA)
- pipe_macroblocks->mo_type = MotionToPipe(xvmc_mb->motion_type, xvmc_mb->dct_type);
+ pipe_macroblocks->mo_type = MotionToPipe(xvmc_mb->motion_type, xvmc_picture_structure);
/* Get rid of Valgrind 'undefined' warnings */
else
pipe_macroblocks->mo_type = -1;
}
}
+PUBLIC
Status XvMCCreateSurface(Display *dpy, XvMCContext *context, XvMCSurface *surface)
{
XvMCContextPrivate *context_priv;
struct pipe_video_context *vpipe;
XvMCSurfacePrivate *surface_priv;
- struct pipe_video_surface *vsfc;
+ struct pipe_resource template;
+ struct pipe_resource *vsfc_tex;
+ struct pipe_surface *vsfc;
+
+ XVMC_MSG(XVMC_TRACE, "[XvMC] Creating surface %p.\n", surface);
assert(dpy);
return XvMCBadSurface;
context_priv = context->privData;
- vpipe = context_priv->vpipe;
+ vpipe = context_priv->vctx->vpipe;
surface_priv = CALLOC(1, sizeof(XvMCSurfacePrivate));
if (!surface_priv)
return BadAlloc;
- vsfc = vpipe->screen->video_surface_create(vpipe->screen, vpipe->chroma_format,
- vpipe->width, vpipe->height);
+ memset(&template, 0, sizeof(struct pipe_resource));
+ template.target = PIPE_TEXTURE_2D;
+ template.format = (enum pipe_format)vpipe->get_param(vpipe, PIPE_CAP_DECODE_TARGET_PREFERRED_FORMAT);
+ template.last_level = 0;
+ if (vpipe->is_format_supported(vpipe, template.format,
+ PIPE_BIND_SAMPLER_VIEW | PIPE_BIND_RENDER_TARGET,
+ PIPE_TEXTURE_GEOM_NON_POWER_OF_TWO)) {
+ template.width0 = context->width;
+ template.height0 = context->height;
+ }
+ else {
+ assert(vpipe->is_format_supported(vpipe, template.format,
+ PIPE_BIND_SAMPLER_VIEW | PIPE_BIND_RENDER_TARGET,
+ PIPE_TEXTURE_GEOM_NON_SQUARE));
+ template.width0 = util_next_power_of_two(context->width);
+ template.height0 = util_next_power_of_two(context->height);
+ }
+ template.depth0 = 1;
+ template.usage = PIPE_USAGE_DEFAULT;
+ template.bind = PIPE_BIND_SAMPLER_VIEW | PIPE_BIND_RENDER_TARGET;
+ template.flags = 0;
+ vsfc_tex = vpipe->screen->resource_create(vpipe->screen, &template);
+ if (!vsfc_tex) {
+ FREE(surface_priv);
+ return BadAlloc;
+ }
+
+ vsfc = vpipe->screen->get_tex_surface(vpipe->screen, vsfc_tex, 0, 0, 0,
+ PIPE_BIND_SAMPLER_VIEW | PIPE_BIND_RENDER_TARGET);
+ pipe_resource_reference(&vsfc_tex, NULL);
if (!vsfc) {
FREE(surface_priv);
return BadAlloc;
SyncHandle();
+ XVMC_MSG(XVMC_TRACE, "[XvMC] Surface %p created.\n", surface);
+
return Success;
}
+PUBLIC
Status XvMCRenderSurface(Display *dpy, XvMCContext *context, unsigned int picture_structure,
XvMCSurface *target_surface, XvMCSurface *past_surface, XvMCSurface *future_surface,
unsigned int flags, unsigned int num_macroblocks, unsigned int first_macroblock,
XvMCSurfacePrivate *future_surface_priv;
struct pipe_mpeg12_macroblock pipe_macroblocks[num_macroblocks];
+ XVMC_MSG(XVMC_TRACE, "[XvMC] Rendering to surface %p.\n", target_surface);
+
assert(dpy);
if (!context || !context->privData)
assert(!future_surface || future_surface_priv->context == context);
context_priv = context->privData;
- vpipe = context_priv->vpipe;
+ vpipe = context_priv->vctx->vpipe;
t_vsfc = target_surface_priv->pipe_vsfc;
p_vsfc = past_surface ? past_surface_priv->pipe_vsfc : NULL;
f_vsfc = future_surface ? future_surface_priv->pipe_vsfc : NULL;
- MacroBlocksToPipe(macroblocks, blocks, first_macroblock,
+ MacroBlocksToPipe(vpipe->screen, picture_structure, macroblocks, blocks, first_macroblock,
num_macroblocks, pipe_macroblocks);
vpipe->set_decode_target(vpipe, t_vsfc);
vpipe->decode_macroblocks(vpipe, p_vsfc, f_vsfc, num_macroblocks,
- &pipe_macroblocks->base, target_surface_priv->render_fence);
+ &pipe_macroblocks->base, &target_surface_priv->render_fence);
+
+ XVMC_MSG(XVMC_TRACE, "[XvMC] Submitted surface %p for rendering.\n", target_surface);
return Success;
}
+PUBLIC
Status XvMCFlushSurface(Display *dpy, XvMCSurface *surface)
{
assert(dpy);
return Success;
}
+PUBLIC
Status XvMCSyncSurface(Display *dpy, XvMCSurface *surface)
{
assert(dpy);
return Success;
}
+PUBLIC
Status XvMCPutSurface(Display *dpy, XvMCSurface *surface, Drawable drawable,
short srcx, short srcy, unsigned short srcw, unsigned short srch,
short destx, short desty, unsigned short destw, unsigned short desth,
int flags)
{
- Window root;
- int x, y;
- unsigned int width, height;
- unsigned int border_width;
- unsigned int depth;
struct pipe_video_context *vpipe;
XvMCSurfacePrivate *surface_priv;
XvMCContextPrivate *context_priv;
+ XvMCSubpicturePrivate *subpicture_priv;
XvMCContext *context;
struct pipe_video_rect src_rect = {srcx, srcy, srcw, srch};
struct pipe_video_rect dst_rect = {destx, desty, destw, desth};
+ struct pipe_surface *drawable_surface;
+
+ XVMC_MSG(XVMC_TRACE, "[XvMC] Displaying surface %p.\n", surface);
assert(dpy);
if (!surface || !surface->privData)
return XvMCBadSurface;
- if (XGetGeometry(dpy, drawable, &root, &x, &y, &width, &height, &border_width, &depth) == BadDrawable)
+ surface_priv = surface->privData;
+ context = surface_priv->context;
+ context_priv = context->privData;
+
+ drawable_surface = vl_drawable_surface_get(context_priv->vctx->vscreen, drawable);
+ if (!drawable_surface)
return BadDrawable;
assert(flags == XVMC_TOP_FIELD || flags == XVMC_BOTTOM_FIELD || flags == XVMC_FRAME_PICTURE);
* until the app updates destw and desth.
*/
/*
- assert(destx + destw - 1 < width);
- assert(desty + desth - 1 < height);
+ assert(destx + destw - 1 < drawable_surface->width);
+ assert(desty + desth - 1 < drawable_surface->height);
*/
- surface_priv = surface->privData;
- context = surface_priv->context;
- context_priv = context->privData;
- vpipe = context_priv->vpipe;
+ subpicture_priv = surface_priv->subpicture ? surface_priv->subpicture->privData : NULL;
+ vpipe = context_priv->vctx->vpipe;
- if (!CreateOrResizeBackBuffer(vpipe, width, height, &context_priv->backbuffer))
+#if 0
+ if (!CreateOrResizeBackBuffer(context_priv->vctx, width, height, &context_priv->backbuffer))
return BadAlloc;
+#endif
+
+ if (subpicture_priv) {
+ struct pipe_video_rect src_rect = {surface_priv->subx, surface_priv->suby, surface_priv->subw, surface_priv->subh};
+ struct pipe_video_rect dst_rect = {surface_priv->surfx, surface_priv->surfy, surface_priv->surfw, surface_priv->surfh};
+ struct pipe_video_rect *src_rects[1] = {&src_rect};
+ struct pipe_video_rect *dst_rects[1] = {&dst_rect};
+
+ XVMC_MSG(XVMC_TRACE, "[XvMC] Surface %p has subpicture %p.\n", surface, surface_priv->subpicture);
+
+ assert(subpicture_priv->surface == surface);
+ vpipe->set_picture_layers(vpipe, &subpicture_priv->sfc, src_rects, dst_rects, 1);
+
+ surface_priv->subpicture = NULL;
+ subpicture_priv->surface = NULL;
+ }
+ else
+ vpipe->set_picture_layers(vpipe, NULL, NULL, NULL, 0);
vpipe->render_picture(vpipe, surface_priv->pipe_vsfc, PictureToPipe(flags), &src_rect,
- context_priv->backbuffer, &dst_rect, surface_priv->disp_fence);
+ drawable_surface, &dst_rect, &surface_priv->disp_fence);
+
+ XVMC_MSG(XVMC_TRACE, "[XvMC] Submitted surface %p for display. Pushing to front buffer.\n", surface);
- vl_video_bind_drawable(vpipe, drawable);
-
vpipe->screen->flush_frontbuffer
(
vpipe->screen,
- context_priv->backbuffer,
- vpipe->priv
+ drawable_surface,
+ vl_contextprivate_get(context_priv->vctx, drawable_surface)
);
+ pipe_surface_reference(&drawable_surface, NULL);
+
+ XVMC_MSG(XVMC_TRACE, "[XvMC] Pushed surface %p to front buffer.\n", surface);
+
return Success;
}
+PUBLIC
Status XvMCGetSurfaceStatus(Display *dpy, XvMCSurface *surface, int *status)
{
assert(dpy);
return Success;
}
+PUBLIC
Status XvMCDestroySurface(Display *dpy, XvMCSurface *surface)
{
XvMCSurfacePrivate *surface_priv;
+ XVMC_MSG(XVMC_TRACE, "[XvMC] Destroying surface %p.\n", surface);
+
assert(dpy);
if (!surface || !surface->privData)
return XvMCBadSurface;
surface_priv = surface->privData;
- pipe_video_surface_reference(&surface_priv->pipe_vsfc, NULL);
+ pipe_surface_reference(&surface_priv->pipe_vsfc, NULL);
FREE(surface_priv);
surface->privData = NULL;
+ XVMC_MSG(XVMC_TRACE, "[XvMC] Surface %p destroyed.\n", surface);
+
return Success;
}
+PUBLIC
Status XvMCHideSurface(Display *dpy, XvMCSurface *surface)
{
assert(dpy);