X-Git-Url: https://git.libre-soc.org/?a=blobdiff_plain;f=src%2Fgallium%2Fstate_trackers%2Fxorg%2Fxvmc%2Fsurface.c;h=9709f2b23737a36d7e62d26d2ca8073ed8423c22;hb=34e5ae5aed8187e0f6395dee2985091cea3a6df6;hp=bf9038f356e4d4eb11e5edd2499138343068fcc4;hpb=8fc433fa0f8c5364454858f9be919387feda440c;p=mesa.git diff --git a/src/gallium/state_trackers/xorg/xvmc/surface.c b/src/gallium/state_trackers/xorg/xvmc/surface.c index bf9038f356e..9709f2b2373 100644 --- a/src/gallium/state_trackers/xorg/xvmc/surface.c +++ b/src/gallium/state_trackers/xorg/xvmc/surface.c @@ -1,8 +1,8 @@ /************************************************************************** - * + * * Copyright 2009 Younes Manton. * All Rights Reserved. - * + * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the * "Software"), to deal in the Software without restriction, including @@ -10,11 +10,11 @@ * distribute, sub license, and/or sell copies of the Software, and to * permit persons to whom the Software is furnished to do so, subject to * the following conditions: - * + * * The above copyright notice and this permission notice (including the * next paragraph) shall be included in all copies or substantial portions * of the Software. - * + * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. @@ -22,15 +22,18 @@ * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - * + * **************************************************************************/ #include #include +#include #include #include #include +#include #include +#include #include "xvmc_private.h" static enum pipe_mpeg12_macroblock_type TypeToPipe(int xvmc_mb_type) @@ -46,6 +49,8 @@ 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; } @@ -62,15 +67,20 @@ static enum pipe_mpeg12_picture_type PictureToPipe(int xvmc_pic) 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: @@ -79,17 +89,23 @@ static enum pipe_mpeg12_motion_type MotionToPipe(int xvmc_motion_type, int xvmc_ 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) @@ -98,38 +114,40 @@ CreateOrResizeBackBuffer(struct pipe_video_context *vpipe, unsigned int width, u 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.width[0] = width; - template.height[0] = height; - template.depth[0] = 1; - pf_get_block(template.format, &template.block); - template.tex_usage = PIPE_TEXTURE_USAGE_DISPLAY_TARGET; - - tex = vpipe->screen->texture_create(vpipe->screen, &template); + template.width0 = width; + template.height0 = height; + template.depth0 = 1; + 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->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, @@ -151,7 +169,7 @@ MacroBlocksToPipe(const XvMCMacroBlockArray *xvmc_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; @@ -171,12 +189,17 @@ MacroBlocksToPipe(const XvMCMacroBlockArray *xvmc_macroblocks, } } +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); @@ -186,14 +209,42 @@ Status XvMCCreateSurface(Display *dpy, XvMCContext *context, XvMCSurface *surfac 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; @@ -211,9 +262,12 @@ Status XvMCCreateSurface(Display *dpy, XvMCContext *context, XvMCSurface *surfac 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, @@ -230,6 +284,8 @@ Status XvMCRenderSurface(Display *dpy, XvMCContext *context, unsigned int pictur 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) @@ -266,22 +322,25 @@ Status XvMCRenderSurface(Display *dpy, XvMCContext *context, unsigned int pictur 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); @@ -292,6 +351,7 @@ Status XvMCFlushSurface(Display *dpy, XvMCSurface *surface) return Success; } +PUBLIC Status XvMCSyncSurface(Display *dpy, XvMCSurface *surface) { assert(dpy); @@ -302,29 +362,34 @@ Status XvMCSyncSurface(Display *dpy, XvMCSurface *surface) 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); @@ -338,33 +403,55 @@ Status XvMCPutSurface(Display *dpy, XvMCSurface *surface, Drawable drawable, * 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); @@ -379,23 +466,29 @@ Status XvMCGetSurfaceStatus(Display *dpy, XvMCSurface *surface, int *status) 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);