Path: blob/21.2-virgl/src/gallium/frontends/xvmc/context.c
4566 views
/**************************************************************************1*2* Copyright 2009 Younes Manton.3* All Rights Reserved.4*5* Permission is hereby granted, free of charge, to any person obtaining a6* copy of this software and associated documentation files (the7* "Software"), to deal in the Software without restriction, including8* without limitation the rights to use, copy, modify, merge, publish,9* distribute, sub license, and/or sell copies of the Software, and to10* permit persons to whom the Software is furnished to do so, subject to11* the following conditions:12*13* The above copyright notice and this permission notice (including the14* next paragraph) shall be included in all copies or substantial portions15* of the Software.16*17* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS18* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF19* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.20* IN NO EVENT SHALL VMWARE AND/OR ITS SUPPLIERS BE LIABLE FOR21* ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,22* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE23* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.24*25**************************************************************************/2627#include <assert.h>2829#include <X11/Xlibint.h>30#include <X11/extensions/XvMClib.h>3132#include "pipe/p_screen.h"33#include "pipe/p_video_codec.h"34#include "pipe/p_video_state.h"35#include "pipe/p_state.h"3637#include "util/u_memory.h"3839#include "vl/vl_csc.h"40#include "vl/vl_winsys.h"4142#include "xvmc_private.h"4344static Status Validate(Display *dpy, XvPortID port, int surface_type_id,45unsigned int width, unsigned int height, int flags,46bool *found_port, int *screen, int *chroma_format,47int *mc_type, int *surface_flags,48unsigned short *subpic_max_w,49unsigned short *subpic_max_h)50{51bool found_surface = false;52XvAdaptorInfo *adaptor_info;53unsigned int num_adaptors;54int num_types;55unsigned int max_width = 0, max_height = 0;56Status ret;5758assert(dpy);59assert(found_port);60assert(screen);61assert(chroma_format);62assert(mc_type);63assert(surface_flags);64assert(subpic_max_w);65assert(subpic_max_h);6667*found_port = false;6869for (int i = 0; i < XScreenCount(dpy); ++i) {70ret = XvQueryAdaptors(dpy, XRootWindow(dpy, i), &num_adaptors, &adaptor_info);71if (ret != Success)72return ret;7374for (unsigned int j = 0; j < num_adaptors && !*found_port; ++j) {75for (unsigned int k = 0; k < adaptor_info[j].num_ports && !*found_port; ++k) {76XvMCSurfaceInfo *surface_info;7778if (adaptor_info[j].base_id + k != port)79continue;8081*found_port = true;8283surface_info = XvMCListSurfaceTypes(dpy, adaptor_info[j].base_id, &num_types);84if (!surface_info) {85XvFreeAdaptorInfo(adaptor_info);86return BadAlloc;87}8889for (int l = 0; l < num_types && !found_surface; ++l) {90if (surface_info[l].surface_type_id != surface_type_id)91continue;9293found_surface = true;94max_width = surface_info[l].max_width;95max_height = surface_info[l].max_height;96*chroma_format = surface_info[l].chroma_format;97*mc_type = surface_info[l].mc_type;98*surface_flags = surface_info[l].flags;99*subpic_max_w = surface_info[l].subpicture_max_width;100*subpic_max_h = surface_info[l].subpicture_max_height;101*screen = i;102103XVMC_MSG(XVMC_TRACE, "[XvMC] Found requested context surface format.\n" \104"[XvMC] screen=%u, port=%u\n" \105"[XvMC] id=0x%08X\n" \106"[XvMC] max width=%u, max height=%u\n" \107"[XvMC] chroma format=0x%08X\n" \108"[XvMC] acceleration level=0x%08X\n" \109"[XvMC] flags=0x%08X\n" \110"[XvMC] subpicture max width=%u, max height=%u\n",111i, port, surface_type_id, max_width, max_height, *chroma_format,112*mc_type, *surface_flags, *subpic_max_w, *subpic_max_h);113}114115free(surface_info);116}117}118119XvFreeAdaptorInfo(adaptor_info);120}121122if (!*found_port) {123XVMC_MSG(XVMC_ERR, "[XvMC] Could not find a suitable port.\n");124return XvBadPort;125}126if (!found_surface) {127XVMC_MSG(XVMC_ERR, "[XvMC] Could not find a suitable surface.\n");128return BadMatch;129}130if (width > max_width || height > max_height) {131XVMC_MSG(XVMC_ERR, "[XvMC] Requested context dimensions (w=%u,h=%u) too large (max w=%u,h=%u).\n",132width, height, max_width, max_height);133return BadValue;134}135if (flags != XVMC_DIRECT && flags != 0) {136XVMC_MSG(XVMC_ERR, "[XvMC] Invalid context flags 0x%08X.\n", flags);137return BadValue;138}139140return Success;141}142143static enum pipe_video_profile ProfileToPipe(int xvmc_profile)144{145if (xvmc_profile & XVMC_MPEG_1)146assert(0);147if (xvmc_profile & XVMC_MPEG_2)148return PIPE_VIDEO_PROFILE_MPEG2_MAIN;149if (xvmc_profile & XVMC_H263)150assert(0);151if (xvmc_profile & XVMC_MPEG_4)152assert(0);153154assert(0);155156XVMC_MSG(XVMC_ERR, "[XvMC] Unrecognized profile 0x%08X.\n", xvmc_profile);157158return -1;159}160161static enum pipe_video_chroma_format FormatToPipe(int xvmc_format)162{163switch (xvmc_format) {164case XVMC_CHROMA_FORMAT_420:165return PIPE_VIDEO_CHROMA_FORMAT_420;166case XVMC_CHROMA_FORMAT_422:167return PIPE_VIDEO_CHROMA_FORMAT_422;168case XVMC_CHROMA_FORMAT_444:169return PIPE_VIDEO_CHROMA_FORMAT_444;170default:171assert(0);172}173174XVMC_MSG(XVMC_ERR, "[XvMC] Unrecognized format 0x%08X.\n", xvmc_format);175176return -1;177}178179PUBLIC180Status XvMCCreateContext(Display *dpy, XvPortID port, int surface_type_id,181int width, int height, int flags, XvMCContext *context)182{183bool found_port;184int scrn = 0;185int chroma_format = 0;186int mc_type = 0;187int surface_flags = 0;188unsigned short subpic_max_w = 0;189unsigned short subpic_max_h = 0;190Status ret;191struct vl_screen *vscreen;192struct pipe_context *pipe;193struct pipe_video_codec templat = {0};194XvMCContextPrivate *context_priv;195vl_csc_matrix csc;196197XVMC_MSG(XVMC_TRACE, "[XvMC] Creating context %p.\n", context);198199assert(dpy);200201if (!context)202return XvMCBadContext;203204ret = Validate(dpy, port, surface_type_id, width, height, flags,205&found_port, &scrn, &chroma_format, &mc_type, &surface_flags,206&subpic_max_w, &subpic_max_h);207208/* Success and XvBadPort have the same value */209if (ret != Success || !found_port)210return ret;211212/* XXX: Current limits */213if (chroma_format != XVMC_CHROMA_FORMAT_420) {214XVMC_MSG(XVMC_ERR, "[XvMC] Cannot decode requested surface type. Unsupported chroma format.\n");215return BadImplementation;216}217if ((mc_type & ~XVMC_IDCT) != (XVMC_MOCOMP | XVMC_MPEG_2)) {218XVMC_MSG(XVMC_ERR, "[XvMC] Cannot decode requested surface type. Non-MPEG2/Mocomp/iDCT acceleration unsupported.\n");219return BadImplementation;220}221if (surface_flags & XVMC_INTRA_UNSIGNED) {222XVMC_MSG(XVMC_ERR, "[XvMC] Cannot decode requested surface type. Unsigned intra unsupported.\n");223return BadImplementation;224}225226context_priv = CALLOC(1, sizeof(XvMCContextPrivate));227if (!context_priv)228return BadAlloc;229230/* TODO: Reuse screen if process creates another context */231vscreen = vl_dri3_screen_create(dpy, scrn);232if (!vscreen)233vscreen = vl_dri2_screen_create(dpy, scrn);234235if (!vscreen) {236XVMC_MSG(XVMC_ERR, "[XvMC] Could not create VL screen.\n");237FREE(context_priv);238return BadAlloc;239}240241pipe = vscreen->pscreen->context_create(vscreen->pscreen, NULL, 0);242if (!pipe) {243XVMC_MSG(XVMC_ERR, "[XvMC] Could not create VL context.\n");244vscreen->destroy(vscreen);245FREE(context_priv);246return BadAlloc;247}248249templat.profile = ProfileToPipe(mc_type);250templat.entrypoint = (mc_type & XVMC_IDCT) ? PIPE_VIDEO_ENTRYPOINT_IDCT : PIPE_VIDEO_ENTRYPOINT_MC;251templat.chroma_format = FormatToPipe(chroma_format);252templat.width = width;253templat.height = height;254templat.max_references = 2;255templat.expect_chunked_decode = true;256257context_priv->decoder = pipe->create_video_codec(pipe, &templat);258259if (!context_priv->decoder) {260XVMC_MSG(XVMC_ERR, "[XvMC] Could not create VL decoder.\n");261pipe->destroy(pipe);262vscreen->destroy(vscreen);263FREE(context_priv);264return BadAlloc;265}266267if (!vl_compositor_init(&context_priv->compositor, pipe)) {268XVMC_MSG(XVMC_ERR, "[XvMC] Could not create VL compositor.\n");269context_priv->decoder->destroy(context_priv->decoder);270pipe->destroy(pipe);271vscreen->destroy(vscreen);272FREE(context_priv);273return BadAlloc;274}275276if (!vl_compositor_init_state(&context_priv->cstate, pipe)) {277XVMC_MSG(XVMC_ERR, "[XvMC] Could not create VL compositor state.\n");278vl_compositor_cleanup(&context_priv->compositor);279context_priv->decoder->destroy(context_priv->decoder);280pipe->destroy(pipe);281vscreen->destroy(vscreen);282FREE(context_priv);283return BadAlloc;284}285286287context_priv->color_standard =288debug_get_bool_option("G3DVL_NO_CSC", FALSE) ?289VL_CSC_COLOR_STANDARD_IDENTITY : VL_CSC_COLOR_STANDARD_BT_601;290context_priv->procamp = vl_default_procamp;291292vl_csc_get_matrix293(294context_priv->color_standard,295&context_priv->procamp, true, &csc296);297vl_compositor_set_csc_matrix(&context_priv->cstate, (const vl_csc_matrix *)&csc, 1.0f, 0.0f);298299context_priv->vscreen = vscreen;300context_priv->pipe = pipe;301context_priv->subpicture_max_width = subpic_max_w;302context_priv->subpicture_max_height = subpic_max_h;303304context->context_id = XAllocID(dpy);305context->surface_type_id = surface_type_id;306context->width = width;307context->height = height;308context->flags = flags;309context->port = port;310context->privData = context_priv;311312SyncHandle();313314XVMC_MSG(XVMC_TRACE, "[XvMC] Context %p created.\n", context);315316return Success;317}318319PUBLIC320Status XvMCDestroyContext(Display *dpy, XvMCContext *context)321{322XvMCContextPrivate *context_priv;323324XVMC_MSG(XVMC_TRACE, "[XvMC] Destroying context %p.\n", context);325326assert(dpy);327328if (!context || !context->privData)329return XvMCBadContext;330331context_priv = context->privData;332context_priv->decoder->destroy(context_priv->decoder);333vl_compositor_cleanup_state(&context_priv->cstate);334vl_compositor_cleanup(&context_priv->compositor);335context_priv->pipe->destroy(context_priv->pipe);336context_priv->vscreen->destroy(context_priv->vscreen);337FREE(context_priv);338context->privData = NULL;339340XVMC_MSG(XVMC_TRACE, "[XvMC] Context %p destroyed.\n", context);341342return Success;343}344345346